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

refactor: allow chain-specific configuration of Evm #1378

Draft
wants to merge 15 commits into
base: main
Choose a base branch
from

Conversation

Wodann
Copy link
Contributor

@Wodann Wodann commented May 3, 2024

Experiment to see whether it would be possible to separate optimism and mainnet SpecIds and other types, such as HaltReason.

I'm curious to hear whether any of this is in line with #918

Copy link
Member

@rakita rakita left a comment

Choose a reason for hiding this comment

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

I have started reviewing this last weeks, but didnt have time to finish it whole and getter better grasp on it.

I general like it, change is needed but would like to minimise renames to get smaller PR.

As this is potentially a breaking change will need look at reth code and think how this impacts them as we are in the middle of devnet for Prague.

]
negate-optimism-default-handler = [
"revm-primitives/negate-optimism-default-handler",
]
Copy link
Member

Choose a reason for hiding this comment

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

Would not remove this yet, but will come back to this after i see what is done inside primitives

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If you're happy with the general approach, I can also adopt this pattern for the last couple of `#[cfg(feature = "optimism")] and then we can be certain that the features are gone from other parts of the code.

pub const fn from_spec_id(spec_id: revm_primitives::SpecId) -> Self {
use revm_primitives::SpecId::*;
pub const fn from_spec_id(spec_id: revm_primitives::EthSpecId) -> Self {
use revm_primitives::EthSpecId::*;
Copy link
Member

Choose a reason for hiding this comment

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

EthSpecId would revert back the name to SpecId. We don't need to specify that it is Eth and it makes too much changes in this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Resolved in c99bc9a


use core::{fmt::Debug, hash::Hash};

pub trait ChainSpec: Clone + Copy + Debug + Sized + 'static {
Copy link
Member

Choose a reason for hiding this comment

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

Would remove Copy so that we are more explicit with clone.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Resolved by a09af7f

type HaltReason: Clone + Debug + PartialEq + Eq + Hash + From<crate::HaltReason> + serde::de::DeserializeOwned + serde::Serialize;
} else {
/// The type that enumerates chain-specific halt reasons.
type HaltReason: Clone + Debug + PartialEq + Eq + Hash + From<crate::HaltReason>;
Copy link
Member

Choose a reason for hiding this comment

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

So with this, we are still having HaltReason. Need to check this but Shouldn't we have From<InstructionResult> here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This line handles the conversion from InstructionResult to type HaltReason thanks to the From<crate::HaltReason>

}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct MainnetChainSpec;
Copy link
Member

Choose a reason for hiding this comment

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

To nit here, it is not exactly MainnetChainSpec as it works on all testnets, but EthChainSpec.

Copy link
Contributor Author

@Wodann Wodann May 21, 2024

Choose a reason for hiding this comment

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

Resolved by 565eaa9


/// Generic result of EVM execution. Used to represent error and generic output.
pub type EVMResultGeneric<T, DBError> = core::result::Result<T, EVMError<DBError>>;

#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ResultAndState {
pub struct ResultAndState<ChainSpecT: ChainSpec> {
Copy link
Member

Choose a reason for hiding this comment

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

It seems unnecessary to tie the Result to the ChainSpec as it only needs the HaltReason.

This brings up all cast functions that do not have a great purpose.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The cast functions were a remnant from another attempt to achieve this. I've removed them in 26dec59.

W.r.t using the generic ChainSpec or HaltReason; up to you. I chose HaltReason in case some hardforks introduce custom SuccessReasons down the line.

#[cfg(feature = "optimism")]
type BenchChainSpec = revm::optimism::OptimismChainSpec;
#[cfg(not(feature = "optimism"))]
type BenchChainSpec = revm::MainnetChainSpec;
Copy link
Member

Choose a reason for hiding this comment

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

This is okay to be left just Mainnet

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Resolved by 53eb5b4

@@ -28,61 +29,68 @@ pub struct SetGenericStage;
/// Requires the database and external context to be set.
pub struct HandlerStage;

impl<'a> Default for EvmBuilder<'a, SetGenericStage, (), EmptyDB> {
impl<'a, ChainSpecT: ChainSpec> Default
Copy link
Member

Choose a reason for hiding this comment

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

This should be default, so variant of ChainSpec should be set, MainnetChainSpec probably

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Resolved by 5f87d2f

impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database>
EvmBuilder<'a, SetGenericStage, ChainSpecT, EXT, DB>
{
pub fn with_chain_spec<NewChainSpecT: ChainSpec>(
Copy link
Member

Choose a reason for hiding this comment

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

// cooment

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Resolved by 9d9e3e4

EvmBuilder {
context: self.context,
handler: EvmBuilder::<'_, SetGenericStage, NewChainSpecT, _, _>::handler(
NewChainSpecT::Hardfork::default(),
Copy link
Member

Choose a reason for hiding this comment

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

This is interesting to note, we now have ChainSpec and Hardfork as two separate entities. ChainSpec is here to define potential hardforks and hardfork type is here so it can be checked against ChainSpec.

We could have a trait Hardfork that will have a fn is_enabling() function. Would come back to this, those two should be split as ChainSpec is something that is going to grow.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is this something you want this PR to cover or a separate one?

@@ -0,0 +1,253 @@
use revm_interpreter::{
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This file merely serves to illustrate that we can support custom opcodes. It should be removed before merging.

@Wodann
Copy link
Contributor Author

Wodann commented May 24, 2024

Given that the general approach seemed to be the right direction, I removed the last instances of [cfg(feature = "optimism")] from the codebase by adding new types to the trait ChainSpec for variability of transaction and block environments.

Please let me know what you think. You should be able to review those changes commit-by-commit

@Wodann
Copy link
Contributor Author

Wodann commented May 24, 2024

I'll hold off on resolving merge conflicts until we're happy with the full design, if that's okay.

/// L1 block info used to compute the L1-cost fee.
///
/// Needs to be provided for Optimism non-deposit transactions.
l1_block_info: Option<L1BlockInfo>,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@rakita my understanding from our earlier conversation was that you wanted me to add the l1_block_info to the chain-specific block environment.

@Wodann
Copy link
Contributor Author

Wodann commented May 24, 2024

There are still some EVMError::Custom invocations in handler_register.rs. My understanding is that we could catch those when validating the environment.

That way we could use chain-specific errors static errors instead of strings. Alternatively, we could also add a custom error type to the trait ChainSpec.

That would allow us to remove the EVMError::Custom(String)

WDYT, @rakita ?

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.

Refactor REVM to make optimism feature flag additive
2 participants