Skip to content

Commit f66c596

Browse files
committed
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
2 parents 754aa02 + e222dc2 commit f66c596

File tree

2 files changed

+22
-13
lines changed

2 files changed

+22
-13
lines changed

src/wallet/rpcwallet.cpp

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,11 +1130,15 @@ class Witnessifier : public boost::static_visitor<bool>
11301130
bool operator()(const CKeyID &keyID) {
11311131
if (pwallet) {
11321132
CScript basescript = GetScriptForDestination(keyID);
1133-
isminetype typ;
1134-
typ = IsMine(*pwallet, basescript, SIGVERSION_WITNESS_V0);
1135-
if (typ != ISMINE_SPENDABLE && typ != ISMINE_WATCH_SOLVABLE)
1136-
return false;
11371133
CScript witscript = GetScriptForWitness(basescript);
1134+
SignatureData sigs;
1135+
// This check is to make sure that the script we created can actually be solved for and signed by us
1136+
// if we were to have the private keys. This is just to make sure that the script is valid and that,
1137+
// if found in a transaction, we would still accept and relay that transcation.
1138+
if (!ProduceSignature(DummySignatureCreator(pwallet), witscript, sigs) ||
1139+
!VerifyScript(sigs.scriptSig, witscript, &sigs.scriptWitness, MANDATORY_SCRIPT_VERIFY_FLAGS | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, DummySignatureCreator(pwallet).Checker())) {
1140+
return false;
1141+
}
11381142
pwallet->AddCScript(witscript);
11391143
result = CScriptID(witscript);
11401144
return true;
@@ -1151,11 +1155,15 @@ class Witnessifier : public boost::static_visitor<bool>
11511155
result = scriptID;
11521156
return true;
11531157
}
1154-
isminetype typ;
1155-
typ = IsMine(*pwallet, subscript, SIGVERSION_WITNESS_V0);
1156-
if (typ != ISMINE_SPENDABLE && typ != ISMINE_WATCH_SOLVABLE)
1157-
return false;
11581158
CScript witscript = GetScriptForWitness(subscript);
1159+
SignatureData sigs;
1160+
// This check is to make sure that the script we created can actually be solved for and signed by us
1161+
// if we were to have the private keys. This is just to make sure that the script is valid and that,
1162+
// if found in a transaction, we would still accept and relay that transcation.
1163+
if (!ProduceSignature(DummySignatureCreator(pwallet), witscript, sigs) ||
1164+
!VerifyScript(sigs.scriptSig, witscript, &sigs.scriptWitness, MANDATORY_SCRIPT_VERIFY_FLAGS | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, DummySignatureCreator(pwallet).Checker())) {
1165+
return false;
1166+
}
11591167
pwallet->AddCScript(witscript);
11601168
result = CScriptID(witscript);
11611169
return true;

test/functional/segwit.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -459,13 +459,14 @@ def run_test(self):
459459
self.mine_and_test_listunspent(unsolvable_after_importaddress, 1)
460460
self.mine_and_test_listunspent(unseen_anytime, 0)
461461

462-
# addwitnessaddress should refuse to return a witness address if an uncompressed key is used or the address is
463-
# not in the wallet
462+
# addwitnessaddress should refuse to return a witness address if an uncompressed key is used
464463
# note that no witness address should be returned by unsolvable addresses
465-
# the multisig_without_privkey_address will fail because its keys were not added with importpubkey
466-
for i in uncompressed_spendable_address + uncompressed_solvable_address + unknown_address + unsolvable_address + [multisig_without_privkey_address]:
464+
for i in uncompressed_spendable_address + uncompressed_solvable_address + unknown_address + unsolvable_address:
467465
assert_raises_jsonrpc(-4, "Public key or redeemscript not known to wallet, or the key is uncompressed", self.nodes[0].addwitnessaddress, i)
468466

467+
# addwitnessaddress should return a witness addresses even if keys are not in the wallet
468+
self.nodes[0].addwitnessaddress(multisig_without_privkey_address)
469+
469470
for i in compressed_spendable_address + compressed_solvable_address:
470471
witaddress = self.nodes[0].addwitnessaddress(i)
471472
# addwitnessaddress should return the same address if it is a known P2SH-witness address
@@ -542,7 +543,7 @@ def run_test(self):
542543
# addwitnessaddress should refuse to return a witness address if an uncompressed key is used
543544
# note that a multisig address returned by addmultisigaddress is not solvable until it is added with importaddress
544545
# premature_witaddress are not accepted until the script is added with addwitnessaddress first
545-
for i in uncompressed_spendable_address + uncompressed_solvable_address + premature_witaddress + [compressed_solvable_address[1]]:
546+
for i in uncompressed_spendable_address + uncompressed_solvable_address + premature_witaddress:
546547
# This will raise an exception
547548
assert_raises_jsonrpc(-4, "Public key or redeemscript not known to wallet, or the key is uncompressed", self.nodes[0].addwitnessaddress, i)
548549

0 commit comments

Comments
 (0)