aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/blockpool.go2
-rw-r--r--core/lattice-data.go13
-rw-r--r--core/total-ordering.go28
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
}