-
Notifications
You must be signed in to change notification settings - Fork 37.7k
rpc: add relevant_blocks
to scanblocks status
#30713
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
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code Coverage & BenchmarksFor details see: https://corecheck.dev/bitcoin/bitcoin/pulls/30713. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. ConflictsNo conflicts as of last run. |
revelant_blocks
to scanblocks status
5891441
to
6bac76f
Compare
🚧 At least one of the CI tasks failed. HintsMake sure to run all tests locally, according to the documentation. The failure may happen due to a number of reasons, for example:
Leave a comment here, if you need help tracking down a confusing failure. |
Concept ACK. This'd be useful, especially in conjunction with #30708. |
src/rpc/blockchain.cpp
Outdated
@@ -2550,7 +2563,8 @@ static RPCHelpMan scanblocks() | |||
|
|||
ret.pushKV("from_height", start_block_height); | |||
ret.pushKV("to_height", start_index->nHeight); // start_index is always the last scanned block here | |||
ret.pushKV("relevant_blocks", std::move(blocks)); | |||
LOCK(cs_relevant_blocks); | |||
ret.pushKV("relevant_blocks", g_relevant_blocks); |
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.
Since status stops working when the scan completes, it seems like we should clear g_relevant_blocks
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.
Yes, thank you. Will update.
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.
That'd introduce a race, where the relevant blocks are cleared before the reserver is destructed (and thus the status call may return an empty list where previously it didn't for the same call)
Not sure if it matters, or worthy to address.
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.
While leaving scanblocks()
without resetting g_relevant_blocks
isn't ideal, resetting g_relevant_blocks
just before BlockFiltersScanReserver
in the start
branch seemed to be a good way to prevent status
from accidentally seeing an empty g_relevant_blocks
(at least in common cases). Please let me know if I'm overlooking a likely concurrency case, and it can be adjusted.
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.
Seems trivial to fix properly? luke-jr@5698131
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.
included, 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.
Concept ACK (coming from #30708).
6bac76f
to
bdda0c1
Compare
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.
tACK 39ee30c
Release notes has been added and g_relevant_blocks
reset has been placed into the start
conditional section since my last review.
Tested on mainnet.
/build/src/bitcoin-cli scanblocks start '["addr(bc1p0cp0vyag6snlta2l7c4am3rue7eef9f72l7uhx52m4v27vfydx9s8tfs7t)"]' 850263
{
"from_height": 850263,
"to_height": 860861,
"relevant_blocks": [
"00000000000000000002b3c2a395905df9d12ce30d2237f064cdafacb81eb33d",
"00000000000000000002bc5cc78f5b0913a5230a8f4b0d5060bc9a60900a5a88",
"00000000000000000001c5291ed6a40c06d3db5c8fb738567654b24a14b24ecb"
],
"completed": true
}
./build/src/bitcoin-cli scanblocks status
{
"progress": 0,
"current_height": 850263,
"relevant_blocks": [
"00000000000000000002b3c2a395905df9d12ce30d2237f064cdafacb81eb33d"
]
}
For those not used to scanblocks
I'd add a little note somewhere in the description that in order to testing this change the block filter index feature should be enabled, by either passing -blockfilterindex
as an argument on the node start up or putting it in the bitcoin.conf
file (same for #30708), even it's specified in the help or an error would lead to that, it'd make it easier and straightforward. Also that if the feature was not enabled before it could take up to a few hours to create the indexes.
Out of the scope of this PR, having played around start
, status
, abort
subcommands, I'd add some more context in the results of the first 2. Perhaps as "good first issue".
-
for
status
subcommand, instead of returning no results when there are no scans in progress:./build/src/bitcoin-cli -datadir=${AU_DATADIR} scanblocks status { "status": "No scan in progress" }
-
for
start
subcommand, when theabort
has been triggered and was no completion:/build/src/bitcoin-cli -datadir=${AU_DATADIR} scanblocks start '["addr(bc1p0cp0vyag6snlta2l7c4am3rue7eef9f72l7uhx52m4v27vfydx9s8tfs7t)"]' 750000 { "from_height": 750000, "to_height": 780002, "relevant_blocks": [ ], "completed": false, "status": "Abort call performed" }
Thanks for reviewing.
These are good ideas for follow-up PRs.
Good idea. Description updated. |
Thanks! It looks good. Forgot to mention that it would be nice to add some test checking |
It would be. I took a look at bitcoin/test/functional/rpc_scanblocks.py Lines 128 to 129 in 0725a37
Any ideas on how to slow down |
Exactly.
I've been playing a bit around the |
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.
Tested changes on mainnet
Started scanning
./build/src/bitcoin-cli scanblocks start '["addr(bc1qgqrn8gratlc59gn5v02nrz0rg8anjjaxt3efh8)"]'
status check
./build/src/bitcoin-cli scanblocks status
{
"progress": 98,
"current_height": 570056,
"relevant_blocks": [
"0000000000005ecf9f819ea03abd8f2a3f0b2cad5e5124bdabd0d7a770fd9067",
"000000000000000479f286761e91b2c983ad63e19b0d53cffc67e731a7558d85"
]
}
scan completed
./build/src/bitcoin-cli scanblocks start '["addr(bc1qgqrn8gratlc59gn5v02nrz0rg8anjjaxt3efh8)"]'
{
"from_height": 0,
"to_height": 577394,
"relevant_blocks": [
"0000000000005ecf9f819ea03abd8f2a3f0b2cad5e5124bdabd0d7a770fd9067",
"000000000000000479f286761e91b2c983ad63e19b0d53cffc67e731a7558d85"
],
"completed": true
}
`
Not sure if it worth it but could craft an unit test that calls to the RPC command. Subclassing and setting the block manager class so the file opening method "stops" at a certain point. It would mimic the delay. |
Provides relevant block hashes to status output. Enables a user to start looking through matching blocks without having to wait on scan completion. Github-Pull: bitcoin#30713 Rebased-From: bdda0c1
Github-Pull: bitcoin#30713 Rebased-From: 39ee30c
Any reason not to scope the new variables? luke-jr@851d354 |
Thanks. Planning to touch this up soon. |
Provides relevant block hashes to status output. Enables a user to start looking through matching blocks without having to wait on scan completion. Co-Authored-By: Luke Dashjr <luke-jr+git@utopios.org>
39ee30c
to
5b2d021
Compare
moved, thanks |
Updated with suggested changes |
Want to reemphasize that I think this is a good change worth doing. I have some questions about using |
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.
Code review ACK 5b2d021. Seems like a nice feature, and the implementation is pretty simple. I think there is a minor regression if scanblocks start is called from multiple threads, and suggested a fix below (#30713 (comment)).
re: #30713 (comment)
Any ideas on how to slow down
scanblocks()
enough to allow astatus
call to consistently return status of a scan in progress?
Will suggest a very general solution that would probably be overkill here, but I think we could have a setmockcondition
RPC that acts like the existing setmocktime
RPC and lets tests toggle global state that could be useful for testing. In this case I imagine a test could call something like setmockcondition({"scanblocks_pause_at_height": 50})
to make the scanning pause at a certain height and setmockcondition({"scanblocks_pause_at_height": null})
to make it resume, and we could have some helpful functions that make this not too intrusive to implement.
static GlobalMutex cs_relevant_blocks; | ||
static UniValue relevant_blocks GUARDED_BY(cs_relevant_blocks); |
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.
In commit "rpc: add relevant_blocks to scanblocks status" (4c9dc4b)
It would be good to declare these next to g_scanfilter_
variables so all global state is declared in one place, and so other functions besides scanblocks
can see this information (other RPCs and maybe tests should be able to access it). Would suggest renaming relevant_blocks
to g_scanfilter_relevant_blocks
and cs_relevant_blocks
to g_scanfilter_relevant_blocks_mutex
. (The "critical section" naming is also a little archaic.)
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.
Thanks. Will include in next update.
ret.pushKV("completed", completed); | ||
reserver.release(); // ensure this is before cs_relevant_blocks is released, so status doesn't try to use moved relevant_blocks |
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.
In commit "rpc: add relevant_blocks to scanblocks status" (4c9dc4b)
Think this is missing a word, suggest "ensure this is called before"
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.
Will include
@@ -2461,6 +2477,11 @@ static RPCHelpMan scanblocks() | |||
g_scanfilter_should_abort_scan = true; | |||
return true; | |||
} else if (request.params[0].get_str() == "start") { | |||
{ | |||
LOCK(cs_relevant_blocks); | |||
relevant_blocks = UniValue(UniValue::VARR); |
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.
In commit "rpc: add relevant_blocks to scanblocks status" (4c9dc4b)
Clearing relevant_blocks
before checking g_scanfilter_in_progress
seems not very nice, because it means if scanblocks start is called while another scan is in progress, instead of just returning an "already in progress" error, it will do that but also partially erase the state of the in-progress scan.
This behavior is not just a limitation of the new feature, but also a regression, because it messes up the "relevant_blocks" return value of the other RPC call when previously it would be accurate.
I think it should be straightforward to fix this by moving this new code below the reserve() call below.
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.
Good catch. Verified locally that truncation occurs. Fixed for next update.
UniValue ret(UniValue::VOBJ); | ||
if (request.params[0].get_str() == "status") { | ||
BlockFiltersScanReserver reserver; | ||
LOCK(cs_relevant_blocks); |
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.
In commit "rpc: add relevant_blocks to scanblocks status" (4c9dc4b)
Lock order here seems a little subtle. Would be good to have a comment saying it is important to lock this before calling reserve so if a scan is currently happening but is about to finish, an accurate "relevant_blocks" value can be returned before the scanning thread clears it.
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.
Agreed. Comment will be added.
revelant_blocks
to scanblocks status
relevant_blocks
to scanblocks status
Great idea. Playing around with it locally. Perhaps it could eventually absorb |
Will revisit later |
Provides relevant block hashes to status output. Enables a user to start looking through matching blocks without having to wait on scan completion. Co-Authored-By: Luke Dashjr <luke-jr+git@utopios.org> Github-Pull: bitcoin#30713 Rebased-From: 4c9dc4b
Github-Pull: bitcoin#30713 Rebased-From: 5b2d021
c6eca6f doc: add guidance for RPC to developer notes (tdb3) Pull request description: Adds guidance statements to the RPC interface section of the developer notes with examples of when to implement `-deprecatedrpc=`. Wanted to increase awareness of preferred RPC implementation approaches for newer contributors. This implements some of what's discussed in #29912 (comment) Opinions may differ, so please don't be shy. We want to make RPC as solid/safe as possible. Examples of discussions where guidelines/context might have added value: #30212 (comment) #29845 (comment) #30381 (review) #29954 (comment) #30410 (review) #30713 #30381 #29060 (review) ACKs for top commit: l0rinc: ACK c6eca6f fjahr: ACK c6eca6f maflcko: lgtm ACK c6eca6f jonatack: ACK c6eca6f Tree-SHA512: 01a98a8dc0eb91762b225d3278cdb4a5e380ceb7486fd096b4ad9122bed859cea8584d8996d3dce51272fdb792f4a793a1bd1c5445efeb87f0a30f9b6e59a790
Currently, after starting a scan with
scanblocks
the user must wait until the scan is complete to see the associated/relevant block hashes.This updates the
scanblocks status
result object to provide therelevant_blocks
found so far.This enables earlier subsequent lookup within matching blocks (e.g. to run
getdescriptoractivity
in PR #30708)Below is an example tested on signet by starting and obtaining status of a scan for an address that has received many coinbase outputs (so there are matches over many blocks, showing the increase in
relevant_blocks
results inscanblocks status
over the life of the scan). Also tested on mainnet (see #30713 (review)).or (to show snapshots over time)
-deprecatedrpc
seems like overkill for the addition of a key (not a data type change). Release notes have been added (affecting user interface).If testing, be sure to enable the block filter index feature (e.g. adding
blockfilterindex=1
to bitcoin.conf), and allow time for the index to build: