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
assumeutxo: change getchainstates RPC to return a list of chainstates #28590
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code CoverageFor detailed information about the code coverage, see the test coverage report. 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. |
Concept ACK, would be good to have this in 26.0 so we don't change the RPC interface afterwards |
Concept ACK, seems like a fine simplification! |
Rebased 3306714 -> ff89dec ( |
Concept ACK tACK ff89dec Tested with a signet IBD, loading the snapshot and waiting for background sync to finish. |
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.
ACK ff89dec (jamesob/ackr/28590.1.ryanofsky.assumeutxo_change_getcha
)
Good simplification, thanks. Built, ran tests locally.
Ah, just had a functional test fail while running in a loop. Investigating...
|
Tangent, but @DrahtBot does not seem to pick up Sjors ACK with "Concept ACK" on the first line and "tACK" on the second line. I guess the ACK detector is overloaded |
self.sync_blocks(nodes=(n0, n1)) | ||
|
||
self.log.info("Ensuring background validation completes") | ||
# N.B.: the `snapshot` key disappears once the background validation is complete. | ||
wait_until_helper(lambda: not n1.getchainstates().get('snapshot')) | ||
wait_until_helper(lambda: len(n1.getchainstates()['chainstates']) != 1) |
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'm not sure I follow this substitution... once background validation completes, chainman.GetAll()
should (at least eventually) return only one chainstate: the fully-validated snapshot chainstate. Maybe s/!=/==
?
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.
Funny, I think as-written this succeeds most of the time because the check is racily performed before validation actually completes, which essentially makes the check exit early.
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.
re: #28590 (comment)
Funny, I think as-written this succeeds most of the time because the check is racily performed before validation actually completes, which essentially makes the check exit early.
Right, this is the opposite of the condition you'd expect. Probably I just wrote the check one way, then inverted when it failed assuming I'd made a mistake. But either of these checks are racy, so it makes more sense to be direct and check the new "validated" field. Updated in new push.
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.
re: #28590 (comment)
Actually thinking about it more, the change you suggested is not racy, and is a little better than just checking the "validated" field because it also ensures that the background chainstate disappears from the list after it is disabled. Also check you suggested is more consistent with the check done for the n2 node below on line 218
I'm ACK again once this change is made: #28590 (comment) |
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.
Updated ff89dec -> 35f6d90 (pr/getchain.2
-> pr/getchain.3
, compare) fixing race condition in test
self.sync_blocks(nodes=(n0, n1)) | ||
|
||
self.log.info("Ensuring background validation completes") | ||
# N.B.: the `snapshot` key disappears once the background validation is complete. | ||
wait_until_helper(lambda: not n1.getchainstates().get('snapshot')) | ||
wait_until_helper(lambda: len(n1.getchainstates()['chainstates']) != 1) |
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.
re: #28590 (comment)
Funny, I think as-written this succeeds most of the time because the check is racily performed before validation actually completes, which essentially makes the check exit early.
Right, this is the opposite of the condition you'd expect. Probably I just wrote the check one way, then inverted when it failed assuming I'd made a mistake. But either of these checks are racy, so it makes more sense to be direct and check the new "validated" field. Updated in new push.
Current getchainstates RPC returns "normal" and "snapshot" fields which are not ideal because it requires new "normal" and "snapshot" terms to be defined, and the definitions are not really consistent with internal code. (In the RPC interface, the "snapshot" chainstate becomes the "normal" chainstate after it is validated, while in internal code there is no "normal chainstate" and the "snapshot chainstate" is still called that temporarily after it is validated). The current getchainstatees RPC is also awkward to use if you to want information about the most-work chainstate because you have to look at the "snapshot" field if it exists, and otherwise fall back to the "normal" field. Fix these issues by having getchainstates just return a flat list of chainstates ordered by work, and adding new chainstate "validated" field alongside the existing "snapshot_blockhash" so it is explicit if a chainstate was originally loaded from a snapshot, and whether the snapshot has been validated.
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.
Updated 35f6d90 -> a9ef702 (pr/getchain.3
-> pr/getchain.4
, compare) taking James suggestion and making test a little stricter and more internally consistent
self.sync_blocks(nodes=(n0, n1)) | ||
|
||
self.log.info("Ensuring background validation completes") | ||
# N.B.: the `snapshot` key disappears once the background validation is complete. | ||
wait_until_helper(lambda: not n1.getchainstates().get('snapshot')) | ||
wait_until_helper(lambda: len(n1.getchainstates()['chainstates']) != 1) |
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.
re: #28590 (comment)
Actually thinking about it more, the change you suggested is not racy, and is a little better than just checking the "validated" field because it also ensures that the background chainstate disappears from the list after it is disabled. Also check you suggested is more consistent with the check done for the n2 node below on line 218
re-ACK a9ef702 Only a test change since I last reviewed, which I didn't study closely. |
re-ACK a9ef702 |
ACK a9ef702 |
…a list of chainstates a9ef702 assumeutxo: change getchainstates RPC to return a list of chainstates (Ryan Ofsky) Pull request description: Current `getchainstates` RPC returns "normal" and "snapshot" fields which are not ideal because it requires new "normal" and "snapshot" terms to be defined, and the definitions are not really consistent with internal code. (In the RPC interface, the "snapshot" chainstate becomes the "normal" chainstate after it is validated, while in internal code there is no "normal chainstate" and the "snapshot chainstate" is still called that temporarily after it is validated). The current `getchainstates` RPC is also awkward to use if you to want information about the most-work chainstate, because you have to look at the "snapshot" field if it exists, and otherwise fall back to the "normal" field. Fix these issues by having `getchainstates` just return a flat list of chainstates ordered by work, and adding a new chainstate "validated" field alongside the existing "snapshot_blockhash" field so it is explicit if a chainstate was originally loaded from a snapshot, and whether the snapshot has been validated. This change was motivated by comment thread in bitcoin#28562 (comment) ACKs for top commit: Sjors: re-ACK a9ef702 jamesob: re-ACK a9ef702 achow101: ACK a9ef702 Tree-SHA512: b364e2e96675fb7beaaee60c4dff4b69e6bc2d8a30dea1ba094265633d1cddf9dbf1c5ce20c07d6e23222cf1e92a195acf6227e4901f3962e81a1e53a43490aa
Current
getchainstates
RPC returns "normal" and "snapshot" fields which are not ideal because it requires new "normal" and "snapshot" terms to be defined, and the definitions are not really consistent with internal code. (In the RPC interface, the "snapshot" chainstate becomes the "normal" chainstate after it is validated, while in internal code there is no "normal chainstate" and the "snapshot chainstate" is still called that temporarily after it is validated).The current
getchainstates
RPC is also awkward to use if you to want information about the most-work chainstate, because you have to look at the "snapshot" field if it exists, and otherwise fall back to the "normal" field.Fix these issues by having
getchainstates
just return a flat list of chainstates ordered by work, and adding a new chainstate "validated" field alongside the existing "snapshot_blockhash" field so it is explicit if a chainstate was originally loaded from a snapshot, and whether the snapshot has been validated.This change was motivated by comment thread in #28562 (comment)