-
Notifications
You must be signed in to change notification settings - Fork 55
refactor(levm,l1,l2): split block execution and update generation #2519
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
Lines of code reportTotal lines added: Detailed view
|
if chain_config.fork(block.header.timestamp) != fork { | ||
return Err(( | ||
ChainError::Custom("Crossing fork boundary in bulk mode".into()), | ||
Some(BatchBlockProcessingFailure { |
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 is a bit confusing, since the problem is not that the block n is invalid, but that the caller made a mistake by calling this functions with blocks from different forks.
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.
Maybe a new error variant?
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.
Sounds good.
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.
We should handle this (if we cannot avoid it) in caller code (aka full sync) as crossing fork boundaries in a batch is something that will eventually happen when syncing networks. This probably exceeds the scope of this PR but we should create an issue for 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 with @fmoletta, we should create a ticket and handle this from the caller. But I think it's better to also check this from inside and return an error.
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.
See conversation in slack. This shouldn't be a problem since we're only dealing with post merge networks and we should be able to do batch block processing across fork boundaries.
crates/blockchain/blockchain.rs
Outdated
Ok(v) => v, | ||
Err(err) => return Err((ChainError::EvmError(err), None)), | ||
}; | ||
for account_update in account_updates { |
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.
not sure what this does, but it seems weird do do account updates processing in the blockchain crate. From a design perspective, it seems this should be done inside the vm crate and that blockchain crate should just get results and update the db?
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.
Actually now that a single get_state_transition call is made, this merge isn't needed. Fixed.
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.
Yep, we also don't need to use all_account_updates
nor the for
loop. We can just send account_updates
directly to the apply_account_updates
method.
let account_updates = result.account_updates; | ||
let _result = vm.execute_block(&block)?; | ||
// let receipts = result.receipts; | ||
let account_updates = vm.get_state_transitions(fork)?; |
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.
hmm, weird to pass the current fork to the get_state_transitions
function. From the outside, it doesn't make much sense.
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's needed because because SpuriousDragon changed the rules on remotion from the trie
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.
But we don't support SpuriousDragon
, so maybe we can avoid this?
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, I wanted to remove that in the past but the thing is that the State EF Tests test for Spurious Dragon and we use this same method. As per my understanding LEVM will ideally support all forks, but if we change opinion on that then it's ok to remove the fork.
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.
The vm should know which fork the block was executed from, so when calling get_state_transitions
it should have that information internally. It should not be passed explicitly. Otherwise I could execute a Cacun
block and then ask for the state transitions for SpuriousDragon
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! The VM knows the fork but the thing is that get_state_transitions
is not a method from the actual VM. It is just a function of the LEVM module in the intersection between L1 and the VM. Maybe it should be a VM method though.
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.
Adding to this. Our VM just exists in the context of a transaction, after executing one we discard the VM and the only thing that's left is the modified state, so we lose that VM instance that knew which fork it was executing. I agree that it's not nice to pass the fork, for now we can just disable SpuriousDragon
checks
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.
The LEVM DB doesn't currently keep track of which blocks it executed.
Benchmark Block Execution Results Comparison Against Main
|
crates/blockchain/blockchain.rs
Outdated
let account_updates = match vm.get_state_transitions(fork) { | ||
Ok(v) => v, | ||
Err(err) => return Err((ChainError::EvmError(err), None)), | ||
}; |
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.
let account_updates = match vm.get_state_transitions(fork) { | |
Ok(v) => v, | |
Err(err) => return Err((ChainError::EvmError(err), None)), | |
}; | |
let account_updates = vm.get_state_transitions(fork).map_err(|err| (ChainError::EvmError(err), None))?; |
nit
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.
Done
@@ -39,9 +39,10 @@ pub fn main() { | |||
panic!("invalid database") | |||
}; | |||
|
|||
let fork = db.chain_config.fork(block.header.timestamp); |
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.
This is not necessary when running with REVM
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.
Fixed
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 it's good!
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
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
Motivation
Currently during batch processing, the state transitions are calculated for every block and then merged, when it would be more performant to calculate them once at the end.
Description
This PR removes the account updates from the execution result and makes every consumer manually request them.
Closes #2504