mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-20 07:09:15 +01:00
Merge bitcoin/bitcoin#28251: validation: fix coins disappearing mid-package evaluation
32c1dd1ad6[test] mempool coins disappearing mid-package evaluation (glozow)a67f460c3f[refactor] split setup in mempool_limit test (glozow)d08696120e[test framework] add ability to spend only confirmed utxos (glozow)3ea71feb11[validation] don't LimitMempoolSize in any subpackage submissions (glozow)d227b7234c[validation] return correct result when already-in-mempool tx gets evicted (glozow)9698b81828[refactor] back-fill results in AcceptPackage (glozow)8ad7ad3392[validation] make PackageMempoolAcceptResult members mutable (glozow)03b87c11ca[validation] add AcceptSubPackage to delegate Accept* calls and clean up m_view (glozow)3f01a3dab1[CCoinsViewMemPool] track non-base coins and allow Reset (glozow)7d7f7a1189[policy] check for duplicate txids in package (glozow) Pull request description: While we are evaluating a package, we split it into "subpackages" for evaluation (currently subpackages all have size 1 except the last one). If a subpackage has size 1, we may add a tx to mempool and call `LimitMempoolSize()`, which evicts transactions if the mempool gets full. We handle the case where the just-submitted transaction is evicted immediately, but we don't handle the case in which a transaction from a previous subpackage (either just submitted or already in mempool) is evicted. Mainly, since the coins created by the evicted transaction are cached in `m_view`, we don't realize the UTXO has disappeared until `CheckInputsFromMempoolAndCache` asserts that they exist. Also, the returned `PackageMempoolAcceptResult` reports that the transaction is in mempool even though it isn't anymore. Fix this by not calling `LimitMempoolSize()` until the very end, and editing the results map with "mempool full" if things fall out. Pointed out by instagibbs infaeed687e5on top of the v3 PR. ACKs for top commit: instagibbs: reACK32c1dd1ad6Tree-SHA512: 61e7f69db4712e5e5bfa27d037ab66bdd97f1bf60a8d9ffb96adb1f0609af012c810d681102ee5c7baec7b5fe8cb7c304a60c63ccc445d00d86a2b7f0e7ddb90
This commit is contained in:
@@ -65,6 +65,17 @@ BOOST_FIXTURE_TEST_CASE(package_sanitization_tests, TestChain100Setup)
|
||||
BOOST_CHECK(!CheckPackage(package_too_large, state_too_large));
|
||||
BOOST_CHECK_EQUAL(state_too_large.GetResult(), PackageValidationResult::PCKG_POLICY);
|
||||
BOOST_CHECK_EQUAL(state_too_large.GetRejectReason(), "package-too-large");
|
||||
|
||||
// Packages can't contain transactions with the same txid.
|
||||
Package package_duplicate_txids_empty;
|
||||
for (auto i{0}; i < 3; ++i) {
|
||||
CMutableTransaction empty_tx;
|
||||
package_duplicate_txids_empty.emplace_back(MakeTransactionRef(empty_tx));
|
||||
}
|
||||
PackageValidationState state_duplicates;
|
||||
BOOST_CHECK(!CheckPackage(package_duplicate_txids_empty, state_duplicates));
|
||||
BOOST_CHECK_EQUAL(state_duplicates.GetResult(), PackageValidationResult::PCKG_POLICY);
|
||||
BOOST_CHECK_EQUAL(state_duplicates.GetRejectReason(), "package-contains-duplicates");
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(package_validation_tests, TestChain100Setup)
|
||||
@@ -809,18 +820,20 @@ BOOST_FIXTURE_TEST_CASE(package_cpfp_tests, TestChain100Setup)
|
||||
expected_pool_size += 1;
|
||||
BOOST_CHECK_MESSAGE(submit_rich_parent.m_state.IsInvalid(), "Package validation unexpectedly succeeded");
|
||||
|
||||
// The child would have been validated on its own and failed, then submitted as a "package" of 1.
|
||||
// The child would have been validated on its own and failed.
|
||||
BOOST_CHECK_EQUAL(submit_rich_parent.m_state.GetResult(), PackageValidationResult::PCKG_TX);
|
||||
BOOST_CHECK_EQUAL(submit_rich_parent.m_state.GetRejectReason(), "transaction failed");
|
||||
|
||||
auto it_parent = submit_rich_parent.m_tx_results.find(tx_parent_rich->GetWitnessHash());
|
||||
auto it_child = submit_rich_parent.m_tx_results.find(tx_child_poor->GetWitnessHash());
|
||||
BOOST_CHECK(it_parent != submit_rich_parent.m_tx_results.end());
|
||||
BOOST_CHECK(it_child != submit_rich_parent.m_tx_results.end());
|
||||
BOOST_CHECK(it_parent->second.m_result_type == MempoolAcceptResult::ResultType::VALID);
|
||||
BOOST_CHECK(it_child->second.m_result_type == MempoolAcceptResult::ResultType::INVALID);
|
||||
BOOST_CHECK(it_parent->second.m_state.GetRejectReason() == "");
|
||||
BOOST_CHECK_MESSAGE(it_parent->second.m_base_fees.value() == high_parent_fee,
|
||||
strprintf("rich parent: expected fee %s, got %s", high_parent_fee, it_parent->second.m_base_fees.value()));
|
||||
BOOST_CHECK(it_parent->second.m_effective_feerate == CFeeRate(high_parent_fee, GetVirtualTransactionSize(*tx_parent_rich)));
|
||||
auto it_child = submit_rich_parent.m_tx_results.find(tx_child_poor->GetWitnessHash());
|
||||
BOOST_CHECK(it_child != submit_rich_parent.m_tx_results.end());
|
||||
BOOST_CHECK_EQUAL(it_child->second.m_result_type, MempoolAcceptResult::ResultType::INVALID);
|
||||
BOOST_CHECK_EQUAL(it_child->second.m_state.GetResult(), TxValidationResult::TX_MEMPOOL_POLICY);
|
||||
|
||||
Reference in New Issue
Block a user