diff --git a/bin/ethlambda/src/cli.rs b/bin/ethlambda/src/cli.rs index f4f97cab..c0f09ddf 100644 --- a/bin/ethlambda/src/cli.rs +++ b/bin/ethlambda/src/cli.rs @@ -89,7 +89,7 @@ pub(crate) struct CliOptions { /// /// A block may carry at most one entry per `AttestationData`, so the /// proposer must collapse same-data proofs either way. When set, - /// `build_block` merges them via recursive Type-1 aggregation into a single + /// `build_block` merges them via recursive single-message aggregation into a single /// union-coverage proof per data (leanSpec #510), maximizing voter coverage /// at the cost of a leanVM aggregation per duplicated data entry. When unset /// (the default), it instead keeps only the single best-coverage proof per diff --git a/crates/blockchain/src/aggregation.rs b/crates/blockchain/src/aggregation.rs index 8fe3e2d2..2442aea6 100644 --- a/crates/blockchain/src/aggregation.rs +++ b/crates/blockchain/src/aggregation.rs @@ -13,7 +13,7 @@ use ethlambda_crypto::aggregate_mixed; use ethlambda_storage::Store; use ethlambda_types::{ attestation::{AggregationBits, HashedAttestationData}, - block::{ByteList512KiB, TypeOneMultiSignature}, + block::{ByteList512KiB, SingleMessageAggregate}, primitives::H256, signature::{ValidatorPublicKey, ValidatorSignature}, state::Validator, @@ -65,7 +65,7 @@ pub struct AggregationSnapshot { /// as a message payload so the store can be updated and gossip publish fired. pub struct AggregatedGroupOutput { pub(crate) hashed: HashedAttestationData, - pub(crate) proof: TypeOneMultiSignature, + pub(crate) proof: SingleMessageAggregate, pub(crate) participants: Vec, pub(crate) keys_to_delete: Vec<(u64, H256)>, } @@ -232,7 +232,7 @@ fn build_job( /// can't be fully resolved (passing fewer pubkeys than the proof expects would /// produce an invalid aggregate). fn resolve_child_pubkeys( - child_proofs: &[TypeOneMultiSignature], + child_proofs: &[SingleMessageAggregate], validators: &[Validator], ) -> (Vec<(Vec, ByteList512KiB)>, Vec) { let mut children = Vec::with_capacity(child_proofs.len()); @@ -290,7 +290,7 @@ pub fn aggregate_job(job: AggregationJob) -> Option { participants.dedup(); let aggregation_bits = aggregation_bits_from_validator_indices(&participants); - let proof = TypeOneMultiSignature::new(aggregation_bits, proof_data); + let proof = SingleMessageAggregate::new(aggregation_bits, proof_data); metrics::observe_aggregated_proof_size(proof.proof.len()); Some(AggregatedGroupOutput { @@ -328,14 +328,14 @@ pub fn finalize_aggregation_session(store: &Store) { /// no proof adds new coverage. This keeps the number of children minimal /// while maximizing the validators we can skip re-aggregating from scratch. fn select_proofs_greedily( - new_proofs: &[TypeOneMultiSignature], - known_proofs: &[TypeOneMultiSignature], -) -> (Vec, HashSet) { - let mut selected: Vec = Vec::new(); + new_proofs: &[SingleMessageAggregate], + known_proofs: &[SingleMessageAggregate], +) -> (Vec, HashSet) { + let mut selected: Vec = Vec::new(); let mut covered: HashSet = HashSet::new(); for proof_set in [new_proofs, known_proofs] { - let mut remaining: Vec<&TypeOneMultiSignature> = proof_set.iter().collect(); + let mut remaining: Vec<&SingleMessageAggregate> = proof_set.iter().collect(); while !remaining.is_empty() { let best_idx = remaining diff --git a/crates/blockchain/src/block_builder.rs b/crates/blockchain/src/block_builder.rs index 208481c2..e52b3fff 100644 --- a/crates/blockchain/src/block_builder.rs +++ b/crates/blockchain/src/block_builder.rs @@ -23,7 +23,7 @@ use ethlambda_state_transition::{ use ethlambda_types::{ ShortRoot, attestation::{AggregatedAttestation, AggregationBits, AttestationData}, - block::{AggregatedAttestations, Block, BlockBody, TypeOneMultiSignature}, + block::{AggregatedAttestations, Block, BlockBody, SingleMessageAggregate}, checkpoint::Checkpoint, primitives::{H256, HashTreeRoot as _}, state::{JustifiedSlots, State}, @@ -52,8 +52,8 @@ pub struct PostBlockCheckpoints { /// caller. /// /// The collapse strategy is gated by `enable_proposer_aggregation`: -/// - **enabled**: same-data proofs are merged via recursive Type-1 aggregation -/// into a single union-coverage proof (leanSpec #510). Maximizes voter +/// - **enabled**: same-data proofs are merged via recursive single-message +/// aggregation into a single union-coverage proof (leanSpec #510). Maximizes voter /// coverage per entry at the cost of a leanVM aggregation per duplicated /// data entry. /// - **disabled** (default): the single best-coverage proof per data is kept @@ -68,9 +68,9 @@ pub(crate) fn build_block( proposer_index: u64, parent_root: H256, known_block_roots: &HashSet, - aggregated_payloads: &HashMap)>, + aggregated_payloads: &HashMap)>, enable_proposer_aggregation: bool, -) -> Result<(Block, Vec, PostBlockCheckpoints), StoreError> { +) -> Result<(Block, Vec, PostBlockCheckpoints), StoreError> { info!(slot, proposer_index, "Building block"); let select_start = Instant::now(); @@ -88,8 +88,8 @@ pub(crate) fn build_block( // Each AttestationData may appear at most once per block (`on_block` // rejects duplicates), so same-data entries must be collapsed to one. // Gated by `enable_proposer_aggregation`: when enabled, proofs sharing an - // AttestationData are merged via recursive Type-1 aggregation into a - // union-coverage proof (leanSpec #510); when disabled, we skip that leanVM + // AttestationData are merged via recursive single-message aggregation into + // a union-coverage proof (leanSpec #510); when disabled, we skip that leanVM // work and keep only the single best-coverage proof per data. Both paths // log the entry / unique-entry counts they already compute. let compact_start = Instant::now(); @@ -151,9 +151,9 @@ fn select_attestations( slot: u64, parent_root: H256, known_block_roots: &HashSet, - aggregated_payloads: &HashMap)>, -) -> Vec<(AggregatedAttestation, TypeOneMultiSignature)> { - let mut selected: Vec<(AggregatedAttestation, TypeOneMultiSignature)> = Vec::new(); + aggregated_payloads: &HashMap)>, +) -> Vec<(AggregatedAttestation, SingleMessageAggregate)> { + let mut selected: Vec<(AggregatedAttestation, SingleMessageAggregate)> = Vec::new(); if aggregated_payloads.is_empty() { return selected; } @@ -304,7 +304,7 @@ fn pick_best_candidate( /// the chain-level facts used to filter and score entries. Built once before /// the round loop in `select_attestations`. struct ChainContext<'a> { - aggregated_payloads: &'a HashMap)>, + aggregated_payloads: &'a HashMap)>, known_block_roots: &'a HashSet, extended_historical_block_hashes: &'a [H256], validator_count: usize, @@ -380,7 +380,7 @@ fn entry_passes_filters( /// finalize and is always scored as tier 3. fn score_entry( att_data: &AttestationData, - proofs: &[TypeOneMultiSignature], + proofs: &[SingleMessageAggregate], current_votes: &HashMap>, projected_finalized_slot: u64, validator_count: usize, @@ -539,10 +539,10 @@ fn build_running_votes(state: &State) -> HashMap> { /// - Multiple entries: merged into one using recursive proof aggregation /// (leanSpec PR #510). fn compact_attestations( - entries: Vec<(AggregatedAttestation, TypeOneMultiSignature)>, + entries: Vec<(AggregatedAttestation, SingleMessageAggregate)>, head_state: &State, block_slot: u64, -) -> Result, StoreError> { +) -> Result, StoreError> { // Group indices by AttestationData, preserving first-occurrence order let mut order: Vec = Vec::new(); let mut groups: HashMap> = HashMap::new(); @@ -571,7 +571,7 @@ fn compact_attestations( ); // Wrap in Option so we can .take() items by index without cloning - let mut items: Vec> = + let mut items: Vec> = entries.into_iter().map(Some).collect(); let mut compacted = Vec::with_capacity(order.len()); @@ -585,7 +585,7 @@ fn compact_attestations( } // Collect all entries for this AttestationData - let group_items: Vec<(AggregatedAttestation, TypeOneMultiSignature)> = indices + let group_items: Vec<(AggregatedAttestation, SingleMessageAggregate)> = indices .iter() .map(|&idx| items[idx].take().expect("index used once")) .collect(); @@ -620,7 +620,7 @@ fn compact_attestations( let merged_proof_data = aggregate_proofs(children, &data_root, slot) .map_err(StoreError::SignatureAggregationFailed)?; - let merged_proof = TypeOneMultiSignature::new(merged_bits.clone(), merged_proof_data); + let merged_proof = SingleMessageAggregate::new(merged_bits.clone(), merged_proof_data); let merged_att = AggregatedAttestation { aggregation_bits: merged_bits, data, @@ -642,9 +642,9 @@ fn compact_attestations( /// and drop the rest. No leanVM aggregation runs; coverage is whatever the best /// individual proof already had, which is the cost of skipping aggregation. fn keep_best_proof_per_data( - entries: Vec<(AggregatedAttestation, TypeOneMultiSignature)>, + entries: Vec<(AggregatedAttestation, SingleMessageAggregate)>, block_slot: u64, -) -> Vec<(AggregatedAttestation, TypeOneMultiSignature)> { +) -> Vec<(AggregatedAttestation, SingleMessageAggregate)> { // Preserve first-occurrence order of distinct AttestationData; for each, // track the index of the best (most participants) entry seen so far. let mut order: Vec = Vec::new(); @@ -677,7 +677,7 @@ fn keep_best_proof_per_data( "Skipping attestation compaction" ); - let mut items: Vec> = + let mut items: Vec> = entries.into_iter().map(Some).collect(); order .iter() @@ -703,8 +703,8 @@ fn keep_best_proof_per_data( /// Each selected proof is appended to `selected` paired with its /// corresponding AggregatedAttestation. fn extend_proofs_greedily( - proofs: &[TypeOneMultiSignature], - selected: &mut Vec<(AggregatedAttestation, TypeOneMultiSignature)>, + proofs: &[SingleMessageAggregate], + selected: &mut Vec<(AggregatedAttestation, SingleMessageAggregate)>, att_data: &AttestationData, ) { if proofs.is_empty() { @@ -798,7 +798,7 @@ mod tests { use super::*; use ethlambda_types::{ attestation::{AggregatedAttestation, AggregationBits, AttestationData}, - block::{ByteList512KiB, MultiMessageAggregate, SignedBlock, TypeOneMultiSignature}, + block::{ByteList512KiB, MultiMessageAggregate, SignedBlock, SingleMessageAggregate}, checkpoint::Checkpoint, state::State, }; @@ -849,7 +849,7 @@ mod tests { }; // Supermajority (3 of 4) so the entry crosses 2/3. - let proofs = vec![TypeOneMultiSignature::empty(make_bits(&[0, 1, 2]))]; + let proofs = vec![SingleMessageAggregate::empty(make_bits(&[0, 1, 2]))]; let (score, _) = score_entry( &att_data, @@ -957,7 +957,7 @@ mod tests { // Simulate a stall: populate the payload pool with many distinct entries. // Each has a unique attestation slot and a large proof payload. - let mut aggregated_payloads: HashMap)> = + let mut aggregated_payloads: HashMap)> = HashMap::new(); for i in 0..NUM_PAYLOAD_ENTRIES { @@ -978,7 +978,7 @@ mod tests { let proof_bytes: Vec = vec![0xAB; PROOF_SIZE]; let proof_data = SszList::try_from(proof_bytes).expect("proof fits in ByteListMiB"); - let proof = TypeOneMultiSignature::new(bits, proof_data); + let proof = SingleMessageAggregate::new(bits, proof_data); aggregated_payloads.insert(data_root, (att_data, vec![proof])); } @@ -1113,11 +1113,11 @@ mod tests { }; let data_root = att_data.hash_tree_root(); let proofs = vec![ - TypeOneMultiSignature::empty(make_bits(&[0])), - TypeOneMultiSignature::empty(make_bits(&[1, 2])), + SingleMessageAggregate::empty(make_bits(&[0])), + SingleMessageAggregate::empty(make_bits(&[1, 2])), ]; - let mut aggregated_payloads: HashMap)> = + let mut aggregated_payloads: HashMap)> = HashMap::new(); aggregated_payloads.insert(data_root, (att_data.clone(), proofs)); @@ -1143,7 +1143,7 @@ mod tests { assert_eq!( signatures.len(), 1, - "one Type-1 proof per attestation entry" + "one single-message aggregate per attestation entry" ); let kept = &block.body.attestations[0]; assert_eq!( @@ -1248,7 +1248,7 @@ mod tests { for i in 0..SUPERMAJORITY { bits.set(i, true).unwrap(); } - let proof = TypeOneMultiSignature::new(bits, SszList::try_from(vec![0xAB; 64]).unwrap()); + let proof = SingleMessageAggregate::new(bits, SszList::try_from(vec![0xAB; 64]).unwrap()); let mut aggregated_payloads = HashMap::new(); aggregated_payloads.insert(data_root, (att_data.clone(), vec![proof])); @@ -1379,8 +1379,8 @@ mod tests { bits.set(i, true).unwrap(); } let proof_a = - TypeOneMultiSignature::new(bits.clone(), SszList::try_from(vec![0xAB; 64]).unwrap()); - let proof_b = TypeOneMultiSignature::new(bits, SszList::try_from(vec![0xCD; 64]).unwrap()); + SingleMessageAggregate::new(bits.clone(), SszList::try_from(vec![0xAB; 64]).unwrap()); + let proof_b = SingleMessageAggregate::new(bits, SszList::try_from(vec![0xCD; 64]).unwrap()); let mut aggregated_payloads = HashMap::new(); aggregated_payloads.insert(att_a.hash_tree_root(), (att_a.clone(), vec![proof_a])); @@ -1433,14 +1433,14 @@ mod tests { aggregation_bits: bits_a.clone(), data: data_a.clone(), }, - TypeOneMultiSignature::empty(bits_a), + SingleMessageAggregate::empty(bits_a), ), ( AggregatedAttestation { aggregation_bits: bits_b.clone(), data: data_b.clone(), }, - TypeOneMultiSignature::empty(bits_b), + SingleMessageAggregate::empty(bits_b), ), ]; @@ -1467,21 +1467,21 @@ mod tests { aggregation_bits: bits_0.clone(), data: data_a.clone(), }, - TypeOneMultiSignature::empty(bits_0), + SingleMessageAggregate::empty(bits_0), ), ( AggregatedAttestation { aggregation_bits: bits_1.clone(), data: data_b.clone(), }, - TypeOneMultiSignature::empty(bits_1), + SingleMessageAggregate::empty(bits_1), ), ( AggregatedAttestation { aggregation_bits: bits_2.clone(), data: data_c.clone(), }, - TypeOneMultiSignature::empty(bits_2), + SingleMessageAggregate::empty(bits_2), ), ]; @@ -1508,9 +1508,9 @@ mod tests { // A = {0, 1, 2, 3} (4 validators — largest, picked first) // B = {2, 3, 4} (overlaps A on {2,3} but adds validator 4) // C = {1, 2} (subset of A — adds nothing, must be skipped) - let proof_a = TypeOneMultiSignature::empty(make_bits(&[0, 1, 2, 3])); - let proof_b = TypeOneMultiSignature::empty(make_bits(&[2, 3, 4])); - let proof_c = TypeOneMultiSignature::empty(make_bits(&[1, 2])); + let proof_a = SingleMessageAggregate::empty(make_bits(&[0, 1, 2, 3])); + let proof_b = SingleMessageAggregate::empty(make_bits(&[2, 3, 4])); + let proof_c = SingleMessageAggregate::empty(make_bits(&[1, 2])); let mut selected = Vec::new(); extend_proofs_greedily(&[proof_a, proof_b, proof_c], &mut selected, &data); @@ -1543,8 +1543,8 @@ mod tests { // B's participants are a subset of A's. After picking A, B offers zero // new coverage and must not be selected (its inclusion would also // violate the disjoint invariant). - let proof_a = TypeOneMultiSignature::empty(make_bits(&[0, 1, 2, 3])); - let proof_b = TypeOneMultiSignature::empty(make_bits(&[1, 2])); + let proof_a = SingleMessageAggregate::empty(make_bits(&[0, 1, 2, 3])); + let proof_b = SingleMessageAggregate::empty(make_bits(&[1, 2])); let mut selected = Vec::new(); extend_proofs_greedily(&[proof_a, proof_b], &mut selected, &data); diff --git a/crates/blockchain/src/lib.rs b/crates/blockchain/src/lib.rs index c3ee9604..89a1a1d5 100644 --- a/crates/blockchain/src/lib.rs +++ b/crates/blockchain/src/lib.rs @@ -170,11 +170,11 @@ pub struct BlockChainServer { /// How the proposer collapses same-data attestations during block building /// (a block may carry at most one entry per `AttestationData`). When true, - /// same-data proofs are merged via recursive Type-1 aggregation into a - /// union-coverage proof (leanSpec #510); when false (the default), only the - /// single best-coverage proof per data is kept, skipping the per-data - /// leanVM aggregation. Seeded from the CLI `--enable-proposer-aggregation` - /// flag at spawn. + /// same-data proofs are merged via recursive single-message aggregation + /// into a union-coverage proof (leanSpec #510); when false (the default), + /// only the single best-coverage proof per data is kept, skipping the + /// per-data leanVM aggregation. Seeded from the CLI + /// `--enable-proposer-aggregation` flag at spawn. enable_proposer_aggregation: bool, /// Pre-merge `new_payloads` snapshot for the attestation aggregate coverage @@ -480,7 +480,8 @@ impl BlockChainServer { /// Build the target slot's block and publish it, one interval early. /// /// Runs at the previous slot's interval 4, blocking the actor for the build - /// (the expensive part is the leanVM Type-1 → Type-2 merge). It first + /// (the expensive part is the leanVM single-message → multi-message + /// aggregate merge). It first /// advances the store to the target slot's interval 0 (accepting /// attestations) so the block is built on exactly the interval-0 state a /// non-prebuilding proposer would see, then builds and publishes — aligned @@ -504,13 +505,15 @@ impl BlockChainServer { // by the idempotency guard in `on_tick`, since the store clock is already // here. let timing = metrics::time_block_building(); - let Ok((block, type_one_proofs, _post_checkpoints)) = store::produce_block_with_signatures( - &mut self.store, - slot, - validator_id, - self.enable_proposer_aggregation, - ) - .inspect_err(|err| error!(%slot, %validator_id, %err, "Failed to build block")) else { + let Ok((block, single_message_aggregates, _post_checkpoints)) = + store::produce_block_with_signatures( + &mut self.store, + slot, + validator_id, + self.enable_proposer_aggregation, + ) + .inspect_err(|err| error!(%slot, %validator_id, %err, "Failed to build block")) + else { metrics::inc_block_building_failures(); return; }; @@ -532,8 +535,9 @@ impl BlockChainServer { return; }; - // Wrap the proposer's raw XMSS signature into a singleton Type-1 SNARK, - // then merge it with every attestation Type-1 into the single Type-2. + // Wrap the proposer's raw XMSS signature into a singleton + // single-message aggregate SNARK, then merge it with every attestation + // single-message aggregate into the single multi-message aggregate. let head_state = self.store.head_state(); let validators = &head_state.validators; let Some(proposer_validator) = validators.get(validator_id as usize) else { @@ -543,7 +547,8 @@ impl BlockChainServer { }; // Decode the proposer's proposal pubkey once and reuse it both for the - // singleton Type-1 wrap and for the Type-2 merge inputs. + // singleton single-message aggregate wrap and for the multi-message + // aggregate merge inputs. let Ok(proposer_pubkey) = proposer_validator.get_proposal_pubkey().inspect_err( |err| error!(%slot, %validator_id, %err, "Failed to decode proposer proposal pubkey"), ) else { @@ -566,18 +571,18 @@ impl BlockChainServer { slot as u32, ) .inspect_err( - |err| error!(%slot, %validator_id, %err, "Failed to wrap proposer signature as Type-1"), + |err| error!(%slot, %validator_id, %err, "Failed to wrap proposer signature as single-message aggregate"), ) else { metrics::inc_block_building_failures(); return; }; let mut merge_inputs: Vec<(Vec, ByteList512KiB)> = - Vec::with_capacity(type_one_proofs.len() + 1); + Vec::with_capacity(single_message_aggregates.len() + 1); let mut resolve_failed = false; - for t1 in &type_one_proofs { + for sma in &single_message_aggregates { let mut pubkeys = Vec::new(); - for vid in t1.participant_indices() { + for vid in sma.participant_indices() { let Some(validator) = validators.get(vid as usize) else { error!(%slot, %validator_id, vid, "Participant out of range while resolving pubkeys"); resolve_failed = true; @@ -595,7 +600,7 @@ impl BlockChainServer { if resolve_failed { break; } - merge_inputs.push((pubkeys, t1.proof.clone())); + merge_inputs.push((pubkeys, sma.proof.clone())); } if resolve_failed { metrics::inc_block_building_failures(); @@ -603,7 +608,7 @@ impl BlockChainServer { } merge_inputs.push((vec![proposer_pubkey], proposer_proof_bytes)); - // Merge yields raw lean-multisig Type-2 bytes. Per-component + // Merge yields raw lean-multisig type-2 bytes. Per-component // participants are rederived at verify time from // `block.body.attestations[i].aggregation_bits` plus // `block.proposer_index`, so nothing else needs persisting. @@ -817,8 +822,9 @@ impl BlockChainServer { "Block imported successfully" ); - // Recover per-attestation Type-1 proofs from the block's - // merged Type-2 and fold them into the local pool. Only + // Recover per-attestation single-message aggregates from the + // block's merged multi-message aggregate and fold them into the + // local pool. Only // run when the chain is in sync — backfilling nodes must // not spam gossip with rederived aggregates. if self.sync_status.duties_allowed() { diff --git a/crates/blockchain/src/reaggregate.rs b/crates/blockchain/src/reaggregate.rs index 082e0050..58bfd34d 100644 --- a/crates/blockchain/src/reaggregate.rs +++ b/crates/blockchain/src/reaggregate.rs @@ -1,6 +1,6 @@ -//! Reaggregate-from-block: recover per-attestation Type-1 proofs from a -//! freshly imported block's merged Type-2 proof and fold them into the local -//! aggregated-payload pool. +//! Reaggregate-from-block: recover per-attestation single-message aggregates +//! from a freshly imported block's merged multi-message aggregate proof and +//! fold them into the local aggregated-payload pool. //! //! Mirrors leanSpec PR #717 `SyncService._deconstruct_block_into_store`. //! Required for catching-up nodes (and aggregators) to surface block-borne @@ -30,18 +30,18 @@ use ethlambda_types::{ AggregatedAttestation, HashedAttestationData, SignedAggregatedAttestation, validator_indices, }, - block::{SignedBlock, TypeOneMultiSignature}, + block::{SignedBlock, SingleMessageAggregate}, primitives::{H256, HashTreeRoot as _}, signature::ValidatorPublicKey, }; use tracing::{debug, warn}; -/// Maximum number of attestations whose Type-1 we will SNARK-split out of +/// Maximum number of attestations whose single-message aggregate we will SNARK-split out of /// any single imported block. Each split runs a fresh recursive SNARK /// (~hundreds of ms) so the cap keeps block-import latency predictable. pub const MAX_REAGGREGATIONS_PER_BLOCK: usize = 4; -/// Recover per-attestation Type-1 proofs from a freshly imported block. +/// Recover per-attestation single-message aggregates from a freshly imported block. /// /// Returns the combined aggregates that gained new validator coverage; the /// caller publishes them on gossip when this node acts as an aggregator. @@ -58,8 +58,9 @@ pub fn reaggregate_from_block( return Vec::new(); } - // The Type-2 proof was built against the parent state's validator set. - // Without it we cannot resolve the pubkey layout the SNARK was bound to. + // The multi-message aggregate proof was built against the parent state's + // validator set. Without it we cannot resolve the pubkey layout the SNARK + // was bound to. let Some(parent_state) = store.get_state(&block.parent_root) else { debug!( block_root = %ethlambda_types::ShortRoot(&block.hash_tree_root().0), @@ -107,7 +108,7 @@ pub fn reaggregate_from_block( // Run the splits and merges. A failure on one attestation is logged // and skipped — partial progress still surfaces useful aggregates. let mut aggregates: Vec = Vec::with_capacity(candidates.len()); - let mut store_inserts: Vec<(HashedAttestationData, TypeOneMultiSignature)> = + let mut store_inserts: Vec<(HashedAttestationData, SingleMessageAggregate)> = Vec::with_capacity(candidates.len()); for candidate in candidates { @@ -119,7 +120,7 @@ pub fn reaggregate_from_block( }; // Step 1: SNARK-split this attestation's component out of the block's - // merged Type-2 proof. + // merged multi-message aggregate proof. let merged_bytes = signed_block.proof.proof_bytes(); let split_bytes = match ethlambda_crypto::split_type_2_by_message( merged_bytes, @@ -133,15 +134,15 @@ pub fn reaggregate_from_block( continue; } }; - let block_t1 = - TypeOneMultiSignature::new(att.aggregation_bits.clone(), split_bytes.clone()); + let block_single_message_aggregate = + SingleMessageAggregate::new(att.aggregation_bits.clone(), split_bytes.clone()); // Step 2: merge the split with local partials covering the same // AttestationData so the combined proof binds every known signer. // A child-only merge needs ≥ 2 children; if we only have the // block proof, use it as-is. let combined = if candidate.local_partials.is_empty() { - block_t1 + block_single_message_aggregate } else { let mut children: Vec<(Vec, _)> = Vec::with_capacity(1 + candidate.local_partials.len()); @@ -151,7 +152,7 @@ pub fn reaggregate_from_block( let block_att_pubkeys = pubkeys_per_component[candidate.idx].clone(); children.push((block_att_pubkeys, split_bytes)); - // Remaining children: local partial Type-1s for the same data. + // Remaining children: local partial single-message aggregates for the same data. let mut bad = false; for partial in &candidate.local_partials { let mut pubkeys = Vec::with_capacity(partial.participants.count_ones()); @@ -202,7 +203,7 @@ pub fn reaggregate_from_block( .set(*vid as usize, true) .expect("vid within union bitfield length"); } - TypeOneMultiSignature::new(union_bits, merged_bytes) + SingleMessageAggregate::new(union_bits, merged_bytes) }; let hashed = HashedAttestationData::new(att.data.clone()); @@ -227,7 +228,7 @@ struct Candidate { idx: usize, data_root: H256, new_validators: usize, - local_partials: Vec, + local_partials: Vec, } /// Identify attestations from a freshly imported block worth SNARK-splitting. @@ -254,7 +255,7 @@ fn select_candidates(store: &Store, attestations: &[AggregatedAttestation]) -> V if block_participants.is_subset(&local_union) { continue; } - let mut local: Vec = new; + let mut local: Vec = new; local.extend(known); candidates.push(Candidate { idx, @@ -331,8 +332,8 @@ mod tests { let mut store = empty_store(); let att = make_att(2, 2, &[0, 1]); let hashed = HashedAttestationData::new(att.data.clone()); - // Seed the new-payload pool with a Type-1 covering validators {0, 1}. - store.insert_new_aggregated_payload(hashed, TypeOneMultiSignature::empty(bits(&[0, 1]))); + // Seed the new-payload pool with a single-message aggregate covering validators {0, 1}. + store.insert_new_aggregated_payload(hashed, SingleMessageAggregate::empty(bits(&[0, 1]))); let candidates = select_candidates(&store, &[att]); assert!(candidates.is_empty()); } @@ -343,7 +344,7 @@ mod tests { let att = make_att(2, 2, &[0, 1, 2]); let hashed = HashedAttestationData::new(att.data.clone()); // Local pool only covers validator 0. - store.insert_new_aggregated_payload(hashed, TypeOneMultiSignature::empty(bits(&[0]))); + store.insert_new_aggregated_payload(hashed, SingleMessageAggregate::empty(bits(&[0]))); let candidates = select_candidates(&store, &[att]); assert_eq!(candidates.len(), 1); // 1 and 2 are uncovered, so new_validators = 2. diff --git a/crates/blockchain/src/store.rs b/crates/blockchain/src/store.rs index f4799797..4ac2a428 100644 --- a/crates/blockchain/src/store.rs +++ b/crates/blockchain/src/store.rs @@ -8,7 +8,7 @@ use ethlambda_types::{ Attestation, AttestationData, HashedAttestationData, SignedAggregatedAttestation, SignedAttestation, validator_indices, }, - block::{Block, BlockHeader, SignedBlock, TypeOneMultiSignature}, + block::{Block, BlockHeader, SignedBlock, SingleMessageAggregate}, checkpoint::Checkpoint, primitives::{H256, HashTreeRoot as _}, signature::{ValidatorPublicKey, ValidatorSignature}, @@ -790,7 +790,7 @@ pub fn produce_block_with_signatures( slot: u64, validator_index: u64, enable_proposer_aggregation: bool, -) -> Result<(Block, Vec, PostBlockCheckpoints), StoreError> { +) -> Result<(Block, Vec, PostBlockCheckpoints), StoreError> { // Get parent block and state to build upon let head_root = get_proposal_head(store, slot); let head_state = store @@ -952,7 +952,7 @@ pub enum StoreError { TooManyAttestationData { count: usize, max: usize }, } -/// Full verification of a signed block's merged Type-2 proof. +/// Full verification of a signed block's merged multi-message aggregate proof. /// /// Structural pre-checks (fast fail) ensure the merged proof's `info` list lines /// up with the block body (one entry per attestation plus a trailing proposer @@ -994,7 +994,7 @@ pub fn verify_block_signatures( let block_root = block.hash_tree_root(); let structural_elapsed = total_start.elapsed(); - // Resolve pubkeys per Type-2 component for verify_type_2 and rederive the + // Resolve pubkeys per multi-message aggregate component for verify_type_2 and rederive the // expected (message, slot) bindings from the block body. Attestation // components use each participant's attestation_pubkey; the trailing // proposer component uses the proposal_pubkey of `block.proposer_index`. @@ -1049,7 +1049,7 @@ pub fn verify_block_signatures( ?structural_elapsed, ?crypto_elapsed, ?total_elapsed, - "Block Type-2 proof verified" + "Block multi-message aggregate proof verified" ); Ok(()) @@ -1108,7 +1108,7 @@ mod tests { attestation::{AggregatedAttestation, AggregationBits, AttestationData}, block::{ AggregatedAttestations, BlockBody, MultiMessageAggregate, SignedBlock, - TypeOneMultiSignature, + SingleMessageAggregate, }, checkpoint::Checkpoint, state::State, @@ -1122,7 +1122,7 @@ mod tests { /// `verify_block_signatures` use an empty blob. fn make_signed_block_proof( _proposer_index: u64, - _attestation_proofs: Vec, + _attestation_proofs: Vec, ) -> MultiMessageAggregate { MultiMessageAggregate::default() } @@ -1194,8 +1194,8 @@ mod tests { let proof = make_signed_block_proof( 0, vec![ - TypeOneMultiSignature::empty(bits_a), - TypeOneMultiSignature::empty(bits_b), + SingleMessageAggregate::empty(bits_a), + SingleMessageAggregate::empty(bits_b), ], ); let signed_block = SignedBlock { diff --git a/crates/blockchain/tests/forkchoice_spectests.rs b/crates/blockchain/tests/forkchoice_spectests.rs index fb4bfb7a..0e1f2e9b 100644 --- a/crates/blockchain/tests/forkchoice_spectests.rs +++ b/crates/blockchain/tests/forkchoice_spectests.rs @@ -10,7 +10,7 @@ use ethlambda_types::{ attestation::{ AttestationData, HashedAttestationData, SignedAggregatedAttestation, SignedAttestation, }, - block::{Block, TypeOneMultiSignature}, + block::{Block, SingleMessageAggregate}, primitives::{ByteList, H256, HashTreeRoot as _}, state::{State, anchor_pair_is_consistent}, }; @@ -109,10 +109,11 @@ fn run(path: &Path) -> datatest_stable::Result<()> { let import_ok = result.is_ok(); assert_step_outcome(step_idx, step.valid, result)?; - // Deconstruct the imported block into per-attestation Type-1s, - // mirroring the node's post-import reaggregation. The real node - // SNARK-splits the block's merged Type-2 proof and folds the - // recovered Type-1s into the pool so block-borne votes carry + // Deconstruct the imported block into per-attestation + // single-message aggregates, mirroring the node's post-import + // reaggregation. The real node SNARK-splits the block's merged + // multi-message aggregate proof and folds the recovered + // single-message aggregates into the pool so block-borne votes carry // fork-choice weight; leanSpec's fork-choice harness gets the // same effect by simulating the proposer build. Fixture blocks // are blank (no real proof to split), so reconstruct structurally @@ -122,14 +123,14 @@ fn run(path: &Path) -> datatest_stable::Result<()> { // the fixtures encode. if import_ok { let block = block_data.to_block(); - let entries: Vec<(HashedAttestationData, TypeOneMultiSignature)> = block + let entries: Vec<(HashedAttestationData, SingleMessageAggregate)> = block .body .attestations .iter() .map(|att| { ( HashedAttestationData::new(att.data.clone()), - TypeOneMultiSignature::empty(att.aggregation_bits.clone()), + SingleMessageAggregate::empty(att.aggregation_bits.clone()), ) }) .collect(); @@ -188,7 +189,7 @@ fn run(path: &Path) -> datatest_stable::Result<()> { .expect("aggregated proof data fits in ByteList512KiB"); let data: AttestationData = att_data.data.into(); let proof = - TypeOneMultiSignature::new(proof_fixture.participants.into(), proof_data); + SingleMessageAggregate::new(proof_fixture.participants.into(), proof_data); let aggregated = SignedAggregatedAttestation { data, proof }; let result = if proofs_are_mocked { diff --git a/crates/common/test-fixtures/src/fork_choice.rs b/crates/common/test-fixtures/src/fork_choice.rs index 1cda6280..f7a07466 100644 --- a/crates/common/test-fixtures/src/fork_choice.rs +++ b/crates/common/test-fixtures/src/fork_choice.rs @@ -119,8 +119,8 @@ pub struct AttestationStepData { /// steps (leanSpec PR #717 schema). /// /// `participants` arrives as `{ data: [bool, ...] }` and `proof` as -/// `{ data: "0x" }`; the latter is the lean-multisig Type-1 -/// `compress_without_pubkeys()` bytes for that AttestationData. +/// `{ data: "0x" }`; the latter is the lean-multisig single-message +/// aggregate `compress_without_pubkeys()` bytes for that AttestationData. #[derive(Debug, Clone, Deserialize)] pub struct ProofStepData { pub participants: AggregationBits, diff --git a/crates/common/test-fixtures/src/verify_signatures.rs b/crates/common/test-fixtures/src/verify_signatures.rs index 9793ee5c..4c25b3b7 100644 --- a/crates/common/test-fixtures/src/verify_signatures.rs +++ b/crates/common/test-fixtures/src/verify_signatures.rs @@ -8,7 +8,7 @@ //! //! signedBlock: //! block: {...standard block fields...} -//! proof: { proof: { data: "0x" } } +//! proof: { proof: { data: "0x" } } use crate::{Block, TestInfo, TestState}; use ethlambda_types::block::{MultiMessageAggregate, SignedBlock}; @@ -54,7 +54,8 @@ pub struct VerifySignaturesTest { pub info: TestInfo, } -/// Fixture-side signed block: a block plus its raw merged Type-2 proof bytes. +/// Fixture-side signed block: a block plus its raw merged multi-message +/// aggregate proof bytes. #[derive(Debug, Clone, Deserialize)] pub struct TestSignedBlock { #[serde(alias = "message")] @@ -62,7 +63,8 @@ pub struct TestSignedBlock { pub proof: MergedProof, } -/// Merged Type-2 proof container for `SignedBlock.proof` (leanSpec PR #799). +/// Merged multi-message aggregate proof container for `SignedBlock.proof` +/// (leanSpec PR #799). /// /// The multi-signature container nests the raw lean-multisig wire one level /// deep: `{ "proof": { "data": "0x..." } }`. @@ -124,7 +126,7 @@ impl From for SignedBlock { impl TestSignedBlock { /// Materialize a `SignedBlock` preserving the fixture-supplied merged - /// Type-2 proof bytes verbatim. + /// multi-message aggregate proof bytes verbatim. /// /// The container carries the raw lean-multisig wire in the /// `MultiMessageAggregate` stored by `SignedBlock.proof`. diff --git a/crates/common/types/src/attestation.rs b/crates/common/types/src/attestation.rs index 4b2206e3..0d68addb 100644 --- a/crates/common/types/src/attestation.rs +++ b/crates/common/types/src/attestation.rs @@ -4,7 +4,7 @@ use libssz_types::{SszBitlist, SszVector}; use serde::{Serialize, Serializer}; use crate::{ - block::TypeOneMultiSignature, + block::SingleMessageAggregate, checkpoint::Checkpoint, primitives::{H256, HashTreeRoot as _}, signature::SIGNATURE_SIZE, @@ -148,13 +148,13 @@ pub fn bits_is_subset(a: &AggregationBits, b: &AggregationBits) -> bool { /// Aggregated attestation with its signature proof, used for gossip on the aggregation topic. /// -/// The `proof` carries a Type-1 single-message multi-signer aggregate: the -/// signed message is the attestation data root, participants live in +/// The `proof` carries a single-message multi-signer aggregate: the signed +/// message is the attestation data root, participants live in /// `proof.participants`, and the raw aggregate bytes are in `proof.proof`. #[derive(Debug, Clone, SszEncode, SszDecode, HashTreeRoot)] pub struct SignedAggregatedAttestation { pub data: AttestationData, - pub proof: TypeOneMultiSignature, + pub proof: SingleMessageAggregate, } /// Attestation data paired with its precomputed tree hash root. diff --git a/crates/common/types/src/block.rs b/crates/common/types/src/block.rs index 7a71140e..5c5508a2 100644 --- a/crates/common/types/src/block.rs +++ b/crates/common/types/src/block.rs @@ -41,12 +41,16 @@ impl core::fmt::Debug for SignedBlock { } } -/// 512 KiB byte-list cap shared by every block-level / Type-1 proof field. -/// Matches leanSpec PR #717's `ByteList512KiB` SSZ container. +/// 512 KiB byte-list cap shared by every block-level / single-message +/// aggregate proof field. Matches leanSpec PR #717's `ByteList512KiB` SSZ +/// container. pub type ByteList512KiB = ByteList<524_288>; /// A merged proof covering multiple messages with a single proof blob. /// +/// Also known as a *type-2* proof: the lean-multisig term for an aggregate +/// binding several distinct messages, each with its own participant set. +/// /// The proof bytes use lean-multisig's compact public-key-free /// representation. SSZ encoding this container adds the offset required for /// its variable-length field. @@ -85,16 +89,16 @@ pub enum MultiMessageAggregateError { } // ============================================================================ -// Type-1 multi-signature +// Single-message aggregate // ============================================================================ // -// Wire format mirrors leanSpec PR #717: `TypeOneMultiSignature` is a flat +// Wire format mirrors leanSpec PR #717: `SingleMessageAggregate` is a flat // `{ participants, proof }` pair. The signed `message` and `slot` are NOT // carried on the envelope — verifiers rederive each component's binding // from the surrounding block body (attestation `data` + slot for body // components, block root + slot for the proposer component). // -// `MultiMessageAggregate` carries the raw lean-multisig Type-2 bytes. +// `MultiMessageAggregate` carries the raw lean-multisig type-2 bytes. // Component participant bitfields come from // `block.body.attestations[i].aggregation_bits` (and `block.proposer_index` for // the trailing proposer entry). @@ -104,7 +108,10 @@ pub enum MultiMessageAggregateError { /// `ethlambda-test-fixtures`, and the wire types in this crate. pub const MAX_ATTESTATIONS_DATA: usize = 8; -/// A Type-1 single-message proof aggregating signatures from many validators. +/// A single-message proof aggregating signatures from many validators. +/// +/// Also known as a *type-1* proof: the lean-multisig term for an aggregate +/// where every participant signs the same message for the same slot. /// /// Used: /// - as a gossip-level `SignedAggregatedAttestation.proof`, @@ -117,15 +124,16 @@ pub const MAX_ATTESTATIONS_DATA: usize = 8; /// the bitfield identifying which validators are bound by the proof. The /// verifier resolves pubkeys from `participants` at verify time. #[derive(Debug, Clone, SszEncode, SszDecode, HashTreeRoot)] -pub struct TypeOneMultiSignature { +pub struct SingleMessageAggregate { /// Bitfield identifying validators bound by this proof. pub participants: AggregationBits, /// Aggregated proof bytes in lean-multisig compact (no-pubkeys) form. pub proof: ByteList512KiB, } -impl TypeOneMultiSignature { - /// Build a Type-1 proof carrying the given participants and proof bytes. +impl SingleMessageAggregate { + /// Build a single-message aggregate carrying the given participants and + /// proof bytes. pub fn new(participants: AggregationBits, proof: ByteList512KiB) -> Self { Self { participants, @@ -133,19 +141,20 @@ impl TypeOneMultiSignature { } } - /// Build a Type-1 proof carrying the given participants and EMPTY proof - /// bytes. Useful as a placeholder in fork-choice payload caches where only - /// the participant set is needed; cannot drive a real Type-2 merge or - /// pass cryptographic verification. + /// Build a single-message aggregate carrying the given participants and + /// EMPTY proof bytes. Useful as a placeholder in fork-choice payload caches + /// where only the participant set is needed; cannot drive a real + /// multi-message aggregate merge or pass cryptographic verification. pub fn empty(participants: AggregationBits) -> Self { Self::new(participants, SszList::new()) } - /// Wrap a proposer's Type-1 proof bytes with the singleton participant set. + /// Wrap a proposer's single-message aggregate proof bytes with the + /// singleton participant set. /// - /// The bytes must be a real aggregated Type-1 over the proposer's XMSS - /// signature (e.g. from `ethlambda_crypto::aggregate_signatures`), not - /// raw XMSS bytes — `verify_type_2` rejects raw-XMSS placeholders. + /// The bytes must be a real aggregate over the proposer's XMSS signature + /// (e.g. from `ethlambda_crypto::aggregate_signatures`), not raw XMSS + /// bytes — `verify_type_2` rejects raw-XMSS placeholders. pub fn for_proposer(proposer_index: u64, proposer_proof_bytes: ByteList512KiB) -> Self { let mut participants = AggregationBits::with_length(proposer_index as usize + 1) .expect("validator index fits"); @@ -275,14 +284,14 @@ mod tests { } #[test] - fn type_one_multi_signature_ssz_round_trip() { + fn single_message_aggregate_ssz_round_trip() { let proof_bytes: Vec = (0..64).collect(); - let sig = TypeOneMultiSignature { + let sig = SingleMessageAggregate { participants: sample_bits(8, &[0, 3, 7]), proof: ByteList512KiB::try_from(proof_bytes.clone()).unwrap(), }; let bytes = sig.to_ssz(); - let decoded = TypeOneMultiSignature::from_ssz_bytes(&bytes).expect("decode"); + let decoded = SingleMessageAggregate::from_ssz_bytes(&bytes).expect("decode"); assert_eq!(decoded.proof.to_vec(), proof_bytes); assert_eq!(decoded.participants.as_bytes(), sig.participants.as_bytes()); } diff --git a/crates/common/types/tests/ssz_spectests.rs b/crates/common/types/tests/ssz_spectests.rs index 8cdb877c..ec318b90 100644 --- a/crates/common/types/tests/ssz_spectests.rs +++ b/crates/common/types/tests/ssz_spectests.rs @@ -63,18 +63,19 @@ fn run_ssz_test(test: &SszTestCase) -> datatest_stable::Result<()> { ethlambda_types::attestation::SignedAttestation, >(test), - // Skipped pending fixture regeneration against the Type-1 / Type-2 - // schema (anshalshukla/leanSpec@0ab09dd). Phase 3 removed the legacy + // Skipped pending fixture regeneration against the single-message / + // multi-message aggregate schema (anshalshukla/leanSpec@0ab09dd). Phase 3 + // removed the legacy // `BlockSignatures` / `AttestationSignatures` / `AggregatedSignatureProof` // containers; the on-disk fixtures still serialise the old shape so // SSZ-byte and root assertions don't line up. - // TODO(type1-type2): re-enable once `LEAN_SPEC_COMMIT_HASH` is bumped. + // TODO(aggregate-schema): re-enable once `LEAN_SPEC_COMMIT_HASH` is bumped. "SignedBlock" | "BlockSignatures" | "AggregatedSignatureProof" | "SignedAggregatedAttestation" => { println!( - " Skipping {} (Type-2 schema migration WIP)", + " Skipping {} (multi-message aggregate schema migration WIP)", test.type_name ); Ok(()) diff --git a/crates/common/types/tests/ssz_types.rs b/crates/common/types/tests/ssz_types.rs index aaf6d350..7e512b56 100644 --- a/crates/common/types/tests/ssz_types.rs +++ b/crates/common/types/tests/ssz_types.rs @@ -131,4 +131,4 @@ impl From for DomainSignedAttestation { // for `SignedBlock`, `BlockSignatures`, `AggregatedSignatureProof`, and // `SignedAggregatedAttestation` are intentionally skipped in // `ssz_spectests.rs::run_ssz_test` until the fixture commit is bumped to the -// Type-1/Type-2 schema. +// single-message / multi-message aggregate schema. diff --git a/crates/net/rpc/src/test_driver.rs b/crates/net/rpc/src/test_driver.rs index c963d1ff..e727d756 100644 --- a/crates/net/rpc/src/test_driver.rs +++ b/crates/net/rpc/src/test_driver.rs @@ -42,7 +42,7 @@ use ethlambda_types::{ attestation::{ AggregationBits as EthAggregationBits, SignedAggregatedAttestation, SignedAttestation, }, - block::{Block, ByteList512KiB, TypeOneMultiSignature}, + block::{Block, ByteList512KiB, SingleMessageAggregate}, checkpoint::Checkpoint, primitives::H256, state::{State, anchor_pair_is_consistent}, @@ -394,7 +394,7 @@ fn apply_step(store: &mut Store, step: ForkChoiceStep) -> Result<(), String> { .map_err(|err| format!("aggregated proof data too large: {err:?}"))?; let data: ethlambda_types::attestation::AttestationData = att.data.into(); let aggregated = SignedAggregatedAttestation { - proof: TypeOneMultiSignature::new(participants, proof_data), + proof: SingleMessageAggregate::new(participants, proof_data), data, }; store::on_gossip_aggregated_attestation(store, aggregated).map_err(|e| e.to_string()) diff --git a/crates/storage/src/store.rs b/crates/storage/src/store.rs index 747d66dc..c916bfca 100644 --- a/crates/storage/src/store.rs +++ b/crates/storage/src/store.rs @@ -10,7 +10,7 @@ use crate::error::Error; use ethlambda_types::{ attestation::{AggregationBits, AttestationData, HashedAttestationData, bits_is_subset}, block::{ - Block, BlockBody, BlockHeader, MultiMessageAggregate, SignedBlock, TypeOneMultiSignature, + Block, BlockBody, BlockHeader, MultiMessageAggregate, SignedBlock, SingleMessageAggregate, }, checkpoint::Checkpoint, primitives::{H256, HashTreeRoot as _}, @@ -131,14 +131,14 @@ const GOSSIP_SIGNATURE_CAP: usize = 2048; #[derive(Clone)] struct PayloadEntry { data: AttestationData, - proofs: Vec, + proofs: Vec, } /// Fixed-size circular buffer for aggregated payloads. /// /// Groups proofs by attestation data (via data_root). Each distinct /// attestation message stores the full `AttestationData` plus all -/// `TypeOneMultiSignature`s covering that message. +/// `SingleMessageAggregate`s covering that message. /// /// Entries are evicted FIFO (by insertion order of the data_root) /// when the buffer reaches capacity. @@ -169,7 +169,7 @@ impl PayloadBuffer { /// any existing proof, the incoming proof is redundant and skipped. /// - Otherwise, any existing proof whose participants are a strict subset /// of the incoming proof's is removed before inserting. - fn push(&mut self, hashed: HashedAttestationData, proof: TypeOneMultiSignature) { + fn push(&mut self, hashed: HashedAttestationData, proof: SingleMessageAggregate) { let (data_root, att_data) = hashed.into_parts(); if let Some(entry) = self.data.get_mut(&data_root) { @@ -218,7 +218,7 @@ impl PayloadBuffer { } /// Insert a batch of (hashed_attestation_data, proof) entries. - fn push_batch(&mut self, entries: Vec<(HashedAttestationData, TypeOneMultiSignature)>) { + fn push_batch(&mut self, entries: Vec<(HashedAttestationData, SingleMessageAggregate)>) { for (hashed, proof) in entries { self.push(hashed, proof); } @@ -230,7 +230,7 @@ impl PayloadBuffer { /// like `promote_new_aggregated_payloads` re-insert into known_payloads /// deterministically. HashMap iteration would be RandomState-seeded and /// produce non-deterministic vote ordering for same-slot equivocation. - fn drain(&mut self) -> Vec<(HashedAttestationData, TypeOneMultiSignature)> { + fn drain(&mut self) -> Vec<(HashedAttestationData, SingleMessageAggregate)> { self.total_proofs = 0; let mut result = Vec::with_capacity(self.data.values().map(|e| e.proofs.len()).sum()); while let Some(data_root) = self.order.pop_front() { @@ -254,7 +254,7 @@ impl PayloadBuffer { } /// Return cloned proofs for a given data_root, or empty vec if none. - fn proofs_for_root(&self, data_root: &H256) -> Vec { + fn proofs_for_root(&self, data_root: &H256) -> Vec { self.data .get(data_root) .map_or_else(Vec::new, |e| e.proofs.clone()) @@ -1313,7 +1313,7 @@ impl Store { /// Returns a snapshot of known payloads as (AttestationData, Vec) pairs. pub fn known_aggregated_payloads( &self, - ) -> HashMap)> { + ) -> HashMap)> { let buf = self.known_payloads.lock().unwrap(); buf.data .iter() @@ -1348,7 +1348,7 @@ impl Store { pub fn existing_proofs_for_data( &self, data_root: &H256, - ) -> (Vec, Vec) { + ) -> (Vec, Vec) { let new = self.new_payloads.lock().unwrap().proofs_for_root(data_root); let known = self .known_payloads @@ -1370,7 +1370,7 @@ impl Store { pub fn insert_known_aggregated_payload( &mut self, hashed: HashedAttestationData, - proof: TypeOneMultiSignature, + proof: SingleMessageAggregate, ) { self.known_payloads.lock().unwrap().push(hashed, proof); } @@ -1378,7 +1378,7 @@ impl Store { /// Batch-insert proofs into the known buffer. pub fn insert_known_aggregated_payloads_batch( &mut self, - entries: Vec<(HashedAttestationData, TypeOneMultiSignature)>, + entries: Vec<(HashedAttestationData, SingleMessageAggregate)>, ) { self.known_payloads.lock().unwrap().push_batch(entries); } @@ -1392,7 +1392,7 @@ impl Store { pub fn insert_new_aggregated_payload( &mut self, hashed: HashedAttestationData, - proof: TypeOneMultiSignature, + proof: SingleMessageAggregate, ) { self.new_payloads.lock().unwrap().push(hashed, proof); } @@ -1400,7 +1400,7 @@ impl Store { /// Batch-insert proofs into the new buffer. pub fn insert_new_aggregated_payloads_batch( &mut self, - entries: Vec<(HashedAttestationData, TypeOneMultiSignature)>, + entries: Vec<(HashedAttestationData, SingleMessageAggregate)>, ) { self.new_payloads.lock().unwrap().push_batch(entries); } @@ -1541,7 +1541,7 @@ fn write_signed_block( .expect("put block body"); } - // Store the merged Type-2 proof blob, keyed by slot||root so signature + // Store the merged multi-message aggregate proof blob, keyed by slot||root so signature // pruning can scan in slot order and stop early. Table name kept for the // column-family migration cost; renaming to `BlockProof` is a follow-up. let proof_entries = vec![(encode_slot_root_key(header.slot, root), proof.to_ssz())]; @@ -1842,28 +1842,28 @@ mod tests { // ============ PayloadBuffer Tests ============ - fn make_proof() -> TypeOneMultiSignature { + fn make_proof() -> SingleMessageAggregate { use ethlambda_types::attestation::AggregationBits; - TypeOneMultiSignature::empty(AggregationBits::new()) + SingleMessageAggregate::empty(AggregationBits::new()) } /// Create a proof with a specific validator bit set (distinct participants). - fn make_proof_for_validator(vid: usize) -> TypeOneMultiSignature { + fn make_proof_for_validator(vid: usize) -> SingleMessageAggregate { use ethlambda_types::attestation::AggregationBits; let mut bits = AggregationBits::with_length(vid + 1).unwrap(); bits.set(vid, true).unwrap(); - TypeOneMultiSignature::empty(bits) + SingleMessageAggregate::empty(bits) } /// Create a proof with bits set for every validator in `vids`. - fn make_proof_for_validators(vids: &[u64]) -> TypeOneMultiSignature { + fn make_proof_for_validators(vids: &[u64]) -> SingleMessageAggregate { use ethlambda_types::attestation::AggregationBits; let max = vids.iter().copied().max().unwrap_or(0) as usize; let mut bits = AggregationBits::with_length(max + 1).unwrap(); for &v in vids { bits.set(v as usize, true).unwrap(); } - TypeOneMultiSignature::empty(bits) + SingleMessageAggregate::empty(bits) } fn make_att_data(slot: u64) -> AttestationData {