Procedural macros for use in guest program to generate short Weierstrass elliptic curve struct with custom intrinsics for compile-time modulus.
The workflow of this macro is very similar to the openvm-algebra-moduli-macros
crate. We recommend reading it first.
// ...
moduli_declare! {
Secp256k1Coord { modulus = "0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F" },
Secp256k1Scalar { modulus = "0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141" },
}
const CURVE_B: Secp256k1Coord = Secp256k1Coord::from_const_bytes(seven_le());
sw_declare! {
Secp256k1Point { mod_type = Secp256k1Coord, b = CURVE_B },
}
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,
}
pub fn main() {
setup_all_moduli();
setup_all_curves();
// ...
}
Again, the principle is the same as in the openvm-algebra-moduli-macros
crate. Here we emphasize the core differences.
The crate provides two macros: sw_declare!
and sw_init!
. The signatures are:
-
sw_declare!
receives comma-separated list of moduli classes descriptions. Each description looks likeSwStruct { mod_type = ModulusName, a = a_expr, b = b_expr }
. HereModulusName
is the name of any struct that implementstrait IntMod
-- in particular, the ones created bymoduli_declare!
do. Parametersa
andb
correspond to the coefficients of the equation defining the curve. They must be compile-time constants. The parametera
may be omitted, in which case it defaults to0
(or, more specifically, to<ModulusName as IntMod>::ZERO
). The parameterb
is required. -
sw_init!
receives comma-separated list of struct names. The struct name must exactly match the name insw_declare!
-- type defs are not allowed (see point 5 below).
What happens under the hood:
sw_declare!
macro creates a struct with two fieldx
andy
of typemod_type
. This struct denotes a point on the corresponding elliptic curve. In the example it would be
struct Secp256k1Point {
x: Secp256k1Coord,
y: Secp256k1Coord,
}
Similar to moduli_declare!
, this macro also creates extern functions for arithmetic operations -- but in this case they are named after the sw type, not after any hexadecimal (since the macro has no way to obtain it from the name of the modulus type anyway):
extern "C" {
fn sw_add_extern_func_Secp256k1Point(rd: usize, rs1: usize, rs2: usize);
fn sw_double_extern_func_Secp256k1Point(rd: usize, rs1: usize);
fn hint_decompress_extern_func_Secp256k1Point(rs1: usize, rs2: usize);
}
- Again,
sw_init!
macro implements these extern functions and defines the setup functions for the sw struct.
#[cfg(target_os = "zkvm")]
mod openvm_intrinsics_ffi_2 {
use :openvm_ecc_guest::{OPCODE, SW_FUNCT3, SwBaseFunct7};
#[no_mangle]
extern "C" fn sw_add_extern_func_Secp256k1Point(rd: usize, rs1: usize, rs2: usize) {
// ...
}
// other externs
}
#[allow(non_snake_case)]
pub fn setup_sw_Secp256k1Point() {
#[cfg(target_os = "zkvm")]
{
// ...
}
}
pub fn setup_all_curves() {
setup_sw_Secp256k1Point();
// other setups
}
-
Again, the
setup
function for every used curve must be called before any other instructions for that curve. If all curves are used, one can callsetup_all_curves()
to setup all of them. -
The order of the items in
sw_init!
must match the order of the moduli in the chip configuration -- more specifically, in the modular extension parameters (the order ofCurveConfig
s inWeierstrassExtension::supported_curves
, which is usually defined with the wholeapp_vm_config
in theopenvm.toml
file). -
Note that, due to the nature of function names, the name of the struct used in
sw_init!
must be the same as insw_declare!
. To illustrate, the following code will fail to compile:
// ...
sw_declare! {
Secp256k1Point { mod_type = Secp256k1Coord, b = CURVE_B },
}
pub type Sw = Secp256k1Point;
sw_init! {
Sw,
}
The reason is that, for example, the function sw_add_extern_func_Secp256k1Point
remains unimplemented, but we implement sw_add_extern_func_Sw
.