github.com/luckypickle/go-ethereum-vet@v1.14.2/tests/transaction_test_util.go (about) 1 // Copyright 2015 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 tests 18 19 import ( 20 "bytes" 21 "errors" 22 "fmt" 23 "math/big" 24 25 "github.com/luckypickle/go-ethereum-vet/common" 26 "github.com/luckypickle/go-ethereum-vet/common/hexutil" 27 "github.com/luckypickle/go-ethereum-vet/common/math" 28 "github.com/luckypickle/go-ethereum-vet/core/types" 29 "github.com/luckypickle/go-ethereum-vet/params" 30 "github.com/luckypickle/go-ethereum-vet/rlp" 31 ) 32 33 // TransactionTest checks RLP decoding and sender derivation of transactions. 34 type TransactionTest struct { 35 json ttJSON 36 } 37 38 type ttJSON struct { 39 BlockNumber math.HexOrDecimal64 `json:"blockNumber"` 40 RLP hexutil.Bytes `json:"rlp"` 41 Sender hexutil.Bytes `json:"sender"` 42 Transaction *ttTransaction `json:"transaction"` 43 } 44 45 //go:generate gencodec -type ttTransaction -field-override ttTransactionMarshaling -out gen_tttransaction.go 46 47 type ttTransaction struct { 48 Data []byte `gencodec:"required"` 49 GasLimit uint64 `gencodec:"required"` 50 GasPrice *big.Int `gencodec:"required"` 51 Nonce uint64 `gencodec:"required"` 52 Value *big.Int `gencodec:"required"` 53 R *big.Int `gencodec:"required"` 54 S *big.Int `gencodec:"required"` 55 V *big.Int `gencodec:"required"` 56 To common.Address `gencodec:"required"` 57 } 58 59 type ttTransactionMarshaling struct { 60 Data hexutil.Bytes 61 GasLimit math.HexOrDecimal64 62 GasPrice *math.HexOrDecimal256 63 Nonce math.HexOrDecimal64 64 Value *math.HexOrDecimal256 65 R *math.HexOrDecimal256 66 S *math.HexOrDecimal256 67 V *math.HexOrDecimal256 68 } 69 70 func (tt *TransactionTest) Run(config *params.ChainConfig) error { 71 tx := new(types.Transaction) 72 if err := rlp.DecodeBytes(tt.json.RLP, tx); err != nil { 73 if tt.json.Transaction == nil { 74 return nil 75 } 76 return fmt.Errorf("RLP decoding failed: %v", err) 77 } 78 // Check sender derivation. 79 signer := types.MakeSigner(config, new(big.Int).SetUint64(uint64(tt.json.BlockNumber))) 80 sender, err := types.Sender(signer, tx) 81 if err != nil { 82 return err 83 } 84 if sender != common.BytesToAddress(tt.json.Sender) { 85 return fmt.Errorf("Sender mismatch: got %x, want %x", sender, tt.json.Sender) 86 } 87 // Check decoded fields. 88 err = tt.json.Transaction.verify(signer, tx) 89 if tt.json.Sender == nil && err == nil { 90 return errors.New("field validations succeeded but should fail") 91 } 92 if tt.json.Sender != nil && err != nil { 93 return fmt.Errorf("field validations failed after RLP decoding: %s", err) 94 } 95 return nil 96 } 97 98 func (tt *ttTransaction) verify(signer types.Signer, tx *types.Transaction) error { 99 if !bytes.Equal(tx.Data(), tt.Data) { 100 return fmt.Errorf("Tx input data mismatch: got %x want %x", tx.Data(), tt.Data) 101 } 102 if tx.Gas() != tt.GasLimit { 103 return fmt.Errorf("GasLimit mismatch: got %d, want %d", tx.Gas(), tt.GasLimit) 104 } 105 if tx.GasPrice().Cmp(tt.GasPrice) != 0 { 106 return fmt.Errorf("GasPrice mismatch: got %v, want %v", tx.GasPrice(), tt.GasPrice) 107 } 108 if tx.Nonce() != tt.Nonce { 109 return fmt.Errorf("Nonce mismatch: got %v, want %v", tx.Nonce(), tt.Nonce) 110 } 111 v, r, s := tx.RawSignatureValues() 112 if r.Cmp(tt.R) != 0 { 113 return fmt.Errorf("R mismatch: got %v, want %v", r, tt.R) 114 } 115 if s.Cmp(tt.S) != 0 { 116 return fmt.Errorf("S mismatch: got %v, want %v", s, tt.S) 117 } 118 if v.Cmp(tt.V) != 0 { 119 return fmt.Errorf("V mismatch: got %v, want %v", v, tt.V) 120 } 121 if tx.To() == nil { 122 if tt.To != (common.Address{}) { 123 return fmt.Errorf("To mismatch when recipient is nil (contract creation): %x", tt.To) 124 } 125 } else if *tx.To() != tt.To { 126 return fmt.Errorf("To mismatch: got %x, want %x", *tx.To(), tt.To) 127 } 128 if tx.Value().Cmp(tt.Value) != 0 { 129 return fmt.Errorf("Value mismatch: got %x, want %x", tx.Value(), tt.Value) 130 } 131 return nil 132 }