Skip to content

Commit

Permalink
refactor: moved common code from bls backend to traits
Browse files Browse the repository at this point in the history
  • Loading branch information
shreyas-londhe committed Dec 26, 2024
1 parent 09fd47e commit a93d47c
Show file tree
Hide file tree
Showing 21 changed files with 414 additions and 803 deletions.
116 changes: 9 additions & 107 deletions bls/src/backends/bls12_381/cached_public_key.rs
Original file line number Diff line number Diff line change
@@ -1,110 +1,12 @@
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
}
use crate::{
error::Error, impl_cached_public_key, traits::CachedPublicKey as CachedPublicKeyTrait,
};

#[inline]
fn decompress(&self) -> Result<&PublicKey, Error> {
self.decompressed
.get_or_try_init(|| self.bytes.try_into().map(Box::new))
}
}
impl_cached_public_key!(
CachedPublicKeyTrait,
CachedPublicKey,
PublicKeyBytes,
PublicKey
);
14 changes: 0 additions & 14 deletions bls/src/backends/bls12_381/public_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,6 @@ impl TryFrom<PublicKeyBytes> for PublicKey {
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());
Expand Down
56 changes: 6 additions & 50 deletions bls/src/backends/bls12_381/public_key_bytes.rs
Original file line number Diff line number Diff line change
@@ -1,68 +1,24 @@
use bls12_381::G1Affine;
use derive_more::AsRef;
use derive_more::derive::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 crate::{impl_public_key_bytes, traits::COMPRESSED_SIZE};

use super::public_key::PublicKey;

type CompressedSize = U48;

construct_fixed_hash! {
#[derive(AsRef)]
pub struct PublicKeyBytes(CompressedSize::USIZE);
pub struct PublicKeyBytes(COMPRESSED_SIZE);
}

impl_fixed_hash_serde!(PublicKeyBytes, CompressedSize::USIZE);
impl_fixed_hash_serde!(PublicKeyBytes, COMPRESSED_SIZE);

impl_public_key_bytes!(PublicKeyBytes);

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;
}
85 changes: 20 additions & 65 deletions bls/src/backends/bls12_381/secret_key.rs
Original file line number Diff line number Diff line change
@@ -1,61 +1,27 @@
use core::ops::Deref;
use core::{
fmt::{Binary, Display, LowerExp, LowerHex, Octal, Pointer, UpperExp, UpperHex},
hash::{Hash, Hasher},
use crate::{
consts::DOMAIN_SEPARATION_TAG, error::Error, impl_secret_key,
traits::SecretKey as SecretKeyTrait,
};
use std::borrow::ToOwned;

use bls12_381::{
hash_to_curve::{ExpandMsgXmd, HashToCurve},
G1Projective, G2Projective, Scalar,
};
use derive_more::Debug;
use serde::Serialize;
use sha2::Sha256;
use ssz::{SszHash, SszWrite};
use static_assertions::assert_not_impl_any;

use super::{
public_key::PublicKey,
secret_key_bytes::{SecretKeyBytes, SIZE},
signature::Signature,
};
use crate::{consts::DOMAIN_SEPARATION_TAG, error::Error, traits::SecretKey as SecretKeyTrait};

#[derive(Debug)]
#[debug("[REDACTED]")]
pub struct SecretKey(Scalar);

assert_not_impl_any! {
SecretKey:

Clone,
Copy,
Deref,
ToOwned,

Binary,
Display,
LowerExp,
LowerHex,
Octal,
Pointer,
UpperExp,
UpperHex,

Serialize,
SszHash,
SszWrite,
}

impl PartialEq for SecretKey {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.as_raw().to_bytes() == other.as_raw().to_bytes()
}
}

impl Eq for SecretKey {}
impl_secret_key!(
SecretKeyTrait<SIZE>,
SecretKey,
Scalar,
SecretKeyBytes,
PublicKey,
Signature
);

impl TryFrom<SecretKeyBytes> for SecretKey {
type Error = Error;
Expand All @@ -74,17 +40,19 @@ impl TryFrom<SecretKeyBytes> for SecretKey {
}
}

impl Hash for SecretKey {
fn hash<H: Hasher>(&self, hasher: &mut H) {
self.as_raw().to_bytes().hash(hasher)
}
}

impl SecretKeyTrait<SIZE> for SecretKey {
type SecretKeyBytes = SecretKeyBytes;
type PublicKey = PublicKey;
type Signature = Signature;

#[inline]
#[must_use]
fn to_bytes(&self) -> SecretKeyBytes {
SecretKeyBytes {
bytes: self.as_raw().to_bytes(),
}
}

#[inline]
#[must_use]
fn to_public_key(&self) -> PublicKey {
Expand All @@ -99,21 +67,8 @@ impl SecretKeyTrait<SIZE> for SecretKey {
&[message.as_ref()],
DOMAIN_SEPARATION_TAG,
);
let signature = h * self.0;
let signature = h * self.as_raw();

Signature::from(signature)
}

#[inline]
#[must_use]
fn to_bytes(&self) -> SecretKeyBytes {
let bytes = self.as_raw().to_bytes();
SecretKeyBytes { bytes }
}
}

impl SecretKey {
const fn as_raw(&self) -> &Scalar {
&self.0
}
}
Loading

0 comments on commit a93d47c

Please sign in to comment.