Skip to content

Commit

Permalink
[book] Write the manual on how to create a new extension (#1060)
Browse files Browse the repository at this point in the history
* Write the manual

* Update book/src/new-extension/howto.md

* Update book/src/new-extension/howto.md

Co-authored-by: Jonathan Wang <[email protected]>

* Some comments

* Other comments

* Rename

---------

Co-authored-by: Jonathan Wang <[email protected]>
  • Loading branch information
Golovanov399 and jonathanpwang authored Dec 16, 2024
1 parent a823773 commit 6b3e68a
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 2 deletions.
41 changes: 41 additions & 0 deletions book/src/advanced-usage/new-extension.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Creating a New Extension

Extensions in OpenVM let you introduce additional functionality without disrupting the existing system. Consider, for example, an extension that provides two new operations on `u32` values: one that squares a number, and another that multiplies it by three. With such an extension:

1. You define functions like `square(x: u32) -> u32` and `mul3(x: u32) -> u32` for use in guest code.
2. When the compiler encounters these functions, it generates corresponding custom [RISC-V instructions](https://github.com/openvm-org/openvm/blob/main/docs/specs/RISCV.md).
3. During the transpilation phase, these custom instructions are translated into OpenVM instructions.
4. At runtime, the OpenVM program sends these new instructions to a specialized [chip](https://github.com/openvm-org/openvm/blob/main/docs/specs/circuit.md) that computes the results and ensures their correctness.

This modular architecture means the extension cleanly adds new capabilities while leaving the rest of OpenVM untouched. The entire system, including the extension’s operations, can still be proven correct.

Conceptually, a new extension consists of three parts:
- **Guest**: High-level Rust code that defines and uses the new operations.
- **Transpiler**: Logic that converts custom RISC-V instructions into corresponding OpenVM instructions.
- **Circuit**: The special chips that enforce correctness of instruction execution through polynomial constraints.

## Guest

In the guest component, your goal is to produce the instructions that represent the new operations. When you want to perform an operation (for example, “calculate _this_ new function of _these_ arguments and write the result _here_”), you generate a custom instruction. You can use the helper macros `custom_insn_r!` and `custom_insn_i!` from `openvm_platform` to ensure these instructions follow the [RISC-V specification](https://riscv.org/specifications/ratified/). For more details, see the RISC-V [contributor documentation](https://github.com/openvm-org/openvm/blob/main/docs/specs/RISCV.md).

## Transpiler

The transpiler maps the newly introduced RISC-V instructions to their OpenVM counterparts. To achieve this, implement a struct that provides the `TranspilerExtension` trait, which includes:

```rust
fn process_custom(&self, instruction_stream: &[u32]) -> Option<(Instruction<F>, usize)>;
```

This function checks if the given instruction stream starts with one of your custom instructions. If so, it returns the corresponding OpenVM instruction and how many 32-bit words were consumed. If not, it returns `None`.

Note that almost always the valid instruction consists of a single 32-bit RISC-V word (so whenever `Some(_, sz)` is returned, `sz` is 1), but in general this may not be the case.

## Circuit

The circuit component is where the extension’s logic is enforced in a zero-knowledge proof context. Here, you create a chip that:

- Implements the computing logic, so that the output always corresponds to the correct result of the new operation. The chip has access to the memory shared with the other chips from the VM via [our special architecture](https://github.com/openvm-org/openvm/blob/main/docs/specs/ISA.md).
- Properly constrains all the inputs, outputs and intermediate variables using polynomial equations in such a way that there is no way to fill these variables with values that correspond to an incorrect output while fitting the constraints.


For more technical details on writing circuits and constraints, consult the OpenVM [contributor documentation](https://github.com/openvm-org/openvm/blob/main/docs/specs/README.md), which provides specifications and guidelines for integrating your extension into the OpenVM framework.
4 changes: 2 additions & 2 deletions book/src/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ OpenVM is an open-source zero-knowledge virtual machine (zkVM) framework focused

The following chapters will guide you through:

- [Getting started](./getting-started/install.md)
- [Getting started](./getting-started/install.md).
- [Writing applications](./writing-apps/overview.md) in Rust targeting OpenVM and generating proofs.
- [Using existing extensions](./custom-extensions/overview.md) to optimize your Rust programs.
- How to add custom VM extensions
- [How to add custom VM extensions](./advanced-usage/new-extension.md).

0 comments on commit 6b3e68a

Please sign in to comment.