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.
1// Copyright (c) 2017-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#include <rpc/util.h>7#include <arith_uint256.h>8#include <chain.h>9#include <common/args.h>10#include <common/messages.h>11#include <common/types.h>12#include <consensus/amount.h>13#include <core_io.h>14#include <crypto/hex_base.h>15#include <node/types.h>16#include <outputtype.h>17#include <pow.h>18#include <script/descriptor.h>19#include <script/signingprovider.h>20#include <script/solver.h>21#include <tinyformat.h>22#include <uint256.h>23#include <univalue.h>24#include <util/bip32.h>25#include <util/check.h>26#include <util/result.h>27#include <util/strencodings.h>28#include <util/string.h>29#include <util/translation.h>31#include <algorithm>32#include <iterator>33#include <memory>34#include <set>35#include <span>36#include <string_view>37#include <tuple>38#include <utility>40using common::PSBTError;41using common::PSBTErrorString;42using common::TransactionErrorString;43using node::TransactionError;44using util::Join;45using util::SplitString;46using util::TrimString;48const std::string UNIX_EPOCH_TIME = "UNIX epoch time";49const std::string EXAMPLE_ADDRESS[2] = {"bc1q09vm5lfy0j5reeulh4x5752q25uqqvz34hufdl", "bc1q02ad21edsxd23d32dfgqqsz4vv4nmtfzuklhy3"};51std::string GetAllOutputTypes()52{53std::vector<std::string> ret;54using U = std::underlying_type_t<TxoutType>;55for (U i = (U)TxoutType::NONSTANDARD; i <= (U)TxoutType::WITNESS_UNKNOWN; ++i) {56ret.emplace_back(GetTxnOutputType(static_cast<TxoutType>(i)));57}58return Join(ret, ", ");59}61void RPCTypeCheckObj(const UniValue& o,62const std::map<std::string, UniValueType>& typesExpected,63bool fAllowNull,64bool fStrict)65{66for (const auto& t : typesExpected) {67const UniValue& v = o.find_value(t.first);68if (!fAllowNull && v.isNull())69throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing %s", t.first));71if (!(t.second.typeAny || v.type() == t.second.type || (fAllowNull && v.isNull())))72throw JSONRPCError(RPC_TYPE_ERROR, strprintf("JSON value of type %s for field %s is not of expected type %s", uvTypeName(v.type()), t.first, uvTypeName(t.second.type)));73}75if (fStrict)76{77for (const std::string& k : o.getKeys())78{79if (!typesExpected.contains(k))80{81std::string err = strprintf("Unexpected key %s", k);82throw JSONRPCError(RPC_TYPE_ERROR, err);83}84}85}86}88int ParseVerbosity(const UniValue& arg, int default_verbosity, bool allow_bool)89{90if (!arg.isNull()) {91if (arg.isBool()) {92if (!allow_bool) {93throw JSONRPCError(RPC_TYPE_ERROR, "Verbosity was boolean but only integer allowed");94}95return arg.get_bool(); // true = 196} else {97return arg.getInt<int>();98}99}100return default_verbosity;101}103CAmount AmountFromValue(const UniValue& value, int decimals)104{105if (!value.isNum() && !value.isStr())106throw JSONRPCError(RPC_TYPE_ERROR, "Amount is not a number or string");107int64_t amount;108if (!ParseFixedPoint(value.getValStr(), decimals, &amount))109throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount");110if (!MoneyRange(amount))111throw JSONRPCError(RPC_TYPE_ERROR, "Amount out of range");112return amount;113}115CFeeRate ParseFeeRate(const UniValue& json)116{117CAmount val{AmountFromValue(json)};118if (val >= COIN) throw JSONRPCError(RPC_INVALID_PARAMETER, "Fee rates larger than or equal to 1BTC/kvB are not accepted");119return CFeeRate{val};120}122uint256 ParseHashV(const UniValue& v, std::string_view name)123{124const std::string& strHex(v.get_str());125if (auto rv{uint256::FromHex(strHex)}) return *rv;126if (auto expected_len{uint256::size() * 2}; strHex.length() != expected_len) {127throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s must be of length %d (not %d, for '%s')", name, expected_len, strHex.length(), strHex));128}129throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s must be hexadecimal string (not '%s')", name, strHex));130}131uint256 ParseHashO(const UniValue& o, std::string_view strKey)132{133return ParseHashV(o.find_value(strKey), strKey);134}135std::vector<unsigned char> ParseHexV(const UniValue& v, std::string_view name)136{137std::string strHex;138if (v.isStr())139strHex = v.get_str();140if (!IsHex(strHex))141throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s must be hexadecimal string (not '%s')", name, strHex));142return ParseHex(strHex);143}144std::vector<unsigned char> ParseHexO(const UniValue& o, std::string_view strKey)145{146return ParseHexV(o.find_value(strKey), strKey);147}149namespace {151/**152* Quote an argument for shell.153*154* @note This is intended for help, not for security-sensitive purposes.155*/156std::string ShellQuote(const std::string& s)157{158std::string result;159result.reserve(s.size() * 2);160for (const char ch: s) {161if (ch == '\'') {162result += "'\''";163} else {164result += ch;165}166}167return "'" + result + "'";168}170/**171* Shell-quotes the argument if it needs quoting, else returns it literally, to save typing.172*173* @note This is intended for help, not for security-sensitive purposes.174*/175std::string ShellQuoteIfNeeded(const std::string& s)176{177for (const char ch: s) {178if (ch == ' ' || ch == '\'' || ch == '"') {179return ShellQuote(s);180}181}183return s;184}186}188std::string HelpExampleCli(const std::string& methodname, const std::string& args)189{190return "> bitcoin-cli " + methodname + " " + args + "\n";191}193std::string HelpExampleCliNamed(const std::string& methodname, const RPCArgList& args)194{195std::string result = "> bitcoin-cli -named " + methodname;196for (const auto& argpair: args) {197const auto& value = argpair.second.isStr()198? argpair.second.get_str()199: argpair.second.write();200result += " " + argpair.first + "=" + ShellQuoteIfNeeded(value);201}202result += "\n";203return result;204}206std::string HelpExampleRpc(const std::string& methodname, const std::string& args)207{208return "> curl --user myusername --data-binary '{\"jsonrpc\": \"2.0\", \"id\": \"curltest\", "209"\"method\": \"" + methodname + "\", \"params\": [" + args + "]}' -H 'content-type: application/json' http://127.0.0.1:8332/\n";210}212std::string HelpExampleRpcNamed(const std::string& methodname, const RPCArgList& args)213{214UniValue params(UniValue::VOBJ);215for (const auto& param: args) {216params.pushKV(param.first, param.second);217}219return "> curl --user myusername --data-binary '{\"jsonrpc\": \"2.0\", \"id\": \"curltest\", "220"\"method\": \"" + methodname + "\", \"params\": " + params.write() + "}' -H 'content-type: application/json' http://127.0.0.1:8332/\n";221}223// Converts a hex string to a public key if possible224CPubKey HexToPubKey(const std::string& hex_in)225{226if (!IsHex(hex_in)) {227throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey \"" + hex_in + "\" must be a hex string");228}229if (hex_in.length() != 66 && hex_in.length() != 130) {230throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey \"" + hex_in + "\" must have a length of either 33 or 65 bytes");231}232CPubKey vchPubKey(ParseHex(hex_in));233if (!vchPubKey.IsFullyValid()) {234throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey \"" + hex_in + "\" must be cryptographically valid.");235}236return vchPubKey;237}239// Creates a multisig address from a given list of public keys, number of signatures required, and the address type240CTxDestination AddAndGetMultisigDestination(const int required, const std::vector<CPubKey>& pubkeys, OutputType type, FlatSigningProvider& keystore, CScript& script_out)241{242// Gather public keys243if (required < 1) {244throw JSONRPCError(RPC_INVALID_PARAMETER, "a multisignature address must require at least one key to redeem");245}246if ((int)pubkeys.size() < required) {247throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("not enough keys supplied (got %u keys, but need at least %d to redeem)", pubkeys.size(), required));248}249if (pubkeys.size() > MAX_PUBKEYS_PER_MULTISIG) {250throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Number of keys involved in the multisignature address creation > %d\nReduce the number", MAX_PUBKEYS_PER_MULTISIG));