Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix schnorr test #158

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion halo2-ecc/src/bn254/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#![allow(non_snake_case)]
use super::bls_signature::BlsSignatureChip;
use super::pairing::PairingChip;
use super::*;
use crate::ecc::EccChip;
Expand Down
4 changes: 3 additions & 1 deletion halo2-ecc/src/secp256k1/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ use crate::{

pub mod ecdsa;
pub mod ecdsa_tests;
pub mod schnorr_signature;
pub mod schnorr_signature_tests;

#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
struct CircuitParams {
pub struct CircuitParams {
strategy: FpStrategy,
degree: u32,
num_advice: usize,
Expand Down
147 changes: 147 additions & 0 deletions halo2-ecc/src/secp256k1/tests/schnorr_signature.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
#![allow(non_snake_case)]
use crate::halo2_proofs::{
arithmetic::CurveAffine,
halo2curves::bn256::Fr,
halo2curves::secp256k1::{Fp, Fq, Secp256k1Affine},
};
use halo2_base::{halo2_proofs::arithmetic::Field, utils::testing::base_test};
use crate::secp256k1::{FpChip, FqChip};
use crate::{
ecc::{schnorr_signature::schnorr_verify_no_pubkey_check, EccChip},
fields::FieldChip,
};
use halo2_base::utils::BigPrimeField;
use halo2_base::utils::fe_to_biguint;
use num_bigint::BigUint;
use halo2_base::gates::RangeChip;
use halo2_base::Context;
use num_integer::Integer;
use rand::rngs::StdRng;
use rand_core::SeedableRng;
use std::fs::File;
use std::io::BufReader;
use std::io::Write;
use std::{fs, io::BufRead};

use super::CircuitParams;

#[derive(Clone, Copy, Debug)]
pub struct SchnorrInput {
pub r: Fp,
pub s: Fq,
pub msg_hash: Fq,
pub pk: Secp256k1Affine,
}

pub fn schnorr_signature_test<F: BigPrimeField>(
ctx: &mut Context<F>,
range: &RangeChip<F>,
params: CircuitParams,
input: SchnorrInput
) -> F {
let fp_chip = FpChip::<F>::new(&range, params.limb_bits, params.num_limbs);
let fq_chip = FqChip::<F>::new(&range, params.limb_bits, params.num_limbs);

let [m, s] = [input.msg_hash, input.s].map(|x| fq_chip.load_private(ctx, x));
let r = fp_chip.load_private(ctx, input.r);

let ecc_chip = EccChip::<F, FpChip<F>>::new(&fp_chip);
let pk = ecc_chip.assign_point(ctx, input.pk);
// test schnorr signature
let res = schnorr_verify_no_pubkey_check::<F, Fp, Fq, Secp256k1Affine>(
&ecc_chip, ctx, pk, r, s, m, 4, 4,
);
*res.value()
}

pub fn random_schnorr_signature_input(rng: &mut StdRng) -> SchnorrInput {
let sk = <Secp256k1Affine as CurveAffine>::ScalarExt::random(rng.clone());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point of the random test is to use different seeded Rngs. So you should use the given rng but mutate it.

Since rng: &mut StdRng is already a mutable reference, I think you should replace all rng.clone() with just rng.

let pk = Secp256k1Affine::from(Secp256k1Affine::generator() * sk);
let msg_hash =
<Secp256k1Affine as CurveAffine>::ScalarExt::random(rng.clone());

let mut k = <Secp256k1Affine as CurveAffine>::ScalarExt::random(rng.clone());

let mut r_point =
Secp256k1Affine::from(Secp256k1Affine::generator() * k).coordinates().unwrap();
let mut x: &Fp = r_point.x();
let mut y: &Fp = r_point.y();
// make sure R.y is even
while fe_to_biguint(y).mod_floor(&BigUint::from(2u64)) != BigUint::from(0u64) {
k = <Secp256k1Affine as CurveAffine>::ScalarExt::random(rng.clone());
r_point = Secp256k1Affine::from(Secp256k1Affine::generator() * k).coordinates().unwrap();
x = r_point.x();
y = r_point.y();
}

let r = *x;
let s = k + sk * msg_hash;

SchnorrInput {r, s, msg_hash, pk}
}

pub fn run_test(input: SchnorrInput) {
let path = "configs/secp256k1/schnorr_circuit.config";
let params: CircuitParams = serde_json::from_reader(
File::open(path).unwrap_or_else(|e| panic!("{path} does not exist: {e:?}")),
)
.unwrap();

let res = base_test()
.k(params.degree)
.lookup_bits(params.lookup_bits)
.run(|ctx, range| schnorr_signature_test(ctx, range, params, input));
assert_eq!(res, Fr::ONE);
}

#[test]
fn test_secp256k1_schnorr() {
let mut rng = StdRng::seed_from_u64(0);
let input = random_schnorr_signature_input(&mut rng);
run_test(input);
}

#[test]
fn bench_secp256k1_schnorr() -> Result<(), Box<dyn std::error::Error>> {
let mut rng = StdRng::from_seed([0u8; 32]);
let config_path = "configs/secp256k1/bench_schnorr.config";
let bench_params_file =
File::open(config_path).unwrap_or_else(|e| panic!("{config_path} does not exist: {e:?}"));
fs::create_dir_all("results/secp256k1").unwrap();
fs::create_dir_all("data").unwrap();
let results_path = "results/secp256k1/schnorr_bench.csv";
let mut fs_results = File::create(results_path).unwrap();
writeln!(fs_results, "degree,num_advice,num_lookup,num_fixed,lookup_bits,limb_bits,num_limbs,proof_time,proof_size,verify_time")?;

let bench_params_reader = BufReader::new(bench_params_file);
for line in bench_params_reader.lines() {
let bench_params: CircuitParams = serde_json::from_str(line.unwrap().as_str()).unwrap();
let k = bench_params.degree;
println!("---------------------- degree = {k} ------------------------------",);

let stats =
base_test().k(k).lookup_bits(bench_params.lookup_bits).unusable_rows(20).bench_builder(
random_schnorr_signature_input(&mut rng),
random_schnorr_signature_input(&mut rng),
|pool, range, input| {
schnorr_signature_test(pool.main(), range, bench_params, input);
},
);

writeln!(
fs_results,
"{},{},{},{},{},{},{},{:?},{},{:?}",
bench_params.degree,
bench_params.num_advice,
bench_params.num_lookup_advice,
bench_params.num_fixed,
bench_params.lookup_bits,
bench_params.limb_bits,
bench_params.num_limbs,
stats.proof_time.time.elapsed(),
stats.proof_size,
stats.verify_time.time.elapsed()
)?;
}
Ok(())
}
Loading