Skip to content

Commit

Permalink
[book] chapter on ecc guest (#1057)
Browse files Browse the repository at this point in the history
* book section on ecc guest

* update

* use from xy

* Apply suggestions from code review

* feat: add more explanations

---------

Co-authored-by: Jonathan Wang <[email protected]>
  • Loading branch information
luffykai and jonathanpwang authored Dec 16, 2024
1 parent 689e171 commit c9f6c33
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 10 deletions.
7 changes: 6 additions & 1 deletion book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@

# Using Extensions

- [Customizable Extensions](./custom-extensions/overview.md)
- [Overview](./custom-extensions/overview.md)
- [Keccak](./custom-extensions/keccak.md)
- [Big Integer](./custom-extensions/bigint.md)
- [Algebra](./custom-extensions/algebra.md)
- [Elliptic Curve Cryptography](./custom-extensions/ecc.md)
- [Elliptic Curve Pairing](./custom-extensions/pairing.md)

# Advanced Usage

Expand Down
87 changes: 86 additions & 1 deletion book/src/custom-extensions/ecc.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,33 @@
# OpenVM ECC

For elliptic curve cryptography, the `openvm-ecc` crate provides macros similar to those in [`openvm-algebra`](./algebra.md):
The OpenVM Elliptic Curve Cryptography Extension provides support for elliptic curve operations through the `openvm-ecc-guest` crate.

## Available traits and methods

- `Group` trait:
This represents an element of a [group](<https://en.wikipedia.org/wiki/Group_(mathematics)>) where the operation is addition. Therefore the trait includes functions for `add`, `sub`, and `double`.

- `IDENTITY` is the identity element of the group.

- `CyclicGroup` trait:
It's a group that has a generator, so it defines `GENERATOR` and `NEG_GENERATOR`.

- `WeierstrassPoint` trait:
It represents an affine point on a Weierstrass elliptic curve and it extends `Group`.

- `Coordinate` type is the type of the coordinates of the point, and it implements `IntMod`.
- `x()`, `y()` are used to get the affine coordinates
- `from_xy` is a constructor for the point, which checks if the point is either identity or on the affine curve.
- The point supports elliptic curve operations through intrinsic functions `add_ne_nonidentity` and `double_nonidentity`.
- `decompress`: Sometimes an elliptic curve point is compressed and represented by its `x` coordinate and the odd/even parity of the `y` coordinate. `decompress` is used to decompress the point back to `(x, y)`.

- `msm`: for multi-scalar multiplication.

- `ecdsa`: for doing ECDSA signature verification and public key recovery from signature.

## Macros

For elliptic curve cryptography, the `openvm-ecc-guest` crate provides macros similar to those in [`openvm-algebra-guest`](./algebra.md):

1. **Declare**: Use `sw_declare!` to define elliptic curves over the previously declared moduli. For example:

Expand All @@ -12,6 +39,7 @@ sw_declare! {
```

Each declared curve must specify the `mod_type` (implementing `IntMod`) and a constant `b` for the Weierstrass curve equation $y^2 = x^3 + b$.
This creates `Bls12_381G1Affine` and `Bn254G1Affine` structs which implement the `Group` and `WeierstrassPoint` traits. The underlying memory layout of the structs uses the memory layout of the `Bls12_381Fp` and `Bn254Fp` structs, respectively.

2. **Init**: Called once, it enumerates these curves and allows the compiler to produce optimized instructions:

Expand All @@ -28,3 +56,60 @@ sw_init! {
- `sw_declare!`: Declares elliptic curve structures.
- `sw_init!`: Initializes them once, linking them to the underlying moduli.
- `setup_sw_<i>()`/`setup_all_curves()`: Secures runtime correctness.

To use elliptic curve operations on a struct defined with `sw_declare!`, it is expected that the struct for the curve's coordinate field was defined using `moduli_declare!`. In particular, the coordinate field needs to be initialized and set up as described in the [algebra extension](./algebra.md) chapter.

For the basic operations provided by the `WeierstrassPoint` trait, the scalar field is not needed. For the ECDSA functions in the `ecdsa` module, the scalar field must also be declared, initialized, and set up.

## Example program

See a working example [here](https://github.com/openvm-org/openvm/blob/main/crates/toolchain/tests/programs/examples/ec.rs).

To use the ECC extension, add the following dependencies to `Cargo.toml`:

```toml
openvm-algebra-guest = { git = "https://github.com/openvm-org/openvm.git" }
openvm-ecc-guest = { git = "https://github.com/openvm-org/openvm.git", features = ["k256"] }
```

One can define their own ECC structs but we will use the Secp256k1 struct from `openvm-ecc-guest` and thus the `k256` feature should be enabled.

```rust
use openvm_ecc_guest::{
k256::{Secp256k1Coord, Secp256k1Point, Secp256k1Scalar},
Group, weierstrass::WeierstrassPoint,
};

openvm_algebra_guest::moduli_setup::moduli_init! {
"0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F",
"0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141"
}

openvm_ecc_guest::sw_setup::sw_init! {
Secp256k1Coord,
}
```

We `moduli_init!` both the coordinate and scalar field because they were declared in the `k256` module, although we will not be using the scalar field below.

With the above we can start doing elliptic curve operations like adding points:

```rust
pub fn main() {
setup_all_moduli();
setup_all_curves();
let x1 = Secp256k1Coord::from_u32(1);
let y1 = Secp256k1Coord::from_le_bytes(&hex!(
"EEA7767E580D75BC6FDD7F58D2A84C2614FB22586068DB63B346C6E60AF21842"
));
let p1 = Secp256k1Point::from_xy_nonidentity(x1, y1).unwrap();

let x2 = Secp256k1Coord::from_u32(2);
let y2 = Secp256k1Coord::from_le_bytes(&hex!(
"D1A847A8F879E0AEE32544DA5BA0B3BD1703A1F52867A5601FF6454DD8180499"
));
let p2 = Secp256k1Point::from_xy_nonidentity(x2, y2).unwrap();

let p3 = &p1 + &p2;
}
```
20 changes: 12 additions & 8 deletions book/src/custom-extensions/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,22 @@

You can seamlessly integrate certain performance-optimized extensions maintained by the OpenVM team to enhance your arithmetic operations and cryptographic computations.

Certain arithmetic operations, particularly modular arithmetic, can be optimized significantly when the modulus is known at compile time. This approach requires a framework to inform the compiler about all the moduli and associated arithmetic structures we intend to use. To achieve this, three steps are involved:
In this chapter, we will explain how to use the following existing extensions:

- [`openvm-keccak-guest`](./keccak.md) - Keccak256 hash function.
- [`openvm-bigint-guest`](./bigint.md) - Big integer arithmetic for 256-bit signed and unsigned integers.
- [`openvm-algebra-guest`](./algebra.md) - Modular arithmetic and complex field extensions.
- [`openvm-ecc-guest`](./ecc.md) - Elliptic curve cryptography.
- [`openvm-pairing-guest`](./pairing.md) - Elliptic curve optimal Ate pairings.

Some extensions such as `openvm-keccak-guest` and `openvm-bigint-guest` can be enabled without specifying any additional configuration.

On the other hand certain arithmetic operations, particularly modular arithmetic, can be optimized significantly when the modulus is known at compile time. This approach requires a framework to inform the compiler about all the moduli and associated arithmetic structures we intend to use. To achieve this, three steps are involved:

1. **Declare**: Introduce a modular arithmetic or related structure, along with its modulus and functionality. This can be done in any library or binary file.
2. **Init**: Performed exactly once in the final binary. It aggregates all previously declared structures, assigns them stable indices, and sets up linkage so that they can be referenced in generated code.
3. **Setup**: A one-time runtime procedure for security. This ensures that the compiled code matches the virtual machine’s expectations and that each instruction set is tied to the correct modulus or extension.

These steps ensure both performance and security: performance because the modulus is known at compile time, and security because runtime checks confirm that the correct structures have been initialized.

The list of existing extensions:

- [`openvm-algebra`](./algebra.md)
- [`openvm-bigint`](./bigint.md)
- [`openvm-keccak`](./keccak.md)
- [`openvm-pairing`](./pairing.md)
- [`openvm-ecc`](./ecc.md)
Our design for the configuration procedure above was inspired by the [EVMMAX proposal](https://github.com/jwasinger/EIPs/blob/evmmax-2/EIPS/eip-6601.md).

0 comments on commit c9f6c33

Please sign in to comment.