Skip to content

Commit

Permalink
add io function and use for generating pop bls/paired
Browse files Browse the repository at this point in the history
  • Loading branch information
coax1d committed Nov 19, 2024
1 parent 1c7c011 commit 156b500
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::{KeyTypeId, RuntimePublic};
use alloc::vec::Vec;
pub use sp_core::bandersnatch::*;

use sp_core::crypto::{ProofOfPossessionGenerator, ProofOfPossessionVerifier};
use sp_core::crypto::ProofOfPossessionVerifier;

mod app {
crate::app_crypto!(super, sp_core::testing::BANDERSNATCH);
Expand Down
6 changes: 2 additions & 4 deletions substrate/primitives/application-crypto/src/bls381.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::{KeyTypeId, RuntimePublic};
use alloc::vec::Vec;

pub use sp_core::bls::bls381::*;
use sp_core::crypto::{ProofOfPossessionGenerator, ProofOfPossessionVerifier};
use sp_core::crypto::ProofOfPossessionVerifier;

mod app {
crate::app_crypto!(super, sp_core::testing::BLS381);
Expand Down Expand Up @@ -54,9 +54,7 @@ impl RuntimePublic for Public {
}

fn generate_pop(&mut self, key_type: KeyTypeId) -> Option<Self::Signature> {
// TODO: Add host function
// sp_io::crypto::generate_pop()
None
sp_io::crypto::bls381_generate_pop(key_type, self)
}

fn verify_pop(&self, pop: &Self::Signature) -> bool {
Expand Down
2 changes: 1 addition & 1 deletion substrate/primitives/application-crypto/src/ecdsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::{KeyTypeId, RuntimePublic};
use alloc::vec::Vec;

pub use sp_core::ecdsa::*;
use sp_core::crypto::{ProofOfPossessionGenerator, ProofOfPossessionVerifier};
use sp_core::crypto::ProofOfPossessionVerifier;

mod app {
crate::app_crypto!(super, sp_core::testing::ECDSA);
Expand Down
62 changes: 59 additions & 3 deletions substrate/primitives/application-crypto/src/ecdsa_bls381.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@
use crate::{KeyTypeId, RuntimePublic};
use alloc::vec::Vec;

use sp_core::{bls381, ecdsa, ecdsa_bls381};
pub use sp_core::paired_crypto::ecdsa_bls381::*;
use sp_core::crypto::{ProofOfPossessionGenerator, ProofOfPossessionVerifier};
use sp_core::crypto::ProofOfPossessionVerifier;

mod app {
crate::app_crypto!(super, sp_core::testing::ECDSA_BLS381);
Expand Down Expand Up @@ -54,8 +55,25 @@ impl RuntimePublic for Public {
}

fn generate_pop(&mut self, key_type: KeyTypeId) -> Option<Self::Signature> {
// TODO: Implement Special Case by calling both pop generations
None
if key_type != sp_core::testing::ECDSA_BLS381 {
return None
}

let pub_key_as_bytes = self.to_raw_vec();

// Split public key bytes into ECDSA and BLS381 parts
let (ecdsa_pub_as_bytes, bls381_pub_as_bytes) = split_pub_key_bytes(&pub_key_as_bytes)?;

// Generate ECDSA proof of possession
let ecdsa_pop = generate_ecdsa_pop(ecdsa_pub_as_bytes)?;

// Generate BLS381 proof of possession
let bls381_pop = generate_bls381_pop(bls381_pub_as_bytes)?;

// Combine the two pops into a single pop
let combined_pop_raw = combine_pop(&ecdsa_pop, &bls381_pop)?;

Some(Self::Signature::from_raw(combined_pop_raw))
}

fn verify_pop(&self, pop: &Self::Signature) -> bool {
Expand All @@ -68,3 +86,41 @@ impl RuntimePublic for Public {
sp_core::crypto::ByteArray::to_raw_vec(self)
}
}

/// Helper: Split public key bytes into ECDSA and BLS381 parts
fn split_pub_key_bytes(pub_key_as_bytes: &[u8])
-> Option<([u8; ecdsa::PUBLIC_KEY_SERIALIZED_SIZE], [u8; bls381::PUBLIC_KEY_SERIALIZED_SIZE])> {
let ecdsa_pub_as_bytes = pub_key_as_bytes[..ecdsa::PUBLIC_KEY_SERIALIZED_SIZE]
.try_into()
.ok()?;
let bls381_pub_as_bytes = pub_key_as_bytes[ecdsa::PUBLIC_KEY_SERIALIZED_SIZE..]
.try_into()
.ok()?;
Some((ecdsa_pub_as_bytes, bls381_pub_as_bytes))
}

/// Helper: Generate ECDSA proof of possession
fn generate_ecdsa_pop(ecdsa_pub_as_bytes: [u8; ecdsa::PUBLIC_KEY_SERIALIZED_SIZE]) -> Option<ecdsa::Signature> {
let pop_context_tag: &[u8] = b"POP_";
let ecdsa_statement = [pop_context_tag, ecdsa_pub_as_bytes.as_slice()].concat();
let ecdsa_pub = ecdsa::Public::from_raw(ecdsa_pub_as_bytes);
sp_io::crypto::ecdsa_sign(sp_core::testing::ECDSA, &ecdsa_pub, ecdsa_statement.as_slice())
}

/// Helper: Generate BLS381 proof of possession
fn generate_bls381_pop(bls381_pub_as_bytes: [u8; bls381::PUBLIC_KEY_SERIALIZED_SIZE]) -> Option<bls381::Signature> {
let bls381_pub = bls381::Public::from_raw(bls381_pub_as_bytes);
sp_io::crypto::bls381_generate_pop(sp_core::testing::BLS381, &bls381_pub)
}

/// Helper: Combine ECDSA and BLS381 pops into a single raw pop
fn combine_pop(
ecdsa_pop: &ecdsa::Signature,
bls381_pop: &bls381::Signature,
) -> Option<[u8; ecdsa_bls381::SIGNATURE_LEN]> {
let mut combined_pop_raw = [0u8; ecdsa_bls381::SIGNATURE_LEN];
combined_pop_raw[..ecdsa::SIGNATURE_SERIALIZED_SIZE].copy_from_slice(ecdsa_pop.as_ref());
combined_pop_raw[ecdsa::SIGNATURE_SERIALIZED_SIZE..].copy_from_slice(bls381_pop.as_ref());
Some(combined_pop_raw)
}

2 changes: 1 addition & 1 deletion substrate/primitives/application-crypto/src/ed25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::{KeyTypeId, RuntimePublic};
use alloc::vec::Vec;

pub use sp_core::ed25519::*;
use sp_core::crypto::{ProofOfPossessionGenerator, ProofOfPossessionVerifier};
use sp_core::crypto::ProofOfPossessionVerifier;

mod app {
crate::app_crypto!(super, sp_core::testing::ED25519);
Expand Down
4 changes: 2 additions & 2 deletions substrate/primitives/core/src/paired_crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,9 @@ pub mod ecdsa_bls381 {
/// An identifier used to match public keys against BLS12-381 keys
pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"ecb8");

const PUBLIC_KEY_LEN: usize =
pub const PUBLIC_KEY_LEN: usize =
ecdsa::PUBLIC_KEY_SERIALIZED_SIZE + bls381::PUBLIC_KEY_SERIALIZED_SIZE;
const SIGNATURE_LEN: usize =
pub const SIGNATURE_LEN: usize =
ecdsa::SIGNATURE_SERIALIZED_SIZE + bls381::SIGNATURE_SERIALIZED_SIZE;

#[doc(hidden)]
Expand Down
11 changes: 10 additions & 1 deletion substrate/primitives/io/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ use tracing;

#[cfg(feature = "std")]
use sp_core::{
crypto::Pair,
crypto::{Pair, ProofOfPossessionGenerator},
hexdisplay::HexDisplay,
offchain::{OffchainDbExt, OffchainWorkerExt, TransactionPoolExt},
storage::ChildInfo,
Expand Down Expand Up @@ -1219,6 +1219,15 @@ pub trait Crypto {
.expect("`bls381_generate` failed")
}

#[cfg(feature = "bls-experimental")]
fn bls381_generate_pop(&mut self, id: KeyTypeId, pub_key: &bls381::Public) -> Option<bls381::Signature> {
self.extension::<KeystoreExt>()
.expect("No `keystore` associated for the current context!")
.bls381_generate_pop(id, pub_key)
.ok()
.flatten()
}

/// Generate an `(ecdsa,bls12-381)` key for the given key type using an optional `seed` and
/// store it in the keystore.
///
Expand Down
16 changes: 16 additions & 0 deletions substrate/primitives/keystore/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,13 @@ pub trait Keystore: Send + Sync {
msg: &[u8],
) -> Result<Option<bls381::Signature>, Error>;

#[cfg(feature = "bls-experimental")]
fn bls381_generate_pop(
&self,
key_type: KeyTypeId,
public: &bls381::Public
) -> Result<Option<bls381::Signature>, Error>;

/// Generate a (ecdsa,bls381) signature pair for a given message.
///
/// Receives [`KeyTypeId`] and a [`ecdsa_bls381::Public`] key to be able to map
Expand Down Expand Up @@ -620,6 +627,15 @@ impl<T: Keystore + ?Sized> Keystore for Arc<T> {
(**self).bls381_sign(key_type, public, msg)
}

#[cfg(feature = "bls-experimental")]
fn bls381_generate_pop(
&self,
key_type: KeyTypeId,
public: &bls381::Public
) -> Result<Option<bls381::Signature>, Error> {
(**self).bls381_generate_pop(key_type, public)
}

#[cfg(feature = "bls-experimental")]
fn ecdsa_bls381_sign(
&self,
Expand Down
20 changes: 19 additions & 1 deletion substrate/primitives/keystore/src/testing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use sp_core::bandersnatch;
#[cfg(feature = "bls-experimental")]
use sp_core::{bls381, ecdsa_bls381, KeccakHasher};
use sp_core::{
crypto::{ByteArray, KeyTypeId, Pair, VrfSecret},
crypto::{ByteArray, KeyTypeId, Pair, VrfSecret, ProofOfPossessionGenerator},
ecdsa, ed25519, sr25519,
};

Expand Down Expand Up @@ -122,6 +122,15 @@ impl MemoryKeystore {
let pre_output = self.pair::<T>(key_type, public).map(|pair| pair.vrf_pre_output(input));
Ok(pre_output)
}

fn generate_pop<T: Pair + ProofOfPossessionGenerator>(
&self,
key_type: KeyTypeId,
public: &T::Public
) -> Result<Option<T::Signature>, Error> {
let pop = self.pair::<T>(key_type, public).map(|mut pair| pair.generate_proof_of_possession());
Ok(pop)
}
}

impl Keystore for MemoryKeystore {
Expand Down Expand Up @@ -298,6 +307,15 @@ impl Keystore for MemoryKeystore {
self.sign::<bls381::Pair>(key_type, public, msg)
}

#[cfg(feature = "bls-experimental")]
fn bls381_generate_pop(
&self,
key_type: KeyTypeId,
public: &bls381::Public
) -> Result<Option<bls381::Signature>, Error> {
self.generate_pop::<bls381::Pair>(key_type, public)
}

#[cfg(feature = "bls-experimental")]
fn ecdsa_bls381_public_keys(&self, key_type: KeyTypeId) -> Vec<ecdsa_bls381::Public> {
self.public_keys::<ecdsa_bls381::Pair>(key_type)
Expand Down

0 comments on commit 156b500

Please sign in to comment.