Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Smoke test on westend #1291

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
6cee4af
Initialize for westend
yrong Sep 13, 2024
6daab71
Update beacon checkpoint
yrong Sep 13, 2024
3df67bd
add back in para threads
alistair-singh Sep 13, 2024
1d4c23a
fix out of bounds error
alistair-singh Sep 14, 2024
093d839
Smoke tests on westend
yrong Sep 17, 2024
cf0a2c8
Load config from env
yrong Sep 18, 2024
3aa5d71
Cleanup env
yrong Sep 18, 2024
63e0860
Remove penpal code
yrong Sep 18, 2024
320b3cc
Merge branch 'main' into ron/smoke-test-on-westend
yrong Sep 20, 2024
cfe98dc
Cleanup
yrong Sep 20, 2024
85e926c
Merge branch 'alistair/fix-mmr-root-validation' into ron/smoke-test-o…
yrong Sep 24, 2024
6e96161
Merge branch 'ron/smoke-test-on-westend' of https://github.com/Snowfo…
yrong Sep 24, 2024
506fe4c
Update smoke tests
yrong Sep 24, 2024
46061ec
Add westend env
yrong Sep 24, 2024
dae1e48
crontab smoke tests
yrong Sep 24, 2024
103c956
Split as two tests
yrong Sep 24, 2024
e5dec6b
Fix typo
yrong Sep 25, 2024
59b82da
Remove assets/parachain non-exist
yrong Sep 26, 2024
583bc90
Revert change
yrong Sep 26, 2024
2d97157
Wait config from env
yrong Sep 26, 2024
77ee850
Load interval from env
yrong Sep 26, 2024
333d766
Add alarm check no transfer
yrong Sep 26, 2024
c7421bd
Adds paseo UI (#1276)
claravanstaden Sep 27, 2024
db4e20a
Update api package
yrong Sep 27, 2024
f8d405a
Merge branch 'alistair/fix-mmr-root-validation' into ron/smoke-test-o…
yrong Sep 27, 2024
09b163c
Fix the merge
yrong Sep 27, 2024
11582b3
Merge branch 'main' into ron/smoke-test-on-westend
yrong Sep 27, 2024
d0c2af1
Remove unused
yrong Sep 27, 2024
02a325b
Fix find on-chain checkpoint (#1294)
claravanstaden Oct 1, 2024
d1d1ce6
Merge branch 'main' into ron/smoke-test-on-westend
claravanstaden Oct 1, 2024
1f983f0
bump version
claravanstaden Oct 1, 2024
5c5056f
Merge remote-tracking branch 'origin/ron/smoke-test-on-westend' into …
claravanstaden Oct 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/release-relayer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ on:
push:
branches:
- main
- release-v1.0.0
workflow_dispatch:

env:
Expand Down
8 changes: 4 additions & 4 deletions relayer/cmd/generate_beacon_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion relayer/cmd/import_beacon_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion relayer/cmd/import_execution_header.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion relayer/cmd/list_beacon_states.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion relayer/cmd/store_beacon_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
26 changes: 23 additions & 3 deletions relayer/relays/beacon/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package config
import (
"errors"
"fmt"
"github.com/snowfork/snowbridge/relayer/config"
)

type Config struct {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
}
22 changes: 11 additions & 11 deletions relayer/relays/beacon/header/header.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
112 changes: 107 additions & 5 deletions relayer/relays/beacon/header/header_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -15,14 +16,16 @@ 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{
SlotsInEpoch: 32,
EpochsPerSyncCommitteePeriod: 256,
DenebForkEpoch: 0,
}
p := protocol.New(settings)
p := protocol.New(settings, MaxRedundancy)
client := mock.API{}
beaconStore := mock.Store{}

Expand Down Expand Up @@ -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{}

Expand Down Expand Up @@ -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{}

Expand Down Expand Up @@ -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{}

Expand Down Expand Up @@ -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{}

Expand Down Expand Up @@ -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)
}
13 changes: 7 additions & 6 deletions relayer/relays/beacon/header/syncer/syncer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down
Loading
Loading