github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/evm/types/tx_data.go (about) 1 package types 2 3 import ( 4 "errors" 5 "fmt" 6 "math/big" 7 8 "github.com/tendermint/go-amino" 9 10 "github.com/fibonacci-chain/fbc/app/utils" 11 12 ethcmn "github.com/ethereum/go-ethereum/common" 13 ) 14 15 // TxData implements the Ethereum transaction data structure. It is used 16 // solely as intended in Ethereum abiding by the protocol. 17 type TxData struct { 18 AccountNonce uint64 `json:"nonce"` 19 Price *big.Int `json:"gasPrice"` 20 GasLimit uint64 `json:"gas"` 21 Recipient *ethcmn.Address `json:"to" rlp:"nil"` // nil means contract creation 22 Amount *big.Int `json:"value"` 23 Payload []byte `json:"input"` 24 25 // signature values 26 V *big.Int `json:"v"` 27 R *big.Int `json:"r"` 28 S *big.Int `json:"s"` 29 30 // hash is only used when marshaling to JSON 31 Hash *ethcmn.Hash `json:"hash" rlp:"-"` 32 } 33 34 // encodableTxData implements the Ethereum transaction data structure. It is used 35 // solely as intended in Ethereum abiding by the protocol. 36 type encodableTxData struct { 37 AccountNonce uint64 `json:"nonce"` 38 Price string `json:"gasPrice"` 39 GasLimit uint64 `json:"gas"` 40 Recipient *ethcmn.Address `json:"to" rlp:"nil"` // nil means contract creation 41 Amount string `json:"value"` 42 Payload []byte `json:"input"` 43 44 // signature values 45 V string `json:"v"` 46 R string `json:"r"` 47 S string `json:"s"` 48 49 // hash is only used when marshaling to JSON 50 Hash *ethcmn.Hash `json:"hash" rlp:"-"` 51 } 52 53 func (tx *encodableTxData) UnmarshalFromAmino(_ *amino.Codec, data []byte) error { 54 var dataLen uint64 = 0 55 var subData []byte 56 57 for { 58 data = data[dataLen:] 59 60 if len(data) == 0 { 61 break 62 } 63 64 pos, pbType, err := amino.ParseProtoPosAndTypeMustOneByte(data[0]) 65 if err != nil { 66 return err 67 } 68 data = data[1:] 69 70 if pbType == amino.Typ3_ByteLength { 71 var n int 72 dataLen, n, err = amino.DecodeUvarint(data) 73 if err != nil { 74 return err 75 } 76 data = data[n:] 77 if len(data) < int(dataLen) { 78 return fmt.Errorf("invalid tx data") 79 } 80 subData = data[:dataLen] 81 } 82 83 switch pos { 84 case 1: 85 var n int 86 tx.AccountNonce, n, err = amino.DecodeUvarint(data) 87 if err != nil { 88 return err 89 } 90 dataLen = uint64(n) 91 case 2: 92 tx.Price = string(subData) 93 case 3: 94 var n int 95 tx.GasLimit, n, err = amino.DecodeUvarint(data) 96 if err != nil { 97 return err 98 } 99 dataLen = uint64(n) 100 case 4: 101 if dataLen != ethcmn.AddressLength { 102 return errors.New("eth addr len error") 103 } 104 tx.Recipient = new(ethcmn.Address) 105 copy(tx.Recipient[:], subData) 106 case 5: 107 tx.Amount = string(subData) 108 case 6: 109 tx.Payload = make([]byte, dataLen) 110 copy(tx.Payload, subData) 111 case 7: 112 tx.V = string(subData) 113 case 8: 114 tx.R = string(subData) 115 case 9: 116 tx.S = string(subData) 117 case 10: 118 if dataLen != ethcmn.HashLength { 119 return errors.New("hash len error") 120 } 121 tx.Hash = new(ethcmn.Hash) 122 copy(tx.Hash[:], subData) 123 default: 124 return fmt.Errorf("unexpect feild num %d", pos) 125 } 126 } 127 return nil 128 } 129 130 func (td TxData) String() string { 131 if td.Recipient != nil { 132 return fmt.Sprintf("nonce=%d price=%s gasLimit=%d recipient=%s amount=%s data=0x%x v=%s r=%s s=%s", 133 td.AccountNonce, td.Price, td.GasLimit, td.Recipient.Hex(), td.Amount, td.Payload, td.V, td.R, td.S) 134 } 135 136 return fmt.Sprintf("nonce=%d price=%s gasLimit=%d recipient=nil amount=%s data=0x%x v=%s r=%s s=%s", 137 td.AccountNonce, td.Price, td.GasLimit, td.Amount, td.Payload, td.V, td.R, td.S) 138 } 139 140 // MarshalAmino defines custom encoding scheme for TxData 141 func (td TxData) MarshalAmino() ([]byte, error) { 142 gasPrice, err := utils.MarshalBigInt(td.Price) 143 if err != nil { 144 return nil, err 145 } 146 147 amount, err := utils.MarshalBigInt(td.Amount) 148 if err != nil { 149 return nil, err 150 } 151 152 v, err := utils.MarshalBigInt(td.V) 153 if err != nil { 154 return nil, err 155 } 156 157 r, err := utils.MarshalBigInt(td.R) 158 if err != nil { 159 return nil, err 160 } 161 162 s, err := utils.MarshalBigInt(td.S) 163 if err != nil { 164 return nil, err 165 } 166 167 e := encodableTxData{ 168 AccountNonce: td.AccountNonce, 169 Price: gasPrice, 170 GasLimit: td.GasLimit, 171 Recipient: td.Recipient, 172 Amount: amount, 173 Payload: td.Payload, 174 V: v, 175 R: r, 176 S: s, 177 Hash: td.Hash, 178 } 179 180 return ModuleCdc.MarshalBinaryBare(e) 181 } 182 183 // UnmarshalAmino defines custom decoding scheme for TxData 184 func (td *TxData) UnmarshalAmino(data []byte) error { 185 var e encodableTxData 186 err := ModuleCdc.UnmarshalBinaryBare(data, &e) 187 if err != nil { 188 return err 189 } 190 191 td.AccountNonce = e.AccountNonce 192 td.GasLimit = e.GasLimit 193 td.Recipient = e.Recipient 194 td.Payload = e.Payload 195 td.Hash = e.Hash 196 197 price, err := utils.UnmarshalBigInt(e.Price) 198 if err != nil { 199 return err 200 } 201 202 if td.Price != nil { 203 td.Price.Set(price) 204 } else { 205 td.Price = price 206 } 207 208 amt, err := utils.UnmarshalBigInt(e.Amount) 209 if err != nil { 210 return err 211 } 212 213 if td.Amount != nil { 214 td.Amount.Set(amt) 215 } else { 216 td.Amount = amt 217 } 218 219 v, err := utils.UnmarshalBigInt(e.V) 220 if err != nil { 221 return err 222 } 223 224 if td.V != nil { 225 td.V.Set(v) 226 } else { 227 td.V = v 228 } 229 230 r, err := utils.UnmarshalBigInt(e.R) 231 if err != nil { 232 return err 233 } 234 235 if td.R != nil { 236 td.R.Set(r) 237 } else { 238 td.R = r 239 } 240 241 s, err := utils.UnmarshalBigInt(e.S) 242 if err != nil { 243 return err 244 } 245 246 if td.S != nil { 247 td.S.Set(s) 248 } else { 249 td.S = s 250 } 251 252 return nil 253 } 254 255 func (td *TxData) unmarshalFromAmino(cdc *amino.Codec, data []byte) error { 256 var e encodableTxData 257 err := e.UnmarshalFromAmino(cdc, data) 258 if err != nil { 259 return err 260 } 261 td.AccountNonce = e.AccountNonce 262 td.GasLimit = e.GasLimit 263 td.Recipient = e.Recipient 264 td.Payload = e.Payload 265 td.Hash = e.Hash 266 267 price, err := utils.UnmarshalBigInt(e.Price) 268 if err != nil { 269 return err 270 } 271 272 if td.Price != nil { 273 td.Price.Set(price) 274 } else { 275 td.Price = price 276 } 277 278 amt, err := utils.UnmarshalBigInt(e.Amount) 279 if err != nil { 280 return err 281 } 282 283 if td.Amount != nil { 284 td.Amount.Set(amt) 285 } else { 286 td.Amount = amt 287 } 288 289 v, err := utils.UnmarshalBigInt(e.V) 290 if err != nil { 291 return err 292 } 293 294 if td.V != nil { 295 td.V.Set(v) 296 } else { 297 td.V = v 298 } 299 300 r, err := utils.UnmarshalBigInt(e.R) 301 if err != nil { 302 return err 303 } 304 305 if td.R != nil { 306 td.R.Set(r) 307 } else { 308 td.R = r 309 } 310 311 s, err := utils.UnmarshalBigInt(e.S) 312 if err != nil { 313 return err 314 } 315 316 if td.S != nil { 317 td.S.Set(s) 318 } else { 319 td.S = s 320 } 321 322 return nil 323 } 324 325 func (td *TxData) UnmarshalFromAmino(cdc *amino.Codec, data []byte) error { 326 err := td.unmarshalFromAmino(cdc, data) 327 if err != nil { 328 u64, n, err := amino.DecodeUvarint(data) 329 if err == nil && int(u64) == (len(data)-n) { 330 return td.unmarshalFromAmino(cdc, data[n:]) 331 } else { 332 return err 333 } 334 } 335 return nil 336 } 337 338 // TODO: Implement JSON marshaling/ unmarshaling for this type 339 340 // TODO: Implement YAML marshaling/ unmarshaling for this type