Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

The principle of PoW Mining algorithm and its implementation in Bitcoin and Ethernet Square

2025-02-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)06/02 Report--

PoW, full name Proof of Work, namely workload proof, also known as mining. Most public chains or virtual currencies, such as Bitcoin and Ethernet Square, are based on the PoW algorithm to implement their consensus mechanism. That is, according to the effective work of mining contribution, to determine the distribution of money.

Bitcoin block

A Bitcoin block consists of a block head and a list of transactions contained in the block. The block size is 80 bytes and consists of:

4 bytes: version number

32 bytes: hash value of the previous block

32 bytes: the Merkle root hash of the transaction list

4 bytes: current timestamp

4 bytes: current difficulty valu

4 bytes: random number Nonce value

This 80-byte block header is the input string of the bitcoin Pow algorithm.

The list of transactions is appended to the block, the first of which is a special transaction in which miners receive rewards and fees.

Definition of block header and block in bitcoin-0.15.1 source code:

Class CBlockHeader {public: / / version number int32_t nVersion; / / the hash value of the previous block uint256 hashPrevBlock; / / the Merkle root hash value of the transaction list uint256 hashMerkleRoot; / / current timestamp uint32_t nTime; / / current mining difficulty, the smaller the nBits, the greater the difficulty uint32_t nBits; / / random number Nonce value uint32_t nNonce; / / other codes slightly} Class CBlock: public CBlockHeader {public: / / transaction list std::vector vtx; / / other code slightly}; / / Code location src/primitives/block.h Bitcoin Pow algorithm principle

The process of Pow is to continuously adjust the Nonce value and do a double SHA256 hash operation on the block head so that the result satisfies the hash value of a given number of leading zeros.

The number of leading zeros depends on the difficulty of mining. The more the number of leading zeros, the greater the difficulty of mining.

The details are as follows:

1. Generate seigniorage transactions and form a transaction list with all other transactions to be packaged into blocks to generate a Merkle root hash.

2. The Merkle root hash value and other fields of the block header are used to form the block head, and the 80-byte length block head is used as the input of the Pow algorithm.

3. Constantly change the random number Nonce in the block head, do a double SHA256 hash operation on the changed block head, and compare it with the target value of the current difficulty. If it is less than the target difficulty, that is, Pow is completed.

The block completed by Pow is broadcast to the whole network, and other nodes will verify that it conforms to the rules. If the verification is valid, other nodes will receive the block and attach it to the existing block chain. After that, we will proceed to the next round of mining.

Implementation of Pow algorithm in bitcoin-0.15.1 source code:

UniValue generateBlocks (std::shared_ptr coinbaseScript, int nGenerate, uint64_t nMaxTries, bool keepScript) {static const int nInnerLoopCount = 0x10000; int nHeightEnd = 0; int nHeight = 0; {/ / Don't keep cs_main locked LOCK (cs_main); nHeight = chainActive.Height (); nHeightEnd = nHeight+nGenerate;} unsigned int nExtraNonce = 0; UniValue blockHashes (UniValue::VARR); while (nHeight)

< nHeightEnd) { std::unique_ptr pblocktemplate(BlockAssembler(Params()).CreateNewBlock(coinbaseScript->

ReserveScript); if (! pblocktemplate.get ()) throw JSONRPCError (RPC_INTERNAL_ERROR, "Couldn't create new block"); CBlock * pblock = & pblocktemplate- > block; {LOCK (cs_main); IncrementExtraNonce (pblock, chainActive.Tip (), nExtraNonce) } / / the random number in the constantly changing block head Nonce / / A pair of changed block heads do a double SHA256 hash operation / / compare with the target value of the current difficulty, if it is less than the target difficulty, that is, Pow complete / / uint64_t nMaxTries = 1000000; that is, retry while 1 million times (nMaxTries > 0 & pblock- > nNonce

< nInnerLoopCount && !CheckProofOfWork(pblock->

GetHash (), pblock- > nBits, Params (). GetConsensus ()) {+ + pblock- > nNonce;-- nMaxTries;} if (nMaxTries = = 0) {break;} if (pblock- > nNonce = = nInnerLoopCount) {continue;} std::shared_ptr shared_pblock = std::make_shared (* pblock) If (! ProcessNewBlock (Params (), shared_pblock, true, nullptr)) throw JSONRPCError (RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted"); + + nHeight; blockHashes.push_back (pblock- > GetHash (). GetHex ()); / / mark script as important because it was used at least for one coinbase output if the script came from the wallet if (keepScript) {coinbaseScript- > KeepScript () }} return blockHashes;} / / Code location src/rpc/mining.cpp

Also attach the bitcoin-0.15.1 source code to generate seigniorage transactions and create new blocks:

Std::unique_ptr BlockAssembler::CreateNewBlock (const CScript& scriptPubKeyIn, bool fMineWitnessTx) {int64_t nTimeStart = GetTimeMicros (); resetBlock (); pblocktemplate.reset (new CBlockTemplate ()); if (! pblocktemplate.get ()) return nullptr; pblock = & pblocktemplate- > block; / / pointer for convenience pblock- > vtx.emplace_back (); pblocktemplate- > vTxFees.push_back (- 1); / / updated at end pblocktemplate- > vTxSigOpsCost.push_back (- 1) / / updated at end LOCK2 (cs_main, mempool.cs); CBlockIndex* pindexPrev = chainActive.Tip (); nHeight = pindexPrev- > nHeight + 1; / / version number pblock- > nVersion = ComputeBlockVersion (pindexPrev, chainparams.GetConsensus ()); if (chainparams.MineBlocksOnDemand ()) pblock- > nVersion = gArgs.GetArg ("- blockversion", pblock- > nVersion); / / current timestamp pblock- > nTime = GetAdjustedTime (); const int64_t nMedianTimePast = pindexPrev- > GetMedianTimePast () NLockTimeCutoff = (STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST)? NMedianTimePast: pblock- > GetBlockTime (); fIncludeWitness = IsWitnessEnabled (pindexPrev, chainparams.GetConsensus ()) & & fMineWitnessTx; int nPackagesSelected = 0; int nDescendantsUpdated = 0; addPackageTxs (nPackagesSelected, nDescendantsUpdated); int64_t nTime1 = GetTimeMicros (); nLastBlockTx = nBlockTx; nLastBlockWeight = nBlockWeight; / / create seigniorage CMutableTransaction coinbaseTx; coinbaseTx.vin.resize (1); coinbaseTx.vin [0] .coins out.SetNull () CoinbaseTx.vout.resize (1); / / Mining awards and fees coinbaseTx.vout [0] .scriptPubKey = scriptPubKeyIn; coinbaseTx.vout [0] .nValue = nFees + GetBlockSubsidy (nHeight, chainparams.GetConsensus ()); coinbaseTx.vin [0] .scriptSig = CScript () vchCoinbaseCommitment = GenerateCoinbaseCommitment (* pblock, pindexPrev, chainparams.GetConsensus ()); pblocktemplate- > vTxFees [0] =-nFees LogPrintf ("CreateNewBlock (): block weight:% u txs:% u fees:% ld sigops% d\ n", GetBlockWeight (* pblock), nBlockTx, nFees, nBlockSigOpsCost); / / Hash value of the previous block pblock- > hashPrevBlock = pindexPrev- > GetBlockHash (); UpdateTime (pblock, chainparams.GetConsensus (), pindexPrev); / / current mining difficulty pblock- > nBits = GetNextWorkRequired (pindexPrev, pblock, chainparams.GetConsensus ()) / Random number Nonce value pblock- > nNonce = 0; pblocktemplate- > vTxSigOpsCost [0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount (* pblock- > vtx [0]); CValidationState state; if (! TestBlockValidity (state, chainparams, * pblock, pindexPrev, false, false) {throw std::runtime_error (strprintf ("% s: TestBlockValidity failed:% s", _ _ func__, FormatStateMessage (state);} int64_t nTime2 = GetTimeMicros () LogPrint (BCLog::BENCH, "CreateNewBlock () packages:% .2fms (% d packages,% d updated descendants), validity:% .2fms (total% .2fms)\ n", 0.001 * (nTime1-nTimeStart), nPackagesSelected, nDescendantsUpdated, 0.001 * (nTime2-nTime1), 0.001 * (nTime2-nTimeStart); return std::move (pblocktemplate);} / / Code location src/miner.cpp Bitcoin Mining difficulty calculation

The new difficulty is calculated for every 2016 blocks created, and the next 2016 blocks use the new difficulty. The calculation steps are as follows:

1. Find the first block of the first 2016 blocks and calculate the time it takes to generate the 2016 blocks.

That is, the time difference between the last block and the first block. The time difference is not less than 3.5 days and not more than 56 days.

2. Calculate the total difficulty of the first 2016 blocks, that is, the difficulty x total time of a single block.

3. Calculate the new difficulty, that is, the total difficulty of 2016 blocks / 14 days, and get the difficulty value per second.

4. A new difficulty is required, and the difficulty is not lower than the minimum difficulty defined by the parameters.

The code for calculating the mining difficulty in the bitcoin-0.15.1 source code is as follows:

/ / nFirstBlockTime is the timestamp of the first 2016 blocks unsigned int CalculateNextWorkRequired (const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params) {if (params.fPowNoRetargeting) return pindexLast- > nBits; / / calculate the time taken to generate the 2016 blocks int64_t nActualTimespan = pindexLast- > GetBlockTime ()-nFirstBlockTime; / / not less than 3.5d if (nActualTimespan)

< params.nPowTargetTimespan/4) nActualTimespan = params.nPowTargetTimespan/4; //不大于56天 if (nActualTimespan >

Params.nPowTargetTimespan*4) nActualTimespan = params.nPowTargetTimespan*4; / / Retarget const arith_uint256 bnPowLimit = UintToArith356 (params.powLimit); arith_uint256 bnNew; bnNew.SetCompact (pindexLast- > nBits); / / calculate the total difficulty of the first 2016 blocks / / that is, the total difficulty of a single block * bnNew * = nActualTimespan; / / calculate the new difficulty / / that is, the sum of the difficulties of 2016 blocks / 14 days bnNew / = params.nPowTargetTimespan / / the smaller the bnNew, the greater the difficulty / / the greater the bnNew, the less the difficulty / / requires a new difficulty, and the difficulty is no less than the minimum difficulty defined by the parameter if (bnNew > bnPowLimit) bnNew = bnPowLimit; return bnNew.GetCompact ();} / / Code location src/pow.cpp Yi Taifang block

Yitaifang block is composed of Header and Body.

Some members of Header are as follows:

ParentHash, parent block hash

UncleHash, the hash of the chunk, specifically the RLP hash of the Uncles array in Body. RLP hash, that is, the SHA3 hash operation is performed after the RLP encoding of a certain type of object.

Coinbase, miner's address.

The RLP hash value of the state Trie root node in Root,StateDB.

The RLP hash value of the tx Trie root node in TxHash,Block.

The RLP hash value of the Receipt Trie root node in ReceiptHash,Block.

Difficulty, block difficulty, that is, the current mining difficulty.

Number, block serial number, that is, parent block Number+1.

GasLimit, the theoretical upper limit of all Gas consumption in the block, specified at the time of creation and calculated by the parent block GasUsed and GasLimit.

GasUsed, the sum of Gas consumed by all Transaction execution in the chunk.

Time, the current timestamp.

Nonce, random number Nonce value.

About Uncle Block:

Uncle blocks, that is, isolated blocks. The block forming speed of Yitaifang is faster, which leads to the formation of isolated blocks.

Yi Tai Fong will reward miners who find isolated blocks, encouraging miners to quote isolated blocks in new blocks and to use isolated blocks to make the main chain heavier. In Ethernet Square, the main chain refers to the heaviest chain.

For state Trie, tx Trie, and Receipt Trie:

State Trie, all account objects can be inserted into a Merkle-PatricaTrie (MPT) structure one by one to form a state Trie.

All the tx objects in Transactions in tx Trie:Block are inserted into the MPT structure one by one to form tx Trie.

After all the Transaction in Receipt Trie:Block is executed, the Receipt array is generated, and all the Receipt is inserted into the MPT structure one by one to form a Receipt Trie.

The members of Body are as follows:

Transactions, transaction list.

Uncles, list of referenced Uncle blocks.

Definition of block header and block in go-ethereum-1.7.3 source code:

Type Header struct {/ / parent block hash ParentHash common.Hash / / Uncle block hash UncleHash common.Hash / / miner address Coinbase common.Address / / StateDB state Trie root node RLP hash value Root common.Hash / / Block tx Trie root node RLP hash value TxHash common.Hash / / Block RLP hash value ReceiptHash common.Hash of Receipt Trie root node Bloom Bloom / / Block difficulty Difficulty * big.Int / / Block sequence number Number * big.Int / / theoretical upper limit of all Gas consumption in the block GasLimit * big.Int / / Total Gas consumed by all Transaction execution in the block GasUsed * big.Int / / current timestamp Time * big.Int Extra [] Byte MixDigest common.Hash / / Random number Nonce value Nonce BlockNonce} type Body struct {/ / transaction list Transactions [] * Transaction / / referenced Uncle Block list Uncles [] * Header} / / Code location core/types/block.go Ethernet Square Pow algorithm principle

The ethernet square Pow algorithm can be expressed as the following formula:

RAND (h, n)

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Servers

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report