-
Notifications
You must be signed in to change notification settings - Fork 36.5k
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
Add ChainstateManager, remove BlockManager global #17737
Conversation
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. |
ce74d24
to
2328317
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.
ACK 0226408, did not read the tests 🔲
Show signature and timestamp
Signature:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
ACK 0226408999, did not read the tests 🔲
-----BEGIN PGP SIGNATURE-----
iQGzBAEBCgAdFiEE+rVPoUahrI9sLGYTzit1aX5ppUgFAlwqrYEACgkQzit1aX5p
pUixgQv9ELRmdepH+VtXfc0mvkvHjZZAGrvdNEAGLqlEK+nbDy0YtUnZtECto3aJ
K/fFg7heGCu3/pRgx25GGDnaRNrOPc+q56kWXUjSS7lweiyx1JYw4V8sVlgas3Ih
4Cxbgy3GxmPL88e1mRBpqBdyKxGi3cPxpPjew63/sllo9ZDPBMsA5g0NcpUwIC2H
TMgdLJbffnHCgCKkIH5/lXah8W7fF6Tt/wyzK4RaijwcxjVrdFheJTv0kLiBJDAG
AmHMVhKDQTBeZFn5CydqeupqV90u7rdFd/S6MliuawQGwtlobeqKqs7jxeR23+Yx
AfAAk6nKLhQFQ5x998j/rGamIcYO7RCRE0be0dZC1KGdhTwIY1LOsSKHlJAn64Ik
XKNJXDbg8o1vnBgAEmzslunwooaOoF2oSyEB4crt++JNYLl38imrOdZ+0kdlQ/BC
GCRJWD/y2WSNRxCrkyJZ6uxTkUf7KmEbh8qwOavXby2DR2rOSOGE9nM9ewXgqbsK
BDO3176X
=Ygdp
-----END PGP SIGNATURE-----
Timestamp of file with hash c4bdc7880969f1e6719cf25c6f715a20e103935d1147395578a097e3179189ff -
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.
Reviewed 6d14916 to 4813167.
Need to dig into parent PR a bit more before to review forward.
7eac28c
to
9a6fb54
Compare
9a6fb54
to
4cab02a
Compare
4cab02a
to
ec64f5c
Compare
Bringing in this IRC comment, if helpful: "recent utxo snapshots for testing are available here: #15606 (comment)" |
ACK 16d20d9 only, will continue review later on 🚀 Show signature and timestampSignature:
Timestamp of file with hash |
ec64f5c
to
1c17381
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.
ACK e7bc059 only, have not reviewed later commits closely 🕧
Show signature and timestamp
Signature:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
ACK e7bc059491d51919f676b35b6843d1c395d452a6 only, have not reviewed later commits closely 🕧
-----BEGIN PGP SIGNATURE-----
iQGzBAEBCgAdFiEE+rVPoUahrI9sLGYTzit1aX5ppUgFAlwqrYAACgkQzit1aX5p
pUjKXwwApeBAJd4ix/yrfHo9bHi30caJGej5Xk3cCvsbTorNmxVgMjJdbcALeADr
AbWHnVntgHiI7oLtzbKrFlKTGi826+stmRIy2VPyVs31L/z7k2pLKJsRFtYO+kzv
ATQ4POaLd58wzFI4bxGtSLBu7I+91f6iLzdtdINYDVJj6g89eBd74ICseFoQjM6x
lAugPzMXzrL8kh71IFBumNpQKq3rNZ9Wb/6oqVCBiZUGUnW4qC3a5aVDhwfnBnKX
YQia7Cej4Ex22+FAxh+4LUl8nO6I+UMH53TASaMG/ZoHUrXpHouWyo9vmUAwBMyp
gqN9AX/V5Hv7YCk3hehviw6p9ZI+Gvs3hrXYlU2FLUFTGXJfQz5yM6jSipnK5tZC
vqx46MazAjQ7x2de/HJIfwf+uEFpZkohauhobu5pMGss0tuVSiWVcofIoS8I5zei
mlEZ6atiGucuEMZmiC8+z3g4TbGo5kztOB00YOVVbY1+jDmuOOs+T220p4FtrDTl
B6J3CRmr
=Ik+8
-----END PGP SIGNATURE-----
Timestamp of file with hash fe215ba014f43a48217fc4a11afdd4fb671d3ccd7e48f8bed366d49affae1228 -
ACK 1c17381, but it looks like the tests fail 🍢 Show signature and timestampSignature:
Timestamp of file with hash |
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 1c17381. I did have a bunch of questions and suggestions below, but the suggestions aren't important, and if the questions don't point to real problems, I think this looks good to merge as is.
src/validation.h
Outdated
* *Background validation chainstate*: an IBD chainstate for which the | ||
* IBD process is happening in the background while use of the | ||
* active chainstate allows the rest of the system to function. |
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 "validation: introduce unused ChainstateManager" (10837ab)
The "Background validation chainstate" term seems a little awkward to me, where I guess every background validation chainstate is an IBD chainstate, but an IBD chainstate isn't a background validation chainstate until a separate snapshot chainstate has been loaded.
It seems like if you replaced the IsBackgroundValidationChainstate()
method with plainer ChainStateManger::IsIBD(chainstate)
and ChainStateManager::HasSnapshot()
methods you could drop the "background validation chainstate" term and method and make things easier to follow.
Or if having the term is more useful, maybe call it a "background IBD chainstate" instead of "background validation chainstate" to be more obvious it's always refers to the IBD chain.
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.
What gets kind of confusing here is that chainstates created from snapshots still technically go through IBD, since by the time the snapshot is actually used to create a chainstate, it's far enough behind the tip that it technically undergoes IBD (albeit an abbreviated one). So I think referring to what I now call the background validation chainstate as the IBD chainstate might be confusing in that sense.
But I agree with you that the naming here isn't ideal. Definitely open to changing this if you have other good ideas.
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: #17737 (comment)
I guess I see that but it would seem more like a reason to avoid the term "IBD chainstate" entirely.
Since chain state manager only has a snapshot chainstate and a non snapshot chainstate, I like the idea of just referring to the two chainstates with the same names consistently, and not muddying the water with other chainstate names and definitions. "IBD chainstate" is what you call the non-snapshot chainstate everywhere except in this one method and comment, which is my why first suggestion is delete "background validation chainstate" comment and have separate methods replacing IsBackgroundValidationChainstate. Switching to "Background IBD chainstate" was just a runner up suggestion.
I guess also I don't find the "IBD chainstate" name to be too confusing because I take IBD chainstate to mean chainstate generated entirely from IBD, not a state with some UTXOs that happened to come from IBD. But for another naming suggestion, maybe an alternative would be to use "snapshot chainstate" and "blocksonly chainstate" instead of "snapshot chainstate" and "IBD chainstate"
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.
Partially (?) fixed by changing IsBackgroundValidationChainstate()
to IsBackgroundIBD()
. I think blocksonly is somewhat confusing because there'd be a confusing overlap with the P2P definition of blocksonly, which I think is different or unrelated.
BOOST_CHECK(c2.ActivateBestChain(_, chainparams, nullptr)); | ||
|
||
BOOST_CHECK(manager.IsSnapshotActive()); | ||
BOOST_CHECK(!manager.IsSnapshotValidated()); |
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 "test: add basic tests for ChainstateManager" (997bf7f)
No test for the case where IsSnapshotValidated returns true, I guess. Understandable if it would make the test setup too complicated
Thanks for the good reviews! I'll be following up shortly with corresponding changes. |
1c17381
to
94ca1e0
Compare
I've incorporated most if not all of the feedback from @MarcoFalke and @ryanofsky which has nicely reduced the size of the diff. Changes include:
|
This allows us to easily initialize multiple chainstates on startup in future commits. It retires the g_chainstate global in lieu of g_chainman.
Feedback incorporated from Russell Yanofsky. Co-authored-by: MarcoFalke <falke.marco@gmail.com>
I'd previously attempted to create a specialized lock for ChainstateManager, but it turns out that because that lock would be required for functions like ChainActive() and ChainstateActive(), it created irreconcilable lock inversions since those functions are used so broadly throughout the codebase. Instead, I'm just using cs_main to protect the contents of g_chainman. Co-authored-by: Russell Yanofsky <russ@yanofsky.org>
abfc152
to
c9017ce
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.
Code Review ACK abfc152
Had a few nits that can well be ignored or addressed in next PR in the assume-utxo series.
General note: I was not sure about some of the ChainstateManager
API, some of the methods seemed like they could be private (IsSnapshotValidated()
seems to be only used internally) and others are not used at all (IsSnapshotValidated
and SnapshotBlockhash
for example) so they could have been included in the next PRs when they are needed. But I can wait and see how they are used in the next PR. :)
@@ -1254,6 +1256,10 @@ void CChainState::InitCoinsDB( | |||
bool should_wipe, | |||
std::string leveldb_name) | |||
{ | |||
if (!m_from_snapshot_blockhash.IsNull()) { | |||
leveldb_name += "_" + m_from_snapshot_blockhash.ToString(); |
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: Do you anticipate more than one snapshot to be present? From the rest of the code it seems to me that this will not be the case. Then I think naming the db just "snapshot" or so is more intuitive.
|
||
to_modify.reset(new CChainState(snapshot_blockhash)); | ||
|
||
// Snapshot chainstates and initial IBD chaintates always become active. |
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.
typo: chaintates
@@ -698,11 +698,17 @@ static void ThreadImport(std::vector<fs::path> vImportFiles) | |||
} | |||
|
|||
// scan for better chains in the block chain database, that are not yet connected in the active best chain |
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: That comment is still relevant to the code below but because of the empty line it seems detached.
Code Review Re-ACK abfc152 |
re-ACK c9017ce 📙 Only changes since my last review:
Show signature and timestampSignature:
Timestamp of file with hash |
@fjahr It looks like your commit hash is the same in the re-ACK |
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 c9017ce
Side-node: there is a g_chainman
access in LoadBlockIndex
(src/validation.cpp L4577), not an issue right now because caller already holds cs_main
but if function is moved in the future a AssertLockHeld
would be better.
assert(g_chainman.m_active_chainstate); | ||
return *g_chainman.m_active_chainstate; | ||
} | ||
|
||
CChain& ChainActive() | ||
{ | ||
LOCK(::cs_main); |
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.
Is this LOCK really necessary given we call ::ChainstateActive()
just after ? Doesn't hurt because we use recursive_mutex but still..
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: #17737 (comment)
Is this LOCK really necessary given we call
::ChainstateActive()
just after ? Doesn't hurt because we use recursive_mutex but still..
Agree it's definitely not necessary (but harmless)
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 c9017ce. No changes since last review other than a straight rebase
@@ -894,7 +921,7 @@ class ChainstateManager | |||
void Reset(); | |||
}; | |||
|
|||
extern ChainstateManager g_chainman; | |||
extern ChainstateManager g_chainman GUARDED_BY(::cs_main); |
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: #17737 (comment)
If understand well the new lock model,
g_chainman
content is undercs_main
but notCChainState
. If yes, why someGetAll
access in init.cpp don't use lock for access ?
I don't think this is true. Maybe it was resolved? You can add EXCLUSIVE_LOCKS_REQUIRED(cs_main) to the GetAll declaration, and it will only fail in test code using a local chain state manager not tied to the cs_main global
assert(g_chainman.m_active_chainstate); | ||
return *g_chainman.m_active_chainstate; | ||
} | ||
|
||
CChain& ChainActive() | ||
{ | ||
LOCK(::cs_main); |
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: #17737 (comment)
Is this LOCK really necessary given we call
::ChainstateActive()
just after ? Doesn't hurt because we use recursive_mutex but still..
Agree it's definitely not necessary (but harmless)
This tip has accumulated a good number of code ACKs, so I'm hesitant to address nits here. If anyone thinks that's the right move though I'm happy to. Edit: and thanks for the reviews, everyone! |
I think we can merge this after the 0.20 branch off. |
c9017ce protect g_chainman with cs_main (James O'Beirne) 2b081c4 test: add basic tests for ChainstateManager (James O'Beirne) 4ae29f5 use ChainstateManager to initialize chainstate (James O'Beirne) 5b690f0 refactor: move RewindBlockIndex to CChainState (James O'Beirne) 89cdf4d validation: introduce unused ChainstateManager (James O'Beirne) 8e2ecfe validation: add CChainState.m_from_snapshot_blockhash (James O'Beirne) Pull request description: This is part of the [assumeutxo project](https://github.com/bitcoin/bitcoin/projects/11): Parent PR: bitcoin#15606 Issue: bitcoin#15605 Specification: https://github.com/jamesob/assumeutxo-docs/tree/master/proposal --- This changeset introduces `ChainstateManager`, which is responsible for creating and managing access to multiple chainstates. Until we allow chainstate creation from UTXO snapshots (next assumeutxo PR?) it's basically unnecessary, but it is a prerequisite for background IBD support. Changes are also made to the initialization process to make use of `g_chainman` and thus clear the way for multiple chainstates being loaded on startup. One immediate benefit of this change is that we no longer have the `g_blockman` global, but instead have the ChainstateManager inject a reference of its shared BlockManager into any chainstate it creates. Another immediate benefit is that uses of `ChainActive()` and `ChainstateActive()` are now covered by lock annotations. Because use of `g_chainman` is annotated to require cs_main, these two functions subsequently follow. Because of whitespace changes, this diff looks bigger than it is. E.g., 4813167 is most easily reviewed with ```sh git show --color-moved=dimmed_zebra -w 4813167 ``` ACKs for top commit: MarcoFalke: re-ACK c9017ce 📙 fjahr: Code Review Re-ACK c9017ce ariard: Code Review ACK c9017ce ryanofsky: Code review ACK c9017ce. No changes since last review other than a straight rebase Tree-SHA512: 3f250d0dc95d4bfd70852ef1e39e081a4a9b71a4453f276e6d474c2ae06ad6ae6a32b4173084fe499e1e9af72dd9007f4a8a375c63ce9ac472ffeaada41ab508
fab6b9d validation: Mark g_chainman DEPRECATED (MarcoFalke) fa1d97b validation: Make ProcessNewBlock*() members of ChainstateManager (MarcoFalke) fa24d49 validation: Make PruneOneBlockFile() a member of ChainstateManager (MarcoFalke) fa84b1c validation: Make LoadBlockIndex() a member of ChainstateManager (MarcoFalke) fa05fdf net: Pass chainman into PeerLogicValidation (MarcoFalke) fa7b626 node: Add chainman alias for g_chainman (MarcoFalke) Pull request description: The global `g_chainman` has recently been introduced in #17737. The chainstate manager is primarily needed for the assumeutxo feature, but it can also simplify testing in the future. The goal of this pull is to make the global chainstate manager internal to validation, so that all external code does not depend on globals and that unit or fuzz tests can pass in their (potentially mocked) chainstate manager. I suggest reviewing the pull request commit-by-commit. It should be relatively straightforward refactoring that does not change behavior at all. ACKs for top commit: ryanofsky: Code review ACK fab6b9d. Had to be rebased but still looks good Tree-SHA512: dcbf114aeef4f8320d466369769f22ce4dd8f46a846870354df176c3de9ff17c64630fbd777e7121d7470d7a8564ed8d37b77168746e8df7489c6877e55d7b4f
Summary: ``` This parameter is unused, but in future commits will allow ChainstateManager to differentiate between chainstates created from a UTXO snapshot from those that weren't. ``` Partial backport (1/5) of core [[bitcoin/bitcoin#17737 | PR17737]]: bitcoin/bitcoin@8e2ecfe Test Plan: ninja all check-all Reviewers: #bitcoin_abc, PiRK Reviewed By: #bitcoin_abc, PiRK Differential Revision: https://reviews.bitcoinabc.org/D8537
Summary: ``` ChainstateManager is responsible for creating and managing multiple chainstates, and will provide a high-level interface for accessing the appropriate chainstate based upon a certain use. ``` Partial backport (2/5) of core [[bitcoin/bitcoin#17737 | PR17737]]: bitcoin/bitcoin@89cdf4d Depends on D8537. Test Plan: ninja all check-all Reviewers: #bitcoin_abc, PiRK Reviewed By: #bitcoin_abc, PiRK Differential Revision: https://reviews.bitcoinabc.org/D8538
Summary: ``` This allows us to easily initialize multiple chainstates on startup in future commits. It retires the g_chainstate global in lieu of g_chainman. ``` Partial backport (3/5) of core [[bitcoin/bitcoin#17737 | PR17737]]: bitcoin/bitcoin@4ae29f5 Includes a fix to `qt/test/apptests.cpp` from the next commit to unbreak the bitcoin-qt tests: bitcoin/bitcoin@2b081c4#diff-41e328d9ba5879d2bd026a700743339b5b300b9bee50844795ef9e27f60bdfb8R85 Depends on D8538. Test Plan: ninja all check-all Reviewers: #bitcoin_abc, deadalnix Reviewed By: #bitcoin_abc, deadalnix Subscribers: deadalnix Differential Revision: https://reviews.bitcoinabc.org/D8539
Summary: Partial backport (4/5) of core [[bitcoin/bitcoin#17737 | PR17737]]: bitcoin/bitcoin@2b081c4 Depends on D8539. Test Plan: ninja check Reviewers: #bitcoin_abc, deadalnix Reviewed By: #bitcoin_abc, deadalnix Differential Revision: https://reviews.bitcoinabc.org/D8540
Summary: ``` I'd previously attempted to create a specialized lock for ChainstateManager, but it turns out that because that lock would be required for functions like ChainActive() and ChainstateActive(), it created irreconcilable lock inversions since those functions are used so broadly throughout the codebase. Instead, I'm just using cs_main to protect the contents of g_chainman. ``` Completes backport (5/5) of core [[bitcoin/bitcoin#17737 | PR17737]]: bitcoin/bitcoin@c9017ce The lock change in `wallet_tests.cpp` is not needed due to out of order backports. Depends on D8540. Test Plan: ninja all check-all Reviewers: #bitcoin_abc, deadalnix Reviewed By: #bitcoin_abc, deadalnix Differential Revision: https://reviews.bitcoinabc.org/D8541
Bitcoin Core PR: bitcoin/bitcoin#17737 Pull request description: This is part of the [assumeutxo project](https://github.com/bitcoin/bitcoin/projects/11): Parent PR: bitcoin/bitcoin#15606 Issue: bitcoin/bitcoin#15605 Specification: https://github.com/jamesob/assumeutxo-docs/tree/master/proposal --- This changeset introduces `ChainstateManager`, which is responsible for creating and managing access to multiple chainstates. Until we allow chainstate creation from UTXO snapshots (next assumeutxo PR?) it's basically unnecessary, but it is a prerequisite for background IBD support. Changes are also made to the initialization process to make use of `g_chainman` and thus clear the way for multiple chainstates being loaded on startup. One immediate benefit of this change is that we no longer have the `g_blockman` global, but instead have the ChainstateManager inject a reference of its shared BlockManager into any chainstate it creates. Another immediate benefit is that uses of `ChainActive()` and `ChainstateActive()` are now covered by lock annotations. Because use of `g_chainman` is annotated to require cs_main, these two functions subsequently follow. Because of whitespace changes, this diff looks bigger than it is. E.g., bitcoin/bitcoin@4813167 is most easily reviewed with ```sh git show --color-moved=dimmed_zebra -w bitcoin/bitcoin@4813167 ```
This is part of the assumeutxo project:
Parent PR: #15606
Issue: #15605
Specification: https://github.com/jamesob/assumeutxo-docs/tree/master/proposal
This changeset introduces
ChainstateManager
, which is responsible for creating and managing access to multiple chainstates. Until we allow chainstate creation from UTXO snapshots (next assumeutxo PR?) it's basically unnecessary, but it is a prerequisite for background IBD support.Changes are also made to the initialization process to make use of
g_chainman
and thus clear the way for multiple chainstates being loaded on startup.One immediate benefit of this change is that we no longer have the
g_blockman
global, but instead have the ChainstateManager inject a reference of its shared BlockManager into any chainstate it creates.Another immediate benefit is that uses of
ChainActive()
andChainstateActive()
are now covered by lock annotations. Because use ofg_chainman
is annotated to require cs_main, these two functions subsequently follow.Because of whitespace changes, this diff looks bigger than it is. E.g., 4813167 is most easily reviewed with