Skip to content

Commit 3e3ebee

Browse files
committed
move pool into chainmgr
1 parent 927fdd6 commit 3e3ebee

File tree

10 files changed

+72
-115
lines changed

10 files changed

+72
-115
lines changed

blockchain/blockchain.go

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ type (
116116
BlockBuilderFactory interface {
117117
// NewBlockBuilder creates block builder
118118
Mint(ctx context.Context, pk crypto.PrivateKey) (*block.Block, error)
119-
Init(hash.Hash256)
120119
}
121120

122121
// blockchain implements the Blockchain interface
@@ -253,17 +252,7 @@ func (bc *blockchain) Start(ctx context.Context) error {
253252
GetBlockTime: bc.getBlockTime,
254253
},
255254
), bc.genesis))
256-
err := bc.lifecycle.OnStart(ctx)
257-
if err != nil {
258-
return err
259-
}
260-
// init block builder factory
261-
if tip, err := bc.tipInfo(bc.TipHeight()); err != nil {
262-
return errors.Wrap(err, "failed to get tip info")
263-
} else {
264-
bc.bbf.Init(tip.Hash)
265-
return nil
266-
}
255+
return bc.lifecycle.OnStart(ctx)
267256
}
268257

269258
// Stop stops the blockchain.

consensus/scheme/rolldpos/chainmanager.go

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,13 @@ type (
6262
}
6363
// StateReaderFactory is the factory interface of state reader
6464
StateReaderFactory interface {
65-
StateReaderAt(*block.Header) (protocol.StateReader, error)
65+
StateReaderAt(hash.Hash256) (protocol.StateReader, error)
6666
}
6767

6868
// BlockBuilderFactory is the factory interface of block builder
6969
BlockBuilderFactory interface {
7070
Mint(ctx context.Context, pk crypto.PrivateKey) (*block.Block, error)
7171
ReceiveBlock(*block.Block) error
72-
Init(hash.Hash256)
73-
AddProposal(*block.Block) error
74-
Block(hash.Hash256) *block.Block
7572
}
7673

7774
chainManager struct {
@@ -80,6 +77,7 @@ type (
8077
timerFactory *prometheustimer.TimerFactory
8178
bc blockchain.Blockchain
8279
bbf BlockBuilderFactory
80+
pool *proposalPool
8381
}
8482

8583
forkChain struct {
@@ -118,6 +116,7 @@ func NewChainManager(bc blockchain.Blockchain, srf StateReaderFactory, bbf Block
118116
bbf: bbf,
119117
timerFactory: timerFactory,
120118
srf: srf,
119+
pool: newProposalPool(),
121120
}
122121
}
123122

@@ -197,7 +196,7 @@ func (cm *chainManager) mintNewBlock(timestamp time.Time, pk crypto.PrivateKey,
197196
if err != nil {
198197
return nil, errors.Wrapf(err, "failed to create block")
199198
}
200-
if err = cm.bbf.AddProposal(blk); err != nil {
199+
if err = cm.pool.AddBlock(blk); err != nil {
201200
blkHash := blk.HashBlock()
202201
log.L().Error("failed to add proposal", zap.Error(err), zap.Uint64("height", blk.Height()), log.Hex("hash", blkHash[:]))
203202
}
@@ -221,11 +220,7 @@ func (fc *forkChain) TipHash() hash.Hash256 {
221220
}
222221

223222
func (cm *chainManager) StateReader() (protocol.StateReader, error) {
224-
head, err := cm.bc.BlockHeaderByHeight(cm.bc.TipHeight())
225-
if err != nil {
226-
return nil, errors.Wrap(err, "failed to get the head block")
227-
}
228-
return cm.srf.StateReaderAt(head)
223+
return cm.srf.StateReaderAt(cm.bc.TipHash())
229224
}
230225

231226
// StateReader returns the state reader
@@ -239,7 +234,7 @@ func (cm *chainManager) ValidateBlock(blk *block.Block) error {
239234
if err != nil {
240235
return err
241236
}
242-
if err = cm.bbf.AddProposal(blk); err != nil {
237+
if err = cm.pool.AddBlock(blk); err != nil {
243238
blkHash := blk.HashBlock()
244239
log.L().Error("failed to add proposal", zap.Error(err), zap.Uint64("height", blk.Height()), log.Hex("hash", blkHash[:]))
245240
}
@@ -255,6 +250,10 @@ func (cm *chainManager) CommitBlock(blk *block.Block) error {
255250
blkHash := blk.HashBlock()
256251
log.L().Error("failed to receive block", zap.Error(err), zap.Uint64("height", blk.Height()), log.Hex("hash", blkHash[:]))
257252
}
253+
if err := cm.pool.ReceiveBlock(blk); err != nil {
254+
blkHash := blk.HashBlock()
255+
log.L().Error("failed to receive block", zap.Error(err), zap.Uint64("height", blk.Height()), log.Hex("hash", blkHash[:]))
256+
}
258257
return nil
259258
}
260259

@@ -263,32 +262,38 @@ func (cm *chainManager) Start(ctx context.Context) error {
263262
if err != nil {
264263
return errors.Wrap(err, "failed to get the head block")
265264
}
266-
cm.bbf.Init(head.HashBlock())
265+
cm.pool.Init(head.HashBlock())
267266
return nil
268267
}
269268

270269
// Fork creates a new chain manager with the given hash
271270
func (cm *chainManager) Fork(hash hash.Hash256) (ForkChain, error) {
272-
head, err := cm.bc.BlockHeaderByHeight(cm.bc.TipHeight())
273-
if err != nil {
274-
return nil, errors.Wrap(err, "failed to get the head block")
275-
}
276-
if hash != head.HashBlock() {
277-
blk := cm.bbf.Block(hash)
271+
var (
272+
head *block.Header
273+
err error
274+
tip = cm.tipInfo()
275+
)
276+
if hash != tip.Hash {
277+
blk := cm.pool.BlockByHash(hash)
278278
if blk == nil {
279279
return nil, errors.Errorf("block %x not found when fork", hash)
280280
}
281281
head = &blk.Header
282+
} else {
283+
head, err = cm.bc.BlockHeaderByHeight(tip.Height)
284+
if head == nil {
285+
return nil, errors.Errorf("block %x not found when fork", hash)
286+
}
282287
}
283-
sr, err := cm.srf.StateReaderAt(head)
288+
sr, err := cm.srf.StateReaderAt(hash)
284289
if err != nil {
285290
return nil, errors.Wrapf(err, "failed to create state reader at %d, hash %x", head.Height(), head.HashBlock())
286291
}
287292
return newForkChain(cm, head, sr), nil
288293
}
289294

290295
func (cm *chainManager) draftBlockByHeight(height uint64, tipHash hash.Hash256) *block.Block {
291-
for blk := cm.bbf.Block(tipHash); blk != nil && blk.Height() >= height; blk = cm.bbf.Block(blk.PrevHash()) {
296+
for blk := cm.pool.BlockByHash(tipHash); blk != nil && blk.Height() >= height; blk = cm.pool.BlockByHash(blk.PrevHash()) {
292297
if blk.Height() == height {
293298
return blk
294299
}
@@ -305,6 +310,10 @@ func (cm *chainManager) TipHash() hash.Hash256 {
305310
}
306311

307312
func (fc *forkChain) tipHash() hash.Hash256 {
313+
if fc.head.Height() == 0 {
314+
g := fc.cm.bc.Genesis()
315+
return g.Hash()
316+
}
308317
return fc.head.HashBlock()
309318
}
310319

state/factory/proposalpool.go renamed to consensus/scheme/rolldpos/proposalpool.go

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package factory
1+
package rolldpos
22

33
import (
44
"sync"
@@ -14,30 +14,30 @@ import (
1414

1515
// proposalPool is a pool of draft blocks
1616
type proposalPool struct {
17-
// blocks is a map of draft blocks
17+
// nodes is a map of draft proposal blocks
1818
// key is the hash of the block
19-
blocks map[hash.Hash256]*block.Block
20-
// forks is a map of draft blocks that are forks
19+
nodes map[hash.Hash256]*block.Block
20+
// leaves is a map of tip blocks of forks
2121
// key is the hash of the tip block of the fork
2222
// value is the timestamp of the block
23-
forks map[hash.Hash256]time.Time
23+
leaves map[hash.Hash256]time.Time
2424
// root is the hash of the tip block of the blockchain
2525
root hash.Hash256
2626
mu sync.Mutex
2727
}
2828

2929
func newProposalPool() *proposalPool {
3030
return &proposalPool{
31-
blocks: make(map[hash.Hash256]*block.Block),
32-
forks: make(map[hash.Hash256]time.Time),
31+
nodes: make(map[hash.Hash256]*block.Block),
32+
leaves: make(map[hash.Hash256]time.Time),
3333
}
3434
}
3535

3636
func (d *proposalPool) Init(root hash.Hash256) {
3737
d.mu.Lock()
3838
defer d.mu.Unlock()
3939
d.root = root
40-
log.L().Info("proposal pool initialized", log.Hex("root", root[:]))
40+
log.L().Debug("proposal pool initialized", log.Hex("root", root[:]))
4141
}
4242

4343
// AddBlock adds a block to the draft pool
@@ -46,19 +46,19 @@ func (d *proposalPool) AddBlock(blk *block.Block) error {
4646
defer d.mu.Unlock()
4747
// nothing to do if the block already exists
4848
hash := blk.HashBlock()
49-
if _, ok := d.blocks[hash]; ok {
49+
if _, ok := d.nodes[hash]; ok {
5050
return nil
5151
}
5252
// it must be a new tip of any fork, or make a new fork
5353
prevHash := blk.PrevHash()
54-
if _, ok := d.forks[prevHash]; ok {
55-
delete(d.forks, prevHash)
54+
if _, ok := d.leaves[prevHash]; ok {
55+
delete(d.leaves, prevHash)
5656
} else if prevHash != d.root {
5757
return errors.Errorf("block %x is not a tip of any fork", prevHash[:])
5858
}
59-
d.forks[hash] = blk.Timestamp()
60-
d.blocks[hash] = blk
61-
log.L().Info("added block to draft pool", log.Hex("hash", hash[:]), zap.Uint64("height", blk.Height()), zap.Time("timestamp", blk.Timestamp()))
59+
d.leaves[hash] = blk.Timestamp()
60+
d.nodes[hash] = blk
61+
log.L().Debug("added block to draft pool", log.Hex("hash", hash[:]), zap.Uint64("height", blk.Height()), zap.Time("timestamp", blk.Timestamp()))
6262
return nil
6363
}
6464

@@ -74,22 +74,22 @@ func (d *proposalPool) ReceiveBlock(blk *block.Block) error {
7474
}
7575

7676
// remove blocks in other forks or older blocks in the same fork
77-
for f := range d.forks {
78-
start := d.blocks[f]
77+
for f := range d.leaves {
78+
start := d.nodes[f]
7979
if f == fork {
8080
start = blk
8181
}
82-
for b := start; b != nil; b = d.blocks[b.PrevHash()] {
82+
for b := start; b != nil; b = d.nodes[b.PrevHash()] {
8383
ha := b.HashBlock()
84-
log.L().Info("remove block from draft pool", log.Hex("hash", ha[:]), zap.Uint64("height", b.Height()), zap.Time("timestamp", b.Timestamp()))
85-
delete(d.blocks, b.HashBlock())
84+
log.L().Debug("remove block from draft pool", log.Hex("hash", ha[:]), zap.Uint64("height", b.Height()), zap.Time("timestamp", b.Timestamp()))
85+
delete(d.nodes, b.HashBlock())
8686
}
8787
}
8888
// reset forks to only this one
89-
if forkTime, ok := d.forks[fork]; ok && d.blocks[fork] != nil {
90-
d.forks = map[hash.Hash256]time.Time{fork: forkTime}
89+
if forkTime, ok := d.leaves[fork]; ok && d.nodes[fork] != nil {
90+
d.leaves = map[hash.Hash256]time.Time{fork: forkTime}
9191
} else {
92-
d.forks = map[hash.Hash256]time.Time{}
92+
d.leaves = map[hash.Hash256]time.Time{}
9393
}
9494
d.root = blk.HashBlock()
9595
return nil
@@ -100,7 +100,7 @@ func (d *proposalPool) Block(height uint64) *block.Block {
100100
d.mu.Lock()
101101
defer d.mu.Unlock()
102102
var blk *block.Block
103-
for _, b := range d.blocks {
103+
for _, b := range d.nodes {
104104
if b.Height() != height {
105105
continue
106106
} else if blk == nil {
@@ -116,13 +116,13 @@ func (d *proposalPool) Block(height uint64) *block.Block {
116116
func (d *proposalPool) BlockByHash(hash hash.Hash256) *block.Block {
117117
d.mu.Lock()
118118
defer d.mu.Unlock()
119-
return d.blocks[hash]
119+
return d.nodes[hash]
120120
}
121121

122122
func (d *proposalPool) BlockByTime(prevHash hash.Hash256, timestamp time.Time) *block.Block {
123123
d.mu.Lock()
124124
defer d.mu.Unlock()
125-
for _, b := range d.blocks {
125+
for _, b := range d.nodes {
126126
if b.PrevHash() == prevHash && b.Timestamp().Equal(timestamp) {
127127
return b
128128
}
@@ -133,12 +133,12 @@ func (d *proposalPool) BlockByTime(prevHash hash.Hash256, timestamp time.Time) *
133133
func (d *proposalPool) forkAt(blk *block.Block) (hash.Hash256, error) {
134134
blkHash := blk.HashBlock()
135135
// If this block isn't in the pool, just return it
136-
if _, ok := d.blocks[blkHash]; !ok {
136+
if _, ok := d.nodes[blkHash]; !ok {
137137
return blkHash, nil
138138
}
139139
// Otherwise, find which fork chain contains it
140-
for forkTip := range d.forks {
141-
for b := d.blocks[forkTip]; b != nil; b = d.blocks[b.PrevHash()] {
140+
for forkTip := range d.leaves {
141+
for b := d.nodes[forkTip]; b != nil; b = d.nodes[b.PrevHash()] {
142142
if blkHash == b.HashBlock() {
143143
return forkTip, nil
144144
}

consensus/scheme/rolldpos/rolldpos.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -162,12 +162,7 @@ func (r *RollDPoS) Calibrate(height uint64) {
162162
// ValidateBlockFooter validates the signatures in the block footer
163163
func (r *RollDPoS) ValidateBlockFooter(blk *block.Block) error {
164164
height := blk.Height()
165-
prevHash := blk.PrevHash()
166-
fork, err := r.ctx.Chain().Fork(prevHash)
167-
if err != nil {
168-
return errors.Wrapf(err, "failed to get fork at height %d with prevHash %x", height, prevHash)
169-
}
170-
roundCalc := r.ctx.RoundCalculator().Fork(fork)
165+
roundCalc := r.ctx.RoundCalculator().Fork(r.ctx.Chain())
171166
round, err := roundCalc.NewRound(height, r.ctx.BlockInterval(height), blk.Timestamp(), nil)
172167
if err != nil {
173168
return err

consensus/scheme/rolldpos/rolldpos_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,8 @@ func TestValidateBlockFooter(t *testing.T) {
201201
bc.EXPECT().BlockFooterByHeight(blockHeight).Return(footer, nil).AnyTimes()
202202
bc.EXPECT().ChainID().Return(uint32(1)).AnyTimes()
203203
bc.EXPECT().TipHeight().Return(blockHeight).AnyTimes()
204-
bc.EXPECT().BlockHeaderByHeight(blockHeight).Return(&block.Header{}, nil).Times(6)
205-
bc.EXPECT().TipHash().Return(hash.ZeroHash256).Times(1)
204+
bc.EXPECT().BlockHeaderByHeight(blockHeight).Return(&block.Header{}, nil).AnyTimes()
205+
bc.EXPECT().TipHash().Return(hash.ZeroHash256).AnyTimes()
206206
sk1 := identityset.PrivateKey(1)
207207
g := genesis.TestDefault()
208208
g.NumDelegates = 4

e2etest/local_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,8 +559,8 @@ func TestStartExistingBlockchain(t *testing.T) {
559559

560560
func newTestConfig() (config.Config, error) {
561561
cfg := config.Default
562-
cfg.Genesis = genesis.TestDefault()
563562
cfg = deepcopy.Copy(cfg).(config.Config)
563+
cfg.Genesis = genesis.TestDefault()
564564
cfg.Chain.TrieDBPath = _triePath
565565
cfg.Chain.ChainDBPath = _dBPath
566566
cfg.Chain.BlobStoreDBPath = _blobPath

state/factory/factory.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ type (
8888
PutBlock(context.Context, *block.Block) error
8989
WorkingSet(context.Context) (protocol.StateManager, error)
9090
WorkingSetAtHeight(context.Context, uint64, ...*action.SealedEnvelope) (protocol.StateManager, error)
91-
StateReaderAt(header *block.Header) (protocol.StateReader, error)
91+
StateReaderAt(hash.Hash256) (protocol.StateReader, error)
9292
}
9393

9494
// factory implements StateFactory interface, tracks changes to account/contract and batch-commits to DB
@@ -548,7 +548,7 @@ func (sf *factory) ReadView(name string) (interface{}, error) {
548548
}
549549

550550
// StateReaderAt returns a state reader at a specific height
551-
func (sf *factory) StateReaderAt(header *block.Header) (protocol.StateReader, error) {
551+
func (sf *factory) StateReaderAt(hash.Hash256) (protocol.StateReader, error) {
552552
panic("implement me")
553553
}
554554

0 commit comments

Comments
 (0)