├── .gitignore ├── crates ├── curve │ ├── src │ │ ├── groth16 │ │ │ ├── mod.rs │ │ │ └── verify.rs │ │ ├── curve.rs │ │ ├── tests │ │ │ ├── curve │ │ │ │ ├── mod.rs │ │ │ │ ├── bn254.rs │ │ │ │ ├── bls12_377.rs │ │ │ │ ├── bls12_381.rs │ │ │ │ ├── bw6_761.rs │ │ │ │ └── cp6_782.rs │ │ │ ├── mod.rs │ │ │ └── mimc.rs │ │ ├── error.rs │ │ ├── ops.rs │ │ ├── lib.rs │ │ └── derive.rs │ └── Cargo.toml ├── merkle-tree │ ├── src │ │ ├── lib.rs │ │ ├── mimc.rs │ │ └── merkle_tree.rs │ └── Cargo.toml └── eddsa │ ├── src │ ├── lib.rs │ ├── w_naf.rs │ ├── jubjub.rs │ ├── verifier.rs │ └── etec.rs │ └── Cargo.toml ├── .github ├── dependabot.yml └── workflows │ └── build.yml ├── tests ├── src │ ├── lib.rs │ └── arkworks │ │ ├── ops.rs │ │ ├── mod.rs │ │ ├── verify.rs │ │ └── bench.rs └── Cargo.toml ├── Cargo.toml ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | gh-pages 3 | .idea 4 | Cargo.lock 5 | -------------------------------------------------------------------------------- /crates/curve/src/groth16/mod.rs: -------------------------------------------------------------------------------- 1 | mod verify; 2 | 3 | pub use verify::*; 4 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "cargo" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | -------------------------------------------------------------------------------- /crates/merkle-tree/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | 3 | #[macro_use] 4 | extern crate alloc; 5 | 6 | #[allow(dead_code)] 7 | mod merkle_tree; 8 | mod mimc; 9 | 10 | pub use self::mimc::*; 11 | -------------------------------------------------------------------------------- /crates/curve/src/curve.rs: -------------------------------------------------------------------------------- 1 | //! Re-export curves 2 | pub use ark_bls12_377::Bls12_377; 3 | pub use ark_bls12_381::Bls12_381; 4 | pub use ark_bn254::Bn254; 5 | pub use ark_bw6_761::BW6_761; 6 | pub use ark_cp6_782::CP6_782; 7 | -------------------------------------------------------------------------------- /crates/curve/src/tests/curve/mod.rs: -------------------------------------------------------------------------------- 1 | //! Tests as exports 2 | 3 | mod bls12_377; 4 | mod bls12_381; 5 | mod bn254; 6 | mod bw6_761; 7 | mod cp6_782; 8 | 9 | pub use self::{bls12_377::*, bls12_381::*, bn254::*, bw6_761::*, cp6_782::*}; 10 | -------------------------------------------------------------------------------- /tests/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Tests 2 | #![cfg(test)] 3 | #![allow(unused_doc_comments)] 4 | #![allow(unused_imports)] 5 | #![allow(unused_variables)] 6 | #![allow(unused_must_use)] 7 | #![allow(non_snake_case)] 8 | #![allow(dead_code)] 9 | mod arkworks; 10 | -------------------------------------------------------------------------------- /crates/eddsa/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | 3 | extern crate alloc; 4 | 5 | mod etec; 6 | mod jubjub; 7 | mod verifier; 8 | mod w_naf; 9 | 10 | pub use self::etec::*; 11 | pub use self::jubjub::*; 12 | pub use self::verifier::*; 13 | pub use self::w_naf::*; 14 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "crates/curve", 4 | "crates/merkle-tree", 5 | "crates/eddsa", 6 | "tests", 7 | ] 8 | 9 | [profile.test] 10 | opt-level = 3 11 | lto = "thin" 12 | incremental = true 13 | debug-assertions = true 14 | debug = true -------------------------------------------------------------------------------- /crates/eddsa/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "eddsa" 3 | version = "0.1.0" 4 | authors = ["Patract "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | once_cell = "1.7" 9 | tiny-keccak = { version = "2.0", features = ["fips202"] } 10 | 11 | zkp-u256 = { git = "https://github.com/patractlabs/OpenZKP", branch = "master", default-features = false } 12 | -------------------------------------------------------------------------------- /crates/merkle-tree/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "merkle-tree" 3 | version = "0.1.0" 4 | authors = ["Patract "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | num-traits = { version = "0.2", default-features = false } 9 | once_cell = "1.7" 10 | tiny-keccak = { version = "2.0", features = ["fips202"] } 11 | 12 | zkp-u256 = { git = "https://github.com/patractlabs/OpenZKP", branch = "master" } 13 | -------------------------------------------------------------------------------- /tests/src/arkworks/ops.rs: -------------------------------------------------------------------------------- 1 | use super::all_curve_three_operations_test; 2 | use arkworks::curve::{Bls12_377, Bls12_381, Bn254, BW6_761, CP6_782}; 3 | 4 | #[test] 5 | fn test_bls12_381() { 6 | all_curve_three_operations_test::(); 7 | } 8 | 9 | #[test] 10 | fn test_bls12_377() { 11 | all_curve_three_operations_test::(); 12 | } 13 | 14 | #[test] 15 | fn test_bn254() { 16 | all_curve_three_operations_test::(); 17 | } 18 | 19 | #[test] 20 | fn test_bw6_761() { 21 | all_curve_three_operations_test::(); 22 | } 23 | 24 | #[test] 25 | fn test_cp6_782() { 26 | all_curve_three_operations_test::(); 27 | } 28 | -------------------------------------------------------------------------------- /crates/eddsa/src/w_naf.rs: -------------------------------------------------------------------------------- 1 | use zkp_u256::U256; 2 | 3 | pub fn w_naf_sequence(mut value: U256, width: usize, result: [U256; 8]) -> U256 { 4 | let a = U256::from(1 << width); 5 | let b = a.clone() >> 1; 6 | let mut k_i = U256::from(0); 7 | 8 | let mut res = &result[0] + U256::from_hex_str("0xff"); 9 | 10 | while value > U256::from(0) { 11 | if &value % U256::from(2) > U256::from(0) { 12 | k_i = &value % &a; 13 | k_i = &k_i 14 | - &a * { 15 | if k_i > b { 16 | 0 17 | } else { 18 | 1 19 | } 20 | }; 21 | value = &value - &k_i; 22 | } 23 | res = &b + &k_i; 24 | value /= U256::from(2); 25 | res = &res - U256::from(1); 26 | } 27 | res - &result[0] 28 | } 29 | -------------------------------------------------------------------------------- /crates/eddsa/src/jubjub.rs: -------------------------------------------------------------------------------- 1 | use once_cell::sync::Lazy; 2 | use zkp_u256::{One, Zero, U256}; 3 | 4 | use super::*; 5 | 6 | pub(crate) static JUBJUB_A: u64 = 168700; 7 | pub(crate) static JUBJUB_D: u64 = 168696; 8 | 9 | // static COFACTOR:u64 = 8; 10 | 11 | pub(crate) static Q: Lazy = Lazy::new(|| { 12 | U256::from_decimal_str( 13 | "21888242871839275222246405745257275088548364400416034343698204186575808495617", 14 | ) 15 | .unwrap() 16 | }); 17 | // static L:Lazy = Lazy::new(|| 18 | // U256::from_decimal_str("21888242871839275222246405745257275088548364400416034343698204186575808495617").unwrap() 19 | // ); 20 | 21 | // fn w_naf5(x:U256,y:U256,w:[[U256;4];32]){ 22 | // point_to_etec(x,y,Q,w[17]) 23 | // } 24 | 25 | pub fn scalar_mult(x: U256, y: U256, mut value: U256) -> Option<(U256, U256)> { 26 | let mut p = point_to_etec(x, y, Q.clone()); 27 | 28 | let mut a = [U256::zero(), U256::one(), U256::zero(), U256::one()]; 29 | while !value.is_zero() { 30 | if !(&value & U256::one()).is_zero() { 31 | a = etec_add(&a, &p, &Q, &JUBJUB_A.into(), &JUBJUB_D.into()); 32 | } 33 | p = etec_double(&p, &Q, &JUBJUB_A.into()); 34 | value /= U256::from(2); 35 | } 36 | etec_to_point(a, Q.clone()) 37 | } 38 | -------------------------------------------------------------------------------- /tests/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tests" 3 | version = "0.1.0" 4 | authors = ["Patract "] 5 | edition = "2018" 6 | 7 | [dev-dependencies] 8 | hex = { version = "0.4.3", default-features = false, features = ["alloc"] } 9 | num-bigint = "0.4" 10 | num-traits = "0.2" 11 | rand = { version = "0.8", default-features = false } 12 | 13 | # Parity 14 | parity-scale-codec = { version = "2.1", default-features = false, features = [ "derive" ] } 15 | 16 | ## Arkworks 17 | ark-std = { version = "0.3", default-features = false } 18 | ark-bls12-377 = { version = "0.3", default-features = false, features = ["curve"] } 19 | ark-bls12-381 = { version = "0.3", default-features = false, features = ["curve"] } 20 | ark-bn254 = { version = "0.3", default-features = false, features = ["curve"] } 21 | ark-bw6-761 = { version = "0.3", default-features = false } 22 | ark-cp6-782 = { version = "0.3", default-features = false } 23 | ark-ff = { version = "0.3", default-features = false } 24 | ark-ec = { version = "0.3", default-features = false } 25 | ark-serialize = { version = "0.3", default-features = false } 26 | ark-relations = { version = "0.3", default-features = false } 27 | ark-groth16 = { version = "0.3", default-features = false } 28 | 29 | # zkMega 30 | arkworks = { package = "zkmega-arkworks", path = "../crates/curve" } 31 | -------------------------------------------------------------------------------- /crates/curve/src/tests/mod.rs: -------------------------------------------------------------------------------- 1 | #![cfg(any(test, feature = "tests"))] 2 | mod curve; 3 | mod mimc; 4 | 5 | pub fn add(curve_id: i32) { 6 | match curve_id { 7 | 0x2a => curve::bls12_377_add(), 8 | 0x2b => curve::bls12_381_add(), 9 | 0x2c => curve::bn254_add(), 10 | 0x2d => curve::bw6_761_add(), 11 | _ => {} 12 | } 13 | } 14 | 15 | pub fn mul(curve_id: i32) { 16 | match curve_id { 17 | 0x2a => curve::bls12_377_mul(), 18 | 0x2b => curve::bls12_381_mul(), 19 | 0x2c => curve::bn254_mul(), 20 | 0x2d => curve::bw6_761_mul(), 21 | _ => {} 22 | } 23 | } 24 | 25 | pub fn pairing(curve_id: i32) { 26 | match curve_id { 27 | 0x2a => curve::bls12_377_pairing(), 28 | 0x2b => curve::bls12_381_pairing(), 29 | 0x2c => curve::bn254_pairing(), 30 | 0x2d => curve::bw6_761_pairing(), 31 | _ => {} 32 | } 33 | } 34 | 35 | pub fn pairing_six(curve_id: i32) { 36 | match curve_id { 37 | 0x2a => curve::bls12_377_pairing_six(), 38 | 0x2b => curve::bls12_381_pairing_six(), 39 | 0x2c => curve::bn254_pairing_six(), 40 | 0x2d => curve::bw6_761_pairing_six(), 41 | _ => {} 42 | } 43 | } 44 | 45 | pub fn verify(curve_id: i32) { 46 | match curve_id { 47 | 0x2a => curve::bls12_377_verify(), 48 | 0x2b => curve::bls12_381_verify(), 49 | 0x2c => curve::bn254_verify(), 50 | 0x2d => curve::bw6_761_verify(), 51 | _ => {} 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /crates/curve/src/error.rs: -------------------------------------------------------------------------------- 1 | //! Curve Result 2 | 3 | use ark_serialize::SerializationError; 4 | use ark_std::{fmt, string::String, vec::Vec}; 5 | 6 | use parity_scale_codec::{Decode, Encode}; 7 | 8 | /// Curve Result 9 | pub type Result = core::result::Result; 10 | 11 | /// Curve Error 12 | #[derive(Debug, Encode, Decode)] 13 | pub enum Error { 14 | InvalidFunctionId, 15 | SerializeDataFailed, 16 | ScaleCodecError, 17 | VerifyParcelFailed, 18 | Custom(Vec), 19 | } 20 | 21 | impl From for Error { 22 | fn from(e: SerializationError) -> Self { 23 | Error::SerializeDataFailed 24 | } 25 | } 26 | 27 | impl From for Error { 28 | fn from(e: parity_scale_codec::Error) -> Self { 29 | Error::ScaleCodecError 30 | } 31 | } 32 | 33 | impl From for Error { 34 | fn from(e: String) -> Self { 35 | Error::Custom(e.as_bytes().to_vec()) 36 | } 37 | } 38 | 39 | impl fmt::Display for Error { 40 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 41 | match self { 42 | Self::InvalidFunctionId => f.write_str("invalid function id"), 43 | Self::SerializeDataFailed => f.write_str("serialize data failed"), 44 | Self::ScaleCodecError => f.write_str("scale codec error"), 45 | Self::VerifyParcelFailed => f.write_str("verify parcel failed"), 46 | Self::Custom(msg) => write!(f, "{}", String::from_utf8_lossy(msg)), 47 | } 48 | } 49 | } 50 | 51 | impl Error { 52 | /// DEBUG string format 53 | pub fn debug(&self) -> String { 54 | format!("{:?}", self) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /crates/curve/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "zkmega-arkworks" 3 | version = "0.1.0" 4 | authors = ["Patract "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | hex = { version = "0.4.3", default-features = false, features = ["alloc"] } 9 | num-bigint = { version = "0.4", default-features = false } 10 | rand = { version = "0.8", default-features = false } 11 | 12 | ## Parity 13 | parity-scale-codec = { version = "2.1", default-features = false, features = ["derive"] } 14 | 15 | ## Arkworks 16 | # https://github.com/arkworks-rs/utils 17 | ark-std = { version = "0.3", default-features = false } 18 | # https://github.com/arkworks-rs/curves 19 | ark-bls12-377 = { version = "0.3", default-features = false, features = ["curve"] } 20 | ark-bls12-381 = { version = "0.3", default-features = false, features = ["curve"] } 21 | ark-bn254 = { version = "0.3", default-features = false, features = ["curve"] } 22 | ark-bw6-761 = { version = "0.3", default-features = false } 23 | ark-cp6-782 = { version = "0.3", default-features = false } 24 | # https://github.com/arkworks-rs/algebra 25 | ark-ec = { version = "0.3", default-features = false } 26 | ark-ff = { version = "0.3", default-features = false } 27 | ark-serialize = { version = "0.3", default-features = false } 28 | # https://github.com/arkworks-rs/groth16 29 | ark-groth16 = { version = "0.3", default-features = false, optional = true } 30 | # https://github.com/arkworks-rs/snark 31 | ark-relations = { version = "0.3", default-features = false, optional = true } 32 | 33 | ## Ink! 34 | #ink_env = { git = "https://github.com/paritytech/ink", default-features = false, optional = true } 35 | ink_env = { version = "3.0.0-rc3", default-features = false, optional = true } 36 | 37 | [dev-dependencies] 38 | ark-relations = { version = "0.3", default-features = false } 39 | ark-groth16 = { version = "0.3", default-features = false } 40 | 41 | [features] 42 | default = [] 43 | tests = ["ark-relations", "ark-groth16"] 44 | ink_std = ["ink_env/std"] 45 | ink = ["ink_env"] 46 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | 8 | jobs: 9 | clippy: 10 | name: Format & Clippy Check 11 | strategy: 12 | matrix: 13 | platform: [ubuntu-latest] 14 | toolchain: [stable] 15 | runs-on: ${{ matrix.platform }} 16 | 17 | steps: 18 | - name: Checkout Sources 19 | uses: actions/checkout@v2 20 | 21 | - name: Install Rust Toolchain 22 | uses: actions-rs/toolchain@v1 23 | with: 24 | profile: minimal 25 | toolchain: ${{ matrix.toolchain }} 26 | override: true 27 | components: rustfmt, clippy 28 | 29 | - name: Check Code Format 30 | uses: actions-rs/cargo@v1 31 | with: 32 | command: fmt 33 | args: --all -- --check 34 | 35 | - name: Clippy Check 36 | uses: actions-rs/cargo@v1 37 | with: 38 | command: clippy 39 | args: -- -D warnings 40 | 41 | build-no-std: 42 | name: Build no_std 43 | strategy: 44 | matrix: 45 | platform: [ubuntu-latest] 46 | toolchain: [stable] 47 | runs-on: ${{ matrix.platform }} 48 | 49 | if: "! contains(toJSON(github.event.commits.head_commit.message), 'ci(skip)')" 50 | steps: 51 | - name: Checkout Sources 52 | uses: actions/checkout@v2 53 | 54 | - name: Install Rust Toolchain 55 | uses: actions-rs/toolchain@v1 56 | with: 57 | profile: minimal 58 | toolchain: ${{ matrix.toolchain }} 59 | override: true 60 | target: thumbv6m-none-eabi 61 | 62 | - name: Build 63 | uses: actions-rs/cargo@v1 64 | with: 65 | command: build 66 | args: -p zkmega-arkworks --no-default-features --target thumbv6m-none-eabi 67 | 68 | build-std: 69 | name: Build & Test 70 | strategy: 71 | matrix: 72 | platform: [ubuntu-latest] 73 | toolchain: [stable] 74 | runs-on: ${{ matrix.platform }} 75 | 76 | if: "! contains(toJSON(github.event.commits.head_commit.message), 'ci(skip)')" 77 | steps: 78 | - name: Checkout Sources 79 | uses: actions/checkout@v2 80 | 81 | - name: Install Rust Toolchain 82 | uses: actions-rs/toolchain@v1 83 | with: 84 | profile: minimal 85 | toolchain: ${{ matrix.toolchain }} 86 | override: true 87 | 88 | - name: Cache Dependencies & Outputs 89 | uses: actions/cache@v2 90 | with: 91 | path: | 92 | ~/.cargo 93 | target 94 | key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} 95 | 96 | - name: Build 97 | uses: actions-rs/cargo@v1 98 | with: 99 | command: build 100 | args: --all -vv 101 | 102 | - name: Test 103 | uses: actions-rs/cargo@v1 104 | with: 105 | command: test 106 | args: --all -vv 107 | -------------------------------------------------------------------------------- /crates/eddsa/src/verifier.rs: -------------------------------------------------------------------------------- 1 | use alloc::vec::Vec; 2 | 3 | use once_cell::sync::Lazy; 4 | use tiny_keccak::{Hasher, Sha3}; 5 | use zkp_u256::U256; 6 | 7 | use super::*; 8 | 9 | static GENERATE: Lazy> = Lazy::new(|| { 10 | let generator = [ 11 | "17777552123799933955779906779655732241715742912184938656739573121738514868268", 12 | "2626589144620713026669568689430873010625803728049924121243784502389097019475", 13 | ]; 14 | generator 15 | .iter() 16 | .map(|g| U256::from_decimal_str(g).unwrap()) 17 | .collect::>() 18 | }); 19 | 20 | pub fn hash_to_u256(data: &[u8]) -> U256 { 21 | let mut hashed = [0u8; 32]; 22 | let mut sha256 = Sha3::v256(); 23 | sha256.update(data); 24 | sha256.finalize(&mut hashed); 25 | 26 | let hash_u256 = U256::from_bytes_be(&hashed); 27 | // (2<<249) - 1 28 | let mask = U256::from_decimal_str( 29 | "1809251394333065553493296640760748560207343510400633813116524750123642650623", 30 | ) 31 | .unwrap(); 32 | 33 | // hash mod mask. 34 | hash_u256 & mask 35 | } 36 | 37 | pub fn verify(hashed_msg: U256, public_key: [U256; 2], r: [U256; 2], s: U256) -> bool { 38 | let mut input = Vec::with_capacity(32 * 5); 39 | let temp = [&r[0], &r[1], &public_key[0], &public_key[1], &hashed_msg]; 40 | temp.iter() 41 | .for_each(|i| input.extend_from_slice(&i.to_bytes_be())); 42 | 43 | if let Some(lhs) = scalar_mult(GENERATE[0].clone(), GENERATE[1].clone(), s) { 44 | let t = hash_to_u256(&input[..]); 45 | if let Some((pk_x, pk_y)) = scalar_mult(public_key[0].clone(), public_key[1].clone(), t) { 46 | let [r_x, r_y] = r; 47 | let etec_point = etec_add( 48 | &point_to_etec(r_x, r_y, Q.clone()), 49 | &point_to_etec(pk_x, pk_y, Q.clone()), 50 | &*Q, 51 | &JUBJUB_A.into(), 52 | &JUBJUB_D.into(), 53 | ); 54 | if let Some(rhs) = etec_to_point(etec_point, Q.clone()) { 55 | return lhs == rhs; 56 | } 57 | } 58 | } 59 | false 60 | } 61 | 62 | #[test] 63 | fn test_eddsa_verify() { 64 | let message = hash_to_u256(b"mimc"); 65 | let sk = U256::from(12); 66 | let (pk_x, pk_y) = scalar_mult(GENERATE[0].clone(), GENERATE[1].clone(), sk.clone()).unwrap(); 67 | 68 | // According to sk and message, generate a deterministic random number. 69 | let mut deterministic_random_number = Vec::new(); 70 | deterministic_random_number.extend_from_slice(&message.to_bytes_be()); 71 | deterministic_random_number.extend_from_slice(&sk.to_bytes_be()); 72 | let r = hash_to_u256(&deterministic_random_number[..]); 73 | let (r_x, r_y) = scalar_mult(GENERATE[0].clone(), GENERATE[1].clone(), r.clone()).unwrap(); 74 | 75 | let mut input = Vec::with_capacity(32 * 5); 76 | let temp = [&r_x, &r_y, &pk_x, &pk_y, &message]; 77 | temp.iter() 78 | .for_each(|i| input.extend_from_slice(&i.to_bytes_be())); 79 | 80 | let hash = hash_to_u256(&input[..]); 81 | // s = r + sk * hash 82 | let s = (r + sk.mulmod(&hash, &Q)) % &*Q; 83 | 84 | assert!(verify(message, [pk_x, pk_y], [r_x, r_y], s)); 85 | } 86 | -------------------------------------------------------------------------------- /crates/merkle-tree/src/mimc.rs: -------------------------------------------------------------------------------- 1 | use alloc::vec::Vec; 2 | 3 | use once_cell::sync::Lazy; 4 | use tiny_keccak::{Hasher, Keccak}; 5 | use zkp_u256::{Zero, U256}; 6 | 7 | // Implements MiMC-p/p(it is possible to use MiMC-2n/n for large block size) 8 | // over the AltBn128 scalar field used by zksnarks 9 | // Paper: https://eprint.iacr.org/2016/492.pdf 10 | // Round constants are generated in sequence from a seed 11 | 12 | // Keccak IV seed. 13 | const SEED: &str = "mimc"; 14 | 15 | static SCALAR_FIELD: Lazy = Lazy::new(|| { 16 | U256::from_decimal_str( 17 | "21888242871839275222246405745257275088548364400416034343698204186575808495617", 18 | ) 19 | .unwrap() 20 | }); 21 | 22 | /// MiMC-p/p with exponent of 7 23 | /// Recommended at least 46 rounds, for a polynomial degree of 2^126 24 | // basic compressed function(based on Even-Mansour mode 25 | fn mimc_pe7(in_x: &U256, in_k: &U256, in_seed: &U256, round_count: u64) -> U256 { 26 | // Initialise round constants, k will be hashed 27 | if round_count < 1 { 28 | return U256::from(0); 29 | } 30 | let mut c = in_seed.clone(); 31 | let mut t: U256; 32 | let mut a: U256; 33 | let mut in_x = in_x.clone(); 34 | 35 | // Further n-2 subsequent rounds include a round constant 36 | for _ in 0..round_count { 37 | let mut keccak = Keccak::v256(); 38 | let mut received = [0u8; 32]; 39 | keccak.update(&c.to_bytes_be()[..]); 40 | keccak.finalize(&mut received); 41 | c = U256::from_bytes_be(&received) % &*SCALAR_FIELD; 42 | 43 | // x = (x + c_i + k)^7 44 | t = &in_x + &c % &*SCALAR_FIELD + in_k % &*SCALAR_FIELD; // t = x + c_i + k 45 | a = t.mulmod(&t, &*SCALAR_FIELD); // t^2 46 | a = a.mulmod(&a, &*SCALAR_FIELD).mulmod(&a, &*SCALAR_FIELD); 47 | in_x = a.mulmod(&t, &*SCALAR_FIELD); // t^7 48 | } 49 | 50 | // Return adds key again as blinding factor 51 | (in_x + in_k) % &*SCALAR_FIELD 52 | } 53 | 54 | // Sponge mode instantiated by MiMC permutation with a fixed key 55 | fn mimc_pe7_mp(in_x: Vec<&U256>, in_k: &U256, in_seed: U256, round_count: u64) -> U256 { 56 | let mut r = in_k.clone(); 57 | for i in in_x { 58 | r = &r + i + mimc_pe7(i, &r, &in_seed, round_count) % &*SCALAR_FIELD; 59 | } 60 | r 61 | } 62 | 63 | pub fn mimc_with_key(msg: Vec<&U256>, in_key: &U256) -> U256 { 64 | let mut keccak = Keccak::v256(); 65 | let mut seed = [0u8; 32]; 66 | keccak.update(SEED.as_ref()); 67 | keccak.finalize(&mut seed); 68 | let in_seed = U256::from_bytes_be(&seed) % &*SCALAR_FIELD; 69 | mimc_pe7_mp(msg, in_key, in_seed, 91) 70 | } 71 | 72 | // padding message to 32 bytes size. 73 | pub fn padding_message(msg: &[u8]) -> Vec { 74 | let quotient = msg.len() / 32; 75 | let mut padding_msg = Vec::new(); 76 | let mut u256_array = [0u8; 32]; 77 | (0..quotient).for_each(|i| { 78 | u256_array.copy_from_slice(&msg[i..i + 32]); 79 | padding_msg.push(U256::from_bytes_be(&u256_array)) 80 | }); 81 | 82 | if msg.len() % 32 != 0 { 83 | let mut padding_array = [0u8; 32]; 84 | padding_array[32 - msg.len()..].copy_from_slice(&msg[quotient * 32..msg.len()]); 85 | let last_u256 = U256::from_bytes_be(&padding_array); 86 | padding_msg.push(last_u256); 87 | }; 88 | padding_msg 89 | } 90 | 91 | pub fn mimc(msg: &[u8]) -> U256 { 92 | let in_k = U256::zero(); 93 | let padding_msg = padding_message(msg); 94 | mimc_with_key(padding_msg.iter().collect(), &in_k) 95 | } 96 | 97 | #[test] 98 | fn test_mimc() { 99 | let message = U256::from_decimal_str("49").unwrap(); 100 | let in_key = U256::zero(); 101 | 102 | assert_eq!(mimc(b"1"), mimc_with_key(vec![&message], &in_key)); 103 | } 104 | -------------------------------------------------------------------------------- /crates/curve/src/ops.rs: -------------------------------------------------------------------------------- 1 | //! Curve Operations 2 | 3 | pub use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve}; 4 | pub use ark_ff::{FromBytes, One, PrimeField, ToBytes, Zero}; 5 | pub use ark_serialize::SerializationError; 6 | pub use ark_std::{ 7 | io::{Error, ErrorKind}, 8 | ops::{MulAssign, Neg}, 9 | str::FromStr, 10 | test_rng, 11 | vec::Vec, 12 | UniformRand, 13 | }; 14 | 15 | /// Arkworks Curve Ops 16 | pub trait CurveBasicOperations: PairingEngine { 17 | // curve basic parameters 18 | const SCALAR_FIELD: &'static str; 19 | const MODULUS: &'static [u8]; 20 | // G1 bytes length 21 | const G1_LEN: usize; 22 | // G2 bytes length 23 | const G2_LEN: usize; 24 | // Scalar bytes length 25 | const SCALAR_LEN: usize; 26 | // Curve ID 27 | const CURVE_ID: u32; 28 | 29 | fn add(input: &[u8]) -> Result, SerializationError> { 30 | // g1 infinity is bool, so two g1s should be + 2 byte. 31 | if input.len() != Self::G1_LEN * 2 { 32 | return Err(Error::new( 33 | ErrorKind::Other, 34 | format!( 35 | "add operation input invalid length, should be {}, \ 36 | input length: {:?}", 37 | Self::G1_LEN * 2, 38 | input.len(), 39 | ), 40 | ) 41 | .into()); 42 | } 43 | let point1 = 44 | <::G1Affine as FromBytes>::read(&input[0..Self::G1_LEN])?; 45 | let point2 = 46 | <::G1Affine as FromBytes>::read(&input[Self::G1_LEN..])?; 47 | 48 | let sum_res = point1 + point2; 49 | let mut output = Vec::new(); 50 | 51 | sum_res.write(&mut output)?; 52 | Ok(output) 53 | } 54 | 55 | fn mul(input: &[u8]) -> Result, SerializationError> { 56 | // g1 infinity is bool, so + 1 byte. 57 | if input.len() != Self::G1_LEN + Self::SCALAR_LEN { 58 | return Err(Error::new( 59 | ErrorKind::Other, 60 | format!( 61 | "scalar_mul operation input invalid length, should be {}, \ 62 | input length: {:?}", 63 | Self::G1_LEN + Self::SCALAR_LEN, 64 | input.len(), 65 | ), 66 | ) 67 | .into()); 68 | } 69 | let point = 70 | <::G1Affine as FromBytes>::read(&input[0..Self::G1_LEN])?; 71 | let scalar = <::Fr as FromBytes>::read(&input[Self::G1_LEN..])?; 72 | 73 | let mul_res = point.into_projective().mul(scalar.into_repr()); 74 | let mut output = Vec::new(); 75 | mul_res.into_affine().write(&mut output)?; 76 | Ok(output) 77 | } 78 | 79 | fn pairings(input: &[u8]) -> Result { 80 | // g1 infinity is bool, so + 1 byte. 81 | let g1_len = Self::G1_LEN; 82 | // ditto, g1 g2 + 2. 83 | let g1_g2_len = Self::G1_LEN + Self::G2_LEN; 84 | if input.len() % g1_g2_len != 0 && !input.is_empty() { 85 | return Err(Error::new( 86 | ErrorKind::Other, 87 | format!( 88 | "pairing operation input invalid length, should be {} \ 89 | input length: {:?}", 90 | g1_g2_len, 91 | input.len(), 92 | ), 93 | ) 94 | .into()); 95 | } 96 | 97 | // Get pairs 98 | let mut pairings = Vec::with_capacity(4); 99 | for i in 0..input.len() / g1_g2_len { 100 | let g1 = <::G1Affine as FromBytes>::read( 101 | &input[i * g1_g2_len..i * g1_g2_len + g1_len], 102 | )?; 103 | let g2 = <::G2Affine as FromBytes>::read( 104 | &input[i * g1_g2_len + g1_len..(i + 1) * g1_g2_len], 105 | )?; 106 | 107 | pairings.push((g1.into(), g2.into())) 108 | } 109 | 110 | // Check if pairing 111 | Ok(::product_of_pairings(&pairings) 112 | == ::Fqk::one()) 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /crates/eddsa/src/etec.rs: -------------------------------------------------------------------------------- 1 | // Extended twisted edwards coordinates 2 | use zkp_u256::{InvMod, One, U256}; 3 | 4 | // Extended twisted edwards coordinates to extended affine coordinates 5 | pub fn etec_to_point(point: [U256; 4], q: U256) -> Option<(U256, U256)> { 6 | point[3] 7 | .inv_mod(&q) 8 | .map(|inv_z| (point[0].mulmod(&inv_z, &q), point[1].mulmod(&inv_z, &q))) 9 | } 10 | 11 | // Project (x,y) point to extended edwards coordinates. 12 | pub fn point_to_etec(x: U256, y: U256, q: U256) -> [U256; 4] { 13 | let mut output = [ 14 | U256::default(), 15 | U256::default(), 16 | U256::default(), 17 | U256::default(), 18 | ]; 19 | output[0] = x.clone(); 20 | output[1] = y.clone(); 21 | output[2] = x.mulmod(&y, &q); 22 | output[3] = U256::one(); 23 | output 24 | } 25 | 26 | pub fn etec_negate(input_point: [U256; 4], q: &U256) -> [U256; 4] { 27 | let mut output_point = [ 28 | U256::default(), 29 | U256::default(), 30 | U256::default(), 31 | U256::default(), 32 | ]; 33 | output_point[0] = q - &input_point[0]; 34 | output_point[1] = input_point[1].clone(); 35 | output_point[2] = q - &input_point[2]; 36 | output_point[3] = input_point[3].clone(); 37 | input_point 38 | } 39 | 40 | // local_a := 0x292FC 41 | // local_q := 0x30644E72E131A029B85045B68181585D2833E84879B9709143E1F593F0000001 42 | #[allow(clippy::many_single_char_names)] 43 | pub fn etec_double(p1: &[U256; 4], local_q: &U256, local_a: &U256) -> [U256; 4] { 44 | // a = x * x 45 | let a = p1[0].mulmod(&p1[0], local_q); 46 | // b = y * y 47 | let b = p1[1].mulmod(&p1[1], local_q); 48 | 49 | // c = z * z * 2 50 | let c = p1[3] 51 | .mulmod(&p1[3], local_q) 52 | .mulmod(&U256::from(2), local_q); 53 | 54 | // d = jubjub_a * a 55 | let d = local_a.mulmod(&a, local_q); 56 | // e = x + y 57 | let mut e = &p1[0] + &p1[1] % local_q; 58 | // e = e^2 - a - b 59 | e = e.mulmod(&e, local_q) + (local_q - &a) % local_q + (local_q - &b) % local_q; 60 | 61 | // g = d + b 62 | let g = &d + &b % local_q; 63 | 64 | // f = g - c 65 | let f = &g + (local_q - &c) % local_q; 66 | 67 | // h = d - b; 68 | let h = &d + (local_q - &b) % local_q; 69 | 70 | // x3 = e * f 71 | // y3 = g * h 72 | // t3 = e * h 73 | // z3 = f * g 74 | let mut p2 = [ 75 | U256::default(), 76 | U256::default(), 77 | U256::default(), 78 | U256::default(), 79 | ]; 80 | let input = [(&e, &f), (&g, &h), (&e, &h), (&f, &g)]; 81 | input 82 | .iter() 83 | .enumerate() 84 | .for_each(|(i, (l, r))| p2[i] = l.mulmod(&r, local_q)); 85 | p2 86 | } 87 | 88 | // x3 = (x1y2 + y1x2) * (z1z2 - dt1t2) 89 | // y3 = (y1y2 - ax1x2) * (z1z2 + dt1t2) 90 | // t3 = (y1y2 - ax1x2) * (x1y2 + y1x2) 91 | // z3 = (z1z2 - dt1t2) * (z1z2 + dt1t2) 92 | #[allow(clippy::many_single_char_names)] 93 | pub fn etec_add( 94 | p1: &[U256; 4], 95 | p2: &[U256; 4], 96 | local_q: &U256, 97 | local_a: &U256, 98 | local_d: &U256, 99 | ) -> [U256; 4] { 100 | // a = x1 * x2 101 | let a = p1[0].mulmod(&p2[0], local_q); 102 | // b = y1 * y2 103 | let b = p1[1].mulmod(&p2[1], local_q); 104 | // c = d * t1 * t2 105 | let c = local_d.mulmod(&p1[2], local_q).mulmod(&p2[2], local_q); 106 | // d = z1 * z2 107 | let d = p1[3].mulmod(&p2[3], local_q); 108 | // e = (x1 + y1) * (x2 + y2) - A - B 109 | let e = ((&p1[0] + &p1[1]) % local_q).mulmod(&((&p2[0] + &p2[1]) % local_q), local_q) 110 | + (((local_q - &a) + (local_q - &b)) % local_q) % local_q; 111 | // f = d - c 112 | let f = &d + (local_q - &c) % local_q; 113 | // g = d + c 114 | let g = &d + c % local_q; 115 | // h = b - a * A 116 | let h = &b + (local_q - local_a.mulmod(&a, local_q)) % local_q; 117 | 118 | // x3 = e * f 119 | // y3 = g * h 120 | // t3 = e * h 121 | // z3 = f * g 122 | let input = [(&e, &f), (&g, &h), (&e, &h), (&f, &g)]; 123 | let mut p3 = [ 124 | U256::default(), 125 | U256::default(), 126 | U256::default(), 127 | U256::default(), 128 | ]; 129 | input 130 | .iter() 131 | .enumerate() 132 | .for_each(|(i, (l, r))| p3[i] = l.mulmod(&r, local_q)); 133 | p3 134 | } 135 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # zkMega 2 | 3 | [zkMega](https://patractlabs.github.io/substrate-contracts-book/zh_CN/zkmega/introduction.html) is a zero-knowledge proof tool set building for the Polkadot ecology. 4 | 5 | * Element group for discussion: https://app.element.io/#/room/#PatractLabsDev:matrix.org 6 | 7 | ## ZK Rollup Introduction 8 | 9 | Compared with the privacy function, the performance improvement brought by Rollup is the 10 | early application direction of zero-knowledge proof. At present, the Layer 2 expansion 11 | plan of the blockchain is to transfer a considerable part of the on-chain workload to 12 | off-chain to complete, and the most watched one is ZK Rollup. The essence of ZK Rollup 13 | is to compress the application on-chain state and store it in a Merkle tree, and move 14 | the state transition funtions to off-chain. At the same time, the correctness of the 15 | off-chain state transition process is guaranteed through the proof of zkSNARK. Compared 16 | with the high cost of directly processing state changes on the chain, the ZK Proof's 17 | on-chain smart contract verification is extremely cost low. At the same time, the 18 | compressed information will also be submitted to the chain together with the proof, 19 | which ensures data availability and obtains the same level of security as Layer 1. 20 | 21 | The Ethereum Layer 2 protocols related to ZK Rollup are: [zkSync][zkSync], [aztec][aztec], 22 | etc. Their contract verification modules share a part of the elliptic curve's basic algorithms. 23 | In 2017, Ethereum integrated three basic cryptographic calculation units of the alt 24 | bn128 curve in the form of pre-compiled contracts, which are [EIP196][EIP196]’s ADD and Scalar_MUL 25 | algorithms, and [EIP197][EIP197]’s Pairing algorithm. On top of this, due to the lack of rapid 26 | upgrade capabilities of Ethereum, the community can only encapsulate some tool libraries 27 | through costly Solidity contracts. On top of these basic contract libraries, many DApps can combine 28 | ZK Rollup technology to achieve some innovations, such as [loopring][loopring], [gitcoin][gitcoin] 29 | and [uniswap][uniswap] etc. However, in the past 3 years, ZK technology has further developed, 30 | such as the more practical [BLS curve][BLS curve], and [PLONK algorithm][PLONK algorithm] etc. 31 | Ethereum has not yet supported it. 32 | 33 | ## Summary of zkMega's plan 34 | - v0.1: Provide on-chain support for elliptic curve alt_bn128 、 bls12_381 、 BLS12-377 and BW6_761 35 | - Integrate addition (ADD), scalar multiplication (MUL) and Pairing functions of the curves in Native layer and Runtime WASM layer. 36 | - Provide these three functions to the upper Runtime Pallets and Contracts to call. 37 | - In the Runtime layer and the Ink! contract layer, provide two zkSNARK Verify upper-layer interfaces ( verification function of groth16, similar to the Verifier library of ethsnarks). 38 | - Start the Metis project and implement EdDSA, MerkleTree, MiMC Hash, etc. contract library on the Ink! contract layer. 39 | 40 | - v0.2: Provide off-chain toolbox support for Ink! contract 41 | - ZoPatract_core integrates arkworks-g16、arkworks-bls12_381、arkworks-bn254 42 | - Implement CLI command for the whole phase of Zksnarks agreement (Zopatract_cli) 43 | - The Ink smart contract template ink_verifier.rs that implements the verifier function is connected to Zopatract_cli's export-verifier. 44 | - Modify the Zopatract JavaScript toolkit 45 | - Test CLI's use of Arkworks groth16 algorithm and curve Bls12_381 and Bn254 curve package 46 | - Test CLI on compile, setup, compute-witness, generate-proof, export-verifier commands in ink! smart contract environments. 47 | - v0.3: Create a sample payment DApp based on Megaclite 48 | 49 | ## Current Development Progress 50 | At present, we have completed the 0.2 version development. 51 | 52 | You Can view: 53 | - 0.1 54 | + [Pairing](https://patractlabs.github.io/zkmega/pairing) 55 | + [Pallet Contracts](https://patractlabs.github.io/zkmega/pallet-contracts) 56 | + [Metis](https://patractlabs.github.io/zkmega/metis) 57 | 58 | Polkadot Treasury report for v0.1: https://polkadot.polkassembly.io/post/221. 59 | 60 | - 0.2 61 | + [ZoPatract](https://github.com/patractlabs/ZoPatract/) 62 | 63 | Report for v0.2 : https://github.com/patractlabs/ZoPatract/blob/master/REPORT.md 64 | 65 | ## LICENSE 66 | 67 | Apache-2.0 68 | 69 | [book]: https://patractlabs.github.io/substrate-contracts-book/zh_CN/zkmega/introduction.html 70 | [zkSync]: https://zksync.io/ 71 | [aztec]: https://aztec.network/ 72 | [EIP196]: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-196.md 73 | [EIP197]: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-197.md 74 | [gitcoin]: https://gitcoin.co/ 75 | [uniswap]: https://uniswap.org/ 76 | [loopring]: https://loopring.org/ 77 | [BLS curve]: https://electriccoin.co/blog/new-snark-curve/ 78 | [PLONK algorithm]: https://eprint.iacr.org/2019/953/20190827:165656 79 | -------------------------------------------------------------------------------- /crates/curve/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused_doc_comments)] 2 | #![allow(unused_imports)] 3 | #![allow(unused_variables)] 4 | #![allow(unused_must_use)] 5 | #![allow(non_snake_case)] 6 | #![cfg_attr(not(features = "std"), no_std)] 7 | 8 | #[macro_use] 9 | extern crate alloc; 10 | 11 | pub mod curve; 12 | mod derive; 13 | pub mod error; 14 | pub mod groth16; 15 | pub mod ops; 16 | pub mod tests; 17 | 18 | pub use ark_serialize::SerializationError; 19 | pub use ark_std::{io::ErrorKind, ops::MulAssign, vec::Vec}; 20 | 21 | pub use self::error::{Error, Result}; 22 | pub use self::ops::CurveBasicOperations; 23 | 24 | /// Call curve function 25 | #[cfg(feature = "ink")] 26 | pub fn call(func_id: u32, input: &[u8]) -> Result> { 27 | use ink_env::chain_extension::{ChainExtensionMethod, FromStatusCode}; 28 | Ok(ChainExtensionMethod::build(func_id) 29 | .input::<&[u8]>() 30 | .output_result::, Error>() 31 | .ignore_error_code() 32 | .call(&input)?) 33 | } 34 | 35 | /// bool to bytes 36 | #[cfg(not(feature = "ink"))] 37 | fn b2b(b: bool) -> Vec { 38 | Vec::from(if b { [0] } else { [1] }) 39 | } 40 | 41 | /// Call curve function 42 | #[cfg(not(feature = "ink"))] 43 | pub fn call(func_id: u32, input: &[u8]) -> Result> { 44 | Ok(match func_id { 45 | // debug 46 | 0x2a => Ok(input.to_vec()), 47 | // add - 0x2a + 0,1,2,3 48 | 0x01000000 => ::add(input), 49 | 0x01000010 => ::add(input), 50 | 0x01000020 => ::add(input), 51 | 0x01000030 => ::add(input), 52 | // mul - 0x3a + 0,1,2,3 53 | 0x01000001 => ::mul(input), 54 | 0x01000011 => ::mul(input), 55 | 0x01000021 => ::mul(input), 56 | 0x01000031 => ::mul(input), 57 | // pairing - 0x4a + 0,1,2,3 58 | 0x01000002 => ::pairings(input).map(b2b), 59 | 0x01000012 => ::pairings(input).map(b2b), 60 | 0x01000022 => ::pairings(input).map(b2b), 61 | 0x01000032 => ::pairings(input).map(b2b), 62 | id => return Err(Error::InvalidFunctionId), 63 | }?) 64 | } 65 | 66 | /// Integrate add 67 | pub fn add(func_id: u32, input: &[u8]) -> Result> { 68 | Ok(match func_id { 69 | 0x00 => call(0x01000000, input)?, 70 | 0x10 => call(0x01000010, input)?, 71 | 0x20 => call(0x01000020, input)?, 72 | 0x30 => call(0x01000030, input)?, 73 | _ => return Err(Error::InvalidFunctionId), 74 | }) 75 | } 76 | 77 | /// Scalar mul 78 | pub fn mul(func_id: u32, input: &[u8]) -> Result> { 79 | Ok(match func_id { 80 | 0x00 => call(0x01000001, input)?, 81 | 0x10 => call(0x01000011, input)?, 82 | 0x20 => call(0x01000021, input)?, 83 | 0x30 => call(0x01000031, input)?, 84 | _ => return Err(Error::InvalidFunctionId), 85 | }) 86 | } 87 | 88 | /// pairing 89 | pub fn pairing(func_id: u32, input: &[u8]) -> Result> { 90 | Ok(match func_id { 91 | 0x00 => call(0x01000002, input)?, 92 | 0x10 => call(0x01000012, input)?, 93 | 0x20 => call(0x01000022, input)?, 94 | 0x30 => call(0x01000032, input)?, 95 | _ => return Err(Error::InvalidFunctionId), 96 | }) 97 | } 98 | 99 | /// Groth16 Verify 100 | pub fn verify( 101 | curve_id: u32, 102 | vk_gamma_abc: Vec>, 103 | vk: Vec, 104 | proof: Vec, 105 | public_inputs: Vec>, 106 | ) -> Result { 107 | match curve_id { 108 | 0x00 => groth16::verify_proof::(vk_gamma_abc, vk, proof, public_inputs), 109 | 0x10 => groth16::verify_proof::(vk_gamma_abc, vk, proof, public_inputs), 110 | 0x20 => groth16::verify_proof::(vk_gamma_abc, vk, proof, public_inputs), 111 | 0x30 => groth16::verify_proof::(vk_gamma_abc, vk, proof, public_inputs), 112 | id => Err(Error::InvalidFunctionId), 113 | } 114 | } 115 | 116 | /// Groth16 Verify Parcel 117 | pub fn verify_parcel(curve_id: u32, parcel: Vec) -> Result { 118 | match curve_id { 119 | 0x00 => groth16::verify::(parcel), 120 | 0x10 => groth16::verify::(parcel), 121 | 0x20 => groth16::verify::(parcel), 122 | 0x30 => groth16::verify::(parcel), 123 | id => Err(Error::InvalidFunctionId), 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /tests/src/arkworks/mod.rs: -------------------------------------------------------------------------------- 1 | mod bench; 2 | mod ops; 3 | mod verify; 4 | 5 | use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve}; 6 | use ark_ff::{FromBytes, One, PrimeField, ToBytes, Zero}; 7 | use ark_serialize::SerializationError; 8 | use ark_std::{ 9 | io::{Error, ErrorKind}, 10 | ops::{MulAssign, Neg}, 11 | str::FromStr, 12 | test_rng, 13 | vec::Vec, 14 | UniformRand, 15 | }; 16 | use arkworks::CurveBasicOperations; 17 | use rand::Rng; 18 | 19 | type G1Affine = ::G1Affine; 20 | type G2Affine = ::G2Affine; 21 | type G1Projective = ::G1Projective; 22 | type G2Projective = ::G2Projective; 23 | type Fr = ::Fr; 24 | 25 | fn all_curve_three_operations_test() 26 | where 27 | T: CurveBasicOperations + PairingEngine, 28 | { 29 | // zero-points additions 30 | { 31 | let mut input = Vec::new(); 32 | as Zero>::zero().write(&mut input); 33 | as Zero>::zero().write(&mut input); 34 | 35 | println!("1 zero: {}", hex::encode(&input)); 36 | let mut expected = Vec::new(); 37 | as Zero>::zero().write(&mut expected); 38 | println!("1 expected: {}", hex::encode(&expected)); 39 | 40 | let res = T::add(&input[..]).unwrap(); 41 | assert_eq!(&expected[..], &res[..]); 42 | println!("test add1 success!"); 43 | } 44 | 45 | // one-points additions 46 | { 47 | let mut input1 = Vec::new(); 48 | as AffineCurve>::prime_subgroup_generator().write(&mut input1); 49 | as AffineCurve>::prime_subgroup_generator().write(&mut input1); 50 | println!("2 input1: {}", hex::encode(&input1)); 51 | 52 | let mut input2 = Vec::new(); 53 | as AffineCurve>::prime_subgroup_generator().write(&mut input2); 54 | as PrimeField>::from_repr(2u64.into()).map(|x| x.write(&mut input2)); 55 | println!("2 input2: {}", hex::encode(&input2)); 56 | 57 | let res1 = T::add(&input1[..]).unwrap(); 58 | let res2 = T::mul(&input2[..]).unwrap(); 59 | println!("2 res1: {}", hex::encode(&res1)); 60 | println!("2 res2: {}", hex::encode(&res2)); 61 | 62 | assert_eq!(res1, res2); 63 | println!("test add2 success!"); 64 | } 65 | 66 | // Prime subgroup generator additions check prime subgroup generator * 2(scalar_mul) 67 | { 68 | let mut input1 = Vec::new(); 69 | as AffineCurve>::prime_subgroup_generator().write(&mut input1); 70 | println!("3 input1: {}", hex::encode(&input1)); 71 | 72 | let mut input2 = Vec::new(); 73 | as AffineCurve>::prime_subgroup_generator().write(&mut input2); 74 | as FromStr>::from_str("2").map(|x| x.write(&mut input2)); 75 | println!("3 input2: {}", hex::encode(&input2)); 76 | 77 | let res1 = T::add(&input1.repeat(2)[..]).expect("Generator add failed"); 78 | let res2 = T::mul(&input2[..]).expect("Generator scalar_mul 2 failed"); 79 | 80 | let mut res3 = Vec::new(); 81 | as AffineCurve>::prime_subgroup_generator() 82 | .into_projective() 83 | .double() 84 | .into_affine() 85 | .write(&mut res3); 86 | 87 | println!("3 res1: {}", hex::encode(&res1)); 88 | println!("3 res2: {}", hex::encode(&res2)); 89 | println!("3 res3: {}", hex::encode(&res3)); 90 | // prime_subgroup_generator + prime_subgroup_generator = prime_subgroup_generator * 2 91 | assert_eq!(res1, res3); 92 | println!("test add3 success!"); 93 | assert_eq!(res2, res3); 94 | println!("test scalar_mul1 success!"); 95 | } 96 | 97 | // test pairings 98 | { 99 | for i in 0..1 { 100 | let mut rng = test_rng(); 101 | let a = as UniformRand>::rand(&mut rng); 102 | let b = as UniformRand>::rand(&mut rng); 103 | let s = as UniformRand>::rand(&mut rng); 104 | 105 | // sa = s * a; 106 | let mut sa = a; 107 | sa.mul_assign(s); 108 | // sb = s * b; 109 | let mut sb = b; 110 | sb.mul_assign(s); 111 | 112 | // write sa sb to input 113 | let mut input = Vec::new(); 114 | sa.into_affine().write(&mut input); 115 | println!("random g1:{:?}", input.len()); 116 | b.into_affine().write(&mut input); 117 | println!("random g1:{:?}", input.len()); 118 | // a get negative. 119 | a.into_affine().neg().write(&mut input); 120 | println!("random g1:{:?}", input.len()); 121 | sb.into_affine().write(&mut input); 122 | println!("random g1:{:?}", input.len()); 123 | println!("4 input: {}", hex::encode(&input)); 124 | 125 | // e(sa, b) = e(sb, a) 126 | assert!(::pairings(&input[..]).expect("pairings failed")); 127 | println!("test pairings{} success!", i + 1); 128 | } 129 | } 130 | 131 | // check pairings 132 | { 133 | let g1 = as AffineCurve>::prime_subgroup_generator(); 134 | let g2 = as AffineCurve>::prime_subgroup_generator(); 135 | 136 | let a1 = g1; 137 | let b1 = g2; 138 | 139 | let a2 = g1 140 | .mul( as PrimeField>::from_repr(1234u64.into()).unwrap()) 141 | .into_affine(); 142 | let b2 = g2 143 | .mul( as PrimeField>::from_repr(1234u64.into()).unwrap()) 144 | .into_affine(); 145 | 146 | // -a3 147 | let a3 = g1.neg(); 148 | let b3 = g2; 149 | 150 | // -a4 151 | let a4 = g1 152 | .mul( as PrimeField>::from_repr(1234u64.into()).unwrap()) 153 | .into_affine() 154 | .neg(); 155 | let b4 = g2 156 | .mul( as PrimeField>::from_repr(1234u64.into()).unwrap()) 157 | .into_affine(); 158 | 159 | // a1 * b1 + a2 * b2 + -a1 * b1 + -a2 * b2 = 0 160 | let expected = ::pairing(a1, b1) 161 | * ::pairing(a2, b2) 162 | * ::pairing(a3, b3) 163 | * ::pairing(a4, b4); 164 | // e(a1*b1) * e(a2*b2) * e(-a1*b1) * e(-a2*b2) = 1 165 | assert_eq!(::Fqk::one(), expected); 166 | 167 | // Encode g1s g2s to input. 168 | let pairings = [(a1, b1), (a2, b2), (a3, b3), (a4, b4)]; 169 | let mut input = Vec::new(); 170 | pairings.iter().for_each(|(g1, g2)| { 171 | g1.write(&mut input); 172 | g2.write(&mut input); 173 | }); 174 | println!("5 input: {}", hex::encode(&input)); 175 | 176 | // check pairings operation:(a1*b1) * e(a2*b2) * e(-a1*b1) * e(-a2*b2) == 1 return true 177 | assert!(::pairings(&input[..]).unwrap()); 178 | println!("test pairings e(a1*b1)*e(a2*b2)*e(-a1*b1)*e(-a2*b2) success!"); 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /crates/curve/src/derive.rs: -------------------------------------------------------------------------------- 1 | //! Impl ops for curves 2 | 3 | use rand::Rng; 4 | 5 | use ark_ec::PairingEngine; 6 | use ark_ff::{Field, One, PrimeField}; 7 | use ark_std::{ops::MulAssign, test_rng, vec::Vec}; 8 | 9 | use crate::CurveBasicOperations; 10 | 11 | /// Paste pairing test 12 | macro_rules! paste_test { 13 | ($curve:ident, $fq:ident) => { 14 | #[test] 15 | fn test_wasm_pairing() { 16 | let mut rng = test_rng(); 17 | let a: G1Projective = rng.gen(); 18 | let b: G2Projective = rng.gen(); 19 | let s: Fr = rng.gen(); 20 | 21 | let mut sa = a; 22 | sa.mul_assign(s); 23 | let mut sb = b; 24 | sb.mul_assign(s); 25 | 26 | let ans1 = <$curve as PairingEngine>::pairing(sa, b); 27 | let ans2 = <$curve as PairingEngine>::pairing(a, sb); 28 | let ans3 = <$curve as PairingEngine>::pairing(a, b).pow(s.into_repr()); 29 | 30 | assert_eq!(ans1, ans2); 31 | assert_eq!(ans2, ans3); 32 | 33 | assert_ne!(ans1, $fq::one()); 34 | assert_ne!(ans2, $fq::one()); 35 | assert_ne!(ans3, $fq::one()); 36 | 37 | assert_eq!(ans1.pow(Fr::characteristic()), $fq::one()); 38 | assert_eq!(ans2.pow(Fr::characteristic()), $fq::one()); 39 | assert_eq!(ans3.pow(Fr::characteristic()), $fq::one()); 40 | } 41 | }; 42 | } 43 | 44 | mod bls12_377 { 45 | use super::*; 46 | use ark_bls12_377::{Bls12_377, Fq12, Fr, G1Projective, G2Projective}; 47 | 48 | impl CurveBasicOperations for Bls12_377 { 49 | const SCALAR_FIELD: &'static str = 50 | "8444461749428370424248824938781546531375899335154063827935233455917409239041"; 51 | // const MODULUS: &'static str = "258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177"; 52 | const MODULUS: &'static [u8] = &[ 53 | 1, 0, 0, 0, 0, 192, 8, 133, 0, 0, 0, 48, 68, 93, 11, 23, 0, 72, 9, 186, 47, 98, 243, 54 | 30, 143, 19, 245, 0, 243, 217, 34, 26, 59, 73, 161, 108, 192, 5, 59, 198, 234, 16, 197, 55 | 23, 70, 58, 174, 1, 56 | ]; 57 | const G1_LEN: usize = 97; 58 | const G2_LEN: usize = 193; 59 | const SCALAR_LEN: usize = 32; 60 | const CURVE_ID: u32 = 0x00; 61 | } 62 | 63 | paste_test!(Bls12_377, Fq12); 64 | } 65 | 66 | mod bls12_381 { 67 | use super::*; 68 | use ark_bls12_381::{Bls12_381, Fq12, Fr, G1Projective, G2Projective}; 69 | 70 | impl CurveBasicOperations for Bls12_381 { 71 | const SCALAR_FIELD: &'static str = 72 | "52435875175126190479447740508185965837690552500527637822603658699938581184513"; 73 | // const MODULUS: &'static str = "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787"; 74 | const MODULUS: &'static [u8] = &[ 75 | 171, 170, 255, 255, 255, 255, 254, 185, 255, 255, 83, 177, 254, 255, 171, 30, 36, 246, 76 | 176, 246, 160, 210, 48, 103, 191, 18, 133, 243, 132, 75, 119, 100, 215, 172, 75, 67, 77 | 182, 167, 27, 75, 154, 230, 127, 57, 234, 17, 1, 26, 78 | ]; 79 | const G1_LEN: usize = 97; 80 | const G2_LEN: usize = 193; 81 | const SCALAR_LEN: usize = 32; 82 | const CURVE_ID: u32 = 0x10; 83 | } 84 | 85 | paste_test!(Bls12_381, Fq12); 86 | } 87 | 88 | mod bn254 { 89 | use super::*; 90 | use ark_bn254::{Bn254, Fq12, Fr, G1Projective, G2Projective}; 91 | 92 | impl CurveBasicOperations for Bn254 { 93 | const SCALAR_FIELD: &'static str = 94 | "21888242871839275222246405745257275088548364400416034343698204186575808495617"; 95 | // const MODULUS: &'static str = "21888242871839275222246405745257275088696311157297823662689037894645226208583"; 96 | const MODULUS: &'static [u8] = &[ 97 | 71, 253, 124, 216, 22, 140, 32, 60, 141, 202, 113, 104, 145, 106, 129, 151, 93, 88, 98 | 129, 129, 182, 69, 80, 184, 41, 160, 49, 225, 114, 78, 100, 48, 99 | ]; 100 | const G1_LEN: usize = 65; 101 | const G2_LEN: usize = 129; 102 | const SCALAR_LEN: usize = 32; 103 | const CURVE_ID: u32 = 0x20; 104 | } 105 | 106 | paste_test!(Bn254, Fq12); 107 | } 108 | 109 | mod bw6_761 { 110 | use super::*; 111 | use ark_bw6_761::{Fq6, Fr, G1Projective, G2Projective, BW6_761}; 112 | 113 | impl CurveBasicOperations for BW6_761 { 114 | const SCALAR_FIELD: &'static str = "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068299"; 115 | // const MODULUS: &'static str = "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068299"; 116 | const MODULUS: &'static [u8] = &[ 117 | 139, 0, 0, 0, 0, 0, 157, 244, 130, 0, 0, 112, 104, 62, 145, 230, 55, 164, 240, 234, 118 | 174, 248, 12, 22, 248, 168, 103, 86, 194, 22, 161, 152, 46, 255, 235, 115, 220, 211, 119 | 220, 113, 144, 253, 249, 18, 237, 200, 137, 134, 4, 35, 180, 37, 255, 186, 206, 3, 25, 120 | 233, 132, 229, 56, 166, 123, 112, 65, 190, 135, 128, 239, 117, 130, 82, 136, 70, 209, 121 | 129, 106, 24, 38, 185, 62, 255, 250, 4, 64, 201, 135, 209, 10, 206, 131, 251, 36, 232, 122 | 34, 1, 123 | ]; 124 | const G1_LEN: usize = 193; 125 | const G2_LEN: usize = 193; 126 | const SCALAR_LEN: usize = 48; 127 | const CURVE_ID: u32 = 0x30; 128 | } 129 | 130 | paste_test!(BW6_761, Fq6); 131 | } 132 | 133 | mod cp6_782 { 134 | use super::*; 135 | use ark_cp6_782::{Fq6, Fr, G1Projective, G2Projective, CP6_782}; 136 | 137 | impl CurveBasicOperations for CP6_782 { 138 | const SCALAR_FIELD: &'static str = "22369874298875696930346742206501054934775599465297184582183496627646774052458024540232479018147881220178054575403841904557897715222633333372134756426301062487682326574958588001132586331462553235407484089304633076250782629492557320825577"; 139 | // const MODULUS: &'static str = "22369874298875696930346742206501054934775599465297184582183496627646774052458024540232479018147881220178054575403841904557897715222633333372134756426301062487682326574958588001132586331462553235407484089304633076250782629492557320825577"; 140 | const MODULUS: &'static [u8] = &[ 141 | 233, 42, 148, 123, 181, 121, 206, 218, 74, 66, 253, 109, 193, 133, 93, 84, 183, 38, 77, 142 | 95, 6, 92, 19, 238, 75, 2, 196, 18, 74, 118, 47, 156, 57, 106, 254, 156, 4, 51, 213, 143 | 26, 32, 19, 156, 199, 119, 251, 163, 82, 146, 87, 124, 97, 200, 150, 53, 171, 139, 215, 144 | 249, 128, 141, 114, 12, 131, 7, 61, 2, 114, 238, 35, 114, 106, 38, 240, 106, 116, 107, 145 | 23, 93, 188, 99, 102, 82, 143, 61, 40, 89, 233, 31, 148, 248, 171, 59, 38, 210, 196, 146 | 72, 56, 147 | ]; 148 | const G1_LEN: usize = 209; 149 | const G2_LEN: usize = 625; 150 | const SCALAR_LEN: usize = 48; 151 | const CURVE_ID: u32 = 0x4; 152 | } 153 | 154 | paste_test!(CP6_782, Fq6); 155 | } 156 | -------------------------------------------------------------------------------- /crates/curve/src/tests/curve/bn254.rs: -------------------------------------------------------------------------------- 1 | use ark_bn254::{Bn254, Fr}; 2 | use ark_ff::{Field, FromBytes, ToBytes}; 3 | use ark_groth16::{verify_proof, PreparedVerifyingKey, Proof, VerifyingKey}; 4 | use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; 5 | use ark_std::{ops::MulAssign, test_rng, vec::Vec, UniformRand}; 6 | 7 | use crate::{tests::mimc::test_mimc_groth_16, CurveBasicOperations}; 8 | 9 | /// BN254 ADD 10 | pub fn bn254_add() { 11 | // two one-points add encode 12 | let input1 = hex::decode( 13 | "01000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000").unwrap(); 14 | 15 | let res1 = Bn254::add(&input1[..]).unwrap(); 16 | 17 | let expected = hex::decode( 18 | "d3cf876dc108c2d3a81c8716a91678d9851518685b04859b021a132ee7440603c4a2185a7abf3effc78f53e349a4a6680a9caeb2965f84e7927c0a0e8c73ed1500").unwrap(); 19 | assert_eq!(res1, expected); 20 | } 21 | 22 | /// BN254 MUL 23 | pub fn bn254_mul() { 24 | let input2 = hex::decode( 25 | "0100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000308f03188746cbabf2f9329f32e6af3c1030c494557ec38d53380f9f5df6d10c").unwrap(); 26 | 27 | let res2 = Bn254::mul(&input2[..]).unwrap(); 28 | 29 | let expected = hex::decode( 30 | "1b67a829f225fa2dfd826ed9dfb6c63fbcb52bba72f01dd9dd84e4b426590e2a7a5f8b601e91a6d52374c844ece03b83757aabb9f093d411393febc5e827372200").unwrap(); 31 | 32 | assert_eq!(res2, expected); 33 | } 34 | 35 | /// BN254 PAIRING 36 | pub fn bn254_pairing() { 37 | // hex![(sa,b),(-sb,a)] 38 | let input = hex::decode( 39 | "cd660ea9af204d56e8536d2fc28c1038e761f1b8e236c0939457b52ab3c3cf11ce10c5d2da7a0cdaf335b66f66107e053c11b5b148b0ea71bac347607fca161400cfc276876571de255ca2cc081c753259f3fac8b28d037e4a17e9505cdcae4322699d38451ba0ef9d69fae88798f6ae96b949ea72a664c835d907bff7d73ced08c211bfd7b8217d9adbcc921ee4a78459e469349f1198db03febd76b79d39741de7671f7c1c8b1cbf4c40415923b9f65822a4001e9d96a8770b791eb74843aa14001b67a829f225fa2dfd826ed9dfb6c63fbcb52bba72f01dd9dd84e4b426590e2acd9df177f8fa79666956a923a5894514e8ddd5c7c5b17ba6f060461b8a262d0e00cfcebd6a33351e4a0d431fc1a7ce2966986a0c993f15ca044a536f7cc73e2518e379338e3f7c8cc191a8d0187244f842338949d93d1ed31a459f76761f5c080a23e18f756349c5075025f1eb76838dacc031c69f46f1298cdbb05f8a436e2d0ee32c918e061ee50b66ca36f12752f96563ad2ad3c4974ca5e1763c4c9dccd10000").unwrap(); 40 | 41 | // e(sa, b) = e(sb, a) 42 | // e(sa, b) * e(-sb, a) = 1 43 | assert!(Bn254::pairings(&input[..]).expect("pairings failed")); 44 | } 45 | 46 | /// BN254 PAIRING SIX 47 | pub fn bn254_pairing_six() { 48 | bn254_pairing(); 49 | 50 | // check pairings 51 | { 52 | // hex![(a1, b1), (a2, b2), (-a1, b1), (-a2, b2)]; 53 | let pairings_encoded = "0100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000edf692d95cbdde46ddda5ef7d422436779445c5e66006a42761e1f12efde0018c212f3aeb785e49712e7a9353349aaf1255dfb31b7bf60723a480d9293938e19aa7dfa6601cce64c7bd3430c69e7d1e38f40cb8d8071ab4aeb6d8cdba55ec8125b9722d1dcdaac55f38eb37033314bbc95330c69ad999eec75f05f58d08906090026052c2b69c54cc8029fcf0f0080f17ff0dad4e843466d144752112ea624960b63cc54e1673e2f2e7a0e0121cb3c7f7a7a2656713fc3fcc68f6f72dae6bdaa1300239480fea1f93725ff9dc1c9f59a62c73ac8dadfe87ca023dd32aa92416a8618d76f11482ffcbcc9a0943306c5cc62390b9ea0c6962420af6ad3e531c9f4802d3faf67b0fe4ee8264a63306f63c3612c1b2a6b26c3f76091167c2e4cbebfa501bd70cfd715766bdf9b512d3f5ef9bb131781b03d0359f7f5c28be067ae88ef2900010000000000000000000000000000000000000000000000000000000000000045fd7cd8168c203c8dca7168916a81975d588181b64550b829a031e1724e643000edf692d95cbdde46ddda5ef7d422436779445c5e66006a42761e1f12efde0018c212f3aeb785e49712e7a9353349aaf1255dfb31b7bf60723a480d9293938e19aa7dfa6601cce64c7bd3430c69e7d1e38f40cb8d8071ab4aeb6d8cdba55ec8125b9722d1dcdaac55f38eb37033314bbc95330c69ad999eec75f05f58d08906090026052c2b69c54cc8029fcf0f0080f17ff0dad4e843466d144752112ea624960be43028f7ae4df10d13bc7047c62d021de3312b10778253f19930bf068c90b91c00239480fea1f93725ff9dc1c9f59a62c73ac8dadfe87ca023dd32aa92416a8618d76f11482ffcbcc9a0943306c5cc62390b9ea0c6962420af6ad3e531c9f4802d3faf67b0fe4ee8264a63306f63c3612c1b2a6b26c3f76091167c2e4cbebfa501bd70cfd715766bdf9b512d3f5ef9bb131781b03d0359f7f5c28be067ae88ef2900"; 54 | 55 | let input = hex::decode(pairings_encoded).unwrap(); 56 | 57 | // check pairings operation:(a1*b1) * e(a2*b2) * e(-a1*b1) * e(-a2*b2) == 1 return true 58 | assert!(Bn254::pairings(&input[..]).unwrap()); 59 | } 60 | } 61 | 62 | pub fn bn254_verify() { 63 | let proof = "cf3bb657065cd0878eabc53790c5fa3680cad24db586bab799e3ae790217c61b0227ad22191396e6ffe7aff14de91d7801e943f836de399b5fd5c8312086440c036648b695ffa27790f2f2a63fcf4c0b130e6b88ac786e3351fc6f13452d18837a922013b86567d6d48ff65baf8cdd0558c52db98f27b6c216df96f8aa1d4d2d"; 64 | let vk = "cc165291944a7b617bad2e6f1560f89f4e7eb42f154333b730e2f2da7828919d94b31d9ebcca3957fff3d94960b0eba2197fabaaa68776e767e8785f63b4541d456d755240d72dae2ee0452c0cd705d7312b9a1d17cff916e87c763d459a5504f00c5d68983d7c029a66ae498a1cc6a2423bf67760bbf922ea7a937a87705e158db79bbff4eb9516d5342ce8cd8d09f68fa094434edceebbb43383fc415d9b23f70bfb6ec84456af219bcd1d682133db3db80b0ae54cf31879e74a0ae547ec0ef92f56757f4a7976c50dc3d538cb1b4ed1736d4e8e8734d5cbf85b2ac8a93d0b020000000000000003c2e806d904d8789f0caf1276fc4897bbf2bbb2e7243df2e4bf941ce61679844d609323ed564943ba7dfd3b362cc85abf7691dd9957c613fc0d282f258f4d17"; 65 | let image = "829d3d572251103bac02b39e397c657c0b1f372bfc4d1b74f6c23de4993b4824"; 66 | 67 | let proof_input = hex::decode(proof).unwrap(); 68 | let vk_input = hex::decode(vk).unwrap(); 69 | let image_input = hex::decode(image).unwrap(); 70 | 71 | let proof = Proof::::deserialize(&*proof_input).expect("Proof deserialize fail:"); 72 | let vk = VerifyingKey::::deserialize(&*vk_input).expect("vk deserialize fail"); 73 | let pvk = PreparedVerifyingKey::::from(vk); 74 | let image = Fr::read(&*image_input).unwrap(); 75 | 76 | assert!(verify_proof(&pvk, &proof, &[image]).unwrap()); 77 | } 78 | 79 | #[test] 80 | pub fn test_bn254_verify() { 81 | bn254_verify(); 82 | } 83 | 84 | #[test] 85 | pub fn test_bn254_groth16() { 86 | test_mimc_groth_16::(); 87 | } 88 | 89 | #[test] 90 | fn test_bn256_additional() { 91 | // zero-points additions 92 | { 93 | let input = hex::decode( 94 | "00000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001").unwrap(); 95 | 96 | let res = Bn254::add(&input[..]).unwrap(); 97 | 98 | let expected = hex::decode( 99 | "0000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001").unwrap(); 100 | 101 | assert_eq!(&expected[..], &res[..]); 102 | } 103 | 104 | // one-points additions 105 | bn254_add(); 106 | } 107 | 108 | #[test] 109 | fn test_bn256_scalar_mul() { 110 | bn254_mul(); 111 | } 112 | 113 | // 30 times pairings 114 | #[test] 115 | fn test_bn256_pairing() { 116 | // test pairings 117 | for i in 0..5 { 118 | bn254_pairing_six(); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /crates/curve/src/tests/mimc.rs: -------------------------------------------------------------------------------- 1 | //! Groth16 MIMC DEMO 2 | 3 | // For randomness (during paramgen and proof generation) 4 | use rand::Rng; 5 | 6 | // For benchmarking 7 | use ark_ff::{Field, FromBytes, ToBytes}; 8 | use ark_std::{test_rng, time::Duration, vec::Vec, UniformRand}; 9 | // We'll use these interfaces to construct our circuit. 10 | use ark_relations::{ 11 | lc, ns, 12 | r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError, Variable}, 13 | }; 14 | // We're going to use the Groth-Maller17 proving system. 15 | use ark_ec::PairingEngine; 16 | use ark_groth16::{ 17 | create_random_proof, generate_random_parameters, prepare_verifying_key, verify_proof, 18 | PreparedVerifyingKey, Proof, VerifyingKey, 19 | }; 20 | use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; 21 | 22 | const MIMC_ROUNDS: usize = 322; 23 | 24 | /// This is an implementation of MiMC, specifically a 25 | /// variant named `LongsightF322p3` for BLS12-381. 26 | /// See http://eprint.iacr.org/2016/492 for more 27 | /// information about this construction. 28 | /// 29 | /// ```text 30 | /// function LongsightF322p3(xL ⦂ Fp, xR ⦂ Fp) { 31 | /// for i from 0 up to 321 { 32 | /// xL, xR := xR + (xL + Ci)^3, xL 33 | /// } 34 | /// return xL 35 | /// } 36 | /// ` 37 | fn mimc(mut xl: F, mut xr: F, constants: &[F]) -> F { 38 | assert_eq!(constants.len(), MIMC_ROUNDS); 39 | 40 | for i in 0..MIMC_ROUNDS { 41 | let mut tmp1 = xl; 42 | tmp1.add_assign(&constants[i]); 43 | let mut tmp2 = tmp1; 44 | tmp2.square_in_place(); 45 | tmp2.mul_assign(&tmp1); 46 | tmp2.add_assign(&xr); 47 | xr = xl; 48 | xl = tmp2; 49 | } 50 | 51 | xl 52 | } 53 | 54 | /// This is our demo circuit for proving knowledge of the 55 | /// preimage of a MiMC hash invocation. 56 | struct MiMCDemo<'a, F: Field> { 57 | xl: Option, 58 | xr: Option, 59 | constants: &'a [F], 60 | } 61 | 62 | /// Our demo circuit implements this `Circuit` trait which 63 | /// is used during paramgen and proving in order to 64 | /// synthesize the constraint system. 65 | impl<'a, F: Field> ConstraintSynthesizer for MiMCDemo<'a, F> { 66 | fn generate_constraints(self, cs: ConstraintSystemRef) -> Result<(), SynthesisError> { 67 | assert_eq!(self.constants.len(), MIMC_ROUNDS); 68 | 69 | // Allocate the first component of the preimage. 70 | let mut xl_value = self.xl; 71 | let mut xl = 72 | cs.new_witness_variable(|| xl_value.ok_or(SynthesisError::AssignmentMissing))?; 73 | 74 | // Allocate the second component of the preimage. 75 | let mut xr_value = self.xr; 76 | let mut xr = 77 | cs.new_witness_variable(|| xr_value.ok_or(SynthesisError::AssignmentMissing))?; 78 | 79 | for i in 0..MIMC_ROUNDS { 80 | // xL, xR := xR + (xL + Ci)^3, xL 81 | let ns = ns!(cs, "round"); 82 | let cs = ns.cs(); 83 | 84 | // tmp = (xL + Ci)^2 85 | let tmp_value = xl_value.map(|mut e| { 86 | e.add_assign(&self.constants[i]); 87 | e.square_in_place(); 88 | e 89 | }); 90 | let tmp = 91 | cs.new_witness_variable(|| tmp_value.ok_or(SynthesisError::AssignmentMissing))?; 92 | 93 | cs.enforce_constraint( 94 | lc!() + xl + (self.constants[i], Variable::One), 95 | lc!() + xl + (self.constants[i], Variable::One), 96 | lc!() + tmp, 97 | )?; 98 | 99 | // new_xL = xR + (xL + Ci)^3 100 | // new_xL = xR + tmp * (xL + Ci) 101 | // new_xL - xR = tmp * (xL + Ci) 102 | let new_xl_value = xl_value.map(|mut e| { 103 | e.add_assign(&self.constants[i]); 104 | e.mul_assign(&tmp_value.unwrap()); 105 | e.add_assign(&xr_value.unwrap()); 106 | e 107 | }); 108 | 109 | let new_xl = if i == (MIMC_ROUNDS - 1) { 110 | // This is the last round, xL is our image and so 111 | // we allocate a public input. 112 | cs.new_input_variable(|| new_xl_value.ok_or(SynthesisError::AssignmentMissing))? 113 | } else { 114 | cs.new_witness_variable(|| new_xl_value.ok_or(SynthesisError::AssignmentMissing))? 115 | }; 116 | 117 | cs.enforce_constraint( 118 | lc!() + tmp, 119 | lc!() + xl + (self.constants[i], Variable::One), 120 | lc!() + new_xl - xr, 121 | )?; 122 | 123 | // xR = xL 124 | xr = xl; 125 | xr_value = xl_value; 126 | 127 | // xL = new_xL 128 | xl = new_xl; 129 | xl_value = new_xl_value; 130 | } 131 | 132 | Ok(()) 133 | } 134 | } 135 | 136 | #[allow(unused)] 137 | pub(crate) fn test_mimc_groth_16() { 138 | // This may not be cryptographically safe, use 139 | // `OsRng` (for example) in production software. 140 | let rng = &mut test_rng(); 141 | 142 | // Generate the MiMC round constants 143 | let constants = (0..MIMC_ROUNDS) 144 | .map(|_| ::rand(rng)) 145 | .collect::>(); 146 | 147 | // println!("Creating parameters..."); 148 | 149 | // Create parameters for our circuit 150 | let params = { 151 | let c = MiMCDemo:: { 152 | xl: None, 153 | xr: None, 154 | constants: &constants, 155 | }; 156 | 157 | generate_random_parameters::(c, rng).unwrap() 158 | }; 159 | 160 | // Prepare the verification key (for proof verification) 161 | let pvk = prepare_verifying_key(¶ms.vk); 162 | 163 | // println!("Creating proofs..."); 164 | 165 | // Let's benchmark stuff! 166 | const SAMPLES: u32 = 1; 167 | // let mut total_proving = Duration::new(0, 0); 168 | // let mut total_verifying = Duration::new(0, 0); 169 | 170 | // Just a place to put the proof data, so we can 171 | // benchmark deserialization. 172 | // let mut proof_vec = vec![]; 173 | 174 | for _ in 0..SAMPLES { 175 | // Generate a random preimage and compute the image 176 | let xl = ::rand(rng); 177 | let xr = ::rand(rng); 178 | let image = mimc(xl, xr, &constants); 179 | 180 | // proof_vec.truncate(0); 181 | 182 | // let start = Instant::now(); 183 | { 184 | // Create an instance of our circuit (with the 185 | // witness) 186 | let c = MiMCDemo { 187 | xl: Some(xl), 188 | xr: Some(xr), 189 | constants: &constants, 190 | }; 191 | 192 | // Create a groth16 proof with our parameters. 193 | let proof = create_random_proof(c, ¶ms, rng).unwrap(); 194 | // total_proving += start.elapsed(); 195 | 196 | let mut proof_vector = Vec::new(); 197 | proof.serialize(&mut proof_vector); 198 | // println!("proof: {:?}", proof_vector.to_hex::()); 199 | let mut pvk_vector = Vec::new(); 200 | pvk.vk.serialize(&mut pvk_vector); 201 | // println!("vk: {:?}", pvk_vector.to_hex::()); 202 | let mut image_vector = Vec::new(); 203 | image.write(&mut image_vector); 204 | // println!("image: {:?}", image_vector.to_hex::()); 205 | 206 | // let start = Instant::now(); 207 | assert!(verify_proof(&pvk, &proof, &[image]).unwrap()); 208 | // total_verifying += start.elapsed(); 209 | 210 | // proof.write(&mut proof_vec).unwrap(); 211 | } 212 | 213 | // let proof = Proof::read(&proof_vec[..]).unwrap(); 214 | // Check the proof 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /tests/src/arkworks/verify.rs: -------------------------------------------------------------------------------- 1 | #![deny( 2 | unused_import_braces, 3 | unused_qualifications, 4 | trivial_casts, 5 | trivial_numeric_casts 6 | )] 7 | #![deny(unused_qualifications, variant_size_differences, stable_features)] 8 | #![deny( 9 | non_shorthand_field_patterns, 10 | unused_attributes, 11 | // unused_imports, 12 | unused_extern_crates 13 | )] 14 | #![deny( 15 | renamed_and_removed_lints, 16 | stable_features, 17 | unused_allocation, 18 | unused_comparisons 19 | )] 20 | #![deny( 21 | unused_must_use, 22 | unused_mut, 23 | unused_unsafe, 24 | private_in_public, 25 | unsafe_code 26 | )] 27 | 28 | // For randomness (during paramgen and proof generation) 29 | use rand::Rng; 30 | 31 | // For benchmarking 32 | // use std::time::{Duration, Instant}; 33 | 34 | // Bring in some tools for using pairing-friendly curves 35 | // We're going to use the BLS12-377 pairing-friendly elliptic curve. 36 | use ark_ff::{biginteger::BigInteger256, Field, ToBytes}; 37 | // use ark_bls12_377::{Bls12_377, Fr}; 38 | // use ark_bls12_381::{Bls12_381, Fr}; 39 | use ark_bn254::{Bn254, Fr}; 40 | // use ark_bw6_761::{BW6_761,Fr}; 41 | // use ark_cp6_782::{CP6_782,Fr}; 42 | 43 | // We'll use these interfaces to construct our circuit. 44 | use ark_ec::PairingEngine; 45 | use ark_relations::{ 46 | lc, ns, 47 | r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError, Variable}, 48 | }; 49 | use arkworks::{groth16::verify_proof, CurveBasicOperations}; 50 | use num_bigint::BigUint; 51 | use num_traits::Num; 52 | 53 | const MIMC_ROUNDS: usize = 322; 54 | 55 | /// This is an implementation of MiMC, specifically a 56 | /// variant named `LongsightF322p3` for BLS12-377. 57 | /// See http://eprint.iacr.org/2016/492 for more 58 | /// information about this construction. 59 | /// 60 | /// `` 61 | /// function LongsightF322p3(xL ⦂ Fp, xR ⦂ Fp) { 62 | /// for i from 0 up to 321 { 63 | /// xL, xR := xR + (xL + Ci)^3, xL 64 | /// } 65 | /// return xL 66 | /// } 67 | /// `` 68 | fn mimc(mut xl: F, mut xr: F, constants: &[F]) -> F { 69 | assert_eq!(constants.len(), MIMC_ROUNDS); 70 | 71 | for i in 0..MIMC_ROUNDS { 72 | let mut tmp1 = xl; 73 | tmp1.add_assign(&constants[i]); 74 | let mut tmp2 = tmp1; 75 | tmp2.square_in_place(); 76 | tmp2.mul_assign(&tmp1); 77 | tmp2.add_assign(&xr); 78 | xr = xl; 79 | xl = tmp2; 80 | } 81 | 82 | xl 83 | } 84 | 85 | /// This is our demo circuit for proving knowledge of the 86 | /// preimage of a MiMC hash invocation. 87 | struct MiMCDemo<'a, F: Field> { 88 | xl: Option, 89 | xr: Option, 90 | constants: &'a [F], 91 | } 92 | 93 | /// Our demo circuit implements this `Circuit` trait which 94 | /// is used during paramgen and proving in order to 95 | /// synthesize the constraint system. 96 | impl<'a, F: Field> ConstraintSynthesizer for MiMCDemo<'a, F> { 97 | fn generate_constraints(self, cs: ConstraintSystemRef) -> Result<(), SynthesisError> { 98 | assert_eq!(self.constants.len(), MIMC_ROUNDS); 99 | 100 | // Allocate the first component of the preimage. 101 | let mut xl_value = self.xl; 102 | let mut xl = 103 | cs.new_witness_variable(|| xl_value.ok_or(SynthesisError::AssignmentMissing))?; 104 | 105 | // Allocate the second component of the preimage. 106 | let mut xr_value = self.xr; 107 | let mut xr = 108 | cs.new_witness_variable(|| xr_value.ok_or(SynthesisError::AssignmentMissing))?; 109 | 110 | for i in 0..MIMC_ROUNDS { 111 | // xL, xR := xR + (xL + Ci)^3, xL 112 | let ns = ns!(cs, "round"); 113 | let cs = ns.cs(); 114 | 115 | // tmp = (xL + Ci)^2 116 | let tmp_value = xl_value.map(|mut e| { 117 | e.add_assign(&self.constants[i]); 118 | e.square_in_place(); 119 | e 120 | }); 121 | let tmp = 122 | cs.new_witness_variable(|| tmp_value.ok_or(SynthesisError::AssignmentMissing))?; 123 | 124 | cs.enforce_constraint( 125 | lc!() + xl + (self.constants[i], Variable::One), 126 | lc!() + xl + (self.constants[i], Variable::One), 127 | lc!() + tmp, 128 | )?; 129 | 130 | // new_xL = xR + (xL + Ci)^3 131 | // new_xL = xR + tmp * (xL + Ci) 132 | // new_xL - xR = tmp * (xL + Ci) 133 | let new_xl_value = xl_value.map(|mut e| { 134 | e.add_assign(&self.constants[i]); 135 | e.mul_assign(&tmp_value.unwrap()); 136 | e.add_assign(&xr_value.unwrap()); 137 | e 138 | }); 139 | 140 | let new_xl = if i == (MIMC_ROUNDS - 1) { 141 | // This is the last round, xL is our image and so 142 | // we allocate a public input. 143 | cs.new_input_variable(|| new_xl_value.ok_or(SynthesisError::AssignmentMissing))? 144 | } else { 145 | cs.new_witness_variable(|| new_xl_value.ok_or(SynthesisError::AssignmentMissing))? 146 | }; 147 | 148 | cs.enforce_constraint( 149 | lc!() + tmp, 150 | lc!() + xl + (self.constants[i], Variable::One), 151 | lc!() + new_xl - xr, 152 | )?; 153 | 154 | // xR = xL 155 | xr = xl; 156 | xr_value = xl_value; 157 | 158 | // xL = new_xL 159 | xl = new_xl; 160 | xl_value = new_xl_value; 161 | } 162 | 163 | Ok(()) 164 | } 165 | } 166 | 167 | #[test] 168 | fn test_mimc_groth16() { 169 | // We're going to use the Groth-Maller17 proving system. 170 | use ark_groth16::{ 171 | create_random_proof, generate_random_parameters, prepare_verifying_key, 172 | verify_proof as raw_verify_proof, 173 | }; 174 | use ark_std::test_rng; 175 | 176 | // This may not be cryptographically safe, use 177 | // `OsRng` (for example) in production software. 178 | let rng = &mut test_rng(); 179 | 180 | // Generate the MiMC round constants 181 | let constants = (0..MIMC_ROUNDS).map(|_| rng.gen()).collect::>(); 182 | 183 | println!("Creating parameters..."); 184 | 185 | // Create parameters for our circuit 186 | let params = { 187 | let c = MiMCDemo:: { 188 | xl: None, 189 | xr: None, 190 | constants: &constants, 191 | }; 192 | 193 | generate_random_parameters::(c, rng).unwrap() 194 | }; 195 | 196 | // Prepare the verification key (for proof verification) 197 | let pvk = prepare_verifying_key(¶ms.vk); 198 | 199 | println!("Creating proofs..."); 200 | 201 | // Let's benchmark stuff! 202 | // const SAMPLES: u32 = 50; 203 | 204 | // Just a place to put the proof data, so we can 205 | // benchmark deserialization. 206 | // let mut proof_vec = vec![]; 207 | 208 | // Generate a random preimage and compute the image 209 | let xl: Fr = rng.gen(); 210 | let xr: Fr = rng.gen(); 211 | let image = mimc(xl, xr, &constants); 212 | 213 | let input_vec = vec![image.clone()]; 214 | // proof_vec.truncate(0); 215 | 216 | { 217 | // Create an instance of our circuit (with the 218 | // witness) 219 | let c = MiMCDemo { 220 | xl: Some(xl), 221 | xr: Some(xr), 222 | constants: &constants, 223 | }; 224 | 225 | // Create a groth16 proof with our parameters. 226 | let proof = create_random_proof(c, ¶ms, rng).unwrap(); 227 | 228 | // proof encode 229 | let mut proof_encode = Vec::new(); 230 | proof.write(&mut proof_encode).unwrap(); 231 | println!("proof:{}", hex::encode(&proof_encode)); 232 | 233 | // vk encode 234 | let mut vk_encode = Vec::new(); 235 | params.vk.gamma_g2.write(&mut vk_encode).unwrap(); 236 | params.vk.delta_g2.write(&mut vk_encode).unwrap(); 237 | params.vk.alpha_g1.write(&mut vk_encode).unwrap(); 238 | params.vk.beta_g2.write(&mut vk_encode).unwrap(); 239 | println!("vk:{}", hex::encode(&vk_encode)); 240 | 241 | // vk_ic encode 242 | let vk_ic = params 243 | .vk 244 | .gamma_abc_g1 245 | .iter() 246 | .map(|ic| { 247 | let mut ic_vector = Vec::new(); 248 | ic.write(&mut ic_vector).unwrap(); 249 | ic_vector 250 | }) 251 | .collect::>>(); 252 | let mut vk_ic_slice = Vec::new(); 253 | vk_ic.iter().for_each(|ic| vk_ic_slice.push(ic.to_vec())); 254 | println!("vk_ic:{}", hex::encode(&vk_ic_slice[0])); 255 | println!("vk_ic2:{}", hex::encode(&vk_ic_slice[1])); 256 | 257 | let mut input = vec![Vec::new(); 1]; 258 | input_vec.iter().enumerate().for_each(|(i, scalar)| { 259 | scalar.write(&mut input[i]).unwrap(); 260 | }); 261 | 262 | let public_input = input.iter().map(|x| x.to_vec()).collect::>(); 263 | println!("public_input:{}", hex::encode(&public_input[0])); 264 | 265 | assert!( 266 | verify_proof::(vk_ic_slice, vk_encode, proof_encode, public_input,) 267 | .expect("verify proof fail ") 268 | ); 269 | } 270 | } 271 | -------------------------------------------------------------------------------- /crates/merkle-tree/src/merkle_tree.rs: -------------------------------------------------------------------------------- 1 | use alloc::vec::Vec; 2 | use core::mem::size_of; 3 | 4 | use once_cell::sync::Lazy; 5 | use tiny_keccak::{Hasher, Keccak}; 6 | use zkp_u256::{Zero, U256}; 7 | 8 | use super::*; 9 | 10 | // ceil(log2(1<<20)) 11 | static TREE_DEPTH: usize = 10; 12 | 13 | // 1<<20 leaves 14 | const MAX_LEAF_COUNT: usize = 1024; 15 | 16 | static FILL_LEVEL_IVS: Lazy> = Lazy::new(|| { 17 | let ivs = [ 18 | "149674538925118052205057075966660054952481571156186698930522557832224430770", 19 | "9670701465464311903249220692483401938888498641874948577387207195814981706974", 20 | "18318710344500308168304415114839554107298291987930233567781901093928276468271", 21 | "6597209388525824933845812104623007130464197923269180086306970975123437805179", 22 | "21720956803147356712695575768577036859892220417043839172295094119877855004262", 23 | "10330261616520855230513677034606076056972336573153777401182178891807369896722", 24 | "17466547730316258748333298168566143799241073466140136663575045164199607937939", 25 | "18881017304615283094648494495339883533502299318365959655029893746755475886610", 26 | "21580915712563378725413940003372103925756594604076607277692074507345076595494", 27 | "12316305934357579015754723412431647910012873427291630993042374701002287130550", 28 | "18905410889238873726515380969411495891004493295170115920825550288019118582494", 29 | "12819107342879320352602391015489840916114959026915005817918724958237245903353", 30 | "8245796392944118634696709403074300923517437202166861682117022548371601758802", 31 | "16953062784314687781686527153155644849196472783922227794465158787843281909585", 32 | "19346880451250915556764413197424554385509847473349107460608536657852472800734", 33 | "14486794857958402714787584825989957493343996287314210390323617462452254101347", 34 | "11127491343750635061768291849689189917973916562037173191089384809465548650641", 35 | "12217916643258751952878742936579902345100885664187835381214622522318889050675", 36 | "722025110834410790007814375535296040832778338853544117497481480537806506496", 37 | "15115624438829798766134408951193645901537753720219896384705782209102859383951", 38 | "11495230981884427516908372448237146604382590904456048258839160861769955046544", 39 | "16867999085723044773810250829569850875786210932876177117428755424200948460050", 40 | "1884116508014449609846749684134533293456072152192763829918284704109129550542", 41 | "14643335163846663204197941112945447472862168442334003800621296569318670799451", 42 | "1933387276732345916104540506251808516402995586485132246682941535467305930334", 43 | "7286414555941977227951257572976885370489143210539802284740420664558593616067", 44 | "16932161189449419608528042274282099409408565503929504242784173714823499212410", 45 | "16562533130736679030886586765487416082772837813468081467237161865787494093536", 46 | "6037428193077828806710267464232314380014232668931818917272972397574634037180", 47 | ]; 48 | ivs.iter() 49 | .map(|iv| U256::from_decimal_str(iv).unwrap()) 50 | .collect::>() 51 | }); 52 | 53 | #[derive(Clone, Debug)] 54 | struct MerkleTree { 55 | cur: usize, 56 | root: U256, 57 | leaves: Vec>, 58 | } 59 | 60 | impl Default for MerkleTree { 61 | fn default() -> Self { 62 | let leaves = (0..TREE_DEPTH + 1) 63 | .rev() 64 | .map(|x| vec![U256::zero(); 2usize.pow(x as u32)]) 65 | .collect::>(); 66 | 67 | let mut mt = MerkleTree { 68 | cur: 0, 69 | root: U256::zero(), 70 | leaves, 71 | }; 72 | mt.init(); 73 | mt 74 | } 75 | } 76 | 77 | impl MerkleTree { 78 | fn init(&mut self) { 79 | for depth in 0..TREE_DEPTH { 80 | self.leaves[depth] 81 | .clone() 82 | .chunks_exact(2) 83 | .enumerate() 84 | .for_each(|(index, chunk)| { 85 | self.leaves[depth][index * 2] = 86 | Self::get_unique_leaf(depth, index * 2, chunk[0].clone()); 87 | self.leaves[depth][index * 2 + 1] = 88 | Self::get_unique_leaf(depth, index * 2 + 1, chunk[1].clone()); 89 | self.leaves[depth + 1][index] = Self::hash_impl( 90 | &self.leaves[depth][index * 2], 91 | &self.leaves[depth][index * 2 + 1], 92 | &FILL_LEVEL_IVS[depth], 93 | ); 94 | }) 95 | } 96 | } 97 | 98 | fn insert(&mut self, message: &[u8]) -> Result<(U256, usize), &'static str> { 99 | let leaf = mimc(message); 100 | if leaf.is_zero() { 101 | return Err("leaf must be non-zero"); 102 | } 103 | 104 | let offset = self.cur; 105 | self.leaves[0][self.cur] = leaf.clone(); 106 | 107 | self.root = self.update(); 108 | self.cur += 1; 109 | 110 | Ok((leaf, offset)) 111 | } 112 | 113 | // Update the leaves of the entire tree, return new tree root. 114 | fn update(&mut self) -> U256 { 115 | let mut current_index = self.cur; 116 | let mut leaf1: U256; 117 | let mut leaf2: U256; 118 | 119 | for depth in 0..TREE_DEPTH { 120 | let next_index = current_index / 2; 121 | if current_index % 2 == 0 { 122 | leaf1 = self.leaves[depth][current_index].clone(); 123 | leaf2 = MerkleTree::get_unique_leaf( 124 | depth, 125 | current_index + 1, 126 | self.leaves[depth][current_index + 1].clone(), 127 | ); 128 | } else { 129 | leaf1 = MerkleTree::get_unique_leaf( 130 | depth, 131 | current_index - 1, 132 | self.leaves[depth][current_index - 1].clone(), 133 | ); 134 | leaf2 = self.leaves[depth][current_index].clone(); 135 | } 136 | self.leaves[depth + 1][next_index] = 137 | MerkleTree::hash_impl(&leaf1, &leaf2, &FILL_LEVEL_IVS[depth]); 138 | current_index = next_index; 139 | } 140 | self.root = self.leaves[TREE_DEPTH][0].clone(); 141 | self.root.clone() 142 | } 143 | 144 | // Return leaf according to depth and index, 145 | fn get_leaf(&self, depth: usize, offset: usize) -> U256 { 146 | MerkleTree::get_unique_leaf(depth, offset, self.leaves[depth][offset].clone()) 147 | } 148 | 149 | // get merkle tree root 150 | fn get_root(&self) -> U256 { 151 | self.root.clone() 152 | } 153 | 154 | // Obtain the merkel proof according to the corresponding leaf of the index 155 | fn get_proof(&self, mut index: usize) -> Vec { 156 | let mut address_bits = vec![false; TREE_DEPTH]; 157 | let mut proof_path = vec![U256::zero(); TREE_DEPTH]; 158 | 159 | for depth in 0..TREE_DEPTH { 160 | address_bits[depth] = index % 2 == 0; 161 | if index % 2 == 0 { 162 | proof_path[depth] = self.get_leaf(depth, index + 1); 163 | } else { 164 | proof_path[depth] = self.get_leaf(depth, index - 1); 165 | } 166 | index /= 2; 167 | } 168 | proof_path 169 | } 170 | 171 | // 172 | fn verify_merkle_proof(&self, leaf: U256, proof: Vec, index: usize) -> bool { 173 | if proof.len() != TREE_DEPTH && index > MAX_LEAF_COUNT { 174 | return false; 175 | } 176 | self.verify_path(leaf, proof, index) == self.get_root() 177 | } 178 | 179 | // Returns calculated merkle root 180 | fn verify_path(&self, leaf: U256, in_path: Vec, mut index: usize) -> U256 { 181 | let mut item = leaf; 182 | for depth in 0..TREE_DEPTH { 183 | if index % 2 == 0 { 184 | item = MerkleTree::hash_impl(&item, &in_path[depth], &FILL_LEVEL_IVS[depth]); 185 | } else { 186 | item = MerkleTree::hash_impl(&in_path[depth], &item, &FILL_LEVEL_IVS[depth]); 187 | } 188 | index /= 2; 189 | } 190 | item 191 | } 192 | 193 | // 194 | fn get_unique_leaf(depth: usize, offset: usize, mut leaf: U256) -> U256 { 195 | if leaf.is_zero() { 196 | // Keccak(depth, offset) 197 | let mut input = [0u8; 32]; 198 | input[0..size_of::()].copy_from_slice(&depth.to_be_bytes()[..]); 199 | input[size_of::()..2 * size_of::()] 200 | .copy_from_slice(&offset.to_be_bytes()[..]); 201 | 202 | let mut keccak = Keccak::v256(); 203 | let mut received = [0u8; 32]; 204 | keccak.update(&input[..]); 205 | keccak.finalize(&mut received); 206 | 207 | leaf = U256::from_bytes_be(&received); 208 | } 209 | leaf 210 | } 211 | 212 | // Use two leaves to generate mimc hash 213 | fn hash_impl(left: &U256, right: &U256, iv: &U256) -> U256 { 214 | let input = vec![left, right]; 215 | mimc_with_key(input, iv) 216 | } 217 | } 218 | 219 | #[test] 220 | fn test_merkle_tree() { 221 | let mut mt = MerkleTree::default(); 222 | let message = b"hello world"; 223 | let (leaf, index) = mt.insert(message).unwrap(); 224 | assert_eq!(mt.update(), mt.get_root()); 225 | 226 | let merkle_proof = mt.get_proof(index); 227 | assert!(mt.verify_merkle_proof(leaf, merkle_proof, index)); 228 | } 229 | -------------------------------------------------------------------------------- /crates/curve/src/tests/curve/bls12_377.rs: -------------------------------------------------------------------------------- 1 | use ark_bls12_377::{Bls12_377, Fr}; 2 | use ark_ff::{Field, FromBytes, ToBytes}; 3 | use ark_groth16::{verify_proof, PreparedVerifyingKey, Proof, VerifyingKey}; 4 | use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; 5 | use ark_std::{ops::MulAssign, test_rng, vec::Vec, UniformRand}; 6 | 7 | use crate::{tests::mimc::test_mimc_groth_16, CurveBasicOperations}; 8 | 9 | /// BLS12_377 ADD 10 | pub fn bls12_377_add() { 11 | // two one-points add encode 12 | let input1 = hex::decode( 13 | "efe91bb26eb1b9ea4e39cdff121548d55ccb37bdc8828218bb419daa2c1e958554ff87bf2562fcc8670a74fede488800a68e9c5555de82fd1a59a934363dfec20523b84fd42a186dd9523eca48b37fbdc4eeaf305d4f671fff2e10c5694a910100efe91bb26eb1b9ea4e39cdff121548d55ccb37bdc8828218bb419daa2c1e958554ff87bf2562fcc8670a74fede488800a68e9c5555de82fd1a59a934363dfec20523b84fd42a186dd9523eca48b37fbdc4eeaf305d4f671fff2e10c5694a910100").unwrap(); 14 | 15 | let res1 = Bls12_377::add(&input1[..]).unwrap(); 16 | 17 | let expected = hex::decode( 18 | "9063416a6ded7a8590dc816765610688551930a2c9970ee97e4b2addf3f7617eed52544b5adb6e05919e93413145ed00edc7d727875edde2a75ced75563fa2d67944c635f1120be8ca61c542aecd99ad37131713186004aee5c87b71b9b0cf0000").unwrap(); 19 | assert_eq!(res1, expected); 20 | } 21 | 22 | /// BLS12_377 MUL 23 | pub fn bls12_377_mul() { 24 | let input2 = hex::decode( 25 | "efe91bb26eb1b9ea4e39cdff121548d55ccb37bdc8828218bb419daa2c1e958554ff87bf2562fcc8670a74fede488800a68e9c5555de82fd1a59a934363dfec20523b84fd42a186dd9523eca48b37fbdc4eeaf305d4f671fff2e10c5694a9101009a649b0d5ed2c8abaea1bddfc107059c7aa9fa82b248d5ffead5bf3157f20212").unwrap(); 26 | 27 | let res2 = Bls12_377::mul(&input2[..]).unwrap(); 28 | 29 | let expected = hex::decode( 30 | "33c670abc1eddeae7b766b48a816c0d6dc6c877df39ffc10f76458821d553f4390997c2d9bcca0f8444f7db19e576f000e2217ade475d721036e32854cc8bb8c6865b614dfc0eabf562b8e3e12be10e1f45d3de4dc33191a994e32135aaa650100").unwrap(); 31 | 32 | assert_eq!(res2, expected); 33 | } 34 | 35 | /// BLS12_377 PAIRING 36 | pub fn bls12_377_pairing() { 37 | // vec![sa,b,-sb,a] 38 | let input = hex::decode( 39 | "3f91af9f54c6c46762fa432ba77fdc7bc170b508b66af45b42bb39b1c77cd513111a2930586b2cb1fd86fdd2034ce800512eb2b6d18c0a2d0e88beca80edce8ffd9e216c15a677a313823bfe97efd8e7cbcde852ceeb77fc78fc6242e8292c010034f4f5f69b22533deac9d117c88d719c189f9a1a82279ba185252018196b74e540414fb37a699046fc643b496411cf002f91afe9bd9b9b0ab98fcf4b6aea16b43d645050c72aac47dfab448adf1a18f37e2c93d68dae425bb9630a796aa07f0143c24ddff137582cfe320e4dcb0e5639bb3eb7ab164bc269e2c14743f48d9a153035353da6abbcbde93ea4eacb994d01c1bf8d711b6ffcc677b0509da0f47de1c131e78022efa63dd03d38b54c490925bbf4bcc063ddac4171057ee4a78b5d000033c670abc1eddeae7b766b48a816c0d6dc6c877df39ffc10f76458821d553f4390997c2d9bcca0f8444f7db19e576f00f3dde8521b4a3163fd91cdaaf7944f8a97e252a550a1085f38e866c2e01b123946eb6388e3d121ac51c29204ec8f480000b5beea6c8d3deecf87c7d73d3a6a2fa78f3472537b26cde5dae5e2b293b4319905ce2618199b265db72cdf83da2e30002eac94d62b172dfd518958607ff1bada47548a37682a906d8e7b474ebf251b1b2ff343e9830bc3a7c6620c34a1114500fa65f92d3cf847fd4d23820a53234fbe1d89584777ae99ed52cc15541bcbcc916191343f14c0a01673411e16fc2b19001040d139da62b80204f0906530b36c072462f6dbfc5a362d8fbcf425c6be60f36c958d6d0894bffec5639b6e20e9ab0000").unwrap(); 40 | 41 | // e(sa, b) = e(sb, a) 42 | // e(sa, b) * e(-sb, a) = 1 43 | assert!(Bls12_377::pairings(&input[..]).expect("pairings failed")); 44 | // println!("test pairings{} success!", i + 1); 45 | } 46 | 47 | /// Pariing Circle 48 | pub fn bls12_377_pairing_six() { 49 | // test pairings 50 | bls12_377_pairing(); 51 | 52 | // check pairings 53 | { 54 | // hex![(a1, b1), (a2, b2), (-a1, b1), (-a2, b2)]; 55 | let pairings_encoded = "efe91bb26eb1b9ea4e39cdff121548d55ccb37bdc8828218bb419daa2c1e958554ff87bf2562fcc8670a74fede488800a68e9c5555de82fd1a59a934363dfec20523b84fd42a186dd9523eca48b37fbdc4eeaf305d4f671fff2e10c5694a9101009651007c8fe4e374025453bb529f88719b6bdb57f501a57e31503e2071f065c5011d84a3a23096c8fe85c771be808401fe6aa16efafe6bb2e66ff7bf8499f85cdec99907ce3e22e7cbce5166ee772753d540b1b1515adc70314000e74060ea00df4dfd09440994f02e7c8c6d8888cff204d232f882c258e4589ab47472ed03deb4efb2cb6b7360d97b6f445d660d6900938feb85d1cda1d90b27525e3fb87942c204e3ce1ab06324f11b593dac11ef61aa701a15a39d549e185583d29f16f80000aafaf0e79aa79ea5f16b5a17763d6c5e2b46fadc470b91c24f3868b9fe80cfeb4611cc935337b357fed7e02ae0073c0137eacc8c8f56bc812783c1ce053eef88382315bd84029d958d3ced6e237b1979e7f66aed4f20292f0948e43e4ade7d00007c1da03901590e708ee46188831e096b478d9aa924bb37827d7ad6711c43ec10c4e93c226235d73358cb351b30214f0137d32b7b86eb47d816778557ae504b58d998457211f9694bd2646a744fb43718d9db8de18fed5eff1edb59bb14c6c6002f0c8568aad2ba7431617bf2e84fb57e05d7c2d42206706e1300062d4c0a49206865bb6d08e37cc7bcc258580bd55f0081584fbeb74ae1e3e1afa480c070f035675216f6fc38fccc9f073a93e63024aaed71a90761ae49054128a583c7c7090000efe91bb26eb1b9ea4e39cdff121548d55ccb37bdc8828218bb419daa2c1e958554ff87bf2562fcc8670a74fede4888005b7163aaaae18587e5a656fb0d200d54fa24516a5b37dbb1b5c0b636aa26a35c765af13b63b6d3a6ebe1b452dcef1c00009651007c8fe4e374025453bb529f88719b6bdb57f501a57e31503e2071f065c5011d84a3a23096c8fe85c771be808401fe6aa16efafe6bb2e66ff7bf8499f85cdec99907ce3e22e7cbce5166ee772753d540b1b1515adc70314000e74060ea00df4dfd09440994f02e7c8c6d8888cff204d232f882c258e4589ab47472ed03deb4efb2cb6b7360d97b6f445d660d6900938feb85d1cda1d90b27525e3fb87942c204e3ce1ab06324f11b593dac11ef61aa701a15a39d549e185583d29f16f80000aafaf0e79aa79ea5f16b5a17763d6c5e2b46fadc470b91c24f3868b9fe80cfeb4611cc935337b357fed7e02ae0073c01ca15337370694c03d97c3e613e1f1c8ec724f4fcaa5f568901d70792cf5e09a15352367f70e51197e1c8e0d8fb5b3001007c1da03901590e708ee46188831e096b478d9aa924bb37827d7ad6711c43ec10c4e93c226235d73358cb351b30214f0137d32b7b86eb47d816778557ae504b58d998457211f9694bd2646a744fb43718d9db8de18fed5eff1edb59bb14c6c6002f0c8568aad2ba7431617bf2e84fb57e05d7c2d42206706e1300062d4c0a49206865bb6d08e37cc7bcc258580bd55f0081584fbeb74ae1e3e1afa480c070f035675216f6fc38fccc9f073a93e63024aaed71a90761ae49054128a583c7c7090000"; 56 | 57 | let input = hex::decode(pairings_encoded).unwrap(); 58 | 59 | // check pairings operation:(a1*b1) * e(a2*b2) * e(-a1*b1) * e(-a2*b2) == 1 return true 60 | assert!(Bls12_377::pairings(&input[..]).unwrap()); 61 | // println!("test pairings e(a1*b1)*e(a2*b2)*e(-a1*b1)*e(-a2*b2) success!"); 62 | } 63 | } 64 | 65 | pub fn bls12_377_verify() { 66 | let proof = "e2342d048b06618cfc80a5fb5301373032d5780ca45e5287e824fd1d3dccfc36d1befe73edaea7378968a003f94e180190f4ad7dc16060ebfbe2bff08077e404e878850682e15f64a5b0f243f53a6d61dc358d41fa6aed615c6296904d71c200c04fe75b3adbecdc3d00df22556a1c949e4b87c81483225f6eaa7560e3035a1c919c4a0d446125dca2e2ef541d58a20026b3bb740a34b4db3a1c689d471b5a7834bb27fd57108bca8cd88d12bb81eae5f8ad807e5de758978ab51d0146017180"; 67 | let vk = "5720823639fe8f3818ade6c24c6d6ed8f78b87369a9fac8a548e01ca001e424ba931033958641fe06677c3f4a1b39f819d629094c47bdf026bbd3424f6e7748b0c3529b495cf24677f309d9f1ed7d3435513224cba204902fd733522b3b855015f395e5b2a7f0fe9e50665d705c48f9b8b20a3f9619f50c1dcddbea7c4a561cdffed750045f875b2d2c569e8d5d0328054f796d78550d14c4ee03cd5915fd8037569696f878312b0093f0149919fc717c0b3f8a2d419fad0edde7e1d55cd2f002c312b660250225a00baf5df511dcce61eb23b28f3980be7fcde0091284670e9064015f452f244e65cad047a20fdd080f70cb4191a256ed9a4d90305f5864993032a0e40433040c259b14c8069d117f3491d75d993271a0a3f13efdd5b18ce006d90eff3b45f8fa10b43a2d4fb80a554304ba5d94ddc19c92b2e1e2f756bd3042c4c0d6e10b6c22c2ea5eb136fb42980020000000000000071c5a779bb19e0aeb6030768f5001017bbd4edb645306ff1591424c501e7aa8b480fc18d8ed404c893d473afa9b82c014d0869345487bb4070110fa318b0f408dcffce12304589878797615d8a72cc00b6a1e3f50cc0e5977063864009072681"; 68 | let image = "a4961fec1c734055a80af91b3fd7405a2cdb741e1867aa7f783ca0959a077110"; 69 | let proof_input = hex::decode(proof).unwrap(); 70 | let vk_input = hex::decode(vk).unwrap(); 71 | let image_input = hex::decode(image).unwrap(); 72 | 73 | let proof = Proof::::deserialize(&*proof_input).expect("Proof deserialize fail:"); 74 | let vk = VerifyingKey::::deserialize(&*vk_input).expect("vk deserialize fail"); 75 | let pvk = PreparedVerifyingKey::::from(vk); 76 | let image = Fr::read(&*image_input).unwrap(); 77 | 78 | assert!(verify_proof(&pvk, &proof, &[image]).unwrap()); 79 | } 80 | 81 | #[test] 82 | fn test_bls12_377_groth16() { 83 | test_mimc_groth_16::(); 84 | } 85 | 86 | #[test] 87 | fn test_bls12_377_verify() { 88 | bls12_377_verify(); 89 | } 90 | 91 | #[test] 92 | fn test_bls12_377_additional() { 93 | // zero-points additions 94 | { 95 | let input = hex::decode( 96 | "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001").unwrap(); 97 | 98 | let res = Bls12_377::add(&input[..]).unwrap(); 99 | 100 | let expected = hex::decode( 101 | "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001").unwrap(); 102 | 103 | assert_eq!(&expected[..], &res[..]); 104 | } 105 | 106 | // one-points additions 107 | bls12_377_add(); 108 | } 109 | 110 | #[test] 111 | fn test_bls12_377_scalar_mul() { 112 | // one-point mul 2 encode 113 | bls12_377_mul(); 114 | } 115 | 116 | // 30 times pairings 117 | #[test] 118 | fn test_bls12_377_pairing() { 119 | for _ in 0..5 { 120 | bls12_377_pairing_six() 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /crates/curve/src/tests/curve/bls12_381.rs: -------------------------------------------------------------------------------- 1 | use ark_bls12_381::{Bls12_381, Fr}; 2 | use ark_ff::{Field, FromBytes, ToBytes}; 3 | use ark_groth16::{verify_proof, PreparedVerifyingKey, Proof, VerifyingKey}; 4 | use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; 5 | use ark_std::{ops::MulAssign, test_rng, vec::Vec, UniformRand}; 6 | 7 | use crate::{tests::mimc::test_mimc_groth_16, CurveBasicOperations}; 8 | 9 | /// BLS12_381 ADD 10 | pub fn bls12_381_add() { 11 | // two one-points add encode 12 | let input1 = hex::decode( 13 | "bbc622db0af03afbef1a7af93fe8556c58ac1b173f3a4ea105b974974f8c68c30faca94f8c63952694d79731a7d3f117e1\ 14 | e7c5462923aa0ce48a88a244c73cd0edb3042ccb18db00f60ad0d595e0f5fce48a1d74ed309ea0f1a0aae381f4b30800\ 15 | bbc622db0af03afbef1a7af93fe8556c58ac1b173f3a4ea105b974974f8c68c30faca94f8c63952694d79731a7d3f117e1\ 16 | e7c5462923aa0ce48a88a244c73cd0edb3042ccb18db00f60ad0d595e0f5fce48a1d74ed309ea0f1a0aae381f4b30800").unwrap(); 17 | 18 | let res1 = Bls12_381::add(&input1[..]).unwrap(); 19 | 20 | let expected = hex::decode( 21 | "4e0fbf29558c9ac3427c1c8fbb758fe22aa658c30a2d90432501289130db21970c45a950ebc8088846674d90eacb720528\ 22 | 9d7479198886ba1bbd16cdd4d9564c6ad75f1d02b93bf761e47086cb3eba22388e9d7773a6fd22a373c6ab8c9d6a1600").unwrap(); 23 | 24 | assert_eq!(res1, expected); 25 | } 26 | 27 | /// BLS12_381 MUL 28 | pub fn bls12_381_mul() { 29 | let input = hex::decode( 30 | "bbc622db0af03afbef1a7af93fe8556c58ac1b173f3a4ea105b974974f8c68c30faca94f8c63952694d79731a7d3f117e1e7c5462923aa0ce48a88a244c73cd0edb3042ccb18db00f60ad0d595e0f5fce48a1d74ed309ea0f1a0aae381f4b3080029833b7bbb804ef963d8b7ad8bc2b8f618f7d002103309d09ad6f3ac351a0c06" 31 | ).unwrap(); 32 | 33 | let res2 = Bls12_381::mul(&input[..]).unwrap(); 34 | 35 | let expected = hex::decode( 36 | "c8315497236f5373dea887756f63ebc5487c07a40cb4c086e9b08c2130229d3740d5610745636296b01eabd0f1265f1233e03378baf08d5bd6e386631d1b143694ebaa70481b86dba120e8dbc1cbf392dbd3718a8af4ad38d4de77bb2b37790900" 37 | ).unwrap(); 38 | 39 | assert_eq!(res2, expected); 40 | } 41 | 42 | /// BLS12_381 PAIRING 43 | pub fn bls12_381_pairing() { 44 | // vec![sa,b,-sb,a] 45 | let input = hex::decode( 46 | "0b198686e7b0d46c9857744a328590a0a4368724b79e3c747df05f90ef692a36dbef2f5643a3789c29f536d58068cb162e\ 47 | 586c47ee9fc22748c5b6ca5e125dcf758bb3899a581e58c0fa5bc8c6be87edeb1bd21125524eb45c750da4a9d278030009\ 48 | c3078d5c5886fb948bbda03027f17c5a4d807fe558c5651578eb4f72038408ca45da26f19066f74c656542cf161507eee2\ 49 | 037db5882ae08f54b0f66c742e3a79375f49b5fc9ff01c2ddd8571b7c479e85b3f9abf5d26a69921ab2cc9728007588d69\ 50 | b2f90b0fe516ffb6be22c41658398ff87550dd01894fe7cf80b1bda6558c622da12fb2a5b57b1f60482a891f0a1430db3f\ 51 | 748ce4124af7ef20ee6ff9b94c1a352517c7975be916ea72887b9ad8660f737bda241d79f76db11c5235001800c8315497\ 52 | 236f5373dea887756f63ebc5487c07a40cb4c086e9b08c2130229d3740d5610745636296b01eabd0f1265f1278cacb8745\ 53 | 0f715e291ccd4de1e497e88f0a068658b7aa8b1df29c17c37f83d1fbd8d9b82bb36d12c607087ebeda871000d879d64cbd\ 54 | 2cd44468ba0e19ddb5dad885f0fed06d1c074868c08229f7269ea8a9d7d4e7de243333a4fe829e8b8a19123013defa5b00\ 55 | 097611c1da36ad481631c58756ec4a6e4850ee00f1801949279d8fc043b589dca9a61edf02c2e707990a9c22b196e2b982\ 56 | f0af96aa87f3a0a38cf46d78be5b8ec18f6b7339a20ee75adf339c2d68f71478b28d06687f9deca7124180ecce34771716\ 57 | 75f9d4e6e779016ede8e63ef4396fd7ad4318ed5561290ca7dcd2288a2ae8894c9c7339e8186681100" 58 | ).unwrap(); 59 | 60 | // e(sa, b) = e(sb, a) 61 | // e(sa, b) * e(-sb, a) = 1 62 | assert!(Bls12_381::pairings(&input[..]).expect("pairings failed")); 63 | } 64 | 65 | /// BLS12_381 PAIRING SIX 66 | pub fn bls12_381_pairing_six() { 67 | // test pairings 68 | { 69 | bls12_381_pairing(); 70 | } 71 | 72 | // check pairings 73 | { 74 | // hex![(a1, b1), (a2, b2), (-a1, b1), (-a2, b2)]; 75 | let pairings_encoded = 76 | "bbc622db0af03afbef1a7af93fe8556c58ac1b173f3a4ea105b974974f8c68c30faca94f8c63952694d79731a7d3f117e1\ 77 | e7c5462923aa0ce48a88a244c73cd0edb3042ccb18db00f60ad0d595e0f5fce48a1d74ed309ea0f1a0aae381f4b30800b8\ 78 | bd21c1c85680d4efbb05a82603ac0b77d1e37a640b51b4023b40fad47ae4c65110c52d27050826910a8ff0b2a24a027e2b\ 79 | 045d057dace5575d941312f14c3349507fdcbb61dab51ab62099d0d06b59654f2788a0d3ac7d609f7152602be0130128b8\ 80 | 08865493e189a2ac3bccc93a922cd16051699a426da7d3bd8caa9bfdad1a352edac6cdc98c116e7d7227d5e50cbe795ff0\ 81 | 5f07a9aaa11dec5c270d373fab992e57ab927426af63a7857e283ecb998bc22bb0d2ac32cc34a72ea0c4060600a99a8987\ 82 | b00903e92d4d1209ce7dc310915d801ec2414a4e571b9080ca8889065419a6f64bd90da2dfbb53514190ec09d4cecc58e6\ 83 | 86ed79717f20afea668b9a8a6023927a6c94ab28e9f45e6cc830e4392c69132144f982704f7d4964e4430400d9e64f510e\ 84 | 959d98fb0c2b7064f6fc21e90d4cb513a9dbb001cddd3d4ce4454527632d438d56a754971b17a25a59d70f1036ecbc7a5c\ 85 | 8d0f27ba421c1c0a068cff756aa419cc42913257a5d78da12ef9194a11767e0e5d0f3739dbce4b21a90b611722a33ff03c\ 86 | 02b91c54d72f6437b7fe9c27f4751bbd1ebdcfd0aa1898ef915ecdb2c9586f05e8faba135d0b64fd0d3610a6e94eb220c3\ 87 | 523519374e582f03d08a8a51f7e452b7a3b7bf6cc8492e01b8c7b79b8929157a18b51ed5c3e26c0a00bbc622db0af03afb\ 88 | ef1a7af93fe8556c58ac1b173f3a4ea105b974974f8c68c30faca94f8c63952694d79731a7d3f117cac239b9d6dc54ad1b\ 89 | 75cb0eba386f4e3642accad5b95566c907b51def6a8167f2212ecfc8767daaa845d555681d4d1100b8bd21c1c85680d4ef\ 90 | bb05a82603ac0b77d1e37a640b51b4023b40fad47ae4c65110c52d27050826910a8ff0b2a24a027e2b045d057dace5575d\ 91 | 941312f14c3349507fdcbb61dab51ab62099d0d06b59654f2788a0d3ac7d609f7152602be0130128b808865493e189a2ac\ 92 | 3bccc93a922cd16051699a426da7d3bd8caa9bfdad1a352edac6cdc98c116e7d7227d5e50cbe795ff05f07a9aaa11dec5c\ 93 | 270d373fab992e57ab927426af63a7857e283ecb998bc22bb0d2ac32cc34a72ea0c4060600a99a8987b00903e92d4d1209\ 94 | ce7dc310915d801ec2414a4e571b9080ca8889065419a6f64bd90da2dfbb53514190ec09d7db32a7197911408e80330214\ 95 | 99208499958d6426669cbb96299094188346809d80e22f956322c8299702f0852dbd1500d9e64f510e959d98fb0c2b7064\ 96 | f6fc21e90d4cb513a9dbb001cddd3d4ce4454527632d438d56a754971b17a25a59d70f1036ecbc7a5c8d0f27ba421c1c0a\ 97 | 068cff756aa419cc42913257a5d78da12ef9194a11767e0e5d0f3739dbce4b21a90b611722a33ff03c02b91c54d72f6437\ 98 | b7fe9c27f4751bbd1ebdcfd0aa1898ef915ecdb2c9586f05e8faba135d0b64fd0d3610a6e94eb220c3523519374e582f03\ 99 | d08a8a51f7e452b7a3b7bf6cc8492e01b8c7b79b8929157a18b51ed5c3e26c0a00"; 100 | 101 | let input = hex::decode(pairings_encoded).unwrap(); 102 | 103 | // check pairings operation:(a1*b1) * e(a2*b2) * e(-a1*b1) * e(-a2*b2) == 1 return true 104 | assert!(Bls12_381::pairings(&input[..]).unwrap()); 105 | } 106 | } 107 | 108 | pub fn bls12_381_verify() { 109 | let proof = "fcafa9753aee681f006d7bf6fc885dcc1a70c33bbfe92bb581ac51e1325b782b1128b1586767cb2ea27555e243abd293443cc8d6ffec17c44207dd41e8ab2f2f2c663f5ed9ab724321de43cbe2ea81908c13643c42a41be1adbc5076e4927b13046d3cdaf5ef775ee48d842599508178276cd41d30e289cbd1d2bb9f92f59b520138fef3e9529139f3961f40f6ea9211de094abc5e25fac259efcfd79a97401359069cde3b48eaa9d3a4d848959eb269d788a415d9c22fb418459474f1f0fc96"; 110 | let vk = "408697568bc15871da494a2fe12199531130a8a5b96f07c69020dc01bf9f3ed043a6e1bd08f8d7826c7d5c0fc5c771995b6d86316ea7c1dc4df3e3396a9f78aadf416d5af1619883f5dbbf0a39c6743b194e5adedda54d7cb3ae33e556602e19dd43a31bca7bdb15ad5245dc1ad0affb97edc8f35bb00d1c5b417a132d5be9b72a39870193b6a142198a888c0fe3768f9094c864d37f890720969430f2682ccc76dc83f9234694590bd334b40dbfa7f28de40e914571d8ae2a88712844f86f0d6dd2f4875120f66304bfcedd55c9a805310155a5345ddc626cbb6fe5ce7026be174a08c798e4d1f1010f97138c30b10a0c06c5cc02155140b97283cc024daf57023a781a9115bb6e17350264f8b52784a6008921402af8c05dd39f4b789bd50435d2c5aefeb6dc9817af41f45779e3a2d80ab98ef923723b938566747c10a4a169ca5097c5d5073449c3d2e65e1629980200000000000000e60f6032ed7f170ba3481c5d99c0890554c808ad380a7c9aefc9e62eeecf0363ecef5e59ba8eaf6dd0af40e08d7cfd82ea7f398187aecf2721441218e54645b17acd35bdf65886255e772a58353ef2e25c92cf7f872bea5afca6081d03e6b115"; 111 | let image = "1d6c7850edbac8a5281ab93d2ed245d47b64f20c21950926d595624b488c291c"; 112 | 113 | let proof_input = hex::decode(proof).unwrap(); 114 | let vk_input = hex::decode(vk).unwrap(); 115 | let image_input = hex::decode(image).unwrap(); 116 | 117 | let proof = Proof::::deserialize(&*proof_input).expect("Proof deserialize fail:"); 118 | let vk = VerifyingKey::::deserialize(&*vk_input).expect("vk deserialize fail"); 119 | let pvk = PreparedVerifyingKey::::from(vk); 120 | let image = Fr::read(&*image_input).unwrap(); 121 | 122 | assert!(verify_proof(&pvk, &proof, &[image]).unwrap()); 123 | } 124 | 125 | #[test] 126 | pub fn test_bls12_381_verify() { 127 | bls12_381_verify(); 128 | } 129 | 130 | #[test] 131 | pub fn test_bls12_381_groth16() { 132 | test_mimc_groth_16::(); 133 | } 134 | 135 | #[test] 136 | fn test_bls12_381_additional() { 137 | // zero-points additions 138 | { 139 | let input = hex::decode( 140 | "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\ 141 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\ 142 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\ 143 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001").unwrap(); 144 | 145 | let res = Bls12_381::add(&input[..]).unwrap(); 146 | 147 | let expected = hex::decode( 148 | "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\ 149 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001").unwrap(); 150 | 151 | assert_eq!(&expected[..], &res[..]); 152 | } 153 | 154 | bls12_381_add(); 155 | } 156 | 157 | #[test] 158 | fn test_bls12_381_scalar_mul() { 159 | bls12_381_mul(); 160 | } 161 | 162 | // 30 times pairings 163 | #[test] 164 | fn test_bls12_381_pairing() { 165 | for i in 0..5 { 166 | bls12_381_pairing_six(); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /crates/curve/src/groth16/verify.rs: -------------------------------------------------------------------------------- 1 | //! Groth16 verifaction 2 | 3 | use alloc::{ 4 | string::{String, ToString}, 5 | vec::Vec, 6 | }; 7 | 8 | use num_bigint::BigUint; 9 | use parity_scale_codec::{Decode, Encode}; 10 | 11 | use crate::{ 12 | error::{Error, Result}, 13 | ops::CurveBasicOperations, 14 | }; 15 | 16 | /// Groth16 Verifying Parcel 17 | #[derive(Debug, Encode, Decode)] 18 | pub struct Groth16Parcel { 19 | pub vk_gamma_abc: Vec>, 20 | pub vk: Vec, 21 | pub proof: Vec, 22 | pub public_inputs: Vec>, 23 | } 24 | 25 | /// Verify Wrapper 26 | pub fn verify(parcel: Vec) -> Result { 27 | let Groth16Parcel { 28 | vk_gamma_abc, 29 | vk, 30 | proof, 31 | public_inputs, 32 | } = Groth16Parcel::decode(&mut parcel.as_ref()).map_err(|_| Error::VerifyParcelFailed)?; 33 | verify_proof::(vk_gamma_abc, vk, proof, public_inputs) 34 | } 35 | 36 | /// preprocess vk and proof to verify proof 37 | pub fn preprocessed_verify_proof( 38 | vk: [&str; 14], 39 | vk_gamma_abc: [&str; 6], 40 | proof_and_input: &[u8], 41 | ) -> Result { 42 | let bytes = hex::decode(proof_and_input).map_err(|e| format!("hex decode error:{}", e))?; 43 | let (proof, input) = bytes.split_at(2 * C::G1_LEN + C::G2_LEN); 44 | 45 | let mut vk_vec = Vec::new(); 46 | vk_vec.append(&mut g2_pad_infinity(vk[6], vk[7], vk[8], vk[9])); 47 | vk_vec.append(&mut g2_pad_infinity(vk[10], vk[11], vk[12], vk[13])); 48 | vk_vec.append(&mut g1_pad_infinity(vk[0], vk[1])); 49 | vk_vec.append(&mut g2_pad_infinity(vk[2], vk[3], vk[4], vk[5])); 50 | 51 | verify_proof::( 52 | (0..vk_gamma_abc.len() / 2) 53 | .map(|i| g1_pad_infinity(vk_gamma_abc[i * 2], vk_gamma_abc[i * 2 + 1])) 54 | .collect(), 55 | vk_vec, 56 | proof.to_vec(), 57 | (0..input.len() / C::SCALAR_LEN) 58 | .map(|i| input[i * C::SCALAR_LEN..(i + 1) * C::SCALAR_LEN].to_vec()) 59 | .collect(), 60 | ) 61 | } 62 | 63 | /// Groth16 verification 64 | pub fn verify_proof( 65 | vk_gamma_abc: Vec>, 66 | vk: Vec, 67 | proof: Vec, 68 | public_inputs: Vec>, 69 | ) -> Result { 70 | let g1_len = C::G1_LEN; 71 | let g2_len = C::G2_LEN; 72 | let g1_g2_len = C::G2_LEN + C::G1_LEN; 73 | let scalar_len = C::SCALAR_LEN; 74 | 75 | if (public_inputs.len() + 1) != vk_gamma_abc.len() { 76 | return Err(Error::VerifyParcelFailed); 77 | } 78 | 79 | // First two fields are used as the sum 80 | let mut acc = vk_gamma_abc[0].to_vec(); 81 | 82 | // Compute the linear combination vk_x 83 | // [(βui(x)+αvi(x)+wi(x))/γ] ∈ G1 84 | // acc = sigma(i:0~l)* [(βui(x)+αvi(x)+wi(x))/γ] ∈ G1 85 | for (i, b) in public_inputs.iter().zip(vk_gamma_abc.iter().skip(1)) { 86 | let mut mul_input = Vec::with_capacity(scalar_len + g1_len); 87 | mul_input.extend_from_slice(b); 88 | mul_input.extend_from_slice(i); 89 | 90 | // Check if invalid length 91 | if mul_input.len() != g1_len + scalar_len { 92 | return Err(Error::SerializeDataFailed); 93 | // return Err(format!( 94 | // "Invalid input length {} for mul operation, should be {}", 95 | // mul_input.len(), 96 | // g1_len + scalar_len 97 | // ) 98 | // .into()); 99 | } 100 | let mul_ic = crate::call(0x01000001 + C::CURVE_ID, &mul_input)?; 101 | 102 | let mut acc_mul_ic = Vec::with_capacity(g1_len * 2); 103 | acc_mul_ic.extend_from_slice(acc.as_ref()); 104 | acc_mul_ic.extend_from_slice(mul_ic.as_ref()); 105 | 106 | // Check if invalid length 107 | if acc_mul_ic.len() != g1_len * 2 { 108 | return Err(Error::SerializeDataFailed); 109 | } 110 | acc = crate::call(0x01000000 + C::CURVE_ID, &*acc_mul_ic)?; 111 | } 112 | 113 | // The original verification equation is: 114 | // A * B = alpha * beta + acc * gamma + C * delta 115 | // ... however, we rearrange it so that it is: 116 | // A * B - acc * gamma - C * delta = alpha * beta 117 | // or equivalently: 118 | // A * B + (-acc) * gamma + (-C) * delta + (-alpha) * beta = 0 119 | let pairings = [ 120 | ( 121 | &proof[0..g1_len / 2], // G1 x 122 | &proof[g1_len / 2..g1_len - 1], // G1 y 123 | &proof[g1_len - 1..g1_len], // G1 infinity 124 | &proof[g1_len..g1_len + g2_len], // G2 125 | ), 126 | ( 127 | &acc[0..g1_len / 2], 128 | &*negate_y::(&acc[g1_len / 2..g1_len - 1]), 129 | &acc[g1_len - 1..g1_len], 130 | &vk[0..g2_len], 131 | ), 132 | ( 133 | &proof[g1_g2_len..g1_g2_len + g1_len / 2], 134 | &*negate_y::(&proof[g1_g2_len + g1_len / 2..g1_g2_len + g1_len - 1]), 135 | &proof[g1_g2_len + g1_len - 1..g1_g2_len + g1_len], 136 | &vk[g2_len..g2_len * 2], 137 | ), 138 | ( 139 | &vk[g2_len * 2..g2_len * 2 + g1_len / 2], 140 | &*negate_y::(&vk[g2_len * 2 + g1_len / 2..g2_len * 2 + g1_len - 1]), 141 | &vk[g2_len * 2 + g1_len - 1..g2_len * 2 + g1_len], 142 | &vk[g2_len * 2 + g1_len..g2_len * 3 + g1_len], 143 | ), 144 | ]; 145 | 146 | let mut input = Vec::with_capacity((g1_len + g2_len) * 4); 147 | pairings.iter().for_each(|(x, y, infinity, g2)| { 148 | input.extend_from_slice(x); 149 | input.extend_from_slice(y); 150 | input.extend_from_slice(infinity); 151 | input.extend_from_slice(g2); 152 | }); 153 | 154 | // Return the result of computing the pairing check 155 | // e(p1[0], p2[0]) * .... * e(p1[n], p2[n]) == 1. 156 | // For example pairing([P1(), P1().negate()], [P2(), P2()]) should return true. 157 | Ok(crate::call(0x01000002 + C::CURVE_ID, &input)?[0] == 0) 158 | } 159 | 160 | // 161 | fn g1_pad_infinity(x: &str, y: &str) -> Vec { 162 | let mut bytes = vec![]; 163 | bytes.append(&mut decode_hex(x.to_string())); 164 | bytes.append(&mut decode_hex(y.to_string())); 165 | bytes.push(0u8); // infinity flag 166 | bytes 167 | } 168 | fn g2_pad_infinity(x1: &str, y1: &str, x2: &str, y2: &str) -> Vec { 169 | let mut bytes = vec![]; 170 | bytes.append(&mut decode_hex(x1.to_string())); 171 | bytes.append(&mut decode_hex(y1.to_string())); 172 | bytes.append(&mut decode_hex(x2.to_string())); 173 | bytes.append(&mut decode_hex(y2.to_string())); 174 | bytes.push(0u8); // infinity flag 175 | bytes 176 | } 177 | fn decode_hex(value: String) -> Vec { 178 | let mut bytes = hex::decode(value.strip_prefix("0x").unwrap()).unwrap(); 179 | bytes.reverse(); 180 | bytes 181 | } 182 | 183 | fn negate_y_based_curve(y: BigUint, MODULUS: &[u8]) -> BigUint { 184 | let q = BigUint::from_bytes_le(MODULUS); 185 | q.clone() - y % q 186 | } 187 | 188 | fn negate_y(y: &[u8]) -> Vec { 189 | let neg_y = negate_y_based_curve(BigUint::from_bytes_le(y), C::MODULUS).to_bytes_le(); 190 | 191 | // Because of randomness, Negate_y vector might not satisfy g1_y_len bytes. 192 | let mut neg_y_fill_with_zero = vec![0; y.len()]; 193 | neg_y_fill_with_zero[0..neg_y.len()].copy_from_slice(&*neg_y); 194 | 195 | neg_y_fill_with_zero 196 | } 197 | 198 | #[test] 199 | fn test_verify() { 200 | use crate::curve::Bls12_381; 201 | 202 | // VK = [alpha beta gamma delta] 203 | const VK:[&str;14] = ["0x0255430d4664c579165e2204f7dcef9556b8077fa7b0d9e6346f68e8a8028373e621e0070117ea963a28ea8daae7c295","0x08ed8bf7cd4fe9a8823594d2c99d6955228b46ee3ae1916ff7c087668eff3c078ee1942760d295af43b77492b100bdbd", 204 | "0x096325545fbbe733305b1d2b0034c01b3bdc7783b7cb9e995f18f14a88c43e2378052854b047c3ea0c941000265e7ea2", "0x00fb167465e35f0581d693aa7225821a0e077dcdd96e7c593415ce9dfa71874680bd9374a82bf729c4688b439f0ded3b", "0x0ebd72a410429e8ca4d379a335601f9d37208df1a067bf554f938f7336671371d86ca66aa83b60723782f3400b170413", "0x0377f821ed328dd127434c4fe06cc899711cdc47854a710102f51338e69bdbdea58ecbe4708d95a2edbecc1d8dbd9e57", 205 | "0x17c73570d12596a5e232f5240c10e9c2d1e7f4730746c8d4562309c0b7af3ad1c199317074e6d1a2e7cb15f1ee3334a1", "0x134256783454e4dad8631526d3b6f9ceaff12bb85e08693ef35cf6081683c4ab42e288d146b235899f50695c8e93493b", "0x0751498144a033087af7870423982200fef4fb15a115aef5120a5dcc573620af2e70bf83e6415ccc4c2b690a175b603b", "0x147b5b60d963b79c12e300a9764de5e2a1968cd07602597c2401a6b158bdc8a6bbad3dc9cc00d559d67ab33f199e032c", 206 | "0x02da9b61f2998b4e2a176d29244f188344a2af7ec66bdf61958344f9e533c731554fdcefb5801b7ad48a983abedd871d", "0x1906c82bfae3600f4d747fd10a8b2ef5219c0252a9ed85fbfbe2e2f126949450f34ada481a781b22db74f4d3d5ffd8eb", "0x14b54cf5402a7f4ae279c09ed9ea9b6aca2dcc96e5e677d8eed9edc3df8460581fca64c5593bd22f3c539a1d63517361", "0x15c6eb142f78a4b99caf9ca97237c2eb6f2dc83e52c395bf9223c4532d3dc754a3afa52ea4b9fef62954f9369218b90c"]; 207 | const VK_GAMMA_ABC:[&str;6] =["0x07fb259c08d05a67e8e17ad3e6cb8e43a3ed1b10ece4dd8cbc0e3030016d09e43d195b7a34a8a46c76c4c327503c0b16","0x12cc86b8791137fef3b4caf4f4a38ec65eafef5bb34882d54ed07e7b1d8cf82423faec3d2c4029ae191119174bb17c4a","0x0d50f43997c6bc4a449d1e877436cbc9b5ecae45ee57ebcfe1a5a60787ce8ebb1692a3a23989d7e14e1216a959323ad3","0x0ec9f709318ddef4d513233c17e9112bdb8cc878bb86aef392dc1ddb4715e6f606ca8b122227ca5ecc31d39dbd8707c5","0x08171915be1b00c1a178f714bd5c3ea46c0070eabeb091a3cc124d53ef1dd47396c3ad2723aa91cd9c722582451282b4","0x1794ec6794a614392a3f63e165c7461cd6a00108ff3fcc102977de92ecb8588f557711f8ead71ffb681bc37b1ee1b7a6"]; 208 | 209 | let proof_and_input = "c900f310725b3ec9dcc26021a8bc01558f44b7aa9bb6bc98399212652248d9988a3fceeccf07b1787cc7dea439c9b20683bc04a9e5a961a4094fc738f98f4878d5298587f9693bf18505b2cf0737fb49017775469d0215d1e0bd8fb36e36c81600f4f56a8745305c97ed023eaf97c5646ba67300a9430ae8ab437446d5f0fbaa48bcec410bbea6941131b518d1212faa02a032871dcedfd968bd0fc93c45c4e026f91193cb4910f92b98ef3f4fac9cf3d168a8fa338c90a4071a9c374edf80c008fbeb5a067bf5e50f213efc8da9822b5064666d369dd39dfd9199b4c2cb2273b5c4d3685216db4325429821bcde61330bfb5b8801e92cd231d53f2f3c09f39e54b99c3bd3780e9ba31b486f736243dd355406b4c5bc43dc65fd39688a41d8a30f0011333c5d8d51e3429ba5c60be670b62f078a048196b98bd5a890c71f1ff1c746d6d764f455d120ec484f87524c2c4b065e66bfa9ff4ab99f06df246ea397e5757bf5045fde4899d33821e2eb71ebcaac8274d306fc2620e2a88ce1d26f0e92030090000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000"; 210 | 211 | assert_eq!( 212 | preprocessed_verify_proof::(VK, VK_GAMMA_ABC, proof_and_input.as_bytes()) 213 | .unwrap(), 214 | true 215 | ); 216 | } 217 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /crates/curve/src/tests/curve/bw6_761.rs: -------------------------------------------------------------------------------- 1 | use ark_bw6_761::{Fr, BW6_761}; 2 | use ark_ff::{Field, FromBytes, ToBytes}; 3 | use ark_groth16::{verify_proof, PreparedVerifyingKey, Proof, VerifyingKey}; 4 | use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; 5 | use ark_std::{ops::MulAssign, test_rng, vec::Vec, UniformRand}; 6 | 7 | use crate::{tests::mimc::test_mimc_groth_16, CurveBasicOperations}; 8 | 9 | /// BW6_761 ADD 10 | pub fn bw6_761_add() { 11 | // two one-points add encode 12 | let input1 = hex::decode( 13 | "3db4e566aff388403f60afa6ac285905823e135603dd50677fa20c289a8f75037109eac9a01fd75b909b7247ce547aa146e7c294d2fcdb11ac2055c1fa7f0179c76ff5854bc505eef0271b55b7cfa0e6aebe77a498ce77b2c890a10e025b07016353e9b42d8ffcbaa1d2200bbeb21cad93fbd0ca1981b0b2533205b341f19d9fd4cdc26f0bb93fbe554c7a71315d68cc06b8b57117fab8c5ba0d7eaff1095926a373e5a2d248731ac69e4c888925950f422acc457b63fde674c56f0a4eb85800003db4e566aff388403f60afa6ac285905823e135603dd50677fa20c289a8f75037109eac9a01fd75b909b7247ce547aa146e7c294d2fcdb11ac2055c1fa7f0179c76ff5854bc505eef0271b55b7cfa0e6aebe77a498ce77b2c890a10e025b07016353e9b42d8ffcbaa1d2200bbeb21cad93fbd0ca1981b0b2533205b341f19d9fd4cdc26f0bb93fbe554c7a71315d68cc06b8b57117fab8c5ba0d7eaff1095926a373e5a2d248731ac69e4c888925950f422acc457b63fde674c56f0a4eb8580000").unwrap(); 14 | 15 | let res1 = BW6_761::add(&input1[..]).unwrap(); 16 | 17 | let expected = hex::decode( 18 | "1ae80b765e09a7bf87f4b2023abea11d37181e0c78db8e28e88a401acb8808ec34e9dc4dae4501219771ec5f13830e413b3d08f4505a8d71fdceb2fcc539d31d2a136e49dba3cb8e8c66551aea983759853ab88b0d83d07d47574a7c18d3bd002adf2f6db69dc19d17a54df5a6db30710eeb0d97c0b58de174e915018ba823ab03aab81282a66148bf8308dbd821b318c8849baec50d824af6151af31bac63910304c02e7abfadbae8ee5f939e4e35698f6750f0c4ee1703560d5454f513940000").unwrap(); 19 | assert_eq!(res1, expected); 20 | } 21 | 22 | /// BW6_761 MUL 23 | pub fn bw6_761_mul() { 24 | let input2 = hex::decode( 25 | "3db4e566aff388403f60afa6ac285905823e135603dd50677fa20c289a8f75037109eac9a01fd75b909b7247ce547aa146e7c294d2fcdb11ac2055c1fa7f0179c76ff5854bc505eef0271b55b7cfa0e6aebe77a498ce77b2c890a10e025b07016353e9b42d8ffcbaa1d2200bbeb21cad93fbd0ca1981b0b2533205b341f19d9fd4cdc26f0bb93fbe554c7a71315d68cc06b8b57117fab8c5ba0d7eaff1095926a373e5a2d248731ac69e4c888925950f422acc457b63fde674c56f0a4eb8580000dab41652cc0635372e025c39eecbb41543853236e87cacff83bbc30aa775ee3a7f73cea5adfe6bef3969c6d7595e2f00").unwrap(); 26 | 27 | let res2 = BW6_761::mul(&input2[..]).unwrap(); 28 | 29 | let expected = hex::decode( 30 | "f6b690da673fb611abab389029808c0c03ec8db39fc1dc62fb8be6a46a2705cddaf1cd479b594c968c6b6737a66636d4372b65c4b9705dca9f2213eab6a0bf1c9e5ff041e417044df70510c6076193d9465379815171d3d8195971a18555d800388f31f277f047afea056648825407409ea154ffb0990fc7b31c378c6198182404a917f105572fa0f2706654de648ae30cd4d086b1823e6f0f5b231c4fec5b5d153d958140105a3b7776f2aa7e8fa130f51e46a321789b0c43331b01e82fee0000").unwrap(); 31 | 32 | assert_eq!(res2, expected); 33 | } 34 | 35 | /// BW6_761 PAIRING 36 | pub fn bw6_761_pairing() { 37 | // hex![(sa,b),(-sb,a)] 38 | let input = hex::decode( 39 | "0bd1717c0d2581b3891c9fc55685efd41599eda572fddae589799d66e55c98c2acac0ff19d907f9f2af31cbe540d22d7d2511fb57874d1d30c26e6b65516b74e49acb5a503c4ceafde11e8102d9607eeee181aea7a192fc3e9f99cb40a9ace00261d6e38f43fd71927c736749beb555c1d35f6cc271630d7b02eb061295b38523dc9c7187c4b988540bb7aa01098776e6b0ff698837039227824bedef4c0017ee2f839bad58c3b25aec3aea039ae99f007144a0975d6208787e87718135b0f00008221187269a97f67ddb3b89674821102b3ce296080a856e24e11cc1036ab36fc345bb86ed61128989a5618057fd09127c61a639f4b4419f48c86ab0f2417fb9984abcc92002ced2a5b61c36a5aeea3ad78b1f708052f30da8b6a146538e34c00ff58f077852dd902f9d4038b9f2fe0b5e4d2e70947ade43e8c1a606b945b0c000be2dea0031bb944715227aafd331690abcdf23a772fa039d38b1648ad2da40715026f359edc375ec7f2c1b16fd7aa0296af31b88ff35eb8c499ae11376ac30000f6b690da673fb611abab389029808c0c03ec8db39fc1dc62fb8be6a46a2705cddaf1cd479b594c968c6b6737a66636d4372b65c4b9705dca9f2213eab6a0bf1c9e5ff041e417044df70510c6076193d9465379815171d3d8195971a18555d8005371ce0d880f554598fa9927e6e989a699029cebfd5efd4e448c30ca607e88742a56d482d67cadd19d8c93be0e64ffa2f74ee39e4d389094098e61c9e9b91f132c81f2feae65281711d0ded6eb88848849e0b4611e51ecc4c79a68fa3cb8340000fdabfe45138bd1f8b64406bee66f099aa67de7c1a8708c74760a83706b1ceae9bf6ae4237269971f7ff3403ba64f07819885beafedd3d90fc5bb9e34c2d90a945a5f8f018e78821046fff3c0aa747cbb6e1d6ef92c126d01813d836271e67600df383d4a00a6365566e278fed9dfbd192252c4d14e0b5e21f9d5823033a1de2dd7280d40ffb3f8551ba54e6efa6734a923d9392d1a31fd7e790ddc465b94258c86567ef506a39731c3b2b756f8d349b06495ace6cbf1a4b2c21f396aaee2980000").unwrap(); 40 | 41 | // e(sa, b) = e(sb, a) 42 | // e(sa, b) * e(-sb, a) = 1 43 | assert!(BW6_761::pairings(&input[..]).expect("pairings failed")); 44 | } 45 | 46 | /// BW6_761 PAIRING SIX 47 | pub fn bw6_761_pairing_six() { 48 | bw6_761_pairing(); 49 | 50 | // check pairings 51 | { 52 | // hex![(a1, b1), (a2, b2), (-a1, b1), (-a2, b2)]; 53 | let pairings_encoded = "3db4e566aff388403f60afa6ac285905823e135603dd50677fa20c289a8f75037109eac9a01fd75b909b7247ce547aa146e7c294d2fcdb11ac2055c1fa7f0179c76ff5854bc505eef0271b55b7cfa0e6aebe77a498ce77b2c890a10e025b07016353e9b42d8ffcbaa1d2200bbeb21cad93fbd0ca1981b0b2533205b341f19d9fd4cdc26f0bb93fbe554c7a71315d68cc06b8b57117fab8c5ba0d7eaff1095926a373e5a2d248731ac69e4c888925950f422acc457b63fde674c56f0a4eb85800001c5f02cd94c130a85b99bfe14fcf1064b054adc2fb6ee900d708d23ccb4869cebab6e100a3173396c7e770ace9cabbc558eb9ff0f1c34e7368a23dab5d1cb4266d0f89131020064c5f11a7c5aa5310d6f960d6692ea852c816b8d94132131001613bc72867a170eb89c6eaf99405ec91a5025a3c3a2daa58c7ff4a50cd6fa93e0023a8ff70c10689b812c7d2db93f264ef3f2933b77ec9949ca5950bc8861d0a16e3ff53278ea7811c18c2ce9acfb726dcd2b6e410eb79819f36617735c31700005e56432f17a05e17b8239bd4e20a277f7b4ea0c17b3ccf821e186f027db66c0c9f0c8d19a47148d4cae52dc01fd4be25824c605a2fe34cc4c99228916463c7436fdca859832ff60f1bfa22d2c397e8b317f8824427e9bed626b36e1be6db0d00ff77df8a3ae314a859e5308a0cecb678701c6f8457388fd2744fc23f77e9e9f2c9ef5c361a3f6784d2d905aad084750420a0a5854b908bb3bb0a6e470b4cb0beab9edee555b352847fb8b63fdd3f62ec331ca4b83f425de5784718e68b64af0000395bd2f69ac70346ef2e6c947f84f05ee91fa5e490e47bcc38cfa049755c336469244435609a7aca6a9eba05d69209945b4ead089273e41b3d19e0bc2bc5c61e60b701b4c3c78e992c63df61812cc813ca7300723d065773cd6cfa0845294800e243b6b05040038a6c3b2b95d8f6fd1f94864ceb50bb51b178fbc77d7ec897632f986e30fc4492f70cb6a6e0e3d8a4c860c741dcc547197376bdeae7eba695cf85453e417d8f52de48e52968abf68f0a531034207a5c3f309533b180bc55f800003db4e566aff388403f60afa6ac285905823e135603dd50677fa20c289a8f75037109eac9a01fd75b909b7247ce547aa146e7c294d2fcdb11ac2055c1fa7f0179c76ff5854bc505eef0271b55b7cfa0e6aebe77a498ce77b2c890a10e025b070128ad164bd270a039e12ddf64aa8b7439a4a81f2095775c63a47662a3802503f959312904d11a9db33ab17fa1bb6b21bafd6afeb3e7c0153e5edb0636479c224a9e4aa2dd1c2d0f38c2a784f9e0f290a9fcd42ebfc4658aea950814f1d62fca00001c5f02cd94c130a85b99bfe14fcf1064b054adc2fb6ee900d708d23ccb4869cebab6e100a3173396c7e770ace9cabbc558eb9ff0f1c34e7368a23dab5d1cb4266d0f89131020064c5f11a7c5aa5310d6f960d6692ea852c816b8d94132131001613bc72867a170eb89c6eaf99405ec91a5025a3c3a2daa58c7ff4a50cd6fa93e0023a8ff70c10689b812c7d2db93f264ef3f2933b77ec9949ca5950bc8861d0a16e3ff53278ea7811c18c2ce9acfb726dcd2b6e410eb79819f36617735c31700005e56432f17a05e17b8239bd4e20a277f7b4ea0c17b3ccf821e186f027db66c0c9f0c8d19a47148d4cae52dc01fd4be25824c605a2fe34cc4c99228916463c7436fdca859832ff60f1bfa22d2c397e8b317f8824427e9bed626b36e1be6db0d008c882075c51c884c291bcfe55b52da6dc787816657c07d438359a5164b2db7a5640f8f3dc29475edbd23f4681c441482e4820ea0b32a43505dde169e2d5acbb1951fa99a99c22fce088e1a428dd8c3cc0ae3564c00872aec91866b159983730000395bd2f69ac70346ef2e6c947f84f05ee91fa5e490e47bcc38cfa049755c336469244435609a7aca6a9eba05d69209945b4ead089273e41b3d19e0bc2bc5c61e60b701b4c3c78e992c63df61812cc813ca7300723d065773cd6cfa0845294800e243b6b05040038a6c3b2b95d8f6fd1f94864ceb50bb51b178fbc77d7ec897632f986e30fc4492f70cb6a6e0e3d8a4c860c741dcc547197376bdeae7eba695cf85453e417d8f52de48e52968abf68f0a531034207a5c3f309533b180bc55f80000"; 54 | 55 | let input = hex::decode(pairings_encoded).unwrap(); 56 | 57 | // check pairings operation:(a1*b1) * e(a2*b2) * e(-a1*b1) * e(-a2*b2) == 1 return true 58 | assert!(BW6_761::pairings(&input[..]).unwrap()); 59 | } 60 | } 61 | 62 | #[test] 63 | fn test_bw6_761_additional() { 64 | // zero-points additions 65 | { 66 | let input = hex::decode( 67 | "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001").unwrap(); 68 | 69 | let res = BW6_761::add(&input[..]).unwrap(); 70 | 71 | let expected = hex::decode( 72 | "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001").unwrap(); 73 | 74 | assert_eq!(&expected[..], &res[..]); 75 | // println!("test add1 success!"); 76 | } 77 | 78 | // one-points additions 79 | bw6_761_add(); 80 | } 81 | 82 | pub fn bw6_761_verify() { 83 | let proof = "cf5ea12a32dc313ec0791efdfca4ffa5dca127faeb57027754f0fcdd0e868623082e4543cae1bb11078c359dabbd4abbb38640c75081dca4aa2ef35bdb5ee4c856465c7b75956b88ab36d940a8df7e13adaa709ee349ed9454c7d67052110280335b53718581ba3e14b48e381078551ff535a3d7a1671dc42898e742857f158a27d249a4d3bbe060016acdf3e9bde0095b23e073e40d56027474673321542ab30641f50f61452762d66984e33745d9456c5eba2cdafc07a52525ef1d3e221e00d1367d1907cd90da19e25e3241fb83393731c0d6183300675275017cc6287f2154abf2320cdc2cefc9df0383f98688e2e22914bef4fc32136222fb9dde45840de012e91cce1d02fbb6250a342b72c8c4155e0ff2ffa7ee71211f2641e816f280"; 84 | let vk = "be5dddc202ba74caa75135e9f81338910969729484a89a438090564689177b491e67f8cfa06ecfcee4acfd7cd364e094c1a4d028f7c7e0677d066cdf1355123e976fa498af59e308954054051fb3fabdda4b0d7a165cd454a71c53ff26546d0021a8ba5d55fabd1999a5a9d717008e812486fd4309d9b4fb75ce4d22199360d6f8855d2e55259220392a9a67b9104adfa1424633f0c527b5516535d43c2632e594a118c05394ea735234b998018ac2906d7f24f89226bb07d1229c6000b1390073174e4bb9c9b03c5ee9ddf21056832e01546744fffc64a5221e7e5cee09d37e534b27ae3725db7d3706c85b3932b269078f55cf1dd54c6e3247ad9a7619ef71315f5fee37909c44a216246c2ba2889b7b00b7f1298f5fb2776562527f401400d1e9ebd9d4d430b34703ac55be08c6d63e791dd2da3f7543b5d6db64e6ce9e0cfb031c168e2bede9cbd39070ecb4e1678d41cd0d48b087fa8a324964fded508df2ef48a7a6c21f1fe95e89aa98b00fb59bee1713e4ffaba216f00e5f15d12201020000000000000029f6308fb1faee384c2deae7744b65d79eafa98a3947df7e35330c73ad0165a2f92844dab884fec1e15e52ac08f9306a1d8e7b4b66f718cece36a90f9aafe59588aafcd6588a55b9c05c3177904e5cbd1e3b59e4077d1caff6329268b5882280639a14c4e08b97d97166d09eff9b57abf973b487fd5f5007c6ccc8adc31dbac74372477c035964e06f06d93e1483fe81ef1b51e525ffad28a053af20271dd363353e7ccd34cd599ac7c8c97fc175e4d9db8b9399db1647f52564757781209b80"; 85 | let image = "28933fc1b649ded455bd7739026be2bf6f7e1c0acde6dee164724218bbf1391e318017e5a6ab8248bda0bdd1f40b8301"; 86 | 87 | let proof_input = hex::decode(proof).unwrap(); 88 | let vk_input = hex::decode(vk).unwrap(); 89 | let image_input = hex::decode(image).unwrap(); 90 | 91 | let proof = Proof::::deserialize(&*proof_input).expect("Proof deserialize fail:"); 92 | let vk = VerifyingKey::::deserialize(&*vk_input).expect("vk deserialize fail"); 93 | let pvk = PreparedVerifyingKey::::from(vk); 94 | let image = Fr::read(&*image_input).unwrap(); 95 | 96 | assert!(verify_proof(&pvk, &proof, &[image]).unwrap()); 97 | } 98 | 99 | #[test] 100 | fn test_bw6_761_groth16() { 101 | test_mimc_groth_16::(); 102 | } 103 | 104 | #[test] 105 | fn test_bw6_761_verify() { 106 | bw6_761_verify(); 107 | } 108 | 109 | #[test] 110 | fn test_bw6_761_scalar_mul() { 111 | bw6_761_mul(); 112 | } 113 | 114 | // 30 times pairings 115 | #[test] 116 | fn test_bw6_761_pairing() { 117 | // test pairings 118 | for i in 0..5 { 119 | bw6_761_pairing_six(); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /crates/curve/src/tests/curve/cp6_782.rs: -------------------------------------------------------------------------------- 1 | use crate::{curve::CP6_782, CurveBasicOperations}; 2 | 3 | /// CP6_782 ADD 4 | pub fn cp6_782_add() { 5 | // two one-points add encode 6 | let input1 = hex::decode( 7 | "0ec0176973190029442be14ed3d59b6b1c5edffbedf5b325e3fb4e8e5727390f66efebabe9aded0d53477fe7a8ced0db437cb6e580654119be0eeaa2f31a367d77f44a71c686fba448b83603ce76796e1518038ba606749b019a7571c78096d2dd0d0000000000002b42bf978df0e1d22d7a68c07530a308108f3553075f36664c3e9d38d2375cf59cc2f53f6071068df86635195fcd48f4e8ab36594b22a4111433ca6beb550372f11c2e640fc4e07a7b403ba124037fc81719ddd5aaf43a88f443a4735b09eaf5e813000000000000000ec0176973190029442be14ed3d59b6b1c5edffbedf5b325e3fb4e8e5727390f66efebabe9aded0d53477fe7a8ced0db437cb6e580654119be0eeaa2f31a367d77f44a71c686fba448b83603ce76796e1518038ba606749b019a7571c78096d2dd0d0000000000002b42bf978df0e1d22d7a68c07530a308108f3553075f36664c3e9d38d2375cf59cc2f53f6071068df86635195fcd48f4e8ab36594b22a4111433ca6beb550372f11c2e640fc4e07a7b403ba124037fc81719ddd5aaf43a88f443a4735b09eaf5e81300000000000000").unwrap(); 8 | 9 | let res1 = CP6_782::add(&input1[..]).unwrap(); 10 | 11 | let expected = hex::decode( 12 | "8a59e8337302d1f3a944462db081110246cfd825ce906197c9364af95a814ae6037909493d0393630581887019acd8c771040cdd0a13e44c6f0ebcb6c9a00c0aad9604e635acef8f8fdb7a348e91085053f3761f8f245e2a3f5c9621d1da78adbe160000000000002cf9422ee038952d966beba7a3aabeae5cf313be40a4f275e04f820c7c58c94900b9ff11f7584564761f40b431525239175742d2b9a01c64cc66a86cabc6b098594879203aea9f9c4d9ee5b74b9ea6c1c58084ab4564c153a15fe89ff5f8405cdd1700000000000000").unwrap(); 13 | assert_eq!(res1, expected); 14 | } 15 | 16 | /// CP6_782 MUL 17 | pub fn cp6_782_mul() { 18 | let input2 = hex::decode( 19 | "0ec0176973190029442be14ed3d59b6b1c5edffbedf5b325e3fb4e8e5727390f66efebabe9aded0d53477fe7a8ced0db437cb6e580654119be0eeaa2f31a367d77f44a71c686fba448b83603ce76796e1518038ba606749b019a7571c78096d2dd0d0000000000002b42bf978df0e1d22d7a68c07530a308108f3553075f36664c3e9d38d2375cf59cc2f53f6071068df86635195fcd48f4e8ab36594b22a4111433ca6beb550372f11c2e640fc4e07a7b403ba124037fc81719ddd5aaf43a88f443a4735b09eaf5e81300000000000000dab41652cc0635372e025c39eecbb41543853236e87cacff83bbc30aa775ee3a7f73cea5adfe6bef3969c6d7595e2f00").unwrap(); 20 | 21 | let res2 = CP6_782::mul(&input2[..]).unwrap(); 22 | 23 | let expected = hex::decode( 24 | "97169d2ea987e88ed3d56076fef75095d629a0259b91fdba98857a138f24f651b4e78bd8993934dc960f64c174fc75ad5d5e3dbda6cc646efd84790f284696fd936e452bc6565bd052c45cbc77b22ec102d6b63f7b9e0dadb17d6fb1a9ab6338f32700000000000060fe6c49d6b893273190c93cb3c0380826fe9ed6d878644b8e3eaca857698b09b6efc0dcba4b65b5a93ecdf3588d7e58039b386a3b6b69ea9e343a7152d5b4d88ff9c995cb330bfa97438a17971e78327e9c879e12e47c79500b6d1c096f4b0bc00c00000000000000").unwrap(); 25 | 26 | assert_eq!(res2, expected); 27 | } 28 | 29 | /// CP6_782 MUL 30 | pub fn cp6_782_pairing() { 31 | // vec![sa,b,-sb,a] 32 | let input = hex::decode( 33 | "63d6b88c9772a400d1d6c4bd8faa04ac061b45ffad95d99ea17d76b9fca649a0a84776fc793a71486eb8c7ca5b83d2636d587614b396595279449de429bc059228bf317f1d4da525cd6e44e848160f76a266a607a444a768afaf022b34d52d66972a000000000000d7e04fd04299104293da186fe28e96fe677eec50c4b2e408a0682281d97b78fd1aaeab4bf4eb630106e6279013310e8a194b46e7b0f97fa125bcaa81bcf699dce5de8ed3a04b830d8517105131c749db6dc4e5608c8780ef75aa445c378fc9c93926000000000000008f0b1ac76c6cb6c0a334a1bf12a15c5ea5e3151219096bf4cb708fd6966930d464160f39836e97bf55e5a2e666257ebf9ce8dc8b71729dd7fb3b69b983c379f263758b2872c061afa4fbfd24cb44402c8d5b6a78caaae7b84e9ec09dba705ebcf327000000000000b78c152b45da1525ff97d596227b242bcaeb1a9420a84412640015bd188d36f03b079aae242678adb0d1c56d247f99a6e25577abc570cb1d73789306fec3150a7e69895856f58f6f0a6155d8fd3d22ddcf5083acb95797127f2d05f6e97d0e9d981f000000000000bfac98f6be9c6035a3e51ca759983590bd7fe2b094d5d6506c69dfd6c0fc4094d3225b3aa38d61f366a080e73e94450dd07581b611307c4149965468ce945858bae85e3b502d4e00b5088c084ef3816eb7476056a173dc0d7182628b82dc5b61e90d000000000000325420227adb00fba5a336f9b3dbc771e62d0fb831643fbb89a153ab83226f26bc9cd25517ed3503838b13b54c1eb4a6c9b3e8d9d5c9d0868a50d37894344a4d41bc00cbaaed588312518d0dbe813d83f0f42d3e90ffc872a8212de98f2dab9d69240000000000008a57a6e71f72d19c90793c434cd77b0f5aa0f6a1eab20ae7cdcef0da9d1e21816d5e93761edd793e26a86329159df91882e95390084ecf5be2fba1c456c40edafae4aa8a64d02122442acb3d384ab7372f1d4d073b63aa3e2c84c563ee504773762700000000000094de4ee023b2f6ab6f6a52c2de5958a63993d224a410f75a7bdd74c84f6e379d2dfd9be248871192fcc5102fb9ea6e5914e5130f6f917e9d752ed425b8e9e30cf6cdf9229844d3f56db05463ad7f1f06e1dbc2e2df3f099bf9917c84b6aeb2f87c320000000000000097169d2ea987e88ed3d56076fef75095d629a0259b91fdba98857a138f24f651b4e78bd8993934dc960f64c174fc75ad5d5e3dbda6cc646efd84790f284696fd936e452bc6565bd052c45cbc77b22ec102d6b63f7b9e0dadb17d6fb1a9ab6338f327000000000000892c2732dfc03ab319b233310ec5244c9128ae882de3aea2bdc3176af20ca492837a3dc049e76f6576d4ced31e6e25fa8ebc43f78c2bccc0eca2bf0f3b9d57aa774338dc22f066708eace05cd4f8e489e5c9caf02a44dc6fcf888b8f32b786b9882b00000000000000a66fec711e683c264adcf7964ad7925227f1c379c6b70b855ad8f813336f0aa60df43eb06470a36e5e0d6981480ad56505d6495a343be33ad238d2776d97c4092d2f617601989f67e756d30f8ffc26f7a711d36fcf46101fae4ed34b614b7bf6930c000000000000936d18f2e311680f740ae3ca58e911149a131484ceaf26f1cebf3cd6d7f4e0e24be42c8a694882bce99a2c4a409a4196dd1fb446498531a00a714c3ba40d03936ee16976ea331f135f0f1481a7bc75be8bc0e19ae1a95387dbb14d27aea369291a14000000000000a86d8629bf6e0c009d7f5d0e50b7788803d2e3572869990baad5cc811966d7f2f089ff363bc63e9310e4790d0f4df201bbabbbe8de41e2dd7008a342f53171aa2165790f48bbefc1705abacd8ffeca9bc2ee9a6c6485bc8b6c935c45603959c4f63700000000000057175a1744fa9951e3c0f5a78f03f67a9bdd0b6d64fd14cd6719a838eb71679024fef7df151336559b5a3d10bdb5d35cb71f40712124e00af89b6285d76e2f11987bfa2d114d6610e37dd1e62f846091a2f4262c8c8fb336d51b012068ade19e902a000000000000772368ad3e515efe9189670d3cc3d35e351fc8f85570e5ec334f7d603527e33026e4df0b724318bb717e2a5097aa4175b32c692d1f5df5ada2a3dd5e4f82413da7f0a786c95da1e5f188dc03b1e409ba2fbf83965f750847be723d4f9904cdf906270000000000006470913a2bedd0ab9f52af14719548440be3bbbac5e9b4f2151bc4460a275df9f388e5309d5c3cd161e294425751a84af4e32cb7679f39b5f20e3f4f4f98af458aaeb36e86bff59b319bdd050cdbe88b0dcab9f9d342c5f41821ed83df1de8c07f1900000000000000").unwrap(); 34 | 35 | // e(sa, b) = e(sb, a) 36 | // e(sa, b) * e(-sb, a) = 1 37 | assert!(CP6_782::pairings(&input[..]).expect("pairings failed")); 38 | // println!("test pairings{} success!", i + 1); 39 | } 40 | 41 | /// CP6_782 MUL 42 | pub fn cp6_782_pairing_six() { 43 | // test pairings 44 | { 45 | cp6_782_pairing(); 46 | } 47 | 48 | // check pairings 49 | { 50 | // hex![(a1, b1), (a2, b2), (-a1, b1), (-a2, b2)]; 51 | let pairings_encoded = "0ec0176973190029442be14ed3d59b6b1c5edffbedf5b325e3fb4e8e5727390f66efebabe9aded0d53477fe7a8ced0db437cb6e580654119be0eeaa2f31a367d77f44a71c686fba448b83603ce76796e1518038ba606749b019a7571c78096d2dd0d0000000000002b42bf978df0e1d22d7a68c07530a308108f3553075f36664c3e9d38d2375cf59cc2f53f6071068df86635195fcd48f4e8ab36594b22a4111433ca6beb550372f11c2e640fc4e07a7b403ba124037fc81719ddd5aaf43a88f443a4735b09eaf5e813000000000000008a504ab3644e901e852ca8942c5d0a14b79eb7c040bea357f6cc187a0da7ebb33e4f04e052f9cb87440c46934c7c36f57ef065c3b780bc476938caf9c87dd4c2e35da0fa31756f15dbe8e8ab1953941a71d768b35101b994ec59752450ad6a60c821000000000000c2ecaf0b48c7435fdc25cffeef75758a2d2eea3e431f5aec9a637d2fa3d8db5cfbe38353e0665a2787059a624f0490c4689d3821775719d700eb1f6222406f02e2ed5ef7274d77a79f088fb15340e9fb300903ae9b3813f54c707791907528108233000000000000ec7001c6219c30a2fd217740a9a5d2aa39c5047243caf2cf010c466b74849c1e62bee8ead6029757d79d5e17821d93687bf8be7c350c28b075042b89395729d03125dd5492c75350b9e8812d3fdb78d5daa5555fa500b15faf6d5f3f0532884dd30900000000000093dc5cd7f3d516a1f18c45c974e5343ae16b2a3193948915dfec95d3874ff35f281a43e1f56278d1f315dc8e695621faaba04c56743c22307964df8a949acabb4e978b6c3efa56135736b92284b3468317791ef0bb67c60c7c443cff579c2f778e15000000000000889c75a94a040308c74bd6ed410915953ea32600eca23c4e5c065266566cb98e7f8cb5491cfd20fb64d62f0bab43391030424044fa983b3daad21034671907279c37f5f3a5ec436c8341957b27f1946cd939511559517b3472a4bed80112ebf3c9090000000000006124bd24fe662ad8fae7bf207c5e5446ecda7cd75a35111bf2dd7ba59e59eb189d67f67170e7c5b9afcd1ccaea422ec3d317238556892cd8719dddbf65aabd416c7be064648945c0953fc0e8bcf2a3c1d3e5838d214ce6e13b8dcd26cae6d236841b00000000000000a63b7bc10341614dfacc7e9db193fa858525277226eaa9f63d549a8167ffb197938dfe267f4dc00417d11706e808767e32c5bf061df779eafbd53afc8d046b988a0fc218fdf5ad00fbe269ca91d98f280ef417c446875eafb066c21d42c8073d6433000000000000e97e981e057a1f9c3acc8fdd3d5c023799c3cfc9306d80ca4d62b78ab4fc1da2bcb77e5c699f4b4e4279c6a45aa4c497720d7924f3ece540b425c8e7df30fb0b14800a48af97c682c13312e2fe3ff7387cda9c01c0f0a89fd9386441735f82104f26000000000000009574222721af4a64fb76392a7068f7e148582687ee50b42965e5494f91c6bd50c01badb90e6ececd9c667feaa73e1f30b4b0b96edd4c3410ef6c33aa5c3fd25946fdf3732402439e5d0765894a18d11a0f9b0b59352e21b3b5f991adfa99bc124d210000000000009f86b939ee2907f968c8ccadfc3698ae0a3d676a44c1bd6afdbd7d2050c5e7e8ab40bf5d9dec914aa08fc3c364d7b891a915d93924c29a239dfcaa75857aa9bf49b235b28cfd95bfd39d33c96d7b3d8db52d641e5e869273c6586f4d2fecfce9b02000000000000081b8163e6b0f6f2533d8636086ece848ba74aec8ae3a2c431ad80d9e2cf8a97d45010ae00f3f410050283764ad09b2eb71aa53da5ae78e25fb85c4d2375da56f93fd050d580af0559053684e42a1442df9e30ad2989a2c194def7cda006af0099930000000000000962ddad8a29b32221d25a4cf0b362d489540bc912335afc5b8bb30a4d805bd42f002ccfb6eaee9d0d232ba721c7022e30c061e6e10513fb9130ec5ad084e23736e8d97d7edda6a60725067b95c19ac3d08916be4ef3a960f163daef3204a019f1a0f0000000000008512c486050cfa97b6058ad7c8bd08dda3ce1310339d565d0082d1a45e612c458ecaf61f9e8bcc90472f8d3828fe5998cda1e8a6866eacc7321887501c569d5a8096b66e2470f37a7506b449e2cb29f86633f89c88ba20b09392fb6416fdcf34200e000000000000d0d2b6eab9b1e1c70835cd8f7a1a40c8b4dbb945697d8a21f0f6c69f251935a0ba9eceef183851e906ada02dcf246d191efa99f2388df5537483a1307cfeb7bce7f7b4102c2ffc7e6cbe7afa47c372e38735566e92a984e5a25632658c70ce5c3f36000000000000000ec0176973190029442be14ed3d59b6b1c5edffbedf5b325e3fb4e8e5727390f66efebabe9aded0d53477fe7a8ced0db437cb6e580654119be0eeaa2f31a367d77f44a71c686fba448b83603ce76796e1518038ba606749b019a7571c78096d2dd0d000000000000bee8d4e32789ec071dc894ad4b55ba4ba797170cfffcdc87ffc326da773ed3a69ca7085da4c1ce8d27ac66ae182e5b5ea9ab45087d74919977a42f15a21c09111620d40ddf5f91efaaaf2fd34614def34b4d75b992331e612b505438e01ce8ce5f24000000000000008a504ab3644e901e852ca8942c5d0a14b79eb7c040bea357f6cc187a0da7ebb33e4f04e052f9cb87440c46934c7c36f57ef065c3b780bc476938caf9c87dd4c2e35da0fa31756f15dbe8e8ab1953941a71d768b35101b994ec59752450ad6a60c821000000000000c2ecaf0b48c7435fdc25cffeef75758a2d2eea3e431f5aec9a637d2fa3d8db5cfbe38353e0665a2787059a624f0490c4689d3821775719d700eb1f6222406f02e2ed5ef7274d77a79f088fb15340e9fb300903ae9b3813f54c707791907528108233000000000000ec7001c6219c30a2fd217740a9a5d2aa39c5047243caf2cf010c466b74849c1e62bee8ead6029757d79d5e17821d93687bf8be7c350c28b075042b89395729d03125dd5492c75350b9e8812d3fdb78d5daa5555fa500b15faf6d5f3f0532884dd30900000000000093dc5cd7f3d516a1f18c45c974e5343ae16b2a3193948915dfec95d3874ff35f281a43e1f56278d1f315dc8e695621faaba04c56743c22307964df8a949acabb4e978b6c3efa56135736b92284b3468317791ef0bb67c60c7c443cff579c2f778e15000000000000889c75a94a040308c74bd6ed410915953ea32600eca23c4e5c065266566cb98e7f8cb5491cfd20fb64d62f0bab43391030424044fa983b3daad21034671907279c37f5f3a5ec436c8341957b27f1946cd939511559517b3472a4bed80112ebf3c9090000000000006124bd24fe662ad8fae7bf207c5e5446ecda7cd75a35111bf2dd7ba59e59eb189d67f67170e7c5b9afcd1ccaea422ec3d317238556892cd8719dddbf65aabd416c7be064648945c0953fc0e8bcf2a3c1d3e5838d214ce6e13b8dcd26cae6d236841b00000000000000a63b7bc10341614dfacc7e9db193fa858525277226eaa9f63d549a8167ffb197938dfe267f4dc00417d11706e808767e32c5bf061df779eafbd53afc8d046b988a0fc218fdf5ad00fbe269ca91d98f280ef417c446875eafb066c21d42c8073d643300000000000000acfb5cb0ffae3e10766d9083295b1d1e637d95d5ee9223fe9f0c88957911fa7cb27f409b9389ccdd99d5221d57dfba1f4a033dd5a94f6ad7b13199ad411177f3bcf7293f8cabe764bc58926cd76583e78bb58d7d37b049465b946ac8c64fb4f911000000000000009574222721af4a64fb76392a7068f7e148582687ee50b42965e5494f91c6bd50c01badb90e6ececd9c667feaa73e1f30b4b0b96edd4c3410ef6c33aa5c3fd25946fdf3732402439e5d0765894a18d11a0f9b0b59352e21b3b5f991adfa99bc124d210000000000009f86b939ee2907f968c8ccadfc3698ae0a3d676a44c1bd6afdbd7d2050c5e7e8ab40bf5d9dec914aa08fc3c364d7b891a915d93924c29a239dfcaa75857aa9bf49b235b28cfd95bfd39d33c96d7b3d8db52d641e5e869273c6586f4d2fecfce9b02000000000000081b8163e6b0f6f2533d8636086ece848ba74aec8ae3a2c431ad80d9e2cf8a97d45010ae00f3f410050283764ad09b2eb71aa53da5ae78e25fb85c4d2375da56f93fd050d580af0559053684e42a1442df9e30ad2989a2c194def7cda006af0099930000000000000962ddad8a29b32221d25a4cf0b362d489540bc912335afc5b8bb30a4d805bd42f002ccfb6eaee9d0d232ba721c7022e30c061e6e10513fb9130ec5ad084e23736e8d97d7edda6a60725067b95c19ac3d08916be4ef3a960f163daef3204a019f1a0f0000000000008512c486050cfa97b6058ad7c8bd08dda3ce1310339d565d0082d1a45e612c458ecaf61f9e8bcc90472f8d3828fe5998cda1e8a6866eacc7321887501c569d5a8096b66e2470f37a7506b449e2cb29f86633f89c88ba20b09392fb6416fdcf34200e000000000000d0d2b6eab9b1e1c70835cd8f7a1a40c8b4dbb945697d8a21f0f6c69f251935a0ba9eceef183851e906ada02dcf246d191efa99f2388df5537483a1307cfeb7bce7f7b4102c2ffc7e6cbe7afa47c372e38735566e92a984e5a25632658c70ce5c3f3600000000000000"; 52 | 53 | let input = hex::decode(pairings_encoded).unwrap(); 54 | 55 | // check pairings operation:(a1*b1) * e(a2*b2) * e(-a1*b1) * e(-a2*b2) == 1 return true 56 | assert!(CP6_782::pairings(&input[..]).unwrap()); 57 | // println!("test pairings e(a1*b1)*e(a2*b2)*e(-a1*b1)*e(-a2*b2) success!"); 58 | } 59 | } 60 | 61 | #[test] 62 | fn test_cp6_782_additional() { 63 | // zero-points additions 64 | { 65 | let input = hex::decode( 66 | "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001").unwrap(); 67 | 68 | let res = CP6_782::add(&input[..]).unwrap(); 69 | 70 | let expected = hex::decode( 71 | "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001").unwrap(); 72 | 73 | assert_eq!(&expected[..], &res[..]); 74 | // println!("test add1 success!"); 75 | } 76 | 77 | // one-points additions 78 | cp6_782_add(); 79 | } 80 | 81 | #[test] 82 | fn test_cp6_782_scalar_mul() { 83 | // one-point mul 2 encode 84 | cp6_782_mul(); 85 | } 86 | 87 | #[test] 88 | fn test_cp6_782_pairing() { 89 | for i in 0..5 { 90 | cp6_782_pairing_six(); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /tests/src/arkworks/bench.rs: -------------------------------------------------------------------------------- 1 | use ark_bls12_377::Bls12_377; 2 | use ark_bls12_381::Bls12_381; 3 | use ark_bn254::Bn254; 4 | use ark_bw6_761::BW6_761; 5 | use ark_cp6_782::CP6_782; 6 | use arkworks::{ 7 | groth16::{verify_proof, Groth16Parcel}, 8 | verify, verify_parcel, 9 | }; 10 | use num_bigint::BigUint; 11 | use num_traits::Num; 12 | use parity_scale_codec::Encode; 13 | 14 | #[test] 15 | fn test_based_bls12_377_mimc_groth16_parcel() { 16 | let parcel = "08850171c5a779bb19e0aeb6030768f5001017bbd4edb645306ff1591424c501e7aa8b480fc18d8ed404c893d473afa9b82c01fb3e19bdf85f4fb8acf97d1507b75eb48972c8a10e13f4637f7bee71f89eafc141453e4646c82e188d9ef8cf71fa2f000085014d0869345487bb4070110fa318b0f408dcffce12304589878797615d8a72cc00b6a1e3f50cc0e59770638640090726013db560d3a19288ecedc60ed9ee0afd50ad3ac96db89d99fc249b85a453ef837e9213f8977ac572d818dc43387678a50100910a54f796d78550d14c4ee03cd5915fd8037569696f878312b0093f0149919fc717c0b3f8a2d419fad0edde7e1d55cd2f002c312b660250225a00baf5df511dcce61eb23b28f3980be7fcde0091284670e9064015f452f244e65cad047a20fdd000ca76892d04e1283e575e098c8e4281ba9113443515f22247921b9c3189dc03dd83cf22b9da3eda70cdd2644a795376002e0b1d0d1d5945dab12a28a31497b48d07739028ac3153be3cf367e3d7e788ac43f6d3ccd3c5c20a4f2d6b0db05ce40000f70cb4191a256ed9a4d90305f5864993032a0e40433040c259b14c8069d117f3491d75d993271a0a3f13efdd5b18ce006d90eff3b45f8fa10b43a2d4fb80a554304ba5d94ddc19c92b2e1e2f756bd3042c4c0d6e10b6c22c2ea5eb136fb42900aca080ed5cfa9ccf92da7e4f631f1f9fd52a4dd227898e21585a7a55656f6315fa3f1e541011b941084fb663515ede0024ff6c7745872af24c5de2acfbf4b7a238f3f80face2310d83d9e953de2051a70abc3be988220291e03c92840e1c1c01005720823639fe8f3818ade6c24c6d6ed8f78b87369a9fac8a548e01ca001e424ba931033958641fe06677c3f4a1b39f01f6d3e9a2052ad1185af9a80086665df50b41674f7f6f181773cee6e78d09ea34ce970ccb5907d5cb2f69c9e0ed8d1f01009d629094c47bdf026bbd3424f6e7748b0c3529b495cf24677f309d9f1ed7d3435513224cba204902fd733522b3b855015f395e5b2a7f0fe9e50665d705c48f9b8b20a3f9619f50c1dcddbea7c4a561cdffed750045f875b2d2c569e8d5d0320015e739c8881a211865f82e39bb6ad21a66ceb1808a5ecc3f11833d61dc938a3b160b1b1829527b52e9d3d98800f29701078dfc5fda2f3dcebaca0f43ac23f6da5044f51cf12ac8b3439df503ab1732f5047601b2cd9d93e6d161dc4719beda00000d06e2342d048b06618cfc80a5fb5301373032d5780ca45e5287e824fd1d3dccfc36d1befe73edaea7378968a003f94e1801de729f41f406c7d94db4995cc2956cdd6b250937dd52b3c8ac812dff25985eb802c727dbfb7c6b055db545d687b1bd000090f4ad7dc16060ebfbe2bff08077e404e878850682e15f64a5b0f243f53a6d61dc358d41fa6aed615c6296904d71c200c04fe75b3adbecdc3d00df22556a1c949e4b87c81483225f6eaa7560e3035a1c919c4a0d446125dca2e2ef541d58a200ec9b0644bea1bd34e84ff04b65c0cc8733d425b43225f81a7580e1027a41b4ce85eb513213f54a76e2b69320dc6d51003b06cb148aa149b0b0e1ffb8f5901adbda3e431c19404cae29f26aac97085c6d1d8eeef33024aafdc649da6475ab99000026b3bb740a34b4db3a1c689d471b5a7834bb27fd57108bca8cd88d12bb81eae5f8ad807e5de758978ab51d0146017100c31d5c7971576e79eec56286dc2602025cb1d0a01e1acdc23a8aece6e9f3c3ecf97d0a9667634e31e79f653a93c13b01000480a4961fec1c734055a80af91b3fd7405a2cdb741e1867aa7f783ca0959a077110"; 17 | assert!( 18 | verify_parcel(0x00, hex::decode(parcel).expect("decode hex failed")) 19 | .expect("verify proof failed") 20 | ); 21 | } 22 | 23 | #[test] 24 | fn test_bls12_377_mimc_groth16() { 25 | let vk_ic:Vec> = vec![hex::decode("71c5a779bb19e0aeb6030768f5001017bbd4edb645306ff1591424c501e7aa8b480fc18d8ed404c893d473afa9b82c01fb3e19bdf85f4fb8acf97d1507b75eb48972c8a10e13f4637f7bee71f89eafc141453e4646c82e188d9ef8cf71fa2f0000").unwrap(), 26 | hex::decode("4d0869345487bb4070110fa318b0f408dcffce12304589878797615d8a72cc00b6a1e3f50cc0e59770638640090726013db560d3a19288ecedc60ed9ee0afd50ad3ac96db89d99fc249b85a453ef837e9213f8977ac572d818dc43387678a50100").unwrap()]; 27 | let vk_encode:Vec = hex::decode("54f796d78550d14c4ee03cd5915fd8037569696f878312b0093f0149919fc717c0b3f8a2d419fad0edde7e1d55cd2f002c312b660250225a00baf5df511dcce61eb23b28f3980be7fcde0091284670e9064015f452f244e65cad047a20fdd000ca76892d04e1283e575e098c8e4281ba9113443515f22247921b9c3189dc03dd83cf22b9da3eda70cdd2644a795376002e0b1d0d1d5945dab12a28a31497b48d07739028ac3153be3cf367e3d7e788ac43f6d3ccd3c5c20a4f2d6b0db05ce40000f70cb4191a256ed9a4d90305f5864993032a0e40433040c259b14c8069d117f3491d75d993271a0a3f13efdd5b18ce006d90eff3b45f8fa10b43a2d4fb80a554304ba5d94ddc19c92b2e1e2f756bd3042c4c0d6e10b6c22c2ea5eb136fb42900aca080ed5cfa9ccf92da7e4f631f1f9fd52a4dd227898e21585a7a55656f6315fa3f1e541011b941084fb663515ede0024ff6c7745872af24c5de2acfbf4b7a238f3f80face2310d83d9e953de2051a70abc3be988220291e03c92840e1c1c01005720823639fe8f3818ade6c24c6d6ed8f78b87369a9fac8a548e01ca001e424ba931033958641fe06677c3f4a1b39f01f6d3e9a2052ad1185af9a80086665df50b41674f7f6f181773cee6e78d09ea34ce970ccb5907d5cb2f69c9e0ed8d1f01009d629094c47bdf026bbd3424f6e7748b0c3529b495cf24677f309d9f1ed7d3435513224cba204902fd733522b3b855015f395e5b2a7f0fe9e50665d705c48f9b8b20a3f9619f50c1dcddbea7c4a561cdffed750045f875b2d2c569e8d5d0320015e739c8881a211865f82e39bb6ad21a66ceb1808a5ecc3f11833d61dc938a3b160b1b1829527b52e9d3d98800f29701078dfc5fda2f3dcebaca0f43ac23f6da5044f51cf12ac8b3439df503ab1732f5047601b2cd9d93e6d161dc4719beda0000").unwrap(); 28 | let proof_encode:Vec = hex::decode("e2342d048b06618cfc80a5fb5301373032d5780ca45e5287e824fd1d3dccfc36d1befe73edaea7378968a003f94e1801de729f41f406c7d94db4995cc2956cdd6b250937dd52b3c8ac812dff25985eb802c727dbfb7c6b055db545d687b1bd000090f4ad7dc16060ebfbe2bff08077e404e878850682e15f64a5b0f243f53a6d61dc358d41fa6aed615c6296904d71c200c04fe75b3adbecdc3d00df22556a1c949e4b87c81483225f6eaa7560e3035a1c919c4a0d446125dca2e2ef541d58a200ec9b0644bea1bd34e84ff04b65c0cc8733d425b43225f81a7580e1027a41b4ce85eb513213f54a76e2b69320dc6d51003b06cb148aa149b0b0e1ffb8f5901adbda3e431c19404cae29f26aac97085c6d1d8eeef33024aafdc649da6475ab99000026b3bb740a34b4db3a1c689d471b5a7834bb27fd57108bca8cd88d12bb81eae5f8ad807e5de758978ab51d0146017100c31d5c7971576e79eec56286dc2602025cb1d0a01e1acdc23a8aece6e9f3c3ecf97d0a9667634e31e79f653a93c13b0100").unwrap(); 29 | let public_input: Vec> = 30 | vec![ 31 | hex::decode("a4961fec1c734055a80af91b3fd7405a2cdb741e1867aa7f783ca0959a077110") 32 | .unwrap(), 33 | ]; 34 | 35 | assert!(verify(0x00, vk_ic, vk_encode, proof_encode, public_input).unwrap()); 36 | } 37 | 38 | #[test] 39 | fn test_based_bls12_381_mimc_groth16_parcel() { 40 | let parcel = "088501e60f6032ed7f170ba3481c5d99c0890554c808ad380a7c9aefc9e62eeecf0363ecef5e59ba8eaf6dd0af40e08d7cfd024314f90080a1461a207aa3098308149837bc6322a8f4b499671c507203e798f90a9aa8fafaebb806c8708c3207a93316008501ea7f398187aecf2721441218e54645b17acd35bdf65886255e772a58353ef2e25c92cf7f872bea5afca6081d03e6b115e74befd85720c241ee5ef038621a1cc72e329db9aebec0faf480e83cbd9e4b735650ab0cce2e321d64311bd34bca9e0200910a9094c864d37f890720969430f2682ccc76dc83f9234694590bd334b40dbfa7f28de40e914571d8ae2a88712844f86f0d6dd2f4875120f66304bfcedd55c9a805310155a5345ddc626cbb6fe5ce7026be174a08c798e4d1f1010f97138c30b10a0e23d3cde62852c7b2aabcd7603f87fc54cb0c2fcfa48a1a6e07ea917eec248284a1409dd21ae7bd64b862e7df91fd0af1f36857260a843ea18cd393172b91196ca17bc5f37efb126d585abfcf23b8438d72f90365c382b661256d7caa361d07000c06c5cc02155140b97283cc024daf57023a781a9115bb6e17350264f8b52784a6008921402af8c05dd39f4b789bd50435d2c5aefeb6dc9817af41f45779e3a2d80ab98ef923723b938566747c10a4a169ca5097c5d5073449c3d2e65e16291850a5721416e102df69729ffab67cf948ca51c4ac4c2b54c521552fd4a5a5462d6d3b77ba9932aba0fda8ea8da76e5b0b9166ba600f9c5cc5e442b64ed560c126f8b88e2761c0c6a17a4dcbc1a132a975683ed0b6018ac45d7f4942ad7831790e00408697568bc15871da494a2fe12199531130a8a5b96f07c69020dc01bf9f3ed043a6e1bd08f8d7826c7d5c0fc5c771195ab91bf6eeaa33cbd89cd7dce7930b383c2453d0cca5c227e1b97b1ae253e40cadf4468d6d86f0bf69a0b0bb55774219005b6d86316ea7c1dc4df3e3396a9f78aadf416d5af1619883f5dbbf0a39c6743b194e5adedda54d7cb3ae33e556602e19dd43a31bca7bdb15ad5245dc1ad0affb97edc8f35bb00d1c5b417a132d5be9b72a39870193b6a142198a888c0fe3760fdf1467c7208394270f2aff044c5c002d6cf189a28e34851dc434933e73e07482dad6c7ab931bfbdf29f5d51a6a866d028b91cd89abc9728cf2f8e139f612b5a248ca0758365d1d83c6bc299152b15a89b136e804ae71174d4f35970be570fd14000d06fcafa9753aee681f006d7bf6fc885dcc1a70c33bbfe92bb581ac51e1325b782b1128b1586767cb2ea27555e243abd213634b87418421a65002e06fd9347b23205761d7e35a2a83ffcd35b16b6bf23982700597f2ed9706ae5e039542e8eabd1800443cc8d6ffec17c44207dd41e8ab2f2f2c663f5ed9ab724321de43cbe2ea81908c13643c42a41be1adbc5076e4927b13046d3cdaf5ef775ee48d842599508178276cd41d30e289cbd1d2bb9f92f59b520138fef3e9529139f3961f40f6ea92113ed1701b0eb62a8b21b0852f5ae0d23b4d8cf7a02a69b04abbf0b9213cc1cd16b0afed74a09f1d965f72e0faaad60215c2788b9672a8f53fb90d44b47fb16e4f97f910226d8ad46ddc1dfa6eb4f709a3c95ccfa7f4cd1b9ea5f3cf3d10c5dd0200de094abc5e25fac259efcfd79a97401359069cde3b48eaa9d3a4d848959eb269d788a415d9c22fb418459474f1f0fc16f4572ace2876cf1170d400d1d12d588f816023602a077b8fa66293ac19c951b6c572fad4481fa576e362d9f3a0ffa0120004801d6c7850edbac8a5281ab93d2ed245d47b64f20c21950926d595624b488c291c"; 41 | assert!( 42 | verify_parcel(0x10, hex::decode(parcel).expect("decode hex failed")) 43 | .expect("verify proof failed") 44 | ); 45 | } 46 | 47 | #[test] 48 | fn test_based_bls12_381_mimc_groth16() { 49 | let vk_ic:Vec> = vec![hex::decode("e60f6032ed7f170ba3481c5d99c0890554c808ad380a7c9aefc9e62eeecf0363ecef5e59ba8eaf6dd0af40e08d7cfd024314f90080a1461a207aa3098308149837bc6322a8f4b499671c507203e798f90a9aa8fafaebb806c8708c3207a9331600").unwrap(), 50 | hex::decode("ea7f398187aecf2721441218e54645b17acd35bdf65886255e772a58353ef2e25c92cf7f872bea5afca6081d03e6b115e74befd85720c241ee5ef038621a1cc72e329db9aebec0faf480e83cbd9e4b735650ab0cce2e321d64311bd34bca9e0200").unwrap()]; 51 | let vk_encode:Vec = hex::decode("9094c864d37f890720969430f2682ccc76dc83f9234694590bd334b40dbfa7f28de40e914571d8ae2a88712844f86f0d6dd2f4875120f66304bfcedd55c9a805310155a5345ddc626cbb6fe5ce7026be174a08c798e4d1f1010f97138c30b10a0e23d3cde62852c7b2aabcd7603f87fc54cb0c2fcfa48a1a6e07ea917eec248284a1409dd21ae7bd64b862e7df91fd0af1f36857260a843ea18cd393172b91196ca17bc5f37efb126d585abfcf23b8438d72f90365c382b661256d7caa361d07000c06c5cc02155140b97283cc024daf57023a781a9115bb6e17350264f8b52784a6008921402af8c05dd39f4b789bd50435d2c5aefeb6dc9817af41f45779e3a2d80ab98ef923723b938566747c10a4a169ca5097c5d5073449c3d2e65e16291850a5721416e102df69729ffab67cf948ca51c4ac4c2b54c521552fd4a5a5462d6d3b77ba9932aba0fda8ea8da76e5b0b9166ba600f9c5cc5e442b64ed560c126f8b88e2761c0c6a17a4dcbc1a132a975683ed0b6018ac45d7f4942ad7831790e00408697568bc15871da494a2fe12199531130a8a5b96f07c69020dc01bf9f3ed043a6e1bd08f8d7826c7d5c0fc5c771195ab91bf6eeaa33cbd89cd7dce7930b383c2453d0cca5c227e1b97b1ae253e40cadf4468d6d86f0bf69a0b0bb55774219005b6d86316ea7c1dc4df3e3396a9f78aadf416d5af1619883f5dbbf0a39c6743b194e5adedda54d7cb3ae33e556602e19dd43a31bca7bdb15ad5245dc1ad0affb97edc8f35bb00d1c5b417a132d5be9b72a39870193b6a142198a888c0fe3760fdf1467c7208394270f2aff044c5c002d6cf189a28e34851dc434933e73e07482dad6c7ab931bfbdf29f5d51a6a866d028b91cd89abc9728cf2f8e139f612b5a248ca0758365d1d83c6bc299152b15a89b136e804ae71174d4f35970be570fd1400").unwrap(); 52 | let proof_encode:Vec = hex::decode("fcafa9753aee681f006d7bf6fc885dcc1a70c33bbfe92bb581ac51e1325b782b1128b1586767cb2ea27555e243abd213634b87418421a65002e06fd9347b23205761d7e35a2a83ffcd35b16b6bf23982700597f2ed9706ae5e039542e8eabd1800443cc8d6ffec17c44207dd41e8ab2f2f2c663f5ed9ab724321de43cbe2ea81908c13643c42a41be1adbc5076e4927b13046d3cdaf5ef775ee48d842599508178276cd41d30e289cbd1d2bb9f92f59b520138fef3e9529139f3961f40f6ea92113ed1701b0eb62a8b21b0852f5ae0d23b4d8cf7a02a69b04abbf0b9213cc1cd16b0afed74a09f1d965f72e0faaad60215c2788b9672a8f53fb90d44b47fb16e4f97f910226d8ad46ddc1dfa6eb4f709a3c95ccfa7f4cd1b9ea5f3cf3d10c5dd0200de094abc5e25fac259efcfd79a97401359069cde3b48eaa9d3a4d848959eb269d788a415d9c22fb418459474f1f0fc16f4572ace2876cf1170d400d1d12d588f816023602a077b8fa66293ac19c951b6c572fad4481fa576e362d9f3a0ffa01200").unwrap(); 53 | let public_input: Vec> = 54 | vec![ 55 | hex::decode("1d6c7850edbac8a5281ab93d2ed245d47b64f20c21950926d595624b488c291c") 56 | .unwrap(), 57 | ]; 58 | 59 | assert!(verify(0x10, vk_ic, vk_encode, proof_encode, public_input).unwrap()); 60 | } 61 | 62 | #[test] 63 | fn test_based_bn254_mimc_groth16_parcel() { 64 | let parcel = "08050103c2e806d904d8789f0caf1276fc4897bbf2bbb2e7243df2e4bf941ce616790479b410872e3c6f73f481d3e37b861fc1521d4a70457ac41efbe874fe0bf6572f0005014d609323ed564943ba7dfd3b362cc85abf7691dd9957c613fc0d282f258f4d17cd4ddfa713c0a6d4d0dcbfc245847bd6a96fa8603a0c0d55389279cdf2967f06001107f00c5d68983d7c029a66ae498a1cc6a2423bf67760bbf922ea7a937a87705e158db79bbff4eb9516d5342ce8cd8d09f68fa094434edceebbb43383fc415d9b235c64a2bc82ea6fa740441af956bc764eefb6be4067948d2d7afc08d7dc114a2e1c0c46208e6590bed192c336b7d89f55c2eca918e6f4eb88e1c729a10612690900f70bfb6ec84456af219bcd1d682133db3db80b0ae54cf31879e74a0ae547ec0ef92f56757f4a7976c50dc3d538cb1b4ed1736d4e8e8734d5cbf85b2ac8a93d0b654ff74df7e792b9cf0fd9d1b07b6ce4d0675f57bc7e9740e64b56c9f866b309eb428ffdf69b419fc53b9d76f1de62559aedc6db7e8b6ac2f3dd0cc963ca041300cc165291944a7b617bad2e6f1560f89f4e7eb42f154333b730e2f2da7828911d7cd0a28314d647bae049c72d4e0b4f31c1f09177fcab13014e3060a70024cb210094b31d9ebcca3957fff3d94960b0eba2197fabaaa68776e767e8785f63b4541d456d755240d72dae2ee0452c0cd705d7312b9a1d17cff916e87c763d459a550438b765cd8877bf753869e1852a7c0d9ac4520abb2b935e2f3ec12423d9edc5289eba05bed12e9fe16017c86791d682d4ae86d94eeab1d7888845c0fb0af85805000d04cf3bb657065cd0878eabc53790c5fa3680cad24db586bab799e3ae790217c61ba5050a0024f8761028a11dd22dfc030227b0a6c353ef5e7e1afad863c13a3304000227ad22191396e6ffe7aff14de91d7801e943f836de399b5fd5c8312086440c036648b695ffa27790f2f2a63fcf4c0b130e6b88ac786e3351fc6f13452d18034bee420c244cf7c63db4761f2feb7c14e409c8c550a68940cc0387e3812ccb10c4eb591ff3a67a87e794e2e76e25126b823ea9f38f95730951f13784e6e10f26007a922013b86567d6d48ff65baf8cdd0558c52db98f27b6c216df96f8aa1d4d2df7b1ead51d93e93ef5abdff83acaabd54736546f6995083127be1ae281ca5200000480829d3d572251103bac02b39e397c657c0b1f372bfc4d1b74f6c23de4993b4824"; 65 | assert!( 66 | verify_parcel(0x20, hex::decode(parcel).expect("decode hex failed")) 67 | .expect("verify proof failed") 68 | ); 69 | } 70 | 71 | #[test] 72 | fn test_based_bn254_mimc_groth16() { 73 | let vk_ic:Vec> = vec![hex::decode("03c2e806d904d8789f0caf1276fc4897bbf2bbb2e7243df2e4bf941ce616790479b410872e3c6f73f481d3e37b861fc1521d4a70457ac41efbe874fe0bf6572f00").unwrap(), 74 | hex::decode("4d609323ed564943ba7dfd3b362cc85abf7691dd9957c613fc0d282f258f4d17cd4ddfa713c0a6d4d0dcbfc245847bd6a96fa8603a0c0d55389279cdf2967f0600").unwrap()]; 75 | let vk_encode:Vec = hex::decode("f00c5d68983d7c029a66ae498a1cc6a2423bf67760bbf922ea7a937a87705e158db79bbff4eb9516d5342ce8cd8d09f68fa094434edceebbb43383fc415d9b235c64a2bc82ea6fa740441af956bc764eefb6be4067948d2d7afc08d7dc114a2e1c0c46208e6590bed192c336b7d89f55c2eca918e6f4eb88e1c729a10612690900f70bfb6ec84456af219bcd1d682133db3db80b0ae54cf31879e74a0ae547ec0ef92f56757f4a7976c50dc3d538cb1b4ed1736d4e8e8734d5cbf85b2ac8a93d0b654ff74df7e792b9cf0fd9d1b07b6ce4d0675f57bc7e9740e64b56c9f866b309eb428ffdf69b419fc53b9d76f1de62559aedc6db7e8b6ac2f3dd0cc963ca041300cc165291944a7b617bad2e6f1560f89f4e7eb42f154333b730e2f2da7828911d7cd0a28314d647bae049c72d4e0b4f31c1f09177fcab13014e3060a70024cb210094b31d9ebcca3957fff3d94960b0eba2197fabaaa68776e767e8785f63b4541d456d755240d72dae2ee0452c0cd705d7312b9a1d17cff916e87c763d459a550438b765cd8877bf753869e1852a7c0d9ac4520abb2b935e2f3ec12423d9edc5289eba05bed12e9fe16017c86791d682d4ae86d94eeab1d7888845c0fb0af8580500").unwrap(); 76 | let proof_encode:Vec = hex::decode("cf3bb657065cd0878eabc53790c5fa3680cad24db586bab799e3ae790217c61ba5050a0024f8761028a11dd22dfc030227b0a6c353ef5e7e1afad863c13a3304000227ad22191396e6ffe7aff14de91d7801e943f836de399b5fd5c8312086440c036648b695ffa27790f2f2a63fcf4c0b130e6b88ac786e3351fc6f13452d18034bee420c244cf7c63db4761f2feb7c14e409c8c550a68940cc0387e3812ccb10c4eb591ff3a67a87e794e2e76e25126b823ea9f38f95730951f13784e6e10f26007a922013b86567d6d48ff65baf8cdd0558c52db98f27b6c216df96f8aa1d4d2df7b1ead51d93e93ef5abdff83acaabd54736546f6995083127be1ae281ca520000").unwrap(); 77 | let public_input: Vec> = 78 | vec![ 79 | hex::decode("829d3d572251103bac02b39e397c657c0b1f372bfc4d1b74f6c23de4993b4824") 80 | .unwrap(), 81 | ]; 82 | 83 | assert!(verify(0x20, vk_ic, vk_encode, proof_encode, public_input).unwrap()); 84 | } 85 | 86 | #[test] 87 | fn test_based_bw6_761_mimc_groth16_parcel() { 88 | let parcel = "08050329f6308fb1faee384c2deae7744b65d79eafa98a3947df7e35330c73ad0165a2f92844dab884fec1e15e52ac08f9306a1d8e7b4b66f718cece36a90f9aafe59588aafcd6588a55b9c05c3177904e5cbd1e3b59e4077d1caff6329268b5882200e349c8213aacabd50f11abe7f59b68fdd37f17b7fe6cee7ec3d04dca42812df1854c6c14234dd6fb7f64220949439c660ede18a5e79c8a115b942bbb7812b89be516469237a138752f6f798bcaf6afdf261e471f6c808aacd4274293cb8aff00000503639a14c4e08b97d97166d09eff9b57abf973b487fd5f5007c6ccc8adc31dbac74372477c035964e06f06d93e1483fe81ef1b51e525ffad28a053af20271dd363353e7ccd34cd599ac7c8c97fc175e4d9db8b9399db1647f52564757781209b001cc3d1e9665bc2a8b7e82d2d074e595f297df3dff536046353057a150f6a453521182a7219ef5d38ae85efd3b505f16549ed4bd63b7166e3a4f82142f584b3ad3e27c371db05cc0ba8a8f870fefccd9eb6e5635d6684193aa4b60082a0b2ac0000110c73174e4bb9c9b03c5ee9ddf21056832e01546744fffc64a5221e7e5cee09d37e534b27ae3725db7d3706c85b3932b269078f55cf1dd54c6e3247ad9a7619ef71315f5fee37909c44a216246c2ba2889b7b00b7f1298f5fb2776562527f4014008864e0733bfdd0d8f599c8bccd50d2204e3dab1863fc52e8a30476c836c16e3e6f7d098f0b34fd9edde526f9039323dcb0228a5e7c6841dcda703efe88d7331ba7d096b5753f442647e643d8ac9dfdd9d85b44824bbcc29ee8b4596e1cee520000d1e9ebd9d4d430b34703ac55be08c6d63e791dd2da3f7543b5d6db64e6ce9e0cfb031c168e2bede9cbd39070ecb4e1678d41cd0d48b087fa8a324964fded508df2ef48a7a6c21f1fe95e89aa98b00fb59bee1713e4ffaba216f00e5f15d12201f23da7e61729bc8866bcdd39bcd7d74e6cc9f9192b94c45c6753b60cef11c3b0474eaa53b3beaf3ee9f3885a547ae21385b5a5d5f15be620b9f2669573461b56e74dd326b48662cd271d1a21bb0c120f45d6bbdc632261908bc6e3ab4356480000be5dddc202ba74caa75135e9f81338910969729484a89a438090564689177b491e67f8cfa06ecfcee4acfd7cd364e094c1a4d028f7c7e0677d066cdf1355123e976fa498af59e308954054051fb3fabdda4b0d7a165cd454a71c53ff26546d000b193a142d557066f0a66964c249e4ee2d0247969ecfe861014dd4f36956da4c870ff3fbd6e16999cd43dc27c2fb2a5d72c7317dbc22d2f32541c1489a7bf716e698f898299c0ddfd09e3a892d2aa2940eec0b9f0cf63e52d83cd5dba7be50000021a8ba5d55fabd1999a5a9d717008e812486fd4309d9b4fb75ce4d22199360d6f8855d2e55259220392a9a67b9104adfa1424633f0c527b5516535d43c2632e594a118c05394ea735234b998018ac2906d7f24f89226bb07d1229c6000b13900b565ae54006fc9ef616aa866efa0e85b4c8d5a13ee55d60a478a0ea0b0cc29bc1fcab4045b6f980297a1815dcfbf5ad3031a0bb4429ad863f8695719b68208d1cd4e515a2b3129142a4bbdca3c3cde033c6256daa1fb79f133f28147a40c5200000d09cf5ea12a32dc313ec0791efdfca4ffa5dca127faeb57027754f0fcdd0e868623082e4543cae1bb11078c359dabbd4abbb38640c75081dca4aa2ef35bdb5ee4c856465c7b75956b88ab36d940a8df7e13adaa709ee349ed9454c7d6705211020087f361ca8cb2e83018809872a71853f0eb99a989362a3a753edbe4f58feec45c19be03b06567b357ec6779f3756b1494b74d98503d5c67ef3548ca9464d7525a3f92cdf335702a76eaaff83330f9da2c4a84b02a99ce06e0b04a1a0f1fd2f80000335b53718581ba3e14b48e381078551ff535a3d7a1671dc42898e742857f158a27d249a4d3bbe060016acdf3e9bde0095b23e073e40d56027474673321542ab30641f50f61452762d66984e33745d9456c5eba2cdafc07a52525ef1d3e221e00c92be8c3030de0338c27d281e887a63ab927478464faa7e7b0bbc68de44734c20cfd24763b8384fc6a15b2f82bf0349b86392aaa2e6fc2c95c1d0891f83a92d3b2c1deb230316eb43d9ddcbd069e600aff23ef13dd1f7b9cfade33db4872300000d1367d1907cd90da19e25e3241fb83393731c0d6183300675275017cc6287f2154abf2320cdc2cefc9df0383f98688e2e22914bef4fc32136222fb9dde45840de012e91cce1d02fbb6250a342b72c8c4155e0ff2ffa7ee71211f2641e816f200f8e725a65be98dafc395c538b2c1a009af190aedb99ecae9410257b5b295fb757dc7af138db54d06c582021442342f8924e092ae2fbf375fe94d6480910f7154b14aec033bd5cf27a2cdd225282b7a2fcaab6ac338a89d994c45976d9b7fa1000004c028933fc1b649ded455bd7739026be2bf6f7e1c0acde6dee164724218bbf1391e318017e5a6ab8248bda0bdd1f40b8301"; 89 | assert!( 90 | verify_parcel(0x30, hex::decode(parcel).expect("decode hex failed")) 91 | .expect("verify proof failed") 92 | ); 93 | } 94 | 95 | #[test] 96 | fn test_based_bw6_761_mimc_groth16() { 97 | let vk_ic:Vec> = vec![hex::decode("29f6308fb1faee384c2deae7744b65d79eafa98a3947df7e35330c73ad0165a2f92844dab884fec1e15e52ac08f9306a1d8e7b4b66f718cece36a90f9aafe59588aafcd6588a55b9c05c3177904e5cbd1e3b59e4077d1caff6329268b5882200e349c8213aacabd50f11abe7f59b68fdd37f17b7fe6cee7ec3d04dca42812df1854c6c14234dd6fb7f64220949439c660ede18a5e79c8a115b942bbb7812b89be516469237a138752f6f798bcaf6afdf261e471f6c808aacd4274293cb8aff0000").unwrap(), 98 | hex::decode("639a14c4e08b97d97166d09eff9b57abf973b487fd5f5007c6ccc8adc31dbac74372477c035964e06f06d93e1483fe81ef1b51e525ffad28a053af20271dd363353e7ccd34cd599ac7c8c97fc175e4d9db8b9399db1647f52564757781209b001cc3d1e9665bc2a8b7e82d2d074e595f297df3dff536046353057a150f6a453521182a7219ef5d38ae85efd3b505f16549ed4bd63b7166e3a4f82142f584b3ad3e27c371db05cc0ba8a8f870fefccd9eb6e5635d6684193aa4b60082a0b2ac0000").unwrap()]; 99 | let vk_encode:Vec = hex::decode("73174e4bb9c9b03c5ee9ddf21056832e01546744fffc64a5221e7e5cee09d37e534b27ae3725db7d3706c85b3932b269078f55cf1dd54c6e3247ad9a7619ef71315f5fee37909c44a216246c2ba2889b7b00b7f1298f5fb2776562527f4014008864e0733bfdd0d8f599c8bccd50d2204e3dab1863fc52e8a30476c836c16e3e6f7d098f0b34fd9edde526f9039323dcb0228a5e7c6841dcda703efe88d7331ba7d096b5753f442647e643d8ac9dfdd9d85b44824bbcc29ee8b4596e1cee520000d1e9ebd9d4d430b34703ac55be08c6d63e791dd2da3f7543b5d6db64e6ce9e0cfb031c168e2bede9cbd39070ecb4e1678d41cd0d48b087fa8a324964fded508df2ef48a7a6c21f1fe95e89aa98b00fb59bee1713e4ffaba216f00e5f15d12201f23da7e61729bc8866bcdd39bcd7d74e6cc9f9192b94c45c6753b60cef11c3b0474eaa53b3beaf3ee9f3885a547ae21385b5a5d5f15be620b9f2669573461b56e74dd326b48662cd271d1a21bb0c120f45d6bbdc632261908bc6e3ab4356480000be5dddc202ba74caa75135e9f81338910969729484a89a438090564689177b491e67f8cfa06ecfcee4acfd7cd364e094c1a4d028f7c7e0677d066cdf1355123e976fa498af59e308954054051fb3fabdda4b0d7a165cd454a71c53ff26546d000b193a142d557066f0a66964c249e4ee2d0247969ecfe861014dd4f36956da4c870ff3fbd6e16999cd43dc27c2fb2a5d72c7317dbc22d2f32541c1489a7bf716e698f898299c0ddfd09e3a892d2aa2940eec0b9f0cf63e52d83cd5dba7be50000021a8ba5d55fabd1999a5a9d717008e812486fd4309d9b4fb75ce4d22199360d6f8855d2e55259220392a9a67b9104adfa1424633f0c527b5516535d43c2632e594a118c05394ea735234b998018ac2906d7f24f89226bb07d1229c6000b13900b565ae54006fc9ef616aa866efa0e85b4c8d5a13ee55d60a478a0ea0b0cc29bc1fcab4045b6f980297a1815dcfbf5ad3031a0bb4429ad863f8695719b68208d1cd4e515a2b3129142a4bbdca3c3cde033c6256daa1fb79f133f28147a40c520000").unwrap(); 100 | let proof_encode:Vec = hex::decode("cf5ea12a32dc313ec0791efdfca4ffa5dca127faeb57027754f0fcdd0e868623082e4543cae1bb11078c359dabbd4abbb38640c75081dca4aa2ef35bdb5ee4c856465c7b75956b88ab36d940a8df7e13adaa709ee349ed9454c7d6705211020087f361ca8cb2e83018809872a71853f0eb99a989362a3a753edbe4f58feec45c19be03b06567b357ec6779f3756b1494b74d98503d5c67ef3548ca9464d7525a3f92cdf335702a76eaaff83330f9da2c4a84b02a99ce06e0b04a1a0f1fd2f80000335b53718581ba3e14b48e381078551ff535a3d7a1671dc42898e742857f158a27d249a4d3bbe060016acdf3e9bde0095b23e073e40d56027474673321542ab30641f50f61452762d66984e33745d9456c5eba2cdafc07a52525ef1d3e221e00c92be8c3030de0338c27d281e887a63ab927478464faa7e7b0bbc68de44734c20cfd24763b8384fc6a15b2f82bf0349b86392aaa2e6fc2c95c1d0891f83a92d3b2c1deb230316eb43d9ddcbd069e600aff23ef13dd1f7b9cfade33db4872300000d1367d1907cd90da19e25e3241fb83393731c0d6183300675275017cc6287f2154abf2320cdc2cefc9df0383f98688e2e22914bef4fc32136222fb9dde45840de012e91cce1d02fbb6250a342b72c8c4155e0ff2ffa7ee71211f2641e816f200f8e725a65be98dafc395c538b2c1a009af190aedb99ecae9410257b5b295fb757dc7af138db54d06c582021442342f8924e092ae2fbf375fe94d6480910f7154b14aec033bd5cf27a2cdd225282b7a2fcaab6ac338a89d994c45976d9b7fa10000").unwrap(); 101 | let public_input:Vec> = vec![hex::decode("28933fc1b649ded455bd7739026be2bf6f7e1c0acde6dee164724218bbf1391e318017e5a6ab8248bda0bdd1f40b8301").unwrap()]; 102 | 103 | assert!(verify(0x30, vk_ic, vk_encode, proof_encode, public_input).unwrap()); 104 | } 105 | 106 | // #[test] 107 | // fn test_based_cp6_782_mimc_groth16(){ 108 | // let vk_ic:Vec> = vec![hex::decode("c48ff48ce582dd0409ce0fb2177bb3a7e4322834bb56e8fb8fc3d50a65572b3a6200b5748635ede9204a0b4e911519067676c85d0768f7a1f6b03445f68ac6f82cbe2d47f10aa57f3e3f8d2d3a43010b60079b70df128becf4518039b80c13ce431a000000000000abd8d3e618010dcd329e6e3f9470b0504ed6e95ada2b26ec6594419dded5c12faf0589b381e11fcca4c7b2bc9eb03a93193cbb23eb15173959030a86187872af8b6c9e2602bae60025412bb7c75de32b53017c9252e6aa2842a9f72d548fda437f2900000000000000").unwrap(), 109 | // hex::decode("1a8b290c5f2538096fba7a0917d8686fac6ca5e50d6b324eee1687add10707a88c41e32d4178d38bc589017731b8b04377b8898fd468accca55dbd19ebb0b7e82f05fd99b31a18818100d2838c14d584004741ee00b0036ad1ebda8b126e53cd09280000000000001ea05e7f36a04e39562ad190d0a50a3be9010dbfae4d7c3c3fd26a1023bc061bd3e64bc0f1cbc6281fa02a8b99a75cb67a4a62e5b65fa1d814a2388bed2e41b8974c816cce13f6aab8d7b3321d42ff54e994ea55ba3634dbc082dfa32cd4180d580900000000000000").unwrap()]; 110 | // let vk_encode:Vec = hex::decode("e7d7500319b8172c363344e454fc7a98b63434c7aad7c6b95a149ac3654bb4594b4dfcc6ac217c5b2f4748b70eecac7a42125332063cb8293f9e6915073557fc39d21a9cbc2b07e211948553b00cb385318a9879a632b01343cf5d1b1bf438f52807000000000000da4107f784023629cf487e70826f0577e0ac24a4d4f55bd38de553c997b7d42c3406ddd1cd912576e15c09688b3e8f13ec9793dfadc54bcc094c9f178fd311ef0ea5b658c07d8db82995d2a0db84a92bc90fafb359d8d8dfedc3be44379539106c04000000000000e939926c00c1209e8bd773750f7912e41a4af0629e60935193f207e9369f6eab458db8613e3dab560b0f4a379ca5deaade0c20a545ed63c2f41949b8e91f3ba39a2cfe0ea88d874268bb64831e9bf1575c4e19a550156336e46a711a7414af37d401000000000000be4e3bf4ab5f6a6bcdd42d98ae765b7ed2f34650ca01196e7767c5ac1de33b6efe65fb1734b83d56031366032e2cb0e956832780fcde270b664558636b40c764ac0214e359397fc57dcddfeee2de10c5ba4cf56fe1c010327b481968023ac382881100000000000047f6352fe1dceddcb5bd057cb736dfac7ce5b41558dbddc90deaa8326a01002d12f01e13f6c9457fcecd7b8af5be3edb5fa1dae8c3f307bfe22b9e39c8ba571ad1cdd75d1f6b4874b6aa30e47d90da73d0e8d5882f16d3165b3072430e7f73cf021a000000000000a4934f0fddbb98dde0d3c77b92f6a897a28c2975ff8f725f285b46272560ee48918c0a3843b778c3a5bf48ca18b7c1ac0d80e0dd84a4daf55413082c15b31f7a59dd3cdc9d69e2fbfce725b187bdefc00af3ecf9db3c6da1ca4cdfc8414984d2a609000000000000005c355a27626a9c17a0cec016248fff40d918d7ce107f8610181717ff082ec0c607cd7aa66b285581a8ee04fde7330e8b64077ca0d653d30e8a75b94b95e979b77874d5513f2edf83e1a19e881cd770856cc77dbd13d79c6db397f4b8935f47d70c1c000000000000c55b26461ff731b6083453ef1a038456be49a38c18e816cfe41b44c96534ad1fe395aae9c6f02770e9692ff3f421d72b6b8f73662bb8e8f57654cf553157a87b306cffc1aaf04b91a605e4f82de78ea94275c1f7abf5f3e3b65dc7c6522e40c4da2e00000000000094664d44979b9f11cee139dba7ffaa36088d0ed6b43288dcd1b7a9644646e6a28e242050d04d6cfa03d3fd063a2cd451e79111c67148e75aeec60898d781f854a516c7d901b3840dfc9a55b328a23eaf4023bce93640ea0dbf9dbeb15395563d3c0d0000000000009a4fb0fcc1e6874be76dfee1573740d2e1b3240d70b07614478bb06e54fa18ab35e6b56f51a52b7ff06edf85d846e8d3e47d7f3b14da9d4fb625481b5784f77782d8ddf1a8d59df61084954ba0c11c4701704d44ba97792ab7ce2fc6926f8c3df32d0000000000009b130e16554c582f463e0dacd63b631c6cbc4db944ac7ab4838372f5cea0f9630f7eab7730f19f9b592fc38b66de23e49f3ba156d0d7c0baefd6c779b39084149d72f2b6461014385c84be7732353fa439010b56ad7bd3a4aeee2babd3cdc77baa0f000000000000cf447707e8ec2cdae95628420927030638195e67b8f8080293c55bebc614ea6ecced54a0fe6196bcc6aca911879473d2caccdc0af5a64e41d01f614cc4e656906f309244d58a73f1a35d982179a17dfc0dcc7d297b633a0ccefb492b314b573176320000000000000035e3dea242b0c3cdda2e8a3b0a4b901811d69d1d466d2cc07ae3082bbc3a9c67e07fa27809c3cdceeb7352fe833bf77dd221c3508bd88e24c573b7336104fc242b487c7985f7be1bf98da87ffd66482c1a96eed8af743aaebe296d3ad2a08486ef2b000000000000f2fc9fb59c72c192209cea6c75e9bc20deeec4467a15d360419f10f9b80abd5c630a9463c976a1b9544f52e241acb36313439df4d8f550626d35b8d69fd37062a17f920373f11106e52bcd37b3408cfd48e86c1f54b1502fc904edf83f07b0ef211d00000000000000c5a253cc7eb998c104b193531cd7b713757ee123f63b53dc2366a81365d9b1f7e3eb25af832505e4776261aa487cacd46f4edfb43f556a767ed77fe1d5cf7b5ad7226b81a431f5a2fcd363a131d26f60b0e3a4bfdc94ed8220d917d1359c7ceb782100000000000029084959c64014f42418e2a25e487e0bd05a3a84db9fcc66f761aa19261e6319063ea1af5bd7ca1e615679d031a0615446290053b8afc46efb35a28bd1d2ea959de350b11fcd90d0778a36c3a93e2bdc47ba40c4d23d20e6ab3da584e1a0093b5c1d00000000000006ccbc6c97f2c2199625181fc65459cebc6ef92244bd69457090a3259a0df9d4a7da67413ec23248385bbdeee6146b49bde117b99d14549dd0156a54005f48b7d67971b88a0e21faa4670ddce10a7bc59a6c2e5fa49f5d764c2e34bce2b42e2cb507000000000000522ea4745b5fc58cff3e327cc7d48e3568cf6a6ba6ce84c47a613c8466f5d28c72bb48b64cf21e8cb533321bdc287d19f1d2b84370ef6372b03bfc3a457247c7277eaed4ca8c8d8205e457c18441882ce92f483836d34d84bdb9c7dc038103484804000000000000028360f48b73719a97daf5f2f0d2e23e263378013b801f5d26942a09c55f277740885c462b94d5c3cc0f96144cf0f225052e08f25a25e5e36c25d0e3d631e0458750f9b0998d6537a4bd3164c24a9260b4d098b78c5ef58094ad5ec2cb647ba5fe1b000000000000afbb585076588466f5f79582ca909a43b6ebe0ef9d439d472e80825bb624afcc3baceb10d73cafe590082fc79b6ae97d35c5bd99454887d0885fa232c600e6d4e8fb45fd35b2807433fd9054a96aec4720df74416e1b70f91848cd6470390beb990f00000000000000").unwrap(); 111 | // let proof_encode:Vec = hex::decode("f77e91cef736ee1cd9b7658315cfdbfbef95d56d2fa6d652454546a11bc903f5cd7f3d04318311b851cdecfb6a68aa299d0ac1ff5c41b3c85d7945c37f65b184a1c108532488cff65b5e050e8a117639a292515e42dddc2282352c36eb6b0b1f67090000000000008d1a2495a7e6012a8c5588f53c2181f64d4882345efed992318edef86049b77757d47b6b0211b3f349e3a7bda8ca5240b8a01f1a12ecfabb5df7dc1422532867b6842febabee0323b4b75c3835868d4771480987e8cef9889190b83ee8c3cd3c2e2500000000000000d3b56af4332486e353cee922e32a7213a3dbc46dab1de1803bddc3af6c3b6de6db54ad3808cb0a1b030a14edf903ad733889c4ac44e3ddf278b993d8dd71310d1c875a81b8ca83fffceca19c9e30b007a09d331398de7e0df71fae8ec2d80a6fc936000000000000b0ca1f7dbed89a490bf38334457cc3690390469f1dba7a9f7ec8eeb74cdac22feea8bc6b8edc5392426d7bf8bb8e75e3f94c04636a89fe6cd218d1ac9d74d259fd6bcdfa6a55a5bd4e8beb90d374fcbae23f071299a5b1ba8e264a46a69e00ace120000000000000c538d2e0fa79a3aff7af0b59d444e7a00910265e1594fe7c5401d65c6116d60b46fe964f7cf2008a96a2d83de1bffa065c61fd0ee9258ec1d5fe54011549c878a08ef335fdabdf9740a85c72114da339809512745e28f6fa6271b2c01c0253dae11e0000000000008343eb8d1346748f3526a357f2ebf40c79b5809018bb1ad0d9e709ff95c941458d5981d21cebeb4a6172804434eebb5cc074a2de06c16ec498b535bd0c612dafff98f55a5cfcc3c8bcf09262cd42dc6ef4e5c6ef4033e186a65a1796cee262c191360000000000002a97e759cc32c7a0c4acfd2bb223edc5e0a7b60ac5fd21d255be3cd7cc75f994a80dbf2aaed52d413d92bd76f212ee27d7049ebbca150b047ee90e143845334f78521ca4e8706d8108e0d30790919fbda763f16265e4d7be4b1e6da2041950ecd12900000000000007ec7eadc046c9bd7793eff1bfefe75cbff48236a367e6ccdd06af87816b6e61e4fe6fb905278e9cf1b8e6884f0e455a52846f6e82631a151a9ce8601a62c8d557dd043b2cfd0bc185978cbe02d3435dc99c51f85b3591b52e3e04d0562147014522000000000000005a03f7a80644e97fc1c64a5aef05a25e1fe6a1c07089af79aff484eff07626ce6f36462a752f7191b1e702dc60e496ad038a60e913e2e3642c0c8e089b3a274ca9aad4fd264e0928641e2c3bddd92d83ce7a07f8a5886592a13c2623ba715b81362a0000000000001be8a85a370bb5ea996b2666994e01d6fd1d0ac71740eaf55ba2bb9a80323e3bcdd9e723f2dae44fbe74f44623c9d5c88ef6c7d04177f5b17781d099882c52927a493b8f45840c706ce795977a72b288ed60155f7e2c99913c03f72eab31cfc82b0300000000000000").unwrap(); 112 | // let public_input:Vec> = hex::decode("28933fc1b649ded455bd7739026be2bf6f7e1c0acde6dee164724218bbf1391e318017e5a6ab8248bda0bdd1f40b8301").unwrap(); 113 | // assert!(verify_proof::(vk_ic, vk_encode, proof_encode, public_input).expect("verify proof fail")); 114 | // } 115 | --------------------------------------------------------------------------------