Skip to content

Commit 1a368e2

Browse files
authored
fix(lib/blocktree): reimplement BestBlockHash to take into account primary blocks in fork choice rule (#2254)
1 parent 6c122b2 commit 1a368e2

22 files changed

+421
-187
lines changed

dot/core/service_integration_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ func TestHandleChainReorg_WithReorg_NoTransactions(t *testing.T) {
279279
height := 5
280280
branch := 3
281281
branches := map[int]int{branch: 1}
282-
state.AddBlocksToStateWithFixedBranches(t, s.blockState.(*state.BlockState), height, branches, 0)
282+
state.AddBlocksToStateWithFixedBranches(t, s.blockState.(*state.BlockState), height, branches)
283283

284284
leaves := s.blockState.(*state.BlockState).Leaves()
285285
require.Equal(t, 2, len(leaves))

dot/rpc/modules/chain_integration_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -387,9 +387,15 @@ func newTestStateService(t *testing.T) *state.Service {
387387
}
388388

389389
func loadTestBlocks(t *testing.T, gh common.Hash, bs *state.BlockState, rt runtime.Instance) {
390+
digest := types.NewDigest()
391+
prd, err := types.NewBabeSecondaryPlainPreDigest(0, 1).ToPreRuntimeDigest()
392+
require.NoError(t, err)
393+
err = digest.Add(*prd)
394+
require.NoError(t, err)
395+
390396
header1 := &types.Header{
391397
Number: big.NewInt(1),
392-
Digest: types.NewDigest(),
398+
Digest: digest,
393399
ParentHash: gh,
394400
StateRoot: trie.EmptyHash,
395401
}
@@ -399,16 +405,10 @@ func loadTestBlocks(t *testing.T, gh common.Hash, bs *state.BlockState, rt runti
399405
Body: sampleBodyBytes,
400406
}
401407

402-
err := bs.AddBlock(block1)
408+
err = bs.AddBlock(block1)
403409
require.NoError(t, err)
404410
bs.StoreRuntime(header1.Hash(), rt)
405411

406-
digest := types.NewDigest()
407-
prd, err := types.NewBabeSecondaryPlainPreDigest(0, 1).ToPreRuntimeDigest()
408-
require.NoError(t, err)
409-
err = digest.Add(*prd)
410-
require.NoError(t, err)
411-
412412
header2 := &types.Header{
413413
Number: big.NewInt(2),
414414
Digest: digest,

dot/rpc/modules/childstate_integration_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,11 +266,18 @@ func setupChildStateStorage(t *testing.T) (*ChildStateModule, common.Hash) {
266266
err = st.Storage.StoreTrie(tr, nil)
267267
require.NoError(t, err)
268268

269+
digest := types.NewDigest()
270+
prd, err := types.NewBabeSecondaryPlainPreDigest(0, 1).ToPreRuntimeDigest()
271+
require.NoError(t, err)
272+
err = digest.Add(*prd)
273+
require.NoError(t, err)
274+
269275
b := &types.Block{
270276
Header: types.Header{
271277
ParentHash: bb.Header.Hash(),
272278
Number: big.NewInt(0).Add(big.NewInt(1), bb.Header.Number),
273279
StateRoot: stateRoot,
280+
Digest: digest,
274281
},
275282
Body: types.Body{},
276283
}

dot/rpc/modules/state_integration_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,11 +530,18 @@ func setupStateModule(t *testing.T) (*StateModule, *common.Hash, *common.Hash) {
530530
err = chain.Storage.StoreTrie(ts, nil)
531531
require.NoError(t, err)
532532

533+
digest := types.NewDigest()
534+
prd, err := types.NewBabeSecondaryPlainPreDigest(0, 1).ToPreRuntimeDigest()
535+
require.NoError(t, err)
536+
err = digest.Add(*prd)
537+
require.NoError(t, err)
538+
533539
b := &types.Block{
534540
Header: types.Header{
535541
ParentHash: chain.Block.BestBlockHash(),
536542
Number: big.NewInt(3),
537543
StateRoot: sr1,
544+
Digest: digest,
538545
},
539546
Body: *types.NewBody([]types.Extrinsic{[]byte{}}),
540547
}

dot/rpc/modules/system_integration_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,11 +319,19 @@ func setupSystemModule(t *testing.T) *SystemModule {
319319

320320
err = chain.Storage.StoreTrie(ts, nil)
321321
require.NoError(t, err)
322+
323+
digest := types.NewDigest()
324+
prd, err := types.NewBabeSecondaryPlainPreDigest(0, 1).ToPreRuntimeDigest()
325+
require.NoError(t, err)
326+
err = digest.Add(*prd)
327+
require.NoError(t, err)
328+
322329
err = chain.Block.AddBlock(&types.Block{
323330
Header: types.Header{
324331
Number: big.NewInt(3),
325332
ParentHash: chain.Block.BestBlockHash(),
326333
StateRoot: ts.MustRoot(),
334+
Digest: digest,
327335
},
328336
Body: types.Body{},
329337
})

dot/state/block.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ func (bs *BlockState) BestBlockHash() common.Hash {
483483
return common.Hash{}
484484
}
485485

486-
return bs.bt.DeepestBlockHash()
486+
return bs.bt.BestBlockHash()
487487
}
488488

489489
// BestBlockHeader returns the block header of the current head of the chain

dot/state/block_test.go

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ func TestGetBlockByNumber(t *testing.T) {
8080
blockHeader := &types.Header{
8181
ParentHash: testGenesisHeader.Hash(),
8282
Number: big.NewInt(1),
83-
Digest: types.NewDigest(),
83+
Digest: createPrimaryBABEDigest(t),
8484
}
8585

8686
block := &types.Block{
@@ -102,7 +102,7 @@ func TestAddBlock(t *testing.T) {
102102
// Create header
103103
header0 := &types.Header{
104104
Number: big.NewInt(1),
105-
Digest: types.NewDigest(),
105+
Digest: createPrimaryBABEDigest(t),
106106
ParentHash: testGenesisHeader.Hash(),
107107
}
108108
// Create blockHash
@@ -119,7 +119,7 @@ func TestAddBlock(t *testing.T) {
119119
// Create header & blockData for block 2
120120
header1 := &types.Header{
121121
Number: big.NewInt(2),
122-
Digest: types.NewDigest(),
122+
Digest: createPrimaryBABEDigest(t),
123123
ParentHash: blockHash0,
124124
}
125125
blockHash1 := header1.Hash()
@@ -244,6 +244,7 @@ func TestAddBlock_BlockNumberToHash(t *testing.T) {
244244
Header: types.Header{
245245
ParentHash: bestHash,
246246
Number: big.NewInt(0).Add(bestHeader.Number, big.NewInt(1)),
247+
Digest: createPrimaryBABEDigest(t),
247248
},
248249
Body: types.Body{},
249250
}
@@ -324,7 +325,7 @@ func TestGetHashByNumber(t *testing.T) {
324325

325326
header := &types.Header{
326327
Number: big.NewInt(1),
327-
Digest: types.NewDigest(),
328+
Digest: createPrimaryBABEDigest(t),
328329
ParentHash: testGenesisHeader.Hash(),
329330
}
330331

@@ -347,7 +348,7 @@ func TestAddBlock_WithReOrg(t *testing.T) {
347348

348349
header1a := &types.Header{
349350
Number: big.NewInt(1),
350-
Digest: types.NewDigest(),
351+
Digest: createPrimaryBABEDigest(t),
351352
ParentHash: testGenesisHeader.Hash(),
352353
}
353354

@@ -366,7 +367,7 @@ func TestAddBlock_WithReOrg(t *testing.T) {
366367

367368
header1b := &types.Header{
368369
Number: big.NewInt(1),
369-
Digest: types.NewDigest(),
370+
Digest: createPrimaryBABEDigest(t),
370371
ParentHash: testGenesisHeader.Hash(),
371372
ExtrinsicsRoot: common.Hash{99},
372373
}
@@ -386,7 +387,7 @@ func TestAddBlock_WithReOrg(t *testing.T) {
386387

387388
header2b := &types.Header{
388389
Number: big.NewInt(2),
389-
Digest: types.NewDigest(),
390+
Digest: createPrimaryBABEDigest(t),
390391
ParentHash: header1b.Hash(),
391392
ExtrinsicsRoot: common.Hash{99},
392393
}
@@ -410,7 +411,7 @@ func TestAddBlock_WithReOrg(t *testing.T) {
410411

411412
header2a := &types.Header{
412413
Number: big.NewInt(2),
413-
Digest: types.NewDigest(),
414+
Digest: createPrimaryBABEDigest(t),
414415
ParentHash: header1a.Hash(),
415416
}
416417

@@ -424,7 +425,7 @@ func TestAddBlock_WithReOrg(t *testing.T) {
424425

425426
header3a := &types.Header{
426427
Number: big.NewInt(3),
427-
Digest: types.NewDigest(),
428+
Digest: createPrimaryBABEDigest(t),
428429
ParentHash: header2a.Hash(),
429430
}
430431

@@ -456,7 +457,7 @@ func TestAddBlockToBlockTree(t *testing.T) {
456457

457458
header := &types.Header{
458459
Number: big.NewInt(1),
459-
Digest: types.NewDigest(),
460+
Digest: createPrimaryBABEDigest(t),
460461
ParentHash: testGenesisHeader.Hash(),
461462
}
462463

dot/state/storage_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ func TestStorage_GetStorageByBlockHash(t *testing.T) {
7272
ParentHash: testGenesisHeader.Hash(),
7373
Number: big.NewInt(1),
7474
StateRoot: root,
75+
Digest: createPrimaryBABEDigest(t),
7576
},
7677
Body: *body,
7778
}

dot/state/test_helpers.go

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
runtime "github.com/ChainSafe/gossamer/lib/runtime/storage"
1717
"github.com/ChainSafe/gossamer/lib/trie"
1818
"github.com/ChainSafe/gossamer/lib/utils"
19+
"github.com/ChainSafe/gossamer/pkg/scale"
1920

2021
"github.com/stretchr/testify/require"
2122
)
@@ -35,6 +36,23 @@ func NewInMemoryDB(t *testing.T) chaindb.Database {
3536
return db
3637
}
3738

39+
func createPrimaryBABEDigest(t *testing.T) scale.VaryingDataTypeSlice {
40+
babeDigest := types.NewBabeDigest()
41+
err := babeDigest.Set(types.BabePrimaryPreDigest{AuthorityIndex: 0})
42+
require.NoError(t, err)
43+
44+
bdEnc, err := scale.Marshal(babeDigest)
45+
require.NoError(t, err)
46+
47+
digest := types.NewDigest()
48+
err = digest.Add(types.PreRuntimeDigest{
49+
ConsensusEngineID: types.BabeEngineID,
50+
Data: bdEnc,
51+
})
52+
require.NoError(t, err)
53+
return digest
54+
}
55+
3856
// branch tree randomly
3957
type testBranch struct {
4058
hash common.Hash
@@ -134,7 +152,7 @@ func AddBlocksToState(t *testing.T, blockState *BlockState, depth int,
134152

135153
// AddBlocksToStateWithFixedBranches adds blocks to a BlockState up to depth, with fixed branches
136154
// branches are provided with a map of depth -> # of branches
137-
func AddBlocksToStateWithFixedBranches(t *testing.T, blockState *BlockState, depth int, branches map[int]int, r byte) {
155+
func AddBlocksToStateWithFixedBranches(t *testing.T, blockState *BlockState, depth int, branches map[int]int) {
138156
previousHash := blockState.BestBlockHash()
139157
tb := []testBranch{}
140158
arrivalTime := time.Now()
@@ -190,10 +208,11 @@ func AddBlocksToStateWithFixedBranches(t *testing.T, blockState *BlockState, dep
190208
previousHash = branch.hash
191209

192210
for i := branch.depth; i < depth; i++ {
211+
d, err := types.NewBabePrimaryPreDigest(0, uint64(i+j+99), [32]byte{}, [64]byte{}).ToPreRuntimeDigest()
212+
require.NoError(t, err)
213+
require.NotNil(t, d)
193214
digest := types.NewDigest()
194-
_ = digest.Add(types.PreRuntimeDigest{
195-
Data: []byte{byte(i), byte(j), r},
196-
})
215+
_ = digest.Add(*d)
197216

198217
block := &types.Block{
199218
Header: types.Header{
@@ -206,7 +225,7 @@ func AddBlocksToStateWithFixedBranches(t *testing.T, blockState *BlockState, dep
206225
}
207226

208227
hash := block.Header.Hash()
209-
err := blockState.AddBlockWithArrivalTime(block, arrivalTime)
228+
err = blockState.AddBlockWithArrivalTime(block, arrivalTime)
210229
require.Nil(t, err)
211230

212231
blockState.StoreRuntime(hash, rt)
@@ -244,6 +263,7 @@ func generateBlockWithRandomTrie(t *testing.T, serv *Service,
244263
ParentHash: *parent,
245264
Number: big.NewInt(bNum),
246265
StateRoot: trieStateRoot,
266+
Digest: createPrimaryBABEDigest(t),
247267
},
248268
Body: *body,
249269
}

dot/sync/chain_processor_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ func TestChainProcessor_HandleJustification(t *testing.T) {
207207
d, err := types.NewBabeSecondaryPlainPreDigest(0, 1).ToPreRuntimeDigest()
208208
require.NoError(t, err)
209209
digest := types.NewDigest()
210-
err = digest.Add(d)
210+
err = digest.Add(*d)
211211
require.NoError(t, err)
212212

213213
header := &types.Header{

dot/sync/message_test.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,19 @@ func addTestBlocksToState(t *testing.T, depth int, blockState BlockState) {
2121
previousNum, err := blockState.BestBlockNumber()
2222
require.Nil(t, err)
2323

24+
digest := types.NewDigest()
25+
prd, err := types.NewBabeSecondaryPlainPreDigest(0, 1).ToPreRuntimeDigest()
26+
require.NoError(t, err)
27+
err = digest.Add(*prd)
28+
require.NoError(t, err)
29+
2430
for i := 1; i <= depth; i++ {
2531
block := &types.Block{
2632
Header: types.Header{
2733
ParentHash: previousHash,
2834
Number: big.NewInt(int64(i)).Add(previousNum, big.NewInt(int64(i))),
2935
StateRoot: trie.EmptyHash,
30-
Digest: types.NewDigest(),
36+
Digest: digest,
3137
},
3238
Body: types.Body{},
3339
}
@@ -362,7 +368,7 @@ func TestService_checkOrGetDescendantHash(t *testing.T) {
362368
branches := map[int]int{
363369
8: 1,
364370
}
365-
state.AddBlocksToStateWithFixedBranches(t, s.blockState.(*state.BlockState), 16, branches, 1)
371+
state.AddBlocksToStateWithFixedBranches(t, s.blockState.(*state.BlockState), 16, branches)
366372

367373
// base case
368374
ancestor, err := s.blockState.GetHashByNumber(big.NewInt(1))

dot/types/babe.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,31 @@ func GetSlotFromHeader(header *Header) (uint64, error) {
114114

115115
return slotNumber, nil
116116
}
117+
118+
// IsPrimary returns true if the block was authored in a primary slot, false otherwise.
119+
func IsPrimary(header *Header) (bool, error) {
120+
if header == nil {
121+
return false, fmt.Errorf("cannot have nil header")
122+
}
123+
124+
if len(header.Digest.Types) == 0 {
125+
return false, fmt.Errorf("chain head missing digest")
126+
}
127+
128+
preDigest, ok := header.Digest.Types[0].Value().(PreRuntimeDigest)
129+
if !ok {
130+
return false, fmt.Errorf("first digest item is not pre-digest: type=%T", header.Digest.Types[0].Value())
131+
}
132+
133+
digest, err := DecodeBabePreDigest(preDigest.Data)
134+
if err != nil {
135+
return false, fmt.Errorf("cannot decode BabePreDigest from pre-digest: %s", err)
136+
}
137+
138+
switch digest.(type) {
139+
case BabePrimaryPreDigest:
140+
return true, nil
141+
default:
142+
return false, nil
143+
}
144+
}

0 commit comments

Comments
 (0)