Long-term L1 execution layer proposal: replace the EVM with RISC-V

Vitalik Buterin claims that replacing the Ethereum Virtual Machine (EVM) with RISC-V could improve zero-knowledge (ZK) proof efficiency by 50 to 100 times. However, is RISC-V truly superior? The EVM has been a stable, battle-tested environment for approximately nine years, while RISC-V lacks substantial real-world experience in blockchain execution contexts. Although PolkaVM has adopted RISC-V, I believe it has not been adequately validated, as it has yet to be thoroughly proven on a mainnet.

The EVM is specifically optimized for smart contract execution, whereas RISC-V, designed as a general-purpose architecture, may lack tailored optimizations for blockchain use cases. While RISC-V’s versatility allows the use of programming languages from other blockchains, Vitalik himself noted that improvements leveraging existing Solidity are preferable. Transitioning the entire ecosystem to a new architecture is a daunting challenge.

Implementing RISC-V in software inevitably leads to performance degradation. Using an emulator for software-based execution raises doubts about its ability to process tasks efficiently. On the other hand, adopting RISC-V hardware would entail significant transition costs. I believe that ZK-EVMs already provide sufficient efficiency for current needs. When considering the costs of development, the effort required for transition, and the potential for unforeseen errors, replacing the EVM with RISC-V does not seem like a compelling approach.

While transitioning to RISC-V may offer potential benefits, I argue that improving ZK-EVMs and optimizing the existing EVM are more practical and stable alternatives.

2 Likes

But… why? And this is genuine question that I don’t understand and need more context about.

The supposed answer is performance. But this until proven might be just a false promise. And if you are getting 100x-1000x improvements in benchmarks, you are clearly doing something wrong and the overhead should be avoidable at least to some extent.

There are multiple projects that try compiling EVM bytecode to native code (Revmc, Nethermind IL-EVM ect.), why not to build a compiler to risc-v that would give us the speedups we need while not needing a complete paradigm change?

The potential problem with that is that classic EVM bytecode is hard to introspect and thus hard to compile, but we have a solution just around the corner - EOF, which should make things much simpler.

Having abstract EVM that is easy to compile to other things, while laser focused on domain problems is probably better than using general purpose architecture. This is the foundation of Java, .Net or LLVM and works well for them, and with some effort it is not a performance bottleneck (for example check Nethermind client performance which is build on .Net).

Also no idea about the hardware that is coming, especially zk-circuts, but my bet is that RISC-V general purpose CPU’s will have a hard time catching up to x86 and ARM.

10 Likes

This proposal is preaty radical — but I believe it will carry the seeds of a renaissance for Ethereum. Native RISC-V execution could supercharge performance, enable more efficient ZK proofs, and better align with future hardware acceleration.

That said, several concerns give me pause:

  • The complexity of implementation could introduce new vulnerabilities and slow down core development.
  • A RISC-V shift raises the bar for low-level developers, potentially increasing the learning curve and reducing accessibility.
  • Without adoption from other EVM chains, we risk fragmenting the broader ecosystem.
  • Backward compatibility with the vast existing contract base may be difficult to guarantee.
  • And finally, coordinating such a transformation through governance and a potential hard fork is no small feat.

Hi. I’m the guy responsible for PolkaVM. Since I see some misinformation flying around here and there let me chime in with some details as to what PolkaVM is and how it works.

PolkaVM currently supports riscv64emac with the Zbb extension, but unlike most (all?) other RISC-V VMs it doesn’t run RISC-V binaries as-is (it’s not actually a RISC-V VM!). Offline we ingest normal RISC-V ELF binaries that you build using a normal compiler, and we translate them into a more constrained and efficient custom bytecode that’s designed for use in a VM (and not native hardware, like RISC-V is). The idea is to remove as much complexity out of the VM itself (which needs to run on-chain), put as much of that complexity as possible into offline tooling (which can run off-chain), and improve security by removing unnecessary features (e.g. in vanilla RISC-V you can jump to any address; in PolkaVM bytecode the code address space is fully virtualized, you can’t jump everywhere, and the bytecode isn’t even loaded into memory that’s accessible by the program).

Performance-wise we get very close to bare metal performance[1]; it’s as fast as wasmtime (which is the state-of-art WASM VM), but it guarantees O(n) recompilation and recompiles programs into native code hundreds times faster. To put this into perspective, it is faster to recompile a program from scratch starting with raw PolkaVM bytecode into the native code than it is to cache the recompilation artifacts and look them up based on their hash (in other words, recompiling the program is faster than calculating its hash), and this is without sacrificing runtime execution performance.

We mainly use RISC-V not because it’s a particularly good bytecode for a VM (it actually isn’t that great), but because it’s simple, well supported and it’s relatively easy to translate to something else, so we can get the best of both worlds - great software compatibility (you can use existing compilers and programming languages, e.g. the other day I ported Quake to PolkaVM[2][3]), but you also get the benefits of a custom, optimized bytecode (blazing fast compilation speed, near-native performance, simplicity and customizability).

Anyway, if you have any questions feel free to ask me anything.


Links: (New account so I’m not allowed to post links, so just replace ā€œgithubā€ with github dot com)

[1] - github/paritytech/polkavm/blob/master/BENCHMARKS.md
[2] - github/paritytech/polkaports/tree/master/apps/quake
[3] - github/paritytech/polkavm/tree/master/examples/quake

14 Likes

Hi, I am one of the core developers of Cartesi’s VM. As someone actively working in a RISC-V VM for blockchain applications – the Cartesi Machine[1], which @GCdePaula kindly mentioned – I wanted to share some perspective supporting the exploration of RISC-V for Ethereum’s execution layer.

One of the biggest advantages I see in adopting RISC-V is the immediate access to mature tooling and ecosystems. Instead of building a completely bespoke environment, using RISC-V allows developers (and the core protocol) to tap into decades of work on compilers like GCC and LLVM, debuggers, libraries, and even full operating systems like Linux. This significantly lowers the barrier for developers and potentially reduces the risk associated with compiler bugs compared to newer, less battle-tested toolchains. It aligns well with the goal of potentially allowing contracts written in languages like Rust or even C++ to target Ethereum, compiled via standard backends. For those who question bugs in LLVM or GCC, strengthening security guarantees by using formally verified compilers such as CompCert[2] that are capable of targeting RISC-V today is a possibility. Thinking big, maybe even running applications on top of formally verified RISC-V operating system kernels such as seL4[3] on VMs covering RISC-V privileged ISA specification (such as the one I work on) could be a possibility for more complex applications demanding to run inside an operating system environment.

The performance concerns raised by some are valid but addressable. From my experience, RISC-V doesn’t inherently sacrifice execution performance when implemented properly. While u256 operations naturally decompose to multiple instructions, in practice in a well optimized RISC-V VM the cost of doing so for most situations should not impact performance that much. Furthermore, optimization techniques at the VM level could significantly mitigate these costs, as the RISC-V ISA is extensible enough to add custom blockchain-specific extensions that could optimize common cryptographic operations (e.g., Keccak256).

I think basing the future execution layer on a standardized, open, and well-supported ISA like RISC-V provides a solid foundation. It offers a path towards leveraging existing software ecosystems, potentially simplifying the developer experience, and benefiting from future hardware advancements in the RISC-V space.

While the road is complex, I believe the potential benefits for scalability, tooling maturity, and long-term maintainability make RISC-V a direction very much worth pursuing for the future of blockchain execution environments. Many existing RISC-V VMs in the blockchain space today demonstrate that robust, production-ready RISC-V implementations can exist. Specifically, I think the Cartesi Machine showcases the power of leveraging a standard, open ISA. It’s a stable, high-performance RISC-V emulator implementing the standard RV64GC ISA capable of running the entire Linux software stack and unmodified RV64GC ELF binaries. Crucially, it’s fully deterministic, right down to floating-point operations. For those curious wanting to grasp what it’s capable of running, I recommend experimenting with my WebCM[4] experiment, a serverless terminal that runs a virtual Linux directly in the browser by emulating a RISC-V machine powered by the Cartesi Machine emulator compiled to WebAssembly.

Now, the L1 proposal focuses on ZK-proofs, whereas Cartesi currently enables on-chain verification via interactive fraud proofs, leveraging deterministic execution, and state Merkle proofs. While the verification mechanism differs, Cartesi confirms that building a verifiable and deterministic execution environment on top of RISC-V is viable and worthwhile.

Of course, integrating RISC-V directly into L1 with ZK-proving presents unique and significant challenges, particularly around gas metering, defining the precise syscalls for state interaction, and optimizing ZK circuits for RISC-V instructions. Performance in the specific context of ZK-proving also needs deep investigation. Fortunately, there are many RISC-V zkVMs projects already doing research and development on those points.

Regarding implementation strategy, I believe serious consideration should be given to the ā€œradical approachā€ of defining a protocol that enshrines the concept of a virtual machine interpreter compiled down to RISC-V. This approach would create a path where Ethereum’s core RISC-V VM could remain minimal and simple, while still being flexible enough to accommodate different VM interpreters beyond the EVM, giving developers more freedom in their virtual machine development.

In short, I believe leveraging a standard like RISC-V offers tremendous advantages in tooling, developer familiarity, flexibility, and even the potential for long-term hardware acceleration. My work experience with the Cartesi Machine reinforces the idea that RISC-V is a powerful and viable foundation for the next generation of verifiable blockchain computation, and it’s exciting to see it being seriously considered for Ethereum’s core execution layer.

–

[1] - /github.com/cartesi/machine-emulator
[2] - /compcert.org
[3] - /sel4.systems
[4] - /edubart.github.io/webcm

Links: New accounts are not allowed to include links, prefix them with https:/.

10 Likes

Hi, can Yul be a good choice for a zk-friendly ISA?

It does not make a hypothesis about how variables are allocated. They could be stack-based (like in EVM), register-based (like in RISC-V), or even memory-based (like in Valida zkVM). The execution layer could provide a (proven) compilation pass from Yul to its assembly language.

In addition, it is relatively standard, being the intermediate language of the Solidity compiler.

2 Likes

I’m working on a longer reply, but have a question @vbuterin : I see how this could potentially help goal 3 (ZK-EVM proving capabilities), but how does it address goal 2 (Desire to keep block production a competitive market)?

1 Like

Fantastic points here Adam! I think overall your comments make a lot sense and I think understanding what we’re trying to optimize for primarily helps us understand which trade offs we want to make and I agree about the tension between optimizing for L1 but canabalizes gains from L2 :thinking:

thinking about this more and wondering how difficult would it be to maintain backwards compatibility between EVM and RISC-V contracts at scale?

also on this could be opt-in at first, with the RISC-V VM gradually becoming dominant as tooling matures?

Not sure what the priorities are. Notice that you really want all the cryptography to move to 32-bit PQ secure stuff, like over M31 or babybear. Going down the KZG+ECC stuff will lead to things that are quantum susceptible, and ~100x slower than STARK friendly crypto.

2 Likes

#1 priority to get more proving scale is to embrace 32-bit logic and 32-bit primes, like M31 and babybear. If you do this, you’ll get things that are probably compatible with fastest STARK proof generation (in addition to being PQ secure)

3 Likes

Hi, I’m the maintainer of the previously mentioned revive Solidity compiler. Your are spot on. Exactly this is the reason for a lot of unnecessary overhead contracts written in Solidity or any other language compiled to the EVM are exposed to.

Adding to that, the big endian nature of the EVM requiring a lot of byte swaps on those u256 values makes things even worse. A big endian VM with 256 bit word size as the only type is by nature unable to compete with lets say PolkaVM or SVM (n.b. a more efficient bytecode would generally also imply more efficient execution proving of said bytecode). I really want to stress your point here.

2 Likes

I like the idea of exploring changes in the EVM to make it more provable.

As for the performances, I understand implicitly the proposal as splitting the EVM in two parts. The first part is a kernel controlling the ā€œsensitiveā€ operations (e.g. handling the state accesses, creating the execution contexts for every calls and subcalls, doing the reverts etc…) and the second part is a free RISC5 interpreter that can be used by the contracts. I am confident it would allow massive saving for use-cases like Fibonacci, doing heavy integer arithmetic and almost no kernel calls. But for actual workload, most of the gas spending is done by doing cryptography operations and storage access. I am also concerned that switching a lot between kernel and user mode may have a non-negligible cost. So, even in a world where every contract has migrated to the RISC5 version of the EVM, the prover runtime savings I see would be well under the objective of 50x.

For similar reasons, I wouldn’t suggest moving to more ZK-friendly ISAs because they would not address the above problem and would also come with the issues of young developer ecosystems. If the target of 100x is important, it would have to be combined with an effective way to optimize the precompiles and the kernel operations and this will require more aggressive solutions. Direct arithmetization, combined with in-depth proof-system engineering (for the precompiles), is a more promising way to get there. This is the path we have been taking at Linea and unlike many, we have no plan to switch to a pure RISC-V approach.

And even then, all the benefits would be negated if the retro-compatibility entails maintaining the old EVM beside the RISC5 one. If the actual driver and primary goal of the proposal is to move away from the current EVM while maintaining ZK-friendliness, then it is understandable. But then, I also have concerns/questions with the proposed approaches.

  1. Side-by-side environments: I worry about these temporary solutions that end up lasting forever and adding a lot complexity to the overall system.
  2. Transpiling on the fly the legacy bytecode. This will require figuring out a transpilation algorithm that guarantees that the contracts always behave in the same way after transpilation. It’s not very clear to me how this would work; would it just expand the ā€œEVMā€ handling of every opcode into RISC5 code?
  3. Multiple execution environments: If we want this to unfold in a way that does not worsen the Eth fragmentation and maintain prover-friendliness, it means we will have to work out a standard way to allow contracts to call each other through different execution environments. For the provers, this corresponds to emulating multiple VMs. I can see how this could make developing on Ethereum more attractive but it also means that the prover complexity will increase even more.

To conclude, I stress that formal verification of zk-EVMs is years away from being L1-ready. I fully appreciate all the steady progress that is being and has been made in the RISC5 ecosystem toward formally verifying the arithmetization of RISC5. However, I think the speed of the progress (vs direct arithmetization) is mainly due to the simplicity of the RISC5 VM, and I’d add that the FV analysis of a RISC5 approach also needs to cover FV-ing the compiler suites. This part is a completely different beast. Taking this into account, contrary to the current popular belief, I don’t think direct arithmetization is that much worse off than RISC5 for FV.

Multiprovers and L2 fallback mechanisms are currently the only short-to-medium-term solution to have fully production-ready ZK systems on-chain.

5 Likes

Thanks for stressing out that a large part of the execution time is in cryptography, and that formally verifying RISC-V VM is not comparable to formally verifying zkEVM, as the compiler is missing, and this is the most complex part!

That being said, I am fairly confident we will have a complete and formally verified stack in Rocq/Coq with an EVM interpreter on RISC-V, down to the Rust implementation of the circuits, by the end of the year thanks to a joint work. It would use the CompCert project internally to compile an optimized EVM implementation in Rocq to RISC-V, and then we would verify the Rust code of the circuits with ā€œcoq-of-rustā€ (I would personally like to see ZK optimized ISA, from an engineering perspective).

If we did go about this, would it be in a separate GitHub repo like eWASM or would it be a sequence of EIPs like EOF?

If the goal is prover efficiency than RISC-V is a sub-optimal choice.
Cost profiles for a direct execution and for proving such execution are different.
Of course, if the direct execution requires less steps, it’s beneficial from the prover perspective too.
However, provers actually prove execution of a trace checking program, not execution of the original program per se.

One such problem is register file. RISCs are register-based ISAs, which is clearly beneficial for direct execution. However, it’s a problem from trace checking perspective, since one needs to maintain register file consistency somehow (e.g. by copying unchanged register values from row to row). And one has to prove load/store operations which moves data from memory to registers and back. Such memory hierarchy is critical for achieving high CPU speed, but it’s a serious source of redundancy from trace checking perspective - and thus degrades prover time. Compare with ZK-optimized ISAs like Cairo or Valida, which have only two or three registers and operate with memory directly.

In that respect, it’s not actually clear whether RISC-V is a really better ISA than EVM from prover (trace checking) perspective. EVM is stack based, so its register file is small.
EVM operates with 256bit numbers, which can be a problem, if much smaller values dominates. However, a prover has an access to an actual execution trace, so it can choose a lighter weight implementation option for small values (e.g. a byte decomposition of a 32bit value can occupy less rows than a byte decomposition of a 256bit value).

3 Likes

Another aspect is smart contract Formal Verification costs. EVM is more a limited ISA than RISC-V, so F/V will be more complicated, in general. RISC-V smart contracts will generally have more loops and more memory operations, both of which pose problems from F/V.

E.g. one study (/www.cs.utexas.edu/~isil/solis.pdf) indicates that roughly one fifth of EVM smart-constracts has one or more loop. Since EVM operates with 256bit values, in RISC-V code more loops will be necessary. Even if loops are unrolled, this will result in much bigger SMT queries.

RISC-V has a richer memory model and there should be more memory operations (e.g. EVM has 1024 256bit stack, vs 16-32 32/64 bit registers). So, aliasing (two syntactically distinct expressions pointing to the same memory location) will be a more severe problem. Which in turn affects static analyses like Call Graph reconstruction, point-to analysis and similar.
I expect that formal reasoning about RISC-V smart-contracts in presence of loops/aliasing will be much more challenging compared to EVM smart-contracts.

2 Likes

If the base protocol only needs to know ā€œThere’s a RISC‑V CPU and a merkleized key‑value store,ā€ a lot of historical EVM quirks disappear. A smaller surface means fewer consensus bugs.

Plus, we inherit battle‑tested compiler stacks like GCC, LLVM, and the Rust toolchain, all with thousands of contributors and years of scrutiny. Relying on these well‑audited compilers means stronger optimization, richer debugging, and formal‑verification tooling right out of the box. Leaner core, proven toolchain, cheaper ZK proofs, faster syncs.

3 Likes

It’s certainly desirable to give the zkVMs something in a more ready format. I want to raise the possibility of going a bit deeper and specifying implementations of the EVM opcodes in an enshrined circuit IR (call it TheIR in for the moment) which could then be consumed directly by the provers.

Objection 1: Provers differ so much that it’s not possible to do this with out giving preference to some particular architecture.
Response 1: The same objection could be raised about enshrining RISC-V. It is the most common target choice but not the only one (see ://x.com/eth_proofs/status/1912604603394502802/photo/1).

Objection 2: But zkVM progress has been spectacular. Won’t constraining the cryptographic backends by providing something too low level / opinionated stifle progress?
Response 2: Agree that this is a serious concern, but we can’t draw conclusions without a deeper viability study. On that note, many different groups have thought about circuit IRs. In particular, as part of the zkEVM Formal Verification Project (://verified-zkevm.org/), Veridise is working on such an IR called LLZK (see ://medium.com/veridise/veridise-secures-ethereum-foundation-grant-to-develop-llzk-a-new-intermediate-representation-ir-224c0e71f4d5). This could be TheIR if it’s designed well enough (broader community involvement would of course be a requirement here).

Objection 3: But then won’t the zkVMs have to implement circuits for TheIR opcodes?
Response 3: We’re talking about long timescales for any of this. ā€œHave toā€? Possibly they will have to the long long run if there is widespread abandonment of EVM interpretation by zkVMs. In the medium (many-year) term, if we can tolerate storing EVM bytecode alongside TheIR bytecode (I don’t know how viable this is), then zkVMs could experiment with both approaches and even incrementally upgrade. In this world, I would regard the switch to consuming TheIR as the change to upgrade the proving system to a format would likely unlock both efficiency gains and the possibility to use security tooling built around TheIR.

Objection 4: But so much energy has gone into supporting RISC-V—why not just go with that?
Response 4: Objections have been raised in previous comments about how RISC-V is too low-level for clean usage in large integer arithmetic cryptography. zkVMs chose generality on the basis of bringing SNARKs to the world generally, and that’s a great feature for those products, but IMO that’s shouldn’t be a factor in the long term.

I’m not strongly advocating for this, just raising it as worthy of discussion and learn any flaws that might be obvious to others :slight_smile:

I want to close by saying that any change, whether the RISC-V proposal or the one I’m suggesting, is a very-long term proposition should not IMO be blocking to unlocking scaling and usability improvements in the short term.

Hey there, I’m the original designer and current maintainer of Nervos CKB-VM. I’m not gonna directly debate which VM is better, but instead just want to sure our journey building a RISC-V based blockchain VMs in the past 7 years.

NOTE: in this post I will talk about IR(intermediate reprentation) and instruction set interchangably. IR is typically used for software virtual machines(VMs), while instruction set is more used to refer a CPU’s instruction set. However in this very post, I use IR and instruction set to refer to the same thing.

  • The choice of CKB-VM, in Nervos’ thoughts, simply came from first principle thinking: all we want is a simple, secure and fast sandbox that is also as thin as possible on commodity CPUs. A CPU instruction set turns out to be the best fit here, and RISC-V stands out amongst other choices: x64 is far too heavyweight(believe it or now, when we first tried RISC-V, there is someone building blockchain VMs using x64!), arm might or might not have a licensing issues. There are certainly other open source RISC CPU cores, but it did seem to us that RISC-V is the one that attracts the most attentions, which will mean more people working on the toolchain. To us it will be a huge advantage.
    • Personally, I could never understand the argument that ā€œRISC-V is for hardware implementations, while xxx is for software implementationsā€. If one really digs down to the IR level, the core RISC-V instructions are not so unlike instructions found in WASM, JVM, or even qemu TCG IR ( /www.qemu.org/docs/master/devel/tcg-ops.html). Yes the RISC-V CSR instructions ( /five-embeddev.com/riscv-user-isa-manual/Priv-v1.12/csr.html) might be slightly weird in a software based VM but there are 2 solutions: 1) you can simply choose not to implement them, CKB-VM does this, I know for a fact that some RISC-V VMs also do this. This choice has served us well for years; 2) other teams such as Cartesi have implemented all the CSR instructions without blockers. It is a solvable problem.
    • Now it is also a good time to share an anecdote lost in history: many consider WASM to be a choice as a blockchain VM, mainly because WASM is designed for software implementations(let’s ignore for a second if this makes any sense). Did you know that before WASM was born, there is a subset of JavaScript named asm.js that was popular for a while? So Alon Zakai first built emscripten, which translates C/C++ code to JavaScript so native code can be used in modern browsers. On the quest to make emscripten more performant, it has been discovered that if JavaScript is written in a particular style ( /kripken.github.io/mloc_emscripten_talk/#/14), the JavaScript code would map to native CPU instructions directly. And this is really the point of asm.js: having a set of pseudo-instructions that can map to native CPU instructions, but still utilizing JavaScript sandbox environment in a browser. Gradually, asm.js evolved into WASM, and somehow grows to be much bigger than asm.js’s original vision(IMHO right now WASM looks more like a clean, freshly designed JVM than asm.js these days). But let’s not forget asm.js’s original goal here: people yearn for a software IR that can map to native CPU instructions deterministically, than a JIT that does it 90% of the time. If RISC-V fulfills such goal, I would see it a perfect fit for a software VM.
  • Many here would be quite surprised that a considerable amount of EVM contracts would actually run much faster when reimplemented in a RISC-V VM. The fundamental reason, is that the majority variables do not need to be declared as 256-bit long. Even though at solidity level one does have values with shorter bits, but at EVM level, they will all be translated to 256-bit long values. I do remember reading somewhere that the original hope was that compiler technologies would catch up to solve this issue, but the unfortunate reality is that compilers never came up close, and might never come up. A similar story is v8: JavaScript shares similar design with EVM, in that JavaScript only has 64-bit double values. V8 spent a whole lot of efforts optimizing JavaScript code, lowering as many values to 32-bit integer value as possible, and the result is still not good enough: WASM was born because people want deterministic 32-bit operations that map to clean CPU instructions in the browser. Now the question is: do we want to repeat the same story in EVM? Do we finally accept that a real, close-to-CPU redesign is required, only when EVM grows to be a 2-million-lines-or-more code base like v8?
    • The problem with having only 256-bit values, does not simply end with performance. I do remember it has been raised many times that a reimplementation of any simple cryptographic algorithm would consume too much gas than one can afford. As a result, many EIPs have been proposed to add almost any cryptographic algorithm to Ethereum as precompiles. I do remember it took 4 years or so to finally have blake2b in Ethereum, many others, including secp256r1 are still in pending state. The fundamental issue here, IMHO, has to do with 256-bit values. Since any EVM operations work on 256-bit values, the gas charged for a mathematical operation(e.g., add/sub/mul) will have to consider the runtime cost of 256-bit values. However, most cryptrographics algorithms nowadays are not only implemented, but designed against 64-bit CPUs, making it quite wasteful to implement them on EVM with only 256-bit value types to spare.
    • This discussion above, really comes back to the recurring theme of designing Nervos CKB-VM: we want a simple, secure and fast instruction set that can map perfectly to native CPU instructions. It enables us to ship Nervos CKB-VM free from any precompiles up till this point(April 2025). I personally consider it my biggest achievement in the past 7 years, to help build a blockchain VM that is free from any precompiles, and as long as I’m working on Nervos CKB-VM, I will continue to fight to keep it this way. Yes I do realize that many other RISC-V VMs introduce precompiles like EVM does, but my wish is that if Nervos CKB-VM can prove that a precompile-free VM is possible, there will be others that follow in this design. And really if Ethereum embraces RISC-V, I do personally recommend that Ethereum can also design its own RISC-V VM in a precompile-free design.
    • With the precompile discussion, I do have a suggestion here: when we discuss EVM vs RISC-V, I do recommend that we make it one step further, to either compare the pros and cons of them either with precompiles included in both, or with precompiles missing in both. Let’s not compare EVM with precompiles to RISC-V without precompiles or the other ways around, to me it is not a proper comparison.
  • A real CPU instruction set is typically the final target of a compiler, leading to the common myth that a higher level IR might embrace optimizations easier than a lower level IR. However, both our reasoning and real experience throughout the years, have proved this to be false:
    • RISC-V does have employed a macro-op fusion ( /arxiv.org/abs/1607.02318) technique, where multiple instructions in a sequence can be merged into a single operation by high performance implementations for speedups. Modern compilers have widely employed this technique to emit instructions in macro-op fusion styles when suitable. One huge benefit of macro-op fusion, is that the semantics won’t change at all even if an implementation does not implement macro-op fusion, so compilers can act in an aggresive way. In Nervos CKB-VM we have employed macro-op fusions resulting in a very good performance bumps.
    • For cases where 256-bit integers are really needed, RISC-V have V extension ( /github.com/riscvarchive/riscv-v-spec) and P extention ( /github.com/riscv/riscv-p-spec) designed for this case. V extension provides support for big vector operations up to 1024 bit integers(I do have to mention that V extension support for 256-bit and bigger integers is only reserved for now, but all the encoding specs are there, you can already implement them). P extension provides SIMD support much like AVX operations. The choice between V and P will vary by cases, but the point is with either V or P extensions, you can have a RISC-V based smart contract implementing 256-bit cryptographic algorithms using V or P extensions, then translate them in your RISC-V VMs to highly optimized x64/aarch64/insert-other-CPUs-here instructions. We have experimented ( /github.com/xxuejie/rvv-prototype/tree/rvv-crypto) this path before, with the introduction of RISC-V V extension, a properly implemented RISC-V smart contract without precompiles, and a highly optimized interpreter VM, we can boost the performance of alt_bn128 operations( /eips.ethereum.org/EIPS/eip-197) to wihin 10x of EVM’s performance with precompile implementations. Note that this result was obtained with an interpreter VM using only x64’s basic instructions. Assuming a JIT or AOT RISC-V implementation, or the introduction of AVX instructions, we might have a real comparible performance to EVM using RISC-V VM without precompiles.
    • Many have a common myth that Nervos CKB-VM is a pure interpreter VM, hence it will be slow and cannot be compared to other high performant VMs. Nothing could be further from the truth. At layer 1, simplicity is a major goal of Nervos’ design. So when the highly optimized interpreter based VM provides enough performance for Nervos CKB, we are happy sticking to an interpreter based design. However, thoughout the years, we have implemented a pure Rust interpreter based VM, an assembly optimized interpreter VM(this is also what is deployed in layer 1 Nervos CKB), a native dynasm-based AOT VM ( /github.com/nervosnetwork/ckb-vm-aot), and an LLVM-based closed-to-native AOT VM. Our latest advancement in optimizing performance can be found in this post ( /xuejie.space/2022_09_08_a_journey_to_the_limit/), in which you can find that in certain cases we are getting much faster and closer-to-native performance compared to other VMs, including WASM VMs. As of today, the term Nervos CKB-VM really represents an umbrella of VMs, all implementing Nervos CKB’s RISC-V flavor(rv64imc_zba_zbb_zbc_zbs with macro-op fusions, we use flavors, not specs, because Nervos CKB-VM strictly contronts to RISC-V ISA, it’s just we have picked particular RISC-V extensions to implement). For difference scenarios, such as a layer 2 implementation, a much faster Nervos CKB-VM branch can definitely be employed for close-to-native performance, where no precompiles are needed.
  • I see discussions about EVM-on-RISCV here, I do want to mention that we have once taken the evmone ( /github.com/ethereum/evmone) implementation, ported it over to RISC-V, then used it to build an Ethereum-style layer-2 ( /github.com/godwokenrises/godwoken/tree/develop/gwos-evm) on Nervos CKB. I do want to mention that this is an earlier attempt in this space, and it definitely had its own set of quirks, but I do want to mention it as an example that at Nervos we do take this no-precompiles approves quite seriously. We have also built a similar path for WASM ( /xuejie.space/2020_03_03_introduction_to_ckb_script_programming_performant_wasm/), where compilcated WASM smart contracts can be translated to RISC-V as well.
  • Some have misbeliefs that cycle(think of it just like gas but in the CPU world everyone talks about cycles) calculations will be impossible for RISC-V. This is also false. We have implemented proper cycle calculations ( /github.com/nervosnetwork/rfcs/blob/master/rfcs/0014-vm-cycle-limits/0014-vm-cycle-limits.md) across the whole umbrella of Nervos CKB-VM implementations, including interpeter based VMs and AOT based VMs. It has never been a problem for us to keep cycle consumptions at every step, and error out when a particular smart contracts run out of cycles. In fact, even for a hardware based RISC-V core, we don’t believe cycle consumptions will be a problem. Performance counters( /www.intel.com/content/www/us/en/developer/articles/tool/performance-counter-monitor.html) have long existed in modern CPUs, even the cycles calculated for a particular blockchain are quite different from the internal cycles of a particular RISC-V CPU die, one can definitely implement such blockchain cycles as a CPU performance counter, and have a real CPU die emit those cycles matching blockchain consensus.

That is already a long post so I will stop here, but free free to reply or contact me if you are interested in more about Nervos CKB-VM. And I do want to repeat it one last time: at Nervos, we want a simple, secure and fast VM that is as thin as possible on modern CPUs, enabling us to build our smart contracts with no precompiles. To the best of our knowledge, RISC-V was the best solution 7 years ago, it is still the best solution we see in the foreseeable future. And if people call out that RISC-V is a hardware solution, so be it, we have implemented via pure software and it continues to serve our purposes perfectly, in this sense, we are happy with what we have, and will continue move forward with this path.

11 Likes