-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Optimize bls precompile by arkworks lib (#993)
* Optimize bls precompile by arkworks lib * Pin bls-test precompose at `address(2017)` * Fmt * Update deps * Add openssl deps in nix * Remove empty line * Format and fix compile * Fix * Resolve conv * Fix * Use rustup on nixos * Fix * Disable in the crab and darwinia network * Add `shell.nix` to .gitigore * Format * Format --------- Co-authored-by: Xavier Lau <[email protected]> Co-authored-by: bear <[email protected]>
- Loading branch information
1 parent
13368e2
commit 26b3b16
Showing
7 changed files
with
355 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,8 @@ | |
# Package Manager | ||
## cargo | ||
target | ||
# nix | ||
shell.nix | ||
## npm | ||
node_modules | ||
|
||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
// This file is part of Darwinia. | ||
// | ||
// Copyright (C) 2018-2023 Darwinia Network | ||
// SPDX-License-Identifier: GPL-3.0 | ||
// | ||
// Darwinia is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
// | ||
// Darwinia is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with Darwinia. If not, see <https://www.gnu.org/licenses/>. | ||
// | ||
// Inspired from https://github.com/w3f/apk-proofs/blob/main/bw6/src/bls/mod.rs | ||
|
||
// core | ||
use core::{borrow::Borrow, ops::Neg}; | ||
// crates.io | ||
use ark_bls12_381::{ | ||
g2::Config as G2Config, Bls12_381, G1Affine, G1Projective, G2Affine, G2Projective, | ||
}; | ||
use ark_ec::{ | ||
hashing::{ | ||
curve_maps::wb::WBMap, map_to_curve_hasher::MapToCurveBasedHasher, HashToCurve, | ||
HashToCurveError, | ||
}, | ||
models::short_weierstrass::Projective, | ||
pairing::Pairing, | ||
AffineRepr, CurveGroup, | ||
}; | ||
use ark_ff::{field_hashers::DefaultFieldHasher, Zero}; | ||
use ark_serialize::*; | ||
use sha2::Sha256; | ||
// substrate | ||
use sp_std::prelude::Vec; | ||
|
||
/// Domain Separation Tag for signatures on G2 | ||
pub const DST_G2: &[u8] = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"; | ||
|
||
#[derive(Clone, Debug)] | ||
pub struct Signature(G2Projective); | ||
impl From<G2Projective> for Signature { | ||
fn from(sig: G2Projective) -> Signature { | ||
Signature(sig) | ||
} | ||
} | ||
impl AsRef<G2Projective> for Signature { | ||
fn as_ref(&self) -> &G2Projective { | ||
&self.0 | ||
} | ||
} | ||
impl Signature { | ||
pub fn from_bytes(bytes: &[u8]) -> Result<Signature, SerializationError> { | ||
let p = G2Affine::deserialize_compressed(bytes)?; | ||
Ok(Self(p.into())) | ||
} | ||
|
||
#[allow(dead_code)] | ||
pub fn aggregate<S: Borrow<Signature>>(signatures: impl IntoIterator<Item = S>) -> Signature { | ||
signatures.into_iter().map(|s| s.borrow().0).sum::<G2Projective>().into() | ||
} | ||
} | ||
|
||
#[derive(Clone, Debug, Eq, PartialEq, Hash, CanonicalSerialize, CanonicalDeserialize)] | ||
pub struct PublicKey(pub G1Projective); | ||
impl From<G1Projective> for PublicKey { | ||
fn from(pk: G1Projective) -> PublicKey { | ||
PublicKey(pk) | ||
} | ||
} | ||
impl PublicKey { | ||
pub fn from_bytes(bytes: &[u8]) -> Result<PublicKey, SerializationError> { | ||
let p = G1Affine::deserialize_compressed(bytes)?; | ||
Ok(Self(p.into())) | ||
} | ||
|
||
pub fn aggregate<P: Borrow<PublicKey>>(public_keys: impl IntoIterator<Item = P>) -> PublicKey { | ||
public_keys.into_iter().map(|s| s.borrow().0).sum::<G1Projective>().into() | ||
} | ||
|
||
pub fn verify(&self, signature: &Signature, message: &G2Projective) -> bool { | ||
Bls12_381::multi_pairing( | ||
[G1Affine::generator().neg(), self.0.into_affine()], | ||
[signature.as_ref().into_affine(), message.into_affine()], | ||
) | ||
.is_zero() | ||
} | ||
} | ||
|
||
pub fn hash_to_curve_g2(message: &[u8]) -> Result<G2Projective, HashToCurveError> { | ||
let wb_to_curve_hasher = MapToCurveBasedHasher::< | ||
Projective<G2Config>, | ||
DefaultFieldHasher<Sha256, 128>, | ||
WBMap<G2Config>, | ||
>::new(DST_G2)?; | ||
Ok(wb_to_curve_hasher.hash(message)?.into()) | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
// crates.io | ||
use rand::Rng; | ||
use ark_std::test_rng; | ||
use ark_bls12_381::Fr; | ||
use ark_ec::Group; | ||
use ark_ff::UniformRand; | ||
// darwinia | ||
use super::*; | ||
|
||
#[derive(Clone, Debug, CanonicalSerialize, CanonicalDeserialize)] | ||
pub struct SecretKey(Fr); | ||
|
||
impl From<Fr> for SecretKey { | ||
fn from(sk: Fr) -> SecretKey { | ||
SecretKey(sk) | ||
} | ||
} | ||
|
||
impl From<&SecretKey> for PublicKey { | ||
fn from(sk: &SecretKey) -> PublicKey { | ||
(G1Projective::generator() * sk.as_ref()).into() | ||
} | ||
} | ||
|
||
impl AsRef<Fr> for SecretKey { | ||
fn as_ref(&self) -> &Fr { | ||
&self.0 | ||
} | ||
} | ||
|
||
impl SecretKey { | ||
pub fn new<R: Rng>(rng: &mut R) -> SecretKey { | ||
SecretKey(Fr::rand(rng)) | ||
} | ||
|
||
pub fn sign(&self, message: &G2Projective) -> Signature { | ||
(*message * self.as_ref()).into() | ||
} | ||
} | ||
|
||
#[test] | ||
fn test_apk() { | ||
let rng = &mut test_rng(); | ||
let message = G2Projective::rand(rng); | ||
|
||
let sks = (0..10).map(|_| SecretKey::new(rng)).collect::<Vec<_>>(); | ||
let pks = sks.iter().map(PublicKey::from).collect::<Vec<_>>(); | ||
let sigs = sks.iter().map(|sk| sk.sign(&message)).collect::<Vec<_>>(); | ||
pks.iter().zip(sigs.iter()).for_each(|(pk, sig)| assert!(pk.verify(sig, &message))); | ||
|
||
let apk = PublicKey::aggregate(pks); | ||
let asig = Signature::aggregate(sigs); | ||
assert!(apk.verify(&asig, &message)); | ||
} | ||
|
||
#[test] | ||
fn test_h2c() { | ||
let message = vec![ | ||
58, 137, 108, 164, 181, 219, 16, 43, 157, 253, 71, 82, 139, 6, 34, 10, 145, 189, 18, | ||
70, 29, 204, 134, 121, 60, 226, 213, 145, 244, 30, 164, 248, | ||
]; | ||
let e = vec![ | ||
178, 18, 44, 225, 215, 170, 68, 228, 52, 151, 40, 113, 171, 202, 76, 203, 156, 112, | ||
105, 249, 147, 210, 132, 79, 69, 117, 109, 151, 35, 71, 117, 21, 119, 179, 181, 81, 92, | ||
22, 22, 88, 190, 243, 147, 248, 3, 210, 87, 98, 0, 84, 201, 248, 182, 249, 99, 59, 86, | ||
60, 71, 244, 250, 189, 134, 232, 18, 82, 72, 76, 83, 155, 46, 113, 128, 107, 49, 67, | ||
174, 100, 244, 181, 33, 174, 14, 151, 112, 62, 141, 100, 173, 191, 103, 178, 205, 17, | ||
237, 147, | ||
]; | ||
let p: G2Affine = hash_to_curve_g2(&message).unwrap().into(); | ||
let mut c = Vec::new(); | ||
p.serialize_compressed(&mut c).unwrap(); | ||
assert_eq!(e, c); | ||
} | ||
} |
Oops, something went wrong.