From 992f5da3ea1fa6fd887be53e79858d2cfbfc50bf Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Thu, 28 Jul 2022 20:37:40 +0530 Subject: [PATCH 01/40] Is it block producer equivocation if different parents --- lib/babe/verify.go | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/babe/verify.go b/lib/babe/verify.go index 8957dd9995..ac5b8f40ae 100644 --- a/lib/babe/verify.go +++ b/lib/babe/verify.go @@ -372,6 +372,7 @@ func (b *verifier) verifyAuthorshipRight(header *types.Header) error { // same authority won't produce two different blocks at the same block number as primary block producer if currentBlockProducerIndex == existingBlockProducerIndex && !currentHash.Equal(header.Hash()) && + currentHeader.ParentHash.Equal(header.ParentHash) && isCurrentBlockProducerPrimary == isExistingBlockProducerPrimary { return ErrProducerEquivocated } From 89088bf000e6fcaaae6587913b349be1c04a06c6 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Fri, 12 Aug 2022 19:17:32 +0530 Subject: [PATCH 02/40] re-wrote block equivocation logic --- dot/state/block.go | 27 +++++++++++++ lib/babe/state.go | 1 + lib/babe/verify.go | 78 ++++++++++++++++++-------------------- lib/blocktree/blocktree.go | 12 ++++++ 4 files changed, 77 insertions(+), 41 deletions(-) diff --git a/dot/state/block.go b/dot/state/block.go index e0409ae971..cb15fdcb3f 100644 --- a/dot/state/block.go +++ b/dot/state/block.go @@ -250,6 +250,33 @@ func (bs *BlockState) GetHashByNumber(num uint) (common.Hash, error) { return common.NewHash(bh), nil } +func (bs *BlockState) GetBlocksBySlot(slotNum uint64) ([]common.Hash, error) { + highestFinalisedHash, err := bs.GetHighestFinalisedHash() + if err != nil { + return nil, err + } + + descendants, err := bs.bt.GetAllDescendants(highestFinalisedHash) + if err != nil { + return nil, err + } + + blocksWithGivenSlot := []common.Hash{} + + for _, desc := range descendants { + descSlot, err := bs.GetSlotForBlock(desc) + if err != nil { + return blocksWithGivenSlot, fmt.Errorf("could not get slot for block %s: %w", desc, err) + } + + if descSlot == slotNum { + blocksWithGivenSlot = append(blocksWithGivenSlot, desc) + } + } + + return blocksWithGivenSlot, nil +} + // GetHeaderByNumber returns the block header on our best chain with the given number func (bs *BlockState) GetHeaderByNumber(num uint) (*types.Header, error) { hash, err := bs.GetHashByNumber(num) diff --git a/lib/babe/state.go b/lib/babe/state.go index 897f06bd35..fcabc15146 100644 --- a/lib/babe/state.go +++ b/lib/babe/state.go @@ -28,6 +28,7 @@ type BlockState interface { GetHeader(common.Hash) (*types.Header, error) GetBlockByNumber(blockNumber uint) (*types.Block, error) GetBlockByHash(common.Hash) (*types.Block, error) + GetBlocksBySlot(uint64) ([]common.Hash, error) GetArrivalTime(common.Hash) (time.Time, error) GenesisHash() common.Hash GetSlotForBlock(common.Hash) (uint64, error) diff --git a/lib/babe/verify.go b/lib/babe/verify.go index ac5b8f40ae..b5ad59adad 100644 --- a/lib/babe/verify.go +++ b/lib/babe/verify.go @@ -325,60 +325,56 @@ func (b *verifier) verifyAuthorshipRight(header *types.Header) error { return ErrBadSignature } - // check if the producer has equivocated, ie. have they produced a conflicting block? - // hashes is hashes of all blocks with same block number as header.Number - hashes := b.blockState.GetAllBlocksAtDepth(header.ParentHash) + equivocated, err := b.verifyBlockEquivocation(header) + if err != nil { + return fmt.Errorf("could not verify block equivocation for header %s: %w", header.Hash(), err) + } + if equivocated { + return ErrProducerEquivocated + } - for _, currentHash := range hashes { - currentHeader, err := b.blockState.GetHeader(currentHash) - if err != nil { - return fmt.Errorf("failed get header %s", err) - } + return nil +} - currentBlockProducerIndex, err := getAuthorityIndex(currentHeader) - if err != nil { - return fmt.Errorf("failed to get authority index %s", err) - } +// verifyBlockEquivocation checks if given block's author has occupied corresponding slot more than once. +func (b *verifier) verifyBlockEquivocation(header *types.Header) (bool, error) { + author, err := getAuthorityIndex(header) + if err != nil { + return false, err + } + currentHash := header.Hash() + slot, err := b.blockState.GetSlotForBlock(currentHash) + if err != nil { + return false, err + } - if len(currentHeader.Digest.Types) == 0 { - return fmt.Errorf("current header missing digest") - } + blocksBySlot, err := b.blockState.GetBlocksBySlot(slot) + if err != nil { + return false, err + } - currentPreDigestItem := currentHeader.Digest.Types[0] - currentPreDigest, ok := currentPreDigestItem.Value().(types.PreRuntimeDigest) - if !ok { - return fmt.Errorf("%w: got %T", types.ErrNoFirstPreDigest, currentPreDigestItem.Value()) + for _, blockBySlot := range blocksBySlot { + if blockBySlot.Equal(currentHash) { + continue } - currentBabePreDigest, err := b.verifyPreRuntimeDigest(¤tPreDigest) + existingHeader, err := b.blockState.GetHeader(blockBySlot) if err != nil { - return fmt.Errorf("failed to verify pre-runtime digest: %w", err) + return false, err } - _, isCurrentBlockProducerPrimary := currentBabePreDigest.(types.BabePrimaryPreDigest) - - var isExistingBlockProducerPrimary bool - var existingBlockProducerIndex uint32 - switch d := babePreDigest.(type) { - case types.BabePrimaryPreDigest: - existingBlockProducerIndex = d.AuthorityIndex - isExistingBlockProducerPrimary = true - case types.BabeSecondaryVRFPreDigest: - existingBlockProducerIndex = d.AuthorityIndex - case types.BabeSecondaryPlainPreDigest: - existingBlockProducerIndex = d.AuthorityIndex + authorOfExistingHeader, err := getAuthorityIndex(existingHeader) + if err != nil { + return false, err } - - // same authority won't produce two different blocks at the same block number as primary block producer - if currentBlockProducerIndex == existingBlockProducerIndex && - !currentHash.Equal(header.Hash()) && - currentHeader.ParentHash.Equal(header.ParentHash) && - isCurrentBlockProducerPrimary == isExistingBlockProducerPrimary { - return ErrProducerEquivocated + if authorOfExistingHeader != author { + continue } + + return false, nil } - return nil + return true, nil } func (b *verifier) verifyPreRuntimeDigest(digest *types.PreRuntimeDigest) (scale.VaryingDataTypeValue, error) { diff --git a/lib/blocktree/blocktree.go b/lib/blocktree/blocktree.go index c5625c6231..853dbca4a3 100644 --- a/lib/blocktree/blocktree.go +++ b/lib/blocktree/blocktree.go @@ -330,6 +330,18 @@ func (bt *BlockTree) GetAllBlocks() []Hash { return bt.root.getAllDescendants(nil) } +func (bt *BlockTree) GetAllDescendants(a common.Hash) ([]Hash, error) { + bt.RLock() + defer bt.RUnlock() + + an := bt.getNode(a) + if an == nil { + return []common.Hash{}, ErrNodeNotFound + } + + return an.getAllDescendants(nil), nil +} + // GetHashByNumber returns the block hash with the given number that is on the best chain. // If the number is lower or higher than the numbers in the blocktree, an error is returned. func (bt *BlockTree) GetHashByNumber(num uint) (common.Hash, error) { From 10aa5b77db85d643ccf3be890f504cc7b9093e10 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Tue, 16 Aug 2022 18:31:07 +0530 Subject: [PATCH 03/40] implement GetBlocksBySlot to mock block state --- dot/state/block.go | 1 + lib/babe/mock_state_test.go | 15 +++++++++++++++ lib/blocktree/blocktree.go | 1 + 3 files changed, 17 insertions(+) diff --git a/dot/state/block.go b/dot/state/block.go index cb15fdcb3f..77eec8c359 100644 --- a/dot/state/block.go +++ b/dot/state/block.go @@ -250,6 +250,7 @@ func (bs *BlockState) GetHashByNumber(num uint) (common.Hash, error) { return common.NewHash(bh), nil } +// GetBlocksBySlot gets all blocks that were produced in given slot. func (bs *BlockState) GetBlocksBySlot(slotNum uint64) ([]common.Hash, error) { highestFinalisedHash, err := bs.GetHighestFinalisedHash() if err != nil { diff --git a/lib/babe/mock_state_test.go b/lib/babe/mock_state_test.go index 38815094a9..aa1d288905 100644 --- a/lib/babe/mock_state_test.go +++ b/lib/babe/mock_state_test.go @@ -197,6 +197,21 @@ func (mr *MockBlockStateMockRecorder) GetBlockByNumber(arg0 interface{}) *gomock return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockByNumber", reflect.TypeOf((*MockBlockState)(nil).GetBlockByNumber), arg0) } +// GetBlocksBySlot mocks base method. +func (m *MockBlockState) GetBlocksBySlot(arg0 uint64) ([]common.Hash, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetBlocksBySlot", arg0) + ret0, _ := ret[0].([]common.Hash) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetBlocksBySlot indicates an expected call of GetBlocksBySlot. +func (mr *MockBlockStateMockRecorder) GetBlocksBySlot(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlocksBySlot", reflect.TypeOf((*MockBlockState)(nil).GetBlocksBySlot), arg0) +} + // GetFinalisedHeader mocks base method. func (m *MockBlockState) GetFinalisedHeader(arg0, arg1 uint64) (*types.Header, error) { m.ctrl.T.Helper() diff --git a/lib/blocktree/blocktree.go b/lib/blocktree/blocktree.go index 853dbca4a3..ee62f4db33 100644 --- a/lib/blocktree/blocktree.go +++ b/lib/blocktree/blocktree.go @@ -330,6 +330,7 @@ func (bt *BlockTree) GetAllBlocks() []Hash { return bt.root.getAllDescendants(nil) } +// GetAllDescendants returns all blocks that are descendants of the given block. func (bt *BlockTree) GetAllDescendants(a common.Hash) ([]Hash, error) { bt.RLock() defer bt.RUnlock() From 626ce7b7c7ce36b1f15f5be582c4aaf07d0fedab Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Tue, 16 Aug 2022 20:32:30 +0530 Subject: [PATCH 04/40] wrapping some errors --- dot/state/block.go | 4 ++-- lib/babe/verify.go | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/dot/state/block.go b/dot/state/block.go index 77eec8c359..1693921c9f 100644 --- a/dot/state/block.go +++ b/dot/state/block.go @@ -254,12 +254,12 @@ func (bs *BlockState) GetHashByNumber(num uint) (common.Hash, error) { func (bs *BlockState) GetBlocksBySlot(slotNum uint64) ([]common.Hash, error) { highestFinalisedHash, err := bs.GetHighestFinalisedHash() if err != nil { - return nil, err + return nil, fmt.Errorf("failed to get highest finalised hash: %w", err) } descendants, err := bs.bt.GetAllDescendants(highestFinalisedHash) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to get descendants of %s: %w", highestFinalisedHash, err) } blocksWithGivenSlot := []common.Hash{} diff --git a/lib/babe/verify.go b/lib/babe/verify.go index b5ad59adad..eba5c22382 100644 --- a/lib/babe/verify.go +++ b/lib/babe/verify.go @@ -340,32 +340,32 @@ func (b *verifier) verifyAuthorshipRight(header *types.Header) error { func (b *verifier) verifyBlockEquivocation(header *types.Header) (bool, error) { author, err := getAuthorityIndex(header) if err != nil { - return false, err + return false, fmt.Errorf("failed to get authority index for %s: %w", header.Hash(), err) } currentHash := header.Hash() slot, err := b.blockState.GetSlotForBlock(currentHash) if err != nil { - return false, err + return false, fmt.Errorf("failed to get slot for block %s: %w", currentHash, err) } - blocksBySlot, err := b.blockState.GetBlocksBySlot(slot) + blocksInSlot, err := b.blockState.GetBlocksBySlot(slot) if err != nil { - return false, err + return false, fmt.Errorf("failed to get blocks produced in slot %d: %w", slot, err) } - for _, blockBySlot := range blocksBySlot { - if blockBySlot.Equal(currentHash) { + for _, blockInSlot := range blocksInSlot { + if blockInSlot.Equal(currentHash) { continue } - existingHeader, err := b.blockState.GetHeader(blockBySlot) + existingHeader, err := b.blockState.GetHeader(blockInSlot) if err != nil { - return false, err + return false, fmt.Errorf("failed to get header for block %s: %w", blockInSlot, err) } authorOfExistingHeader, err := getAuthorityIndex(existingHeader) if err != nil { - return false, err + return false, fmt.Errorf("failed to get authority index for block %s: %w", blockInSlot, err) } if authorOfExistingHeader != author { continue From 6cf664ceaff50d01b0bf3429ecae0fcc382b67c7 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Fri, 9 Sep 2022 20:29:28 +0530 Subject: [PATCH 05/40] temp --- lib/babe/verify_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/babe/verify_test.go b/lib/babe/verify_test.go index 3d9c229f86..da6956404b 100644 --- a/lib/babe/verify_test.go +++ b/lib/babe/verify_test.go @@ -540,6 +540,7 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { mockBlockState.EXPECT().GetAllBlocksAtDepth(gomock.Any()).Return(h1) mockBlockState.EXPECT().GetHeader(h).Return(types.NewEmptyHeader(), nil) + mockBlockState.EXPECT().GetSlotForBlock(gomock.AssignableToTypeOf(common.Hash{})).Return(uint64(1), nil) mockBlockStateErr.EXPECT().GetAllBlocksAtDepth(gomock.Any()).Return(h1) mockBlockStateErr.EXPECT().GetHeader(h).Return(nil, errors.New("get header error")) From f248663085c4a8d7f121c571e802f94d51dd47fa Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Thu, 13 Oct 2022 22:55:08 +0530 Subject: [PATCH 06/40] fix tests --- dot/state/block.go | 3 ++ dot/types/babe.go | 5 +++ lib/babe/epoch_test.go | 1 + lib/babe/errors.go | 1 + lib/babe/verify.go | 10 +++--- lib/babe/verify_test.go | 77 +++++++++++++++++++++++++++-------------- 6 files changed, 67 insertions(+), 30 deletions(-) diff --git a/dot/state/block.go b/dot/state/block.go index 96f0aabd33..4c0f482078 100644 --- a/dot/state/block.go +++ b/dot/state/block.go @@ -266,6 +266,9 @@ func (bs *BlockState) GetBlocksBySlot(slotNum uint64) ([]common.Hash, error) { for _, desc := range descendants { descSlot, err := bs.GetSlotForBlock(desc) + if errors.Is(err, types.ErrGenesisHeader) { + continue + } if err != nil { return blocksWithGivenSlot, fmt.Errorf("could not get slot for block %s: %w", desc, err) } diff --git a/dot/types/babe.go b/dot/types/babe.go index f1dc529af9..b3dc69e009 100644 --- a/dot/types/babe.go +++ b/dot/types/babe.go @@ -28,6 +28,7 @@ const ( var ( ErrChainHeadMissingDigest = errors.New("chain head missing digest") + ErrGenesisHeader = errors.New("genesis header doesn't have a slot") ) // BabeConfiguration contains the genesis data for BABE @@ -108,6 +109,10 @@ type ConfigData struct { // GetSlotFromHeader returns the BABE slot from the given header func GetSlotFromHeader(header *Header) (uint64, error) { + if header.Number == 0 { + return 0, ErrGenesisHeader + } + if len(header.Digest.Types) == 0 { return 0, ErrChainHeadMissingDigest } diff --git a/lib/babe/epoch_test.go b/lib/babe/epoch_test.go index 1580dea7eb..a38725695e 100644 --- a/lib/babe/epoch_test.go +++ b/lib/babe/epoch_test.go @@ -33,6 +33,7 @@ func TestBabeService_checkAndSetFirstSlot(t *testing.T) { encDigest := newEncodedBabeDigest(t, testBabeSecondaryPlainPreDigest) header := newTestHeader(t, *types.NewBABEPreRuntimeDigest(encDigest)) + header.Number = 1 block := &types.Block{ Header: *header, } diff --git a/lib/babe/errors.go b/lib/babe/errors.go index 1017bed595..e5d3e11dfb 100644 --- a/lib/babe/errors.go +++ b/lib/babe/errors.go @@ -72,6 +72,7 @@ var ( errNoBABEAuthorityKeyProvided = errors.New("cannot create BABE service as authority; no keypair provided") errLastDigestItemNotSeal = errors.New("last digest item is not seal") errLaggingSlot = errors.New("current slot is smaller than slot of best block") + errNoDigest = errors.New("no digest provided") other Other invalidCustom InvalidCustom diff --git a/lib/babe/verify.go b/lib/babe/verify.go index 4d47bd02fc..a1a8037387 100644 --- a/lib/babe/verify.go +++ b/lib/babe/verify.go @@ -339,13 +339,15 @@ func (b *verifier) verifyAuthorshipRight(header *types.Header) error { } // verifyBlockEquivocation checks if given block's author has occupied corresponding slot more than once. +// It returns true if block was equivocated. func (b *verifier) verifyBlockEquivocation(header *types.Header) (bool, error) { author, err := getAuthorityIndex(header) if err != nil { return false, fmt.Errorf("failed to get authority index for %s: %w", header.Hash(), err) } + currentHash := header.Hash() - slot, err := b.blockState.GetSlotForBlock(currentHash) + slot, err := types.GetSlotFromHeader(header) if err != nil { return false, fmt.Errorf("failed to get slot for block %s: %w", currentHash, err) } @@ -373,10 +375,10 @@ func (b *verifier) verifyBlockEquivocation(header *types.Header) (bool, error) { continue } - return false, nil + return true, nil } - return true, nil + return false, nil } func (b *verifier) verifyPreRuntimeDigest(digest *types.PreRuntimeDigest) (scale.VaryingDataTypeValue, error) { @@ -487,7 +489,7 @@ func (b *verifier) verifyPrimarySlotWinner(authorityIndex uint32, func getAuthorityIndex(header *types.Header) (uint32, error) { if len(header.Digest.Types) == 0 { - return 0, fmt.Errorf("no digest provided") + return 0, errNoDigest } digestValue, err := header.Digest.Types[0].Value() diff --git a/lib/babe/verify_test.go b/lib/babe/verify_test.go index 880c98352a..d2d289869b 100644 --- a/lib/babe/verify_test.go +++ b/lib/babe/verify_test.go @@ -499,57 +499,60 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { assert.NoError(t, err) testHeaderPrimary := types.NewEmptyHeader() testHeaderPrimary.Digest = testDigestPrimary - + testHeaderPrimary.Number = 1 // Secondary Plain Test Header testParentPrd, err := testBabeSecondaryPlainPreDigest.ToPreRuntimeDigest() assert.NoError(t, err) testParentHeader := newTestHeader(t, *testParentPrd) - + testParentHeader.Number = 1 testParentHash := encodeAndHashHeader(t, testParentHeader) testSecondaryPrd, err := testBabeSecondaryPlainPreDigest.ToPreRuntimeDigest() assert.NoError(t, err) testSecPlainHeader := newTestHeader(t, *testSecondaryPrd) testSecPlainHeader.ParentHash = testParentHash - + testSecPlainHeader.Number = 1 // Secondary Vrf Test Header encParentVrfDigest := newEncodedBabeDigest(t, testBabeSecondaryVRFPreDigest) testParentVrfHeader := newTestHeader(t, *types.NewBABEPreRuntimeDigest(encParentVrfDigest)) + testParentVrfHeader.Number = 1 testVrfParentHash := encodeAndHashHeader(t, testParentVrfHeader) encVrfHeader := newEncodedBabeDigest(t, testBabeSecondaryVRFPreDigest) testSecVrfHeader := newTestHeader(t, *types.NewBABEPreRuntimeDigest(encVrfHeader)) testSecVrfHeader.ParentHash = testVrfParentHash + testSecVrfHeader.Number = 1 h := common.MustHexToHash("0x01") h1 := []common.Hash{h} - mockBlockState.EXPECT().GetAllBlocksAtDepth(gomock.Any()).Return(h1) mockBlockState.EXPECT().GetHeader(h).Return(types.NewEmptyHeader(), nil) - mockBlockState.EXPECT().GetSlotForBlock(gomock.AssignableToTypeOf(common.Hash{})).Return(uint64(1), nil) + mockBlockState.EXPECT().GetBlocksBySlot(gomock.Any()).Return(h1, nil) - mockBlockStateErr.EXPECT().GetAllBlocksAtDepth(gomock.Any()).Return(h1) mockBlockStateErr.EXPECT().GetHeader(h).Return(nil, errors.New("get header error")) + mockBlockStateErr.EXPECT().GetBlocksBySlot(gomock.Any()).Return(h1, nil) // Case 0: First element not preruntime digest header0 := newTestHeader(t, testInvalidSeal, testInvalidSeal) - + header0.Number = 1 // Case 1: Last element not seal header1 := newTestHeader(t, testInvalidPreRuntimeDigest, testInvalidPreRuntimeDigest) + header1.Number = 1 // Case 2: Fail to verify preruntime digest header2 := newTestHeader(t, testInvalidPreRuntimeDigest, testInvalidSeal) - + header2.Number = 1 // Case 3: Invalid Seal Length babePrd, err := testBabePrimaryPreDigest.ToPreRuntimeDigest() assert.NoError(t, err) header3 := newTestHeader(t, *babePrd, testInvalidSeal) + header3.Number = 1 babeVerifier := newTestVerifier(kp, mockBlockState, scale.MaxUint128, false) // Case 4: Invalid signature - BabePrimaryPreDigest babePrd2, err := testBabePrimaryPreDigest.ToPreRuntimeDigest() assert.NoError(t, err) header4 := newTestHeader(t, *babePrd2) - + header4.Number = 1 signAndAddSeal(t, kp, header4, []byte{1}) babeVerifier2 := newTestVerifier(kp, mockBlockState, scale.MaxUint128, false) @@ -557,7 +560,7 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { babeSecPlainPrd, err := testBabeSecondaryPlainPreDigest.ToPreRuntimeDigest() assert.NoError(t, err) header5 := newTestHeader(t, *babeSecPlainPrd) - + header5.Number = 1 signAndAddSeal(t, kp, header5, []byte{1}) babeVerifier3 := newTestVerifier(kp, mockBlockState, scale.MaxUint128, true) @@ -565,7 +568,7 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { encSecVrfDigest := newEncodedBabeDigest(t, testBabeSecondaryVRFPreDigest) assert.NoError(t, err) header6 := newTestHeader(t, *types.NewBABEPreRuntimeDigest(encSecVrfDigest)) - + header6.Number = 1 signAndAddSeal(t, kp, header6, []byte{1}) babeVerifier4 := newTestVerifier(kp, mockBlockState, scale.MaxUint128, true) @@ -573,6 +576,7 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { babeParentPrd, err := testBabePrimaryPreDigest.ToPreRuntimeDigest() assert.NoError(t, err) babeParentHeader := newTestHeader(t, *babeParentPrd) + babeParentHeader.Number = 1 parentHash := encodeAndHashHeader(t, babeParentHeader) babePrd3, err := testBabePrimaryPreDigest.ToPreRuntimeDigest() @@ -580,6 +584,7 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { header7 := newTestHeader(t, *babePrd3) header7.ParentHash = parentHash + header7.Number = 1 hash := encodeAndHashHeader(t, header7) signAndAddSeal(t, kp, header7, hash[:]) @@ -646,13 +651,13 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { name: "valid digest items, getAuthorityIndex error", verifier: *babeVerifier5, header: header7, - expErr: errors.New("failed to get authority index no digest provided"), + expErr: errNoDigest, }, { name: "get header err", verifier: *babeVerifier6, header: header7, - expErr: errors.New("failed get header get header error"), + expErr: errors.New("failed to get header for block"), }, } for _, tt := range tests { @@ -660,7 +665,7 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { b := &tt.verifier err := b.verifyAuthorshipRight(tt.header) if tt.expErr != nil { - assert.EqualError(t, err, tt.expErr.Error()) + assert.ErrorContains(t, err, tt.expErr.Error()) } else { assert.NoError(t, err) } @@ -683,6 +688,22 @@ func Test_verifier_verifyAuthorshipRightEquivocatory(t *testing.T) { output, proof, err := kp.VrfSign(makeTranscript(Randomness{}, uint64(1), 1)) assert.NoError(t, err) + output2, proof2, err := kp.VrfSign(makeTranscript(Randomness{}, uint64(1), 2)) + assert.NoError(t, err) + secDigestExisting := types.BabePrimaryPreDigest{ + AuthorityIndex: 1, + SlotNumber: 1, + VRFOutput: output2, + VRFProof: proof2, + } + prdExisting, err := secDigestExisting.ToPreRuntimeDigest() + assert.NoError(t, err) + + headerExisting := newTestHeader(t, *prdExisting) + headerExisting.Number = 1 + hashExisting := encodeAndHashHeader(t, headerExisting) + signAndAddSeal(t, kp, headerExisting, hashExisting[:]) + testBabeSecondaryPlainPreDigest := types.BabeSecondaryPlainPreDigest{ AuthorityIndex: 1, SlotNumber: 1, @@ -694,11 +715,12 @@ func Test_verifier_verifyAuthorshipRightEquivocatory(t *testing.T) { VrfProof: proof, } - //BabePrimaryPreDigest case + // BabePrimaryPreDigest case secDigest1 := types.BabePrimaryPreDigest{ - SlotNumber: 1, - VRFOutput: output, - VRFProof: proof, + AuthorityIndex: 1, + SlotNumber: 1, + VRFOutput: output, + VRFProof: proof, } prd1, err := secDigest1.ToPreRuntimeDigest() assert.NoError(t, err) @@ -712,55 +734,58 @@ func Test_verifier_verifyAuthorshipRightEquivocatory(t *testing.T) { verifierEquivocatoryPrimary := newVerifier(mockBlockStateEquiv1, 1, vi) headerEquivocatoryPrimary := newTestHeader(t, *prd1) + headerEquivocatoryPrimary.Number = 1 hashEquivocatoryPrimary := encodeAndHashHeader(t, headerEquivocatoryPrimary) signAndAddSeal(t, kp, headerEquivocatoryPrimary, hashEquivocatoryPrimary[:]) - mockBlockStateEquiv1.EXPECT().GetAllBlocksAtDepth(headerEquivocatoryPrimary.ParentHash).Return( - []common.Hash{hashEquivocatoryPrimary}) mockBlockStateEquiv1.EXPECT().GetHeader(hashEquivocatoryPrimary).Return(headerEquivocatoryPrimary, nil) + mockBlockStateEquiv1.EXPECT().GetBlocksBySlot(gomock.Any()).Return([]common.Hash{hashEquivocatoryPrimary, hashExisting}, nil) // Secondary Plain Test Header testParentPrd, err := testBabeSecondaryPlainPreDigest.ToPreRuntimeDigest() assert.NoError(t, err) testParentHeader := newTestHeader(t, *testParentPrd) + testParentHeader.Number = 1 testParentHash := encodeAndHashHeader(t, testParentHeader) testSecondaryPrd, err := testBabeSecondaryPlainPreDigest.ToPreRuntimeDigest() assert.NoError(t, err) testSecPlainHeader := newTestHeader(t, *testSecondaryPrd) testSecPlainHeader.ParentHash = testParentHash + testSecPlainHeader.Number = 1 babeSecPlainPrd2, err := testBabeSecondaryPlainPreDigest.ToPreRuntimeDigest() assert.NoError(t, err) headerEquivocatorySecondaryPlain := newTestHeader(t, *babeSecPlainPrd2) + headerEquivocatorySecondaryPlain.Number = 1 hashEquivocatorySecondaryPlain := encodeAndHashHeader(t, headerEquivocatorySecondaryPlain) signAndAddSeal(t, kp, headerEquivocatorySecondaryPlain, hashEquivocatorySecondaryPlain[:]) babeVerifier8 := newTestVerifier(kp, mockBlockStateEquiv2, scale.MaxUint128, true) - mockBlockStateEquiv2.EXPECT().GetAllBlocksAtDepth(headerEquivocatorySecondaryPlain.ParentHash).Return( - []common.Hash{hashEquivocatorySecondaryPlain}) mockBlockStateEquiv2.EXPECT().GetHeader(hashEquivocatorySecondaryPlain).Return(headerEquivocatorySecondaryPlain, nil) + mockBlockStateEquiv2.EXPECT().GetBlocksBySlot(gomock.Any()).Return([]common.Hash{hashEquivocatorySecondaryPlain, hashExisting}, nil) // Secondary Vrf Test Header encParentVrfDigest := newEncodedBabeDigest(t, testBabeSecondaryVRFPreDigest) testParentVrfHeader := newTestHeader(t, *types.NewBABEPreRuntimeDigest(encParentVrfDigest)) + testParentVrfHeader.Number = 1 testVrfParentHash := encodeAndHashHeader(t, testParentVrfHeader) encVrfHeader := newEncodedBabeDigest(t, testBabeSecondaryVRFPreDigest) testSecVrfHeader := newTestHeader(t, *types.NewBABEPreRuntimeDigest(encVrfHeader)) testSecVrfHeader.ParentHash = testVrfParentHash - + testSecVrfHeader.Number = 1 encVrfDigest := newEncodedBabeDigest(t, testBabeSecondaryVRFPreDigest) assert.NoError(t, err) headerEquivocatorySecondaryVRF := newTestHeader(t, *types.NewBABEPreRuntimeDigest(encVrfDigest)) - + headerEquivocatorySecondaryVRF.Number = 1 hashEquivocatorySecondaryVRF := encodeAndHashHeader(t, headerEquivocatorySecondaryVRF) signAndAddSeal(t, kp, headerEquivocatorySecondaryVRF, hashEquivocatorySecondaryVRF[:]) babeVerifierEquivocatorySecondaryVRF := newTestVerifier(kp, mockBlockStateEquiv3, scale.MaxUint128, true) - mockBlockStateEquiv3.EXPECT().GetAllBlocksAtDepth(headerEquivocatorySecondaryVRF.ParentHash).Return( - []common.Hash{hashEquivocatorySecondaryVRF}) + mockBlockStateEquiv3.EXPECT().GetHeader(hashEquivocatorySecondaryVRF).Return(headerEquivocatorySecondaryVRF, nil) + mockBlockStateEquiv3.EXPECT().GetBlocksBySlot(gomock.Any()).Return([]common.Hash{hashEquivocatorySecondaryVRF, hashExisting}, nil) tests := []struct { name string From 5f204484dad2919566bb5743a2071d06c738309d Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Fri, 14 Oct 2022 12:10:10 +0530 Subject: [PATCH 07/40] more fixes --- lib/babe/epoch_test.go | 1 - lib/babe/verify_test.go | 35 +++++++++-------------------------- 2 files changed, 9 insertions(+), 27 deletions(-) diff --git a/lib/babe/epoch_test.go b/lib/babe/epoch_test.go index a38725695e..1580dea7eb 100644 --- a/lib/babe/epoch_test.go +++ b/lib/babe/epoch_test.go @@ -33,7 +33,6 @@ func TestBabeService_checkAndSetFirstSlot(t *testing.T) { encDigest := newEncodedBabeDigest(t, testBabeSecondaryPlainPreDigest) header := newTestHeader(t, *types.NewBABEPreRuntimeDigest(encDigest)) - header.Number = 1 block := &types.Block{ Header: *header, } diff --git a/lib/babe/verify_test.go b/lib/babe/verify_test.go index d2d289869b..b0f5d379f1 100644 --- a/lib/babe/verify_test.go +++ b/lib/babe/verify_test.go @@ -21,6 +21,7 @@ import ( func newTestHeader(t *testing.T, digest ...scale.VaryingDataTypeValue) *types.Header { t.Helper() header := types.NewEmptyHeader() + header.Number = 1 for _, d := range digest { err := header.Digest.Add(d) assert.NoError(t, err) @@ -499,28 +500,23 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { assert.NoError(t, err) testHeaderPrimary := types.NewEmptyHeader() testHeaderPrimary.Digest = testDigestPrimary - testHeaderPrimary.Number = 1 // Secondary Plain Test Header testParentPrd, err := testBabeSecondaryPlainPreDigest.ToPreRuntimeDigest() assert.NoError(t, err) testParentHeader := newTestHeader(t, *testParentPrd) - testParentHeader.Number = 1 testParentHash := encodeAndHashHeader(t, testParentHeader) testSecondaryPrd, err := testBabeSecondaryPlainPreDigest.ToPreRuntimeDigest() assert.NoError(t, err) testSecPlainHeader := newTestHeader(t, *testSecondaryPrd) testSecPlainHeader.ParentHash = testParentHash - testSecPlainHeader.Number = 1 // Secondary Vrf Test Header encParentVrfDigest := newEncodedBabeDigest(t, testBabeSecondaryVRFPreDigest) testParentVrfHeader := newTestHeader(t, *types.NewBABEPreRuntimeDigest(encParentVrfDigest)) - testParentVrfHeader.Number = 1 testVrfParentHash := encodeAndHashHeader(t, testParentVrfHeader) encVrfHeader := newEncodedBabeDigest(t, testBabeSecondaryVRFPreDigest) testSecVrfHeader := newTestHeader(t, *types.NewBABEPreRuntimeDigest(encVrfHeader)) testSecVrfHeader.ParentHash = testVrfParentHash - testSecVrfHeader.Number = 1 h := common.MustHexToHash("0x01") h1 := []common.Hash{h} @@ -533,26 +529,23 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { // Case 0: First element not preruntime digest header0 := newTestHeader(t, testInvalidSeal, testInvalidSeal) - header0.Number = 1 + // Case 1: Last element not seal header1 := newTestHeader(t, testInvalidPreRuntimeDigest, testInvalidPreRuntimeDigest) - header1.Number = 1 // Case 2: Fail to verify preruntime digest header2 := newTestHeader(t, testInvalidPreRuntimeDigest, testInvalidSeal) - header2.Number = 1 + // Case 3: Invalid Seal Length babePrd, err := testBabePrimaryPreDigest.ToPreRuntimeDigest() assert.NoError(t, err) header3 := newTestHeader(t, *babePrd, testInvalidSeal) - header3.Number = 1 babeVerifier := newTestVerifier(kp, mockBlockState, scale.MaxUint128, false) // Case 4: Invalid signature - BabePrimaryPreDigest babePrd2, err := testBabePrimaryPreDigest.ToPreRuntimeDigest() assert.NoError(t, err) header4 := newTestHeader(t, *babePrd2) - header4.Number = 1 signAndAddSeal(t, kp, header4, []byte{1}) babeVerifier2 := newTestVerifier(kp, mockBlockState, scale.MaxUint128, false) @@ -560,7 +553,6 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { babeSecPlainPrd, err := testBabeSecondaryPlainPreDigest.ToPreRuntimeDigest() assert.NoError(t, err) header5 := newTestHeader(t, *babeSecPlainPrd) - header5.Number = 1 signAndAddSeal(t, kp, header5, []byte{1}) babeVerifier3 := newTestVerifier(kp, mockBlockState, scale.MaxUint128, true) @@ -568,7 +560,6 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { encSecVrfDigest := newEncodedBabeDigest(t, testBabeSecondaryVRFPreDigest) assert.NoError(t, err) header6 := newTestHeader(t, *types.NewBABEPreRuntimeDigest(encSecVrfDigest)) - header6.Number = 1 signAndAddSeal(t, kp, header6, []byte{1}) babeVerifier4 := newTestVerifier(kp, mockBlockState, scale.MaxUint128, true) @@ -576,7 +567,6 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { babeParentPrd, err := testBabePrimaryPreDigest.ToPreRuntimeDigest() assert.NoError(t, err) babeParentHeader := newTestHeader(t, *babeParentPrd) - babeParentHeader.Number = 1 parentHash := encodeAndHashHeader(t, babeParentHeader) babePrd3, err := testBabePrimaryPreDigest.ToPreRuntimeDigest() @@ -584,7 +574,6 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { header7 := newTestHeader(t, *babePrd3) header7.ParentHash = parentHash - header7.Number = 1 hash := encodeAndHashHeader(t, header7) signAndAddSeal(t, kp, header7, hash[:]) @@ -700,7 +689,6 @@ func Test_verifier_verifyAuthorshipRightEquivocatory(t *testing.T) { assert.NoError(t, err) headerExisting := newTestHeader(t, *prdExisting) - headerExisting.Number = 1 hashExisting := encodeAndHashHeader(t, headerExisting) signAndAddSeal(t, kp, headerExisting, hashExisting[:]) @@ -734,58 +722,54 @@ func Test_verifier_verifyAuthorshipRightEquivocatory(t *testing.T) { verifierEquivocatoryPrimary := newVerifier(mockBlockStateEquiv1, 1, vi) headerEquivocatoryPrimary := newTestHeader(t, *prd1) - headerEquivocatoryPrimary.Number = 1 hashEquivocatoryPrimary := encodeAndHashHeader(t, headerEquivocatoryPrimary) signAndAddSeal(t, kp, headerEquivocatoryPrimary, hashEquivocatoryPrimary[:]) mockBlockStateEquiv1.EXPECT().GetHeader(hashEquivocatoryPrimary).Return(headerEquivocatoryPrimary, nil) - mockBlockStateEquiv1.EXPECT().GetBlocksBySlot(gomock.Any()).Return([]common.Hash{hashEquivocatoryPrimary, hashExisting}, nil) + mockBlockStateEquiv1.EXPECT().GetBlocksBySlot(gomock.Any()).Return( + []common.Hash{hashEquivocatoryPrimary, hashExisting}, nil) // Secondary Plain Test Header testParentPrd, err := testBabeSecondaryPlainPreDigest.ToPreRuntimeDigest() assert.NoError(t, err) testParentHeader := newTestHeader(t, *testParentPrd) - testParentHeader.Number = 1 testParentHash := encodeAndHashHeader(t, testParentHeader) testSecondaryPrd, err := testBabeSecondaryPlainPreDigest.ToPreRuntimeDigest() assert.NoError(t, err) testSecPlainHeader := newTestHeader(t, *testSecondaryPrd) testSecPlainHeader.ParentHash = testParentHash - testSecPlainHeader.Number = 1 babeSecPlainPrd2, err := testBabeSecondaryPlainPreDigest.ToPreRuntimeDigest() assert.NoError(t, err) headerEquivocatorySecondaryPlain := newTestHeader(t, *babeSecPlainPrd2) - headerEquivocatorySecondaryPlain.Number = 1 hashEquivocatorySecondaryPlain := encodeAndHashHeader(t, headerEquivocatorySecondaryPlain) signAndAddSeal(t, kp, headerEquivocatorySecondaryPlain, hashEquivocatorySecondaryPlain[:]) babeVerifier8 := newTestVerifier(kp, mockBlockStateEquiv2, scale.MaxUint128, true) mockBlockStateEquiv2.EXPECT().GetHeader(hashEquivocatorySecondaryPlain).Return(headerEquivocatorySecondaryPlain, nil) - mockBlockStateEquiv2.EXPECT().GetBlocksBySlot(gomock.Any()).Return([]common.Hash{hashEquivocatorySecondaryPlain, hashExisting}, nil) + mockBlockStateEquiv2.EXPECT().GetBlocksBySlot(gomock.Any()).Return( + []common.Hash{hashEquivocatorySecondaryPlain, hashExisting}, nil) // Secondary Vrf Test Header encParentVrfDigest := newEncodedBabeDigest(t, testBabeSecondaryVRFPreDigest) testParentVrfHeader := newTestHeader(t, *types.NewBABEPreRuntimeDigest(encParentVrfDigest)) - testParentVrfHeader.Number = 1 testVrfParentHash := encodeAndHashHeader(t, testParentVrfHeader) encVrfHeader := newEncodedBabeDigest(t, testBabeSecondaryVRFPreDigest) testSecVrfHeader := newTestHeader(t, *types.NewBABEPreRuntimeDigest(encVrfHeader)) testSecVrfHeader.ParentHash = testVrfParentHash - testSecVrfHeader.Number = 1 encVrfDigest := newEncodedBabeDigest(t, testBabeSecondaryVRFPreDigest) assert.NoError(t, err) headerEquivocatorySecondaryVRF := newTestHeader(t, *types.NewBABEPreRuntimeDigest(encVrfDigest)) - headerEquivocatorySecondaryVRF.Number = 1 hashEquivocatorySecondaryVRF := encodeAndHashHeader(t, headerEquivocatorySecondaryVRF) signAndAddSeal(t, kp, headerEquivocatorySecondaryVRF, hashEquivocatorySecondaryVRF[:]) babeVerifierEquivocatorySecondaryVRF := newTestVerifier(kp, mockBlockStateEquiv3, scale.MaxUint128, true) mockBlockStateEquiv3.EXPECT().GetHeader(hashEquivocatorySecondaryVRF).Return(headerEquivocatorySecondaryVRF, nil) - mockBlockStateEquiv3.EXPECT().GetBlocksBySlot(gomock.Any()).Return([]common.Hash{hashEquivocatorySecondaryVRF, hashExisting}, nil) + mockBlockStateEquiv3.EXPECT().GetBlocksBySlot(gomock.Any()).Return( + []common.Hash{hashEquivocatorySecondaryVRF, hashExisting}, nil) tests := []struct { name string @@ -971,7 +955,6 @@ func TestVerificationManager_VerifyBlock(t *testing.T) { encVrfDigest := newEncodedBabeDigest(t, testBabeSecondaryVRFPreDigest) assert.NoError(t, err) block1Header2 := newTestHeader(t, *types.NewBABEPreRuntimeDigest(encVrfDigest)) - block1Header2.Number = 1 authority := types.NewAuthority(kp.Public(), uint64(1)) info := &verifierInfo{ From 208650a8426a4a61ff24c1f65e9ee2ea9b6090f3 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Tue, 18 Oct 2022 11:33:04 +0530 Subject: [PATCH 08/40] temp --- lib/babe/verify_test.go | 6 +++++- lib/blocktree/blocktree.go | 8 ++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/babe/verify_test.go b/lib/babe/verify_test.go index b0f5d379f1..bd7bb24263 100644 --- a/lib/babe/verify_test.go +++ b/lib/babe/verify_test.go @@ -491,24 +491,28 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { // Primary Test Header encTestDigest := newEncodedBabeDigest(t, types.BabePrimaryPreDigest{AuthorityIndex: 0}) - testDigestPrimary := types.NewDigest() err = testDigestPrimary.Add(types.PreRuntimeDigest{ ConsensusEngineID: types.BabeEngineID, Data: encTestDigest, }) assert.NoError(t, err) + testHeaderPrimary := types.NewEmptyHeader() testHeaderPrimary.Digest = testDigestPrimary + // Secondary Plain Test Header testParentPrd, err := testBabeSecondaryPlainPreDigest.ToPreRuntimeDigest() assert.NoError(t, err) + testParentHeader := newTestHeader(t, *testParentPrd) testParentHash := encodeAndHashHeader(t, testParentHeader) testSecondaryPrd, err := testBabeSecondaryPlainPreDigest.ToPreRuntimeDigest() assert.NoError(t, err) + testSecPlainHeader := newTestHeader(t, *testSecondaryPrd) testSecPlainHeader.ParentHash = testParentHash + // Secondary Vrf Test Header encParentVrfDigest := newEncodedBabeDigest(t, testBabeSecondaryVRFPreDigest) testParentVrfHeader := newTestHeader(t, *types.NewBABEPreRuntimeDigest(encParentVrfDigest)) diff --git a/lib/blocktree/blocktree.go b/lib/blocktree/blocktree.go index ee62f4db33..062081c891 100644 --- a/lib/blocktree/blocktree.go +++ b/lib/blocktree/blocktree.go @@ -331,16 +331,16 @@ func (bt *BlockTree) GetAllBlocks() []Hash { } // GetAllDescendants returns all blocks that are descendants of the given block. -func (bt *BlockTree) GetAllDescendants(a common.Hash) ([]Hash, error) { +func (bt *BlockTree) GetAllDescendants(hash common.Hash) ([]Hash, error) { bt.RLock() defer bt.RUnlock() - an := bt.getNode(a) - if an == nil { + node := bt.getNode(hash) + if node == nil { return []common.Hash{}, ErrNodeNotFound } - return an.getAllDescendants(nil), nil + return node.getAllDescendants(nil), nil } // GetHashByNumber returns the block hash with the given number that is on the best chain. From 591247de09e9446b072036d690789a070ee8c932 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Wed, 19 Oct 2022 19:24:48 +0800 Subject: [PATCH 09/40] Update dot/state/block.go Co-authored-by: Quentin McGaw --- dot/state/block.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dot/state/block.go b/dot/state/block.go index 4c0f482078..1947375889 100644 --- a/dot/state/block.go +++ b/dot/state/block.go @@ -259,7 +259,7 @@ func (bs *BlockState) GetBlocksBySlot(slotNum uint64) ([]common.Hash, error) { descendants, err := bs.bt.GetAllDescendants(highestFinalisedHash) if err != nil { - return nil, fmt.Errorf("failed to get descendants of %s: %w", highestFinalisedHash, err) + return nil, fmt.Errorf("failed to get descendants: %w", err) } blocksWithGivenSlot := []common.Hash{} From 2f5fc9317bc4d97edabfe8731cb9f0222f4d0425 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Wed, 19 Oct 2022 19:37:26 +0800 Subject: [PATCH 10/40] Update lib/babe/verify.go Co-authored-by: Quentin McGaw --- lib/babe/verify.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/babe/verify.go b/lib/babe/verify.go index a1a8037387..222d8898d7 100644 --- a/lib/babe/verify.go +++ b/lib/babe/verify.go @@ -489,7 +489,7 @@ func (b *verifier) verifyPrimarySlotWinner(authorityIndex uint32, func getAuthorityIndex(header *types.Header) (uint32, error) { if len(header.Digest.Types) == 0 { - return 0, errNoDigest + return 0, fmt.Errorf("for block hash %s: %w", header.Hash(), errNoDigest) } digestValue, err := header.Digest.Types[0].Value() From 9025f7d0466dfa89eedc14e54bf375e7024e049a Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Wed, 19 Oct 2022 19:40:21 +0800 Subject: [PATCH 11/40] Update lib/babe/verify.go Co-authored-by: Quentin McGaw --- lib/babe/verify.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/babe/verify.go b/lib/babe/verify.go index 222d8898d7..e8f0696d16 100644 --- a/lib/babe/verify.go +++ b/lib/babe/verify.go @@ -338,7 +338,7 @@ func (b *verifier) verifyAuthorshipRight(header *types.Header) error { return nil } -// verifyBlockEquivocation checks if given block's author has occupied corresponding slot more than once. +// verifyBlockEquivocation checks if the given block's author has occupied the corresponding slot more than once. // It returns true if block was equivocated. func (b *verifier) verifyBlockEquivocation(header *types.Header) (bool, error) { author, err := getAuthorityIndex(header) From 450262a8933ccd25fc60d41abb1535cd72fd2512 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Wed, 19 Oct 2022 19:40:54 +0800 Subject: [PATCH 12/40] Update lib/blocktree/blocktree.go Co-authored-by: Quentin McGaw --- lib/blocktree/blocktree.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/blocktree/blocktree.go b/lib/blocktree/blocktree.go index ee62f4db33..e8cd9b6b41 100644 --- a/lib/blocktree/blocktree.go +++ b/lib/blocktree/blocktree.go @@ -337,7 +337,7 @@ func (bt *BlockTree) GetAllDescendants(a common.Hash) ([]Hash, error) { an := bt.getNode(a) if an == nil { - return []common.Hash{}, ErrNodeNotFound + return []common.Hash{}, fmt.Errorf("%w: for block hash %s", ErrNodeNotFound, a) } return an.getAllDescendants(nil), nil From 6ceeffe07c058ae2d771c40882b1dda18029159e Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Thu, 20 Oct 2022 14:34:38 +0530 Subject: [PATCH 13/40] added tests and addressed some review comments --- dot/state/block_test.go | 56 +++++++++++++++++++++++++++++++++ lib/babe/verify_test.go | 10 +++--- lib/blocktree/blocktree_test.go | 9 ++++++ 3 files changed, 70 insertions(+), 5 deletions(-) diff --git a/dot/state/block_test.go b/dot/state/block_test.go index e437a674b2..21686d52b8 100644 --- a/dot/state/block_test.go +++ b/dot/state/block_test.go @@ -195,6 +195,62 @@ func TestGetSlotForBlock(t *testing.T) { require.Equal(t, expectedSlot, res) } +func TestGetBlocksBySlot(t *testing.T) { + // create two block in the same slot and test if GetBlocksBySlot gets us + // both the blocks + bs := newTestBlockState(t, newTriesEmpty()) + slot := uint64(77) + + babeHeader := types.NewBabeDigest() + err := babeHeader.Set(*types.NewBabePrimaryPreDigest(0, slot, [32]byte{}, [64]byte{})) + require.NoError(t, err) + data, err := scale.Marshal(babeHeader) + require.NoError(t, err) + preDigest := types.NewBABEPreRuntimeDigest(data) + + digest := types.NewDigest() + err = digest.Add(*preDigest) + require.NoError(t, err) + block := &types.Block{ + Header: types.Header{ + ParentHash: testGenesisHeader.Hash(), + Number: 1, + Digest: digest, + }, + Body: types.Body{}, + } + + err = bs.AddBlock(block) + require.NoError(t, err) + + babeHeader2 := types.NewBabeDigest() + err = babeHeader2.Set(*types.NewBabePrimaryPreDigest(1, slot, [32]byte{}, [64]byte{})) + require.NoError(t, err) + data2, err := scale.Marshal(babeHeader2) + require.NoError(t, err) + preDigest2 := types.NewBABEPreRuntimeDigest(data2) + + digest2 := types.NewDigest() + err = digest2.Add(*preDigest2) + require.NoError(t, err) + block2 := &types.Block{ + Header: types.Header{ + ParentHash: testGenesisHeader.Hash(), + Number: 1, + Digest: digest2, + }, + Body: types.Body{}, + } + err = bs.AddBlock(block2) + require.NoError(t, err) + + blocks, err := bs.GetBlocksBySlot(slot) + require.NoError(t, err) + require.Equal(t, len(blocks), 2) + require.Contains(t, blocks, block.Header.Hash()) + require.Contains(t, blocks, block2.Header.Hash()) +} + func TestIsBlockOnCurrentChain(t *testing.T) { bs := newTestBlockState(t, newTriesEmpty()) currChain, branchChains := AddBlocksToState(t, bs, 3, false) diff --git a/lib/babe/verify_test.go b/lib/babe/verify_test.go index bd7bb24263..8c73131885 100644 --- a/lib/babe/verify_test.go +++ b/lib/babe/verify_test.go @@ -526,10 +526,10 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { h1 := []common.Hash{h} mockBlockState.EXPECT().GetHeader(h).Return(types.NewEmptyHeader(), nil) - mockBlockState.EXPECT().GetBlocksBySlot(gomock.Any()).Return(h1, nil) + mockBlockState.EXPECT().GetBlocksBySlot(gomock.AssignableToTypeOf(uint64(0))).Return(h1, nil) mockBlockStateErr.EXPECT().GetHeader(h).Return(nil, errors.New("get header error")) - mockBlockStateErr.EXPECT().GetBlocksBySlot(gomock.Any()).Return(h1, nil) + mockBlockStateErr.EXPECT().GetBlocksBySlot(gomock.AssignableToTypeOf(uint64(0))).Return(h1, nil) // Case 0: First element not preruntime digest header0 := newTestHeader(t, testInvalidSeal, testInvalidSeal) @@ -730,7 +730,7 @@ func Test_verifier_verifyAuthorshipRightEquivocatory(t *testing.T) { signAndAddSeal(t, kp, headerEquivocatoryPrimary, hashEquivocatoryPrimary[:]) mockBlockStateEquiv1.EXPECT().GetHeader(hashEquivocatoryPrimary).Return(headerEquivocatoryPrimary, nil) - mockBlockStateEquiv1.EXPECT().GetBlocksBySlot(gomock.Any()).Return( + mockBlockStateEquiv1.EXPECT().GetBlocksBySlot(gomock.AssignableToTypeOf(uint64(0))).Return( []common.Hash{hashEquivocatoryPrimary, hashExisting}, nil) // Secondary Plain Test Header @@ -753,7 +753,7 @@ func Test_verifier_verifyAuthorshipRightEquivocatory(t *testing.T) { babeVerifier8 := newTestVerifier(kp, mockBlockStateEquiv2, scale.MaxUint128, true) mockBlockStateEquiv2.EXPECT().GetHeader(hashEquivocatorySecondaryPlain).Return(headerEquivocatorySecondaryPlain, nil) - mockBlockStateEquiv2.EXPECT().GetBlocksBySlot(gomock.Any()).Return( + mockBlockStateEquiv2.EXPECT().GetBlocksBySlot(gomock.AssignableToTypeOf(uint64(0))).Return( []common.Hash{hashEquivocatorySecondaryPlain, hashExisting}, nil) // Secondary Vrf Test Header @@ -772,7 +772,7 @@ func Test_verifier_verifyAuthorshipRightEquivocatory(t *testing.T) { babeVerifierEquivocatorySecondaryVRF := newTestVerifier(kp, mockBlockStateEquiv3, scale.MaxUint128, true) mockBlockStateEquiv3.EXPECT().GetHeader(hashEquivocatorySecondaryVRF).Return(headerEquivocatorySecondaryVRF, nil) - mockBlockStateEquiv3.EXPECT().GetBlocksBySlot(gomock.Any()).Return( + mockBlockStateEquiv3.EXPECT().GetBlocksBySlot(gomock.AssignableToTypeOf(uint64(0))).Return( []common.Hash{hashEquivocatorySecondaryVRF, hashExisting}, nil) tests := []struct { diff --git a/lib/blocktree/blocktree_test.go b/lib/blocktree/blocktree_test.go index ca6fd5f1a2..718f0d14fd 100644 --- a/lib/blocktree/blocktree_test.go +++ b/lib/blocktree/blocktree_test.go @@ -347,6 +347,15 @@ func TestBlockTree_GetAllBlocksAtNumber(t *testing.T) { require.Equal(t, expected, hashes) } +func TestBlockTreeGetAllDescendants(t *testing.T) { + // Create tree with number 4 (with 4 nodes) + bt, hashes := createFlatTree(t, 4) + + descendants, err := bt.GetAllDescendants(bt.root.hash) + require.NoError(t, err) + require.NotEqual(t, hashes, descendants) +} + func TestBlockTree_IsDecendantOf(t *testing.T) { // Create tree with number 4 (with 4 nodes) bt, hashes := createFlatTree(t, 4) From 5259e5d567760f2ce8ff63f8145d0b017723d220 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Tue, 25 Oct 2022 20:13:00 +0530 Subject: [PATCH 14/40] temp --- dot/state/block.go | 4 ++-- dot/state/block_test.go | 6 +++--- lib/babe/mock_state_test.go | 12 ++++++------ lib/babe/state.go | 2 +- lib/babe/verify.go | 6 +++--- lib/babe/verify_test.go | 6 +++--- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/dot/state/block.go b/dot/state/block.go index 1947375889..7215d126d9 100644 --- a/dot/state/block.go +++ b/dot/state/block.go @@ -250,8 +250,8 @@ func (bs *BlockState) GetHashByNumber(num uint) (common.Hash, error) { return common.NewHash(bh), nil } -// GetBlocksBySlot gets all blocks that were produced in given slot. -func (bs *BlockState) GetBlocksBySlot(slotNum uint64) ([]common.Hash, error) { +// GetBlockHashesBySlot gets all blocks that were produced in given slot. +func (bs *BlockState) GetBlockHashesBySlot(slotNum uint64) ([]common.Hash, error) { highestFinalisedHash, err := bs.GetHighestFinalisedHash() if err != nil { return nil, fmt.Errorf("failed to get highest finalised hash: %w", err) diff --git a/dot/state/block_test.go b/dot/state/block_test.go index 21686d52b8..e115a18842 100644 --- a/dot/state/block_test.go +++ b/dot/state/block_test.go @@ -195,8 +195,8 @@ func TestGetSlotForBlock(t *testing.T) { require.Equal(t, expectedSlot, res) } -func TestGetBlocksBySlot(t *testing.T) { - // create two block in the same slot and test if GetBlocksBySlot gets us +func TestGetBlockHashesBySlot(t *testing.T) { + // create two block in the same slot and test if GetBlockHashesBySlot gets us // both the blocks bs := newTestBlockState(t, newTriesEmpty()) slot := uint64(77) @@ -244,7 +244,7 @@ func TestGetBlocksBySlot(t *testing.T) { err = bs.AddBlock(block2) require.NoError(t, err) - blocks, err := bs.GetBlocksBySlot(slot) + blocks, err := bs.GetBlockHashesBySlot(slot) require.NoError(t, err) require.Equal(t, len(blocks), 2) require.Contains(t, blocks, block.Header.Hash()) diff --git a/lib/babe/mock_state_test.go b/lib/babe/mock_state_test.go index 0a75954d34..cf3cf60e1e 100644 --- a/lib/babe/mock_state_test.go +++ b/lib/babe/mock_state_test.go @@ -197,19 +197,19 @@ func (mr *MockBlockStateMockRecorder) GetBlockByNumber(arg0 interface{}) *gomock return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockByNumber", reflect.TypeOf((*MockBlockState)(nil).GetBlockByNumber), arg0) } -// GetBlocksBySlot mocks base method. -func (m *MockBlockState) GetBlocksBySlot(arg0 uint64) ([]common.Hash, error) { +// GetBlockHashesBySlot mocks base method. +func (m *MockBlockState) GetBlockHashesBySlot(arg0 uint64) ([]common.Hash, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetBlocksBySlot", arg0) + ret := m.ctrl.Call(m, "GetBlockHashesBySlot", arg0) ret0, _ := ret[0].([]common.Hash) ret1, _ := ret[1].(error) return ret0, ret1 } -// GetBlocksBySlot indicates an expected call of GetBlocksBySlot. -func (mr *MockBlockStateMockRecorder) GetBlocksBySlot(arg0 interface{}) *gomock.Call { +// GetBlockHashesBySlot indicates an expected call of GetBlockHashesBySlot. +func (mr *MockBlockStateMockRecorder) GetBlockHashesBySlot(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlocksBySlot", reflect.TypeOf((*MockBlockState)(nil).GetBlocksBySlot), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockHashesBySlot", reflect.TypeOf((*MockBlockState)(nil).GetBlockHashesBySlot), arg0) } // GetFinalisedHeader mocks base method. diff --git a/lib/babe/state.go b/lib/babe/state.go index d9097dad09..f17781cf4c 100644 --- a/lib/babe/state.go +++ b/lib/babe/state.go @@ -28,7 +28,7 @@ type BlockState interface { GetHeader(common.Hash) (*types.Header, error) GetBlockByNumber(blockNumber uint) (*types.Block, error) GetBlockByHash(common.Hash) (*types.Block, error) - GetBlocksBySlot(uint64) ([]common.Hash, error) + GetBlockHashesBySlot(uint64) ([]common.Hash, error) GetArrivalTime(common.Hash) (time.Time, error) GenesisHash() common.Hash GetSlotForBlock(common.Hash) (uint64, error) diff --git a/lib/babe/verify.go b/lib/babe/verify.go index e8f0696d16..8e7e09d702 100644 --- a/lib/babe/verify.go +++ b/lib/babe/verify.go @@ -138,7 +138,7 @@ func (v *VerificationManager) VerifyBlock(header *types.Header) error { if !block1IsFinal { firstSlot, err := types.GetSlotFromHeader(header) if err != nil { - return fmt.Errorf("failed to get slot from block 1: %w", err) + return fmt.Errorf("failed to get slot from header of block 1: %w", err) } logger.Debugf("syncing block 1, setting first slot as %d", firstSlot) @@ -349,10 +349,10 @@ func (b *verifier) verifyBlockEquivocation(header *types.Header) (bool, error) { currentHash := header.Hash() slot, err := types.GetSlotFromHeader(header) if err != nil { - return false, fmt.Errorf("failed to get slot for block %s: %w", currentHash, err) + return false, fmt.Errorf("failed to get slot from header of block %s: %w", currentHash, err) } - blocksInSlot, err := b.blockState.GetBlocksBySlot(slot) + blocksInSlot, err := b.blockState.GetBlockHashesBySlot(slot) if err != nil { return false, fmt.Errorf("failed to get blocks produced in slot %d: %w", slot, err) } diff --git a/lib/babe/verify_test.go b/lib/babe/verify_test.go index d23a3e7900..50b1956d17 100644 --- a/lib/babe/verify_test.go +++ b/lib/babe/verify_test.go @@ -156,7 +156,7 @@ func Test_getAuthorityIndex(t *testing.T) { { name: "No Digest", args: args{types.NewEmptyHeader()}, - expErr: errors.New("no digest provided"), + expErr: errNoDigest, }, { name: "First Digest Invalid Type", @@ -528,10 +528,10 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { h1 := []common.Hash{h} mockBlockState.EXPECT().GetHeader(h).Return(types.NewEmptyHeader(), nil) - mockBlockState.EXPECT().GetBlocksBySlot(gomock.AssignableToTypeOf(uint64(0))).Return(h1, nil) + mockBlockState.EXPECT().GetBlockHashesBySlot(gomock.AssignableToTypeOf(uint64(0))).Return(h1, nil) mockBlockStateErr.EXPECT().GetHeader(h).Return(nil, errors.New("get header error")) - mockBlockStateErr.EXPECT().GetBlocksBySlot(gomock.AssignableToTypeOf(uint64(0))).Return(h1, nil) + mockBlockStateErr.EXPECT().GetBlockHashesBySlot(gomock.AssignableToTypeOf(uint64(0))).Return(h1, nil) // Case 0: First element not preruntime digest header0 := newTestHeader(t, testInvalidSeal, testInvalidSeal) From 305fd281d4b19c117e59babbf1378a38b4617a80 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Tue, 25 Oct 2022 20:13:33 +0530 Subject: [PATCH 15/40] temp --- lib/babe/verify_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/babe/verify_test.go b/lib/babe/verify_test.go index 50b1956d17..160c607aee 100644 --- a/lib/babe/verify_test.go +++ b/lib/babe/verify_test.go @@ -733,7 +733,7 @@ func Test_verifier_verifyAuthorshipRightEquivocatory(t *testing.T) { signAndAddSeal(t, kp, headerEquivocatoryPrimary, hashEquivocatoryPrimary[:]) mockBlockStateEquiv1.EXPECT().GetHeader(hashEquivocatoryPrimary).Return(headerEquivocatoryPrimary, nil) - mockBlockStateEquiv1.EXPECT().GetBlocksBySlot(gomock.AssignableToTypeOf(uint64(0))).Return( + mockBlockStateEquiv1.EXPECT().GetBlockHashesBySlot(gomock.AssignableToTypeOf(uint64(0))).Return( []common.Hash{hashEquivocatoryPrimary, hashExisting}, nil) // Secondary Plain Test Header @@ -756,7 +756,7 @@ func Test_verifier_verifyAuthorshipRightEquivocatory(t *testing.T) { babeVerifier8 := newTestVerifier(kp, mockBlockStateEquiv2, scale.MaxUint128, true) mockBlockStateEquiv2.EXPECT().GetHeader(hashEquivocatorySecondaryPlain).Return(headerEquivocatorySecondaryPlain, nil) - mockBlockStateEquiv2.EXPECT().GetBlocksBySlot(gomock.AssignableToTypeOf(uint64(0))).Return( + mockBlockStateEquiv2.EXPECT().GetBlockHashesBySlot(gomock.AssignableToTypeOf(uint64(0))).Return( []common.Hash{hashEquivocatorySecondaryPlain, hashExisting}, nil) // Secondary Vrf Test Header @@ -775,7 +775,7 @@ func Test_verifier_verifyAuthorshipRightEquivocatory(t *testing.T) { babeVerifierEquivocatorySecondaryVRF := newTestVerifier(kp, mockBlockStateEquiv3, scale.MaxUint128, true) mockBlockStateEquiv3.EXPECT().GetHeader(hashEquivocatorySecondaryVRF).Return(headerEquivocatorySecondaryVRF, nil) - mockBlockStateEquiv3.EXPECT().GetBlocksBySlot(gomock.AssignableToTypeOf(uint64(0))).Return( + mockBlockStateEquiv3.EXPECT().GetBlockHashesBySlot(gomock.AssignableToTypeOf(uint64(0))).Return( []common.Hash{hashEquivocatorySecondaryVRF, hashExisting}, nil) tests := []struct { From e5904f6f896407bbccc50a47629ceb85ca1e42a6 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Wed, 26 Oct 2022 17:32:27 +0800 Subject: [PATCH 16/40] Update lib/babe/verify.go Co-authored-by: Quentin McGaw --- lib/babe/verify.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/babe/verify.go b/lib/babe/verify.go index 8e7e09d702..94db396329 100644 --- a/lib/babe/verify.go +++ b/lib/babe/verify.go @@ -343,7 +343,7 @@ func (b *verifier) verifyAuthorshipRight(header *types.Header) error { func (b *verifier) verifyBlockEquivocation(header *types.Header) (bool, error) { author, err := getAuthorityIndex(header) if err != nil { - return false, fmt.Errorf("failed to get authority index for %s: %w", header.Hash(), err) + return false, fmt.Errorf("failed to get authority index: %w", err) } currentHash := header.Hash() From 60c837776c1fdf3c45e609c65088c096683f0ac7 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Wed, 26 Oct 2022 17:34:11 +0800 Subject: [PATCH 17/40] Update lib/babe/verify.go Co-authored-by: Quentin McGaw --- lib/babe/verify.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/babe/verify.go b/lib/babe/verify.go index 94db396329..f944b8dc9e 100644 --- a/lib/babe/verify.go +++ b/lib/babe/verify.go @@ -329,7 +329,7 @@ func (b *verifier) verifyAuthorshipRight(header *types.Header) error { equivocated, err := b.verifyBlockEquivocation(header) if err != nil { - return fmt.Errorf("could not verify block equivocation for header %s: %w", header.Hash(), err) + return fmt.Errorf("could not verify block equivocation: %w", err) } if equivocated { return ErrProducerEquivocated From db73ab59510d8e8fa6b1c43a9cfa83e3b29cb736 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Wed, 26 Oct 2022 15:13:54 +0530 Subject: [PATCH 18/40] addressed reviews --- lib/babe/verify.go | 12 ++++++------ lib/babe/verify_test.go | 6 +++--- lib/blocktree/blocktree_test.go | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/babe/verify.go b/lib/babe/verify.go index 8e7e09d702..0a6c51f7a4 100644 --- a/lib/babe/verify.go +++ b/lib/babe/verify.go @@ -352,24 +352,24 @@ func (b *verifier) verifyBlockEquivocation(header *types.Header) (bool, error) { return false, fmt.Errorf("failed to get slot from header of block %s: %w", currentHash, err) } - blocksInSlot, err := b.blockState.GetBlockHashesBySlot(slot) + blockHashesInSlot, err := b.blockState.GetBlockHashesBySlot(slot) if err != nil { return false, fmt.Errorf("failed to get blocks produced in slot %d: %w", slot, err) } - for _, blockInSlot := range blocksInSlot { - if blockInSlot.Equal(currentHash) { + for _, blockHashInSlot := range blockHashesInSlot { + if blockHashInSlot.Equal(currentHash) { continue } - existingHeader, err := b.blockState.GetHeader(blockInSlot) + existingHeader, err := b.blockState.GetHeader(blockHashInSlot) if err != nil { - return false, fmt.Errorf("failed to get header for block %s: %w", blockInSlot, err) + return false, fmt.Errorf("failed to get header for block %s: %w", blockHashInSlot, err) } authorOfExistingHeader, err := getAuthorityIndex(existingHeader) if err != nil { - return false, fmt.Errorf("failed to get authority index for block %s: %w", blockInSlot, err) + return false, fmt.Errorf("failed to get authority index for block %s: %w", blockHashInSlot, err) } if authorOfExistingHeader != author { continue diff --git a/lib/babe/verify_test.go b/lib/babe/verify_test.go index 160c607aee..a69b40d964 100644 --- a/lib/babe/verify_test.go +++ b/lib/babe/verify_test.go @@ -686,13 +686,13 @@ func Test_verifier_verifyAuthorshipRightEquivocatory(t *testing.T) { output2, proof2, err := kp.VrfSign(makeTranscript(Randomness{}, uint64(1), 2)) assert.NoError(t, err) - secDigestExisting := types.BabePrimaryPreDigest{ + secondDigestExisting := types.BabePrimaryPreDigest{ AuthorityIndex: 1, SlotNumber: 1, VRFOutput: output2, VRFProof: proof2, } - prdExisting, err := secDigestExisting.ToPreRuntimeDigest() + prdExisting, err := secondDigestExisting.ToPreRuntimeDigest() assert.NoError(t, err) headerExisting := newTestHeader(t, *prdExisting) @@ -996,7 +996,7 @@ func TestVerificationManager_VerifyBlock(t *testing.T) { name: "get slot from header error", vm: vm1, header: block1Header, - expErr: fmt.Errorf("failed to get slot from block 1: %w", types.ErrChainHeadMissingDigest), + expErr: fmt.Errorf("failed to get slot from header of block 1: %w", types.ErrChainHeadMissingDigest), }, { name: "set first slot error", diff --git a/lib/blocktree/blocktree_test.go b/lib/blocktree/blocktree_test.go index 718f0d14fd..24212ed826 100644 --- a/lib/blocktree/blocktree_test.go +++ b/lib/blocktree/blocktree_test.go @@ -353,7 +353,7 @@ func TestBlockTreeGetAllDescendants(t *testing.T) { descendants, err := bt.GetAllDescendants(bt.root.hash) require.NoError(t, err) - require.NotEqual(t, hashes, descendants) + require.Equal(t, hashes, descendants) } func TestBlockTree_IsDecendantOf(t *testing.T) { From e5138f32acb3544b40f05df4c479510e1b5152da Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Wed, 26 Oct 2022 17:44:57 +0530 Subject: [PATCH 19/40] addressed some comment --- lib/babe/verify_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/babe/verify_test.go b/lib/babe/verify_test.go index a69b40d964..f047b9ed81 100644 --- a/lib/babe/verify_test.go +++ b/lib/babe/verify_test.go @@ -156,7 +156,7 @@ func Test_getAuthorityIndex(t *testing.T) { { name: "No Digest", args: args{types.NewEmptyHeader()}, - expErr: errNoDigest, + expErr: fmt.Errorf("for block hash %s: %w", types.NewEmptyHeader().Hash(), errNoDigest), }, { name: "First Digest Invalid Type", @@ -647,13 +647,13 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { name: "valid digest items, getAuthorityIndex error", verifier: *babeVerifier5, header: header7, - expErr: errNoDigest, + expErr: fmt.Errorf("could not verify block equivocation: failed to get authority index for block 0x0100000000000000000000000000000000000000000000000000000000000000: for block hash %s: %w", types.NewEmptyHeader().Hash(), errNoDigest), }, { name: "get header err", verifier: *babeVerifier6, header: header7, - expErr: errors.New("failed to get header for block"), + expErr: fmt.Errorf("could not verify block equivocation: failed to get header for block 0x0100000000000000000000000000000000000000000000000000000000000000: get header error"), }, } for _, tt := range tests { @@ -661,7 +661,7 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { b := &tt.verifier err := b.verifyAuthorshipRight(tt.header) if tt.expErr != nil { - assert.ErrorContains(t, err, tt.expErr.Error()) + assert.EqualError(t, err, tt.expErr.Error()) } else { assert.NoError(t, err) } From f62ee9f546ac28eb198706417754e26738e99b28 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Wed, 26 Oct 2022 18:21:35 +0530 Subject: [PATCH 20/40] fixing lint --- lib/babe/verify_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/babe/verify_test.go b/lib/babe/verify_test.go index f047b9ed81..4b4fffa295 100644 --- a/lib/babe/verify_test.go +++ b/lib/babe/verify_test.go @@ -647,13 +647,13 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { name: "valid digest items, getAuthorityIndex error", verifier: *babeVerifier5, header: header7, - expErr: fmt.Errorf("could not verify block equivocation: failed to get authority index for block 0x0100000000000000000000000000000000000000000000000000000000000000: for block hash %s: %w", types.NewEmptyHeader().Hash(), errNoDigest), + expErr: fmt.Errorf("could not verify block equivocation: failed to get authority index for block %s: for block hash %s: %w", h, types.NewEmptyHeader().Hash(), errNoDigest), }, { name: "get header err", verifier: *babeVerifier6, header: header7, - expErr: fmt.Errorf("could not verify block equivocation: failed to get header for block 0x0100000000000000000000000000000000000000000000000000000000000000: get header error"), + expErr: fmt.Errorf("could not verify block equivocation: failed to get header for block %s: get header error", h), }, } for _, tt := range tests { From 6b0e1f37d95ec62cb84e5709a716db1db307a114 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Wed, 26 Oct 2022 18:25:54 +0530 Subject: [PATCH 21/40] fixing lint --- lib/babe/verify_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/babe/verify_test.go b/lib/babe/verify_test.go index 4b4fffa295..2d5b9e88d1 100644 --- a/lib/babe/verify_test.go +++ b/lib/babe/verify_test.go @@ -647,7 +647,8 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { name: "valid digest items, getAuthorityIndex error", verifier: *babeVerifier5, header: header7, - expErr: fmt.Errorf("could not verify block equivocation: failed to get authority index for block %s: for block hash %s: %w", h, types.NewEmptyHeader().Hash(), errNoDigest), + expErr: fmt.Errorf("could not verify block equivocation: failed to get authority index for block %s: for block hash %s: %w", //nolint:lll + h, types.NewEmptyHeader().Hash(), errNoDigest), }, { name: "get header err", From 33a0341b790a691b3d9727838f42a2acfffd6053 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Fri, 28 Oct 2022 17:20:29 +0530 Subject: [PATCH 22/40] small change --- lib/babe/verify.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/babe/verify.go b/lib/babe/verify.go index a45b0ae5a1..f059aae85e 100644 --- a/lib/babe/verify.go +++ b/lib/babe/verify.go @@ -332,7 +332,7 @@ func (b *verifier) verifyAuthorshipRight(header *types.Header) error { return fmt.Errorf("could not verify block equivocation: %w", err) } if equivocated { - return ErrProducerEquivocated + return fmt.Errorf("%w for block header %s", ErrProducerEquivocated, header.Hash()) } return nil From 63e541f94d907c2402f61d74504f774576b7b2e9 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Sat, 29 Oct 2022 09:49:19 +0800 Subject: [PATCH 23/40] Update lib/blocktree/blocktree_test.go Co-authored-by: Quentin McGaw --- lib/blocktree/blocktree_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/blocktree/blocktree_test.go b/lib/blocktree/blocktree_test.go index 24212ed826..dc5e90cddd 100644 --- a/lib/blocktree/blocktree_test.go +++ b/lib/blocktree/blocktree_test.go @@ -348,6 +348,8 @@ func TestBlockTree_GetAllBlocksAtNumber(t *testing.T) { } func TestBlockTreeGetAllDescendants(t *testing.T) { + t.Parallel() + // Create tree with number 4 (with 4 nodes) bt, hashes := createFlatTree(t, 4) From 3b72b7d53de285eb11674af03791010249663317 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Sat, 29 Oct 2022 09:49:57 +0800 Subject: [PATCH 24/40] Update lib/blocktree/blocktree.go Co-authored-by: Quentin McGaw --- lib/blocktree/blocktree.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/blocktree/blocktree.go b/lib/blocktree/blocktree.go index 94a1e85c11..45f27411db 100644 --- a/lib/blocktree/blocktree.go +++ b/lib/blocktree/blocktree.go @@ -330,7 +330,7 @@ func (bt *BlockTree) GetAllBlocks() []Hash { return bt.root.getAllDescendants(nil) } -// GetAllDescendants returns all blocks that are descendants of the given block. +// GetAllDescendants returns all block hashes that are descendants of the given block hash. func (bt *BlockTree) GetAllDescendants(hash common.Hash) ([]Hash, error) { bt.RLock() defer bt.RUnlock() From 3d5569a8feb1f1c27b85ec310e7c61a0f838de21 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Sat, 29 Oct 2022 10:44:28 +0800 Subject: [PATCH 25/40] Update dot/state/block.go Co-authored-by: Quentin McGaw --- dot/state/block.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dot/state/block.go b/dot/state/block.go index 7215d126d9..ae89f12b7e 100644 --- a/dot/state/block.go +++ b/dot/state/block.go @@ -270,7 +270,7 @@ func (bs *BlockState) GetBlockHashesBySlot(slotNum uint64) ([]common.Hash, error continue } if err != nil { - return blocksWithGivenSlot, fmt.Errorf("could not get slot for block %s: %w", desc, err) + return nil, fmt.Errorf("could not get slot for block %s: %w", desc, err) } if descSlot == slotNum { From 5f1679cc0db9cba789ae8c5f6b8b9e22db50f029 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Sat, 29 Oct 2022 10:46:22 +0800 Subject: [PATCH 26/40] Update dot/state/block_test.go Co-authored-by: Quentin McGaw --- dot/state/block_test.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dot/state/block_test.go b/dot/state/block_test.go index e115a18842..60d60ad86f 100644 --- a/dot/state/block_test.go +++ b/dot/state/block_test.go @@ -246,9 +246,8 @@ func TestGetBlockHashesBySlot(t *testing.T) { blocks, err := bs.GetBlockHashesBySlot(slot) require.NoError(t, err) - require.Equal(t, len(blocks), 2) - require.Contains(t, blocks, block.Header.Hash()) - require.Contains(t, blocks, block2.Header.Hash()) + expectedBlockHashes := []common.Hash{block.Header.Hash(), block2.Header.Hash()} + require.ElementsMatch(t, blocks, expectedBlockHashes) } func TestIsBlockOnCurrentChain(t *testing.T) { From f25b7022f48bf76d208e31b140aa72f0d6612f3a Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Sat, 29 Oct 2022 10:47:09 +0800 Subject: [PATCH 27/40] Update lib/babe/verify_test.go Co-authored-by: Quentin McGaw --- lib/babe/verify_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/babe/verify_test.go b/lib/babe/verify_test.go index 2d5b9e88d1..255799a724 100644 --- a/lib/babe/verify_test.go +++ b/lib/babe/verify_test.go @@ -528,7 +528,7 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { h1 := []common.Hash{h} mockBlockState.EXPECT().GetHeader(h).Return(types.NewEmptyHeader(), nil) - mockBlockState.EXPECT().GetBlockHashesBySlot(gomock.AssignableToTypeOf(uint64(0))).Return(h1, nil) + mockBlockState.EXPECT().GetBlockHashesBySlot(uint64(1)).Return(h1, nil) mockBlockStateErr.EXPECT().GetHeader(h).Return(nil, errors.New("get header error")) mockBlockStateErr.EXPECT().GetBlockHashesBySlot(gomock.AssignableToTypeOf(uint64(0))).Return(h1, nil) From 3906343e0a518c00db7d82cbc573b03829239dbe Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Sat, 29 Oct 2022 10:47:57 +0800 Subject: [PATCH 28/40] Update lib/babe/verify_test.go Co-authored-by: Quentin McGaw --- lib/babe/verify_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/babe/verify_test.go b/lib/babe/verify_test.go index 255799a724..9c6ddd8c6c 100644 --- a/lib/babe/verify_test.go +++ b/lib/babe/verify_test.go @@ -776,7 +776,7 @@ func Test_verifier_verifyAuthorshipRightEquivocatory(t *testing.T) { babeVerifierEquivocatorySecondaryVRF := newTestVerifier(kp, mockBlockStateEquiv3, scale.MaxUint128, true) mockBlockStateEquiv3.EXPECT().GetHeader(hashEquivocatorySecondaryVRF).Return(headerEquivocatorySecondaryVRF, nil) - mockBlockStateEquiv3.EXPECT().GetBlockHashesBySlot(gomock.AssignableToTypeOf(uint64(0))).Return( + mockBlockStateEquiv3.EXPECT().GetBlockHashesBySlot(uint64(1)).Return( []common.Hash{hashEquivocatorySecondaryVRF, hashExisting}, nil) tests := []struct { From 9e798df6493986a587b6470bfab597c56767f7cb Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Sat, 29 Oct 2022 11:14:50 +0800 Subject: [PATCH 29/40] Update lib/babe/verify_test.go Co-authored-by: Quentin McGaw --- lib/babe/verify_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/babe/verify_test.go b/lib/babe/verify_test.go index 9c6ddd8c6c..af6722c056 100644 --- a/lib/babe/verify_test.go +++ b/lib/babe/verify_test.go @@ -531,7 +531,7 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { mockBlockState.EXPECT().GetBlockHashesBySlot(uint64(1)).Return(h1, nil) mockBlockStateErr.EXPECT().GetHeader(h).Return(nil, errors.New("get header error")) - mockBlockStateErr.EXPECT().GetBlockHashesBySlot(gomock.AssignableToTypeOf(uint64(0))).Return(h1, nil) + mockBlockStateErr.EXPECT().GetBlockHashesBySlot(uint64(1)).Return(h1, nil) // Case 0: First element not preruntime digest header0 := newTestHeader(t, testInvalidSeal, testInvalidSeal) From de936cd806270e6862bb716c44c62b7153fb88de Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Sat, 29 Oct 2022 11:19:33 +0800 Subject: [PATCH 30/40] Update lib/babe/verify_test.go Co-authored-by: Quentin McGaw --- lib/babe/verify_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/babe/verify_test.go b/lib/babe/verify_test.go index af6722c056..e869569098 100644 --- a/lib/babe/verify_test.go +++ b/lib/babe/verify_test.go @@ -734,7 +734,7 @@ func Test_verifier_verifyAuthorshipRightEquivocatory(t *testing.T) { signAndAddSeal(t, kp, headerEquivocatoryPrimary, hashEquivocatoryPrimary[:]) mockBlockStateEquiv1.EXPECT().GetHeader(hashEquivocatoryPrimary).Return(headerEquivocatoryPrimary, nil) - mockBlockStateEquiv1.EXPECT().GetBlockHashesBySlot(gomock.AssignableToTypeOf(uint64(0))).Return( + mockBlockStateEquiv1.EXPECT().GetBlockHashesBySlot(uint64(1)).Return( []common.Hash{hashEquivocatoryPrimary, hashExisting}, nil) // Secondary Plain Test Header From 09954162938e1fbae9dec2dd063c86ec23f203fb Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Sat, 29 Oct 2022 11:24:46 +0800 Subject: [PATCH 31/40] Update lib/babe/verify_test.go Co-authored-by: Quentin McGaw --- lib/babe/verify_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/babe/verify_test.go b/lib/babe/verify_test.go index e869569098..b9b3354051 100644 --- a/lib/babe/verify_test.go +++ b/lib/babe/verify_test.go @@ -757,7 +757,7 @@ func Test_verifier_verifyAuthorshipRightEquivocatory(t *testing.T) { babeVerifier8 := newTestVerifier(kp, mockBlockStateEquiv2, scale.MaxUint128, true) mockBlockStateEquiv2.EXPECT().GetHeader(hashEquivocatorySecondaryPlain).Return(headerEquivocatorySecondaryPlain, nil) - mockBlockStateEquiv2.EXPECT().GetBlockHashesBySlot(gomock.AssignableToTypeOf(uint64(0))).Return( + mockBlockStateEquiv2.EXPECT().GetBlockHashesBySlot(uint64(1)).Return( []common.Hash{hashEquivocatorySecondaryPlain, hashExisting}, nil) // Secondary Vrf Test Header From a99e5dd5702a4aaf03e734e93212375b548c1334 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Sat, 29 Oct 2022 08:58:41 +0530 Subject: [PATCH 32/40] addressed some more reviews --- dot/state/block.go | 2 +- dot/state/block_test.go | 7 ++++--- lib/babe/verify.go | 2 +- lib/babe/verify_test.go | 12 +++++++----- lib/blocktree/blocktree.go | 2 +- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/dot/state/block.go b/dot/state/block.go index 7215d126d9..ae89f12b7e 100644 --- a/dot/state/block.go +++ b/dot/state/block.go @@ -270,7 +270,7 @@ func (bs *BlockState) GetBlockHashesBySlot(slotNum uint64) ([]common.Hash, error continue } if err != nil { - return blocksWithGivenSlot, fmt.Errorf("could not get slot for block %s: %w", desc, err) + return nil, fmt.Errorf("could not get slot for block %s: %w", desc, err) } if descSlot == slotNum { diff --git a/dot/state/block_test.go b/dot/state/block_test.go index e115a18842..a0d064ad8f 100644 --- a/dot/state/block_test.go +++ b/dot/state/block_test.go @@ -196,6 +196,8 @@ func TestGetSlotForBlock(t *testing.T) { } func TestGetBlockHashesBySlot(t *testing.T) { + t.Parallel() + // create two block in the same slot and test if GetBlockHashesBySlot gets us // both the blocks bs := newTestBlockState(t, newTriesEmpty()) @@ -246,9 +248,8 @@ func TestGetBlockHashesBySlot(t *testing.T) { blocks, err := bs.GetBlockHashesBySlot(slot) require.NoError(t, err) - require.Equal(t, len(blocks), 2) - require.Contains(t, blocks, block.Header.Hash()) - require.Contains(t, blocks, block2.Header.Hash()) + + require.ElementsMatch(t, blocks, []common.Hash{block.Header.Hash(), block2.Header.Hash()}) } func TestIsBlockOnCurrentChain(t *testing.T) { diff --git a/lib/babe/verify.go b/lib/babe/verify.go index f059aae85e..57745a8e3e 100644 --- a/lib/babe/verify.go +++ b/lib/babe/verify.go @@ -354,7 +354,7 @@ func (b *verifier) verifyBlockEquivocation(header *types.Header) (bool, error) { blockHashesInSlot, err := b.blockState.GetBlockHashesBySlot(slot) if err != nil { - return false, fmt.Errorf("failed to get blocks produced in slot %d: %w", slot, err) + return false, fmt.Errorf("failed to get blocks produced in slot: %w", err) } for _, blockHashInSlot := range blockHashesInSlot { diff --git a/lib/babe/verify_test.go b/lib/babe/verify_test.go index 2d5b9e88d1..8bc9299c1a 100644 --- a/lib/babe/verify_test.go +++ b/lib/babe/verify_test.go @@ -647,14 +647,16 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { name: "valid digest items, getAuthorityIndex error", verifier: *babeVerifier5, header: header7, - expErr: fmt.Errorf("could not verify block equivocation: failed to get authority index for block %s: for block hash %s: %w", //nolint:lll + expErr: fmt.Errorf("could not verify block equivocation: "+ + "failed to get authority index for block %s: for block hash %s: %w", h, types.NewEmptyHeader().Hash(), errNoDigest), }, { name: "get header err", verifier: *babeVerifier6, header: header7, - expErr: fmt.Errorf("could not verify block equivocation: failed to get header for block %s: get header error", h), + expErr: fmt.Errorf("could not verify block equivocation:"+ + "failed to get header for block %s: get header error", h), }, } for _, tt := range tests { @@ -789,19 +791,19 @@ func Test_verifier_verifyAuthorshipRightEquivocatory(t *testing.T) { name: "equivocate - primary", verifier: *verifierEquivocatoryPrimary, header: headerEquivocatoryPrimary, - expErr: ErrProducerEquivocated, + expErr: fmt.Errorf("%w for block header %s", ErrProducerEquivocated, headerEquivocatoryPrimary.Hash()), }, { name: "equivocate - secondary plain", verifier: *babeVerifier8, header: headerEquivocatorySecondaryPlain, - expErr: ErrProducerEquivocated, + expErr: fmt.Errorf("%w for block header %s", ErrProducerEquivocated, headerEquivocatorySecondaryPlain.Hash()), }, { name: "equivocate - secondary vrf", verifier: *babeVerifierEquivocatorySecondaryVRF, header: headerEquivocatorySecondaryVRF, - expErr: ErrProducerEquivocated, + expErr: fmt.Errorf("%w for block header %s", ErrProducerEquivocated, headerEquivocatorySecondaryVRF.Hash()), }, } for _, tt := range tests { diff --git a/lib/blocktree/blocktree.go b/lib/blocktree/blocktree.go index 94a1e85c11..8470bb88ce 100644 --- a/lib/blocktree/blocktree.go +++ b/lib/blocktree/blocktree.go @@ -337,7 +337,7 @@ func (bt *BlockTree) GetAllDescendants(hash common.Hash) ([]Hash, error) { node := bt.getNode(hash) if node == nil { - return []common.Hash{}, fmt.Errorf("%w: for block hash %s", ErrNodeNotFound, hash) + return nil, fmt.Errorf("%w: for block hash %s", ErrNodeNotFound, hash) } return node.getAllDescendants(nil), nil From 004551e9e76033501f71cf2333c82b9c5be0a6a2 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Sat, 29 Oct 2022 09:51:23 +0530 Subject: [PATCH 33/40] test fix --- lib/babe/verify_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/babe/verify_test.go b/lib/babe/verify_test.go index 8e57c11933..fad585bea6 100644 --- a/lib/babe/verify_test.go +++ b/lib/babe/verify_test.go @@ -655,7 +655,7 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { name: "get header err", verifier: *babeVerifier6, header: header7, - expErr: fmt.Errorf("could not verify block equivocation:"+ + expErr: fmt.Errorf("could not verify block equivocation: "+ "failed to get header for block %s: get header error", h), }, } From d6dd61522fbaea3d606fb487f7600682fc78d369 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Sat, 29 Oct 2022 12:22:27 +0800 Subject: [PATCH 34/40] Update lib/babe/state.go Co-authored-by: Quentin McGaw --- lib/babe/state.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/babe/state.go b/lib/babe/state.go index f17781cf4c..973960b9de 100644 --- a/lib/babe/state.go +++ b/lib/babe/state.go @@ -28,7 +28,7 @@ type BlockState interface { GetHeader(common.Hash) (*types.Header, error) GetBlockByNumber(blockNumber uint) (*types.Block, error) GetBlockByHash(common.Hash) (*types.Block, error) - GetBlockHashesBySlot(uint64) ([]common.Hash, error) + GetBlockHashesBySlot(slot uint64) (blockHashes []common.Hash, err error) GetArrivalTime(common.Hash) (time.Time, error) GenesisHash() common.Hash GetSlotForBlock(common.Hash) (uint64, error) From eb60722755be5f485b4ae184c9ec9d8f9f005304 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Sat, 29 Oct 2022 10:21:27 +0530 Subject: [PATCH 35/40] one more test fix --- lib/babe/verify_integration_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/babe/verify_integration_test.go b/lib/babe/verify_integration_test.go index 4bb37dfd12..32685826fe 100644 --- a/lib/babe/verify_integration_test.go +++ b/lib/babe/verify_integration_test.go @@ -466,7 +466,7 @@ func TestVerifyAuthorshipRight_Equivocation(t *testing.T) { require.NoError(t, err) err = verifier.verifyAuthorshipRight(&block2.Header) - require.Equal(t, ErrProducerEquivocated, err) + require.Equal(t, fmt.Errorf("%w for block header %s", ErrProducerEquivocated, block2.Header.Hash()), err) } func TestVerifyForkBlocksWithRespectiveEpochData(t *testing.T) { From ee8d7ff41b757cbe0391efbb3c47c01451830a2c Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Mon, 31 Oct 2022 11:17:46 +0530 Subject: [PATCH 36/40] test for verifyBlockEquivocation --- lib/babe/verify_test.go | 137 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/lib/babe/verify_test.go b/lib/babe/verify_test.go index fad585bea6..9f18931e41 100644 --- a/lib/babe/verify_test.go +++ b/lib/babe/verify_test.go @@ -673,6 +673,143 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { } } +func Test_verifier_verifyBlockEquivocation(t *testing.T) { + ctrl := gomock.NewController(t) + + // Generate keys + kp, err := sr25519.GenerateKeypair() + assert.NoError(t, err) + + auth := types.NewAuthority(kp.Public(), uint64(1)) + vi := &verifierInfo{ + authorities: []types.Authority{*auth, *auth}, + threshold: scale.MaxUint128, + } + + // Case 1. could not get authority index from header + verifier1 := newVerifier(NewMockBlockState(ctrl), 1, vi) + testHeader1 := types.NewEmptyHeader() + + // Case 2. could not get slot from header + verifier2 := verifier1 + output, proof, err := kp.VrfSign(makeTranscript(Randomness{}, uint64(1), 1)) + assert.NoError(t, err) + + testDigest := types.BabePrimaryPreDigest{ + AuthorityIndex: 1, + SlotNumber: 1, + VRFOutput: output, + VRFProof: proof, + } + prd, err := testDigest.ToPreRuntimeDigest() + assert.NoError(t, err) + + testHeader2 := newTestHeader(t, *prd) + testHeader2.Number = 0 + + // Case 3. could not get block hashes by slot + testHeader3 := newTestHeader(t, *prd) + testHeader3.Number = 1 + + mockBlockState3 := NewMockBlockState(ctrl) + mockBlockState3.EXPECT().GetBlockHashesBySlot(uint64(1)).Return( + nil, errors.New("test error")) + + verifier3 := newVerifier(mockBlockState3, 1, vi) + + // Case 4. no equivocation on finding the same block + testHeader4 := newTestHeader(t, *prd) + testHeader4.Number = 1 + testHash4 := testHeader4.Hash() + mockBlockState4 := NewMockBlockState(ctrl) + mockBlockState4.EXPECT().GetBlockHashesBySlot(uint64(1)).Return( + []common.Hash{testHash4}, nil) + + verifier4 := newVerifier(mockBlockState4, 1, vi) + + // Case 5. claiming a slot twice results in equivocation + testHeader5 := newTestHeader(t, *prd) + testHeader5.Number = 1 + + output5, proof5, err := kp.VrfSign(makeTranscript(Randomness{}, uint64(1), 2)) + assert.NoError(t, err) + + testDigest5 := types.BabePrimaryPreDigest{ + AuthorityIndex: 1, + SlotNumber: 1, + VRFOutput: output5, + VRFProof: proof5, + } + prd5, err := testDigest5.ToPreRuntimeDigest() + assert.NoError(t, err) + + existingHeader := newTestHeader(t, *prd5) + mockBlockState5 := NewMockBlockState(ctrl) + mockBlockState5.EXPECT().GetBlockHashesBySlot(uint64(1)).Return( + []common.Hash{existingHeader.Hash()}, nil) + mockBlockState5.EXPECT().GetHeader(existingHeader.Hash()).Return( + existingHeader, nil) + + verifier5 := newVerifier(mockBlockState5, 1, vi) + + tests := []struct { + name string + verifier verifier + header *types.Header + equivocated bool + expErr error + }{ + { + name: "could not get authority index from header", + verifier: *verifier1, + header: testHeader1, + equivocated: false, + expErr: fmt.Errorf("failed to get authority index: for block hash %s: %w", testHeader1.Hash(), errNoDigest), + }, + { + name: "could not get slot from header", + verifier: *verifier2, + header: testHeader2, + equivocated: false, + expErr: fmt.Errorf("failed to get slot from header of block %s: %w", testHeader2.Hash(), types.ErrGenesisHeader), + }, + { + name: "could not get block hashes by slot", + verifier: *verifier3, + header: testHeader3, + equivocated: false, + expErr: fmt.Errorf("failed to get blocks produced in slot: test error"), + }, + { + name: "no equivocation on finding the same block", + verifier: *verifier4, + header: testHeader4, + equivocated: false, + expErr: nil, + }, + { + name: "claiming same slot twice results in equivocation", + verifier: *verifier5, + header: testHeader5, + equivocated: true, + expErr: nil, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt := tt + equivocated, err := tt.verifier.verifyBlockEquivocation(tt.header) + assert.Equal(t, equivocated, tt.equivocated) + if tt.expErr != nil { + assert.EqualError(t, err, tt.expErr.Error()) + } else { + assert.NoError(t, err) + } + }) + } +} + func Test_verifier_verifyAuthorshipRightEquivocatory(t *testing.T) { ctrl := gomock.NewController(t) From ad630b99332a5f1d36a4003a9e6b4ce114d1085f Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Mon, 31 Oct 2022 11:21:06 +0530 Subject: [PATCH 37/40] fix lint --- lib/babe/verify_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/babe/verify_test.go b/lib/babe/verify_test.go index 9f18931e41..6b76986f4e 100644 --- a/lib/babe/verify_test.go +++ b/lib/babe/verify_test.go @@ -771,7 +771,8 @@ func Test_verifier_verifyBlockEquivocation(t *testing.T) { verifier: *verifier2, header: testHeader2, equivocated: false, - expErr: fmt.Errorf("failed to get slot from header of block %s: %w", testHeader2.Hash(), types.ErrGenesisHeader), + expErr: fmt.Errorf("failed to get slot from header of block %s: %w", + testHeader2.Hash(), types.ErrGenesisHeader), }, { name: "could not get block hashes by slot", From 976624592b512978c40f19912e8bb09ca02526d4 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Tue, 1 Nov 2022 22:55:57 +0800 Subject: [PATCH 38/40] Update dot/state/block.go Co-authored-by: Quentin McGaw --- dot/state/block.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dot/state/block.go b/dot/state/block.go index ae89f12b7e..10513ec434 100644 --- a/dot/state/block.go +++ b/dot/state/block.go @@ -250,7 +250,7 @@ func (bs *BlockState) GetHashByNumber(num uint) (common.Hash, error) { return common.NewHash(bh), nil } -// GetBlockHashesBySlot gets all blocks that were produced in given slot. +// GetBlockHashesBySlot gets all block hashes that were produced in the given slot. func (bs *BlockState) GetBlockHashesBySlot(slotNum uint64) ([]common.Hash, error) { highestFinalisedHash, err := bs.GetHighestFinalisedHash() if err != nil { From 95531c9c786210ca7ca137af9e8c8fb641fac30f Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Tue, 1 Nov 2022 22:56:12 +0800 Subject: [PATCH 39/40] Update lib/babe/verify.go Co-authored-by: Quentin McGaw --- lib/babe/verify.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/babe/verify.go b/lib/babe/verify.go index 57745a8e3e..0f7dc0d08c 100644 --- a/lib/babe/verify.go +++ b/lib/babe/verify.go @@ -339,7 +339,7 @@ func (b *verifier) verifyAuthorshipRight(header *types.Header) error { } // verifyBlockEquivocation checks if the given block's author has occupied the corresponding slot more than once. -// It returns true if block was equivocated. +// It returns true if the block was equivocated. func (b *verifier) verifyBlockEquivocation(header *types.Header) (bool, error) { author, err := getAuthorityIndex(header) if err != nil { From 2dcb8cd200ef627cb87f858b509f4e03ff350b75 Mon Sep 17 00:00:00 2001 From: Kishan Sagathiya Date: Wed, 2 Nov 2022 09:30:32 +0530 Subject: [PATCH 40/40] addressed qdm12's comments --- dot/state/block.go | 4 ++-- lib/babe/verify.go | 2 +- lib/babe/verify_integration_test.go | 3 ++- lib/babe/verify_test.go | 19 +++++++++++-------- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/dot/state/block.go b/dot/state/block.go index ae89f12b7e..eb09953a0f 100644 --- a/dot/state/block.go +++ b/dot/state/block.go @@ -270,7 +270,7 @@ func (bs *BlockState) GetBlockHashesBySlot(slotNum uint64) ([]common.Hash, error continue } if err != nil { - return nil, fmt.Errorf("could not get slot for block %s: %w", desc, err) + return nil, fmt.Errorf("could not get slot for block: %w", err) } if descSlot == slotNum { @@ -536,7 +536,7 @@ func (bs *BlockState) BestBlock() (*types.Block, error) { func (bs *BlockState) GetSlotForBlock(hash common.Hash) (uint64, error) { header, err := bs.GetHeader(hash) if err != nil { - return 0, err + return 0, fmt.Errorf("getting header for hash %s: %w", hash, err) } return types.GetSlotFromHeader(header) diff --git a/lib/babe/verify.go b/lib/babe/verify.go index 57745a8e3e..b5ea94f08e 100644 --- a/lib/babe/verify.go +++ b/lib/babe/verify.go @@ -364,7 +364,7 @@ func (b *verifier) verifyBlockEquivocation(header *types.Header) (bool, error) { existingHeader, err := b.blockState.GetHeader(blockHashInSlot) if err != nil { - return false, fmt.Errorf("failed to get header for block %s: %w", blockHashInSlot, err) + return false, fmt.Errorf("failed to get header for block: %w", err) } authorOfExistingHeader, err := getAuthorityIndex(existingHeader) diff --git a/lib/babe/verify_integration_test.go b/lib/babe/verify_integration_test.go index 32685826fe..6679f69b0c 100644 --- a/lib/babe/verify_integration_test.go +++ b/lib/babe/verify_integration_test.go @@ -466,7 +466,8 @@ func TestVerifyAuthorshipRight_Equivocation(t *testing.T) { require.NoError(t, err) err = verifier.verifyAuthorshipRight(&block2.Header) - require.Equal(t, fmt.Errorf("%w for block header %s", ErrProducerEquivocated, block2.Header.Hash()), err) + require.ErrorIs(t, err, ErrProducerEquivocated) + require.EqualError(t, err, fmt.Sprintf("%s for block header %s", ErrProducerEquivocated, block2.Header.Hash())) } func TestVerifyForkBlocksWithRespectiveEpochData(t *testing.T) { diff --git a/lib/babe/verify_test.go b/lib/babe/verify_test.go index 6b76986f4e..a6168b0349 100644 --- a/lib/babe/verify_test.go +++ b/lib/babe/verify_test.go @@ -655,8 +655,8 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { name: "get header err", verifier: *babeVerifier6, header: header7, - expErr: fmt.Errorf("could not verify block equivocation: "+ - "failed to get header for block %s: get header error", h), + expErr: fmt.Errorf("could not verify block equivocation: " + + "failed to get header for block: get header error"), }, } for _, tt := range tests { @@ -674,7 +674,7 @@ func Test_verifier_verifyAuthorshipRight(t *testing.T) { } func Test_verifier_verifyBlockEquivocation(t *testing.T) { - ctrl := gomock.NewController(t) + t.Parallel() // Generate keys kp, err := sr25519.GenerateKeypair() @@ -687,7 +687,7 @@ func Test_verifier_verifyBlockEquivocation(t *testing.T) { } // Case 1. could not get authority index from header - verifier1 := newVerifier(NewMockBlockState(ctrl), 1, vi) + verifier1 := newVerifier(NewMockBlockState(gomock.NewController(t)), 1, vi) testHeader1 := types.NewEmptyHeader() // Case 2. could not get slot from header @@ -711,7 +711,7 @@ func Test_verifier_verifyBlockEquivocation(t *testing.T) { testHeader3 := newTestHeader(t, *prd) testHeader3.Number = 1 - mockBlockState3 := NewMockBlockState(ctrl) + mockBlockState3 := NewMockBlockState(gomock.NewController(t)) mockBlockState3.EXPECT().GetBlockHashesBySlot(uint64(1)).Return( nil, errors.New("test error")) @@ -721,7 +721,7 @@ func Test_verifier_verifyBlockEquivocation(t *testing.T) { testHeader4 := newTestHeader(t, *prd) testHeader4.Number = 1 testHash4 := testHeader4.Hash() - mockBlockState4 := NewMockBlockState(ctrl) + mockBlockState4 := NewMockBlockState(gomock.NewController(t)) mockBlockState4.EXPECT().GetBlockHashesBySlot(uint64(1)).Return( []common.Hash{testHash4}, nil) @@ -744,7 +744,7 @@ func Test_verifier_verifyBlockEquivocation(t *testing.T) { assert.NoError(t, err) existingHeader := newTestHeader(t, *prd5) - mockBlockState5 := NewMockBlockState(ctrl) + mockBlockState5 := NewMockBlockState(gomock.NewController(t)) mockBlockState5.EXPECT().GetBlockHashesBySlot(uint64(1)).Return( []common.Hash{existingHeader.Hash()}, nil) mockBlockState5.EXPECT().GetHeader(existingHeader.Hash()).Return( @@ -798,8 +798,11 @@ func Test_verifier_verifyBlockEquivocation(t *testing.T) { } for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { - tt := tt + t.Parallel() + equivocated, err := tt.verifier.verifyBlockEquivocation(tt.header) assert.Equal(t, equivocated, tt.equivocated) if tt.expErr != nil {