Skip to content

Commit 97485de

Browse files
refactor: moving signature logic from ethlambda-types to ethlambda-crypto (#541)
## Description / Motivation porting the lean-sig based signature logic from types crate to crypto crate as mentioned [here](#531 (comment)) It is first of all a cleaner and more idiomatic approach and secondly ethlambda-types crate builds/compiles for the prover crate(zkVM prover), which also leads to dependency conflicts between leansig dependencies and the zkVM sdk dependencies being used. This port removes all leansig dependencies from the ethlambda-types ## What Changed - added a new `signature.rs` file to the crypto crate along with a extension trait `ValidatorPublicKeys` with the same methods as before, it helps in avoiding cyclic dependencies and the call sites remain the same. - removed the older `signature.rs` from the types crate and moved the `SIGNATURE_SIZE` directly to the `attestation.rs` ## Verification Checklist - [x] Ran `make fmt` - [x] Ran `make lint` (clippy with `-D warnings`) - [x] Ran `cargo test --workspace --release` — all passing --------- Co-authored-by: Pablo Deymonnaz <pdeymon@fi.uba.ar>
1 parent b990e3c commit 97485de

17 files changed

Lines changed: 58 additions & 60 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bin/ethlambda/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use cli::CliOptions;
3636
use ethlambda_blockchain::MILLISECONDS_PER_SLOT;
3737
use ethlambda_blockchain::block_builder::ProposerConfig;
3838
use ethlambda_blockchain::key_manager::ValidatorKeyPair;
39+
use ethlambda_crypto::signature::ValidatorSecretKey;
3940
use ethlambda_network_api::{InitBlockChain, InitP2P, ToBlockChainToP2PRef, ToP2PToBlockChainRef};
4041
use ethlambda_p2p::{
4142
Bootnode, P2P, PeerId, SwarmConfig, attestation_subscription_subnets, build_swarm, parse_enrs,
@@ -44,7 +45,6 @@ use ethlambda_types::primitives::{H256, HashTreeRoot as _};
4445
use ethlambda_types::{
4546
aggregator::AggregatorController,
4647
genesis::GenesisConfig,
47-
signature::ValidatorSecretKey,
4848
state::{State, ValidatorPubkeyBytes},
4949
};
5050
use eyre::WrapErr;

crates/blockchain/src/aggregation.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ use std::collections::{HashMap, HashSet};
2020
use std::time::{Duration, Instant, SystemTime};
2121

2222
use ethlambda_crypto::aggregate_mixed;
23+
use ethlambda_crypto::signature::{ValidatorPublicKey, ValidatorSignature};
2324
use ethlambda_storage::Store;
2425
use ethlambda_types::{
2526
ShortRoot,
2627
attestation::{AggregationBits, AttestationData, HashedAttestationData},
2728
block::{ByteList512KiB, SingleMessageAggregate},
2829
primitives::H256,
29-
signature::{ValidatorPublicKey, ValidatorSignature},
3030
state::Validator,
3131
};
3232
use spawned_concurrency::message::Message;
@@ -425,7 +425,7 @@ fn resolve_job(
425425
let Some(validator) = validators.get(*vid as usize) else {
426426
continue;
427427
};
428-
let Ok(pubkey) = validator.get_attestation_pubkey() else {
428+
let Ok(pubkey) = ValidatorPublicKey::from_bytes(&validator.attestation_pubkey) else {
429429
continue;
430430
};
431431
raw_by_id.insert(*vid, (pubkey, sig.clone()));
@@ -492,7 +492,10 @@ fn resolve_child_pubkeys(
492492
let participant_ids: Vec<u64> = proof.participant_indices().collect();
493493
let child_pubkeys: Vec<ValidatorPublicKey> = participant_ids
494494
.iter()
495-
.filter_map(|&vid| validators.get(vid as usize)?.get_attestation_pubkey().ok())
495+
.filter_map(|&vid| {
496+
let v = validators.get(vid as usize)?;
497+
ValidatorPublicKey::from_bytes(&v.attestation_pubkey).ok()
498+
})
496499
.collect();
497500
if child_pubkeys.len() != participant_ids.len() {
498501
warn!(
@@ -796,7 +799,7 @@ mod tests {
796799
/// never checks signature validity, only that it clones and carries a
797800
/// resolvable id — mirrors `ethlambda_storage::store::tests::make_dummy_sig`.
798801
fn dummy_sig() -> ValidatorSignature {
799-
use ethlambda_types::signature::LeanSignatureScheme;
802+
use ethlambda_crypto::signature::LeanSignatureScheme;
800803
use leansig::{serialization::Serializable, signature::SignatureScheme};
801804
use rand::{SeedableRng, rngs::StdRng};
802805

crates/blockchain/src/block_builder.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use std::{
1515
time::Instant,
1616
};
1717

18-
use ethlambda_crypto::aggregate_proofs;
18+
use ethlambda_crypto::{aggregate_proofs, signature::ValidatorPublicKey};
1919
use ethlambda_state_transition::{
2020
attestation_data_matches_chain, justified_slots_ops, process_block, process_slots,
2121
slot_is_justifiable_after,
@@ -657,11 +657,11 @@ fn compact_attestations(
657657
let pubkeys = proof
658658
.participant_indices()
659659
.map(|vid| {
660-
head_state
660+
let validator = head_state
661661
.validators
662662
.get(vid as usize)
663-
.ok_or(StoreError::InvalidValidatorIndex)?
664-
.get_attestation_pubkey()
663+
.ok_or(StoreError::InvalidValidatorIndex)?;
664+
ValidatorPublicKey::from_bytes(&validator.attestation_pubkey)
665665
.map_err(|_| StoreError::PubkeyDecodingFailed(vid))
666666
})
667667
.collect::<Result<Vec<_>, _>>()?;

crates/blockchain/src/key_manager.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use std::collections::HashMap;
22
use std::time::Instant;
33

4+
use ethlambda_crypto::signature::{ValidatorSecretKey, ValidatorSignature};
45
use ethlambda_types::{
56
attestation::{AttestationData, XmssSignature},
67
primitives::{H256, HashTreeRoot as _},
7-
signature::{ValidatorSecretKey, ValidatorSignature},
88
};
99
use tracing::{info, warn};
1010

crates/blockchain/src/lib.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::collections::{HashMap, HashSet, VecDeque};
22
use std::time::{Duration, Instant, SystemTime};
33

4+
use ethlambda_crypto::signature::{ValidatorPublicKey, ValidatorSignature};
45
use ethlambda_network_api::{BlockChainToP2PRef, InitP2P};
56
use ethlambda_state_transition::is_proposer;
67
use ethlambda_storage::{ALL_TABLES, Store};
@@ -10,7 +11,6 @@ use ethlambda_types::{
1011
attestation::{SignedAggregatedAttestation, SignedAttestation},
1112
block::{ByteList512KiB, MultiMessageAggregate, SignedBlock},
1213
primitives::{H256, HashTreeRoot as _},
13-
signature::{ValidatorPublicKey, ValidatorSignature},
1414
};
1515

1616
use crate::aggregation::{
@@ -763,7 +763,10 @@ impl BlockChainServer {
763763
// Decode the proposer's proposal pubkey once and reuse it both for the
764764
// singleton single-message aggregate wrap and for the multi-message
765765
// aggregate merge inputs.
766-
let Ok(proposer_pubkey) = proposer_validator.get_proposal_pubkey().inspect_err(
766+
let Ok(proposer_pubkey) = ValidatorPublicKey::from_bytes(
767+
&proposer_validator.proposal_pubkey,
768+
)
769+
.inspect_err(
767770
|err| error!(%slot, %validator_id, %err, "Failed to decode proposer proposal pubkey"),
768771
) else {
769772
metrics::inc_block_building_failures();
@@ -802,7 +805,7 @@ impl BlockChainServer {
802805
resolve_failed = true;
803806
break;
804807
};
805-
match validator.get_attestation_pubkey() {
808+
match ValidatorPublicKey::from_bytes(&validator.attestation_pubkey) {
806809
Ok(pk) => pubkeys.push(pk),
807810
Err(err) => {
808811
error!(%slot, %validator_id, vid, %err, "Failed to decode attestation pubkey");

crates/blockchain/src/reaggregate.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
2525
use std::collections::HashSet;
2626

27+
use ethlambda_crypto::signature::ValidatorPublicKey;
2728
use ethlambda_storage::Store;
2829
use ethlambda_types::{
2930
attestation::{
@@ -32,7 +33,6 @@ use ethlambda_types::{
3233
},
3334
block::{SignedBlock, SingleMessageAggregate},
3435
primitives::{H256, HashTreeRoot as _},
35-
signature::ValidatorPublicKey,
3636
};
3737
use tracing::{debug, warn};
3838

@@ -83,7 +83,9 @@ pub fn reaggregate_from_block(
8383
warn!(vid, "Reaggregation aborted: participant out of range");
8484
return Vec::new();
8585
}
86-
let Ok(pk) = validators[vid as usize].get_attestation_pubkey() else {
86+
let Ok(pk) =
87+
ValidatorPublicKey::from_bytes(&validators[vid as usize].attestation_pubkey)
88+
else {
8789
warn!(vid, "Reaggregation aborted: bad attestation pubkey");
8890
return Vec::new();
8991
};
@@ -94,7 +96,8 @@ pub fn reaggregate_from_block(
9496
if block.proposer_index >= num_validators {
9597
return Vec::new();
9698
}
97-
let Ok(proposer_pubkey) = validators[block.proposer_index as usize].get_proposal_pubkey()
99+
let Ok(proposer_pubkey) =
100+
ValidatorPublicKey::from_bytes(&validators[block.proposer_index as usize].proposal_pubkey)
98101
else {
99102
return Vec::new();
100103
};
@@ -161,7 +164,9 @@ pub fn reaggregate_from_block(
161164
bad = true;
162165
break;
163166
}
164-
match validators[vid as usize].get_attestation_pubkey() {
167+
match ValidatorPublicKey::from_bytes(
168+
&validators[vid as usize].attestation_pubkey,
169+
) {
165170
Ok(pk) => pubkeys.push(pk),
166171
Err(_) => {
167172
bad = true;

crates/blockchain/src/store.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::collections::{HashMap, HashSet};
22

3+
use ethlambda_crypto::signature::{ValidatorPublicKey, ValidatorSignature};
34
use ethlambda_state_transition::{is_proposer, slot_is_justifiable_after};
45
use ethlambda_storage::{ForkCheckpoints, Store};
56
use ethlambda_types::{
@@ -11,7 +12,6 @@ use ethlambda_types::{
1112
block::{Block, BlockHeader, SignedBlock, SingleMessageAggregate},
1213
checkpoint::Checkpoint,
1314
primitives::{H256, HashTreeRoot as _},
14-
signature::{ValidatorPublicKey, ValidatorSignature},
1515
state::{HISTORICAL_ROOTS_LIMIT, State},
1616
};
1717
use tracing::{info, trace, warn};
@@ -418,9 +418,10 @@ pub fn on_gossip_attestation(
418418
if validator_id >= target_state.validators.len() as u64 {
419419
return Err(StoreError::InvalidValidatorIndex);
420420
}
421-
let validator_pubkey = target_state.validators[validator_id as usize]
422-
.get_attestation_pubkey()
423-
.map_err(|_| StoreError::PubkeyDecodingFailed(validator_id))?;
421+
let validator_pubkey = ValidatorPublicKey::from_bytes(
422+
&target_state.validators[validator_id as usize].attestation_pubkey,
423+
)
424+
.map_err(|_| StoreError::PubkeyDecodingFailed(validator_id))?;
424425

425426
// Verify the validator's XMSS signature
426427
let slot: u32 = attestation.data.slot.try_into().expect("slot exceeds u32");
@@ -513,8 +514,7 @@ fn on_gossip_aggregated_attestation_core(
513514
let pubkeys: Vec<_> = participant_indices
514515
.iter()
515516
.map(|&vid| {
516-
validators[vid as usize]
517-
.get_attestation_pubkey()
517+
ValidatorPublicKey::from_bytes(&validators[vid as usize].attestation_pubkey)
518518
.map_err(|_| StoreError::PubkeyDecodingFailed(vid))
519519
})
520520
.collect::<Result<_, _>>()?;
@@ -1142,8 +1142,7 @@ pub fn verify_block_signatures(
11421142
let validator = validators
11431143
.get(vid as usize)
11441144
.ok_or(StoreError::InvalidValidatorIndex)?;
1145-
let pk = validator
1146-
.get_attestation_pubkey()
1145+
let pk = ValidatorPublicKey::from_bytes(&validator.attestation_pubkey)
11471146
.map_err(|_| StoreError::PubkeyDecodingFailed(vid))?;
11481147
pubkeys.push(pk);
11491148
}
@@ -1156,8 +1155,7 @@ pub fn verify_block_signatures(
11561155
let proposer_validator = validators
11571156
.get(block.proposer_index as usize)
11581157
.ok_or(StoreError::InvalidValidatorIndex)?;
1159-
let proposer_pubkey = proposer_validator
1160-
.get_proposal_pubkey()
1158+
let proposer_pubkey = ValidatorPublicKey::from_bytes(&proposer_validator.proposal_pubkey)
11611159
.map_err(|_| StoreError::PubkeyDecodingFailed(block.proposer_index))?;
11621160
pubkeys_per_component.push(vec![proposer_pubkey]);
11631161
let block_slot_u32 =

crates/common/crypto/src/lib.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
use std::sync::Once;
22

3-
use ethlambda_types::{
4-
block::ByteList512KiB,
5-
primitives::H256,
6-
signature::{ValidatorPublicKey, ValidatorSignature},
7-
};
3+
use ethlambda_types::{block::ByteList512KiB, primitives::H256};
4+
5+
use crate::signature::{ValidatorPublicKey, ValidatorSignature};
86
use lean_multisig::{
97
MultiMessageAggregateSignature as LMType2, ProofError,
108
SingleMessageAggregateSignature as LMType1, aggregate_single_message_signatures,
@@ -14,6 +12,8 @@ use lean_multisig::{
1412
use leansig_wrapper::{XmssPublicKey as LeanSigPubKey, XmssSignature as LeanSigSignature};
1513
use thiserror::Error;
1614

15+
pub mod signature;
16+
1717
#[cfg(feature = "shadow-integration")]
1818
pub mod shadow_cost;
1919

@@ -508,7 +508,7 @@ pub fn split_type_2_by_message(
508508
#[cfg(test)]
509509
mod tests {
510510
use super::*;
511-
use ethlambda_types::signature::LeanSignatureScheme;
511+
use crate::signature::LeanSignatureScheme;
512512
use leansig::{serialization::Serializable, signature::SignatureScheme};
513513
use rand::{SeedableRng, rngs::StdRng};
514514

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1+
//! Validator XMSS signatures, public/secret keys, and the leansig-backed
2+
//! primitives behind them.
3+
14
use std::ops::Range;
25

6+
use ethlambda_types::primitives::H256;
37
use leansig::{
48
serialization::Serializable,
59
signature::{SignatureScheme, SignatureSchemeSecretKey as _, SigningError},
610
};
711

8-
use crate::primitives::H256;
9-
1012
/// The XMSS signature scheme used for validator signatures.
1113
///
1214
/// This is a post-quantum secure signature scheme based on hash functions.
@@ -25,11 +27,6 @@ pub type LeanSigSecretKey = <LeanSignatureScheme as SignatureScheme>::SecretKey;
2527

2628
pub type Signature = LeanSigSignature;
2729

28-
/// Size of an XMSS signature in bytes.
29-
///
30-
/// Computed from: path(32*8*4) + rho(7*4) + hashes(46*8*4) + ssz_offsets(3*4) = 2536
31-
pub const SIGNATURE_SIZE: usize = 2536;
32-
3330
/// Error returned when parsing signature or key bytes fails.
3431
#[derive(Debug, Clone, thiserror::Error)]
3532
#[error("signature parse error: {0}")]

0 commit comments

Comments
 (0)