![兄弟連區(qū)Go語言+區(qū)塊鏈技術(shù)培訓(xùn)以太坊源碼分析(11)eth目前的共識算法pow的整理_第1頁](http://file4.renrendoc.com/view/f8478691839d95a3e30c07f5efb76c5b/f8478691839d95a3e30c07f5efb76c5b1.gif)
![兄弟連區(qū)Go語言+區(qū)塊鏈技術(shù)培訓(xùn)以太坊源碼分析(11)eth目前的共識算法pow的整理_第2頁](http://file4.renrendoc.com/view/f8478691839d95a3e30c07f5efb76c5b/f8478691839d95a3e30c07f5efb76c5b2.gif)
![兄弟連區(qū)Go語言+區(qū)塊鏈技術(shù)培訓(xùn)以太坊源碼分析(11)eth目前的共識算法pow的整理_第3頁](http://file4.renrendoc.com/view/f8478691839d95a3e30c07f5efb76c5b/f8478691839d95a3e30c07f5efb76c5b3.gif)
下載本文檔
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、 80/80兄弟連區(qū)塊鏈技術(shù)培訓(xùn)以太坊源碼分析(11)eth目前的共識算法pow的整理# eth目前的共識算法pow的整理# 涉及的代碼子包主要有consensus,miner,core,geth/consensus 共識算法 consensus.go1. Prepare方法2. CalcDifficulty方法:計算工作量3. AccumulateRewards方法:計算每個塊的出塊獎勵4. VerifySeal方法:校驗pow的工作量難度是否符合要求,返回nil則通過5. verifyHeader方法:校驗區(qū)塊頭是否符合共識規(guī)則/miner 挖礦work.gocommitNewWork()
2、:提交新的塊,新的交易,從交易池中獲取未打包的交易,然后提交交易,進(jìn)行打包_核心代碼_:/ Create the current work task and check any fork transitions neededwork := self.currentif self.config.DAOForkSupport & self.config.DAOForkBlock != nil & self.config.DAOForkBlock.Cmp(header.Number) = 0 misc.ApplyDAOHardFork(work.state)pending, err := self.
3、eth.TxPool().Pending()if err != nil log.Error(Failed to fetch pending transactions, err, err)returntxs := types.NewTransactionsByPriceAndNonce(self.current.signer, pending)mitTransactions(self.mux, txs, self.chain, self.coinbase)eth/handler.goNewProtocolManager - verifyHeader - VerifySeal_整條鏈的運(yùn)行,打包交
4、易,出塊的流程_/cmd/geth/main.go/mainmakeFullNode-RegisterEthService-eth.New-NewProtocolManager - verifyHeader - VerifySeal# eth的共識算法pow調(diào)用棧詳解# 核心的邏輯需要從/eth/handler.go/NewProtocolManager方法下開始,關(guān)鍵代碼:manager.downloader = downloader.New(mode, chaindb, manager.eventMux, blockchain, nil, manager.removePeer)valida
5、tor := func(header *types.Header) error return engine.VerifyHeader(blockchain, header, true)heighter := func() uint64 return blockchain.CurrentBlock().NumberU64()inserter := func(blocks types.Blocks) (int, error) / If fast sync is running, deny importing weird blocksif atomic.LoadUint32(&manager.fas
6、tSync) = 1 log.Warn(Discarded bad propagated block, number, blocks0.Number(), hash, blocks0.Hash()return 0, nilatomic.StoreUint32(&manager.acceptTxs, 1) / Mark initial sync done on any fetcher importreturn manager.blockchain.InsertChain(blocks)manager.fetcher = fetcher.New(blockchain.GetBlockByHash,
7、 validator, manager.BroadcastBlock, heighter, inserter, manager.removePeer)return manager, nil# 該方法中生成了一個校驗區(qū)塊頭部的對象validator# 讓我們繼續(xù)跟進(jìn)engine.VerifyHeader(blockchain, header, true)方法:/ VerifyHeader checks whether a header conforms to the consensus rules of the/ stock Ethereum ethash engine.func (ethash
8、 *Ethash) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error / If were running a full engine faking, accept any input as validif ethash.fakeFull return nil/ Short circuit if the header is known, or its parent notnumber := header.Number.Uint64()if chain.GetHeader(header.
9、Hash(), number) != nil return nilparent := chain.GetHeader(header.ParentHash, number-1)if parent = nil return consensus.ErrUnknownAncestor/ Sanity checks passed, do a proper verificationreturn ethash.verifyHeader(chain, header, parent, false, seal)# 首先看第一個if,它的邏輯判斷是如果為true,那么就關(guān)閉所有的共識規(guī)則校驗,緊跟著兩個if判斷是只
10、要該block的header的hash和number或者上一個header的hash和number存在鏈上,那么它header的共識規(guī)則校驗就通過,如果都不通過,那么該區(qū)塊校驗失敗跑出錯誤.如果走到最后一個return,那么就需要做一些其他額外驗證/ verifyHeader checks whether a header conforms to the consensus rules of the/ stock Ethereum ethash engine./ See YP section 4.3.4. Block Header Validityfunc (ethash *Ethash) v
11、erifyHeader(chain consensus.ChainReader, header, parent *types.Header, uncle bool, seal bool) error / Ensure that the headers extra-data section is of a reasonable sizeif uint64(len(header.Extra) params.MaximumExtraDataSize return fmt.Errorf(extra-data too long: %d %d, len(header.Extra), params.Maxi
12、mumExtraDataSize)/ Verify the headers timestampif uncle if header.Time.Cmp(math.MaxBig256) 0 return errLargeBlockTime else if header.Time.Cmp(big.NewInt(time.Now().Unix() 0 return consensus.ErrFutureBlockif header.Time.Cmp(parent.Time) = 0 return errZeroBlockTime/ Verify the blocks difficulty based
13、in its timestamp and parents difficultyexpected := CalcDifficulty(chain.Config(), header.Time.Uint64(), parent)if expected.Cmp(header.Difficulty) != 0 return fmt.Errorf(invalid difficulty: have %v, want %v, header.Difficulty, expected)/ Verify that the gas limit is 0 return fmt.Errorf(invalid gasLim
14、it: have %v, max %v, header.GasLimit, math.MaxBig63)/ Verify that the gasUsed is 0 return fmt.Errorf(invalid gasUsed: have %v, gasLimit %v, header.GasUsed, header.GasLimit)/ Verify that the gas limit remains within allowed boundsdiff := new(big.Int).Set(parent.GasLimit)diff = diff.Sub(diff, header.G
15、asLimit)diff.Abs(diff)limit := new(big.Int).Set(parent.GasLimit)limit = limit.Div(limit, params.GasLimitBoundDivisor)if diff.Cmp(limit) = 0 | header.GasLimit.Cmp(params.MinGasLimit) 0 return fmt.Errorf(invalid gas limit: have %v, want %v += %v, header.GasLimit, parent.GasLimit, limit)/ Verify that t
16、he block number is parents +1if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(big.NewInt(1) != 0 return consensus.ErrInvalidNumber/ Verify the engine specific seal securing the blockif seal if err := ethash.VerifySeal(chain, header); err != nil return err/ If all checks passed, va
17、lidate any special fields for hard forksif err := misc.VerifyDAOHeaderExtraData(chain.Config(), header); err != nil return errif err := misc.VerifyForkHashes(chain.Config(), header, uncle); err != nil return errreturn nil# 該方法會去校驗該區(qū)塊頭中的extra數(shù)據(jù)是不是比約定的參數(shù)最大值還大,如果超過,則返回錯誤,其次會去判斷該區(qū)塊是不是一個uncle區(qū)塊,如果header的
18、時間戳不符合規(guī)則則返回錯誤,然后根據(jù)鏈的配置,header的時間戳以及上一個區(qū)塊計算中本次區(qū)塊期待的難度,如果header的難度和期待的不一致,或header的gasLimit比最大數(shù)字還大,或已用的gas超過gasLimit,則返回錯誤.如果gasLimit超過預(yù)定的最大值或最小值,或header的number減去上一個block的header的number不為1,則返回錯誤.seal為true,則會去校驗該區(qū)塊是否符合pow的工作量證明的要求(verifySeal方法),因為私有鏈一般是不需要pow.最后兩個if是去判斷區(qū)塊是否具有正確的hash,防止用戶在不同的鏈上,以及校驗塊頭的額外數(shù)
19、據(jù)字段是否符合DAO硬叉規(guī)則# uncle block:_eth允許曠工在挖到一個塊的同時包含一組uncle block列表,主要有兩個作用:_1. 由于網(wǎng)絡(luò)傳播的延遲原因,通過獎勵那些由于不是鏈組成區(qū)塊部分而產(chǎn)生陳舊或孤立區(qū)塊的曠工,從而減少集權(quán)激勵2. 通過增加在主鏈上的工作量來增加鏈條的安全性(在工作中,少浪費工作在陳舊的塊上)eth的pow核心代碼:/ CalcDifficulty is the difficulty adjustment algorithm. It returns/ the difficulty that a new block should have when cr
20、eated at time/ given the parent blocks time and difficulty./ TODO (karalabe): Move the chain maker into this package and make this private!func CalcDifficulty(config *params.ChainConfig, time uint64, parent *types.Header) *big.Int next := new(big.Int).Add(parent.Number, big1)switch case config.IsByz
21、antium(next):return calcDifficultyByzantium(time, parent)case config.IsHomestead(next):return calcDifficultyHomestead(time, parent)default:return calcDifficultyFrontier(time, parent)# 該方法的第一個case是根據(jù)拜占庭規(guī)則去計算新塊應(yīng)該具有的難度,第二個case是根據(jù)宅基地規(guī)則去計算新塊應(yīng)該具有的難度,第三個case是根據(jù)邊界規(guī)則去計算難度# pow計算生成新塊代碼解析_/consensus/seal.go/se
22、al_/ Seal implements consensus.Engine, attempting to find a nonce that satisfies/ the blocks difficulty requirements.func (ethash *Ethash) Seal(chain consensus.ChainReader, block *types.Block, stop -chan struct) (*types.Block, error) / If were running a fake PoW, simply return a 0 nonce immediatelyi
23、f ethash.fakeMode header := block.Header()header.Nonce, header.MixDigest = types.BlockNonce, common.Hashreturn block.WithSeal(header), nil/ If were running a shared PoW, delegate sealing to itif ethash.shared != nil return ethash.shared.Seal(chain, block, stop)/ Create a runner and the multiple sear
24、ch threads it directsabort := make(chan struct)found := make(chan *types.Block)ethash.lock.Lock()threads := ethash.threadsif ethash.rand = nil seed, err := crand.Int(crand.Reader, big.NewInt(math.MaxInt64)if err != nil ethash.lock.Unlock()return nil, errethash.rand = rand.New(rand.NewSource(seed.Int
25、64()ethash.lock.Unlock()if threads = 0 threads = runtime.NumCPU()if threads 0 threads = 0 / Allows disabling local mining without extra logic around local/remotevar pend sync.WaitGroupfor i := 0; i threads; i+ pend.Add(1)go func(id int, nonce uint64) defer pend.Done()ethash.mine(block, id, nonce, ab
26、ort, found)(i, uint64(ethash.rand.Int63()/ Wait until sealing is terminated or a nonce is foundvar result *types.Blockselect case -stop:/ Outside abort, stop all miner threadsclose(abort)case result = -found:/ One of the threads found a block, abort all othersclose(abort)case -ethash.update:/ Thread
27、 count was changed on user request, restartclose(abort)pend.Wait()return ethash.Seal(chain, block, stop)/ Wait for all miners to terminate and return the blockpend.Wait()return result, nil# 該方法的foreach中并行挖新塊,一旦停止或者找到新快,則廢棄其他所有的,如果協(xié)程計算有變更,則重新調(diào)用方法# 好了pow挖礦的核心方法已經(jīng)出現(xiàn),ethash.mine,如果挖取到新塊,那么就寫入到found chan
28、nel/ mine is the actual proof-of-work miner that searches for a nonce starting from/ seed that results in correct final block difficulty.func (ethash *Ethash) mine(block *types.Block, id int, seed uint64, abort chan struct, found chan *types.Block) / Extract some data from the headervar (header = bl
29、ock.Header()hash = header.HashNoNonce().Bytes()target = new(big.Int).Div(maxUint256, header.Difficulty)number = header.Number.Uint64()dataset = ethash.dataset(number)/ Start generating random nonces until we abort or find a good onevar (attempts = int64(0)nonce = seed)logger := log.New(miner, id)log
30、ger.Trace(Started ethash search for new nonces, seed, seed)for select case -abort:/ Mining terminated, update stats and abortlogger.Trace(Ethash nonce search aborted, attempts, nonce-seed)ethash.hashrate.Mark(attempts)returndefault:/ We dont have to update hash rate on every nonce, so update after a
31、fter 2X noncesattempts+if (attempts % (1 15) = 0 ethash.hashrate.Mark(attempts)attempts = 0/ Compute the PoW value of this noncedigest, result := hashimotoFull(dataset, hash, nonce)if new(big.Int).SetBytes(result).Cmp(target) = 0 / Correct nonce found, create a new header with itheader = types.CopyH
32、eader(header)header.Nonce = types.EncodeNonce(nonce)header.MixDigest = common.BytesToHash(digest)/ Seal and return a block (if still needed)select case found - block.WithSeal(header):logger.Trace(Ethash nonce found and reported, attempts, nonce-seed, nonce, nonce)case -abort:logger.Trace(Ethash nonc
33、e found but discarded, attempts, nonce-seed, nonce, nonce)returnnonce+# target是目標(biāo)新塊的難度,hashimotoFull方法計算出一個hash值,如果產(chǎn)生的hash值小于等于target的值,則hash難度符合要求,將符合要求的header寫入到found channel中,并返回,否則一直循環(huán)/ hashimotoFull aggregates data from the full dataset (using the full in-memory/ dataset) in order to produce ou
34、r final value for a particular header hash and/ nonce.func hashimotoFull(dataset uint32, hash byte, nonce uint64) (byte, byte) lookup := func(index uint32) uint32 offset := index * hashWordsreturn datasetoffset : offset+hashWordsreturn hashimoto(hash, nonce, uint64(len(dataset)*4, lookup)/ hashimoto
35、 aggregates data from the full dataset in order to produce our final/ value for a particular header hash and nonce.func hashimoto(hash byte, nonce uint64, size uint64, lookup func(index uint32) uint32) (byte, byte) / Calculate the number of theoretical rows (we use one buffer nonetheless)rows := uin
36、t32(size / mixBytes)/ Combine header+nonce into a 64 byte seedseed := make(byte, 40)copy(seed, hash)binary.LittleEndian.PutUint64(seed32:, nonce)seed = crypto.Keccak512(seed)seedHead := binary.LittleEndian.Uint32(seed)/ Start the mix with replicated seedmix := make(uint32, mixBytes/4)for i := 0; i l
37、en(mix); i+ mixi = binary.LittleEndian.Uint32(seedi%16*4:)/ Mix in random dataset nodestemp := make(uint32, len(mix)for i := 0; i loopAccesses; i+ parent := fnv(uint32(i)seedHead, mixi%len(mix) % rowsfor j := uint32(0); j mixBytes/hashBytes; j+ copy(tempj*hashWords:, lookup(2*parent+j)fnvHash(mix, t
38、emp)/ Compress mixfor i := 0; i len(mix); i += 4 mixi/4 = fnv(fnv(fnv(mixi, mixi+1), mixi+2), mixi+3)mix = mix:len(mix)/4digest := make(byte, common.HashLength)for i, val := range mix binary.LittleEndian.PutUint32(digesti*4:, val)return digest, crypto.Keccak256(append(seed, digest.)# 可以看到,該方法是不斷的進(jìn)行s
39、ha256的hash運(yùn)算,然后返回進(jìn)行hash值難度的對比,如果hash的十六進(jìn)制大小小于等于預(yù)定的難度,那么這個hash就是符合產(chǎn)塊要求的產(chǎn)生一個隨機(jī)seed,賦給nonce隨機(jī)數(shù),然后進(jìn)行sha256的hash運(yùn)算,如果算出的hash難度不符合目標(biāo)難度,則nonce+1,繼續(xù)運(yùn)算worker.go/wait()func (self *worker) wait() for mustCommitNewWork := truefor result := range self.recv atomic.AddInt32(&self.atWork, -1)if result = nil continu
40、eagent.go/mine()方法func (self *CpuAgent) mine(work *Work, stop -chan struct) if result, err := self.engine.Seal(self.chain, work.Block, stop); result != nil log.Info(Successfully sealed new block, number, result.Number(), hash, result.Hash()self.returnCh - &Resultwork, result else if err != nil log.W
41、arn(Block sealing failed, err, err)self.returnCh makeFullNode - utils.RegisterEthService- eth.New(ctx, cfg)- miner.New(eth, eth.chainConfig, eth.EventMux(), eth.engine)這個是啟動鏈后到挖礦,共識代碼的整個調(diào)用棧,開始分析核心方法func New(eth Backend, config *params.ChainConfig, mux *event.TypeMux, engine consensus.Engine) *Miner
42、miner := &Minereth: eth,mux: mux,engine: engine,worker: newWorker(config, engine, common.Address, eth, mux),canStart: 1,miner.Register(NewCpuAgent(eth.BlockChain(), engine)go miner.update()return miner從miner.Update()的邏輯可以看出,對于任何一個Ethereum網(wǎng)絡(luò)中的節(jié)點來說,挖掘一個新區(qū)塊和從其他節(jié)點下載、同步一個新區(qū)塊,根本是相互沖突的。這樣的規(guī)定,保證了在某個節(jié)點上,一個新區(qū)
43、塊只可能有一種來源,這可以大大降低可能出現(xiàn)的區(qū)塊沖突,并避免全網(wǎng)中計算資源的浪費。首先是:func (self *Miner) Register(agent Agent) if self.Mining() agent.Start()self.worker.register(agent)func (self *worker) register(agent Agent) self.mu.Lock()defer self.mu.Unlock()self.agentsagent = structagent.SetReturnCh(self.recv)該方法中將self的recv管道綁定在了agent的
44、return管道然后是newWorker方法func newWorker(config *params.ChainConfig, engine consensus.Engine, coinbase common.Address, eth Backend, mux *event.TypeMux) *worker worker := &workerconfig: config,engine: engine,eth: eth,mux: mux,txCh: make(chan core.TxPreEvent, txChanSize),chainHeadCh: make(chan core.ChainH
45、eadEvent, chainHeadChanSize),chainSideCh: make(chan core.ChainSideEvent, chainSideChanSize),chainDb: eth.ChainDb(),recv: make(chan *Result, resultQueueSize),chain: eth.BlockChain(),proc: eth.BlockChain().Validator(),possibleUncles: make(mapcommon.Hash*types.Block),coinbase: coinbase,agents: make(map
46、Agentstruct),unconfirmed: newUnconfirmedBlocks(eth.BlockChain(), miningLogAtDepth),/ Subscribe TxPreEvent for tx poolworker.txSub = eth.TxPool().SubscribeTxPreEvent(worker.txCh)/ Subscribe events for blockchainworker.chainHeadSub = eth.BlockChain().SubscribeChainHeadEvent(worker.chainHeadCh)worker.c
47、hainSideSub = eth.BlockChain().SubscribeChainSideEvent(worker.chainSideCh)go worker.update()go worker.wait()mitNewWork()return worker該方法中綁定了三個管道,額外啟動了兩個goroutine執(zhí)行update和wait方法,func (self *worker) update() defer self.txSub.Unsubscribe()defer self.chainHeadSub.Unsubscribe()defer self.chainSideSub.Uns
48、ubscribe()for / A real event arrived, process interesting contentselect / Handle ChainHeadEventcase -self.chainHeadCh:mitNewWork()/ Handle ChainSideEventcase ev := -self.chainSideCh:self.uncleMu.Lock()self.possibleUnclesev.Block.Hash() = ev.Blockself.uncleMu.Unlock()/ Handle TxPreEventcase ev := -se
49、lf.txCh:/ Apply transaction to the pending state if were not miningif atomic.LoadInt32(&self.mining) = 0 self.currentMu.Lock()acc, _ := types.Sender(self.current.signer, ev.Tx)txs := mapcommon.Addresstypes.Transactionsacc: ev.Txtxset := types.NewTransactionsByPriceAndNonce(self.current.signer, txs)m
50、itTransactions(self.mux, txset, self.chain, self.coinbase)self.currentMu.Unlock() else / If were mining, but nothing is being processed, wake on new transactionsif self.config.Clique != nil & self.config.Clique.Period = 0 mitNewWork()/ System stoppedcase -self.txSub.Err():returncase -self.chainHeadS
51、ub.Err():returncase -self.chainSideSub.Err():returnworker.update方法中接收各種事件,并且是永久循環(huán),如果有錯誤事件發(fā)生,則終止,如果有新的交易事件,則執(zhí)行commitTransactions驗證提交交易到本地的trx判定池中,供下次出塊使用worker.wait的方法接收self.recv管道的結(jié)果,也就是本地新挖出的塊,如果有挖出,則寫入塊數(shù)據(jù),并廣播一個chainHeadEvent事件,同時將該塊添加到待確認(rèn)列表中,并且提交一個新的工作量,commitNewWork方法相當(dāng)于共識的第一個階段,它會組裝一個標(biāo)準(zhǔn)的塊,其他包含產(chǎn)出
52、該塊需要的難度,然后將產(chǎn)出該塊的工作以及塊信息廣播給所有代理,接著agent.go中的update方法監(jiān)聽到廣播新塊工作量的任務(wù),開始挖礦,搶該塊的出塊權(quán)func (self *CpuAgent) mine(work *Work, stop -chan struct) if result, err := self.engine.Seal(self.chain, work.Block, stop); result != nil log.Info(Successfully sealed new block, number, result.Number(), hash, result.Hash()s
53、elf.returnCh - &Resultwork, result else if err != nil log.Warn(Block sealing failed, err, err)self.returnCh - nil該方法中開始進(jìn)行塊的hash難度計算,如果返回的result結(jié)果不為空,說明挖礦成功,將結(jié)果寫入到returnCh通道中然后worker.go中的wait方法又接收到了信息開始處理.如果不是組裝好帶有隨機(jī)數(shù)hash的,那么存儲塊將會返回錯誤,stat, err := self.chain.WriteBlockAndState(block, work.receipts, w
54、ork.state)if err != nil log.Error(Failed writing block to chain, err, err)continueremote_agent 提供了一套RPC接口,可以實現(xiàn)遠(yuǎn)程礦工進(jìn)行采礦的功能。 比如我有一個礦機(jī),礦機(jī)內(nèi)部沒有運(yùn)行以太坊節(jié)點,礦機(jī)首先從remote_agent獲取當(dāng)前的任務(wù),然后進(jìn)行挖礦計算,當(dāng)挖礦完成后,提交計算結(jié)果,完成挖礦。# eth共識算法分析,從本地節(jié)點挖到塊開始分析# 首先目前生產(chǎn)環(huán)境上面,肯定不是以CPU的形式挖礦的,那么就是remoteAgent這種形式,也就是礦機(jī)通過網(wǎng)絡(luò)請求從以太的節(jié)點獲取當(dāng)前節(jié)點的出塊任務(wù),
55、然后礦機(jī)根據(jù)算出符合該塊難度hash值,提交給節(jié)點,也就是對應(yīng)的以下方法.func (a *RemoteAgent) SubmitWork(nonce types.BlockNonce, mixDigest, hash common.Hash) bool a.mu.Lock()defer a.mu.Unlock()/ Make sure the work submitted is presentwork := a.workhashif work = nil log.Info(Work submitted but none pending, hash, hash)return false/ Ma
56、ke sure the Engine solutions is indeed validresult := work.Block.Header()result.Nonce = nonceresult.MixDigest = mixDigestif err := a.engine.VerifySeal(a.chain, result); err != nil log.Warn(Invalid proof-of-work submitted, hash, hash, err, err)return falseblock := work.Block.WithSeal(result)/ Solutio
57、ns seems to be valid, return to the miner and notify acceptancea.returnCh startNode- utils.StartNode(stack)- stack.Start()- /node/node.go/Start() - service.Start(running)- /eth/backend.go/Start() - /eth/handler.go/Start()好了核心邏輯在handler.go/Start()里面func (pm *ProtocolManager) Start(maxPeers int) pm.ma
58、xPeers = maxPeers/ broadcast transactions/ 廣播交易的通道。 txCh會作為txpool的TxPreEvent訂閱通道。txpool有了這種消息會通知給這個txCh。 廣播交易的goroutine會把這個消息廣播出去。pm.txCh = make(chan core.TxPreEvent, txChanSize)/ 訂閱的回執(zhí)pm.txSub = pm.txpool.SubscribeTxPreEvent(pm.txCh)go pm.txBroadcastLoop()/ 訂閱挖礦消息。當(dāng)新的Block被挖出來的時候會產(chǎn)生消息。 這個訂閱和上面的那個訂閱
59、采用了兩種不同的模式,這種是標(biāo)記為Deprecated的訂閱方式。/ broadcast mined blockspm.minedBlockSub = pm.eventMux.Subscribe(core.NewMinedBlockEvent)/挖礦廣播 goroutine 當(dāng)挖出來的時候需要盡快的廣播到網(wǎng)絡(luò)上面去 本地挖出的塊通過這種形式廣播出去go pm.minedBroadcastLoop()/ 同步器負(fù)責(zé)周期性地與網(wǎng)絡(luò)同步,下載散列和塊以及處理通知處理程序。/ start sync handlersgo pm.syncer()/ txsyncLoop負(fù)責(zé)每個新連接的初始事務(wù)同步。 當(dāng)新
60、的peer出現(xiàn)時,我們轉(zhuǎn)發(fā)所有當(dāng)前待處理的事務(wù)。 為了最小化出口帶寬使用,我們一次只發(fā)送一個小包。go pm.txsyncLoop()pm.minedBroadcastLoop()里面就有管道接收到上面post出來的出塊消息,跟進(jìn)去將會看到通過p2p網(wǎng)絡(luò)發(fā)送給節(jié)點的邏輯/ BroadcastBlock will either propagate a block to a subset of its peers, or/ will only announce its availability (depending whats requested).func (pm *ProtocolManage
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 歷史街區(qū)石材裝修配送協(xié)議
- 親子酒店裝修項目合同
- 校園裝修合同樣本-@-1
- 鎮(zhèn)江彩鋼瓦防腐施工方案
- 木材加工配送合同模板
- 化工原料特種運(yùn)輸協(xié)議
- 2025年度網(wǎng)絡(luò)安全技術(shù)顧問聘用協(xié)議
- 國際旅游業(yè)務(wù)居間協(xié)議
- 魚塘合作管理方案
- 象山消防通風(fēng)排煙施工方案
- 徐金桂行政法與行政訴訟法新講義
- 瀝青拌合設(shè)備結(jié)構(gòu)認(rèn)知
- GB/T 13234-2018用能單位節(jié)能量計算方法
- (課件)肝性腦病
- 北師大版五年級上冊數(shù)學(xué)教學(xué)課件第5課時 人民幣兌換
- 工程回訪記錄單
- 住房公積金投訴申請書
- 高考物理二輪專題課件:“配速法”解決擺線問題
- 檢驗科生物安全風(fēng)險評估報告
- 京頤得移動門診產(chǎn)品輸液
- 如何做一名合格的帶教老師PPT精選文檔
評論
0/150
提交評論