From 629a478eaf62fce4841635b2421c2d03991e7a28 Mon Sep 17 00:00:00 2001 From: ron Date: Fri, 31 May 2024 09:46:54 +0800 Subject: [PATCH 1/9] Sync beefy commitment on demand --- relayer/cmd/root.go | 1 + relayer/cmd/sync_beefy_commitment.go | 65 ++++++++++++++++ relayer/relays/beefy/ethereum-writer.go | 37 +++++---- relayer/relays/beefy/main.go | 44 +++++++++++ relayer/relays/beefy/polkadot-listener.go | 91 ++++++++++++++++++++--- 5 files changed, 214 insertions(+), 24 deletions(-) create mode 100644 relayer/cmd/sync_beefy_commitment.go diff --git a/relayer/cmd/root.go b/relayer/cmd/root.go index 11f8b794e..85b18eb65 100644 --- a/relayer/cmd/root.go +++ b/relayer/cmd/root.go @@ -36,6 +36,7 @@ func init() { rootCmd.AddCommand(storeBeaconStateCmd()) rootCmd.AddCommand(importBeaconStateCmd()) rootCmd.AddCommand(listBeaconStateCmd()) + rootCmd.AddCommand(syncBeefyCommitmentCmd()) } func Execute() { diff --git a/relayer/cmd/sync_beefy_commitment.go b/relayer/cmd/sync_beefy_commitment.go new file mode 100644 index 000000000..c16d763b2 --- /dev/null +++ b/relayer/cmd/sync_beefy_commitment.go @@ -0,0 +1,65 @@ +package cmd + +import ( + "fmt" + "log" + + "github.com/sirupsen/logrus" + "github.com/snowfork/snowbridge/relayer/chain/ethereum" + "github.com/snowfork/snowbridge/relayer/relays/beefy" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +func syncBeefyCommitmentCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "sync-latest-beefy-commitment", + Short: "Sync beefy commitment on demand", + Args: cobra.ExactArgs(0), + RunE: SyncBeefyCommitmentFn, + } + + cmd.Flags().String("config", "/tmp/snowbridge/beefy-relay.json", "Path to configuration file") + cmd.MarkFlagRequired("config") + cmd.Flags().String("private-key", "", "Ethereum private key") + cmd.Flags().String("privateKeyFile", "", "The file from which to read the private key") + cmd.Flags().Uint64P("relay-block", "b", 0, "Relay block number which contains a Parachain message") + cmd.MarkFlagRequired("relay-block") + return cmd +} + +func SyncBeefyCommitmentFn(cmd *cobra.Command, _ []string) error { + ctx := cmd.Context() + + log.SetOutput(logrus.WithFields(logrus.Fields{"logger": "stdlib"}).WriterLevel(logrus.InfoLevel)) + logrus.SetLevel(logrus.DebugLevel) + + configFile, err := cmd.Flags().GetString("config") + viper.SetConfigFile(configFile) + if err := viper.ReadInConfig(); err != nil { + return err + } + + var config beefy.Config + err = viper.Unmarshal(&config) + if err != nil { + return err + } + privateKey, _ := cmd.Flags().GetString("private-key") + privateKeyFile, _ := cmd.Flags().GetString("privateKeyFile") + if privateKey == "" && privateKeyFile == "" { + return fmt.Errorf("missing private key") + } + keypair, err := ethereum.ResolvePrivateKey(privateKey, privateKeyFile) + if err != nil { + return err + } + + relay, err := beefy.NewRelay(&config, keypair) + if err != nil { + return err + } + relayBlockNumber, _ := cmd.Flags().GetUint64("relay-block") + err = relay.SyncUpdate(ctx, relayBlockNumber) + return err +} diff --git a/relayer/relays/beefy/ethereum-writer.go b/relayer/relays/beefy/ethereum-writer.go index eb3968e12..a9b445090 100644 --- a/relayer/relays/beefy/ethereum-writer.go +++ b/relayer/relays/beefy/ethereum-writer.go @@ -40,22 +40,10 @@ func NewEthereumWriter( } func (wr *EthereumWriter) Start(ctx context.Context, eg *errgroup.Group, requests <-chan Request) error { - address := common.HexToAddress(wr.config.Contracts.BeefyClient) - contract, err := contracts.NewBeefyClient(address, wr.conn.Client()) + err := wr.initialize(ctx) if err != nil { - return fmt.Errorf("create beefy client: %w", err) + return fmt.Errorf("initialize EthereumWriter: %w", err) } - wr.contract = contract - - callOpts := bind.CallOpts{ - Context: ctx, - } - blockWaitPeriod, err := wr.contract.RandaoCommitDelay(&callOpts) - if err != nil { - return fmt.Errorf("create randao commit delay: %w", err) - } - wr.blockWaitPeriod = blockWaitPeriod.Uint64() - log.WithField("randaoCommitDelay", wr.blockWaitPeriod).Trace("Fetched randaoCommitDelay") // launch task processor eg.Go(func() error { @@ -301,3 +289,24 @@ func (wr *EthereumWriter) doSubmitFinal(ctx context.Context, commitmentHash [32] return tx, nil } + +func (wr *EthereumWriter) initialize(ctx context.Context) error { + address := common.HexToAddress(wr.config.Contracts.BeefyClient) + contract, err := contracts.NewBeefyClient(address, wr.conn.Client()) + if err != nil { + return fmt.Errorf("create beefy client: %w", err) + } + wr.contract = contract + + callOpts := bind.CallOpts{ + Context: ctx, + } + blockWaitPeriod, err := wr.contract.RandaoCommitDelay(&callOpts) + if err != nil { + return fmt.Errorf("create randao commit delay: %w", err) + } + wr.blockWaitPeriod = blockWaitPeriod.Uint64() + log.WithField("randaoCommitDelay", wr.blockWaitPeriod).Trace("Fetched randaoCommitDelay") + + return nil +} diff --git a/relayer/relays/beefy/main.go b/relayer/relays/beefy/main.go index af7a6b9fa..e18e88486 100644 --- a/relayer/relays/beefy/main.go +++ b/relayer/relays/beefy/main.go @@ -102,3 +102,47 @@ func (relay *Relay) getInitialState(ctx context.Context) (uint64, uint64, error) return latestBeefyBlock, currentValidatorSet.Id.Uint64(), nil } + +func (relay *Relay) SyncUpdate(ctx context.Context, relayBlockNumber uint64) error { + err := relay.relaychainConn.Connect(ctx) + if err != nil { + return fmt.Errorf("create relaychain connection: %w", err) + } + + err = relay.ethereumConn.Connect(ctx) + if err != nil { + return fmt.Errorf("create ethereum connection: %w", err) + } + beefyBlock, validatorSetID, err := relay.getInitialState(ctx) + if err != nil { + return fmt.Errorf("fetch BeefyClient current state: %w", err) + } + if relayBlockNumber <= beefyBlock { + log.WithFields(log.Fields{ + "validatorSetID": validatorSetID, + "beefyBlock": beefyBlock, + "relayBlock": relayBlockNumber, + }).Info("Already synced so just ignore") + return nil + } + request, err := relay.polkadotListener.generateBeefyUpdateRequest(relayBlockNumber) + if err != nil { + return fmt.Errorf("fail to generate next beefy request: %w", err) + } + err = relay.ethereumWriter.initialize(ctx) + if err != nil { + return fmt.Errorf("initialize EthereumWriter: %w", err) + } + err = relay.ethereumWriter.submit(ctx, request) + if err != nil { + return fmt.Errorf("fail to submit beefy update: %w", err) + } + updatedBeefyBlock, _, _ := relay.getInitialState(ctx) + log.WithFields(log.Fields{ + "initialValidatorSetID": validatorSetID, + "initialBeefyBlock": beefyBlock, + "blockNumber": relayBlockNumber, + "updatedBeefyBlock": updatedBeefyBlock, + }).Info("Sync beefy update success") + return nil +} diff --git a/relayer/relays/beefy/polkadot-listener.go b/relayer/relays/beefy/polkadot-listener.go index 5aebb9a0b..e12481eb3 100644 --- a/relayer/relays/beefy/polkadot-listener.go +++ b/relayer/relays/beefy/polkadot-listener.go @@ -3,6 +3,7 @@ package beefy import ( "context" "fmt" + "time" log "github.com/sirupsen/logrus" "github.com/snowfork/go-substrate-rpc-client/v4/types" @@ -13,9 +14,8 @@ import ( ) type PolkadotListener struct { - config *SourceConfig - conn *relaychain.Connection - beefyAuthoritiesKey types.StorageKey + config *SourceConfig + conn *relaychain.Connection } func NewPolkadotListener( @@ -34,12 +34,6 @@ func (li *PolkadotListener) Start( currentBeefyBlock uint64, currentValidatorSetID uint64, ) (<-chan Request, error) { - storageKey, err := types.CreateStorageKey(li.conn.Metadata(), "Beefy", "Authorities", nil, nil) - if err != nil { - return nil, fmt.Errorf("create storage key: %w", err) - } - li.beefyAuthoritiesKey = storageKey - requests := make(chan Request, 1) eg.Go(func() error { @@ -111,8 +105,12 @@ func (li *PolkadotListener) scanCommitments( } func (li *PolkadotListener) queryBeefyAuthorities(blockHash types.Hash) ([]substrate.Authority, error) { + storageKey, err := types.CreateStorageKey(li.conn.Metadata(), "Beefy", "Authorities", nil, nil) + if err != nil { + return nil, fmt.Errorf("create storage key: %w", err) + } var authorities []substrate.Authority - ok, err := li.conn.API().RPC.State.GetStorage(li.beefyAuthoritiesKey, &authorities, blockHash) + ok, err := li.conn.API().RPC.State.GetStorage(storageKey, &authorities, blockHash) if err != nil { return nil, err } @@ -150,3 +148,76 @@ func (li *PolkadotListener) queryBeefyNextAuthoritySet(blockHash types.Hash) (Be return nextAuthoritySet, nil } + +func (li *PolkadotListener) generateBeefyUpdateRequest(relayBlockNumber uint64) (Request, error) { + api := li.conn.API() + meta := li.conn.Metadata() + var request Request + var latestBeefyBlockNumber uint64 + var latestBeefyBlockHash types.Hash + for { + finalizedBeefyBlockHash, err := api.RPC.Beefy.GetFinalizedHead() + if err != nil { + return request, fmt.Errorf("fetch beefy finalized head: %w", err) + } + + finalizedBeefyBlockHeader, err := api.RPC.Chain.GetHeader(finalizedBeefyBlockHash) + if err != nil { + return request, fmt.Errorf("fetch block header: %w", err) + } + + latestBeefyBlockNumber = uint64(finalizedBeefyBlockHeader.Number) + if latestBeefyBlockNumber < relayBlockNumber { + time.Sleep(6 * time.Second) + continue + } + latestBeefyBlockHash = finalizedBeefyBlockHash + break + } + + nextFinalizedBeefyBlock, err := api.RPC.Chain.GetBlock(latestBeefyBlockHash) + if err != nil { + return request, fmt.Errorf("fetch block: %w", err) + } + + var commitment *types.SignedCommitment + for j := range nextFinalizedBeefyBlock.Justifications { + sc := types.OptionalSignedCommitment{} + if nextFinalizedBeefyBlock.Justifications[j].EngineID() == "BEEF" { + err := types.DecodeFromBytes(nextFinalizedBeefyBlock.Justifications[j].Payload(), &sc) + if err != nil { + return request, fmt.Errorf("decode BEEFY signed commitment: %w", err) + } + ok, value := sc.Unwrap() + if ok { + commitment = &value + } + } + } + if commitment == nil { + return request, fmt.Errorf("beefy block without a valid commitment") + } + + proofIsValid, proof, err := makeProof(meta, api, uint32(latestBeefyBlockNumber), latestBeefyBlockHash) + if err != nil { + return request, fmt.Errorf("proof generation for block %v at hash %v: %w", latestBeefyBlockNumber, latestBeefyBlockHash.Hex(), err) + } + if !proofIsValid { + return request, fmt.Errorf("Proof for leaf is invalid for block %v at hash %v: %w", latestBeefyBlockNumber, latestBeefyBlockHash.Hex(), err) + } + + committedBeefyBlockNumber := uint64(commitment.Commitment.BlockNumber) + committedBeefyBlockHash, err := api.RPC.Chain.GetBlockHash(uint64(committedBeefyBlockNumber)) + + validators, err := li.queryBeefyAuthorities(committedBeefyBlockHash) + if err != nil { + return request, fmt.Errorf("fetch beefy authorities at block %v: %w", committedBeefyBlockHash, err) + } + request = Request{ + Validators: validators, + SignedCommitment: *commitment, + Proof: proof, + } + + return request, nil +} From 67c52e8940ba333fdfe62db7203a69cec988fd11 Mon Sep 17 00:00:00 2001 From: ron Date: Fri, 31 May 2024 14:14:10 +0800 Subject: [PATCH 2/9] Minor fix --- relayer/cmd/sync_beefy_commitment.go | 1 - relayer/relays/beefy/main.go | 19 +++++++++++++++++-- relayer/relays/beefy/scanner.go | 4 ---- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/relayer/cmd/sync_beefy_commitment.go b/relayer/cmd/sync_beefy_commitment.go index c16d763b2..d0fd1399f 100644 --- a/relayer/cmd/sync_beefy_commitment.go +++ b/relayer/cmd/sync_beefy_commitment.go @@ -20,7 +20,6 @@ func syncBeefyCommitmentCmd() *cobra.Command { } cmd.Flags().String("config", "/tmp/snowbridge/beefy-relay.json", "Path to configuration file") - cmd.MarkFlagRequired("config") cmd.Flags().String("private-key", "", "Ethereum private key") cmd.Flags().String("privateKeyFile", "", "The file from which to read the private key") cmd.Flags().Uint64P("relay-block", "b", 0, "Relay block number which contains a Parachain message") diff --git a/relayer/relays/beefy/main.go b/relayer/relays/beefy/main.go index e18e88486..2bb090782 100644 --- a/relayer/relays/beefy/main.go +++ b/relayer/relays/beefy/main.go @@ -13,6 +13,7 @@ import ( "github.com/snowfork/snowbridge/relayer/contracts" "github.com/snowfork/snowbridge/relayer/crypto/secp256k1" + "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus" ) @@ -125,7 +126,7 @@ func (relay *Relay) SyncUpdate(ctx context.Context, relayBlockNumber uint64) err }).Info("Already synced so just ignore") return nil } - request, err := relay.polkadotListener.generateBeefyUpdateRequest(relayBlockNumber) + task, err := relay.polkadotListener.generateBeefyUpdateRequest(relayBlockNumber) if err != nil { return fmt.Errorf("fail to generate next beefy request: %w", err) } @@ -133,7 +134,21 @@ func (relay *Relay) SyncUpdate(ctx context.Context, relayBlockNumber uint64) err if err != nil { return fmt.Errorf("initialize EthereumWriter: %w", err) } - err = relay.ethereumWriter.submit(ctx, request) + state, err := relay.ethereumWriter.queryBeefyClientState(ctx) + if err != nil { + return fmt.Errorf("query beefy client state: %w", err) + } + if task.SignedCommitment.Commitment.BlockNumber <= uint32(state.LatestBeefyBlock) { + log.WithFields(logrus.Fields{ + "beefyBlockNumber": task.SignedCommitment.Commitment.BlockNumber, + "beefyBlockSynced": state.LatestBeefyBlock, + }).Info("Commitment already synced") + return nil + } + // Mandatory commitments are always signed by the next validator set recorded in + // the beefy light client + task.ValidatorsRoot = state.NextValidatorSetRoot + err = relay.ethereumWriter.submit(ctx, task) if err != nil { return fmt.Errorf("fail to submit beefy update: %w", err) } diff --git a/relayer/relays/beefy/scanner.go b/relayer/relays/beefy/scanner.go index ebaef22c9..efd0f1e0e 100644 --- a/relayer/relays/beefy/scanner.go +++ b/relayer/relays/beefy/scanner.go @@ -5,7 +5,6 @@ import ( "fmt" "time" - log "github.com/sirupsen/logrus" gsrpc "github.com/snowfork/go-substrate-rpc-client/v4" "github.com/snowfork/go-substrate-rpc-client/v4/types" "github.com/snowfork/snowbridge/relayer/crypto/keccak" @@ -76,8 +75,6 @@ func scanBlocks(ctx context.Context, meta *types.Metadata, api *gsrpc.SubstrateA } current := startBlock for { - log.Info("foo") - finalizedBlockNumber := uint64(finalizedHeader.Number) if current > finalizedBlockNumber { select { @@ -111,7 +108,6 @@ func scanBlocks(ctx context.Context, meta *types.Metadata, api *gsrpc.SubstrateA } if sessionIndex > currentSessionIndex { - log.Info("BOO") currentSessionIndex = sessionIndex } else { current++ From dba8cfc8cda1445e02d41f7136d5bd46a241e098 Mon Sep 17 00:00:00 2001 From: ron Date: Fri, 31 May 2024 14:36:49 +0800 Subject: [PATCH 3/9] More comments --- relayer/relays/beefy/main.go | 59 ++++++++++++++--------- relayer/relays/beefy/polkadot-listener.go | 2 +- 2 files changed, 36 insertions(+), 25 deletions(-) diff --git a/relayer/relays/beefy/main.go b/relayer/relays/beefy/main.go index 2bb090782..18cf7e6ad 100644 --- a/relayer/relays/beefy/main.go +++ b/relayer/relays/beefy/main.go @@ -105,59 +105,70 @@ func (relay *Relay) getInitialState(ctx context.Context) (uint64, uint64, error) } func (relay *Relay) SyncUpdate(ctx context.Context, relayBlockNumber uint64) error { + // Initialize relaychainConn err := relay.relaychainConn.Connect(ctx) if err != nil { return fmt.Errorf("create relaychain connection: %w", err) } + // Initialize ethereumConn err = relay.ethereumConn.Connect(ctx) if err != nil { return fmt.Errorf("create ethereum connection: %w", err) } - beefyBlock, validatorSetID, err := relay.getInitialState(ctx) + err = relay.ethereumWriter.initialize(ctx) if err != nil { - return fmt.Errorf("fetch BeefyClient current state: %w", err) + return fmt.Errorf("initialize EthereumWriter: %w", err) + } + + state, err := relay.ethereumWriter.queryBeefyClientState(ctx) + if err != nil { + return fmt.Errorf("query beefy client state: %w", err) } - if relayBlockNumber <= beefyBlock { + // Ignore relay block already synced + if relayBlockNumber <= state.LatestBeefyBlock { log.WithFields(log.Fields{ - "validatorSetID": validatorSetID, - "beefyBlock": beefyBlock, + "validatorSetID": state.CurrentValidatorSetID, + "beefyBlock": state.LatestBeefyBlock, "relayBlock": relayBlockNumber, - }).Info("Already synced so just ignore") + }).Info("Relay block already synced, just ignore") return nil } - task, err := relay.polkadotListener.generateBeefyUpdateRequest(relayBlockNumber) + + // generate beefy update for that specific relay block + task, err := relay.polkadotListener.generateBeefyUpdate(relayBlockNumber) if err != nil { return fmt.Errorf("fail to generate next beefy request: %w", err) } - err = relay.ethereumWriter.initialize(ctx) - if err != nil { - return fmt.Errorf("initialize EthereumWriter: %w", err) - } - state, err := relay.ethereumWriter.queryBeefyClientState(ctx) - if err != nil { - return fmt.Errorf("query beefy client state: %w", err) - } + + // Ignore commitment already synced if task.SignedCommitment.Commitment.BlockNumber <= uint32(state.LatestBeefyBlock) { log.WithFields(logrus.Fields{ "beefyBlockNumber": task.SignedCommitment.Commitment.BlockNumber, "beefyBlockSynced": state.LatestBeefyBlock, - }).Info("Commitment already synced") + }).Info("New commitment already synced, just ignore") return nil } - // Mandatory commitments are always signed by the next validator set recorded in - // the beefy light client - task.ValidatorsRoot = state.NextValidatorSetRoot + + // Submit the task + if task.SignedCommitment.Commitment.ValidatorSetID == state.CurrentValidatorSetID { + task.ValidatorsRoot = state.CurrentValidatorSetRoot + } else { + task.ValidatorsRoot = state.NextValidatorSetRoot + } err = relay.ethereumWriter.submit(ctx, task) if err != nil { return fmt.Errorf("fail to submit beefy update: %w", err) } - updatedBeefyBlock, _, _ := relay.getInitialState(ctx) + + updatedState, err := relay.ethereumWriter.queryBeefyClientState(ctx) + if err != nil { + return fmt.Errorf("query beefy client state: %w", err) + } log.WithFields(log.Fields{ - "initialValidatorSetID": validatorSetID, - "initialBeefyBlock": beefyBlock, - "blockNumber": relayBlockNumber, - "updatedBeefyBlock": updatedBeefyBlock, + "latestBeefyBlock": updatedState.LatestBeefyBlock, + "currentValidatorSetID": updatedState.CurrentValidatorSetID, + "nextValidatorSetID": updatedState.NextValidatorSetID, }).Info("Sync beefy update success") return nil } diff --git a/relayer/relays/beefy/polkadot-listener.go b/relayer/relays/beefy/polkadot-listener.go index e12481eb3..1f8db5805 100644 --- a/relayer/relays/beefy/polkadot-listener.go +++ b/relayer/relays/beefy/polkadot-listener.go @@ -149,7 +149,7 @@ func (li *PolkadotListener) queryBeefyNextAuthoritySet(blockHash types.Hash) (Be return nextAuthoritySet, nil } -func (li *PolkadotListener) generateBeefyUpdateRequest(relayBlockNumber uint64) (Request, error) { +func (li *PolkadotListener) generateBeefyUpdate(relayBlockNumber uint64) (Request, error) { api := li.conn.API() meta := li.conn.Metadata() var request Request From a886879bc42cf7a1dcf4f8bc97285f3ddda6b419 Mon Sep 17 00:00:00 2001 From: ron Date: Fri, 31 May 2024 20:59:47 +0800 Subject: [PATCH 4/9] More refactoring --- relayer/relays/beefy/ethereum-writer.go | 5 -- relayer/relays/beefy/main.go | 43 +++-------- relayer/relays/beefy/polkadot-listener.go | 34 ++------- relayer/relays/beefy/scanner.go | 87 +++++++++++------------ 4 files changed, 55 insertions(+), 114 deletions(-) diff --git a/relayer/relays/beefy/ethereum-writer.go b/relayer/relays/beefy/ethereum-writer.go index a9b445090..87446d7c7 100644 --- a/relayer/relays/beefy/ethereum-writer.go +++ b/relayer/relays/beefy/ethereum-writer.go @@ -40,11 +40,6 @@ func NewEthereumWriter( } func (wr *EthereumWriter) Start(ctx context.Context, eg *errgroup.Group, requests <-chan Request) error { - err := wr.initialize(ctx) - if err != nil { - return fmt.Errorf("initialize EthereumWriter: %w", err) - } - // launch task processor eg.Go(func() error { for { diff --git a/relayer/relays/beefy/main.go b/relayer/relays/beefy/main.go index 18cf7e6ad..103baa457 100644 --- a/relayer/relays/beefy/main.go +++ b/relayer/relays/beefy/main.go @@ -6,11 +6,8 @@ import ( "golang.org/x/sync/errgroup" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" "github.com/snowfork/snowbridge/relayer/chain/ethereum" "github.com/snowfork/snowbridge/relayer/chain/relaychain" - "github.com/snowfork/snowbridge/relayer/contracts" "github.com/snowfork/snowbridge/relayer/crypto/secp256k1" "github.com/sirupsen/logrus" @@ -57,53 +54,33 @@ func (relay *Relay) Start(ctx context.Context, eg *errgroup.Group) error { if err != nil { return fmt.Errorf("create ethereum connection: %w", err) } + err = relay.ethereumWriter.initialize(ctx) + if err != nil { + return fmt.Errorf("initialize ethereum writer: %w", err) + } - initialBeefyBlock, initialValidatorSetID, err := relay.getInitialState(ctx) + initialState, err := relay.ethereumWriter.queryBeefyClientState(ctx) if err != nil { return fmt.Errorf("fetch BeefyClient current state: %w", err) } log.WithFields(log.Fields{ - "beefyBlock": initialBeefyBlock, - "validatorSetID": initialValidatorSetID, + "beefyBlock": initialState.LatestBeefyBlock, + "validatorSetID": initialState.CurrentValidatorSetID, }).Info("Retrieved current BeefyClient state") - requests, err := relay.polkadotListener.Start(ctx, eg, initialBeefyBlock, initialValidatorSetID) + requests, err := relay.polkadotListener.Start(ctx, eg, initialState.LatestBeefyBlock, initialState.CurrentValidatorSetID) if err != nil { return fmt.Errorf("initialize polkadot listener: %w", err) } err = relay.ethereumWriter.Start(ctx, eg, requests) if err != nil { - return fmt.Errorf("initialize ethereum writer: %w", err) + return fmt.Errorf("start ethereum writer: %w", err) } return nil } -func (relay *Relay) getInitialState(ctx context.Context) (uint64, uint64, error) { - address := common.HexToAddress(relay.config.Sink.Contracts.BeefyClient) - beefyClient, err := contracts.NewBeefyClient(address, relay.ethereumConn.Client()) - if err != nil { - return 0, 0, err - } - - callOpts := bind.CallOpts{ - Context: ctx, - } - - latestBeefyBlock, err := beefyClient.LatestBeefyBlock(&callOpts) - if err != nil { - return 0, 0, err - } - - currentValidatorSet, err := beefyClient.CurrentValidatorSet(&callOpts) - if err != nil { - return 0, 0, err - } - - return latestBeefyBlock, currentValidatorSet.Id.Uint64(), nil -} - func (relay *Relay) SyncUpdate(ctx context.Context, relayBlockNumber uint64) error { // Initialize relaychainConn err := relay.relaychainConn.Connect(ctx) @@ -136,7 +113,7 @@ func (relay *Relay) SyncUpdate(ctx context.Context, relayBlockNumber uint64) err } // generate beefy update for that specific relay block - task, err := relay.polkadotListener.generateBeefyUpdate(relayBlockNumber) + task, err := relay.polkadotListener.generateBeefyUpdate(ctx, relayBlockNumber) if err != nil { return fmt.Errorf("fail to generate next beefy request: %w", err) } diff --git a/relayer/relays/beefy/polkadot-listener.go b/relayer/relays/beefy/polkadot-listener.go index 1f8db5805..dfae7b5d0 100644 --- a/relayer/relays/beefy/polkadot-listener.go +++ b/relayer/relays/beefy/polkadot-listener.go @@ -149,7 +149,7 @@ func (li *PolkadotListener) queryBeefyNextAuthoritySet(blockHash types.Hash) (Be return nextAuthoritySet, nil } -func (li *PolkadotListener) generateBeefyUpdate(relayBlockNumber uint64) (Request, error) { +func (li *PolkadotListener) generateBeefyUpdate(ctx context.Context, relayBlockNumber uint64) (Request, error) { api := li.conn.API() meta := li.conn.Metadata() var request Request @@ -175,35 +175,9 @@ func (li *PolkadotListener) generateBeefyUpdate(relayBlockNumber uint64) (Reques break } - nextFinalizedBeefyBlock, err := api.RPC.Chain.GetBlock(latestBeefyBlockHash) + commitment, proof, err := fetchCommitmentAndProof(ctx, meta, api, latestBeefyBlockHash) if err != nil { - return request, fmt.Errorf("fetch block: %w", err) - } - - var commitment *types.SignedCommitment - for j := range nextFinalizedBeefyBlock.Justifications { - sc := types.OptionalSignedCommitment{} - if nextFinalizedBeefyBlock.Justifications[j].EngineID() == "BEEF" { - err := types.DecodeFromBytes(nextFinalizedBeefyBlock.Justifications[j].Payload(), &sc) - if err != nil { - return request, fmt.Errorf("decode BEEFY signed commitment: %w", err) - } - ok, value := sc.Unwrap() - if ok { - commitment = &value - } - } - } - if commitment == nil { - return request, fmt.Errorf("beefy block without a valid commitment") - } - - proofIsValid, proof, err := makeProof(meta, api, uint32(latestBeefyBlockNumber), latestBeefyBlockHash) - if err != nil { - return request, fmt.Errorf("proof generation for block %v at hash %v: %w", latestBeefyBlockNumber, latestBeefyBlockHash.Hex(), err) - } - if !proofIsValid { - return request, fmt.Errorf("Proof for leaf is invalid for block %v at hash %v: %w", latestBeefyBlockNumber, latestBeefyBlockHash.Hex(), err) + return request, fmt.Errorf("fetch commitment and proof: %w", err) } committedBeefyBlockNumber := uint64(commitment.Commitment.BlockNumber) @@ -216,7 +190,7 @@ func (li *PolkadotListener) generateBeefyUpdate(relayBlockNumber uint64) (Reques request = Request{ Validators: validators, SignedCommitment: *commitment, - Proof: proof, + Proof: *proof, } return request, nil diff --git a/relayer/relays/beefy/scanner.go b/relayer/relays/beefy/scanner.go index efd0f1e0e..695cbf478 100644 --- a/relayer/relays/beefy/scanner.go +++ b/relayer/relays/beefy/scanner.go @@ -169,59 +169,16 @@ func scanCommitments(ctx context.Context, meta *types.Metadata, api *gsrpc.Subst return } - block, err := api.RPC.Chain.GetBlock(result.BlockHash) + commitment, proof, err := fetchCommitmentAndProof(ctx, meta, api, result.BlockHash) if err != nil { - emitError(fmt.Errorf("fetch block: %w", err)) - return - } - - var commitment *types.SignedCommitment - for j := range block.Justifications { - sc := types.OptionalSignedCommitment{} - // Filter justification by EngineID - // https://github.com/paritytech/substrate/blob/55c64bcc2af5a6e5fc3eb245e638379ebe18a58d/primitives/beefy/src/lib.rs#L114 - if block.Justifications[j].EngineID() == "BEEF" { - // Decode as SignedCommitment - // https://github.com/paritytech/substrate/blob/bcee526a9b73d2df9d5dea0f1a17677618d70b8e/primitives/beefy/src/commitment.rs#L89 - err := types.DecodeFromBytes(block.Justifications[j].Payload(), &sc) - if err != nil { - emitError(fmt.Errorf("decode signed beefy commitment: %w", err)) - return - } - ok, value := sc.Unwrap() - if ok { - commitment = &value - } - } - } - - if commitment == nil { - emitError(fmt.Errorf("expected mandatory beefy justification in block")) - return - } - - blockNumber := commitment.Commitment.BlockNumber - blockHash, err := api.RPC.Chain.GetBlockHash(uint64(blockNumber)) - if err != nil { - emitError(fmt.Errorf("fetch block hash: %w", err)) - return - - } - proofIsValid, proof, err := makeProof(meta, api, blockNumber, blockHash) - if err != nil { - emitError(fmt.Errorf("proof generation for block %v at hash %v: %w", blockNumber, blockHash.Hex(), err)) - return - } - - if !proofIsValid { - emitError(fmt.Errorf("Leaf for parent block %v at hash %v is unprovable", blockNumber, blockHash.Hex())) + emitError(fmt.Errorf("fetch commitment and proof: %w", err)) return } select { case <-ctx.Done(): return - case out <- ScanCommitmentsResult{BlockHash: blockHash, SignedCommitment: *commitment, Proof: proof}: + case out <- ScanCommitmentsResult{BlockHash: result.BlockHash, SignedCommitment: *commitment, Proof: *proof}: } } } @@ -290,3 +247,41 @@ func verifyProof(meta *types.Metadata, api *gsrpc.SubstrateAPI, proof merkle.Sim return actualRoot == expectedRoot, nil } + +func fetchCommitmentAndProof(ctx context.Context, meta *types.Metadata, api *gsrpc.SubstrateAPI, beefyBlockHash types.Hash) (*types.SignedCommitment, *merkle.SimplifiedMMRProof, error) { + beefyHeader, err := api.RPC.Chain.GetHeader(beefyBlockHash) + if err != nil { + return nil, nil, fmt.Errorf("fetch header: %w", err) + } + beefyBlock, err := api.RPC.Chain.GetBlock(beefyBlockHash) + if err != nil { + return nil, nil, fmt.Errorf("fetch block: %w", err) + } + + var commitment *types.SignedCommitment + for j := range beefyBlock.Justifications { + sc := types.OptionalSignedCommitment{} + if beefyBlock.Justifications[j].EngineID() == "BEEF" { + err := types.DecodeFromBytes(beefyBlock.Justifications[j].Payload(), &sc) + if err != nil { + return nil, nil, fmt.Errorf("decode BEEFY signed commitment: %w", err) + } + ok, value := sc.Unwrap() + if ok { + commitment = &value + } + } + } + if commitment == nil { + return nil, nil, fmt.Errorf("beefy block without a valid commitment") + } + + proofIsValid, proof, err := makeProof(meta, api, uint32(beefyHeader.Number), beefyBlockHash) + if err != nil { + return nil, nil, fmt.Errorf("proof generation for block %v at hash %v: %w", beefyHeader.Number, beefyBlockHash.Hex(), err) + } + if !proofIsValid { + return nil, nil, fmt.Errorf("Proof for leaf is invalid for block %v at hash %v: %w", beefyHeader.Number, beefyBlockHash.Hex(), err) + } + return commitment, &proof, nil +} From 10f38d48648755585737a2e88770c1745abf1f9d Mon Sep 17 00:00:00 2001 From: ron Date: Sun, 2 Jun 2024 00:11:39 +0800 Subject: [PATCH 5/9] Fix for skip mandatory commitment --- relayer/relays/beefy/main.go | 9 ++- relayer/relays/beefy/polkadot-listener.go | 82 ++++++++++++++++++----- 2 files changed, 72 insertions(+), 19 deletions(-) diff --git a/relayer/relays/beefy/main.go b/relayer/relays/beefy/main.go index 103baa457..6e60d45a9 100644 --- a/relayer/relays/beefy/main.go +++ b/relayer/relays/beefy/main.go @@ -126,9 +126,16 @@ func (relay *Relay) SyncUpdate(ctx context.Context, relayBlockNumber uint64) err }).Info("New commitment already synced, just ignore") return nil } + if task.SignedCommitment.Commitment.ValidatorSetID > state.NextValidatorSetID { + log.WithFields(log.Fields{ + "state": state, + "task": task, + }).Error("Task unexpected, wait for mandatory updates to catch up") + return fmt.Errorf("Task unexpected") + } // Submit the task - if task.SignedCommitment.Commitment.ValidatorSetID == state.CurrentValidatorSetID { + if task.SignedCommitment.Commitment.ValidatorSetID == state.CurrentValidatorSetID || task.SignedCommitment.Commitment.ValidatorSetID == state.NextValidatorSetID-1 { task.ValidatorsRoot = state.CurrentValidatorSetRoot } else { task.ValidatorsRoot = state.NextValidatorSetRoot diff --git a/relayer/relays/beefy/polkadot-listener.go b/relayer/relays/beefy/polkadot-listener.go index dfae7b5d0..ea425a013 100644 --- a/relayer/relays/beefy/polkadot-listener.go +++ b/relayer/relays/beefy/polkadot-listener.go @@ -153,17 +153,45 @@ func (li *PolkadotListener) generateBeefyUpdate(ctx context.Context, relayBlockN api := li.conn.API() meta := li.conn.Metadata() var request Request + beefyBlockHash, err := li.findNextBeefyBlock(relayBlockNumber) + if err != nil { + return request, fmt.Errorf("find match beefy block: %w", err) + } + + commitment, proof, err := fetchCommitmentAndProof(ctx, meta, api, beefyBlockHash) + if err != nil { + return request, fmt.Errorf("fetch commitment and proof: %w", err) + } + + committedBeefyBlockNumber := uint64(commitment.Commitment.BlockNumber) + committedBeefyBlockHash, err := api.RPC.Chain.GetBlockHash(uint64(committedBeefyBlockNumber)) + + validators, err := li.queryBeefyAuthorities(committedBeefyBlockHash) + if err != nil { + return request, fmt.Errorf("fetch beefy authorities at block %v: %w", committedBeefyBlockHash, err) + } + request = Request{ + Validators: validators, + SignedCommitment: *commitment, + Proof: *proof, + } + + return request, nil +} + +func (li *PolkadotListener) findLatestBeefyBlock(relayBlockNumber uint64) (types.Hash, error) { + api := li.conn.API() var latestBeefyBlockNumber uint64 var latestBeefyBlockHash types.Hash for { finalizedBeefyBlockHash, err := api.RPC.Beefy.GetFinalizedHead() if err != nil { - return request, fmt.Errorf("fetch beefy finalized head: %w", err) + return latestBeefyBlockHash, fmt.Errorf("fetch beefy finalized head: %w", err) } finalizedBeefyBlockHeader, err := api.RPC.Chain.GetHeader(finalizedBeefyBlockHash) if err != nil { - return request, fmt.Errorf("fetch block header: %w", err) + return latestBeefyBlockHash, fmt.Errorf("fetch block header: %w", err) } latestBeefyBlockNumber = uint64(finalizedBeefyBlockHeader.Number) @@ -174,24 +202,42 @@ func (li *PolkadotListener) generateBeefyUpdate(ctx context.Context, relayBlockN latestBeefyBlockHash = finalizedBeefyBlockHash break } + return latestBeefyBlockHash, nil +} - commitment, proof, err := fetchCommitmentAndProof(ctx, meta, api, latestBeefyBlockHash) - if err != nil { - return request, fmt.Errorf("fetch commitment and proof: %w", err) - } - - committedBeefyBlockNumber := uint64(commitment.Commitment.BlockNumber) - committedBeefyBlockHash, err := api.RPC.Chain.GetBlockHash(uint64(committedBeefyBlockNumber)) +func (li *PolkadotListener) findNextBeefyBlock(relayBlockNumber uint64) (types.Hash, error) { + api := li.conn.API() + nextBeefyBlockNumber := relayBlockNumber + var nextBeefyBlockHash types.Hash + var err error + for { + nextBeefyBlockHash, err = api.RPC.Chain.GetBlockHash(nextBeefyBlockNumber) + if err != nil { + return nextBeefyBlockHash, fmt.Errorf("fetch block hash: %w", err) + } + block, err := api.RPC.Chain.GetBlock(nextBeefyBlockHash) + if err != nil { + return nextBeefyBlockHash, fmt.Errorf("fetch block: %w", err) + } - validators, err := li.queryBeefyAuthorities(committedBeefyBlockHash) - if err != nil { - return request, fmt.Errorf("fetch beefy authorities at block %v: %w", committedBeefyBlockHash, err) - } - request = Request{ - Validators: validators, - SignedCommitment: *commitment, - Proof: *proof, + var commitment *types.SignedCommitment + for j := range block.Justifications { + sc := types.OptionalSignedCommitment{} + if block.Justifications[j].EngineID() == "BEEF" { + err := types.DecodeFromBytes(block.Justifications[j].Payload(), &sc) + if err != nil { + return nextBeefyBlockHash, fmt.Errorf("decode BEEFY signed commitment: %w", err) + } + ok, value := sc.Unwrap() + if ok { + commitment = &value + } + } + } + if commitment != nil { + return nextBeefyBlockHash, nil + } + nextBeefyBlockNumber++ } - return request, nil } From 98e3e74a58119717134797cfecec8a8895e43124 Mon Sep 17 00:00:00 2001 From: ron Date: Mon, 3 Jun 2024 10:36:07 +0800 Subject: [PATCH 6/9] Some refactoring --- relayer/cmd/sync_beefy_commitment.go | 12 ++++++------ relayer/relays/beefy/main.go | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/relayer/cmd/sync_beefy_commitment.go b/relayer/cmd/sync_beefy_commitment.go index d0fd1399f..444840e33 100644 --- a/relayer/cmd/sync_beefy_commitment.go +++ b/relayer/cmd/sync_beefy_commitment.go @@ -21,9 +21,9 @@ func syncBeefyCommitmentCmd() *cobra.Command { cmd.Flags().String("config", "/tmp/snowbridge/beefy-relay.json", "Path to configuration file") cmd.Flags().String("private-key", "", "Ethereum private key") - cmd.Flags().String("privateKeyFile", "", "The file from which to read the private key") - cmd.Flags().Uint64P("relay-block", "b", 0, "Relay block number which contains a Parachain message") - cmd.MarkFlagRequired("relay-block") + cmd.Flags().String("private-key-file", "", "The file from which to read the private key") + cmd.Flags().Uint64P("block-number", "b", 0, "Relay block number which contains a Parachain message") + cmd.MarkFlagRequired("block-number") return cmd } @@ -45,7 +45,7 @@ func SyncBeefyCommitmentFn(cmd *cobra.Command, _ []string) error { return err } privateKey, _ := cmd.Flags().GetString("private-key") - privateKeyFile, _ := cmd.Flags().GetString("privateKeyFile") + privateKeyFile, _ := cmd.Flags().GetString("private-key-file") if privateKey == "" && privateKeyFile == "" { return fmt.Errorf("missing private key") } @@ -58,7 +58,7 @@ func SyncBeefyCommitmentFn(cmd *cobra.Command, _ []string) error { if err != nil { return err } - relayBlockNumber, _ := cmd.Flags().GetUint64("relay-block") - err = relay.SyncUpdate(ctx, relayBlockNumber) + blockNumber, _ := cmd.Flags().GetUint64("block-number") + err = relay.OneShotSync(ctx, blockNumber) return err } diff --git a/relayer/relays/beefy/main.go b/relayer/relays/beefy/main.go index 6e60d45a9..27ed0d7b2 100644 --- a/relayer/relays/beefy/main.go +++ b/relayer/relays/beefy/main.go @@ -81,7 +81,7 @@ func (relay *Relay) Start(ctx context.Context, eg *errgroup.Group) error { return nil } -func (relay *Relay) SyncUpdate(ctx context.Context, relayBlockNumber uint64) error { +func (relay *Relay) OneShotSync(ctx context.Context, blockNumber uint64) error { // Initialize relaychainConn err := relay.relaychainConn.Connect(ctx) if err != nil { @@ -103,17 +103,17 @@ func (relay *Relay) SyncUpdate(ctx context.Context, relayBlockNumber uint64) err return fmt.Errorf("query beefy client state: %w", err) } // Ignore relay block already synced - if relayBlockNumber <= state.LatestBeefyBlock { + if blockNumber <= state.LatestBeefyBlock { log.WithFields(log.Fields{ "validatorSetID": state.CurrentValidatorSetID, "beefyBlock": state.LatestBeefyBlock, - "relayBlock": relayBlockNumber, + "relayBlock": blockNumber, }).Info("Relay block already synced, just ignore") return nil } // generate beefy update for that specific relay block - task, err := relay.polkadotListener.generateBeefyUpdate(ctx, relayBlockNumber) + task, err := relay.polkadotListener.generateBeefyUpdate(ctx, blockNumber) if err != nil { return fmt.Errorf("fail to generate next beefy request: %w", err) } From 715ac5a1c8030dac8a6ce4d3a899d48083d4eaa3 Mon Sep 17 00:00:00 2001 From: ron Date: Mon, 3 Jun 2024 13:53:51 +0800 Subject: [PATCH 7/9] Find for next beefy block --- relayer/relays/beefy/polkadot-listener.go | 93 ++++++++++++----------- 1 file changed, 47 insertions(+), 46 deletions(-) diff --git a/relayer/relays/beefy/polkadot-listener.go b/relayer/relays/beefy/polkadot-listener.go index 4a188e104..9c55caf84 100644 --- a/relayer/relays/beefy/polkadot-listener.go +++ b/relayer/relays/beefy/polkadot-listener.go @@ -151,65 +151,66 @@ func (li *PolkadotListener) generateBeefyUpdate(ctx context.Context, relayBlockN return request, nil } -func (li *PolkadotListener) findLatestBeefyBlock(relayBlockNumber uint64) (types.Hash, error) { +func (li *PolkadotListener) findNextBeefyBlock(blockNumber uint64) (types.Hash, error) { api := li.conn.API() - var latestBeefyBlockNumber uint64 - var latestBeefyBlockHash types.Hash + var nextBeefyBlockHash, finalizedBeefyBlockHash types.Hash + var err error + nextBeefyBlockNumber := blockNumber for { - finalizedBeefyBlockHash, err := api.RPC.Beefy.GetFinalizedHead() + finalizedBeefyBlockHash, err = api.RPC.Beefy.GetFinalizedHead() if err != nil { - return latestBeefyBlockHash, fmt.Errorf("fetch beefy finalized head: %w", err) + return nextBeefyBlockHash, fmt.Errorf("fetch beefy finalized head: %w", err) } - finalizedBeefyBlockHeader, err := api.RPC.Chain.GetHeader(finalizedBeefyBlockHash) if err != nil { - return latestBeefyBlockHash, fmt.Errorf("fetch block header: %w", err) + return nextBeefyBlockHash, fmt.Errorf("fetch block header: %w", err) } - - latestBeefyBlockNumber = uint64(finalizedBeefyBlockHeader.Number) - if latestBeefyBlockNumber < relayBlockNumber { + latestBeefyBlockNumber := uint64(finalizedBeefyBlockHeader.Number) + if latestBeefyBlockNumber <= nextBeefyBlockNumber { + // The relay block not finalized yet, just wait and retry time.Sleep(6 * time.Second) continue - } - latestBeefyBlockHash = finalizedBeefyBlockHash - break - } - return latestBeefyBlockHash, nil -} - -func (li *PolkadotListener) findNextBeefyBlock(relayBlockNumber uint64) (types.Hash, error) { - api := li.conn.API() - nextBeefyBlockNumber := relayBlockNumber - var nextBeefyBlockHash types.Hash - var err error - for { - nextBeefyBlockHash, err = api.RPC.Chain.GetBlockHash(nextBeefyBlockNumber) - if err != nil { - return nextBeefyBlockHash, fmt.Errorf("fetch block hash: %w", err) - } - block, err := api.RPC.Chain.GetBlock(nextBeefyBlockHash) - if err != nil { - return nextBeefyBlockHash, fmt.Errorf("fetch block: %w", err) - } - - var commitment *types.SignedCommitment - for j := range block.Justifications { - sc := types.OptionalSignedCommitment{} - if block.Justifications[j].EngineID() == "BEEF" { - err := types.DecodeFromBytes(block.Justifications[j].Payload(), &sc) + } else if latestBeefyBlockNumber <= nextBeefyBlockNumber+600 { + // The relay block has been finalized not long ago(1 hour), just return the finalized block + nextBeefyBlockHash = finalizedBeefyBlockHash + break + } else { + // The relay block has been finalized for a long time, in this case return the next block + // which contains a beefy justification + for { + if nextBeefyBlockNumber == latestBeefyBlockNumber { + nextBeefyBlockHash = finalizedBeefyBlockHash + break + } + nextBeefyBlockHash, err = api.RPC.Chain.GetBlockHash(nextBeefyBlockNumber) if err != nil { - return nextBeefyBlockHash, fmt.Errorf("decode BEEFY signed commitment: %w", err) + return nextBeefyBlockHash, fmt.Errorf("fetch block hash: %w", err) } - ok, value := sc.Unwrap() - if ok { - commitment = &value + block, err := api.RPC.Chain.GetBlock(nextBeefyBlockHash) + if err != nil { + return nextBeefyBlockHash, fmt.Errorf("fetch block: %w", err) } + + var commitment *types.SignedCommitment + for j := range block.Justifications { + sc := types.OptionalSignedCommitment{} + if block.Justifications[j].EngineID() == "BEEF" { + err := types.DecodeFromBytes(block.Justifications[j].Payload(), &sc) + if err != nil { + return nextBeefyBlockHash, fmt.Errorf("decode BEEFY signed commitment: %w", err) + } + ok, value := sc.Unwrap() + if ok { + commitment = &value + } + } + } + if commitment != nil { + return nextBeefyBlockHash, nil + } + nextBeefyBlockNumber++ } } - if commitment != nil { - return nextBeefyBlockHash, nil - } - nextBeefyBlockNumber++ } - + return nextBeefyBlockHash, nil } From 913960e24144370f423be8fcc9fd482d87002c90 Mon Sep 17 00:00:00 2001 From: ron Date: Mon, 3 Jun 2024 18:40:39 +0800 Subject: [PATCH 8/9] Improve log --- relayer/relays/beefy/main.go | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/relayer/relays/beefy/main.go b/relayer/relays/beefy/main.go index 27ed0d7b2..bc0425971 100644 --- a/relayer/relays/beefy/main.go +++ b/relayer/relays/beefy/main.go @@ -10,7 +10,6 @@ import ( "github.com/snowfork/snowbridge/relayer/chain/relaychain" "github.com/snowfork/snowbridge/relayer/crypto/secp256k1" - "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus" ) @@ -118,20 +117,24 @@ func (relay *Relay) OneShotSync(ctx context.Context, blockNumber uint64) error { return fmt.Errorf("fail to generate next beefy request: %w", err) } - // Ignore commitment already synced + // Ignore commitment earlier than LatestBeefyBlock which is outdated if task.SignedCommitment.Commitment.BlockNumber <= uint32(state.LatestBeefyBlock) { - log.WithFields(logrus.Fields{ - "beefyBlockNumber": task.SignedCommitment.Commitment.BlockNumber, - "beefyBlockSynced": state.LatestBeefyBlock, - }).Info("New commitment already synced, just ignore") + log.WithFields(log.Fields{ + "latestBeefyBlock": state.LatestBeefyBlock, + "currentValidatorSetID": state.CurrentValidatorSetID, + "nextValidatorSetID": state.NextValidatorSetID, + "blockNumberToSync": task.SignedCommitment.Commitment.BlockNumber, + }).Info("Commitment outdated, just ignore") return nil } if task.SignedCommitment.Commitment.ValidatorSetID > state.NextValidatorSetID { log.WithFields(log.Fields{ - "state": state, - "task": task, - }).Error("Task unexpected, wait for mandatory updates to catch up") - return fmt.Errorf("Task unexpected") + "latestBeefyBlock": state.LatestBeefyBlock, + "currentValidatorSetID": state.CurrentValidatorSetID, + "nextValidatorSetID": state.NextValidatorSetID, + "validatorSetIDToSync": task.SignedCommitment.Commitment.ValidatorSetID, + }).Warn("Task unexpected, wait for mandatory updates to catch up first") + return nil } // Submit the task From edd9f21c0b6b972928dc48a4c93e58c1867bbc0b Mon Sep 17 00:00:00 2001 From: ron Date: Mon, 3 Jun 2024 18:47:59 +0800 Subject: [PATCH 9/9] Remove check unrelated --- relayer/relays/beefy/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relayer/relays/beefy/main.go b/relayer/relays/beefy/main.go index bc0425971..1222f88a7 100644 --- a/relayer/relays/beefy/main.go +++ b/relayer/relays/beefy/main.go @@ -138,7 +138,7 @@ func (relay *Relay) OneShotSync(ctx context.Context, blockNumber uint64) error { } // Submit the task - if task.SignedCommitment.Commitment.ValidatorSetID == state.CurrentValidatorSetID || task.SignedCommitment.Commitment.ValidatorSetID == state.NextValidatorSetID-1 { + if task.SignedCommitment.Commitment.ValidatorSetID == state.CurrentValidatorSetID { task.ValidatorsRoot = state.CurrentValidatorSetRoot } else { task.ValidatorsRoot = state.NextValidatorSetRoot