From 40f30be90ec42d125daa84df54f13bd6fff3e0ec Mon Sep 17 00:00:00 2001 From: David Date: Wed, 5 Jul 2023 22:57:50 +0800 Subject: [PATCH 1/3] feat(prover): integrate new anchor transaction circuits --- bindings/encoding/input.go | 26 +++++++ bindings/encoding/input_test.go | 8 ++ prover/proof_producer/proof_producer.go | 3 +- prover/proof_producer/zkevm_rpcd_producer.go | 75 ++++++++++++++----- .../proof_submitter/valid_proof_submitter.go | 29 ++++--- 5 files changed, 110 insertions(+), 31 deletions(-) diff --git a/bindings/encoding/input.go b/bindings/encoding/input.go index bd242d63f..a493c58e8 100644 --- a/bindings/encoding/input.go +++ b/bindings/encoding/input.go @@ -106,6 +106,20 @@ var ( }, }, } + depositsProcessedComponents = []abi.ArgumentMarshaling{ + { + Name: "recipient", + Type: "address", + }, + { + Name: "amount", + Type: "uint96", + }, + { + Name: "id", + Type: "uint64", + }, + } evidenceComponents = []abi.ArgumentMarshaling{ { Name: "metaHash", @@ -160,6 +174,9 @@ var ( // Evidence EvidenceType, _ = abi.NewType("tuple", "TaikoData.BlockEvidence", evidenceComponents) EvidenceArgs = abi.Arguments{{Name: "Evidence", Type: EvidenceType}} + // DepositsProcessed + DepositsProcessedType, _ = abi.NewType("tuple[]", "TaikoData.EthDeposit[]", depositsProcessedComponents) + DepositsProcessedArgs = abi.Arguments{{Name: "DepositsProcessed", Type: DepositsProcessedType}} ) // Contract ABIs. @@ -237,6 +254,15 @@ func EncodeProveBlockInput( return evidenceBytes, nil } +// EncodeDepositsProcessed performs the solidity `abi.encode` for the given deposits. +func EncodeDepositsProcessed(deposits []bindings.TaikoDataEthDeposit) ([]byte, error) { + b, err := DepositsProcessedArgs.Pack(deposits) + if err != nil { + return nil, fmt.Errorf("failed to abi.encode deposits, %w", err) + } + return b, nil +} + // EncodeProveBlockInvalidInput encodes the input params for TaikoL1.proveBlockInvalid. func EncodeProveBlockInvalidInput( evidence *TaikoL1Evidence, diff --git a/bindings/encoding/input_test.go b/bindings/encoding/input_test.go index 35bb137a3..cac06b8d1 100644 --- a/bindings/encoding/input_test.go +++ b/bindings/encoding/input_test.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/stretchr/testify/require" + "github.com/taikoxyz/taiko-client/bindings" ) func TestEncodeEvidence(t *testing.T) { @@ -42,6 +43,13 @@ func TestEncodeProposeBlockInput(t *testing.T) { require.NotNil(t, encoded) } +func TestEncodeDepositsProcessed(t *testing.T) { + encoded, err := EncodeDepositsProcessed([]bindings.TaikoDataEthDeposit{}) + + require.Nil(t, err) + require.NotNil(t, encoded) +} + func TestEncodeProveBlockInput(t *testing.T) { encoded, err := EncodeProveBlockInput( &TaikoL1Evidence{ diff --git a/prover/proof_producer/proof_producer.go b/prover/proof_producer/proof_producer.go index eadea1997..1d97ecd25 100644 --- a/prover/proof_producer/proof_producer.go +++ b/prover/proof_producer/proof_producer.go @@ -21,13 +21,14 @@ type ProofRequestOptions struct { L1SignalService common.Address L2SignalService common.Address TaikoL2 common.Address - MetaHash common.Hash + MetaData *bindings.TaikoDataBlockMetadata BlockHash common.Hash ParentHash common.Hash SignalRoot common.Hash Graffiti string GasUsed uint64 ParentGasUsed uint64 + AnchorGasCost uint64 } type ProofWithHeader struct { diff --git a/prover/proof_producer/zkevm_rpcd_producer.go b/prover/proof_producer/zkevm_rpcd_producer.go index ecb695250..5735d9e64 100644 --- a/prover/proof_producer/zkevm_rpcd_producer.go +++ b/prover/proof_producer/zkevm_rpcd_producer.go @@ -14,8 +14,10 @@ import ( "github.com/cenkalti/backoff/v4" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" "github.com/taikoxyz/taiko-client/bindings" + "github.com/taikoxyz/taiko-client/bindings/encoding" ) var ( @@ -59,20 +61,36 @@ type RequestProofBodyParam struct { // RequestProofBody represents the JSON body of RequestProofBody.Param's `protocol_instance` field. type ProtocolInstance struct { - L1SignalService string `json:"l1_signal_service"` - L2SignalService string `json:"l2_signal_service"` - TaikoL2 string `json:"l2_contract"` - MetaHash string `json:"meta_hash"` - BlockHash string `json:"block_hash"` - ParentHash string `json:"parent_hash"` - SignalRoot string `json:"signal_root"` - Graffiti string `json:"graffiti"` - Prover string `json:"prover"` - GasUsed uint64 `json:"gas_used"` - ParentGasUsed uint64 `json:"parent_gas_used"` - BlockMaxGasLimit uint64 `json:"block_max_gas_limit"` - MaxTransactionsPerBlock uint64 `json:"max_transactions_per_block"` - MaxBytesPerTxList uint64 `json:"max_bytes_per_tx_list"` + L1SignalService string `json:"l1_signal_service"` + L2SignalService string `json:"l2_signal_service"` + TaikoL2 string `json:"l2_contract"` + MetaData *RequestProofMetaData `json:"meta_data"` + BlockHash string `json:"block_hash"` + ParentHash string `json:"parent_hash"` + SignalRoot string `json:"signal_root"` + Graffiti string `json:"graffiti"` + Prover string `json:"prover"` + GasUsed uint64 `json:"gas_used"` + ParentGasUsed uint64 `json:"parent_gas_used"` + BlockMaxGasLimit uint64 `json:"block_max_gas_limit"` + MaxTransactionsPerBlock uint64 `json:"max_transactions_per_block"` + MaxBytesPerTxList uint64 `json:"max_bytes_per_tx_list"` + AnchorGasCost uint64 `json:"anchor_gas_cost"` +} + +type RequestProofMetaData struct { + ID uint64 `json:"id"` + Timestamp uint64 `json:"timestamp"` + L1Height uint64 `json:"l1_height"` + L1Hash string `json:"l1_hash"` + L1MixHash string `json:"l1_mix_hash"` + DepositsProcessed string `json:"deposits_processed"` + TxListHash string `json:"tx_list_hash"` + TxListByteStart uint32 `json:"tx_list_byte_start"` + TxListByteEnd uint32 `json:"tx_list_byte_end"` + GasLimit uint32 `json:"gas_limit"` + Beneficiary string `json:"beneficiary"` + Treasury string `json:"treasury"` } // RequestProofBodyResponse represents the JSON body of the response of the proof requests. @@ -204,6 +222,11 @@ func (p *ZkevmRpcdProducer) callProverDaemon(ctx context.Context, opts *ProofReq // requestProof sends a RPC request to proverd to try to get the requested proof. func (p *ZkevmRpcdProducer) requestProof(opts *ProofRequestOptions) (*RpcdOutput, error) { + abiEncodedDeposits, err := encoding.EncodeDepositsProcessed(opts.MetaData.DepositsProcessed) + if err != nil { + return nil, err + } + reqBody := RequestProofBody{ JsonRPC: "2.0", ID: common.Big1, @@ -219,11 +242,24 @@ func (p *ZkevmRpcdProducer) requestProof(opts *ProofRequestOptions) (*RpcdOutput MockFeedback: false, Aggregate: true, ProtocolInstance: &ProtocolInstance{ - Prover: opts.ProverAddress.Hex()[2:], - L1SignalService: opts.L1SignalService.Hex()[2:], - L2SignalService: opts.L2SignalService.Hex()[2:], - TaikoL2: opts.TaikoL2.Hex()[2:], - MetaHash: opts.MetaHash.Hex()[2:], + Prover: opts.ProverAddress.Hex()[2:], + L1SignalService: opts.L1SignalService.Hex()[2:], + L2SignalService: opts.L2SignalService.Hex()[2:], + TaikoL2: opts.TaikoL2.Hex()[2:], + MetaData: &RequestProofMetaData{ + ID: opts.MetaData.Id, + Timestamp: opts.MetaData.Timestamp, + L1Height: opts.MetaData.L1Height, + L1Hash: common.Bytes2Hex(opts.MetaData.L1Hash[:])[2:], + L1MixHash: common.Bytes2Hex(opts.MetaData.MixHash[:])[2:], + DepositsProcessed: crypto.Keccak256Hash(abiEncodedDeposits).Hex()[2:], + TxListHash: common.Bytes2Hex(opts.MetaData.TxListHash[:])[2:], + TxListByteStart: uint32(opts.MetaData.TxListByteStart.Uint64()), + TxListByteEnd: uint32(opts.MetaData.TxListByteEnd.Uint64()), + GasLimit: opts.MetaData.GasLimit, + Beneficiary: opts.MetaData.Beneficiary.Hex()[2:], + Treasury: opts.MetaData.Treasury.Hex()[2:], + }, BlockHash: opts.BlockHash.Hex()[2:], ParentHash: opts.ParentHash.Hex()[2:], SignalRoot: opts.SignalRoot.Hex()[2:], @@ -233,6 +269,7 @@ func (p *ZkevmRpcdProducer) requestProof(opts *ProofRequestOptions) (*RpcdOutput BlockMaxGasLimit: uint64(p.ProtocolConfig.BlockMaxGasLimit), MaxTransactionsPerBlock: p.ProtocolConfig.BlockMaxTransactions, MaxBytesPerTxList: p.ProtocolConfig.BlockMaxTxListBytes, + AnchorGasCost: opts.AnchorGasCost, }, }}, } diff --git a/prover/proof_submitter/valid_proof_submitter.go b/prover/proof_submitter/valid_proof_submitter.go index eb7b699a2..6e7b4960a 100644 --- a/prover/proof_submitter/valid_proof_submitter.go +++ b/prover/proof_submitter/valid_proof_submitter.go @@ -103,18 +103,18 @@ func (s *ValidProofSubmitter) RequestProof(ctx context.Context, event *bindings. return fmt.Errorf("failed to get the L2 parent block by hash (%s): %w", block.ParentHash(), err) } - blockInfo, err := s.rpc.TaikoL1.GetBlock(nil, event.Id) - if err != nil { - return err - } - if block.Transactions().Len() == 0 { return errors.New("no transaction in block") } signalRoot, err := s.rpc.GetStorageRoot(ctx, s.rpc.L2GethClient, s.l2SignalService, block.Number()) if err != nil { - return fmt.Errorf("error getting storageroot: %w", err) + return fmt.Errorf("failed to get storage root: %w", err) + } + + anchorTxReceipt, err := s.anchorTxValidator.GetAndValidateAnchorTxReceipt(ctx, block.Transactions()[0]) + if err != nil { + return fmt.Errorf("failed to get anchor transaction receipt: %w", err) } // Request proof. @@ -125,13 +125,14 @@ func (s *ValidProofSubmitter) RequestProof(ctx context.Context, event *bindings. L1SignalService: s.l1SignalService, L2SignalService: s.l2SignalService, TaikoL2: s.taikoL2Address, - MetaHash: blockInfo.MetaHash, + MetaData: &event.Meta, BlockHash: block.Hash(), ParentHash: block.ParentHash(), SignalRoot: signalRoot, Graffiti: common.Bytes2Hex(s.graffiti[:]), GasUsed: block.GasUsed(), ParentGasUsed: parent.GasUsed(), + AnchorGasCost: anchorTxReceipt.GasUsed, } if err := s.proofProducer.RequestProof(ctx, opts, event.Id, &event.Meta, block.Header(), s.resultCh); err != nil { @@ -196,8 +197,13 @@ func (s *ValidProofSubmitter) SubmitProof( return fmt.Errorf("failed to fetch anchor transaction receipt: %w", err) } + blockInfo, err := s.rpc.TaikoL1.GetBlock(nil, blockID) + if err != nil { + return err + } + evidence := &encoding.TaikoL1Evidence{ - MetaHash: proofWithHeader.Opts.MetaHash, + MetaHash: blockInfo.MetaHash, ParentHash: proofWithHeader.Opts.ParentHash, BlockHash: proofWithHeader.Opts.BlockHash, SignalRoot: proofWithHeader.Opts.SignalRoot, @@ -207,9 +213,10 @@ func (s *ValidProofSubmitter) SubmitProof( Proof: zkProof, } - var circuitsIdx uint16 - var prover common.Address - + var ( + circuitsIdx uint16 + prover common.Address + ) if s.isOracleProver { prover = encoding.OracleProverAddress From e9678175f78d9f7d2cc98ad2d8aea9c2e1778301 Mon Sep 17 00:00:00 2001 From: David Date: Thu, 6 Jul 2023 00:18:32 +0800 Subject: [PATCH 2/3] feat: update producer --- prover/proof_producer/zkevm_rpcd_producer.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/prover/proof_producer/zkevm_rpcd_producer.go b/prover/proof_producer/zkevm_rpcd_producer.go index 5735d9e64..fbdceba2b 100644 --- a/prover/proof_producer/zkevm_rpcd_producer.go +++ b/prover/proof_producer/zkevm_rpcd_producer.go @@ -250,10 +250,10 @@ func (p *ZkevmRpcdProducer) requestProof(opts *ProofRequestOptions) (*RpcdOutput ID: opts.MetaData.Id, Timestamp: opts.MetaData.Timestamp, L1Height: opts.MetaData.L1Height, - L1Hash: common.Bytes2Hex(opts.MetaData.L1Hash[:])[2:], - L1MixHash: common.Bytes2Hex(opts.MetaData.MixHash[:])[2:], + L1Hash: common.Bytes2Hex(opts.MetaData.L1Hash[:]), + L1MixHash: common.Bytes2Hex(opts.MetaData.MixHash[:]), DepositsProcessed: crypto.Keccak256Hash(abiEncodedDeposits).Hex()[2:], - TxListHash: common.Bytes2Hex(opts.MetaData.TxListHash[:])[2:], + TxListHash: common.Bytes2Hex(opts.MetaData.TxListHash[:]), TxListByteStart: uint32(opts.MetaData.TxListByteStart.Uint64()), TxListByteEnd: uint32(opts.MetaData.TxListByteEnd.Uint64()), GasLimit: opts.MetaData.GasLimit, From 3299bd1c33c5ff24479d7bed2574a52ed63b9bd5 Mon Sep 17 00:00:00 2001 From: David Date: Fri, 7 Jul 2023 13:16:01 +0800 Subject: [PATCH 3/3] feat: update request params --- prover/proof_producer/proof_producer.go | 2 +- prover/proof_producer/zkevm_rpcd_producer.go | 4 ++-- prover/proof_submitter/valid_proof_submitter.go | 7 +------ 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/prover/proof_producer/proof_producer.go b/prover/proof_producer/proof_producer.go index 1d97ecd25..ef6081be3 100644 --- a/prover/proof_producer/proof_producer.go +++ b/prover/proof_producer/proof_producer.go @@ -28,7 +28,7 @@ type ProofRequestOptions struct { Graffiti string GasUsed uint64 ParentGasUsed uint64 - AnchorGasCost uint64 + AnchorGasLimit uint64 } type ProofWithHeader struct { diff --git a/prover/proof_producer/zkevm_rpcd_producer.go b/prover/proof_producer/zkevm_rpcd_producer.go index fbdceba2b..e2caec33f 100644 --- a/prover/proof_producer/zkevm_rpcd_producer.go +++ b/prover/proof_producer/zkevm_rpcd_producer.go @@ -75,7 +75,7 @@ type ProtocolInstance struct { BlockMaxGasLimit uint64 `json:"block_max_gas_limit"` MaxTransactionsPerBlock uint64 `json:"max_transactions_per_block"` MaxBytesPerTxList uint64 `json:"max_bytes_per_tx_list"` - AnchorGasCost uint64 `json:"anchor_gas_cost"` + AnchorGasLimit uint64 `json:"anchor_gas_limit"` } type RequestProofMetaData struct { @@ -269,7 +269,7 @@ func (p *ZkevmRpcdProducer) requestProof(opts *ProofRequestOptions) (*RpcdOutput BlockMaxGasLimit: uint64(p.ProtocolConfig.BlockMaxGasLimit), MaxTransactionsPerBlock: p.ProtocolConfig.BlockMaxTransactions, MaxBytesPerTxList: p.ProtocolConfig.BlockMaxTxListBytes, - AnchorGasCost: opts.AnchorGasCost, + AnchorGasLimit: opts.AnchorGasLimit, }, }}, } diff --git a/prover/proof_submitter/valid_proof_submitter.go b/prover/proof_submitter/valid_proof_submitter.go index 6e7b4960a..5c727be1b 100644 --- a/prover/proof_submitter/valid_proof_submitter.go +++ b/prover/proof_submitter/valid_proof_submitter.go @@ -112,11 +112,6 @@ func (s *ValidProofSubmitter) RequestProof(ctx context.Context, event *bindings. return fmt.Errorf("failed to get storage root: %w", err) } - anchorTxReceipt, err := s.anchorTxValidator.GetAndValidateAnchorTxReceipt(ctx, block.Transactions()[0]) - if err != nil { - return fmt.Errorf("failed to get anchor transaction receipt: %w", err) - } - // Request proof. opts := &proofProducer.ProofRequestOptions{ Height: block.Number(), @@ -132,7 +127,7 @@ func (s *ValidProofSubmitter) RequestProof(ctx context.Context, event *bindings. Graffiti: common.Bytes2Hex(s.graffiti[:]), GasUsed: block.GasUsed(), ParentGasUsed: parent.GasUsed(), - AnchorGasCost: anchorTxReceipt.GasUsed, + AnchorGasLimit: block.Transactions()[0].Gas(), } if err := s.proofProducer.RequestProof(ctx, opts, event.Id, &event.Meta, block.Header(), s.resultCh); err != nil {