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.
1501rawTx.vin.push_back(input);1502total_input_value += output.txout.nValue;1503}1504}1506std::vector<COutPoint> outpoints_spent;1507outpoints_spent.reserve(rawTx.vin.size());1509for (const CTxIn& tx_in : rawTx.vin) {1510outpoints_spent.push_back(tx_in.prevout);1511}1513// estimate final size of tx1514const TxSize tx_size{CalculateMaximumSignedTxSize(CTransaction(rawTx), pwallet.get())};1515if (tx_size.vsize == -1) {1516throw JSONRPCError(RPC_WALLET_ERROR, "Unable to determine the size of the transaction, the wallet contains unsolvable descriptors");1517}1518const CAmount fee_from_size{fee_rate.GetFee(tx_size.vsize)};1519const std::optional<CAmount> total_bump_fees{pwallet->chain().calculateCombinedBumpFee(outpoints_spent, fee_rate)};1520CAmount effective_value = total_input_value - fee_from_size - total_bump_fees.value_or(0);1522if (fee_from_size > pwallet->m_default_max_tx_fee) {1523throw JSONRPCError(RPC_WALLET_ERROR, TransactionErrorString(TransactionError::MAX_FEE_EXCEEDED).original);1524}1526if (effective_value <= 0) {1527if (send_max) {1528throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Total value of UTXO pool too low to pay for transaction, try using lower feerate.");1529} else {1530throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Total value of UTXO pool too low to pay for transaction. Try using lower feerate or excluding uneconomic UTXOs with 'send_max' option.");1531}1532}1534// If this transaction is too large, e.g. because the wallet has many UTXOs, it will be rejected by the node's mempool.1535if (tx_size.weight > coin_control.m_max_tx_weight) {1536throw JSONRPCError(RPC_WALLET_ERROR, "Transaction too large.");1537}1539CAmount output_amounts_claimed{0};1540for (const CTxOut& out : rawTx.vout) {1541output_amounts_claimed += out.nValue;1542}1544if (output_amounts_claimed > total_input_value) {1545throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Assigned more value to outputs than available funds.");1546}1548const CAmount remainder{effective_value - output_amounts_claimed};1549if (remainder < 0) {1550throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds for fees after creating specified outputs.");1551}1553const CAmount per_output_without_amount{remainder / (long)addresses_without_amount.size()};1555bool gave_remaining_to_first{false};1556for (CTxOut& out : rawTx.vout) {1557CTxDestination dest;1558ExtractDestination(out.scriptPubKey, dest);1559std::string addr{EncodeDestination(dest)};1560if (addresses_without_amount.contains(addr)) {1561out.nValue = per_output_without_amount;1562if (!gave_remaining_to_first) {1563out.nValue += remainder % addresses_without_amount.size();1564gave_remaining_to_first = true;1565}1566if (IsDust(out, pwallet->chain().relayDustFee())) {1567// Dynamically generated output amount is dust1568throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Dynamically assigned remainder results in dust output.");1569}1570} else {1571if (IsDust(out, pwallet->chain().relayDustFee())) {1572// Specified output amount is dust1573throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Specified output amount to %s is below dust threshold.", addr));1574}1575}1576}1578const bool lock_unspents{options.exists("lock_unspents") ? options["lock_unspents"].get_bool() : false};1579if (lock_unspents) {1580for (const CTxIn& txin : rawTx.vin) {1581pwallet->LockCoin(txin.prevout, /*persist=*/false);1582}1583}1585return FinishTransaction(pwallet, options, rawTx);1586}1587};1588}1590RPCMethod walletprocesspsbt()1591{1592return RPCMethod{1593"walletprocesspsbt",1594"Update a PSBT with input information from our wallet and then sign inputs\n"1595"that we can sign for." +1596HELP_REQUIRING_PASSPHRASE,1597{1598{"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction base64 string"},1599{"sign", RPCArg::Type::BOOL, RPCArg::Default{true}, "Also sign the transaction when updating (requires wallet to be unlocked)"},1600{"sighashtype", RPCArg::Type::STR, RPCArg::DefaultHint{"DEFAULT for Taproot, ALL otherwise"}, "The signature hash type to sign with if not specified by the PSBT. Must be one of\n"1601" \"DEFAULT\"\n"1602" \"ALL\"\n"1603" \"NONE\"\n"1604" \"SINGLE\"\n"1605" \"ALL|ANYONECANPAY\"\n"1606" \"NONE|ANYONECANPAY\"\n"1607" \"SINGLE|ANYONECANPAY\""},1608{"bip32derivs", RPCArg::Type::BOOL, RPCArg::Default{true}, "Include BIP 32 derivation paths for public keys if we know them"},1609{"finalize", RPCArg::Type::BOOL, RPCArg::Default{true}, "Also finalize inputs if possible"},1610},1611RPCResult{1612RPCResult::Type::OBJ, "", "",1613{1614{RPCResult::Type::STR, "psbt", "The base64-encoded partially signed transaction"},1615{RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"},1616{RPCResult::Type::STR_HEX, "hex", /*optional=*/true, "The hex-encoded network transaction if complete"},1617}1618},1619RPCExamples{1620HelpExampleCli("walletprocesspsbt", "\"psbt\"")1621},1622[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue1623{1624const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);1625if (!pwallet) return UniValue::VNULL;1627const CWallet& wallet{*pwallet};1628// Make sure the results are valid at least up to the most recent block1629// the user could have gotten from another RPC command prior to now1630wallet.BlockUntilSyncedToCurrentChain();1632// Unserialize the transaction1633util::Result<PartiallySignedTransaction> psbt_res = DecodeBase64PSBT(request.params[0].get_str());1634if (!psbt_res) {1635throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", util::ErrorString(psbt_res).original));1636}1637PartiallySignedTransaction psbtx = *psbt_res;1639// Get the sighash type1640std::optional<int> nHashType = ParseSighashString(request.params[2]);1642// Fill transaction with our data and also sign1643bool sign = request.params[1].isNull() ? true : request.params[1].get_bool();1644bool bip32derivs = request.params[3].isNull() ? true : request.params[3].get_bool();1645bool finalize = request.params[4].isNull() ? true : request.params[4].get_bool();1646bool complete = true;1648if (sign) EnsureWalletIsUnlocked(*pwallet);1650const auto err{wallet.FillPSBT(psbtx, {.sign = sign, .sighash_type = nHashType, .finalize = finalize, .bip32_derivs = bip32derivs}, complete)};1651if (err) {1652throw JSONRPCPSBTError(*err);1653}1655UniValue result(UniValue::VOBJ);1656DataStream ssTx{};1657ssTx << psbtx;1658result.pushKV("psbt", EncodeBase64(ssTx.str()));1659result.pushKV("complete", complete);1660if (complete) {1661CMutableTransaction mtx;1662// Returns true if complete, which we already think it is.1663CHECK_NONFATAL(FinalizeAndExtractPSBT(psbtx, mtx));1664DataStream ssTx_final;1665ssTx_final << TX_WITH_WITNESS(mtx);1666result.pushKV("hex", HexStr(ssTx_final));1667}1669return result;1670},1671};1672}1674RPCMethod walletcreatefundedpsbt()1675{1676return RPCMethod{1677"walletcreatefundedpsbt",1678"Creates and funds a transaction in the Partially Signed Transaction format.\n"1679"Implements the Creator and Updater roles.\n"1680"All existing inputs must either have their previous output transaction be in the wallet\n"1681"or be in the UTXO set. Solving data must be provided for non-wallet inputs.\n",1682{1683{"inputs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "Leave empty to add inputs automatically. See add_inputs option.",1684{1685{"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",1686{1687{"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},1688{"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"},1689{"sequence", RPCArg::Type::NUM, RPCArg::DefaultHint{"depends on the value of the 'locktime' and 'options.replaceable' arguments"}, "The sequence number"},1690{"weight", RPCArg::Type::NUM, RPCArg::DefaultHint{"Calculated from wallet and solving data"}, "The maximum weight for this input, "1691"including the weight of the outpoint and sequence number. "1692"Note that signature sizes are not guaranteed to be consistent, "1693"so the maximum DER signatures size of 73 bytes should be used when considering ECDSA signatures."1694"Remember to convert serialized sizes to weight units when necessary."},1695},1696},1697},1698},1699{"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The outputs specified as key-value pairs.\n"1700"Each key may only appear once, i.e. there can only be one 'data' output, and no address may be duplicated.\n"1701"At least one output of either type must be specified.\n"1702"For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also\n"1703"accepted as second parameter.",1704OutputsDoc(),1705RPCArgOptions{.skip_type_check = true}},1706{"locktime", RPCArg::Type::NUM, RPCArg::Default{0}, "Raw locktime. Non-0 value also locktime-activates inputs"},1707{"options", RPCArg::Type::OBJ_NAMED_PARAMS, RPCArg::Optional::OMITTED, "",1708Cat<std::vector<RPCArg>>(1709{1710{"add_inputs", RPCArg::Type::BOOL, RPCArg::DefaultHint{"false when \"inputs\" are specified, true otherwise"}, "Automatically include coins from the wallet to cover the target amount.\n"},1711{"include_unsafe", RPCArg::Type::BOOL, RPCArg::Default{false}, "Include inputs that are not safe to spend (unconfirmed transactions from outside keys and unconfirmed replacement transactions).\n"1712"Warning: the resulting transaction may become invalid if one of the unsafe inputs disappears.\n"1713"If that happens, you will need to fund the transaction with different inputs and republish it."},1714{"minconf", RPCArg::Type::NUM, RPCArg::Default{0}, "If add_inputs is specified, require inputs with at least this many confirmations."},1715{"maxconf", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "If add_inputs is specified, require inputs with at most this many confirmations."},1716{"changeAddress", RPCArg::Type::STR, RPCArg::DefaultHint{"automatic"}, "The bitcoin address to receive the change"},1717{"changePosition", RPCArg::Type::NUM, RPCArg::DefaultHint{"random"}, "The index of the change output"},1718{"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if changeAddress is not specified. Options are " + FormatAllOutputTypes() + "."},1719{"includeWatching", RPCArg::Type::BOOL, RPCArg::Default{false}, "(DEPRECATED) No longer used"},1720{"lockUnspents", RPCArg::Type::BOOL, RPCArg::Default{false}, "Lock selected unspent outputs"},1721{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},1722{"feeRate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_UNIT + "/kvB."},1723{"subtractFeeFromOutputs", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "The outputs to subtract the fee from.\n"1724"The fee will be equally deducted from the amount of each specified output.\n"1725"Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"1726"If no outputs are specified here, the sender pays the fee.",1727{1728{"vout_index", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "The zero-based output index, before a change output is added."},1729},1730},1731{"max_tx_weight", RPCArg::Type::NUM, RPCArg::Default{MAX_STANDARD_TX_WEIGHT}, "The maximum acceptable transaction weight.\n"1732"Transaction building will fail if this can not be satisfied."},1733},1734FundTxDoc()),1735RPCArgOptions{.oneline_description="options"}},1736{"bip32derivs", RPCArg::Type::BOOL, RPCArg::Default{true}, "Include BIP 32 derivation paths for public keys if we know them"},1737{"version", RPCArg::Type::NUM, RPCArg::Default{DEFAULT_WALLET_TX_VERSION}, "Transaction version"},1738{"psbt_version", RPCArg::Type::NUM, RPCArg::Default(2), "The PSBT version number to use."},1739},1740RPCResult{1741RPCResult::Type::OBJ, "", "",1742{1743{RPCResult::Type::STR, "psbt", "The resulting raw transaction (base64-encoded string)"},1744{RPCResult::Type::STR_AMOUNT, "fee", "Fee in " + CURRENCY_UNIT + " the resulting transaction pays"},1745{RPCResult::Type::NUM, "changepos", "The position of the added change output, or -1"},1746}1747},1748RPCExamples{1749"\nCreate a PSBT with automatically picked inputs that sends 0.5 BTC to an address and has a fee rate of 2 sat/vB:\n"1750+ HelpExampleCli("walletcreatefundedpsbt", "\"[]\" \"[{\\\"" + EXAMPLE_ADDRESS[0] + "\\\":0.5}]\" 0 \"{\\\"add_inputs\\\":true,\\\"fee_rate\\\":2}\"")