0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-01 09:35:52 -05:00
This commit is contained in:
Jon Atack 2025-02-01 00:05:57 +01:00 committed by GitHub
commit c9df413da1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 62 additions and 23 deletions

View file

@ -122,3 +122,21 @@ std::optional<OutputType> OutputTypeFromDestination(const CTxDestination& dest)
}
return std::nullopt;
}
std::vector<std::string> GetOutputTypes()
{
std::vector<std::string> v;
for (auto t : OUTPUT_TYPES) {
v.emplace_back("\"" + FormatOutputType(t) + "\"");
}
return v;
}
std::vector<std::string> GetLegacyOutputTypes()
{
std::vector<std::string> v;
for (auto t : LEGACY_TYPES) {
v.emplace_back("\"" + FormatOutputType(t) + "\"");
}
return v;
}

View file

@ -12,6 +12,7 @@
#include <array>
#include <optional>
#include <string>
#include <unordered_set>
#include <vector>
enum class OutputType {
@ -29,6 +30,16 @@ static constexpr auto OUTPUT_TYPES = std::array{
OutputType::BECH32M,
};
/** OutputTypes supported by the LegacyScriptPubKeyMan */
static constexpr auto LEGACY_TYPES = std::array{
OutputType::LEGACY,
OutputType::P2SH_SEGWIT,
OutputType::BECH32,
};
static const std::unordered_set<OutputType> LEGACY_OUTPUT_TYPES {
LEGACY_TYPES.begin(), LEGACY_TYPES.end()
};
std::optional<OutputType> ParseOutputType(const std::string& str);
const std::string& FormatOutputType(OutputType type);
@ -51,4 +62,7 @@ CTxDestination AddAndGetDestinationForScript(FlatSigningProvider& keystore, cons
/** Get the OutputType for a CTxDestination */
std::optional<OutputType> OutputTypeFromDestination(const CTxDestination& dest);
std::vector<std::string> GetOutputTypes();
std::vector<std::string> GetLegacyOutputTypes();
#endif // BITCOIN_OUTPUTTYPE_H

View file

@ -25,6 +25,8 @@
#include <tuple>
#include <vector>
using util::Join;
static RPCHelpMan validateaddress()
{
return RPCHelpMan{
@ -96,7 +98,7 @@ static RPCHelpMan createmultisig()
{
{"key", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "The hex-encoded public key"},
}},
{"address_type", RPCArg::Type::STR, RPCArg::Default{"legacy"}, "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
{"address_type", RPCArg::Type::STR, RPCArg::Default{"legacy"}, "The address type to use. Options are " + Join(GetLegacyOutputTypes(), ", ") + "."},
},
RPCResult{
RPCResult::Type::OBJ, "", "",

View file

@ -26,6 +26,7 @@
#include <walletinitinterface.h>
using node::NodeContext;
using util::Join;
namespace wallet {
class WalletInit : public WalletInitInterface
@ -46,11 +47,10 @@ public:
void WalletInit::AddWalletOptions(ArgsManager& argsman) const
{
argsman.AddArg("-addresstype", strprintf("What type of addresses to use (\"legacy\", \"p2sh-segwit\", \"bech32\", or \"bech32m\", default: \"%s\")", FormatOutputType(DEFAULT_ADDRESS_TYPE)), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
argsman.AddArg("-addresstype", strprintf("What type of addresses to use (%s), default: \"%s\")", Join(GetOutputTypes(), ", "), FormatOutputType(DEFAULT_ADDRESS_TYPE)), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
argsman.AddArg("-avoidpartialspends", strprintf("Group outputs by address, selecting many (possibly all) or none, instead of selecting on a per-output basis. Privacy is improved as addresses are mostly swept with fewer transactions and outputs are aggregated in clean change addresses. It may result in higher fees due to less optimal coin selection caused by this added limitation and possibly a larger-than-necessary number of inputs being used. Always enabled for wallets with \"avoid_reuse\" enabled, otherwise default: %u.", DEFAULT_AVOIDPARTIALSPENDS), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
argsman.AddArg("-changetype",
"What type of change to use (\"legacy\", \"p2sh-segwit\", \"bech32\", or \"bech32m\"). Default is \"legacy\" when "
"-addresstype=legacy, else it is an implementation detail.",
strprintf("What type of change to use (%s). Default is \"legacy\" when -addresstype=legacy, otherwise it is an implementation detail.", Join(GetOutputTypes(), ", ")),
ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
argsman.AddArg("-consolidatefeerate=<amt>", strprintf("The maximum feerate (in %s/kvB) at which transaction building may use more inputs than strictly necessary so that the wallet's UTXO pool can be reduced (default: %s).", CURRENCY_UNIT, FormatMoney(DEFAULT_CONSOLIDATE_FEERATE)), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
argsman.AddArg("-disablewallet", "Do not load the wallet and disable wallet RPC calls", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);

View file

@ -17,6 +17,8 @@
#include <univalue.h>
using util::Join;
namespace wallet {
RPCHelpMan getnewaddress()
{
@ -26,7 +28,7 @@ RPCHelpMan getnewaddress()
"so payments received with the address will be associated with 'label'.\n",
{
{"label", RPCArg::Type::STR, RPCArg::Default{""}, "The label name for the address to be linked to. It can also be set to the empty string \"\" to represent the default label. The label does not need to exist, it will be created if there is no label by the given name."},
{"address_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -addresstype"}, "The address type to use. Options are \"legacy\", \"p2sh-segwit\", \"bech32\", and \"bech32m\"."},
{"address_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -addresstype"}, "The address type to use. Options are " + Join(GetOutputTypes(), ", ") + "."},
},
RPCResult{
RPCResult::Type::STR, "address", "The new bitcoin address"
@ -76,7 +78,7 @@ RPCHelpMan getrawchangeaddress()
"\nReturns a new Bitcoin address, for receiving change.\n"
"This is for use with raw transactions, NOT normal use.\n",
{
{"address_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The address type to use. Options are \"legacy\", \"p2sh-segwit\", \"bech32\", and \"bech32m\"."},
{"address_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The address type to use. Options are " + Join(GetOutputTypes(), ", ") + "."},
},
RPCResult{
RPCResult::Type::STR, "address", "The address"
@ -232,7 +234,7 @@ RPCHelpMan addmultisigaddress()
},
},
{"label", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "A label to assign the addresses to."},
{"address_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -addresstype"}, "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
{"address_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -addresstype"}, "The address type to use. Options are " + Join(GetLegacyOutputTypes(), ", ") + "."},
},
RPCResult{
RPCResult::Type::OBJ, "", "",
@ -529,6 +531,7 @@ RPCHelpMan getaddressinfo()
RPCResult::Type::OBJ, "", "",
{
{RPCResult::Type::STR, "address", "The bitcoin address validated."},
{RPCResult::Type::STR, "address_type", "The type of bitcoin address; will be one of " + Join(GetOutputTypes(), ", ") + "."},
{RPCResult::Type::STR_HEX, "scriptPubKey", "The hex-encoded output script generated by the address."},
{RPCResult::Type::BOOL, "ismine", "If the address is yours."},
{RPCResult::Type::BOOL, "iswatchonly", "If the address is watchonly."},
@ -591,8 +594,8 @@ RPCHelpMan getaddressinfo()
UniValue ret(UniValue::VOBJ);
std::string currentAddress = EncodeDestination(dest);
ret.pushKV("address", currentAddress);
ret.pushKV("address", EncodeDestination(dest));
ret.pushKV("address_type", FormatOutputType(OutputTypeFromDestination(dest).value()));
CScript scriptPubKey = GetScriptForDestination(dest);
ret.pushKV("scriptPubKey", HexStr(scriptPubKey));

View file

@ -29,6 +29,7 @@ using common::InvalidEstimateModeErrorMessage;
using common::StringForFeeReason;
using common::TransactionErrorString;
using node::TransactionError;
using util::Join;
namespace wallet {
std::vector<CRecipient> CreateRecipients(const std::vector<std::pair<CTxDestination, CAmount>>& outputs, const std::set<int>& subtract_fee_outputs)
@ -763,7 +764,7 @@ RPCHelpMan fundrawtransaction()
{"maxconf", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "If add_inputs is specified, require inputs with at most this many confirmations."},
{"changeAddress", RPCArg::Type::STR, RPCArg::DefaultHint{"automatic"}, "The bitcoin address to receive the change"},
{"changePosition", RPCArg::Type::NUM, RPCArg::DefaultHint{"random"}, "The index of the change output"},
{"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", \"bech32\", and \"bech32m\"."},
{"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if changeAddress is not specified. Options are: " + Join(GetOutputTypes(), ", ") + "."},
{"includeWatching", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Also select inputs which are watch only.\n"
"Only solvable inputs can be used. Watch-only destinations are solvable if the public key and/or output script was imported,\n"
"e.g. with 'importpubkey' or 'importmulti' with the 'pubkeys' or 'desc' field."},
@ -1221,7 +1222,7 @@ RPCHelpMan send()
{"add_to_wallet", RPCArg::Type::BOOL, RPCArg::Default{true}, "When false, returns a serialized transaction which will not be added to the wallet or broadcast"},
{"change_address", RPCArg::Type::STR, RPCArg::DefaultHint{"automatic"}, "The bitcoin address to receive the change"},
{"change_position", RPCArg::Type::NUM, RPCArg::DefaultHint{"random"}, "The index of the change output"},
{"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if change_address is not specified. Options are \"legacy\", \"p2sh-segwit\", \"bech32\" and \"bech32m\"."},
{"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if change_address is not specified. Options are: " + Join(GetOutputTypes(), ", ") + "."},
{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB.", RPCArgOptions{.also_positional = true}},
{"include_watching", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Also select inputs which are watch only.\n"
"Only solvable inputs can be used. Watch-only destinations are solvable if the public key and/or output script was imported,\n"
@ -1700,7 +1701,7 @@ RPCHelpMan walletcreatefundedpsbt()
{"maxconf", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "If add_inputs is specified, require inputs with at most this many confirmations."},
{"changeAddress", RPCArg::Type::STR, RPCArg::DefaultHint{"automatic"}, "The bitcoin address to receive the change"},
{"changePosition", RPCArg::Type::NUM, RPCArg::DefaultHint{"random"}, "The index of the change output"},
{"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", \"bech32\", and \"bech32m\"."},
{"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if changeAddress is not specified. Options are: " + Join(GetOutputTypes(), ", ") + "."},
{"includeWatching", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Also select inputs which are watch only"},
{"lockUnspents", RPCArg::Type::BOOL, RPCArg::Default{false}, "Lock selected unspent outputs"},
{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},

View file

@ -21,6 +21,7 @@
#include <univalue.h>
using util::Join;
namespace wallet {
@ -930,7 +931,7 @@ static RPCHelpMan createwalletdescriptor()
"The address type must be one that the wallet does not already have a descriptor for."
+ HELP_REQUIRING_PASSPHRASE,
{
{"type", RPCArg::Type::STR, RPCArg::Optional::NO, "The address type the descriptor will produce. Options are \"legacy\", \"p2sh-segwit\", \"bech32\", and \"bech32m\"."},
{"type", RPCArg::Type::STR, RPCArg::Optional::NO, "The address type the descriptor will produce. Options are " + Join(GetOutputTypes(), ", ") + "."},
{"options", RPCArg::Type::OBJ_NAMED_PARAMS, RPCArg::Optional::OMITTED, "", {
{"internal", RPCArg::Type::BOOL, RPCArg::DefaultHint{"Both external and internal will be generated unless this parameter is specified"}, "Whether to only make one descriptor that is internal (if parameter is true) or external (if parameter is false)"},
{"hdkey", RPCArg::Type::STR, RPCArg::DefaultHint{"The HD key used by all other active descriptors"}, "The HD key that the wallet knows the private key of, listed using 'gethdkeys', to use for this descriptor's key"},

View file

@ -22,6 +22,7 @@
#include <optional>
using common::PSBTError;
using util::Join;
using util::ToString;
namespace wallet {
@ -31,7 +32,7 @@ const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000;
util::Result<CTxDestination> LegacyScriptPubKeyMan::GetNewDestination(const OutputType type)
{
if (LEGACY_OUTPUT_TYPES.count(type) == 0) {
return util::Error{_("Error: Legacy wallets only support the \"legacy\", \"p2sh-segwit\", and \"bech32\" address types")};
return util::Error{strprintf(_("Error: Legacy wallets only support the %s address types"), Join(GetLegacyOutputTypes(), ", "))};
}
assert(type != OutputType::BECH32M);
@ -305,7 +306,7 @@ bool LegacyScriptPubKeyMan::Encrypt(const CKeyingMaterial& master_key, WalletBat
util::Result<CTxDestination> LegacyScriptPubKeyMan::GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool)
{
if (LEGACY_OUTPUT_TYPES.count(type) == 0) {
return util::Error{_("Error: Legacy wallets only support the \"legacy\", \"p2sh-segwit\", and \"bech32\" address types")};
return util::Error{strprintf(_("Error: Legacy wallets only support the %s address types"), Join(GetLegacyOutputTypes(), ", "))};
}
assert(type != OutputType::BECH32M);

View file

@ -270,13 +270,6 @@ public:
boost::signals2::signal<void (const ScriptPubKeyMan* spkm, int64_t new_birth_time)> NotifyFirstKeyTimeChanged;
};
/** OutputTypes supported by the LegacyScriptPubKeyMan */
static const std::unordered_set<OutputType> LEGACY_OUTPUT_TYPES {
OutputType::LEGACY,
OutputType::P2SH_SEGWIT,
OutputType::BECH32,
};
class DescriptorScriptPubKeyMan;
// Manages the data for a LegacyScriptPubKeyMan.

View file

@ -126,7 +126,11 @@ class HelpRpcTest(BitcoinTestFramework):
f.write(self.nodes[0].help(call))
def wallet_help(self):
assert 'getnewaddress ( "label" "address_type" )' in self.nodes[0].help('getnewaddress')
assert '"legacy", "p2sh-segwit", "bech32", "bech32m".' in self.nodes[0].help('getaddressinfo')
assert '"legacy", "p2sh-segwit", "bech32".' in self.nodes[0].help('addmultisigaddress')
ret = self.nodes[0].help('getnewaddress')
assert '"legacy", "p2sh-segwit", "bech32", "bech32m".' in ret
assert 'getnewaddress ( "label" "address_type" )' in ret
self.restart_node(0, extra_args=['-nowallet=1'])
assert 'getnewaddress ( "label" "address_type" )' in self.nodes[0].help('getnewaddress')

View file

@ -104,6 +104,7 @@ class AddressTypeTest(BitcoinTestFramework):
info = self.nodes[node].getaddressinfo(address)
assert self.nodes[node].validateaddress(address)['isvalid']
assert_equal(info.get('solvable'), True)
assert_equal(info['address_type'], "legacy" if typ == "p2sh-segwit" else typ)
if not multisig and typ == 'legacy':
# P2PKH
@ -163,6 +164,7 @@ class AddressTypeTest(BitcoinTestFramework):
info = self.nodes[node].getaddressinfo(address)
assert 'desc' in info
assert_equal(info['desc'], utxo['desc'])
assert_equal(info['address_type'], "legacy" if typ == "p2sh-segwit" else typ)
assert self.nodes[node].validateaddress(address)['isvalid']
# Use a ridiculously roundabout way to find the key origin info through