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.
251throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");252}253pwallet->RefreshAllTXOs();255return UniValue::VNULL;256},257};258}260class DescribeWalletAddressVisitor261{262public:263const SigningProvider * const provider;265// NOLINTNEXTLINE(misc-no-recursion)266void ProcessSubScript(const CScript& subscript, UniValue& obj) const267{268// Always present: script type and redeemscript269std::vector<std::vector<unsigned char>> solutions_data;270TxoutType which_type = Solver(subscript, solutions_data);271obj.pushKV("script", GetTxnOutputType(which_type));272obj.pushKV("hex", HexStr(subscript));274CTxDestination embedded;275if (ExtractDestination(subscript, embedded)) {276// Only when the script corresponds to an address.277UniValue subobj(UniValue::VOBJ);278UniValue detail = DescribeAddress(embedded);279subobj.pushKVs(std::move(detail));280UniValue wallet_detail = std::visit(*this, embedded);281subobj.pushKVs(std::move(wallet_detail));282subobj.pushKV("address", EncodeDestination(embedded));283subobj.pushKV("scriptPubKey", HexStr(subscript));284// Always report the pubkey at the top level, so that `getnewaddress()['pubkey']` always works.285if (subobj.exists("pubkey")) obj.pushKV("pubkey", subobj["pubkey"]);286obj.pushKV("embedded", std::move(subobj));287} else if (which_type == TxoutType::MULTISIG) {288// Also report some information on multisig scripts (which do not have a corresponding address).289obj.pushKV("sigsrequired", solutions_data[0][0]);290UniValue pubkeys(UniValue::VARR);291for (size_t i = 1; i < solutions_data.size() - 1; ++i) {292CPubKey key(solutions_data[i].begin(), solutions_data[i].end());293pubkeys.push_back(HexStr(key));294}295obj.pushKV("pubkeys", std::move(pubkeys));296}297}299explicit DescribeWalletAddressVisitor(const SigningProvider* _provider) : provider(_provider) {}301UniValue operator()(const CNoDestination& dest) const { return UniValue(UniValue::VOBJ); }302UniValue operator()(const PubKeyDestination& dest) const { return UniValue(UniValue::VOBJ); }304UniValue operator()(const PKHash& pkhash) const305{306CKeyID keyID{ToKeyID(pkhash)};307UniValue obj(UniValue::VOBJ);308CPubKey vchPubKey;309if (provider && provider->GetPubKey(keyID, vchPubKey)) {310obj.pushKV("pubkey", HexStr(vchPubKey));311obj.pushKV("iscompressed", vchPubKey.IsCompressed());312}313return obj;314}316// NOLINTNEXTLINE(misc-no-recursion)317UniValue operator()(const ScriptHash& scripthash) const318{319UniValue obj(UniValue::VOBJ);320CScript subscript;321if (provider && provider->GetCScript(ToScriptID(scripthash), subscript)) {322ProcessSubScript(subscript, obj);323}324return obj;325}327UniValue operator()(const WitnessV0KeyHash& id) const328{329UniValue obj(UniValue::VOBJ);330CPubKey pubkey;331if (provider && provider->GetPubKey(ToKeyID(id), pubkey)) {332obj.pushKV("pubkey", HexStr(pubkey));333}334return obj;335}337// NOLINTNEXTLINE(misc-no-recursion)338UniValue operator()(const WitnessV0ScriptHash& id) const339{340UniValue obj(UniValue::VOBJ);341CScript subscript;342CRIPEMD160 hasher;343uint160 hash;344hasher.Write(id.begin(), 32).Finalize(hash.begin());345if (provider && provider->GetCScript(CScriptID(hash), subscript)) {346ProcessSubScript(subscript, obj);347}348return obj;349}351UniValue operator()(const WitnessV1Taproot& id) const { return UniValue(UniValue::VOBJ); }352UniValue operator()(const PayToAnchor& id) const { return UniValue(UniValue::VOBJ); }353UniValue operator()(const WitnessUnknown& id) const { return UniValue(UniValue::VOBJ); }354};356static UniValue DescribeWalletAddress(const CWallet& wallet, const CTxDestination& dest)357{358UniValue ret(UniValue::VOBJ);359UniValue detail = DescribeAddress(dest);360CScript script = GetScriptForDestination(dest);361std::unique_ptr<SigningProvider> provider = nullptr;362provider = wallet.GetSolvingProvider(script);363ret.pushKVs(std::move(detail));364ret.pushKVs(std::visit(DescribeWalletAddressVisitor(provider.get()), dest));365return ret;366}368static std::vector<RPCResult> GetAddressInfoBaseFields()369{370return {371{RPCResult::Type::STR, "address", /*optional=*/true, "The bitcoin address of the embedded script."},372{RPCResult::Type::STR_HEX, "scriptPubKey", /*optional=*/true, "The hex-encoded output script generated by the address."},373{RPCResult::Type::BOOL, "isscript", /*optional=*/true, "If the key is a script."},374{RPCResult::Type::BOOL, "iswitness", /*optional=*/true, "If the address is a witness address."},375{RPCResult::Type::NUM, "witness_version", /*optional=*/true, "The version number of the witness program."},376{RPCResult::Type::STR_HEX, "witness_program", /*optional=*/true, "The hex value of the witness program."},377{RPCResult::Type::STR, "script", /*optional=*/true,378"The output script type. Only if isscript is true and the redeemscript is known. Possible\n"379"types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_keyhash,\n"380"witness_v0_scripthash, witness_unknown."},381{RPCResult::Type::STR_HEX, "hex", /*optional=*/true, "The redeemscript for the p2sh address."},382{RPCResult::Type::ARR, "pubkeys", /*optional=*/true,383"Array of pubkeys associated with the known redeemscript (only if script is multisig).",384{385{RPCResult::Type::STR, "pubkey", ""},386}},387{RPCResult::Type::NUM, "sigsrequired", /*optional=*/true,388"The number of signatures required to spend multisig output (only if script is multisig)."},389{RPCResult::Type::STR_HEX, "pubkey", /*optional=*/true,390"The hex value of the raw public key for single-key addresses (possibly embedded in P2SH or P2WSH)."},391{RPCResult::Type::BOOL, "iscompressed", /*optional=*/true, "If the pubkey is compressed."},392};393}395static std::vector<RPCResult> GetAddressInfoEmbeddedFields(bool include_nested)396{397auto fields = GetAddressInfoBaseFields();399if (include_nested) {400auto nested = GetAddressInfoBaseFields();401fields.emplace_back(402RPCResult::Type::OBJ,403"embedded",404/*optional=*/true,405"Information about the address embedded in P2SH or P2WSH, if relevant and known.",406std::move(nested)407);408}410return fields;411}413RPCMethod getaddressinfo()414{415return RPCMethod{416"getaddressinfo",417"Return information about the given bitcoin address.\n"418"Some of the information will only be present if the address is in the active wallet.\n",419{420{"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address for which to get information."},421},422RPCResult{423RPCResult::Type::OBJ, "", "",424{425{RPCResult::Type::STR, "address", "The bitcoin address validated."},426{RPCResult::Type::STR_HEX, "scriptPubKey", "The hex-encoded output script generated by the address."},427{RPCResult::Type::BOOL, "ismine", "If the address is yours."},428{RPCResult::Type::BOOL, "iswatchonly", "(DEPRECATED) Always false."},429{RPCResult::Type::BOOL, "solvable", "If we know how to spend coins sent to this address, ignoring the possible lack of private keys."},430{RPCResult::Type::STR, "desc", /*optional=*/true, "A descriptor for spending coins sent to this address (only when solvable)."},431{RPCResult::Type::STR, "parent_desc", /*optional=*/true, "The descriptor used to derive this address if this is a descriptor wallet"},432{RPCResult::Type::BOOL, "isscript", /*optional=*/true, "If the key is a script."},433{RPCResult::Type::BOOL, "ischange", "If the address was used for change output."},434{RPCResult::Type::BOOL, "iswitness", "If the address is a witness address."},435{RPCResult::Type::NUM, "witness_version", /*optional=*/true, "The version number of the witness program."},436{RPCResult::Type::STR_HEX, "witness_program", /*optional=*/true, "The hex value of the witness program."},437{RPCResult::Type::STR, "script", /*optional=*/true, "The output script type. Only if isscript is true and the redeemscript is known. Possible\n"438"types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_keyhash,\n"439"witness_v0_scripthash, witness_unknown."},440{RPCResult::Type::STR_HEX, "hex", /*optional=*/true, "The redeemscript for the p2sh address."},441{RPCResult::Type::ARR, "pubkeys", /*optional=*/true, "Array of pubkeys associated with the known redeemscript (only if script is multisig).",442{443{RPCResult::Type::STR, "pubkey", ""},444}},445{RPCResult::Type::NUM, "sigsrequired", /*optional=*/true, "The number of signatures required to spend multisig output (only if script is multisig)."},446{RPCResult::Type::STR_HEX, "pubkey", /*optional=*/true, "The hex value of the raw public key for single-key addresses (possibly embedded in P2SH or P2WSH)."},447{RPCResult::Type::OBJ, "embedded", /*optional=*/true,448"Information about the address embedded in P2SH or P2WSH, if relevant and known.",449ElideGroup(450GetAddressInfoEmbeddedFields(/*include_nested=*/true),451"Includes all getaddressinfo output fields for the embedded address, excluding metadata (timestamp, hdkeypath, hdseedid)\n"452"and relation to the wallet (ismine)."453)},454{RPCResult::Type::BOOL, "iscompressed", /*optional=*/true, "If the pubkey is compressed."},455{RPCResult::Type::NUM_TIME, "timestamp", /*optional=*/true, "The creation time of the key, if available, expressed in " + UNIX_EPOCH_TIME + "."},456{RPCResult::Type::STR, "hdkeypath", /*optional=*/true, "The HD keypath, if the key is HD and available."},457{RPCResult::Type::STR_HEX, "hdseedid", /*optional=*/true, "The Hash160 of the HD seed."},458{RPCResult::Type::STR_HEX, "hdmasterfingerprint", /*optional=*/true, "The fingerprint of the master key."},459{RPCResult::Type::ARR, "labels", "Array of labels associated with the address. Currently limited to one label but returned\n"460"as an array to keep the API stable if multiple labels are enabled in the future.",461{462{RPCResult::Type::STR, "label name", "Label name (defaults to \"\")."},463}},464}465},466RPCExamples{467HelpExampleCli("getaddressinfo", "\"" + EXAMPLE_ADDRESS[0] + "\"") +468HelpExampleRpc("getaddressinfo", "\"" + EXAMPLE_ADDRESS[0] + "\"")469},470[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue471{472const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);473if (!pwallet) return UniValue::VNULL;475LOCK(pwallet->cs_wallet);477std::string error_msg;478CTxDestination dest = DecodeDestination(request.params[0].get_str(), error_msg);480// Make sure the destination is valid481if (!IsValidDestination(dest)) {482// Set generic error message in case 'DecodeDestination' didn't set it483if (error_msg.empty()) error_msg = "Invalid address";485throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error_msg);486}488UniValue ret(UniValue::VOBJ);490std::string currentAddress = EncodeDestination(dest);491ret.pushKV("address", currentAddress);493CScript scriptPubKey = GetScriptForDestination(dest);494ret.pushKV("scriptPubKey", HexStr(scriptPubKey));496std::unique_ptr<SigningProvider> provider = pwallet->GetSolvingProvider(scriptPubKey);498bool mine = pwallet->IsMine(dest);499ret.pushKV("ismine", mine);