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

feat: Add BLS signature verification for BN254 #89

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
56 changes: 9 additions & 47 deletions halo2-ecc/src/bn254/bls_signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use super::pairing::PairingChip;
use super::{Fp12Chip, Fp2Chip, FpChip, FqPoint};
use crate::ecc::EccChip;
use crate::fields::{FieldChip, PrimeField};
use crate::fields::PrimeField;
use crate::halo2_proofs::halo2curves::bn256::{G1Affine, G2Affine};
use halo2_base::Context;

Expand Down Expand Up @@ -41,55 +41,17 @@ impl<'chip, F: PrimeField> BlsSignatureChip<'chip, F> {
let fp2_chip = Fp2Chip::<F>::new(self.fp_chip);
let g2_chip = EccChip::new(&fp2_chip);

let g1_assigned = self.pairing_chip.load_private_g1_unchecked(ctx, g1);
// Checking element from G1 is on curve also check that it's in subgroup G1 since G1 has cofactor of 1
g1_chip.assert_is_on_curve::<halo2_base::halo2_proofs::halo2curves::bn256::G1Affine>(
ctx,
&g1_assigned,
);

let hash_m_assigned = self.pairing_chip.load_private_g2_unchecked(ctx, msghash);
g2_chip.assert_is_on_curve::<halo2_base::halo2_proofs::halo2curves::bn256::G2Affine>(
ctx,
&hash_m_assigned,
);
let g1_assigned = self.pairing_chip.load_private_g1(ctx, g1);

let mut signature_agg_assigned =
self.pairing_chip.load_private_g2_unchecked(ctx, signatures[0]);
g2_chip.field_chip.enforce_less_than(ctx, signature_agg_assigned.x().clone());
let mut pubkey_agg_assigned = self.pairing_chip.load_private_g1_unchecked(ctx, pubkeys[0]);
g1_chip.field_chip.enforce_less_than(ctx, pubkey_agg_assigned.x().clone());
let hash_m_assigned = self.pairing_chip.load_private_g2(ctx, msghash);

// loop through signatures and aggregate them
for (index, signature) in signatures.iter().enumerate() {
if index > 0 {
let signature_assigned =
self.pairing_chip.load_private_g2_unchecked(ctx, *signature);
g2_chip.field_chip.enforce_less_than(ctx, signature_assigned.x().clone());
g2_chip
.assert_is_on_curve::<halo2_base::halo2_proofs::halo2curves::bn256::G2Affine>(
ctx,
&signature_assigned,
);
signature_agg_assigned =
g2_chip.add_unequal(ctx, &signature_agg_assigned, &signature_assigned, false);
}
}
let signature_points =
signatures.iter().map(|pt| g2_chip.assign_point(ctx, *pt)).collect::<Vec<_>>();
flyingnobita marked this conversation as resolved.
Show resolved Hide resolved
let signature_agg_assigned = g2_chip.sum::<G2Affine>(ctx, signature_points);

// loop through pubkeys and aggregate them
for (index, pubkey) in pubkeys.iter().enumerate() {
if index > 0 {
let pubkey_assigned = self.pairing_chip.load_private_g1_unchecked(ctx, *pubkey);
g1_chip.field_chip.enforce_less_than(ctx, pubkey_assigned.x().clone());
g1_chip
.assert_is_on_curve::<halo2_base::halo2_proofs::halo2curves::bn256::G1Affine>(
ctx,
&pubkey_assigned,
);
pubkey_agg_assigned =
g1_chip.add_unequal(ctx, &pubkey_agg_assigned, &pubkey_assigned, false);
}
}
let pubkey_points =
pubkeys.iter().map(|pt| g1_chip.assign_point(ctx, *pt)).collect::<Vec<_>>();
flyingnobita marked this conversation as resolved.
Show resolved Hide resolved
let pubkey_agg_assigned = g1_chip.sum::<G1Affine>(ctx, pubkey_points);

flyingnobita marked this conversation as resolved.
Show resolved Hide resolved
let fp12_chip = Fp12Chip::<F>::new(self.fp_chip);
let g12_chip = EccChip::new(&fp12_chip);
Expand Down
16 changes: 4 additions & 12 deletions halo2-ecc/src/bn254/pairing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -453,23 +453,15 @@ impl<'chip, F: PrimeField> PairingChip<'chip, F> {
Self { fp_chip }
}

pub fn load_private_g1_unchecked(
&self,
ctx: &mut Context<F>,
point: G1Affine,
) -> EcPoint<F, FpPoint<F>> {
pub fn load_private_g1(&self, ctx: &mut Context<F>, point: G1Affine) -> EcPoint<F, FpPoint<F>> {
let g1_chip = EccChip::new(self.fp_chip);
g1_chip.load_private_unchecked(ctx, (point.x, point.y))
g1_chip.load_private::<G1Affine>(ctx, (point.x, point.y))
}

pub fn load_private_g2_unchecked(
&self,
ctx: &mut Context<F>,
point: G2Affine,
) -> EcPoint<F, FqPoint<F>> {
pub fn load_private_g2(&self, ctx: &mut Context<F>, point: G2Affine) -> EcPoint<F, FqPoint<F>> {
let fp2_chip = Fp2Chip::new(self.fp_chip);
let g2_chip = EccChip::new(&fp2_chip);
g2_chip.load_private_unchecked(ctx, (point.x, point.y))
g2_chip.load_private::<G2Affine>(ctx, (point.x, point.y))
}

pub fn miller_loop(
Expand Down
12 changes: 6 additions & 6 deletions halo2-ecc/src/bn254/tests/pairing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ fn pairing_check_test<F: PrimeField>(
let range = RangeChip::<F>::default(params.lookup_bits);
let fp_chip = FpChip::<F>::new(&range, params.limb_bits, params.num_limbs);
let chip = PairingChip::new(&fp_chip);
let P_assigned = chip.load_private_g1_unchecked(ctx, P);
let Q_assigned = chip.load_private_g2_unchecked(ctx, Q);
let S_assigned = chip.load_private_g1_unchecked(ctx, S);
let T_assigned = chip.load_private_g2_unchecked(ctx, G2Affine::generator());
let P_assigned = chip.load_private_g1(ctx, P);
let Q_assigned = chip.load_private_g2(ctx, Q);
let S_assigned = chip.load_private_g1(ctx, S);
let T_assigned = chip.load_private_g2(ctx, G2Affine::generator());
chip.pairing_check(ctx, &Q_assigned, &P_assigned, &T_assigned, &S_assigned);
}

Expand All @@ -60,8 +60,8 @@ fn pairing_test<F: PrimeField>(
let range = RangeChip::<F>::default(params.lookup_bits);
let fp_chip = FpChip::<F>::new(&range, params.limb_bits, params.num_limbs);
let chip = PairingChip::new(&fp_chip);
let P_assigned = chip.load_private_g1_unchecked(ctx, P);
let Q_assigned = chip.load_private_g2_unchecked(ctx, Q);
let P_assigned = chip.load_private_g1(ctx, P);
let Q_assigned = chip.load_private_g2(ctx, Q);
// test optimal ate pairing
let f = chip.pairing(ctx, &Q_assigned, &P_assigned);
let actual_f = pairing(&P, &Q);
Expand Down