From 248268baa2fff8c90d5142e3f398aee717b4d468 Mon Sep 17 00:00:00 2001 From: David Date: Wed, 24 Apr 2024 15:38:05 +0800 Subject: [PATCH] feat(bindings): introduce `TryParsingCustomErrorFromReceipt` (#755) --- bindings/encoding/custom_error.go | 49 +++++++++++++++--- proposer/proposer.go | 2 +- prover/proof_submitter/proof_contester.go | 54 ++++++++++---------- prover/proof_submitter/proof_submitter.go | 4 +- prover/proof_submitter/transaction/sender.go | 2 + 5 files changed, 74 insertions(+), 37 deletions(-) diff --git a/bindings/encoding/custom_error.go b/bindings/encoding/custom_error.go index 6f9f08f6c..04c029795 100644 --- a/bindings/encoding/custom_error.go +++ b/bindings/encoding/custom_error.go @@ -1,10 +1,53 @@ package encoding import ( + "context" "errors" "strings" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" ) +// BlockHashContractCallerAndTransactionReader represents a contract caller and transaction reader. +type BlockHashContractCallerAndTransactionReader interface { + bind.BlockHashContractCaller + ethereum.TransactionReader +} + +// TryParsingCustomErrorFromReceipt tries to parse the custom error from the given receipt. +func TryParsingCustomErrorFromReceipt( + ctx context.Context, + rpc BlockHashContractCallerAndTransactionReader, + from common.Address, + receipt *types.Receipt, +) error { + // Fetch the raw transaction. + tx, _, err := rpc.TransactionByHash(ctx, receipt.TxHash) + if err != nil { + return err + } + + // Call the contract at the block hash. + _, err = rpc.CallContractAtHash(ctx, ethereum.CallMsg{ + From: from, + To: tx.To(), + Gas: tx.Gas(), + GasPrice: tx.GasPrice(), + GasFeeCap: tx.GasFeeCap(), + GasTipCap: tx.GasTipCap(), + Value: tx.Value(), + Data: tx.Data(), + AccessList: tx.AccessList(), + BlobGasFeeCap: tx.BlobGasFeeCap(), + BlobHashes: tx.BlobHashes(), + }, receipt.BlockHash) + + return TryParsingCustomError(err) +} + // TryParsingCustomError tries to checks whether the given error is one of the // custom errors defined the protocol ABIs, if so, it will return // the matched custom error, otherwise, it simply returns the original error. @@ -28,12 +71,6 @@ func TryParsingCustomError(originalError error) error { } } - for _, hookCustomError := range AssignmentHookABI.Errors { - if strings.HasPrefix(hookCustomError.ID.Hex(), errData) { - return errors.New(hookCustomError.Name) - } - } - return originalError } diff --git a/proposer/proposer.go b/proposer/proposer.go index e32bfe8b8..62161cd9c 100644 --- a/proposer/proposer.go +++ b/proposer/proposer.go @@ -323,7 +323,7 @@ func (p *Proposer) ProposeOp(ctx context.Context) error { log.Error( "Failed to send TaikoL1.proposeBlock transaction", "index", i, - "error", encoding.TryParsingCustomError(err), + "error", err, ) continue } diff --git a/prover/proof_submitter/proof_contester.go b/prover/proof_submitter/proof_contester.go index 0a7b3f9f8..b073b26ed 100644 --- a/prover/proof_submitter/proof_contester.go +++ b/prover/proof_submitter/proof_contester.go @@ -92,35 +92,33 @@ func (c *ProofContester) SubmitContest( return err } - return encoding.TryParsingCustomError( - c.sender.Send( - ctx, - &proofProducer.ProofWithHeader{ - BlockID: blockID, - Meta: meta, - Header: header, - Proof: []byte{}, - Opts: &proofProducer.ProofRequestOptions{ - EventL1Hash: l1HeaderProposedIn.Hash(), - StateRoot: header.Root, - }, - Tier: tier, + return c.sender.Send( + ctx, + &proofProducer.ProofWithHeader{ + BlockID: blockID, + Meta: meta, + Header: header, + Proof: []byte{}, + Opts: &proofProducer.ProofRequestOptions{ + EventL1Hash: l1HeaderProposedIn.Hash(), + StateRoot: header.Root, }, - c.txBuilder.Build( - blockID, - meta, - &bindings.TaikoDataTransition{ - ParentHash: header.ParentHash, - BlockHash: header.Hash(), - StateRoot: header.Root, - Graffiti: c.graffiti, - }, - &bindings.TaikoDataTierProof{ - Tier: transition.Tier, - Data: []byte{}, - }, - false, - ), + Tier: tier, + }, + c.txBuilder.Build( + blockID, + meta, + &bindings.TaikoDataTransition{ + ParentHash: header.ParentHash, + BlockHash: header.Hash(), + StateRoot: header.Root, + Graffiti: c.graffiti, + }, + &bindings.TaikoDataTierProof{ + Tier: transition.Tier, + Data: []byte{}, + }, + false, ), ) } diff --git a/prover/proof_submitter/proof_submitter.go b/prover/proof_submitter/proof_submitter.go index c48c3b637..c8b015d9f 100644 --- a/prover/proof_submitter/proof_submitter.go +++ b/prover/proof_submitter/proof_submitter.go @@ -154,7 +154,7 @@ func (s *ProofSubmitter) SubmitProof( } // Build the TaikoL1.proveBlock transaction and send it to the L1 node. - if err = encoding.TryParsingCustomError(s.sender.Send( + if err = s.sender.Send( ctx, proofWithHeader, s.txBuilder.Build( @@ -172,7 +172,7 @@ func (s *ProofSubmitter) SubmitProof( }, proofWithHeader.Tier == encoding.TierGuardianID, ), - )); err != nil { + ); err != nil { if err.Error() == transaction.ErrUnretryableSubmission.Error() { return nil } diff --git a/prover/proof_submitter/transaction/sender.go b/prover/proof_submitter/transaction/sender.go index 55b0dc2bd..d1b7c96f2 100644 --- a/prover/proof_submitter/transaction/sender.go +++ b/prover/proof_submitter/transaction/sender.go @@ -11,6 +11,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" + "github.com/taikoxyz/taiko-client/bindings/encoding" "github.com/taikoxyz/taiko-client/internal/metrics" "github.com/taikoxyz/taiko-client/pkg/rpc" producer "github.com/taikoxyz/taiko-client/prover/proof_producer" @@ -75,6 +76,7 @@ func (s *Sender) Send( "blockID", proofWithHeader.BlockID, "tier", proofWithHeader.Tier, "txHash", receipt.TxHash, + "error", encoding.TryParsingCustomErrorFromReceipt(ctx, s.rpc.L1, s.txmgr.From(), receipt), ) metrics.ProverSubmissionRevertedCounter.Add(1) return ErrUnretryableSubmission