diff --git a/crates/example-types/src/node_types.rs b/crates/example-types/src/node_types.rs index de74d12b3a..a3a657acaf 100644 --- a/crates/example-types/src/node_types.rs +++ b/crates/example-types/src/node_types.rs @@ -15,7 +15,7 @@ use hotshot::traits::{ use hotshot_types::{ data::ViewNumber, signature_key::{BLSPubKey, BuilderKey}, - traits::node_implementation::NodeType, + traits::node_implementation::{NodeType, Versions}, }; use serde::{Deserialize, Serialize}; use vbs::version::StaticVersion; @@ -45,12 +45,6 @@ use crate::{ pub struct TestTypes; impl NodeType for TestTypes { type AuctionResult = TestAuctionResult; - type Base = StaticVersion<0, 1>; - type Upgrade = StaticVersion<0, 2>; - const UPGRADE_HASH: [u8; 32] = [ - 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - 0, 0, - ]; type Time = ViewNumber; type BlockHeader = TestBlockHeader; type BlockPayload = TestBlockPayload; @@ -80,12 +74,6 @@ impl NodeType for TestTypes { pub struct TestConsecutiveLeaderTypes; impl NodeType for TestConsecutiveLeaderTypes { type AuctionResult = TestAuctionResult; - type Base = StaticVersion<0, 1>; - type Upgrade = StaticVersion<0, 2>; - const UPGRADE_HASH: [u8; 32] = [ - 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - 0, 0, - ]; type Time = ViewNumber; type BlockHeader = TestBlockHeader; type BlockPayload = TestBlockPayload; @@ -144,3 +132,17 @@ impl NodeImplementation for Libp2pImpl { type Storage = TestStorage; type AuctionResultsProvider = TestAuctionResultsProvider; } + +#[derive(Clone, Debug, Copy)] +pub struct TestVersions {} + +impl Versions for TestVersions { + type Base = StaticVersion<0, 1>; + type Upgrade = StaticVersion<0, 2>; + const UPGRADE_HASH: [u8; 32] = [ + 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, + ]; + + type Marketplace = StaticVersion<0, 3>; +} diff --git a/crates/example-types/src/state_types.rs b/crates/example-types/src/state_types.rs index d005084d0f..50c40fee73 100644 --- a/crates/example-types/src/state_types.rs +++ b/crates/example-types/src/state_types.rs @@ -5,6 +5,8 @@ // along with the HotShot repository. If not, see . //! Implementations for examples and tests only +use std::fmt::Debug; + use async_trait::async_trait; use committable::{Commitment, Committable}; use hotshot_types::{ @@ -19,7 +21,6 @@ use hotshot_types::{ }; use rand::Rng; use serde::{Deserialize, Serialize}; -use std::fmt::Debug; use vbs::version::Version; pub use crate::node_types::TestTypes; diff --git a/crates/examples/combined/all.rs b/crates/examples/combined/all.rs index bd69dc61c1..70363db3ec 100644 --- a/crates/examples/combined/all.rs +++ b/crates/examples/combined/all.rs @@ -20,7 +20,7 @@ use hotshot::{ traits::implementations::{KeyPair, TestingDef, WrappedSignatureKey}, types::SignatureKey, }; -use hotshot_example_types::state_types::TestTypes; +use hotshot_example_types::{node_types::TestVersions, state_types::TestTypes}; use hotshot_orchestrator::client::ValidatorArgs; use hotshot_types::traits::node_implementation::NodeType; use infra::{gen_local_address, BUILDER_BASE_PORT, VALIDATOR_BASE_PORT}; @@ -146,12 +146,14 @@ async fn main() { let builder_address = gen_local_address::(i); let node = async_spawn(async move { - infra::main_entry_point::(ValidatorArgs { - url: orchestrator_url, - advertise_address: Some(advertise_address), - builder_address: Some(builder_address), - network_config_file: None, - }) + infra::main_entry_point::( + ValidatorArgs { + url: orchestrator_url, + advertise_address: Some(advertise_address), + builder_address: Some(builder_address), + network_config_file: None, + }, + ) .await; }); nodes.push(node); diff --git a/crates/examples/combined/multi-validator.rs b/crates/examples/combined/multi-validator.rs index 9b6e37f516..71ab7afd91 100644 --- a/crates/examples/combined/multi-validator.rs +++ b/crates/examples/combined/multi-validator.rs @@ -10,7 +10,7 @@ use async_compatibility_layer::{ logging::{setup_backtrace, setup_logging}, }; use clap::Parser; -use hotshot_example_types::state_types::TestTypes; +use hotshot_example_types::{node_types::TestVersions, state_types::TestTypes}; use hotshot_orchestrator::client::{MultiValidatorArgs, ValidatorArgs}; use tracing::instrument; @@ -36,7 +36,7 @@ async fn main() { let args = args.clone(); let node = async_spawn(async move { - infra::main_entry_point::( + infra::main_entry_point::( ValidatorArgs::from_multi_args(args, node_index), ) .await; diff --git a/crates/examples/combined/validator.rs b/crates/examples/combined/validator.rs index 9f97b7f8db..a73c80f70d 100644 --- a/crates/examples/combined/validator.rs +++ b/crates/examples/combined/validator.rs @@ -9,7 +9,7 @@ use std::{net::SocketAddr, str::FromStr}; use async_compatibility_layer::logging::{setup_backtrace, setup_logging}; use clap::Parser; -use hotshot_example_types::state_types::TestTypes; +use hotshot_example_types::{node_types::TestVersions, state_types::TestTypes}; use hotshot_orchestrator::client::ValidatorArgs; use local_ip_address::local_ip; use tracing::{debug, instrument}; @@ -42,5 +42,5 @@ async fn main() { ); debug!("connecting to orchestrator at {:?}", args.url); - infra::main_entry_point::(args).await; + infra::main_entry_point::(args).await; } diff --git a/crates/examples/infra/mod.rs b/crates/examples/infra/mod.rs index 812168bb2c..9ca8cc127a 100755 --- a/crates/examples/infra/mod.rs +++ b/crates/examples/infra/mod.rs @@ -59,7 +59,7 @@ use hotshot_types::{ block_contents::{BlockHeader, TestableBlock}, election::Membership, network::{ConnectedNetwork, Topic}, - node_implementation::{ConsensusTime, NodeType}, + node_implementation::{ConsensusTime, NodeType, Versions}, states::TestableState, }, HotShotConfig, PeerConfig, ValidatorConfig, @@ -347,6 +347,7 @@ pub trait RunDa< Storage = TestStorage, AuctionResultsProvider = TestAuctionResultsProvider, >, + V: Versions, > where ::ValidatedState: TestableState, ::BlockPayload: TestableBlock, @@ -364,7 +365,7 @@ pub trait RunDa< /// # Panics if it cannot generate a genesis block, fails to initialize HotShot, or cannot /// get the anchored view /// Note: sequencing leaf does not have state, so does not return state - async fn initialize_state_and_hotshot(&self) -> SystemContextHandle { + async fn initialize_state_and_hotshot(&self) -> SystemContextHandle { let initializer = hotshot::HotShotInitializer::::from_genesis(TestInstanceState::default()) .await @@ -430,7 +431,7 @@ pub trait RunDa< #[allow(clippy::too_many_lines)] async fn run_hotshot( &self, - context: SystemContextHandle, + context: SystemContextHandle, transactions: &mut Vec, transactions_to_send_per_round: u64, transaction_size_in_bytes: u64, @@ -619,7 +620,8 @@ impl< Storage = TestStorage, AuctionResultsProvider = TestAuctionResultsProvider, >, - > RunDa, NODE> for PushCdnDaRun + V: Versions, + > RunDa, NODE, V> for PushCdnDaRun where ::ValidatedState: TestableState, ::BlockPayload: TestableBlock, @@ -696,7 +698,8 @@ impl< Storage = TestStorage, AuctionResultsProvider = TestAuctionResultsProvider, >, - > RunDa, NODE> for Libp2pDaRun + V: Versions, + > RunDa, NODE, V> for Libp2pDaRun where ::ValidatedState: TestableState, ::BlockPayload: TestableBlock, @@ -782,7 +785,8 @@ impl< Storage = TestStorage, AuctionResultsProvider = TestAuctionResultsProvider, >, - > RunDa, NODE> for CombinedDaRun + V: Versions, + > RunDa, NODE, V> for CombinedDaRun where ::ValidatedState: TestableState, ::BlockPayload: TestableBlock, @@ -794,20 +798,21 @@ where libp2p_advertise_address: Option, ) -> CombinedDaRun { // Initialize our Libp2p network - let libp2p_network: Libp2pDaRun = as RunDa< - TYPES, - Libp2pNetwork, - Libp2pImpl, - >>::initialize_networking( - config.clone(), libp2p_advertise_address - ) - .await; + let libp2p_network: Libp2pDaRun = + as RunDa< + TYPES, + Libp2pNetwork, + Libp2pImpl, + V, + >>::initialize_networking(config.clone(), libp2p_advertise_address) + .await; // Initialize our CDN network let cdn_network: PushCdnDaRun = as RunDa< TYPES, PushCdnNetwork, PushCdnImpl, + V, >>::initialize_networking( config.clone(), libp2p_advertise_address ) @@ -852,7 +857,8 @@ pub async fn main_entry_point< Storage = TestStorage, AuctionResultsProvider = TestAuctionResultsProvider, >, - RUNDA: RunDa, + V: Versions, + RUNDA: RunDa, >( args: ValidatorArgs, ) where diff --git a/crates/examples/libp2p/all.rs b/crates/examples/libp2p/all.rs index 770e6ea91d..8f0e0a75a6 100644 --- a/crates/examples/libp2p/all.rs +++ b/crates/examples/libp2p/all.rs @@ -12,7 +12,7 @@ use async_compatibility_layer::{ art::async_spawn, logging::{setup_backtrace, setup_logging}, }; -use hotshot_example_types::state_types::TestTypes; +use hotshot_example_types::{node_types::TestVersions, state_types::TestTypes}; use hotshot_orchestrator::client::ValidatorArgs; use infra::{gen_local_address, BUILDER_BASE_PORT, VALIDATOR_BASE_PORT}; use tracing::instrument; @@ -51,12 +51,14 @@ async fn main() { let builder_address = gen_local_address::(i); let orchestrator_url = orchestrator_url.clone(); let node = async_spawn(async move { - infra::main_entry_point::(ValidatorArgs { - url: orchestrator_url, - advertise_address: Some(advertise_address), - builder_address: Some(builder_address), - network_config_file: None, - }) + infra::main_entry_point::( + ValidatorArgs { + url: orchestrator_url, + advertise_address: Some(advertise_address), + builder_address: Some(builder_address), + network_config_file: None, + }, + ) .await; }); nodes.push(node); diff --git a/crates/examples/libp2p/multi-validator.rs b/crates/examples/libp2p/multi-validator.rs index 7f55d9462a..42621d6946 100644 --- a/crates/examples/libp2p/multi-validator.rs +++ b/crates/examples/libp2p/multi-validator.rs @@ -10,7 +10,7 @@ use async_compatibility_layer::{ logging::{setup_backtrace, setup_logging}, }; use clap::Parser; -use hotshot_example_types::state_types::TestTypes; +use hotshot_example_types::{node_types::TestVersions, state_types::TestTypes}; use hotshot_orchestrator::client::{MultiValidatorArgs, ValidatorArgs}; use tracing::instrument; @@ -36,7 +36,7 @@ async fn main() { let args = args.clone(); let node = async_spawn(async move { - infra::main_entry_point::( + infra::main_entry_point::( ValidatorArgs::from_multi_args(args, node_index), ) .await; diff --git a/crates/examples/libp2p/validator.rs b/crates/examples/libp2p/validator.rs index 5948ebd107..41a02d6eb1 100644 --- a/crates/examples/libp2p/validator.rs +++ b/crates/examples/libp2p/validator.rs @@ -9,7 +9,7 @@ use std::{net::SocketAddr, str::FromStr}; use async_compatibility_layer::logging::{setup_backtrace, setup_logging}; use clap::Parser; -use hotshot_example_types::state_types::TestTypes; +use hotshot_example_types::{node_types::TestVersions, state_types::TestTypes}; use hotshot_orchestrator::client::ValidatorArgs; use local_ip_address::local_ip; use tracing::{debug, instrument}; @@ -41,5 +41,5 @@ async fn main() { ); debug!("connecting to orchestrator at {:?}", args.url); - infra::main_entry_point::(args).await; + infra::main_entry_point::(args).await; } diff --git a/crates/examples/push-cdn/all.rs b/crates/examples/push-cdn/all.rs index b360170c21..6d97d34d9f 100644 --- a/crates/examples/push-cdn/all.rs +++ b/crates/examples/push-cdn/all.rs @@ -17,7 +17,7 @@ use hotshot::{ traits::implementations::{TestingDef, WrappedSignatureKey}, types::SignatureKey, }; -use hotshot_example_types::state_types::TestTypes; +use hotshot_example_types::{node_types::TestVersions, state_types::TestTypes}; use hotshot_orchestrator::client::ValidatorArgs; use hotshot_types::traits::node_implementation::NodeType; use infra::{gen_local_address, BUILDER_BASE_PORT}; @@ -140,12 +140,14 @@ async fn main() { let orchestrator_url = orchestrator_url.clone(); let builder_address = gen_local_address::(i); let node = async_spawn(async move { - infra::main_entry_point::(ValidatorArgs { - url: orchestrator_url, - advertise_address: None, - builder_address: Some(builder_address), - network_config_file: None, - }) + infra::main_entry_point::( + ValidatorArgs { + url: orchestrator_url, + advertise_address: None, + builder_address: Some(builder_address), + network_config_file: None, + }, + ) .await; }); nodes.push(node); diff --git a/crates/examples/push-cdn/multi-validator.rs b/crates/examples/push-cdn/multi-validator.rs index 77520cdd25..b8070f8b1c 100644 --- a/crates/examples/push-cdn/multi-validator.rs +++ b/crates/examples/push-cdn/multi-validator.rs @@ -10,7 +10,7 @@ use async_compatibility_layer::{ logging::{setup_backtrace, setup_logging}, }; use clap::Parser; -use hotshot_example_types::state_types::TestTypes; +use hotshot_example_types::{node_types::TestVersions, state_types::TestTypes}; use hotshot_orchestrator::client::{MultiValidatorArgs, ValidatorArgs}; use tracing::instrument; @@ -36,7 +36,7 @@ async fn main() { let args = args.clone(); let node = async_spawn(async move { - infra::main_entry_point::( + infra::main_entry_point::( ValidatorArgs::from_multi_args(args, node_index), ) .await; diff --git a/crates/examples/push-cdn/validator.rs b/crates/examples/push-cdn/validator.rs index 5e6c0e67bc..70d53cdc33 100644 --- a/crates/examples/push-cdn/validator.rs +++ b/crates/examples/push-cdn/validator.rs @@ -7,7 +7,7 @@ //! A validator use async_compatibility_layer::logging::{setup_backtrace, setup_logging}; use clap::Parser; -use hotshot_example_types::state_types::TestTypes; +use hotshot_example_types::{node_types::TestVersions, state_types::TestTypes}; use hotshot_orchestrator::client::ValidatorArgs; use tracing::{debug, instrument}; @@ -28,5 +28,5 @@ async fn main() { setup_backtrace(); let args = ValidatorArgs::parse(); debug!("connecting to orchestrator at {:?}", args.url); - infra::main_entry_point::(args).await; + infra::main_entry_point::(args).await; } diff --git a/crates/hotshot/src/lib.rs b/crates/hotshot/src/lib.rs index 7998efc9b1..090a9687de 100644 --- a/crates/hotshot/src/lib.rs +++ b/crates/hotshot/src/lib.rs @@ -12,10 +12,12 @@ pub mod documentation; use futures::future::{select, Either}; -use hotshot_types::traits::network::BroadcastDelay; +use hotshot_types::{ + message::UpgradeLock, + traits::{network::BroadcastDelay, node_implementation::Versions}, +}; use rand::Rng; use url::Url; -use vbs::version::StaticVersionType; /// Contains traits consumed by [`SystemContext`] pub mod traits; @@ -47,8 +49,8 @@ use hotshot_types::{ constants::{EVENT_CHANNEL_SIZE, EXTERNAL_EVENT_CHANNEL_SIZE}, data::{Leaf, QuorumProposal}, event::{EventType, LeafInfo}, - message::{DataMessage, Message, MessageKind, Proposal, VersionedMessage}, - simple_certificate::{QuorumCertificate, UpgradeCertificate}, + message::{DataMessage, Message, MessageKind, Proposal}, + simple_certificate::QuorumCertificate, traits::{ consensus_api::ConsensusApi, election::Membership, @@ -65,7 +67,6 @@ use hotshot_types::{ /// Reexport rand crate pub use rand; use tracing::{debug, instrument, trace}; -use vbs::version::Version; use crate::{ tasks::{add_consensus_tasks, add_network_tasks}, @@ -101,7 +102,7 @@ pub struct Memberships { } /// Holds the state needed to participate in `HotShot` consensus -pub struct SystemContext> { +pub struct SystemContext, V: Versions> { /// The public key of this node public_key: TYPES::SignatureKey, @@ -126,9 +127,6 @@ pub struct SystemContext> { /// Immutable instance state instance_state: Arc, - /// The network version - version: Arc>, - /// The view to enter when first starting consensus start_view: TYPES::Time, @@ -154,13 +152,15 @@ pub struct SystemContext> { /// Reference to the internal storage for consensus datum. pub storage: Arc>, - /// a potential upgrade certificate that has been decided on by the consensus tasks. - pub decided_upgrade_certificate: Arc>>>, + /// shared lock for upgrade information + pub upgrade_lock: UpgradeLock, /// Marketplace config for this instance of HotShot pub marketplace_config: MarketplaceConfig, } -impl> Clone for SystemContext { +impl, V: Versions> Clone + for SystemContext +{ #![allow(deprecated)] fn clone(&self) -> Self { Self { @@ -172,7 +172,6 @@ impl> Clone for SystemContext> Clone for SystemContext> SystemContext { +impl, V: Versions> SystemContext { #![allow(deprecated)] /// Creates a new [`Arc`] with the given configuration options. /// @@ -260,7 +259,7 @@ impl> SystemContext { let (internal_tx, internal_rx) = internal_channel; let (mut external_tx, mut external_rx) = external_channel; - let decided_upgrade_certificate = Arc::new(RwLock::new(None)); + let upgrade_lock = UpgradeLock::::new(); // Allow overflow on the channel, otherwise sending to it may block. external_rx.set_overflow(true); @@ -318,20 +317,18 @@ impl> SystemContext { ); let consensus = Arc::new(RwLock::new(consensus)); - let version = Arc::new(RwLock::new(TYPES::Base::VERSION)); // This makes it so we won't block on broadcasting if there is not a receiver // Our own copy of the receiver is inactive so it doesn't count. external_tx.set_await_active(false); - let inner: Arc> = Arc::new(SystemContext { + let inner: Arc> = Arc::new(SystemContext { id: nonce, consensus: OuterConsensus::new(consensus), instance_state: Arc::new(instance_state), public_key, private_key, config, - version, start_view: initializer.start_view, network, memberships: Arc::new(memberships), @@ -341,7 +338,7 @@ impl> SystemContext { external_event_stream: (external_tx, external_rx.deactivate()), anchored_leaf: anchored_leaf.clone(), storage: Arc::new(RwLock::new(storage)), - decided_upgrade_certificate, + upgrade_lock, marketplace_config, }); @@ -457,7 +454,6 @@ impl> SystemContext { pub async fn publish_transaction_async( &self, transaction: TYPES::Transaction, - decided_upgrade_certificate: Arc>>>, ) -> Result<(), HotShotError> { trace!("Adding transaction to our own queue"); @@ -472,10 +468,10 @@ impl> SystemContext { kind: MessageKind::from(message_kind), }; - let cert = decided_upgrade_certificate.read().await.clone(); - - let serialized_message = message - .serialize(&cert) + let serialized_message = self + .upgrade_lock + .serialize(&message) + .await .map_err(|_| HotShotError::FailedToSerialize)?; async_spawn(async move { @@ -584,7 +580,7 @@ impl> SystemContext { marketplace_config: MarketplaceConfig, ) -> Result< ( - SystemContextHandle, + SystemContextHandle, Sender>>, Receiver>>, ), @@ -614,11 +610,11 @@ impl> SystemContext { } } -impl> SystemContext { +impl, V: Versions> SystemContext { /// Spawn all tasks that operate on [`SystemContextHandle`]. /// /// For a list of which tasks are being spawned, see this module's documentation. - pub async fn run_tasks(&self) -> SystemContextHandle { + pub async fn run_tasks(&self) -> SystemContextHandle { let consensus_registry = ConsensusTaskRegistry::new(); let network_registry = NetworkTaskRegistry::new(); @@ -636,8 +632,8 @@ impl> SystemContext { memberships: Arc::clone(&self.memberships), }; - add_network_tasks::(&mut handle).await; - add_consensus_tasks::(&mut handle).await; + add_network_tasks::(&mut handle).await; + add_consensus_tasks::(&mut handle).await; handle } @@ -648,11 +644,12 @@ type Channel = (Sender>, Receiver>); #[async_trait] /// Trait for handling messages for a node with a twin copy of consensus -pub trait TwinsHandlerState +pub trait TwinsHandlerState where Self: std::fmt::Debug + Send + Sync, TYPES: NodeType, I: NodeImplementation, + V: Versions, { /// Handle a message sent to the twin from the network task, forwarding it to one of the two twins. async fn send_handler( @@ -742,7 +739,10 @@ where metrics: ConsensusMetricsValue, storage: I::Storage, marketplace_config: MarketplaceConfig, - ) -> (SystemContextHandle, SystemContextHandle) { + ) -> ( + SystemContextHandle, + SystemContextHandle, + ) { let left_system_context = SystemContext::new( public_key.clone(), private_key.clone(), @@ -822,8 +822,8 @@ where }; // add consensus tasks to each handle, using their individual internal event streams - add_consensus_tasks::(&mut left_handle).await; - add_consensus_tasks::(&mut right_handle).await; + add_consensus_tasks::(&mut left_handle).await; + add_consensus_tasks::(&mut right_handle).await; // fuse the event streams from both handles before initializing the network tasks let fused_internal_event_stream = self.fuse_channels( @@ -838,7 +838,7 @@ where ); // add the network tasks to the left handle. note: because the left handle has the fused event stream, the network tasks on the left handle will handle messages from both handles. - add_network_tasks::(&mut left_handle).await; + add_network_tasks::(&mut left_handle).await; // revert to the original event stream on the left handle, for any applications that want to listen to it left_handle.internal_event_stream = left_internal_event_stream.clone(); @@ -853,7 +853,7 @@ where pub struct RandomTwinsHandler; #[async_trait] -impl> TwinsHandlerState +impl, V: Versions> TwinsHandlerState for RandomTwinsHandler { async fn send_handler( @@ -885,7 +885,7 @@ impl> TwinsHandlerState pub struct DoubleTwinsHandler; #[async_trait] -impl> TwinsHandlerState +impl, V: Versions> TwinsHandlerState for DoubleTwinsHandler { async fn send_handler( @@ -906,8 +906,8 @@ impl> TwinsHandlerState } #[async_trait] -impl> ConsensusApi - for SystemContextHandle +impl, V: Versions> ConsensusApi + for SystemContextHandle { fn total_nodes(&self) -> NonZeroUsize { self.hotshot.config.num_nodes_with_stake diff --git a/crates/hotshot/src/tasks/mod.rs b/crates/hotshot/src/tasks/mod.rs index ce9634140c..d01facfadd 100644 --- a/crates/hotshot/src/tasks/mod.rs +++ b/crates/hotshot/src/tasks/mod.rs @@ -36,7 +36,7 @@ use hotshot_task_impls::{ use hotshot_types::{ constants::EVENT_CHANNEL_SIZE, data::QuorumProposal, - message::{Messages, Proposal, VersionedMessage}, + message::{Messages, Proposal}, traits::{ network::ConnectedNetwork, node_implementation::{ConsensusTime, NodeImplementation, NodeType}, @@ -47,7 +47,8 @@ use vbs::version::StaticVersionType; use crate::{ tasks::task_state::CreateTaskState, types::SystemContextHandle, ConsensusApi, ConsensusMetricsValue, ConsensusTaskRegistry, HotShotConfig, HotShotInitializer, - MarketplaceConfig, Memberships, NetworkTaskRegistry, SignatureKey, SystemContext, + MarketplaceConfig, Memberships, NetworkTaskRegistry, SignatureKey, SystemContext, UpgradeLock, + Versions, }; /// event for global event stream @@ -60,8 +61,12 @@ pub enum GlobalEvent { } /// Add tasks for network requests and responses -pub async fn add_request_network_task>( - handle: &mut SystemContextHandle, +pub async fn add_request_network_task< + TYPES: NodeType, + I: NodeImplementation, + V: Versions, +>( + handle: &mut SystemContextHandle, ) { let state = NetworkRequestState::::create_from(handle).await; @@ -74,8 +79,8 @@ pub async fn add_request_network_task>( - handle: &mut SystemContextHandle, +pub fn add_response_task, V: Versions>( + handle: &mut SystemContextHandle, request_receiver: RequestReceiver, ) { let state = NetworkResponseState::::new( @@ -97,8 +102,9 @@ pub fn add_network_message_task< TYPES: NodeType, I: NodeImplementation, NET: ConnectedNetwork, + V: Versions, >( - handle: &mut SystemContextHandle, + handle: &mut SystemContextHandle, channel: &Arc, ) { let network_state: NetworkMessageTaskState<_> = NetworkMessageTaskState { @@ -106,7 +112,7 @@ pub fn add_network_message_task< external_event_stream: handle.output_event_stream.0.clone(), }; - let decided_upgrade_certificate = Arc::clone(&handle.hotshot.decided_upgrade_certificate); + let upgrade_lock = handle.hotshot.upgrade_lock.clone(); let network = Arc::clone(channel); let mut state = network_state.clone(); @@ -115,15 +121,11 @@ pub fn add_network_message_task< futures::pin_mut!(shutdown_signal); let recv_stream = stream::unfold((), |()| async { - let decided_upgrade_certificate_lock = decided_upgrade_certificate.read().await.clone(); let msgs = match network.recv_msgs().await { Ok(msgs) => { let mut deserialized_messages = Vec::new(); for msg in msgs { - let deserialized_message = match VersionedMessage::deserialize( - &msg, - &decided_upgrade_certificate_lock, - ) { + let deserialized_message = match upgrade_lock.deserialize(&msg).await { Ok(deserialized) => deserialized, Err(e) => { tracing::error!("Failed to deserialize message: {}", e); @@ -176,20 +178,21 @@ pub fn add_network_message_task< pub fn add_network_event_task< TYPES: NodeType, I: NodeImplementation, + V: Versions, NET: ConnectedNetwork, >( - handle: &mut SystemContextHandle, + handle: &mut SystemContextHandle, channel: Arc, membership: TYPES::Membership, filter: fn(&Arc>) -> bool, ) { - let network_state: NetworkEventTaskState<_, _, _> = NetworkEventTaskState { + let network_state: NetworkEventTaskState<_, V, _, _> = NetworkEventTaskState { channel, view: TYPES::Time::genesis(), membership, filter, storage: Arc::clone(&handle.storage()), - decided_upgrade_certificate: None, + upgrade_lock: UpgradeLock::new(), }; let task = Task::new( network_state, @@ -200,24 +203,24 @@ pub fn add_network_event_task< } /// Adds consensus-related tasks to a `SystemContextHandle`. -pub async fn add_consensus_tasks>( - handle: &mut SystemContextHandle, +pub async fn add_consensus_tasks, V: Versions>( + handle: &mut SystemContextHandle, ) { handle.add_task(ViewSyncTaskState::::create_from(handle).await); handle.add_task(VidTaskState::::create_from(handle).await); handle.add_task(DaTaskState::::create_from(handle).await); - handle.add_task(TransactionTaskState::::create_from(handle).await); + handle.add_task(TransactionTaskState::::create_from(handle).await); // only spawn the upgrade task if we are actually configured to perform an upgrade. - if TYPES::Base::VERSION < TYPES::Upgrade::VERSION { - handle.add_task(UpgradeTaskState::::create_from(handle).await); + if V::Base::VERSION < V::Upgrade::VERSION { + handle.add_task(UpgradeTaskState::::create_from(handle).await); } { #![cfg(not(feature = "dependency-tasks"))] use hotshot_task_impls::consensus::ConsensusTaskState; - handle.add_task(ConsensusTaskState::::create_from(handle).await); + handle.add_task(ConsensusTaskState::::create_from(handle).await); } { #![cfg(feature = "dependency-tasks")] @@ -226,10 +229,10 @@ pub async fn add_consensus_tasks>( quorum_proposal_recv::QuorumProposalRecvTaskState, quorum_vote::QuorumVoteTaskState, }; - handle.add_task(QuorumProposalTaskState::::create_from(handle).await); - handle.add_task(QuorumVoteTaskState::::create_from(handle).await); - handle.add_task(QuorumProposalRecvTaskState::::create_from(handle).await); - handle.add_task(Consensus2TaskState::::create_from(handle).await); + handle.add_task(QuorumProposalTaskState::::create_from(handle).await); + handle.add_task(QuorumVoteTaskState::::create_from(handle).await); + handle.add_task(QuorumProposalRecvTaskState::::create_from(handle).await); + handle.add_task(Consensus2TaskState::::create_from(handle).await); } #[cfg(feature = "rewind")] @@ -244,8 +247,8 @@ pub async fn add_consensus_tasks>( /// # Usage /// Use in `select!` macros or similar constructs for graceful shutdowns: #[must_use] -pub fn create_shutdown_event_monitor>( - handle: &SystemContextHandle, +pub fn create_shutdown_event_monitor, V: Versions>( + handle: &SystemContextHandle, ) -> BoxFuture<'static, ()> { // Activate the cloned internal event stream let mut event_stream = handle.internal_event_stream.1.activate_cloned(); @@ -272,7 +275,7 @@ pub fn create_shutdown_event_monitor [Byzantine logic layer] <-> Network -pub trait EventTransformerState> +pub trait EventTransformerState, V: Versions> where Self: std::fmt::Debug + Send + Sync + 'static, { @@ -296,7 +299,7 @@ where metrics: ConsensusMetricsValue, storage: I::Storage, marketplace_config: MarketplaceConfig, - ) -> SystemContextHandle { + ) -> SystemContextHandle { let hotshot = SystemContext::new( public_key, private_key, @@ -326,7 +329,7 @@ where memberships: Arc::clone(&hotshot.memberships), }; - add_consensus_tasks::(&mut handle).await; + add_consensus_tasks::(&mut handle).await; self.add_network_tasks(&mut handle).await; handle @@ -334,7 +337,7 @@ where /// Add byzantine network tasks with the trait #[allow(clippy::too_many_lines)] - async fn add_network_tasks(&'static mut self, handle: &mut SystemContextHandle) { + async fn add_network_tasks(&'static mut self, handle: &mut SystemContextHandle) { let state_in = Arc::new(RwLock::new(self)); let state_out = Arc::clone(&state_in); // channels between the task spawned in this function and the network tasks. @@ -362,7 +365,7 @@ where ); // spawn the network tasks with our newly-created channel - add_network_tasks::(handle).await; + add_network_tasks::(handle).await; std::mem::swap( &mut internal_event_stream, @@ -479,7 +482,7 @@ pub struct BadProposalViewDos { } #[async_trait] -impl> EventTransformerState +impl, V: Versions> EventTransformerState for BadProposalViewDos { async fn recv_handler(&mut self, event: &HotShotEvent) -> Vec> { @@ -514,7 +517,7 @@ impl> EventTransformerState> EventTransformerState +impl, V: Versions> EventTransformerState for DoubleProposeVote { async fn recv_handler(&mut self, event: &HotShotEvent) -> Vec> { @@ -585,8 +588,8 @@ impl> DishonestLeader { } #[async_trait] -impl + std::fmt::Debug> - EventTransformerState for DishonestLeader +impl + std::fmt::Debug, V: Versions> + EventTransformerState for DishonestLeader { async fn recv_handler(&mut self, event: &HotShotEvent) -> Vec> { vec![event.clone()] @@ -608,8 +611,8 @@ impl + std::fmt::Debug> } /// adds tasks for sending/receiving messages to/from the network. -pub async fn add_network_tasks>( - handle: &mut SystemContextHandle, +pub async fn add_network_tasks, V: Versions>( + handle: &mut SystemContextHandle, ) { let network = Arc::clone(&handle.network); let quorum_membership = handle.memberships.quorum_membership.clone(); diff --git a/crates/hotshot/src/tasks/task_state.rs b/crates/hotshot/src/tasks/task_state.rs index 9d78dfa285..6cd8e14077 100644 --- a/crates/hotshot/src/tasks/task_state.rs +++ b/crates/hotshot/src/tasks/task_state.rs @@ -11,19 +11,12 @@ use std::{ use async_trait::async_trait; use chrono::Utc; -#[cfg(not(feature = "dependency-tasks"))] -use hotshot_task_impls::consensus::ConsensusTaskState; -#[cfg(feature = "rewind")] -use hotshot_task_impls::rewind::RewindTaskState; use hotshot_task_impls::{ - builder::BuilderClient, da::DaTaskState, request::NetworkRequestState, - transactions::TransactionTaskState, upgrade::UpgradeTaskState, vid::VidTaskState, - view_sync::ViewSyncTaskState, -}; -#[cfg(feature = "dependency-tasks")] -use hotshot_task_impls::{ - consensus2::Consensus2TaskState, quorum_proposal::QuorumProposalTaskState, + builder::BuilderClient, consensus::ConsensusTaskState, consensus2::Consensus2TaskState, + da::DaTaskState, quorum_proposal::QuorumProposalTaskState, quorum_proposal_recv::QuorumProposalRecvTaskState, quorum_vote::QuorumVoteTaskState, + request::NetworkRequestState, rewind::RewindTaskState, transactions::TransactionTaskState, + upgrade::UpgradeTaskState, vid::VidTaskState, view_sync::ViewSyncTaskState, }; use hotshot_types::{ consensus::OuterConsensus, @@ -33,25 +26,26 @@ use hotshot_types::{ }, }; -use crate::types::SystemContextHandle; +use crate::{types::SystemContextHandle, Versions}; /// Trait for creating task states. #[async_trait] -pub trait CreateTaskState +pub trait CreateTaskState where TYPES: NodeType, I: NodeImplementation, + V: Versions, { /// Function to create the task state from a given `SystemContextHandle`. - async fn create_from(handle: &SystemContextHandle) -> Self; + async fn create_from(handle: &SystemContextHandle) -> Self; } #[async_trait] -impl> CreateTaskState +impl, V: Versions> CreateTaskState for NetworkRequestState { - async fn create_from(handle: &SystemContextHandle) -> NetworkRequestState { - NetworkRequestState { + async fn create_from(handle: &SystemContextHandle) -> Self { + Self { network: Arc::clone(&handle.hotshot.network), state: OuterConsensus::new(handle.hotshot.consensus()), view: handle.cur_view().await, @@ -68,12 +62,12 @@ impl> CreateTaskState } #[async_trait] -impl> CreateTaskState - for UpgradeTaskState +impl, V: Versions> CreateTaskState + for UpgradeTaskState { - async fn create_from(handle: &SystemContextHandle) -> UpgradeTaskState { + async fn create_from(handle: &SystemContextHandle) -> Self { #[cfg(not(feature = "example-upgrade"))] - return UpgradeTaskState { + return Self { output_event_stream: handle.hotshot.external_event_stream.0.clone(), cur_view: handle.cur_view().await, quorum_membership: handle.hotshot.memberships.quorum_membership.clone().into(), @@ -90,11 +84,11 @@ impl> CreateTaskState stop_proposing_time: handle.hotshot.config.stop_proposing_time, start_voting_time: handle.hotshot.config.start_voting_time, stop_voting_time: handle.hotshot.config.stop_voting_time, - decided_upgrade_certificate: Arc::clone(&handle.hotshot.decided_upgrade_certificate), + upgrade_lock: handle.hotshot.upgrade_lock.clone(), }; #[cfg(feature = "example-upgrade")] - return UpgradeTaskState { + return Self { output_event_stream: handle.hotshot.external_event_stream.0.clone(), cur_view: handle.cur_view().await, quorum_membership: handle.hotshot.memberships.quorum_membership.clone().into(), @@ -111,17 +105,17 @@ impl> CreateTaskState stop_proposing_time: u64::MAX, start_voting_time: 0, stop_voting_time: u64::MAX, - decided_upgrade_certificate: Arc::clone(&handle.hotshot.decided_upgrade_certificate), + upgrade_lock: handle.hotshot.upgrade_lock.clone(), }; } } #[async_trait] -impl> CreateTaskState +impl, V: Versions> CreateTaskState for VidTaskState { - async fn create_from(handle: &SystemContextHandle) -> VidTaskState { - VidTaskState { + async fn create_from(handle: &SystemContextHandle) -> Self { + Self { consensus: OuterConsensus::new(handle.hotshot.consensus()), cur_view: handle.cur_view().await, vote_collector: None, @@ -135,11 +129,11 @@ impl> CreateTaskState } #[async_trait] -impl> CreateTaskState +impl, V: Versions> CreateTaskState for DaTaskState { - async fn create_from(handle: &SystemContextHandle) -> DaTaskState { - DaTaskState { + async fn create_from(handle: &SystemContextHandle) -> Self { + Self { consensus: OuterConsensus::new(handle.hotshot.consensus()), output_event_stream: handle.hotshot.external_event_stream.0.clone(), da_membership: handle.hotshot.memberships.da_membership.clone().into(), @@ -156,12 +150,13 @@ impl> CreateTaskState } #[async_trait] -impl> CreateTaskState +impl, V: Versions> CreateTaskState for ViewSyncTaskState { - async fn create_from(handle: &SystemContextHandle) -> ViewSyncTaskState { + async fn create_from(handle: &SystemContextHandle) -> Self { let cur_view = handle.cur_view().await; - ViewSyncTaskState { + + Self { current_view: cur_view, next_view: cur_view, network: Arc::clone(&handle.hotshot.network), @@ -186,11 +181,11 @@ impl> CreateTaskState } #[async_trait] -impl> CreateTaskState - for TransactionTaskState +impl, V: Versions> CreateTaskState + for TransactionTaskState { - async fn create_from(handle: &SystemContextHandle) -> TransactionTaskState { - TransactionTaskState { + async fn create_from(handle: &SystemContextHandle) -> Self { + Self { builder_timeout: handle.builder_timeout(), output_event_stream: handle.hotshot.external_event_stream.0.clone(), consensus: OuterConsensus::new(handle.hotshot.consensus()), @@ -209,7 +204,7 @@ impl> CreateTaskState .cloned() .map(BuilderClient::new) .collect(), - decided_upgrade_certificate: Arc::clone(&handle.hotshot.decided_upgrade_certificate), + upgrade_lock: handle.hotshot.upgrade_lock.clone(), auction_results_provider: Arc::clone( &handle.hotshot.marketplace_config.auction_results_provider, ), @@ -222,16 +217,15 @@ impl> CreateTaskState } } -#[cfg(not(feature = "dependency-tasks"))] #[async_trait] -impl> CreateTaskState - for ConsensusTaskState +impl, V: Versions> CreateTaskState + for ConsensusTaskState { - async fn create_from(handle: &SystemContextHandle) -> ConsensusTaskState { + async fn create_from(handle: &SystemContextHandle) -> Self { let consensus = handle.hotshot.consensus(); let timeout_task = handle.spawn_initial_timeout_task(); - ConsensusTaskState { + Self { consensus: OuterConsensus::new(consensus), instance_state: handle.hotshot.instance_state(), timeout: handle.hotshot.config.next_view_timeout, @@ -255,20 +249,19 @@ impl> CreateTaskState quorum_membership: handle.hotshot.memberships.quorum_membership.clone().into(), da_membership: handle.hotshot.memberships.da_membership.clone().into(), storage: Arc::clone(&handle.storage), - decided_upgrade_certificate: Arc::clone(&handle.hotshot.decided_upgrade_certificate), + upgrade_lock: handle.hotshot.upgrade_lock.clone(), } } } -#[cfg(feature = "dependency-tasks")] #[async_trait] -impl> CreateTaskState - for QuorumVoteTaskState +impl, V: Versions> CreateTaskState + for QuorumVoteTaskState { - async fn create_from(handle: &SystemContextHandle) -> QuorumVoteTaskState { + async fn create_from(handle: &SystemContextHandle) -> Self { let consensus = handle.hotshot.consensus(); - QuorumVoteTaskState { + Self { public_key: handle.public_key().clone(), private_key: handle.private_key().clone(), consensus: OuterConsensus::new(consensus), @@ -281,23 +274,20 @@ impl> CreateTaskState output_event_stream: handle.hotshot.external_event_stream.0.clone(), id: handle.hotshot.id, storage: Arc::clone(&handle.storage), - decided_upgrade_certificate: Arc::clone(&handle.hotshot.decided_upgrade_certificate), + upgrade_lock: handle.hotshot.upgrade_lock.clone(), } } } -#[cfg(feature = "dependency-tasks")] #[async_trait] -impl> CreateTaskState - for QuorumProposalTaskState +impl, V: Versions> CreateTaskState + for QuorumProposalTaskState { - async fn create_from( - handle: &SystemContextHandle, - ) -> QuorumProposalTaskState { + async fn create_from(handle: &SystemContextHandle) -> Self { let consensus = handle.hotshot.consensus(); let timeout_task = handle.spawn_initial_timeout_task(); - QuorumProposalTaskState { + Self { latest_proposed_view: handle.cur_view().await, proposal_dependencies: HashMap::new(), network: Arc::clone(&handle.hotshot.network), @@ -314,23 +304,20 @@ impl> CreateTaskState round_start_delay: handle.hotshot.config.round_start_delay, id: handle.hotshot.id, formed_upgrade_certificate: None, - decided_upgrade_certificate: Arc::clone(&handle.hotshot.decided_upgrade_certificate), + upgrade_lock: handle.hotshot.upgrade_lock.clone(), } } } -#[cfg(feature = "dependency-tasks")] #[async_trait] -impl> CreateTaskState - for QuorumProposalRecvTaskState +impl, V: Versions> CreateTaskState + for QuorumProposalRecvTaskState { - async fn create_from( - handle: &SystemContextHandle, - ) -> QuorumProposalRecvTaskState { + async fn create_from(handle: &SystemContextHandle) -> Self { let consensus = handle.hotshot.consensus(); let timeout_task = handle.spawn_initial_timeout_task(); - QuorumProposalRecvTaskState { + Self { public_key: handle.public_key().clone(), private_key: handle.private_key().clone(), consensus: OuterConsensus::new(consensus), @@ -348,21 +335,20 @@ impl> CreateTaskState spawned_tasks: BTreeMap::new(), instance_state: handle.hotshot.instance_state(), id: handle.hotshot.id, - decided_upgrade_certificate: Arc::clone(&handle.hotshot.decided_upgrade_certificate), + upgrade_lock: handle.hotshot.upgrade_lock.clone(), } } } -#[cfg(feature = "dependency-tasks")] #[async_trait] -impl> CreateTaskState - for Consensus2TaskState +impl, V: Versions> CreateTaskState + for Consensus2TaskState { - async fn create_from(handle: &SystemContextHandle) -> Consensus2TaskState { + async fn create_from(handle: &SystemContextHandle) -> Self { let consensus = handle.hotshot.consensus(); let timeout_task = handle.spawn_initial_timeout_task(); - Consensus2TaskState { + Self { public_key: handle.public_key().clone(), private_key: handle.private_key().clone(), instance_state: handle.hotshot.instance_state(), @@ -381,18 +367,17 @@ impl> CreateTaskState consensus: OuterConsensus::new(consensus), last_decided_view: handle.cur_view().await, id: handle.hotshot.id, - decided_upgrade_certificate: Arc::clone(&handle.hotshot.decided_upgrade_certificate), + upgrade_lock: handle.hotshot.upgrade_lock.clone(), } } } -#[cfg(feature = "rewind")] #[async_trait] -impl> CreateTaskState +impl, V: Versions> CreateTaskState for RewindTaskState { - async fn create_from(handle: &SystemContextHandle) -> RewindTaskState { - RewindTaskState { + async fn create_from(handle: &SystemContextHandle) -> Self { + Self { events: Vec::new(), id: handle.hotshot.id, } diff --git a/crates/hotshot/src/types/handle.rs b/crates/hotshot/src/types/handle.rs index 4587e145aa..0b285b593f 100644 --- a/crates/hotshot/src/types/handle.rs +++ b/crates/hotshot/src/types/handle.rs @@ -26,14 +26,14 @@ use hotshot_types::{ use tokio::task::JoinHandle; use tracing::instrument; -use crate::{traits::NodeImplementation, types::Event, Memberships, SystemContext}; +use crate::{traits::NodeImplementation, types::Event, Memberships, SystemContext, Versions}; /// Event streaming handle for a [`SystemContext`] instance running in the background /// /// This type provides the means to message and interact with a background [`SystemContext`] instance, /// allowing the ability to receive [`Event`]s from it, send transactions to it, and interact with /// the underlying storage. -pub struct SystemContextHandle> { +pub struct SystemContextHandle, V: Versions> { /// The [sender](Sender) and [receiver](Receiver), /// to allow the application to communicate with HotShot. pub(crate) output_event_stream: (Sender>, InactiveReceiver>), @@ -51,7 +51,7 @@ pub struct SystemContextHandle> { pub(crate) network_registry: NetworkTaskRegistry, /// Internal reference to the underlying [`SystemContext`] - pub hotshot: Arc>, + pub hotshot: Arc>, /// Reference to the internal storage for consensus datum. pub(crate) storage: Arc>, @@ -63,7 +63,9 @@ pub struct SystemContextHandle> { pub memberships: Arc>, } -impl + 'static> SystemContextHandle { +impl + 'static, V: Versions> + SystemContextHandle +{ /// Adds a hotshot consensus-related task to the `SystemContextHandle`. pub fn add_task> + 'static>(&mut self, task_state: S) { let task = Task::new( @@ -154,9 +156,7 @@ impl + 'static> SystemContextHandl &self, tx: TYPES::Transaction, ) -> Result<(), HotShotError> { - self.hotshot - .publish_transaction_async(tx, Arc::clone(&self.hotshot.decided_upgrade_certificate)) - .await + self.hotshot.publish_transaction_async(tx).await } /// Get the underlying consensus state for this [`SystemContext`] diff --git a/crates/macros/src/lib.rs b/crates/macros/src/lib.rs index cc333dabae..4a9f921fd2 100644 --- a/crates/macros/src/lib.rs +++ b/crates/macros/src/lib.rs @@ -19,6 +19,8 @@ use syn::{ struct CrossTestData { /// imlementations impls: ExprArray, + /// versions + versions: ExprArray, /// types types: ExprArray, /// name of the test @@ -34,6 +36,7 @@ impl CrossTestDataBuilder { fn is_ready(&self) -> bool { self.impls.is_some() && self.types.is_some() + && self.versions.is_some() && self.test_name.is_some() && self.metadata.is_some() && self.test_name.is_some() @@ -48,6 +51,8 @@ struct TestData { ty: ExprPath, /// impl imply: ExprPath, + /// impl + version: ExprPath, /// name of test test_name: Ident, /// test description @@ -101,6 +106,7 @@ impl TestData { let TestData { ty, imply, + version, test_name, metadata, ignore, @@ -124,7 +130,7 @@ impl TestData { async fn #test_name() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - TestDescription::<#ty, #imply>::gen_launcher((#metadata), 0).launch().run_test::().await; + TestDescription::<#ty, #imply, #version>::gen_launcher((#metadata), 0).launch().run_test::().await; } } } @@ -137,6 +143,7 @@ mod keywords { syn::custom_keyword!(TestName); syn::custom_keyword!(Types); syn::custom_keyword!(Impls); + syn::custom_keyword!(Versions); } impl Parse for CrossTestData { @@ -156,6 +163,11 @@ impl Parse for CrossTestData { input.parse::()?; let impls = input.parse::()?; description.impls(impls); + } else if input.peek(keywords::Versions) { + let _ = input.parse::()?; + input.parse::()?; + let versions = input.parse::()?; + description.versions(versions); } else if input.peek(keywords::TestName) { let _ = input.parse::()?; input.parse::()?; @@ -173,7 +185,7 @@ impl Parse for CrossTestData { description.ignore(ignore); } else { panic!( - "Unexpected token. Expected one of: Metadata, Ignore, Impls, Types, Testname" + "Unexpected token. Expected one of: Metadata, Ignore, Impls, Versions, Types, Testname" ); } if input.peek(Token![,]) { @@ -204,28 +216,38 @@ fn cross_tests_internal(test_spec: CrossTestData) -> TokenStream { p }); + let versions = test_spec.versions.elems.iter().map(|t| { + let Expr::Path(p) = t else { + panic!("Expected Path for Version! Got {t:?}"); + }; + p + }); + let mut result = quote! {}; for ty in types.clone() { let mut type_mod = quote! {}; for imp in impls.clone() { - let test_data = TestDataBuilder::create_empty() - .test_name(test_spec.test_name.clone()) - .metadata(test_spec.metadata.clone()) - .ignore(test_spec.ignore.clone()) - .imply(imp.clone()) - .ty(ty.clone()) - .build() - .unwrap(); - let test = test_data.generate_test(); - - let impl_str = format_ident!("{}", imp.to_lower_snake_str()); - let impl_result = quote! { - pub mod #impl_str { - use super::*; - #test - } - }; - type_mod.extend(impl_result); + for version in versions.clone() { + let test_data = TestDataBuilder::create_empty() + .test_name(test_spec.test_name.clone()) + .metadata(test_spec.metadata.clone()) + .ignore(test_spec.ignore.clone()) + .version(version.clone()) + .imply(imp.clone()) + .ty(ty.clone()) + .build() + .unwrap(); + let test = test_data.generate_test(); + + let impl_str = format_ident!("{}", imp.to_lower_snake_str()); + let impl_result = quote! { + pub mod #impl_str { + use super::*; + #test + } + }; + type_mod.extend(impl_result); + } } let ty_str = format_ident!("{}", ty.to_lower_snake_str()); let typ_result = quote! { diff --git a/crates/task-impls/src/consensus/handlers.rs b/crates/task-impls/src/consensus/handlers.rs index 37a97093f8..187b486ebb 100644 --- a/crates/task-impls/src/consensus/handlers.rs +++ b/crates/task-impls/src/consensus/handlers.rs @@ -4,8 +4,6 @@ // You should have received a copy of the MIT License // along with the HotShot repository. If not, see . -#![cfg(not(feature = "dependency-tasks"))] - use core::time::Duration; use std::{marker::PhantomData, sync::Arc}; @@ -20,11 +18,10 @@ use committable::Committable; use futures::FutureExt; use hotshot_types::{ consensus::{CommitmentAndMetadata, OuterConsensus, View}, - constants::MarketplaceVersion, data::{null_block, Leaf, QuorumProposal, ViewChangeEvidence}, event::{Event, EventType}, message::{GeneralConsensusMessage, Proposal}, - simple_certificate::{version, UpgradeCertificate}, + simple_certificate::UpgradeCertificate, simple_vote::QuorumData, traits::{ block_contents::BlockHeader, @@ -44,6 +41,7 @@ use vbs::version::{StaticVersionType, Version}; use super::ConsensusTaskState; use crate::{ + consensus::{UpgradeLock, Versions}, events::HotShotEvent, helpers::{ broadcast_event, decide_from_proposal, fetch_proposal, parent_leaf_and_state, update_view, @@ -56,7 +54,7 @@ use crate::{ /// the proposal send evnet. #[allow(clippy::too_many_arguments)] #[instrument(skip_all, fields(id = id, view = *view))] -pub async fn create_and_send_proposal( +pub async fn create_and_send_proposal( public_key: TYPES::SignatureKey, private_key: ::PrivateKey, consensus: OuterConsensus, @@ -83,7 +81,7 @@ pub async fn create_and_send_proposal( .context("Failed to get vid share")?; drop(consensus_read); - let block_header = if version < MarketplaceVersion::VERSION { + let block_header = if version < V::Marketplace::VERSION { TYPES::BlockHeader::new_legacy( state.as_ref(), instance_state.as_ref(), @@ -162,7 +160,7 @@ pub async fn create_and_send_proposal( /// standard case proposal scenario. #[allow(clippy::too_many_arguments)] #[instrument(skip_all)] -pub async fn publish_proposal_from_commitment_and_metadata( +pub async fn publish_proposal_from_commitment_and_metadata( view: TYPES::Time, sender: Sender>>, quorum_membership: Arc, @@ -171,7 +169,7 @@ pub async fn publish_proposal_from_commitment_and_metadata( consensus: OuterConsensus, delay: u64, formed_upgrade_certificate: Option>, - decided_upgrade_certificate: Arc>>>, + upgrade_lock: UpgradeLock, commitment_and_metadata: Option>, proposal_cert: Option>, instance_state: Arc, @@ -199,7 +197,7 @@ pub async fn publish_proposal_from_commitment_and_metadata( if let Some(cert) = proposal_upgrade_certificate.clone() { if cert - .is_relevant(view, Arc::clone(&decided_upgrade_certificate)) + .is_relevant(view, Arc::clone(&upgrade_lock.decided_upgrade_certificate)) .await .is_err() { @@ -224,10 +222,10 @@ pub async fn publish_proposal_from_commitment_and_metadata( "Cannot propose because our VID payload commitment and metadata is for an older view." ); - let version = version(view, &decided_upgrade_certificate.read().await.clone())?; + let version = upgrade_lock.version(view).await?; let create_and_send_proposal_handle = async_spawn(async move { - match create_and_send_proposal( + match create_and_send_proposal::( public_key, private_key, OuterConsensus::new(Arc::clone(&consensus.inner_consensus)), @@ -259,7 +257,7 @@ pub async fn publish_proposal_from_commitment_and_metadata( /// `commitment_and_metadata`, or a `decided_upgrade_certificate`. #[allow(clippy::too_many_arguments)] #[instrument(skip_all)] -pub async fn publish_proposal_if_able( +pub async fn publish_proposal_if_able( view: TYPES::Time, sender: Sender>>, quorum_membership: Arc, @@ -268,7 +266,7 @@ pub async fn publish_proposal_if_able( consensus: OuterConsensus, delay: u64, formed_upgrade_certificate: Option>, - decided_upgrade_certificate: Arc>>>, + upgrade_lock: UpgradeLock, commitment_and_metadata: Option>, proposal_cert: Option>, instance_state: Arc, @@ -283,7 +281,7 @@ pub async fn publish_proposal_if_able( consensus, delay, formed_upgrade_certificate, - decided_upgrade_certificate, + upgrade_lock, commitment_and_metadata, proposal_cert, instance_state, @@ -297,11 +295,15 @@ pub async fn publish_proposal_if_able( /// Returns the proposal that should be used to set the `cur_proposal` for other tasks. #[allow(clippy::too_many_lines)] #[instrument(skip_all)] -pub(crate) async fn handle_quorum_proposal_recv>( +pub(crate) async fn handle_quorum_proposal_recv< + TYPES: NodeType, + I: NodeImplementation, + V: Versions, +>( proposal: &Proposal>, sender: &TYPES::SignatureKey, event_stream: Sender>>, - task_state: &mut ConsensusTaskState, + task_state: &mut ConsensusTaskState, ) -> Result>> { let sender = sender.clone(); debug!( @@ -475,7 +477,7 @@ pub(crate) async fn handle_quorum_proposal_recv>( +pub async fn handle_quorum_proposal_validated< + TYPES: NodeType, + I: NodeImplementation, + V: Versions, +>( proposal: &QuorumProposal, event_stream: Sender>>, - task_state: &mut ConsensusTaskState, + task_state: &mut ConsensusTaskState, ) -> Result<()> { let view = proposal.view_number(); task_state.current_proposal = Some(proposal.clone()); @@ -531,13 +537,17 @@ pub async fn handle_quorum_proposal_validated = ( +type VoteInfo = ( <::SignatureKey as SignatureKey>::PrivateKey, - Arc>>>, + UpgradeLock, Arc<::Membership>, Sender>>, ); @@ -649,7 +659,11 @@ type VoteInfo = ( /// Check if we are able to vote, like whether the proposal is valid, /// whether we have DAC and VID share, and if so, vote. #[instrument(skip_all, fields(id = id, view = *cur_view))] -pub async fn update_state_and_vote_if_able>( +pub async fn update_state_and_vote_if_able< + TYPES: NodeType, + I: NodeImplementation, + V: Versions, +>( cur_view: TYPES::Time, proposal: QuorumProposal, public_key: TYPES::SignatureKey, @@ -657,7 +671,7 @@ pub async fn update_state_and_vote_if_able>, quorum_membership: Arc, instance_state: Arc, - vote_info: VoteInfo, + vote_info: VoteInfo, id: u64, ) -> bool { use hotshot_types::simple_vote::QuorumVote; @@ -681,7 +695,7 @@ pub async fn update_state_and_vote_if_able version, Err(e) => { error!("Failed to calculate the version: {e:?}"); diff --git a/crates/task-impls/src/consensus/mod.rs b/crates/task-impls/src/consensus/mod.rs index e87a59438d..2b6970f785 100644 --- a/crates/task-impls/src/consensus/mod.rs +++ b/crates/task-impls/src/consensus/mod.rs @@ -4,8 +4,6 @@ // You should have received a copy of the MIT License // along with the HotShot repository. If not, see . -#![cfg(not(feature = "dependency-tasks"))] - use std::{collections::BTreeMap, sync::Arc}; use anyhow::Result; @@ -21,12 +19,12 @@ use hotshot_types::{ consensus::{CommitmentAndMetadata, OuterConsensus}, data::{QuorumProposal, VidDisperseShare, ViewChangeEvidence}, event::{Event, EventType}, - message::Proposal, + message::{Proposal, UpgradeLock}, simple_certificate::{QuorumCertificate, TimeoutCertificate, UpgradeCertificate}, simple_vote::{QuorumVote, TimeoutData, TimeoutVote}, traits::{ election::Membership, - node_implementation::{NodeImplementation, NodeType}, + node_implementation::{NodeImplementation, NodeType, Versions}, signature_key::SignatureKey, storage::Storage, }, @@ -58,7 +56,7 @@ type VoteCollectorOption = Option> { +pub struct ConsensusTaskState, V: Versions> { /// Our public key pub public_key: TYPES::SignatureKey, /// Our Private Key @@ -132,11 +130,11 @@ pub struct ConsensusTaskState> { /// This node's storage ref pub storage: Arc>, - /// an upgrade certificate that has been decided on, if any - pub decided_upgrade_certificate: Arc>>>, + /// Lock for a decided upgrade + pub upgrade_lock: UpgradeLock, } -impl> ConsensusTaskState { +impl, V: Versions> ConsensusTaskState { /// Cancel all tasks the consensus tasks has spawned before the given view pub async fn cancel_tasks(&mut self, view: TYPES::Time) { let keep = self.spawned_tasks.split_off(&view); @@ -210,7 +208,7 @@ impl> ConsensusTaskState OuterConsensus::new(Arc::clone(&self.consensus.inner_consensus)), self.round_start_delay, self.formed_upgrade_certificate.clone(), - Arc::clone(&self.decided_upgrade_certificate), + self.upgrade_lock.clone(), self.payload_commitment_and_metadata.clone(), self.proposal_cert.clone(), Arc::clone(&self.instance_state), @@ -240,7 +238,7 @@ impl> ConsensusTaskState if proposal.view_number() != view { return; } - let upgrade = Arc::clone(&self.decided_upgrade_certificate); + let upgrade = self.upgrade_lock.clone(); let pub_key = self.public_key.clone(); let priv_key = self.private_key.clone(); let consensus = OuterConsensus::new(Arc::clone(&self.consensus.inner_consensus)); @@ -250,7 +248,7 @@ impl> ConsensusTaskState let instance_state = Arc::clone(&self.instance_state); let id = self.id; let handle = async_spawn(async move { - update_state_and_vote_if_able::( + update_state_and_vote_if_able::( view, proposal, pub_key, @@ -489,7 +487,13 @@ impl> ConsensusTaskState // If we have a decided upgrade certificate, the protocol version may also have // been upgraded. - if let Some(cert) = self.decided_upgrade_certificate.read().await.clone() { + if let Some(cert) = self + .upgrade_lock + .decided_upgrade_certificate + .read() + .await + .clone() + { if new_view == cert.data.new_version_first_view { error!( "Version upgraded based on a decided upgrade cert: {:?}", @@ -703,7 +707,9 @@ impl> ConsensusTaskState } #[async_trait] -impl> TaskState for ConsensusTaskState { +impl, V: Versions> TaskState + for ConsensusTaskState +{ type Event = HotShotEvent; async fn handle_event( diff --git a/crates/task-impls/src/consensus2/handlers.rs b/crates/task-impls/src/consensus2/handlers.rs index a72d4958b7..69d10e9788 100644 --- a/crates/task-impls/src/consensus2/handlers.rs +++ b/crates/task-impls/src/consensus2/handlers.rs @@ -24,17 +24,22 @@ use tracing::{debug, error, instrument}; use super::Consensus2TaskState; use crate::{ + consensus2::Versions, events::{HotShotEvent, HotShotTaskCompleted}, helpers::{broadcast_event, cancel_task}, vote_collection::{create_vote_accumulator, AccumulatorInfo, HandleVoteEvent}, }; /// Handle a `QuorumVoteRecv` event. -pub(crate) async fn handle_quorum_vote_recv>( +pub(crate) async fn handle_quorum_vote_recv< + TYPES: NodeType, + I: NodeImplementation, + V: Versions, +>( vote: &QuorumVote, event: Arc>, sender: &Sender>>, - task_state: &mut Consensus2TaskState, + task_state: &mut Consensus2TaskState, ) -> Result<()> { // Are we the leader for this view? ensure!( @@ -73,11 +78,15 @@ pub(crate) async fn handle_quorum_vote_recv>( +pub(crate) async fn handle_timeout_vote_recv< + TYPES: NodeType, + I: NodeImplementation, + V: Versions, +>( vote: &TimeoutVote, event: Arc>, sender: &Sender>>, - task_state: &mut Consensus2TaskState, + task_state: &mut Consensus2TaskState, ) -> Result<()> { // Are we the leader for this view? ensure!( @@ -118,10 +127,14 @@ pub(crate) async fn handle_timeout_vote_recv>( +pub(crate) async fn handle_view_change< + TYPES: NodeType, + I: NodeImplementation, + V: Versions, +>( new_view_number: TYPES::Time, sender: &Sender>>, - task_state: &mut Consensus2TaskState, + task_state: &mut Consensus2TaskState, ) -> Result<()> { ensure!( new_view_number > task_state.cur_view, @@ -135,8 +148,12 @@ pub(crate) async fn handle_view_change>( +pub(crate) async fn handle_timeout, V: Versions>( view_number: TYPES::Time, sender: &Sender>>, - task_state: &mut Consensus2TaskState, + task_state: &mut Consensus2TaskState, ) -> Result<()> { ensure!( task_state.cur_view < view_number, diff --git a/crates/task-impls/src/consensus2/mod.rs b/crates/task-impls/src/consensus2/mod.rs index a31c97850d..65c80cab34 100644 --- a/crates/task-impls/src/consensus2/mod.rs +++ b/crates/task-impls/src/consensus2/mod.rs @@ -16,10 +16,11 @@ use hotshot_task::task::TaskState; use hotshot_types::{ consensus::OuterConsensus, event::Event, - simple_certificate::{QuorumCertificate, TimeoutCertificate, UpgradeCertificate}, + message::UpgradeLock, + simple_certificate::{QuorumCertificate, TimeoutCertificate}, simple_vote::{QuorumVote, TimeoutVote}, traits::{ - node_implementation::{NodeImplementation, NodeType}, + node_implementation::{NodeImplementation, NodeType, Versions}, signature_key::SignatureKey, }, }; @@ -39,7 +40,7 @@ type VoteCollectorOption = Option> { +pub struct Consensus2TaskState, V: Versions> { /// Our public key pub public_key: TYPES::SignatureKey, @@ -96,10 +97,10 @@ pub struct Consensus2TaskState> { /// The node's id pub id: u64, - /// An upgrade certificate that has been decided on, if any. - pub decided_upgrade_certificate: Arc>>>, + /// Lock for a decided upgrade + pub upgrade_lock: UpgradeLock, } -impl> Consensus2TaskState { +impl, V: Versions> Consensus2TaskState { /// Handles a consensus event received on the event stream #[instrument(skip_all, fields(id = self.id, cur_view = *self.cur_view, last_decided_view = *self.last_decided_view), name = "Consensus replica task", level = "error", target = "Consensus2TaskState")] pub async fn handle( @@ -153,7 +154,9 @@ impl> Consensus2TaskState> TaskState for Consensus2TaskState { +impl, V: Versions> TaskState + for Consensus2TaskState +{ type Event = HotShotEvent; async fn handle_event( diff --git a/crates/task-impls/src/lib.rs b/crates/task-impls/src/lib.rs index 5693000636..ed3dc5a0ee 100644 --- a/crates/task-impls/src/lib.rs +++ b/crates/task-impls/src/lib.rs @@ -63,5 +63,4 @@ pub mod quorum_proposal; pub mod quorum_proposal_recv; /// Task for storing and replaying all received tasks by a node -#[cfg(feature = "rewind")] pub mod rewind; diff --git a/crates/task-impls/src/network.rs b/crates/task-impls/src/network.rs index bcef607db7..fe6712a1c4 100644 --- a/crates/task-impls/src/network.rs +++ b/crates/task-impls/src/network.rs @@ -17,13 +17,12 @@ use hotshot_types::{ event::{Event, EventType, HotShotAction}, message::{ DaConsensusMessage, DataMessage, GeneralConsensusMessage, Message, MessageKind, Proposal, - SequencingMessage, VersionedMessage, + SequencingMessage, UpgradeLock, }, - simple_certificate::UpgradeCertificate, traits::{ election::Membership, network::{BroadcastDelay, ConnectedNetwork, TransmitType, ViewMessage}, - node_implementation::{ConsensusTime, NodeType}, + node_implementation::{ConsensusTime, NodeType, Versions}, storage::Storage, }, vote::{HasViewNumber, Vote}, @@ -210,6 +209,7 @@ impl NetworkMessageTaskState { /// network event task state pub struct NetworkEventTaskState< TYPES: NodeType, + V: Versions, COMMCHANNEL: ConnectedNetwork, S: Storage, > { @@ -224,16 +224,17 @@ pub struct NetworkEventTaskState< pub filter: fn(&Arc>) -> bool, /// Storage to store actionable events pub storage: Arc>, - /// Decided upgrade certificate - pub decided_upgrade_certificate: Option>, + /// Lock for a decided upgrade + pub upgrade_lock: UpgradeLock, } #[async_trait] impl< TYPES: NodeType, + V: Versions, COMMCHANNEL: ConnectedNetwork, S: Storage + 'static, - > TaskState for NetworkEventTaskState + > TaskState for NetworkEventTaskState { type Event = HotShotEvent; @@ -257,9 +258,10 @@ impl< impl< TYPES: NodeType, + V: Versions, COMMCHANNEL: ConnectedNetwork, S: Storage + 'static, - > NetworkEventTaskState + > NetworkEventTaskState { /// Handle the given event. /// @@ -297,7 +299,7 @@ impl< ) } HotShotEvent::VidDisperseSend(proposal, sender) => { - self.handle_vid_disperse_proposal(proposal, &sender); + self.handle_vid_disperse_proposal(proposal, &sender).await; return; } HotShotEvent::DaProposalSend(proposal, sender) => { @@ -404,10 +406,6 @@ impl< .await; return; } - HotShotEvent::UpgradeDecided(cert) => { - self.decided_upgrade_certificate = Some(cert.clone()); - return; - } _ => { return; } @@ -428,9 +426,9 @@ impl< let committee_topic = membership.committee_topic(); let net = Arc::clone(&self.channel); let storage = Arc::clone(&self.storage); - let decided_upgrade_certificate = self.decided_upgrade_certificate.clone(); + let upgrade_lock = self.upgrade_lock.clone(); async_spawn(async move { - if NetworkEventTaskState::::maybe_record_action( + if NetworkEventTaskState::::maybe_record_action( maybe_action, Arc::clone(&storage), view, @@ -449,7 +447,7 @@ impl< } } - let serialized_message = match message.serialize(&decided_upgrade_certificate) { + let serialized_message = match upgrade_lock.serialize(&message).await { Ok(serialized) => serialized, Err(e) => { error!("Failed to serialize message: {}", e); @@ -479,7 +477,7 @@ impl< } /// handle `VidDisperseSend` - fn handle_vid_disperse_proposal( + async fn handle_vid_disperse_proposal( &self, vid_proposal: Proposal>, sender: &::SignatureKey, @@ -496,7 +494,7 @@ impl< DaConsensusMessage::VidDisperseMsg(proposal), )), // TODO not a DaConsensusMessage https://github.com/EspressoSystems/HotShot/issues/1696 }; - let serialized_message = match message.serialize(&self.decided_upgrade_certificate) { + let serialized_message = match self.upgrade_lock.serialize(&message).await { Ok(serialized) => serialized, Err(e) => { error!("Failed to serialize message: {}", e); @@ -510,7 +508,7 @@ impl< let net = Arc::clone(&self.channel); let storage = Arc::clone(&self.storage); async_spawn(async move { - if NetworkEventTaskState::::maybe_record_action( + if NetworkEventTaskState::::maybe_record_action( Some(HotShotAction::VidDisperse), storage, view, diff --git a/crates/task-impls/src/quorum_proposal/handlers.rs b/crates/task-impls/src/quorum_proposal/handlers.rs index 3dbf147c4f..f2386ce826 100644 --- a/crates/task-impls/src/quorum_proposal/handlers.rs +++ b/crates/task-impls/src/quorum_proposal/handlers.rs @@ -20,10 +20,9 @@ use hotshot_task::{ }; use hotshot_types::{ consensus::{CommitmentAndMetadata, OuterConsensus}, - constants::MarketplaceVersion, data::{Leaf, QuorumProposal, VidDisperse, ViewChangeEvidence}, message::Proposal, - simple_certificate::{version, UpgradeCertificate}, + simple_certificate::UpgradeCertificate, traits::{ block_contents::BlockHeader, node_implementation::NodeType, signature_key::SignatureKey, }, @@ -34,6 +33,7 @@ use vbs::version::StaticVersionType; use crate::{ events::HotShotEvent, helpers::{broadcast_event, fetch_proposal, parent_leaf_and_state}, + quorum_proposal::{UpgradeLock, Versions}, }; /// Proposal dependency types. These types represent events that precipitate a proposal. @@ -59,7 +59,7 @@ pub(crate) enum ProposalDependency { } /// Handler for the proposal dependency -pub struct ProposalDependencyHandle { +pub struct ProposalDependencyHandle { /// Latest view number that has been proposed for (proxy for cur_view). pub latest_proposed_view: TYPES::Time, @@ -98,14 +98,14 @@ pub struct ProposalDependencyHandle { /// since they will be present in the leaf we propose off of. pub formed_upgrade_certificate: Option>, - /// An upgrade certificate that has been decided on, if any. - pub decided_upgrade_certificate: Arc>>>, + /// Lock for a decided upgrade + pub upgrade_lock: UpgradeLock, /// The node's id pub id: u64, } -impl ProposalDependencyHandle { +impl ProposalDependencyHandle { /// Publishes a proposal given the [`CommitmentAndMetadata`], [`VidDisperse`] /// and high qc [`hotshot_types::simple_certificate::QuorumCertificate`], /// with optional [`ViewChangeEvidence`]. @@ -165,12 +165,9 @@ impl ProposalDependencyHandle { "Cannot propose because our VID payload commitment and metadata is for an older view." ); - let version = version( - self.view_number, - &self.decided_upgrade_certificate.read().await.clone(), - )?; + let version = self.upgrade_lock.version(self.view_number).await?; - let block_header = if version < MarketplaceVersion::VERSION { + let block_header = if version < V::Marketplace::VERSION { TYPES::BlockHeader::new_legacy( state.as_ref(), self.instance_state.as_ref(), @@ -246,7 +243,7 @@ impl ProposalDependencyHandle { Ok(()) } } -impl HandleDepOutput for ProposalDependencyHandle { +impl HandleDepOutput for ProposalDependencyHandle { type Output = Vec>>>>; #[allow(clippy::no_effect_underscore_binding)] @@ -347,7 +344,7 @@ impl HandleDepOutput for ProposalDependencyHandle { vid_share.unwrap(), proposal_cert, self.formed_upgrade_certificate.clone(), - Arc::clone(&self.decided_upgrade_certificate), + Arc::clone(&self.upgrade_lock.decided_upgrade_certificate), ) .await { diff --git a/crates/task-impls/src/quorum_proposal/mod.rs b/crates/task-impls/src/quorum_proposal/mod.rs index f2179058cb..cd382c38f5 100644 --- a/crates/task-impls/src/quorum_proposal/mod.rs +++ b/crates/task-impls/src/quorum_proposal/mod.rs @@ -21,10 +21,11 @@ use hotshot_task::{ use hotshot_types::{ consensus::OuterConsensus, event::Event, + message::UpgradeLock, simple_certificate::UpgradeCertificate, traits::{ election::Membership, - node_implementation::{ConsensusTime, NodeImplementation, NodeType}, + node_implementation::{ConsensusTime, NodeImplementation, NodeType, Versions}, signature_key::SignatureKey, storage::Storage, }, @@ -43,7 +44,7 @@ use crate::{ mod handlers; /// The state for the quorum proposal task. -pub struct QuorumProposalTaskState> { +pub struct QuorumProposalTaskState, V: Versions> { /// Latest view number that has been proposed for. pub latest_proposed_view: TYPES::Time, @@ -97,11 +98,13 @@ pub struct QuorumProposalTaskState /// since they will be present in the leaf we propose off of. pub formed_upgrade_certificate: Option>, - /// An upgrade certificate that has been decided on, if any. - pub decided_upgrade_certificate: Arc>>>, + /// Lock for a decided upgrade + pub upgrade_lock: UpgradeLock, } -impl> QuorumProposalTaskState { +impl, V: Versions> + QuorumProposalTaskState +{ /// Create an event dependency #[instrument(skip_all, fields(id = self.id, latest_proposed_view = *self.latest_proposed_view), name = "Create event dependency", level = "info")] fn create_event_dependency( @@ -323,7 +326,7 @@ impl> QuorumProposalTaskState> QuorumProposalTaskState> TaskState - for QuorumProposalTaskState +impl, V: Versions> TaskState + for QuorumProposalTaskState { type Event = HotShotEvent; diff --git a/crates/task-impls/src/quorum_proposal_recv/handlers.rs b/crates/task-impls/src/quorum_proposal_recv/handlers.rs index 0b53c96880..9792fa64d6 100644 --- a/crates/task-impls/src/quorum_proposal_recv/handlers.rs +++ b/crates/task-impls/src/quorum_proposal_recv/handlers.rs @@ -35,14 +35,15 @@ use crate::{ broadcast_event, fetch_proposal, update_view, validate_proposal_safety_and_liveness, validate_proposal_view_and_certs, SEND_VIEW_CHANGE_EVENT, }, + quorum_proposal_recv::{UpgradeLock, Versions}, }; /// Update states in the event that the parent state is not found for a given `proposal`. #[instrument(skip_all)] -async fn validate_proposal_liveness>( +async fn validate_proposal_liveness, V: Versions>( proposal: &Proposal>, event_sender: &Sender>>, - task_state: &mut QuorumProposalRecvTaskState, + task_state: &mut QuorumProposalRecvTaskState, ) -> Result<()> { let view_number = proposal.data.view_number(); let mut consensus_write = task_state.consensus.write().await; @@ -124,11 +125,15 @@ async fn validate_proposal_liveness>( +pub(crate) async fn handle_quorum_proposal_recv< + TYPES: NodeType, + I: NodeImplementation, + V: Versions, +>( proposal: &Proposal>, sender: &TYPES::SignatureKey, event_sender: &Sender>>, - task_state: &mut QuorumProposalRecvTaskState, + task_state: &mut QuorumProposalRecvTaskState, ) -> Result<()> { let sender = sender.clone(); let cur_view = task_state.cur_view; @@ -229,7 +234,7 @@ pub(crate) async fn handle_quorum_proposal_recv> { +pub struct QuorumProposalRecvTaskState, V: Versions> { /// Our public key pub public_key: TYPES::SignatureKey, @@ -96,11 +97,13 @@ pub struct QuorumProposalRecvTaskState>>>, + /// Lock for a decided upgrade + pub upgrade_lock: UpgradeLock, } -impl> QuorumProposalRecvTaskState { +impl, V: Versions> + QuorumProposalRecvTaskState +{ /// Cancel all tasks the consensus tasks has spawned before the given view pub async fn cancel_tasks(&mut self, view: TYPES::Time) { let keep = self.spawned_tasks.split_off(&view); @@ -134,8 +137,8 @@ impl> QuorumProposalRecvTaskState< } #[async_trait] -impl> TaskState - for QuorumProposalRecvTaskState +impl, V: Versions> TaskState + for QuorumProposalRecvTaskState { type Event = HotShotEvent; diff --git a/crates/task-impls/src/quorum_vote/handlers.rs b/crates/task-impls/src/quorum_vote/handlers.rs index 862f60ca7c..3a296ad8c7 100644 --- a/crates/task-impls/src/quorum_vote/handlers.rs +++ b/crates/task-impls/src/quorum_vote/handlers.rs @@ -22,6 +22,7 @@ use super::QuorumVoteTaskState; use crate::{ events::HotShotEvent, helpers::{broadcast_event, decide_from_proposal, LeafChainTraversalOutcome}, + quorum_vote::Versions, }; /// Handles the `QuorumProposalValidated` event. @@ -29,10 +30,11 @@ use crate::{ pub(crate) async fn handle_quorum_proposal_validated< TYPES: NodeType, I: NodeImplementation, + V: Versions, >( proposal: &QuorumProposal, sender: &Sender>>, - task_state: &mut QuorumVoteTaskState, + task_state: &mut QuorumVoteTaskState, ) -> Result<()> { let LeafChainTraversalOutcome { new_locked_view_number, @@ -45,13 +47,17 @@ pub(crate) async fn handle_quorum_proposal_validated< } = decide_from_proposal( proposal, OuterConsensus::new(Arc::clone(&task_state.consensus.inner_consensus)), - Arc::clone(&task_state.decided_upgrade_certificate), + Arc::clone(&task_state.upgrade_lock.decided_upgrade_certificate), &task_state.public_key, ) .await; if let Some(cert) = decided_upgrade_cert.clone() { - let mut decided_certificate_lock = task_state.decided_upgrade_certificate.write().await; + let mut decided_certificate_lock = task_state + .upgrade_lock + .decided_upgrade_certificate + .write() + .await; *decided_certificate_lock = Some(cert.clone()); drop(decided_certificate_lock); let _ = sender diff --git a/crates/task-impls/src/quorum_vote/mod.rs b/crates/task-impls/src/quorum_vote/mod.rs index 2cde7fc04e..6c4f8651e3 100644 --- a/crates/task-impls/src/quorum_vote/mod.rs +++ b/crates/task-impls/src/quorum_vote/mod.rs @@ -22,13 +22,12 @@ use hotshot_types::{ consensus::OuterConsensus, data::{Leaf, VidDisperseShare, ViewNumber}, event::Event, - message::Proposal, - simple_certificate::{version, UpgradeCertificate}, + message::{Proposal, UpgradeLock}, simple_vote::{QuorumData, QuorumVote}, traits::{ block_contents::BlockHeader, election::Membership, - node_implementation::{ConsensusTime, NodeImplementation, NodeType}, + node_implementation::{ConsensusTime, NodeImplementation, NodeType, Versions}, signature_key::SignatureKey, storage::Storage, ValidatedState, @@ -63,7 +62,7 @@ enum VoteDependency { } /// Handler for the vote dependency. -pub struct VoteDependencyHandle> { +pub struct VoteDependencyHandle, V: Versions> { /// Public key. pub public_key: TYPES::SignatureKey, /// Private Key. @@ -82,13 +81,15 @@ pub struct VoteDependencyHandle> { pub sender: Sender>>, /// Event receiver. pub receiver: Receiver>>, - /// An upgrade certificate that has been decided on, if any. - pub decided_upgrade_certificate: Arc>>>, + /// Lock for a decided upgrade + pub upgrade_lock: UpgradeLock, /// The node's id pub id: u64, } -impl + 'static> VoteDependencyHandle { +impl + 'static, V: Versions> + VoteDependencyHandle +{ /// Updates the shared consensus state with the new voting data. #[instrument(skip_all, target = "VoteDependencyHandle", fields(id = self.id, view = *self.view_number))] async fn update_shared_state( @@ -130,10 +131,8 @@ impl + 'static> VoteDependencyHand drop(consensus_reader); - let version = version( - self.view_number, - &self.decided_upgrade_certificate.read().await.clone(), - )?; + let version = self.upgrade_lock.version(self.view_number).await?; + let (validated_state, state_delta) = parent_state .validate_and_apply_header( &self.instance_state, @@ -230,8 +229,8 @@ impl + 'static> VoteDependencyHand } } -impl + 'static> HandleDepOutput - for VoteDependencyHandle +impl + 'static, V: Versions> HandleDepOutput + for VoteDependencyHandle { type Output = Vec>>; @@ -353,7 +352,7 @@ impl + 'static> HandleDepOutput /// The state for the quorum vote task. /// /// Contains all of the information for the quorum vote. -pub struct QuorumVoteTaskState> { +pub struct QuorumVoteTaskState, V: Versions> { /// Public key. pub public_key: TYPES::SignatureKey, @@ -390,11 +389,11 @@ pub struct QuorumVoteTaskState> { /// Reference to the storage. pub storage: Arc>, - /// An upgrade certificate that has been decided on, if any. - pub decided_upgrade_certificate: Arc>>>, + /// Lock for a decided upgrade + pub upgrade_lock: UpgradeLock, } -impl> QuorumVoteTaskState { +impl, V: Versions> QuorumVoteTaskState { /// Create an event dependency. #[instrument(skip_all, fields(id = self.id, latest_voted_view = *self.latest_voted_view), name = "Quorum vote create event dependency", level = "error")] fn create_event_dependency( @@ -479,7 +478,7 @@ impl> QuorumVoteTaskState { + VoteDependencyHandle:: { public_key: self.public_key.clone(), private_key: self.private_key.clone(), consensus: OuterConsensus::new(Arc::clone(&self.consensus.inner_consensus)), @@ -489,7 +488,7 @@ impl> QuorumVoteTaskState> QuorumVoteTaskState> TaskState for QuorumVoteTaskState { +impl, V: Versions> TaskState + for QuorumVoteTaskState +{ type Event = HotShotEvent; async fn handle_event( diff --git a/crates/task-impls/src/rewind.rs b/crates/task-impls/src/rewind.rs index b61c1a186e..669b410b52 100644 --- a/crates/task-impls/src/rewind.rs +++ b/crates/task-impls/src/rewind.rs @@ -26,8 +26,8 @@ pub struct RewindTaskState { impl RewindTaskState { /// Handles all events, storing them to the private state - pub fn handle(&mut self, event: Arc>) { - self.events.push(Arc::clone(&event)); + pub fn handle(&mut self, event: &Arc>) { + self.events.push(Arc::clone(event)); } } @@ -41,7 +41,7 @@ impl TaskState for RewindTaskState { _sender: &Sender>, _receiver: &Receiver>, ) -> Result<()> { - self.handle(event); + self.handle(&event); Ok(()) } diff --git a/crates/task-impls/src/transactions.rs b/crates/task-impls/src/transactions.rs index 3aaa24b763..ee7203f491 100644 --- a/crates/task-impls/src/transactions.rs +++ b/crates/task-impls/src/transactions.rs @@ -12,22 +12,20 @@ use std::{ use anyhow::{bail, Result}; use async_broadcast::{Receiver, Sender}; use async_compatibility_layer::art::{async_sleep, async_timeout}; -use async_lock::RwLock; use async_trait::async_trait; use futures::{future::join_all, stream::FuturesUnordered, StreamExt}; use hotshot_builder_api::v0_1::block_info::AvailableBlockInfo; use hotshot_task::task::TaskState; use hotshot_types::{ consensus::OuterConsensus, - constants::MarketplaceVersion, data::{null_block, PackedBundle}, event::{Event, EventType}, - simple_certificate::{version, UpgradeCertificate}, + message::UpgradeLock, traits::{ auction_results_provider::AuctionResultsProvider, block_contents::{precompute_vid_commitment, BuilderFee, EncodeBytes}, election::Membership, - node_implementation::{ConsensusTime, HasUrls, NodeImplementation, NodeType}, + node_implementation::{ConsensusTime, HasUrls, NodeImplementation, NodeType, Versions}, signature_key::{BuilderSignatureKey, SignatureKey}, BlockPayload, }, @@ -76,7 +74,7 @@ pub struct BuilderResponse { } /// Tracks state of a Transaction task -pub struct TransactionTaskState> { +pub struct TransactionTaskState, V: Versions> { /// The state's api pub builder_timeout: Duration, @@ -106,25 +104,22 @@ pub struct TransactionTaskState> { pub instance_state: Arc, /// This state's ID pub id: u64, - /// Decided upgrade certificate - pub decided_upgrade_certificate: Arc>>>, + /// Lock for a decided upgrade + pub upgrade_lock: UpgradeLock, /// auction results provider pub auction_results_provider: Arc, /// fallback builder url pub fallback_builder_url: Url, } -impl> TransactionTaskState { +impl, V: Versions> TransactionTaskState { /// handle view change decide legacy or not pub async fn handle_view_change( &mut self, event_stream: &Sender>>, block_view: TYPES::Time, ) -> Option { - let version = match version( - block_view, - &self.decided_upgrade_certificate.read().await.clone(), - ) { + let version = match self.upgrade_lock.version(block_view).await { Ok(v) => v, Err(e) => { tracing::error!("Failed to calculate version: {:?}", e); @@ -132,7 +127,7 @@ impl> TransactionTaskState> TransactionTaskState>>, block_view: TYPES::Time, ) -> Option { - let version = match hotshot_types::simple_certificate::version( - block_view, - &self - .decided_upgrade_certificate - .read() - .await - .as_ref() - .cloned(), - ) { + let version = match self.upgrade_lock.version(block_view).await { Ok(v) => v, Err(err) => { error!("Upgrade certificate requires unsupported version, refusing to request blocks: {}", err); @@ -167,6 +154,7 @@ impl> TransactionTaskState> TransactionTaskState(self.membership.total_nodes(), version) else { error!("Failed to get null fee"); return None; @@ -250,15 +239,7 @@ impl> TransactionTaskState>>, block_view: TYPES::Time, ) -> Option { - let version = match hotshot_types::simple_certificate::version( - block_view, - &self - .decided_upgrade_certificate - .read() - .await - .as_ref() - .cloned(), - ) { + let version = match self.upgrade_lock.version(block_view).await { Ok(v) => v, Err(err) => { error!("Upgrade certificate requires unsupported version, refusing to request blocks: {}", err); @@ -268,6 +249,7 @@ impl> TransactionTaskState> TransactionTaskState(self.membership.total_nodes(), version) + else { error!("Failed to get null fee"); return None; }; @@ -738,7 +722,9 @@ impl> TransactionTaskState> TaskState for TransactionTaskState { +impl, V: Versions> TaskState + for TransactionTaskState +{ type Event = HotShotEvent; async fn handle_event( diff --git a/crates/task-impls/src/upgrade.rs b/crates/task-impls/src/upgrade.rs index e4463c9076..680c61d82c 100644 --- a/crates/task-impls/src/upgrade.rs +++ b/crates/task-impls/src/upgrade.rs @@ -19,12 +19,12 @@ use hotshot_types::{ }, data::UpgradeProposal, event::{Event, EventType}, - message::Proposal, + message::{Proposal, UpgradeLock}, simple_certificate::UpgradeCertificate, simple_vote::{UpgradeProposalData, UpgradeVote}, traits::{ election::Membership, - node_implementation::{ConsensusTime, NodeImplementation, NodeType}, + node_implementation::{ConsensusTime, NodeImplementation, NodeType, Versions}, signature_key::SignatureKey, }, vote::HasViewNumber, @@ -44,7 +44,7 @@ use crate::{ type VoteCollectorOption = Option>; /// Tracks state of a DA task -pub struct UpgradeTaskState> { +pub struct UpgradeTaskState, V: Versions> { /// Output events to application pub output_event_stream: async_broadcast::Sender>, @@ -93,14 +93,18 @@ pub struct UpgradeTaskState> { /// Unix time in seconds at which we stop voting on an upgrade pub stop_voting_time: u64, - /// Upgrade certificate that has been decided on, if any - pub decided_upgrade_certificate: Arc>>>, + /// Lock for a decided upgrade + pub upgrade_lock: UpgradeLock, } -impl> UpgradeTaskState { +impl, V: Versions> UpgradeTaskState { /// Check if we have decided on an upgrade certificate async fn upgraded(&self) -> bool { - self.decided_upgrade_certificate.read().await.is_some() + self.upgrade_lock + .decided_upgrade_certificate + .read() + .await + .is_some() } /// main task event handler @@ -120,7 +124,7 @@ impl> UpgradeTaskState { if self.upgraded().await { info!( "Already upgraded to {:?}, skip voting.", - TYPES::Upgrade::VERSION + V::Upgrade::VERSION ); return None; } @@ -139,9 +143,9 @@ impl> UpgradeTaskState { } // If the proposal does not match our upgrade target, we immediately exit. - if proposal.data.upgrade_proposal.new_version_hash != TYPES::UPGRADE_HASH - || proposal.data.upgrade_proposal.old_version != TYPES::Base::VERSION - || proposal.data.upgrade_proposal.new_version != TYPES::Upgrade::VERSION + if proposal.data.upgrade_proposal.new_version_hash != V::UPGRADE_HASH + || proposal.data.upgrade_proposal.old_version != V::Base::VERSION + || proposal.data.upgrade_proposal.new_version != V::Upgrade::VERSION { return None; } @@ -284,9 +288,9 @@ impl> UpgradeTaskState { == self.public_key { let upgrade_proposal_data = UpgradeProposalData { - old_version: TYPES::Base::VERSION, - new_version: TYPES::Upgrade::VERSION, - new_version_hash: TYPES::UPGRADE_HASH.to_vec(), + old_version: V::Base::VERSION, + new_version: V::Upgrade::VERSION, + new_version_hash: V::UPGRADE_HASH.to_vec(), // We schedule the upgrade to begin 15 views in the future old_version_last_view: TYPES::Time::new(view + UPGRADE_BEGIN_OFFSET), // and end 20 views in the future @@ -337,7 +341,9 @@ impl> UpgradeTaskState { #[async_trait] /// task state implementation for the upgrade task -impl> TaskState for UpgradeTaskState { +impl, V: Versions> TaskState + for UpgradeTaskState +{ type Event = HotShotEvent; async fn handle_event( diff --git a/crates/testing/src/block_builder/mod.rs b/crates/testing/src/block_builder/mod.rs index 0261a1481f..b6cbffd91b 100644 --- a/crates/testing/src/block_builder/mod.rs +++ b/crates/testing/src/block_builder/mod.rs @@ -85,7 +85,7 @@ pub fn run_builder_source( let mut app: App = App::with_state(source); app.register_module("block_info", builder_api) .expect("Failed to register the builder API"); - async_spawn(app.serve(url, TYPES::Base::instance())) + async_spawn(app.serve(url, hotshot_builder_api::v0_1::Version::instance())) }; let mut handle = Some(start_builder(url.clone(), source.clone())); diff --git a/crates/testing/src/block_builder/simple.rs b/crates/testing/src/block_builder/simple.rs index 54e9c9318b..cd9a320b9b 100644 --- a/crates/testing/src/block_builder/simple.rs +++ b/crates/testing/src/block_builder/simple.rs @@ -252,7 +252,7 @@ impl SimpleBuilderSource { app.register_module::("block_info", builder_api) .expect("Failed to register the builder API"); - async_spawn(app.serve(url, TYPES::Base::instance())); + async_spawn(app.serve(url, hotshot_builder_api::v0_1::Version::instance())); } } diff --git a/crates/testing/src/completion_task.rs b/crates/testing/src/completion_task.rs index 5cdd70bbcf..b5e61fe1ca 100644 --- a/crates/testing/src/completion_task.rs +++ b/crates/testing/src/completion_task.rs @@ -13,7 +13,7 @@ use async_lock::RwLock; use async_std::task::JoinHandle; use hotshot::traits::TestableNodeImplementation; use hotshot_task_impls::helpers::broadcast_event; -use hotshot_types::traits::node_implementation::NodeType; +use hotshot_types::traits::node_implementation::{NodeType, Versions}; use snafu::Snafu; #[cfg(async_executor_impl = "tokio")] use tokio::task::JoinHandle; @@ -27,17 +27,19 @@ use crate::{test_runner::Node, test_task::TestEvent}; pub struct CompletionTaskErr {} /// Completion task state -pub struct CompletionTask> { +pub struct CompletionTask, V: Versions> { pub tx: Sender, pub rx: Receiver, /// handles to the nodes in the test - pub(crate) handles: Arc>>>, + pub(crate) handles: Arc>>>, /// Duration of the task. pub duration: Duration, } -impl> CompletionTask { +impl, V: Versions> + CompletionTask +{ pub fn run(mut self) -> JoinHandle<()> { async_spawn(async move { if async_timeout(self.duration, self.wait_for_shutdown()) diff --git a/crates/testing/src/helpers.rs b/crates/testing/src/helpers.rs index dfb5781d64..09c3b6e87e 100644 --- a/crates/testing/src/helpers.rs +++ b/crates/testing/src/helpers.rs @@ -19,7 +19,7 @@ use hotshot::{ use hotshot_example_types::{ auction_results_provider_types::TestAuctionResultsProvider, block_types::TestTransaction, - node_types::{MemoryImpl, TestTypes}, + node_types::{MemoryImpl, TestTypes, TestVersions}, state_types::{TestInstanceState, TestValidatedState}, storage_types::TestStorage, }; @@ -35,7 +35,7 @@ use hotshot_types::{ consensus_api::ConsensusApi, election::Membership, network::Topic, - node_implementation::{ConsensusTime, NodeType}, + node_implementation::{ConsensusTime, NodeType, Versions}, }, utils::{View, ViewInner}, vid::{vid_scheme, VidCommitment, VidSchemeType}, @@ -56,14 +56,15 @@ pub async fn build_system_handle< Storage = TestStorage, AuctionResultsProvider = TestAuctionResultsProvider, > + TestableNodeImplementation, + V: Versions, >( node_id: u64, ) -> ( - SystemContextHandle, + SystemContextHandle, Sender>>, Receiver>>, ) { - let builder: TestDescription = TestDescription::default_multiple_rounds(); + let builder: TestDescription = TestDescription::default_multiple_rounds(); let launcher = builder.gen_launcher(node_id); @@ -339,7 +340,7 @@ pub fn build_da_certificate( } pub async fn build_vote( - handle: &SystemContextHandle, + handle: &SystemContextHandle, proposal: QuorumProposal, ) -> GeneralConsensusMessage { let view = ViewNumber::new(*proposal.view_number); diff --git a/crates/testing/src/overall_safety_task.rs b/crates/testing/src/overall_safety_task.rs index ce967ad8d2..97ea7fcdf1 100644 --- a/crates/testing/src/overall_safety_task.rs +++ b/crates/testing/src/overall_safety_task.rs @@ -19,7 +19,7 @@ use hotshot_types::{ error::RoundTimedoutState, event::{Event, EventType, LeafChain}, simple_certificate::QuorumCertificate, - traits::node_implementation::{ConsensusTime, NodeType}, + traits::node_implementation::{ConsensusTime, NodeType, Versions}, vid::VidCommitment, }; use snafu::Snafu; @@ -85,9 +85,9 @@ pub enum OverallSafetyTaskErr { } /// Data availability task state -pub struct OverallSafetyTask> { +pub struct OverallSafetyTask, V: Versions> { /// handles - pub handles: Arc>>>, + pub handles: Arc>>>, /// ctx pub ctx: RoundCtx, /// configure properties @@ -98,7 +98,9 @@ pub struct OverallSafetyTask, } -impl> OverallSafetyTask { +impl, V: Versions> + OverallSafetyTask +{ async fn handle_view_failure(&mut self, num_failed_views: usize, view_number: TYPES::Time) { let expected_views_to_fail = &mut self.properties.expected_views_to_fail; @@ -128,8 +130,8 @@ impl> OverallSafetyTask> TestTaskState - for OverallSafetyTask +impl, V: Versions> TestTaskState + for OverallSafetyTask { type Event = Event; diff --git a/crates/testing/src/predicates/upgrade_with_consensus.rs b/crates/testing/src/predicates/upgrade_with_consensus.rs index 5cf8de8a4e..7a63edd583 100644 --- a/crates/testing/src/predicates/upgrade_with_consensus.rs +++ b/crates/testing/src/predicates/upgrade_with_consensus.rs @@ -9,13 +9,13 @@ use std::sync::Arc; use async_trait::async_trait; -use hotshot_example_types::node_types::{MemoryImpl, TestTypes}; +use hotshot_example_types::node_types::{MemoryImpl, TestTypes, TestVersions}; use hotshot_task_impls::consensus::ConsensusTaskState; use hotshot_types::simple_certificate::UpgradeCertificate; use crate::predicates::{Predicate, PredicateResult}; -type ConsensusTaskTestState = ConsensusTaskState; +type ConsensusTaskTestState = ConsensusTaskState; type UpgradeCertCallback = Arc>>) -> bool + Send + Sync>; @@ -34,7 +34,12 @@ impl std::fmt::Debug for UpgradeCertPredicate { #[async_trait] impl Predicate for UpgradeCertPredicate { async fn evaluate(&self, input: &ConsensusTaskTestState) -> PredicateResult { - let upgrade_cert = input.decided_upgrade_certificate.read().await.clone(); + let upgrade_cert = input + .upgrade_lock + .decided_upgrade_certificate + .read() + .await + .clone(); PredicateResult::from((self.check)(upgrade_cert.into())) } diff --git a/crates/testing/src/predicates/upgrade_with_proposal.rs b/crates/testing/src/predicates/upgrade_with_proposal.rs index de39befe9e..8f45414a9a 100644 --- a/crates/testing/src/predicates/upgrade_with_proposal.rs +++ b/crates/testing/src/predicates/upgrade_with_proposal.rs @@ -4,18 +4,16 @@ // You should have received a copy of the MIT License // along with the HotShot repository. If not, see . -#![cfg(feature = "dependency-tasks")] - use std::sync::Arc; use async_trait::async_trait; -use hotshot_example_types::node_types::{MemoryImpl, TestTypes}; +use hotshot_example_types::node_types::{MemoryImpl, TestTypes, TestVersions}; use hotshot_task_impls::quorum_proposal::QuorumProposalTaskState; use hotshot_types::simple_certificate::UpgradeCertificate; use crate::predicates::{Predicate, PredicateResult}; -type QuorumProposalTaskTestState = QuorumProposalTaskState; +type QuorumProposalTaskTestState = QuorumProposalTaskState; type UpgradeCertCallback = Arc>>) -> bool + Send + Sync>; @@ -34,7 +32,12 @@ impl std::fmt::Debug for UpgradeCertPredicate { #[async_trait] impl Predicate for UpgradeCertPredicate { async fn evaluate(&self, input: &QuorumProposalTaskTestState) -> PredicateResult { - let upgrade_cert = input.decided_upgrade_certificate.read().await.clone(); + let upgrade_cert = input + .upgrade_lock + .decided_upgrade_certificate + .read() + .await + .clone(); PredicateResult::from((self.check)(upgrade_cert.into())) } diff --git a/crates/testing/src/predicates/upgrade_with_vote.rs b/crates/testing/src/predicates/upgrade_with_vote.rs index 1d28914f79..20f4102495 100644 --- a/crates/testing/src/predicates/upgrade_with_vote.rs +++ b/crates/testing/src/predicates/upgrade_with_vote.rs @@ -4,17 +4,15 @@ // You should have received a copy of the MIT License // along with the HotShot repository. If not, see . -#![cfg(feature = "dependency-tasks")] - use std::sync::Arc; use async_trait::async_trait; -use hotshot_example_types::node_types::{MemoryImpl, TestTypes}; +use hotshot_example_types::node_types::{MemoryImpl, TestTypes, TestVersions}; use hotshot_task_impls::quorum_vote::QuorumVoteTaskState; use hotshot_types::simple_certificate::UpgradeCertificate; use crate::predicates::{Predicate, PredicateResult}; -type QuorumVoteTaskTestState = QuorumVoteTaskState; +type QuorumVoteTaskTestState = QuorumVoteTaskState; type UpgradeCertCallback = Arc>>) -> bool + Send + Sync>; @@ -30,11 +28,15 @@ impl std::fmt::Debug for UpgradeCertPredicate { } } -#[cfg(feature = "dependency-tasks")] #[async_trait] impl Predicate for UpgradeCertPredicate { async fn evaluate(&self, input: &QuorumVoteTaskTestState) -> PredicateResult { - let upgrade_cert = input.decided_upgrade_certificate.read().await.clone(); + let upgrade_cert = input + .upgrade_lock + .decided_upgrade_certificate + .read() + .await + .clone(); PredicateResult::from((self.check)(upgrade_cert.into())) } diff --git a/crates/testing/src/spinning_task.rs b/crates/testing/src/spinning_task.rs index 72611d44d9..5d94297f60 100644 --- a/crates/testing/src/spinning_task.rs +++ b/crates/testing/src/spinning_task.rs @@ -26,7 +26,7 @@ use hotshot_types::{ simple_certificate::QuorumCertificate, traits::{ network::ConnectedNetwork, - node_implementation::{NodeImplementation, NodeType}, + node_implementation::{NodeImplementation, NodeType, Versions}, }, vote::HasViewNumber, ValidatorConfig, @@ -46,11 +46,11 @@ pub type StateAndBlock = (Vec, Vec); pub struct SpinningTaskErr {} /// Spinning task state -pub struct SpinningTask> { +pub struct SpinningTask, V: Versions> { /// handle to the nodes - pub(crate) handles: Arc>>>, + pub(crate) handles: Arc>>>, /// late start nodes - pub(crate) late_start: HashMap>, + pub(crate) late_start: HashMap>, /// time based changes pub(crate) changes: BTreeMap>, /// most recent view seen by spinning task @@ -68,7 +68,8 @@ impl< TYPES: NodeType, I: TestableNodeImplementation, N: ConnectedNetwork, - > TestTaskState for SpinningTask + V: Versions, + > TestTaskState for SpinningTask where I: TestableNodeImplementation, I: NodeImplementation< @@ -231,7 +232,7 @@ where node_id < config.da_staked_committee_size as u64, ); let context = - TestRunner::::add_node_with_config_and_channels( + TestRunner::::add_node_with_config_and_channels( node_id, network.clone(), (*memberships).clone(), diff --git a/crates/testing/src/test_builder.rs b/crates/testing/src/test_builder.rs index bb82847592..9a654e619e 100644 --- a/crates/testing/src/test_builder.rs +++ b/crates/testing/src/test_builder.rs @@ -17,8 +17,9 @@ use hotshot_example_types::{ storage_types::TestStorage, testable_delay::DelayConfig, }; use hotshot_types::{ - consensus::ConsensusMetricsValue, traits::node_implementation::NodeType, ExecutionType, - HotShotConfig, ValidatorConfig, + consensus::ConsensusMetricsValue, + traits::node_implementation::{NodeType, Versions}, + ExecutionType, HotShotConfig, ValidatorConfig, }; use tide_disco::Url; use vec1::Vec1; @@ -56,7 +57,7 @@ pub struct TimingData { /// metadata describing a test #[derive(Clone)] -pub struct TestDescription> { +pub struct TestDescription, V: Versions> { /// Total number of staked nodes in the test pub num_nodes_with_stake: usize, /// Total number of non-staked nodes in the test @@ -91,30 +92,31 @@ pub struct TestDescription> { /// description of the solver to run pub solver: FakeSolverApiDescription, /// nodes with byzantine behaviour - pub behaviour: Rc Behaviour>, + pub behaviour: Rc Behaviour>, /// Delay config if any to add delays to asynchronous calls pub async_delay_config: DelayConfig, } #[derive(Debug)] -pub enum Behaviour> { - ByzantineTwins(Box>), - Byzantine(Box>), +pub enum Behaviour, V: Versions> { + ByzantineTwins(Box>), + Byzantine(Box>), Standard, } pub async fn create_test_handle< TYPES: NodeType, I: NodeImplementation, + V: Versions, >( - metadata: TestDescription, + metadata: TestDescription, node_id: u64, network: Network, memberships: Memberships, config: HotShotConfig, storage: I::Storage, marketplace_config: MarketplaceConfig, -) -> SystemContextHandle { +) -> SystemContextHandle { let initializer = HotShotInitializer::::from_genesis(TestInstanceState::new( metadata.async_delay_config, )) @@ -170,7 +172,7 @@ pub async fn create_test_handle< .await } Behaviour::Standard => { - let hotshot = SystemContext::::new( + let hotshot = SystemContext::::new( public_key, private_key, node_id, @@ -228,7 +230,7 @@ impl Default for TimingData { } } -impl> TestDescription { +impl, V: Versions> TestDescription { /// the default metadata for a stress test #[must_use] #[allow(clippy::redundant_field_names)] @@ -268,7 +270,7 @@ impl> TestDescription { pub fn default_multiple_rounds() -> Self { let num_nodes_with_stake = 10; let num_nodes_without_stake = 0; - TestDescription:: { + TestDescription:: { // TODO: remove once we have fixed the DHT timeout issue // https://github.com/EspressoSystems/HotShot/issues/2088 num_bootstrap_nodes: num_nodes_with_stake, @@ -290,7 +292,7 @@ impl> TestDescription { ..TimingData::default() }, view_sync_properties: ViewSyncTaskDescription::Threshold(0, num_nodes_with_stake), - ..TestDescription::::default() + ..TestDescription::::default() } } @@ -330,7 +332,9 @@ impl> TestDescription { } } -impl> Default for TestDescription { +impl, V: Versions> Default + for TestDescription +{ /// by default, just a single round #[allow(clippy::redundant_field_names)] fn default() -> Self { @@ -377,8 +381,11 @@ impl> Default for TestDescription< } } -impl, I: TestableNodeImplementation> - TestDescription +impl< + TYPES: NodeType, + I: TestableNodeImplementation, + V: Versions, + > TestDescription where I: NodeImplementation>, { @@ -387,7 +394,7 @@ where /// # Panics /// if some of the the configuration values are zero #[must_use] - pub fn gen_launcher(self, node_id: u64) -> TestLauncher { + pub fn gen_launcher(self, node_id: u64) -> TestLauncher { let TestDescription { num_nodes_with_stake, num_bootstrap_nodes, diff --git a/crates/testing/src/test_launcher.rs b/crates/testing/src/test_launcher.rs index 8db6169c75..7f197fd1ea 100644 --- a/crates/testing/src/test_launcher.rs +++ b/crates/testing/src/test_launcher.rs @@ -14,7 +14,7 @@ use hotshot_example_types::storage_types::TestStorage; use hotshot_types::{ traits::{ network::{AsyncGenerator, ConnectedNetwork}, - node_implementation::NodeType, + node_implementation::{NodeType, Versions}, }, HotShotConfig, }; @@ -40,18 +40,18 @@ pub struct ResourceGenerators> { +pub struct TestLauncher, V: Versions> { /// generator for resources pub resource_generator: ResourceGenerators, /// metadata used for tasks - pub metadata: TestDescription, + pub metadata: TestDescription, } -impl> TestLauncher { +impl, V: Versions> TestLauncher { /// launch the test #[must_use] - pub fn launch>(self) -> TestRunner { - TestRunner:: { + pub fn launch>(self) -> TestRunner { + TestRunner:: { launcher: self, nodes: Vec::new(), solver_server: None, diff --git a/crates/testing/src/test_runner.rs b/crates/testing/src/test_runner.rs index 06b9c87579..372e3ece3b 100644 --- a/crates/testing/src/test_runner.rs +++ b/crates/testing/src/test_runner.rs @@ -37,7 +37,7 @@ use hotshot_types::{ traits::{ election::Membership, network::{ConnectedNetwork, Topic}, - node_implementation::{ConsensusTime, NodeImplementation, NodeType}, + node_implementation::{ConsensusTime, NodeImplementation, NodeType, Versions}, }, HotShotConfig, ValidatorConfig, }; @@ -70,8 +70,9 @@ impl TaskErr for T {} impl< TYPES: NodeType, I: TestableNodeImplementation, + V: Versions, N: ConnectedNetwork, - > TestRunner + > TestRunner where I: TestableNodeImplementation, I: NodeImplementation< @@ -190,7 +191,7 @@ where .await, async_delay_config: self.launcher.metadata.async_delay_config, }; - let spinning_task = TestTask::>::new( + let spinning_task = TestTask::>::new( spinning_task_state, event_rxs.clone(), test_receiver.clone(), @@ -215,7 +216,7 @@ where test_receiver.clone(), ); - let overall_safety_task = TestTask::>::new( + let overall_safety_task = TestTask::>::new( overall_safety_task_state, event_rxs.clone(), test_receiver.clone(), @@ -590,7 +591,7 @@ where validator_config: ValidatorConfig, storage: I::Storage, marketplace_config: MarketplaceConfig, - ) -> Arc> { + ) -> Arc> { // Get key pair for certificate aggregation let private_key = validator_config.private_key.clone(); let public_key = validator_config.public_key.clone(); @@ -627,7 +628,7 @@ where Receiver>>, ), external_channel: (Sender>, Receiver>), - ) -> Arc> { + ) -> Arc> { // Get key pair for certificate aggregation let private_key = validator_config.private_key.clone(); let public_key = validator_config.public_key.clone(); @@ -650,13 +651,13 @@ where } /// a node participating in a test -pub struct Node> { +pub struct Node, V: Versions> { /// The node's unique identifier pub node_id: u64, /// The underlying network belonging to the node pub network: Network, /// The handle to the node's internals - pub handle: SystemContextHandle, + pub handle: SystemContextHandle, } /// This type combines all of the paramters needed to build the context for a node that started @@ -677,10 +678,10 @@ pub struct LateNodeContextParameters> { +pub enum LateNodeContext, V: Versions> { /// The system context that we're passing directly to the node, this means the node is already /// initialized successfully. - InitializedContext(Arc>), + InitializedContext(Arc>), /// The system context that we're passing to the node when it is not yet initialized, so we're /// initializing it based on the received leaf and init parameters. @@ -690,12 +691,12 @@ pub enum LateNodeContext> } /// A yet-to-be-started node that participates in tests -pub struct LateStartNode> { +pub struct LateStartNode, V: Versions> { /// The underlying network belonging to the node pub network: Network, /// Either the context to which we will use to launch HotShot for initialized node when it's /// time, or the parameters that will be used to initialize the node and launch HotShot. - pub context: LateNodeContext, + pub context: LateNodeContext, } /// The runner of a test network @@ -703,16 +704,17 @@ pub struct LateStartNode> pub struct TestRunner< TYPES: NodeType, I: TestableNodeImplementation, + V: Versions, N: ConnectedNetwork, > { /// test launcher, contains a bunch of useful metadata and closures - pub(crate) launcher: TestLauncher, + pub(crate) launcher: TestLauncher, /// nodes in the test - pub(crate) nodes: Vec>, + pub(crate) nodes: Vec>, /// the solver server running in the test pub(crate) solver_server: Option<(Url, JoinHandle<()>)>, /// nodes with a late start - pub(crate) late_start: HashMap>, + pub(crate) late_start: HashMap>, /// the next node unique identifier pub(crate) next_node_id: u64, /// Phantom for N diff --git a/crates/testing/src/test_task.rs b/crates/testing/src/test_task.rs index cba6ae4d9d..0dcc56c068 100644 --- a/crates/testing/src/test_task.rs +++ b/crates/testing/src/test_task.rs @@ -16,8 +16,11 @@ use futures::future::select_all; use hotshot::types::Event; use hotshot_task_impls::{events::HotShotEvent, network::NetworkMessageTaskState}; use hotshot_types::{ - message::{Messages, VersionedMessage}, - traits::{network::ConnectedNetwork, node_implementation::NodeType}, + message::{Messages, UpgradeLock}, + traits::{ + network::ConnectedNetwork, + node_implementation::{NodeType, Versions}, + }, }; #[cfg(async_executor_impl = "tokio")] use tokio::task::{spawn, JoinHandle}; @@ -109,10 +112,12 @@ impl TestTask { /// Add the network task to handle messages and publish events. pub async fn add_network_message_test_task< TYPES: NodeType, + V: Versions, NET: ConnectedNetwork, >( internal_event_stream: Sender>>, external_event_stream: Sender>, + upgrade_lock: UpgradeLock, channel: Arc, ) -> JoinHandle<()> { let net = Arc::clone(&channel); @@ -131,8 +136,7 @@ pub async fn add_network_message_test_task< let mut deserialized_messages = Vec::new(); for msg in msgs { - let deserialized_message = match VersionedMessage::deserialize(&msg, &None) - { + let deserialized_message = match upgrade_lock.deserialize(&msg).await { Ok(deserialized) => deserialized, Err(e) => { tracing::error!("Failed to deserialize message: {}", e); diff --git a/crates/testing/src/txn_task.rs b/crates/testing/src/txn_task.rs index fa2d839352..b2238db02a 100644 --- a/crates/testing/src/txn_task.rs +++ b/crates/testing/src/txn_task.rs @@ -12,7 +12,7 @@ use async_lock::RwLock; #[cfg(async_executor_impl = "async-std")] use async_std::task::JoinHandle; use hotshot::traits::TestableNodeImplementation; -use hotshot_types::traits::node_implementation::NodeType; +use hotshot_types::traits::node_implementation::{NodeType, Versions}; use rand::thread_rng; use snafu::Snafu; #[cfg(async_executor_impl = "tokio")] @@ -28,10 +28,10 @@ use crate::{test_runner::Node, test_task::TestEvent}; pub struct TxnTaskErr {} /// state of task that decides when things are completed -pub struct TxnTask> { +pub struct TxnTask, V: Versions> { // TODO should this be in a rwlock? Or maybe a similar abstraction to the registry is in order /// Handles for all nodes. - pub handles: Arc>>>, + pub handles: Arc>>>, /// Optional index of the next node. pub next_node_idx: Option, /// time to wait between txns @@ -40,7 +40,7 @@ pub struct TxnTask> { pub shutdown_chan: Receiver, } -impl> TxnTask { +impl, V: Versions> TxnTask { pub fn run(mut self) -> JoinHandle<()> { async_spawn(async move { async_sleep(Duration::from_millis(100)).await; diff --git a/crates/testing/src/view_generator.rs b/crates/testing/src/view_generator.rs index 70d858a01a..0c335bbc14 100644 --- a/crates/testing/src/view_generator.rs +++ b/crates/testing/src/view_generator.rs @@ -17,7 +17,7 @@ use futures::{FutureExt, Stream}; use hotshot::types::{BLSPubKey, SignatureKey, SystemContextHandle}; use hotshot_example_types::{ block_types::{TestBlockHeader, TestBlockPayload, TestMetadata, TestTransaction}, - node_types::{MemoryImpl, TestTypes}, + node_types::{MemoryImpl, TestTypes, TestVersions}, state_types::{TestInstanceState, TestValidatedState}, }; use hotshot_types::{ @@ -394,7 +394,7 @@ impl TestView { pub fn create_quorum_vote( &self, - handle: &SystemContextHandle, + handle: &SystemContextHandle, ) -> QuorumVote { QuorumVote::::create_signed_vote( QuorumData { @@ -410,7 +410,7 @@ impl TestView { pub fn create_upgrade_vote( &self, data: UpgradeProposalData, - handle: &SystemContextHandle, + handle: &SystemContextHandle, ) -> UpgradeVote { UpgradeVote::::create_signed_vote( data, @@ -424,7 +424,7 @@ impl TestView { pub fn create_da_vote( &self, data: DaData, - handle: &SystemContextHandle, + handle: &SystemContextHandle, ) -> DaVote { DaVote::create_signed_vote( data, diff --git a/crates/testing/tests/tests_1/block_builder.rs b/crates/testing/tests/tests_1/block_builder.rs index ef68a4b9b7..b7099b62d4 100644 --- a/crates/testing/tests/tests_1/block_builder.rs +++ b/crates/testing/tests/tests_1/block_builder.rs @@ -13,7 +13,7 @@ use async_compatibility_layer::art::async_sleep; use hotshot_builder_api::v0_1::block_info::AvailableBlockData; use hotshot_example_types::{ block_types::{TestBlockPayload, TestMetadata, TestTransaction}, - node_types::TestTypes, + node_types::{TestTypes, TestVersions}, }; use hotshot_orchestrator::config::RandomBuilderConfig; use hotshot_task_impls::builder::{BuilderClient, BuilderClientError}; @@ -21,7 +21,9 @@ use hotshot_testing::block_builder::{ BuilderTask, RandomBuilderImplementation, TestBuilderImplementation, }; use hotshot_types::traits::{ - block_contents::vid_commitment, node_implementation::NodeType, signature_key::SignatureKey, + block_contents::vid_commitment, + node_implementation::{NodeType, Versions}, + signature_key::SignatureKey, BlockPayload, }; use tide_disco::Url; @@ -50,7 +52,7 @@ async fn test_random_block_builder() { let builder_started = Instant::now(); - let client: BuilderClient::Base> = + let client: BuilderClient::Base> = BuilderClient::new(api_url); assert!(client.connect(Duration::from_millis(100)).await); diff --git a/crates/testing/tests/tests_1/consensus_task.rs b/crates/testing/tests/tests_1/consensus_task.rs index 4464e15682..2e02c9a7b9 100644 --- a/crates/testing/tests/tests_1/consensus_task.rs +++ b/crates/testing/tests/tests_1/consensus_task.rs @@ -14,7 +14,7 @@ use futures::StreamExt; use hotshot::tasks::task_state::CreateTaskState; use hotshot_example_types::{ block_types::TestMetadata, - node_types::{MemoryImpl, TestTypes}, + node_types::{MemoryImpl, TestTypes, TestVersions}, state_types::TestInstanceState, }; use hotshot_macros::{run_test, test_scripts}; @@ -37,7 +37,10 @@ use hotshot_testing::{ use hotshot_types::{ data::{null_block, ViewChangeEvidence, ViewNumber}, simple_vote::{TimeoutData, TimeoutVote, ViewSyncFinalizeData}, - traits::{election::Membership, node_implementation::ConsensusTime}, + traits::{ + election::Membership, + node_implementation::{ConsensusTime, Versions}, + }, utils::BuilderCommitment, vote::HasViewNumber, }; @@ -51,13 +54,14 @@ const TIMEOUT: Duration = Duration::from_millis(35); #[cfg_attr(async_executor_impl = "tokio", tokio::test(flavor = "multi_thread"))] #[cfg_attr(async_executor_impl = "async-std", async_std::test)] async fn test_consensus_task() { - use hotshot_types::constants::BaseVersion; use vbs::version::StaticVersionType; async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let handle = build_system_handle::(2).await.0; + 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(); @@ -104,9 +108,9 @@ async fn test_consensus_task() { builder_commitment, TestMetadata, ViewNumber::new(2), - vec1![null_block::builder_fee( + vec1![null_block::builder_fee::( quorum_membership.total_nodes(), - BaseVersion::version() + ::Base::VERSION, ) .unwrap()], None, @@ -129,7 +133,8 @@ async fn test_consensus_task() { ]), ]; - let consensus_state = ConsensusTaskState::::create_from(&handle).await; + let consensus_state = + ConsensusTaskState::::create_from(&handle).await; let mut consensus_script = TaskScript { timeout: TIMEOUT, state: consensus_state, @@ -146,7 +151,9 @@ async fn test_consensus_vote() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let handle = build_system_handle::(2).await.0; + 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(); @@ -183,7 +190,8 @@ async fn test_consensus_vote() { exact(QuorumVoteSend(votes[0].clone())), ])]; - let consensus_state = ConsensusTaskState::::create_from(&handle).await; + let consensus_state = + ConsensusTaskState::::create_from(&handle).await; let mut consensus_script = TaskScript { timeout: TIMEOUT, state: consensus_state, @@ -198,13 +206,15 @@ async fn test_consensus_vote() { #[cfg_attr(async_executor_impl = "async-std", async_std::test)] async fn test_view_sync_finalize_propose() { use hotshot_example_types::{block_types::TestMetadata, state_types::TestValidatedState}; - use hotshot_types::{constants::BaseVersion, data::null_block}; + use hotshot_types::data::null_block; use vbs::version::StaticVersionType; async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let handle = build_system_handle::(4).await.0; + 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(); @@ -296,7 +306,11 @@ async fn test_view_sync_finalize_propose() { builder_commitment, TestMetadata, ViewNumber::new(4), - vec1![null_block::builder_fee(4, BaseVersion::version()).unwrap()], + vec1![null_block::builder_fee::( + 4, + ::Base::VERSION + ) + .unwrap()], None, ), ], @@ -320,7 +334,8 @@ async fn test_view_sync_finalize_propose() { ]), ]; - let consensus_state = ConsensusTaskState::::create_from(&handle).await; + let consensus_state = + ConsensusTaskState::::create_from(&handle).await; let mut consensus_script = TaskScript { timeout: TIMEOUT, state: consensus_state, @@ -339,7 +354,9 @@ async fn test_view_sync_finalize_vote() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let handle = build_system_handle::(5).await.0; + 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(); @@ -415,7 +432,8 @@ async fn test_view_sync_finalize_vote() { ]), ]; - let consensus_state = ConsensusTaskState::::create_from(&handle).await; + let consensus_state = + ConsensusTaskState::::create_from(&handle).await; let mut consensus_script = TaskScript { timeout: TIMEOUT, state: consensus_state, @@ -434,7 +452,9 @@ async fn test_view_sync_finalize_vote_fail_view_number() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let handle = build_system_handle::(5).await.0; + 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(); @@ -517,7 +537,8 @@ async fn test_view_sync_finalize_vote_fail_view_number() { Expectations::from_outputs(vec![]), ]; - let consensus_state = ConsensusTaskState::::create_from(&handle).await; + let consensus_state = + ConsensusTaskState::::create_from(&handle).await; let mut consensus_script = TaskScript { timeout: TIMEOUT, state: consensus_state, @@ -534,7 +555,9 @@ async fn test_vid_disperse_storage_failure() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let handle = build_system_handle::(2).await.0; + let handle = 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; @@ -569,7 +592,8 @@ async fn test_vid_disperse_storage_failure() { quorum_proposal_validated(), ])]; - let consensus_state = ConsensusTaskState::::create_from(&handle).await; + let consensus_state = + ConsensusTaskState::::create_from(&handle).await; let mut consensus_script = TaskScript { timeout: TIMEOUT, state: consensus_state, diff --git a/crates/testing/tests/tests_1/da_task.rs b/crates/testing/tests/tests_1/da_task.rs index 61a2c1671d..34dfc406b6 100644 --- a/crates/testing/tests/tests_1/da_task.rs +++ b/crates/testing/tests/tests_1/da_task.rs @@ -10,7 +10,7 @@ use futures::StreamExt; use hotshot::tasks::task_state::CreateTaskState; use hotshot_example_types::{ block_types::{TestMetadata, TestTransaction}, - node_types::{MemoryImpl, TestTypes}, + node_types::{MemoryImpl, TestTypes, TestVersions}, }; use hotshot_macros::{run_test, test_scripts}; use hotshot_task_impls::{da::DaTaskState, events::HotShotEvent::*}; @@ -22,12 +22,12 @@ use hotshot_testing::{ view_generator::TestViewGenerator, }; use hotshot_types::{ - constants::BaseVersion, data::{null_block, PackedBundle, ViewNumber}, simple_vote::DaData, traits::{ - block_contents::precompute_vid_commitment, election::Membership, - node_implementation::ConsensusTime, + block_contents::precompute_vid_commitment, + election::Membership, + node_implementation::{ConsensusTime, Versions}, }, }; use vbs::version::StaticVersionType; @@ -38,7 +38,9 @@ async fn test_da_task() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let handle = build_system_handle::(2).await.0; + 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(); @@ -85,9 +87,9 @@ async fn test_da_task() { encoded_transactions, TestMetadata, ViewNumber::new(2), - vec1::vec1![null_block::builder_fee( + vec1::vec1![null_block::builder_fee::( quorum_membership.total_nodes(), - BaseVersion::version() + ::Base::VERSION ) .unwrap()], Some(precompute), @@ -122,7 +124,9 @@ async fn test_da_task_storage_failure() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let handle = build_system_handle::(2).await.0; + let handle = 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; @@ -172,9 +176,9 @@ async fn test_da_task_storage_failure() { encoded_transactions, TestMetadata, ViewNumber::new(2), - vec1::vec1![null_block::builder_fee( + vec1::vec1![null_block::builder_fee::( quorum_membership.total_nodes(), - BaseVersion::version() + ::Base::VERSION ) .unwrap()], Some(precompute), diff --git a/crates/testing/tests/tests_1/libp2p.rs b/crates/testing/tests/tests_1/libp2p.rs index 30239d38bd..32f0878999 100644 --- a/crates/testing/tests/tests_1/libp2p.rs +++ b/crates/testing/tests/tests_1/libp2p.rs @@ -6,7 +6,7 @@ use std::time::Duration; -use hotshot_example_types::node_types::{Libp2pImpl, TestTypes}; +use hotshot_example_types::node_types::{Libp2pImpl, TestTypes, TestVersions}; use hotshot_testing::{ block_builder::SimpleBuilderImplementation, completion_task::{CompletionTaskDescription, TimeBasedCompletionTaskDescription}, @@ -23,7 +23,7 @@ use tracing::instrument; async fn libp2p_network() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let metadata: TestDescription = TestDescription { + let metadata: TestDescription = TestDescription { overall_safety_properties: OverallSafetyPropertiesDescription { check_leaf: true, ..Default::default() @@ -54,7 +54,7 @@ async fn libp2p_network() { async fn libp2p_network_failures_2() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let mut metadata: TestDescription = TestDescription { + let mut metadata: TestDescription = TestDescription { overall_safety_properties: OverallSafetyPropertiesDescription { check_leaf: true, ..Default::default() @@ -102,7 +102,8 @@ async fn libp2p_network_failures_2() { async fn test_stress_libp2p_network() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let metadata: TestDescription = TestDescription::default_stress(); + let metadata: TestDescription = + TestDescription::default_stress(); metadata .gen_launcher(0) .launch() diff --git a/crates/testing/tests/tests_1/network_task.rs b/crates/testing/tests/tests_1/network_task.rs index 858e9446ce..a3b3245533 100644 --- a/crates/testing/tests/tests_1/network_task.rs +++ b/crates/testing/tests/tests_1/network_task.rs @@ -10,7 +10,7 @@ use async_broadcast::Sender; use async_compatibility_layer::art::async_timeout; use async_lock::RwLock; use hotshot::traits::implementations::MemoryNetwork; -use hotshot_example_types::node_types::{MemoryImpl, TestTypes}; +use hotshot_example_types::node_types::{MemoryImpl, TestTypes, TestVersions}; use hotshot_task::task::{ConsensusTaskRegistry, Task}; use hotshot_task_impls::{ events::HotShotEvent, @@ -22,6 +22,7 @@ use hotshot_testing::{ }; use hotshot_types::{ data::ViewNumber, + message::UpgradeLock, traits::{ election::Membership, node_implementation::{ConsensusTime, NodeType}, @@ -41,8 +42,9 @@ async fn test_network_task() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let builder: TestDescription = + let builder: TestDescription = TestDescription::default_multiple_rounds(); + let upgrade_lock = UpgradeLock::::new(); let node_id = 1; let launcher = builder.gen_launcher(node_id); @@ -60,13 +62,13 @@ async fn test_network_task() { Topic::Global, config.fixed_leader_for_gpuvid, ); - let network_state: NetworkEventTaskState, _> = + let network_state: NetworkEventTaskState, _> = NetworkEventTaskState { channel: network.clone(), view: ViewNumber::new(0), membership: membership.clone(), filter: network::quorum_filter, - decided_upgrade_certificate: None, + upgrade_lock: upgrade_lock.clone(), storage, }; let (tx, rx) = async_broadcast::broadcast(10); @@ -83,6 +85,7 @@ async fn test_network_task() { add_network_message_test_task( out_tx_internal.clone(), out_tx_external.clone(), + upgrade_lock, network.clone(), ) .await; @@ -114,7 +117,7 @@ async fn test_network_storage_fail() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let builder: TestDescription = + let builder: TestDescription = TestDescription::default_multiple_rounds(); let node_id = 1; @@ -127,6 +130,7 @@ 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 upgrade_lock = UpgradeLock::::new(); let membership = ::Membership::create_election( known_nodes_with_stake.clone(), @@ -134,13 +138,13 @@ async fn test_network_storage_fail() { Topic::Global, config.fixed_leader_for_gpuvid, ); - let network_state: NetworkEventTaskState, _> = + let network_state: NetworkEventTaskState, _> = NetworkEventTaskState { channel: network.clone(), view: ViewNumber::new(0), membership: membership.clone(), filter: network::quorum_filter, - decided_upgrade_certificate: None, + upgrade_lock: upgrade_lock.clone(), storage, }; let (tx, rx) = async_broadcast::broadcast(10); @@ -158,6 +162,7 @@ async fn test_network_storage_fail() { add_network_message_test_task( out_tx_internal.clone(), out_tx_external.clone(), + upgrade_lock, network.clone(), ) .await; 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 b737d90927..d0d727b370 100644 --- a/crates/testing/tests/tests_1/quorum_proposal_recv_task.rs +++ b/crates/testing/tests/tests_1/quorum_proposal_recv_task.rs @@ -11,7 +11,7 @@ use futures::StreamExt; use hotshot::tasks::task_state::CreateTaskState; use hotshot_example_types::{ - node_types::{MemoryImpl, TestTypes}, + node_types::{MemoryImpl, TestTypes, TestVersions}, state_types::TestValidatedState, }; use hotshot_macros::{run_test, test_scripts}; @@ -46,7 +46,9 @@ async fn test_quorum_proposal_recv_task() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let handle = build_system_handle::(2).await.0; + 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 consensus = handle.hotshot.consensus(); @@ -104,7 +106,9 @@ async fn test_quorum_proposal_recv_task() { exact(ViewChange(ViewNumber::new(2))), ])]; - let state = QuorumProposalRecvTaskState::::create_from(&handle).await; + let state = + QuorumProposalRecvTaskState::::create_from(&handle) + .await; let mut script = TaskScript { timeout: Duration::from_millis(35), state, @@ -132,7 +136,9 @@ async fn test_quorum_proposal_recv_task_liveness_check() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let handle = build_system_handle::(4).await.0; + let handle = build_system_handle::(4) + .await + .0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); let da_membership = handle.hotshot.memberships.da_membership.clone(); let consensus = handle.hotshot.consensus(); @@ -208,7 +214,9 @@ async fn test_quorum_proposal_recv_task_liveness_check() { exact(HighQcUpdated(proposals[2].data.justify_qc.clone())), ])]; - let state = QuorumProposalRecvTaskState::::create_from(&handle).await; + let state = + QuorumProposalRecvTaskState::::create_from(&handle) + .await; let mut script = TaskScript { timeout: Duration::from_millis(35), state, diff --git a/crates/testing/tests/tests_1/quorum_proposal_task.rs b/crates/testing/tests/tests_1/quorum_proposal_task.rs index eda6c459c8..61372110a8 100644 --- a/crates/testing/tests/tests_1/quorum_proposal_task.rs +++ b/crates/testing/tests/tests_1/quorum_proposal_task.rs @@ -12,7 +12,7 @@ use futures::StreamExt; use hotshot::{tasks::task_state::CreateTaskState, traits::ValidatedState}; use hotshot_example_types::{ block_types::TestMetadata, - node_types::{MemoryImpl, TestTypes}, + node_types::{MemoryImpl, TestTypes, TestVersions}, state_types::TestValidatedState, }; use hotshot_macros::{run_test, test_scripts}; @@ -29,7 +29,10 @@ use hotshot_testing::{ use hotshot_types::{ data::{null_block, Leaf, ViewChangeEvidence, ViewNumber}, simple_vote::{TimeoutData, ViewSyncFinalizeData}, - traits::{election::Membership, node_implementation::ConsensusTime}, + traits::{ + election::Membership, + node_implementation::{ConsensusTime, Versions}, + }, utils::BuilderCommitment, vote::HasViewNumber, }; @@ -43,14 +46,13 @@ const TIMEOUT: Duration = Duration::from_millis(35); #[cfg_attr(async_executor_impl = "async-std", async_std::test)] async fn test_quorum_proposal_task_quorum_proposal_view_1() { use hotshot_testing::script::{Expectations, TaskScript}; - use hotshot_types::constants::BaseVersion; use vbs::version::StaticVersionType; async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); let node_id = 1; - let handle = build_system_handle::(node_id) + let handle = build_system_handle::(node_id) .await .0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); @@ -83,8 +85,11 @@ async fn test_quorum_proposal_task_quorum_proposal_view_1() { // We must send the genesis cert here to initialize hotshot successfully. let genesis_cert = proposals[0].data.justify_qc.clone(); let builder_commitment = BuilderCommitment::from_raw_digest(sha2::Sha256::new().finalize()); - let builder_fee = - null_block::builder_fee(quorum_membership.total_nodes(), BaseVersion::version()).unwrap(); + let builder_fee = null_block::builder_fee::( + quorum_membership.total_nodes(), + ::Base::VERSION, + ) + .unwrap(); drop(consensus_writer); let inputs = vec![ @@ -119,7 +124,7 @@ async fn test_quorum_proposal_task_quorum_proposal_view_1() { ]; let quorum_proposal_task_state = - QuorumProposalTaskState::::create_from(&handle).await; + QuorumProposalTaskState::::create_from(&handle).await; let mut script = TaskScript { timeout: TIMEOUT, @@ -133,14 +138,13 @@ async fn test_quorum_proposal_task_quorum_proposal_view_1() { #[cfg_attr(async_executor_impl = "tokio", tokio::test(flavor = "multi_thread"))] #[cfg_attr(async_executor_impl = "async-std", async_std::test)] async fn test_quorum_proposal_task_quorum_proposal_view_gt_1() { - use hotshot_types::constants::BaseVersion; use vbs::version::StaticVersionType; async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); let node_id = 3; - let handle = build_system_handle::(node_id) + let handle = build_system_handle::(node_id) .await .0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); @@ -187,8 +191,11 @@ async fn test_quorum_proposal_task_quorum_proposal_view_gt_1() { drop(consensus_writer); let builder_commitment = BuilderCommitment::from_raw_digest(sha2::Sha256::new().finalize()); - let builder_fee = - null_block::builder_fee(quorum_membership.total_nodes(), BaseVersion::version()).unwrap(); + let builder_fee = null_block::builder_fee::( + quorum_membership.total_nodes(), + ::Base::VERSION, + ) + .unwrap(); let inputs = vec![ random![ @@ -302,7 +309,7 @@ async fn test_quorum_proposal_task_quorum_proposal_view_gt_1() { ]; let quorum_proposal_task_state = - QuorumProposalTaskState::::create_from(&handle).await; + QuorumProposalTaskState::::create_from(&handle).await; let mut script = TaskScript { timeout: TIMEOUT, @@ -317,14 +324,13 @@ async fn test_quorum_proposal_task_quorum_proposal_view_gt_1() { #[cfg_attr(async_executor_impl = "tokio", tokio::test(flavor = "multi_thread"))] #[cfg_attr(async_executor_impl = "async-std", async_std::test)] async fn test_quorum_proposal_task_qc_timeout() { - use hotshot_types::constants::BaseVersion; use vbs::version::StaticVersionType; async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); let node_id = 3; - let handle = build_system_handle::(node_id) + let handle = build_system_handle::(node_id) .await .0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); @@ -372,10 +378,11 @@ async fn test_quorum_proposal_task_qc_timeout() { builder_commitment, TestMetadata, ViewNumber::new(3), - vec1![ - null_block::builder_fee(quorum_membership.total_nodes(), BaseVersion::version()) - .unwrap() - ], + vec1![null_block::builder_fee::( + quorum_membership.total_nodes(), + ::Base::VERSION + ) + .unwrap()], None, ), VidDisperseSend(vid_dispersals[2].clone(), handle.public_key()), @@ -388,7 +395,7 @@ async fn test_quorum_proposal_task_qc_timeout() { let expectations = vec![Expectations::from_outputs(vec![quorum_proposal_send()])]; let quorum_proposal_task_state = - QuorumProposalTaskState::::create_from(&handle).await; + QuorumProposalTaskState::::create_from(&handle).await; let mut script = TaskScript { timeout: TIMEOUT, @@ -403,14 +410,14 @@ async fn test_quorum_proposal_task_qc_timeout() { #[cfg_attr(async_executor_impl = "async-std", async_std::test)] async fn test_quorum_proposal_task_view_sync() { use hotshot_example_types::block_types::TestMetadata; - use hotshot_types::{constants::BaseVersion, data::null_block}; + use hotshot_types::data::null_block; use vbs::version::StaticVersionType; async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); let node_id = 2; - let handle = build_system_handle::(node_id) + let handle = build_system_handle::(node_id) .await .0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); @@ -460,10 +467,11 @@ async fn test_quorum_proposal_task_view_sync() { builder_commitment, TestMetadata, ViewNumber::new(2), - vec1![ - null_block::builder_fee(quorum_membership.total_nodes(), BaseVersion::version()) - .unwrap() - ], + vec1![null_block::builder_fee::( + quorum_membership.total_nodes(), + ::Base::VERSION + ) + .unwrap()], None, ), VidDisperseSend(vid_dispersals[1].clone(), handle.public_key()), @@ -476,7 +484,7 @@ async fn test_quorum_proposal_task_view_sync() { let expectations = vec![Expectations::from_outputs(vec![quorum_proposal_send()])]; let quorum_proposal_task_state = - QuorumProposalTaskState::::create_from(&handle).await; + QuorumProposalTaskState::::create_from(&handle).await; let mut script = TaskScript { timeout: TIMEOUT, @@ -490,14 +498,13 @@ async fn test_quorum_proposal_task_view_sync() { #[cfg_attr(async_executor_impl = "tokio", tokio::test(flavor = "multi_thread"))] #[cfg_attr(async_executor_impl = "async-std", async_std::test)] async fn test_quorum_proposal_task_liveness_check() { - use hotshot_types::constants::BaseVersion; use vbs::version::StaticVersionType; async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); let node_id = 3; - let handle = build_system_handle::(node_id) + let handle = build_system_handle::(node_id) .await .0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); @@ -533,8 +540,11 @@ async fn test_quorum_proposal_task_liveness_check() { drop(consensus_writer); let builder_commitment = BuilderCommitment::from_raw_digest(sha2::Sha256::new().finalize()); - let builder_fee = - null_block::builder_fee(quorum_membership.total_nodes(), BaseVersion::version()).unwrap(); + let builder_fee = null_block::builder_fee::( + quorum_membership.total_nodes(), + ::Base::VERSION, + ) + .unwrap(); // We need to handle the views where we aren't the leader to ensure that the states are // updated properly. @@ -657,7 +667,7 @@ async fn test_quorum_proposal_task_liveness_check() { ]; let quorum_proposal_task_state = - QuorumProposalTaskState::::create_from(&handle).await; + QuorumProposalTaskState::::create_from(&handle).await; let mut script = TaskScript { timeout: TIMEOUT, @@ -674,7 +684,9 @@ async fn test_quorum_proposal_task_with_incomplete_events() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let handle = build_system_handle::(2).await.0; + 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(); @@ -700,7 +712,7 @@ async fn test_quorum_proposal_task_with_incomplete_events() { let expectations = vec![Expectations::from_outputs(vec![])]; let quorum_proposal_task_state = - QuorumProposalTaskState::::create_from(&handle).await; + QuorumProposalTaskState::::create_from(&handle).await; let mut script = TaskScript { timeout: TIMEOUT, diff --git a/crates/testing/tests/tests_1/quorum_vote_task.rs b/crates/testing/tests/tests_1/quorum_vote_task.rs index b9643c3073..83019caad4 100644 --- a/crates/testing/tests/tests_1/quorum_vote_task.rs +++ b/crates/testing/tests/tests_1/quorum_vote_task.rs @@ -11,7 +11,7 @@ use std::time::Duration; use futures::StreamExt; use hotshot::tasks::task_state::CreateTaskState; -use hotshot_example_types::node_types::{MemoryImpl, TestTypes}; +use hotshot_example_types::node_types::{MemoryImpl, TestTypes, TestVersions}; use hotshot_macros::{run_test, test_scripts}; use hotshot_testing::{ all_predicates, @@ -40,7 +40,9 @@ async fn test_quorum_vote_task_success() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let handle = build_system_handle::(2).await.0; + 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(); @@ -84,7 +86,7 @@ async fn test_quorum_vote_task_success() { ])]; let quorum_vote_state = - QuorumVoteTaskState::::create_from(&handle).await; + QuorumVoteTaskState::::create_from(&handle).await; let mut script = TaskScript { timeout: TIMEOUT, @@ -106,7 +108,9 @@ async fn test_quorum_vote_task_miss_dependency() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let handle = build_system_handle::(2).await.0; + 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(); @@ -169,7 +173,7 @@ async fn test_quorum_vote_task_miss_dependency() { ]; let quorum_vote_state = - QuorumVoteTaskState::::create_from(&handle).await; + QuorumVoteTaskState::::create_from(&handle).await; let mut script = TaskScript { timeout: TIMEOUT, @@ -191,7 +195,9 @@ async fn test_quorum_vote_task_incorrect_dependency() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let handle = build_system_handle::(2).await.0; + 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(); @@ -221,7 +227,7 @@ async fn test_quorum_vote_task_incorrect_dependency() { ])]; let quorum_vote_state = - QuorumVoteTaskState::::create_from(&handle).await; + QuorumVoteTaskState::::create_from(&handle).await; let mut script = TaskScript { timeout: TIMEOUT, diff --git a/crates/testing/tests/tests_1/test_success.rs b/crates/testing/tests/tests_1/test_success.rs index 07c1f72697..ef955e13d7 100644 --- a/crates/testing/tests/tests_1/test_success.rs +++ b/crates/testing/tests/tests_1/test_success.rs @@ -4,10 +4,11 @@ // You should have received a copy of the MIT License // along with the HotShot repository. If not, see . -use std::time::Duration; +use std::{rc::Rc, time::Duration}; +use hotshot::tasks::{BadProposalViewDos, DoubleProposeVote}; use hotshot_example_types::{ - node_types::{Libp2pImpl, MemoryImpl, PushCdnImpl, TestConsecutiveLeaderTypes}, + node_types::{Libp2pImpl, MemoryImpl, PushCdnImpl, TestConsecutiveLeaderTypes, TestVersions}, state_types::TestTypes, testable_delay::{DelayConfig, DelayOptions, DelaySettings, SupportedTraitTypesForAsyncDelay}, }; @@ -15,19 +16,15 @@ use hotshot_macros::cross_tests; use hotshot_testing::{ block_builder::SimpleBuilderImplementation, completion_task::{CompletionTaskDescription, TimeBasedCompletionTaskDescription}, - test_builder::TestDescription, + test_builder::{Behaviour, TestDescription}, view_sync_task::ViewSyncTaskDescription, }; -use { - hotshot::tasks::{BadProposalViewDos, DoubleProposeVote}, - hotshot_testing::test_builder::Behaviour, - std::rc::Rc, -}; cross_tests!( TestName: test_success, Impls: [MemoryImpl, Libp2pImpl, PushCdnImpl], Types: [TestTypes], + Versions: [TestVersions], Ignore: false, Metadata: { TestDescription { @@ -46,6 +43,7 @@ cross_tests!( TestName: test_success_with_async_delay, Impls: [MemoryImpl, Libp2pImpl, PushCdnImpl], Types: [TestTypes], + Versions: [TestVersions], Ignore: false, Metadata: { let mut metadata = TestDescription { @@ -77,6 +75,7 @@ cross_tests!( TestName: test_success_with_async_delay_2, Impls: [MemoryImpl, Libp2pImpl, PushCdnImpl], Types: [TestTypes], + Versions: [TestVersions], Ignore: false, Metadata: { let mut metadata = TestDescription { @@ -116,6 +115,7 @@ cross_tests!( TestName: double_propose_vote, Impls: [MemoryImpl], Types: [TestTypes], + Versions: [TestVersions], Ignore: false, Metadata: { let behaviour = Rc::new(|node_id| { match node_id { @@ -141,6 +141,7 @@ cross_tests!( TestName: multiple_bad_proposals, Impls: [MemoryImpl], Types: [TestTypes], + Versions: [TestVersions], Ignore: false, Metadata: { let behaviour = Rc::new(|node_id| { match node_id { @@ -169,6 +170,7 @@ cross_tests!( TestName: test_with_double_leader_no_failures, Impls: [MemoryImpl, Libp2pImpl, PushCdnImpl], Types: [TestConsecutiveLeaderTypes], + Versions: [TestVersions], Ignore: false, Metadata: { let mut metadata = TestDescription::default_more_nodes(); diff --git a/crates/testing/tests/tests_1/test_with_failures_2.rs b/crates/testing/tests/tests_1/test_with_failures_2.rs index 661f3aa3d0..54d3e5193f 100644 --- a/crates/testing/tests/tests_1/test_with_failures_2.rs +++ b/crates/testing/tests/tests_1/test_with_failures_2.rs @@ -12,7 +12,7 @@ use std::{ }; use hotshot_example_types::{ - node_types::{Libp2pImpl, MemoryImpl, PushCdnImpl, TestConsecutiveLeaderTypes}, + node_types::{Libp2pImpl, MemoryImpl, PushCdnImpl, TestConsecutiveLeaderTypes, TestVersions}, state_types::TestTypes, }; use hotshot_macros::cross_tests; @@ -31,6 +31,7 @@ cross_tests!( TestName: test_with_failures_2, Impls: [MemoryImpl, Libp2pImpl, PushCdnImpl], Types: [TestTypes], + Versions: [TestVersions], Ignore: false, Metadata: { let mut metadata = TestDescription::default_more_nodes(); @@ -72,6 +73,7 @@ cross_tests!( TestName: dishonest_leader, Impls: [MemoryImpl], Types: [TestTypes], + Versions: [TestVersions], Ignore: false, Metadata: { let behaviour = Rc::new(|node_id| { @@ -113,6 +115,7 @@ cross_tests!( TestName: test_with_double_leader_failures, Impls: [MemoryImpl, Libp2pImpl, PushCdnImpl], Types: [TestConsecutiveLeaderTypes], + Versions: [TestVersions], Ignore: false, Metadata: { let mut metadata = TestDescription::default_more_nodes(); diff --git a/crates/testing/tests/tests_1/transaction_task.rs b/crates/testing/tests/tests_1/transaction_task.rs index 14ffd17f61..24764f6a3d 100644 --- a/crates/testing/tests/tests_1/transaction_task.rs +++ b/crates/testing/tests/tests_1/transaction_task.rs @@ -1,18 +1,18 @@ use hotshot::tasks::task_state::CreateTaskState; use hotshot_example_types::{ block_types::TestMetadata, - node_types::{MemoryImpl, TestConsecutiveLeaderTypes}, + node_types::{MemoryImpl, TestConsecutiveLeaderTypes, TestVersions}, }; use hotshot_task_impls::{ events::HotShotEvent, harness::run_harness, transactions::TransactionTaskState, }; use hotshot_testing::helpers::build_system_handle; use hotshot_types::{ - constants::BaseVersion, data::{null_block, PackedBundle, ViewNumber}, traits::{ - block_contents::precompute_vid_commitment, election::Membership, - node_implementation::ConsensusTime, + block_contents::precompute_vid_commitment, + election::Membership, + node_implementation::{ConsensusTime, Versions}, }, }; use vbs::version::StaticVersionType; @@ -26,9 +26,10 @@ async fn test_transaction_task_leader_two_views_in_a_row() { // Build the API for node 2. let node_id = 2; - let handle = build_system_handle::(node_id) - .await - .0; + let handle = + build_system_handle::(node_id) + .await + .0; let mut input = Vec::new(); let mut output = Vec::new(); @@ -45,11 +46,13 @@ async fn test_transaction_task_leader_two_views_in_a_row() { vec![].into(), TestMetadata, current_view, - vec1::vec1![null_block::builder_fee( - quorum_membership.total_nodes(), - BaseVersion::version() - ) - .unwrap()], + vec1::vec1![ + null_block::builder_fee::( + quorum_membership.total_nodes(), + ::Base::VERSION + ) + .unwrap() + ], Some(precompute_data.clone()), None, ); @@ -60,6 +63,9 @@ async fn test_transaction_task_leader_two_views_in_a_row() { output.push(HotShotEvent::BlockRecv(exp_packed_bundle)); let transaction_state = - TransactionTaskState::::create_from(&handle).await; + TransactionTaskState::::create_from( + &handle, + ) + .await; run_harness(input, output, transaction_state, false).await; } diff --git a/crates/testing/tests/tests_1/upgrade_task_with_consensus.rs b/crates/testing/tests/tests_1/upgrade_task_with_consensus.rs index a3784da1cb..d196356455 100644 --- a/crates/testing/tests/tests_1/upgrade_task_with_consensus.rs +++ b/crates/testing/tests/tests_1/upgrade_task_with_consensus.rs @@ -15,7 +15,7 @@ use futures::StreamExt; use hotshot::{tasks::task_state::CreateTaskState, types::SystemContextHandle}; use hotshot_example_types::{ block_types::{TestMetadata, TestTransaction}, - node_types::{MemoryImpl, TestTypes}, + node_types::{MemoryImpl, TestTypes, TestVersions}, state_types::TestInstanceState, }; use hotshot_macros::test_scripts; @@ -29,10 +29,12 @@ use hotshot_testing::{ view_generator::TestViewGenerator, }; use hotshot_types::{ - constants::BaseVersion, data::{null_block, ViewNumber}, simple_vote::UpgradeProposalData, - traits::{election::Membership, node_implementation::ConsensusTime}, + traits::{ + election::Membership, + node_implementation::{ConsensusTime, Versions}, + }, vote::HasViewNumber, }; use vbs::version::{StaticVersionType, Version}; @@ -47,7 +49,9 @@ async fn test_upgrade_task_vote() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let handle = build_system_handle::(1).await.0; + 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(); @@ -180,7 +184,8 @@ async fn test_upgrade_task_vote() { }, ]; - let consensus_state = ConsensusTaskState::::create_from(&handle).await; + let consensus_state = + ConsensusTaskState::::create_from(&handle).await; let mut consensus_script = TaskScript { timeout: Duration::from_millis(65), state: consensus_state, @@ -204,7 +209,9 @@ async fn test_upgrade_task_propose() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let handle = build_system_handle::(3).await.0; + let handle = build_system_handle::(3) + .await + .0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); let da_membership = handle.hotshot.memberships.da_membership.clone(); @@ -255,8 +262,10 @@ async fn test_upgrade_task_propose() { .iter() .map(|h| views[2].create_upgrade_vote(upgrade_data.clone(), &h.0)); - let consensus_state = ConsensusTaskState::::create_from(&handle).await; - let upgrade_state = UpgradeTaskState::::create_from(&handle).await; + let consensus_state = + ConsensusTaskState::::create_from(&handle).await; + let upgrade_state = + UpgradeTaskState::::create_from(&handle).await; let upgrade_vote_recvs: Vec<_> = upgrade_votes.map(UpgradeVoteRecv).collect(); @@ -279,9 +288,9 @@ async fn test_upgrade_task_propose() { proposals[2].data.block_header.builder_commitment.clone(), TestMetadata, ViewNumber::new(3), - vec1![null_block::builder_fee( + vec1![null_block::builder_fee::( quorum_membership.total_nodes(), - BaseVersion::version() + ::Base::VERSION ) .unwrap()], None, @@ -366,15 +375,20 @@ async fn test_upgrade_task_blank_blocks() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let handle = build_system_handle::(6).await.0; + 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 }; - let builder_fee = - null_block::builder_fee(quorum_membership.total_nodes(), BaseVersion::version()).unwrap(); + let builder_fee = null_block::builder_fee::( + quorum_membership.total_nodes(), + ::Base::VERSION, + ) + .unwrap(); let upgrade_data: UpgradeProposalData = UpgradeProposalData { old_version, @@ -452,8 +466,10 @@ async fn test_upgrade_task_blank_blocks() { views.push(view.clone()); } - let consensus_state = ConsensusTaskState::::create_from(&handle).await; - let upgrade_state = UpgradeTaskState::::create_from(&handle).await; + let consensus_state = + ConsensusTaskState::::create_from(&handle).await; + let upgrade_state = + UpgradeTaskState::::create_from(&handle).await; let inputs = vec![ vec![ 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 07099f5182..ce30a6f1fd 100644 --- a/crates/testing/tests/tests_1/upgrade_task_with_proposal.rs +++ b/crates/testing/tests/tests_1/upgrade_task_with_proposal.rs @@ -14,7 +14,7 @@ use futures::StreamExt; use hotshot::{tasks::task_state::CreateTaskState, types::SystemContextHandle}; use hotshot_example_types::{ block_types::{TestMetadata, TestTransaction}, - node_types::{MemoryImpl, TestTypes}, + node_types::{MemoryImpl, TestTypes, TestVersions}, state_types::{TestInstanceState, TestValidatedState}, }; use hotshot_macros::{run_test, test_scripts}; @@ -32,10 +32,13 @@ use hotshot_testing::{ view_generator::TestViewGenerator, }; use hotshot_types::{ - constants::BaseVersion, data::{null_block, Leaf, ViewNumber}, simple_vote::UpgradeProposalData, - traits::{election::Membership, node_implementation::ConsensusTime, ValidatedState}, + traits::{ + election::Membership, + node_implementation::{ConsensusTime, Versions}, + ValidatedState, + }, utils::BuilderCommitment, vote::HasViewNumber, }; @@ -59,7 +62,9 @@ async fn test_upgrade_task_with_proposal() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let handle = build_system_handle::(3).await.0; + let handle = build_system_handle::(3) + .await + .0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); let da_membership = handle.hotshot.memberships.da_membership.clone(); @@ -133,15 +138,19 @@ async fn test_upgrade_task_with_proposal() { let genesis_cert = proposals[0].data.justify_qc.clone(); let genesis_leaf = Leaf::genesis(&validated_state, &*handle.hotshot.instance_state()).await; let builder_commitment = BuilderCommitment::from_raw_digest(sha2::Sha256::new().finalize()); - let builder_fee = - null_block::builder_fee(quorum_membership.total_nodes(), BaseVersion::version()).unwrap(); + let builder_fee = null_block::builder_fee::( + quorum_membership.total_nodes(), + ::Base::VERSION, + ) + .unwrap(); let upgrade_votes = other_handles .iter() .map(|h| views[2].create_upgrade_vote(upgrade_data.clone(), &h.0)); let proposal_state = - QuorumProposalTaskState::::create_from(&handle).await; - let upgrade_state = UpgradeTaskState::::create_from(&handle).await; + QuorumProposalTaskState::::create_from(&handle).await; + let upgrade_state = + UpgradeTaskState::::create_from(&handle).await; let upgrade_vote_recvs: Vec<_> = upgrade_votes.map(UpgradeVoteRecv).collect(); 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 9595a0355c..5613f66734 100644 --- a/crates/testing/tests/tests_1/upgrade_task_with_vote.rs +++ b/crates/testing/tests/tests_1/upgrade_task_with_vote.rs @@ -14,7 +14,7 @@ use futures::StreamExt; use hotshot::{tasks::task_state::CreateTaskState, types::SystemContextHandle}; use hotshot_example_types::{ block_types::{TestMetadata, TestTransaction}, - node_types::{MemoryImpl, TestTypes}, + node_types::{MemoryImpl, TestTypes, TestVersions}, state_types::TestInstanceState, }; use hotshot_macros::{run_test, test_scripts}; @@ -51,7 +51,9 @@ async fn test_upgrade_task_with_vote() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let handle = build_system_handle::(2).await.0; + 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(); @@ -188,7 +190,8 @@ async fn test_upgrade_task_with_vote() { ), ]; - let vote_state = QuorumVoteTaskState::::create_from(&handle).await; + let vote_state = + QuorumVoteTaskState::::create_from(&handle).await; let mut vote_script = TaskScript { timeout: TIMEOUT, state: vote_state, diff --git a/crates/testing/tests/tests_1/vid_task.rs b/crates/testing/tests/tests_1/vid_task.rs index 131cfe48e0..cf42272d58 100644 --- a/crates/testing/tests/tests_1/vid_task.rs +++ b/crates/testing/tests/tests_1/vid_task.rs @@ -9,7 +9,7 @@ use std::{marker::PhantomData, sync::Arc}; use hotshot::{tasks::task_state::CreateTaskState, types::SignatureKey}; use hotshot_example_types::{ block_types::{TestBlockPayload, TestMetadata, TestTransaction}, - node_types::{MemoryImpl, TestTypes}, + node_types::{MemoryImpl, TestTypes, TestVersions}, state_types::{TestInstanceState, TestValidatedState}, }; use hotshot_macros::{run_test, test_scripts}; @@ -21,12 +21,11 @@ use hotshot_testing::{ serial, }; use hotshot_types::{ - constants::BaseVersion, data::{null_block, DaProposal, PackedBundle, VidDisperse, ViewNumber}, traits::{ consensus_api::ConsensusApi, election::Membership, - node_implementation::{ConsensusTime, NodeType}, + node_implementation::{ConsensusTime, NodeType, Versions}, BlockPayload, }, }; @@ -43,7 +42,9 @@ async fn test_vid_task() { async_compatibility_layer::logging::setup_backtrace(); // Build the API for node 2. - let handle = build_system_handle::(2).await.0; + let handle = build_system_handle::(2) + .await + .0; let pub_key = handle.public_key(); // quorum membership for VID share distribution @@ -98,9 +99,9 @@ async fn test_vid_task() { encoded_transactions, TestMetadata, ViewNumber::new(2), - vec1::vec1![null_block::builder_fee( + vec1::vec1![null_block::builder_fee::( quorum_membership.total_nodes(), - BaseVersion::version() + ::Base::VERSION ) .unwrap()], Some(vid_precompute), @@ -117,9 +118,9 @@ async fn test_vid_task() { builder_commitment, TestMetadata, ViewNumber::new(2), - vec1![null_block::builder_fee( + vec1![null_block::builder_fee::( quorum_membership.total_nodes(), - BaseVersion::version() + ::Base::VERSION ) .unwrap()], None, diff --git a/crates/testing/tests/tests_1/view_sync_task.rs b/crates/testing/tests/tests_1/view_sync_task.rs index 671d9506a2..eba1c2ebdf 100644 --- a/crates/testing/tests/tests_1/view_sync_task.rs +++ b/crates/testing/tests/tests_1/view_sync_task.rs @@ -5,7 +5,7 @@ // along with the HotShot repository. If not, see . use hotshot::tasks::task_state::CreateTaskState; -use hotshot_example_types::node_types::{MemoryImpl, TestTypes}; +use hotshot_example_types::node_types::{MemoryImpl, TestTypes, TestVersions}; use hotshot_task_impls::{ events::HotShotEvent, harness::run_harness, view_sync::ViewSyncTaskState, }; @@ -23,7 +23,9 @@ async fn test_view_sync_task() { async_compatibility_layer::logging::setup_backtrace(); // Build the API for node 5. - let handle = build_system_handle::(5).await.0; + let handle = build_system_handle::(5) + .await + .0; let vote_data = ViewSyncPreCommitData { relay: 0, diff --git a/crates/testing/tests/tests_1/vote_dependency_handle.rs b/crates/testing/tests/tests_1/vote_dependency_handle.rs index b831c256bd..2938ea6ef9 100644 --- a/crates/testing/tests/tests_1/vote_dependency_handle.rs +++ b/crates/testing/tests/tests_1/vote_dependency_handle.rs @@ -5,7 +5,7 @@ use std::time::Duration; use async_broadcast::broadcast; use async_compatibility_layer::art::async_timeout; use futures::StreamExt; -use hotshot_example_types::node_types::{MemoryImpl, TestTypes}; +use hotshot_example_types::node_types::{MemoryImpl, TestTypes, TestVersions}; use hotshot_task::dependency_task::HandleDepOutput; use hotshot_task_impls::{events::HotShotEvent::*, quorum_vote::VoteDependencyHandle}; use hotshot_testing::{ @@ -14,8 +14,10 @@ use hotshot_testing::{ view_generator::TestViewGenerator, }; use hotshot_types::{ - consensus::OuterConsensus, data::ViewNumber, traits::consensus_api::ConsensusApi, - traits::node_implementation::ConsensusTime, vote::HasViewNumber, + consensus::OuterConsensus, + data::ViewNumber, + traits::{consensus_api::ConsensusApi, node_implementation::ConsensusTime}, + vote::HasViewNumber, }; use itertools::Itertools; @@ -33,7 +35,7 @@ async fn test_vote_dependency_handle() { // We use a node ID of 2 here abitrarily. 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 = build_system_handle::(node_id) .await .0; let quorum_membership = handle.hotshot.memberships.quorum_membership.clone(); @@ -85,19 +87,20 @@ async fn test_vote_dependency_handle() { let (event_sender, mut event_receiver) = broadcast(1024); let view_number = ViewNumber::new(node_id); - let vote_dependency_handle_state = VoteDependencyHandle:: { - public_key: handle.public_key().clone(), - private_key: handle.private_key().clone(), - consensus: OuterConsensus::new(consensus.clone()), - instance_state: handle.hotshot.instance_state(), - quorum_membership: handle.hotshot.memberships.quorum_membership.clone().into(), - storage: Arc::clone(&handle.storage()), - view_number, - sender: event_sender.clone(), - receiver: event_receiver.clone(), - decided_upgrade_certificate: Arc::clone(&handle.hotshot.decided_upgrade_certificate), - id: handle.hotshot.id, - }; + let vote_dependency_handle_state = + VoteDependencyHandle:: { + public_key: handle.public_key().clone(), + private_key: handle.private_key().clone(), + consensus: OuterConsensus::new(consensus.clone()), + instance_state: handle.hotshot.instance_state(), + quorum_membership: handle.hotshot.memberships.quorum_membership.clone().into(), + storage: Arc::clone(&handle.storage()), + view_number, + sender: event_sender.clone(), + receiver: event_receiver.clone(), + upgrade_lock: handle.hotshot.upgrade_lock.clone(), + id: handle.hotshot.id, + }; vote_dependency_handle_state .handle_dep_result(inputs.clone().into_iter().map(|i| i.into()).collect()) diff --git a/crates/testing/tests/tests_2/catchup.rs b/crates/testing/tests/tests_2/catchup.rs index f78cc9c580..33f8af1576 100644 --- a/crates/testing/tests/tests_2/catchup.rs +++ b/crates/testing/tests/tests_2/catchup.rs @@ -10,7 +10,7 @@ async fn test_catchup() { use std::time::Duration; - use hotshot_example_types::node_types::{MemoryImpl, TestTypes}; + use hotshot_example_types::node_types::{MemoryImpl, TestTypes, TestVersions}; use hotshot_testing::{ block_builder::SimpleBuilderImplementation, completion_task::{CompletionTaskDescription, TimeBasedCompletionTaskDescription}, @@ -25,7 +25,8 @@ async fn test_catchup() { next_view_timeout: 2000, ..Default::default() }; - let mut metadata: TestDescription = TestDescription::default(); + let mut metadata: TestDescription = + TestDescription::default(); let catchup_node = vec![ChangeNode { idx: 19, updown: UpDown::Up, @@ -69,7 +70,7 @@ async fn test_catchup() { async fn test_catchup_cdn() { use std::time::Duration; - use hotshot_example_types::node_types::{PushCdnImpl, TestTypes}; + use hotshot_example_types::node_types::{PushCdnImpl, TestTypes, TestVersions}; use hotshot_testing::{ block_builder::SimpleBuilderImplementation, completion_task::{CompletionTaskDescription, TimeBasedCompletionTaskDescription}, @@ -84,7 +85,8 @@ async fn test_catchup_cdn() { next_view_timeout: 2000, ..Default::default() }; - let mut metadata: TestDescription = TestDescription::default(); + let mut metadata: TestDescription = + TestDescription::default(); let catchup_nodes = vec![ChangeNode { idx: 18, updown: UpDown::Up, @@ -123,7 +125,7 @@ async fn test_catchup_cdn() { async fn test_catchup_one_node() { use std::time::Duration; - use hotshot_example_types::node_types::{MemoryImpl, TestTypes}; + use hotshot_example_types::node_types::{MemoryImpl, TestTypes, TestVersions}; use hotshot_testing::{ block_builder::SimpleBuilderImplementation, completion_task::{CompletionTaskDescription, TimeBasedCompletionTaskDescription}, @@ -137,7 +139,8 @@ async fn test_catchup_one_node() { next_view_timeout: 2000, ..Default::default() }; - let mut metadata: TestDescription = TestDescription::default(); + let mut metadata: TestDescription = + TestDescription::default(); let catchup_nodes = vec![ChangeNode { idx: 18, updown: UpDown::Up, @@ -178,7 +181,7 @@ async fn test_catchup_one_node() { async fn test_catchup_in_view_sync() { use std::time::Duration; - use hotshot_example_types::node_types::{MemoryImpl, TestTypes}; + use hotshot_example_types::node_types::{MemoryImpl, TestTypes, TestVersions}; use hotshot_testing::{ block_builder::SimpleBuilderImplementation, completion_task::{CompletionTaskDescription, TimeBasedCompletionTaskDescription}, @@ -192,7 +195,8 @@ async fn test_catchup_in_view_sync() { next_view_timeout: 2000, ..Default::default() }; - let mut metadata: TestDescription = TestDescription::default(); + let mut metadata: TestDescription = + TestDescription::default(); let catchup_nodes = vec![ ChangeNode { idx: 18, @@ -240,7 +244,7 @@ async fn test_catchup_in_view_sync() { async fn test_catchup_reload() { use std::time::Duration; - use hotshot_example_types::node_types::{MemoryImpl, TestTypes}; + use hotshot_example_types::node_types::{MemoryImpl, TestTypes, TestVersions}; use hotshot_testing::{ block_builder::SimpleBuilderImplementation, completion_task::{CompletionTaskDescription, TimeBasedCompletionTaskDescription}, @@ -255,7 +259,8 @@ async fn test_catchup_reload() { next_view_timeout: 2000, ..Default::default() }; - let mut metadata: TestDescription = TestDescription::default(); + let mut metadata: TestDescription = + TestDescription::default(); let catchup_node = vec![ChangeNode { idx: 19, updown: UpDown::Up, @@ -299,7 +304,7 @@ async fn test_catchup_reload() { async fn test_all_restart() { use std::time::Duration; - use hotshot_example_types::node_types::{CombinedImpl, TestTypes}; + use hotshot_example_types::node_types::{CombinedImpl, TestTypes, TestVersions}; use hotshot_testing::{ block_builder::SimpleBuilderImplementation, completion_task::{CompletionTaskDescription, TimeBasedCompletionTaskDescription}, @@ -314,7 +319,8 @@ async fn test_all_restart() { next_view_timeout: 2000, ..Default::default() }; - let mut metadata: TestDescription = TestDescription::default(); + let mut metadata: TestDescription = + TestDescription::default(); let mut catchup_nodes = vec![]; for i in 1..20 { catchup_nodes.push(ChangeNode { diff --git a/crates/testing/tests/tests_2/push_cdn.rs b/crates/testing/tests/tests_2/push_cdn.rs index dbc0d152c1..5b2dc0d5b1 100644 --- a/crates/testing/tests/tests_2/push_cdn.rs +++ b/crates/testing/tests/tests_2/push_cdn.rs @@ -7,7 +7,7 @@ use std::time::Duration; use async_compatibility_layer::logging::shutdown_logging; -use hotshot_example_types::node_types::{PushCdnImpl, TestTypes}; +use hotshot_example_types::node_types::{PushCdnImpl, TestTypes, TestVersions}; use hotshot_testing::{ block_builder::SimpleBuilderImplementation, completion_task::{CompletionTaskDescription, TimeBasedCompletionTaskDescription}, @@ -23,7 +23,7 @@ use tracing::instrument; async fn push_cdn_network() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let metadata: TestDescription = TestDescription { + let metadata: TestDescription = TestDescription { timing_data: TimingData { round_start_delay: 25, next_view_timeout: 10_000, diff --git a/crates/testing/tests/tests_2/test_with_failures_one.rs b/crates/testing/tests/tests_2/test_with_failures_one.rs index 030103a37e..5408b57eb5 100644 --- a/crates/testing/tests/tests_2/test_with_failures_one.rs +++ b/crates/testing/tests/tests_2/test_with_failures_one.rs @@ -5,7 +5,7 @@ // along with the HotShot repository. If not, see . use hotshot_example_types::{ - node_types::{Libp2pImpl, MemoryImpl, PushCdnImpl}, + node_types::{Libp2pImpl, MemoryImpl, PushCdnImpl, TestVersions}, state_types::TestTypes, }; use hotshot_macros::cross_tests; @@ -20,6 +20,7 @@ cross_tests!( TestName: test_with_failures_one, Impls: [MemoryImpl, Libp2pImpl, PushCdnImpl], Types: [TestTypes], + Versions: [TestVersions], Ignore: false, Metadata: { let mut metadata = TestDescription::default_more_nodes(); diff --git a/crates/testing/tests/tests_3/memory_network.rs b/crates/testing/tests/tests_3/memory_network.rs index 4fe3ae6d49..03a9abe2d1 100644 --- a/crates/testing/tests/tests_3/memory_network.rs +++ b/crates/testing/tests/tests_3/memory_network.rs @@ -19,12 +19,13 @@ use hotshot::{ use hotshot_example_types::{ auction_results_provider_types::{TestAuctionResult, TestAuctionResultsProvider}, block_types::{TestBlockHeader, TestBlockPayload, TestTransaction}, + node_types::TestVersions, state_types::{TestInstanceState, TestValidatedState}, storage_types::TestStorage, }; use hotshot_types::{ data::ViewNumber, - message::{DataMessage, Message, MessageKind, VersionedMessage}, + message::{DataMessage, Message, MessageKind, UpgradeLock}, signature_key::{BLSPubKey, BuilderKey}, traits::{ network::{BroadcastDelay, ConnectedNetwork, TestableNetworkingImplementation, Topic}, @@ -34,7 +35,6 @@ use hotshot_types::{ use rand::{rngs::StdRng, RngCore, SeedableRng}; use serde::{Deserialize, Serialize}; use tracing::{instrument, trace}; -use vbs::version::StaticVersion; #[derive( Copy, @@ -53,12 +53,6 @@ pub struct Test; impl NodeType for Test { type AuctionResult = TestAuctionResult; - type Base = StaticVersion<0, 1>; - type Upgrade = StaticVersion<0, 2>; - const UPGRADE_HASH: [u8; 32] = [ - 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - 0, 0, - ]; type Time = ViewNumber; type BlockHeader = TestBlockHeader; type BlockPayload = TestBlockPayload; @@ -167,10 +161,12 @@ async fn memory_network_direct_queue() { let first_messages: Vec> = gen_messages(5, 100, pub_key_1); + let upgrade_lock = UpgradeLock::::new(); + // Test 1 -> 2 // Send messages for sent_message in first_messages { - let serialized_message = VersionedMessage::serialize(&sent_message, &None).unwrap(); + let serialized_message = upgrade_lock.serialize(&sent_message).await.unwrap(); network1 .direct_message(serialized_message.clone(), pub_key_2) .await @@ -180,7 +176,7 @@ async fn memory_network_direct_queue() { .await .expect("Failed to receive message"); let recv_message = recv_messages.pop().unwrap(); - let deserialized_message = VersionedMessage::deserialize(&recv_message, &None).unwrap(); + let deserialized_message = upgrade_lock.deserialize(&recv_message).await.unwrap(); assert!(recv_messages.is_empty()); fake_message_eq(sent_message, deserialized_message); } @@ -190,7 +186,7 @@ async fn memory_network_direct_queue() { // Test 2 -> 1 // Send messages for sent_message in second_messages { - let serialized_message = VersionedMessage::serialize(&sent_message, &None).unwrap(); + let serialized_message = upgrade_lock.serialize(&sent_message).await.unwrap(); network2 .direct_message(serialized_message.clone(), pub_key_1) .await @@ -200,7 +196,7 @@ async fn memory_network_direct_queue() { .await .expect("Failed to receive message"); let recv_message = recv_messages.pop().unwrap(); - let deserialized_message = VersionedMessage::deserialize(&recv_message, &None).unwrap(); + let deserialized_message = upgrade_lock.deserialize(&recv_message).await.unwrap(); assert!(recv_messages.is_empty()); fake_message_eq(sent_message, deserialized_message); } @@ -220,10 +216,12 @@ async fn memory_network_broadcast_queue() { let first_messages: Vec> = gen_messages(5, 100, pub_key_1); + let upgrade_lock = UpgradeLock::::new(); + // Test 1 -> 2 // Send messages for sent_message in first_messages { - let serialized_message = VersionedMessage::serialize(&sent_message, &None).unwrap(); + let serialized_message = upgrade_lock.serialize(&sent_message).await.unwrap(); network1 .broadcast_message(serialized_message.clone(), Topic::Da, BroadcastDelay::None) .await @@ -233,7 +231,7 @@ async fn memory_network_broadcast_queue() { .await .expect("Failed to receive message"); let recv_message = recv_messages.pop().unwrap(); - let deserialized_message = VersionedMessage::deserialize(&recv_message, &None).unwrap(); + let deserialized_message = upgrade_lock.deserialize(&recv_message).await.unwrap(); assert!(recv_messages.is_empty()); fake_message_eq(sent_message, deserialized_message); } @@ -243,7 +241,7 @@ async fn memory_network_broadcast_queue() { // Test 2 -> 1 // Send messages for sent_message in second_messages { - let serialized_message = VersionedMessage::serialize(&sent_message, &None).unwrap(); + let serialized_message = upgrade_lock.serialize(&sent_message).await.unwrap(); network2 .broadcast_message( serialized_message.clone(), @@ -257,7 +255,7 @@ async fn memory_network_broadcast_queue() { .await .expect("Failed to receive message"); let recv_message = recv_messages.pop().unwrap(); - let deserialized_message = VersionedMessage::deserialize(&recv_message, &None).unwrap(); + let deserialized_message = upgrade_lock.deserialize(&recv_message).await.unwrap(); assert!(recv_messages.is_empty()); fake_message_eq(sent_message, deserialized_message); } @@ -289,8 +287,10 @@ async fn memory_network_test_in_flight_message_count() { Some(0) ); + let upgrade_lock = UpgradeLock::::new(); + for (count, message) in messages.iter().enumerate() { - let serialized_message = VersionedMessage::serialize(message, &None).unwrap(); + let serialized_message = upgrade_lock.serialize(message).await.unwrap(); network1 .direct_message(serialized_message.clone(), pub_key_2) diff --git a/crates/testing/tests/tests_3/test_with_builder_failures.rs b/crates/testing/tests/tests_3/test_with_builder_failures.rs index 4f01d92d94..1b2d3ac13c 100644 --- a/crates/testing/tests/tests_3/test_with_builder_failures.rs +++ b/crates/testing/tests/tests_3/test_with_builder_failures.rs @@ -6,7 +6,7 @@ use std::time::Duration; -use hotshot_example_types::node_types::{MemoryImpl, PushCdnImpl, TestTypes}; +use hotshot_example_types::node_types::{MemoryImpl, PushCdnImpl, TestTypes, TestVersions}; use hotshot_macros::cross_tests; use hotshot_testing::{ block_builder::SimpleBuilderImplementation, @@ -19,6 +19,7 @@ cross_tests!( TestName: test_with_builder_failures, Impls: [MemoryImpl, PushCdnImpl], Types: [TestTypes], + Versions: [TestVersions], Ignore: false, Metadata: { let mut metadata = TestDescription::default_multiple_rounds(); diff --git a/crates/testing/tests/tests_3/test_with_failures_half_f.rs b/crates/testing/tests/tests_3/test_with_failures_half_f.rs index 76f37bde10..e4d7f58d68 100644 --- a/crates/testing/tests/tests_3/test_with_failures_half_f.rs +++ b/crates/testing/tests/tests_3/test_with_failures_half_f.rs @@ -5,7 +5,7 @@ // along with the HotShot repository. If not, see . use hotshot_example_types::{ - node_types::{Libp2pImpl, MemoryImpl, PushCdnImpl}, + node_types::{Libp2pImpl, MemoryImpl, PushCdnImpl, TestVersions}, state_types::TestTypes, }; use hotshot_macros::cross_tests; @@ -19,6 +19,7 @@ cross_tests!( TestName: test_with_failures_half_f, Impls: [MemoryImpl, Libp2pImpl, PushCdnImpl], Types: [TestTypes], + Versions: [TestVersions], Ignore: false, Metadata: { let mut metadata = TestDescription::default_more_nodes(); diff --git a/crates/testing/tests/tests_4/test_with_failures_f.rs b/crates/testing/tests/tests_4/test_with_failures_f.rs index 778062fc66..c36b043294 100644 --- a/crates/testing/tests/tests_4/test_with_failures_f.rs +++ b/crates/testing/tests/tests_4/test_with_failures_f.rs @@ -5,7 +5,7 @@ // along with the HotShot repository. If not, see . use hotshot_example_types::{ - node_types::{Libp2pImpl, MemoryImpl, PushCdnImpl}, + node_types::{Libp2pImpl, MemoryImpl, PushCdnImpl, TestVersions}, state_types::TestTypes, }; use hotshot_macros::cross_tests; @@ -19,6 +19,7 @@ cross_tests!( TestName: test_with_failures_f, Impls: [MemoryImpl, Libp2pImpl, PushCdnImpl], Types: [TestTypes], + Versions: [TestVersions], Ignore: false, Metadata: { let mut metadata = TestDescription::default_more_nodes(); diff --git a/crates/testing/tests/tests_5/combined_network.rs b/crates/testing/tests/tests_5/combined_network.rs index 45e36e895f..bc35b9ad3c 100644 --- a/crates/testing/tests/tests_5/combined_network.rs +++ b/crates/testing/tests/tests_5/combined_network.rs @@ -6,7 +6,7 @@ use std::time::Duration; -use hotshot_example_types::node_types::{CombinedImpl, TestTypes}; +use hotshot_example_types::node_types::{CombinedImpl, TestTypes, TestVersions}; use hotshot_testing::{ block_builder::SimpleBuilderImplementation, completion_task::{CompletionTaskDescription, TimeBasedCompletionTaskDescription}, @@ -27,7 +27,7 @@ async fn test_combined_network() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let metadata: TestDescription = TestDescription { + let metadata: TestDescription = TestDescription { timing_data: TimingData { round_start_delay: 25, next_view_timeout: 10_000, @@ -62,7 +62,7 @@ async fn test_combined_network() { async fn test_combined_network_cdn_crash() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let mut metadata: TestDescription = TestDescription { + let mut metadata: TestDescription = TestDescription { timing_data: TimingData { round_start_delay: 25, next_view_timeout: 10_000, @@ -109,7 +109,7 @@ async fn test_combined_network_cdn_crash() { async fn test_combined_network_reup() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let mut metadata: TestDescription = TestDescription { + let mut metadata: TestDescription = TestDescription { timing_data: TimingData { round_start_delay: 25, next_view_timeout: 10_000, @@ -162,7 +162,7 @@ async fn test_combined_network_reup() { async fn test_combined_network_half_dc() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let mut metadata: TestDescription = TestDescription { + let mut metadata: TestDescription = TestDescription { timing_data: TimingData { round_start_delay: 25, next_view_timeout: 10_000, @@ -238,7 +238,7 @@ fn generate_random_node_changes( async fn test_stress_combined_network_fuzzy() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let mut metadata: TestDescription = TestDescription { + let mut metadata: TestDescription = TestDescription { num_bootstrap_nodes: 10, num_nodes_with_stake: 20, start_nodes: 20, diff --git a/crates/testing/tests/tests_5/timeout.rs b/crates/testing/tests/tests_5/timeout.rs index b7b31c9e7c..2a9cd4e73a 100644 --- a/crates/testing/tests/tests_5/timeout.rs +++ b/crates/testing/tests/tests_5/timeout.rs @@ -12,7 +12,7 @@ async fn test_timeout() { use std::time::Duration; - use hotshot_example_types::node_types::{MemoryImpl, TestTypes}; + use hotshot_example_types::node_types::{MemoryImpl, TestTypes, TestVersions}; use hotshot_testing::{ block_builder::SimpleBuilderImplementation, completion_task::{CompletionTaskDescription, TimeBasedCompletionTaskDescription}, @@ -27,7 +27,7 @@ async fn test_timeout() { ..Default::default() }; - let mut metadata: TestDescription = TestDescription { + let mut metadata: TestDescription = TestDescription { num_nodes_with_stake: 10, start_nodes: 10, ..Default::default() @@ -72,7 +72,7 @@ async fn test_timeout() { async fn test_timeout_libp2p() { use std::time::Duration; - use hotshot_example_types::node_types::{Libp2pImpl, TestTypes}; + use hotshot_example_types::node_types::{Libp2pImpl, TestTypes, TestVersions}; use hotshot_testing::{ block_builder::SimpleBuilderImplementation, completion_task::{CompletionTaskDescription, TimeBasedCompletionTaskDescription}, @@ -90,7 +90,7 @@ async fn test_timeout_libp2p() { ..Default::default() }; - let mut metadata: TestDescription = TestDescription { + let mut metadata: TestDescription = TestDescription { num_nodes_with_stake: 10, start_nodes: 10, num_bootstrap_nodes: 10, diff --git a/crates/testing/tests/tests_5/unreliable_network.rs b/crates/testing/tests/tests_5/unreliable_network.rs index f3d4c18d52..1525ca55e9 100644 --- a/crates/testing/tests/tests_5/unreliable_network.rs +++ b/crates/testing/tests/tests_5/unreliable_network.rs @@ -6,7 +6,7 @@ use std::time::{Duration, Instant}; -use hotshot_example_types::node_types::{Libp2pImpl, TestTypes}; +use hotshot_example_types::node_types::{Libp2pImpl, TestTypes, TestVersions}; use hotshot_testing::{ block_builder::SimpleBuilderImplementation, completion_task::{CompletionTaskDescription, TimeBasedCompletionTaskDescription}, @@ -24,7 +24,7 @@ use tracing::instrument; async fn libp2p_network_sync() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let metadata: TestDescription = TestDescription { + let metadata: TestDescription = TestDescription { overall_safety_properties: OverallSafetyPropertiesDescription { check_leaf: true, ..Default::default() @@ -62,7 +62,7 @@ async fn test_memory_network_sync() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let metadata: TestDescription = TestDescription { + let metadata: TestDescription = TestDescription { // allow more time to pass in CI completion_task_description: CompletionTaskDescription::TimeBasedCompletionTaskBuilder( TimeBasedCompletionTaskDescription { @@ -89,7 +89,7 @@ async fn test_memory_network_sync() { async fn libp2p_network_async() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let metadata: TestDescription = TestDescription { + let metadata: TestDescription = TestDescription { overall_safety_properties: OverallSafetyPropertiesDescription { check_leaf: true, num_failed_views: 50, @@ -103,7 +103,8 @@ async fn libp2p_network_async() { timing_data: TimingData { timeout_ratio: (1, 1), next_view_timeout: 25000, - ..TestDescription::::default_multiple_rounds().timing_data + ..TestDescription::::default_multiple_rounds() + .timing_data }, unreliable_network: Some(Box::new(AsynchronousNetwork { keep_numerator: 9, @@ -136,7 +137,7 @@ async fn test_memory_network_async() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let metadata: TestDescription = TestDescription { + let metadata: TestDescription = TestDescription { overall_safety_properties: OverallSafetyPropertiesDescription { check_leaf: true, num_failed_views: 5000, @@ -151,7 +152,8 @@ async fn test_memory_network_async() { timing_data: TimingData { timeout_ratio: (1, 1), next_view_timeout: 1000, - ..TestDescription::::default_multiple_rounds().timing_data + ..TestDescription::::default_multiple_rounds() + .timing_data }, unreliable_network: Some(Box::new(AsynchronousNetwork { keep_numerator: 95, @@ -182,7 +184,7 @@ async fn test_memory_network_partially_sync() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let metadata: TestDescription = TestDescription { + let metadata: TestDescription = TestDescription { overall_safety_properties: OverallSafetyPropertiesDescription { num_failed_views: 0, ..Default::default() @@ -226,7 +228,7 @@ async fn test_memory_network_partially_sync() { async fn libp2p_network_partially_sync() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let metadata: TestDescription = TestDescription { + let metadata: TestDescription = TestDescription { overall_safety_properties: OverallSafetyPropertiesDescription { num_failed_views: 0, ..Default::default() @@ -275,7 +277,7 @@ async fn test_memory_network_chaos() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let metadata: TestDescription = TestDescription { + let metadata: TestDescription = TestDescription { // allow more time to pass in CI completion_task_description: CompletionTaskDescription::TimeBasedCompletionTaskBuilder( TimeBasedCompletionTaskDescription { @@ -306,7 +308,7 @@ async fn test_memory_network_chaos() { async fn libp2p_network_chaos() { async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let metadata: TestDescription = TestDescription { + let metadata: TestDescription = TestDescription { overall_safety_properties: OverallSafetyPropertiesDescription { check_leaf: true, ..Default::default() diff --git a/crates/types/src/constants.rs b/crates/types/src/constants.rs index 2d497c0674..51db4cd41e 100644 --- a/crates/types/src/constants.rs +++ b/crates/types/src/constants.rs @@ -8,8 +8,6 @@ use std::time::Duration; -use vbs::version::StaticVersion; - /// timeout for fetching auction results from the solver pub const AUCTION_RESULTS_FETCH_TIMEOUT: Duration = Duration::from_millis(500); @@ -43,27 +41,6 @@ pub const EVENT_CHANNEL_SIZE: usize = 100_000; /// Default channel size for HotShot -> application communication pub const EXTERNAL_EVENT_CHANNEL_SIZE: usize = 100_000; -/// Constants for `WebServerNetwork` and `WebServer` -/// The Web CDN is not, strictly speaking, bound to the network; it can have its own versioning. -/// Web Server CDN Version (major) -pub const WEB_SERVER_MAJOR_VERSION: u16 = 0; -/// Web Server CDN Version (minor) -pub const WEB_SERVER_MINOR_VERSION: u16 = 1; - -/// Type for Web Server CDN Version -pub type WebServerVersion = StaticVersion; - -/// Constant for Web Server CDN Version -pub const WEB_SERVER_VERSION: WebServerVersion = StaticVersion {}; - -/// Type for semver representation of "Base" version -pub type BaseVersion = StaticVersion<0, 1>; - -/// Type for semver representation of "Marketplace" version -pub type MarketplaceVersion = StaticVersion<0, 3>; -/// Constant for semver representation of "Marketplace" version -pub const MARKETPLACE_VERSION: MarketplaceVersion = StaticVersion {}; - /// The offset for how far in the future we will send out a `QuorumProposal` with an `UpgradeCertificate` we form. This is also how far in advance of sending a `QuorumProposal` we begin collecting votes on an `UpgradeProposal`. pub const UPGRADE_PROPOSE_OFFSET: u64 = 5; diff --git a/crates/types/src/data.rs b/crates/types/src/data.rs index 9c61f6b9b6..15eb3599e6 100644 --- a/crates/types/src/data.rs +++ b/crates/types/src/data.rs @@ -802,8 +802,10 @@ pub mod null_block { use crate::{ traits::{ - block_contents::BuilderFee, node_implementation::NodeType, - signature_key::BuilderSignatureKey, BlockPayload, + block_contents::BuilderFee, + node_implementation::{NodeType, Versions}, + signature_key::BuilderSignatureKey, + BlockPayload, }, vid::{vid_scheme, VidCommitment}, }; @@ -827,7 +829,7 @@ pub mod null_block { /// Builder fee data for a null block payload #[must_use] - pub fn builder_fee( + pub fn builder_fee( num_storage_nodes: usize, version: vbs::version::Version, ) -> Option> { @@ -839,7 +841,7 @@ pub mod null_block { [0_u8; 32], 0, ); - if version >= crate::constants::MarketplaceVersion::version() { + if version >= V::Marketplace::VERSION { match TYPES::BuilderSignatureKey::sign_sequencing_fee_marketplace(&priv_key, FEE_AMOUNT) { Ok(sig) => Some(BuilderFee { diff --git a/crates/types/src/message.rs b/crates/types/src/message.rs index ccbd53347f..dcd653e7b2 100644 --- a/crates/types/src/message.rs +++ b/crates/types/src/message.rs @@ -9,9 +9,10 @@ //! This module contains types used to represent the various types of messages that //! `HotShot` nodes can send among themselves. -use std::{fmt, fmt::Debug, marker::PhantomData}; +use std::{fmt, fmt::Debug, marker::PhantomData, sync::Arc}; use anyhow::{bail, ensure, Context, Result}; +use async_lock::RwLock; use cdn_proto::util::mnemonic; use committable::Committable; use derivative::Derivative; @@ -24,7 +25,7 @@ use vbs::{ use crate::{ data::{DaProposal, Leaf, QuorumProposal, UpgradeProposal, VidDisperseShare}, simple_certificate::{ - version, DaCertificate, UpgradeCertificate, ViewSyncCommitCertificate2, + DaCertificate, UpgradeCertificate, ViewSyncCommitCertificate2, ViewSyncFinalizeCertificate2, ViewSyncPreCommitCertificate2, }, simple_vote::{ @@ -34,7 +35,7 @@ use crate::{ traits::{ election::Membership, network::{DataRequest, ResponseMessage, ViewMessage}, - node_implementation::{ConsensusTime, NodeType}, + node_implementation::{ConsensusTime, NodeType, Versions}, signature_key::SignatureKey, }, vote::HasViewNumber, @@ -51,74 +52,6 @@ pub struct Message { pub kind: MessageKind, } -/// Trait for messages that have a versioned serialization. -pub trait VersionedMessage<'a, TYPES> -where - TYPES: NodeType, - Self: Serialize + Deserialize<'a> + HasViewNumber + Sized, -{ - /// Serialize a message with a version number, using `message.view_number()` and an optional decided upgrade certificate to determine the message's version. - /// - /// # Errors - /// - /// Errors if serialization fails. - fn serialize( - &self, - upgrade_certificate: &Option>, - ) -> Result> { - let view = self.view_number(); - - let version = version(view, upgrade_certificate)?; - - let serialized_message = match version { - // Associated constants cannot be used in pattern matches, so we do this trick instead. - v if v == TYPES::Base::VERSION => Serializer::::serialize(&self), - v if v == TYPES::Upgrade::VERSION => Serializer::::serialize(&self), - _ => { - bail!("Attempted to serialize with an incompatible version. This should be impossible."); - } - }; - - serialized_message.context("Failed to serialize message!") - } - - /// Deserialize a message with a version number, using `message.view_number()` and an optional decided upgrade certificate to determine the message's version. This function will fail on improperly versioned messages. - /// - /// # Errors - /// - /// Errors if deserialization fails. - fn deserialize( - message: &'a [u8], - upgrade_certificate: &Option>, - ) -> Result { - let actual_version = Version::deserialize(message) - .context("Failed to read message version!")? - .0; - - let deserialized_message: Self = match actual_version { - v if v == TYPES::Base::VERSION => Serializer::::deserialize(message), - v if v == TYPES::Upgrade::VERSION => Serializer::::deserialize(message), - _ => { - bail!("Cannot deserialize message!"); - } - } - .context("Failed to deserialize message!")?; - - let view = deserialized_message.view_number(); - - let expected_version = version(view, upgrade_certificate)?; - - ensure!( - actual_version == expected_version, - "Message has invalid version number for its view. Expected: {expected_version}, Actual: {actual_version}, View: {view:?}" - ); - - Ok(deserialized_message) - } -} - -impl<'a, TYPES> VersionedMessage<'a, TYPES> for Message where TYPES: NodeType {} - impl fmt::Debug for Message { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("Message") @@ -420,3 +353,108 @@ where Ok(()) } } + +#[derive(Clone)] +/// A lock for an upgrade certificate decided by HotShot, which doubles as `PhantomData` for an instance of the `Versions` trait. +pub struct UpgradeLock { + /// a shared lock to an upgrade certificate decided by consensus + pub decided_upgrade_certificate: Arc>>>, + + /// phantom data for the `Versions` trait + pub _pd: PhantomData, +} + +impl UpgradeLock { + #[allow(clippy::new_without_default)] + /// Create a new `UpgradeLock` for a fresh instance of HotShot + pub fn new() -> Self { + Self { + decided_upgrade_certificate: Arc::new(RwLock::new(None)), + _pd: PhantomData::, + } + } + + /// Calculate the version applied in a view, based on the provided upgrade lock. + /// + /// # Errors + /// Returns an error if we do not support the version required by the decided upgrade certificate. + pub async fn version(&self, view: TYPES::Time) -> Result { + let upgrade_certificate = self.decided_upgrade_certificate.read().await; + + let version = match *upgrade_certificate { + Some(ref cert) => { + if view >= cert.data.new_version_first_view { + if cert.data.new_version == V::Upgrade::VERSION { + V::Upgrade::VERSION + } else { + bail!("The network has upgraded to a new version that we do not support!"); + } + } else { + V::Base::VERSION + } + } + None => V::Base::VERSION, + }; + + Ok(version) + } + + /// Serialize a message with a version number, using `message.view_number()` and an optional decided upgrade certificate to determine the message's version. + /// + /// # Errors + /// + /// Errors if serialization fails. + pub async fn serialize + Serialize>( + &self, + message: &M, + ) -> Result> { + let view = message.view_number(); + + let version = self.version(view).await?; + + let serialized_message = match version { + // Associated constants cannot be used in pattern matches, so we do this trick instead. + v if v == V::Base::VERSION => Serializer::::serialize(&message), + v if v == V::Upgrade::VERSION => Serializer::::serialize(&message), + _ => { + bail!("Attempted to serialize with an incompatible version. This should be impossible."); + } + }; + + serialized_message.context("Failed to serialize message!") + } + + /// Deserialize a message with a version number, using `message.view_number()` to determine the message's version. This function will fail on improperly versioned messages. + /// + /// # Errors + /// + /// Errors if deserialization fails. + pub async fn deserialize + for<'a> Deserialize<'a>>( + &self, + message: &[u8], + ) -> Result { + let actual_version = Version::deserialize(message) + .context("Failed to read message version!")? + .0; + + let deserialized_message: M = match actual_version { + v if v == V::Base::VERSION => Serializer::::deserialize(message), + v if v == V::Upgrade::VERSION => Serializer::::deserialize(message), + _ => { + bail!("Cannot deserialize message!"); + } + } + .context("Failed to deserialize message!")?; + + let view = deserialized_message.view_number(); + + let expected_version = self.version(view).await?; + + ensure!( + actual_version == expected_version, + "Message has invalid version number for its view. Expected: {expected_version}, Actual: {actual_version}, View: {view:?}" + ); + + Ok(deserialized_message) + } +} diff --git a/crates/types/src/simple_certificate.rs b/crates/types/src/simple_certificate.rs index 637a32d1e7..4069cb2d98 100644 --- a/crates/types/src/simple_certificate.rs +++ b/crates/types/src/simple_certificate.rs @@ -13,12 +13,11 @@ use std::{ sync::Arc, }; -use anyhow::{bail, ensure, Result}; +use anyhow::{ensure, Result}; use async_lock::RwLock; use committable::{Commitment, Committable}; use ethereum_types::U256; use serde::{Deserialize, Serialize}; -use vbs::version::{StaticVersionType, Version}; use crate::{ data::serialize_signature2, @@ -247,29 +246,3 @@ pub type ViewSyncFinalizeCertificate2 = /// Type alias for a `UpgradeCertificate`, which is a `SimpleCertificate` of `UpgradeProposalData` pub type UpgradeCertificate = SimpleCertificate, UpgradeThreshold>; - -/// Calculate the version applied in a view, based on the provided upgrade certificate. -/// -/// # Errors -/// Returns an error if we do not support the version required by the upgrade certificate. -pub fn version( - view: TYPES::Time, - upgrade_certificate: &Option>, -) -> Result { - let version = match upgrade_certificate { - Some(ref cert) => { - if view >= cert.data.new_version_first_view { - if cert.data.new_version == TYPES::Upgrade::VERSION { - TYPES::Upgrade::VERSION - } else { - bail!("The network has upgraded to a new version that we do not support!"); - } - } else { - TYPES::Base::VERSION - } - } - None => TYPES::Base::VERSION, - }; - - Ok(version) -} diff --git a/crates/types/src/traits/node_implementation.rs b/crates/types/src/traits/node_implementation.rs index 8d9a6a4ffd..1bb9bcb3fc 100644 --- a/crates/types/src/traits/node_implementation.rs +++ b/crates/types/src/traits/node_implementation.rs @@ -207,15 +207,6 @@ pub trait NodeType: + Sync + 'static { - /// The base version of HotShot this node is instantiated with. - type Base: StaticVersionType; - - /// The version of HotShot this node may be upgraded to. Set equal to `Base` to disable upgrades. - type Upgrade: StaticVersionType; - - /// The hash for the upgrade. - const UPGRADE_HASH: [u8; 32]; - /// The time type that this hotshot setup is using. /// /// This should be the same `Time` that `ValidatedState::Time` is using. @@ -261,3 +252,18 @@ pub trait NodeType: /// The type builder uses to sign its messages type BuilderSignatureKey: BuilderSignatureKey; } + +/// Version information for HotShot +pub trait Versions: Clone + Copy + Debug + Send + Sync + 'static { + /// The base version of HotShot this node is instantiated with. + type Base: StaticVersionType; + + /// The version of HotShot this node may be upgraded to. Set equal to `Base` to disable upgrades. + type Upgrade: StaticVersionType; + + /// The hash for the upgrade. + const UPGRADE_HASH: [u8; 32]; + + /// The version at which to switch over to marketplace logic + type Marketplace: StaticVersionType; +}