Skip to content

Commit

Permalink
feat: support BLS12-381 (based on bls12_381 crate) (#8)
Browse files Browse the repository at this point in the history
Add curve BLS12-381. Targets `ff = "0.13.0"`.

### Sources:
- https://github.com/privacy-scaling-explorations/bls12_381 (all types,
majority of trait impls, and tests)
-
https://github.com/privacy-scaling-explorations/halo2curves/blob/support_bls12-381/src/bls12_381/mod.rs
(endomorphism)

The decision to copy implementation from `bls12_381` crate is explained
by the numerous additional trait impls needed to be compatible with
`halo2-lib`. See bellow.

### Additional changes
- implement `ff::PrimeField` for
[Fp](https://github.com/timoftime/halo2curves/blob/support_bls12-381/src/bls12_381/fp.rs#L366-L396C2),
[Scalar](https://github.com/timoftime/halo2curves/blob/support_bls12-381/src/bls12_381/scalar.rs#L723-L752),
[Fp2](https://github.com/timoftime/halo2curves/blob/support_bls12-381/src/bls12_381/fp2.rs#L625-L680).
- implement misc traits for halo2lib compatibility for
[Fp](https://github.com/timoftime/halo2curves/blob/support_bls12-381/src/bls12_381/fp.rs#L960-L1000),
[Scalar](https://github.com/timoftime/halo2curves/blob/support_bls12-381/src/bls12_381/scalar.rs#L825-L856),
[Fp2](https://github.com/timoftime/halo2curves/blob/support_bls12-381/src/bls12_381/fp2.rs#L682-L696)
- implement ff::Field for
[Fp2](https://github.com/timoftime/halo2curves/blob/support_bls12-381/src/bls12_381/fp2.rs#L416-L599C6)
including
[`sqrt_ratio`](https://github.com/timoftime/halo2curves/blob/support_bls12-381/src/bls12_381/fp2.rs#L495-L599C6).
- implement `CurveAffine` and `CurveAffineExt` for
[G1](https://github.com/timoftime/halo2curves/blob/support_bls12-381/src/bls12_381/g1.rs#L491-L539)
and
[G2](https://github.com/timoftime/halo2curves/blob/support_bls12-381/src/bls12_381/g2.rs#L1341-L1388)
- switch to LE encoding for
[Fp](https://github.com/timoftime/halo2curves/blob/support_bls12-381/src/bls12_381/fp.rs#L413-L517),
[G1Affine](https://github.com/timoftime/halo2curves/blob/support_bls12-381/src/bls12_381/g1.rs#L1198-L1231)
and
[G2Affine](https://github.com/timoftime/halo2curves/blob/support_bls12-381/src/bls12_381/g2.rs#L1254-L1284)
for compatibility with halo2lib
- BE encoding is kept in a separate methods to remain compatible with
test vectors, and since BE is more commonly used for BLS12 (e.g.
Ethereum)
- use local `arithmetic.rs` funcs and a `derive` module instead of
https://github.com/privacy-scaling-explorations/bls12_381/blob/main/src/util.rs
  • Loading branch information
jonathanpwang authored Jan 25, 2024
2 parents 048c5dd + ae2cec1 commit b7b6525
Show file tree
Hide file tree
Showing 23 changed files with 15,477 additions and 0 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ bincode = "1.3.3"
serde_json = "1.0.105"
hex = "0.4"
rand_chacha = "0.3.1"
sha3 = "0.10.8"

[dependencies]
subtle = "2.4"
Expand All @@ -36,6 +37,8 @@ serde_arrays = { version = "0.1.0", optional = true }
hex = { version = "0.4", optional = true, default-features = false, features = ["alloc", "serde"] }
blake2b_simd = "1"
maybe-rayon = { version = "0.1.0", default-features = false }
digest = "0.10.7"
sha2 = "0.10.8"

[features]
default = ["bits", "multicore", "bn256-table", "derive_serde"]
Expand Down
85 changes: 85 additions & 0 deletions src/bls12_381/endo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
//! Source: https://github.com/privacy-scaling-explorations/halo2curves/blob/support_bls12-381/src/bls12_381/mod.rs
use crate::arithmetic::mul_512;
use crate::arithmetic::sbb;
use crate::{
arithmetic::{CurveEndo, EndoParameters},
endo,
};
use ff::PrimeField;
use ff::WithSmallOrderMulGroup;
use std::convert::TryInto;

use super::{G1Projective, Scalar};

// Obtained from https://github.com/ConsenSys/gnark-crypto/blob/master/ecc/utils.go
// See https://github.com/demining/Endomorphism-Secp256k1/blob/main/README.md
// to have more details about the endomorphism.
const ENDO_PARAMS_BLS: EndoParameters = EndoParameters {
// round(b2/n)
gamma2: [0x63f6e522f6cfee30u64, 0x7c6becf1e01faadd, 0x01, 0x0],
// round(-b1/n)
gamma1: [0x02u64, 0x0, 0x0, 0x0],
b1: [0x01u64, 0x0, 0x0, 0x0],
b2: [0x0000000100000000, 0xac45a4010001a402, 0x0, 0x0],
};

endo!(G1Projective, Scalar, ENDO_PARAMS_BLS);

#[test]
fn test_endo() {
use ff::Field;
use rand_core::OsRng;

for _ in 0..100000 {
let k = Scalar::random(OsRng);
let (k1, k1_neg, k2, k2_neg) = G1Projective::decompose_scalar(&k);
if k1_neg & k2_neg {
assert_eq!(
k,
-Scalar::from_u128(k1) + Scalar::ZETA * Scalar::from_u128(k2)
)
} else if k1_neg {
assert_eq!(
k,
-Scalar::from_u128(k1) - Scalar::ZETA * Scalar::from_u128(k2)
)
} else if k2_neg {
assert_eq!(
k,
Scalar::from_u128(k1) + Scalar::ZETA * Scalar::from_u128(k2)
)
} else {
assert_eq!(
k,
Scalar::from_u128(k1) - Scalar::ZETA * Scalar::from_u128(k2)
)
}
}

for _ in 0..100000 {
let k = Scalar::random(OsRng);
let (k1, k1_neg, k2, k2_neg) = G1Projective::decompose_scalar(&k);
if k1_neg & k2_neg {
assert_eq!(
k,
-Scalar::from_u128(k1) + Scalar::ZETA * Scalar::from_u128(k2)
)
} else if k1_neg {
assert_eq!(
k,
-Scalar::from_u128(k1) - Scalar::ZETA * Scalar::from_u128(k2)
)
} else if k2_neg {
assert_eq!(
k,
Scalar::from_u128(k1) + Scalar::ZETA * Scalar::from_u128(k2)
)
} else {
assert_eq!(
k,
Scalar::from_u128(k1) - Scalar::ZETA * Scalar::from_u128(k2)
)
}
}
}
Loading

0 comments on commit b7b6525

Please sign in to comment.