@gmaxwell pointed out the lack of grace period in #9490#issue-199407998.
The importwallet RPC which uses key timestamps in a similar way already has a 2 hour grace period.
Concept ACK.
So one consequence of this is that if you use the manual pruning you will potentially prune past the time your imports will attempt to search, and then fail.
Yes. Though I’m not sure that warrants any changes. After all it’s the same for importwallet already.
At the least this grace period needs to be clearly documented in the RPC help so that it can be taken into account.
1071@@ -1072,7 +1072,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
1072 }
1073
1074 if (fRescan && fRunScan && requests.size() && nLowestTimestamp <= chainActive.Tip()->GetBlockTimeMax()) {
1075- CBlockIndex* pindex = nLowestTimestamp > minimumTimestamp ? chainActive.FindEarliestAtLeast(nLowestTimestamp) : chainActive.Genesis();
1076+ CBlockIndex* pindex = nLowestTimestamp > minimumTimestamp ? chainActive.FindEarliestAtLeast(nLowestTimestamp - 7200) : chainActive.Genesis();
So one consequence of this is that if you use the manual pruning you will potentially prune past the time your imports will attempt to search, and then fail.
Yes. Though I’m not sure that warrants any changes. After all it’s the same for importwallet already.
I would want to address this by only adding the grace period when fPruneMode
is false. The way I see it, if you’re using the rescan feature on a pruned node, you already have to be pretty careful, and while there are real improvements we can make for pruned nodes (like marking keys that could have incomplete transaction lists, or looking for spendable outputs in the utxo set in #9137), adding a grace period for importmulti rescans on pruned nodes is only a slightly useful thing to begin with, so it would be simplest for the code and for users to just keep the current behavior in this case.
At the least this grace period needs to be clearly documented in the RPC help so that it can be taken into account.
Will add a short note.
This change was discussed some on IRC: https://botbot.me/freenode/bitcoin-core-dev/msg/80989053/ https://botbot.me/freenode/bitcoin-core-dev/msg/81013278/
Created #9773 to deal with the issue of pruned nodes. morcos argued against removing the grace period when fPruneMode was false because not having a grace period could potentially lead to missing transaction data, and gmaxwell argued against disabling importmulti rescans on pruned nodes because partial rescanning is an important feature for pruned nodes, so #9773 deals with the issue by returning errors from importmulti when rescans fail because blocks are missing or corrupt.
Still need to add some documentation about the grace period, and add a min call to avoid passing negative values to FindEarliestAtLeast, but the bulk of the code in this PR (i.e. import-rescan.py) is ready for review.
Get rid of partial functions so the test can be more easily extended to add
more variants of imports with options that affect rescanning (e.g. different
key timestamps).
Also change the second half of the test to send /to/ the imported addresses,
instead of /from/ the imported addresses. The goal of this part of the test was
to confirm that the wallet would pick up new transactions after an import
regardless of whether or not a rescan happened during the import. But because
the wallet can only do this reliably for incoming transactions and not outgoing
transactions (which require the wallet to look up transaction inputs) the test
previously was less meaningful than it should have been.
Gregory Maxwell <greg@xiph.org> pointed out the lack of grace period in
https://github.com/bitcoin/bitcoin/pull/9490#issue-199407998.
The importwallet RPC which uses key timestamps in a similar way already has a 2
hour grace period.
utACK e662af3
Please tag 0.14 only reviewed code changes did not review test changes
1072@@ -1072,7 +1073,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
1073 }
1074
1075 if (fRescan && fRunScan && requests.size() && nLowestTimestamp <= chainActive.Tip()->GetBlockTimeMax()) {
1076- CBlockIndex* pindex = nLowestTimestamp > minimumTimestamp ? chainActive.FindEarliestAtLeast(nLowestTimestamp) : chainActive.Genesis();
1077+ CBlockIndex* pindex = nLowestTimestamp > minimumTimestamp ? chainActive.FindEarliestAtLeast(std::max<int64_t>(nLowestTimestamp - 7200, 0)) : chainActive.Genesis();
nit: I think this should be std::max<int64_t>(nLowestTimestamp - 7200, minimumTimestamp)
I only mention because I’m unsure if 0 has a special meaning somewhere.
0 has special meaning for the CWallet::nTimeFirstKey variable, but I recently removed all outside references to that variable and made it private so that no other code that wasn’t dealing with it directly would have to worry about special meanings of 0.
minimumTimestamp would work fine if it were set to 0 instead of 1, and I have some local changes to remove this variable, so I didn’t want to add another use here.
Concept ACK, although as commented in #9778, if these grace periods need to be consistent, I think we should have a constant (also used for normal rescan?).
Yes, would make sense to define a constant. No, that does not need to hold up merging this.