From 778ae2303645ecd53856a16594619738e6c8beb2 Mon Sep 17 00:00:00 2001 From: Keyao Shen Date: Sat, 30 Sep 2023 16:35:29 -0700 Subject: [PATCH 01/20] Fix index update and parameter --- crates/web_server/src/lib.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/crates/web_server/src/lib.rs b/crates/web_server/src/lib.rs index ef7850cbb0..861c6a5a67 100644 --- a/crates/web_server/src/lib.rs +++ b/crates/web_server/src/lib.rs @@ -309,7 +309,12 @@ impl WebServerDataSource for WebServerState { .or_insert_with(|| vec![(*highest_index, vote)]); self.view_sync_vote_index .entry(view_number) - .and_modify(|index| *index += 1); + .and_modify(|index| { + // Update the index if it's not just added. + if *index > 0 { + *index += 1 + } + }); Ok(()) } /// Stores a received proposal in the `WebServerState` @@ -337,7 +342,8 @@ impl WebServerDataSource for WebServerState { ) -> Result<(), Error> { // Only keep proposal history for MAX_VIEWS number of view if self.view_sync_proposals.len() >= MAX_VIEWS { - self.view_sync_proposals.remove(&self.oldest_view_sync_vote); + self.view_sync_proposals + .remove(&self.oldest_view_sync_proposal); while !self .view_sync_proposals .contains_key(&self.oldest_view_sync_proposal) @@ -355,7 +361,12 @@ impl WebServerDataSource for WebServerState { .or_insert_with(|| vec![(*highest_index, proposal)]); self.view_sync_proposal_index .entry(view_number) - .and_modify(|index| *index += 1); + .and_modify(|index| { + // Update the index if it's not just added. + if *index > 0 { + *index += 1 + } + }); Ok(()) } From 00b0dc9b7d256204ce047485cb12c55496829285 Mon Sep 17 00:00:00 2001 From: elliedavidson <118024407+elliedavidson@users.noreply.github.com> Date: Sun, 1 Oct 2023 10:43:48 +0900 Subject: [PATCH 02/20] update cargo lock --- Cargo.lock | 86 +++++++++++++++--------------- crates/task-impls/src/consensus.rs | 1 + crates/task-impls/src/da.rs | 2 + 3 files changed, 46 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b74a031ce6..617fb4165d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -286,7 +286,7 @@ dependencies = [ "blake2", "derivative", "digest 0.10.7", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -526,7 +526,7 @@ dependencies = [ "num-traits", "rusticata-macros", "thiserror", - "time 0.3.28", + "time 0.3.29", ] [[package]] @@ -1031,9 +1031,9 @@ dependencies = [ [[package]] name = "blake3" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "199c42ab6972d92c9f8995f086273d25c42fc0f7b2a1fcefba465c1352d25ba5" +checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87" dependencies = [ "arrayref", "arrayvec", @@ -1236,9 +1236,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.2" +version = "4.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a13b88d2c62ff462f88e4a121f17a82c1af05693a2f192b5c38d14de73c19f6" +checksum = "824956d0dca8334758a5b7f7e50518d66ea319330cbceedcf76905c2f6ab30e3" dependencies = [ "clap_builder", "clap_derive", @@ -1246,9 +1246,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.2" +version = "4.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bb9faaa7c2ef94b2743a21f5a29e6f0010dff4caa69ac8e9d6cf8b6fa74da08" +checksum = "122ec64120a49b4563ccaedcbea7818d069ed8e9aa6d829b82d8a4128936b2ab" dependencies = [ "anstream", "anstyle", @@ -2050,7 +2050,7 @@ dependencies = [ "ed25519", "rand_core 0.6.4", "serde", - "sha2 0.10.7", + "sha2 0.10.8", "zeroize", ] @@ -2654,7 +2654,7 @@ dependencies = [ "serde_json", "snafu", "surf-disco", - "time 0.3.28", + "time 0.3.29", "tokio", "toml 0.7.8", "tracing", @@ -2802,7 +2802,7 @@ dependencies = [ "rand_chacha 0.3.1", "serde", "snafu", - "time 0.3.28", + "time 0.3.29", "tokio", "tracing", ] @@ -2875,7 +2875,7 @@ dependencies = [ "serde_json", "snafu", "tagged-base64 0.2.4", - "time 0.3.28", + "time 0.3.29", "tokio", "tracing", "typenum", @@ -3313,7 +3313,7 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "jf-primitives" version = "0.4.0-pre.0" -source = "git+https://github.com/EspressoSystems/jellyfish#ef404b72acc63179b56a08c99c0cc4c6604b6669" +source = "git+https://github.com/EspressoSystems/jellyfish#30752c6c1af7b933e2536d7aeb991a40af4b806a" dependencies = [ "anyhow", "ark-bls12-377", @@ -3348,7 +3348,7 @@ dependencies = [ "rand_chacha 0.3.1", "rayon", "serde", - "sha2 0.10.7", + "sha2 0.10.8", "sha3", "tagged-base64 0.3.3", "typenum", @@ -3358,7 +3358,7 @@ dependencies = [ [[package]] name = "jf-relation" version = "0.4.0-pre.0" -source = "git+https://github.com/EspressoSystems/jellyfish#ef404b72acc63179b56a08c99c0cc4c6604b6669" +source = "git+https://github.com/EspressoSystems/jellyfish#30752c6c1af7b933e2536d7aeb991a40af4b806a" dependencies = [ "ark-bls12-377", "ark-bls12-381", @@ -3384,7 +3384,7 @@ dependencies = [ [[package]] name = "jf-utils" version = "0.4.0-pre.0" -source = "git+https://github.com/EspressoSystems/jellyfish#ef404b72acc63179b56a08c99c0cc4c6604b6669" +source = "git+https://github.com/EspressoSystems/jellyfish#30752c6c1af7b933e2536d7aeb991a40af4b806a" dependencies = [ "ark-ec", "ark-ff", @@ -3393,7 +3393,7 @@ dependencies = [ "digest 0.10.7", "rayon", "serde", - "sha2 0.10.7", + "sha2 0.10.8", "tagged-base64 0.3.3", ] @@ -3646,7 +3646,7 @@ dependencies = [ "rand 0.8.5", "regex", "serde", - "sha2 0.10.7", + "sha2 0.10.8", "smallvec", "unsigned-varint", "void", @@ -3690,7 +3690,7 @@ dependencies = [ "rand 0.8.5", "ring", "serde", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", "zeroize", ] @@ -3716,7 +3716,7 @@ dependencies = [ "quick-protobuf", "rand 0.8.5", "serde", - "sha2 0.10.7", + "sha2 0.10.8", "smallvec", "thiserror", "uint", @@ -3823,7 +3823,7 @@ dependencies = [ "once_cell", "quick-protobuf", "rand 0.8.5", - "sha2 0.10.7", + "sha2 0.10.8", "snow", "static_assertions", "thiserror", @@ -4883,7 +4883,7 @@ checksum = "b42f0394d3123e33353ca5e1e89092e533d2cc490389f2bd6131c43c634ebc5f" dependencies = [ "once_cell", "pest", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -5217,9 +5217,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.10.4" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13f81c9a9d574310b8351f8666f5a93ac3b0069c45c28ad52c10291389a7cf9" +checksum = "2c78e758510582acc40acb90458401172d41f1016f8c9dde89e49677afb7eec1" dependencies = [ "bytes 1.4.0", "rand 0.8.5", @@ -5361,7 +5361,7 @@ checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" dependencies = [ "pem", "ring", - "time 0.3.28", + "time 0.3.29", "yasna", ] @@ -5740,9 +5740,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.106" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc66a619ed80bf7a0f6b17dd063a84b88f6dea1813737cf469aef1d081142c2" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" dependencies = [ "itoa 1.0.9", "ryu", @@ -5794,7 +5794,7 @@ dependencies = [ "serde", "serde_json", "serde_with_macros 2.3.3", - "time 0.3.28", + "time 0.3.29", ] [[package]] @@ -5811,7 +5811,7 @@ dependencies = [ "serde", "serde_json", "serde_with_macros 3.3.0", - "time 0.3.28", + "time 0.3.29", ] [[package]] @@ -5891,9 +5891,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -6082,7 +6082,7 @@ dependencies = [ "rand_core 0.6.4", "ring", "rustc_version 0.4.0", - "sha2 0.10.7", + "sha2 0.10.8", "subtle", ] @@ -6695,22 +6695,22 @@ dependencies = [ [[package]] name = "time" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f6bb557fd245c28e6411aa56b6403c689ad95061f50e4be16c274e70a17e48" +checksum = "426f806f4089c493dcac0d24c29c01e2c38baf8e30f1b716ee37e83d200b18fe" dependencies = [ "deranged", "itoa 1.0.9", "serde", "time-core", - "time-macros 0.2.14", + "time-macros 0.2.15", ] [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" @@ -6724,9 +6724,9 @@ dependencies = [ [[package]] name = "time-macros" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a942f44339478ef67935ab2bbaec2fb0322496cf3cbe84b261e06ac3814c572" +checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" dependencies = [ "time-core", ] @@ -7138,9 +7138,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ucd-trie" @@ -7626,7 +7626,7 @@ dependencies = [ "oid-registry", "rusticata-macros", "thiserror", - "time 0.3.28", + "time 0.3.29", ] [[package]] @@ -7659,7 +7659,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" dependencies = [ - "time 0.3.28", + "time 0.3.29", ] [[package]] diff --git a/crates/task-impls/src/consensus.rs b/crates/task-impls/src/consensus.rs index 63f3f45f1d..ad6a1c8c99 100644 --- a/crates/task-impls/src/consensus.rs +++ b/crates/task-impls/src/consensus.rs @@ -1093,6 +1093,7 @@ where } SequencingHotShotEvent::SendDABlockData(block) => { // ED TODO Should make sure this is actually the most recent block + // ED Should make this a map to view self.block = block; } _ => {} diff --git a/crates/task-impls/src/da.rs b/crates/task-impls/src/da.rs index c7d20786ab..37fcdde00b 100644 --- a/crates/task-impls/src/da.rs +++ b/crates/task-impls/src/da.rs @@ -500,6 +500,8 @@ where drop(consensus); + // ED This is taking a really long time to return, since is based on application + // let mut block = ::StateType::next_block(None); let txns = self.wait_for_transactions(parent_leaf).await?; From afe335b4098a0d5bd1f42995c7900064bddac206 Mon Sep 17 00:00:00 2001 From: elliedavidson <118024407+elliedavidson@users.noreply.github.com> Date: Sun, 1 Oct 2023 11:03:38 +0900 Subject: [PATCH 03/20] Update self.block to be option --- crates/hotshot/src/tasks/mod.rs | 2 +- crates/task-impls/src/consensus.rs | 98 ++++++++++++++++-------------- 2 files changed, 52 insertions(+), 48 deletions(-) diff --git a/crates/hotshot/src/tasks/mod.rs b/crates/hotshot/src/tasks/mod.rs index 55e430cbe4..5415bad8ea 100644 --- a/crates/hotshot/src/tasks/mod.rs +++ b/crates/hotshot/src/tasks/mod.rs @@ -352,7 +352,7 @@ where consensus, timeout: handle.hotshot.inner.config.next_view_timeout, cur_view: TYPES::Time::new(0), - block: TYPES::BlockType::new(), + block: Some(TYPES::BlockType::new()), quorum_exchange: c_api.inner.exchanges.quorum_exchange().clone().into(), api: c_api.clone(), committee_exchange: c_api.inner.exchanges.committee_exchange().clone().into(), diff --git a/crates/task-impls/src/consensus.rs b/crates/task-impls/src/consensus.rs index ad6a1c8c99..30a48fda4d 100644 --- a/crates/task-impls/src/consensus.rs +++ b/crates/task-impls/src/consensus.rs @@ -86,7 +86,7 @@ pub struct SequencingConsensusTaskState< pub cur_view: TYPES::Time, /// Current block submitted to DA - pub block: TYPES::BlockType, + pub block: Option, /// the quorum exchange pub quorum_exchange: Arc>, @@ -1094,7 +1094,7 @@ where SequencingHotShotEvent::SendDABlockData(block) => { // ED TODO Should make sure this is actually the most recent block // ED Should make this a map to view - self.block = block; + self.block = Some(block); } _ => {} } @@ -1102,7 +1102,7 @@ where /// Sends a proposal if possible from the high qc we have pub async fn publish_proposal_if_able( - &self, + &mut self, _qc: QuorumCertificate, view: TYPES::Time, ) -> bool { @@ -1167,52 +1167,56 @@ where // TODO do some sort of sanity check on the view number that it matches decided } - let block_commitment = self.block.commit(); - if block_commitment == TYPES::BlockType::new().commit() { - debug!("Block is generic block! {:?}", self.cur_view); - } - - let leaf = SequencingLeaf { - view_number: view, - height: parent_leaf.height + 1, - justify_qc: consensus.high_qc.clone(), - parent_commitment: parent_leaf.commit(), - // Use the block commitment rather than the block, so that the replica can construct - // the same leaf with the commitment. - deltas: Right(block_commitment), - rejected: vec![], - timestamp: time::OffsetDateTime::now_utc().unix_timestamp_nanos(), - proposer_id: self.api.public_key().to_bytes(), - }; + if let Some(block) = &self.block { + let block_commitment = block.commit(); + if block_commitment == TYPES::BlockType::new().commit() { + debug!("Block is generic block! {:?}", self.cur_view); + } - let signature = self - .quorum_exchange - .sign_validating_or_commitment_proposal::(&leaf.commit()); - // TODO: DA cert is sent as part of the proposal here, we should split this out so we don't have to wait for it. - let proposal = QuorumProposal { - block_commitment, - view_number: leaf.view_number, - height: leaf.height, - justify_qc: consensus.high_qc.clone(), - // TODO ED Update this to be the actual TC if there is one - timeout_certificate: None, - proposer_id: leaf.proposer_id, - dac: None, - }; + let leaf = SequencingLeaf { + view_number: view, + height: parent_leaf.height + 1, + justify_qc: consensus.high_qc.clone(), + parent_commitment: parent_leaf.commit(), + // Use the block commitment rather than the block, so that the replica can construct + // the same leaf with the commitment. + deltas: Right(block_commitment), + rejected: vec![], + timestamp: time::OffsetDateTime::now_utc().unix_timestamp_nanos(), + proposer_id: self.api.public_key().to_bytes(), + }; + + let signature = self + .quorum_exchange + .sign_validating_or_commitment_proposal::(&leaf.commit()); + // TODO: DA cert is sent as part of the proposal here, we should split this out so we don't have to wait for it. + let proposal = QuorumProposal { + block_commitment, + view_number: leaf.view_number, + height: leaf.height, + justify_qc: consensus.high_qc.clone(), + // TODO ED Update this to be the actual TC if there is one + timeout_certificate: None, + proposer_id: leaf.proposer_id, + dac: None, + }; + + let message = Proposal { + data: proposal, + signature, + }; + debug!("Sending proposal for view {:?} \n {:?}", self.cur_view, ""); - let message = Proposal { - data: proposal, - signature, - }; - debug!("Sending proposal for view {:?} \n {:?}", self.cur_view, ""); - - self.event_stream - .publish(SequencingHotShotEvent::QuorumProposalSend( - message, - self.quorum_exchange.public_key().clone(), - )) - .await; - true + self.event_stream + .publish(SequencingHotShotEvent::QuorumProposalSend( + message, + self.quorum_exchange.public_key().clone(), + )) + .await; + self.block = None; + return true + } + false } } From 26a565ce3c7f0fbea6dd830fb94334ea9ee5a6a2 Mon Sep 17 00:00:00 2001 From: elliedavidson <118024407+elliedavidson@users.noreply.github.com> Date: Sun, 1 Oct 2023 11:12:05 +0900 Subject: [PATCH 04/20] Cargo fmt --- crates/task-impls/src/consensus.rs | 4 ++-- crates/task-impls/src/da.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/task-impls/src/consensus.rs b/crates/task-impls/src/consensus.rs index 30a48fda4d..3c3ba5abd7 100644 --- a/crates/task-impls/src/consensus.rs +++ b/crates/task-impls/src/consensus.rs @@ -1213,8 +1213,8 @@ where self.quorum_exchange.public_key().clone(), )) .await; - self.block = None; - return true + self.block = None; + return true; } false } diff --git a/crates/task-impls/src/da.rs b/crates/task-impls/src/da.rs index 37fcdde00b..4037e07a23 100644 --- a/crates/task-impls/src/da.rs +++ b/crates/task-impls/src/da.rs @@ -501,7 +501,7 @@ where drop(consensus); // ED This is taking a really long time to return, since is based on application - // + // let mut block = ::StateType::next_block(None); let txns = self.wait_for_transactions(parent_leaf).await?; From 09452be58f7e7651e2bbe9da519af6ab042ce134 Mon Sep 17 00:00:00 2001 From: elliedavidson <118024407+elliedavidson@users.noreply.github.com> Date: Sun, 1 Oct 2023 11:54:12 +0900 Subject: [PATCH 05/20] Update view sync logging --- crates/task-impls/src/view_sync.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/crates/task-impls/src/view_sync.rs b/crates/task-impls/src/view_sync.rs index 18c8ae581f..eafeb7a468 100644 --- a/crates/task-impls/src/view_sync.rs +++ b/crates/task-impls/src/view_sync.rs @@ -277,7 +277,7 @@ where (certificate_internal, ViewSyncPhase::Finalize) } }; - debug!( + error!( "Received view sync cert for phase {:?}", last_seen_certificate ); @@ -483,7 +483,10 @@ where } self.num_timeouts_tracked += 1; - error!("Num timeouts tracked is {}", self.num_timeouts_tracked); + error!( + "Num timeouts tracked is {}. View {} timed out", + self.num_timeouts_tracked, *view_number + ); if self.num_timeouts_tracked > 2 { error!("Too many timeouts! This shouldn't happen"); @@ -491,6 +494,10 @@ where // TODO ED Make this a configurable variable if self.num_timeouts_tracked == 2 { + error!( + "Starting view sync protocol; attempting to sync on view {}", + *view_number + 1 + ); // Start polling for view sync certificates self.exchange .network() @@ -637,7 +644,7 @@ where // Ignore certificate if it is for an older round if certificate_internal.round < self.next_view { - debug!("We're already in a higher round"); + error!("We're already in a higher round"); return (None, self); } @@ -654,9 +661,9 @@ where // If certificate is not valid, return current state if !self .exchange - .is_valid_view_sync_cert(message.data, certificate_internal.round) + .is_valid_view_sync_cert(message.data.clone(), certificate_internal.round) { - error!("Not valid view sync cert!"); + error!("Not valid view sync cert! {:?}", message.data); return (None, self); } From ee401c6d090879cc035d3de742c7bac38337879f Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Sun, 1 Oct 2023 17:46:19 -0400 Subject: [PATCH 06/20] feat: memory network reliability --- crates/hotshot/src/traits.rs | 2 +- .../src/traits/networking/memory_network.rs | 149 ++++++------ crates/testing/src/network_reliability.rs | 163 ------------- crates/types/src/traits/network.rs | 229 +++++++++++++++++- 4 files changed, 299 insertions(+), 244 deletions(-) delete mode 100644 crates/testing/src/network_reliability.rs diff --git a/crates/hotshot/src/traits.rs b/crates/hotshot/src/traits.rs index a0e56cf86d..370dc47839 100644 --- a/crates/hotshot/src/traits.rs +++ b/crates/hotshot/src/traits.rs @@ -14,7 +14,7 @@ pub mod implementations { pub use super::{ networking::{ libp2p_network::{Libp2pCommChannel, Libp2pNetwork, PeerInfoVec}, - memory_network::{DummyReliability, MasterMap, MemoryCommChannel, MemoryNetwork}, + memory_network::{MasterMap, MemoryCommChannel, MemoryNetwork}, web_server_libp2p_fallback::{CombinedNetworks, WebServerWithFallbackCommChannel}, web_server_network::{WebCommChannel, WebServerNetwork}, }, diff --git a/crates/hotshot/src/traits/networking/memory_network.rs b/crates/hotshot/src/traits/networking/memory_network.rs index 976186c030..9d9e751ee5 100644 --- a/crates/hotshot/src/traits/networking/memory_network.rs +++ b/crates/hotshot/src/traits/networking/memory_network.rs @@ -6,7 +6,7 @@ use super::{FailedToSerializeSnafu, NetworkError, NetworkReliability, NetworkingMetrics}; use crate::NodeImplementation; use async_compatibility_layer::{ - art::{async_sleep, async_spawn}, + art::async_spawn, channel::{bounded, Receiver, SendError, Sender}, }; use async_lock::{Mutex, RwLock}; @@ -42,18 +42,6 @@ use std::{ }; use tracing::{debug, error, info, info_span, instrument, trace, warn, Instrument}; -#[derive(Debug, Clone, Copy)] -/// dummy implementation of network reliability -pub struct DummyReliability {} -impl NetworkReliability for DummyReliability { - fn sample_keep(&self) -> bool { - true - } - fn sample_delay(&self) -> std::time::Duration { - std::time::Duration::ZERO - } -} - /// Shared state for in-memory mock networking. /// /// This type is responsible for keeping track of the channels to each [`MemoryNetwork`], and is @@ -104,6 +92,9 @@ struct MemoryNetworkInner { /// The networking metrics we're keeping track of metrics: NetworkingMetrics, + + /// config to introduce unreliability to the network + reliability_config: Option>>, } /// In memory only network simulator. @@ -134,7 +125,7 @@ impl MemoryNetwork { pub_key: K, metrics: Box, master_map: Arc>, - reliability_config: Option>, + reliability_config: Option>>, ) -> MemoryNetwork { info!("Attaching new MemoryNetwork"); let (broadcast_input, broadcast_task_recv) = bounded(128); @@ -165,30 +156,11 @@ impl MemoryNetwork { match x { Ok(x) => { let dts = direct_task_send.clone(); - if let Some(r) = reliability_config.clone() { - async_spawn(async move { - if r.sample_keep() { - let delay = r.sample_delay(); - if delay > std::time::Duration::ZERO { - async_sleep(delay).await; - } - let res = dts.send(x).await; - if res.is_ok() { - trace!("Passed message to output queue"); - } else { - error!("Output queue receivers are shutdown"); - } - } else { - warn!("dropping packet!"); - } - }); + let res = dts.send(x).await; + if res.is_ok() { + trace!("Passed message to output queue"); } else { - let res = dts.send(x).await; - if res.is_ok() { - trace!("Passed message to output queue"); - } else { - error!("Output queue receivers are shutdown"); - } + error!("Output queue receivers are shutdown"); } } Err(e) => { @@ -203,28 +175,11 @@ impl MemoryNetwork { match x { Ok(x) => { let bts = broadcast_task_send.clone(); - if let Some(r) = reliability_config.clone() { - async_spawn(async move { - if r.sample_keep() { - let delay = r.sample_delay(); - if delay > std::time::Duration::ZERO { - async_sleep(delay).await; - } - let res = bts.send(x).await; - if res.is_ok() { - trace!("Passed message to output queue"); - } else { - warn!("dropping packet!"); - } - } - }); + let res = bts.send(x).await; + if res.is_ok() { + trace!("Passed message to output queue"); } else { - let res = bts.send(x).await; - if res.is_ok() { - trace!("Passed message to output queue"); - } else { - warn!("dropping packet!"); - } + warn!("dropping packet!"); } } Err(e) => { @@ -249,6 +204,7 @@ impl MemoryNetwork { master_map: master_map.clone(), in_flight_message_count, metrics: NetworkingMetrics::new(&*metrics), + reliability_config, }), }; master_map.map.insert(pub_key, mn.clone()); @@ -347,20 +303,40 @@ impl ConnectedNetwork for Memory .context(FailedToSerializeSnafu)?; trace!("Message bincoded, sending"); for node in &self.inner.master_map.map { + // TODO delay/drop etc here let (key, node) = node.pair(); if !recipients.contains(key) { continue; } trace!(?key, "Sending message to node"); - let res = node.broadcast_input(vec.clone()).await; - match res { - Ok(_) => { - self.inner.metrics.outgoing_message_count.add(1); - trace!(?key, "Delivered message to remote"); + if let Some(r) = &self.inner.reliability_config { + let config = r.read().await; + { + let node2 = node.clone(); + let fut = config.chaos_send_msg( + vec.clone(), + Arc::new(move |msg: Vec| { + let node3 = (node2).clone(); + boxed_sync(async move { + let _res = node3.broadcast_input(msg).await; + // NOTE we're dropping metrics here but this is only for testing + // purposes. I think that should be okay + }) + }), + ); + async_spawn(fut); } - Err(e) => { - self.inner.metrics.message_failed_to_send.add(1); - warn!(?e, ?key, "Error sending broadcast message to node"); + } else { + let res = node.broadcast_input(vec.clone()).await; + match res { + Ok(_) => { + self.inner.metrics.outgoing_message_count.add(1); + trace!(?key, "Delivered message to remote"); + } + Err(e) => { + self.inner.metrics.message_failed_to_send.add(1); + warn!(?e, ?key, "Error sending broadcast message to node"); + } } } } @@ -376,18 +352,37 @@ impl ConnectedNetwork for Memory .context(FailedToSerializeSnafu)?; trace!("Message bincoded, finding recipient"); if let Some(node) = self.inner.master_map.map.get(&recipient) { - let node = node.value(); - let res = node.direct_input(vec).await; - match res { - Ok(_) => { - self.inner.metrics.outgoing_message_count.add(1); - trace!(?recipient, "Delivered message to remote"); - Ok(()) + let node = node.value().clone(); + if let Some(r) = &self.inner.reliability_config { + let config = r.read().await; + { + let fut = config.chaos_send_msg( + vec.clone(), + Arc::new(move |msg: Vec| { + let node2 = node.clone(); + boxed_sync(async move { + let _res = node2.broadcast_input(msg).await; + // NOTE we're dropping metrics here but this is only for testing + // purposes. I think that should be okay + }) + }), + ); + async_spawn(fut); } - Err(e) => { - self.inner.metrics.message_failed_to_send.add(1); - warn!(?e, ?recipient, "Error delivering direct message"); - Err(NetworkError::CouldNotDeliver) + Ok(()) + } else { + let res = node.direct_input(vec).await; + match res { + Ok(_) => { + self.inner.metrics.outgoing_message_count.add(1); + trace!(?recipient, "Delivered message to remote"); + Ok(()) + } + Err(e) => { + self.inner.metrics.message_failed_to_send.add(1); + warn!(?e, ?recipient, "Error delivering direct message"); + Err(NetworkError::CouldNotDeliver) + } } } } else { diff --git a/crates/testing/src/network_reliability.rs b/crates/testing/src/network_reliability.rs deleted file mode 100644 index 97b22b533b..0000000000 --- a/crates/testing/src/network_reliability.rs +++ /dev/null @@ -1,163 +0,0 @@ -use std::time::Duration; - -use hotshot::traits::NetworkReliability; -use rand::{ - distributions::{Bernoulli, Uniform}, - prelude::Distribution, -}; - -/// A synchronous network. Packets may be delayed, but are guaranteed -/// to arrive within `timeout` ns -#[derive(Clone, Copy, Debug, Default)] -pub struct SynchronousNetwork { - /// Max delay of packet before arrival - timeout_ms: u64, - /// Lowest value in milliseconds that a packet may be delayed - delay_low_ms: u64, -} - -impl NetworkReliability for SynchronousNetwork { - /// never drop a packet - fn sample_keep(&self) -> bool { - true - } - fn sample_delay(&self) -> Duration { - Duration::from_millis( - Uniform::new_inclusive(self.delay_low_ms, self.timeout_ms) - .sample(&mut rand::thread_rng()), - ) - } -} - -/// An asynchronous network. Packets may be dropped entirely -/// or delayed for arbitrarily long periods -/// probability that packet is kept = `keep_numerator` / `keep_denominator` -/// packet delay is obtained by sampling from a uniform distribution -/// between `delay_low_ms` and `delay_high_ms`, inclusive -#[derive(Debug, Clone, Copy)] -pub struct AsynchronousNetwork { - /// numerator for probability of keeping packets - keep_numerator: u32, - /// denominator for probability of keeping packets - keep_denominator: u32, - /// lowest value in milliseconds that a packet may be delayed - delay_low_ms: u64, - /// highest value in milliseconds that a packet may be delayed - delay_high_ms: u64, -} - -impl NetworkReliability for AsynchronousNetwork { - fn sample_keep(&self) -> bool { - Bernoulli::from_ratio(self.keep_numerator, self.keep_denominator) - .unwrap() - .sample(&mut rand::thread_rng()) - } - fn sample_delay(&self) -> Duration { - Duration::from_millis( - Uniform::new_inclusive(self.delay_low_ms, self.delay_high_ms) - .sample(&mut rand::thread_rng()), - ) - } -} - -/// An partially synchronous network. Behaves asynchronously -/// until some arbitrary time bound, GST, -/// then synchronously after GST -#[derive(Debug, Clone, Copy)] -pub struct PartiallySynchronousNetwork { - /// asynchronous portion of network - asynchronous: AsynchronousNetwork, - /// synchronous portion of network - synchronous: SynchronousNetwork, - /// time when GST occurs - gst: std::time::Duration, - /// when the network was started - start: std::time::Instant, -} - -impl NetworkReliability for PartiallySynchronousNetwork { - /// never drop a packet - fn sample_keep(&self) -> bool { - true - } - fn sample_delay(&self) -> Duration { - // act asyncronous before gst - if self.start.elapsed() < self.gst { - if self.asynchronous.sample_keep() { - self.asynchronous.sample_delay() - } else { - // assume packet was "dropped" and will arrive after gst - self.synchronous.sample_delay() + self.gst - } - } else { - // act syncronous after gst - self.synchronous.sample_delay() - } - } -} - -impl Default for AsynchronousNetwork { - // disable all chance of failure - fn default() -> Self { - AsynchronousNetwork { - keep_numerator: 1, - keep_denominator: 1, - delay_low_ms: 0, - delay_high_ms: 0, - } - } -} - -impl Default for PartiallySynchronousNetwork { - fn default() -> Self { - PartiallySynchronousNetwork { - synchronous: SynchronousNetwork::default(), - asynchronous: AsynchronousNetwork::default(), - gst: std::time::Duration::new(0, 0), - start: std::time::Instant::now(), - } - } -} - -impl SynchronousNetwork { - /// create new `SynchronousNetwork` - pub fn new(timeout: u64, delay_low_ms: u64) -> Self { - SynchronousNetwork { - timeout_ms: timeout, - delay_low_ms, - } - } -} - -impl AsynchronousNetwork { - /// create new `AsynchronousNetwork` - pub fn new( - keep_numerator: u32, - keep_denominator: u32, - delay_low_ms: u64, - delay_high_ms: u64, - ) -> Self { - AsynchronousNetwork { - keep_numerator, - keep_denominator, - delay_low_ms, - delay_high_ms, - } - } -} - -impl PartiallySynchronousNetwork { - /// create new `PartiallySynchronousNetwork` - pub fn new( - asynchronous: AsynchronousNetwork, - synchronous: SynchronousNetwork, - gst: std::time::Duration, - ) -> Self { - PartiallySynchronousNetwork { - asynchronous, - synchronous, - gst, - start: std::time::Instant::now(), - } - } -} diff --git a/crates/types/src/traits/network.rs b/crates/types/src/traits/network.rs index ef02b05245..1729636836 100644 --- a/crates/types/src/traits/network.rs +++ b/crates/types/src/traits/network.rs @@ -2,9 +2,10 @@ //! //! Contains types and traits used by `HotShot` to abstract over network access +use async_compatibility_layer::art::async_sleep; #[cfg(async_executor_impl = "async-std")] use async_std::future::TimeoutError; -use hotshot_task::BoxSyncFuture; +use hotshot_task::{boxed_sync, BoxSyncFuture}; use libp2p_networking::network::NetworkNodeHandleError; #[cfg(async_executor_impl = "tokio")] use tokio::time::error::Elapsed as TimeoutError; @@ -14,6 +15,10 @@ use super::{election::Membership, node_implementation::NodeType, signature_key:: use crate::{data::ViewNumber, message::MessagePurpose}; use async_compatibility_layer::channel::UnboundedSendError; use async_trait::async_trait; +use rand::{ + distributions::{Bernoulli, Uniform}, + prelude::Distribution, +}; use serde::{Deserialize, Serialize}; use snafu::Snafu; use std::{collections::BTreeSet, fmt::Debug, sync::Arc, time::Duration}; @@ -366,6 +371,7 @@ pub enum NetworkChange { } /// interface describing how reliable the network is +#[async_trait] pub trait NetworkReliability: Debug + Sync + std::marker::Send { /// Sample from bernoulli distribution to decide whether /// or not to keep a packet @@ -373,8 +379,225 @@ pub trait NetworkReliability: Debug + Sync + std::marker::Send { /// /// Panics if `self.keep_numerator > self.keep_denominator` /// - fn sample_keep(&self) -> bool; + fn sample_keep(&self) -> bool { + true + } + /// sample from uniform distribution to decide whether /// or not to keep a packet - fn sample_delay(&self) -> Duration; + fn sample_delay(&self) -> Duration { + std::time::Duration::ZERO + } + + /// scramble the packet + fn scramble(&self, msg: Vec) -> Vec { + msg + } + + /// number of times to repeat the packet + fn sample_repeat(&self) -> usize { + 1 + } + + /// given a message and a way to send the message, + /// decide whether or not to send the message + /// how long to delay the message + /// whether or not to send duplicates + /// and whether or not to include noise with the message + /// then send the message + fn chaos_send_msg( + &self, + msg: Vec, + send_fn: Arc) -> BoxSyncFuture<'static, ()>>, + ) -> BoxSyncFuture<'static, ()> { + let sample_keep = self.sample_keep(); + let delay = self.sample_delay(); + let repeats = self.sample_repeat(); + let mut msgs = Vec::new(); + for _idx in 0..repeats { + let scrambled = self.scramble(msg.clone()); + msgs.push(scrambled); + } + let closure = async move { + if sample_keep { + async_sleep(delay).await; + for msg in msgs { + send_fn(msg).await; + } + } + }; + boxed_sync(closure) + } +} + +/// ideal network +#[derive(Clone, Copy, Debug, Default)] +pub struct PerfectNetwork {} + +impl NetworkReliability for PerfectNetwork {} + +/// A synchronous network. Packets may be delayed, but are guaranteed +/// to arrive within `timeout` ns +#[derive(Clone, Copy, Debug, Default)] +pub struct SynchronousNetwork { + /// Max delay of packet before arrival + timeout_ms: u64, + /// Lowest value in milliseconds that a packet may be delayed + delay_low_ms: u64, +} + +impl NetworkReliability for SynchronousNetwork { + /// never drop a packet + fn sample_keep(&self) -> bool { + true + } + fn sample_delay(&self) -> Duration { + Duration::from_millis( + Uniform::new_inclusive(self.delay_low_ms, self.timeout_ms) + .sample(&mut rand::thread_rng()), + ) + } +} + +/// An asynchronous network. Packets may be dropped entirely +/// or delayed for arbitrarily long periods +/// probability that packet is kept = `keep_numerator` / `keep_denominator` +/// packet delay is obtained by sampling from a uniform distribution +/// between `delay_low_ms` and `delay_high_ms`, inclusive +#[derive(Debug, Clone, Copy)] +pub struct AsynchronousNetwork { + /// numerator for probability of keeping packets + keep_numerator: u32, + /// denominator for probability of keeping packets + keep_denominator: u32, + /// lowest value in milliseconds that a packet may be delayed + delay_low_ms: u64, + /// highest value in milliseconds that a packet may be delayed + delay_high_ms: u64, +} + +impl NetworkReliability for AsynchronousNetwork { + fn sample_keep(&self) -> bool { + Bernoulli::from_ratio(self.keep_numerator, self.keep_denominator) + .unwrap() + .sample(&mut rand::thread_rng()) + } + fn sample_delay(&self) -> Duration { + Duration::from_millis( + Uniform::new_inclusive(self.delay_low_ms, self.delay_high_ms) + .sample(&mut rand::thread_rng()), + ) + } +} + +/// An partially synchronous network. Behaves asynchronously +/// until some arbitrary time bound, GST, +/// then synchronously after GST +#[allow(clippy::similar_names)] +#[derive(Debug, Clone, Copy)] +pub struct PartiallySynchronousNetwork { + /// asynchronous portion of network + asynchronous: AsynchronousNetwork, + /// synchronous portion of network + synchronous: SynchronousNetwork, + /// time when GST occurs + gst: std::time::Duration, + /// when the network was started + start: std::time::Instant, +} + +impl NetworkReliability for PartiallySynchronousNetwork { + /// never drop a packet + fn sample_keep(&self) -> bool { + true + } + fn sample_delay(&self) -> Duration { + // act asyncronous before gst + if self.start.elapsed() < self.gst { + if self.asynchronous.sample_keep() { + self.asynchronous.sample_delay() + } else { + // assume packet was "dropped" and will arrive after gst + self.synchronous.sample_delay() + self.gst + } + } else { + // act syncronous after gst + self.synchronous.sample_delay() + } + } +} + +impl Default for AsynchronousNetwork { + // disable all chance of failure + fn default() -> Self { + AsynchronousNetwork { + keep_numerator: 1, + keep_denominator: 1, + delay_low_ms: 0, + delay_high_ms: 0, + } + } +} + +impl Default for PartiallySynchronousNetwork { + fn default() -> Self { + PartiallySynchronousNetwork { + synchronous: SynchronousNetwork::default(), + asynchronous: AsynchronousNetwork::default(), + gst: std::time::Duration::new(0, 0), + start: std::time::Instant::now(), + } + } +} + +impl SynchronousNetwork { + /// create new `SynchronousNetwork` + #[must_use] + pub fn new(timeout: u64, delay_low_ms: u64) -> Self { + SynchronousNetwork { + timeout_ms: timeout, + delay_low_ms, + } + } +} + +impl AsynchronousNetwork { + /// create new `AsynchronousNetwork` + #[must_use] + pub fn new( + keep_numerator: u32, + keep_denominator: u32, + delay_low_ms: u64, + delay_high_ms: u64, + ) -> Self { + AsynchronousNetwork { + keep_numerator, + keep_denominator, + delay_low_ms, + delay_high_ms, + } + } +} + +impl PartiallySynchronousNetwork { + /// create new `PartiallySynchronousNetwork` + #[allow(clippy::similar_names)] + #[must_use] + pub fn new( + asynchronous: AsynchronousNetwork, + synchronous: SynchronousNetwork, + gst: std::time::Duration, + ) -> Self { + PartiallySynchronousNetwork { + asynchronous, + synchronous, + gst, + start: std::time::Instant::now(), + } + } +} + +/// A chaotic network using all the networking calls +pub struct ChaosNetwork { + // TODO } From aad8fc5de84f0dbdec8a68ff59929001fd2fa60b Mon Sep 17 00:00:00 2001 From: Brendon Fish Date: Mon, 2 Oct 2023 11:03:43 -0400 Subject: [PATCH 07/20] log why we don't vote at INFO level --- crates/task-impls/src/consensus.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/task-impls/src/consensus.rs b/crates/task-impls/src/consensus.rs index 3c3ba5abd7..9b5491f43e 100644 --- a/crates/task-impls/src/consensus.rs +++ b/crates/task-impls/src/consensus.rs @@ -45,7 +45,7 @@ use std::{ }; #[cfg(async_executor_impl = "tokio")] use tokio::task::JoinHandle; -use tracing::{debug, error, instrument}; +use tracing::{debug, error, instrument, info}; /// Error returned by the consensus task #[derive(Snafu, Debug)] @@ -456,13 +456,13 @@ where } } } - debug!( + info!( "Couldn't find DAC cert in certs, meaning we haven't received it yet for view {:?}", *proposal.get_view_number(), ); return false; } - debug!( + info!( "Could not vote because we don't have a proposal yet for view {}", *self.cur_view ); From 6b1ef1a3cb78c2cb5a3cc148bff7049de307519a Mon Sep 17 00:00:00 2001 From: Keyao Shen Date: Mon, 2 Oct 2023 14:17:23 -0700 Subject: [PATCH 08/20] Remove index nonzero check, rename hightest_index --- crates/task-impls/src/consensus.rs | 2 +- crates/web_server/src/lib.rs | 32 ++++++++++-------------------- 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/crates/task-impls/src/consensus.rs b/crates/task-impls/src/consensus.rs index 9b5491f43e..b4a38db5e5 100644 --- a/crates/task-impls/src/consensus.rs +++ b/crates/task-impls/src/consensus.rs @@ -45,7 +45,7 @@ use std::{ }; #[cfg(async_executor_impl = "tokio")] use tokio::task::JoinHandle; -use tracing::{debug, error, instrument, info}; +use tracing::{debug, error, info, instrument}; /// Error returned by the consensus task #[derive(Snafu, Debug)] diff --git a/crates/web_server/src/lib.rs b/crates/web_server/src/lib.rs index 861c6a5a67..ac2730b448 100644 --- a/crates/web_server/src/lib.rs +++ b/crates/web_server/src/lib.rs @@ -280,11 +280,11 @@ impl WebServerDataSource for WebServerState { self.oldest_vote += 1; } } - let highest_index = self.vote_index.entry(view_number).or_insert(0); + let next_index = self.vote_index.entry(view_number).or_insert(0); self.votes .entry(view_number) - .and_modify(|current_votes| current_votes.push((*highest_index, vote.clone()))) - .or_insert_with(|| vec![(*highest_index, vote)]); + .and_modify(|current_votes| current_votes.push((*next_index, vote.clone()))) + .or_insert_with(|| vec![(*next_index, vote)]); self.vote_index .entry(view_number) .and_modify(|index| *index += 1); @@ -302,19 +302,14 @@ impl WebServerDataSource for WebServerState { self.oldest_view_sync_vote += 1; } } - let highest_index = self.view_sync_vote_index.entry(view_number).or_insert(0); + let next_index = self.view_sync_vote_index.entry(view_number).or_insert(0); self.view_sync_votes .entry(view_number) - .and_modify(|current_votes| current_votes.push((*highest_index, vote.clone()))) - .or_insert_with(|| vec![(*highest_index, vote)]); + .and_modify(|current_votes| current_votes.push((*next_index, vote.clone()))) + .or_insert_with(|| vec![(*next_index, vote)]); self.view_sync_vote_index .entry(view_number) - .and_modify(|index| { - // Update the index if it's not just added. - if *index > 0 { - *index += 1 - } - }); + .and_modify(|index| *index += 1); Ok(()) } /// Stores a received proposal in the `WebServerState` @@ -351,22 +346,17 @@ impl WebServerDataSource for WebServerState { self.oldest_view_sync_proposal += 1; } } - let highest_index = self + let next_index = self .view_sync_proposal_index .entry(view_number) .or_insert(0); self.view_sync_proposals .entry(view_number) - .and_modify(|current_props| current_props.push((*highest_index, proposal.clone()))) - .or_insert_with(|| vec![(*highest_index, proposal)]); + .and_modify(|current_props| current_props.push((*next_index, proposal.clone()))) + .or_insert_with(|| vec![(*next_index, proposal)]); self.view_sync_proposal_index .entry(view_number) - .and_modify(|index| { - // Update the index if it's not just added. - if *index > 0 { - *index += 1 - } - }); + .and_modify(|index| *index += 1); Ok(()) } From 03c90ac55d184548f4fa1cfa0bcf284edc0558d1 Mon Sep 17 00:00:00 2001 From: Jeb Bearer Date: Mon, 2 Oct 2023 17:24:01 -0400 Subject: [PATCH 09/20] Decrease network task polling frequency from 500ns to 100ms (#1853) * Decrease network task polling frequency from 500ns to 100ms * Fix format * increase webserver test duration --------- Co-authored-by: Rob --- crates/hotshot/src/tasks/mod.rs | 4 ++-- crates/task-impls/src/consensus.rs | 2 +- crates/testing/tests/web_server.rs | 8 ++++++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/crates/hotshot/src/tasks/mod.rs b/crates/hotshot/src/tasks/mod.rs index 5415bad8ea..1b411c35d2 100644 --- a/crates/hotshot/src/tasks/mod.rs +++ b/crates/hotshot/src/tasks/mod.rs @@ -162,7 +162,7 @@ where .expect("Failed to receive broadcast messages"), ); if msgs.0.is_empty() { - async_sleep(Duration::new(0, 500)).await; + async_sleep(Duration::from_millis(100)).await; } else { break msgs; } @@ -182,7 +182,7 @@ where .expect("Failed to receive direct messages"), ); if msgs.0.is_empty() { - async_sleep(Duration::new(0, 500)).await; + async_sleep(Duration::from_millis(100)).await; } else { break msgs; } diff --git a/crates/task-impls/src/consensus.rs b/crates/task-impls/src/consensus.rs index 9b5491f43e..b4a38db5e5 100644 --- a/crates/task-impls/src/consensus.rs +++ b/crates/task-impls/src/consensus.rs @@ -45,7 +45,7 @@ use std::{ }; #[cfg(async_executor_impl = "tokio")] use tokio::task::JoinHandle; -use tracing::{debug, error, instrument, info}; +use tracing::{debug, error, info, instrument}; /// Error returned by the consensus task #[derive(Snafu, Debug)] diff --git a/crates/testing/tests/web_server.rs b/crates/testing/tests/web_server.rs index 75d0e4f89c..9b19532902 100644 --- a/crates/testing/tests/web_server.rs +++ b/crates/testing/tests/web_server.rs @@ -1,5 +1,8 @@ +use std::time::Duration; + use async_compatibility_layer::logging::shutdown_logging; use hotshot_testing::{ + completion_task::{CompletionTaskDescription, TimeBasedCompletionTaskDescription}, node_types::{SequencingTestTypes, SequencingWebImpl}, overall_safety_task::OverallSafetyPropertiesDescription, test_builder::{TestMetadata, TimingData}, @@ -28,6 +31,11 @@ async fn web_server_network() { num_successful_views: 35, ..Default::default() }, + completion_task_description: CompletionTaskDescription::TimeBasedCompletionTaskBuilder( + TimeBasedCompletionTaskDescription { + duration: Duration::from_secs(20), + }, + ), ..TestMetadata::default() }; metadata From fe1d06a9280098b33a481d0c639961cd83c72a16 Mon Sep 17 00:00:00 2001 From: Keyao Shen Date: Tue, 3 Oct 2023 18:02:04 -0700 Subject: [PATCH 10/20] Update logging --- crates/task-impls/src/da.rs | 2 +- crates/task-impls/src/view_sync.rs | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/task-impls/src/da.rs b/crates/task-impls/src/da.rs index 4037e07a23..b6244c972a 100644 --- a/crates/task-impls/src/da.rs +++ b/crates/task-impls/src/da.rs @@ -604,7 +604,7 @@ where match result { Err(_) => { // Fall through below to updating new block - error!( + debug!( "propose_max_round_time passed, sending transactions we have so far" ); } diff --git a/crates/task-impls/src/view_sync.rs b/crates/task-impls/src/view_sync.rs index eafeb7a468..3ff00b6cf0 100644 --- a/crates/task-impls/src/view_sync.rs +++ b/crates/task-impls/src/view_sync.rs @@ -781,6 +781,7 @@ where let phase = self.phase.clone(); async move { async_sleep(self.view_sync_timeout).await; + error!("Vote sending timed out in ViewSyncCertificateRecv"); stream .publish(SequencingHotShotEvent::ViewSyncTimeout( TYPES::Time::new(*self.next_view), @@ -842,6 +843,7 @@ where let stream = self.event_stream.clone(); async move { async_sleep(self.view_sync_timeout).await; + error!("Vote sending timed out in ViewSyncTrigger"); stream .publish(SequencingHotShotEvent::ViewSyncTimeout( TYPES::Time::new(*self.next_view), @@ -912,6 +914,7 @@ where let stream = self.event_stream.clone(); async move { async_sleep(self.view_sync_timeout).await; + error!("Vote sending timed out in ViewSyncTimeout"); stream .publish(SequencingHotShotEvent::ViewSyncTimeout( TYPES::Time::new(*self.next_view), From 8ce1a01e5d3660efcf88071f0337360b817783cb Mon Sep 17 00:00:00 2001 From: Keyao Shen Date: Tue, 3 Oct 2023 18:04:48 -0700 Subject: [PATCH 11/20] Fix a task name --- crates/task-impls/src/view_sync.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/task-impls/src/view_sync.rs b/crates/task-impls/src/view_sync.rs index 3ff00b6cf0..ad9191f3f1 100644 --- a/crates/task-impls/src/view_sync.rs +++ b/crates/task-impls/src/view_sync.rs @@ -543,7 +543,8 @@ where let name = format!( "View Sync Replica Task: Attempting to enter view {:?} from view {:?}", - self.next_view, self.current_view + *view_number + 1, + *view_number ); let replica_handle_event = HandleEvent(Arc::new( From 517c688fe090402a89d166641edd0c293e1c107d Mon Sep 17 00:00:00 2001 From: Brendon Fish Date: Tue, 3 Oct 2023 23:29:55 -0400 Subject: [PATCH 12/20] Subscribe to web server when starting view sync --- crates/task-impls/src/view_sync.rs | 48 +++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/crates/task-impls/src/view_sync.rs b/crates/task-impls/src/view_sync.rs index eafeb7a468..1b5417722b 100644 --- a/crates/task-impls/src/view_sync.rs +++ b/crates/task-impls/src/view_sync.rs @@ -299,19 +299,20 @@ where } // We do not have a replica task already running, so start one - let mut replica_state = ViewSyncReplicaTaskState { - current_view: certificate_internal.round, - next_view: certificate_internal.round, - relay: 0, - finalized: false, - sent_view_change_event: false, - phase: ViewSyncPhase::None, - exchange: self.exchange.clone(), - api: self.api.clone(), - event_stream: self.event_stream.clone(), - view_sync_timeout: self.view_sync_timeout, - id: self.id, - }; + let mut replica_state: ViewSyncReplicaTaskState = + ViewSyncReplicaTaskState { + current_view: certificate_internal.round, + next_view: certificate_internal.round, + relay: 0, + finalized: false, + sent_view_change_event: false, + phase: ViewSyncPhase::None, + exchange: self.exchange.clone(), + api: self.api.clone(), + event_stream: self.event_stream.clone(), + view_sync_timeout: self.view_sync_timeout, + id: self.id, + }; let result = replica_state.handle_event(event.clone()).await; @@ -514,10 +515,29 @@ where .await; // panic!("Starting view sync!"); // Spawn replica task + let next_view = *view_number + 1; + // Subscribe to the next view just in case there is progress being made + self.exchange + .network() + .inject_consensus_info(ConsensusIntentEvent::PollForProposal(next_view)) + .await; + + self.exchange + .network() + .inject_consensus_info(ConsensusIntentEvent::PollForDAC(next_view)) + .await; + + if self.exchange.is_leader(TYPES::Time::new(next_view + 1)) { + debug!("Polling for quorum votes for view {}", next_view); + self.exchange + .network() + .inject_consensus_info(ConsensusIntentEvent::PollForVotes(next_view)) + .await; + } let mut replica_state = ViewSyncReplicaTaskState { current_view: self.current_view, - next_view: TYPES::Time::new(*view_number + 1), + next_view: TYPES::Time::new(next_view), relay: 0, finalized: false, sent_view_change_event: false, From 96a61a1ddb536279458f6bd6744ef425a7a154a8 Mon Sep 17 00:00:00 2001 From: Keyao Shen Date: Wed, 4 Oct 2023 17:37:38 -0700 Subject: [PATCH 13/20] Remove commitment check in is_valid_cert, update state even is missing parent leaf. --- crates/task-impls/src/consensus.rs | 330 +++++++++++++++------------- crates/types/src/traits/election.rs | 9 +- 2 files changed, 185 insertions(+), 154 deletions(-) diff --git a/crates/task-impls/src/consensus.rs b/crates/task-impls/src/consensus.rs index b4a38db5e5..3f2551245a 100644 --- a/crates/task-impls/src/consensus.rs +++ b/crates/task-impls/src/consensus.rs @@ -429,8 +429,13 @@ where // Validate the DAC. if self .committee_exchange - .is_valid_cert(cert, proposal.block_commitment) + .is_valid_cert(cert) { + // Validate the block commitment for non-genesis DAC. + if !cert.is_genesis() && cert.leaf_commitment() != proposal.block_commitment { + error!("Block commitment does not equal parent commitment"); + return false; + } self.quorum_exchange.create_yes_message( proposal.justify_qc.commit(), leaf.commit(), @@ -567,7 +572,6 @@ where Ok(Some(vote_token)) => { debug!("We were chosen for consensus committee on {:?}", view); let consensus = self.consensus.upgradable_read().await; - let message; // TODO ED Insert TC logic here @@ -582,111 +586,147 @@ where .cloned() }; - // Justify qc's leaf commitment is not the same as the parent's leaf commitment, but it should be (in this case) - let Some(parent) = parent else { - error!( - "Proposal's parent missing from storage with commitment: {:?}", - justify_qc.leaf_commitment() - ); - return; - }; - let parent_commitment = parent.commit(); - let leaf: SequencingLeaf<_> = SequencingLeaf { - view_number: view, - height: proposal.data.height, - justify_qc: justify_qc.clone(), - parent_commitment, - deltas: Right(proposal.data.block_commitment), - rejected: Vec::new(), - timestamp: time::OffsetDateTime::now_utc().unix_timestamp_nanos(), - proposer_id: sender.to_bytes(), - }; + // Validate the `justify_qc`. let justify_qc_commitment = justify_qc.commit(); - let leaf_commitment = leaf.commit(); + let invalid = !self.quorum_exchange.is_valid_cert(&justify_qc); + let leaf; - // Validate the `justify_qc`. - if !self - .quorum_exchange - .is_valid_cert(&justify_qc, parent_commitment) - { - error!("Invalid justify_qc in proposal!. parent commitment is {:?} justify qc is {:?}", parent_commitment, justify_qc.clone()); + // Justify qc's leaf commitment is not the same as the parent's leaf commitment, but it should be (in this case) + if let Some(parent) = parent { + let message; + leaf = SequencingLeaf { + view_number: view, + height: proposal.data.height, + justify_qc: justify_qc.clone(), + parent_commitment: parent.commit(), + deltas: Right(proposal.data.block_commitment), + rejected: Vec::new(), + timestamp: time::OffsetDateTime::now_utc().unix_timestamp_nanos(), + proposer_id: sender.to_bytes(), + }; + let parent_commitment = parent.commit(); + let leaf_commitment = leaf.commit(); - message = self.quorum_exchange.create_no_message::( - justify_qc_commitment, - leaf_commitment, - view, - vote_token, - ); - } - // Validate the `height`. - else if leaf.height != parent.height + 1 { - error!( - "Incorrect height in proposal (expected {}, got {})", - parent.height + 1, - leaf.height - ); - message = self.quorum_exchange.create_no_message( - justify_qc_commitment, - leaf_commitment, - view, - vote_token, - ); - } - // Validate the signature. - else if !view_leader_key - .validate(&proposal.signature, leaf_commitment.as_ref()) - { - error!(?proposal.signature, "Could not verify proposal."); - message = self.quorum_exchange.create_no_message( - justify_qc_commitment, - leaf_commitment, - view, - vote_token, - ); - } - // Create a positive vote if either liveness or safety check - // passes. - else { - // Liveness check. - let liveness_check = justify_qc.view_number > consensus.locked_view; - - // Safety check. - // Check if proposal extends from the locked leaf. - let outcome = consensus.visit_leaf_ancestors( - justify_qc.view_number, - Terminator::Inclusive(consensus.locked_view), - false, - |leaf| { - // if leaf view no == locked view no then we're done, report success by - // returning true - leaf.view_number != consensus.locked_view - }, - ); - let safety_check = outcome.is_ok(); - if let Err(e) = outcome { - self.api.send_view_error(view, Arc::new(e)).await; - } + if invalid { + error!("Invalid justify_qc in proposal! parent commitment is {:?} justify qc is {:?}", parent_commitment, justify_qc.clone()); - // Skip if both saftey and liveness checks fail. - if !safety_check && !liveness_check { - error!("Failed safety check and liveness check"); + message = self.quorum_exchange.create_no_message::( + justify_qc_commitment, + leaf_commitment, + view, + vote_token, + ); + } + // Validate the leaf commitment for non-genesis QC. + else if !justify_qc.is_genesis() + && justify_qc.leaf_commitment() != parent_commitment + { + error!("Leaf commitment does not equal parent commitment"); + message = self.quorum_exchange.create_no_message::( + justify_qc_commitment, + leaf_commitment, + view, + vote_token, + ); + } + // Validate the `height`. + else if leaf.height != parent.height + 1 { + error!( + "Incorrect height in proposal (expected {}, got {})", + parent.height + 1, + leaf.height + ); message = self.quorum_exchange.create_no_message( justify_qc_commitment, leaf_commitment, view, vote_token, ); - } else { - // Generate a message with yes vote. - message = self.quorum_exchange.create_yes_message( + } + // Validate the signature. + else if !view_leader_key + .validate(&proposal.signature, leaf_commitment.as_ref()) + { + error!(?proposal.signature, "Could not verify proposal."); + message = self.quorum_exchange.create_no_message( justify_qc_commitment, leaf_commitment, view, vote_token, ); } + // Create a positive vote if either liveness or safety check + // passes. + // Liveness check. + else { + let liveness_check = justify_qc.view_number > consensus.locked_view; + + // Safety check. + // Check if proposal extends from the locked leaf. + let outcome = consensus.visit_leaf_ancestors( + justify_qc.view_number, + Terminator::Inclusive(consensus.locked_view), + false, + |leaf| { + // if leaf view no == locked view no then we're done, report success by + // returning true + leaf.view_number != consensus.locked_view + }, + ); + let safety_check = outcome.is_ok(); + if let Err(e) = outcome { + self.api.send_view_error(view, Arc::new(e)).await; + } + + // Skip if both saftey and liveness checks fail. + if !safety_check && !liveness_check { + error!("Failed safety check and liveness check"); + message = self.quorum_exchange.create_no_message( + justify_qc_commitment, + leaf_commitment, + view, + vote_token, + ); + } + // Generate a message with yes vote. + else { + message = self.quorum_exchange.create_yes_message( + justify_qc_commitment, + leaf_commitment, + view, + vote_token, + ); + } + } + + if let GeneralConsensusMessage::Vote(vote) = message { + debug!("Sending vote to next leader {:?}", vote); + }; + } else { + // Allow missing parent so we can update the state, but we won't + // vote in this case. + error!( + "Proposal's parent missing from storage with commitment: {:?}", + justify_qc.leaf_commitment() + ); + + if invalid { + error!("Invalid justify_qc in proposal {:?}", justify_qc.clone()); + } + leaf = SequencingLeaf { + view_number: view, + height: proposal.data.height, + justify_qc: justify_qc.clone(), + parent_commitment: justify_qc.leaf_commitment(), + deltas: Right(proposal.data.block_commitment), + rejected: Vec::new(), + timestamp: time::OffsetDateTime::now_utc().unix_timestamp_nanos(), + proposer_id: sender.to_bytes(), + }; } + // TODO (Keyao) Update consensus state only if all verifications pass. + // let high_qc = leaf.justify_qc.clone(); let mut new_anchor_view = consensus.last_decided_view; let mut new_locked_view = consensus.locked_view; @@ -702,64 +742,64 @@ where if parent_view + 1 == view { current_chain_length += 1; if let Err(e) = consensus.visit_leaf_ancestors( - parent_view, - Terminator::Exclusive(old_anchor_view), - true, - |leaf| { - if !new_decide_reached { - if last_view_number_visited == leaf.view_number + 1 { - last_view_number_visited = leaf.view_number; - current_chain_length += 1; - if current_chain_length == 2 { - new_locked_view = leaf.view_number; - new_commit_reached = true; - // The next leaf in the chain, if there is one, is decided, so this - // leaf's justify_qc would become the QC for the decided chain. - new_decide_qc = Some(leaf.justify_qc.clone()); - } else if current_chain_length == 3 { - new_anchor_view = leaf.view_number; - new_decide_reached = true; - } - } else { - // nothing more to do here... we don't have a new chain extension - return false; - } - } - // starting from the first iteration with a three chain, e.g. right after the else if case nested in the if case above - if new_decide_reached { - let mut leaf = leaf.clone(); - - // If the full block is available for this leaf, include it in the leaf - // chain that we send to the client. - if let Some(block) = - consensus.saved_blocks.get(leaf.get_deltas_commitment()) - { - if let Err(err) = leaf.fill_deltas(block.clone()) { - error!("unable to fill leaf {} with block {}, block will not be available: {}", - leaf.commit(), block.commit(), err); + parent_view, + Terminator::Exclusive(old_anchor_view), + true, + |leaf| { + if !new_decide_reached { + if last_view_number_visited == leaf.view_number + 1 { + last_view_number_visited = leaf.view_number; + current_chain_length += 1; + if current_chain_length == 2 { + new_locked_view = leaf.view_number; + new_commit_reached = true; + // The next leaf in the chain, if there is one, is decided, so this + // leaf's justify_qc would become the QC for the decided chain. + new_decide_qc = Some(leaf.justify_qc.clone()); + } else if current_chain_length == 3 { + new_anchor_view = leaf.view_number; + new_decide_reached = true; + } + } else { + // nothing more to do here... we don't have a new chain extension + return false; + } } - } - - leaf_views.push(leaf.clone()); - match &leaf.deltas { - Left(block) => { - let txns = block.contained_transactions(); - for txn in txns { - included_txns.insert(txn); + // starting from the first iteration with a three chain, e.g. right after the else if case nested in the if case above + if new_decide_reached { + let mut leaf = leaf.clone(); + + // If the full block is available for this leaf, include it in the leaf + // chain that we send to the client. + if let Some(block) = + consensus.saved_blocks.get(leaf.get_deltas_commitment()) + { + if let Err(err) = leaf.fill_deltas(block.clone()) { + error!("unable to fill leaf {} with block {}, block will not be available: {}", + leaf.commit(), block.commit(), err); + } + } + + leaf_views.push(leaf.clone()); + match &leaf.deltas { + Left(block) => { + let txns = block.contained_transactions(); + for txn in txns { + included_txns.insert(txn); + } + } + Right(_) => {} } } - Right(_) => {} + true + }, + ) { + error!("publishing view error"); + self.output_event_stream.publish(Event { + view_number: view, + event: EventType::Error { error: e.into() }, + }).await; } - } - true - }, - ) { - error!("publishing view error"); - self.output_event_stream.publish(Event { - view_number: view, - event: EventType::Error { error: e.into() }, - }).await; - } } let included_txns_set: HashSet<_> = if new_decide_reached { @@ -883,10 +923,6 @@ where // Update current view and publish a view change event so other tasks also update self.update_view(new_view).await; - - if let GeneralConsensusMessage::Vote(vote) = message { - debug!("Sending vote to next leader {:?}", vote); - }; } } } diff --git a/crates/types/src/traits/election.rs b/crates/types/src/traits/election.rs index 81a173e954..fdc435163b 100644 --- a/crates/types/src/traits/election.rs +++ b/crates/types/src/traits/election.rs @@ -342,18 +342,13 @@ pub trait ConsensusExchange: Send + Sync { /// The contents of a vote on `commit`. fn vote_data(&self, commit: Commitment) -> VoteData; - /// Validate a QC. - fn is_valid_cert(&self, qc: &Self::Certificate, commit: Commitment) -> bool { + /// Validate a certificate. + fn is_valid_cert(&self, qc: &Self::Certificate) -> bool { if qc.is_genesis() && qc.view_number() == TYPES::Time::genesis() { return true; } let leaf_commitment = qc.leaf_commitment(); - if leaf_commitment != commit { - error!("Leaf commitment does not equal parent commitment"); - return false; - } - match qc.signatures() { AssembledSignature::DA(qc) => { let real_commit = VoteData::DA(leaf_commitment).commit(); From 6579a5b83276f1b3aaab92ee78834af1979380fd Mon Sep 17 00:00:00 2001 From: Keyao Shen Date: Wed, 4 Oct 2023 20:01:54 -0700 Subject: [PATCH 14/20] Check ancestors only if having parent leaf --- crates/task-impls/src/consensus.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/crates/task-impls/src/consensus.rs b/crates/task-impls/src/consensus.rs index 3f2551245a..268249518c 100644 --- a/crates/task-impls/src/consensus.rs +++ b/crates/task-impls/src/consensus.rs @@ -592,7 +592,7 @@ where let leaf; // Justify qc's leaf commitment is not the same as the parent's leaf commitment, but it should be (in this case) - if let Some(parent) = parent { + if let Some(parent) = parent.clone() { let message; leaf = SequencingLeaf { view_number: view, @@ -736,12 +736,13 @@ where let mut new_decide_qc = None; let mut leaf_views = Vec::new(); let mut included_txns = HashSet::new(); - let old_anchor_view = consensus.last_decided_view; - let parent_view = leaf.justify_qc.view_number; - let mut current_chain_length = 0usize; - if parent_view + 1 == view { - current_chain_length += 1; - if let Err(e) = consensus.visit_leaf_ancestors( + if parent.is_some() { + let old_anchor_view = consensus.last_decided_view; + let parent_view = leaf.justify_qc.view_number; + let mut current_chain_length = 0usize; + if parent_view + 1 == view { + current_chain_length += 1; + if let Err(e) = consensus.visit_leaf_ancestors( parent_view, Terminator::Exclusive(old_anchor_view), true, @@ -800,6 +801,7 @@ where event: EventType::Error { error: e.into() }, }).await; } + } } let included_txns_set: HashSet<_> = if new_decide_reached { @@ -904,7 +906,7 @@ where drop(consensus); if should_propose { debug!( - "Attempting to publish proposal after voting; now in view: {}", + "Attempting to publish proposal before voting; now in view: {}", *new_view ); self.publish_proposal_if_able(qc.clone(), qc.view_number + 1) From 5f2a69de33c699d1e4074493f18977dd4dc7caf5 Mon Sep 17 00:00:00 2001 From: Brendon Fish Date: Thu, 5 Oct 2023 10:03:46 -0400 Subject: [PATCH 15/20] store leaf and return if missing parent, fix subscribe in view sync --- crates/task-impls/src/consensus.rs | 38 +++++++++++++++++++++++++----- crates/task-impls/src/view_sync.rs | 20 ++++++++-------- 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/crates/task-impls/src/consensus.rs b/crates/task-impls/src/consensus.rs index 268249518c..12d7313075 100644 --- a/crates/task-impls/src/consensus.rs +++ b/crates/task-impls/src/consensus.rs @@ -339,8 +339,9 @@ where // Justify qc's leaf commitment is not the same as the parent's leaf commitment, but it should be (in this case) let Some(parent) = parent else { error!( - "Proposal's parent missing from storage with commitment: {:?}", - justify_qc.leaf_commitment() + "Proposal's parent missing from storage with commitment: {:?}, proposal view {:?}", + justify_qc.leaf_commitment(), + proposal.view_number, ); return false; }; @@ -408,8 +409,9 @@ where // Justify qc's leaf commitment is not the same as the parent's leaf commitment, but it should be (in this case) let Some(parent) = parent else { error!( - "Proposal's parent missing from storage with commitment: {:?}", - justify_qc.leaf_commitment() + "Proposal's parent missing from storage with commitment: {:?}, proposal view {:?}", + justify_qc.leaf_commitment(), + proposal.view_number, ); return false; }; @@ -706,12 +708,14 @@ where // Allow missing parent so we can update the state, but we won't // vote in this case. error!( - "Proposal's parent missing from storage with commitment: {:?}", - justify_qc.leaf_commitment() + "Proposal's parent missing from storage with commitment: {:?}, proposal view {:?}", + justify_qc.leaf_commitment(), + proposal.data.view_number, ); if invalid { error!("Invalid justify_qc in proposal {:?}", justify_qc.clone()); + return; } leaf = SequencingLeaf { view_number: view, @@ -723,6 +727,28 @@ where timestamp: time::OffsetDateTime::now_utc().unix_timestamp_nanos(), proposer_id: sender.to_bytes(), }; + if !view_leader_key + .validate(&proposal.signature, leaf.commit().as_ref()) + { + error!(?proposal.signature, "Could not verify proposal."); + return; + } + + let mut consensus = RwLockUpgradableReadGuard::upgrade(consensus).await; + consensus.state_map.insert( + view, + View { + view_inner: ViewInner::Leaf { + leaf: leaf.commit(), + }, + }, + ); + consensus.saved_leaves.insert(leaf.commit(), leaf.clone()); + drop(consensus); + // The valid QC and signature on the proposal is evidence we can go to the next view + // even though we can't vote in this round because we missed the last proposal. + self.update_view(TYPES::Time::new(*view + 1)).await; + return; } // TODO (Keyao) Update consensus state only if all verifications pass. diff --git a/crates/task-impls/src/view_sync.rs b/crates/task-impls/src/view_sync.rs index e35ec6f399..da52ceaf82 100644 --- a/crates/task-impls/src/view_sync.rs +++ b/crates/task-impls/src/view_sync.rs @@ -516,25 +516,25 @@ where // panic!("Starting view sync!"); // Spawn replica task let next_view = *view_number + 1; + // Subscribe to the view after we are leader since we know we won't propose in the next view if we are leader. + let subscribe_view = if self.exchange.is_leader(TYPES::Time::new(next_view)) { + next_view + 1 + } else { + next_view + }; // Subscribe to the next view just in case there is progress being made self.exchange .network() - .inject_consensus_info(ConsensusIntentEvent::PollForProposal(next_view)) + .inject_consensus_info(ConsensusIntentEvent::PollForProposal( + subscribe_view, + )) .await; self.exchange .network() - .inject_consensus_info(ConsensusIntentEvent::PollForDAC(next_view)) + .inject_consensus_info(ConsensusIntentEvent::PollForDAC(subscribe_view)) .await; - if self.exchange.is_leader(TYPES::Time::new(next_view + 1)) { - debug!("Polling for quorum votes for view {}", next_view); - self.exchange - .network() - .inject_consensus_info(ConsensusIntentEvent::PollForVotes(next_view)) - .await; - } - let mut replica_state = ViewSyncReplicaTaskState { current_view: self.current_view, next_view: TYPES::Time::new(next_view), From 2065da93413d18c6362958db8b02be91a09d5c57 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 8 Oct 2023 00:18:58 +0000 Subject: [PATCH 16/20] flake.lock: Update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'fenix': 'github:nix-community/fenix/3116ee073ab3931c78328ca126224833c95e6227' (2023-09-30) → 'github:nix-community/fenix/6e3bc9460b51a4602b7e85746ec3e3988b8bd8c9' (2023-10-07) • Updated input 'fenix/rust-analyzer-src': 'github:rust-lang/rust-analyzer/4791a5de21735e3d9414d131a4f973da9bae0537' (2023-09-29) → 'github:rust-lang/rust-analyzer/b1f89a84ab350091e6c20cfe30c2fab8d76b80e4' (2023-10-06) • Updated input 'flake-compat': 'github:edolstra/flake-compat/35bb57c0c8d8b62bbfd284272c928ceb64ddbde9' (2023-01-17) → 'github:edolstra/flake-compat/0f9255e01c2351cc7d116c072cb317785dd33b33' (2023-10-04) • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/bd9b686c0168041aea600222be0805a0de6e6ab8' (2023-09-29) → 'github:NixOS/nixpkgs/2de1be5b51c3d6fa833f1c1f222dc867dd054b31' (2023-10-07) --- flake.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/flake.lock b/flake.lock index 99bccee207..c170fd09d4 100644 --- a/flake.lock +++ b/flake.lock @@ -41,11 +41,11 @@ "rust-analyzer-src": "rust-analyzer-src" }, "locked": { - "lastModified": 1696054802, - "narHash": "sha256-VTON/WlYeyzFoYwwsb8KveqJJCfWEI6NtZYHcAFKBuo=", + "lastModified": 1696659643, + "narHash": "sha256-HO1VCcwEe3jlEIUlSv1jFwt/ILw1fWxP0g8S9kRsous=", "owner": "nix-community", "repo": "fenix", - "rev": "3116ee073ab3931c78328ca126224833c95e6227", + "rev": "6e3bc9460b51a4602b7e85746ec3e3988b8bd8c9", "type": "github" }, "original": { @@ -57,11 +57,11 @@ "flake-compat": { "flake": false, "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", "owner": "edolstra", "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", "type": "github" }, "original": { @@ -72,11 +72,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1695978539, - "narHash": "sha256-lta5HToBZMWZ2hl5CautNSUgIZViR41QxN7JKbMAjgQ=", + "lastModified": 1696661029, + "narHash": "sha256-GIB5VTkvsDIqfMpdtuetOzpm64P8wm8nBSv5Eo8XM3Y=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "bd9b686c0168041aea600222be0805a0de6e6ab8", + "rev": "2de1be5b51c3d6fa833f1c1f222dc867dd054b31", "type": "github" }, "original": { @@ -99,11 +99,11 @@ "rust-analyzer-src": { "flake": false, "locked": { - "lastModified": 1696014495, - "narHash": "sha256-TcDFXRK9weJ1yCQyo6zxRhLfYHe/GcXDbSUpiszNCuw=", + "lastModified": 1696592032, + "narHash": "sha256-kY1temv39OjasB81KHdoMqpxh21F3kStwxE51eqViJ0=", "owner": "rust-lang", "repo": "rust-analyzer", - "rev": "4791a5de21735e3d9414d131a4f973da9bae0537", + "rev": "b1f89a84ab350091e6c20cfe30c2fab8d76b80e4", "type": "github" }, "original": { From 34c9d01edca58a0acea1741265e8e4f189268fbe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Oct 2023 09:06:45 -0400 Subject: [PATCH 17/20] Bump styfle/cancel-workflow-action from 0.11.0 to 0.12.0 (#1861) Bumps [styfle/cancel-workflow-action](https://github.com/styfle/cancel-workflow-action) from 0.11.0 to 0.12.0. - [Release notes](https://github.com/styfle/cancel-workflow-action/releases) - [Commits](https://github.com/styfle/cancel-workflow-action/compare/0.11.0...0.12.0) --- updated-dependencies: - dependency-name: styfle/cancel-workflow-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- .github/workflows/build_arm_nix.yml | 2 +- .github/workflows/build_nix.yml | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/doc.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 151e8a8a50..f2899484dd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,7 +22,7 @@ jobs: - tokio runs-on: ubuntu-latest steps: - - uses: styfle/cancel-workflow-action@0.11.0 + - uses: styfle/cancel-workflow-action@0.12.0 name: Cancel Outdated Builds with: all_but_latest: true diff --git a/.github/workflows/build_arm_nix.yml b/.github/workflows/build_arm_nix.yml index 44878cdefe..b1f76073af 100644 --- a/.github/workflows/build_arm_nix.yml +++ b/.github/workflows/build_arm_nix.yml @@ -20,7 +20,7 @@ jobs: volumes: - github_nix:/nix steps: - - uses: styfle/cancel-workflow-action@0.11.0 + - uses: styfle/cancel-workflow-action@0.12.0 name: Cancel Outdated Builds with: all_but_latest: true diff --git a/.github/workflows/build_nix.yml b/.github/workflows/build_nix.yml index a98c9ae2b4..cceee336f3 100644 --- a/.github/workflows/build_nix.yml +++ b/.github/workflows/build_nix.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 120 steps: - - uses: styfle/cancel-workflow-action@0.11.0 + - uses: styfle/cancel-workflow-action@0.12.0 name: Cancel Outdated Builds with: all_but_latest: true diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 5dd6b32725..304e2fd377 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -9,7 +9,7 @@ jobs: code-coverage: runs-on: ubuntu-latest steps: - - uses: styfle/cancel-workflow-action@0.11.0 + - uses: styfle/cancel-workflow-action@0.12.0 name: Cancel Outdated Builds with: all_but_latest: true diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index bb6f576711..5df5b3430f 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 35 steps: - - uses: styfle/cancel-workflow-action@0.11.0 + - uses: styfle/cancel-workflow-action@0.12.0 name: Cancel Outdated Builds with: all_but_latest: true From 11fd017e3dbbce24bef67bfd0ba7598efddac62f Mon Sep 17 00:00:00 2001 From: elliedavidson <118024407+elliedavidson@users.noreply.github.com> Date: Mon, 9 Oct 2023 11:14:59 -0400 Subject: [PATCH 18/20] merge with main --- .github/workflows/build.yml | 62 +- .github/workflows/lints.yml | 36 - .gitignore | 1 + Cargo.lock | 686 +++++++++--------- Cargo.toml | 98 +-- crates/constants/Cargo.toml | 5 + crates/constants/src/lib.rs | 10 + crates/hotshot-qc/Cargo.toml | 2 +- crates/hotshot-signature-key/src/bn254.rs | 6 +- .../src/bn254/bn254_priv.rs | 8 +- .../src/bn254/bn254_pub.rs | 37 +- crates/hotshot-stake-table/Cargo.toml | 2 +- crates/hotshot/Cargo.toml | 30 +- crates/hotshot/examples/infra/mod.rs | 5 +- crates/hotshot/examples/infra/modDA.rs | 520 ++++++++----- .../examples/libp2p/multi-validator.rs | 69 ++ .../hotshot/examples/libp2p/orchestrator.rs | 24 +- crates/hotshot/examples/libp2p/types.rs | 83 ++- crates/hotshot/examples/libp2p/validator.rs | 30 +- .../examples/web-server-da/multi-validator.rs | 4 +- .../web-server-da/multi-web-server.rs | 8 +- .../examples/web-server-da/orchestrator.rs | 4 +- .../hotshot/examples/web-server-da/types.rs | 57 +- .../examples/web-server-da/validator.rs | 4 +- .../examples/web-server-da/web-server.rs | 4 +- crates/hotshot/src/demo.rs | 207 ++++++ crates/hotshot/src/demos.rs | 8 - crates/hotshot/src/demos/sdemo.rs | 384 ---------- crates/hotshot/src/demos/vdemo.rs | 607 ---------------- crates/hotshot/src/lib.rs | 82 +-- crates/hotshot/src/tasks/mod.rs | 184 ++--- crates/hotshot/src/traits.rs | 4 +- .../src/traits/election/static_committee.rs | 44 +- .../src/traits/networking/libp2p_network.rs | 245 +++---- .../src/traits/networking/memory_network.rs | 577 +++------------ .../networking/web_server_libp2p_fallback.rs | 66 +- .../traits/networking/web_server_network.rs | 169 +++-- .../networking/web_sever_libp2p_fallback.rs | 318 -------- .../src/traits/storage/atomic_storage.rs | 16 +- .../atomic_storage/dual_key_value_store.rs | 6 +- .../src/traits/storage/memory_storage.rs | 11 +- crates/hotshot/src/types/handle.rs | 8 +- crates/libp2p-networking/Cargo.toml | 11 +- .../src/network/behaviours/dht/cache.rs | 325 +++++++++ .../network/behaviours/{dht.rs => dht/mod.rs} | 52 +- .../src/network/behaviours/gossip.rs | 12 +- crates/libp2p-networking/src/network/node.rs | 7 +- .../src/network/node/config.rs | 4 + .../src/network/node/handle.rs | 18 +- crates/libp2p-networking/tests/counter.rs | 4 +- crates/orchestrator/Cargo.toml | 4 +- .../default-libp2p-run-config.toml | 18 +- crates/orchestrator/default-run-config.toml | 4 +- .../default-web-server-run-config.toml | 4 +- crates/orchestrator/src/config.rs | 46 +- crates/orchestrator/src/lib.rs | 19 +- crates/task-impls/Cargo.toml | 3 +- crates/task-impls/src/consensus.rs | 231 +++--- crates/task-impls/src/da.rs | 486 +++++++------ crates/task-impls/src/events.rs | 40 +- crates/task-impls/src/lib.rs | 3 + crates/task-impls/src/network.rs | 64 +- crates/task-impls/src/transactions.rs | 417 +++++++++++ crates/task-impls/src/view_sync.rs | 85 ++- crates/task/Cargo.toml | 1 - crates/testing/Cargo.toml | 2 +- crates/testing/README.md | 2 +- crates/testing/src/network_reliability.rs | 163 ----- crates/testing/src/node_types.rs | 192 +++-- crates/testing/src/overall_safety_task.rs | 8 +- crates/testing/src/spinning_task.rs | 3 +- crates/testing/src/task_helpers.rs | 37 +- crates/testing/src/test_builder.rs | 9 +- crates/testing/src/test_launcher.rs | 4 - crates/testing/src/test_runner.rs | 11 +- crates/testing/tests/atomic_storage.rs | 72 +- crates/testing/tests/basic.rs | 12 +- crates/testing/tests/catchup.rs | 62 +- crates/testing/tests/da_task.rs | 84 ++- crates/testing/tests/memory_network.rs | 371 ++++++++++ crates/testing/tests/network_task.rs | 62 +- crates/testing/tests/timeout.rs | 2 +- crates/types/Cargo.toml | 18 +- crates/types/src/block_impl.rs | 127 ++++ crates/types/src/certificate.rs | 94 ++- crates/types/src/consensus.rs | 16 +- crates/types/src/constants.rs | 14 - crates/types/src/data.rs | 126 +++- crates/types/src/event.rs | 3 +- crates/types/src/lib.rs | 6 +- crates/types/src/message.rs | 72 +- crates/types/src/traits.rs | 2 +- crates/types/src/traits/block_contents.rs | 63 +- crates/types/src/traits/consensus_api.rs | 19 +- crates/types/src/traits/election.rs | 433 ++++++----- crates/types/src/traits/network.rs | 283 +++++++- .../types/src/traits/node_implementation.rs | 34 +- crates/types/src/traits/signature_key.rs | 34 +- crates/types/src/traits/state.rs | 22 +- crates/types/src/traits/storage.rs | 10 +- crates/types/src/vote.rs | 576 +++++++++++++-- crates/web_server/Cargo.toml | 3 - crates/web_server/api.toml | 7 + crates/web_server/src/config.rs | 28 + crates/web_server/src/lib.rs | 15 + docs/espresso-sequencer-paper.pdf | Bin 868752 -> 791332 bytes flake.lock | 36 +- flake.nix | 3 +- justfile | 18 +- testing-macros/Cargo.toml | 1 - testing-macros/src/lib.rs | 6 +- testing-macros/tests/integration/failures.rs | 4 +- testing-macros/tests/integration/smoke.rs | 4 +- 113 files changed, 5350 insertions(+), 4412 deletions(-) delete mode 100644 .github/workflows/lints.yml create mode 100644 crates/constants/Cargo.toml create mode 100644 crates/constants/src/lib.rs create mode 100644 crates/hotshot/examples/libp2p/multi-validator.rs create mode 100644 crates/hotshot/src/demo.rs delete mode 100644 crates/hotshot/src/demos.rs delete mode 100644 crates/hotshot/src/demos/sdemo.rs delete mode 100644 crates/hotshot/src/demos/vdemo.rs delete mode 100644 crates/hotshot/src/traits/networking/web_sever_libp2p_fallback.rs create mode 100644 crates/libp2p-networking/src/network/behaviours/dht/cache.rs rename crates/libp2p-networking/src/network/behaviours/{dht.rs => dht/mod.rs} (94%) create mode 100644 crates/task-impls/src/transactions.rs delete mode 100644 crates/testing/src/network_reliability.rs create mode 100644 crates/testing/tests/memory_network.rs create mode 100644 crates/types/src/block_impl.rs delete mode 100644 crates/types/src/constants.rs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e387389168..151e8a8a50 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,4 +1,4 @@ -name: Build and Test Workflow +name: Build, Lint, and Test on: push: @@ -33,6 +33,9 @@ jobs: - uses: Swatinem/rust-cache@v2 name: Enable Rust Caching + with: + shared-key: "" + prefix-key: ${{ matrix.just_variants }} - name: Install dependencies run: | @@ -40,8 +43,9 @@ jobs: sudo apt-get install -y protobuf-compiler cargo install just - - name: Check - run: just ${{ matrix.just_variants }} check + - name: Run linting + run: | + just ${{ matrix.just_variants }} lint - name: Build all crates in workspace run: just ${{ matrix.just_variants }} build @@ -53,32 +57,32 @@ jobs: env: RUST_BACKTRACE: full - - name: Setup Docker BuildKit (buildx) - if: matrix.just_variants == 'async_std' - uses: docker/setup-buildx-action@v2 + # - name: Setup Docker BuildKit (buildx) + # if: matrix.just_variants == 'async_std' + # uses: docker/setup-buildx-action@v3 - - name: Login to Github Container Repo - uses: docker/login-action@v2 - if: github.event_name != 'pull_request' && matrix.just_variants == 'async_std' - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} + # - name: Login to Github Container Repo + # uses: docker/login-action@v3 + # if: github.event_name != 'pull_request' && matrix.just_variants == 'async_std' + # with: + # registry: ghcr.io + # username: ${{ github.repository_owner }} + # password: ${{ secrets.GITHUB_TOKEN }} - - name: Generate docker metadata (web-server) - uses: docker/metadata-action@v4 - if: matrix.just_variants == 'async_std' - id: web-server - with: - images: ghcr.io/espressosystems/hotshot/web-server + # - name: Generate docker metadata (web-server) + # uses: docker/metadata-action@v5 + # if: matrix.just_variants == 'async_std' + # id: web-server + # with: + # images: ghcr.io/espressosystems/hotshot/web-server - - name: Build and push web-server docker - uses: docker/build-push-action@v4 - if: matrix.just_variants == 'async_std' - with: - context: ./ - file: ./deploy/web-server.Dockerfile - platforms: linux/amd64 - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.web-server.outputs.tags }} - labels: ${{ steps.web-server.outputs.labels }} + # - name: Build and push web-server docker + # uses: docker/build-push-action@v5 + # if: matrix.just_variants == 'async_std' + # with: + # context: ./ + # file: ./deploy/web-server.Dockerfile + # platforms: linux/amd64 + # push: ${{ github.event_name != 'pull_request' }} + # tags: ${{ steps.web-server.outputs.tags }} + # labels: ${{ steps.web-server.outputs.labels }} diff --git a/.github/workflows/lints.yml b/.github/workflows/lints.yml deleted file mode 100644 index 9ab7bf8c03..0000000000 --- a/.github/workflows/lints.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: Lints Workflow - -on: - push: - branches: - - 'main' - pull_request: - branches: - - 'main' - - '*/*' - workflow_dispatch: - -jobs: - lints: - runs-on: ubuntu-latest - timeout-minutes: 25 - steps: - - uses: styfle/cancel-workflow-action@0.11.0 - name: Cancel Outdated Builds - with: - all_but_latest: true - access_token: ${{ github.token }} - - - name: Install Nix - uses: cachix/install-nix-action@v23 - - - uses: actions/checkout@v4 - name: Checkout Repository - - - name: Format Check - run: cargo fmt -- --check - - - name: Clippy - run: | - nix develop -c just async_std lint - nix develop -c just tokio lint diff --git a/.gitignore b/.gitignore index 839d85dc3d..ff07ca5941 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ /target_dirs /.vscode/settings.json **/.DS_Store +*.cache \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 617fb4165d..64bc01b7ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -140,9 +140,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.0.5" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c378d78423fdad8089616f827526ee33c19f2fddbd5de1629152c9593ba4783" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] @@ -164,9 +164,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.5.0" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" dependencies = [ "anstyle", "anstyle-parse", @@ -178,15 +178,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c4c2c83f81532e5845a733998b6971faca23490340a418e9b72a3ec9de12ea" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] name = "anstyle-parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" dependencies = [ "utf8parse", ] @@ -202,9 +202,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "2.1.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" dependencies = [ "anstyle", "windows-sys", @@ -575,7 +575,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", - "event-listener", + "event-listener 2.5.3", "futures-core", ] @@ -611,14 +611,14 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.5.1" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb" +checksum = "2c1da3ae8dabd9c00f453a329dfe1fb28da3c0a72e2478cdcd93171740c20499" dependencies = [ "async-lock", "async-task", "concurrent-queue", - "fastrand", + "fastrand 2.0.1", "futures-lite", "slab", ] @@ -680,7 +680,7 @@ dependencies = [ "log", "parking", "polling", - "rustix", + "rustix 0.37.24", "slab", "socket2 0.4.9", "waker-fn", @@ -692,36 +692,52 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" dependencies = [ - "event-listener", + "event-listener 2.5.3", ] [[package]] name = "async-net" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4051e67316bc7eff608fe723df5d32ed639946adcd69e07df41fd42a7b411f1f" +checksum = "0434b1ed18ce1cf5769b8ac540e33f01fa9471058b5e89da9e06f3c882a8c12f" dependencies = [ "async-io", - "autocfg", "blocking", "futures-lite", ] [[package]] name = "async-process" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9" +checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" dependencies = [ "async-io", "async-lock", - "autocfg", + "async-signal", "blocking", "cfg-if", - "event-listener", + "event-listener 3.0.0", "futures-lite", - "rustix", - "signal-hook", + "rustix 0.38.18", + "windows-sys", +] + +[[package]] +name = "async-signal" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1079d27511f6c038736279421774ef4ad4bdd2e300825f4a48c4cc463a57cedf" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 0.38.18", + "signal-hook-registry", + "slab", "windows-sys", ] @@ -782,33 +798,11 @@ dependencies = [ "trust-dns-resolver", ] -[[package]] -name = "async-stream" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" -dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite 0.2.13", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.31", -] - [[package]] name = "async-task" -version = "4.4.0" +version = "4.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" +checksum = "b9441c6b2fe128a7c2bf680a44c34d0df31ce09e5b7e401fcca3faa483dbc921" [[package]] name = "async-trait" @@ -818,7 +812,7 @@ checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.38", ] [[package]] @@ -854,7 +848,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4057f2c32adbb2fc158e22fb38433c8e9bbf76b75a4732c7c0cbaf695fb65568" dependencies = [ - "bytes 1.4.0", + "bytes 1.5.0", "futures-sink", "futures-util", "memchr", @@ -863,9 +857,9 @@ dependencies = [ [[package]] name = "atomic-waker" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "atomic_enum" @@ -893,7 +887,7 @@ dependencies = [ "async-trait", "axum-core", "bitflags 1.3.2", - "bytes 1.4.0", + "bytes 1.5.0", "futures-util", "http", "http-body", @@ -919,7 +913,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" dependencies = [ "async-trait", - "bytes 1.4.0", + "bytes 1.5.0", "futures-util", "http", "http-body", @@ -964,9 +958,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.3" +version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "414dcefbc63d77c526a76b3afcf6fbb9b5e2791c19c3aa2297733208750c6e53" +checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" [[package]] name = "base64ct" @@ -989,12 +983,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - [[package]] name = "bitflags" version = "1.3.2" @@ -1063,17 +1051,18 @@ dependencies = [ [[package]] name = "blocking" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65" +checksum = "8c36a4d0d48574b3dd360b4b7d95cc651d2b6557b6402848a27d4b228a473e2a" dependencies = [ "async-channel", "async-lock", "async-task", - "atomic-waker", - "fastrand", + "fastrand 2.0.1", + "futures-io", "futures-lite", - "log", + "piper", + "tracing", ] [[package]] @@ -1097,9 +1086,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "byte-slice-cast" @@ -1109,9 +1098,9 @@ checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" @@ -1121,9 +1110,9 @@ checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" dependencies = [ "serde", ] @@ -1194,9 +1183,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.28" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ed24df0632f708f5f6d8082675bef2596f7084dee3dd55f632290bf35bfe0f" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" dependencies = [ "android-tzdata", "iana-time-zone", @@ -1236,9 +1225,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.5" +version = "4.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824956d0dca8334758a5b7f7e50518d66ea319330cbceedcf76905c2f6ab30e3" +checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" dependencies = [ "clap_builder", "clap_derive", @@ -1246,9 +1235,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.5" +version = "4.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "122ec64120a49b4563ccaedcbea7818d069ed8e9aa6d829b82d8a4128936b2ab" +checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" dependencies = [ "anstream", "anstyle", @@ -1265,7 +1254,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.38", ] [[package]] @@ -1310,7 +1299,7 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "commit" version = "0.2.2" -source = "git+https://github.com/EspressoSystems/commit?tag=0.2.2#7e938186607f87da5fd642ce36313aaeab0cfaca" +source = "git+https://github.com/EspressoSystems/commit#5f1c28f1a109f2b36cf597e61a222614958db3b2" dependencies = [ "arbitrary", "ark-serialize 0.3.0", @@ -1318,18 +1307,17 @@ dependencies = [ "derivative", "derive_more", "funty", - "generic-array", "hex", "serde", "sha3", - "tagged-base64 0.2.4", + "tagged-base64 0.3.1", ] [[package]] name = "concurrent-queue" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" +checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" dependencies = [ "crossbeam-utils", ] @@ -1421,7 +1409,7 @@ checksum = "03a5d7b21829bc7b4bf4754a978a241ae54ea55a40f92bb20216e54096f4b951" dependencies = [ "aes-gcm 0.8.0", "base64 0.13.1", - "hkdf", + "hkdf 0.10.0", "hmac 0.10.1", "percent-encoding", "rand 0.8.5", @@ -1572,17 +1560,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "704722d1d929489c8528bb1882805700f1ba20f54325704973e786352320b1ed" dependencies = [ "blake2", - "curve25519-dalek 4.0.0", + "curve25519-dalek 4.1.1", "rand_core 0.6.4", "serdect", ] -[[package]] -name = "ct-codecs" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3b7eb4404b8195a9abb6356f4ac07d8ba267045c8d6d220ac4dc992e6cc75df" - [[package]] name = "ctr" version = "0.6.0" @@ -1629,9 +1611,9 @@ dependencies = [ [[package]] name = "curl-sys" -version = "0.4.65+curl-8.2.1" +version = "0.4.67+curl-8.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "961ba061c9ef2fe34bbd12b807152d96f0badd2bebe7b90ce6c8c8b7572a0986" +checksum = "3cc35d066510b197a0f72de863736641539957628c8a42e70e27c66849e77c34" dependencies = [ "cc", "libc", @@ -1640,7 +1622,7 @@ dependencies = [ "openssl-sys", "pkg-config", "vcpkg", - "winapi", + "windows-sys", ] [[package]] @@ -1658,9 +1640,9 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.0.0" +version = "4.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f711ade317dd348950a9910f81c5947e3d8907ebd2b83f76203ff1807e6a2bc2" +checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" dependencies = [ "cfg-if", "cpufeatures", @@ -1681,7 +1663,7 @@ checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.38", ] [[package]] @@ -1749,7 +1731,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.31", + "syn 2.0.38", ] [[package]] @@ -1771,7 +1753,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core 0.20.3", "quote", - "syn 2.0.31", + "syn 2.0.38", ] [[package]] @@ -1781,7 +1763,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown 0.14.0", + "hashbrown 0.14.1", "lock_api", "once_cell", "parking_lot_core", @@ -1865,7 +1847,7 @@ checksum = "53e0efad4403bfc52dc201159c4b842a246a14b98c64b55dfd0f2d89729dfeb8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.38", ] [[package]] @@ -1987,7 +1969,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.38", ] [[package]] @@ -2016,9 +1998,9 @@ checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" [[package]] name = "dyn-clone" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfc4744c1b8f2a09adc0e55242f60b1af195d88596bd8700be74418c056c555" +checksum = "23d2f3407d9a573d666de4b5bdf10569d73ca9478087346697dcbae6244bfbcd" [[package]] name = "ed25519" @@ -2030,23 +2012,13 @@ dependencies = [ "signature", ] -[[package]] -name = "ed25519-compact" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a3d382e8464107391c8706b4c14b087808ecb909f6c15c34114bc42e53a9e4c" -dependencies = [ - "ct-codecs", - "getrandom 0.2.10", -] - [[package]] name = "ed25519-dalek" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7277392b266383ef8396db7fdeb1e77b6c52fed775f5df15bb24f35b72156980" dependencies = [ - "curve25519-dalek 4.0.0", + "curve25519-dalek 4.1.1", "ed25519", "rand_core 0.6.4", "serde", @@ -2119,25 +2091,14 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" +checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" dependencies = [ - "errno-dragonfly", "libc", "windows-sys", ] -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "espresso-systems-common" version = "0.4.0" @@ -2181,6 +2142,17 @@ version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +[[package]] +name = "event-listener" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29e56284f00d94c1bc7fd3c77027b4623c88c1f53d8d2394c6199f2921dea325" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite 0.2.13", +] + [[package]] name = "eyre" version = "0.6.8" @@ -2200,11 +2172,17 @@ dependencies = [ "instant", ] +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + [[package]] name = "fiat-crypto" -version = "0.1.20" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77" +checksum = "d0870c84016d4b481be5c9f323c24f65e31e901ae618f0e80f4308fb00de1d2d" [[package]] name = "fixed-hash" @@ -2327,7 +2305,7 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" dependencies = [ - "fastrand", + "fastrand 1.9.0", "futures-core", "futures-io", "memchr", @@ -2344,7 +2322,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.38", ] [[package]] @@ -2489,7 +2467,7 @@ version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" dependencies = [ - "bytes 1.4.0", + "bytes 1.5.0", "fnv", "futures-core", "futures-sink", @@ -2522,9 +2500,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" [[package]] name = "hdrhistogram" @@ -2547,9 +2525,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "hex" @@ -2573,6 +2551,15 @@ dependencies = [ "hmac 0.10.1", ] +[[package]] +name = "hkdf" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" +dependencies = [ + "hmac 0.12.1", +] + [[package]] name = "hmac" version = "0.8.1" @@ -2593,6 +2580,15 @@ dependencies = [ "digest 0.9.0", ] +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "hmac-drbg" version = "0.3.0" @@ -2637,6 +2633,7 @@ dependencies = [ "espresso-systems-common 0.4.1", "ethereum-types", "futures", + "hotshot-constants", "hotshot-orchestrator", "hotshot-signature-key", "hotshot-task", @@ -2644,10 +2641,10 @@ dependencies = [ "hotshot-types", "hotshot-utils", "hotshot-web-server", + "jf-primitives", "libp2p", "libp2p-identity", "libp2p-networking", - "nll", "rand 0.8.5", "rand_chacha 0.3.1", "serde", @@ -2661,6 +2658,10 @@ dependencies = [ "typenum", ] +[[package]] +name = "hotshot-constants" +version = "0.3.3" + [[package]] name = "hotshot-orchestrator" version = "0.1.1" @@ -2678,7 +2679,6 @@ dependencies = [ "libp2p", "libp2p-core", "libp2p-networking", - "nll", "serde", "serde_json", "snafu", @@ -2770,7 +2770,6 @@ dependencies = [ "atomic_enum", "either", "futures", - "nll", "pin-project", "serde", "snafu", @@ -2785,7 +2784,6 @@ dependencies = [ "async-compatibility-layer", "async-lock", "async-std", - "async-stream", "async-trait", "atomic_enum", "bincode", @@ -2793,11 +2791,11 @@ dependencies = [ "commit", "either", "futures", + "hotshot-constants", "hotshot-task", "hotshot-types", "hotshot-utils", "jf-primitives", - "nll", "pin-project", "rand_chacha 0.3.1", "serde", @@ -2816,6 +2814,7 @@ dependencies = [ "async-lock", "async-std", "async-trait", + "bincode", "bitvec", "blake3", "commit", @@ -2828,7 +2827,6 @@ dependencies = [ "hotshot-types", "hotshot-utils", "jf-primitives", - "nll", "rand 0.8.5", "rand_chacha 0.3.1", "serde", @@ -2842,6 +2840,7 @@ name = "hotshot-types" version = "0.1.0" dependencies = [ "arbitrary", + "ark-bls12-381", "ark-serialize 0.3.0", "ark-std 0.4.0", "async-compatibility-layer", @@ -2849,7 +2848,6 @@ dependencies = [ "async-std", "async-trait", "bincode", - "bit-vec", "bitvec", "blake3", "commit", @@ -2857,22 +2855,24 @@ dependencies = [ "derivative", "digest 0.10.7", "displaydoc", - "ed25519-compact", "either", "espresso-systems-common 0.4.1", "ethereum-types", "futures", "generic-array", "hex_fmt", + "hotshot-constants", "hotshot-task", "hotshot-utils", "jf-primitives", + "jf-utils", "libp2p-networking", - "nll", "rand 0.8.5", "rand_chacha 0.3.1", "serde", "serde_json", + "sha2 0.10.8", + "sha3", "snafu", "tagged-base64 0.2.4", "time 0.3.29", @@ -2904,13 +2904,10 @@ dependencies = [ "hotshot-utils", "jf-primitives", "libp2p-core", - "nll", - "portpicker", "rand 0.8.5", "serde", "serde_json", "snafu", - "surf-disco", "tide", "tide-disco 0.4.1 (git+https://github.com/EspressoSystems/tide-disco.git?tag=v0.4.1)", "tokio", @@ -2924,7 +2921,7 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" dependencies = [ - "bytes 1.4.0", + "bytes 1.5.0", "fnv", "itoa 1.0.9", ] @@ -2935,7 +2932,7 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ - "bytes 1.4.0", + "bytes 1.5.0", "http", "pin-project-lite 0.2.13", ] @@ -3000,7 +2997,7 @@ version = "0.14.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" dependencies = [ - "bytes 1.4.0", + "bytes 1.5.0", "futures-channel", "futures-core", "futures-util", @@ -3186,12 +3183,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" dependencies = [ "equivalent", - "hashbrown 0.14.0", + "hashbrown 0.14.1", "serde", ] @@ -3216,7 +3213,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f97967975f448f1a7ddb12b0bc41069d09ed6a1c161a92687e057325db35d413" dependencies = [ - "bytes 1.4.0", + "bytes 1.5.0", ] [[package]] @@ -3245,7 +3242,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" dependencies = [ - "socket2 0.5.3", + "socket2 0.5.4", "widestring", "windows-sys", "winreg", @@ -3313,7 +3310,7 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "jf-primitives" version = "0.4.0-pre.0" -source = "git+https://github.com/EspressoSystems/jellyfish#30752c6c1af7b933e2536d7aeb991a40af4b806a" +source = "git+https://github.com/EspressoSystems/jellyfish#1626a8448e7af8ea153241004375deff9fd961da" dependencies = [ "anyhow", "ark-bls12-377", @@ -3337,7 +3334,6 @@ dependencies = [ "digest 0.10.7", "displaydoc", "espresso-systems-common 0.4.0", - "generic-array", "hashbrown 0.13.2", "itertools 0.10.5", "jf-relation", @@ -3358,7 +3354,7 @@ dependencies = [ [[package]] name = "jf-relation" version = "0.4.0-pre.0" -source = "git+https://github.com/EspressoSystems/jellyfish#30752c6c1af7b933e2536d7aeb991a40af4b806a" +source = "git+https://github.com/EspressoSystems/jellyfish#1626a8448e7af8ea153241004375deff9fd961da" dependencies = [ "ark-bls12-377", "ark-bls12-381", @@ -3384,7 +3380,7 @@ dependencies = [ [[package]] name = "jf-utils" version = "0.4.0-pre.0" -source = "git+https://github.com/EspressoSystems/jellyfish#30752c6c1af7b933e2536d7aeb991a40af4b806a" +source = "git+https://github.com/EspressoSystems/jellyfish#1626a8448e7af8ea153241004375deff9fd961da" dependencies = [ "ark-ec", "ark-ff", @@ -3443,9 +3439,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" [[package]] name = "libnghttp2-sys" @@ -3463,7 +3459,7 @@ version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32d07d1502a027366d55afe187621c2d7895dc111a3df13b35fed698049681d7" dependencies = [ - "bytes 1.4.0", + "bytes 1.5.0", "futures", "futures-timer", "getrandom 0.2.10", @@ -3544,9 +3540,9 @@ dependencies = [ [[package]] name = "libp2p-core" -version = "0.40.0" +version = "0.40.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef7dd7b09e71aac9271c60031d0e558966cdb3253ba0308ab369bb2de80630d0" +checksum = "dd44289ab25e4c9230d9246c475a22241e301b23e8f4061d3bdef304a1a99713" dependencies = [ "either", "fnv", @@ -3626,9 +3622,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d157562dba6017193e5285acf6b1054759e83540bfd79f75b69d6ce774c88da" dependencies = [ "asynchronous-codec", - "base64 0.21.3", + "base64 0.21.4", "byteorder", - "bytes 1.4.0", + "bytes 1.5.0", "either", "fnv", "futures", @@ -3676,13 +3672,14 @@ dependencies = [ [[package]] name = "libp2p-identity" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686e73aff5e23efbb99bc85340ea6fd8686986aa7b283a881ba182cfca535ca9" +checksum = "57bf6e730ec5e7022958da53ffb03b326e681b7316939012ae9b3c7449a812d4" dependencies = [ "asn1_der", "bs58", "ed25519-dalek", + "hkdf 0.12.3", "libsecp256k1", "log", "multihash", @@ -3697,13 +3694,13 @@ dependencies = [ [[package]] name = "libp2p-kad" -version = "0.44.4" +version = "0.44.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc125f83d8f75322c79e4ade74677d299b34aa5c9d9b5251c03ec28c683cb765" +checksum = "41c5c483b1e90e79409711f515c5bea5de9c4d772a245b1ac01a2233fbcb67fe" dependencies = [ "arrayvec", "asynchronous-codec", - "bytes 1.4.0", + "bytes 1.5.0", "either", "fnv", "futures", @@ -3714,6 +3711,7 @@ dependencies = [ "libp2p-swarm", "log", "quick-protobuf", + "quick-protobuf-codec", "rand 0.8.5", "serde", "sha2 0.10.8", @@ -3740,7 +3738,7 @@ dependencies = [ "log", "rand 0.8.5", "smallvec", - "socket2 0.5.3", + "socket2 0.5.4", "tokio", "trust-dns-proto", "void", @@ -3775,12 +3773,13 @@ dependencies = [ "async-trait", "bincode", "blake3", - "clap", "color-eyre", "custom_debug", + "dashmap", "derive_builder", "either", "futures", + "hotshot-constants", "hotshot-utils", "libp2p", "libp2p-identity", @@ -3812,8 +3811,8 @@ version = "0.43.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71ce70757f2c0d82e9a3ef738fb10ea0723d16cec37f078f719e2c247704c1bb" dependencies = [ - "bytes 1.4.0", - "curve25519-dalek 4.0.0", + "bytes 1.5.0", + "curve25519-dalek 4.1.1", "futures", "libp2p-core", "libp2p-identity", @@ -3833,9 +3832,9 @@ dependencies = [ [[package]] name = "libp2p-ping" -version = "0.43.0" +version = "0.43.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cd5ee3270229443a2b34b27ed0cb7470ef6b4a6e45e54e89a8771fa683bab48" +checksum = "e702d75cd0827dfa15f8fd92d15b9932abe38d10d21f47c50438c71dd1b5dae3" dependencies = [ "either", "futures", @@ -3856,7 +3855,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37266c683a757df713f7dcda0cdcb5ad4681355ffa1b37b77c113c176a531195" dependencies = [ "asynchronous-codec", - "bytes 1.4.0", + "bytes 1.5.0", "futures", "libp2p-core", "libp2p-identity", @@ -3886,7 +3885,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cb763e88f9a043546bfebd3575f340e7dd3d6c1b2cf2629600ec8965360c63a" dependencies = [ "async-std", - "bytes 1.4.0", + "bytes 1.5.0", "futures", "futures-timer", "if-watch", @@ -3898,7 +3897,7 @@ dependencies = [ "quinn", "rand 0.8.5", "rustls", - "socket2 0.5.3", + "socket2 0.5.4", "thiserror", "tokio", ] @@ -3910,7 +3909,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb07202cdf103486709fda5d9d10a0297a8ba01c212b1e19b7943c45c1bd7d6" dependencies = [ "asynchronous-codec", - "bytes 1.4.0", + "bytes 1.5.0", "either", "futures", "futures-timer", @@ -3971,9 +3970,9 @@ dependencies = [ [[package]] name = "libp2p-swarm" -version = "0.43.3" +version = "0.43.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28016944851bd73526d3c146aabf0fa9bbe27c558f080f9e5447da3a1772c01a" +checksum = "ab94183f8fc2325817835b57946deb44340c99362cd4606c0a5717299b2ba369" dependencies = [ "async-std", "either", @@ -4003,7 +4002,7 @@ dependencies = [ "proc-macro-warning", "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.38", ] [[package]] @@ -4020,7 +4019,7 @@ dependencies = [ "libp2p-core", "libp2p-identity", "log", - "socket2 0.5.3", + "socket2 0.5.4", "tokio", ] @@ -4173,6 +4172,12 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +[[package]] +name = "linux-raw-sys" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" + [[package]] name = "lock_api" version = "0.4.10" @@ -4244,9 +4249,9 @@ checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "matchit" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed1202b2a6f884ae56f04cff409ab315c5ce26b5e58d7412e484f01fd52f52ef" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "maud" @@ -4296,9 +4301,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.3" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memoffset" @@ -4404,9 +4409,9 @@ dependencies = [ [[package]] name = "multihash" -version = "0.19.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd59dcc2bbe70baabeac52cd22ae52c55eefe6c38ff11a9439f16a350a939f2" +checksum = "076d548d76a0e2a0d4ab471d0b1c36c577786dfc4471242035d97a12a735c492" dependencies = [ "core2", "serde", @@ -4419,7 +4424,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea0df8e5eec2298a62b326ee4f0d7fe1a6b90a09dfcf9df37b38f947a8c42f19" dependencies = [ - "bytes 1.4.0", + "bytes 1.5.0", "futures", "log", "pin-project", @@ -4528,7 +4533,7 @@ name = "netlink-proto" version = "0.9.2" source = "git+https://github.com/espressosystems/netlink.git#1347bed011eeae7ece9851773906c4a3c80a5d77" dependencies = [ - "bytes 1.4.0", + "bytes 1.5.0", "futures", "log", "netlink-packet-core 0.4.2 (git+https://github.com/espressosystems/netlink.git)", @@ -4542,7 +4547,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65b4b14489ab424703c092062176d52ba55485a89c076b4f9db05092b7223aa6" dependencies = [ - "bytes 1.4.0", + "bytes 1.5.0", "futures", "log", "netlink-packet-core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4557,7 +4562,7 @@ version = "0.8.2" source = "git+https://github.com/espressosystems/netlink.git#1347bed011eeae7ece9851773906c4a3c80a5d77" dependencies = [ "async-io", - "bytes 1.4.0", + "bytes 1.5.0", "futures", "libc", "log", @@ -4570,7 +4575,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6471bf08e7ac0135876a9581bf3217ef0333c191c128d34878079f42ee150411" dependencies = [ "async-io", - "bytes 1.4.0", + "bytes 1.5.0", "futures", "libc", "log", @@ -4612,11 +4617,6 @@ dependencies = [ "libc", ] -[[package]] -name = "nll" -version = "1.0.0" -source = "git+https://github.com/EspressoSystems/nll.git#c84499eb8de11beee5caa9390deff8a8ca3b9514" - [[package]] name = "nohash-hasher" version = "0.2.0" @@ -4666,9 +4666,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", ] @@ -4721,9 +4721,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.92" +version = "0.9.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db7e971c2c2bba161b2d2fdf37080177eff520b3bc044787c7f1f5f9e78d869b" +checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" dependencies = [ "cc", "libc", @@ -4787,9 +4787,9 @@ dependencies = [ [[package]] name = "parking" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" +checksum = "e52c774a4c39359c1d1c52e43f73dd91a75a614652c825408eec30c95a9b2067" [[package]] name = "parking_lot" @@ -4843,9 +4843,9 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pest" -version = "2.7.3" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a4d085fd991ac8d5b05a147b437791b4260b76326baf0fc60cf7c9c27ecd33" +checksum = "c022f1e7b65d6a24c0dbbd5fb344c66881bc01f3e5ae74a1c8100f2f985d98a4" dependencies = [ "memchr", "thiserror", @@ -4854,9 +4854,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.3" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bee7be22ce7918f641a33f08e3f43388c7656772244e2bbb2477f44cc9021a" +checksum = "35513f630d46400a977c4cb58f78e1bfbe01434316e60c37d27b9ad6139c66d8" dependencies = [ "pest", "pest_generator", @@ -4864,22 +4864,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.3" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1511785c5e98d79a05e8a6bc34b4ac2168a0e3e92161862030ad84daa223141" +checksum = "bc9fc1b9e7057baba189b5c626e2d6f40681ae5b6eb064dc7c7834101ec8123a" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.38", ] [[package]] name = "pest_meta" -version = "2.7.3" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42f0394d3123e33353ca5e1e89092e533d2cc490389f2bd6131c43c634ebc5f" +checksum = "1df74e9e7ec4053ceb980e7c0c8bd3594e977fde1af91daba9c928e8e8c6708d" dependencies = [ "once_cell", "pest", @@ -4903,7 +4903,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.38", ] [[package]] @@ -4930,6 +4930,17 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d15b6607fa632996eb8a17c9041cb6071cb75ac057abd45dece578723ea8c7c0" +[[package]] +name = "piper" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +dependencies = [ + "atomic-waker", + "fastrand 2.0.1", + "futures-io", +] + [[package]] name = "pkcs8" version = "0.10.2" @@ -5013,15 +5024,6 @@ dependencies = [ "universal-hash 0.4.0", ] -[[package]] -name = "portpicker" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be97d76faf1bfab666e1375477b23fde79eccf0276e9b63b92a39d676a889ba9" -dependencies = [ - "rand 0.8.5", -] - [[package]] name = "ppv-lite86" version = "0.2.17" @@ -5089,14 +5091,14 @@ checksum = "3d1eaa7fa0aa1929ffdf7eeb6eac234dde6268914a14ad44d23521ab6a9b258e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.38", ] [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ "unicode-ident", ] @@ -5121,7 +5123,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.38", ] [[package]] @@ -5130,7 +5132,7 @@ version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" dependencies = [ - "bytes 1.4.0", + "bytes 1.5.0", "prost-derive", ] @@ -5178,7 +5180,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ededb1cd78531627244d51dd0c7139fbe736c7d57af0092a76f0ffb2f56e98" dependencies = [ "asynchronous-codec", - "bytes 1.4.0", + "bytes 1.5.0", "quick-protobuf", "thiserror", "unsigned-varint", @@ -5203,7 +5205,7 @@ checksum = "8cc2c5017e4b43d5995dcea317bc46c1e09404c0a9664d2908f7f02dfe943d75" dependencies = [ "async-io", "async-std", - "bytes 1.4.0", + "bytes 1.5.0", "futures-io", "pin-project-lite 0.2.13", "quinn-proto", @@ -5221,7 +5223,7 @@ version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c78e758510582acc40acb90458401172d41f1016f8c9dde89e49677afb7eec1" dependencies = [ - "bytes 1.4.0", + "bytes 1.5.0", "rand 0.8.5", "ring", "rustc-hash", @@ -5238,9 +5240,9 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "055b4e778e8feb9f93c4e439f71dc2156ef13360b432b799e179a8c4cdf0b1d7" dependencies = [ - "bytes 1.4.0", + "bytes 1.5.0", "libc", - "socket2 0.5.3", + "socket2 0.5.4", "tracing", "windows-sys", ] @@ -5333,9 +5335,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" dependencies = [ "either", "rayon-core", @@ -5343,14 +5345,12 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] @@ -5396,13 +5396,13 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.5" +version = "1.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" +checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.3.8", + "regex-automata 0.3.9", "regex-syntax 0.7.5", ] @@ -5417,9 +5417,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" +checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" dependencies = [ "aho-corasick", "memchr", @@ -5469,7 +5469,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" dependencies = [ - "bytes 1.4.0", + "bytes 1.5.0", "rustc-hex", ] @@ -5577,7 +5577,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.18", + "semver 1.0.19", ] [[package]] @@ -5591,15 +5591,28 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.23" +version = "0.37.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" +checksum = "4279d76516df406a8bd37e7dff53fd37d1a093f997a3c34a5c21658c126db06d" dependencies = [ "bitflags 1.3.2", "errno", "io-lifetimes", "libc", - "linux-raw-sys", + "linux-raw-sys 0.3.8", + "windows-sys", +] + +[[package]] +name = "rustix" +version = "0.38.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a74ee2d7c2581cd139b42447d7d9389b889bdaad3a73f1ebb16f2a3237bb19c" +dependencies = [ + "bitflags 2.4.0", + "errno", + "libc", + "linux-raw-sys 0.4.10", "windows-sys", ] @@ -5617,9 +5630,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.101.4" +version = "0.101.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d93931baf2d282fff8d3a532bbfd7653f734643161b87e3e01e59a04439bf0d" +checksum = "3c7d5dece342910d9ba34d259310cae3e0154b873b35408b787b59bce53d34fe" dependencies = [ "ring", "untrusted", @@ -5693,9 +5706,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" +checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" [[package]] name = "semver-parser" @@ -5726,7 +5739,7 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.38", ] [[package]] @@ -5803,11 +5816,11 @@ version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ca3b16a3d82c4088f343b7480a93550b3eabe1a358569c2dfe38bbcead07237" dependencies = [ - "base64 0.21.3", + "base64 0.21.4", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.0.0", + "indexmap 2.0.2", "serde", "serde_json", "serde_with_macros 3.3.0", @@ -5823,7 +5836,7 @@ dependencies = [ "darling 0.20.3", "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.38", ] [[package]] @@ -5835,7 +5848,7 @@ dependencies = [ "darling 0.20.3", "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.38", ] [[package]] @@ -5912,9 +5925,9 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] @@ -5980,7 +5993,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38aabbeafa6f6dead8cebf246fe9fae1f9215c8d29b3a69f93bd62a9e4a3dcd6" dependencies = [ - "event-listener", + "event-listener 2.5.3", ] [[package]] @@ -6005,9 +6018,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "smartcow" @@ -6078,7 +6091,7 @@ dependencies = [ "aes-gcm 0.9.2", "blake2", "chacha20poly1305 0.9.1", - "curve25519-dalek 4.0.0", + "curve25519-dalek 4.1.1", "rand_core 0.6.4", "ring", "rustc_version 0.4.0", @@ -6098,9 +6111,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" +checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" dependencies = [ "libc", "windows-sys", @@ -6113,7 +6126,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" dependencies = [ "base64 0.13.1", - "bytes 1.4.0", + "bytes 1.5.0", "futures", "httparse", "log", @@ -6260,7 +6273,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.31", + "syn 2.0.38", ] [[package]] @@ -6311,15 +6324,15 @@ dependencies = [ [[package]] name = "sval" -version = "2.6.1" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b031320a434d3e9477ccf9b5756d57d4272937b8d22cb88af80b7633a1b78b1" +checksum = "e55089b73dfa822e1eb6b635f8795215512cca94bfae11aee3a1a06228bc88bb" [[package]] name = "sval_buffer" -version = "2.6.1" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bf7e9412af26b342f3f2cc5cc4122b0105e9d16eb76046cd14ed10106cf6028" +checksum = "df307823073d63f1fb126895439fead41afc493ea35d636cceedef9f6b32ba81" dependencies = [ "sval", "sval_ref", @@ -6327,18 +6340,18 @@ dependencies = [ [[package]] name = "sval_dynamic" -version = "2.6.1" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0ef628e8a77a46ed3338db8d1b08af77495123cc229453084e47cd716d403cf" +checksum = "e5f8e4c4d6d028d3cbff66c2bb3d98181d031d312b7df4550eea7142d7036f37" dependencies = [ "sval", ] [[package]] name = "sval_fmt" -version = "2.6.1" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dc09e9364c2045ab5fa38f7b04d077b3359d30c4c2b3ec4bae67a358bd64326" +checksum = "ad53f8eb502b0a3051fea001ae2e3723044699868ebfe06ea81b45545db392c2" dependencies = [ "itoa 1.0.9", "ryu", @@ -6347,9 +6360,9 @@ dependencies = [ [[package]] name = "sval_json" -version = "2.6.1" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ada6f627e38cbb8860283649509d87bc4a5771141daa41c78fd31f2b9485888d" +checksum = "f913253c9f6cd27645ba9a0b6788039b5d4338eae0833c64b42ef178168d2862" dependencies = [ "itoa 1.0.9", "ryu", @@ -6358,18 +6371,18 @@ dependencies = [ [[package]] name = "sval_ref" -version = "2.6.1" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703ca1942a984bd0d9b5a4c0a65ab8b4b794038d080af4eb303c71bc6bf22d7c" +checksum = "66a9661412d06740ebe81512a527b3d9220460eb7685f4399232c0e670108cb7" dependencies = [ "sval", ] [[package]] name = "sval_serde" -version = "2.6.1" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830926cd0581f7c3e5d51efae4d35c6b6fc4db583842652891ba2f1bed8db046" +checksum = "b8d077e98c1c8dfa466837ae0ec1e03c78138d42ac75662dac05e1bf0aebae20" dependencies = [ "serde", "sval", @@ -6390,9 +6403,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.31" +version = "2.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398" +checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" dependencies = [ "proc-macro2", "quote", @@ -6466,6 +6479,20 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "tagged-base64" +version = "0.3.1" +source = "git+https://github.com/EspressoSystems/tagged-base64.git?tag=0.3.1#9207d39ba7a9c11801511a7077ea4330b6173e44" +dependencies = [ + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "base64 0.13.1", + "crc-any", + "serde", + "snafu", + "tagged-base64-macros 0.3.1", +] + [[package]] name = "tagged-base64" version = "0.3.3" @@ -6501,6 +6528,15 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "tagged-base64-macros" +version = "0.3.1" +source = "git+https://github.com/EspressoSystems/tagged-base64.git?tag=0.3.1#9207d39ba7a9c11801511a7077ea4330b6173e44" +dependencies = [ + "quote", + "syn 1.0.109", +] + [[package]] name = "tagged-base64-macros" version = "0.3.3" @@ -6519,22 +6555,22 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "thiserror" -version = "1.0.48" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.48" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.38", ] [[package]] @@ -6591,7 +6627,7 @@ dependencies = [ "maud 0.24.0", "parking_lot", "routefinder", - "semver 1.0.18", + "semver 1.0.19", "serde", "serde_json", "serde_with 2.3.3", @@ -6637,7 +6673,7 @@ dependencies = [ "maud 0.25.0", "parking_lot", "routefinder", - "semver 1.0.18", + "semver 1.0.19", "serde", "serde_json", "serde_with 3.3.0", @@ -6770,19 +6806,19 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.32.0" +version = "1.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" +checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" dependencies = [ "backtrace", - "bytes 1.4.0", + "bytes 1.5.0", "libc", "mio", "num_cpus", "parking_lot", "pin-project-lite 0.2.13", "signal-hook-registry", - "socket2 0.5.3", + "socket2 0.5.4", "tokio-macros", "tracing", "windows-sys", @@ -6806,7 +6842,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.38", ] [[package]] @@ -6822,11 +6858,11 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" dependencies = [ - "bytes 1.4.0", + "bytes 1.5.0", "futures-core", "futures-sink", "pin-project-lite 0.2.13", @@ -6870,7 +6906,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.0.2", "serde", "serde_spanned", "toml_datetime", @@ -6885,8 +6921,8 @@ checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a" dependencies = [ "async-trait", "axum", - "base64 0.21.3", - "bytes 1.4.0", + "base64 0.21.4", + "bytes 1.5.0", "futures-core", "futures-util", "h2", @@ -6958,7 +6994,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.38", ] [[package]] @@ -7105,7 +7141,7 @@ checksum = "5fe8dada8c1a3aeca77d6b51a4f1314e0f4b8e438b7b1b71e3ddaca8080e4093" dependencies = [ "base64 0.13.1", "byteorder", - "bytes 1.4.0", + "bytes 1.5.0", "http", "httparse", "input_buffer", @@ -7125,7 +7161,7 @@ checksum = "983d40747bce878d2fb67d910dcb8bd3eca2b2358540c3cc1b98c027407a3ae3" dependencies = [ "base64 0.13.1", "byteorder", - "bytes 1.4.0", + "bytes 1.5.0", "http", "httparse", "log", @@ -7177,9 +7213,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" @@ -7218,12 +7254,12 @@ dependencies = [ [[package]] name = "unsigned-varint" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d86a8dc7f45e4c1b0d30e43038c38f274e77af056aa5f74b93c2cf9eb3c1c836" +checksum = "6889a77d49f1f013504cec6bf97a2c730394adedaeb1deb5ea08949a50541105" dependencies = [ "asynchronous-codec", - "bytes 1.4.0", + "bytes 1.5.0", ] [[package]] @@ -7318,9 +7354,9 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[package]] name = "waker-fn" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" +checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" [[package]] name = "want" @@ -7366,7 +7402,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.38", "wasm-bindgen-shared", ] @@ -7400,7 +7436,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.38", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -7575,9 +7611,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.5.15" +version = "0.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc" +checksum = "037711d82167854aff2018dfd193aa0fef5370f456732f0d5a0c59b0f1b4b907" dependencies = [ "memchr", ] @@ -7679,5 +7715,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.38", ] diff --git a/Cargo.toml b/Cargo.toml index cc985000ed..688e9c37d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,13 +17,14 @@ members = [ "crates/testing", "crates/types", "crates/utils", + "crates/constants", # "testing-macros", "crates/task", "crates/task-impls", "crates/hotshot-qc", "crates/hotshot-signature-key", "crates/hotshot-stake-table", - "crates/hotshot" + "crates/hotshot", ] resolver = "2" @@ -43,71 +44,76 @@ bitvec = { version = "1.0.1", default-features = false, features = [ "atomic", "serde", ] } -blake3 = "1.4" -commit = { git = "https://github.com/EspressoSystems/commit", tag = "0.2.2" } +blake3 = "1.5" +commit = { git = "https://github.com/EspressoSystems/commit" } custom_debug = "0.5" digest = "0.10" either = { version = "1.8" } espresso-systems-common = { git = "https://github.com/espressosystems/espresso-systems-common", tag = "0.4.1" } ethereum-types = { version = "0.14.1", features = ["impl-serde"] } futures = "0.3.28" + +# TODO generic-array should not be a direct dependency +# https://github.com/EspressoSystems/HotShot/issues/1850 +generic-array = { version = "0.14.7", features = ["serde"] } + jf-primitives = { git = "https://github.com/EspressoSystems/jellyfish" } jf-relation = { git = "https://github.com/EspressoSystems/jellyfish" } jf-utils = { git = "https://github.com/espressosystems/jellyfish" } libp2p-identity = "0.2" libp2p-networking = { path = "./crates/libp2p-networking", version = "0.1.0", default-features = false } libp2p-swarm-derive = { version = "=0.33.0" } -nll = { git = "https://github.com/EspressoSystems/nll.git" } rand = "0.8.5" rand_chacha = { version = "0.3.1", default-features = false } serde = { version = "1.0.188", features = ["derive"] } +sha2 = "0.10" snafu = "0.7.5" surf-disco = { git = "https://github.com/EspressoSystems/surf-disco.git", tag = "v0.4.2" } -time = "0.3.28" +time = "0.3.29" toml = "0.7.8" tracing = "0.1.37" -typenum = "1.16.0" +typenum = "1.17.0" libp2p = { package = "libp2p", version = "0.52.3", features = [ - "macros", - "autonat", - "deflate", - "dns", - "floodsub", - "gossipsub", - "identify", - "kad", - "mdns", - "noise", - "ping", - "plaintext", - "pnet", - "quic", - "relay", - "request-response", - "rendezvous", - "secp256k1", - "serde", - "tcp", - "uds", - "wasm-ext", - "websocket", - "yamux", + "macros", + "autonat", + "deflate", + "dns", + "floodsub", + "gossipsub", + "identify", + "kad", + "mdns", + "noise", + "ping", + "plaintext", + "pnet", + "quic", + "relay", + "request-response", + "rendezvous", + "secp256k1", + "serde", + "tcp", + "uds", + "wasm-ext", + "websocket", + "yamux", ] } async-std = { version = "1.12.0", features = ["attributes"] } tokio = { version = "1.32.0", features = [ - "fs", - "io-util", - "io-std", - "macros", - "net", - "parking_lot", - "process", - "rt", - "rt-multi-thread", - "signal", - "sync", - "time", - "tracing", + "fs", + "io-util", + "io-std", + "macros", + "net", + "parking_lot", + "process", + "rt", + "rt-multi-thread", + "signal", + "sync", + "time", + "tracing", ] } ### Profiles @@ -117,9 +123,15 @@ tokio = { version = "1.32.0", features = [ ## Apply some optimizations to test dependencies in debug/test builds +[profile.dev] +strip = true +debug = 0 + # Generally optimize dependencies a little [profile.dev.package."*"] opt-level = 1 +strip = true +debug = 0 # The default release profile without LTO. [profile.release] diff --git a/crates/constants/Cargo.toml b/crates/constants/Cargo.toml new file mode 100644 index 0000000000..6f04253d2e --- /dev/null +++ b/crates/constants/Cargo.toml @@ -0,0 +1,5 @@ +[package] +name = "hotshot-constants" +version.workspace = true + +[dependencies] diff --git a/crates/constants/src/lib.rs b/crates/constants/src/lib.rs new file mode 100644 index 0000000000..8a4d9d5d46 --- /dev/null +++ b/crates/constants/src/lib.rs @@ -0,0 +1,10 @@ +//! configurable constants for hotshot + +/// the ID of the genesis block proposer +pub const GENESIS_PROPOSER_ID: [u8; 2] = [4, 2]; + +/// the number of views to gather information for ahead of time +pub const LOOK_AHEAD: u64 = 5; + +/// the default kademlia record republication interval (in seconds) +pub const KAD_DEFAULT_REPUB_INTERVAL_SEC: u64 = 28800; diff --git a/crates/hotshot-qc/Cargo.toml b/crates/hotshot-qc/Cargo.toml index 0faa1f0a87..9c53fb335a 100644 --- a/crates/hotshot-qc/Cargo.toml +++ b/crates/hotshot-qc/Cargo.toml @@ -19,7 +19,7 @@ ark-std = { workspace = true } bincode = { workspace = true } bitvec = { workspace = true } ethereum-types = { workspace = true } -generic-array = "0.14.7" +generic-array = { workspace = true } hotshot-types = { path = "../types" } jf-primitives = { workspace = true } jf-relation = { workspace = true } diff --git a/crates/hotshot-signature-key/src/bn254.rs b/crates/hotshot-signature-key/src/bn254.rs index fc7273afd5..2414c89c9c 100644 --- a/crates/hotshot-signature-key/src/bn254.rs +++ b/crates/hotshot-signature-key/src/bn254.rs @@ -1,8 +1,8 @@ //! Demonstration implementation of the [`SignatureKey`] trait using BN254 use hotshot_types::traits::signature_key::{EncodedPublicKey, EncodedSignature, SignatureKey}; -/// `BN254Priv` implementation +/// `BLSPrivKey` implementation mod bn254_priv; -/// `BN254Pub` implementation +/// `BLSPubKey` implementation mod bn254_pub; -pub use self::{bn254_priv::BN254Priv, bn254_pub::BN254Pub}; +pub use self::{bn254_priv::BLSPrivKey, bn254_pub::BLSPubKey}; diff --git a/crates/hotshot-signature-key/src/bn254/bn254_priv.rs b/crates/hotshot-signature-key/src/bn254/bn254_priv.rs index 3b7000eea4..439b52ff39 100644 --- a/crates/hotshot-signature-key/src/bn254/bn254_priv.rs +++ b/crates/hotshot-signature-key/src/bn254/bn254_priv.rs @@ -7,12 +7,12 @@ use std::cmp::Ordering; /// Private key type for a bn254 keypair #[derive(PartialEq, Eq, Clone, Serialize, Deserialize, Debug)] -pub struct BN254Priv { +pub struct BLSPrivKey { /// The private key for this keypair pub(super) priv_key: QCSignKey, } -impl BN254Priv { +impl BLSPrivKey { /// Generate a new private key from scratch #[must_use] pub fn generate() -> Self { @@ -54,7 +54,7 @@ impl BN254Priv { } } -impl PartialOrd for BN254Priv { +impl PartialOrd for BLSPrivKey { fn partial_cmp(&self, other: &Self) -> Option { let self_bytes = &self.priv_key.to_string(); let other_bytes = &other.priv_key.to_string(); @@ -62,7 +62,7 @@ impl PartialOrd for BN254Priv { } } -impl Ord for BN254Priv { +impl Ord for BLSPrivKey { fn cmp(&self, other: &Self) -> Ordering { let self_bytes = &self.priv_key.to_string(); let other_bytes = &other.priv_key.to_string(); diff --git a/crates/hotshot-signature-key/src/bn254/bn254_pub.rs b/crates/hotshot-signature-key/src/bn254/bn254_pub.rs index c25fad4be0..025d455129 100644 --- a/crates/hotshot-signature-key/src/bn254/bn254_pub.rs +++ b/crates/hotshot-signature-key/src/bn254/bn254_pub.rs @@ -1,4 +1,4 @@ -use super::{BN254Priv, EncodedPublicKey, EncodedSignature, SignatureKey}; +use super::{BLSPrivKey, EncodedPublicKey, EncodedSignature, SignatureKey}; use bincode::Options; use bitvec::prelude::*; use blake3::traits::digest::generic_array::GenericArray; @@ -22,12 +22,12 @@ use typenum::U32; /// This type makes use of noise for non-determinisitc signatures. #[derive(Clone, PartialEq, Eq, Hash, Copy, Serialize, Deserialize, Debug)] -pub struct BN254Pub { +pub struct BLSPubKey { /// The public key for this keypair pub_key: VerKey, } -impl PartialOrd for BN254Pub { +impl PartialOrd for BLSPubKey { fn partial_cmp(&self, other: &Self) -> Option { let self_bytes = &self.pub_key.to_string(); let other_bytes = &other.pub_key.to_string(); @@ -35,7 +35,7 @@ impl PartialOrd for BN254Pub { } } -impl Ord for BN254Pub { +impl Ord for BLSPubKey { fn cmp(&self, other: &Self) -> Ordering { let self_bytes = &self.pub_key.to_string(); let other_bytes = &other.pub_key.to_string(); @@ -43,18 +43,16 @@ impl Ord for BN254Pub { } } -impl SignatureKey for BN254Pub { - type PrivateKey = BN254Priv; +impl SignatureKey for BLSPubKey { + type PrivateKey = BLSPrivKey; type StakeTableEntry = JFStakeTableEntry; type QCParams = JFQCParams< ::VerificationKey, ::PublicParameter, >; - type QCType = ( - ::Signature, - BitVec, - ); - // as AssembledQuorumCertificate>::QC; + type PureAssembledSignatureType = + ::Signature; + type QCType = (Self::PureAssembledSignatureType, BitVec); #[instrument(skip(self))] fn validate(&self, signature: &EncodedSignature, data: &[u8]) -> bool { @@ -114,7 +112,7 @@ impl SignatureKey for BN254Pub { fn from_bytes(bytes: &EncodedPublicKey) -> Option { let x: Result = bincode_opts().deserialize(&bytes.0); match x { - Ok(pub_key) => Some(BN254Pub { pub_key }), + Ok(pub_key) => Some(BLSPubKey { pub_key }), Err(e) => { debug!(?e, "Failed to deserialize public key"); None @@ -134,6 +132,12 @@ impl SignatureKey for BN254Pub { } } + fn get_public_key(entry: &Self::StakeTableEntry) -> Self { + Self { + pub_key: entry.stake_key, + } + } + fn get_public_parameter( stake_entries: Vec, threshold: U256, @@ -150,19 +154,14 @@ impl SignatureKey for BN254Pub { BitVectorQC::::check(real_qc_pp, msg, qc).is_ok() } - fn get_sig_proof( - signature: &Self::QCType, - ) -> ( - ::Signature, - BitVec, - ) { + fn get_sig_proof(signature: &Self::QCType) -> (Self::PureAssembledSignatureType, BitVec) { signature.clone() } fn assemble( real_qc_pp: &Self::QCParams, signers: &BitSlice, - sigs: &[::Signature], + sigs: &[Self::PureAssembledSignatureType], ) -> Self::QCType { BitVectorQC::::assemble(real_qc_pp, signers, sigs) .expect("this assembling shouldn't fail") diff --git a/crates/hotshot-stake-table/Cargo.toml b/crates/hotshot-stake-table/Cargo.toml index 8f11e4d66f..4059589a85 100644 --- a/crates/hotshot-stake-table/Cargo.toml +++ b/crates/hotshot-stake-table/Cargo.toml @@ -16,7 +16,7 @@ bitvec = { workspace = true } digest = { workspace = true } displaydoc = { version = "0.2.3", default-features = false } ethereum-types = { workspace = true } -generic-array = "0.14.7" +generic-array = { workspace = true } hotshot-types = { path = "../types" } jf-primitives = { workspace = true } jf-relation = { workspace = true } diff --git a/crates/hotshot/Cargo.toml b/crates/hotshot/Cargo.toml index 7edc7363c5..d7816208f1 100644 --- a/crates/hotshot/Cargo.toml +++ b/crates/hotshot/Cargo.toml @@ -25,16 +25,21 @@ docs = [] doc-images = [] hotshot-testing = [] -# [[example]] -# name = "libp2p-validator" -# required-features = ["demo", "libp2p/rsa"] -# path = "examples/libp2p/validator.rs" -# -# [[example]] -# name = "libp2p-orchestrator" -# required-features = ["demo", "libp2p/rsa"] -# path = "examples/libp2p/orchestrator.rs" -# +[[example]] +name = "libp2p-validator" +required-features = ["demo", "libp2p/rsa"] +path = "examples/libp2p/validator.rs" + +[[example]] +name = "libp2p-multi-validator" +required-features = ["demo", "libp2p/rsa"] +path = "examples/libp2p/multi-validator.rs" + +[[example]] +name = "libp2p-orchestrator" +required-features = ["demo", "libp2p/rsa"] +path = "examples/libp2p/orchestrator.rs" + # [[example]] # name = "web-server-orchestrator" # required-features = ["demo", "libp2p/rsa"] @@ -80,6 +85,7 @@ bincode = { workspace = true } bitvec = { workspace = true } clap = { version = "4.4", features = ["derive", "env"], optional = true } commit = { workspace = true } +hotshot-constants = { path = "../constants" } custom_debug = { workspace = true } dashmap = "5.5.1" derivative = { version = "2.2.0", optional = true } @@ -95,10 +101,10 @@ hotshot-types = { path = "../types", version = "0.1.0", default-features = false hotshot-utils = { path = "../utils" } hotshot-task = { path = "../task", version = "0.1.0", default-features = false } hotshot-task-impls = { path = "../task-impls", version = "0.1.0", default-features = false } +jf-primitives = { workspace = true } libp2p = { workspace = true } libp2p-identity = { workspace = true } libp2p-networking = { workspace = true } -nll = { workspace = true } rand = { workspace = true } rand_chacha = { workspace = true } serde = { workspace = true, features = ["rc"] } @@ -116,6 +122,6 @@ async-std = { workspace = true } [dev-dependencies] blake3 = { workspace = true } clap = { version = "4.4", features = ["derive", "env"] } -serde_json = "1.0.106" +serde_json = "1.0.107" toml = { workspace = true } diff --git a/crates/hotshot/examples/infra/mod.rs b/crates/hotshot/examples/infra/mod.rs index efd3b8169d..06d7d9deb3 100644 --- a/crates/hotshot/examples/infra/mod.rs +++ b/crates/hotshot/examples/infra/mod.rs @@ -52,7 +52,7 @@ pub fn load_config_from_file( > = config_toml.into(); // Generate network's public keys - config.config.known_nodes = (0..config.config.total_nodes.get()) + let known_nodes: Vec<_> = (0..config.config.total_nodes.get()) .map(|node_id| { TYPES::SignatureKey::generated_from_seed_indexed( config.seed, @@ -63,13 +63,12 @@ pub fn load_config_from_file( .collect(); config.config.known_nodes_with_stake = (0..config.config.total_nodes.get()) - .map(|node_id| config.config.known_nodes[node_id].get_stake_table_entry(1u64)) + .map(|node_id| known_nodes[node_id].get_stake_table_entry(1u64)) .collect(); config } -/// yeesh maybe we should just implement SignatureKey for this... pub fn libp2p_generate_indexed_identity(seed: [u8; 32], index: u64) -> Keypair { let mut hasher = blake3::Hasher::new(); hasher.update(&seed); diff --git a/crates/hotshot/examples/infra/modDA.rs b/crates/hotshot/examples/infra/modDA.rs index 729cbfd79f..ef188a7849 100644 --- a/crates/hotshot/examples/infra/modDA.rs +++ b/crates/hotshot/examples/infra/modDA.rs @@ -1,11 +1,14 @@ use crate::infra::{load_config_from_file, OrchestratorArgs}; use async_compatibility_layer::logging::{setup_backtrace, setup_logging}; +use async_lock::RwLock; use async_trait::async_trait; use futures::StreamExt; use hotshot::{ traits::{ - implementations::{MemoryStorage, WebCommChannel, WebServerNetwork}, + implementations::{ + Libp2pCommChannel, Libp2pNetwork, MemoryStorage, WebCommChannel, WebServerNetwork, + }, NodeImplementation, }, types::{SignatureKey, SystemContextHandle}, @@ -18,8 +21,9 @@ use hotshot_orchestrator::{ }; use hotshot_task::task::FilterEvent; use hotshot_types::{ + block_impl::{VIDBlockPayload, VIDTransaction}, certificate::ViewSyncCertificate, - data::{DAProposal, QuorumProposal, SequencingLeaf, TestableLeaf}, + data::{QuorumProposal, SequencingLeaf, TestableLeaf}, event::{Event, EventType}, message::{Message, SequencingMessage}, traits::{ @@ -33,9 +37,20 @@ use hotshot_types::{ }, state::{ConsensusTime, TestableBlock, TestableState}, }, - vote::{DAVote, QuorumVote, ViewSyncVote}, HotShotConfig, }; +use libp2p_identity::{ + ed25519::{self, SecretKey}, + Keypair, +}; +use libp2p_networking::{ + network::{MeshParams, NetworkNodeConfigBuilder, NetworkNodeType}, + reexport::Multiaddr, +}; +use rand::rngs::StdRng; +use rand::SeedableRng; +use std::{collections::BTreeSet, sync::Arc}; +use std::{num::NonZeroUsize, str::FromStr}; // use libp2p::{ // identity::{ // ed25519::{Keypair as EdKeypair, SecretKey}, @@ -44,11 +59,11 @@ use hotshot_types::{ // multiaddr::{self, Protocol}, // Multiaddr, // }; -// use libp2p_identity::PeerId; +use libp2p_identity::PeerId; // use libp2p_networking::network::{MeshParams, NetworkNodeConfigBuilder, NetworkNodeType}; +use std::{fmt::Debug, net::Ipv4Addr}; use std::{ //collections::{BTreeSet, VecDeque}, - collections::VecDeque, //fs, mem, net::IpAddr, @@ -58,7 +73,6 @@ use std::{ //time::{Duration, Instant}, time::Instant, }; -use std::{fmt::Debug, net::Ipv4Addr}; //use surf_disco::error::ClientError; //use surf_disco::Client; use tracing::{debug, error, info, warn}; @@ -67,27 +81,9 @@ use tracing::{debug, error, info, warn}; pub async fn run_orchestrator_da< TYPES: NodeType, MEMBERSHIP: Membership + Debug, - DANETWORK: CommunicationChannel< - TYPES, - Message, - DAProposal, - DAVote, - MEMBERSHIP, - > + Debug, - QUORUMNETWORK: CommunicationChannel< - TYPES, - Message, - QuorumProposal>, - QuorumVote>, - MEMBERSHIP, - > + Debug, - VIEWSYNCNETWORK: CommunicationChannel< - TYPES, - Message, - ViewSyncCertificate, - ViewSyncVote, - MEMBERSHIP, - > + Debug, + DANETWORK: CommunicationChannel, MEMBERSHIP> + Debug, + QUORUMNETWORK: CommunicationChannel, MEMBERSHIP> + Debug, + VIEWSYNCNETWORK: CommunicationChannel, MEMBERSHIP> + Debug, NODE: NodeImplementation< TYPES, Leaf = SequencingLeaf, @@ -130,32 +126,27 @@ pub async fn run_orchestrator_da< .await; } +/// Helper function to calculate the nuymber of transactions to send per node per round +fn calculate_num_tx_per_round( + node_index: u64, + total_num_nodes: usize, + transactions_per_round: usize, +) -> usize { + if node_index == 0 { + transactions_per_round / total_num_nodes + transactions_per_round % total_num_nodes + } else { + transactions_per_round / total_num_nodes + } +} + /// Defines the behavior of a "run" of the network with a given configuration #[async_trait] pub trait RunDA< TYPES: NodeType, MEMBERSHIP: Membership + Debug, - DANETWORK: CommunicationChannel< - TYPES, - Message, - DAProposal, - DAVote, - MEMBERSHIP, - > + Debug, - QUORUMNETWORK: CommunicationChannel< - TYPES, - Message, - QuorumProposal>, - QuorumVote>, - MEMBERSHIP, - > + Debug, - VIEWSYNCNETWORK: CommunicationChannel< - TYPES, - Message, - ViewSyncCertificate, - ViewSyncVote, - MEMBERSHIP, - > + Debug, + DANETWORK: CommunicationChannel, MEMBERSHIP> + Debug, + QUORUMNETWORK: CommunicationChannel, MEMBERSHIP> + Debug, + VIEWSYNCNETWORK: CommunicationChannel, MEMBERSHIP> + Debug, NODE: NodeImplementation< TYPES, Leaf = SequencingLeaf, @@ -215,7 +206,6 @@ pub trait RunDA< // Get KeyPair for certificate Aggregation let (pk, sk) = TYPES::SignatureKey::generated_from_seed_indexed(config.seed, config.node_index); - let known_nodes = config.config.known_nodes.clone(); let known_nodes_with_stake = config.config.known_nodes_with_stake.clone(); let entry = pk.get_stake_table_entry(1u64); @@ -240,7 +230,6 @@ pub trait RunDA< let exchanges = NODE::Exchanges::create( known_nodes_with_stake.clone(), - known_nodes.clone(), (quorum_election_config, committee_election_config), ( quorum_network.clone(), @@ -279,38 +268,23 @@ pub trait RunDA< } = self.get_config(); let size = mem::size_of::(); - let adjusted_padding = if padding < size { 0 } else { padding - size }; - let mut txns: VecDeque = VecDeque::new(); - - // TODO ED: In the future we should have each node generate transactions every round to simulate a more realistic network - let tx_to_gen = transactions_per_round * rounds * 3; - { - let mut txn_rng = rand::thread_rng(); - for _ in 0..tx_to_gen { - let txn = - <::StateType as TestableState>::create_random_transaction( - None, - &mut txn_rng, - padding as u64, - ); - txns.push_back(txn); - } - } - debug!("Generated {} transactions", tx_to_gen); + let padding = padding.saturating_sub(size); + let mut txn_rng = StdRng::seed_from_u64(node_index); - debug!("Adjusted padding size is {:?} bytes", adjusted_padding); - let mut round = 0; - let mut total_transactions = 0; + debug!("Adjusted padding size is {:?} bytes", padding); - let start = Instant::now(); + let mut total_transactions_committed = 0; + let mut total_transactions_sent = 0; + let transactions_to_send_per_round = + calculate_num_tx_per_round(node_index, total_nodes.get(), transactions_per_round); info!("Starting hotshot!"); + let start = Instant::now(); + let (mut event_stream, _streamid) = context.get_event_stream(FilterEvent::default()).await; let mut anchor_view: TYPES::Time = ::genesis(); let mut num_successful_commits = 0; - let total_nodes_u64 = total_nodes.get() as u64; - context.hotshot.start_consensus().await; loop { @@ -339,8 +313,20 @@ pub trait RunDA< } } + // send transactions + for _ in 0..transactions_to_send_per_round { + let txn = + <::StateType as TestableState>::create_random_transaction( + None, + &mut txn_rng, + padding as u64, + ); + _ = context.submit_transaction(txn).await.unwrap(); + total_transactions_sent += 1; + } + if let Some(size) = block_size { - total_transactions += size; + total_transactions_committed += size; } num_successful_commits += leaf_chain.len(); @@ -359,39 +345,16 @@ pub trait RunDA< EventType::NextLeaderViewTimeout { view_number } => { warn!("Timed out as the next leader in view {:?}", view_number); } - EventType::ViewFinished { view_number } => { - if *view_number > round { - round = *view_number; - info!("view finished: {:?}", view_number); - for _ in 0..transactions_per_round { - if node_index >= total_nodes_u64 - 10 { - let txn = txns.pop_front().unwrap(); - - debug!("Submitting txn on round {}", round); - - let result = context.submit_transaction(txn).await; - - if result.is_err() { - error! ( - "Could not send transaction to web server on round {}", - round - ) - } - } - } - } - } + EventType::ViewFinished { view_number: _ } => {} _ => unimplemented!(), } } } - - round += 1; } // Output run results let total_time_elapsed = start.elapsed(); - error!("{rounds} rounds completed in {total_time_elapsed:?} - Total transactions committed: {total_transactions} - Total commitments: {num_successful_commits}"); + error!("[{node_index}]: {rounds} rounds completed in {total_time_elapsed:?} - Total transactions sent: {total_transactions_sent} - Total transactions committed: {total_transactions_committed} - Total commitments: {num_successful_commits}"); } /// Returns the da network for this run @@ -415,23 +378,6 @@ pub trait RunDA< // WEB SERVER -/// Alias for the [`WebCommChannel`] for sequencing consensus. -type StaticDAComm = - WebCommChannel, DAVote, MEMBERSHIP>; - -/// Alias for the ['WebCommChannel'] for validating consensus -type StaticQuorumComm = WebCommChannel< - TYPES, - I, - QuorumProposal>, - QuorumVote>, - MEMBERSHIP, ->; - -/// Alias for the ['WebCommChannel'] for view sync consensus -type StaticViewSyncComm = - WebCommChannel, ViewSyncVote, MEMBERSHIP>; - /// Represents a web server-based run pub struct WebServerDARun< TYPES: NodeType, @@ -443,14 +389,14 @@ pub struct WebServerDARun< ::StakeTableEntry, TYPES::ElectionConfigType, >, - quorum_network: StaticQuorumComm, - da_network: StaticDAComm, - view_sync_network: StaticViewSyncComm, + quorum_network: WebCommChannel, + da_network: WebCommChannel, + view_sync_network: WebCommChannel, } #[async_trait] impl< - TYPES: NodeType, + TYPES: NodeType, MEMBERSHIP: Membership + Debug, NODE: NodeImplementation< TYPES, @@ -463,32 +409,20 @@ impl< SequencingLeaf, QuorumProposal>, MEMBERSHIP, - WebCommChannel< - TYPES, - NODE, - QuorumProposal>, - QuorumVote>, - MEMBERSHIP, - >, + WebCommChannel, Message, >, CommitteeExchange< TYPES, MEMBERSHIP, - WebCommChannel, DAVote, MEMBERSHIP>, + WebCommChannel, Message, >, ViewSyncExchange< TYPES, ViewSyncCertificate, MEMBERSHIP, - WebCommChannel< - TYPES, - NODE, - ViewSyncCertificate, - ViewSyncVote, - MEMBERSHIP, - >, + WebCommChannel, Message, >, >, @@ -499,9 +433,9 @@ impl< RunDA< TYPES, MEMBERSHIP, - StaticDAComm, - StaticQuorumComm, - StaticViewSyncComm, + WebCommChannel, + WebCommChannel, + WebCommChannel, NODE, > for WebServerDARun where @@ -540,21 +474,11 @@ where ); // Create the network - let quorum_network: WebCommChannel< - TYPES, - NODE, - QuorumProposal>, - QuorumVote>, - MEMBERSHIP, - > = WebCommChannel::new(underlying_quorum_network.clone().into()); + let quorum_network: WebCommChannel = + WebCommChannel::new(underlying_quorum_network.clone().into()); - let view_sync_network: WebCommChannel< - TYPES, - NODE, - ViewSyncCertificate, - ViewSyncVote, - MEMBERSHIP, - > = WebCommChannel::new(underlying_quorum_network.into()); + let view_sync_network: WebCommChannel = + WebCommChannel::new(underlying_quorum_network.into()); let WebServerConfig { host, @@ -563,17 +487,10 @@ where }: WebServerConfig = config.clone().da_web_server_config.unwrap(); // Each node runs the DA network so that leaders have access to transactions and DA votes - let da_network: WebCommChannel, DAVote, MEMBERSHIP> = - WebCommChannel::new( - WebServerNetwork::create( - &host.to_string(), - port, - wait_between_polls, - pub_key, - true, - ) + let da_network: WebCommChannel = WebCommChannel::new( + WebServerNetwork::create(&host.to_string(), port, wait_between_polls, pub_key, true) .into(), - ); + ); WebServerDARun { config, @@ -583,28 +500,244 @@ where } } - fn get_da_network( - &self, - ) -> WebCommChannel, DAVote, MEMBERSHIP> { + fn get_da_network(&self) -> WebCommChannel { self.da_network.clone() } - fn get_quorum_network( + fn get_quorum_network(&self) -> WebCommChannel { + self.quorum_network.clone() + } + + fn get_view_sync_network(&self) -> WebCommChannel { + self.view_sync_network.clone() + } + + fn get_config( &self, - ) -> WebCommChannel< + ) -> NetworkConfig< + TYPES::SignatureKey, + ::StakeTableEntry, + TYPES::ElectionConfigType, + > { + self.config.clone() + } +} + +// Libp2p + +/// Represents a libp2p-based run +pub struct Libp2pDARun, MEMBERSHIP: Membership> +{ + config: NetworkConfig< + TYPES::SignatureKey, + ::StakeTableEntry, + TYPES::ElectionConfigType, + >, + quorum_network: Libp2pCommChannel, + da_network: Libp2pCommChannel, + view_sync_network: Libp2pCommChannel, +} + +#[async_trait] +impl< + TYPES: NodeType, + MEMBERSHIP: Membership + Debug, + NODE: NodeImplementation< + TYPES, + Leaf = SequencingLeaf, + Exchanges = SequencingExchanges< + TYPES, + Message, + QuorumExchange< + TYPES, + SequencingLeaf, + QuorumProposal>, + MEMBERSHIP, + Libp2pCommChannel, + Message, + >, + CommitteeExchange< + TYPES, + MEMBERSHIP, + Libp2pCommChannel, + Message, + >, + ViewSyncExchange< + TYPES, + ViewSyncCertificate, + MEMBERSHIP, + Libp2pCommChannel, + Message, + >, + >, + Storage = MemoryStorage>, + ConsensusMessage = SequencingMessage, + >, + > + RunDA< TYPES, - NODE, - QuorumProposal>, - QuorumVote>, MEMBERSHIP, - > { + Libp2pCommChannel, + Libp2pCommChannel, + Libp2pCommChannel, + NODE, + > for Libp2pDARun +where + ::StateType: TestableState, + ::BlockType: TestableBlock, + SequencingLeaf: TestableLeaf, + Self: Sync, +{ + async fn initialize_networking( + config: NetworkConfig< + TYPES::SignatureKey, + ::StakeTableEntry, + TYPES::ElectionConfigType, + >, + ) -> Libp2pDARun { + let (pubkey, _privkey) = + <::SignatureKey as SignatureKey>::generated_from_seed_indexed( + config.seed, + config.node_index, + ); + let mut config = config; + let libp2p_config = config + .libp2p_config + .take() + .expect("Configuration is not for a Libp2p network"); + let bs_len = libp2p_config.bootstrap_nodes.len(); + let bootstrap_nodes: Vec<(PeerId, Multiaddr)> = libp2p_config + .bootstrap_nodes + .iter() + .map(|(addr, pair)| { + let kp = Keypair::from_protobuf_encoding(pair).unwrap(); + let peer_id = PeerId::from_public_key(&kp.public()); + let multiaddr = + Multiaddr::from_str(&format!("/ip4/{}/udp/{}/quic-v1", addr.ip(), addr.port())) + .unwrap(); + (peer_id, multiaddr) + }) + .collect(); + let identity = libp2p_generate_indexed_identity(config.seed, config.node_index); + let node_type = if (config.node_index as usize) < bs_len { + NetworkNodeType::Bootstrap + } else { + NetworkNodeType::Regular + }; + let node_index = config.node_index; + let port_index = match libp2p_config.index_ports { + true => node_index, + false => 0, + }; + let bound_addr: Multiaddr = format!( + "/{}/{}/udp/{}/quic-v1", + if libp2p_config.public_ip.is_ipv4() { + "ip4" + } else { + "ip6" + }, + libp2p_config.public_ip, + libp2p_config.base_port as u64 + port_index + ) + .parse() + .unwrap(); + + // generate network + let mut config_builder = NetworkNodeConfigBuilder::default(); + assert!(config.config.total_nodes.get() > 2); + let replicated_nodes = NonZeroUsize::new(config.config.total_nodes.get() - 2).unwrap(); + config_builder.replication_factor(replicated_nodes); + config_builder.identity(identity.clone()); + + config_builder.bound_addr(Some(bound_addr.clone())); + + let to_connect_addrs = bootstrap_nodes + .iter() + .map(|(peer_id, multiaddr)| (Some(*peer_id), multiaddr.clone())) + .collect(); + + config_builder.to_connect_addrs(to_connect_addrs); + + let mesh_params = + // NOTE I'm arbitrarily choosing these. + match node_type { + NetworkNodeType::Bootstrap => MeshParams { + mesh_n_high: libp2p_config.bootstrap_mesh_n_high, + mesh_n_low: libp2p_config.bootstrap_mesh_n_low, + mesh_outbound_min: libp2p_config.bootstrap_mesh_outbound_min, + mesh_n: libp2p_config.bootstrap_mesh_n, + }, + NetworkNodeType::Regular => MeshParams { + mesh_n_high: libp2p_config.mesh_n_high, + mesh_n_low: libp2p_config.mesh_n_low, + mesh_outbound_min: libp2p_config.mesh_outbound_min, + mesh_n: libp2p_config.mesh_n, + }, + NetworkNodeType::Conductor => unreachable!(), + }; + config_builder.mesh_params(Some(mesh_params)); + + let mut all_keys = BTreeSet::new(); + let mut da_keys = BTreeSet::new(); + for i in 0..config.config.total_nodes.get() as u64 { + let privkey = TYPES::SignatureKey::generated_from_seed_indexed([0u8; 32], i).1; + let pubkey = TYPES::SignatureKey::from_private(&privkey); + if i < config.config.da_committee_size as u64 { + da_keys.insert(pubkey.clone()); + } + all_keys.insert(pubkey); + } + + let node_config = config_builder.build().unwrap(); + let underlying_quorum_network = Libp2pNetwork::new( + NoMetrics::boxed(), + node_config, + pubkey.clone(), + Arc::new(RwLock::new( + bootstrap_nodes + .iter() + .map(|(peer_id, addr)| (Some(*peer_id), addr.clone())) + .collect(), + )), + bs_len, + config.node_index as usize, + // NOTE: this introduces an invariant that the keys are assigned using this indexed + // function + all_keys, + da_keys, + ) + .await + .unwrap(); + + underlying_quorum_network.wait_for_ready().await; + + // Create the network + let quorum_network: Libp2pCommChannel = + Libp2pCommChannel::new(underlying_quorum_network.clone().into()); + + let view_sync_network: Libp2pCommChannel = + Libp2pCommChannel::new(underlying_quorum_network.clone().into()); + + let da_network: Libp2pCommChannel = + Libp2pCommChannel::new(underlying_quorum_network.clone().into()); + + Libp2pDARun { + config, + quorum_network, + da_network, + view_sync_network, + } + } + + fn get_da_network(&self) -> Libp2pCommChannel { + self.da_network.clone() + } + + fn get_quorum_network(&self) -> Libp2pCommChannel { self.quorum_network.clone() } - fn get_view_sync_network( - &self, - ) -> WebCommChannel, ViewSyncVote, MEMBERSHIP> - { + fn get_view_sync_network(&self) -> Libp2pCommChannel { self.view_sync_network.clone() } @@ -621,29 +754,11 @@ where /// Main entry point for validators pub async fn main_entry_point< - TYPES: NodeType, + TYPES: NodeType, MEMBERSHIP: Membership + Debug, - DANETWORK: CommunicationChannel< - TYPES, - Message, - DAProposal, - DAVote, - MEMBERSHIP, - > + Debug, - QUORUMNETWORK: CommunicationChannel< - TYPES, - Message, - QuorumProposal>, - QuorumVote>, - MEMBERSHIP, - > + Debug, - VIEWSYNCNETWORK: CommunicationChannel< - TYPES, - Message, - ViewSyncCertificate, - ViewSyncVote, - MEMBERSHIP, - > + Debug, + DANETWORK: CommunicationChannel, MEMBERSHIP> + Debug, + QUORUMNETWORK: CommunicationChannel, MEMBERSHIP> + Debug, + VIEWSYNCNETWORK: CommunicationChannel, MEMBERSHIP> + Debug, NODE: NodeImplementation< TYPES, Leaf = SequencingLeaf, @@ -720,3 +835,12 @@ pub async fn main_entry_point< info!("All nodes are ready! Starting HotShot"); run.run_hotshot(hotshot).await; } + +pub fn libp2p_generate_indexed_identity(seed: [u8; 32], index: u64) -> Keypair { + let mut hasher = blake3::Hasher::new(); + hasher.update(&seed); + hasher.update(&index.to_le_bytes()); + let new_seed = *hasher.finalize().as_bytes(); + let sk_bytes = SecretKey::try_from_bytes(new_seed).unwrap(); + >::from(sk_bytes).into() +} diff --git a/crates/hotshot/examples/libp2p/multi-validator.rs b/crates/hotshot/examples/libp2p/multi-validator.rs new file mode 100644 index 0000000000..3ed46fa979 --- /dev/null +++ b/crates/hotshot/examples/libp2p/multi-validator.rs @@ -0,0 +1,69 @@ +use async_compatibility_layer::{ + art::async_spawn, + logging::{setup_backtrace, setup_logging}, +}; +use clap::Parser; +use hotshot::demo::DemoTypes; +use hotshot_orchestrator::client::ValidatorArgs; +use std::net::IpAddr; +use tracing::instrument; + +use crate::types::{DANetwork, NodeImpl, QuorumNetwork, ThisMembership, ThisRun, ViewSyncNetwork}; + +pub mod types; + +#[path = "../infra/mod.rs"] +pub mod infra; +#[path = "../infra/modDA.rs"] +pub mod infra_da; + +#[derive(Parser, Debug, Clone)] +struct MultiValidatorArgs { + /// Number of validators to run + pub num_nodes: u16, + /// The address the orchestrator runs on + pub host: IpAddr, + /// The port the orchestrator runs on + pub port: u16, + /// This node's public IP address, for libp2p + /// If no IP address is passed in, it will default to 127.0.0.1 + pub public_ip: Option, +} + +#[cfg_attr( + async_executor_impl = "tokio", + tokio::main(flavor = "multi_thread", worker_threads = 2) +)] +#[cfg_attr(async_executor_impl = "async-std", async_std::main)] +#[instrument] +async fn main() { + setup_logging(); + setup_backtrace(); + let args = MultiValidatorArgs::parse(); + tracing::error!( + "connecting to orchestrator at {:?}:{:?}", + args.host, + args.port + ); + let mut nodes = Vec::new(); + for _ in 0..args.num_nodes { + let node = async_spawn(async move { + infra_da::main_entry_point::< + DemoTypes, + ThisMembership, + DANetwork, + QuorumNetwork, + ViewSyncNetwork, + NodeImpl, + ThisRun, + >(ValidatorArgs { + host: args.host.to_string(), + port: args.port, + public_ip: args.public_ip, + }) + .await + }); + nodes.push(node); + } + let _result = futures::future::join_all(nodes).await; +} diff --git a/crates/hotshot/examples/libp2p/orchestrator.rs b/crates/hotshot/examples/libp2p/orchestrator.rs index 3bb08103d0..594d004a93 100644 --- a/crates/hotshot/examples/libp2p/orchestrator.rs +++ b/crates/hotshot/examples/libp2p/orchestrator.rs @@ -1,15 +1,21 @@ pub mod types; +use async_compatibility_layer::logging::{setup_backtrace, setup_logging}; use clap::Parser; -use hotshot::demos::vdemo::VDemoTypes; +use hotshot::demo::DemoTypes; use tracing::instrument; use types::ThisMembership; -use crate::infra::{run_orchestrator, OrchestratorArgs}; -use crate::types::{NodeImpl, ThisNetwork}; +use crate::{ + infra::OrchestratorArgs, + infra_da::run_orchestrator_da, + types::{DANetwork, NodeImpl, QuorumNetwork, ViewSyncNetwork}, +}; #[path = "../infra/mod.rs"] pub mod infra; +#[path = "../infra/modDA.rs"] +pub mod infra_da; #[cfg_attr( async_executor_impl = "tokio", @@ -18,7 +24,17 @@ pub mod infra; #[cfg_attr(async_executor_impl = "async-std", async_std::main)] #[instrument] async fn main() { + setup_logging(); + setup_backtrace(); let args = OrchestratorArgs::parse(); - run_orchestrator::(args).await; + run_orchestrator_da::< + DemoTypes, + ThisMembership, + DANetwork, + QuorumNetwork, + ViewSyncNetwork, + NodeImpl, + >(args) + .await; } diff --git a/crates/hotshot/examples/libp2p/types.rs b/crates/hotshot/examples/libp2p/types.rs index 8b3c70e5e1..79b1ea1419 100644 --- a/crates/hotshot/examples/libp2p/types.rs +++ b/crates/hotshot/examples/libp2p/types.rs @@ -1,60 +1,75 @@ -use crate::infra::Libp2pRun; -use hotshot::traits::implementations::MemoryStorage; +use crate::infra_da::Libp2pDARun; use hotshot::{ - demos::vdemo::VDemoTypes, + demo::DemoTypes, traits::{ - election::static_committee::GeneralStaticCommittee, implementations::Libp2pCommChannel, + election::static_committee::GeneralStaticCommittee, + implementations::{Libp2pCommChannel, MemoryStorage}, }, }; -use hotshot_types::message::{Message, ValidatingMessage}; -use hotshot_types::traits::{ - election::QuorumExchange, - node_implementation::{ChannelMaps, NodeImplementation, ValidatingExchanges}, -}; use hotshot_types::{ - data::{ValidatingLeaf, ValidatingProposal}, - traits::node_implementation::NodeType, - vote::QuorumVote, + certificate::ViewSyncCertificate, + data::{DAProposal, QuorumProposal, SequencingLeaf}, + message::{Message, SequencingMessage}, + traits::{ + election::{CommitteeExchange, QuorumExchange, ViewSyncExchange}, + node_implementation::{ChannelMaps, NodeImplementation, NodeType, SequencingExchanges}, + }, + vote::{DAVote, QuorumVote, ViewSyncVote}, }; use serde::{Deserialize, Serialize}; use std::fmt::Debug; -#[derive(Clone, Debug, Deserialize, Serialize, Hash, Eq, PartialEq)] +#[derive(Clone, Debug, Deserialize, Serialize, Hash, PartialEq, Eq)] pub struct NodeImpl {} -pub type ThisLeaf = ValidatingLeaf; +pub type ThisLeaf = SequencingLeaf; pub type ThisMembership = - GeneralStaticCommittee::SignatureKey>; -pub type ThisNetwork = - Libp2pCommChannel; + GeneralStaticCommittee::SignatureKey>; +pub type DANetwork = Libp2pCommChannel; +pub type QuorumNetwork = Libp2pCommChannel; +pub type ViewSyncNetwork = Libp2pCommChannel; + +pub type ThisDAProposal = DAProposal; +pub type ThisDAVote = DAVote; -pub type ThisProposal = ValidatingProposal; -pub type ThisVote = QuorumVote; +pub type ThisQuorumProposal = QuorumProposal; +pub type ThisQuorumVote = QuorumVote; -impl NodeImplementation for NodeImpl { - type Storage = MemoryStorage; - type Leaf = ValidatingLeaf; - type Exchanges = ValidatingExchanges< - VDemoTypes, - Message, +pub type ThisViewSyncProposal = ViewSyncCertificate; +pub type ThisViewSyncVote = ViewSyncVote; + +impl NodeImplementation for NodeImpl { + type Storage = MemoryStorage; + type Leaf = SequencingLeaf; + type Exchanges = SequencingExchanges< + DemoTypes, + Message, QuorumExchange< - VDemoTypes, + DemoTypes, Self::Leaf, - ThisProposal, + ThisQuorumProposal, + ThisMembership, + QuorumNetwork, + Message, + >, + CommitteeExchange>, + ViewSyncExchange< + DemoTypes, + ThisViewSyncProposal, ThisMembership, - ThisNetwork, - Message, + ViewSyncNetwork, + Message, >, >; - type ConsensusMessage = ValidatingMessage; + type ConsensusMessage = SequencingMessage; fn new_channel_maps( - start_view: ::Time, + start_view: ::Time, ) -> ( - ChannelMaps, - Option>, + ChannelMaps, + Option>, ) { (ChannelMaps::new(start_view), None) } } -pub type ThisRun = Libp2pRun; +pub type ThisRun = Libp2pDARun; diff --git a/crates/hotshot/examples/libp2p/validator.rs b/crates/hotshot/examples/libp2p/validator.rs index 59009c9d8f..ab44e02991 100644 --- a/crates/hotshot/examples/libp2p/validator.rs +++ b/crates/hotshot/examples/libp2p/validator.rs @@ -1,15 +1,18 @@ -use crate::infra::main_entry_point; +use async_compatibility_layer::logging::{setup_backtrace, setup_logging}; use clap::Parser; -use hotshot::demos::vdemo::VDemoTypes; -use hotshot_orchestrator::client::ValidatorArgs; -use tracing::instrument; +use hotshot::demo::DemoTypes; +use tracing::{info, instrument}; + +use crate::types::{DANetwork, NodeImpl, QuorumNetwork, ThisMembership, ThisRun, ViewSyncNetwork}; -use crate::types::{NodeImpl, ThisMembership, ThisNetwork, ThisRun}; +use hotshot_orchestrator::client::ValidatorArgs; pub mod types; #[path = "../infra/mod.rs"] pub mod infra; +#[path = "../infra/modDA.rs"] +pub mod infra_da; #[cfg_attr( async_executor_impl = "tokio", @@ -18,6 +21,21 @@ pub mod infra; #[cfg_attr(async_executor_impl = "async-std", async_std::main)] #[instrument] async fn main() { + setup_logging(); + setup_backtrace(); let args = ValidatorArgs::parse(); - main_entry_point::(args).await; + info!( + "connecting to orchestrator at {:?}:{:?}", + args.host, args.port + ); + infra_da::main_entry_point::< + DemoTypes, + ThisMembership, + DANetwork, + QuorumNetwork, + ViewSyncNetwork, + NodeImpl, + ThisRun, + >(args) + .await; } diff --git a/crates/hotshot/examples/web-server-da/multi-validator.rs b/crates/hotshot/examples/web-server-da/multi-validator.rs index 8a0f53c1c9..3ed46fa979 100644 --- a/crates/hotshot/examples/web-server-da/multi-validator.rs +++ b/crates/hotshot/examples/web-server-da/multi-validator.rs @@ -3,7 +3,7 @@ use async_compatibility_layer::{ logging::{setup_backtrace, setup_logging}, }; use clap::Parser; -use hotshot::demos::sdemo::SDemoTypes; +use hotshot::demo::DemoTypes; use hotshot_orchestrator::client::ValidatorArgs; use std::net::IpAddr; use tracing::instrument; @@ -49,7 +49,7 @@ async fn main() { for _ in 0..args.num_nodes { let node = async_spawn(async move { infra_da::main_entry_point::< - SDemoTypes, + DemoTypes, ThisMembership, DANetwork, QuorumNetwork, diff --git a/crates/hotshot/examples/web-server-da/multi-web-server.rs b/crates/hotshot/examples/web-server-da/multi-web-server.rs index c41c9c0b03..f954050ad0 100644 --- a/crates/hotshot/examples/web-server-da/multi-web-server.rs +++ b/crates/hotshot/examples/web-server-da/multi-web-server.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use async_compatibility_layer::{art::async_spawn, channel::oneshot}; use clap::Parser; -use hotshot::demos::sdemo::SDemoTypes; +use hotshot::demo::DemoTypes; use tracing::error; #[derive(Parser, Debug)] @@ -27,7 +27,7 @@ async fn main() { let cdn_server = async_spawn(async move { if let Err(e) = hotshot_web_server::run_web_server::< - ::SignatureKey, + ::SignatureKey, >(Some(server_shutdown_cdn), args.cdn_port) .await { @@ -37,7 +37,7 @@ async fn main() { }); let da_server = async_spawn(async move { if let Err(e) = hotshot_web_server::run_web_server::< - ::SignatureKey, + ::SignatureKey, >(Some(server_shutdown_da), args.da_port) .await { @@ -47,7 +47,7 @@ async fn main() { }); let vs_server = async_spawn(async move { if let Err(e) = hotshot_web_server::run_web_server::< - ::SignatureKey, + ::SignatureKey, >(Some(server_shutdown_view_sync), args.view_sync_port) .await { diff --git a/crates/hotshot/examples/web-server-da/orchestrator.rs b/crates/hotshot/examples/web-server-da/orchestrator.rs index 772d3aa12e..594d004a93 100644 --- a/crates/hotshot/examples/web-server-da/orchestrator.rs +++ b/crates/hotshot/examples/web-server-da/orchestrator.rs @@ -2,7 +2,7 @@ pub mod types; use async_compatibility_layer::logging::{setup_backtrace, setup_logging}; use clap::Parser; -use hotshot::demos::sdemo::SDemoTypes; +use hotshot::demo::DemoTypes; use tracing::instrument; use types::ThisMembership; @@ -29,7 +29,7 @@ async fn main() { let args = OrchestratorArgs::parse(); run_orchestrator_da::< - SDemoTypes, + DemoTypes, ThisMembership, DANetwork, QuorumNetwork, diff --git a/crates/hotshot/examples/web-server-da/types.rs b/crates/hotshot/examples/web-server-da/types.rs index 9ea1f9a694..017784b354 100644 --- a/crates/hotshot/examples/web-server-da/types.rs +++ b/crates/hotshot/examples/web-server-da/types.rs @@ -1,6 +1,6 @@ use crate::infra_da::WebServerDARun; use hotshot::{ - demos::sdemo::SDemoTypes, + demo::DemoTypes, traits::{ election::static_committee::GeneralStaticCommittee, implementations::{MemoryStorage, WebCommChannel}, @@ -22,57 +22,54 @@ use std::fmt::Debug; #[derive(Clone, Debug, Deserialize, Serialize, Hash, PartialEq, Eq)] pub struct NodeImpl {} -pub type ThisLeaf = SequencingLeaf; +pub type ThisLeaf = SequencingLeaf; pub type ThisMembership = - GeneralStaticCommittee::SignatureKey>; -pub type DANetwork = - WebCommChannel; -pub type QuorumNetwork = - WebCommChannel; -pub type ViewSyncNetwork = - WebCommChannel; + GeneralStaticCommittee::SignatureKey>; +pub type DANetwork = WebCommChannel; +pub type QuorumNetwork = WebCommChannel; +pub type ViewSyncNetwork = WebCommChannel; -pub type ThisDAProposal = DAProposal; -pub type ThisDAVote = DAVote; +pub type ThisDAProposal = DAProposal; +pub type ThisDAVote = DAVote; -pub type ThisQuorumProposal = QuorumProposal; -pub type ThisQuorumVote = QuorumVote; +pub type ThisQuorumProposal = QuorumProposal; +pub type ThisQuorumVote = QuorumVote; -pub type ThisViewSyncProposal = ViewSyncCertificate; -pub type ThisViewSyncVote = ViewSyncVote; +pub type ThisViewSyncProposal = ViewSyncCertificate; +pub type ThisViewSyncVote = ViewSyncVote; -impl NodeImplementation for NodeImpl { - type Storage = MemoryStorage; - type Leaf = SequencingLeaf; +impl NodeImplementation for NodeImpl { + type Storage = MemoryStorage; + type Leaf = SequencingLeaf; type Exchanges = SequencingExchanges< - SDemoTypes, - Message, + DemoTypes, + Message, QuorumExchange< - SDemoTypes, + DemoTypes, Self::Leaf, ThisQuorumProposal, ThisMembership, QuorumNetwork, - Message, + Message, >, - CommitteeExchange>, + CommitteeExchange>, ViewSyncExchange< - SDemoTypes, + DemoTypes, ThisViewSyncProposal, ThisMembership, ViewSyncNetwork, - Message, + Message, >, >; - type ConsensusMessage = SequencingMessage; + type ConsensusMessage = SequencingMessage; fn new_channel_maps( - start_view: ::Time, + start_view: ::Time, ) -> ( - ChannelMaps, - Option>, + ChannelMaps, + Option>, ) { (ChannelMaps::new(start_view), None) } } -pub type ThisRun = WebServerDARun; +pub type ThisRun = WebServerDARun; diff --git a/crates/hotshot/examples/web-server-da/validator.rs b/crates/hotshot/examples/web-server-da/validator.rs index ec2415fd65..ab44e02991 100644 --- a/crates/hotshot/examples/web-server-da/validator.rs +++ b/crates/hotshot/examples/web-server-da/validator.rs @@ -1,6 +1,6 @@ use async_compatibility_layer::logging::{setup_backtrace, setup_logging}; use clap::Parser; -use hotshot::demos::sdemo::SDemoTypes; +use hotshot::demo::DemoTypes; use tracing::{info, instrument}; use crate::types::{DANetwork, NodeImpl, QuorumNetwork, ThisMembership, ThisRun, ViewSyncNetwork}; @@ -29,7 +29,7 @@ async fn main() { args.host, args.port ); infra_da::main_entry_point::< - SDemoTypes, + DemoTypes, ThisMembership, DANetwork, QuorumNetwork, diff --git a/crates/hotshot/examples/web-server-da/web-server.rs b/crates/hotshot/examples/web-server-da/web-server.rs index 99d0b12f63..9c4912c6a3 100644 --- a/crates/hotshot/examples/web-server-da/web-server.rs +++ b/crates/hotshot/examples/web-server-da/web-server.rs @@ -1,4 +1,4 @@ -use hotshot::demos::sdemo::SDemoTypes; +use hotshot::demo::DemoTypes; use std::sync::Arc; use async_compatibility_layer::{ @@ -23,7 +23,7 @@ async fn main() { let (server_shutdown_sender, server_shutdown) = oneshot(); let _sender = Arc::new(server_shutdown_sender); let _result = hotshot_web_server::run_web_server::< - ::SignatureKey, + ::SignatureKey, >(Some(server_shutdown), args.port) .await; } diff --git a/crates/hotshot/src/demo.rs b/crates/hotshot/src/demo.rs new file mode 100644 index 0000000000..81cac76f4b --- /dev/null +++ b/crates/hotshot/src/demo.rs @@ -0,0 +1,207 @@ +//! Sequencing consensus demo +//! +//! This module provides an implementation of the `HotShot` suite of traits that implements a +//! basic demonstration of sequencing consensus. +//! +//! These implementations are useful in examples and integration testing, but are not suitable for +//! production use. +use crate::traits::election::static_committee::{StaticElectionConfig, StaticVoteToken}; +use commit::{Commitment, Committable}; +use derivative::Derivative; +use either::Either; +use hotshot_signature_key::bn254::BLSPubKey; +use hotshot_types::{ + block_impl::{BlockPayloadError, VIDBlockPayload, VIDTransaction}, + certificate::{AssembledSignature, QuorumCertificate}, + data::{ + fake_commitment, genesis_proposer_id, random_commitment, LeafType, SequencingLeaf, + ViewNumber, + }, + traits::{ + election::Membership, + node_implementation::NodeType, + state::{ConsensusTime, TestableState}, + BlockPayload, State, + }, +}; +use rand::Rng; +use serde::{Deserialize, Serialize}; +use std::{fmt::Debug, marker::PhantomData}; + +/// sequencing demo entry state +#[derive(PartialEq, Eq, Hash, Serialize, Deserialize, Clone, Debug)] +pub struct SDemoState { + /// the block height + block_height: u64, + /// the view number + view_number: ViewNumber, + /// the previous state commitment + prev_state_commitment: Commitment, +} + +impl Committable for SDemoState { + fn commit(&self) -> Commitment { + commit::RawCommitmentBuilder::new("SDemo State Commit") + .u64_field("block_height", self.block_height) + .u64_field("view_number", *self.view_number) + .field("prev_state_commitment", self.prev_state_commitment) + .finalize() + } + + fn tag() -> String { + "SEQUENCING_DEMO_STATE".to_string() + } +} + +impl Default for SDemoState { + fn default() -> Self { + Self { + block_height: 0, + view_number: ViewNumber::genesis(), + prev_state_commitment: fake_commitment(), + } + } +} + +impl State for SDemoState { + type Error = BlockPayloadError; + + type BlockType = VIDBlockPayload; + + type Time = ViewNumber; + + fn validate_block(&self, _block: &Self::BlockType, view_number: &Self::Time) -> bool { + if view_number == &ViewNumber::genesis() { + &self.view_number == view_number + } else { + self.view_number < *view_number + } + } + + fn append( + &self, + block: &Self::BlockType, + view_number: &Self::Time, + ) -> Result { + if !self.validate_block(block, view_number) { + return Err(BlockPayloadError::InvalidBlock); + } + + Ok(SDemoState { + block_height: self.block_height + 1, + view_number: *view_number, + prev_state_commitment: self.commit(), + }) + } + + fn on_commit(&self) {} +} + +impl TestableState for SDemoState { + fn create_random_transaction( + _state: Option<&Self>, + _rng: &mut dyn rand::RngCore, + padding: u64, + ) -> ::Transaction { + /// clippy appeasement for `RANDOM_TX_BASE_SIZE` + const RANDOM_TX_BASE_SIZE: usize = 8; + VIDTransaction(vec![0; RANDOM_TX_BASE_SIZE + (padding as usize)]) + } +} +/// Implementation of [`NodeType`] for [`VDemoNode`] +#[derive( + Copy, + Clone, + Debug, + Default, + Hash, + PartialEq, + Eq, + PartialOrd, + Ord, + serde::Serialize, + serde::Deserialize, +)] +pub struct DemoTypes; + +impl NodeType for DemoTypes { + type Time = ViewNumber; + type BlockType = VIDBlockPayload; + type SignatureKey = BLSPubKey; + type VoteTokenType = StaticVoteToken; + type Transaction = VIDTransaction; + type ElectionConfigType = StaticElectionConfig; + type StateType = SDemoState; +} + +/// The node implementation for the sequencing demo +#[derive(Derivative)] +#[derivative(Clone(bound = ""))] +pub struct SDemoNode(PhantomData) +where + MEMBERSHIP: Membership + std::fmt::Debug; + +impl SDemoNode +where + MEMBERSHIP: Membership + std::fmt::Debug, +{ + /// Create a new `SDemoNode` + #[must_use] + pub fn new() -> Self { + SDemoNode(PhantomData) + } +} + +impl Debug for SDemoNode +where + MEMBERSHIP: Membership + std::fmt::Debug, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("SDemoNode") + .field("_phantom", &"phantom") + .finish() + } +} + +impl Default for SDemoNode +where + MEMBERSHIP: Membership + std::fmt::Debug, +{ + fn default() -> Self { + Self::new() + } +} + +/// Provides a random [`QuorumCertificate`] +pub fn random_quorum_certificate>( + rng: &mut dyn rand::RngCore, +) -> QuorumCertificate> { + QuorumCertificate { + // block_commitment: random_commitment(rng), + leaf_commitment: random_commitment(rng), + view_number: TYPES::Time::new(rng.gen()), + signatures: AssembledSignature::Genesis(), + is_genesis: rng.gen(), + } +} + +/// Provides a random [`SequencingLeaf`] +pub fn random_sequencing_leaf( + deltas: Either>, + rng: &mut dyn rand::RngCore, +) -> SequencingLeaf { + let justify_qc = random_quorum_certificate(rng); + // let state = TYPES::StateType::default() + // .append(&deltas, &TYPES::Time::new(42)) + // .unwrap_or_default(); + SequencingLeaf { + view_number: justify_qc.view_number, + height: rng.next_u64(), + justify_qc, + parent_commitment: random_commitment(rng), + deltas, + rejected: Vec::new(), + timestamp: time::OffsetDateTime::now_utc().unix_timestamp_nanos(), + proposer_id: genesis_proposer_id(), + } +} diff --git a/crates/hotshot/src/demos.rs b/crates/hotshot/src/demos.rs deleted file mode 100644 index 7ddbef89c6..0000000000 --- a/crates/hotshot/src/demos.rs +++ /dev/null @@ -1,8 +0,0 @@ -//! Contains implementations of the `HotShot` traits used in the examples and integration testing. -//! -//! These implementations are not suitable for production use. - -/// this is a demo for sequencing consensus -pub mod sdemo; -/// this is a demo for validating consensus -pub mod vdemo; diff --git a/crates/hotshot/src/demos/sdemo.rs b/crates/hotshot/src/demos/sdemo.rs deleted file mode 100644 index 97117347a9..0000000000 --- a/crates/hotshot/src/demos/sdemo.rs +++ /dev/null @@ -1,384 +0,0 @@ -//! Sequencing consensus demo -//! -//! This module provides an implementation of the `HotShot` suite of traits that implements a -//! basic demonstration of sequencing consensus. -//! -//! These implementations are useful in examples and integration testing, but are not suitable for -//! production use. -use crate::traits::election::static_committee::{StaticElectionConfig, StaticVoteToken}; -use std::{ - collections::HashSet, - fmt::{Debug, Display}, - marker::PhantomData, - ops::Deref, -}; - -use commit::{Commitment, Committable}; -use derivative::Derivative; -use either::Either; -use hotshot_signature_key::bn254::BN254Pub; -use hotshot_types::{ - certificate::{AssembledSignature, QuorumCertificate}, - constants::genesis_proposer_id, - data::{fake_commitment, random_commitment, LeafType, SequencingLeaf, ViewNumber}, - traits::{ - block_contents::Transaction, - election::Membership, - node_implementation::NodeType, - state::{ConsensusTime, TestableBlock, TestableState}, - Block, State, - }, -}; -use rand::Rng; -use serde::{Deserialize, Serialize}; -use snafu::Snafu; - -/// The transaction for the sequencing demo -#[derive(PartialEq, Eq, Hash, Serialize, Deserialize, Clone, Debug)] -pub struct SDemoTransaction { - /// identifier for the transaction - pub id: u64, - /// padding to add to txn (to make it larger and thereby more realistic) - pub padding: Vec, -} - -impl Deref for SDemoTransaction { - type Target = u64; - - fn deref(&self) -> &Self::Target { - &self.id - } -} - -impl Committable for SDemoTransaction { - fn commit(&self) -> Commitment { - commit::RawCommitmentBuilder::new("SDemo Txn Comm") - .u64_field("id", self.id) - .finalize() - } - - fn tag() -> String { - "SEQUENCING_DEMO_TXN".to_string() - } -} - -impl Transaction for SDemoTransaction {} - -impl SDemoTransaction { - /// create a new transaction - #[must_use] - pub fn new(id: u64) -> Self { - Self { - id, - padding: vec![], - } - } -} - -/// genesis block -#[derive(PartialEq, Eq, Hash, Serialize, Deserialize, Clone, Debug)] -pub struct SDemoGenesisBlock {} - -/// Any block after genesis -#[derive(PartialEq, Eq, Hash, Serialize, Deserialize, Clone, Debug)] -pub struct SDemoNormalBlock { - /// Block state commitment - pub previous_state: (), - /// Transaction vector - pub transactions: Vec, -} - -/// The block for the sequencing demo -#[derive(PartialEq, Eq, Hash, Serialize, Deserialize, Clone, Debug)] -pub enum SDemoBlock { - /// genesis block - Genesis(SDemoGenesisBlock), - /// normal block - Normal(SDemoNormalBlock), -} - -impl Committable for SDemoBlock { - fn commit(&self) -> Commitment { - match &self { - SDemoBlock::Genesis(_) => { - commit::RawCommitmentBuilder::new("SDemo Genesis Comm").finalize() - } - SDemoBlock::Normal(block) => { - let mut builder = commit::RawCommitmentBuilder::new("SDemo Normal Comm"); - for txn in &block.transactions { - builder = builder.u64_field("transaction", **txn); - } - builder.finalize() - } - } - } - - fn tag() -> String { - "SEQUENCING_DEMO_BLOCK".to_string() - } -} - -/// sequencing demo entry state -#[derive(PartialEq, Eq, Hash, Serialize, Deserialize, Clone, Debug)] -pub struct SDemoState { - /// the block height - block_height: u64, - /// the view number - view_number: ViewNumber, - /// the previous state commitment - prev_state_commitment: Commitment, -} - -impl Committable for SDemoState { - fn commit(&self) -> Commitment { - commit::RawCommitmentBuilder::new("SDemo State Commit") - .u64_field("block_height", self.block_height) - .u64_field("view_number", *self.view_number) - .field("prev_state_commitment", self.prev_state_commitment) - .finalize() - } - - fn tag() -> String { - "SEQUENCING_DEMO_STATE".to_string() - } -} - -impl Default for SDemoState { - fn default() -> Self { - Self { - block_height: 0, - view_number: ViewNumber::genesis(), - prev_state_commitment: fake_commitment(), - } - } -} - -/// The error type for the sequencing demo -#[derive(Snafu, Debug)] -pub enum SDemoError { - /// Previous state commitment does not match - PreviousStateMismatch, - /// Nonce was reused - ReusedTxn, - /// Genesis failure - GenesisFailed, - /// Genesis reencountered after initialization - GenesisAfterStart, - /// no transasctions added to genesis - GenesisCantHaveTransactions, - /// invalid block - InvalidBlock, -} - -impl Display for SDemoBlock { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - SDemoBlock::Genesis(_) => { - write!(f, "SDemo Genesis Block") - } - SDemoBlock::Normal(block) => { - write!(f, "SDemo Normal Block #txns={}", block.transactions.len()) - } - } - } -} - -impl TestableBlock for SDemoBlock { - fn genesis() -> Self { - SDemoBlock::Genesis(SDemoGenesisBlock {}) - } - - fn txn_count(&self) -> u64 { - match self { - SDemoBlock::Genesis(_) => 0, - SDemoBlock::Normal(n) => n.transactions.len() as u64, - } - } -} - -impl Block for SDemoBlock { - type Error = SDemoError; - - type Transaction = SDemoTransaction; - - fn new() -> Self { - ::genesis() - } - - fn add_transaction_raw( - &self, - tx: &Self::Transaction, - ) -> std::result::Result { - match self { - SDemoBlock::Genesis(_) => Err(SDemoError::GenesisCantHaveTransactions), - SDemoBlock::Normal(n) => { - let mut new = n.clone(); - new.transactions.push(tx.clone()); - Ok(SDemoBlock::Normal(new)) - } - } - } - - fn contained_transactions(&self) -> HashSet> { - match self { - SDemoBlock::Genesis(_) => HashSet::new(), - SDemoBlock::Normal(n) => n - .transactions - .iter() - .map(commit::Committable::commit) - .collect(), - } - } -} - -impl State for SDemoState { - type Error = SDemoError; - - type BlockType = SDemoBlock; - - type Time = ViewNumber; - - fn next_block(_state: Option) -> Self::BlockType { - SDemoBlock::Normal(SDemoNormalBlock { - previous_state: (), - transactions: Vec::new(), - }) - } - - fn validate_block(&self, block: &Self::BlockType, view_number: &Self::Time) -> bool { - match block { - SDemoBlock::Genesis(_) => { - view_number == &ViewNumber::genesis() && view_number == &self.view_number - } - SDemoBlock::Normal(_n) => self.view_number < *view_number, - } - } - - fn append( - &self, - block: &Self::BlockType, - view_number: &Self::Time, - ) -> Result { - if !self.validate_block(block, view_number) { - return Err(SDemoError::InvalidBlock); - } - - Ok(SDemoState { - block_height: self.block_height + 1, - view_number: *view_number, - prev_state_commitment: self.commit(), - }) - } - - fn on_commit(&self) {} -} - -impl TestableState for SDemoState { - fn create_random_transaction( - _state: Option<&Self>, - rng: &mut dyn rand::RngCore, - padding: u64, - ) -> ::Transaction { - SDemoTransaction { - id: rng.gen_range(0..10), - padding: vec![0; padding as usize], - } - } -} -/// Implementation of [`NodeType`] for [`VDemoNode`] -#[derive( - Copy, - Clone, - Debug, - Default, - Hash, - PartialEq, - Eq, - PartialOrd, - Ord, - serde::Serialize, - serde::Deserialize, -)] -pub struct SDemoTypes; - -impl NodeType for SDemoTypes { - type Time = ViewNumber; - type BlockType = SDemoBlock; - type SignatureKey = BN254Pub; - type VoteTokenType = StaticVoteToken; - type Transaction = SDemoTransaction; - type ElectionConfigType = StaticElectionConfig; - type StateType = SDemoState; -} - -/// The node implementation for the sequencing demo -#[derive(Derivative)] -#[derivative(Clone(bound = ""))] -pub struct SDemoNode(PhantomData) -where - MEMBERSHIP: Membership + std::fmt::Debug; - -impl SDemoNode -where - MEMBERSHIP: Membership + std::fmt::Debug, -{ - /// Create a new `SDemoNode` - #[must_use] - pub fn new() -> Self { - SDemoNode(PhantomData) - } -} - -impl Debug for SDemoNode -where - MEMBERSHIP: Membership + std::fmt::Debug, -{ - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("SDemoNode") - .field("_phantom", &"phantom") - .finish() - } -} - -impl Default for SDemoNode -where - MEMBERSHIP: Membership + std::fmt::Debug, -{ - fn default() -> Self { - Self::new() - } -} - -/// Provides a random [`QuorumCertificate`] -pub fn random_quorum_certificate>( - rng: &mut dyn rand::RngCore, -) -> QuorumCertificate { - QuorumCertificate { - // block_commitment: random_commitment(rng), - leaf_commitment: random_commitment(rng), - view_number: TYPES::Time::new(rng.gen()), - signatures: AssembledSignature::Genesis(), - is_genesis: rng.gen(), - } -} - -/// Provides a random [`SequencingLeaf`] -pub fn random_sequencing_leaf( - deltas: Either>, - rng: &mut dyn rand::RngCore, -) -> SequencingLeaf { - let justify_qc = random_quorum_certificate(rng); - // let state = TYPES::StateType::default() - // .append(&deltas, &TYPES::Time::new(42)) - // .unwrap_or_default(); - SequencingLeaf { - view_number: justify_qc.view_number, - height: rng.next_u64(), - justify_qc, - parent_commitment: random_commitment(rng), - deltas, - rejected: Vec::new(), - timestamp: time::OffsetDateTime::now_utc().unix_timestamp_nanos(), - proposer_id: genesis_proposer_id(), - } -} diff --git a/crates/hotshot/src/demos/vdemo.rs b/crates/hotshot/src/demos/vdemo.rs deleted file mode 100644 index 1d091c60b1..0000000000 --- a/crates/hotshot/src/demos/vdemo.rs +++ /dev/null @@ -1,607 +0,0 @@ -// //! Validating (vanilla) consensus demo -// //! -// //! This module provides an implementation of the `HotShot` suite of traits that implements a -// //! basic demonstration of validating consensus. -// //! -// //! These implementations are useful in examples and integration testing, but are not suitable for -// //! production use. -// -// use crate::traits::{ -// election::static_committee::{StaticElectionConfig, StaticVoteToken}, -// Block, -// }; -// use commit::{Commitment, Committable}; -// use derivative::Derivative; -// -// use hotshot_types::{ -// certificate::{QuorumCertificate, YesNoSignature}, -// constants::genesis_proposer_id, -// data::{random_commitment, LeafType, ValidatingLeaf, ViewNumber}, -// traits::{ -// block_contents::Transaction, -// consensus_type::validating_consensus::ValidatingConsensus, -// election::Membership, -// node_implementation::NodeType, -// signature_key::ed25519::Ed25519Pub, -// state::{ConsensusTime, TestableBlock, TestableState}, -// State, -// }, -// }; -// -// use rand::Rng; -// use serde::{Deserialize, Serialize}; -// use snafu::{ensure, Snafu}; -// use std::{ -// collections::{BTreeMap, HashSet}, -// fmt::{Debug, Display}, -// marker::PhantomData, -// }; -// use tracing::error; -// -// /// The account identifier type used by the demo -// /// -// /// This is a type alias to [`String`] for simplicity. -// pub type Account = String; -// -// /// The account balance type used by the demo -// /// -// /// This is a type alias to [`u64`] for simplicity. -// pub type Balance = u64; -// -// /// Records a reduction in an account balance -// #[derive(PartialEq, Eq, Hash, Serialize, Deserialize, Clone, Debug)] -// pub struct Subtraction { -// /// An account identifier -// pub account: Account, -// /// An account balance -// pub amount: Balance, -// } -// -// /// Records an increase in an account balance -// #[derive(PartialEq, Eq, Hash, Serialize, Deserialize, Clone, Debug)] -// pub struct Addition { -// /// An account identifier -// pub account: Account, -// /// An account balance -// pub amount: Balance, -// } -// -// /// The error type for the validating demo -// #[derive(Snafu, Debug)] -// pub enum VDemoError { -// /// The subtraction and addition amounts for this transaction were not equal -// InconsistentTransaction, -// /// No such input account exists -// NoSuchInputAccount, -// /// No such output account exists -// NoSuchOutputAccount, -// /// Tried to move more money than was in the account -// InsufficentBalance, -// /// Previous state commitment does not match -// PreviousStateMismatch, -// /// Nonce was reused -// ReusedNonce, -// /// Genesis failure -// GenesisFailed, -// /// Genesis reencountered after initialization -// GenesisAfterStart, -// } -// -// /// The transaction for the validating demo -// #[derive(PartialEq, Eq, Hash, Serialize, Deserialize, Clone, Debug)] -// pub struct VDemoTransaction { -// /// An increment to an account balance -// pub add: Addition, -// /// A decrement to an account balance -// pub sub: Subtraction, -// /// The nonce for a transaction, no two transactions can have the same nonce -// pub nonce: u64, -// /// Number of bytes to pad to each transaction -// pub padding: Vec, -// } -// -// impl Transaction for VDemoTransaction {} -// -// impl VDemoTransaction { -// /// Ensures that this transaction is at least consistent with itself -// #[must_use] -// pub fn validate_independence(&self) -> bool { -// // Ensure that we are adding to one account exactly as much as we are subtracting from -// // another -// self.add.amount <= self.sub.amount // TODO why not strict equality? -// } -// } -// -// /// The state for the validating demo -// /// NOTE both fields are btrees because we need -// /// ordered-ing otherwise commitments will not match -// #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, Hash)] -// pub struct VDemoState { -// /// Key/value store of accounts and balances -// pub balances: BTreeMap, -// // /// Set of previously seen nonces -// // pub nonces: BTreeSet, -// } -// -// impl Committable for VDemoState { -// fn commit(&self) -> Commitment { -// let mut builder = commit::RawCommitmentBuilder::new("VDemo State Comm"); -// -// for (k, v) in &self.balances { -// builder = builder.u64_field(k, *v); -// } -// builder = builder.constant_str("nonces"); -// -// // for nonce in &self.nonces { -// // builder = builder.u64(*nonce); -// // } -// -// builder.finalize() -// } -// -// fn tag() -> String { -// "VALIDATING_DEMO_STATE".to_string() -// } -// } -// -// /// initializes the first state on genesis -// #[derive(PartialEq, Eq, Hash, Serialize, Deserialize, Clone, Debug)] -// pub struct VDemoGenesisBlock { -// /// initializes the first state -// pub accounts: BTreeMap, -// } -// -// /// Any block after genesis -// #[derive(PartialEq, Eq, Hash, Serialize, Deserialize, Clone, Debug)] -// pub struct VDemoNormalBlock { -// /// Block state commitment -// pub previous_state: Commitment, -// /// Transaction vector -// pub transactions: Vec, -// } -// -// /// The block for the validating demo -// #[derive(PartialEq, Eq, Hash, Serialize, Deserialize, Clone, Debug)] -// pub enum VDemoBlock { -// /// genesis block -// Genesis(VDemoGenesisBlock), -// /// normal block -// Normal(VDemoNormalBlock), -// } -// -// impl Committable for VDemoBlock { -// fn commit(&self) -> Commitment { -// match &self { -// VDemoBlock::Genesis(block) => { -// let mut builder = commit::RawCommitmentBuilder::new("VDemo Genesis Comm") -// .u64_field("account_count", block.accounts.len() as u64); -// for account in &block.accounts { -// builder = builder.u64_field(account.0, *account.1); -// } -// builder.finalize() -// } -// VDemoBlock::Normal(block) => { -// let mut builder = commit::RawCommitmentBuilder::new("VDemo Block Comm") -// .var_size_field("Previous State", block.previous_state.as_ref()); -// -// for txn in &block.transactions { -// builder = builder -// .u64_field(&txn.add.account, txn.add.amount) -// .u64_field(&txn.sub.account, txn.sub.amount) -// .constant_str("nonce") -// .u64_field("nonce", txn.nonce); -// } -// -// builder.finalize() -// } -// } -// } -// -// fn tag() -> String { -// "VALIDATING_DEMO_BLOCK".to_string() -// } -// } -// -// impl Committable for VDemoTransaction { -// fn commit(&self) -> Commitment { -// commit::RawCommitmentBuilder::new("VDemo Txn Comm") -// .u64_field(&self.add.account, self.add.amount) -// .u64_field(&self.sub.account, self.sub.amount) -// .constant_str("nonce") -// .u64_field("nonce", self.nonce) -// .finalize() -// } -// -// fn tag() -> String { -// "VALIDATING_DEMO_TXN".to_string() -// } -// } -// -// impl VDemoBlock { -// /// generate a genesis block with the provided initial accounts and balances -// #[must_use] -// pub fn genesis_from(accounts: BTreeMap) -> Self { -// Self::Genesis(VDemoGenesisBlock { accounts }) -// } -// } -// -// impl State for VDemoState { -// type Error = VDemoError; -// -// type BlockType = VDemoBlock; -// -// type Time = ViewNumber; -// -// #[allow(clippy::panic)] -// fn next_block(state: Option) -> Self::BlockType { -// match state { -// Some(state) => VDemoBlock::Normal(VDemoNormalBlock { -// previous_state: state.commit(), -// transactions: Vec::new(), -// }), -// None => panic!("State is required for the next block"), -// } -// } -// -// // Note: validate_block is actually somewhat redundant, its meant to be a quick and dirty check -// // for clarity, the logic is duplicated with append_to -// fn validate_block(&self, block: &Self::BlockType, _view_number: &Self::Time) -> bool { -// match block { -// VDemoBlock::Genesis(_) => self.balances.is_empty(), // && self.nonces.is_empty(), -// VDemoBlock::Normal(block) => { -// let state = self; -// // A valid block is one in which every transaction is internally consistent, and results in -// // nobody having a negative balance -// // -// // We will check this, in this case, by making a trial copy of our balances map, making -// // trial modifications to it, and then asserting that no balances are negative -// let mut trial_balances = state.balances.clone(); -// for tx in &block.transactions { -// // This is a macro from SNAFU that returns an Err if the condition is not satisfied -// // -// // We first check that the transaction is internally consistent, then apply the change -// // to our trial map -// if !tx.validate_independence() { -// error!("validate_independence failed"); -// return false; -// } -// // Find the input account, and subtract the transfer balance from it, failing if it -// // doesn't exist -// if let Some(input_account) = trial_balances.get_mut(&tx.sub.account) { -// *input_account -= tx.sub.amount; -// } else { -// error!("no such input account"); -// return false; -// } -// // Find the output account, and add the transfer balance to it, failing if it doesn't -// // exist -// if let Some(output_account) = trial_balances.get_mut(&tx.add.account) { -// *output_account += tx.add.amount; -// } else { -// error!("no such output account"); -// return false; -// } -// // // Check to make sure the nonce isn't used -// // if state.nonces.contains(&tx.nonce) { -// // warn!(?state, ?tx, "State nonce is used for transaction"); -// // return false; -// // } -// } -// // This block has now passed all our tests, and thus has not done anything bad, so the block -// // is valid if its previous state hash matches that of the previous state -// let result = block.previous_state == state.commit(); -// if !result { -// error!( -// "hash failure. previous_block: {:?} hash_state: {:?}", -// block.previous_state, -// state.commit() -// ); -// } -// result -// } -// } -// } -// -// fn append( -// &self, -// block: &Self::BlockType, -// _view_number: &Self::Time, -// ) -> std::result::Result { -// match block { -// VDemoBlock::Genesis(block) => { -// if self.balances.is_empty() { -// // && self.nonces.is_empty() -// let mut new_state = Self::default(); -// for account in &block.accounts { -// if new_state -// .balances -// .insert(account.0.clone(), *account.1) -// .is_some() -// { -// error!("Adding the same account twice during application of genesis block!"); -// return Err(VDemoError::GenesisFailed); -// } -// } -// Ok(new_state) -// } else { -// Err(VDemoError::GenesisAfterStart) -// } -// } -// VDemoBlock::Normal(block) => { -// let state = self; -// // A valid block is one in which every transaction is internally consistent, and results in -// // nobody having a negative balance -// // -// // We will check this, in this case, by making a trial copy of our balances map, making -// // trial modifications to it, and then asserting that no balances are negative -// let mut trial_balances = state.balances.clone(); -// for tx in &block.transactions { -// // This is a macro from SNAFU that returns an Err if the condition is not satisfied -// // -// // We first check that the transaction is internally consistent, then apply the change -// // to our trial map -// ensure!(tx.validate_independence(), InconsistentTransactionSnafu); -// // Find the input account, and subtract the transfer balance from it, failing if it -// // doesn't exist -// if let Some(input_account) = trial_balances.get_mut(&tx.sub.account) { -// *input_account -= tx.sub.amount; -// } else { -// return Err(VDemoError::NoSuchInputAccount); -// } -// // Find the output account, and add the transfer balance to it, failing if it doesn't -// // exist -// if let Some(output_account) = trial_balances.get_mut(&tx.add.account) { -// *output_account += tx.add.amount; -// } else { -// return Err(VDemoError::NoSuchOutputAccount); -// } -// // // Check for nonce reuse -// // if state.nonces.contains(&tx.nonce) { -// // return Err(VDemoError::ReusedNonce); -// // } -// } -// // Make sure our previous state commitment matches the provided state -// if block.previous_state == state.commit() { -// // This block has now passed all our tests, and thus has not done anything bad -// // Add the nonces from this block -// // let mut nonces = state.nonces.clone(); -// // for tx in &block.transactions { -// // nonces.insert(tx.nonce); -// // } -// Ok(VDemoState { -// balances: trial_balances, -// // nonces, -// }) -// } else { -// Err(VDemoError::PreviousStateMismatch) -// } -// } -// } -// } -// -// fn on_commit(&self) { -// // Does nothing in this implementation -// } -// } -// -// impl Display for VDemoBlock { -// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { -// match self { -// VDemoBlock::Genesis(block) => { -// write!(f, "VDemo Genesis Block: {block:#?}") -// } -// VDemoBlock::Normal(block) => { -// write!(f, "VDemo Normal Block #txns={}", block.transactions.len()) -// } -// } -// } -// } -// -// impl TestableState for VDemoState { -// fn create_random_transaction( -// state: Option<&Self>, -// rng: &mut dyn rand::RngCore, -// padding: u64, -// ) -> ::Transaction { -// use rand::seq::IteratorRandom; -// -// let state = state.expect("Missing state"); -// -// let non_zero_balances = state -// .balances -// .iter() -// .filter(|b| *b.1 > 0) -// .collect::>(); -// -// assert!( -// !non_zero_balances.is_empty(), -// "No nonzero balances were available! Unable to generate transaction." -// ); -// -// let input_account = non_zero_balances.iter().choose(rng).unwrap().0; -// let output_account = state.balances.keys().choose(rng).unwrap(); -// let amount = rng.gen_range(0..100); -// -// VDemoTransaction { -// add: Addition { -// account: output_account.to_string(), -// amount, -// }, -// sub: Subtraction { -// account: input_account.to_string(), -// amount, -// }, -// nonce: rng.gen(), -// padding: vec![0; padding as usize], -// } -// } -// } -// -// impl TestableBlock for VDemoBlock { -// fn genesis() -> Self { -// let accounts: BTreeMap = vec![ -// ("Joe", 1_000_000), -// ("Nathan M", 500_000), -// ("John", 400_000), -// ("Nathan Y", 600_000), -// ("Ian", 5_000_000), -// ] -// .into_iter() -// .map(|(x, y)| (x.to_string(), y)) -// .collect(); -// Self::Genesis(VDemoGenesisBlock { accounts }) -// } -// -// fn txn_count(&self) -> u64 { -// if let VDemoBlock::Normal(block) = self { -// block.transactions.len() as u64 -// } else { -// 0 -// } -// } -// } -// -// impl Block for VDemoBlock { -// type Transaction = VDemoTransaction; -// -// type Error = VDemoError; -// -// fn new() -> Self { -// ::genesis() -// } -// -// fn add_transaction_raw( -// &self, -// tx: &Self::Transaction, -// ) -> std::result::Result { -// match self { -// VDemoBlock::Genesis(_) => Err(VDemoError::GenesisAfterStart), -// VDemoBlock::Normal(block) => { -// // first, make sure that the transaction is internally valid -// if tx.validate_independence() { -// // Then check the previous transactions in the block -// if block.transactions.iter().any(|x| x.nonce == tx.nonce) { -// return Err(VDemoError::ReusedNonce); -// } -// let mut new_block = block.clone(); -// // Insert our transaction and return -// new_block.transactions.push(tx.clone()); -// Ok(VDemoBlock::Normal(new_block)) -// } else { -// Err(VDemoError::InconsistentTransaction) -// } -// } -// } -// } -// fn contained_transactions(&self) -> HashSet> { -// match self { -// VDemoBlock::Genesis(_) => HashSet::new(), -// VDemoBlock::Normal(block) => block -// .transactions -// .clone() -// .into_iter() -// .map(|tx| tx.commit()) -// .collect(), -// } -// } -// } -// -// /// Implementation of [`NodeType`] for [`VDemoNode`] -// #[derive( -// Copy, -// Clone, -// Debug, -// Default, -// Hash, -// PartialEq, -// Eq, -// PartialOrd, -// Ord, -// serde::Serialize, -// serde::Deserialize, -// )] -// pub struct VDemoTypes; -// -// impl NodeType for VDemoTypes { -// type ConsensusType = ValidatingConsensus; -// type Time = ViewNumber; -// type BlockType = VDemoBlock; -// type SignatureKey = Ed25519Pub; -// type VoteTokenType = StaticVoteToken; -// type Transaction = VDemoTransaction; -// type ElectionConfigType = StaticElectionConfig; -// type StateType = VDemoState; -// } -// -// /// The node implementation for the validating demo -// #[derive(Derivative)] -// #[derivative(Clone(bound = ""))] -// pub struct VDemoNode(PhantomData) -// where -// MEMBERSHIP: Membership + Debug; -// -// impl VDemoNode -// where -// MEMBERSHIP: Membership + Debug, -// { -// /// Create a new `VDemoNode` -// #[must_use] -// pub fn new() -> Self { -// VDemoNode(PhantomData) -// } -// } -// -// impl Debug for VDemoNode -// where -// MEMBERSHIP: Membership + Debug, -// { -// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { -// f.debug_struct("VDemoNode") -// .field("_phantom", &"phantom") -// .finish() -// } -// } -// -// impl Default for VDemoNode -// where -// MEMBERSHIP: Membership + Debug, -// { -// fn default() -> Self { -// Self::new() -// } -// } -// -// /// Provides a random [`QuorumCertificate`] -// pub fn random_quorum_certificate>( -// rng: &mut dyn rand::RngCore, -// ) -> QuorumCertificate { -// QuorumCertificate { -// // block_commitment: random_commitment(rng), -// leaf_commitment: random_commitment(rng), -// view_number: TYPES::Time::new(rng.gen()), -// signatures: YesNoSignature::Yes(BTreeMap::default()), -// is_genesis: rng.gen(), -// } -// } -// -// /// Provides a random [`ValidatingLeaf`] -// pub fn random_validating_leaf>( -// deltas: TYPES::BlockType, -// rng: &mut dyn rand::RngCore, -// ) -> ValidatingLeaf { -// let justify_qc = random_quorum_certificate(rng); -// let state = TYPES::StateType::default() -// .append(&deltas, &TYPES::Time::new(42)) -// .unwrap_or_default(); -// ValidatingLeaf { -// view_number: justify_qc.view_number, -// height: rng.next_u64(), -// justify_qc, -// parent_commitment: random_commitment(rng), -// deltas, -// state, -// rejected: Vec::new(), -// timestamp: time::OffsetDateTime::now_utc().unix_timestamp_nanos(), -// proposer_id: genesis_proposer_id(), -// } -// } diff --git a/crates/hotshot/src/lib.rs b/crates/hotshot/src/lib.rs index fa435e1f1d..b7872ce59e 100644 --- a/crates/hotshot/src/lib.rs +++ b/crates/hotshot/src/lib.rs @@ -19,12 +19,10 @@ #[cfg(feature = "docs")] pub mod documentation; -/// Data availability support -// pub mod da; /// Contains structures and functions for committee election pub mod certificate; #[cfg(feature = "demo")] -pub mod demos; +pub mod demo; /// Contains traits consumed by [`HotShot`] pub mod traits; /// Contains types used by the crate @@ -36,17 +34,17 @@ use crate::{ certificate::QuorumCertificate, tasks::{ add_consensus_task, add_da_task, add_network_event_task, add_network_message_task, - add_view_sync_task, + add_transaction_task, add_view_sync_task, }, traits::{NodeImplementation, Storage}, types::{Event, SystemContextHandle}, }; use async_compatibility_layer::{ art::{async_spawn, async_spawn_local}, - async_primitives::{broadcast::BroadcastSender, subscribable_rwlock::SubscribableRwLock}, - channel::{unbounded, UnboundedReceiver, UnboundedSender}, + async_primitives::broadcast::BroadcastSender, + channel::UnboundedSender, }; -use async_lock::{Mutex, RwLock, RwLockUpgradableReadGuard, RwLockWriteGuard}; +use async_lock::{RwLock, RwLockUpgradableReadGuard, RwLockWriteGuard}; use async_trait::async_trait; use commit::{Commitment, Committable}; use custom_debug::Debug; @@ -57,9 +55,10 @@ use hotshot_task::{ use hotshot_task_impls::{events::SequencingHotShotEvent, network::NetworkTaskKind}; use hotshot_types::{ + block_impl::{VIDBlockPayload, VIDTransaction}, certificate::{DACertificate, ViewSyncCertificate}, consensus::{BlockStore, Consensus, ConsensusMetrics, View, ViewInner, ViewQueue}, - data::{DAProposal, DeltasType, LeafType, ProposalType, QuorumProposal, SequencingLeaf}, + data::{DAProposal, DeltasType, LeafType, QuorumProposal, SequencingLeaf}, error::StorageSnafu, message::{ ConsensusMessageType, DataMessage, InternalTrigger, Message, MessageKind, @@ -79,12 +78,12 @@ use hotshot_types::{ storage::StoredView, State, }, - vote::{ViewSyncData, VoteType}, + vote::ViewSyncData, HotShotConfig, }; use snafu::ResultExt; use std::{ - collections::{BTreeMap, HashMap, HashSet}, + collections::{BTreeMap, HashMap}, marker::PhantomData, num::NonZeroUsize, sync::Arc, @@ -114,7 +113,6 @@ pub struct SystemContextInner> { /// Configuration items for this hotshot instance config: HotShotConfig< - TYPES::SignatureKey, ::StakeTableEntry, TYPES::ElectionConfigType, >, @@ -134,11 +132,6 @@ pub struct SystemContextInner> { /// a reference to the metrics that the implementor is using. _metrics: Box, - /// Transactions - /// (this is shared btwn hotshot and `Consensus`) - transactions: - Arc, TYPES::Transaction>>>, - /// The hotstuff implementation consensus: Arc>>, @@ -146,9 +139,6 @@ pub struct SystemContextInner> { /// latter of which is only applicable for sequencing consensus. channel_maps: (ChannelMaps, Option>), - /// for receiving messages in the network lookup task - recv_network_lookup: Arc>>>, - // global_registry: GlobalRegistry, /// Access to the output event stream. output_event_stream: ChannelStream>, @@ -178,7 +168,6 @@ impl> SystemContext { private_key: ::PrivateKey, nonce: u64, config: HotShotConfig< - TYPES::SignatureKey, ::StakeTableEntry, TYPES::ElectionConfigType, >, @@ -224,8 +213,6 @@ impl> SystemContext { state_map, cur_view: start_view, last_decided_view: anchored_leaf.get_view_number(), - transactions: Arc::default(), - seen_transactions: HashSet::new(), saved_leaves, saved_blocks, // TODO this is incorrect @@ -236,19 +223,14 @@ impl> SystemContext { invalid_qc: 0, }; let consensus = Arc::new(RwLock::new(consensus)); - let txns = consensus.read().await.get_transactions(); - let (_send_network_lookup, recv_network_lookup) = unbounded(); let inner: Arc> = Arc::new(SystemContextInner { - recv_network_lookup: Arc::new(Mutex::new(recv_network_lookup)), id: nonce, channel_maps: I::new_channel_maps(start_view), consensus, - transactions: txns, public_key, private_key, config, - // networking, storage, exchanges: Arc::new(exchanges), event_sender: RwLock::default(), @@ -405,7 +387,6 @@ impl> SystemContext { private_key: ::PrivateKey, node_id: u64, config: HotShotConfig< - TYPES::SignatureKey, ::StakeTableEntry, TYPES::ElectionConfigType, >, @@ -554,11 +535,6 @@ impl> SystemContext { /// [`HotShot`] implementations that depend on [`TYPES::ConsensusType`]. #[async_trait] pub trait HotShotType> { - /// Get the [`transactions`] field of [`HotShot`]. - fn transactions( - &self, - ) -> &Arc, TYPES::Transaction>>>; - /// Get the [`hotstuff`] field of [`HotShot`]. fn consensus(&self) -> &Arc>>; @@ -658,7 +634,7 @@ pub trait HotShotType> { #[async_trait] impl< - TYPES: NodeType, + TYPES: NodeType, I: NodeImplementation< TYPES, Leaf = SequencingLeaf, @@ -671,8 +647,8 @@ where TYPES, Message, Proposal = QuorumProposal>, - Certificate = QuorumCertificate>, - Commitment = SequencingLeaf, + Certificate = QuorumCertificate>>, + Commitment = Commitment>, Membership = MEMBERSHIP, > + 'static, CommitteeEx: ConsensusExchange< @@ -680,7 +656,7 @@ where Message, Proposal = DAProposal, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, Membership = MEMBERSHIP, > + 'static, ViewSyncEx: ConsensusExchange< @@ -688,16 +664,10 @@ where Message, Proposal = ViewSyncCertificate, Certificate = ViewSyncCertificate, - Commitment = ViewSyncData, + Commitment = Commitment>, Membership = MEMBERSHIP, > + 'static, { - fn transactions( - &self, - ) -> &Arc, TYPES::Transaction>>> { - &self.inner.transactions - } - fn consensus(&self) -> &Arc>> { &self.inner.consensus } @@ -775,6 +745,13 @@ where handle.clone(), ) .await; + let task_runner = add_transaction_task( + task_runner, + internal_event_stream.clone(), + committee_exchange.clone(), + handle.clone(), + ) + .await; let task_runner = add_view_sync_task::( task_runner, internal_event_stream.clone(), @@ -936,10 +913,7 @@ impl< I: NodeImplementation>, > SequencingConsensusApi for HotShotSequencingConsensusApi { - async fn send_direct_message< - PROPOSAL: ProposalType, - VOTE: VoteType, - >( + async fn send_direct_message( &self, recipient: TYPES::SignatureKey, message: SequencingMessage, @@ -964,10 +938,7 @@ impl< Ok(()) } - async fn send_direct_da_message< - PROPOSAL: ProposalType, - VOTE: VoteType, - >( + async fn send_direct_da_message( &self, recipient: TYPES::SignatureKey, message: SequencingMessage, @@ -994,10 +965,7 @@ impl< // TODO (DA) Refactor ConsensusApi and HotShot to use SystemContextInner directly. // - async fn send_broadcast_message< - PROPOSAL: ProposalType, - VOTE: VoteType, - >( + async fn send_broadcast_message( &self, message: SequencingMessage, ) -> std::result::Result<(), NetworkError> { @@ -1091,7 +1059,7 @@ impl> HotShotInitializer::genesis(); + let justify_qc = QuorumCertificate::>::genesis(); Ok(Self { inner: LEAF::new(time, justify_qc, genesis_block, state), diff --git a/crates/hotshot/src/tasks/mod.rs b/crates/hotshot/src/tasks/mod.rs index 1b411c35d2..bc95f8dbb6 100644 --- a/crates/hotshot/src/tasks/mod.rs +++ b/crates/hotshot/src/tasks/mod.rs @@ -2,9 +2,10 @@ use crate::{ async_spawn, types::SystemContextHandle, DACertificate, HotShotSequencingConsensusApi, - QuorumCertificate, SequencingQuorumEx, SystemContext, + QuorumCertificate, SequencingQuorumEx, }; -use async_compatibility_layer::art::{async_sleep, async_spawn_local}; +use async_compatibility_layer::art::async_sleep; +use commit::{Commitment, CommitmentBounds}; use futures::FutureExt; use hotshot_task::{ boxed_sync, @@ -22,11 +23,12 @@ use hotshot_task_impls::{ NetworkEventTaskState, NetworkEventTaskTypes, NetworkMessageTaskState, NetworkMessageTaskTypes, NetworkTaskKind, }, + transactions::{TransactionTaskState, TransactionsTaskTypes}, view_sync::{ViewSyncTaskState, ViewSyncTaskStateTypes}, }; use hotshot_types::{ + block_impl::{VIDBlockPayload, VIDTransaction}, certificate::ViewSyncCertificate, - constants::LOOK_AHEAD, data::{ProposalType, QuorumProposal, SequencingLeaf}, event::Event, message::{Message, Messages, SequencingMessage}, @@ -37,79 +39,15 @@ use hotshot_types::{ CommitteeEx, ExchangesType, NodeImplementation, NodeType, ViewSyncEx, }, state::ConsensusTime, - Block, }, vote::{ViewSyncData, VoteType}, }; use std::{ - collections::HashMap, + collections::{HashMap, HashSet}, marker::PhantomData, - sync::{ - atomic::{AtomicBool, Ordering}, - Arc, - }, + sync::Arc, time::Duration, }; -use tracing::info; - -/// Task to look up a node in the future as needed -pub async fn network_lookup_task>( - hotshot: SystemContext, - shut_down: Arc, -) { - info!("Launching network lookup task"); - let networking = hotshot.inner.exchanges.quorum_exchange().network().clone(); - - let inner = hotshot.inner.clone(); - - let mut completion_map: HashMap> = HashMap::default(); - - while !shut_down.load(Ordering::Relaxed) { - let lock = hotshot.inner.recv_network_lookup.lock().await; - - if let Ok(Some(cur_view)) = lock.recv().await { - let view_to_lookup = cur_view + LOOK_AHEAD; - - // perform pruning - // TODO in the future btreemap would be better - completion_map = completion_map - .drain() - .filter(|(view, is_done)| { - if !is_done.load(Ordering::Relaxed) { - // we are past the view where this is useful - if cur_view >= *view { - is_done.store(true, Ordering::Relaxed); - return true; - } - // we aren't done - return false; - } - true - }) - .collect(); - - // logic to look ahead - if !inner.exchanges.quorum_exchange().is_leader(view_to_lookup) { - let is_done = Arc::new(AtomicBool::new(false)); - completion_map.insert(view_to_lookup, is_done.clone()); - let inner = inner.clone(); - let networking = networking.clone(); - async_spawn_local(async move { - info!("starting lookup for {:?}", view_to_lookup); - let _result = networking - .lookup_node(inner.exchanges.quorum_exchange().get_leader(view_to_lookup)) - .await; - info!("finished lookup for {:?}", view_to_lookup); - }); - } - } - } - - // shut down all child tasks - for (_, is_done) in completion_map { - is_done.store(true, Ordering::Relaxed); - } -} /// event for global event stream #[derive(Clone, Debug)] @@ -130,8 +68,9 @@ pub async fn add_network_message_task< Leaf = SequencingLeaf, ConsensusMessage = SequencingMessage, >, + COMMITMENT: CommitmentBounds, PROPOSAL: ProposalType, - VOTE: VoteType, + VOTE: VoteType, MEMBERSHIP: Membership, EXCHANGE: ConsensusExchange< TYPES, @@ -147,8 +86,7 @@ pub async fn add_network_message_task< ) -> TaskRunner // This bound is required so that we can call the `recv_msgs` function of `CommunicationChannel`. where - EXCHANGE::Networking: - CommunicationChannel, PROPOSAL, VOTE, MEMBERSHIP>, + EXCHANGE::Networking: CommunicationChannel, MEMBERSHIP>, { let channel = exchange.network().clone(); let broadcast_stream = GeneratedStream::>::new(Arc::new(move || { @@ -240,8 +178,9 @@ pub async fn add_network_event_task< Leaf = SequencingLeaf, ConsensusMessage = SequencingMessage, >, + COMMITMENT: CommitmentBounds, PROPOSAL: ProposalType, - VOTE: VoteType, + VOTE: VoteType, MEMBERSHIP: Membership, EXCHANGE: ConsensusExchange< TYPES, @@ -258,19 +197,16 @@ pub async fn add_network_event_task< ) -> TaskRunner // This bound is required so that we can call the `recv_msgs` function of `CommunicationChannel`. where - EXCHANGE::Networking: - CommunicationChannel, PROPOSAL, VOTE, MEMBERSHIP>, + EXCHANGE::Networking: CommunicationChannel, MEMBERSHIP>, { let filter = NetworkEventTaskState::< TYPES, I, - PROPOSAL, - VOTE, MEMBERSHIP, >::Networking, >::filter(task_kind); let channel = exchange.network().clone(); - let network_state: NetworkEventTaskState<_, _, _, _, _, _> = NetworkEventTaskState { + let network_state: NetworkEventTaskState<_, _, _, _> = NetworkEventTaskState { channel, event_stream: event_stream.clone(), view: TYPES::Time::genesis(), @@ -278,7 +214,7 @@ where }; let registry = task_runner.registry.clone(); let network_event_handler = HandleEvent(Arc::new( - move |event, mut state: NetworkEventTaskState<_, _, _, _, MEMBERSHIP, _>| { + move |event, mut state: NetworkEventTaskState<_, _, MEMBERSHIP, _>| { let membership = exchange.membership().clone(); async move { let completion_status = state.handle_event(event, &membership).await; @@ -290,7 +226,7 @@ where let networking_name = "Networking Task"; let networking_task_builder = - TaskBuilder::>::new(networking_name.to_string()) + TaskBuilder::>::new(networking_name.to_string()) .register_event_stream(event_stream.clone(), filter) .await .register_registry(&mut registry.clone()) @@ -314,7 +250,7 @@ where /// # Panics /// Is unable to panic. This section here is just to satisfy clippy pub async fn add_consensus_task< - TYPES: NodeType, + TYPES: NodeType, I: NodeImplementation< TYPES, Leaf = SequencingLeaf, @@ -331,14 +267,14 @@ where TYPES, Message, Proposal = QuorumProposal>, - Certificate = QuorumCertificate>, - Commitment = SequencingLeaf, + Certificate = QuorumCertificate>>, + Commitment = Commitment>, >, CommitteeEx: ConsensusExchange< TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { let consensus = handle.hotshot.get_consensus(); @@ -352,7 +288,7 @@ where consensus, timeout: handle.hotshot.inner.config.next_view_timeout, cur_view: TYPES::Time::new(0), - block: Some(TYPES::BlockType::new()), + block: Some(VIDBlockPayload::genesis()), quorum_exchange: c_api.inner.exchanges.quorum_exchange().clone().into(), api: c_api.clone(), committee_exchange: c_api.inner.exchanges.committee_exchange().clone().into(), @@ -428,7 +364,7 @@ where TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { // build the da task @@ -476,6 +412,80 @@ where task_runner.add_task(da_task_id, da_name.to_string(), da_task) } +/// add the Transaction Handling task +/// # Panics +/// Is unable to panic. This section here is just to satisfy clippy +pub async fn add_transaction_task< + TYPES: NodeType, + I: NodeImplementation< + TYPES, + Leaf = SequencingLeaf, + ConsensusMessage = SequencingMessage, + >, +>( + task_runner: TaskRunner, + event_stream: ChannelStream>, + committee_exchange: CommitteeEx, + handle: SystemContextHandle, +) -> TaskRunner +where + CommitteeEx: ConsensusExchange< + TYPES, + Message, + Certificate = DACertificate, + Commitment = Commitment, + >, +{ + // build the transactions task + let c_api: HotShotSequencingConsensusApi = HotShotSequencingConsensusApi { + inner: handle.hotshot.inner.clone(), + }; + let registry = task_runner.registry.clone(); + let transactions_state = TransactionTaskState { + registry: registry.clone(), + api: c_api.clone(), + consensus: handle.hotshot.get_consensus(), + transactions: Arc::default(), + seen_transactions: HashSet::new(), + cur_view: TYPES::Time::new(0), + committee_exchange: committee_exchange.into(), + event_stream: event_stream.clone(), + id: handle.hotshot.inner.id, + }; + let transactions_event_handler = HandleEvent(Arc::new( + move |event, + mut state: TransactionTaskState< + TYPES, + I, + HotShotSequencingConsensusApi, + >| { + async move { + let completion_status = state.handle_event(event).await; + (completion_status, state) + } + .boxed() + }, + )); + let transactions_name = "Transactions Task"; + let transactions_event_filter = FilterEvent(Arc::new( + TransactionTaskState::>::filter, + )); + + let transactions_task_builder = TaskBuilder::< + TransactionsTaskTypes>, + >::new(transactions_name.to_string()) + .register_event_stream(event_stream.clone(), transactions_event_filter) + .await + .register_registry(&mut registry.clone()) + .await + .register_state(transactions_state) + .register_event_handler(transactions_event_handler); + // impossible for unwrap to fail + // we *just* registered + let da_task_id = transactions_task_builder.get_task_id().unwrap(); + let da_task = TransactionsTaskTypes::build(transactions_task_builder).launch(); + task_runner.add_task(da_task_id, transactions_name.to_string(), da_task) +} /// add the view sync task /// # Panics /// Is unable to panic. This section here is just to satisfy clippy @@ -497,7 +507,7 @@ where Message, Proposal = ViewSyncCertificate, Certificate = ViewSyncCertificate, - Commitment = ViewSyncData, + Commitment = Commitment>, >, { let api = HotShotSequencingConsensusApi { diff --git a/crates/hotshot/src/traits.rs b/crates/hotshot/src/traits.rs index 0f751912c5..370dc47839 100644 --- a/crates/hotshot/src/traits.rs +++ b/crates/hotshot/src/traits.rs @@ -4,7 +4,7 @@ mod networking; mod node_implementation; mod storage; -pub use hotshot_types::traits::{Block, State}; +pub use hotshot_types::traits::{BlockPayload, State}; pub use networking::{NetworkError, NetworkReliability}; pub use node_implementation::{NodeImplementation, TestableNodeImplementation}; pub use storage::{Result as StorageResult, Storage}; @@ -14,7 +14,7 @@ pub mod implementations { pub use super::{ networking::{ libp2p_network::{Libp2pCommChannel, Libp2pNetwork, PeerInfoVec}, - memory_network::{DummyReliability, MasterMap, MemoryCommChannel, MemoryNetwork}, + memory_network::{MasterMap, MemoryCommChannel, MemoryNetwork}, web_server_libp2p_fallback::{CombinedNetworks, WebServerWithFallbackCommChannel}, web_server_network::{WebCommChannel, WebServerNetwork}, }, diff --git a/crates/hotshot/src/traits/election/static_committee.rs b/crates/hotshot/src/traits/election/static_committee.rs index 2c95746d4b..ccdcfb722f 100644 --- a/crates/hotshot/src/traits/election/static_committee.rs +++ b/crates/hotshot/src/traits/election/static_committee.rs @@ -1,7 +1,7 @@ // use ark_bls12_381::Parameters as Param381; use commit::{Commitment, Committable, RawCommitmentBuilder}; use espresso_systems_common::hotshot::tag; -use hotshot_signature_key::bn254::BN254Pub; +use hotshot_signature_key::bn254::BLSPubKey; use hotshot_types::{ data::LeafType, traits::{ @@ -19,12 +19,8 @@ use tracing::debug; #[derive(Clone, Debug, Eq, PartialEq)] pub struct GeneralStaticCommittee, PUBKEY: SignatureKey> { - /// All the nodes participating - nodes: Vec, /// All the nodes participating and their stake nodes_with_stake: Vec, - /// The nodes on the static committee - committee_nodes: Vec, /// The nodes on the static committee and their stake committee_nodes_with_stake: Vec, /// Node type phantom @@ -34,18 +30,16 @@ pub struct GeneralStaticCommittee, PUBKEY: Signa } /// static committee using a vrf kp -pub type StaticCommittee = GeneralStaticCommittee; +pub type StaticCommittee = GeneralStaticCommittee; impl, PUBKEY: SignatureKey> GeneralStaticCommittee { /// Creates a new dummy elector #[must_use] - pub fn new(nodes: Vec, nodes_with_stake: Vec) -> Self { + pub fn new(_nodes: &[PUBKEY], nodes_with_stake: Vec) -> Self { Self { - nodes: nodes.clone(), nodes_with_stake: nodes_with_stake.clone(), - committee_nodes: nodes, committee_nodes_with_stake: nodes_with_stake, _type_phantom: PhantomData, _leaf_phantom: PhantomData, @@ -107,8 +101,9 @@ where /// Index the vector of public keys with the current view number fn get_leader(&self, view_number: TYPES::Time) -> PUBKEY { - let index = (*view_number % self.nodes.len() as u64) as usize; - self.nodes[index].clone() + let index = (*view_number % self.nodes_with_stake.len() as u64) as usize; + let res = self.nodes_with_stake[index].clone(); + TYPES::SignatureKey::get_public_key(&res) } /// Simply make the partial signature @@ -117,9 +112,9 @@ where view_number: TYPES::Time, private_key: &::PrivateKey, ) -> std::result::Result>, ElectionError> { - // TODO ED Below let pub_key = PUBKEY::from_private(private_key); - if !self.committee_nodes.contains(&pub_key) { + let entry = pub_key.get_stake_table_entry(1u64); + if !self.committee_nodes_with_stake.contains(&entry) { return Ok(None); } let mut message: Vec = vec![]; @@ -137,7 +132,8 @@ where ) -> Result, ElectionError> { match token { Checked::Valid(t) | Checked::Unchecked(t) => { - if self.committee_nodes.contains(&pub_key) { + let entry = pub_key.get_stake_table_entry(1u64); + if self.committee_nodes_with_stake.contains(&entry) { Ok(Checked::Valid(t)) } else { Ok(Checked::Inval(t)) @@ -153,18 +149,13 @@ where fn create_election( keys_qc: Vec, - keys: Vec, config: TYPES::ElectionConfigType, ) -> Self { - let mut committee_nodes = keys.clone(); let mut committee_nodes_with_stake = keys_qc.clone(); - committee_nodes.truncate(config.num_nodes.try_into().unwrap()); debug!("Election Membership Size: {}", config.num_nodes); committee_nodes_with_stake.truncate(config.num_nodes.try_into().unwrap()); Self { nodes_with_stake: keys_qc, - nodes: keys, - committee_nodes, committee_nodes_with_stake, _type_phantom: PhantomData, _leaf_phantom: PhantomData, @@ -172,21 +163,28 @@ where } fn total_nodes(&self) -> usize { - self.committee_nodes.len() + self.committee_nodes_with_stake.len() } fn success_threshold(&self) -> NonZeroU64 { - NonZeroU64::new(((self.committee_nodes.len() as u64 * 2) / 3) + 1).unwrap() + NonZeroU64::new(((self.committee_nodes_with_stake.len() as u64 * 2) / 3) + 1).unwrap() } fn failure_threshold(&self) -> NonZeroU64 { - NonZeroU64::new(((self.committee_nodes.len() as u64) / 3) + 1).unwrap() + NonZeroU64::new(((self.committee_nodes_with_stake.len() as u64) / 3) + 1).unwrap() } fn get_committee( &self, _view_number: ::Time, ) -> std::collections::BTreeSet<::SignatureKey> { - self.committee_nodes.clone().into_iter().collect() + // Transfer from committee_nodes_with_stake to pure committee_nodes + (0..self.committee_nodes_with_stake.len()) + .map(|node_id| { + ::SignatureKey::get_public_key( + &self.committee_nodes_with_stake[node_id], + ) + }) + .collect() } } diff --git a/crates/hotshot/src/traits/networking/libp2p_network.rs b/crates/hotshot/src/traits/networking/libp2p_network.rs index c01bf53982..52ed2b73bc 100644 --- a/crates/hotshot/src/traits/networking/libp2p_network.rs +++ b/crates/hotshot/src/traits/networking/libp2p_network.rs @@ -6,15 +6,16 @@ use super::NetworkingMetrics; use crate::NodeImplementation; use async_compatibility_layer::{ art::{async_block_on, async_sleep, async_spawn}, - channel::{unbounded, UnboundedReceiver, UnboundedSender}, + channel::{unbounded, UnboundedReceiver, UnboundedSendError, UnboundedSender}, }; use async_lock::RwLock; use async_trait::async_trait; use bimap::BiHashMap; use bincode::Options; +use hotshot_constants::LOOK_AHEAD; use hotshot_task::{boxed_sync, BoxSyncFuture}; use hotshot_types::{ - data::ProposalType, + data::ViewNumber, message::{Message, MessageKind}, traits::{ election::Membership, @@ -26,8 +27,8 @@ use hotshot_types::{ }, node_implementation::NodeType, signature_key::SignatureKey, + state::ConsensusTime, }, - vote::VoteType, }; use hotshot_utils::bincode::bincode_opts; use libp2p_identity::PeerId; @@ -49,10 +50,13 @@ use std::{ marker::PhantomData, num::NonZeroUsize, str::FromStr, - sync::{atomic::AtomicBool, Arc}, + sync::{ + atomic::{AtomicBool, AtomicU64, Ordering}, + Arc, + }, time::Duration, }; -use tracing::{error, info, instrument}; +use tracing::{error, info, instrument, warn}; /// hardcoded topic of QC used pub const QC_TOPIC: &str = "global"; @@ -79,9 +83,6 @@ struct Libp2pNetworkInner { pk: K, /// handle to control the network handle: Arc>, - /// Bidirectional map from public key provided by espresso - /// to public key provided by libp2p - pubkey_pid_map: RwLock>, /// map of known replica peer ids to public keys broadcast_recv: UnboundedReceiver, /// Sender for broadcast messages @@ -90,6 +91,8 @@ struct Libp2pNetworkInner { direct_send: UnboundedSender, /// Receiver for direct messages direct_recv: UnboundedReceiver, + /// Sender for node lookup (relevant view number, key of node) (None for shutdown) + node_lookup_send: UnboundedSender>, /// this is really cheating to enable local tests /// hashset of (bootstrap_addr, peer_id) bootstrap_addrs: PeerInfoVec, @@ -107,6 +110,10 @@ struct Libp2pNetworkInner { /// hash(hashset) -> topic /// btreemap ordered so is hashable topic_map: RwLock, String>>, + /// the latest view number (for node lookup purposes) + /// NOTE: supposed to represent a ViewNumber but we + /// haven't made that atomic yet and we prefer lock-free + latest_seen_view: Arc, } /// Networking implementation that uses libp2p @@ -244,11 +251,7 @@ impl Libp2pNetwork { /// Returns when network is ready pub async fn wait_for_ready(&self) { loop { - if self - .inner - .is_ready - .load(std::sync::atomic::Ordering::Relaxed) - { + if self.inner.is_ready.load(Ordering::Relaxed) { break; } async_sleep(Duration::from_secs(1)).await; @@ -282,7 +285,7 @@ impl Libp2pNetwork { ) -> Result, NetworkError> { assert!(bootstrap_addrs_len > 4, "Need at least 5 bootstrap nodes"); let network_handle = Arc::new( - NetworkNodeHandle::<()>::new(config, id) + Box::pin(NetworkNodeHandle::<()>::new(config, id)) .await .map_err(Into::::into)?, ); @@ -300,7 +303,6 @@ impl Libp2pNetwork { } let mut pubkey_pid_map = BiHashMap::new(); - pubkey_pid_map.insert(pk.clone(), network_handle.peer_id()); let mut topic_map = BiHashMap::new(); @@ -313,11 +315,11 @@ impl Libp2pNetwork { // if bounded figure out a way to log dropped msgs let (direct_send, direct_recv) = unbounded(); let (broadcast_send, broadcast_recv) = unbounded(); + let (node_lookup_send, node_lookup_recv) = unbounded(); let result = Libp2pNetwork { inner: Arc::new(Libp2pNetworkInner { handle: network_handle, - pubkey_pid_map: RwLock::new(pubkey_pid_map), broadcast_recv, direct_send: direct_send.clone(), direct_recv, @@ -330,16 +332,49 @@ impl Libp2pNetwork { is_bootstrapped: Arc::new(AtomicBool::new(false)), metrics: NetworkingMetrics::new(&*metrics), topic_map, + node_lookup_send, + // Start the latest view from 0. "Latest" refers to "most recent view we are polling for + // proposals on". We need this because to have consensus info injected we need a working + // network already. In the worst case, we send a few lookups we don't need. + latest_seen_view: Arc::new(AtomicU64::new(0)), }), }; result.spawn_event_generator(direct_send, broadcast_send); - + result.spawn_node_lookup(node_lookup_recv); result.spawn_connect(id); Ok(result) } + /// Spawns task for looking up nodes pre-emptively + #[allow(clippy::cast_sign_loss, clippy::cast_precision_loss)] + fn spawn_node_lookup(&self, node_lookup_recv: UnboundedReceiver>) { + let handle = self.inner.handle.clone(); + let dht_timeout = self.inner.dht_timeout; + let latest_seen_view = self.inner.latest_seen_view.clone(); + + // deals with handling lookup queue. should be infallible + let handle_ = handle.clone(); + async_spawn(async move { + // cancels on shutdown + while let Ok(Some((view_number, pk))) = node_lookup_recv.recv().await { + /// defines lookahead threshold based on the constant + const THRESHOLD: u64 = (LOOK_AHEAD as f64 * 0.8) as u64; + + info!("Performing lookup for peer {:?}", pk); + + // only run if we are not too close to the next view number + if latest_seen_view.load(Ordering::Relaxed) + THRESHOLD <= *view_number { + // look up + if let Err(err) = handle_.lookup_node::(pk.clone(), dht_timeout).await { + error!("Failed to perform lookup for key {:?}: {}", pk, err); + }; + } + } + }); + } + /// Initiates connection to the outside world fn spawn_connect(&self, id: usize) { let pk = self.inner.pk.clone(); @@ -376,7 +411,7 @@ impl Libp2pNetwork { .await .unwrap(); - while !is_bootstrapped.load(std::sync::atomic::Ordering::Relaxed) { + while !is_bootstrapped.load(Ordering::Relaxed) { async_sleep(Duration::from_secs(1)).await; } @@ -414,7 +449,7 @@ impl Libp2pNetwork { node_type ); - is_ready.store(true, std::sync::atomic::Ordering::Relaxed); + is_ready.store(true, Ordering::Relaxed); info!("STARTING CONSENSUS ON {:?}", handle.peer_id()); Ok::<(), NetworkError>(()) } @@ -480,7 +515,7 @@ impl Libp2pNetwork { .context(FailedToSerializeSnafu); } NetworkEvent::IsBootstrapped => { - is_bootstrapped.store(true, std::sync::atomic::Ordering::Relaxed); + is_bootstrapped.store(true, Ordering::Relaxed); } } } @@ -499,9 +534,7 @@ impl ConnectedNetwork for Libp2p #[instrument(name = "Libp2pNetwork::ready_nonblocking", skip_all)] async fn is_ready(&self) -> bool { - self.inner - .is_ready - .load(std::sync::atomic::Ordering::Relaxed) + self.inner.is_ready.load(Ordering::Relaxed) } #[instrument(name = "Libp2pNetwork::shut_down", skip_all)] @@ -511,6 +544,7 @@ impl ConnectedNetwork for Libp2p Self: 'b, { let closure = async move { + self.inner.node_lookup_send.send(None).await.unwrap(); if self.inner.handle.is_killed() { error!("Called shut down when already shut down! Noop."); } else { @@ -544,7 +578,7 @@ impl ConnectedNetwork for Libp2p source: NetworkNodeHandleError::NoSuchTopic, })? .clone(); - error!("Broadcasting to topic {}", topic); + info!("broadcasting to topic: {}", topic); // gossip doesn't broadcast from itself, so special case if recipients.contains(&self.inner.pk) { @@ -586,37 +620,24 @@ impl ConnectedNetwork for Libp2p } self.wait_for_ready().await; - // check local cache. if that fails, initiate search - // if search fails, just error out - // NOTE: relay may be a good way to fix this in the future . - let pid: PeerId = if let Some(pid) = self + + let pid = match self .inner - .pubkey_pid_map - .read() + .handle + .lookup_node::(recipient.clone(), self.inner.dht_timeout) .await - .get_by_left(&recipient) { - *pid - } else { - match self - .inner - .handle - .get_record_timeout(&recipient, self.inner.dht_timeout) - .await - { - Ok(r) => r, - Err(e) => { - self.inner.metrics.message_failed_to_send.add(1); - error!("Failed to message {:?} because could not find recipient peer id for pk {:?}", message, recipient); - return Err(NetworkError::Libp2p { source: e }); - } + Ok(pid) => pid, + Err(err) => { + self.inner.metrics.message_failed_to_send.add(1); + error!( + "Failed to message {:?} because could not find recipient peer id for pk {:?}", + message, recipient + ); + return Err(NetworkError::Libp2p { source: err }); } }; - if let Err(e) = self.inner.handle.lookup_pid(pid).await { - self.inner.metrics.message_failed_to_send.add(1); - return Err(e.into()); - } match self.inner.handle.direct_request(pid, &message).await { Ok(()) => { self.inner.metrics.outgoing_message_count.add(1); @@ -669,44 +690,37 @@ impl ConnectedNetwork for Libp2p boxed_sync(closure) } - #[instrument(name = "Libp2pNetwork::lookup_node", skip_all)] - async fn lookup_node(&self, pk: K) -> Result<(), NetworkError> { - self.wait_for_ready().await; - - if self.inner.handle.is_killed() { - return Err(NetworkError::ShutDown); - } - - let maybe_pid = self - .inner - .handle - .get_record_timeout(&pk, self.inner.dht_timeout) + #[instrument(name = "Libp2pNetwork::queue_node_lookup", skip_all)] + async fn queue_node_lookup( + &self, + view_number: ViewNumber, + pk: K, + ) -> Result<(), UnboundedSendError>> { + self.inner + .node_lookup_send + .send(Some((view_number, pk))) .await - .map_err(Into::::into); - - if let Ok(pid) = maybe_pid { - if self.inner.handle.lookup_pid(pid).await.is_err() { - error!("Failed to look up pid"); - return Err(NetworkError::Libp2p { - source: NetworkNodeHandleError::DHTError { - source: libp2p_networking::network::error::DHTError::NotFound, - }, - }); - }; - } else { - error!("Unable to look up pubkey {:?}", pk); - return Err(NetworkError::Libp2p { - source: NetworkNodeHandleError::DHTError { - source: libp2p_networking::network::error::DHTError::NotFound, - }, - }); - } - - Ok(()) } - async fn inject_consensus_info(&self, _event: ConsensusIntentEvent) { - // Not required + async fn inject_consensus_info(&self, event: ConsensusIntentEvent) { + match event { + ConsensusIntentEvent::PollFutureLeader(future_view, future_leader) => { + let _ = self + .queue_node_lookup(ViewNumber::new(future_view), future_leader) + .await + .map_err(|err| warn!("failed to process node lookup request: {}", err)); + } + + ConsensusIntentEvent::PollForProposal(new_view) => { + if new_view > self.inner.latest_seen_view.load(Ordering::Relaxed) { + self.inner + .latest_seen_view + .store(new_view, Ordering::Relaxed); + } + } + + _ => {} + } } } @@ -715,21 +729,14 @@ impl ConnectedNetwork for Libp2p pub struct Libp2pCommChannel< TYPES: NodeType, I: NodeImplementation, - PROPOSAL: ProposalType, - VOTE: VoteType, MEMBERSHIP: Membership, >( Arc, TYPES::SignatureKey>>, - PhantomData<(TYPES, I, PROPOSAL, VOTE, MEMBERSHIP)>, + PhantomData<(TYPES, I, MEMBERSHIP)>, ); -impl< - TYPES: NodeType, - I: NodeImplementation, - PROPOSAL: ProposalType, - VOTE: VoteType, - MEMBERSHIP: Membership, - > Libp2pCommChannel +impl, MEMBERSHIP: Membership> + Libp2pCommChannel { /// create a new libp2p communication channel #[must_use] @@ -738,14 +745,9 @@ impl< } } -impl< - TYPES: NodeType, - I: NodeImplementation, - PROPOSAL: ProposalType, - VOTE: VoteType, - MEMBERSHIP: Membership, - > TestableNetworkingImplementation> - for Libp2pCommChannel +impl, MEMBERSHIP: Membership> + TestableNetworkingImplementation> + for Libp2pCommChannel where MessageKind: ViewMessage, { @@ -787,14 +789,9 @@ where // top // we don't really want to make this the default implementation because that forces it to require ConnectedNetwork to be implemented. The struct we implement over might use multiple ConnectedNetworks #[async_trait] -impl< - TYPES: NodeType, - I: NodeImplementation, - PROPOSAL: ProposalType, - VOTE: VoteType, - MEMBERSHIP: Membership, - > CommunicationChannel, PROPOSAL, VOTE, MEMBERSHIP> - for Libp2pCommChannel +impl, MEMBERSHIP: Membership> + CommunicationChannel, MEMBERSHIP> + for Libp2pCommChannel where MessageKind: ViewMessage, { @@ -851,30 +848,30 @@ where boxed_sync(closure) } - async fn lookup_node(&self, pk: TYPES::SignatureKey) -> Result<(), NetworkError> { - self.0.lookup_node(pk).await + async fn queue_node_lookup( + &self, + view_number: ViewNumber, + pk: TYPES::SignatureKey, + ) -> Result<(), UnboundedSendError>> { + self.0.queue_node_lookup(view_number, pk).await } - async fn inject_consensus_info(&self, _event: ConsensusIntentEvent) { - // Not required + async fn inject_consensus_info(&self, event: ConsensusIntentEvent) { + as ConnectedNetwork< + Message, + TYPES::SignatureKey, + >>::inject_consensus_info(&self.0, event) + .await; } } -impl< - TYPES: NodeType, - I: NodeImplementation, - PROPOSAL: ProposalType, - VOTE: VoteType, - MEMBERSHIP: Membership, - > +impl, MEMBERSHIP: Membership> TestableChannelImplementation< TYPES, Message, - PROPOSAL, - VOTE, MEMBERSHIP, Libp2pNetwork, TYPES::SignatureKey>, - > for Libp2pCommChannel + > for Libp2pCommChannel { fn generate_network( ) -> Box, TYPES::SignatureKey>>) -> Self + 'static> diff --git a/crates/hotshot/src/traits/networking/memory_network.rs b/crates/hotshot/src/traits/networking/memory_network.rs index d6269e2c38..9d9e751ee5 100644 --- a/crates/hotshot/src/traits/networking/memory_network.rs +++ b/crates/hotshot/src/traits/networking/memory_network.rs @@ -6,7 +6,7 @@ use super::{FailedToSerializeSnafu, NetworkError, NetworkReliability, NetworkingMetrics}; use crate::NodeImplementation; use async_compatibility_layer::{ - art::{async_sleep, async_spawn}, + art::async_spawn, channel::{bounded, Receiver, SendError, Sender}, }; use async_lock::{Mutex, RwLock}; @@ -16,20 +16,17 @@ use dashmap::DashMap; use futures::StreamExt; use hotshot_task::{boxed_sync, BoxSyncFuture}; use hotshot_types::{ - data::ProposalType, message::{Message, MessageKind}, traits::{ election::Membership, metrics::{Metrics, NoMetrics}, network::{ - CommunicationChannel, ConnectedNetwork, ConsensusIntentEvent, NetworkMsg, - TestableChannelImplementation, TestableNetworkingImplementation, TransmitType, - ViewMessage, + CommunicationChannel, ConnectedNetwork, NetworkMsg, TestableChannelImplementation, + TestableNetworkingImplementation, TransmitType, ViewMessage, }, node_implementation::NodeType, signature_key::SignatureKey, }, - vote::VoteType, }; use hotshot_utils::bincode::bincode_opts; use rand::Rng; @@ -45,18 +42,6 @@ use std::{ }; use tracing::{debug, error, info, info_span, instrument, trace, warn, Instrument}; -#[derive(Debug, Clone, Copy)] -/// dummy implementation of network reliability -pub struct DummyReliability {} -impl NetworkReliability for DummyReliability { - fn sample_keep(&self) -> bool { - true - } - fn sample_delay(&self) -> std::time::Duration { - std::time::Duration::ZERO - } -} - /// Shared state for in-memory mock networking. /// /// This type is responsible for keeping track of the channels to each [`MemoryNetwork`], and is @@ -107,6 +92,9 @@ struct MemoryNetworkInner { /// The networking metrics we're keeping track of metrics: NetworkingMetrics, + + /// config to introduce unreliability to the network + reliability_config: Option>>, } /// In memory only network simulator. @@ -137,7 +125,7 @@ impl MemoryNetwork { pub_key: K, metrics: Box, master_map: Arc>, - reliability_config: Option>, + reliability_config: Option>>, ) -> MemoryNetwork { info!("Attaching new MemoryNetwork"); let (broadcast_input, broadcast_task_recv) = bounded(128); @@ -168,30 +156,11 @@ impl MemoryNetwork { match x { Ok(x) => { let dts = direct_task_send.clone(); - if let Some(r) = reliability_config.clone() { - async_spawn(async move { - if r.sample_keep() { - let delay = r.sample_delay(); - if delay > std::time::Duration::ZERO { - async_sleep(delay).await; - } - let res = dts.send(x).await; - if res.is_ok() { - trace!("Passed message to output queue"); - } else { - error!("Output queue receivers are shutdown"); - } - } else { - warn!("dropping packet!"); - } - }); + let res = dts.send(x).await; + if res.is_ok() { + trace!("Passed message to output queue"); } else { - let res = dts.send(x).await; - if res.is_ok() { - trace!("Passed message to output queue"); - } else { - error!("Output queue receivers are shutdown"); - } + error!("Output queue receivers are shutdown"); } } Err(e) => { @@ -206,28 +175,11 @@ impl MemoryNetwork { match x { Ok(x) => { let bts = broadcast_task_send.clone(); - if let Some(r) = reliability_config.clone() { - async_spawn(async move { - if r.sample_keep() { - let delay = r.sample_delay(); - if delay > std::time::Duration::ZERO { - async_sleep(delay).await; - } - let res = bts.send(x).await; - if res.is_ok() { - trace!("Passed message to output queue"); - } else { - warn!("dropping packet!"); - } - } - }); + let res = bts.send(x).await; + if res.is_ok() { + trace!("Passed message to output queue"); } else { - let res = bts.send(x).await; - if res.is_ok() { - trace!("Passed message to output queue"); - } else { - warn!("dropping packet!"); - } + warn!("dropping packet!"); } } Err(e) => { @@ -252,6 +204,7 @@ impl MemoryNetwork { master_map: master_map.clone(), in_flight_message_count, metrics: NetworkingMetrics::new(&*metrics), + reliability_config, }), }; master_map.map.insert(pub_key, mn.clone()); @@ -350,20 +303,40 @@ impl ConnectedNetwork for Memory .context(FailedToSerializeSnafu)?; trace!("Message bincoded, sending"); for node in &self.inner.master_map.map { + // TODO delay/drop etc here let (key, node) = node.pair(); if !recipients.contains(key) { continue; } trace!(?key, "Sending message to node"); - let res = node.broadcast_input(vec.clone()).await; - match res { - Ok(_) => { - self.inner.metrics.outgoing_message_count.add(1); - trace!(?key, "Delivered message to remote"); + if let Some(r) = &self.inner.reliability_config { + let config = r.read().await; + { + let node2 = node.clone(); + let fut = config.chaos_send_msg( + vec.clone(), + Arc::new(move |msg: Vec| { + let node3 = (node2).clone(); + boxed_sync(async move { + let _res = node3.broadcast_input(msg).await; + // NOTE we're dropping metrics here but this is only for testing + // purposes. I think that should be okay + }) + }), + ); + async_spawn(fut); } - Err(e) => { - self.inner.metrics.message_failed_to_send.add(1); - warn!(?e, ?key, "Error sending broadcast message to node"); + } else { + let res = node.broadcast_input(vec.clone()).await; + match res { + Ok(_) => { + self.inner.metrics.outgoing_message_count.add(1); + trace!(?key, "Delivered message to remote"); + } + Err(e) => { + self.inner.metrics.message_failed_to_send.add(1); + warn!(?e, ?key, "Error sending broadcast message to node"); + } } } } @@ -379,18 +352,37 @@ impl ConnectedNetwork for Memory .context(FailedToSerializeSnafu)?; trace!("Message bincoded, finding recipient"); if let Some(node) = self.inner.master_map.map.get(&recipient) { - let node = node.value(); - let res = node.direct_input(vec).await; - match res { - Ok(_) => { - self.inner.metrics.outgoing_message_count.add(1); - trace!(?recipient, "Delivered message to remote"); - Ok(()) + let node = node.value().clone(); + if let Some(r) = &self.inner.reliability_config { + let config = r.read().await; + { + let fut = config.chaos_send_msg( + vec.clone(), + Arc::new(move |msg: Vec| { + let node2 = node.clone(); + boxed_sync(async move { + let _res = node2.broadcast_input(msg).await; + // NOTE we're dropping metrics here but this is only for testing + // purposes. I think that should be okay + }) + }), + ); + async_spawn(fut); } - Err(e) => { - self.inner.metrics.message_failed_to_send.add(1); - warn!(?e, ?recipient, "Error delivering direct message"); - Err(NetworkError::CouldNotDeliver) + Ok(()) + } else { + let res = node.direct_input(vec).await; + match res { + Ok(_) => { + self.inner.metrics.outgoing_message_count.add(1); + trace!(?recipient, "Delivered message to remote"); + Ok(()) + } + Err(e) => { + self.inner.metrics.message_failed_to_send.add(1); + warn!(?e, ?recipient, "Error delivering direct message"); + Err(NetworkError::CouldNotDeliver) + } } } } else { @@ -448,16 +440,6 @@ impl ConnectedNetwork for Memory }; boxed_sync(closure) } - - #[instrument(name = "MemoryNetwork::lookup_node", skip_all)] - async fn lookup_node(&self, _pk: K) -> Result<(), NetworkError> { - // no lookup required - Ok(()) - } - - async fn inject_consensus_info(&self, _event: ConsensusIntentEvent) { - // Not required - } } /// memory identity communication channel @@ -465,21 +447,14 @@ impl ConnectedNetwork for Memory pub struct MemoryCommChannel< TYPES: NodeType, I: NodeImplementation, - PROPOSAL: ProposalType, - VOTE: VoteType, MEMBERSHIP: Membership, >( Arc, TYPES::SignatureKey>>, - PhantomData<(I, PROPOSAL, VOTE, MEMBERSHIP)>, + PhantomData<(I, MEMBERSHIP)>, ); -impl< - TYPES: NodeType, - I: NodeImplementation, - PROPOSAL: ProposalType, - VOTE: VoteType, - MEMBERSHIP: Membership, - > MemoryCommChannel +impl, MEMBERSHIP: Membership> + MemoryCommChannel { /// create new communication channel #[must_use] @@ -488,14 +463,9 @@ impl< } } -impl< - TYPES: NodeType, - I: NodeImplementation, - PROPOSAL: ProposalType, - VOTE: VoteType, - MEMBERSHIP: Membership, - > TestableNetworkingImplementation> - for MemoryCommChannel +impl, MEMBERSHIP: Membership> + TestableNetworkingImplementation> + for MemoryCommChannel where MessageKind: ViewMessage, { @@ -525,14 +495,9 @@ where } #[async_trait] -impl< - TYPES: NodeType, - I: NodeImplementation, - PROPOSAL: ProposalType, - VOTE: VoteType, - MEMBERSHIP: Membership, - > CommunicationChannel, PROPOSAL, VOTE, MEMBERSHIP> - for MemoryCommChannel +impl, MEMBERSHIP: Membership> + CommunicationChannel, MEMBERSHIP> + for MemoryCommChannel where MessageKind: ViewMessage, { @@ -588,31 +553,15 @@ where let closure = async move { self.0.recv_msgs(transmit_type).await }; boxed_sync(closure) } - - async fn lookup_node(&self, pk: TYPES::SignatureKey) -> Result<(), NetworkError> { - self.0.lookup_node(pk).await - } - - async fn inject_consensus_info(&self, _event: ConsensusIntentEvent) { - // Not required - } } -impl< - TYPES: NodeType, - I: NodeImplementation, - PROPOSAL: ProposalType, - VOTE: VoteType, - MEMBERSHIP: Membership, - > +impl, MEMBERSHIP: Membership> TestableChannelImplementation< TYPES, Message, - PROPOSAL, - VOTE, MEMBERSHIP, MemoryNetwork, TYPES::SignatureKey>, - > for MemoryCommChannel + > for MemoryCommChannel { fn generate_network( ) -> Box, TYPES::SignatureKey>>) -> Self + 'static> @@ -620,359 +569,3 @@ impl< Box::new(move |network| MemoryCommChannel::new(network)) } } - -#[cfg(test)] -// panic in tests -#[allow(clippy::panic)] -mod tests { - // use super::*; - // use crate::{ - // demos::vdemo::{Addition, Subtraction, VDemoBlock, VDemoState, VDemoTransaction}, - // traits::election::static_committee::{ - // GeneralStaticCommittee, StaticElectionConfig, StaticVoteToken, - // }, - // }; - // - // use crate::traits::implementations::MemoryStorage; - // use async_compatibility_layer::logging::setup_logging; - // use hotshot_types::traits::election::QuorumExchange; - // use hotshot_types::traits::node_implementation::{ChannelMaps, ValidatingExchanges}; - // use hotshot_types::{ - // data::ViewNumber, - // message::{DataMessage, MessageKind, ValidatingMessage}, - // traits::{ - // signature_key::ed25519::{Ed25519Priv, Ed25519Pub}, - // state::ConsensusTime, - // }, - // vote::QuorumVote, - // }; - // use hotshot_types::{ - // data::{ValidatingLeaf, ValidatingProposal}, - // traits::consensus_type::validating_consensus::ValidatingConsensus, - // }; - // use serde::{Deserialize, Serialize}; - // - // #[derive( - // Copy, - // Clone, - // Debug, - // Default, - // Hash, - // PartialEq, - // Eq, - // PartialOrd, - // Ord, - // serde::Serialize, - // serde::Deserialize, - // )] - // struct Test {} - // #[derive(Clone, Debug, Deserialize, Serialize, Hash, Eq, PartialEq)] - // struct TestImpl {} - // - // // impl NetworkMsg for Test {} - // - // impl NodeType for Test { - // // TODO (da) can this be SequencingConsensus? - // type ConsensusType = ValidatingConsensus; - // type Time = ViewNumber; - // type BlockType = VDemoBlock; - // type SignatureKey = Ed25519Pub; - // type VoteTokenType = StaticVoteToken; - // type Transaction = VDemoTransaction; - // type ElectionConfigType = StaticElectionConfig; - // type StateType = VDemoState; - // } - // - // type TestMembership = GeneralStaticCommittee; - // type TestNetwork = MemoryCommChannel; - // - // impl NodeImplementation for TestImpl { - // type ConsensusMessage = ValidatingMessage; - // type Exchanges = ValidatingExchanges< - // Test, - // Message, - // QuorumExchange< - // Test, - // TestLeaf, - // TestProposal, - // TestMembership, - // TestNetwork, - // Message, - // >, - // ViewSyncExchange>, - // >; - // type Leaf = TestLeaf; - // type Storage = MemoryStorage; - // - // fn new_channel_maps( - // start_view: ViewNumber, - // ) -> (ChannelMaps, Option>) { - // (ChannelMaps::new(start_view), None) - // } - // } - // - // type TestLeaf = ValidatingLeaf; - // type TestVote = QuorumVote; - // type TestProposal = ValidatingProposal; - // - // /// fake Eq - // /// we can't compare the votetokentype for equality, so we can't - // /// derive EQ on `VoteType` and thereby message - // /// we are only sending data messages, though so we compare key and - // /// data message - // fn fake_message_eq(message_1: Message, message_2: Message) { - // assert_eq!(message_1.sender, message_2.sender); - // if let MessageKind::Data(DataMessage::SubmitTransaction(d_1, _)) = message_1.kind { - // if let MessageKind::Data(DataMessage::SubmitTransaction(d_2, _)) = message_2.kind { - // assert_eq!(d_1, d_2); - // } - // } else { - // panic!("Got unexpected message type in memory test!"); - // } - // } - // - // #[instrument] - // fn get_pubkey() -> Ed25519Pub { - // let priv_key = Ed25519Priv::generate(); - // Ed25519Pub::from_private(&priv_key) - // } - // - // /// create a message - // fn gen_messages(num_messages: u64, seed: u64, pk: Ed25519Pub) -> Vec> { - // let mut messages = Vec::new(); - // for i in 0..num_messages { - // let message = Message { - // sender: pk, - // kind: MessageKind::Data(DataMessage::SubmitTransaction( - // VDemoTransaction { - // add: Addition { - // account: "A".to_string(), - // amount: 50 + i + seed, - // }, - // sub: Subtraction { - // account: "B".to_string(), - // amount: 50 + i + seed, - // }, - // nonce: seed + i, - // padding: vec![50; 0], - // }, - // ::new(0), - // )), - // _phantom: PhantomData, - // }; - // messages.push(message); - // } - // messages - // } - // - // // Spawning a single MemoryNetwork should produce no errors - // #[cfg_attr( - // feature = "tokio-executor", - // tokio::test(flavor = "multi_thread", worker_threads = 2) - // )] - // #[cfg_attr(feature = "async-std-executor", async_std::test)] - // #[instrument] - // async fn spawn_single() { - // setup_logging(); - // let group: Arc, ::SignatureKey>> = - // MasterMap::new(); - // trace!(?group); - // let pub_key = get_pubkey(); - // let _network = MemoryNetwork::new(pub_key, NoMetrics::boxed(), group, Option::None); - // } - // - // // // Spawning a two MemoryNetworks and connecting them should produce no errors - // #[cfg_attr( - // feature = "tokio-executor", - // tokio::test(flavor = "multi_thread", worker_threads = 2) - // )] - // #[cfg_attr(feature = "async-std-executor", async_std::test)] - // #[instrument] - // async fn spawn_double() { - // setup_logging(); - // let group: Arc, ::SignatureKey>> = - // MasterMap::new(); - // trace!(?group); - // let pub_key_1 = get_pubkey(); - // let _network_1 = - // MemoryNetwork::new(pub_key_1, NoMetrics::boxed(), group.clone(), Option::None); - // let pub_key_2 = get_pubkey(); - // let _network_2 = MemoryNetwork::new(pub_key_2, NoMetrics::boxed(), group, Option::None); - // } - // - // // Check to make sure direct queue works - // #[cfg_attr( - // feature = "tokio-executor", - // tokio::test(flavor = "multi_thread", worker_threads = 2) - // )] - // #[cfg_attr(feature = "async-std-executor", async_std::test)] - // #[allow(deprecated)] - // #[instrument] - // async fn direct_queue() { - // setup_logging(); - // // Create some dummy messages - // - // // Make and connect the networking instances - // let group: Arc, ::SignatureKey>> = - // MasterMap::new(); - // trace!(?group); - // let pub_key_1 = get_pubkey(); - // let network1 = - // MemoryNetwork::new(pub_key_1, NoMetrics::boxed(), group.clone(), Option::None); - // let pub_key_2 = get_pubkey(); - // let network2 = MemoryNetwork::new(pub_key_2, NoMetrics::boxed(), group, Option::None); - // - // let first_messages: Vec> = gen_messages(5, 100, pub_key_1); - // - // // Test 1 -> 2 - // // Send messages - // for sent_message in first_messages { - // network1 - // .direct_message(sent_message.clone(), pub_key_2) - // .await - // .expect("Failed to message node"); - // let mut recv_messages = network2 - // .recv_msgs(TransmitType::Direct) - // .await - // .expect("Failed to receive message"); - // let recv_message = recv_messages.pop().unwrap(); - // assert!(recv_messages.is_empty()); - // fake_message_eq(sent_message, recv_message); - // } - // - // let second_messages: Vec> = gen_messages(5, 200, pub_key_2); - // - // // Test 2 -> 1 - // // Send messages - // for sent_message in second_messages { - // network2 - // .direct_message(sent_message.clone(), pub_key_1) - // .await - // .expect("Failed to message node"); - // let mut recv_messages = network1 - // .recv_msgs(TransmitType::Direct) - // .await - // .expect("Failed to receive message"); - // let recv_message = recv_messages.pop().unwrap(); - // assert!(recv_messages.is_empty()); - // fake_message_eq(sent_message, recv_message); - // } - // } - // - // // Check to make sure direct queue works - // #[cfg_attr( - // feature = "tokio-executor", - // tokio::test(flavor = "multi_thread", worker_threads = 2) - // )] - // #[cfg_attr(feature = "async-std-executor", async_std::test)] - // #[allow(deprecated)] - // #[instrument] - // async fn broadcast_queue() { - // setup_logging(); - // // Make and connect the networking instances - // let group: Arc, ::SignatureKey>> = - // MasterMap::new(); - // trace!(?group); - // let pub_key_1 = get_pubkey(); - // let network1 = - // MemoryNetwork::new(pub_key_1, NoMetrics::boxed(), group.clone(), Option::None); - // let pub_key_2 = get_pubkey(); - // let network2 = MemoryNetwork::new(pub_key_2, NoMetrics::boxed(), group, Option::None); - // - // let first_messages: Vec> = gen_messages(5, 100, pub_key_1); - // - // // Test 1 -> 2 - // // Send messages - // for sent_message in first_messages { - // network1 - // .broadcast_message( - // sent_message.clone(), - // vec![pub_key_2].into_iter().collect::>(), - // ) - // .await - // .expect("Failed to message node"); - // let mut recv_messages = network2 - // .recv_msgs(TransmitType::Broadcast) - // .await - // .expect("Failed to receive message"); - // let recv_message = recv_messages.pop().unwrap(); - // assert!(recv_messages.is_empty()); - // fake_message_eq(sent_message, recv_message); - // } - // - // let second_messages: Vec> = gen_messages(5, 200, pub_key_2); - // - // // Test 2 -> 1 - // // Send messages - // for sent_message in second_messages { - // network2 - // .broadcast_message( - // sent_message.clone(), - // vec![pub_key_1].into_iter().collect::>(), - // ) - // .await - // .expect("Failed to message node"); - // let mut recv_messages = network1 - // .recv_msgs(TransmitType::Broadcast) - // .await - // .expect("Failed to receive message"); - // let recv_message = recv_messages.pop().unwrap(); - // assert!(recv_messages.is_empty()); - // fake_message_eq(sent_message, recv_message); - // } - // } - // - // #[cfg_attr( - // feature = "tokio-executor", - // tokio::test(flavor = "multi_thread", worker_threads = 2) - // )] - // #[cfg_attr(feature = "async-std-executor", async_std::test)] - // #[instrument] - // #[allow(deprecated)] - // async fn test_in_flight_message_count() { - // // setup_logging(); - // - // // let group: Arc, ::SignatureKey>> = - // // MasterMap::new(); - // // trace!(?group); - // // let pub_key_1 = get_pubkey(); - // // let network1 = - // // MemoryNetwork::new(pub_key_1, NoMetrics::boxed(), group.clone(), Option::None); - // // let pub_key_2 = get_pubkey(); - // // let network2 = MemoryNetwork::new(pub_key_2, NoMetrics::boxed(), group, Option::None); - // - // // // Create some dummy messages - // // let messages: Vec> = gen_messages(5, 100, pub_key_1); - // - // // // assert_eq!(network1.in_flight_message_count(), Some(0)); - // // // assert_eq!(network2.in_flight_message_count(), Some(0)); - // - // // for (_count, message) in messages.iter().enumerate() { - // // network1 - // // .direct_message(message.clone(), pub_key_2) - // // .await - // // .unwrap(); - // // // network 2 has received `count` broadcast messages and `count + 1` direct messages - // // // assert_eq!(network2.in_flight_message_count(), Some(count + count + 1)); - // - // // // network2.broadcast_message(message.clone()).await.unwrap(); - // // // network 1 has received `count` broadcast messages - // // // assert_eq!(network1.in_flight_message_count(), Some(count + 1)); - // - // // // network 2 has received `count + 1` broadcast messages and `count + 1` direct messages - // // // assert_eq!(network2.in_flight_message_count(), Some((count + 1) * 2)); - // // } - // - // // for _count in (0..messages.len()).rev() { - // // network1.recv_msgs(TransmitType::Broadcast).await.unwrap(); - // // // assert_eq!(network1.in_flight_message_count(), Some(count)); - // - // // network2.recv_msgs(TransmitType::Broadcast).await.unwrap(); - // // network2.recv_msgs(TransmitType::Direct).await.unwrap(); - // // // assert_eq!(network2.in_flight_message_count(), Some(count * 2)); - // // } - // - // // // assert_eq!(network1.in_flight_message_count(), Some(0)); - // // // assert_eq!(network2.in_flight_message_count(), Some(0)); - // } -} diff --git a/crates/hotshot/src/traits/networking/web_server_libp2p_fallback.rs b/crates/hotshot/src/traits/networking/web_server_libp2p_fallback.rs index 723c7c071d..b3324681a5 100644 --- a/crates/hotshot/src/traits/networking/web_server_libp2p_fallback.rs +++ b/crates/hotshot/src/traits/networking/web_server_libp2p_fallback.rs @@ -10,9 +10,10 @@ use async_trait::async_trait; use futures::join; +use async_compatibility_layer::channel::UnboundedSendError; use hotshot_task::{boxed_sync, BoxSyncFuture}; use hotshot_types::{ - data::ProposalType, + data::ViewNumber, message::Message, traits::{ election::Membership, @@ -23,7 +24,6 @@ use hotshot_types::{ }, node_implementation::NodeType, }, - vote::VoteType, }; use std::{marker::PhantomData, sync::Arc}; use tracing::error; @@ -155,13 +155,8 @@ impl, MEMBERSHIP: Membership, - PROPOSAL: ProposalType, - VOTE: VoteType, - MEMBERSHIP: Membership, - > CommunicationChannel, PROPOSAL, VOTE, MEMBERSHIP> +impl, MEMBERSHIP: Membership> + CommunicationChannel, MEMBERSHIP> for WebServerWithFallbackCommChannel { type NETWORK = CombinedNetworks; @@ -263,51 +258,38 @@ impl< boxed_sync(closure) } - async fn lookup_node(&self, pk: TYPES::SignatureKey) -> Result<(), NetworkError> { - match join!( - self.network().lookup_node(pk.clone()), - self.fallback().lookup_node(pk) - ) { - (Err(e1), Err(e2)) => { - error!( - "Both network lookups failed primary error: {}, fallback error: {}", - e1, e2 - ); - Err(e1) - } - (Err(e), _) => { - error!("Failed primary lookup with error: {}", e); - Ok(()) - } - (_, Err(e)) => { - error!("Failed backup lookup with error: {}", e); - Ok(()) - } - _ => Ok(()), - } + async fn queue_node_lookup( + &self, + view_number: ViewNumber, + pk: TYPES::SignatureKey, + ) -> Result<(), UnboundedSendError>> { + self.network() + .queue_node_lookup(view_number, pk.clone()) + .await?; + self.fallback().queue_node_lookup(view_number, pk).await?; + + Ok(()) } - async fn inject_consensus_info(&self, event: ConsensusIntentEvent) { + async fn inject_consensus_info(&self, event: ConsensusIntentEvent) { as ConnectedNetwork< Message, TYPES::SignatureKey, - >>::inject_consensus_info(self.network(), event) + >>::inject_consensus_info(self.network(), event.clone()) .await; + + as ConnectedNetwork< + Message, + TYPES::SignatureKey, + >>::inject_consensus_info(self.fallback(), event) + .await; } } -impl< - TYPES: NodeType, - I: NodeImplementation, - PROPOSAL: ProposalType, - VOTE: VoteType, - MEMBERSHIP: Membership, - > +impl, MEMBERSHIP: Membership> TestableChannelImplementation< TYPES, Message, - PROPOSAL, - VOTE, MEMBERSHIP, CombinedNetworks, > for WebServerWithFallbackCommChannel diff --git a/crates/hotshot/src/traits/networking/web_server_network.rs b/crates/hotshot/src/traits/networking/web_server_network.rs index e0001b94ab..72cd62cc8d 100644 --- a/crates/hotshot/src/traits/networking/web_server_network.rs +++ b/crates/hotshot/src/traits/networking/web_server_network.rs @@ -13,7 +13,6 @@ use async_lock::RwLock; use async_trait::async_trait; use hotshot_task::{boxed_sync, BoxSyncFuture}; use hotshot_types::{ - data::ProposalType, message::{Message, MessagePurpose}, traits::{ election::Membership, @@ -25,7 +24,6 @@ use hotshot_types::{ node_implementation::{NodeImplementation, NodeType}, signature_key::SignatureKey, }, - vote::VoteType, }; use hotshot_web_server::{self, config}; use rand::random; @@ -48,21 +46,14 @@ use tracing::{debug, error, info}; pub struct WebCommChannel< TYPES: NodeType, I: NodeImplementation, - PROPOSAL: ProposalType, - VOTE: VoteType, MEMBERSHIP: Membership, >( Arc, TYPES::SignatureKey, TYPES>>, - PhantomData<(MEMBERSHIP, I, PROPOSAL, VOTE)>, + PhantomData<(MEMBERSHIP, I)>, ); -impl< - TYPES: NodeType, - I: NodeImplementation, - PROPOSAL: ProposalType, - VOTE: VoteType, - MEMBERSHIP: Membership, - > WebCommChannel +impl, MEMBERSHIP: Membership> + WebCommChannel { /// Create new communication channel #[must_use] @@ -128,17 +119,23 @@ struct Inner { // TODO ED This should be TYPES::Time // Theoretically there should never be contention for this lock... /// Task map for quorum proposals. - proposal_task_map: Arc>>>, + proposal_task_map: + Arc>>>>, /// Task map for quorum votes. - vote_task_map: Arc>>>, + vote_task_map: + Arc>>>>, /// Task map for DACs. - dac_task_map: Arc>>>, + dac_task_map: + Arc>>>>, /// Task map for view sync certificates. - view_sync_cert_task_map: Arc>>>, + view_sync_cert_task_map: + Arc>>>>, /// Task map for view sync votes. - view_sync_vote_task_map: Arc>>>, + view_sync_vote_task_map: + Arc>>>>, /// Task map for transactions - txn_task_map: Arc>>>, + txn_task_map: + Arc>>>>, } impl Inner { @@ -146,7 +143,7 @@ impl Inner { /// Pull a web server. async fn poll_web_server( &self, - receiver: UnboundedReceiver, + receiver: UnboundedReceiver>, message_purpose: MessagePurpose, view_number: u64, ) -> Result<(), NetworkError> { @@ -161,6 +158,7 @@ impl Inner { while self.running.load(Ordering::Relaxed) { let endpoint = match message_purpose { MessagePurpose::Proposal => config::get_proposal_route(view_number), + MessagePurpose::CurrentProposal => config::get_recent_proposal_route(), MessagePurpose::Vote => config::get_vote_route(view_number, vote_index), MessagePurpose::Data => config::get_transactions_route(tx_index), MessagePurpose::Internal => unimplemented!(), @@ -171,6 +169,9 @@ impl Inner { config::get_view_sync_vote_route(view_number, vote_index) } MessagePurpose::DAC => config::get_da_certificate_route(view_number), + MessagePurpose::VidDisperse => config::get_vid_disperse_route(view_number), // like `Proposal` + MessagePurpose::VidVote => config::get_vid_vote_route(view_number, vote_index), // like `Vote` + MessagePurpose::VidCert => config::get_vid_cert_route(view_number), // like `DAC` }; if message_purpose == MessagePurpose::Data { @@ -221,6 +222,15 @@ impl Inner { // } // } } + MessagePurpose::CurrentProposal => { + // Only pushing the first proposal since we will soon only be allowing 1 proposal per view + self.broadcast_poll_queue + .write() + .await + .push(deserialized_messages[0].clone()); + + return Ok(()); + } MessagePurpose::Vote => { // error!( // "Received {} votes from web server for view {} is da {}", @@ -234,6 +244,14 @@ impl Inner { direct_poll_queue.push(vote.clone()); } } + MessagePurpose::VidVote => { + // TODO copy-pasted from `MessagePurpose::Vote` https://github.com/EspressoSystems/HotShot/issues/1690 + let mut direct_poll_queue = self.direct_poll_queue.write().await; + for vote in &deserialized_messages { + vote_index += 1; + direct_poll_queue.push(vote.clone()); + } + } MessagePurpose::DAC => { debug!( "Received DAC from web server for view {} {}", @@ -249,6 +267,41 @@ impl Inner { // In future we should check to make sure DAC is valid return Ok(()); } + MessagePurpose::VidCert => { + // TODO copy-pasted from `MessagePurpose::DAC` https://github.com/EspressoSystems/HotShot/issues/1690 + debug!( + "Received VID cert from web server for view {} {}", + view_number, self.is_da + ); + // Only pushing the first proposal since we will soon only be allowing 1 proposal per view + self.broadcast_poll_queue + .write() + .await + .push(deserialized_messages[0].clone()); + + // return if we found a VID cert, since there will only be 1 per view + // In future we should check to make sure VID cert is valid + return Ok(()); + } + MessagePurpose::VidDisperse => { + // TODO copy-pasted from `MessagePurpose::Proposal` https://github.com/EspressoSystems/HotShot/issues/1690 + + // Only pushing the first proposal since we will soon only be allowing 1 proposal per view + self.broadcast_poll_queue + .write() + .await + .push(deserialized_messages[0].clone()); + + return Ok(()); + // Wait for the view to change before polling for proposals again + // let event = receiver.recv().await; + // match event { + // Ok(event) => view_number = event.view_number(), + // Err(_r) => { + // error!("Proposal receiver error! It was likely shutdown") + // } + // } + } MessagePurpose::ViewSyncVote => { // error!( // "Received {} view sync votes from web server for view {} is da {}", @@ -500,13 +553,18 @@ impl< MessagePurpose::Proposal => config::post_proposal_route(*view_number), MessagePurpose::Vote => config::post_vote_route(*view_number), MessagePurpose::Data => config::post_transactions_route(), - MessagePurpose::Internal => return Err(WebServerNetworkError::EndpointError), + MessagePurpose::Internal | MessagePurpose::CurrentProposal => { + return Err(WebServerNetworkError::EndpointError) + } MessagePurpose::ViewSyncProposal => { // error!("Posting view sync proposal route is: {}", config::post_view_sync_proposal_route(*view_number)); config::post_view_sync_proposal_route(*view_number) } MessagePurpose::ViewSyncVote => config::post_view_sync_vote_route(*view_number), MessagePurpose::DAC => config::post_da_certificate_route(*view_number), + MessagePurpose::VidVote => config::post_vid_vote_route(*view_number), + MessagePurpose::VidDisperse => config::post_vid_disperse_route(*view_number), + MessagePurpose::VidCert => config::post_vid_cert_route(*view_number), }; let network_msg: SendMsg = SendMsg { @@ -518,14 +576,9 @@ impl< } #[async_trait] -impl< - TYPES: NodeType, - I: NodeImplementation, - PROPOSAL: ProposalType, - VOTE: VoteType, - MEMBERSHIP: Membership, - > CommunicationChannel, PROPOSAL, VOTE, MEMBERSHIP> - for WebCommChannel +impl, MEMBERSHIP: Membership> + CommunicationChannel, MEMBERSHIP> + for WebCommChannel { type NETWORK = WebServerNetwork, TYPES::SignatureKey, TYPES>; /// Blocks until node is successfully initialized @@ -608,13 +661,7 @@ impl< boxed_sync(closure) } - /// look up a node - /// blocking - async fn lookup_node(&self, _pk: TYPES::SignatureKey) -> Result<(), NetworkError> { - Ok(()) - } - - async fn inject_consensus_info(&self, event: ConsensusIntentEvent) { + async fn inject_consensus_info(&self, event: ConsensusIntentEvent) { as ConnectedNetwork< Message, TYPES::SignatureKey, @@ -725,14 +772,8 @@ impl< boxed_sync(closure) } - /// look up a node - /// blocking - async fn lookup_node(&self, _pk: K) -> Result<(), NetworkError> { - Ok(()) - } - #[allow(clippy::too_many_lines)] - async fn inject_consensus_info(&self, event: ConsensusIntentEvent) { + async fn inject_consensus_info(&self, event: ConsensusIntentEvent) { debug!( "Injecting event: {:?} is da {}", event.clone(), @@ -783,6 +824,25 @@ impl< .await; } } + ConsensusIntentEvent::PollForCurrentProposal => { + // create new task + let (_, receiver) = unbounded(); + + async_spawn({ + let inner_clone = self.inner.clone(); + async move { + if let Err(e) = inner_clone + .poll_web_server(receiver, MessagePurpose::CurrentProposal, 1) + .await + { + error!( + "Background receive proposal polling encountered an error: {:?}", + e + ); + } + } + }); + } ConsensusIntentEvent::PollForVotes(view_number) => { let mut task_map = self.inner.vote_task_map.write().await; if let Entry::Vacant(e) = task_map.entry(view_number) { @@ -997,7 +1057,7 @@ impl< }; } - _ => error!("Unexpected event!"), + _ => {} } } } @@ -1052,14 +1112,9 @@ impl> } } -impl< - TYPES: NodeType, - I: NodeImplementation, - PROPOSAL: ProposalType, - VOTE: VoteType, - MEMBERSHIP: Membership, - > TestableNetworkingImplementation> - for WebCommChannel +impl, MEMBERSHIP: Membership> + TestableNetworkingImplementation> + for WebCommChannel { fn generator( expected_node_count: usize, @@ -1087,21 +1142,13 @@ impl< } } -impl< - TYPES: NodeType, - I: NodeImplementation, - PROPOSAL: ProposalType, - VOTE: VoteType, - MEMBERSHIP: Membership, - > +impl, MEMBERSHIP: Membership> TestableChannelImplementation< TYPES, Message, - PROPOSAL, - VOTE, MEMBERSHIP, WebServerNetwork, TYPES::SignatureKey, TYPES>, - > for WebCommChannel + > for WebCommChannel { fn generate_network() -> Box< dyn Fn(Arc, TYPES::SignatureKey, TYPES>>) -> Self diff --git a/crates/hotshot/src/traits/networking/web_sever_libp2p_fallback.rs b/crates/hotshot/src/traits/networking/web_sever_libp2p_fallback.rs deleted file mode 100644 index 723c7c071d..0000000000 --- a/crates/hotshot/src/traits/networking/web_sever_libp2p_fallback.rs +++ /dev/null @@ -1,318 +0,0 @@ -//! Networking Implementation that has a primary and a fallback newtork. If the primary -//! Errors we will use the backup to send or receive -use super::NetworkError; -use crate::{ - traits::implementations::{Libp2pNetwork, WebServerNetwork}, - NodeImplementation, -}; - -use async_trait::async_trait; - -use futures::join; - -use hotshot_task::{boxed_sync, BoxSyncFuture}; -use hotshot_types::{ - data::ProposalType, - message::Message, - traits::{ - election::Membership, - network::{ - CommunicationChannel, ConnectedNetwork, ConsensusIntentEvent, - TestableChannelImplementation, TestableNetworkingImplementation, TransmitType, - ViewMessage, - }, - node_implementation::NodeType, - }, - vote::VoteType, -}; -use std::{marker::PhantomData, sync::Arc}; -use tracing::error; -/// A communication channel with 2 networks, where we can fall back to the slower network if the -/// primary fails -#[derive(Clone, Debug)] -pub struct WebServerWithFallbackCommChannel< - TYPES: NodeType, - I: NodeImplementation, - MEMBERSHIP: Membership, -> { - /// The two networks we'll use for send/recv - networks: Arc>, -} - -impl, MEMBERSHIP: Membership> - WebServerWithFallbackCommChannel -{ - /// Constructor - #[must_use] - pub fn new(networks: Arc>) -> Self { - Self { networks } - } - - /// Get a ref to the primary network - #[must_use] - pub fn network(&self) -> &WebServerNetwork, TYPES::SignatureKey, TYPES> { - &self.networks.0 - } - - /// Get a ref to the backup network - #[must_use] - pub fn fallback(&self) -> &Libp2pNetwork, TYPES::SignatureKey> { - &self.networks.1 - } -} - -/// Wrapper for the tuple of `WebServerNetwork` and `Libp2pNetwork` -/// We need this so we can impl `TestableNetworkingImplementation` -/// on the tuple -#[derive(Debug, Clone)] -pub struct CombinedNetworks< - TYPES: NodeType, - I: NodeImplementation, - MEMBERSHIP: Membership, ->( - pub WebServerNetwork, TYPES::SignatureKey, TYPES>, - pub Libp2pNetwork, TYPES::SignatureKey>, - pub PhantomData, -); - -impl, MEMBERSHIP: Membership> - TestableNetworkingImplementation> - for CombinedNetworks -{ - fn generator( - expected_node_count: usize, - num_bootstrap: usize, - network_id: usize, - da_committee_size: usize, - is_da: bool, - ) -> Box Self + 'static> { - let generators = ( - , - TYPES::SignatureKey, - TYPES, - > as TestableNetworkingImplementation<_, _>>::generator( - expected_node_count, - num_bootstrap, - network_id, - da_committee_size, - is_da - ), - , TYPES::SignatureKey> as TestableNetworkingImplementation<_, _>>::generator( - expected_node_count, - num_bootstrap, - network_id, - da_committee_size, - is_da - ) - ); - Box::new(move |node_id| { - CombinedNetworks(generators.0(node_id), generators.1(node_id), PhantomData) - }) - } - - /// Get the number of messages in-flight. - /// - /// Some implementations will not be able to tell how many messages there are in-flight. These implementations should return `None`. - fn in_flight_message_count(&self) -> Option { - None - } -} - -impl, MEMBERSHIP: Membership> - TestableNetworkingImplementation> - for WebServerWithFallbackCommChannel -{ - fn generator( - expected_node_count: usize, - num_bootstrap: usize, - network_id: usize, - da_committee_size: usize, - is_da: bool, - ) -> Box Self + 'static> { - let generator = as TestableNetworkingImplementation<_, _>>::generator( - expected_node_count, - num_bootstrap, - network_id, - da_committee_size, - is_da - ); - Box::new(move |node_id| Self { - networks: generator(node_id).into(), - }) - } - - /// Get the number of messages in-flight. - /// - /// Some implementations will not be able to tell how many messages there are in-flight. These implementations should return `None`. - fn in_flight_message_count(&self) -> Option { - None - } -} - -#[async_trait] -impl< - TYPES: NodeType, - I: NodeImplementation, - PROPOSAL: ProposalType, - VOTE: VoteType, - MEMBERSHIP: Membership, - > CommunicationChannel, PROPOSAL, VOTE, MEMBERSHIP> - for WebServerWithFallbackCommChannel -{ - type NETWORK = CombinedNetworks; - - async fn wait_for_ready(&self) { - join!( - self.network().wait_for_ready(), - self.fallback().wait_for_ready() - ); - } - - async fn is_ready(&self) -> bool { - self.network().is_ready().await && self.fallback().is_ready().await - } - - fn shut_down<'a, 'b>(&'a self) -> BoxSyncFuture<'b, ()> - where - 'a: 'b, - Self: 'b, - { - let closure = async move { - join!(self.network().shut_down(), self.fallback().shut_down()); - }; - boxed_sync(closure) - } - - async fn broadcast_message( - &self, - message: Message, - election: &MEMBERSHIP, - ) -> Result<(), NetworkError> { - let recipients = - >::get_committee(election, message.get_view_number()); - let fallback = self - .fallback() - .broadcast_message(message.clone(), recipients.clone()); - let network = self.network().broadcast_message(message, recipients); - match join!(fallback, network) { - (Err(e1), Err(e2)) => { - error!( - "Both network broadcasts failed primary error: {}, fallback error: {}", - e1, e2 - ); - Err(e1) - } - (Err(e), _) => { - error!("Failed primary broadcast with error: {}", e); - Ok(()) - } - (_, Err(e)) => { - error!("Failed backup broadcast with error: {}", e); - Ok(()) - } - _ => Ok(()), - } - } - - async fn direct_message( - &self, - message: Message, - recipient: TYPES::SignatureKey, - ) -> Result<(), NetworkError> { - match self - .network() - .direct_message(message.clone(), recipient.clone()) - .await - { - Ok(_) => Ok(()), - Err(e) => { - error!( - "Falling back on direct message, error on primary network: {}", - e - ); - self.fallback().direct_message(message, recipient).await - } - } - } - - fn recv_msgs<'a, 'b>( - &'a self, - transmit_type: TransmitType, - ) -> BoxSyncFuture<'b, Result>, NetworkError>> - where - 'a: 'b, - Self: 'b, - { - let closure = async move { - match self.network().recv_msgs(transmit_type).await { - Ok(msgs) => Ok(msgs), - Err(e) => { - error!( - "Falling back on recv message, error on primary network: {}", - e - ); - self.fallback().recv_msgs(transmit_type).await - } - } - }; - boxed_sync(closure) - } - - async fn lookup_node(&self, pk: TYPES::SignatureKey) -> Result<(), NetworkError> { - match join!( - self.network().lookup_node(pk.clone()), - self.fallback().lookup_node(pk) - ) { - (Err(e1), Err(e2)) => { - error!( - "Both network lookups failed primary error: {}, fallback error: {}", - e1, e2 - ); - Err(e1) - } - (Err(e), _) => { - error!("Failed primary lookup with error: {}", e); - Ok(()) - } - (_, Err(e)) => { - error!("Failed backup lookup with error: {}", e); - Ok(()) - } - _ => Ok(()), - } - } - - async fn inject_consensus_info(&self, event: ConsensusIntentEvent) { - as ConnectedNetwork< - Message, - TYPES::SignatureKey, - >>::inject_consensus_info(self.network(), event) - .await; - } -} - -impl< - TYPES: NodeType, - I: NodeImplementation, - PROPOSAL: ProposalType, - VOTE: VoteType, - MEMBERSHIP: Membership, - > - TestableChannelImplementation< - TYPES, - Message, - PROPOSAL, - VOTE, - MEMBERSHIP, - CombinedNetworks, - > for WebServerWithFallbackCommChannel -{ - fn generate_network() -> Box) -> Self + 'static> { - Box::new(move |network| WebServerWithFallbackCommChannel::new(network)) - } -} diff --git a/crates/hotshot/src/traits/storage/atomic_storage.rs b/crates/hotshot/src/traits/storage/atomic_storage.rs index 9d054fe1ac..4654d65ca7 100644 --- a/crates/hotshot/src/traits/storage/atomic_storage.rs +++ b/crates/hotshot/src/traits/storage/atomic_storage.rs @@ -33,7 +33,7 @@ where atomic_store: Mutex, /// The Blocks stored by this [`AtomicStorage`] - blocks: HashMapStore, STATE::Block>, + blocks: HashMapStore, STATE::BlockPayload>, /// The [`QuorumCertificate`]s stored by this [`AtomicStorage`] qcs: DualKeyValueStore>, @@ -142,15 +142,15 @@ impl Storage for AtomicStorage { #[instrument(name = "AtomicStorage::get_block", skip_all)] async fn get_block( &self, - hash: &Commitment, - ) -> StorageResult> { + hash: &Commitment, + ) -> StorageResult> { Ok(self.inner.blocks.get(hash).await) } #[instrument(name = "AtomicStorage::get_qc", skip_all)] async fn get_qc( &self, - hash: &Commitment, + hash: &Commitment, ) -> StorageResult>> { Ok(self.inner.qcs.load_by_key_1_ref(hash).await) } @@ -176,7 +176,7 @@ impl Storage for AtomicStorage { #[instrument(name = "AtomicStorage::get_leaf_by_block", skip_all)] async fn get_leaf_by_block( &self, - hash: &Commitment, + hash: &Commitment, ) -> StorageResult>> { Ok(self.inner.leaves.load_by_key_2_ref(hash).await) } @@ -187,7 +187,7 @@ impl Storage for AtomicStorage { } async fn get_internal_state(&self) -> StorageState { - let mut blocks: Vec<(Commitment, STATE::Block)> = + let mut blocks: Vec<(Commitment, STATE::BBlockPayloadlock)> = self.inner.blocks.load_all().await.into_iter().collect(); blocks.sort_by_key(|(hash, _)| *hash); @@ -226,8 +226,8 @@ impl<'a, STATE: StateContents + 'static> StorageUpdater<'a, STATE> #[instrument(name = "AtomicStorage::get_block", skip_all)] async fn insert_block( &mut self, - hash: Commitment, - block: STATE::Block, + hash: Commitment, + block: STATE::BlockPayload, ) -> StorageResult { trace!(?block, "inserting block"); self.inner diff --git a/crates/hotshot/src/traits/storage/atomic_storage/dual_key_value_store.rs b/crates/hotshot/src/traits/storage/atomic_storage/dual_key_value_store.rs index 70431af012..84cf8c76a2 100644 --- a/crates/hotshot/src/traits/storage/atomic_storage/dual_key_value_store.rs +++ b/crates/hotshot/src/traits/storage/atomic_storage/dual_key_value_store.rs @@ -181,7 +181,7 @@ pub trait DualKeyValue: Serialize + DeserializeOwned + Clone { } impl DualKeyValue for QuorumCertificate { - type Key1 = Commitment; + type Key1 = Commitment; type Key2 = ViewNumber; const KEY_1_NAME: &'static str = "block_commitment"; @@ -200,7 +200,7 @@ where STATE: StateContents, { type Key1 = Commitment>; - type Key2 = Commitment; + type Key2 = Commitment; const KEY_1_NAME: &'static str = "leaf_commitment"; const KEY_2_NAME: &'static str = "block_commitment"; @@ -210,6 +210,6 @@ where } fn key_2(&self) -> Self::Key2 { - ::commit(&self.deltas) + ::commit(&self.deltas) } } diff --git a/crates/hotshot/src/traits/storage/memory_storage.rs b/crates/hotshot/src/traits/storage/memory_storage.rs index 2a9e570a76..dd6e0217d5 100644 --- a/crates/hotshot/src/traits/storage/memory_storage.rs +++ b/crates/hotshot/src/traits/storage/memory_storage.rs @@ -117,16 +117,15 @@ mod test { use crate::traits::election::static_committee::{StaticElectionConfig, StaticVoteToken}; use super::*; - use hotshot_signature_key::bn254::BN254Pub; + use hotshot_signature_key::bn254::BLSPubKey; use hotshot_types::{ certificate::{AssembledSignature, QuorumCertificate}, - constants::genesis_proposer_id, - data::{fake_commitment, ValidatingLeaf, ViewNumber}, + data::{fake_commitment, genesis_proposer_id, ValidatingLeaf, ViewNumber}, traits::{ block_contents::dummy::{DummyBlock, DummyState}, node_implementation::NodeType, state::ConsensusTime, - Block, + BlockPayload, }, }; use std::{fmt::Debug, hash::Hash}; @@ -150,9 +149,9 @@ mod test { impl NodeType for DummyTypes { type Time = ViewNumber; type BlockType = DummyBlock; - type SignatureKey = BN254Pub; + type SignatureKey = BLSPubKey; type VoteTokenType = StaticVoteToken; - type Transaction = ::Transaction; + type Transaction = ::Transaction; type ElectionConfigType = StaticElectionConfig; type StateType = DummyState; } diff --git a/crates/hotshot/src/types/handle.rs b/crates/hotshot/src/types/handle.rs index 5b8e737c1a..35e79a78dd 100644 --- a/crates/hotshot/src/types/handle.rs +++ b/crates/hotshot/src/types/handle.rs @@ -190,7 +190,7 @@ impl + 'static> SystemContextHandl if let Ok(anchor_leaf) = self.storage().get_anchored_view().await { if anchor_leaf.view_number == TYPES::Time::genesis() { let leaf: I::Leaf = I::Leaf::from_stored_view(anchor_leaf); - let mut qc = QuorumCertificate::::genesis(); + let mut qc = QuorumCertificate::>::genesis(); qc.set_leaf_commitment(leaf.commit()); let event = Event { view_number: TYPES::Time::genesis(), @@ -226,7 +226,7 @@ impl + 'static> SystemContextHandl // ) -> Result< // ( // Vec<>::Leaf>, - // QuorumCertificate>::Leaf>, + // QuorumCertificate>::Leaf>>, // ), // HotShotError, // > { @@ -333,7 +333,7 @@ impl + 'static> SystemContextHandl #[cfg(feature = "hotshot-testing")] pub fn create_yes_message( &self, - justify_qc_commitment: Commitment>, + justify_qc_commitment: Commitment>>, leaf_commitment: Commitment, current_view: TYPES::Time, vote_token: TYPES::VoteTokenType, @@ -342,7 +342,7 @@ impl + 'static> SystemContextHandl QuorumEx: ConsensusExchange< TYPES, Message, - Certificate = QuorumCertificate, + Certificate = QuorumCertificate>, >, { let inner = self.hotshot.inner.clone(); diff --git a/crates/libp2p-networking/Cargo.toml b/crates/libp2p-networking/Cargo.toml index 9e9df1cd98..dfdb02020e 100644 --- a/crates/libp2p-networking/Cargo.toml +++ b/crates/libp2p-networking/Cargo.toml @@ -9,7 +9,7 @@ authors = ["Espresso Systems "] [features] default = ["webui"] -webui = ["tide"] +webui = [] # # this only has effect on linux # lossy_network = [ @@ -34,6 +34,7 @@ custom_debug = { workspace = true } derive_builder = "0.12.0" either = { workspace = true } futures = { workspace = true } +hotshot-constants = { path = "../constants" } hotshot-utils = { path = "../utils" } libp2p-swarm-derive = { workspace = true } libp2p-identity = { workspace = true } @@ -41,19 +42,19 @@ libp2p-noise = { version = "0.43.0", default-features = false } parking_lot = "0.12.1" rand = { workspace = true } serde = { workspace = true } -serde_json = "1.0.106" +serde_json = "1.0.107" snafu = { workspace = true } tide = { version = "0.16", optional = true, default-features = false, features = [ "h1-server", ] } -# TODO do we want this as non optional?? -tokio-stream = "0.1.14" tracing = { workspace = true } void = "1.0.2" +dashmap = "5.5.3" [target.'cfg(all(async_executor_impl = "tokio"))'.dependencies] libp2p = { workspace = true, features = ["tokio"] } tokio = { workspace = true } +tokio-stream = "0.1.14" [target.'cfg(all(async_executor_impl = "async-std"))'.dependencies] libp2p = { workspace = true, features = ["async-std"] } async-std = { workspace = true } @@ -74,5 +75,3 @@ netlink-sys = { git = "https://github.com/espressosystems/netlink.git", version ], optional = true } netlink-packet-generic = { git = "https://github.com/espressosystems/netlink.git", version = "0.2.0", optional = true } -[dev-dependencies] -clap = { version = "4.4", features = ["derive", "env"] } diff --git a/crates/libp2p-networking/src/network/behaviours/dht/cache.rs b/crates/libp2p-networking/src/network/behaviours/dht/cache.rs new file mode 100644 index 0000000000..602bb41e16 --- /dev/null +++ b/crates/libp2p-networking/src/network/behaviours/dht/cache.rs @@ -0,0 +1,325 @@ +use std::{ + collections::{BTreeMap, HashMap}, + sync::{ + atomic::{AtomicU32, Ordering}, + Arc, + }, + time::{Duration, SystemTime}, +}; + +use async_compatibility_layer::art::async_block_on; +use async_lock::RwLock; +use bincode::Options; +use dashmap::{mapref::one::Ref, DashMap}; +use hotshot_constants::KAD_DEFAULT_REPUB_INTERVAL_SEC; +use hotshot_utils::bincode::bincode_opts; +use snafu::{ResultExt, Snafu}; + +/// Error wrapper type for cache +#[derive(Debug, Snafu)] +#[snafu(visibility(pub))] +pub enum CacheError { + /// Failed to read or write from disk + Disk { + /// source of error + source: std::io::Error, + }, + + /// Failure to serialize the cache + Serialization { + /// source of error + source: Box, + }, + + /// Failure to deserialize the cache + Deserialization { + /// source of error + source: Box, + }, + + /// General cache error + GeneralCache { + /// source of error + source: Box, + }, +} + +#[derive(Clone, derive_builder::Builder, custom_debug::Debug, Default)] +pub struct Config { + #[builder(default = "Some(\"dht.cache\".to_string())")] + pub filename: Option, + #[builder(default = "Duration::from_secs(KAD_DEFAULT_REPUB_INTERVAL_SEC * 16)")] + pub expiry: Duration, + #[builder(default = "4")] + pub max_disk_parity_delta: u32, +} + +impl Default for Cache { + fn default() -> Self { + async_block_on(Self::new(Config::default())) + } +} + +pub struct Cache { + /// the cache's config + config: Config, + + /// the cache for records (key -> value) + cache: Arc, Vec>>, + /// the expiries for the dht cache, in order (expiry time -> key) + expiries: Arc>>>, + + /// number of inserts since the last save + disk_parity_delta: Arc, +} + +impl Cache { + pub async fn new(config: Config) -> Self { + let cache = Self { + cache: Arc::new(DashMap::new()), + expiries: Arc::new(RwLock::new(BTreeMap::new())), + config, + disk_parity_delta: Arc::new(AtomicU32::new(0)), + }; + + // try loading from file + if let Err(err) = cache.load().await { + tracing::warn!("failed to load cache from file: {}", err); + }; + + cache + } + + pub async fn load(&self) -> Result<(), CacheError> { + if let Some(filename) = &self.config.filename { + let encoded = std::fs::read(filename).context(DiskSnafu)?; + + let cache: HashMap, Vec)> = bincode_opts() + .deserialize(&encoded) + .context(DeserializationSnafu)?; + + // inline prune and insert + let now = SystemTime::now(); + for (expiry, (key, value)) in cache { + if now < expiry { + self.cache.insert(key.clone(), value); + self.expiries.write().await.insert(expiry, key); + } + } + } + + Ok(()) + } + + pub async fn save(&self) -> Result<(), CacheError> { + if let Some(filename) = &self.config.filename { + // prune first + self.prune().await; + + // serialize + let mut cache_to_write = HashMap::new(); + let expiries = self.expiries.read().await; + for (expiry, key) in &*expiries { + if let Some(entry) = self.cache.get(key) { + cache_to_write.insert(expiry, (key, entry.value().clone())); + } else { + tracing::warn!("key not found in cache: {:?}", key); + Err(CacheError::GeneralCache { + source: Box::new(bincode::ErrorKind::Custom( + "key not found in cache".to_string(), + )), + })?; + }; + } + + let encoded = bincode_opts() + .serialize(&cache_to_write) + .context(SerializationSnafu)?; + + std::fs::write(filename, encoded).context(DiskSnafu)?; + } + + Ok(()) + } + + async fn prune(&self) { + let now = SystemTime::now(); + let mut expiries = self.expiries.write().await; + let mut removed: u32 = 0; + + while let Some((expires, key)) = expiries.pop_first() { + if now > expires { + self.cache.remove(&key); + removed += 1; + } else { + expiries.insert(expires, key); + break; + } + } + + if removed > 0 { + self.disk_parity_delta.fetch_add(removed, Ordering::Relaxed); + } + } + + pub async fn get(&self, key: &Vec) -> Option, Vec>> { + // prune, save if necessary + self.prune().await; + self.save_if_necessary().await; + + // get + self.cache.get(key) + } + + pub async fn insert(&self, key: Vec, value: Vec) { + // insert into cache and expiries + self.cache.insert(key.clone(), value); + self.expiries + .write() + .await + .insert(SystemTime::now() + self.config.expiry, key); + + // save if reached max disk parity delta + self.disk_parity_delta.fetch_add(1, Ordering::Relaxed); + self.save_if_necessary().await; + } + + async fn save_if_necessary(&self) { + let cur_disk_parity_delta = self.disk_parity_delta.load(Ordering::Relaxed); + if cur_disk_parity_delta >= self.config.max_disk_parity_delta { + if let Err(err) = self.save().await { + tracing::error!("failed to save cache to file: {}", err); + }; + } + } +} + +#[cfg(test)] +mod test { + + use super::*; + use async_compatibility_layer::art::async_sleep; + use libp2p_identity::PeerId; + use tracing::instrument; + + /// cache eviction test + #[cfg_attr( + async_executor_impl = "tokio", + tokio::test(flavor = "multi_thread", worker_threads = 2) + )] + #[cfg_attr(async_executor_impl = "async-std", async_std::test)] + #[instrument] + async fn test_dht_cache_eviction() { + async_compatibility_layer::logging::setup_logging(); + async_compatibility_layer::logging::setup_backtrace(); + + // cache with 1s eviction + let cache = Cache::new(Config { + filename: None, + expiry: Duration::from_secs(1), + max_disk_parity_delta: 4, + }) + .await; + + let (key, value) = (PeerId::random(), PeerId::random()); + + // insert + cache.insert(key.to_bytes(), value.to_bytes()).await; + + // check that it is in the cache and expiries + assert_eq!( + cache.get(&key.to_bytes()).await.unwrap().value(), + &value.to_bytes() + ); + assert_eq!(cache.expiries.read().await.len(), 1); + + // sleep for 1s + async_sleep(Duration::from_secs(1)).await; + + // check that now is evicted + assert!(cache.get(&key.to_bytes()).await.is_none()); + + // check that the cache and expiries are empty + assert!(cache.expiries.read().await.is_empty()); + assert!(cache.cache.is_empty()); + } + + /// cache add test + #[cfg_attr( + async_executor_impl = "tokio", + tokio::test(flavor = "multi_thread", worker_threads = 2) + )] + #[cfg_attr(async_executor_impl = "async-std", async_std::test)] + #[instrument] + async fn test_dht_cache_save_load() { + let _ = std::fs::remove_file("test.cache"); + + let cache = Cache::new(Config { + filename: Some("test.cache".to_string()), + expiry: Duration::from_secs(600), + max_disk_parity_delta: 4, + }) + .await; + + // add 10 key-value pairs to the cache + for i in 0u8..10u8 { + let (key, value) = (vec![i; 1], vec![i + 1; 1]); + cache.insert(key, value).await; + } + + // save the cache + cache.save().await.unwrap(); + + // load the cache + let cache = Cache::new(Config { + filename: Some("test.cache".to_string()), + expiry: Duration::from_secs(600), + max_disk_parity_delta: 4, + }) + .await; + + // check that the cache has the 10 key-value pairs + for i in 0u8..10u8 { + let (key, value) = (vec![i; 1], vec![i + 1; 1]); + assert_eq!(cache.get(&key).await.unwrap().value(), &value); + } + + // delete the cache file + let _ = std::fs::remove_file("test.cache"); + } + + #[cfg_attr( + async_executor_impl = "tokio", + tokio::test(flavor = "multi_thread", worker_threads = 2) + )] + #[cfg_attr(async_executor_impl = "async-std", async_std::test)] + #[instrument] + async fn test_dht_disk_parity() { + let _ = std::fs::remove_file("test.cache"); + + let cache = Cache::new(Config { + // tests run sequentially, shouldn't matter + filename: Some("test.cache".to_string()), + expiry: Duration::from_secs(600), + max_disk_parity_delta: 4, + }) + .await; + + // insert into cache + for i in 0..3 { + cache.insert(vec![i; 1], vec![i + 1; 1]).await; + } + + // check that file is not saved + assert!(!std::path::Path::new("test.cache").exists()); + + // insert into cache + cache.insert(vec![0; 1], vec![1; 1]).await; + + // check that file is saved + assert!(std::path::Path::new("test.cache").exists()); + + // delete the cache file + _ = std::fs::remove_file("test.cache"); + } +} diff --git a/crates/libp2p-networking/src/network/behaviours/dht.rs b/crates/libp2p-networking/src/network/behaviours/dht/mod.rs similarity index 94% rename from crates/libp2p-networking/src/network/behaviours/dht.rs rename to crates/libp2p-networking/src/network/behaviours/dht/mod.rs index 46adb05d0c..7086b6dab1 100644 --- a/crates/libp2p-networking/src/network/behaviours/dht.rs +++ b/crates/libp2p-networking/src/network/behaviours/dht/mod.rs @@ -5,6 +5,9 @@ use std::{ time::Duration, }; +mod cache; + +use async_compatibility_layer::art::async_block_on; use futures::channel::oneshot::Sender; use libp2p::{ kad::{ @@ -21,6 +24,8 @@ use tracing::{error, info, warn}; pub(crate) const NUM_REPLICATED_TO_TRUST: usize = 2; const MAX_DHT_QUERY_SIZE: usize = 5; +use self::cache::Cache; + use super::exponential_backoff::ExponentialBackoff; /// Behaviour wrapping libp2p's kademlia @@ -56,6 +61,8 @@ pub struct DHTBehaviour { pub peer_id: PeerId, /// replication factor pub replication_factor: NonZeroUsize, + /// kademlia cache + cache: Cache, } /// State of bootstrapping @@ -106,10 +113,11 @@ impl DHTBehaviour { /// Create a new DHT behaviour #[must_use] - pub fn new( + pub async fn new( mut kadem: Kademlia, pid: PeerId, replication_factor: NonZeroUsize, + cache_location: Option, ) -> Self { // needed because otherwise we stay in client mode when testing locally // and don't publish keys stuff @@ -138,6 +146,13 @@ impl DHTBehaviour { }, in_progress_get_closest_peers: HashMap::default(), replication_factor, + cache: Cache::new( + cache::ConfigBuilder::default() + .filename(cache_location) + .build() + .unwrap_or_default(), + ) + .await, } } @@ -223,17 +238,26 @@ impl DHTBehaviour { return; } - let qid = self.kadem.get_record(key.clone().into()); - let query = KadGetQuery { - backoff, - progress: DHTProgress::InProgress(qid), - notify: chan, - num_replicas: factor, - key, - retry_count: retry_count - 1, - records: HashMap::default(), - }; - self.in_progress_get_record_queries.insert(qid, query); + // check cache before making the request + if let Some(entry) = async_block_on(self.cache.get(&key)) { + // exists in cache + if chan.send(entry.value().clone()).is_err() { + warn!("Get DHT: channel closed before get record request result could be sent"); + } + } else { + // doesn't exist in cache, actually propagate request + let qid = self.kadem.get_record(key.clone().into()); + let query = KadGetQuery { + backoff, + progress: DHTProgress::InProgress(qid), + notify: chan, + num_replicas: factor, + key, + retry_count: retry_count - 1, + records: HashMap::default(), + }; + self.in_progress_get_record_queries.insert(qid, query); + } } /// update state based on recv-ed get query @@ -279,6 +303,10 @@ impl DHTBehaviour { .into_iter() .find(|(_, v)| *v >= NUM_REPLICATED_TO_TRUST) { + // insert into cache + async_block_on(self.cache.insert(key, r.clone())); + + // return value if notify.send(r).is_err() { warn!("Get DHT: channel closed before get record request result could be sent"); } diff --git a/crates/libp2p-networking/src/network/behaviours/gossip.rs b/crates/libp2p-networking/src/network/behaviours/gossip.rs index 1119ad27f3..bfc946c9b5 100644 --- a/crates/libp2p-networking/src/network/behaviours/gossip.rs +++ b/crates/libp2p-networking/src/network/behaviours/gossip.rs @@ -4,13 +4,13 @@ use std::{ }; use libp2p::{ - gossipsub::{Behaviour, Event, IdentTopic, TopicHash}, + gossipsub::{Behaviour, Event, IdentTopic, PublishError::Duplicate, TopicHash}, swarm::{NetworkBehaviour, PollParameters, THandlerInEvent, THandlerOutEvent, ToSwarm}, Multiaddr, }; use libp2p_identity::PeerId; -use tracing::{error, info, warn}; +use tracing::{debug, error, info, warn}; use super::exponential_backoff::ExponentialBackoff; @@ -214,8 +214,12 @@ impl GossipBehaviour { /// Publish a given gossip pub fn publish_gossip(&mut self, topic: IdentTopic, contents: Vec) { let res = self.gossipsub.publish(topic.clone(), contents.clone()); - if res.is_err() { - error!("error publishing gossip message {:?}", res); + if let Err(e) = res { + if matches!(e, Duplicate) { + debug!("duplicate gossip message"); + } else { + error!("error publishing gossip message {:?}", e); + } self.in_progress_gossip.push_back((topic, contents)); } } diff --git a/crates/libp2p-networking/src/network/node.rs b/crates/libp2p-networking/src/network/node.rs index 37c9683428..835058bf84 100644 --- a/crates/libp2p-networking/src/network/node.rs +++ b/crates/libp2p-networking/src/network/node.rs @@ -31,6 +31,7 @@ use async_compatibility_layer::{ }; use either::Either; use futures::{select, FutureExt, StreamExt}; +use hotshot_constants::KAD_DEFAULT_REPUB_INTERVAL_SEC; use libp2p::{ core::{muxing::StreamMuxerBox, transport::Boxed}, gossipsub::{ @@ -239,7 +240,7 @@ impl NetworkNode { // 8 hours by default let record_republication_interval = config .republication_interval - .unwrap_or(Duration::from_secs(28800)); + .unwrap_or(Duration::from_secs(KAD_DEFAULT_REPUB_INTERVAL_SEC)); let ttl = Some(config.ttl.unwrap_or(16 * record_republication_interval)); kconfig .set_parallelism(NonZeroUsize::new(1).unwrap()) @@ -268,7 +269,9 @@ impl NetworkNode { config .replication_factor .unwrap_or_else(|| NonZeroUsize::new(4).unwrap()), - ), + config.dht_cache_location.clone(), + ) + .await, identify, DMBehaviour::new(request_response), ); diff --git a/crates/libp2p-networking/src/network/node/config.rs b/crates/libp2p-networking/src/network/node/config.rs index 4d19b6f516..d97097e8e1 100644 --- a/crates/libp2p-networking/src/network/node/config.rs +++ b/crates/libp2p-networking/src/network/node/config.rs @@ -24,6 +24,10 @@ pub struct NetworkNodeConfig { #[builder(setter(into, strip_option), default = "DEFAULT_REPLICATION_FACTOR")] pub replication_factor: Option, + /// location of the dht cache, default is None + #[builder(default = "None")] + pub dht_cache_location: Option, + #[builder(default)] /// parameters for gossipsub mesh network pub mesh_params: Option, diff --git a/crates/libp2p-networking/src/network/node/handle.rs b/crates/libp2p-networking/src/network/node/handle.rs index 3a7236c353..c4e6460666 100644 --- a/crates/libp2p-networking/src/network/node/handle.rs +++ b/crates/libp2p-networking/src/network/node/handle.rs @@ -112,7 +112,6 @@ impl NetworkNodeHandle { let kill_switch = Mutex::new(Some(kill_switch)); let recv_kill = Mutex::new(Some(recv_kill)); - Ok(NetworkNodeHandle { network_config: config, state: std::sync::Arc::default(), @@ -283,6 +282,23 @@ impl NetworkNodeHandle { r.await.map_err(|_| NetworkNodeHandleError::RecvError) } + /// Looks up a node's `PeerId` and attempts to validate routing + /// # Errors + /// if the peer was unable to be looked up (did not provide a response, DNE) + pub async fn lookup_node Deserialize<'a> + Serialize>( + &self, + key: V, + dht_timeout: Duration, + ) -> Result { + // get record (from DHT) + let pid = self.get_record_timeout::(&key, dht_timeout).await?; + + // pid lookup for routing + self.lookup_pid(pid).await?; + + Ok(pid) + } + /// Insert a record into the kademlia DHT /// # Errors /// - Will return [`NetworkNodeHandleError::DHTError`] when encountering an error putting to DHT diff --git a/crates/libp2p-networking/tests/counter.rs b/crates/libp2p-networking/tests/counter.rs index ae3277b29f..eefbdcf37b 100644 --- a/crates/libp2p-networking/tests/counter.rs +++ b/crates/libp2p-networking/tests/counter.rs @@ -12,7 +12,7 @@ use libp2p_networking::network::{ use serde::{Deserialize, Serialize}; use snafu::ResultExt; use std::{fmt::Debug, sync::Arc, time::Duration}; -use tracing::{error, info, instrument, warn}; +use tracing::{debug, error, info, instrument, warn}; #[cfg(async_executor_impl = "async-std")] use async_std::prelude::StreamExt; @@ -304,7 +304,7 @@ async fn run_dht_rounds( ) { let mut rng = rand::thread_rng(); for i in 0..num_rounds { - error!("round: {:?}", i); + debug!("begin round {}", i); let msg_handle = get_random_handle(handles, &mut rng); let mut key = vec![0; DHT_KV_PADDING]; key.push((starting_val + i) as u8); diff --git a/crates/orchestrator/Cargo.toml b/crates/orchestrator/Cargo.toml index 3febbbce65..4a1cfad69c 100644 --- a/crates/orchestrator/Cargo.toml +++ b/crates/orchestrator/Cargo.toml @@ -16,14 +16,14 @@ blake3 = { workspace = true, features = ["traits-preview"] } hotshot-types = { version = "0.1.0", path = "../types", default-features = false } hotshot-utils = { path = "../utils" } libp2p-networking = { workspace = true } -nll = { workspace = true } tide-disco = { git = "https://github.com/EspressoSystems/tide-disco.git", tag = "v0.4.1" } surf-disco = { workspace = true } tracing = { workspace = true } serde = { workspace = true } serde_json = "1.0.96" snafu = { workspace = true } -toml = "0.5.9" # TODO GG upgrade to toml = { workspace = true } +# TODO upgrade to toml = { workspace = true } https://github.com/EspressoSystems/HotShot/issues/1698 +toml = "0.5.9" [target.'cfg(all(async_executor_impl = "tokio"))'.dependencies] tokio = { workspace = true } diff --git a/crates/orchestrator/default-libp2p-run-config.toml b/crates/orchestrator/default-libp2p-run-config.toml index 5d43c940fa..a353ed06f5 100644 --- a/crates/orchestrator/default-libp2p-run-config.toml +++ b/crates/orchestrator/default-libp2p-run-config.toml @@ -1,5 +1,5 @@ -rounds = 100 -transactions_per_round = 10 +rounds = 10 +transactions_per_round = 12 node_index = 0 seed = [ 0, @@ -39,7 +39,6 @@ padding = 10 start_delay_seconds = 60 [libp2p_config] -num_bootstrap_nodes = 5 index_ports = true bootstrap_mesh_n_high = 4 bootstrap_mesh_n_low = 4 @@ -49,18 +48,15 @@ mesh_n_high = 4 mesh_n_low = 4 mesh_outbound_min = 2 mesh_n = 4 -next_view_timeout = 10 -propose_min_round_time = 0 -propose_max_round_time = 10 online_time = 10 -num_txn_per_round = 10 base_port = 9000 [config] -total_nodes = 5 +total_nodes = 10 +committee_nodes = 5 max_transactions = 100 min_transactions = 0 -next_view_timeout = 10000 +next_view_timeout = 30000 timeout_ratio = [ 11, 10, @@ -73,6 +69,8 @@ num_bootstrap = 5 secs = 0 nanos = 0 +# TODO (Keyao) Clean up configuration parameters. +# [config.propose_max_round_time] -secs = 1 +secs = 2 nanos = 0 diff --git a/crates/orchestrator/default-run-config.toml b/crates/orchestrator/default-run-config.toml index fe34d75811..ee8333f80a 100644 --- a/crates/orchestrator/default-run-config.toml +++ b/crates/orchestrator/default-run-config.toml @@ -55,8 +55,10 @@ num_bootstrap = 4 secs = 0 nanos = 0 +# TODO (Keyao) Clean up configuration parameters. +# [config.propose_max_round_time] -secs = 1 +secs = 2 nanos = 0 [web_server_config] diff --git a/crates/orchestrator/default-web-server-run-config.toml b/crates/orchestrator/default-web-server-run-config.toml index 0ea0f86ccf..c5d0bd0253 100644 --- a/crates/orchestrator/default-web-server-run-config.toml +++ b/crates/orchestrator/default-web-server-run-config.toml @@ -56,8 +56,10 @@ num_bootstrap = 4 secs = 0 nanos = 0 +# TODO (Keyao) Clean up configuration parameters. +# [config.propose_max_round_time] -secs = 1 +secs = 2 nanos = 0 [web_server_config] diff --git a/crates/orchestrator/src/config.rs b/crates/orchestrator/src/config.rs index 061ab256d5..f61911d944 100644 --- a/crates/orchestrator/src/config.rs +++ b/crates/orchestrator/src/config.rs @@ -1,4 +1,5 @@ use hotshot_types::{ExecutionType, HotShotConfig}; +use std::marker::PhantomData; use std::{ net::{IpAddr, Ipv4Addr, SocketAddr}, num::NonZeroUsize, @@ -7,7 +8,7 @@ use std::{ #[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] pub struct Libp2pConfig { pub bootstrap_nodes: Vec<(SocketAddr, Vec)>, - pub num_bootstrap_nodes: u64, + pub num_bootstrap_nodes: usize, pub public_ip: IpAddr, pub base_port: u16, pub node_index: u64, @@ -21,15 +22,14 @@ pub struct Libp2pConfig { pub mesh_outbound_min: usize, pub mesh_n: usize, pub next_view_timeout: u64, - pub propose_min_round_time: u64, - pub propose_max_round_time: u64, + pub propose_min_round_time: Duration, + pub propose_max_round_time: Duration, pub online_time: u64, - pub num_txn_per_round: u64, + pub num_txn_per_round: usize, } #[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] pub struct Libp2pConfigFile { - pub num_bootstrap_nodes: u64, pub index_ports: bool, pub bootstrap_mesh_n_high: usize, pub bootstrap_mesh_n_low: usize, @@ -39,11 +39,7 @@ pub struct Libp2pConfigFile { pub mesh_n_low: usize, pub mesh_outbound_min: usize, pub mesh_n: usize, - pub next_view_timeout: u64, - pub propose_min_round_time: u64, - pub propose_max_round_time: u64, pub online_time: u64, - pub num_txn_per_round: u64, pub base_port: u16, } @@ -58,6 +54,10 @@ pub struct WebServerConfig { pub struct NetworkConfig { pub rounds: usize, pub transactions_per_round: usize, + pub num_bootrap: usize, + pub next_view_timeout: u64, + pub propose_min_round_time: Duration, + pub propose_max_round_time: Duration, pub node_index: u64, pub seed: [u8; 32], pub padding: usize, @@ -65,9 +65,10 @@ pub struct NetworkConfig { pub key_type_name: String, pub election_config_type_name: String, pub libp2p_config: Option, - pub config: HotShotConfig, + pub config: HotShotConfig, pub web_server_config: Option, pub da_web_server_config: Option, + _key_type_phantom: PhantomData, } impl Default for NetworkConfig { @@ -85,6 +86,11 @@ impl Default for NetworkConfig { election_config_type_name: std::any::type_name::().to_string(), web_server_config: None, da_web_server_config: None, + _key_type_phantom: PhantomData, + next_view_timeout: 10, + num_bootrap: 5, + propose_min_round_time: Duration::from_secs(0), + propose_max_round_time: Duration::from_secs(10), } } } @@ -123,10 +129,14 @@ impl From for NetworkConfig { rounds: val.rounds, transactions_per_round: val.transactions_per_round, node_index: 0, + num_bootrap: val.config.num_bootstrap, + next_view_timeout: val.config.next_view_timeout, + propose_max_round_time: val.config.propose_max_round_time, + propose_min_round_time: val.config.propose_min_round_time, seed: val.seed, padding: val.padding, libp2p_config: val.libp2p_config.map(|libp2p_config| Libp2pConfig { - num_bootstrap_nodes: libp2p_config.num_bootstrap_nodes, + num_bootstrap_nodes: val.config.num_bootstrap, index_ports: libp2p_config.index_ports, bootstrap_nodes: Vec::new(), public_ip: IpAddr::V4(Ipv4Addr::UNSPECIFIED), @@ -140,11 +150,11 @@ impl From for NetworkConfig { mesh_n_low: libp2p_config.mesh_n_low, mesh_outbound_min: libp2p_config.mesh_outbound_min, mesh_n: libp2p_config.mesh_n, - next_view_timeout: libp2p_config.next_view_timeout, - propose_min_round_time: libp2p_config.propose_min_round_time, - propose_max_round_time: libp2p_config.propose_max_round_time, + next_view_timeout: val.config.next_view_timeout, + propose_min_round_time: val.config.propose_min_round_time, + propose_max_round_time: val.config.propose_max_round_time, online_time: libp2p_config.online_time, - num_txn_per_round: libp2p_config.num_txn_per_round, + num_txn_per_round: val.transactions_per_round, }), config: val.config.into(), key_type_name: std::any::type_name::().to_string(), @@ -152,6 +162,7 @@ impl From for NetworkConfig { start_delay_seconds: val.start_delay_seconds, web_server_config: val.web_server_config, da_web_server_config: val.da_web_server_config, + _key_type_phantom: PhantomData, } } } @@ -183,14 +194,13 @@ pub struct HotShotConfigFile { pub propose_max_round_time: Duration, } -impl From for HotShotConfig { +impl From for HotShotConfig { fn from(val: HotShotConfigFile) -> Self { HotShotConfig { execution_type: ExecutionType::Continuous, total_nodes: val.total_nodes, max_transactions: val.max_transactions, min_transactions: val.min_transactions, - known_nodes: Vec::new(), known_nodes_with_stake: Vec::new(), da_committee_size: val.committee_nodes, next_view_timeout: val.next_view_timeout, @@ -220,7 +230,7 @@ fn default_config() -> HotShotConfigFile { total_nodes: NonZeroUsize::new(10).unwrap(), committee_nodes: 5, max_transactions: NonZeroUsize::new(100).unwrap(), - min_transactions: 0, + min_transactions: 1, next_view_timeout: 10000, timeout_ratio: (11, 10), round_start_delay: 1, diff --git a/crates/orchestrator/src/lib.rs b/crates/orchestrator/src/lib.rs index 4391fc43e6..d3faa7d410 100644 --- a/crates/orchestrator/src/lib.rs +++ b/crates/orchestrator/src/lib.rs @@ -26,7 +26,6 @@ use libp2p::identity::{ Keypair, }; -/// yeesh maybe we should just implement SignatureKey for this... pub fn libp2p_generate_indexed_identity(seed: [u8; 32], index: u64) -> Keypair { let mut hasher = blake3::Hasher::new(); hasher.update(&seed); @@ -117,9 +116,7 @@ where if self.config.libp2p_config.clone().is_some() { let libp2p_config_clone = self.config.libp2p_config.clone().unwrap(); // Designate node as bootstrap node and store its identity information - if libp2p_config_clone.bootstrap_nodes.len() - < libp2p_config_clone.num_bootstrap_nodes.try_into().unwrap() - { + if libp2p_config_clone.bootstrap_nodes.len() < libp2p_config_clone.num_bootstrap_nodes { let port_index = match libp2p_config_clone.index_ports { true => node_index, false => 0, @@ -146,9 +143,7 @@ where ) -> Result, ServerError> { if self.config.libp2p_config.is_some() { let libp2p_config = self.config.clone().libp2p_config.unwrap(); - if libp2p_config.bootstrap_nodes.len() - < libp2p_config.num_bootstrap_nodes.try_into().unwrap() - { + if libp2p_config.bootstrap_nodes.len() < libp2p_config.num_bootstrap_nodes { return Err(ServerError { status: tide_disco::StatusCode::BadRequest, message: "Not enough bootstrap nodes have registered".to_string(), @@ -174,7 +169,15 @@ where fn post_ready(&mut self) -> Result<(), ServerError> { self.nodes_connected += 1; println!("Nodes connected: {}", self.nodes_connected); - if self.nodes_connected >= self.config.config.known_nodes.len().try_into().unwrap() { + if self.nodes_connected + >= self + .config + .config + .known_nodes_with_stake + .len() + .try_into() + .unwrap() + { self.start = true; } Ok(()) diff --git a/crates/task-impls/Cargo.toml b/crates/task-impls/Cargo.toml index 71b7e467d8..08c900b53b 100644 --- a/crates/task-impls/Cargo.toml +++ b/crates/task-impls/Cargo.toml @@ -10,14 +10,13 @@ async-compatibility-layer = { workspace = true } async-trait = { workspace = true } either = { workspace = true } futures = { workspace = true } -nll = { workspace = true } serde = { workspace = true } snafu = { workspace = true } async-lock = { workspace = true } tracing = { workspace = true } atomic_enum = "0.2.0" pin-project = "1.1.3" -async-stream = "0.3.5" +hotshot-constants = { path = "../constants", default-features = false } hotshot-types = { path = "../types", default-features = false } hotshot-task = { path = "../task", default-features = false } time = { workspace = true } diff --git a/crates/task-impls/src/consensus.rs b/crates/task-impls/src/consensus.rs index 12d7313075..11a98de85c 100644 --- a/crates/task-impls/src/consensus.rs +++ b/crates/task-impls/src/consensus.rs @@ -1,23 +1,21 @@ use crate::events::SequencingHotShotEvent; -use async_compatibility_layer::{ - art::{async_sleep, async_spawn}, - async_primitives::subscribable_rwlock::ReadView, -}; +use async_compatibility_layer::art::{async_sleep, async_spawn}; use async_lock::{RwLock, RwLockUpgradableReadGuard}; #[cfg(async_executor_impl = "async-std")] use async_std::task::JoinHandle; -use bincode::Options; use bitvec::prelude::*; -use commit::Committable; +use commit::{Commitment, Committable}; use core::time::Duration; use either::{Either, Left, Right}; use futures::FutureExt; +use hotshot_constants::LOOK_AHEAD; use hotshot_task::{ event_stream::{ChannelStream, EventStream}, global_registry::GlobalRegistry, task::{FilterEvent, HandleEvent, HotShotTaskCompleted, HotShotTaskTypes, TS}, task_impls::{HSTWithEvent, TaskBuilder}, }; +use hotshot_types::vote::QuorumVoteAccumulator; use hotshot_types::{ certificate::{DACertificate, QuorumCertificate}, consensus::{Consensus, View}, @@ -31,12 +29,12 @@ use hotshot_types::{ node_implementation::{CommitteeEx, NodeImplementation, NodeType, SequencingQuorumEx}, signature_key::SignatureKey, state::ConsensusTime, - Block, + BlockPayload, }, utils::{Terminator, ViewInner}, - vote::{QuorumVote, VoteAccumulator, VoteType}, + vote::{QuorumVote, VoteType}, }; -use hotshot_utils::bincode::bincode_opts; + use snafu::Snafu; use std::{ collections::{HashMap, HashSet}, @@ -66,14 +64,14 @@ pub struct SequencingConsensusTaskState< TYPES, Message, Proposal = QuorumProposal>, - Certificate = QuorumCertificate>, - Commitment = SequencingLeaf, + Certificate = QuorumCertificate>>, + Commitment = Commitment>, >, CommitteeEx: ConsensusExchange< TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { /// The global task registry @@ -128,7 +126,7 @@ pub struct SequencingConsensusTaskState< pub id: u64, /// The most Recent QC we've formed from votes, if we've formed it. - pub qc: Option>, + pub qc: Option>>, } /// State for the vote collection task. This handles the building of a QC from a votes received @@ -140,16 +138,23 @@ pub struct VoteCollectionTaskState< TYPES, Message, Proposal = QuorumProposal>, - Certificate = QuorumCertificate>, - Commitment = SequencingLeaf, + Certificate = QuorumCertificate>>, + Commitment = Commitment>, >, { /// the quorum exchange pub quorum_exchange: Arc>, #[allow(clippy::type_complexity)] /// Accumulator for votes - pub accumulator: - Either, QuorumCertificate>, + pub accumulator: Either< + >> as SignedCertificate< + TYPES, + TYPES::Time, + TYPES::VoteTokenType, + Commitment>, + >>::VoteAccumulator, + QuorumCertificate>>, + >, /// View which this vote collection task is collecting votes in pub cur_view: TYPES::Time, /// The event stream shared by all tasks @@ -165,8 +170,8 @@ where TYPES, Message, Proposal = QuorumProposal>, - Certificate = QuorumCertificate>, - Commitment = SequencingLeaf, + Certificate = QuorumCertificate>>, + Commitment = Commitment>, >, { } @@ -185,37 +190,32 @@ where TYPES, Message, Proposal = QuorumProposal>, - Certificate = QuorumCertificate>, - Commitment = SequencingLeaf, + Certificate = QuorumCertificate>>, + Commitment = Commitment>, >, { - // TODO ED Emit a view change event upon new proposal? match event { - SequencingHotShotEvent::QuorumVoteRecv(vote) => match vote { - QuorumVote::Yes(vote) => { + SequencingHotShotEvent::QuorumVoteRecv(vote) => match vote.clone() { + QuorumVote::Yes(vote_internal) => { // For the case where we receive votes after we've made a certificate if state.accumulator.is_right() { return (None, state); } - if vote.current_view != state.cur_view { + if vote_internal.current_view != state.cur_view { error!( "Vote view does not match! vote view is {} current view is {}", - *vote.current_view, *state.cur_view + *vote_internal.current_view, *state.cur_view ); return (None, state); } let accumulator = state.accumulator.left().unwrap(); - match state.quorum_exchange.accumulate_vote( - &vote.signature.0, - &vote.signature.1, - vote.leaf_commitment, - vote.vote_data, - vote.vote_token.clone(), - state.cur_view, + + match state.quorum_exchange.accumulate_vote_2( accumulator, - None, + &vote, + &vote_internal.leaf_commitment, ) { Either::Left(acc) => { state.accumulator = Either::Left(acc); @@ -272,14 +272,14 @@ where TYPES, Message, Proposal = QuorumProposal>, - Certificate = QuorumCertificate>, - Commitment = SequencingLeaf, + Certificate = QuorumCertificate>>, + Commitment = Commitment>, >, CommitteeEx: ConsensusExchange< TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { #[instrument(skip_all, fields(id = self.id, view = *self.cur_view), name = "Consensus genesis leaf", level = "error")] @@ -367,10 +367,7 @@ where ); if let GeneralConsensusMessage::Vote(vote) = message { - debug!( - "Sending vote to next quorum leader {:?}", - vote.current_view() - ); + debug!("Sending vote to next quorum leader {:?}", vote.get_view()); self.event_stream .publish(SequencingHotShotEvent::QuorumVoteSend(vote)) .await; @@ -449,12 +446,8 @@ where }; - // TODO ED Only publish event in vote if able if let GeneralConsensusMessage::Vote(vote) = message { - debug!( - "Sending vote to next quorum leader {:?}", - vote.current_view() - ); + debug!("Sending vote to next quorum leader {:?}", vote.get_view()); self.event_stream .publish(SequencingHotShotEvent::QuorumVoteSend(vote)) .await; @@ -495,6 +488,25 @@ where self.cur_view = new_view; self.current_proposal = None; + if new_view == TYPES::Time::new(1) { + self.quorum_exchange + .network() + .inject_consensus_info(ConsensusIntentEvent::PollForCurrentProposal) + .await; + } + + // Poll the future leader for lookahead + let lookahead_view = new_view + LOOK_AHEAD; + if !self.quorum_exchange.is_leader(lookahead_view) { + self.quorum_exchange + .network() + .inject_consensus_info(ConsensusIntentEvent::PollFutureLeader( + *lookahead_view, + self.quorum_exchange.get_leader(lookahead_view), + )) + .await; + } + // Start polling for proposals for the new view self.quorum_exchange .network() @@ -550,7 +562,7 @@ where let view = proposal.data.get_view_number(); if view < self.cur_view { - error!("view too high {:?}", proposal.data.clone()); + debug!("Proposal is from an older view {:?}", proposal.data.clone()); return; } @@ -855,46 +867,10 @@ where } #[allow(clippy::cast_precision_loss)] if new_decide_reached { - let mut included_txn_size = 0; - let mut included_txn_count = 0; - let txns = consensus.transactions.cloned().await; - // store transactions in this block we never added to our transactions. - let _ = included_txns_set.iter().map(|hash| { - if !txns.contains_key(hash) { - consensus.seen_transactions.insert(*hash); - } - }); - drop(txns); - consensus - .transactions - .modify(|txns| { - *txns = txns - .drain() - .filter(|(txn_hash, txn)| { - if included_txns_set.contains(txn_hash) { - included_txn_count += 1; - included_txn_size += bincode_opts() - .serialized_size(txn) - .unwrap_or_default(); - false - } else { - true - } - }) - .collect(); - }) - .await; - - consensus - .metrics - .outstanding_transactions - .update(-included_txn_count); - consensus - .metrics - .outstanding_transactions_memory_size - .update(-(i64::try_from(included_txn_size).unwrap_or(i64::MAX))); - debug!("about to publish decide"); + self.event_stream + .publish(SequencingHotShotEvent::LeafDecided(leaf_views.clone())) + .await; let decide_sent = self.output_event_stream.publish(Event { view_number: consensus.last_decided_view, event: EventType::Decide { @@ -955,26 +931,26 @@ where } } SequencingHotShotEvent::QuorumVoteRecv(vote) => { - debug!("Received quroum vote: {:?}", vote.current_view()); + debug!("Received quroum vote: {:?}", vote.get_view()); - if !self.quorum_exchange.is_leader(vote.current_view() + 1) { + if !self.quorum_exchange.is_leader(vote.get_view() + 1) { error!( "We are not the leader for view {} are we the leader for view + 1? {}", - *vote.current_view() + 1, - self.quorum_exchange.is_leader(vote.current_view() + 2) + *vote.get_view() + 1, + self.quorum_exchange.is_leader(vote.get_view() + 2) ); return; } - match vote { - QuorumVote::Yes(vote) => { + match vote.clone() { + QuorumVote::Yes(vote_internal) => { let handle_event = HandleEvent(Arc::new(move |event, state| { async move { vote_handle(state, event).await }.boxed() })); let collection_view = if let Some((collection_view, collection_task, _)) = &self.vote_collector { - if vote.current_view > *collection_view { + if vote_internal.current_view > *collection_view { // ED I think we'd want to let that task timeout to avoid a griefing vector self.registry.shutdown_task(*collection_task).await; } @@ -983,37 +959,31 @@ where TYPES::Time::new(0) }; - let acc = VoteAccumulator { + // Todo check if we are the leader + let new_accumulator = QuorumVoteAccumulator { total_vote_outcomes: HashMap::new(), - da_vote_outcomes: HashMap::new(), yes_vote_outcomes: HashMap::new(), no_vote_outcomes: HashMap::new(), - viewsync_precommit_vote_outcomes: HashMap::new(), - viewsync_commit_vote_outcomes: HashMap::new(), - viewsync_finalize_vote_outcomes: HashMap::new(), + success_threshold: self.quorum_exchange.success_threshold(), failure_threshold: self.quorum_exchange.failure_threshold(), + sig_lists: Vec::new(), signers: bitvec![0; self.quorum_exchange.total_nodes()], + phantom: PhantomData, }; - // Todo check if we are the leader - let accumulator = self.quorum_exchange.accumulate_vote( - &vote.clone().signature.0, - &vote.clone().signature.1, - vote.clone().leaf_commitment, - vote.clone().vote_data.clone(), - vote.clone().vote_token.clone(), - vote.clone().current_view, - acc, - None, + let accumulator = self.quorum_exchange.accumulate_vote_2( + new_accumulator, + &vote, + &vote_internal.clone().leaf_commitment, ); - if vote.current_view > collection_view { + if vote_internal.current_view > collection_view { let state = VoteCollectionTaskState { quorum_exchange: self.quorum_exchange.clone(), accumulator, - cur_view: vote.current_view, + cur_view: vote_internal.current_view, event_stream: self.event_stream.clone(), id: self.id, }; @@ -1033,17 +1003,22 @@ where let id = builder.get_task_id().unwrap(); let stream_id = builder.get_stream_id().unwrap(); - self.vote_collector = Some((vote.current_view, id, stream_id)); + self.vote_collector = Some((vote_internal.current_view, id, stream_id)); let _task = async_spawn(async move { VoteCollectionTypes::build(builder).launch().await; }); - debug!("Starting vote handle for view {:?}", vote.current_view); + debug!( + "Starting vote handle for view {:?}", + vote_internal.current_view + ); } else if let Some((_, _, stream_id)) = self.vote_collector { self.event_stream .direct_message( stream_id, - SequencingHotShotEvent::QuorumVoteRecv(QuorumVote::Yes(vote)), + SequencingHotShotEvent::QuorumVoteRecv(QuorumVote::Yes( + vote_internal, + )), ) .await; } @@ -1102,7 +1077,17 @@ where self.update_view(view + 1).await; } } + SequencingHotShotEvent::VidCertRecv(cert) => { + debug!("VID cert received for view ! {}", *cert.view_number); + let view = cert.view_number; + self.certs.insert(view, cert); // TODO new cert type for VID https://github.com/EspressoSystems/HotShot/issues/1701 + + // TODO Make sure we aren't voting for an arbitrarily old round for no reason + if self.vote_if_able().await { + self.update_view(view + 1).await; + } + } SequencingHotShotEvent::ViewChange(new_view) => { debug!("View Change event for view {}", *new_view); @@ -1167,10 +1152,9 @@ where /// Sends a proposal if possible from the high qc we have pub async fn publish_proposal_if_able( &mut self, - _qc: QuorumCertificate, + _qc: QuorumCertificate>, view: TYPES::Time, ) -> bool { - // TODO ED This should not be qc view number + 1 if !self.quorum_exchange.is_leader(view) { error!( "Somehow we formed a QC but are not the leader for the next view {:?}", @@ -1231,11 +1215,9 @@ where // TODO do some sort of sanity check on the view number that it matches decided } + // let block_commitment = Some(self.block.commit()); if let Some(block) = &self.block { let block_commitment = block.commit(); - if block_commitment == TYPES::BlockType::new().commit() { - debug!("Block is generic block! {:?}", self.cur_view); - } let leaf = SequencingLeaf { view_number: view, @@ -1298,14 +1280,14 @@ where TYPES, Message, Proposal = QuorumProposal>, - Certificate = QuorumCertificate>, - Commitment = SequencingLeaf, + Certificate = QuorumCertificate>>, + Commitment = Commitment>, >, CommitteeEx: ConsensusExchange< TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { } @@ -1347,14 +1329,14 @@ where TYPES, Message, Proposal = QuorumProposal>, - Certificate = QuorumCertificate>, - Commitment = SequencingLeaf, + Certificate = QuorumCertificate>>, + Commitment = Commitment>, >, CommitteeEx: ConsensusExchange< TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { if let SequencingHotShotEvent::Shutdown = event { @@ -1375,6 +1357,7 @@ pub fn consensus_event_filter>( | SequencingHotShotEvent::QuorumVoteRecv(_) | SequencingHotShotEvent::QCFormed(_) | SequencingHotShotEvent::DACRecv(_) + | SequencingHotShotEvent::VidCertRecv(_) | SequencingHotShotEvent::ViewChange(_) | SequencingHotShotEvent::SendDABlockData(_) | SequencingHotShotEvent::Timeout(_) diff --git a/crates/task-impls/src/da.rs b/crates/task-impls/src/da.rs index b6244c972a..1100f4e078 100644 --- a/crates/task-impls/src/da.rs +++ b/crates/task-impls/src/da.rs @@ -1,12 +1,9 @@ use crate::events::SequencingHotShotEvent; -use async_compatibility_layer::{ - art::{async_spawn, async_timeout}, - async_primitives::subscribable_rwlock::ReadView, -}; +use async_compatibility_layer::art::async_spawn; use async_lock::RwLock; -use bincode::config::Options; + use bitvec::prelude::*; -use commit::Committable; +use commit::{Commitment, Committable}; use either::{Either, Left, Right}; use futures::FutureExt; use hotshot_task::{ @@ -15,11 +12,14 @@ use hotshot_task::{ task::{FilterEvent, HandleEvent, HotShotTaskCompleted, HotShotTaskTypes, TS}, task_impls::{HSTWithEvent, TaskBuilder}, }; +use hotshot_types::traits::election::SignedCertificate; +use hotshot_types::vote::DAVoteAccumulator; +use hotshot_types::vote::VoteType; use hotshot_types::{ certificate::DACertificate, consensus::{Consensus, View}, data::{DAProposal, ProposalType, SequencingLeaf}, - message::{CommitteeConsensusMessage, Message, Proposal, SequencingMessage}, + message::{Message, Proposal, SequencingMessage}, traits::{ consensus_api::SequencingConsensusApi, election::{CommitteeExchangeType, ConsensusExchange, Membership}, @@ -27,18 +27,14 @@ use hotshot_types::{ node_implementation::{CommitteeEx, NodeImplementation, NodeType}, signature_key::SignatureKey, state::ConsensusTime, - Block, State, + BlockPayload, }, utils::ViewInner, - vote::VoteAccumulator, }; -use hotshot_utils::bincode::bincode_opts; + use snafu::Snafu; -use std::{ - collections::{HashMap, HashSet}, - sync::Arc, - time::Instant, -}; +use std::marker::PhantomData; +use std::{collections::HashMap, sync::Arc}; use tracing::{debug, error, instrument, warn}; #[derive(Snafu, Debug)] @@ -59,7 +55,7 @@ pub struct DATaskState< TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { /// The state's api @@ -70,7 +66,6 @@ pub struct DATaskState< /// View number this view is executing in. pub cur_view: TYPES::Time, - // pub transactions: Arc>>, /// Reference to consensus. Leader will require a read lock on this. pub consensus: Arc>>>, @@ -96,15 +91,22 @@ pub struct DAVoteCollectionTaskState< TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { /// the committee exchange pub committee_exchange: Arc>, - /// the vote accumulator - pub accumulator: - Either, DACertificate>, - // TODO ED Make this just "view" since it is only for this task + #[allow(clippy::type_complexity)] + /// Accumulates DA votes + pub accumulator: Either< + as SignedCertificate< + TYPES, + TYPES::Time, + TYPES::VoteTokenType, + Commitment, + >>::VoteAccumulator, + DACertificate, + >, /// the current view pub cur_view: TYPES::Time, /// event stream for channel events @@ -120,7 +122,7 @@ where TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { } @@ -138,7 +140,7 @@ where TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { match event { @@ -153,21 +155,16 @@ where } let accumulator = state.accumulator.left().unwrap(); - match state.committee_exchange.accumulate_vote( - &vote.signature.0, - &vote.signature.1, - vote.block_commitment, - vote.vote_data, - vote.vote_token.clone(), - state.cur_view, + + match state.committee_exchange.accumulate_vote_2( accumulator, - None, + &vote, + &vote.block_commitment, ) { - Left(acc) => { - state.accumulator = Either::Left(acc); - // debug!("Not enough DA votes! "); - return (None, state); + Left(new_accumulator) => { + state.accumulator = either::Left(new_accumulator); } + Right(dac) => { debug!("Sending DAC! {:?}", dac.view_number); state @@ -192,8 +189,51 @@ where } } } + SequencingHotShotEvent::VidVoteRecv(vote) => { + // TODO copy-pasted from DAVoteRecv https://github.com/EspressoSystems/HotShot/issues/1690 + + debug!("VID vote recv, collection task {:?}", vote.get_view()); + // panic!("Vote handle received DA vote for view {}", *vote.current_view); + + let accumulator = state.accumulator.left().unwrap(); + + match state.committee_exchange.accumulate_vote_2( + accumulator, + &vote, + &vote.block_commitment, + ) { + Left(new_accumulator) => { + state.accumulator = either::Left(new_accumulator); + } + + Right(vid_cert) => { + debug!("Sending VID cert! {:?}", vid_cert.view_number); + state + .event_stream + .publish(SequencingHotShotEvent::VidCertSend( + vid_cert.clone(), + state.committee_exchange.public_key().clone(), + )) + .await; + + state.accumulator = Right(vid_cert.clone()); + state + .committee_exchange + .network() + .inject_consensus_info(ConsensusIntentEvent::CancelPollForVotes( + *vid_cert.view_number, + )) + .await; + + // Return completed at this point + return (Some(HotShotTaskCompleted::ShutDown), state); + } + } + } SequencingHotShotEvent::Shutdown => return (Some(HotShotTaskCompleted::ShutDown), state), - _ => {} + _ => { + error!("unexpected event {:?}", event); + } } (None, state) } @@ -212,46 +252,16 @@ where TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { /// main task event handler #[instrument(skip_all, fields(id = self.id, view = *self.cur_view), name = "DA Main Task", level = "error")] - pub async fn handle_event( &mut self, event: SequencingHotShotEvent, ) -> Option { match event { - SequencingHotShotEvent::TransactionsRecv(transactions) => { - // TODO ED Add validation checks - - let mut consensus = self.consensus.write().await; - consensus - .get_transactions() - .modify(|txns| { - for transaction in transactions { - let size = bincode_opts().serialized_size(&transaction).unwrap_or(0); - - // If we didn't already know about this transaction, update our mempool metrics. - if !consensus.seen_transactions.remove(&transaction.commit()) - && txns.insert(transaction.commit(), transaction).is_none() - { - consensus.metrics.outstanding_transactions.update(1); - consensus - .metrics - .outstanding_transactions_memory_size - .update(i64::try_from(size).unwrap_or_else(|e| { - warn!("Conversion failed: {e}. Using the max value."); - i64::MAX - })); - } - } - }) - .await; - - return None; - } SequencingHotShotEvent::DAProposalRecv(proposal, sender) => { debug!( "DA proposal received for view: {:?}", @@ -298,7 +308,7 @@ where } Ok(Some(vote_token)) => { // Generate and send vote - let message = self.committee_exchange.create_da_message( + let vote = self.committee_exchange.create_da_message( block_commitment, view, vote_token, @@ -307,12 +317,10 @@ where // ED Don't think this is necessary? // self.cur_view = view; - if let CommitteeConsensusMessage::DAVote(vote) = message { - debug!("Sending vote to the DA leader {:?}", vote.current_view); - self.event_stream - .publish(SequencingHotShotEvent::DAVoteSend(vote)) - .await; - } + debug!("Sending vote to the DA leader {:?}", vote.current_view); + self.event_stream + .publish(SequencingHotShotEvent::DAVoteSend(vote)) + .await; let mut consensus = self.consensus.write().await; // Ensure this view is in the view map for garbage collection, but do not overwrite if @@ -356,32 +364,25 @@ where } else { TYPES::Time::new(0) }; - let acc = VoteAccumulator { - total_vote_outcomes: HashMap::new(), + + let new_accumulator = DAVoteAccumulator { da_vote_outcomes: HashMap::new(), - yes_vote_outcomes: HashMap::new(), - no_vote_outcomes: HashMap::new(), - viewsync_precommit_vote_outcomes: HashMap::new(), - viewsync_commit_vote_outcomes: HashMap::new(), - viewsync_finalize_vote_outcomes: HashMap::new(), success_threshold: self.committee_exchange.success_threshold(), - failure_threshold: self.committee_exchange.failure_threshold(), sig_lists: Vec::new(), signers: bitvec![0; self.committee_exchange.total_nodes()], + phantom: PhantomData, }; - let accumulator = self.committee_exchange.accumulate_vote( - &vote.clone().signature.0, - &vote.clone().signature.1, - vote.clone().block_commitment, - vote.clone().vote_data.clone(), - vote.clone().vote_token.clone(), - vote.clone().current_view, - acc, - None, + + let accumulator = self.committee_exchange.accumulate_vote_2( + new_accumulator, + &vote, + &vote.clone().block_commitment, ); + if view > collection_view { let state = DAVoteCollectionTaskState { committee_exchange: self.committee_exchange.clone(), + accumulator, cur_view: view, event_stream: self.event_stream.clone(), @@ -412,7 +413,163 @@ where .await; }; } - // TODO ED Update high QC through QCFormed event + SequencingHotShotEvent::VidVoteRecv(vote) => { + // TODO copy-pasted from DAVoteRecv https://github.com/EspressoSystems/HotShot/issues/1690 + + // warn!( + // "VID vote recv, Main Task {:?}, key: {:?}", + // vote.current_view, + // self.committee_exchange.public_key() + // ); + // Check if we are the leader and the vote is from the sender. + let view = vote.current_view; + if !self.committee_exchange.is_leader(view) { + error!( + "We are not the VID leader for view {} are we leader for next view? {}", + *view, + self.committee_exchange.is_leader(view + 1) + ); + return None; + } + + let handle_event = HandleEvent(Arc::new(move |event, state| { + async move { vote_handle(state, event).await }.boxed() + })); + let collection_view = + if let Some((collection_view, collection_id, _)) = &self.vote_collector { + // TODO: Is this correct for consecutive leaders? + if view > *collection_view { + // warn!("shutting down for view {:?}", collection_view); + self.registry.shutdown_task(*collection_id).await; + } + *collection_view + } else { + TYPES::Time::new(0) + }; + + let new_accumulator = DAVoteAccumulator { + da_vote_outcomes: HashMap::new(), + success_threshold: self.committee_exchange.success_threshold(), + sig_lists: Vec::new(), + signers: bitvec![0; self.committee_exchange.total_nodes()], + phantom: PhantomData, + }; + + let accumulator = self.committee_exchange.accumulate_vote_2( + new_accumulator, + &vote, + &vote.clone().block_commitment, + ); + + if view > collection_view { + let state = DAVoteCollectionTaskState { + committee_exchange: self.committee_exchange.clone(), + + accumulator, + cur_view: view, + event_stream: self.event_stream.clone(), + id: self.id, + }; + let name = "VID Vote Collection"; + let filter = FilterEvent(Arc::new(|event| { + matches!(event, SequencingHotShotEvent::VidVoteRecv(_)) + })); + let builder = + TaskBuilder::>::new(name.to_string()) + .register_event_stream(self.event_stream.clone(), filter) + .await + .register_registry(&mut self.registry.clone()) + .await + .register_state(state) + .register_event_handler(handle_event); + let id = builder.get_task_id().unwrap(); + let stream_id = builder.get_stream_id().unwrap(); + let _task = + async_spawn( + async move { DAVoteCollectionTypes::build(builder).launch().await }, + ); + self.vote_collector = Some((view, id, stream_id)); + } else if let Some((_, _, stream_id)) = self.vote_collector { + self.event_stream + .direct_message(stream_id, SequencingHotShotEvent::VidVoteRecv(vote)) + .await; + }; + } + SequencingHotShotEvent::VidDisperseRecv(disperse, sender) => { + // TODO copy-pasted from DAProposalRecv https://github.com/EspressoSystems/HotShot/issues/1690 + debug!( + "VID disperse received for view: {:?}", + disperse.data.get_view_number() + ); + + // ED NOTE: Assuming that the next view leader is the one who sends DA proposal for this view + let view = disperse.data.get_view_number(); + + // Allow a DA proposal that is one view older, in case we have voted on a quorum + // proposal and updated the view. + // `self.cur_view` should be at least 1 since there is a view change before getting + // the `DAProposalRecv` event. Otherewise, the view number subtraction below will + // cause an overflow error. + if view < self.cur_view - 1 { + warn!("Throwing away VID disperse data that is more than one view older"); + return None; + } + + debug!("VID disperse data is fresh."); + let block_commitment = disperse.data.commitment; + + // ED Is this the right leader? + let view_leader_key = self.committee_exchange.get_leader(view); + if view_leader_key != sender { + error!("VID proposal doesn't have expected leader key for view {} \n DA proposal is: [N/A for VID]", *view); + return None; + } + + if !view_leader_key.validate(&disperse.signature, block_commitment.as_ref()) { + error!("Could not verify VID proposal sig."); + return None; + } + + let vote_token = self.committee_exchange.make_vote_token(view); + match vote_token { + Err(e) => { + error!("Failed to generate vote token for {:?} {:?}", view, e); + } + Ok(None) => { + debug!("We were not chosen for VID quorum on {:?}", view); + } + Ok(Some(vote_token)) => { + // Generate and send vote + let vote = self.committee_exchange.create_vid_message( + block_commitment, + view, + vote_token, + ); + + // ED Don't think this is necessary? + // self.cur_view = view; + + debug!("Sending vote to the VID leader {:?}", vote.current_view); + self.event_stream + .publish(SequencingHotShotEvent::VidVoteSend(vote)) + .await; + let mut consensus = self.consensus.write().await; + + // Ensure this view is in the view map for garbage collection, but do not overwrite if + // there is already a view there: the replica task may have inserted a `Leaf` view which + // contains strictly more information. + consensus.state_map.entry(view).or_insert(View { + view_inner: ViewInner::DA { + block: block_commitment, + }, + }); + + // Record the block we have promised to make available. + // TODO https://github.com/EspressoSystems/HotShot/issues/1692 + // consensus.saved_blocks.insert(proposal.data.deltas); + } + } + } SequencingHotShotEvent::ViewChange(view) => { if *self.cur_view >= *view { return None; @@ -425,7 +582,6 @@ where // Inject view info into network // ED I think it is possible that you receive a quorum proposal, vote on it and update your view before the da leader has sent their proposal, and therefore you skip polling for this view? - // TODO ED Only poll if you are on the committee let is_da = self .committee_exchange .membership() @@ -451,8 +607,6 @@ where .await; } - // TODO ED Make this a new task so it doesn't block main DA task - // If we are not the next leader (DA leader for this view) immediately exit if !self.committee_exchange.is_leader(self.cur_view + 1) { // panic!("We are not the DA leader for view {}", *self.cur_view + 1); @@ -466,64 +620,19 @@ where .inject_consensus_info(ConsensusIntentEvent::PollForVotes(*self.cur_view + 1)) .await; - // ED Copy of parent_leaf() function from sequencing leader - - let consensus = self.consensus.read().await; - let parent_view_number = &consensus.high_qc.view_number; - - let Some(parent_view) = consensus.state_map.get(parent_view_number) else { - error!( - "Couldn't find high QC parent in state map. Parent view {:?}", - parent_view_number - ); - return None; - }; - let Some(leaf) = parent_view.get_leaf_commitment() else { - error!( - ?parent_view_number, - ?parent_view, - "Parent of high QC points to a view without a proposal" - ); - return None; - }; - let Some(leaf) = consensus.saved_leaves.get(&leaf) else { - error!("Failed to find high QC parent."); - return None; - }; - let parent_leaf = leaf.clone(); - - // Prepare the DA Proposal - // let Some(parent_leaf) = self.parent_leaf().await else { - // warn!("Couldn't find high QC parent in state map."); - // return None; - // }; - - drop(consensus); - - // ED This is taking a really long time to return, since is based on application - // - let mut block = ::StateType::next_block(None); - let txns = self.wait_for_transactions(parent_leaf).await?; - + return None; + } + SequencingHotShotEvent::BlockReady(block, view) => { self.committee_exchange .network() - .inject_consensus_info(ConsensusIntentEvent::CancelPollForTransactions( - *self.cur_view + 1, - )) + .inject_consensus_info(ConsensusIntentEvent::CancelPollForTransactions(*view)) .await; - for txn in txns { - if let Ok(new_block) = block.add_transaction_raw(&txn) { - block = new_block; - continue; - } - } - let signature = self.committee_exchange.sign_da_proposal(&block.commit()); let data: DAProposal = DAProposal { deltas: block.clone(), // Upon entering a new view we want to send a DA Proposal for the next view -> Is it always the case that this is cur_view + 1? - view_number: self.cur_view + 1, + view_number: view, }; debug!("Sending DA proposal for view {:?}", data.view_number); @@ -537,20 +646,13 @@ where self.event_stream .publish(SequencingHotShotEvent::SendDABlockData(block.clone())) .await; - // if let Err(e) = self.api.send_da_broadcast(message.clone()).await { - // consensus.metrics.failed_to_send_messages.add(1); - // warn!(?message, ?e, "Could not broadcast leader proposal"); - // } else { - // consensus.metrics.outgoing_broadcast_messages.add(1); - // } + self.event_stream .publish(SequencingHotShotEvent::DAProposalSend( - message, + message.clone(), self.committee_exchange.public_key().clone(), )) .await; - - return None; } SequencingHotShotEvent::Timeout(view) => { @@ -563,73 +665,11 @@ where SequencingHotShotEvent::Shutdown => { return Some(HotShotTaskCompleted::ShutDown); } - _ => {} - } - None - } - - /// return None if we can't get transactions - #[instrument(skip_all, fields(id = self.id, view = *self.cur_view), name = "DA Vote Collection Task", level = "error")] - - async fn wait_for_transactions( - &self, - parent_leaf: SequencingLeaf, - ) -> Option> { - let task_start_time = Instant::now(); - - // let parent_leaf = self.parent_leaf().await?; - let previous_used_txns = match parent_leaf.deltas { - Either::Left(block) => block.contained_transactions(), - Either::Right(_commitment) => HashSet::new(), - }; - - let consensus = self.consensus.read().await; - - let receiver = consensus.transactions.subscribe().await; - - loop { - let all_txns = consensus.transactions.cloned().await; - debug!("Size of transactions: {}", all_txns.len()); - let unclaimed_txns: Vec<_> = all_txns - .iter() - .filter(|(txn_hash, _txn)| !previous_used_txns.contains(txn_hash)) - .collect(); - - let time_past = task_start_time.elapsed(); - if unclaimed_txns.len() < self.api.min_transactions() - && (time_past < self.api.propose_max_round_time()) - { - let duration = self.api.propose_max_round_time() - time_past; - let result = async_timeout(duration, receiver.recv()).await; - match result { - Err(_) => { - // Fall through below to updating new block - debug!( - "propose_max_round_time passed, sending transactions we have so far" - ); - } - Ok(Err(e)) => { - // Something unprecedented is wrong, and `transactions` has been dropped - error!("Channel receiver error for SubscribableRwLock {:?}", e); - return None; - } - Ok(Ok(_)) => continue, - } + _ => { + error!("unexpected event {:?}", event); } - break; } - let all_txns = consensus.transactions.cloned().await; - let txns: Vec = all_txns - .iter() - .filter_map(|(txn_hash, txn)| { - if previous_used_txns.contains(txn_hash) { - None - } else { - Some(txn.clone()) - } - }) - .collect(); - Some(txns) + None } /// Filter the DA event. @@ -639,8 +679,10 @@ where SequencingHotShotEvent::DAProposalRecv(_, _) | SequencingHotShotEvent::DAVoteRecv(_) | SequencingHotShotEvent::Shutdown - | SequencingHotShotEvent::TransactionsRecv(_) + | SequencingHotShotEvent::BlockReady(_, _) | SequencingHotShotEvent::Timeout(_) + | SequencingHotShotEvent::VidDisperseRecv(_, _) + | SequencingHotShotEvent::VidVoteRecv(_) | SequencingHotShotEvent::ViewChange(_) ) } @@ -661,7 +703,7 @@ where TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { } diff --git a/crates/task-impls/src/events.rs b/crates/task-impls/src/events.rs index 98819108a4..f9fc7f8ba3 100644 --- a/crates/task-impls/src/events.rs +++ b/crates/task-impls/src/events.rs @@ -1,6 +1,8 @@ +use crate::view_sync::ViewSyncPhase; +use commit::Commitment; use hotshot_types::{ certificate::{DACertificate, QuorumCertificate}, - data::DAProposal, + data::{DAProposal, VidDisperse}, message::Proposal, traits::node_implementation::{ NodeImplementation, NodeType, QuorumProposalType, ViewSyncProposalType, @@ -8,8 +10,6 @@ use hotshot_types::{ vote::{DAVote, QuorumVote, ViewSyncVote}, }; -use crate::view_sync::ViewSyncPhase; - /// All of the possible events that can be passed between Sequecning `HotShot` tasks #[derive(Eq, Hash, PartialEq, Debug, Clone)] pub enum SequencingHotShotEvent> { @@ -18,7 +18,7 @@ pub enum SequencingHotShotEvent> { /// A quorum proposal has been received from the network; handled by the consensus task QuorumProposalRecv(Proposal>, TYPES::SignatureKey), /// A quorum vote has been received from the network; handled by the consensus task - QuorumVoteRecv(QuorumVote), + QuorumVoteRecv(QuorumVote>), /// A DA proposal has been received from the network; handled by the DA task DAProposalRecv(Proposal>, TYPES::SignatureKey), /// A DA vote has been received by the network; handled by the DA task @@ -28,13 +28,13 @@ pub enum SequencingHotShotEvent> { /// Send a quorum proposal to the network; emitted by the leader in the consensus task QuorumProposalSend(Proposal>, TYPES::SignatureKey), /// Send a quorum vote to the next leader; emitted by a replica in the consensus task after seeing a valid quorum proposal - QuorumVoteSend(QuorumVote), + QuorumVoteSend(QuorumVote>), /// Send a DA proposal to the DA committee; emitted by the DA leader (which is the same node as the leader of view v + 1) in the DA task DAProposalSend(Proposal>, TYPES::SignatureKey), /// Send a DA vote to the DA leader; emitted by DA committee members in the DA task after seeing a valid DA proposal DAVoteSend(DAVote), /// The next leader has collected enough votes to form a QC; emitted by the next leader in the consensus task; an internal event only - QCFormed(QuorumCertificate), + QCFormed(QuorumCertificate>), /// The DA leader has collected enough votes to form a DAC; emitted by the DA leader in the DA task; sent to the entire network via the networking task DACSend(DACertificate, TYPES::SignatureKey), /// The current view has changed; emitted by the replica in the consensus task or replica in the view sync task; received by almost all other tasks @@ -62,4 +62,32 @@ pub enum SequencingHotShotEvent> { TransactionSend(TYPES::Transaction, TYPES::SignatureKey), /// Event to send DA block data from DA leader to next quorum leader (which should always be the same node); internal event only SendDABlockData(TYPES::BlockType), + /// Event when the transactions task has a block formed + BlockReady(TYPES::BlockType, TYPES::Time), + /// Event when consensus decided on a leaf + LeafDecided(Vec), + /// Send VID shares to VID storage nodes; emitted by the DA leader + /// + /// Like [`DAProposalSend`]. + VidDisperseSend(Proposal>, TYPES::SignatureKey), + /// Vid disperse data has been received from the network; handled by the DA task + /// + /// Like [`DAProposalRecv`]. + VidDisperseRecv(Proposal>, TYPES::SignatureKey), + /// Send a VID vote to the VID leader; emitted by VID storage nodes in the DA task after seeing a valid VID dispersal + /// + /// Like [`DAVoteSend`] + VidVoteSend(DAVote), + /// A VID vote has been received by the network; handled by the DA task + /// + /// Like [`DAVoteRecv`] + VidVoteRecv(DAVote), + /// The VID leader has collected enough votes to form a VID cert; emitted by the VID leader in the DA task; sent to the entire network via the networking task + /// + /// Like [`DACSend`] + VidCertSend(DACertificate, TYPES::SignatureKey), + /// A VID cert has been recieved by the network; handled by the consensus task + /// + /// Like [`DACRecv`] + VidCertRecv(DACertificate), } diff --git a/crates/task-impls/src/lib.rs b/crates/task-impls/src/lib.rs index aca2cafdea..5e7492d84a 100644 --- a/crates/task-impls/src/lib.rs +++ b/crates/task-impls/src/lib.rs @@ -17,6 +17,9 @@ pub mod consensus; /// The task which implements the main parts of data availability. pub mod da; +/// The task which implements all transaction handling +pub mod transactions; + /// Defines the events passed between tasks pub mod events; diff --git a/crates/task-impls/src/network.rs b/crates/task-impls/src/network.rs index a4b083ba37..5fbada8539 100644 --- a/crates/task-impls/src/network.rs +++ b/crates/task-impls/src/network.rs @@ -7,7 +7,7 @@ use hotshot_task::{ GeneratedStream, Merge, }; use hotshot_types::{ - data::{ProposalType, SequencingLeaf}, + data::SequencingLeaf, message::{ CommitteeConsensusMessage, GeneralConsensusMessage, Message, MessageKind, Messages, SequencingMessage, @@ -106,6 +106,15 @@ impl< // panic!("Recevid DA C! "); SequencingHotShotEvent::DACRecv(cert) } + CommitteeConsensusMessage::VidDisperseMsg(proposal) => { + SequencingHotShotEvent::VidDisperseRecv(proposal, sender) + } + CommitteeConsensusMessage::VidVote(vote) => { + SequencingHotShotEvent::VidVoteRecv(vote.clone()) + } + CommitteeConsensusMessage::VidCertificate(cert) => { + SequencingHotShotEvent::VidCertRecv(cert) + } }, }; // TODO (Keyao benchmarking) Update these event variants (similar to the @@ -137,10 +146,8 @@ pub struct NetworkEventTaskState< Leaf = SequencingLeaf, ConsensusMessage = SequencingMessage, >, - PROPOSAL: ProposalType, - VOTE: VoteType, MEMBERSHIP: Membership, - COMMCHANNEL: CommunicationChannel, PROPOSAL, VOTE, MEMBERSHIP>, + COMMCHANNEL: CommunicationChannel, MEMBERSHIP>, > { /// comm channel pub channel: COMMCHANNEL, @@ -149,7 +156,7 @@ pub struct NetworkEventTaskState< /// view number pub view: TYPES::Time, /// phantom data - pub phantom: PhantomData<(PROPOSAL, VOTE, MEMBERSHIP)>, + pub phantom: PhantomData, // TODO ED Need to add exchange so we can get the recipient key and our own key? } @@ -160,11 +167,9 @@ impl< Leaf = SequencingLeaf, ConsensusMessage = SequencingMessage, >, - PROPOSAL: ProposalType, - VOTE: VoteType, MEMBERSHIP: Membership, - COMMCHANNEL: CommunicationChannel, PROPOSAL, VOTE, MEMBERSHIP>, - > TS for NetworkEventTaskState + COMMCHANNEL: CommunicationChannel, MEMBERSHIP>, + > TS for NetworkEventTaskState { } @@ -175,17 +180,16 @@ impl< Leaf = SequencingLeaf, ConsensusMessage = SequencingMessage, >, - PROPOSAL: ProposalType, - VOTE: VoteType, MEMBERSHIP: Membership, - COMMCHANNEL: CommunicationChannel, PROPOSAL, VOTE, MEMBERSHIP>, - > NetworkEventTaskState + COMMCHANNEL: CommunicationChannel, MEMBERSHIP>, + > NetworkEventTaskState { /// Handle the given event. /// /// Returns the completion status. /// # Panics /// Panic sif a direct message event is received with no recipient + #[allow(clippy::too_many_lines)] // TODO https://github.com/EspressoSystems/HotShot/issues/1704 pub async fn handle_event( &mut self, event: SequencingHotShotEvent, @@ -208,9 +212,16 @@ impl< GeneralConsensusMessage::Vote(vote.clone()), ))), TransmitType::Direct, - Some(membership.get_leader(vote.current_view() + 1)), + Some(membership.get_leader(vote.get_view() + 1)), + ), + SequencingHotShotEvent::VidDisperseSend(proposal, sender) => ( + sender, + MessageKind::::from_consensus_message(SequencingMessage(Right( + CommitteeConsensusMessage::VidDisperseMsg(proposal), + ))), // TODO not a CommitteeConsensusMessage https://github.com/EspressoSystems/HotShot/issues/1696 + TransmitType::Broadcast, // TODO not a broadcast https://github.com/EspressoSystems/HotShot/issues/1696 + None, ), - SequencingHotShotEvent::DAProposalSend(proposal, sender) => ( sender, MessageKind::::from_consensus_message(SequencingMessage(Right( @@ -219,6 +230,14 @@ impl< TransmitType::Broadcast, None, ), + SequencingHotShotEvent::VidVoteSend(vote) => ( + vote.signature_key(), + MessageKind::::from_consensus_message(SequencingMessage(Right( + CommitteeConsensusMessage::VidVote(vote.clone()), + ))), + TransmitType::Direct, + Some(membership.get_leader(vote.current_view)), // TODO who is VID leader? https://github.com/EspressoSystems/HotShot/issues/1699 + ), SequencingHotShotEvent::DAVoteSend(vote) => ( vote.signature_key(), MessageKind::::from_consensus_message(SequencingMessage(Right( @@ -227,6 +246,14 @@ impl< TransmitType::Direct, Some(membership.get_leader(vote.current_view)), ), + SequencingHotShotEvent::VidCertSend(certificate, sender) => ( + sender, + MessageKind::::from_consensus_message(SequencingMessage(Right( + CommitteeConsensusMessage::VidCertificate(certificate), + ))), + TransmitType::Broadcast, + None, + ), // ED NOTE: This needs to be broadcasted to all nodes, not just ones on the DA committee SequencingHotShotEvent::DACSend(certificate, sender) => ( sender, @@ -307,6 +334,7 @@ impl< | SequencingHotShotEvent::QuorumVoteSend(_) | SequencingHotShotEvent::Shutdown | SequencingHotShotEvent::DACSend(_, _) + | SequencingHotShotEvent::VidCertSend(_, _) | SequencingHotShotEvent::ViewChange(_) ) } @@ -318,6 +346,8 @@ impl< SequencingHotShotEvent::DAProposalSend(_, _) | SequencingHotShotEvent::DAVoteSend(_) | SequencingHotShotEvent::Shutdown + | SequencingHotShotEvent::VidDisperseSend(_, _) + | SequencingHotShotEvent::VidVoteSend(_) | SequencingHotShotEvent::ViewChange(_) ) } @@ -348,9 +378,9 @@ pub type NetworkMessageTaskTypes = HSTWithMessage< >; /// network event task types -pub type NetworkEventTaskTypes = HSTWithEvent< +pub type NetworkEventTaskTypes = HSTWithEvent< NetworkTaskError, SequencingHotShotEvent, ChannelStream>, - NetworkEventTaskState, + NetworkEventTaskState, >; diff --git a/crates/task-impls/src/transactions.rs b/crates/task-impls/src/transactions.rs new file mode 100644 index 0000000000..c682f5f38d --- /dev/null +++ b/crates/task-impls/src/transactions.rs @@ -0,0 +1,417 @@ +use crate::events::SequencingHotShotEvent; +use async_compatibility_layer::async_primitives::subscribable_rwlock::SubscribableRwLock; +use async_compatibility_layer::{ + art::async_timeout, async_primitives::subscribable_rwlock::ReadView, +}; +use async_lock::RwLock; +use bincode::config::Options; +use commit::{Commitment, Committable}; +use either::{Left, Right}; +use hotshot_task::{ + event_stream::{ChannelStream, EventStream}, + global_registry::GlobalRegistry, + task::{HotShotTaskCompleted, TS}, + task_impls::HSTWithEvent, +}; +use hotshot_types::{ + block_impl::{VIDBlockPayload, VIDTransaction, NUM_CHUNKS, NUM_STORAGE_NODES}, + certificate::DACertificate, + consensus::Consensus, + data::{SequencingLeaf, VidDisperse, VidScheme, VidSchemeTrait}, + message::{Message, Proposal, SequencingMessage}, + traits::{ + consensus_api::SequencingConsensusApi, + election::{CommitteeExchangeType, ConsensusExchange}, + node_implementation::{CommitteeEx, NodeImplementation, NodeType}, + BlockPayload, + }, +}; +use hotshot_utils::bincode::bincode_opts; +use snafu::Snafu; +use std::{ + collections::{HashMap, HashSet}, + sync::Arc, + time::Instant, +}; +use tracing::{debug, error, instrument, warn}; + +/// A type alias for `HashMap, T>` +type CommitmentMap = HashMap, T>; + +#[derive(Snafu, Debug)] +/// Error type for consensus tasks +pub struct ConsensusTaskError {} + +/// Tracks state of a Transaction task +pub struct TransactionTaskState< + TYPES: NodeType, + I: NodeImplementation< + TYPES, + Leaf = SequencingLeaf, + ConsensusMessage = SequencingMessage, + >, + A: SequencingConsensusApi, I> + 'static, +> where + CommitteeEx: ConsensusExchange< + TYPES, + Message, + Certificate = DACertificate, + Commitment = Commitment, + >, +{ + /// The state's api + pub api: A, + /// Global registry task for the state + pub registry: GlobalRegistry, + + /// View number this view is executing in. + pub cur_view: TYPES::Time, + + /// Reference to consensus. Leader will require a read lock on this. + pub consensus: Arc>>>, + + /// A list of undecided transactions + pub transactions: Arc>>, + + /// A list of transactions we've seen decided, but didn't receive + pub seen_transactions: HashSet>, + + /// the committee exchange + pub committee_exchange: Arc>, + + /// Global events stream to publish events + pub event_stream: ChannelStream>, + + /// This state's ID + pub id: u64, +} + +// We have two `TransactionTaskState` implementations with different bounds. The implementation +// here requires `TYPES: NodeType`, +// whereas it's just `TYPES: NodeType` in the second implementation. +impl< + TYPES: NodeType, + I: NodeImplementation< + TYPES, + Leaf = SequencingLeaf, + ConsensusMessage = SequencingMessage, + >, + A: SequencingConsensusApi, I> + 'static, + > TransactionTaskState +where + CommitteeEx: ConsensusExchange< + TYPES, + Message, + Certificate = DACertificate, + Commitment = Commitment, + >, +{ + /// main task event handler + #[instrument(skip_all, fields(id = self.id, view = *self.cur_view), name = "Transaction Handling Task", level = "error")] + + pub async fn handle_event( + &mut self, + event: SequencingHotShotEvent, + ) -> Option { + match event { + SequencingHotShotEvent::TransactionsRecv(transactions) => { + let consensus = self.consensus.read().await; + self.transactions + .modify(|txns| { + for transaction in transactions { + let size = bincode_opts().serialized_size(&transaction).unwrap_or(0); + + // If we didn't already know about this transaction, update our mempool metrics. + if !self.seen_transactions.remove(&transaction.commit()) + && txns.insert(transaction.commit(), transaction).is_none() + { + consensus.metrics.outstanding_transactions.update(1); + consensus + .metrics + .outstanding_transactions_memory_size + .update(i64::try_from(size).unwrap_or_else(|e| { + warn!("Conversion failed: {e}. Using the max value."); + i64::MAX + })); + } + } + }) + .await; + + return None; + } + SequencingHotShotEvent::LeafDecided(leaf_chain) => { + let mut included_txns = HashSet::new(); + let mut included_txn_size = 0; + let mut included_txn_count = 0; + for leaf in leaf_chain { + match &leaf.deltas { + Left(block) => { + let txns = block.contained_transactions(); + for txn in txns { + included_txns.insert(txn); + } + } + Right(_) => {} + } + } + let consensus = self.consensus.read().await; + let txns = self.transactions.cloned().await; + + let _ = included_txns.iter().map(|hash| { + if !txns.contains_key(hash) { + self.seen_transactions.insert(*hash); + } + }); + drop(txns); + self.transactions + .modify(|txns| { + *txns = txns + .drain() + .filter(|(txn_hash, txn)| { + if included_txns.contains(txn_hash) { + included_txn_count += 1; + included_txn_size += + bincode_opts().serialized_size(txn).unwrap_or_default(); + false + } else { + true + } + }) + .collect(); + }) + .await; + + consensus + .metrics + .outstanding_transactions + .update(-included_txn_count); + consensus + .metrics + .outstanding_transactions_memory_size + .update(-(i64::try_from(included_txn_size).unwrap_or(i64::MAX))); + return None; + } + SequencingHotShotEvent::ViewChange(view) => { + if *self.cur_view >= *view { + return None; + } + + if *view - *self.cur_view > 1 { + error!("View changed by more than 1 going to view {:?}", view); + } + self.cur_view = view; + + // If we are not the next leader (DA leader for this view) immediately exit + if !self.committee_exchange.is_leader(self.cur_view + 1) { + // panic!("We are not the DA leader for view {}", *self.cur_view + 1); + return None; + } + + // ED Copy of parent_leaf() function from sequencing leader + + let consensus = self.consensus.read().await; + let parent_view_number = &consensus.high_qc.view_number; + + let Some(parent_view) = consensus.state_map.get(parent_view_number) else { + error!( + "Couldn't find high QC parent in state map. Parent view {:?}", + parent_view_number + ); + return None; + }; + let Some(leaf) = parent_view.get_leaf_commitment() else { + error!( + ?parent_view_number, + ?parent_view, + "Parent of high QC points to a view without a proposal" + ); + return None; + }; + let Some(leaf) = consensus.saved_leaves.get(&leaf) else { + error!("Failed to find high QC parent."); + return None; + }; + let parent_leaf = leaf.clone(); + + drop(consensus); + + let txns = self.wait_for_transactions(parent_leaf).await?; + // TODO (Keyao) Determine whether to allow empty transaction when proposing a block. + // + + debug!("Prepare VID shares"); + // TODO https://github.com/EspressoSystems/HotShot/issues/1686 + let srs = hotshot_types::data::test_srs(NUM_STORAGE_NODES); + let vid = VidScheme::new(NUM_CHUNKS, NUM_STORAGE_NODES, &srs).unwrap(); + // TODO https://github.com/EspressoSystems/jellyfish/issues/375 + let mut txns_flatten = Vec::new(); + for txn in &txns { + txns_flatten.extend(txn.0.clone()); + } + let vid_disperse = vid.disperse(&txns_flatten).unwrap(); + let block = VIDBlockPayload { + transactions: txns, + commitment: vid_disperse.commit, + }; + + self.event_stream + .publish(SequencingHotShotEvent::BlockReady(block.clone(), view + 1)) + .await; + + // TODO (Keyao) Determine and update where to publish VidDisperseSend. + // + self.event_stream + .publish(SequencingHotShotEvent::VidDisperseSend( + Proposal { + data: VidDisperse { + view_number: view + 1, + commitment: block.commit(), + shares: vid_disperse.shares, + common: vid_disperse.common, + }, + // TODO (Keyao) This is also signed in DA task. + signature: self.committee_exchange.sign_da_proposal(&block.commit()), + }, + // TODO don't send to committee, send to quorum (consensus.rs) https://github.com/EspressoSystems/HotShot/issues/1696 + self.committee_exchange.public_key().clone(), + )) + .await; + return None; + } + SequencingHotShotEvent::Shutdown => { + return Some(HotShotTaskCompleted::ShutDown); + } + _ => {} + } + None + } +} + +// We have two `TransactionTaskState` implementations with different bounds. The implementation +// above requires `TYPES: NodeType`, +// whereas here it's just `TYPES: NodeType`. +impl< + TYPES: NodeType, + I: NodeImplementation< + TYPES, + Leaf = SequencingLeaf, + ConsensusMessage = SequencingMessage, + >, + A: SequencingConsensusApi, I> + 'static, + > TransactionTaskState +where + CommitteeEx: ConsensusExchange< + TYPES, + Message, + Certificate = DACertificate, + Commitment = Commitment, + >, +{ + #[instrument(skip_all, fields(id = self.id, view = *self.cur_view), name = "Transaction Handling Task", level = "error")] + async fn wait_for_transactions( + &self, + _parent_leaf: SequencingLeaf, + ) -> Option> { + let task_start_time = Instant::now(); + + // TODO (Keyao) Investigate the use of transaction hash + // + // let parent_leaf = self.parent_leaf().await?; + // let previous_used_txns = match parent_leaf.deltas { + // Either::Left(block) => block.contained_transactions(), + // Either::Right(_commitment) => HashSet::new(), + // }; + + let receiver = self.transactions.subscribe().await; + + loop { + let all_txns = self.transactions.cloned().await; + debug!("Size of transactions: {}", all_txns.len()); + // TODO (Keyao) Investigate the use of transaction hash + // + // let unclaimed_txns: Vec<_> = all_txns + // .iter() + // .filter(|(txn_hash, _txn)| !previous_used_txns.contains(txn_hash)) + // .collect(); + let unclaimed_txns = all_txns; + + let time_past = task_start_time.elapsed(); + if unclaimed_txns.len() < self.api.min_transactions() + && (time_past < self.api.propose_max_round_time()) + { + let duration = self.api.propose_max_round_time() - time_past; + let result = async_timeout(duration, receiver.recv()).await; + match result { + Err(_) => { + // Fall through below to updating new block + error!( + "propose_max_round_time passed, sending transactions we have so far" + ); + } + Ok(Err(e)) => { + // Something unprecedented is wrong, and `transactions` has been dropped + error!("Channel receiver error for SubscribableRwLock {:?}", e); + return None; + } + Ok(Ok(_)) => continue, + } + } + break; + } + let all_txns = self.transactions.cloned().await; + // TODO (Keyao) Investigate the use of transaction hash + // + let txns: Vec = all_txns.values().cloned().collect(); + // let txns: Vec = all_txns + // .iter() + // .filter_map(|(txn_hash, txn)| { + // if previous_used_txns.contains(txn_hash) { + // None + // } else { + // Some(txn.clone()) + // } + // }) + // .collect(); + Some(txns) + } + + /// Event filter for the transaction task + pub fn filter(event: &SequencingHotShotEvent) -> bool { + matches!( + event, + SequencingHotShotEvent::TransactionsRecv(_) + | SequencingHotShotEvent::LeafDecided(_) + | SequencingHotShotEvent::Shutdown + | SequencingHotShotEvent::ViewChange(_) + ) + } +} + +/// task state implementation for Transactions Task +impl< + TYPES: NodeType, + I: NodeImplementation< + TYPES, + Leaf = SequencingLeaf, + ConsensusMessage = SequencingMessage, + >, + A: SequencingConsensusApi, I> + 'static, + > TS for TransactionTaskState +where + CommitteeEx: ConsensusExchange< + TYPES, + Message, + Certificate = DACertificate, + Commitment = Commitment, + >, +{ +} + +/// Type alias for DA Task Types +pub type TransactionsTaskTypes = HSTWithEvent< + ConsensusTaskError, + SequencingHotShotEvent, + ChannelStream>, + TransactionTaskState, +>; diff --git a/crates/task-impls/src/view_sync.rs b/crates/task-impls/src/view_sync.rs index da52ceaf82..4b241c37cd 100644 --- a/crates/task-impls/src/view_sync.rs +++ b/crates/task-impls/src/view_sync.rs @@ -1,7 +1,7 @@ #![allow(clippy::module_name_repetitions)] use crate::events::SequencingHotShotEvent; use async_compatibility_layer::art::{async_sleep, async_spawn}; -use commit::Committable; +use commit::{Commitment, Committable}; use either::Either::{self, Left, Right}; use futures::FutureExt; use hotshot_task::{ @@ -9,7 +9,13 @@ use hotshot_task::{ task::{FilterEvent, HandleEvent, HotShotTaskCompleted, HotShotTaskTypes, TS}, task_impls::{HSTWithEvent, TaskBuilder}, }; -use hotshot_types::traits::{election::Membership, network::ConsensusIntentEvent}; +use hotshot_types::{ + traits::{ + election::{Membership, SignedCertificate}, + network::ConsensusIntentEvent, + }, + vote::ViewSyncVoteAccumulator, +}; use bitvec::prelude::*; use hotshot_task::global_registry::GlobalRegistry; @@ -25,10 +31,10 @@ use hotshot_types::{ signature_key::SignatureKey, state::ConsensusTime, }, - vote::{ViewSyncData, ViewSyncVote, VoteAccumulator}, + vote::{ViewSyncData, ViewSyncVote}, }; use snafu::Snafu; -use std::{collections::HashMap, sync::Arc, time::Duration}; +use std::{collections::HashMap, marker::PhantomData, sync::Arc, time::Duration}; use tracing::{debug, error, instrument}; #[derive(PartialEq, PartialOrd, Clone, Debug, Eq, Hash)] /// Phases of view sync @@ -69,7 +75,7 @@ pub struct ViewSyncTaskState< Message, Proposal = ViewSyncCertificate, Certificate = ViewSyncCertificate, - Commitment = ViewSyncData, + Commitment = Commitment>, >, { /// Registry to register sub tasks @@ -118,7 +124,7 @@ where Message, Proposal = ViewSyncCertificate, Certificate = ViewSyncCertificate, - Commitment = ViewSyncData, + Commitment = Commitment>, >, { } @@ -146,7 +152,7 @@ pub struct ViewSyncReplicaTaskState< Message, Proposal = ViewSyncCertificate, Certificate = ViewSyncCertificate, - Commitment = ViewSyncData, + Commitment = Commitment>, >, { /// Timeout for view sync rounds @@ -189,7 +195,7 @@ where Message, Proposal = ViewSyncCertificate, Certificate = ViewSyncCertificate, - Commitment = ViewSyncData, + Commitment = Commitment>, >, { } @@ -216,8 +222,14 @@ pub struct ViewSyncRelayTaskState< /// View sync exchange pub exchange: Arc>, /// Vote accumulator + #[allow(clippy::type_complexity)] pub accumulator: Either< - VoteAccumulator>, + as SignedCertificate< + TYPES, + TYPES::Time, + TYPES::VoteTokenType, + Commitment>, + >>::VoteAccumulator, ViewSyncCertificate, >, /// Our node id; for logging @@ -258,7 +270,7 @@ where Message, Proposal = ViewSyncCertificate, Certificate = ViewSyncCertificate, - Commitment = ViewSyncData, + Commitment = Commitment>, >, { #[instrument(skip_all, fields(id = self.id, view = *self.current_view), name = "View Sync Main Task", level = "error")] @@ -381,24 +393,23 @@ where return; } - let accumulator = VoteAccumulator { - total_vote_outcomes: HashMap::new(), - da_vote_outcomes: HashMap::new(), - yes_vote_outcomes: HashMap::new(), - no_vote_outcomes: HashMap::new(), - viewsync_precommit_vote_outcomes: HashMap::new(), - viewsync_commit_vote_outcomes: HashMap::new(), - viewsync_finalize_vote_outcomes: HashMap::new(), + let new_accumulator = ViewSyncVoteAccumulator { + pre_commit_vote_outcomes: HashMap::new(), + commit_vote_outcomes: HashMap::new(), + finalize_vote_outcomes: HashMap::new(), + success_threshold: self.exchange.success_threshold(), failure_threshold: self.exchange.failure_threshold(), + sig_lists: Vec::new(), signers: bitvec![0; self.exchange.total_nodes()], + phantom: PhantomData, }; let mut relay_state = ViewSyncRelayTaskState { event_stream: self.event_stream.clone(), exchange: self.exchange.clone(), - accumulator: either::Left(accumulator), + accumulator: either::Left(new_accumulator), id: self.id, }; @@ -637,7 +648,7 @@ where Message, Proposal = ViewSyncCertificate, Certificate = ViewSyncCertificate, - Commitment = ViewSyncData, + Commitment = Commitment>, >, { #[instrument(skip_all, fields(id = self.id, view = *self.current_view), name = "View Sync Replica Task", level = "error")] @@ -971,7 +982,7 @@ where Message, Proposal = ViewSyncCertificate, Certificate = ViewSyncCertificate, - Commitment = ViewSyncData, + Commitment = Commitment>, >, { /// Handles incoming events for the view sync relay task @@ -989,7 +1000,7 @@ where return (Some(HotShotTaskCompleted::ShutDown), self); } - let (vote_internal, phase) = match vote { + let (vote_internal, phase) = match vote.clone() { ViewSyncVote::PreCommit(vote_internal) => { (vote_internal, ViewSyncPhase::PreCommit) } @@ -1024,15 +1035,10 @@ where *vote_internal.round, vote_internal.relay ); - let accumulator = self.exchange.accumulate_vote( - &vote_internal.signature.0, - &vote_internal.signature.1, - view_sync_data, - vote_internal.vote_data, - vote_internal.vote_token.clone(), - vote_internal.round, + let accumulator = self.exchange.accumulate_vote_2( self.accumulator.left().unwrap(), - Some(vote_internal.relay), + &vote, + &view_sync_data, ); self.accumulator = match accumulator { @@ -1044,7 +1050,6 @@ where data: certificate.clone(), signature, }; - // error!("Sending view sync cert {:?}", message.clone()); self.event_stream .publish(SequencingHotShotEvent::ViewSyncCertificateSend( message, @@ -1053,19 +1058,19 @@ where .await; // Reset accumulator for new certificate - either::Left(VoteAccumulator { - total_vote_outcomes: HashMap::new(), - da_vote_outcomes: HashMap::new(), - yes_vote_outcomes: HashMap::new(), - no_vote_outcomes: HashMap::new(), - viewsync_precommit_vote_outcomes: HashMap::new(), - viewsync_commit_vote_outcomes: HashMap::new(), - viewsync_finalize_vote_outcomes: HashMap::new(), + let new_accumulator = ViewSyncVoteAccumulator { + pre_commit_vote_outcomes: HashMap::new(), + commit_vote_outcomes: HashMap::new(), + finalize_vote_outcomes: HashMap::new(), + success_threshold: self.exchange.success_threshold(), failure_threshold: self.exchange.failure_threshold(), + sig_lists: Vec::new(), signers: bitvec![0; self.exchange.total_nodes()], - }) + phantom: PhantomData, + }; + either::Left(new_accumulator) } }; diff --git a/crates/task/Cargo.toml b/crates/task/Cargo.toml index 720a7aca6a..cb1703831f 100644 --- a/crates/task/Cargo.toml +++ b/crates/task/Cargo.toml @@ -10,7 +10,6 @@ async-compatibility-layer = { workspace = true } async-trait = { workspace = true } either = { workspace = true } futures = { workspace = true } -nll = { workspace = true } serde = { workspace = true } snafu = { workspace = true } async-lock = { workspace = true } diff --git a/crates/testing/Cargo.toml b/crates/testing/Cargo.toml index e75c328a5d..935f9e4342 100644 --- a/crates/testing/Cargo.toml +++ b/crates/testing/Cargo.toml @@ -34,13 +34,13 @@ rand = { workspace = true } rand_chacha = { workspace = true } snafu = { workspace = true } tracing = { workspace = true } -nll = { workspace = true } serde = { workspace = true } ethereum-types = { workspace = true } bitvec = { workspace = true } [dev-dependencies] async-lock = { workspace = true } +bincode = { workspace = true } # GG any better options for serialization? [target.'cfg(all(async_executor_impl = "tokio"))'.dependencies] tokio = { workspace = true } diff --git a/crates/testing/README.md b/crates/testing/README.md index a477450092..59b281f421 100644 --- a/crates/testing/README.md +++ b/crates/testing/README.md @@ -69,4 +69,4 @@ async { }; ``` -See TODO for examples. +See TODO for examples. \ No newline at end of file diff --git a/crates/testing/src/network_reliability.rs b/crates/testing/src/network_reliability.rs deleted file mode 100644 index 97b22b533b..0000000000 --- a/crates/testing/src/network_reliability.rs +++ /dev/null @@ -1,163 +0,0 @@ -use std::time::Duration; - -use hotshot::traits::NetworkReliability; -use rand::{ - distributions::{Bernoulli, Uniform}, - prelude::Distribution, -}; - -/// A synchronous network. Packets may be delayed, but are guaranteed -/// to arrive within `timeout` ns -#[derive(Clone, Copy, Debug, Default)] -pub struct SynchronousNetwork { - /// Max delay of packet before arrival - timeout_ms: u64, - /// Lowest value in milliseconds that a packet may be delayed - delay_low_ms: u64, -} - -impl NetworkReliability for SynchronousNetwork { - /// never drop a packet - fn sample_keep(&self) -> bool { - true - } - fn sample_delay(&self) -> Duration { - Duration::from_millis( - Uniform::new_inclusive(self.delay_low_ms, self.timeout_ms) - .sample(&mut rand::thread_rng()), - ) - } -} - -/// An asynchronous network. Packets may be dropped entirely -/// or delayed for arbitrarily long periods -/// probability that packet is kept = `keep_numerator` / `keep_denominator` -/// packet delay is obtained by sampling from a uniform distribution -/// between `delay_low_ms` and `delay_high_ms`, inclusive -#[derive(Debug, Clone, Copy)] -pub struct AsynchronousNetwork { - /// numerator for probability of keeping packets - keep_numerator: u32, - /// denominator for probability of keeping packets - keep_denominator: u32, - /// lowest value in milliseconds that a packet may be delayed - delay_low_ms: u64, - /// highest value in milliseconds that a packet may be delayed - delay_high_ms: u64, -} - -impl NetworkReliability for AsynchronousNetwork { - fn sample_keep(&self) -> bool { - Bernoulli::from_ratio(self.keep_numerator, self.keep_denominator) - .unwrap() - .sample(&mut rand::thread_rng()) - } - fn sample_delay(&self) -> Duration { - Duration::from_millis( - Uniform::new_inclusive(self.delay_low_ms, self.delay_high_ms) - .sample(&mut rand::thread_rng()), - ) - } -} - -/// An partially synchronous network. Behaves asynchronously -/// until some arbitrary time bound, GST, -/// then synchronously after GST -#[derive(Debug, Clone, Copy)] -pub struct PartiallySynchronousNetwork { - /// asynchronous portion of network - asynchronous: AsynchronousNetwork, - /// synchronous portion of network - synchronous: SynchronousNetwork, - /// time when GST occurs - gst: std::time::Duration, - /// when the network was started - start: std::time::Instant, -} - -impl NetworkReliability for PartiallySynchronousNetwork { - /// never drop a packet - fn sample_keep(&self) -> bool { - true - } - fn sample_delay(&self) -> Duration { - // act asyncronous before gst - if self.start.elapsed() < self.gst { - if self.asynchronous.sample_keep() { - self.asynchronous.sample_delay() - } else { - // assume packet was "dropped" and will arrive after gst - self.synchronous.sample_delay() + self.gst - } - } else { - // act syncronous after gst - self.synchronous.sample_delay() - } - } -} - -impl Default for AsynchronousNetwork { - // disable all chance of failure - fn default() -> Self { - AsynchronousNetwork { - keep_numerator: 1, - keep_denominator: 1, - delay_low_ms: 0, - delay_high_ms: 0, - } - } -} - -impl Default for PartiallySynchronousNetwork { - fn default() -> Self { - PartiallySynchronousNetwork { - synchronous: SynchronousNetwork::default(), - asynchronous: AsynchronousNetwork::default(), - gst: std::time::Duration::new(0, 0), - start: std::time::Instant::now(), - } - } -} - -impl SynchronousNetwork { - /// create new `SynchronousNetwork` - pub fn new(timeout: u64, delay_low_ms: u64) -> Self { - SynchronousNetwork { - timeout_ms: timeout, - delay_low_ms, - } - } -} - -impl AsynchronousNetwork { - /// create new `AsynchronousNetwork` - pub fn new( - keep_numerator: u32, - keep_denominator: u32, - delay_low_ms: u64, - delay_high_ms: u64, - ) -> Self { - AsynchronousNetwork { - keep_numerator, - keep_denominator, - delay_low_ms, - delay_high_ms, - } - } -} - -impl PartiallySynchronousNetwork { - /// create new `PartiallySynchronousNetwork` - pub fn new( - asynchronous: AsynchronousNetwork, - synchronous: SynchronousNetwork, - gst: std::time::Duration, - ) -> Self { - PartiallySynchronousNetwork { - asynchronous, - synchronous, - gst, - start: std::time::Instant::now(), - } - } -} diff --git a/crates/testing/src/node_types.rs b/crates/testing/src/node_types.rs index 1d2985c56d..4ffd74e2bf 100644 --- a/crates/testing/src/node_types.rs +++ b/crates/testing/src/node_types.rs @@ -2,7 +2,7 @@ use hotshot::traits::implementations::CombinedNetworks; use std::{marker::PhantomData, sync::Arc}; use hotshot::{ - demos::sdemo::{SDemoBlock, SDemoState, SDemoTransaction}, + demo::SDemoState, traits::{ election::static_committee::{StaticCommittee, StaticElectionConfig, StaticVoteToken}, implementations::{ @@ -11,18 +11,18 @@ use hotshot::{ }, NodeImplementation, }, - types::bn254::BN254Pub, + types::bn254::BLSPubKey, }; use hotshot_types::{ + block_impl::{VIDBlockPayload, VIDTransaction}, certificate::ViewSyncCertificate, - data::{DAProposal, QuorumProposal, SequencingLeaf, ViewNumber}, + data::{QuorumProposal, SequencingLeaf, ViewNumber}, message::{Message, SequencingMessage}, traits::{ election::{CommitteeExchange, QuorumExchange, ViewSyncExchange}, network::{TestableChannelImplementation, TestableNetworkingImplementation}, node_implementation::{ChannelMaps, NodeType, SequencingExchanges, TestableExchange}, }, - vote::{DAVote, QuorumVote, ViewSyncVote}, }; use serde::{Deserialize, Serialize}; @@ -42,10 +42,10 @@ use serde::{Deserialize, Serialize}; pub struct SequencingTestTypes; impl NodeType for SequencingTestTypes { type Time = ViewNumber; - type BlockType = SDemoBlock; - type SignatureKey = BN254Pub; + type BlockType = VIDBlockPayload; + type SignatureKey = BLSPubKey; type VoteTokenType = StaticVoteToken; - type Transaction = SDemoTransaction; + type Transaction = VIDTransaction; type ElectionConfigType = StaticElectionConfig; type StateType = SDemoState; } @@ -65,80 +65,33 @@ pub struct StaticFallbackImpl; pub type StaticMembership = StaticCommittee>; -pub type StaticMemoryDAComm = MemoryCommChannel< - SequencingTestTypes, - SequencingMemoryImpl, - DAProposal, - DAVote, - StaticMembership, ->; +pub type StaticMemoryDAComm = + MemoryCommChannel; -type StaticLibp2pDAComm = Libp2pCommChannel< - SequencingTestTypes, - SequencingLibp2pImpl, - DAProposal, - DAVote, - StaticMembership, ->; +type StaticLibp2pDAComm = + Libp2pCommChannel; -type StaticWebDAComm = WebCommChannel< - SequencingTestTypes, - SequencingWebImpl, - DAProposal, - DAVote, - StaticMembership, ->; +type StaticWebDAComm = WebCommChannel; type StaticFallbackComm = WebServerWithFallbackCommChannel; -pub type StaticMemoryQuorumComm = MemoryCommChannel< - SequencingTestTypes, - SequencingMemoryImpl, - QuorumProposal>, - QuorumVote>, - StaticMembership, ->; +pub type StaticMemoryQuorumComm = + MemoryCommChannel; -type StaticLibp2pQuorumComm = Libp2pCommChannel< - SequencingTestTypes, - SequencingLibp2pImpl, - QuorumProposal>, - QuorumVote>, - StaticMembership, ->; +type StaticLibp2pQuorumComm = + Libp2pCommChannel; -type StaticWebQuorumComm = WebCommChannel< - SequencingTestTypes, - SequencingWebImpl, - QuorumProposal>, - QuorumVote>, - StaticMembership, ->; +type StaticWebQuorumComm = WebCommChannel; -pub type StaticMemoryViewSyncComm = MemoryCommChannel< - SequencingTestTypes, - SequencingMemoryImpl, - ViewSyncCertificate, - ViewSyncVote, - StaticMembership, ->; +pub type StaticMemoryViewSyncComm = + MemoryCommChannel; -type StaticLibp2pViewSyncComm = Libp2pCommChannel< - SequencingTestTypes, - SequencingLibp2pImpl, - ViewSyncCertificate, - ViewSyncVote, - StaticMembership, ->; +type StaticLibp2pViewSyncComm = + Libp2pCommChannel; -type StaticWebViewSyncComm = WebCommChannel< - SequencingTestTypes, - SequencingWebImpl, - ViewSyncCertificate, - ViewSyncVote, - StaticMembership, ->; +type StaticWebViewSyncComm = + WebCommChannel; pub type SequencingLibp2pExchange = SequencingExchanges< SequencingTestTypes, @@ -231,9 +184,24 @@ impl Box::new(move |id| { let network = Arc::new(network_generator(id)); - let quorum_chan = <>>::Networking as TestableChannelImplementation<_, _, _, _, _, _>>::generate_network()(network.clone()); - let committee_chan = <>>::Networking as TestableChannelImplementation<_, _, _, _, _, _>>::generate_network()(network.clone()); - let view_sync_chan = <>>::Networking as TestableChannelImplementation<_, _, _, _, _, _>>::generate_network()(network); + let quorum_chan = + <, + >>::Networking as TestableChannelImplementation<_, _, _, _>>::generate_network( + )(network.clone()); + let committee_chan = + <, + >>::Networking as TestableChannelImplementation<_, _, _, _>>::generate_network( + )(network.clone()); + let view_sync_chan = + <, + >>::Networking as TestableChannelImplementation<_, _, _, _>>::generate_network( + )(network); (quorum_chan, committee_chan, view_sync_chan) }) @@ -325,9 +293,24 @@ impl Box::new(move |id| { let network = Arc::new(network_generator(id)); let network_da = Arc::new(network_da_generator(id)); - let quorum_chan = <>>::Networking as TestableChannelImplementation<_, _, _, _, _, _>>::generate_network()(network.clone()); - let committee_chan = <>>::Networking as TestableChannelImplementation<_, _, _, _, _, _>>::generate_network()(network_da); - let view_sync_chan = <>>::Networking as TestableChannelImplementation<_, _, _, _, _, _>>::generate_network()(network); + let quorum_chan = + <, + >>::Networking as TestableChannelImplementation<_, _, _, _>>::generate_network( + )(network.clone()); + let committee_chan = + <, + >>::Networking as TestableChannelImplementation<_, _, _, _>>::generate_network( + )(network_da); + let view_sync_chan = + <, + >>::Networking as TestableChannelImplementation<_, _, _, _>>::generate_network( + )(network); (quorum_chan, committee_chan, view_sync_chan) }) @@ -445,9 +428,24 @@ impl Box::new(move |id| { let network = Arc::new(network_generator(id)); let network_da = Arc::new(network_da_generator(id)); - let quorum_chan = <>>::Networking as TestableChannelImplementation<_, _, _, _, _, _>>::generate_network()(network.clone()); - let committee_chan = <>>::Networking as TestableChannelImplementation<_, _, _, _, _, _>>::generate_network()(network_da); - let view_sync_chan = <>>::Networking as TestableChannelImplementation<_, _, _, _, _, _>>::generate_network()(network); + let quorum_chan = + <, + >>::Networking as TestableChannelImplementation<_, _, _, _>>::generate_network( + )(network.clone()); + let committee_chan = + <, + >>::Networking as TestableChannelImplementation<_, _, _, _>>::generate_network( + )(network_da); + let view_sync_chan = + <, + >>::Networking as TestableChannelImplementation<_, _, _, _>>::generate_network( + )(network); (quorum_chan, committee_chan, view_sync_chan) }) @@ -584,44 +582,20 @@ impl <, - >>::Networking as TestableChannelImplementation< - _, - _, - QuorumProposal< - SequencingTestTypes, - >::Leaf, - >, - QuorumVote< - SequencingTestTypes, - >::Leaf, - >, - _, - _, - >>::generate_network()(network.clone()); + >>::Networking as TestableChannelImplementation<_, _, _, _>>::generate_network( + )(network.clone()); let committee_chan = <, - >>::Networking as TestableChannelImplementation< - _, - _, - DAProposal, - DAVote, - _, - _, - >>::generate_network()(network_da); + >>::Networking as TestableChannelImplementation<_, _, _, _>>::generate_network( + )(network_da); let view_sync_chan = <, - >>::Networking as TestableChannelImplementation< - _, - _, - ViewSyncCertificate, - ViewSyncVote, - _, - _, - >>::generate_network()(network); + >>::Networking as TestableChannelImplementation<_, _, _, _>>::generate_network( + )(network); (quorum_chan, committee_chan, view_sync_chan) }) } diff --git a/crates/testing/src/overall_safety_task.rs b/crates/testing/src/overall_safety_task.rs index 4bda48adcc..b2a9a88451 100644 --- a/crates/testing/src/overall_safety_task.rs +++ b/crates/testing/src/overall_safety_task.rs @@ -90,9 +90,13 @@ impl> TS for OverallSafety pub struct RoundResult> { /// Transactions that were submitted // pub txns: Vec, + /// Nodes that committed this round /// id -> (leaf, qc) - pub success_nodes: HashMap, QuorumCertificate)>, + // TODO GG: isn't it infeasible to store a Vec? + #[allow(clippy::type_complexity)] + success_nodes: HashMap, QuorumCertificate>)>, + /// Nodes that failed to commit this round pub failed_nodes: HashMap>>>, @@ -185,7 +189,7 @@ impl> RoundResult pub fn insert_into_result( &mut self, idx: usize, - result: (Vec, QuorumCertificate), + result: (Vec, QuorumCertificate>), maybe_block_size: Option, ) -> Option { self.success_nodes.insert(idx as u64, result.clone()); diff --git a/crates/testing/src/spinning_task.rs b/crates/testing/src/spinning_task.rs index c8ef07d51c..a9d9e5d586 100644 --- a/crates/testing/src/spinning_task.rs +++ b/crates/testing/src/spinning_task.rs @@ -113,7 +113,8 @@ impl SpinningTaskDescription { state.late_start.remove(&idx.try_into().unwrap()) { tracing::error!("Spinning up node late"); - node.run_tasks().await; + let handle = node.run_tasks().await; + handle.hotshot.start_consensus().await; } } UpDown::Down => { diff --git a/crates/testing/src/task_helpers.rs b/crates/testing/src/task_helpers.rs index 13868721d4..f4e7fe49a8 100644 --- a/crates/testing/src/task_helpers.rs +++ b/crates/testing/src/task_helpers.rs @@ -6,14 +6,15 @@ use commit::Committable; use either::Right; use hotshot::{ certificate::QuorumCertificate, - traits::{Block, NodeImplementation, TestableNodeImplementation}, - types::{bn254::BN254Pub, SignatureKey, SystemContextHandle}, + traits::{NodeImplementation, TestableNodeImplementation}, + types::{bn254::BLSPubKey, SignatureKey, SystemContextHandle}, HotShotInitializer, HotShotSequencingConsensusApi, SystemContext, }; use hotshot_task::event_stream::ChannelStream; use hotshot_task_impls::events::SequencingHotShotEvent; use hotshot_types::{ - data::{QuorumProposal, SequencingLeaf, ViewNumber}, + block_impl::{VIDBlockPayload, NUM_CHUNKS, NUM_STORAGE_NODES}, + data::{QuorumProposal, SequencingLeaf, VidScheme, ViewNumber}, message::{Message, Proposal}, traits::{ consensus_api::ConsensusSharedApi, @@ -21,7 +22,7 @@ use hotshot_types::{ metrics::NoMetrics, node_implementation::{CommitteeEx, ExchangesType, NodeType, QuorumEx}, signature_key::EncodedSignature, - state::ConsensusTime, + state::{ConsensusTime, TestableBlock}, }, }; @@ -47,9 +48,9 @@ pub async fn build_system_handle( >>::block_genesis()) .unwrap(); - let known_nodes = config.known_nodes.clone(); let known_nodes_with_stake = config.known_nodes_with_stake.clone(); - let private_key = ::generated_from_seed_indexed([0u8; 32], node_id).1; + let private_key = + ::generated_from_seed_indexed([0u8; 32], node_id).1; let public_key = ::SignatureKey::from_private(&private_key); let quorum_election_config = config.election_config.clone().unwrap_or_else(|| { as ConsensusExchange< @@ -67,7 +68,6 @@ pub async fn build_system_handle( let exchanges = >::Exchanges::create( known_nodes_with_stake.clone(), - known_nodes.clone(), (quorum_election_config, committee_election_config), networks, public_key, @@ -90,7 +90,7 @@ pub async fn build_system_handle( async fn build_quorum_proposal_and_signature( handle: &SystemContextHandle, - private_key: &::PrivateKey, + private_key: &::PrivateKey, view: u64, ) -> ( QuorumProposal>, @@ -117,8 +117,7 @@ async fn build_quorum_proposal_and_signature( let parent_leaf = leaf.clone(); // every event input is seen on the event stream in the output. - - let block_commitment = ::BlockType::new().commit(); + let block = ::genesis(); let leaf = SequencingLeaf { view_number: ViewNumber::new(view), height: parent_leaf.height + 1, @@ -126,14 +125,14 @@ async fn build_quorum_proposal_and_signature( parent_commitment: parent_leaf.commit(), // Use the block commitment rather than the block, so that the replica can construct // the same leaf with the commitment. - deltas: Right(block_commitment), + deltas: Right(block.commit()), rejected: vec![], timestamp: 0, proposer_id: api.public_key().to_bytes(), }; - let signature = ::sign(private_key, leaf.commit().as_ref()); + let signature = ::sign(private_key, leaf.commit().as_ref()); let proposal = QuorumProposal::> { - block_commitment, + block_commitment: block.commit(), view_number: ViewNumber::new(view), height: 1, justify_qc: QuorumCertificate::genesis(), @@ -147,7 +146,7 @@ async fn build_quorum_proposal_and_signature( pub async fn build_quorum_proposal( handle: &SystemContextHandle, - private_key: &::PrivateKey, + private_key: &::PrivateKey, view: u64, ) -> Proposal>> { let (proposal, signature) = @@ -158,8 +157,14 @@ pub async fn build_quorum_proposal( } } -pub fn key_pair_for_id(node_id: u64) -> (::PrivateKey, BN254Pub) { - let private_key = ::generated_from_seed_indexed([0u8; 32], node_id).1; +pub fn key_pair_for_id(node_id: u64) -> (::PrivateKey, BLSPubKey) { + let private_key = + ::generated_from_seed_indexed([0u8; 32], node_id).1; let public_key = ::SignatureKey::from_private(&private_key); (private_key, public_key) } + +pub fn vid_init() -> VidScheme { + let srs = hotshot_types::data::test_srs(NUM_STORAGE_NODES); + VidScheme::new(NUM_CHUNKS, NUM_STORAGE_NODES, &srs).unwrap() +} diff --git a/crates/testing/src/test_builder.rs b/crates/testing/src/test_builder.rs index f1db2a9320..3515f04368 100644 --- a/crates/testing/src/test_builder.rs +++ b/crates/testing/src/test_builder.rs @@ -124,7 +124,7 @@ impl TestMetadata { } } - /// Default setting with 20 nodes and 10 views of successful views. + /// Default setting with 20 nodes and 8 views of successful views. pub fn default_more_nodes_less_success() -> TestMetadata { TestMetadata { total_nodes: 20, @@ -139,11 +139,11 @@ impl TestMetadata { completion_task_description: CompletionTaskDescription::TimeBasedCompletionTaskBuilder( TimeBasedCompletionTaskDescription { // Increase the duration to get the expected number of successful views. - duration: Duration::new(40, 0), + duration: Duration::new(200, 0), }, ), overall_safety_properties: OverallSafetyPropertiesDescription { - num_successful_views: 10, + num_successful_views: 8, ..Default::default() }, ..TestMetadata::default() @@ -219,7 +219,6 @@ impl TestMetadata { num_bootstrap: num_bootstrap_nodes, min_transactions, max_transactions: NonZeroUsize::new(99999).unwrap(), - known_nodes, known_nodes_with_stake, da_committee_size, next_view_timeout: 500, @@ -247,7 +246,7 @@ impl TestMetadata { } = timing_data; let mod_config = // TODO this should really be using the timing config struct - |a: &mut HotShotConfig::StakeTableEntry, TYPES::ElectionConfigType>| { + |a: &mut HotShotConfig<::StakeTableEntry, TYPES::ElectionConfigType>| { a.next_view_timeout = next_view_timeout; a.timeout_ratio = timeout_ratio; a.round_start_delay = round_start_delay; diff --git a/crates/testing/src/test_launcher.rs b/crates/testing/src/test_launcher.rs index 4a7e6bd9b1..4fb230b315 100644 --- a/crates/testing/src/test_launcher.rs +++ b/crates/testing/src/test_launcher.rs @@ -83,8 +83,6 @@ where QuorumCommChannel: CommunicationChannel< TYPES, Message, - as ConsensusExchange>>::Proposal, - as ConsensusExchange>>::Vote, as ConsensusExchange>>::Membership, >, { @@ -94,7 +92,6 @@ where pub storage: Generator<>::Storage>, /// configuration used to generate each hotshot node pub config: HotShotConfig< - TYPES::SignatureKey, ::StakeTableEntry, TYPES::ElectionConfigType, >, @@ -198,7 +195,6 @@ impl> TestLauncher::StakeTableEntry, TYPES::ElectionConfigType, >, diff --git a/crates/testing/src/test_runner.rs b/crates/testing/src/test_runner.rs index 57c82d24e9..056f0f8a26 100644 --- a/crates/testing/src/test_runner.rs +++ b/crates/testing/src/test_runner.rs @@ -41,8 +41,6 @@ where QuorumCommChannel: CommunicationChannel< TYPES, Message, - as ConsensusExchange>>::Proposal, - as ConsensusExchange>>::Vote, as ConsensusExchange>>::Membership, >, { @@ -59,8 +57,6 @@ where QuorumCommChannel: CommunicationChannel< TYPES, Message, - as ConsensusExchange>>::Proposal, - as ConsensusExchange>>::Vote, as ConsensusExchange>>::Membership, >, { @@ -202,8 +198,8 @@ where >, { let mut results = vec![]; - for _i in 0..total { - tracing::error!("running node{}", _i); + for i in 0..total { + tracing::debug!("launch node {}", i); let node_id = self.next_node_id; let storage = (self.launcher.resource_generator.storage)(node_id); let config = self.launcher.resource_generator.config.clone(); @@ -234,7 +230,6 @@ where storage: I::Storage, initializer: HotShotInitializer, config: HotShotConfig< - TYPES::SignatureKey, ::StakeTableEntry, TYPES::ElectionConfigType, >, @@ -250,7 +245,6 @@ where let node_id = self.next_node_id; self.next_node_id += 1; - let known_nodes = config.known_nodes.clone(); let known_nodes_with_stake = config.known_nodes_with_stake.clone(); // Generate key pair for certificate aggregation let private_key = TYPES::SignatureKey::generated_from_seed_indexed([0u8; 32], node_id).1; @@ -265,7 +259,6 @@ where let committee_election_config = I::committee_election_config_generator(); let exchanges = I::Exchanges::create( known_nodes_with_stake.clone(), - known_nodes.clone(), ( quorum_election_config, committee_election_config(config.da_committee_size as u64), diff --git a/crates/testing/tests/atomic_storage.rs b/crates/testing/tests/atomic_storage.rs index 3b97a60c9c..381db09d87 100644 --- a/crates/testing/tests/atomic_storage.rs +++ b/crates/testing/tests/atomic_storage.rs @@ -6,83 +6,13 @@ use hotshot::{ random_quorom_certificate, random_transaction, random_validating_leaf, VDemoBlock, VDemoState, }, - traits::{Block, State, Storage}, + traits::{BlockPayload, State, Storage}, }; use hotshot_types::{data::ViewNumber, traits::state::TestableState}; use rand::thread_rng; type AtomicStorage = hotshot::traits::implementations::AtomicStorage; -#[cfg_attr( - async_executor_impl = "tokio", - tokio::test(flavor = "multi_thread", worker_threads = 2) -)] -#[cfg_attr(async_executor_impl = "async-std", async_std::test)] -async fn test_happy_path_blocks() { - // This folder will be destroyed when the last handle to it closes - let file = tempfile::tempdir().expect("Could not create temp dir"); - let path = file.path(); - println!("Using store in {:?}", path); - let mut store = AtomicStorage::open(path).expect("Could not open atomic store"); - - let block = VDEntryBlock::default(); - let hash = block.hash(); - store - .update(|mut m| { - let block = block.clone(); - async move { m.insert_block(hash, block).await } - }) - .await - .unwrap(); - - // Make sure the data is still there after re-opening - drop(store); - store = AtomicStorage::open(path).expect("Could not open atomic store"); - assert_eq!( - store.get_block(&hash).await.unwrap(), - Some(DEntryBlock::default()) - ); - - // Add some transactions - let mut rng = thread_rng(); - let state = >::get_starting_state(); - let mut hashes = Vec::new(); - let mut block = block; - for _ in 0..10 { - let new = block - .add_transaction_raw(&random_transaction(&state, &mut rng)) - .expect("Could not add transaction"); - println!("Inserting {:?}: {:?}", new.hash(), new); - store - .update(|mut m| { - let new = new.clone(); - async move { m.insert_block(new.hash(), new.clone()).await } - }) - .await - .unwrap(); - hashes.push(new.hash()); - block = new; - } - - // read them all back 3 times - // 1st time: normal readback - // 2nd: after dropping and re-opening the store - for i in 0..3 { - if i == 1 { - drop(store); - store = AtomicStorage::open(path).expect("Could not open atomic store"); - } - - // read them all back - for (idx, hash) in hashes.iter().enumerate() { - match store.get_block(hash).await.expect("Could not read hash") { - Some(block) => println!("read {:?}", block), - None => panic!("Could not read hash {} {:?}", idx, hash), - } - } - } -} - #[cfg_attr( async_executor_impl = "tokio", tokio::test(flavor = "multi_thread", worker_threads = 2) diff --git a/crates/testing/tests/basic.rs b/crates/testing/tests/basic.rs index fc4b6017f7..35e75fffa7 100644 --- a/crates/testing/tests/basic.rs +++ b/crates/testing/tests/basic.rs @@ -6,13 +6,23 @@ #[cfg_attr(async_executor_impl = "async-std", async_std::test)] async fn test_success() { use hotshot_testing::{ + completion_task::{CompletionTaskDescription, TimeBasedCompletionTaskDescription}, node_types::{SequencingMemoryImpl, SequencingTestTypes}, test_builder::TestMetadata, }; + use std::time::Duration; async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); - let metadata = TestMetadata::default(); + let metadata = TestMetadata { + // allow more time to pass in CI + completion_task_description: CompletionTaskDescription::TimeBasedCompletionTaskBuilder( + TimeBasedCompletionTaskDescription { + duration: Duration::from_millis(1_200_000), + }, + ), + ..TestMetadata::default() + }; metadata .gen_launcher::() .launch() diff --git a/crates/testing/tests/catchup.rs b/crates/testing/tests/catchup.rs index 2cbc6c8a16..01610f38f2 100644 --- a/crates/testing/tests/catchup.rs +++ b/crates/testing/tests/catchup.rs @@ -59,6 +59,61 @@ async fn test_catchup() { .await; } +#[cfg(test)] +#[cfg_attr( + async_executor_impl = "tokio", + tokio::test(flavor = "multi_thread", worker_threads = 2) +)] +#[cfg_attr(async_executor_impl = "async-std", async_std::test)] +async fn test_catchup_web() { + use std::time::Duration; + + use hotshot_testing::{ + completion_task::{CompletionTaskDescription, TimeBasedCompletionTaskDescription}, + node_types::{SequencingTestTypes, SequencingWebImpl}, + overall_safety_task::OverallSafetyPropertiesDescription, + spinning_task::{ChangeNode, SpinningTaskDescription, UpDown}, + test_builder::{TestMetadata, TimingData}, + }; + + async_compatibility_layer::logging::setup_logging(); + async_compatibility_layer::logging::setup_backtrace(); + let timing_data = TimingData { + next_view_timeout: 1000, + ..Default::default() + }; + let mut metadata = TestMetadata::default(); + let catchup_nodes = vec![ChangeNode { + idx: 18, + updown: UpDown::Up, + }]; + + metadata.timing_data = timing_data; + metadata.start_nodes = 19; + metadata.total_nodes = 20; + + metadata.spinning_properties = SpinningTaskDescription { + node_changes: vec![(Duration::from_millis(400), catchup_nodes)], + }; + + metadata.completion_task_description = + CompletionTaskDescription::TimeBasedCompletionTaskBuilder( + TimeBasedCompletionTaskDescription { + duration: Duration::from_millis(100000), + }, + ); + metadata.overall_safety_properties = OverallSafetyPropertiesDescription { + check_leaf: true, + ..Default::default() + }; + + metadata + .gen_launcher::() + .launch() + .run_test() + .await; +} + /// Test that one node catches up and has sucessful views after coming back #[cfg(test)] #[cfg_attr( @@ -66,6 +121,7 @@ async fn test_catchup() { tokio::test(flavor = "multi_thread", worker_threads = 2) )] #[cfg_attr(async_executor_impl = "async-std", async_std::test)] +#[ignore] async fn test_catchup_one_node() { use std::time::Duration; @@ -94,13 +150,13 @@ async fn test_catchup_one_node() { metadata.total_nodes = 20; metadata.spinning_properties = SpinningTaskDescription { - node_changes: vec![(Duration::new(1, 0), catchup_nodes)], + node_changes: vec![(Duration::from_millis(400), catchup_nodes)], }; metadata.completion_task_description = CompletionTaskDescription::TimeBasedCompletionTaskBuilder( TimeBasedCompletionTaskDescription { - duration: Duration::from_millis(100000), + duration: Duration::from_millis(20000), }, ); metadata.overall_safety_properties = OverallSafetyPropertiesDescription { @@ -108,7 +164,7 @@ async fn test_catchup_one_node() { ..Default::default() }; // only alow for the view which the catchup node hasn't started to fail - metadata.overall_safety_properties.num_failed_views = 1; + metadata.overall_safety_properties.num_failed_views = 5; metadata .gen_launcher::() diff --git a/crates/testing/tests/da_task.rs b/crates/testing/tests/da_task.rs index 0322909203..e31c34e6aa 100644 --- a/crates/testing/tests/da_task.rs +++ b/crates/testing/tests/da_task.rs @@ -1,9 +1,13 @@ use commit::Committable; use hotshot::HotShotSequencingConsensusApi; use hotshot_task_impls::events::SequencingHotShotEvent; -use hotshot_testing::node_types::{SequencingMemoryImpl, SequencingTestTypes}; +use hotshot_testing::{ + node_types::{SequencingMemoryImpl, SequencingTestTypes}, + task_helpers::vid_init, +}; use hotshot_types::{ - data::{DAProposal, ViewNumber}, + block_impl::VIDTransaction, + data::{DAProposal, VidDisperse, VidSchemeTrait, ViewNumber}, traits::{ consensus_api::ConsensusSharedApi, election::ConsensusExchange, node_implementation::ExchangesType, state::ConsensusTime, @@ -17,15 +21,11 @@ use std::collections::HashMap; )] #[cfg_attr(async_executor_impl = "async-std", async_std::test)] async fn test_da_task() { - use hotshot::{ - demos::sdemo::{SDemoBlock, SDemoNormalBlock}, - tasks::add_da_task, - }; + use hotshot::tasks::add_da_task; use hotshot_task_impls::harness::run_harness; use hotshot_testing::task_helpers::build_system_handle; use hotshot_types::{ - message::{CommitteeConsensusMessage, Proposal}, - traits::election::CommitteeExchangeType, + block_impl::VIDBlockPayload, message::Proposal, traits::election::CommitteeExchangeType, }; async_compatibility_layer::logging::setup_logging(); @@ -39,12 +39,16 @@ async fn test_da_task() { }; let committee_exchange = api.inner.exchanges.committee_exchange().clone(); let pub_key = *api.public_key(); - let block = SDemoBlock::Normal(SDemoNormalBlock { - previous_state: (), - transactions: Vec::new(), - }); - let block_commitment = block.commit(); - let signature = committee_exchange.sign_da_proposal(&block_commitment); + let vid = vid_init(); + let txn = vec![0u8]; + let vid_disperse = vid.disperse(&txn).unwrap(); + let block_commitment = vid_disperse.commit; + let block = VIDBlockPayload { + transactions: vec![VIDTransaction(txn)], + commitment: block_commitment, + }; + + let signature = committee_exchange.sign_da_proposal(&block.commit()); let proposal = DAProposal { deltas: block.clone(), view_number: ViewNumber::new(2), @@ -53,6 +57,17 @@ async fn test_da_task() { data: proposal, signature, }; + let vid_proposal = Proposal { + data: VidDisperse { + view_number: message.data.view_number, + commitment: block.commit(), + shares: vid_disperse.shares, + common: vid_disperse.common, + }, + signature: message.signature.clone(), + }; + // TODO for now reuse the same block commitment and signature as DA committee + // https://github.com/EspressoSystems/jellyfish/issues/369 // Every event input is seen on the event stream in the output. let mut input = Vec::new(); @@ -61,26 +76,51 @@ async fn test_da_task() { // In view 1, node 2 is the next leader. input.push(SequencingHotShotEvent::ViewChange(ViewNumber::new(1))); input.push(SequencingHotShotEvent::ViewChange(ViewNumber::new(2))); + input.push(SequencingHotShotEvent::BlockReady( + block.clone(), + ViewNumber::new(2), + )); input.push(SequencingHotShotEvent::DAProposalRecv( message.clone(), pub_key, )); + input.push(SequencingHotShotEvent::VidDisperseRecv( + vid_proposal.clone(), + pub_key, + )); input.push(SequencingHotShotEvent::Shutdown); output.insert(SequencingHotShotEvent::ViewChange(ViewNumber::new(1)), 1); - output.insert(SequencingHotShotEvent::SendDABlockData(block), 1); + output.insert( + SequencingHotShotEvent::BlockReady(block.clone(), ViewNumber::new(2)), + 1, + ); + output.insert(SequencingHotShotEvent::SendDABlockData(block.clone()), 1); output.insert( SequencingHotShotEvent::DAProposalSend(message.clone(), pub_key), 1, ); - if let Ok(Some(vote_token)) = committee_exchange.make_vote_token(ViewNumber::new(2)) { - let da_message = - committee_exchange.create_da_message(block_commitment, ViewNumber::new(2), vote_token); - if let CommitteeConsensusMessage::DAVote(vote) = da_message { - output.insert(SequencingHotShotEvent::DAVoteSend(vote), 1); - } - } + let vote_token = committee_exchange + .make_vote_token(ViewNumber::new(2)) + .unwrap() + .unwrap(); + let da_vote = + committee_exchange.create_da_message(block.commit(), ViewNumber::new(2), vote_token); + output.insert(SequencingHotShotEvent::DAVoteSend(da_vote), 1); + + let vote_token = committee_exchange + .make_vote_token(ViewNumber::new(2)) + .unwrap() + .unwrap(); + let vid_vote = + committee_exchange.create_vid_message(block.commit(), ViewNumber::new(2), vote_token); + output.insert(SequencingHotShotEvent::VidVoteSend(vid_vote), 1); + output.insert(SequencingHotShotEvent::DAProposalRecv(message, pub_key), 1); + output.insert( + SequencingHotShotEvent::VidDisperseRecv(vid_proposal, pub_key), + 1, + ); output.insert(SequencingHotShotEvent::ViewChange(ViewNumber::new(2)), 1); output.insert(SequencingHotShotEvent::Shutdown, 1); diff --git a/crates/testing/tests/memory_network.rs b/crates/testing/tests/memory_network.rs new file mode 100644 index 0000000000..27f6ae6531 --- /dev/null +++ b/crates/testing/tests/memory_network.rs @@ -0,0 +1,371 @@ +use std::collections::BTreeSet; +use std::marker::PhantomData; +use std::sync::Arc; + +use async_compatibility_layer::logging::setup_logging; +use hotshot::demo::SDemoState; +use hotshot::traits::election::static_committee::{ + GeneralStaticCommittee, StaticElectionConfig, StaticVoteToken, +}; +use hotshot::traits::implementations::{ + MasterMap, MemoryCommChannel, MemoryNetwork, MemoryStorage, +}; +use hotshot::traits::NodeImplementation; +use hotshot::types::bn254::{BLSPrivKey, BLSPubKey}; +use hotshot::types::SignatureKey; +use hotshot_types::block_impl::{VIDBlockPayload, VIDTransaction}; +use hotshot_types::certificate::ViewSyncCertificate; +use hotshot_types::data::{DAProposal, QuorumProposal, SequencingLeaf}; +use hotshot_types::message::{Message, SequencingMessage}; +use hotshot_types::traits::election::{CommitteeExchange, QuorumExchange, ViewSyncExchange}; +use hotshot_types::traits::metrics::NoMetrics; +use hotshot_types::traits::network::TestableNetworkingImplementation; +use hotshot_types::traits::network::{ConnectedNetwork, TransmitType}; +use hotshot_types::traits::node_implementation::{ChannelMaps, NodeType, SequencingExchanges}; +use hotshot_types::vote::{DAVote, ViewSyncVote}; +use hotshot_types::{ + data::ViewNumber, + message::{DataMessage, MessageKind}, + traits::state::ConsensusTime, + vote::QuorumVote, +}; +use rand::rngs::StdRng; +use rand::{RngCore, SeedableRng}; +use serde::{Deserialize, Serialize}; +use tracing::instrument; +use tracing::trace; + +#[derive( + Copy, + Clone, + Debug, + Default, + Hash, + PartialEq, + Eq, + PartialOrd, + Ord, + serde::Serialize, + serde::Deserialize, +)] +pub struct Test; + +impl NodeType for Test { + type Time = ViewNumber; + type BlockType = VIDBlockPayload; + type SignatureKey = BLSPubKey; + type VoteTokenType = StaticVoteToken; + type Transaction = VIDTransaction; + type ElectionConfigType = StaticElectionConfig; + type StateType = SDemoState; +} + +#[derive(Clone, Debug, Deserialize, Serialize, Hash, PartialEq, Eq)] +pub struct TestImpl {} + +pub type ThisLeaf = SequencingLeaf; +pub type ThisMembership = GeneralStaticCommittee::SignatureKey>; +pub type DANetwork = MemoryCommChannel; +pub type QuorumNetwork = MemoryCommChannel; +pub type ViewSyncNetwork = MemoryCommChannel; + +pub type ThisDAProposal = DAProposal; +pub type ThisDAVote = DAVote; + +pub type ThisQuorumProposal = QuorumProposal; +pub type ThisQuorumVote = QuorumVote; + +pub type ThisViewSyncProposal = ViewSyncCertificate; +pub type ThisViewSyncVote = ViewSyncVote; + +impl NodeImplementation for TestImpl { + type Storage = MemoryStorage; + type Leaf = SequencingLeaf; + type Exchanges = SequencingExchanges< + Test, + Message, + QuorumExchange< + Test, + Self::Leaf, + ThisQuorumProposal, + ThisMembership, + QuorumNetwork, + Message, + >, + CommitteeExchange>, + ViewSyncExchange< + Test, + ThisViewSyncProposal, + ThisMembership, + ViewSyncNetwork, + Message, + >, + >; + type ConsensusMessage = SequencingMessage; + + fn new_channel_maps( + start_view: ::Time, + ) -> (ChannelMaps, Option>) { + (ChannelMaps::new(start_view), None) + } +} + +/// fake Eq +/// we can't compare the votetokentype for equality, so we can't +/// derive EQ on `VoteType` and thereby message +/// we are only sending data messages, though so we compare key and +/// data message +fn fake_message_eq(message_1: Message, message_2: Message) { + assert_eq!(message_1.sender, message_2.sender); + if let MessageKind::Data(DataMessage::SubmitTransaction(d_1, _)) = message_1.kind { + if let MessageKind::Data(DataMessage::SubmitTransaction(d_2, _)) = message_2.kind { + assert_eq!(d_1, d_2); + } + } else { + panic!("Got unexpected message type in memory test!"); + } +} + +#[instrument] +fn get_pubkey() -> BLSPubKey { + // random 32 bytes + let mut bytes = [0; 32]; + rand::thread_rng().fill_bytes(&mut bytes); + BLSPubKey::from_private(&BLSPrivKey::generate_from_seed(bytes)) +} + +/// create a message +fn gen_messages(num_messages: u64, seed: u64, pk: BLSPubKey) -> Vec> { + let mut messages = Vec::new(); + for _ in 0..num_messages { + // create a random transaction from seed + let mut bytes = [0u8; 8]; + let mut rng = StdRng::seed_from_u64(seed); + rng.fill_bytes(&mut bytes); + + let message = Message { + sender: pk, + kind: MessageKind::Data(DataMessage::SubmitTransaction( + VIDTransaction(bytes.to_vec()), + ::new(0), + )), + _phantom: PhantomData, + }; + messages.push(message); + } + messages +} + +// Spawning a single MemoryNetwork should produce no errors +#[cfg_attr( + async_executor_impl = "tokio", + tokio::test(flavor = "multi_thread", worker_threads = 2) +)] +#[cfg_attr(async_executor_impl = "async-std", async_std::test)] +#[instrument] +async fn memory_network_spawn_single() { + setup_logging(); + let group: Arc, ::SignatureKey>> = + MasterMap::new(); + trace!(?group); + let pub_key = get_pubkey(); + let _network = MemoryNetwork::new(pub_key, NoMetrics::boxed(), group, Option::None); +} + +// // Spawning a two MemoryNetworks and connecting them should produce no errors +#[cfg_attr( + async_executor_impl = "tokio", + tokio::test(flavor = "multi_thread", worker_threads = 2) +)] +#[cfg_attr(async_executor_impl = "async-std", async_std::test)] +#[instrument] +async fn memory_network_spawn_double() { + setup_logging(); + let group: Arc, ::SignatureKey>> = + MasterMap::new(); + trace!(?group); + let pub_key_1 = get_pubkey(); + let _network_1 = MemoryNetwork::new(pub_key_1, NoMetrics::boxed(), group.clone(), Option::None); + let pub_key_2 = get_pubkey(); + let _network_2 = MemoryNetwork::new(pub_key_2, NoMetrics::boxed(), group, Option::None); +} + +// Check to make sure direct queue works +#[cfg_attr( + async_executor_impl = "tokio", + tokio::test(flavor = "multi_thread", worker_threads = 2) +)] +#[cfg_attr(async_executor_impl = "async-std", async_std::test)] +#[instrument] +async fn memory_network_direct_queue() { + setup_logging(); + // Create some dummy messages + + // Make and connect the networking instances + let group: Arc, ::SignatureKey>> = + MasterMap::new(); + trace!(?group); + + let pub_key_1 = get_pubkey(); + let network1 = MemoryNetwork::new(pub_key_1, NoMetrics::boxed(), group.clone(), Option::None); + + let pub_key_2 = get_pubkey(); + let network2 = MemoryNetwork::new(pub_key_2, NoMetrics::boxed(), group, Option::None); + + let first_messages: Vec> = gen_messages(5, 100, pub_key_1); + + // Test 1 -> 2 + // Send messages + for sent_message in first_messages { + network1 + .direct_message(sent_message.clone(), pub_key_2) + .await + .expect("Failed to message node"); + let mut recv_messages = network2 + .recv_msgs(TransmitType::Direct) + .await + .expect("Failed to receive message"); + let recv_message = recv_messages.pop().unwrap(); + assert!(recv_messages.is_empty()); + fake_message_eq(sent_message, recv_message); + } + + let second_messages: Vec> = gen_messages(5, 200, pub_key_2); + + // Test 2 -> 1 + // Send messages + for sent_message in second_messages { + network2 + .direct_message(sent_message.clone(), pub_key_1) + .await + .expect("Failed to message node"); + let mut recv_messages = network1 + .recv_msgs(TransmitType::Direct) + .await + .expect("Failed to receive message"); + let recv_message = recv_messages.pop().unwrap(); + assert!(recv_messages.is_empty()); + fake_message_eq(sent_message, recv_message); + } +} + +// Check to make sure direct queue works +#[cfg_attr( + async_executor_impl = "tokio", + tokio::test(flavor = "multi_thread", worker_threads = 2) +)] +#[cfg_attr(async_executor_impl = "async-std", async_std::test)] +#[instrument] +async fn memory_network_broadcast_queue() { + setup_logging(); + // Make and connect the networking instances + let group: Arc, ::SignatureKey>> = + MasterMap::new(); + trace!(?group); + let pub_key_1 = get_pubkey(); + let network1 = MemoryNetwork::new(pub_key_1, NoMetrics::boxed(), group.clone(), Option::None); + let pub_key_2 = get_pubkey(); + let network2 = MemoryNetwork::new(pub_key_2, NoMetrics::boxed(), group, Option::None); + + let first_messages: Vec> = gen_messages(5, 100, pub_key_1); + + // Test 1 -> 2 + // Send messages + for sent_message in first_messages { + network1 + .broadcast_message( + sent_message.clone(), + vec![pub_key_2].into_iter().collect::>(), + ) + .await + .expect("Failed to message node"); + let mut recv_messages = network2 + .recv_msgs(TransmitType::Broadcast) + .await + .expect("Failed to receive message"); + let recv_message = recv_messages.pop().unwrap(); + assert!(recv_messages.is_empty()); + fake_message_eq(sent_message, recv_message); + } + + let second_messages: Vec> = gen_messages(5, 200, pub_key_2); + + // Test 2 -> 1 + // Send messages + for sent_message in second_messages { + network2 + .broadcast_message( + sent_message.clone(), + vec![pub_key_1].into_iter().collect::>(), + ) + .await + .expect("Failed to message node"); + let mut recv_messages = network1 + .recv_msgs(TransmitType::Broadcast) + .await + .expect("Failed to receive message"); + let recv_message = recv_messages.pop().unwrap(); + assert!(recv_messages.is_empty()); + fake_message_eq(sent_message, recv_message); + } +} + +#[cfg_attr( + async_executor_impl = "tokio", + tokio::test(flavor = "multi_thread", worker_threads = 2) +)] +#[cfg_attr(async_executor_impl = "async-std", async_std::test)] +#[instrument] +#[allow(deprecated)] +async fn memory_network_test_in_flight_message_count() { + setup_logging(); + + let group: Arc, ::SignatureKey>> = + MasterMap::new(); + trace!(?group); + let pub_key_1 = get_pubkey(); + let network1 = MemoryNetwork::new(pub_key_1, NoMetrics::boxed(), group.clone(), Option::None); + let pub_key_2 = get_pubkey(); + let network2 = MemoryNetwork::new(pub_key_2, NoMetrics::boxed(), group, Option::None); + + // Create some dummy messages + let messages: Vec> = gen_messages(5, 100, pub_key_1); + let broadcast_recipients = BTreeSet::from([pub_key_1, pub_key_2]); + + assert_eq!(network1.in_flight_message_count(), Some(0)); + assert_eq!(network2.in_flight_message_count(), Some(0)); + + for (count, message) in messages.iter().enumerate() { + network1 + .direct_message(message.clone(), pub_key_2) + .await + .unwrap(); + // network 2 has received `count` broadcast messages and `count + 1` direct messages + assert_eq!(network2.in_flight_message_count(), Some(count + count + 1)); + + network2 + .broadcast_message(message.clone(), broadcast_recipients.clone()) + .await + .unwrap(); + // network 1 has received `count` broadcast messages + assert_eq!(network1.in_flight_message_count(), Some(count + 1)); + + // network 2 has received `count + 1` broadcast messages and `count + 1` direct messages + assert_eq!(network2.in_flight_message_count(), Some((count + 1) * 2)); + } + + while network1.in_flight_message_count().unwrap() > 0 { + network1.recv_msgs(TransmitType::Broadcast).await.unwrap(); + } + + while network2.in_flight_message_count().unwrap() > messages.len() { + network2.recv_msgs(TransmitType::Direct).await.unwrap(); + } + + while network2.in_flight_message_count().unwrap() > 0 { + network2.recv_msgs(TransmitType::Broadcast).await.unwrap(); + } + + assert_eq!(network1.in_flight_message_count(), Some(0)); + assert_eq!(network2.in_flight_message_count(), Some(0)); +} diff --git a/crates/testing/tests/network_task.rs b/crates/testing/tests/network_task.rs index aa0c80024f..c4165a8c31 100644 --- a/crates/testing/tests/network_task.rs +++ b/crates/testing/tests/network_task.rs @@ -3,10 +3,10 @@ use hotshot::HotShotSequencingConsensusApi; use hotshot_task_impls::events::SequencingHotShotEvent; use hotshot_testing::{ node_types::{SequencingMemoryImpl, SequencingTestTypes}, - task_helpers::build_quorum_proposal, + task_helpers::{build_quorum_proposal, vid_init}, }; use hotshot_types::{ - data::{DAProposal, ViewNumber}, + data::{DAProposal, VidSchemeTrait, ViewNumber}, traits::{ consensus_api::ConsensusSharedApi, node_implementation::ExchangesType, state::ConsensusTime, }, @@ -21,10 +21,14 @@ use std::collections::HashMap; #[cfg_attr(async_executor_impl = "async-std", async_std::test)] #[ignore] async fn test_network_task() { - use hotshot::demos::sdemo::{SDemoBlock, SDemoNormalBlock}; use hotshot_task_impls::harness::run_harness; use hotshot_testing::task_helpers::build_system_handle; - use hotshot_types::{message::Proposal, traits::election::CommitteeExchangeType}; + use hotshot_types::{ + block_impl::{VIDBlockPayload, VIDTransaction}, + data::VidDisperse, + message::Proposal, + traits::election::CommitteeExchangeType, + }; async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); @@ -38,12 +42,15 @@ async fn test_network_task() { let committee_exchange = api.inner.exchanges.committee_exchange().clone(); let pub_key = *api.public_key(); let priv_key = api.private_key(); - let block = SDemoBlock::Normal(SDemoNormalBlock { - previous_state: (), - transactions: Vec::new(), - }); - let block_commitment = block.commit(); - let signature = committee_exchange.sign_da_proposal(&block_commitment); + let vid = vid_init(); + let txn = vec![0u8]; + let vid_disperse = vid.disperse(&txn).unwrap(); + let block_commitment = vid_disperse.commit; + let block = VIDBlockPayload { + transactions: vec![VIDTransaction(txn)], + commitment: block_commitment, + }; + let signature = committee_exchange.sign_da_proposal(&block.commit()); let da_proposal = Proposal { data: DAProposal { deltas: block.clone(), @@ -52,16 +59,35 @@ async fn test_network_task() { signature, }; let quorum_proposal = build_quorum_proposal(&handle, priv_key, 2).await; + // TODO for now reuse the same block commitment and signature as DA committee + // https://github.com/EspressoSystems/jellyfish/issues/369 + let da_vid_disperse = Proposal { + data: VidDisperse { + view_number: da_proposal.data.view_number, + commitment: block.commit(), + shares: vid_disperse.shares, + common: vid_disperse.common, + }, + signature: da_proposal.signature.clone(), + }; // Every event input is seen on the event stream in the output. let mut input = Vec::new(); let mut output = HashMap::new(); input.push(SequencingHotShotEvent::ViewChange(ViewNumber::new(1))); + input.push(SequencingHotShotEvent::BlockReady( + block.clone(), + ViewNumber::new(2), + )); input.push(SequencingHotShotEvent::DAProposalSend( da_proposal.clone(), pub_key, )); + input.push(SequencingHotShotEvent::VidDisperseSend( + da_vid_disperse.clone(), + pub_key, + )); input.push(SequencingHotShotEvent::QuorumProposalSend( quorum_proposal.clone(), pub_key, @@ -70,11 +96,25 @@ async fn test_network_task() { input.push(SequencingHotShotEvent::Shutdown); output.insert(SequencingHotShotEvent::ViewChange(ViewNumber::new(1)), 2); - // One output from the input, the other from the DA task. output.insert( SequencingHotShotEvent::DAProposalSend(da_proposal.clone(), pub_key), + 2, // 2 occurrences: 1 from `input`, 1 from the DA task + ); + output.insert( + SequencingHotShotEvent::BlockReady(block.clone(), ViewNumber::new(2)), 2, ); + output.insert( + SequencingHotShotEvent::VidDisperseRecv(da_vid_disperse.clone(), pub_key), + 1, + ); + output.insert( + SequencingHotShotEvent::VidDisperseSend(da_vid_disperse, pub_key), + 2, // 2 occurrences: 1 from `input`, 1 from the DA task + ); + output.insert(SequencingHotShotEvent::Timeout(ViewNumber::new(1)), 1); + output.insert(SequencingHotShotEvent::Timeout(ViewNumber::new(2)), 1); + // Only one output from the input. // The consensus task will fail to send a second proposal, like the DA task does, due to the // view number check in `publish_proposal_if_able` in consensus.rs, and we will see an error in diff --git a/crates/testing/tests/timeout.rs b/crates/testing/tests/timeout.rs index 7ebeddd577..f8963c9d52 100644 --- a/crates/testing/tests/timeout.rs +++ b/crates/testing/tests/timeout.rs @@ -30,7 +30,7 @@ async fn test_timeout() { metadata.timing_data = timing_data; metadata.spinning_properties = SpinningTaskDescription { - node_changes: vec![(Duration::new(1, 0), dead_nodes)], + node_changes: vec![(Duration::new(0, 5000), dead_nodes)], }; // TODO ED Add safety task, etc to confirm TCs are being formed diff --git a/crates/types/Cargo.toml b/crates/types/Cargo.toml index f65eac0983..c0eb7a11e0 100644 --- a/crates/types/Cargo.toml +++ b/crates/types/Cargo.toml @@ -8,16 +8,17 @@ version = "0.1.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] -demo = ["ed25519-compact"] +demo = [] [dependencies] arbitrary = { version = "1.3", features = ["derive"] } +ark-bls12-381 = { workspace = true } async-compatibility-layer = { workspace = true } async-lock = { workspace = true } async-trait = { workspace = true } ark-serialize = { version = "0.3", features = [ "derive", -] } # TODO GG upgrade to 0.4 and inherit this dep from workspace +] } # TODO upgrade to 0.4 and inherit this dep from workspace https://github.com/EspressoSystems/HotShot/issues/1700 ark-std = { workspace = true } bincode = { workspace = true } bitvec = { workspace = true } @@ -27,30 +28,31 @@ custom_debug = { workspace = true } derivative = "2.2.0" digest = { workspace = true } displaydoc = { version = "0.2.3", default-features = false } -ed25519-compact = { version = "2.0.4", optional = true } either = { workspace = true, features = ["serde"] } espresso-systems-common = { workspace = true } futures = { workspace = true } -generic-array = "0.14.7" +generic-array = { workspace = true } hex_fmt = "0.3.0" +hotshot-constants = { path = "../constants" } hotshot-utils = { path = "../utils" } hotshot-task = { path = "../task", default-features = false } -jf-primitives = { workspace = true } -nll = { workspace = true } +jf-primitives = { workspace = true, features = ["test-srs"] } +jf-utils = { workspace = true } libp2p-networking = { workspace = true } rand = { workspace = true } rand_chacha = { workspace = true } serde = { workspace = true } +sha2 = { workspace = true } +sha3 = "^0.10" snafu = { workspace = true } tagged-base64 = { git = "https://github.com/EspressoSystems/tagged-base64", tag = "0.2.4" } time = { workspace = true } tracing = { workspace = true } ethereum-types = { workspace = true } -bit-vec = "0.6.3" typenum = { workspace = true } [dev-dependencies] -serde_json = "1.0.106" +serde_json = "1.0.107" [target.'cfg(all(async_executor_impl = "async-std"))'.dependencies] async-std = { workspace = true } diff --git a/crates/types/src/block_impl.rs b/crates/types/src/block_impl.rs new file mode 100644 index 0000000000..2360cb3a24 --- /dev/null +++ b/crates/types/src/block_impl.rs @@ -0,0 +1,127 @@ +//! This module provides an implementation of the `HotShot` suite of traits. +use std::{ + collections::HashSet, + fmt::{Debug, Display}, +}; + +use crate::{ + data::{test_srs, VidScheme, VidSchemeTrait}, + traits::{block_contents::Transaction, state::TestableBlock, BlockPayload}, +}; +use commit::{Commitment, Committable}; +use serde::{Deserialize, Serialize}; +use sha3::{Digest, Keccak256}; +use snafu::Snafu; + +// TODO +/// Number of storage nodes for VID initiation. +pub const NUM_STORAGE_NODES: usize = 10; +// TODO +/// Number of chunks for VID initiation. +pub const NUM_CHUNKS: usize = 5; + +/// The transaction in a [`VIDBlockPayload`]. +#[derive(Default, PartialEq, Eq, Hash, Serialize, Deserialize, Clone, Debug)] +pub struct VIDTransaction(pub Vec); + +impl Committable for VIDTransaction { + fn commit(&self) -> Commitment { + let builder = commit::RawCommitmentBuilder::new("Txn Comm"); + let mut hasher = Keccak256::new(); + hasher.update(&self.0); + let generic_array = hasher.finalize(); + builder.generic_byte_array(&generic_array).finalize() + } + + fn tag() -> String { + "SEQUENCING_TXN".to_string() + } +} + +impl Transaction for VIDTransaction {} + +/// The error type for block payload. +#[derive(Snafu, Debug)] +pub enum BlockPayloadError { + /// Previous state commitment does not match + PreviousStateMismatch, + /// Nonce was reused + ReusedTxn, + /// Genesis failure + GenesisFailed, + /// Genesis reencountered after initialization + GenesisAfterStart, + /// invalid block + InvalidBlock, +} + +/// A [`BlockPayload`] that contains a list of `VIDTransaction`. +#[derive(PartialEq, Eq, Hash, Serialize, Deserialize, Clone, Debug)] +pub struct VIDBlockPayload { + /// List of transactions. + pub transactions: Vec, + /// VID commitment. + pub commitment: ::Commit, +} + +impl VIDBlockPayload { + /// Create a genesis block payload with transaction bytes `vec![0]`, to be used for + /// consensus task initiation. + /// # Panics + /// If the `VidScheme` construction fails. + #[must_use] + pub fn genesis() -> Self { + // TODO + let srs = test_srs(NUM_STORAGE_NODES); + // TODO We are using constant numbers for now, but they will change as the quorum size + // changes. + // TODO + let vid = VidScheme::new(NUM_CHUNKS, NUM_STORAGE_NODES, &srs).unwrap(); + let txn = vec![0]; + let vid_disperse = vid.disperse(&txn).unwrap(); + VIDBlockPayload { + transactions: vec![VIDTransaction(txn)], + commitment: vid_disperse.commit, + } + } +} + +impl Committable for VIDBlockPayload { + fn commit(&self) -> Commitment { + let builder = commit::RawCommitmentBuilder::new("BlockPayload Comm"); + builder.generic_byte_array(&self.commitment).finalize() + } + + fn tag() -> String { + "VID_BLOCK_PAYLOAD".to_string() + } +} + +impl Display for VIDBlockPayload { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "BlockPayload #txns={}", self.transactions.len()) + } +} + +impl TestableBlock for VIDBlockPayload { + fn genesis() -> Self { + Self::genesis() + } + + fn txn_count(&self) -> u64 { + self.transactions.len() as u64 + } +} + +impl BlockPayload for VIDBlockPayload { + type Error = BlockPayloadError; + + type Transaction = VIDTransaction; + + fn contained_transactions(&self) -> HashSet> { + self.transactions + .iter() + .map(commit::Committable::commit) + .collect() + } +} diff --git a/crates/types/src/certificate.rs b/crates/types/src/certificate.rs index 47720eba75..09c3235744 100644 --- a/crates/types/src/certificate.rs +++ b/crates/types/src/certificate.rs @@ -1,22 +1,29 @@ //! Provides two types of cerrtificates and their accumulators. +use crate::vote::DAVoteAccumulator; +use crate::vote::QuorumVote; +use crate::vote::QuorumVoteAccumulator; +use crate::vote::ViewSyncVoteAccumulator; +use crate::vote::VoteType; use crate::{ - data::{fake_commitment, serialize_signature, LeafType}, + data::serialize_signature, traits::{ election::{SignedCertificate, VoteData, VoteToken}, node_implementation::NodeType, signature_key::{EncodedPublicKey, EncodedSignature, SignatureKey}, state::ConsensusTime, }, - vote::ViewSyncData, + vote::{DAVote, ViewSyncData, ViewSyncVote}, }; use bincode::Options; -use commit::{Commitment, Committable}; +use commit::{Commitment, CommitmentBounds, Committable}; + use espresso_systems_common::hotshot::tag; use hotshot_utils::bincode::bincode_opts; use serde::{Deserialize, Serialize}; use std::{ fmt::{self, Debug, Display, Formatter}, + hash::Hash, ops::Deref, }; use tracing::debug; @@ -43,12 +50,12 @@ pub struct DACertificate { /// /// A Quorum Certificate is a threshold signature of the `Leaf` being proposed, as well as some /// metadata, such as the `Stage` of consensus the quorum certificate was generated during. -#[derive(custom_debug::Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Hash)] +#[derive(custom_debug::Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Hash, Eq)] #[serde(bound(deserialize = ""))] -pub struct QuorumCertificate> { +pub struct QuorumCertificate { /// commitment to previous leaf #[debug(skip)] - pub leaf_commitment: Commitment, + pub leaf_commitment: COMMITMENT, /// Which view this QC relates to pub view_number: TYPES::Time, /// assembled signature for certificate aggregation @@ -57,7 +64,9 @@ pub struct QuorumCertificate> pub is_genesis: bool, } -impl> Display for QuorumCertificate { +impl Display + for QuorumCertificate +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!( f, @@ -132,15 +141,15 @@ pub enum AssembledSignature { } /// Data from a vote needed to accumulate into a `SignedCertificate` -pub struct VoteMetaData { +pub struct VoteMetaData { /// Voter's public key pub encoded_key: EncodedPublicKey, /// Votes signature pub encoded_signature: EncodedSignature, /// Commitment to what's voted on. E.g. the leaf for a `QuorumCertificate` - pub commitment: Commitment, + pub commitment: COMMITMENT, /// Data of the vote, yes, no, timeout, or DA - pub data: VoteData, + pub data: VoteData, /// The votes's token pub vote_token: T, /// View number for the vote @@ -150,19 +159,26 @@ pub struct VoteMetaData, } -impl> - SignedCertificate - for QuorumCertificate +impl + SignedCertificate + for QuorumCertificate { + type Vote = QuorumVote; + type VoteAccumulator = QuorumVoteAccumulator; + fn from_signatures_and_commitment( - view_number: TYPES::Time, signatures: AssembledSignature, - commit: Commitment, - _relay: Option, + vote: Self::Vote, ) -> Self { + let leaf_commitment = match vote.clone() { + QuorumVote::Yes(vote_internal) | QuorumVote::No(vote_internal) => { + vote_internal.leaf_commitment + } + QuorumVote::Timeout(_) => unimplemented!(), + }; let qc = QuorumCertificate { - leaf_commitment: commit, - view_number, + leaf_commitment, + view_number: vote.get_view(), signatures, is_genesis: false, }; @@ -178,11 +194,11 @@ impl> self.signatures.clone() } - fn leaf_commitment(&self) -> Commitment { + fn leaf_commitment(&self) -> COMMITMENT { self.leaf_commitment } - fn set_leaf_commitment(&mut self, commitment: Commitment) { + fn set_leaf_commitment(&mut self, commitment: COMMITMENT) { self.leaf_commitment = commitment; } @@ -191,8 +207,9 @@ impl> } fn genesis() -> Self { + // TODO GG need a new way to get fake commit now that we don't have Committable Self { - leaf_commitment: fake_commitment::(), + leaf_commitment: COMMITMENT::default_commitment_no_preimage(), view_number: ::genesis(), signatures: AssembledSignature::Genesis(), is_genesis: true, @@ -200,16 +217,14 @@ impl> } } -impl> Eq for QuorumCertificate {} - -impl> Committable - for QuorumCertificate +impl Committable + for QuorumCertificate { fn commit(&self) -> Commitment { let signatures_bytes = serialize_signature(&self.signatures); commit::RawCommitmentBuilder::new("Quorum Certificate Commitment") - .field("leaf commitment", self.leaf_commitment) + .var_size_field("leaf commitment", self.leaf_commitment.as_ref()) .u64_field("view number", *self.view_number.deref()) .constant_str("justify_qc signatures") .var_size_bytes(&signatures_bytes) @@ -221,19 +236,21 @@ impl> Committable } } -impl SignedCertificate +impl + SignedCertificate> for DACertificate { + type Vote = DAVote; + type VoteAccumulator = DAVoteAccumulator, Self::Vote>; + fn from_signatures_and_commitment( - view_number: TYPES::Time, signatures: AssembledSignature, - commit: Commitment, - _relay: Option, + vote: Self::Vote, ) -> Self { DACertificate { - view_number, + view_number: vote.get_view(), signatures, - block_commitment: commit, + block_commitment: vote.block_commitment, } } @@ -309,19 +326,20 @@ impl Committable for ViewSyncCertificate { } impl - SignedCertificate> + SignedCertificate>> for ViewSyncCertificate { + type Vote = ViewSyncVote; + type VoteAccumulator = + ViewSyncVoteAccumulator>, Self::Vote>; /// Build a QC from the threshold signature and commitment fn from_signatures_and_commitment( - view_number: TYPES::Time, signatures: AssembledSignature, - _commit: Commitment>, - relay: Option, + vote: Self::Vote, ) -> Self { let certificate_internal = ViewSyncCertificateInternal { - round: view_number, - relay: relay.unwrap(), + round: vote.get_view(), + relay: vote.relay(), signatures: signatures.clone(), }; match signatures { diff --git a/crates/types/src/consensus.rs b/crates/types/src/consensus.rs index a29c840056..e10900aa7e 100644 --- a/crates/types/src/consensus.rs +++ b/crates/types/src/consensus.rs @@ -2,8 +2,6 @@ pub use crate::traits::node_implementation::ViewQueue; pub use crate::utils::{View, ViewInner}; -use async_compatibility_layer::async_primitives::subscribable_rwlock::SubscribableRwLock; -use std::collections::HashSet; use crate::utils::Terminator; use crate::{ @@ -41,12 +39,6 @@ pub struct Consensus> { /// last view had a successful decide event pub last_decided_view: TYPES::Time, - /// A list of undecided transactions - pub transactions: Arc>>, - - /// A list of transactions we've seen decided, but didn't receive - pub seen_transactions: HashSet>, - /// Map of leaf hash -> leaf /// - contains undecided leaves /// - includes the MOST RECENT decided leaf @@ -61,7 +53,7 @@ pub struct Consensus> { pub locked_view: TYPES::Time, /// the highqc per spec - pub high_qc: QuorumCertificate, + pub high_qc: QuorumCertificate>, /// A reference to the metrics trait #[debug(skip)] @@ -264,12 +256,6 @@ impl> Consensus { self.state_map = self.state_map.split_off(&new_anchor_view); } - /// return a clone of the internal storage of unclaimed transactions - #[must_use] - pub fn get_transactions(&self) -> Arc>> { - self.transactions.clone() - } - /// Gets the last decided state /// # Panics /// if the last decided view's state does not exist in the state map diff --git a/crates/types/src/constants.rs b/crates/types/src/constants.rs deleted file mode 100644 index 26acfb1abc..0000000000 --- a/crates/types/src/constants.rs +++ /dev/null @@ -1,14 +0,0 @@ -//! configurable constants for hotshot - -use crate::traits::signature_key::EncodedPublicKey; - -/// the number of views to gather information for ahead of time -pub const LOOK_AHEAD: u64 = 5; - -/// the genesis proposer pk -/// unfortunately need to allocate on the heap (for vec), so this ends up as a function instead of a -/// const -#[must_use] -pub fn genesis_proposer_id() -> EncodedPublicKey { - EncodedPublicKey(vec![4, 2]) -} diff --git a/crates/types/src/data.rs b/crates/types/src/data.rs index 68fc0ec064..44a1937161 100644 --- a/crates/types/src/data.rs +++ b/crates/types/src/data.rs @@ -8,23 +8,24 @@ use crate::{ AssembledSignature, DACertificate, QuorumCertificate, TimeoutCertificate, ViewSyncCertificate, }, - constants::genesis_proposer_id, traits::{ - election::SignedCertificate, node_implementation::NodeType, signature_key::{EncodedPublicKey, SignatureKey}, state::{ConsensusTime, TestableBlock, TestableState}, storage::StoredView, - Block, State, + BlockPayload, State, }, }; +use ark_bls12_381::Bls12_381; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Read, SerializationError, Write}; use bincode::Options; use commit::{Commitment, Committable}; use derivative::Derivative; use either::Either; use espresso_systems_common::hotshot::tag; +use hotshot_constants::GENESIS_PROPOSER_ID; use hotshot_utils::bincode::bincode_opts; +use jf_primitives::pcs::{checked_fft_size, prelude::UnivariateKzgPCS, PolynomialCommitmentScheme}; use rand::Rng; use serde::{Deserialize, Serialize}; use snafu::{ensure, Snafu}; @@ -100,8 +101,14 @@ impl std::ops::Sub for ViewNumber { } } +/// Generate the genesis block proposer ID from the defined constant +#[must_use] +pub fn genesis_proposer_id() -> EncodedPublicKey { + EncodedPublicKey(GENESIS_PROPOSER_ID.to_vec()) +} + /// The `Transaction` type associated with a `State`, as a syntactic shortcut -pub type Transaction = <::BlockType as Block>::Transaction; +pub type Transaction = <::BlockType as BlockPayload>::Transaction; /// `Commitment` to the `Transaction` type associated with a `State`, as a syntactic shortcut pub type TxnCommitment = Commitment>; @@ -124,21 +131,21 @@ where pub height: u64, /// Per spec, justification - pub justify_qc: QuorumCertificate, + pub justify_qc: QuorumCertificate>, /// The hash of the parent `Leaf` /// So we can ask if it extends #[debug(skip)] pub parent_commitment: Commitment, - /// Block leaf wants to apply + /// BlockPayload leaf wants to apply pub deltas: TYPES::BlockType, /// What the state should be after applying `self.deltas` pub state_commitment: Commitment, /// Transactions that were marked for rejection while collecting deltas - pub rejected: Vec<::Transaction>, + pub rejected: Vec<::Transaction>, /// the propser id pub proposer_id: EncodedPublicKey, @@ -147,12 +154,50 @@ where /// A proposal to start providing data availability for a block. #[derive(custom_debug::Debug, Serialize, Deserialize, Clone, Eq, PartialEq, Hash)] pub struct DAProposal { - /// Block leaf wants to apply + /// BlockPayload leaf wants to apply pub deltas: TYPES::BlockType, /// View this proposal applies to pub view_number: TYPES::Time, } +/// The VID scheme type used in `HotShot`. +pub type VidScheme = jf_primitives::vid::advz::Advz; +pub use jf_primitives::vid::VidScheme as VidSchemeTrait; + +/// VID dispersal data +/// +/// Like [`DAProposal`]. +#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq, Hash)] +pub struct VidDisperse { + /// The view number for which this VID data is intended + pub view_number: TYPES::Time, + /// Block commitment + pub commitment: Commitment, + /// VID shares dispersed among storage nodes + pub shares: Vec<::Share>, + /// VID common data sent to all storage nodes + pub common: ::Common, +} + +/// Trusted KZG setup for VID. +/// +/// TESTING ONLY: don't use this in production +/// TODO +/// +/// # Panics +/// ...because this is only for tests. This comment exists to pacify clippy. +#[must_use] +pub fn test_srs( + num_storage_nodes: usize, +) -> as PolynomialCommitmentScheme>::SRS { + let mut rng = jf_utils::test_rng(); + UnivariateKzgPCS::::gen_srs_for_testing( + &mut rng, + checked_fft_size(num_storage_nodes).unwrap(), + ) + .unwrap() +} + /// Proposal to append a block. #[derive(custom_debug::Debug, Serialize, Deserialize, Clone, Eq, PartialEq, Hash)] #[serde(bound(deserialize = ""))] @@ -167,7 +212,7 @@ pub struct QuorumProposal> { pub height: u64, /// Per spec, justification - pub justify_qc: QuorumCertificate, + pub justify_qc: QuorumCertificate>, /// Possible timeout certificate. Only present if the justify_qc is not for the preceding view pub timeout_certificate: Option>, @@ -196,6 +241,13 @@ impl ProposalType for DAProposal { } } +impl ProposalType for VidDisperse { + type NodeType = TYPES; + fn get_view_number(&self) -> ::Time { + self.view_number + } +} + impl> ProposalType for QuorumProposal { @@ -233,14 +285,14 @@ pub trait ProposalType: /// full. It is guaranteed to contain, at least, a cryptographic commitment to the block, and it /// provides an interface for resolving the commitment to a full block if the full block is /// available. -pub trait DeltasType: +pub trait DeltasType: Clone + Debug + for<'a> Deserialize<'a> + PartialEq + Eq + std::hash::Hash + Send + Serialize + Sync { /// Errors reported by this type. type Error: std::error::Error; /// Get a cryptographic commitment to the block represented by this delta. - fn block_commitment(&self) -> Commitment; + fn block_commitment(&self) -> Commitment; /// Get the full block if it is available, otherwise return this object unchanged. /// @@ -248,7 +300,7 @@ pub trait DeltasType: /// /// Returns the original [`DeltasType`], unchanged, in an [`Err`] variant in the case where the /// full block is not currently available. - fn try_resolve(self) -> Result; + fn try_resolve(self) -> Result; /// Fill this [`DeltasType`] by providing a complete block. /// @@ -259,7 +311,7 @@ pub trait DeltasType: /// /// Fails if `block` does not match `self.block_commitment()`, or if the block is not able to be /// stored for some implementation-defined reason. - fn fill(&mut self, block: Block) -> Result<(), Self::Error>; + fn fill(&mut self, block: BlockPayload) -> Result<(), Self::Error>; } /// Error which occurs when [`DeltasType::fill`] is called with a block that does not match the @@ -389,7 +441,7 @@ pub trait LeafType: /// Create a new leaf from its components. fn new( view_number: LeafTime, - justify_qc: QuorumCertificate, + justify_qc: QuorumCertificate>, deltas: LeafBlock, state: LeafState, ) -> Self; @@ -402,7 +454,7 @@ pub trait LeafType: /// Change the height of this leaf. fn set_height(&mut self, height: u64); /// The QC linking this leaf to its parent in the chain. - fn get_justify_qc(&self) -> QuorumCertificate; + fn get_justify_qc(&self) -> QuorumCertificate>; /// Commitment to this leaf's parent. fn get_parent_commitment(&self) -> Commitment; /// The block contained in this leaf. @@ -442,10 +494,10 @@ pub type LeafDeltasError = as DeltasType pub type LeafNode = ::NodeType; /// The [`StateType`] in a [`LeafType`]. pub type LeafState = as NodeType>::StateType; -/// The [`Block`] in a [`LeafType`]. +/// The [`BlockPayload`] in a [`LeafType`]. pub type LeafBlock = as NodeType>::BlockType; /// The [`Transaction`] in a [`LeafType`]. -pub type LeafTransaction = as Block>::Transaction; +pub type LeafTransaction = as BlockPayload>::Transaction; /// The [`ConsensusTime`] used by a [`LeafType`]. pub type LeafTime = as NodeType>::Time; @@ -459,12 +511,12 @@ pub trait TestableLeaf { &self, rng: &mut dyn rand::RngCore, padding: u64, - ) -> <::BlockType as Block>::Transaction; + ) -> <::BlockType as BlockPayload>::Transaction; } /// This is the consensus-internal analogous concept to a block, and it contains the block proper, /// as well as the hash of its parent `Leaf`. -/// NOTE: `State` is constrained to implementing `BlockContents`, is `TypeMap::Block` +/// NOTE: `State` is constrained to implementing `BlockContents`, is `TypeMap::BlockPayload` #[derive(Serialize, Deserialize, Clone, Debug, Derivative)] #[serde(bound(deserialize = ""))] #[derivative(Hash, PartialEq, Eq)] @@ -476,20 +528,20 @@ pub struct ValidatingLeaf { pub height: u64, /// Per spec, justification - pub justify_qc: QuorumCertificate, + pub justify_qc: QuorumCertificate>, /// The hash of the parent `Leaf` /// So we can ask if it extends - pub parent_commitment: Commitment>, + pub parent_commitment: Commitment, - /// Block leaf wants to apply + /// BlockPayload leaf wants to apply pub deltas: TYPES::BlockType, /// What the state should be AFTER applying `self.deltas` pub state: TYPES::StateType, /// Transactions that were marked for rejection while collecting deltas - pub rejected: Vec<::Transaction>, + pub rejected: Vec<::Transaction>, /// the timestamp the leaf was constructed at, in nanoseconds. Only exposed for dashboard stats #[derivative(PartialEq = "ignore")] @@ -504,7 +556,7 @@ pub struct ValidatingLeaf { /// This is the consensus-internal analogous concept to a block, and it contains the block proper, /// as well as the hash of its parent `Leaf`. -/// NOTE: `State` is constrained to implementing `BlockContents`, is `TypeMap::Block` +/// NOTE: `State` is constrained to implementing `BlockContents`, is `TypeMap::BlockPayload` #[derive(Serialize, Deserialize, Clone, Debug, Derivative, Eq)] #[serde(bound(deserialize = ""))] pub struct SequencingLeaf { @@ -515,17 +567,17 @@ pub struct SequencingLeaf { pub height: u64, /// Per spec, justification - pub justify_qc: QuorumCertificate, + pub justify_qc: QuorumCertificate>, /// The hash of the parent `SequencingLeaf` /// So we can ask if it extends - pub parent_commitment: Commitment>, + pub parent_commitment: Commitment, /// The block or block commitment to be applied pub deltas: Either>, /// Transactions that were marked for rejection while collecting deltas - pub rejected: Vec<::Transaction>, + pub rejected: Vec<::Transaction>, /// the timestamp the leaf was constructed at, in nanoseconds. Only exposed for dashboard stats pub timestamp: i128, @@ -589,7 +641,7 @@ impl LeafType for ValidatingLeaf { fn new( view_number: ::Time, - justify_qc: QuorumCertificate, + justify_qc: QuorumCertificate>, deltas: ::BlockType, state: ::StateType, ) -> Self { @@ -618,7 +670,7 @@ impl LeafType for ValidatingLeaf { self.height = height; } - fn get_justify_qc(&self) -> QuorumCertificate { + fn get_justify_qc(&self) -> QuorumCertificate> { self.justify_qc.clone() } @@ -642,7 +694,7 @@ impl LeafType for ValidatingLeaf { self.state.clone() } - fn get_rejected(&self) -> Vec<::Transaction> { + fn get_rejected(&self) -> Vec<::Transaction> { self.rejected.clone() } @@ -680,7 +732,7 @@ where &self, rng: &mut dyn rand::RngCore, padding: u64, - ) -> <::BlockType as Block>::Transaction { + ) -> <::BlockType as BlockPayload>::Transaction { ::create_random_transaction( Some(&self.state), rng, @@ -706,7 +758,7 @@ impl LeafType for SequencingLeaf { fn new( view_number: ::Time, - justify_qc: QuorumCertificate, + justify_qc: QuorumCertificate>, deltas: ::BlockType, _state: ::StateType, ) -> Self { @@ -734,7 +786,7 @@ impl LeafType for SequencingLeaf { self.height = height; } - fn get_justify_qc(&self) -> QuorumCertificate { + fn get_justify_qc(&self) -> QuorumCertificate> { self.justify_qc.clone() } @@ -757,7 +809,7 @@ impl LeafType for SequencingLeaf { // The Sequencing Leaf doesn't have a state. fn get_state(&self) -> Self::MaybeState {} - fn get_rejected(&self) -> Vec<::Transaction> { + fn get_rejected(&self) -> Vec<::Transaction> { self.rejected.clone() } @@ -794,7 +846,7 @@ where &self, rng: &mut dyn rand::RngCore, padding: u64, - ) -> <::BlockType as Block>::Transaction { + ) -> <::BlockType as BlockPayload>::Transaction { TYPES::StateType::create_random_transaction(None, rng, padding) } } @@ -879,7 +931,7 @@ impl Committable for ValidatingLeaf { .u64(*self.justify_qc.view_number) .field( "justify_qc leaf commitment", - self.justify_qc.leaf_commitment(), + self.justify_qc.leaf_commitment, ) .constant_str("justify_qc signatures") .var_size_bytes(&signatures_bytes) @@ -911,7 +963,7 @@ impl Committable for SequencingLeaf { .u64(*self.justify_qc.view_number) .field( "justify_qc leaf commitment", - self.justify_qc.leaf_commitment(), + self.justify_qc.leaf_commitment, ) .constant_str("justify_qc signatures") .var_size_bytes(&signatures_bytes) diff --git a/crates/types/src/event.rs b/crates/types/src/event.rs index f33a39f8cd..5d091cd400 100644 --- a/crates/types/src/event.rs +++ b/crates/types/src/event.rs @@ -4,6 +4,7 @@ use crate::{ certificate::QuorumCertificate, data::LeafType, error::HotShotError, traits::node_implementation::NodeType, }; +use commit::Commitment; use std::sync::Arc; /// A status event emitted by a `HotShot` instance /// @@ -42,7 +43,7 @@ pub enum EventType> { /// /// Note that the QC for each additional leaf in the chain can be obtained from the leaf /// before it using - qc: Arc>, + qc: Arc>>, /// Optional information of the number of transactions in the block, for logging purposes. block_size: Option, }, diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index e574bef876..54739106c3 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -11,9 +11,9 @@ use std::{num::NonZeroUsize, time::Duration}; +pub mod block_impl; pub mod certificate; pub mod consensus; -pub mod constants; pub mod data; pub mod error; pub mod event; @@ -36,7 +36,7 @@ pub enum ExecutionType { /// Holds configuration for a `HotShot` #[derive(Clone, custom_debug::Debug, serde::Serialize, serde::Deserialize)] -pub struct HotShotConfig { +pub struct HotShotConfig { /// Whether to run one view or continuous views pub execution_type: ExecutionType, /// Total number of nodes in the network @@ -45,8 +45,6 @@ pub struct HotShotConfig { pub min_transactions: usize, /// Maximum transactions per block pub max_transactions: NonZeroUsize, - /// List of known node's public keys, including own, sorted by nonce () - pub known_nodes: Vec, /// List of known node's public keys and stake value for certificate aggregation, serving as public parameter pub known_nodes_with_stake: Vec, /// List of DA committee nodes for static DA committe diff --git a/crates/types/src/message.rs b/crates/types/src/message.rs index 89d2864aa9..c26de8bcef 100644 --- a/crates/types/src/message.rs +++ b/crates/types/src/message.rs @@ -5,7 +5,7 @@ use crate::{ certificate::DACertificate, - data::{DAProposal, ProposalType}, + data::{DAProposal, ProposalType, VidDisperse}, traits::{ network::{NetworkMsg, ViewMessage}, node_implementation::{ @@ -15,6 +15,7 @@ use crate::{ }, vote::{DAVote, QuorumVote, ViewSyncVote, VoteType}, }; +use commit::Commitment; use derivative::Derivative; use either::Either::{self, Left, Right}; use serde::{Deserialize, Serialize}; @@ -52,11 +53,13 @@ impl> ViewMessage for Messa #[derive(Clone, Debug)] pub struct Messages>(pub Vec>); -/// A message type agnostic description of a messages purpose +/// A message type agnostic description of a message's purpose #[derive(PartialEq, Copy, Clone)] pub enum MessagePurpose { /// Message with a quorum proposal. Proposal, + /// Message with most recent proposal the server has + CurrentProposal, /// Message with a quorum vote. Vote, /// Message with a view sync vote. @@ -69,6 +72,12 @@ pub enum MessagePurpose { Internal, /// Data message Data, + /// VID disperse, like [`Proposal`]. + VidDisperse, + /// VID vote, like [`Vote`]. + VidVote, + /// VID certificate, like [`DAC`]. + VidCert, } // TODO (da) make it more customized to the consensus layer, maybe separating the specific message @@ -141,7 +150,7 @@ where /// Message with a quorum proposal. Proposal(Proposal>, TYPES::SignatureKey), /// Message with a quorum vote. - Vote(QuorumVote, TYPES::SignatureKey), + Vote(QuorumVote>, TYPES::SignatureKey), /// Message with a view sync vote. ViewSyncVote(ViewSyncVote), /// Message with a view sync certificate. @@ -207,6 +216,12 @@ pub enum ProcessedCommitteeConsensusMessage { DAVote(DAVote, TYPES::SignatureKey), /// Certificate for the DA. DACertificate(DACertificate, TYPES::SignatureKey), + /// VID dispersal data. Like [`DAProposal`] + VidDisperseMsg(Proposal>, TYPES::SignatureKey), + /// Vote from VID storage node. Like [`DAVote`] + VidVote(DAVote, TYPES::SignatureKey), + /// Certificate for VID. Like [`DACertificate`] + VidCertificate(DACertificate, TYPES::SignatureKey), } impl From> @@ -223,6 +238,15 @@ impl From> ProcessedCommitteeConsensusMessage::DACertificate(cert, _) => { CommitteeConsensusMessage::DACertificate(cert) } + ProcessedCommitteeConsensusMessage::VidDisperseMsg(disperse, _) => { + CommitteeConsensusMessage::VidDisperseMsg(disperse) + } + ProcessedCommitteeConsensusMessage::VidVote(v, _) => { + CommitteeConsensusMessage::VidVote(v) + } + ProcessedCommitteeConsensusMessage::VidCertificate(cert, _) => { + CommitteeConsensusMessage::VidCertificate(cert) + } } } } @@ -240,6 +264,15 @@ impl ProcessedCommitteeConsensusMessage { CommitteeConsensusMessage::DACertificate(cert) => { ProcessedCommitteeConsensusMessage::DACertificate(cert, sender) } + CommitteeConsensusMessage::VidDisperseMsg(disperse) => { + ProcessedCommitteeConsensusMessage::VidDisperseMsg(disperse, sender) + } + CommitteeConsensusMessage::VidVote(v) => { + ProcessedCommitteeConsensusMessage::VidVote(v, sender) + } + CommitteeConsensusMessage::VidCertificate(cert) => { + ProcessedCommitteeConsensusMessage::VidCertificate(cert, sender) + } } } } @@ -282,7 +315,7 @@ where Proposal(Proposal>), /// Message with a quorum vote. - Vote(QuorumVote), + Vote(QuorumVote>), /// Message with a view sync vote. ViewSyncVote(ViewSyncVote), @@ -307,6 +340,23 @@ pub enum CommitteeConsensusMessage { /// Certificate data is available DACertificate(DACertificate), + + /// Initiate VID dispersal. + /// + /// Like [`DAProposal`]. Use `Msg` suffix to distinguish from [`VidDisperse`]. + /// TODO this variant should not be a [`CommitteeConsensusMessage`] because + VidDisperseMsg(Proposal>), + + /// Vote for VID disperse data + /// + /// Like [`DAVote`]. + /// TODO currently re-using [`DAVote`]; do we need a separate VID vote? + VidVote(DAVote), + /// VID certificate data is available + /// + /// Like [`DACertificate`] + /// TODO currently re-using [`DACertificate`]; do we need a separate VID cert? + VidCertificate(DACertificate), } /// Messages related to the consensus protocol. @@ -359,7 +409,7 @@ impl< // this should match replica upon receipt p.data.get_view_number() } - GeneralConsensusMessage::Vote(vote_message) => vote_message.current_view(), + GeneralConsensusMessage::Vote(vote_message) => vote_message.get_view(), GeneralConsensusMessage::InternalTrigger(trigger) => match trigger { InternalTrigger::Timeout(time) => *time, }, @@ -376,8 +426,13 @@ impl< // this should match replica upon receipt p.data.get_view_number() } - CommitteeConsensusMessage::DAVote(vote_message) => vote_message.current_view(), - CommitteeConsensusMessage::DACertificate(cert) => cert.view_number, + CommitteeConsensusMessage::DAVote(vote_message) => vote_message.get_view(), + CommitteeConsensusMessage::DACertificate(cert) + | CommitteeConsensusMessage::VidCertificate(cert) => cert.view_number, + CommitteeConsensusMessage::VidDisperseMsg(disperse) => { + disperse.data.get_view_number() + } + CommitteeConsensusMessage::VidVote(vote) => vote.get_view(), } } } @@ -397,7 +452,10 @@ impl< Right(committee_message) => match committee_message { CommitteeConsensusMessage::DAProposal(_) => MessagePurpose::Proposal, CommitteeConsensusMessage::DAVote(_) => MessagePurpose::Vote, + CommitteeConsensusMessage::VidVote(_) => MessagePurpose::VidVote, CommitteeConsensusMessage::DACertificate(_) => MessagePurpose::DAC, + CommitteeConsensusMessage::VidDisperseMsg(_) => MessagePurpose::VidDisperse, + CommitteeConsensusMessage::VidCertificate(_) => todo!(), }, } } diff --git a/crates/types/src/traits.rs b/crates/types/src/traits.rs index c6a76acea3..9c25e5fcb8 100644 --- a/crates/types/src/traits.rs +++ b/crates/types/src/traits.rs @@ -11,5 +11,5 @@ pub mod stake_table; pub mod state; pub mod storage; -pub use block_contents::Block; +pub use block_contents::BlockPayload; pub use state::State; diff --git a/crates/types/src/traits/block_contents.rs b/crates/types/src/traits/block_contents.rs index b7d9b4da44..2fc3383a14 100644 --- a/crates/types/src/traits/block_contents.rs +++ b/crates/types/src/traits/block_contents.rs @@ -1,10 +1,10 @@ //! Abstraction over the contents of a block //! -//! This module provides the [`Block`] trait, which describes the behaviors that a block is -//! expected to have. +//! This module provides the [`BlockPayload`] and [`BlockHeader`] traits, which describe the +//! behaviors that a block is expected to have. use commit::{Commitment, Committable}; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use serde::{de::DeserializeOwned, Serialize}; use std::{ collections::HashSet, @@ -13,16 +13,17 @@ use std::{ hash::Hash, }; +// TODO (Keyao) Determine whether we can refactor BlockPayload and Transaction from traits to structs. +// /// Abstraction over the full contents of a block /// -/// This trait encapsulates the behaviors that a block must have in order to be used by consensus: -/// * Must have a predefined error type ([`Block::Error`]) +/// This trait encapsulates the behaviors that the transactions of a block must have in order to be +/// used by consensus +/// * Must have a predefined error type ([`BlockPayload::Error`]) /// * Must have a transaction type that can be compared for equality, serialized and serialized, /// sent between threads, and can have a hash produced of it -/// * Must be able to be produced incrementally by appending transactions -/// ([`add_transaction_raw`](Block::add_transaction_raw)) /// * Must be hashable -pub trait Block: +pub trait BlockPayload: Serialize + Clone + Debug @@ -41,45 +42,32 @@ pub trait Block: /// The type of the transitions we are applying type Transaction: Transaction; - /// Construct an empty or genesis block. - fn new() -> Self; - - /// Attempts to add a transaction, returning an Error if it would result in a structurally - /// invalid block - /// - /// # Errors - /// - /// Should return an error if this transaction leads to an invalid block - fn add_transaction_raw(&self, tx: &Self::Transaction) - -> std::result::Result; - /// returns hashes of all the transactions in this block /// TODO make this ordered with a vec fn contained_transactions(&self) -> HashSet>; } -/// Commitment to a block, used by data availibity -#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)] -#[serde(bound(deserialize = ""), transparent)] -pub struct BlockCommitment(pub Commitment); - -/// Abstraction over any type of transaction. Used by [`Block`]. +// TODO (Keyao) Determine whether we can refactor BlockPayload and Transaction from traits to structs. +// +/// Abstraction over any type of transaction. Used by [`BlockPayload`]. pub trait Transaction: Clone + Serialize + DeserializeOwned + Debug + PartialEq + Eq + Sync + Send + Committable + Hash { } -/// Dummy implementation of `BlockContents` for unit tests +/// Dummy implementation of `BlockPayload` for unit tests pub mod dummy { use std::fmt::Display; - use super::{Block, Commitment, Committable, Debug, Hash, HashSet, Serialize}; + use super::{BlockPayload, Commitment, Committable, Debug, Hash, HashSet, Serialize}; use rand::Rng; use serde::Deserialize; pub use crate::traits::state::dummy::DummyState; use crate::traits::state::TestableBlock; + // TODO (Keyao) Investigate the use of DummyBlock. + // /// The dummy block #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] pub struct DummyBlock { @@ -107,7 +95,7 @@ pub mod dummy { impl Committable for DummyTransaction { fn commit(&self) -> commit::Commitment { - commit::RawCommitmentBuilder::new("Dummy Block Comm") + commit::RawCommitmentBuilder::new("Dummy BlockPayload Comm") .u64_field("Dummy Field", 0) .finalize() } @@ -132,24 +120,11 @@ pub mod dummy { } } - impl Block for DummyBlock { + impl BlockPayload for DummyBlock { type Error = DummyError; type Transaction = DummyTransaction; - fn new() -> Self { - ::genesis() - } - - fn add_transaction_raw( - &self, - _tx: &Self::Transaction, - ) -> std::result::Result { - Ok(Self { - nonce: self.nonce + 1, - }) - } - fn contained_transactions(&self) -> HashSet> { HashSet::new() } @@ -167,7 +142,7 @@ pub mod dummy { impl Committable for DummyBlock { fn commit(&self) -> commit::Commitment { - commit::RawCommitmentBuilder::new("Dummy Block Comm") + commit::RawCommitmentBuilder::new("Dummy BlockPayload Comm") .u64_field("Nonce", self.nonce) .finalize() } diff --git a/crates/types/src/traits/consensus_api.rs b/crates/types/src/traits/consensus_api.rs index 2687107886..08716a3d73 100644 --- a/crates/types/src/traits/consensus_api.rs +++ b/crates/types/src/traits/consensus_api.rs @@ -2,7 +2,7 @@ use crate::{ certificate::QuorumCertificate, - data::{LeafType, ProposalType}, + data::LeafType, error::HotShotError, event::{Event, EventType}, message::{DataMessage, SequencingMessage}, @@ -12,10 +12,9 @@ use crate::{ signature_key::SignatureKey, storage::StorageError, }, - vote::VoteType, }; use async_trait::async_trait; - +use commit::Commitment; use std::{num::NonZeroUsize, sync::Arc, time::Duration}; /// The API that [`HotStuff`] needs to talk to the system, implemented for both validating and @@ -98,7 +97,7 @@ pub trait ConsensusSharedApi< &self, view_number: TYPES::Time, leaf_views: Vec, - decide_qc: QuorumCertificate, + decide_qc: QuorumCertificate>, ) { self.send_event(Event { view_number, @@ -130,27 +129,21 @@ pub trait SequencingConsensusApi< >: ConsensusSharedApi { /// Send a direct message to the given recipient - async fn send_direct_message, VOTE: VoteType>( + async fn send_direct_message( &self, recipient: TYPES::SignatureKey, message: SequencingMessage, ) -> std::result::Result<(), NetworkError>; /// send a direct message using the DA communication channel - async fn send_direct_da_message< - PROPOSAL: ProposalType, - VOTE: VoteType, - >( + async fn send_direct_da_message( &self, recipient: TYPES::SignatureKey, message: SequencingMessage, ) -> std::result::Result<(), NetworkError>; /// Send a broadcast message to the entire network. - async fn send_broadcast_message< - PROPOSAL: ProposalType, - VOTE: VoteType, - >( + async fn send_broadcast_message( &self, message: SequencingMessage, ) -> std::result::Result<(), NetworkError>; diff --git a/crates/types/src/traits/election.rs b/crates/types/src/traits/election.rs index fdc435163b..0a881cd093 100644 --- a/crates/types/src/traits/election.rs +++ b/crates/types/src/traits/election.rs @@ -15,10 +15,11 @@ use crate::{ }; use crate::{ - message::{CommitteeConsensusMessage, GeneralConsensusMessage, Message}, + message::{GeneralConsensusMessage, Message}, vote::ViewSyncVoteInternal, }; +use crate::vote::Accumulator2; use crate::{ data::LeafType, traits::{ @@ -28,12 +29,12 @@ use crate::{ state::ConsensusTime, }, vote::{ - Accumulator, DAVote, QuorumVote, TimeoutVote, ViewSyncData, ViewSyncVote, VoteAccumulator, - VoteType, YesOrNoVote, + DAVote, QuorumVote, TimeoutVote, ViewSyncData, ViewSyncVote, VoteAccumulator, VoteType, + YesOrNoVote, }, }; use bincode::Options; -use commit::{Commitment, Committable}; +use commit::{Commitment, CommitmentBounds, Committable}; use derivative::Derivative; use either::Either; use ethereum_types::U256; @@ -60,6 +61,7 @@ pub enum ElectionError { /// the outcome is already knowable. /// /// This would be a useful general utility. +#[derive(Clone)] pub enum Checked { /// This item has been checked, and is valid Valid(T), @@ -72,65 +74,46 @@ pub enum Checked { /// Data to vote on for different types of votes. #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)] #[serde(bound(deserialize = ""))] -pub enum VoteData { +pub enum VoteData +where + COMMITMENT: CommitmentBounds, +{ /// Vote to provide availability for a block. - DA(Commitment), + DA(COMMITMENT), /// Vote to append a leaf to the log. - Yes(Commitment), + Yes(COMMITMENT), /// Vote to reject a leaf from the log. - No(Commitment), + No(COMMITMENT), /// Vote to time out and proceed to the next view. - Timeout(Commitment), + Timeout(COMMITMENT), /// Vote to pre-commit the view sync. - ViewSyncPreCommit(Commitment), + ViewSyncPreCommit(COMMITMENT), /// Vote to commit the view sync. - ViewSyncCommit(Commitment), + ViewSyncCommit(COMMITMENT), /// Vote to finalize the view sync. - ViewSyncFinalize(Commitment), + ViewSyncFinalize(COMMITMENT), } -/// Make different types of `VoteData` committable -impl Committable for VoteData { - fn commit(&self) -> Commitment { +impl VoteData +where + COMMITMENT: CommitmentBounds, +{ + /// Return the underlying commitment. + #[must_use] + pub fn get_commit(&self) -> COMMITMENT { + #[allow(clippy::enum_glob_use)] + use VoteData::*; match self { - VoteData::DA(block_commitment) => commit::RawCommitmentBuilder::new("DA Block Commit") - .field("block_commitment", *block_commitment) - .finalize(), - VoteData::Yes(leaf_commitment) => commit::RawCommitmentBuilder::new("Yes Vote Commit") - .field("leaf_commitment", *leaf_commitment) - .finalize(), - VoteData::No(leaf_commitment) => commit::RawCommitmentBuilder::new("No Vote Commit") - .field("leaf_commitment", *leaf_commitment) - .finalize(), - VoteData::Timeout(view_number_commitment) => { - commit::RawCommitmentBuilder::new("Timeout View Number Commit") - .field("view_number_commitment", *view_number_commitment) - .finalize() - } - VoteData::ViewSyncPreCommit(commitment) => { - commit::RawCommitmentBuilder::new("ViewSyncPreCommit") - .field("commitment", *commitment) - .finalize() - } - VoteData::ViewSyncCommit(commitment) => { - commit::RawCommitmentBuilder::new("ViewSyncCommit") - .field("commitment", *commitment) - .finalize() - } - VoteData::ViewSyncFinalize(commitment) => { - commit::RawCommitmentBuilder::new("ViewSyncFinalize") - .field("commitment", *commitment) - .finalize() - } + DA(c) | Yes(c) | No(c) | Timeout(c) | ViewSyncPreCommit(c) | ViewSyncCommit(c) + | ViewSyncFinalize(c) => *c, } } - - fn tag() -> String { - ("VOTE_DATA_COMMIT").to_string() - } } -impl VoteData { +impl VoteData +where + COMMITMENT: CommitmentBounds, +{ #[must_use] /// Convert vote data into bytes. /// @@ -152,7 +135,6 @@ pub trait VoteToken: + PartialEq + Hash + Eq - + Committable { // type StakeTable; // type KeyPair: SignatureKey; @@ -175,18 +157,25 @@ pub trait ElectionConfig: } /// A certificate of some property which has been signed by a quroum of nodes. -pub trait SignedCertificate +pub trait SignedCertificate where Self: Send + Sync + Clone + Serialize + for<'a> Deserialize<'a>, - COMMITTABLE: Committable + Serialize + Clone, + COMMITMENT: CommitmentBounds, TOKEN: VoteToken, { + /// `VoteType` that is used in this certificate + type Vote: VoteType; + + /// `Accumulator` type to accumulate votes. + type VoteAccumulator: Accumulator2; + /// Build a QC from the threshold signature and commitment + // TODO ED Rename this function and rework this function parameters + // Assumes last vote was valid since it caused a QC to form. + // Removes need for relay on other cert specific fields fn from_signatures_and_commitment( - view_number: TIME, signatures: AssembledSignature, - commit: Commitment, - relay: Option, + vote: Self::Vote, ) -> Self; /// Get the view number. @@ -196,12 +185,13 @@ where fn signatures(&self) -> AssembledSignature; // TODO (da) the following functions should be refactored into a QC-specific trait. + // TODO ED Make an issue for this /// Get the leaf commitment. - fn leaf_commitment(&self) -> Commitment; + fn leaf_commitment(&self) -> COMMITMENT; /// Set the leaf commitment. - fn set_leaf_commitment(&mut self, commitment: Commitment); + fn set_leaf_commitment(&mut self, commitment: COMMITMENT); /// Get whether the certificate is for the genesis block. fn is_genesis(&self) -> bool; @@ -221,7 +211,6 @@ pub trait Membership: /// TODO may want to move this to a testableelection trait fn create_election( entries: Vec<::StakeTableEntry>, - keys: Vec, config: TYPES::ElectionConfigType, ) -> Self; @@ -276,7 +265,8 @@ pub trait ConsensusExchange: Send + Sync { /// A proposal for participants to vote on. type Proposal: ProposalType; /// A vote on a [`Proposal`](Self::Proposal). - type Vote: VoteType; + // TODO ED Make this equal Certificate vote (if possible?) + type Vote: VoteType; /// A [`SignedCertificate`] attesting to a decision taken by the committee. type Certificate: SignedCertificate + Hash @@ -284,14 +274,13 @@ pub trait ConsensusExchange: Send + Sync { /// The committee eligible to make decisions. type Membership: Membership; /// Network used by [`Membership`](Self::Membership) to communicate. - type Networking: CommunicationChannel; + type Networking: CommunicationChannel; /// Commitments to items which are the subject of proposals and decisions. - type Commitment: Committable + Serialize + Clone; + type Commitment: CommitmentBounds; /// Join a [`ConsensusExchange`] with the given identity (`pk` and `sk`). fn create( entries: Vec<::StakeTableEntry>, - keys: Vec, config: TYPES::ElectionConfigType, network: Self::Networking, pk: TYPES::SignatureKey, @@ -340,7 +329,7 @@ pub trait ConsensusExchange: Send + Sync { } /// The contents of a vote on `commit`. - fn vote_data(&self, commit: Commitment) -> VoteData; + fn vote_data(&self, commit: Self::Commitment) -> VoteData; /// Validate a certificate. fn is_valid_cert(&self, qc: &Self::Certificate) -> bool { @@ -351,7 +340,7 @@ pub trait ConsensusExchange: Send + Sync { match qc.signatures() { AssembledSignature::DA(qc) => { - let real_commit = VoteData::DA(leaf_commitment).commit(); + let real_commit = VoteData::DA(leaf_commitment).get_commit(); let real_qc_pp = ::get_public_parameter( self.membership().get_committee_qc_stake_table(), U256::from(self.membership().success_threshold().get()), @@ -359,7 +348,7 @@ pub trait ConsensusExchange: Send + Sync { ::check(&real_qc_pp, real_commit.as_ref(), &qc) } AssembledSignature::Yes(qc) => { - let real_commit = VoteData::Yes(leaf_commitment).commit(); + let real_commit = VoteData::Yes(leaf_commitment).get_commit(); let real_qc_pp = ::get_public_parameter( self.membership().get_committee_qc_stake_table(), U256::from(self.membership().success_threshold().get()), @@ -367,7 +356,7 @@ pub trait ConsensusExchange: Send + Sync { ::check(&real_qc_pp, real_commit.as_ref(), &qc) } AssembledSignature::No(qc) => { - let real_commit = VoteData::No(leaf_commitment).commit(); + let real_commit = VoteData::No(leaf_commitment).get_commit(); let real_qc_pp = ::get_public_parameter( self.membership().get_committee_qc_stake_table(), U256::from(self.membership().success_threshold().get()), @@ -395,7 +384,7 @@ pub trait ConsensusExchange: Send + Sync { let mut is_valid_vote_token = false; let mut is_valid_signature = false; if let Some(key) = ::from_bytes(encoded_key) { - is_valid_signature = key.validate(encoded_signature, data.commit().as_ref()); + is_valid_signature = key.validate(encoded_signature, data.get_commit().as_ref()); let valid_vote_token = self.membership().validate_vote_token(key, vote_token); is_valid_vote_token = match valid_vote_token { Err(_) => { @@ -409,59 +398,39 @@ pub trait ConsensusExchange: Send + Sync { is_valid_signature && is_valid_vote_token } + /// Validate a vote by checking its signature and token. + fn is_valid_vote_2( + &self, + key: &TYPES::SignatureKey, + encoded_signature: &EncodedSignature, + data: &VoteData, + vote_token: &Checked, + ) -> bool { + let is_valid_signature = key.validate(encoded_signature, data.get_commit().as_ref()); + let valid_vote_token = self + .membership() + .validate_vote_token(key.clone(), vote_token.clone()); + let is_valid_vote_token = match valid_vote_token { + Err(_) => { + error!("Vote token was invalid"); + false + } + Ok(Checked::Valid(_)) => true, + Ok(Checked::Inval(_) | Checked::Unchecked(_)) => false, + }; + + is_valid_signature && is_valid_vote_token + } + #[doc(hidden)] + fn accumulate_internal( &self, - vota_meta: VoteMetaData, - accumulator: VoteAccumulator, - ) -> Either, Self::Certificate> { - if !self.is_valid_vote( - &vota_meta.encoded_key, - &vota_meta.encoded_signature, - vota_meta.data.clone(), - // Ignoring deserialization errors below since we are getting rid of it soon - Checked::Unchecked(vota_meta.vote_token.clone()), - ) { - error!("Invalid vote!"); - return Either::Left(accumulator); - } - - if let Some(key) = ::from_bytes(&vota_meta.encoded_key) - { - let stake_table_entry = key.get_stake_table_entry(1u64); - let append_node_id = self - .membership() - .get_committee_qc_stake_table() - .iter() - .position(|x| *x == stake_table_entry.clone()) - .unwrap(); - - match accumulator.append(( - vota_meta.commitment, - ( - vota_meta.encoded_key.clone(), - ( - vota_meta.encoded_signature.clone(), - self.membership().get_committee_qc_stake_table(), - append_node_id, - vota_meta.data, - vota_meta.vote_token, - ), - ), - )) { - Either::Left(accumulator) => Either::Left(accumulator), - Either::Right(signatures) => { - Either::Right(Self::Certificate::from_signatures_and_commitment( - vota_meta.view_number, - signatures, - vota_meta.commitment, - vota_meta.relay, - )) - } - } - } else { - Either::Left(accumulator) - } + _vota_meta: VoteMetaData, + _accumulator: VoteAccumulator, + ) -> Either, Self::Certificate> + { + todo!() // TODO ED Remove this function } /// Add a vote to the accumulating signature. Return The certificate if the vote @@ -471,13 +440,79 @@ pub trait ConsensusExchange: Send + Sync { &self, encoded_key: &EncodedPublicKey, encoded_signature: &EncodedSignature, - leaf_commitment: Commitment, + leaf_commitment: Self::Commitment, vote_data: VoteData, vote_token: TYPES::VoteTokenType, view_number: TYPES::Time, - accumlator: VoteAccumulator, + accumlator: VoteAccumulator, relay: Option, - ) -> Either, Self::Certificate>; + ) -> Either, Self::Certificate>; + + // TODO ED Depending on what we do in the future with the exchanges trait, we can move the accumulator out of the `SignedCertificate` + // trait. Logically, I feel it makes sense to accumulate on the certificate rather than the exchange, however. + /// Accumulate vote + /// Returns either the accumulate if no threshold was reached, or a `SignedCertificate` if the threshold was reached + #[allow(clippy::type_complexity)] + fn accumulate_vote_2( + &self, + accumulator: <>::Certificate as SignedCertificate< + TYPES, + TYPES::Time, + TYPES::VoteTokenType, + Self::Commitment, + >>::VoteAccumulator, + vote: &<>::Certificate as SignedCertificate< + TYPES, + TYPES::Time, + TYPES::VoteTokenType, + Self::Commitment, + >>::Vote, + _commit: &Self::Commitment, + ) -> Either< + <>::Certificate as SignedCertificate< + TYPES, + TYPES::Time, + TYPES::VoteTokenType, + Self::Commitment, + >>::VoteAccumulator, + Self::Certificate, + > { + if !self.is_valid_vote_2( + &vote.get_key(), + &vote.get_signature(), + &vote.get_data(), + // TODO ED We've had this comment for a while: Ignoring deserialization errors below since we are getting rid of it soon + &Checked::Unchecked(vote.get_vote_token()), + ) { + error!("Invalid vote!"); + return Either::Left(accumulator); + } + + let stake_table_entry = vote.get_key().get_stake_table_entry(1u64); + // TODO ED Could we make this part of the vote in the future? It's only a usize. + let append_node_id = self + .membership() + .get_committee_qc_stake_table() + .iter() + .position(|x| *x == stake_table_entry.clone()) + .unwrap(); + + // TODO ED Should make append function take a reference to vote + match accumulator.append( + vote.clone(), + append_node_id, + self.membership().get_committee_qc_stake_table(), + ) { + Either::Left(accumulator) => Either::Left(accumulator), + Either::Right(signatures) => { + // TODO ED Update this function to just take in the signatures and most recent vote + Either::Right(Self::Certificate::from_signatures_and_commitment( + signatures, + vote.clone(), + )) + } + } + } /// The committee which votes on proposals. fn membership(&self) -> &Self::Membership; @@ -512,7 +547,23 @@ pub trait CommitteeExchangeType: block_commitment: Commitment, current_view: TYPES::Time, vote_token: TYPES::VoteTokenType, - ) -> CommitteeConsensusMessage; + ) -> DAVote; + + // TODO temporary vid methods, move to quorum https://github.com/EspressoSystems/HotShot/issues/1696 + + /// Create a message with a vote on VID disperse data. + fn create_vid_message( + &self, + block_commitment: Commitment, + current_view: TYPES::Time, + vote_token: TYPES::VoteTokenType, + ) -> DAVote; + + /// Sign a vote on VID proposal. + fn sign_vid_vote( + &self, + block_commitment: Commitment, + ) -> (EncodedPublicKey, EncodedSignature); } /// Standard implementation of [`CommitteeExchangeType`] utilizing a DA committee. @@ -521,7 +572,7 @@ pub trait CommitteeExchangeType: pub struct CommitteeExchange< TYPES: NodeType, MEMBERSHIP: Membership, - NETWORK: CommunicationChannel, DAVote, MEMBERSHIP>, + NETWORK: CommunicationChannel, M: NetworkMsg, > { /// The network being used by this exchange. @@ -542,7 +593,7 @@ pub struct CommitteeExchange< impl< TYPES: NodeType, MEMBERSHIP: Membership, - NETWORK: CommunicationChannel, DAVote, MEMBERSHIP>, + NETWORK: CommunicationChannel, M: NetworkMsg, > CommitteeExchangeType for CommitteeExchange { @@ -564,9 +615,7 @@ impl< ) -> (EncodedPublicKey, EncodedSignature) { let signature = TYPES::SignatureKey::sign( &self.private_key, - VoteData::::DA(block_commitment) - .commit() - .as_ref(), + VoteData::DA(block_commitment).get_commit().as_ref(), ); (self.public_key.to_bytes(), signature) } @@ -576,22 +625,49 @@ impl< block_commitment: Commitment, current_view: TYPES::Time, vote_token: TYPES::VoteTokenType, - ) -> CommitteeConsensusMessage { + ) -> DAVote { let signature = self.sign_da_vote(block_commitment); - CommitteeConsensusMessage::::DAVote(DAVote { + DAVote { signature, block_commitment, current_view, vote_token, vote_data: VoteData::DA(block_commitment), - }) + } + } + + fn create_vid_message( + &self, + block_commitment: Commitment, + current_view: ::Time, + vote_token: ::VoteTokenType, + ) -> DAVote { + let signature = self.sign_vid_vote(block_commitment); + DAVote { + signature, + block_commitment, + current_view, + vote_token, + vote_data: VoteData::DA(block_commitment), + } + } + + fn sign_vid_vote( + &self, + block_commitment: Commitment<::BlockType>, + ) -> (EncodedPublicKey, EncodedSignature) { + let signature = TYPES::SignatureKey::sign( + &self.private_key, + VoteData::DA(block_commitment).get_commit().as_ref(), + ); + (self.public_key.to_bytes(), signature) } } impl< TYPES: NodeType, MEMBERSHIP: Membership, - NETWORK: CommunicationChannel, DAVote, MEMBERSHIP>, + NETWORK: CommunicationChannel, M: NetworkMsg, > ConsensusExchange for CommitteeExchange { @@ -600,20 +676,18 @@ impl< type Certificate = DACertificate; type Membership = MEMBERSHIP; type Networking = NETWORK; - type Commitment = TYPES::BlockType; + type Commitment = Commitment; fn create( entries: Vec<::StakeTableEntry>, - keys: Vec, config: TYPES::ElectionConfigType, network: Self::Networking, pk: TYPES::SignatureKey, entry: ::StakeTableEntry, sk: ::PrivateKey, ) -> Self { - let membership = >::Membership::create_election( - entries, keys, config, - ); + let membership = + >::Membership::create_election(entries, config); Self { network, membership, @@ -634,7 +708,7 @@ impl< .make_vote_token(view_number, &self.private_key) } - fn vote_data(&self, commit: Commitment) -> VoteData { + fn vote_data(&self, commit: Self::Commitment) -> VoteData { VoteData::DA(commit) } @@ -644,13 +718,14 @@ impl< &self, encoded_key: &EncodedPublicKey, encoded_signature: &EncodedSignature, - leaf_commitment: Commitment, + leaf_commitment: Self::Commitment, vote_data: VoteData, vote_token: TYPES::VoteTokenType, view_number: TYPES::Time, - accumlator: VoteAccumulator, + accumlator: VoteAccumulator, _relay: Option, - ) -> Either, Self::Certificate> { + ) -> Either, Self::Certificate> + { let meta = VoteMetaData { encoded_key: encoded_key.clone(), encoded_signature: encoded_signature.clone(), @@ -728,7 +803,7 @@ pub trait QuorumExchangeType, /// Create a message with a negative vote on validating or commitment proposal. fn create_no_message>( &self, - justify_qc_commitment: Commitment>, + justify_qc_commitment: Commitment>>, leaf_commitment: Commitment, current_view: TYPES::Time, vote_token: TYPES::VoteTokenType, @@ -739,7 +814,7 @@ pub trait QuorumExchangeType, /// Create a message with a timeout vote on validating or commitment proposal. fn create_timeout_message>( &self, - justify_qc: QuorumCertificate, + justify_qc: QuorumCertificate>, current_view: TYPES::Time, vote_token: TYPES::VoteTokenType, ) -> GeneralConsensusMessage @@ -755,7 +830,7 @@ pub struct QuorumExchange< LEAF: LeafType, PROPOSAL: ProposalType, MEMBERSHIP: Membership, - NETWORK: CommunicationChannel, MEMBERSHIP>, + NETWORK: CommunicationChannel, M: NetworkMsg, > { /// The network being used by this exchange. @@ -778,7 +853,7 @@ impl< LEAF: LeafType, MEMBERSHIP: Membership, PROPOSAL: ProposalType, - NETWORK: CommunicationChannel, MEMBERSHIP>, + NETWORK: CommunicationChannel, M: NetworkMsg, > QuorumExchangeType for QuorumExchange @@ -786,7 +861,7 @@ impl< /// Create a message with a positive vote on validating or commitment proposal. fn create_yes_message>( &self, - justify_qc_commitment: Commitment>, + justify_qc_commitment: Commitment>>, leaf_commitment: Commitment, current_view: TYPES::Time, vote_token: TYPES::VoteTokenType, @@ -825,7 +900,7 @@ impl< ) -> (EncodedPublicKey, EncodedSignature) { let signature = TYPES::SignatureKey::sign( &self.private_key, - VoteData::::Yes(leaf_commitment).commit().as_ref(), + VoteData::Yes(leaf_commitment).get_commit().as_ref(), ); (self.public_key.to_bytes(), signature) } @@ -841,7 +916,7 @@ impl< ) -> (EncodedPublicKey, EncodedSignature) { let signature = TYPES::SignatureKey::sign( &self.private_key, - VoteData::::No(leaf_commitment).commit().as_ref(), + VoteData::No(leaf_commitment).get_commit().as_ref(), ); (self.public_key.to_bytes(), signature) } @@ -856,8 +931,8 @@ impl< fn sign_timeout_vote(&self, view_number: TYPES::Time) -> (EncodedPublicKey, EncodedSignature) { let signature = TYPES::SignatureKey::sign( &self.private_key, - VoteData::::Timeout(view_number.commit()) - .commit() + VoteData::Timeout(view_number.commit()) + .get_commit() .as_ref(), ); (self.public_key.to_bytes(), signature) @@ -865,7 +940,7 @@ impl< /// Create a message with a negative vote on validating or commitment proposal. fn create_no_message>( &self, - justify_qc_commitment: Commitment>, + justify_qc_commitment: Commitment>>, leaf_commitment: Commitment, current_view: TYPES::Time, vote_token: TYPES::VoteTokenType, @@ -887,7 +962,7 @@ impl< /// Create a message with a timeout vote on validating or commitment proposal. fn create_timeout_message>( &self, - high_qc: QuorumCertificate, + high_qc: QuorumCertificate>, current_view: TYPES::Time, vote_token: TYPES::VoteTokenType, ) -> GeneralConsensusMessage @@ -910,30 +985,28 @@ impl< LEAF: LeafType, PROPOSAL: ProposalType, MEMBERSHIP: Membership, - NETWORK: CommunicationChannel, MEMBERSHIP>, + NETWORK: CommunicationChannel, M: NetworkMsg, > ConsensusExchange for QuorumExchange { type Proposal = PROPOSAL; - type Vote = QuorumVote; - type Certificate = QuorumCertificate; + type Vote = QuorumVote>; + type Certificate = QuorumCertificate>; type Membership = MEMBERSHIP; type Networking = NETWORK; - type Commitment = LEAF; + type Commitment = Commitment; fn create( entries: Vec<::StakeTableEntry>, - keys: Vec, config: TYPES::ElectionConfigType, network: Self::Networking, pk: TYPES::SignatureKey, entry: ::StakeTableEntry, sk: ::PrivateKey, ) -> Self { - let membership = >::Membership::create_election( - entries, keys, config, - ); + let membership = + >::Membership::create_election(entries, config); Self { network, membership, @@ -948,7 +1021,7 @@ impl< &self.network } - fn vote_data(&self, commit: Commitment) -> VoteData { + fn vote_data(&self, commit: Self::Commitment) -> VoteData { VoteData::Yes(commit) } @@ -962,9 +1035,10 @@ impl< vote_data: VoteData, vote_token: TYPES::VoteTokenType, view_number: TYPES::Time, - accumlator: VoteAccumulator, + accumlator: VoteAccumulator, TYPES>, _relay: Option, - ) -> Either, Self::Certificate> { + ) -> Either, TYPES>, Self::Certificate> + { let meta = VoteMetaData { encoded_key: encoded_key.clone(), encoded_signature: encoded_signature.clone(), @@ -1047,7 +1121,7 @@ pub struct ViewSyncExchange< TYPES: NodeType, PROPOSAL: ProposalType, MEMBERSHIP: Membership, - NETWORK: CommunicationChannel, MEMBERSHIP>, + NETWORK: CommunicationChannel, M: NetworkMsg, > { /// The network being used by this exchange. @@ -1069,7 +1143,7 @@ impl< TYPES: NodeType, MEMBERSHIP: Membership, PROPOSAL: ProposalType, - NETWORK: CommunicationChannel, MEMBERSHIP>, + NETWORK: CommunicationChannel, M: NetworkMsg, > ViewSyncExchangeType for ViewSyncExchange { @@ -1108,7 +1182,9 @@ impl< ) -> (EncodedPublicKey, EncodedSignature) { let signature = TYPES::SignatureKey::sign( &self.private_key, - VoteData::ViewSyncPreCommit(commitment).commit().as_ref(), + VoteData::ViewSyncPreCommit(commitment) + .get_commit() + .as_ref(), ); (self.public_key.to_bytes(), signature) @@ -1149,7 +1225,7 @@ impl< ) -> (EncodedPublicKey, EncodedSignature) { let signature = TYPES::SignatureKey::sign( &self.private_key, - VoteData::ViewSyncCommit(commitment).commit().as_ref(), + VoteData::ViewSyncCommit(commitment).get_commit().as_ref(), ); (self.public_key.to_bytes(), signature) @@ -1190,7 +1266,7 @@ impl< ) -> (EncodedPublicKey, EncodedSignature) { let signature = TYPES::SignatureKey::sign( &self.private_key, - VoteData::ViewSyncFinalize(commitment).commit().as_ref(), + VoteData::ViewSyncFinalize(commitment).get_commit().as_ref(), ); (self.public_key.to_bytes(), signature) @@ -1221,7 +1297,7 @@ impl< }; match certificate_internal.signatures { AssembledSignature::ViewSyncPreCommit(raw_signatures) => { - let real_commit = VoteData::ViewSyncPreCommit(vote_data.commit()).commit(); + let real_commit = VoteData::ViewSyncPreCommit(vote_data.commit()).get_commit(); let real_qc_pp = ::get_public_parameter( self.membership().get_committee_qc_stake_table(), U256::from(self.membership().failure_threshold().get()), @@ -1233,7 +1309,7 @@ impl< ) } AssembledSignature::ViewSyncCommit(raw_signatures) => { - let real_commit = VoteData::ViewSyncCommit(vote_data.commit()).commit(); + let real_commit = VoteData::ViewSyncCommit(vote_data.commit()).get_commit(); let real_qc_pp = ::get_public_parameter( self.membership().get_committee_qc_stake_table(), U256::from(self.membership().success_threshold().get()), @@ -1245,7 +1321,7 @@ impl< ) } AssembledSignature::ViewSyncFinalize(raw_signatures) => { - let real_commit = VoteData::ViewSyncFinalize(vote_data.commit()).commit(); + let real_commit = VoteData::ViewSyncFinalize(vote_data.commit()).get_commit(); let real_qc_pp = ::get_public_parameter( self.membership().get_committee_qc_stake_table(), U256::from(self.membership().success_threshold().get()), @@ -1270,7 +1346,7 @@ impl< TYPES: NodeType, PROPOSAL: ProposalType, MEMBERSHIP: Membership, - NETWORK: CommunicationChannel, MEMBERSHIP>, + NETWORK: CommunicationChannel, M: NetworkMsg, > ConsensusExchange for ViewSyncExchange { @@ -1279,20 +1355,18 @@ impl< type Certificate = ViewSyncCertificate; type Membership = MEMBERSHIP; type Networking = NETWORK; - type Commitment = ViewSyncData; + type Commitment = Commitment>; fn create( entries: Vec<::StakeTableEntry>, - keys: Vec, config: TYPES::ElectionConfigType, network: Self::Networking, pk: TYPES::SignatureKey, entry: ::StakeTableEntry, sk: ::PrivateKey, ) -> Self { - let membership = >::Membership::create_election( - entries, keys, config, - ); + let membership = + >::Membership::create_election(entries, config); Self { network, membership, @@ -1307,7 +1381,7 @@ impl< &self.network } - fn vote_data(&self, _commit: Commitment) -> VoteData { + fn vote_data(&self, _commit: Self::Commitment) -> VoteData { unimplemented!() } @@ -1319,9 +1393,12 @@ impl< vote_data: VoteData, vote_token: TYPES::VoteTokenType, view_number: TYPES::Time, - accumlator: VoteAccumulator>, + accumlator: VoteAccumulator>, TYPES>, relay: Option, - ) -> Either>, Self::Certificate> { + ) -> Either< + VoteAccumulator>, TYPES>, + Self::Certificate, + > { let meta = VoteMetaData { encoded_key: encoded_key.clone(), encoded_signature: encoded_signature.clone(), diff --git a/crates/types/src/traits/network.rs b/crates/types/src/traits/network.rs index ee2d09672d..1729636836 100644 --- a/crates/types/src/traits/network.rs +++ b/crates/types/src/traits/network.rs @@ -2,17 +2,23 @@ //! //! Contains types and traits used by `HotShot` to abstract over network access +use async_compatibility_layer::art::async_sleep; #[cfg(async_executor_impl = "async-std")] use async_std::future::TimeoutError; -use hotshot_task::BoxSyncFuture; +use hotshot_task::{boxed_sync, BoxSyncFuture}; use libp2p_networking::network::NetworkNodeHandleError; #[cfg(async_executor_impl = "tokio")] use tokio::time::error::Elapsed as TimeoutError; #[cfg(not(any(async_executor_impl = "async-std", async_executor_impl = "tokio")))] compile_error! {"Either config option \"async-std\" or \"tokio\" must be enabled for this crate."} use super::{election::Membership, node_implementation::NodeType, signature_key::SignatureKey}; -use crate::{data::ProposalType, message::MessagePurpose, vote::VoteType}; +use crate::{data::ViewNumber, message::MessagePurpose}; +use async_compatibility_layer::channel::UnboundedSendError; use async_trait::async_trait; +use rand::{ + distributions::{Bernoulli, Uniform}, + prelude::Distribution, +}; use serde::{Deserialize, Serialize}; use snafu::Snafu; use std::{collections::BTreeSet, fmt::Debug, sync::Arc, time::Duration}; @@ -130,11 +136,13 @@ pub enum NetworkError { #[derive(Clone, Debug)] // Storing view number as a u64 to avoid the need TYPES generic /// Events to poll or cancel consensus processes. -pub enum ConsensusIntentEvent { +pub enum ConsensusIntentEvent { /// Poll for votes for a particular view PollForVotes(u64), /// Poll for a proposal for a particular view PollForProposal(u64), + /// Poll for the most recent proposal the webserver has + PollForCurrentProposal, /// Poll for a DAC for a particular view PollForDAC(u64), /// Poll for view sync votes starting at a particular view @@ -143,6 +151,8 @@ pub enum ConsensusIntentEvent { PollForViewSyncCertificate(u64), /// Poll for new transactions PollForTransactions(u64), + /// Poll for future leader + PollFutureLeader(u64, K), /// Cancel polling for votes CancelPollForVotes(u64), /// Cancel polling for view sync votes. @@ -157,7 +167,7 @@ pub enum ConsensusIntentEvent { CancelPollForTransactions(u64), } -impl ConsensusIntentEvent { +impl ConsensusIntentEvent { /// Get the view number of the event. #[must_use] pub fn view_number(&self) -> u64 { @@ -173,7 +183,9 @@ impl ConsensusIntentEvent { | ConsensusIntentEvent::CancelPollForViewSyncCertificate(view_number) | ConsensusIntentEvent::PollForViewSyncCertificate(view_number) | ConsensusIntentEvent::PollForTransactions(view_number) - | ConsensusIntentEvent::CancelPollForTransactions(view_number) => *view_number, + | ConsensusIntentEvent::CancelPollForTransactions(view_number) + | ConsensusIntentEvent::PollFutureLeader(view_number, _) => *view_number, + ConsensusIntentEvent::PollForCurrentProposal => 1, } } } @@ -196,13 +208,8 @@ pub trait ViewMessage { /// API for interacting directly with a consensus committee /// intended to be implemented for both DA and for validating consensus committees #[async_trait] -pub trait CommunicationChannel< - TYPES: NodeType, - M: NetworkMsg, - PROPOSAL: ProposalType, - VOTE: VoteType, - MEMBERSHIP: Membership, ->: Clone + Debug + Send + Sync + 'static +pub trait CommunicationChannel>: + Clone + Debug + Send + Sync + 'static { /// Underlying Network implementation's type type NETWORK; @@ -250,13 +257,18 @@ pub trait CommunicationChannel< 'a: 'b, Self: 'b; - /// look up a node - /// blocking - async fn lookup_node(&self, pk: TYPES::SignatureKey) -> Result<(), NetworkError>; + /// queues looking up a node + async fn queue_node_lookup( + &self, + _view_number: ViewNumber, + _pk: TYPES::SignatureKey, + ) -> Result<(), UnboundedSendError>> { + Ok(()) + } /// Injects consensus data such as view number into the networking implementation /// blocking - async fn inject_consensus_info(&self, event: ConsensusIntentEvent); + async fn inject_consensus_info(&self, _event: ConsensusIntentEvent) {} } /// represents a networking implmentration @@ -305,14 +317,19 @@ pub trait ConnectedNetwork: 'a: 'b, Self: 'b; - /// look up a node - /// blocking - async fn lookup_node(&self, pk: K) -> Result<(), NetworkError>; + /// queues lookup of a node + async fn queue_node_lookup( + &self, + _view_number: ViewNumber, + _pk: K, + ) -> Result<(), UnboundedSendError>> { + Ok(()) + } /// Injects consensus data such as view number into the networking implementation /// blocking /// Ideally we would pass in the `Time` type, but that requires making the entire trait generic over NodeType - async fn inject_consensus_info(&self, event: ConsensusIntentEvent); + async fn inject_consensus_info(&self, _event: ConsensusIntentEvent) {} } /// Describes additional functionality needed by the test network implementation @@ -335,11 +352,9 @@ pub trait TestableNetworkingImplementation { pub trait TestableChannelImplementation< TYPES: NodeType, M: NetworkMsg, - PROPOSAL: ProposalType, - VOTE: VoteType, MEMBERSHIP: Membership, NETWORK, ->: CommunicationChannel +>: CommunicationChannel { /// generates the `CommunicationChannel` given it's associated network type fn generate_network() -> Box) -> Self + 'static>; @@ -356,6 +371,7 @@ pub enum NetworkChange { } /// interface describing how reliable the network is +#[async_trait] pub trait NetworkReliability: Debug + Sync + std::marker::Send { /// Sample from bernoulli distribution to decide whether /// or not to keep a packet @@ -363,8 +379,225 @@ pub trait NetworkReliability: Debug + Sync + std::marker::Send { /// /// Panics if `self.keep_numerator > self.keep_denominator` /// - fn sample_keep(&self) -> bool; + fn sample_keep(&self) -> bool { + true + } + /// sample from uniform distribution to decide whether /// or not to keep a packet - fn sample_delay(&self) -> Duration; + fn sample_delay(&self) -> Duration { + std::time::Duration::ZERO + } + + /// scramble the packet + fn scramble(&self, msg: Vec) -> Vec { + msg + } + + /// number of times to repeat the packet + fn sample_repeat(&self) -> usize { + 1 + } + + /// given a message and a way to send the message, + /// decide whether or not to send the message + /// how long to delay the message + /// whether or not to send duplicates + /// and whether or not to include noise with the message + /// then send the message + fn chaos_send_msg( + &self, + msg: Vec, + send_fn: Arc) -> BoxSyncFuture<'static, ()>>, + ) -> BoxSyncFuture<'static, ()> { + let sample_keep = self.sample_keep(); + let delay = self.sample_delay(); + let repeats = self.sample_repeat(); + let mut msgs = Vec::new(); + for _idx in 0..repeats { + let scrambled = self.scramble(msg.clone()); + msgs.push(scrambled); + } + let closure = async move { + if sample_keep { + async_sleep(delay).await; + for msg in msgs { + send_fn(msg).await; + } + } + }; + boxed_sync(closure) + } +} + +/// ideal network +#[derive(Clone, Copy, Debug, Default)] +pub struct PerfectNetwork {} + +impl NetworkReliability for PerfectNetwork {} + +/// A synchronous network. Packets may be delayed, but are guaranteed +/// to arrive within `timeout` ns +#[derive(Clone, Copy, Debug, Default)] +pub struct SynchronousNetwork { + /// Max delay of packet before arrival + timeout_ms: u64, + /// Lowest value in milliseconds that a packet may be delayed + delay_low_ms: u64, +} + +impl NetworkReliability for SynchronousNetwork { + /// never drop a packet + fn sample_keep(&self) -> bool { + true + } + fn sample_delay(&self) -> Duration { + Duration::from_millis( + Uniform::new_inclusive(self.delay_low_ms, self.timeout_ms) + .sample(&mut rand::thread_rng()), + ) + } +} + +/// An asynchronous network. Packets may be dropped entirely +/// or delayed for arbitrarily long periods +/// probability that packet is kept = `keep_numerator` / `keep_denominator` +/// packet delay is obtained by sampling from a uniform distribution +/// between `delay_low_ms` and `delay_high_ms`, inclusive +#[derive(Debug, Clone, Copy)] +pub struct AsynchronousNetwork { + /// numerator for probability of keeping packets + keep_numerator: u32, + /// denominator for probability of keeping packets + keep_denominator: u32, + /// lowest value in milliseconds that a packet may be delayed + delay_low_ms: u64, + /// highest value in milliseconds that a packet may be delayed + delay_high_ms: u64, +} + +impl NetworkReliability for AsynchronousNetwork { + fn sample_keep(&self) -> bool { + Bernoulli::from_ratio(self.keep_numerator, self.keep_denominator) + .unwrap() + .sample(&mut rand::thread_rng()) + } + fn sample_delay(&self) -> Duration { + Duration::from_millis( + Uniform::new_inclusive(self.delay_low_ms, self.delay_high_ms) + .sample(&mut rand::thread_rng()), + ) + } +} + +/// An partially synchronous network. Behaves asynchronously +/// until some arbitrary time bound, GST, +/// then synchronously after GST +#[allow(clippy::similar_names)] +#[derive(Debug, Clone, Copy)] +pub struct PartiallySynchronousNetwork { + /// asynchronous portion of network + asynchronous: AsynchronousNetwork, + /// synchronous portion of network + synchronous: SynchronousNetwork, + /// time when GST occurs + gst: std::time::Duration, + /// when the network was started + start: std::time::Instant, +} + +impl NetworkReliability for PartiallySynchronousNetwork { + /// never drop a packet + fn sample_keep(&self) -> bool { + true + } + fn sample_delay(&self) -> Duration { + // act asyncronous before gst + if self.start.elapsed() < self.gst { + if self.asynchronous.sample_keep() { + self.asynchronous.sample_delay() + } else { + // assume packet was "dropped" and will arrive after gst + self.synchronous.sample_delay() + self.gst + } + } else { + // act syncronous after gst + self.synchronous.sample_delay() + } + } +} + +impl Default for AsynchronousNetwork { + // disable all chance of failure + fn default() -> Self { + AsynchronousNetwork { + keep_numerator: 1, + keep_denominator: 1, + delay_low_ms: 0, + delay_high_ms: 0, + } + } +} + +impl Default for PartiallySynchronousNetwork { + fn default() -> Self { + PartiallySynchronousNetwork { + synchronous: SynchronousNetwork::default(), + asynchronous: AsynchronousNetwork::default(), + gst: std::time::Duration::new(0, 0), + start: std::time::Instant::now(), + } + } +} + +impl SynchronousNetwork { + /// create new `SynchronousNetwork` + #[must_use] + pub fn new(timeout: u64, delay_low_ms: u64) -> Self { + SynchronousNetwork { + timeout_ms: timeout, + delay_low_ms, + } + } +} + +impl AsynchronousNetwork { + /// create new `AsynchronousNetwork` + #[must_use] + pub fn new( + keep_numerator: u32, + keep_denominator: u32, + delay_low_ms: u64, + delay_high_ms: u64, + ) -> Self { + AsynchronousNetwork { + keep_numerator, + keep_denominator, + delay_low_ms, + delay_high_ms, + } + } +} + +impl PartiallySynchronousNetwork { + /// create new `PartiallySynchronousNetwork` + #[allow(clippy::similar_names)] + #[must_use] + pub fn new( + asynchronous: AsynchronousNetwork, + synchronous: SynchronousNetwork, + gst: std::time::Duration, + ) -> Self { + PartiallySynchronousNetwork { + asynchronous, + synchronous, + gst, + start: std::time::Instant::now(), + } + } +} + +/// A chaotic network using all the networking calls +pub struct ChaosNetwork { + // TODO } diff --git a/crates/types/src/traits/node_implementation.rs b/crates/types/src/traits/node_implementation.rs index 8ba5abdebb..49d9184bc4 100644 --- a/crates/types/src/traits/node_implementation.rs +++ b/crates/types/src/traits/node_implementation.rs @@ -19,7 +19,7 @@ use crate::{ message::{ConsensusMessageType, Message, SequencingMessage}, traits::{ election::Membership, network::TestableChannelImplementation, signature_key::SignatureKey, - storage::Storage, Block, + storage::Storage, BlockPayload, }, }; use async_compatibility_layer::channel::{unbounded, UnboundedReceiver, UnboundedSender}; @@ -166,7 +166,6 @@ pub trait ExchangesType, MESSA /// Create all exchanges. fn create( entries: Vec<::StakeTableEntry>, - keys: Vec, configs: Self::ElectionConfigs, networks: ( >::Networking, @@ -184,7 +183,7 @@ pub trait ExchangesType, MESSA /// Get the view sync exchange. fn view_sync_exchange(&self) -> &Self::ViewSyncExchange; - /// Block the underlying networking interfaces until node is successfully initialized into the + /// BlockPayload the underlying networking interfaces until node is successfully initialized into the /// networks. async fn wait_for_networks_ready(&self); @@ -257,7 +256,6 @@ where fn create( entries: Vec<::StakeTableEntry>, - keys: Vec, configs: Self::ElectionConfigs, networks: ( >::Networking, @@ -270,7 +268,6 @@ where ) -> Self { let quorum_exchange = QUORUMEXCHANGE::create( entries.clone(), - keys.clone(), configs.0.clone(), networks.0, pk.clone(), @@ -279,7 +276,6 @@ where ); let view_sync_exchange = VIEWSYNCEXCHANGE::create( entries.clone(), - keys.clone(), configs.0, networks.2, pk.clone(), @@ -287,7 +283,7 @@ where sk.clone(), ); let committee_exchange = - COMMITTEEEXCHANGE::create(entries, keys, configs.1, networks.1, pk, entry, sk); + COMMITTEEEXCHANGE::create(entries, configs.1, networks.1, pk, entry, sk); Self { quorum_exchange, @@ -363,7 +359,7 @@ pub trait TestableNodeImplementation: NodeImplementation state: Option<&TYPES::StateType>, rng: &mut dyn rand::RngCore, padding: u64, - ) -> ::Transaction; + ) -> ::Transaction; /// Creates random transaction if possible /// otherwise panics @@ -372,7 +368,7 @@ pub trait TestableNodeImplementation: NodeImplementation leaf: &Self::Leaf, rng: &mut dyn rand::RngCore, padding: u64, - ) -> ::Transaction; + ) -> ::Transaction; /// generate a genesis block fn block_genesis() -> TYPES::BlockType; @@ -401,24 +397,18 @@ where QuorumCommChannel: TestableChannelImplementation< TYPES, Message, - QuorumProposalType, - QuorumVoteType, QuorumMembership, QuorumNetwork, >, CommitteeCommChannel: TestableChannelImplementation< TYPES, Message, - CommitteeProposalType, - CommitteeVote, CommitteeMembership, QuorumNetwork, >, ViewSyncCommChannel: TestableChannelImplementation< TYPES, Message, - ViewSyncProposalType, - ViewSyncVoteType, ViewSyncMembership, QuorumNetwork, >, @@ -438,7 +428,7 @@ where state: Option<&TYPES::StateType>, rng: &mut dyn rand::RngCore, padding: u64, - ) -> ::Transaction { + ) -> ::Transaction { ::create_random_transaction(state, rng, padding) } @@ -446,7 +436,7 @@ where leaf: &Self::Leaf, rng: &mut dyn rand::RngCore, padding: u64, - ) -> ::Transaction { + ) -> ::Transaction { ::create_random_transaction(leaf, rng, padding) } @@ -518,8 +508,6 @@ pub type ViewSyncMembership = QuorumMembership; pub type QuorumNetwork = as CommunicationChannel< TYPES, Message, - QuorumProposalType, - QuorumVoteType, QuorumMembership, >>::NETWORK; @@ -527,8 +515,6 @@ pub type QuorumNetwork = as Communication pub type CommitteeNetwork = as CommunicationChannel< TYPES, Message, - CommitteeProposalType, - CommitteeVote, CommitteeMembership, >>::NETWORK; @@ -536,8 +522,6 @@ pub type CommitteeNetwork = as Communi pub type ViewSyncNetwork = as CommunicationChannel< TYPES, Message, - ViewSyncProposalType, - ViewSyncVoteType, ViewSyncMembership, >>::NETWORK; @@ -565,14 +549,14 @@ pub trait NodeType: /// The block type that this hotshot setup is using. /// /// This should be the same block that `StateType::BlockType` is using. - type BlockType: Block; + type BlockType: BlockPayload; /// The signature key that this hotshot setup is using. type SignatureKey: SignatureKey; /// The vote token that this hotshot setup is using. type VoteTokenType: VoteToken; /// The transaction type that this hotshot setup is using. /// - /// This should be equal to `Block::Transaction` + /// This should be equal to `BlockPayload::Transaction` type Transaction: Transaction; /// The election config type that this hotshot setup is using. type ElectionConfigType: ElectionConfig; diff --git a/crates/types/src/traits/signature_key.rs b/crates/types/src/traits/signature_key.rs index 5daed175bd..d5141816f5 100644 --- a/crates/types/src/traits/signature_key.rs +++ b/crates/types/src/traits/signature_key.rs @@ -3,9 +3,6 @@ use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Read, Serializatio use bitvec::prelude::*; use espresso_systems_common::hotshot::tag; use ethereum_types::U256; -use jf_primitives::signatures::{ - bls_over_bn254::BLSOverBN254CurveSignatureScheme, SignatureScheme, -}; use serde::{Deserialize, Serialize}; use std::{fmt::Debug, hash::Hash}; use tagged_base64::tagged; @@ -23,17 +20,13 @@ use tagged_base64::tagged; PartialOrd, Ord, )] -pub struct EncodedPublicKey( - #[debug(with = "custom_debug::hexbuf")] pub Vec, // pub ::VerificationKey -); +pub struct EncodedPublicKey(#[debug(with = "custom_debug::hexbuf")] pub Vec); /// Type saftey wrapper for byte encoded signature #[derive( Clone, custom_debug::Debug, Hash, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, )] -pub struct EncodedSignature( - #[debug(with = "custom_debug::hexbuf")] pub Vec, // pub ::Signature -); +pub struct EncodedSignature(#[debug(with = "custom_debug::hexbuf")] pub Vec); impl AsRef<[u8]> for EncodedSignature { fn as_ref(&self) -> &[u8] { @@ -70,6 +63,17 @@ pub trait SignatureKey: + for<'a> Deserialize<'a>; /// The type of the quorum certificate parameters used for assembled signature type QCParams: Send + Sync + Sized + Clone + Debug + Hash; + /// The type of the assembled signature, without `BitVec` + type PureAssembledSignatureType: Send + + Sync + + Sized + + Clone + + Debug + + Hash + + PartialEq + + Eq + + Serialize + + for<'a> Deserialize<'a>; /// The type of the assembled qc: assembled signature + `BitVec` type QCType: Send + Sync @@ -101,6 +105,9 @@ pub trait SignatureKey: /// get the stake table entry from the public key and stake value fn get_stake_table_entry(&self, stake: u64) -> Self::StakeTableEntry; + /// only get the public key from the stake table entry + fn get_public_key(entry: &Self::StakeTableEntry) -> Self; + /// get the public parameter for the assembled signature checking fn get_public_parameter( stake_entries: Vec, @@ -111,17 +118,12 @@ pub trait SignatureKey: fn check(real_qc_pp: &Self::QCParams, data: &[u8], qc: &Self::QCType) -> bool; /// get the assembled signature and the `BitVec` separately from the assembled signature - fn get_sig_proof( - signature: &Self::QCType, - ) -> ( - ::Signature, - BitVec, - ); + fn get_sig_proof(signature: &Self::QCType) -> (Self::PureAssembledSignatureType, BitVec); /// assemble the signature from the partial signature and the indication of signers in `BitVec` fn assemble( real_qc_pp: &Self::QCParams, signers: &BitSlice, - sigs: &[::Signature], + sigs: &[Self::PureAssembledSignatureType], ) -> Self::QCType; } diff --git a/crates/types/src/traits/state.rs b/crates/types/src/traits/state.rs index 83fb250442..bd8fe7d2ed 100644 --- a/crates/types/src/traits/state.rs +++ b/crates/types/src/traits/state.rs @@ -3,7 +3,7 @@ //! This module provides the [`State`] trait, which serves as an compatibility over the current //! network state, which is modified by the transactions contained within blocks. -use crate::traits::Block; +use crate::traits::BlockPayload; use commit::Committable; use espresso_systems_common::hotshot::tag; use serde::{de::DeserializeOwned, Serialize}; @@ -19,9 +19,7 @@ use std::{ /// /// This trait represents the behaviors that the 'global' ledger state must have: /// * A defined error type ([`Error`](State::Error)) -/// * The type of block that modifies this type of state ([`Block`](State::BlockType)) -/// * A method to get a template (empty) next block from the current state -/// ([`next_block`](State::next_block)) +/// * The type of block that modifies this type of state ([`BlockPayload`](State::BlockType)) /// * The ability to validate that a block is actually a valid extension of this state /// ([`validate_block`](State::validate_block)) /// * The ability to produce a new state, with the modifications from the block applied @@ -42,13 +40,10 @@ pub trait State: /// The error type for this particular type of ledger state type Error: Error + Debug + Send + Sync; /// The type of block this state is associated with - type BlockType: Block; + type BlockType: BlockPayload; /// Time compatibility needed for reward collection type Time: ConsensusTime; - /// Returns an empty, template next block given this current state - fn next_block(prev_commitment: Option) -> Self::BlockType; - /// Returns true if and only if the provided block is valid and can extend this state fn validate_block(&self, block: &Self::BlockType, view_number: &Self::Time) -> bool; @@ -109,11 +104,11 @@ where state: Option<&Self>, rng: &mut dyn rand::RngCore, padding: u64, - ) -> ::Transaction; + ) -> ::Transaction; } /// extra functions required on block to be usable by hotshot-testing -pub trait TestableBlock: Block + Debug { +pub trait TestableBlock: BlockPayload + Debug { /// generate a genesis block fn genesis() -> Self; @@ -165,13 +160,6 @@ pub mod dummy { type BlockType = DummyBlock; type Time = ViewNumber; - fn next_block(state: Option) -> Self::BlockType { - match state { - Some(state) => DummyBlock { nonce: state.nonce }, - None => unimplemented!(), - } - } - fn validate_block(&self, _block: &Self::BlockType, _view_number: &Self::Time) -> bool { false } diff --git a/crates/types/src/traits/storage.rs b/crates/types/src/traits/storage.rs index 41b7cc225a..122698486c 100644 --- a/crates/types/src/traits/storage.rs +++ b/crates/types/src/traits/storage.rs @@ -4,7 +4,7 @@ use super::{node_implementation::NodeType, signature_key::EncodedPublicKey}; use crate::{ certificate::QuorumCertificate, data::LeafType, - traits::{election::SignedCertificate, Block}, + traits::{election::SignedCertificate, BlockPayload}, }; use async_trait::async_trait; use commit::Commitment; @@ -132,7 +132,7 @@ pub struct StoredView> { /// The parent of this view pub parent: Commitment, /// The justify QC of this view. See the hotstuff paper for more information on this. - pub justify_qc: QuorumCertificate, + pub justify_qc: QuorumCertificate>, /// The state of this view pub state: LEAF::MaybeState, /// The deltas of this view @@ -152,16 +152,16 @@ where TYPES: NodeType, LEAF: LeafType, { - /// Create a new `StoredView` from the given QC, Block and State. + /// Create a new `StoredView` from the given QC, `BlockPayload` and State. /// /// Note that this will set the `parent` to `LeafHash::default()`, so this will not have a parent. pub fn from_qc_block_and_state( - qc: QuorumCertificate, + qc: QuorumCertificate>, deltas: LEAF::DeltasType, state: LEAF::MaybeState, height: u64, parent_commitment: Commitment, - rejected: Vec<::Transaction>, + rejected: Vec<::Transaction>, proposer_id: EncodedPublicKey, ) -> Self { Self { diff --git a/crates/types/src/vote.rs b/crates/types/src/vote.rs index cdbb8cb03f..9e232b755a 100644 --- a/crates/types/src/vote.rs +++ b/crates/types/src/vote.rs @@ -5,7 +5,6 @@ use crate::{ certificate::{AssembledSignature, QuorumCertificate}, - data::LeafType, traits::{ election::{VoteData, VoteToken}, node_implementation::NodeType, @@ -14,27 +13,34 @@ use crate::{ }; use bincode::Options; use bitvec::prelude::*; -use commit::{Commitment, Committable}; +use commit::{Commitment, CommitmentBounds, Committable}; use either::Either; use ethereum_types::U256; use hotshot_utils::bincode::bincode_opts; -use jf_primitives::signatures::{ - bls_over_bn254::BLSOverBN254CurveSignatureScheme, SignatureScheme, -}; use serde::{Deserialize, Serialize}; use std::{ collections::{BTreeMap, HashMap}, fmt::Debug, + hash::Hash, + marker::PhantomData, num::NonZeroU64, }; use tracing::error; /// The vote sent by consensus messages. -pub trait VoteType: +pub trait VoteType: Debug + Clone + 'static + Serialize + for<'a> Deserialize<'a> + Send + Sync + PartialEq { - /// The view this vote was cast for. - fn current_view(&self) -> TYPES::Time; + /// Get the view this vote was cast for + fn get_view(&self) -> TYPES::Time; + /// Get the signature key associated with this vote + fn get_key(&self) -> TYPES::SignatureKey; + /// Get the signature associated with this vote + fn get_signature(&self) -> EncodedSignature; + /// Get the data this vote was signed over + fn get_data(&self) -> VoteData; + /// Get the vote token of this vote + fn get_vote_token(&self) -> TYPES::VoteTokenType; } /// A vote on DA proposal. @@ -50,35 +56,35 @@ pub struct DAVote { /// The vote token generated by this replica pub vote_token: TYPES::VoteTokenType, /// The vote data this vote is signed over - pub vote_data: VoteData, + pub vote_data: VoteData>, } /// A positive or negative vote on validating or commitment proposal. #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)] #[serde(bound(deserialize = ""))] -pub struct YesOrNoVote> { +pub struct YesOrNoVote { /// TODO we should remove this /// this is correct, but highly inefficient /// we should check a cache, and if that fails request the qc - pub justify_qc_commitment: Commitment>, + pub justify_qc_commitment: Commitment>, /// The signature share associated with this vote pub signature: (EncodedPublicKey, EncodedSignature), /// The leaf commitment being voted on. - pub leaf_commitment: Commitment, + pub leaf_commitment: COMMITMENT, /// The view this vote was cast for pub current_view: TYPES::Time, /// The vote token generated by this replica pub vote_token: TYPES::VoteTokenType, /// The vote data this vote is signed over - pub vote_data: VoteData, + pub vote_data: VoteData, } /// A timeout vote. #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)] #[serde(bound(deserialize = ""))] -pub struct TimeoutVote> { +pub struct TimeoutVote { /// The highest valid QC this node knows about - pub high_qc: QuorumCertificate, + pub high_qc: QuorumCertificate, /// The signature share associated with this vote pub signature: (EncodedPublicKey, EncodedSignature), /// The view this vote was cast for @@ -86,7 +92,7 @@ pub struct TimeoutVote> { /// The vote token generated by this replica pub vote_token: TYPES::VoteTokenType, /// The vote data this vote is signed over - pub vote_data: VoteData, + pub vote_data: VoteData>, } /// The internals of a view sync vote @@ -104,7 +110,7 @@ pub struct ViewSyncVoteInternal { /// The vote token generated by this replica pub vote_token: TYPES::VoteTokenType, /// The vote data this vote is signed over - pub vote_data: VoteData>, + pub vote_data: VoteData>>, } /// The data View Sync votes are signed over @@ -181,19 +187,31 @@ impl ViewSyncVote { /// Votes on validating or commitment proposal. #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)] #[serde(bound(deserialize = ""))] -pub enum QuorumVote> { +pub enum QuorumVote { /// Posivite vote. - Yes(YesOrNoVote), + Yes(YesOrNoVote), /// Negative vote. - No(YesOrNoVote), + No(YesOrNoVote), /// Timeout vote. - Timeout(TimeoutVote), + Timeout(TimeoutVote), } -impl VoteType for DAVote { - fn current_view(&self) -> TYPES::Time { +impl VoteType> for DAVote { + fn get_view(&self) -> TYPES::Time { self.current_view } + fn get_key(&self) -> ::SignatureKey { + self.signature_key() + } + fn get_signature(&self) -> EncodedSignature { + self.signature.1.clone() + } + fn get_data(&self) -> VoteData> { + self.vote_data.clone() + } + fn get_vote_token(&self) -> ::VoteTokenType { + self.vote_token.clone() + } } impl DAVote { @@ -205,19 +223,39 @@ impl DAVote { } } -impl> VoteType - for QuorumVote +impl VoteType + for QuorumVote { - fn current_view(&self) -> TYPES::Time { + fn get_view(&self) -> TYPES::Time { match self { QuorumVote::Yes(v) | QuorumVote::No(v) => v.current_view, QuorumVote::Timeout(v) => v.current_view, } } + + fn get_key(&self) -> ::SignatureKey { + self.signature_key() + } + fn get_signature(&self) -> EncodedSignature { + self.signature() + } + fn get_data(&self) -> VoteData { + match self { + QuorumVote::Yes(v) | QuorumVote::No(v) => v.vote_data.clone(), + QuorumVote::Timeout(_) => unimplemented!(), + } + } + fn get_vote_token(&self) -> ::VoteTokenType { + match self { + QuorumVote::Yes(v) | QuorumVote::No(v) => v.vote_token.clone(), + QuorumVote::Timeout(_) => unimplemented!(), + } + } } -impl> QuorumVote { +impl QuorumVote { /// Get the encoded signature. + pub fn signature(&self) -> EncodedSignature { match &self { Self::Yes(vote) | Self::No(vote) => vote.signature.1.clone(), @@ -227,6 +265,7 @@ impl> QuorumVote /// Get the signature key. /// # Panics /// If the deserialization fails. + pub fn signature_key(&self) -> TYPES::SignatureKey { let encoded = match &self { Self::Yes(vote) | Self::No(vote) => vote.signature.0.clone(), @@ -236,14 +275,36 @@ impl> QuorumVote } } -impl VoteType for ViewSyncVote { - fn current_view(&self) -> TYPES::Time { +impl VoteType>> for ViewSyncVote { + fn get_view(&self) -> TYPES::Time { match self { ViewSyncVote::PreCommit(v) | ViewSyncVote::Commit(v) | ViewSyncVote::Finalize(v) => { v.round } } } + fn get_key(&self) -> ::SignatureKey { + self.signature_key() + } + + fn get_signature(&self) -> EncodedSignature { + self.signature() + } + fn get_data(&self) -> VoteData>> { + match self { + ViewSyncVote::PreCommit(vote_internal) + | ViewSyncVote::Commit(vote_internal) + | ViewSyncVote::Finalize(vote_internal) => vote_internal.vote_data.clone(), + } + } + + fn get_vote_token(&self) -> ::VoteTokenType { + match self { + ViewSyncVote::PreCommit(vote_internal) + | ViewSyncVote::Commit(vote_internal) + | ViewSyncVote::Finalize(vote_internal) => vote_internal.vote_token.clone(), + } + } } /// The aggreation of votes, implemented by `VoteAccumulator`. @@ -255,18 +316,449 @@ pub trait Accumulator: Sized { fn append(self, val: T) -> Either; } +/// Accumulator trait used to accumulate votes into an `AssembledSignature` +pub trait Accumulator2< + TYPES: NodeType, + COMMITMENT: CommitmentBounds, + VOTE: VoteType, +>: Sized +{ + /// Append 1 vote to the accumulator. If the threshold is not reached, return + /// the accumulator, else return the `AssembledSignature` + /// Only called from inside `accumulate_internal` + fn append( + self, + vote: VOTE, + vote_node_id: usize, + stake_table_entries: Vec<::StakeTableEntry>, + ) -> Either>; +} + +/// Accumulates DA votes +pub struct DAVoteAccumulator< + TYPES: NodeType, + COMMITMENT: CommitmentBounds, + VOTE: VoteType, +> { + /// Map of all da signatures accumlated so far + pub da_vote_outcomes: VoteMap, + /// A quorum's worth of stake, generally 2f + 1 + pub success_threshold: NonZeroU64, + /// A list of valid signatures for certificate aggregation + pub sig_lists: Vec<::PureAssembledSignatureType>, + /// A bitvec to indicate which node is active and send out a valid signature for certificate aggregation, this automatically do uniqueness check + pub signers: BitVec, + /// Phantom data to specify the vote this accumulator is for + pub phantom: PhantomData, +} + +impl> + Accumulator2 for DAVoteAccumulator +{ + fn append( + mut self, + vote: VOTE, + vote_node_id: usize, + stake_table_entries: Vec<::StakeTableEntry>, + ) -> Either> { + let VoteData::DA(vote_commitment) = vote.get_data() else { + return Either::Left(self); + }; + + let encoded_key = vote.get_key().to_bytes(); + + // Deserialize the signature so that it can be assembeld into a QC + // TODO ED Update this once we've gotten rid of EncodedSignature + let original_signature: ::PureAssembledSignatureType = + bincode_opts() + .deserialize(&vote.get_signature().0) + .expect("Deserialization on the signature shouldn't be able to fail."); + + let (da_stake_casted, da_vote_map) = self + .da_vote_outcomes + .entry(vote_commitment) + .or_insert_with(|| (0, BTreeMap::new())); + + // Check for duplicate vote + // TODO ED Re-encoding signature key to bytes until we get rid of EncodedKey + // Have to do this because SignatureKey is not hashable + if da_vote_map.contains_key(&encoded_key) { + return Either::Left(self); + } + + if self.signers.get(vote_node_id).as_deref() == Some(&true) { + error!("Node id is already in signers list"); + return Either::Left(self); + } + self.signers.set(vote_node_id, true); + self.sig_lists.push(original_signature); + + // Already checked that vote data was for a DA vote above + *da_stake_casted += u64::from(vote.get_vote_token().vote_count()); + da_vote_map.insert( + encoded_key, + (vote.get_signature(), vote.get_data(), vote.get_vote_token()), + ); + + if *da_stake_casted >= u64::from(self.success_threshold) { + // Assemble QC + let real_qc_pp = ::get_public_parameter( + // TODO ED Something about stake table entries. Might be easier to just pass in membership? + stake_table_entries.clone(), + U256::from(self.success_threshold.get()), + ); + + let real_qc_sig = ::assemble( + &real_qc_pp, + self.signers.as_bitslice(), + &self.sig_lists[..], + ); + + self.da_vote_outcomes.remove(&vote_commitment); + + return Either::Right(AssembledSignature::DA(real_qc_sig)); + } + Either::Left(self) + } +} + +/// Accumulate quorum votes +pub struct QuorumVoteAccumulator< + TYPES: NodeType, + COMMITMENT: CommitmentBounds, + VOTE: VoteType, +> { + /// Map of all signatures accumlated so far + pub total_vote_outcomes: VoteMap, + /// Map of all yes signatures accumlated so far + pub yes_vote_outcomes: VoteMap, + /// Map of all no signatures accumlated so far + pub no_vote_outcomes: VoteMap, + + /// A quorum's worth of stake, generally 2f + 1 + pub success_threshold: NonZeroU64, + /// A failure threshold, generally f + 1 + pub failure_threshold: NonZeroU64, + /// A list of valid signatures for certificate aggregation + pub sig_lists: Vec<::PureAssembledSignatureType>, + /// A bitvec to indicate which node is active and send out a valid signature for certificate aggregation, this automatically do uniqueness check + pub signers: BitVec, + /// Phantom data to ensure this struct is over a specific `VoteType` implementation + pub phantom: PhantomData, +} + +impl> + Accumulator2 for QuorumVoteAccumulator +{ + fn append( + mut self, + vote: VOTE, + vote_node_id: usize, + stake_table_entries: Vec<::StakeTableEntry>, + ) -> Either> { + let (VoteData::Yes(vote_commitment) | VoteData::No(vote_commitment)) = vote.get_data() + else { + return Either::Left(self); + }; + + let encoded_key = vote.get_key().to_bytes(); + + // Deserialize the signature so that it can be assembeld into a QC + // TODO ED Update this once we've gotten rid of EncodedSignature + let original_signature: ::PureAssembledSignatureType = + bincode_opts() + .deserialize(&vote.get_signature().0) + .expect("Deserialization on the signature shouldn't be able to fail."); + + let (total_stake_casted, total_vote_map) = self + .total_vote_outcomes + .entry(vote_commitment) + .or_insert_with(|| (0, BTreeMap::new())); + + let (yes_stake_casted, yes_vote_map) = self + .yes_vote_outcomes + .entry(vote_commitment) + .or_insert_with(|| (0, BTreeMap::new())); + + let (no_stake_casted, no_vote_map) = self + .no_vote_outcomes + .entry(vote_commitment) + .or_insert_with(|| (0, BTreeMap::new())); + + // Check for duplicate vote + // TODO ED Re-encoding signature key to bytes until we get rid of EncodedKey + // Have to do this because SignatureKey is not hashable + if total_vote_map.contains_key(&encoded_key) { + return Either::Left(self); + } + + if self.signers.get(vote_node_id).as_deref() == Some(&true) { + error!("Node id is already in signers list"); + return Either::Left(self); + } + self.signers.set(vote_node_id, true); + self.sig_lists.push(original_signature); + + // TODO ED Make all these get calls as local variables to avoid constantly calling them + *total_stake_casted += u64::from(vote.get_vote_token().vote_count()); + total_vote_map.insert( + encoded_key.clone(), + (vote.get_signature(), vote.get_data(), vote.get_vote_token()), + ); + + match vote.get_data() { + VoteData::Yes(_) => { + *yes_stake_casted += u64::from(vote.get_vote_token().vote_count()); + yes_vote_map.insert( + encoded_key, + (vote.get_signature(), vote.get_data(), vote.get_vote_token()), + ); + } + VoteData::No(_) => { + *no_stake_casted += u64::from(vote.get_vote_token().vote_count()); + no_vote_map.insert( + encoded_key, + (vote.get_signature(), vote.get_data(), vote.get_vote_token()), + ); + } + _ => return Either::Left(self), + } + + if *total_stake_casted >= u64::from(self.success_threshold) { + // Assemble QC + let real_qc_pp = ::get_public_parameter( + // TODO ED Something about stake table entries. Might be easier to just pass in membership? + stake_table_entries.clone(), + U256::from(self.success_threshold.get()), + ); + + let real_qc_sig = ::assemble( + &real_qc_pp, + self.signers.as_bitslice(), + &self.sig_lists[..], + ); + + if *yes_stake_casted >= u64::from(self.success_threshold) { + self.yes_vote_outcomes.remove(&vote_commitment); + return Either::Right(AssembledSignature::Yes(real_qc_sig)); + } else if *no_stake_casted >= u64::from(self.failure_threshold) { + self.total_vote_outcomes.remove(&vote_commitment); + return Either::Right(AssembledSignature::No(real_qc_sig)); + } + } + Either::Left(self) + } +} + +/// Accumulates view sync votes +pub struct ViewSyncVoteAccumulator< + TYPES: NodeType, + COMMITMENT: CommitmentBounds, + VOTE: VoteType, +> { + /// Map of all pre_commit signatures accumlated so far + pub pre_commit_vote_outcomes: VoteMap, + /// Map of all ommit signatures accumlated so far + pub commit_vote_outcomes: VoteMap, + /// Map of all finalize signatures accumlated so far + pub finalize_vote_outcomes: VoteMap, + + /// A quorum's worth of stake, generally 2f + 1 + pub success_threshold: NonZeroU64, + /// A quorum's failure threshold, generally f + 1 + pub failure_threshold: NonZeroU64, + /// A list of valid signatures for certificate aggregation + pub sig_lists: Vec<::PureAssembledSignatureType>, + /// A bitvec to indicate which node is active and send out a valid signature for certificate aggregation, this automatically do uniqueness check + pub signers: BitVec, + /// Phantom data since we want the accumulator to be attached to a single `VoteType` + pub phantom: PhantomData, +} + +impl> + Accumulator2 for ViewSyncVoteAccumulator +{ + #[allow(clippy::too_many_lines)] + fn append( + mut self, + vote: VOTE, + vote_node_id: usize, + stake_table_entries: Vec<::StakeTableEntry>, + ) -> Either> { + let (VoteData::ViewSyncPreCommit(vote_commitment) + | VoteData::ViewSyncCommit(vote_commitment) + | VoteData::ViewSyncFinalize(vote_commitment)) = vote.get_data() + else { + return Either::Left(self); + }; + + // error!("Vote is {:?}", vote.clone()); + + let encoded_key = vote.get_key().to_bytes(); + + // Deserialize the signature so that it can be assembeld into a QC + // TODO ED Update this once we've gotten rid of EncodedSignature + let original_signature: ::PureAssembledSignatureType = + bincode_opts() + .deserialize(&vote.get_signature().0) + .expect("Deserialization on the signature shouldn't be able to fail."); + + let (pre_commit_stake_casted, pre_commit_vote_map) = self + .pre_commit_vote_outcomes + .entry(vote_commitment) + .or_insert_with(|| (0, BTreeMap::new())); + + // Check for duplicate vote + if pre_commit_vote_map.contains_key(&encoded_key) { + return Either::Left(self); + } + + let (commit_stake_casted, commit_vote_map) = self + .commit_vote_outcomes + .entry(vote_commitment) + .or_insert_with(|| (0, BTreeMap::new())); + + if commit_vote_map.contains_key(&encoded_key) { + return Either::Left(self); + } + + let (finalize_stake_casted, finalize_vote_map) = self + .finalize_vote_outcomes + .entry(vote_commitment) + .or_insert_with(|| (0, BTreeMap::new())); + + if finalize_vote_map.contains_key(&encoded_key) { + return Either::Left(self); + } + + // update the active_keys and sig_lists + // TODO ED Possible bug where a node sends precommit vote and then commit vote after + // precommit cert is formed, their commit vote won't be counted because of this check + // Probably need separate signers vecs. + if self.signers.get(vote_node_id).as_deref() == Some(&true) { + error!("node id already in signers"); + return Either::Left(self); + } + self.signers.set(vote_node_id, true); + self.sig_lists.push(original_signature); + + match vote.get_data() { + VoteData::ViewSyncPreCommit(_) => { + *pre_commit_stake_casted += u64::from(vote.get_vote_token().vote_count()); + pre_commit_vote_map.insert( + encoded_key, + (vote.get_signature(), vote.get_data(), vote.get_vote_token()), + ); + } + VoteData::ViewSyncCommit(_) => { + *commit_stake_casted += u64::from(vote.get_vote_token().vote_count()); + commit_vote_map.insert( + encoded_key, + (vote.get_signature(), vote.get_data(), vote.get_vote_token()), + ); + } + VoteData::ViewSyncFinalize(_) => { + *finalize_stake_casted += u64::from(vote.get_vote_token().vote_count()); + finalize_vote_map.insert( + encoded_key, + (vote.get_signature(), vote.get_data(), vote.get_vote_token()), + ); + } + _ => unimplemented!(), + } + + if *pre_commit_stake_casted >= u64::from(self.failure_threshold) { + let real_qc_pp = ::get_public_parameter( + stake_table_entries, + U256::from(self.failure_threshold.get()), + ); + + let real_qc_sig = ::assemble( + &real_qc_pp, + self.signers.as_bitslice(), + &self.sig_lists[..], + ); + + self.pre_commit_vote_outcomes + .remove(&vote_commitment) + .unwrap(); + return Either::Right(AssembledSignature::ViewSyncPreCommit(real_qc_sig)); + } + + if *commit_stake_casted >= u64::from(self.success_threshold) { + let real_qc_pp = ::get_public_parameter( + stake_table_entries.clone(), + U256::from(self.success_threshold.get()), + ); + + let real_qc_sig = ::assemble( + &real_qc_pp, + self.signers.as_bitslice(), + &self.sig_lists[..], + ); + self.commit_vote_outcomes.remove(&vote_commitment).unwrap(); + return Either::Right(AssembledSignature::ViewSyncCommit(real_qc_sig)); + } + + if *finalize_stake_casted >= u64::from(self.success_threshold) { + let real_qc_pp = ::get_public_parameter( + stake_table_entries.clone(), + U256::from(self.success_threshold.get()), + ); + + let real_qc_sig = ::assemble( + &real_qc_pp, + self.signers.as_bitslice(), + &self.sig_lists[..], + ); + self.finalize_vote_outcomes + .remove(&vote_commitment) + .unwrap(); + return Either::Right(AssembledSignature::ViewSyncFinalize(real_qc_sig)); + } + + Either::Left(self) + } +} + +/// Placeholder accumulator; will be replaced by accumulator for each certificate type +pub struct AccumulatorPlaceholder< + TYPES: NodeType, + COMMITMENT: CommitmentBounds, + VOTE: VoteType, +> { + /// Phantom data to make compiler happy + pub phantom: PhantomData<(TYPES, VOTE, COMMITMENT)>, +} + +impl> + Accumulator2 for AccumulatorPlaceholder +{ + fn append( + self, + _vote: VOTE, + _vote_node_id: usize, + _stake_table_entries: Vec<::StakeTableEntry>, + ) -> Either> { + either::Left(self) + } +} + /// Mapping of commitments to vote tokens by key. -type VoteMap = HashMap< - Commitment, +// TODO ED Remove this whole token generic +type VoteMap = HashMap< + COMMITMENT, ( u64, - BTreeMap, TOKEN)>, + BTreeMap, TOKEN)>, ), >; /// Describe the process of collecting signatures on block or leaf commitment, to form a DAC or QC, /// respectively. -pub struct VoteAccumulator { +/// +/// TODO GG used only in election.rs; move this to there and make it private? +pub struct VoteAccumulator { /// Map of all signatures accumlated so far pub total_vote_outcomes: VoteMap, /// Map of all da signatures accumlated so far @@ -286,28 +778,28 @@ pub struct VoteAccumulator { /// Enough stake to know that we cannot possibly get a quorum, generally f + 1 pub failure_threshold: NonZeroU64, /// A list of valid signatures for certificate aggregation - pub sig_lists: Vec<::Signature>, + pub sig_lists: Vec<::PureAssembledSignatureType>, /// A bitvec to indicate which node is active and send out a valid signature for certificate aggregation, this automatically do uniqueness check pub signers: BitVec, } -impl +impl Accumulator< ( - Commitment, + COMMITMENT, ( EncodedPublicKey, ( EncodedSignature, Vec<::StakeTableEntry>, usize, - VoteData, + VoteData, TOKEN, ), ), ), AssembledSignature, - > for VoteAccumulator + > for VoteAccumulator where TOKEN: Clone + VoteToken, { @@ -315,14 +807,14 @@ where fn append( mut self, val: ( - Commitment, + COMMITMENT, ( EncodedPublicKey, ( EncodedSignature, Vec<::StakeTableEntry>, usize, - VoteData, + VoteData, TOKEN, ), ), @@ -331,7 +823,7 @@ where let (commitment, (key, (sig, entries, node_id, vote_data, token))) = val; // Desereialize the sig so that it can be assembeld into a QC - let origianl_sig: ::Signature = + let original_signature: ::PureAssembledSignatureType = bincode_opts() .deserialize(&sig.0) .expect("Deserialization on the signature shouldn't be able to fail."); @@ -385,7 +877,7 @@ where return Either::Left(self); } self.signers.set(node_id, true); - self.sig_lists.push(origianl_sig); + self.sig_lists.push(original_signature); *total_stake_casted += u64::from(token.vote_count()); total_vote_map.insert(key.clone(), (sig.clone(), vote_data.clone(), token.clone())); diff --git a/crates/web_server/Cargo.toml b/crates/web_server/Cargo.toml index 827d5a5258..bc2520065a 100644 --- a/crates/web_server/Cargo.toml +++ b/crates/web_server/Cargo.toml @@ -22,7 +22,6 @@ hotshot-types = { path = "../types", default-features = false } hotshot-utils = { path = "../utils" } jf-primitives = { workspace = true } tide-disco = { git = "https://github.com/EspressoSystems/tide-disco.git", tag = "v0.4.1" } -nll = { workspace = true } tracing = { workspace = true } rand = { workspace = true } serde = { workspace = true } @@ -30,8 +29,6 @@ serde_json = "1.0.96" snafu = { workspace = true } tide = { version = "0.16.0", default-features = false } toml = { workspace = true } -portpicker = "0.1" -surf-disco = { workspace = true } [dev-dependencies] hotshot-types = { path = "../types", default-features = false } diff --git a/crates/web_server/api.toml b/crates/web_server/api.toml index 5f749bcdb0..cc610fc9c9 100644 --- a/crates/web_server/api.toml +++ b/crates/web_server/api.toml @@ -11,6 +11,13 @@ DOC = """ Return the proposal for a given view number """ +# GET the proposal for a view, where the view is passed as an argument +[route.getrecentproposal] +PATH = ["proposal/"] +DOC = """ +Return the proposal for the most recent view the server has +""" + # POST a proposal, where the view is passed as an argument [route.postproposal] PATH = ["proposal/:view_number"] diff --git a/crates/web_server/src/config.rs b/crates/web_server/src/config.rs index 1da2781c55..f9d0e7c0c7 100644 --- a/crates/web_server/src/config.rs +++ b/crates/web_server/src/config.rs @@ -17,6 +17,10 @@ pub fn post_proposal_route(view_number: u64) -> String { format!("api/proposal/{view_number}") } +pub fn get_recent_proposal_route() -> String { + "api/proposal".to_string() +} + pub fn get_da_certificate_route(view_number: u64) -> String { format!("api/certificate/{view_number}") } @@ -33,6 +37,30 @@ pub fn post_vote_route(view_number: u64) -> String { format!("api/votes/{view_number}") } +pub fn get_vid_disperse_route(view_number: u64) -> String { + format!("api/vid/disperse/{view_number}") +} + +pub fn post_vid_disperse_route(view_number: u64) -> String { + format!("api/vid/disperse/{view_number}") +} + +pub fn get_vid_vote_route(view_number: u64, index: u64) -> String { + format!("api/vid/votes/{view_number}/{index}") +} + +pub fn post_vid_vote_route(view_number: u64) -> String { + format!("api/vid/votes/{view_number}") +} + +pub fn get_vid_cert_route(view_number: u64) -> String { + format!("api/vid/cert/{view_number}") +} + +pub fn post_vid_cert_route(view_number: u64) -> String { + format!("api/vid/cert/{view_number}") +} + pub fn get_transactions_route(index: u64) -> String { format!("api/transactions/{index}") } diff --git a/crates/web_server/src/lib.rs b/crates/web_server/src/lib.rs index ac2730b448..e29ce036e8 100644 --- a/crates/web_server/src/lib.rs +++ b/crates/web_server/src/lib.rs @@ -33,6 +33,8 @@ struct WebServerState { da_certificates: HashMap)>, /// view for oldest proposals in memory oldest_proposal: u64, + /// view for the most recent proposal to help nodes catchup + recent_proposal: u64, /// view for teh oldest DA certificate oldest_certificate: u64, @@ -74,6 +76,7 @@ impl WebServerState { num_txns: 0, oldest_vote: 0, oldest_proposal: 0, + recent_proposal: 0, oldest_certificate: 0, shutdown: None, stake_table: Vec::new(), @@ -101,6 +104,7 @@ impl WebServerState { /// Trait defining methods needed for the `WebServerState` pub trait WebServerDataSource { fn get_proposal(&self, view_number: u64) -> Result>>, Error>; + fn get_recent_proposal(&self) -> Result>>, Error>; fn get_view_sync_proposal( &self, view_number: u64, @@ -156,6 +160,10 @@ impl WebServerDataSource for WebServerState { } } + fn get_recent_proposal(&self) -> Result>>, Error> { + self.get_proposal(self.recent_proposal) + } + fn get_view_sync_proposal( &self, view_number: u64, @@ -316,6 +324,10 @@ impl WebServerDataSource for WebServerState { fn post_proposal(&mut self, view_number: u64, mut proposal: Vec) -> Result<(), Error> { debug!("Received proposal for view {}", view_number); + if view_number > self.recent_proposal { + self.recent_proposal = view_number; + } + // Only keep proposal history for MAX_VIEWS number of view if self.proposals.len() >= MAX_VIEWS { self.proposals.remove(&self.oldest_proposal); @@ -495,6 +507,9 @@ where } .boxed() })? + .get("getrecentproposal", |_req, state| { + async move { state.get_recent_proposal() }.boxed() + })? .get("getviewsyncproposal", |req, state| { async move { let view_number: u64 = req.integer_param("view_number")?; diff --git a/docs/espresso-sequencer-paper.pdf b/docs/espresso-sequencer-paper.pdf index add7843500dc3a5305b6f58d1c020c0fde9a3efb..a5aeb7eac6c34115bb3cdfb8e40ba83111038d14 100644 GIT binary patch delta 460422 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�=#MI! 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

|Fx*Wi=oX;sTORf)WP8ggr*reJ<4iux&eJw@yB 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

WX{?d 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%0DC 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%0A}KE0xsmrV)aZ~tKn*Jh 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%0Ab5{V+dHzF$+Z`jgoZ0P%jxT7 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 OH(9Zp)YJ@Lc_L)Gcp{FRr0NH`uIzW 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::BlockType; type SignatureKey = #signature_key_type; - type Transaction = <<#demo_state as hotshot_types::traits::State>::BlockType as hotshot_types::traits::Block>::Transaction; + type Transaction = <<#demo_state as hotshot_types::traits::State>::BlockType as hotshot_types::traits::BlockPayload>::Transaction; type StateType = #demo_state; type VoteTokenType = hotshot::traits::election::static_committee::StaticVoteToken; type ElectionConfigType = hotshot::traits::election::static_committee::StaticElectionConfig; @@ -616,8 +616,8 @@ pub fn cross_all_types(input: TokenStream) -> TokenStream { slow, } = parse_macro_input!(input as CrossAllTypesSpec); let tokens = quote! { - DemoType: [ /* (SequencingConsensus, hotshot::demos::sdemo::SDemoState), */ (ValidatingConsensus, hotshot::demos::vdemo::VDemoState) ], - SignatureKey: [ hotshot_types::traits::signature_key::bn254::BN254Pub ], + DemoType: [ /* (SequencingConsensus, hotshot::demo::SDemoState), */ (ValidatingConsensus, hotshot::demos::vdemo::VDemoState) ], + SignatureKey: [ hotshot_types::traits::signature_key::bn254::BLSPubKey ], CommChannel: [ hotshot::traits::implementations::Libp2pCommChannel, hotshot::traits::implementations::CentralizedCommChannel ], Time: [ hotshot_types::data::ViewNumber ], Storage: [ hotshot::traits::implementations::MemoryStorage ], diff --git a/testing-macros/tests/integration/failures.rs b/testing-macros/tests/integration/failures.rs index bb74781229..cbe2ce5619 100644 --- a/testing-macros/tests/integration/failures.rs +++ b/testing-macros/tests/integration/failures.rs @@ -2,7 +2,7 @@ use hotshot_testing_macros::cross_tests; cross_tests!( DemoType: [ (ValidatingConsensus, hotshot::demos::vdemo::VDemoState) ], - SignatureKey: [ hotshot_types::traits::signature_key::bn254::BN254Pub ], + SignatureKey: [ hotshot_types::traits::signature_key::bn254::BLSPubKey ], CommChannel: [ hotshot::traits::implementations::MemoryCommChannel ], Storage: [ hotshot::traits::implementations::MemoryStorage ], Time: [ hotshot_types::data::ViewNumber ], @@ -37,7 +37,7 @@ cross_tests!( cross_tests!( DemoType: [ (ValidatingConsensus, hotshot::demos::vdemo::VDemoState) ], - SignatureKey: [ hotshot_types::traits::signature_key::bn254::BN254Pub ], + SignatureKey: [ hotshot_types::traits::signature_key::bn254::BLSPubKey ], CommChannel: [ hotshot::traits::implementations::MemoryCommChannel ], Storage: [ hotshot::traits::implementations::MemoryStorage ], Time: [ hotshot_types::data::ViewNumber ], diff --git a/testing-macros/tests/integration/smoke.rs b/testing-macros/tests/integration/smoke.rs index f88323ab9b..26650d3a3f 100644 --- a/testing-macros/tests/integration/smoke.rs +++ b/testing-macros/tests/integration/smoke.rs @@ -2,7 +2,7 @@ use hotshot_testing_macros::cross_tests; cross_tests!( DemoType: [(ValidatingConsensus, hotshot::demos::vdemo::VDemoState)], - SignatureKey: [ hotshot_types::traits::signature_key::bn254::BN254Pub ], + SignatureKey: [ hotshot_types::traits::signature_key::bn254::BLSPubKey ], CommChannel: [ hotshot::traits::implementations::MemoryCommChannel ], Storage: [ hotshot::traits::implementations::MemoryStorage ], Time: [ hotshot_types::data::ViewNumber ], @@ -21,7 +21,7 @@ cross_tests!( cross_tests!( DemoType: [(ValidatingConsensus, hotshot::demos::vdemo::VDemoState) ], - SignatureKey: [ hotshot_types::traits::signature_key::bn254::BN254Pub ], + SignatureKey: [ hotshot_types::traits::signature_key::bn254::BLSPubKey ], CommChannel: [ hotshot::traits::implementations::MemoryCommChannel ], Storage: [ hotshot::traits::implementations::MemoryStorage ], Time: [ hotshot_types::data::ViewNumber ], From e1a85479bb29a86f7a118d184feda558ae49520b Mon Sep 17 00:00:00 2001 From: elliedavidson <118024407+elliedavidson@users.noreply.github.com> Date: Mon, 9 Oct 2023 11:55:04 -0400 Subject: [PATCH 19/20] Add tracing to network task --- crates/task-impls/src/network.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/task-impls/src/network.rs b/crates/task-impls/src/network.rs index 5fbada8539..605239c748 100644 --- a/crates/task-impls/src/network.rs +++ b/crates/task-impls/src/network.rs @@ -22,6 +22,7 @@ use hotshot_types::{ use snafu::Snafu; use std::{marker::PhantomData, sync::Arc}; use tracing::error; +use tracing::instrument; /// the type of network task #[derive(Clone, Copy, Debug)] @@ -190,6 +191,8 @@ impl< /// # Panics /// Panic sif a direct message event is received with no recipient #[allow(clippy::too_many_lines)] // TODO https://github.com/EspressoSystems/HotShot/issues/1704 + #[instrument(skip_all, fields(view = *self.view), name = "Newtork Task", level = "error")] + pub async fn handle_event( &mut self, event: SequencingHotShotEvent, From 6abf91e9b4738680e9275cb13ce5affe8860d94f Mon Sep 17 00:00:00 2001 From: Rob Date: Mon, 9 Oct 2023 15:25:08 -0400 Subject: [PATCH 20/20] increase stack size for async_std --- justfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/justfile b/justfile index d0c4b9a5b2..1e1c21aa96 100644 --- a/justfile +++ b/justfile @@ -13,7 +13,7 @@ run_ci: lint build test @async_std target *ARGS: echo setting executor to async-std - export RUSTDOCFLAGS='--cfg async_executor_impl="async-std" --cfg async_channel_impl="async-std" {{original_rustdocflags}}' RUSTFLAGS='--cfg async_executor_impl="async-std" --cfg async_channel_impl="async-std" {{original_rustflags}}' && just {{target}} {{ARGS}} + export RUST_MIN_STACK=4194304 RUSTDOCFLAGS='--cfg async_executor_impl="async-std" --cfg async_channel_impl="async-std" {{original_rustdocflags}}' RUSTFLAGS='--cfg async_executor_impl="async-std" --cfg async_channel_impl="async-std" {{original_rustflags}}' && just {{target}} {{ARGS}} build: cargo build --verbose --workspace --examples --bins --tests --lib --benches

A;tqbH{LJ3@lPj6?5uk*QmS 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�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
cu3zilGgQqZMKkmXe#Q?CCa0* zjCnEMp~DgMc8(@wFquwd!R%+Te{MRhsULR|&}wyqs2F6O{&e%1l#cYH6n@Y}3S&v{ z(w937KTkW(prOL$@-LYh*}e;3MD-=HsTDuQwXVtMJHjvMDVGx_L-w^dpR4G5o-8E;jt zyh9qPc|DP2@K<*>5sTt4I|>W?DUE%qzKb15MzvfTp+dTedxYtdqailVaEtc6(^hX; zCQg@bBUP3Bo4G(*qw~@fRn@`9eVWHNHynwacu8Ljii1{z1F;p?f2!@miQze=>5PQO z)ua?lP}Y0>pTCcpZ^a(icbP4&LD@n-Lv(Nsu%ek(6tu)2%l92(eo#R4Xm&uT7wc-I z>=k*3A3nmhPo{mijyMr_FZs4{K(^(S>z3g`R->CTEarK_BV!@#BoR_3*&f`o`=VuH zk*$wsO}(`CS*mx1f3KwnUAbVNl42+lo=k$T1R@FpB7}+->J2s!Z!1I5J@IL1klauq z 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
WeQP(_|j&ckjMKqvtg> zM+uK+v2>2ip6|{qXV1{%W3Ouaw?ehrMmo%zA^~QC-~AF!v9adjyzPQgD*gLsdsZ{& zsu=rd8Te&}RS1Y|&{jb3jwH4;!C#L47`+o+{|I9@MV*U^7nhJ!2mGS>**RKDu zalW(B%Eg02nYut4yGXf91ThGlvKb74Z=T)2Cx9yo36Ow^;7MtLT0$X-2nrQ(f6jXN z&3?aj|KOxX-|ZrWR26mzZUqBCC!9k_JMBnV~rmD6s#4fI$Pc zZ_qe&sGZ;|9f$`V5*9r|Z2Yqp@QW1|IC5}vDWAh93kVx*>CpiwG7?0z_(-JqxX&OD z6O-oModBB{LM6MqFI3Azu7ivmM3i?|Lyo#f! zK|BKmw8gJsP9mM#--Zepd6d|pB6~hxs)71H6P%M!kZ$kpfCY8y30Ot|f{Fr=XCXtJ zz_N%Mpd%BFkn{I=l}(tKK_4o46qAuVPJ*{bo_*o zA2dO^4dBo