From a179855cd2ed7614e94c090e80111d2bc3ea365c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ecl=C3=A9sio=20Junior?= Date: Thu, 15 Jun 2023 15:43:39 -0400 Subject: [PATCH] fix(dot/digest): create `BlockImportHandler` and remove channel (#3312) --- dot/core/interfaces.go | 4 + dot/core/messages_integration_test.go | 9 ++ dot/core/mocks_generate_test.go | 2 +- dot/core/mocks_test.go | 39 ++++- dot/core/service.go | 10 +- dot/core/service_integration_test.go | 8 + dot/core/service_test.go | 36 +++-- dot/digest/block_import.go | 146 ++++++++++++++++++ dot/digest/digest.go | 196 +------------------------ dot/digest/digest_integration_test.go | 44 +++--- dot/digest/interfaces.go | 4 +- dot/digest/mock_epoch_state_test.go | 28 ++-- dot/mock_node_builder_test.go | 9 +- dot/node.go | 8 +- dot/node_integration_test.go | 2 +- dot/services.go | 5 +- dot/services_integration_test.go | 24 +-- dot/state/epoch.go | 51 ++++++- dot/state/epoch_test.go | 4 +- lib/babe/helpers_test.go | 4 + lib/babe/mocks/{network.go => core.go} | 40 ++++- lib/babe/mocks_generate_test.go | 2 +- lib/babe/verify_integration_test.go | 15 +- 23 files changed, 402 insertions(+), 288 deletions(-) create mode 100644 dot/digest/block_import.go rename lib/babe/mocks/{network.go => core.go} (61%) diff --git a/dot/core/interfaces.go b/dot/core/interfaces.go index 79d0f25925..3b66b88522 100644 --- a/dot/core/interfaces.go +++ b/dot/core/interfaces.go @@ -19,6 +19,10 @@ import ( "github.com/ChainSafe/gossamer/lib/transaction" ) +type BlockImportDigestHandler interface { + Handle(*types.Header) error +} + // BlockState interface for block state methods type BlockState interface { BestBlockHash() common.Hash diff --git a/dot/core/messages_integration_test.go b/dot/core/messages_integration_test.go index 038e5dfb9b..12dde72647 100644 --- a/dot/core/messages_integration_test.go +++ b/dot/core/messages_integration_test.go @@ -104,6 +104,11 @@ func TestService_HandleBlockProduced(t *testing.T) { Body: *types.NewBody([]types.Extrinsic{}), } + onBlockImportHandlerMock := NewMockBlockImportDigestHandler(ctrl) + onBlockImportHandlerMock.EXPECT().Handle(&newBlock.Header).Return(nil) + + s.onBlockImport = onBlockImportHandlerMock + expected := &network.BlockAnnounceMessage{ ParentHash: newBlock.Header.ParentHash, Number: newBlock.Header.Number, @@ -172,6 +177,10 @@ func TestService_HandleTransactionMessage(t *testing.T) { currentSlot := currentTimestamp / babeConfig.SlotDuration block := buildTestBlockWithoutExtrinsics(t, rt, genHeader, currentSlot, currentTimestamp) + onBlockImportDigestHandlerMock := NewMockBlockImportDigestHandler(ctrl) + onBlockImportDigestHandlerMock.EXPECT().Handle(&block.Header).Return(nil) + + s.onBlockImport = onBlockImportDigestHandlerMock err = s.handleBlock(block, ts) require.NoError(t, err) diff --git a/dot/core/mocks_generate_test.go b/dot/core/mocks_generate_test.go index fae8ae0c25..c36531f0f8 100644 --- a/dot/core/mocks_generate_test.go +++ b/dot/core/mocks_generate_test.go @@ -3,5 +3,5 @@ package core -//go:generate mockgen -destination=mocks_test.go -package $GOPACKAGE . BlockState,StorageState,TransactionState,Network,CodeSubstitutedState,Telemetry +//go:generate mockgen -destination=mocks_test.go -package $GOPACKAGE . BlockState,StorageState,TransactionState,Network,CodeSubstitutedState,Telemetry,BlockImportDigestHandler //go:generate mockgen -destination=mock_runtime_instance_test.go -package $GOPACKAGE github.com/ChainSafe/gossamer/lib/runtime Instance diff --git a/dot/core/mocks_test.go b/dot/core/mocks_test.go index 896859d0f8..dad47f2139 100644 --- a/dot/core/mocks_test.go +++ b/dot/core/mocks_test.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/ChainSafe/gossamer/dot/core (interfaces: BlockState,StorageState,TransactionState,Network,CodeSubstitutedState,Telemetry) +// Source: github.com/ChainSafe/gossamer/dot/core (interfaces: BlockState,StorageState,TransactionState,Network,CodeSubstitutedState,Telemetry,BlockImportDigestHandler) // Package core is a generated GoMock package. package core @@ -528,3 +528,40 @@ func (mr *MockTelemetryMockRecorder) SendMessage(arg0 interface{}) *gomock.Call mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMessage", reflect.TypeOf((*MockTelemetry)(nil).SendMessage), arg0) } + +// MockBlockImportDigestHandler is a mock of BlockImportDigestHandler interface. +type MockBlockImportDigestHandler struct { + ctrl *gomock.Controller + recorder *MockBlockImportDigestHandlerMockRecorder +} + +// MockBlockImportDigestHandlerMockRecorder is the mock recorder for MockBlockImportDigestHandler. +type MockBlockImportDigestHandlerMockRecorder struct { + mock *MockBlockImportDigestHandler +} + +// NewMockBlockImportDigestHandler creates a new mock instance. +func NewMockBlockImportDigestHandler(ctrl *gomock.Controller) *MockBlockImportDigestHandler { + mock := &MockBlockImportDigestHandler{ctrl: ctrl} + mock.recorder = &MockBlockImportDigestHandlerMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockBlockImportDigestHandler) EXPECT() *MockBlockImportDigestHandlerMockRecorder { + return m.recorder +} + +// Handle mocks base method. +func (m *MockBlockImportDigestHandler) Handle(arg0 *types.Header) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Handle", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// Handle indicates an expected call of Handle. +func (mr *MockBlockImportDigestHandlerMockRecorder) Handle(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Handle", reflect.TypeOf((*MockBlockImportDigestHandler)(nil).Handle), arg0) +} diff --git a/dot/core/service.go b/dot/core/service.go index 4a2aaa8b65..db95841b28 100644 --- a/dot/core/service.go +++ b/dot/core/service.go @@ -52,7 +52,8 @@ type Service struct { codeSubstitutedState CodeSubstitutedState // Keystore - keys *keystore.GlobalKeystore + keys *keystore.GlobalKeystore + onBlockImport BlockImportDigestHandler } // Config holds the configuration for the core Service. @@ -68,6 +69,7 @@ type Config struct { CodeSubstitutes map[common.Hash]string CodeSubstitutedState CodeSubstitutedState + OnBlockImport BlockImportDigestHandler } // NewService returns a new core service that connects the runtime, BABE @@ -89,6 +91,7 @@ func NewService(cfg *Config) (*Service, error) { blockAddCh: blockAddCh, codeSubstitute: cfg.CodeSubstitutes, codeSubstitutedState: cfg.CodeSubstitutedState, + onBlockImport: cfg.OnBlockImport, } return srv, nil @@ -209,6 +212,11 @@ func (s *Service) handleBlock(block *types.Block, state *rtstorage.TrieState) er } } + err = s.onBlockImport.Handle(&block.Header) + if err != nil { + return fmt.Errorf("on block import handle: %w", err) + } + logger.Debugf("imported block %s and stored state trie with root %s", block.Header.Hash(), state.MustRoot()) diff --git a/dot/core/service_integration_test.go b/dot/core/service_integration_test.go index 00956528fd..ecd72a28b6 100644 --- a/dot/core/service_integration_test.go +++ b/dot/core/service_integration_test.go @@ -76,6 +76,10 @@ func TestAnnounceBlock(t *testing.T) { Body: *types.NewBody([]types.Extrinsic{}), } + onBlockImportHandleMock := NewMockBlockImportDigestHandler(ctrl) + onBlockImportHandleMock.EXPECT().Handle(&newBlock.Header).Return(nil) + s.onBlockImport = onBlockImportHandleMock + expected := &network.BlockAnnounceMessage{ ParentHash: newBlock.Header.ParentHash, Number: newBlock.Header.Number, @@ -481,6 +485,10 @@ func TestService_HandleSubmittedExtrinsic(t *testing.T) { block := buildTestBlockWithoutExtrinsics(t, rt, genHeader, currentSlotNumber, currentTimestamp) + onBlockImportHandlerMock := NewMockBlockImportDigestHandler(ctrl) + onBlockImportHandlerMock.EXPECT().Handle(&block.Header).Return(nil) + s.onBlockImport = onBlockImportHandlerMock + err = s.handleBlock(block, ts) require.NoError(t, err) diff --git a/dot/core/service_test.go b/dot/core/service_test.go index 66ee3a8485..db1659faf2 100644 --- a/dot/core/service_test.go +++ b/dot/core/service_test.go @@ -423,9 +423,13 @@ func Test_Service_handleBlock(t *testing.T) { mockBlockState.EXPECT().AddBlock(&block).Return(blocktree.ErrBlockExists) mockBlockState.EXPECT().GetRuntime(block.Header.ParentHash).Return(nil, errTestDummyError) + onBlockImportHandlerMock := NewMockBlockImportDigestHandler(ctrl) + onBlockImportHandlerMock.EXPECT().Handle(&block.Header).Return(nil) + service := &Service{ - storageState: mockStorageState, - blockState: mockBlockState, + storageState: mockStorageState, + blockState: mockBlockState, + onBlockImport: onBlockImportHandlerMock, } execTest(t, service, &block, trieState, errTestDummyError) }) @@ -448,9 +452,13 @@ func Test_Service_handleBlock(t *testing.T) { mockBlockState.EXPECT().HandleRuntimeChanges(trieState, runtimeMock, block.Header.Hash()). Return(errTestDummyError) + onBlockImportHandlerMock := NewMockBlockImportDigestHandler(ctrl) + onBlockImportHandlerMock.EXPECT().Handle(&block.Header).Return(nil) + service := &Service{ - storageState: mockStorageState, - blockState: mockBlockState, + storageState: mockStorageState, + blockState: mockBlockState, + onBlockImport: onBlockImportHandlerMock, } execTest(t, service, &block, trieState, errTestDummyError) }) @@ -472,10 +480,13 @@ func Test_Service_handleBlock(t *testing.T) { mockBlockState.EXPECT().GetRuntime(block.Header.ParentHash).Return(runtimeMock, nil) mockBlockState.EXPECT().HandleRuntimeChanges(trieState, runtimeMock, block.Header.Hash()).Return(nil) + onBlockImportHandlerMock := NewMockBlockImportDigestHandler(ctrl) + onBlockImportHandlerMock.EXPECT().Handle(&block.Header).Return(nil) service := &Service{ - storageState: mockStorageState, - blockState: mockBlockState, - ctx: context.Background(), + storageState: mockStorageState, + blockState: mockBlockState, + ctx: context.Background(), + onBlockImport: onBlockImportHandlerMock, } execTest(t, service, &block, trieState, nil) }) @@ -531,12 +542,15 @@ func Test_Service_HandleBlockProduced(t *testing.T) { mockBlockState.EXPECT().HandleRuntimeChanges(trieState, runtimeMock, block.Header.Hash()).Return(nil) mockNetwork := NewMockNetwork(ctrl) mockNetwork.EXPECT().GossipMessage(msg) + onBlockImportHandlerMock := NewMockBlockImportDigestHandler(ctrl) + onBlockImportHandlerMock.EXPECT().Handle(&block.Header).Return(nil) service := &Service{ - storageState: mockStorageState, - blockState: mockBlockState, - net: mockNetwork, - ctx: context.Background(), + storageState: mockStorageState, + blockState: mockBlockState, + net: mockNetwork, + ctx: context.Background(), + onBlockImport: onBlockImportHandlerMock, } execTest(t, service, &block, trieState, nil) }) diff --git a/dot/digest/block_import.go b/dot/digest/block_import.go new file mode 100644 index 0000000000..56ac4f7d49 --- /dev/null +++ b/dot/digest/block_import.go @@ -0,0 +1,146 @@ +// Copyright 2023 ChainSafe Systems (ON) +// SPDX-License-Identifier: LGPL-3.0-only + +package digest + +import ( + "fmt" + + "github.com/ChainSafe/gossamer/dot/types" + "github.com/ChainSafe/gossamer/pkg/scale" +) + +type BlockImportHandler struct { + epochState EpochState + grandpaState GrandpaState +} + +func NewBlockImportHandler(epochState EpochState, grandpaState GrandpaState) *BlockImportHandler { + return &BlockImportHandler{ + epochState: epochState, + grandpaState: grandpaState, + } +} + +func (h *BlockImportHandler) Handle(importedBlockHeader *types.Header) error { + err := h.handleDigests(importedBlockHeader) + if err != nil { + return fmt.Errorf("while handling digests: %w", err) + } + + // TODO: move to core handleBlock + // https://github.com/ChainSafe/gossamer/issues/3330 + err = h.grandpaState.ApplyForcedChanges(importedBlockHeader) + if err != nil { + return fmt.Errorf("while apply forced changes: %s", err) + } + + return nil +} + +// HandleDigests handles consensus digests for an imported block +func (h *BlockImportHandler) handleDigests(header *types.Header) error { + consensusDigests := toConsensusDigests(header.Digest.Types) + consensusDigests, err := checkForGRANDPAForcedChanges(consensusDigests) + if err != nil { + return fmt.Errorf("failed while checking GRANDPA digests: %w", err) + } + + for i := range consensusDigests { + // avoiding implicit memory aliasing in for loop, since: + // for _, digest := range consensusDigests { &digest } + // is using the address of a loop variable + digest := consensusDigests[i] + err := h.handleConsensusDigest(&digest, header) + if err != nil { + logger.Errorf("cannot handle consensus digest: %w", err) + } + } + + return nil +} + +func (h *BlockImportHandler) handleConsensusDigest(d *types.ConsensusDigest, header *types.Header) error { + switch d.ConsensusEngineID { + case types.GrandpaEngineID: + data := types.NewGrandpaConsensusDigest() + err := scale.Unmarshal(d.Data, &data) + if err != nil { + return err + } + + return h.grandpaState.HandleGRANDPADigest(header, data) + case types.BabeEngineID: + data := types.NewBabeConsensusDigest() + err := scale.Unmarshal(d.Data, &data) + if err != nil { + return err + } + + return h.epochState.HandleBABEDigest(header, data) + default: + return fmt.Errorf("%w: 0x%x", ErrUnknownConsensusEngineID, d.ConsensusEngineID.ToBytes()) + } +} + +// toConsensusDigests converts a slice of scale.VaryingDataType to a slice of types.ConsensusDigest. +func toConsensusDigests(scaleVaryingTypes []scale.VaryingDataType) []types.ConsensusDigest { + consensusDigests := make([]types.ConsensusDigest, 0, len(scaleVaryingTypes)) + + for _, d := range scaleVaryingTypes { + digestValue, err := d.Value() + if err != nil { + logger.Error(err.Error()) + continue + } + digest, ok := digestValue.(types.ConsensusDigest) + if !ok { + continue + } + + switch digest.ConsensusEngineID { + case types.GrandpaEngineID, types.BabeEngineID: + consensusDigests = append(consensusDigests, digest) + } + } + + return consensusDigests +} + +// checkForGRANDPAForcedChanges removes any GrandpaScheduledChange in the presence of a +// GrandpaForcedChange in the same block digest, returning a new slice of types.ConsensusDigest +func checkForGRANDPAForcedChanges(digests []types.ConsensusDigest) ([]types.ConsensusDigest, error) { + var hasForcedChange bool + digestsWithoutScheduled := make([]types.ConsensusDigest, 0, len(digests)) + for i, digest := range digests { + if digest.ConsensusEngineID != types.GrandpaEngineID { + digestsWithoutScheduled = append(digestsWithoutScheduled, digest) + continue + } + + data := types.NewGrandpaConsensusDigest() + err := scale.Unmarshal(digest.Data, &data) + if err != nil { + return nil, fmt.Errorf("cannot unmarshal GRANDPA consensus digest: %w", err) + } + + dataValue, err := data.Value() + if err != nil { + return nil, fmt.Errorf("getting value of digest type at index %d: %w", i, err) + } + switch dataValue.(type) { + case types.GrandpaScheduledChange: + case types.GrandpaForcedChange: + hasForcedChange = true + digestsWithoutScheduled = append(digestsWithoutScheduled, digest) + default: + digestsWithoutScheduled = append(digestsWithoutScheduled, digest) + } + } + + if hasForcedChange { + return digestsWithoutScheduled, nil + } + + return digests, nil +} diff --git a/dot/digest/digest.go b/dot/digest/digest.go index 8015cad053..5ba27adb00 100644 --- a/dot/digest/digest.go +++ b/dot/digest/digest.go @@ -6,13 +6,13 @@ package digest import ( "context" "errors" - "fmt" "github.com/ChainSafe/gossamer/dot/types" "github.com/ChainSafe/gossamer/internal/log" - "github.com/ChainSafe/gossamer/pkg/scale" ) +var logger = log.NewFromGlobal(log.AddContext("pkg", "digest")) + var ( ErrUnknownConsensusEngineID = errors.New("unknown consensus engine ID") ) @@ -30,19 +30,14 @@ type Handler struct { // block notification channels imported chan *types.Block finalised chan *types.FinalisationInfo - - logger Logger } // NewHandler returns a new Handler -func NewHandler(lvl log.Level, blockState BlockState, epochState EpochState, +func NewHandler(blockState BlockState, epochState EpochState, grandpaState GrandpaState) (*Handler, error) { imported := blockState.GetImportedBlockNotifierChannel() finalised := blockState.GetFinalisedNotifierChannel() - logger := log.NewFromGlobal(log.AddContext("pkg", "digest")) - logger.Patch(log.SetLevel(lvl)) - ctx, cancel := context.WithCancel(context.Background()) return &Handler{ ctx: ctx, @@ -52,13 +47,11 @@ func NewHandler(lvl log.Level, blockState BlockState, epochState EpochState, grandpaState: grandpaState, imported: imported, finalised: finalised, - logger: logger, }, nil } // Start starts the Handler func (h *Handler) Start() error { - go h.handleBlockImport(h.ctx) go h.handleBlockFinalisation(h.ctx) return nil } @@ -71,183 +64,6 @@ func (h *Handler) Stop() error { return nil } -// HandleDigests handles consensus digests for an imported block -func (h *Handler) HandleDigests(header *types.Header) error { - consensusDigests := h.toConsensusDigests(header.Digest.Types) - consensusDigests, err := checkForGRANDPAForcedChanges(consensusDigests) - if err != nil { - return fmt.Errorf("failed while checking GRANDPA digests: %w", err) - } - - for i := range consensusDigests { - // avoiding implicit memory aliasing in for loop, since: - // for _, digest := range consensusDigests { &digest } - // is using the address of a loop variable - digest := consensusDigests[i] - err := h.handleConsensusDigest(&digest, header) - if err != nil { - h.logger.Errorf("cannot handle consensus digest: %w", err) - } - } - - return nil -} - -// toConsensusDigests converts a slice of scale.VaryingDataType to a slice of types.ConsensusDigest. -func (h *Handler) toConsensusDigests(scaleVaryingTypes []scale.VaryingDataType) []types.ConsensusDigest { - consensusDigests := make([]types.ConsensusDigest, 0, len(scaleVaryingTypes)) - - for _, d := range scaleVaryingTypes { - digestValue, err := d.Value() - if err != nil { - h.logger.Error(err.Error()) - continue - } - digest, ok := digestValue.(types.ConsensusDigest) - if !ok { - continue - } - - switch digest.ConsensusEngineID { - case types.GrandpaEngineID, types.BabeEngineID: - consensusDigests = append(consensusDigests, digest) - } - } - - return consensusDigests -} - -// checkForGRANDPAForcedChanges removes any GrandpaScheduledChange in the presence of a -// GrandpaForcedChange in the same block digest, returning a new slice of types.ConsensusDigest -func checkForGRANDPAForcedChanges(digests []types.ConsensusDigest) ([]types.ConsensusDigest, error) { - var hasForcedChange bool - digestsWithoutScheduled := make([]types.ConsensusDigest, 0, len(digests)) - for i, digest := range digests { - if digest.ConsensusEngineID != types.GrandpaEngineID { - digestsWithoutScheduled = append(digestsWithoutScheduled, digest) - continue - } - - data := types.NewGrandpaConsensusDigest() - err := scale.Unmarshal(digest.Data, &data) - if err != nil { - return nil, fmt.Errorf("cannot unmarshal GRANDPA consensus digest: %w", err) - } - - dataValue, err := data.Value() - if err != nil { - return nil, fmt.Errorf("getting value of digest type at index %d: %w", i, err) - } - switch dataValue.(type) { - case types.GrandpaScheduledChange: - case types.GrandpaForcedChange: - hasForcedChange = true - digestsWithoutScheduled = append(digestsWithoutScheduled, digest) - default: - digestsWithoutScheduled = append(digestsWithoutScheduled, digest) - } - } - - if hasForcedChange { - return digestsWithoutScheduled, nil - } - - return digests, nil -} - -func (h *Handler) handleConsensusDigest(d *types.ConsensusDigest, header *types.Header) error { - switch d.ConsensusEngineID { - case types.GrandpaEngineID: - data := types.NewGrandpaConsensusDigest() - err := scale.Unmarshal(d.Data, &data) - if err != nil { - return err - } - - return h.grandpaState.HandleGRANDPADigest(header, data) - case types.BabeEngineID: - data := types.NewBabeConsensusDigest() - err := scale.Unmarshal(d.Data, &data) - if err != nil { - return err - } - - return h.handleBabeConsensusDigest(data, header) - default: - return fmt.Errorf("%w: 0x%x", ErrUnknownConsensusEngineID, d.ConsensusEngineID.ToBytes()) - } -} - -func (h *Handler) handleBabeConsensusDigest(digest scale.VaryingDataType, header *types.Header) error { - headerHash := header.Hash() - - digestValue, err := digest.Value() - if err != nil { - return fmt.Errorf("getting digest value: %w", err) - } - switch val := digestValue.(type) { - case types.NextEpochData: - currEpoch, err := h.epochState.GetEpochForBlock(header) - if err != nil { - return fmt.Errorf("getting epoch for block %d (%s): %w", - header.Number, headerHash, err) - } - - nextEpoch := currEpoch + 1 - h.epochState.StoreBABENextEpochData(nextEpoch, headerHash, val) - h.logger.Debugf("stored BABENextEpochData data: %v for hash: %s to epoch: %d", digest, headerHash, nextEpoch) - return nil - - case types.BABEOnDisabled: - return nil - - case types.VersionedNextConfigData: - nextConfigDataVersion, err := val.Value() - if err != nil { - return fmt.Errorf("getting digest value: %w", err) - } - - switch nextConfigData := nextConfigDataVersion.(type) { - case types.NextConfigDataV1: - currEpoch, err := h.epochState.GetEpochForBlock(header) - if err != nil { - return fmt.Errorf("getting epoch for block %d (%s): %w", header.Number, headerHash, err) - } - nextEpoch := currEpoch + 1 - h.epochState.StoreBABENextConfigData(nextEpoch, headerHash, nextConfigData) - h.logger.Debugf("stored BABENextConfigData data: %v for hash: %s to epoch: %d", digest, headerHash, nextEpoch) - return nil - default: - return fmt.Errorf("next config data version not supported: %T", nextConfigDataVersion) - } - } - - return errors.New("invalid consensus digest data") -} - -func (h *Handler) handleBlockImport(ctx context.Context) { - for { - select { - case block := <-h.imported: - if block == nil { - continue - } - - err := h.HandleDigests(&block.Header) - if err != nil { - h.logger.Errorf("failed to handle digests: %s", err) - } - - err = h.grandpaState.ApplyForcedChanges(&block.Header) - if err != nil { - h.logger.Errorf("failed to apply forced changes: %s", err) - } - case <-ctx.Done(): - return - } - } -} - func (h *Handler) handleBlockFinalisation(ctx context.Context) { for { select { @@ -258,17 +74,17 @@ func (h *Handler) handleBlockFinalisation(ctx context.Context) { err := h.epochState.FinalizeBABENextEpochData(&info.Header) if err != nil { - h.logger.Errorf("failed to persist babe next epoch data: %s", err) + logger.Errorf("failed to persist babe next epoch data: %s", err) } err = h.epochState.FinalizeBABENextConfigData(&info.Header) if err != nil { - h.logger.Errorf("failed to persist babe next epoch config: %s", err) + logger.Errorf("failed to persist babe next epoch config: %s", err) } err = h.grandpaState.ApplyScheduledChanges(&info.Header) if err != nil { - h.logger.Errorf("failed to apply scheduled change: %s", err) + logger.Errorf("failed to apply scheduled change: %s", err) } case <-ctx.Done(): diff --git a/dot/digest/digest_integration_test.go b/dot/digest/digest_integration_test.go index 6d4c295c3b..5994c26469 100644 --- a/dot/digest/digest_integration_test.go +++ b/dot/digest/digest_integration_test.go @@ -13,7 +13,6 @@ import ( "github.com/ChainSafe/gossamer/dot/state" "github.com/ChainSafe/gossamer/dot/types" - "github.com/ChainSafe/gossamer/internal/log" "github.com/ChainSafe/gossamer/lib/common" "github.com/ChainSafe/gossamer/lib/crypto/ed25519" "github.com/ChainSafe/gossamer/lib/crypto/sr25519" @@ -24,7 +23,7 @@ import ( "github.com/stretchr/testify/require" ) -func newTestHandler(t *testing.T) (*Handler, *state.Service) { +func newTestHandler(t *testing.T) (*Handler, *BlockImportHandler, *state.Service) { testDatadirPath := t.TempDir() ctrl := gomock.NewController(t) @@ -48,13 +47,15 @@ func newTestHandler(t *testing.T) (*Handler, *state.Service) { err = stateSrvc.Start() require.NoError(t, err) - dh, err := NewHandler(log.Critical, stateSrvc.Block, stateSrvc.Epoch, stateSrvc.Grandpa) + dh, err := NewHandler(stateSrvc.Block, stateSrvc.Epoch, stateSrvc.Grandpa) require.NoError(t, err) - return dh, stateSrvc + + blockImportHandler := NewBlockImportHandler(stateSrvc.Epoch, stateSrvc.Grandpa) + return dh, blockImportHandler, stateSrvc } func TestHandler_GrandpaScheduledChange(t *testing.T) { - handler, _ := newTestHandler(t) + handler, blockImportHandler, _ := newTestHandler(t) handler.Start() defer handler.Stop() @@ -88,7 +89,7 @@ func TestHandler_GrandpaScheduledChange(t *testing.T) { } // include a GrandpaScheduledChange on a block of number 3 - err = handler.handleConsensusDigest(d, headers[3]) + err = blockImportHandler.handleConsensusDigest(d, headers[3]) require.NoError(t, err) // finalize block of number 3 @@ -108,7 +109,7 @@ func TestHandler_GrandpaScheduledChange(t *testing.T) { } func TestHandler_GrandpaForcedChange(t *testing.T) { - handler, _ := newTestHandler(t) + handler, blockImportHandler, _ := newTestHandler(t) handler.Start() defer handler.Stop() @@ -139,13 +140,17 @@ func TestHandler_GrandpaForcedChange(t *testing.T) { // tracking the GrandpaForcedChange under block 1 // and when block number 4 being imported then we should apply the change - err = handler.handleConsensusDigest(d, headers[1]) + err = blockImportHandler.handleConsensusDigest(d, headers[1]) require.NoError(t, err) // create new blocks and import them - state.AddBlocksToState(t, handler.blockState.(*state.BlockState), 4, false) + headersInState, _ := state.AddBlocksToState(t, handler.blockState.(*state.BlockState), 4, false) + for _, header := range headersInState { + err := blockImportHandler.Handle(header) + require.NoError(t, err) + } - time.Sleep(time.Millisecond * 500) + //time.Sleep(time.Millisecond * 500) setID, err := handler.grandpaState.(*state.GrandpaState).GetCurrentSetID() require.NoError(t, err) require.Equal(t, uint64(1), setID) @@ -233,7 +238,7 @@ func TestMultipleGRANDPADigests_ShouldIncludeJustForcedChanges(t *testing.T) { Digest: digests, } - handler, _ := newTestHandler(t) + _, blockImportHandler, _ := newTestHandler(t) ctrl := gomock.NewController(t) grandpaState := NewMockGrandpaState(ctrl) @@ -250,14 +255,15 @@ func TestMultipleGRANDPADigests_ShouldIncludeJustForcedChanges(t *testing.T) { grandpaState.EXPECT().HandleGRANDPADigest(header, expected).Return(nil) } - handler.grandpaState = grandpaState - handler.HandleDigests(header) + blockImportHandler.grandpaState = grandpaState + err := blockImportHandler.handleDigests(header) + require.NoError(t, err) }) } } func TestHandler_HandleBABEOnDisabled(t *testing.T) { - handler, _ := newTestHandler(t) + _, blockImportHandler, _ := newTestHandler(t) header := &types.Header{ Number: 1, } @@ -276,7 +282,7 @@ func TestHandler_HandleBABEOnDisabled(t *testing.T) { Data: data, } - err = handler.handleConsensusDigest(d, header) + err = blockImportHandler.handleConsensusDigest(d, header) require.NoError(t, err) } @@ -338,9 +344,9 @@ func TestHandler_HandleNextEpochData(t *testing.T) { } header := createHeaderWithPreDigest(t, 10) - handler, stateSrv := newTestHandler(t) + handler, blockImportHandler, stateSrv := newTestHandler(t) - err = handler.handleConsensusDigest(d, header) + err = blockImportHandler.handleConsensusDigest(d, header) require.NoError(t, err) const targetEpoch = 1 @@ -403,9 +409,9 @@ func TestHandler_HandleNextConfigData(t *testing.T) { header := createHeaderWithPreDigest(t, 10) - handler, stateSrv := newTestHandler(t) + handler, blockImportHandler, stateSrv := newTestHandler(t) - err = handler.handleConsensusDigest(d, header) + err = blockImportHandler.handleConsensusDigest(d, header) require.NoError(t, err) const targetEpoch = 1 diff --git a/dot/digest/interfaces.go b/dot/digest/interfaces.go index 151dff1c36..db7fdbd710 100644 --- a/dot/digest/interfaces.go +++ b/dot/digest/interfaces.go @@ -7,7 +7,6 @@ import ( "encoding/json" "github.com/ChainSafe/gossamer/dot/types" - "github.com/ChainSafe/gossamer/lib/common" "github.com/ChainSafe/gossamer/pkg/scale" ) @@ -22,8 +21,7 @@ type BlockState interface { // EpochState is the interface for state.EpochState type EpochState interface { GetEpochForBlock(header *types.Header) (uint64, error) - StoreBABENextEpochData(epoch uint64, hash common.Hash, nextEpochData types.NextEpochData) - StoreBABENextConfigData(epoch uint64, hash common.Hash, nextEpochData types.NextConfigDataV1) + HandleBABEDigest(header *types.Header, digest scale.VaryingDataType) error FinalizeBABENextEpochData(finalizedHeader *types.Header) error FinalizeBABENextConfigData(finalizedHeader *types.Header) error } diff --git a/dot/digest/mock_epoch_state_test.go b/dot/digest/mock_epoch_state_test.go index dc1f49c9a9..c2285656c3 100644 --- a/dot/digest/mock_epoch_state_test.go +++ b/dot/digest/mock_epoch_state_test.go @@ -8,7 +8,7 @@ import ( reflect "reflect" types "github.com/ChainSafe/gossamer/dot/types" - common "github.com/ChainSafe/gossamer/lib/common" + scale "github.com/ChainSafe/gossamer/pkg/scale" gomock "github.com/golang/mock/gomock" ) @@ -78,26 +78,16 @@ func (mr *MockEpochStateMockRecorder) GetEpochForBlock(arg0 interface{}) *gomock return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEpochForBlock", reflect.TypeOf((*MockEpochState)(nil).GetEpochForBlock), arg0) } -// StoreBABENextConfigData mocks base method. -func (m *MockEpochState) StoreBABENextConfigData(arg0 uint64, arg1 common.Hash, arg2 types.NextConfigDataV1) { +// HandleBABEDigest mocks base method. +func (m *MockEpochState) HandleBABEDigest(arg0 *types.Header, arg1 scale.VaryingDataType) error { m.ctrl.T.Helper() - m.ctrl.Call(m, "StoreBABENextConfigData", arg0, arg1, arg2) -} - -// StoreBABENextConfigData indicates an expected call of StoreBABENextConfigData. -func (mr *MockEpochStateMockRecorder) StoreBABENextConfigData(arg0, arg1, arg2 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreBABENextConfigData", reflect.TypeOf((*MockEpochState)(nil).StoreBABENextConfigData), arg0, arg1, arg2) -} - -// StoreBABENextEpochData mocks base method. -func (m *MockEpochState) StoreBABENextEpochData(arg0 uint64, arg1 common.Hash, arg2 types.NextEpochData) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "StoreBABENextEpochData", arg0, arg1, arg2) + ret := m.ctrl.Call(m, "HandleBABEDigest", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 } -// StoreBABENextEpochData indicates an expected call of StoreBABENextEpochData. -func (mr *MockEpochStateMockRecorder) StoreBABENextEpochData(arg0, arg1, arg2 interface{}) *gomock.Call { +// HandleBABEDigest indicates an expected call of HandleBABEDigest. +func (mr *MockEpochStateMockRecorder) HandleBABEDigest(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreBABENextEpochData", reflect.TypeOf((*MockEpochState)(nil).StoreBABENextEpochData), arg0, arg1, arg2) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandleBABEDigest", reflect.TypeOf((*MockEpochState)(nil).HandleBABEDigest), arg0, arg1) } diff --git a/dot/mock_node_builder_test.go b/dot/mock_node_builder_test.go index e140602a46..c6fed7321d 100644 --- a/dot/mock_node_builder_test.go +++ b/dot/mock_node_builder_test.go @@ -16,7 +16,6 @@ import ( sync "github.com/ChainSafe/gossamer/dot/sync" system "github.com/ChainSafe/gossamer/dot/system" types "github.com/ChainSafe/gossamer/dot/types" - log "github.com/ChainSafe/gossamer/internal/log" babe "github.com/ChainSafe/gossamer/lib/babe" grandpa "github.com/ChainSafe/gossamer/lib/grandpa" keystore "github.com/ChainSafe/gossamer/lib/keystore" @@ -92,18 +91,18 @@ func (mr *MocknodeBuilderIfaceMockRecorder) createCoreService(config, ks, st, ne } // createDigestHandler mocks base method. -func (m *MocknodeBuilderIface) createDigestHandler(lvl log.Level, st *state.Service) (*digest.Handler, error) { +func (m *MocknodeBuilderIface) createDigestHandler(st *state.Service) (*digest.Handler, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "createDigestHandler", lvl, st) + ret := m.ctrl.Call(m, "createDigestHandler", st) ret0, _ := ret[0].(*digest.Handler) ret1, _ := ret[1].(error) return ret0, ret1 } // createDigestHandler indicates an expected call of createDigestHandler. -func (mr *MocknodeBuilderIfaceMockRecorder) createDigestHandler(lvl, st interface{}) *gomock.Call { +func (mr *MocknodeBuilderIfaceMockRecorder) createDigestHandler(st interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "createDigestHandler", reflect.TypeOf((*MocknodeBuilderIface)(nil).createDigestHandler), lvl, st) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "createDigestHandler", reflect.TypeOf((*MocknodeBuilderIface)(nil).createDigestHandler), st) } // createGRANDPAService mocks base method. diff --git a/dot/node.go b/dot/node.go index 1a9374647f..5b899f367c 100644 --- a/dot/node.go +++ b/dot/node.go @@ -59,7 +59,7 @@ type nodeBuilderIface interface { loadRuntime(config *cfg.Config, ns *runtime.NodeStorage, stateSrvc *state.Service, ks *keystore.GlobalKeystore, net *network.Service) error createBlockVerifier(st *state.Service) *babe.VerificationManager - createDigestHandler(lvl log.Level, st *state.Service) (*digest.Handler, error) + createDigestHandler(st *state.Service) (*digest.Handler, error) createCoreService(config *cfg.Config, ks *keystore.GlobalKeystore, st *state.Service, net *network.Service, dh *digest.Handler) (*core.Service, error) createGRANDPAService(config *cfg.Config, st *state.Service, ks KeyStore, @@ -346,11 +346,7 @@ func newNode(config *cfg.Config, ver := builder.createBlockVerifier(stateSrvc) - digestLogLevel, err := log.ParseLevel(config.Log.Digest) - if err != nil { - return nil, fmt.Errorf("cannot parse digest log level: %w", err) - } - dh, err := builder.createDigestHandler(digestLogLevel, stateSrvc) + dh, err := builder.createDigestHandler(stateSrvc) if err != nil { return nil, err } diff --git a/dot/node_integration_test.go b/dot/node_integration_test.go index cfb1be0aa7..2d7c158727 100644 --- a/dot/node_integration_test.go +++ b/dot/node_integration_test.go @@ -127,7 +127,7 @@ func TestNewNode(t *testing.T) { ks, gomock.AssignableToTypeOf(&network.Service{})).Return(nil) m.EXPECT().createBlockVerifier(gomock.AssignableToTypeOf(&state.Service{})). Return(&babe.VerificationManager{}) - m.EXPECT().createDigestHandler(log.Critical, gomock.AssignableToTypeOf(&state.Service{})). + m.EXPECT().createDigestHandler(gomock.AssignableToTypeOf(&state.Service{})). Return(&digest.Handler{}, nil) m.EXPECT().createCoreService(initConfig, ks, gomock.AssignableToTypeOf(&state.Service{}), gomock.AssignableToTypeOf(&network.Service{}), &digest.Handler{}). diff --git a/dot/services.go b/dot/services.go index 82c76edadf..4c7a2f96e1 100644 --- a/dot/services.go +++ b/dot/services.go @@ -276,6 +276,7 @@ func (nodeBuilder) createCoreService(config *cfg.Config, ks *keystore.GlobalKeys Network: net, CodeSubstitutes: codeSubs, CodeSubstitutedState: st.Base, + OnBlockImport: digest.NewBlockImportHandler(st.Epoch, st.Grandpa), } // create new core service @@ -494,8 +495,8 @@ func (nodeBuilder) newSyncService(config *cfg.Config, st *state.Service, fg Bloc return sync.NewService(syncCfg) } -func (nodeBuilder) createDigestHandler(lvl log.Level, st *state.Service) (*digest.Handler, error) { - return digest.NewHandler(lvl, st.Block, st.Epoch, st.Grandpa) +func (nodeBuilder) createDigestHandler(st *state.Service) (*digest.Handler, error) { + return digest.NewHandler(st.Block, st.Epoch, st.Grandpa) } func createPprofService(config cfg.PprofConfig) (service *pprof.Service) { diff --git a/dot/services_integration_test.go b/dot/services_integration_test.go index bcf9d1d596..6750742428 100644 --- a/dot/services_integration_test.go +++ b/dot/services_integration_test.go @@ -497,9 +497,7 @@ func TestCreateCoreService(t *testing.T) { networkSrvc := &network.Service{} builder := nodeBuilder{} - digestLevel, err := log.ParseLevel(config.Log.Digest) - require.NoError(t, err) - dh, err := builder.createDigestHandler(digestLevel, stateSrvc) + dh, err := builder.createDigestHandler(stateSrvc) require.NoError(t, err) coreSrvc, err := builder.createCoreService(config, ks, stateSrvc, networkSrvc, dh) @@ -545,9 +543,7 @@ func TestCreateSyncService(t *testing.T) { ver := builder.createBlockVerifier(stateSrvc) - digestLevel, err := log.ParseLevel(config.Log.Digest) - require.NoError(t, err) - dh, err := builder.createDigestHandler(digestLevel, stateSrvc) + dh, err := builder.createDigestHandler(stateSrvc) require.NoError(t, err) coreSrvc, err := builder.createCoreService(config, ks, stateSrvc, &network.Service{}, dh) @@ -604,9 +600,7 @@ func TestCreateRPCService(t *testing.T) { err = builder.loadRuntime(config, ns, stateSrvc, ks, networkSrvc) require.NoError(t, err) - digestLevel, err := log.ParseLevel(config.Log.Digest) - require.NoError(t, err) - dh, err := builder.createDigestHandler(digestLevel, stateSrvc) + dh, err := builder.createDigestHandler(stateSrvc) require.NoError(t, err) coreSrvc, err := builder.createCoreService(config, ks, stateSrvc, networkSrvc, dh) @@ -657,9 +651,7 @@ func TestCreateBABEService_Integration(t *testing.T) { err = builder.loadRuntime(config, ns, stateSrvc, ks, &network.Service{}) require.NoError(t, err) - digestLevel, err := log.ParseLevel(config.Log.Digest) - require.NoError(t, err) - dh, err := builder.createDigestHandler(digestLevel, stateSrvc) + dh, err := builder.createDigestHandler(stateSrvc) require.NoError(t, err) coreSrvc, err := builder.createCoreService(config, ks, stateSrvc, &network.Service{}, dh) @@ -770,9 +762,7 @@ func TestNewWebSocketServer(t *testing.T) { err = builder.loadRuntime(config, ns, stateSrvc, ks, networkSrvc) require.NoError(t, err) - digestLevel, err := log.ParseLevel(config.Log.Digest) - require.NoError(t, err) - dh, err := builder.createDigestHandler(digestLevel, stateSrvc) + dh, err := builder.createDigestHandler(stateSrvc) require.NoError(t, err) coreSrvc, err := builder.createCoreService(config, ks, stateSrvc, networkSrvc, dh) @@ -858,8 +848,6 @@ func Test_createDigestHandler(t *testing.T) { err = startStateService(*config.State, stateSrvc) require.NoError(t, err) - digestLevel, err := log.ParseLevel(config.Log.Digest) - require.NoError(t, err) - _, err = builder.createDigestHandler(digestLevel, stateSrvc) + _, err = builder.createDigestHandler(stateSrvc) require.NoError(t, err) } diff --git a/dot/state/epoch.go b/dot/state/epoch.go index ca7c8abcce..6dc18546b2 100644 --- a/dot/state/epoch.go +++ b/dot/state/epoch.go @@ -383,6 +383,53 @@ func (s *EpochState) getConfigDataFromDatabase(epoch uint64) (*types.ConfigData, return info, nil } +func (s *EpochState) HandleBABEDigest(header *types.Header, digest scale.VaryingDataType) error { + headerHash := header.Hash() + + digestValue, err := digest.Value() + if err != nil { + return fmt.Errorf("getting digest value: %w", err) + } + switch val := digestValue.(type) { + case types.NextEpochData: + currEpoch, err := s.GetEpochForBlock(header) + if err != nil { + return fmt.Errorf("getting epoch for block %d (%s): %w", + header.Number, headerHash, err) + } + + nextEpoch := currEpoch + 1 + s.storeBABENextEpochData(nextEpoch, headerHash, val) + logger.Debugf("stored BABENextEpochData data: %v for hash: %s to epoch: %d", digest, headerHash, nextEpoch) + return nil + + case types.BABEOnDisabled: + return nil + + case types.VersionedNextConfigData: + nextConfigDataVersion, err := val.Value() + if err != nil { + return fmt.Errorf("getting digest value: %w", err) + } + + switch nextConfigData := nextConfigDataVersion.(type) { + case types.NextConfigDataV1: + currEpoch, err := s.GetEpochForBlock(header) + if err != nil { + return fmt.Errorf("getting epoch for block %d (%s): %w", header.Number, headerHash, err) + } + nextEpoch := currEpoch + 1 + s.storeBABENextConfigData(nextEpoch, headerHash, nextConfigData) + logger.Debugf("stored BABENextConfigData data: %v for hash: %s to epoch: %d", digest, headerHash, nextEpoch) + return nil + default: + return fmt.Errorf("next config data version not supported: %T", nextConfigDataVersion) + } + } + + return errors.New("invalid consensus digest data") +} + type nextEpochMap[T types.NextEpochData | types.NextConfigDataV1] map[uint64]map[common.Hash]T func (nem nextEpochMap[T]) Retrieve(blockState *BlockState, epoch uint64, header *types.Header) (*T, error) { @@ -493,7 +540,7 @@ func (s *EpochState) SkipVerify(header *types.Header) (bool, error) { } // StoreBABENextEpochData stores the types.NextEpochData under epoch and hash keys -func (s *EpochState) StoreBABENextEpochData(epoch uint64, hash common.Hash, nextEpochData types.NextEpochData) { +func (s *EpochState) storeBABENextEpochData(epoch uint64, hash common.Hash, nextEpochData types.NextEpochData) { s.nextEpochDataLock.Lock() defer s.nextEpochDataLock.Unlock() @@ -505,7 +552,7 @@ func (s *EpochState) StoreBABENextEpochData(epoch uint64, hash common.Hash, next } // StoreBABENextConfigData stores the types.NextConfigData under epoch and hash keys -func (s *EpochState) StoreBABENextConfigData(epoch uint64, hash common.Hash, nextConfigData types.NextConfigDataV1) { +func (s *EpochState) storeBABENextConfigData(epoch uint64, hash common.Hash, nextConfigData types.NextConfigDataV1) { s.nextConfigDataLock.Lock() defer s.nextConfigDataLock.Unlock() diff --git a/dot/state/epoch_test.go b/dot/state/epoch_test.go index 4addc8e278..93ec72b2b2 100644 --- a/dot/state/epoch_test.go +++ b/dot/state/epoch_test.go @@ -388,7 +388,7 @@ func TestStoreAndFinalizeBabeNextEpochData(t *testing.T) { for _, e := range tt.inMemoryEpoch { for i, hash := range e.hashes { - epochState.StoreBABENextEpochData(e.epoch, hash, e.nextData[i]) + epochState.storeBABENextEpochData(e.epoch, hash, e.nextData[i]) } } @@ -568,7 +568,7 @@ func TestStoreAndFinalizeBabeNextConfigData(t *testing.T) { for _, e := range tt.inMemoryEpoch { for i, hash := range e.hashes { - epochState.StoreBABENextConfigData(e.epoch, hash, e.nextData[i]) + epochState.storeBABENextConfigData(e.epoch, hash, e.nextData[i]) } } diff --git a/lib/babe/helpers_test.go b/lib/babe/helpers_test.go index 9839d3254f..b3599e0dab 100644 --- a/lib/babe/helpers_test.go +++ b/lib/babe/helpers_test.go @@ -232,6 +232,9 @@ func createTestService(t *testing.T, cfg ServiceConfig, genesis genesis.Genesis, mockNetwork := mocks.NewMockNetwork(ctrl) mockNetwork.EXPECT().GossipMessage(gomock.Any()).AnyTimes() + digestOnBlockImportMock := mocks.NewMockBlockImportDigestHandler(ctrl) + digestOnBlockImportMock.EXPECT().Handle(gomock.Any()).AnyTimes() + coreConfig := core.Config{ BlockState: dbSrv.Block, StorageState: storageState, @@ -241,6 +244,7 @@ func createTestService(t *testing.T, cfg ServiceConfig, genesis genesis.Genesis, Network: mockNetwork, CodeSubstitutedState: dbSrv.Base, CodeSubstitutes: make(map[common.Hash]string), + OnBlockImport: digestOnBlockImportMock, } babeService.blockImportHandler = newTestCoreService(t, &coreConfig, genesis, diff --git a/lib/babe/mocks/network.go b/lib/babe/mocks/core.go similarity index 61% rename from lib/babe/mocks/network.go rename to lib/babe/mocks/core.go index 6aaacbc0af..6809a6d7d0 100644 --- a/lib/babe/mocks/network.go +++ b/lib/babe/mocks/core.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/ChainSafe/gossamer/dot/core (interfaces: Network) +// Source: github.com/ChainSafe/gossamer/dot/core (interfaces: Network,BlockImportDigestHandler) // Package mocks is a generated GoMock package. package mocks @@ -9,6 +9,7 @@ import ( network "github.com/ChainSafe/gossamer/dot/network" peerset "github.com/ChainSafe/gossamer/dot/peerset" + types "github.com/ChainSafe/gossamer/dot/types" gomock "github.com/golang/mock/gomock" peer "github.com/libp2p/go-libp2p/core/peer" ) @@ -73,3 +74,40 @@ func (mr *MockNetworkMockRecorder) ReportPeer(arg0, arg1 interface{}) *gomock.Ca mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReportPeer", reflect.TypeOf((*MockNetwork)(nil).ReportPeer), arg0, arg1) } + +// MockBlockImportDigestHandler is a mock of BlockImportDigestHandler interface. +type MockBlockImportDigestHandler struct { + ctrl *gomock.Controller + recorder *MockBlockImportDigestHandlerMockRecorder +} + +// MockBlockImportDigestHandlerMockRecorder is the mock recorder for MockBlockImportDigestHandler. +type MockBlockImportDigestHandlerMockRecorder struct { + mock *MockBlockImportDigestHandler +} + +// NewMockBlockImportDigestHandler creates a new mock instance. +func NewMockBlockImportDigestHandler(ctrl *gomock.Controller) *MockBlockImportDigestHandler { + mock := &MockBlockImportDigestHandler{ctrl: ctrl} + mock.recorder = &MockBlockImportDigestHandlerMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockBlockImportDigestHandler) EXPECT() *MockBlockImportDigestHandlerMockRecorder { + return m.recorder +} + +// Handle mocks base method. +func (m *MockBlockImportDigestHandler) Handle(arg0 *types.Header) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Handle", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// Handle indicates an expected call of Handle. +func (mr *MockBlockImportDigestHandlerMockRecorder) Handle(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Handle", reflect.TypeOf((*MockBlockImportDigestHandler)(nil).Handle), arg0) +} diff --git a/lib/babe/mocks_generate_test.go b/lib/babe/mocks_generate_test.go index 58378cdc74..1236b19e54 100644 --- a/lib/babe/mocks_generate_test.go +++ b/lib/babe/mocks_generate_test.go @@ -5,5 +5,5 @@ package babe //go:generate mockgen -destination=mock_telemetry_test.go -package $GOPACKAGE . Telemetry //go:generate mockgen -destination=mocks/runtime.go -package mocks github.com/ChainSafe/gossamer/lib/runtime Instance -//go:generate mockgen -destination=mocks/network.go -package mocks github.com/ChainSafe/gossamer/dot/core Network +//go:generate mockgen -destination=mocks/core.go -package mocks github.com/ChainSafe/gossamer/dot/core Network,BlockImportDigestHandler //go:generate mockgen -destination=mock_state_test.go -package $GOPACKAGE . BlockState,ImportedBlockNotifierManager,StorageState,TransactionState,EpochState,BlockImportHandler diff --git a/lib/babe/verify_integration_test.go b/lib/babe/verify_integration_test.go index 12db82b9b3..138ab8e021 100644 --- a/lib/babe/verify_integration_test.go +++ b/lib/babe/verify_integration_test.go @@ -16,7 +16,6 @@ import ( "github.com/ChainSafe/gossamer/dot/state" "github.com/ChainSafe/gossamer/dot/telemetry" "github.com/ChainSafe/gossamer/dot/types" - "github.com/ChainSafe/gossamer/internal/log" "github.com/ChainSafe/gossamer/lib/common" "github.com/ChainSafe/gossamer/lib/crypto/sr25519" "github.com/ChainSafe/gossamer/pkg/scale" @@ -531,7 +530,9 @@ func TestVerifyForkBlocksWithRespectiveEpochData(t *testing.T) { epochState, err := state.NewEpochStateFromGenesis(inMemoryDB, stateService.Block, epochBABEConfig) require.NoError(t, err) - digestHandler, err := digest.NewHandler(log.DoNotChange, stateService.Block, epochState, stateService.Grandpa) + onBlockImportDigestHandler := digest.NewBlockImportHandler(epochState, stateService.Grandpa) + + digestHandler, err := digest.NewHandler(stateService.Block, epochState, stateService.Grandpa) require.NoError(t, err) digestHandler.Start() @@ -550,7 +551,7 @@ func TestVerifyForkBlocksWithRespectiveEpochData(t *testing.T) { SecondarySlots: 1, } aliceBlockHeader := issueConsensusDigestsBlockFromGenesis(t, &genesisHeader, keyring.KeyAlice, - stateService, aliceBlockNextEpoch, aliceBlockNextConfigData) + stateService, aliceBlockNextEpoch, aliceBlockNextConfigData, onBlockImportDigestHandler) bobBlockNextEpoch := types.NextEpochData{ Authorities: authorities[6:], @@ -561,7 +562,7 @@ func TestVerifyForkBlocksWithRespectiveEpochData(t *testing.T) { SecondarySlots: 1, } bobBlockHeader := issueConsensusDigestsBlockFromGenesis(t, &genesisHeader, keyring.KeyBob, - stateService, bobBlockNextEpoch, bobBlockNextConfigData) + stateService, bobBlockNextEpoch, bobBlockNextConfigData, onBlockImportDigestHandler) // wait for digest handleBlockImport goroutine gets the imported // block, process its digest and store the info at epoch state @@ -672,7 +673,8 @@ func TestVerifyForkBlocksWithRespectiveEpochData(t *testing.T) { // blocks that contains different consensus messages digests func issueConsensusDigestsBlockFromGenesis(t *testing.T, genesisHeader *types.Header, kp *sr25519.Keypair, stateService *state.Service, - nextEpoch types.NextEpochData, nextConfig types.NextConfigDataV1) *types.Header { + nextEpoch types.NextEpochData, nextConfig types.NextConfigDataV1, + onImportBlockDigestHandler *digest.BlockImportHandler) *types.Header { t.Helper() output, proof, err := kp.VrfSign(makeTranscript(Randomness{}, uint64(0), 0)) @@ -728,6 +730,9 @@ func issueConsensusDigestsBlockFromGenesis(t *testing.T, genesisHeader *types.He }) require.NoError(t, err) + err = onImportBlockDigestHandler.Handle(headerWhoOwnsNextEpochDigest) + require.NoError(t, err) + return headerWhoOwnsNextEpochDigest }