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
Add SegWit support to importmulti #14454
Add SegWit support to importmulti #14454
Conversation
Reviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
src/wallet/rpcdump.cpp
Outdated
|
||
CTxDestination pubkey_dest = pubKey.GetID(); | ||
CTxDestination pubkey_dest = pubKey.GetID(); |
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 longer needed?
src/wallet/rpcdump.cpp
Outdated
if (pubKeys.size() && keys.size() == 0) { | ||
const std::string& strPubKey = pubKeys[0].get_str(); | ||
// Generate the scripts | ||
std::vector<unsigned char> vData(ParseHex(strWitnessScript)); |
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.
Use another variable name to avoid shadowing existing local variable vData
:-)
Thanks for reviewing @practicalswift, both comments addressed :) |
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.
Concept ACK
59f8e547130fc1cb756da7d990f65445ca196f5f could be squashed into 24092b3402693d8a2c39b640db18748b168863e9
acdba74ee011bfcafc9f28b528918815b1de4920 seems to be an unrelated change
if (isP2SH && !IsHex(strRedeemScript)) { | ||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid redeem script"); | ||
// Force users to provide the witness script in its field rather than redeemscript | ||
if (!strRedeemScript.empty() && script.IsPayToWitnessScriptHash()) { |
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.
Instead of checking that strRedeemScript
is not empty, this should check that strWitnessScript
is empty. Or it could check both: !strRedeemScript.empty() && strWitnessScript.empty()
.
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 should be possible to provide a P2WSH scriptPubKey without providing the witness script for it, e.g. watch only, so I don't think that's right
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 checking both covers that case.
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.
Checking both would mean that if witnessScript and redeemScript were both present, it would allow it, which makes no sense if its not a P2WSH address
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.
P2WSH scriptPubKey without providing the witness script for it, e.g. watch only
Do we already support that? And test it? If not, maybe it's easier to just treat it as P2SH until we know the witnessScript
.
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.
@Sjors Yes, of course, just importaddress
it. It probably works fine without this PR even.
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.
@sipa so we currently support importing a 3...
address as watch-only, but the wallet doesn't know or care if it's SegWit or not. The new code here is for a scenario where you do know it's SegWit script.IsPayToWitnessScriptHash()
, which means you know the strRedeemScript
, but you don't know the strWitnessScript
. That seems a strange situation. Why would anyone give you the legacy redeem script but not the Segwit witness 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.
@Sjors I have no idea what you're talking about. This is about the case where you're importing a bech32 P2WSH address (no P2SH), without revealing the script inside - which is a totally reasonable thing if you don't care about solvability.
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.
@sipa I see, I may have gotten confused because Github is showing if (isP2SH && !IsHex(strRedeemScript
as the deleted line, but this thread is about an earlier code branch.
src/wallet/rpcdump.cpp
Outdated
// Import redeem script. | ||
std::vector<unsigned char> vData(ParseHex(strRedeemScript)); | ||
CScript redeemScript = CScript(vData.begin(), vData.end()); | ||
CScriptID redeem_id(redeemScript); | ||
CScript redeemDestination = GetScriptForDestination(redeem_id); |
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.
nit: snake_case
src/wallet/rpcdump.cpp
Outdated
|
||
// Optional fields. | ||
const std::string& strRedeemScript = data.exists("redeemscript") ? data["redeemscript"].get_str() : ""; | ||
const std::string& strWitnessScript = data.exists("witnessscript") ? data["witnessscript"].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.
nit: snake_case
src/wallet/rpcdump.cpp
Outdated
const std::string& strPubKey = pubKeys[0].get_str(); | ||
// Generate the scripts | ||
std::vector<unsigned char> vData(ParseHex(strWitnessScript)); | ||
CScript witnessScript = CScript(vData.begin(), vData.end()); |
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.
nit: snake_case
src/wallet/rpcdump.cpp
Outdated
std::vector<unsigned char> vData(ParseHex(strWitnessScript)); | ||
CScript witnessScript = CScript(vData.begin(), vData.end()); | ||
CScriptID witness_id(witnessScript); | ||
CScript witnessDestination = GetScriptForDestination(WitnessV0ScriptHash(witnessScript)); |
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.
nit: snake_case
src/wallet/rpcdump.cpp
Outdated
// P2PK/P2PKH/P2WPKH | ||
} else if (dest.type() == typeid(CKeyID) || dest.type() == typeid(WitnessV0KeyHash)) { | ||
if (keys.size() > 1 || pubKeys.size() > 1) { | ||
throw JSONRPCError(RPC_INVALID_PARAMETER, "More than private key given for one address"); |
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 error wouldn't make sense if only pubkeys were given.
src/wallet/rpcdump.cpp
Outdated
} | ||
pubkey = pubkey_temp; | ||
} | ||
if (pubkey.size()) { |
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.
Instead of checking pubkey size, check validity? (e.g. use IsValid()
or IsFullyValid()
)
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.
IsValid() just performs the same size check anyway, but yep I'll do that for the sake of clarity, I don't think we need an IsFullyValid() check here
Thanks @achow101, addressed all your points |
@meshcollider I don't think it's necessary to import the pubkeys involved separately anymore since #14424, and in fact that sounds very dangerous (you could be tricked into importing a 2-of-3 multisig where you have 2 of the keys, but then receiving a payment to a P2PKH of the third key, and seeing it treated towards your watch-only balance). NACK until that is fixed (or at least restricted to not have that issue, but I believe that rebasing on 14424 will be sufficient). |
@sipa good point, fixed, and rebased on master to include the public key fix |
I think there are a few things that need fixing:
|
I believe I've addressed the points, thanks for the feedback so far |
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.
Concept ACK
src/wallet/rpcdump.cpp
Outdated
} | ||
|
||
// Import private keys. | ||
// P2PK/P2PKH/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.
I think it may make sense to repeat the trick from the P2SH block of 'descending' into scriptPubKey/address of the redeemscript, to the P2WSH block, and then do P2PK/P2PKH/P2WPKH as a totally new case rather than an else branch. This would make the code work correctly for P2PK/P2PKH nested inside P2WSH (maybe track that you don't permit P2WPKH inside P2WSH though).
@@ -458,6 +468,74 @@ def run_test (self): | |||
"timestamp": "", | |||
}]) | |||
|
|||
# Import P2WPKH address |
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.
There are a number more scenarios that make sense to test, I think:
- Address based import (without key/script) of P2WSH-multisig
- For all of P2WPKH, P2WSH-multisig, P2SH-P2WPKH, P2SH-P2WSH-multisig, versions with script/pubkey but no private key, and test that the result is solvable.
- P2WPKH with private key, result must be spendable (not just watchonly)
- P2WSH-multisig and P2SH-multisig with more than 1 key, where some of the keys are specified as private keys, and some as public keys.
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.
Re "Address based import", should this result in the following?
"ismine": false,
"iswatchonly": true,
"issolvable": false,
"isscript": true,
"iswitness": true,
"witness_version": 0
Re "must be spendable", this means "ismine": true
and "iswatchonly": 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.
@Sjors Correct.
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.
Concept ACK.
I tested 65ecf2d importing a watch-only bech32 address, which worked.
I also tested importing a watch-only p2sh-p2wpkh address like so: importmulti '[{"scriptPubKey": {"address": "2NFiDQiCdRYaRUdWMerff1qSTR4EC7zSBmB"}, "timestamp": "now", "pubkeys": ["03f33112792b07e9994933287ea71069d94176225f745822e47151d39e754d957f"]}]'
. This is considered "issolvable": false
. Once I add the private key it does know how to solve it.
Code looks good to me, but I don't pretend to understand all the edge cases involved. The tests really help illustrate it, so the more the better, see Sipa's suggestions:
480cba3#r225796932)
src/wallet/rpcdump.cpp
Outdated
// Should have script or JSON with "address". | ||
if (!(scriptPubKey.getType() == UniValue::VOBJ && scriptPubKey.exists("address")) && !(scriptPubKey.getType() == UniValue::VSTR)) { | ||
bool isScript = scriptPubKey.getType() == UniValue::VSTR; | ||
if (!isScript && !(scriptPubKey.getType() == UniValue::VOBJ && scriptPubKey.exists("address"))) { | ||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid scriptPubKey"); |
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.
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid scriptPubKey"); | |
throw JSONRPCError(RPC_INVALID_PARAMETER, "scriptPubKey must be string with script or JSON with address string"); |
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 how the code suggestion feature works. I suspect it creates a new commit, in which case it's better to just copy-paste the text and amend an existing commit.
src/wallet/rpcdump.cpp
Outdated
@@ -858,32 +853,31 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con | |||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Incompatibility found between watchonly and keys"); | |||
} | |||
|
|||
// Internal + Label | |||
// Internal addresses should not have a label | |||
if (internal && data.exists("label")) { | |||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Incompatibility found between internal and label"); |
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.
Suggest using the same error message as the above comment: Internal addresses should not have a label
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.
Could we also get a test for this?
if (isP2SH && !IsHex(strRedeemScript)) { | ||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid redeem script"); | ||
// Force users to provide the witness script in its field rather than redeemscript | ||
if (!strRedeemScript.empty() && script.IsPayToWitnessScriptHash()) { |
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.
P2WSH scriptPubKey without providing the witness script for it, e.g. watch only
Do we already support that? And test it? If not, maybe it's easier to just treat it as P2SH until we know the witnessScript
.
@@ -809,29 +809,24 @@ UniValue dumpwallet(const JSONRPCRequest& request) | |||
static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) |
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.
Maybe move this function to a different file? Unless dump
means dumping ground :-)
I understand if you prefer to keep this PR simple though.
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 specific to importing things, though, which is the scope of rpcdump.cpp?
@@ -458,6 +468,74 @@ def run_test (self): | |||
"timestamp": "", | |||
}]) | |||
|
|||
# Import P2WPKH address |
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.
Re "Address based import", should this result in the following?
"ismine": false,
"iswatchonly": true,
"issolvable": false,
"isscript": true,
"iswitness": true,
"witness_version": 0
Re "must be spendable", this means "ismine": true
and "iswatchonly": false
?
src/wallet/rpcdump.cpp
Outdated
// Should have script or JSON with "address". | ||
if (!(scriptPubKey.getType() == UniValue::VOBJ && scriptPubKey.exists("address")) && !(scriptPubKey.getType() == UniValue::VSTR)) { | ||
bool isScript = scriptPubKey.getType() == UniValue::VSTR; | ||
if (!isScript && !(scriptPubKey.getType() == UniValue::VOBJ && scriptPubKey.exists("address"))) { | ||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid scriptPubKey"); |
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.
Good time to give a more descriptive error?
src/wallet/rpcdump.cpp
Outdated
@@ -858,32 +853,31 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con | |||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Incompatibility found between watchonly and keys"); | |||
} | |||
|
|||
// Internal + Label | |||
// Internal addresses should not have a label | |||
if (internal && data.exists("label")) { | |||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Incompatibility found between internal and label"); |
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.
Could we also get a test for this?
src/wallet/rpcdump.cpp
Outdated
throw JSONRPCError(RPC_INVALID_PARAMETER, "More than private key given for one address"); | ||
// Force users to provide the witness script in its field rather than redeemscript | ||
if (!strRedeemScript.empty() && script.IsPayToWitnessScriptHash()) { | ||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Provide witnessscript not redeemscript for P2WSH address"); |
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.
wording suggestion: "P2WSH addresses have an empty redeemscript. Please provide the witnessscript instead."
src/wallet/rpcdump.cpp
Outdated
if (!strRedeemScript.empty() && script.IsPayToScriptHash()) { | ||
// Check the redeemScript is valid | ||
if (!IsHex(strRedeemScript)) { | ||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid redeem 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.
suggestion: "Invalid redeem script: must be hex string"
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid scriptPubKey"); | ||
} | ||
const std::string& output = isScript ? scriptPubKey.get_str() : scriptPubKey["address"].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.
while we're here could we rename this to something more self-documenting?
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.
@instagibbs what do you suggest? script_or_address
?
src/wallet/rpcdump.cpp
Outdated
if (!pwallet->HaveCScript(redeem_id) && !pwallet->AddCScript(redeemScript)) { | ||
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet"); | ||
} | ||
|
||
CScript redeemDestination = GetScriptForDestination(redeem_id); | ||
// Check for P2SH-P2WSH |
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 understand this is a transient commit, but could there be a TODO P2SH-P2WPKH comment somewhere around here?
src/wallet/rpcdump.cpp
Outdated
CKeyID vchAddress = pubkey.GetID(); | ||
pwallet->MarkDirty(); | ||
pwallet->SetAddressBook(vchAddress, label, "receive"); | ||
// P2WSH |
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.
// (P2SH-)P2WSH
Makes it more clear to me that the above block changed the 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.
And same thing with: // P2PK/P2PKH/P2WPKH
src/wallet/rpcdump.cpp
Outdated
} | ||
|
||
// Process. // | ||
CScript original_script = 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.
scriptpubkey_script
more self-explanatory? "original" is context dependent.
src/wallet/rpcdump.cpp
Outdated
|
||
// Process. // | ||
CScript original_script = script; | ||
CTxDestination original_dest = 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.
scriptpubkey_dest
more self-explanatory? "original" is context dependent.
All comments so far are addressed, lots more tests added. Thanks @sipa, @instagibbs, @Sjors |
@meshcollider I'm still seeing the same behavior I described above when importing a |
@Sjors You need the redeemscript to make your example solvable (otherwise there is no way for the matcher to go from a P2SH hash to knowing what script the hash is of). With the private key the weird-evil-but-necessary magic behaviour that causes us to automatically recognize P2WPKH and P2SH-P2WPKH payments to known private keys triggers. |
Your wording suggests you're not a fan of adding that weird-evil-but-optional magic behavior to the (very common) case of having one public key? |
@Sjors I'm not really a fan of it, this code is already edge-cased enough without adding more ifs to test for, but I'm happy to add it if you really think its worthwhile. |
@Sjors No, but I have suggested something else before, which would perhaps also solve your issue, namely that for all single-key schemes you can just provide the pubkey, and At the very least, something for another PR, though. |
And such a case would be so easy with descriptors too ;) |
I'm fine with focusing on descriptors, since those are an order of magnitude more intuitive than the current |
Comments addressed + squashed some commits together |
src/wallet/rpcdump.cpp
Outdated
if (IsValidDestination(dest)) { | ||
pwallet->SetAddressBook(dest, label, "receive"); | ||
// Import into the wallet | ||
if (!pwallet->AddWatchOnly(witness_script, timestamp)) { |
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.
A small issue still: for P2SH-P2WSH it's unnecessary (and undesirable, I think) to also import the inner P2WSH script as watch-only.
It's not necessary because we're already marking the P2SH-P2WSH script as watch-only, and for solvability all we need is AddCScript
, not AddWatchOnly
.
It's undesirable because it will cause us to treat payments to the P2WSH address as watchonly IsMine (instead of just the P2SH-P2WSH 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.
Good point, fixed
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 added a few more questions inline, hopefully merely to reduce my own confusion.
My above concerns are addressed in e4a66bb, modulo two tests that @sipa requested and are either missing or I overlooked them.
The added tests only cover whether importmulti returns true, not whether it actually imported anything.
This is done now by checking properties via getaddressinfo
.
The added tests are restricted to watchonly and spendable cases, but no solvable-but-not-spendable ones.
Some of the ['solvable'], True)
tests now check that ['ismine'], False
, but none check for iswatchonly'],False]
.
Address based import (without key/script) of P2WSH-multisig
Covered in # P2WSH multisig address without scripts or keys
and # P2SH-P2WSH 1-of-1 multisig + redeemscript with no private key
For all of P2WPKH, P2WSH-multisig, P2SH-P2WPKH, P2SH-P2WSH-multisig, versions with script/pubkey but no private key, and test that the result is solvable.
I think this one is still missing for P2WSH multisig, between the # P2WSH multisig address without scripts or keys
and # Same P2WSH multisig address as above, but now with witnessscript + private keys
tests?
P2WPKH with private key, result must be spendable (not just watchonly)
Where "spendable" means ("ismine": true and "iswatchonly": false)
. This is done.
P2WSH-multisig and P2SH-multisig with more than 1 key, where some of the keys are specified as private keys, and some as public keys.
Missing?
I made a commit that checks solvable
for all legacy scenarios as well: Sjors@02d553b
assert_equal(result[0]['success'], True) | ||
address_assert = self.nodes[1].getaddressinfo(address['address']) | ||
assert_equal(address_assert['iswatchonly'], True) | ||
assert_equal(address_assert['solvable'], 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.
@sipa can you remind me why a Native Pay-to-Witness-Public-Key-Hash isn't solvable
, even though legacy Pay-to-Public-Key-Hash addresses are? Is that just to reduce evil magic like in the P2SH-P2PKH case?
If so, maybe add a comment in the test or in the RPC doc?
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 this example it's not solvable because the public key isn't included. It has nothing to do with the script/witness hashing type.
In general, solvability is very easy. Start at the scriptPubKey. Whenever it includes a script hash, we must receive the actual script, and recurse into it. Whenever you encounter a pubkey hash, we must receive the actual public key. A scriptPubKey is solvable whenever you can descend all the way to scripts and pubkeys without any hashes of unknown things.
The only exception to that is that whenever you have a private key X, we also automatically import the P2WPKH and P2SH-P2WPKH versions of it, so no separate importing is needed in that case.
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 this example it's not solvable because the public key isn't included.
OK, that makes sense. Actually I misread the legacy test: it does add the public key, which why it's solvable.
Squashed fixups into their respective commits, thanks for the review :) |
utACK c11875c |
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
}]) | ||
assert_equal(result[0]['success'], True) | ||
address_assert = self.nodes[1].getaddressinfo(multi_sig_script['address']) | ||
assert_equal(address_assert['solvable'], 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.
nit: if "sigsrequired" and "ismine" aren't in results can we assert their absence here?
}]) | ||
assert_equal(result[0]['success'], True) | ||
address_assert = self.nodes[1].getaddressinfo(multi_sig_script['address']) | ||
assert_equal(address_assert['solvable'], 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.
nit: ismine?
@@ -3538,6 +3538,7 @@ UniValue getaddressinfo(const JSONRPCRequest& request) | |||
" \"address\" : \"address\", (string) The bitcoin address validated\n" | |||
" \"scriptPubKey\" : \"hex\", (string) The hex-encoded scriptPubKey generated by the address\n" | |||
" \"ismine\" : true|false, (boolean) If the address is yours or not\n" | |||
" \"solvable\" : true|false, (boolean) If the address is solvable by the wallet\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.
Could have release note.
pwallet->UpdateTimeFirstKey(timestamp); | ||
} | ||
// (P2SH-)P2PK/P2PKH/P2WPKH | ||
if (dest.type() == typeid(CKeyID) || dest.type() == typeid(WitnessV0KeyHash)) { |
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.
First time using RTTI? Maybe it could be avoided?
BTW, didn't test but I don't see variant::type()
in boost 1.47 documentation.
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.
@promag it seems to be there: https://www.boost.org/doc/libs/1_47_0/doc/html/boost/variant.html
I could also do dest.which() == 1 || dest.which() == 4
but that's very unclear, or define a new enum of the types, but that seemed over the top unless there's a good reason to avoid RTTI?
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.
Indeed it's in 1.47. Anyway this is removed in #14565.
utACK 201451b |
looks good to me, adding the |
c11875c Add segwit address tests for importmulti (MeshCollider) 201451b Make getaddressinfo return solvability (MeshCollider) 1753d21 Add release notes for importmulti segwit change (MeshCollider) 353c064 Fix typo in test_framework/blocktools (MeshCollider) f6ed748 Add SegWit support to importmulti with some ProcessImport cleanup (MeshCollider) Pull request description: Add support for segwit to importmulti, supports P2WSH, P2WPKH, P2SH-P2WPKH, P2SH-P2WSH. Adds a new `witnessscript` parameter which must be used for the witness scripts in the relevant situations. Also includes some tests for the various import types. ~Also makes the change in #14019 redundant, but cherry-picks the test from that PR to test the behavior (@achow101).~ Fixes #12253, also addresses the second point in #12703, and fixes #14407 Tree-SHA512: 775a755c524d1c387a99acddd772f677d2073876b72403dcfb92c59f9b405ae13ceedcf4dbd2ee1d7a8db91c494f67ca137161032ee3a2071282eeb411be090a
b985e9c Add release notes for importmulti descriptor support (MeshCollider) fbb5e93 Add test for importing via descriptor (MeshCollider) 9f48053 [wallet] Allow descriptor imports with importmulti (MeshCollider) d2b381c [wallet] Refactor ProcessImport() to call ProcessImportLegacy() (John Newbery) 4cac0dd [wallet] Add ProcessImportLegacy() (John Newbery) a1b25e1 [wallet] Refactor ProcessImport() (John Newbery) Pull request description: ~~Based on #14454 #14565, last two commits only are for review.~~ Best reviewed with `?w=1` Allows a descriptor to be imported into the wallet using `importmulti` RPC. Start and end of range can be specified for ranged descriptors. The descriptor is implicitly converted to old structures on import. Also adds a simple test of a P2SH-P2WPKH address being imported as a descriptor. More tests to come, as well as release notes. Tree-SHA512: 160eb6fd574c4ae5b70e0109f7e5ccc95d9309138603408a1114ceb3c558065409c0d7afb66926bc8e1743c365a3b300c5f944ff18b2451acc0514fbeca1f2b3
Summary: Partial backport of Core [[bitcoin/bitcoin#14454 | PR14454]] bitcoin/bitcoin@f6ed748 bitcoin/bitcoin@c11875c#diff-3dfbfa462305488434b8d8da81f99de7R99-R111 Depends on D6061 Test Plan: ninja ninja check ninja check-functional Reviewers: O1 Bitcoin ABC, #bitcoin_abc, deadalnix Reviewed By: O1 Bitcoin ABC, #bitcoin_abc, deadalnix Subscribers: deadalnix Differential Revision: https://reviews.bitcoinabc.org/D6051
Add support for segwit to importmulti, supports P2WSH, P2WPKH, P2SH-P2WPKH, P2SH-P2WSH. Adds a new
witnessscript
parameter which must be used for the witness scripts in the relevant situations.Also includes some tests for the various import types.
Also makes the change in #14019 redundant, but cherry-picks the test from that PR to test the behavior (@achow101).Fixes #12253, also addresses the second point in #12703, and fixes #14407