aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2017-08-01 13:36:57 +0200
committerWladimir J. van der Laan <laanwj@gmail.com>2017-08-01 14:27:01 +0200
commitf66c59650527022b4f7abd98ff0a1a4e4741bd34 (patch)
tree6b752fdb514168fded5bb3ef07ded029d1e5bc93
parent754aa02b8a72af0fa0a3b2bdfee1ef1b592aef6a (diff)
parente222dc2aee263bf28cf19689b9c9ed97da054682 (diff)
Merge #10788: [RPC] Fix addwitnessaddress by replacing ismine with producesignature
e222dc2 Replace ismine with producesignature check in witnessifier (Andrew Chow) Pull request description: Instead of using ismine to check whether an address can be spent by us, make the witness version of the script or address first and then use ProduceSignature with the DummySignatureCreator to check if we can solve for the script. This is to fix cases where we don't have all of the private keys (for something like a multisig address) but have the redeemscript so we can witnessify it. Tree-SHA512: 371777aee839cceb41f099109a13689120d35cf3880cde39216596cc2aac5cc1096af7d9cf07ad9306c3b05c073897f4518a7e97f0b88642f1e3b80b799f481e
-rw-r--r--src/wallet/rpcwallet.cpp24
-rwxr-xr-xtest/functional/segwit.py11
2 files changed, 22 insertions, 13 deletions
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 14560860cb..a7c229fa74 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -1130,11 +1130,15 @@ public:
bool operator()(const CKeyID &keyID) {
if (pwallet) {
CScript basescript = GetScriptForDestination(keyID);
- isminetype typ;
- typ = IsMine(*pwallet, basescript, SIGVERSION_WITNESS_V0);
- if (typ != ISMINE_SPENDABLE && typ != ISMINE_WATCH_SOLVABLE)
- return false;
CScript witscript = GetScriptForWitness(basescript);
+ SignatureData sigs;
+ // This check is to make sure that the script we created can actually be solved for and signed by us
+ // 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 transcation.
+ if (!ProduceSignature(DummySignatureCreator(pwallet), witscript, sigs) ||
+ !VerifyScript(sigs.scriptSig, witscript, &sigs.scriptWitness, MANDATORY_SCRIPT_VERIFY_FLAGS | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, DummySignatureCreator(pwallet).Checker())) {
+ return false;
+ }
pwallet->AddCScript(witscript);
result = CScriptID(witscript);
return true;
@@ -1151,11 +1155,15 @@ public:
result = scriptID;
return true;
}
- isminetype typ;
- typ = IsMine(*pwallet, subscript, SIGVERSION_WITNESS_V0);
- if (typ != ISMINE_SPENDABLE && typ != ISMINE_WATCH_SOLVABLE)
- return false;
CScript witscript = GetScriptForWitness(subscript);
+ SignatureData sigs;
+ // This check is to make sure that the script we created can actually be solved for and signed by us
+ // 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 transcation.
+ if (!ProduceSignature(DummySignatureCreator(pwallet), witscript, sigs) ||
+ !VerifyScript(sigs.scriptSig, witscript, &sigs.scriptWitness, MANDATORY_SCRIPT_VERIFY_FLAGS | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, DummySignatureCreator(pwallet).Checker())) {
+ return false;
+ }
pwallet->AddCScript(witscript);
result = CScriptID(witscript);
return true;
diff --git a/test/functional/segwit.py b/test/functional/segwit.py
index ac95d66466..51eaa34a54 100755
--- a/test/functional/segwit.py
+++ b/test/functional/segwit.py
@@ -459,13 +459,14 @@ class SegWitTest(BitcoinTestFramework):
self.mine_and_test_listunspent(unsolvable_after_importaddress, 1)
self.mine_and_test_listunspent(unseen_anytime, 0)
- # addwitnessaddress should refuse to return a witness address if an uncompressed key is used or the address is
- # not in the wallet
+ # addwitnessaddress should refuse to return a witness address if an uncompressed key is used
# note that no witness address should be returned by unsolvable addresses
- # the multisig_without_privkey_address will fail because its keys were not added with importpubkey
- for i in uncompressed_spendable_address + uncompressed_solvable_address + unknown_address + unsolvable_address + [multisig_without_privkey_address]:
+ for i in uncompressed_spendable_address + uncompressed_solvable_address + unknown_address + unsolvable_address:
assert_raises_jsonrpc(-4, "Public key or redeemscript not known to wallet, or the key is uncompressed", self.nodes[0].addwitnessaddress, i)
+ # addwitnessaddress should return a witness addresses even if keys are not in the wallet
+ self.nodes[0].addwitnessaddress(multisig_without_privkey_address)
+
for i in compressed_spendable_address + compressed_solvable_address:
witaddress = self.nodes[0].addwitnessaddress(i)
# addwitnessaddress should return the same address if it is a known P2SH-witness address
@@ -542,7 +543,7 @@ class SegWitTest(BitcoinTestFramework):
# addwitnessaddress should refuse to return a witness address if an uncompressed key is used
# note that a multisig address returned by addmultisigaddress is not solvable until it is added with importaddress
# premature_witaddress are not accepted until the script is added with addwitnessaddress first
- for i in uncompressed_spendable_address + uncompressed_solvable_address + premature_witaddress + [compressed_solvable_address[1]]:
+ for i in uncompressed_spendable_address + uncompressed_solvable_address + premature_witaddress:
# This will raise an exception
assert_raises_jsonrpc(-4, "Public key or redeemscript not known to wallet, or the key is uncompressed", self.nodes[0].addwitnessaddress, i)