-
Notifications
You must be signed in to change notification settings - Fork 392
refactor(spec-specs): Refactor state changes and frame hierarchy #1841
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
base: eips/amsterdam/eip-7928
Are you sure you want to change the base?
refactor(spec-specs): Refactor state changes and frame hierarchy #1841
Conversation
7e81fd1 to
af5d4ef
Compare
af5d4ef to
4569117
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## eips/amsterdam/eip-7928 #1841 +/- ##
===========================================================
- Coverage 82.46% 82.45% -0.02%
===========================================================
Files 797 797
Lines 47987 47996 +9
Branches 4341 4331 -10
===========================================================
Hits 39574 39574
- Misses 7927 7936 +9
Partials 486 486
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| disable_precompiles: bool | ||
| parent_evm: Optional["Evm"] | ||
| transaction_state_changes: StateChanges | ||
| is_create: bool = False |
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 in case of Message and TransactionEnvironment, I'd prefer not to rely on default values of the dataclass. I think the specs are more readable when we explicitly define all the attributes of these objects at the time of instantiation. Same for BlockEnvironment
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 fixed this for is_create. Do you think the same for state_changes or do you think this is fine to instantiate with a blank slate there?
| def create_child_frame(parent: StateChanges) -> StateChanges: | ||
| """ | ||
| Create a child frame for nested execution. | ||
| Create a child frame linked to the given parent. |
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 other thing we need to consider here is if we are ok with the _block_access_index defaulting to 0 for every child frame. I think every child frame should get the same _block_access_index as it parent.
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. I also think this can have the underscore removed? I will include this here.
| parent_frame = get_parent_frame(message) | ||
| create_frame = create_child_frame(parent_frame) | ||
| block_access_index = get_block_access_index( | ||
| message.block_env.block_state_changes |
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 rename this to block_env.state_changes to stay consistent with the tx_env.state_changes and message.state_changes
| increment_nonce(state, message.current_target) | ||
| nonce_after = get_account(state, message.current_target).nonce | ||
| track_nonce_change( | ||
| message.state_changes, |
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.
If we make the _block_access_index directly available in every child frame, we would not need to pass it as a function parameter
| set_code( | ||
| state, message.current_target, contract_code, create_frame | ||
| # Track code change for contract creation | ||
| pre_code = get_account(state, message.current_target).code |
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 this will always be b`` since we check if the target has code or nonce before going ahead with contract creation
src/ethereum/forks/amsterdam/fork.py
Outdated
| BlockAccessIndex( | ||
| get_block_access_index(block_env.block_state_changes) | ||
| ), | ||
| block_access_index, |
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.
If we intend to call this function beyond a transaction processing, might be best to rename it to normalize_balance_changes instead
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 we can normalize all net-zero filtering here once we remove that from merge_on_success as I mentioned before. And yeah, agreed, this is called on withdrawals too so the naming should be better here.
| recipient_address: Address, | ||
| amount: U256, | ||
| state_changes: StateChanges, | ||
| ) -> 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.
Note to self: Discuss the reasoning behind separating this out.
| if (addr, key) in child_frame.pre_storage: | ||
| if child_frame.pre_storage[(addr, key)] != value: | ||
| if (addr, key) in tx_frame.pre_storage: | ||
| if tx_frame.pre_storage[(addr, key)] != value: |
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 am thinking of the following scenario. tx_frame.pre_storage is 1. The parent_frame of the current frame changes it to 2 and the current frame changes it back to 1. Would the changes made by the current frame be ignored because the value is the same as in the tx_frame but the changes in the parent_frame be captured. Thus leading us to believe the overall change was 1->2 while in reality it was 1->2->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.
Yes! I think this is definitely broken and I wrote a test to make sure here :). I think this should be simplified quite a bit. The children should just merge all their changes to the parent's changes to be honest, to update the state of the parent after processing the child frame, and the net-zero filtering should only be done at the commit_transaction_frame level. That's the reason that has its own method anyhow since the only difference between the top-level transaction frame committing and merge_on_success for child frames is that net-zero changes need to be filtered out.
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 did check this before and after and it was broken but now passes those nested tests. Good tests to have 👍🏼
🗒️ Description
BlockEnvironment,TransactionEnvironment, andMessage. This removes much of the unnecessary complexity related to parent frame tracking.state_changesfromStatefunctions, opt to capture changes before and after (from comments here)🔗 Related Issues or PRs
#1836
✅ Checklist
toxchecks to avoid unnecessary CI fails, see also Code Standards and Enabling Pre-commit Checks:uvx tox -e statictype(scope):.Cute Animal Picture