-
Notifications
You must be signed in to change notification settings - Fork 717
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
[Validation] Introduce rolling cache for block hashes in masternode manager #1904
[Validation] Introduce rolling cache for block hashes in masternode manager #1904
Conversation
af6f11b
to
bb53c17
Compare
Rebased on master and added functional test. |
Rebase needed. Small conflicts with master |
bb53c17
to
3e3059a
Compare
Done. |
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 3e3059a.
Really really nice 🍺 .
} else { | ||
// Use chainActive | ||
LOCK(cs_main); | ||
return chainActive[nHeight]->GetBlockHash(); |
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.
Note for the future: this cs_main
could be a potential deadlock in GetNextMasternodeInQueueForPayment
, where we are locking the internal CMasternodeMan::cs
first.
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. It should be addressed in the future (even before deterministic masternodes, GetNextMasternodeInQueueForPayment
can be refactored, rearranging its locks properly and removing the redundancies).
But, at least with this patch, it's only on blocks deeper than 200.
Currently on master we lock it for every block (even twice inside CalculateScore
).
which can be used for testing the contents of the cycling vector
If the height is within the cache size. Otherwise get the hash from chainActive. No need to use the convoluted GetBlockHash in masternode.cpp
Not used anymore
removes cs_main lock to access chainActive in CMasternodePing::CheckAndUpdate
to check the validity of the contents of the mnmanager block-hashes rolling cache
3e3059a
to
dd67066
Compare
Nit addressed and PR rebased on master. |
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.
ACK dd67066
872da91 Speedup listmasternodes removing a redundant for loop over every MN on the mnnodeman. (furszy) ea434a1 CMasternodeMan::GetMasternodeRanks removed unneeded MN extra validations and totally unnecessary extra vector load. (furszy) Pull request description: Built on top of #1904 . PR starting on 9123d22. `listmasternodes` RPC command was taking a considerable amount of time, checked the flow and discovered a lot of redundancies in the process. This PR aims to correct them. 1) `CMasternodeMan::GetMasternodeRanks` is only used for an RPC call and it was checking and validating each Masternode instead of just retrieve them as it suppose to be doing (the tier two thread is the only one responsible of check and update the masternodes list). 2) `CMasternodeMan::GetMasternodeRanks` had a totally unneeded second vector load. Looping over the entire masternodes list one more time after getting it. 3) `listmasternodes` after calling `GetMasternodeRanks` was looking for each of the retrieved masternodes one more time using the retrieved masternode vin (yes..). ACKs for top commit: random-zebra: ACK 872da91 Fuzzbawls: ACK 872da91 Tree-SHA512: 52db4488ec429594a8fa6cacceaaf494ec0da179929b7de30f8698cbbb2d940c0d859f8a0082dce33ead5227066079011f30480434ab935906e12aa80b4199a3
Problem:
Validation of many objects on the second layer (masternode pings, winners/scores, etc...) requires access to chainActive to get the hashes of blocks at a certain height. This is done very often (especially for masternode pings) and means holding
cs_main
lock every time, making the process slow and possibly leading to locking order inconsistencies.Solution:
Cache the last N block hashes in the masternode manager.
In order to implement this efficiently, we introduce a new data structure called
CyclingVector
, which is a fixed-size vector, exposing only a setterSet(i, value)
which modifies the indexi % N
.The cache is initialized at startup and updated when blocks get connected to / disconnected from the tip.
The size (
CACHED_BLOCK_HASHES
) is currently set a default value of 200 making it possible to validate all masternode pings (but not all masternode winners) without accessing chainActive. In the future we could add a startup flag to let the user customize this (higher cache size would, as usual, mean faster execution but higher memory usage).An RPC
getcachedblockhashes
is introduced, in order to print the content of the cache. This can be used later in the functional test suite for better testing.This PR also removes the accesses to chainActive to get the current chain-height (using a value cached in the manager).