use chia_bls::{PublicKey, SecretKey, Signature};
use rand_core::{CryptoRng, RngCore};
use zeroize::Zeroizing;
use crate::error::{KeystoreError, Result};
use crate::scheme::KeyScheme;
#[derive(Debug, Clone, Copy)]
pub struct L1WalletBls;
impl KeyScheme for L1WalletBls {
type PublicKey = PublicKey;
type Signature = Signature;
const MAGIC: [u8; 6] = *b"DIGLW1";
const NAME: &'static str = "L1WalletBls";
const SCHEME_ID: u16 = 0x0003;
const SECRET_LEN: usize = 32;
fn generate<R: RngCore + CryptoRng>(rng: &mut R) -> Zeroizing<Vec<u8>> {
let mut seed = Zeroizing::new(vec![0u8; Self::SECRET_LEN]);
rng.fill_bytes(&mut seed);
seed
}
fn public_key(secret: &[u8]) -> Result<Self::PublicKey> {
let sk = secret_to_secret_key(secret)?;
Ok(sk.public_key())
}
fn sign(secret: &[u8], msg: &[u8]) -> Result<Self::Signature> {
let sk = secret_to_secret_key(secret)?;
Ok(chia_bls::sign(&sk, msg))
}
}
fn secret_to_secret_key(secret: &[u8]) -> Result<SecretKey> {
if secret.len() != L1WalletBls::SECRET_LEN {
return Err(KeystoreError::InvalidPlaintext {
expected: L1WalletBls::SECRET_LEN,
got: secret.len(),
});
}
Ok(SecretKey::from_seed(secret))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn magic_differs_from_bls_signing() {
use crate::scheme::BlsSigning;
assert_ne!(L1WalletBls::MAGIC, BlsSigning::MAGIC);
assert_ne!(L1WalletBls::SCHEME_ID, BlsSigning::SCHEME_ID);
}
#[test]
fn roundtrip_sign_verify() {
let seed = [42u8; 32];
let pk = L1WalletBls::public_key(&seed).unwrap();
let sig = L1WalletBls::sign(&seed, b"hi").unwrap();
assert!(chia_bls::verify(&sig, &pk, b"hi"));
}
}