Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

K256

The K256 guest library uses openvm-ecc-guest to provide elliptic curve operations over the Secp256k1 curve. It is intended as a patch for the k256 rust crate and can be swapped in for accelerated signature verification usage. Note that signing from a private key is not supported.

Example program

See a working example here.

To use the K256 guest library, add the following dependencies to Cargo.toml:

openvm-algebra-guest = { git = "https://github.com/openvm-org/openvm.git" }
openvm-ecc-guest = { git = "https://github.com/openvm-org/openvm.git" }
openvm-k256 = { git = "https://github.com/openvm-org/openvm.git", package = "k256" }

The guest library provides a Secp256k1Coord, which represents a field element on the coordinate field of Secp256k1, and a Secp256k1Point, which represents an Secp256k1 elliptic curve point.

The K256 guest library handles the "Declare" phase described in Optimizing Modular Arithmetic. The consuming guest program is responsible for running the "Init" phase via openvm::init!().

use hex_literal::hex;
use openvm_algebra_guest::IntMod;
use openvm_ecc_guest::weierstrass::WeierstrassPoint;
use openvm_k256::{Secp256k1Coord, Secp256k1Point};
openvm::init!();
/* The init! macro will expand to the following
openvm_algebra_guest::moduli_macros::moduli_init! {
    "0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F",
    "0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141"
}

openvm_ecc_guest::sw_macros::sw_init! {
    Secp256k1Point,
}
*/

moduli_init! is called for 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:

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

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

    #[allow(clippy::op_ref)]
    let _p3 = &p1 + &p2;
}

Config parameters

For the guest program to build successfully, all used moduli and curves must be declared in the .toml config file in the following format:

[app_vm_config.modular]
supported_moduli = ["115792089237316195423570985008687907853269984665640564039457584007908834671663", "115792089237316195423570985008687907852837564279074904382605163141518161494337"]

[[app_vm_config.ecc.supported_curves]]
struct_name = "Secp256k1Point"
modulus = "115792089237316195423570985008687907853269984665640564039457584007908834671663"
scalar = "115792089237316195423570985008687907852837564279074904382605163141518161494337"
a = "0"
b = "7"

The supported_moduli parameter is a list of moduli that the guest program will use. As mentioned in the algebra extension chapter, the order of moduli in [app_vm_config.modular] must match the order in the moduli_init! macro.

The ecc.supported_curves parameter is a list of supported curves that the guest program will use. They must be provided in decimal format in the .toml file. For multiple curves create multiple [[app_vm_config.ecc.supported_curves]] sections. The order of curves in [[app_vm_config.ecc.supported_curves]] must match the order in the sw_init! macro. Also, the struct_name field must be the name of the elliptic curve struct created by sw_declare!. In this example, the Secp256k1Point struct is created in openvm_ecc_guest::k256.