diff --git a/lib/babe/helpers_test.go b/lib/babe/helpers_test.go index 697103cf6f..b49fd3b45a 100644 --- a/lib/babe/helpers_test.go +++ b/lib/babe/helpers_test.go @@ -184,6 +184,8 @@ func createTestService(t *testing.T, cfg ServiceConfig, genesis genesis.Genesis, dbSrv := state.NewService(config) dbSrv.UseMemDB() + dbSrv.Transaction = state.NewTransactionState(telemetryMock) + err := dbSrv.Initialise(&genesis, &genesisHeader, &genesisTrie) require.NoError(t, err) @@ -215,6 +217,7 @@ func createTestService(t *testing.T, cfg ServiceConfig, genesis genesis.Genesis, nodeStorage.BaseDB = dbSrv.Base rtCfg.NodeStorage = nodeStorage + rtCfg.Transaction = dbSrv.Transaction runtime, err := wasmer.NewRuntimeFromGenesis(rtCfg) require.NoError(t, err) cfg.BlockState.(*state.BlockState).StoreRuntime(cfg.BlockState.BestBlockHash(), runtime) diff --git a/lib/babe/verify.go b/lib/babe/verify.go index 3b8d98360d..485febe461 100644 --- a/lib/babe/verify.go +++ b/lib/babe/verify.go @@ -4,6 +4,7 @@ package babe import ( + "errors" "fmt" "sync" @@ -13,6 +14,8 @@ import ( "github.com/ChainSafe/gossamer/pkg/scale" ) +var errEmptyKeyOwnershipProof = errors.New("key ownership proof is nil") + // verifierInfo contains the information needed to verify blocks // it remains the same for an epoch type verifierInfo struct { @@ -360,6 +363,8 @@ func (b *verifier) submitAndReportEquivocation( keyOwnershipProof, err := runtimeInstance.BabeGenerateKeyOwnershipProof(slot, offenderPublicKey) if err != nil { return fmt.Errorf("getting key ownership proof from runtime: %w", err) + } else if keyOwnershipProof == nil { + return errEmptyKeyOwnershipProof } equivocationProof := &types.BabeEquivocationProof{ diff --git a/lib/babe/verify_integration_test.go b/lib/babe/verify_integration_test.go index 3c864f91ef..bb0f2f8cbc 100644 --- a/lib/babe/verify_integration_test.go +++ b/lib/babe/verify_integration_test.go @@ -433,18 +433,11 @@ func TestVerifyAuthorshipRight(t *testing.T) { require.NoError(t, err) } -// TODO this test failing is related too issue #3136 func TestVerifyAuthorshipRight_Equivocation(t *testing.T) { - t.Skip() - kp, err := sr25519.GenerateKeypair() - require.NoError(t, err) - - cfg := ServiceConfig{ - Keypair: kp, - } - genesis, genesisTrie, genesisHeader := newWestendDevGenesisWithTrieAndHeader(t) - babeService := createTestService(t, cfg, genesis, genesisTrie, genesisHeader, nil) + babeService := createTestService(t, ServiceConfig{}, genesis, genesisTrie, genesisHeader, nil) + verificationManager := NewVerificationManager(babeService.blockState, babeService.epochState) + epochData, err := babeService.initiateEpoch(testEpochIndex) require.NoError(t, err) @@ -452,19 +445,6 @@ func TestVerifyAuthorshipRight_Equivocation(t *testing.T) { runtime, err := babeService.blockState.GetRuntime(bestBlockHash) require.NoError(t, err) - epochData.threshold = maxThreshold - epochData.authorities = []types.Authority{ - { - Key: kp.Public().(*sr25519.PublicKey), - }, - } - - verifier := newVerifier(babeService.blockState, testEpochIndex, &verifierInfo{ - authorities: epochData.authorities, - threshold: epochData.threshold, - randomness: epochData.randomness, - }) - // slots are 6 seconds on westend and using time.Now() allows us to create a block at any point in the slot. // So we need to manually set time to produce consistent results. See here: // https://github.com/paritytech/substrate/blob/09de7b41599add51cf27eca8f1bc4c50ed8e9453/frame/timestamp/src/lib.rs#L229 @@ -481,13 +461,13 @@ func TestVerifyAuthorshipRight_Equivocation(t *testing.T) { err = babeService.blockState.AddBlock(block) require.NoError(t, err) - err = verifier.verifyAuthorshipRight(&block.Header) + err = verificationManager.VerifyBlock(&block.Header) require.NoError(t, err) err = babeService.blockState.AddBlock(block2) require.NoError(t, err) - err = verifier.verifyAuthorshipRight(&block2.Header) + err = verificationManager.VerifyBlock(&block2.Header) require.ErrorIs(t, err, ErrProducerEquivocated) require.EqualError(t, err, fmt.Sprintf("%s for block header %s", ErrProducerEquivocated, block2.Header.Hash())) } diff --git a/lib/grandpa/vote_message.go b/lib/grandpa/vote_message.go index 43ba96ee60..d8efeb7ce7 100644 --- a/lib/grandpa/vote_message.go +++ b/lib/grandpa/vote_message.go @@ -17,7 +17,10 @@ import ( "github.com/libp2p/go-libp2p/core/peer" ) -var errBeforeFinalizedBlock = errors.New("before latest finalized block") +var ( + errBeforeFinalizedBlock = errors.New("before latest finalized block") + errEmptyKeyOwnershipProof = errors.New("key ownership proof is nil") +) type networkVoteMessage struct { from peer.ID @@ -284,6 +287,8 @@ func (s *Service) reportEquivocation(stage Subround, existingVote *SignedVote, c opaqueKeyOwnershipProof, err := runtime.GrandpaGenerateKeyOwnershipProof(setID, pubKey) if err != nil { return fmt.Errorf("getting key ownership proof: %w", err) + } else if opaqueKeyOwnershipProof == nil { + return errEmptyKeyOwnershipProof } grandpaEquivocation := types.GrandpaEquivocation{ diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go index b7298cb574..9ba3f026b9 100644 --- a/lib/runtime/wasmer/exports.go +++ b/lib/runtime/wasmer/exports.go @@ -110,13 +110,17 @@ func (in *Instance) BabeGenerateKeyOwnershipProof(slot uint64, authorityID [32]b return nil, fmt.Errorf("executing %s: %w", runtime.BabeAPIGenerateKeyOwnershipProof, err) } - keyOwnershipProof := types.OpaqueKeyOwnershipProof{} + var keyOwnershipProof *types.OpaqueKeyOwnershipProof err = scale.Unmarshal(encodedKeyOwnershipProof, &keyOwnershipProof) if err != nil { return nil, fmt.Errorf("scale decoding key ownership proof: %w", err) } - return keyOwnershipProof, nil + if keyOwnershipProof == nil { + return nil, nil + } + + return *keyOwnershipProof, nil } // BabeSubmitReportEquivocationUnsignedExtrinsic reports equivocation report to the runtime. @@ -297,13 +301,17 @@ func (in *Instance) GrandpaGenerateKeyOwnershipProof(authSetID uint64, authority return nil, err } - keyOwnershipProof := types.GrandpaOpaqueKeyOwnershipProof{} + var keyOwnershipProof *types.GrandpaOpaqueKeyOwnershipProof err = scale.Unmarshal(encodedOpaqueKeyOwnershipProof, &keyOwnershipProof) if err != nil { return nil, fmt.Errorf("scale decoding: %w", err) } - return keyOwnershipProof, nil + if keyOwnershipProof == nil { + return nil, nil + } + + return *keyOwnershipProof, nil } // GrandpaSubmitReportEquivocationUnsignedExtrinsic reports an equivocation report to the runtime. diff --git a/lib/runtime/wasmer/exports_test.go b/lib/runtime/wasmer/exports_test.go index a6da3188ac..890026ff4f 100644 --- a/lib/runtime/wasmer/exports_test.go +++ b/lib/runtime/wasmer/exports_test.go @@ -161,7 +161,7 @@ func balanceKey(t *testing.T, pub []byte) []byte { return append(append(append(h0, h1...), h2...), pub...) } -func TestNodeRuntime_ValidateTransaction(t *testing.T) { +func TestWestendRuntime_ValidateTransaction(t *testing.T) { genesisPath := utils.GetWestendDevRawGenesisPath(t) gen := genesisFromRawJSON(t, genesisPath) genTrie, err := NewTrieFromGenesis(gen) @@ -316,8 +316,9 @@ func TestInstance_BabeGenerateKeyOwnershipProof(t *testing.T) { authorityID := babeConfig.GenesisAuthorities[0].Key const slot = uint64(10) - _, err = rt.BabeGenerateKeyOwnershipProof(slot, authorityID) + res, err := rt.BabeGenerateKeyOwnershipProof(slot, authorityID) require.NoError(t, err) + require.Nil(t, res) }) } } @@ -1103,10 +1104,10 @@ func TestInstance_GrandpaGenerateKeyOwnershipProof(t *testing.T) { identityPubKey, _ := ed25519.NewPublicKey(identity) authorityID := identityPubKey.AsBytes() - encodedOpaqueKeyOwnershipProof, err := instance.GrandpaGenerateKeyOwnershipProof(uint64(0), authorityID) - require.NoError(t, err) + opaqueKeyOwnershipProof, err := instance.GrandpaGenerateKeyOwnershipProof(uint64(0), authorityID) // Since the input is not valid with respect to the instance, an empty proof is returned - require.Empty(t, encodedOpaqueKeyOwnershipProof) + require.NoError(t, err) + require.Nil(t, opaqueKeyOwnershipProof) } func TestInstance_GrandpaSubmitReportEquivocationUnsignedExtrinsic(t *testing.T) {