diff options
-rw-r--r-- | core/blockpool.go | 2 | ||||
-rw-r--r-- | core/lattice-data.go | 13 | ||||
-rw-r--r-- | core/total-ordering.go | 28 |
3 files changed, 38 insertions, 5 deletions
diff --git a/core/blockpool.go b/core/blockpool.go index 7441cf9..60b8f5d 100644 --- a/core/blockpool.go +++ b/core/blockpool.go @@ -38,7 +38,7 @@ func newBlockPool(chainNum uint32) (pool blockPool) { // resize the pool if new chain is added. func (p *blockPool) resize(num uint32) { - if uint32(len(*p)) < num { + if uint32(len(*p)) >= num { return } newPool := make([]types.ByPosition, num) diff --git a/core/lattice-data.go b/core/lattice-data.go index 2a3ec29..dd0b534 100644 --- a/core/lattice-data.go +++ b/core/lattice-data.go @@ -389,6 +389,10 @@ func (data *latticeData) prepareBlock(b *types.Block) error { if config = data.getConfig(b.Position.Round); config == nil { return ErrUnknownRoundID } + // When this chain is illegal in this round, reject it. + if b.Position.ChainID >= config.numChains { + return ErrInvalidChainID + } // Reset fields to make sure we got these information from parent block. b.Position.Height = 0 b.ParentHash = common.Hash{} @@ -449,9 +453,12 @@ func (data *latticeData) prepareBlock(b *types.Block) error { // The reference block is already acked. continue } - // Can't ack block too old or too new to us. - if DiffUint64( - status.tip.Position.Round, b.Position.Round) > 1 { + if status.tip.Position.Round > b.Position.Round { + // Avoid forward acking: acking some block from later rounds. + continue + } + if b.Position.Round > status.tip.Position.Round+1 { + // Can't ack block too old or too new to us. continue } acks = append(acks, status.tip.Hash) diff --git a/core/total-ordering.go b/core/total-ordering.go index ec9e643..480cdd4 100644 --- a/core/total-ordering.go +++ b/core/total-ordering.go @@ -214,6 +214,11 @@ func (cache *totalOrderingObjectCache) requestAckedStatus() ( // recycleAckedStatys recycles the structure to record acking status. func (cache *totalOrderingObjectCache) recycleAckedStatus( acked []*totalOrderingHeightRecord) { + // If the recycled objects supports lower numChains than we required, + // don't recycle it. + if uint32(len(acked)) != cache.numChains { + return + } cache.ackedStatus = append(cache.ackedStatus, acked) } @@ -231,6 +236,11 @@ func (cache *totalOrderingObjectCache) recycleWinRecord( if win == nil { return } + // If the recycled objects supports lower numChains than we required, + // don't recycle it. + if uint32(len(win.wins)) != cache.numChains { + return + } cache.winRecordPool.Put(win) } @@ -253,6 +263,11 @@ func (cache *totalOrderingObjectCache) requestHeightVector() (hv []uint64) { // recycleHeightVector recycles an instance to record acking heights // of one candidate. func (cache *totalOrderingObjectCache) recycleHeightVector(hv []uint64) { + // If the recycled objects supports lower numChains than we required, + // don't recycle it. + if uint32(len(hv)) != cache.numChains { + return + } cache.heightVectors = append(cache.heightVectors, hv) } @@ -275,6 +290,11 @@ func (cache *totalOrderingObjectCache) requestWinRecordContainer() ( // recycleWinRecordContainer recycles a map of totalOrderingWinRecord. func (cache *totalOrderingObjectCache) recycleWinRecordContainer( con []*totalOrderingWinRecord) { + // If the recycled objects supports lower numChains than we required, + // don't recycle it. + if uint32(len(con)) != cache.numChains { + return + } cache.winRecordContainers = append(cache.winRecordContainers, con) } @@ -1292,9 +1312,15 @@ func (to *totalOrdering) deliverBlocks() ( if !cfg.isValidLastBlock(b) { continue } - to.flushReadyChains[b.Position.ChainID] = struct{}{} to.flushed[b.Position.ChainID] = struct{}{} } + // Some last blocks for the round to be flushed might not be delivered + // yet. + for _, tip := range to.globalVector.tips[:cfg.numChains] { + if tip.Position.Round > to.curRound || cfg.isValidLastBlock(tip) { + to.flushReadyChains[tip.Position.ChainID] = struct{}{} + } + } } return } |