New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SegWit wallet support #11403
SegWit wallet support #11403
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Light review, it would be nice to push base PR's.
src/wallet/wallet.cpp
Outdated
CKeyID CWallet::GetKeyForDestination(const CTxDestination& dest) const | ||
{ | ||
// Only supports P2PKH, P2WPKH, P2SH-P2WPKH. | ||
if (boost::get<CKeyID>(&dest)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In commit Expose method to find key for a single-key destination:
Use boost::apply_visitor
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried that, but the result is much longer and harder to get right (see below). It's also the wrong approach I think. A visitor is used when you want to handle all possible types - here we specifically only want to support a specific subset of cases (P2PKH, P2WPKH, P2SH-P2WPKH).
src/wallet/wallet.cpp
Outdated
CScript script; | ||
CTxDestination inner_dest; | ||
if (GetCScript(boost::get<CScriptID>(dest), script) && ExtractDestination(script, inner_dest)) { | ||
if (boost::get<WitnessV0KeyHash>(&inner_dest)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In commit Expose method to find key for a single-key destination:
Recursive call?
return GetKeyForDestination(inner_dest);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not that easy, as it could match a superset (for example P2SH-P2PKH), or even invalid things (P2SH-P2SH-P2WPKH?).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right.
Isn't boost::get kind of expensive? Avoid 2nd call?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's very cheap - look at the tag, and return the argument with a cast.
src/wallet/wallet.cpp
Outdated
@@ -4072,3 +4074,82 @@ CKeyID CWallet::GetKeyForDestination(const CTxDestination& dest) const | |||
} | |||
return CKeyID(); | |||
} | |||
|
|||
static const std::string STYLE_STRING_NONE = ""; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In commit SegWit wallet support:
Remove?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
src/wallet/init.cpp
Outdated
std::string style = gArgs.GetArg("-addressstyle", "default"); | ||
OutputStyle parsed_style = ParseStyle(style); | ||
if (parsed_style == STYLE_NONE) { | ||
return InitError(strprintf(_("Unknown address style '%s'"), style)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add init tests (follow up maybe)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will add those later.
src/wallet/rpcwallet.cpp
Outdated
"\nReturns a new Bitcoin address, for receiving change.\n" | ||
"This is for use with raw transactions, NOT normal use.\n" | ||
"\nArguments:\n" | ||
"1. \"style\" (string, optional) The address style to use. Valid options are 'p2pkh', 'p2sh_p2wpkh', and 'p2wpkh'\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing default value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added.
src/wallet/rpcwallet.cpp
Outdated
if (!request.params[1].isNull()) { | ||
style = ParseStyle(request.params[1].get_str()); | ||
if (style == STYLE_NONE) { | ||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address style '%s'", request.params[1].get_str())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing test for this error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will add later.
src/wallet/rpcwallet.cpp
Outdated
"\nReturns a new Bitcoin address for receiving payments.\n" | ||
"If 'account' is specified (DEPRECATED), it is added to the address book \n" | ||
"so payments received with the address will be credited to 'account'.\n" | ||
"\nArguments:\n" | ||
"1. \"account\" (string, optional) DEPRECATED. The account name for the address to be linked to. If not provided, the default account \"\" is used. It can also be set to the empty string \"\" to represent the default account. The account does not need to exist, it will be created if there is no account by the given name.\n" | ||
"2. \"style\" (string, optional) The address style to use. Valid options are 'p2pkh', 'p2sh_p2wpkh', and 'p2wpkh'\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Default value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added.
src/wallet/init.cpp
Outdated
style = gArgs.GetArg("-changestyle", style); | ||
parsed_style = ParseStyle(style); | ||
if (parsed_style == STYLE_NONE) { | ||
return InitError(strprintf(_("Unknown change style '%s'"), style)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add init tests (follow up maybe)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will add those later.
src/wallet/rpcwallet.cpp
Outdated
if (!request.params[0].isNull()) { | ||
style = ParseStyle(request.params[1].get_str()); | ||
if (style == STYLE_NONE) { | ||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address style '%s'", request.params[0].get_str())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will add.
test/functional/segwit.py
Outdated
self.nodes[i].addwitnessaddress(newaddress) | ||
self.nodes[i].addwitnessaddress(multiaddress) | ||
multiscript = CScript([OP_1, hex_str_to_bytes(self.pubkey[-1]), OP_1, OP_CHECKMULTISIG]) | ||
p2sh_addr = self.nodes[i].addwitnessaddress(newaddress, True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove , True
so that default value is tested.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
src/wallet/init.cpp
Outdated
@@ -15,6 +15,8 @@ | |||
std::string GetWalletHelpString(bool showDebug) | |||
{ | |||
std::string strUsage = HelpMessageGroup(_("Wallet options:")); | |||
strUsage += HelpMessageOpt("-addressstyle", _("What style addresses to use (\"p2pkh\", \"p2sh_p2wpkh\", \"p2wpkh\")")); | |||
strUsage += HelpMessageOpt("-changestyle", _("What style change to use (\"p2pkh\", \"p2sh_p2wpkh\", \"p2wpkh\")")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should mention the defaults, which likely means refactoring how the "default" string is handled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added explanation of defaults.
src/wallet/wallet.cpp
Outdated
if (style == STYLE_STRING_LEGACY) { | ||
return STYLE_LEGACY; | ||
} else if (style == STYLE_STRING_P2SH || style == "default") { | ||
return STYLE_P2SH; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Default should probably remain legacy until support for newer styles is complete (eg, import*
RPC)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather not. This makes the existing tests far more powerful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tests don't need to (and probably shouldn't) rely on defaults...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes and no.
I think that many tests, which are primarily testing things unrelated to addresses, should use the default address type. They don't strictly rely on them, but it's better if they work with either type, and it's certainly easier to not need to change all of them.
src/wallet/rpcwallet.cpp
Outdated
"\nReturns a new Bitcoin address for receiving payments.\n" | ||
"If 'account' is specified (DEPRECATED), it is added to the address book \n" | ||
"so payments received with the address will be credited to 'account'.\n" | ||
"\nArguments:\n" | ||
"1. \"account\" (string, optional) DEPRECATED. The account name for the address to be linked to. If not provided, the default account \"\" is used. It can also be set to the empty string \"\" to represent the default account. The account does not need to exist, it will be created if there is no account by the given name.\n" | ||
"2. \"style\" (string, optional) The address style to use. Valid options are 'p2pkh', 'p2sh_p2wpkh', and 'p2wpkh'\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like it would be better to change the deprecated "account"
into a JSON Object options
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that should be done separately.
A potential problem with supporting |
maybe it should be renamed to |
8213838 [Qt] tolerate BIP173/bech32 addresses during input validation (Jonas Schnelli) 06eaca6 [RPC] Wallet: test importing of native witness scripts (NicolasDorier) fd0041a Use BIP173 addresses in segwit.py test (Pieter Wuille) e278f12 Support BIP173 in addwitnessaddress (Pieter Wuille) c091b99 Implement BIP173 addresses and tests (Pieter Wuille) bd355b8 Add regtest testing to base58_tests (Pieter Wuille) 6565c55 Convert base58_tests from type/payload to scriptPubKey comparison (Pieter Wuille) 8fd2267 Import Bech32 C++ reference code & tests (Pieter Wuille) 1e46ebd Implement {Encode,Decode}Destination without CBitcoinAddress (Pieter Wuille) Pull request description: Builds on top of #11117. This adds support for: * Creating BIP173 addresses for testing (through `addwitnessaddress`, though by default it still produces P2SH versions) * Sending to BIP173 addresses (including non-v0 ones) * Analysing BIP173 addresses (through `validateaddress`) It includes a reformatted version of the [C++ Bech32 reference code](https://github.com/sipa/bech32/tree/master/ref/c%2B%2B) and an independent implementation of the address encoding/decoding logic (integrated with CTxDestination). All BIP173 test vectors are included. Not included (and intended for other PRs): * Full wallet support for SegWit (which would include automatically adding witness scripts to the wallet during automatic keypool topup, SegWit change outputs, ...) [see #11403] * Splitting base58.cpp and tests/base58_tests.cpp up into base58-specific code, and "address encoding"-code [see #11372] * Error locating in UI for BIP173 addresses. Tree-SHA512: 238031185fd07f3ac873c586043970cc2db91bf7735c3c168cb33a3db39a7bda81d4891b649685bb17ef90dc63af0328e7705d8cd3e8dafd6c4d3c08fb230341
Needs rebase after #11167 merge but that'll make it clearer what's new here to review 👍 |
src/rpc/misc.cpp
Outdated
@@ -64,6 +67,13 @@ class DescribeAddressVisitor : public boost::static_visitor<UniValue> | |||
obj.push_back(Pair("script", GetTxnOutputType(whichType))); | |||
obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end()))); | |||
UniValue a(UniValue::VARR); | |||
if (whichType == TX_WITNESS_V0_KEYHASH || whichType == TX_WITNESS_V0_SCRIPTHASH) { | |||
UniValue subobj = boost::apply_visitor(*this, addresses[0]); | |||
obj.push_back(Pair("embedded", std::move(subobj))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This field needs to be added anywhere it's used in help text for RPC calls.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You might want to copy the field to the help text rather than move it, though :p
(Use after move here)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
src/wallet/wallet.h
Outdated
@@ -1111,6 +1111,9 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface | |||
* have all private keys. This is unrelated to whether we consider this | |||
* output to be ours. */ | |||
bool IsSolvable(const CScript& script) const; | |||
|
|||
/** Return the hashes of the keys involved in a script. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove plurals from description.
a3a79cd
to
20da344
Compare
Rebased after #11167 merge. |
src/wallet/wallet.cpp
Outdated
|
||
CKeyID CWallet::GetKeyForDestination(const CTxDestination& dest) const | ||
{ | ||
// Only supports P2PKH, P2WPKH, P2SH-P2WPKH. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pedantic nit, but this only supports v0 of each witness version
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've always considered P2WPKH as specifically referring to v0 20-byte witness programs, and P2WSH as v0 32-byte ones. We'll need to come up with even clumsier names later ;)
src/wallet/rpcwallet.cpp
Outdated
"\nReturns a new Bitcoin address for receiving payments.\n" | ||
"If 'account' is specified (DEPRECATED), it is added to the address book \n" | ||
"so payments received with the address will be credited to 'account'.\n" | ||
"\nArguments:\n" | ||
"1. \"account\" (string, optional) DEPRECATED. The account name for the address to be linked to. If not provided, the default account \"\" is used. It can also be set to the empty string \"\" to represent the default account. The account does not need to exist, it will be created if there is no account by the given name.\n" | ||
"2. \"style\" (string, optional) The address style to use. Valid options are 'p2pkh', 'p2sh_p2wpkh', and 'p2wpkh'\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
startup options strings being different than getnewaddress options is a bit odd to me?
'p2sh_p2wpkh' vs p2sh
etc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed. Standardized on 'legacy', 'p2sh', and 'bech32'. It's not entirely accurate, as P2SH is a scriptPubKey type and not its address encoding, but meh - they're probably the most recognizable names.
src/wallet/wallet.cpp
Outdated
@@ -43,6 +43,8 @@ CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE); | |||
unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET; | |||
bool bSpendZeroConfChange = DEFAULT_SPEND_ZEROCONF_CHANGE; | |||
bool fWalletRbf = DEFAULT_WALLET_RBF; | |||
OutputStyle address_style = STYLE_P2SH; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No solution off the top of my head, but it makes sense that this would be set per-wallet. If not, could we name it g_address_style
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed as a global now, as we don't really have a way to configure it per wallet. Can be revised if there ever is.
src/wallet/init.cpp
Outdated
address_style = parsed_style; | ||
} | ||
|
||
style = gArgs.GetArg("-changestyle", style); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changestyle needs a test
src/wallet/rpcwallet.cpp
Outdated
"\nReturns a new Bitcoin address, for receiving change.\n" | ||
"This is for use with raw transactions, NOT normal use.\n" | ||
"\nArguments:\n" | ||
"1. \"style\" (string, optional) The address style to use. Valid options are 'p2pkh', 'p2sh_p2wpkh', and 'p2wpkh'\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
argument needs a test
src/wallet/rpcwallet.cpp
Outdated
@@ -1234,7 +1254,7 @@ UniValue addwitnessaddress(const JSONRPCRequest& request) | |||
|
|||
{ | |||
LOCK(cs_main); | |||
if (!IsWitnessEnabled(chainActive.Tip(), Params().GetConsensus()) && !gArgs.GetBoolArg("-walletprematurewitness", false)) { | |||
if (!IsWitnessEnabled(pindexBestHeader, Params().GetConsensus()) && !gArgs.GetBoolArg("-walletprematurewitness", false)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change seems way out of place here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
src/wallet/wallet.cpp
Outdated
@@ -43,6 +43,8 @@ CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE); | |||
unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET; | |||
bool bSpendZeroConfChange = DEFAULT_SPEND_ZEROCONF_CHANGE; | |||
bool fWalletRbf = DEFAULT_WALLET_RBF; | |||
OutputStyle address_style = STYLE_P2SH; | |||
OutputStyle change_style = STYLE_P2SH; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same suggestion as address_style
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
20da344
to
5632374
Compare
Regarding petertodd's concern, I think something like flack's suggestion would address it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK 5632374f2f71bca384ceed07ca6842fd87102346
src/wallet/wallet.cpp
Outdated
static const std::string STYLE_STRING_NONE = ""; | ||
static const std::string STYLE_STRING_LEGACY = "legacy"; | ||
static const std::string STYLE_STRING_P2SH = "p2sh"; | ||
static const std::string STYLE_STRING_SEGWIT = "segwit"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The help for e.g. getnewaddress
says "p2wpkh"
etc. One or the other needs to be changed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, I think it's consistent now.
src/wallet/rpcwallet.cpp
Outdated
throw std::runtime_error( | ||
"getnewaddress ( \"account\" )\n" | ||
"getnewaddress ( \"account\" ) ( \"style\" )\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you want "getnewaddress ( \"account\" \"style\" )\n"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
src/wallet/rpcwallet.cpp
Outdated
throw std::runtime_error( | ||
"getnewaddress ( \"account\" )\n" | ||
"getnewaddress ( \"account\" ) ( \"style\" )\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't just be tacked on the end. Accounts are deprecated. Just replace "account" with an options Object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would be API breaking for a lot of parties which is at odds with rapid deployment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't just be tacked on the end. Accounts are deprecated. Just replace "account" with an options Object.
In this particular context, account will just be renamed to label, rather than removed entirely. (At least this is what #11536 does.)
5632374
to
f542dae
Compare
src/script/standard.h
Outdated
struct WitnessV0KeyHash : public uint160 | ||
{ | ||
public: | ||
WitnessV0KeyHash() : uint160() {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could instead inherit the ctors from uint160/uint256 to shortcut the construction from WitnessV0KeyHash(uint160(foo)
to WitnessV0KeyHash(foo)
:
using uint160::uint160;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a few more comments.
I suspect I'm missing something about the generic-ish functions in CWallet. Do you maybe have plans to make those per-wallet as @instagibbs suggested?
src/rpc/misc.cpp
Outdated
if (whichType == TX_WITNESS_V0_KEYHASH || whichType == TX_WITNESS_V0_SCRIPTHASH) { | ||
UniValue subobj = boost::apply_visitor(*this, addresses[0]); | ||
obj.push_back(Pair("embedded", std::move(subobj))); | ||
if (subobj.exists("pubkey")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why dupe this? Helps with existing tooling?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, tests that expect to see a pubkey
field when calling validateaddress
on the output of getnewaddress
.
src/wallet/wallet.cpp
Outdated
CKeyID CWallet::GetKeyForDestination(const CTxDestination& dest) const | ||
{ | ||
// Only supports P2PKH, P2WPKH, P2SH-P2WPKH. | ||
if (boost::get<CKeyID>(&dest)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
imo, it's clearer (and less redundant) to test the result of the assignment:
if (const CKeyID* ret = boost::get<CKeyID>(&dest)) {
return *ret;
}
Edit: That's also the common paradigm for using std::weak_ptr::lock()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
src/keystore.cpp
Outdated
if (pubkey.IsCompressed()) { | ||
CScript script = CScript() << OP_0 << ToByteVector(pubkey.GetID()); | ||
// This does not use AddCScript, as it may be overridden. | ||
mapScripts[CScriptID(script)] = std::move(script); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about the sequencing rules here. I'd feel safer with a temporary CScriptID.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ugh, thanks for pointing that out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about the sequencing rules here. I'd feel safer with a temporary CScriptID.
For the record, there should be no issue here. std::move just does an rvalue reference cast to influence template deduction and function overloading. It doesn't actually actually move anything or do anything else at runtime.
src/wallet/wallet.cpp
Outdated
// if we were to have the private keys. This is just to make sure that the script is valid and that, | ||
// if found in a transaction, we would still accept and relay that transaction. In particular, | ||
// it will reject witness outputs that require signing with an uncompressed public key. | ||
DummySignatureCreator creator(this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't this pass in nullptr and move out of CWallet? Unless I'm missing something, it's not actually related.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved to script/signer.
src/wallet/wallet.cpp
Outdated
} | ||
} | ||
|
||
CTxDestination CWallet::GetDestinationForKey(const CPubKey& key, OutputStyle style) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If IsSolvable moves out of CWallet, I believe these can too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. IsSolvable is moved to script/sign, GetDestinationForKey is moved to keystore.
src/wallet/wallet.cpp
Outdated
CScript witprog = GetScriptForDestination(witdest); | ||
// Check if the resulting program is solvable (i.e. doesn't use an uncompressed key) | ||
if (!IsSolvable(witprog)) return CScriptID(script); | ||
AddCScript(witprog); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems the caller should be responsible for adding this if it's a WitnessV0ScriptHash? Like the others, this doesn't seem like wallet functionality to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it's ugly. I don't immediately see a nicer solution though, except for a callback to pass in, or duplicating part of this function just to find the correct program.
Note that if it weren't for the implicitly-know-about-witness-versions-of-keys logic, an equivalent line would be needed in GetDestinationForKey or its callers.
The wallet probably needs to be able to generate both For example, I might send an email requesting payment to a So rather than I think this was brought up elsewhere, but If |
@Sjors There is an RPC argument added to address-creating RPCs to override the default. |
@sipa I see, perhaps |
… GetAccountDestination
… GetAccountDestination
… GetAccountDestination
… GetAccountDestination
… safety 9c8eca7 Split up key and script metadata for better type safety (Russell Yanofsky) Pull request description: Suggested by @TheBlueMatt bitcoin#11403 (comment) Combining the maps was probably never a good arrangement but is more problematic now in presence of WitnessV0ScriptHash and WitnessV0KeyHash types. Tree-SHA512: 9263e9c01090fb49221e91d88a88241a9691dda3e92d86041c8e284306a64d3af5e2438249f9dcc3e6e4a5c11c1a89f975a86d55690adf95bf2636f15f99f92a
… safety 9c8eca7 Split up key and script metadata for better type safety (Russell Yanofsky) Pull request description: Suggested by @TheBlueMatt bitcoin#11403 (comment) Combining the maps was probably never a good arrangement but is more problematic now in presence of WitnessV0ScriptHash and WitnessV0KeyHash types. Tree-SHA512: 9263e9c01090fb49221e91d88a88241a9691dda3e92d86041c8e284306a64d3af5e2438249f9dcc3e6e4a5c11c1a89f975a86d55690adf95bf2636f15f99f92a
… safety 9c8eca7 Split up key and script metadata for better type safety (Russell Yanofsky) Pull request description: Suggested by @TheBlueMatt bitcoin#11403 (comment) Combining the maps was probably never a good arrangement but is more problematic now in presence of WitnessV0ScriptHash and WitnessV0KeyHash types. Tree-SHA512: 9263e9c01090fb49221e91d88a88241a9691dda3e92d86041c8e284306a64d3af5e2438249f9dcc3e6e4a5c11c1a89f975a86d55690adf95bf2636f15f99f92a
… safety 9c8eca7 Split up key and script metadata for better type safety (Russell Yanofsky) Pull request description: Suggested by @TheBlueMatt bitcoin#11403 (comment) Combining the maps was probably never a good arrangement but is more problematic now in presence of WitnessV0ScriptHash and WitnessV0KeyHash types. Tree-SHA512: 9263e9c01090fb49221e91d88a88241a9691dda3e92d86041c8e284306a64d3af5e2438249f9dcc3e6e4a5c11c1a89f975a86d55690adf95bf2636f15f99f92a
… safety 9c8eca7 Split up key and script metadata for better type safety (Russell Yanofsky) Pull request description: Suggested by @TheBlueMatt bitcoin#11403 (comment) Combining the maps was probably never a good arrangement but is more problematic now in presence of WitnessV0ScriptHash and WitnessV0KeyHash types. Tree-SHA512: 9263e9c01090fb49221e91d88a88241a9691dda3e92d86041c8e284306a64d3af5e2438249f9dcc3e6e4a5c11c1a89f975a86d55690adf95bf2636f15f99f92a
… safety 9c8eca7 Split up key and script metadata for better type safety (Russell Yanofsky) Pull request description: Suggested by @TheBlueMatt bitcoin#11403 (comment) Combining the maps was probably never a good arrangement but is more problematic now in presence of WitnessV0ScriptHash and WitnessV0KeyHash types. Tree-SHA512: 9263e9c01090fb49221e91d88a88241a9691dda3e92d86041c8e284306a64d3af5e2438249f9dcc3e6e4a5c11c1a89f975a86d55690adf95bf2636f15f99f92a
…s_type, g_change_type f765bb3 Fix ListCoins test failure due to unset g_address_type, g_change_type (Russell Yanofsky) Pull request description: New global variables were introduced in bitcoin#11403 and not setting them causes: ``` test_bitcoin: wallet/wallet.cpp:4199: CTxDestination GetDestinationForKey(const CPubKey&, OutputType): Assertion `false' failed. unknown location(0): fatal error in "ListCoins": signal: SIGABRT (application abort requested) ``` It's possible to reproduce the failure reliably by running: ``` src/test/test_bitcoin --log_level=test_suite --run_test=wallet_tests/ListCoins ``` Failures happen nondeterministically because boost test framework doesn't run tests in a specified order, and tests that run previously can set the global variables and mask the bug. Example travis failure: https://travis-ci.org/bitcoin/bitcoin/builds/327642495 Tree-SHA512: 3e0875716f66bc0304cf92a26457e6b54ecfe15ed962f4343577b05fc56bb577554422b7f53949ad6085ac5798ad7816b8176c5b01e050ddbfbb925d2732767a
Summary: Improvements and cleanups by John Newbery This is from [[bitcoin/bitcoin#11403 | PR11403]] : bitcoin/bitcoin@b224a47 We initially decided not to backport it because we don't have this feature, but it turns out it exercice various parts of the code and is useful. In addition, it makes backport easier. Also include a trick similar to [[bitcoin/bitcoin#17124 | PR17124]] to significantly speedup the test. Test Plan: ninja all check-all Reviewers: #bitcoin_abc, majcosta Reviewed By: #bitcoin_abc, majcosta Differential Revision: https://reviews.bitcoinabc.org/D6131
Summary: Improvements and cleanups by John Newbery This is from [[bitcoin/bitcoin#11403 | PR11403]] : bitcoin/bitcoin@b224a47 We initially decided not to backport it because we don't have this feature, but it turns out it exercice various parts of the code and is useful. In addition, it makes backport easier. Also include a trick similar to [[bitcoin/bitcoin#17124 | PR17124]] to significantly speedup the test. Test Plan: ninja all check-all Reviewers: #bitcoin_abc, majcosta Reviewed By: #bitcoin_abc, majcosta Differential Revision: https://reviews.bitcoinabc.org/D6131
backport: bitcoin#10244, bitcoin#18123, bitcoin#12906 + Parts of bitcoin#11403
…ype, g_change_type b7f6002 Fix rescan test failure due to unset g_address_type, g_change_type (Russell Yanofsky) Pull request description: New global variables were introduced in bitcoin#11403 and not setting them causes: ``` test_bitcoin: wallet/wallet.cpp:4259: CTxDestination GetDestinationForKey(const CPubKey&, OutputType): Assertion `false' failed. unknown location(0): fatal error in "importwallet_rescan": signal: SIGABRT (application abort requested) ``` It's possible to reproduce the failure reliably by running: ``` src/test/test_bitcoin --log_level=test_suite --run_test=wallet_tests/importwallet_rescan ``` Failures happen nondeterministically because boost test framework doesn't run tests in a specified order, and tests that run previously can set the global variables and mask the bug. This is similar to bug bitcoin#12150. Example travis failure is https://travis-ci.org/bitcoin/bitcoin/jobs/340642010 Tree-SHA512: ab40662b3356892b726f1f552e22d58d86b5e982538741e52b37ee447a0c97c76c24ae543687edf2e25d9dd925722909d37abfae95d93bf09e23fa245a4c3351
9c8eca7 Split up key and script metadata for better type safety (Russell Yanofsky) Pull request description: Suggested by @TheBlueMatt bitcoin/bitcoin#11403 (comment) Combining the maps was probably never a good arrangement but is more problematic now in presence of WitnessV0ScriptHash and WitnessV0KeyHash types. Tree-SHA512: 9263e9c01090fb49221e91d88a88241a9691dda3e92d86041c8e284306a64d3af5e2438249f9dcc3e6e4a5c11c1a89f975a86d55690adf95bf2636f15f99f92a
… safety 9c8eca7 Split up key and script metadata for better type safety (Russell Yanofsky) Pull request description: Suggested by @TheBlueMatt bitcoin#11403 (comment) Combining the maps was probably never a good arrangement but is more problematic now in presence of WitnessV0ScriptHash and WitnessV0KeyHash types. Tree-SHA512: 9263e9c01090fb49221e91d88a88241a9691dda3e92d86041c8e284306a64d3af5e2438249f9dcc3e6e4a5c11c1a89f975a86d55690adf95bf2636f15f99f92a
… GetAccountDestination
This implements a minimum viable implementation of SegWit wallet support, based on top of #11389, and includes part of the functionality from #11089.
Two new configuration options are added:
-addresstype
, with optionslegacy
,p2sh
, andbech32
. It controls what kind of addresses are produced bygetnewaddress
,getaccountaddress
, andcreatemultisigaddress
.-changetype
, with the same options, and by default equal to-addresstype
, that controls what kind of change is used.All wallet private and public keys can be used for any type of address. Support for address types dependent on different derivation paths will need a major overhaul of how our internal detection of outputs work. I expect that that will happen for a next major version.
The above also applies to imported keys, as having a distinction there but not for normal operations is a disaster for testing, and probably for comprehension of users. This has some ugly effects, like needing to associate the provided label to
importprivkey
with each style address for the corresponding key.To deal with witness outputs requiring a corresponding redeemscript in wallet, three approaches are used:
getnewaddress
or multisig RPCs explicitly get their redeemscripts added to the wallet file. This means that downgrading after creating a witness address will work, as long as the wallet file is up to date.These approaches correspond to solutions 3a, 1a, and 5a respectively from https://gist.github.com/sipa/125cfa1615946d0c3f3eec2ad7f250a2. As argued there, there is no full solution for dealing with the case where you both downgrade and restore a backup, so that's also not implemented.
dumpwallet
,importwallet
,importmulti
,signmessage
andverifymessage
don't work with SegWit addresses yet. They're remaining TODOs, for this PR or a follow-up. Because of that, several tests unexpectedly run with-addresstype=legacy
for now.