Skip to content

Commit 55f98d0

Browse files
committed
rpc: output parent wallet descriptors for coins in listunspent
1 parent b724476 commit 55f98d0

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

src/wallet/rpc/coins.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,9 @@ RPCHelpMan listunspent()
543543
{RPCResult::Type::BOOL, "solvable", "Whether we know how to spend this output, ignoring the lack of keys"},
544544
{RPCResult::Type::BOOL, "reused", /*optional=*/true, "(only present if avoid_reuse is set) Whether this output is reused/dirty (sent to an address that was previously spent from)"},
545545
{RPCResult::Type::STR, "desc", /*optional=*/true, "(only when solvable) A descriptor for spending this output"},
546+
{RPCResult::Type::ARR, "parent_descs", /*optional=*/false, "List of parent descriptors for the scriptPubKey of this coin.", {
547+
{RPCResult::Type::STR, "desc", "The descriptor string."},
548+
}},
546549
{RPCResult::Type::BOOL, "safe", "Whether this output is considered safe to spend. Unconfirmed transactions\n"
547550
"from outside keys and unconfirmed replacement transactions are considered unsafe\n"
548551
"and are not eligible for spending by fundrawtransaction and sendtoaddress."},
@@ -722,6 +725,7 @@ RPCHelpMan listunspent()
722725
entry.pushKV("desc", descriptor->ToString());
723726
}
724727
}
728+
PushParentDescriptors(*pwallet, scriptPubKey, entry);
725729
if (avoid_reuse) entry.pushKV("reused", reused);
726730
entry.pushKV("safe", out.safe);
727731
results.push_back(entry);

test/functional/wallet_basic.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from itertools import product
88

99
from test_framework.blocktools import COINBASE_MATURITY
10+
from test_framework.descriptors import descsum_create
1011
from test_framework.test_framework import BitcoinTestFramework
1112
from test_framework.util import (
1213
assert_array_result,
@@ -700,6 +701,38 @@ def run_test(self):
700701
txid_feeReason_four = self.nodes[2].sendmany(dummy='', amounts={address: 5}, verbose=False)
701702
assert_equal(self.nodes[2].gettransaction(txid_feeReason_four)['txid'], txid_feeReason_four)
702703

704+
self.log.info("Testing 'listunspent' outputs the parent descriptor(s) of coins")
705+
# Create two multisig descriptors, and send a UTxO each.
706+
multi_a = descsum_create("wsh(multi(1,tpubD6NzVbkrYhZ4YBNjUo96Jxd1u4XKWgnoc7LsA1jz3Yc2NiDbhtfBhaBtemB73n9V5vtJHwU6FVXwggTbeoJWQ1rzdz8ysDuQkpnaHyvnvzR/*,tpubD6NzVbkrYhZ4YHdDGMAYGaWxMSC1B6tPRTHuU5t3BcfcS3nrF523iFm5waFd1pP3ZvJt4Jr8XmCmsTBNx5suhcSgtzpGjGMASR3tau1hJz4/*))")
707+
multi_b = descsum_create("wsh(multi(1,tpubD6NzVbkrYhZ4YHdDGMAYGaWxMSC1B6tPRTHuU5t3BcfcS3nrF523iFm5waFd1pP3ZvJt4Jr8XmCmsTBNx5suhcSgtzpGjGMASR3tau1hJz4/*,tpubD6NzVbkrYhZ4Y2RLiuEzNQkntjmsLpPYDm3LTRBYynUQtDtpzeUKAcb9sYthSFL3YR74cdFgF5mW8yKxv2W2CWuZDFR2dUpE5PF9kbrVXNZ/*))")
708+
addr_a = self.nodes[0].deriveaddresses(multi_a, 0)[0]
709+
addr_b = self.nodes[0].deriveaddresses(multi_b, 0)[0]
710+
txid_a = self.nodes[0].sendtoaddress(addr_a, 0.01)
711+
txid_b = self.nodes[0].sendtoaddress(addr_b, 0.01)
712+
self.generate(self.nodes[0], 1, sync_fun=self.no_op)
713+
# Now import the descriptors, make sure we can identify on which descriptor each coin was received.
714+
self.nodes[0].createwallet(wallet_name="wo", descriptors=True, disable_private_keys=True)
715+
wo_wallet = self.nodes[0].get_wallet_rpc("wo")
716+
wo_wallet.importdescriptors([
717+
{
718+
"desc": multi_a,
719+
"active": False,
720+
"timestamp": "now",
721+
},
722+
{
723+
"desc": multi_b,
724+
"active": False,
725+
"timestamp": "now",
726+
},
727+
])
728+
coins = wo_wallet.listunspent(minconf=0)
729+
assert_equal(len(coins), 2)
730+
coin_a = next(c for c in coins if c["txid"] == txid_a)
731+
assert_equal(coin_a["parent_descs"][0], multi_a)
732+
coin_b = next(c for c in coins if c["txid"] == txid_b)
733+
assert_equal(coin_b["parent_descs"][0], multi_b)
734+
self.nodes[0].unloadwallet("wo")
735+
703736

704737
if __name__ == '__main__':
705738
WalletTest().main()

0 commit comments

Comments
 (0)