github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/tests/transaction_test_util.go (about) 1 // Copyright 2015 The Spectrum Authors 2 // This file is part of the Spectrum library. 3 // 4 // The Spectrum 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 Spectrum 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 Spectrum 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/SmartMeshFoundation/Spectrum/common" 26 "github.com/SmartMeshFoundation/Spectrum/common/hexutil" 27 "github.com/SmartMeshFoundation/Spectrum/common/math" 28 "github.com/SmartMeshFoundation/Spectrum/core/types" 29 "github.com/SmartMeshFoundation/Spectrum/params" 30 "github.com/SmartMeshFoundation/Spectrum/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 *big.Int `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.HexOrDecimal256 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 } else { 76 return fmt.Errorf("RLP decoding failed: %v", err) 77 } 78 } 79 // Check sender derivation. 80 signer := types.MakeSigner(config, new(big.Int).SetUint64(uint64(tt.json.BlockNumber))) 81 sender, err := types.Sender(signer, tx) 82 if err != nil { 83 return err 84 } 85 if sender != common.BytesToAddress(tt.json.Sender) { 86 return fmt.Errorf("Sender mismatch: got %x, want %x", sender, tt.json.Sender) 87 } 88 // Check decoded fields. 89 err = tt.json.Transaction.verify(signer, tx) 90 if tt.json.Sender == nil && err == nil { 91 return errors.New("field validations succeeded but should fail") 92 } 93 if tt.json.Sender != nil && err != nil { 94 return fmt.Errorf("field validations failed after RLP decoding: %s", err) 95 } 96 return nil 97 } 98 99 func (tt *ttTransaction) verify(signer types.Signer, tx *types.Transaction) error { 100 if !bytes.Equal(tx.Data(), tt.Data) { 101 return fmt.Errorf("Tx input data mismatch: got %x want %x", tx.Data(), tt.Data) 102 } 103 if tx.Gas().Cmp(tt.GasLimit) != 0 { 104 return fmt.Errorf("GasLimit mismatch: got %v, want %v", tx.Gas(), tt.GasLimit) 105 } 106 if tx.GasPrice().Cmp(tt.GasPrice) != 0 { 107 return fmt.Errorf("GasPrice mismatch: got %v, want %v", tx.GasPrice(), tt.GasPrice) 108 } 109 if tx.Nonce() != tt.Nonce { 110 return fmt.Errorf("Nonce mismatch: got %v, want %v", tx.Nonce(), tt.Nonce) 111 } 112 v, r, s := tx.RawSignatureValues() 113 if r.Cmp(tt.R) != 0 { 114 return fmt.Errorf("R mismatch: got %v, want %v", r, tt.R) 115 } 116 if s.Cmp(tt.S) != 0 { 117 return fmt.Errorf("S mismatch: got %v, want %v", s, tt.S) 118 } 119 if v.Cmp(tt.V) != 0 { 120 return fmt.Errorf("V mismatch: got %v, want %v", v, tt.V) 121 } 122 if tx.To() == nil { 123 if tt.To != (common.Address{}) { 124 return fmt.Errorf("To mismatch when recipient is nil (contract creation): %x", tt.To) 125 } 126 } else if *tx.To() != tt.To { 127 return fmt.Errorf("To mismatch: got %x, want %x", *tx.To(), tt.To) 128 } 129 if tx.Value().Cmp(tt.Value) != 0 { 130 return fmt.Errorf("Value mismatch: got %x, want %x", tx.Value(), tt.Value) 131 } 132 return nil 133 }