diff --git a/common/types/block.go b/common/types/block.go index 74750b8c3..a823755b5 100644 --- a/common/types/block.go +++ b/common/types/block.go @@ -3,11 +3,13 @@ package types import ( "encoding/binary" "errors" + "fmt" "math" "github.com/scroll-tech/go-ethereum/common" "github.com/scroll-tech/go-ethereum/common/hexutil" "github.com/scroll-tech/go-ethereum/core/types" + "github.com/scroll-tech/go-ethereum/log" ) // CalldataNonZeroByteGas is the gas consumption per non zero byte in calldata. @@ -22,9 +24,10 @@ func GetKeccak256Gas(size uint64) uint64 { type WrappedBlock struct { Header *types.Header `json:"header"` // Transactions is only used for recover types.Transactions, the from of types.TransactionData field is missing. - Transactions []*types.TransactionData `json:"transactions"` - WithdrawRoot common.Hash `json:"withdraw_trie_root,omitempty"` - RowConsumption *types.RowConsumption `json:"row_consumption"` + Transactions []*types.TransactionData `json:"transactions"` + WithdrawRoot common.Hash `json:"withdraw_trie_root,omitempty"` + RowConsumption *types.RowConsumption `json:"row_consumption"` + txPayloadLengthCache map[string]uint64 } // NumL1Messages returns the number of L1 messages in this block. @@ -95,7 +98,8 @@ func (w *WrappedBlock) EstimateL1CommitCalldataSize() uint64 { if txData.Type == types.L1MessageTxType { continue } - size += uint64(len(txData.Data)) + size += 64 // 60 bytes BlockContext + 4 bytes payload length + size += w.getTxPayloadLength(txData) } return size } @@ -110,22 +114,9 @@ func (w *WrappedBlock) EstimateL1CommitGas() uint64 { continue } - data, _ := hexutil.Decode(txData.Data) - tx := types.NewTx(&types.LegacyTx{ - Nonce: txData.Nonce, - To: txData.To, - Value: txData.Value.ToInt(), - Gas: txData.Gas, - GasPrice: txData.GasPrice.ToInt(), - Data: data, - V: txData.V.ToInt(), - R: txData.R.ToInt(), - S: txData.S.ToInt(), - }) - rlpTxData, _ := tx.MarshalBinary() - txPayloadLength := uint64(len(rlpTxData)) + txPayloadLength := w.getTxPayloadLength(txData) total += CalldataNonZeroByteGas * txPayloadLength // an over-estimate: treat each byte as non-zero - total += CalldataNonZeroByteGas * 4 // size of a uint32 field + total += CalldataNonZeroByteGas * 64 // 60 bytes BlockContext + 4 bytes payload length total += GetKeccak256Gas(txPayloadLength) // l2 tx hash } @@ -149,3 +140,48 @@ func (w *WrappedBlock) L2TxsNum() uint64 { } return count } + +func (w *WrappedBlock) getTxPayloadLength(txData *types.TransactionData) uint64 { + if w.txPayloadLengthCache == nil { + w.txPayloadLengthCache = make(map[string]uint64) + } + + if length, exists := w.txPayloadLengthCache[txData.TxHash]; exists { + return length + } + + rlpTxData, err := convertTxDataToRLPEncoding(txData) + if err != nil { + log.Crit("convertTxDataToRLPEncoding failed, which should not happen", "hash", txData.TxHash, "err", err) + return 0 + } + txPayloadLength := uint64(len(rlpTxData)) + w.txPayloadLengthCache[txData.TxHash] = txPayloadLength + return txPayloadLength +} + +func convertTxDataToRLPEncoding(txData *types.TransactionData) ([]byte, error) { + data, err := hexutil.Decode(txData.Data) + if err != nil { + return nil, fmt.Errorf("failed to decode txData.Data: %s, err: %w", txData.Data, err) + } + + tx := types.NewTx(&types.LegacyTx{ + Nonce: txData.Nonce, + To: txData.To, + Value: txData.Value.ToInt(), + Gas: txData.Gas, + GasPrice: txData.GasPrice.ToInt(), + Data: data, + V: txData.V.ToInt(), + R: txData.R.ToInt(), + S: txData.S.ToInt(), + }) + + rlpTxData, err := tx.MarshalBinary() + if err != nil { + return nil, fmt.Errorf("failed to marshal binary of the tx: %+v, err: %w", tx, err) + } + + return rlpTxData, nil +} diff --git a/common/types/chunk.go b/common/types/chunk.go index f6498b7e9..feba818de 100644 --- a/common/types/chunk.go +++ b/common/types/chunk.go @@ -8,7 +8,6 @@ import ( "strings" "github.com/scroll-tech/go-ethereum/common" - "github.com/scroll-tech/go-ethereum/common/hexutil" "github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/crypto" ) @@ -65,23 +64,7 @@ func (c *Chunk) Encode(totalL1MessagePoppedBefore uint64) ([]byte, error) { if txData.Type == types.L1MessageTxType { continue } - data, err := hexutil.Decode(txData.Data) - if err != nil { - return nil, err - } - // right now we only support legacy tx - tx := types.NewTx(&types.LegacyTx{ - Nonce: txData.Nonce, - To: txData.To, - Value: txData.Value.ToInt(), - Gas: txData.Gas, - GasPrice: txData.GasPrice.ToInt(), - Data: data, - V: txData.V.ToInt(), - R: txData.R.ToInt(), - S: txData.S.ToInt(), - }) - rlpTxData, err := tx.MarshalBinary() + rlpTxData, err := convertTxDataToRLPEncoding(txData) if err != nil { return nil, err } diff --git a/common/version/version.go b/common/version/version.go index 43b686c09..e7a14fc15 100644 --- a/common/version/version.go +++ b/common/version/version.go @@ -6,7 +6,7 @@ import ( "strings" ) -var tag = "v4.1.90" +var tag = "v4.1.91" var commit = func() string { if info, ok := debug.ReadBuildInfo(); ok {