diff --git a/enclave/client.go b/enclave/client.go index 3d0ddbc..c9056db 100644 --- a/enclave/client.go +++ b/enclave/client.go @@ -49,7 +49,7 @@ func (c *Client) SetSignerKey(ctx context.Context, encrypted hexutil.Bytes) erro return c.callContext(ctx, nil, "setSignerKey", encrypted) } -func (c *Client) ExecuteStateless(ctx context.Context, config *PerChainConfig, l1Origin *types.Header, l1Receipts types.Receipts, previousBlockTxs types.Transactions, blockHeader *types.Header, blockTxs types.Transactions, witness hexutil.Bytes, messageAccount *eth.AccountResult, prevMessageAccountHash common.Hash) (*Proposal, error) { +func (c *Client) ExecuteStateless(ctx context.Context, config *PerChainConfig, l1Origin *types.Header, l1Receipts types.Receipts, previousBlockTxs []hexutil.Bytes, blockHeader *types.Header, blockTxs []hexutil.Bytes, witness hexutil.Bytes, messageAccount *eth.AccountResult, prevMessageAccountHash common.Hash) (*Proposal, error) { var result Proposal return &result, c.callContext(ctx, &result, "executeStateless", config, l1Origin, l1Receipts, previousBlockTxs, blockHeader, blockTxs, witness, messageAccount, prevMessageAccountHash) } diff --git a/enclave/rpc.go b/enclave/rpc.go index 0ea8b7b..756ef5d 100644 --- a/enclave/rpc.go +++ b/enclave/rpc.go @@ -23,9 +23,9 @@ type RPC interface { config *PerChainConfig, l1Origin *types.Header, l1Receipts types.Receipts, - previousBlockTxs types.Transactions, + previousBlockTxs []hexutil.Bytes, blockHeader *types.Header, - blockTxs types.Transactions, + blockTxs []hexutil.Bytes, witness hexutil.Bytes, messageAccount *eth.AccountResult, prevMessageAccountHash common.Hash, diff --git a/enclave/server.go b/enclave/server.go index 2d03116..3aa1250 100644 --- a/enclave/server.go +++ b/enclave/server.go @@ -233,9 +233,9 @@ func (s *Server) ExecuteStateless( cfg *PerChainConfig, l1Origin *types.Header, l1Receipts types.Receipts, - previousBlockTxs types.Transactions, + previousBlockTxs []hexutil.Bytes, blockHeader *types.Header, - blockTxs types.Transactions, + blockTxs []hexutil.Bytes, witness hexutil.Bytes, messageAccount *eth.AccountResult, prevMessageAccountHash common.Hash, @@ -260,13 +260,32 @@ func (s *Server) ExecuteStateless( return nil, errors.New("invalid parent hash") } - previousTxHash := types.DeriveSha(previousBlockTxs, trie.NewStackTrie(nil)) + unmarshalTxs := func(rlp []hexutil.Bytes) (types.Transactions, error) { + txs := make(types.Transactions, len(rlp)) + for i, tx := range rlp { + txs[i] = new(types.Transaction) + if err := txs[i].UnmarshalBinary(tx); err != nil { + return nil, fmt.Errorf("failed to unmarshal transaction: %w", err) + } + } + return txs, nil + } + previousTxs, err := unmarshalTxs(previousBlockTxs) + if err != nil { + return nil, err + } + txs, err := unmarshalTxs(blockTxs) + if err != nil { + return nil, err + } + + previousTxHash := types.DeriveSha(previousTxs, trie.NewStackTrie(nil)) if previousTxHash != previousBlockHeader.TxHash { return nil, errors.New("invalid tx hash") } previousBlock := types.NewBlockWithHeader(previousBlockHeader).WithBody(types.Body{ - Transactions: previousBlockTxs, + Transactions: previousTxs, }) rollupConfig := config.ToRollupConfig() @@ -280,7 +299,7 @@ func (s *Server) ExecuteStateless( } l1Fetcher := NewL1ReceiptsFetcher(l1OriginHash, l1Origin, l1Receipts) - l2Fetcher := NewL2SystemConfigFetcher(rollupConfig, previousBlockHash, previousBlockHeader, previousBlockTxs) + l2Fetcher := NewL2SystemConfigFetcher(rollupConfig, previousBlockHash, previousBlockHeader, previousTxs) attributeBuilder := derive.NewFetchingAttributesBuilder(rollupConfig, l1Fetcher, l2Fetcher) payload, err := attributeBuilder.PreparePayloadAttributes(context.Background(), l2Parent, eth.BlockID{ Hash: l1OriginHash, @@ -290,26 +309,22 @@ func (s *Server) ExecuteStateless( return nil, fmt.Errorf("failed to prepare payload attributes: %w", err) } - if blockTxs.Len() < len(payload.Transactions) { + if txs.Len() < len(payload.Transactions) { return nil, errors.New("invalid transaction count") } for i, payloadTx := range payload.Transactions { - tx := blockTxs[i] + tx := txs[i] if !tx.IsDepositTx() { return nil, errors.New("invalid transaction type") } - m, err := tx.MarshalBinary() - if err != nil { - return nil, fmt.Errorf("failed to marshal transaction: %w", err) - } - if !bytes.Equal(m, payloadTx) { + if !bytes.Equal(blockTxs[i], payloadTx) { return nil, errors.New("invalid deposit transaction") } } // block must only contain deposit transactions if it is outside the sequencer drift - if blockTxs.Len() > len(payload.Transactions) && + if txs.Len() > len(payload.Transactions) && blockHeader.Time > l1Origin.Time+maxSequencerDriftFjord { return nil, errors.New("L1 origin is too old") } @@ -318,7 +333,7 @@ func (s *Server) ExecuteStateless( blockHeader.Root = common.Hash{} blockHeader.ReceiptHash = common.Hash{} block := types.NewBlockWithHeader(blockHeader).WithBody(types.Body{ - Transactions: blockTxs, + Transactions: txs, }) blockHeader.Root, blockHeader.ReceiptHash, err = core.ExecuteStateless(config.ChainConfig, block, w) if err != nil { diff --git a/op-proposer/proposer/prover.go b/op-proposer/proposer/prover.go index 15df28d..0c2ddbe 100644 --- a/op-proposer/proposer/prover.go +++ b/op-proposer/proposer/prover.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/hashicorp/go-multierror" "github.com/mdehoog/op-nitro/enclave" @@ -127,14 +128,33 @@ func (o *Prover) Generate(ctx context.Context, blockNumber uint64) (*Proposal, b return nil, false, &multierror.Error{Errors: errors} } + marshalTxs := func(txs types.Transactions) ([]hexutil.Bytes, error) { + rlp := make([]hexutil.Bytes, len(txs)) + var err error + for i, tx := range txs { + if rlp[i], err = tx.MarshalBinary(); err != nil { + return nil, fmt.Errorf("failed to marshal transaction: %w", err) + } + } + return rlp, nil + } + previousTxs, err := marshalTxs(previousBlock.value.Transactions()) + if err != nil { + return nil, false, err + } + txs, err := marshalTxs(block.Transactions()) + if err != nil { + return nil, false, err + } + output, err := o.enclave.ExecuteStateless( ctx, o.config, l1Origin.value, l1Receipts.value, - previousBlock.value.Transactions(), + previousTxs, block.Header(), - block.Transactions(), + txs, witness.value, messageAccount.value, prevMessageAccount.value.StorageHash,