Skip to content

Commit e63410e

Browse files
Merge dashpay#7028: backport: auto 20251202
4e43e6b partial bitcoin#26094: rpc: Return block hash & height in getbalances, gettransaction and getwalletinfo (#1182) (PastaBot) 9af554c Merge bitcoin#25975: contrib/init: Better systemd integration (PastaBot) 4313de4 Merge bitcoin#27657: doc: Remove unused NO_BLOOM_VERSION constant (PastaBot) Pull request description: ## Issue being fixed or feature implemented batch of automated backports ## What was done? Small batch of auto backports ## How Has This Been Tested? CI ## Breaking Changes ## Checklist: - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ ACKs for top commit: knst: utACK 4e43e6b (if CI succeed) UdjinM6: utACK 4e43e6b Tree-SHA512: a14c80aa4a26035f3fe9550048b3b6d0c9f316d78aa8e13bb9c9d2f5aabaaac0a0e78b182174c01709539eedfa76f29f060f5cf1cdf1dbcae2dd134edcb64066
2 parents b12e32d + 4e43e6b commit e63410e

File tree

10 files changed

+76
-13
lines changed

10 files changed

+76
-13
lines changed

contrib/init/dashd.service

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ After=network-online.target
1818
Wants=network-online.target
1919

2020
[Service]
21-
ExecStart=/usr/bin/dashd -daemonwait \
22-
-pid=/run/dashd/dashd.pid \
23-
-conf=/etc/dash/dash.conf \
24-
-datadir=/var/lib/dashd
21+
ExecStart=/usr/bin/dashd -pid=/run/dashd/dashd.pid \
22+
-conf=/etc/dash/dash.conf \
23+
-datadir=/var/lib/dashd \
24+
-startupnotify='systemd-notify --ready' \
25+
-shutdownnotify='systemd-notify --stopping'
2526

2627
# Make sure the config directory is readable by the service user
2728
PermissionsStartOnly=true
@@ -30,8 +31,10 @@ ExecStartPre=/bin/chgrp dashcore /etc/dash
3031
# Process management
3132
####################
3233

33-
Type=forking
34+
Type=notify
35+
NotifyAccess=all
3436
PIDFile=/run/dashd/dashd.pid
37+
3538
Restart=on-failure
3639
TimeoutStartSec=infinity
3740
TimeoutStopSec=600

doc/release-notes-26094.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
- The `getbalances` RPC now returns a `lastprocessedblock` JSON object which contains the wallet's last processed block
2+
hash and height at the time the balances were calculated. This result shouldn't be cached because importing new keys could invalidate it.
3+
- The `gettransaction` RPC now returns a `lastprocessedblock` JSON object which contains the wallet's last processed block
4+
hash and height at the time the transaction information was generated.
5+
- The `getwalletinfo` RPC now returns a `lastprocessedblock` JSON object which contains the wallet's last processed block
6+
hash and height at the time the wallet information was generated.

src/protocol.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,8 @@ extern const char* GETADDR;
134134
/**
135135
* The mempool message requests the TXIDs of transactions that the receiving
136136
* node has verified as valid but which have not yet appeared in a block.
137-
* @since protocol version 60002.
137+
* @since protocol version 60002 as described by BIP35.
138+
* Only available with service bit NODE_BLOOM, see also BIP111.
138139
*/
139140
extern const char* MEMPOOL;
140141
/**
@@ -315,8 +316,6 @@ enum ServiceFlags : uint64_t {
315316
// set by all Dash Core non pruned nodes, and is unset by SPV clients or other light clients.
316317
NODE_NETWORK = (1 << 0),
317318
// NODE_BLOOM means the node is capable and willing to handle bloom-filtered connections.
318-
// Dash Core nodes used to support this by default, without advertising this bit,
319-
// but no longer do as of protocol version 70201 (= NO_BLOOM_VERSION)
320319
NODE_BLOOM = (1 << 2),
321320
// NODE_COMPACT_FILTERS means the node will service basic block filter requests.
322321
// See BIP157 and BIP158 for details on how this is implemented.

src/wallet/rpc/coins.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,7 @@ RPCHelpMan getbalances()
452452
{RPCResult::Type::STR_AMOUNT, "untrusted_pending", " untrusted pending balance (outputs created by others that are in the mempool)"},
453453
{RPCResult::Type::STR_AMOUNT, "immature", " balance from immature coinbase outputs"},
454454
}},
455+
RESULT_LAST_PROCESSED_BLOCK,
455456
},
456457
},
457458
RPCExamples{
@@ -494,6 +495,8 @@ RPCHelpMan getbalances()
494495
balances_watchonly.pushKV("immature", ValueFromAmount(bal.m_watchonly_immature));
495496
balances.pushKV("watchonly", balances_watchonly);
496497
}
498+
499+
AppendLastProcessedBlock(balances, wallet);
497500
return balances;
498501
},
499502
};

src/wallet/rpc/transactions.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,7 @@ RPCHelpMan gettransaction()
736736
{
737737
{RPCResult::Type::ELISION, "", "RPC decoderawtransaction method, or the RPC getrawtransaction method when `verbose` is passed."},
738738
}},
739+
RESULT_LAST_PROCESSED_BLOCK,
739740
}),
740741
},
741742
RPCExamples{
@@ -795,6 +796,7 @@ RPCHelpMan gettransaction()
795796
entry.pushKV("decoded", decoded);
796797
}
797798

799+
AppendLastProcessedBlock(entry, *pwallet);
798800
return entry;
799801
},
800802
};

src/wallet/rpc/util.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,4 +164,14 @@ void HandleWalletError(const std::shared_ptr<CWallet> wallet, DatabaseStatus& st
164164
throw JSONRPCError(code, error.original);
165165
}
166166
}
167+
168+
void AppendLastProcessedBlock(UniValue& entry, const CWallet& wallet) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
169+
{
170+
AssertLockHeld(wallet.cs_wallet);
171+
UniValue lastprocessedblock{UniValue::VOBJ};
172+
lastprocessedblock.pushKV("hash", wallet.GetLastBlockHash().GetHex());
173+
lastprocessedblock.pushKV("height", wallet.GetLastBlockHeight());
174+
entry.pushKV("lastprocessedblock", lastprocessedblock);
175+
}
176+
167177
} // namespace wallet

src/wallet/rpc/util.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#define BITCOIN_WALLET_RPC_UTIL_H
77

88
#include <context.h>
9+
#include <rpc/util.h>
10+
#include <wallet/wallet.h>
911

1012
#include <memory>
1113
#include <string>
@@ -16,13 +18,17 @@ class JSONRPCRequest;
1618
class UniValue;
1719

1820
namespace wallet {
19-
class CWallet;
2021
class LegacyScriptPubKeyMan;
2122
enum class DatabaseStatus;
2223
struct WalletContext;
2324

2425
extern const std::string HELP_REQUIRING_PASSPHRASE;
2526

27+
static const RPCResult RESULT_LAST_PROCESSED_BLOCK { RPCResult::Type::OBJ, "lastprocessedblock", "hash and height of the block this information was generated on",{
28+
{RPCResult::Type::STR_HEX, "hash", "hash of the block this information was generated on"},
29+
{RPCResult::Type::NUM, "height", "height of the block this information was generated on"}}
30+
};
31+
2632
/**
2733
* Figures out what wallet, if any, to use for a JSONRPCRequest.
2834
*
@@ -43,6 +49,7 @@ std::string LabelFromValue(const UniValue& value);
4349

4450
void HandleWalletError(const std::shared_ptr<CWallet> wallet, DatabaseStatus& status, bilingual_str& error);
4551
int64_t ParseISO8601DateTime(const std::string& str);
52+
void AppendLastProcessedBlock(UniValue& entry, const CWallet& wallet) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
4653
} // namespace wallet
4754

4855
#endif // BITCOIN_WALLET_RPC_UTIL_H

src/wallet/rpc/wallet.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ static RPCHelpMan getwalletinfo()
192192
}},
193193
{RPCResult::Type::BOOL, "descriptors", "whether this wallet uses descriptors for scriptPubKey management"},
194194
{RPCResult::Type::BOOL, "external_signer", "whether this wallet is configured to use an external signer such as a hardware wallet"},
195+
RESULT_LAST_PROCESSED_BLOCK,
195196
},
196197
},
197198
RPCExamples{
@@ -270,6 +271,8 @@ static RPCHelpMan getwalletinfo()
270271
}
271272
obj.pushKV("descriptors", pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
272273
obj.pushKV("external_signer", pwallet->IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER));
274+
275+
AppendLastProcessedBlock(obj, *pwallet);
273276
return obj;
274277
},
275278
};

test/functional/wallet_balance.py

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from test_framework.test_framework import BitcoinTestFramework
1212
from test_framework.util import (
1313
assert_equal,
14+
assert_is_hash_string,
1415
assert_raises_rpc_error,
1516
)
1617

@@ -174,8 +175,13 @@ def test_balances(*, fee_node_1=0):
174175
'untrusted_pending': Decimal('30.0') - fee_node_1}} # Doesn't include output of node 0's send since it was spent
175176
if self.options.descriptors:
176177
del expected_balances_0["watchonly"]
177-
assert_equal(self.nodes[0].getbalances(), expected_balances_0)
178-
assert_equal(self.nodes[1].getbalances(), expected_balances_1)
178+
balances_0 = self.nodes[0].getbalances()
179+
balances_1 = self.nodes[1].getbalances()
180+
# remove lastprocessedblock keys (they will be tested later)
181+
del balances_0['lastprocessedblock']
182+
del balances_1['lastprocessedblock']
183+
assert_equal(balances_0, expected_balances_0)
184+
assert_equal(balances_1, expected_balances_1)
179185
# getbalance without any arguments includes unconfirmed transactions, but not untrusted transactions
180186
assert_equal(self.nodes[0].getbalance(), Decimal('9.99')) # change from node 0's send
181187
assert_equal(self.nodes[1].getbalance(), Decimal('0')) # node 1's send had an unsafe input
@@ -304,5 +310,30 @@ def test_balances(*, fee_node_1=0):
304310
assert_equal(self.nodes[0].getbalances()['mine']['untrusted_pending'], Decimal('0.1'))
305311

306312

313+
# Tests the lastprocessedblock JSON object in getbalances, getwalletinfo
314+
# and gettransaction by checking for valid hex strings and by comparing
315+
# the hashes & heights between generated blocks.
316+
self.log.info("Test getbalances returns expected lastprocessedblock json object")
317+
prev_hash = self.nodes[0].getbestblockhash()
318+
prev_height = self.nodes[0].getblock(prev_hash)['height']
319+
self.generatetoaddress(self.nodes[0], 5, self.nodes[0].get_deterministic_priv_key().address)
320+
lastblock = self.nodes[0].getbalances()['lastprocessedblock']
321+
assert_is_hash_string(lastblock['hash'])
322+
assert_equal((prev_hash == lastblock['hash']), False)
323+
assert_equal(lastblock['height'], prev_height + 5)
324+
325+
prev_hash = self.nodes[0].getbestblockhash()
326+
prev_height = self.nodes[0].getblock(prev_hash)['height']
327+
self.log.info("Test getwalletinfo returns expected lastprocessedblock json object")
328+
walletinfo = self.nodes[0].getwalletinfo()
329+
assert_equal(walletinfo['lastprocessedblock']['height'], prev_height)
330+
assert_equal(walletinfo['lastprocessedblock']['hash'], prev_hash)
331+
332+
self.log.info("Test gettransaction returns expected lastprocessedblock json object")
333+
txid = self.nodes[1].sendtoaddress(self.nodes[1].getnewaddress(), 0.01)
334+
tx_info = self.nodes[1].gettransaction(txid)
335+
assert_equal(tx_info['lastprocessedblock']['height'], prev_height)
336+
assert_equal(tx_info['lastprocessedblock']['hash'], prev_hash)
337+
307338
if __name__ == '__main__':
308339
WalletTest().main()

test/functional/wallet_basic.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -710,8 +710,7 @@ def run_test(self):
710710
"vout": baz["vout"]}
711711
expected_fields = frozenset({'amount', 'chainlock', 'confirmations', 'details', 'fee',
712712
'instantlock', 'instantlock_internal',
713-
'hex', 'timereceived', 'time', 'trusted', 'txid', 'walletconflicts'})
714-
713+
'hex', 'lastprocessedblock', 'timereceived', 'time', 'trusted', 'txid', 'walletconflicts'})
715714
verbose_field = "decoded"
716715
expected_verbose_fields = expected_fields | {verbose_field}
717716

0 commit comments

Comments
 (0)