In this PR, "timestamp": "now" is represented as std::nullopt in ImportDescriptorRequest::timestamp (master resolves "now" immediately to an int64_t). So this branch can’t call requests.at(i).timestamp.value(), because there is no value for "now".
The code needs to use the resolved timestamp computed earlier from std::max(request.timestamp.value_or(now), minimum_timestamp).
Suggested patch (with a new test to cover this case):
<details>
<summary>diff</summary>
diff --git a/src/wallet/imports.cpp b/src/wallet/imports.cpp
index 5f9c4ca99b..4a268b3f3d 100644
--- a/src/wallet/imports.cpp
+++ b/src/wallet/imports.cpp
@@ -170,6 +170,8 @@ namespace wallet{
std::vector<wallet::ImportDescriptorRequest> requests)
{
std::vector<wallet::ImportDescriptorResult> response;
+ std::vector<int64_t> resolved_timestamps;
+ resolved_timestamps.reserve(requests.size());
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -210,6 +212,7 @@ namespace wallet{
for (wallet::ImportDescriptorRequest& request : requests) {
const int64_t timestamp = std::max(request.timestamp.value_or(now), minimum_timestamp);
+ resolved_timestamps.push_back(timestamp);
wallet::ImportDescriptorResult result = wallet::ImportDescriptor(
wallet,
request.descriptor,
@@ -257,14 +260,16 @@ namespace wallet{
// range, or if the import result already has an error set, let
// the result stand unmodified. Otherwise replace the result
// with an error message.
- if (scanned_time <= requests.at(i).timestamp.value() || !result.success) continue;
+ const int64_t timestamp{resolved_timestamps.at(i)};
+ if (scanned_time <= timestamp || !result.success) continue;
+ const int64_t error_timestamp{requests.at(i).timestamp.value_or(timestamp)};
result.success = false;
std::string error_msg = strprintf("Rescan failed for descriptor with timestamp %d. There "
"was an error reading a block from time %d, which is after or within %d seconds "
"of key creation, and could contain transactions pertaining to the desc. As a "
"result, transactions and coins using this desc may not appear in the wallet.",
- requests.at(i).timestamp.value(), scanned_time - TIMESTAMP_WINDOW - 1, TIMESTAMP_WINDOW);
+ error_timestamp, scanned_time - TIMESTAMP_WINDOW - 1, TIMESTAMP_WINDOW);
if (wallet.chain().havePruned()) {
error_msg += strprintf(" This error could be caused by pruning or data corruption "
"(see bitcoind log for details) and could be dealt with by downloading and "
diff --git a/test/functional/wallet_assumeutxo.py b/test/functional/wallet_assumeutxo.py
index a8c97be778..9e05028316 100755
--- a/test/functional/wallet_assumeutxo.py
+++ b/test/functional/wallet_assumeutxo.py
@@ -215,12 +215,18 @@ class AssumeutxoTest(BitcoinTestFramework):
wallet_name = "w1"
n1.createwallet(wallet_name, disable_private_keys=True)
key = get_generate_key()
- time = n1.getblockchaininfo()['time']
+ block_info = n1.getblockchaininfo()
+ time = block_info['time']
+ def expected_rescan_error(timestamp):
+ return f"Rescan failed for descriptor with timestamp {timestamp}. There was an error reading a block from time {time}, which is after or within 7200 seconds of key creation, and could contain transactions pertaining to the desc. As a result, transactions and coins using this desc may not appear in the wallet. This error is likely caused by an in-progress assumeutxo background sync. Check logs or getchainstates RPC for assumeutxo background sync progress and try again later."
timestamp = 0
- expected_error_message = f"Rescan failed for descriptor with timestamp {timestamp}. There was an error reading a block from time {time}, which is after or within 7200 seconds of key creation, and could contain transactions pertaining to the desc. As a result, transactions and coins using this desc may not appear in the wallet. This error is likely caused by an in-progress assumeutxo background sync. Check logs or getchainstates RPC for assumeutxo background sync progress and try again later."
result = self.import_descriptor(n1, wallet_name, key, timestamp)
assert_equal(result[0]['error']['code'], -1)
- assert_equal(result[0]['error']['message'], expected_error_message)
+ assert_equal(result[0]['error']['message'], expected_rescan_error(timestamp))
+ now_timestamp = block_info['mediantime']
+ result = self.import_descriptor(n1, wallet_name, get_generate_key(), "now")
+ assert_equal(result[0]['error']['code'], -1)
+ assert_equal(result[0]['error']['message'], expected_rescan_error(now_timestamp))
self.log.info("Test that rescanning blocks from before the snapshot fails when blocks are not available from the background sync yet")
w1 = n1.get_wallet_rpc(wallet_name)
</details>