From 802da4aa3b22589882851fcd8fec74cd5e28ac93 Mon Sep 17 00:00:00 2001 From: pls148 <184445976+pls148@users.noreply.github.com> Date: Wed, 12 Feb 2025 13:12:59 -0800 Subject: [PATCH] Push DRB result to Membership --- .../src/traits/election/static_committee.rs | 46 +++++++++++++-- .../src/quorum_proposal/handlers.rs | 2 +- crates/task-impls/src/quorum_vote/handlers.rs | 43 +++++++++++++- crates/testing/src/helpers.rs | 17 +++++- crates/testing/src/test_builder.rs | 15 ++++- crates/testing/src/view_generator.rs | 59 +++++++++++++++++-- crates/testing/tests/tests_1/da_task.rs | 12 ++-- crates/testing/tests/tests_1/message.rs | 6 +- crates/testing/tests/tests_1/network_task.rs | 12 ++-- .../tests_1/quorum_proposal_recv_task.rs | 12 ++-- .../tests/tests_1/quorum_proposal_task.rs | 36 +++++------ .../testing/tests/tests_1/quorum_vote_task.rs | 18 +++--- .../tests_1/upgrade_task_with_proposal.rs | 6 +- .../tests/tests_1/upgrade_task_with_vote.rs | 6 +- .../tests/tests_1/vote_dependency_handle.rs | 6 +- crates/types/src/drb.rs | 9 ++- crates/types/src/traits/election.rs | 13 +++- 17 files changed, 237 insertions(+), 81 deletions(-) diff --git a/crates/hotshot/src/traits/election/static_committee.rs b/crates/hotshot/src/traits/election/static_committee.rs index deae814155..70d69c23f2 100644 --- a/crates/hotshot/src/traits/election/static_committee.rs +++ b/crates/hotshot/src/traits/election/static_committee.rs @@ -6,7 +6,9 @@ use std::{cmp::max, collections::BTreeMap, num::NonZeroU64}; +use async_trait::async_trait; use hotshot_types::{ + drb::{self, DrbResult, INITIAL_DRB_RESULT}, traits::{ election::Membership, node_implementation::NodeType, @@ -15,7 +17,7 @@ use hotshot_types::{ PeerConfig, }; use primitive_types::U256; -use utils::anytrace::Result; +use utils::anytrace::*; #[derive(Clone, Debug, Eq, PartialEq, Hash)] /// The static committee election @@ -38,8 +40,12 @@ pub struct StaticCommittee { /// The nodes on the committee and their stake, indexed by public key indexed_da_stake_table: BTreeMap::StakeTableEntry>, + + /// The results of DRB calculations + drb_result_table: BTreeMap, } +#[async_trait] impl Membership for StaticCommittee { type Error = utils::anytrace::Error; @@ -95,6 +101,7 @@ impl Membership for StaticCommittee { da_stake_table: da_members, indexed_stake_table, indexed_da_stake_table, + drb_result_table: BTreeMap::new(), } } @@ -196,12 +203,29 @@ impl Membership for StaticCommittee { fn lookup_leader( &self, view_number: ::View, - _epoch: Option<::Epoch>, + epoch: Option<::Epoch>, ) -> Result { - #[allow(clippy::cast_possible_truncation)] - let index = *view_number as usize % self.eligible_leaders.len(); - let res = self.eligible_leaders[index].clone(); - Ok(TYPES::SignatureKey::public_key(&res)) + if false{//let Some(epoch) = epoch { + /*let drb_result = if *epoch <= 2 { + &INITIAL_DRB_RESULT + } else { + self.drb_result_table + .get(&epoch) + .ok_or_else(|| panic!("DRB result not available for epoch {:?}", epoch))? + };*/ + let drb_result = &INITIAL_DRB_RESULT; + + Ok(drb::leader::( + view_number, + &self.eligible_leaders, + *drb_result, + )) + } else { + #[allow(clippy::cast_possible_truncation)] + let index = ((*view_number as usize) + 1) % self.eligible_leaders.len(); + let res = self.eligible_leaders[index].clone(); + Ok(TYPES::SignatureKey::public_key(&res)) + } } /// Get the total number of nodes in the committee @@ -234,4 +258,14 @@ impl Membership for StaticCommittee { let len = self.stake_table.len(); NonZeroU64::new(max((len as u64 * 9) / 10, ((len as u64 * 2) / 3) + 1)).unwrap() } + + async fn add_drb_result( + &self, + epoch: TYPES::Epoch, + drb_result: DrbResult, + ) -> Option> { + Some(Box::new(move |s: &mut Self| { + s.drb_result_table.insert(epoch, drb_result); + })) + } } diff --git a/crates/task-impls/src/quorum_proposal/handlers.rs b/crates/task-impls/src/quorum_proposal/handlers.rs index 4f7ff5719a..d6ebb62232 100644 --- a/crates/task-impls/src/quorum_proposal/handlers.rs +++ b/crates/task-impls/src/quorum_proposal/handlers.rs @@ -202,7 +202,7 @@ impl ProposalDependencyHandle { ) -> Option> { tracing::debug!("getting the next epoch QC"); // If we haven't upgraded to Epochs just return None right away - if self.upgrade_lock.version_infallible(self.view_number).await < V::Epochs::VERSION { + if !self.upgrade_lock.epochs_enabled(self.view_number).await { return None; } if let Some(next_epoch_qc) = self.consensus.read().await.next_epoch_high_qc() { diff --git a/crates/task-impls/src/quorum_vote/handlers.rs b/crates/task-impls/src/quorum_vote/handlers.rs index 1f8179a29d..1eee76f82c 100644 --- a/crates/task-impls/src/quorum_vote/handlers.rs +++ b/crates/task-impls/src/quorum_vote/handlers.rs @@ -46,6 +46,22 @@ use crate::{ quorum_vote::Versions, }; +async fn notify_membership_of_drb_result( + membership: &Arc>, + epoch: ::Epoch, + drb_result: DrbResult, +) { + let write_callback = { + let membership_reader = membership.read().await; + membership_reader.add_drb_result(epoch, drb_result).await + }; + + if let Some(write_callback) = write_callback { + let mut membership_writer = membership.write().await; + write_callback(&mut *membership_writer); + } +} + /// Store the DRB result from the computation task to the shared `results` table. /// /// Returns the result if it exists. @@ -89,7 +105,12 @@ async fn store_and_get_computed_drb_result< .drb_seeds_and_results .results .insert(epoch_number, result); + drop(consensus_writer); + + notify_membership_of_drb_result::(&task_state.membership, epoch_number, result) + .await; task_state.drb_computation = None; + Ok(result) } Err(e) => Err(warn!("Error in DRB calculation: {:?}.", e)), @@ -196,6 +217,12 @@ async fn start_drb_task, V: Versio .drb_seeds_and_results .results .insert(*task_epoch, result); + notify_membership_of_drb_result::( + &task_state.membership, + *task_epoch, + result, + ) + .await; task_state.drb_computation = None; } Err(e) => { @@ -283,9 +310,13 @@ async fn store_drb_seed_and_result else { bail!("Failed to serialize the QC signature."); }; - let Ok(drb_seed_input) = drb_seed_input_vec.try_into() else { - bail!("Failed to convert the serialized QC signature into a DRB seed input."); - }; + + // TODO: Replace the leader election with a weighted version. + // + let mut drb_seed_input = [0u8; 32]; + let len = drb_seed_input_vec.len().min(32); + drb_seed_input[..len].copy_from_slice(&drb_seed_input_vec[..len]); + task_state .consensus .write() @@ -305,6 +336,12 @@ async fn store_drb_seed_and_result .drb_seeds_and_results .results .insert(current_epoch_number + 1, result); + notify_membership_of_drb_result::( + &task_state.membership, + current_epoch_number + 1, + result, + ) + .await; } else { bail!("The last block of the epoch is decided but doesn't contain a DRB result."); } diff --git a/crates/testing/src/helpers.rs b/crates/testing/src/helpers.rs index 1bbb099c93..21a9451d3e 100644 --- a/crates/testing/src/helpers.rs +++ b/crates/testing/src/helpers.rs @@ -5,7 +5,7 @@ // along with the HotShot repository. If not, see . #![allow(clippy::panic)] -use std::{fmt::Debug, hash::Hash, marker::PhantomData, sync::Arc}; +use std::{collections::BTreeMap, fmt::Debug, hash::Hash, marker::PhantomData, sync::Arc}; use async_broadcast::{Receiver, Sender}; use async_lock::RwLock; @@ -47,6 +47,11 @@ use vbs::version::Version; use crate::{test_builder::TestDescription, test_launcher::TestLauncher}; +pub type TestNodeKeyMap = BTreeMap< + ::SignatureKey, + <::SignatureKey as SignatureKey>::PrivateKey, +>; + /// create the [`SystemContextHandle`] from a node id, with no epochs /// # Panics /// if cannot create a [`HotShotInitializer`] @@ -64,6 +69,7 @@ pub async fn build_system_handle< SystemContextHandle, Sender>>, Receiver>>, + Arc, ) { let builder: TestDescription = TestDescription::default_multiple_rounds(); @@ -91,6 +97,7 @@ pub async fn build_system_handle_from_launcher< SystemContextHandle, Sender>>, Receiver>>, + Arc, ) { let network = (launcher.resource_generators.channel_generator)(node_id).await; let storage = (launcher.resource_generators.storage)(node_id); @@ -118,7 +125,9 @@ pub async fn build_system_handle_from_launcher< hotshot_config.known_da_nodes.clone(), ))); - SystemContext::init( + let node_key_map = launcher.metadata.build_node_key_map(); + + let (c, s, r) = SystemContext::init( public_key, private_key, node_id, @@ -131,7 +140,9 @@ pub async fn build_system_handle_from_launcher< marketplace_config, ) .await - .expect("Could not init hotshot") + .expect("Could not init hotshot"); + + (c, s, r, node_key_map) } /// create certificate diff --git a/crates/testing/src/test_builder.rs b/crates/testing/src/test_builder.rs index b2182e4d34..bf0f49afa3 100644 --- a/crates/testing/src/test_builder.rs +++ b/crates/testing/src/test_builder.rs @@ -15,8 +15,8 @@ use hotshot::{ HotShotInitializer, MarketplaceConfig, SystemContext, TwinsHandlerState, }; use hotshot_example_types::{ - auction_results_provider_types::TestAuctionResultsProvider, state_types::TestInstanceState, - storage_types::TestStorage, testable_delay::DelayConfig, + auction_results_provider_types::TestAuctionResultsProvider, node_types::TestTypes, + state_types::TestInstanceState, storage_types::TestStorage, testable_delay::DelayConfig, }; use hotshot_types::{ consensus::ConsensusMetricsValue, @@ -32,6 +32,7 @@ use super::{ txn_task::TxnTaskDescription, }; use crate::{ + helpers::{key_pair_for_id, TestNodeKeyMap}, spinning_task::SpinningTaskDescription, test_launcher::{Network, ResourceGenerators, TestLauncher}, test_task::TestTaskStateSeed, @@ -451,6 +452,16 @@ impl, V: Versions> TestDescription ..self } } + + pub fn build_node_key_map(&self) -> Arc { + let mut node_key_map = TestNodeKeyMap::new(); + for i in 0..self.test_config.num_nodes_with_stake.into() { + let (private_key, public_key) = key_pair_for_id::(i as u64); + node_key_map.insert(public_key, private_key); + } + + Arc::new(node_key_map) + } } impl, V: Versions> Default diff --git a/crates/testing/src/view_generator.rs b/crates/testing/src/view_generator.rs index abe4277590..489a279488 100644 --- a/crates/testing/src/view_generator.rs +++ b/crates/testing/src/view_generator.rs @@ -6,6 +6,7 @@ use std::{ cmp::max, + collections::BTreeMap, marker::PhantomData, pin::Pin, sync::Arc, @@ -37,6 +38,7 @@ use hotshot_types::{ }, traits::{ consensus_api::ConsensusApi, + election::Membership, node_implementation::{ConsensusTime, NodeType, Versions}, BlockPayload, }, @@ -46,7 +48,7 @@ use rand::{thread_rng, Rng}; use sha2::{Digest, Sha256}; use crate::helpers::{ - build_cert, build_da_certificate, build_vid_proposal, da_payload_commitment, key_pair_for_id, + build_cert, build_da_certificate, build_vid_proposal, da_payload_commitment, TestNodeKeyMap, }; #[derive(Clone)] @@ -57,6 +59,7 @@ pub struct TestView { pub view_number: ViewNumber, pub epoch_number: Option, pub membership: Arc::Membership>>, + pub node_key_map: Arc, pub vid_disperse: Proposal>, pub vid_proposal: ( Vec>>, @@ -73,8 +76,31 @@ pub struct TestView { } impl TestView { + async fn find_leader_key_pair( + membership: &Arc::Membership>>, + node_key_map: &Arc, + view_number: ::View, + epoch: Option<::Epoch>, + ) -> ( + <::SignatureKey as SignatureKey>::PrivateKey, + ::SignatureKey, + ) { + let membership_reader = membership.read().await; + let leader = membership_reader + .leader(view_number, epoch) + .expect("expected Membership::leader to succeed"); + drop(membership_reader); + + let sk = node_key_map + .get(&leader) + .expect("expected Membership::leader public key to be in node_key_map"); + + (sk.clone(), leader) + } + pub async fn genesis( membership: &Arc::Membership>>, + node_key_map: Arc, ) -> Self { let genesis_view = ViewNumber::new(1); let genesis_epoch = genesis_epoch_from_version::(); @@ -96,7 +122,10 @@ impl TestView { &metadata, ); - let (private_key, public_key) = key_pair_for_id::(*genesis_view); + //let (private_key, public_key) = key_pair_for_id::(*genesis_view); + let (private_key, public_key) = + Self::find_leader_key_pair(membership, &node_key_map, genesis_view, genesis_epoch) + .await; let leader_public_key = public_key; @@ -198,6 +227,7 @@ impl TestView { view_number: genesis_view, epoch_number: genesis_epoch, membership: membership.clone(), + node_key_map, vid_disperse, vid_proposal: (vid_proposal, public_key), da_certificate, @@ -235,9 +265,19 @@ impl TestView { epoch: old_epoch, }; - let (old_private_key, old_public_key) = key_pair_for_id::(*old_view); + //let (old_private_key, old_public_key) = key_pair_for_id::(*old_view); + let (old_private_key, old_public_key) = + Self::find_leader_key_pair(&self.membership, &self.node_key_map, old_view, old_epoch) + .await; - let (private_key, public_key) = key_pair_for_id::(*next_view); + //let (private_key, public_key) = key_pair_for_id::(*next_view); + let (private_key, public_key) = Self::find_leader_key_pair( + &self.membership, + &self.node_key_map, + next_view, + self.epoch_number, + ) + .await; let leader_public_key = public_key; @@ -441,6 +481,7 @@ impl TestView { view_number: next_view, epoch_number: self.epoch_number, membership: self.membership.clone(), + node_key_map: self.node_key_map.clone(), vid_disperse, vid_proposal: (vid_proposal, public_key), da_certificate, @@ -517,14 +558,19 @@ impl TestView { pub struct TestViewGenerator { pub current_view: Option, pub membership: Arc::Membership>>, + pub node_key_map: Arc, pub _pd: PhantomData, } impl TestViewGenerator { - pub fn generate(membership: Arc::Membership>>) -> Self { + pub fn generate( + membership: Arc::Membership>>, + node_key_map: Arc, + ) -> Self { TestViewGenerator { current_view: None, membership, + node_key_map, _pd: PhantomData, } } @@ -603,12 +649,13 @@ impl Stream for TestViewGenerator { fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let mem = Arc::clone(&self.membership); + let nkm = Arc::clone(&self.node_key_map); let curr_view = &self.current_view.clone(); let mut fut = if let Some(ref view) = curr_view { async move { TestView::next_view(view).await }.boxed() } else { - async move { TestView::genesis::(&mem).await }.boxed() + async move { TestView::genesis::(&mem, nkm).await }.boxed() }; match fut.as_mut().poll(cx) { diff --git a/crates/testing/tests/tests_1/da_task.rs b/crates/testing/tests/tests_1/da_task.rs index 5006cab51d..d08901e8df 100644 --- a/crates/testing/tests/tests_1/da_task.rs +++ b/crates/testing/tests/tests_1/da_task.rs @@ -35,9 +35,9 @@ use vbs::version::{StaticVersionType, Version}; async fn test_da_task() { hotshot::helpers::initialize_logging(); - let handle = build_system_handle::(2) + let (handle, _,_,node_key_map ) = build_system_handle::(2) .await - .0; + ; let membership = Arc::clone(&handle.hotshot.memberships); let default_version = Version { major: 0, minor: 0 }; @@ -52,7 +52,7 @@ async fn test_da_task() { default_version, ); - let mut generator = TestViewGenerator::::generate(membership.clone()); + let mut generator = TestViewGenerator::::generate(membership.clone(), node_key_map.clone()); let mut proposals = Vec::new(); let mut leaders = Vec::new(); @@ -142,9 +142,9 @@ async fn test_da_task() { async fn test_da_task_storage_failure() { hotshot::helpers::initialize_logging(); - let handle = build_system_handle::(2) + let (handle,_,_,node_key_map) = build_system_handle::(2) .await - .0; + ; // Set the error flag here for the system handle. This causes it to emit an error on append. handle.storage().write().await.should_return_err = true; @@ -161,7 +161,7 @@ async fn test_da_task_storage_failure() { default_version, ); - let mut generator = TestViewGenerator::::generate(Arc::clone(&membership)); + let mut generator = TestViewGenerator::::generate(Arc::clone(&membership), Arc::clone(&node_key_map)); let mut proposals = Vec::new(); let mut leaders = Vec::new(); diff --git a/crates/testing/tests/tests_1/message.rs b/crates/testing/tests/tests_1/message.rs index c2970befd5..5bb11574ba 100644 --- a/crates/testing/tests/tests_1/message.rs +++ b/crates/testing/tests/tests_1/message.rs @@ -76,12 +76,12 @@ async fn test_certificate2_validity() { hotshot::helpers::initialize_logging(); let node_id = 1; - let handle = build_system_handle::(node_id) + let (handle,_,_,node_key_map) = build_system_handle::(node_id) .await - .0; + ; let membership = Arc::clone(&handle.hotshot.memberships); - let mut generator = TestViewGenerator::::generate(Arc::clone(&membership)); + let mut generator = TestViewGenerator::::generate(Arc::clone(&membership), Arc::clone(&node_key_map)); 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 f634c60113..c7e8237464 100644 --- a/crates/testing/tests/tests_1/network_task.rs +++ b/crates/testing/tests/tests_1/network_task.rs @@ -43,9 +43,9 @@ async fn test_network_task() { TestDescription::default_multiple_rounds(); let upgrade_lock = UpgradeLock::::new(); let node_id = 1; - let handle = build_system_handle::(node_id) + let (handle,_,_,node_key_map) = build_system_handle::(node_id) .await - .0; + ; let launcher = builder.gen_launcher(); let network = (launcher.resource_generators.channel_generator)(node_id).await; @@ -80,7 +80,7 @@ async fn test_network_task() { let task = Task::new(network_state, tx.clone(), rx); task_reg.run_task(task); - let mut generator = TestViewGenerator::::generate(membership); + let mut generator = TestViewGenerator::::generate(membership, node_key_map); let view = generator.next().await.unwrap(); let (out_tx_internal, mut out_rx_internal) = async_broadcast::broadcast(10); @@ -215,9 +215,9 @@ async fn test_network_storage_fail() { let builder: TestDescription = TestDescription::default_multiple_rounds(); let node_id = 1; - let handle = build_system_handle::(node_id) + let (handle,_,_,node_key_map) = build_system_handle::(node_id) .await - .0; + ; let launcher = builder.gen_launcher(); let network = (launcher.resource_generators.channel_generator)(node_id).await; @@ -253,7 +253,7 @@ async fn test_network_storage_fail() { let task = Task::new(network_state, tx.clone(), rx); task_reg.run_task(task); - let mut generator = TestViewGenerator::::generate(membership); + let mut generator = TestViewGenerator::::generate(membership,node_key_map); let view = generator.next().await.unwrap(); let (out_tx_internal, mut out_rx_internal): (Sender>>, _) = diff --git a/crates/testing/tests/tests_1/quorum_proposal_recv_task.rs b/crates/testing/tests/tests_1/quorum_proposal_recv_task.rs index 29d2389f2d..6c06970dfe 100644 --- a/crates/testing/tests/tests_1/quorum_proposal_recv_task.rs +++ b/crates/testing/tests/tests_1/quorum_proposal_recv_task.rs @@ -51,14 +51,14 @@ async fn test_quorum_proposal_recv_task() { hotshot::helpers::initialize_logging(); - let handle = build_system_handle::(2) + let (handle,_,_,node_key_map) = build_system_handle::(2) .await - .0; + ; let membership = Arc::clone(&handle.hotshot.memberships); let consensus = handle.hotshot.consensus(); let mut consensus_writer = consensus.write().await; - let mut generator = TestViewGenerator::::generate(membership); + let mut generator = TestViewGenerator::::generate(membership, node_key_map); let mut proposals = Vec::new(); let mut leaders = Vec::new(); let mut votes = Vec::new(); @@ -126,14 +126,14 @@ async fn test_quorum_proposal_recv_task_liveness_check() { hotshot::helpers::initialize_logging(); - let handle = build_system_handle::(4) + let (handle,_,_,node_key_map) = build_system_handle::(4) .await - .0; + ; let membership = Arc::clone(&handle.hotshot.memberships); let consensus = handle.hotshot.consensus(); let mut consensus_writer = consensus.write().await; - let mut generator = TestViewGenerator::::generate(membership); + let mut generator = TestViewGenerator::::generate(membership,node_key_map); let mut proposals = Vec::new(); let mut leaders = Vec::new(); let mut votes = 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 9545f79cfc..91a95b149d 100644 --- a/crates/testing/tests/tests_1/quorum_proposal_task.rs +++ b/crates/testing/tests/tests_1/quorum_proposal_task.rs @@ -47,9 +47,9 @@ async fn test_quorum_proposal_task_quorum_proposal_view_1() { hotshot::helpers::initialize_logging(); let node_id = 1; - let handle = build_system_handle::(node_id) + let (handle,_,_,node_key_map) = build_system_handle::(node_id) .await - .0; + ; let membership = Arc::clone(&handle.hotshot.memberships); let version = handle @@ -66,7 +66,7 @@ async fn test_quorum_proposal_task_quorum_proposal_view_1() { ) .await; - let mut generator = TestViewGenerator::::generate(Arc::clone(&membership)); + let mut generator = TestViewGenerator::::generate(Arc::clone(&membership), Arc::clone(&node_key_map)); let mut proposals = Vec::new(); let mut leaders = Vec::new(); @@ -151,13 +151,13 @@ async fn test_quorum_proposal_task_quorum_proposal_view_gt_1() { hotshot::helpers::initialize_logging(); let node_id = 3; - let handle = build_system_handle::(node_id) + let (handle,_,_,node_key_map) = build_system_handle::(node_id) .await - .0; + ; let membership = Arc::clone(&handle.hotshot.memberships); - let mut generator = TestViewGenerator::::generate(membership.clone()); + let mut generator = TestViewGenerator::::generate(membership.clone(),node_key_map.clone()); let mut proposals = Vec::new(); let mut leaders = Vec::new(); @@ -335,9 +335,9 @@ async fn test_quorum_proposal_task_qc_timeout() { hotshot::helpers::initialize_logging(); let node_id = 3; - let handle = build_system_handle::(node_id) + let (handle,_,_,node_key_map) = build_system_handle::(node_id) .await - .0; + ; let membership = Arc::clone(&handle.hotshot.memberships); let version = handle .hotshot @@ -354,7 +354,7 @@ async fn test_quorum_proposal_task_qc_timeout() { .await; let builder_commitment = BuilderCommitment::from_raw_digest(sha2::Sha256::new().finalize()); - let mut generator = TestViewGenerator::::generate(Arc::clone(&membership)); + let mut generator = TestViewGenerator::::generate(Arc::clone(&membership),Arc::clone(&node_key_map)); let mut proposals = Vec::new(); let mut leaders = Vec::new(); @@ -433,9 +433,9 @@ async fn test_quorum_proposal_task_view_sync() { hotshot::helpers::initialize_logging(); let node_id = 2; - let handle = build_system_handle::(node_id) + let (handle,_,_,node_key_map) = build_system_handle::(node_id) .await - .0; + ; let membership = Arc::clone(&handle.hotshot.memberships); let version = handle @@ -453,7 +453,7 @@ async fn test_quorum_proposal_task_view_sync() { .await; let builder_commitment = BuilderCommitment::from_raw_digest(sha2::Sha256::new().finalize()); - let mut generator = TestViewGenerator::::generate(Arc::clone(&membership)); + let mut generator = TestViewGenerator::::generate(Arc::clone(&membership), Arc::clone(&node_key_map)); let mut proposals = Vec::new(); let mut leaders = Vec::new(); @@ -532,13 +532,13 @@ async fn test_quorum_proposal_task_liveness_check() { hotshot::helpers::initialize_logging(); let node_id = 3; - let handle = build_system_handle::(node_id) + let (handle,_,_,node_key_map) = build_system_handle::(node_id) .await - .0; + ; let membership = Arc::clone(&handle.hotshot.memberships); - let mut generator = TestViewGenerator::::generate(Arc::clone(&membership)); + let mut generator = TestViewGenerator::::generate(Arc::clone(&membership), Arc::clone(&node_key_map)); let mut proposals = Vec::new(); let mut leaders = Vec::new(); @@ -711,12 +711,12 @@ async fn test_quorum_proposal_task_liveness_check() { async fn test_quorum_proposal_task_with_incomplete_events() { hotshot::helpers::initialize_logging(); - let handle = build_system_handle::(2) + let (handle,_,_,node_key_map) = build_system_handle::(2) .await - .0; + ; let membership = Arc::clone(&handle.hotshot.memberships); - let mut generator = TestViewGenerator::::generate(membership); + let mut generator = TestViewGenerator::::generate(membership,node_key_map); 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 4ea37ebe00..5bc28deb79 100644 --- a/crates/testing/tests/tests_1/quorum_vote_task.rs +++ b/crates/testing/tests/tests_1/quorum_vote_task.rs @@ -41,13 +41,13 @@ async fn test_quorum_vote_task_success() { hotshot::helpers::initialize_logging(); - let handle = build_system_handle::(2) + let (handle,_,_,node_key_map) = build_system_handle::(2) .await - .0; + ; let membership = Arc::clone(&handle.hotshot.memberships); - let mut generator = TestViewGenerator::::generate(membership); + let mut generator = TestViewGenerator::::generate(membership,node_key_map); let mut proposals = Vec::new(); let mut leaves = Vec::new(); @@ -108,13 +108,13 @@ async fn test_quorum_vote_task_miss_dependency() { hotshot::helpers::initialize_logging(); - let handle = build_system_handle::(2) + let (handle,_,_,node_key_map) = build_system_handle::(2) .await - .0; + ; let membership = Arc::clone(&handle.hotshot.memberships); - let mut generator = TestViewGenerator::::generate(membership); + let mut generator = TestViewGenerator::::generate(membership,node_key_map); let mut proposals = Vec::new(); let mut leaders = Vec::new(); @@ -192,13 +192,13 @@ async fn test_quorum_vote_task_incorrect_dependency() { hotshot::helpers::initialize_logging(); - let handle = build_system_handle::(2) + let (handle,_,_,node_key_map) = build_system_handle::(2) .await - .0; + ; let membership = Arc::clone(&handle.hotshot.memberships); - let mut generator = TestViewGenerator::::generate(membership); + let mut generator = TestViewGenerator::::generate(membership,node_key_map); let mut proposals = Vec::new(); let mut leaves = Vec::new(); diff --git a/crates/testing/tests/tests_1/upgrade_task_with_proposal.rs b/crates/testing/tests/tests_1/upgrade_task_with_proposal.rs index 820fb3a562..b9b56ccca6 100644 --- a/crates/testing/tests/tests_1/upgrade_task_with_proposal.rs +++ b/crates/testing/tests/tests_1/upgrade_task_with_proposal.rs @@ -55,9 +55,9 @@ async fn test_upgrade_task_with_proposal() { hotshot::helpers::initialize_logging(); - let handle = build_system_handle::(3) + let (handle,_,_,node_key_map) = build_system_handle::(3) .await - .0; + ; let other_handles = futures::future::join_all((0..=9).map(build_system_handle)).await; @@ -85,7 +85,7 @@ async fn test_upgrade_task_with_proposal() { let membership = Arc::clone(&handle.hotshot.memberships); - let mut generator = TestViewGenerator::::generate(Arc::clone(&membership)); + let mut generator = TestViewGenerator::::generate(Arc::clone(&membership),Arc::clone(&node_key_map)); for view in (&mut generator).take(1).collect::>().await { proposals.push(view.quorum_proposal.clone()); diff --git a/crates/testing/tests/tests_1/upgrade_task_with_vote.rs b/crates/testing/tests/tests_1/upgrade_task_with_vote.rs index 841fd86a86..699cffd0a0 100644 --- a/crates/testing/tests/tests_1/upgrade_task_with_vote.rs +++ b/crates/testing/tests/tests_1/upgrade_task_with_vote.rs @@ -45,9 +45,9 @@ async fn test_upgrade_task_with_vote() { hotshot::helpers::initialize_logging(); - let handle = build_system_handle::(2) + let (handle,_,_,node_key_map) = build_system_handle::(2) .await - .0; + ; let old_version = Version { major: 0, minor: 1 }; let new_version = Version { major: 0, minor: 2 }; @@ -71,7 +71,7 @@ async fn test_upgrade_task_with_vote() { let mut consensus_writer = consensus.write().await; let membership = Arc::clone(&handle.hotshot.memberships); - let mut generator = TestViewGenerator::::generate(membership); + let mut generator = TestViewGenerator::::generate(membership,node_key_map); for view in (&mut generator).take(2).collect::>().await { proposals.push(view.quorum_proposal.clone()); diff --git a/crates/testing/tests/tests_1/vote_dependency_handle.rs b/crates/testing/tests/tests_1/vote_dependency_handle.rs index a6e36c800f..802ab78fa3 100644 --- a/crates/testing/tests/tests_1/vote_dependency_handle.rs +++ b/crates/testing/tests/tests_1/vote_dependency_handle.rs @@ -33,12 +33,12 @@ async fn test_vote_dependency_handle() { // We use a node ID of 2 here arbitrarily. We just need it to build the system handle. let node_id = 2; // Construct the system handle for the node ID to build all of the state objects. - let handle = build_system_handle::(node_id) + let (handle,_,_,node_key_map) = build_system_handle::(node_id) .await - .0; + ; let membership = Arc::clone(&handle.hotshot.memberships); - let mut generator = TestViewGenerator::::generate(membership); + let mut generator = TestViewGenerator::::generate(membership,node_key_map); // Generate our state for the test let mut proposals = Vec::new(); diff --git a/crates/types/src/drb.rs b/crates/types/src/drb.rs index e52fb89605..4cb9b2576a 100644 --- a/crates/types/src/drb.rs +++ b/crates/types/src/drb.rs @@ -81,18 +81,23 @@ pub fn compute_drb_result(drb_seed_input: DrbSeedInput) -> DrbR /// The DRB result is the output of a spawned `compute_drb_result` call. #[must_use] pub fn leader( - view_number: usize, + view_number: TYPES::View, stake_table: &[::StakeTableEntry], drb_result: DrbResult, ) -> TYPES::SignatureKey { let mut hasher = DefaultHasher::new(); + drb_result.hash(&mut hasher); view_number.hash(&mut hasher); + #[allow(clippy::cast_possible_truncation)] + let hash = hasher.finish() as usize; + // TODO: Use the total stake rather than `len()` and update the indexing after switching to // a weighted stake table. // - let index = (hasher.finish() as usize) % stake_table.len(); + let index = hash % stake_table.len(); + tracing::error!("drb::leader Picked index {index} for view_number {view_number:?}"); let entry = stake_table[index].clone(); TYPES::SignatureKey::public_key(&entry) } diff --git a/crates/types/src/traits/election.rs b/crates/types/src/traits/election.rs index 4e5347f49d..47adf2396b 100644 --- a/crates/types/src/traits/election.rs +++ b/crates/types/src/traits/election.rs @@ -11,7 +11,7 @@ use async_trait::async_trait; use utils::anytrace::Result; use super::node_implementation::NodeType; -use crate::{traits::signature_key::SignatureKey, PeerConfig}; +use crate::{drb::DrbResult, traits::signature_key::SignatureKey, PeerConfig}; #[async_trait] /// A protocol for determining membership in and participating in a committee. @@ -152,4 +152,15 @@ pub trait Membership: Debug + Send + Sync { async fn sync_l1(&self) -> Option> { None } + + #[allow(clippy::type_complexity)] + /// Called to notify the Membership when a new DRB result has been calculated. + /// Observes the same semantics as add_epoch_root + async fn add_drb_result( + &self, + _epoch: TYPES::Epoch, + _drb_result: DrbResult, + ) -> Option> { + None + } }