diff --git a/Cargo.toml b/Cargo.toml index b1dd6f4..5a77f0e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,52 +6,29 @@ authors = ["Sora Suegami"] description = "RSA verification circuit in halo2." license = "MIT" -[lib] -crate-type = ["cdylib", "rlib"] - [dependencies] -# halo2wrong = { git = "https://github.com/privacy-scaling-explorations/halo2wrong", tag = "v2023_01_20" } -# maingate = { git = "https://github.com/privacy-scaling-explorations/halo2wrong", tag = "v2023_01_20" } halo2-dynamic-sha256 = { git = "https://github.com/zkemail/halo2-dynamic-sha256.git", version = "0.1.0", branch = "main", optional = true } num-bigint = { version = "0.4", features = ["rand"] } sha2 = "0.10.6" rand = "0.8.5" rsa = { version = "0.6.1", features = ["serde"] } -halo2-base = { version = "0.2.2", default-features = false, features = [ - "halo2-pse", - "display", -], git = "https://github.com/axiom-crypto/halo2-lib.git", rev = "9860acc" } -halo2-ecc = { version = "0.2.2", default-features = false, features = [ - "halo2-pse", +halo2-base = { branch = "community-edition", default-features = false, features = [ + "halo2-axiom", "display", -], git = "https://github.com/axiom-crypto/halo2-lib.git", rev = "9860acc" } + "test-utils" +], git = "https://github.com/axiom-crypto/halo2-lib.git"} +halo2-ecc = { branch = "community-edition", default-features = false, features = [ + "halo2-axiom", + "display" +], git = "https://github.com/axiom-crypto/halo2-lib.git"} num-traits = "0.2.15" - -[target.'cfg(target_family = "wasm")'.dependencies] -getrandom = { version = "0.2", features = ["js"] } -wasm-bindgen = { version = "0.2.81", features = ["serde-serialize"] } -console_error_panic_hook = "0.1.7" -rayon = "1.5" -wasm-bindgen-rayon = { version = "1.0" } -web-sys = { version = "0.3", features = [ - "Request", - "Window", - "Response", - "console", -] } -wasm-bindgen-futures = "0.4" -js-sys = "0.3" -serde = { version = "1.0", features = ["derive"] } -serde-wasm-bindgen = "0.4" -rand = "0.8.5" +env_logger = "0.10.0" [dev-dependencies] criterion = "0.4" -[[bench]] -name = "bench" -harness = false - [features] -default = ["sha256"] -sha256 = ["halo2-dynamic-sha256"] +default = ["halo2-axiom", "display"] +display = ["halo2-base/display"] +halo2-pse = ["halo2-base/halo2-pse"] +halo2-axiom = ["halo2-base/halo2-axiom"] diff --git a/benches/bench.rs b/benches/bench.rs deleted file mode 100644 index ab5f8ca..0000000 --- a/benches/bench.rs +++ /dev/null @@ -1,314 +0,0 @@ -use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use halo2_base::halo2_proofs::poly::kzg::strategy::{AccumulatorStrategy, SingleStrategy}; -use halo2_base::halo2_proofs::{ - circuit::{Cell, Layouter, Region, SimpleFloorPlanner, Value}, - dev::MockProver, - halo2curves::bn256::{Bn256, Fr, G1Affine}, - plonk::Error, - plonk::{ - create_proof, keygen_pk, keygen_vk, verify_proof, Circuit, Column, ConstraintSystem, - Instance, ProvingKey, VerifyingKey, - }, - poly::{ - commitment::{Params, ParamsProver}, - kzg::{ - commitment::{KZGCommitmentScheme, ParamsKZG}, - multiopen::{ProverGWC, VerifierGWC}, - }, - Rotation, - }, - transcript::{ - Blake2bRead, Blake2bWrite, Challenge255, TranscriptReadBuffer, TranscriptWriterBuffer, - }, - SerdeFormat, -}; -use halo2_base::utils::fe_to_bigint; -use halo2_base::ContextParams; -use halo2_base::QuantumCell; -use halo2_base::{gates::range::RangeStrategy::Vertical, SKIP_FIRST_PASS}; -use halo2_base::{ - gates::{flex_gate::FlexGateConfig, range::RangeConfig, GateInstructions, RangeInstructions}, - utils::{bigint_to_fe, biguint_to_fe, fe_to_biguint, modulus, PrimeField}, - AssignedValue, Context, -}; -use halo2_dynamic_sha256::Sha256DynamicConfig; -use halo2_ecc::bigint::{ - big_is_equal, big_is_zero, big_less_than, carry_mod, mul_no_carry, negative, select, sub, - CRTInteger, FixedCRTInteger, FixedOverflowInteger, OverflowInteger, -}; -use halo2_rsa::{ - impl_pkcs1v15_basic_circuit, AssignedBigUint, AssignedRSAPubE, AssignedRSAPublicKey, - AssignedRSASignature, BigUintConfig, BigUintInstructions, Fresh, RSAConfig, RSAInstructions, - RSAPubE, RSAPublicKey, RSASignature, RSASignatureVerifier, -}; -use num_bigint::{BigInt, BigUint, Sign}; -use num_traits::{One, Signed, Zero}; -use rand::rngs::OsRng; -use std::marker::PhantomData; - -use rand::{thread_rng, Rng}; -use rsa::{Hash, PaddingScheme, PublicKeyParts, RsaPrivateKey, RsaPublicKey}; -use sha2::{Digest, Sha256}; -use std::{ - fs::File, - io::{prelude::*, BufReader, BufWriter}, - path::Path, -}; - -// impl_pkcs1v15_basic_circuit!( -// Pkcs1v15_1024_64EnabledBenchConfig, -// Pkcs1v15_1024_64EnabledBenchCircuit, -// setup_pkcs1v15_1024_64_enabled, -// prove_pkcs1v15_1024_64_enabled, -// 1024, -// 80, -// 16, -// 8, -// 15, -// true -// ); - -// impl_pkcs1v15_basic_circuit!( -// Pkcs1v15_1024_128EnabledBenchConfig, -// Pkcs1v15_1024_128EnabledBenchCircuit, -// setup_pkcs1v15_1024_128_enabled, -// prove_pkcs1v15_1024_128_enabled, -// 1024, -// 128, -// 8, -// 8, -// 13, -// true -// ); - -impl_pkcs1v15_basic_circuit!( - Pkcs1v15_1024_1024EnabledBenchConfig, - Pkcs1v15_1024_1024EnabledBenchCircuit, - setup_pkcs1v15_1024_1024_enabled, - prove_pkcs1v15_1024_1024_enabled, - 1024, - 1024, - 3, - 1, - 16, - 1, - 19, - true -); - -// impl_pkcs1v15_basic_circuit!( -// Pkcs1v15_2048_64EnabledBenchConfig, -// Pkcs1v15_2048_64EnabledBenchCircuit, -// setup_pkcs1v15_2048_64_enabled, -// prove_pkcs1v15_2048_64_enabled, -// 2048, -// 64, -// 8, -// 8, -// 13, -// true -// ); - -// impl_pkcs1v15_basic_circuit!( -// Pkcs1v15_2048_128EnabledBenchConfig, -// Pkcs1v15_2048_128EnabledBenchCircuit, -// setup_pkcs1v15_2048_128_enabled, -// prove_pkcs1v15_2048_128_enabled, -// 2048, -// 128, -// 8, -// 8, -// 13, -// true -// ); - -impl_pkcs1v15_basic_circuit!( - Pkcs1v15_2048_1024EnabledBenchConfig, - Pkcs1v15_2048_1024EnabledBenchCircuit, - setup_pkcs1v15_2048_1024_enabled, - prove_pkcs1v15_2048_1024_enabled, - 2048, - 1024, - 3, - 1, - 16, - 1, - 19, - true -); - -impl_pkcs1v15_basic_circuit!( - Pkcs1v15_2048_3072EnabledBenchConfig, - Pkcs1v15_2048_30720EnabledBenchCircuit, - setup_pkcs1v15_2048_10240_enabled, - prove_pkcs1v15_2048_10240_enabled, - 2048, - 10240, - 21, - 4, - 16, - 2, - 19, - true -); - -impl_pkcs1v15_basic_circuit!( - Pkcs1v15_2048_1024DisabledBenchConfig, - Pkcs1v15_2048DisabledBenchCircuit, - setup_pkcs1v15_2048_1024_disabled, - prove_pkcs1v15_2048_1024_disabled, - 2048, - 1024, - 1, - 1, - 16, - 1, - 19, - false -); - -fn save_params_pk_and_vk( - params_filename: &str, - pk_filename: &str, - vk_filename: &str, - params: &ParamsKZG, - pk: &ProvingKey, - vk: &VerifyingKey, -) { - let f = File::create(params_filename).unwrap(); - let mut writer = BufWriter::new(f); - params.write(&mut writer).unwrap(); - writer.flush().unwrap(); - - let f = File::create(pk_filename).unwrap(); - let mut writer = BufWriter::new(f); - pk.write(&mut writer, SerdeFormat::RawBytes).unwrap(); - writer.flush().unwrap(); - - let f = File::create(vk_filename).unwrap(); - let mut writer = BufWriter::new(f); - vk.write(&mut writer, SerdeFormat::RawBytes).unwrap(); - writer.flush().unwrap(); -} - -fn bench_pkcs1v15_1024_enabled(c: &mut Criterion) { - let mut group = c.benchmark_group("pkcs1v15, 1024 bit public key, sha2 enabled"); - group.sample_size(10); - // let (params, vk, pk) = setup_pkcs1v15_1024_64_enabled(); - // save_params_pk_and_vk( - // "benches/params_1024_64.bin", - // "benches/1024_64.pk", - // "benches/1024_64.vk", - // ¶ms, - // &pk, - // &vk, - // ); - // group.bench_function("message 64 bytes", |b| { - // b.iter(|| prove_pkcs1v15_1024_64_enabled(¶ms, &vk, &pk)) - // }); - // let (params, vk, pk) = setup_pkcs1v15_1024_128_enabled(); - // save_params_pk_and_vk( - // "benches/params_1024_128.bin", - // "benches/1024_128.pk", - // "benches/1024_128.vk", - // ¶ms, - // &pk, - // &vk, - // ); - // group.bench_function("message 128 bytes", |b| { - // b.iter(|| prove_pkcs1v15_1024_128_enabled(¶ms, &vk, &pk)) - // }); - let (params, vk, pk) = setup_pkcs1v15_1024_1024_enabled(); - save_params_pk_and_vk( - "benches/params_1024_1024.bin", - "benches/1024_1024.pk", - "benches/1024_1024.vk", - ¶ms, - &pk, - &vk, - ); - group.bench_function("message 1024 bytes", |b| { - b.iter(|| prove_pkcs1v15_1024_1024_enabled(¶ms, &vk, &pk)) - }); - group.finish(); -} - -fn bench_pkcs1v15_2048_enabled(c: &mut Criterion) { - let mut group = c.benchmark_group("pkcs1v15, 2048 bit public key, sha2 enabled"); - group.sample_size(10); - // let (params, vk, pk) = setup_pkcs1v15_2048_64_enabled(); - // save_params_pk_and_vk( - // "benches/params_2048_64.bin", - // "benches/2048_64.pk", - // "benches/2048_64.vk", - // ¶ms, - // &pk, - // &vk, - // ); - // group.bench_function("message 64 bytes", |b| { - // b.iter(|| prove_pkcs1v15_2048_64_enabled(¶ms, &vk, &pk)) - // }); - // let (params, vk, pk) = setup_pkcs1v15_2048_128_enabled(); - // save_params_pk_and_vk( - // "benches/params_2048_128.bin", - // "benches/2048_128.pk", - // "benches/2048_128.vk", - // ¶ms, - // &pk, - // &vk, - // ); - // group.bench_function("message 128 bytes", |b| { - // b.iter(|| prove_pkcs1v15_2048_128_enabled(¶ms, &vk, &pk)) - // }); - let (params, vk, pk) = setup_pkcs1v15_2048_1024_enabled(); - save_params_pk_and_vk( - "benches/params_2048_1024.bin", - "benches/2048_1024.pk", - "benches/2048_1024.vk", - ¶ms, - &pk, - &vk, - ); - group.bench_function("message 1024 bytes", |b| { - b.iter(|| prove_pkcs1v15_2048_1024_enabled(¶ms, &vk, &pk)) - }); - let (params, vk, pk) = setup_pkcs1v15_2048_10240_enabled(); - save_params_pk_and_vk( - "benches/params_2048_10240.bin", - "benches/2048_10240.pk", - "benches/2048_10240.vk", - ¶ms, - &pk, - &vk, - ); - group.bench_function("message 10240 bytes", |b| { - b.iter(|| prove_pkcs1v15_2048_10240_enabled(¶ms, &vk, &pk)) - }); - group.finish(); -} - -fn bench_pkcs1v15_2048_disabled(c: &mut Criterion) { - let mut group = c.benchmark_group("pkcs1v15, 2048 bit public key, sha2 disabled"); - group.sample_size(10); - let (params, vk, pk) = setup_pkcs1v15_2048_1024_disabled(); - save_params_pk_and_vk( - "benches/params_2048_1024_disable.bin", - "benches/2048_1024_disable.pk", - "benches/2048_1024_disable.vk", - ¶ms, - &pk, - &vk, - ); - group.bench_function("message 1024 bytes", |b| { - b.iter(|| prove_pkcs1v15_2048_1024_disabled(¶ms, &vk, &pk)) - }); - group.finish(); -} - -criterion_group!( - benches, - bench_pkcs1v15_1024_enabled, - bench_pkcs1v15_2048_enabled, - bench_pkcs1v15_2048_disabled -); -criterion_main!(benches); diff --git a/examples/rsa_example.rs b/examples/rsa_example.rs deleted file mode 100644 index 2383273..0000000 --- a/examples/rsa_example.rs +++ /dev/null @@ -1,226 +0,0 @@ -// //! The following example circuit takes the message bytes and pkcs1v15 signature as private input and the RSA public key and message hash as public input. -// //! The circuit constraints are satisfied if and only if the following conditions hold. -// //! 1. The resulting hash of the given message is equal to the given hash. -// //! 2. The given signature is valid for the given public key and hash. -// use halo2_dynamic_sha256::{Field, Sha256Chip, Sha256Config}; -// use halo2_rsa::{ -// big_integer::{BigIntConfig, UnassignedInteger}, -// RSAChip, RSAConfig, RSAInstructions, RSAPubE, RSAPublicKey, RSASignature, RSASignatureVerifier, -// }; -// use halo2wrong::{ -// curves::FieldExt, -// halo2::{ -// circuit::SimpleFloorPlanner, -// plonk::{Circuit, ConstraintSystem, Error}, -// }, -// }; -// use maingate::{ -// decompose_big, MainGate, MainGateInstructions, RangeChip, RangeInstructions, RegionCtx, -// }; -// use num_bigint::BigUint; -// use std::marker::PhantomData; - -// #[derive(Debug, Clone)] -// struct RSAExampleConfig { -// rsa_config: RSAConfig, -// sha256_config: Sha256Config, -// } - -// struct RSAExample { -// signature: RSASignature, -// public_key: RSAPublicKey, -// msg: Vec, -// r: F, -// _f: PhantomData, -// } - -// impl RSAExample { -// const BITS_LEN: usize = 2048; -// const LIMB_WIDTH: usize = RSAChip::::LIMB_WIDTH; -// const EXP_LIMB_BITS: usize = 5; -// const DEFAULT_E: u128 = 65537; -// fn rsa_chip(&self, config: RSAConfig) -> RSAChip { -// RSAChip::new(config, Self::BITS_LEN, Self::EXP_LIMB_BITS) -// } -// fn sha256_chip(&self, config: Sha256Config) -> Sha256Chip { -// Sha256Chip::new(config) -// } -// } - -// impl Circuit for RSAExample { -// type Config = RSAExampleConfig; -// type FloorPlanner = SimpleFloorPlanner; - -// fn without_witnesses(&self) -> Self { -// unimplemented!(); -// } - -// fn configure(meta: &mut ConstraintSystem) -> Self::Config { -// // 1. Configure `MainGate`. -// let main_gate_config = MainGate::::configure(meta); -// // 2. Compute bit length parameters by calling `RSAChip::::compute_range_lens` function. -// let (composition_bit_lens, overflow_bit_lens) = -// RSAChip::::compute_range_lens(Self::BITS_LEN / Self::LIMB_WIDTH); -// // 3. Configure `RangeChip`. -// let range_config = RangeChip::::configure( -// meta, -// &main_gate_config, -// composition_bit_lens, -// overflow_bit_lens, -// ); -// // 4. Configure `BigIntConfig`. -// let bigint_config = BigIntConfig::new(range_config.clone(), main_gate_config.clone()); -// // 5. Configure `RSAConfig`. -// let rsa_config = RSAConfig::new(bigint_config); -// // 6. Configure `Sha256Config`. -// let sha256_config = Sha256Config::configure(meta, 128 + 64); -// Self::Config { -// rsa_config, -// sha256_config, -// } -// } - -// fn synthesize( -// &self, -// config: Self::Config, -// mut layouter: impl halo2wrong::halo2::circuit::Layouter, -// ) -> Result<(), Error> { -// let rsa_chip = self.rsa_chip(config.rsa_config); -// let sha256_chip = self.sha256_chip(config.sha256_config); -// let bigint_chip = rsa_chip.bigint_chip(); -// let main_gate = rsa_chip.main_gate(); -// // 1. Assign a public key and signature. -// let (public_key, signature) = layouter.assign_region( -// || "rsa signature with hash test using 2048 bits public keys", -// |region| { -// let offset = 0; -// let ctx = &mut RegionCtx::new(region, offset); -// let sign = rsa_chip.assign_signature(ctx, self.signature.clone())?; -// let public_key = rsa_chip.assign_public_key(ctx, self.public_key.clone())?; -// Ok((public_key, sign)) -// }, -// )?; -// // 2. Create a RSA signature verifier from `RSAChip` and `Sha256BitChip` -// let verifier = RSASignatureVerifier::new(rsa_chip, sha256_chip); -// // 3. Receives the verification result and the resulting hash of `self.msg` from `RSASignatureVerifier`. -// let (is_valid, hashed_msg) = layouter.assign_region( -// || "verify pkcs1v15 signature", -// |mut region| { -// verifier.verify_pkcs1v15_signature( -// region, -// &public_key, -// &self.msg, -// &signature, -// self.r, -// ) -// }, -// )?; -// // 4. Expose the RSA public key as public input. -// for (i, limb) in public_key.n.limbs().into_iter().enumerate() { -// main_gate.expose_public( -// layouter.namespace(|| format!("expose {} th public key limb", i)), -// limb.assigned_val(), -// i, -// )?; -// } -// let num_limb_n = Self::BITS_LEN / RSAChip::::LIMB_WIDTH; -// // 5. Expose the resulting hash as public input. -// for (i, val) in hashed_msg.into_iter().enumerate() { -// main_gate.expose_public( -// layouter.namespace(|| format!("expose {} th hashed_msg limb", i)), -// val, -// num_limb_n + i, -// )?; -// } -// // 6. The verification result must be one. -// layouter.assign_region( -// || "assert is_valid==1", -// |region| { -// let offset = 0; -// let ctx = &mut RegionCtx::new(region, offset); -// main_gate.assert_one(ctx, &is_valid)?; -// Ok(()) -// }, -// )?; -// // Create lookup tables for range check in `range_chip`. -// let range_chip = bigint_chip.range_chip(); -// range_chip.load_table(&mut layouter)?; -// Ok(()) -// } -// } - -// fn main() { -// use halo2wrong::curves::bn256::Fr as F; -// use halo2wrong::halo2::dev::MockProver; -// use rand::{thread_rng, Rng}; -// use rsa::{Hash, PaddingScheme, PublicKeyParts, RsaPrivateKey, RsaPublicKey}; -// use sha2::{Digest, Sha256}; - -// let limb_width = RSAExample::::LIMB_WIDTH; -// let num_limbs = RSAExample::::BITS_LEN / RSAExample::::LIMB_WIDTH; -// // 1. Uniformly sample a RSA key pair. -// let mut rng = thread_rng(); -// let private_key = -// RsaPrivateKey::new(&mut rng, RSAExample::::BITS_LEN).expect("failed to generate a key"); -// let public_key = RsaPublicKey::from(&private_key); -// // 2. Uniformly sample a message. -// let mut msg: [u8; 128] = [0; 128]; -// for i in 0..128 { -// msg[i] = rng.gen(); -// } -// // 3. Compute the SHA256 hash of `msg`. -// let hashed_msg = Sha256::digest(&msg); -// // 4. Generate a pkcs1v15 signature. -// let padding = PaddingScheme::PKCS1v15Sign { -// hash: Some(Hash::SHA2_256), -// }; -// let mut sign = private_key -// .sign(padding, &hashed_msg) -// .expect("fail to sign a hashed message."); -// sign.reverse(); -// let sign_big = BigUint::from_bytes_le(&sign); -// let sign_limbs = decompose_big::(sign_big.clone(), num_limbs, limb_width); -// let signature = RSASignature::new(UnassignedInteger::from(sign_limbs)); - -// // 5. Construct `RSAPublicKey` from `n` of `public_key` and fixed `e`. -// let n_big = BigUint::from_radix_le(&public_key.n().clone().to_radix_le(16), 16).unwrap(); -// let n_limbs = decompose_big::(n_big.clone(), num_limbs, limb_width); -// let n_unassigned = UnassignedInteger::from(n_limbs.clone()); -// let e_fix = RSAPubE::Fix(BigUint::from(RSAExample::::DEFAULT_E)); -// let public_key = RSAPublicKey::new(n_unassigned, e_fix); - -// // 6. Create our circuit! -// // Compute the randomness from the hashed_msg. -// let mut seed = [0; 64]; -// for idx in 0..32 { -// seed[idx] = hashed_msg[idx]; -// } -// let r = F::from_bytes_wide(&seed); -// let circuit = RSAExample:: { -// signature, -// public_key, -// msg: msg.to_vec(), -// r, -// _f: PhantomData, -// }; - -// // 7. Create public inputs -// let n_fes = n_limbs; -// let mut hash_fes = hashed_msg -// .iter() -// .map(|byte| F::from(*byte as u64)) -// .collect::>(); -// let mut column0_public_inputs = n_fes; -// column0_public_inputs.append(&mut hash_fes); -// let public_inputs = vec![column0_public_inputs]; - -// // 8. Generate a proof. -// let k = 18; -// let prover = match MockProver::run(k, &circuit, public_inputs) { -// Ok(prover) => prover, -// Err(e) => panic!("{:#?}", e), -// }; -// // 9. Verify the proof. -// assert!(prover.verify().is_ok()); -// } -fn main() {} diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 8d05880..0000000 --- a/package-lock.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "halo2_rsa", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "dependencies": { - "halo2-rsa": "file:pkg" - } - }, - "node_modules/halo2-rsa": { - "resolved": "pkg", - "link": true - }, - "pkg": { - "version": "0.1.0", - "license": "MIT" - } - }, - "dependencies": { - "halo2-rsa": { - "version": "file:pkg" - } - } -} diff --git a/package.json b/package.json deleted file mode 100644 index 6301a31..0000000 --- a/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "dependencies": { - "halo2-rsa": "file:pkg" - } -} diff --git a/rust-toolchain b/rust-toolchain index d0217cd..6f6d7b3 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -nightly-2022-10-28 +nightly-2023-08-12 diff --git a/src/big_uint/chip.rs b/src/big_uint/chip.rs index c856739..3912d0d 100644 --- a/src/big_uint/chip.rs +++ b/src/big_uint/chip.rs @@ -1,37 +1,33 @@ -use std::marker::PhantomData; - -use super::utils::{decompose_bigint, decompose_biguint}; +use super::utils::decompose_biguint; use crate::{AssignedBigUint, BigUintInstructions, Fresh, Muled, RangeType, RefreshAux}; -use halo2_base::halo2_proofs::{circuit::Region, circuit::Value, plonk::Error}; +use halo2_base::halo2_proofs::plonk::Error; use halo2_base::utils::fe_to_bigint; -use halo2_base::ContextParams; use halo2_base::QuantumCell; use halo2_base::{ - gates::{flex_gate::FlexGateConfig, range::RangeConfig, GateInstructions, RangeInstructions}, - utils::{bigint_to_fe, biguint_to_fe, fe_to_biguint, modulus, PrimeField}, + gates::{flex_gate::GateChip, range::RangeChip, GateInstructions, RangeInstructions}, + utils::{bigint_to_fe, biguint_to_fe, fe_to_biguint, BigPrimeField}, AssignedValue, Context, }; use halo2_ecc::bigint::{ - big_is_equal, big_is_zero, big_less_than, carry_mod, mul_no_carry, negative, select, sub, - CRTInteger, FixedCRTInteger, FixedOverflowInteger, OverflowInteger, + big_is_equal, big_is_zero, mul_no_carry, select, sub, FixedOverflowInteger, OverflowInteger, }; use num_bigint::{BigInt, BigUint, Sign}; -use num_traits::{One, Signed, Zero}; +use num_traits::{One, Zero}; #[derive(Clone, Debug)] -pub struct BigUintConfig { - pub range: RangeConfig, +pub struct BigUintConfig { + pub range: RangeChip, pub limb_bits: usize, } -impl BigUintInstructions for BigUintConfig { - /// Getter for [`FlexGateConfig`]. - fn gate(&self) -> &FlexGateConfig { +impl BigUintInstructions for BigUintConfig { + /// Getter for [`GateChip`]. + fn gate(&self) -> &GateChip { &self.range.gate } - /// Getter for [`RangeConfig`]. - fn range(&self) -> &RangeConfig { + /// Getter for [`RangeChip`]. + fn range(&self) -> &RangeChip { &self.range } @@ -40,59 +36,54 @@ impl BigUintInstructions for BigUintConfig { self.limb_bits } - fn assign_integer<'v>( + fn assign_integer( &self, - ctx: &mut Context<'v, F>, - value: Value, + ctx: &mut Context, + value: &BigUint, bit_len: usize, - ) -> Result, Error> { + ) -> Result, Error> { assert_eq!(bit_len % self.limb_bits, 0); let num_limbs = bit_len / self.limb_bits; - let gate = self.gate(); let range = self.range(); - let limbs = value - .as_ref() - .map(|v| decompose_biguint(v, num_limbs, self.limb_bits)) - .transpose_vec(num_limbs); - let limbs = limbs + let limbs = decompose_biguint(&value, num_limbs, self.limb_bits); + let assigned_limbs: Vec> = limbs .into_iter() - .map(|v| QuantumCell::Witness(v)) - .collect::>>(); - let assigned_limbs: Vec> = gate.assign_region(ctx, limbs, vec![]); + .map(|v| ctx.load_witness(v)) + .collect(); for limb in assigned_limbs.iter() { - range.range_check(ctx, &limb, self.limb_bits); + range.range_check(ctx, *limb, self.limb_bits); } - let int = OverflowInteger::construct(assigned_limbs, self.limb_bits); - Ok(AssignedBigUint::new(int, value)) + let int = OverflowInteger::new(assigned_limbs, self.limb_bits); + Ok(AssignedBigUint::new(int, value.clone())) } - fn assign_constant<'v>( + fn assign_constant( &self, - ctx: &mut Context<'v, F>, + ctx: &mut Context, value: BigUint, - ) -> Result, Error> { + ) -> Result, Error> { let num_limbs = self.num_limbs(&BigInt::from_biguint(Sign::Plus, value.clone())); let limbs = decompose_biguint::(&value, num_limbs, self.limb_bits); let fixed_int = FixedOverflowInteger::construct(limbs); - let int = fixed_int.assign(self.gate(), ctx, self.limb_bits); - Ok(AssignedBigUint::new(int, Value::known(value))) + let int = fixed_int.assign(ctx).into_overflow(self.limb_bits); + Ok(AssignedBigUint::new(int, value)) } - fn max_value<'v>( + fn max_value( &self, - ctx: &mut Context<'v, F>, + ctx: &mut Context, num_limbs: usize, - ) -> Result, Error> { + ) -> Result, Error> { let value = (BigUint::from(1u64) << (self.limb_bits * num_limbs)) - BigUint::from(1u64); self.assign_constant(ctx, value) } - fn refresh<'v>( + fn refresh( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Muled>, + ctx: &mut Context, + a: &AssignedBigUint, aux: &RefreshAux, - ) -> Result, Error> { + ) -> Result, Error> { // For converting `a` to a [`Fresh`] type integer, we decompose each limb of `a` into `self.limb_width`-bits values. assert_eq!(self.limb_bits, aux.limb_bits); // The i-th value of `aux.increased_limbs_vec` represents the number of increased values when converting i-th limb of `a` into `self.limb_width`-bits values. @@ -105,7 +96,7 @@ impl BigUintInstructions for BigUintConfig { let gate = self.gate(); let mut refreshed_limbs = Vec::with_capacity(num_limbs_fresh); - let zero_assigned = gate.load_zero(ctx); + let zero_assigned = ctx.load_zero(); let a_limbs = a.limbs(); for i in 0..a.num_limbs() { refreshed_limbs.push(a_limbs[i].clone()); @@ -128,63 +119,59 @@ impl BigUintInstructions for BigUintConfig { // When `j>0`, `n` is carried to the `i+j`-th limb. refreshed_limbs[i + j] = gate.add( ctx, - QuantumCell::Existing(&refreshed_limbs[i + j]), - QuantumCell::Existing(&n), + QuantumCell::Existing(refreshed_limbs[i + j]), + QuantumCell::Existing(n), ); } // We use `q` as the next `limb`. limb = q; } // `limb` should be zero because we decomposed all bits of the `i`-th overflowing limb value into `self.limb_width` bits values. - gate.assert_is_const(ctx, &limb, F::zero()); + gate.assert_is_const(ctx, &limb, &F::from(0)); } let range = self.range(); for limb in refreshed_limbs.iter() { - range.range_check(ctx, &limb, self.limb_bits); + range.range_check(ctx, *limb, self.limb_bits); } - let int = OverflowInteger::construct(refreshed_limbs, self.limb_bits); + let int = OverflowInteger::new(refreshed_limbs, self.limb_bits); let new_assigned_int = AssignedBigUint::new(int, a.value()); Ok(new_assigned_int) } /// Given a bit value `sel`, return `a` if `a`=1 and `b` otherwise. - fn select<'v, T: RangeType>( + fn select( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, T>, - b: &AssignedBigUint<'v, F, T>, - sel: &AssignedValue<'v, F>, - ) -> Result, Error> { - let int = select::assign(self.gate(), ctx, &a.int, &b.int, sel); - let value = a - .value - .as_ref() - .zip(b.value.as_ref()) - .zip(sel.value) - .map(|((a, b), sel)| { - if sel == F::one() { - a.clone() - } else { - b.clone() - } - }); + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, + sel: &AssignedValue, + ) -> Result, Error> { + let int = select::assign(self.gate(), ctx, a.int.clone(), b.int.clone(), *sel); + let value = { + if sel.value() == &F::from(1) { + a.value().clone() + } else { + b.value().clone() + } + }; + Ok(AssignedBigUint::new(int, value)) } /// Given two inputs `a,b`, performs the addition `a + b`. - fn add<'v>( + fn add( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error> { + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, + ) -> Result, Error> { let gate = self.gate(); let range = self.range(); - let out_value = a.value.as_ref().zip(b.value.as_ref()).map(|(a, b)| a + b); + let out_value = a.value.clone() + b.value.clone(); let n1 = a.num_limbs(); let n2 = b.num_limbs(); let max_n = if n1 < n2 { n2 } else { n1 }; - let zero_value = gate.load_zero(ctx); + let zero_value = ctx.load_zero(); let a = a.extend_limbs(max_n - n1, zero_value.clone()); let b = b.extend_limbs(max_n - n2, zero_value.clone()); @@ -197,43 +184,41 @@ impl BigUintInstructions for BigUintConfig { for i in 0..max_n { let a_b = gate.add( ctx, - QuantumCell::Existing(&a.limb(i)), - QuantumCell::Existing(&b.limb(i)), + QuantumCell::Existing(*a.limb(i)), + QuantumCell::Existing(*b.limb(i)), ); let sum = gate.add( ctx, - QuantumCell::Existing(&a_b), - QuantumCell::Existing(&carrys[i]), + QuantumCell::Existing(a_b), + QuantumCell::Existing(carrys[i]), ); - let sum_big = sum.value().map(|f| fe_to_biguint(f)); + let sum_big = fe_to_biguint(sum.value()); // `c_val_f` is lower `self.limb_bits` bits of `a + b + carrys[i]`. - let c_val: Value = sum_big - .clone() - .map(|b| biguint_to_fe::(&(&b % &limb_max))); - let carry_val: Value = sum_big.map(|b| biguint_to_fe::(&(b >> self.limb_bits))); + let c_val = biguint_to_fe::(&(&sum_big.clone() % &limb_max)); + let carry_val = biguint_to_fe::(&(sum_big >> self.limb_bits)); // `c` and `carry` should fit in `self.limb_bits` bits. - let c = gate.load_witness(ctx, c_val); - range.range_check(ctx, &c, self.limb_bits); - let carry = gate.load_witness(ctx, carry_val); - range.range_check(ctx, &carry, self.limb_bits); + let c = ctx.load_witness(c_val); + range.range_check(ctx, c, self.limb_bits); + let carry = ctx.load_witness(carry_val); + range.range_check(ctx, carry, self.limb_bits); let c_add_carry = gate.mul_add( ctx, - QuantumCell::Existing(&carry), + QuantumCell::Existing(carry), QuantumCell::Constant(limb_max_f), - QuantumCell::Existing(&c), + QuantumCell::Existing(c), ); // `a + b + carrys[i] == c + carry` - gate.assert_equal( + gate.is_equal( ctx, - QuantumCell::Existing(&sum), - QuantumCell::Existing(&c_add_carry), + QuantumCell::Existing(sum), + QuantumCell::Existing(c_add_carry), ); c_vals.push(c); carrys.push(carry); } // Add the last carry to the `c_vals`. c_vals.push(carrys[max_n].clone()); - let int = OverflowInteger::construct(c_vals, self.limb_bits); + let int = OverflowInteger::new(c_vals, self.limb_bits); Ok(AssignedBigUint::new(int, out_value)) } @@ -249,68 +234,75 @@ impl BigUintInstructions for BigUintConfig { /// Returns the subtraction result as [`AssignedInteger`] and the assigned bit as [`AssignedValue`] that represents whether the result is overflowed or not. /// If `a>=b`, the result is equivalent to `a - b` and the bit is zero. /// Otherwise, the bit is one. - fn sub_unsafe<'v>( + fn sub_unsafe( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, - ) -> Result<(AssignedBigUint<'v, F, Fresh>, AssignedValue<'v, F>), Error> { + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, + ) -> Result<(AssignedBigUint, AssignedValue), Error> { let gate = self.gate(); let n1 = a.num_limbs(); let n2 = b.num_limbs(); let max_n = if n1 < n2 { n2 } else { n1 }; - let zero_value = gate.load_zero(ctx); + let zero_value = ctx.load_zero(); let a = a.extend_limbs(max_n - n1, zero_value.clone()); let b = b.extend_limbs(max_n - n2, zero_value.clone()); let limb_base = biguint_to_fe::(&(BigUint::one() << self.limb_bits)); + + // TODO: Underconstrained? Convert overflow int to proper int + let a_proper = FixedOverflowInteger::construct( + a.limbs().iter().map(|x| *x.value()).collect() + ).assign(ctx); + let b_proper = FixedOverflowInteger::construct( + b.limbs().iter().map(|x| *x.value()).collect() + ).assign(ctx); + let (int, overflow) = - sub::assign(self.range(), ctx, &a.int, &b.int, self.limb_bits, limb_base); + sub::assign(self.range(), ctx, a_proper, b_proper, self.limb_bits, limb_base); // let int_neg = negative::assign(gate, ctx, &int); - let is_overflow_zero = gate.is_zero(ctx, &overflow); - let is_overflow = gate.not(ctx, QuantumCell::Existing(&is_overflow_zero)); + let is_overflow_zero = gate.is_zero(ctx, overflow); + let is_overflow = gate.not(ctx, QuantumCell::Existing(is_overflow_zero)); // let actual_int = select::assign(gate, ctx, &int_neg, &int, &is_overflow); - let value = a - .value - .zip(b.value) - .map(|(a, b)| if a >= b { a - b } else { BigUint::zero() }); + let value = { + if a.value >= b.value { a.value - b.value } else { BigUint::zero() } + }; Ok((AssignedBigUint::new(int, value), is_overflow)) } - fn mul<'v>( + fn mul( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error> { - let gate = self.gate(); + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, + ) -> Result, Error> { let n1 = a.num_limbs(); let n2 = b.num_limbs(); let num_limbs = n1 + n2 - 1; - let zero_value = gate.load_zero(ctx); + let zero_value = ctx.load_zero(); let a = a.extend_limbs(num_limbs - n1, zero_value.clone()); let b = b.extend_limbs(num_limbs - n2, zero_value.clone()); let num_limbs_log2_ceil = (num_limbs as f32).log2().ceil() as usize; - let int = mul_no_carry::truncate(self.gate(), ctx, &a.int, &b.int, num_limbs_log2_ceil); - let value = a.value.zip(b.value).map(|(a, b)| a * b); + let int = mul_no_carry::truncate(self.gate(), ctx, a.int, b.int, num_limbs_log2_ceil); + let value = a.value * b.value; Ok(AssignedBigUint::new(int, value)) } - fn square<'v>( + fn square( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error> { + ctx: &mut Context, + a: &AssignedBigUint, + ) -> Result, Error> { self.mul(ctx, a, a) } /// Given two inputs `a,b` and a modulus `n`, performs the modular addition `a + b mod n`. - fn add_mod<'v>( + fn add_mod( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, - n: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error> { + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, + n: &AssignedBigUint, + ) -> Result, Error> { // 1. Compute `a + b`. // 2. Compute `a + b - n`. // 3. If the subtraction is overflowed, i.e., `a + b < n`, returns `a + b`. Otherwise, returns `a + b - n`. @@ -322,13 +314,13 @@ impl BigUintInstructions for BigUintConfig { } /// Given two inputs `a,b` and a modulus `n`, performs the modular subtraction `a - b mod n`. - fn sub_mod<'v>( + fn sub_mod( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, - n: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error> { + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, + n: &AssignedBigUint, + ) -> Result, Error> { // 1. Compute `a - b`. // 2. Compute `(a + n) - b = a - b + n`. // 3. If the subtraction in 1 is overflowed, i.e., `a - b < 0`, returns `a - b + n`. Otherwise, returns `a - b`. @@ -338,7 +330,7 @@ impl BigUintInstructions for BigUintConfig { // The number of limbs of `subed2` is `max(n.num_limbs(), subed1.num_limbs()) >= subed1.num_limbs()`. let added = self.add(ctx, a, n)?; let (subed2, is_overflowed2) = self.sub_unsafe(ctx, &added, b)?; - self.gate().assert_is_const(ctx, &is_overflowed2, F::zero()); + self.gate().assert_is_const(ctx, &is_overflowed2, &F::from(0)); let result = self.select(ctx, &subed2, &subed1, &is_overflowed1)?; Ok(result.slice_limbs(0, result.num_limbs() - 2)) } @@ -355,13 +347,13 @@ impl BigUintInstructions for BigUintConfig { /// Returns the modular multiplication result `a * b mod n` as [`AssignedInteger`]. /// # Requirements /// Before calling this function, you must assert that `a( + fn mul_mod( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, - n: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error> { + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, + n: &AssignedBigUint, + ) -> Result, Error> { // The following constraints are designed with reference to AsymmetricMultiplierReducer template in https://github.com/jacksoom/circom-bigint/blob/master/circuits/mult.circom. // However, we do not regroup multiple limbs like the circom-bigint implementation because addition is not free, i.e., it makes constraints as well as multiplication, in the Plonk constraints system. // Besides, we use lookup tables to optimize range checks. @@ -369,30 +361,23 @@ impl BigUintInstructions for BigUintConfig { let n1 = a.num_limbs(); let n2 = b.num_limbs(); assert_eq!(n1, n.num_limbs()); - let (a_big, b_big, n_big) = (a.value(), b.value(), n.value()); + let (a_big, b_big, n_big) = (&a.value(), &b.value(), &n.value()); // 1. Compute the product as `BigUint`. let full_prod_big = a_big * b_big; // 2. Compute the quotient and remainder when the product is divided by `n`. - let (q_big, prod_big) = full_prod_big - .zip(n_big.as_ref()) - .map(|(full_prod, n)| (&full_prod / n, &full_prod % n)) - .unzip(); + let (q_big, prod_big) = (&full_prod_big / n_big, &full_prod_big % n_big); // 3. Assign the quotient and remainder after checking the range of each limb. - let assign_q = self.assign_integer(ctx, q_big, n2 * limb_bits)?; - let assign_n = self.assign_integer(ctx, n_big, n1 * limb_bits)?; - let assign_prod = self.assign_integer(ctx, prod_big, n1 * limb_bits)?; + let assign_q = self.assign_integer(ctx, &q_big, n2 * limb_bits)?; + let assign_n = self.assign_integer(ctx, &n_big, n1 * limb_bits)?; + let assign_prod = self.assign_integer(ctx, &prod_big, n1 * limb_bits)?; // 4. Assert `a * b = quotient_int * n + prod_int`, i.e., `prod_int = (a * b) mod n`. let ab = self.mul(ctx, a, b)?; let qn = self.mul(ctx, &assign_q, &assign_n)?; let gate = self.gate(); let n_sum = n1 + n2; let qn_prod = { - let value = qn - .value - .as_ref() - .zip(assign_prod.value.as_ref()) - .map(|(a, b)| a + b); + let value = qn.value.clone() + assign_prod.value.clone(); let mut limbs = Vec::with_capacity(n1 + n2 - 1); let qn_limbs = qn.limbs(); let prod_limbs = assign_prod.limbs(); @@ -400,67 +385,67 @@ impl BigUintInstructions for BigUintConfig { if i < n1 { limbs.push(gate.add( ctx, - QuantumCell::Existing(&qn_limbs[i]), - QuantumCell::Existing(&prod_limbs[i]), + QuantumCell::Existing(qn_limbs[i]), + QuantumCell::Existing(prod_limbs[i]), )); } else { limbs.push(qn_limbs[i].clone()); } } - let int = OverflowInteger::construct(limbs, self.limb_bits); + let int = OverflowInteger::new(limbs, self.limb_bits); AssignedBigUint::::new(int, value) }; let is_eq = self.is_equal_muled(ctx, &ab, &qn_prod, n1, n2)?; - gate.assert_is_const(ctx, &is_eq, F::one()); + gate.assert_is_const(ctx, &is_eq, &F::from(1)); Ok(assign_prod) } /// Given a input `a` and a modulus `n`, performs the modular square `a^2 mod n`. - fn square_mod<'v>( + fn square_mod( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - n: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error> { + ctx: &mut Context, + a: &AssignedBigUint, + n: &AssignedBigUint, + ) -> Result, Error> { self.mul_mod(ctx, a, a, n) } /// Given a base `a`, a variable exponent `e`, and a modulus `n`, performs the modular power `a^e mod n`. - fn pow_mod<'v>( + fn pow_mod( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - e: &AssignedValue<'v, F>, - n: &AssignedBigUint<'v, F, Fresh>, + ctx: &mut Context, + a: &AssignedBigUint, + e: &AssignedValue, + n: &AssignedBigUint, exp_bits: usize, - ) -> Result, Error> { + ) -> Result, Error> { let gate = self.gate(); - let e_bits = gate.num_to_bits(ctx, e, exp_bits); + let e_bits = gate.num_to_bits(ctx, *e, exp_bits); let num_limbs = a.num_limbs(); assert_eq!(num_limbs, n.num_limbs()); let mut acc = self.assign_constant(ctx, BigUint::one())?; - let zero = gate.load_zero(ctx); + let zero = ctx.load_zero(); acc = acc.extend_limbs(num_limbs - acc.num_limbs(), zero); - let mut squared: AssignedBigUint<'v, F, Fresh> = a.clone(); + let mut squared = a.clone(); for e_bit in e_bits.into_iter() { // Compute `acc * squared`. let muled = self.mul_mod(ctx, &acc, &squared, n)?; // If `e_bit = 1`, update `acc` to `acc * squared`. Otherwise, use the same `acc`. acc = self.select(ctx, &muled, &acc, &e_bit)?; // Square `squared`. - squared = self.square_mod(ctx, &squared, n)?; + squared = self.square_mod(ctx, &squared, n).unwrap().into(); } Ok(acc) } /// Given a base `a`, a fixed exponent `e`, and a modulus `n`, performs the modular power `a^e mod n`. - fn pow_mod_fixed_exp<'v>( + fn pow_mod_fixed_exp( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, + ctx: &mut Context, + a: &AssignedBigUint, e: &BigUint, - n: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error> { + n: &AssignedBigUint, + ) -> Result, Error> { let num_limbs = a.num_limbs(); assert_eq!(num_limbs, n.num_limbs()); let num_e_bits = Self::bits_size(&BigInt::from_biguint(Sign::Plus, e.clone())); @@ -476,13 +461,13 @@ impl BigUintInstructions for BigUintConfig { .collect::>(); let e_bits = e_bits[0..num_e_bits].to_vec(); let mut acc = self.assign_constant(ctx, BigUint::from(1usize))?; - let zero = self.gate().load_zero(ctx); + let zero = ctx.load_zero(); acc = acc.extend_limbs(num_limbs - acc.num_limbs(), zero); - let mut squared: AssignedBigUint<'v, F, Fresh> = a.clone(); + let mut squared = a.clone(); for e_bit in e_bits.into_iter() { let cur_sq = squared; // Square `squared`. - squared = self.square_mod(ctx, &cur_sq, n)?; + squared = self.square_mod(ctx, &cur_sq, n).unwrap().into(); if !e_bit { continue; } @@ -493,34 +478,44 @@ impl BigUintInstructions for BigUintConfig { } /// Returns an assigned bit representing whether `a` is zero or not. - fn is_zero<'v>( + fn is_zero( &self, - ctx: &mut Context<'v, F>, - a: &'v AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error> { - let out = big_is_zero::assign(self.gate(), ctx, a.int_ref()); + ctx: &mut Context, + a: &AssignedBigUint, + ) -> Result, Error> { + // TODO: Underconstrained + let a_proper = FixedOverflowInteger::construct( + a.limbs().iter().map(|x| *x.value()).collect() + ).assign(ctx); + let out = big_is_zero::assign(self.gate(), ctx, a_proper); Ok(out) } /// Returns an assigned bit representing whether `a` and `b` are equivalent, whose [`RangeType`] is [`Fresh`]. - fn is_equal_fresh<'v>( + fn is_equal_fresh( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error> { - Ok(big_is_equal::assign(self.gate(), ctx, &a.int, &b.int)) + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, + ) -> Result, Error> { + let a_proper = FixedOverflowInteger::construct( + a.limbs().iter().map(|x| *x.value()).collect() + ).assign(ctx); + let b_proper = FixedOverflowInteger::construct( + b.limbs().iter().map(|x| *x.value()).collect() + ).assign(ctx); + Ok(big_is_equal::assign(self.gate(), ctx, a_proper, b_proper)) } /// Returns an assigned bit representing whether `a` and `b` are equivalent, whose [`RangeType`] is [`Muled`]. - fn is_equal_muled<'v>( + fn is_equal_muled( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Muled>, - b: &AssignedBigUint<'v, F, Muled>, + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, num_limbs_l: usize, num_limbs_r: usize, - ) -> Result, Error> { + ) -> Result, Error> { // The following constraints are designed with reference to EqualWhenCarried template in https://github.com/jacksoom/circom-bigint/blob/master/circuits/mult.circom. // We use lookup tables to optimize range checks. let min_n = if num_limbs_r >= num_limbs_l { @@ -543,26 +538,26 @@ impl BigUintInstructions for BigUintConfig { // but this doesn't work because early sums might be negative. // So instead we verify that `a - b + word_max = word_max`. let limb_max = BigInt::from(1) << self.limb_bits; - let zero = gate.load_constant(ctx, F::zero()); + let zero = ctx.load_constant(F::from(0)); let mut accumulated_extra = zero.clone(); let mut carry = Vec::with_capacity(num_limbs); let mut cs = Vec::with_capacity(num_limbs); carry.push(zero.clone()); - let mut eq_bit = gate.load_constant(ctx, F::one()); + let mut eq_bit = ctx.load_constant(F::from(1)); let a_limbs = a.limbs(); let b_limbs = b.limbs(); for i in 0..num_limbs { // `sum = a - b + word_max` let a_b_sub = gate.sub( ctx, - QuantumCell::Existing(&a_limbs[i]), - QuantumCell::Existing(&b_limbs[i]), + QuantumCell::Existing(a_limbs[i]), + QuantumCell::Existing(b_limbs[i]), ); let sum = gate.sum( ctx, vec![ - QuantumCell::Existing(&a_b_sub), - QuantumCell::Existing(&carry[i]), + QuantumCell::Existing(a_b_sub), + QuantumCell::Existing(carry[i]), QuantumCell::Constant(muled_limb_max_fe), ], ); @@ -575,37 +570,37 @@ impl BigUintInstructions for BigUintConfig { // `accumulated_extra` is the sum of `word_max`. accumulated_extra = gate.add( ctx, - QuantumCell::Existing(&accumulated_extra), + QuantumCell::Existing(accumulated_extra), QuantumCell::Constant(muled_limb_max_fe), ); let (q_acc, mod_acc) = self.div_mod_unsafe(ctx, &accumulated_extra, &limb_max); // If and only if `a` is equal to `b`, lower `self.limb_width` bits of `sum` and `accumulated_extra` are the same. let cs_acc_eq = gate.is_equal( ctx, - QuantumCell::Existing(&cs[i]), - QuantumCell::Existing(&mod_acc), + QuantumCell::Existing(cs[i]), + QuantumCell::Existing(mod_acc), ); eq_bit = gate.and( ctx, - QuantumCell::Existing(&eq_bit), - QuantumCell::Existing(&cs_acc_eq), + QuantumCell::Existing(eq_bit), + QuantumCell::Existing(cs_acc_eq), ); accumulated_extra = q_acc; if i < num_limbs - 1 { // Assert that each carry fits in `carry_bits` bits. - range.range_check(ctx, &carry[i + 1], carry_bits); + range.range_check(ctx, carry[i + 1], carry_bits); } else { // The final carry should match the `accumulated_extra`. let final_carry_eq = gate.is_equal( ctx, - QuantumCell::Existing(&carry[i + 1]), - QuantumCell::Existing(&accumulated_extra), + QuantumCell::Existing(carry[i + 1]), + QuantumCell::Existing(accumulated_extra), ); eq_bit = gate.and( ctx, - QuantumCell::Existing(&eq_bit), - QuantumCell::Existing(&final_carry_eq), + QuantumCell::Existing(eq_bit), + QuantumCell::Existing(final_carry_eq), ); } } @@ -613,12 +608,12 @@ impl BigUintInstructions for BigUintConfig { } /// Returns an assigned bit representing whether `a` is less than `b` (`a( + fn is_less_than( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error> { + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, + ) -> Result, Error> { let (_, is_overfloe) = self.sub_unsafe(ctx, a, b)?; // let gate = self.gate(); // let is_overflow_zero = gate.is_zero(ctx, &overflow); @@ -627,118 +622,107 @@ impl BigUintInstructions for BigUintConfig { } /// Returns an assigned bit representing whether `a` is less than or equal to `b` (`a<=b`). - fn is_less_than_or_equal<'v>( + fn is_less_than_or_equal( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error> { + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, + ) -> Result, Error> { let is_less = self.is_less_than(ctx, a, b)?; let is_eq = self.is_equal_fresh(ctx, a, b)?; let gate = self.gate(); - let is_not_eq = gate.not(ctx, QuantumCell::Existing(&is_eq)); + let is_not_eq = gate.not(ctx, QuantumCell::Existing(is_eq)); Ok(gate.and( ctx, - QuantumCell::Existing(&is_less), - QuantumCell::Existing(&is_not_eq), + QuantumCell::Existing(is_less), + QuantumCell::Existing(is_not_eq), )) } /// Returns an assigned bit representing whether `a` is greater than `b` (`a>b`). - fn is_greater_than<'v>( + fn is_greater_than( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error> { + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, + ) -> Result, Error> { let is_less_than_or_eq = self.is_less_than_or_equal(ctx, a, b)?; Ok(self .gate() - .not(ctx, QuantumCell::Existing(&is_less_than_or_eq))) + .not(ctx, QuantumCell::Existing(is_less_than_or_eq))) } /// Returns an assigned bit representing whether `a` is greater than or equal to `b` (`a>=b`). - fn is_greater_than_or_equal<'v>( + fn is_greater_than_or_equal( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error> { + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, + ) -> Result, Error> { let is_less_than = self.is_less_than(ctx, a, b)?; - Ok(self.gate().not(ctx, QuantumCell::Existing(&is_less_than))) + Ok(self.gate().not(ctx, QuantumCell::Existing(is_less_than))) } /// Returns an assigned bit representing whether `a` is in the order-`n` finite field. - fn is_in_field<'v>( + fn is_in_field( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - n: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error> { + ctx: &mut Context, + a: &AssignedBigUint, + n: &AssignedBigUint, + ) -> Result, Error> { self.is_less_than(ctx, a, n) } /// Assert that an assigned bit representing whether `a` and `b` are equivalent, whose [`RangeType`] is [`Fresh`]. - fn assert_equal_fresh<'v>( + fn assert_equal_fresh( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, ) -> Result<(), Error> { let result = self.is_equal_fresh(ctx, a, b)?; - self.gate().assert_is_const(ctx, &result, F::one()); + self.gate().assert_is_const(ctx, &result, &F::from(1)); Ok(()) } /// Assert that an assigned bit representing whether `a` and `b` are equivalent, whose [`RangeType`] is [`Fresh`]. - fn assert_equal_muled<'v>( + fn assert_equal_muled( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Muled>, - b: &AssignedBigUint<'v, F, Muled>, + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, num_limbs_l: usize, num_limbs_r: usize, ) -> Result<(), Error> { let result = self.is_equal_muled(ctx, a, b, num_limbs_l, num_limbs_r)?; - self.gate().assert_is_const(ctx, &result, F::one()); + self.gate().assert_is_const(ctx, &result, &F::from(1)); Ok(()) } /// Assert that an assigned bit representing whether `a` is in the order-`n` finite field. - fn assert_in_field<'v>( + fn assert_in_field( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, ) -> Result<(), Error> { let result = self.is_in_field(ctx, a, b)?; - self.gate().assert_is_const(ctx, &result, F::one()); + self.gate().assert_is_const(ctx, &result, &F::from(1)); Ok(()) } } -impl BigUintConfig { +impl BigUintConfig { /// Construct a new [`BigIntChip`] from the configuration and parameters. /// /// # Arguments /// /// # Return values /// Returns a new [`BigIntChip`] - pub fn construct(range: RangeConfig, limb_bits: usize) -> Self { + pub fn construct(range: RangeChip, limb_bits: usize) -> Self { Self { range, limb_bits } } - pub fn new_context<'a, 'b>(&'b self, region: Region<'a, F>) -> Context<'a, F> { - Context::new( - region, - ContextParams { - max_rows: self.range.gate.max_rows, - num_context_ids: 1, - fixed_columns: self.range.gate.constants.clone(), - }, - ) - } - /// Returns the fewest bits necessary to express the [`BigUint`]. fn bits_size(val: &BigInt) -> usize { val.bits() as usize @@ -780,44 +764,42 @@ impl BigUintConfig { /// Given a integer `a` and a divisor `n`, performs `a/n` and `a mod n`. /// # Panics /// Panics if `n=0`. - fn div_mod_unsafe<'v>( + fn div_mod_unsafe( &self, - ctx: &mut Context<'v, F>, - a: &AssignedValue<'v, F>, + ctx: &mut Context, + a: &AssignedValue, b: &BigInt, - ) -> (AssignedValue<'v, F>, AssignedValue<'v, F>) { + ) -> (AssignedValue, AssignedValue) { let gate = self.gate(); - let (q_val, n_val) = a - .value - .map(|a| { - let a = fe_to_bigint(&a); - let (q_val, n_val) = (&a / b, &a % b); - (bigint_to_fe(&q_val), bigint_to_fe(&n_val)) - }) - .unzip(); - let q = gate.load_witness(ctx, q_val); - let n = gate.load_witness(ctx, n_val); + let (q_val, n_val) = { + let a = fe_to_bigint(a.value()); + let (q_val, n_val) = (&a / b, &a % b); + (bigint_to_fe(&q_val), bigint_to_fe(&n_val)) + }; + + let q = ctx.load_witness(q_val); + let n = ctx.load_witness(n_val); let prod = gate.mul( ctx, - QuantumCell::Existing(&q), + QuantumCell::Existing(q), QuantumCell::Constant(bigint_to_fe(b)), ); - let a_prod_sub = gate.sub(ctx, QuantumCell::Existing(&a), QuantumCell::Existing(&prod)); + let a_prod_sub = gate.sub(ctx, QuantumCell::Existing(*a), QuantumCell::Existing(prod)); let is_eq = gate.is_equal( ctx, - QuantumCell::Existing(&n), - QuantumCell::Existing(&a_prod_sub), + QuantumCell::Existing(n), + QuantumCell::Existing(a_prod_sub), ); - gate.assert_is_const(ctx, &is_eq, F::one()); + gate.assert_is_const(ctx, &is_eq, &F::from(1)); (q, n) } - // fn carry_mod<'v>( + // fn carry_mod( // &self, - // ctx: &mut Context<'v, F>, - // a: &CRTInteger<'v, F>, + // ctx: &mut Context, + // a: &CRTInteger, // carry_mod_params: CarryModParams, - // ) -> CRTInteger<'v, F> { + // ) -> CRTInteger { // carry_mod::crt( // self.range(), // ctx, @@ -836,1964 +818,2022 @@ impl BigUintConfig { #[cfg(test)] mod test { use std::str::FromStr; - use super::*; - use crate::big_pow_mod; - use halo2_base::halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner}, - dev::MockProver, - halo2curves::bn256::Fr, - plonk::{Circuit, ConstraintSystem}, - }; - use halo2_base::{gates::range::RangeStrategy::Vertical, ContextParams, SKIP_FIRST_PASS}; - use num_traits::FromPrimitive; - - macro_rules! impl_bigint_test_circuit { - ($circuit_name:ident, $test_fn_name:ident, $limb_width:expr, $bits_len:expr, $k:expr, $should_be_error:expr, $( $synth:tt )*) => { - struct $circuit_name { - a: BigUint, - b: BigUint, - n: BigUint, - _f: PhantomData, - } - - impl $circuit_name { - const LIMB_WIDTH: usize = $limb_width; - const BITS_LEN: usize = $bits_len; - const NUM_ADVICE:usize = 50; - const NUM_FIXED:usize = 1; - const NUM_LOOKUP_ADVICE:usize = 4; - const LOOKUP_BITS:usize = 12; - } - - impl Circuit for $circuit_name { - type Config = BigUintConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - unimplemented!(); - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let range_config = RangeConfig::configure(meta,Vertical, &[Self::NUM_ADVICE], &[Self::NUM_LOOKUP_ADVICE], Self::NUM_FIXED, Self::LOOKUP_BITS, 0, $k); - let bigint_config = BigUintConfig::construct(range_config, Self::LIMB_WIDTH); - bigint_config - } - - $( $synth )* + use halo2_base::halo2_proofs::halo2curves::bn256::Fr; + use halo2_base::utils::testing::base_test; + + #[test] + fn test_add() { + // Uncomment to enable RUST_LOG + // env_logger::init(); + + let k: usize = 18; + + // Circuit inputs + let limb_bits = 64; + + base_test().k(k as u32).lookup_bits(k - 1).run(|ctx, range| { + // Configure range chip + let range = range.clone(); + let chip = BigUintConfig::construct(range, 64); + let a_limbs = vec![ + ctx.load_witness(Fr::one()), + ctx.load_witness(Fr::one()), + ctx.load_witness(Fr::one()), + ctx.load_witness(Fr::one()), + ctx.load_witness(Fr::one()), + ctx.load_witness(Fr::one()), + ]; + let b_limbs = vec![ + ctx.load_witness(Fr::one()), + ctx.load_witness(Fr::zero()), + ctx.load_witness(Fr::one()), + ctx.load_witness(Fr::one()), + ctx.load_witness(Fr::one()), + ctx.load_witness(Fr::one()), + ]; + // 1 + 2^64 + 2^128 + 2^192 + 2^256 + 2^320 + let a = AssignedBigUint::::new( + OverflowInteger::new(a_limbs.clone(), limb_bits), + BigUint::from_str("2135987035920910082510813795406868310032552609100727358564487664277988894699682310826844728852481").unwrap(), + ); + // 1 + 2^128 + 2^192 + 2^256 + 2^320 + let b = AssignedBigUint::::new( + OverflowInteger::new(b_limbs.clone(), limb_bits), + BigUint::from_str("2135987035920910082510813795406868310032552609100727358564487664277988894699663864082771019300865").unwrap(), + ); + let output = chip.add(ctx, &a, &b).unwrap(); + assert_eq!(output.value(), a.value() + b.value()); + for i in 0..a_limbs.len() { + assert_eq!(*output.limb(i).value(), a_limbs[i].value() + b_limbs[i].value()); } - - #[test] - fn $test_fn_name() { - use num_bigint::RandomBits; - use rand::{thread_rng, Rng}; - fn run() { - let mut rng = thread_rng(); - let bits_len = $circuit_name::::BITS_LEN as u64; - let mut n = BigUint::default(); - while n.bits() != bits_len { - n = rng.sample(RandomBits::new(bits_len)); - } - let a = rng.sample::(RandomBits::new(bits_len)) % &n; - let b = rng.sample::(RandomBits::new(bits_len)) % &n; - let circuit = $circuit_name:: { - a, - b, - n, - _f: PhantomData, - }; - - let public_inputs = vec![]; - let k = $k; - let prover = match MockProver::run(k, &circuit, public_inputs) { - Ok(prover) => prover, - Err(e) => panic!("{:#?}", e) - }; - if $should_be_error { - assert!(prover.verify().is_err()); - } else { - prover.verify().unwrap(); - } - } - run::(); - } - }; + }); + } - - impl_bigint_test_circuit!( - TestAddCircuit, - test_add_circuit, - 64, - 2048, - 13, - false, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "random add test", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let a_assigned = - config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; - let b_assigned = - config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; - let ab = config.add(ctx, &a_assigned, &b_assigned)?; - let ba = config.add(ctx, &b_assigned, &a_assigned)?; - config.assert_equal_fresh(ctx, &ab, &ba)?; - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - impl_bigint_test_circuit!( - TestBadAddCircuit, - test_bad_add_circuit, - 64, - 2048, - 13, - true, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "random add test", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let a_assigned = - config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; - let b_assigned = - config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; - let ab = config.add(ctx, &a_assigned, &b_assigned)?; - let n_assigned = - config.assign_integer(ctx, Value::known(self.n.clone()), Self::BITS_LEN)?; - let zero_value = config.gate().load_zero(ctx); - let n_assigned = n_assigned.extend_limbs(1, zero_value); - config.assert_equal_fresh(ctx, &ab, &n_assigned)?; - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - impl_bigint_test_circuit!( - TestSubCircuit, - test_sub_circuit, - 64, - 2048, - 13, - false, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "random add test", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let b: BigUint = &self.b >> 128; - let a_assigned = - config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; - let b_assigned = - config.assign_integer(ctx, Value::known(b.clone()), Self::BITS_LEN)?; - let sub = &self.a - &b; - let sub_assigned = config.assign_constant(ctx, sub)?; - let (ab, is_overflow) = config.sub_unsafe(ctx, &a_assigned, &b_assigned)?; - config.assert_equal_fresh(ctx, &ab, &sub_assigned)?; - config.gate().assert_is_const(ctx, &is_overflow, F::zero()); - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - impl_bigint_test_circuit!( - TestOverflowSubCircuit, - test_overflow_sub_circuit, - 64, - 2048, - 13, - false, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "random add test", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let a: BigUint = &self.a >> 128; - let b: BigUint = self.b.clone(); - let a_assigned = - config.assign_integer(ctx, Value::known(a.clone()), Self::BITS_LEN)?; - let b_assigned = - config.assign_integer(ctx, Value::known(b.clone()), Self::BITS_LEN)?; - let (_, is_overflow) = config.sub_unsafe(ctx, &a_assigned, &b_assigned)?; - config.gate().assert_is_const(ctx, &is_overflow, F::one()); - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - // impl_bigint_test_circuit!( - // TestBadSubCircuit, - // test_bad_sub_circuit, - // 64, - // 2048, - // 13, - // true, - // fn synthesize( - // &self, - // config: Self::Config, - // mut layouter: impl Layouter, - // ) -> Result<(), Error> { - // config.range().load_lookup_table(&mut layouter)?; - // let mut first_pass = SKIP_FIRST_PASS; - // layouter.assign_region( - // || "random add test", - // |region| { - // if first_pass { - // first_pass = false; - // return Ok(()); - // } - - // let mut aux = config.new_context(region); - // let ctx = &mut aux; - // let a_assigned = - // config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; - // let b_assigned = - // config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; - // let n_assigned = - // config.assign_integer(ctx, Value::known(self.n.clone()), Self::BITS_LEN)?; - // let (ab, _) = config.sub_unsafe(ctx, &a_assigned, &b_assigned)?; - // config.assert_equal_fresh(ctx, &ab, &n_assigned)?; - // config.range().finalize(ctx); - // { - // println!("total advice cells: {}", ctx.total_advice); - // let const_rows = ctx.total_fixed + 1; - // println!("maximum rows used by a fixed column: {const_rows}"); - // println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - // } - // Ok(()) - // }, - // )?; - // Ok(()) - // } - // ); - - impl_bigint_test_circuit!( - TestMulCircuit, - test_mul_circuit, - 64, - 2048, - 13, - false, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "random mul test", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let a_assigned = - config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; - let b_assigned = - config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; - config.mul(ctx, &a_assigned, &b_assigned)?; - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - impl_bigint_test_circuit!( - TestFreshEqualCircuit, - test_fresh_equal_circuit, - 64, - 2048, - 13, - false, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "random add test", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let a_assigned = - config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; - let b_assigned = - config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; - config.assert_equal_fresh(ctx, &a_assigned, &a_assigned)?; - config.assert_equal_fresh(ctx, &b_assigned, &b_assigned)?; - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - impl_bigint_test_circuit!( - TestBadFreshEqualCircuit, - test_bad_fresh_equal_circuit, - 64, - 2048, - 13, - true, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "random add test", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let a_assigned = - config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; - let b_assigned = - config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; - config.assert_equal_fresh(ctx, &a_assigned, &b_assigned)?; - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - impl_bigint_test_circuit!( - TestMuledEqualCircuit, - test_muled_equal_circuit, - 64, - 2048, - 13, - false, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "random refresh test", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let a_assigned = - config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; - let b_assigned = - config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; - let ab = config.mul(ctx, &a_assigned, &b_assigned)?; - let ba = config.mul(ctx, &b_assigned, &a_assigned)?; - let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; - config.assert_equal_muled(ctx, &ab, &ba, num_limbs, num_limbs)?; - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - impl_bigint_test_circuit!( - TestBadMuledEqualCircuit, - test_bad_muled_equal_circuit, - 64, - 2048, - 13, - true, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "random refresh test", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let a_assigned = - config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; - let b_assigned = - config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; - let ab = config.mul(ctx, &a_assigned, &b_assigned)?; - let zero = config.assign_constant(ctx, BigUint::zero())?; - let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; - let zero_value = config.gate().load_zero(ctx); - let zero = zero - .extend_limbs(ab.num_limbs() - zero.num_limbs(), zero_value) - .to_muled(); - config.assert_equal_muled(ctx, &ab, &zero, num_limbs, num_limbs)?; - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - impl_bigint_test_circuit!( - TestRefreshCircuit, - test_refresh_circuit, - 64, - 2048, - 13, - false, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "random refresh test", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let a_assigned = - config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; - let b_assigned = - config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; - let ab = config.mul(ctx, &a_assigned, &b_assigned)?; - let ba = config.mul(ctx, &b_assigned, &a_assigned)?; - let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; - let aux = RefreshAux::new(Self::LIMB_WIDTH, num_limbs, num_limbs); - let ab_refreshed = config.refresh(ctx, &ab, &aux)?; - let ba_refreshed = config.refresh(ctx, &ba, &aux)?; - config.assert_equal_fresh(ctx, &ab_refreshed, &ba_refreshed)?; - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - impl_bigint_test_circuit!( - TestThreeMulCircuit, - test_three_mul_circuit, - 64, - 2048, - 13, - false, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "random mul test", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let a_assigned = - config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; - let b_assigned = - config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; - let n_assigned = - config.assign_integer(ctx, Value::known(self.n.clone()), Self::BITS_LEN)?; - let ab = config.mul(ctx, &a_assigned, &b_assigned)?; - let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; - let aux = RefreshAux::new(Self::LIMB_WIDTH, num_limbs, num_limbs); - let ab_refreshed = config.refresh(ctx, &ab, &aux)?; - let refreshed_num_limbs = ab_refreshed.num_limbs(); - let abn = config.mul(ctx, &ab_refreshed, &n_assigned)?; - abn.value.as_ref().map(|v| println!("abn {:?}", v)); - let nb = config.mul(ctx, &n_assigned, &b_assigned)?; - let nb_refreshed = config.refresh(ctx, &nb, &aux)?; - let nba = config.mul(ctx, &a_assigned, &nb_refreshed)?; - nba.value.as_ref().map(|v| println!("nba {:?}", v)); - config.assert_equal_muled(ctx, &abn, &nba, refreshed_num_limbs, num_limbs)?; - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - impl_bigint_test_circuit!( - TestAddModCircuit, - test_add_mod_circuit, - 64, - 2048, - 13, - false, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "random refresh test", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let a_assigned = - config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; - let b_assigned = - config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; - let n_assigned = - config.assign_integer(ctx, Value::known(self.n.clone()), Self::BITS_LEN)?; - let ab = config.add_mod(ctx, &a_assigned, &b_assigned, &n_assigned)?; - let ba = config.add_mod(ctx, &b_assigned, &a_assigned, &n_assigned)?; - let is_eq = config.is_equal_fresh(ctx, &ab, &ba)?; - config.gate().assert_is_const(ctx, &is_eq, F::one()); - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - impl_bigint_test_circuit!( - TestBadAddModCircuit, - test_bad_add_mod_circuit, - 64, - 2048, - 13, - true, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "random refresh test", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let a_assigned = - config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; - let b_assigned = - config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; - let n_assigned = - config.assign_integer(ctx, Value::known(self.n.clone()), Self::BITS_LEN)?; - let ab = config.add_mod(ctx, &a_assigned, &b_assigned, &n_assigned)?; - let is_eq = config.is_equal_fresh(ctx, &ab, &n_assigned)?; - config.gate().assert_is_const(ctx, &is_eq, F::one()); - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - // impl_bigint_test_circuit!( - // TestSubModCircuit, - // test_sub_mod_circuit, - // 64, - // 2048, - // false, - // fn synthesize( - // &self, - // config: Self::Config, - // mut layouter: impl halo2wrong::halo2::circuit::Layouter, - // ) -> Result<(), Error> { - // let bigint_chip = self.bigint_chip(config); - // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; - // layouter.assign_region( - // || "random sub_mod test", - // |region| { - // let offset = 0; - // let ctx = &mut RegionCtx::new(region, offset); - // let sub = if &self.a >= &self.b { - // &self.a - &self.b - // } else { - // &self.a + &self.n - &self.b - // }; - // let a_limbs = decompose_big::(self.a.clone(), num_limbs, Self::LIMB_WIDTH); - // let a_unassigned = UnassignedInteger::from(a_limbs); - // let b_limbs = decompose_big::(self.b.clone(), num_limbs, Self::LIMB_WIDTH); - // let b_unassigned = UnassignedInteger::from(b_limbs); - // let n_limbs = decompose_big::(self.n.clone(), num_limbs, Self::LIMB_WIDTH); - // let n_unassigned = UnassignedInteger::from(n_limbs); - // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; - // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; - // let n_assigned = bigint_chip.assign_integer(ctx, n_unassigned)?; - // let ab = bigint_chip.sub_mod(ctx, &a_assigned, &b_assigned, &n_assigned)?; - // let sub_assigned = bigint_chip.assign_constant_fresh(ctx, sub)?; - // bigint_chip.assert_equal_fresh(ctx, &ab, &sub_assigned)?; - // Ok(()) - // }, - // )?; - // let range_chip = bigint_chip.range_chip(); - // range_chip.load_table(&mut layouter)?; - // //range_chip.load_overflow_tables(&mut layouter)?; - // Ok(()) - // } - // ); - - // impl_bigint_test_circuit!( - // TestSubModOverflowCircuit, - // test_sub_mod_overflow_circuit, - // 64, - // 2048, - // true, - // fn synthesize( - // &self, - // config: Self::Config, - // mut layouter: impl halo2wrong::halo2::circuit::Layouter, - // ) -> Result<(), Error> { - // let bigint_chip = self.bigint_chip(config); - // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; - // layouter.assign_region( - // || "random sub_mod overflow test", - // |region| { - // let offset = 0; - // let ctx = &mut RegionCtx::new(region, offset); - // let a_limbs = decompose_big::(self.a.clone(), num_limbs, Self::LIMB_WIDTH); - // let a_unassigned = UnassignedInteger::from(a_limbs); - // let b_limbs = decompose_big::(self.b.clone(), num_limbs, Self::LIMB_WIDTH); - // let b_unassigned = UnassignedInteger::from(b_limbs); - // let n_limbs = - // decompose_big::(self.n.clone() >> 1024, num_limbs, Self::LIMB_WIDTH); - // let n_unassigned = UnassignedInteger::from(n_limbs); - // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; - // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; - // let n_assigned = bigint_chip.assign_integer(ctx, n_unassigned)?; - // bigint_chip.sub_mod(ctx, &a_assigned, &b_assigned, &n_assigned)?; - // Ok(()) - // }, - // )?; - // let range_chip = bigint_chip.range_chip(); - // range_chip.load_table(&mut layouter)?; - // //range_chip.load_overflow_tables(&mut layouter)?; - // Ok(()) - // } - // ); - - // impl_bigint_test_circuit!( - // TestBadSubModCircuit, - // test_bad_sub_mod_circuit, - // 64, - // 2048, - // true, - // fn synthesize( - // &self, - // config: Self::Config, - // mut layouter: impl halo2wrong::halo2::circuit::Layouter, - // ) -> Result<(), Error> { - // let bigint_chip = self.bigint_chip(config); - // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; - // layouter.assign_region( - // || "random sub_mod test with an error case", - // |region| { - // let offset = 0; - // let ctx = &mut RegionCtx::new(region, offset); - // let a_limbs = decompose_big::(self.a.clone(), num_limbs, Self::LIMB_WIDTH); - // let a_unassigned = UnassignedInteger::from(a_limbs); - // let b_limbs = decompose_big::(self.b.clone(), num_limbs, Self::LIMB_WIDTH); - // let b_unassigned = UnassignedInteger::from(b_limbs); - // let n_limbs = decompose_big::(self.n.clone(), num_limbs, Self::LIMB_WIDTH); - // let n_unassigned = UnassignedInteger::from(n_limbs); - // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; - // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; - // let n_assigned = bigint_chip.assign_integer(ctx, n_unassigned)?; - // let ab = bigint_chip.sub_mod(ctx, &a_assigned, &b_assigned, &n_assigned)?; - // bigint_chip.assert_equal_fresh(ctx, &ab, &n_assigned)?; - // Ok(()) - // }, - // )?; - // let range_chip = bigint_chip.range_chip(); - // range_chip.load_table(&mut layouter)?; - // //range_chip.load_overflow_tables(&mut layouter)?; - // Ok(()) - // } - // ); - - impl_bigint_test_circuit!( - TestMulModCircuit, - test_mul_mod_circuit, - 64, - 2048, - 13, - false, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "random refresh test", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let a_assigned = - config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; - let b_assigned = - config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; - let n_assigned = - config.assign_integer(ctx, Value::known(self.n.clone()), Self::BITS_LEN)?; - let ab = config.mul_mod(ctx, &a_assigned, &b_assigned, &n_assigned)?; - let ba = config.mul_mod(ctx, &b_assigned, &a_assigned, &n_assigned)?; - let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; - config.assert_equal_fresh(ctx, &ab, &ba)?; - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - impl_bigint_test_circuit!( - TestBadMulModCircuit, - test_bad_mul_mod_circuit, - 64, - 2048, - 13, - true, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "random refresh test", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let a_assigned = - config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; - let b_assigned = - config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; - let n_assigned = - config.assign_integer(ctx, Value::known(self.n.clone()), Self::BITS_LEN)?; - let ab = config.mul_mod(ctx, &a_assigned, &b_assigned, &n_assigned)?; - let zero = config.assign_constant(ctx, BigUint::zero())?; - let zero_value = config.gate().load_zero(ctx); - let zero = zero.extend_limbs(ab.num_limbs() - zero.num_limbs(), zero_value); - config.assert_equal_fresh(ctx, &ab, &zero)?; - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - impl_bigint_test_circuit!( - TestPowModFixedExpCircuit, - test_pow_mod_fixed_exp_circuit, - 64, - 2048, - 13, - false, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "random pow_mod test", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let a_assigned = - config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; - let n_assigned = - config.assign_integer(ctx, Value::known(self.n.clone()), Self::BITS_LEN)?; - let e = BigUint::from_u64(65537).unwrap(); - let powed = config.pow_mod_fixed_exp(ctx, &a_assigned, &e, &n_assigned)?; - let ans_big = big_pow_mod(&self.a, &e, &self.n); - let ans_assigned = config.assign_constant(ctx, ans_big)?; - config.assert_equal_fresh(ctx, &powed, &ans_assigned)?; - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - impl_bigint_test_circuit!( - TestBadPowModFixedExpCircuit, - test_bad_pow_mod_fixed_exp_circuit, - 64, - 2048, - 13, - true, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "random pow_mod test", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let a_assigned = - config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; - let n_assigned = - config.assign_integer(ctx, Value::known(self.n.clone()), Self::BITS_LEN)?; - let e = BigUint::from_u64(65537).unwrap(); - let powed = config.pow_mod_fixed_exp(ctx, &a_assigned, &e, &n_assigned)?; - let zero = config.assign_constant(ctx, BigUint::zero())?; - let zero_value = config.gate().load_zero(ctx); - let zero = zero.extend_limbs(powed.num_limbs() - zero.num_limbs(), zero_value); - config.assert_equal_fresh(ctx, &powed, &zero)?; - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - // impl_bigint_test_circuit!( - // TestIsZeroCircuit, - // test_is_zero_circuit, - // 64, - // 2048, - // false, - // fn synthesize( - // &self, - // config: Self::Config, - // mut layouter: impl halo2wrong::halo2::circuit::Layouter, - // ) -> Result<(), Error> { - // let bigint_chip = self.bigint_chip(config); - // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; - // layouter.assign_region( - // || "random is_zero test", - // |region| { - // let offset = 0; - // let ctx = &mut RegionCtx::new(region, offset); - // assert!(self.a != BigUint::from(0usize)); - // let a_limbs = decompose_big::(self.a.clone(), num_limbs, Self::LIMB_WIDTH); - // let a_unassigned = UnassignedInteger::from(a_limbs); - // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; - // let zero = bigint_chip.assign_constant_fresh(ctx, BigUint::from(0usize))?; - // bigint_chip.assert_zero(ctx, &zero)?; - // let a_is_zero = bigint_chip.is_zero(ctx, &a_assigned)?; - // let main_gate = bigint_chip.main_gate(); - // main_gate.assert_zero(ctx, &a_is_zero)?; - // Ok(()) - // }, - // )?; - // let range_chip = bigint_chip.range_chip(); - // range_chip.load_table(&mut layouter)?; - // //range_chip.load_overflow_tables(&mut layouter)?; - // Ok(()) - // } - // ); - - // impl_bigint_test_circuit!( - // TestLessThanCircuit, - // test_less_than_circuit, - // 64, - // 2048, - // false, - // fn synthesize( - // &self, - // config: Self::Config, - // mut layouter: impl halo2wrong::halo2::circuit::Layouter, - // ) -> Result<(), Error> { - // let bigint_chip = self.bigint_chip(config); - // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; - // layouter.assign_region( - // || "random assert_less_than test", - // |region| { - // let offset = 0; - // let ctx = &mut RegionCtx::new(region, offset); - // let a = &self.a >> 128; - // let b = self.b.clone(); - // let a_limbs = decompose_big::(a, num_limbs, Self::LIMB_WIDTH); - // let a_unassigned = UnassignedInteger::from(a_limbs); - // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; - // let b_limbs = decompose_big::(b, num_limbs, Self::LIMB_WIDTH); - // let b_unassigned = UnassignedInteger::from(b_limbs); - // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; - // bigint_chip.assert_less_than(ctx, &a_assigned, &b_assigned)?; - // Ok(()) - // }, - // )?; - // let range_chip = bigint_chip.range_chip(); - // range_chip.load_table(&mut layouter)?; - // //range_chip.load_overflow_tables(&mut layouter)?; - // Ok(()) - // } - // ); - - // impl_bigint_test_circuit!( - // TestBadLessThanCircuit, - // test_bad_less_than_circuit, - // 64, - // 2048, - // true, - // fn synthesize( - // &self, - // config: Self::Config, - // mut layouter: impl halo2wrong::halo2::circuit::Layouter, - // ) -> Result<(), Error> { - // let bigint_chip = self.bigint_chip(config); - // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; - // layouter.assign_region( - // || "random assert_less_than test with an error case", - // |region| { - // let offset = 0; - // let ctx = &mut RegionCtx::new(region, offset); - // let a = self.a.clone(); - // let b = self.b.clone() >> 128; - // let a_limbs = decompose_big::(a, num_limbs, Self::LIMB_WIDTH); - // let a_unassigned = UnassignedInteger::from(a_limbs); - // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; - // let b_limbs = decompose_big::(b, num_limbs, Self::LIMB_WIDTH); - // let b_unassigned = UnassignedInteger::from(b_limbs); - // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; - // bigint_chip.assert_less_than(ctx, &a_assigned, &b_assigned)?; - // Ok(()) - // }, - // )?; - // let range_chip = bigint_chip.range_chip(); - // range_chip.load_table(&mut layouter)?; - // //range_chip.load_overflow_tables(&mut layouter)?; - // Ok(()) - // } - // ); - - // impl_bigint_test_circuit!( - // TestLessThanOrEqualCircuit, - // test_less_than_or_equal_circuit, - // 64, - // 2048, - // false, - // fn synthesize( - // &self, - // config: Self::Config, - // mut layouter: impl halo2wrong::halo2::circuit::Layouter, - // ) -> Result<(), Error> { - // let bigint_chip = self.bigint_chip(config); - // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; - // layouter.assign_region( - // || "random assert_less_than_or_equal test", - // |region| { - // let offset = 0; - // let ctx = &mut RegionCtx::new(region, offset); - // let a = self.a.clone(); - // let b = self.a.clone(); - // let a_limbs = decompose_big::(a, num_limbs, Self::LIMB_WIDTH); - // let a_unassigned = UnassignedInteger::from(a_limbs); - // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; - // let b_limbs = decompose_big::(b, num_limbs, Self::LIMB_WIDTH); - // let b_unassigned = UnassignedInteger::from(b_limbs); - // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; - // bigint_chip.assert_less_than_or_equal(ctx, &a_assigned, &b_assigned)?; - // Ok(()) - // }, - // )?; - // let range_chip = bigint_chip.range_chip(); - // range_chip.load_table(&mut layouter)?; - // //range_chip.load_overflow_tables(&mut layouter)?; - // Ok(()) - // } - // ); - - // impl_bigint_test_circuit!( - // TestBadLessThanOrEqualCircuit, - // test_bad_less_than_or_equal_circuit, - // 64, - // 2048, - // true, - // fn synthesize( - // &self, - // config: Self::Config, - // mut layouter: impl halo2wrong::halo2::circuit::Layouter, - // ) -> Result<(), Error> { - // let bigint_chip = self.bigint_chip(config); - // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; - // layouter.assign_region( - // || "random assert_less_than_or_equal test with an error case", - // |region| { - // let offset = 0; - // let ctx = &mut RegionCtx::new(region, offset); - // let a = self.a.clone(); - // let b = self.b.clone() >> 128; - // let a_limbs = decompose_big::(a, num_limbs, Self::LIMB_WIDTH); - // let a_unassigned = UnassignedInteger::from(a_limbs); - // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; - // let b_limbs = decompose_big::(b, num_limbs, Self::LIMB_WIDTH); - // let b_unassigned = UnassignedInteger::from(b_limbs); - // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; - // bigint_chip.assert_less_than_or_equal(ctx, &a_assigned, &b_assigned)?; - // Ok(()) - // }, - // )?; - // let range_chip = bigint_chip.range_chip(); - // range_chip.load_table(&mut layouter)?; - // //range_chip.load_overflow_tables(&mut layouter)?; - // Ok(()) - // } - // ); - - // impl_bigint_test_circuit!( - // TestGreaterThanCircuit, - // test_greater_than_circuit, - // 64, - // 2048, - // false, - // fn synthesize( - // &self, - // config: Self::Config, - // mut layouter: impl halo2wrong::halo2::circuit::Layouter, - // ) -> Result<(), Error> { - // let bigint_chip = self.bigint_chip(config); - // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; - // layouter.assign_region( - // || "random assert_greater_than test", - // |region| { - // let offset = 0; - // let ctx = &mut RegionCtx::new(region, offset); - // let a = self.a.clone(); - // let b = self.a.clone() >> 128; - // let a_limbs = decompose_big::(a, num_limbs, Self::LIMB_WIDTH); - // let a_unassigned = UnassignedInteger::from(a_limbs); - // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; - // let b_limbs = decompose_big::(b, num_limbs, Self::LIMB_WIDTH); - // let b_unassigned = UnassignedInteger::from(b_limbs); - // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; - // bigint_chip.assert_greater_than(ctx, &a_assigned, &b_assigned)?; - // Ok(()) - // }, - // )?; - // let range_chip = bigint_chip.range_chip(); - // range_chip.load_table(&mut layouter)?; - // //range_chip.load_overflow_tables(&mut layouter)?; - // Ok(()) - // } - // ); - - // impl_bigint_test_circuit!( - // TestBadGreaterThanCircuit, - // test_bad_greater_than_circuit, - // 64, - // 2048, - // true, - // fn synthesize( - // &self, - // config: Self::Config, - // mut layouter: impl halo2wrong::halo2::circuit::Layouter, - // ) -> Result<(), Error> { - // let bigint_chip = self.bigint_chip(config); - // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; - // layouter.assign_region( - // || "random assert_greater_than test with an error case", - // |region| { - // let offset = 0; - // let ctx = &mut RegionCtx::new(region, offset); - // let a = self.a.clone() >> 128; - // let b = self.b.clone(); - // let a_limbs = decompose_big::(a, num_limbs, Self::LIMB_WIDTH); - // let a_unassigned = UnassignedInteger::from(a_limbs); - // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; - // let b_limbs = decompose_big::(b, num_limbs, Self::LIMB_WIDTH); - // let b_unassigned = UnassignedInteger::from(b_limbs); - // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; - // bigint_chip.assert_greater_than(ctx, &a_assigned, &b_assigned)?; - // Ok(()) - // }, - // )?; - // let range_chip = bigint_chip.range_chip(); - // range_chip.load_table(&mut layouter)?; - // //range_chip.load_overflow_tables(&mut layouter)?; - // Ok(()) - // } - // ); - - // impl_bigint_test_circuit!( - // TestGreaterThanOrEqualCircuit, - // test_greater_than_or_equal_circuit, - // 64, - // 2048, - // false, - // fn synthesize( - // &self, - // config: Self::Config, - // mut layouter: impl halo2wrong::halo2::circuit::Layouter, - // ) -> Result<(), Error> { - // let bigint_chip = self.bigint_chip(config); - // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; - // layouter.assign_region( - // || "random assert_greater_than_or_equal test", - // |region| { - // let offset = 0; - // let ctx = &mut RegionCtx::new(region, offset); - // let a = self.a.clone(); - // let b = self.a.clone(); - // let a_limbs = decompose_big::(a, num_limbs, Self::LIMB_WIDTH); - // let a_unassigned = UnassignedInteger::from(a_limbs); - // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; - // let b_limbs = decompose_big::(b, num_limbs, Self::LIMB_WIDTH); - // let b_unassigned = UnassignedInteger::from(b_limbs); - // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; - // bigint_chip.assert_greater_than_or_equal(ctx, &a_assigned, &b_assigned)?; - // Ok(()) - // }, - // )?; - // let range_chip = bigint_chip.range_chip(); - // range_chip.load_table(&mut layouter)?; - // //range_chip.load_overflow_tables(&mut layouter)?; - // Ok(()) - // } - // ); - - // impl_bigint_test_circuit!( - // TestBadGreaterThanOrEqualCircuit, - // test_bad_greater_than_or_equal_circuit, - // 64, - // 2048, - // true, - // fn synthesize( - // &self, - // config: Self::Config, - // mut layouter: impl halo2wrong::halo2::circuit::Layouter, - // ) -> Result<(), Error> { - // let bigint_chip = self.bigint_chip(config); - // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; - // layouter.assign_region( - // || "random assert_greater_than_or_equal test with an error case", - // |region| { - // let offset = 0; - // let ctx = &mut RegionCtx::new(region, offset); - // let a = self.a.clone() >> 128; - // let b = self.b.clone(); - // let a_limbs = decompose_big::(a, num_limbs, Self::LIMB_WIDTH); - // let a_unassigned = UnassignedInteger::from(a_limbs); - // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; - // let b_limbs = decompose_big::(b, num_limbs, Self::LIMB_WIDTH); - // let b_unassigned = UnassignedInteger::from(b_limbs); - // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; - // bigint_chip.assert_greater_than_or_equal(ctx, &a_assigned, &b_assigned)?; - // Ok(()) - // }, - // )?; - // let range_chip = bigint_chip.range_chip(); - // range_chip.load_table(&mut layouter)?; - // //range_chip.load_overflow_tables(&mut layouter)?; - // Ok(()) - // } - // ); - - impl_bigint_test_circuit!( - TestInFieldCircuit, - test_in_field_circuit, - 64, - 2048, - 13, - false, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "random refresh test", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let a_assigned = - config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; - let n_assigned = - config.assign_integer(ctx, Value::known(self.n.clone()), Self::BITS_LEN)?; - config.assert_in_field(ctx, &a_assigned, &n_assigned)?; - let zero = config.assign_constant(ctx, BigUint::from(0u64))?; - config.assert_in_field(ctx, &zero, &n_assigned)?; - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - impl_bigint_test_circuit!( - TestBadInFieldCircuit, - test_bad_in_field_circuit, - 64, - 2048, - 13, - true, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "random refresh test", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let a_assigned = - config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; - let n_assigned = - config.assign_integer(ctx, Value::known(self.n.clone()), Self::BITS_LEN)?; - let invalid = config.is_in_field(ctx, &n_assigned, &n_assigned)?; - config.gate().assert_is_const(ctx, &invalid, F::one()); - let invalid = config.is_in_field(ctx, &a_assigned, &n_assigned)?; - config.gate().assert_is_const(ctx, &invalid, F::one()); - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - // impl_bigint_test_circuit!( - // TestMulCase1Circuit, - // test_mul_case1, - // 64, - // 2048, - // false, - // fn synthesize( - // &self, - // config: Self::Config, - // mut layouter: impl halo2wrong::halo2::circuit::Layouter, - // ) -> Result<(), Error> { - // let bigint_chip = self.bigint_chip(config); - // layouter.assign_region( - // || "1 * 1 = 1", - // |region| { - // let offset = 0; - // let ctx = &mut RegionCtx::new(region, offset); - // let one = bigint_chip.assign_constant_fresh(ctx, BigUint::from(1usize))?; - // let n = one.num_limbs(); - // let one_muled = bigint_chip.mul(ctx, &one, &one)?; - // let zero = AssignedLimb::from( - // bigint_chip.main_gate().assign_constant(ctx, F::zero())?, - // ); - // bigint_chip.assert_equal_muled(ctx, &one.to_muled(zero), &one_muled, n, n)?; - // Ok(()) - // }, - // )?; - // let range_chip = bigint_chip.range_chip(); - // range_chip.load_table(&mut layouter)?; - // //range_chip.load_overflow_tables(&mut layouter)?; - // Ok(()) - // } - // ); - - // impl_bigint_test_circuit!( - // TestMulCase3Circuit, - // test_mul_case3, - // 64, - // 2048, - // false, - // fn synthesize( - // &self, - // config: Self::Config, - // mut layouter: impl halo2wrong::halo2::circuit::Layouter, - // ) -> Result<(), Error> { - // let bigint_chip = self.bigint_chip(config); - // layouter.assign_region( - // || "(1+0x+3x^2)(3+1x) = 3+1x+9x^2+3x^3", - // |region| { - // let offset = 0; - // let ctx = &mut RegionCtx::new(region, offset); - // let out_base = BigUint::from(1usize) << Self::LIMB_WIDTH; - // let a_big = - // BigUint::from(1usize) + 0usize * &out_base + 3usize * &out_base * &out_base; - // let a_assigned = bigint_chip.assign_constant_fresh(ctx, a_big)?; - // let n1 = a_assigned.num_limbs(); - // let b_big = - // BigUint::from(3usize) + 1usize * &out_base + 0usize * &out_base * &out_base; - // let b_assigned = bigint_chip.assign_constant_fresh(ctx, b_big)?; - // let n2 = b_assigned.num_limbs(); - // let ab = bigint_chip.mul(ctx, &a_assigned, &b_assigned)?; - // let ans_big = BigUint::from(3usize) - // + 1usize * &out_base - // + 9usize * &out_base * &out_base - // + 3usize * &out_base * &out_base * &out_base; - // let ans_assigned = bigint_chip.assign_constant_muled(ctx, ans_big, n1, n2)?; - // bigint_chip.assert_equal_muled(ctx, &ab, &ans_assigned, n1, n2)?; - // Ok(()) - // }, - // )?; - // let range_chip = bigint_chip.range_chip(); - // range_chip.load_table(&mut layouter)?; - // //range_chip.load_overflow_tables(&mut layouter)?; - // Ok(()) - // } - // ); - - // impl_bigint_test_circuit!( - // TestMulCase4Circuit, - // test_mul_case4, - // 64, - // 2048, - // false, - // fn synthesize( - // &self, - // config: Self::Config, - // mut layouter: impl halo2wrong::halo2::circuit::Layouter, - // ) -> Result<(), Error> { - // let bigint_chip = self.bigint_chip(config); - // layouter.assign_region( - // || "(3 + 4x + 5x^2 + 6x^3)(9 + 10x + 11x^2 + 12x^3) = 27 + 66 x + 118 x^2 + 184 x^3 + 163 x^4 + 126 x^5 + 72 x^6 ", - // |region| { - // let offset = 0; - // let ctx = &mut RegionCtx::new(region, offset); - // let out_base = BigUint::from(1usize) << Self::LIMB_WIDTH; - // let a_big = - // BigUint::from(3usize) + 4usize * &out_base + 5usize * &out_base.pow(2) + 6usize * &out_base.pow(3); - // let a_assigned = bigint_chip.assign_constant_fresh(ctx, a_big)?; - // let n1 = a_assigned.num_limbs(); - // let b_big = - // BigUint::from(9usize) + 10usize * &out_base + 11usize * &out_base.pow(2) + 12usize * &out_base.pow(3); - // let b_assigned = bigint_chip.assign_constant_fresh(ctx, b_big)?; - // let n2 = b_assigned.num_limbs(); - // let ab = bigint_chip.mul(ctx, &a_assigned, &b_assigned)?; - // let ans_big = BigUint::from(27usize) + 66usize * &out_base + 118usize * &out_base.pow(2u32) + 184usize * &out_base.pow(3u32) + 163usize * &out_base.pow(4u32) + 126usize * &out_base.pow(5u32) + 72usize * &out_base.pow(6u32); - // let ans_assigned = bigint_chip.assign_constant_muled(ctx, ans_big, n1, n2)?; - // bigint_chip.assert_equal_muled(ctx, &ab, &ans_assigned, n1, n2)?; - // Ok(()) - // }, - // )?; - // let range_chip = bigint_chip.range_chip(); - // range_chip.load_table(&mut layouter)?; - // //range_chip.load_overflow_tables(&mut layouter)?; - // Ok(()) - // } - // ); - - // impl_bigint_test_circuit!( - // TestMulCase5Circuit, - // test_mul_case5, - // 64, - // 2048, - // false, - // fn synthesize( - // &self, - // config: Self::Config, - // mut layouter: impl halo2wrong::halo2::circuit::Layouter, - // ) -> Result<(), Error> { - // let bigint_chip = self.bigint_chip(config); - // layouter.assign_region( - // || "big square test", - // |region| { - // let offset = 0; - // let ctx = &mut RegionCtx::new(region, offset); - // let out_base = BigUint::from(1usize) << Self::LIMB_WIDTH; - // let a_big = BigUint::from(4819187580044832333u128) - // + 9183764011217009606u128 * &out_base - // + 11426964127496009747u128 * &out_base.pow(2) - // + 17898263845095661790u128 * &out_base.pow(3) - // + 12102522037140783322u128 * &out_base.pow(4) - // + 4029304176671511763u128 * &out_base.pow(5) - // + 11339410859987005436u128 * &out_base.pow(6) - // + 12120243430436644729u128 * &out_base.pow(7) - // + 2888435820322958146u128 * &out_base.pow(8) - // + 7612614626488966390u128 * &out_base.pow(9) - // + 3872170484348249672u128 * &out_base.pow(10) - // + 9589147526444685354u128 * &out_base.pow(11) - // + 16391157694429928307u128 * &out_base.pow(12) - // + 12256166884204507566u128 * &out_base.pow(13) - // + 4257963982333550934u128 * &out_base.pow(14) - // + 916988490704u128 * &out_base.pow(15); - // let a_assigned = bigint_chip.assign_constant_fresh(ctx, a_big)?; - // let n1 = a_assigned.num_limbs(); - // let ab = bigint_chip.square(ctx, &a_assigned)?; - // let ans_big = BigUint::from(23224568931658367244754058218082222889u128) - // + BigUint::from_str("88516562921839445888640380379840781596").unwrap() - // * &out_base - // + BigUint::from_str("194478888615417946406783868151393774738").unwrap() - // * &out_base.pow(2) - // + BigUint::from_str("382395265476432217957523230769986571504").unwrap() - // * &out_base.pow(3) - // + BigUint::from_str("575971019676008360859069855433378813941").unwrap() - // * &out_base.pow(4) - // + BigUint::from_str("670174995752918677131397897218932582682").unwrap() - // * &out_base.pow(5) - // + BigUint::from_str("780239872348808029089572423614905198300").unwrap() - // * &out_base.pow(6) - // + BigUint::from_str("850410093737715640261630122959874522628").unwrap() - // * &out_base.pow(7) - // + BigUint::from_str("800314959349304909735238452892956199392").unwrap() - // * &out_base.pow(8) - // + BigUint::from_str("906862855407309870283714027678210238070").unwrap() - // * &out_base.pow(9) - // + BigUint::from_str("967727310654811444144097720329196927129").unwrap() - // * &out_base.pow(10) - // + BigUint::from_str("825671020037461535758117365587238596380").unwrap() - // * &out_base.pow(11) - // + BigUint::from_str("991281789723902700168027417052185830252").unwrap() - // * &out_base.pow(12) - // + BigUint::from_str("1259367815833216292413970809061165585320").unwrap() - // * &out_base.pow(13) - // + BigUint::from_str("1351495628781923848799708082622582598675").unwrap() - // * &out_base.pow(14) - // + BigUint::from_str("1451028634949220760698564802414695011932").unwrap() - // * &out_base.pow(15) - // + BigUint::from_str("1290756126635958771067082204577975256756").unwrap() - // * &out_base.pow(16) - // + BigUint::from_str("936482288980049848345464202850902738826").unwrap() - // * &out_base.pow(17) - // + BigUint::from_str("886330568585033438612679243731110283692").unwrap() - // * &out_base.pow(18) - // + BigUint::from_str("823948310509772835433730556487356331346").unwrap() - // * &out_base.pow(19) - // + BigUint::from_str("649341353489205691855914543942648985328").unwrap() - // * &out_base.pow(20) - // + BigUint::from_str("497838205323760437611385487609464464168").unwrap() - // * &out_base.pow(21) - // + BigUint::from_str("430091148520710550273018448938020664564").unwrap() - // * &out_base.pow(22) - // + BigUint::from_str("474098876922017329965321439330710234148").unwrap() - // * &out_base.pow(23) - // + BigUint::from_str("536697574159375092388958994084813127393").unwrap() - // * &out_base.pow(24) - // + BigUint::from_str("483446024935732188792400155524449880972").unwrap() - // * &out_base.pow(25) - // + BigUint::from_str("289799562463011227421662267162524920264").unwrap() - // * &out_base.pow(26) - // + BigUint::from_str("104372664369829937912234314161010649544").unwrap() - // * &out_base.pow(27) - // + BigUint::from_str("18130279752377737976455635841349605284").unwrap() - // * &out_base.pow(28) - // + BigUint::from_str("7809007931264072381739139035072").unwrap() - // * &out_base.pow(29) - // + BigUint::from_str("840867892083599894415616").unwrap() - // * &out_base.pow(30) - // + BigUint::from_str("0").unwrap() * &out_base.pow(31); - // let ans_assigned = bigint_chip.assign_constant_muled(ctx, ans_big, n1, n1)?; - // bigint_chip.assert_equal_muled(ctx, &ab, &ans_assigned, n1, n1)?; - // Ok(()) - // }, - // )?; - // let range_chip = bigint_chip.range_chip(); - // range_chip.load_table(&mut layouter)?; - // //range_chip.load_overflow_tables(&mut layouter)?; - // Ok(()) - // } - // ); - - // impl_bigint_test_circuit!( - // TestMulCase6Circuit, - // test_mul_case6, - // 64, - // 2048, - // false, - // fn synthesize( - // &self, - // config: Self::Config, - // mut layouter: impl halo2wrong::halo2::circuit::Layouter, - // ) -> Result<(), Error> { - // let bigint_chip = self.bigint_chip(config); - // layouter.assign_region( - // || "(1+x)(1+x+x^2) = 1 + 2x + 2x^2 + x^3", - // |region| { - // let offset = 0; - // let ctx = &mut RegionCtx::new(region, offset); - // let out_base = BigUint::from(1usize) << Self::LIMB_WIDTH; - // let a_big = BigUint::from(1usize) + 1usize * &out_base; - // let a_assigned = bigint_chip.assign_constant_fresh(ctx, a_big)?; - // let n1 = a_assigned.num_limbs(); - // let b_big = - // BigUint::from(1usize) + 1usize * &out_base + 1usize * &out_base.pow(2); - // let b_assigned = bigint_chip.assign_constant_fresh(ctx, b_big)?; - // let n2 = b_assigned.num_limbs(); - // let ab = bigint_chip.mul(ctx, &a_assigned, &b_assigned)?; - // let ans_big = BigUint::from(1usize) - // + 2usize * &out_base - // + 2usize * &out_base.pow(2u32) - // + 1usize * &out_base.pow(3u32); - // let ans_assigned = bigint_chip.assign_constant_muled(ctx, ans_big, n1, n2)?; - // bigint_chip.assert_equal_muled(ctx, &ab, &ans_assigned, n1, n2)?; - // Ok(()) - // }, - // )?; - // let range_chip = bigint_chip.range_chip(); - // range_chip.load_table(&mut layouter)?; - // //range_chip.load_overflow_tables(&mut layouter)?; - // Ok(()) - // } - // ); - - // impl_bigint_test_circuit!( - // TestMulCase7Circuit, - // test_mul_case7, - // 64, - // 2048, - // false, - // fn synthesize( - // &self, - // config: Self::Config, - // mut layouter: impl halo2wrong::halo2::circuit::Layouter, - // ) -> Result<(), Error> { - // let bigint_chip = self.bigint_chip(config); - // layouter.assign_region( - // || "(1+7x)(1+x+x^2) = 1 + 8x + 8x^2 + 7x^3", - // |region| { - // let offset = 0; - // let ctx = &mut RegionCtx::new(region, offset); - // let out_base = BigUint::from(1usize) << Self::LIMB_WIDTH; - // let a_big = BigUint::from(1usize) + 7usize * &out_base; - // let a_assigned = bigint_chip.assign_constant_fresh(ctx, a_big)?; - // let n1 = a_assigned.num_limbs(); - // let b_big = - // BigUint::from(1usize) + 1usize * &out_base + 1usize * &out_base.pow(2); - // let b_assigned = bigint_chip.assign_constant_fresh(ctx, b_big)?; - // let n2 = b_assigned.num_limbs(); - // let ab = bigint_chip.mul(ctx, &a_assigned, &b_assigned)?; - // let ans_big = BigUint::from(1usize) - // + 8usize * &out_base - // + 8usize * &out_base.pow(2u32) - // + 7usize * &out_base.pow(3u32); - // let ans_assigned = bigint_chip.assign_constant_muled(ctx, ans_big, n1, n2)?; - // bigint_chip.assert_equal_muled(ctx, &ab, &ans_assigned, n1, n2)?; - // Ok(()) - // }, - // )?; - // let range_chip = bigint_chip.range_chip(); - // range_chip.load_table(&mut layouter)?; - // //range_chip.load_overflow_tables(&mut layouter)?; - // Ok(()) - // } - // ); - - // impl_bigint_test_circuit!( - // TestMulModCase1Circuit, - // test_mulmod_case1, - // 64, - // 2048, - // false, - // fn synthesize( - // &self, - // config: Self::Config, - // mut layouter: impl halo2wrong::halo2::circuit::Layouter, - // ) -> Result<(), Error> { - // let bigint_chip = self.bigint_chip(config); - // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; - // layouter.assign_region( - // || "0 * (random) = 0 mod n", - // |region| { - // let offset = 0; - // let ctx = &mut RegionCtx::new(region, offset); - // let zero_big = BigUint::from(0usize); - // let a_big = zero_big.clone(); - // let a_assigned = bigint_chip.assign_constant_fresh(ctx, a_big)?; - // let b_limbs = decompose_big::(self.b.clone(), num_limbs, Self::LIMB_WIDTH); - // let b_unassigned = UnassignedInteger::from(b_limbs); - // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; - // let n_limbs = decompose_big::(self.n.clone(), num_limbs, Self::LIMB_WIDTH); - // let n_unassigned = UnassignedInteger::from(n_limbs); - // let n_assigned = bigint_chip.assign_integer(ctx, n_unassigned)?; - // let ab = bigint_chip.mul_mod(ctx, &a_assigned, &b_assigned, &n_assigned)?; - // let ans_big = zero_big; - // let ans_assigned = bigint_chip.assign_constant_fresh(ctx, ans_big)?; - // bigint_chip.assert_equal_fresh(ctx, &ab, &ans_assigned)?; - // Ok(()) - // }, - // )?; - // let range_chip = bigint_chip.range_chip(); - // range_chip.load_table(&mut layouter)?; - // //range_chip.load_overflow_tables(&mut layouter)?; - // Ok(()) - // } - // ); - - // impl_bigint_test_circuit!( - // TestMulModCase2Circuit, - // test_mulmod_case2, - // 64, - // 2048, - // false, - // fn synthesize( - // &self, - // config: Self::Config, - // mut layouter: impl halo2wrong::halo2::circuit::Layouter, - // ) -> Result<(), Error> { - // let bigint_chip = self.bigint_chip(config); - // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; - // layouter.assign_region( - // || "n * 1 mod n = 0", - // |region| { - // let offset = 0; - // let ctx = &mut RegionCtx::new(region, offset); - // let a_limbs = decompose_big::(self.n.clone(), num_limbs, Self::LIMB_WIDTH); - // let a_unassigned = UnassignedInteger::from(a_limbs); - // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; - // let b_big = BigUint::from(1usize); - // let b_assigned = bigint_chip.assign_constant_fresh(ctx, b_big)?; - // let n_limbs = decompose_big::(self.n.clone(), num_limbs, Self::LIMB_WIDTH); - // let n_unassigned = UnassignedInteger::from(n_limbs); - // let n_assigned = bigint_chip.assign_integer(ctx, n_unassigned)?; - // let ab = bigint_chip.mul_mod(ctx, &a_assigned, &b_assigned, &n_assigned)?; - // let ans_big = BigUint::from(0usize); - // let ans_assigned = bigint_chip.assign_constant_fresh(ctx, ans_big)?; - // bigint_chip.assert_equal_fresh(ctx, &ab, &ans_assigned)?; - // Ok(()) - // }, - // )?; - // let range_chip = bigint_chip.range_chip(); - // range_chip.load_table(&mut layouter)?; - // //range_chip.load_overflow_tables(&mut layouter)?; - // Ok(()) - // } - // ); - - // impl_bigint_test_circuit!( - // TestMulModCase3Circuit, - // test_mulmod_case3, - // 64, - // 2048, - // false, - // fn synthesize( - // &self, - // config: Self::Config, - // mut layouter: impl halo2wrong::halo2::circuit::Layouter, - // ) -> Result<(), Error> { - // let bigint_chip = self.bigint_chip(config); - // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; - // layouter.assign_region( - // || "(n - 1) * (n - 1) mod n = 1", - // |region| { - // let offset = 0; - // let ctx = &mut RegionCtx::new(region, offset); - // let n_sub_1 = &self.n - &1u8; - // let a_limbs = decompose_big::(n_sub_1.clone(), num_limbs, Self::LIMB_WIDTH); - // let a_unassigned = UnassignedInteger::from(a_limbs); - // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; - // let b_limbs = decompose_big::(n_sub_1.clone(), num_limbs, Self::LIMB_WIDTH); - // let b_unassigned = UnassignedInteger::from(b_limbs); - // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; - // let n_limbs = decompose_big::(self.n.clone(), num_limbs, Self::LIMB_WIDTH); - // let n_unassigned = UnassignedInteger::from(n_limbs); - // let n_assigned = bigint_chip.assign_integer(ctx, n_unassigned)?; - // let ab = bigint_chip.mul_mod(ctx, &a_assigned, &b_assigned, &n_assigned)?; - // let ans_big = BigUint::from(1usize); - // let ans_assigned = bigint_chip.assign_constant_fresh(ctx, ans_big)?; - // bigint_chip.assert_equal_fresh(ctx, &ab, &ans_assigned)?; - // Ok(()) - // }, - // )?; - // let range_chip = bigint_chip.range_chip(); - // range_chip.load_table(&mut layouter)?; - // //range_chip.load_overflow_tables(&mut layouter)?; - // Ok(()) - // } - // ); - - // impl_bigint_test_circuit!( - // TestMulModCase4Circuit, - // test_mulmod_case4, - // 64, - // 2048, - // false, - // fn synthesize( - // &self, - // config: Self::Config, - // mut layouter: impl halo2wrong::halo2::circuit::Layouter, - // ) -> Result<(), Error> { - // let bigint_chip = self.bigint_chip(config); - // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; - // layouter.assign_region( - // || "(n - 1) * (n - 2) mod n = 2", - // |region| { - // let offset = 0; - // let ctx = &mut RegionCtx::new(region, offset); - // let n_sub_1 = &self.n - &1u8; - // let a_limbs = decompose_big::(n_sub_1.clone(), num_limbs, Self::LIMB_WIDTH); - // let a_unassigned = UnassignedInteger::from(a_limbs); - // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; - // let n_sub_2 = &self.n - &2u8; - // let b_limbs = decompose_big::(n_sub_2.clone(), num_limbs, Self::LIMB_WIDTH); - // let b_unassigned = UnassignedInteger::from(b_limbs); - // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; - // let n_limbs = decompose_big::(self.n.clone(), num_limbs, Self::LIMB_WIDTH); - // let n_unassigned = UnassignedInteger::from(n_limbs); - // let n_assigned = bigint_chip.assign_integer(ctx, n_unassigned)?; - // let ab = bigint_chip.mul_mod(ctx, &a_assigned, &b_assigned, &n_assigned)?; - // let ans_big = BigUint::from(2usize); - // let ans_assigned = bigint_chip.assign_constant_fresh(ctx, ans_big)?; - // bigint_chip.assert_equal_fresh(ctx, &ab, &ans_assigned)?; - // Ok(()) - // }, - // )?; - // let range_chip = bigint_chip.range_chip(); - // range_chip.load_table(&mut layouter)?; - // //range_chip.load_overflow_tables(&mut layouter)?; - // Ok(()) - // } - // ); } + +// #[cfg(test)] +// mod test { +// use std::str::FromStr; + +// use super::*; +// use crate::big_pow_mod; +// use halo2_base::halo2_proofs::{ +// circuit::{Layouter, SimpleFloorPlanner}, +// dev::MockProver, +// halo2curves::bn256::Fr, +// plonk::{Circuit, ConstraintSystem}, +// }; +// use halo2_base::{gates::range::RangeStrategy::Vertical, ContextParams, SKIP_FIRST_PASS}; +// use num_traits::FromPrimitive; + +// macro_rules! impl_bigint_test_circuit { +// ($circuit_name:ident, $test_fn_name:ident, $limb_width:expr, $bits_len:expr, $k:expr, $should_be_error:expr, $( $synth:tt )*) => { +// struct $circuit_name { +// a: BigUint, +// b: BigUint, +// n: BigUint, +// _f: PhantomData, +// } + +// impl $circuit_name { +// const LIMB_WIDTH: usize = $limb_width; +// const BITS_LEN: usize = $bits_len; +// const NUM_ADVICE:usize = 50; +// const NUM_FIXED:usize = 1; +// const NUM_LOOKUP_ADVICE:usize = 4; +// const LOOKUP_BITS:usize = 12; +// } + +// impl Circuit for $circuit_name { +// type Config = BigUintConfig; +// type FloorPlanner = SimpleFloorPlanner; + +// fn without_witnesses(&self) -> Self { +// unimplemented!(); +// } + +// fn configure(meta: &mut ConstraintSystem) -> Self::Config { +// let range_config = RangeConfig::configure(meta,Vertical, &[Self::NUM_ADVICE], &[Self::NUM_LOOKUP_ADVICE], Self::NUM_FIXED, Self::LOOKUP_BITS, 0, $k); +// let bigint_config = BigUintConfig::construct(range_config, Self::LIMB_WIDTH); +// bigint_config +// } + +// $( $synth )* + +// } + +// #[test] +// fn $test_fn_name() { +// use num_bigint::RandomBits; +// use rand::{thread_rng, Rng}; +// fn run() { +// let mut rng = thread_rng(); +// let bits_len = $circuit_name::::BITS_LEN as u64; +// let mut n = BigUint::default(); +// while n.bits() != bits_len { +// n = rng.sample(RandomBits::new(bits_len)); +// } +// let a = rng.sample::(RandomBits::new(bits_len)) % &n; +// let b = rng.sample::(RandomBits::new(bits_len)) % &n; +// let circuit = $circuit_name:: { +// a, +// b, +// n, +// _f: PhantomData, +// }; + +// let public_inputs = vec![]; +// let k = $k; +// let prover = match MockProver::run(k, &circuit, public_inputs) { +// Ok(prover) => prover, +// Err(e) => panic!("{:#?}", e) +// }; +// if $should_be_error { +// assert!(prover.verify().is_err()); +// } else { +// prover.verify().unwrap(); +// } +// } +// run::(); +// } +// }; +// } + +// impl_bigint_test_circuit!( +// TestAddCircuit, +// test_add_circuit, +// 64, +// 2048, +// 13, +// false, +// fn synthesize( +// &self, +// config: Self::Config, +// mut layouter: impl Layouter, +// ) -> Result<(), Error> { +// config.range().load_lookup_table(&mut layouter)?; +// let mut first_pass = SKIP_FIRST_PASS; +// layouter.assign_region( +// || "random add test", +// |region| { +// if first_pass { +// first_pass = false; +// return Ok(()); +// } + +// let mut aux = config.new_context(region); +// let ctx = &mut aux; +// let a_assigned = +// config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; +// let b_assigned = +// config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; +// let ab = config.add(ctx, &a_assigned, &b_assigned)?; +// let ba = config.add(ctx, &b_assigned, &a_assigned)?; +// config.assert_equal_fresh(ctx, &ab, &ba)?; +// config.range().finalize(ctx); +// { +// println!("total advice cells: {}", ctx.total_advice); +// let const_rows = ctx.total_fixed + 1; +// println!("maximum rows used by a fixed column: {const_rows}"); +// println!("lookup cells used: {}", ctx.cells_to_lookup.len()); +// } +// Ok(()) +// }, +// )?; +// Ok(()) +// } +// ); + +// impl_bigint_test_circuit!( +// TestBadAddCircuit, +// test_bad_add_circuit, +// 64, +// 2048, +// 13, +// true, +// fn synthesize( +// &self, +// config: Self::Config, +// mut layouter: impl Layouter, +// ) -> Result<(), Error> { +// config.range().load_lookup_table(&mut layouter)?; +// let mut first_pass = SKIP_FIRST_PASS; +// layouter.assign_region( +// || "random add test", +// |region| { +// if first_pass { +// first_pass = false; +// return Ok(()); +// } + +// let mut aux = config.new_context(region); +// let ctx = &mut aux; +// let a_assigned = +// config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; +// let b_assigned = +// config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; +// let ab = config.add(ctx, &a_assigned, &b_assigned)?; +// let n_assigned = +// config.assign_integer(ctx, Value::known(self.n.clone()), Self::BITS_LEN)?; +// let zero_value = config.gate().load_zero(ctx); +// let n_assigned = n_assigned.extend_limbs(1, zero_value); +// config.assert_equal_fresh(ctx, &ab, &n_assigned)?; +// config.range().finalize(ctx); +// { +// println!("total advice cells: {}", ctx.total_advice); +// let const_rows = ctx.total_fixed + 1; +// println!("maximum rows used by a fixed column: {const_rows}"); +// println!("lookup cells used: {}", ctx.cells_to_lookup.len()); +// } +// Ok(()) +// }, +// )?; +// Ok(()) +// } +// ); + +// impl_bigint_test_circuit!( +// TestSubCircuit, +// test_sub_circuit, +// 64, +// 2048, +// 13, +// false, +// fn synthesize( +// &self, +// config: Self::Config, +// mut layouter: impl Layouter, +// ) -> Result<(), Error> { +// config.range().load_lookup_table(&mut layouter)?; +// let mut first_pass = SKIP_FIRST_PASS; +// layouter.assign_region( +// || "random add test", +// |region| { +// if first_pass { +// first_pass = false; +// return Ok(()); +// } + +// let mut aux = config.new_context(region); +// let ctx = &mut aux; +// let b: BigUint = &self.b >> 128; +// let a_assigned = +// config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; +// let b_assigned = +// config.assign_integer(ctx, Value::known(b.clone()), Self::BITS_LEN)?; +// let sub = &self.a - &b; +// let sub_assigned = config.assign_constant(ctx, sub)?; +// let (ab, is_overflow) = config.sub_unsafe(ctx, &a_assigned, &b_assigned)?; +// config.assert_equal_fresh(ctx, &ab, &sub_assigned)?; +// config.gate().assert_is_const(ctx, &is_overflow, F::from(0)); +// config.range().finalize(ctx); +// { +// println!("total advice cells: {}", ctx.total_advice); +// let const_rows = ctx.total_fixed + 1; +// println!("maximum rows used by a fixed column: {const_rows}"); +// println!("lookup cells used: {}", ctx.cells_to_lookup.len()); +// } +// Ok(()) +// }, +// )?; +// Ok(()) +// } +// ); + +// impl_bigint_test_circuit!( +// TestOverflowSubCircuit, +// test_overflow_sub_circuit, +// 64, +// 2048, +// 13, +// false, +// fn synthesize( +// &self, +// config: Self::Config, +// mut layouter: impl Layouter, +// ) -> Result<(), Error> { +// config.range().load_lookup_table(&mut layouter)?; +// let mut first_pass = SKIP_FIRST_PASS; +// layouter.assign_region( +// || "random add test", +// |region| { +// if first_pass { +// first_pass = false; +// return Ok(()); +// } + +// let mut aux = config.new_context(region); +// let ctx = &mut aux; +// let a: BigUint = &self.a >> 128; +// let b: BigUint = self.b.clone(); +// let a_assigned = +// config.assign_integer(ctx, Value::known(a.clone()), Self::BITS_LEN)?; +// let b_assigned = +// config.assign_integer(ctx, Value::known(b.clone()), Self::BITS_LEN)?; +// let (_, is_overflow) = config.sub_unsafe(ctx, &a_assigned, &b_assigned)?; +// config.gate().assert_is_const(ctx, &is_overflow, F::from(1)); +// config.range().finalize(ctx); +// { +// println!("total advice cells: {}", ctx.total_advice); +// let const_rows = ctx.total_fixed + 1; +// println!("maximum rows used by a fixed column: {const_rows}"); +// println!("lookup cells used: {}", ctx.cells_to_lookup.len()); +// } +// Ok(()) +// }, +// )?; +// Ok(()) +// } +// ); + +// // impl_bigint_test_circuit!( +// // TestBadSubCircuit, +// // test_bad_sub_circuit, +// // 64, +// // 2048, +// // 13, +// // true, +// // fn synthesize( +// // &self, +// // config: Self::Config, +// // mut layouter: impl Layouter, +// // ) -> Result<(), Error> { +// // config.range().load_lookup_table(&mut layouter)?; +// // let mut first_pass = SKIP_FIRST_PASS; +// // layouter.assign_region( +// // || "random add test", +// // |region| { +// // if first_pass { +// // first_pass = false; +// // return Ok(()); +// // } + +// // let mut aux = config.new_context(region); +// // let ctx = &mut aux; +// // let a_assigned = +// // config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; +// // let b_assigned = +// // config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; +// // let n_assigned = +// // config.assign_integer(ctx, Value::known(self.n.clone()), Self::BITS_LEN)?; +// // let (ab, _) = config.sub_unsafe(ctx, &a_assigned, &b_assigned)?; +// // config.assert_equal_fresh(ctx, &ab, &n_assigned)?; +// // config.range().finalize(ctx); +// // { +// // println!("total advice cells: {}", ctx.total_advice); +// // let const_rows = ctx.total_fixed + 1; +// // println!("maximum rows used by a fixed column: {const_rows}"); +// // println!("lookup cells used: {}", ctx.cells_to_lookup.len()); +// // } +// // Ok(()) +// // }, +// // )?; +// // Ok(()) +// // } +// // ); + +// impl_bigint_test_circuit!( +// TestMulCircuit, +// test_mul_circuit, +// 64, +// 2048, +// 13, +// false, +// fn synthesize( +// &self, +// config: Self::Config, +// mut layouter: impl Layouter, +// ) -> Result<(), Error> { +// config.range().load_lookup_table(&mut layouter)?; +// let mut first_pass = SKIP_FIRST_PASS; +// layouter.assign_region( +// || "random mul test", +// |region| { +// if first_pass { +// first_pass = false; +// return Ok(()); +// } + +// let mut aux = config.new_context(region); +// let ctx = &mut aux; +// let a_assigned = +// config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; +// let b_assigned = +// config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; +// config.mul(ctx, &a_assigned, &b_assigned)?; +// config.range().finalize(ctx); +// { +// println!("total advice cells: {}", ctx.total_advice); +// let const_rows = ctx.total_fixed + 1; +// println!("maximum rows used by a fixed column: {const_rows}"); +// println!("lookup cells used: {}", ctx.cells_to_lookup.len()); +// } +// Ok(()) +// }, +// )?; +// Ok(()) +// } +// ); + +// impl_bigint_test_circuit!( +// TestFreshEqualCircuit, +// test_fresh_equal_circuit, +// 64, +// 2048, +// 13, +// false, +// fn synthesize( +// &self, +// config: Self::Config, +// mut layouter: impl Layouter, +// ) -> Result<(), Error> { +// config.range().load_lookup_table(&mut layouter)?; +// let mut first_pass = SKIP_FIRST_PASS; +// layouter.assign_region( +// || "random add test", +// |region| { +// if first_pass { +// first_pass = false; +// return Ok(()); +// } + +// let mut aux = config.new_context(region); +// let ctx = &mut aux; +// let a_assigned = +// config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; +// let b_assigned = +// config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; +// config.assert_equal_fresh(ctx, &a_assigned, &a_assigned)?; +// config.assert_equal_fresh(ctx, &b_assigned, &b_assigned)?; +// config.range().finalize(ctx); +// { +// println!("total advice cells: {}", ctx.total_advice); +// let const_rows = ctx.total_fixed + 1; +// println!("maximum rows used by a fixed column: {const_rows}"); +// println!("lookup cells used: {}", ctx.cells_to_lookup.len()); +// } +// Ok(()) +// }, +// )?; +// Ok(()) +// } +// ); + +// impl_bigint_test_circuit!( +// TestBadFreshEqualCircuit, +// test_bad_fresh_equal_circuit, +// 64, +// 2048, +// 13, +// true, +// fn synthesize( +// &self, +// config: Self::Config, +// mut layouter: impl Layouter, +// ) -> Result<(), Error> { +// config.range().load_lookup_table(&mut layouter)?; +// let mut first_pass = SKIP_FIRST_PASS; +// layouter.assign_region( +// || "random add test", +// |region| { +// if first_pass { +// first_pass = false; +// return Ok(()); +// } + +// let mut aux = config.new_context(region); +// let ctx = &mut aux; +// let a_assigned = +// config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; +// let b_assigned = +// config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; +// config.assert_equal_fresh(ctx, &a_assigned, &b_assigned)?; +// config.range().finalize(ctx); +// { +// println!("total advice cells: {}", ctx.total_advice); +// let const_rows = ctx.total_fixed + 1; +// println!("maximum rows used by a fixed column: {const_rows}"); +// println!("lookup cells used: {}", ctx.cells_to_lookup.len()); +// } +// Ok(()) +// }, +// )?; +// Ok(()) +// } +// ); + +// impl_bigint_test_circuit!( +// TestMuledEqualCircuit, +// test_muled_equal_circuit, +// 64, +// 2048, +// 13, +// false, +// fn synthesize( +// &self, +// config: Self::Config, +// mut layouter: impl Layouter, +// ) -> Result<(), Error> { +// config.range().load_lookup_table(&mut layouter)?; +// let mut first_pass = SKIP_FIRST_PASS; +// layouter.assign_region( +// || "random refresh test", +// |region| { +// if first_pass { +// first_pass = false; +// return Ok(()); +// } + +// let mut aux = config.new_context(region); +// let ctx = &mut aux; +// let a_assigned = +// config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; +// let b_assigned = +// config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; +// let ab = config.mul(ctx, &a_assigned, &b_assigned)?; +// let ba = config.mul(ctx, &b_assigned, &a_assigned)?; +// let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; +// config.assert_equal_muled(ctx, &ab, &ba, num_limbs, num_limbs)?; +// config.range().finalize(ctx); +// { +// println!("total advice cells: {}", ctx.total_advice); +// let const_rows = ctx.total_fixed + 1; +// println!("maximum rows used by a fixed column: {const_rows}"); +// println!("lookup cells used: {}", ctx.cells_to_lookup.len()); +// } +// Ok(()) +// }, +// )?; +// Ok(()) +// } +// ); + +// impl_bigint_test_circuit!( +// TestBadMuledEqualCircuit, +// test_bad_muled_equal_circuit, +// 64, +// 2048, +// 13, +// true, +// fn synthesize( +// &self, +// config: Self::Config, +// mut layouter: impl Layouter, +// ) -> Result<(), Error> { +// config.range().load_lookup_table(&mut layouter)?; +// let mut first_pass = SKIP_FIRST_PASS; +// layouter.assign_region( +// || "random refresh test", +// |region| { +// if first_pass { +// first_pass = false; +// return Ok(()); +// } + +// let mut aux = config.new_context(region); +// let ctx = &mut aux; +// let a_assigned = +// config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; +// let b_assigned = +// config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; +// let ab = config.mul(ctx, &a_assigned, &b_assigned)?; +// let zero = config.assign_constant(ctx, BigUint::zero())?; +// let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; +// let zero_value = config.gate().load_zero(ctx); +// let zero = zero +// .extend_limbs(ab.num_limbs() - zero.num_limbs(), zero_value) +// .to_muled(); +// config.assert_equal_muled(ctx, &ab, &zero, num_limbs, num_limbs)?; +// config.range().finalize(ctx); +// { +// println!("total advice cells: {}", ctx.total_advice); +// let const_rows = ctx.total_fixed + 1; +// println!("maximum rows used by a fixed column: {const_rows}"); +// println!("lookup cells used: {}", ctx.cells_to_lookup.len()); +// } +// Ok(()) +// }, +// )?; +// Ok(()) +// } +// ); + +// impl_bigint_test_circuit!( +// TestRefreshCircuit, +// test_refresh_circuit, +// 64, +// 2048, +// 13, +// false, +// fn synthesize( +// &self, +// config: Self::Config, +// mut layouter: impl Layouter, +// ) -> Result<(), Error> { +// config.range().load_lookup_table(&mut layouter)?; +// let mut first_pass = SKIP_FIRST_PASS; +// layouter.assign_region( +// || "random refresh test", +// |region| { +// if first_pass { +// first_pass = false; +// return Ok(()); +// } + +// let mut aux = config.new_context(region); +// let ctx = &mut aux; +// let a_assigned = +// config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; +// let b_assigned = +// config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; +// let ab = config.mul(ctx, &a_assigned, &b_assigned)?; +// let ba = config.mul(ctx, &b_assigned, &a_assigned)?; +// let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; +// let aux = RefreshAux::new(Self::LIMB_WIDTH, num_limbs, num_limbs); +// let ab_refreshed = config.refresh(ctx, &ab, &aux)?; +// let ba_refreshed = config.refresh(ctx, &ba, &aux)?; +// config.assert_equal_fresh(ctx, &ab_refreshed, &ba_refreshed)?; +// config.range().finalize(ctx); +// { +// println!("total advice cells: {}", ctx.total_advice); +// let const_rows = ctx.total_fixed + 1; +// println!("maximum rows used by a fixed column: {const_rows}"); +// println!("lookup cells used: {}", ctx.cells_to_lookup.len()); +// } +// Ok(()) +// }, +// )?; +// Ok(()) +// } +// ); + +// impl_bigint_test_circuit!( +// TestThreeMulCircuit, +// test_three_mul_circuit, +// 64, +// 2048, +// 13, +// false, +// fn synthesize( +// &self, +// config: Self::Config, +// mut layouter: impl Layouter, +// ) -> Result<(), Error> { +// config.range().load_lookup_table(&mut layouter)?; +// let mut first_pass = SKIP_FIRST_PASS; +// layouter.assign_region( +// || "random mul test", +// |region| { +// if first_pass { +// first_pass = false; +// return Ok(()); +// } + +// let mut aux = config.new_context(region); +// let ctx = &mut aux; +// let a_assigned = +// config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; +// let b_assigned = +// config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; +// let n_assigned = +// config.assign_integer(ctx, Value::known(self.n.clone()), Self::BITS_LEN)?; +// let ab = config.mul(ctx, &a_assigned, &b_assigned)?; +// let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; +// let aux = RefreshAux::new(Self::LIMB_WIDTH, num_limbs, num_limbs); +// let ab_refreshed = config.refresh(ctx, &ab, &aux)?; +// let refreshed_num_limbs = ab_refreshed.num_limbs(); +// let abn = config.mul(ctx, &ab_refreshed, &n_assigned)?; +// abn.value.as_ref().map(|v| println!("abn {:?}", v)); +// let nb = config.mul(ctx, &n_assigned, &b_assigned)?; +// let nb_refreshed = config.refresh(ctx, &nb, &aux)?; +// let nba = config.mul(ctx, &a_assigned, &nb_refreshed)?; +// nba.value.as_ref().map(|v| println!("nba {:?}", v)); +// config.assert_equal_muled(ctx, &abn, &nba, refreshed_num_limbs, num_limbs)?; +// config.range().finalize(ctx); +// { +// println!("total advice cells: {}", ctx.total_advice); +// let const_rows = ctx.total_fixed + 1; +// println!("maximum rows used by a fixed column: {const_rows}"); +// println!("lookup cells used: {}", ctx.cells_to_lookup.len()); +// } +// Ok(()) +// }, +// )?; +// Ok(()) +// } +// ); + +// impl_bigint_test_circuit!( +// TestAddModCircuit, +// test_add_mod_circuit, +// 64, +// 2048, +// 13, +// false, +// fn synthesize( +// &self, +// config: Self::Config, +// mut layouter: impl Layouter, +// ) -> Result<(), Error> { +// config.range().load_lookup_table(&mut layouter)?; +// let mut first_pass = SKIP_FIRST_PASS; +// layouter.assign_region( +// || "random refresh test", +// |region| { +// if first_pass { +// first_pass = false; +// return Ok(()); +// } + +// let mut aux = config.new_context(region); +// let ctx = &mut aux; +// let a_assigned = +// config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; +// let b_assigned = +// config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; +// let n_assigned = +// config.assign_integer(ctx, Value::known(self.n.clone()), Self::BITS_LEN)?; +// let ab = config.add_mod(ctx, &a_assigned, &b_assigned, &n_assigned)?; +// let ba = config.add_mod(ctx, &b_assigned, &a_assigned, &n_assigned)?; +// let is_eq = config.is_equal_fresh(ctx, &ab, &ba)?; +// config.gate().assert_is_const(ctx, &is_eq, F::from(1)); +// config.range().finalize(ctx); +// { +// println!("total advice cells: {}", ctx.total_advice); +// let const_rows = ctx.total_fixed + 1; +// println!("maximum rows used by a fixed column: {const_rows}"); +// println!("lookup cells used: {}", ctx.cells_to_lookup.len()); +// } +// Ok(()) +// }, +// )?; +// Ok(()) +// } +// ); + +// impl_bigint_test_circuit!( +// TestBadAddModCircuit, +// test_bad_add_mod_circuit, +// 64, +// 2048, +// 13, +// true, +// fn synthesize( +// &self, +// config: Self::Config, +// mut layouter: impl Layouter, +// ) -> Result<(), Error> { +// config.range().load_lookup_table(&mut layouter)?; +// let mut first_pass = SKIP_FIRST_PASS; +// layouter.assign_region( +// || "random refresh test", +// |region| { +// if first_pass { +// first_pass = false; +// return Ok(()); +// } + +// let mut aux = config.new_context(region); +// let ctx = &mut aux; +// let a_assigned = +// config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; +// let b_assigned = +// config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; +// let n_assigned = +// config.assign_integer(ctx, Value::known(self.n.clone()), Self::BITS_LEN)?; +// let ab = config.add_mod(ctx, &a_assigned, &b_assigned, &n_assigned)?; +// let is_eq = config.is_equal_fresh(ctx, &ab, &n_assigned)?; +// config.gate().assert_is_const(ctx, &is_eq, F::from(1)); +// config.range().finalize(ctx); +// { +// println!("total advice cells: {}", ctx.total_advice); +// let const_rows = ctx.total_fixed + 1; +// println!("maximum rows used by a fixed column: {const_rows}"); +// println!("lookup cells used: {}", ctx.cells_to_lookup.len()); +// } +// Ok(()) +// }, +// )?; +// Ok(()) +// } +// ); + +// // impl_bigint_test_circuit!( +// // TestSubModCircuit, +// // test_sub_mod_circuit, +// // 64, +// // 2048, +// // false, +// // fn synthesize( +// // &self, +// // config: Self::Config, +// // mut layouter: impl halo2wrong::halo2::circuit::Layouter, +// // ) -> Result<(), Error> { +// // let bigint_chip = self.bigint_chip(config); +// // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; +// // layouter.assign_region( +// // || "random sub_mod test", +// // |region| { +// // let offset = 0; +// // let ctx = &mut RegionCtx::new(region, offset); +// // let sub = if &self.a >= &self.b { +// // &self.a - &self.b +// // } else { +// // &self.a + &self.n - &self.b +// // }; +// // let a_limbs = decompose_big::(self.a.clone(), num_limbs, Self::LIMB_WIDTH); +// // let a_unassigned = UnassignedInteger::from(a_limbs); +// // let b_limbs = decompose_big::(self.b.clone(), num_limbs, Self::LIMB_WIDTH); +// // let b_unassigned = UnassignedInteger::from(b_limbs); +// // let n_limbs = decompose_big::(self.n.clone(), num_limbs, Self::LIMB_WIDTH); +// // let n_unassigned = UnassignedInteger::from(n_limbs); +// // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; +// // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; +// // let n_assigned = bigint_chip.assign_integer(ctx, n_unassigned)?; +// // let ab = bigint_chip.sub_mod(ctx, &a_assigned, &b_assigned, &n_assigned)?; +// // let sub_assigned = bigint_chip.assign_constant_fresh(ctx, sub)?; +// // bigint_chip.assert_equal_fresh(ctx, &ab, &sub_assigned)?; +// // Ok(()) +// // }, +// // )?; +// // let range_chip = bigint_chip.range_chip(); +// // range_chip.load_table(&mut layouter)?; +// // //range_chip.load_overflow_tables(&mut layouter)?; +// // Ok(()) +// // } +// // ); + +// // impl_bigint_test_circuit!( +// // TestSubModOverflowCircuit, +// // test_sub_mod_overflow_circuit, +// // 64, +// // 2048, +// // true, +// // fn synthesize( +// // &self, +// // config: Self::Config, +// // mut layouter: impl halo2wrong::halo2::circuit::Layouter, +// // ) -> Result<(), Error> { +// // let bigint_chip = self.bigint_chip(config); +// // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; +// // layouter.assign_region( +// // || "random sub_mod overflow test", +// // |region| { +// // let offset = 0; +// // let ctx = &mut RegionCtx::new(region, offset); +// // let a_limbs = decompose_big::(self.a.clone(), num_limbs, Self::LIMB_WIDTH); +// // let a_unassigned = UnassignedInteger::from(a_limbs); +// // let b_limbs = decompose_big::(self.b.clone(), num_limbs, Self::LIMB_WIDTH); +// // let b_unassigned = UnassignedInteger::from(b_limbs); +// // let n_limbs = +// // decompose_big::(self.n.clone() >> 1024, num_limbs, Self::LIMB_WIDTH); +// // let n_unassigned = UnassignedInteger::from(n_limbs); +// // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; +// // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; +// // let n_assigned = bigint_chip.assign_integer(ctx, n_unassigned)?; +// // bigint_chip.sub_mod(ctx, &a_assigned, &b_assigned, &n_assigned)?; +// // Ok(()) +// // }, +// // )?; +// // let range_chip = bigint_chip.range_chip(); +// // range_chip.load_table(&mut layouter)?; +// // //range_chip.load_overflow_tables(&mut layouter)?; +// // Ok(()) +// // } +// // ); + +// // impl_bigint_test_circuit!( +// // TestBadSubModCircuit, +// // test_bad_sub_mod_circuit, +// // 64, +// // 2048, +// // true, +// // fn synthesize( +// // &self, +// // config: Self::Config, +// // mut layouter: impl halo2wrong::halo2::circuit::Layouter, +// // ) -> Result<(), Error> { +// // let bigint_chip = self.bigint_chip(config); +// // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; +// // layouter.assign_region( +// // || "random sub_mod test with an error case", +// // |region| { +// // let offset = 0; +// // let ctx = &mut RegionCtx::new(region, offset); +// // let a_limbs = decompose_big::(self.a.clone(), num_limbs, Self::LIMB_WIDTH); +// // let a_unassigned = UnassignedInteger::from(a_limbs); +// // let b_limbs = decompose_big::(self.b.clone(), num_limbs, Self::LIMB_WIDTH); +// // let b_unassigned = UnassignedInteger::from(b_limbs); +// // let n_limbs = decompose_big::(self.n.clone(), num_limbs, Self::LIMB_WIDTH); +// // let n_unassigned = UnassignedInteger::from(n_limbs); +// // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; +// // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; +// // let n_assigned = bigint_chip.assign_integer(ctx, n_unassigned)?; +// // let ab = bigint_chip.sub_mod(ctx, &a_assigned, &b_assigned, &n_assigned)?; +// // bigint_chip.assert_equal_fresh(ctx, &ab, &n_assigned)?; +// // Ok(()) +// // }, +// // )?; +// // let range_chip = bigint_chip.range_chip(); +// // range_chip.load_table(&mut layouter)?; +// // //range_chip.load_overflow_tables(&mut layouter)?; +// // Ok(()) +// // } +// // ); + +// impl_bigint_test_circuit!( +// TestMulModCircuit, +// test_mul_mod_circuit, +// 64, +// 2048, +// 13, +// false, +// fn synthesize( +// &self, +// config: Self::Config, +// mut layouter: impl Layouter, +// ) -> Result<(), Error> { +// config.range().load_lookup_table(&mut layouter)?; +// let mut first_pass = SKIP_FIRST_PASS; +// layouter.assign_region( +// || "random refresh test", +// |region| { +// if first_pass { +// first_pass = false; +// return Ok(()); +// } + +// let mut aux = config.new_context(region); +// let ctx = &mut aux; +// let a_assigned = +// config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; +// let b_assigned = +// config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; +// let n_assigned = +// config.assign_integer(ctx, Value::known(self.n.clone()), Self::BITS_LEN)?; +// let ab = config.mul_mod(ctx, &a_assigned, &b_assigned, &n_assigned)?; +// let ba = config.mul_mod(ctx, &b_assigned, &a_assigned, &n_assigned)?; +// let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; +// config.assert_equal_fresh(ctx, &ab, &ba)?; +// config.range().finalize(ctx); +// { +// println!("total advice cells: {}", ctx.total_advice); +// let const_rows = ctx.total_fixed + 1; +// println!("maximum rows used by a fixed column: {const_rows}"); +// println!("lookup cells used: {}", ctx.cells_to_lookup.len()); +// } +// Ok(()) +// }, +// )?; +// Ok(()) +// } +// ); + +// impl_bigint_test_circuit!( +// TestBadMulModCircuit, +// test_bad_mul_mod_circuit, +// 64, +// 2048, +// 13, +// true, +// fn synthesize( +// &self, +// config: Self::Config, +// mut layouter: impl Layouter, +// ) -> Result<(), Error> { +// config.range().load_lookup_table(&mut layouter)?; +// let mut first_pass = SKIP_FIRST_PASS; +// layouter.assign_region( +// || "random refresh test", +// |region| { +// if first_pass { +// first_pass = false; +// return Ok(()); +// } + +// let mut aux = config.new_context(region); +// let ctx = &mut aux; +// let a_assigned = +// config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; +// let b_assigned = +// config.assign_integer(ctx, Value::known(self.b.clone()), Self::BITS_LEN)?; +// let n_assigned = +// config.assign_integer(ctx, Value::known(self.n.clone()), Self::BITS_LEN)?; +// let ab = config.mul_mod(ctx, &a_assigned, &b_assigned, &n_assigned)?; +// let zero = config.assign_constant(ctx, BigUint::zero())?; +// let zero_value = config.gate().load_zero(ctx); +// let zero = zero.extend_limbs(ab.num_limbs() - zero.num_limbs(), zero_value); +// config.assert_equal_fresh(ctx, &ab, &zero)?; +// config.range().finalize(ctx); +// { +// println!("total advice cells: {}", ctx.total_advice); +// let const_rows = ctx.total_fixed + 1; +// println!("maximum rows used by a fixed column: {const_rows}"); +// println!("lookup cells used: {}", ctx.cells_to_lookup.len()); +// } +// Ok(()) +// }, +// )?; +// Ok(()) +// } +// ); + +// impl_bigint_test_circuit!( +// TestPowModFixedExpCircuit, +// test_pow_mod_fixed_exp_circuit, +// 64, +// 2048, +// 13, +// false, +// fn synthesize( +// &self, +// config: Self::Config, +// mut layouter: impl Layouter, +// ) -> Result<(), Error> { +// config.range().load_lookup_table(&mut layouter)?; +// let mut first_pass = SKIP_FIRST_PASS; +// layouter.assign_region( +// || "random pow_mod test", +// |region| { +// if first_pass { +// first_pass = false; +// return Ok(()); +// } + +// let mut aux = config.new_context(region); +// let ctx = &mut aux; +// let a_assigned = +// config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; +// let n_assigned = +// config.assign_integer(ctx, Value::known(self.n.clone()), Self::BITS_LEN)?; +// let e = BigUint::from_u64(65537).unwrap(); +// let powed = config.pow_mod_fixed_exp(ctx, &a_assigned, &e, &n_assigned)?; +// let ans_big = big_pow_mod(&self.a, &e, &self.n); +// let ans_assigned = config.assign_constant(ctx, ans_big)?; +// config.assert_equal_fresh(ctx, &powed, &ans_assigned)?; +// config.range().finalize(ctx); +// { +// println!("total advice cells: {}", ctx.total_advice); +// let const_rows = ctx.total_fixed + 1; +// println!("maximum rows used by a fixed column: {const_rows}"); +// println!("lookup cells used: {}", ctx.cells_to_lookup.len()); +// } +// Ok(()) +// }, +// )?; +// Ok(()) +// } +// ); + +// impl_bigint_test_circuit!( +// TestBadPowModFixedExpCircuit, +// test_bad_pow_mod_fixed_exp_circuit, +// 64, +// 2048, +// 13, +// true, +// fn synthesize( +// &self, +// config: Self::Config, +// mut layouter: impl Layouter, +// ) -> Result<(), Error> { +// config.range().load_lookup_table(&mut layouter)?; +// let mut first_pass = SKIP_FIRST_PASS; +// layouter.assign_region( +// || "random pow_mod test", +// |region| { +// if first_pass { +// first_pass = false; +// return Ok(()); +// } + +// let mut aux = config.new_context(region); +// let ctx = &mut aux; +// let a_assigned = +// config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; +// let n_assigned = +// config.assign_integer(ctx, Value::known(self.n.clone()), Self::BITS_LEN)?; +// let e = BigUint::from_u64(65537).unwrap(); +// let powed = config.pow_mod_fixed_exp(ctx, &a_assigned, &e, &n_assigned)?; +// let zero = config.assign_constant(ctx, BigUint::zero())?; +// let zero_value = config.gate().load_zero(ctx); +// let zero = zero.extend_limbs(powed.num_limbs() - zero.num_limbs(), zero_value); +// config.assert_equal_fresh(ctx, &powed, &zero)?; +// config.range().finalize(ctx); +// { +// println!("total advice cells: {}", ctx.total_advice); +// let const_rows = ctx.total_fixed + 1; +// println!("maximum rows used by a fixed column: {const_rows}"); +// println!("lookup cells used: {}", ctx.cells_to_lookup.len()); +// } +// Ok(()) +// }, +// )?; +// Ok(()) +// } +// ); + +// // impl_bigint_test_circuit!( +// // TestIsZeroCircuit, +// // test_is_zero_circuit, +// // 64, +// // 2048, +// // false, +// // fn synthesize( +// // &self, +// // config: Self::Config, +// // mut layouter: impl halo2wrong::halo2::circuit::Layouter, +// // ) -> Result<(), Error> { +// // let bigint_chip = self.bigint_chip(config); +// // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; +// // layouter.assign_region( +// // || "random is_zero test", +// // |region| { +// // let offset = 0; +// // let ctx = &mut RegionCtx::new(region, offset); +// // assert!(self.a != BigUint::from(0usize)); +// // let a_limbs = decompose_big::(self.a.clone(), num_limbs, Self::LIMB_WIDTH); +// // let a_unassigned = UnassignedInteger::from(a_limbs); +// // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; +// // let zero = bigint_chip.assign_constant_fresh(ctx, BigUint::from(0usize))?; +// // bigint_chip.assert_zero(ctx, &zero)?; +// // let a_is_zero = bigint_chip.is_zero(ctx, &a_assigned)?; +// // let main_gate = bigint_chip.main_gate(); +// // main_gate.assert_zero(ctx, &a_is_zero)?; +// // Ok(()) +// // }, +// // )?; +// // let range_chip = bigint_chip.range_chip(); +// // range_chip.load_table(&mut layouter)?; +// // //range_chip.load_overflow_tables(&mut layouter)?; +// // Ok(()) +// // } +// // ); + +// // impl_bigint_test_circuit!( +// // TestLessThanCircuit, +// // test_less_than_circuit, +// // 64, +// // 2048, +// // false, +// // fn synthesize( +// // &self, +// // config: Self::Config, +// // mut layouter: impl halo2wrong::halo2::circuit::Layouter, +// // ) -> Result<(), Error> { +// // let bigint_chip = self.bigint_chip(config); +// // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; +// // layouter.assign_region( +// // || "random assert_less_than test", +// // |region| { +// // let offset = 0; +// // let ctx = &mut RegionCtx::new(region, offset); +// // let a = &self.a >> 128; +// // let b = self.b.clone(); +// // let a_limbs = decompose_big::(a, num_limbs, Self::LIMB_WIDTH); +// // let a_unassigned = UnassignedInteger::from(a_limbs); +// // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; +// // let b_limbs = decompose_big::(b, num_limbs, Self::LIMB_WIDTH); +// // let b_unassigned = UnassignedInteger::from(b_limbs); +// // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; +// // bigint_chip.assert_less_than(ctx, &a_assigned, &b_assigned)?; +// // Ok(()) +// // }, +// // )?; +// // let range_chip = bigint_chip.range_chip(); +// // range_chip.load_table(&mut layouter)?; +// // //range_chip.load_overflow_tables(&mut layouter)?; +// // Ok(()) +// // } +// // ); + +// // impl_bigint_test_circuit!( +// // TestBadLessThanCircuit, +// // test_bad_less_than_circuit, +// // 64, +// // 2048, +// // true, +// // fn synthesize( +// // &self, +// // config: Self::Config, +// // mut layouter: impl halo2wrong::halo2::circuit::Layouter, +// // ) -> Result<(), Error> { +// // let bigint_chip = self.bigint_chip(config); +// // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; +// // layouter.assign_region( +// // || "random assert_less_than test with an error case", +// // |region| { +// // let offset = 0; +// // let ctx = &mut RegionCtx::new(region, offset); +// // let a = self.a.clone(); +// // let b = self.b.clone() >> 128; +// // let a_limbs = decompose_big::(a, num_limbs, Self::LIMB_WIDTH); +// // let a_unassigned = UnassignedInteger::from(a_limbs); +// // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; +// // let b_limbs = decompose_big::(b, num_limbs, Self::LIMB_WIDTH); +// // let b_unassigned = UnassignedInteger::from(b_limbs); +// // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; +// // bigint_chip.assert_less_than(ctx, &a_assigned, &b_assigned)?; +// // Ok(()) +// // }, +// // )?; +// // let range_chip = bigint_chip.range_chip(); +// // range_chip.load_table(&mut layouter)?; +// // //range_chip.load_overflow_tables(&mut layouter)?; +// // Ok(()) +// // } +// // ); + +// // impl_bigint_test_circuit!( +// // TestLessThanOrEqualCircuit, +// // test_less_than_or_equal_circuit, +// // 64, +// // 2048, +// // false, +// // fn synthesize( +// // &self, +// // config: Self::Config, +// // mut layouter: impl halo2wrong::halo2::circuit::Layouter, +// // ) -> Result<(), Error> { +// // let bigint_chip = self.bigint_chip(config); +// // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; +// // layouter.assign_region( +// // || "random assert_less_than_or_equal test", +// // |region| { +// // let offset = 0; +// // let ctx = &mut RegionCtx::new(region, offset); +// // let a = self.a.clone(); +// // let b = self.a.clone(); +// // let a_limbs = decompose_big::(a, num_limbs, Self::LIMB_WIDTH); +// // let a_unassigned = UnassignedInteger::from(a_limbs); +// // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; +// // let b_limbs = decompose_big::(b, num_limbs, Self::LIMB_WIDTH); +// // let b_unassigned = UnassignedInteger::from(b_limbs); +// // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; +// // bigint_chip.assert_less_than_or_equal(ctx, &a_assigned, &b_assigned)?; +// // Ok(()) +// // }, +// // )?; +// // let range_chip = bigint_chip.range_chip(); +// // range_chip.load_table(&mut layouter)?; +// // //range_chip.load_overflow_tables(&mut layouter)?; +// // Ok(()) +// // } +// // ); + +// // impl_bigint_test_circuit!( +// // TestBadLessThanOrEqualCircuit, +// // test_bad_less_than_or_equal_circuit, +// // 64, +// // 2048, +// // true, +// // fn synthesize( +// // &self, +// // config: Self::Config, +// // mut layouter: impl halo2wrong::halo2::circuit::Layouter, +// // ) -> Result<(), Error> { +// // let bigint_chip = self.bigint_chip(config); +// // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; +// // layouter.assign_region( +// // || "random assert_less_than_or_equal test with an error case", +// // |region| { +// // let offset = 0; +// // let ctx = &mut RegionCtx::new(region, offset); +// // let a = self.a.clone(); +// // let b = self.b.clone() >> 128; +// // let a_limbs = decompose_big::(a, num_limbs, Self::LIMB_WIDTH); +// // let a_unassigned = UnassignedInteger::from(a_limbs); +// // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; +// // let b_limbs = decompose_big::(b, num_limbs, Self::LIMB_WIDTH); +// // let b_unassigned = UnassignedInteger::from(b_limbs); +// // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; +// // bigint_chip.assert_less_than_or_equal(ctx, &a_assigned, &b_assigned)?; +// // Ok(()) +// // }, +// // )?; +// // let range_chip = bigint_chip.range_chip(); +// // range_chip.load_table(&mut layouter)?; +// // //range_chip.load_overflow_tables(&mut layouter)?; +// // Ok(()) +// // } +// // ); + +// // impl_bigint_test_circuit!( +// // TestGreaterThanCircuit, +// // test_greater_than_circuit, +// // 64, +// // 2048, +// // false, +// // fn synthesize( +// // &self, +// // config: Self::Config, +// // mut layouter: impl halo2wrong::halo2::circuit::Layouter, +// // ) -> Result<(), Error> { +// // let bigint_chip = self.bigint_chip(config); +// // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; +// // layouter.assign_region( +// // || "random assert_greater_than test", +// // |region| { +// // let offset = 0; +// // let ctx = &mut RegionCtx::new(region, offset); +// // let a = self.a.clone(); +// // let b = self.a.clone() >> 128; +// // let a_limbs = decompose_big::(a, num_limbs, Self::LIMB_WIDTH); +// // let a_unassigned = UnassignedInteger::from(a_limbs); +// // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; +// // let b_limbs = decompose_big::(b, num_limbs, Self::LIMB_WIDTH); +// // let b_unassigned = UnassignedInteger::from(b_limbs); +// // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; +// // bigint_chip.assert_greater_than(ctx, &a_assigned, &b_assigned)?; +// // Ok(()) +// // }, +// // )?; +// // let range_chip = bigint_chip.range_chip(); +// // range_chip.load_table(&mut layouter)?; +// // //range_chip.load_overflow_tables(&mut layouter)?; +// // Ok(()) +// // } +// // ); + +// // impl_bigint_test_circuit!( +// // TestBadGreaterThanCircuit, +// // test_bad_greater_than_circuit, +// // 64, +// // 2048, +// // true, +// // fn synthesize( +// // &self, +// // config: Self::Config, +// // mut layouter: impl halo2wrong::halo2::circuit::Layouter, +// // ) -> Result<(), Error> { +// // let bigint_chip = self.bigint_chip(config); +// // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; +// // layouter.assign_region( +// // || "random assert_greater_than test with an error case", +// // |region| { +// // let offset = 0; +// // let ctx = &mut RegionCtx::new(region, offset); +// // let a = self.a.clone() >> 128; +// // let b = self.b.clone(); +// // let a_limbs = decompose_big::(a, num_limbs, Self::LIMB_WIDTH); +// // let a_unassigned = UnassignedInteger::from(a_limbs); +// // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; +// // let b_limbs = decompose_big::(b, num_limbs, Self::LIMB_WIDTH); +// // let b_unassigned = UnassignedInteger::from(b_limbs); +// // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; +// // bigint_chip.assert_greater_than(ctx, &a_assigned, &b_assigned)?; +// // Ok(()) +// // }, +// // )?; +// // let range_chip = bigint_chip.range_chip(); +// // range_chip.load_table(&mut layouter)?; +// // //range_chip.load_overflow_tables(&mut layouter)?; +// // Ok(()) +// // } +// // ); + +// // impl_bigint_test_circuit!( +// // TestGreaterThanOrEqualCircuit, +// // test_greater_than_or_equal_circuit, +// // 64, +// // 2048, +// // false, +// // fn synthesize( +// // &self, +// // config: Self::Config, +// // mut layouter: impl halo2wrong::halo2::circuit::Layouter, +// // ) -> Result<(), Error> { +// // let bigint_chip = self.bigint_chip(config); +// // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; +// // layouter.assign_region( +// // || "random assert_greater_than_or_equal test", +// // |region| { +// // let offset = 0; +// // let ctx = &mut RegionCtx::new(region, offset); +// // let a = self.a.clone(); +// // let b = self.a.clone(); +// // let a_limbs = decompose_big::(a, num_limbs, Self::LIMB_WIDTH); +// // let a_unassigned = UnassignedInteger::from(a_limbs); +// // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; +// // let b_limbs = decompose_big::(b, num_limbs, Self::LIMB_WIDTH); +// // let b_unassigned = UnassignedInteger::from(b_limbs); +// // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; +// // bigint_chip.assert_greater_than_or_equal(ctx, &a_assigned, &b_assigned)?; +// // Ok(()) +// // }, +// // )?; +// // let range_chip = bigint_chip.range_chip(); +// // range_chip.load_table(&mut layouter)?; +// // //range_chip.load_overflow_tables(&mut layouter)?; +// // Ok(()) +// // } +// // ); + +// // impl_bigint_test_circuit!( +// // TestBadGreaterThanOrEqualCircuit, +// // test_bad_greater_than_or_equal_circuit, +// // 64, +// // 2048, +// // true, +// // fn synthesize( +// // &self, +// // config: Self::Config, +// // mut layouter: impl halo2wrong::halo2::circuit::Layouter, +// // ) -> Result<(), Error> { +// // let bigint_chip = self.bigint_chip(config); +// // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; +// // layouter.assign_region( +// // || "random assert_greater_than_or_equal test with an error case", +// // |region| { +// // let offset = 0; +// // let ctx = &mut RegionCtx::new(region, offset); +// // let a = self.a.clone() >> 128; +// // let b = self.b.clone(); +// // let a_limbs = decompose_big::(a, num_limbs, Self::LIMB_WIDTH); +// // let a_unassigned = UnassignedInteger::from(a_limbs); +// // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; +// // let b_limbs = decompose_big::(b, num_limbs, Self::LIMB_WIDTH); +// // let b_unassigned = UnassignedInteger::from(b_limbs); +// // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; +// // bigint_chip.assert_greater_than_or_equal(ctx, &a_assigned, &b_assigned)?; +// // Ok(()) +// // }, +// // )?; +// // let range_chip = bigint_chip.range_chip(); +// // range_chip.load_table(&mut layouter)?; +// // //range_chip.load_overflow_tables(&mut layouter)?; +// // Ok(()) +// // } +// // ); + +// impl_bigint_test_circuit!( +// TestInFieldCircuit, +// test_in_field_circuit, +// 64, +// 2048, +// 13, +// false, +// fn synthesize( +// &self, +// config: Self::Config, +// mut layouter: impl Layouter, +// ) -> Result<(), Error> { +// config.range().load_lookup_table(&mut layouter)?; +// let mut first_pass = SKIP_FIRST_PASS; +// layouter.assign_region( +// || "random refresh test", +// |region| { +// if first_pass { +// first_pass = false; +// return Ok(()); +// } + +// let mut aux = config.new_context(region); +// let ctx = &mut aux; +// let a_assigned = +// config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; +// let n_assigned = +// config.assign_integer(ctx, Value::known(self.n.clone()), Self::BITS_LEN)?; +// config.assert_in_field(ctx, &a_assigned, &n_assigned)?; +// let zero = config.assign_constant(ctx, BigUint::from(0u64))?; +// config.assert_in_field(ctx, &zero, &n_assigned)?; +// config.range().finalize(ctx); +// { +// println!("total advice cells: {}", ctx.total_advice); +// let const_rows = ctx.total_fixed + 1; +// println!("maximum rows used by a fixed column: {const_rows}"); +// println!("lookup cells used: {}", ctx.cells_to_lookup.len()); +// } +// Ok(()) +// }, +// )?; +// Ok(()) +// } +// ); + +// impl_bigint_test_circuit!( +// TestBadInFieldCircuit, +// test_bad_in_field_circuit, +// 64, +// 2048, +// 13, +// true, +// fn synthesize( +// &self, +// config: Self::Config, +// mut layouter: impl Layouter, +// ) -> Result<(), Error> { +// config.range().load_lookup_table(&mut layouter)?; +// let mut first_pass = SKIP_FIRST_PASS; +// layouter.assign_region( +// || "random refresh test", +// |region| { +// if first_pass { +// first_pass = false; +// return Ok(()); +// } + +// let mut aux = config.new_context(region); +// let ctx = &mut aux; +// let a_assigned = +// config.assign_integer(ctx, Value::known(self.a.clone()), Self::BITS_LEN)?; +// let n_assigned = +// config.assign_integer(ctx, Value::known(self.n.clone()), Self::BITS_LEN)?; +// let invalid = config.is_in_field(ctx, &n_assigned, &n_assigned)?; +// config.gate().assert_is_const(ctx, &invalid, F::from(1)); +// let invalid = config.is_in_field(ctx, &a_assigned, &n_assigned)?; +// config.gate().assert_is_const(ctx, &invalid, F::from(1)); +// config.range().finalize(ctx); +// { +// println!("total advice cells: {}", ctx.total_advice); +// let const_rows = ctx.total_fixed + 1; +// println!("maximum rows used by a fixed column: {const_rows}"); +// println!("lookup cells used: {}", ctx.cells_to_lookup.len()); +// } +// Ok(()) +// }, +// )?; +// Ok(()) +// } +// ); + +// // impl_bigint_test_circuit!( +// // TestMulCase1Circuit, +// // test_mul_case1, +// // 64, +// // 2048, +// // false, +// // fn synthesize( +// // &self, +// // config: Self::Config, +// // mut layouter: impl halo2wrong::halo2::circuit::Layouter, +// // ) -> Result<(), Error> { +// // let bigint_chip = self.bigint_chip(config); +// // layouter.assign_region( +// // || "1 * 1 = 1", +// // |region| { +// // let offset = 0; +// // let ctx = &mut RegionCtx::new(region, offset); +// // let one = bigint_chip.assign_constant_fresh(ctx, BigUint::from(1usize))?; +// // let n = one.num_limbs(); +// // let one_muled = bigint_chip.mul(ctx, &one, &one)?; +// // let zero = AssignedLimb::from( +// // bigint_chip.main_gate().assign_constant(ctx, F::from(0))?, +// // ); +// // bigint_chip.assert_equal_muled(ctx, &one.to_muled(zero), &one_muled, n, n)?; +// // Ok(()) +// // }, +// // )?; +// // let range_chip = bigint_chip.range_chip(); +// // range_chip.load_table(&mut layouter)?; +// // //range_chip.load_overflow_tables(&mut layouter)?; +// // Ok(()) +// // } +// // ); + +// // impl_bigint_test_circuit!( +// // TestMulCase3Circuit, +// // test_mul_case3, +// // 64, +// // 2048, +// // false, +// // fn synthesize( +// // &self, +// // config: Self::Config, +// // mut layouter: impl halo2wrong::halo2::circuit::Layouter, +// // ) -> Result<(), Error> { +// // let bigint_chip = self.bigint_chip(config); +// // layouter.assign_region( +// // || "(1+0x+3x^2)(3+1x) = 3+1x+9x^2+3x^3", +// // |region| { +// // let offset = 0; +// // let ctx = &mut RegionCtx::new(region, offset); +// // let out_base = BigUint::from(1usize) << Self::LIMB_WIDTH; +// // let a_big = +// // BigUint::from(1usize) + 0usize * &out_base + 3usize * &out_base * &out_base; +// // let a_assigned = bigint_chip.assign_constant_fresh(ctx, a_big)?; +// // let n1 = a_assigned.num_limbs(); +// // let b_big = +// // BigUint::from(3usize) + 1usize * &out_base + 0usize * &out_base * &out_base; +// // let b_assigned = bigint_chip.assign_constant_fresh(ctx, b_big)?; +// // let n2 = b_assigned.num_limbs(); +// // let ab = bigint_chip.mul(ctx, &a_assigned, &b_assigned)?; +// // let ans_big = BigUint::from(3usize) +// // + 1usize * &out_base +// // + 9usize * &out_base * &out_base +// // + 3usize * &out_base * &out_base * &out_base; +// // let ans_assigned = bigint_chip.assign_constant_muled(ctx, ans_big, n1, n2)?; +// // bigint_chip.assert_equal_muled(ctx, &ab, &ans_assigned, n1, n2)?; +// // Ok(()) +// // }, +// // )?; +// // let range_chip = bigint_chip.range_chip(); +// // range_chip.load_table(&mut layouter)?; +// // //range_chip.load_overflow_tables(&mut layouter)?; +// // Ok(()) +// // } +// // ); + +// // impl_bigint_test_circuit!( +// // TestMulCase4Circuit, +// // test_mul_case4, +// // 64, +// // 2048, +// // false, +// // fn synthesize( +// // &self, +// // config: Self::Config, +// // mut layouter: impl halo2wrong::halo2::circuit::Layouter, +// // ) -> Result<(), Error> { +// // let bigint_chip = self.bigint_chip(config); +// // layouter.assign_region( +// // || "(3 + 4x + 5x^2 + 6x^3)(9 + 10x + 11x^2 + 12x^3) = 27 + 66 x + 118 x^2 + 184 x^3 + 163 x^4 + 126 x^5 + 72 x^6 ", +// // |region| { +// // let offset = 0; +// // let ctx = &mut RegionCtx::new(region, offset); +// // let out_base = BigUint::from(1usize) << Self::LIMB_WIDTH; +// // let a_big = +// // BigUint::from(3usize) + 4usize * &out_base + 5usize * &out_base.pow(2) + 6usize * &out_base.pow(3); +// // let a_assigned = bigint_chip.assign_constant_fresh(ctx, a_big)?; +// // let n1 = a_assigned.num_limbs(); +// // let b_big = +// // BigUint::from(9usize) + 10usize * &out_base + 11usize * &out_base.pow(2) + 12usize * &out_base.pow(3); +// // let b_assigned = bigint_chip.assign_constant_fresh(ctx, b_big)?; +// // let n2 = b_assigned.num_limbs(); +// // let ab = bigint_chip.mul(ctx, &a_assigned, &b_assigned)?; +// // let ans_big = BigUint::from(27usize) + 66usize * &out_base + 118usize * &out_base.pow(2u32) + 184usize * &out_base.pow(3u32) + 163usize * &out_base.pow(4u32) + 126usize * &out_base.pow(5u32) + 72usize * &out_base.pow(6u32); +// // let ans_assigned = bigint_chip.assign_constant_muled(ctx, ans_big, n1, n2)?; +// // bigint_chip.assert_equal_muled(ctx, &ab, &ans_assigned, n1, n2)?; +// // Ok(()) +// // }, +// // )?; +// // let range_chip = bigint_chip.range_chip(); +// // range_chip.load_table(&mut layouter)?; +// // //range_chip.load_overflow_tables(&mut layouter)?; +// // Ok(()) +// // } +// // ); + +// // impl_bigint_test_circuit!( +// // TestMulCase5Circuit, +// // test_mul_case5, +// // 64, +// // 2048, +// // false, +// // fn synthesize( +// // &self, +// // config: Self::Config, +// // mut layouter: impl halo2wrong::halo2::circuit::Layouter, +// // ) -> Result<(), Error> { +// // let bigint_chip = self.bigint_chip(config); +// // layouter.assign_region( +// // || "big square test", +// // |region| { +// // let offset = 0; +// // let ctx = &mut RegionCtx::new(region, offset); +// // let out_base = BigUint::from(1usize) << Self::LIMB_WIDTH; +// // let a_big = BigUint::from(4819187580044832333u128) +// // + 9183764011217009606u128 * &out_base +// // + 11426964127496009747u128 * &out_base.pow(2) +// // + 17898263845095661790u128 * &out_base.pow(3) +// // + 12102522037140783322u128 * &out_base.pow(4) +// // + 4029304176671511763u128 * &out_base.pow(5) +// // + 11339410859987005436u128 * &out_base.pow(6) +// // + 12120243430436644729u128 * &out_base.pow(7) +// // + 2888435820322958146u128 * &out_base.pow(8) +// // + 7612614626488966390u128 * &out_base.pow(9) +// // + 3872170484348249672u128 * &out_base.pow(10) +// // + 9589147526444685354u128 * &out_base.pow(11) +// // + 16391157694429928307u128 * &out_base.pow(12) +// // + 12256166884204507566u128 * &out_base.pow(13) +// // + 4257963982333550934u128 * &out_base.pow(14) +// // + 916988490704u128 * &out_base.pow(15); +// // let a_assigned = bigint_chip.assign_constant_fresh(ctx, a_big)?; +// // let n1 = a_assigned.num_limbs(); +// // let ab = bigint_chip.square(ctx, &a_assigned)?; +// // let ans_big = BigUint::from(23224568931658367244754058218082222889u128) +// // + BigUint::from_str("88516562921839445888640380379840781596").unwrap() +// // * &out_base +// // + BigUint::from_str("194478888615417946406783868151393774738").unwrap() +// // * &out_base.pow(2) +// // + BigUint::from_str("382395265476432217957523230769986571504").unwrap() +// // * &out_base.pow(3) +// // + BigUint::from_str("575971019676008360859069855433378813941").unwrap() +// // * &out_base.pow(4) +// // + BigUint::from_str("670174995752918677131397897218932582682").unwrap() +// // * &out_base.pow(5) +// // + BigUint::from_str("780239872348808029089572423614905198300").unwrap() +// // * &out_base.pow(6) +// // + BigUint::from_str("850410093737715640261630122959874522628").unwrap() +// // * &out_base.pow(7) +// // + BigUint::from_str("800314959349304909735238452892956199392").unwrap() +// // * &out_base.pow(8) +// // + BigUint::from_str("906862855407309870283714027678210238070").unwrap() +// // * &out_base.pow(9) +// // + BigUint::from_str("967727310654811444144097720329196927129").unwrap() +// // * &out_base.pow(10) +// // + BigUint::from_str("825671020037461535758117365587238596380").unwrap() +// // * &out_base.pow(11) +// // + BigUint::from_str("991281789723902700168027417052185830252").unwrap() +// // * &out_base.pow(12) +// // + BigUint::from_str("1259367815833216292413970809061165585320").unwrap() +// // * &out_base.pow(13) +// // + BigUint::from_str("1351495628781923848799708082622582598675").unwrap() +// // * &out_base.pow(14) +// // + BigUint::from_str("1451028634949220760698564802414695011932").unwrap() +// // * &out_base.pow(15) +// // + BigUint::from_str("1290756126635958771067082204577975256756").unwrap() +// // * &out_base.pow(16) +// // + BigUint::from_str("936482288980049848345464202850902738826").unwrap() +// // * &out_base.pow(17) +// // + BigUint::from_str("886330568585033438612679243731110283692").unwrap() +// // * &out_base.pow(18) +// // + BigUint::from_str("823948310509772835433730556487356331346").unwrap() +// // * &out_base.pow(19) +// // + BigUint::from_str("649341353489205691855914543942648985328").unwrap() +// // * &out_base.pow(20) +// // + BigUint::from_str("497838205323760437611385487609464464168").unwrap() +// // * &out_base.pow(21) +// // + BigUint::from_str("430091148520710550273018448938020664564").unwrap() +// // * &out_base.pow(22) +// // + BigUint::from_str("474098876922017329965321439330710234148").unwrap() +// // * &out_base.pow(23) +// // + BigUint::from_str("536697574159375092388958994084813127393").unwrap() +// // * &out_base.pow(24) +// // + BigUint::from_str("483446024935732188792400155524449880972").unwrap() +// // * &out_base.pow(25) +// // + BigUint::from_str("289799562463011227421662267162524920264").unwrap() +// // * &out_base.pow(26) +// // + BigUint::from_str("104372664369829937912234314161010649544").unwrap() +// // * &out_base.pow(27) +// // + BigUint::from_str("18130279752377737976455635841349605284").unwrap() +// // * &out_base.pow(28) +// // + BigUint::from_str("7809007931264072381739139035072").unwrap() +// // * &out_base.pow(29) +// // + BigUint::from_str("840867892083599894415616").unwrap() +// // * &out_base.pow(30) +// // + BigUint::from_str("0").unwrap() * &out_base.pow(31); +// // let ans_assigned = bigint_chip.assign_constant_muled(ctx, ans_big, n1, n1)?; +// // bigint_chip.assert_equal_muled(ctx, &ab, &ans_assigned, n1, n1)?; +// // Ok(()) +// // }, +// // )?; +// // let range_chip = bigint_chip.range_chip(); +// // range_chip.load_table(&mut layouter)?; +// // //range_chip.load_overflow_tables(&mut layouter)?; +// // Ok(()) +// // } +// // ); + +// // impl_bigint_test_circuit!( +// // TestMulCase6Circuit, +// // test_mul_case6, +// // 64, +// // 2048, +// // false, +// // fn synthesize( +// // &self, +// // config: Self::Config, +// // mut layouter: impl halo2wrong::halo2::circuit::Layouter, +// // ) -> Result<(), Error> { +// // let bigint_chip = self.bigint_chip(config); +// // layouter.assign_region( +// // || "(1+x)(1+x+x^2) = 1 + 2x + 2x^2 + x^3", +// // |region| { +// // let offset = 0; +// // let ctx = &mut RegionCtx::new(region, offset); +// // let out_base = BigUint::from(1usize) << Self::LIMB_WIDTH; +// // let a_big = BigUint::from(1usize) + 1usize * &out_base; +// // let a_assigned = bigint_chip.assign_constant_fresh(ctx, a_big)?; +// // let n1 = a_assigned.num_limbs(); +// // let b_big = +// // BigUint::from(1usize) + 1usize * &out_base + 1usize * &out_base.pow(2); +// // let b_assigned = bigint_chip.assign_constant_fresh(ctx, b_big)?; +// // let n2 = b_assigned.num_limbs(); +// // let ab = bigint_chip.mul(ctx, &a_assigned, &b_assigned)?; +// // let ans_big = BigUint::from(1usize) +// // + 2usize * &out_base +// // + 2usize * &out_base.pow(2u32) +// // + 1usize * &out_base.pow(3u32); +// // let ans_assigned = bigint_chip.assign_constant_muled(ctx, ans_big, n1, n2)?; +// // bigint_chip.assert_equal_muled(ctx, &ab, &ans_assigned, n1, n2)?; +// // Ok(()) +// // }, +// // )?; +// // let range_chip = bigint_chip.range_chip(); +// // range_chip.load_table(&mut layouter)?; +// // //range_chip.load_overflow_tables(&mut layouter)?; +// // Ok(()) +// // } +// // ); + +// // impl_bigint_test_circuit!( +// // TestMulCase7Circuit, +// // test_mul_case7, +// // 64, +// // 2048, +// // false, +// // fn synthesize( +// // &self, +// // config: Self::Config, +// // mut layouter: impl halo2wrong::halo2::circuit::Layouter, +// // ) -> Result<(), Error> { +// // let bigint_chip = self.bigint_chip(config); +// // layouter.assign_region( +// // || "(1+7x)(1+x+x^2) = 1 + 8x + 8x^2 + 7x^3", +// // |region| { +// // let offset = 0; +// // let ctx = &mut RegionCtx::new(region, offset); +// // let out_base = BigUint::from(1usize) << Self::LIMB_WIDTH; +// // let a_big = BigUint::from(1usize) + 7usize * &out_base; +// // let a_assigned = bigint_chip.assign_constant_fresh(ctx, a_big)?; +// // let n1 = a_assigned.num_limbs(); +// // let b_big = +// // BigUint::from(1usize) + 1usize * &out_base + 1usize * &out_base.pow(2); +// // let b_assigned = bigint_chip.assign_constant_fresh(ctx, b_big)?; +// // let n2 = b_assigned.num_limbs(); +// // let ab = bigint_chip.mul(ctx, &a_assigned, &b_assigned)?; +// // let ans_big = BigUint::from(1usize) +// // + 8usize * &out_base +// // + 8usize * &out_base.pow(2u32) +// // + 7usize * &out_base.pow(3u32); +// // let ans_assigned = bigint_chip.assign_constant_muled(ctx, ans_big, n1, n2)?; +// // bigint_chip.assert_equal_muled(ctx, &ab, &ans_assigned, n1, n2)?; +// // Ok(()) +// // }, +// // )?; +// // let range_chip = bigint_chip.range_chip(); +// // range_chip.load_table(&mut layouter)?; +// // //range_chip.load_overflow_tables(&mut layouter)?; +// // Ok(()) +// // } +// // ); + +// // impl_bigint_test_circuit!( +// // TestMulModCase1Circuit, +// // test_mulmod_case1, +// // 64, +// // 2048, +// // false, +// // fn synthesize( +// // &self, +// // config: Self::Config, +// // mut layouter: impl halo2wrong::halo2::circuit::Layouter, +// // ) -> Result<(), Error> { +// // let bigint_chip = self.bigint_chip(config); +// // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; +// // layouter.assign_region( +// // || "0 * (random) = 0 mod n", +// // |region| { +// // let offset = 0; +// // let ctx = &mut RegionCtx::new(region, offset); +// // let zero_big = BigUint::from(0usize); +// // let a_big = zero_big.clone(); +// // let a_assigned = bigint_chip.assign_constant_fresh(ctx, a_big)?; +// // let b_limbs = decompose_big::(self.b.clone(), num_limbs, Self::LIMB_WIDTH); +// // let b_unassigned = UnassignedInteger::from(b_limbs); +// // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; +// // let n_limbs = decompose_big::(self.n.clone(), num_limbs, Self::LIMB_WIDTH); +// // let n_unassigned = UnassignedInteger::from(n_limbs); +// // let n_assigned = bigint_chip.assign_integer(ctx, n_unassigned)?; +// // let ab = bigint_chip.mul_mod(ctx, &a_assigned, &b_assigned, &n_assigned)?; +// // let ans_big = zero_big; +// // let ans_assigned = bigint_chip.assign_constant_fresh(ctx, ans_big)?; +// // bigint_chip.assert_equal_fresh(ctx, &ab, &ans_assigned)?; +// // Ok(()) +// // }, +// // )?; +// // let range_chip = bigint_chip.range_chip(); +// // range_chip.load_table(&mut layouter)?; +// // //range_chip.load_overflow_tables(&mut layouter)?; +// // Ok(()) +// // } +// // ); + +// // impl_bigint_test_circuit!( +// // TestMulModCase2Circuit, +// // test_mulmod_case2, +// // 64, +// // 2048, +// // false, +// // fn synthesize( +// // &self, +// // config: Self::Config, +// // mut layouter: impl halo2wrong::halo2::circuit::Layouter, +// // ) -> Result<(), Error> { +// // let bigint_chip = self.bigint_chip(config); +// // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; +// // layouter.assign_region( +// // || "n * 1 mod n = 0", +// // |region| { +// // let offset = 0; +// // let ctx = &mut RegionCtx::new(region, offset); +// // let a_limbs = decompose_big::(self.n.clone(), num_limbs, Self::LIMB_WIDTH); +// // let a_unassigned = UnassignedInteger::from(a_limbs); +// // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; +// // let b_big = BigUint::from(1usize); +// // let b_assigned = bigint_chip.assign_constant_fresh(ctx, b_big)?; +// // let n_limbs = decompose_big::(self.n.clone(), num_limbs, Self::LIMB_WIDTH); +// // let n_unassigned = UnassignedInteger::from(n_limbs); +// // let n_assigned = bigint_chip.assign_integer(ctx, n_unassigned)?; +// // let ab = bigint_chip.mul_mod(ctx, &a_assigned, &b_assigned, &n_assigned)?; +// // let ans_big = BigUint::from(0usize); +// // let ans_assigned = bigint_chip.assign_constant_fresh(ctx, ans_big)?; +// // bigint_chip.assert_equal_fresh(ctx, &ab, &ans_assigned)?; +// // Ok(()) +// // }, +// // )?; +// // let range_chip = bigint_chip.range_chip(); +// // range_chip.load_table(&mut layouter)?; +// // //range_chip.load_overflow_tables(&mut layouter)?; +// // Ok(()) +// // } +// // ); + +// // impl_bigint_test_circuit!( +// // TestMulModCase3Circuit, +// // test_mulmod_case3, +// // 64, +// // 2048, +// // false, +// // fn synthesize( +// // &self, +// // config: Self::Config, +// // mut layouter: impl halo2wrong::halo2::circuit::Layouter, +// // ) -> Result<(), Error> { +// // let bigint_chip = self.bigint_chip(config); +// // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; +// // layouter.assign_region( +// // || "(n - 1) * (n - 1) mod n = 1", +// // |region| { +// // let offset = 0; +// // let ctx = &mut RegionCtx::new(region, offset); +// // let n_sub_1 = &self.n - &1u8; +// // let a_limbs = decompose_big::(n_sub_1.clone(), num_limbs, Self::LIMB_WIDTH); +// // let a_unassigned = UnassignedInteger::from(a_limbs); +// // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; +// // let b_limbs = decompose_big::(n_sub_1.clone(), num_limbs, Self::LIMB_WIDTH); +// // let b_unassigned = UnassignedInteger::from(b_limbs); +// // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; +// // let n_limbs = decompose_big::(self.n.clone(), num_limbs, Self::LIMB_WIDTH); +// // let n_unassigned = UnassignedInteger::from(n_limbs); +// // let n_assigned = bigint_chip.assign_integer(ctx, n_unassigned)?; +// // let ab = bigint_chip.mul_mod(ctx, &a_assigned, &b_assigned, &n_assigned)?; +// // let ans_big = BigUint::from(1usize); +// // let ans_assigned = bigint_chip.assign_constant_fresh(ctx, ans_big)?; +// // bigint_chip.assert_equal_fresh(ctx, &ab, &ans_assigned)?; +// // Ok(()) +// // }, +// // )?; +// // let range_chip = bigint_chip.range_chip(); +// // range_chip.load_table(&mut layouter)?; +// // //range_chip.load_overflow_tables(&mut layouter)?; +// // Ok(()) +// // } +// // ); + +// // impl_bigint_test_circuit!( +// // TestMulModCase4Circuit, +// // test_mulmod_case4, +// // 64, +// // 2048, +// // false, +// // fn synthesize( +// // &self, +// // config: Self::Config, +// // mut layouter: impl halo2wrong::halo2::circuit::Layouter, +// // ) -> Result<(), Error> { +// // let bigint_chip = self.bigint_chip(config); +// // let num_limbs = Self::BITS_LEN / Self::LIMB_WIDTH; +// // layouter.assign_region( +// // || "(n - 1) * (n - 2) mod n = 2", +// // |region| { +// // let offset = 0; +// // let ctx = &mut RegionCtx::new(region, offset); +// // let n_sub_1 = &self.n - &1u8; +// // let a_limbs = decompose_big::(n_sub_1.clone(), num_limbs, Self::LIMB_WIDTH); +// // let a_unassigned = UnassignedInteger::from(a_limbs); +// // let a_assigned = bigint_chip.assign_integer(ctx, a_unassigned)?; +// // let n_sub_2 = &self.n - &2u8; +// // let b_limbs = decompose_big::(n_sub_2.clone(), num_limbs, Self::LIMB_WIDTH); +// // let b_unassigned = UnassignedInteger::from(b_limbs); +// // let b_assigned = bigint_chip.assign_integer(ctx, b_unassigned)?; +// // let n_limbs = decompose_big::(self.n.clone(), num_limbs, Self::LIMB_WIDTH); +// // let n_unassigned = UnassignedInteger::from(n_limbs); +// // let n_assigned = bigint_chip.assign_integer(ctx, n_unassigned)?; +// // let ab = bigint_chip.mul_mod(ctx, &a_assigned, &b_assigned, &n_assigned)?; +// // let ans_big = BigUint::from(2usize); +// // let ans_assigned = bigint_chip.assign_constant_fresh(ctx, ans_big)?; +// // bigint_chip.assert_equal_fresh(ctx, &ab, &ans_assigned)?; +// // Ok(()) +// // }, +// // )?; +// // let range_chip = bigint_chip.range_chip(); +// // range_chip.load_table(&mut layouter)?; +// // //range_chip.load_overflow_tables(&mut layouter)?; +// // Ok(()) +// // } +// // ); +// } diff --git a/src/big_uint/instructions.rs b/src/big_uint/instructions.rs index 71af315..d825082 100644 --- a/src/big_uint/instructions.rs +++ b/src/big_uint/instructions.rs @@ -1,235 +1,232 @@ use crate::{AssignedBigUint, Fresh, Muled, RangeType, RefreshAux}; -use halo2_base::halo2_proofs::circuit::Value; -// use halo2wrong::halo2::{arithmetic::FieldExt, plonk::Error}; -use halo2_base::gates::{flex_gate::FlexGateConfig, range::RangeConfig}; +use halo2_base::gates::{flex_gate::GateChip, range::RangeChip}; use halo2_base::halo2_proofs::plonk::Error; -use halo2_base::{utils::PrimeField, AssignedValue, Context}; -// use maingate::{AssignedValue, RegionCtx}; +use halo2_base::{utils::BigPrimeField, AssignedValue, Context}; use num_bigint::BigUint; /// Instructions for big-integer operations. -pub trait BigUintInstructions { - /// Return [`FlexGateConfig`] - fn gate(&self) -> &FlexGateConfig; - /// Return [`RangeConfig`] - fn range(&self) -> &RangeConfig; +pub trait BigUintInstructions { + /// Return [`GateChip`] + fn gate(&self) -> &GateChip; + /// Return [`RangeChip`] + fn range(&self) -> &RangeChip; /// Return limb bits. fn limb_bits(&self) -> usize; /// Assigns a variable [`AssignedBigUint`] whose [`RangeType`] is [`Fresh`]. - fn assign_integer<'v>( + fn assign_integer( &self, - ctx: &mut Context<'v, F>, - value: Value, + ctx: &mut Context, + value: &BigUint, bit_len: usize, - ) -> Result, Error>; + ) -> Result, Error>; /// Assigns a constant [`AssignedBigUint`] whose [`RangeType`] is [`Fresh`]. - fn assign_constant<'v>( + fn assign_constant( &self, - ctx: &mut Context<'v, F>, + ctx: &mut Context, value: BigUint, - ) -> Result, Error>; + ) -> Result, Error>; /// Assigns the maximum integer whose number of limbs is `num_limbs`. - fn max_value<'v>( + fn max_value( &self, - ctx: &mut Context<'v, F>, + ctx: &mut Context, num_limbs: usize, - ) -> Result, Error>; + ) -> Result, Error>; /// Converts a [`Muled`] type integer to a [`Fresh`] type integer. - fn refresh<'v>( + fn refresh( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Muled>, + ctx: &mut Context, + a: &AssignedBigUint, aux: &RefreshAux, - ) -> Result, Error>; + ) -> Result, Error>; /// Given a bit value `sel`, return `a` if `a`=1 and `b` otherwise. - fn select<'v, T: RangeType>( + fn select( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, T>, - b: &AssignedBigUint<'v, F, T>, - sel: &AssignedValue<'v, F>, - ) -> Result, Error>; + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, + sel: &AssignedValue, + ) -> Result, Error>; /// Given two inputs `a,b`, performs the addition `a + b`. - fn add<'v>( + fn add( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error>; + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, + ) -> Result, Error>; /// Given two inputs `a,b`, performs the subtraction `a - b`. /// The result is correct iff `a>=b`. - fn sub_unsafe<'v>( + fn sub_unsafe( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, - ) -> Result<(AssignedBigUint<'v, F, Fresh>, AssignedValue<'v, F>), Error>; + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, + ) -> Result<(AssignedBigUint, AssignedValue), Error>; /// Given two inputs `a,b`, performs the multiplication `a * b`. - fn mul<'v>( + fn mul( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error>; + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, + ) -> Result, Error>; /// Given a inputs `a`, performs the square `a^2`. - fn square<'v>( + fn square( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error>; + ctx: &mut Context, + a: &AssignedBigUint, + ) -> Result, Error>; /// Given two inputs `a,b` and a modulus `n`, performs the modular addition `a + b mod n`. - fn add_mod<'v>( + fn add_mod( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, - n: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error>; + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, + n: &AssignedBigUint, + ) -> Result, Error>; /// Given two inputs `a,b` and a modulus `n`, performs the modular subtraction `a - b mod n`. - fn sub_mod<'v>( + fn sub_mod( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, - n: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error>; + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, + n: &AssignedBigUint, + ) -> Result, Error>; /// Given two inputs `a,b` and a modulus `n`, performs the modular multiplication `a * b mod n`. - fn mul_mod<'v>( + fn mul_mod( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, - n: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error>; + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, + n: &AssignedBigUint, + ) -> Result, Error>; /// Given a input `a` and a modulus `n`, performs the modular square `a^2 mod n`. - fn square_mod<'v>( + fn square_mod( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - n: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error>; + ctx: &mut Context, + a: &AssignedBigUint, + n: &AssignedBigUint, + ) -> Result, Error>; /// Given a base `a`, a variable exponent `e`, and a modulus `n`, performs the modular power `a^e mod n`. - fn pow_mod<'v>( + fn pow_mod( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - e: &AssignedValue<'v, F>, - n: &AssignedBigUint<'v, F, Fresh>, + ctx: &mut Context, + a: &AssignedBigUint, + e: &AssignedValue, + n: &AssignedBigUint, exp_bits: usize, - ) -> Result, Error>; + ) -> Result, Error>; /// Given a base `a`, a fixed exponent `e`, and a modulus `n`, performs the modular power `a^e mod n`. - fn pow_mod_fixed_exp<'v>( + fn pow_mod_fixed_exp( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, + ctx: &mut Context, + a: &AssignedBigUint, e: &BigUint, - n: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error>; + n: &AssignedBigUint, + ) -> Result, Error>; /// Returns an assigned bit representing whether `a` is zero or not. - fn is_zero<'v>( + fn is_zero( &self, - ctx: &mut Context<'v, F>, - a: &'v AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error>; + ctx: &mut Context, + a: &AssignedBigUint, + ) -> Result, Error>; /// Returns an assigned bit representing whether `a` and `b` are equivalent, whose [`RangeType`] is [`Fresh`]. - fn is_equal_fresh<'v>( + fn is_equal_fresh( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error>; + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, + ) -> Result, Error>; /// Returns an assigned bit representing whether `a` and `b` are equivalent, whose [`RangeType`] is [`Muled`]. - fn is_equal_muled<'v>( + fn is_equal_muled( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Muled>, - b: &AssignedBigUint<'v, F, Muled>, + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, num_limbs_l: usize, num_limbs_r: usize, - ) -> Result, Error>; + ) -> Result, Error>; /// Returns an assigned bit representing whether `a` is less than `b` (`a( + fn is_less_than( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error>; + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, + ) -> Result, Error>; /// Returns an assigned bit representing whether `a` is less than or equal to `b` (`a<=b`). - fn is_less_than_or_equal<'v>( + fn is_less_than_or_equal( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error>; + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, + ) -> Result, Error>; /// Returns an assigned bit representing whether `a` is greater than `b` (`a>b`). - fn is_greater_than<'v>( + fn is_greater_than( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error>; + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, + ) -> Result, Error>; /// Returns an assigned bit representing whether `a` is greater than or equal to `b` (`a>=b`). - fn is_greater_than_or_equal<'v>( + fn is_greater_than_or_equal( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error>; + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, + ) -> Result, Error>; /// Returns an assigned bit representing whether `a` is in the order-`n` finite field. - fn is_in_field<'v>( + fn is_in_field( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, - ) -> Result, Error>; + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, + ) -> Result, Error>; /// Assert that an assigned bit representing whether `a` and `b` are equivalent, whose [`RangeType`] is [`Fresh`]. - fn assert_equal_fresh<'v>( + fn assert_equal_fresh( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, ) -> Result<(), Error>; /// Assert that an assigned bit representing whether `a` and `b` are equivalent, whose [`RangeType`] is [`Fresh`]. - fn assert_equal_muled<'v>( + fn assert_equal_muled( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Muled>, - b: &AssignedBigUint<'v, F, Muled>, + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, num_limbs_l: usize, num_limbs_r: usize, ) -> Result<(), Error>; /// Assert that an assigned bit representing whether `a` is in the order-`n` finite field. - fn assert_in_field<'v>( + fn assert_in_field( &self, - ctx: &mut Context<'v, F>, - a: &AssignedBigUint<'v, F, Fresh>, - b: &AssignedBigUint<'v, F, Fresh>, + ctx: &mut Context, + a: &AssignedBigUint, + b: &AssignedBigUint, ) -> Result<(), Error>; } diff --git a/src/big_uint/mod.rs b/src/big_uint/mod.rs index d9dd4f1..0185f91 100644 --- a/src/big_uint/mod.rs +++ b/src/big_uint/mod.rs @@ -7,19 +7,19 @@ pub use chip::*; pub use instructions::*; pub use utils::*; -use halo2_base::{halo2_proofs::circuit::Value, utils::PrimeField, AssignedValue}; -use halo2_ecc::bigint::{CRTInteger, OverflowInteger}; +use halo2_base::{utils::BigPrimeField, AssignedValue}; +use halo2_ecc::bigint::OverflowInteger; use num_bigint::BigUint; #[derive(Debug, Clone)] -pub struct AssignedBigUint<'v, F: PrimeField, T: RangeType> { - int: OverflowInteger<'v, F>, - value: Value, +pub struct AssignedBigUint { + int: OverflowInteger, + value: BigUint, _t: PhantomData, } -impl<'v, F: PrimeField, T: RangeType> AssignedBigUint<'v, F, T> { - pub fn new(int: OverflowInteger<'v, F>, value: Value) -> Self { +impl AssignedBigUint { + pub fn new(int: OverflowInteger, value: BigUint) -> Self { Self { int, value, @@ -35,15 +35,15 @@ impl<'v, F: PrimeField, T: RangeType> AssignedBigUint<'v, F, T> { self.int.limbs.len() } - pub fn limbs(&self) -> &[AssignedValue<'v, F>] { + pub fn limbs(&self) -> &[AssignedValue] { &self.int.limbs } - pub fn value(&self) -> Value { + pub fn value(&self) -> BigUint { self.value.clone() } - pub fn extend_limbs(&self, num_extend_limbs: usize, zero_value: AssignedValue<'v, F>) -> Self { + pub fn extend_limbs(&self, num_extend_limbs: usize, zero_value: AssignedValue) -> Self { let max_limb_bits = self.int_ref().max_limb_bits; let pre_num_limbs = self.num_limbs(); let mut limbs = self.int.limbs.clone(); @@ -51,7 +51,7 @@ impl<'v, F: PrimeField, T: RangeType> AssignedBigUint<'v, F, T> { limbs.push(zero_value.clone()); } assert_eq!(pre_num_limbs + num_extend_limbs, limbs.len()); - let int = OverflowInteger::construct(limbs, max_limb_bits); + let int = OverflowInteger::new(limbs, max_limb_bits); Self::new(int, self.value()) } @@ -59,23 +59,23 @@ impl<'v, F: PrimeField, T: RangeType> AssignedBigUint<'v, F, T> { let max_limb_bits = self.int_ref().max_limb_bits; let value = self.value(); let limbs = &self.int.limbs; - let int = OverflowInteger::construct(limbs[min..=max].to_vec(), max_limb_bits); + let int = OverflowInteger::new(limbs[min..=max].to_vec(), max_limb_bits); Self::new(int, value) } - pub fn int_ref(&'v self) -> &'v OverflowInteger<'v, F> { + pub fn int_ref(&self) -> &OverflowInteger { &self.int } } -impl<'v, F: PrimeField> AssignedBigUint<'v, F, Fresh> { - pub fn to_muled(self) -> AssignedBigUint<'v, F, Muled> { +impl AssignedBigUint { + pub fn to_muled(self) -> AssignedBigUint { AssignedBigUint::new(self.int, self.value) } } -impl<'v, F: PrimeField> AssignedBigUint<'v, F, Muled> { - pub(crate) fn to_fresh_unsafe(self) -> AssignedBigUint<'v, F, Fresh> { +impl AssignedBigUint { + pub fn to_fresh_unsafe(self) -> AssignedBigUint { AssignedBigUint::new(self.int, self.value) } } @@ -141,19 +141,6 @@ impl RefreshAux { } muled.push(sum); } - // for i in 0..d { - // let mut j = if num_limbs_r >= i + 1 { - // 0 - // } else { - // i + 1 - num_limbs_r - // }; - // muled.push(BigUint::from(0usize)); - // while j < num_limbs_l && j <= i { - // let k = i - j; - // muled[i] += &l_max[j] * &r_max[k]; - // j += 1; - // } - // } let mut increased_limbs_vec = Vec::new(); let mut cur_d = 0; let max_d = d; diff --git a/src/big_uint/utils.rs b/src/big_uint/utils.rs index b6facb7..7c5cd44 100644 --- a/src/big_uint/utils.rs +++ b/src/big_uint/utils.rs @@ -1,14 +1,8 @@ -use halo2_base::{ - halo2_proofs::circuit::Value, - utils::{ - bigint_to_fe, biguint_to_fe, bit_length, decompose_bigint as _decompose_bigint, - decompose_biguint as _decompose_biguint, modulus, PrimeField, - }, -}; -use num_bigint::{BigInt, BigUint, Sign}; -use num_traits::{One, Signed}; +use halo2_base::utils::{decompose_biguint as _decompose_biguint, BigPrimeField}; +use num_bigint::{BigInt, BigUint}; +use num_traits::Signed; -pub fn decompose_bigint( +pub fn decompose_bigint( e: &BigInt, number_of_limbs: usize, limb_bits_len: usize, @@ -23,7 +17,7 @@ pub fn decompose_bigint( } } -pub fn decompose_biguint( +pub fn decompose_biguint( e: &BigUint, number_of_limbs: usize, limb_bits_len: usize, @@ -75,7 +69,7 @@ pub(crate) fn decompose_u64_digits_to_limbs( .collect() } -pub(crate) fn big_pow_mod(a: &BigUint, b: &BigUint, n: &BigUint) -> BigUint { +pub fn big_pow_mod(a: &BigUint, b: &BigUint, n: &BigUint) -> BigUint { let one = BigUint::from(1usize); let two = BigUint::from(2usize); if b == &BigUint::default() { @@ -90,49 +84,4 @@ pub(crate) fn big_pow_mod(a: &BigUint, b: &BigUint, n: &BigUint) -> BigUint { } else { x2 } -} - -// pub(crate) struct CarryModParams { -// pub limb_bits: usize, -// pub num_limbs: usize, - -// pub num_limbs_bits: usize, -// pub num_limbs_log2_ceil: usize, -// pub limb_bases: Vec, -// pub limb_base_big: BigInt, -// pub limb_mask: BigUint, - -// pub p: BigInt, -// pub p_limbs: Vec, -// pub p_native: F, -// } - -// impl CarryModParams { -// pub fn new(limb_bits: usize, num_limbs: usize, p: BigInt) -> Self { -// // https://github.com/axiom-crypto/halo2-lib/blob/main/halo2-ecc/src/fields/fp.rs#L96 -// let limb_mask = (BigUint::from(1u64) << limb_bits) - 1usize; -// let p_limbs = decompose_bigint(&p, num_limbs, limb_bits); -// let native_modulus = BigInt::from_biguint(Sign::Plus, modulus::()); -// let p_native = bigint_to_fe(&(&p % &native_modulus)); - -// let limb_base = biguint_to_fe::(&(BigUint::one() << limb_bits)); -// let mut limb_bases = Vec::with_capacity(num_limbs); -// limb_bases.push(F::one()); -// while limb_bases.len() != num_limbs { -// limb_bases.push(limb_base * limb_bases.last().unwrap()); -// } - -// Self { -// limb_bits, -// num_limbs, -// num_limbs_bits: bit_length(num_limbs as u64), -// num_limbs_log2_ceil: bit_length(num_limbs as u64), -// limb_bases, -// limb_base_big: BigInt::one() << limb_bits, -// limb_mask, -// p: p.into(), -// p_limbs, -// p_native, -// } -// } -// } +} \ No newline at end of file diff --git a/src/chip.rs b/src/chip.rs index ea054bd..69f9e74 100644 --- a/src/chip.rs +++ b/src/chip.rs @@ -3,22 +3,19 @@ use crate::{ AssignedBigUint, AssignedRSAPubE, AssignedRSAPublicKey, AssignedRSASignature, BigUintConfig, Fresh, RSAInstructions, RSAPubE, RSAPublicKey, RSASignature, }; -use halo2_base::halo2_proofs::{circuit::Region, circuit::Value, plonk::Error}; -use halo2_base::utils::fe_to_bigint; -use halo2_base::ContextParams; +use halo2_base::halo2_proofs::plonk::Error; use halo2_base::QuantumCell; use halo2_base::{ - gates::{flex_gate::FlexGateConfig, range::RangeConfig, GateInstructions, RangeInstructions}, - utils::{bigint_to_fe, biguint_to_fe, fe_to_biguint, modulus, PrimeField}, + gates::{flex_gate::GateChip, range::RangeChip, GateInstructions, RangeInstructions}, + utils::{biguint_to_fe, fe_to_biguint, BigPrimeField}, AssignedValue, Context, }; use num_bigint::BigUint; -use std::marker::PhantomData; /// Configuration for [`RSAConfig`]. #[derive(Clone, Debug)] -pub struct RSAConfig { +pub struct RSAConfig { /// Configuration for [`BigUintConfig`]. biguint_config: BigUintConfig, /// The default bit length of [`Fresh`] type integers in this chip. @@ -27,7 +24,7 @@ pub struct RSAConfig { exp_bits: usize, } -impl RSAInstructions for RSAConfig { +impl RSAInstructions for RSAConfig { /// Assigns a [`AssignedRSAPublicKey`]. /// /// # Arguments @@ -36,17 +33,17 @@ impl RSAInstructions for RSAConfig { /// /// # Return values /// Returns a new [`AssignedRSAPublicKey`]. - fn assign_public_key<'v>( + fn assign_public_key( &self, - ctx: &mut Context<'v, F>, + ctx: &mut Context, public_key: RSAPublicKey, - ) -> Result, Error> { + ) -> Result, Error> { let biguint_config = self.biguint_config(); - let n = biguint_config.assign_integer(ctx, public_key.n, self.default_bits)?; + let n = biguint_config.assign_integer(ctx, &public_key.n, self.default_bits)?; let e = match public_key.e { RSAPubE::Var(e) => { - let assigned = self.gate().load_witness(ctx, e.map(|v| biguint_to_fe(&v))); - self.range().range_check(ctx, &assigned, self.exp_bits); + let assigned = ctx.load_witness(biguint_to_fe(&e)); + self.range().range_check(ctx, assigned, self.exp_bits); AssignedRSAPubE::Var(assigned) } RSAPubE::Fix(e) => AssignedRSAPubE::Fix(e), @@ -62,13 +59,13 @@ impl RSAInstructions for RSAConfig { /// /// # Return values /// Returns a new [`AssignedRSASignature`]. - fn assign_signature<'v>( + fn assign_signature( &self, - ctx: &mut Context<'v, F>, + ctx: &mut Context, signature: RSASignature, - ) -> Result, Error> { + ) -> Result, Error> { let biguint_config = self.biguint_config(); - let c = biguint_config.assign_integer(ctx, signature.c, self.default_bits)?; + let c = biguint_config.assign_integer(ctx, &signature.c, self.default_bits)?; Ok(AssignedRSASignature::new(c)) } @@ -81,12 +78,12 @@ impl RSAInstructions for RSAConfig { /// /// # Return values /// Returns the modular power result `x^e mod n` as [`AssignedBigUint`]. - fn modpow_public_key<'v>( + fn modpow_public_key( &self, - ctx: &mut Context<'v, F>, - x: &AssignedBigUint<'v, F, Fresh>, - public_key: &AssignedRSAPublicKey<'v, F>, - ) -> Result, Error> { + ctx: &mut Context, + x: &AssignedBigUint, + public_key: &AssignedRSAPublicKey, + ) -> Result, Error> { let biguint_config = self.biguint_config(); biguint_config.assert_in_field(ctx, x, &public_key.n)?; let powed = match &public_key.e { @@ -110,16 +107,16 @@ impl RSAInstructions for RSAConfig { /// Returns the assigned bit as [`AssignedValue`]. /// If `signature` is valid for `public_key` and `hashed_msg`, the bit is equivalent to one. /// Otherwise, the bit is equivalent to zero. - fn verify_pkcs1v15_signature<'v>( + fn verify_pkcs1v15_signature( &self, - ctx: &mut Context<'v, F>, - public_key: &AssignedRSAPublicKey<'v, F>, - hashed_msg: &[AssignedValue<'v, F>], - signature: &AssignedRSASignature<'v, F>, - ) -> Result, Error> { + ctx: &mut Context, + public_key: &AssignedRSAPublicKey, + hashed_msg: &[AssignedValue], + signature: &AssignedRSASignature, + ) -> Result, Error> { assert_eq!(self.biguint_config.limb_bits(), 64); let gate = self.gate(); - let mut is_eq = gate.load_constant(ctx, F::one()); + let mut is_eq = ctx.load_constant(F::from(1)); let powed = self.modpow_public_key(ctx, &signature.c, public_key)?; let hash_len = hashed_msg.len(); assert_eq!(hash_len, 4); @@ -128,13 +125,13 @@ impl RSAInstructions for RSAConfig { for (limb, hash) in powed.limbs()[0..hash_len].iter().zip(hashed_msg.iter()) { let is_hash_eq = gate.is_equal( ctx, - QuantumCell::Existing(limb), - QuantumCell::Existing(hash), + QuantumCell::Existing(*limb), + QuantumCell::Existing(*hash), ); is_eq = gate.and( ctx, - QuantumCell::Existing(&is_eq), - QuantumCell::Existing(&is_hash_eq), + QuantumCell::Existing(is_eq), + QuantumCell::Existing(is_hash_eq), ); } @@ -143,103 +140,100 @@ impl RSAInstructions for RSAConfig { // 0b00110000001100010011000000001101000001100000100101100000100001100100100000000001011001010000001100000100000000100000000100000101000000000000010000100000 let is_prefix_64_1_eq = gate.is_equal( ctx, - QuantumCell::Existing(&powed.limbs()[hash_len]), + QuantumCell::Existing(powed.limbs()[hash_len]), QuantumCell::Constant(biguint_to_fe(&BigUint::from(217300885422736416u64))), ); let is_prefix_64_2_eq = gate.is_equal( ctx, - QuantumCell::Existing(&powed.limbs()[hash_len + 1]), + QuantumCell::Existing(powed.limbs()[hash_len + 1]), QuantumCell::Constant(biguint_to_fe(&BigUint::from(938447882527703397u64))), ); let is_eq = gate.and( ctx, - QuantumCell::Existing(&is_eq), - QuantumCell::Existing(&is_prefix_64_1_eq), + QuantumCell::Existing(is_eq), + QuantumCell::Existing(is_prefix_64_1_eq), ); let is_eq = gate.and( ctx, - QuantumCell::Existing(&is_eq), - QuantumCell::Existing(&is_prefix_64_2_eq), + QuantumCell::Existing(is_eq), + QuantumCell::Existing(is_prefix_64_2_eq), ); // remain 24 bit let u32_v: BigUint = BigUint::from(1usize) << 32; - let (remain_low, remain_high) = powed - .limb(hash_len + 2) - .value() - .map(|v| { - let big_v = fe_to_biguint(v); - let low = biguint_to_fe::(&(&big_v % &u32_v)); - let high = biguint_to_fe::(&(&big_v / &u32_v)); - (low, high) - }) - .unzip(); + let (remain_low, remain_high) = { + let a = powed.limb(hash_len + 2).value(); + let big_v = fe_to_biguint(a); + let low = biguint_to_fe::(&(&big_v % &u32_v)); + let high = biguint_to_fe::(&(&big_v / &u32_v)); + (low, high) + }; let range = self.range(); - let remain_low = gate.load_witness(ctx, remain_low); - range.range_check(ctx, &remain_low, 32); - let remain_high = gate.load_witness(ctx, remain_high); - range.range_check(ctx, &remain_high, 32); + let remain_low = ctx.load_witness(remain_low); + range.range_check(ctx, remain_low, 32); + let remain_high = ctx.load_witness(remain_high); + range.range_check(ctx, remain_high, 32); let remain_concat = gate.mul_add( ctx, - QuantumCell::Existing(&remain_high), + QuantumCell::Existing(remain_high), QuantumCell::Constant(biguint_to_fe(&u32_v)), - QuantumCell::Existing(&remain_low), + QuantumCell::Existing(remain_low), ); - gate.assert_equal( + gate.is_equal( ctx, - QuantumCell::Existing(&powed.limbs()[hash_len + 2]), - QuantumCell::Existing(&remain_concat), + QuantumCell::Existing(powed.limbs()[hash_len + 2]), + QuantumCell::Existing(remain_concat), ); let is_prefix_32_eq = gate.is_equal( ctx, - QuantumCell::Existing(&remain_low), + QuantumCell::Existing(remain_low), QuantumCell::Constant(biguint_to_fe(&BigUint::from(3158320u32))), ); let is_eq = gate.and( ctx, - QuantumCell::Existing(&is_eq), - QuantumCell::Existing(&is_prefix_32_eq), + QuantumCell::Existing(is_eq), + QuantumCell::Existing(is_prefix_32_eq), ); // 3. Check PS and em[1] = 1. the same code like golang std lib rsa.VerifyPKCS1v15 let is_ff_32_eq = gate.is_equal( ctx, - QuantumCell::Existing(&remain_high), + QuantumCell::Existing(remain_high), QuantumCell::Constant(biguint_to_fe(&BigUint::from(4294967295u32))), ); let mut is_eq = gate.and( ctx, - QuantumCell::Existing(&is_eq), - QuantumCell::Existing(&is_ff_32_eq), + QuantumCell::Existing(is_eq), + QuantumCell::Existing(is_ff_32_eq), ); let num_limbs = self.default_bits / self.biguint_config().limb_bits(); for limb in powed.limbs()[(hash_len + 3)..(num_limbs - 1)].iter() { let is_ff_64_eq = gate.is_equal( ctx, - QuantumCell::Existing(limb), + QuantumCell::Existing(*limb), QuantumCell::Constant(biguint_to_fe(&BigUint::from(18446744073709551615u64))), ); is_eq = gate.and( ctx, - QuantumCell::Existing(&is_eq), - QuantumCell::Existing(&is_ff_64_eq), + QuantumCell::Existing(is_eq), + QuantumCell::Existing(is_ff_64_eq), ); } //562949953421311 = 0b1111111111111111111111111111111111111111111111111 = 0x00 || 0x01 || (0xff)^* let is_last_em_eq = gate.is_equal( ctx, - QuantumCell::Existing(&powed.limbs()[num_limbs - 1]), + QuantumCell::Existing(powed.limbs()[num_limbs - 1]), QuantumCell::Constant(biguint_to_fe(&BigUint::from(562949953421311u64))), ); let is_eq = gate.and( ctx, - QuantumCell::Existing(&is_eq), - QuantumCell::Existing(&is_last_em_eq), + QuantumCell::Existing(is_eq), + QuantumCell::Existing(is_last_em_eq), ); Ok(is_eq.clone()) } } -impl RSAConfig { +impl RSAConfig { /// Creates new [`RSAConfig`] from [`BigUintInstructions`]. /// /// # Arguments @@ -261,606 +255,285 @@ impl RSAConfig { } } - /// Return [`Context`] - pub fn new_context<'a, 'b>(&'b self, region: Region<'a, F>) -> Context<'a, F> { - self.biguint_config.new_context(region) - } - /// Getter for [`BigUintConfig`]. pub fn biguint_config(&self) -> &BigUintConfig { &self.biguint_config } - /// Getter for [`FlexGateConfig`]. - pub fn gate(&self) -> &FlexGateConfig { + /// Getter for [`GateChip`]. + pub fn gate(&self) -> &GateChip { &self.biguint_config.gate() } - /// Getter for [`RangeConfig`]. - pub fn range(&self) -> &RangeConfig { + /// Getter for [`RangeChip`]. + pub fn range(&self) -> &RangeChip { &self.biguint_config.range() } } #[cfg(test)] mod test { + use crate::big_uint::decompose_biguint; use std::str::FromStr; - use super::*; - use crate::big_uint::decompose_biguint; - use halo2_base::halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner}, - dev::MockProver, - halo2curves::bn256::Fr, - plonk::{Circuit, ConstraintSystem}, - }; - use halo2_base::{gates::range::RangeStrategy::Vertical, ContextParams, SKIP_FIRST_PASS}; - - use num_bigint::RandomBits; - use num_traits::FromPrimitive; - use rand::{thread_rng, Rng}; - - macro_rules! impl_rsa_modpow_test_circuit { - ($circuit_name:ident, $test_fn_name:ident, $bits_len:expr, $limb_bits:expr, $k:expr, $should_be_error:expr, $( $synth:tt )*) => { - struct $circuit_name { - n: BigUint, - e: BigUint, - x: BigUint, - _f: PhantomData - } - - impl $circuit_name { - const BITS_LEN:usize = $bits_len; - const LIMB_BITS:usize = $limb_bits; - const EXP_LIMB_BITS:usize = 5; - const DEFAULT_E: u128 = 65537; - const NUM_ADVICE:usize = 50; - const NUM_FIXED:usize = 1; - const NUM_LOOKUP_ADVICE:usize = 4; - const LOOKUP_BITS:usize = 12; - } - - impl Circuit for $circuit_name { - type Config = RSAConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - unimplemented!(); - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let range_config = RangeConfig::configure(meta,Vertical, &[Self::NUM_ADVICE], &[Self::NUM_LOOKUP_ADVICE], Self::NUM_FIXED, Self::LOOKUP_BITS, 0, $k); - let bigint_config = BigUintConfig::construct(range_config, Self::LIMB_BITS); - RSAConfig::construct(bigint_config, Self::BITS_LEN, Self::EXP_LIMB_BITS) - } - - $( $synth )* - - } - - #[test] - fn $test_fn_name() { - fn run() { - let mut rng = thread_rng(); - let bits_len = $circuit_name::::BITS_LEN as u64; - let mut n = BigUint::default(); - while n.bits() != bits_len { - n = rng.sample(RandomBits::new(bits_len)); - } - let e = rng.sample::(RandomBits::new($circuit_name::::EXP_LIMB_BITS as u64)) % &n; - let x = rng.sample::(RandomBits::new(bits_len)) % &n; - let circuit = $circuit_name:: { - n, - e, - x, - _f: PhantomData - }; - - let public_inputs = vec![]; - let k = $k; - let prover = match MockProver::run(k, &circuit, public_inputs) { - Ok(prover) => prover, - Err(e) => panic!("{:#?}", e) - }; - assert_eq!(prover.verify().is_err(), $should_be_error); - } - run::(); - } - }; - } - + use halo2_base::halo2_proofs::halo2curves::bn256::Fr; + use halo2_base::utils::testing::base_test; use crate::big_pow_mod; - impl_rsa_modpow_test_circuit!( - TestRSAModPow2048Circuit, - test_rsa_modpow_2048_circuit, - 2048, - 64, - 14, - false, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let biguint_config = config.biguint_config(); - - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "random rsa modpow test with 2048 bits public keys", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let e_var = RSAPubE::Var(Value::known(self.e.clone())); - let e_fix = RSAPubE::Fix(BigUint::from_u128(Self::DEFAULT_E).unwrap()); - let public_key_var = RSAPublicKey::new(Value::known(self.n.clone()), e_var); - let public_key_var = config.assign_public_key(ctx, public_key_var)?; - let public_key_fix = RSAPublicKey::new(Value::known(self.n.clone()), e_fix); - let public_key_fix = config.assign_public_key(ctx, public_key_fix)?; - let x_assigned = biguint_config.assign_integer( - ctx, - Value::known(self.x.clone()), - Self::BITS_LEN, - )?; - let powed_var = config.modpow_public_key(ctx, &x_assigned, &public_key_var)?; - let powed_fix = config.modpow_public_key(ctx, &x_assigned, &public_key_fix)?; - let valid_powed_var = big_pow_mod(&self.x, &self.e, &self.n); - let valid_powed_fix = - big_pow_mod(&self.x, &BigUint::from(Self::DEFAULT_E), &self.n); - let valid_powed_var = biguint_config.assign_constant(ctx, valid_powed_var)?; - let valid_powed_fix = biguint_config.assign_constant(ctx, valid_powed_fix)?; - biguint_config.assert_equal_fresh(ctx, &powed_var, &valid_powed_var)?; - biguint_config.assert_equal_fresh(ctx, &powed_fix, &valid_powed_fix)?; - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - impl_rsa_modpow_test_circuit!( - TestBadRSAModPow2048Circuit, - test_bad_rsa_modpow_2048_circuit, - 2048, - 64, - 14, - true, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let biguint_config = config.biguint_config(); - - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "random rsa modpow test with 2048 bits public keys", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let e_var = RSAPubE::Var(Value::known(self.e.clone())); - let e_fix = RSAPubE::Fix(BigUint::from_u128(Self::DEFAULT_E).unwrap()); - let public_key_var = RSAPublicKey::new(Value::known(self.n.clone()), e_var); - let public_key_var = config.assign_public_key(ctx, public_key_var)?; - let public_key_fix = RSAPublicKey::new(Value::known(self.n.clone()), e_fix); - let public_key_fix = config.assign_public_key(ctx, public_key_fix)?; - let x_assigned = biguint_config.assign_integer( - ctx, - Value::known(self.x.clone()), - Self::BITS_LEN, - )?; - let powed_var = config.modpow_public_key(ctx, &x_assigned, &public_key_var)?; - let powed_fix = config.modpow_public_key(ctx, &x_assigned, &public_key_fix)?; - let max = biguint_config.max_value(ctx, powed_var.num_limbs())?; - biguint_config.assert_equal_fresh(ctx, &powed_var, &max)?; - let max = biguint_config.max_value(ctx, powed_fix.num_limbs())?; - biguint_config.assert_equal_fresh(ctx, &powed_fix, &max)?; - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - impl_rsa_modpow_test_circuit!( - TestRSAModPow1024Circuit, - test_rsa_modpow_1024_circuit, - 1024, - 64, - 13, - false, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let biguint_config = config.biguint_config(); - let limb_bits = Self::LIMB_BITS; - let num_limbs = Self::BITS_LEN / Self::LIMB_BITS; - - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "random rsa modpow test with 2048 bits public keys", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let e_var = RSAPubE::Var(Value::known(self.e.clone())); - let e_fix = RSAPubE::Fix(BigUint::from_u128(Self::DEFAULT_E).unwrap()); - let public_key_var = RSAPublicKey::new(Value::known(self.n.clone()), e_var); - let public_key_var = config.assign_public_key(ctx, public_key_var)?; - let public_key_fix = RSAPublicKey::new(Value::known(self.n.clone()), e_fix); - let public_key_fix = config.assign_public_key(ctx, public_key_fix)?; - let x_assigned = biguint_config.assign_integer( - ctx, - Value::known(self.x.clone()), - Self::BITS_LEN, - )?; - let powed_var = config.modpow_public_key(ctx, &x_assigned, &public_key_var)?; - let powed_fix = config.modpow_public_key(ctx, &x_assigned, &public_key_fix)?; - let valid_powed_var = big_pow_mod(&self.x, &self.e, &self.n); - let valid_powed_fix = - big_pow_mod(&self.x, &BigUint::from(Self::DEFAULT_E), &self.n); - let valid_powed_var = biguint_config.assign_constant(ctx, valid_powed_var)?; - let valid_powed_fix = biguint_config.assign_constant(ctx, valid_powed_fix)?; - biguint_config.assert_equal_fresh(ctx, &powed_var, &valid_powed_var)?; - biguint_config.assert_equal_fresh(ctx, &powed_fix, &valid_powed_fix)?; - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - impl_rsa_modpow_test_circuit!( - TestBadRSAModPow1024Circuit, - test_bad_rsa_modpow_1024_circuit, - 1024, - 64, - 13, - true, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let biguint_config = config.biguint_config(); - let limb_bits = Self::LIMB_BITS; - let num_limbs = Self::BITS_LEN / Self::LIMB_BITS; - - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "random rsa modpow test with 2048 bits public keys", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let e_var = RSAPubE::Var(Value::known(self.e.clone())); - let e_fix = RSAPubE::Fix(BigUint::from_u128(Self::DEFAULT_E).unwrap()); - let public_key_var = RSAPublicKey::new(Value::known(self.n.clone()), e_var); - let public_key_var = config.assign_public_key(ctx, public_key_var)?; - let public_key_fix = RSAPublicKey::new(Value::known(self.n.clone()), e_fix); - let public_key_fix = config.assign_public_key(ctx, public_key_fix)?; - let x_assigned = biguint_config.assign_integer( - ctx, - Value::known(self.x.clone()), - Self::BITS_LEN, - )?; - let powed_var = config.modpow_public_key(ctx, &x_assigned, &public_key_var)?; - let powed_fix = config.modpow_public_key(ctx, &x_assigned, &public_key_fix)?; - let max = biguint_config.max_value(ctx, powed_var.num_limbs())?; - biguint_config.assert_equal_fresh(ctx, &powed_var, &max)?; - let max = biguint_config.max_value(ctx, powed_fix.num_limbs())?; - biguint_config.assert_equal_fresh(ctx, &powed_fix, &max)?; - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - macro_rules! impl_rsa_signature_test_circuit { - ($circuit_name:ident, $test_fn_name:ident, $bits_len:expr, $limb_bits:expr, $k:expr, $should_be_error:expr, $( $synth:tt )*) => { - struct $circuit_name { - _f: PhantomData - } + #[test] + fn test_2048_modpow_public_key() { + let k: usize = 18; + + // Circuit inputs + let limb_bits = 64; + let default_bits = 2048; + let exp_bits = 5; + let default_e = 65537 as u32; + + base_test().k(k as u32).lookup_bits(k - 1).run(|ctx, range| { + let range = range.clone(); + let bigint_chip = BigUintConfig::construct(range, limb_bits); + let chip = RSAConfig::construct(bigint_chip, default_bits, exp_bits); + let e_fix = RSAPubE::Fix(BigUint::from(default_e)); + let n_big = BigUint::from_str("27333278531038650284292446400685983964543820405055158402397263907659995327446166369388984969315774410223081038389734916442552953312548988147687296936649645550823280957757266695625382122565413076484125874545818286099364801140117875853249691189224238587206753225612046406534868213180954324992542640955526040556053150097561640564120642863954208763490114707326811013163227280580130702236406906684353048490731840275232065153721031968704703853746667518350717957685569289022049487955447803273805415754478723962939325870164033644600353029240991739641247820015852898600430315191986948597672794286676575642204004244219381500407").unwrap(); + let public_key = RSAPublicKey::new(n_big.clone(), e_fix); + let public_key = chip.assign_public_key(ctx, public_key); + let msg_big = BigUint::from_str("83814198383102558219731078260892729932246618004265700685467928187377105751529").unwrap(); + let msg_assigned = chip.biguint_config.assign_integer( + ctx, + &msg_big.clone(), + default_bits, + ); + + let powed = chip.modpow_public_key(ctx, &msg_assigned.unwrap(), &public_key.unwrap()); + let expected_powed = big_pow_mod(&msg_big, &BigUint::from(default_e), &n_big); + let expected_powed = chip.biguint_config().assign_constant(ctx, expected_powed); + chip.biguint_config().assert_equal_fresh(ctx, &powed.unwrap(), &expected_powed.unwrap()).unwrap(); + }); + } - impl $circuit_name { - const BITS_LEN:usize = $bits_len; - const LIMB_BITS:usize = $limb_bits; - const EXP_LIMB_BITS:usize = 5; - const DEFAULT_E: u128 = 65537; - const NUM_ADVICE:usize = 50; - const NUM_FIXED:usize = 1; - const NUM_LOOKUP_ADVICE:usize = 4; - const LOOKUP_BITS:usize = 12; - } + #[test] + fn test_bad_2048_modpow_public_key() { + let k: usize = 18; + + // Circuit inputs + let limb_bits = 64; + let default_bits = 2048; + let exp_bits = 5; + let default_e = 65537 as u32; + + base_test().k(k as u32).lookup_bits(k - 1).expect_satisfied(false).run(|ctx, range| { + let range = range.clone(); + let bigint_chip = BigUintConfig::construct(range, limb_bits); + let chip = RSAConfig::construct(bigint_chip, default_bits, exp_bits); + let e_fix = RSAPubE::Fix(BigUint::from(default_e)); + let n_big = BigUint::from_str("27333278531038650284292446400685983964543820405055158402397263907659995327446166369388984969315774410223081038389734916442552953312548988147687296936649645550823280957757266695625382122565413076484125874545818286099364801140117875853249691189224238587206753225612046406534868213180954324992542640955526040556053150097561640564120642863954208763490114707326811013163227280580130702236406906684353048490731840275232065153721031968704703853746667518350717957685569289022049487955447803273805415754478723962939325870164033644600353029240991739641247820015852898600430315191986948597672794286676575642204004244219381500407").unwrap(); + let public_key = RSAPublicKey::new(n_big.clone(), e_fix); + let public_key = chip.assign_public_key(ctx, public_key); + let msg_big = BigUint::from_str("83814198383102558219731078260892729932246618004265700685467928187377105751529").unwrap(); + let msg_assigned = chip.biguint_config.assign_integer( + ctx, + &msg_big.clone(), + default_bits, + ); + + let powed = chip.modpow_public_key(ctx, &msg_assigned.unwrap(), &public_key.unwrap()); + let powed = powed.unwrap().clone(); + let max = chip.biguint_config().max_value(ctx, powed.num_limbs()); + chip.biguint_config().assert_equal_fresh(ctx, &powed, &max.unwrap()).unwrap(); + }); + } - impl Circuit for $circuit_name { - type Config = RSAConfig; - type FloorPlanner = SimpleFloorPlanner; + #[test] + fn test_1024_modpow_public_key() { + let k: usize = 18; + + // Circuit inputs + let limb_bits = 64; + let default_bits = 1024; + let exp_bits = 5; + let default_e = 65537 as u32; + + base_test().k(k as u32).lookup_bits(k - 1).run(|ctx, range| { + let range = range.clone(); + let bigint_chip = BigUintConfig::construct(range, limb_bits); + let chip = RSAConfig::construct(bigint_chip, default_bits, exp_bits); + let e_fix = RSAPubE::Fix(BigUint::from(default_e)); + let n_big = BigUint::from_str("107289837545940078268745022404080197756713492641688496535588794073231113663754058018862686762411228470731274703520877348777567694438387351688322419762264406460523426827357314688051865748955987197068553714344169462788708049399769970047547738378550534865494278049193738022398562701983786771227004540503235555427").unwrap(); + let public_key = RSAPublicKey::new(n_big.clone(), e_fix); + let public_key = chip.assign_public_key(ctx, public_key); + let msg_big = BigUint::from_str("77929134187608511922495239264200453516249189680211783157419138967626951463678384095540409755596022527110500588052868475990692956380263184337020353767554108632525056703455094349084868832834519825911531623507412532278652516715214908372427289788659924082086149173428600500839052600213260337159219251648111234888").unwrap(); + let msg_assigned = chip.biguint_config.assign_integer( + ctx, + &msg_big.clone(), + default_bits, + ); + + let powed = chip.modpow_public_key(ctx, &msg_assigned.unwrap(), &public_key.unwrap()); + let expected_powed = big_pow_mod(&msg_big, &BigUint::from(default_e), &n_big); + let expected_powed = chip.biguint_config().assign_constant(ctx, expected_powed); + chip.biguint_config().assert_equal_fresh(ctx, &powed.unwrap(), &expected_powed.unwrap()).unwrap(); + }); + } - fn without_witnesses(&self) -> Self { - unimplemented!(); - } + #[test] + fn test_bad_1024_modpow_public_key() { + let k: usize = 18; + + // Circuit inputs + let limb_bits = 64; + let default_bits = 1024; + let exp_bits = 5; + let default_e = 65537 as u32; + + base_test().k(k as u32).lookup_bits(k - 1).expect_satisfied(false).run(|ctx, range| { + let range = range.clone(); + let bigint_chip = BigUintConfig::construct(range, limb_bits); + let chip = RSAConfig::construct(bigint_chip, default_bits, exp_bits); + let e_fix = RSAPubE::Fix(BigUint::from(default_e)); + let n_big = BigUint::from_str("107289837545940078268745022404080197756713492641688496535588794073231113663754058018862686762411228470731274703520877348777567694438387351688322419762264406460523426827357314688051865748955987197068553714344169462788708049399769970047547738378550534865494278049193738022398562701983786771227004540503235555427").unwrap(); + let public_key = RSAPublicKey::new(n_big.clone(), e_fix); + let public_key = chip.assign_public_key(ctx, public_key); + let msg_big = BigUint::from_str("77929134187608511922495239264200453516249189680211783157419138967626951463678384095540409755596022527110500588052868475990692956380263184337020353767554108632525056703455094349084868832834519825911531623507412532278652516715214908372427289788659924082086149173428600500839052600213260337159219251648111234888").unwrap(); + let msg_assigned = chip.biguint_config.assign_integer( + ctx, + &msg_big.clone(), + default_bits, + ); + + let powed = chip.modpow_public_key(ctx, &msg_assigned.unwrap(), &public_key.unwrap()); + let powed = powed.unwrap().clone(); + let max = chip.biguint_config().max_value(ctx, powed.num_limbs()); + chip.biguint_config().assert_equal_fresh(ctx, &powed, &max.unwrap()).unwrap(); + }); + } - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let range_config = RangeConfig::configure(meta,Vertical, &[Self::NUM_ADVICE], &[Self::NUM_LOOKUP_ADVICE], Self::NUM_FIXED, Self::LOOKUP_BITS, 0, $k); - let bigint_config = BigUintConfig::construct(range_config, Self::LIMB_BITS); - RSAConfig::construct(bigint_config, Self::BITS_LEN, Self::EXP_LIMB_BITS) - } + #[test] + fn test_2048_verify_pkcs1v15_signature() { + let k: usize = 18; + + // Circuit inputs + let limb_bits = 64; + let default_bits = 2048; + let exp_bits = 5; + let default_e = 65537 as u32; + + base_test().k(k as u32).lookup_bits(k - 1).run(|ctx, range| { + let range = range.clone(); + let bigint_chip = BigUintConfig::construct(range, limb_bits); + let chip = RSAConfig::construct(bigint_chip, default_bits, exp_bits); + let e_fix = RSAPubE::Fix(BigUint::from(default_e)); + let n_big = BigUint::from_str("27333278531038650284292446400685983964543820405055158402397263907659995327446166369388984969315774410223081038389734916442552953312548988147687296936649645550823280957757266695625382122565413076484125874545818286099364801140117875853249691189224238587206753225612046406534868213180954324992542640955526040556053150097561640564120642863954208763490114707326811013163227280580130702236406906684353048490731840275232065153721031968704703853746667518350717957685569289022049487955447803273805415754478723962939325870164033644600353029240991739641247820015852898600430315191986948597672794286676575642204004244219381500407").unwrap(); + let public_key = RSAPublicKey::new(n_big, e_fix); + let public_key = chip.assign_public_key(ctx, public_key); + let sign_big = BigUint::from_str("27166015521685750287064830171899789431519297967327068200526003963687696216659347317736779094212876326032375924944649760206771585778103092909024744594654706678288864890801000499430246054971129440518072676833029702477408973737931913964693831642228421821166326489172152903376352031367604507095742732994611253344812562891520292463788291973539285729019102238815435155266782647328690908245946607690372534644849495733662205697837732960032720813567898672483741410294744324300408404611458008868294953357660121510817012895745326996024006347446775298357303082471522757091056219893320485806442481065207020262668955919408138704593").unwrap(); + let sign = RSASignature::new(sign_big); + let sign = chip.assign_signature(ctx, sign); + let hashed_msg_big = BigUint::from_str("83814198383102558219731078260892729932246618004265700685467928187377105751529").unwrap(); + let hashed_msg_limbs = decompose_biguint::(&hashed_msg_big, 4, 256/4); + let hashed_msg_assigned = hashed_msg_limbs.into_iter().map(|limb| ctx.load_witness(limb)).collect::>>(); + + let is_valid = chip.verify_pkcs1v15_signature(ctx, &public_key.unwrap(), &hashed_msg_assigned, &sign.unwrap()); + + chip.gate().assert_is_const(ctx, &is_valid.unwrap(), &Fr::one()); + }); + } - $( $synth )* + #[test] + fn test_bad_2048_verify_pkcs1v15_signature() { + let k: usize = 18; + + // Circuit inputs + let limb_bits = 64; + let default_bits = 2048; + let exp_bits = 5; + let default_e = 65537 as u32; + + base_test().k(k as u32).lookup_bits(k - 1).expect_satisfied(false).run(|ctx, range| { + let range = range.clone(); + let bigint_chip = BigUintConfig::construct(range, limb_bits); + let chip = RSAConfig::construct(bigint_chip, default_bits, exp_bits); + let e_fix = RSAPubE::Fix(BigUint::from(default_e)); + let n_big = BigUint::from_str("27333278531038650284292446400685983964543820405055158402397263907659995327446166369388984969315774410223081038389734916442552953312548988147687296936649645550823280957757266695625382122565413076484125874545818286099364801140117875853249691189224238587206753225612046406534868213180954324992542640955526040556053150097561640564120642863954208763490114707326811013163227280580130702236406906684353048490731840275232065153721031968704703853746667518350717957685569289022049487955447803273805415754478723962939325870164033644600353029240991739641247820015852898600430315191986948597672794286676575642204004244219381500407").unwrap(); + let public_key = RSAPublicKey::new(n_big, e_fix); + let public_key = chip.assign_public_key(ctx, public_key); + + // Input bad signature + let sign_big = BigUint::from_str("1234").unwrap(); + let sign = RSASignature::new(sign_big); + let sign = chip.assign_signature(ctx, sign); + let hashed_msg_big = BigUint::from_str("83814198383102558219731078260892729932246618004265700685467928187377105751529").unwrap(); + let hashed_msg_limbs = decompose_biguint::(&hashed_msg_big, 4, 256/4); + let hashed_msg_assigned = hashed_msg_limbs.into_iter().map(|limb| ctx.load_witness(limb)).collect::>>(); + + let is_valid = chip.verify_pkcs1v15_signature(ctx, &public_key.unwrap(), &hashed_msg_assigned, &sign.unwrap()); + + chip.gate().assert_is_const(ctx, &is_valid.unwrap(), &Fr::one()); + }); + } - } + #[test] + fn test_2048_verify_pkcs1v15_signature_2() { + let k: usize = 18; + + // Circuit inputs + let limb_bits = 64; + let default_bits = 2048; + let exp_bits = 5; + let default_e = 65537 as u32; + + base_test().k(k as u32).lookup_bits(k - 1).run(|ctx, range| { + let range = range.clone(); + let bigint_chip = BigUintConfig::construct(range, limb_bits); + let chip = RSAConfig::construct(bigint_chip, default_bits, exp_bits); + let e_fix = RSAPubE::Fix(BigUint::from(default_e)); + let n_big = BigUint::from_str("24226501697440012621102249466312043787685293040734225606346036389705515508545746221669035424138747582133889500686654172873671086178893587422987328751464627501601101326475761646014534358699943642495332701081302954020983110372109611581202820849485662540890985814355975252780310958088652613376767040069489530039075302709233494829280591680666351811024913107949144932224439129715181798714328219977771472462901856297952813239115577652450722815852332547886777292613005505949100406231716599634852632308325816916535875123863510650526931916871614411907700873376659841257216885666098127478325534982891697988739616416855214839339").unwrap(); + let public_key = RSAPublicKey::new(n_big, e_fix); + let public_key = chip.assign_public_key(ctx, public_key); + let sign_big = BigUint::from_str("18928545496959757512579438348223103860103247450097569223971486743312798156950374943336714741350742176674694049986481729075548718599712271054643150030165230392897481507710187505775911256946250999396358633095137650326818007610162375520522758780751710735664264200260854016867498935206556916247099180950775474524799944404833222133011134000549939512938205188018503377612813102061504146765520561811620128786062447005833886367575841545493555268747671930923697279690399480501746857825917608323993022396398648205737336204493624060285359455268389160802763426461171262704764369336704988874821898000892148693988241020931055723252").unwrap(); + let sign = RSASignature::new(sign_big); + let sign = chip.assign_signature(ctx, sign); + let hashed_msg_big = BigUint::from_str("83814198383102558219731078260892729932246618004265700685467928187377105751529").unwrap(); + let hashed_msg_limbs = decompose_biguint::(&hashed_msg_big, 4, 256/4); + let hashed_msg_assigned = hashed_msg_limbs.into_iter().map(|limb| ctx.load_witness(limb)).collect::>>(); + + let is_valid = chip.verify_pkcs1v15_signature(ctx, &public_key.unwrap(), &hashed_msg_assigned, &sign.unwrap()); + + chip.gate().assert_is_const(ctx, &is_valid.unwrap(), &Fr::one()); + }); + } - #[test] - fn $test_fn_name() { - fn run() { - let circuit = $circuit_name:: { - _f: PhantomData - }; - - let public_inputs = vec![]; - let k = $k; - let prover = match MockProver::run(k, &circuit, public_inputs) { - Ok(prover) => prover, - Err(e) => panic!("{:#?}", e) - }; - assert_eq!(prover.verify().is_err(), $should_be_error); - } - run::(); - } - }; + #[test] + fn test_bad_2048_verify_pkcs1v15_signature_2() { + let k: usize = 18; + + // Circuit inputs + let limb_bits = 64; + let default_bits = 2048; + let exp_bits = 5; + let default_e = 65537 as u32; + + base_test().k(k as u32).lookup_bits(k - 1).expect_satisfied(false).run(|ctx, range| { + let range = range.clone(); + let bigint_chip = BigUintConfig::construct(range, limb_bits); + let chip = RSAConfig::construct(bigint_chip, default_bits, exp_bits); + let e_fix = RSAPubE::Fix(BigUint::from(default_e)); + let n_big = BigUint::from_str("24226501697440012621102249466312043787685293040734225606346036389705515508545746221669035424138747582133889500686654172873671086178893587422987328751464627501601101326475761646014534358699943642495332701081302954020983110372109611581202820849485662540890985814355975252780310958088652613376767040069489530039075302709233494829280591680666351811024913107949144932224439129715181798714328219977771472462901856297952813239115577652450722815852332547886777292613005505949100406231716599634852632308325816916535875123863510650526931916871614411907700873376659841257216885666098127478325534982891697988739616416855214839339").unwrap(); + let public_key = RSAPublicKey::new(n_big, e_fix); + let public_key = chip.assign_public_key(ctx, public_key); + + // Input bad signature + let sign_big = BigUint::from_str("18928545496959757512579438348223103860103247450097569223971486743312798156950374943336714741350742176674694049986481729075548718599712271054643150030165230392897481507710187505775911256946250999396358633095137650326818007610162375520522758780751710735664264200260854016867498935206556916247099180950775474524799944404833222133011134000549939512938205188018503377612813102061504146765520561811620128786062447005833886367575841545493555268747671930923697279690399480501746857825917608323993022396398648205737336204493624060285359455268389160802763426461171262704764369336704988874821898000892148693988241020931055723251").unwrap(); + let sign = RSASignature::new(sign_big); + let sign = chip.assign_signature(ctx, sign); + let hashed_msg_big = BigUint::from_str("83814198383102558219731078260892729932246618004265700685467928187377105751529").unwrap(); + let hashed_msg_limbs = decompose_biguint::(&hashed_msg_big, 4, 256/4); + let hashed_msg_assigned = hashed_msg_limbs.into_iter().map(|limb| ctx.load_witness(limb)).collect::>>(); + + let is_valid = chip.verify_pkcs1v15_signature(ctx, &public_key.unwrap(), &hashed_msg_assigned, &sign.unwrap()); + + chip.gate().assert_is_const(ctx, &is_valid.unwrap(), &Fr::one()); + }); } - impl_rsa_signature_test_circuit!( - TestRSASignatureCircuit1, - test_rsa_signature_circuit1, - 2048, - 64, - 13, - false, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "random rsa modpow test with 2048 bits public keys", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let e_fix = RSAPubE::Fix(BigUint::from(Self::DEFAULT_E)); - let n_big = BigUint::from_str("27333278531038650284292446400685983964543820405055158402397263907659995327446166369388984969315774410223081038389734916442552953312548988147687296936649645550823280957757266695625382122565413076484125874545818286099364801140117875853249691189224238587206753225612046406534868213180954324992542640955526040556053150097561640564120642863954208763490114707326811013163227280580130702236406906684353048490731840275232065153721031968704703853746667518350717957685569289022049487955447803273805415754478723962939325870164033644600353029240991739641247820015852898600430315191986948597672794286676575642204004244219381500407").unwrap(); - let public_key = RSAPublicKey::new(Value::known(n_big), e_fix); - let public_key = config.assign_public_key(ctx, public_key)?; - let sign_big = BigUint::from_str("27166015521685750287064830171899789431519297967327068200526003963687696216659347317736779094212876326032375924944649760206771585778103092909024744594654706678288864890801000499430246054971129440518072676833029702477408973737931913964693831642228421821166326489172152903376352031367604507095742732994611253344812562891520292463788291973539285729019102238815435155266782647328690908245946607690372534644849495733662205697837732960032720813567898672483741410294744324300408404611458008868294953357660121510817012895745326996024006347446775298357303082471522757091056219893320485806442481065207020262668955919408138704593").unwrap(); - let sign = RSASignature::new(Value::known(sign_big)); - let sign = config.assign_signature(ctx, sign)?; - let hashed_msg_big = BigUint::from_str("83814198383102558219731078260892729932246618004265700685467928187377105751529").unwrap(); - let hashed_msg_limbs = decompose_biguint::(&hashed_msg_big, 4, 256/4); - let hashed_msg_assigned = hashed_msg_limbs.into_iter().map(|limb| config.gate().load_witness(ctx, Value::known(limb))).collect::>>(); - let is_valid = config.verify_pkcs1v15_signature(ctx, &public_key, &hashed_msg_assigned, &sign)?; - config.gate().assert_is_const(ctx, &is_valid, F::one()); - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - impl_rsa_signature_test_circuit!( - TestRSASignatureCircuit2, - test_rsa_signature_circuit2, - 2048, - 64, - 13, - false, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "random rsa modpow test with 2048 bits public keys", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let e_fix = RSAPubE::Fix(BigUint::from(Self::DEFAULT_E)); - let n_big = BigUint::from_str("24226501697440012621102249466312043787685293040734225606346036389705515508545746221669035424138747582133889500686654172873671086178893587422987328751464627501601101326475761646014534358699943642495332701081302954020983110372109611581202820849485662540890985814355975252780310958088652613376767040069489530039075302709233494829280591680666351811024913107949144932224439129715181798714328219977771472462901856297952813239115577652450722815852332547886777292613005505949100406231716599634852632308325816916535875123863510650526931916871614411907700873376659841257216885666098127478325534982891697988739616416855214839339").unwrap(); - let public_key = RSAPublicKey::new(Value::known(n_big), e_fix); - let public_key = config.assign_public_key(ctx, public_key)?; - let sign_big = BigUint::from_str("18928545496959757512579438348223103860103247450097569223971486743312798156950374943336714741350742176674694049986481729075548718599712271054643150030165230392897481507710187505775911256946250999396358633095137650326818007610162375520522758780751710735664264200260854016867498935206556916247099180950775474524799944404833222133011134000549939512938205188018503377612813102061504146765520561811620128786062447005833886367575841545493555268747671930923697279690399480501746857825917608323993022396398648205737336204493624060285359455268389160802763426461171262704764369336704988874821898000892148693988241020931055723252").unwrap(); - let sign = RSASignature::new(Value::known(sign_big)); - let sign = config.assign_signature(ctx, sign)?; - let hashed_msg_big = BigUint::from_str("83814198383102558219731078260892729932246618004265700685467928187377105751529").unwrap(); - let hashed_msg_limbs = decompose_biguint::(&hashed_msg_big, 4, 256/4); - let hashed_msg_assigned = hashed_msg_limbs.into_iter().map(|limb| config.gate().load_witness(ctx, Value::known(limb))).collect::>>(); - let is_valid = config.verify_pkcs1v15_signature(ctx, &public_key, &hashed_msg_assigned, &sign)?; - config.gate().assert_is_const(ctx, &is_valid, F::one()); - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - impl_rsa_signature_test_circuit!( - TestBadRSASignatureCircuit, - test_bad_rsa_signature_circuit, - 2048, - 64, - 13, - true, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "rsa signature test using 2048 bits public keys with a uncorrect case", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let e_fix = RSAPubE::Fix(BigUint::from(Self::DEFAULT_E)); - let n_big = BigUint::from_str("24226501697440012621102249466312043787685293040734225606346036389705515508545746221669035424138747582133889500686654172873671086178893587422987328751464627501601101326475761646014534358699943642495332701081302954020983110372109611581202820849485662540890985814355975252780310958088652613376767040069489530039075302709233494829280591680666351811024913107949144932224439129715181798714328219977771472462901856297952813239115577652450722815852332547886777292613005505949100406231716599634852632308325816916535875123863510650526931916871614411907700873376659841257216885666098127478325534982891697988739616416855214839339").unwrap(); - let public_key = RSAPublicKey::new(Value::known(n_big), e_fix); - let public_key = config.assign_public_key(ctx, public_key)?; - let sign_big = BigUint::from_str("18928545496959756512579438348223103860103247450097569223971486743312798156950374943336714741350742176674694049986481729075548718599712271054643150030165230392897481507710187505775911256946250999396358633095137650326818007610162375520522758780751710735664264200260854016867498935206556916247099180950775474524799944404833222133011134000549939512938205188018503377612813102061504146765520561811620128786062447005833886367575841545493555268747671930923697279690399480501746857825917608323993022396398648205737336204493624060285359455268389160802763426461171262704764369336704988874821898000892148693988241020931055723252").unwrap(); - let sign = RSASignature::new(Value::known(sign_big)); - let sign = config.assign_signature(ctx, sign)?; - let hashed_msg_big = BigUint::from_str("83814198383102558219731078260892729932246618004265700685467928187377105751529").unwrap(); - let hashed_msg_limbs = decompose_biguint::(&hashed_msg_big, 4, 256/4); - let hashed_msg_assigned = hashed_msg_limbs.into_iter().map(|limb| config.gate().load_witness(ctx, Value::known(limb))).collect::>>(); - let is_valid = config.verify_pkcs1v15_signature(ctx, &public_key, &hashed_msg_assigned, &sign)?; - config.gate().assert_is_const(ctx, &is_valid, F::one()); - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); - - impl_rsa_signature_test_circuit!( - TestBadRSASignatureCircuit2, - test_bad_rsa_signature_circuit2, - 2048, - 64, - 13, - true, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "rsa signature test using 2048 bits public keys with a uncorrect case", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = config.new_context(region); - let ctx = &mut aux; - let e_fix = RSAPubE::Fix(BigUint::from(Self::DEFAULT_E)); - let n_big = BigUint::from_str("24226501697440012621102249466312043787685293040734225606346036389705515508545746221669035424138747582133889500686654172873671086178893587422987328751464627501601101326475761646014534358699943642495332701081302954020983110372109611581202820849485662540890985814355975252780310958088652613376767040069489530039075302709233494829280591680666351811024913107949144932224439129715181798714328219977771472462901856297952813239115577652450722815852332547886777292613005505949100406231716599634852632308325816916535875123863510650526931916871614411907700873376659841257216885666098127478325534982891697988739616416855214839339").unwrap(); - let public_key = RSAPublicKey::new(Value::known(n_big), e_fix); - let public_key = config.assign_public_key(ctx, public_key)?; - let sign_big = BigUint::from_str("18928545496959756512579438348223103860103247450097569223971486743312798156950374943336714741350742176674694049986481729075548718599712271054643150030165230392897481507710187505775911256946250999396358633095137650326818007610162375520522758780751710735664264200260854016867498935206556916247099180950775474524799944404833222133011134000549939512938205188018503377612813102061504146765520561811620128786062447005833886367575841545493555268747671930923697279690399480501746857825917608323993022396398648205737336204493624060285359455268389160802763426461171262704764369336704988874821898000892148693988241020931055723252").unwrap(); - let sign = RSASignature::new(Value::known(sign_big)); - let sign = config.assign_signature(ctx, sign)?; - let hashed_msg_big = BigUint::from_str("83814198383102558219731078260892729932246618004265700685467928187377105751529").unwrap(); - let hashed_msg_limbs = decompose_biguint::(&hashed_msg_big, 4, 256/4); - let hashed_msg_assigned = hashed_msg_limbs.into_iter().map(|limb| config.gate().load_witness(ctx, Value::known(limb))).collect::>>(); - let is_valid = config.verify_pkcs1v15_signature(ctx, &public_key, &hashed_msg_assigned, &sign)?; - config.gate().assert_is_const(ctx, &is_valid, F::one()); - config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - ); -} +} \ No newline at end of file diff --git a/src/instructions.rs b/src/instructions.rs index a1e9ffb..e0d43b7 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -1,45 +1,41 @@ use crate::{ AssignedBigUint, AssignedRSAPublicKey, AssignedRSASignature, Fresh, RSAPublicKey, RSASignature, }; -use halo2_base::halo2_proofs::{circuit::Region, circuit::Value, plonk::Error}; -use halo2_base::utils::fe_to_bigint; -use halo2_base::ContextParams; -use halo2_base::QuantumCell; +use halo2_base::halo2_proofs::plonk::Error; use halo2_base::{ - gates::{flex_gate::FlexGateConfig, range::RangeConfig, GateInstructions, RangeInstructions}, - utils::{bigint_to_fe, biguint_to_fe, fe_to_biguint, modulus, PrimeField}, + utils::BigPrimeField, AssignedValue, Context, }; /// Instructions for RSA operations. -pub trait RSAInstructions { +pub trait RSAInstructions { /// Assigns a [`AssignedRSAPublicKey`]. - fn assign_public_key<'v>( + fn assign_public_key( &self, - ctx: &mut Context<'v, F>, + ctx: &mut Context, public_key: RSAPublicKey, - ) -> Result, Error>; + ) -> Result, Error>; /// Assigns a [`AssignedRSASignature`]. - fn assign_signature<'v>( + fn assign_signature( &self, - ctx: &mut Context<'v, F>, + ctx: &mut Context, signature: RSASignature, - ) -> Result, Error>; + ) -> Result, Error>; /// Given a base `x`, a RSA public key (e,n), performs the modular power `x^e mod n`. - fn modpow_public_key<'v>( + fn modpow_public_key( &self, - ctx: &mut Context<'v, F>, - x: &AssignedBigUint<'v, F, Fresh>, - public_key: &AssignedRSAPublicKey<'v, F>, - ) -> Result, Error>; + ctx: &mut Context, + x: &AssignedBigUint, + public_key: &AssignedRSAPublicKey, + ) -> Result, Error>; /// Given a RSA public key, a message hashed with SHA256, and a pkcs1v15 signature, verifies the signature with the public key and the hashed messaged. - fn verify_pkcs1v15_signature<'v>( + fn verify_pkcs1v15_signature( &self, - ctx: &mut Context<'v, F>, - public_key: &AssignedRSAPublicKey<'v, F>, - hashed_msg: &[AssignedValue<'v, F>], - signature: &AssignedRSASignature<'v, F>, - ) -> Result, Error>; + ctx: &mut Context, + public_key: &AssignedRSAPublicKey, + hashed_msg: &[AssignedValue], + signature: &AssignedRSASignature, + ) -> Result, Error>; } diff --git a/src/lib.rs b/src/lib.rs index d8f482f..8679595 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,76 +3,52 @@ //! A chip in this library, [`RSAConfig`], defines constraints for verifying the RSA relations, specifically modular power `x^e mod n` and [pkcs1v15 signature](https://www.rfc-editor.org/rfc/rfc3447) verification. //! Its circuit configuration differs depending on whether the exponent parameter `e` of the RSA public key is variable or fixed. //! For example, since `e` is often fixed to `65537` in the case of pkcs1v15 signature verification, defining `e` as a fixed parameter [`RSAPubE::Fix`] can optimize the number of constraints. -//! -//! In addition to [`RSAConfig`], this library also provides a high-level circuit implementation to verify pkcs1v15 signatures, [`RSASignatureVerifier`]. -//! The verification function in [`RSAConfig`] requires as input a hashed message, whereas the function in [`RSASignatureVerifier`] computes a SHA256 hash of the given message and verifies the given signature for that hash. pub mod big_uint; use std::marker::PhantomData; pub use big_uint::*; -use halo2_base::halo2_proofs::{circuit::Value, plonk::Error}; -use halo2_base::QuantumCell; use halo2_base::{ - gates::{flex_gate::FlexGateConfig, range::RangeConfig, GateInstructions, RangeInstructions}, - utils::{bigint_to_fe, biguint_to_fe, fe_to_biguint, modulus, PrimeField}, - AssignedValue, Context, -}; -use halo2_ecc::bigint::{ - big_is_equal, big_is_zero, big_less_than, carry_mod, mul_no_carry, negative, select, sub, - CRTInteger, FixedCRTInteger, FixedOverflowInteger, OverflowInteger, + utils::BigPrimeField, + AssignedValue, }; -use num_bigint::{BigInt, BigUint, Sign}; -use num_traits::{One, Signed, Zero}; +use num_bigint::BigUint; mod chip; mod instructions; pub use chip::*; pub use instructions::*; -#[cfg(feature = "sha256")] -mod macros; -#[cfg(feature = "sha256")] -pub use halo2_dynamic_sha256; -#[cfg(feature = "sha256")] -use halo2_dynamic_sha256::{AssignedHashResult, Sha256DynamicConfig}; -#[cfg(feature = "sha256")] -pub use macros::*; - -#[cfg(target_arch = "wasm32")] -mod wasm; -#[cfg(target_arch = "wasm32")] -pub use wasm::*; /// A parameter `e` in the RSA public key that is about to be assigned. #[derive(Clone, Debug)] pub enum RSAPubE { /// A variable parameter `e`. - Var(Value), + Var(BigUint), /// A fixed parameter `e`. Fix(BigUint), } /// A parameter `e` in the assigned RSA public key. #[derive(Clone, Debug)] -pub enum AssignedRSAPubE<'v, F: PrimeField> { +pub enum AssignedRSAPubE { /// A variable parameter `e`. - Var(AssignedValue<'v, F>), + Var(AssignedValue), /// A fixed parameter `e`. Fix(BigUint), } /// RSA public key that is about to be assigned. #[derive(Clone, Debug)] -pub struct RSAPublicKey { +pub struct RSAPublicKey { /// a modulus parameter - pub n: Value, + pub n: BigUint, /// an exponent parameter pub e: RSAPubE, _f: PhantomData, } -impl RSAPublicKey { +impl RSAPublicKey { /// Creates new [`RSAPublicKey`] from `n` and `e`. /// /// # Arguments @@ -81,17 +57,7 @@ impl RSAPublicKey { /// /// # Return values /// Returns new [`RSAPublicKey`]. - pub fn new(n: Value, e: RSAPubE) -> Self { - Self { - n, - e, - _f: PhantomData, - } - } - - pub fn without_witness(fix_e: BigUint) -> Self { - let n = Value::unknown(); - let e = RSAPubE::Fix(fix_e); + pub fn new(n: BigUint, e: RSAPubE) -> Self { Self { n, e, @@ -102,14 +68,14 @@ impl RSAPublicKey { /// An assigned RSA public key. #[derive(Clone, Debug)] -pub struct AssignedRSAPublicKey<'v, F: PrimeField> { +pub struct AssignedRSAPublicKey { /// a modulus parameter - pub n: AssignedBigUint<'v, F, Fresh>, + pub n: AssignedBigUint, /// an exponent parameter - pub e: AssignedRSAPubE<'v, F>, + pub e: AssignedRSAPubE, } -impl<'v, F: PrimeField> AssignedRSAPublicKey<'v, F> { +impl AssignedRSAPublicKey { /// Creates new [`AssignedRSAPublicKey`] from assigned `n` and `e`. /// /// # Arguments @@ -118,20 +84,19 @@ impl<'v, F: PrimeField> AssignedRSAPublicKey<'v, F> { /// /// # Return values /// Returns new [`AssignedRSAPublicKey`]. - pub fn new(n: AssignedBigUint<'v, F, Fresh>, e: AssignedRSAPubE<'v, F>) -> Self { + pub fn new(n: AssignedBigUint, e: AssignedRSAPubE) -> Self { Self { n, e } } } /// RSA signature that is about to be assigned. #[derive(Clone, Debug)] -pub struct RSASignature { - /// an integer of the signature. - pub c: Value, +pub struct RSASignature { + c: BigUint, _f: PhantomData, } -impl RSASignature { +impl RSASignature { /// Creates new [`RSASignature`] from its integer. /// /// # Arguments @@ -139,24 +104,23 @@ impl RSASignature { /// /// # Return values /// Returns new [`RSASignature`]. - pub fn new(c: Value) -> Self { + pub fn new(c: BigUint) -> Self { Self { c, _f: PhantomData } } - pub fn without_witness() -> Self { - let c = Value::unknown(); - Self { c, _f: PhantomData } - } + // pub fn without_witness() -> Self { + // let c = Value::unknown(); + // Self { c, _f: PhantomData } + // } } /// An assigned RSA signature. #[derive(Clone, Debug)] -pub struct AssignedRSASignature<'v, F: PrimeField> { - /// an integer of the signature. - pub c: AssignedBigUint<'v, F, Fresh>, +pub struct AssignedRSASignature { + c: AssignedBigUint, } -impl<'v, F: PrimeField> AssignedRSASignature<'v, F> { +impl AssignedRSASignature { /// Creates new [`AssignedRSASignature`] from its assigned integer. /// /// # Arguments @@ -164,469 +128,7 @@ impl<'v, F: PrimeField> AssignedRSASignature<'v, F> { /// /// # Return values /// Returns new [`AssignedRSASignature`]. - pub fn new(c: AssignedBigUint<'v, F, Fresh>) -> Self { + pub fn new(c: AssignedBigUint) -> Self { Self { c } } -} - -#[cfg(feature = "sha256")] -/// A circuit implementation to verify pkcs1v15 signatures. -#[derive(Clone, Debug)] -pub struct RSASignatureVerifier { - rsa_config: RSAConfig, - sha256_config: Sha256DynamicConfig, -} - -#[cfg(feature = "sha256")] -impl RSASignatureVerifier { - /// Creates new [`RSASignatureVerifier`] from [`RSAChip`] and [`Sha256BitChip`]. - /// - /// # Arguments - /// * rsa_config - a [`RSAConfig`]. - /// * sha256_config - a [`Sha256DynamicConfig`] - /// - /// # Return values - /// Returns new [`RSASignatureVerifier`]. - pub fn new(rsa_config: RSAConfig, sha256_config: Sha256DynamicConfig) -> Self { - Self { - rsa_config, - sha256_config, - } - } - - /// Given a RSA public key, signed message bytes, and a pkcs1v15 signature, verifies the signature with SHA256 hash function. - /// - /// # Arguments - /// * layouter - a layouter of the constraints system. - /// * public_key - an assigned public key used for the verification. - /// * msg - signed message bytes. - /// * signature - a pkcs1v15 signature to be verified. - /// - /// # Return values - /// Returns the assigned bit as `AssignedValue`. - /// If `signature` is valid for `public_key` and `msg`, the bit is equivalent to one. - /// Otherwise, the bit is equivalent to zero. - pub fn verify_pkcs1v15_signature<'a, 'b: 'a>( - &'a mut self, - // mut layouter: impl Layouter, - ctx: &mut Context<'b, F>, - public_key: &AssignedRSAPublicKey<'b, F>, - msg: &'a [u8], - signature: &AssignedRSASignature<'b, F>, - ) -> Result<(AssignedValue<'b, F>, Vec>), Error> { - let sha256 = &mut self.sha256_config; - let rsa = self.rsa_config.clone(); - let biguint = &rsa.biguint_config(); - let result = sha256.digest(ctx, msg, None)?; - let mut hashed_bytes = result.output_bytes; - hashed_bytes.reverse(); - let bytes_bits = hashed_bytes.len() * 8; - let limb_bits = biguint.limb_bits(); - let limb_bytes = limb_bits / 8; - let mut hashed_u64s = vec![]; - let bases = (0..limb_bytes) - .map(|i| F::from((1u64 << (8 * i)) as u64)) - .map(QuantumCell::Constant) - .collect::>>(); - for i in 0..(bytes_bits / limb_bits) { - let left = hashed_bytes[limb_bytes * i..limb_bytes * (i + 1)] - .iter() - .map(QuantumCell::Existing) - .collect::>>(); - let sum = biguint.gate().inner_product(ctx, left, bases.clone()); - hashed_u64s.push(sum); - } - let is_sign_valid = - rsa.verify_pkcs1v15_signature(ctx, public_key, &hashed_u64s, signature)?; - - hashed_bytes.reverse(); - Ok((is_sign_valid, hashed_bytes)) - } -} - -#[cfg(feature = "sha256")] -#[cfg(test)] -mod test { - use super::*; - use crate::big_uint::decompose_biguint; - use halo2_base::halo2_proofs::{ - circuit::{Cell, Layouter, SimpleFloorPlanner}, - dev::MockProver, - halo2curves::bn256::Fr, - plonk::{Circuit, Column, ConstraintSystem, Instance}, - }; - use halo2_base::{gates::range::RangeStrategy::Vertical, ContextParams, SKIP_FIRST_PASS}; - use halo2_dynamic_sha256::Sha256DynamicConfig; - - use num_bigint::RandomBits; - use num_traits::FromPrimitive; - use rand::{thread_rng, Rng}; - use rsa::{Hash, PaddingScheme, PublicKey, PublicKeyParts, RsaPrivateKey, RsaPublicKey}; - use sha2::{Digest, Sha256}; - - macro_rules! impl_rsa_signature_test_circuit { - ($config_name:ident, $circuit_name:ident, $test_fn_name:ident, $bits_len:expr, $msg_len:expr, $num_advice:expr, $num_lookup_advice:expr, $lookup_bits:expr, $k:expr, $should_be_error:expr, $( $synth:tt )*) => { - #[derive(Debug,Clone)] - struct $config_name { - rsa_config: RSAConfig, - sha256_config: Sha256DynamicConfig, - n_instance: Column, - hash_instance: Column - } - - struct $circuit_name { - private_key: RsaPrivateKey, - public_key: RsaPublicKey, - msg: Vec, - _f: PhantomData - } - - impl $circuit_name { - const BITS_LEN:usize = $bits_len; - const MSG_LEN:usize = $msg_len; - const EXP_LIMB_BITS:usize = 5; - const DEFAULT_E: u128 = 65537; - const NUM_ADVICE:usize = $num_advice; - const NUM_FIXED:usize = 1; - const NUM_LOOKUP_ADVICE:usize = $num_lookup_advice; - const LOOKUP_BITS:usize = $lookup_bits; - const SHA256_LOOKUP_BITS:usize = 8; - const SHA256_LOOKUP_ADVICE:usize = 8; - } - - impl Circuit for $circuit_name { - type Config = $config_name; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - unimplemented!(); - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let range_config = RangeConfig::configure(meta,Vertical, &[Self::NUM_ADVICE], &[Self::NUM_LOOKUP_ADVICE], Self::NUM_FIXED, Self::LOOKUP_BITS, 0, $k); - let bigint_config = BigUintConfig::construct(range_config.clone(), 64); - let rsa_config = RSAConfig::construct(bigint_config, Self::BITS_LEN, Self::EXP_LIMB_BITS); - let sha256_config = Sha256DynamicConfig::configure(meta,vec![Self::MSG_LEN], range_config,Self::SHA256_LOOKUP_BITS,Self::SHA256_LOOKUP_ADVICE,true); - let n_instance = meta.instance_column(); - let hash_instance = meta.instance_column(); - meta.enable_equality(n_instance); - meta.enable_equality(hash_instance); - Self::Config { - rsa_config, - sha256_config, - n_instance, - hash_instance - } - } - - $( $synth )* - - } - - #[test] - fn $test_fn_name() { - fn run() { - let mut rng = thread_rng(); - let private_key = RsaPrivateKey::new(&mut rng, $circuit_name::::BITS_LEN).expect("failed to generate a key"); - let public_key = RsaPublicKey::from(&private_key); - let n = BigUint::from_radix_le(&public_key.n().to_radix_le(16),16).unwrap(); - let mut msg:[u8;128] = [0;128]; - for i in 0..128 { - msg[i] = rng.gen(); - } - let hashed_msg = Sha256::digest(&msg); - let circuit = $circuit_name:: { - private_key, - public_key, - msg: msg.to_vec(), - _f: PhantomData - }; - let num_limbs = $bits_len / 64; - let limb_bits = 64; - let n_fes = decompose_biguint::(&n, num_limbs, limb_bits); - let hash_fes = hashed_msg.iter().map(|byte| F::from(*byte as u64)).collect::>(); - let public_inputs = vec![n_fes,hash_fes]; - let k = $k; - let prover = match MockProver::run(k, &circuit, public_inputs) { - Ok(prover) => prover, - Err(e) => panic!("{:#?}", e) - }; - if $should_be_error { - assert!(prover.verify().is_err()); - } else { - prover.verify().unwrap(); - } - } - run::(); - } - }; - } - - impl_rsa_signature_test_circuit!( - TestRSASignatureWithHashConfig1, - TestRSASignatureWithHashCircuit1, - test_rsa_signature_with_hash_circuit1, - 2048, - 1024, - 80, - 16, - 12, - 15, - false, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let biguint_config = config.rsa_config.biguint_config(); - config.sha256_config.load(&mut layouter)?; - biguint_config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - let (public_key_cells, hashed_msg_cells) = layouter.assign_region( - || "random rsa modpow test with 2048 bits public keys", - |region| { - if first_pass { - first_pass = false; - return Ok((vec![], vec![])); - } - - let mut aux = biguint_config.new_context(region); - let ctx = &mut aux; - let hashed_msg = Sha256::digest(&self.msg); - let padding = PaddingScheme::PKCS1v15Sign { - hash: Some(Hash::SHA2_256), - }; - let mut sign = self - .private_key - .sign(padding, &hashed_msg) - .expect("fail to sign a hashed message."); - sign.reverse(); - let sign_big = BigUint::from_bytes_le(&sign); - let sign = config - .rsa_config - .assign_signature(ctx, RSASignature::new(Value::known(sign_big)))?; - let n_big = - BigUint::from_radix_le(&self.public_key.n().clone().to_radix_le(16), 16) - .unwrap(); - let e_fix = RSAPubE::Fix(BigUint::from(Self::DEFAULT_E)); - let public_key = config - .rsa_config - .assign_public_key(ctx, RSAPublicKey::new(Value::known(n_big), e_fix))?; - let mut verifier = RSASignatureVerifier::new( - config.rsa_config.clone(), - config.sha256_config.clone(), - ); - let (is_valid, hashed_msg) = - verifier.verify_pkcs1v15_signature(ctx, &public_key, &self.msg, &sign)?; - biguint_config - .gate() - .assert_is_const(ctx, &is_valid, F::one()); - biguint_config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - let public_key_cells = public_key - .n - .limbs() - .into_iter() - .map(|v| v.cell()) - .collect::>(); - let hashed_msg_cells = hashed_msg - .into_iter() - .map(|v| v.cell()) - .collect::>(); - Ok((public_key_cells, hashed_msg_cells)) - }, - )?; - for (i, cell) in public_key_cells.into_iter().enumerate() { - layouter.constrain_instance(cell, config.n_instance, i)?; - } - for (i, cell) in hashed_msg_cells.into_iter().enumerate() { - layouter.constrain_instance(cell, config.hash_instance, i)?; - } - Ok(()) - } - ); - - impl_rsa_signature_test_circuit!( - TestRSASignatureWithHashConfig2, - TestRSASignatureWithHashCircuit2, - test_rsa_signature_with_hash_circuit2, - 2048, - 2048, - 100, - 16, - 12, - 15, - false, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let biguint_config = config.rsa_config.biguint_config(); - config.sha256_config.load(&mut layouter)?; - biguint_config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - let (public_key_cells, hashed_msg_cells) = layouter.assign_region( - || "random rsa modpow test with 2048 bits public keys", - |region| { - if first_pass { - first_pass = false; - return Ok((vec![], vec![])); - } - - let mut aux = biguint_config.new_context(region); - let ctx = &mut aux; - let hashed_msg = Sha256::digest(&self.msg); - let padding = PaddingScheme::PKCS1v15Sign { - hash: Some(Hash::SHA2_256), - }; - let mut sign = self - .private_key - .sign(padding, &hashed_msg) - .expect("fail to sign a hashed message."); - sign.reverse(); - let sign_big = BigUint::from_bytes_le(&sign); - let sign = config - .rsa_config - .assign_signature(ctx, RSASignature::new(Value::known(sign_big)))?; - let n_big = - BigUint::from_radix_le(&self.public_key.n().clone().to_radix_le(16), 16) - .unwrap(); - let e_fix = RSAPubE::Fix(BigUint::from(Self::DEFAULT_E)); - let public_key = config - .rsa_config - .assign_public_key(ctx, RSAPublicKey::new(Value::known(n_big), e_fix))?; - let mut verifier = RSASignatureVerifier::new( - config.rsa_config.clone(), - config.sha256_config.clone(), - ); - let (is_valid, hashed_msg) = - verifier.verify_pkcs1v15_signature(ctx, &public_key, &self.msg, &sign)?; - biguint_config - .gate() - .assert_is_const(ctx, &is_valid, F::one()); - biguint_config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - let public_key_cells = public_key - .n - .limbs() - .into_iter() - .map(|v| v.cell()) - .collect::>(); - let hashed_msg_cells = hashed_msg - .into_iter() - .map(|v| v.cell()) - .collect::>(); - Ok((public_key_cells, hashed_msg_cells)) - }, - )?; - for (i, cell) in public_key_cells.into_iter().enumerate() { - layouter.constrain_instance(cell, config.n_instance, i)?; - } - for (i, cell) in hashed_msg_cells.into_iter().enumerate() { - layouter.constrain_instance(cell, config.hash_instance, i)?; - } - Ok(()) - } - ); - - impl_rsa_signature_test_circuit!( - TestBadRSASignatureWithHashConfig1, - TestBadRSASignatureWithHashCircuit, - test_bad_rsa_signature_with_hash_circuit1, - 2048, - 1024, - 80, - 16, - 12, - 15, - true, - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let biguint_config = config.rsa_config.biguint_config(); - config.sha256_config.load(&mut layouter)?; - biguint_config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - let (public_key_cells, hashed_msg_cells) = layouter.assign_region( - || "random rsa modpow test with 2048 bits public keys", - |region| { - if first_pass { - first_pass = false; - return Ok((vec![], vec![])); - } - - let mut aux = biguint_config.new_context(region); - let ctx = &mut aux; - // let hashed_msg = Sha256::digest(&self.msg); - let padding = PaddingScheme::PKCS1v15Sign { - hash: Some(Hash::SHA2_256), - }; - let invalid_msg = [0; 32]; - let mut sign = self - .private_key - .sign(padding, &invalid_msg) - .expect("fail to sign a hashed message."); - sign.reverse(); - let sign_big = BigUint::from_bytes_le(&sign); - let sign = config - .rsa_config - .assign_signature(ctx, RSASignature::new(Value::known(sign_big)))?; - let n_big = - BigUint::from_radix_le(&self.public_key.n().clone().to_radix_le(16), 16) - .unwrap(); - let e_fix = RSAPubE::Fix(BigUint::from(Self::DEFAULT_E)); - let public_key = config - .rsa_config - .assign_public_key(ctx, RSAPublicKey::new(Value::known(n_big), e_fix))?; - let mut verifier = RSASignatureVerifier::new( - config.rsa_config.clone(), - config.sha256_config.clone(), - ); - let (is_valid, hashed_msg) = - verifier.verify_pkcs1v15_signature(ctx, &public_key, &self.msg, &sign)?; - biguint_config - .gate() - .assert_is_const(ctx, &is_valid, F::one()); - biguint_config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - let public_key_cells = public_key - .n - .limbs() - .into_iter() - .map(|v| v.cell()) - .collect::>(); - let hashed_msg_cells = hashed_msg - .into_iter() - .map(|v| v.cell()) - .collect::>(); - Ok((public_key_cells, hashed_msg_cells)) - }, - )?; - for (i, cell) in public_key_cells.into_iter().enumerate() { - layouter.constrain_instance(cell, config.n_instance, i)?; - } - for (i, cell) in hashed_msg_cells.into_iter().enumerate() { - layouter.constrain_instance(cell, config.hash_instance, i)?; - } - Ok(()) - } - ); -} +} \ No newline at end of file diff --git a/src/macros.rs b/src/macros.rs deleted file mode 100644 index 12b0a73..0000000 --- a/src/macros.rs +++ /dev/null @@ -1,319 +0,0 @@ -use crate::{ - AssignedBigUint, AssignedRSAPubE, AssignedRSAPublicKey, AssignedRSASignature, BigUintConfig, - BigUintInstructions, Fresh, RSAConfig, RSAInstructions, RSAPubE, RSAPublicKey, RSASignature, - RSASignatureVerifier, -}; -use halo2_base::halo2_proofs::{ - circuit::{Cell, Layouter, Region, SimpleFloorPlanner, Value}, - dev::MockProver, - halo2curves::bn256::{Bn256, Fr, G1Affine}, - plonk::{create_proof, keygen_pk, keygen_vk, Error}, - plonk::{Circuit, Column, ConstraintSystem, Instance}, -}; -use halo2_base::utils::fe_to_bigint; -use halo2_base::ContextParams; -use halo2_base::QuantumCell; -use halo2_base::{gates::range::RangeStrategy::Vertical, SKIP_FIRST_PASS}; -use halo2_base::{ - gates::{flex_gate::FlexGateConfig, range::RangeConfig, GateInstructions, RangeInstructions}, - utils::{bigint_to_fe, biguint_to_fe, fe_to_biguint, modulus, PrimeField}, - AssignedValue, Context, -}; -use halo2_dynamic_sha256::Sha256DynamicConfig; -use halo2_ecc::bigint::{ - big_is_equal, big_is_zero, big_less_than, carry_mod, mul_no_carry, negative, select, sub, - CRTInteger, FixedCRTInteger, FixedOverflowInteger, OverflowInteger, -}; -use num_bigint::{BigInt, BigUint, Sign}; -use num_traits::{One, Signed, Zero}; -use rand::rngs::OsRng; -use std::marker::PhantomData; - -use halo2_base::halo2_proofs::poly::kzg::strategy::SingleStrategy; -use rand::{thread_rng, Rng}; -use rsa::{Hash, PaddingScheme, PublicKeyParts, RsaPrivateKey, RsaPublicKey}; -use sha2::{Digest, Sha256}; - -#[macro_export] -macro_rules! impl_pkcs1v15_basic_circuit { - ($config_name:ident, $circuit_name:ident, $setup_fn_name:ident, $prove_fn_name:ident, $bits_len:expr, $msg_len:expr, $num_flex_advice:expr, $num_range_advice:expr, $sha256_lookup_bits:expr, $sha256_lookup_advice:expr, $k:expr, $sha2_chip_enabled:expr) => { - #[derive(Debug, Clone)] - struct $config_name { - rsa_config: RSAConfig, - sha256_config: Option>, - } - - struct $circuit_name { - signature: RSASignature, - public_key: RSAPublicKey, - msg: Vec, - _f: PhantomData, - } - - impl $circuit_name { - const BITS_LEN: usize = $bits_len; - const MSG_LEN: usize = $msg_len; - const LIMB_WIDTH: usize = 64; - const EXP_LIMB_BITS: usize = 5; - const DEFAULT_E: u128 = 65537; - const NUM_ADVICE: usize = $num_flex_advice; - const NUM_FIXED: usize = 1; - const NUM_LOOKUP_ADVICE: usize = $num_range_advice; - const LOOKUP_BITS: usize = $k - 1; - const SHA256_LOOKUP_BITS: usize = $sha256_lookup_bits; - const SHA256_LOOKUP_ADVICE: usize = $sha256_lookup_advice; - } - - impl Default for $circuit_name { - fn default() -> Self { - let num_limbs = Self::BITS_LEN / 64; - let signature = RSASignature::without_witness(); - let public_key = RSAPublicKey::without_witness(BigUint::from(Self::DEFAULT_E)); - let msg = if $sha2_chip_enabled { - vec![0; $msg_len - 9] - } else { - vec![0; 32] - }; - Self { - signature, - public_key, - msg, - _f: PhantomData, - } - } - } - - impl Circuit for $circuit_name { - type Config = $config_name; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - unimplemented!(); - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let range_config = RangeConfig::configure( - meta, - Vertical, - &[Self::NUM_ADVICE], - &[Self::NUM_LOOKUP_ADVICE], - Self::NUM_FIXED, - Self::LOOKUP_BITS, - 0, - $k, - ); - let bigint_config = BigUintConfig::construct(range_config.clone(), 64); - let rsa_config = - RSAConfig::construct(bigint_config, Self::BITS_LEN, Self::EXP_LIMB_BITS); - let sha256_config = if $sha2_chip_enabled { - let sha256_config = Sha256DynamicConfig::configure( - meta, - vec![Self::MSG_LEN], - range_config, - Self::SHA256_LOOKUP_BITS, - Self::SHA256_LOOKUP_ADVICE, - true, - ); - Some(sha256_config) - } else { - None - }; - - Self::Config { - rsa_config, - sha256_config, - } - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let biguint_config = config.rsa_config.biguint_config(); - let limb_bits = 64; - let num_limbs = Self::BITS_LEN / limb_bits; - if let Some(sha256_config) = config.sha256_config.as_ref() { - sha256_config.load(&mut layouter)?; - } - biguint_config.range().load_lookup_table(&mut layouter)?; - let mut first_pass = SKIP_FIRST_PASS; - layouter.assign_region( - || "pkcs1v15 signature verification", - |region| { - if first_pass { - first_pass = false; - return Ok(()); - } - - let mut aux = biguint_config.new_context(region); - let ctx = &mut aux; - let hashed_msg = Sha256::digest(&self.msg); - let padding = PaddingScheme::PKCS1v15Sign { - hash: Some(Hash::SHA2_256), - }; - let sign = config - .rsa_config - .assign_signature(ctx, self.signature.clone())?; - let public_key = config - .rsa_config - .assign_public_key(ctx, self.public_key.clone())?; - if $sha2_chip_enabled { - let mut verifier = RSASignatureVerifier::new( - config.rsa_config.clone(), - config.sha256_config.clone().unwrap(), - ); - let (is_valid, hashed_msg) = verifier.verify_pkcs1v15_signature( - ctx, - &public_key, - &self.msg, - &sign, - )?; - biguint_config - .gate() - .assert_is_const(ctx, &is_valid, F::one()); - } else { - let gate = config.rsa_config.gate(); - let mut msg = self.msg.clone(); - msg.reverse(); - let hash_u64s = msg.chunks(limb_bits / 8).map(|limbs| { - let mut sum = 0u64; - for (i, limb) in limbs.into_iter().enumerate() { - sum += (*limb as u64) << (8 * i); - } - F::from(sum) - }); - let assigned_msg = hash_u64s - .map(|v| gate.load_witness(ctx, Value::known(v))) - .collect::>>(); - let is_valid = config.rsa_config.verify_pkcs1v15_signature( - ctx, - &public_key, - &assigned_msg, - &sign, - )?; - config - .rsa_config - .gate() - .assert_is_const(ctx, &is_valid, F::one()); - } - biguint_config.range().finalize(ctx); - { - println!("total advice cells: {}", ctx.total_advice); - let const_rows = ctx.total_fixed + 1; - println!("maximum rows used by a fixed column: {const_rows}"); - println!("lookup cells used: {}", ctx.cells_to_lookup.len()); - } - Ok(()) - }, - )?; - Ok(()) - } - } - - fn $setup_fn_name() -> ( - ParamsKZG, - VerifyingKey, - ProvingKey, - ) { - let circuit = $circuit_name::::default(); - let k = $k; - let params = ParamsKZG::::setup(k, OsRng); - let vk = keygen_vk(¶ms, &circuit).unwrap(); - let pk = keygen_pk(¶ms, vk.clone(), &circuit).unwrap(); - (params, vk, pk) - } - - fn $prove_fn_name( - params: &ParamsKZG, - vk: &VerifyingKey, - pk: &ProvingKey, - ) { - let limb_bits = 64; - let num_limbs = $bits_len / 64; - // 1. Uniformly sample a RSA key pair. - let mut rng = thread_rng(); - let private_key = RsaPrivateKey::new(&mut rng, $circuit_name::::BITS_LEN) - .expect("failed to generate a key"); - let public_key = RsaPublicKey::from(&private_key); - // 2. Uniformly sample a message. - // 3. Compute the SHA256 hash of `msg`. - let (msg, hashed_msg) = if $sha2_chip_enabled { - let mut msg: [u8; $msg_len - 9] = [0; $msg_len - 9]; - for i in 0..($msg_len - 9) { - msg[i] = rng.gen(); - } - let hashed_msg = Sha256::digest(&msg).to_vec(); - (msg.to_vec(), hashed_msg) - } else { - let mut msg: [u8; 32] = [0; 32]; - for i in 0..32 { - msg[i] = rng.gen(); - } - let hashed_msg = Sha256::digest(&msg).to_vec(); - (hashed_msg.clone(), hashed_msg) - }; - - // 4. Generate a pkcs1v15 signature. - let padding = PaddingScheme::PKCS1v15Sign { - hash: Some(Hash::SHA2_256), - }; - let mut sign = private_key - .sign(padding, &hashed_msg) - .expect("fail to sign a hashed message."); - sign.reverse(); - let sign_big = BigUint::from_bytes_le(&sign); - let signature = RSASignature::new(Value::known(sign_big)); - - // 5. Construct `RSAPublicKey` from `n` of `public_key` and fixed `e`. - let n_big = - BigUint::from_radix_le(&public_key.n().clone().to_radix_le(16), 16).unwrap(); - let e_fix = RSAPubE::Fix(BigUint::from($circuit_name::::DEFAULT_E)); - let public_key = RSAPublicKey::new(Value::known(n_big), e_fix); - - // 6. Create our circuit! - let circuit = $circuit_name:: { - signature, - public_key, - msg, - _f: PhantomData, - }; - - let prover = match MockProver::run($k, &circuit, vec![]) { - Ok(prover) => prover, - Err(e) => panic!("{:#?}", e), - }; - prover.verify().unwrap(); - - // 7. Generate a proof. - let proof = { - let mut transcript = Blake2bWrite::<_, G1Affine, Challenge255<_>>::init(vec![]); - create_proof::, ProverGWC<_>, _, _, _, _>( - params, - pk, - &[circuit], - &[&[]], - OsRng, - &mut transcript, - ) - .unwrap(); - transcript.finalize() - }; - // // 9. Verify the proof. - { - let mut transcript = Blake2bRead::<_, _, Challenge255<_>>::init(&proof[..]); - let verifier_params = params.verifier_params(); - let strategy = SingleStrategy::new(&verifier_params); - // let strategy = AccumulatorStrategy::new(verifier_params); - verify_proof::<_, VerifierGWC<_>, _, _, _>( - verifier_params, - vk, - strategy, - &[&[]], - &mut transcript, - ) - .unwrap(); - } - } - }; -} diff --git a/src/wasm.rs b/src/wasm.rs deleted file mode 100644 index 6c87ecb..0000000 --- a/src/wasm.rs +++ /dev/null @@ -1,457 +0,0 @@ -use crate::{ - impl_pkcs1v15_basic_circuit, AssignedBigUint, AssignedRSAPubE, AssignedRSAPublicKey, - AssignedRSASignature, BigUintConfig, BigUintInstructions, Fresh, RSAConfig, RSAInstructions, - RSAPubE, RSAPublicKey, RSASignature, RSASignatureVerifier, -}; -use halo2_base::halo2_proofs::{ - circuit::{Cell, Layouter, Region, SimpleFloorPlanner, Value}, - dev::MockProver, - halo2curves::bn256::{Bn256, Fr, G1Affine}, - plonk::{ - create_proof, keygen_pk, keygen_vk, Circuit, Column, ConstraintSystem, Instance, - ProvingKey, VerifyingKey, - }, - plonk::{verify_proof, Error}, - poly::{ - commitment::{Params, ParamsProver}, - kzg::{ - commitment::{KZGCommitmentScheme, ParamsKZG}, - multiopen::{ProverGWC, VerifierGWC}, - strategy::SingleStrategy, - }, - Rotation, VerificationStrategy, - }, - transcript::{ - Blake2bRead, Blake2bWrite, Challenge255, TranscriptReadBuffer, TranscriptWriterBuffer, - }, - SerdeFormat, -}; -use halo2_base::utils::fe_to_bigint; -use halo2_base::ContextParams; -use halo2_base::QuantumCell; -use halo2_base::{gates::range::RangeStrategy::Vertical, SKIP_FIRST_PASS}; -use halo2_base::{ - gates::{flex_gate::FlexGateConfig, range::RangeConfig, GateInstructions, RangeInstructions}, - utils::{bigint_to_fe, biguint_to_fe, fe_to_biguint, modulus, PrimeField}, - AssignedValue, Context, -}; -use halo2_dynamic_sha256::{Field, Sha256CompressionConfig, Sha256DynamicConfig}; -use halo2_ecc::bigint::{ - big_is_equal, big_is_zero, big_less_than, carry_mod, mul_no_carry, negative, select, sub, - CRTInteger, FixedCRTInteger, FixedOverflowInteger, OverflowInteger, -}; -use num_bigint::{BigInt, BigUint, Sign}; -use num_traits::{One, Signed, Zero}; -use rand::rngs::OsRng; -use std::marker::PhantomData; - -use rand::{thread_rng, Rng}; -use rsa::{Hash, PaddingScheme, PublicKeyParts, RsaPrivateKey, RsaPublicKey}; -use sha2::{Digest, Sha256}; - -use js_sys::{Array, JsString, Uint8Array}; -use rayon::prelude::*; -use serde::{Deserialize, Serialize}; -use serde_wasm_bindgen::*; -use std::fs::File; -use std::io::{BufReader, BufWriter, Write}; -use std::time::{Duration, SystemTime, UNIX_EPOCH}; -use wasm_bindgen::prelude::*; -pub use wasm_bindgen_rayon::init_thread_pool; -use web_sys::console::*; - -impl_pkcs1v15_basic_circuit!( - Pkcs1v15_1024_64EnabledBenchConfig, - Pkcs1v15_1024_64EnabledBenchCircuit, - setup_pkcs1v15_1024_64_enabled, - prove_pkcs1v15_1024_64_enabled, - 1024, - 64, - 1, - 13, - true -); - -impl_pkcs1v15_basic_circuit!( - Pkcs1v15_1024_128EnabledBenchConfig, - Pkcs1v15_1024_128EnabledBenchCircuit, - setup_pkcs1v15_1024_128_enabled, - prove_pkcs1v15_1024_128_enabled, - 1024, - 128, - 1, - 13, - true -); - -impl_pkcs1v15_basic_circuit!( - Pkcs1v15_1024_1024EnabledBenchConfig, - Pkcs1v15_1024_1024EnabledBenchCircuit, - setup_pkcs1v15_1024_1024_enabled, - prove_pkcs1v15_1024_1024_enabled, - 1024, - 1024, - 1, - 13, - true -); - -impl_pkcs1v15_basic_circuit!( - Pkcs1v15_2048_64EnabledBenchConfig, - Pkcs1v15_2048_64EnabledBenchCircuit, - setup_pkcs1v15_2048_64_enabled, - prove_pkcs1v15_2048_64_enabled, - 2048, - 64, - 1, - 13, - true -); - -impl_pkcs1v15_basic_circuit!( - Pkcs1v15_2048_128EnabledBenchConfig, - Pkcs1v15_2048_128EnabledBenchCircuit, - setup_pkcs1v15_2048_128_enabled, - prove_pkcs1v15_2048_128_enabled, - 2048, - 128, - 1, - 13, - true -); - -impl_pkcs1v15_basic_circuit!( - Pkcs1v15_2048_1024EnabledBenchConfig, - Pkcs1v15_2048_1024EnabledBenchCircuit, - setup_pkcs1v15_2048_1024_enabled, - prove_pkcs1v15_2048_1024_enabled, - 2048, - 1024, - 1, - 13, - true -); - -impl_pkcs1v15_basic_circuit!( - Pkcs1v15_2048_1024DisabledBenchConfig, - Pkcs1v15_2048_1024DisabledBenchCircuit, - setup_pkcs1v15_2048_1024_disabled, - prove_pkcs1v15_2048_1024_disabled, - 2048, - 1024, - 1, - 13, - false -); - -#[wasm_bindgen] -pub fn sample_rsa_private_key(bits_len: usize) -> JsValue { - let mut rng = thread_rng(); - let private_key = RsaPrivateKey::new(&mut rng, bits_len).expect("failed to generate a key"); - serde_wasm_bindgen::to_value(&private_key).unwrap() -} - -#[wasm_bindgen] -pub fn generate_rsa_public_key(private_key: JsValue) -> JsValue { - let private_key: RsaPrivateKey = serde_wasm_bindgen::from_value(private_key).unwrap(); - let public_key = RsaPublicKey::from(private_key); - serde_wasm_bindgen::to_value(&public_key).unwrap() -} - -#[wasm_bindgen] -pub fn sign(private_key: JsValue, msg: JsValue) -> JsValue { - let private_key: RsaPrivateKey = serde_wasm_bindgen::from_value(private_key).unwrap(); - //let msg: Vec = serde_wasm_bindgen::from_value(msg).unwrap(); - let msg: Vec = Uint8Array::new(&msg).to_vec(); - let hashed_msg = Sha256::digest(&msg).to_vec(); - - let padding = PaddingScheme::PKCS1v15Sign { - hash: Some(Hash::SHA2_256), - }; - let sign = private_key - .sign(padding, &hashed_msg) - .expect("fail to sign a hashed message."); - serde_wasm_bindgen::to_value(&sign).unwrap() -} - -#[wasm_bindgen] -pub fn sha256_msg(msg: JsValue) -> JsValue { - //let msg: Vec = serde_wasm_bindgen::from_value(msg).unwrap(); - let msg: Vec = Uint8Array::new(&msg).to_vec(); - let hashed_msg = Sha256::digest(&msg).to_vec(); - serde_wasm_bindgen::to_value(&hashed_msg).unwrap() -} - -#[macro_export] -macro_rules! impl_pkcs1v15_wasm_functions { - ($circuit_name:ident, $prove_fn_name:ident, $verify_fn_name:ident, $msg_len:expr, $k:expr, $sha2_chip_enabled:expr) => { - #[wasm_bindgen] - pub fn $prove_fn_name( - params: JsValue, - pk: JsValue, - public_key: JsValue, - msg: JsValue, - signature: JsValue, - ) -> JsValue { - console_error_panic_hook::set_once(); - - let params = Uint8Array::new(¶ms).to_vec(); - let params = ParamsKZG::::read(&mut BufReader::new(¶ms[..])).unwrap(); - - let pk: Vec = Uint8Array::new(&pk).to_vec(); - let pk = ProvingKey::::read::<_, $circuit_name>( - &mut BufReader::new(&pk[..]), - SerdeFormat::RawBytes, - ) - .unwrap(); - - let public_key: RsaPublicKey = serde_wasm_bindgen::from_value(public_key).unwrap(); - let n_big = - BigUint::from_radix_le(&public_key.n().clone().to_radix_le(16), 16).unwrap(); - let e_fix = RSAPubE::Fix(BigUint::from($circuit_name::::DEFAULT_E)); - let public_key = RSAPublicKey::new(Value::known(n_big), e_fix); - - let msg: Vec = Uint8Array::new(&msg).to_vec(); - let mut signature: Vec = serde_wasm_bindgen::from_value(signature).unwrap(); - - signature.reverse(); - let sign_big = BigUint::from_bytes_le(&signature); - let signature = RSASignature::new(Value::known(sign_big)); - - let circuit = $circuit_name:: { - signature, - public_key, - msg, - _f: PhantomData, - }; - - let prover = match MockProver::run($k, &circuit, vec![]) { - Ok(prover) => prover, - Err(e) => panic!("{:#?}", e), - }; - prover.verify().unwrap(); - - let proof = { - let mut transcript = Blake2bWrite::<_, G1Affine, Challenge255<_>>::init(vec![]); - create_proof::, ProverGWC<_>, _, _, _, _>( - ¶ms, - &pk, - &[circuit], - &[&[]], - OsRng, - &mut transcript, - ) - .unwrap(); - transcript.finalize() - }; - serde_wasm_bindgen::to_value(&proof).unwrap() - } - - #[wasm_bindgen] - pub fn $verify_fn_name(params: JsValue, vk: JsValue, proof: JsValue) -> bool { - console_error_panic_hook::set_once(); - - let params = Uint8Array::new(¶ms).to_vec(); - let params = ParamsKZG::::read(&mut BufReader::new(¶ms[..])).unwrap(); - let vk: Vec = Uint8Array::new(&vk).to_vec(); - let vk = VerifyingKey::::read::<_, $circuit_name>( - &mut BufReader::new(&vk[..]), - SerdeFormat::RawBytes, - ) - .unwrap(); - - let strategy = SingleStrategy::new(¶ms); - let proof: Vec = serde_wasm_bindgen::from_value(proof).unwrap(); - let mut transcript = Blake2bRead::<_, _, Challenge255<_>>::init(&proof[..]); - verify_proof::<_, VerifierGWC<_>, _, _, _>( - ¶ms, - &vk, - strategy, - &[&[]], - &mut transcript, - ) - .expect("proof invalid"); - true - } - }; -} - -impl_pkcs1v15_wasm_functions!( - Pkcs1v15_1024_64EnabledBenchCircuit, - prove_pkcs1v15_1024_64_circuit, - verify_pkcs1v15_1024_64_circuit, - 64, - 13, - true -); - -impl_pkcs1v15_wasm_functions!( - Pkcs1v15_1024_128EnabledBenchCircuit, - prove_pkcs1v15_1024_128_circuit, - verify_pkcs1v15_1024_128_circuit, - 128, - 13, - true -); - -impl_pkcs1v15_wasm_functions!( - Pkcs1v15_1024_1024EnabledBenchCircuit, - prove_pkcs1v15_1024_1024_circuit, - verify_pkcs1v15_1024_1024_circuit, - 1024, - 13, - true -); - -impl_pkcs1v15_wasm_functions!( - Pkcs1v15_2048_64EnabledBenchCircuit, - prove_pkcs1v15_2048_64_circuit, - verify_pkcs1v15_2048_64_circuit, - 64, - 13, - true -); - -impl_pkcs1v15_wasm_functions!( - Pkcs1v15_2048_128EnabledBenchCircuit, - prove_pkcs1v15_2048_128_circuit, - verify_pkcs1v15_2048_128_circuit, - 128, - 13, - true -); - -impl_pkcs1v15_wasm_functions!( - Pkcs1v15_2048_1024EnabledBenchCircuit, - prove_pkcs1v15_2048_1024_circuit, - verify_pkcs1v15_2048_1024_circuit, - 1024, - 13, - true -); - -impl_pkcs1v15_wasm_functions!( - Pkcs1v15_2048_1024DisabledBenchCircuit, - prove_pkcs1v15_no_sha2_2048_1024_circuit, - verify_pkcs1v15_no_sha2_2048_1024_circuit, - 1024, - 13, - false -); - -#[macro_export] -macro_rules! impl_pkcs1v15_wasm_multi_exec_bench { - ($circuit_name:ident, $k:expr, $multi_bench_fn_name:ident) => { - #[wasm_bindgen] - pub fn $multi_bench_fn_name( - params: JsValue, - pk: JsValue, - vk: JsValue, - public_key: JsValue, - msg: JsValue, - signature: JsValue, - times: usize, - ) -> Array { - let params = Uint8Array::new(¶ms).to_vec(); - let params = ParamsKZG::::read(&mut BufReader::new(¶ms[..])).unwrap(); - let pk = Uint8Array::new(&pk).to_vec(); - let pk = ProvingKey::::read::<_, $circuit_name>( - &mut BufReader::new(&pk[..]), - SerdeFormat::RawBytes, - ) - .unwrap(); - let vk = Uint8Array::new(&vk).to_vec(); - let vk = VerifyingKey::::read::<_, $circuit_name>( - &mut BufReader::new(&vk[..]), - SerdeFormat::RawBytes, - ) - .unwrap(); - let public_key: RsaPublicKey = serde_wasm_bindgen::from_value(public_key).unwrap(); - let msg: Vec = Uint8Array::new(&msg).to_vec(); - let mut signature: Vec = serde_wasm_bindgen::from_value(signature).unwrap(); - signature.reverse(); - - let (sum, square_sum) = (0..times) - .into_par_iter() - .map(|i| { - let window = web_sys::window().expect("should have a window in this context"); - let performance = window - .performance() - .expect("performance should be available"); - let n_big = BigUint::from_radix_le(&public_key.n().clone().to_radix_le(16), 16) - .unwrap(); - let e_fix = RSAPubE::Fix(BigUint::from($circuit_name::::DEFAULT_E)); - let public_key = RSAPublicKey::new(Value::known(n_big), e_fix); - let msg = msg.to_vec(); - let sign_big = BigUint::from_bytes_le(&signature); - let signature = RSASignature::new(Value::known(sign_big)); - - let circuit = $circuit_name:: { - signature, - public_key, - msg, - _f: PhantomData, - }; - - let prover = match MockProver::run($k, &circuit, vec![]) { - Ok(prover) => prover, - Err(e) => panic!("{:#?}", e), - }; - prover.verify().unwrap(); - - // log_2(&"start proof generation at".into(), &i.into()); - let start = performance.timing().request_start(); - let proof = { - let mut transcript = - Blake2bWrite::<_, G1Affine, Challenge255<_>>::init(vec![]); - create_proof::, ProverGWC<_>, _, _, _, _>( - ¶ms, - &pk, - &[circuit], - &[&[]], - OsRng, - &mut transcript, - ) - .unwrap(); - transcript.finalize() - }; - let end = performance.timing().response_end(); - // let strategy = SingleStrategy::new(¶ms); - // let mut transcript = Blake2bRead::<_, _, Challenge255<_>>::init(&proof[..]); - // verify_proof::<_, VerifierGWC<_>, _, _, _>( - // ¶ms, - // &vk, - // strategy, - // &[&[]], - // &mut transcript, - // ) - // .expect("proof invalid"); - let sub = end - start; - // log_3(&"proof generation result ".into(), &i.into(), &sub.into()); - (sub, sub * sub) - }) - .reduce( - || (0.0f64, 0.0f64), - |results: (f64, f64), subs: (f64, f64)| { - (results.0 + subs.0, results.1 + subs.1) - }, - ); - let times = times as f64; - let avg = sum / times; - let square_avg = square_sum / times; - let var = square_avg * square_avg - avg * avg; - let sdv = var.sqrt(); - // let result = [JsValue::from_f64(avg), JsValue::from_f64(sdv)]; - let array = Array::new(); - array.set(0, JsValue::from_f64(avg)); - array.set(1, JsValue::from_f64(sdv)); - array - } - }; -} - -impl_pkcs1v15_wasm_multi_exec_bench!( - Pkcs1v15_2048_1024EnabledBenchCircuit, - 13, - multi_bench_2048_1024_circuit -); diff --git a/web-client/.gitignore b/web-client/.gitignore deleted file mode 100644 index 4d29575..0000000 --- a/web-client/.gitignore +++ /dev/null @@ -1,23 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# production -/build - -# misc -.DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local - -npm-debug.log* -yarn-debug.log* -yarn-error.log* diff --git a/web-client/README.md b/web-client/README.md deleted file mode 100644 index 3d18040..0000000 --- a/web-client/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# Web client - -This is an example web client for halo2_rsa for benchmarking purposes. - -## Credits - -The web client and rust wasm code refers to [halo2 wasm guide](https://zcash.github.io/halo2/user/wasm-port.html) and [this repository](https://github.com/nalinbhardwaj/zordle/tree/main/test-client). diff --git a/web-client/config/env.js b/web-client/config/env.js deleted file mode 100644 index ffa7e49..0000000 --- a/web-client/config/env.js +++ /dev/null @@ -1,104 +0,0 @@ -'use strict'; - -const fs = require('fs'); -const path = require('path'); -const paths = require('./paths'); - -// Make sure that including paths.js after env.js will read .env variables. -delete require.cache[require.resolve('./paths')]; - -const NODE_ENV = process.env.NODE_ENV; -if (!NODE_ENV) { - throw new Error( - 'The NODE_ENV environment variable is required but was not specified.' - ); -} - -// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use -const dotenvFiles = [ - `${paths.dotenv}.${NODE_ENV}.local`, - // Don't include `.env.local` for `test` environment - // since normally you expect tests to produce the same - // results for everyone - NODE_ENV !== 'test' && `${paths.dotenv}.local`, - `${paths.dotenv}.${NODE_ENV}`, - paths.dotenv, -].filter(Boolean); - -// Load environment variables from .env* files. Suppress warnings using silent -// if this file is missing. dotenv will never modify any environment variables -// that have already been set. Variable expansion is supported in .env files. -// https://github.com/motdotla/dotenv -// https://github.com/motdotla/dotenv-expand -dotenvFiles.forEach(dotenvFile => { - if (fs.existsSync(dotenvFile)) { - require('dotenv-expand')( - require('dotenv').config({ - path: dotenvFile, - }) - ); - } -}); - -// We support resolving modules according to `NODE_PATH`. -// This lets you use absolute paths in imports inside large monorepos: -// https://github.com/facebook/create-react-app/issues/253. -// It works similar to `NODE_PATH` in Node itself: -// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders -// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored. -// Otherwise, we risk importing Node.js core modules into an app instead of webpack shims. -// https://github.com/facebook/create-react-app/issues/1023#issuecomment-265344421 -// We also resolve them to make sure all tools using them work consistently. -const appDirectory = fs.realpathSync(process.cwd()); -process.env.NODE_PATH = (process.env.NODE_PATH || '') - .split(path.delimiter) - .filter(folder => folder && !path.isAbsolute(folder)) - .map(folder => path.resolve(appDirectory, folder)) - .join(path.delimiter); - -// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be -// injected into the application via DefinePlugin in webpack configuration. -const REACT_APP = /^REACT_APP_/i; - -function getClientEnvironment(publicUrl) { - const raw = Object.keys(process.env) - .filter(key => REACT_APP.test(key)) - .reduce( - (env, key) => { - env[key] = process.env[key]; - return env; - }, - { - // Useful for determining whether we’re running in production mode. - // Most importantly, it switches React into the correct mode. - NODE_ENV: process.env.NODE_ENV || 'development', - // Useful for resolving the correct path to static assets in `public`. - // For example, . - // This should only be used as an escape hatch. Normally you would put - // images into the `src` and `import` them in code to get their paths. - PUBLIC_URL: publicUrl, - // We support configuring the sockjs pathname during development. - // These settings let a developer run multiple simultaneous projects. - // They are used as the connection `hostname`, `pathname` and `port` - // in webpackHotDevClient. They are used as the `sockHost`, `sockPath` - // and `sockPort` options in webpack-dev-server. - WDS_SOCKET_HOST: process.env.WDS_SOCKET_HOST, - WDS_SOCKET_PATH: process.env.WDS_SOCKET_PATH, - WDS_SOCKET_PORT: process.env.WDS_SOCKET_PORT, - // Whether or not react-refresh is enabled. - // It is defined here so it is available in the webpackHotDevClient. - FAST_REFRESH: process.env.FAST_REFRESH !== 'false', - } - ); - // Stringify all values so we can feed into webpack DefinePlugin - const stringified = { - 'process.env': Object.keys(raw).reduce((env, key) => { - env[key] = JSON.stringify(raw[key]); - return env; - }, {}), - }; - - return { raw, stringified }; -} - -module.exports = getClientEnvironment; diff --git a/web-client/config/getHttpsConfig.js b/web-client/config/getHttpsConfig.js deleted file mode 100644 index 013d493..0000000 --- a/web-client/config/getHttpsConfig.js +++ /dev/null @@ -1,66 +0,0 @@ -'use strict'; - -const fs = require('fs'); -const path = require('path'); -const crypto = require('crypto'); -const chalk = require('react-dev-utils/chalk'); -const paths = require('./paths'); - -// Ensure the certificate and key provided are valid and if not -// throw an easy to debug error -function validateKeyAndCerts({ cert, key, keyFile, crtFile }) { - let encrypted; - try { - // publicEncrypt will throw an error with an invalid cert - encrypted = crypto.publicEncrypt(cert, Buffer.from('test')); - } catch (err) { - throw new Error( - `The certificate "${chalk.yellow(crtFile)}" is invalid.\n${err.message}` - ); - } - - try { - // privateDecrypt will throw an error with an invalid key - crypto.privateDecrypt(key, encrypted); - } catch (err) { - throw new Error( - `The certificate key "${chalk.yellow(keyFile)}" is invalid.\n${ - err.message - }` - ); - } -} - -// Read file and throw an error if it doesn't exist -function readEnvFile(file, type) { - if (!fs.existsSync(file)) { - throw new Error( - `You specified ${chalk.cyan( - type - )} in your env, but the file "${chalk.yellow(file)}" can't be found.` - ); - } - return fs.readFileSync(file); -} - -// Get the https config -// Return cert files if provided in env, otherwise just true or false -function getHttpsConfig() { - const { SSL_CRT_FILE, SSL_KEY_FILE, HTTPS } = process.env; - const isHttps = HTTPS === 'true'; - - if (isHttps && SSL_CRT_FILE && SSL_KEY_FILE) { - const crtFile = path.resolve(paths.appPath, SSL_CRT_FILE); - const keyFile = path.resolve(paths.appPath, SSL_KEY_FILE); - const config = { - cert: readEnvFile(crtFile, 'SSL_CRT_FILE'), - key: readEnvFile(keyFile, 'SSL_KEY_FILE'), - }; - - validateKeyAndCerts({ ...config, keyFile, crtFile }); - return config; - } - return isHttps; -} - -module.exports = getHttpsConfig; diff --git a/web-client/config/jest/babelTransform.js b/web-client/config/jest/babelTransform.js deleted file mode 100644 index 5b391e4..0000000 --- a/web-client/config/jest/babelTransform.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict'; - -const babelJest = require('babel-jest').default; - -const hasJsxRuntime = (() => { - if (process.env.DISABLE_NEW_JSX_TRANSFORM === 'true') { - return false; - } - - try { - require.resolve('react/jsx-runtime'); - return true; - } catch (e) { - return false; - } -})(); - -module.exports = babelJest.createTransformer({ - presets: [ - [ - require.resolve('babel-preset-react-app'), - { - runtime: hasJsxRuntime ? 'automatic' : 'classic', - }, - ], - ], - babelrc: false, - configFile: false, -}); diff --git a/web-client/config/jest/cssTransform.js b/web-client/config/jest/cssTransform.js deleted file mode 100644 index 8f65114..0000000 --- a/web-client/config/jest/cssTransform.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; - -// This is a custom Jest transformer turning style imports into empty objects. -// http://facebook.github.io/jest/docs/en/webpack.html - -module.exports = { - process() { - return 'module.exports = {};'; - }, - getCacheKey() { - // The output is always the same. - return 'cssTransform'; - }, -}; diff --git a/web-client/config/jest/fileTransform.js b/web-client/config/jest/fileTransform.js deleted file mode 100644 index aab6761..0000000 --- a/web-client/config/jest/fileTransform.js +++ /dev/null @@ -1,40 +0,0 @@ -'use strict'; - -const path = require('path'); -const camelcase = require('camelcase'); - -// This is a custom Jest transformer turning file imports into filenames. -// http://facebook.github.io/jest/docs/en/webpack.html - -module.exports = { - process(src, filename) { - const assetFilename = JSON.stringify(path.basename(filename)); - - if (filename.match(/\.svg$/)) { - // Based on how SVGR generates a component name: - // https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6 - const pascalCaseFilename = camelcase(path.parse(filename).name, { - pascalCase: true, - }); - const componentName = `Svg${pascalCaseFilename}`; - return `const React = require('react'); - module.exports = { - __esModule: true, - default: ${assetFilename}, - ReactComponent: React.forwardRef(function ${componentName}(props, ref) { - return { - $$typeof: Symbol.for('react.element'), - type: 'svg', - ref: ref, - key: null, - props: Object.assign({}, props, { - children: ${assetFilename} - }) - }; - }), - };`; - } - - return `module.exports = ${assetFilename};`; - }, -}; diff --git a/web-client/config/modules.js b/web-client/config/modules.js deleted file mode 100644 index d63e41d..0000000 --- a/web-client/config/modules.js +++ /dev/null @@ -1,134 +0,0 @@ -'use strict'; - -const fs = require('fs'); -const path = require('path'); -const paths = require('./paths'); -const chalk = require('react-dev-utils/chalk'); -const resolve = require('resolve'); - -/** - * Get additional module paths based on the baseUrl of a compilerOptions object. - * - * @param {Object} options - */ -function getAdditionalModulePaths(options = {}) { - const baseUrl = options.baseUrl; - - if (!baseUrl) { - return ''; - } - - const baseUrlResolved = path.resolve(paths.appPath, baseUrl); - - // We don't need to do anything if `baseUrl` is set to `node_modules`. This is - // the default behavior. - if (path.relative(paths.appNodeModules, baseUrlResolved) === '') { - return null; - } - - // Allow the user set the `baseUrl` to `appSrc`. - if (path.relative(paths.appSrc, baseUrlResolved) === '') { - return [paths.appSrc]; - } - - // If the path is equal to the root directory we ignore it here. - // We don't want to allow importing from the root directly as source files are - // not transpiled outside of `src`. We do allow importing them with the - // absolute path (e.g. `src/Components/Button.js`) but we set that up with - // an alias. - if (path.relative(paths.appPath, baseUrlResolved) === '') { - return null; - } - - // Otherwise, throw an error. - throw new Error( - chalk.red.bold( - "Your project's `baseUrl` can only be set to `src` or `node_modules`." + - ' Create React App does not support other values at this time.' - ) - ); -} - -/** - * Get webpack aliases based on the baseUrl of a compilerOptions object. - * - * @param {*} options - */ -function getWebpackAliases(options = {}) { - const baseUrl = options.baseUrl; - - if (!baseUrl) { - return {}; - } - - const baseUrlResolved = path.resolve(paths.appPath, baseUrl); - - if (path.relative(paths.appPath, baseUrlResolved) === '') { - return { - src: paths.appSrc, - }; - } -} - -/** - * Get jest aliases based on the baseUrl of a compilerOptions object. - * - * @param {*} options - */ -function getJestAliases(options = {}) { - const baseUrl = options.baseUrl; - - if (!baseUrl) { - return {}; - } - - const baseUrlResolved = path.resolve(paths.appPath, baseUrl); - - if (path.relative(paths.appPath, baseUrlResolved) === '') { - return { - '^src/(.*)$': '/src/$1', - }; - } -} - -function getModules() { - // Check if TypeScript is setup - const hasTsConfig = fs.existsSync(paths.appTsConfig); - const hasJsConfig = fs.existsSync(paths.appJsConfig); - - if (hasTsConfig && hasJsConfig) { - throw new Error( - 'You have both a tsconfig.json and a jsconfig.json. If you are using TypeScript please remove your jsconfig.json file.' - ); - } - - let config; - - // If there's a tsconfig.json we assume it's a - // TypeScript project and set up the config - // based on tsconfig.json - if (hasTsConfig) { - const ts = require(resolve.sync('typescript', { - basedir: paths.appNodeModules, - })); - config = ts.readConfigFile(paths.appTsConfig, ts.sys.readFile).config; - // Otherwise we'll check if there is jsconfig.json - // for non TS projects. - } else if (hasJsConfig) { - config = require(paths.appJsConfig); - } - - config = config || {}; - const options = config.compilerOptions || {}; - - const additionalModulePaths = getAdditionalModulePaths(options); - - return { - additionalModulePaths: additionalModulePaths, - webpackAliases: getWebpackAliases(options), - jestAliases: getJestAliases(options), - hasTsConfig, - }; -} - -module.exports = getModules(); diff --git a/web-client/config/paths.js b/web-client/config/paths.js deleted file mode 100644 index f0a6cd9..0000000 --- a/web-client/config/paths.js +++ /dev/null @@ -1,77 +0,0 @@ -'use strict'; - -const path = require('path'); -const fs = require('fs'); -const getPublicUrlOrPath = require('react-dev-utils/getPublicUrlOrPath'); - -// Make sure any symlinks in the project folder are resolved: -// https://github.com/facebook/create-react-app/issues/637 -const appDirectory = fs.realpathSync(process.cwd()); -const resolveApp = relativePath => path.resolve(appDirectory, relativePath); - -// We use `PUBLIC_URL` environment variable or "homepage" field to infer -// "public path" at which the app is served. -// webpack needs to know it to put the right