-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: added bls12_381 backend to bls crate
- Loading branch information
1 parent
d97f032
commit 5c68f83
Showing
14 changed files
with
762 additions
and
9 deletions.
There are no files selected for viewing
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
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,110 @@ | ||
use derivative::Derivative; | ||
use once_cell::race::OnceBox; | ||
use serde::{Deserialize, Serialize}; | ||
use ssz::{ReadError, Size, SszHash, SszRead, SszReadDefault as _, SszSize, SszWrite, H256}; | ||
|
||
use super::{public_key::PublicKey, public_key_bytes::PublicKeyBytes}; | ||
use crate::{error::Error, traits::CachedPublicKey as CachedPublicKeyTrait}; | ||
|
||
#[derive(Default, Debug, Derivative, Deserialize, Serialize)] | ||
#[derivative(PartialEq, Eq)] | ||
#[serde(transparent)] | ||
pub struct CachedPublicKey { | ||
bytes: PublicKeyBytes, | ||
#[derivative(PartialEq = "ignore")] | ||
#[serde(skip)] | ||
decompressed: OnceBox<PublicKey>, | ||
} | ||
|
||
impl Clone for CachedPublicKey { | ||
fn clone(&self) -> Self { | ||
let Self { | ||
bytes, | ||
ref decompressed, | ||
} = *self; | ||
match decompressed.get().copied() { | ||
Some(public_key) => Self::new(bytes, public_key), | ||
None => bytes.into(), | ||
} | ||
} | ||
} | ||
|
||
impl From<PublicKeyBytes> for CachedPublicKey { | ||
#[inline] | ||
fn from(bytes: PublicKeyBytes) -> Self { | ||
Self { | ||
bytes, | ||
decompressed: OnceBox::new(), | ||
} | ||
} | ||
} | ||
|
||
impl From<PublicKey> for CachedPublicKey { | ||
#[inline] | ||
fn from(public_key: PublicKey) -> Self { | ||
Self::new(public_key.into(), public_key) | ||
} | ||
} | ||
|
||
impl SszSize for CachedPublicKey { | ||
const SIZE: Size = PublicKeyBytes::SIZE; | ||
} | ||
|
||
impl<C> SszRead<C> for CachedPublicKey { | ||
#[inline] | ||
fn from_ssz_unchecked(_context: &C, bytes: &[u8]) -> Result<Self, ReadError> { | ||
Ok(Self { | ||
bytes: PublicKeyBytes::from_ssz_default(bytes)?, | ||
decompressed: OnceBox::new(), | ||
}) | ||
} | ||
} | ||
|
||
impl SszWrite for CachedPublicKey { | ||
#[inline] | ||
fn write_fixed(&self, bytes: &mut [u8]) { | ||
self.bytes.write_fixed(bytes); | ||
} | ||
} | ||
|
||
impl SszHash for CachedPublicKey { | ||
type PackingFactor = <PublicKeyBytes as SszHash>::PackingFactor; | ||
|
||
#[inline] | ||
fn hash_tree_root(&self) -> H256 { | ||
self.bytes.hash_tree_root() | ||
} | ||
} | ||
|
||
impl CachedPublicKeyTrait for CachedPublicKey { | ||
type PublicKeyBytes = PublicKeyBytes; | ||
type PublicKey = PublicKey; | ||
|
||
fn new(bytes: PublicKeyBytes, public_key: PublicKey) -> Self { | ||
let decompressed = OnceBox::new(); | ||
decompressed | ||
.set(Box::new(public_key)) | ||
.expect("decompressed is empty because OnceBox::new returns an empty cell"); | ||
|
||
Self { | ||
bytes, | ||
decompressed, | ||
} | ||
} | ||
|
||
#[inline] | ||
fn as_bytes(&self) -> &PublicKeyBytes { | ||
&self.bytes | ||
} | ||
|
||
#[inline] | ||
fn to_bytes(&self) -> PublicKeyBytes { | ||
self.bytes | ||
} | ||
|
||
#[inline] | ||
fn decompress(&self) -> Result<&PublicKey, Error> { | ||
self.decompressed | ||
.get_or_try_init(|| self.bytes.try_into().map(Box::new)) | ||
} | ||
} |
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,7 @@ | ||
pub mod cached_public_key; | ||
pub mod public_key; | ||
pub mod public_key_bytes; | ||
pub mod secret_key; | ||
pub mod secret_key_bytes; | ||
pub mod signature; | ||
pub mod signature_bytes; |
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,61 @@ | ||
use bls12_381::{G1Affine, G1Projective}; | ||
use derive_more::From; | ||
|
||
use crate::{error::Error, traits::PublicKey as PublicKeyTrait}; | ||
|
||
use super::public_key_bytes::PublicKeyBytes; | ||
|
||
#[derive(Clone, Copy, PartialEq, Eq, Debug, From)] | ||
pub struct PublicKey(G1Projective); | ||
|
||
impl Default for PublicKey { | ||
#[inline] | ||
fn default() -> Self { | ||
Self(G1Projective::identity()) | ||
} | ||
} | ||
|
||
impl TryFrom<PublicKeyBytes> for PublicKey { | ||
type Error = Error; | ||
|
||
#[inline] | ||
fn try_from(bytes: PublicKeyBytes) -> Result<Self, Self::Error> { | ||
let point: G1Affine = Option::from(G1Affine::from_compressed(bytes.as_ref())) | ||
.ok_or(Error::DecompressionFailed)?; | ||
|
||
if !bool::from(point.is_torsion_free()) { | ||
return Err(Error::DecompressionFailed); | ||
} | ||
|
||
Ok(Self(point.into())) | ||
} | ||
} | ||
|
||
impl PublicKeyTrait for PublicKey { | ||
type PublicKeyBytes = PublicKeyBytes; | ||
|
||
fn aggregate_nonempty(public_keys: impl IntoIterator<Item = Self>) -> Result<Self, Error> { | ||
public_keys | ||
.into_iter() | ||
.reduce(Self::aggregate) | ||
.ok_or(Error::NoPublicKeysToAggregate) | ||
} | ||
|
||
#[inline] | ||
#[must_use] | ||
fn aggregate(mut self, other: Self) -> Self { | ||
self.aggregate_in_place(other); | ||
self | ||
} | ||
|
||
#[inline] | ||
fn aggregate_in_place(&mut self, other: Self) { | ||
self.as_raw().add(other.as_raw()); | ||
} | ||
} | ||
|
||
impl PublicKey { | ||
pub(crate) const fn as_raw(&self) -> &G1Projective { | ||
&self.0 | ||
} | ||
} |
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,68 @@ | ||
use bls12_381::G1Affine; | ||
use derive_more::AsRef; | ||
use fixed_hash::construct_fixed_hash; | ||
use hex::FromHex; | ||
use impl_serde::impl_fixed_hash_serde; | ||
use ssz::{BytesToDepth, MerkleTree, ReadError, Size, SszHash, SszRead, SszSize, SszWrite, H256}; | ||
use typenum::{Unsigned as _, U1, U48}; | ||
|
||
use crate::traits::PublicKeyBytes as PublicKeyBytesTrait; | ||
|
||
use super::public_key::PublicKey; | ||
|
||
type CompressedSize = U48; | ||
|
||
construct_fixed_hash! { | ||
#[derive(AsRef)] | ||
pub struct PublicKeyBytes(CompressedSize::USIZE); | ||
} | ||
|
||
impl_fixed_hash_serde!(PublicKeyBytes, CompressedSize::USIZE); | ||
|
||
impl From<PublicKey> for PublicKeyBytes { | ||
#[inline] | ||
fn from(public_key: PublicKey) -> Self { | ||
Self(G1Affine::from(public_key.as_raw()).to_compressed()) | ||
} | ||
} | ||
|
||
impl FromHex for PublicKeyBytes { | ||
type Error = <[u8; CompressedSize::USIZE] as FromHex>::Error; | ||
|
||
fn from_hex<T: AsRef<[u8]>>(digits: T) -> Result<Self, Self::Error> { | ||
FromHex::from_hex(digits).map(Self) | ||
} | ||
} | ||
|
||
impl SszSize for PublicKeyBytes { | ||
const SIZE: Size = Size::Fixed { | ||
size: CompressedSize::USIZE, | ||
}; | ||
} | ||
|
||
impl<C> SszRead<C> for PublicKeyBytes { | ||
#[inline] | ||
fn from_ssz_unchecked(_context: &C, bytes: &[u8]) -> Result<Self, ReadError> { | ||
Ok(Self::from_slice(bytes)) | ||
} | ||
} | ||
|
||
impl SszWrite for PublicKeyBytes { | ||
#[inline] | ||
fn write_fixed(&self, bytes: &mut [u8]) { | ||
bytes.copy_from_slice(self.as_bytes()); | ||
} | ||
} | ||
|
||
impl SszHash for PublicKeyBytes { | ||
type PackingFactor = U1; | ||
|
||
#[inline] | ||
fn hash_tree_root(&self) -> H256 { | ||
MerkleTree::<BytesToDepth<CompressedSize>>::merkleize_bytes(self) | ||
} | ||
} | ||
|
||
impl PublicKeyBytesTrait for PublicKeyBytes { | ||
type PublicKey = PublicKey; | ||
} |
Oops, something went wrong.