mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-05-05 03:18:50 +02:00
Merge bitcoin/bitcoin#25504: RPC: allow to track coins by parent descriptors
a6b0c1fcc0doc: add releases notes for 25504 (listsinceblock updates) (Antoine Poinsot)0fd2d14454rpc: add an include_change parameter to listsinceblock (Antoine Poinsot)55f98d087erpc: output parent wallet descriptors for coins in listunspent (Antoine Poinsot)b724476158rpc: output wallet descriptors for received entries in listsinceblock (Antoine Poinsot)55a82eaf91wallet: allow to fetch the wallet descriptors for a given Script (Antoine Poinsot) Pull request description: Wallet descriptors are useful for applications using the Bitcoin Core wallet as a backend for tracking coins, as they allow to track coins for multiple descriptors in a single wallet. However there is no information currently given for such applications to link a coin with an imported descriptor, severely limiting the possibilities for such applications of using multiple descriptors in a single wallet. This PR outputs the matching imported descriptor(s) for a given received coin in `listsinceblock` (and friends). It comes from a need for an application i'm working on, but i think it's something any software using `bitcoind` to track multiple descriptors in a single wallet would have eventually. For instance i'm thinking about the BDK project. Currently, the way to achieve this is to import raw addresses with labels and to have your application be responsible for wallet things like the gap limit. I'll add this to the output of `listunspent` too if this gets a few Concept ACKs. ACKs for top commit: instagibbs: ACKa6b0c1fcc0achow101: re-ACKa6b0c1fcc0Tree-SHA512: 7a5850e8de98b439ddede2cb72de0208944f8cda67272e8b8037678738d55b7a5272375be808b0f7d15def4904430e089dafdcc037436858ff3292c5f8b75e37
This commit is contained in:
@@ -315,13 +315,16 @@ static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
|
||||
* @param filter_label Optional label string to filter incoming transactions.
|
||||
*/
|
||||
template <class Vec>
|
||||
static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nMinDepth, bool fLong, Vec& ret, const isminefilter& filter_ismine, const std::string* filter_label) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
|
||||
static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nMinDepth, bool fLong,
|
||||
Vec& ret, const isminefilter& filter_ismine, const std::string* filter_label,
|
||||
bool include_change = false)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
|
||||
{
|
||||
CAmount nFee;
|
||||
std::list<COutputEntry> listReceived;
|
||||
std::list<COutputEntry> listSent;
|
||||
|
||||
CachedTxGetAmounts(wallet, wtx, listReceived, listSent, nFee, filter_ismine);
|
||||
CachedTxGetAmounts(wallet, wtx, listReceived, listSent, nFee, filter_ismine, include_change);
|
||||
|
||||
bool involvesWatchonly = CachedTxIsFromMe(wallet, wtx, ISMINE_WATCH_ONLY);
|
||||
|
||||
@@ -367,6 +370,7 @@ static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nM
|
||||
entry.pushKV("involvesWatchonly", true);
|
||||
}
|
||||
MaybePushAddress(entry, r.destination);
|
||||
PushParentDescriptors(wallet, wtx.tx->vout.at(r.vout).scriptPubKey, entry);
|
||||
if (wtx.IsCoinBase())
|
||||
{
|
||||
if (wallet.GetTxDepthInMainChain(wtx) < 1)
|
||||
@@ -418,7 +422,11 @@ static const std::vector<RPCResult> TransactionDescriptionString()
|
||||
{RPCResult::Type::NUM_TIME, "timereceived", "The time received expressed in " + UNIX_EPOCH_TIME + "."},
|
||||
{RPCResult::Type::STR, "comment", /*optional=*/true, "If a comment is associated with the transaction, only present if not empty."},
|
||||
{RPCResult::Type::STR, "bip125-replaceable", "(\"yes|no|unknown\") Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n"
|
||||
"may be unknown for unconfirmed transactions not in the mempool."}};
|
||||
"may be unknown for unconfirmed transactions not in the mempool."},
|
||||
{RPCResult::Type::ARR, "parent_descs", /*optional=*/true, "Only if 'category' is 'received'. List of parent descriptors for the scriptPubKey of this coin.", {
|
||||
{RPCResult::Type::STR, "desc", "The descriptor string."},
|
||||
}},
|
||||
};
|
||||
}
|
||||
|
||||
RPCHelpMan listtransactions()
|
||||
@@ -543,6 +551,7 @@ RPCHelpMan listsinceblock()
|
||||
{"include_watchonly", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Include transactions to watch-only addresses (see 'importaddress')"},
|
||||
{"include_removed", RPCArg::Type::BOOL, RPCArg::Default{true}, "Show transactions that were removed due to a reorg in the \"removed\" array\n"
|
||||
"(not guaranteed to work on pruned nodes)"},
|
||||
{"include_change", RPCArg::Type::BOOL, RPCArg::Default{false}, "Also add entries for change outputs.\n"},
|
||||
},
|
||||
RPCResult{
|
||||
RPCResult::Type::OBJ, "", "",
|
||||
@@ -623,6 +632,7 @@ RPCHelpMan listsinceblock()
|
||||
}
|
||||
|
||||
bool include_removed = (request.params[3].isNull() || request.params[3].get_bool());
|
||||
bool include_change = (!request.params[4].isNull() && request.params[4].get_bool());
|
||||
|
||||
int depth = height ? wallet.GetLastBlockHeight() + 1 - *height : -1;
|
||||
|
||||
@@ -632,7 +642,7 @@ RPCHelpMan listsinceblock()
|
||||
const CWalletTx& tx = pairWtx.second;
|
||||
|
||||
if (depth == -1 || abs(wallet.GetTxDepthInMainChain(tx)) < depth) {
|
||||
ListTransactions(wallet, tx, 0, true, transactions, filter, nullptr /* filter_label */);
|
||||
ListTransactions(wallet, tx, 0, true, transactions, filter, nullptr /* filter_label */, /*include_change=*/include_change);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -649,7 +659,7 @@ RPCHelpMan listsinceblock()
|
||||
if (it != wallet.mapWallet.end()) {
|
||||
// We want all transactions regardless of confirmation count to appear here,
|
||||
// even negative confirmation ones, hence the big negative.
|
||||
ListTransactions(wallet, it->second, -100000000, true, removed, filter, nullptr /* filter_label */);
|
||||
ListTransactions(wallet, it->second, -100000000, true, removed, filter, nullptr /* filter_label */, /*include_change=*/include_change);
|
||||
}
|
||||
}
|
||||
blockId = block.hashPrevBlock;
|
||||
@@ -709,6 +719,9 @@ RPCHelpMan gettransaction()
|
||||
"'send' category of transactions."},
|
||||
{RPCResult::Type::BOOL, "abandoned", /*optional=*/true, "'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
|
||||
"'send' category of transactions."},
|
||||
{RPCResult::Type::ARR, "parent_descs", /*optional=*/true, "Only if 'category' is 'received'. List of parent descriptors for the scriptPubKey of this coin.", {
|
||||
{RPCResult::Type::STR, "desc", "The descriptor string."},
|
||||
}},
|
||||
}},
|
||||
}},
|
||||
{RPCResult::Type::STR_HEX, "hex", "Raw data for transaction"},
|
||||
|
||||
Reference in New Issue
Block a user