mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-22 15:04:44 +01:00
Merge bitcoin/bitcoin#25934: wallet, rpc: add label
to listsinceblock
4e362c2b72
doc: add release note for 25934 (brunoerg)fe488b4c4b
test: add coverage for `label` in `listsinceblock` (brunoerg)722e9a418d
wallet, rpc: add `label` to `listsinceblock` (brunoerg)852891ff98
refactor, wallet: use optional for `label` in `ListTransactions` (brunoerg) Pull request description: This PR adds `label` parameter to `listsinceblock` to be able to fetch all incoming transactions having the specified label since a specific block. It's possible to use it in `listtransactions`, however, it's only possible to set the number of transactions to return, not a specific block to fetch from. `getreceivedbylabel` only returns the total amount received, not the txs info. `listreceivedbylabel` doesn't list all the informations about the transactions and it's not possible to fetch since a block. ACKs for top commit: achow101: ACK4e362c2b72
w0xlt: ACK4e362c2b72
aureleoules: ACK4e362c2b72
Tree-SHA512: fbde5db8cebf7a27804154fa61997b5155ad512e978cebb78c17acab9efcb624ea5f39d649899d12e5e675f80d4d0064cae8132b864de0d93a8d1e6fbcb9a737
This commit is contained in:
commit
a653f4bb1f
3 changed files with 38 additions and 9 deletions
8
doc/release-notes-25934.md
Normal file
8
doc/release-notes-25934.md
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
Low-level changes
|
||||||
|
=================
|
||||||
|
|
||||||
|
RPC
|
||||||
|
---
|
||||||
|
|
||||||
|
- RPC `listsinceblock` now accepts an optional `label` argument
|
||||||
|
to fetch incoming transactions having the specified label. (#25934)
|
|
@ -316,7 +316,7 @@ static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
|
||||||
*/
|
*/
|
||||||
template <class Vec>
|
template <class Vec>
|
||||||
static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nMinDepth, bool fLong,
|
static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nMinDepth, bool fLong,
|
||||||
Vec& ret, const isminefilter& filter_ismine, const std::string* filter_label,
|
Vec& ret, const isminefilter& filter_ismine, const std::optional<std::string>& filter_label,
|
||||||
bool include_change = false)
|
bool include_change = false)
|
||||||
EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
|
EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
|
||||||
{
|
{
|
||||||
|
@ -329,7 +329,7 @@ static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nM
|
||||||
bool involvesWatchonly = CachedTxIsFromMe(wallet, wtx, ISMINE_WATCH_ONLY);
|
bool involvesWatchonly = CachedTxIsFromMe(wallet, wtx, ISMINE_WATCH_ONLY);
|
||||||
|
|
||||||
// Sent
|
// Sent
|
||||||
if (!filter_label)
|
if (!filter_label.has_value())
|
||||||
{
|
{
|
||||||
for (const COutputEntry& s : listSent)
|
for (const COutputEntry& s : listSent)
|
||||||
{
|
{
|
||||||
|
@ -362,7 +362,7 @@ static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nM
|
||||||
if (address_book_entry) {
|
if (address_book_entry) {
|
||||||
label = address_book_entry->GetLabel();
|
label = address_book_entry->GetLabel();
|
||||||
}
|
}
|
||||||
if (filter_label && label != *filter_label) {
|
if (filter_label.has_value() && label != filter_label.value()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
UniValue entry(UniValue::VOBJ);
|
UniValue entry(UniValue::VOBJ);
|
||||||
|
@ -485,10 +485,10 @@ RPCHelpMan listtransactions()
|
||||||
// the user could have gotten from another RPC command prior to now
|
// the user could have gotten from another RPC command prior to now
|
||||||
pwallet->BlockUntilSyncedToCurrentChain();
|
pwallet->BlockUntilSyncedToCurrentChain();
|
||||||
|
|
||||||
const std::string* filter_label = nullptr;
|
std::optional<std::string> filter_label;
|
||||||
if (!request.params[0].isNull() && request.params[0].get_str() != "*") {
|
if (!request.params[0].isNull() && request.params[0].get_str() != "*") {
|
||||||
filter_label = &request.params[0].get_str();
|
filter_label = request.params[0].get_str();
|
||||||
if (filter_label->empty()) {
|
if (filter_label.value().empty()) {
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Label argument must be a valid label name or \"*\".");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Label argument must be a valid label name or \"*\".");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -552,6 +552,7 @@ RPCHelpMan listsinceblock()
|
||||||
{"include_removed", RPCArg::Type::BOOL, RPCArg::Default{true}, "Show transactions that were removed due to a reorg in the \"removed\" array\n"
|
{"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)"},
|
"(not guaranteed to work on pruned nodes)"},
|
||||||
{"include_change", RPCArg::Type::BOOL, RPCArg::Default{false}, "Also add entries for change outputs.\n"},
|
{"include_change", RPCArg::Type::BOOL, RPCArg::Default{false}, "Also add entries for change outputs.\n"},
|
||||||
|
{"label", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "Return only incoming transactions paying to addresses with the specified label.\n"},
|
||||||
},
|
},
|
||||||
RPCResult{
|
RPCResult{
|
||||||
RPCResult::Type::OBJ, "", "",
|
RPCResult::Type::OBJ, "", "",
|
||||||
|
@ -634,6 +635,11 @@ RPCHelpMan listsinceblock()
|
||||||
bool include_removed = (request.params[3].isNull() || request.params[3].get_bool());
|
bool include_removed = (request.params[3].isNull() || request.params[3].get_bool());
|
||||||
bool include_change = (!request.params[4].isNull() && request.params[4].get_bool());
|
bool include_change = (!request.params[4].isNull() && request.params[4].get_bool());
|
||||||
|
|
||||||
|
std::optional<std::string> filter_label;
|
||||||
|
if (!request.params[5].isNull()) {
|
||||||
|
filter_label = request.params[5].get_str();
|
||||||
|
}
|
||||||
|
|
||||||
int depth = height ? wallet.GetLastBlockHeight() + 1 - *height : -1;
|
int depth = height ? wallet.GetLastBlockHeight() + 1 - *height : -1;
|
||||||
|
|
||||||
UniValue transactions(UniValue::VARR);
|
UniValue transactions(UniValue::VARR);
|
||||||
|
@ -642,7 +648,7 @@ RPCHelpMan listsinceblock()
|
||||||
const CWalletTx& tx = pairWtx.second;
|
const CWalletTx& tx = pairWtx.second;
|
||||||
|
|
||||||
if (depth == -1 || abs(wallet.GetTxDepthInMainChain(tx)) < depth) {
|
if (depth == -1 || abs(wallet.GetTxDepthInMainChain(tx)) < depth) {
|
||||||
ListTransactions(wallet, tx, 0, true, transactions, filter, /*filter_label=*/nullptr, /*include_change=*/include_change);
|
ListTransactions(wallet, tx, 0, true, transactions, filter, filter_label, include_change);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -659,7 +665,7 @@ RPCHelpMan listsinceblock()
|
||||||
if (it != wallet.mapWallet.end()) {
|
if (it != wallet.mapWallet.end()) {
|
||||||
// We want all transactions regardless of confirmation count to appear here,
|
// We want all transactions regardless of confirmation count to appear here,
|
||||||
// even negative confirmation ones, hence the big negative.
|
// even negative confirmation ones, hence the big negative.
|
||||||
ListTransactions(wallet, it->second, -100000000, true, removed, filter, /*filter_label=*/nullptr, /*include_change=*/include_change);
|
ListTransactions(wallet, it->second, -100000000, true, removed, filter, filter_label, include_change);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
blockId = block.hashPrevBlock;
|
blockId = block.hashPrevBlock;
|
||||||
|
@ -777,7 +783,7 @@ RPCHelpMan gettransaction()
|
||||||
WalletTxToJSON(*pwallet, wtx, entry);
|
WalletTxToJSON(*pwallet, wtx, entry);
|
||||||
|
|
||||||
UniValue details(UniValue::VARR);
|
UniValue details(UniValue::VARR);
|
||||||
ListTransactions(*pwallet, wtx, 0, false, details, filter, /*filter_label=*/nullptr);
|
ListTransactions(*pwallet, wtx, 0, false, details, filter, /*filter_label=*/std::nullopt);
|
||||||
entry.pushKV("details", details);
|
entry.pushKV("details", details);
|
||||||
|
|
||||||
std::string strHex = EncodeHexTx(*wtx.tx, pwallet->chain().rpcSerializationFlags());
|
std::string strHex = EncodeHexTx(*wtx.tx, pwallet->chain().rpcSerializationFlags());
|
||||||
|
|
|
@ -49,6 +49,7 @@ class ListSinceBlockTest(BitcoinTestFramework):
|
||||||
self.test_desc()
|
self.test_desc()
|
||||||
self.test_send_to_self()
|
self.test_send_to_self()
|
||||||
self.test_op_return()
|
self.test_op_return()
|
||||||
|
self.test_label()
|
||||||
|
|
||||||
def test_no_blockhash(self):
|
def test_no_blockhash(self):
|
||||||
self.log.info("Test no blockhash")
|
self.log.info("Test no blockhash")
|
||||||
|
@ -465,6 +466,20 @@ class ListSinceBlockTest(BitcoinTestFramework):
|
||||||
|
|
||||||
assert 'address' not in op_ret_tx
|
assert 'address' not in op_ret_tx
|
||||||
|
|
||||||
|
def test_label(self):
|
||||||
|
self.log.info('Test passing "label" argument fetches incoming transactions having the specified label')
|
||||||
|
new_addr = self.nodes[1].getnewaddress(label="new_addr", address_type="bech32")
|
||||||
|
|
||||||
|
self.nodes[2].sendtoaddress(address=new_addr, amount="0.001")
|
||||||
|
self.generate(self.nodes[2], 1)
|
||||||
|
|
||||||
|
for label in ["new_addr", ""]:
|
||||||
|
new_addr_transactions = self.nodes[1].listsinceblock(label=label)["transactions"]
|
||||||
|
assert_equal(len(new_addr_transactions), 1)
|
||||||
|
assert_equal(new_addr_transactions[0]["label"], label)
|
||||||
|
if label == "new_addr":
|
||||||
|
assert_equal(new_addr_transactions[0]["address"], new_addr)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
ListSinceBlockTest().main()
|
ListSinceBlockTest().main()
|
||||||
|
|
Loading…
Add table
Reference in a new issue