mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-01 09:35:52 -05:00
Merge a283dbd9c4
into 85f96b01b7
This commit is contained in:
commit
c9df413da1
11 changed files with 62 additions and 23 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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, "", "",
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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."},
|
||||
|
|
|
@ -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"},
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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')
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue