github.com/juliankolbe/go-ethereum@v1.9.992/cmd/devp2p/internal/ethtest/transaction.go (about) 1 // Copyright 2020 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 ethtest 18 19 import ( 20 "time" 21 22 "github.com/juliankolbe/go-ethereum/common" 23 "github.com/juliankolbe/go-ethereum/core/types" 24 "github.com/juliankolbe/go-ethereum/crypto" 25 "github.com/juliankolbe/go-ethereum/internal/utesting" 26 ) 27 28 //var faucetAddr = common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7") 29 var faucetKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 30 31 func sendSuccessfulTx(t *utesting.T, s *Suite, tx *types.Transaction) { 32 sendConn := s.setupConnection(t) 33 sendSuccessfulTxWithConn(t, s, tx, sendConn) 34 } 35 36 func sendSuccessfulTxWithConn(t *utesting.T, s *Suite, tx *types.Transaction, sendConn *Conn) { 37 t.Logf("sending tx: %v %v %v\n", tx.Hash().String(), tx.GasPrice(), tx.Gas()) 38 // Send the transaction 39 if err := sendConn.Write(&Transactions{tx}); err != nil { 40 t.Fatal(err) 41 } 42 time.Sleep(100 * time.Millisecond) 43 recvConn := s.setupConnection(t) 44 // Wait for the transaction announcement 45 switch msg := recvConn.ReadAndServe(s.chain, timeout).(type) { 46 case *Transactions: 47 recTxs := *msg 48 for _, gotTx := range recTxs { 49 if gotTx.Hash() == tx.Hash() { 50 // Ok 51 return 52 } 53 } 54 t.Fatalf("missing transaction: got %v missing %v", recTxs, tx.Hash()) 55 case *NewPooledTransactionHashes: 56 txHashes := *msg 57 for _, gotHash := range txHashes { 58 if gotHash == tx.Hash() { 59 return 60 } 61 } 62 t.Fatalf("missing transaction announcement: got %v missing %v", txHashes, tx.Hash()) 63 default: 64 t.Fatalf("unexpected message in sendSuccessfulTx: %s", pretty.Sdump(msg)) 65 } 66 } 67 68 func sendFailingTx(t *utesting.T, s *Suite, tx *types.Transaction) { 69 sendConn, recvConn := s.setupConnection(t), s.setupConnection(t) 70 sendFailingTxWithConns(t, s, tx, sendConn, recvConn) 71 } 72 73 func sendFailingTxWithConns(t *utesting.T, s *Suite, tx *types.Transaction, sendConn, recvConn *Conn) { 74 // Wait for a transaction announcement 75 switch msg := recvConn.ReadAndServe(s.chain, timeout).(type) { 76 case *NewPooledTransactionHashes: 77 break 78 default: 79 t.Logf("unexpected message, logging: %v", pretty.Sdump(msg)) 80 } 81 // Send the transaction 82 if err := sendConn.Write(&Transactions{tx}); err != nil { 83 t.Fatal(err) 84 } 85 // Wait for another transaction announcement 86 switch msg := recvConn.ReadAndServe(s.chain, timeout).(type) { 87 case *Transactions: 88 t.Fatalf("Received unexpected transaction announcement: %v", msg) 89 case *NewPooledTransactionHashes: 90 t.Fatalf("Received unexpected pooledTx announcement: %v", msg) 91 case *Error: 92 // Transaction should not be announced -> wait for timeout 93 return 94 default: 95 t.Fatalf("unexpected message in sendFailingTx: %s", pretty.Sdump(msg)) 96 } 97 } 98 99 func unknownTx(t *utesting.T, s *Suite) *types.Transaction { 100 tx := getNextTxFromChain(t, s) 101 var to common.Address 102 if tx.To() != nil { 103 to = *tx.To() 104 } 105 txNew := types.NewTransaction(tx.Nonce()+1, to, tx.Value(), tx.Gas(), tx.GasPrice(), tx.Data()) 106 return signWithFaucet(t, txNew) 107 } 108 109 func getNextTxFromChain(t *utesting.T, s *Suite) *types.Transaction { 110 // Get a new transaction 111 var tx *types.Transaction 112 for _, blocks := range s.fullChain.blocks[s.chain.Len():] { 113 txs := blocks.Transactions() 114 if txs.Len() != 0 { 115 tx = txs[0] 116 break 117 } 118 } 119 if tx == nil { 120 t.Fatal("could not find transaction") 121 } 122 return tx 123 } 124 125 func getOldTxFromChain(t *utesting.T, s *Suite) *types.Transaction { 126 var tx *types.Transaction 127 for _, blocks := range s.fullChain.blocks[:s.chain.Len()-1] { 128 txs := blocks.Transactions() 129 if txs.Len() != 0 { 130 tx = txs[0] 131 break 132 } 133 } 134 if tx == nil { 135 t.Fatal("could not find transaction") 136 } 137 return tx 138 } 139 140 func invalidNonceTx(t *utesting.T, s *Suite) *types.Transaction { 141 tx := getNextTxFromChain(t, s) 142 var to common.Address 143 if tx.To() != nil { 144 to = *tx.To() 145 } 146 txNew := types.NewTransaction(tx.Nonce()-2, to, tx.Value(), tx.Gas(), tx.GasPrice(), tx.Data()) 147 return signWithFaucet(t, txNew) 148 } 149 150 func hugeAmount(t *utesting.T, s *Suite) *types.Transaction { 151 tx := getNextTxFromChain(t, s) 152 amount := largeNumber(2) 153 var to common.Address 154 if tx.To() != nil { 155 to = *tx.To() 156 } 157 txNew := types.NewTransaction(tx.Nonce(), to, amount, tx.Gas(), tx.GasPrice(), tx.Data()) 158 return signWithFaucet(t, txNew) 159 } 160 161 func hugeGasPrice(t *utesting.T, s *Suite) *types.Transaction { 162 tx := getNextTxFromChain(t, s) 163 gasPrice := largeNumber(2) 164 var to common.Address 165 if tx.To() != nil { 166 to = *tx.To() 167 } 168 txNew := types.NewTransaction(tx.Nonce(), to, tx.Value(), tx.Gas(), gasPrice, tx.Data()) 169 return signWithFaucet(t, txNew) 170 } 171 172 func hugeData(t *utesting.T, s *Suite) *types.Transaction { 173 tx := getNextTxFromChain(t, s) 174 var to common.Address 175 if tx.To() != nil { 176 to = *tx.To() 177 } 178 txNew := types.NewTransaction(tx.Nonce(), to, tx.Value(), tx.Gas(), tx.GasPrice(), largeBuffer(2)) 179 return signWithFaucet(t, txNew) 180 } 181 182 func signWithFaucet(t *utesting.T, tx *types.Transaction) *types.Transaction { 183 signer := types.HomesteadSigner{} 184 signedTx, err := types.SignTx(tx, signer, faucetKey) 185 if err != nil { 186 t.Fatalf("could not sign tx: %v\n", err) 187 } 188 return signedTx 189 }