mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-11-30 15:58:24 +01:00
rpc: output parent wallet descriptors for coins in listunspent
This commit is contained in:
@@ -543,6 +543,9 @@ RPCHelpMan listunspent()
|
|||||||
{RPCResult::Type::BOOL, "solvable", "Whether we know how to spend this output, ignoring the lack of keys"},
|
{RPCResult::Type::BOOL, "solvable", "Whether we know how to spend this output, ignoring the lack of keys"},
|
||||||
{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)"},
|
{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)"},
|
||||||
{RPCResult::Type::STR, "desc", /*optional=*/true, "(only when solvable) A descriptor for spending this output"},
|
{RPCResult::Type::STR, "desc", /*optional=*/true, "(only when solvable) A descriptor for spending this output"},
|
||||||
|
{RPCResult::Type::ARR, "parent_descs", /*optional=*/false, "List of parent descriptors for the scriptPubKey of this coin.", {
|
||||||
|
{RPCResult::Type::STR, "desc", "The descriptor string."},
|
||||||
|
}},
|
||||||
{RPCResult::Type::BOOL, "safe", "Whether this output is considered safe to spend. Unconfirmed transactions\n"
|
{RPCResult::Type::BOOL, "safe", "Whether this output is considered safe to spend. Unconfirmed transactions\n"
|
||||||
"from outside keys and unconfirmed replacement transactions are considered unsafe\n"
|
"from outside keys and unconfirmed replacement transactions are considered unsafe\n"
|
||||||
"and are not eligible for spending by fundrawtransaction and sendtoaddress."},
|
"and are not eligible for spending by fundrawtransaction and sendtoaddress."},
|
||||||
@@ -722,6 +725,7 @@ RPCHelpMan listunspent()
|
|||||||
entry.pushKV("desc", descriptor->ToString());
|
entry.pushKV("desc", descriptor->ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PushParentDescriptors(*pwallet, scriptPubKey, entry);
|
||||||
if (avoid_reuse) entry.pushKV("reused", reused);
|
if (avoid_reuse) entry.pushKV("reused", reused);
|
||||||
entry.pushKV("safe", out.safe);
|
entry.pushKV("safe", out.safe);
|
||||||
results.push_back(entry);
|
results.push_back(entry);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ from decimal import Decimal
|
|||||||
from itertools import product
|
from itertools import product
|
||||||
|
|
||||||
from test_framework.blocktools import COINBASE_MATURITY
|
from test_framework.blocktools import COINBASE_MATURITY
|
||||||
|
from test_framework.descriptors import descsum_create
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import (
|
from test_framework.util import (
|
||||||
assert_array_result,
|
assert_array_result,
|
||||||
@@ -700,6 +701,38 @@ class WalletTest(BitcoinTestFramework):
|
|||||||
txid_feeReason_four = self.nodes[2].sendmany(dummy='', amounts={address: 5}, verbose=False)
|
txid_feeReason_four = self.nodes[2].sendmany(dummy='', amounts={address: 5}, verbose=False)
|
||||||
assert_equal(self.nodes[2].gettransaction(txid_feeReason_four)['txid'], txid_feeReason_four)
|
assert_equal(self.nodes[2].gettransaction(txid_feeReason_four)['txid'], txid_feeReason_four)
|
||||||
|
|
||||||
|
self.log.info("Testing 'listunspent' outputs the parent descriptor(s) of coins")
|
||||||
|
# Create two multisig descriptors, and send a UTxO each.
|
||||||
|
multi_a = descsum_create("wsh(multi(1,tpubD6NzVbkrYhZ4YBNjUo96Jxd1u4XKWgnoc7LsA1jz3Yc2NiDbhtfBhaBtemB73n9V5vtJHwU6FVXwggTbeoJWQ1rzdz8ysDuQkpnaHyvnvzR/*,tpubD6NzVbkrYhZ4YHdDGMAYGaWxMSC1B6tPRTHuU5t3BcfcS3nrF523iFm5waFd1pP3ZvJt4Jr8XmCmsTBNx5suhcSgtzpGjGMASR3tau1hJz4/*))")
|
||||||
|
multi_b = descsum_create("wsh(multi(1,tpubD6NzVbkrYhZ4YHdDGMAYGaWxMSC1B6tPRTHuU5t3BcfcS3nrF523iFm5waFd1pP3ZvJt4Jr8XmCmsTBNx5suhcSgtzpGjGMASR3tau1hJz4/*,tpubD6NzVbkrYhZ4Y2RLiuEzNQkntjmsLpPYDm3LTRBYynUQtDtpzeUKAcb9sYthSFL3YR74cdFgF5mW8yKxv2W2CWuZDFR2dUpE5PF9kbrVXNZ/*))")
|
||||||
|
addr_a = self.nodes[0].deriveaddresses(multi_a, 0)[0]
|
||||||
|
addr_b = self.nodes[0].deriveaddresses(multi_b, 0)[0]
|
||||||
|
txid_a = self.nodes[0].sendtoaddress(addr_a, 0.01)
|
||||||
|
txid_b = self.nodes[0].sendtoaddress(addr_b, 0.01)
|
||||||
|
self.generate(self.nodes[0], 1, sync_fun=self.no_op)
|
||||||
|
# Now import the descriptors, make sure we can identify on which descriptor each coin was received.
|
||||||
|
self.nodes[0].createwallet(wallet_name="wo", descriptors=True, disable_private_keys=True)
|
||||||
|
wo_wallet = self.nodes[0].get_wallet_rpc("wo")
|
||||||
|
wo_wallet.importdescriptors([
|
||||||
|
{
|
||||||
|
"desc": multi_a,
|
||||||
|
"active": False,
|
||||||
|
"timestamp": "now",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": multi_b,
|
||||||
|
"active": False,
|
||||||
|
"timestamp": "now",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
coins = wo_wallet.listunspent(minconf=0)
|
||||||
|
assert_equal(len(coins), 2)
|
||||||
|
coin_a = next(c for c in coins if c["txid"] == txid_a)
|
||||||
|
assert_equal(coin_a["parent_descs"][0], multi_a)
|
||||||
|
coin_b = next(c for c in coins if c["txid"] == txid_b)
|
||||||
|
assert_equal(coin_b["parent_descs"][0], multi_b)
|
||||||
|
self.nodes[0].unloadwallet("wo")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
WalletTest().main()
|
WalletTest().main()
|
||||||
|
|||||||
Reference in New Issue
Block a user