From 94995b7e10b11206f6b739946a8f9861b81e5d29 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com> Date: Wed, 8 Nov 2023 16:20:31 +0800 Subject: [PATCH] add `L1MessageTx` type (#555) * init * rename * fix * fix * gofmt --- core/types/transaction.go | 26 +++++++++++++++ core/types/tx_l1_message.go | 65 +++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 core/types/tx_l1_message.go diff --git a/core/types/transaction.go b/core/types/transaction.go index 6f83c21d8f..25a81a56b9 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -45,6 +45,8 @@ const ( AccessListTxType = 0x01 DynamicFeeTxType = 0x02 BlobTxType = 0x03 + + L1MessageTxType = 0x7E ) // Transaction is an Ethereum transaction. @@ -202,6 +204,8 @@ func (tx *Transaction) decodeTyped(b []byte) (TxData, error) { inner = new(DynamicFeeTx) case BlobTxType: inner = new(BlobTx) + case L1MessageTxType: + inner = new(BlobTx) default: return nil, ErrTxTypeNotSupported } @@ -510,6 +514,28 @@ func (tx *Transaction) WithSignature(signer Signer, sig []byte) (*Transaction, e return &Transaction{inner: cpy, time: tx.time}, nil } +// IsL1MessageTx returns true if the transaction is an L1 cross-domain tx. +func (tx *Transaction) IsL1MessageTx() bool { + return tx.Type() == L1MessageTxType +} + +// AsL1MessageTx casts the tx into an L1 cross-domain tx. +func (tx *Transaction) AsL1MessageTx() *L1MessageTx { + if !tx.IsL1MessageTx() { + return nil + } + return tx.inner.(*L1MessageTx) +} + +// L1MessageQueueIndex returns the L1 queue index if `tx` is of type `L1MessageTx`. +// It returns 0 otherwise. +func (tx *Transaction) L1MessageQueueIndex() uint64 { + if !tx.IsL1MessageTx() { + return 0 + } + return tx.AsL1MessageTx().QueueIndex +} + // Transactions implements DerivableList for transactions. type Transactions []*Transaction diff --git a/core/types/tx_l1_message.go b/core/types/tx_l1_message.go new file mode 100644 index 0000000000..eede730416 --- /dev/null +++ b/core/types/tx_l1_message.go @@ -0,0 +1,65 @@ +package types + +import ( + "bytes" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/rlp" +) + +// payload, RLP encoded +type L1MessageTx struct { + QueueIndex uint64 + Gas uint64 // gas limit + To *common.Address // can not be nil, we do not allow contract creation from L1 + Value *big.Int + Data []byte + Sender common.Address +} + +// copy creates a deep copy of the transaction data and initializes all fields. +func (tx *L1MessageTx) copy() TxData { + cpy := &L1MessageTx{ + QueueIndex: tx.QueueIndex, + Gas: tx.Gas, + To: copyAddressPtr(tx.To), + Value: new(big.Int), + Data: common.CopyBytes(tx.Data), + Sender: tx.Sender, + } + if tx.Value != nil { + cpy.Value.Set(tx.Value) + } + return cpy +} + +// accessors for innerTx. +func (tx *L1MessageTx) txType() byte { return L1MessageTxType } +func (tx *L1MessageTx) chainID() *big.Int { return common.Big0 } +func (tx *L1MessageTx) accessList() AccessList { return nil } +func (tx *L1MessageTx) data() []byte { return tx.Data } +func (tx *L1MessageTx) gas() uint64 { return tx.Gas } +func (tx *L1MessageTx) gasFeeCap() *big.Int { return new(big.Int) } +func (tx *L1MessageTx) gasTipCap() *big.Int { return new(big.Int) } +func (tx *L1MessageTx) gasPrice() *big.Int { return new(big.Int) } +func (tx *L1MessageTx) effectiveGasPrice(*big.Int, *big.Int) *big.Int { return new(big.Int) } +func (tx *L1MessageTx) value() *big.Int { return tx.Value } +func (tx *L1MessageTx) nonce() uint64 { return 0 } +func (tx *L1MessageTx) to() *common.Address { return tx.To } + +func (tx *L1MessageTx) rawSignatureValues() (v, r, s *big.Int) { + return common.Big0, common.Big0, common.Big0 +} + +func (tx *L1MessageTx) setSignatureValues(chainID, v, r, s *big.Int) { + // this is a noop for l1 message transactions +} + +func (tx *L1MessageTx) encode(b *bytes.Buffer) error { + return rlp.Encode(b, tx) +} + +func (tx *L1MessageTx) decode(input []byte) error { + return rlp.DecodeBytes(input, tx) +}