diff options
Diffstat (limited to 'core/test/block-revealer.go')
-rw-r--r-- | core/test/block-revealer.go | 214 |
1 files changed, 3 insertions, 211 deletions
diff --git a/core/test/block-revealer.go b/core/test/block-revealer.go index ebd2e35..90b3d3e 100644 --- a/core/test/block-revealer.go +++ b/core/test/block-revealer.go @@ -19,9 +19,7 @@ package test import ( "errors" - "math/rand" "sort" - "time" "github.com/dexon-foundation/dexon-consensus/common" "github.com/dexon-foundation/dexon-consensus/core/db" @@ -65,217 +63,11 @@ func loadAllBlocks(iter db.BlockIterator) ( return } -// RandomDAGBlockRevealer implements BlockRevealer interface, which would load -// all blocks from db, and randomly pick one block to reveal if it still forms -// a valid DAG in revealed blocks. -type RandomDAGBlockRevealer struct { - // blocksByChain group all blocks by chains and sorting - // them by height. - blocksByChain map[uint32][]*types.Block - // tipIndexes store the height of next block from one chain - // to check if is candidate. - tipIndexes map[uint32]int - // candidate are blocks that forms valid DAG with - // current revealed blocks. - candidates []*types.Block - candidateChains map[uint32]struct{} - // revealed stores block hashes of current revealed blocks. - revealed map[common.Hash]struct{} - randGen *rand.Rand -} - -// NewRandomDAGBlockRevealer constructs RandomDAGBlockRevealer. -func NewRandomDAGBlockRevealer( - iter db.BlockIterator) (r *RandomDAGBlockRevealer, err error) { - - blocks, err := loadAllBlocks(iter) - if err != nil { - return - } - - // Rearrange blocks by nodes and height. - blocksByChain := make(map[uint32][]*types.Block) - for _, block := range blocks { - blocksByChain[block.Position.ChainID] = - append(blocksByChain[block.Position.ChainID], block) - } - // Make sure blocks are sorted by block heights, from lower to higher. - for chainID := range blocksByChain { - sort.Sort(types.ByPosition(blocksByChain[chainID])) - } - r = &RandomDAGBlockRevealer{ - blocksByChain: blocksByChain, - randGen: rand.New(rand.NewSource(time.Now().UnixNano())), - candidateChains: make(map[uint32]struct{}), - } - // Make sure this revealer is ready to use. - r.Reset() - return -} - -// pickCandidates is a helper function to pick candidates from current tips. -func (r *RandomDAGBlockRevealer) pickCandidates() { - for chainID, tip := range r.tipIndexes { - if _, isPicked := r.candidateChains[chainID]; isPicked { - continue - } - blocks, exists := r.blocksByChain[chainID] - if !exists { - continue - } - if tip >= len(blocks) { - continue - } - block := blocks[tip] - if isAllAckingBlockRevealed(block, r.revealed) { - r.tipIndexes[chainID]++ - r.candidates = append(r.candidates, block) - r.candidateChains[chainID] = struct{}{} - } - } -} - -// NextBlock implement Revealer.Next method, which would reveal blocks -// forming valid DAGs. -func (r *RandomDAGBlockRevealer) NextBlock() (types.Block, error) { - if len(r.candidates) == 0 { - r.pickCandidates() - if len(r.candidates) == 0 { - return types.Block{}, db.ErrIterationFinished - } - } - - // Pick next block to be revealed. - picked := r.randGen.Intn(len(r.candidates)) - block := r.candidates[picked] - r.candidates = - append(r.candidates[:picked], r.candidates[picked+1:]...) - delete(r.candidateChains, block.Position.ChainID) - r.revealed[block.Hash] = struct{}{} - r.pickCandidates() - return *block, nil -} - -// Reset implement Revealer.Reset method, which would reset the revealing. -func (r *RandomDAGBlockRevealer) Reset() { - r.tipIndexes = make(map[uint32]int) - for chainID := range r.blocksByChain { - r.tipIndexes[chainID] = 0 - } - r.revealed = make(map[common.Hash]struct{}) - r.candidates = []*types.Block{} -} - -// RandomBlockRevealer implements BlockRevealer interface, which would load -// all blocks from db, and randomly pick one block to reveal. -type RandomBlockRevealer struct { - blocks map[common.Hash]*types.Block - remains common.Hashes - randGen *rand.Rand -} - -// NewRandomBlockRevealer constructs RandomBlockRevealer. -func NewRandomBlockRevealer( - iter db.BlockIterator) (r *RandomBlockRevealer, err error) { - - blocks, err := loadAllBlocks(iter) - if err != nil { - return - } - r = &RandomBlockRevealer{ - blocks: blocks, - randGen: rand.New(rand.NewSource(time.Now().UnixNano())), - } - r.Reset() - return -} - -// NextBlock implements Revealer.NextBlock method, which would reveal blocks -// randomly. -func (r *RandomBlockRevealer) NextBlock() (types.Block, error) { - if len(r.remains) == 0 { - return types.Block{}, db.ErrIterationFinished - } - - picked := r.randGen.Intn(len(r.remains)) - block := r.blocks[r.remains[picked]] - r.remains = - append(r.remains[:picked], r.remains[picked+1:]...) - return *block, nil -} - -// Reset implement Revealer.Reset method, which would reset revealing. -func (r *RandomBlockRevealer) Reset() { - hashes := common.Hashes{} - for hash := range r.blocks { - hashes = append(hashes, hash) - } - r.remains = hashes -} - -// RandomTipBlockRevealer implements BlockRevealer interface, which would load -// all blocks from db, and randomly pick one chain's tip to reveal. -type RandomTipBlockRevealer struct { - chainsBlock []map[uint64]*types.Block - chainTip []uint64 - chainRevealSeq []uint32 - revealed int - randGen *rand.Rand -} - -// NewRandomTipBlockRevealer constructs RandomTipBlockRevealer. -func NewRandomTipBlockRevealer( - iter db.BlockIterator) (r *RandomTipBlockRevealer, err error) { - - blocks, err := loadAllBlocks(iter) - if err != nil { - return - } - r = &RandomTipBlockRevealer{ - randGen: rand.New(rand.NewSource(time.Now().UnixNano())), - } - for _, b := range blocks { - for b.Position.ChainID >= uint32(len(r.chainsBlock)) { - r.chainsBlock = append(r.chainsBlock, make(map[uint64]*types.Block)) - r.chainTip = append(r.chainTip, 0) - } - r.chainsBlock[b.Position.ChainID][b.Position.Height] = b - r.chainRevealSeq = append(r.chainRevealSeq, b.Position.ChainID) - } - r.Reset() - return -} - -// NextBlock implements Revealer.Next method, which would reveal blocks randomly. -func (r *RandomTipBlockRevealer) NextBlock() (types.Block, error) { - if len(r.chainRevealSeq) == r.revealed { - return types.Block{}, db.ErrIterationFinished - } - - picked := r.chainRevealSeq[r.revealed] - r.revealed++ - block := r.chainsBlock[picked][r.chainTip[picked]] - r.chainTip[picked]++ - return *block, nil -} - -// Reset implement Revealer.Reset method, which would reset revealing. -func (r *RandomTipBlockRevealer) Reset() { - r.revealed = 0 - r.randGen.Shuffle(len(r.chainRevealSeq), func(i, j int) { - r.chainRevealSeq[i], r.chainRevealSeq[j] = - r.chainRevealSeq[j], r.chainRevealSeq[i] - }) - for i := range r.chainTip { - r.chainTip[i] = 0 - } -} - // CompactionChainBlockRevealer implements BlockRevealer interface, which would // load all blocks from db, reveal them in the order of compaction chain, // from the genesis block to the latest one. type CompactionChainBlockRevealer struct { - blocks types.ByFinalizationHeight + blocks types.BlocksByFinalizationHeight nextRevealIndex int } @@ -290,14 +82,14 @@ func NewCompactionChainBlockRevealer(iter db.BlockIterator, if startHeight == 0 { startHeight = 1 } - blocks := types.ByFinalizationHeight{} + blocks := types.BlocksByFinalizationHeight{} for _, b := range blocksByHash { if b.Finalization.Height < startHeight { continue } blocks = append(blocks, b) } - sort.Sort(types.ByFinalizationHeight(blocks)) + sort.Sort(types.BlocksByFinalizationHeight(blocks)) // Make sure the finalization height of blocks are incremental with step 1. for idx, b := range blocks { if idx == 0 { |