From 3f08d9b07c296de656512e7ee47a8884e39220f6 Mon Sep 17 00:00:00 2001 From: Ron Date: Wed, 21 Jun 2023 19:25:21 +0800 Subject: [PATCH] Fix for beefy (#863) * For sno-516 * Fix beefy relayer * Revert change * Improve scan beefy commitments * Block waiting handover commit & Error handing * Allow update in nextValidatorSet without handover * Fix resolve comments * Some polish --- .gitignore | 1 + .../contracts/scripts/configure-beefy.ts | 2 +- core/packages/contracts/src/BeefyClient.sol | 2 +- core/packages/test/config/beefy-relay.json | 1 - relayer/.vscode/launch.json | 11 ++-- relayer/chain/relaychain/connection.go | 1 - relayer/cmd/parachain_head_proof.go | 9 ++- relayer/go.mod | 2 +- relayer/relays/beefy/config.go | 6 +- relayer/relays/beefy/polkadot-listener.go | 63 +++++++++---------- relayer/relays/beefy/scanner.go | 6 +- relayer/relays/parachain/beefy-listener.go | 1 - relayer/relays/parachain/config.go | 4 +- 13 files changed, 52 insertions(+), 57 deletions(-) diff --git a/.gitignore b/.gitignore index dec02136352a2..6dda8766388ef 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,4 @@ node_modules/ .direnv .envrc parachain/build_rs_cov.profraw +compiler_config.json diff --git a/core/packages/contracts/scripts/configure-beefy.ts b/core/packages/contracts/scripts/configure-beefy.ts index 69554100cdbcf..3016aa6bb0959 100644 --- a/core/packages/contracts/scripts/configure-beefy.ts +++ b/core/packages/contracts/scripts/configure-beefy.ts @@ -81,7 +81,7 @@ function createMerkleTree(leaves: Buffer[]) { const leafHashes = leaves.map((value) => hasher(value)) const tree = new MerkleTree(leafHashes, hasher, { sortLeaves: false, - sortPairs: true, + sortPairs: false, }) return tree } diff --git a/core/packages/contracts/src/BeefyClient.sol b/core/packages/contracts/src/BeefyClient.sol index 9d63739ca7a43..5c691bc8858cc 100644 --- a/core/packages/contracts/src/BeefyClient.sol +++ b/core/packages/contracts/src/BeefyClient.sol @@ -264,7 +264,7 @@ contract BeefyClient is Ownable { revert PrevRandaoNotCaptured(); } - if (commitment.validatorSetID != currentValidatorSet.id) { + if (commitment.validatorSetID != currentValidatorSet.id && commitment.validatorSetID != nextValidatorSet.id) { revert InvalidCommitment(); } diff --git a/core/packages/test/config/beefy-relay.json b/core/packages/test/config/beefy-relay.json index 76bc27c70452d..e22dd31090f9b 100644 --- a/core/packages/test/config/beefy-relay.json +++ b/core/packages/test/config/beefy-relay.json @@ -11,7 +11,6 @@ "endpoint": "ws://127.0.0.1:8546", "gas-limit": null }, - "start-block": 0, "descendants-until-final": 3, "contracts": { "BeefyClient": null diff --git a/relayer/.vscode/launch.json b/relayer/.vscode/launch.json index 6db6a47d2b15d..ad989c17b32e4 100644 --- a/relayer/.vscode/launch.json +++ b/relayer/.vscode/launch.json @@ -5,22 +5,25 @@ "version": "0.2.0", "configurations": [ { - "name": "Start Relayer", + "name": "Start Beefy Relayer", "type": "go", "request": "launch", "mode": "auto", "program": "${workspaceFolder}/main.go", "args": [ "run", + "beefy", "--config", - "/tmp/snowbridge-e2e-config/config.toml" + "/tmp/snowbridge/beefy-relay.json", + "--ethereum.private-key", + "0x935b65c833ced92c43ef9de6bff30703d941bd92a2637cb00cfad389f5862109" ], "env": { "SNOWBRIDGE_BEEFY_KEY": "0x935b65c833ced92c43ef9de6bff30703d941bd92a2637cb00cfad389f5862109", "SNOWBRIDGE_MESSAGE_KEY": "0x8013383de6e5a891e7754ae1ef5a21e7661f1fe67cd47ca8ebf4acd6de66879a", "SNOWBRIDGE_PARACHAIN_KEY": "//Relay", - "SNOWBRIDGE_RELAYCHAIN_KEY": "//Alice", - }, + "SNOWBRIDGE_RELAYCHAIN_KEY": "//Alice" + } } ] } diff --git a/relayer/chain/relaychain/connection.go b/relayer/chain/relaychain/connection.go index 5755e3ae8f00f..c2d1e38124438 100644 --- a/relayer/chain/relaychain/connection.go +++ b/relayer/chain/relaychain/connection.go @@ -87,7 +87,6 @@ func (conn *Connection) GetMMRRootHash(blockHash types.Hash) (types.Hash, error) func (co *Connection) GenerateProofForBlock( blockNumber uint64, latestBeefyBlockHash types.Hash, - beefyActivationBlock uint64, ) (types.GenerateMMRProofResponse, error) { log.WithFields(log.Fields{ "blockNumber": blockNumber, diff --git a/relayer/cmd/parachain_head_proof.go b/relayer/cmd/parachain_head_proof.go index e4f2655cad28f..dcb2259c73e36 100644 --- a/relayer/cmd/parachain_head_proof.go +++ b/relayer/cmd/parachain_head_proof.go @@ -72,16 +72,15 @@ func ParachainHeadProofFn(cmd *cobra.Command, _ []string) error { copy(beefyBlockHash[:], beefyBlockHashHex[0:32]) relayChainBlock, _ := cmd.Flags().GetUint64("relaychain-block") - mmrProof, err := conn.GenerateProofForBlock(relayChainBlock, beefyBlockHash, 0) + mmrProof, err := conn.GenerateProofForBlock(relayChainBlock, beefyBlockHash) if err != nil { log.WithError(err).Error("Cannot connect.") return err } log.WithFields(log.Fields{ - "relayChainBlock": relayChainBlock, - "beefyBlockHash": beefyBlockHash, - "beefyActivationBlock": 0, - "mmrProof": mmrProof, + "relayChainBlock": relayChainBlock, + "beefyBlockHash": beefyBlockHash, + "mmrProof": mmrProof, }).Info("conn.GenerateProofForBlock") paraID, _ := cmd.Flags().GetUint32("parachain-id") diff --git a/relayer/go.mod b/relayer/go.mod index a64648d18baa5..d1410e786dd34 100644 --- a/relayer/go.mod +++ b/relayer/go.mod @@ -1,6 +1,6 @@ module github.com/snowfork/snowbridge/relayer -go 1.18 +go 1.20 require ( github.com/cbroglie/mustache v1.4.0 diff --git a/relayer/relays/beefy/config.go b/relayer/relays/beefy/config.go index 2ce0d558efcd1..99291b164c942 100644 --- a/relayer/relays/beefy/config.go +++ b/relayer/relays/beefy/config.go @@ -10,10 +10,8 @@ type Config struct { } type SourceConfig struct { - Polkadot config.PolkadotConfig `mapstructure:"polkadot"` - // Block number when Beefy was activated - BeefyActivationBlock uint64 `mapstructure:"beefy-activation-block"` - FastForwardDepth uint64 `mapstructure:"fast-forward-depth"` + Polkadot config.PolkadotConfig `mapstructure:"polkadot"` + FastForwardDepth uint64 `mapstructure:"fast-forward-depth"` } type SinkConfig struct { diff --git a/relayer/relays/beefy/polkadot-listener.go b/relayer/relays/beefy/polkadot-listener.go index 1d0b7af831951..5512adb34499f 100644 --- a/relayer/relays/beefy/polkadot-listener.go +++ b/relayer/relays/beefy/polkadot-listener.go @@ -41,7 +41,7 @@ func (li *PolkadotListener) Start( } li.beefyAuthoritiesKey = storageKey - requests := make(chan Request) + requests := make(chan Request, 1) eg.Go(func() error { defer close(requests) @@ -61,7 +61,7 @@ func (li *PolkadotListener) scanCommitments( currentValidatorSet uint64, requests chan<- Request, ) error { - in, err := ScanSafeCommitments(ctx, li.conn.Metadata(), li.conn.API(), currentBeefyBlock+1, li.config.Source.BeefyActivationBlock) + in, err := ScanSafeCommitments(ctx, li.conn.Metadata(), li.conn.API(), currentBeefyBlock+1) if err != nil { return fmt.Errorf("scan commitments: %w", err) } @@ -78,18 +78,28 @@ func (li *PolkadotListener) scanCommitments( return fmt.Errorf("scan safe commitments: %w", result.Error) } - if result.SignedCommitment.Commitment.ValidatorSetID == currentValidatorSet+1 { - // Workaround for https://github.com/paritytech/polkadot/pull/6577 - if uint64(result.MMRProof.Leaf.BeefyNextAuthoritySet.ID) != result.SignedCommitment.Commitment.ValidatorSetID+1 { - log.WithFields(log.Fields{ - "commitment": log.Fields{ - "blockNumber": result.SignedCommitment.Commitment.BlockNumber, - "validatorSetID": result.SignedCommitment.Commitment.ValidatorSetID, - }, - }).Info("Discarded invalid handover commitment with BeefyNextAuthoritySet not change") - continue - } - currentValidatorSet++ + committedBeefyBlock := result.SignedCommitment.Commitment.BlockNumber + validatorSetID := result.SignedCommitment.Commitment.ValidatorSetID + nextValidatorSetID := uint64(result.MMRProof.Leaf.BeefyNextAuthoritySet.ID) + + logEntry := log.WithFields(log.Fields{ + "commitment": log.Fields{ + "blockNumber": committedBeefyBlock, + "validatorSetID": validatorSetID, + "nextValidatorSetID": nextValidatorSetID, + }, + "validatorSetID": currentValidatorSet, + }) + if validatorSetID < currentValidatorSet || validatorSetID > currentValidatorSet+1 { + return fmt.Errorf("commitment has unexpected validatorSetID: blockNumber=%v validatorSetID=%v expectedValidatorSetID=%v", + committedBeefyBlock, + validatorSetID, + currentValidatorSet, + ) + } + + if validatorSetID == currentValidatorSet+1 && validatorSetID == nextValidatorSetID-1 { + validators, err := li.queryBeefyAuthorities(result.BlockHash) if err != nil { return fmt.Errorf("fetch beefy authorities at block %v: %w", result.BlockHash, err) @@ -106,15 +116,12 @@ func (li *PolkadotListener) scanCommitments( case <-ctx.Done(): return ctx.Err() case requests <- task: + logEntry.Info("New commitment with handover added to channel") + currentValidatorSet++ } - } else if result.SignedCommitment.Commitment.ValidatorSetID == currentValidatorSet { + } else if (validatorSetID == currentValidatorSet || validatorSetID == currentValidatorSet+1) && validatorSetID == nextValidatorSetID { if result.Depth > li.config.Source.FastForwardDepth { - log.WithFields(log.Fields{ - "commitment": log.Fields{ - "blockNumber": result.SignedCommitment.Commitment.BlockNumber, - "validatorSetID": result.SignedCommitment.Commitment.ValidatorSetID, - }, - }).Warn("Discarded commitment with depth not fast forward") + logEntry.Warn("Discarded commitment with depth not fast forward") continue } @@ -133,20 +140,12 @@ func (li *PolkadotListener) scanCommitments( // drop task if it can't be processed immediately select { case requests <- task: + logEntry.Info("New commitment added to channel") default: - log.WithFields(log.Fields{ - "commitment": log.Fields{ - "blockNumber": result.SignedCommitment.Commitment.BlockNumber, - "validatorSetID": result.SignedCommitment.Commitment.ValidatorSetID, - }, - }).Info("Discarded commitment") + logEntry.Warn("Discarded commitment fail adding to channel") } } else { - return fmt.Errorf("commitment has unexpected validatorSetID: blockNumber=%v validatorSetID=%v expectedValidatorSetID=%v", - result.SignedCommitment.Commitment.BlockNumber, - result.SignedCommitment.Commitment.ValidatorSetID, - currentValidatorSet, - ) + logEntry.Warn("Discarded invalid commitment") } } } diff --git a/relayer/relays/beefy/scanner.go b/relayer/relays/beefy/scanner.go index 9b7ad2a65c2a8..3188812f9b7ea 100644 --- a/relayer/relays/beefy/scanner.go +++ b/relayer/relays/beefy/scanner.go @@ -170,13 +170,13 @@ type ScanSafeCommitmentsResult struct { Error error } -func ScanSafeCommitments(ctx context.Context, meta *types.Metadata, api *gsrpc.SubstrateAPI, startBlock uint64, beefyActivationBlock uint64) (<-chan ScanSafeCommitmentsResult, error) { +func ScanSafeCommitments(ctx context.Context, meta *types.Metadata, api *gsrpc.SubstrateAPI, startBlock uint64) (<-chan ScanSafeCommitmentsResult, error) { out := make(chan ScanSafeCommitmentsResult) - go scanSafeCommitments(ctx, meta, api, startBlock, beefyActivationBlock, out) + go scanSafeCommitments(ctx, meta, api, startBlock, out) return out, nil } -func scanSafeCommitments(ctx context.Context, meta *types.Metadata, api *gsrpc.SubstrateAPI, startBlock uint64, beefyActivationBlock uint64, out chan<- ScanSafeCommitmentsResult) { +func scanSafeCommitments(ctx context.Context, meta *types.Metadata, api *gsrpc.SubstrateAPI, startBlock uint64, out chan<- ScanSafeCommitmentsResult) { defer close(out) sendError := func(err error) { diff --git a/relayer/relays/parachain/beefy-listener.go b/relayer/relays/parachain/beefy-listener.go index cd8be8414c6b9..dd9bc0f988050 100644 --- a/relayer/relays/parachain/beefy-listener.go +++ b/relayer/relays/parachain/beefy-listener.go @@ -236,7 +236,6 @@ func (li *BeefyListener) generateProof(ctx context.Context, input *ProofInput, h mmrProof, err := li.relaychainConn.GenerateProofForBlock( input.RelayBlockNumber+1, latestBeefyBlockHash, - li.config.BeefyActivationBlock, ) if err != nil { return nil, fmt.Errorf("generate MMR leaf proof: %w", err) diff --git a/relayer/relays/parachain/config.go b/relayer/relays/parachain/config.go index 61fe8aaee7a05..deb2e872d057c 100644 --- a/relayer/relays/parachain/config.go +++ b/relayer/relays/parachain/config.go @@ -14,9 +14,7 @@ type SourceConfig struct { Parachain config.ParachainConfig `mapstructure:"parachain"` Ethereum config.EthereumConfig `mapstructure:"ethereum"` Contracts SourceContractsConfig `mapstructure:"contracts"` - // Block number when Beefy was activated - BeefyActivationBlock uint64 `mapstructure:"beefy-activation-block"` - LaneID uint32 `mapstructure:"lane-id"` + LaneID uint32 `mapstructure:"lane-id"` } type SourceContractsConfig struct {