Skip to content
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

Ensure state is correct in both EVM and Scilla environments #2414

Merged
merged 1 commit into from
Mar 6, 2025

Conversation

JamesHinshelwood
Copy link
Contributor

@JamesHinshelwood JamesHinshelwood commented Feb 27, 2025

When an interop. transaction is run, we need to be careful to keep track of state changes in both sides of the world.

This PR takes the approach of:

  • Let revm keep track of EVM state changes as normal.
  • When an interop call is made to the Scilla interpreter, we make sure any 'pending' changes from the EVM side are visible to the Scilla contract.
  • When the Scilla call finishes, if any 'pending' EVM changes were modified further, we apply those changes to the EVM state journal before transferring control back to revm.

This ensures the state we read is consistent and that when we come to apply state delta updates, there is no overlap between the EVM and Scilla state maps.

Copy link
Contributor

github-actions bot commented Feb 27, 2025

🐰 Bencher Report

Branchfix-interop
Testbedself-hosted
Click to view all benchmark results
BenchmarkLatencyBenchmark Result
milliseconds (ms)
(Result Δ%)
Upper Boundary
milliseconds (ms)
(Limit %)
full-blocks-erc20-transfers/full-blocks-erc20-transfers📈 view plot
🚷 view threshold
1,071.50 ms
(-1.44%)Baseline: 1,087.20 ms
1,429.22 ms
(74.97%)
full-blocks-evm-transfers/full-blocks-evm-transfers📈 view plot
🚷 view threshold
453.45 ms
(+11.43%)Baseline: 406.94 ms
490.06 ms
(92.53%)
full-blocks-zil-transfers/full-blocks-zil-transfers📈 view plot
🚷 view threshold
3,400.00 ms
(-16.06%)Baseline: 4,050.69 ms
5,644.12 ms
(60.24%)
process-empty/process-empty📈 view plot
🚷 view threshold
10.32 ms
(+3.21%)Baseline: 10.00 ms
10.73 ms
(96.17%)
🐰 View full continuous benchmarking report in Bencher

@JamesHinshelwood JamesHinshelwood force-pushed the fix-interop branch 2 times, most recently from fcea5fd to 09ca46a Compare February 28, 2025 12:39
@JamesHinshelwood JamesHinshelwood marked this pull request as ready for review February 28, 2025 12:39
@JamesHinshelwood JamesHinshelwood force-pushed the fix-interop branch 3 times, most recently from fa19856 to 0e0afa8 Compare March 6, 2025 15:57
When an interop. transaction is run, we need to be careful to
keep track of state changes in both sides of the world.

This PR takes the approach of:
* Let `revm` keep track of EVM state changes as normal.
* When an interop call is made to the Scilla interpreter, we make
sure any 'pending' changes from the EVM side are visible to the
Scilla contract.
* When the Scilla call finishes, if any 'pending' EVM changes were
modified further, we apply those changes to the EVM state journal
before transferring control back to `revm`.

This ensures the state we read is consistent and that when we come
to apply state delta updates, there is no overlap between the EVM
and Scilla state maps.
@JamesHinshelwood JamesHinshelwood added this pull request to the merge queue Mar 6, 2025
Merged via the queue into main with commit a80bcec Mar 6, 2025
5 of 6 checks passed
@JamesHinshelwood JamesHinshelwood deleted the fix-interop branch March 6, 2025 17:33
Copy link
Contributor

@rrw-zilliqa rrw-zilliqa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll hit the approve button, but I'm not sure I understand the implications of either this patch or of the scilla execution mechanism generally - there's a lot of special-casing going on, and this is security critical code. That said, absent a lot of comments and probably some refactoring, I'm unlikely to get any better inside a week, and we do need to fix the bug...

One thing to check is that scilla remote contract reads still work - zeroing the storage location might be sufficiently safe, in that since scilla contracts will never end up in the journaled evm log, scilla can never legally read them via remote contract reads (or remote library references), but it would be nice to be more certain.

@@ -622,6 +626,7 @@ fn scilla_call_precompile<I: ScillaInspector>(
};
trace!(?result, "scilla_call complete");
if !&result.success {
evmctx.db = state;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This allows failed scilla transitions to modify the state - do we want to allow this?

@@ -631,7 +636,25 @@ fn scilla_call_precompile<I: ScillaInspector>(
return err("scilla call failed");
}
}
// Move the new state back into `evmctx`.
state.new_state.retain(|address, account| {
if !account.touched {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to rely on side effects in retain() ? (it's safe, but .. )

.original_bytes()
.to_vec()
}),
storage_root: B256::ZERO, // There's no need to set this, since Scilla cannot query EVM contracts' state.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can't query the code either, so why set that?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants