@@ -420,73 +420,62 @@ BOOST_FIXTURE_TEST_CASE(calc_feerate_diagram_rbf, TestChain100Setup)
420
420
const auto entry_low = pool.GetIter (low_tx->GetHash ()).value ();
421
421
const auto low_size = entry_low->GetTxSize ();
422
422
423
- std::vector<FeeFrac> old_diagram, new_diagram;
424
-
425
423
// Replacement of size 1
426
- const auto replace_one{pool.CalculateFeerateDiagramsForRBF (/* replacement_fees=*/ 0 , /* replacement_vsize=*/ 1 , {entry_low}, {entry_low})};
427
- BOOST_CHECK (replace_one.has_value ());
428
- old_diagram = replace_one->first ;
429
- new_diagram = replace_one->second ;
430
- BOOST_CHECK (old_diagram.size () == 2 );
431
- BOOST_CHECK (new_diagram.size () == 2 );
432
- BOOST_CHECK (old_diagram[0 ] == FeeFrac (0 , 0 ));
433
- BOOST_CHECK (old_diagram[1 ] == FeeFrac (low_fee, low_size));
434
- BOOST_CHECK (new_diagram[0 ] == FeeFrac (0 , 0 ));
435
- BOOST_CHECK (new_diagram[1 ] == FeeFrac (0 , 1 ));
424
+ {
425
+ const auto replace_one{pool.CalculateFeerateDiagramsForRBF (/* replacement_fees=*/ 0 , /* replacement_vsize=*/ 1 , {entry_low}, {entry_low})};
426
+ BOOST_CHECK (replace_one.has_value ());
427
+ std::vector<FeeFrac> expected_old_diagram{FeeFrac (0 , 0 ), FeeFrac (low_fee, low_size)};
428
+ BOOST_CHECK (replace_one->first == expected_old_diagram);
429
+ std::vector<FeeFrac> expected_new_diagram{FeeFrac (0 , 0 ), FeeFrac (0 , 1 )};
430
+ BOOST_CHECK (replace_one->second == expected_new_diagram);
431
+ }
436
432
437
433
// Non-zero replacement fee/size
438
- const auto replace_one_fee{pool.CalculateFeerateDiagramsForRBF (/* replacement_fees=*/ high_fee, /* replacement_vsize=*/ low_size, {entry_low}, {entry_low})};
439
- BOOST_CHECK (replace_one_fee.has_value ());
440
- old_diagram = replace_one_fee->first ;
441
- new_diagram = replace_one_fee->second ;
442
- BOOST_CHECK (old_diagram.size () == 2 );
443
- BOOST_CHECK (new_diagram.size () == 2 );
444
- BOOST_CHECK (old_diagram[0 ] == FeeFrac (0 , 0 ));
445
- BOOST_CHECK (old_diagram[1 ] == FeeFrac (low_fee, low_size));
446
- BOOST_CHECK (new_diagram[0 ] == FeeFrac (0 , 0 ));
447
- BOOST_CHECK (new_diagram[1 ] == FeeFrac (high_fee, low_size));
434
+ {
435
+ const auto replace_one_fee{pool.CalculateFeerateDiagramsForRBF (/* replacement_fees=*/ high_fee, /* replacement_vsize=*/ low_size, {entry_low}, {entry_low})};
436
+ BOOST_CHECK (replace_one_fee.has_value ());
437
+ std::vector<FeeFrac> expected_old_diagram{FeeFrac (0 , 0 ), FeeFrac (low_fee, low_size)};
438
+ BOOST_CHECK (replace_one_fee->first == expected_old_diagram);
439
+ std::vector<FeeFrac> expected_new_diagram{FeeFrac (0 , 0 ), FeeFrac (high_fee, low_size)};
440
+ BOOST_CHECK (replace_one_fee->second == expected_new_diagram);
441
+ }
448
442
449
443
// Add a second transaction to the cluster that will make a single chunk, to be evicted in the RBF
450
444
const auto high_tx = make_tx (/* inputs=*/ {low_tx}, /* output_values=*/ {995 * CENT});
451
445
pool.addUnchecked (entry.Fee (high_fee).FromTx (high_tx));
452
446
const auto entry_high = pool.GetIter (high_tx->GetHash ()).value ();
453
447
const auto high_size = entry_high->GetTxSize ();
454
448
455
- const auto replace_single_chunk{pool.CalculateFeerateDiagramsForRBF (/* replacement_fees=*/ high_fee, /* replacement_vsize=*/ low_size, {entry_low}, {entry_low, entry_high})};
456
- BOOST_CHECK (replace_single_chunk.has_value ());
457
- old_diagram = replace_single_chunk->first ;
458
- new_diagram = replace_single_chunk->second ;
459
- BOOST_CHECK (old_diagram.size () == 2 );
460
- BOOST_CHECK (new_diagram.size () == 2 );
461
- BOOST_CHECK (old_diagram[0 ] == FeeFrac (0 , 0 ));
462
- BOOST_CHECK (old_diagram[1 ] == FeeFrac (low_fee + high_fee, low_size + high_size));
463
- BOOST_CHECK (new_diagram[0 ] == FeeFrac (0 , 0 ));
464
- BOOST_CHECK (new_diagram[1 ] == FeeFrac (high_fee, low_size));
449
+ {
450
+ const auto replace_single_chunk{pool.CalculateFeerateDiagramsForRBF (/* replacement_fees=*/ high_fee, /* replacement_vsize=*/ low_size, {entry_low}, {entry_low, entry_high})};
451
+ BOOST_CHECK (replace_single_chunk.has_value ());
452
+ std::vector<FeeFrac> expected_old_diagram{FeeFrac (0 , 0 ), FeeFrac (low_fee + high_fee, low_size + high_size)};
453
+ BOOST_CHECK (replace_single_chunk->first == expected_old_diagram);
454
+ std::vector<FeeFrac> expected_new_diagram{FeeFrac (0 , 0 ), FeeFrac (high_fee, low_size)};
455
+ BOOST_CHECK (replace_single_chunk->second == expected_new_diagram);
456
+ }
465
457
466
458
// Conflict with the 2nd tx, resulting in new diagram with three entries
467
- const auto replace_cpfp_child{pool.CalculateFeerateDiagramsForRBF (/* replacement_fees=*/ high_fee, /* replacement_vsize=*/ low_size, {entry_high}, {entry_high})};
468
- BOOST_CHECK (replace_cpfp_child.has_value ());
469
- old_diagram = replace_cpfp_child->first ;
470
- new_diagram = replace_cpfp_child->second ;
471
- BOOST_CHECK (old_diagram.size () == 2 );
472
- BOOST_CHECK (new_diagram.size () == 3 );
473
- BOOST_CHECK (old_diagram[0 ] == FeeFrac (0 , 0 ));
474
- BOOST_CHECK (old_diagram[1 ] == FeeFrac (low_fee + high_fee, low_size + high_size));
475
- BOOST_CHECK (new_diagram[0 ] == FeeFrac (0 , 0 ));
476
- BOOST_CHECK (new_diagram[1 ] == FeeFrac (high_fee, low_size));
477
- BOOST_CHECK (new_diagram[2 ] == FeeFrac (low_fee + high_fee, low_size + low_size));
459
+ {
460
+ const auto replace_cpfp_child{pool.CalculateFeerateDiagramsForRBF (/* replacement_fees=*/ high_fee, /* replacement_vsize=*/ low_size, {entry_high}, {entry_high})};
461
+ BOOST_CHECK (replace_cpfp_child.has_value ());
462
+ std::vector<FeeFrac> expected_old_diagram{FeeFrac (0 , 0 ), FeeFrac (low_fee + high_fee, low_size + high_size)};
463
+ BOOST_CHECK (replace_cpfp_child->first == expected_old_diagram);
464
+ std::vector<FeeFrac> expected_new_diagram{FeeFrac (0 , 0 ), FeeFrac (high_fee, low_size), FeeFrac (low_fee + high_fee, low_size + low_size)};
465
+ BOOST_CHECK (replace_cpfp_child->second == expected_new_diagram);
466
+ }
478
467
479
468
// third transaction causes the topology check to fail
480
469
const auto normal_tx = make_tx (/* inputs=*/ {high_tx}, /* output_values=*/ {995 * CENT});
481
470
pool.addUnchecked (entry.Fee (normal_fee).FromTx (normal_tx));
482
471
const auto entry_normal = pool.GetIter (normal_tx->GetHash ()).value ();
483
472
const auto normal_size = entry_normal->GetTxSize ();
484
473
485
- const auto replace_too_large{pool. CalculateFeerateDiagramsForRBF ( /* replacement_fees= */ normal_fee, /* replacement_vsize= */ normal_size, {entry_low}, {entry_low, entry_high, entry_normal})};
486
- BOOST_CHECK (! replace_too_large. has_value ()) ;
487
- BOOST_CHECK_EQUAL ( util::ErrorString (replace_too_large). original , strprintf ( " %s has 2 descendants, max 1 allowed " , low_tx-> GetHash (). GetHex () ));
488
- old_diagram. clear ( );
489
- new_diagram. clear ();
474
+ {
475
+ const auto replace_too_large{pool. CalculateFeerateDiagramsForRBF ( /* replacement_fees= */ normal_fee, /* replacement_vsize= */ normal_size, {entry_low}, {entry_low, entry_high, entry_normal})} ;
476
+ BOOST_CHECK (!replace_too_large. has_value ( ));
477
+ BOOST_CHECK_EQUAL ( util::ErrorString (replace_too_large). original , strprintf ( " %s has 2 descendants, max 1 allowed " , low_tx-> GetHash (). GetHex ()) );
478
+ }
490
479
491
480
// Make a size 2 cluster that is itself two chunks; evict both txns
492
481
const auto high_tx_2 = make_tx (/* inputs=*/ {m_coinbase_txns[1 ]}, /* output_values=*/ {10 * COIN});
@@ -499,17 +488,14 @@ BOOST_FIXTURE_TEST_CASE(calc_feerate_diagram_rbf, TestChain100Setup)
499
488
const auto entry_low_2 = pool.GetIter (low_tx_2->GetHash ()).value ();
500
489
const auto low_size_2 = entry_low_2->GetTxSize ();
501
490
502
- const auto replace_two_chunks_single_cluster{pool.CalculateFeerateDiagramsForRBF (/* replacement_fees=*/ high_fee, /* replacement_vsize=*/ low_size, {entry_high_2}, {entry_high_2, entry_low_2})};
503
- BOOST_CHECK (replace_two_chunks_single_cluster.has_value ());
504
- old_diagram = replace_two_chunks_single_cluster->first ;
505
- new_diagram = replace_two_chunks_single_cluster->second ;
506
- BOOST_CHECK (old_diagram.size () == 3 );
507
- BOOST_CHECK (new_diagram.size () == 2 );
508
- BOOST_CHECK (old_diagram[0 ] == FeeFrac (0 , 0 ));
509
- BOOST_CHECK (old_diagram[1 ] == FeeFrac (high_fee, high_size_2));
510
- BOOST_CHECK (old_diagram[2 ] == FeeFrac (low_fee + high_fee, low_size_2 + high_size_2));
511
- BOOST_CHECK (new_diagram[0 ] == FeeFrac (0 , 0 ));
512
- BOOST_CHECK (new_diagram[1 ] == FeeFrac (high_fee, low_size_2));
491
+ {
492
+ const auto replace_two_chunks_single_cluster{pool.CalculateFeerateDiagramsForRBF (/* replacement_fees=*/ high_fee, /* replacement_vsize=*/ low_size, {entry_high_2}, {entry_high_2, entry_low_2})};
493
+ BOOST_CHECK (replace_two_chunks_single_cluster.has_value ());
494
+ std::vector<FeeFrac> expected_old_diagram{FeeFrac (0 , 0 ), FeeFrac (high_fee, high_size_2), FeeFrac (low_fee + high_fee, low_size_2 + high_size_2)};
495
+ BOOST_CHECK (replace_two_chunks_single_cluster->first == expected_old_diagram);
496
+ std::vector<FeeFrac> expected_new_diagram{FeeFrac (0 , 0 ), FeeFrac (high_fee, low_size_2)};
497
+ BOOST_CHECK (replace_two_chunks_single_cluster->second == expected_new_diagram);
498
+ }
513
499
514
500
// You can have more than two direct conflicts if the there are multiple effected clusters, all of size 2 or less
515
501
const auto conflict_1 = make_tx (/* inputs=*/ {m_coinbase_txns[2 ]}, /* output_values=*/ {10 * COIN});
@@ -524,40 +510,37 @@ BOOST_FIXTURE_TEST_CASE(calc_feerate_diagram_rbf, TestChain100Setup)
524
510
pool.addUnchecked (entry.Fee (low_fee).FromTx (conflict_3));
525
511
const auto conflict_3_entry = pool.GetIter (conflict_3->GetHash ()).value ();
526
512
527
- const auto replace_multiple_clusters{pool.CalculateFeerateDiagramsForRBF (/* replacement_fees=*/ high_fee, /* replacement_vsize=*/ low_size, {conflict_1_entry, conflict_2_entry, conflict_3_entry}, {conflict_1_entry, conflict_2_entry, conflict_3_entry})};
528
-
529
- BOOST_CHECK (replace_multiple_clusters.has_value ());
530
- old_diagram = replace_multiple_clusters->first ;
531
- new_diagram = replace_multiple_clusters->second ;
532
- BOOST_CHECK (old_diagram.size () == 4 );
533
- BOOST_CHECK (new_diagram.size () == 2 );
513
+ {
514
+ const auto replace_multiple_clusters{pool.CalculateFeerateDiagramsForRBF (/* replacement_fees=*/ high_fee, /* replacement_vsize=*/ low_size, {conflict_1_entry, conflict_2_entry, conflict_3_entry}, {conflict_1_entry, conflict_2_entry, conflict_3_entry})};
515
+ BOOST_CHECK (replace_multiple_clusters.has_value ());
516
+ BOOST_CHECK (replace_multiple_clusters->first .size () == 4 );
517
+ BOOST_CHECK (replace_multiple_clusters->second .size () == 2 );
518
+ }
534
519
535
520
// Add a child transaction to conflict_1 and make it cluster size 2, still one chunk due to same feerate
536
521
const auto conflict_1_child = make_tx (/* inputs=*/ {conflict_1}, /* output_values=*/ {995 * CENT});
537
522
pool.addUnchecked (entry.Fee (low_fee).FromTx (conflict_1_child));
538
523
const auto conflict_1_child_entry = pool.GetIter (conflict_1_child->GetHash ()).value ();
539
524
540
- const auto replace_multiple_clusters_2{pool.CalculateFeerateDiagramsForRBF (/* replacement_fees=*/ high_fee, /* replacement_vsize=*/ low_size, {conflict_1_entry, conflict_2_entry, conflict_3_entry}, {conflict_1_entry, conflict_2_entry, conflict_3_entry, conflict_1_child_entry})};
525
+ {
526
+ const auto replace_multiple_clusters_2{pool.CalculateFeerateDiagramsForRBF (/* replacement_fees=*/ high_fee, /* replacement_vsize=*/ low_size, {conflict_1_entry, conflict_2_entry, conflict_3_entry}, {conflict_1_entry, conflict_2_entry, conflict_3_entry, conflict_1_child_entry})};
541
527
542
- BOOST_CHECK (replace_multiple_clusters_2.has_value ());
543
- old_diagram = replace_multiple_clusters_2->first ;
544
- new_diagram = replace_multiple_clusters_2->second ;
545
- BOOST_CHECK (old_diagram.size () == 4 );
546
- BOOST_CHECK (new_diagram.size () == 2 );
547
- old_diagram.clear ();
548
- new_diagram.clear ();
528
+ BOOST_CHECK (replace_multiple_clusters_2.has_value ());
529
+ BOOST_CHECK (replace_multiple_clusters_2->first .size () == 4 );
530
+ BOOST_CHECK (replace_multiple_clusters_2->second .size () == 2 );
531
+ }
549
532
550
533
// Add another descendant to conflict_1, making the cluster size > 2 should fail at this point.
551
534
const auto conflict_1_grand_child = make_tx (/* inputs=*/ {conflict_1_child}, /* output_values=*/ {995 * CENT});
552
535
pool.addUnchecked (entry.Fee (high_fee).FromTx (conflict_1_grand_child));
553
536
const auto conflict_1_grand_child_entry = pool.GetIter (conflict_1_child->GetHash ()).value ();
554
537
555
- const auto replace_cluster_size_3{pool.CalculateFeerateDiagramsForRBF (/* replacement_fees=*/ high_fee, /* replacement_vsize=*/ low_size, {conflict_1_entry, conflict_2_entry, conflict_3_entry}, {conflict_1_entry, conflict_2_entry, conflict_3_entry, conflict_1_child_entry, conflict_1_grand_child_entry})};
538
+ {
539
+ const auto replace_cluster_size_3{pool.CalculateFeerateDiagramsForRBF (/* replacement_fees=*/ high_fee, /* replacement_vsize=*/ low_size, {conflict_1_entry, conflict_2_entry, conflict_3_entry}, {conflict_1_entry, conflict_2_entry, conflict_3_entry, conflict_1_child_entry, conflict_1_grand_child_entry})};
556
540
557
- BOOST_CHECK (!replace_cluster_size_3.has_value ());
558
- BOOST_CHECK_EQUAL (util::ErrorString (replace_cluster_size_3).original , strprintf (" %s has 2 descendants, max 1 allowed" , conflict_1->GetHash ().GetHex ()));
559
- BOOST_CHECK (old_diagram.empty ());
560
- BOOST_CHECK (new_diagram.empty ());
541
+ BOOST_CHECK (!replace_cluster_size_3.has_value ());
542
+ BOOST_CHECK_EQUAL (util::ErrorString (replace_cluster_size_3).original , strprintf (" %s has 2 descendants, max 1 allowed" , conflict_1->GetHash ().GetHex ()));
543
+ }
561
544
}
562
545
563
546
BOOST_AUTO_TEST_CASE (feerate_diagram_utilities)
0 commit comments