@@ -353,74 +353,122 @@ BOOST_AUTO_TEST_CASE(noncontextual_package_tests)
353353 }
354354}
355355
356- BOOST_AUTO_TEST_CASE (package_submission_tests )
356+ BOOST_AUTO_TEST_CASE (package_topology )
357357{
358358 // Mine blocks to mature coinbases.
359- mineBlocks (60 );
359+ mineBlocks (20 );
360360 CFeeRate minfeerate (5000 );
361361 MockMempoolMinFee (minfeerate);
362362 LOCK (cs_main);
363363 unsigned int expected_pool_size = m_node.mempool ->size ();
364364 CKey parent_key = GenerateRandomKey ();
365365 CScript parent_locking_script = GetScriptForDestination (PKHash (parent_key.GetPubKey ()));
366366 const CAmount coinbase_value{50 * COIN};
367+ const CAmount generous_fee{1000 };
367368
368- // Unrelated transactions are not allowed in package submission.
369369 Package package_unrelated;
370370 for (size_t i{0 }; i < 10 ; ++i) {
371- auto mtx = CreateValidMempoolTransaction (/* input_transaction=*/ m_coinbase_txns[i + 25 ], /* input_vout=*/ 0 ,
371+ auto mtx = CreateValidMempoolTransaction (/* input_transaction=*/ m_coinbase_txns[i], /* input_vout=*/ 0 ,
372372 /* input_height=*/ 0 , /* input_signing_key=*/ coinbaseKey,
373373 /* output_destination=*/ parent_locking_script,
374- /* output_amount=*/ CAmount ( 49 * COIN) , /* submit=*/ false );
374+ /* output_amount=*/ coinbase_value - generous_fee , /* submit=*/ false );
375375 package_unrelated.emplace_back (MakeTransactionRef (mtx));
376376 }
377377 auto result_unrelated_submit = ProcessNewPackage (m_node.chainman ->ActiveChainstate (), *m_node.mempool ,
378378 package_unrelated, /* test_accept=*/ false , /* client_maxfeerate=*/ {});
379- // We don't expect m_tx_results for each transaction when basic sanity checks haven't passed.
380- BOOST_CHECK (result_unrelated_submit.m_state .IsInvalid ());
381- BOOST_CHECK_EQUAL (result_unrelated_submit.m_state .GetResult (), PackageValidationResult::PCKG_POLICY);
382- BOOST_CHECK_EQUAL (result_unrelated_submit.m_state .GetRejectReason (), " package-not-child-with-parents" );
379+ BOOST_CHECK (result_unrelated_submit.m_state .IsValid ());
380+ expected_pool_size += 10 ;
383381 BOOST_CHECK_EQUAL (m_node.mempool ->size (), expected_pool_size);
384-
382+ // We should see a result for each transaction. They should have been validated individually.
383+ for (const auto & tx : package_unrelated) {
384+ auto it = result_unrelated_submit.m_tx_results .find (tx->GetWitnessHash ());
385+ BOOST_CHECK (it != result_unrelated_submit.m_tx_results .end ());
386+ BOOST_CHECK (it->second .m_state .IsValid ());
387+ BOOST_CHECK_EQUAL (it->second .m_subpackage_wtxids .value ().size (), 1 );
388+ }
385389 // Parent and Child (and Grandchild) Package
386- Package package_parent_child;
387390 Package package_3gen;
388- auto mtx_parent = CreateValidMempoolTransaction (/* input_transaction=*/ m_coinbase_txns[0 ], /* input_vout=*/ 0 ,
391+ auto mtx_parent = CreateValidMempoolTransaction (/* input_transaction=*/ m_coinbase_txns[10 ], /* input_vout=*/ 0 ,
389392 /* input_height=*/ 0 , /* input_signing_key=*/ coinbaseKey,
390393 /* output_destination=*/ parent_locking_script,
391- /* output_amount=*/ CAmount ( 49 * COIN) , /* submit=*/ false );
394+ /* output_amount=*/ coinbase_value - generous_fee , /* submit=*/ false );
392395 CTransactionRef tx_parent = MakeTransactionRef (mtx_parent);
393- package_parent_child.push_back (tx_parent);
394396 package_3gen.push_back (tx_parent);
395397
396398 CKey child_key = GenerateRandomKey ();
397399 CScript child_locking_script = GetScriptForDestination (PKHash (child_key.GetPubKey ()));
398400 auto mtx_child = CreateValidMempoolTransaction (/* input_transaction=*/ tx_parent, /* input_vout=*/ 0 ,
399401 /* input_height=*/ 101 , /* input_signing_key=*/ parent_key,
400402 /* output_destination=*/ child_locking_script,
401- /* output_amount=*/ CAmount ( 48 * COIN) , /* submit=*/ false );
403+ /* output_amount=*/ coinbase_value - 2 * generous_fee , /* submit=*/ false );
402404 CTransactionRef tx_child = MakeTransactionRef (mtx_child);
403- package_parent_child.push_back (tx_child);
404405 package_3gen.push_back (tx_child);
405406
406407 CKey grandchild_key = GenerateRandomKey ();
407408 CScript grandchild_locking_script = GetScriptForDestination (PKHash (grandchild_key.GetPubKey ()));
408409 auto mtx_grandchild = CreateValidMempoolTransaction (/* input_transaction=*/ tx_child, /* input_vout=*/ 0 ,
409410 /* input_height=*/ 101 , /* input_signing_key=*/ child_key,
410411 /* output_destination=*/ grandchild_locking_script,
411- /* output_amount=*/ CAmount ( 47 * COIN) , /* submit=*/ false );
412+ /* output_amount=*/ coinbase_value - 3 * generous_fee , /* submit=*/ false );
412413 CTransactionRef tx_grandchild = MakeTransactionRef (mtx_grandchild);
413414 package_3gen.push_back (tx_grandchild);
414415
415- // 3 Generations is not allowed .
416+ // Submit package parent + child + grandchild .
416417 {
417418 auto result_3gen_submit = ProcessNewPackage (m_node.chainman ->ActiveChainstate (), *m_node.mempool ,
418419 package_3gen, /* test_accept=*/ false , /* client_maxfeerate=*/ {});
419- BOOST_CHECK (result_3gen_submit.m_state .IsInvalid ());
420- BOOST_CHECK_EQUAL (result_3gen_submit.m_state .GetResult (), PackageValidationResult::PCKG_POLICY);
421- BOOST_CHECK_EQUAL (result_3gen_submit.m_state .GetRejectReason (), " package-not-child-with-parents" );
420+ expected_pool_size += 3 ;
421+ BOOST_CHECK_MESSAGE (result_3gen_submit.m_state .IsValid (),
422+ " Package validation unexpectedly failed: " << result_3gen_submit.m_state .GetRejectReason ());
423+ BOOST_CHECK_EQUAL (result_3gen_submit.m_tx_results .size (), package_3gen.size ());
424+ auto it_parent = result_3gen_submit.m_tx_results .find (tx_parent->GetWitnessHash ());
425+ auto it_child = result_3gen_submit.m_tx_results .find (tx_child->GetWitnessHash ());
426+ auto it_grandchild = result_3gen_submit.m_tx_results .find (tx_grandchild->GetWitnessHash ());
427+
428+ BOOST_CHECK (it_parent->second .m_effective_feerate == CFeeRate (generous_fee, GetVirtualTransactionSize (*tx_parent)));
429+ BOOST_CHECK_EQUAL (it_parent->second .m_subpackage_wtxids .value ().size (), 1 );
430+ BOOST_CHECK_EQUAL (it_parent->second .m_subpackage_wtxids .value ().front (), tx_parent->GetWitnessHash ());
431+ BOOST_CHECK (it_child->second .m_effective_feerate == CFeeRate (generous_fee, GetVirtualTransactionSize (*tx_child)));
432+ BOOST_CHECK_EQUAL (it_child->second .m_subpackage_wtxids .value ().size (), 1 );
433+ BOOST_CHECK_EQUAL (it_child->second .m_subpackage_wtxids .value ().front (), tx_child->GetWitnessHash ());
434+
435+ BOOST_CHECK (it_grandchild->second .m_effective_feerate == CFeeRate (generous_fee, GetVirtualTransactionSize (*tx_grandchild)));
436+ BOOST_CHECK_EQUAL (it_grandchild->second .m_subpackage_wtxids .value ().size (), 1 );
437+ BOOST_CHECK_EQUAL (it_grandchild->second .m_subpackage_wtxids .value ().front (), tx_grandchild->GetWitnessHash ());
438+
422439 BOOST_CHECK_EQUAL (m_node.mempool ->size (), expected_pool_size);
423440 }
441+ }
442+
443+ BOOST_AUTO_TEST_CASE (package_submission_tests)
444+ {
445+ // Mine blocks to mature coinbases.
446+ mineBlocks (60 );
447+ CFeeRate minfeerate (5000 );
448+ MockMempoolMinFee (minfeerate);
449+ LOCK (cs_main);
450+ unsigned int expected_pool_size = m_node.mempool ->size ();
451+ CKey parent_key = GenerateRandomKey ();
452+ CScript parent_locking_script = GetScriptForDestination (PKHash (parent_key.GetPubKey ()));
453+ const CAmount coinbase_value{50 * COIN};
454+
455+ // Parent and Child
456+ Package package_parent_child;
457+ auto mtx_parent = CreateValidMempoolTransaction (/* input_transaction=*/ m_coinbase_txns[0 ], /* input_vout=*/ 0 ,
458+ /* input_height=*/ 0 , /* input_signing_key=*/ coinbaseKey,
459+ /* output_destination=*/ parent_locking_script,
460+ /* output_amount=*/ CAmount (49 * COIN), /* submit=*/ false );
461+ CTransactionRef tx_parent = MakeTransactionRef (mtx_parent);
462+ package_parent_child.push_back (tx_parent);
463+
464+ CKey child_key = GenerateRandomKey ();
465+ CScript child_locking_script = GetScriptForDestination (PKHash (child_key.GetPubKey ()));
466+ auto mtx_child = CreateValidMempoolTransaction (/* input_transaction=*/ tx_parent, /* input_vout=*/ 0 ,
467+ /* input_height=*/ 101 , /* input_signing_key=*/ parent_key,
468+ /* output_destination=*/ child_locking_script,
469+ /* output_amount=*/ CAmount (48 * COIN), /* submit=*/ false );
470+ CTransactionRef tx_child = MakeTransactionRef (mtx_child);
471+ package_parent_child.push_back (tx_child);
424472
425473 // Parent and child package where transactions are invalid for reasons other than fee and
426474 // missing inputs, so the package validation isn't expected to happen.
@@ -448,22 +496,21 @@ BOOST_AUTO_TEST_CASE(package_submission_tests)
448496 BOOST_CHECK_EQUAL (result_quit_early.m_state .GetResult (), PackageValidationResult::PCKG_TX);
449497 }
450498
451- // Submit package with parent + child.
499+ // Submit package parent + child
452500 {
453- const auto submit_parent_child = ProcessNewPackage (m_node.chainman ->ActiveChainstate (), *m_node.mempool ,
454- package_parent_child, /* test_accept=*/ false , /* client_maxfeerate=*/ {});
501+ auto result_parent_child_submit = ProcessNewPackage (m_node.chainman ->ActiveChainstate (), *m_node.mempool ,
502+ package_parent_child, /* test_accept=*/ false , /* client_maxfeerate=*/ {});
455503 expected_pool_size += 2 ;
456- BOOST_CHECK_MESSAGE (submit_parent_child.m_state .IsValid (),
457- " Package validation unexpectedly failed: " << submit_parent_child.m_state .GetRejectReason ());
458- BOOST_CHECK_EQUAL (submit_parent_child.m_tx_results .size (), package_parent_child.size ());
459- auto it_parent = submit_parent_child.m_tx_results .find (tx_parent->GetWitnessHash ());
460- auto it_child = submit_parent_child.m_tx_results .find (tx_child->GetWitnessHash ());
461- BOOST_CHECK (it_parent != submit_parent_child.m_tx_results .end ());
462- BOOST_CHECK (it_parent->second .m_state .IsValid ());
463- BOOST_CHECK (it_parent->second .m_effective_feerate == CFeeRate (1 * COIN, GetVirtualTransactionSize (*tx_parent)));
504+ BOOST_CHECK_MESSAGE (result_parent_child_submit.m_state .IsValid (),
505+ " Package validation unexpectedly failed: " << result_parent_child_submit.m_state .GetRejectReason ());
506+ BOOST_CHECK_EQUAL (result_parent_child_submit.m_tx_results .size (), package_parent_child.size ());
507+ auto it_parent = result_parent_child_submit.m_tx_results .find (tx_parent->GetWitnessHash ());
508+ auto it_child = result_parent_child_submit.m_tx_results .find (tx_child->GetWitnessHash ());
509+
510+ BOOST_CHECK (it_parent->second .m_effective_feerate == CFeeRate (COIN, GetVirtualTransactionSize (*tx_parent)));
464511 BOOST_CHECK_EQUAL (it_parent->second .m_subpackage_wtxids .value ().size (), 1 );
465512 BOOST_CHECK_EQUAL (it_parent->second .m_subpackage_wtxids .value ().front (), tx_parent->GetWitnessHash ());
466- BOOST_CHECK (it_child->second .m_effective_feerate == CFeeRate (1 * COIN, GetVirtualTransactionSize (*tx_child)));
513+ BOOST_CHECK (it_child->second .m_effective_feerate == CFeeRate (COIN, GetVirtualTransactionSize (*tx_child)));
467514 BOOST_CHECK_EQUAL (it_child->second .m_subpackage_wtxids .value ().size (), 1 );
468515 BOOST_CHECK_EQUAL (it_child->second .m_subpackage_wtxids .value ().front (), tx_child->GetWitnessHash ());
469516
@@ -1530,15 +1577,15 @@ BOOST_FIXTURE_TEST_CASE(linearization_tests, TestChain100Setup)
15301577 // 3sat/vB 3sat/vB 20sat/vB
15311578 // ^ ^ ^ ^
15321579 // parent1 parent2
1533- // 7sat /vB 7sat /vB
1580+ // 8sat /vB 8sat /vB
15341581 // ^ ^ ^ ^
15351582 // child
15361583 // 1sat/vB
15371584 //
15381585 // child is also spending all the grandparents so that this is a child-with-parents package.
15391586 const CFeeRate feerate_grandparents_low (3000 );
15401587 const CFeeRate feerate_grandparent_high (20000 );
1541- const CFeeRate feerate_parents (8000 );
1588+ const CFeeRate feerate_parents (8200 );
15421589 const CFeeRate feerate_child (1000 );
15431590 const CFeeRate mempool_min_feerate{m_node.mempool ->GetMinFee ()};
15441591
0 commit comments