Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1251},1252[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue1253{1254const ArgsManager& args{EnsureAnyArgsman(request.context)};1255const CTxMemPool& mempool = EnsureAnyMemPool(request.context);1257if (!mempool.GetLoadTried()) {1258throw JSONRPCError(RPC_MISC_ERROR, "The mempool was not loaded yet");1259}1261const fs::path& dump_path = MempoolPath(args);1263if (!DumpMempool(mempool, dump_path)) {1264throw JSONRPCError(RPC_MISC_ERROR, "Unable to dump mempool to disk");1265}1267UniValue ret(UniValue::VOBJ);1268ret.pushKV("filename", dump_path.utf8string());1270return ret;1271},1272};1273}1275static std::vector<RPCResult> OrphanDescription()1276{1277return {1278RPCResult{RPCResult::Type::STR_HEX, "txid", "The transaction hash in hex"},1279RPCResult{RPCResult::Type::STR_HEX, "wtxid", "The transaction witness hash in hex"},1280RPCResult{RPCResult::Type::NUM, "bytes", "The serialized transaction size in bytes"},1281RPCResult{RPCResult::Type::NUM, "vsize", "(DEPRECATED) use vsize_bip141 instead. The virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted."},1282RPCResult{RPCResult::Type::NUM, "vsize_bip141", "The virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted."},1283RPCResult{RPCResult::Type::NUM, "weight", "The transaction weight as defined in BIP 141."},1284RPCResult{RPCResult::Type::ARR, "from", "",1285{1286RPCResult{RPCResult::Type::NUM, "peer_id", "Peer ID"},1287}},1288};1289}1291static UniValue OrphanToJSON(const node::TxOrphanage::OrphanInfo& orphan)1292{1293UniValue o(UniValue::VOBJ);1294o.pushKV("txid", orphan.tx->GetHash().ToString());1295o.pushKV("wtxid", orphan.tx->GetWitnessHash().ToString());1296o.pushKV("bytes", orphan.tx->ComputeTotalSize());1297o.pushKV("vsize", GetVirtualTransactionSize(*orphan.tx));1298o.pushKV("vsize_bip141", GetVirtualTransactionSize(*orphan.tx));1299o.pushKV("weight", GetTransactionWeight(*orphan.tx));1300UniValue from(UniValue::VARR);1301for (const auto fromPeer: orphan.announcers) {1302from.push_back(fromPeer);1303}1304o.pushKV("from", from);1305return o;1306}1308static RPCMethod getorphantxs()1309{1310return RPCMethod{1311"getorphantxs",1312"Shows transactions in the tx orphanage.\n"1313"\nEXPERIMENTAL warning: this call may be changed in future releases.\n",1314{1315{"verbosity", RPCArg::Type::NUM, RPCArg::Default{0}, "0 for an array of txids (may contain duplicates), 1 for an array of objects with tx details, and 2 for details from (1) and tx hex",1316RPCArgOptions{.skip_type_check = true}},1317},1318{1319RPCResult{"for verbose = 0",1320RPCResult::Type::ARR, "", "",1321{1322{RPCResult::Type::STR_HEX, "txid", "The transaction hash in hex"},1323}},1324RPCResult{"for verbose = 1",1325RPCResult::Type::ARR, "", "",1326{1327{RPCResult::Type::OBJ, "", "", OrphanDescription()},1328}},1329RPCResult{"for verbose = 2",1330RPCResult::Type::ARR, "", "",1331{1332{RPCResult::Type::OBJ, "", "",1333Cat<std::vector<RPCResult>>(1334OrphanDescription(),1335{{RPCResult::Type::STR_HEX, "hex", "The serialized, hex-encoded transaction data"}}1336)1337},1338}},1339},1340RPCExamples{1341HelpExampleCli("getorphantxs", "2")1342+ HelpExampleRpc("getorphantxs", "2")1343},1344[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue1345{1346const NodeContext& node = EnsureAnyNodeContext(request.context);1347PeerManager& peerman = EnsurePeerman(node);1348std::vector<node::TxOrphanage::OrphanInfo> orphanage = peerman.GetOrphanTransactions();1350int verbosity{ParseVerbosity(request.params[0], /*default_verbosity=*/0, /*allow_bool=*/false)};1352UniValue ret(UniValue::VARR);1354if (verbosity == 0) {1355for (auto const& orphan : orphanage) {1356ret.push_back(orphan.tx->GetHash().ToString());1357}1358} else if (verbosity == 1) {1359for (auto const& orphan : orphanage) {1360ret.push_back(OrphanToJSON(orphan));1361}1362} else if (verbosity == 2) {1363for (auto const& orphan : orphanage) {1364UniValue o{OrphanToJSON(orphan)};1365o.pushKV("hex", EncodeHexTx(*orphan.tx));1366ret.push_back(o);1367}1368} else {1369throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid verbosity value " + ToString(verbosity));1370}1372return ret;1373},1374};1375}1377static RPCMethod submitpackage()1378{1379return RPCMethod{"submitpackage",1380"Submit a package of raw transactions (serialized, hex-encoded) to local node.\n"1381"The package will be validated according to consensus and mempool policy rules. If any transaction passes, it will be accepted to mempool.\n"1382"This RPC is experimental and the interface may be unstable. Refer to doc/policy/packages.md for documentation on package policies.\n"1383"Warning: successful submission does not mean the transactions will propagate throughout the network.\n"1384,1385{1386{"package", RPCArg::Type::ARR, RPCArg::Optional::NO, "An array of raw transactions.\n"1387"The package must consist of a transaction with (some, all, or none of) its unconfirmed parents. A single transaction is permitted.\n"1388"None of the parents may depend on each other. Parents that are already in mempool do not need to be present in the package.\n"1389"The package must be topologically sorted, with the child being the last element in the array if there are multiple elements.",1390{1391{"rawtx", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, ""},1392},1393},1394{"maxfeerate", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK())},1395"Reject transactions whose fee rate is higher than the specified value, expressed in " + CURRENCY_UNIT +1396"/kvB.\nFee rates larger than 1BTC/kvB are rejected.\nSet to 0 to accept any fee rate."},1397{"maxburnamount", RPCArg::Type::AMOUNT, RPCArg::Default{FormatMoney(DEFAULT_MAX_BURN_AMOUNT)},1398"Reject transactions with provably unspendable outputs (e.g. 'datacarrier' outputs that use the OP_RETURN opcode) greater than the specified value, expressed in " + CURRENCY_UNIT + ".\n"1399"If burning funds through unspendable outputs is desired, increase this value.\n"1400"This check is based on heuristics and does not guarantee spendability of outputs.\n"1401},1402},1403RPCResult{1404RPCResult::Type::OBJ, "", "",1405{1406{RPCResult::Type::STR, "package_msg", "The transaction package result message. \"success\" indicates all transactions were accepted into or are already in the mempool."},1407{RPCResult::Type::OBJ_DYN, "tx-results", "The transaction results keyed by wtxid. An entry is returned for every submitted wtxid.",1408{1409{RPCResult::Type::OBJ, "wtxid", "transaction wtxid", {1410{RPCResult::Type::STR_HEX, "txid", "The transaction hash in hex"},1411{RPCResult::Type::STR_HEX, "other-wtxid", /*optional=*/true, "The wtxid of a different transaction with the same txid but different witness found in the mempool. This means the submitted transaction was ignored."},1412{RPCResult::Type::NUM, "vsize_adjusted", /*optional=*/true, "Maximum of sigop-adjusted size (-bytespersigop) and virtual transaction size as defined in BIP 141."},1413{RPCResult::Type::NUM, "vsize", /*optional=*/true, "(DEPRECATED) Was previously erroneously described as the BIP 141 vsize, but is actually sigops-adjusted vsize.\n"1414"Use vsize_bip141 to actually get that behavior or switch to the explicit vsize_adjusted for retained behavior."},1415{RPCResult::Type::NUM, "vsize_bip141", /*optional=*/true, "Virtual transaction size as defined in BIP 141."},1416{RPCResult::Type::OBJ, "fees", /*optional=*/true, "Transaction fees", {1417{RPCResult::Type::STR_AMOUNT, "base", "transaction fee in " + CURRENCY_UNIT},1418{RPCResult::Type::STR_AMOUNT, "effective-feerate", /*optional=*/true, "if the transaction was not already in the mempool, the effective feerate in " + CURRENCY_UNIT + " per KvB. For example, the package feerate and/or feerate with modified fees from prioritisetransaction."},1419{RPCResult::Type::ARR, "effective-includes", /*optional=*/true, "if effective-feerate is provided, the wtxids of the transactions whose fees and vsizes are included in effective-feerate.",1420{{RPCResult::Type::STR_HEX, "", "transaction wtxid in hex"},1421}},1422}},1423{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."},1424}}1425}},1426{RPCResult::Type::ARR, "replaced-transactions", /*optional=*/true, "List of txids of replaced transactions",1427{1428{RPCResult::Type::STR_HEX, "", "The transaction id"},1429}},1430},1431},1432RPCExamples{1433HelpExampleRpc("submitpackage", R"(["raw-parent-tx-1", "raw-parent-tx-2", "raw-child-tx"])") +1434HelpExampleCli("submitpackage", R"('["raw-tx-without-unconfirmed-parents"]')")1435},1436[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue1437{1438const UniValue raw_transactions = request.params[0].get_array();1439if (raw_transactions.empty() || raw_transactions.size() > MAX_PACKAGE_COUNT) {1440throw JSONRPCError(RPC_INVALID_PARAMETER,1441"Array must contain between 1 and " + ToString(MAX_PACKAGE_COUNT) + " transactions.");1442}1444// Fee check needs to be run with chainstate and package context1445const CFeeRate max_raw_tx_fee_rate{ParseFeeRate(self.Arg<UniValue>("maxfeerate"))};1446std::optional<CFeeRate> client_maxfeerate{max_raw_tx_fee_rate};1447// 0-value is special; it's mapped to no sanity check1448if (max_raw_tx_fee_rate == CFeeRate(0)) {1449client_maxfeerate = std::nullopt;1450}1452// Burn sanity check is run with no context1453const CAmount max_burn_amount = request.params[2].isNull() ? 0 : AmountFromValue(request.params[2]);1455std::vector<CTransactionRef> txns;1456txns.reserve(raw_transactions.size());1457for (const auto& rawtx : raw_transactions.getValues()) {1458CMutableTransaction mtx;1459if (!DecodeHexTx(mtx, rawtx.get_str())) {1460throw JSONRPCError(RPC_DESERIALIZATION_ERROR,1461"TX decode failed: " + rawtx.get_str() + " Make sure the tx has at least one input.");1462}1464for (const auto& out : mtx.vout) {1465if((out.scriptPubKey.IsUnspendable() || !out.scriptPubKey.HasValidOps()) && out.nValue > max_burn_amount) {1466throw JSONRPCTransactionError(TransactionError::MAX_BURN_EXCEEDED);1467}1468}1470txns.emplace_back(MakeTransactionRef(std::move(mtx)));1471}1472CHECK_NONFATAL(!txns.empty());1473if (txns.size() > 1 && !IsChildWithParentsTree(txns)) {1474throw JSONRPCTransactionError(TransactionError::INVALID_PACKAGE, "package topology disallowed. not child-with-parents or parents depend on each other.");1475}1477NodeContext& node = EnsureAnyNodeContext(request.context);1478CTxMemPool& mempool = EnsureMemPool(node);1479Chainstate& chainstate = EnsureChainman(node).ActiveChainstate();1480const auto package_result = WITH_LOCK(::cs_main, return ProcessNewPackage(chainstate, mempool, txns, /*test_accept=*/ false, client_maxfeerate));1482std::string package_msg = "success";1484// First catch package-wide errors, continue if we can1485switch(package_result.m_state.GetResult()) {1486case PackageValidationResult::PCKG_RESULT_UNSET:1487{1488// Belt-and-suspenders check; everything should be successful here1489CHECK_NONFATAL(package_result.m_tx_results.size() == txns.size());1490for (const auto& tx : txns) {1491CHECK_NONFATAL(mempool.exists(tx->GetHash()));1492}1493break;1494}1495case PackageValidationResult::PCKG_MEMPOOL_ERROR:1496{1497// This only happens with internal bug; user should stop and report1498throw JSONRPCTransactionError(TransactionError::MEMPOOL_ERROR,1499package_result.m_state.GetRejectReason());1500}