1+ const logger = new ( require ( '../logger' ) ) ( 'BLOCK_POOL' ) ;
2+
13const _get = require ( 'lodash/get' ) ;
2- const logger = require ( '../logger' ) ( 'BLOCK_POOL' ) ;
3- const { ConsensusConsts, ValidatorOffenseTypes } = require ( './constants' ) ;
4+ const { ConsensusConsts, ValidatorOffenseTypes } = require ( '../consensus/constants' ) ;
45const { StateVersions } = require ( '../common/constants' ) ;
56const CommonUtil = require ( '../common/common-util' ) ;
6- const ConsensusUtil = require ( './consensus-util' ) ;
7+ const ConsensusUtil = require ( '../consensus /consensus-util' ) ;
78const Transaction = require ( '../tx-pool/transaction' ) ;
89
910class BlockPool {
10- constructor ( node , lastBlock ) {
11+ constructor ( node ) {
1112 this . node = node ;
1213 const lastFinalizedBlock = this . node . bc . lastBlock ( ) ;
14+ this . longestNotarizedChainTips = lastFinalizedBlock ? [ lastFinalizedBlock . hash ] : [ ] ;
1315
1416 // Mapping of a block hash to the block's info (block, proposal tx, voting txs)
1517 // e.g. { [<blockHash>]: { block, proposal, votes: { [<address>]: <number> }, tallied } }
@@ -28,41 +30,24 @@ class BlockPool {
2830 // Mapping of a number to a set of block hashes proposed for the number.
2931 // e.g. { [<blockNumber>]: Set<blockHash> }
3032 this . numberToBlockSet = { } ;
33+ this . heighestSeenBlockNumber = - 1 ;
34+ }
3135
32- this . longestNotarizedChainTips = [ lastFinalizedBlock . hash ] ;
33-
34- let lastFinalizedBlockHash ; let lastFinalizedBlockEpoch ; let lastFinalizedBlockNumber ;
35- if ( lastFinalizedBlock ) {
36- lastFinalizedBlockHash = lastFinalizedBlock . hash ;
37- lastFinalizedBlockEpoch = lastFinalizedBlock . epoch ;
38- lastFinalizedBlockNumber = lastFinalizedBlock . number ;
39- }
40- if ( lastBlock ) {
41- const lastBlockHash = lastBlock . hash ;
42- const lastBlockEpoch = lastBlock . epoch ;
43- const lastBlockNumber = lastBlock . number ;
44- if ( lastFinalizedBlock && lastFinalizedBlock . hash === lastBlock . last_hash ) {
45- const proposal = ConsensusUtil . filterProposalFromVotes ( lastBlock . last_votes ) ;
46- this . hashToBlockInfo [ lastFinalizedBlockHash ] = {
47- block : lastFinalizedBlock ,
48- proposal,
49- votes : lastBlock . last_votes . filter ( ( val ) => val . hash !== proposal . hash ) ,
50- notarized : true
51- } ;
52- this . hashToNextBlockSet [ lastFinalizedBlockHash ] = new Set ( [ lastBlockHash ] ) ;
53- this . epochToBlock [ lastFinalizedBlockEpoch ] = lastFinalizedBlockHash ;
54- this . numberToBlockSet [ lastFinalizedBlockNumber ] = new Set ( [ lastFinalizedBlockHash ] ) ;
55- }
56- this . hashToBlockInfo [ lastBlockHash ] = { block : lastBlock } ;
57- this . epochToBlock [ lastBlockEpoch ] = lastBlockHash ;
58- this . numberToBlockSet [ lastBlockNumber ] = new Set ( [ lastBlockHash ] ) ;
59- } else if ( lastFinalizedBlock ) {
60- this . hashToBlockInfo [ lastFinalizedBlockHash ] = { block : lastFinalizedBlock , notarized : true } ;
61- this . epochToBlock [ lastFinalizedBlockEpoch ] = lastFinalizedBlockHash ;
62- this . numberToBlockSet [ lastFinalizedBlockNumber ] = new Set ( [ lastFinalizedBlockHash ] ) ;
36+ getLongestNotarizedChainHeight ( ) {
37+ return this . longestNotarizedChainTips . length > 0 ?
38+ this . hashToBlockInfo [ this . longestNotarizedChainTips [ 0 ] ] . block . number : this . node . bc . lastBlockNumber ( ) ;
39+ }
40+
41+ updateHighestSeenBlockNumber ( blockNumber ) {
42+ if ( blockNumber > this . heighestSeenBlockNumber ) {
43+ this . heighestSeenBlockNumber = blockNumber ;
6344 }
6445 }
6546
47+ getHeighestSeenBlockNumber ( ) {
48+ return this . heighestSeenBlockNumber ;
49+ }
50+
6651 updateLongestNotarizedChains ( ) {
6752 const LOG_HEADER = 'updateLongestNotarizedChains' ;
6853 const currentLongest = this . longestNotarizedChainTips . length ?
@@ -120,7 +105,7 @@ class BlockPool {
120105 const LOG_HEADER = 'getLongestNotarizedChainList' ;
121106 const lastBlockNumber = this . node . bc . lastBlockNumber ( ) ;
122107 const lastFinalized = fromBlock ? fromBlock
123- : lastBlockNumber < 1 ? { block : this . node . bc . lastBlock ( ) , notarized : true }
108+ : lastBlockNumber < 1 ? { block : this . node . bc . lastBlock ( ) , notarized : true }
124109 : this . hashToBlockInfo [ this . node . bc . lastBlock ( ) . hash ] ;
125110 logger . debug ( `[${ LOG_HEADER } ] lastFinalized: ${ JSON . stringify ( lastFinalized , null , 2 ) } ` ) ;
126111 const chainList = [ ] ;
@@ -129,6 +114,7 @@ class BlockPool {
129114 }
130115
131116 dfsLongest ( currentNode , currentChain , chainList , withInfo = false ) {
117+ const LOG_HEADER = 'dfsLongest' ;
132118 if ( ! currentNode || ! currentNode . notarized || ! currentNode . block ) {
133119 return ;
134120 }
@@ -143,13 +129,13 @@ class BlockPool {
143129 chainList [ 0 ] [ chainList [ 0 ] . length - 1 ] . block . number :
144130 chainList [ 0 ] [ chainList [ 0 ] . length - 1 ] . number : 0 ;
145131 if ( blockNumber > longestNumber ) {
146- logger . debug ( '[blockPool:dfsLongest ] New longest chain found: ' +
132+ logger . debug ( `[ ${ LOG_HEADER } ] New longest chain found: ` +
147133 `${ JSON . stringify ( currentChain , null , 2 ) } , longestNumber: ${ blockNumber } ` ) ;
148134 chainList . length = 0 ;
149135 chainList . push ( [ ...currentChain ] ) ;
150136 longestNumber = blockNumber ;
151137 } else if ( blockNumber === longestNumber ) {
152- logger . debug ( '[blockPool:dfsLongest ] Another longest chain found: ' +
138+ logger . debug ( `[ ${ LOG_HEADER } ] Another longest chain found: ` +
153139 `${ JSON . stringify ( currentChain , null , 2 ) } , longestNumber: ${ blockNumber } ` ) ;
154140 chainList . push ( [ ...currentChain ] ) ;
155141 }
@@ -162,16 +148,26 @@ class BlockPool {
162148 this . dfsLongest ( this . hashToBlockInfo [ val ] , currentChain , chainList , withInfo ) ;
163149 }
164150 currentChain . pop ( ) ;
165- logger . debug ( '[blockPool:dfsLongest] returning.. currentChain: ' +
166- `${ JSON . stringify ( currentChain , null , 2 ) } ` ) ;
151+ logger . debug ( `[${ LOG_HEADER } ] returning.. currentChain: ${ JSON . stringify ( currentChain , null , 2 ) } ` ) ;
167152 }
168153
169154 // A finalizable chain (extension of current finalized chain):
170155 // 1. all of its blocks are notarized
171156 // 2. ends with three blocks that have consecutive epoch numbers
172- getFinalizableChain ( ) {
157+ getFinalizableChain ( isGenesisStart ) {
158+ const genesisBlockHash = this . node . bc . genesisBlockHash ;
159+ const genesisBlockInfo = this . hashToBlockInfo [ genesisBlockHash ] ;
160+ const chainWithGenesisBlock = genesisBlockInfo ? [ genesisBlockInfo . block ] : [ ] ;
161+ if ( isGenesisStart ) {
162+ return chainWithGenesisBlock ;
163+ }
173164 const lastFinalized = { block : this . node . bc . lastBlock ( ) , notarized : true } ;
174- return this . dfsFinalizable ( lastFinalized , [ ] ) ;
165+ const chain = this . dfsFinalizable ( lastFinalized , [ ] ) ;
166+ if ( chain . length === 0 && this . node . bc . lastBlockNumber ( ) < 0 && this . hashToBlockInfo [ genesisBlockHash ] ) {
167+ // When node first started (fetching from peers or loading from disk)
168+ return chainWithGenesisBlock ;
169+ }
170+ return chain ;
175171 }
176172
177173 dfsFinalizable ( currentNode , currentChain ) {
@@ -194,7 +190,7 @@ class BlockPool {
194190 return [ ...currentChain ] ;
195191 }
196192 let res ;
197- let longest = [ ] ;
193+ let longest = BlockPool . endsWithThreeConsecutiveEpochs ( currentChain ) ? [ ... currentChain ] : [ ] ;
198194 for ( const blockHash of nextBlockSet ) {
199195 res = this . dfsFinalizable ( this . hashToBlockInfo [ blockHash ] , currentChain ) ;
200196 if ( res && BlockPool . endsWithThreeConsecutiveEpochs ( res ) && res . length > longest . length ) {
@@ -230,10 +226,10 @@ class BlockPool {
230226 hasSeenBlock ( blockHash ) {
231227 if ( this . hashToBlockInfo [ blockHash ] ) {
232228 const blockInfo = this . hashToBlockInfo [ blockHash ] ;
233- return blockInfo && blockInfo . block && ( blockInfo . block . number === 0 || ! ! blockInfo . proposal ) ;
229+ return blockInfo && blockInfo . block ;
234230 } else if ( this . hashToInvalidBlockInfo [ blockHash ] ) {
235231 const blockInfo = this . hashToInvalidBlockInfo [ blockHash ] ;
236- return blockInfo && blockInfo . block && ( blockInfo . block . number === 0 || ! ! blockInfo . proposal ) ;
232+ return blockInfo && blockInfo . block ;
237233 }
238234 return false ;
239235 }
@@ -316,10 +312,14 @@ class BlockPool {
316312 this . hashToNextBlockSet [ lastHash ] . add ( block . hash ) ;
317313 }
318314
315+ addToHashToDbMap ( blockHash , db ) {
316+ this . hashToDb . set ( blockHash , db ) ;
317+ }
318+
319319 addSeenBlock ( block , proposalTx , isValid = true ) {
320320 const LOG_HEADER = 'addSeenBlock' ;
321321 logger . info (
322- `[${ LOG_HEADER } ] Adding seen block to the block pool: ${ block . number } / ${ block . epoch } / ${ isValid } ` ) ;
322+ `[${ LOG_HEADER } ] Adding seen block to the block pool: ${ block . hash } / ${ block . number } / ${ block . epoch } / ${ isValid } ` ) ;
323323 const blockHash = block . hash ;
324324 if ( isValid ) {
325325 if ( ! this . checkEpochToBlockMap ( block ) ) {
@@ -340,6 +340,7 @@ class BlockPool {
340340 this . addToInvalidBlockInfoMap ( block , proposalTx ) ;
341341 this . addToNumberToBlockSet ( block ) ;
342342 }
343+ this . updateHighestSeenBlockNumber ( block . number ) ;
343344 return true ;
344345 }
345346
@@ -417,13 +418,13 @@ class BlockPool {
417418
418419 addProposal ( proposalTx , blockHash ) {
419420 const LOG_HEADER = 'addProposal' ;
420- if ( ! this . hashToInvalidBlockInfo [ blockHash ] ) {
421- this . hashToInvalidBlockInfo [ blockHash ] = { } ;
422- } else if ( this . hashToInvalidBlockInfo [ blockHash ] . proposal ) {
421+ if ( ! this . hashToBlockInfo [ blockHash ] ) {
422+ this . hashToBlockInfo [ blockHash ] = { } ;
423+ } else if ( this . hashToBlockInfo [ blockHash ] . proposal ) {
423424 logger . debug ( `[${ LOG_HEADER } ] Already have seen this proposal` ) ;
424425 return ;
425426 }
426- this . hashToInvalidBlockInfo [ blockHash ] . proposal = proposalTx ;
427+ this . hashToBlockInfo [ blockHash ] . proposal = proposalTx ;
427428 logger . debug ( `[${ LOG_HEADER } ] Proposal tx for block added: ${ blockHash } ` ) ;
428429 }
429430
@@ -434,13 +435,18 @@ class BlockPool {
434435 logger . info ( `[${ LOG_HEADER } ] Current block is unavailable` ) ;
435436 return ;
436437 }
438+ if ( currentBlockInfo . block . number === 0 ) {
439+ this . hashToBlockInfo [ currentBlockInfo . block . hash ] . notarized = true ;
440+ this . updateLongestNotarizedChains ( this . hashToBlockInfo [ currentBlockInfo . block . hash ] ) ;
441+ return ;
442+ }
437443 const lastBlockNumber = currentBlockInfo . block . number - 1 ;
438444 const lastHash = currentBlockInfo . block . last_hash ;
439445 const lastFinalizedBlock = this . node . bc . lastBlock ( ) ;
440446 let prevBlock ;
441- if ( lastBlockNumber === lastFinalizedBlock . number ) {
447+ if ( lastFinalizedBlock && lastFinalizedBlock . number === lastBlockNumber ) {
442448 prevBlock = lastFinalizedBlock ;
443- } else if ( lastBlockNumber > lastFinalizedBlock . number ) {
449+ } else if ( _get ( this . hashToBlockInfo [ lastHash ] , 'block' ) ) {
444450 prevBlock = _get ( this . hashToBlockInfo [ lastHash ] , 'block' ) ;
445451 } else {
446452 prevBlock = this . node . bc . getBlockByHash ( lastHash ) ;
@@ -472,12 +478,13 @@ class BlockPool {
472478 }
473479 }
474480
475- // Remove everything that came before lastBlock including lastBlock .
481+ // Remove everything that came before lastBlock.
476482 cleanUpAfterFinalization ( lastBlock , recordedInvalidBlocks ) {
477483 const targetNumber = lastBlock . number ;
478- Object . keys ( this . numberToBlockSet ) . forEach ( ( blockNumber ) => {
484+ for ( const blockNumber of Object . keys ( this . numberToBlockSet ) ) {
479485 if ( blockNumber < targetNumber ) {
480- this . numberToBlockSet [ blockNumber ] . forEach ( ( blockHash ) => {
486+ const blockHashList = this . numberToBlockSet [ blockNumber ] ;
487+ for ( const blockHash of blockHashList ) {
481488 if ( this . hashToInvalidBlockInfo [ blockHash ] ) {
482489 if ( recordedInvalidBlocks . has ( blockHash ) ||
483490 blockNumber < targetNumber - ConsensusConsts . MAX_CONSENSUS_LOGS_IN_STATES ) {
@@ -488,19 +495,19 @@ class BlockPool {
488495 this . cleanUpForBlockHash ( blockHash ) ;
489496 this . numberToBlockSet [ blockNumber ] . delete ( blockHash ) ;
490497 }
491- } ) ;
498+ }
492499 if ( ! this . numberToBlockSet [ blockNumber ] . size ) {
493500 delete this . numberToBlockSet [ blockNumber ] ;
494501 }
495502 }
496- } ) ;
497- Object . keys ( this . epochToBlock ) . forEach ( ( epoch ) => {
503+ }
504+ for ( const epoch of Object . keys ( this . epochToBlock ) ) {
498505 if ( epoch < lastBlock . epoch ) {
499506 const blockHash = this . epochToBlock [ epoch ] ;
500507 this . cleanUpForBlockHash ( blockHash ) ;
501508 delete this . epochToBlock [ epoch ] ;
502509 }
503- } ) ;
510+ }
504511 this . updateLongestNotarizedChains ( ) ;
505512 }
506513
0 commit comments