gitee.com/liu-zhao234568/cntest@v1.0.0/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 "fmt" 21 "math/big" 22 "strings" 23 "time" 24 25 "gitee.com/liu-zhao234568/cntest/common" 26 "gitee.com/liu-zhao234568/cntest/core/types" 27 "gitee.com/liu-zhao234568/cntest/crypto" 28 "gitee.com/liu-zhao234568/cntest/internal/utesting" 29 "gitee.com/liu-zhao234568/cntest/params" 30 ) 31 32 //var faucetAddr = common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7") 33 var faucetKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 34 35 func (s *Suite) sendSuccessfulTxs(t *utesting.T, isEth66 bool) error { 36 tests := []*types.Transaction{ 37 getNextTxFromChain(s), 38 unknownTx(s), 39 } 40 for i, tx := range tests { 41 if tx == nil { 42 return fmt.Errorf("could not find tx to send") 43 } 44 t.Logf("Testing tx propagation %d: sending tx %v %v %v\n", i, tx.Hash().String(), tx.GasPrice(), tx.Gas()) 45 // get previous tx if exists for reference in case of old tx propagation 46 var prevTx *types.Transaction 47 if i != 0 { 48 prevTx = tests[i-1] 49 } 50 // write tx to connection 51 if err := sendSuccessfulTx(s, tx, prevTx, isEth66); err != nil { 52 return fmt.Errorf("send successful tx test failed: %v", err) 53 } 54 } 55 return nil 56 } 57 58 func sendSuccessfulTx(s *Suite, tx *types.Transaction, prevTx *types.Transaction, isEth66 bool) error { 59 sendConn, recvConn, err := s.createSendAndRecvConns(isEth66) 60 if err != nil { 61 return err 62 } 63 defer sendConn.Close() 64 defer recvConn.Close() 65 if err = sendConn.peer(s.chain, nil); err != nil { 66 return fmt.Errorf("peering failed: %v", err) 67 } 68 // Send the transaction 69 if err = sendConn.Write(&Transactions{tx}); err != nil { 70 return fmt.Errorf("failed to write to connection: %v", err) 71 } 72 // peer receiving connection to node 73 if err = recvConn.peer(s.chain, nil); err != nil { 74 return fmt.Errorf("peering failed: %v", err) 75 } 76 // update last nonce seen 77 nonce = tx.Nonce() 78 // Wait for the transaction announcement 79 for { 80 switch msg := recvConn.readAndServe(s.chain, timeout).(type) { 81 case *Transactions: 82 recTxs := *msg 83 // if you receive an old tx propagation, read from connection again 84 if len(recTxs) == 1 && prevTx != nil { 85 if recTxs[0] == prevTx { 86 continue 87 } 88 } 89 for _, gotTx := range recTxs { 90 if gotTx.Hash() == tx.Hash() { 91 // Ok 92 return nil 93 } 94 } 95 return fmt.Errorf("missing transaction: got %v missing %v", recTxs, tx.Hash()) 96 case *NewPooledTransactionHashes: 97 txHashes := *msg 98 // if you receive an old tx propagation, read from connection again 99 if len(txHashes) == 1 && prevTx != nil { 100 if txHashes[0] == prevTx.Hash() { 101 continue 102 } 103 } 104 for _, gotHash := range txHashes { 105 if gotHash == tx.Hash() { 106 // Ok 107 return nil 108 } 109 } 110 return fmt.Errorf("missing transaction announcement: got %v missing %v", txHashes, tx.Hash()) 111 default: 112 return fmt.Errorf("unexpected message in sendSuccessfulTx: %s", pretty.Sdump(msg)) 113 } 114 } 115 } 116 117 func (s *Suite) sendMaliciousTxs(t *utesting.T, isEth66 bool) error { 118 badTxs := []*types.Transaction{ 119 getOldTxFromChain(s), 120 invalidNonceTx(s), 121 hugeAmount(s), 122 hugeGasPrice(s), 123 hugeData(s), 124 } 125 // setup receiving connection before sending malicious txs 126 var ( 127 recvConn *Conn 128 err error 129 ) 130 if isEth66 { 131 recvConn, err = s.dial66() 132 } else { 133 recvConn, err = s.dial() 134 } 135 if err != nil { 136 return fmt.Errorf("dial failed: %v", err) 137 } 138 defer recvConn.Close() 139 if err = recvConn.peer(s.chain, nil); err != nil { 140 return fmt.Errorf("peering failed: %v", err) 141 } 142 for i, tx := range badTxs { 143 t.Logf("Testing malicious tx propagation: %v\n", i) 144 if err = sendMaliciousTx(s, tx, isEth66); err != nil { 145 return fmt.Errorf("malicious tx test failed:\ntx: %v\nerror: %v", tx, err) 146 } 147 } 148 // check to make sure bad txs aren't propagated 149 return checkMaliciousTxPropagation(s, badTxs, recvConn) 150 } 151 152 func sendMaliciousTx(s *Suite, tx *types.Transaction, isEth66 bool) error { 153 // setup connection 154 var ( 155 conn *Conn 156 err error 157 ) 158 if isEth66 { 159 conn, err = s.dial66() 160 } else { 161 conn, err = s.dial() 162 } 163 if err != nil { 164 return fmt.Errorf("dial failed: %v", err) 165 } 166 defer conn.Close() 167 if err = conn.peer(s.chain, nil); err != nil { 168 return fmt.Errorf("peering failed: %v", err) 169 } 170 // write malicious tx 171 if err = conn.Write(&Transactions{tx}); err != nil { 172 return fmt.Errorf("failed to write to connection: %v", err) 173 } 174 return nil 175 } 176 177 var nonce = uint64(99) 178 179 // sendMultipleSuccessfulTxs sends the given transactions to the node and 180 // expects the node to accept and propagate them. 181 func sendMultipleSuccessfulTxs(t *utesting.T, s *Suite, txs []*types.Transaction) error { 182 txMsg := Transactions(txs) 183 t.Logf("sending %d txs\n", len(txs)) 184 185 sendConn, recvConn, err := s.createSendAndRecvConns(true) 186 if err != nil { 187 return err 188 } 189 defer sendConn.Close() 190 defer recvConn.Close() 191 if err = sendConn.peer(s.chain, nil); err != nil { 192 return fmt.Errorf("peering failed: %v", err) 193 } 194 if err = recvConn.peer(s.chain, nil); err != nil { 195 return fmt.Errorf("peering failed: %v", err) 196 } 197 // Send the transactions 198 if err = sendConn.Write(&txMsg); err != nil { 199 return fmt.Errorf("failed to write message to connection: %v", err) 200 } 201 // update nonce 202 nonce = txs[len(txs)-1].Nonce() 203 // Wait for the transaction announcement(s) and make sure all sent txs are being propagated 204 recvHashes := make([]common.Hash, 0) 205 // all txs should be announced within 3 announcements 206 for i := 0; i < 3; i++ { 207 switch msg := recvConn.readAndServe(s.chain, timeout).(type) { 208 case *Transactions: 209 for _, tx := range *msg { 210 recvHashes = append(recvHashes, tx.Hash()) 211 } 212 case *NewPooledTransactionHashes: 213 recvHashes = append(recvHashes, *msg...) 214 default: 215 if !strings.Contains(pretty.Sdump(msg), "i/o timeout") { 216 return fmt.Errorf("unexpected message while waiting to receive txs: %s", pretty.Sdump(msg)) 217 } 218 } 219 // break once all 2000 txs have been received 220 if len(recvHashes) == 2000 { 221 break 222 } 223 if len(recvHashes) > 0 { 224 _, missingTxs := compareReceivedTxs(recvHashes, txs) 225 if len(missingTxs) > 0 { 226 continue 227 } else { 228 t.Logf("successfully received all %d txs", len(txs)) 229 return nil 230 } 231 } 232 } 233 _, missingTxs := compareReceivedTxs(recvHashes, txs) 234 if len(missingTxs) > 0 { 235 for _, missing := range missingTxs { 236 t.Logf("missing tx: %v", missing.Hash()) 237 } 238 return fmt.Errorf("missing %d txs", len(missingTxs)) 239 } 240 return nil 241 } 242 243 // checkMaliciousTxPropagation checks whether the given malicious transactions were 244 // propagated by the node. 245 func checkMaliciousTxPropagation(s *Suite, txs []*types.Transaction, conn *Conn) error { 246 switch msg := conn.readAndServe(s.chain, time.Second*8).(type) { 247 case *Transactions: 248 // check to see if any of the failing txs were in the announcement 249 recvTxs := make([]common.Hash, len(*msg)) 250 for i, recvTx := range *msg { 251 recvTxs[i] = recvTx.Hash() 252 } 253 badTxs, _ := compareReceivedTxs(recvTxs, txs) 254 if len(badTxs) > 0 { 255 return fmt.Errorf("received %d bad txs: \n%v", len(badTxs), badTxs) 256 } 257 case *NewPooledTransactionHashes: 258 badTxs, _ := compareReceivedTxs(*msg, txs) 259 if len(badTxs) > 0 { 260 return fmt.Errorf("received %d bad txs: \n%v", len(badTxs), badTxs) 261 } 262 case *Error: 263 // Transaction should not be announced -> wait for timeout 264 return nil 265 default: 266 return fmt.Errorf("unexpected message in sendFailingTx: %s", pretty.Sdump(msg)) 267 } 268 return nil 269 } 270 271 // compareReceivedTxs compares the received set of txs against the given set of txs, 272 // returning both the set received txs that were present within the given txs, and 273 // the set of txs that were missing from the set of received txs 274 func compareReceivedTxs(recvTxs []common.Hash, txs []*types.Transaction) (present []*types.Transaction, missing []*types.Transaction) { 275 // create a map of the hashes received from node 276 recvHashes := make(map[common.Hash]common.Hash) 277 for _, hash := range recvTxs { 278 recvHashes[hash] = hash 279 } 280 281 // collect present txs and missing txs separately 282 present = make([]*types.Transaction, 0) 283 missing = make([]*types.Transaction, 0) 284 for _, tx := range txs { 285 if _, exists := recvHashes[tx.Hash()]; exists { 286 present = append(present, tx) 287 } else { 288 missing = append(missing, tx) 289 } 290 } 291 return present, missing 292 } 293 294 func unknownTx(s *Suite) *types.Transaction { 295 tx := getNextTxFromChain(s) 296 if tx == nil { 297 return nil 298 } 299 var to common.Address 300 if tx.To() != nil { 301 to = *tx.To() 302 } 303 txNew := types.NewTransaction(tx.Nonce()+1, to, tx.Value(), tx.Gas(), tx.GasPrice(), tx.Data()) 304 return signWithFaucet(s.chain.chainConfig, txNew) 305 } 306 307 func getNextTxFromChain(s *Suite) *types.Transaction { 308 // Get a new transaction 309 for _, blocks := range s.fullChain.blocks[s.chain.Len():] { 310 txs := blocks.Transactions() 311 if txs.Len() != 0 { 312 return txs[0] 313 } 314 } 315 return nil 316 } 317 318 func generateTxs(s *Suite, numTxs int) (map[common.Hash]common.Hash, []*types.Transaction, error) { 319 txHashMap := make(map[common.Hash]common.Hash, numTxs) 320 txs := make([]*types.Transaction, numTxs) 321 322 nextTx := getNextTxFromChain(s) 323 if nextTx == nil { 324 return nil, nil, fmt.Errorf("failed to get the next transaction") 325 } 326 gas := nextTx.Gas() 327 328 nonce = nonce + 1 329 // generate txs 330 for i := 0; i < numTxs; i++ { 331 tx := generateTx(s.chain.chainConfig, nonce, gas) 332 if tx == nil { 333 return nil, nil, fmt.Errorf("failed to get the next transaction") 334 } 335 txHashMap[tx.Hash()] = tx.Hash() 336 txs[i] = tx 337 nonce = nonce + 1 338 } 339 return txHashMap, txs, nil 340 } 341 342 func generateTx(chainConfig *params.ChainConfig, nonce uint64, gas uint64) *types.Transaction { 343 var to common.Address 344 tx := types.NewTransaction(nonce, to, big.NewInt(1), gas, big.NewInt(1), []byte{}) 345 return signWithFaucet(chainConfig, tx) 346 } 347 348 func getOldTxFromChain(s *Suite) *types.Transaction { 349 for _, blocks := range s.fullChain.blocks[:s.chain.Len()-1] { 350 txs := blocks.Transactions() 351 if txs.Len() != 0 { 352 return txs[0] 353 } 354 } 355 return nil 356 } 357 358 func invalidNonceTx(s *Suite) *types.Transaction { 359 tx := getNextTxFromChain(s) 360 if tx == nil { 361 return nil 362 } 363 var to common.Address 364 if tx.To() != nil { 365 to = *tx.To() 366 } 367 txNew := types.NewTransaction(tx.Nonce()-2, to, tx.Value(), tx.Gas(), tx.GasPrice(), tx.Data()) 368 return signWithFaucet(s.chain.chainConfig, txNew) 369 } 370 371 func hugeAmount(s *Suite) *types.Transaction { 372 tx := getNextTxFromChain(s) 373 if tx == nil { 374 return nil 375 } 376 amount := largeNumber(2) 377 var to common.Address 378 if tx.To() != nil { 379 to = *tx.To() 380 } 381 txNew := types.NewTransaction(tx.Nonce(), to, amount, tx.Gas(), tx.GasPrice(), tx.Data()) 382 return signWithFaucet(s.chain.chainConfig, txNew) 383 } 384 385 func hugeGasPrice(s *Suite) *types.Transaction { 386 tx := getNextTxFromChain(s) 387 if tx == nil { 388 return nil 389 } 390 gasPrice := largeNumber(2) 391 var to common.Address 392 if tx.To() != nil { 393 to = *tx.To() 394 } 395 txNew := types.NewTransaction(tx.Nonce(), to, tx.Value(), tx.Gas(), gasPrice, tx.Data()) 396 return signWithFaucet(s.chain.chainConfig, txNew) 397 } 398 399 func hugeData(s *Suite) *types.Transaction { 400 tx := getNextTxFromChain(s) 401 if tx == nil { 402 return nil 403 } 404 var to common.Address 405 if tx.To() != nil { 406 to = *tx.To() 407 } 408 txNew := types.NewTransaction(tx.Nonce(), to, tx.Value(), tx.Gas(), tx.GasPrice(), largeBuffer(2)) 409 return signWithFaucet(s.chain.chainConfig, txNew) 410 } 411 412 func signWithFaucet(chainConfig *params.ChainConfig, tx *types.Transaction) *types.Transaction { 413 signer := types.LatestSigner(chainConfig) 414 signedTx, err := types.SignTx(tx, signer, faucetKey) 415 if err != nil { 416 return nil 417 } 418 return signedTx 419 }