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
Improve Remasc storage before 0.5.0 activation #793
Conversation
rskj-core/src/main/java/org/ethereum/core/genesis/BlockChainLoader.java
Outdated
Show resolved
Hide resolved
66bea77
to
2ed4da9
Compare
* @return BlockResult with the final state data. | ||
*/ | ||
public BlockResult execute(Block block, byte[] stateRoot, boolean discardInvalidTxs) { | ||
return execute(block, stateRoot, discardInvalidTxs, false); | ||
public BlockResult execute(Block block, Block parent, boolean discardInvalidTxs) { |
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 is really necessary to switch from the stateRoot to the parent block here ? In the future nodes will fast sync, and therefore the first block to be executed won't have a block parent to reference. It may have a BlockHeader parent, but not a full block.
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 think passing the BlockHeader could suffice. If not, then maybe we can pass both the parent block id and the stateroot, and the code uses one or the other (the one that is != null)
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 passed the BlockHeader
. Good catch!
What does make more sense, to remove the feature of validating pre RSKIP85 states completely (this PR) or to deactivate this feature by default, but leave a command line switch or configuration option to re-activate it on request ? |
I think we could, but then we wouldn't be able to simplify our codebase as this PR does. In fact, supporting more options makes it more complex. I think that archive versions (such as |
2ed4da9
to
e294033
Compare
It seems this breaks |
99e78df
to
8f80082
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.
LGTM
88d1494
to
8b02782
Compare
SonarQube analysis reported 17 issues Top 10 issues
|
This PR is interesting in many ways. I will try to explain the basics here, but I think it deserves a blog post.
Motivation
When we launched our mainnet we overlooked a feature that made the
Remasc
contract (which manages the distribution of miner fees) store too much information on disk. It stored a list of sibling blocks that changed in every block, and the contract storage grew unbounded.We were able to claim back some resources through a process we call
pruning
, which is in many ways similar to Ethereum's garbage collection (only that it targets this specific contract).For the
0.5.0
version we proposed RSKIP85 (see #611) which fixes this issue by not storing siblings information on disk at all. This change allowed us to move forward but the pain remained for anyone trying to synchronize a node from scratch.Implementation
Basically we won't validate state roots before 0.5.0. This is in a sense similar to what fast-sync would do: you ignore some part of the history and continue from then on.
Apply RSKIP85 storage changes from the beginning
This is the crux of this change. We want that nodes never store this information from the beginning, which means we won't ever face the current storage problems. This means we can also get rid of the
pruning
feature, which has to suspend block processing and perform expensive storage copying to work.State roots won't be validated until
0.5.0
activationIn order to change the storage format, the release that includes this change (possibly
0.6.2
) will not validate state roots until the block that activates RSKIP85. This only affects mainnet, from block0
until block729000
.State roots will be validated after
0.5.0
activationThese changes were developed so that when the block 729000 is reached, the storage is in exactly the same state as if nothing had changed. From that point on, we turn on state root validation and continue synchronizing as usual. This is possible because when implementing RSKIP85 we ensured the storage was cleaned as soon as the hard fork was activated, and also because the changes in storage do not affect the distribution logic.
Future work
Checkpoints
The proposed implementation only guarantees consistency once you synced past block number 729000. It also doesn't allow to upgrade a node that hadn't synced past block 729000 (though this is unlikely to happen). Checkpoints could solve both problems at once, though not without its own set of problems.
Garbage collection
We leave the work of a full-featured garbage collector for later. Version
0.7.0
will introduce a set of storage changes we callunitrie
, which will lend itself to a much easier and efficient garbage collection process. Thepruning
feature that is deleted here should be considered when implementing it, both to draw inspiration and learn from past mistakes.