In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-13 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/01 Report--
In this article, the editor introduces in detail the "Ethernet Square DPOS consensus mechanism source code analysis", the content is detailed, the steps are clear, and the details are handled properly. I hope this "Yi Tai Fang DPOS consensus mechanism source code analysis" article can help you solve your doubts.
1. Preface:
Any consensus mechanism must answer, including, but not limited to, the following questions:
Who should generate the next new chunk added to the database?
When should the next block be generated?
What transactions should be included in this block?
How to amend this Agreement?
How to solve the competition problem of transaction history?
Second, function description:
Each holder of bit shares votes for the candidate trustee according to their shareholding ratio; select the top 21 representatives with the largest number of votes (or other numbers, specifically determined by the blockchain project party) to become 21 super nodes with exactly equal power (real: trustee / witness); produce blocks by polling every 3 seconds; while other candidate trustees have no right to produce blocks
1. Shareholders: the bitstock holds the owner; each account votes for the witness according to the number of currencies held; the vote can be changed at any time; it may not be voted; but only yes can be cast.
2. Witnesses (trustee / representative, Bitcoin-like miners):
To register as a candidate trustee, you need to pay a deposit, which is to prevent the node from doing evil. Generally speaking, if you become a trustee, you will become a super node for mining. The super node takes about two weeks to break even, which urges the super node not to do evil for at least two weeks.
3. Selected representative (it is not considered in the implementation step)
Delegates are also elected in a manner similar to that of election witnesses. The founding account (the genesis account) has the right to modify the network parameters, and the representative is the co-signer of the special account. These parameters include transaction costs, block size, witness salary and block interval, etc. After most representatives approve the proposed change, shareholders have a 2-week review period (review period), during which they can vote to kick out the representative and invalidate the proposed change.
4. Block rule: poll the trustee every 3 seconds; and each witness will take turns to produce a block within a fixed, pre-planned period of 2 seconds. When all witnesses finish their turn, they will be shuffled. If a witness does not produce a block within his own time period, that period will be skipped and the next witness will continue to generate the next block. Whenever witnesses produce a block, they get a corresponding service charge. The remuneration level of the witness is determined by the representative elected by the shareholders (delegate). If a witness does not produce a block, he will not be paid and may be voted out in the future.
5. The algorithm mainly consists of two core parts: block verifier election and block verifier scheduling.
(1) the first batch of block verifiers is designated by the Genesis Block, and each subsequent cycle (defined by the specific implementation) will be re-elected in the first block at the beginning of the cycle. The election process of the verifier is as follows:
Kick out the verifier with insufficient block in the last cycle.
Count the number of votes of the candidates at the end of the election block (the first block of each cycle), and select the top N with the highest number of votes as examiners.
Randomly disturb the block order of the verifier, and the examiner gives the block according to the random result order.
(2) the verifier dispatches the block according to the election result, and the other nodes verify whether the block order and the election result are consistent according to the election result. If the block is inconsistent, the block is considered illegal and discarded directly.
Third, the source code analysis of DPOS consensus mechanism in Ethernet Square.
1. Launch the portal:
Debugging script at the entrance of Tai Tai Fong:
The startup of the ethersquare project: init () function in main.go-- > call geth method-- > call function StartMining-- in startNode-- > backend.go > start function in miner.go
Func init () {/ / Initialize the CLI app and start Geth app.Action = geth} func geth (ctx * cli.Context) error {/ / get all nodes based on the context configuration information and register the node in the ethersquare service / / makeFullNode function-- > flags.go function RegisterEthService-- > eth.New-- > NewProtocolManager-- > InsertChain in dpos block information check node: = makeFullNode (ctx) / / startup node startNode (ctx) Node) node.Wait () return nil}
Boot node description
Func startNode (ctx * cli.Context, stack * node.Node) {/ / start the current node: utils.StartNode (stack) / / unlock the registered wallet event and automatically derive the wallet event / / listen wallet event if ctx.GlobalBool (utils.MiningEnabledFlag.Name) {/ / determine whether the full node is full, only the full node has mining rights: var ethereum * eth.Ethereum if err: = stack.Service (& ethereum) Err! = nil {utils.Fatalf ("ethereum service not running:% v", err)} / / set gas price ethereum.TxPool () .SetGasPrice (utils.GlobalBig (ctx, utils.GasPriceFlag.Name)) / / verify whether the current chunk trustee: validator, err: = s.Validator (), start the service packaging block if err: = ethereum.StartMining (true) Err! = nil {utils.Fatalf ("Failed to start mining:% v", err)}
The above StartMining method will call the start function in miner.go. Before calling the startup function, all nodes have been started and the relevant initialization work has been carried out (details are as follows)
Func (self * Miner) Start (coinbase common.Address) {atomic.StoreInt32 (& self.shouldStart, 1) self.worker.setCoinbase (coinbase) self.coinbase = coinbase if atomic.LoadInt32 (& self.canStart) = 0 {log.Info ("Network syncing, will start miner afterwards") return} atomic.StoreInt32 (& self.mining, 1) log.Info ("Starting mining operation") / / get the current node address, start the service self.worker.start ()}
The start function of worker.go calls the mintLoop function
Func (self * worker) mintLoop () {ticker: = time.NewTicker (time.Second). The C / / for loop is constantly listening to the self signal. When the self is stopped, the closing operation code is called, and the loop listener is picked out directly, and the function exits. For {select {case now: = commitTransaction function-- > call ApplyTransaction function in state_processor.go-- > applyDposMessage
Func ApplyTransaction (config * params.ChainConfig, dposContext * types.DposContext, bc * BlockChain, author * common.Address, gp * GasPool, statedb * state.StateDB, header * types.Header, tx * types.Transaction, usedGas * big.Int, cfg vm.Config) (* types.Receipt, * big.Int, error) {msg, err: = tx.AsMessage (types.MakeSigner (config, header.Number)) if err! = nil {return nil, nil Err} if msg.To () = = nil & & msg.Type ()! = types.Binary {return nil, nil, types.ErrInvalidType} / / context for creating EVM environment context: = NewEVMContext (msg, header, bc, author) / / Create a new environment which holds all relevant information / / create EVM virtual machine to process transactions and smart contracts vmenv: = vm.NewEVM (context, statedb, config) Cfg) / / Apply the transaction to the current state (included in the env) _, gas, failed, err: = ApplyMessage (vmenv, msg, gp) if err! = nil {return nil, nil, err} if msg.Type ()! = types.Binary {/ / if it is a non-transfer or contract call type transaction if err = applyDposMessage (dposContext, msg) Err! = nil {return nil, nil, err}} func applyDposMessage (dposContext * types.DposContext Msg types.Message) error {switch msg.Type () {case types.LoginCandidate:// becomes a candidate dposContext.BecomeCandidate (msg.From ()) case types.LogoutCandidate:// cancels candidate dposContext.KickoutCandidate (msg.From ()) case types.Delegate:// before voting / / you need to check whether the account is a candidate. If the voter has voted for someone else before, cancel the previous vote first, then cancel the vote by dposContext.Delegate (msg.From (), * (msg.To ()) case types.UnDelegate://) dposContext.UnDelegate (msg.From (), * (msg.To ()) default: return types.ErrInvalidType} return nil}
4. Packing out block process
Worker.go
Func (self * worker) mintBlock (now int64) {engine, ok: = self.engine. (* dpos.Dpos) if! ok {log.Error ("Only the dpos engine was allowed") return} / / the mining union checks whether the current validator is the current node (every 3 seconds). If so, it means that you have been polled. Err: = engine.CheckValidator (self.chain.CurrentBlock (), now) if err! = nil {case dpos.ErrWaitForPrevBlock, dpos.ErrMintFutureBlock, dpos.ErrInvalidBlockValidator, dpos.ErrInvalidMintBlockTime: log.Debug ("Failed to mint the block, while", "err", err) default: log.Error ("Failed to mint the block", "err") Err)} return} / / create a new blocking task work, err: = self.createNewWork () if err! = nil {log.Error ("Failed to create the new work", "err", err) return} / / Seal will sign the new block result, err: = self.engine.Seal (self.chain, work.Block, self.quitCh) if err! = nil {log.Error ("Failed to seal the block") "err", err) return} / / broadcast new blocks to neighboring nodes Other nodes will receive the new block according to the signature of the block and the election result to see whether the new block should be issued by the verifier self.recv maxValidatorSize {/ / if the candidate is greater than the predetermined number of trustees constant maxValidatorSize, the former maxValidatorSize is selected as the trustee candidates = candidates [: maxValidatorSize]} / / rearranging trustees, because the use of seed consists of the hash of the parent block and the current cycle number So the list of trustees calculated by each node will be the same. Seed: = int64 (binary.LittleEndian.Uint32 (crypto.Keccak512 (parent.Hash (). Bytes () + I r: = rand.New (rand.NewSource (seed)) for I: = len (candidates)-1; I > 0 Candidates-{j: = int (r.Int31n (int32 (I + 1)) candidates [I], candidates [j] = candidates [j], candidates [I]} sortedValidators: = make ([] common.Address, 0) for _, candidate: = range candidates {sortedValidators = append (sortedValidators, candidate.address)} / / Save trustee list epochTrie, _: = types.NewEpochTrie (common.Hash {}) Ec.DposContext.DB () ec.DposContext.SetEpoch (epochTrie) ec.DposContext.SetValidators (sortedValidators) log.Info ("Come to new epoch", "prevEpoch", I, "nextEpoch", iTun1)} return nil}
(2) realization of vote counting
First find out the list of candidates corresponding to voters.
The balance of all voters is accumulated as votes into the total number of votes of the candidate.
The vote counting function is the countVotes function in the tryElect election function in epoch_context.go.
Func (ec * EpochContext) countVotes () (votes map [common.Address] * big.Int Err error) {votes = map [common.Address] * big.Int {} delegateTrie: = ec.DposContext.DelegateTrie () / / record the list of verifiers and corresponding voters candidateTrie: = ec.DposContext.CandidateTrie () / / get the list of candidates statedb: = ec.statedb iterCandidate: = trie.NewIterator (candidateTrie.NodeIterator (nil)) existCandidate: = iterCandidate.Next () if! existCandidate {return votes Errors.New ("no candidates")} / / traverse the candidate list for existCandidate {candidate: = iterCandidate.Value candidateAddr: = common.BytesToAddress (candidate) delegateIterator: = trie.NewIterator (delegateTrie.PrefixIterator (candidate)) existDelegator: = delegateIterator.Next () if! existDelegator {votes [candidateAddr] = new (big.Int) existCandidate = iterCandidate.Next () continue} / / traverse the voter list corresponding to the followers for existDelegator {delegator: = delegateIterator.Value score Ok: = votes [candidateAddr] if! ok {score = new (big.Int)} delegatorAddr: = common.BytesToAddress (delegator) / / get the voter's balance as votes accumulated into the candidate's votes weight: = statedb.GetBalance (delegatorAddr) score.Add (score Weight) votes [candidateAddr] = score existDelegator = delegateIterator.Next ()} existCandidate = iterCandidate.Next ()} return votes, nil} here This article "the source code analysis of DPOS consensus mechanism in Yi Tai Fang" has been introduced. If you want to master the knowledge points of this article, you still need to practice and use it yourself. If you want to know more about the article, you are welcome to follow the industry information channel.
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: 267
*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.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.