github.com/baptiste-b-pegasys/quorum/v22@v22.4.2/core/types/transaction_marshalling.go (about)

     1  package types
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"math/big"
     7  
     8  	"github.com/ethereum/go-ethereum/common"
     9  	"github.com/ethereum/go-ethereum/common/hexutil"
    10  )
    11  
    12  // txJSON is the JSON representation of transactions.
    13  type txJSON struct {
    14  	Type hexutil.Uint64 `json:"type"`
    15  
    16  	// Common transaction fields:
    17  	Nonce    *hexutil.Uint64 `json:"nonce"`
    18  	GasPrice *hexutil.Big    `json:"gasPrice"`
    19  	Gas      *hexutil.Uint64 `json:"gas"`
    20  	Value    *hexutil.Big    `json:"value"`
    21  	Data     *hexutil.Bytes  `json:"input"`
    22  	V        *hexutil.Big    `json:"v"`
    23  	R        *hexutil.Big    `json:"r"`
    24  	S        *hexutil.Big    `json:"s"`
    25  	To       *common.Address `json:"to"`
    26  
    27  	// Access list transaction fields:
    28  	ChainID    *hexutil.Big `json:"chainId,omitempty"`
    29  	AccessList *AccessList  `json:"accessList,omitempty"`
    30  
    31  	// Only used for encoding:
    32  	Hash common.Hash `json:"hash"`
    33  }
    34  
    35  // MarshalJSON marshals as JSON with a hash.
    36  func (t *Transaction) MarshalJSON() ([]byte, error) {
    37  	var enc txJSON
    38  	// These are set for all tx types.
    39  	enc.Hash = t.Hash()
    40  	enc.Type = hexutil.Uint64(t.Type())
    41  
    42  	// Other fields are set conditionally depending on tx type.
    43  	switch tx := t.inner.(type) {
    44  	case *LegacyTx:
    45  		enc.Nonce = (*hexutil.Uint64)(&tx.Nonce)
    46  		enc.Gas = (*hexutil.Uint64)(&tx.Gas)
    47  		enc.GasPrice = (*hexutil.Big)(tx.GasPrice)
    48  		enc.Value = (*hexutil.Big)(tx.Value)
    49  		enc.Data = (*hexutil.Bytes)(&tx.Data)
    50  		enc.To = t.To()
    51  		enc.V = (*hexutil.Big)(tx.V)
    52  		enc.R = (*hexutil.Big)(tx.R)
    53  		enc.S = (*hexutil.Big)(tx.S)
    54  	case *AccessListTx:
    55  		enc.ChainID = (*hexutil.Big)(tx.ChainID)
    56  		enc.AccessList = &tx.AccessList
    57  		enc.Nonce = (*hexutil.Uint64)(&tx.Nonce)
    58  		enc.Gas = (*hexutil.Uint64)(&tx.Gas)
    59  		enc.GasPrice = (*hexutil.Big)(tx.GasPrice)
    60  		enc.Value = (*hexutil.Big)(tx.Value)
    61  		enc.Data = (*hexutil.Bytes)(&tx.Data)
    62  		enc.To = t.To()
    63  		enc.V = (*hexutil.Big)(tx.V)
    64  		enc.R = (*hexutil.Big)(tx.R)
    65  		enc.S = (*hexutil.Big)(tx.S)
    66  	}
    67  	return json.Marshal(&enc)
    68  }
    69  
    70  // UnmarshalJSON unmarshals from JSON.
    71  func (t *Transaction) UnmarshalJSON(input []byte) error {
    72  	var dec txJSON
    73  	if err := json.Unmarshal(input, &dec); err != nil {
    74  		return err
    75  	}
    76  
    77  	// Decode / verify fields according to transaction type.
    78  	var inner TxData
    79  	switch dec.Type {
    80  	case LegacyTxType:
    81  		var itx LegacyTx
    82  		inner = &itx
    83  		if dec.To != nil {
    84  			itx.To = dec.To
    85  		}
    86  		if dec.Nonce == nil {
    87  			return errors.New("missing required field 'nonce' in transaction")
    88  		}
    89  		itx.Nonce = uint64(*dec.Nonce)
    90  		if dec.GasPrice == nil {
    91  			return errors.New("missing required field 'gasPrice' in transaction")
    92  		}
    93  		itx.GasPrice = (*big.Int)(dec.GasPrice)
    94  		if dec.Gas == nil {
    95  			return errors.New("missing required field 'gas' in transaction")
    96  		}
    97  		itx.Gas = uint64(*dec.Gas)
    98  		if dec.Value == nil {
    99  			return errors.New("missing required field 'value' in transaction")
   100  		}
   101  		itx.Value = (*big.Int)(dec.Value)
   102  		if dec.Data == nil {
   103  			return errors.New("missing required field 'input' in transaction")
   104  		}
   105  		itx.Data = *dec.Data
   106  		if dec.V == nil {
   107  			return errors.New("missing required field 'v' in transaction")
   108  		}
   109  		itx.V = (*big.Int)(dec.V)
   110  		if dec.R == nil {
   111  			return errors.New("missing required field 'r' in transaction")
   112  		}
   113  		itx.R = (*big.Int)(dec.R)
   114  		if dec.S == nil {
   115  			return errors.New("missing required field 's' in transaction")
   116  		}
   117  		itx.S = (*big.Int)(dec.S)
   118  		withSignature := itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0
   119  		if withSignature {
   120  			if err := sanityCheckSignature(itx.V, itx.R, itx.S, true); err != nil {
   121  				return err
   122  			}
   123  		}
   124  
   125  	case AccessListTxType:
   126  		var itx AccessListTx
   127  		inner = &itx
   128  		// Access list is optional for now.
   129  		if dec.AccessList != nil {
   130  			itx.AccessList = *dec.AccessList
   131  		}
   132  		if dec.ChainID == nil {
   133  			return errors.New("missing required field 'chainId' in transaction")
   134  		}
   135  		itx.ChainID = (*big.Int)(dec.ChainID)
   136  		if dec.To != nil {
   137  			itx.To = dec.To
   138  		}
   139  		if dec.Nonce == nil {
   140  			return errors.New("missing required field 'nonce' in transaction")
   141  		}
   142  		itx.Nonce = uint64(*dec.Nonce)
   143  		if dec.GasPrice == nil {
   144  			return errors.New("missing required field 'gasPrice' in transaction")
   145  		}
   146  		itx.GasPrice = (*big.Int)(dec.GasPrice)
   147  		if dec.Gas == nil {
   148  			return errors.New("missing required field 'gas' in transaction")
   149  		}
   150  		itx.Gas = uint64(*dec.Gas)
   151  		if dec.Value == nil {
   152  			return errors.New("missing required field 'value' in transaction")
   153  		}
   154  		itx.Value = (*big.Int)(dec.Value)
   155  		if dec.Data == nil {
   156  			return errors.New("missing required field 'input' in transaction")
   157  		}
   158  		itx.Data = *dec.Data
   159  		if dec.V == nil {
   160  			return errors.New("missing required field 'v' in transaction")
   161  		}
   162  		itx.V = (*big.Int)(dec.V)
   163  		if dec.R == nil {
   164  			return errors.New("missing required field 'r' in transaction")
   165  		}
   166  		itx.R = (*big.Int)(dec.R)
   167  		if dec.S == nil {
   168  			return errors.New("missing required field 's' in transaction")
   169  		}
   170  		itx.S = (*big.Int)(dec.S)
   171  		withSignature := itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0
   172  		if withSignature {
   173  			if err := sanityCheckSignature(itx.V, itx.R, itx.S, false); err != nil {
   174  				return err
   175  			}
   176  		}
   177  
   178  	default:
   179  		return ErrTxTypeNotSupported
   180  	}
   181  
   182  	// Now set the inner transaction.
   183  	t.setDecoded(inner, 0)
   184  
   185  	// TODO: check hash here?
   186  	return nil
   187  }