diff --git a/core/types/gen_access_tuple.go b/core/types/gen_access_tuple.go index d740b70981..fc48a84cc0 100644 --- a/core/types/gen_access_tuple.go +++ b/core/types/gen_access_tuple.go @@ -12,8 +12,8 @@ import ( // MarshalJSON marshals as JSON. func (a AccessTuple) MarshalJSON() ([]byte, error) { type AccessTuple struct { - Address common.Address `json:"address" gencodec:"required"` - StorageKeys []common.Hash `json:"storageKeys" gencodec:"required"` + Address common.Address `json:"address" gencodec:"required"` + StorageKeys []common.Hash `json:"storageKeys" gencodec:"required"` } var enc AccessTuple enc.Address = a.Address @@ -24,8 +24,8 @@ func (a AccessTuple) MarshalJSON() ([]byte, error) { // UnmarshalJSON unmarshals from JSON. func (a *AccessTuple) UnmarshalJSON(input []byte) error { type AccessTuple struct { - Address *common.Address `json:"address" gencodec:"required"` - StorageKeys []common.Hash `json:"storageKeys" gencodec:"required"` + Address *common.Address `json:"address" gencodec:"required"` + StorageKeys []common.Hash `json:"storageKeys" gencodec:"required"` } var dec AccessTuple if err := json.Unmarshal(input, &dec); err != nil { diff --git a/core/types/transaction.go b/core/types/transaction.go index b7cb36b602..f0b674f344 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -198,7 +198,7 @@ func (tx *Transaction) decodeTyped(b []byte) (TxData, error) { return &inner, err case BlobTxType: var inner BlobTx - err := rlp.DecodeBytes(b[1:], &inner) + err := rlp.DecodeBytes(b[1:], &inner) // TODO(karalabe): This needs to be ssz return &inner, err default: return nil, ErrTxTypeNotSupported @@ -417,7 +417,11 @@ func (tx *Transaction) Size() uint64 { return size.(uint64) } c := writeCounter(0) - rlp.Encode(&c, &tx.inner) + if tx.Type() == BlobTxType { + rlp.Encode(&c, &tx.inner) // TODO(karalabe): Replace with SSZ encoding + } else { + rlp.Encode(&c, &tx.inner) + } size := uint64(c) if tx.Type() != LegacyTxType { diff --git a/core/types/transaction_marshalling.go b/core/types/transaction_marshalling.go index 6c6c50d498..2566d0b8d6 100644 --- a/core/types/transaction_marshalling.go +++ b/core/types/transaction_marshalling.go @@ -23,28 +23,28 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/holiman/uint256" ) // txJSON is the JSON representation of transactions. type txJSON struct { Type hexutil.Uint64 `json:"type"` - ChainID *hexutil.Big `json:"chainId,omitempty"` + // Common transaction fields: Nonce *hexutil.Uint64 `json:"nonce"` - To *common.Address `json:"to"` - Gas *hexutil.Uint64 `json:"gas"` GasPrice *hexutil.Big `json:"gasPrice"` MaxPriorityFeePerGas *hexutil.Big `json:"maxPriorityFeePerGas"` MaxFeePerGas *hexutil.Big `json:"maxFeePerGas"` - MaxFeePerDataGas *hexutil.Big `json:"maxFeePerDataGas,omitempty"` + Gas *hexutil.Uint64 `json:"gas"` Value *hexutil.Big `json:"value"` - Input *hexutil.Bytes `json:"input"` - AccessList *AccessList `json:"accessList,omitempty"` - BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"` + Data *hexutil.Bytes `json:"input"` V *hexutil.Big `json:"v"` R *hexutil.Big `json:"r"` S *hexutil.Big `json:"s"` + To *common.Address `json:"to"` + + // Access list transaction fields: + ChainID *hexutil.Big `json:"chainId,omitempty"` + AccessList *AccessList `json:"accessList,omitempty"` // Only used for encoding: Hash common.Hash `json:"hash"` @@ -61,57 +61,39 @@ func (tx *Transaction) MarshalJSON() ([]byte, error) { switch itx := tx.inner.(type) { case *LegacyTx: enc.Nonce = (*hexutil.Uint64)(&itx.Nonce) - enc.To = tx.To() enc.Gas = (*hexutil.Uint64)(&itx.Gas) enc.GasPrice = (*hexutil.Big)(itx.GasPrice) enc.Value = (*hexutil.Big)(itx.Value) - enc.Input = (*hexutil.Bytes)(&itx.Data) + enc.Data = (*hexutil.Bytes)(&itx.Data) + enc.To = tx.To() enc.V = (*hexutil.Big)(itx.V) enc.R = (*hexutil.Big)(itx.R) enc.S = (*hexutil.Big)(itx.S) - case *AccessListTx: enc.ChainID = (*hexutil.Big)(itx.ChainID) + enc.AccessList = &itx.AccessList enc.Nonce = (*hexutil.Uint64)(&itx.Nonce) - enc.To = tx.To() enc.Gas = (*hexutil.Uint64)(&itx.Gas) enc.GasPrice = (*hexutil.Big)(itx.GasPrice) enc.Value = (*hexutil.Big)(itx.Value) - enc.Input = (*hexutil.Bytes)(&itx.Data) - enc.AccessList = &itx.AccessList + enc.Data = (*hexutil.Bytes)(&itx.Data) + enc.To = tx.To() enc.V = (*hexutil.Big)(itx.V) enc.R = (*hexutil.Big)(itx.R) enc.S = (*hexutil.Big)(itx.S) - case *DynamicFeeTx: enc.ChainID = (*hexutil.Big)(itx.ChainID) + enc.AccessList = &itx.AccessList enc.Nonce = (*hexutil.Uint64)(&itx.Nonce) - enc.To = tx.To() enc.Gas = (*hexutil.Uint64)(&itx.Gas) enc.MaxFeePerGas = (*hexutil.Big)(itx.GasFeeCap) enc.MaxPriorityFeePerGas = (*hexutil.Big)(itx.GasTipCap) enc.Value = (*hexutil.Big)(itx.Value) - enc.Input = (*hexutil.Bytes)(&itx.Data) - enc.AccessList = &itx.AccessList + enc.Data = (*hexutil.Bytes)(&itx.Data) + enc.To = tx.To() enc.V = (*hexutil.Big)(itx.V) enc.R = (*hexutil.Big)(itx.R) enc.S = (*hexutil.Big)(itx.S) - - case *BlobTx: - enc.ChainID = (*hexutil.Big)(itx.ChainID.ToBig()) - enc.Nonce = (*hexutil.Uint64)(&itx.Nonce) - enc.Gas = (*hexutil.Uint64)(&itx.Gas) - enc.MaxFeePerGas = (*hexutil.Big)(itx.GasFeeCap.ToBig()) - enc.MaxPriorityFeePerGas = (*hexutil.Big)(itx.GasTipCap.ToBig()) - enc.MaxFeePerDataGas = (*hexutil.Big)(itx.BlobFeeCap.ToBig()) - enc.Value = (*hexutil.Big)(itx.Value.ToBig()) - enc.Input = (*hexutil.Bytes)(&itx.Data) - enc.AccessList = &itx.AccessList - enc.BlobVersionedHashes = itx.BlobHashes - enc.To = tx.To() - enc.V = (*hexutil.Big)(itx.V.ToBig()) - enc.R = (*hexutil.Big)(itx.R.ToBig()) - enc.S = (*hexutil.Big)(itx.S.ToBig()) } return json.Marshal(&enc) } @@ -129,29 +111,29 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error { case LegacyTxType: var itx LegacyTx inner = &itx + if dec.To != nil { + itx.To = dec.To + } if dec.Nonce == nil { return errors.New("missing required field 'nonce' in transaction") } itx.Nonce = uint64(*dec.Nonce) - if dec.To != nil { - itx.To = dec.To - } - if dec.Gas == nil { - return errors.New("missing required field 'gas' in transaction") - } - itx.Gas = uint64(*dec.Gas) if dec.GasPrice == nil { return errors.New("missing required field 'gasPrice' in transaction") } itx.GasPrice = (*big.Int)(dec.GasPrice) + if dec.Gas == nil { + return errors.New("missing required field 'gas' in transaction") + } + itx.Gas = uint64(*dec.Gas) if dec.Value == nil { return errors.New("missing required field 'value' in transaction") } itx.Value = (*big.Int)(dec.Value) - if dec.Input == nil { + if dec.Data == nil { return errors.New("missing required field 'input' in transaction") } - itx.Data = *dec.Input + itx.Data = *dec.Data if dec.V == nil { return errors.New("missing required field 'v' in transaction") } @@ -174,39 +156,40 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error { case AccessListTxType: var itx AccessListTx inner = &itx + // Access list is optional for now. + if dec.AccessList != nil { + itx.AccessList = *dec.AccessList + } if dec.ChainID == nil { return errors.New("missing required field 'chainId' in transaction") } itx.ChainID = (*big.Int)(dec.ChainID) + if dec.To != nil { + itx.To = dec.To + } if dec.Nonce == nil { return errors.New("missing required field 'nonce' in transaction") } itx.Nonce = uint64(*dec.Nonce) - if dec.To != nil { - itx.To = dec.To - } - if dec.Gas == nil { - return errors.New("missing required field 'gas' in transaction") - } - itx.Gas = uint64(*dec.Gas) if dec.GasPrice == nil { return errors.New("missing required field 'gasPrice' in transaction") } itx.GasPrice = (*big.Int)(dec.GasPrice) + if dec.Gas == nil { + return errors.New("missing required field 'gas' in transaction") + } + itx.Gas = uint64(*dec.Gas) if dec.Value == nil { return errors.New("missing required field 'value' in transaction") } itx.Value = (*big.Int)(dec.Value) - if dec.Input == nil { + if dec.Data == nil { return errors.New("missing required field 'input' in transaction") } - itx.Data = *dec.Input + itx.Data = *dec.Data if dec.V == nil { return errors.New("missing required field 'v' in transaction") } - if dec.AccessList != nil { - itx.AccessList = *dec.AccessList - } itx.V = (*big.Int)(dec.V) if dec.R == nil { return errors.New("missing required field 'r' in transaction") @@ -226,21 +209,21 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error { case DynamicFeeTxType: var itx DynamicFeeTx inner = &itx + // Access list is optional for now. + if dec.AccessList != nil { + itx.AccessList = *dec.AccessList + } if dec.ChainID == nil { return errors.New("missing required field 'chainId' in transaction") } itx.ChainID = (*big.Int)(dec.ChainID) + if dec.To != nil { + itx.To = dec.To + } if dec.Nonce == nil { return errors.New("missing required field 'nonce' in transaction") } itx.Nonce = uint64(*dec.Nonce) - if dec.To != nil { - itx.To = dec.To - } - if dec.Gas == nil { - return errors.New("missing required field 'gas' for txdata") - } - itx.Gas = uint64(*dec.Gas) if dec.MaxPriorityFeePerGas == nil { return errors.New("missing required field 'maxPriorityFeePerGas' for txdata") } @@ -249,20 +232,21 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error { return errors.New("missing required field 'maxFeePerGas' for txdata") } itx.GasFeeCap = (*big.Int)(dec.MaxFeePerGas) + if dec.Gas == nil { + return errors.New("missing required field 'gas' for txdata") + } + itx.Gas = uint64(*dec.Gas) if dec.Value == nil { return errors.New("missing required field 'value' in transaction") } itx.Value = (*big.Int)(dec.Value) - if dec.Input == nil { + if dec.Data == nil { return errors.New("missing required field 'input' in transaction") } - itx.Data = *dec.Input + itx.Data = *dec.Data if dec.V == nil { return errors.New("missing required field 'v' in transaction") } - if dec.AccessList != nil { - itx.AccessList = *dec.AccessList - } itx.V = (*big.Int)(dec.V) if dec.R == nil { return errors.New("missing required field 'r' in transaction") @@ -279,70 +263,6 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error { } } - case BlobTxType: - var itx BlobTx - inner = &itx - if dec.ChainID == nil { - return errors.New("missing required field 'chainId' in transaction") - } - itx.ChainID = uint256.MustFromBig((*big.Int)(dec.ChainID)) - if dec.Nonce == nil { - return errors.New("missing required field 'nonce' in transaction") - } - itx.Nonce = uint64(*dec.Nonce) - if dec.To != nil { - itx.To = dec.To - } - if dec.Gas == nil { - return errors.New("missing required field 'gas' for txdata") - } - itx.Gas = uint64(*dec.Gas) - if dec.MaxPriorityFeePerGas == nil { - return errors.New("missing required field 'maxPriorityFeePerGas' for txdata") - } - itx.GasTipCap = uint256.MustFromBig((*big.Int)(dec.MaxPriorityFeePerGas)) - if dec.MaxFeePerGas == nil { - return errors.New("missing required field 'maxFeePerGas' for txdata") - } - itx.GasFeeCap = uint256.MustFromBig((*big.Int)(dec.MaxFeePerGas)) - if dec.MaxFeePerDataGas == nil { - return errors.New("missing required field 'maxFeePerDataGas' for txdata") - } - itx.BlobFeeCap = uint256.MustFromBig((*big.Int)(dec.MaxFeePerDataGas)) - if dec.Value == nil { - return errors.New("missing required field 'value' in transaction") - } - itx.Value = uint256.MustFromBig((*big.Int)(dec.Value)) - if dec.Input == nil { - return errors.New("missing required field 'input' in transaction") - } - itx.Data = *dec.Input - if dec.V == nil { - return errors.New("missing required field 'v' in transaction") - } - if dec.AccessList != nil { - itx.AccessList = *dec.AccessList - } - if dec.BlobVersionedHashes == nil { - return errors.New("missing required field 'blobVersionedHashes' in transaction") - } - itx.BlobHashes = dec.BlobVersionedHashes - itx.V = uint256.MustFromBig((*big.Int)(dec.V)) - if dec.R == nil { - return errors.New("missing required field 'r' in transaction") - } - itx.R = uint256.MustFromBig((*big.Int)(dec.R)) - if dec.S == nil { - return errors.New("missing required field 's' in transaction") - } - itx.S = uint256.MustFromBig((*big.Int)(dec.S)) - withSignature := itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0 - if withSignature { - if err := sanityCheckSignature(itx.V.ToBig(), itx.R.ToBig(), itx.S.ToBig(), false); err != nil { - return err - } - } - default: return ErrTxTypeNotSupported } diff --git a/core/types/tx_access_list.go b/core/types/tx_access_list.go index 7ce9da73ec..825942a41d 100644 --- a/core/types/tx_access_list.go +++ b/core/types/tx_access_list.go @@ -29,8 +29,8 @@ type AccessList []AccessTuple // AccessTuple is the element type of an access list. type AccessTuple struct { - Address common.Address `json:"address" gencodec:"required"` - StorageKeys []common.Hash `json:"storageKeys" gencodec:"required"` + Address common.Address `json:"address" gencodec:"required"` + StorageKeys []common.Hash `json:"storageKeys" gencodec:"required"` } // StorageKeys returns the total number of storage keys in the access list. diff --git a/core/types/tx_blob.go b/core/types/tx_blob.go index 58065d0017..1f64a9871b 100644 --- a/core/types/tx_blob.go +++ b/core/types/tx_blob.go @@ -31,7 +31,7 @@ type BlobTx struct { GasTipCap *uint256.Int // a.k.a. maxPriorityFeePerGas GasFeeCap *uint256.Int // a.k.a. maxFeePerGas Gas uint64 - To *common.Address `rlp:"nil"` // nil means contract creation + To *common.Address // `rlp:"nil"` // nil means contract creation Value *uint256.Int Data []byte AccessList AccessList