github.com/theQRL/go-zond@v0.2.1/cmd/devp2p/internal/zondtest/transaction.go (about) 1 // Copyright 2020 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU 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 // go-ethereum 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 General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 package zondtest 18 19 // TODO(now.youtrack.cloud/issue/TGZ-6) 20 /* 21 import ( 22 "errors" 23 "fmt" 24 "math/big" 25 "strings" 26 "time" 27 28 "github.com/theQRL/go-zond/common" 29 "github.com/theQRL/go-zond/core/types" 30 "github.com/theQRL/go-zond/crypto/pqcrypto" 31 "github.com/theQRL/go-zond/internal/utesting" 32 "github.com/theQRL/go-zond/params" 33 ) 34 35 // var faucetAddr, _ = common.NewAddressFromString("Z71562b71999873DB5b286dF957af199Ec94617F7") 36 var faucetKey, _ = pqcrypto.HexToDilithium("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 37 38 func (s *Suite) sendSuccessfulTxs(t *utesting.T) error { 39 tests := []*types.Transaction{ 40 getNextTxFromChain(s), 41 unknownTx(s), 42 } 43 for i, tx := range tests { 44 if tx == nil { 45 return errors.New("could not find tx to send") 46 } 47 t.Logf("Testing tx propagation %d: sending tx %v %v %v\n", i, tx.Hash().String(), tx.GasPrice(), tx.Gas()) 48 // get previous tx if exists for reference in case of old tx propagation 49 var prevTx *types.Transaction 50 if i != 0 { 51 prevTx = tests[i-1] 52 } 53 // write tx to connection 54 if err := sendSuccessfulTx(s, tx, prevTx); err != nil { 55 return fmt.Errorf("send successful tx test failed: %v", err) 56 } 57 } 58 return nil 59 } 60 61 func sendSuccessfulTx(s *Suite, tx *types.Transaction, prevTx *types.Transaction) error { 62 sendConn, recvConn, err := s.createSendAndRecvConns() 63 if err != nil { 64 return err 65 } 66 defer sendConn.Close() 67 defer recvConn.Close() 68 if err = sendConn.peer(s.chain, nil); err != nil { 69 return fmt.Errorf("peering failed: %v", err) 70 } 71 // Send the transaction 72 if err = sendConn.Write(&Transactions{tx}); err != nil { 73 return fmt.Errorf("failed to write to connection: %v", err) 74 } 75 // peer receiving connection to node 76 if err = recvConn.peer(s.chain, nil); err != nil { 77 return fmt.Errorf("peering failed: %v", err) 78 } 79 80 // update last nonce seen 81 nonce = tx.Nonce() 82 83 // Wait for the transaction announcement 84 for { 85 switch msg := recvConn.readAndServe(s.chain, timeout).(type) { 86 case *Transactions: 87 recTxs := *msg 88 // if you receive an old tx propagation, read from connection again 89 if len(recTxs) == 1 && prevTx != nil { 90 if recTxs[0] == prevTx { 91 continue 92 } 93 } 94 for _, gotTx := range recTxs { 95 if gotTx.Hash() == tx.Hash() { 96 // Ok 97 return nil 98 } 99 } 100 return fmt.Errorf("missing transaction: got %v missing %v", recTxs, tx.Hash()) 101 case *NewPooledTransactionHashes66: 102 txHashes := *msg 103 // if you receive an old tx propagation, read from connection again 104 if len(txHashes) == 1 && prevTx != nil { 105 if txHashes[0] == prevTx.Hash() { 106 continue 107 } 108 } 109 for _, gotHash := range txHashes { 110 if gotHash == tx.Hash() { 111 // Ok 112 return nil 113 } 114 } 115 return fmt.Errorf("missing transaction announcement: got %v missing %v", txHashes, tx.Hash()) 116 case *NewPooledTransactionHashes: 117 txHashes := msg.Hashes 118 if len(txHashes) != len(msg.Sizes) { 119 return fmt.Errorf("invalid msg size lengths: hashes: %v sizes: %v", len(txHashes), len(msg.Sizes)) 120 } 121 if len(txHashes) != len(msg.Types) { 122 return fmt.Errorf("invalid msg type lengths: hashes: %v types: %v", len(txHashes), len(msg.Types)) 123 } 124 // if you receive an old tx propagation, read from connection again 125 if len(txHashes) == 1 && prevTx != nil { 126 if txHashes[0] == prevTx.Hash() { 127 continue 128 } 129 } 130 for index, gotHash := range txHashes { 131 if gotHash == tx.Hash() { 132 if msg.Sizes[index] != uint32(tx.Size()) { 133 return fmt.Errorf("invalid tx size: got %v want %v", msg.Sizes[index], tx.Size()) 134 } 135 if msg.Types[index] != tx.Type() { 136 return fmt.Errorf("invalid tx type: got %v want %v", msg.Types[index], tx.Type()) 137 } 138 // Ok 139 return nil 140 } 141 } 142 return fmt.Errorf("missing transaction announcement: got %v missing %v", txHashes, tx.Hash()) 143 144 default: 145 return fmt.Errorf("unexpected message in sendSuccessfulTx: %s", pretty.Sdump(msg)) 146 } 147 } 148 } 149 150 func (s *Suite) sendMaliciousTxs(t *utesting.T) error { 151 badTxs := []*types.Transaction{ 152 getOldTxFromChain(s), 153 invalidNonceTx(s), 154 hugeAmount(s), 155 hugeGasPrice(s), 156 hugeData(s), 157 } 158 159 // setup receiving connection before sending malicious txs 160 recvConn, err := s.dial() 161 if err != nil { 162 return fmt.Errorf("dial failed: %v", err) 163 } 164 defer recvConn.Close() 165 if err = recvConn.peer(s.chain, nil); err != nil { 166 return fmt.Errorf("peering failed: %v", err) 167 } 168 169 for i, tx := range badTxs { 170 t.Logf("Testing malicious tx propagation: %v\n", i) 171 if err = sendMaliciousTx(s, tx); err != nil { 172 return fmt.Errorf("malicious tx test failed:\ntx: %v\nerror: %v", tx, err) 173 } 174 } 175 // check to make sure bad txs aren't propagated 176 return checkMaliciousTxPropagation(s, badTxs, recvConn) 177 } 178 179 func sendMaliciousTx(s *Suite, tx *types.Transaction) error { 180 conn, err := s.dial() 181 if err != nil { 182 return fmt.Errorf("dial failed: %v", err) 183 } 184 defer conn.Close() 185 if err = conn.peer(s.chain, nil); err != nil { 186 return fmt.Errorf("peering failed: %v", err) 187 } 188 189 // write malicious tx 190 if err = conn.Write(&Transactions{tx}); err != nil { 191 return fmt.Errorf("failed to write to connection: %v", err) 192 } 193 return nil 194 } 195 196 var nonce = uint64(99) 197 198 // sendMultipleSuccessfulTxs sends the given transactions to the node and 199 // expects the node to accept and propagate them. 200 func sendMultipleSuccessfulTxs(t *utesting.T, s *Suite, txs []*types.Transaction) error { 201 txMsg := Transactions(txs) 202 t.Logf("sending %d txs\n", len(txs)) 203 204 sendConn, recvConn, err := s.createSendAndRecvConns() 205 if err != nil { 206 return err 207 } 208 defer sendConn.Close() 209 defer recvConn.Close() 210 if err = sendConn.peer(s.chain, nil); err != nil { 211 return fmt.Errorf("peering failed: %v", err) 212 } 213 if err = recvConn.peer(s.chain, nil); err != nil { 214 return fmt.Errorf("peering failed: %v", err) 215 } 216 217 // Send the transactions 218 if err = sendConn.Write(&txMsg); err != nil { 219 return fmt.Errorf("failed to write message to connection: %v", err) 220 } 221 222 // update nonce 223 nonce = txs[len(txs)-1].Nonce() 224 225 // Wait for the transaction announcement(s) and make sure all sent txs are being propagated. 226 // all txs should be announced within a couple announcements. 227 recvHashes := make([]common.Hash, 0) 228 229 for i := 0; i < 20; i++ { 230 switch msg := recvConn.readAndServe(s.chain, timeout).(type) { 231 case *Transactions: 232 for _, tx := range *msg { 233 recvHashes = append(recvHashes, tx.Hash()) 234 } 235 case *NewPooledTransactionHashes66: 236 recvHashes = append(recvHashes, *msg...) 237 case *NewPooledTransactionHashes: 238 recvHashes = append(recvHashes, msg.Hashes...) 239 default: 240 if !strings.Contains(pretty.Sdump(msg), "i/o timeout") { 241 return fmt.Errorf("unexpected message while waiting to receive txs: %s", pretty.Sdump(msg)) 242 } 243 } 244 // break once all 2000 txs have been received 245 if len(recvHashes) == 2000 { 246 break 247 } 248 if len(recvHashes) > 0 { 249 _, missingTxs := compareReceivedTxs(recvHashes, txs) 250 if len(missingTxs) > 0 { 251 continue 252 } else { 253 t.Logf("successfully received all %d txs", len(txs)) 254 return nil 255 } 256 } 257 } 258 _, missingTxs := compareReceivedTxs(recvHashes, txs) 259 if len(missingTxs) > 0 { 260 for _, missing := range missingTxs { 261 t.Logf("missing tx: %v", missing.Hash()) 262 } 263 return fmt.Errorf("missing %d txs", len(missingTxs)) 264 } 265 return nil 266 } 267 268 // checkMaliciousTxPropagation checks whether the given malicious transactions were 269 // propagated by the node. 270 func checkMaliciousTxPropagation(s *Suite, txs []*types.Transaction, conn *Conn) error { 271 switch msg := conn.readAndServe(s.chain, time.Second*8).(type) { 272 case *Transactions: 273 // check to see if any of the failing txs were in the announcement 274 recvTxs := make([]common.Hash, len(*msg)) 275 for i, recvTx := range *msg { 276 recvTxs[i] = recvTx.Hash() 277 } 278 badTxs, _ := compareReceivedTxs(recvTxs, txs) 279 if len(badTxs) > 0 { 280 return fmt.Errorf("received %d bad txs: \n%v", len(badTxs), badTxs) 281 } 282 case *NewPooledTransactionHashes66: 283 badTxs, _ := compareReceivedTxs(*msg, txs) 284 if len(badTxs) > 0 { 285 return fmt.Errorf("received %d bad txs: \n%v", len(badTxs), badTxs) 286 } 287 case *NewPooledTransactionHashes: 288 badTxs, _ := compareReceivedTxs(msg.Hashes, txs) 289 if len(badTxs) > 0 { 290 return fmt.Errorf("received %d bad txs: \n%v", len(badTxs), badTxs) 291 } 292 case *Error: 293 // Transaction should not be announced -> wait for timeout 294 return nil 295 default: 296 return fmt.Errorf("unexpected message in sendFailingTx: %s", pretty.Sdump(msg)) 297 } 298 return nil 299 } 300 301 // compareReceivedTxs compares the received set of txs against the given set of txs, 302 // returning both the set received txs that were present within the given txs, and 303 // the set of txs that were missing from the set of received txs 304 func compareReceivedTxs(recvTxs []common.Hash, txs []*types.Transaction) (present []*types.Transaction, missing []*types.Transaction) { 305 // create a map of the hashes received from node 306 recvHashes := make(map[common.Hash]common.Hash) 307 for _, hash := range recvTxs { 308 recvHashes[hash] = hash 309 } 310 311 // collect present txs and missing txs separately 312 present = make([]*types.Transaction, 0) 313 missing = make([]*types.Transaction, 0) 314 for _, tx := range txs { 315 if _, exists := recvHashes[tx.Hash()]; exists { 316 present = append(present, tx) 317 } else { 318 missing = append(missing, tx) 319 } 320 } 321 return present, missing 322 } 323 324 func unknownTx(s *Suite) *types.Transaction { 325 tx := getNextTxFromChain(s) 326 if tx == nil { 327 return nil 328 } 329 var to common.Address 330 if tx.To() != nil { 331 to = *tx.To() 332 } 333 txNew := types.NewTx(&types.DynamicFeeTx{ 334 Nonce: tx.Nonce() + 1, 335 To: &to, 336 Value: tx.Value(), 337 Gas: tx.Gas(), 338 GasFeeCap: tx.GasPrice(), 339 Data: tx.Data(), 340 }) 341 return signWithFaucet(s.chain.chainConfig, txNew) 342 } 343 344 func getNextTxFromChain(s *Suite) *types.Transaction { 345 // Get a new transaction 346 for _, blocks := range s.fullChain.blocks[s.chain.Len():] { 347 txs := blocks.Transactions() 348 if txs.Len() != 0 { 349 return txs[0] 350 } 351 } 352 return nil 353 } 354 355 func generateTxs(s *Suite, numTxs int) (map[common.Hash]common.Hash, []*types.Transaction, error) { 356 txHashMap := make(map[common.Hash]common.Hash, numTxs) 357 txs := make([]*types.Transaction, numTxs) 358 359 nextTx := getNextTxFromChain(s) 360 if nextTx == nil { 361 return nil, nil, errors.New("failed to get the next transaction") 362 } 363 gas := nextTx.Gas() 364 365 nonce = nonce + 1 366 // generate txs 367 for i := 0; i < numTxs; i++ { 368 tx := generateTx(s.chain.chainConfig, nonce, gas) 369 if tx == nil { 370 return nil, nil, errors.New("failed to get the next transaction") 371 } 372 txHashMap[tx.Hash()] = tx.Hash() 373 txs[i] = tx 374 nonce = nonce + 1 375 } 376 return txHashMap, txs, nil 377 } 378 379 func generateTx(chainConfig *params.ChainConfig, nonce uint64, gas uint64) *types.Transaction { 380 var to common.Address 381 tx := types.NewTx(&types.DynamicFeeTx{ 382 Nonce: nonce, 383 To: &to, 384 Value: big.NewInt(1), 385 Gas: gas, 386 GasFeeCap: big.NewInt(1), 387 Data: []byte{}, 388 }) 389 return signWithFaucet(chainConfig, tx) 390 } 391 392 func getOldTxFromChain(s *Suite) *types.Transaction { 393 for _, blocks := range s.fullChain.blocks[:s.chain.Len()-1] { 394 txs := blocks.Transactions() 395 if txs.Len() != 0 { 396 return txs[0] 397 } 398 } 399 return nil 400 } 401 402 func invalidNonceTx(s *Suite) *types.Transaction { 403 tx := getNextTxFromChain(s) 404 if tx == nil { 405 return nil 406 } 407 var to common.Address 408 if tx.To() != nil { 409 to = *tx.To() 410 } 411 txNew := types.NewTx(&types.DynamicFeeTx{ 412 Nonce: tx.Nonce() - 2, 413 To: &to, 414 Value: tx.Value(), 415 Gas: tx.Gas(), 416 GasFeeCap: tx.GasPrice(), 417 Data: tx.Data(), 418 }) 419 return signWithFaucet(s.chain.chainConfig, txNew) 420 } 421 422 func hugeAmount(s *Suite) *types.Transaction { 423 tx := getNextTxFromChain(s) 424 if tx == nil { 425 return nil 426 } 427 amount := largeNumber(2) 428 var to common.Address 429 if tx.To() != nil { 430 to = *tx.To() 431 } 432 txNew := types.NewTx(&types.DynamicFeeTx{ 433 Nonce: tx.Nonce(), 434 To: &to, 435 Value: amount, 436 Gas: tx.Gas(), 437 GasFeeCap: tx.GasPrice(), 438 Data: tx.Data(), 439 }) 440 return signWithFaucet(s.chain.chainConfig, txNew) 441 } 442 443 func hugeGasPrice(s *Suite) *types.Transaction { 444 tx := getNextTxFromChain(s) 445 if tx == nil { 446 return nil 447 } 448 gasPrice := largeNumber(2) 449 var to common.Address 450 if tx.To() != nil { 451 to = *tx.To() 452 } 453 txNew := types.NewTx(&types.DynamicFeeTx{ 454 Nonce: tx.Nonce(), 455 To: &to, 456 Value: tx.Value(), 457 Gas: tx.Gas(), 458 GasFeeCap: gasPrice, 459 Data: tx.Data(), 460 }) 461 return signWithFaucet(s.chain.chainConfig, txNew) 462 } 463 464 func hugeData(s *Suite) *types.Transaction { 465 tx := getNextTxFromChain(s) 466 if tx == nil { 467 return nil 468 } 469 var to common.Address 470 if tx.To() != nil { 471 to = *tx.To() 472 } 473 txNew := types.NewTx(&types.DynamicFeeTx{ 474 Nonce: tx.Nonce(), 475 To: &to, 476 Value: tx.Value(), 477 Gas: tx.Gas(), 478 GasFeeCap: tx.GasPrice(), 479 Data: largeBuffer(2), 480 }) 481 return signWithFaucet(s.chain.chainConfig, txNew) 482 } 483 484 func signWithFaucet(chainConfig *params.ChainConfig, tx *types.Transaction) *types.Transaction { 485 signer := types.LatestSigner(chainConfig) 486 signedTx, err := types.SignTx(tx, signer, faucetKey) 487 if err != nil { 488 return nil 489 } 490 return signedTx 491 } 492 */