From c319f32a1e4a3471554006523c90856a943b366e Mon Sep 17 00:00:00 2001 From: Aaryamann Challani <43716372+rymnc@users.noreply.github.com> Date: Tue, 7 Mar 2023 18:15:06 +0530 Subject: [PATCH] feat(rln): package rln w/ resources into a static lib (#118) * feat(rln): package resources into lib * fix(rln): use Path * fix(rln): fmt * fix(rln): trailing slash --- .github/workflows/nightly-release.yml | 43 ++++++++++++-------- rln/Cargo.toml | 6 ++- rln/src/circuit.rs | 56 +++++++++++++++------------ rln/src/public.rs | 2 +- 4 files changed, 64 insertions(+), 43 deletions(-) diff --git a/.github/workflows/nightly-release.yml b/.github/workflows/nightly-release.yml index 9c8538a..d663c6d 100644 --- a/.github/workflows/nightly-release.yml +++ b/.github/workflows/nightly-release.yml @@ -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: @@ -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 @@ -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: @@ -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 }} @@ -136,6 +149,4 @@ jobs: with: failOnError: false name: | - linux-archive - macos-archive - browser-rln-wasm-archive + *-archive diff --git a/rln/Cargo.toml b/rln/Cargo.toml index 9036832..6d119e1 100644 --- a/rln/Cargo.toml +++ b/rln/Cargo.toml @@ -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 @@ -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" diff --git a/rln/src/circuit.rs b/rln/src/circuit.rs index b11b8f3..944241d 100644 --- a/rln/src/circuit.rs +++ b/rln/src/circuit.rs @@ -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; @@ -22,11 +21,12 @@ 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 @@ -34,11 +34,11 @@ const WASM_FILENAME: &str = "rln.wasm"; // 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 @@ -63,13 +63,14 @@ pub fn zkey_from_raw(zkey_data: &Vec) -> Result<(ProvingKey, Constrai } // Loads the proving key +#[cfg(not(target_arch = "wasm32"))] pub fn zkey_from_folder( resources_folder: &str, ) -> Result<(ProvingKey, ConstraintMatrices)> { - 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!")) @@ -93,15 +94,18 @@ pub fn vk_from_raw(vk_data: &Vec, zkey_data: &Vec) -> Result Result> { - 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; - - 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) @@ -128,9 +132,14 @@ pub fn circom_from_raw(wasm_buffer: Vec) -> Result<&'static Mutex Result<&'static Mutex> { // 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 @@ -231,10 +240,8 @@ fn to_verifying_key(json: serde_json::Value) -> Result> { } // Computes the verification key from its JSON serialization -fn vk_from_json(vk_path: &str) -> Result> { - let json = std::fs::read_to_string(vk_path)?; - let json: Value = serde_json::from_str(&json)?; - +fn vk_from_json(vk: &str) -> Result> { + let json: Value = serde_json::from_str(vk)?; to_verifying_key(json) } @@ -247,6 +254,7 @@ fn vk_from_vector(vk: &[u8]) -> Result> { } // 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, diff --git a/rln/src/public.rs b/rln/src/public.rs index 4bdf702..8f8c968 100644 --- a/rln/src/public.rs +++ b/rln/src/public.rs @@ -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);