You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In #1711, I discussed the roadmap for releasing Rust EVM 1.0 and integrating it into Frontier. Over the past few weeks, we have made significant progress toward bringing this into reality. In particular:
I have reached a design that I think is good. It's fully customizable without too much type complexity.
We now pass the entire Ethereum test suite of the Istanbul hard fork. Other hard forks have not yet been checked, but will be done soon.
Integration plans
After documentation, fixes, and final release of Rust EVM 1.0, we'll begin the integration into Frontier. The plan is to write an additional crate evm-compat that mimics the interface of v0.x (mainly StackExecutor), reducing the amount of integration efforts. This should allow us to finish the integration without any major structural changes in Frontier.
Things that you may find interesting
Rust EVM 1.0 is more extensible, and it contains a few new features that you may find interesting.
Async precompiles.
Users of Rust EVM often implement complex custom precompiles. It is a long-requested feature that those precompiles can also do custom call/create, just like a normal EVM contract. In the past, this was not easy to do. EVM engines need to use a heap-based call stack (for deep calls), and in this case, a call/create would not continue the function, but must return first. After the call stack finishes executing subcalls, it then "feeds back" the result to the current level.
In Rust EVM 1.0, we get async precompiles. It uses the async fn Rust construct that returns a Future, allowing something like below to be possible:
asyncfnasync_precompile_noop(submit:Rc<FutureInterpreterSubmit<CallCreateAction,()>>) -> ExitResult{// Do something.let feedback = submit.submit(CallCreateAction::Call{ .. }).await;// Do something else.Ok(ExitSucceed::Returned)}
Custom gas metering
In v0.x, gas metering is already customizable, but in certain situations, it is still messy. On many occasions, we must modify the existing code or create additional hooks.
In Rust EVM 1.0, we can use a chained etable. This is like a generic "hook" into every step of opcode execution and has access to the same set of information as the gasometer (in fact, the standard gasometer itself is implemented as a chained etable).
Better development process for new EIPs
For unreleased EIPs, in the past, we always faced the dilemma of where to add them into our codebase. We want new EIPs probably well in advance of when it is adopted in the Ethereum mainnet, yet we must also prepare for the situation where we want to scrap it, as the Ethereum community may come up with a better EIP in the meantime.
Rust EVM 1.0 makes it possible to implement new opcode features as a separate crate. Take a look at the draft EVM64 implementation as an example.
Custom interpreters
The interpreter type in Rust EVM 1.0 is customizable, and the call stack itself is generic. It's now possible to invoke another type of interpreter in a call stack as long as it adheres to a few basic rules.
Account versioning
Rust EVM 1.0 also gets all constructs necessary to implement account versioning, which may become important at some point if we ever want to implement an EIP that may be incompatible with old versions. The Config reference pointer is now passed down in the state to each call stack. You can set a new config (at each call stack) and it will work as expected.
Principle: Customizability reduces development efforts and testing requirements
The general approach for writing a customized engine based on EVM hasn't changed in the past decades. Unless one is already sufficiently big (like OP Stack) and upstream is willing to merge support themselves, it almost always requires forking a codebase and then making changes internally. As time passes by, the two codebases diverge so much that it's generally not possible anymore to merge upstream changes. We're unfortunately seeing that again in Revive's REVM integration.
Even with sufficient manpower, this still presents problems -- Ethereum has an extensive test suite, and any customization will make it impossible to use the test suite ever again, even if only a small part is changed. This significantly increases development efforts and testing requirements. Rust EVM 1.0 wants to present a different picture:
By making as many parts of the system as possible generic, customizability is improved.
The "standard" Ethereum mainnet is just a specialization, which can be fully tested against the test suite.
Other custom chains use the same construct and the same codebase. Only those that are changed need to be retested.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
In #1711, I discussed the roadmap for releasing Rust EVM 1.0 and integrating it into Frontier. Over the past few weeks, we have made significant progress toward bringing this into reality. In particular:
Integration plans
After documentation, fixes, and final release of Rust EVM 1.0, we'll begin the integration into Frontier. The plan is to write an additional crate
evm-compatthat mimics the interface of v0.x (mainlyStackExecutor), reducing the amount of integration efforts. This should allow us to finish the integration without any major structural changes in Frontier.Things that you may find interesting
Rust EVM 1.0 is more extensible, and it contains a few new features that you may find interesting.
Async precompiles.
Users of Rust EVM often implement complex custom precompiles. It is a long-requested feature that those precompiles can also do custom call/create, just like a normal EVM contract. In the past, this was not easy to do. EVM engines need to use a heap-based call stack (for deep calls), and in this case, a call/create would not continue the function, but must return first. After the call stack finishes executing subcalls, it then "feeds back" the result to the current level.
In Rust EVM 1.0, we get async precompiles. It uses the
async fnRust construct that returns aFuture, allowing something like below to be possible:Custom gas metering
In v0.x, gas metering is already customizable, but in certain situations, it is still messy. On many occasions, we must modify the existing code or create additional hooks.
In Rust EVM 1.0, we can use a chained etable. This is like a generic "hook" into every step of opcode execution and has access to the same set of information as the gasometer (in fact, the standard gasometer itself is implemented as a chained etable).
Better development process for new EIPs
For unreleased EIPs, in the past, we always faced the dilemma of where to add them into our codebase. We want new EIPs probably well in advance of when it is adopted in the Ethereum mainnet, yet we must also prepare for the situation where we want to scrap it, as the Ethereum community may come up with a better EIP in the meantime.
Rust EVM 1.0 makes it possible to implement new opcode features as a separate crate. Take a look at the draft EVM64 implementation as an example.
Custom interpreters
The interpreter type in Rust EVM 1.0 is customizable, and the call stack itself is generic. It's now possible to invoke another type of interpreter in a call stack as long as it adheres to a few basic rules.
Account versioning
Rust EVM 1.0 also gets all constructs necessary to implement account versioning, which may become important at some point if we ever want to implement an EIP that may be incompatible with old versions. The
Configreference pointer is now passed down in the state to each call stack. You can set a new config (at each call stack) and it will work as expected.Principle: Customizability reduces development efforts and testing requirements
The general approach for writing a customized engine based on EVM hasn't changed in the past decades. Unless one is already sufficiently big (like OP Stack) and upstream is willing to merge support themselves, it almost always requires forking a codebase and then making changes internally. As time passes by, the two codebases diverge so much that it's generally not possible anymore to merge upstream changes. We're unfortunately seeing that again in Revive's REVM integration.
Even with sufficient manpower, this still presents problems -- Ethereum has an extensive test suite, and any customization will make it impossible to use the test suite ever again, even if only a small part is changed. This significantly increases development efforts and testing requirements. Rust EVM 1.0 wants to present a different picture:
Beta Was this translation helpful? Give feedback.
All reactions