diff --git a/relayer/chain/ethereum/message.go b/relayer/chain/ethereum/message.go index c1356a5087..8a038a4610 100644 --- a/relayer/chain/ethereum/message.go +++ b/relayer/chain/ethereum/message.go @@ -9,11 +9,8 @@ import ( etypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rlp" etrie "github.com/ethereum/go-ethereum/trie" - "github.com/sirupsen/logrus" "github.com/snowfork/go-substrate-rpc-client/v4/types" "github.com/snowfork/snowbridge/relayer/chain/parachain" - - log "github.com/sirupsen/logrus" ) func MakeMessageFromEvent(event *etypes.Log, receiptsTrie *etrie.Trie) (*parachain.Message, error) { @@ -47,18 +44,9 @@ func MakeMessageFromEvent(event *etypes.Log, receiptsTrie *etrie.Trie) (*paracha Data: event.Data, }, Proof: parachain.Proof{ - BlockHash: types.NewH256(event.BlockHash.Bytes()), - TxIndex: types.NewU32(uint32(event.TxIndex)), - Data: proof, + ReceiptProof: proof, }, } - log.WithFields(logrus.Fields{ - "EventLog": m.EventLog, - "Proof": m.Proof, - "txHash": event.TxHash.Hex(), - "BlockNumber": event.BlockNumber, - }).Debug("Generated message from Ethereum log") - return &m, nil } diff --git a/relayer/chain/ethereum/message_test.go b/relayer/chain/ethereum/message_test.go index e9c953b222..6d1c547a0f 100644 --- a/relayer/chain/ethereum/message_test.go +++ b/relayer/chain/ethereum/message_test.go @@ -65,7 +65,7 @@ func TestMessage_Proof(t *testing.T) { if err != nil { panic(err) } - proofNodes := TestProof(*msg.Proof.Data) + proofNodes := TestProof(*msg.Proof.ReceiptProof) provenReceipt, err := gethTrie.VerifyProof(block.ReceiptHash(), key, &proofNodes) assert.Nil(t, err) assert.Equal(t, provenReceipt, receipt5Encoded) diff --git a/relayer/chain/parachain/message.go b/relayer/chain/parachain/message.go index c8c2ff6df8..5f3a29c4ce 100644 --- a/relayer/chain/parachain/message.go +++ b/relayer/chain/parachain/message.go @@ -9,6 +9,8 @@ import ( gethCommon "github.com/ethereum/go-ethereum/common" "github.com/snowfork/go-substrate-rpc-client/v4/types" + "github.com/snowfork/snowbridge/relayer/relays/beacon/header/syncer/json" + "github.com/snowfork/snowbridge/relayer/relays/beacon/header/syncer/scale" "github.com/snowfork/snowbridge/relayer/relays/util" ) @@ -24,9 +26,8 @@ type Message struct { } type Proof struct { - BlockHash types.H256 - TxIndex types.U32 - Data *ProofData + ReceiptProof *ProofData + ExecutionProof scale.HeaderUpdatePayload } type ProofData struct { @@ -36,7 +37,7 @@ type ProofData struct { type MessageJSON struct { EventLog EventLogJSON `json:"event_log"` - Proof ProofJSON + Proof ProofJSON `json:"proof"` } type EventLogJSON struct { @@ -46,9 +47,8 @@ type EventLogJSON struct { } type ProofJSON struct { - BlockHash string `json:"block_hash"` - TxIndex uint32 `json:"tx_index"` - Data *ProofDataJSON `json:"data"` + ReceiptProof *ProofDataJSON `json:"receipt_proof"` + ExecutionProof json.HeaderUpdate `json:"execution_proof"` } type ProofDataJSON struct { @@ -83,12 +83,11 @@ func (m Message) ToJSON() MessageJSON { Data: m.EventLog.Data.Hex(), }, Proof: ProofJSON{ - BlockHash: m.Proof.BlockHash.Hex(), - TxIndex: uint32(m.Proof.TxIndex), - Data: &ProofDataJSON{ - Keys: util.ScaleBytesToArrayHexArray(m.Proof.Data.Keys), - Values: util.ScaleBytesToArrayHexArray(m.Proof.Data.Values), + ReceiptProof: &ProofDataJSON{ + Keys: util.ScaleBytesToArrayHexArray(m.Proof.ReceiptProof.Keys), + Values: util.ScaleBytesToArrayHexArray(m.Proof.ReceiptProof.Values), }, + ExecutionProof: m.Proof.ExecutionProof.ToJSON(), }, } } @@ -105,8 +104,8 @@ func (e *EventLogJSON) RemoveLeadingZeroHashes() { } func (p *ProofJSON) RemoveLeadingZeroHashes() { - p.BlockHash = removeLeadingZeroHash(p.BlockHash) - p.Data.RemoveLeadingZeroHashes() + p.ReceiptProof.RemoveLeadingZeroHashes() + p.ExecutionProof.RemoveLeadingZeroHashes() } func (p *ProofDataJSON) RemoveLeadingZeroHashes() { diff --git a/relayer/chain/parachain/writer.go b/relayer/chain/parachain/writer.go index 1838183645..2959898206 100644 --- a/relayer/chain/parachain/writer.go +++ b/relayer/chain/parachain/writer.go @@ -361,27 +361,6 @@ func (wr *ParachainWriter) getNumberFromParachain(pallet, storage string) (uint6 return uint64(number), nil } -func (wr *ParachainWriter) GetCompactExecutionHeaderStateByBlockHash(blockHash types.H256) (state.CompactExecutionHeaderState, error) { - var headerState state.CompactExecutionHeaderState - key, err := types.CreateStorageKey(wr.conn.Metadata(), "EthereumBeaconClient", "ExecutionHeaders", blockHash[:], nil) - if err != nil { - return headerState, fmt.Errorf("create storage key for ExecutionHeaders: %w", err) - } - - var compactExecutionHeader scale.CompactExecutionHeader - _, err = wr.conn.API().RPC.State.GetStorageLatest(key, &compactExecutionHeader) - if err != nil { - return headerState, fmt.Errorf("get storage for ExecutionHeaders (err): %w", err) - } - headerState = state.CompactExecutionHeaderState{ - ParentHash: common.Hash(compactExecutionHeader.ParentHash), - BlockNumber: uint64(compactExecutionHeader.BlockNumber.Int64()), - StateRoot: common.Hash(compactExecutionHeader.StateRoot), - ReceiptsRoot: common.Hash(compactExecutionHeader.ReceiptsRoot), - } - return headerState, nil -} - func (wr *ParachainWriter) GetLastFinalizedStateIndex() (types.U32, error) { var index types.U32 key, err := types.CreateStorageKey(wr.conn.Metadata(), "EthereumBeaconClient", "FinalizedBeaconStateIndex", nil, nil) diff --git a/relayer/cmd/generate_beacon_data.go b/relayer/cmd/generate_beacon_data.go index 6f480dd1c9..72d98dee96 100644 --- a/relayer/cmd/generate_beacon_data.go +++ b/relayer/cmd/generate_beacon_data.go @@ -29,10 +29,10 @@ import ( "github.com/spf13/viper" ) -func generateBeaconDataCmd() *cobra.Command { +func generateBeaconFixtureCmd() *cobra.Command { cmd := &cobra.Command{ - Use: "generate-beacon-data", - Short: "Generate beacon data.", + Use: "generate-beacon-fixture", + Short: "Generate beacon fixture.", Args: cobra.ExactArgs(0), RunE: generateBeaconTestFixture, } @@ -40,7 +40,6 @@ func generateBeaconDataCmd() *cobra.Command { cmd.Flags().String("url", "http://127.0.0.1:9596", "Beacon URL") cmd.Flags().Bool("wait_until_next_period", true, "Waiting until next period") cmd.Flags().Uint32("nonce", 1, "Nonce of the inbound message") - cmd.Flags().String("test_case", "register_token", "Inbound test case") return cmd } @@ -71,25 +70,40 @@ func generateExecutionUpdateCmd() *cobra.Command { return cmd } +func generateInboundFixtureCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "generate-inbound-fixture", + Short: "Generate inbound fixture.", + Args: cobra.ExactArgs(0), + RunE: generateInboundFixture, + } + + cmd.Flags().String("url", "http://127.0.0.1:9596", "Beacon URL") + cmd.Flags().Uint32("nonce", 1, "Nonce of the inbound message") + cmd.Flags().String("test_case", "register_token", "Inbound test case") + return cmd +} + type Data struct { CheckpointUpdate beaconjson.CheckPoint SyncCommitteeUpdate beaconjson.Update FinalizedHeaderUpdate beaconjson.Update HeaderUpdate beaconjson.HeaderUpdate - InboundMessageTest InboundMessageTest + InboundMessage parachain.MessageJSON + TestCase string } -type InboundMessageTest struct { - ExecutionHeader beaconjson.CompactExecutionHeader `json:"execution_header"` - Message parachain.MessageJSON `json:"message"` +type InboundFixture struct { + FinalizedHeaderUpdate beaconjson.Update `json:"update"` + Message parachain.MessageJSON `json:"message"` } const ( - pathToBeaconBenchmarkData = "polkadot-sdk/bridges/snowbridge/pallets/ethereum-client/src/benchmarking/fixtures.rs" - pathToBenchmarkDataTemplate = "polkadot-sdk/bridges/snowbridge/templates/benchmarking-fixtures.mustache" - pathToBeaconTestFixtureFiles = "polkadot-sdk/bridges/snowbridge/pallets/ethereum-client/tests/fixtures" - pathToInboundQueueFixtureTemplate = "polkadot-sdk/bridges/snowbridge/templates/%s.mustache" - pathToInboundQueueFixtureData = "polkadot-sdk/bridges/snowbridge/pallets/inbound-queue/fixtures/src/%s.rs" + pathToBeaconTestFixtureFiles = "polkadot-sdk/bridges/snowbridge/pallets/ethereum-client/tests/fixtures" + pathToInboundQueueFixtureTemplate = "polkadot-sdk/bridges/snowbridge/templates/beacon-fixtures.mustache" + pathToInboundQueueFixtureData = "polkadot-sdk/bridges/snowbridge/pallets/ethereum-client/fixtures/src/lib.rs" + pathToInboundQueueFixtureTestCaseTemplate = "polkadot-sdk/bridges/snowbridge/templates/inbound-fixtures.mustache" + pathToInboundQueueFixtureTestCaseData = "polkadot-sdk/bridges/snowbridge/pallets/inbound-queue/fixtures/src/%s.rs" ) // Only print the hex encoded call as output of this command @@ -147,7 +161,7 @@ func generateBeaconTestFixture(cmd *cobra.Command, _ []string) error { return err } - viper.SetConfigFile("web/packages/test/config/beacon-relay.json") + viper.SetConfigFile("/tmp/snowbridge/beacon-relay.json") if err = viper.ReadInConfig(); err != nil { return err } @@ -199,10 +213,6 @@ func generateBeaconTestFixture(cmd *cobra.Command, _ []string) error { initialSyncHeaderSlot := initialSync.Header.Slot initialSyncPeriod := s.ComputeSyncPeriodAtSlot(initialSyncHeaderSlot) initialEpoch := s.ComputeEpochAtSlot(initialSyncHeaderSlot) - log.WithFields(log.Fields{ - "epoch": initialEpoch, - "period": initialSyncPeriod, - }).Info("created initial sync file") // generate SyncCommitteeUpdate for filling the missing NextSyncCommittee in initial checkpoint syncCommitteeUpdateScale, err := s.GetSyncCommitteePeriodUpdate(initialSyncPeriod) @@ -210,30 +220,31 @@ func generateBeaconTestFixture(cmd *cobra.Command, _ []string) error { return fmt.Errorf("get sync committee update: %w", err) } syncCommitteeUpdate := syncCommitteeUpdateScale.Payload.ToJSON() + log.WithFields(log.Fields{ + "epoch": initialEpoch, + "period": initialSyncPeriod, + }).Info("created initial sync file") err = writeJSONToFile(syncCommitteeUpdate, fmt.Sprintf("%s/%s", pathToBeaconTestFixtureFiles, "sync-committee-update.json")) if err != nil { return err } log.Info("created sync committee update file") - // get inbound message data + // get inbound message data start channelID := executionConfig.Source.ChannelID address := common.HexToAddress(executionConfig.Source.Contracts.Gateway) gatewayContract, err := contracts.NewGateway(address, ethconn.Client()) if err != nil { return err } - nonce, err := cmd.Flags().GetUint32("nonce") if err != nil { return err } - event, err := getEthereumEvent(ctx, gatewayContract, channelID, nonce) if err != nil { return err } - receiptTrie, err := headerCache.GetReceiptTrie(ctx, event.Raw.BlockHash) if err != nil { return err @@ -267,8 +278,6 @@ func generateBeaconTestFixture(cmd *cobra.Command, _ []string) error { return err } - messageJSON := inboundMessage.ToJSON() - if blockNumber == messageBlockNumber { log.WithFields(log.Fields{ "slot": beaconBlock.Data.Message.Slot, @@ -286,33 +295,24 @@ func generateBeaconTestFixture(cmd *cobra.Command, _ []string) error { if err != nil { return fmt.Errorf("get header update: %w", err) } + inboundMessage.Proof.ExecutionProof = headerUpdateScale headerUpdate := headerUpdateScale.ToJSON() log.WithField("blockNumber", blockNumber).Info("found beacon block by slot") - err = writeJSONToFile(headerUpdate, fmt.Sprintf("%s/%s", pathToBeaconTestFixtureFiles, "execution-header-update.json")) + messageJSON := inboundMessage.ToJSON() + + err = writeJSONToFile(headerUpdate, fmt.Sprintf("%s/%s", pathToBeaconTestFixtureFiles, "execution-proof.json")) if err != nil { return err } log.Info("created execution update file") - - compactBeaconHeader := beaconjson.CompactExecutionHeader{ - ParentHash: headerUpdate.ExecutionHeader.Deneb.ParentHash, - StateRoot: headerUpdate.ExecutionHeader.Deneb.StateRoot, - ReceiptsRoot: headerUpdate.ExecutionHeader.Deneb.ReceiptsRoot, - BlockNumber: headerUpdate.ExecutionHeader.Deneb.BlockNumber, - } - - inboundMessageTest := InboundMessageTest{ - ExecutionHeader: compactBeaconHeader, - Message: messageJSON, - } - - err = writeJSONToFile(inboundMessageTest, fmt.Sprintf("%s/%s", pathToBeaconTestFixtureFiles, "inbound-message.json")) + err = writeJSONToFile(messageJSON, fmt.Sprintf("%s/%s", pathToBeaconTestFixtureFiles, "inbound-message.json")) if err != nil { return err } log.Info("created inbound message file") + // get inbound message data end finalizedUpdate := finalizedUpdateAfterMessage.Payload.ToJSON() if finalizedUpdate.AttestedHeader.Slot <= initialSyncHeaderSlot { @@ -335,67 +335,31 @@ func generateBeaconTestFixture(cmd *cobra.Command, _ []string) error { "period": finalizedPeriod, }).Info("created finalized header update file") - // Generate benchmark fixture - log.Info("now updating benchmarking data files") - + // Generate benchmark fixture and inbound fixture // Rust file hexes require the 0x of hashes to be removed initialSync.RemoveLeadingZeroHashes() syncCommitteeUpdate.RemoveLeadingZeroHashes() finalizedUpdate.RemoveLeadingZeroHashes() headerUpdate.RemoveLeadingZeroHashes() - - log.WithFields(log.Fields{ - "location": pathToBeaconTestFixtureFiles, - "template": pathToBenchmarkDataTemplate, - }).Info("rendering file using mustache") - - inboundMessageTest.Message.RemoveLeadingZeroHashes() - inboundMessageTest.ExecutionHeader.RemoveLeadingZeroHashes() + messageJSON.RemoveLeadingZeroHashes() data := Data{ CheckpointUpdate: initialSync, SyncCommitteeUpdate: syncCommitteeUpdate, FinalizedHeaderUpdate: finalizedUpdate, HeaderUpdate: headerUpdate, - InboundMessageTest: inboundMessageTest, - } - - // writing beacon fixtures - rendered, err := mustache.RenderFile(pathToBenchmarkDataTemplate, data) - if err != nil { - return fmt.Errorf("render beacon benchmark fixture: %w", err) - } - - log.WithFields(log.Fields{ - "location": pathToBeaconBenchmarkData, - }).Info("writing result file") - - err = writeBenchmarkDataFile(fmt.Sprintf("%s", pathToBeaconBenchmarkData), rendered) - if err != nil { - return err - } - - // writing inbound queue fixtures - testCase, err := cmd.Flags().GetString("test_case") - if err != nil { - return err - } - if testCase != "register_token" && testCase != "send_token" { - return fmt.Errorf("invalid test case: %s", testCase) + InboundMessage: messageJSON, } - pathToInboundQueueFixtureTemplate := fmt.Sprintf(pathToInboundQueueFixtureTemplate, testCase) - pathToInboundQueueFixtureData := fmt.Sprintf(pathToInboundQueueFixtureData, testCase) - rendered, err = mustache.RenderFile(pathToInboundQueueFixtureTemplate, data) + // writing beacon inbound fixtures + rendered, err := mustache.RenderFile(pathToInboundQueueFixtureTemplate, data) if err != nil { return fmt.Errorf("render inbound queue benchmark fixture: %w", err) } - log.WithFields(log.Fields{ "location": pathToInboundQueueFixtureData, }).Info("writing result file") - - err = writeBenchmarkDataFile(fmt.Sprintf("%s", pathToInboundQueueFixtureData), rendered) + err = writeRawDataFile(fmt.Sprintf("%s", pathToInboundQueueFixtureData), rendered) if err != nil { return err } @@ -469,7 +433,7 @@ func writeJSONToFile(data interface{}, path string) error { return nil } -func writeBenchmarkDataFile(path string, fileContents string) error { +func writeRawDataFile(path string, fileContents string) error { f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755) if err != nil { @@ -662,3 +626,167 @@ func getFinalizedUpdate(s syncer.Syncer, eventBlockNumber uint64) (*scale.Update return &finalizedUpdate, nil } + +func generateInboundFixture(cmd *cobra.Command, _ []string) error { + err := func() error { + ctx := context.Background() + + endpoint, err := cmd.Flags().GetString("url") + if err != nil { + return err + } + + viper.SetConfigFile("/tmp/snowbridge/beacon-relay.json") + if err = viper.ReadInConfig(); err != nil { + return err + } + + var conf beaconConf.Config + err = viper.Unmarshal(&conf) + if err != nil { + return err + } + + log.WithFields(log.Fields{"endpoint": endpoint}).Info("connecting to beacon API") + s := syncer.New(endpoint, conf.Source.Beacon.Spec) + + viper.SetConfigFile("/tmp/snowbridge/execution-relay-asset-hub.json") + + if err = viper.ReadInConfig(); err != nil { + return err + } + + var executionConfig executionConf.Config + err = viper.Unmarshal(&executionConfig, viper.DecodeHook(execution.HexHookFunc())) + if err != nil { + return fmt.Errorf("unable to parse execution relay config: %w", err) + } + + ethconn := ethereum.NewConnection(&executionConfig.Source.Ethereum, nil) + err = ethconn.Connect(ctx) + if err != nil { + return err + } + + headerCache, err := ethereum.NewHeaderBlockCache( + ðereum.DefaultBlockLoader{Conn: ethconn}, + ) + if err != nil { + return err + } + + // get inbound message data start + channelID := executionConfig.Source.ChannelID + address := common.HexToAddress(executionConfig.Source.Contracts.Gateway) + gatewayContract, err := contracts.NewGateway(address, ethconn.Client()) + if err != nil { + return err + } + nonce, err := cmd.Flags().GetUint32("nonce") + if err != nil { + return err + } + event, err := getEthereumEvent(ctx, gatewayContract, channelID, nonce) + if err != nil { + return err + } + receiptTrie, err := headerCache.GetReceiptTrie(ctx, event.Raw.BlockHash) + if err != nil { + return err + } + inboundMessage, err := ethereum.MakeMessageFromEvent(&event.Raw, receiptTrie) + if err != nil { + return err + } + messageBlockNumber := event.Raw.BlockNumber + + log.WithFields(log.Fields{ + "message": inboundMessage, + "blockHash": event.Raw.BlockHash.Hex(), + "blockNumber": messageBlockNumber, + }).Info("event is at block") + + finalizedUpdateAfterMessage, err := getFinalizedUpdate(*s, messageBlockNumber) + if err != nil { + return err + } + + finalizedHeaderSlot := uint64(finalizedUpdateAfterMessage.Payload.FinalizedHeader.Slot) + + beaconBlock, blockNumber, err := getBeaconBlockContainingExecutionHeader(*s, messageBlockNumber, finalizedHeaderSlot) + if err != nil { + return fmt.Errorf("get beacon block containing header: %w", err) + } + + beaconBlockSlot, err := strconv.ParseUint(beaconBlock.Data.Message.Slot, 10, 64) + if err != nil { + return err + } + + if blockNumber == messageBlockNumber { + log.WithFields(log.Fields{ + "slot": beaconBlock.Data.Message.Slot, + "blockHash": beaconBlock.Data.Message.Body.ExecutionPayload.BlockHash, + "blockNumber": blockNumber, + }).WithError(err).Info("found execution header containing event") + } + + checkPoint := cache.Proof{ + FinalizedBlockRoot: finalizedUpdateAfterMessage.FinalizedHeaderBlockRoot, + BlockRootsTree: finalizedUpdateAfterMessage.BlockRootsTree, + Slot: uint64(finalizedUpdateAfterMessage.Payload.FinalizedHeader.Slot), + } + headerUpdateScale, err := s.GetHeaderUpdateBySlotWithCheckpoint(beaconBlockSlot, &checkPoint) + if err != nil { + return fmt.Errorf("get header update: %w", err) + } + inboundMessage.Proof.ExecutionProof = headerUpdateScale + headerUpdate := headerUpdateScale.ToJSON() + + log.WithField("blockNumber", blockNumber).Info("found beacon block by slot") + + messageJSON := inboundMessage.ToJSON() + + finalizedUpdate := finalizedUpdateAfterMessage.Payload.ToJSON() + + finalizedUpdate.RemoveLeadingZeroHashes() + headerUpdate.RemoveLeadingZeroHashes() + messageJSON.RemoveLeadingZeroHashes() + + // writing inbound fixture by test case + testCase, err := cmd.Flags().GetString("test_case") + if err != nil { + return err + } + if testCase != "register_token" && testCase != "send_token" && testCase != "send_token_to_penpal" { + return fmt.Errorf("invalid test case: %s", testCase) + } + + data := Data{ + FinalizedHeaderUpdate: finalizedUpdate, + HeaderUpdate: headerUpdate, + InboundMessage: messageJSON, + TestCase: testCase, + } + + rendered, err := mustache.RenderFile(pathToInboundQueueFixtureTestCaseTemplate, data) + if err != nil { + return fmt.Errorf("render inbound queue benchmark fixture: %w", err) + } + + pathToInboundQueueFixtureTestCaseData := fmt.Sprintf(pathToInboundQueueFixtureTestCaseData, testCase) + err = writeRawDataFile(fmt.Sprintf("%s", pathToInboundQueueFixtureTestCaseData), rendered) + if err != nil { + return err + } + + log.Info("done") + + return nil + }() + if err != nil { + log.WithError(err).Error("error generating beacon data") + } + + return nil +} diff --git a/relayer/cmd/root.go b/relayer/cmd/root.go index 0ff86eae71..411d080433 100644 --- a/relayer/cmd/root.go +++ b/relayer/cmd/root.go @@ -29,9 +29,10 @@ func init() { rootCmd.AddCommand(basicChannelLeafProofCmd()) rootCmd.AddCommand(parachainHeadProofCmd()) rootCmd.AddCommand(importExecutionHeaderCmd()) - rootCmd.AddCommand(generateBeaconDataCmd()) + rootCmd.AddCommand(generateBeaconFixtureCmd()) rootCmd.AddCommand(generateBeaconCheckpointCmd()) rootCmd.AddCommand(generateExecutionUpdateCmd()) + rootCmd.AddCommand(generateInboundFixtureCmd()) } func Execute() { diff --git a/relayer/relays/beacon/header/header.go b/relayer/relays/beacon/header/header.go index f12f59831e..a82b495d27 100644 --- a/relayer/relays/beacon/header/header.go +++ b/relayer/relays/beacon/header/header.go @@ -11,7 +11,6 @@ import ( "github.com/snowfork/snowbridge/relayer/relays/beacon/header/syncer/scale" log "github.com/sirupsen/logrus" - "github.com/snowfork/go-substrate-rpc-client/v4/types" "github.com/snowfork/snowbridge/relayer/chain/parachain" "github.com/snowfork/snowbridge/relayer/relays/beacon/cache" "github.com/snowfork/snowbridge/relayer/relays/beacon/header/syncer" @@ -335,50 +334,24 @@ func (h *Header) getHeaderUpdateBySlot(slot uint64) (scale.HeaderUpdatePayload, return h.syncer.GetHeaderUpdate(blockRoot, &checkpoint) } -func (h *Header) SyncExecutionHeader(ctx context.Context, blockRoot common.Hash) error { +func (h *Header) FetchExecutionProof(blockRoot common.Hash) (scale.HeaderUpdatePayload, error) { + var headerUpdate scale.HeaderUpdatePayload header, err := h.syncer.Client.GetHeader(blockRoot) if err != nil { - return fmt.Errorf("get beacon header by blockRoot: %w", err) + return headerUpdate, fmt.Errorf("get beacon header by blockRoot: %w", err) } lastFinalizedHeaderState, err := h.writer.GetLastFinalizedHeaderState() if err != nil { - return fmt.Errorf("fetch last finalized header state: %w", err) + return headerUpdate, fmt.Errorf("fetch last finalized header state: %w", err) } if header.Slot > lastFinalizedHeaderState.BeaconSlot { - return ErrBeaconHeaderNotFinalized - } - headerUpdate, err := h.getHeaderUpdateBySlot(header.Slot) - if err != nil { - return fmt.Errorf("get header update by slot with ancestry proof: %w", err) + return headerUpdate, ErrBeaconHeaderNotFinalized } - var blockHash types.H256 - if headerUpdate.ExecutionHeader.Deneb != nil { - blockHash = headerUpdate.ExecutionHeader.Deneb.BlockHash - } else if headerUpdate.ExecutionHeader.Capella != nil { - blockHash = headerUpdate.ExecutionHeader.Capella.BlockHash - } else { - return fmt.Errorf("invalid blockHash in headerUpdate") - } - compactExecutionHeaderState, err := h.writer.GetCompactExecutionHeaderStateByBlockHash(blockHash) + headerUpdate, err = h.getHeaderUpdateBySlot(header.Slot) if err != nil { - return fmt.Errorf("get compactExecutionHeaderState by blockHash: %w", err) - } - if compactExecutionHeaderState.BlockNumber != 0 { - log.WithFields(log.Fields{"blockRoot": blockRoot.Hex(), "blockHash": blockHash.Hex(), "blockNumber": compactExecutionHeaderState.BlockNumber}).Info("ExecutionHeaderState already exist") - return nil + return headerUpdate, fmt.Errorf("get header update by slot with ancestry proof: %w", err) } - err = h.writer.WriteToParachainAndWatch(ctx, "EthereumBeaconClient.submit_execution_header", headerUpdate) - if err != nil { - return fmt.Errorf("submit_execution_header: %w", err) - } - compactExecutionHeaderState, err = h.writer.GetCompactExecutionHeaderStateByBlockHash(blockHash) - if err != nil { - return fmt.Errorf("get compactExecutionHeaderState by blockHash: %w", err) - } - if compactExecutionHeaderState.BlockNumber == 0 { - return fmt.Errorf("execution header did not sync successfully") - } - return nil + return headerUpdate, nil } func (h *Header) isInitialSyncPeriod() bool { diff --git a/relayer/relays/beacon/state/beacon_deneb_encoding.go b/relayer/relays/beacon/state/beacon_deneb_encoding.go index 274323124a..e4b2e10a34 100644 --- a/relayer/relays/beacon/state/beacon_deneb_encoding.go +++ b/relayer/relays/beacon/state/beacon_deneb_encoding.go @@ -1,5 +1,5 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: 00aea8602ff5e5fb2169a817d63f065398a715fcb79623b35af84d972c308644 +// Hash: bf79b1b8dfc6467c2ea96da7962e06ebfc35d247e27dae4aec667508dfc5d5c5 // Version: 0.1.3 package state diff --git a/relayer/relays/beacon/state/beacon_encoding.go b/relayer/relays/beacon/state/beacon_encoding.go index 3ed880a78c..571446605c 100644 --- a/relayer/relays/beacon/state/beacon_encoding.go +++ b/relayer/relays/beacon/state/beacon_encoding.go @@ -1,5 +1,5 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: 00aea8602ff5e5fb2169a817d63f065398a715fcb79623b35af84d972c308644 +// Hash: bf79b1b8dfc6467c2ea96da7962e06ebfc35d247e27dae4aec667508dfc5d5c5 // Version: 0.1.3 package state diff --git a/relayer/relays/beacon/state/state.go b/relayer/relays/beacon/state/state.go index 13bdf8e683..9b22e7dd66 100644 --- a/relayer/relays/beacon/state/state.go +++ b/relayer/relays/beacon/state/state.go @@ -17,10 +17,3 @@ type FinalizedHeader struct { InitialCheckpointRoot common.Hash InitialCheckpointSlot uint64 } - -type CompactExecutionHeaderState struct { - ParentHash common.Hash - BlockNumber uint64 - StateRoot common.Hash - ReceiptsRoot common.Hash -} diff --git a/relayer/relays/execution/main.go b/relayer/relays/execution/main.go index 2d55a2fc99..f7993b0352 100644 --- a/relayer/relays/execution/main.go +++ b/relayer/relays/execution/main.go @@ -139,6 +139,7 @@ func (r *Relay) Start(ctx context.Context, eg *errgroup.Group) error { "blockHash": ev.Raw.BlockHash.Hex(), "blockNumber": ev.Raw.BlockNumber, "txHash": ev.Raw.TxHash.Hex(), + "txIndex": ev.Raw.TxIndex, "channelID": types.H256(ev.ChannelID).Hex(), }) @@ -154,14 +155,20 @@ func (r *Relay) Start(ctx context.Context, eg *errgroup.Group) error { } // ParentBeaconRoot in https://eips.ethereum.org/EIPS/eip-4788 from Deneb onward - err = beaconHeader.SyncExecutionHeader(ctx, *blockHeader.ParentBeaconRoot) + executionProof, err := beaconHeader.FetchExecutionProof(*blockHeader.ParentBeaconRoot) if err == header.ErrBeaconHeaderNotFinalized { logger.Warn("beacon header not finalized, just skipped") continue } if err != nil { - return fmt.Errorf("sync beacon header: %w", err) + return fmt.Errorf("fetch execution header proof: %w", err) } + inboundMsg.Proof.ExecutionProof = executionProof + + logger.WithFields(logrus.Fields{ + "EventLog": inboundMsg.EventLog, + "Proof": inboundMsg.Proof, + }).Debug("Generated message from Ethereum log") err = writer.WriteToParachainAndWatch(ctx, "EthereumInboundQueue.submit", inboundMsg) if err != nil {