Skip to content

Commit

Permalink
feat(rln): package rln w/ resources into a static lib (#118)
Browse files Browse the repository at this point in the history
* feat(rln): package resources into lib

* fix(rln): use Path

* fix(rln): fmt

* fix(rln): trailing slash
  • Loading branch information
rymnc committed Mar 7, 2023
1 parent bf2aa16 commit c319f32
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 43 deletions.
43 changes: 27 additions & 16 deletions .github/workflows/nightly-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ on:

jobs:
linux:
strategy:
matrix:
target:
- x86_64-unknown-linux-gnu
# TODO: enable after https://github.com/rust-lang/cargo/issues/4133 is resolved
# - aarch64-unknown-linux-gnu
# - i686-unknown-linux-gnu
name: Linux build
runs-on: ubuntu-latest
steps:
Expand All @@ -17,25 +24,32 @@ jobs:
profile: minimal
toolchain: stable
override: true
target: ${{ matrix.target }}
- name: Update git submodules
run: git submodule update --init --recursive
- name: cargo build
run: |
cargo build --release --workspace --exclude rln-wasm
cargo build --release --target ${{ matrix.target }} --workspace --exclude rln-wasm
mkdir release
cp target/release/librln* release/
tar -czvf linux-rln.tar.gz release/
cp target/${{ matrix.target }}/release/librln* release/
tar -czvf ${{ matrix.target }}-rln.tar.gz release/
- name: Upload archive artifact
uses: actions/upload-artifact@v2
with:
name: linux-archive
path: linux-rln.tar.gz
name: ${{ matrix.target }}-archive
path: ${{ matrix.target }}-rln.tar.gz
retention-days: 2

macos:
name: MacOS build
runs-on: macos-latest
strategy:
matrix:
target:
- x86_64-apple-darwin
# TODO: enable after https://github.com/rust-lang/cargo/issues/4133 is resolved
# - aarch64-apple-darwin
steps:
- name: Checkout sources
uses: actions/checkout@v2
Expand All @@ -47,20 +61,21 @@ jobs:
profile: minimal
toolchain: stable
override: true
target: ${{ matrix.target }}
- name: Update git submodules
run: git submodule update --init --recursive
- name: cargo build
run: |
cargo build --release --workspace --exclude rln-wasm
cargo build --release --target ${{ matrix.target }} --workspace --exclude rln-wasm
mkdir release
cp target/release/librln* release/
tar -czvf macos-rln.tar.gz release/
cp target/${{ matrix.target }}/release/librln* release/
tar -czvf ${{ matrix.target }}-rln.tar.gz release/
- name: Upload archive artifact
uses: actions/upload-artifact@v2
with:
name: macos-archive
path: macos-rln.tar.gz
name: ${{ matrix.target }}-archive
path: ${{ matrix.target }}-rln.tar.gz
retention-days: 2

browser-rln-wasm:
Expand Down Expand Up @@ -125,9 +140,7 @@ jobs:
--title 'Nightly build ("master" branch)' \
--generate-notes \
--notes-start-tag $start_tag \
linux-archive/linux-rln.tar.gz \
macos-archive/macos-rln.tar.gz \
browser-rln-wasm-archive/browser-rln-wasm.tar.gz
*-archive/*.tar.gz \
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Expand All @@ -136,6 +149,4 @@ jobs:
with:
failOnError: false
name: |
linux-archive
macos-archive
browser-rln-wasm-archive
*-archive
6 changes: 4 additions & 2 deletions rln/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ edition = "2021"
license = "MIT OR Apache-2.0"

[lib]
crate-type = ["cdylib", "rlib", "staticlib"]
crate-type = ["rlib", "staticlib"]

# This flag disable cargo doctests, i.e. testing example code-snippets in documentation
doctest = false
Expand Down Expand Up @@ -41,7 +41,9 @@ utils = { path = "../utils/", default-features = false }
pmtree = { git = "https://github.com/Rate-Limiting-Nullifier/pmtree", rev = "f6d1a1fecad72cd39e6808e78085091d541dc882", optional = true}

# serialization
serde_json = "=1.0.93"
serde_json = "1.0.48"

include_dir = "=0.7.3"

[dev-dependencies]
sled = "=0.34.7"
Expand Down
56 changes: 32 additions & 24 deletions rln/src/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use cfg_if::cfg_if;
use color_eyre::{Report, Result};
use num_bigint::BigUint;
use serde_json::Value;
use std::fs::File;
use std::io::Cursor;
use std::path::Path;
use std::str::FromStr;
Expand All @@ -22,23 +21,24 @@ cfg_if! {
use once_cell::sync::OnceCell;
use std::sync::Mutex;
use wasmer::{Module, Store};
use include_dir::{include_dir, Dir};
}
}

const ZKEY_FILENAME: &str = "rln_final.zkey";
const VK_FILENAME: &str = "verifying_key.json";
const VK_FILENAME: &str = "verification_key.json";
const WASM_FILENAME: &str = "rln.wasm";

// These parameters are used for tests
// Note that the circuit and keys in TEST_RESOURCES_FOLDER are compiled for Merkle trees of height 15, 19 and 20
// Changing these parameters to other values than these defaults will cause zkSNARK proof verification to fail
pub const TEST_PARAMETERS_INDEX: usize = 2;
pub const TEST_TREE_HEIGHT: usize = [15, 19, 20][TEST_PARAMETERS_INDEX];
pub const TEST_RESOURCES_FOLDER: &str = [
"./resources/tree_height_15/",
"./resources/tree_height_19/",
"./resources/tree_height_20/",
][TEST_PARAMETERS_INDEX];
pub const TEST_RESOURCES_FOLDER: &str =
["tree_height_15", "tree_height_19", "tree_height_20"][TEST_PARAMETERS_INDEX];

#[cfg(not(target_arch = "wasm32"))]
static RESOURCES_DIR: Dir<'_> = include_dir!("$CARGO_MANIFEST_DIR/resources");

// The following types define the pairing friendly elliptic curve, the underlying finite fields and groups default to this module
// Note that proofs are serialized assuming Fr to be 4x8 = 32 bytes in size. Hence, changing to a curve with different encoding will make proof verification to fail
Expand All @@ -63,13 +63,14 @@ pub fn zkey_from_raw(zkey_data: &Vec<u8>) -> Result<(ProvingKey<Curve>, Constrai
}

// Loads the proving key
#[cfg(not(target_arch = "wasm32"))]
pub fn zkey_from_folder(
resources_folder: &str,
) -> Result<(ProvingKey<Curve>, ConstraintMatrices<Fr>)> {
let zkey_path = format!("{resources_folder}{ZKEY_FILENAME}");
if Path::new(&zkey_path).exists() {
let mut file = File::open(&zkey_path)?;
let proving_key_and_matrices = read_zkey(&mut file)?;
let zkey = RESOURCES_DIR.get_file(Path::new(resources_folder).join(ZKEY_FILENAME));
if let Some(zkey) = zkey {
let mut c = Cursor::new(zkey.contents());
let proving_key_and_matrices = read_zkey(&mut c)?;
Ok(proving_key_and_matrices)
} else {
Err(Report::msg("No proving key found!"))
Expand All @@ -93,15 +94,18 @@ pub fn vk_from_raw(vk_data: &Vec<u8>, zkey_data: &Vec<u8>) -> Result<VerifyingKe
}

// Loads the verification key
#[cfg(not(target_arch = "wasm32"))]
pub fn vk_from_folder(resources_folder: &str) -> Result<VerifyingKey<Curve>> {
let vk_path = format!("{resources_folder}{VK_FILENAME}");
let zkey_path = format!("{resources_folder}{ZKEY_FILENAME}");
let vk = RESOURCES_DIR.get_file(Path::new(resources_folder).join(VK_FILENAME));
let zkey = RESOURCES_DIR.get_file(Path::new(resources_folder).join(ZKEY_FILENAME));

let verifying_key: VerifyingKey<Curve>;

if Path::new(&vk_path).exists() {
vk_from_json(&vk_path)
} else if Path::new(&zkey_path).exists() {
if let Some(vk) = vk {
verifying_key = vk_from_json(vk.contents_utf8().ok_or(Report::msg(
"Could not read verification key from JSON file!",
))?)?;
Ok(verifying_key)
} else if let Some(_zkey) = zkey {
let (proving_key, _matrices) = zkey_from_folder(resources_folder)?;
verifying_key = proving_key.vk;
Ok(verifying_key)
Expand All @@ -128,9 +132,14 @@ pub fn circom_from_raw(wasm_buffer: Vec<u8>) -> Result<&'static Mutex<WitnessCal
#[cfg(not(target_arch = "wasm32"))]
pub fn circom_from_folder(resources_folder: &str) -> Result<&'static Mutex<WitnessCalculator>> {
// We read the wasm file
let wasm_path = format!("{resources_folder}{WASM_FILENAME}");
let wasm_buffer = std::fs::read(wasm_path)?;
circom_from_raw(wasm_buffer)
let wasm = RESOURCES_DIR.get_file(Path::new(resources_folder).join(WASM_FILENAME));

if let Some(wasm) = wasm {
let wasm_buffer = wasm.contents();
circom_from_raw(wasm_buffer.to_vec())
} else {
Err(Report::msg("No wasm file found!"))
}
}

// The following function implementations are taken/adapted from https://github.com/gakonst/ark-circom/blob/1732e15d6313fe176b0b1abb858ac9e095d0dbd7/src/zkey.rs
Expand Down Expand Up @@ -231,10 +240,8 @@ fn to_verifying_key(json: serde_json::Value) -> Result<VerifyingKey<Curve>> {
}

// Computes the verification key from its JSON serialization
fn vk_from_json(vk_path: &str) -> Result<VerifyingKey<Curve>> {
let json = std::fs::read_to_string(vk_path)?;
let json: Value = serde_json::from_str(&json)?;

fn vk_from_json(vk: &str) -> Result<VerifyingKey<Curve>> {
let json: Value = serde_json::from_str(vk)?;
to_verifying_key(json)
}

Expand All @@ -247,6 +254,7 @@ fn vk_from_vector(vk: &[u8]) -> Result<VerifyingKey<Curve>> {
}

// Checks verification key to be correct with respect to proving key
#[cfg(not(target_arch = "wasm32"))]
pub fn check_vk_from_zkey(
resources_folder: &str,
verifying_key: VerifyingKey<Curve>,
Expand Down
2 changes: 1 addition & 1 deletion rln/src/public.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl RLN<'_> {
/// use std::io::Cursor;
///
/// let tree_height = 20;
/// let resources = Cursor::new("./resources/tree_height_20/");
/// let resources = Cursor::new("tree_height_20");
///
/// // We create a new RLN instance
/// let mut rln = RLN::new(tree_height, resources);
Expand Down

0 comments on commit c319f32

Please sign in to comment.