From fb655ffd44fabcec610cff2b10261d67e2f4f94b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Fran=C3=A7a?= Date: Wed, 11 Dec 2024 17:06:03 +0000 Subject: [PATCH] Removed attester set from genesis. --- node/Cargo.lock | 27 ++---- node/libs/roles/src/attester/tests.rs | 86 ------------------- .../roles/src/proto/validator/genesis.proto | 5 +- node/libs/roles/src/validator/conv.rs | 24 +----- .../roles/src/validator/messages/genesis.rs | 4 +- .../src/validator/messages/tests/consensus.rs | 3 +- .../roles/src/validator/messages/tests/mod.rs | 59 ++----------- .../messages/tests/replica_commit.rs | 5 +- .../messages/tests/replica_timeout.rs | 10 ++- .../src/validator/messages/tests/versions.rs | 17 +--- node/libs/roles/src/validator/testonly.rs | 9 -- 11 files changed, 32 insertions(+), 217 deletions(-) diff --git a/node/Cargo.lock b/node/Cargo.lock index c9b74ebd..cf6329e8 100644 --- a/node/Cargo.lock +++ b/node/Cargo.lock @@ -320,7 +320,7 @@ dependencies = [ "bitflags 2.6.0", "cexpr", "clang-sys", - "itertools 0.12.1", + "itertools", "lazy_static", "lazycell", "log", @@ -676,7 +676,7 @@ dependencies = [ "clap", "criterion-plot", "is-terminal", - "itertools 0.10.5", + "itertools", "num-traits", "once_cell", "oorandom", @@ -697,7 +697,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" dependencies = [ "cast", - "itertools 0.10.5", + "itertools", ] [[package]] @@ -1746,15 +1746,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.12" @@ -2703,7 +2694,7 @@ checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" dependencies = [ "bytes", "heck", - "itertools 0.12.1", + "itertools", "log", "multimap", "once_cell", @@ -2723,7 +2714,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.12.1", + "itertools", "proc-macro2", "quote", "syn", @@ -2988,9 +2979,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.17" +version = "0.23.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f1a745511c54ba6d4465e8d5dfbd81b45791756de28d4981af70d6dca128f1e" +checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" dependencies = [ "aws-lc-rs", "log", @@ -3833,9 +3824,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.3" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", diff --git a/node/libs/roles/src/attester/tests.rs b/node/libs/roles/src/attester/tests.rs index c9d85cd4..8abd6d67 100644 --- a/node/libs/roles/src/attester/tests.rs +++ b/node/libs/roles/src/attester/tests.rs @@ -1,5 +1,4 @@ use super::*; -use crate::validator::testonly::Setup; use assert_matches::assert_matches; use rand::Rng; use zksync_concurrency::ctx; @@ -134,91 +133,6 @@ fn test_agg_signature_verify() { .is_err()); } -#[test] -fn test_batch_qc() { - use BatchQCVerifyError as Error; - let ctx = ctx::test_root(&ctx::RealClock); - let rng = &mut ctx.rng(); - - let setup1 = Setup::new(rng, 6); - // Completely different genesis. - let setup2 = Setup::new(rng, 6); - // Genesis with only a subset of the attesters. - let genesis3 = { - let mut genesis3 = (*setup1.genesis).clone(); - genesis3.attesters = Committee::new( - setup1 - .genesis - .attesters - .as_ref() - .unwrap() - .iter() - .take(3) - .cloned(), - ) - .unwrap() - .into(); - genesis3.with_hash() - }; - - let attesters = setup1.genesis.attesters.as_ref().unwrap(); - - // Create QCs with increasing number of attesters. - for i in 0..setup1.attester_keys.len() + 1 { - let mut qc = BatchQC::new(Batch { - genesis: setup1.genesis.hash(), - number: rng.gen(), - hash: rng.gen(), - }); - for key in &setup1.attester_keys[0..i] { - qc.add(&key.sign_msg(qc.message.clone()), attesters) - .unwrap(); - } - - let expected_weight: u64 = attesters.iter().take(i).map(|w| w.weight).sum(); - if expected_weight >= attesters.threshold() { - qc.verify(setup1.genesis.hash(), attesters) - .expect("failed to verify QC"); - } else { - assert_matches!( - qc.verify(setup1.genesis.hash(), attesters), - Err(Error::NotEnoughSigners { .. }) - ); - } - - // Mismatching attesters sets. - assert!(qc - .verify( - setup1.genesis.hash(), - setup2.genesis.attesters.as_ref().unwrap() - ) - .is_err()); - assert!(qc - .verify(setup1.genesis.hash(), genesis3.attesters.as_ref().unwrap()) - .is_err()); - } -} - -#[test] -fn test_attester_committee_weights() { - let ctx = ctx::test_root(&ctx::RealClock); - let rng = &mut ctx.rng(); - - // Attesters with non-uniform weights - let setup = Setup::new_with_weights(rng, vec![1000, 600, 800, 6000, 900, 700]); - // Expected sum of the attesters weights - let sums = [1000, 1600, 2400, 8400, 9300, 10000]; - let attesters = setup.genesis.attesters.as_ref().unwrap(); - - let msg: Batch = rng.gen(); - let mut qc = BatchQC::new(msg.clone()); - for (i, weight) in sums.iter().enumerate() { - let key = &setup.attester_keys[i]; - qc.add(&key.sign_msg(msg.clone()), attesters).unwrap(); - assert_eq!(attesters.weight_of_keys(qc.signatures.keys()), *weight); - } -} - #[test] fn test_committee_weights_overflow_check() { let ctx = ctx::test_root(&ctx::RealClock); diff --git a/node/libs/roles/src/proto/validator/genesis.proto b/node/libs/roles/src/proto/validator/genesis.proto index 7605e705..16d98fca 100644 --- a/node/libs/roles/src/proto/validator/genesis.proto +++ b/node/libs/roles/src/proto/validator/genesis.proto @@ -23,8 +23,8 @@ message LeaderSelectionMode { } message Genesis { - reserved 1,2; - reserved "fork","validators"; + reserved 1,2,9; + reserved "fork","validators", "attesters"; optional uint64 chain_id = 5; // required optional uint64 fork_number = 6; // required; ForkNumber optional uint64 first_block = 7; // required; BlockNumber @@ -33,7 +33,6 @@ message Genesis { // We will either remove them entirely, or keep them for the initial epoch. optional uint32 protocol_version = 8; // required; ProtocolVersion repeated WeightedValidator validators_v1 = 3; - repeated attester.WeightedAttester attesters = 9; // optional optional LeaderSelectionMode leader_selection = 4; // required } diff --git a/node/libs/roles/src/validator/conv.rs b/node/libs/roles/src/validator/conv.rs index 5addcab2..536da024 100644 --- a/node/libs/roles/src/validator/conv.rs +++ b/node/libs/roles/src/validator/conv.rs @@ -5,12 +5,7 @@ use super::{ ProposalJustification, ProtocolVersion, PublicKey, ReplicaCommit, ReplicaNewView, ReplicaTimeout, Signature, Signed, Signers, TimeoutQC, View, ViewNumber, WeightedValidator, }; -use crate::{ - attester::{self, WeightedAttester}, - node::SessionId, - proto::validator as proto, - validator::LeaderSelectionMode, -}; +use crate::{node::SessionId, proto::validator as proto, validator::LeaderSelectionMode}; use anyhow::Context as _; use std::collections::BTreeMap; use zksync_consensus_crypto::ByteFmt; @@ -27,13 +22,6 @@ impl ProtoFmt for GenesisRaw { .map(|(i, v)| WeightedValidator::read(v).context(i)) .collect::>() .context("validators_v1")?; - let attesters: Vec<_> = r - .attesters - .iter() - .enumerate() - .map(|(i, v)| WeightedAttester::read(v).context(i)) - .collect::>() - .context("attesters")?; Ok(GenesisRaw { chain_id: ChainId(*required(&r.chain_id).context("chain_id")?), fork_number: ForkNumber(*required(&r.fork_number).context("fork_number")?), @@ -41,11 +29,6 @@ impl ProtoFmt for GenesisRaw { protocol_version: ProtocolVersion(r.protocol_version.context("protocol_version")?), validators: Committee::new(validators.into_iter()).context("validators_v1")?, - attesters: if attesters.is_empty() { - None - } else { - Some(attester::Committee::new(attesters.into_iter()).context("attesters")?) - }, leader_selection: read_required(&r.leader_selection).context("leader_selection")?, }) } @@ -57,11 +40,6 @@ impl ProtoFmt for GenesisRaw { protocol_version: Some(self.protocol_version.0), validators_v1: self.validators.iter().map(|v| v.build()).collect(), - attesters: self - .attesters - .as_ref() - .map(|c| c.iter().map(|v| v.build()).collect()) - .unwrap_or_default(), leader_selection: Some(self.leader_selection.build()), } } diff --git a/node/libs/roles/src/validator/messages/genesis.rs b/node/libs/roles/src/validator/messages/genesis.rs index 19d6daeb..7ab8f4e6 100644 --- a/node/libs/roles/src/validator/messages/genesis.rs +++ b/node/libs/roles/src/validator/messages/genesis.rs @@ -1,6 +1,6 @@ //! Messages related to the consensus protocol. use super::{BlockNumber, LeaderSelectionMode, ViewNumber}; -use crate::{attester, validator}; +use crate::validator; use std::{fmt, hash::Hash}; use zksync_consensus_crypto::{keccak256::Keccak256, ByteFmt, Text, TextFmt}; @@ -18,8 +18,6 @@ pub struct GenesisRaw { pub first_block: BlockNumber, /// Set of validators of the chain. pub validators: validator::Committee, - /// Set of attesters of the chain. - pub attesters: Option, /// The mode used for selecting leader for a given view. pub leader_selection: LeaderSelectionMode, } diff --git a/node/libs/roles/src/validator/messages/tests/consensus.rs b/node/libs/roles/src/validator/messages/tests/consensus.rs index 632f7508..1a8cac23 100644 --- a/node/libs/roles/src/validator/messages/tests/consensus.rs +++ b/node/libs/roles/src/validator/messages/tests/consensus.rs @@ -28,13 +28,12 @@ fn test_view_prev() { #[test] fn test_view_verify() { - let genesis = genesis_with_attesters(); + let genesis = genesis(); let view = View { genesis: genesis.hash(), number: ViewNumber(1), }; assert!(view.verify(&genesis).is_ok()); - assert!(view.verify(&genesis_empty_attesters()).is_err()); let view = View { genesis: GenesisHash::default(), number: ViewNumber(1), diff --git a/node/libs/roles/src/validator/messages/tests/mod.rs b/node/libs/roles/src/validator/messages/tests/mod.rs index 798f74ed..6b7a1308 100644 --- a/node/libs/roles/src/validator/messages/tests/mod.rs +++ b/node/libs/roles/src/validator/messages/tests/mod.rs @@ -1,8 +1,5 @@ use super::*; -use crate::{ - attester::{self, WeightedAttester}, - validator::{self, testonly::Setup}, -}; +use crate::validator::{self, testonly::Setup}; use rand::Rng; use zksync_consensus_crypto::Text; @@ -18,7 +15,7 @@ mod versions; /// Hardcoded view. fn view() -> View { View { - genesis: genesis_empty_attesters().hash(), + genesis: genesis().hash(), number: ViewNumber(9136), } } @@ -58,18 +55,6 @@ fn validator_keys() -> Vec { .collect() } -/// Hardcoded attester secret keys. -fn attester_keys() -> Vec { - [ - "attester:secret:secp256k1:27cb45b1670a1ae8d376a85821d51c7f91ebc6e32788027a84758441aaf0a987", - "attester:secret:secp256k1:20132edc08a529e927f155e710ae7295a2a0d249f1b1f37726894d1d0d8f0d81", - "attester:secret:secp256k1:0946901f0a6650284726763b12de5da0f06df0016c8ec2144cf6b1903f1979a6", - ] - .iter() - .map(|raw| Text::new(raw).decode().unwrap()) - .collect() -} - /// Hardcoded validator committee. fn validator_committee() -> Committee { Committee::new( @@ -84,37 +69,8 @@ fn validator_committee() -> Committee { .unwrap() } -/// Hardcoded attester committee. -fn attester_committee() -> attester::Committee { - attester::Committee::new( - attester_keys() - .iter() - .enumerate() - .map(|(i, key)| WeightedAttester { - key: key.public(), - weight: i as u64 + 10, - }), - ) - .unwrap() -} - /// Hardcoded genesis with no attesters. -fn genesis_empty_attesters() -> Genesis { - GenesisRaw { - chain_id: ChainId(1337), - fork_number: ForkNumber(42), - first_block: BlockNumber(2834), - - protocol_version: ProtocolVersion(1), - validators: validator_committee(), - attesters: None, - leader_selection: LeaderSelectionMode::Weighted, - } - .with_hash() -} - -/// Hardcoded genesis with attesters. -fn genesis_with_attesters() -> Genesis { +fn genesis() -> Genesis { GenesisRaw { chain_id: ChainId(1337), fork_number: ForkNumber(42), @@ -122,7 +78,6 @@ fn genesis_with_attesters() -> Genesis { protocol_version: ProtocolVersion(1), validators: validator_committee(), - attesters: attester_committee().into(), leader_selection: LeaderSelectionMode::Weighted, } .with_hash() @@ -146,7 +101,7 @@ fn replica_commit() -> ReplicaCommit { /// Hardcoded `CommitQC`. fn commit_qc() -> CommitQC { - let genesis = genesis_empty_attesters(); + let genesis = genesis(); let replica_commit = replica_commit(); let mut x = CommitQC::new(replica_commit.clone(), &genesis); for k in validator_keys() { @@ -160,7 +115,7 @@ fn commit_qc() -> CommitQC { fn replica_timeout() -> ReplicaTimeout { ReplicaTimeout { view: View { - genesis: genesis_empty_attesters().hash(), + genesis: genesis().hash(), number: ViewNumber(9169), }, high_vote: Some(replica_commit()), @@ -171,10 +126,10 @@ fn replica_timeout() -> ReplicaTimeout { /// Hardcoded `TimeoutQC`. fn timeout_qc() -> TimeoutQC { let mut x = TimeoutQC::new(View { - genesis: genesis_empty_attesters().hash(), + genesis: genesis().hash(), number: ViewNumber(9169), }); - let genesis = genesis_empty_attesters(); + let genesis = genesis(); let replica_timeout = replica_timeout(); for k in validator_keys() { x.add(&k.sign_msg(replica_timeout.clone()), &genesis) diff --git a/node/libs/roles/src/validator/messages/tests/replica_commit.rs b/node/libs/roles/src/validator/messages/tests/replica_commit.rs index d7b9d349..8a322e80 100644 --- a/node/libs/roles/src/validator/messages/tests/replica_commit.rs +++ b/node/libs/roles/src/validator/messages/tests/replica_commit.rs @@ -4,12 +4,13 @@ use zksync_concurrency::ctx; #[test] fn test_replica_commit_verify() { - let genesis = genesis_empty_attesters(); + let mut genesis = genesis(); let commit = replica_commit(); assert!(commit.verify(&genesis).is_ok()); // Wrong view - let wrong_genesis = genesis_with_attesters().clone(); + genesis.0.chain_id = ChainId(1); + let wrong_genesis = genesis.0.with_hash(); assert_matches!( commit.verify(&wrong_genesis), Err(ReplicaCommitVerifyError::BadView(_)) diff --git a/node/libs/roles/src/validator/messages/tests/replica_timeout.rs b/node/libs/roles/src/validator/messages/tests/replica_timeout.rs index 09e5c49c..c7b6886d 100644 --- a/node/libs/roles/src/validator/messages/tests/replica_timeout.rs +++ b/node/libs/roles/src/validator/messages/tests/replica_timeout.rs @@ -4,12 +4,14 @@ use zksync_concurrency::ctx; #[test] fn test_replica_timeout_verify() { - let genesis = genesis_empty_attesters(); + let genesis = genesis(); let timeout = replica_timeout(); assert!(timeout.verify(&genesis).is_ok()); // Wrong view - let wrong_genesis = genesis_with_attesters().clone(); + let mut wrong_raw_genesis = genesis.0.clone(); + wrong_raw_genesis.chain_id = ChainId(1); + let wrong_genesis = wrong_raw_genesis.with_hash(); assert_matches!( timeout.verify(&wrong_genesis), Err(ReplicaTimeoutVerifyError::BadView(_)) @@ -17,7 +19,7 @@ fn test_replica_timeout_verify() { // Invalid high vote let mut timeout = replica_timeout(); - timeout.high_vote.as_mut().unwrap().view.genesis = genesis_with_attesters().hash(); + timeout.high_vote.as_mut().unwrap().view.genesis = wrong_genesis.hash(); assert_matches!( timeout.verify(&genesis), Err(ReplicaTimeoutVerifyError::InvalidHighVote(_)) @@ -25,7 +27,7 @@ fn test_replica_timeout_verify() { // Invalid high QC let mut timeout = replica_timeout(); - timeout.high_qc.as_mut().unwrap().message.view.genesis = genesis_with_attesters().hash(); + timeout.high_qc.as_mut().unwrap().message.view.genesis = wrong_genesis.hash(); assert_matches!( timeout.verify(&genesis), Err(ReplicaTimeoutVerifyError::InvalidHighQC(_)) diff --git a/node/libs/roles/src/validator/messages/tests/versions.rs b/node/libs/roles/src/validator/messages/tests/versions.rs index a19f152a..842e4497 100644 --- a/node/libs/roles/src/validator/messages/tests/versions.rs +++ b/node/libs/roles/src/validator/messages/tests/versions.rs @@ -11,26 +11,13 @@ mod version1 { /// Even if it was, ALL versions of genesis need to be supported FOREVER, /// unless we introduce dynamic regenesis. #[test] - fn genesis_hash_change_detector_empty_attesters() { + fn genesis_hash_change_detector() { let want: GenesisHash = Text::new( "genesis_hash:keccak256:75cfa582fcda9b5da37af8fb63a279f777bb17a97a50519e1a61aad6c77a522f", ) .decode() .unwrap(); - assert_eq!(want, genesis_empty_attesters().hash()); - } - - /// Note that genesis is NOT versioned by ProtocolVersion. - /// Even if it was, ALL versions of genesis need to be supported FOREVER, - /// unless we introduce dynamic regenesis. - #[test] - fn genesis_hash_change_detector_nonempty_attesters() { - let want: GenesisHash = Text::new( - "genesis_hash:keccak256:586a4bc6167c084d7499cead9267b224ab04a4fdeff555630418bcd2df5d186d", - ) - .decode() - .unwrap(); - assert_eq!(want, genesis_with_attesters().hash()); + assert_eq!(want, genesis().hash()); } /// Asserts that msg.hash()==hash and that sig is a diff --git a/node/libs/roles/src/validator/testonly.rs b/node/libs/roles/src/validator/testonly.rs index 5ceff2ac..aa69421f 100644 --- a/node/libs/roles/src/validator/testonly.rs +++ b/node/libs/roles/src/validator/testonly.rs @@ -97,14 +97,6 @@ impl Setup { } })) .unwrap(), - attesters: attester::Committee::new(spec.attester_weights.iter().map(|(k, w)| { - attester::WeightedAttester { - key: k.public(), - weight: *w, - } - })) - .unwrap() - .into(), leader_selection: spec.leader_selection, } .with_hash(), @@ -407,7 +399,6 @@ impl Distribution for Standard { protocol_version: rng.gen(), validators: rng.gen(), - attesters: rng.gen(), leader_selection: rng.gen(), };