From 6097b0918704d7370e41068a1f25e6baaad23847 Mon Sep 17 00:00:00 2001 From: rob-maron <132852777+rob-maron@users.noreply.github.com> Date: Fri, 26 Apr 2024 21:47:36 -0400 Subject: [PATCH] Fix conditional DA: remove node indexing (#3045) * fix conditional DA: remove node indexing * fix genesis DAC by using DA membership in tests * PR comments * PR comment --- crates/example-types/src/node_types.rs | 3 +- crates/examples/infra/mod.rs | 138 ++++++++---------- crates/examples/push-cdn/whitelist-adapter.rs | 6 +- crates/hotshot/src/lib.rs | 6 +- .../src/traits/election/static_committee.rs | 104 +++++-------- .../src/traits/networking/libp2p_network.rs | 2 +- crates/orchestrator/src/client.rs | 22 +-- crates/orchestrator/src/config.rs | 39 ++--- crates/orchestrator/src/lib.rs | 54 +++---- crates/testing/src/spinning_task.rs | 2 +- crates/testing/src/task_helpers.rs | 25 +--- crates/testing/src/test_builder.rs | 18 +-- crates/testing/src/test_launcher.rs | 4 +- crates/testing/src/test_runner.rs | 26 +--- crates/testing/src/view_generator.rs | 24 ++- .../testing/tests/tests_1/consensus_task.rs | 85 +++++------ crates/testing/tests/tests_1/da_task.rs | 8 +- crates/testing/tests/tests_1/network_task.rs | 20 +-- .../tests/tests_1/proposal_ordering.rs | 4 +- .../tests/tests_1/quorum_proposal_task.rs | 20 ++- .../testing/tests/tests_1/quorum_vote_task.rs | 12 +- crates/testing/tests/tests_1/upgrade_task.rs | 12 +- .../testing/tests/tests_3/memory_network.rs | 3 +- crates/types/src/lib.rs | 12 +- crates/types/src/traits/election.rs | 22 +-- .../types/src/traits/node_implementation.rs | 22 --- 26 files changed, 280 insertions(+), 413 deletions(-) diff --git a/crates/example-types/src/node_types.rs b/crates/example-types/src/node_types.rs index 0f45946c6f..ca0c29e20c 100644 --- a/crates/example-types/src/node_types.rs +++ b/crates/example-types/src/node_types.rs @@ -1,5 +1,5 @@ use hotshot::traits::{ - election::static_committee::{GeneralStaticCommittee, StaticCommittee, StaticElectionConfig}, + election::static_committee::{GeneralStaticCommittee, StaticCommittee}, implementations::{ CombinedNetworks, Libp2pNetwork, MemoryNetwork, PushCdnNetwork, WebServerNetwork, }, @@ -42,7 +42,6 @@ impl NodeType for TestTypes { type BlockPayload = TestBlockPayload; type SignatureKey = BLSPubKey; type Transaction = TestTransaction; - type ElectionConfigType = StaticElectionConfig; type ValidatedState = TestValidatedState; type InstanceState = TestInstanceState; type Membership = GeneralStaticCommittee; diff --git a/crates/examples/infra/mod.rs b/crates/examples/infra/mod.rs index 0d9bac23f8..29ef95abc4 100644 --- a/crates/examples/infra/mod.rs +++ b/crates/examples/infra/mod.rs @@ -70,7 +70,7 @@ pub struct OrchestratorArgs { /// The url the orchestrator runs on; this should be in the form of `http://localhost:5555` or `http://0.0.0.0:5555` pub url: Url, /// The configuration file to be used for this run - pub config: NetworkConfig, + pub config: NetworkConfig, } #[derive(Parser, Debug, Clone)] @@ -96,10 +96,8 @@ impl Default for ConfigArgs { /// # Panics /// If unable to read the config file from the command line #[allow(clippy::too_many_lines)] -pub fn read_orchestrator_init_config() -> ( - NetworkConfig, - Url, -) { +pub fn read_orchestrator_init_config() -> (NetworkConfig, Url) +{ // assign default setting let mut orchestrator_url = Url::parse("http://localhost:4444").unwrap(); let mut args = ConfigArgs::default(); @@ -211,7 +209,7 @@ pub fn read_orchestrator_init_config() -> ( } else { error!("No config file provided, we'll use the default one."); } - let mut config: NetworkConfig = + let mut config: NetworkConfig = load_config_from_file::(&args.config_file); if let Some(total_nodes_string) = matches.get_one::("total_nodes") { @@ -282,15 +280,14 @@ pub fn read_orchestrator_init_config() -> ( #[must_use] pub fn load_config_from_file( config_file: &str, -) -> NetworkConfig { +) -> NetworkConfig { let config_file_as_string: String = fs::read_to_string(config_file) .unwrap_or_else(|_| panic!("Could not read config file located at {config_file}")); let config_toml: NetworkConfigFile = toml::from_str::>(&config_file_as_string) .expect("Unable to convert config file to TOML"); - let mut config: NetworkConfig = - config_toml.into(); + let mut config: NetworkConfig = config_toml.into(); // my_own_validator_config would be best to load from file, // but its type is too complex to load so we'll generate it from seed now. @@ -314,11 +311,7 @@ pub async fn run_orchestrator< OrchestratorArgs { url, config }: OrchestratorArgs, ) { println!("Starting orchestrator",); - let _result = hotshot_orchestrator::run_orchestrator::< - TYPES::SignatureKey, - TYPES::ElectionConfigType, - >(config, url) - .await; + let _ = hotshot_orchestrator::run_orchestrator::(config, url).await; } /// Helper function to calculate the nuymber of transactions to send per node per round @@ -339,7 +332,7 @@ fn calculate_num_tx_per_round( /// # Panics /// Panics if the web server config doesn't exist in `config` fn webserver_network_from_config( - config: NetworkConfig, + config: NetworkConfig, pub_key: TYPES::SignatureKey, ) -> WebServerNetwork { // Get the configuration for the web server @@ -372,7 +365,7 @@ pub trait RunDA< { /// Initializes networking, returns self async fn initialize_networking( - config: NetworkConfig, + config: NetworkConfig, libp2p_advertise_address: Option, ) -> Self; @@ -394,46 +387,32 @@ pub trait RunDA< let da_network = self.get_da_channel(); let quorum_network = self.get_quorum_channel(); - // Since we do not currently pass the election config type in the NetworkConfig, this will always be the default election config - let quorum_election_config = config.config.election_config.clone().unwrap_or_else(|| { - TYPES::Membership::default_election_config( - config.config.num_nodes_with_stake.get() as u64, - config.config.num_nodes_without_stake as u64, - ) - }); - - let committee_election_config = TYPES::Membership::default_election_config( - // Use the number of _actual_ DA nodes connected for the committee size - config.config.known_da_nodes.len() as u64, - config.config.num_nodes_without_stake as u64, - ); let networks_bundle = Networks { quorum_network: quorum_network.clone().into(), da_network: da_network.clone().into(), _pd: PhantomData, }; + // Create the quorum membership from all nodes + let quorum_membership = ::Membership::create_election( + known_nodes_with_stake.clone(), + known_nodes_with_stake.clone(), + config.config.fixed_leader_for_gpuvid, + ); + + // Create the quorum membership from all nodes, specifying the committee + // as the known da nodes + let da_membership = ::Membership::create_election( + known_nodes_with_stake.clone(), + known_nodes_with_stake, + config.config.fixed_leader_for_gpuvid, + ); + let memberships = Memberships { - quorum_membership: ::Membership::create_election( - known_nodes_with_stake.clone(), - quorum_election_config.clone(), - config.config.fixed_leader_for_gpuvid, - ), - da_membership: ::Membership::create_election( - known_nodes_with_stake.clone(), - committee_election_config, - config.config.fixed_leader_for_gpuvid, - ), - vid_membership: ::Membership::create_election( - known_nodes_with_stake.clone(), - quorum_election_config.clone(), - config.config.fixed_leader_for_gpuvid, - ), - view_sync_membership: ::Membership::create_election( - known_nodes_with_stake.clone(), - quorum_election_config, - config.config.fixed_leader_for_gpuvid, - ), + quorum_membership: quorum_membership.clone(), + da_membership, + vid_membership: quorum_membership.clone(), + view_sync_membership: quorum_membership, }; SystemContext::init( @@ -620,7 +599,7 @@ pub trait RunDA< fn get_quorum_channel(&self) -> QUORUMNET; /// Returns the config for this run - fn get_config(&self) -> NetworkConfig; + fn get_config(&self) -> NetworkConfig; } // WEB SERVER @@ -628,7 +607,7 @@ pub trait RunDA< /// Represents a web server-based run pub struct WebServerDARun { /// the network configuration - config: NetworkConfig, + config: NetworkConfig, /// quorum channel quorum_channel: WebServerNetwork, /// data availability channel @@ -665,7 +644,7 @@ where NetworkVersion: 'static, { async fn initialize_networking( - config: NetworkConfig, + config: NetworkConfig, _libp2p_advertise_address: Option, ) -> WebServerDARun { // Get our own key @@ -701,7 +680,7 @@ where self.quorum_channel.clone() } - fn get_config(&self) -> NetworkConfig { + fn get_config(&self) -> NetworkConfig { self.config.clone() } } @@ -711,7 +690,7 @@ where /// Represents a Push CDN-based run pub struct PushCdnDaRun { /// The underlying configuration - config: NetworkConfig, + config: NetworkConfig, /// The quorum channel quorum_channel: PushCdnNetwork, /// The DA channel @@ -740,7 +719,7 @@ where Self: Sync, { async fn initialize_networking( - config: NetworkConfig, + config: NetworkConfig, _libp2p_advertise_address: Option, ) -> PushCdnDaRun { // Get our own key @@ -787,7 +766,7 @@ where self.quorum_channel.clone() } - fn get_config(&self) -> NetworkConfig { + fn get_config(&self) -> NetworkConfig { self.config.clone() } } @@ -797,7 +776,7 @@ where /// Represents a libp2p-based run pub struct Libp2pDARun { /// the network configuration - config: NetworkConfig, + config: NetworkConfig, /// quorum channel quorum_channel: Libp2pNetwork, TYPES::SignatureKey>, /// data availability channel @@ -832,7 +811,7 @@ where Self: Sync, { async fn initialize_networking( - config: NetworkConfig, + config: NetworkConfig, libp2p_advertise_address: Option, ) -> Libp2pDARun { // Extrapolate keys for ease of use @@ -885,7 +864,7 @@ where self.quorum_channel.clone() } - fn get_config(&self) -> NetworkConfig { + fn get_config(&self) -> NetworkConfig { self.config.clone() } } @@ -895,7 +874,7 @@ where /// Represents a combined-network-based run pub struct CombinedDARun { /// the network configuration - config: NetworkConfig, + config: NetworkConfig, /// quorum channel quorum_channel: CombinedNetworks, /// data availability channel @@ -924,7 +903,7 @@ where Self: Sync, { async fn initialize_networking( - config: NetworkConfig, + config: NetworkConfig, libp2p_advertise_address: Option, ) -> CombinedDARun { // Initialize our Libp2p network @@ -981,7 +960,7 @@ where self.quorum_channel.clone() } - fn get_config(&self) -> NetworkConfig { + fn get_config(&self) -> NetworkConfig { self.config.clone() } } @@ -1020,11 +999,13 @@ pub async fn main_entry_point< let orchestrator_client: OrchestratorClient = OrchestratorClient::new(args.clone()); // We assume one node will not call this twice to generate two validator_config-s with same identity. - let my_own_validator_config = NetworkConfig::::generate_init_validator_config( - &orchestrator_client, - // This is false for now, we only use it to generate the keypair - false - ).await; + let my_own_validator_config = + NetworkConfig::::generate_init_validator_config( + &orchestrator_client, + // This is false for now, we only use it to generate the keypair + false, + ) + .await; // Derives our Libp2p private key from our private key, and then returns the public key of that key let libp2p_public_key = @@ -1037,18 +1018,17 @@ pub async fn main_entry_point< // It returns the complete config which also includes peer's public key and public config. // This function will be taken solely by sequencer right after OrchestratorClient::new, // which means the previous `generate_validator_config_when_init` will not be taken by sequencer, it's only for key pair generation for testing in hotshot. - let (mut run_config, source) = - NetworkConfig::::get_complete_config( - &orchestrator_client, - args.clone().network_config_file, - my_own_validator_config, - args.advertise_address, - Some(libp2p_public_key), - // If `indexed_da` is true: use the node index to determine if we are a DA node. - true, - ) - .await - .expect("failed to get config"); + let (mut run_config, source) = NetworkConfig::::get_complete_config( + &orchestrator_client, + args.clone().network_config_file, + my_own_validator_config, + args.advertise_address, + Some(libp2p_public_key), + // If `indexed_da` is true: use the node index to determine if we are a DA node. + true, + ) + .await + .expect("failed to get config"); let builder_task = match run_config.builder { BuilderType::External => None, diff --git a/crates/examples/push-cdn/whitelist-adapter.rs b/crates/examples/push-cdn/whitelist-adapter.rs index 14ffa8dc91..9666e459f7 100644 --- a/crates/examples/push-cdn/whitelist-adapter.rs +++ b/crates/examples/push-cdn/whitelist-adapter.rs @@ -52,10 +52,8 @@ async fn main() -> Result<()> { // Attempt to get the config from the orchestrator. // Loops internally until the config is received. - let config: NetworkConfig< - ::SignatureKey, - ::ElectionConfigType, - > = orchestrator_client.get_config_after_collection().await; + let config: NetworkConfig<::SignatureKey> = + orchestrator_client.get_config_after_collection().await; tracing::info!("Received config from orchestrator"); diff --git a/crates/hotshot/src/lib.rs b/crates/hotshot/src/lib.rs index 86919099ca..28809ad528 100644 --- a/crates/hotshot/src/lib.rs +++ b/crates/hotshot/src/lib.rs @@ -121,7 +121,7 @@ pub struct SystemContext> { private_key: ::PrivateKey, /// Configuration items for this hotshot instance - pub config: HotShotConfig, + pub config: HotShotConfig, /// Networks used by the instance of hotshot pub networks: Arc>, @@ -205,7 +205,7 @@ impl> SystemContext { public_key: TYPES::SignatureKey, private_key: ::PrivateKey, nonce: u64, - config: HotShotConfig, + config: HotShotConfig, memberships: Memberships, networks: Networks, initializer: HotShotInitializer, @@ -483,7 +483,7 @@ impl> SystemContext { public_key: TYPES::SignatureKey, private_key: ::PrivateKey, node_id: u64, - config: HotShotConfig, + config: HotShotConfig, memberships: Memberships, networks: Networks, initializer: HotShotInitializer, diff --git a/crates/hotshot/src/traits/election/static_committee.rs b/crates/hotshot/src/traits/election/static_committee.rs index d2c01455c8..1aa4d967ca 100644 --- a/crates/hotshot/src/traits/election/static_committee.rs +++ b/crates/hotshot/src/traits/election/static_committee.rs @@ -1,20 +1,14 @@ -// use ark_bls12_381::Parameters as Param381; -use std::{marker::PhantomData, num::NonZeroU64}; - use ethereum_types::U256; +// use ark_bls12_381::Parameters as Param381; +use hotshot_types::traits::signature_key::StakeTableEntryType; use hotshot_types::{ signature_key::BLSPubKey, - traits::{ - election::{ElectionConfig, Membership}, - node_implementation::NodeType, - signature_key::{SignatureKey, StakeTableEntryType}, - }, + traits::{election::Membership, node_implementation::NodeType, signature_key::SignatureKey}, PeerConfig, }; #[cfg(feature = "randomized-leader-election")] use rand::{rngs::StdRng, Rng}; -#[allow(deprecated)] -use serde::{Deserialize, Serialize}; +use std::{marker::PhantomData, num::NonZeroU64}; use tracing::debug; /// Dummy implementation of [`Membership`] @@ -22,7 +16,7 @@ use tracing::debug; #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct GeneralStaticCommittee { /// All the nodes participating and their stake - nodes_with_stake: Vec, + all_nodes_with_stake: Vec, /// The nodes on the static committee and their stake committee_nodes_with_stake: Vec, /// builder nodes @@ -46,7 +40,7 @@ impl GeneralStaticCommittee { fixed_leader_for_gpuvid: usize, ) -> Self { Self { - nodes_with_stake: nodes_with_stake.clone(), + all_nodes_with_stake: nodes_with_stake.clone(), committee_nodes_with_stake: nodes_with_stake, committee_nodes_without_stake: nodes_without_stake, fixed_leader_for_gpuvid, @@ -55,21 +49,10 @@ impl GeneralStaticCommittee { } } -/// configuration for static committee. stub for now -#[derive(Default, Clone, Serialize, Deserialize, core::fmt::Debug)] -pub struct StaticElectionConfig { - /// Number of nodes on the committee - num_nodes_with_stake: u64, - /// Number of non staking nodes - num_nodes_without_stake: u64, -} - -impl ElectionConfig for StaticElectionConfig {} - impl Membership for GeneralStaticCommittee where - TYPES: NodeType, + TYPES: NodeType, { /// Clone the public key and corresponding stake table for current elected committee fn get_committee_qc_stake_table(&self) -> Vec { @@ -82,8 +65,8 @@ where )))] /// Index the vector of public keys with the current view number fn get_leader(&self, view_number: TYPES::Time) -> PUBKEY { - let index = usize::try_from(*view_number % self.nodes_with_stake.len() as u64).unwrap(); - let res = self.nodes_with_stake[index].clone(); + let index = usize::try_from(*view_number % self.all_nodes_with_stake.len() as u64).unwrap(); + let res = self.all_nodes_with_stake[index].clone(); TYPES::SignatureKey::get_public_key(&res) } @@ -123,44 +106,41 @@ where } } - fn default_election_config( - num_nodes_with_stake: u64, - num_nodes_without_stake: u64, - ) -> TYPES::ElectionConfigType { - StaticElectionConfig { - num_nodes_with_stake, - num_nodes_without_stake, - } - } - fn create_election( - entries: Vec>, - config: TYPES::ElectionConfigType, + mut all_nodes: Vec>, + committee_members: Vec>, fixed_leader_for_gpuvid: usize, ) -> Self { - let nodes_with_stake: Vec = entries - .iter() - .map(|x| x.stake_table_entry.clone()) - .collect(); + let mut committee_nodes_with_stake = Vec::new(); + let mut committee_nodes_without_stake = Vec::new(); - let mut committee_nodes_with_stake: Vec = Vec::new(); - - let mut committee_nodes_without_stake: Vec = Vec::new(); - // filter out the committee nodes with non-zero state and zero stake - for node in &nodes_with_stake { - if node.get_stake() == U256::from(0) { - committee_nodes_without_stake.push(PUBKEY::get_public_key(node)); + // Iterate over committee members + for entry in committee_members + .iter() + .map(|entry| entry.stake_table_entry.clone()) + { + if entry.get_stake() > U256::from(0) { + // Positive stake + committee_nodes_with_stake.push(entry); } else { - committee_nodes_with_stake.push(node.clone()); + // Zero stake + committee_nodes_without_stake.push(PUBKEY::get_public_key(&entry)); } } - debug!("Election Membership Size: {}", config.num_nodes_with_stake); - // truncate committee_nodes_with_stake to only `num_nodes` with lower index - // since the `num_nodes_without_stake` are not part of the committee, - committee_nodes_with_stake.truncate(config.num_nodes_with_stake.try_into().unwrap()); - committee_nodes_without_stake.truncate(config.num_nodes_without_stake.try_into().unwrap()); + + // Retain all nodes with stake + all_nodes.retain(|entry| entry.stake_table_entry.get_stake() > U256::from(0)); + + debug!( + "Election Membership Size: {}", + committee_nodes_with_stake.len() + ); + Self { - nodes_with_stake, + all_nodes_with_stake: all_nodes + .into_iter() + .map(|entry| entry.stake_table_entry) + .collect(), committee_nodes_with_stake, committee_nodes_without_stake, fixed_leader_for_gpuvid, @@ -188,13 +168,9 @@ where &self, _view_number: ::Time, ) -> std::collections::BTreeSet<::SignatureKey> { - // Transfer from committee_nodes_with_stake to pure committee_nodes - (0..self.committee_nodes_with_stake.len()) - .map(|node_id| { - ::SignatureKey::get_public_key( - &self.committee_nodes_with_stake[node_id], - ) - }) + self.committee_nodes_with_stake + .iter() + .map(|node| ::SignatureKey::get_public_key(node)) .collect() } @@ -217,7 +193,7 @@ where impl GeneralStaticCommittee where - TYPES: NodeType, + TYPES: NodeType, { #[allow(clippy::must_use_candidate)] /// get the non-staked builder nodes diff --git a/crates/hotshot/src/traits/networking/libp2p_network.rs b/crates/hotshot/src/traits/networking/libp2p_network.rs index 1dc082c76c..3895200a7a 100644 --- a/crates/hotshot/src/traits/networking/libp2p_network.rs +++ b/crates/hotshot/src/traits/networking/libp2p_network.rs @@ -345,7 +345,7 @@ impl Libp2pNetwork { /// # Panics /// If we are unable to calculate the replication factor pub async fn from_config( - mut config: NetworkConfig, + mut config: NetworkConfig, bind_address: SocketAddr, pub_key: &K, priv_key: &K::PrivateKey, diff --git a/crates/orchestrator/src/client.rs b/crates/orchestrator/src/client.rs index c4c732d39c..988cb22a27 100644 --- a/crates/orchestrator/src/client.rs +++ b/crates/orchestrator/src/client.rs @@ -3,11 +3,7 @@ use std::{net::SocketAddr, time::Duration}; use async_compatibility_layer::art::async_sleep; use clap::Parser; use futures::{Future, FutureExt}; -use hotshot_types::{ - constants::Version01, - traits::{election::ElectionConfig, signature_key::SignatureKey}, - PeerConfig, -}; +use hotshot_types::{constants::Version01, traits::signature_key::SignatureKey, PeerConfig}; use libp2p::{Multiaddr, PeerId}; use surf_disco::{error::ClientError, Client}; use tide_disco::Url; @@ -84,8 +80,6 @@ pub struct BenchResultsDownloadConfig { pub transaction_size: u64, /// The number of rounds pub rounds: usize, - /// The type of leader election used - pub leader_election_type: String, // Results starting here /// The average latency of the transactions @@ -196,11 +190,11 @@ impl OrchestratorClient { /// # Errors /// If we were unable to serialize the Libp2p data #[allow(clippy::type_complexity)] - pub async fn get_config_without_peer( + pub async fn get_config_without_peer( &self, libp2p_address: Option, libp2p_public_key: Option, - ) -> anyhow::Result> { + ) -> anyhow::Result> { // Get the (possible) Libp2p advertise address from our args let libp2p_address = libp2p_address.map(|f| { Multiaddr::try_from(format!( @@ -236,7 +230,7 @@ impl OrchestratorClient { // get the corresponding config let f = |client: Client| { async move { - let config: Result, ClientError> = client + let config: Result, ClientError> = client .post(&format!("api/config/{node_index}")) .send() .await; @@ -277,9 +271,7 @@ impl OrchestratorClient { /// /// Does not fail, retries internally until success. #[instrument(skip_all, name = "orchestrator config")] - pub async fn get_config_after_collection( - &self, - ) -> NetworkConfig { + pub async fn get_config_after_collection(&self) -> NetworkConfig { // Define the request for post-register configurations let get_config_after_collection = |client: Client| { async move { @@ -308,12 +300,12 @@ impl OrchestratorClient { /// # Panics /// if unable to post #[instrument(skip(self), name = "orchestrator public keys")] - pub async fn post_and_wait_all_public_keys( + pub async fn post_and_wait_all_public_keys( &self, node_index: u64, my_pub_key: PeerConfig, is_da: bool, - ) -> NetworkConfig { + ) -> NetworkConfig { // send my public key let _send_pubkey_ready_f: Result<(), ClientError> = self .client diff --git a/crates/orchestrator/src/config.rs b/crates/orchestrator/src/config.rs index a7e44f2892..0856b09716 100644 --- a/crates/orchestrator/src/config.rs +++ b/crates/orchestrator/src/config.rs @@ -1,5 +1,4 @@ use std::{ - collections::HashSet, env, fs, net::SocketAddr, num::NonZeroUsize, @@ -11,8 +10,7 @@ use std::{ use clap::ValueEnum; use hotshot_types::{ - traits::{election::ElectionConfig, signature_key::SignatureKey}, - ExecutionType, HotShotConfig, PeerConfig, ValidatorConfig, + traits::signature_key::SignatureKey, ExecutionType, HotShotConfig, PeerConfig, ValidatorConfig, }; use libp2p::{Multiaddr, PeerId}; use serde_inline_default::serde_inline_default; @@ -156,7 +154,7 @@ impl Default for RandomBuilderConfig { /// a network configuration #[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] #[serde(bound(deserialize = ""))] -pub struct NetworkConfig { +pub struct NetworkConfig { /// number of views to run pub rounds: usize, /// number of transactions per view @@ -181,12 +179,10 @@ pub struct NetworkConfig { pub start_delay_seconds: u64, /// name of the key type (for debugging) pub key_type_name: String, - /// election config type (for debugging) - pub election_config_type_name: String, /// the libp2p config pub libp2p_config: Option, /// the hotshot config - pub config: HotShotConfig, + pub config: HotShotConfig, /// the webserver config pub web_server_config: Option, /// the data availability web server config @@ -211,7 +207,7 @@ pub enum NetworkConfigSource { File, } -impl NetworkConfig { +impl NetworkConfig { /// Asynchronously retrieves a `NetworkConfig` either from a file or from an orchestrator. /// /// This function takes an `OrchestratorClient`, an optional file path, and Libp2p-specific parameters. @@ -242,7 +238,7 @@ impl NetworkConfig { file: Option, libp2p_address: Option, libp2p_public_key: Option, - ) -> anyhow::Result<(NetworkConfig, NetworkConfigSource)> { + ) -> anyhow::Result<(NetworkConfig, NetworkConfigSource)> { if let Some(file) = file { info!("Retrieving config from the file"); // if we pass in file, try there first @@ -301,7 +297,7 @@ impl NetworkConfig { libp2p_public_key: Option, // If true, we will use the node index to determine if we are a DA node indexed_da: bool, - ) -> anyhow::Result<(NetworkConfig, NetworkConfigSource)> { + ) -> anyhow::Result<(NetworkConfig, NetworkConfigSource)> { let (mut run_config, source) = Self::from_file_or_orchestrator(client, file, libp2p_address, libp2p_public_key) .await?; @@ -324,8 +320,8 @@ impl NetworkConfig { } // one more round of orchestrator here to get peer's public key/config - let updated_config: NetworkConfig = client - .post_and_wait_all_public_keys::( + let updated_config: NetworkConfig = client + .post_and_wait_all_public_keys::( run_config.node_index, run_config .config @@ -434,7 +430,7 @@ impl NetworkConfig { } } -impl Default for NetworkConfig { +impl Default for NetworkConfig { fn default() -> Self { Self { rounds: ORCHESTRATOR_DEFAULT_NUM_ROUNDS, @@ -446,7 +442,6 @@ impl Default for NetworkConfig { config: HotShotConfigFile::default().into(), start_delay_seconds: 60, key_type_name: std::any::type_name::().to_string(), - election_config_type_name: std::any::type_name::().to_string(), web_server_config: None, da_web_server_config: None, cdn_marshal_address: None, @@ -512,7 +507,7 @@ pub struct NetworkConfigFile { pub random_builder: Option, } -impl From> for NetworkConfig { +impl From> for NetworkConfig { fn from(val: NetworkConfigFile) -> Self { NetworkConfig { rounds: val.rounds, @@ -544,7 +539,6 @@ impl From> for NetworkC }), config: val.config.into(), key_type_name: std::any::type_name::().to_string(), - election_config_type_name: std::any::type_name::().to_string(), start_delay_seconds: val.start_delay_seconds, cdn_marshal_address: val.cdn_marshal_address, web_server_config: val.web_server_config, @@ -581,7 +575,7 @@ pub struct HotShotConfigFile { pub known_nodes_with_stake: Vec>, #[serde(skip)] /// The known DA nodes' public key and stake values - pub known_da_nodes: HashSet>, + pub known_da_nodes: Vec>, #[serde(skip)] /// The known non-staking nodes' pub known_nodes_without_stake: Vec, @@ -666,7 +660,7 @@ impl ValidatorConfigFile { } } -impl From> for HotShotConfig { +impl From> for HotShotConfig { fn from(val: HotShotConfigFile) -> Self { HotShotConfig { execution_type: ExecutionType::Continuous, @@ -688,7 +682,6 @@ impl From> for HotS num_bootstrap: val.num_bootstrap, builder_timeout: val.builder_timeout, data_request_delay: val.data_request_delay, - election_config: None, builder_url: val.builder_url, } } @@ -708,9 +701,9 @@ impl From for ValidatorConfig { ValidatorConfig::generated_from_seed_indexed(val.seed, val.node_id, 1, val.is_da) } } -impl From for HotShotConfig { +impl From for HotShotConfig { fn from(value: ValidatorConfigFile) -> Self { - let mut config: HotShotConfig = HotShotConfigFile::default().into(); + let mut config: HotShotConfig = HotShotConfigFile::default().into(); config.my_own_validator_config = value.into(); config } @@ -722,7 +715,7 @@ impl Default for HotShotConfigFile { let staked_committee_nodes: usize = 5; // Aggregate the DA nodes - let mut known_da_nodes = HashSet::new(); + let mut known_da_nodes = Vec::new(); let gen_known_nodes_with_stake = (0..10) .map(|node_id| { @@ -731,7 +724,7 @@ impl Default for HotShotConfigFile { // Add to DA nodes based on index if node_id < staked_committee_nodes as u64 { - known_da_nodes.insert(cur_validator_config.get_public_config()); + known_da_nodes.push(cur_validator_config.get_public_config()); cur_validator_config.is_da = true; } diff --git a/crates/orchestrator/src/lib.rs b/crates/orchestrator/src/lib.rs index d7250320ef..69d434947f 100644 --- a/crates/orchestrator/src/lib.rs +++ b/crates/orchestrator/src/lib.rs @@ -11,11 +11,7 @@ use async_lock::RwLock; use client::{BenchResults, BenchResultsDownloadConfig}; use csv::Writer; use futures::FutureExt; -use hotshot_types::{ - constants::Version01, - traits::{election::ElectionConfig, signature_key::SignatureKey}, - PeerConfig, -}; +use hotshot_types::{constants::Version01, traits::signature_key::SignatureKey, PeerConfig}; use libp2p::{ identity::{ ed25519::{Keypair as EdKeypair, SecretKey}, @@ -63,13 +59,13 @@ pub fn libp2p_generate_indexed_identity(seed: [u8; 32], index: u64) -> Keypair { /// The state of the orchestrator #[derive(Default, Clone)] -struct OrchestratorState { +struct OrchestratorState { /// Tracks the latest node index we have generated a configuration for latest_index: u16, /// Tracks the latest temporary index we have generated for init validator's key pair tmp_latest_index: u16, /// The network configuration - config: NetworkConfig, + config: NetworkConfig, /// The total nodes that have posted their public keys nodes_with_pubkey: u64, /// Whether the network configuration has been updated with all the peer's public keys/configs @@ -87,11 +83,9 @@ struct OrchestratorState { nodes_post_results: u64, } -impl - OrchestratorState -{ +impl OrchestratorState { /// create a new [`OrchestratorState`] - pub fn new(network_config: NetworkConfig) -> Self { + pub fn new(network_config: NetworkConfig) -> Self { OrchestratorState { latest_index: 0, tmp_latest_index: 0, @@ -115,7 +109,6 @@ impl transactions_per_round: self.config.transactions_per_round, transaction_size: self.bench_results.transaction_size_in_bytes, rounds: self.config.rounds, - leader_election_type: self.config.election_config_type_name.clone(), avg_latency_in_sec: self.bench_results.avg_latency_in_sec, minimum_latency_in_sec: self.bench_results.minimum_latency_in_sec, maximum_latency_in_sec: self.bench_results.maximum_latency_in_sec, @@ -140,7 +133,7 @@ impl } /// An api exposed by the orchestrator -pub trait OrchestratorApi { +pub trait OrchestratorApi { /// Post an identity to the orchestrator. Takes in optional /// arguments so others can identify us on the Libp2p network. /// # Errors @@ -153,10 +146,7 @@ pub trait OrchestratorApi { /// post endpoint for each node's config /// # Errors /// if unable to serve - fn post_getconfig( - &mut self, - _node_index: u16, - ) -> Result, ServerError>; + fn post_getconfig(&mut self, _node_index: u16) -> Result, ServerError>; /// get endpoint for the next available temporary node index /// # Errors /// if unable to serve @@ -177,7 +167,7 @@ pub trait OrchestratorApi { /// get endpoint for the network config after all peers public keys are collected /// # Errors /// if unable to serve - fn get_config_after_peer_collected(&self) -> Result, ServerError>; + fn get_config_after_peer_collected(&self) -> Result, ServerError>; /// get endpoint for whether or not the run has started /// # Errors /// if unable to serve @@ -192,10 +182,9 @@ pub trait OrchestratorApi { fn post_ready(&mut self) -> Result<(), ServerError>; } -impl OrchestratorApi for OrchestratorState +impl OrchestratorApi for OrchestratorState where KEY: serde::Serialize + Clone + SignatureKey + 'static, - ELECTION: serde::Serialize + Clone + Send + ElectionConfig + 'static, { /// Post an identity to the orchestrator. Takes in optional /// arguments so others can identify us on the Libp2p network. @@ -236,10 +225,7 @@ where // Assumes nodes will set their own index that they received from the // 'identity' endpoint - fn post_getconfig( - &mut self, - _node_index: u16, - ) -> Result, ServerError> { + fn post_getconfig(&mut self, _node_index: u16) -> Result, ServerError> { Ok(self.config.clone()) } @@ -284,7 +270,7 @@ where self.config .config .known_da_nodes - .insert(register_pub_key_with_stake); + .push(register_pub_key_with_stake); }; self.nodes_with_pubkey += 1; @@ -308,7 +294,7 @@ where Ok(self.peer_pub_ready) } - fn get_config_after_peer_collected(&self) -> Result, ServerError> { + fn get_config_after_peer_collected(&self) -> Result, ServerError> { if !self.peer_pub_ready { return Err(ServerError { status: tide_disco::StatusCode::BadRequest, @@ -393,13 +379,12 @@ where } /// Sets up all API routes -fn define_api( +fn define_api( ) -> Result, ApiError> where State: 'static + Send + Sync + ReadState + WriteState, - ::State: Send + Sync + OrchestratorApi, + ::State: Send + Sync + OrchestratorApi, KEY: serde::Serialize, - ELECTION: serde::Serialize, VER: 'static, { let api_toml = toml::from_str::(include_str!(concat!( @@ -476,21 +461,16 @@ where /// This errors if tide disco runs into an issue during serving /// # Panics /// This panics if unable to register the api with tide disco -pub async fn run_orchestrator( - network_config: NetworkConfig, - url: Url, -) -> io::Result<()> +pub async fn run_orchestrator(network_config: NetworkConfig, url: Url) -> io::Result<()> where KEY: SignatureKey + 'static + serde::Serialize, - ELECTION: ElectionConfig + 'static + serde::Serialize, { let web_api = define_api().map_err(|_e| io::Error::new(ErrorKind::Other, "Failed to define api")); - let state: RwLock> = - RwLock::new(OrchestratorState::new(network_config)); + let state: RwLock> = RwLock::new(OrchestratorState::new(network_config)); - let mut app = App::>, ServerError>::with_state(state); + let mut app = App::>, ServerError>::with_state(state); app.register_module::("api", web_api.unwrap()) .expect("Error registering api"); tracing::error!("listening on {:?}", url); diff --git a/crates/testing/src/spinning_task.rs b/crates/testing/src/spinning_task.rs index 3b87d85dad..5ca2754c16 100644 --- a/crates/testing/src/spinning_task.rs +++ b/crates/testing/src/spinning_task.rs @@ -67,7 +67,7 @@ impl< N: ConnectedNetwork, TYPES::SignatureKey>, > TestTaskState for SpinningTask where - I: TestableNodeImplementation, + I: TestableNodeImplementation, I: NodeImplementation< TYPES, QuorumNetwork = N, diff --git a/crates/testing/src/task_helpers.rs b/crates/testing/src/task_helpers.rs index 43b1dd642d..02442b5648 100644 --- a/crates/testing/src/task_helpers.rs +++ b/crates/testing/src/task_helpers.rs @@ -61,20 +61,6 @@ pub async fn build_system_handle( let _known_nodes_without_stake = config.known_nodes_without_stake.clone(); - let quorum_election_config = config.election_config.clone().unwrap_or_else(|| { - ::Membership::default_election_config( - config.num_nodes_with_stake.get() as u64, - config.num_nodes_without_stake as u64, - ) - }); - - let committee_election_config = config.election_config.clone().unwrap_or_else(|| { - ::Membership::default_election_config( - // Use the _actual_ number of known DA nodes instead of the expected number of DA nodes - config.known_da_nodes.len() as u64, - config.num_nodes_without_stake as u64, - ) - }); let networks_bundle = Networks { quorum_network: networks.0.clone(), da_network: networks.1.clone(), @@ -84,22 +70,22 @@ pub async fn build_system_handle( let memberships = Memberships { quorum_membership: ::Membership::create_election( known_nodes_with_stake.clone(), - quorum_election_config.clone(), + known_nodes_with_stake.clone(), config.fixed_leader_for_gpuvid, ), da_membership: ::Membership::create_election( known_nodes_with_stake.clone(), - committee_election_config, + config.known_da_nodes.clone(), config.fixed_leader_for_gpuvid, ), vid_membership: ::Membership::create_election( known_nodes_with_stake.clone(), - quorum_election_config.clone(), + known_nodes_with_stake.clone(), config.fixed_leader_for_gpuvid, ), view_sync_membership: ::Membership::create_election( known_nodes_with_stake.clone(), - quorum_election_config, + known_nodes_with_stake, config.fixed_leader_for_gpuvid, ), }; @@ -279,6 +265,7 @@ pub fn build_vid_proposal( pub fn build_da_certificate( quorum_membership: &::Membership, + da_membership: &::Membership, view_number: ViewNumber, transactions: Vec, public_key: &::SignatureKey, @@ -295,7 +282,7 @@ pub fn build_da_certificate( build_cert::, DACertificate>( da_data, - quorum_membership, + da_membership, view_number, public_key, private_key, diff --git a/crates/testing/src/test_builder.rs b/crates/testing/src/test_builder.rs index 8421de7f8d..26ebc85922 100644 --- a/crates/testing/src/test_builder.rs +++ b/crates/testing/src/test_builder.rs @@ -1,11 +1,10 @@ -use std::{collections::HashSet, num::NonZeroUsize, sync::Arc, time::Duration}; +use std::{num::NonZeroUsize, sync::Arc, time::Duration}; use hotshot::traits::{NetworkReliability, NodeImplementation, TestableNodeImplementation}; use hotshot_example_types::{state_types::TestInstanceState, storage_types::TestStorage}; use hotshot_orchestrator::config::ValidatorConfigFile; use hotshot_types::{ - traits::{election::Membership, node_implementation::NodeType}, - ExecutionType, HotShotConfig, ValidatorConfig, + traits::node_implementation::NodeType, ExecutionType, HotShotConfig, ValidatorConfig, }; use tide_disco::Url; @@ -230,7 +229,7 @@ impl TestDescription { #[must_use] pub fn gen_launcher< TYPES: NodeType, - I: TestableNodeImplementation, + I: TestableNodeImplementation, >( self, node_id: u64, @@ -248,7 +247,7 @@ impl TestDescription { .. } = self.clone(); - let mut known_da_nodes = HashSet::new(); + let mut known_da_nodes = Vec::new(); // We assign known_nodes' public key and stake value here rather than read from config file since it's a test. let known_nodes_with_stake = (0..num_nodes_with_stake) @@ -263,7 +262,7 @@ impl TestDescription { // Add the node to the known DA nodes based on the index (for tests) if node_id_ < da_staked_committee_size { - known_da_nodes.insert(cur_validator_config.get_public_config()); + known_da_nodes.push(cur_validator_config.get_public_config()); } cur_validator_config.get_public_config() @@ -305,11 +304,6 @@ impl TestDescription { start_delay: 1, builder_timeout: Duration::from_millis(1000), data_request_delay: Duration::from_millis(200), - // TODO what's the difference between this and the second config? - election_config: Some(TYPES::Membership::default_election_config( - num_nodes_with_stake as u64, - 0, - )), // Placeholder until we spin up the builder builder_url: Url::parse("http://localhost:9999").expect("Valid URL"), }; @@ -325,7 +319,7 @@ impl TestDescription { } = timing_data; let mod_config = // TODO this should really be using the timing config struct - |a: &mut HotShotConfig| { + |a: &mut HotShotConfig| { a.next_view_timeout = next_view_timeout; a.timeout_ratio = timeout_ratio; a.round_start_delay = round_start_delay; diff --git a/crates/testing/src/test_launcher.rs b/crates/testing/src/test_launcher.rs index 8f2ed21cc0..5845350b97 100644 --- a/crates/testing/src/test_launcher.rs +++ b/crates/testing/src/test_launcher.rs @@ -29,7 +29,7 @@ pub struct ResourceGenerators>, /// configuration used to generate each hotshot node - pub config: HotShotConfig, + pub config: HotShotConfig, } /// test launcher @@ -58,7 +58,7 @@ impl> TestLauncher), + mut f: impl FnMut(&mut HotShotConfig), ) -> Self { f(&mut self.resource_generator.config); self diff --git a/crates/testing/src/test_runner.rs b/crates/testing/src/test_runner.rs index 23d06cad82..85e5025666 100644 --- a/crates/testing/src/test_runner.rs +++ b/crates/testing/src/test_runner.rs @@ -61,7 +61,7 @@ pub type LateNodeContext = Either< ( >::Storage, Memberships, - HotShotConfig<::SignatureKey, ::ElectionConfigType>, + HotShotConfig<::SignatureKey>, ), >; @@ -119,7 +119,7 @@ impl< N: ConnectedNetwork, TYPES::SignatureKey>, > TestRunner where - I: TestableNodeImplementation, + I: TestableNodeImplementation, I: NodeImplementation< TYPES, QuorumNetwork = N, @@ -335,12 +335,7 @@ where let mut results = vec![]; let config = self.launcher.resource_generator.config.clone(); let known_nodes_with_stake = config.known_nodes_with_stake.clone(); - let quorum_election_config = config.election_config.clone().unwrap_or_else(|| { - TYPES::Membership::default_election_config( - config.num_nodes_with_stake.get() as u64, - config.num_nodes_without_stake as u64, - ) - }); + let (mut builder_task, builder_url) = B::start(config.num_nodes_with_stake.into(), B::Config::default()).await; for i in 0..total { @@ -349,30 +344,25 @@ where self.next_node_id += 1; tracing::debug!("launch node {}", i); - let committee_election_config = I::committee_election_config_generator(); let memberships = Memberships { quorum_membership: ::Membership::create_election( known_nodes_with_stake.clone(), - quorum_election_config.clone(), + known_nodes_with_stake.clone(), config.fixed_leader_for_gpuvid, ), da_membership: ::Membership::create_election( known_nodes_with_stake.clone(), - committee_election_config( - // Use the _actual_ number of DA nodes instead of expected - config.known_da_nodes.len() as u64, - config.num_nodes_without_stake as u64, - ), + config.known_da_nodes.clone(), config.fixed_leader_for_gpuvid, ), vid_membership: ::Membership::create_election( known_nodes_with_stake.clone(), - quorum_election_config.clone(), + known_nodes_with_stake.clone(), config.fixed_leader_for_gpuvid, ), view_sync_membership: ::Membership::create_election( known_nodes_with_stake.clone(), - quorum_election_config.clone(), + known_nodes_with_stake.clone(), config.fixed_leader_for_gpuvid, ), }; @@ -446,7 +436,7 @@ where networks: Networks, memberships: Memberships, initializer: HotShotInitializer, - config: HotShotConfig, + config: HotShotConfig, validator_config: ValidatorConfig, storage: I::Storage, ) -> Arc> { diff --git a/crates/testing/src/view_generator.rs b/crates/testing/src/view_generator.rs index 8a43cb980d..321e5e6ac9 100644 --- a/crates/testing/src/view_generator.rs +++ b/crates/testing/src/view_generator.rs @@ -37,6 +37,7 @@ pub struct TestView { pub leaf: Leaf, pub view_number: ViewNumber, pub quorum_membership: ::Membership, + pub da_membership: ::Membership, pub vid_proposal: ( Vec>>, ::SignatureKey, @@ -51,7 +52,10 @@ pub struct TestView { } impl TestView { - pub fn genesis(quorum_membership: &::Membership) -> Self { + pub fn genesis( + quorum_membership: &::Membership, + da_membership: &::Membership, + ) -> Self { let genesis_view = ViewNumber::new(1); let transactions = Vec::new(); @@ -78,6 +82,7 @@ impl TestView { let da_certificate = build_da_certificate( quorum_membership, + da_membership, genesis_view, transactions.clone(), &public_key, @@ -136,6 +141,7 @@ impl TestView { leaf, view_number: genesis_view, quorum_membership: quorum_membership.clone(), + da_membership: da_membership.clone(), vid_proposal: (vid_proposal, public_key), da_certificate, transactions, @@ -162,6 +168,8 @@ impl TestView { let next_view = max(old_view, self.view_number) + 1; let quorum_membership = &self.quorum_membership; + let da_membership = &self.da_membership; + let transactions = &self.transactions; let quorum_data = QuorumData { @@ -192,6 +200,7 @@ impl TestView { let da_certificate = build_da_certificate( quorum_membership, + da_membership, next_view, transactions.clone(), &public_key, @@ -326,6 +335,7 @@ impl TestView { leaf, view_number: next_view, quorum_membership: quorum_membership.clone(), + da_membership: self.da_membership.clone(), vid_proposal: (vid_proposal, public_key), da_certificate, leader_public_key, @@ -393,13 +403,18 @@ impl TestView { pub struct TestViewGenerator { pub current_view: Option, pub quorum_membership: ::Membership, + pub da_membership: ::Membership, } impl TestViewGenerator { - pub fn generate(quorum_membership: ::Membership) -> Self { + pub fn generate( + quorum_membership: ::Membership, + da_membership: ::Membership, + ) -> Self { TestViewGenerator { current_view: None, quorum_membership, + da_membership, } } @@ -479,7 +494,10 @@ impl Iterator for TestViewGenerator { if let Some(view) = &self.current_view { self.current_view = Some(TestView::next_view(view)); } else { - self.current_view = Some(TestView::genesis(&self.quorum_membership)); + self.current_view = Some(TestView::genesis( + &self.quorum_membership, + &self.da_membership, + )); } self.current_view.clone() diff --git a/crates/testing/tests/tests_1/consensus_task.rs b/crates/testing/tests/tests_1/consensus_task.rs index 1b37aae268..05646e60dd 100644 --- a/crates/testing/tests/tests_1/consensus_task.rs +++ b/crates/testing/tests/tests_1/consensus_task.rs @@ -1,12 +1,9 @@ -use hotshot::{ - tasks::{inject_consensus_polls, task_state::CreateTaskState}, -}; +use hotshot::tasks::{inject_consensus_polls, task_state::CreateTaskState}; use std::sync::Arc; - -use hotshot_example_types::state_types::TestInstanceState; use hotshot_example_types::node_types::{MemoryImpl, TestTypes}; +use hotshot_example_types::state_types::TestInstanceState; use hotshot_task_impls::{consensus::ConsensusTaskState, events::HotShotEvent::*}; use hotshot_testing::{ predicates::event::{ @@ -40,6 +37,7 @@ async fn test_consensus_task() { let handle = build_system_handle(2).await.0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); + let da_membership = handle.hotshot.memberships.da_membership.clone(); // Make some empty encoded transactions, we just care about having a commitment handy for the // later calls. We need the VID commitment to be able to propose later. @@ -48,7 +46,8 @@ async fn test_consensus_task() { let vid_disperse = vid.disperse(&encoded_transactions).unwrap(); let payload_commitment = vid_disperse.commit; - let mut generator = TestViewGenerator::generate(quorum_membership.clone()); + let mut generator = + TestViewGenerator::generate(quorum_membership.clone(), da_membership.clone()); let mut proposals = Vec::new(); let mut leaders = Vec::new(); @@ -92,7 +91,11 @@ async fn test_consensus_task() { builder_commitment, TestMetadata, ViewNumber::new(2), - null_block::builder_fee(quorum_membership.total_nodes(), Arc::new(TestInstanceState {})).unwrap(), + null_block::builder_fee( + quorum_membership.total_nodes(), + Arc::new(TestInstanceState {}), + ) + .unwrap(), ), ], outputs: vec![ @@ -103,11 +106,7 @@ async fn test_consensus_task() { asserts: vec![], }; - let consensus_state = ConsensusTaskState::< - TestTypes, - MemoryImpl, - >::create_from(&handle) - .await; + let consensus_state = ConsensusTaskState::::create_from(&handle).await; inject_consensus_polls(&consensus_state).await; @@ -131,8 +130,10 @@ async fn test_consensus_vote() { let handle = build_system_handle(2).await.0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); + let da_membership = handle.hotshot.memberships.da_membership.clone(); - let mut generator = TestViewGenerator::generate(quorum_membership.clone()); + let mut generator = + TestViewGenerator::generate(quorum_membership.clone(), da_membership.clone()); let mut proposals = Vec::new(); let mut leaders = Vec::new(); @@ -163,11 +164,7 @@ async fn test_consensus_vote() { asserts: vec![], }; - let consensus_state = ConsensusTaskState::< - TestTypes, - MemoryImpl, - >::create_from(&handle) - .await; + let consensus_state = ConsensusTaskState::::create_from(&handle).await; inject_consensus_polls(&consensus_state).await; run_test_script(vec![view_1], consensus_state).await; @@ -182,8 +179,10 @@ async fn test_vote_with_specific_order(input_permutation: Vec) { let handle = build_system_handle(2).await.0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); + let da_membership = handle.hotshot.memberships.da_membership.clone(); - let mut generator = TestViewGenerator::generate(quorum_membership.clone()); + let mut generator = + TestViewGenerator::generate(quorum_membership.clone(), da_membership.clone()); let mut proposals = Vec::new(); let mut leaders = Vec::new(); @@ -232,11 +231,7 @@ async fn test_vote_with_specific_order(input_permutation: Vec) { asserts: vec![], }; - let consensus_state = ConsensusTaskState::< - TestTypes, - MemoryImpl, - >::create_from(&handle) - .await; + let consensus_state = ConsensusTaskState::::create_from(&handle).await; inject_consensus_polls(&consensus_state).await; run_test_script(vec![view_1, view_2], consensus_state).await; @@ -270,6 +265,8 @@ async fn test_view_sync_finalize_propose() { let handle = build_system_handle(4).await.0; let (priv_key, pub_key) = key_pair_for_id(4); let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); + let da_membership = handle.hotshot.memberships.da_membership.clone(); + // Make some empty encoded transactions, we just care about having a commitment handy for the // later calls. We need the VID commitment to be able to propose later. let mut vid = vid_scheme_from_view_number::(&quorum_membership, ViewNumber::new(4)); @@ -282,7 +279,8 @@ async fn test_view_sync_finalize_propose() { round: ViewNumber::new(4), }; - let mut generator = TestViewGenerator::generate(quorum_membership.clone()); + let mut generator = + TestViewGenerator::generate(quorum_membership.clone(), da_membership.clone()); let mut proposals = Vec::new(); let mut leaders = Vec::new(); let mut votes = Vec::new(); @@ -384,11 +382,7 @@ async fn test_view_sync_finalize_propose() { asserts: vec![], }; - let consensus_state = ConsensusTaskState::< - TestTypes, - MemoryImpl, - >::create_from(&handle) - .await; + let consensus_state = ConsensusTaskState::::create_from(&handle).await; let stages = vec![view_1, view_2_3, view_4]; @@ -407,13 +401,15 @@ async fn test_view_sync_finalize_vote() { let handle = build_system_handle(5).await.0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); + let da_membership = handle.hotshot.memberships.da_membership.clone(); let view_sync_finalize_data: ViewSyncFinalizeData = ViewSyncFinalizeData { relay: 4, round: ViewNumber::new(5), }; - let mut generator = TestViewGenerator::generate(quorum_membership.clone()); + let mut generator = + TestViewGenerator::generate(quorum_membership.clone(), da_membership.clone()); let mut proposals = Vec::new(); let mut leaders = Vec::new(); let mut votes = Vec::new(); @@ -483,11 +479,7 @@ async fn test_view_sync_finalize_vote() { asserts: vec![], }; - let consensus_state = ConsensusTaskState::< - TestTypes, - MemoryImpl, - >::create_from(&handle) - .await; + let consensus_state = ConsensusTaskState::::create_from(&handle).await; let stages = vec![view_1, view_2, view_3]; @@ -506,13 +498,15 @@ async fn test_view_sync_finalize_vote_fail_view_number() { let handle = build_system_handle(5).await.0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); + let da_membership = handle.hotshot.memberships.da_membership.clone(); let view_sync_finalize_data: ViewSyncFinalizeData = ViewSyncFinalizeData { relay: 4, round: ViewNumber::new(10), }; - let mut generator = TestViewGenerator::generate(quorum_membership.clone()); + let mut generator = + TestViewGenerator::generate(quorum_membership.clone(), da_membership.clone()); let mut proposals = Vec::new(); let mut leaders = Vec::new(); let mut votes = Vec::new(); @@ -592,11 +586,7 @@ async fn test_view_sync_finalize_vote_fail_view_number() { asserts: vec![], }; - let consensus_state = ConsensusTaskState::< - TestTypes, - MemoryImpl, - >::create_from(&handle) - .await; + let consensus_state = ConsensusTaskState::::create_from(&handle).await; let stages = vec![view_1, view_2, view_3]; @@ -616,7 +606,10 @@ async fn test_vid_disperse_storage_failure() { // Set the error flag here for the system handle. This causes it to emit an error on append. handle.get_storage().write().await.should_return_err = true; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); - let mut generator = TestViewGenerator::generate(quorum_membership.clone()); + let da_membership = handle.hotshot.memberships.da_membership.clone(); + + let mut generator = + TestViewGenerator::generate(quorum_membership.clone(), da_membership.clone()); let mut proposals = Vec::new(); let mut leaders = Vec::new(); @@ -646,11 +639,7 @@ async fn test_vid_disperse_storage_failure() { asserts: vec![], }; - let consensus_state = ConsensusTaskState::< - TestTypes, - MemoryImpl, - >::create_from(&handle) - .await; + let consensus_state = ConsensusTaskState::::create_from(&handle).await; inject_consensus_polls(&consensus_state).await; diff --git a/crates/testing/tests/tests_1/da_task.rs b/crates/testing/tests/tests_1/da_task.rs index 43dba3ae9d..2aa0a9472f 100644 --- a/crates/testing/tests/tests_1/da_task.rs +++ b/crates/testing/tests/tests_1/da_task.rs @@ -31,6 +31,8 @@ async fn test_da_task() { let handle = build_system_handle(2).await.0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); + let da_membership = handle.hotshot.memberships.da_membership.clone(); + // Make some empty encoded transactions, we just care about having a commitment handy for the // later calls. We need the VID commitment to be able to propose later. @@ -41,7 +43,7 @@ async fn test_da_task() { handle.hotshot.memberships.quorum_membership.total_nodes(), ); - let mut generator = TestViewGenerator::generate(quorum_membership.clone()); + let mut generator = TestViewGenerator::generate(quorum_membership.clone(), da_membership); let mut proposals = Vec::new(); let mut leaders = Vec::new(); @@ -110,6 +112,8 @@ async fn test_da_task_storage_failure() { // Set the error flag here for the system handle. This causes it to emit an error on append. handle.get_storage().write().await.should_return_err = true; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); + let da_membership = handle.hotshot.memberships.da_membership.clone(); + // Make some empty encoded transactions, we just care about having a commitment handy for the // later calls. We need the VID commitment to be able to propose later. @@ -120,7 +124,7 @@ async fn test_da_task_storage_failure() { handle.hotshot.memberships.quorum_membership.total_nodes(), ); - let mut generator = TestViewGenerator::generate(quorum_membership.clone()); + let mut generator = TestViewGenerator::generate(quorum_membership.clone(), da_membership); let mut proposals = Vec::new(); let mut leaders = Vec::new(); diff --git a/crates/testing/tests/tests_1/network_task.rs b/crates/testing/tests/tests_1/network_task.rs index 04a7594911..631c6add2e 100644 --- a/crates/testing/tests/tests_1/network_task.rs +++ b/crates/testing/tests/tests_1/network_task.rs @@ -40,16 +40,10 @@ async fn test_network_task() { let config = launcher.resource_generator.config.clone(); let public_key = config.my_own_validator_config.public_key; let known_nodes_with_stake = config.known_nodes_with_stake.clone(); - let quorum_election_config = config.election_config.clone().unwrap_or_else(|| { - ::Membership::default_election_config( - config.num_nodes_with_stake.get() as u64, - config.num_nodes_without_stake as u64, - ) - }); let membership = ::Membership::create_election( known_nodes_with_stake.clone(), - quorum_election_config.clone(), + known_nodes_with_stake, config.fixed_leader_for_gpuvid, ); let channel = networks.0.clone(); @@ -68,7 +62,7 @@ async fn test_network_task() { let task = Task::new(tx.clone(), rx, task_reg.clone(), network_state); task_reg.run_task(task).await; - let mut generator = TestViewGenerator::generate(membership.clone()); + let mut generator = TestViewGenerator::generate(membership.clone(), membership); let view = generator.next().unwrap(); let (out_tx, mut out_rx) = async_broadcast::broadcast(10); @@ -109,16 +103,10 @@ async fn test_network_storage_fail() { let config = launcher.resource_generator.config.clone(); let public_key = config.my_own_validator_config.public_key; let known_nodes_with_stake = config.known_nodes_with_stake.clone(); - let quorum_election_config = config.election_config.clone().unwrap_or_else(|| { - ::Membership::default_election_config( - config.num_nodes_with_stake.get() as u64, - config.num_nodes_without_stake as u64, - ) - }); let membership = ::Membership::create_election( known_nodes_with_stake.clone(), - quorum_election_config.clone(), + known_nodes_with_stake, config.fixed_leader_for_gpuvid, ); let channel = networks.0.clone(); @@ -137,7 +125,7 @@ async fn test_network_storage_fail() { let task = Task::new(tx.clone(), rx, task_reg.clone(), network_state); task_reg.run_task(task).await; - let mut generator = TestViewGenerator::generate(membership.clone()); + let mut generator = TestViewGenerator::generate(membership.clone(), membership); let view = generator.next().unwrap(); let (out_tx, mut out_rx) = async_broadcast::broadcast(10); diff --git a/crates/testing/tests/tests_1/proposal_ordering.rs b/crates/testing/tests/tests_1/proposal_ordering.rs index e430362255..a5a53fd0f3 100644 --- a/crates/testing/tests/tests_1/proposal_ordering.rs +++ b/crates/testing/tests/tests_1/proposal_ordering.rs @@ -38,6 +38,8 @@ async fn test_ordering_with_specific_order(input_permutation: Vec) { let node_id = 2; let handle = build_system_handle(node_id).await.0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); + let da_membership = handle.hotshot.memberships.da_membership.clone(); + let mut vid = vid_scheme_from_view_number::(&quorum_membership, ViewNumber::new(node_id)); @@ -48,7 +50,7 @@ async fn test_ordering_with_specific_order(input_permutation: Vec) { let vid_disperse = vid.disperse(&encoded_transactions).unwrap(); let payload_commitment = vid_disperse.commit; - let mut generator = TestViewGenerator::generate(quorum_membership.clone()); + let mut generator = TestViewGenerator::generate(quorum_membership.clone(), da_membership); let mut proposals = Vec::new(); let mut leaders = Vec::new(); diff --git a/crates/testing/tests/tests_1/quorum_proposal_task.rs b/crates/testing/tests/tests_1/quorum_proposal_task.rs index d977c229b2..6ff624b12f 100644 --- a/crates/testing/tests/tests_1/quorum_proposal_task.rs +++ b/crates/testing/tests/tests_1/quorum_proposal_task.rs @@ -52,9 +52,11 @@ async fn test_quorum_proposal_task_quorum_proposal() { // case in the genesis view. let handle = build_system_handle(2).await.0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); + let da_membership = handle.hotshot.memberships.da_membership.clone(); + let payload_commitment = make_payload_commitment(&quorum_membership, ViewNumber::new(2)); - let mut generator = TestViewGenerator::generate(quorum_membership.clone()); + let mut generator = TestViewGenerator::generate(quorum_membership.clone(), da_membership); let mut proposals = Vec::new(); let mut leaders = Vec::new(); @@ -131,10 +133,12 @@ async fn test_quorum_proposal_task_qc_timeout() { let handle = build_system_handle(2).await.0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); + let da_membership = handle.hotshot.memberships.da_membership.clone(); + let payload_commitment = make_payload_commitment(&quorum_membership, ViewNumber::new(2)); let builder_commitment = BuilderCommitment::from_raw_digest(sha2::Sha256::new().finalize()); - let mut generator = TestViewGenerator::generate(quorum_membership.clone()); + let mut generator = TestViewGenerator::generate(quorum_membership.clone(), da_membership); let mut proposals = Vec::new(); let mut leaders = Vec::new(); @@ -195,10 +199,12 @@ async fn test_quorum_proposal_task_view_sync() { // case in the genesis view. let handle = build_system_handle(2).await.0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); + let da_membership = handle.hotshot.memberships.da_membership.clone(); + let payload_commitment = make_payload_commitment(&quorum_membership, ViewNumber::new(2)); let builder_commitment = BuilderCommitment::from_raw_digest(sha2::Sha256::new().finalize()); - let mut generator = TestViewGenerator::generate(quorum_membership.clone()); + let mut generator = TestViewGenerator::generate(quorum_membership.clone(), da_membership); let mut proposals = Vec::new(); let mut leaders = Vec::new(); @@ -265,9 +271,11 @@ async fn test_quorum_proposal_task_propose_now() { let handle = build_system_handle(2).await.0; let (private_key, public_key) = key_pair_for_id(2); let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); + let da_membership = handle.hotshot.memberships.da_membership.clone(); + let payload_commitment = make_payload_commitment(&quorum_membership, ViewNumber::new(2)); - let mut generator = TestViewGenerator::generate(quorum_membership.clone()); + let mut generator = TestViewGenerator::generate(quorum_membership.clone(), da_membership); let mut proposals = Vec::new(); let mut leaders = Vec::new(); @@ -388,8 +396,10 @@ async fn test_quorum_proposal_task_with_incomplete_events() { // case in the genesis view. let handle = build_system_handle(2).await.0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); + let da_membership = handle.hotshot.memberships.da_membership.clone(); + - let mut generator = TestViewGenerator::generate(quorum_membership.clone()); + let mut generator = TestViewGenerator::generate(quorum_membership.clone(), da_membership); let mut proposals = Vec::new(); let mut leaders = Vec::new(); diff --git a/crates/testing/tests/tests_1/quorum_vote_task.rs b/crates/testing/tests/tests_1/quorum_vote_task.rs index 09f4fbadc6..ee7bfdb5ac 100644 --- a/crates/testing/tests/tests_1/quorum_vote_task.rs +++ b/crates/testing/tests/tests_1/quorum_vote_task.rs @@ -21,8 +21,10 @@ async fn test_quorum_vote_task_success() { let handle = build_system_handle(2).await.0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); + let da_membership = handle.hotshot.memberships.da_membership.clone(); - let mut generator = TestViewGenerator::generate(quorum_membership.clone()); + + let mut generator = TestViewGenerator::generate(quorum_membership.clone(), da_membership); generator.next(); let view = generator.current_view.clone().unwrap(); @@ -70,8 +72,10 @@ async fn test_quorum_vote_task_vote_now() { let handle = build_system_handle(2).await.0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); + let da_membership = handle.hotshot.memberships.da_membership.clone(); + - let mut generator = TestViewGenerator::generate(quorum_membership.clone()); + let mut generator = TestViewGenerator::generate(quorum_membership.clone(), da_membership); generator.next(); let view = generator.current_view.clone().unwrap(); @@ -116,8 +120,10 @@ async fn test_quorum_vote_task_miss_dependency() { let handle = build_system_handle(2).await.0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); + let da_membership = handle.hotshot.memberships.da_membership.clone(); + - let mut generator = TestViewGenerator::generate(quorum_membership.clone()); + let mut generator = TestViewGenerator::generate(quorum_membership.clone(), da_membership); let mut proposals = Vec::new(); let mut leaders = Vec::new(); diff --git a/crates/testing/tests/tests_1/upgrade_task.rs b/crates/testing/tests/tests_1/upgrade_task.rs index 0ed62a373b..8f321895d9 100644 --- a/crates/testing/tests/tests_1/upgrade_task.rs +++ b/crates/testing/tests/tests_1/upgrade_task.rs @@ -42,6 +42,8 @@ async fn test_consensus_task_upgrade() { let handle = build_system_handle(1).await.0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); + let da_membership = handle.hotshot.memberships.da_membership.clone(); + let old_version = Version { major: 0, minor: 1 }; let new_version = Version { major: 0, minor: 2 }; @@ -61,7 +63,7 @@ async fn test_consensus_task_upgrade() { let mut vids = Vec::new(); let mut leaders = Vec::new(); - let mut generator = TestViewGenerator::generate(quorum_membership.clone()); + let mut generator = TestViewGenerator::generate(quorum_membership.clone(), da_membership); for view in (&mut generator).take(2) { proposals.push(view.quorum_proposal.clone()); @@ -176,6 +178,8 @@ async fn test_upgrade_and_consensus_task() { let handle = build_system_handle(2).await.0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); + let da_membership = handle.hotshot.memberships.da_membership.clone(); + let other_handles = futures::future::join_all((0..=9).map(build_system_handle)).await; @@ -198,7 +202,7 @@ async fn test_upgrade_and_consensus_task() { let mut leaders = Vec::new(); let mut views = Vec::new(); - let mut generator = TestViewGenerator::generate(quorum_membership.clone()); + let mut generator = TestViewGenerator::generate(quorum_membership.clone(), da_membership); for view in (&mut generator).take(1) { proposals.push(view.quorum_proposal.clone()); @@ -336,6 +340,8 @@ async fn test_upgrade_and_consensus_task_blank_blocks() { let handle = build_system_handle(6).await.0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); + let da_membership = handle.hotshot.memberships.da_membership.clone(); + let old_version = Version { major: 0, minor: 1 }; let new_version = Version { major: 0, minor: 2 }; @@ -356,7 +362,7 @@ async fn test_upgrade_and_consensus_task_blank_blocks() { let mut leaders = Vec::new(); let mut views = Vec::new(); - let mut generator = TestViewGenerator::generate(quorum_membership.clone()); + let mut generator = TestViewGenerator::generate(quorum_membership.clone(), da_membership); for view in (&mut generator).take(1) { proposals.push(view.quorum_proposal.clone()); diff --git a/crates/testing/tests/tests_3/memory_network.rs b/crates/testing/tests/tests_3/memory_network.rs index 15bc954497..cd6e04f2e9 100644 --- a/crates/testing/tests/tests_3/memory_network.rs +++ b/crates/testing/tests/tests_3/memory_network.rs @@ -3,7 +3,7 @@ use std::collections::BTreeSet; use std::sync::Arc; use async_compatibility_layer::logging::setup_logging; -use hotshot::traits::election::static_committee::{GeneralStaticCommittee, StaticElectionConfig}; +use hotshot::traits::election::static_committee::GeneralStaticCommittee; use hotshot::traits::implementations::{MasterMap, MemoryNetwork, NetworkingMetricsValue}; use hotshot::traits::NodeImplementation; use hotshot::types::SignatureKey; @@ -50,7 +50,6 @@ impl NodeType for Test { type BlockPayload = TestBlockPayload; type SignatureKey = BLSPubKey; type Transaction = TestTransaction; - type ElectionConfigType = StaticElectionConfig; type ValidatedState = TestValidatedState; type InstanceState = TestInstanceState; type Membership = GeneralStaticCommittee; diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index e9ca937f5d..4fe91f8d8f 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -1,13 +1,11 @@ //! Types and Traits for the `HotShot` consensus module -use std::{ - collections::HashSet, fmt::Debug, future::Future, num::NonZeroUsize, pin::Pin, time::Duration, -}; +use std::{fmt::Debug, future::Future, num::NonZeroUsize, pin::Pin, time::Duration}; use bincode::Options; use displaydoc::Display; use light_client::StateVerKey; use tracing::error; -use traits::{election::ElectionConfig, signature_key::SignatureKey}; +use traits::signature_key::SignatureKey; use url::Url; use crate::utils::bincode_opts; @@ -157,7 +155,7 @@ impl Default for PeerConfig { /// Holds configuration for a `HotShot` #[derive(Clone, custom_debug::Debug, serde::Serialize, serde::Deserialize)] #[serde(bound(deserialize = ""))] -pub struct HotShotConfig { +pub struct HotShotConfig { /// Whether to run one view or continuous views pub execution_type: ExecutionType, /// The proportion of nodes required before the orchestrator issues the ready signal, @@ -171,7 +169,7 @@ pub struct HotShotConfig { /// List of known node's public keys and stake value for certificate aggregation, serving as public parameter pub known_nodes_with_stake: Vec>, /// All public keys known to be DA nodes - pub known_da_nodes: HashSet>, + pub known_da_nodes: Vec>, /// List of known non-staking nodes' public keys pub known_nodes_without_stake: Vec, /// My own validator config, including my public key, private key, stake value, serving as private parameter @@ -198,8 +196,6 @@ pub struct HotShotConfig { pub builder_timeout: Duration, /// time to wait until we request data associated with a proposal pub data_request_delay: Duration, - /// the election configuration - pub election_config: Option, /// Builder API base URL pub builder_url: Url, } diff --git a/crates/types/src/traits/election.rs b/crates/types/src/traits/election.rs index 956f6654e2..08829b9ae2 100644 --- a/crates/types/src/traits/election.rs +++ b/crates/types/src/traits/election.rs @@ -21,33 +21,15 @@ pub enum ElectionError { MathError, } -/// election config -pub trait ElectionConfig: - Default - + Clone - + serde::Serialize - + for<'de> serde::Deserialize<'de> - + Sync - + Send - + core::fmt::Debug -{ -} - /// A protocol for determining membership in and participating in a committee. pub trait Membership: Clone + Debug + Eq + PartialEq + Send + Sync + Hash + 'static { - /// generate a default election configuration - fn default_election_config( - num_nodes_with_stake: u64, - num_nodes_without_stake: u64, - ) -> TYPES::ElectionConfigType; - /// create an election /// TODO may want to move this to a testableelection trait fn create_election( - entries: Vec>, - config: TYPES::ElectionConfigType, + all_nodes: Vec>, + committee_members: Vec>, fixed_leader_for_gpuvid: usize, ) -> Self; diff --git a/crates/types/src/traits/node_implementation.rs b/crates/types/src/traits/node_implementation.rs index 4f11e66dba..6935ca4653 100644 --- a/crates/types/src/traits/node_implementation.rs +++ b/crates/types/src/traits/node_implementation.rs @@ -17,7 +17,6 @@ use serde::{Deserialize, Serialize}; use super::{ block_contents::{BlockHeader, TestableBlock, Transaction}, - election::ElectionConfig, network::{ AsyncGenerator, ConnectedNetwork, NetworkReliability, TestableNetworkingImplementation, }, @@ -59,13 +58,6 @@ pub trait NodeImplementation: #[allow(clippy::type_complexity)] #[async_trait] pub trait TestableNodeImplementation: NodeImplementation { - /// Election config for the DA committee - type CommitteeElectionConfig; - - /// Generates a committee-specific election - fn committee_election_config_generator( - ) -> Box Self::CommitteeElectionConfig + 'static>; - /// Creates random transaction if possible /// otherwise panics /// `padding` is the bytes of padding to add to the transaction @@ -108,18 +100,6 @@ where I::QuorumNetwork: TestableNetworkingImplementation, I::CommitteeNetwork: TestableNetworkingImplementation, { - type CommitteeElectionConfig = TYPES::ElectionConfigType; - - fn committee_election_config_generator( - ) -> Box Self::CommitteeElectionConfig + 'static> { - Box::new(|num_nodes_with_stake, num_nodes_without_stake| { - ::Membership::default_election_config( - num_nodes_with_stake, - num_nodes_without_stake, - ) - }) - } - fn state_create_random_transaction( state: Option<&TYPES::ValidatedState>, rng: &mut dyn rand::RngCore, @@ -228,8 +208,6 @@ pub trait NodeType: /// /// This should be equal to `BlockPayload::Transaction` type Transaction: Transaction; - /// The election config type that this hotshot setup is using. - type ElectionConfigType: ElectionConfig; /// The instance-level state type that this hotshot setup is using. type InstanceState: InstanceState;