From 532215cebb9610835fffb44603a565f66fa299d2 Mon Sep 17 00:00:00 2001 From: Nalin Date: Fri, 28 Jul 2023 19:11:36 +0100 Subject: [PATCH] traitify groups and support bn254/grumpkin (#33) * traitify groups and support bn254/grumpkin * bump version --- .github/workflows/test.yml | 18 +- Cargo.toml | 6 +- README.md | 50 +- browser-test/Cargo.toml | 3 +- browser-test/env.sh | 5 + browser-test/rust-toolchain | 2 +- browser-test/src/wasm.rs | 63 +- examples/bitcoin.rs | 26 +- examples/bitcoin/benchmark.csv | 10 +- examples/bitcoin/circom/bitcoin.circom | 4 +- .../bitcoin/circom/bitcoin_benchmark.circom | 6 +- examples/toy/bn254/toy.r1cs | Bin 0 -> 272 bytes examples/toy/{ => bn254}/toy.sym | 0 examples/toy/{ => bn254}/toy_cpp/Makefile | 0 examples/toy/{ => bn254}/toy_cpp/calcwit.cpp | 0 examples/toy/{ => bn254}/toy_cpp/calcwit.hpp | 6 +- examples/toy/bn254/toy_cpp/calcwit.o | Bin 0 -> 16120 bytes examples/toy/{ => bn254}/toy_cpp/circom.hpp | 12 +- examples/toy/bn254/toy_cpp/fr.asm | 8794 +++++++++++++++++ examples/toy/{ => bn254}/toy_cpp/fr.cpp | 54 +- examples/toy/bn254/toy_cpp/fr.hpp | 164 + examples/toy/bn254/toy_cpp/fr.o | Bin 0 -> 14304 bytes examples/toy/bn254/toy_cpp/fr_asm.o | Bin 0 -> 36778 bytes examples/toy/{ => bn254}/toy_cpp/main.cpp | 0 examples/toy/bn254/toy_cpp/main.o | Bin 0 -> 170992 bytes examples/toy/bn254/toy_cpp/toy | Bin 0 -> 237160 bytes examples/toy/{ => bn254}/toy_cpp/toy.cpp | 18 +- examples/toy/bn254/toy_cpp/toy.dat | Bin 0 -> 6264 bytes examples/toy/bn254/toy_cpp/toy.o | Bin 0 -> 4848 bytes .../{ => bn254}/toy_js/generate_witness.js | 0 examples/toy/bn254/toy_js/toy.wasm | Bin 0 -> 34401 bytes .../{ => bn254}/toy_js/witness_calculator.js | 0 examples/toy/compile.sh | 8 +- examples/toy/{ => pasta}/toy.r1cs | Bin examples/toy/pasta/toy.sym | 5 + examples/toy/pasta/toy_cpp/Makefile | 22 + examples/toy/pasta/toy_cpp/calcwit.cpp | 126 + examples/toy/pasta/toy_cpp/calcwit.hpp | 69 + examples/toy/pasta/toy_cpp/calcwit.o | Bin 0 -> 16120 bytes examples/toy/pasta/toy_cpp/circom.hpp | 85 + examples/toy/{ => pasta}/toy_cpp/fr.asm | 13 +- examples/toy/pasta/toy_cpp/fr.cpp | 321 + examples/toy/{ => pasta}/toy_cpp/fr.hpp | 35 +- examples/toy/pasta/toy_cpp/fr.o | Bin 0 -> 14304 bytes examples/toy/{ => pasta}/toy_cpp/fr_asm.o | Bin 36786 -> 36778 bytes examples/toy/pasta/toy_cpp/main.cpp | 288 + examples/toy/pasta/toy_cpp/main.o | Bin 0 -> 170992 bytes examples/toy/pasta/toy_cpp/toy | Bin 0 -> 237160 bytes examples/toy/pasta/toy_cpp/toy.cpp | 107 + examples/toy/{ => pasta}/toy_cpp/toy.dat | Bin examples/toy/pasta/toy_cpp/toy.o | Bin 0 -> 4848 bytes examples/toy/pasta/toy_js/generate_witness.js | 20 + examples/toy/{ => pasta}/toy_js/toy.wasm | Bin 34394 -> 34402 bytes .../toy/pasta/toy_js/witness_calculator.js | 337 + examples/toy/toy_cpp/calcwit.o | Bin 14808 -> 0 bytes examples/toy/toy_cpp/fr.o | Bin 12392 -> 0 bytes examples/toy/toy_cpp/main.o | Bin 167840 -> 0 bytes examples/toy/toy_cpp/toy | Bin 230120 -> 0 bytes examples/toy/toy_cpp/toy.o | Bin 4704 -> 0 bytes examples/{toy_wasm.rs => toy_bn254.rs} | 63 +- examples/{toy.rs => toy_pasta.rs} | 61 +- src/circom/file.rs | 27 +- src/circom/reader.rs | 28 +- src/circom/wasm.rs | 10 +- src/lib.rs | 307 +- 65 files changed, 10860 insertions(+), 313 deletions(-) create mode 100644 browser-test/env.sh create mode 100644 examples/toy/bn254/toy.r1cs rename examples/toy/{ => bn254}/toy.sym (100%) rename examples/toy/{ => bn254}/toy_cpp/Makefile (100%) rename examples/toy/{ => bn254}/toy_cpp/calcwit.cpp (100%) rename examples/toy/{ => bn254}/toy_cpp/calcwit.hpp (95%) create mode 100644 examples/toy/bn254/toy_cpp/calcwit.o rename examples/toy/{ => bn254}/toy_cpp/circom.hpp (85%) create mode 100644 examples/toy/bn254/toy_cpp/fr.asm rename examples/toy/{ => bn254}/toy_cpp/fr.cpp (84%) create mode 100644 examples/toy/bn254/toy_cpp/fr.hpp create mode 100644 examples/toy/bn254/toy_cpp/fr.o create mode 100644 examples/toy/bn254/toy_cpp/fr_asm.o rename examples/toy/{ => bn254}/toy_cpp/main.cpp (100%) create mode 100644 examples/toy/bn254/toy_cpp/main.o create mode 100755 examples/toy/bn254/toy_cpp/toy rename examples/toy/{ => bn254}/toy_cpp/toy.cpp (84%) create mode 100644 examples/toy/bn254/toy_cpp/toy.dat create mode 100644 examples/toy/bn254/toy_cpp/toy.o rename examples/toy/{ => bn254}/toy_js/generate_witness.js (100%) create mode 100644 examples/toy/bn254/toy_js/toy.wasm rename examples/toy/{ => bn254}/toy_js/witness_calculator.js (100%) rename examples/toy/{ => pasta}/toy.r1cs (100%) create mode 100644 examples/toy/pasta/toy.sym create mode 100644 examples/toy/pasta/toy_cpp/Makefile create mode 100644 examples/toy/pasta/toy_cpp/calcwit.cpp create mode 100644 examples/toy/pasta/toy_cpp/calcwit.hpp create mode 100644 examples/toy/pasta/toy_cpp/calcwit.o create mode 100644 examples/toy/pasta/toy_cpp/circom.hpp rename examples/toy/{ => pasta}/toy_cpp/fr.asm (99%) create mode 100644 examples/toy/pasta/toy_cpp/fr.cpp rename examples/toy/{ => pasta}/toy_cpp/fr.hpp (77%) create mode 100644 examples/toy/pasta/toy_cpp/fr.o rename examples/toy/{ => pasta}/toy_cpp/fr_asm.o (56%) create mode 100644 examples/toy/pasta/toy_cpp/main.cpp create mode 100644 examples/toy/pasta/toy_cpp/main.o create mode 100755 examples/toy/pasta/toy_cpp/toy create mode 100644 examples/toy/pasta/toy_cpp/toy.cpp rename examples/toy/{ => pasta}/toy_cpp/toy.dat (100%) create mode 100644 examples/toy/pasta/toy_cpp/toy.o create mode 100644 examples/toy/pasta/toy_js/generate_witness.js rename examples/toy/{ => pasta}/toy_js/toy.wasm (98%) create mode 100644 examples/toy/pasta/toy_js/witness_calculator.js delete mode 100644 examples/toy/toy_cpp/calcwit.o delete mode 100644 examples/toy/toy_cpp/fr.o delete mode 100644 examples/toy/toy_cpp/main.o delete mode 100755 examples/toy/toy_cpp/toy delete mode 100644 examples/toy/toy_cpp/toy.o rename examples/{toy_wasm.rs => toy_bn254.rs} (56%) rename examples/{toy.rs => toy_pasta.rs} (58%) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b5caa57..3558940 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,13 +4,12 @@ env: NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} jobs: - check-toy-example-wasm: + check-toy-example-bn254: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: - repository: nalinbhardwaj/circom - ref: pasta + repository: iden3/circom - uses: actions-rs/toolchain@v1 with: toolchain: stable @@ -28,14 +27,13 @@ jobs: with: node-version: "16" - run: bash ./examples/toy/compile.sh - - run: cargo run --release --example toy_wasm - check-toy-example-cpp: + - run: cargo run --release --example toy_bn254 + check-toy-example-pasta: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: - repository: nalinbhardwaj/circom - ref: pasta + repository: iden3/circom - uses: actions-rs/toolchain@v1 with: toolchain: stable @@ -53,15 +51,15 @@ jobs: with: node-version: "16" - run: bash ./examples/toy/compile.sh - - run: cargo run --release --example toy + - run: cargo run --release --example toy_pasta check-toy-example-browser: runs-on: ubuntu-latest steps: - uses: actions-rs/toolchain@v1 with: - toolchain: nightly-2022-08-09 + toolchain: nightly-2022-12-12 - run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh - uses: actions/checkout@v3 - - run: rustup component add rust-src --toolchain nightly-2022-08-09-x86_64-unknown-linux-gnu + - run: rustup component add rust-src --toolchain nightly-2022-12-12-x86_64-unknown-linux-gnu - run: cd browser-test && wasm-pack build --target web --out-dir test-client/public/pkg - run: cd browser-test/test-client && yarn install && CI=false yarn build diff --git a/Cargo.toml b/Cargo.toml index f7ea615..aa92571 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nova-scotia" -version = "0.4.0" +version = "0.5.0" edition = "2021" authors = ["Nalin "] description = "Middleware to compile Circom circuits to Nova zkSNARK scheme" @@ -19,10 +19,10 @@ byteorder = "1.4.3" ff = { version = "0.13", features = ["derive"]} hex-literal = "0.3.4" itertools = "0.9.0" -nova-snark = { version = "0.21.0", default-features = false } +nova-snark = "0.23.0" num-bigint = { version = "0.4", features = ["serde", "rand"] } num-traits = "0.2.15" -pasta_curves = { version = "0.5.1", features = ["repr-c", "serde"] } +pasta_curves = "0.5" serde = "1.0" serde_json = "1.0.85" diff --git a/README.md b/README.md index 8ee508b..609ca0c 100644 --- a/README.md +++ b/README.md @@ -12,15 +12,15 @@ Nova is the state of the art for recursive SNARKs, Circom is the state of the ar As [Justin Drake talks about it](https://youtu.be/SwonTtOQzAk), I think the right way to think of Nova is as a preprocessor for zkSNARKs with lots of repeated structure -- Nova can shrink the cost (in number of R1CS constraints) of checking N instances of a problem to ~one instance of the same problem. This is clean and magical and lends itself well to a world where we take the output of Nova and then verify it in a "real" zkSNARK (like PLONK/groth16/Spartan) to obtain a actually fully minified proof (that is sublinear even in the size of one instance). Notably, [this pattern is already used](https://youtu.be/VmYpbFxBdtM?t=155) in settings like [zkEVMs](https://youtu.be/j7An-33_Zs0), but with STARK proofs instead of Nova proofs. IMO, Nova (and folding scheme-like things in particular) lend themselves better to the properties we want with the preprocessing layer vs. STARKs: fast compression, minimal cryptographic assumptions and low recursive overhead.[^1] +Nova Scotia comes with extensive [examples](https://github.com/nalinbhardwaj/Nova-Scotia/tree/main/examples), as well as a [in-browser usage example](https://github.com/nalinbhardwaj/Nova-Scotia/tree/main/browser-test). We will describe the proving/verifying workflow in more detail below. + [^1]: But currently, Nova/R1CS lacks the customizability of STARKS (custom gates and lookup tables in particular), so there is a tradeoff here. ## How? ![Nova Scotia](https://user-images.githubusercontent.com/6984346/201644973-fb084b6c-3807-4bf4-99bf-a1461271f1b5.png) -To use it yourself, install this branch of [Circom](https://docs.circom.io) which adds support for the [Pasta Curves](https://electriccoin.co/blog/the-pasta-curves-for-halo-2-and-beyond/) to the C++ witness generator: [nalinbhardwaj/pasta](https://github.com/nalinbhardwaj/circom/tree/pasta). To install this branch, clone the git repo (using `git clone https://github.com/nalinbhardwaj/circom.git && git checkout pasta`). Then build and install the `circom` binary by running `cargo install --path circom`. This will overwrite any existing `circom` binary. Refer to the [Circom documentation](https://docs.circom.io/getting-started/installation/#installing-dependencies) for more information. - -Note that if you are interested in generating and verifying proofs in browsers, you must use the WASM witness generator. We will describe in-browser proving and verification later in the README. +To use it yourself, start by installing [Circom](https://docs.circom.io) as described in the [Circom documentation](https://docs.circom.io/getting-started/installation/#installing-dependencies). ### Writing Nova Step Circuits in Circom @@ -28,24 +28,30 @@ To write Nova Scotia circuits in Circom, we operate on the abstraction of one st When you're ready, compile your circuit using `circom [file].circom --r1cs --sym --c --prime vesta` for the vesta curve. Compile the C++ witness generator in `[file]_cpp` by running `make` in that folder. Alternately, you can compile the WASM witness generator using `circom [file].circom --r1cs --sym --wasm --prime vesta`. We will later use the R1CS file and the witness generator binary (either C++ binary or WASM), so make note of their filepaths. You can independently test these step circuits by running witness generation as described in the [Circom documentation](https://docs.circom.io/getting-started/computing-the-witness/). +Since Nova runs on a cycle of elliptic curves, you must specify the curve via traits and in the Circom compilation command. Currently, Nova Scotia supports any cycle supported by Nova upstream in [provider](https://github.com/microsoft/Nova/tree/main/src/provider) and by Circom's `--prime` flag. You can see example circuits for both the [Pasta (pallas/vesta)](https://github.com/nalinbhardwaj/Nova-Scotia/blob/main/examples/toy_pasta.rs) and [bn254/grumpkin](https://github.com/nalinbhardwaj/Nova-Scotia/blob/main/examples/toy_bn254.rs) curves in the examples directory. + ### Rust shimming for Nova Scotia -Now, start a new Rust project and add Nova Scotia to your dependencies. Then, you can start using your Circom step circuits with Nova. Start by defining the paths to the Circom output and loading the R1CS file: +Start a new Rust project and add Nova Scotia to your dependencies. Then, you can start using your Circom step circuits with Nova. Start by defining the paths to the Circom output and loading the R1CS file: ```rust +// The cycle of curves we use, can be any cycle supported by Nova +type G1 = pasta_curves::pallas::Point; +type G2 = pasta_curves::vesta::Point; + let circuit_file = root.join("examples/bitcoin/circom/bitcoin_benchmark.r1cs"); let witness_generator_file = root.join("examples/bitcoin/circom/bitcoin_benchmark_cpp/bitcoin_benchmark"); -let r1cs = load_r1cs(&circuit_file); // loads R1CS file into memory +let r1cs = load_r1cs::(&circuit_file); // loads R1CS file into memory ``` -Circom supports witness generation using both C++ and WASM, so you can choose which one to use by passing `witness_generator_file` either as the generated C++ binary or as the WASM output of Circom (the `circuit.wasm` file). If you use WASM, we assume you have a compatible version of `node` installed on your system. +Circom supports witness generation using both C++ and WASM, so you can choose which one to use by passing `witness_generator_file` either as the generated C++ binary or as the WASM output of Circom (the `circuit.wasm` file). If you use WASM, we assume you have a compatible version of `node` installed on your system. Note that for proving locally, we recommend using the C++ witness generator for performance (except on M1/M2 Macs where it is not supported). For in-browser proving/verifying, you must use the WASM witness generator. We will describe in-browser proving and verification workflow later in the README. Then, create the public parameters (CRS) using the `create_public_params` function: ```rust -let pp = create_public_params(r1cs.clone()); +let pp = create_public_params::(r1cs.clone()); ``` Now, construct the input to Circom witness generator at each step of recursion. This is a HashMap representation of the JSON input to your Circom input. For instance, in the case of the [bitcoin](https://github.com/nalinbhardwaj/Nova-Scotia/blob/main/examples/bitcoin.rs#L40) example, `private_inputs` is a list of `HashMap`s, each containing block headers and block hashes for the blocks that step of recursion verifies, and the public input `step_in` is the previous block hash in the chain. @@ -54,15 +60,15 @@ To instantiate this recursion, we use `create_recursive_circuit` from Nova Scoti ```rust let recursive_snark = create_recursive_circuit( - witness_generator_file, + FileLocation::PathBuf(witness_generator_file), r1cs, private_inputs, - start_public_input.clone(), + start_public_input.to_vec(), &pp, ).unwrap(); ``` -Verification is done using the `verify` function defined by Nova, which additionally takes secondary inputs that Nova Scotia will initialise to `vec![::Scalar::zero()]`, so just pass that in: +Verification is done using the `verify` function defined by Nova, which additionally takes secondary inputs that Nova Scotia will initialise to `[F::zero()]`, so just pass that in: ```rust println!("Verifying a RecursiveSNARK..."); @@ -70,8 +76,8 @@ let start = Instant::now(); let res = recursive_snark.verify( &pp, iteration_count, - start_public_input.clone(), - vec![::Scalar::zero()], + &start_public_input.clone(), + &[F::zero()], ); println!( "RecursiveSNARK::verify: {:?}, took {:?}", @@ -94,11 +100,11 @@ bitcoin.rs is a more complex example that uses Nova to create a prover for bitco | Number of recursion steps | Blocks verified per step | Prover time | Verifier time (uncompressed) | | ------------------------- | ------------------------ | ----------- | ---------------------------- | -| 120 | 1 | 57.33s | 197.20ms | -| 60 | 2 | 46.11s | 307.08ms | -| 40 | 3 | 43.60s | 449.02ms | -| 30 | 4 | 41.17s | 560.53ms | -| 24 | 5 | 39.73s | 728.09ms | +| 120 | 1 | 55.38s | 214.43ms | +| 60 | 2 | 49.05s | 434.96ms | +| 40 | 3 | 42.08s | 509.03ms | +| 30 | 4 | 45.40s | 923.23ms | +| 24 | 5 | 48.43s | 991.89ms | Note that the verification times are linear in the number of blocks per step of recursion, while the proving time reduces with fewer recursive steps. In practice, you would use the output of Nova as an input to another SNARK scheme like Plonk/groth16 (as previously mentioned) to obtain full succinctness. @@ -112,15 +118,7 @@ Nova Scotia also supports proving and verification of proofs in browser, along w ## Notes for interested contributors -### TODO list - -- [ ] Switch Nova to BN254/grumpkin cycle to make it work on Ethereum chain! This should be doable since Nova only needs DLOG hardness. -- [ ] Write Relaxed R1CS verifiers in plonk/groth16 libraries (ex. Halo 2, Circom). -- [ ] Make Nova work with secp/secq cycle for efficient ECDSA signature verification + aggregation - -Seperately, since Nova's `StepCircuit` trait is pretty much the same as Bellperson's `Circuit` trait, we can probably also use the transpilation in this repo to use [Bellperson](https://github.com/filecoin-project/bellperson) with Circom circuits/proofs, along with its [snarkpack](https://eprint.iacr.org/2021/529) aggregation features. - -If you are interested in any of these tasks and want to work on them, please reach out! [0xPARC's PARC Squad](https://0xparc.org/blog/parc-squad) may also be able to provide financial and technical support for related work. +Please see [GitHub issues](https://github.com/nalinbhardwaj/Nova-Scotia/issues) if you are interested in contributing. You can reach out to me directly on Telegram at @nibnalin if you have any questions. ### Credits diff --git a/browser-test/Cargo.toml b/browser-test/Cargo.toml index e62291f..e47b053 100644 --- a/browser-test/Cargo.toml +++ b/browser-test/Cargo.toml @@ -7,11 +7,12 @@ edition = "2021" [dependencies] nova-scotia = { path = "../" } -nova-snark = { version = "0.21.0", default-features = false } +nova-snark = "0.23.0" num-bigint = { version = "0.4", features = ["serde", "rand"] } num-traits = "0.2.15" serde = "1.0" serde_json = "1.0.85" +pasta_curves = "0.5" [target.'cfg(target_family = "wasm")'.dependencies] getrandom = { version = "0.2", features = ["js"]} diff --git a/browser-test/env.sh b/browser-test/env.sh new file mode 100644 index 0000000..8c1e9a2 --- /dev/null +++ b/browser-test/env.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +export PATH="/usr/local/opt/llvm/bin/:$PATH" +export CC=/usr/local/opt/llvm/bin/clang +export AR=/usr/local/opt/llvm/bin/llvm-ar \ No newline at end of file diff --git a/browser-test/rust-toolchain b/browser-test/rust-toolchain index 8caa299..467f338 100644 --- a/browser-test/rust-toolchain +++ b/browser-test/rust-toolchain @@ -1 +1 @@ -nightly-2022-08-09 \ No newline at end of file +nightly-2022-12-12 \ No newline at end of file diff --git a/browser-test/src/wasm.rs b/browser-test/src/wasm.rs index 1f797b5..10e1bfc 100644 --- a/browser-test/src/wasm.rs +++ b/browser-test/src/wasm.rs @@ -1,12 +1,10 @@ use std::collections::HashMap; -use nova_scotia::FileLocation; use nova_scotia::{ circom::{circuit::CircomCircuit, reader::load_r1cs}, - create_public_params, create_recursive_circuit, EE1, EE2, F1, F2, G1, G2, S1, S2, + create_public_params, create_recursive_circuit, FileLocation, F, S, }; use nova_snark::{ - spartan::RelaxedR1CSSNARK, traits::{circuit::TrivialTestCircuit, Group}, CompressedSNARK, PublicParams, }; @@ -48,13 +46,16 @@ pub fn init_panic_hook() { const WEBSITE_ROOT: &str = "https://effulgent-liger-07e9d0.netlify.app/"; +type G1 = pasta_curves::pallas::Point; +type G2 = pasta_curves::vesta::Point; + #[wasm_bindgen] pub async fn generate_params() -> String { - let r1cs = load_r1cs(&FileLocation::URL( + let r1cs = load_r1cs::(&FileLocation::URL( WEBSITE_ROOT.to_string().clone() + &"toy.r1cs".to_string(), )) .await; - let pp = create_public_params(r1cs.clone()); + let pp: PublicParams = create_public_params(r1cs.clone()); let serialised = serde_json::to_string(&pp).unwrap(); return serialised; } @@ -63,7 +64,7 @@ pub async fn generate_params() -> String { pub async fn generate_proof(pp_str: String) -> String { let iteration_count = 5; - let r1cs = load_r1cs(&FileLocation::URL( + let r1cs = load_r1cs::(&FileLocation::URL( WEBSITE_ROOT.to_string().clone() + &"toy.r1cs".to_string(), )) .await; @@ -77,13 +78,12 @@ pub async fn generate_proof(pp_str: String) -> String { private_inputs.push(private_input); } - let start_public_input = vec![F1::from(10), F1::from(10)]; + let start_public_input = [F::::from(10), F::::from(10)]; - let pp = - serde_json::from_str::, TrivialTestCircuit>>( - &pp_str, - ) - .unwrap(); + let pp = serde_json::from_str::< + PublicParams>, TrivialTestCircuit>>, + >(&pp_str) + .unwrap(); console_log!( "Number of constraints per step (primary circuit): {}", @@ -108,29 +108,24 @@ pub async fn generate_proof(pp_str: String) -> String { witness_generator_wasm, r1cs, private_inputs, - start_public_input.clone(), + start_public_input.to_vec(), &pp, ) .await .unwrap(); // TODO: empty? - let z0_secondary = vec![::Scalar::zero()]; + let z0_secondary = [F::::zero()]; // verify the recursive SNARK console_log!("Verifying a RecursiveSNARK..."); - let res = recursive_snark.verify( - &pp, - iteration_count, - start_public_input.clone(), - z0_secondary.clone(), - ); + let res = recursive_snark.verify(&pp, iteration_count, &start_public_input, &z0_secondary); assert!(res.is_ok()); // produce a compressed SNARK console_log!("Generating a CompressedSNARK using Spartan with IPA-PC..."); - let (pk, _vk) = CompressedSNARK::<_, _, _, _, S1, S2>::setup(&pp).unwrap(); - let res = CompressedSNARK::<_, _, _, _, S1, S2>::prove(&pp, &pk, &recursive_snark); + let (pk, _vk) = CompressedSNARK::<_, _, _, _, S, S>::setup(&pp).unwrap(); + let res = CompressedSNARK::<_, _, _, _, S, S>::prove(&pp, &pk, &recursive_snark); assert!(res.is_ok()); let compressed_snark = res.unwrap(); return serde_json::to_string(&compressed_snark).unwrap(); @@ -138,25 +133,17 @@ pub async fn generate_proof(pp_str: String) -> String { #[wasm_bindgen] pub async fn verify_compressed_proof(pp_str: String, proof_str: String) -> bool { - let pp = - serde_json::from_str::, TrivialTestCircuit>>( - &pp_str, - ) - .unwrap(); - let (_pk, vk) = CompressedSNARK::<_, _, _, _, S1, S2>::setup(&pp).unwrap(); + let pp = serde_json::from_str::< + PublicParams>, TrivialTestCircuit>>, + >(&pp_str) + .unwrap(); + let (_pk, vk) = CompressedSNARK::<_, _, _, _, S, S>::setup(&pp).unwrap(); let iteration_count = 5; - let start_public_input = vec![F1::from(10), F1::from(10)]; - let z0_secondary = vec![::Scalar::zero()]; + let start_public_input = vec![F::::from(10), F::::from(10)]; + let z0_secondary = vec![F::::zero()]; let compressed_proof = serde_json::from_str::< - CompressedSNARK< - G1, - G2, - CircomCircuit, - TrivialTestCircuit, - RelaxedR1CSSNARK, - RelaxedR1CSSNARK, - >, + CompressedSNARK>, TrivialTestCircuit>, S, S>, >(&proof_str) .unwrap(); let res = compressed_proof.verify( diff --git a/examples/bitcoin.rs b/examples/bitcoin.rs index dabb48f..7a65764 100644 --- a/examples/bitcoin.rs +++ b/examples/bitcoin.rs @@ -7,7 +7,7 @@ use std::{ use ff::PrimeField; use nova_scotia::{ - circom::reader::load_r1cs, create_public_params, create_recursive_circuit, FileLocation, F1, G2, + circom::reader::load_r1cs, create_public_params, create_recursive_circuit, FileLocation, F, }; use nova_snark::traits::Group; use serde::{Deserialize, Serialize}; @@ -22,10 +22,13 @@ struct Blocks { } fn bench(iteration_count: usize, per_iteration_count: usize) -> (Duration, Duration) { + type G1 = pasta_curves::pallas::Point; + type G2 = pasta_curves::vesta::Point; + let root = current_dir().unwrap(); let circuit_file = root.join("examples/bitcoin/circom/bitcoin_benchmark.r1cs"); - let r1cs = load_r1cs(&FileLocation::PathBuf(circuit_file)); + let r1cs = load_r1cs::(&FileLocation::PathBuf(circuit_file)); let witness_generator_file = root.join("examples/bitcoin/circom/bitcoin_benchmark_cpp/bitcoin_benchmark"); @@ -33,9 +36,9 @@ fn bench(iteration_count: usize, per_iteration_count: usize) -> (Duration, Durat let btc_blocks: Blocks = serde_json::from_str(include_str!("bitcoin/fetcher/btc-blocks.json")).unwrap(); - let start_public_input = vec![ - F1::from_str_vartime(&btc_blocks.prevBlockHash[0]).unwrap(), - F1::from_str_vartime(&btc_blocks.prevBlockHash[1]).unwrap(), + let start_public_input = [ + F::::from_str_vartime(&btc_blocks.prevBlockHash[0]).unwrap(), + F::::from_str_vartime(&btc_blocks.prevBlockHash[1]).unwrap(), ]; let mut private_inputs = Vec::new(); @@ -61,7 +64,7 @@ fn bench(iteration_count: usize, per_iteration_count: usize) -> (Duration, Durat // println!("{:?} {:?}", start_public_input, private_inputs); - let pp = create_public_params(r1cs.clone()); + let pp = create_public_params::(r1cs.clone()); println!( "Number of constraints per step (primary circuit): {}", @@ -87,24 +90,19 @@ fn bench(iteration_count: usize, per_iteration_count: usize) -> (Duration, Durat FileLocation::PathBuf(witness_generator_file), r1cs, private_inputs, - start_public_input.clone(), + start_public_input.to_vec(), &pp, ) .unwrap(); let prover_time = start.elapsed(); println!("RecursiveSNARK creation took {:?}", start.elapsed()); - let z0_secondary = vec![::Scalar::zero()]; + let z0_secondary = [::Scalar::zero()]; // verify the recursive SNARK println!("Verifying a RecursiveSNARK..."); let start = Instant::now(); - let res = recursive_snark.verify( - &pp, - iteration_count, - start_public_input.clone(), - z0_secondary.clone(), - ); + let res = recursive_snark.verify(&pp, iteration_count, &start_public_input, &z0_secondary); println!( "RecursiveSNARK::verify: {:?}, took {:?}", res, diff --git a/examples/bitcoin/benchmark.csv b/examples/bitcoin/benchmark.csv index 8715b80..6cb4411 100644 --- a/examples/bitcoin/benchmark.csv +++ b/examples/bitcoin/benchmark.csv @@ -1,6 +1,6 @@ iteration_count,per_iteration_count,prover_time,verifier_time -120,1,71.309186774s,263.608988ms -60,2,60.127530781s,463.162481ms -40,3,52.164369497s,671.983056ms -30,4,54.131651799s,878.674828ms -24,5,56.433211616s,1.111124065s +120,1,55.385328292s,214.435377ms +60,2,49.05568792s,434.960619ms +40,3,42.080714823s,509.038888ms +30,4,45.407602287s,923.23241ms +24,5,48.438942637s,991.893288ms diff --git a/examples/bitcoin/circom/bitcoin.circom b/examples/bitcoin/circom/bitcoin.circom index c4402fc..1aa94b0 100644 --- a/examples/bitcoin/circom/bitcoin.circom +++ b/examples/bitcoin/circom/bitcoin.circom @@ -174,7 +174,7 @@ template CheckOneBlock() { template Main(BLOCK_COUNT) { signal input step_in[2]; - signal output lastBlockHash[2]; + signal output step_out[2]; // last block hash signal input blockHashes[BLOCK_COUNT][2]; signal input blockHeaders[BLOCK_COUNT][80]; @@ -196,7 +196,7 @@ template Main(BLOCK_COUNT) { checker[i].blockHeaders[j] <== blockHeaders[i][j]; } } - for (var j = 0;j < 2;j++) lastBlockHash[j] <== blockHashes[BLOCK_COUNT - 1][j]; + for (var j = 0;j < 2;j++) step_out[j] <== blockHashes[BLOCK_COUNT - 1][j]; } component main { public [step_in] } = Main(1); diff --git a/examples/bitcoin/circom/bitcoin_benchmark.circom b/examples/bitcoin/circom/bitcoin_benchmark.circom index 2c0e53c..1aa94b0 100644 --- a/examples/bitcoin/circom/bitcoin_benchmark.circom +++ b/examples/bitcoin/circom/bitcoin_benchmark.circom @@ -174,7 +174,7 @@ template CheckOneBlock() { template Main(BLOCK_COUNT) { signal input step_in[2]; - signal output lastBlockHash[2]; + signal output step_out[2]; // last block hash signal input blockHashes[BLOCK_COUNT][2]; signal input blockHeaders[BLOCK_COUNT][80]; @@ -196,7 +196,7 @@ template Main(BLOCK_COUNT) { checker[i].blockHeaders[j] <== blockHeaders[i][j]; } } - for (var j = 0;j < 2;j++) lastBlockHash[j] <== blockHashes[BLOCK_COUNT - 1][j]; + for (var j = 0;j < 2;j++) step_out[j] <== blockHashes[BLOCK_COUNT - 1][j]; } -component main { public [step_in] } = Main(5); +component main { public [step_in] } = Main(1); diff --git a/examples/toy/bn254/toy.r1cs b/examples/toy/bn254/toy.r1cs new file mode 100644 index 0000000000000000000000000000000000000000..3332eb6e7402869cd36a2b4ecb242b3fe6906661 GIT binary patch literal 272 zcmXRiOfF_*U|?VdVkRK20AgeS69xZWDY*S0+b}A1|;tQHADeO1NnIEWd*7Mxf_H*df9*&1VC(%n>0WiBmfcz0g!qS M0I2~1klR220LkSaGynhq literal 0 HcmV?d00001 diff --git a/examples/toy/toy.sym b/examples/toy/bn254/toy.sym similarity index 100% rename from examples/toy/toy.sym rename to examples/toy/bn254/toy.sym diff --git a/examples/toy/toy_cpp/Makefile b/examples/toy/bn254/toy_cpp/Makefile similarity index 100% rename from examples/toy/toy_cpp/Makefile rename to examples/toy/bn254/toy_cpp/Makefile diff --git a/examples/toy/toy_cpp/calcwit.cpp b/examples/toy/bn254/toy_cpp/calcwit.cpp similarity index 100% rename from examples/toy/toy_cpp/calcwit.cpp rename to examples/toy/bn254/toy_cpp/calcwit.cpp diff --git a/examples/toy/toy_cpp/calcwit.hpp b/examples/toy/bn254/toy_cpp/calcwit.hpp similarity index 95% rename from examples/toy/toy_cpp/calcwit.hpp rename to examples/toy/bn254/toy_cpp/calcwit.hpp index 5f5ae24..363de21 100644 --- a/examples/toy/toy_cpp/calcwit.hpp +++ b/examples/toy/bn254/toy_cpp/calcwit.hpp @@ -10,7 +10,7 @@ #include "circom.hpp" #include "fr.hpp" -#define NMUTEXES 12 //512 +#define NMUTEXES 32 //512 u64 fnv1a(std::string s); @@ -32,9 +32,9 @@ class Circom_CalcWit { // parallelism std::mutex numThreadMutex; std::condition_variable ntcvs; - uint numThread; + int numThread; - uint maxThread; + int maxThread; // Functions called by the circuit Circom_CalcWit(Circom_Circuit *aCircuit, uint numTh = NMUTEXES); diff --git a/examples/toy/bn254/toy_cpp/calcwit.o b/examples/toy/bn254/toy_cpp/calcwit.o new file mode 100644 index 0000000000000000000000000000000000000000..28d1cc35f81e5c8811e254c03eb0b763d0e356da GIT binary patch literal 16120 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 Y6lrb7{|PlH+XGwjC-_EBA|>g603H0sKL7v# literal 0 HcmV?d00001 diff --git a/examples/toy/toy_cpp/circom.hpp b/examples/toy/bn254/toy_cpp/circom.hpp similarity index 85% rename from examples/toy/toy_cpp/circom.hpp rename to examples/toy/bn254/toy_cpp/circom.hpp index d9c8df1..eabc686 100644 --- a/examples/toy/toy_cpp/circom.hpp +++ b/examples/toy/bn254/toy_cpp/circom.hpp @@ -47,12 +47,12 @@ struct Circom_Component { std::string templateName; std::string componentName; u64 idFather; - u32* subcomponents; - bool* subcomponentsParallel; - bool *outputIsSet; //one for each output - std::mutex *mutexes; //one for each output - std::condition_variable *cvs; - std::thread *sbct; //subcomponent threads + u32* subcomponents = NULL; + bool* subcomponentsParallel = NULL; + bool *outputIsSet = NULL; //one for each output + std::mutex *mutexes = NULL; //one for each output + std::condition_variable *cvs = NULL; + std::thread *sbct = NULL;//subcomponent threads }; /* diff --git a/examples/toy/bn254/toy_cpp/fr.asm b/examples/toy/bn254/toy_cpp/fr.asm new file mode 100644 index 0000000..611e89c --- /dev/null +++ b/examples/toy/bn254/toy_cpp/fr.asm @@ -0,0 +1,8794 @@ + + + global Fr_copy + global Fr_copyn + global Fr_add + global Fr_sub + global Fr_neg + global Fr_mul + global Fr_square + global Fr_band + global Fr_bor + global Fr_bxor + global Fr_bnot + global Fr_shl + global Fr_shr + global Fr_eq + global Fr_neq + global Fr_lt + global Fr_gt + global Fr_leq + global Fr_geq + global Fr_land + global Fr_lor + global Fr_lnot + global Fr_toNormal + global Fr_toLongNormal + global Fr_toMontgomery + global Fr_toInt + global Fr_isTrue + global Fr_q + global Fr_R3 + + global Fr_rawCopy + global Fr_rawZero + global Fr_rawSwap + global Fr_rawAdd + global Fr_rawSub + global Fr_rawNeg + global Fr_rawMMul + global Fr_rawMSquare + global Fr_rawToMontgomery + global Fr_rawFromMontgomery + global Fr_rawIsEq + global Fr_rawIsZero + global Fr_rawq + global Fr_rawR3 + + extern Fr_fail + DEFAULT REL + + section .text + + + + + + + + + + + + + + + + + + + + +;;;;;;;;;;;;;;;;;;;;;; +; copy +;;;;;;;;;;;;;;;;;;;;;; +; Copies +; Params: +; rsi <= the src +; rdi <= the dest +; +; Nidified registers: +; rax +;;;;;;;;;;;;;;;;;;;;;;; +Fr_copy: + + mov rax, [rsi + 0] + mov [rdi + 0], rax + + mov rax, [rsi + 8] + mov [rdi + 8], rax + + mov rax, [rsi + 16] + mov [rdi + 16], rax + + mov rax, [rsi + 24] + mov [rdi + 24], rax + + mov rax, [rsi + 32] + mov [rdi + 32], rax + + ret + + +;;;;;;;;;;;;;;;;;;;;;; +; rawCopy +;;;;;;;;;;;;;;;;;;;;;; +; Copies +; Params: +; rsi <= the src +; rdi <= the dest +; +; Nidified registers: +; rax +;;;;;;;;;;;;;;;;;;;;;;; +Fr_rawCopy: + + mov rax, [rsi + 0] + mov [rdi + 0], rax + + mov rax, [rsi + 8] + mov [rdi + 8], rax + + mov rax, [rsi + 16] + mov [rdi + 16], rax + + mov rax, [rsi + 24] + mov [rdi + 24], rax + + ret + + +;;;;;;;;;;;;;;;;;;;;;; +; rawZero +;;;;;;;;;;;;;;;;;;;;;; +; Copies +; Params: +; rsi <= the src +; +; Nidified registers: +; rax +;;;;;;;;;;;;;;;;;;;;;;; +Fr_rawZero: + xor rax, rax + + mov [rdi + 0], rax + + mov [rdi + 8], rax + + mov [rdi + 16], rax + + mov [rdi + 24], rax + + ret + +;;;;;;;;;;;;;;;;;;;;;; +; rawSwap +;;;;;;;;;;;;;;;;;;;;;; +; Copies +; Params: +; rdi <= a +; rsi <= p +; +; Nidified registers: +; rax +;;;;;;;;;;;;;;;;;;;;;;; +Fr_rawSwap: + + mov rax, [rsi + 0] + mov rcx, [rdi + 0] + mov [rdi + 0], rax + mov [rsi + 0], rbx + + mov rax, [rsi + 8] + mov rcx, [rdi + 8] + mov [rdi + 8], rax + mov [rsi + 8], rbx + + mov rax, [rsi + 16] + mov rcx, [rdi + 16] + mov [rdi + 16], rax + mov [rsi + 16], rbx + + mov rax, [rsi + 24] + mov rcx, [rdi + 24] + mov [rdi + 24], rax + mov [rsi + 24], rbx + + ret + + +;;;;;;;;;;;;;;;;;;;;;; +; copy an array of integers +;;;;;;;;;;;;;;;;;;;;;; +; Copies +; Params: +; rsi <= the src +; rdi <= the dest +; rdx <= number of integers to copy +; +; Nidified registers: +; rax +;;;;;;;;;;;;;;;;;;;;;;; +Fr_copyn: +Fr_copyn_loop: + mov r8, rsi + mov r9, rdi + mov rax, 5 + mul rdx + mov rcx, rax + cld + rep movsq + mov rsi, r8 + mov rdi, r9 + ret + +;;;;;;;;;;;;;;;;;;;;;; +; rawCopyS2L +;;;;;;;;;;;;;;;;;;;;;; +; Convert a 64 bit integer to a long format field element +; Params: +; rsi <= the integer +; rdi <= Pointer to the overwritted element +; +; Nidified registers: +; rax +;;;;;;;;;;;;;;;;;;;;;;; + +rawCopyS2L: + mov al, 0x80 + shl rax, 56 + mov [rdi], rax ; set the result to LONG normal + + cmp rsi, 0 + js u64toLong_adjust_neg + + mov [rdi + 8], rsi + xor rax, rax + + mov [rdi + 16], rax + + mov [rdi + 24], rax + + mov [rdi + 32], rax + + ret + +u64toLong_adjust_neg: + add rsi, [q] ; Set the first digit + mov [rdi + 8], rsi ; + + mov rsi, -1 ; all ones + + mov rax, rsi ; Add to q + adc rax, [q + 8 ] + mov [rdi + 16], rax + + mov rax, rsi ; Add to q + adc rax, [q + 16 ] + mov [rdi + 24], rax + + mov rax, rsi ; Add to q + adc rax, [q + 24 ] + mov [rdi + 32], rax + + ret + +;;;;;;;;;;;;;;;;;;;;;; +; toInt +;;;;;;;;;;;;;;;;;;;;;; +; Convert a 64 bit integer to a long format field element +; Params: +; rsi <= Pointer to the element +; Returs: +; rax <= The value +;;;;;;;;;;;;;;;;;;;;;;; +Fr_toInt: + mov rax, [rdi] + bt rax, 63 + jc Fr_long + movsx rax, eax + ret + +Fr_long: + push rbp + push rsi + push rdx + mov rbp, rsp + bt rax, 62 + jnc Fr_longNormal +Fr_longMontgomery: + + sub rsp, 40 + push rsi + mov rsi, rdi + mov rdi, rsp + call Fr_toNormal + pop rsi + + +Fr_longNormal: + mov rax, [rdi + 8] + mov rcx, rax + shr rcx, 31 + jnz Fr_longNeg + + mov rcx, [rdi + 16] + test rcx, rcx + jnz Fr_longNeg + + mov rcx, [rdi + 24] + test rcx, rcx + jnz Fr_longNeg + + mov rcx, [rdi + 32] + test rcx, rcx + jnz Fr_longNeg + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + +Fr_longNeg: + mov rax, [rdi + 8] + sub rax, [q] + jnc Fr_longErr + + mov rcx, [rdi + 16] + sbb rcx, [q + 8] + jnc Fr_longErr + + mov rcx, [rdi + 24] + sbb rcx, [q + 16] + jnc Fr_longErr + + mov rcx, [rdi + 32] + sbb rcx, [q + 24] + jnc Fr_longErr + + mov rcx, rax + sar rcx, 31 + add rcx, 1 + jnz Fr_longErr + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + +Fr_longErr: + push rdi + mov rdi, 0 + call Fr_fail + pop rdi + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + + + +Fr_rawMMul: + push r15 + push r14 + push r13 + push r12 + mov rcx,rdx + mov r9,[ np ] + xor r10,r10 + +; FirstLoop + mov rdx,[rsi + 0] + mulx rax,r11,[rcx] + mulx r8,r12,[rcx +8] + adcx r12,rax + mulx rax,r13,[rcx +16] + adcx r13,r8 + mulx r8,r14,[rcx +24] + adcx r14,rax + mov r15,r10 + adcx r15,r8 +; SecondLoop + mov rdx,r9 + mulx rax,rdx,r11 + mulx r8,rax,[q] + adcx rax,r11 + mulx rax,r11,[q +8] + adcx r11,r8 + adox r11,r12 + mulx r8,r12,[q +16] + adcx r12,rax + adox r12,r13 + mulx rax,r13,[q +24] + adcx r13,r8 + adox r13,r14 + mov r14,r10 + adcx r14,rax + adox r14,r15 + +; FirstLoop + mov rdx,[rsi + 8] + mov r15,r10 + mulx r8,rax,[rcx +0] + adcx r11,rax + adox r12,r8 + mulx r8,rax,[rcx +8] + adcx r12,rax + adox r13,r8 + mulx r8,rax,[rcx +16] + adcx r13,rax + adox r14,r8 + mulx r8,rax,[rcx +24] + adcx r14,rax + adox r15,r8 + adcx r15,r10 +; SecondLoop + mov rdx,r9 + mulx rax,rdx,r11 + mulx r8,rax,[q] + adcx rax,r11 + mulx rax,r11,[q +8] + adcx r11,r8 + adox r11,r12 + mulx r8,r12,[q +16] + adcx r12,rax + adox r12,r13 + mulx rax,r13,[q +24] + adcx r13,r8 + adox r13,r14 + mov r14,r10 + adcx r14,rax + adox r14,r15 + +; FirstLoop + mov rdx,[rsi + 16] + mov r15,r10 + mulx r8,rax,[rcx +0] + adcx r11,rax + adox r12,r8 + mulx r8,rax,[rcx +8] + adcx r12,rax + adox r13,r8 + mulx r8,rax,[rcx +16] + adcx r13,rax + adox r14,r8 + mulx r8,rax,[rcx +24] + adcx r14,rax + adox r15,r8 + adcx r15,r10 +; SecondLoop + mov rdx,r9 + mulx rax,rdx,r11 + mulx r8,rax,[q] + adcx rax,r11 + mulx rax,r11,[q +8] + adcx r11,r8 + adox r11,r12 + mulx r8,r12,[q +16] + adcx r12,rax + adox r12,r13 + mulx rax,r13,[q +24] + adcx r13,r8 + adox r13,r14 + mov r14,r10 + adcx r14,rax + adox r14,r15 + +; FirstLoop + mov rdx,[rsi + 24] + mov r15,r10 + mulx r8,rax,[rcx +0] + adcx r11,rax + adox r12,r8 + mulx r8,rax,[rcx +8] + adcx r12,rax + adox r13,r8 + mulx r8,rax,[rcx +16] + adcx r13,rax + adox r14,r8 + mulx r8,rax,[rcx +24] + adcx r14,rax + adox r15,r8 + adcx r15,r10 +; SecondLoop + mov rdx,r9 + mulx rax,rdx,r11 + mulx r8,rax,[q] + adcx rax,r11 + mulx rax,r11,[q +8] + adcx r11,r8 + adox r11,r12 + mulx r8,r12,[q +16] + adcx r12,rax + adox r12,r13 + mulx rax,r13,[q +24] + adcx r13,r8 + adox r13,r14 + mov r14,r10 + adcx r14,rax + adox r14,r15 + +;comparison + cmp r14,[q + 24] + jc Fr_rawMMul_done + jnz Fr_rawMMul_sq + cmp r13,[q + 16] + jc Fr_rawMMul_done + jnz Fr_rawMMul_sq + cmp r12,[q + 8] + jc Fr_rawMMul_done + jnz Fr_rawMMul_sq + cmp r11,[q + 0] + jc Fr_rawMMul_done + jnz Fr_rawMMul_sq +Fr_rawMMul_sq: + sub r11,[q +0] + sbb r12,[q +8] + sbb r13,[q +16] + sbb r14,[q +24] +Fr_rawMMul_done: + mov [rdi + 0],r11 + mov [rdi + 8],r12 + mov [rdi + 16],r13 + mov [rdi + 24],r14 + pop r12 + pop r13 + pop r14 + pop r15 + ret +Fr_rawMSquare: + push r15 + push r14 + push r13 + push r12 + mov rcx,rdx + mov r9,[ np ] + xor r10,r10 + +; FirstLoop + mov rdx,[rsi + 0] + mulx rax,r11,rdx + mulx r8,r12,[rsi +8] + adcx r12,rax + mulx rax,r13,[rsi +16] + adcx r13,r8 + mulx r8,r14,[rsi +24] + adcx r14,rax + mov r15,r10 + adcx r15,r8 +; SecondLoop + mov rdx,r9 + mulx rax,rdx,r11 + mulx r8,rax,[q] + adcx rax,r11 + mulx rax,r11,[q +8] + adcx r11,r8 + adox r11,r12 + mulx r8,r12,[q +16] + adcx r12,rax + adox r12,r13 + mulx rax,r13,[q +24] + adcx r13,r8 + adox r13,r14 + mov r14,r10 + adcx r14,rax + adox r14,r15 + +; FirstLoop + mov rdx,[rsi + 8] + mov r15,r10 + mulx r8,rax,[rsi +0] + adcx r11,rax + adox r12,r8 + mulx r8,rax,[rsi +8] + adcx r12,rax + adox r13,r8 + mulx r8,rax,[rsi +16] + adcx r13,rax + adox r14,r8 + mulx r8,rax,[rsi +24] + adcx r14,rax + adox r15,r8 + adcx r15,r10 +; SecondLoop + mov rdx,r9 + mulx rax,rdx,r11 + mulx r8,rax,[q] + adcx rax,r11 + mulx rax,r11,[q +8] + adcx r11,r8 + adox r11,r12 + mulx r8,r12,[q +16] + adcx r12,rax + adox r12,r13 + mulx rax,r13,[q +24] + adcx r13,r8 + adox r13,r14 + mov r14,r10 + adcx r14,rax + adox r14,r15 + +; FirstLoop + mov rdx,[rsi + 16] + mov r15,r10 + mulx r8,rax,[rsi +0] + adcx r11,rax + adox r12,r8 + mulx r8,rax,[rsi +8] + adcx r12,rax + adox r13,r8 + mulx r8,rax,[rsi +16] + adcx r13,rax + adox r14,r8 + mulx r8,rax,[rsi +24] + adcx r14,rax + adox r15,r8 + adcx r15,r10 +; SecondLoop + mov rdx,r9 + mulx rax,rdx,r11 + mulx r8,rax,[q] + adcx rax,r11 + mulx rax,r11,[q +8] + adcx r11,r8 + adox r11,r12 + mulx r8,r12,[q +16] + adcx r12,rax + adox r12,r13 + mulx rax,r13,[q +24] + adcx r13,r8 + adox r13,r14 + mov r14,r10 + adcx r14,rax + adox r14,r15 + +; FirstLoop + mov rdx,[rsi + 24] + mov r15,r10 + mulx r8,rax,[rsi +0] + adcx r11,rax + adox r12,r8 + mulx r8,rax,[rsi +8] + adcx r12,rax + adox r13,r8 + mulx r8,rax,[rsi +16] + adcx r13,rax + adox r14,r8 + mulx r8,rax,[rsi +24] + adcx r14,rax + adox r15,r8 + adcx r15,r10 +; SecondLoop + mov rdx,r9 + mulx rax,rdx,r11 + mulx r8,rax,[q] + adcx rax,r11 + mulx rax,r11,[q +8] + adcx r11,r8 + adox r11,r12 + mulx r8,r12,[q +16] + adcx r12,rax + adox r12,r13 + mulx rax,r13,[q +24] + adcx r13,r8 + adox r13,r14 + mov r14,r10 + adcx r14,rax + adox r14,r15 + +;comparison + cmp r14,[q + 24] + jc Fr_rawMSquare_done + jnz Fr_rawMSquare_sq + cmp r13,[q + 16] + jc Fr_rawMSquare_done + jnz Fr_rawMSquare_sq + cmp r12,[q + 8] + jc Fr_rawMSquare_done + jnz Fr_rawMSquare_sq + cmp r11,[q + 0] + jc Fr_rawMSquare_done + jnz Fr_rawMSquare_sq +Fr_rawMSquare_sq: + sub r11,[q +0] + sbb r12,[q +8] + sbb r13,[q +16] + sbb r14,[q +24] +Fr_rawMSquare_done: + mov [rdi + 0],r11 + mov [rdi + 8],r12 + mov [rdi + 16],r13 + mov [rdi + 24],r14 + pop r12 + pop r13 + pop r14 + pop r15 + ret +Fr_rawMMul1: + push r15 + push r14 + push r13 + push r12 + mov rcx,rdx + mov r9,[ np ] + xor r10,r10 + +; FirstLoop + mov rdx,rcx + mulx rax,r11,[rsi] + mulx r8,r12,[rsi +8] + adcx r12,rax + mulx rax,r13,[rsi +16] + adcx r13,r8 + mulx r8,r14,[rsi +24] + adcx r14,rax + mov r15,r10 + adcx r15,r8 +; SecondLoop + mov rdx,r9 + mulx rax,rdx,r11 + mulx r8,rax,[q] + adcx rax,r11 + mulx rax,r11,[q +8] + adcx r11,r8 + adox r11,r12 + mulx r8,r12,[q +16] + adcx r12,rax + adox r12,r13 + mulx rax,r13,[q +24] + adcx r13,r8 + adox r13,r14 + mov r14,r10 + adcx r14,rax + adox r14,r15 + + mov r15,r10 +; SecondLoop + mov rdx,r9 + mulx rax,rdx,r11 + mulx r8,rax,[q] + adcx rax,r11 + mulx rax,r11,[q +8] + adcx r11,r8 + adox r11,r12 + mulx r8,r12,[q +16] + adcx r12,rax + adox r12,r13 + mulx rax,r13,[q +24] + adcx r13,r8 + adox r13,r14 + mov r14,r10 + adcx r14,rax + adox r14,r15 + + mov r15,r10 +; SecondLoop + mov rdx,r9 + mulx rax,rdx,r11 + mulx r8,rax,[q] + adcx rax,r11 + mulx rax,r11,[q +8] + adcx r11,r8 + adox r11,r12 + mulx r8,r12,[q +16] + adcx r12,rax + adox r12,r13 + mulx rax,r13,[q +24] + adcx r13,r8 + adox r13,r14 + mov r14,r10 + adcx r14,rax + adox r14,r15 + + mov r15,r10 +; SecondLoop + mov rdx,r9 + mulx rax,rdx,r11 + mulx r8,rax,[q] + adcx rax,r11 + mulx rax,r11,[q +8] + adcx r11,r8 + adox r11,r12 + mulx r8,r12,[q +16] + adcx r12,rax + adox r12,r13 + mulx rax,r13,[q +24] + adcx r13,r8 + adox r13,r14 + mov r14,r10 + adcx r14,rax + adox r14,r15 + +;comparison + cmp r14,[q + 24] + jc Fr_rawMMul1_done + jnz Fr_rawMMul1_sq + cmp r13,[q + 16] + jc Fr_rawMMul1_done + jnz Fr_rawMMul1_sq + cmp r12,[q + 8] + jc Fr_rawMMul1_done + jnz Fr_rawMMul1_sq + cmp r11,[q + 0] + jc Fr_rawMMul1_done + jnz Fr_rawMMul1_sq +Fr_rawMMul1_sq: + sub r11,[q +0] + sbb r12,[q +8] + sbb r13,[q +16] + sbb r14,[q +24] +Fr_rawMMul1_done: + mov [rdi + 0],r11 + mov [rdi + 8],r12 + mov [rdi + 16],r13 + mov [rdi + 24],r14 + pop r12 + pop r13 + pop r14 + pop r15 + ret +Fr_rawFromMontgomery: + push r15 + push r14 + push r13 + push r12 + mov rcx,rdx + mov r9,[ np ] + xor r10,r10 + +; FirstLoop + mov r11,[rsi +0] + mov r12,[rsi +8] + mov r13,[rsi +16] + mov r14,[rsi +24] + mov r15,r10 +; SecondLoop + mov rdx,r9 + mulx rax,rdx,r11 + mulx r8,rax,[q] + adcx rax,r11 + mulx rax,r11,[q +8] + adcx r11,r8 + adox r11,r12 + mulx r8,r12,[q +16] + adcx r12,rax + adox r12,r13 + mulx rax,r13,[q +24] + adcx r13,r8 + adox r13,r14 + mov r14,r10 + adcx r14,rax + adox r14,r15 + + mov r15,r10 +; SecondLoop + mov rdx,r9 + mulx rax,rdx,r11 + mulx r8,rax,[q] + adcx rax,r11 + mulx rax,r11,[q +8] + adcx r11,r8 + adox r11,r12 + mulx r8,r12,[q +16] + adcx r12,rax + adox r12,r13 + mulx rax,r13,[q +24] + adcx r13,r8 + adox r13,r14 + mov r14,r10 + adcx r14,rax + adox r14,r15 + + mov r15,r10 +; SecondLoop + mov rdx,r9 + mulx rax,rdx,r11 + mulx r8,rax,[q] + adcx rax,r11 + mulx rax,r11,[q +8] + adcx r11,r8 + adox r11,r12 + mulx r8,r12,[q +16] + adcx r12,rax + adox r12,r13 + mulx rax,r13,[q +24] + adcx r13,r8 + adox r13,r14 + mov r14,r10 + adcx r14,rax + adox r14,r15 + + mov r15,r10 +; SecondLoop + mov rdx,r9 + mulx rax,rdx,r11 + mulx r8,rax,[q] + adcx rax,r11 + mulx rax,r11,[q +8] + adcx r11,r8 + adox r11,r12 + mulx r8,r12,[q +16] + adcx r12,rax + adox r12,r13 + mulx rax,r13,[q +24] + adcx r13,r8 + adox r13,r14 + mov r14,r10 + adcx r14,rax + adox r14,r15 + +;comparison + cmp r14,[q + 24] + jc Fr_rawFromMontgomery_done + jnz Fr_rawFromMontgomery_sq + cmp r13,[q + 16] + jc Fr_rawFromMontgomery_done + jnz Fr_rawFromMontgomery_sq + cmp r12,[q + 8] + jc Fr_rawFromMontgomery_done + jnz Fr_rawFromMontgomery_sq + cmp r11,[q + 0] + jc Fr_rawFromMontgomery_done + jnz Fr_rawFromMontgomery_sq +Fr_rawFromMontgomery_sq: + sub r11,[q +0] + sbb r12,[q +8] + sbb r13,[q +16] + sbb r14,[q +24] +Fr_rawFromMontgomery_done: + mov [rdi + 0],r11 + mov [rdi + 8],r12 + mov [rdi + 16],r13 + mov [rdi + 24],r14 + pop r12 + pop r13 + pop r14 + pop r15 + ret + +;;;;;;;;;;;;;;;;;;;;;; +; rawToMontgomery +;;;;;;;;;;;;;;;;;;;;;; +; Convert a number to Montgomery +; rdi <= Pointer destination element +; rsi <= Pointer to src element +;;;;;;;;;;;;;;;;;;;; +Fr_rawToMontgomery: + push rdx + lea rdx, [R2] + call Fr_rawMMul + pop rdx + ret + +;;;;;;;;;;;;;;;;;;;;;; +; toMontgomery +;;;;;;;;;;;;;;;;;;;;;; +; Convert a number to Montgomery +; rdi <= Destination +; rdi <= Pointer element to convert +; Modified registers: +; r8, r9, 10, r11, rax, rcx +;;;;;;;;;;;;;;;;;;;; +Fr_toMontgomery: + mov rax, [rsi] + bt rax, 62 ; check if montgomery + jc toMontgomery_doNothing + bt rax, 63 + jc toMontgomeryLong + +toMontgomeryShort: + movsx rdx, eax + mov [rdi], rdx + add rdi, 8 + lea rsi, [R2] + cmp rdx, 0 + js negMontgomeryShort +posMontgomeryShort: + call Fr_rawMMul1 + sub rdi, 8 + mov r11b, 0x40 + shl r11d, 24 + mov [rdi+4], r11d + ret + +negMontgomeryShort: + neg rdx ; Do the multiplication positive and then negate the result. + call Fr_rawMMul1 + mov rsi, rdi + call rawNegL + sub rdi, 8 + mov r11b, 0x40 + shl r11d, 24 + mov [rdi+4], r11d + ret + + +toMontgomeryLong: + mov [rdi], rax + add rdi, 8 + add rsi, 8 + lea rdx, [R2] + call Fr_rawMMul + sub rsi, 8 + sub rdi, 8 + mov r11b, 0xC0 + shl r11d, 24 + mov [rdi+4], r11d + ret + + +toMontgomery_doNothing: + call Fr_copy + ret + +;;;;;;;;;;;;;;;;;;;;;; +; toNormal +;;;;;;;;;;;;;;;;;;;;;; +; Convert a number from Montgomery +; rdi <= Destination +; rsi <= Pointer element to convert +; Modified registers: +; r8, r9, 10, r11, rax, rcx +;;;;;;;;;;;;;;;;;;;; +Fr_toNormal: + mov rax, [rsi] + bt rax, 62 ; check if montgomery + jnc toNormal_doNothing + bt rax, 63 ; if short, it means it's converted + jnc toNormal_doNothing + +toNormalLong: + add rdi, 8 + add rsi, 8 + call Fr_rawFromMontgomery + sub rsi, 8 + sub rdi, 8 + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + ret + +toNormal_doNothing: + call Fr_copy + ret + +;;;;;;;;;;;;;;;;;;;;;; +; toLongNormal +;;;;;;;;;;;;;;;;;;;;;; +; Convert a number to long normal +; rdi <= Destination +; rsi <= Pointer element to convert +; Modified registers: +; r8, r9, 10, r11, rax, rcx +;;;;;;;;;;;;;;;;;;;; +Fr_toLongNormal: + mov rax, [rsi] + bt rax, 63 ; check if long + jnc toLongNormal_fromShort + bt rax, 62 ; check if montgomery + jc toLongNormal_fromMontgomery + call Fr_copy ; It is already long + ret + +toLongNormal_fromMontgomery: + add rdi, 8 + add rsi, 8 + call Fr_rawFromMontgomery + sub rsi, 8 + sub rdi, 8 + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + ret + +toLongNormal_fromShort: + mov r8, rsi ; save rsi + movsx rsi, eax + call rawCopyS2L + mov rsi, r8 ; recover rsi + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + ret + + + + + + + + + + + + +;;;;;;;;;;;;;;;;;;;;;; +; add +;;;;;;;;;;;;;;;;;;;;;; +; Adds two elements of any kind +; Params: +; rsi <= Pointer to element 1 +; rdx <= Pointer to element 2 +; rdi <= Pointer to result +; Modified Registers: +; r8, r9, 10, r11, rax, rcx +;;;;;;;;;;;;;;;;;;;;;; +Fr_add: + push rbp + push rsi + push rdx + mov rbp, rsp + mov rax, [rsi] + mov rcx, [rdx] + bt rax, 63 ; Check if is short first operand + jc add_l1 + bt rcx, 63 ; Check if is short second operand + jc add_s1l2 + +add_s1s2: ; Both operands are short + + xor rdx, rdx + mov edx, eax + add edx, ecx + jo add_manageOverflow ; rsi already is the 64bits result + + mov [rdi], rdx ; not necessary to adjust so just save and return + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + +add_manageOverflow: ; Do the operation in 64 bits + push rsi + movsx rsi, eax + movsx rdx, ecx + add rsi, rdx + call rawCopyS2L + pop rsi + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + +add_l1: + bt rcx, 63 ; Check if is short second operand + jc add_l1l2 + +;;;;;;;; +add_l1s2: + bt rax, 62 ; check if montgomery first + jc add_l1ms2 +add_l1ns2: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + add rsi, 8 + movsx rdx, ecx + add rdi, 8 + cmp rdx, 0 + + jns tmp_1 + neg rdx + call rawSubLS + sub rdi, 8 + sub rsi, 8 + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret +tmp_1: + call rawAddLS + sub rdi, 8 + sub rsi, 8 + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + +add_l1ms2: + bt rcx, 62 ; check if montgomery second + jc add_l1ms2m +add_l1ms2n: + mov r11b, 0xC0 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toMontgomery + mov rdx, rdi + pop rdi + pop rsi + + + add rdi, 8 + add rsi, 8 + add rdx, 8 + call rawAddLL + sub rdi, 8 + sub rsi, 8 + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + +add_l1ms2m: + mov r11b, 0xC0 + shl r11d, 24 + mov [rdi+4], r11d + + add rdi, 8 + add rsi, 8 + add rdx, 8 + call rawAddLL + sub rdi, 8 + sub rsi, 8 + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + +;;;;;;;; +add_s1l2: + bt rcx, 62 ; check if montgomery second + jc add_s1l2m +add_s1l2n: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + lea rsi, [rdx + 8] + movsx rdx, eax + add rdi, 8 + cmp rdx, 0 + + jns tmp_2 + neg rdx + call rawSubLS + sub rdi, 8 + sub rsi, 8 + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret +tmp_2: + call rawAddLS + sub rdi, 8 + sub rsi, 8 + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + +add_s1l2m: + bt rax, 62 ; check if montgomery first + jc add_s1ml2m +add_s1nl2m: + mov r11b, 0xC0 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toMontgomery + mov rsi, rdi + pop rdi + pop rdx + + + add rdi, 8 + add rsi, 8 + add rdx, 8 + call rawAddLL + sub rdi, 8 + sub rsi, 8 + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + +add_s1ml2m: + mov r11b, 0xC0 + shl r11d, 24 + mov [rdi+4], r11d + + add rdi, 8 + add rsi, 8 + add rdx, 8 + call rawAddLL + sub rdi, 8 + sub rsi, 8 + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + +;;;; +add_l1l2: + bt rax, 62 ; check if montgomery first + jc add_l1ml2 +add_l1nl2: + bt rcx, 62 ; check if montgomery second + jc add_l1nl2m +add_l1nl2n: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + add rdi, 8 + add rsi, 8 + add rdx, 8 + call rawAddLL + sub rdi, 8 + sub rsi, 8 + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + +add_l1nl2m: + mov r11b, 0xC0 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toMontgomery + mov rsi, rdi + pop rdi + pop rdx + + + add rdi, 8 + add rsi, 8 + add rdx, 8 + call rawAddLL + sub rdi, 8 + sub rsi, 8 + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + +add_l1ml2: + bt rcx, 62 ; check if montgomery seconf + jc add_l1ml2m +add_l1ml2n: + mov r11b, 0xC0 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toMontgomery + mov rdx, rdi + pop rdi + pop rsi + + + add rdi, 8 + add rsi, 8 + add rdx, 8 + call rawAddLL + sub rdi, 8 + sub rsi, 8 + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + +add_l1ml2m: + mov r11b, 0xC0 + shl r11d, 24 + mov [rdi+4], r11d + + add rdi, 8 + add rsi, 8 + add rdx, 8 + call rawAddLL + sub rdi, 8 + sub rsi, 8 + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + + +;;;;;;;;;;;;;;;;;;;;;; +; rawAddLL +;;;;;;;;;;;;;;;;;;;;;; +; Adds two elements of type long +; Params: +; rsi <= Pointer to the long data of element 1 +; rdx <= Pointer to the long data of element 2 +; rdi <= Pointer to the long data of result +; Modified Registers: +; rax +;;;;;;;;;;;;;;;;;;;;;; +rawAddLL: +Fr_rawAdd: + ; Add component by component with carry + + mov rax, [rsi + 0] + add rax, [rdx + 0] + mov [rdi + 0], rax + + mov rax, [rsi + 8] + adc rax, [rdx + 8] + mov [rdi + 8], rax + + mov rax, [rsi + 16] + adc rax, [rdx + 16] + mov [rdi + 16], rax + + mov rax, [rsi + 24] + adc rax, [rdx + 24] + mov [rdi + 24], rax + + jc rawAddLL_sq ; if overflow, substract q + + ; Compare with q + + + cmp rax, [q + 24] + jc rawAddLL_done ; q is bigget so done. + jnz rawAddLL_sq ; q is lower + + + mov rax, [rdi + 16] + + cmp rax, [q + 16] + jc rawAddLL_done ; q is bigget so done. + jnz rawAddLL_sq ; q is lower + + + mov rax, [rdi + 8] + + cmp rax, [q + 8] + jc rawAddLL_done ; q is bigget so done. + jnz rawAddLL_sq ; q is lower + + + mov rax, [rdi + 0] + + cmp rax, [q + 0] + jc rawAddLL_done ; q is bigget so done. + jnz rawAddLL_sq ; q is lower + + ; If equal substract q +rawAddLL_sq: + + mov rax, [q + 0] + sub [rdi + 0], rax + + mov rax, [q + 8] + sbb [rdi + 8], rax + + mov rax, [q + 16] + sbb [rdi + 16], rax + + mov rax, [q + 24] + sbb [rdi + 24], rax + +rawAddLL_done: + ret + + +;;;;;;;;;;;;;;;;;;;;;; +; rawAddLS +;;;;;;;;;;;;;;;;;;;;;; +; Adds two elements of type long +; Params: +; rdi <= Pointer to the long data of result +; rsi <= Pointer to the long data of element 1 +; rdx <= Value to be added +;;;;;;;;;;;;;;;;;;;;;; +rawAddLS: + ; Add component by component with carry + + add rdx, [rsi] + mov [rdi] ,rdx + + mov rdx, 0 + adc rdx, [rsi + 8] + mov [rdi + 8], rdx + + mov rdx, 0 + adc rdx, [rsi + 16] + mov [rdi + 16], rdx + + mov rdx, 0 + adc rdx, [rsi + 24] + mov [rdi + 24], rdx + + jc rawAddLS_sq ; if overflow, substract q + + ; Compare with q + + mov rax, [rdi + 24] + cmp rax, [q + 24] + jc rawAddLS_done ; q is bigget so done. + jnz rawAddLS_sq ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 16] + jc rawAddLS_done ; q is bigget so done. + jnz rawAddLS_sq ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 8] + jc rawAddLS_done ; q is bigget so done. + jnz rawAddLS_sq ; q is lower + + mov rax, [rdi + 0] + cmp rax, [q + 0] + jc rawAddLS_done ; q is bigget so done. + jnz rawAddLS_sq ; q is lower + + ; If equal substract q +rawAddLS_sq: + + mov rax, [q + 0] + sub [rdi + 0], rax + + mov rax, [q + 8] + sbb [rdi + 8], rax + + mov rax, [q + 16] + sbb [rdi + 16], rax + + mov rax, [q + 24] + sbb [rdi + 24], rax + +rawAddLS_done: + ret + + + + + + + + + + + + + + + +;;;;;;;;;;;;;;;;;;;;;; +; sub +;;;;;;;;;;;;;;;;;;;;;; +; Substracts two elements of any kind +; Params: +; rsi <= Pointer to element 1 +; rdx <= Pointer to element 2 +; rdi <= Pointer to result +; Modified Registers: +; r8, r9, 10, r11, rax, rcx +;;;;;;;;;;;;;;;;;;;;;; +Fr_sub: + push rbp + push rsi + push rdx + mov rbp, rsp + mov rax, [rsi] + mov rcx, [rdx] + bt rax, 63 ; Check if is long first operand + jc sub_l1 + bt rcx, 63 ; Check if is long second operand + jc sub_s1l2 + +sub_s1s2: ; Both operands are short + + xor rdx, rdx + mov edx, eax + sub edx, ecx + jo sub_manageOverflow ; rsi already is the 64bits result + + mov [rdi], rdx ; not necessary to adjust so just save and return + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + +sub_manageOverflow: ; Do the operation in 64 bits + push rsi + movsx rsi, eax + movsx rdx, ecx + sub rsi, rdx + call rawCopyS2L + pop rsi + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + +sub_l1: + bt rcx, 63 ; Check if is short second operand + jc sub_l1l2 + +;;;;;;;; +sub_l1s2: + bt rax, 62 ; check if montgomery first + jc sub_l1ms2 +sub_l1ns2: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + add rsi, 8 + movsx rdx, ecx + add rdi, 8 + cmp rdx, 0 + + jns tmp_3 + neg rdx + call rawAddLS + sub rdi, 8 + sub rsi, 8 + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret +tmp_3: + call rawSubLS + sub rdi, 8 + sub rsi, 8 + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + +sub_l1ms2: + bt rcx, 62 ; check if montgomery second + jc sub_l1ms2m +sub_l1ms2n: + mov r11b, 0xC0 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toMontgomery + mov rdx, rdi + pop rdi + pop rsi + + + add rdi, 8 + add rsi, 8 + add rdx, 8 + call rawSubLL + sub rdi, 8 + sub rsi, 8 + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + +sub_l1ms2m: + mov r11b, 0xC0 + shl r11d, 24 + mov [rdi+4], r11d + + add rdi, 8 + add rsi, 8 + add rdx, 8 + call rawSubLL + sub rdi, 8 + sub rsi, 8 + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + +;;;;;;;; +sub_s1l2: + bt rcx, 62 ; check if montgomery first + jc sub_s1l2m +sub_s1l2n: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + cmp eax, 0 + + js tmp_4 + + ; First Operand is positive + push rsi + add rdi, 8 + movsx rsi, eax + add rdx, 8 + call rawSubSL + sub rdi, 8 + pop rsi + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + +tmp_4: ; First operand is negative + push rsi + lea rsi, [rdx + 8] + movsx rdx, eax + add rdi, 8 + neg rdx + call rawNegLS + sub rdi, 8 + pop rsi + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + +sub_s1l2m: + bt rax, 62 ; check if montgomery second + jc sub_s1ml2m +sub_s1nl2m: + mov r11b, 0xC0 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toMontgomery + mov rsi, rdi + pop rdi + pop rdx + + + add rdi, 8 + add rsi, 8 + add rdx, 8 + call rawSubLL + sub rdi, 8 + sub rsi, 8 + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + +sub_s1ml2m: + mov r11b, 0xC0 + shl r11d, 24 + mov [rdi+4], r11d + + add rdi, 8 + add rsi, 8 + add rdx, 8 + call rawSubLL + sub rdi, 8 + sub rsi, 8 + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + +;;;; +sub_l1l2: + bt rax, 62 ; check if montgomery first + jc sub_l1ml2 +sub_l1nl2: + bt rcx, 62 ; check if montgomery second + jc sub_l1nl2m +sub_l1nl2n: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + add rdi, 8 + add rsi, 8 + add rdx, 8 + call rawSubLL + sub rdi, 8 + sub rsi, 8 + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + +sub_l1nl2m: + mov r11b, 0xC0 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toMontgomery + mov rsi, rdi + pop rdi + pop rdx + + + add rdi, 8 + add rsi, 8 + add rdx, 8 + call rawSubLL + sub rdi, 8 + sub rsi, 8 + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + +sub_l1ml2: + bt rcx, 62 ; check if montgomery seconf + jc sub_l1ml2m +sub_l1ml2n: + mov r11b, 0xC0 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toMontgomery + mov rdx, rdi + pop rdi + pop rsi + + + add rdi, 8 + add rsi, 8 + add rdx, 8 + call rawSubLL + sub rdi, 8 + sub rsi, 8 + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + +sub_l1ml2m: + mov r11b, 0xC0 + shl r11d, 24 + mov [rdi+4], r11d + + add rdi, 8 + add rsi, 8 + add rdx, 8 + call rawSubLL + sub rdi, 8 + sub rsi, 8 + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + +;;;;;;;;;;;;;;;;;;;;;; +; rawSubLS +;;;;;;;;;;;;;;;;;;;;;; +; Substracts a short element from the long element +; Params: +; rdi <= Pointer to the long data of result +; rsi <= Pointer to the long data of element 1 where will be substracted +; rdx <= Value to be substracted +; [rdi] = [rsi] - rdx +; Modified Registers: +; rax +;;;;;;;;;;;;;;;;;;;;;; +rawSubLS: + ; Substract first digit + + mov rax, [rsi] + sub rax, rdx + mov [rdi] ,rax + mov rdx, 0 + + mov rax, [rsi + 8] + sbb rax, rdx + mov [rdi + 8], rax + + mov rax, [rsi + 16] + sbb rax, rdx + mov [rdi + 16], rax + + mov rax, [rsi + 24] + sbb rax, rdx + mov [rdi + 24], rax + + jnc rawSubLS_done ; if overflow, add q + + ; Add q +rawSubLS_aq: + + mov rax, [q + 0] + add [rdi + 0], rax + + mov rax, [q + 8] + adc [rdi + 8], rax + + mov rax, [q + 16] + adc [rdi + 16], rax + + mov rax, [q + 24] + adc [rdi + 24], rax + +rawSubLS_done: + ret + + +;;;;;;;;;;;;;;;;;;;;;; +; rawSubSL +;;;;;;;;;;;;;;;;;;;;;; +; Substracts a long element from a short element +; Params: +; rdi <= Pointer to the long data of result +; rsi <= Value from where will bo substracted +; rdx <= Pointer to long of the value to be substracted +; +; [rdi] = rsi - [rdx] +; Modified Registers: +; rax +;;;;;;;;;;;;;;;;;;;;;; +rawSubSL: + ; Substract first digit + sub rsi, [rdx] + mov [rdi] ,rsi + + + mov rax, 0 + sbb rax, [rdx + 8] + mov [rdi + 8], rax + + mov rax, 0 + sbb rax, [rdx + 16] + mov [rdi + 16], rax + + mov rax, 0 + sbb rax, [rdx + 24] + mov [rdi + 24], rax + + jnc rawSubSL_done ; if overflow, add q + + ; Add q +rawSubSL_aq: + + mov rax, [q + 0] + add [rdi + 0], rax + + mov rax, [q + 8] + adc [rdi + 8], rax + + mov rax, [q + 16] + adc [rdi + 16], rax + + mov rax, [q + 24] + adc [rdi + 24], rax + +rawSubSL_done: + ret + +;;;;;;;;;;;;;;;;;;;;;; +; rawSubLL +;;;;;;;;;;;;;;;;;;;;;; +; Substracts a long element from a short element +; Params: +; rdi <= Pointer to the long data of result +; rsi <= Pointer to long from where substracted +; rdx <= Pointer to long of the value to be substracted +; +; [rdi] = [rsi] - [rdx] +; Modified Registers: +; rax +;;;;;;;;;;;;;;;;;;;;;; +rawSubLL: +Fr_rawSub: + ; Substract first digit + + mov rax, [rsi + 0] + sub rax, [rdx + 0] + mov [rdi + 0], rax + + mov rax, [rsi + 8] + sbb rax, [rdx + 8] + mov [rdi + 8], rax + + mov rax, [rsi + 16] + sbb rax, [rdx + 16] + mov [rdi + 16], rax + + mov rax, [rsi + 24] + sbb rax, [rdx + 24] + mov [rdi + 24], rax + + jnc rawSubLL_done ; if overflow, add q + + ; Add q +rawSubLL_aq: + + mov rax, [q + 0] + add [rdi + 0], rax + + mov rax, [q + 8] + adc [rdi + 8], rax + + mov rax, [q + 16] + adc [rdi + 16], rax + + mov rax, [q + 24] + adc [rdi + 24], rax + +rawSubLL_done: + ret + +;;;;;;;;;;;;;;;;;;;;;; +; rawNegLS +;;;;;;;;;;;;;;;;;;;;;; +; Substracts a long element and a short element form 0 +; Params: +; rdi <= Pointer to the long data of result +; rsi <= Pointer to long from where substracted +; rdx <= short value to be substracted too +; +; [rdi] = -[rsi] - rdx +; Modified Registers: +; rax +;;;;;;;;;;;;;;;;;;;;;; +rawNegLS: + mov rax, [q] + sub rax, rdx + mov [rdi], rax + + mov rax, [q + 8 ] + sbb rax, 0 + mov [rdi + 8], rax + + mov rax, [q + 16 ] + sbb rax, 0 + mov [rdi + 16], rax + + mov rax, [q + 24 ] + sbb rax, 0 + mov [rdi + 24], rax + + setc dl + + + mov rax, [rdi + 0 ] + sub rax, [rsi + 0] + mov [rdi + 0], rax + + mov rax, [rdi + 8 ] + sbb rax, [rsi + 8] + mov [rdi + 8], rax + + mov rax, [rdi + 16 ] + sbb rax, [rsi + 16] + mov [rdi + 16], rax + + mov rax, [rdi + 24 ] + sbb rax, [rsi + 24] + mov [rdi + 24], rax + + + setc dh + or dl, dh + jz rawNegSL_done + + ; it is a negative value, so add q + + mov rax, [q + 0] + add [rdi + 0], rax + + mov rax, [q + 8] + adc [rdi + 8], rax + + mov rax, [q + 16] + adc [rdi + 16], rax + + mov rax, [q + 24] + adc [rdi + 24], rax + + +rawNegSL_done: + ret + + + + + + + +;;;;;;;;;;;;;;;;;;;;;; +; neg +;;;;;;;;;;;;;;;;;;;;;; +; Adds two elements of any kind +; Params: +; rsi <= Pointer to element to be negated +; rdi <= Pointer to result +; [rdi] = -[rsi] +;;;;;;;;;;;;;;;;;;;;;; +Fr_neg: + mov rax, [rsi] + bt rax, 63 ; Check if is short first operand + jc neg_l + +neg_s: ; Operand is short + + neg eax + jo neg_manageOverflow ; Check if overflow. (0x80000000 is the only case) + + mov [rdi], rax ; not necessary to adjust so just save and return + ret + +neg_manageOverflow: ; Do the operation in 64 bits + push rsi + movsx rsi, eax + neg rsi + call rawCopyS2L + pop rsi + ret + + + +neg_l: + mov [rdi], rax ; Copy the type + + add rdi, 8 + add rsi, 8 + call rawNegL + sub rdi, 8 + sub rsi, 8 + ret + + + +;;;;;;;;;;;;;;;;;;;;;; +; rawNeg +;;;;;;;;;;;;;;;;;;;;;; +; Negates a value +; Params: +; rdi <= Pointer to the long data of result +; rsi <= Pointer to the long data of element 1 +; +; [rdi] = - [rsi] +;;;;;;;;;;;;;;;;;;;;;; +rawNegL: +Fr_rawNeg: + ; Compare is zero + + xor rax, rax + + cmp [rsi + 0], rax + jnz doNegate + + cmp [rsi + 8], rax + jnz doNegate + + cmp [rsi + 16], rax + jnz doNegate + + cmp [rsi + 24], rax + jnz doNegate + + ; it's zero so just set to zero + + mov [rdi + 0], rax + + mov [rdi + 8], rax + + mov [rdi + 16], rax + + mov [rdi + 24], rax + + ret +doNegate: + + mov rax, [q + 0] + sub rax, [rsi + 0] + mov [rdi + 0], rax + + mov rax, [q + 8] + sbb rax, [rsi + 8] + mov [rdi + 8], rax + + mov rax, [q + 16] + sbb rax, [rsi + 16] + mov [rdi + 16], rax + + mov rax, [q + 24] + sbb rax, [rsi + 24] + mov [rdi + 24], rax + + ret + + + + + + + + + + + + + + + + + + + +;;;;;;;;;;;;;;;;;;;;;; +; square +;;;;;;;;;;;;;;;;;;;;;; +; Squares a field element +; Params: +; rsi <= Pointer to element 1 +; rdi <= Pointer to result +; [rdi] = [rsi] * [rsi] +; Modified Registers: +; r8, r9, 10, r11, rax, rcx +;;;;;;;;;;;;;;;;;;;;;; +Fr_square: + mov r8, [rsi] + bt r8, 63 ; Check if is short first operand + jc square_l1 + +square_s1: ; Both operands are short + + xor rax, rax + mov eax, r8d + imul eax + jo square_manageOverflow ; rsi already is the 64bits result + + mov [rdi], rax ; not necessary to adjust so just save and return + +square_manageOverflow: ; Do the operation in 64 bits + push rsi + movsx rax, r8d + imul rax + mov rsi, rax + call rawCopyS2L + pop rsi + + ret + +square_l1: + bt r8, 62 ; check if montgomery first + jc square_l1m +square_l1n: + mov r11b, 0xC0 + shl r11d, 24 + mov [rdi+4], r11d + + add rdi, 8 + add rsi, 8 + call Fr_rawMSquare + sub rdi, 8 + sub rsi, 8 + + + push rsi + add rdi, 8 + mov rsi, rdi + lea rdx, [R3] + call Fr_rawMMul + sub rdi, 8 + pop rsi + + ret + +square_l1m: + mov r11b, 0xC0 + shl r11d, 24 + mov [rdi+4], r11d + + add rdi, 8 + add rsi, 8 + call Fr_rawMSquare + sub rdi, 8 + sub rsi, 8 + + ret + + + +;;;;;;;;;;;;;;;;;;;;;; +; mul +;;;;;;;;;;;;;;;;;;;;;; +; Multiplies two elements of any kind +; Params: +; rsi <= Pointer to element 1 +; rdx <= Pointer to element 2 +; rdi <= Pointer to result +; [rdi] = [rsi] * [rdi] +; Modified Registers: +; r8, r9, 10, r11, rax, rcx +;;;;;;;;;;;;;;;;;;;;;; +Fr_mul: + mov r8, [rsi] + mov r9, [rdx] + bt r8, 63 ; Check if is short first operand + jc mul_l1 + bt r9, 63 ; Check if is short second operand + jc mul_s1l2 + +mul_s1s2: ; Both operands are short + + xor rax, rax + mov eax, r8d + imul r9d + jo mul_manageOverflow ; rsi already is the 64bits result + + mov [rdi], rax ; not necessary to adjust so just save and return + +mul_manageOverflow: ; Do the operation in 64 bits + push rsi + movsx rax, r8d + movsx rcx, r9d + imul rcx + mov rsi, rax + call rawCopyS2L + pop rsi + + ret + +mul_l1: + bt r9, 63 ; Check if is short second operand + jc mul_l1l2 + +;;;;;;;; +mul_l1s2: + bt r8, 62 ; check if montgomery first + jc mul_l1ms2 +mul_l1ns2: + bt r9, 62 ; check if montgomery first + jc mul_l1ns2m +mul_l1ns2n: + mov r11b, 0xC0 + shl r11d, 24 + mov [rdi+4], r11d + + push rsi + add rsi, 8 + movsx rdx, r9d + add rdi, 8 + cmp rdx, 0 + + jns tmp_5 + neg rdx + call Fr_rawMMul1 + mov rsi, rdi + call rawNegL + sub rdi, 8 + pop rsi + + jmp tmp_6 +tmp_5: + call Fr_rawMMul1 + sub rdi, 8 + pop rsi +tmp_6: + + + + push rsi + add rdi, 8 + mov rsi, rdi + lea rdx, [R3] + call Fr_rawMMul + sub rdi, 8 + pop rsi + + ret + + +mul_l1ns2m: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + add rdi, 8 + add rsi, 8 + add rdx, 8 + call Fr_rawMMul + sub rdi, 8 + sub rsi, 8 + + ret + + +mul_l1ms2: + bt r9, 62 ; check if montgomery second + jc mul_l1ms2m +mul_l1ms2n: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + push rsi + add rsi, 8 + movsx rdx, r9d + add rdi, 8 + cmp rdx, 0 + + jns tmp_7 + neg rdx + call Fr_rawMMul1 + mov rsi, rdi + call rawNegL + sub rdi, 8 + pop rsi + + jmp tmp_8 +tmp_7: + call Fr_rawMMul1 + sub rdi, 8 + pop rsi +tmp_8: + + + ret + +mul_l1ms2m: + mov r11b, 0xC0 + shl r11d, 24 + mov [rdi+4], r11d + + add rdi, 8 + add rsi, 8 + add rdx, 8 + call Fr_rawMMul + sub rdi, 8 + sub rsi, 8 + + ret + + +;;;;;;;; +mul_s1l2: + bt r8, 62 ; check if montgomery first + jc mul_s1ml2 +mul_s1nl2: + bt r9, 62 ; check if montgomery first + jc mul_s1nl2m +mul_s1nl2n: + mov r11b, 0xC0 + shl r11d, 24 + mov [rdi+4], r11d + + push rsi + lea rsi, [rdx + 8] + movsx rdx, r8d + add rdi, 8 + cmp rdx, 0 + + jns tmp_9 + neg rdx + call Fr_rawMMul1 + mov rsi, rdi + call rawNegL + sub rdi, 8 + pop rsi + + jmp tmp_10 +tmp_9: + call Fr_rawMMul1 + sub rdi, 8 + pop rsi +tmp_10: + + + + push rsi + add rdi, 8 + mov rsi, rdi + lea rdx, [R3] + call Fr_rawMMul + sub rdi, 8 + pop rsi + + ret + +mul_s1nl2m: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + push rsi + lea rsi, [rdx + 8] + movsx rdx, r8d + add rdi, 8 + cmp rdx, 0 + + jns tmp_11 + neg rdx + call Fr_rawMMul1 + mov rsi, rdi + call rawNegL + sub rdi, 8 + pop rsi + + jmp tmp_12 +tmp_11: + call Fr_rawMMul1 + sub rdi, 8 + pop rsi +tmp_12: + + + ret + +mul_s1ml2: + bt r9, 62 ; check if montgomery first + jc mul_s1ml2m +mul_s1ml2n: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + add rdi, 8 + add rsi, 8 + add rdx, 8 + call Fr_rawMMul + sub rdi, 8 + sub rsi, 8 + + ret + +mul_s1ml2m: + mov r11b, 0xC0 + shl r11d, 24 + mov [rdi+4], r11d + + add rdi, 8 + add rsi, 8 + add rdx, 8 + call Fr_rawMMul + sub rdi, 8 + sub rsi, 8 + + ret + +;;;; +mul_l1l2: + bt r8, 62 ; check if montgomery first + jc mul_l1ml2 +mul_l1nl2: + bt r9, 62 ; check if montgomery second + jc mul_l1nl2m +mul_l1nl2n: + mov r11b, 0xC0 + shl r11d, 24 + mov [rdi+4], r11d + + add rdi, 8 + add rsi, 8 + add rdx, 8 + call Fr_rawMMul + sub rdi, 8 + sub rsi, 8 + + + push rsi + add rdi, 8 + mov rsi, rdi + lea rdx, [R3] + call Fr_rawMMul + sub rdi, 8 + pop rsi + + ret + +mul_l1nl2m: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + add rdi, 8 + add rsi, 8 + add rdx, 8 + call Fr_rawMMul + sub rdi, 8 + sub rsi, 8 + + ret + +mul_l1ml2: + bt r9, 62 ; check if montgomery seconf + jc mul_l1ml2m +mul_l1ml2n: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + add rdi, 8 + add rsi, 8 + add rdx, 8 + call Fr_rawMMul + sub rdi, 8 + sub rsi, 8 + + ret + +mul_l1ml2m: + mov r11b, 0xC0 + shl r11d, 24 + mov [rdi+4], r11d + + add rdi, 8 + add rsi, 8 + add rdx, 8 + call Fr_rawMMul + sub rdi, 8 + sub rsi, 8 + + ret + + + + + + + + + + + + + + + + + + + +;;;;;;;;;;;;;;;;;;;;;; +; band +;;;;;;;;;;;;;;;;;;;;;; +; Adds two elements of any kind +; Params: +; rsi <= Pointer to element 1 +; rdx <= Pointer to element 2 +; rdi <= Pointer to result +; Modified Registers: +; r8, r9, 10, r11, rax, rcx +;;;;;;;;;;;;;;;;;;;;;; +Fr_band: + push rbp + push rsi + push rdx + mov rbp, rsp + mov rax, [rsi] + mov rcx, [rdx] + bt rax, 63 ; Check if is short first operand + jc and_l1 + bt rcx, 63 ; Check if is short second operand + jc and_s1l2 + +and_s1s2: + + cmp eax, 0 + + js tmp_13 + + cmp ecx, 0 + js tmp_13 + xor rdx, rdx ; both ops are positive so do the op and return + mov edx, eax + and edx, ecx + mov [rdi], rdx ; not necessary to adjust so just save and return + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + +tmp_13: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toLongNormal + mov rdx, rdi + pop rdi + pop rsi + + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toLongNormal + mov rsi, rdi + pop rdi + pop rdx + + + + mov rax, [rsi + 8] + and rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + and rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + and rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + and rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_15 ; q is bigget so done. + jnz tmp_14 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_15 ; q is bigget so done. + jnz tmp_14 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_15 ; q is bigget so done. + jnz tmp_14 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_15 ; q is bigget so done. + jnz tmp_14 ; q is lower + + ; If equal substract q +tmp_14: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_15: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + + + + +and_l1: + bt rcx, 63 ; Check if is short second operand + jc and_l1l2 + + +and_l1s2: + bt rax, 62 ; check if montgomery first + jc and_l1ms2 +and_l1ns2: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + mov rcx, [rdx] + cmp ecx, 0 + + js tmp_16 + movsx rax, ecx + and rax, [rsi +8] + mov [rdi+8], rax + + xor rax, rax + and rax, [rsi + 16]; + + mov [rdi + 16 ], rax; + + xor rax, rax + and rax, [rsi + 24]; + + mov [rdi + 24 ], rax; + + xor rax, rax + and rax, [rsi + 32]; + + and rax, [lboMask] ; + + mov [rdi + 32 ], rax; + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_18 ; q is bigget so done. + jnz tmp_17 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_18 ; q is bigget so done. + jnz tmp_17 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_18 ; q is bigget so done. + jnz tmp_17 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_18 ; q is bigget so done. + jnz tmp_17 ; q is lower + + ; If equal substract q +tmp_17: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_18: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + +tmp_16: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toLongNormal + mov rdx, rdi + pop rdi + pop rsi + + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + + mov rax, [rsi + 8] + and rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + and rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + and rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + and rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_20 ; q is bigget so done. + jnz tmp_19 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_20 ; q is bigget so done. + jnz tmp_19 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_20 ; q is bigget so done. + jnz tmp_19 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_20 ; q is bigget so done. + jnz tmp_19 ; q is lower + + ; If equal substract q +tmp_19: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_20: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + + +and_l1ms2: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toNormal + mov rsi, rdi + pop rdi + pop rdx + + + mov rcx, [rdx] + cmp ecx, 0 + + js tmp_21 + movsx rax, ecx + and rax, [rsi +8] + mov [rdi+8], rax + + xor rax, rax + and rax, [rsi + 16]; + + mov [rdi + 16 ], rax; + + xor rax, rax + and rax, [rsi + 24]; + + mov [rdi + 24 ], rax; + + xor rax, rax + and rax, [rsi + 32]; + + and rax, [lboMask] ; + + mov [rdi + 32 ], rax; + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_23 ; q is bigget so done. + jnz tmp_22 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_23 ; q is bigget so done. + jnz tmp_22 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_23 ; q is bigget so done. + jnz tmp_22 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_23 ; q is bigget so done. + jnz tmp_22 ; q is lower + + ; If equal substract q +tmp_22: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_23: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + +tmp_21: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toLongNormal + mov rdx, rdi + pop rdi + pop rsi + + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + + mov rax, [rsi + 8] + and rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + and rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + and rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + and rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_25 ; q is bigget so done. + jnz tmp_24 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_25 ; q is bigget so done. + jnz tmp_24 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_25 ; q is bigget so done. + jnz tmp_24 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_25 ; q is bigget so done. + jnz tmp_24 ; q is lower + + ; If equal substract q +tmp_24: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_25: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + + + +and_s1l2: + bt rcx, 62 ; check if montgomery first + jc and_s1l2m +and_s1l2n: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + mov eax, [rsi] + cmp eax, 0 + + js tmp_26 + and rax, [rdx +8] + mov [rdi+8], rax + + xor rax, rax + and rax, [rdx + 16] + + mov [rdi + 16 ], rax + + xor rax, rax + and rax, [rdx + 24] + + mov [rdi + 24 ], rax + + xor rax, rax + and rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_28 ; q is bigget so done. + jnz tmp_27 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_28 ; q is bigget so done. + jnz tmp_27 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_28 ; q is bigget so done. + jnz tmp_27 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_28 ; q is bigget so done. + jnz tmp_27 ; q is lower + + ; If equal substract q +tmp_27: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_28: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + +tmp_26: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toLongNormal + mov rsi, rdi + pop rdi + pop rdx + + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + + mov rax, [rsi + 8] + and rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + and rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + and rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + and rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_30 ; q is bigget so done. + jnz tmp_29 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_30 ; q is bigget so done. + jnz tmp_29 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_30 ; q is bigget so done. + jnz tmp_29 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_30 ; q is bigget so done. + jnz tmp_29 ; q is lower + + ; If equal substract q +tmp_29: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_30: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + + +and_s1l2m: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toNormal + mov rdx, rdi + pop rdi + pop rsi + + + mov eax, [rsi] + cmp eax, 0 + + js tmp_31 + and rax, [rdx +8] + mov [rdi+8], rax + + xor rax, rax + and rax, [rdx + 16] + + mov [rdi + 16 ], rax + + xor rax, rax + and rax, [rdx + 24] + + mov [rdi + 24 ], rax + + xor rax, rax + and rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_33 ; q is bigget so done. + jnz tmp_32 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_33 ; q is bigget so done. + jnz tmp_32 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_33 ; q is bigget so done. + jnz tmp_32 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_33 ; q is bigget so done. + jnz tmp_32 ; q is lower + + ; If equal substract q +tmp_32: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_33: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + +tmp_31: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toLongNormal + mov rsi, rdi + pop rdi + pop rdx + + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + + mov rax, [rsi + 8] + and rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + and rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + and rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + and rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_35 ; q is bigget so done. + jnz tmp_34 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_35 ; q is bigget so done. + jnz tmp_34 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_35 ; q is bigget so done. + jnz tmp_34 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_35 ; q is bigget so done. + jnz tmp_34 ; q is lower + + ; If equal substract q +tmp_34: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_35: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + + + +and_l1l2: + bt rax, 62 ; check if montgomery first + jc and_l1ml2 + bt rcx, 62 ; check if montgomery first + jc and_l1nl2m +and_l1nl2n: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + + mov rax, [rsi + 8] + and rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + and rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + and rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + and rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_37 ; q is bigget so done. + jnz tmp_36 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_37 ; q is bigget so done. + jnz tmp_36 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_37 ; q is bigget so done. + jnz tmp_36 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_37 ; q is bigget so done. + jnz tmp_36 ; q is lower + + ; If equal substract q +tmp_36: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_37: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + +and_l1nl2m: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toNormal + mov rdx, rdi + pop rdi + pop rsi + + + + mov rax, [rsi + 8] + and rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + and rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + and rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + and rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_39 ; q is bigget so done. + jnz tmp_38 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_39 ; q is bigget so done. + jnz tmp_38 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_39 ; q is bigget so done. + jnz tmp_38 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_39 ; q is bigget so done. + jnz tmp_38 ; q is lower + + ; If equal substract q +tmp_38: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_39: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + +and_l1ml2: + bt rcx, 62 ; check if montgomery first + jc and_l1ml2m +and_l1ml2n: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toNormal + mov rsi, rdi + pop rdi + pop rdx + + + + mov rax, [rsi + 8] + and rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + and rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + and rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + and rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_41 ; q is bigget so done. + jnz tmp_40 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_41 ; q is bigget so done. + jnz tmp_40 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_41 ; q is bigget so done. + jnz tmp_40 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_41 ; q is bigget so done. + jnz tmp_40 ; q is lower + + ; If equal substract q +tmp_40: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_41: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + +and_l1ml2m: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toNormal + mov rsi, rdi + pop rdi + pop rdx + + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toNormal + mov rdx, rdi + pop rdi + pop rsi + + + + mov rax, [rsi + 8] + and rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + and rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + and rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + and rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_43 ; q is bigget so done. + jnz tmp_42 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_43 ; q is bigget so done. + jnz tmp_42 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_43 ; q is bigget so done. + jnz tmp_42 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_43 ; q is bigget so done. + jnz tmp_42 ; q is lower + + ; If equal substract q +tmp_42: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_43: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + +;;;;;;;;;;;;;;;;;;;;;; +; bor +;;;;;;;;;;;;;;;;;;;;;; +; Adds two elements of any kind +; Params: +; rsi <= Pointer to element 1 +; rdx <= Pointer to element 2 +; rdi <= Pointer to result +; Modified Registers: +; r8, r9, 10, r11, rax, rcx +;;;;;;;;;;;;;;;;;;;;;; +Fr_bor: + push rbp + push rsi + push rdx + mov rbp, rsp + mov rax, [rsi] + mov rcx, [rdx] + bt rax, 63 ; Check if is short first operand + jc or_l1 + bt rcx, 63 ; Check if is short second operand + jc or_s1l2 + +or_s1s2: + + cmp eax, 0 + + js tmp_44 + + cmp ecx, 0 + js tmp_44 + xor rdx, rdx ; both ops are positive so do the op and return + mov edx, eax + or edx, ecx + mov [rdi], rdx ; not necessary to adjust so just save and return + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + +tmp_44: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toLongNormal + mov rdx, rdi + pop rdi + pop rsi + + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toLongNormal + mov rsi, rdi + pop rdi + pop rdx + + + + mov rax, [rsi + 8] + or rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + or rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + or rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + or rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_46 ; q is bigget so done. + jnz tmp_45 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_46 ; q is bigget so done. + jnz tmp_45 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_46 ; q is bigget so done. + jnz tmp_45 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_46 ; q is bigget so done. + jnz tmp_45 ; q is lower + + ; If equal substract q +tmp_45: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_46: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + + + + +or_l1: + bt rcx, 63 ; Check if is short second operand + jc or_l1l2 + + +or_l1s2: + bt rax, 62 ; check if montgomery first + jc or_l1ms2 +or_l1ns2: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + mov rcx, [rdx] + cmp ecx, 0 + + js tmp_47 + movsx rax, ecx + or rax, [rsi +8] + mov [rdi+8], rax + + xor rax, rax + or rax, [rsi + 16]; + + mov [rdi + 16 ], rax; + + xor rax, rax + or rax, [rsi + 24]; + + mov [rdi + 24 ], rax; + + xor rax, rax + or rax, [rsi + 32]; + + and rax, [lboMask] ; + + mov [rdi + 32 ], rax; + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_49 ; q is bigget so done. + jnz tmp_48 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_49 ; q is bigget so done. + jnz tmp_48 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_49 ; q is bigget so done. + jnz tmp_48 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_49 ; q is bigget so done. + jnz tmp_48 ; q is lower + + ; If equal substract q +tmp_48: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_49: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + +tmp_47: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toLongNormal + mov rdx, rdi + pop rdi + pop rsi + + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + + mov rax, [rsi + 8] + or rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + or rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + or rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + or rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_51 ; q is bigget so done. + jnz tmp_50 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_51 ; q is bigget so done. + jnz tmp_50 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_51 ; q is bigget so done. + jnz tmp_50 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_51 ; q is bigget so done. + jnz tmp_50 ; q is lower + + ; If equal substract q +tmp_50: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_51: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + + +or_l1ms2: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toNormal + mov rsi, rdi + pop rdi + pop rdx + + + mov rcx, [rdx] + cmp ecx, 0 + + js tmp_52 + movsx rax, ecx + or rax, [rsi +8] + mov [rdi+8], rax + + xor rax, rax + or rax, [rsi + 16]; + + mov [rdi + 16 ], rax; + + xor rax, rax + or rax, [rsi + 24]; + + mov [rdi + 24 ], rax; + + xor rax, rax + or rax, [rsi + 32]; + + and rax, [lboMask] ; + + mov [rdi + 32 ], rax; + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_54 ; q is bigget so done. + jnz tmp_53 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_54 ; q is bigget so done. + jnz tmp_53 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_54 ; q is bigget so done. + jnz tmp_53 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_54 ; q is bigget so done. + jnz tmp_53 ; q is lower + + ; If equal substract q +tmp_53: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_54: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + +tmp_52: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toLongNormal + mov rdx, rdi + pop rdi + pop rsi + + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + + mov rax, [rsi + 8] + or rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + or rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + or rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + or rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_56 ; q is bigget so done. + jnz tmp_55 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_56 ; q is bigget so done. + jnz tmp_55 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_56 ; q is bigget so done. + jnz tmp_55 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_56 ; q is bigget so done. + jnz tmp_55 ; q is lower + + ; If equal substract q +tmp_55: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_56: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + + + +or_s1l2: + bt rcx, 62 ; check if montgomery first + jc or_s1l2m +or_s1l2n: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + mov eax, [rsi] + cmp eax, 0 + + js tmp_57 + or rax, [rdx +8] + mov [rdi+8], rax + + xor rax, rax + or rax, [rdx + 16] + + mov [rdi + 16 ], rax + + xor rax, rax + or rax, [rdx + 24] + + mov [rdi + 24 ], rax + + xor rax, rax + or rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_59 ; q is bigget so done. + jnz tmp_58 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_59 ; q is bigget so done. + jnz tmp_58 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_59 ; q is bigget so done. + jnz tmp_58 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_59 ; q is bigget so done. + jnz tmp_58 ; q is lower + + ; If equal substract q +tmp_58: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_59: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + +tmp_57: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toLongNormal + mov rsi, rdi + pop rdi + pop rdx + + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + + mov rax, [rsi + 8] + or rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + or rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + or rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + or rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_61 ; q is bigget so done. + jnz tmp_60 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_61 ; q is bigget so done. + jnz tmp_60 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_61 ; q is bigget so done. + jnz tmp_60 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_61 ; q is bigget so done. + jnz tmp_60 ; q is lower + + ; If equal substract q +tmp_60: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_61: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + + +or_s1l2m: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toNormal + mov rdx, rdi + pop rdi + pop rsi + + + mov eax, [rsi] + cmp eax, 0 + + js tmp_62 + or rax, [rdx +8] + mov [rdi+8], rax + + xor rax, rax + or rax, [rdx + 16] + + mov [rdi + 16 ], rax + + xor rax, rax + or rax, [rdx + 24] + + mov [rdi + 24 ], rax + + xor rax, rax + or rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_64 ; q is bigget so done. + jnz tmp_63 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_64 ; q is bigget so done. + jnz tmp_63 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_64 ; q is bigget so done. + jnz tmp_63 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_64 ; q is bigget so done. + jnz tmp_63 ; q is lower + + ; If equal substract q +tmp_63: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_64: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + +tmp_62: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toLongNormal + mov rsi, rdi + pop rdi + pop rdx + + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + + mov rax, [rsi + 8] + or rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + or rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + or rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + or rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_66 ; q is bigget so done. + jnz tmp_65 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_66 ; q is bigget so done. + jnz tmp_65 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_66 ; q is bigget so done. + jnz tmp_65 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_66 ; q is bigget so done. + jnz tmp_65 ; q is lower + + ; If equal substract q +tmp_65: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_66: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + + + +or_l1l2: + bt rax, 62 ; check if montgomery first + jc or_l1ml2 + bt rcx, 62 ; check if montgomery first + jc or_l1nl2m +or_l1nl2n: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + + mov rax, [rsi + 8] + or rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + or rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + or rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + or rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_68 ; q is bigget so done. + jnz tmp_67 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_68 ; q is bigget so done. + jnz tmp_67 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_68 ; q is bigget so done. + jnz tmp_67 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_68 ; q is bigget so done. + jnz tmp_67 ; q is lower + + ; If equal substract q +tmp_67: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_68: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + +or_l1nl2m: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toNormal + mov rdx, rdi + pop rdi + pop rsi + + + + mov rax, [rsi + 8] + or rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + or rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + or rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + or rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_70 ; q is bigget so done. + jnz tmp_69 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_70 ; q is bigget so done. + jnz tmp_69 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_70 ; q is bigget so done. + jnz tmp_69 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_70 ; q is bigget so done. + jnz tmp_69 ; q is lower + + ; If equal substract q +tmp_69: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_70: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + +or_l1ml2: + bt rcx, 62 ; check if montgomery first + jc or_l1ml2m +or_l1ml2n: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toNormal + mov rsi, rdi + pop rdi + pop rdx + + + + mov rax, [rsi + 8] + or rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + or rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + or rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + or rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_72 ; q is bigget so done. + jnz tmp_71 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_72 ; q is bigget so done. + jnz tmp_71 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_72 ; q is bigget so done. + jnz tmp_71 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_72 ; q is bigget so done. + jnz tmp_71 ; q is lower + + ; If equal substract q +tmp_71: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_72: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + +or_l1ml2m: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toNormal + mov rsi, rdi + pop rdi + pop rdx + + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toNormal + mov rdx, rdi + pop rdi + pop rsi + + + + mov rax, [rsi + 8] + or rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + or rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + or rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + or rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_74 ; q is bigget so done. + jnz tmp_73 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_74 ; q is bigget so done. + jnz tmp_73 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_74 ; q is bigget so done. + jnz tmp_73 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_74 ; q is bigget so done. + jnz tmp_73 ; q is lower + + ; If equal substract q +tmp_73: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_74: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + +;;;;;;;;;;;;;;;;;;;;;; +; bxor +;;;;;;;;;;;;;;;;;;;;;; +; Adds two elements of any kind +; Params: +; rsi <= Pointer to element 1 +; rdx <= Pointer to element 2 +; rdi <= Pointer to result +; Modified Registers: +; r8, r9, 10, r11, rax, rcx +;;;;;;;;;;;;;;;;;;;;;; +Fr_bxor: + push rbp + push rsi + push rdx + mov rbp, rsp + mov rax, [rsi] + mov rcx, [rdx] + bt rax, 63 ; Check if is short first operand + jc xor_l1 + bt rcx, 63 ; Check if is short second operand + jc xor_s1l2 + +xor_s1s2: + + cmp eax, 0 + + js tmp_75 + + cmp ecx, 0 + js tmp_75 + xor rdx, rdx ; both ops are positive so do the op and return + mov edx, eax + xor edx, ecx + mov [rdi], rdx ; not necessary to adjust so just save and return + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + +tmp_75: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toLongNormal + mov rdx, rdi + pop rdi + pop rsi + + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toLongNormal + mov rsi, rdi + pop rdi + pop rdx + + + + mov rax, [rsi + 8] + xor rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + xor rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + xor rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + xor rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_77 ; q is bigget so done. + jnz tmp_76 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_77 ; q is bigget so done. + jnz tmp_76 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_77 ; q is bigget so done. + jnz tmp_76 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_77 ; q is bigget so done. + jnz tmp_76 ; q is lower + + ; If equal substract q +tmp_76: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_77: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + + + + +xor_l1: + bt rcx, 63 ; Check if is short second operand + jc xor_l1l2 + + +xor_l1s2: + bt rax, 62 ; check if montgomery first + jc xor_l1ms2 +xor_l1ns2: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + mov rcx, [rdx] + cmp ecx, 0 + + js tmp_78 + movsx rax, ecx + xor rax, [rsi +8] + mov [rdi+8], rax + + xor rax, rax + xor rax, [rsi + 16]; + + mov [rdi + 16 ], rax; + + xor rax, rax + xor rax, [rsi + 24]; + + mov [rdi + 24 ], rax; + + xor rax, rax + xor rax, [rsi + 32]; + + and rax, [lboMask] ; + + mov [rdi + 32 ], rax; + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_80 ; q is bigget so done. + jnz tmp_79 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_80 ; q is bigget so done. + jnz tmp_79 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_80 ; q is bigget so done. + jnz tmp_79 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_80 ; q is bigget so done. + jnz tmp_79 ; q is lower + + ; If equal substract q +tmp_79: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_80: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + +tmp_78: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toLongNormal + mov rdx, rdi + pop rdi + pop rsi + + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + + mov rax, [rsi + 8] + xor rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + xor rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + xor rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + xor rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_82 ; q is bigget so done. + jnz tmp_81 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_82 ; q is bigget so done. + jnz tmp_81 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_82 ; q is bigget so done. + jnz tmp_81 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_82 ; q is bigget so done. + jnz tmp_81 ; q is lower + + ; If equal substract q +tmp_81: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_82: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + + +xor_l1ms2: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toNormal + mov rsi, rdi + pop rdi + pop rdx + + + mov rcx, [rdx] + cmp ecx, 0 + + js tmp_83 + movsx rax, ecx + xor rax, [rsi +8] + mov [rdi+8], rax + + xor rax, rax + xor rax, [rsi + 16]; + + mov [rdi + 16 ], rax; + + xor rax, rax + xor rax, [rsi + 24]; + + mov [rdi + 24 ], rax; + + xor rax, rax + xor rax, [rsi + 32]; + + and rax, [lboMask] ; + + mov [rdi + 32 ], rax; + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_85 ; q is bigget so done. + jnz tmp_84 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_85 ; q is bigget so done. + jnz tmp_84 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_85 ; q is bigget so done. + jnz tmp_84 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_85 ; q is bigget so done. + jnz tmp_84 ; q is lower + + ; If equal substract q +tmp_84: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_85: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + +tmp_83: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toLongNormal + mov rdx, rdi + pop rdi + pop rsi + + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + + mov rax, [rsi + 8] + xor rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + xor rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + xor rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + xor rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_87 ; q is bigget so done. + jnz tmp_86 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_87 ; q is bigget so done. + jnz tmp_86 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_87 ; q is bigget so done. + jnz tmp_86 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_87 ; q is bigget so done. + jnz tmp_86 ; q is lower + + ; If equal substract q +tmp_86: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_87: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + + + +xor_s1l2: + bt rcx, 62 ; check if montgomery first + jc xor_s1l2m +xor_s1l2n: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + mov eax, [rsi] + cmp eax, 0 + + js tmp_88 + xor rax, [rdx +8] + mov [rdi+8], rax + + xor rax, rax + xor rax, [rdx + 16] + + mov [rdi + 16 ], rax + + xor rax, rax + xor rax, [rdx + 24] + + mov [rdi + 24 ], rax + + xor rax, rax + xor rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_90 ; q is bigget so done. + jnz tmp_89 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_90 ; q is bigget so done. + jnz tmp_89 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_90 ; q is bigget so done. + jnz tmp_89 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_90 ; q is bigget so done. + jnz tmp_89 ; q is lower + + ; If equal substract q +tmp_89: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_90: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + +tmp_88: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toLongNormal + mov rsi, rdi + pop rdi + pop rdx + + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + + mov rax, [rsi + 8] + xor rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + xor rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + xor rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + xor rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_92 ; q is bigget so done. + jnz tmp_91 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_92 ; q is bigget so done. + jnz tmp_91 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_92 ; q is bigget so done. + jnz tmp_91 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_92 ; q is bigget so done. + jnz tmp_91 ; q is lower + + ; If equal substract q +tmp_91: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_92: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + + +xor_s1l2m: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toNormal + mov rdx, rdi + pop rdi + pop rsi + + + mov eax, [rsi] + cmp eax, 0 + + js tmp_93 + xor rax, [rdx +8] + mov [rdi+8], rax + + xor rax, rax + xor rax, [rdx + 16] + + mov [rdi + 16 ], rax + + xor rax, rax + xor rax, [rdx + 24] + + mov [rdi + 24 ], rax + + xor rax, rax + xor rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_95 ; q is bigget so done. + jnz tmp_94 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_95 ; q is bigget so done. + jnz tmp_94 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_95 ; q is bigget so done. + jnz tmp_94 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_95 ; q is bigget so done. + jnz tmp_94 ; q is lower + + ; If equal substract q +tmp_94: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_95: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + +tmp_93: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toLongNormal + mov rsi, rdi + pop rdi + pop rdx + + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + + mov rax, [rsi + 8] + xor rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + xor rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + xor rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + xor rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_97 ; q is bigget so done. + jnz tmp_96 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_97 ; q is bigget so done. + jnz tmp_96 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_97 ; q is bigget so done. + jnz tmp_96 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_97 ; q is bigget so done. + jnz tmp_96 ; q is lower + + ; If equal substract q +tmp_96: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_97: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + + + +xor_l1l2: + bt rax, 62 ; check if montgomery first + jc xor_l1ml2 + bt rcx, 62 ; check if montgomery first + jc xor_l1nl2m +xor_l1nl2n: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + + mov rax, [rsi + 8] + xor rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + xor rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + xor rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + xor rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_99 ; q is bigget so done. + jnz tmp_98 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_99 ; q is bigget so done. + jnz tmp_98 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_99 ; q is bigget so done. + jnz tmp_98 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_99 ; q is bigget so done. + jnz tmp_98 ; q is lower + + ; If equal substract q +tmp_98: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_99: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + +xor_l1nl2m: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toNormal + mov rdx, rdi + pop rdi + pop rsi + + + + mov rax, [rsi + 8] + xor rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + xor rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + xor rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + xor rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_101 ; q is bigget so done. + jnz tmp_100 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_101 ; q is bigget so done. + jnz tmp_100 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_101 ; q is bigget so done. + jnz tmp_100 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_101 ; q is bigget so done. + jnz tmp_100 ; q is lower + + ; If equal substract q +tmp_100: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_101: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + +xor_l1ml2: + bt rcx, 62 ; check if montgomery first + jc xor_l1ml2m +xor_l1ml2n: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toNormal + mov rsi, rdi + pop rdi + pop rdx + + + + mov rax, [rsi + 8] + xor rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + xor rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + xor rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + xor rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_103 ; q is bigget so done. + jnz tmp_102 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_103 ; q is bigget so done. + jnz tmp_102 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_103 ; q is bigget so done. + jnz tmp_102 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_103 ; q is bigget so done. + jnz tmp_102 ; q is lower + + ; If equal substract q +tmp_102: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_103: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + +xor_l1ml2m: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toNormal + mov rsi, rdi + pop rdi + pop rdx + + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toNormal + mov rdx, rdi + pop rdi + pop rsi + + + + mov rax, [rsi + 8] + xor rax, [rdx + 8] + + mov [rdi + 8 ], rax + + mov rax, [rsi + 16] + xor rax, [rdx + 16] + + mov [rdi + 16 ], rax + + mov rax, [rsi + 24] + xor rax, [rdx + 24] + + mov [rdi + 24 ], rax + + mov rax, [rsi + 32] + xor rax, [rdx + 32] + + and rax, [lboMask] + + mov [rdi + 32 ], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_105 ; q is bigget so done. + jnz tmp_104 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_105 ; q is bigget so done. + jnz tmp_104 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_105 ; q is bigget so done. + jnz tmp_104 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_105 ; q is bigget so done. + jnz tmp_104 ; q is lower + + ; If equal substract q +tmp_104: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_105: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + + +;;;;;;;;;;;;;;;;;;;;;; +; bnot +;;;;;;;;;;;;;;;;;;;;;; +; Adds two elements of any kind +; Params: +; rsi <= Pointer to element 1 +; rdi <= Pointer to result +; Modified Registers: +; r8, r9, 10, r11, rax, rcx +;;;;;;;;;;;;;;;;;;;;;; +Fr_bnot: + push rbp + push rsi + push rdx + mov rbp, rsp + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + + mov rax, [rsi] + bt rax, 63 ; Check if is long operand + jc bnot_l1 +bnot_s: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toLongNormal + mov rsi, rdi + pop rdi + pop rdx + + jmp bnot_l1n + +bnot_l1: + bt rax, 62 ; check if montgomery first + jnc bnot_l1n + +bnot_l1m: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toNormal + mov rsi, rdi + pop rdi + pop rdx + + +bnot_l1n: + + mov rax, [rsi + 8] + not rax + + mov [rdi + 8], rax + + mov rax, [rsi + 16] + not rax + + mov [rdi + 16], rax + + mov rax, [rsi + 24] + not rax + + mov [rdi + 24], rax + + mov rax, [rsi + 32] + not rax + + and rax, [lboMask] + + mov [rdi + 32], rax + + + + + + ; Compare with q + + mov rax, [rdi + 32] + cmp rax, [q + 24] + jc tmp_107 ; q is bigget so done. + jnz tmp_106 ; q is lower + + mov rax, [rdi + 24] + cmp rax, [q + 16] + jc tmp_107 ; q is bigget so done. + jnz tmp_106 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 8] + jc tmp_107 ; q is bigget so done. + jnz tmp_106 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 0] + jc tmp_107 ; q is bigget so done. + jnz tmp_106 ; q is lower + + ; If equal substract q +tmp_106: + + mov rax, [q + 0] + sub [rdi + 8], rax + + mov rax, [q + 8] + sbb [rdi + 16], rax + + mov rax, [q + 16] + sbb [rdi + 24], rax + + mov rax, [q + 24] + sbb [rdi + 32], rax + +tmp_107: + + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + + +;;;;;;;;;;;;;;;;;;;;;; +; rawShr +;;;;;;;;;;;;;;;;;;;;;; +; Adds two elements of any kind +; Params: +; rsi <= Pointer to element 1 +; rdx <= how much is shifted +; rdi <= Pointer to result +; Modified Registers: +; r8, r9, 10, r11, rax, rcx +;;;;;;;;;;;;;;;;;;;;;; +rawShr: + cmp rdx, 0 + je Fr_rawCopy + + cmp rdx, 254 + jae Fr_rawZero + +rawShr_nz: + mov r8, rdx + shr r8,6 + mov rcx, rdx + and rcx, 0x3F + jz rawShr_aligned + mov ch, 64 + sub ch, cl + + mov r9, 1 + rol cx, 8 + shl r9, cl + rol cx, 8 + sub r9, 1 + mov r10, r9 + not r10 + + + cmp r8, 3 + jae rawShr_if2_0 + + mov rax, [rsi + r8*8 + 0 ] + shr rax, cl + and rax, r9 + mov r11, [rsi + r8*8 + 8 ] + rol cx, 8 + shl r11, cl + rol cx, 8 + and r11, r10 + or rax, r11 + mov [rdi + 0], rax + + jmp rawShr_endif_0 +rawShr_if2_0: + jne rawShr_else_0 + + mov rax, [rsi + r8*8 + 0 ] + shr rax, cl + and rax, r9 + mov [rdi + 0], rax + + jmp rawShr_endif_0 +rawShr_else_0: + xor rax, rax + mov [rdi + 0], rax +rawShr_endif_0: + + cmp r8, 2 + jae rawShr_if2_1 + + mov rax, [rsi + r8*8 + 8 ] + shr rax, cl + and rax, r9 + mov r11, [rsi + r8*8 + 16 ] + rol cx, 8 + shl r11, cl + rol cx, 8 + and r11, r10 + or rax, r11 + mov [rdi + 8], rax + + jmp rawShr_endif_1 +rawShr_if2_1: + jne rawShr_else_1 + + mov rax, [rsi + r8*8 + 8 ] + shr rax, cl + and rax, r9 + mov [rdi + 8], rax + + jmp rawShr_endif_1 +rawShr_else_1: + xor rax, rax + mov [rdi + 8], rax +rawShr_endif_1: + + cmp r8, 1 + jae rawShr_if2_2 + + mov rax, [rsi + r8*8 + 16 ] + shr rax, cl + and rax, r9 + mov r11, [rsi + r8*8 + 24 ] + rol cx, 8 + shl r11, cl + rol cx, 8 + and r11, r10 + or rax, r11 + mov [rdi + 16], rax + + jmp rawShr_endif_2 +rawShr_if2_2: + jne rawShr_else_2 + + mov rax, [rsi + r8*8 + 16 ] + shr rax, cl + and rax, r9 + mov [rdi + 16], rax + + jmp rawShr_endif_2 +rawShr_else_2: + xor rax, rax + mov [rdi + 16], rax +rawShr_endif_2: + + cmp r8, 0 + jae rawShr_if2_3 + + mov rax, [rsi + r8*8 + 24 ] + shr rax, cl + and rax, r9 + mov r11, [rsi + r8*8 + 32 ] + rol cx, 8 + shl r11, cl + rol cx, 8 + and r11, r10 + or rax, r11 + mov [rdi + 24], rax + + jmp rawShr_endif_3 +rawShr_if2_3: + jne rawShr_else_3 + + mov rax, [rsi + r8*8 + 24 ] + shr rax, cl + and rax, r9 + mov [rdi + 24], rax + + jmp rawShr_endif_3 +rawShr_else_3: + xor rax, rax + mov [rdi + 24], rax +rawShr_endif_3: + + + ret + +rawShr_aligned: + + cmp r8, 3 + ja rawShr_if3_0 + mov rax, [rsi + r8*8 + 0 ] + mov [rdi + 0], rax + jmp rawShr_endif3_0 +rawShr_if3_0: + xor rax, rax + mov [rdi + 0], rax +rawShr_endif3_0: + + cmp r8, 2 + ja rawShr_if3_1 + mov rax, [rsi + r8*8 + 8 ] + mov [rdi + 8], rax + jmp rawShr_endif3_1 +rawShr_if3_1: + xor rax, rax + mov [rdi + 8], rax +rawShr_endif3_1: + + cmp r8, 1 + ja rawShr_if3_2 + mov rax, [rsi + r8*8 + 16 ] + mov [rdi + 16], rax + jmp rawShr_endif3_2 +rawShr_if3_2: + xor rax, rax + mov [rdi + 16], rax +rawShr_endif3_2: + + cmp r8, 0 + ja rawShr_if3_3 + mov rax, [rsi + r8*8 + 24 ] + mov [rdi + 24], rax + jmp rawShr_endif3_3 +rawShr_if3_3: + xor rax, rax + mov [rdi + 24], rax +rawShr_endif3_3: + + ret + + +;;;;;;;;;;;;;;;;;;;;;; +; rawShl +;;;;;;;;;;;;;;;;;;;;;; +; Adds two elements of any kind +; Params: +; rsi <= Pointer to element 1 +; rdx <= how much is shifted +; rdi <= Pointer to result +; Modified Registers: +; r8, r9, 10, r11, rax, rcx +;;;;;;;;;;;;;;;;;;;;;; +rawShl: + cmp rdx, 0 + je Fr_rawCopy + + cmp rdx, 254 + jae Fr_rawZero + + mov r8, rdx + shr r8,6 + mov rcx, rdx + and rcx, 0x3F + jz rawShl_aligned + mov ch, 64 + sub ch, cl + + + mov r10, 1 + shl r10, cl + sub r10, 1 + mov r9, r10 + not r9 + + mov rdx, rsi + mov rax, r8 + shl rax, 3 + sub rdx, rax + + + cmp r8, 3 + jae rawShl_if2_3 + + mov rax, [rdx + 24 ] + shl rax, cl + and rax, r9 + mov r11, [rdx + 16 ] + rol cx, 8 + shr r11, cl + rol cx, 8 + and r11, r10 + or rax, r11 + + and rax, [lboMask] + + + mov [rdi + 24], rax + + jmp rawShl_endif_3 +rawShl_if2_3: + jne rawShl_else_3 + + mov rax, [rdx + 24 ] + shl rax, cl + and rax, r9 + + and rax, [lboMask] + + + mov [rdi + 24], rax + + jmp rawShl_endif_3 +rawShl_else_3: + xor rax, rax + mov [rdi + 24], rax +rawShl_endif_3: + + cmp r8, 2 + jae rawShl_if2_2 + + mov rax, [rdx + 16 ] + shl rax, cl + and rax, r9 + mov r11, [rdx + 8 ] + rol cx, 8 + shr r11, cl + rol cx, 8 + and r11, r10 + or rax, r11 + + + mov [rdi + 16], rax + + jmp rawShl_endif_2 +rawShl_if2_2: + jne rawShl_else_2 + + mov rax, [rdx + 16 ] + shl rax, cl + and rax, r9 + + + mov [rdi + 16], rax + + jmp rawShl_endif_2 +rawShl_else_2: + xor rax, rax + mov [rdi + 16], rax +rawShl_endif_2: + + cmp r8, 1 + jae rawShl_if2_1 + + mov rax, [rdx + 8 ] + shl rax, cl + and rax, r9 + mov r11, [rdx + 0 ] + rol cx, 8 + shr r11, cl + rol cx, 8 + and r11, r10 + or rax, r11 + + + mov [rdi + 8], rax + + jmp rawShl_endif_1 +rawShl_if2_1: + jne rawShl_else_1 + + mov rax, [rdx + 8 ] + shl rax, cl + and rax, r9 + + + mov [rdi + 8], rax + + jmp rawShl_endif_1 +rawShl_else_1: + xor rax, rax + mov [rdi + 8], rax +rawShl_endif_1: + + cmp r8, 0 + jae rawShl_if2_0 + + mov rax, [rdx + 0 ] + shl rax, cl + and rax, r9 + mov r11, [rdx + -8 ] + rol cx, 8 + shr r11, cl + rol cx, 8 + and r11, r10 + or rax, r11 + + + mov [rdi + 0], rax + + jmp rawShl_endif_0 +rawShl_if2_0: + jne rawShl_else_0 + + mov rax, [rdx + 0 ] + shl rax, cl + and rax, r9 + + + mov [rdi + 0], rax + + jmp rawShl_endif_0 +rawShl_else_0: + xor rax, rax + mov [rdi + 0], rax +rawShl_endif_0: + + + + + + + ; Compare with q + + mov rax, [rdi + 24] + cmp rax, [q + 24] + jc tmp_109 ; q is bigget so done. + jnz tmp_108 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 16] + jc tmp_109 ; q is bigget so done. + jnz tmp_108 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 8] + jc tmp_109 ; q is bigget so done. + jnz tmp_108 ; q is lower + + mov rax, [rdi + 0] + cmp rax, [q + 0] + jc tmp_109 ; q is bigget so done. + jnz tmp_108 ; q is lower + + ; If equal substract q +tmp_108: + + mov rax, [q + 0] + sub [rdi + 0], rax + + mov rax, [q + 8] + sbb [rdi + 8], rax + + mov rax, [q + 16] + sbb [rdi + 16], rax + + mov rax, [q + 24] + sbb [rdi + 24], rax + +tmp_109: + + ret; + +rawShl_aligned: + mov rdx, rsi + mov rax, r8 + shl rax, 3 + sub rdx, rax + + + cmp r8, 3 + ja rawShl_if3_3 + mov rax, [rdx + 24 ] + + and rax, [lboMask] + + mov [rdi + 24], rax + jmp rawShl_endif3_3 +rawShl_if3_3: + xor rax, rax + mov [rdi + 24], rax +rawShl_endif3_3: + + cmp r8, 2 + ja rawShl_if3_2 + mov rax, [rdx + 16 ] + + mov [rdi + 16], rax + jmp rawShl_endif3_2 +rawShl_if3_2: + xor rax, rax + mov [rdi + 16], rax +rawShl_endif3_2: + + cmp r8, 1 + ja rawShl_if3_1 + mov rax, [rdx + 8 ] + + mov [rdi + 8], rax + jmp rawShl_endif3_1 +rawShl_if3_1: + xor rax, rax + mov [rdi + 8], rax +rawShl_endif3_1: + + cmp r8, 0 + ja rawShl_if3_0 + mov rax, [rdx + 0 ] + + mov [rdi + 0], rax + jmp rawShl_endif3_0 +rawShl_if3_0: + xor rax, rax + mov [rdi + 0], rax +rawShl_endif3_0: + + + + + + ; Compare with q + + mov rax, [rdi + 24] + cmp rax, [q + 24] + jc tmp_111 ; q is bigget so done. + jnz tmp_110 ; q is lower + + mov rax, [rdi + 16] + cmp rax, [q + 16] + jc tmp_111 ; q is bigget so done. + jnz tmp_110 ; q is lower + + mov rax, [rdi + 8] + cmp rax, [q + 8] + jc tmp_111 ; q is bigget so done. + jnz tmp_110 ; q is lower + + mov rax, [rdi + 0] + cmp rax, [q + 0] + jc tmp_111 ; q is bigget so done. + jnz tmp_110 ; q is lower + + ; If equal substract q +tmp_110: + + mov rax, [q + 0] + sub [rdi + 0], rax + + mov rax, [q + 8] + sbb [rdi + 8], rax + + mov rax, [q + 16] + sbb [rdi + 16], rax + + mov rax, [q + 24] + sbb [rdi + 24], rax + +tmp_111: + + ret + + + + + + +;;;;;;;;;;;;;;;;;;;;;; +; shr +;;;;;;;;;;;;;;;;;;;;;; +; Adds two elements of any kind +; Params: +; rsi <= Pointer to element 1 +; rdx <= Pointer to element 2 +; rdi <= Pointer to result +; Modified Registers: +; r8, r9, 10, r11, rax, rcx +;;;;;;;;;;;;;;;;;;;;;; +Fr_shr: + push rbp + push rsi + push rdi + push rdx + mov rbp, rsp + + + + + + + mov rcx, [rdx] + bt rcx, 63 ; Check if is short second operand + jnc tmp_112 + + ; long 2 + bt rcx, 62 ; Check if is montgomery second operand + jnc tmp_113 + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toNormal + mov rdx, rdi + pop rdi + pop rsi + +tmp_113: + mov rcx, [rdx + 8] + cmp rcx, 254 + jae tmp_114 + xor rax, rax + + cmp [rdx + 16], rax + jnz tmp_114 + + cmp [rdx + 24], rax + jnz tmp_114 + + cmp [rdx + 32], rax + jnz tmp_114 + + mov rdx, rcx + jmp do_shr + +tmp_114: + mov rcx, [q] + sub rcx, [rdx+8] + cmp rcx, 254 + jae setzero + mov rax, [q] + sub rax, [rdx+8] + + mov rax, [q+ 8] + sbb rax, [rdx + 16] + jnz setzero + + mov rax, [q+ 16] + sbb rax, [rdx + 24] + jnz setzero + + mov rax, [q+ 24] + sbb rax, [rdx + 32] + jnz setzero + + mov rdx, rcx + jmp do_shl + +tmp_112: + cmp ecx, 0 + jl tmp_115 + cmp ecx, 254 + jae setzero + movsx rdx, ecx + jmp do_shr +tmp_115: + neg ecx + cmp ecx, 254 + jae setzero + movsx rdx, ecx + jmp do_shl + + + + +;;;;;;;;;;;;;;;;;;;;;; +; shl +;;;;;;;;;;;;;;;;;;;;;; +; Adds two elements of any kind +; Params: +; rsi <= Pointer to element 1 +; rdx <= Pointer to element 2 +; rdi <= Pointer to result +; Modified Registers: +; r8, r9, 10, r11, rax, rcx +;;;;;;;;;;;;;;;;;;;;;; +Fr_shl: + push rbp + push rsi + push rdi + push rdx + mov rbp, rsp + + + + + + mov rcx, [rdx] + bt rcx, 63 ; Check if is short second operand + jnc tmp_116 + + ; long 2 + bt rcx, 62 ; Check if is montgomery second operand + jnc tmp_117 + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toNormal + mov rdx, rdi + pop rdi + pop rsi + +tmp_117: + mov rcx, [rdx + 8] + cmp rcx, 254 + jae tmp_118 + xor rax, rax + + cmp [rdx + 16], rax + jnz tmp_118 + + cmp [rdx + 24], rax + jnz tmp_118 + + cmp [rdx + 32], rax + jnz tmp_118 + + mov rdx, rcx + jmp do_shl + +tmp_118: + mov rcx, [q] + sub rcx, [rdx+8] + cmp rcx, 254 + jae setzero + mov rax, [q] + sub rax, [rdx+8] + + mov rax, [q+ 8] + sbb rax, [rdx + 16] + jnz setzero + + mov rax, [q+ 16] + sbb rax, [rdx + 24] + jnz setzero + + mov rax, [q+ 24] + sbb rax, [rdx + 32] + jnz setzero + + mov rdx, rcx + jmp do_shr + +tmp_116: + cmp ecx, 0 + jl tmp_119 + cmp ecx, 254 + jae setzero + movsx rdx, ecx + jmp do_shl +tmp_119: + neg ecx + cmp ecx, 254 + jae setzero + movsx rdx, ecx + jmp do_shr + + + +;;;;;;;;;; +;;; doShl +;;;;;;;;;; +do_shl: + mov rcx, [rsi] + bt rcx, 63 ; Check if is short second operand + jc do_shll +do_shls: + + movsx rax, ecx + cmp rax, 0 + jz setzero; + jl do_shlcl + + cmp rdx, 31 + jae do_shlcl + + mov cl, dl + shl rax, cl + mov rcx, rax + shr rcx, 31 + jnz do_shlcl + mov [rdi], rax + mov rsp, rbp + pop rdx + pop rdi + pop rsi + pop rbp + ret + +do_shlcl: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toLongNormal + mov rsi, rdi + pop rdi + pop rdx + + jmp do_shlln + +do_shll: + bt rcx, 62 ; Check if is short second operand + jnc do_shlln + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toNormal + mov rsi, rdi + pop rdi + pop rdx + +do_shlln: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + add rdi, 8 + add rsi, 8 + call rawShl + mov rsp, rbp + pop rdx + pop rdi + pop rsi + pop rbp + ret + + +;;;;;;;;;; +;;; doShr +;;;;;;;;;; +do_shr: + mov rcx, [rsi] + bt rcx, 63 ; Check if is short second operand + jc do_shrl +do_shrs: + movsx rax, ecx + cmp rax, 0 + jz setzero; + jl do_shrcl + + cmp rdx, 31 + jae setzero + + mov cl, dl + shr rax, cl + mov [rdi], rax + mov rsp, rbp + pop rdx + pop rdi + pop rsi + pop rbp + ret + +do_shrcl: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toLongNormal + mov rsi, rdi + pop rdi + pop rdx + + +do_shrl: + bt rcx, 62 ; Check if is short second operand + jnc do_shrln + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toNormal + mov rsi, rdi + pop rdi + pop rdx + +do_shrln: + mov r11b, 0x80 + shl r11d, 24 + mov [rdi+4], r11d + add rdi, 8 + add rsi, 8 + call rawShr + mov rsp, rbp + pop rdx + pop rdi + pop rsi + pop rbp + ret + +setzero: + xor rax, rax + mov [rdi], rax + mov rsp, rbp + pop rdx + pop rdi + pop rsi + pop rbp + ret + + + + + +;;;;;;;;;;;;;;;;;;;;;; +; rgt - Raw Greater Than +;;;;;;;;;;;;;;;;;;;;;; +; returns in ax 1 id *rsi > *rdx +; Params: +; rsi <= Pointer to element 1 +; rdx <= Pointer to element 2 +; rax <= Return 1 or 0 +; Modified Registers: +; r8, r9, rax +;;;;;;;;;;;;;;;;;;;;;; +Fr_rgt: + push rbp + push rsi + push rdx + mov rbp, rsp + mov r8, [rsi] + mov r9, [rdx] + bt r8, 63 ; Check if is short first operand + jc rgt_l1 + bt r9, 63 ; Check if is short second operand + jc rgt_s1l2 + +rgt_s1s2: ; Both operands are short + cmp r8d, r9d + jg rgt_ret1 + jmp rgt_ret0 + + +rgt_l1: + bt r9, 63 ; Check if is short second operand + jc rgt_l1l2 + +;;;;;;;; +rgt_l1s2: + bt r8, 62 ; check if montgomery first + jc rgt_l1ms2 +rgt_l1ns2: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toLongNormal + mov rdx, rdi + pop rdi + pop rsi + + jmp rgtL1L2 + +rgt_l1ms2: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toLongNormal + mov rdx, rdi + pop rdi + pop rsi + + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toNormal + mov rsi, rdi + pop rdi + pop rdx + + jmp rgtL1L2 + + +;;;;;;;; +rgt_s1l2: + bt r9, 62 ; check if montgomery second + jc rgt_s1l2m +rgt_s1l2n: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toLongNormal + mov rsi, rdi + pop rdi + pop rdx + + jmp rgtL1L2 + +rgt_s1l2m: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toLongNormal + mov rsi, rdi + pop rdi + pop rdx + + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toNormal + mov rdx, rdi + pop rdi + pop rsi + + jmp rgtL1L2 + +;;;; +rgt_l1l2: + bt r8, 62 ; check if montgomery first + jc rgt_l1ml2 +rgt_l1nl2: + bt r9, 62 ; check if montgomery second + jc rgt_l1nl2m +rgt_l1nl2n: + jmp rgtL1L2 + +rgt_l1nl2m: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toNormal + mov rdx, rdi + pop rdi + pop rsi + + jmp rgtL1L2 + +rgt_l1ml2: + bt r9, 62 ; check if montgomery second + jc rgt_l1ml2m +rgt_l1ml2n: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toNormal + mov rsi, rdi + pop rdi + pop rdx + + jmp rgtL1L2 + +rgt_l1ml2m: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toNormal + mov rsi, rdi + pop rdi + pop rdx + + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toNormal + mov rdx, rdi + pop rdi + pop rsi + + jmp rgtL1L2 + + +;;;;;; +; rgtL1L2 +;;;;;; + +rgtL1L2: + + + mov rax, [rsi + 32] + cmp [half + 24], rax ; comare with (q-1)/2 + jc rgtl1l2_n1 ; half e1-e2 is neg => e1 < e2 + + jnz rgtl1l2_p1 ; half>rax => e1 -e2 is pos => e1 > e2 + + + mov rax, [rsi + 24] + cmp [half + 16], rax ; comare with (q-1)/2 + jc rgtl1l2_n1 ; half e1-e2 is neg => e1 < e2 + + jnz rgtl1l2_p1 ; half>rax => e1 -e2 is pos => e1 > e2 + + + mov rax, [rsi + 16] + cmp [half + 8], rax ; comare with (q-1)/2 + jc rgtl1l2_n1 ; half e1-e2 is neg => e1 < e2 + + jnz rgtl1l2_p1 ; half>rax => e1 -e2 is pos => e1 > e2 + + + mov rax, [rsi + 8] + cmp [half + 0], rax ; comare with (q-1)/2 + jc rgtl1l2_n1 ; half e1-e2 is neg => e1 < e2 + + jmp rgtl1l2_p1 + + + +rgtl1l2_p1: + + + mov rax, [rdx + 32] + cmp [half + 24], rax ; comare with (q-1)/2 + jc rgt_ret1 ; half e1-e2 is neg => e1 < e2 + + jnz rgtRawL1L2 ; half>rax => e1 -e2 is pos => e1 > e2 + + + mov rax, [rdx + 24] + cmp [half + 16], rax ; comare with (q-1)/2 + jc rgt_ret1 ; half e1-e2 is neg => e1 < e2 + + jnz rgtRawL1L2 ; half>rax => e1 -e2 is pos => e1 > e2 + + + mov rax, [rdx + 16] + cmp [half + 8], rax ; comare with (q-1)/2 + jc rgt_ret1 ; half e1-e2 is neg => e1 < e2 + + jnz rgtRawL1L2 ; half>rax => e1 -e2 is pos => e1 > e2 + + + mov rax, [rdx + 8] + cmp [half + 0], rax ; comare with (q-1)/2 + jc rgt_ret1 ; half e1-e2 is neg => e1 < e2 + + jmp rgtRawL1L2 + + + + +rgtl1l2_n1: + + + mov rax, [rdx + 32] + cmp [half + 24], rax ; comare with (q-1)/2 + jc rgtRawL1L2 ; half e1-e2 is neg => e1 < e2 + + jnz rgt_ret0 ; half>rax => e1 -e2 is pos => e1 > e2 + + + mov rax, [rdx + 24] + cmp [half + 16], rax ; comare with (q-1)/2 + jc rgtRawL1L2 ; half e1-e2 is neg => e1 < e2 + + jnz rgt_ret0 ; half>rax => e1 -e2 is pos => e1 > e2 + + + mov rax, [rdx + 16] + cmp [half + 8], rax ; comare with (q-1)/2 + jc rgtRawL1L2 ; half e1-e2 is neg => e1 < e2 + + jnz rgt_ret0 ; half>rax => e1 -e2 is pos => e1 > e2 + + + mov rax, [rdx + 8] + cmp [half + 0], rax ; comare with (q-1)/2 + jc rgtRawL1L2 ; half e1-e2 is neg => e1 < e2 + + jmp rgt_ret0 + + + + + +rgtRawL1L2: + + mov rax, [rsi + 32] + cmp [rdx + 32], rax ; comare with (q-1)/2 + jc rgt_ret1 ; rsi 1st > 2nd + + jnz rgt_ret0 + + + mov rax, [rsi + 24] + cmp [rdx + 24], rax ; comare with (q-1)/2 + jc rgt_ret1 ; rsi 1st > 2nd + + jnz rgt_ret0 + + + mov rax, [rsi + 16] + cmp [rdx + 16], rax ; comare with (q-1)/2 + jc rgt_ret1 ; rsi 1st > 2nd + + jnz rgt_ret0 + + + mov rax, [rsi + 8] + cmp [rdx + 8], rax ; comare with (q-1)/2 + jc rgt_ret1 ; rsi 1st > 2nd + + + +rgt_ret0: + xor rax, rax + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret +rgt_ret1: + mov rax, 1 + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + +;;;;;;;;;;;;;;;;;;;;;; +; rlt - Raw Less Than +;;;;;;;;;;;;;;;;;;;;;; +; returns in ax 1 id *rsi > *rdx +; Params: +; rsi <= Pointer to element 1 +; rdx <= Pointer to element 2 +; rax <= Return 1 or 0 +; Modified Registers: +; r8, r9, rax +;;;;;;;;;;;;;;;;;;;;;; +Fr_rlt: + push rbp + push rsi + push rdx + mov rbp, rsp + mov r8, [rsi] + mov r9, [rdx] + bt r8, 63 ; Check if is short first operand + jc rlt_l1 + bt r9, 63 ; Check if is short second operand + jc rlt_s1l2 + +rlt_s1s2: ; Both operands are short + cmp r8d, r9d + jl rlt_ret1 + jmp rlt_ret0 + + +rlt_l1: + bt r9, 63 ; Check if is short second operand + jc rlt_l1l2 + +;;;;;;;; +rlt_l1s2: + bt r8, 62 ; check if montgomery first + jc rlt_l1ms2 +rlt_l1ns2: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toLongNormal + mov rdx, rdi + pop rdi + pop rsi + + jmp rltL1L2 + +rlt_l1ms2: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toLongNormal + mov rdx, rdi + pop rdi + pop rsi + + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toNormal + mov rsi, rdi + pop rdi + pop rdx + + jmp rltL1L2 + + +;;;;;;;; +rlt_s1l2: + bt r9, 62 ; check if montgomery second + jc rlt_s1l2m +rlt_s1l2n: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toLongNormal + mov rsi, rdi + pop rdi + pop rdx + + jmp rltL1L2 + +rlt_s1l2m: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toLongNormal + mov rsi, rdi + pop rdi + pop rdx + + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toNormal + mov rdx, rdi + pop rdi + pop rsi + + jmp rltL1L2 + +;;;; +rlt_l1l2: + bt r8, 62 ; check if montgomery first + jc rlt_l1ml2 +rlt_l1nl2: + bt r9, 62 ; check if montgomery second + jc rlt_l1nl2m +rlt_l1nl2n: + jmp rltL1L2 + +rlt_l1nl2m: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toNormal + mov rdx, rdi + pop rdi + pop rsi + + jmp rltL1L2 + +rlt_l1ml2: + bt r9, 62 ; check if montgomery second + jc rlt_l1ml2m +rlt_l1ml2n: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toNormal + mov rsi, rdi + pop rdi + pop rdx + + jmp rltL1L2 + +rlt_l1ml2m: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toNormal + mov rsi, rdi + pop rdi + pop rdx + + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toNormal + mov rdx, rdi + pop rdi + pop rsi + + jmp rltL1L2 + + +;;;;;; +; rltL1L2 +;;;;;; + +rltL1L2: + + + mov rax, [rsi + 32] + cmp [half + 24], rax ; comare with (q-1)/2 + jc rltl1l2_n1 ; half e1-e2 is neg => e1 < e2 + + jnz rltl1l2_p1 ; half>rax => e1 -e2 is pos => e1 > e2 + + + mov rax, [rsi + 24] + cmp [half + 16], rax ; comare with (q-1)/2 + jc rltl1l2_n1 ; half e1-e2 is neg => e1 < e2 + + jnz rltl1l2_p1 ; half>rax => e1 -e2 is pos => e1 > e2 + + + mov rax, [rsi + 16] + cmp [half + 8], rax ; comare with (q-1)/2 + jc rltl1l2_n1 ; half e1-e2 is neg => e1 < e2 + + jnz rltl1l2_p1 ; half>rax => e1 -e2 is pos => e1 > e2 + + + mov rax, [rsi + 8] + cmp [half + 0], rax ; comare with (q-1)/2 + jc rltl1l2_n1 ; half e1-e2 is neg => e1 < e2 + + jmp rltl1l2_p1 + + + +rltl1l2_p1: + + + mov rax, [rdx + 32] + cmp [half + 24], rax ; comare with (q-1)/2 + jc rlt_ret0 ; half e1-e2 is neg => e1 < e2 + + jnz rltRawL1L2 ; half>rax => e1 -e2 is pos => e1 > e2 + + + mov rax, [rdx + 24] + cmp [half + 16], rax ; comare with (q-1)/2 + jc rlt_ret0 ; half e1-e2 is neg => e1 < e2 + + jnz rltRawL1L2 ; half>rax => e1 -e2 is pos => e1 > e2 + + + mov rax, [rdx + 16] + cmp [half + 8], rax ; comare with (q-1)/2 + jc rlt_ret0 ; half e1-e2 is neg => e1 < e2 + + jnz rltRawL1L2 ; half>rax => e1 -e2 is pos => e1 > e2 + + + mov rax, [rdx + 8] + cmp [half + 0], rax ; comare with (q-1)/2 + jc rlt_ret0 ; half e1-e2 is neg => e1 < e2 + + jmp rltRawL1L2 + + + + +rltl1l2_n1: + + + mov rax, [rdx + 32] + cmp [half + 24], rax ; comare with (q-1)/2 + jc rltRawL1L2 ; half e1-e2 is neg => e1 < e2 + + jnz rlt_ret1 ; half>rax => e1 -e2 is pos => e1 > e2 + + + mov rax, [rdx + 24] + cmp [half + 16], rax ; comare with (q-1)/2 + jc rltRawL1L2 ; half e1-e2 is neg => e1 < e2 + + jnz rlt_ret1 ; half>rax => e1 -e2 is pos => e1 > e2 + + + mov rax, [rdx + 16] + cmp [half + 8], rax ; comare with (q-1)/2 + jc rltRawL1L2 ; half e1-e2 is neg => e1 < e2 + + jnz rlt_ret1 ; half>rax => e1 -e2 is pos => e1 > e2 + + + mov rax, [rdx + 8] + cmp [half + 0], rax ; comare with (q-1)/2 + jc rltRawL1L2 ; half e1-e2 is neg => e1 < e2 + + jmp rlt_ret1 + + + + + +rltRawL1L2: + + mov rax, [rsi + 32] + cmp [rdx + 32], rax ; comare with (q-1)/2 + jc rlt_ret0 ; rsi 1st > 2nd + jnz rlt_ret1 + + mov rax, [rsi + 24] + cmp [rdx + 24], rax ; comare with (q-1)/2 + jc rlt_ret0 ; rsi 1st > 2nd + jnz rlt_ret1 + + mov rax, [rsi + 16] + cmp [rdx + 16], rax ; comare with (q-1)/2 + jc rlt_ret0 ; rsi 1st > 2nd + jnz rlt_ret1 + + mov rax, [rsi + 8] + cmp [rdx + 8], rax ; comare with (q-1)/2 + jc rlt_ret0 ; rsi 1st > 2nd + jnz rlt_ret1 + + +rlt_ret0: + xor rax, rax + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret +rlt_ret1: + mov rax, 1 + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + + +;;;;;;;;;;;;;;;;;;;;;; +; req - Raw Eq +;;;;;;;;;;;;;;;;;;;;;; +; returns in ax 1 id *rsi == *rdx +; Params: +; rsi <= Pointer to element 1 +; rdx <= Pointer to element 2 +; rax <= Return 1 or 0 +; Modified Registers: +; r8, r9, rax +;;;;;;;;;;;;;;;;;;;;;; +Fr_req: + push rbp + push rsi + push rdx + mov rbp, rsp + mov r8, [rsi] + mov r9, [rdx] + bt r8, 63 ; Check if is short first operand + jc req_l1 + bt r9, 63 ; Check if is short second operand + jc req_s1l2 + +req_s1s2: ; Both operands are short + cmp r8d, r9d + je req_ret1 + jmp req_ret0 + + +req_l1: + bt r9, 63 ; Check if is short second operand + jc req_l1l2 + +;;;;;;;; +req_l1s2: + bt r8, 62 ; check if montgomery first + jc req_l1ms2 +req_l1ns2: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toLongNormal + mov rdx, rdi + pop rdi + pop rsi + + jmp reqL1L2 + +req_l1ms2: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toMontgomery + mov rdx, rdi + pop rdi + pop rsi + + jmp reqL1L2 + + +;;;;;;;; +req_s1l2: + bt r9, 62 ; check if montgomery second + jc req_s1l2m +req_s1l2n: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toLongNormal + mov rsi, rdi + pop rdi + pop rdx + + jmp reqL1L2 + +req_s1l2m: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toMontgomery + mov rsi, rdi + pop rdi + pop rdx + + jmp reqL1L2 + +;;;; +req_l1l2: + bt r8, 62 ; check if montgomery first + jc req_l1ml2 +req_l1nl2: + bt r9, 62 ; check if montgomery second + jc req_l1nl2m +req_l1nl2n: + jmp reqL1L2 + +req_l1nl2m: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rdx + push r8 + call Fr_toMontgomery + mov rsi, rdi + pop rdi + pop rdx + + jmp reqL1L2 + +req_l1ml2: + bt r9, 62 ; check if montgomery second + jc req_l1ml2m +req_l1ml2n: + + mov r8, rdi + sub rsp, 40 + mov rdi, rsp + push rsi + mov rsi, rdx + push r8 + call Fr_toMontgomery + mov rdx, rdi + pop rdi + pop rsi + + jmp reqL1L2 + +req_l1ml2m: + jmp reqL1L2 + + +;;;;;; +; eqL1L2 +;;;;;; + +reqL1L2: + + mov rax, [rsi + 8] + cmp [rdx + 8], rax + jne req_ret0 ; rsi 1st > 2nd + + mov rax, [rsi + 16] + cmp [rdx + 16], rax + jne req_ret0 ; rsi 1st > 2nd + + mov rax, [rsi + 24] + cmp [rdx + 24], rax + jne req_ret0 ; rsi 1st > 2nd + + mov rax, [rsi + 32] + cmp [rdx + 32], rax + jne req_ret0 ; rsi 1st > 2nd + + +req_ret1: + mov rax, 1 + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + +req_ret0: + xor rax, rax + mov rsp, rbp + pop rdx + pop rsi + pop rbp + ret + + +;;;;;;;;;;;;;;;;;;;;;; +; gt +;;;;;;;;;;;;;;;;;;;;;; +; Compares two elements of any kind +; Params: +; rsi <= Pointer to element 1 +; rdx <= Pointer to element 2 +; rdi <= Pointer to result can be zero or one. +; Modified Registers: +; rax, rcx +;;;;;;;;;;;;;;;;;;;;;; +Fr_gt: + call Fr_rgt + mov [rdi], rax + ret + +;;;;;;;;;;;;;;;;;;;;;; +; lt +;;;;;;;;;;;;;;;;;;;;;; +; Compares two elements of any kind +; Params: +; rsi <= Pointer to element 1 +; rdx <= Pointer to element 2 +; rdi <= Pointer to result can be zero or one. +; Modified Registers: +; rax, rcx +;;;;;;;;;;;;;;;;;;;;;; +Fr_lt: + call Fr_rlt + mov [rdi], rax + ret + +;;;;;;;;;;;;;;;;;;;;;; +; eq +;;;;;;;;;;;;;;;;;;;;;; +; Compares two elements of any kind +; Params: +; rsi <= Pointer to element 1 +; rdx <= Pointer to element 2 +; rdi <= Pointer to result can be zero or one. +; Modified Registers: +; rax, rcx +;;;;;;;;;;;;;;;;;;;;;; +Fr_eq: + call Fr_req + mov [rdi], rax + ret + +;;;;;;;;;;;;;;;;;;;;;; +; neq +;;;;;;;;;;;;;;;;;;;;;; +; Compares two elements of any kind +; Params: +; rsi <= Pointer to element 1 +; rdx <= Pointer to element 2 +; rdi <= Pointer to result can be zero or one. +; Modified Registers: +; rax, rcx +;;;;;;;;;;;;;;;;;;;;;; +Fr_neq: + call Fr_req + xor rax, 1 + mov [rdi], rax + ret + +;;;;;;;;;;;;;;;;;;;;;; +; geq +;;;;;;;;;;;;;;;;;;;;;; +; Compares two elements of any kind +; Params: +; rsi <= Pointer to element 1 +; rdx <= Pointer to element 2 +; rdi <= Pointer to result can be zero or one. +; Modified Registers: +; rax, rcx +;;;;;;;;;;;;;;;;;;;;;; +Fr_geq: + call Fr_rlt + xor rax, 1 + mov [rdi], rax + ret + +;;;;;;;;;;;;;;;;;;;;;; +; leq +;;;;;;;;;;;;;;;;;;;;;; +; Compares two elements of any kind +; Params: +; rsi <= Pointer to element 1 +; rdx <= Pointer to element 2 +; rdi <= Pointer to result can be zero or one. +; Modified Registers: +; rax, rcx +;;;;;;;;;;;;;;;;;;;;;; +Fr_leq: + call Fr_rgt + xor rax, 1 + mov [rdi], rax + ret + + + +;;;;;;;;;;;;;;;;;;;;;; +; rawIsEq +;;;;;;;;;;;;;;;;;;;;;; +; Compares two elements of any kind +; Params: +; rdi <= Pointer to element 1 +; rsi <= Pointer to element 2 +; Returns +; ax <= 1 if are equal 0, otherwise +; Modified Registers: +; rax +;;;;;;;;;;;;;;;;;;;;;; +Fr_rawIsEq: + + mov rax, [rsi + 0] + cmp [rdi + 0], rax + jne rawIsEq_ret0 + + mov rax, [rsi + 8] + cmp [rdi + 8], rax + jne rawIsEq_ret0 + + mov rax, [rsi + 16] + cmp [rdi + 16], rax + jne rawIsEq_ret0 + + mov rax, [rsi + 24] + cmp [rdi + 24], rax + jne rawIsEq_ret0 + +rawIsEq_ret1: + mov rax, 1 + ret + +rawIsEq_ret0: + xor rax, rax + ret + +;;;;;;;;;;;;;;;;;;;;;; +; rawIsZero +;;;;;;;;;;;;;;;;;;;;;; +; Compares two elements of any kind +; Params: +; rdi <= Pointer to element 1 +; Returns +; ax <= 1 if is 0, otherwise +; Modified Registers: +; rax +;;;;;;;;;;;;;;;;;;;;;; +Fr_rawIsZero: + + cmp qword [rdi + 0], $0 + jne rawIsZero_ret0 + + cmp qword [rdi + 8], $0 + jne rawIsZero_ret0 + + cmp qword [rdi + 16], $0 + jne rawIsZero_ret0 + + cmp qword [rdi + 24], $0 + jne rawIsZero_ret0 + + +rawIsZero_ret1: + mov rax, 1 + ret + +rawIsZero_ret0: + xor rax, rax + ret + + + + + + + + + + + +;;;;;;;;;;;;;;;;;;;;;; +; land +;;;;;;;;;;;;;;;;;;;;;; +; Logical and between two elements +; Params: +; rsi <= Pointer to element 1 +; rdx <= Pointer to element 2 +; rdi <= Pointer to result zero or one +; Modified Registers: +; rax, rcx, r8 +;;;;;;;;;;;;;;;;;;;;;; +Fr_land: + + + + + + + mov rax, [rsi] + bt rax, 63 + jc tmp_120 + + test eax, eax + jz retZero_122 + jmp retOne_121 + +tmp_120: + + mov rax, [rsi + 8] + test rax, rax + jnz retOne_121 + + mov rax, [rsi + 16] + test rax, rax + jnz retOne_121 + + mov rax, [rsi + 24] + test rax, rax + jnz retOne_121 + + mov rax, [rsi + 32] + test rax, rax + jnz retOne_121 + + +retZero_122: + mov qword r8, 0 + jmp done_123 + +retOne_121: + mov qword r8, 1 + +done_123: + + + + + + + + mov rax, [rdx] + bt rax, 63 + jc tmp_124 + + test eax, eax + jz retZero_126 + jmp retOne_125 + +tmp_124: + + mov rax, [rdx + 8] + test rax, rax + jnz retOne_125 + + mov rax, [rdx + 16] + test rax, rax + jnz retOne_125 + + mov rax, [rdx + 24] + test rax, rax + jnz retOne_125 + + mov rax, [rdx + 32] + test rax, rax + jnz retOne_125 + + +retZero_126: + mov qword rcx, 0 + jmp done_127 + +retOne_125: + mov qword rcx, 1 + +done_127: + + and rcx, r8 + mov [rdi], rcx + ret + + +;;;;;;;;;;;;;;;;;;;;;; +; lor +;;;;;;;;;;;;;;;;;;;;;; +; Logical or between two elements +; Params: +; rsi <= Pointer to element 1 +; rdx <= Pointer to element 2 +; rdi <= Pointer to result zero or one +; Modified Registers: +; rax, rcx, r8 +;;;;;;;;;;;;;;;;;;;;;; +Fr_lor: + + + + + + + mov rax, [rsi] + bt rax, 63 + jc tmp_128 + + test eax, eax + jz retZero_130 + jmp retOne_129 + +tmp_128: + + mov rax, [rsi + 8] + test rax, rax + jnz retOne_129 + + mov rax, [rsi + 16] + test rax, rax + jnz retOne_129 + + mov rax, [rsi + 24] + test rax, rax + jnz retOne_129 + + mov rax, [rsi + 32] + test rax, rax + jnz retOne_129 + + +retZero_130: + mov qword r8, 0 + jmp done_131 + +retOne_129: + mov qword r8, 1 + +done_131: + + + + + + + + mov rax, [rdx] + bt rax, 63 + jc tmp_132 + + test eax, eax + jz retZero_134 + jmp retOne_133 + +tmp_132: + + mov rax, [rdx + 8] + test rax, rax + jnz retOne_133 + + mov rax, [rdx + 16] + test rax, rax + jnz retOne_133 + + mov rax, [rdx + 24] + test rax, rax + jnz retOne_133 + + mov rax, [rdx + 32] + test rax, rax + jnz retOne_133 + + +retZero_134: + mov qword rcx, 0 + jmp done_135 + +retOne_133: + mov qword rcx, 1 + +done_135: + + or rcx, r8 + mov [rdi], rcx + ret + + +;;;;;;;;;;;;;;;;;;;;;; +; lnot +;;;;;;;;;;;;;;;;;;;;;; +; Do the logical not of an element +; Params: +; rsi <= Pointer to element to be tested +; rdi <= Pointer to result one if element1 is zero and zero otherwise +; Modified Registers: +; rax, rax, r8 +;;;;;;;;;;;;;;;;;;;;;; +Fr_lnot: + + + + + + + mov rax, [rsi] + bt rax, 63 + jc tmp_136 + + test eax, eax + jz retZero_138 + jmp retOne_137 + +tmp_136: + + mov rax, [rsi + 8] + test rax, rax + jnz retOne_137 + + mov rax, [rsi + 16] + test rax, rax + jnz retOne_137 + + mov rax, [rsi + 24] + test rax, rax + jnz retOne_137 + + mov rax, [rsi + 32] + test rax, rax + jnz retOne_137 + + +retZero_138: + mov qword rcx, 0 + jmp done_139 + +retOne_137: + mov qword rcx, 1 + +done_139: + + test rcx, rcx + + jz lnot_retOne +lnot_retZero: + mov qword [rdi], 0 + ret +lnot_retOne: + mov qword [rdi], 1 + ret + + +;;;;;;;;;;;;;;;;;;;;;; +; isTrue +;;;;;;;;;;;;;;;;;;;;;; +; Convert a 64 bit integer to a long format field element +; Params: +; rsi <= Pointer to the element +; Returs: +; rax <= 1 if true 0 if false +;;;;;;;;;;;;;;;;;;;;;;; +Fr_isTrue: + + + + + + + mov rax, [rdi] + bt rax, 63 + jc tmp_140 + + test eax, eax + jz retZero_142 + jmp retOne_141 + +tmp_140: + + mov rax, [rdi + 8] + test rax, rax + jnz retOne_141 + + mov rax, [rdi + 16] + test rax, rax + jnz retOne_141 + + mov rax, [rdi + 24] + test rax, rax + jnz retOne_141 + + mov rax, [rdi + 32] + test rax, rax + jnz retOne_141 + + +retZero_142: + mov qword rax, 0 + jmp done_143 + +retOne_141: + mov qword rax, 1 + +done_143: + + ret + + + + + + section .data +Fr_q: + dd 0 + dd 0x80000000 +Fr_rawq: +q dq 0x43e1f593f0000001,0x2833e84879b97091,0xb85045b68181585d,0x30644e72e131a029 +half dq 0xa1f0fac9f8000000,0x9419f4243cdcb848,0xdc2822db40c0ac2e,0x183227397098d014 +R2 dq 0x1bb8e645ae216da7,0x53fe3ab1e35c59e3,0x8c49833d53bb8085,0x0216d0b17f4e44a5 +Fr_R3: + dd 0 + dd 0x80000000 +Fr_rawR3: +R3 dq 0x5e94d8e1b4bf0040,0x2a489cbe1cfbb6b8,0x893cc664a19fcfed,0x0cf8594b7fcc657c +lboMask dq 0x3fffffffffffffff +np dq 0xc2e1f593efffffff + diff --git a/examples/toy/toy_cpp/fr.cpp b/examples/toy/bn254/toy_cpp/fr.cpp similarity index 84% rename from examples/toy/toy_cpp/fr.cpp rename to examples/toy/bn254/toy_cpp/fr.cpp index 78e8567..14864de 100644 --- a/examples/toy/toy_cpp/fr.cpp +++ b/examples/toy/bn254/toy_cpp/fr.cpp @@ -53,7 +53,7 @@ bool Fr_init() { return true; } -void Fr_str2element(PFrElement pE, char const *s, int base) { +void Fr_str2element(PFrElement pE, char const *s, uint base) { mpz_t mr; mpz_init_set_str(mr, s, base); mpz_fdiv_r(mr, mr, q); @@ -169,8 +169,8 @@ void Fr_fail() { RawFr::RawFr() { Fr_init(); - fromString(fZero, "0"); - fromString(fOne, "1"); + set(fZero, 0); + set(fOne, 1); neg(fNegOne, fOne); } @@ -197,7 +197,27 @@ void RawFr::fromUI(Element &r, unsigned long int v) { mpz_clear(mr); } +RawFr::Element RawFr::set(int value) { + Element r; + set(r, value); + return r; +} +void RawFr::set(Element &r, int value) { + mpz_t mr; + mpz_init(mr); + mpz_set_si(mr, value); + if (value < 0) { + mpz_add(mr, mr, q); + } + + mpz_export((void *)(r.v), NULL, -1, 8, -1, 0, mr); + + for (int i=0; i +#include +#include + +#ifdef __APPLE__ +#include // typedef unsigned int uint; +#endif // __APPLE__ + +#define Fr_N64 4 +#define Fr_SHORT 0x00000000 +#define Fr_LONG 0x80000000 +#define Fr_LONGMONTGOMERY 0xC0000000 +typedef uint64_t FrRawElement[Fr_N64]; +typedef struct __attribute__((__packed__)) { + int32_t shortVal; + uint32_t type; + FrRawElement longVal; +} FrElement; +typedef FrElement *PFrElement; +extern FrElement Fr_q; +extern FrElement Fr_R3; +extern FrRawElement Fr_rawq; +extern FrRawElement Fr_rawR3; + +extern "C" void Fr_copy(PFrElement r, PFrElement a); +extern "C" void Fr_copyn(PFrElement r, PFrElement a, int n); +extern "C" void Fr_add(PFrElement r, PFrElement a, PFrElement b); +extern "C" void Fr_sub(PFrElement r, PFrElement a, PFrElement b); +extern "C" void Fr_neg(PFrElement r, PFrElement a); +extern "C" void Fr_mul(PFrElement r, PFrElement a, PFrElement b); +extern "C" void Fr_square(PFrElement r, PFrElement a); +extern "C" void Fr_band(PFrElement r, PFrElement a, PFrElement b); +extern "C" void Fr_bor(PFrElement r, PFrElement a, PFrElement b); +extern "C" void Fr_bxor(PFrElement r, PFrElement a, PFrElement b); +extern "C" void Fr_bnot(PFrElement r, PFrElement a); +extern "C" void Fr_shl(PFrElement r, PFrElement a, PFrElement b); +extern "C" void Fr_shr(PFrElement r, PFrElement a, PFrElement b); +extern "C" void Fr_eq(PFrElement r, PFrElement a, PFrElement b); +extern "C" void Fr_neq(PFrElement r, PFrElement a, PFrElement b); +extern "C" void Fr_lt(PFrElement r, PFrElement a, PFrElement b); +extern "C" void Fr_gt(PFrElement r, PFrElement a, PFrElement b); +extern "C" void Fr_leq(PFrElement r, PFrElement a, PFrElement b); +extern "C" void Fr_geq(PFrElement r, PFrElement a, PFrElement b); +extern "C" void Fr_land(PFrElement r, PFrElement a, PFrElement b); +extern "C" void Fr_lor(PFrElement r, PFrElement a, PFrElement b); +extern "C" void Fr_lnot(PFrElement r, PFrElement a); +extern "C" void Fr_toNormal(PFrElement r, PFrElement a); +extern "C" void Fr_toLongNormal(PFrElement r, PFrElement a); +extern "C" void Fr_toMontgomery(PFrElement r, PFrElement a); + +extern "C" int Fr_isTrue(PFrElement pE); +extern "C" int Fr_toInt(PFrElement pE); + +extern "C" void Fr_rawCopy(FrRawElement pRawResult, const FrRawElement pRawA); +extern "C" void Fr_rawSwap(FrRawElement pRawResult, FrRawElement pRawA); +extern "C" void Fr_rawAdd(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB); +extern "C" void Fr_rawSub(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB); +extern "C" void Fr_rawNeg(FrRawElement pRawResult, const FrRawElement pRawA); +extern "C" void Fr_rawMMul(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB); +extern "C" void Fr_rawMSquare(FrRawElement pRawResult, const FrRawElement pRawA); +extern "C" void Fr_rawMMul1(FrRawElement pRawResult, const FrRawElement pRawA, uint64_t pRawB); +extern "C" void Fr_rawToMontgomery(FrRawElement pRawResult, const FrRawElement &pRawA); +extern "C" void Fr_rawFromMontgomery(FrRawElement pRawResult, const FrRawElement &pRawA); +extern "C" int Fr_rawIsEq(const FrRawElement pRawA, const FrRawElement pRawB); +extern "C" int Fr_rawIsZero(const FrRawElement pRawB); + +extern "C" void Fr_fail(); + + +// Pending functions to convert + +void Fr_str2element(PFrElement pE, char const*s, uint base); +char *Fr_element2str(PFrElement pE); +void Fr_idiv(PFrElement r, PFrElement a, PFrElement b); +void Fr_mod(PFrElement r, PFrElement a, PFrElement b); +void Fr_inv(PFrElement r, PFrElement a); +void Fr_div(PFrElement r, PFrElement a, PFrElement b); +void Fr_pow(PFrElement r, PFrElement a, PFrElement b); + +class RawFr { + +public: + const static int N64 = Fr_N64; + const static int MaxBits = 254; + + + struct Element { + FrRawElement v; + }; + +private: + Element fZero; + Element fOne; + Element fNegOne; + +public: + + RawFr(); + ~RawFr(); + + const Element &zero() { return fZero; }; + const Element &one() { return fOne; }; + const Element &negOne() { return fNegOne; }; + Element set(int value); + void set(Element &r, int value); + + void fromString(Element &r, const std::string &n, uint32_t radix = 10); + std::string toString(const Element &a, uint32_t radix = 10); + + void inline copy(Element &r, const Element &a) { Fr_rawCopy(r.v, a.v); }; + void inline swap(Element &a, Element &b) { Fr_rawSwap(a.v, b.v); }; + void inline add(Element &r, const Element &a, const Element &b) { Fr_rawAdd(r.v, a.v, b.v); }; + void inline sub(Element &r, const Element &a, const Element &b) { Fr_rawSub(r.v, a.v, b.v); }; + void inline mul(Element &r, const Element &a, const Element &b) { Fr_rawMMul(r.v, a.v, b.v); }; + + Element inline add(const Element &a, const Element &b) { Element r; Fr_rawAdd(r.v, a.v, b.v); return r;}; + Element inline sub(const Element &a, const Element &b) { Element r; Fr_rawSub(r.v, a.v, b.v); return r;}; + Element inline mul(const Element &a, const Element &b) { Element r; Fr_rawMMul(r.v, a.v, b.v); return r;}; + + Element inline neg(const Element &a) { Element r; Fr_rawNeg(r.v, a.v); return r; }; + Element inline square(const Element &a) { Element r; Fr_rawMSquare(r.v, a.v); return r; }; + + Element inline add(int a, const Element &b) { return add(set(a), b);}; + Element inline sub(int a, const Element &b) { return sub(set(a), b);}; + Element inline mul(int a, const Element &b) { return mul(set(a), b);}; + + Element inline add(const Element &a, int b) { return add(a, set(b));}; + Element inline sub(const Element &a, int b) { return sub(a, set(b));}; + Element inline mul(const Element &a, int b) { return mul(a, set(b));}; + + void inline mul1(Element &r, const Element &a, uint64_t b) { Fr_rawMMul1(r.v, a.v, b); }; + void inline neg(Element &r, const Element &a) { Fr_rawNeg(r.v, a.v); }; + void inline square(Element &r, const Element &a) { Fr_rawMSquare(r.v, a.v); }; + void inv(Element &r, const Element &a); + void div(Element &r, const Element &a, const Element &b); + void exp(Element &r, const Element &base, uint8_t* scalar, unsigned int scalarSize); + + void inline toMontgomery(Element &r, const Element &a) { Fr_rawToMontgomery(r.v, a.v); }; + void inline fromMontgomery(Element &r, const Element &a) { Fr_rawFromMontgomery(r.v, a.v); }; + int inline eq(const Element &a, const Element &b) { return Fr_rawIsEq(a.v, b.v); }; + int inline isZero(const Element &a) { return Fr_rawIsZero(a.v); }; + + void toMpz(mpz_t r, const Element &a); + void fromMpz(Element &a, const mpz_t r); + + int toRprBE(const Element &element, uint8_t *data, int bytes); + int fromRprBE(Element &element, const uint8_t *data, int bytes); + + int bytes ( void ) { return Fr_N64 * 8; }; + + void fromUI(Element &r, unsigned long int v); + + static RawFr field; + +}; + + +#endif // __FR_H + + + diff --git a/examples/toy/bn254/toy_cpp/fr.o b/examples/toy/bn254/toy_cpp/fr.o new file mode 100644 index 0000000000000000000000000000000000000000..d6fc2487f3288401b3466de2cdc767a41ea86477 GIT binary patch literal 14304 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 literal 0 HcmV?d00001 diff --git a/examples/toy/bn254/toy_cpp/fr_asm.o b/examples/toy/bn254/toy_cpp/fr_asm.o new file mode 100644 index 0000000000000000000000000000000000000000..f1e71add507141aa908b3da814b45412150bac9e GIT binary patch literal 36778 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 p)IeISfpUg319E0N&o_Ho{!HJv6rVf<$)8>{dRp literal 0 HcmV?d00001 diff --git a/examples/toy/toy_cpp/main.cpp b/examples/toy/bn254/toy_cpp/main.cpp similarity index 100% rename from examples/toy/toy_cpp/main.cpp rename to examples/toy/bn254/toy_cpp/main.cpp diff --git a/examples/toy/bn254/toy_cpp/main.o b/examples/toy/bn254/toy_cpp/main.o new file mode 100644 index 0000000000000000000000000000000000000000..c95e528a22077f682109981f7a3c580beb6613fd GIT binary patch literal 170992 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

#=8rs^F!?am}C5X4AS23>SVn+t@z| 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 ZHC|J-*JM?CZ53XVwNN^Kj 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


Pj9y}Q;^@>VmKJds$YXp> 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 JeL2(r{s&XK^9BF_ literal 0 HcmV?d00001 diff --git a/examples/toy/toy_cpp/toy.cpp b/examples/toy/bn254/toy_cpp/toy.cpp similarity index 84% rename from examples/toy/toy_cpp/toy.cpp rename to examples/toy/bn254/toy_cpp/toy.cpp index 4146f63..4fc4df5 100644 --- a/examples/toy/toy_cpp/toy.cpp +++ b/examples/toy/bn254/toy_cpp/toy.cpp @@ -29,17 +29,23 @@ void release_memory_component(Circom_CalcWit* ctx, uint pos) {{ if (pos != 0){{ -delete ctx->componentMemory[pos].subcomponents; +if(ctx->componentMemory[pos].subcomponents) +delete []ctx->componentMemory[pos].subcomponents; -delete ctx->componentMemory[pos].subcomponentsParallel; +if(ctx->componentMemory[pos].subcomponentsParallel) +delete []ctx->componentMemory[pos].subcomponentsParallel; -delete ctx->componentMemory[pos].outputIsSet; +if(ctx->componentMemory[pos].outputIsSet) +delete []ctx->componentMemory[pos].outputIsSet; -delete ctx->componentMemory[pos].mutexes; +if(ctx->componentMemory[pos].mutexes) +delete []ctx->componentMemory[pos].mutexes; -delete ctx->componentMemory[pos].cvs; +if(ctx->componentMemory[pos].cvs) +delete []ctx->componentMemory[pos].cvs; -delete ctx->componentMemory[pos].sbct; +if(ctx->componentMemory[pos].sbct) +delete []ctx->componentMemory[pos].sbct; }} diff --git a/examples/toy/bn254/toy_cpp/toy.dat b/examples/toy/bn254/toy_cpp/toy.dat new file mode 100644 index 0000000000000000000000000000000000000000..3bf0e7ef94c6c1eb7944b0153031b95ff60b58d5 GIT binary patch literal 6264 zcmZQz7zLvtFd71*Aut*Oqai?k2sj&s{QdhTR+$xQ1S9!I4NIN=_pThDDScxfGt_rX z!_t?do*E5-(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7|bC68?S+lOTfk{ xSWq49fXc<>LCtaa{r|tejLEb$nr9Q{Pc8dnrsq~!k-s=EP5(aotb^rTd;pZ&87=?- literal 0 HcmV?d00001 diff --git a/examples/toy/bn254/toy_cpp/toy.o b/examples/toy/bn254/toy_cpp/toy.o new file mode 100644 index 0000000000000000000000000000000000000000..12a727fc7e7ced3751d31e619a079838695f2c66 GIT binary patch literal 4848 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 B9D4u& literal 0 HcmV?d00001 diff --git a/examples/toy/toy_js/witness_calculator.js b/examples/toy/bn254/toy_js/witness_calculator.js similarity index 100% rename from examples/toy/toy_js/witness_calculator.js rename to examples/toy/bn254/toy_js/witness_calculator.js diff --git a/examples/toy/compile.sh b/examples/toy/compile.sh index 9d525df..56f86ed 100644 --- a/examples/toy/compile.sh +++ b/examples/toy/compile.sh @@ -1,4 +1,8 @@ #!/bin/bash -circom ./examples/toy/toy.circom --r1cs --wasm --sym --c --output ./examples/toy/ --prime vesta -cd examples/toy/toy_cpp && make \ No newline at end of file +circom ./examples/toy/toy.circom --r1cs --wasm --sym --c --output ./examples/toy/pasta/ --prime vesta +cd examples/toy/pasta/toy_cpp && make +cd - + +circom ./examples/toy/toy.circom --r1cs --wasm --sym --c --output ./examples/toy/bn254/ --prime bn128 +cd examples/toy/bn254/toy_cpp && make \ No newline at end of file diff --git a/examples/toy/toy.r1cs b/examples/toy/pasta/toy.r1cs similarity index 100% rename from examples/toy/toy.r1cs rename to examples/toy/pasta/toy.r1cs diff --git a/examples/toy/pasta/toy.sym b/examples/toy/pasta/toy.sym new file mode 100644 index 0000000..e346cd4 --- /dev/null +++ b/examples/toy/pasta/toy.sym @@ -0,0 +1,5 @@ +1,1,0,main.step_out[0] +2,2,0,main.step_out[1] +3,3,0,main.step_in[0] +4,4,0,main.step_in[1] +5,-1,0,main.adder diff --git a/examples/toy/pasta/toy_cpp/Makefile b/examples/toy/pasta/toy_cpp/Makefile new file mode 100644 index 0000000..de1a5e7 --- /dev/null +++ b/examples/toy/pasta/toy_cpp/Makefile @@ -0,0 +1,22 @@ +CC=g++ +CFLAGS=-std=c++11 -O3 -I. +DEPS_HPP = circom.hpp calcwit.hpp fr.hpp +DEPS_O = main.o calcwit.o fr.o fr_asm.o + +ifeq ($(shell uname),Darwin) + NASM=nasm -fmacho64 --prefix _ +endif +ifeq ($(shell uname),Linux) + NASM=nasm -felf64 +endif + +all: toy + +%.o: %.cpp $(DEPS_HPP) + $(CC) -c $< $(CFLAGS) + +fr_asm.o: fr.asm + $(NASM) fr.asm -o fr_asm.o + +toy: $(DEPS_O) toy.o + $(CC) -o toy *.o -lgmp diff --git a/examples/toy/pasta/toy_cpp/calcwit.cpp b/examples/toy/pasta/toy_cpp/calcwit.cpp new file mode 100644 index 0000000..949fea4 --- /dev/null +++ b/examples/toy/pasta/toy_cpp/calcwit.cpp @@ -0,0 +1,126 @@ +#include +#include +#include +#include "calcwit.hpp" + +extern void run(Circom_CalcWit* ctx); + +std::string int_to_hex( u64 i ) +{ + std::stringstream stream; + stream << "0x" + << std::setfill ('0') << std::setw(16) + << std::hex << i; + return stream.str(); +} + +u64 fnv1a(std::string s) { + u64 hash = 0xCBF29CE484222325LL; + for(char& c : s) { + hash ^= u64(c); + hash *= 0x100000001B3LL; + } + return hash; +} + +Circom_CalcWit::Circom_CalcWit (Circom_Circuit *aCircuit, uint maxTh) { + circuit = aCircuit; + inputSignalAssignedCounter = get_main_input_signal_no(); + inputSignalAssigned = new bool[inputSignalAssignedCounter]; + for (int i = 0; i< inputSignalAssignedCounter; i++) { + inputSignalAssigned[i] = false; + } + signalValues = new FrElement[get_total_signal_no()]; + Fr_str2element(&signalValues[0], "1", 10); + componentMemory = new Circom_Component[get_number_of_components()]; + circuitConstants = circuit ->circuitConstants; + templateInsId2IOSignalInfo = circuit -> templateInsId2IOSignalInfo; + + maxThread = maxTh; + + // parallelism + numThread = 0; + +} + +Circom_CalcWit::~Circom_CalcWit() { + // ... +} + +uint Circom_CalcWit::getInputSignalHashPosition(u64 h) { + uint n = get_size_of_input_hashmap(); + uint pos = (uint)(h % (u64)n); + if (circuit->InputHashMap[pos].hash!=h){ + uint inipos = pos; + pos++; + while (pos != inipos) { + if (circuit->InputHashMap[pos].hash==h) return pos; + if (circuit->InputHashMap[pos].hash==0) { + fprintf(stderr, "Signal not found\n"); + assert(false); + } + pos = (pos+1)%n; + } + fprintf(stderr, "Signals not found\n"); + assert(false); + } + return pos; +} + +void Circom_CalcWit::tryRunCircuit(){ + if (inputSignalAssignedCounter == 0) { + run(this); + } +} + +void Circom_CalcWit::setInputSignal(u64 h, uint i, FrElement & val){ + if (inputSignalAssignedCounter == 0) { + fprintf(stderr, "No more signals to be assigned\n"); + assert(false); + } + uint pos = getInputSignalHashPosition(h); + if (i >= circuit->InputHashMap[pos].signalsize) { + fprintf(stderr, "Input signal array access exceeds the size\n"); + assert(false); + } + + uint si = circuit->InputHashMap[pos].signalid+i; + if (inputSignalAssigned[si-get_main_input_signal_start()]) { + fprintf(stderr, "Signal assigned twice: %d\n", si); + assert(false); + } + signalValues[si] = val; + inputSignalAssigned[si-get_main_input_signal_start()] = true; + inputSignalAssignedCounter--; + tryRunCircuit(); +} + +u64 Circom_CalcWit::getInputSignalSize(u64 h) { + uint pos = getInputSignalHashPosition(h); + return circuit->InputHashMap[pos].signalsize; +} + +std::string Circom_CalcWit::getTrace(u64 id_cmp){ + if (id_cmp == 0) return componentMemory[id_cmp].componentName; + else{ + u64 id_father = componentMemory[id_cmp].idFather; + std::string my_name = componentMemory[id_cmp].componentName; + + return Circom_CalcWit::getTrace(id_father) + "." + my_name; + } + + +} + +std::string Circom_CalcWit::generate_position_array(uint* dimensions, uint size_dimensions, uint index){ + std::string positions = ""; + + for (uint i = 0 ; i < size_dimensions; i++){ + uint last_pos = index % dimensions[size_dimensions -1 - i]; + index = index / dimensions[size_dimensions -1 - i]; + std::string new_pos = "[" + std::to_string(last_pos) + "]"; + positions = new_pos + positions; + } + return positions; +} + diff --git a/examples/toy/pasta/toy_cpp/calcwit.hpp b/examples/toy/pasta/toy_cpp/calcwit.hpp new file mode 100644 index 0000000..363de21 --- /dev/null +++ b/examples/toy/pasta/toy_cpp/calcwit.hpp @@ -0,0 +1,69 @@ +#ifndef CIRCOM_CALCWIT_H +#define CIRCOM_CALCWIT_H + +#include +#include +#include +#include +#include + +#include "circom.hpp" +#include "fr.hpp" + +#define NMUTEXES 32 //512 + +u64 fnv1a(std::string s); + +class Circom_CalcWit { + + bool *inputSignalAssigned; + uint inputSignalAssignedCounter; + + Circom_Circuit *circuit; + +public: + + FrElement *signalValues; + Circom_Component* componentMemory; + FrElement* circuitConstants; + std::map templateInsId2IOSignalInfo; + std::string* listOfTemplateMessages; + + // parallelism + std::mutex numThreadMutex; + std::condition_variable ntcvs; + int numThread; + + int maxThread; + + // Functions called by the circuit + Circom_CalcWit(Circom_Circuit *aCircuit, uint numTh = NMUTEXES); + ~Circom_CalcWit(); + + // Public functions + void setInputSignal(u64 h, uint i, FrElement &val); + void tryRunCircuit(); + + u64 getInputSignalSize(u64 h); + + inline uint getRemaingInputsToBeSet() { + return inputSignalAssignedCounter; + } + + inline void getWitness(uint idx, PFrElement val) { + Fr_copy(val, &signalValues[circuit->witness2SignalList[idx]]); + } + + std::string getTrace(u64 id_cmp); + + std::string generate_position_array(uint* dimensions, uint size_dimensions, uint index); + +private: + + uint getInputSignalHashPosition(u64 h); + +}; + +typedef void (*Circom_TemplateFunction)(uint __cIdx, Circom_CalcWit* __ctx); + +#endif // CIRCOM_CALCWIT_H diff --git a/examples/toy/pasta/toy_cpp/calcwit.o b/examples/toy/pasta/toy_cpp/calcwit.o new file mode 100644 index 0000000000000000000000000000000000000000..28d1cc35f81e5c8811e254c03eb0b763d0e356da GIT binary patch literal 16120 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 Y6lrb7{|PlH+XGwjC-_EBA|>g603H0sKL7v# literal 0 HcmV?d00001 diff --git a/examples/toy/pasta/toy_cpp/circom.hpp b/examples/toy/pasta/toy_cpp/circom.hpp new file mode 100644 index 0000000..eabc686 --- /dev/null +++ b/examples/toy/pasta/toy_cpp/circom.hpp @@ -0,0 +1,85 @@ +#ifndef __CIRCOM_H +#define __CIRCOM_H + +#include +#include +#include +#include +#include + +#include "fr.hpp" + +typedef unsigned long long u64; +typedef uint32_t u32; +typedef uint8_t u8; + +//only for the main inputs +struct __attribute__((__packed__)) HashSignalInfo { + u64 hash; + u64 signalid; + u64 signalsize; +}; + +struct IODef { + u32 offset; + u32 len; + u32 *lengths; +}; + +struct IODefPair { + u32 len; + IODef* defs; +}; + +struct Circom_Circuit { + // const char *P; + HashSignalInfo* InputHashMap; + u64* witness2SignalList; + FrElement* circuitConstants; + std::map templateInsId2IOSignalInfo; +}; + + +struct Circom_Component { + u32 templateId; + u64 signalStart; + u32 inputCounter; + std::string templateName; + std::string componentName; + u64 idFather; + u32* subcomponents = NULL; + bool* subcomponentsParallel = NULL; + bool *outputIsSet = NULL; //one for each output + std::mutex *mutexes = NULL; //one for each output + std::condition_variable *cvs = NULL; + std::thread *sbct = NULL;//subcomponent threads +}; + +/* +For every template instantiation create two functions: +- name_create +- name_run + +//PFrElement: pointer to FrElement + +Every name_run or circom_function has: +===================================== + +//array of PFrElements for auxiliars in expression computation (known size); +PFrElements expaux[]; + +//array of PFrElements for local vars (known size) +PFrElements lvar[]; + +*/ + +uint get_main_input_signal_start(); +uint get_main_input_signal_no(); +uint get_total_signal_no(); +uint get_number_of_components(); +uint get_size_of_input_hashmap(); +uint get_size_of_witness(); +uint get_size_of_constants(); +uint get_size_of_io_map(); + +#endif // __CIRCOM_H diff --git a/examples/toy/toy_cpp/fr.asm b/examples/toy/pasta/toy_cpp/fr.asm similarity index 99% rename from examples/toy/toy_cpp/fr.asm rename to examples/toy/pasta/toy_cpp/fr.asm index d539042..0e180a5 100644 --- a/examples/toy/toy_cpp/fr.asm +++ b/examples/toy/pasta/toy_cpp/fr.asm @@ -65,6 +65,10 @@ + + + + ;;;;;;;;;;;;;;;;;;;;;; ; copy ;;;;;;;;;;;;;;;;;;;;;; @@ -284,15 +288,12 @@ Fr_long: jnc Fr_longNormal Fr_longMontgomery: - mov r8, rdi sub rsp, 40 + push rsi + mov rsi, rdi mov rdi, rsp - push rdx - push r8 call Fr_toNormal - mov rsi, rdi - pop rdi - pop rdx + pop rsi Fr_longNormal: diff --git a/examples/toy/pasta/toy_cpp/fr.cpp b/examples/toy/pasta/toy_cpp/fr.cpp new file mode 100644 index 0000000..14864de --- /dev/null +++ b/examples/toy/pasta/toy_cpp/fr.cpp @@ -0,0 +1,321 @@ +#include "fr.hpp" +#include +#include +#include +#include +#include + + +static mpz_t q; +static mpz_t zero; +static mpz_t one; +static mpz_t mask; +static size_t nBits; +static bool initialized = false; + + +void Fr_toMpz(mpz_t r, PFrElement pE) { + FrElement tmp; + Fr_toNormal(&tmp, pE); + if (!(tmp.type & Fr_LONG)) { + mpz_set_si(r, tmp.shortVal); + if (tmp.shortVal<0) { + mpz_add(r, r, q); + } + } else { + mpz_import(r, Fr_N64, -1, 8, -1, 0, (const void *)tmp.longVal); + } +} + +void Fr_fromMpz(PFrElement pE, mpz_t v) { + if (mpz_fits_sint_p(v)) { + pE->type = Fr_SHORT; + pE->shortVal = mpz_get_si(v); + } else { + pE->type = Fr_LONG; + for (int i=0; ilongVal[i] = 0; + mpz_export((void *)(pE->longVal), NULL, -1, 8, -1, 0, v); + } +} + + +bool Fr_init() { + if (initialized) return false; + initialized = true; + mpz_init(q); + mpz_import(q, Fr_N64, -1, 8, -1, 0, (const void *)Fr_q.longVal); + mpz_init_set_ui(zero, 0); + mpz_init_set_ui(one, 1); + nBits = mpz_sizeinbase (q, 2); + mpz_init(mask); + mpz_mul_2exp(mask, one, nBits); + mpz_sub(mask, mask, one); + return true; +} + +void Fr_str2element(PFrElement pE, char const *s, uint base) { + mpz_t mr; + mpz_init_set_str(mr, s, base); + mpz_fdiv_r(mr, mr, q); + Fr_fromMpz(pE, mr); + mpz_clear(mr); +} + +char *Fr_element2str(PFrElement pE) { + FrElement tmp; + mpz_t r; + if (!(pE->type & Fr_LONG)) { + if (pE->shortVal>=0) { + char *r = new char[32]; + sprintf(r, "%d", pE->shortVal); + return r; + } else { + mpz_init_set_si(r, pE->shortVal); + mpz_add(r, r, q); + } + } else { + Fr_toNormal(&tmp, pE); + mpz_init(r); + mpz_import(r, Fr_N64, -1, 8, -1, 0, (const void *)tmp.longVal); + } + char *res = mpz_get_str (0, 10, r); + mpz_clear(r); + return res; +} + +void Fr_idiv(PFrElement r, PFrElement a, PFrElement b) { + mpz_t ma; + mpz_t mb; + mpz_t mr; + mpz_init(ma); + mpz_init(mb); + mpz_init(mr); + + Fr_toMpz(ma, a); + // char *s1 = mpz_get_str (0, 10, ma); + // printf("s1 %s\n", s1); + Fr_toMpz(mb, b); + // char *s2 = mpz_get_str (0, 10, mb); + // printf("s2 %s\n", s2); + mpz_fdiv_q(mr, ma, mb); + // char *sr = mpz_get_str (0, 10, mr); + // printf("r %s\n", sr); + Fr_fromMpz(r, mr); + + mpz_clear(ma); + mpz_clear(mb); + mpz_clear(mr); +} + +void Fr_mod(PFrElement r, PFrElement a, PFrElement b) { + mpz_t ma; + mpz_t mb; + mpz_t mr; + mpz_init(ma); + mpz_init(mb); + mpz_init(mr); + + Fr_toMpz(ma, a); + Fr_toMpz(mb, b); + mpz_fdiv_r(mr, ma, mb); + Fr_fromMpz(r, mr); + + mpz_clear(ma); + mpz_clear(mb); + mpz_clear(mr); +} + +void Fr_pow(PFrElement r, PFrElement a, PFrElement b) { + mpz_t ma; + mpz_t mb; + mpz_t mr; + mpz_init(ma); + mpz_init(mb); + mpz_init(mr); + + Fr_toMpz(ma, a); + Fr_toMpz(mb, b); + mpz_powm(mr, ma, mb, q); + Fr_fromMpz(r, mr); + + mpz_clear(ma); + mpz_clear(mb); + mpz_clear(mr); +} + +void Fr_inv(PFrElement r, PFrElement a) { + mpz_t ma; + mpz_t mr; + mpz_init(ma); + mpz_init(mr); + + Fr_toMpz(ma, a); + mpz_invert(mr, ma, q); + Fr_fromMpz(r, mr); + mpz_clear(ma); + mpz_clear(mr); +} + +void Fr_div(PFrElement r, PFrElement a, PFrElement b) { + FrElement tmp; + Fr_inv(&tmp, b); + Fr_mul(r, a, &tmp); +} + +void Fr_fail() { + assert(false); +} + + +RawFr::RawFr() { + Fr_init(); + set(fZero, 0); + set(fOne, 1); + neg(fNegOne, fOne); +} + +RawFr::~RawFr() { +} + +void RawFr::fromString(Element &r, const std::string &s, uint32_t radix) { + mpz_t mr; + mpz_init_set_str(mr, s.c_str(), radix); + mpz_fdiv_r(mr, mr, q); + for (int i=0; i>3] & (1 << (p & 0x7))) +void RawFr::exp(Element &r, const Element &base, uint8_t* scalar, unsigned int scalarSize) { + bool oneFound = false; + Element copyBase; + copy(copyBase, base); + for (int i=scalarSize*8-1; i>=0; i--) { + if (!oneFound) { + if ( !BIT_IS_SET(scalar, i) ) continue; + copy(r, copyBase); + oneFound = true; + continue; + } + square(r, r); + if ( BIT_IS_SET(scalar, i) ) { + mul(r, r, copyBase); + } + } + if (!oneFound) { + copy(r, fOne); + } +} + +void RawFr::toMpz(mpz_t r, const Element &a) { + Element tmp; + Fr_rawFromMontgomery(tmp.v, a.v); + mpz_import(r, Fr_N64, -1, 8, -1, 0, (const void *)tmp.v); +} + +void RawFr::fromMpz(Element &r, const mpz_t a) { + for (int i=0; i #include +#ifdef __APPLE__ +#include // typedef unsigned int uint; +#endif // __APPLE__ + #define Fr_N64 4 #define Fr_SHORT 0x00000000 #define Fr_LONG 0x80000000 @@ -68,7 +72,7 @@ extern "C" void Fr_fail(); // Pending functions to convert -void Fr_str2element(PFrElement pE, char const*s, int base); +void Fr_str2element(PFrElement pE, char const*s, uint base); char *Fr_element2str(PFrElement pE); void Fr_idiv(PFrElement r, PFrElement a, PFrElement b); void Fr_mod(PFrElement r, PFrElement a, PFrElement b); @@ -97,9 +101,11 @@ class RawFr { RawFr(); ~RawFr(); - Element &zero() { return fZero; }; - Element &one() { return fOne; }; - Element &negOne() { return fNegOne; }; + const Element &zero() { return fZero; }; + const Element &one() { return fOne; }; + const Element &negOne() { return fNegOne; }; + Element set(int value); + void set(Element &r, int value); void fromString(Element &r, const std::string &n, uint32_t radix = 10); std::string toString(const Element &a, uint32_t radix = 10); @@ -109,6 +115,22 @@ class RawFr { void inline add(Element &r, const Element &a, const Element &b) { Fr_rawAdd(r.v, a.v, b.v); }; void inline sub(Element &r, const Element &a, const Element &b) { Fr_rawSub(r.v, a.v, b.v); }; void inline mul(Element &r, const Element &a, const Element &b) { Fr_rawMMul(r.v, a.v, b.v); }; + + Element inline add(const Element &a, const Element &b) { Element r; Fr_rawAdd(r.v, a.v, b.v); return r;}; + Element inline sub(const Element &a, const Element &b) { Element r; Fr_rawSub(r.v, a.v, b.v); return r;}; + Element inline mul(const Element &a, const Element &b) { Element r; Fr_rawMMul(r.v, a.v, b.v); return r;}; + + Element inline neg(const Element &a) { Element r; Fr_rawNeg(r.v, a.v); return r; }; + Element inline square(const Element &a) { Element r; Fr_rawMSquare(r.v, a.v); return r; }; + + Element inline add(int a, const Element &b) { return add(set(a), b);}; + Element inline sub(int a, const Element &b) { return sub(set(a), b);}; + Element inline mul(int a, const Element &b) { return mul(set(a), b);}; + + Element inline add(const Element &a, int b) { return add(a, set(b));}; + Element inline sub(const Element &a, int b) { return sub(a, set(b));}; + Element inline mul(const Element &a, int b) { return mul(a, set(b));}; + void inline mul1(Element &r, const Element &a, uint64_t b) { Fr_rawMMul1(r.v, a.v, b); }; void inline neg(Element &r, const Element &a) { Fr_rawNeg(r.v, a.v); }; void inline square(Element &r, const Element &a) { Fr_rawMSquare(r.v, a.v); }; @@ -124,6 +146,11 @@ class RawFr { void toMpz(mpz_t r, const Element &a); void fromMpz(Element &a, const mpz_t r); + int toRprBE(const Element &element, uint8_t *data, int bytes); + int fromRprBE(Element &element, const uint8_t *data, int bytes); + + int bytes ( void ) { return Fr_N64 * 8; }; + void fromUI(Element &r, unsigned long int v); static RawFr field; diff --git a/examples/toy/pasta/toy_cpp/fr.o b/examples/toy/pasta/toy_cpp/fr.o new file mode 100644 index 0000000000000000000000000000000000000000..d6fc2487f3288401b3466de2cdc767a41ea86477 GIT binary patch literal 14304 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 literal 0 HcmV?d00001 diff --git a/examples/toy/toy_cpp/fr_asm.o b/examples/toy/pasta/toy_cpp/fr_asm.o similarity index 56% rename from examples/toy/toy_cpp/fr_asm.o rename to examples/toy/pasta/toy_cpp/fr_asm.o index 6c96ae4cc03b0d40c9d3327baece1367d0aa6775..b68efe95bc003c704d59c26bef7c78063ad48115 100644 GIT binary patch literal 36778 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 IG{g6Q0LXedO#lD@ diff --git a/examples/toy/pasta/toy_cpp/main.cpp b/examples/toy/pasta/toy_cpp/main.cpp new file mode 100644 index 0000000..18d846c --- /dev/null +++ b/examples/toy/pasta/toy_cpp/main.cpp @@ -0,0 +1,288 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using json = nlohmann::json; + +#include "calcwit.hpp" +#include "circom.hpp" + + +#define handle_error(msg) \ + do { perror(msg); exit(EXIT_FAILURE); } while (0) + +Circom_Circuit* loadCircuit(std::string const &datFileName) { + Circom_Circuit *circuit = new Circom_Circuit; + + int fd; + struct stat sb; + + fd = open(datFileName.c_str(), O_RDONLY); + if (fd == -1) { + std::cout << ".dat file not found: " << datFileName << "\n"; + throw std::system_error(errno, std::generic_category(), "open"); + } + + if (fstat(fd, &sb) == -1) { /* To obtain file size */ + throw std::system_error(errno, std::generic_category(), "fstat"); + } + + u8* bdata = (u8*)mmap(NULL, sb.st_size, PROT_READ , MAP_PRIVATE, fd, 0); + close(fd); + + circuit->InputHashMap = new HashSignalInfo[get_size_of_input_hashmap()]; + uint dsize = get_size_of_input_hashmap()*sizeof(HashSignalInfo); + memcpy((void *)(circuit->InputHashMap), (void *)bdata, dsize); + + circuit->witness2SignalList = new u64[get_size_of_witness()]; + uint inisize = dsize; + dsize = get_size_of_witness()*sizeof(u64); + memcpy((void *)(circuit->witness2SignalList), (void *)(bdata+inisize), dsize); + + circuit->circuitConstants = new FrElement[get_size_of_constants()]; + if (get_size_of_constants()>0) { + inisize += dsize; + dsize = get_size_of_constants()*sizeof(FrElement); + memcpy((void *)(circuit->circuitConstants), (void *)(bdata+inisize), dsize); + } + + std::map templateInsId2IOSignalInfo1; + if (get_size_of_io_map()>0) { + u32 index[get_size_of_io_map()]; + inisize += dsize; + dsize = get_size_of_io_map()*sizeof(u32); + memcpy((void *)index, (void *)(bdata+inisize), dsize); + inisize += dsize; + assert(inisize % sizeof(u32) == 0); + assert(sb.st_size % sizeof(u32) == 0); + u32 dataiomap[(sb.st_size-inisize)/sizeof(u32)]; + memcpy((void *)dataiomap, (void *)(bdata+inisize), sb.st_size-inisize); + u32* pu32 = dataiomap; + + for (int i = 0; i < get_size_of_io_map(); i++) { + u32 n = *pu32; + IODefPair p; + p.len = n; + IODef defs[n]; + pu32 += 1; + for (u32 j = 0; j templateInsId2IOSignalInfo = move(templateInsId2IOSignalInfo1); + + munmap(bdata, sb.st_size); + + return circuit; +} + +bool check_valid_number(std::string & s, uint base){ + bool is_valid = true; + if (base == 16){ + for (uint i = 0; i < s.size(); i++){ + is_valid &= ( + ('0' <= s[i] && s[i] <= '9') || + ('a' <= s[i] && s[i] <= 'f') || + ('A' <= s[i] && s[i] <= 'F') + ); + } + } else{ + for (uint i = 0; i < s.size(); i++){ + is_valid &= ('0' <= s[i] && s[i] < char(int('0') + base)); + } + } + return is_valid; +} + +void json2FrElements (json val, std::vector & vval){ + if (!val.is_array()) { + FrElement v; + std::string s_aux, s; + uint base; + if (val.is_string()) { + s_aux = val.get(); + std::string possible_prefix = s_aux.substr(0, 2); + if (possible_prefix == "0b" || possible_prefix == "0B"){ + s = s_aux.substr(2, s_aux.size() - 2); + base = 2; + } else if (possible_prefix == "0o" || possible_prefix == "0O"){ + s = s_aux.substr(2, s_aux.size() - 2); + base = 8; + } else if (possible_prefix == "0x" || possible_prefix == "0X"){ + s = s_aux.substr(2, s_aux.size() - 2); + base = 16; + } else{ + s = s_aux; + base = 10; + } + if (!check_valid_number(s, base)){ + std::ostringstream errStrStream; + errStrStream << "Invalid number in JSON input: " << s_aux << "\n"; + throw std::runtime_error(errStrStream.str() ); + } + } else if (val.is_number()) { + double vd = val.get(); + std::stringstream stream; + stream << std::fixed << std::setprecision(0) << vd; + s = stream.str(); + base = 10; + } else { + std::ostringstream errStrStream; + errStrStream << "Invalid JSON type\n"; + throw std::runtime_error(errStrStream.str() ); + } + Fr_str2element (&v, s.c_str(), base); + vval.push_back(v); + } else { + for (uint i = 0; i < val.size(); i++) { + json2FrElements (val[i], vval); + } + } +} + + +void loadJson(Circom_CalcWit *ctx, std::string filename) { + std::ifstream inStream(filename); + json j; + inStream >> j; + + u64 nItems = j.size(); + // printf("Items : %llu\n",nItems); + if (nItems == 0){ + ctx->tryRunCircuit(); + } + for (json::iterator it = j.begin(); it != j.end(); ++it) { + // std::cout << it.key() << " => " << it.value() << '\n'; + u64 h = fnv1a(it.key()); + std::vector v; + json2FrElements(it.value(),v); + uint signalSize = ctx->getInputSignalSize(h); + if (v.size() < signalSize) { + std::ostringstream errStrStream; + errStrStream << "Error loading signal " << it.key() << ": Not enough values\n"; + throw std::runtime_error(errStrStream.str() ); + } + if (v.size() > signalSize) { + std::ostringstream errStrStream; + errStrStream << "Error loading signal " << it.key() << ": Too many values\n"; + throw std::runtime_error(errStrStream.str() ); + } + for (uint i = 0; i " << Fr_element2str(&(v[i])) << '\n'; + ctx->setInputSignal(h,i,v[i]); + } catch (std::runtime_error e) { + std::ostringstream errStrStream; + errStrStream << "Error setting signal: " << it.key() << "\n" << e.what(); + throw std::runtime_error(errStrStream.str() ); + } + } + } +} + +void writeBinWitness(Circom_CalcWit *ctx, std::string wtnsFileName) { + FILE *write_ptr; + + write_ptr = fopen(wtnsFileName.c_str(),"wb"); + + fwrite("wtns", 4, 1, write_ptr); + + u32 version = 2; + fwrite(&version, 4, 1, write_ptr); + + u32 nSections = 2; + fwrite(&nSections, 4, 1, write_ptr); + + // Header + u32 idSection1 = 1; + fwrite(&idSection1, 4, 1, write_ptr); + + u32 n8 = Fr_N64*8; + + u64 idSection1length = 8 + n8; + fwrite(&idSection1length, 8, 1, write_ptr); + + fwrite(&n8, 4, 1, write_ptr); + + fwrite(Fr_q.longVal, Fr_N64*8, 1, write_ptr); + + uint Nwtns = get_size_of_witness(); + + u32 nVars = (u32)Nwtns; + fwrite(&nVars, 4, 1, write_ptr); + + // Data + u32 idSection2 = 2; + fwrite(&idSection2, 4, 1, write_ptr); + + u64 idSection2length = (u64)n8*(u64)Nwtns; + fwrite(&idSection2length, 8, 1, write_ptr); + + FrElement v; + + for (int i=0;igetWitness(i, &v); + Fr_toLongNormal(&v, &v); + fwrite(v.longVal, Fr_N64*8, 1, write_ptr); + } + fclose(write_ptr); +} + +int main (int argc, char *argv[]) { + std::string cl(argv[0]); + if (argc!=3) { + std::cout << "Usage: " << cl << " \n"; + } else { + std::string datfile = cl + ".dat"; + std::string jsonfile(argv[1]); + std::string wtnsfile(argv[2]); + + // auto t_start = std::chrono::high_resolution_clock::now(); + + Circom_Circuit *circuit = loadCircuit(datfile); + + Circom_CalcWit *ctx = new Circom_CalcWit(circuit); + + loadJson(ctx, jsonfile); + if (ctx->getRemaingInputsToBeSet()!=0) { + std::cerr << "Not all inputs have been set. Only " << get_main_input_signal_no()-ctx->getRemaingInputsToBeSet() << " out of " << get_main_input_signal_no() << std::endl; + assert(false); + } + /* + for (uint i = 0; igetWitness(i, &x); + std::cout << i << ": " << Fr_element2str(&x) << std::endl; + } + */ + + //auto t_mid = std::chrono::high_resolution_clock::now(); + //std::cout << std::chrono::duration(t_mid-t_start).count()<(t_end-t_mid).count()<tcNVL}n6lR20f#}R= z4%4yR-rCyR+R}%=(%bfyKEQ|t6Tu|nqd|P2SVZx`c&y?pgon)kyY@ck%uEP^x8C3F z=lA*NlQU<(_u6Z(z4qQ~t-a4*cmI9g0H4p_*T)Y}Kb~dcDdXYqSe{|xKfvGigyi!1 zI-E4FpE7;&43tRzrcH~^oFCP0?Vl8!GAZYGUE5C1l~+XI@+QA;p%hZ&Yjo4dd)lo4y{MIp^A& zs=lNGdzM%GMGe<9`wbH0Ad^}0Cxh3#GLlvg%HCzwxp`F{@BUJ&KYx@B&zLwc6iY3lr-U;W(|*6=L@ ze^+{?JWPlvj4CE^o>Ue%~3nWS&dPyLtAtGosUCx6J$cE!Rz( z7OwXqacr8P3#vUvhc3O$fp3%Fca4rJX!5jaGjEvIFz4EvXX^Al+dFKA&eVCbj^Em# z%e!xzrkBHgz8iFm{{14aVLUoliO<)UhrbFQ>C>g;TgqF2kaV@L`+Ywoapxy~U)fK5 zKFae=M3RXSt)Vj`kMY+_E z)nc}8?Q5oMYMt1i29Cgb0z;_<6#Hh_+MSoB-E4iUubaGB7qhl?TVE0vPe_lfF|C*K zQo9v2x;aXfBiRzRZeAKat=_*!`BjA@8!4kSlpc9P*!n;P2dr1>tq&vC8)iD#qEHoV z0gcU08Ajrlv`=|V>w)<+TQ#VU4vDuIW_;@ovtnJydfh3mjS4SL4_P5Sa7lXPnPKZK z6*De9@=t-Tw!TL49ZC#aGw%zhRtp{jUF`(EL13g}XV~hd#JxR>4_n(qfM^99L;kj~ z^as^Q7{eJk0(U4ivfNB9XwfBPgB@n-fg4n(1(yV@aU&wu!pd+ewmg(= zQ%S6rP<5LT{}WwF10`i3H5KP3x~+%;n|gvmOGEL;h?=^@Ol}TavE@eM-)U>Gikv}T zomEs5OvQ@EThW@Lu=SzYx~-4t5X1zlzNR>ojuo3$yW59>^te8e^i4@$DBfNgu3pd- zd+3qFC~l1mFjaSa!4jX5Sb{es+1eo&Gc{SmB`q;iQ(J%}c9y-ULH(U$3{Q~S=j&0B zWY=kshOU+>8pXO15*Rn1g1@0Yo<%isPy|* z)e>zF!gs#-0+KjAcF(zfUZZ>jsS1q4&D2<;B=9f9ts073S1n!NrJd~34z^OIyIwe%C?ys-q!90kDev{;$y7N z&h6pU_~LNtveNjz(%8t_m41qd-Q2jlk8$T?gM2$Pq#dqfawB)_HxM|YVKe+pJBn0O{LsmRHZB}eoJ zl6sY-j@{D`Fm8Di07(8#W>-m`&Aiv27BucEoqLi-W~?wRL+@C<})IUpKQ_4qK0!@z?e>7_&-lI>Ya)>T0OR`3;=n7~1SOPMme74ms^j z2{C4kxzLA>o&6>GfoS5i{#=+dVsh`KjFN$SlVX1uM;j6b^1NRFppGS`4vjWuF#c@#{{ z?t}yEhrr9gc$gVDzEvUc%nA>Il{f`~{m#eX@N+P6ox;aWf{)oBO$Lsty|`X}m!D^| zfVfT?0IZvNMpr#8Kbz&}8Nz41)?hTeCXQ!tY-})YeAW$pOB^o|3Px@OPculmc`JoJ zrs{YO*Hco*-?Ai>J{VoqB0rDo3dsBcnLo@gWs7*gRD zlI$ari9;oOhh!f+NnQePQ37m<-TR4C{!8FBDivMVL0Xb*mI|NbE%d%uX!T_rFHuoc z94Z;zw0RSc)czcSn_s}ORvhh$601Kjk|%*ql0dw(JE&tb#m{b~JB2i6;hD36HcRL% z0>05%tYa3o33E$aN;d?$T80^kFfP-2K@aopT4N@x4n4DQWHr^jDeZ>kc@)2(N)s^(N!dp z0DfBJXET99B@Hr4X8|yr!?^KP9U3qigh|foo}F)JRxNhnk4* z!A04@9j3LLE^w&0#6A`LLd6|EI;ESUr8{N~eO(35I`JKO7vg_mxp3Zh==srA4D{*#_013|8!5jSFh#O2BoA*FMG8X^J6afjn5L-bZhcXte-O`ZclRF`whY__< zc1eGrs_LR${^(paH~I;McVBnn-czJGvrem5@V^9X%x=bYXMd#pQT%&{-k{vG`t8tZ z=!Yne{TOM_zFLQoM<&D3rNX=zUy3Q6{d-+FjC*#g^aQkiNIem*X8Vz4i4y2)EjAL> ztSn4xy_y_dZc;Ksl`Z`M4bSR#op^=cIO!O{&Z7|5buH3W^o;Ut0eorrdl1y$tE zhH>J?j4opUj4p*sY=(bqhJPq-v0iue1|xZ^<`#$2-QX&AeC8QYq}GROy=i7!LxRG; zNa)IX!_RW_O|{&7%~@`~q?Vh{=;bE;Gpl4LBi}#MYN2`*;|DdY=-RV*0iX2&Kky;V6Vz<3<}jMyK=W@Do~zam+vtJ@SxwvsIn7{P$}(Z|t30QrRar81 z{WmD&Z!A+ag{;J7S{)vRfYn+30;=o_${zJm^)2hE;&CDMq1C$16D5AhhsMI|21rv6 zG(O>cYJ9>UdmW$f<`%|hs~Vq&!rtky=;_}6!08_2{zskld?)L9-G8xdwTUj{-j=Cr ztrs%C`Vg_p?o1ainee>zNKbiK2VEYrxM)Fr+rfT!@KH>BOrEHgL{Lx53 z{+d3~6Vx^*(Goi)a~IQ%MCZy6vCA@3X0dr@vDvz-$l7dHzc}y2%v2I8dUN7SRfKU@ zP|a6a)7qkTh6sL4XD5nNwyt3)+Z6|8*9HL6ZzSgtXs?i6cSUfi*&bXD&_3KPxI4vN zgLG(_3QLyJ3bQ>~$xC7o(@99!%Bl*xf=m6;fe3$=E3cVS3E9&xH%6$es)qD}CNmvd zs>F6x&xEWUD)HiA(=vdGfx+^9HAP19*D`z_3|eC=zlJ06oaen*yltL$mU!pFuFQ1M z%FHCZXb-r*`x0glKo$6U0rdl;R7HJY3=TG$>D7`<1D#$it#e^dncG+G!GG%aN=EaF zuP?H+%S_d7H`^2aY6+F{DKOZmN(iS{OHzasO<`-F3hD~N`vozbx(;MNV5O5RO$yPe z6BUT5zDRg#O-rL$DzLuYParc>btb_YFglr*#al`Vk&3#K^ZE5h2brnWO}I1=PM4VR zwZ%^JT(ZEs)J^uVNV+n=2Wci!u0FBz5xU%GJXn0kF2QfRi3oGF;>+3$$1adLBmD-jfQ#jKqVaHC9HJcD4GWLq+goAL)80DevXxhKw0+ z-RHs#p{$~B8C9B0_QRx0VjxqYP4M}!i0(2{*XL52)NkLUP(=e?I|wo2&rgF z-_NDCVgZ|KoI#vuF%o|V-(A5bO+xpnx)mO%Hr8nu0Z=RWn!-4CL^& zr=HY*VdM9&A}cNThpHbl?tTlfCZq?IhpRJTV|>PZ=sf+`H&p#(*r?kcN&Y=LT%~L$ zv(Lsbjwe zggax+Jdvb*v3;qeE~HoyV7A2_Ni(?VE4V2uLiD}y0%KcTs4NEU(1~Jc0#`e_Q#=&8$Wk2gVb^4A_;!Y@6oWc;El zh*&q3&vs{jR~XOC6te2ei?wp0zT8B+P+vYJ&|Y7DgV3ZIUss$rvXoLpOSj`~j8Cns zvilMqim#(|9pKhdus(9vUsp^7|4v&&DfEk%4$EtoZgt+YIlj1Sys5b9ZBtZ-x`m^= zDAqlp`#HXLHeL;|XcClYJa2vG*01%U@pq^dFwPcah0?(rWR5qjyBqOF(hKN;MJPGu z4f6mUSK0$ovweKAWTq#=sp;E8{=GEcv|=3!oKSnByh)<@3*h#8BQ>s=g38dSP~ep# z=vMl3(&6+i8p}&7o&N2M)@)eVIum{fRPjbi30t?7LhQQuy#5nijZ(wZO)&=7-Oye) zU$o2MVOU|u^}v_vG&62Dx`gWDHDBK#`s4lki&c+DhoRIs)3nBy(r+k-^80OA*Z3*A z-)>MCam()khXX>7elv#qdiK|7wOIdT@c`B+^c`6qwsru(=zN5w$N5>1 zn-x#rdYDVr_L#ZVsEIp8*%|V;%j8;`TmOfv_rSB_Yj-ehxyv{E?TB@IIm(xtI|GY@ zzI`1v1B|=x1w>{bP5@^vG5J%g6WJCA0PSjKwBzRZh~JpoZ0 zCF(yVYNQv1HbtW167_3|I@XIiT1P!AQNJMyMcU!GnTUq+QV7gg03{hR85n1Qy33t~ znH|v!YGs+39(vU=YPr~49%Wl zX}b3&7jKeT@=aj>1dwqzqg zvR`YGx1b=sLV{eBE>4Rt@p$yS#$EpCNsYVIUgcg%ZKf_}gWSh#?JklTw#6D}BD|v&e^xpZpwn{3B4x`H0d0wGD(n~5EPU_Sn zL9-=j7%h;jP^8a3-0?_r*c3_~;q>o@Njgzc*3-zi%2uiYbJFCX+ObE*U$UE*L;THB z7JqQqWbxiCbkiq#oPamVg+=5cmdawEwZsif)k>g`4E8bk@&y2tQUqF9DJYj3Rfn+c zNG@07%H2=Gfb>9h2XDw)*Oipk=q2C?T$+GHl8~&#OYyb51Ynm_)A`-hNVmGhi8H-I zlB?Wqhtp@+S?HitT9t;iiWF+?HY?Vft-Jf054-yk)A;>Hlyc}~@4O$Njk~L1NfCHv z^hB8Q>_MCj#&$D32yMR9QE$DistIHtljWgQkxHtXD!L)6z7)PTT)lnX zqh>P8Cfia_IDjd_fyRu4pL!$KCyRZ|5s7lfc8%ZZ&sYWJDY8mU#C+qK=$W4U$+R|@ zsUr!CeQck{{A6Yo^=NX)e5gQy2Ug2wnPnCI$pYeH==%}^2gi1pR$2;n(yx{D>D4k& z9PskQ3M@^MOH_ectf1UT0=&dpP@saHttVxTW^g-Y>3JB#5M^ocEt+fIu}%hf-VDbq z(11i2cJiQ-29&JfwQ4qLRUw(@)l9M4qcRd6VMuxvly7Mv`v4g*y7D|~Nss#A2+AA+ zO}YH3=e|qE3)xLKyWZ)D*JT6;-hGYSAHtic@3TQTQy`RW;r|4L-}SJGk)IDUkKr;a zC8c?KAWm`Ht@l_mX}RsT56j5D*4-+3{g7EAp%>a1wo#NC(?;TFgfSpSxW%bNBmfsO zgmsU8MKbow%#pO#+KkCt$>8wBcO%a`Uq!s4yD`1Gn8NY~z8mZT0zr%^$)WpbaOhCL zrx3(hgFrX+c<5H!Z&jC<*_n|+1nVewoAo&ojWyQl{jMe{lD|OvUEW@WJw(_#l|2Ym#8nlJ zq%t-6+4%b6Kv&R*g=i#ob1A!t>|@LuVe4JpB-uWjDP*K@uyjq|RJ3nd{OKYc*K=#K z&Sn$3&OV7BZ|ZSusPrCBXS-vqfRLMW^j_2B&)$APS-YaKAnAu}tKD4*+|UYcqH|hc z_-gwMXsP-EBVe{264ajD!Ao#J_sZ6psZP>{(A;^@OLmBAl z7I;+M?)YVp2tJfo50V@JG!f{_7!7$%Nvoc4vU?+7Kl;ByXrKIot>f9VH;!f_fRMeI zS+-1Xb8~Q2wb<_z>|S6}-%%1dPn>_anqnq*LjG(1N@pto4minZUJ>l{$4Z1n1AvCq zOfA@|b0)IUw|m`L*3A z_&ZZf3yZS77;(q?nb{UZ&$7f$kNU{~c(&7hiusQH4k2sMz_^ULRn^%ZY+-(7EG%fr zMTV{Soyc`gJ0KXz+0k3%vt<(59$Y>`CtALy7>Ak^+~Udl?EYC@TTgaKYov^V zED9`ZtrdKd%unv08U2_8ap(S#so=8#>u(|B_m9CNnkk@pf0&Y+qhAp+Nl$H3{TE8r zm&0#si!VtPb(`stjb`hceM5bt<*eQu8j+=tR`2EDrSK(gGeg<-NcAVN74DP|HBZS~ zp?%tXaK}5#z(9bFfVE;e!!DdU-4#+esTtqKnpL-i!vP?s(~LiXP-JQg zcHAB8ER-p}HjK{|82!E5O)L*kKCQySNslpO<>VHzUY%&73Bf44!;VC(k3t*X5kX2( zDE>=JtBZ74F7zPfx!VYARlt0pa_dCQUQER%9$%cM9po4uyUs;<503+G&SZIo7i zp@?->Qe%8R640zlpi$l}b$}^B`LT8B`m=paNm1XRQT{qFbQ-ZLdu-UU_ebwKCLx&~ zG&uLGT>AV3y^44@?Cg8$+KSG~0WiBXM>*2xO$vZ@3VfCLod%Bl&`K7<&PN>3~KzyZCe2#pjQ)^l0?QB3%l<{@9g0 zbV5Be1ywCfV#_E!Z*Z9@rG!(JNMX@G!P1v#uP!zEpQQ2TY^fpk6Z-*h(c(bnASLsr zhTCg$<~bFxK(`>%EbLM0cFMd~`sRT~5k?v4(|<$Euu0jorlV7yy3klUK=K z@vUObuE8}p@{lXQ{u(}ZGtwi`D?!#2T=wxQQ1^0xKaFZa<%{df|%_9~#!OJ|9rw9 zvQCOv4aKyBiqtUnM%C%L6_pFb{`{Uj`Xu^6LGG*<04%o^l1)Y4L5G5a2X5C=x$AT* z^41?pwy!%rUv`hC8MV*UwE|GVdhCjcj}+&Tu1A}_R;-#+m_K(OE&dMj{JrUMh+d4l z>sWMZe(%|_)Hd$x12QIht824R+_E*(4jj+P=}+VnO+>O-ex5B0b4j7 zYq3wIKOr}F_Eo2atOeMSujSMb31xtW5etXMEa;r`JZN!K+AlkGu~Kp>(Yk}-ltCqX zjKmM!N{%kA9n2A`Oq3**W((cTz?@2D4^*Ep_FuZf7_Lg`&fI;0r4) zGc{0-5PfX_LgY=UIs{3>ICwxSl>cxueHAN^0Kvtv9huu0P7rnrlVXQiz0*j%z!D&w zK5ZW6@{&H@wu46LVIYlF6&Y%?SemHZM=l*@>9Nam2kVVAe;Bxvu z5rDslx@I}EKf03U2Q{`!kp#+lrtp|p=iCdhgOb6Q8qc5_SBy_|D)Z)Q zeai2kBTt_aQsVflGUHU6YGo2*;o|IfSy)Tq$=}kMnV-wFsZyVr*(=K?4ZQu$NGv5e5PRd7qjaMc z4v%&z&#l2O5&U`tA4)~!$E`N(C8ABcj7lRSG?l4Ql(kN010~H${)* z$Xf?%BDeB6ar+0(c?(FeSpl1x=dGhc)^PX$I_UAm%C;gO{(Qo)`-V~8VzUIoutbR8 z)(!D~NH^xS*G%8W>BzM^goqoFGKzkV{;AvHknSs*bnglK-xu8tMZ})Wtfma@Zpl32 zx&NGLRb>l8JbXs11;x;>Q`+TPA(R53JcZDLW?$_5%wX$1auJcm$@B z5Fx4(33Lgqhi+A=E?HX)+D-3`P&!V0-`$1pIHe53_ptZ|IeM>>V@b(eIGI3}CewJS zIx>}Xi(A?n$>Eh&FFvodo5kmq_5?mk8=zjJ2J_OTy$0^w(q>DJ5iT@mi|;rW((T>( zr7cj!jD3heU|Y*em-am=P3!GSuF|E6%9geb(WQyn58nn|nrM3QeOnbX_C{S=%q`6h zxuE=9l6%dZD!${~YCaI(Ah!v>!$&jA)N9lkycA%@;m&bG`)GImc4W-1A&oopxyuGO z*=Kz>EP0oc8M}FY&GVNYPk-q8YM$@&Eav%3kLTz3h4x?O>EzklaLcm%msJC@X}FnJy}ho+JBe)|L%RSRpXOiuu4> z?rJ1lZO68UQYS@Hw;(|acG~^fJdzk=Ihp+!eb`-$eGfu|7k;@*&Gzr|vQG`g7YIv? z3pa4ikA~6?}YukWG<(G*c0}bwc}A1=_=$QMQai3 zO?v{zsH2dOV{+pj;MFHm3(bZUMFQgS0^3pAs9}&IXaYBUtjP46>NP6P%N36phkFdf z+XQKGqa4q?k>_Ndkv*O$ewojtzaami)T!t`U*0yaxM2xro|(V8qDPsj+mIu&II`wy zX`78L!5GD1J@J~d>~iU!DZ1XL%3s{S&>ld>d>;Fk3H~Am^@AV53Y00wL^CddVh?Zx zEmep?V5b^STZ|C0T+=+c8t870qz3ozL&(n z$xnF}^E}++`7?eOU*7thEg3gO7~#~S;!wq3L#k=u zd`zhI4UBC5=B}U727{&+=9&xD1jX!ho(!GbeA(;x*%RCDl3-^vy}v{7Icg6tg*H^S>5?DjCFs-%UUC!U8!KtdHY|CM#rbe> zIDqHE9?$vs>v?YBxr#@|Wd0M!uh!$qu4vF>T4=HukYC#VCb4iXR%ko7za;MTZKD;O zU3F#J+OE>+?N>bJwbtWT+MX|*x=4sGsEVBCF7{6CvHm>JdQa1Jet6N z_QBz|^57H*y!Expny1eg5wf0VdPQF%yI6OMY+SIMdG5c2FtoN2+jO*!xAz@UpSr1U zaVpVw32|8U#x7yG3=y&E_e@nr5k+TvHkC?JRz?_-vZmk*UW~CO_(H%+C?ihUVF&Jb zV>ziJ{(XV?CuQ8N5;E$a=Yj-^MpFBJ#M-L+pjRcRw#t?^I32YK6pqM~Oxj0?$i{_A z>@>xvQ!Af0D@u#!BmL7dJXM_idswMU0nS@fWlwyLW`;8oNS82$X$x7xzU!^Xv$D;r z*bz#Z!^AwVqBU$>_A18x%S>ydS@9ur{=%c#`N3qcF?uOGaXPy^BPmu|NW+YK#Eg(l z>+(>1?=f>rvaFY9BWYXnl5H zERMJ`hhE4x0NuY#cRB3rUj?6L^*-Z!zUOtEt=8ztzo`shy7K(o-iGYqy8%R4`y{0#}a|hOkK|6 z?~A7O4R+;SQE2p1y~no1xF}GH_PM&a*0>jB4q***m}y;3_{F7}J0){c!3=lZhmcqDS+eC4l zk5oO8{8H8IQnX^#{mt~mQovwwI|$J!XgCbsYOQa(*e!!1Xo-cH-!sueDFT~!DZ^dA zy7Vjh;L&h_#*6yKj#YYKVG1a^r29O!RHy`YrQGQSv`;Uiu-^2)qeg#cp$Th?Hep@v zSn;)Mn_{grUJhxlIY*{G>qRxV4yHF=u1r_a9%H(iEiheeQTe;jEGyGh%`r&inXVEc zrmH%lcLj5={8I2UpV1mnXB*ps%|p!Q=r?E2oHldL9LC#24ei0!S##QgYvFv_JRu!x zuD7%vkH{uLO3ZR1tDezJZYxA^EH93Rq}kj zn^WmxlFt5Df>le7Q7t*sZOKU05|e{A1@LdR2dWGl6~jKGM^m08B-fPK;r5X#Z6S|y z&#>tGs1!dk)(k*PF>oH@Yi$UmS4*XJ*8DU;i9m(X0|J;>~(_*Hsr?DhQq%v zrXyLCz7tMysGA*G^@q_>Y*#w-(~Im*%LiF`YpWvC#kSK4olZX49c&3(=W=)rw29T` z_)?GGOQFvBBu~J|`6QNDrJLQ-) zWNlWwXvTNpe-M9!i#y|6w}#T@R@Urh>$@24wOJp;Uqd0kYq}Aqxjt@|yMUxvZPALM z3dmauTfsH1a-NfGT-n->Mvp4g3QgIuVVT#->g-<_9GsLe5*r9I(-YXnilGrJcHPJN z`pW3B9{uF&|5%iRJ*|&^5Tfi&A8r5SQ}HWqGZ;BPYhy!temeR%b4GW+r>YBGy>^=mTw@#^1X_UARA$z*xPnIVpUhz4%8qARX5 z=v*8q3pCZ2m$8|HZPu3$6RQ(fDUE8fg~3uT{p_E(X7aobVHYaK-c>!&*MBr=ymd+U4(TK z_OIx64&&X%azkshsOlMe9;dsDA2D5)A`=t_rx+f#v;{kmK;OVH6uU}=4Yd+$AB|ueGkhlq zEsz@9eL42a(sno}sPzS~+|+Dg7eN5GC^+*&C@cH>VDlgS^jN-#iOqyI-e-=!ty1@r zBWG$>K4t{<{uFr}_B$KoJVJUr^)c6=0!zq&EiS?pty0-C4nlFFl>2H|7Rwp?V}zw` zc-KA(K8n$&6CBNiFzg9cf5hqDh;i{p%tve!mqz7Sev}i^6HDzQ!qsoixiS-ienaVr z{$>8K6#-?z>Ix>a{Ur(vxl zB$SH5sqJv}xklm&86ZrDEGTvef1_{YEFMCF*8i*g;N@ z189U9ydrj7ZhVVje;OG}>T*OrhedaosbRX9*h6w$e#3iCLD2`psTm_8)o|a}LdL}} zz@Lo78imLOoq~m1rH|}+bYx4odTT)&?yP|zMTdZ-i}MK)>*L@ zktCB7Xgf1{s^Czu-(K*CjZ^jE@Xs+*JB-8+C;+94P*?wO>b4PLSt!U1RU-uYz`3-rO%dzW zq(UMMZZngL7`eIg{$|?eN9j~R2s^4*oCr0S}ap=rXRiK&8Nfpioldd*hkW3 zp1dBO658-?sQPIb0R6Cq_K3tidJO4LjihcWue8ha({liS&X4S`d-xD5aE9+=ArUPw zdf#;q)j+(QL)pzd*I_h?#>yU|^dtBwgBat^iE0?IE`Hw4B&mra?|}J-*_C3SRQ>ea z5ur54@x^jq#4NOa}R-QsTRfVi0PADn2XT$&MfQH;3adyJ$#^ueBk-K{hZqGW6D`P??_lg zx}-_y++Bm1?JSe=3%FC)<`&{++H}{ird4c5axsO=Z~MGlOoJF%+o!bk^@*-t+ouV?i#n=LEnFe=hr-Id7kBwF!$MlJ0CwXUR8f{zAXMuZP03m&N;szdbxh8 zA#hJQVV3$w~ z$DQYOS+39PPmjL&euP{R9J&BnjKS(GT$?f@=fFgWSd**jc)8#pT`&?Uws4{JLaprNKK#mfw_zk= zgi@s3-5^C)B$wmjB%hpy6BJ`BFguc3IG^RRk*Jq#S^5Dv?8n)DNok*)<6p)ac!_gw zeU_~e8IB?Y%k=oJ;qzW?OUfZYw(RP#pp?C4AV0z((?geSlik0AQE&ZbKS)F5xSnaP z5IiWP$Rgk#!Gy{6N2;y&OOk@#Uae9esKa|f&d;Q8_CrpJ&_hH{^x7VX8M0(Qd_>1O zxOn4Jaq;8Vdd0=V+!S*I1Tme)28_~iQ|PRTxZ9HV@q1W%@`t=`z4oS9LwoXmoHGSM zH{dYSX-UDElvM_3Q%G)0HW4J9u|(b)o9Yl}`d%rNJd!n>R_WHv%;i(kQKd9aK1A=j zqeob&a||@SdJ|byH9#PRx^AgcxjBx2(;rT0!b>h(vQRS*% zyh3UZCc2`fZR(P%fr!n^h_;6Y8f(f2#wyzMZH)w15^T2D6-(QM#+((sx9{=3s*nyg zGNhN9n4VuD>_M}I5vD$kAt8>!S)arx2vE}>DdeJrNRiPT*_N0k)3(?d>x$X22kc>V|=y~6WzA~L_0*mTL+Qk^48xb7)hmL7Er zFV!;DROQNv<=D4`odfZ4Ib%_lQk>eVWBYX*CSK~}L~cj8fUEJ|my>+krBX}2a-xkv z^hZ0~VP-e{->FB=Rkg#aJAlTW_41jI2zFT)Rb(9y$2tsvE8}P85^2vd!d-< z`U3F&(i?bx&aBtq<=Px=ux}E4rQCTmrq@hm-ntc@cd?p{N7xsr_G{cF)`3g8i~x){ zAr8rUOgvXh455?*c^>z4!=!#a!51_#zv!L&RVJb*D#%sVO9}2$Zpp{UvaUg1738_S z#}mcx>@Tf7U3WKuAvGC2d><|a5Hf|?G8dp~yluV{Qin;fq(li&ag6&uOc}vMM`)F0C6Oz+i4PVT4_Rm+LWF zusumns5G-37#_uM80*MK?(3tTa{ zwfP7ESZ_{K6NY443e{Sq{H_mEpW(nkL+%?lkjDwEtuemWbvDlTK`zEo2d_{FD zIamRc<0d09L~>NRF*S2yj1!%T+#XuUL6dbIuL-Y8_uIl&Hggs3X4wrnEp9$M=T=p5 z09zxHaV<6GZiFOGs;BkQA~!7giT#ew2?TR*hnf?iz%teXAtL}6lgkHPJvso+RX1r zDBL9vUL=s{7o9K4MU*eh1_%(`uT*j}k!dH$xyxW}$eL;* z00yDgQM=r!{gx_@uP+XXx9sGqig{mRcM&)Jo3dNQNVeyFL{Ilo=~vNvSr-+_kD)0> zbiR22o6t^`@;c(C@N6f8JmPoV|L9xF%Aa3^e$*VMYL0iG5girpKG#V8RQhdAUz1Mp z=*MMf*%l;6bKegbzi69lFZZjPPs8cCBbcl!?ZLV9lCIC3Yu#)V9(yO}IXAj4e@epY zn`tO^c!K(k$cI(*z3zzyPhHR^Rhy%ql zO2KeBM0a&LREM#$yO{~FZyj=qk^BaeYKVKw)F_wp@S^&(&vQo-)dskxcSwBCVMgN5 z%#P`}TptndZZYnR;WgHL=*sAX1)z)&9&jYOJ-mzX1{!ZKhYN5&FiLP=Fh#B0a+8f+ zlev}b1>-YBWR4+VPNEqCh83fOT-vMiou0Xne3~Z&tail|e!xuar7#jFl0fhYUvRKE zG!KiJdqJF%r)qvs5vh3B6(!!K9#_M z(zVi4H~{JZdW2im=GU6m6uKnuR{b2J`!ijq>-=LmQ-+H4<`&~_nZVhK`vK4qJ#fzO z-&!~rv9-4@xRtMd?P)FSg0Jf?2&5*J4RR&0`<4_EKvgABV4FcWZau3L=IP=LXG zpH*zG9zC)3m^!wASz2Awq*1=h(&gubvh*`5Fbu%*3E+m&5CJ1nh`?l0kq)LmYJu5E ze20CaOH-LU@f>2O7>P8C&BBg(x5MdSxho+f_$feG-#mn^b&@82MqmNL=9cEMg3OPg z6+LXKBNhAHVN*>XhPm$bkcW+)M)yNr*l+hhUY^N-9z7oN^yraK=e7t_%WelURvGoM zs%}`-2WW89O^Q|R670Uls@S-5EuqGm9s6;t-iFK2JY>qsC6Y;!yO6Yx>q(}Pusm}$ z2@6m?lM6o-Z7QN1OY~>P@pE*{KM9WA>EIq(QAS@1D}(j>Z&aNbZ+LGR7j7m z*~+}6sK6~iQG+G|8%fi9YyN(K6w?W(wl$AY+peufJS`mY2dEGw(~bjV651k@r80HS z9hGTtGJJG^46}8HDJsJb4cfPfWLlJv?sEA` z0$ir}$~ukd#A*URGyP4Lp84k*<44er{4u_7t&H(k*h1%_)mxPu+8F;CxeEw4dVn!L zpM(XdK81kX7{3bNXU6gSH0YlT$I0g1kktcBEq}T?Q`(iy{;4=KP+o&FedKjmX3xjG zN-`hGYhdQ@yj((Na2$;UPOZ=`p#*E~X>y19Sl=c(DETwSST5zLQ&h^Ujbs;ybHn4^ zF(dg#K>&05J{X17ddI6$7}NJ1yL_x*jO1Gcw{APkzxIx`zVfAetxc`lj~uikj}jzg zQ29lJ8heEG?-ACx?V`pf8Z)QRl(DMl#J>W<9bEP^81^Ra_?|_^U44kZV^0=dK5w8D z-G5Mv{SW~toaWuB>Ke4w{+<$W_P9{i*}w%Jfgxmb>(-=6iJ9p%<5My@yFR_lDQVRs zI(h6)a=r;h4=JZ&x3>wK{?nmmp)Z%VIF8k!zX) za1GsS4-IAO%MmivmyZBcYz4+X`49t(-M|g5G%$b5yI*P>!KK|<7;MXW;K~(5Jc#4I zl{o$j$0l(+fMXb+KC^#}V~RNbUDAkSv7`~l9g+re&BQcApDb>X!w~*maZlCmXT^QF zcFzEgOi;V0(1J|0c7IRYXKVNK;+Fd}q>ggrNDo)Wjn%Wxlt zyfz~;Jlx~O{i1d!#Ql_Zw~D(}yZ4EEg?5i&l2xic^3E5xDEo1*5cj`n_xs{bYWF#8 z?lRxh?iHph$M705lj4dF5$U?=W3prJh$-7<7wpiHjn7Ie#s+BqrdQo9`9M6tvv7Wbn_H} zQ?ctffoBBINFFt-^Pa*Z-#wN|`*xltp6~H2<@qhox8K)KbDrA``+xEM3WNTisa?{q z|Nq1GkdLbVZ#+k_+?+z)pXC{qm*-z`|DBbx`}_$1pIM(*u-^DA&q&JnEb0Fl(%#Ql z>J5%x_6Yw?4}Z@*f9w(ekmGOR-Ol6bYvq0{IS&y|U!N0B7L_xX8OYy7Hi?bw6q#Uq z6HTJx4X5TIw3t_0zj)CQawy5rzz8$>Yc6Zw$|6`tH z64@#O#|gDz>&8N{WU6jRd+=GdJifH~*Z3|DWN$IzqgXwvMVpqChtlIjTG@iMayeI9 zG`sR=S?Z5d^2eVq)AGl0h#wasePl1s)e^zfEyxf*$;K|rY@x&@>R^Vef4~gX6E}_s zT29K-GJhteUgrm_$JAQ(4S;hK7>Vx@k3C~8CRm`QeeQ9=rgP;Macg01Mugsl`iB-J zb>haOeF$}prkj}&J*m_CNS)q4u+(XXh;K_=@vSRwjQHOi-*i^ZW$CkO)b}35E)6Sd zHE$v@;Z(+SdhP}gJ=+vpQxP}KTrL+*XmN2MHEu}S?2PX^Y;Ij1iZjAn)kzivvLOVb zHTqi!?$UKN(;iD#jU^)~-}ucerr+b;^^4{z0gRlNh*L*L8_8{S6os!jn{b657YI#gbI%r3P-cJ0e2-XSWyi7d95({LPpOm83mnBF zF*Bc%DA!2djU%x5Qa6{f&(tL9mMs`a>;pUT?qIYZZHQej)#PE?O{v>y#N|uPy&?i! zIW3m!1j^9c9w-_3pR-LU-XF?dS_WZi{d_2WDf)T5T0f81(a#6s3sKN>E@ND6sCpa< zdbwK@wFsv0wR{zzLlB@a)-Em|SHi@*`$vz7clR@r>j(&R6_sH>fnjLG{D|szU6WAVQ&lGh?GZrQeJ@ zeGm(Tb_6S6xnkm)+08b*RD?v*l)4e zZc!obV%mN0ci$ZI1^VCYhsLb&uvABQVk{b8*0^XGI7h{vrdhpqu2J7~9$MCrHLX@#grygu1U<&A*vMTiXs3)Oxh#~kVO(#7et8Hg*!8Gj z*L!miD%j4D;xsUuMPcLOjHpX4^yU*(E>M9StkybYBk^tNr5qoxuVMY-%kZAvN*1IXX1zs%|Y`Vo!l%e)P5TMfi;pMmuV@P?8jB_<<7fc zne^B%9m4nK`$<>C7Y#vlvKNR#)?Sq*kP4R%sZW2Slg>J9PI)@;2;+BNzj*88_K@`D zKUL7gclR^yR*bv#*O+&?tk}u=O|oX)to`Tqk~L0!amo7Ef~@JQI#D0a8LsMdGM47m zIqy<3Sx*$^2{1E!TAt%1Pe-8j%|U_Iw~B-Qot*Bk_wVtqwKjQXTdLuVg?DrK%IRzG zcxRJB4_%H4o3IK7IONC;h8UqWU<@yNLyU;acu8zn=r^rQ_e{PYD1C#zFMak@yVnNtiYsOz~5km-LJmy+Y zV?QZSE3`V5WWGRvqYv)|#Mi)U0f>hi30XhIyNirug@S*lnOY&pRHaI@{;Ox6K}PcX zBt1~GVwZA6UNx!eb7>N1MECC|aL@3|nj70xN1Z$po}obo^Io6b6(&*U-&Kd#(r|5K zE{%GT&ZI+BzsUK$EyDV+M@XeL9neSge`?SM)A&W}+|%+3hZbV7Jb&irtW6X>{_2p}d9KB{IUqq;v5xC5hHqx|$%LK%9Y?*VfRpxn6$W1KDc(cJ6(a~T`DtYb4 ztPhQIO8$kFosl@Z*yrPVmi==6n4G!xy5-$PD65!dY6urrbt6%2K{-oX0Kp_3tZphkPRyPwHB?;|@3N!UR`mLP^4fZEy?T+YT#w=D1I)9?PP*W*5aIV4CXLzf;T zrxn^y^#af7BtIBDCmsMEOmJ?19g4(_i+AMoQ6xnzq_0{>En258P5uz8;4P z#!6Xo%|F+5a5~*Pxe#MN<$hh6aY23Vu?4x>CzEdBsg&ttbn20g^+$h3Y4g26`K-{r$m3HprT}9j76BT% zUa1EQ?ZB^v3|31~I$?UXfS)6qRdBHX1{%|o8_je?xRrbLL*`_-+abgC=Vb?j3$vxq z2QEwa&Y|LK(|;TcE^q7hnaHjee7z61Sal~qnNh-K4i&<44+SIIJ7iq12?_$4w$B%!WXh2Og~kkcNqK`&^}FC~Ca zC;wQ#9l9|RKf#~rbOIF(32rl|Ge$D?^3zwm>V7)8qESseM&bqu{Ez%xqK?n(ke?$Y z*HetcOu3W5%_XN!GRnM3E{PO+JwrlP$AMWK1JPJ2*O42T}Z*&f=iAzn`d7;XRchlOl$wGJ$T=o zIdbvxk7dCqmI3TTm$(-%!`3B!bC`OcogNH#(tUF^a2 zaYW~aW<&9XuB7w{F+Wjhmf-qNe0|Cra%chfK^9ui!ny*x`d@p5FjTb z62y0Gxf9MMdbW=ttEfE4!4K}ecB#5YtQ_7bQ=iF{Etfviqdx;KH10_|VPEcWl*C5j zS{VUk$f$eNWa^P__Q$^bDc$j1g<$E9--%0K{cR*Wl*j3gZ7Pj)M;ETlZhmP0ejV_0 z=lWxzL;q*#4t2?(OCSmPD#!jEq&TtW*wSBDXl(cBuS*DZ3Y#r0Hxi?Dx*k1vZZ4hE zrzfg(g?$?1&TlnEEYbH->#lVbsrl!lmA+kn58B$OZY27|?NZHW+XftGHqZU$EzxV| zm(4V-@qV)zhcKfueEr+TAHh`<+^Z*73vuZ_=a>d(lx}0gc05L+QBa;9H4t%_$)4D| zA~Zd!pA)3W&bgU;xgMNL3kN3*YN^YhmcyWyxeV%Ou7X8f*Cr&l+#%vd-Eh6>r~dyy zEaxUhQeDn9l-)v{&;t(cXfJrM)@5f|C9EBaQd{2s@j=+RM|^%WgBtPEUA*^bIUP4 zw@jIG4MRpQHRVf%a!c2KU%p6AkzQ9HzqsGT8Mc(GE*>sVjf@tgsnW3PO!E4t3ep<=lpJd%3<2=^_CxecC(hcaa3PfDlPCtQ6e2dJ&Q2{=-_+AA>DlI@D50m9s<_Un&J#rxA1efGKNxh&crFu_c zhC_}8m>K$gwOwD(Sg?_be2zrO=?=h!E;S)0xvC{YKxP6f^s1Js$E%*PHg?+3Hgn&# zw9Z($(KLeZ^Ppx_*XnR;M6(KKge=h`q_J>>(937Abe9pPx>z^*a~M=cvWlM83*ZaH zrRV~FTBkgfz>G&^5ze=qjpSGH(9p#7yt7Zl_ZahzGH1v=uQc2jo-vYv@w5z#QJp^& z0(YoH4UB8Z;taaE@(uEf)Hldy%AnBSAn#=~aPe|shcmMv`poO<8t^jo!TU6N{>QpH z`Yo@U?O8Z;oXALsLdJ`AQJ7e*LUSuDXT@P8{-7gjL9S+J`ZL)^;sG5YgI`4mJ^fIH z6)a4L$`@(&`)Iiy`!0oWWnmsm;M)Lhgt{R@_-Tw!Wh2lW=fazOk^XaGOunH!!c*w~ zzvIcsp0J?Z(Z`&xRKSc^^=y80h0<}eA#lo%{?fjU4NH{@amtk~m#|MCdzfLut0huy z=Hwbm_oGIfnRUXcX0B9Y-=MZV{cWgAMcG&9sxcB`&n)+}xD^`-Q4BI~3zu>5t?4>( zypHJE5$b9#uM@;}smtf*f;}93Q>j#y;S#pqf5>`Yoi%nRS0#)`Z`rO>Gd1f=4um^k zUnJ?h?*sDHw8x>~5e$ypjS=d8bCXf^g9P$6b?^BjWX*jw&6aR=CDX6G@L{C?iG-_r z&%fh_M{i$jG!1BC2Io57)TLNlUB)x6xbOpN9g^HV%%s1Sb`j+r?foz^PdX*0UlW*%hLDm9#13wTz}os4&%^}nCZIdX6oTa!2>s@T_h?5 z@5VHJ?}@8X;I^AQ{laami})4*x8*RC%e^rYS4?2`X0b2z=+pK!d?vn)UkynjLx1W z3RzfaAvhQS6akJh00;ssCR3%{>fFs3XP78mDfe%pjv5LQpjk97T&Smr7G)b}r^nId zuPDE6-=IUa4*1glP3wSs7<2u1S1m&)BPOFlkD>UuQrhil#}gUprvn-Vc$dNGc9$5* z-w1~Ckde6?Wqj_wg#0M6C{g?9!a%G9&Otf(d33@rM9G;C%x-l31?T&fJwY6b=-Ke( zqhc1&2Wn781bu}pdf+DcQ%Q0>b$q~Gm3KGOa@RPZ-vVtM5aewn&MPi74p5Ym`963L zrS4v)5at;U=(ukYC#0*1Plq)S=Bm~u4l@895g`JT0a;?@0!QmW*N#A^Je5GIT;5xi z1Bk;uK%1oYZXXayUC+*79`*qr>Gdu<0!GEuLi+$0;aDT8gd!nUmX%^4@JcTR0`D=f zzKsaj*%^@E+ZjB3AOisb1;f7iq3W0Qo$LY%+p0!&eRPiA^7bddqf*OfTn-A)-n0h~ zXwAWcA)#v^K%bBQtQG=D;{Fi}ff4@3`4te9*kAaR;;x5F|3g z>Xpd>6?MJYmGq+RKE1D;3^-K4?rl04V4s&lHX}Dh96Dgl-#QpzpPPNaM{o;mA842KoTTNIgvie(+gL1pc+aMBr+Cd@`zlgE&0GWhl&={gPf^7Kl3zro4HJ zT^6NHWbv$+69KVA%!kk~G3W8)LAXl_k4vz$1`~mn9$B821X}g!G^$NP zCQ6oDBuiC>)mA|*2(mTQUM>GFAty?fG5iqR%W}Xz-yWZXHF{Mh4_bF5F1L^JQ?&xxQH`<$>0CwVT???By6S%^@T;c`%@7t%k z&XhgObvEW%2z*1f!ma?C`b)(xU+)%a`T;EjCb&?#kT)!O99w`t^ZbbCZk{bXH}ZUu zXY7t__DP;^V-t}7_?3--BhL`~09I~`Dt!NlaX=&JER>IMYUN2e8DVi}?!2;adeL+x z93Nk73?4s>X9N!)fg5jPp1^q1U)U&-D}awuGMG}k50~dzaVgp6RG*gc=qrHXS6l&H z-}DPHYG_l}_;Oo&d?`NpGgA{rsB2`slMCpS(!aS+qLiio{2R?x?4ab2GeR5Y4edoL zVISrlrCcPNHS1}I`%<EUGukMysBLJP@Y`;*&f`al2}u>%7IY6^3@)c#RftH5o)ei2N%*s zo$*&MBC>@q7BOj~Xo)R1)00~qm@m|4smRWEzDk3e*y3DT%tg=RAg2g7YkFqG@pZMz zz{SNngO736nU}&D^p3t&&Ogm^AkMe{P&l}(IGp-YY8=0P>iNP_m=8)-pu<>iRy-O` zmwymSpTKt(rXfdsoO`R&m!q7Yn>DMR=evLx&Fg2TF0xPN$Bgf(odcs7(WgfgoBYM#84-;i~Y>6c?6eeZa!8$u8HU*H2lSP9gZUqty~Yny49 zoA`PWpQ-I$G>5MO4*44uA(=p$;TWm2se%YX73;{bZ~}L)yb?+c*M&D$fczxBrNo;#rvW5 zb{XEGjqmYIyN&M!RGQGnx5B5638p3%2l<+M#m0K;#hovT!g8Y>vG(E%ZG1gY{Y=;x zw=Gz)AyUl=HbMCF0m1lMDX-pooW%9k27b+r+svICLtI94>aigm9Ui#Nw2lp?2OSym zKNAA=0T=h{BUWjE9u8V2bo3#I7#E&mz1T&Kc4+6u$f?Kmy|P$A8X3sx?h69el;VK( zVx;0@!2sV`Gp&>Cl3>a#R@Q^!Xs)H{PBQ_Ew$)d31g)n7d|)yDNv#?w-+qfUG%d9A zS?E2SIx3VJW~Ro3PevK{Og%T8(t!han--lvp*Um}%lFayqP-B+R*i)96{UoZn*j-&RM=xU$Mz*1tKsX+WA5#TvSs-HWA9A>s;c(B z|FsVwM>ud$)GSd?rHLhmW#ya`3OUhLZ&sF~qEZMXhtwu1F-1hFtSqf)o=m-IrIm?g zYBQFVHpxv*jRvwb(~9@|UF)|Ghr`%??(@FS|M}lt#}8|*-}9 zC7|a!c#p#&G+gu$MPAH}#+D}GYpV+`g!fAd`|w7kM2TOs8e7UYVIITFknzE|gwkR8 zE&jyoQ2)f^G-x^afb@)oexH)#D{t|wUYvX~BLrR&%Ww)14&HTOhF2btz&CpTtn?zs zh92j;eA_3wUsIetq{ z9Ny-+C#;;)@B#}2iqC3{D8V;ueTE(7PRwme=@<8(Do|CI8}G$@uZTWoH4Fh@ue%s~ z-5YT5b$R*u)$V5`&P&*VWHPC^e`Wk*PLqHkSQLaY!p_{^9Ny^M->jT=`tzmyUT}Uw zF%}m5m??jFny@?!-}~H-W{&8vmB{f}JUTjmy|L1@A-6|U?{)f?IFEt73ztQzkHekE z^++Epr!AaH5-~m^Pw_@|408p|@n_D_^7Ao%BvvMr9_A-C^bwYx7Qcm85>?foCKf~` z77j#eEsv`bQxNMQlQN_KvPPuDT7* z_G^QftM%7S?SfCeEbWM|fS0dCBDB0Tl5&?em7BZ1czS!IHrp>M@Oz(%uRf3AoHw5R zI*<9{$c#W2G zMB&sZtd6nkRfz%R>I$sBOTAIUExc=74*TYRRgN#^ZpXKvZ*l4&#^YOv`u9B;IQD6? zZ{X19zpy`2*Yh+Uq+k2c-PCs9)_=9{(Ajz5f1Ze=&+J63NI3xEbijtzi5oI=yc05~ zPT+GU8@DHHNy(U&x-H>NR6~6r4sCsd{hZ0v?FkE6KXdZMvDz~lb)K7zmb2TVF@?A? z3VS!$uHo|~SgconG^5PSW6iTYzQ;R`@hl>qu3Tv4;EQls$Zjj={9_3lteif_5=t#^ z0-miXD<6dErRlsW>HP#o`++>|#rqy?a&@NBuNV7cGAd9>&MQb2rXaYxiv(h-k(3{b z*V$l2I@fGnRd>?i^0;}KRybULMi9Na1aygVMzXsMiC8y|=;NdcplI}Vs ziRGgpWBNqHAGRY~Dtf2|y;Vw}uaXP5rJe*RE@9|iR#5ls^_Urge9 zW9B=6pUFO{kN%88yRG&z5cj+_$UgUrO%^7UVzJ}Y$Kh|~blG=oP`2o}fat5|qcV@r zPk47*!a?k0nax+u;$!uso2%Y;(Z~;SLq|7scOEm{%*_Wmy-8@8TxhxTcEVauVRI(> z+Gy`vqTKU_a6VL+Q)(9rUzfl(dAKJW&=qw1{4h^2WA2P&D-^RkkKXoNqspqy;nonv z6xltWcS;bA{yOj;H1I&wFwAL3NASRuo}=_%Flx3UB>c0jfkccPl31*FcWZoZJg6(OsTcCJ%Ph| zVj)hOZAJWlz|V~ygzq1wo&DnpU@Vw?-}~WweY4ZfjKl)7WS_SMs|R#q7r+4}Z)T2PXl#R&VzS@IygDw) z-Ui_-F{2VYVE0l_GzW=559J_eKSz?LHmOIfwAcD{Q`Bg*+R9trol?6DQM?=Dit(FRdo(?aA4A z8`WSm3FvBO6!0q~I$Gu5@->pJ(DZa>`EGL@*16Afv_7jhv1qACHaVp69vem!W^+-Ix6K zx(C4SwZ{?p zf0%dNU^m%3jf)*O`{gEf6-CAJB=!6<=R-a-L+v99Q=?4#!x!1Te-Egj<=^6!ne5E* z{?Y+(AE!Hy4;l6ea?dxRO8)356t`5bd?N{q^r{ zLD-@}%VZzyyGC9H#QGvfJsv~``;@Gu{&MAK?EmAK%k$wb5& zplZA1@Q08I40TK$p}yCsP;+Z&wC}KUYbSr3$%Vp}!6uY|4O86M!=uF57OM6fv1xuf z>EEtJK7X7T?EX7McVzxw=81M;SYRDbTM z+Wcqq@Pbx}`A0@zf3{5`ZcSsF>rJ%#GfZ)D(+f}g9vzNbrjW^rAF$R+==P!Bk}a_C zK2)9-;D?soc|38%r-KJCx}b;P3_aakVEe-mQ75E$Ho! zr;*UXU4k*<>Zop?C-pqveK)p4TkJ_Jh)m26OU%C%-gs;O5)L=sU|K91*?J*^`8Cl! z_(Ve9TV6Ns$cH817688QIk2^LArtd;6cBUn@*~!|sFR}@bBBq!3o%EA<@2o$ zuj^B3jC2!5+S|8E7e451GO!_Cm}F~JoHA`eSwt-w*LvaQt#y8)+OT9;x_>2NOlR%7 zIEVaeF@vt^>l6KcSiOISW`qM9M>uaQ%-L-kHtxRTBe20(Y)!!OU~?k!S6V!79e3}L zSUB6G&D#d`z)s7c{%}W~O4zN3MC8CAC~ePEG`g94F;i=jRB#dV<}1F8Ui-ys$D^J{ zw(Z6QBg(h6rT3)FaW{Jm)B9Pq^hfAbID5fzJaOJOGne+;Xi3Zu(ldXw*GBYzlDcZo zQC92EYVK#ef_|y~{fv#sm2J55hUw96`*;!F_}PT-^epk+uPF_MT|x;hcQQv%!rRvvu$${=$w!arLEptvee_AgXsZ zo}*fOXJa)Db?jq*-9ZaBMGZM)^aw4YFnwO!SILMctMpD+%8 zV`_Repeu>qPZ(q@lQbeW0=4WX*mJJh_Z9rsC-!{Ie7&N-Z^vx2sbRR;SJ#f&^T@Wq z8-eZ@+xhC&4s=^rm9kdpTWbC{{pQ&1`mQuBRJMKvZeL4hgW+fHGbkN_j)s>5< z&KMQ5Z$=aHhIb|dH_muB4?AZ``1~)o&R8iC8Y`GzXmG0;-1rX3<*}xUp{Mf~$E{Pn zUsz+$%Iuo@_N=OojOi+)cdZU#VbkmH{5@P1n2+8{BjKf6+5F zX3zEC(K9t_&-K5fXKFIWzs_7plhm2lM(aAW6{xB+PaDfM8WHU&UbD{B(IeHkAFbyH z|JD8oXY#80qmcjfNB@KRqh~JluUntdBz0>N{>G>`9jK~XBaG!}jfgjZTI$wc=#K)& zJ3b(S8C5;w9XFMd@_!8+@~Y}rEoWcMj^F>)dY4piwKJ*r)wp?NkArr9j9o-bjjwhd zu09UpBnqckJ8UtIgZ55#mEFH<9MtDts)dF+Su?o*zH#upQU3LA5=~O?z8$IST?J58 z?>;t`pKC-6qj=3et(Jv@ew897-)2a(mlJ;b*Z=*lL}@zA!+ux@k+i@`;~lUI7q!4cfj;JLw7=?NEZl|;f7EYl;Nmplj_R!jjJxl z@czl13y$F|X->am`mm*W*Us&H6hQ*+t zaDx@M+=_Wl9^a4Z`M!HWCuqSr`J)KWG%IW#VOvO_ldl|B=)%)!BXCYW_(y!k??>El z!=0;29D#odYp|;CQ6Ziq^3$uGlRq{b<>iI6Ia-l45APX{tvcyh&k_0G8aN`)LzxTh z`)4>R`nN<~p%*r${!0XKL|)(ZT8rrUACa%~&Z{mj{g19JsJ=KDkMl`57++cI!FU|w z;lX%wjEBcy?St`f;K6v~Q0vXwYU@9JJ^=S?alTaQk3Nj~pZZhxBNl(P{*({>-&%j_ zc>dN?)zoo6puxk0xe)g~f6Ma|v3iK){rjO#Zzt}qnEj;j<~>>1-|amV^XP}|VDt<9 z^dYewzC&W)vGejfBqq-~^u~VAj==4m#DbvmEWML-1AO7bL>_cw?z}lLXsy_dmZN7g z1GJVg>UcT==L~$0E!f*z*zWX{pK98){hWmT(8IhE-a^MW4E4E=s?$~YexFkhYkV*Q z|KphjzPPYTp!%4n1$dLDO29sTReG4GlDJuOxCsSf?aVS7{LW#O>Tjo4X{Zs0vcsoU z3!+9G$`13bcvTwgIFudcTl2Ohl;KkV6sS86WrtsafX*v?8J)iDzxlPmd-3D<$miqt z1b(mKM?3q+rzP9M%x|54i66f?+Dhzb&tH3(1J7gW{rhA+^O@juzj$H)h3E5;W4izs z1^v0BPw1?_yI(B9KHa^@z^V#0??$J}=>zL)&c}?9FH0;Rku>jOl@klQ*J;NWC6@Qp zb}e8xhjx5PVtGf};X!d(_30ZDrXE1-HHyi53y+@1e&d2lK<5UZD7YGx!W>7kiL+8O zk+v21Ex_-EfZrOJYn%r|8|#779>WW!Iq`gK(w5(YlM07-z{t-BnsFvn3ZKp>2m)Ddda+-&O|YdMZUh#O^WI8&j^n5kHmTS zRBA6cwLt!w*IMrOcWMu(t@NeeY`MwL$=tY2Donsl-w|?kou&d|6!rv__X}JS6IEK74f^s`|*1V zzX;ST|6e8SYHeTa&-Gg-r9Z#I*Pojg-SZwn)!xYGNIH%fC88PHCywm9V`cV^PLRGi zR)(8nI7Vmho$%%O+Y(B+^4Nh|wS#$B!)HQ?&uap15L}GG0C$zmgHXPSWI<@T7lT30 z4N3FndX)F3y6)Eb;*((R)-gf}yK%nC1GS|!)eiNP$5aJ^+|Vz6l&9dT4+uK@s~z;S zTYDgV^`+W+AQ|U9hvVb0Nu58yF-|n@%h0yvyyqackPRq3UOW|wR*nxv;DKhgax<&< zJMYP-U-j3w&(!Ui5A~rvW2F($q}iN9V9l0%FnHj$;NA+&xi=^Dmuw&0+v#5($ebUg zFq14in5$d*fNi0=a7yuxLp(;vqi!Se4~!`2(7_xH-RH$22p$bJ?SoH2nD*ss8oGUr zC`iSlkL-*BsKGfH?{0@WKZOhN9mh+)@(Nvw!t-7D?@oxdc zd@TTTCs$SZJ1HGd<^6B;mGDMiebszAt9h2G=J*mw z^_$ZEno6nZzgD#a9#lc){?@ML|Fm;1khS$E_Id?pZ0oGzd;vZVCHvQMJUGz#eY1A0 zt(IeO)3scWT&L-p&V!}_bsTSXsi$@)xL@pm8+tF&d@D@1dp`cc zL#5>@{x=W#E{9q=N>0W{uwq_{v!@=Ow7QftNc8EtzQ9XaVBgyCOxtXo*%i)w4FFZ} zKrQEAWIv_#@PdnYWF8wMBRU_&-Uxcp1oWa?us4Dk(jTZDzP%AQrzD&&4eyL2GoPB1 z^V>0BI-a

g4?EsAIn+_58rSfCnhpOWG67q%8+{Kt49f+K!GhR-wa;)ftB)^07Q3 z&%^8&p{DGpif>)#<2k7qUJ#pDfX65B$@cP4BtY90W<~j(kuTyGi{yMfc3@;~f%Ea- zb8hh?<`#aH!|wn5tZJz*HJ?|gqyM|4s?OY8z5nA4kbwSgctKV77t&z&=YL&evgZZ~8>;ERriX3Q`g4X2Eq|xgw){=C zm%n(8dnumR;1akE%D(zUBB9uC!?s`?%Pn-Z)(;JBAKY43 z8$S7x|3O`qhsD89gXtU_p5HsEa0FHw30QL?#pAG4J!u}Xs&##OlIv5StbW7_d}?q=R5|8)gIeRS*6w8`X6|M-mOb#O8yHVQ6kf1H?*P^Mc;GHuvd-tS zWoB8UXlsr81_Xw@|G^F>Iz-PWr z>k23P7INZWeBkjg&okntGIP&7ec4WD7Ltf}CBfS7Sxxl8csa~pc@}eS+o*E@)7Gu907Be2tUk@pz+g`FX9)tBD;jeJFn zPVYF%mj&0O{~9A-V&r2fUs0d@_ge6RA|rnQs6YR|@1)Z^(a6*E@?-Vo&rgT}>eCdB zh#wdqzP#@c{HWUUbBmGhZsdDWo+sGrl%J$4>ILhJ{L7T*d;02>f8uN%pItheBCe+V zvHIk%H}a1e`DcKaf2~hGLknKuHS#x5zH_bZN9xayM*e3b&)W1dUn6~}uKeLWG34hP zM*b_x52#Omsgb|S$bUomq4mkHHs!lsBjRP2Z@uxq#mMIw`9%%Nk2LaQjQkZ1%C|G} z9gO_h4a)y;md>AFG$Kv_^~e7;Bfr(izulnx5+lFN$gie+Tz&a@wUM7<Q& zSNV1|^4*R6NXpl%|Idy(y}?G_OZj^Bzi;GsX+-=0)UW?RBmbC@Z_%Ls3?uI~@=JjF z_4hOKgN^)p%GVqJNF(3E$akfDz4`N12c19rH6q3|sDHJQUvK2!2kO^SW^1o2N z-uRC+@?(sA2IcFGe>)@J!N@P8e7*XIn)dRjk$;BrAJ$jjt~B!5M*arMyX%ub$H)&d z@>f&7WqtA|b;Z0O+Q?6(JlD6n{wthRyFz`3?(sWE^EKh>PlrdT2ZKWJ=c7TZAoW3T z$g|;U7oVWt5aN6;T$P0It0(J2!=4UTC!J{!+~0JFQqP2W?g>|Khq;y76XsbKu6_%{ zF<*T9v(mcXQv9UB(^mK)x5{<6A9t(uj#D0Wt7n7U54+X&AlE}~RS+Du#I05ayB53E zXH8n~i&RgAw*F_N`YANx{YZ6>v-J~^YEjd5)@HZb6!sj{eH-ptqJ*B~q<+b$lvP?RL42MXLR-9tR@T$_O~Fjd0x;sWwN%o`}F_58TjlJYoS-ttwYU zSizajIs9}1FT^)8G5lRigK6p7d6RsheK_(n*L#__bj{uvU0@*R-ED+T{l|c ze*{^dIie2+Ti-j*RH`V*wJTVy3~F8ytlkfbn;)!B26+{~aX|emT3X@PI`6TpTdn8^ zEjw7)msl1ue3(+h+>eB-doAbpVd|A2_wjJ`VNmpZmpTyS+!C(t4?gXWaJ4?z{dKr{ zCpi3AxLOkuxyTii>umpHqcfcG-y_tC2$blK z$dH4PA@4;dFfrE6%tCzy<6q=mtCaBXEw#*Y9O@JQUEPQp-rLj!B7`;tqE-kHJd`Ofy|T6cDFZGJDum_ z@4Tjaq%12fmpVnMQ^I?wGcb**T#;gpyQC?q<^5JTYV#V4e-}BNsMG6$oUgmB+z{6a zw<->8`T#1R(}{MzHq3RG+bVHIf9tlEL_~k>w!Vmn{>*JX6B+%X+d3K<{kGd$=)R^Z zZ&sXcwNg6}fgP6fcZcVNB!#@b@3p~ zQx0cYko8JXt3yH7&LGUtO#+$csIRVHtmx+**4>WiXB<^J2Ur)L=DOEmT^g0|uu@Jx zX<2Kn=J<1u74n;9eZ^v5o z(5Y$=K8Ee8wA85P<(9hDio;uGS6k?TOdW_hFM4l~8Wp)NNZo0 zMScwHAUyo{XmI#8r@Gx4{fE!Qme_ zS8oJ|A8f8}4QaEWnOYrk*6Jv=E96&X$~(?B=-7`t&q9^IH6r@nXlq%-6-xaO(P~MQ z%8UG)QlCV&`XN$%7r73-gq_Y6%`E4zkejXK3;gU*Z`*}*tg2%jtr+QJL*8~+-&oES z4t2t6kH7D8^sMf0a7c2MKh)Vm%lTtF>u&37Ec1L}o^G{XU^!R1tfkhPrb@jQ*7Px# zwLRyTrU)&6~t+Tw7%?LlUY#^1|=UB9(g?*}{acSZ0Ej(0t3XK3Wn_G*9V zd<%xPO~Y^Zs3T3oi#@6&Ec|49bz6A&9Uiqgy!FBMYG1ggqMe%OnxNFzu2#F+p>J)o zr@i_l!t+BrwZ-jvubtZGj^5l(9dox?-A+9aZPgRa+q}?Lz1Q4>h4%N&qgTT|+VwQ# zqoeO_t9C@Uxvj1GG1~J-j9S_v`gn|bwuS5G81-I@=zqqjvKDRLjZq6)dbY=?CtF6p z9;3FlJgwBD4z_e{ic$HkqMwaXD_ga>Cq})|%5z7I+Se+2ag6%o6xRZ{wss$Fqn5XB zS=L6CwvOK2M%{VpsjJ(lXHSh@*hVcp&9%d$?m5l%YkT#`Y3LIwPHXjHJ9T@TZ$s?* z9+e!v$x``NI98dnyY6+WCoR{JQ1yuw{dTBY>4>~DR2^`* zA84YshJ@got#5^_$BG|q|4u6-dT#{$M7C2=!=aRDOgi4UIbNQV%$t54hBp zrp^Nq>aC_2S$=HV{P_sAAe2AMOSkRq)oR=&#$UWl?Q*wo|V}c|K^TK97oish#>Y%JqCZb$_$y;&$q}W^D@Esa?%H zx3^QjG>gt_r;3`pD%+}c&7;3>tF|?7vzztH^HEz>7#+P6_R+3)+p15ZqhD^T4oA0n zysau~;VEvb*0zXV(N?|N!gUYoU5n_vw(7Q)ZGMbVPq*}Z8>8N88I7HeZ(5#q#Dn_f zDvMF8T1CGfqc*o{vk~^KJnLiB?WaVqiBZL^UC+R^wR?GtdZl&Cc`@qe*3l>1s25H> zb!Qv({;AQ=qOP6h`qra1p5}VMquyjKyQ@vB6YbQ~Z4R@RpS$=VvEHer$*r0x!K;qQloE^4g)FQM^E%XyE(I$-(r zafsXb(Pcp@ITBUn0x$*O1C`Ng})yQ#>3_(f}`>0 z(vbEqg{ZY5A^7`+5DXM{dh#Ki?+8bqy3BuE!(2|yLsaHjQ5azEv(A3g!Vt%481iAP zHS9Ml{A3d=&v84vFA9z-4pk2X$1MoOf}#DoQ0s@_=FFw2`Jw8rkhpoFsLhz6d=}#R ztqEpb%?~tD%bUb)M;iDyE{ zN=sdm%BUbN-K^NLp)Uoat6%Ea609BzVv>WR@#oUu_M3y%+TalU{X($E7m)UIY3Qb4 zYY7_U_F(m7(B+72a5VnBJGlLu!Rp1}5d8g$zn@C$jLfBuyMnPqLIAshqVeb9p!RnJ zBlRKpdnxYw+41@7y1S?}rP9Jb4pvVfO5X;n&5Y9W;As5$TyXnCSV;tj;O~!u&yh6$ z^)NgNbJWhwP$w^o!n|mq#fj0gR#V@^NZ0=_P@Z2nTu%k7LyqRlg0T!ddry#hFDL`y zvVGL&&i2v9`GTd2t>`V5wGLIt*FIKoEPopn>TRp(L&0iOQ24rF3wi!Zuyt2(yq_HA zq@zPWa9D*_=w64l&kFt2VSQ`e?2};nIdA16@Hs2&gu~kC2)`}J+UmfP0e0r9T+!BQ zIXrZg!@42#Rfo0J3SIB8-m&J`B1XrPkblw&`_^GS?Fc{Ou+|6Y;JoiQ$e^;n>_BDr zpZ7uku+V26)|}8+9M&6F=sJh>cA)+z;P;8T^;cRQN4L5sNTo$C2vW1q*wGIm+z$q+FCF2VgD_!%yb*)kza?JLYLZfu zqCT?J?6Z;4k6@0g%fExdAA_Ubai}ZKe%zt*xD?)NMLp_JN3F9TcBqFO7whQie=Kug z)%WkY0T)&x)h<*pec2jpaocPmk^cV;3Am;OTn`0Ydjqb`0oU<>Yp7gy__li6Y^%4; zWpdeOTfJ@mO)lGPZr4=(+dkm3U2J)eT({Us|T+={tfr=)m2Q`6E@JsFw!BQqysN-vKJQ<+(*8ER^_H^r;cGgGDv zN}D-3C(Wy7q@-nZot%}W(lXMr({4!hbo3CJQ)6?^Kd-Z=Z(mQm%AV9U+dH8y*Z4^) zexQoaRPm!!{A?9JP9}9U#Km^jmfks8sbMN% z=FH5Q9>yyzV;UkbEh8n}qk4HpA_=J(nK{#@d!RBWH9HKJV=^;6Gg30<_^gcY>{PF} z$~VH9HA&6#W@M|e*(uXfVfOUVG3a_tc4kIDPanMO9r5W(k$z!{A*H0Jn@DDRrl(w= z>Y0?9n&E-kuAWgD>2sg}UObsoJv!6W)Rgq>R5d9jJ8klWZ0}42tx~eHQ)hZ7q#^w? z(^4|Lia~Xqj@+FwfeH1T-q%EWg11+%%t_azPWF0ky2&$Rf=*mlv4K!VPI`KlcV=zg zQfAIfnd9%vSk&*y#LwTC*wpWBQd&mJ%xZy&ji0yck%-KhN+)kdPPP}h<}u2$J&+SxGDs^@i3WIW;&h6wugX(m4Cr`>$ghva7oU=nxlXGUy zWSY^wJB>f1N|(v?UNr)|E+^BQ>I>19>NGy5lP}>@Gt<*EXQfW@Oq%2A?wOuC+cPC? zTADYzhOcadojEPVo9Y>R&fp&L@m;%u1BVQ$RTG>Bi3kR|`gQpU8eJwz0l}b?ijVj7 z>Fb%CIVDw>u;;9^{0wl3pWQ8k&df~r^D*|EcwC;?kzh zDmo8}#*C|5(RqzkbiOAxp*}_DH&#)1C>k}U?ih7%tfC8`Xym1JE4rYuiZ1lT4j447 zZbcV1R?$VC*ntW46#qqyRn!BDM%Nvo9_$CkPim~To}SpmdNRDH*5+-jwgH~l;X~?< z+W@Vts%x~nl{#9?Ku_%7>xtXI#>Q%pCw53Zu^OafHMOzY276)${jKga4%XUcHdb2# z8*|;-5*n*#2=pY?t*2(sR(qazLoYRWctV|ux;3_!>V{rw@StvWD{5>n)eXJW;6a#~ z+T(3NzuB#^y;L{!QiBJbU$>&h_EO!@OAQ{>y>3N~?WMY*ml`>s?#`uKV|%G?=%q$q zKCE{^$2!4r&AYCr#SqBLDpYA!pzLT{Mwh-^@d?f>xHjM&6t9vA7|!fZ7?Zk>Qt;h zu&hss?d&w7~si|35<6w&H(=s!4s@QPm9NRgrUt0DAz4AjMu_mt7-2{mALgSnXwP-a06H?Pt zxo%=sPLM_A=~W8tRhGRZjO(YkCYz8pBP(4N>yk3Rwcd;gX{)r!umry$bxJ?wotcx0&{#I7@GjC9NOxgd0J6KS{w0dVw2FFOcF>oRe{FM&_&x(_X7;n4SMv z+e2ll$1bF7Dx8wWw$6n)=VREKOP!g`ojcuz`}XzydCobCt=z9DVMIZq+eBT+h?Dy3 z)9v$!Q^X^CWTaDpKc013%Qb1s|_xuSHx^=r~ zQp%JGQ*$z~9g&$aVKR2sYV&-d^wqvxD???RoGk(9~cM`u!{DKlK)f2y#_?>~@zv4gC&%gf; z?UH>x_^Ws&2wO@7F*Dn39+tw9MUG|L)>A&j#|8_XrLzLP%E@Xfm?*7xwO{7xT z^TOS2UUFy281%nQ%-=x~nl;>`qK$iHXm$OA&oH7odV()-@(MM0$mj^oZC{(!h?PK@wz8%UxITg zytd$n^!wari+gdLc2+nC!TdFzjFtYkLfm=u4(Y4mUW!99ysiqUA4Q@+9!Iu#-G(3H zSHpjaxJ!Ge;a)24IO|%i{5>6wsOLgzSL#gsaKEpH|73CRR)>3$xZ}W3wfv74{mF8V zaxpafm+vxhR|6QjQgy{YO587jjDP*zApR$c`?Fe$tqmtO#U1yI^i>fMewn!U=gn4J zz2J^Zv?&#Qma!dak!ep#lQY~#eW48hKqOJ{oR+@?jwwQCxaULJ*@b+ zy5d)B{So()0R8Lj^d)QWiq)uA|Kc8L#A<{;QQYeazo-HIrQ#k{hyF5g4{SfXCI0c3 z8jp3gpNZn$KOp^w#D6i4Z1Sor{I%l#JpB9D4<|b`Tv_@wl~OqQUd_FOxKG5<7G4MN z^Y`x+_hg(NBQz7oxnE2K3KXHQbA8y?L zmx%k{AnqT2uDE+Lv>G)I@Yny8xaW#{OGoYLE1qfm?}mPqpNW*Q(*Krujo~m*TmMta zfg9H>clGpdknpn>8TT$ts=JqpdvTF*f2NM`lkYU{b(P;laX-!EPmTEJ-evq}L4kk$ z{6)f#f6TZK2WlH%bH)90xcmE`a<&O-;^W5u&1fI~9&b&e!;ow2zIsIC6yiu;`b>7OY6leZfG?B;7rf3djpDO3OS@91K} zpSaEV|K9lb#ji}GSu$O8l!Yjr(~9Ceh|^{cnG9539pHS=>2IudRM%i97oz z|N2p8$Nwv%xUTXq6ZbzM<{$sx#edme0o<`s3N~ za9s&^|L}L)>HpEVcM91qrW%e=U@LS#J%W`+TEk#P5MhK>yMuYrN%49zLCoL3SKKFt8vly`|MV@l{X32OV8FlpUlsTM zVaEN20RLZzdkH5_xIV$J*8bmR+y@5uSKW+#MTFrXz(4#LaqsUo?t$U=5%-cPm8yXO?+&SvhP|Hs8Ws6Ebh(fa4!+}=5@H2HK0H0wEDyE-++5o1MbBQxR*BIuK0K| zuDbFkz5(}%4Y(II;9k;zdqo58o|yXMpWJ|ZZUgRX8*ndcz&)yM{qgJHfO}R0?!^tb zmp0(8I5DcP{2Oqe*noRc1MVdaxK}jb?rC3t{F57S&uzecZ3FIQ4Y)^n>W^Rl2Hdk6 za4&Aay|e*$b$b2ri*LYvVgv3)4Y-#y;NC*lPRz}2_?xn3M_Ey>P-hXM+yVBS^Dch` zFILBOmdL3Akx{oh21PUxGvx;3S1fX}kB*(bnsQvqJ2x7AvTUxB8!|6sN$}Dj>RX0i z(aT2eX8f%$Tc4lYt8m!Cm%-y2DPq2G2h9t{1NwY?TJ6WLLgYR)#ZeXRh zsePR4^Oxq)~H4wp_p zkOheU2tV7Pwy-W_uB z{743_^KH3W^o^&!eMW9N;-D`(AH~RU^B|Xe$jHe)XjQ)W$*qFiIFaLeMqjo*zkJyR zInTF7ALrF|$^8zw9wHYRC?{sduLDZP)>mJ+!yy;jh;Y4->o0QkmD@_l%@(;c1LNnH zUObbjO3F=o>(a-1{T<{Ie>QU5kJOi)e*x`)>5d6jYWguFFWcl*mO_6o@s<$FXT%)8~OUmYbC=MIhkfwg^tH!uayLKDg?u&oSuacO)4(?yu>qmi!+Kxr!@{9M`$ki2je(q}5pp*{F18VJk3lZJ z5pwTBu16!}et}&7M##muFrG9*ZZPDM8zGktxp9qm|a?2Ybw+nK`jgZ58(9~0nkn0eM{=N}%!y&h! z5prJ0l{7+bCFFKALT)SMN*f{f9prX5Laqhw<(4%`5E5&a+JoQ;qR#^fQY5prE1*SZmMV<6{ggxpP#i)}#8p8r@kBoEg+6rn4Ek@_fm zpQ1Yq94kGG&3c080C_oomW;ILP07{gf%G>XzvB-Ye>~sE%h^UERENJVkm3GB$rHxk zt@MP;IWNGU%zGKmR{T6q8u@(`#^szGAb&~C`27yKaZee4a=TtRFAne*ux?>^-7#k_ zecJfrxj$Yt(iPy3>EixG>?-5$3GJ&Ee`3#YRziM<$n$(4FK19d{A$T}yroFRuQ%b? z$3&b<1N;TVkKu8DBK8I2Z!2{0a%Knk8(DLGFc|(yUNru;7;nlsEx@15;~0(?^2M@G z#dCwaoTCEd1JcF(>?}z+aerOg~i7g-4j{NkuK%I=@7j1F* z>e;UW{hePq4uyK)#mzT?K#6&y7Exm*eGpHo#v% z`Lo{ahrg1&#@_+$3;x~+@K;NC+@Dx@!1$BfxXSrxfWKP88v}p+4;p{vc6ciS`~~bY zFrJIy@3{Emc{g6pxdHxa=@+;^k^7V6i}9wM?*#bs+fU>EM48CP+45@wVUq( zmj9bwUP}Yy1NMtpPshWbQ}zRSevVg-^hmsP`XRsYgh>a_yJ`6e0pZkAPFvxxB2rh^ zN}hw${w{9V-|z6Z;}qkM=hw8qa{~MYMWzTa0+6m)#6a2->{@?cu443oX0DrQt!EjbV{?G`c zmgmKIIcEjP*OKr1;jb*&_~SV>?QcTE{$jAcpFP_6v-fkIg97~3(vHW#pJ!}9JkJgA zS4%v(Khb)e@h7)UmGhJUe*xh!AGg9^^5w?g2|NE!);%8lLisC=JkPc1{3x$op84J( z9QFNbBkybfKL*IxQoiHiZ^s1VkLS;LIX?>U=Ql1ahWzr0MxN)4!fL zKcJ4wH!s*5;Lk4{?oU*t8TmCP80GvRK)#lI?&3oIyTIr8n<*y3}=h6DZVY&Vef74}um*>xPID!2`K>X;B z`x9$(0>Znu{_wiMUpo9vpKbj4<{@_l`18xZm5@I^$H?>i8Lt}sQ9ylQ{J1}%ZVK?1 z84yl@KgQ3+{eWEK?=6^lIWG(FC--F-P9MlGyw%9_{24FjpaA(=!qNK^^Nc^9OVj?& z5Af%g504=nHQ&hdoSK&J6d)ha{usY6;BVaR#vkt?Ykz_B#9GRi`x99UjK3RfeNd9R8N)8!?_|)8QR#*k2y}tzBgN@tm3V7dU^ZC7!Rs-;RQSc&=+WykFoi zs?hk`V2Afm!~VEGv3!Z~$MbSJo_96uZwmay7X_qmUVy(^(zg=+67L8|-?ah$0?L8) zco+N?-D&)NW1@+A9N0CGH7g?kBuR*k0UQiaAmkD*Vx7;&%XK{Js)?D%>pYFNk@y z@JZoPai1^dTZFTO6U2S2m`4hS3eOeyj$&>nJVjWE^G3|Sqafq=gYcm6195*-%&!Sw z5_xt;J7VI|HR>hcG5`3nyUKM?mf#r&G^ zCE-Kjez%yH2p0%5#XVKbR|_u_UM%hxh`Fnhc$UD%>pYFNk@y z@JZoPai1^dTZFTO6U2S2m`4hS3eOeyj$&>nJVjWE^Ts!@{e!yvg$IR8#eKe*ZxPNC zUISuJGj0-i3z!UE4-OUkbHH0+J`;QxuUL-(qb=39IrxxLaVJ|_Jg*ja1Z4P!z#Ad| z88{F2JHgw)r@&jmA`fVNmA}sPhNZ`2#ZC@9`Xp&L5EB$Ai=pEA$9kfHNQ;4yJ<#np(;MxlcjH>jRMS zdI_Yy#bTc)_A|u(V&OMFE{!2mj*NZ^*Kl6mMgef4?HyC94DpA>(z865s-!Ggi90eA@y$Q&28jHj*J|jTJ z<6@BE^#bYtd|@Xc6Hoi^9EQ7vYe4Gl2Bv}?!6{%; z8RYozJji^!Pq;{UD@eIikmWKF#3PY$mxB!FQjp z^8t|IZvih>s_jaU;m!t^f&_5}1S02%&Vknx-eQvPz`CBgw9`Fn0%SXW`Bx+NJV^T|K-$k0 z{&I|;E?05)gUr`ELF&yD^GzW0BNJpgrh`n!)gaSxnJ`&6RNM!Oxwr6K;pxH_;8oD~ zJCriK&q1bRi2iY%#{yX{ zzy55}QvotP-+)ZdUg2)x2jc#=nBNe-Bz#)961)=n^FW3(8Dx5r#5@3Gdb)#5&u2%B z+=n3Tw}G^ONZ0~o{MY?t;{Pm2y(>T@Ic^!qcrOAO?|H(TgxTVrA?9hqD}^J3{lUwj z?`)9z!$8LSrwU^}4Bi3zFG0p{q1fk&eU8|V6fXGD#CI-O1o`Vg=Jzy^@tz1W-hT%f z?@_`;;l<+KOU&mBI|)w}y1>hz@0TA;I3IzG_eL@Q17y4(1DAl8i2XpZzfkPm!o2TI zexDAqzMKj&{^20wZ-I>eiSJDOD?rBou<&c)9&z6#=J$kKgzJP)fMcPr2xK@}Ame|T zm`8z({~&M)_yY!K%6$XU{&SG_>xHo(>&xrkn)bRLWdF4aWdF4iWdC(D*bclNWdAi@ z?1zC&_aKn%{R|LIH13 z!^r~~&Naeu!hXW0AoW&Y@kF`LKy2ys{Rr$0^Jb9YtQPl&goVOegx$b_)U(fUH~1dn zzX=RM`P~b$e3ycZ*8=bsFb8C~6U2SAm@g2X4su*P6}%f+*&M`FzpoR#3;K6`ZN`_k zK!)==h^WN92!04Y3vzs12~y88kn6`n5KE!H^T3B7mk!e3WRQ9;2kGw;knO0y*!L8k zCp-(J-gY4Mo&r*D1W3Kd{%Q1n4^r6+5pEZ55MB$iU7sy%4zgYE_|%k33HTt&Wh2P>>hs`AxIYH6Ty6kaFJ^))k2Ek5 zoCFR92Y{>>UwmTnX&17Egw2FbkaFLBZ0g@Z5LF}YYY!D}wN4QT2a|e*|iUC;Hj1;DcXMzGM?XnN5K!pzC^eVWWE%Gzkx+y zZ^UCZ$b5svSQ$d#BAt{B8qTepiDmzwRL85e0Ic z^wqm2zlMPQeQmC__i1G(QQg$>m}|P zkmYd&Ncq2klpi3B7siPD$8Vbad>N#^T#)5^_g0hsLhyd1|8@{tW_{;^%OQ6i$aF@6 z45tamaCW_6m?NAh90O9$1F{}Qf$TRzLH0YFUN`;3%q_pPk~&|{Z;}?xPJjs{zH)Q-2vu-TR^6Fo$wKm@y`btZZ61hXMqfNDo8z7 zfsexd5|H)40SAhft1e$DW3{5{L4Yg_Xa5+15&;zNck^cHS({6lz$PV{Bn@;^FYdHfs`K% zQh#TV@@+xNSH5E8zXd7(DMrs1f8Q22}Y9DWJUxPZHao59Cnegb?F zyc2u|ydHcSoB#$>4;Tb~^P*C3!hWZ43-}w%>%rbgQoh)Gg_jEl3oBkQ{$B>!j|>-c zACP*^1*zvGIzNU}4z2>z#XKH-3}z=t{|~G)IPM9F>qC(FwGCVX`^Q0!Co{mi!BlY{3-(|Y2kHOS=S=-v2h#sikoKcN#;d=uo7f*g zp|hVn2vYuYkm0Qd8D1{P`kn)_z7GZ24q`#d??Gj!`+FeGTR@JR_k#3424sAPi+dmN zBE8gQg!|BF>2E5?dXy;UE+EIVj$m)tM}n+Z$IzH5zfbtKaJ}$h;bP$|;Ur<{ z6DEDP3ll)5vnR-Oy2bwR<4WCw`nL(B`#(UsKLfr8`^!M4dlbm{^aNQiPX(DTQ6T+= zfGo#P(YRTTC142j+zV1}Hh3%Svq1KvX(0R2N#JsXGX`Y8`5gvdhPNMNc+U$*2zv;- zfRsCqL81u$4}r|ry&&7?{UGyk)Wb&4g&^f(LCUoUDHjP+&H*xhCyGt{eg+x8FF}^i zCm{RzjUeUMfQ;|sAoJrv@GIyq63zv6d4ml1Dv;rh0U7Qfka~K7=qlnmfh)kh51IV@ z2xR^}4YD1r5c4wdBgoAcW`PXnDq*6q9msH7f(+LMGTf67nsASRYZ)GRFSrie4lW1x zgNs3ip9wO&D?s+QW5s@?aH#M?kowL9sqfbZjJ_{G>MI4QZyiW|4}z3004YBKWcY(Y z%J%>%-v*@o?<ZZ%P5FO)Sg&^f;f|Q>MQa%Z!d^eE!9wYn_m74YZ5J>xvh3mm0$Uh6R93BB#4tIbo|Cu1e z8v-)CU+y#Y@H-GzeGh=FhaZ5fhdV&l!)HPIe;8yvoC{LVXpnlEf^3(6qH(cZ{t7bw z+rhyw&jIP4A@0+}{UUKc0A;U2&u(xd_%etoK-{Ck#o#)auLCjU$6X1&1P%m)5l$~K z2s|C!0Q+)uG8l^DHi6XpDEKD0R5%xW1?DMY9wWS1c&_l5yN#X?LHb__avpK6nA?NY zb8?x?Kfsq^ehZ}BII&LzG33WRaF;2!nc(>_p9yXSf4tLhy>O0jJa`1|mx0XBA>dw^ z&jBYu|C@K1@_!2Ccr^^Bb2&&oy~KQ;m`@dRGco^I zXygxqlz#(c{O%I_0q(G$ia@rTbddR$2r}QUDKPbDFi1HM zNV$`XjQgPZCSSXQ=O7(tgN#obkog-9o(=w*XY9*`dxakfw+mkpt`R;eyjNHtoGZ*0 zP7_`!93>niyhwPCu)Q!^7%DtD&&2ab;XdJ~!gqwP3pWba3ZE1{D7;&^SePwL5ViqX zZ;#$)!rc$j{F<1b6Y~wiOU1swn8SsS-fGHcsqjW&Kk#+re;l|Ki~(6bEya8!SIPyX z+!G+n_coCA;0loS;JUd+|3r}f2ZEGq2U70XEk!|AyGVBKE~%zeMbB7yEQEPZ9HZApM^s_ASL+c9XGx9b~*81R3w^L8h

#=8rs^F!?am}C5X4AS23>SVn+t@z| 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 ZHC|J-*JM?CZ53XVfpo|KrK-3u_m~;zXjRZRp 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 literal 0 HcmV?d00001 diff --git a/examples/toy/pasta/toy_cpp/toy.cpp b/examples/toy/pasta/toy_cpp/toy.cpp new file mode 100644 index 0000000..4fc4df5 --- /dev/null +++ b/examples/toy/pasta/toy_cpp/toy.cpp @@ -0,0 +1,107 @@ +#include +#include +#include +#include "circom.hpp" +#include "calcwit.hpp" +void Example_0_create(uint soffset,uint coffset,Circom_CalcWit* ctx,std::string componentName,uint componentFather); +void Example_0_run(uint ctx_index,Circom_CalcWit* ctx); +Circom_TemplateFunction _functionTable[1] = { +Example_0_run }; +Circom_TemplateFunction _functionTableParallel[1] = { +NULL }; +uint get_main_input_signal_start() {return 3;} + +uint get_main_input_signal_no() {return 3;} + +uint get_total_signal_no() {return 6;} + +uint get_number_of_components() {return 1;} + +uint get_size_of_input_hashmap() {return 256;} + +uint get_size_of_witness() {return 5;} + +uint get_size_of_constants() {return 2;} + +uint get_size_of_io_map() {return 0;} + +void release_memory_component(Circom_CalcWit* ctx, uint pos) {{ + +if (pos != 0){{ + +if(ctx->componentMemory[pos].subcomponents) +delete []ctx->componentMemory[pos].subcomponents; + +if(ctx->componentMemory[pos].subcomponentsParallel) +delete []ctx->componentMemory[pos].subcomponentsParallel; + +if(ctx->componentMemory[pos].outputIsSet) +delete []ctx->componentMemory[pos].outputIsSet; + +if(ctx->componentMemory[pos].mutexes) +delete []ctx->componentMemory[pos].mutexes; + +if(ctx->componentMemory[pos].cvs) +delete []ctx->componentMemory[pos].cvs; + +if(ctx->componentMemory[pos].sbct) +delete []ctx->componentMemory[pos].sbct; + +}} + + +}} + + +// function declarations +// template declarations +void Example_0_create(uint soffset,uint coffset,Circom_CalcWit* ctx,std::string componentName,uint componentFather){ +ctx->componentMemory[coffset].templateId = 0; +ctx->componentMemory[coffset].templateName = "Example"; +ctx->componentMemory[coffset].signalStart = soffset; +ctx->componentMemory[coffset].inputCounter = 3; +ctx->componentMemory[coffset].componentName = componentName; +ctx->componentMemory[coffset].idFather = componentFather; +ctx->componentMemory[coffset].subcomponents = new uint[0]; +} + +void Example_0_run(uint ctx_index,Circom_CalcWit* ctx){ +FrElement* signalValues = ctx->signalValues; +u64 mySignalStart = ctx->componentMemory[ctx_index].signalStart; +std::string myTemplateName = ctx->componentMemory[ctx_index].templateName; +std::string myComponentName = ctx->componentMemory[ctx_index].componentName; +u64 myFather = ctx->componentMemory[ctx_index].idFather; +u64 myId = ctx_index; +u32* mySubcomponents = ctx->componentMemory[ctx_index].subcomponents; +bool* mySubcomponentsParallel = ctx->componentMemory[ctx_index].subcomponentsParallel; +FrElement* circuitConstants = ctx->circuitConstants; +std::string* listOfTemplateMessages = ctx->listOfTemplateMessages; +FrElement expaux[3]; +FrElement lvar[0]; +uint sub_component_aux; +uint index_multiple_eq; +{ +PFrElement aux_dest = &signalValues[mySignalStart + 0]; +// load src +Fr_add(&expaux[0],&signalValues[mySignalStart + 2],&signalValues[mySignalStart + 4]); // line circom 12 +// end load src +Fr_copy(aux_dest,&expaux[0]); +} +{ +PFrElement aux_dest = &signalValues[mySignalStart + 1]; +// load src +Fr_add(&expaux[0],&signalValues[mySignalStart + 2],&signalValues[mySignalStart + 3]); // line circom 13 +// end load src +Fr_copy(aux_dest,&expaux[0]); +} +for (uint i = 0; i < 0; i++){ +uint index_subc = ctx->componentMemory[ctx_index].subcomponents[i]; +if (index_subc != 0)release_memory_component(ctx,index_subc); +} +} + +void run(Circom_CalcWit* ctx){ +Example_0_create(1,0,ctx,"main",0); +Example_0_run(0,ctx); +} + diff --git a/examples/toy/toy_cpp/toy.dat b/examples/toy/pasta/toy_cpp/toy.dat similarity index 100% rename from examples/toy/toy_cpp/toy.dat rename to examples/toy/pasta/toy_cpp/toy.dat diff --git a/examples/toy/pasta/toy_cpp/toy.o b/examples/toy/pasta/toy_cpp/toy.o new file mode 100644 index 0000000000000000000000000000000000000000..12a727fc7e7ced3751d31e619a079838695f2c66 GIT binary patch literal 4848 zcmbtYeQX=$8GoImi91S?ZZHz)hY=ucW7*;~$v||QP3-2bNh+^NX;f(5T%AkeV4p4f zoVuYK=}Zte*AQ(TLK@n-|A4g0D)QFKId;@yQYbhEi0BBNR z#ANm$Ip?~X)9K10&ilgseKuO<6I1|*;?d=EH!*e(398s6F`GCaiAK4ai>fJ|>&gjt zywf61vv4?vV*bZ8P~VWED|U3MHx%p(uHqRHPfU-!g?KdO(hjR{tCrRk=h0*$k<@It zJD%MqJ097I7Md=!7EVIEjGm5ZBSPq&@2jr*=BfD(a?jnYFQr6vp4Cpqv?0#BLk@FR z67eQQAq!%@Z(+Xmmf@O^oU5aJIISd9OX;pJP;JQr!mEF~HDBpwtAAMLQD^=ZfCdaJ zJ&Y4;?fD|j^cP_VC8I`iQS{AJ@4 zsj!U#Nd+bu;f3zPc!N|p;4`jD7cbXz7fv^LrDAJ?l%H#miWiz!R#x68Yq=1*+b0yw zP)N3-tGMg+p5p#Xa=sjqi{~z#r_jXFZ!;6RWcpOp$1`t3x*Nq-x{fGu1bK!4pV zNit?_?B`Qm#u2Mect5ou~g z-)=1qG$iU@FB)7cI#h`JMti0{(p!6q*=4zKd|8_Mn|=qjQMH_ZvsAY?zz!Do-)prj zKU>QFr`!1SdJghVk$1c09fo&F-z{BStdfem0*Ej_Jni(Kcl+zUT+h^!9*_$I%W{6s z%ntv{mBZh%=Pwuc@3HeQoBmS%4KMAL^w`WAG8W}Rk54i}joxyov7UAU>>6R$Y#)x0 zaiyn_^~pwPkK`BU1J@CERoC}V@S$EQ{~;W%&4m}d=R(>4lCG!fk z`5q1q;IQGCtTnRF2xB;{x3i;+9o_L_1v|O-wF>r2&t0!nu#28QP#vV-e((3EJ!~vM za1DiXN+J~(H(_WVhsVyFs)DwW{am!~>vZ1)nQ^U4>le{Yx{?0;CiKLi4BoZR_*_@i6`gY&O!*3;j#b-^nV16pQG2@!Y({g3L2< zn0a#bp86d%Uh3)Hknh6qUBz7$B>Kx(u(tlmijJGbW74$4ZI5}kU>AqomCrVhcMf(7 zTd?~*>`Gg(dk=OmY{6~^<~_XyJ6emJuoLUHt}ow2&PQN3DD23`B)fkH^EGFyi`$;A zdd6HKvOf!(l;|U^r%5-kr?nySOhmfPm8F-0>2f! z68tOR*WioC+^sKzlm1uWq<;*Y^y5N*Cpg~io3?@DF5L8I1Sk9^_*cPyCh!#aZNNta zeo*jl3;r19PjzO%sm=kx4-5G{;JYEe4SWw{->nz=tC&04{}r6%7r=J{zX*)=&v4*vS;P|T!2<{V{gd|^tAMujl=LMe>d{FR! z;6A}AFXf^4O3DLf#(5jTfP0=tKWkxN-)A!d+xLYr*wLGWO?00kY~OEw4FzG66VdxV z;dz1I75KcsT>>u({5yfC1*UyR{xbrXzzNeNh|XXTCOOfUFbGcy`~z^p_Wf=Qes!3W z{XO&o>9P0h@0lX>!qtpN*G_!QrT@7Le*>|d_WyM08=!RRD_!^j7p8sYwEx(JpK;kg z>B|4COF!YNhw%exeCnl6;fwKD%Xdapozq(dk7=o_&NHzQO^Nf2uB7#G)1s9uv~1#p zn&!!2`bbPAHC59ymfBD1Ol(56lo~v3o&SEP?qp2Y)Qs?Ib84*2qe^Bpp`^^H{`=PG zlc>;Aw3yYbuUAW2er85JsnZm!nF!5LJYrf5DHcD}tMB97-`HZA5E*ukS*Pp&T0{VYey`N_V5lR9z7b)x; zq9@ZN35O}u5$ntRu$sx@v)VNSV86Q(I6rp7{2QfrXKz "); +} else { + const input = JSON.parse(readFileSync(process.argv[3], "utf8")); + + const buffer = readFileSync(process.argv[2]); + wc(buffer).then(async witnessCalculator => { + // const w= await witnessCalculator.calculateWitness(input,0); + // for (let i=0; i< w.length; i++){ + // console.log(w[i]); + // } + const buff= await witnessCalculator.calculateWTNSBin(input,0); + writeFile(process.argv[4], buff, function(err) { + if (err) throw err; + }); + }); +} diff --git a/examples/toy/toy_js/toy.wasm b/examples/toy/pasta/toy_js/toy.wasm similarity index 98% rename from examples/toy/toy_js/toy.wasm rename to examples/toy/pasta/toy_js/toy.wasm index 9e69b53ba23e1304bebc836ea7332bb5d86b4cdd..95405bfe3428cce57d827b5cad1c928455160b52 100644 GIT binary patch delta 57 zcmV-90LK5?i~{0}0a&L08rGvEsL_QOV delta 49 zcmV-10M7s7i~`z>0 { + const h = fnvHash(k); + const hMSB = parseInt(h.slice(0,8), 16); + const hLSB = parseInt(h.slice(8,16), 16); + const fArr = flatArray(input[k]); + let signalSize = this.instance.exports.getInputSignalSize(hMSB, hLSB); + if (signalSize < 0){ + throw new Error(`Signal ${k} not found\n`); + } + if (fArr.length < signalSize) { + throw new Error(`Not enough values for input signal ${k}\n`); + } + if (fArr.length > signalSize) { + throw new Error(`Too many values for input signal ${k}\n`); + } + for (let i=0; i0) { + res.unshift(0); + i--; + } + } + return res; +} + +function fromArray32(arr) { //returns a BigInt + var res = BigInt(0); + const radix = BigInt(0x100000000); + for (let i = 0; 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 NA5EnA@NAl2{|gTSr`P}h diff --git a/examples/toy/toy_cpp/fr.o b/examples/toy/toy_cpp/fr.o deleted file mode 100644 index 9a8e4a3064045563bad145a0d7ee368c3c9f7142..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12392 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 z 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 bZksveaqP7_HGZec=Tv!}D#PP(>Fa+0Yl%ZA diff --git a/examples/toy/toy_cpp/toy b/examples/toy/toy_cpp/toy deleted file mode 100755 index 8de5abe0d2349254e663a499842acc30eb2f0edc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 230120 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ň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 |$M=V-J6LKr;T7>FELL`hjd?x_WCmTRBL*aS%H^ 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 F{~s#m@1p() + ); let iteration_count = 5; let root = current_dir().unwrap(); - let circuit_file = root.join("examples/toy/toy.r1cs"); - let r1cs = load_r1cs(&FileLocation::PathBuf(circuit_file)); - let witness_generator_wasm = root.join("examples/toy/toy_js/toy.wasm"); + let circuit_file = root.join(circuit_filepath); + let r1cs = load_r1cs::(&FileLocation::PathBuf(circuit_file)); + let witness_generator_file = root.join(witness_gen_filepath); let mut private_inputs = Vec::new(); for i in 0..iteration_count { @@ -22,9 +34,9 @@ fn main() { private_inputs.push(private_input); } - let start_public_input = vec![F1::from(10), F1::from(10)]; + let start_public_input = [F::::from(10), F::::from(10)]; - let pp = create_public_params(r1cs.clone()); + let pp: PublicParams = create_public_params(r1cs.clone()); println!( "Number of constraints per step (primary circuit): {}", @@ -47,27 +59,22 @@ fn main() { println!("Creating a RecursiveSNARK..."); let start = Instant::now(); let recursive_snark = create_recursive_circuit( - FileLocation::PathBuf(witness_generator_wasm), + FileLocation::PathBuf(witness_generator_file), r1cs, private_inputs, - start_public_input.clone(), + start_public_input.to_vec(), &pp, ) .unwrap(); println!("RecursiveSNARK creation took {:?}", start.elapsed()); // TODO: empty? - let z0_secondary = vec![::Scalar::zero()]; + let z0_secondary = [F::::from(0)]; // verify the recursive SNARK println!("Verifying a RecursiveSNARK..."); let start = Instant::now(); - let res = recursive_snark.verify( - &pp, - iteration_count, - start_public_input.clone(), - z0_secondary.clone(), - ); + let res = recursive_snark.verify(&pp, iteration_count, &start_public_input, &z0_secondary); println!( "RecursiveSNARK::verify: {:?}, took {:?}", res, @@ -78,8 +85,8 @@ fn main() { // produce a compressed SNARK println!("Generating a CompressedSNARK using Spartan with IPA-PC..."); let start = Instant::now(); - let (pk, vk) = CompressedSNARK::<_, _, _, _, S1, S2>::setup(&pp).unwrap(); - let res = CompressedSNARK::<_, _, _, _, S1, S2>::prove(&pp, &pk, &recursive_snark); + let (pk, vk) = CompressedSNARK::<_, _, _, _, S, S>::setup(&pp).unwrap(); + let res = CompressedSNARK::<_, _, _, _, S, S>::prove(&pp, &pk, &recursive_snark); println!( "CompressedSNARK::prove: {:?}, took {:?}", res.is_ok(), @@ -94,8 +101,8 @@ fn main() { let res = compressed_snark.verify( &vk, iteration_count, - start_public_input.clone(), - z0_secondary, + start_public_input.to_vec(), + z0_secondary.to_vec(), ); println!( "CompressedSNARK::verify: {:?}, took {:?}", @@ -104,3 +111,15 @@ fn main() { ); assert!(res.is_ok()); } + +fn main() { + let group_name = "bn254"; + + let circuit_filepath = format!("examples/toy/{}/toy.r1cs", group_name); + for witness_gen_filepath in [ + format!("examples/toy/{}/toy_cpp/toy", group_name), + format!("examples/toy/{}/toy_js/toy.wasm", group_name), + ] { + run_test(circuit_filepath.clone(), witness_gen_filepath); + } +} diff --git a/examples/toy.rs b/examples/toy_pasta.rs similarity index 58% rename from examples/toy.rs rename to examples/toy_pasta.rs index d2236ce..f6e842d 100644 --- a/examples/toy.rs +++ b/examples/toy_pasta.rs @@ -1,19 +1,30 @@ use std::{collections::HashMap, env::current_dir, time::Instant}; use nova_scotia::{ - circom::reader::load_r1cs, create_public_params, create_recursive_circuit, FileLocation, F1, - G2, S1, S2, + circom::reader::load_r1cs, create_public_params, create_recursive_circuit, FileLocation, F, S, +}; +use nova_snark::{ + provider, + traits::{circuit::StepCircuit, Group}, + CompressedSNARK, PublicParams, }; -use nova_snark::{traits::Group, CompressedSNARK}; use serde_json::json; -fn main() { +fn run_test(circuit_filepath: String, witness_gen_filepath: String) { + type G1 = pasta_curves::pallas::Point; + type G2 = pasta_curves::vesta::Point; + + println!( + "Running test with witness generator: {} and group: {}", + witness_gen_filepath, + std::any::type_name::() + ); let iteration_count = 5; let root = current_dir().unwrap(); - let circuit_file = root.join("examples/toy/toy.r1cs"); - let r1cs = load_r1cs(&FileLocation::PathBuf(circuit_file)); - let witness_generator_file = root.join("examples/toy/toy_cpp/toy"); + let circuit_file = root.join(circuit_filepath); + let r1cs = load_r1cs::(&FileLocation::PathBuf(circuit_file)); + let witness_generator_file = root.join(witness_gen_filepath); let mut private_inputs = Vec::new(); for i in 0..iteration_count { @@ -22,9 +33,9 @@ fn main() { private_inputs.push(private_input); } - let start_public_input = vec![F1::from(10), F1::from(10)]; + let start_public_input = [F::::from(10), F::::from(10)]; - let pp = create_public_params(r1cs.clone()); + let pp: PublicParams = create_public_params(r1cs.clone()); println!( "Number of constraints per step (primary circuit): {}", @@ -50,24 +61,19 @@ fn main() { FileLocation::PathBuf(witness_generator_file), r1cs, private_inputs, - start_public_input.clone(), + start_public_input.to_vec(), &pp, ) .unwrap(); println!("RecursiveSNARK creation took {:?}", start.elapsed()); // TODO: empty? - let z0_secondary = vec![::Scalar::zero()]; + let z0_secondary = [F::::from(0)]; // verify the recursive SNARK println!("Verifying a RecursiveSNARK..."); let start = Instant::now(); - let res = recursive_snark.verify( - &pp, - iteration_count, - start_public_input.clone(), - z0_secondary.clone(), - ); + let res = recursive_snark.verify(&pp, iteration_count, &start_public_input, &z0_secondary); println!( "RecursiveSNARK::verify: {:?}, took {:?}", res, @@ -78,8 +84,9 @@ fn main() { // produce a compressed SNARK println!("Generating a CompressedSNARK using Spartan with IPA-PC..."); let start = Instant::now(); - let (pk, vk) = CompressedSNARK::<_, _, _, _, S1, S2>::setup(&pp).unwrap(); - let res = CompressedSNARK::<_, _, _, _, S1, S2>::prove(&pp, &pk, &recursive_snark); + + let (pk, vk) = CompressedSNARK::<_, _, _, _, S, S>::setup(&pp).unwrap(); + let res = CompressedSNARK::<_, _, _, _, S, S>::prove(&pp, &pk, &recursive_snark); println!( "CompressedSNARK::prove: {:?}, took {:?}", res.is_ok(), @@ -94,8 +101,8 @@ fn main() { let res = compressed_snark.verify( &vk, iteration_count, - start_public_input.clone(), - z0_secondary, + start_public_input.to_vec(), + z0_secondary.to_vec(), ); println!( "CompressedSNARK::verify: {:?}, took {:?}", @@ -104,3 +111,15 @@ fn main() { ); assert!(res.is_ok()); } + +fn main() { + let group_name = "pasta"; + + let circuit_filepath = format!("examples/toy/{}/toy.r1cs", group_name); + for witness_gen_filepath in [ + format!("examples/toy/{}/toy_cpp/toy", group_name), + format!("examples/toy/{}/toy_js/toy.wasm", group_name), + ] { + run_test(circuit_filepath.clone(), witness_gen_filepath); + } +} diff --git a/src/circom/file.rs b/src/circom/file.rs index 8fad95f..564f3b7 100644 --- a/src/circom/file.rs +++ b/src/circom/file.rs @@ -4,15 +4,13 @@ use crate::circom::circuit::Constraint; use byteorder::{LittleEndian, ReadBytesExt}; use ff::PrimeField; -use pasta_curves::group::Group; +use hex_literal::hex; +use nova_snark::traits::Group; use std::{ collections::HashMap, io::{Error, ErrorKind, Read, Result, Seek, SeekFrom}, }; -type G1 = pasta_curves::pallas::Point; -type G2 = pasta_curves::vesta::Point; - // R1CSFile's header #[derive(Debug, Default)] pub struct Header { @@ -120,7 +118,11 @@ fn read_map(mut reader: R, size: u64, header: &Header) -> Result(mut reader: R) -> Result::Scalar>> { +pub fn from_reader(mut reader: R) -> Result::Scalar>> +where + G1: Group::Scalar>, + G2: Group::Scalar>, +{ let mut magic = [0u8; 4]; reader.read_exact(&mut magic)?; if magic != [0x72, 0x31, 0x63, 0x73] { @@ -161,8 +163,14 @@ pub fn from_reader(mut reader: R) -> Result(reader).unwrap(); assert_eq!(file.version, 1); assert_eq!(file.header.field_size, 32); diff --git a/src/circom/reader.rs b/src/circom/reader.rs index 2a445f4..171e343 100644 --- a/src/circom/reader.rs +++ b/src/circom/reader.rs @@ -14,9 +14,7 @@ use crate::circom::circuit::{CircuitJson, R1CS}; use crate::circom::file::{from_reader, read_field}; use crate::FileLocation; use ff::PrimeField; -use pasta_curves::group::Group; - -type G1 = pasta_curves::pallas::Point; +use nova_snark::traits::Group; pub fn generate_witness_from_bin( witness_bin: &Path, @@ -172,7 +170,11 @@ pub(crate) fn load_witness_from_bin_reader( #[cfg(not(target_family = "wasm"))] /// load r1cs file by filename with autodetect encoding (bin or json) -pub fn load_r1cs(filename: &FileLocation) -> R1CS<::Scalar> { +pub fn load_r1cs(filename: &FileLocation) -> R1CS<::Scalar> +where + G1: Group::Scalar>, + G2: Group::Scalar>, +{ let filename = match filename { FileLocation::PathBuf(filename) => filename, FileLocation::URL(_) => panic!("unreachable"), @@ -180,7 +182,7 @@ pub fn load_r1cs(filename: &FileLocation) -> R1CS<::Scalar> { if filename.ends_with("json") { load_r1cs_from_json_file(filename) } else { - load_r1cs_from_bin_file(filename) + load_r1cs_from_bin_file::(filename) } } @@ -230,17 +232,25 @@ fn load_r1cs_from_json(reader: R) -> R1CS { } /// load r1cs from bin file by filename -fn load_r1cs_from_bin_file(filename: &Path) -> R1CS<::Scalar> { +fn load_r1cs_from_bin_file(filename: &Path) -> R1CS<::Scalar> +where + G1: Group::Scalar>, + G2: Group::Scalar>, +{ let reader = OpenOptions::new() .read(true) .open(filename) .expect("unable to open."); - load_r1cs_from_bin(BufReader::new(reader)) + load_r1cs_from_bin::<_, G1, G2>(BufReader::new(reader)) } /// load r1cs from bin by a reader -pub(crate) fn load_r1cs_from_bin(reader: R) -> R1CS<::Scalar> { - let file = from_reader(reader).expect("unable to read."); +pub(crate) fn load_r1cs_from_bin(reader: R) -> R1CS<::Scalar> +where + G1: Group::Scalar>, + G2: Group::Scalar>, +{ + let file = from_reader::<_, G1, G2>(reader).expect("unable to read."); let num_inputs = (1 + file.header.n_pub_in + file.header.n_pub_out) as usize; let num_variables = file.header.n_wires as usize; let num_aux = num_variables - num_inputs; diff --git a/src/circom/wasm.rs b/src/circom/wasm.rs index c09f41e..3e98207 100644 --- a/src/circom/wasm.rs +++ b/src/circom/wasm.rs @@ -1,4 +1,4 @@ -use crate::{FileLocation, G1, R1CS}; +use crate::{FileLocation, R1CS}; use crate::circom::reader::{load_r1cs_from_bin, load_witness_from_bin_reader}; use ff::PrimeField; @@ -43,14 +43,18 @@ pub async fn generate_witness_browser(input_json_string: &str, wasm_file: &str) #[cfg(target_family = "wasm")] /// load r1cs file by filename with autodetect encoding (bin or json) -pub async fn load_r1cs(filename: &FileLocation) -> R1CS<::Scalar> { +pub async fn load_r1cs(filename: &FileLocation) -> R1CS<::Scalar> +where + G1: Group::Scalar>, + G2: Group::Scalar>, +{ let filename = match filename { FileLocation::PathBuf(_) => panic!("unreachable"), FileLocation::URL(path) => path, }; let r1cs_ser = read_file(filename).await.to_vec(); let r1cs_cursor = Cursor::new(r1cs_ser); - load_r1cs_from_bin(r1cs_cursor) + load_r1cs_from_bin::<_, G1, G2>(r1cs_cursor) } #[cfg(target_family = "wasm")] diff --git a/src/lib.rs b/src/lib.rs index 5f514bd..be27caa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,7 +5,9 @@ use std::{ path::{Path, PathBuf}, }; +use crate::circom::reader::generate_witness_from_bin; use circom::circuit::{CircomCircuit, R1CS}; +use ff::Field; use nova_snark::{ traits::{circuit::TrivialTestCircuit, Group}, PublicParams, RecursiveSNARK, @@ -15,8 +17,6 @@ use num_traits::Num; use serde::{Deserialize, Serialize}; use serde_json::Value; -use crate::circom::reader::generate_witness_from_bin; - #[cfg(not(target_family = "wasm"))] use crate::circom::reader::generate_witness_from_wasm; @@ -25,24 +25,23 @@ use crate::circom::wasm::generate_witness_from_wasm; pub mod circom; -pub type G1 = pasta_curves::pallas::Point; -pub type F1 = ::Scalar; -pub type EE1 = nova_snark::provider::ipa_pc::EvaluationEngine; -pub type S1 = nova_snark::spartan::RelaxedR1CSSNARK; -pub type G2 = pasta_curves::vesta::Point; -pub type F2 = ::Scalar; -pub type EE2 = nova_snark::provider::ipa_pc::EvaluationEngine; -pub type S2 = nova_snark::spartan::RelaxedR1CSSNARK; - -pub type C1 = CircomCircuit; -pub type C2 = TrivialTestCircuit; +pub type F = ::Scalar; +pub type EE = nova_snark::provider::ipa_pc::EvaluationEngine; +pub type S = nova_snark::spartan::snark::RelaxedR1CSSNARK>; +pub type C1 = CircomCircuit<::Scalar>; +pub type C2 = TrivialTestCircuit<::Scalar>; +#[derive(Clone)] pub enum FileLocation { PathBuf(PathBuf), URL(String), } -pub fn create_public_params(r1cs: R1CS) -> PublicParams { +pub fn create_public_params(r1cs: R1CS>) -> PublicParams, C2> +where + G1: Group::Scalar>, + G2: Group::Scalar>, +{ let circuit_primary = CircomCircuit { r1cs, witness: None, @@ -61,13 +60,110 @@ struct CircomInput { } #[cfg(not(target_family = "wasm"))] -pub fn create_recursive_circuit( +fn compute_witness( + current_public_input: Vec, + private_input: HashMap, + witness_generator_file: FileLocation, + witness_generator_output: &Path, +) -> Vec<::Scalar> +where + G1: Group::Scalar>, + G2: Group::Scalar>, +{ + let decimal_stringified_input: Vec = current_public_input + .iter() + .map(|x| BigInt::from_str_radix(x, 16).unwrap().to_str_radix(10)) + .collect(); + + let input = CircomInput { + step_in: decimal_stringified_input.clone(), + extra: private_input.clone(), + }; + + let is_wasm = match &witness_generator_file { + FileLocation::PathBuf(path) => path.extension().unwrap_or_default() == "wasm", + FileLocation::URL(_) => true, + }; + let input_json = serde_json::to_string(&input).unwrap(); + + if is_wasm { + generate_witness_from_wasm::>( + &witness_generator_file, + &input_json, + &witness_generator_output, + ) + } else { + let witness_generator_file = match &witness_generator_file { + FileLocation::PathBuf(path) => path, + FileLocation::URL(_) => panic!("unreachable"), + }; + generate_witness_from_bin::>( + &witness_generator_file, + &input_json, + &witness_generator_output, + ) + } +} + +#[cfg(target_family = "wasm")] +async fn compute_witness( + current_public_input: Vec, + private_input: HashMap, witness_generator_file: FileLocation, - r1cs: R1CS, + witness_generator_output: &Path, +) -> Vec<::Scalar> +where + G1: Group::Scalar>, + G2: Group::Scalar>, +{ + let decimal_stringified_input: Vec = current_public_input + .iter() + .map(|x| BigInt::from_str_radix(x, 16).unwrap().to_str_radix(10)) + .collect(); + + let input = CircomInput { + step_in: decimal_stringified_input.clone(), + extra: private_input.clone(), + }; + + let is_wasm = match &witness_generator_file { + FileLocation::PathBuf(path) => path.extension().unwrap_or_default() == "wasm", + FileLocation::URL(_) => true, + }; + let input_json = serde_json::to_string(&input).unwrap(); + + if is_wasm { + generate_witness_from_wasm::>( + &witness_generator_file, + &input_json, + &witness_generator_output, + ) + .await + } else { + let witness_generator_file = match &witness_generator_file { + FileLocation::PathBuf(path) => path, + FileLocation::URL(_) => panic!("unreachable"), + }; + generate_witness_from_bin::>( + &witness_generator_file, + &input_json, + &witness_generator_output, + ) + } +} + +#[cfg(not(target_family = "wasm"))] +pub fn create_recursive_circuit( + witness_generator_file: FileLocation, + r1cs: R1CS>, private_inputs: Vec>, - start_public_input: Vec, - pp: &PublicParams, -) -> Result, std::io::Error> { + start_public_input: Vec>, + pp: &PublicParams, C2>, +) -> Result, C2>, std::io::Error> +where + G1: Group::Scalar>, + G2: Group::Scalar>, +{ let root = current_dir().unwrap(); let witness_generator_output = root.join("circom_witness.wtns"); @@ -79,45 +175,36 @@ pub fn create_recursive_circuit( .collect::>(); let mut current_public_input = start_public_input_hex.clone(); - let circuit_secondary = TrivialTestCircuit::default(); - let z0_secondary = vec![::Scalar::zero()]; - let mut recursive_snark: Option> = None; - - for i in 0..iteration_count { - let decimal_stringified_input: Vec = current_public_input - .iter() - .map(|x| BigInt::from_str_radix(x, 16).unwrap().to_str_radix(10)) - .collect(); + let witness_0 = compute_witness::( + current_public_input.clone(), + private_inputs[0].clone(), + witness_generator_file.clone(), + &witness_generator_output, + ); - let input = CircomInput { - step_in: decimal_stringified_input.clone(), - extra: private_inputs[i].clone(), - }; + let circuit_0 = CircomCircuit { + r1cs: r1cs.clone(), + witness: Some(witness_0), + }; + let circuit_secondary = TrivialTestCircuit::default(); + let z0_secondary = vec![G2::Scalar::ZERO]; - let input_json = serde_json::to_string(&input).unwrap(); + let mut recursive_snark = RecursiveSNARK::, C2>::new( + &pp, + &circuit_0, + &circuit_secondary, + start_public_input.clone(), + z0_secondary.clone(), + ); - let is_wasm = match &witness_generator_file { - FileLocation::PathBuf(path) => path.extension().unwrap_or_default() == "wasm", - FileLocation::URL(_) => true, - }; + for i in 0..iteration_count { + let witness = compute_witness::( + current_public_input.clone(), + private_inputs[i].clone(), + witness_generator_file.clone(), + &witness_generator_output, + ); - let witness = if is_wasm { - generate_witness_from_wasm::<::Scalar>( - &witness_generator_file, - &input_json, - &witness_generator_output, - ) - } else { - let witness_generator_file = match &witness_generator_file { - FileLocation::PathBuf(path) => path, - FileLocation::URL(_) => panic!("unreachable"), - }; - generate_witness_from_bin::<::Scalar>( - &witness_generator_file, - &input_json, - &witness_generator_output, - ) - }; let circuit = CircomCircuit { r1cs: r1cs.clone(), witness: Some(witness), @@ -129,33 +216,36 @@ pub fn create_recursive_circuit( .map(|&x| format!("{:?}", x).strip_prefix("0x").unwrap().to_string()) .collect(); - let res = RecursiveSNARK::prove_step( + let res = recursive_snark.prove_step( &pp, - recursive_snark, - circuit.clone(), - circuit_secondary.clone(), + &circuit, + &circuit_secondary, start_public_input.clone(), z0_secondary.clone(), ); assert!(res.is_ok()); - recursive_snark = Some(res.unwrap()); } fs::remove_file(witness_generator_output)?; - let recursive_snark = recursive_snark.unwrap(); Ok(recursive_snark) } #[cfg(target_family = "wasm")] -pub async fn create_recursive_circuit( +pub async fn create_recursive_circuit( witness_generator_file: FileLocation, - r1cs: R1CS, + r1cs: R1CS>, private_inputs: Vec>, - start_public_input: Vec, - pp: &PublicParams, -) -> Result, std::io::Error> { + start_public_input: Vec>, + pp: &PublicParams, C2>, +) -> Result, C2>, std::io::Error> +where + G1: Group::Scalar>, + G2: Group::Scalar>, +{ + let root = current_dir().unwrap(); + let witness_generator_output = root.join("circom_witness.wtns"); + let iteration_count = private_inputs.len(); - let mut circuit_iterations = Vec::with_capacity(iteration_count); let start_public_input_hex = start_public_input .iter() @@ -163,76 +253,59 @@ pub async fn create_recursive_circuit( .collect::>(); let mut current_public_input = start_public_input_hex.clone(); - for i in 0..iteration_count { - let decimal_stringified_input: Vec = current_public_input - .iter() - .map(|x| BigInt::from_str_radix(x, 16).unwrap().to_str_radix(10)) - .collect(); - - let input = CircomInput { - step_in: decimal_stringified_input.clone(), - extra: private_inputs[i].clone(), - }; + let witness_0 = compute_witness::( + current_public_input.clone(), + private_inputs[0].clone(), + witness_generator_file.clone(), + &witness_generator_output, + ) + .await; + + let circuit_0 = CircomCircuit { + r1cs: r1cs.clone(), + witness: Some(witness_0), + }; + let circuit_secondary = TrivialTestCircuit::default(); + let z0_secondary = vec![G2::Scalar::ZERO]; - let input_json = serde_json::to_string(&input).unwrap(); + let mut recursive_snark = RecursiveSNARK::, C2>::new( + &pp, + &circuit_0, + &circuit_secondary, + start_public_input.clone(), + z0_secondary.clone(), + ); - let is_wasm = match &witness_generator_file { - FileLocation::PathBuf(path) => path.extension().unwrap_or_default() == "wasm", - FileLocation::URL(_) => true, - }; + for i in 0..iteration_count { + let witness = compute_witness::( + current_public_input.clone(), + private_inputs[i].clone(), + witness_generator_file.clone(), + &witness_generator_output, + ) + .await; - let witness = if is_wasm { - generate_witness_from_wasm::<::Scalar>( - &witness_generator_file, - &input_json, - Path::new(""), - ) - .await - } else { - let witness_generator_file = match &witness_generator_file { - FileLocation::PathBuf(path) => path, - FileLocation::URL(_) => panic!("unreachable"), - }; - generate_witness_from_bin::<::Scalar>( - &witness_generator_file, - &input_json, - Path::new(""), - ) - }; let circuit = CircomCircuit { r1cs: r1cs.clone(), witness: Some(witness), }; - let current_public_output = circuit.get_public_outputs(); - circuit_iterations.push(circuit); + let current_public_output = circuit.get_public_outputs(); current_public_input = current_public_output .iter() .map(|&x| format!("{:?}", x).strip_prefix("0x").unwrap().to_string()) .collect(); - } - let circuit_secondary = TrivialTestCircuit::default(); - - let mut recursive_snark: Option> = None; - - let z0_secondary = vec![::Scalar::zero()]; - - for i in 0..iteration_count { - let res = RecursiveSNARK::prove_step( + let res = recursive_snark.prove_step( &pp, - recursive_snark, - circuit_iterations[i].clone(), - circuit_secondary.clone(), + &circuit, + &circuit_secondary, start_public_input.clone(), z0_secondary.clone(), ); - assert!(res.is_ok()); - recursive_snark = Some(res.unwrap()); } - - let recursive_snark = recursive_snark.unwrap(); + fs::remove_file(witness_generator_output)?; Ok(recursive_snark) }