Terminology: I'll use the word vanilla to mean the unaltered EVM as proposed in the Ethereum white/yellow paper.
In its current form, it's impossible to run REVM both in vanilla and Optimism mode. Rust features are supposed to be additive such that enabling a feature doesn't disable some other feature. Unfortunately, in REVM the optimism feature flag doesn't quite work this way. When you enable the optimism feature flag, you can no longer use a vanilla EVM. Instead:
the enum SpecId will contain optimism-specific hardforks;
the enum HaltReason contains optimism-specific variants;
the enum InvalidTransaction contains optimism-specific variants;
the struct TxEnv contains a field optimism: OptimismFields
the struct InnerEvmContext contains a field l1_block_info: L1BlockInfo.
As a result, vanilla EVM exeuction code in EDR would need to set missing struct fields at construction and handle missing enum variants in match statements.
I did some experiments to see whether I could decouple the SpecId and HaltReason. The results are in this draft PR: https://github.com/bluealloy/revm/pull/1378. With this design it's possible to configure the EVM per chain, allowing:
static typing of the chain spec using trait ChainSpec;
the EvmBuilder to restrict typing using the specified ChainSpec;
custom HaltReasons;
custom SpecIds;
custom opcode handlers that have access to the chain-specific trait {CustomChain}Spec;
reuse of the vanilla mainnet opcode handlers, thanks to the ability to const cast to the base trait {Vanilla}Spec
I did not research the OpCode struct, which provides convenience functions for retrieving opcode name, accessing the jump table, etc. However, it seems possible to extend the opcode! macro to implement chain-specific OpCode structs that are able to retrieve this information for that particular chain
Based on the design pattern used in the draft PR, I think we can use the same pattern as I used for HaltReason to also convert the TxEnv and InnerEvmContext to use composition instead of a feature flag inside the structs.
With those changes, I think that would remove the last occurrences of the optimism feature flag inside "core" REVM code.
Alternatives
If we cannot make the base REVM implementation generic for alternative chains, we can use the generic EXT (i.e. external context) to pass in chain-specific data for the block, transaction, SpecId, etc.
This doesn't allow us to override the HaltReason, ExecutionResult, etc.; preventing us from returning chain specific errors this way. We can circumvent this by setting chain-specific results in the external context.
This solution doesn't follow the normal control-flow of Rust, so will be "hacky".
Terminology: I'll use the word vanilla to mean the unaltered EVM as proposed in the Ethereum white/yellow paper.
In its current form, it's impossible to run REVM both in vanilla and Optimism mode. Rust features are supposed to be additive such that enabling a feature doesn't disable some other feature. Unfortunately, in REVM the
optimism
feature flag doesn't quite work this way. When you enable theoptimism
feature flag, you can no longer use a vanilla EVM. Instead:enum SpecId
will contain optimism-specific hardforks;enum HaltReason
contains optimism-specific variants;enum InvalidTransaction
contains optimism-specific variants;struct TxEnv
contains a fieldoptimism: OptimismFields
struct InnerEvmContext
contains a fieldl1_block_info: L1BlockInfo
.As a result, vanilla EVM exeuction code in EDR would need to set missing struct fields at construction and handle missing enum variants in
match
statements.I did some experiments to see whether I could decouple the
SpecId
andHaltReason
. The results are in this draft PR: https://github.com/bluealloy/revm/pull/1378. With this design it's possible to configure the EVM per chain, allowing:trait ChainSpec
;EvmBuilder
to restrict typing using the specifiedChainSpec
;HaltReason
s;SpecId
s;trait {CustomChain}Spec
;const
cast to the basetrait {Vanilla}Spec
I did not research the
OpCode
struct, which provides convenience functions for retrieving opcode name, accessing the jump table, etc. However, it seems possible to extend the opcode! macro to implement chain-specificOpCode
structs that are able to retrieve this information for that particular chainBased on the design pattern used in the draft PR, I think we can use the same pattern as I used for HaltReason to also convert the
TxEnv
andInnerEvmContext
to use composition instead of a feature flag inside the structs.With those changes, I think that would remove the last occurrences of the optimism feature flag inside "core" REVM code.
Alternatives
If we cannot make the base REVM implementation generic for alternative chains, we can use the generic
EXT
(i.e. external context) to pass in chain-specific data for the block, transaction,SpecId
, etc.This doesn't allow us to override the
HaltReason
,ExecutionResult
, etc.; preventing us from returning chain specific errors this way. We can circumvent this by setting chain-specific results in the external context.This solution doesn't follow the normal control-flow of Rust, so will be "hacky".