diff --git a/relayer/cmd/generate_beacon_data.go b/relayer/cmd/generate_beacon_data.go index dfa13e860a..06202d84e5 100644 --- a/relayer/cmd/generate_beacon_data.go +++ b/relayer/cmd/generate_beacon_data.go @@ -132,7 +132,7 @@ func generateBeaconCheckpoint(cmd *cobra.Command, _ []string) error { return err } - p := protocol.New(conf.Source.Beacon.Spec) + p := protocol.New(conf.Source.Beacon.Spec, conf.Sink.Parachain.HeaderRedundancy) store := store.New(conf.Source.Beacon.DataStore.Location, conf.Source.Beacon.DataStore.MaxEntries, *p) store.Connect() defer store.Close() @@ -193,7 +193,7 @@ func generateBeaconTestFixture(cmd *cobra.Command, _ []string) error { return err } - p := protocol.New(conf.Source.Beacon.Spec) + p := protocol.New(conf.Source.Beacon.Spec, conf.Sink.Parachain.HeaderRedundancy) store := store.New(conf.Source.Beacon.DataStore.Location, conf.Source.Beacon.DataStore.MaxEntries, *p) err = store.Connect() @@ -504,7 +504,7 @@ func generateExecutionUpdate(cmd *cobra.Command, _ []string) error { } log.WithFields(log.Fields{"endpoint": conf.Source.Beacon.Endpoint}).Info("connecting to beacon API") - p := protocol.New(conf.Source.Beacon.Spec) + p := protocol.New(conf.Source.Beacon.Spec, conf.Sink.Parachain.HeaderRedundancy) store := store.New(conf.Source.Beacon.DataStore.Location, conf.Source.Beacon.DataStore.MaxEntries, *p) store.Connect() @@ -695,7 +695,7 @@ func generateInboundFixture(cmd *cobra.Command, _ []string) error { return err } - p := protocol.New(beaconConf.Source.Beacon.Spec) + p := protocol.New(beaconConf.Source.Beacon.Spec, beaconConf.Sink.Parachain.HeaderRedundancy) store := store.New(beaconConf.Source.Beacon.DataStore.Location, beaconConf.Source.Beacon.DataStore.MaxEntries, *p) store.Connect() diff --git a/relayer/cmd/import_beacon_state.go b/relayer/cmd/import_beacon_state.go index f683e48db0..0dac560832 100644 --- a/relayer/cmd/import_beacon_state.go +++ b/relayer/cmd/import_beacon_state.go @@ -71,7 +71,7 @@ func importBeaconState(cmd *cobra.Command, _ []string) error { return fmt.Errorf("open finalized state file: %w", err) } - p := protocol.New(conf.Source.Beacon.Spec) + p := protocol.New(conf.Source.Beacon.Spec, conf.Sink.Parachain.HeaderRedundancy) store := store.New(conf.Source.Beacon.DataStore.Location, conf.Source.Beacon.DataStore.MaxEntries, *p) beaconClient := api.NewBeaconClient(conf.Source.Beacon.Endpoint, conf.Source.Beacon.StateEndpoint) syncer := syncer.New(beaconClient, &store, p) diff --git a/relayer/cmd/import_execution_header.go b/relayer/cmd/import_execution_header.go index c003131e96..45126a63f7 100644 --- a/relayer/cmd/import_execution_header.go +++ b/relayer/cmd/import_execution_header.go @@ -109,7 +109,7 @@ func importExecutionHeaderFn(cmd *cobra.Command, _ []string) error { log.WithField("hash", beaconHeader).Info("will be syncing execution header for beacon hash") - p := protocol.New(conf.Source.Beacon.Spec) + p := protocol.New(conf.Source.Beacon.Spec, conf.Sink.Parachain.HeaderRedundancy) store := store.New(conf.Source.Beacon.DataStore.Location, conf.Source.Beacon.DataStore.MaxEntries, *p) store.Connect() defer store.Close() diff --git a/relayer/cmd/list_beacon_states.go b/relayer/cmd/list_beacon_states.go index f3113968f1..cbc48fd4c5 100644 --- a/relayer/cmd/list_beacon_states.go +++ b/relayer/cmd/list_beacon_states.go @@ -49,7 +49,7 @@ func listBeaconState(cmd *cobra.Command, _ []string) error { return err } - p := protocol.New(conf.Source.Beacon.Spec) + p := protocol.New(conf.Source.Beacon.Spec, conf.Sink.Parachain.HeaderRedundancy) store := store.New(conf.Source.Beacon.DataStore.Location, conf.Source.Beacon.DataStore.MaxEntries, *p) err = store.Connect() diff --git a/relayer/cmd/store_beacon_state.go b/relayer/cmd/store_beacon_state.go index 490a39a4d5..2158bf54bd 100644 --- a/relayer/cmd/store_beacon_state.go +++ b/relayer/cmd/store_beacon_state.go @@ -49,7 +49,7 @@ func storeBeaconState(cmd *cobra.Command, _ []string) error { return err } - p := protocol.New(conf.Source.Beacon.Spec) + p := protocol.New(conf.Source.Beacon.Spec, conf.Sink.Parachain.HeaderRedundancy) store := store.New(conf.Source.Beacon.DataStore.Location, conf.Source.Beacon.DataStore.MaxEntries, *p) beaconClient := api.NewBeaconClient(conf.Source.Beacon.Endpoint, conf.Source.Beacon.StateEndpoint) syncer := syncer.New(beaconClient, &store, p) diff --git a/relayer/relays/beacon/config/config.go b/relayer/relays/beacon/config/config.go index 1e3b465597..f0c9c86374 100644 --- a/relayer/relays/beacon/config/config.go +++ b/relayer/relays/beacon/config/config.go @@ -3,7 +3,6 @@ package config import ( "errors" "fmt" - "github.com/snowfork/snowbridge/relayer/config" ) type Config struct { @@ -35,8 +34,16 @@ type BeaconConfig struct { } type SinkConfig struct { - Parachain config.ParachainConfig `mapstructure:"parachain"` - UpdateSlotInterval uint64 `mapstructure:"updateSlotInterval"` + Parachain ParachainConfig `mapstructure:"parachain"` + UpdateSlotInterval uint64 `mapstructure:"updateSlotInterval"` +} + +type ParachainConfig struct { + Endpoint string `mapstructure:"endpoint"` + MaxWatchedExtrinsics int64 `mapstructure:"maxWatchedExtrinsics"` + // The max number of header in the FinalizedBeaconStateBuffer on-chain. + // https://github.com/paritytech/polkadot-sdk/blob/master/bridges/snowbridge/pallets/ethereum-client/src/types.rs#L23 + HeaderRedundancy uint64 `mapstructure:"headerRedundancy"` } func (c Config) Validate() error { @@ -81,3 +88,16 @@ func (b BeaconConfig) Validate() error { } return nil } + +func (p ParachainConfig) Validate() error { + if p.Endpoint == "" { + return errors.New("[endpoint] is not set") + } + if p.MaxWatchedExtrinsics == 0 { + return errors.New("[maxWatchedExtrinsics] is not set") + } + if p.HeaderRedundancy == 0 { + return errors.New("[HeaderRedundancy] is not set") + } + return nil +} diff --git a/relayer/relays/beacon/header/header.go b/relayer/relays/beacon/header/header.go index d65f75ebca..e7dca2c828 100644 --- a/relayer/relays/beacon/header/header.go +++ b/relayer/relays/beacon/header/header.go @@ -523,32 +523,32 @@ func (h *Header) findLatestCheckPoint(slot uint64) (state.FinalizedHeader, error return beaconState, fmt.Errorf("GetLastFinalizedStateIndex error: %w", err) } startIndex := uint64(lastIndex) - endIndex := uint64(0) + endIndex := startIndex + 1 syncCommitteePeriod := h.protocol.Settings.SlotsInEpoch * h.protocol.Settings.EpochsPerSyncCommitteePeriod - slotPeriodIndex := slot / syncCommitteePeriod - - for index := startIndex; index >= endIndex; index-- { + totalStates := syncCommitteePeriod * h.protocol.HeaderRedundancy // Total size of the circular buffer, + // https://github.com/paritytech/polkadot-sdk/blob/master/bridges/snowbridge/pallets/ethereum-client/src/lib.rs#L75 + for index := startIndex; index != endIndex; index = (index - 1 + totalStates) % totalStates { beaconRoot, err := h.writer.GetFinalizedBeaconRootByIndex(uint32(index)) if err != nil { return beaconState, fmt.Errorf("GetFinalizedBeaconRootByIndex %d, error: %w", index, err) } beaconState, err = h.writer.GetFinalizedHeaderStateByBlockRoot(beaconRoot) if err != nil { - return beaconState, fmt.Errorf("GetFinalizedHeaderStateByBlockRoot %s, error: %w", beaconRoot.Hex(), err) + // As soon as it can't find a block root, it means the circular wrap around array is empty. + log.WithFields(log.Fields{"index": index, "blockRoot": beaconRoot.Hex()}).WithError(err).Info("searching for checkpoint on-chain failed") + break } - statePeriodIndex := beaconState.BeaconSlot / syncCommitteePeriod + if beaconState.BeaconSlot < slot { + log.WithFields(log.Fields{"index": index, "blockRoot": beaconRoot.Hex()}).WithError(err).Debug("unable to find a relevant on-chain header") break } // Found the beaconState - if beaconState.BeaconSlot > slot && beaconState.BeaconSlot < slot+syncCommitteePeriod && slotPeriodIndex == statePeriodIndex { - break + if beaconState.BeaconSlot > slot && beaconState.BeaconSlot < slot+syncCommitteePeriod { + return beaconState, nil } } - if beaconState.BeaconSlot > slot && beaconState.BeaconSlot < slot+syncCommitteePeriod { - return beaconState, nil - } return beaconState, fmt.Errorf("no checkpoint on chain for slot %d", slot) } diff --git a/relayer/relays/beacon/header/header_test.go b/relayer/relays/beacon/header/header_test.go index 5ff7cee5ef..358cbe9d09 100644 --- a/relayer/relays/beacon/header/header_test.go +++ b/relayer/relays/beacon/header/header_test.go @@ -3,6 +3,7 @@ package header import ( "context" "github.com/ethereum/go-ethereum/common" + "github.com/snowfork/go-substrate-rpc-client/v4/types" "github.com/snowfork/snowbridge/relayer/relays/beacon/config" "github.com/snowfork/snowbridge/relayer/relays/beacon/header/syncer/api" "github.com/snowfork/snowbridge/relayer/relays/beacon/mock" @@ -15,6 +16,8 @@ import ( "testing" ) +const MaxRedundancy = 20 + // Verifies that the closest checkpoint is populated successfully if it is not populated in the first place. func TestSyncInterimFinalizedUpdate_WithDataFromAPI(t *testing.T) { settings := config.SpecSettings{ @@ -22,7 +25,7 @@ func TestSyncInterimFinalizedUpdate_WithDataFromAPI(t *testing.T) { EpochsPerSyncCommitteePeriod: 256, DenebForkEpoch: 0, } - p := protocol.New(settings) + p := protocol.New(settings, MaxRedundancy) client := mock.API{} beaconStore := mock.Store{} @@ -80,7 +83,7 @@ func TestSyncInterimFinalizedUpdate_WithDataFromStore(t *testing.T) { EpochsPerSyncCommitteePeriod: 256, DenebForkEpoch: 0, } - p := protocol.New(settings) + p := protocol.New(settings, MaxRedundancy) client := mock.API{} beaconStore := mock.Store{} @@ -146,7 +149,7 @@ func TestSyncInterimFinalizedUpdate_WithDataFromStoreWithDifferentBlocks(t *test EpochsPerSyncCommitteePeriod: 256, DenebForkEpoch: 0, } - p := protocol.New(settings) + p := protocol.New(settings, MaxRedundancy) client := mock.API{} beaconStore := mock.Store{} @@ -212,7 +215,7 @@ func TestSyncInterimFinalizedUpdate_BeaconStateNotAvailableInAPIAndStore(t *test EpochsPerSyncCommitteePeriod: 256, DenebForkEpoch: 0, } - p := protocol.New(settings) + p := protocol.New(settings, MaxRedundancy) client := mock.API{} beaconStore := mock.Store{} @@ -256,7 +259,7 @@ func TestSyncInterimFinalizedUpdate_NoValidBlocksFound(t *testing.T) { EpochsPerSyncCommitteePeriod: 256, DenebForkEpoch: 0, } - p := protocol.New(settings) + p := protocol.New(settings, MaxRedundancy) client := mock.API{} beaconStore := mock.Store{} @@ -324,3 +327,102 @@ func TestShouldUpdate(t *testing.T) { assert.Equal(t, tt.result, result, "expected %t but found %t", tt.result, result) } } + +func TestFindLatestCheckPoint(t *testing.T) { + settings := config.SpecSettings{ + SlotsInEpoch: 4, + EpochsPerSyncCommitteePeriod: 2, + DenebForkEpoch: 0, + } + maxRedundancy := uint64(2) + p := protocol.New(settings, maxRedundancy) + // Total circular array would be 4 * 2 * 2 = 16 + client := mock.API{} + beaconStore := mock.Store{} + + headerIndex5 := common.HexToHash("0xd118e1464716db841f14ac1c3245f2b7900ee6f896ac85362deae3ff90c14c78") + headerIndex4 := common.HexToHash("0xe9d993e257b0d7ac775b8a03827209db2c7314a780c24a7fad64fd9fcee529f7") + headerIndex3 := common.HexToHash("0x7f2c1240dd714f3d74050638c642f14bf49f541d42f0808b7ae0c188c7edbb08") + headerIndex2 := common.HexToHash("0x01eaa6cbb00311f19c84965f3a9e8ddf56dd5443dfa8ea35c3e6d0b6306554b3") + headerIndex1 := common.HexToHash("0xa106b85508139ad0417cc521f41943a74908bfedbc6f548b3d1acddf60548493") + headerIndex0 := common.HexToHash("0xefef79bf51c3e02c19f9cbe718c6e226ad516153622a500bf783fce2aa8ec7c6") + headerIndex15 := common.HexToHash("0x416f890494e218d3cb32ce1ef3bd08e3acccf6e112b66db544cfcc6295bbdc2a") + headerIndex14 := common.HexToHash("0x74c4e67ca468722a7c3af52c5f96f4bbdd60b4d237ae7693863dca308e3c354c") + + h := New( + &mock.Writer{ + LastFinalizedState: state.FinalizedHeader{ + BeaconBlockRoot: common.Hash{}, + BeaconSlot: 50, + InitialCheckpointRoot: common.Hash{}, + InitialCheckpointSlot: 0, + }, + LastFinalizedStateIndex: 5, + FinalizedBeaconRootByIndex: map[uint32]types.H256{ + 5: types.H256(headerIndex5), + 4: types.H256(headerIndex4), + 3: types.H256(headerIndex3), + 2: types.H256(headerIndex2), + 1: types.H256(headerIndex1), + 0: types.H256(headerIndex0), + 15: types.H256(headerIndex15), + 14: types.H256(headerIndex14), + }, + FinalizedHeaderStateByBlockRoot: map[types.H256]state.FinalizedHeader{ + types.H256(headerIndex5): state.FinalizedHeader{ + BeaconBlockRoot: headerIndex5, + BeaconSlot: 50, + }, + types.H256(headerIndex4): state.FinalizedHeader{ + BeaconBlockRoot: headerIndex4, + BeaconSlot: 46, + }, + types.H256(headerIndex3): state.FinalizedHeader{ + BeaconBlockRoot: headerIndex3, + BeaconSlot: 42, + }, + types.H256(headerIndex2): state.FinalizedHeader{ + BeaconBlockRoot: headerIndex2, + BeaconSlot: 38, + }, + types.H256(headerIndex1): state.FinalizedHeader{ + BeaconBlockRoot: headerIndex1, + BeaconSlot: 30, + }, + types.H256(headerIndex0): state.FinalizedHeader{ + BeaconBlockRoot: headerIndex0, + BeaconSlot: 32, + }, + types.H256(headerIndex15): state.FinalizedHeader{ + BeaconBlockRoot: headerIndex15, + BeaconSlot: 20, + }, + types.H256(headerIndex14): state.FinalizedHeader{ + BeaconBlockRoot: headerIndex14, + BeaconSlot: 18, + }, + }, + }, + &client, + settings, + &beaconStore, + p, + 316, + ) + + // Slot 20 would be usable to prove slot 19 + header, err := h.findLatestCheckPoint(19) + assert.NoError(t, err) + assert.Equal(t, headerIndex15, header.BeaconBlockRoot) + assert.Equal(t, uint64(20), header.BeaconSlot) + + // No header would be within range to prove slot 4 + _, err = h.findLatestCheckPoint(4) + assert.Error(t, err) + + // Slot 46 would be usable to prove slot 19 + header, err = h.findLatestCheckPoint(40) + assert.NoError(t, err) + assert.Equal(t, headerIndex4, header.BeaconBlockRoot) + assert.Equal(t, uint64(46), header.BeaconSlot) +} diff --git a/relayer/relays/beacon/header/syncer/syncer_test.go b/relayer/relays/beacon/header/syncer/syncer_test.go index 3e94469058..b74dfb15c2 100644 --- a/relayer/relays/beacon/header/syncer/syncer_test.go +++ b/relayer/relays/beacon/header/syncer/syncer_test.go @@ -19,13 +19,14 @@ import ( ) const TestUrl = "https://lodestar-sepolia.chainsafe.io" +const MaxRedundancy = 20 func newTestRunner() *Syncer { return New(api.NewBeaconClient(TestUrl, TestUrl), &mock.Store{}, protocol.New(config.SpecSettings{ SlotsInEpoch: 32, EpochsPerSyncCommitteePeriod: 256, DenebForkEpoch: 0, - })) + }, MaxRedundancy)) } // Verifies that the Lodestar provided finalized endpoint matches the manually constructed finalized endpoint @@ -110,7 +111,7 @@ func TestGetFinalizedUpdateWithSyncCommitteeUpdateAtSlot(t *testing.T) { SlotsInEpoch: 32, EpochsPerSyncCommitteePeriod: 256, DenebForkEpoch: 0, - })) + }, MaxRedundancy)) // Manually construct a finalized update manualUpdate, err := syncer.GetFinalizedUpdateAtAttestedSlot(129, 0, true) @@ -165,7 +166,7 @@ func TestFindAttestedAndFinalizedHeadersAtBoundary(t *testing.T) { SlotsInEpoch: 32, EpochsPerSyncCommitteePeriod: 256, DenebForkEpoch: 0, - })) + }, MaxRedundancy)) attested, err := syncer.FindValidAttestedHeader(8000, 8160) assert.NoError(t, err) @@ -195,7 +196,7 @@ func TestFindAttestedAndFinalizedHeadersAtBoundary(t *testing.T) { SlotsInEpoch: 32, EpochsPerSyncCommitteePeriod: 256, DenebForkEpoch: 0, - })) + }, MaxRedundancy)) attested, err = syncer.FindValidAttestedHeader(32576, 32704) assert.NoError(t, err) @@ -225,7 +226,7 @@ func TestFindAttestedAndFinalizedHeadersAtBoundary(t *testing.T) { SlotsInEpoch: 32, EpochsPerSyncCommitteePeriod: 256, DenebForkEpoch: 0, - })) + }, MaxRedundancy)) attested, err = syncer.FindValidAttestedHeader(25076, 32736) assert.NoError(t, err) @@ -249,7 +250,7 @@ func TestFindAttestedAndFinalizedHeadersAtBoundary(t *testing.T) { SlotsInEpoch: 32, EpochsPerSyncCommitteePeriod: 256, DenebForkEpoch: 0, - })) + }, MaxRedundancy)) attested, err = syncer.FindValidAttestedHeader(32540, 32768) assert.Error(t, err) diff --git a/relayer/relays/beacon/main.go b/relayer/relays/beacon/main.go index 58b46d8688..1e6c1937c8 100644 --- a/relayer/relays/beacon/main.go +++ b/relayer/relays/beacon/main.go @@ -37,7 +37,7 @@ func (r *Relay) Start(ctx context.Context, eg *errgroup.Group) error { paraconn := parachain.NewConnection(r.config.Sink.Parachain.Endpoint, r.keypair.AsKeyringPair()) - err := paraconn.ConnectWithHeartBeat(ctx, 60 * time.Second) + err := paraconn.ConnectWithHeartBeat(ctx, 60*time.Second) if err != nil { return err } @@ -47,7 +47,7 @@ func (r *Relay) Start(ctx context.Context, eg *errgroup.Group) error { r.config.Sink.Parachain.MaxWatchedExtrinsics, ) - p := protocol.New(specSettings) + p := protocol.New(specSettings, r.config.Sink.Parachain.HeaderRedundancy) err = writer.Start(ctx, eg) if err != nil { diff --git a/relayer/relays/beacon/mock/mock_writer.go b/relayer/relays/beacon/mock/mock_writer.go index b0700e7cc5..054a99c7f2 100644 --- a/relayer/relays/beacon/mock/mock_writer.go +++ b/relayer/relays/beacon/mock/mock_writer.go @@ -12,7 +12,10 @@ import ( ) type Writer struct { - LastFinalizedState state.FinalizedHeader + LastFinalizedState state.FinalizedHeader + LastFinalizedStateIndex types.U32 + FinalizedBeaconRootByIndex map[uint32]types.H256 + FinalizedHeaderStateByBlockRoot map[types.H256]state.FinalizedHeader } func (m *Writer) GetLastExecutionHeaderState() (state.ExecutionHeader, error) { @@ -20,11 +23,11 @@ func (m *Writer) GetLastExecutionHeaderState() (state.ExecutionHeader, error) { } func (m *Writer) GetLastFinalizedStateIndex() (types.U32, error) { - return 0, nil + return m.LastFinalizedStateIndex, nil } func (m *Writer) GetFinalizedBeaconRootByIndex(index uint32) (types.H256, error) { - return types.H256{}, nil + return m.FinalizedBeaconRootByIndex[index], nil } func (m *Writer) BatchCall(ctx context.Context, extrinsic []string, calls []interface{}) error { @@ -66,7 +69,7 @@ func (m *Writer) GetLastBasicChannelNonceByAddress(address common.Address) (uint } func (m *Writer) GetFinalizedHeaderStateByBlockRoot(blockRoot types.H256) (state.FinalizedHeader, error) { - return state.FinalizedHeader{}, nil + return m.FinalizedHeaderStateByBlockRoot[blockRoot], nil } func (m *Writer) FindCheckPointBackward(slot uint64) (state.FinalizedHeader, error) { diff --git a/relayer/relays/beacon/protocol/protocol.go b/relayer/relays/beacon/protocol/protocol.go index a0935730ab..a81a6b30e2 100644 --- a/relayer/relays/beacon/protocol/protocol.go +++ b/relayer/relays/beacon/protocol/protocol.go @@ -10,12 +10,14 @@ import ( type Protocol struct { Settings config.SpecSettings SlotsPerHistoricalRoot uint64 + HeaderRedundancy uint64 } -func New(setting config.SpecSettings) *Protocol { +func New(setting config.SpecSettings, headerRedundancy uint64) *Protocol { return &Protocol{ Settings: setting, SlotsPerHistoricalRoot: setting.SlotsInEpoch * setting.EpochsPerSyncCommitteePeriod, + HeaderRedundancy: headerRedundancy, } } diff --git a/relayer/relays/beacon/store/datastore_test.go b/relayer/relays/beacon/store/datastore_test.go index efb10f75d7..75069c5883 100644 --- a/relayer/relays/beacon/store/datastore_test.go +++ b/relayer/relays/beacon/store/datastore_test.go @@ -13,6 +13,7 @@ import ( ) const TestDataStoreFile = "./" +const MaxRedundancy = 20 func TestGetBeaconState(t *testing.T) { _ = os.RemoveAll(TestDataStoreFile + BeaconStateDir) @@ -22,7 +23,7 @@ func TestGetBeaconState(t *testing.T) { SlotsInEpoch: 32, EpochsPerSyncCommitteePeriod: 256, DenebForkEpoch: 0, - })) + }, MaxRedundancy)) err := store.Connect() require.NoError(t, err) defer func() { @@ -66,7 +67,7 @@ func TestPruneOldStates(t *testing.T) { SlotsInEpoch: 32, EpochsPerSyncCommitteePeriod: 256, DenebForkEpoch: 0, - })) + }, MaxRedundancy)) err := store.Connect() require.NoError(t, err) defer func() { @@ -137,7 +138,7 @@ func TestFindBeaconStateWithinRange(t *testing.T) { SlotsInEpoch: 32, EpochsPerSyncCommitteePeriod: 256, DenebForkEpoch: 0, - }) + }, MaxRedundancy) store := New(TestDataStoreFile, 2, *p) err := store.Connect() require.NoError(t, err) diff --git a/relayer/relays/execution/config.go b/relayer/relays/execution/config.go index 1390812e11..70dd1d5cae 100644 --- a/relayer/relays/execution/config.go +++ b/relayer/relays/execution/config.go @@ -46,7 +46,7 @@ type ContractsConfig struct { } type SinkConfig struct { - Parachain config.ParachainConfig `mapstructure:"parachain"` + Parachain beaconconf.ParachainConfig `mapstructure:"parachain"` } type ChannelID [32]byte diff --git a/relayer/relays/execution/main.go b/relayer/relays/execution/main.go index 8d11993574..afe722ca5f 100644 --- a/relayer/relays/execution/main.go +++ b/relayer/relays/execution/main.go @@ -87,7 +87,7 @@ func (r *Relay) Start(ctx context.Context, eg *errgroup.Group) error { } r.gatewayContract = contract - p := protocol.New(r.config.Source.Beacon.Spec) + p := protocol.New(r.config.Source.Beacon.Spec, r.config.Sink.Parachain.HeaderRedundancy) store := store.New(r.config.Source.Beacon.DataStore.Location, r.config.Source.Beacon.DataStore.MaxEntries, *p) store.Connect() diff --git a/web/packages/test/config/beacon-relay.json b/web/packages/test/config/beacon-relay.json index b7ac5fc9d6..73534b66f6 100644 --- a/web/packages/test/config/beacon-relay.json +++ b/web/packages/test/config/beacon-relay.json @@ -18,7 +18,8 @@ "sink": { "parachain": { "endpoint": "ws://127.0.0.1:11144", - "maxWatchedExtrinsics": 8 + "maxWatchedExtrinsics": 8, + "headerRedundancy": 20 }, "updateSlotInterval": 30 } diff --git a/web/packages/test/config/execution-relay.json b/web/packages/test/config/execution-relay.json index 9bd122aeb7..f94caa75c3 100644 --- a/web/packages/test/config/execution-relay.json +++ b/web/packages/test/config/execution-relay.json @@ -25,7 +25,8 @@ "sink": { "parachain": { "endpoint": "ws://127.0.0.1:11144", - "maxWatchedExtrinsics": 8 + "maxWatchedExtrinsics": 8, + "headerRedundancy": 20 } }, "instantVerification": false,