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