Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/app/src/obolapi/exit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

use std::collections::HashMap;

use pluto_crypto::{blst_impl::BlstImpl, tbls::Tbls, types::Signature};
use pluto_crypto::{tbls, types::Signature};
use serde::{Deserialize, Serialize};

use pluto_cluster::{
Expand Down Expand Up @@ -353,7 +353,7 @@ impl Client {
}

// Perform threshold aggregation
let full_sig = BlstImpl.threshold_aggregate(&raw_signatures)?;
let full_sig = tbls::threshold_aggregate(&raw_signatures)?;

let epoch_u64: u64 = exit_response.epoch.parse()?;

Expand Down
39 changes: 16 additions & 23 deletions crates/app/tests/wiring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ use pluto_core::{
ProposerDutyDefinition, PubKey, SignedData, SignedDataSet, Slot, SlotNumber,
},
};
use pluto_crypto::{blst_impl::BlstImpl, tbls::Tbls};
use pluto_crypto::tbls;
use pluto_eth2api::{
BeaconNodeClient, EthBeaconNodeApiClient, GetStateValidatorsResponseResponse,
GetStateValidatorsResponseResponseDatum,
Expand Down Expand Up @@ -176,7 +176,7 @@ async fn count_posts(server: &MockServer, submit_path: &str) -> usize {
/// signed message is arbitrary — only the distinct share index and identical
/// unsigned payload (so ParSigDB groups the partials) matter.
fn attester_partial(share_idx: u64, share: &pluto_crypto::types::PrivateKey) -> ParSignedData {
let sig = BlstImpl.sign(share, &[42u8; 32]).expect("sign share");
let sig = tbls::sign(share, &[42u8; 32]).expect("sign share");
let attestation = phase0::Attestation {
aggregation_bits: phase0::BitList::with_bits(8, &[0]),
data: phase0::AttestationData {
Expand Down Expand Up @@ -446,10 +446,9 @@ async fn wiring_connects_sign_path() {
// Build two real BLS partial signatures (threshold 2 of 2) over the same
// attestation so SigAgg's `threshold_aggregate` succeeds and the broadcaster
// submits.
let tbls = BlstImpl;
let mut rng = rand::thread_rng();
let secret = tbls.generate_secret_key(&mut rng).expect("secret");
let shares = tbls.threshold_split(&secret, 2, 2).expect("split");
let secret = tbls::generate_secret_key(&mut rng).expect("secret");
let shares = tbls::threshold_split(&secret, 2, 2).expect("split");
let attester_duty = Duty::new_attester_duty(SlotNumber::new(1));

let mut share_iter = shares.into_iter();
Expand Down Expand Up @@ -564,16 +563,15 @@ async fn wiring_connects_sign_path_proposer() {
.expect("wire did not deadlock")
.expect("wire succeeded");

let tbls = BlstImpl;
let mut rng = rand::thread_rng();
let secret = tbls.generate_secret_key(&mut rng).expect("secret");
let shares = tbls.threshold_split(&secret, 2, 2).expect("split");
let secret = tbls::generate_secret_key(&mut rng).expect("secret");
let shares = tbls::threshold_split(&secret, 2, 2).expect("split");

// Each partial signs an arbitrary message with its own share (permissive
// verifier), swapping only the block signature onto an identical unsigned
// block so ParSigDB's threshold-matching groups them.
let make_par = |share_idx: u64, share: &pluto_crypto::types::PrivateKey| {
let sig = tbls.sign(share, &[42u8; 32]).expect("sign");
let sig = tbls::sign(share, &[42u8; 32]).expect("sign");
pluto_core::signeddata::VersionedSignedProposal::new_partial(
phase0_proposal(sig),
share_idx,
Expand Down Expand Up @@ -638,10 +636,9 @@ async fn wiring_connects_sign_path_sync_contribution() {
.expect("wire did not deadlock")
.expect("wire succeeded");

let tbls = BlstImpl;
let mut rng = rand::thread_rng();
let secret = tbls.generate_secret_key(&mut rng).expect("secret");
let shares = tbls.threshold_split(&secret, 2, 2).expect("split");
let secret = tbls::generate_secret_key(&mut rng).expect("secret");
let shares = tbls::threshold_split(&secret, 2, 2).expect("split");

// Identical unsigned contribution across shares; each partial swaps only the
// top-level signature (`set_signature`), preserving the payload so ParSigDB
Expand All @@ -661,7 +658,7 @@ async fn wiring_connects_sign_path_sync_contribution() {
signature: [0; 96],
};
let make_par = |share_idx: u64, share: &pluto_crypto::types::PrivateKey| {
let sig = tbls.sign(share, &[42u8; 32]).expect("sign");
let sig = tbls::sign(share, &[42u8; 32]).expect("sign");
let contribution = altair::SignedContributionAndProof {
signature: sig,
..base_contribution.clone()
Expand Down Expand Up @@ -720,12 +717,11 @@ async fn wiring_rejects_bad_partial_signature() {

// Real BLS group key: the verifier parses this pubkey and verifies the
// reconstructed group signature against the beacon attester signing domain.
let tbls = BlstImpl;
let mut rng = rand::thread_rng();
let secret = tbls.generate_secret_key(&mut rng).expect("secret");
let group_pubkey_bytes = tbls.secret_to_public_key(&secret).expect("group pubkey");
let secret = tbls::generate_secret_key(&mut rng).expect("secret");
let group_pubkey_bytes = tbls::secret_to_public_key(&secret).expect("group pubkey");
let pubkey = PubKey::new(group_pubkey_bytes);
let shares = tbls.threshold_split(&secret, 2, 2).expect("split");
let shares = tbls::threshold_split(&secret, 2, 2).expect("split");

// REAL eth2 verifier (mirrors production `run`): BeaconMock serves the
// signing domain via `/eth/v1/config/spec` + `/eth/v1/beacon/genesis`.
Expand Down Expand Up @@ -769,7 +765,7 @@ async fn wiring_rejects_bad_partial_signature() {
let attester_duty = Duty::new_attester_duty(SlotNumber::new(1));

let make_par = |share_idx: u64, share: &pluto_crypto::types::PrivateKey| {
let sig = tbls.sign(share, &[42u8; 32]).expect("sign");
let sig = tbls::sign(share, &[42u8; 32]).expect("sign");
let attestation = phase0::Attestation {
signature: sig,
..base_attestation.clone()
Expand Down Expand Up @@ -996,12 +992,9 @@ async fn multinode_parsig_exchange_reaches_submission() {
}

// One real threshold-BLS keyset: N shares, any THRESHOLD reconstruct.
let tbls = BlstImpl;
let mut rng = rand::thread_rng();
let secret = tbls.generate_secret_key(&mut rng).expect("secret");
let shares = tbls
.threshold_split(&secret, N as u64, THRESHOLD)
.expect("split");
let secret = tbls::generate_secret_key(&mut rng).expect("secret");
let shares = tbls::threshold_split(&secret, N as u64, THRESHOLD).expect("split");
let attester_duty = Duty::new_attester_duty(SlotNumber::new(1));

// Each node stores its own partial internally; the router fans it out to
Expand Down
42 changes: 15 additions & 27 deletions crates/cli/src/commands/create_cluster.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ use pluto_cluster::{
};
use pluto_consensus::protocols;
use pluto_crypto::{
blst_impl::BlstImpl,
tbls::Tbls,
tbls,
types::{PrivateKey, PublicKey},
};
use pluto_eth1wrap as eth1wrap;
Expand Down Expand Up @@ -674,7 +673,6 @@ fn create_validator_registrations(
.try_into()
.map_err(|_| CreateClusterError::InvalidForkVersionLength)?;

let tbls = BlstImpl;
let mut registrations = Vec::with_capacity(secrets.len());

for (secret, fee_address) in secrets.iter().zip(fee_recipient_addresses.iter()) {
Expand All @@ -684,7 +682,7 @@ fn create_validator_registrations(
eth2util::network::fork_version_to_genesis_time(&fork_version)?
};

let pk = tbls.secret_to_public_key(secret)?;
let pk = tbls::secret_to_public_key(secret)?;

let unsigned_reg = eth2util_registration::new_message(
pk,
Expand All @@ -695,7 +693,7 @@ fn create_validator_registrations(

let sig_root = eth2util_registration::get_message_signing_root(&unsigned_reg, fork_version);

let sig = tbls.sign(secret, &sig_root)?;
let sig = tbls::sign(secret, &sig_root)?;

registrations.push(BuilderRegistration {
message: Registration {
Expand Down Expand Up @@ -855,16 +853,15 @@ fn sign_deposit_datas(
if deposit_amounts.is_empty() {
return Err(CreateClusterError::EmptyDepositAmounts);
}
let tbls = BlstImpl;
let mut dd = Vec::new();
for &deposit_amount in deposit_amounts {
let mut datas = Vec::new();
for (secret, withdrawal_addr) in secrets.iter().zip(withdrawal_addresses.iter()) {
let withdrawal_addr = eth2util::helpers::checksum_address(withdrawal_addr)?;
let pk = tbls.secret_to_public_key(secret)?;
let pk = tbls::secret_to_public_key(secret)?;
let msg = deposit::new_message(pk, &withdrawal_addr, deposit_amount, compounding)?;
let sig_root = deposit::get_message_signing_root(&msg, network)?;
let sig = tbls.sign(secret, &sig_root)?;
let sig = tbls::sign(secret, &sig_root)?;
datas.push(DepositData {
pub_key: msg.pubkey,
withdrawal_credentials: msg.withdrawal_credentials,
Expand All @@ -878,11 +875,10 @@ fn sign_deposit_datas(
}

fn generate_keys(num_validators: u64) -> Result<Vec<PrivateKey>> {
let tbls = BlstImpl;
let mut secrets = Vec::new();

for _ in 0..num_validators {
let secret = tbls.generate_secret_key(OsRng)?;
let secret = tbls::generate_secret_key(OsRng)?;
secrets.push(secret);
}

Expand Down Expand Up @@ -993,12 +989,11 @@ fn get_tss_shares(
threshold: u64,
num_nodes: u64,
) -> Result<(Vec<PublicKey>, Vec<Vec<PrivateKey>>)> {
let tbls = BlstImpl;
let mut dvs = Vec::new();
let mut splits = Vec::new();

for secret in secrets {
let shares = tbls.threshold_split(secret, num_nodes, threshold)?;
let shares = tbls::threshold_split(secret, num_nodes, threshold)?;

// Preserve order when transforming from map of private shares to array of
// private keys
Expand All @@ -1008,7 +1003,7 @@ fn get_tss_shares(

splits.push(secret_set);

let pubkey = tbls.secret_to_public_key(secret)?;
let pubkey = tbls::secret_to_public_key(secret)?;
dvs.push(pubkey);
}

Expand Down Expand Up @@ -1275,15 +1270,14 @@ fn get_validators(
}

let mut vals = Vec::with_capacity(dv_pubkeys.len());
let tbls = BlstImpl;

for (idx, dv_pubkey) in dv_pubkeys.iter().enumerate() {
let pub_shares: Vec<Vec<u8>> = dv_priv_shares
.get(idx)
.map(|shares| {
shares
.iter()
.map(|share| tbls.secret_to_public_key(share))
.map(tbls::secret_to_public_key)
.collect::<std::result::Result<Vec<_>, _>>()
})
.transpose()?
Expand Down Expand Up @@ -1320,12 +1314,11 @@ fn get_validators(
fn agg_sign(secrets: &[Vec<PrivateKey>], message: &[u8]) -> Result<Vec<u8>> {
use pluto_crypto::types::Signature;

let tbls = BlstImpl;
let mut sigs: Vec<Signature> = Vec::new();

for shares in secrets {
for share in shares {
let sig = tbls.sign(share, message)?;
let sig = tbls::sign(share, message)?;
sigs.push(sig);
}
}
Expand All @@ -1334,7 +1327,7 @@ fn agg_sign(secrets: &[Vec<PrivateKey>], message: &[u8]) -> Result<Vec<u8>> {
return Ok(Vec::new());
}

let agg = tbls.aggregate(&sigs)?;
let agg = tbls::aggregate(&sigs)?;
Ok(agg.to_vec())
}

Expand Down Expand Up @@ -1447,7 +1440,6 @@ mod tests {
lock::Lock,
version::versions::*,
};
use pluto_crypto::{blst_impl::BlstImpl, tbls::Tbls as _};
use pluto_eth1wrap::EthClient;
use pluto_eth2util::{
deposit,
Expand Down Expand Up @@ -1785,10 +1777,9 @@ mod tests {
match prep {
PrepKind::None => {}
PrepKind::SplitKeys { num_keys } => {
let tbls = BlstImpl;
let mut keys = Vec::new();
for _ in 0..num_keys {
keys.push(tbls.generate_secret_key(rand::thread_rng()).unwrap());
keys.push(tbls::generate_secret_key(rand::thread_rng()).unwrap());
}
keystore::store_keys_insecure(
&keys,
Expand Down Expand Up @@ -2094,10 +2085,9 @@ mod tests {
let split_keys_temp = TempDir::new().unwrap();

// Generate and store split keys insecurely.
let tbls_impl = BlstImpl;
let mut keys = Vec::new();
for _ in 0..num_split_keys {
keys.push(tbls_impl.generate_secret_key(rand::thread_rng()).unwrap());
keys.push(tbls::generate_secret_key(rand::thread_rng()).unwrap());
}
keystore::store_keys_insecure(&keys, split_keys_temp.path(), &CONFIRM_INSECURE_KEYS)
.await
Expand Down Expand Up @@ -2492,9 +2482,7 @@ mod tests {

const TEST_AUTH_TOKEN: &str = "api-token-test";

let tbls_impl = BlstImpl;

let original_secret = tbls_impl.generate_secret_key(rand::thread_rng()).unwrap();
let original_secret = tbls::generate_secret_key(rand::thread_rng()).unwrap();
let key_dir = TempDir::new().unwrap();
keystore::store_keys_insecure(
std::slice::from_ref(&original_secret),
Expand Down Expand Up @@ -2575,7 +2563,7 @@ mod tests {
shares.insert(u64::try_from(i + 1).unwrap(), secret);
}

let recovered = tbls_impl.recover_secret(&shares).unwrap();
let recovered = tbls::recover_secret(&shares).unwrap();
assert_eq!(recovered, original_secret);
}

Expand Down
8 changes: 3 additions & 5 deletions crates/cluster/src/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use chrono::{DateTime, Utc};
use pluto_crypto::tbls::Tbls;
use pluto_crypto::tbls;
use pluto_eth2util::helpers::{checksum_address, public_key_to_address};
use pluto_k1util::K1UtilError;
use serde::{Deserialize, Deserializer, Serializer};
Expand Down Expand Up @@ -217,15 +217,13 @@ pub fn agg_sign(
secrets: &[Vec<pluto_crypto::types::PrivateKey>],
message: &[u8],
) -> Result<pluto_crypto::types::Signature, pluto_crypto::types::Error> {
let blst = pluto_crypto::blst_impl::BlstImpl;

let sigs = secrets
.iter()
.flat_map(|shares| shares.iter())
.map(|share| blst.sign(share, message))
.map(|share| tbls::sign(share, message))
.collect::<Result<Vec<_>, _>>()?;

blst.aggregate(&sigs)
tbls::aggregate(&sigs)
}

#[cfg(test)]
Expand Down
14 changes: 7 additions & 7 deletions crates/cluster/src/lock.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::ops::Deref;

use pluto_crypto::{blst_impl::BlstImpl, tbls::Tbls, tblsconv};
use pluto_crypto::{tbls, types};
use pluto_eth1wrap::EthClient;
use pluto_eth2api::spec::phase0::{VERSION_LEN, Version};
use pluto_eth2util::registration;
Expand Down Expand Up @@ -70,7 +70,7 @@ pub enum LockError {

/// Failed to convert BLS bytes
#[error("Failed to convert BLS bytes: {0}")]
FailedToConvertBLSBytes(#[from] pluto_crypto::tblsconv::ConvError),
FailedToConvertBLSBytes(#[from] pluto_crypto::types::ConvError),

/// Failed to verify BLS signature
#[error("Failed to verify BLS signature: {0}")]
Expand Down Expand Up @@ -298,18 +298,18 @@ impl Lock {
return Err(LockError::EmptyLockAggregateSignature);
}

let signature = tblsconv::signature_from_bytes(&self.signature_aggregate)?;
let signature = types::signature_from_bytes(&self.signature_aggregate)?;

let pubkeys = self
.distributed_validators
.iter()
.flat_map(|v| v.pub_shares.iter())
.map(|share| tblsconv::pubkey_from_bytes(share))
.map(|share| types::pubkey_from_bytes(share))
.collect::<std::result::Result<Vec<_>, _>>()?;

let hash = hash_lock(self)?;

BlstImpl.verify_aggregate(&pubkeys, signature, &hash)?;
tbls::verify_aggregate(&pubkeys, signature, &hash)?;

self.verify_builder_registrations()?;
self.verify_node_signatures()
Expand Down Expand Up @@ -412,7 +412,7 @@ impl Lock {
timestamp: validator.builder_registration.message.timestamp.timestamp(),
})?;

let pubkey = tblsconv::pubkey_from_bytes(&validator.pub_key)?;
let pubkey = types::pubkey_from_bytes(&validator.pub_key)?;

let registration_message = registration::new_message(
pubkey,
Expand All @@ -424,7 +424,7 @@ impl Lock {
let signing_root =
registration::get_message_signing_root(&registration_message, fork_version);

BlstImpl.verify(
tbls::verify(
&pubkey,
signing_root.as_ref(),
&validator.builder_registration.signature,
Expand Down
Loading
Loading