github.com/bcnmy/go-ethereum@v1.10.27/core/types/transaction_marshalling.go (about)

     1  // Copyright 2021 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package types
    18  
    19  import (
    20  	"encoding/json"
    21  	"errors"
    22  	"math/big"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/common/hexutil"
    26  )
    27  
    28  // txJSON is the JSON representation of transactions.
    29  type txJSON struct {
    30  	Type hexutil.Uint64 `json:"type"`
    31  
    32  	// Common transaction fields:
    33  	Nonce                *hexutil.Uint64 `json:"nonce"`
    34  	GasPrice             *hexutil.Big    `json:"gasPrice"`
    35  	MaxPriorityFeePerGas *hexutil.Big    `json:"maxPriorityFeePerGas"`
    36  	MaxFeePerGas         *hexutil.Big    `json:"maxFeePerGas"`
    37  	Gas                  *hexutil.Uint64 `json:"gas"`
    38  	Value                *hexutil.Big    `json:"value"`
    39  	Data                 *hexutil.Bytes  `json:"input"`
    40  	V                    *hexutil.Big    `json:"v"`
    41  	R                    *hexutil.Big    `json:"r"`
    42  	S                    *hexutil.Big    `json:"s"`
    43  	To                   *common.Address `json:"to"`
    44  
    45  	// Access list transaction fields:
    46  	ChainID    *hexutil.Big `json:"chainId,omitempty"`
    47  	AccessList *AccessList  `json:"accessList,omitempty"`
    48  
    49  	// Only used for encoding:
    50  	Hash common.Hash `json:"hash"`
    51  }
    52  
    53  // MarshalJSON marshals as JSON with a hash.
    54  func (t *Transaction) MarshalJSON() ([]byte, error) {
    55  	var enc txJSON
    56  	// These are set for all tx types.
    57  	enc.Hash = t.Hash()
    58  	enc.Type = hexutil.Uint64(t.Type())
    59  
    60  	// Other fields are set conditionally depending on tx type.
    61  	switch tx := t.inner.(type) {
    62  	case *LegacyTx:
    63  		enc.Nonce = (*hexutil.Uint64)(&tx.Nonce)
    64  		enc.Gas = (*hexutil.Uint64)(&tx.Gas)
    65  		enc.GasPrice = (*hexutil.Big)(tx.GasPrice)
    66  		enc.Value = (*hexutil.Big)(tx.Value)
    67  		enc.Data = (*hexutil.Bytes)(&tx.Data)
    68  		enc.To = t.To()
    69  		enc.V = (*hexutil.Big)(tx.V)
    70  		enc.R = (*hexutil.Big)(tx.R)
    71  		enc.S = (*hexutil.Big)(tx.S)
    72  	case *AccessListTx:
    73  		enc.ChainID = (*hexutil.Big)(tx.ChainID)
    74  		enc.AccessList = &tx.AccessList
    75  		enc.Nonce = (*hexutil.Uint64)(&tx.Nonce)
    76  		enc.Gas = (*hexutil.Uint64)(&tx.Gas)
    77  		enc.GasPrice = (*hexutil.Big)(tx.GasPrice)
    78  		enc.Value = (*hexutil.Big)(tx.Value)
    79  		enc.Data = (*hexutil.Bytes)(&tx.Data)
    80  		enc.To = t.To()
    81  		enc.V = (*hexutil.Big)(tx.V)
    82  		enc.R = (*hexutil.Big)(tx.R)
    83  		enc.S = (*hexutil.Big)(tx.S)
    84  	case *DynamicFeeTx:
    85  		enc.ChainID = (*hexutil.Big)(tx.ChainID)
    86  		enc.AccessList = &tx.AccessList
    87  		enc.Nonce = (*hexutil.Uint64)(&tx.Nonce)
    88  		enc.Gas = (*hexutil.Uint64)(&tx.Gas)
    89  		enc.MaxFeePerGas = (*hexutil.Big)(tx.GasFeeCap)
    90  		enc.MaxPriorityFeePerGas = (*hexutil.Big)(tx.GasTipCap)
    91  		enc.Value = (*hexutil.Big)(tx.Value)
    92  		enc.Data = (*hexutil.Bytes)(&tx.Data)
    93  		enc.To = t.To()
    94  		enc.V = (*hexutil.Big)(tx.V)
    95  		enc.R = (*hexutil.Big)(tx.R)
    96  		enc.S = (*hexutil.Big)(tx.S)
    97  	}
    98  	return json.Marshal(&enc)
    99  }
   100  
   101  // UnmarshalJSON unmarshals from JSON.
   102  func (t *Transaction) UnmarshalJSON(input []byte) error {
   103  	var dec txJSON
   104  	if err := json.Unmarshal(input, &dec); err != nil {
   105  		return err
   106  	}
   107  
   108  	// Decode / verify fields according to transaction type.
   109  	var inner TxData
   110  	switch dec.Type {
   111  	case LegacyTxType:
   112  		var itx LegacyTx
   113  		inner = &itx
   114  		if dec.To != nil {
   115  			itx.To = dec.To
   116  		}
   117  		if dec.Nonce == nil {
   118  			return errors.New("missing required field 'nonce' in transaction")
   119  		}
   120  		itx.Nonce = uint64(*dec.Nonce)
   121  		if dec.GasPrice == nil {
   122  			return errors.New("missing required field 'gasPrice' in transaction")
   123  		}
   124  		itx.GasPrice = (*big.Int)(dec.GasPrice)
   125  		if dec.Gas == nil {
   126  			return errors.New("missing required field 'gas' in transaction")
   127  		}
   128  		itx.Gas = uint64(*dec.Gas)
   129  		if dec.Value == nil {
   130  			return errors.New("missing required field 'value' in transaction")
   131  		}
   132  		itx.Value = (*big.Int)(dec.Value)
   133  		if dec.Data == nil {
   134  			return errors.New("missing required field 'input' in transaction")
   135  		}
   136  		itx.Data = *dec.Data
   137  		if dec.V == nil {
   138  			return errors.New("missing required field 'v' in transaction")
   139  		}
   140  		itx.V = (*big.Int)(dec.V)
   141  		if dec.R == nil {
   142  			return errors.New("missing required field 'r' in transaction")
   143  		}
   144  		itx.R = (*big.Int)(dec.R)
   145  		if dec.S == nil {
   146  			return errors.New("missing required field 's' in transaction")
   147  		}
   148  		itx.S = (*big.Int)(dec.S)
   149  		withSignature := itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0
   150  		if withSignature {
   151  			if err := sanityCheckSignature(itx.V, itx.R, itx.S, true); err != nil {
   152  				return err
   153  			}
   154  		}
   155  
   156  	case AccessListTxType:
   157  		var itx AccessListTx
   158  		inner = &itx
   159  		// Access list is optional for now.
   160  		if dec.AccessList != nil {
   161  			itx.AccessList = *dec.AccessList
   162  		}
   163  		if dec.ChainID == nil {
   164  			return errors.New("missing required field 'chainId' in transaction")
   165  		}
   166  		itx.ChainID = (*big.Int)(dec.ChainID)
   167  		if dec.To != nil {
   168  			itx.To = dec.To
   169  		}
   170  		if dec.Nonce == nil {
   171  			return errors.New("missing required field 'nonce' in transaction")
   172  		}
   173  		itx.Nonce = uint64(*dec.Nonce)
   174  		if dec.GasPrice == nil {
   175  			return errors.New("missing required field 'gasPrice' in transaction")
   176  		}
   177  		itx.GasPrice = (*big.Int)(dec.GasPrice)
   178  		if dec.Gas == nil {
   179  			return errors.New("missing required field 'gas' in transaction")
   180  		}
   181  		itx.Gas = uint64(*dec.Gas)
   182  		if dec.Value == nil {
   183  			return errors.New("missing required field 'value' in transaction")
   184  		}
   185  		itx.Value = (*big.Int)(dec.Value)
   186  		if dec.Data == nil {
   187  			return errors.New("missing required field 'input' in transaction")
   188  		}
   189  		itx.Data = *dec.Data
   190  		if dec.V == nil {
   191  			return errors.New("missing required field 'v' in transaction")
   192  		}
   193  		itx.V = (*big.Int)(dec.V)
   194  		if dec.R == nil {
   195  			return errors.New("missing required field 'r' in transaction")
   196  		}
   197  		itx.R = (*big.Int)(dec.R)
   198  		if dec.S == nil {
   199  			return errors.New("missing required field 's' in transaction")
   200  		}
   201  		itx.S = (*big.Int)(dec.S)
   202  		withSignature := itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0
   203  		if withSignature {
   204  			if err := sanityCheckSignature(itx.V, itx.R, itx.S, false); err != nil {
   205  				return err
   206  			}
   207  		}
   208  
   209  	case DynamicFeeTxType:
   210  		var itx DynamicFeeTx
   211  		inner = &itx
   212  		// Access list is optional for now.
   213  		if dec.AccessList != nil {
   214  			itx.AccessList = *dec.AccessList
   215  		}
   216  		if dec.ChainID == nil {
   217  			return errors.New("missing required field 'chainId' in transaction")
   218  		}
   219  		itx.ChainID = (*big.Int)(dec.ChainID)
   220  		if dec.To != nil {
   221  			itx.To = dec.To
   222  		}
   223  		if dec.Nonce == nil {
   224  			return errors.New("missing required field 'nonce' in transaction")
   225  		}
   226  		itx.Nonce = uint64(*dec.Nonce)
   227  		if dec.MaxPriorityFeePerGas == nil {
   228  			return errors.New("missing required field 'maxPriorityFeePerGas' for txdata")
   229  		}
   230  		itx.GasTipCap = (*big.Int)(dec.MaxPriorityFeePerGas)
   231  		if dec.MaxFeePerGas == nil {
   232  			return errors.New("missing required field 'maxFeePerGas' for txdata")
   233  		}
   234  		itx.GasFeeCap = (*big.Int)(dec.MaxFeePerGas)
   235  		if dec.Gas == nil {
   236  			return errors.New("missing required field 'gas' for txdata")
   237  		}
   238  		itx.Gas = uint64(*dec.Gas)
   239  		if dec.Value == nil {
   240  			return errors.New("missing required field 'value' in transaction")
   241  		}
   242  		itx.Value = (*big.Int)(dec.Value)
   243  		if dec.Data == nil {
   244  			return errors.New("missing required field 'input' in transaction")
   245  		}
   246  		itx.Data = *dec.Data
   247  		if dec.V == nil {
   248  			return errors.New("missing required field 'v' in transaction")
   249  		}
   250  		itx.V = (*big.Int)(dec.V)
   251  		if dec.R == nil {
   252  			return errors.New("missing required field 'r' in transaction")
   253  		}
   254  		itx.R = (*big.Int)(dec.R)
   255  		if dec.S == nil {
   256  			return errors.New("missing required field 's' in transaction")
   257  		}
   258  		itx.S = (*big.Int)(dec.S)
   259  		withSignature := itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0
   260  		if withSignature {
   261  			if err := sanityCheckSignature(itx.V, itx.R, itx.S, false); err != nil {
   262  				return err
   263  			}
   264  		}
   265  
   266  	default:
   267  		return ErrTxTypeNotSupported
   268  	}
   269  
   270  	// Now set the inner transaction.
   271  	t.setDecoded(inner, 0)
   272  
   273  	// TODO: check hash here?
   274  	return nil
   275  }