-
Notifications
You must be signed in to change notification settings - Fork 37.7k
Add scanblocks RPC call (attempt 2) #23549
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
c0c2115
to
1e5ec5f
Compare
Previously involved:
|
Thanks for reviving 20664. There are many interesting PRs by jonasschnelli which never got merged for different reasons. Will test it this weekend. |
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
I tried the syntax based on example mentioned in PR description and it gives me an error:
I checked the code for RPC help but don't understand what exactly should be enabled and how are filters used in this RPC |
You probably did not run I guess that issue could be caught earlier and use a better error message :) |
Thanks for the help @fjahr. Tried running
Got response after few minutes with lot of block hashes. I was expecting a quick response based on concept of this PR and time it took for |
Concept ACK Is there plans to add functionality similiar to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept re-ACK. Thanks for picking this up! 👍
Did a first quick test on signet with a coinbase tx address from an arbitrary block (height 1337) that is spent about 1000 blocks later (https://explorer.bc-2.jp/address/tb1q6tnc9k7a3pdufryr9tpttjulh97g838vljyrgx):
$ ./src/bitcoind -signet -blockfilterindex=1 &
$ ./src/bitcoin-cli -signet scanblocks start '["addr(tb1q6tnc9k7a3pdufryr9tpttjulh97g838vljyrgx)"]'
{
"from_height": 0,
"to_height": 66345,
"relevant_blocks": [
"00000109e0671e4b8bc44ae1f08a6a87d656968d08e264f20631ed32f69fbea8",
"00000030b26a4a94272999a68068adf0b617beef9caac51d6ff003dbf4bd8223"
]
}
On a quick glance over the second commit, I saw that the help examples are not working, see comment below. Will review more in-depth within the next days.
c1e71fb
to
e1c8918
Compare
@theStack fixed, thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NACK
Based on my testing I was not able to do fast scan as mentioned in OP:
Why is this useful?
Fast wallet rescans: get the relevant blocks and only rescan those via rescanblockchain getblockheader()[height] getblockheader()[height]). A future PR may add an option to allow to provide an array of blockhashes to rescanblockchain.
@prayank23 Without blockfilters it would take many times longer, and without this PR the functionality to scan blocks doesn't exist at all. |
@sipa is that considering the time it takes for |
@prayank23 You only need to build the filters once, and you need them too for -peerblockfilters (if you want to support BIP157 protocol). |
src/rpc/blockchain.cpp
Outdated
static const auto scan_result_abort = RPCResult{"When action=='abort'", RPCResult::Type::BOOL, "", ""}; | ||
static const auto scan_result_status_none = RPCResult{"When action=='status' and no scan is in progress", RPCResult::Type::NONE, "", ""}; | ||
static const auto scan_result_status_some = RPCResult{ | ||
"When action=='status' and scan is in progress", RPCResult::Type::OBJ, "", "", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other RPC docs use plain English "if verbose is not set or set to false"
Suggest adopting the language used in prior revisions of this feature
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what you mean here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean we should stick to either plain English or pseudo-code for docs, but avoid mixing the two.
src/rpc/blockchain.cpp
Outdated
} | ||
} | ||
if (!request.params[3].isNull()) { | ||
stop_block = active_chain[request.params[3].get_int()]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's possible this block could be reorg'd out during the scan, and then it won't stop until it reaches the new best block?
I guess if it was reorg'd out, it probably doesn't matter, but might be nice to fix.
Proposed changes (feel free to squash): jamesob/bitcoin@2021-11-scanblocks...luke-jr:rpc_scanblocks |
Co-authored-by: James O'Beirne <james.obeirne@gmail.com>
b770100
to
626b7c8
Compare
Trivial rebase pushed. Given the number of (tested) ACKs here it would be nice to get this merged sooner rather than later; it's been open almost a year. |
On my list to reACK soon(tm) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
left some nits, feel free to ignore
while (block) { | ||
node.rpc_interruption_point(); // allow a clean shutdown | ||
if (g_scanfilter_should_abort_scan) { | ||
LogPrintf("scanblocks RPC aborted at height %d.\n", block->nHeight); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure about unconditional logging here. This will fill the disk and there is no way for a user to disable it, unless they turn off all logging.
Is there a reason to log as opposed to return something to the rpc user?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, wouldn't be bad to return a "completed" flag inside the return object.
// compare the elements-set with each filter | ||
if (filter.GetFilter().MatchAny(needle_set)) { | ||
blocks.push_back(filter.GetBlockHash().GetHex()); | ||
LogPrint(BCLog::RPC, "scanblocks: found match in %s\n", filter.GetBlockHash().GetHex()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: If this logging is for debugging, maybe put this in the debug category?
Though, I wonder what the use is, given that this will be returned to the RPC user anyway, so there would be no need to persist this in the debug log?
if (block == stop_block) next = nullptr; | ||
} | ||
if (start_index->nHeight + amount_per_chunk == block->nHeight || next == nullptr) { | ||
LogPrint(BCLog::RPC, "Fetching blockfilters from height %d to height %d.\n", start_index->nHeight, block->nHeight); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same?
Unless there are any correctness problems I'm going to leave this PR as-is; 3 solid ACKs, so would be nice to get this merged. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
diff re-ACK 626b7c8
I can tackle all the remaining nits on the follow-up PR that I'm planning to do (#23549 (review))
Does this also need release notes? |
ae3626e test: use MiniWallet for rpc_scanblocks.py (Sebastian Falbesoner) Pull request description: This is a small follow-up for bitcoin#23549 which introduced `scanblocks`. Since that RPC doesn't need the wallet, we can switch the functional test to use MiniWallet. ACKs for top commit: MarcoFalke: review ACK ae3626e Tree-SHA512: e0b0088103e059b29719299c58fd5173b1cff58cb73025a9a33ad493cd0ac50ba25a5f790e471c00a09b4dca80f3c011174ca4e0c8f34746c39831f5823dc8ba
ff138f9 doc: add `scanblocks` to list of descriptor RPCs (Sebastian Falbesoner) Pull request description: This is a tiny documentation follow-up to #23549. ACKs for top commit: aureleoules: ACK ff138f9 shaavan: ACK ff138f9 Tree-SHA512: cc45b78c13ec4aa5bac688648f8e83f04a9ae54376e67371b280428f0253e2585cf0575fa51e3835d4c13c940559bfcdd88d7504bf97a81b2a73bb34a0db7577
626b7c8 fuzz: add scanblocks as safe for fuzzing (James O'Beirne) 94fe545 test: rpc: add scanblocks functional test (Jonas Schnelli) 6ef2566 rpc: add scanblocks - scan for relevant blocks with descriptors (Jonas Schnelli) a4258f6 rpc: move-only: consolidate blockchain scan args (James O'Beirne) Pull request description: Revives bitcoin#20664. All feedback from the previous PR has either been responded to inline or incorporated here. --- Major changes from Jonas' PR: - consolidated arguments for scantxoutset/scanblocks - substantial cleanup of the functional test Here's the range-diff (`git range-diff master jonasschnelli/2020/12/filterblocks_rpc jamesob/2021-11-scanblocks`): https://gist.github.com/jamesob/aa4a975344209f0316444b8de2ec1d18 ### Original PR description > The `scanblocks` RPC call allows one to get relevant blockhashes from a set of descriptors by scanning all blockfilters in a given range. > > **Example:** > > `scanblocks start '["addr(<bitcoin_address>)"]' 661000` (returns relevant blockhashes for `<bitcoin_address>` from blockrange 661000->tip) > > ## Why is this useful? > **Fast wallet rescans**: get the relevant blocks and only rescan those via `rescanblockchain getblockheader(<hash>)[height] getblockheader(<hash>)[height])`. A future PR may add an option to allow to provide an array of blockhashes to `rescanblockchain`. > > **prune wallet rescans**: (_needs additional changes_): together with a call to fetch blocks from the p2p network if they have been pruned, it would allow to rescan wallets back to the genesis block in pruned mode (relevant bitcoin#15946). > > **SPV mode** (_needs additional changes_): it would be possible to build the blockfilterindex from the p2p network (rather then deriving them from the blocks) and thus allow some sort of hybrid-SPV mode with moderate bandwidth consumption (related bitcoin#9483) ACKs for top commit: furszy: diff re-ACK 626b7c8 Tree-SHA512: f84e4dcb851b122b39e9700c58fbc31e899cdcf9b587df9505eaf1f45578cc4253e89ce2a45d1ff21bd213e31ddeedbbcad2c80810f46755b30acc17b07e2873
ae3626e test: use MiniWallet for rpc_scanblocks.py (Sebastian Falbesoner) Pull request description: This is a small follow-up for bitcoin#23549 which introduced `scanblocks`. Since that RPC doesn't need the wallet, we can switch the functional test to use MiniWallet. ACKs for top commit: MarcoFalke: review ACK ae3626e Tree-SHA512: e0b0088103e059b29719299c58fd5173b1cff58cb73025a9a33ad493cd0ac50ba25a5f790e471c00a09b4dca80f3c011174ca4e0c8f34746c39831f5823dc8ba
ff138f9 doc: add `scanblocks` to list of descriptor RPCs (Sebastian Falbesoner) Pull request description: This is a tiny documentation follow-up to bitcoin#23549. ACKs for top commit: aureleoules: ACK ff138f9 shaavan: ACK ff138f9 Tree-SHA512: cc45b78c13ec4aa5bac688648f8e83f04a9ae54376e67371b280428f0253e2585cf0575fa51e3835d4c13c940559bfcdd88d7504bf97a81b2a73bb34a0db7577
b922f6b rpc: scanblocks, add "completed" flag to the result obj (furszy) ce50acc rpc: scanblocks, do not traverse the whole chain block by block (furszy) Pull request description: Coming from bitcoin/bitcoin#23549 (review) The current `scanblocks` flow walks-through every block in the active chain until hits the chain tip or processes 10k blocks, then calls `lookupFilterRange` function to obtain all filters from that particular range. This is only done to obtain the heights range to look up the block filters. Which is unneeded. As `scanblocks` only lookup block filters in the active chain, we can directly calculate the lookup range heights, by using the chain tip, without requiring to traverse the chain block by block. ACKs for top commit: achow101: ACK b922f6b TheCharlatan: ACK b922f6b Tree-SHA512: 0587e6d9cf87a59184adb2dbc26a4e2bce3a16233594c6c330f69feb49bf7dc63fdacf44fc20308e93441159ebc604c63eb7de19204d3e745a2ff16004892b45
b922f6b rpc: scanblocks, add "completed" flag to the result obj (furszy) ce50acc rpc: scanblocks, do not traverse the whole chain block by block (furszy) Pull request description: Coming from bitcoin#23549 (review) The current `scanblocks` flow walks-through every block in the active chain until hits the chain tip or processes 10k blocks, then calls `lookupFilterRange` function to obtain all filters from that particular range. This is only done to obtain the heights range to look up the block filters. Which is unneeded. As `scanblocks` only lookup block filters in the active chain, we can directly calculate the lookup range heights, by using the chain tip, without requiring to traverse the chain block by block. ACKs for top commit: achow101: ACK b922f6b TheCharlatan: ACK b922f6b Tree-SHA512: 0587e6d9cf87a59184adb2dbc26a4e2bce3a16233594c6c330f69feb49bf7dc63fdacf44fc20308e93441159ebc604c63eb7de19204d3e745a2ff16004892b45
For later reuse in `scanblocks`. Github-Pull: bitcoin#23549 Rebased-From: a4258f6
Co-authored-by: James O'Beirne <james.obeirne@gmail.com> Github-Pull: bitcoin#23549 Rebased-From: 6ef2566
Co-authored-by: James O'Beirne <james.obeirne@gmail.com> Github-Pull: bitcoin#23549 Rebased-From: 94fe545
Github-Pull: bitcoin#23549 Rebased-From: 626b7c8
Revives #20664. All feedback from the previous PR has either been responded to inline or incorporated here.
Major changes from Jonas' PR:
Here's the range-diff (
git range-diff master jonasschnelli/2020/12/filterblocks_rpc jamesob/2021-11-scanblocks
): https://gist.github.com/jamesob/aa4a975344209f0316444b8de2ec1d18Original PR description