github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/protocol/txpool_test.go (about) 1 package protocol 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/davecgh/go-spew/spew" 8 9 "github.com/bytom/bytom/consensus" 10 "github.com/bytom/bytom/database/storage" 11 "github.com/bytom/bytom/event" 12 "github.com/bytom/bytom/protocol/bc" 13 "github.com/bytom/bytom/protocol/bc/types" 14 "github.com/bytom/bytom/protocol/state" 15 "github.com/bytom/bytom/testutil" 16 ) 17 18 var testTxs = []*types.Tx{ 19 //tx0 20 types.NewTx(types.TxData{ 21 SerializedSize: 100, 22 Inputs: []*types.TxInput{ 23 types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, 1, 1, []byte{0x51}), 24 }, 25 Outputs: []*types.TxOutput{ 26 types.NewTxOutput(*consensus.BTMAssetID, 1, []byte{0x6a}), 27 }, 28 }), 29 //tx1 30 types.NewTx(types.TxData{ 31 SerializedSize: 100, 32 Inputs: []*types.TxInput{ 33 types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, 1, 1, []byte{0x51}), 34 }, 35 Outputs: []*types.TxOutput{ 36 types.NewTxOutput(*consensus.BTMAssetID, 1, []byte{0x6b}), 37 }, 38 }), 39 //tx2 40 types.NewTx(types.TxData{ 41 SerializedSize: 150, 42 TimeRange: 0, 43 Inputs: []*types.TxInput{ 44 types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, 1, 1, []byte{0x51}), 45 types.NewSpendInput(nil, bc.NewHash([32]byte{0x02}), bc.NewAssetID([32]byte{0xa1}), 4, 1, []byte{0x51}), 46 }, 47 Outputs: []*types.TxOutput{ 48 types.NewTxOutput(*consensus.BTMAssetID, 1, []byte{0x6b}), 49 types.NewTxOutput(bc.NewAssetID([32]byte{0xa1}), 4, []byte{0x61}), 50 }, 51 }), 52 //tx3 53 types.NewTx(types.TxData{ 54 SerializedSize: 100, 55 Inputs: []*types.TxInput{ 56 types.NewSpendInput(nil, testutil.MustDecodeHash("dbea684b5c5153ed7729669a53d6c59574f26015a3e1eb2a0e8a1c645425a764"), bc.NewAssetID([32]byte{0xa1}), 4, 1, []byte{0x61}), 57 }, 58 Outputs: []*types.TxOutput{ 59 types.NewTxOutput(bc.NewAssetID([32]byte{0xa1}), 3, []byte{0x62}), 60 types.NewTxOutput(bc.NewAssetID([32]byte{0xa1}), 1, []byte{0x63}), 61 }, 62 }), 63 //tx4 64 types.NewTx(types.TxData{ 65 SerializedSize: 100, 66 Inputs: []*types.TxInput{ 67 types.NewSpendInput(nil, testutil.MustDecodeHash("d84d0be0fd08e7341f2d127749bb0d0844d4560f53bd54861cee9981fd922cad"), bc.NewAssetID([32]byte{0xa1}), 3, 0, []byte{0x62}), 68 }, 69 Outputs: []*types.TxOutput{ 70 types.NewTxOutput(bc.NewAssetID([32]byte{0xa1}), 2, []byte{0x64}), 71 types.NewTxOutput(bc.NewAssetID([32]byte{0xa1}), 1, []byte{0x65}), 72 }, 73 }), 74 //tx5 75 types.NewTx(types.TxData{ 76 SerializedSize: 100, 77 Inputs: []*types.TxInput{ 78 types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, 1, 1, []byte{0x51}), 79 }, 80 Outputs: []*types.TxOutput{ 81 types.NewTxOutput(*consensus.BTMAssetID, 0, []byte{0x51}), 82 }, 83 }), 84 //tx6 85 types.NewTx(types.TxData{ 86 SerializedSize: 100, 87 Inputs: []*types.TxInput{ 88 types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, 3, 1, []byte{0x51}), 89 types.NewSpendInput(nil, testutil.MustDecodeHash("d84d0be0fd08e7341f2d127749bb0d0844d4560f53bd54861cee9981fd922cad"), bc.NewAssetID([32]byte{0xa1}), 3, 0, []byte{0x62}), 90 }, 91 Outputs: []*types.TxOutput{ 92 types.NewTxOutput(*consensus.BTMAssetID, 2, []byte{0x51}), 93 types.NewTxOutput(bc.NewAssetID([32]byte{0xa1}), 0, []byte{0x65}), 94 }, 95 }), 96 } 97 98 type mockStore struct{} 99 100 func (s *mockStore) BlockExist(hash *bc.Hash) bool { return false } 101 func (s *mockStore) GetBlock(*bc.Hash) (*types.Block, error) { return nil, nil } 102 func (s *mockStore) GetStoreStatus() *BlockStoreState { return nil } 103 func (s *mockStore) GetTransactionStatus(*bc.Hash) (*bc.TransactionStatus, error) { return nil, nil } 104 func (s *mockStore) GetTransactionsUtxo(*state.UtxoViewpoint, []*bc.Tx) error { return nil } 105 func (s *mockStore) GetUtxo(*bc.Hash) (*storage.UtxoEntry, error) { return nil, nil } 106 func (s *mockStore) LoadBlockIndex(uint64) (*state.BlockIndex, error) { return nil, nil } 107 func (s *mockStore) SaveBlock(*types.Block, *bc.TransactionStatus) error { return nil } 108 func (s *mockStore) SaveChainStatus(*state.BlockNode, *state.UtxoViewpoint) error { return nil } 109 110 func TestAddOrphan(t *testing.T) { 111 cases := []struct { 112 before *TxPool 113 after *TxPool 114 addOrphan *TxDesc 115 requireParents []*bc.Hash 116 }{ 117 { 118 before: &TxPool{ 119 orphans: map[bc.Hash]*orphanTx{}, 120 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{}, 121 }, 122 after: &TxPool{ 123 orphans: map[bc.Hash]*orphanTx{ 124 testTxs[0].ID: { 125 TxDesc: &TxDesc{ 126 Tx: testTxs[0], 127 }, 128 }, 129 }, 130 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{ 131 testTxs[0].SpentOutputIDs[0]: { 132 testTxs[0].ID: { 133 TxDesc: &TxDesc{ 134 Tx: testTxs[0], 135 }, 136 }, 137 }, 138 }, 139 }, 140 addOrphan: &TxDesc{Tx: testTxs[0]}, 141 requireParents: []*bc.Hash{&testTxs[0].SpentOutputIDs[0]}, 142 }, 143 { 144 before: &TxPool{ 145 orphans: map[bc.Hash]*orphanTx{ 146 testTxs[0].ID: { 147 TxDesc: &TxDesc{ 148 Tx: testTxs[0], 149 }, 150 }, 151 }, 152 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{ 153 testTxs[0].SpentOutputIDs[0]: { 154 testTxs[0].ID: { 155 TxDesc: &TxDesc{ 156 Tx: testTxs[0], 157 }, 158 }, 159 }, 160 }, 161 }, 162 after: &TxPool{ 163 orphans: map[bc.Hash]*orphanTx{ 164 testTxs[0].ID: { 165 TxDesc: &TxDesc{ 166 Tx: testTxs[0], 167 }, 168 }, 169 testTxs[1].ID: { 170 TxDesc: &TxDesc{ 171 Tx: testTxs[1], 172 }, 173 }, 174 }, 175 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{ 176 testTxs[0].SpentOutputIDs[0]: { 177 testTxs[0].ID: { 178 TxDesc: &TxDesc{ 179 Tx: testTxs[0], 180 }, 181 }, 182 testTxs[1].ID: { 183 TxDesc: &TxDesc{ 184 Tx: testTxs[1], 185 }, 186 }, 187 }, 188 }, 189 }, 190 addOrphan: &TxDesc{Tx: testTxs[1]}, 191 requireParents: []*bc.Hash{&testTxs[1].SpentOutputIDs[0]}, 192 }, 193 { 194 before: &TxPool{ 195 orphans: map[bc.Hash]*orphanTx{}, 196 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{}, 197 }, 198 after: &TxPool{ 199 orphans: map[bc.Hash]*orphanTx{ 200 testTxs[2].ID: { 201 TxDesc: &TxDesc{ 202 Tx: testTxs[2], 203 }, 204 }, 205 }, 206 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{ 207 testTxs[2].SpentOutputIDs[1]: { 208 testTxs[2].ID: { 209 TxDesc: &TxDesc{ 210 Tx: testTxs[2], 211 }, 212 }, 213 }, 214 }, 215 }, 216 addOrphan: &TxDesc{Tx: testTxs[2]}, 217 requireParents: []*bc.Hash{&testTxs[2].SpentOutputIDs[1]}, 218 }, 219 } 220 221 for i, c := range cases { 222 c.before.addOrphan(c.addOrphan, c.requireParents) 223 for _, orphan := range c.before.orphans { 224 orphan.expiration = time.Time{} 225 } 226 for _, orphans := range c.before.orphansByPrev { 227 for _, orphan := range orphans { 228 orphan.expiration = time.Time{} 229 } 230 } 231 if !testutil.DeepEqual(c.before, c.after) { 232 t.Errorf("case %d: got %v want %v", i, c.before, c.after) 233 } 234 } 235 } 236 237 func TestAddTransaction(t *testing.T) { 238 dispatcher := event.NewDispatcher() 239 cases := []struct { 240 before *TxPool 241 after *TxPool 242 addTx *TxDesc 243 }{ 244 { 245 before: &TxPool{ 246 pool: map[bc.Hash]*TxDesc{}, 247 utxo: map[bc.Hash]*types.Tx{}, 248 eventDispatcher: dispatcher, 249 }, 250 after: &TxPool{ 251 pool: map[bc.Hash]*TxDesc{ 252 testTxs[2].ID: { 253 Tx: testTxs[2], 254 StatusFail: false, 255 }, 256 }, 257 utxo: map[bc.Hash]*types.Tx{ 258 *testTxs[2].ResultIds[0]: testTxs[2], 259 *testTxs[2].ResultIds[1]: testTxs[2], 260 }, 261 }, 262 addTx: &TxDesc{ 263 Tx: testTxs[2], 264 StatusFail: false, 265 }, 266 }, 267 { 268 before: &TxPool{ 269 pool: map[bc.Hash]*TxDesc{}, 270 utxo: map[bc.Hash]*types.Tx{}, 271 eventDispatcher: dispatcher, 272 }, 273 after: &TxPool{ 274 pool: map[bc.Hash]*TxDesc{ 275 testTxs[2].ID: { 276 Tx: testTxs[2], 277 StatusFail: true, 278 }, 279 }, 280 utxo: map[bc.Hash]*types.Tx{ 281 *testTxs[2].ResultIds[0]: testTxs[2], 282 }, 283 }, 284 addTx: &TxDesc{ 285 Tx: testTxs[2], 286 StatusFail: true, 287 }, 288 }, 289 } 290 291 for i, c := range cases { 292 c.before.addTransaction(c.addTx) 293 for _, txD := range c.before.pool { 294 txD.Added = time.Time{} 295 } 296 if !testutil.DeepEqual(c.before.pool, c.after.pool) { 297 t.Errorf("case %d: got %v want %v", i, c.before.pool, c.after.pool) 298 } 299 if !testutil.DeepEqual(c.before.utxo, c.after.utxo) { 300 t.Errorf("case %d: got %v want %v", i, c.before.utxo, c.after.utxo) 301 } 302 } 303 } 304 305 func TestExpireOrphan(t *testing.T) { 306 before := &TxPool{ 307 orphans: map[bc.Hash]*orphanTx{ 308 testTxs[0].ID: { 309 expiration: time.Unix(1533489701, 0), 310 TxDesc: &TxDesc{ 311 Tx: testTxs[0], 312 }, 313 }, 314 testTxs[1].ID: { 315 expiration: time.Unix(1633489701, 0), 316 TxDesc: &TxDesc{ 317 Tx: testTxs[1], 318 }, 319 }, 320 }, 321 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{ 322 testTxs[0].SpentOutputIDs[0]: { 323 testTxs[0].ID: { 324 expiration: time.Unix(1533489701, 0), 325 TxDesc: &TxDesc{ 326 Tx: testTxs[0], 327 }, 328 }, 329 testTxs[1].ID: { 330 expiration: time.Unix(1633489701, 0), 331 TxDesc: &TxDesc{ 332 Tx: testTxs[1], 333 }, 334 }, 335 }, 336 }, 337 } 338 339 want := &TxPool{ 340 orphans: map[bc.Hash]*orphanTx{ 341 testTxs[1].ID: { 342 expiration: time.Unix(1633489701, 0), 343 TxDesc: &TxDesc{ 344 Tx: testTxs[1], 345 }, 346 }, 347 }, 348 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{ 349 testTxs[0].SpentOutputIDs[0]: { 350 testTxs[1].ID: { 351 expiration: time.Unix(1633489701, 0), 352 TxDesc: &TxDesc{ 353 Tx: testTxs[1], 354 }, 355 }, 356 }, 357 }, 358 } 359 360 before.ExpireOrphan(time.Unix(1633479701, 0)) 361 if !testutil.DeepEqual(before, want) { 362 t.Errorf("got %v want %v", before, want) 363 } 364 } 365 366 func TestProcessOrphans(t *testing.T) { 367 dispatcher := event.NewDispatcher() 368 cases := []struct { 369 before *TxPool 370 after *TxPool 371 processTx *TxDesc 372 }{ 373 { 374 before: &TxPool{ 375 pool: map[bc.Hash]*TxDesc{}, 376 utxo: map[bc.Hash]*types.Tx{}, 377 eventDispatcher: dispatcher, 378 orphans: map[bc.Hash]*orphanTx{ 379 testTxs[3].ID: { 380 TxDesc: &TxDesc{ 381 Tx: testTxs[3], 382 }, 383 }, 384 }, 385 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{ 386 testTxs[3].SpentOutputIDs[0]: { 387 testTxs[3].ID: { 388 TxDesc: &TxDesc{ 389 Tx: testTxs[3], 390 }, 391 }, 392 }, 393 }, 394 }, 395 after: &TxPool{ 396 pool: map[bc.Hash]*TxDesc{ 397 testTxs[3].ID: { 398 Tx: testTxs[3], 399 StatusFail: false, 400 }, 401 }, 402 utxo: map[bc.Hash]*types.Tx{ 403 *testTxs[3].ResultIds[0]: testTxs[3], 404 *testTxs[3].ResultIds[1]: testTxs[3], 405 }, 406 eventDispatcher: dispatcher, 407 orphans: map[bc.Hash]*orphanTx{}, 408 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{}, 409 }, 410 processTx: &TxDesc{Tx: testTxs[2]}, 411 }, 412 { 413 before: &TxPool{ 414 pool: map[bc.Hash]*TxDesc{}, 415 utxo: map[bc.Hash]*types.Tx{}, 416 eventDispatcher: dispatcher, 417 orphans: map[bc.Hash]*orphanTx{ 418 testTxs[3].ID: { 419 TxDesc: &TxDesc{ 420 Tx: testTxs[3], 421 }, 422 }, 423 testTxs[4].ID: { 424 TxDesc: &TxDesc{ 425 Tx: testTxs[4], 426 }, 427 }, 428 }, 429 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{ 430 testTxs[3].SpentOutputIDs[0]: { 431 testTxs[3].ID: { 432 TxDesc: &TxDesc{ 433 Tx: testTxs[3], 434 }, 435 }, 436 }, 437 testTxs[4].SpentOutputIDs[0]: { 438 testTxs[4].ID: { 439 TxDesc: &TxDesc{ 440 Tx: testTxs[4], 441 }, 442 }, 443 }, 444 }, 445 }, 446 after: &TxPool{ 447 pool: map[bc.Hash]*TxDesc{ 448 testTxs[3].ID: { 449 Tx: testTxs[3], 450 StatusFail: false, 451 }, 452 testTxs[4].ID: { 453 Tx: testTxs[4], 454 StatusFail: false, 455 }, 456 }, 457 utxo: map[bc.Hash]*types.Tx{ 458 *testTxs[3].ResultIds[0]: testTxs[3], 459 *testTxs[3].ResultIds[1]: testTxs[3], 460 *testTxs[4].ResultIds[0]: testTxs[4], 461 *testTxs[4].ResultIds[1]: testTxs[4], 462 }, 463 eventDispatcher: dispatcher, 464 orphans: map[bc.Hash]*orphanTx{}, 465 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{}, 466 }, 467 processTx: &TxDesc{Tx: testTxs[2]}, 468 }, 469 } 470 471 for i, c := range cases { 472 c.before.store = &mockStore{} 473 c.before.addTransaction(c.processTx) 474 c.before.processOrphans(c.processTx) 475 c.before.RemoveTransaction(&c.processTx.Tx.ID) 476 c.before.store = nil 477 c.before.lastUpdated = 0 478 for _, txD := range c.before.pool { 479 txD.Added = time.Time{} 480 } 481 482 if !testutil.DeepEqual(c.before, c.after) { 483 t.Errorf("case %d: got %v want %v", i, c.before, c.after) 484 } 485 } 486 } 487 488 func TestRemoveOrphan(t *testing.T) { 489 cases := []struct { 490 before *TxPool 491 after *TxPool 492 removeHashes []*bc.Hash 493 }{ 494 { 495 before: &TxPool{ 496 orphans: map[bc.Hash]*orphanTx{ 497 testTxs[0].ID: { 498 expiration: time.Unix(1533489701, 0), 499 TxDesc: &TxDesc{ 500 Tx: testTxs[0], 501 }, 502 }, 503 }, 504 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{ 505 testTxs[0].SpentOutputIDs[0]: { 506 testTxs[0].ID: { 507 expiration: time.Unix(1533489701, 0), 508 TxDesc: &TxDesc{ 509 Tx: testTxs[0], 510 }, 511 }, 512 }, 513 }, 514 }, 515 after: &TxPool{ 516 orphans: map[bc.Hash]*orphanTx{}, 517 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{}, 518 }, 519 removeHashes: []*bc.Hash{ 520 &testTxs[0].ID, 521 }, 522 }, 523 { 524 before: &TxPool{ 525 orphans: map[bc.Hash]*orphanTx{ 526 testTxs[0].ID: { 527 expiration: time.Unix(1533489701, 0), 528 TxDesc: &TxDesc{ 529 Tx: testTxs[0], 530 }, 531 }, 532 testTxs[1].ID: { 533 expiration: time.Unix(1533489701, 0), 534 TxDesc: &TxDesc{ 535 Tx: testTxs[1], 536 }, 537 }, 538 }, 539 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{ 540 testTxs[0].SpentOutputIDs[0]: { 541 testTxs[0].ID: { 542 expiration: time.Unix(1533489701, 0), 543 TxDesc: &TxDesc{ 544 Tx: testTxs[0], 545 }, 546 }, 547 testTxs[1].ID: { 548 expiration: time.Unix(1533489701, 0), 549 TxDesc: &TxDesc{ 550 Tx: testTxs[1], 551 }, 552 }, 553 }, 554 }, 555 }, 556 after: &TxPool{ 557 orphans: map[bc.Hash]*orphanTx{ 558 testTxs[0].ID: { 559 expiration: time.Unix(1533489701, 0), 560 TxDesc: &TxDesc{ 561 Tx: testTxs[0], 562 }, 563 }, 564 }, 565 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{ 566 testTxs[0].SpentOutputIDs[0]: { 567 testTxs[0].ID: { 568 expiration: time.Unix(1533489701, 0), 569 TxDesc: &TxDesc{ 570 Tx: testTxs[0], 571 }, 572 }, 573 }, 574 }, 575 }, 576 removeHashes: []*bc.Hash{ 577 &testTxs[1].ID, 578 }, 579 }, 580 } 581 582 for i, c := range cases { 583 for _, hash := range c.removeHashes { 584 c.before.removeOrphan(hash) 585 } 586 if !testutil.DeepEqual(c.before, c.after) { 587 t.Errorf("case %d: got %v want %v", i, c.before, c.after) 588 } 589 } 590 } 591 592 type mockStore1 struct{} 593 594 func (s *mockStore1) BlockExist(hash *bc.Hash) bool { return false } 595 func (s *mockStore1) GetBlock(*bc.Hash) (*types.Block, error) { return nil, nil } 596 func (s *mockStore1) GetStoreStatus() *BlockStoreState { return nil } 597 func (s *mockStore1) GetTransactionStatus(*bc.Hash) (*bc.TransactionStatus, error) { return nil, nil } 598 func (s *mockStore1) GetTransactionsUtxo(utxoView *state.UtxoViewpoint, tx []*bc.Tx) error { 599 for _, hash := range testTxs[2].SpentOutputIDs { 600 utxoView.Entries[hash] = &storage.UtxoEntry{IsCoinBase: false, Spent: false} 601 } 602 return nil 603 } 604 func (s *mockStore1) GetUtxo(*bc.Hash) (*storage.UtxoEntry, error) { return nil, nil } 605 func (s *mockStore1) LoadBlockIndex(uint64) (*state.BlockIndex, error) { return nil, nil } 606 func (s *mockStore1) SaveBlock(*types.Block, *bc.TransactionStatus) error { return nil } 607 func (s *mockStore1) SaveChainStatus(*state.BlockNode, *state.UtxoViewpoint) error { return nil } 608 609 func TestProcessTransaction(t *testing.T) { 610 txPool := &TxPool{ 611 pool: make(map[bc.Hash]*TxDesc), 612 utxo: make(map[bc.Hash]*types.Tx), 613 orphans: make(map[bc.Hash]*orphanTx), 614 orphansByPrev: make(map[bc.Hash]map[bc.Hash]*orphanTx), 615 store: &mockStore1{}, 616 eventDispatcher: event.NewDispatcher(), 617 } 618 cases := []struct { 619 want *TxPool 620 addTx *TxDesc 621 }{ 622 //Dust tx 623 { 624 want: &TxPool{}, 625 addTx: &TxDesc{ 626 Tx: testTxs[3], 627 StatusFail: false, 628 }, 629 }, 630 //Dust tx 631 { 632 want: &TxPool{}, 633 addTx: &TxDesc{ 634 Tx: testTxs[4], 635 StatusFail: false, 636 }, 637 }, 638 //Dust tx 639 { 640 want: &TxPool{}, 641 addTx: &TxDesc{ 642 Tx: testTxs[5], 643 StatusFail: false, 644 }, 645 }, 646 //Dust tx 647 { 648 want: &TxPool{}, 649 addTx: &TxDesc{ 650 Tx: testTxs[6], 651 StatusFail: false, 652 }, 653 }, 654 //normal tx 655 { 656 want: &TxPool{ 657 pool: map[bc.Hash]*TxDesc{ 658 testTxs[2].ID: { 659 Tx: testTxs[2], 660 StatusFail: false, 661 Weight: 150, 662 }, 663 }, 664 utxo: map[bc.Hash]*types.Tx{ 665 *testTxs[2].ResultIds[0]: testTxs[2], 666 *testTxs[2].ResultIds[1]: testTxs[2], 667 }, 668 }, 669 addTx: &TxDesc{ 670 Tx: testTxs[2], 671 StatusFail: false, 672 }, 673 }, 674 } 675 676 for i, c := range cases { 677 txPool.ProcessTransaction(c.addTx.Tx, c.addTx.StatusFail, 0, 0) 678 for _, txD := range txPool.pool { 679 txD.Added = time.Time{} 680 } 681 for _, txD := range txPool.orphans { 682 txD.Added = time.Time{} 683 txD.expiration = time.Time{} 684 } 685 686 if !testutil.DeepEqual(txPool.pool, c.want.pool) { 687 t.Errorf("case %d: test ProcessTransaction pool mismatch got %s want %s", i, spew.Sdump(txPool.pool), spew.Sdump(c.want.pool)) 688 } 689 if !testutil.DeepEqual(txPool.utxo, c.want.utxo) { 690 t.Errorf("case %d: test ProcessTransaction utxo mismatch got %s want %s", i, spew.Sdump(txPool.utxo), spew.Sdump(c.want.utxo)) 691 } 692 if !testutil.DeepEqual(txPool.orphans, c.want.orphans) { 693 t.Errorf("case %d: test ProcessTransaction orphans mismatch got %s want %s", i, spew.Sdump(txPool.orphans), spew.Sdump(c.want.orphans)) 694 } 695 if !testutil.DeepEqual(txPool.orphansByPrev, c.want.orphansByPrev) { 696 t.Errorf("case %d: test ProcessTransaction orphansByPrev mismatch got %s want %s", i, spew.Sdump(txPool.orphansByPrev), spew.Sdump(c.want.orphansByPrev)) 697 } 698 } 699 }