github.com/ethw3/go-ethereuma@v0.0.0-20221013053120-c14602a4c23c/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/ethw3/go-ethereuma/common" 25 "github.com/ethw3/go-ethereuma/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 }