mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-19 06:43:45 +01:00
Merge bitcoin/bitcoin#33427: rpc: Always return per-wtxid entries in submitpackage tx-results
cad9a7fd73rpc: Always return per-wtxid entries in submitpackage tx-results (John Moffett) Pull request description: Follow-up to #28848 When `submitpackage` produced no per-transaction result for a member, the RPC set `"error": "unevaluated"` but then continued without inserting the entry into `tx-results`, making it impossible for callers to know which `wtxids` were unevaluated. This inserts the error result before continuing, updates help text, and adjusts functional tests to expect entries for all submitted `wtxids`. ACKs for top commit: instagibbs: ACKcad9a7fd73glozow: ACKcad9a7fd73Tree-SHA512: 8df5c9b3d1f17aaf0311c38f028ae4b55d4c52a660f85171f105c4f65d130b14ab00698ac5d7c27403a0c37fff391c154c3ad44cc99ba4d549d9c30751b8360f
This commit is contained in:
@@ -955,7 +955,7 @@ static RPCHelpMan submitpackage()
|
||||
RPCResult::Type::OBJ, "", "",
|
||||
{
|
||||
{RPCResult::Type::STR, "package_msg", "The transaction package result message. \"success\" indicates all transactions were accepted into or are already in the mempool."},
|
||||
{RPCResult::Type::OBJ_DYN, "tx-results", "transaction results keyed by wtxid",
|
||||
{RPCResult::Type::OBJ_DYN, "tx-results", "The transaction results keyed by wtxid. An entry is returned for every submitted wtxid.",
|
||||
{
|
||||
{RPCResult::Type::OBJ, "wtxid", "transaction wtxid", {
|
||||
{RPCResult::Type::STR_HEX, "txid", "The transaction hash in hex"},
|
||||
@@ -968,7 +968,7 @@ static RPCHelpMan submitpackage()
|
||||
{{RPCResult::Type::STR_HEX, "", "transaction wtxid in hex"},
|
||||
}},
|
||||
}},
|
||||
{RPCResult::Type::STR, "error", /*optional=*/true, "The transaction error string, if it was rejected by the mempool"},
|
||||
{RPCResult::Type::STR, "error", /*optional=*/true, "Error string if rejected from mempool, or \"package-not-validated\" when the package aborts before any per-tx processing."},
|
||||
}}
|
||||
}},
|
||||
{RPCResult::Type::ARR, "replaced-transactions", /*optional=*/true, "List of txids of replaced transactions",
|
||||
@@ -1082,10 +1082,15 @@ static RPCHelpMan submitpackage()
|
||||
for (const auto& tx : txns) {
|
||||
UniValue result_inner{UniValue::VOBJ};
|
||||
result_inner.pushKV("txid", tx->GetHash().GetHex());
|
||||
const auto wtxid_hex = tx->GetWitnessHash().GetHex();
|
||||
auto it = package_result.m_tx_results.find(tx->GetWitnessHash());
|
||||
if (it == package_result.m_tx_results.end()) {
|
||||
// No results, report error and continue
|
||||
result_inner.pushKV("error", "unevaluated");
|
||||
// No per-tx result for this wtxid
|
||||
// Current invariant: per-tx results are all-or-none (every member or empty on package abort).
|
||||
// If any exist yet this one is missing, it's an unexpected partial map.
|
||||
CHECK_NONFATAL(package_result.m_tx_results.empty());
|
||||
result_inner.pushKV("error", "package-not-validated");
|
||||
tx_result_map.pushKV(wtxid_hex, std::move(result_inner));
|
||||
continue;
|
||||
}
|
||||
const auto& tx_result = it->second;
|
||||
@@ -1118,7 +1123,7 @@ static RPCHelpMan submitpackage()
|
||||
}
|
||||
break;
|
||||
}
|
||||
tx_result_map.pushKV(tx->GetWitnessHash().GetHex(), std::move(result_inner));
|
||||
tx_result_map.pushKV(wtxid_hex, std::move(result_inner));
|
||||
}
|
||||
rpc_result.pushKV("tx-results", std::move(tx_result_map));
|
||||
UniValue replaced_list(UniValue::VARR);
|
||||
|
||||
@@ -263,13 +263,23 @@ class RPCPackagesTest(BitcoinTestFramework):
|
||||
])
|
||||
|
||||
submitres = node.submitpackage([tx1["hex"], tx2["hex"], tx_child["hex"]])
|
||||
assert_equal(submitres, {'package_msg': 'conflict-in-package', 'tx-results': {}, 'replaced-transactions': []})
|
||||
expected = {
|
||||
tx1["wtxid"]: {"txid": tx1["txid"], "error": "package-not-validated"},
|
||||
tx2["wtxid"]: {"txid": tx2["txid"], "error": "package-not-validated"},
|
||||
tx_child["wtxid"]: {"txid": tx_child["txid"], "error": "package-not-validated"},
|
||||
}
|
||||
assert_equal(submitres, {"package_msg": "conflict-in-package", "tx-results": expected,"replaced-transactions": []})
|
||||
|
||||
# Submit tx1 to mempool, then try the same package again
|
||||
node.sendrawtransaction(tx1["hex"])
|
||||
|
||||
submitres = node.submitpackage([tx1["hex"], tx2["hex"], tx_child["hex"]])
|
||||
assert_equal(submitres, {'package_msg': 'conflict-in-package', 'tx-results': {}, 'replaced-transactions': []})
|
||||
expected = {
|
||||
tx1["wtxid"]: {"txid": tx1["txid"], "error": "package-not-validated"},
|
||||
tx2["wtxid"]: {"txid": tx2["txid"], "error": "package-not-validated"},
|
||||
tx_child["wtxid"]: {"txid": tx_child["txid"], "error": "package-not-validated"},
|
||||
}
|
||||
assert_equal(submitres, {"package_msg": "conflict-in-package", "tx-results": expected,"replaced-transactions": []})
|
||||
assert tx_child["txid"] not in node.getrawmempool()
|
||||
|
||||
# without the in-mempool ancestor tx1 included in the call, tx2 can be submitted, but
|
||||
|
||||
Reference in New Issue
Block a user