From fd14ceb309636f7df8010be51d2769ce1add5066 Mon Sep 17 00:00:00 2001 From: Brendon Fish Date: Fri, 3 Nov 2023 13:53:19 -0400 Subject: [PATCH 1/2] Integrate new DAVote and Certificate --- crates/task-impls/src/consensus.rs | 11 +++-- crates/task-impls/src/da.rs | 59 +++++++++++++------------- crates/task-impls/src/events.rs | 19 +++++---- crates/task-impls/src/network.rs | 4 +- crates/testing/src/task_helpers.rs | 1 - crates/testing/tests/da_task.rs | 15 ++++--- crates/types/src/data.rs | 6 +-- crates/types/src/message.rs | 46 ++++++++++++-------- crates/types/src/simple_certificate.rs | 6 ++- crates/types/src/simple_vote.rs | 4 +- crates/types/src/traits/election.rs | 47 -------------------- 11 files changed, 90 insertions(+), 128 deletions(-) diff --git a/crates/task-impls/src/consensus.rs b/crates/task-impls/src/consensus.rs index f5b755cd8a..803b952a14 100644 --- a/crates/task-impls/src/consensus.rs +++ b/crates/task-impls/src/consensus.rs @@ -22,7 +22,7 @@ use hotshot_types::{ data::{Leaf, LeafType, ProposalType, QuorumProposal}, event::{Event, EventType}, message::{GeneralConsensusMessage, Message, Proposal, SequencingMessage}, - simple_certificate::QuorumCertificate2, + simple_certificate::{DACertificate2, QuorumCertificate2}, simple_vote::{QuorumData, QuorumVote}, traits::{ block_contents::BlockHeader, @@ -129,7 +129,7 @@ pub struct ConsensusTaskState< pub output_event_stream: ChannelStream>, /// All the DA certs we've received for current and future views. - pub da_certs: HashMap>, + pub da_certs: HashMap>, /// All the VID certs we've received for current and future views. pub vid_certs: HashMap>, @@ -529,10 +529,10 @@ where }; // Validate the DAC. - let message = if self.committee_exchange.is_valid_cert(cert) { + let message = if cert.is_valid_cert(self.committee_exchange.membership()) { // Validate the block payload commitment for non-genesis DAC. - if !cert.is_genesis() - && cert.leaf_commitment() + if !cert.is_genesis + && cert.get_data().payload_commit != proposal.block_header.payload_commitment() { error!("Block payload commitment does not equal parent commitment"); @@ -1372,7 +1372,6 @@ where justify_qc: consensus.high_qc.clone(), timeout_certificate: timeout_certificate.or_else(|| None), proposer_id: leaf.proposer_id, - dac: None, }; let message = Proposal { diff --git a/crates/task-impls/src/da.rs b/crates/task-impls/src/da.rs index b027d532a9..086f353e5f 100644 --- a/crates/task-impls/src/da.rs +++ b/crates/task-impls/src/da.rs @@ -12,15 +12,15 @@ use hotshot_task::{ task::{FilterEvent, HandleEvent, HotShotTaskCompleted, HotShotTaskTypes, TS}, task_impls::{HSTWithEvent, TaskBuilder}, }; -use hotshot_types::vote::DAVoteAccumulator; use hotshot_types::{ certificate::DACertificate, consensus::{Consensus, View}, data::{DAProposal, Leaf, ProposalType}, message::{Message, Proposal, SequencingMessage}, + simple_vote::{DAData, DAVote2}, traits::{ consensus_api::ConsensusApi, - election::{CommitteeExchangeType, ConsensusExchange, Membership, SignedCertificate}, + election::{CommitteeExchangeType, ConsensusExchange, Membership}, network::{CommunicationChannel, ConsensusIntentEvent}, node_implementation::{CommitteeEx, NodeImplementation, NodeType}, signature_key::SignatureKey, @@ -28,6 +28,11 @@ use hotshot_types::{ BlockPayload, }, utils::ViewInner, + vote2::HasViewNumber, + vote2::VoteAccumulator2, +}; +use hotshot_types::{ + simple_certificate::DACertificate2, traits::node_implementation::CommitteeMembership, }; use snafu::Snafu; @@ -92,13 +97,12 @@ pub struct DAVoteCollectionTaskState< #[allow(clippy::type_complexity)] /// Accumulates DA votes pub accumulator: Either< - as SignedCertificate< + VoteAccumulator2< TYPES, - TYPES::Time, - TYPES::VoteTokenType, - Commitment, - >>::VoteAccumulator, - DACertificate, + DAVote2>, + DACertificate2, + >, + DACertificate2, >, /// the current view pub cur_view: TYPES::Time, @@ -138,8 +142,8 @@ where { match event { HotShotEvent::DAVoteRecv(vote) => { - debug!("DA vote recv, collection task {:?}", vote.current_view); - // panic!("Vote handle received DA vote for view {}", *vote.current_view); + debug!("DA vote recv, collection task {:?}", vote.get_view_number()); + // panic!("Vote handle received DA vote for view {}", *vote.get_view_number()); // For the case where we receive votes after we've made a certificate if state.accumulator.is_right() { @@ -149,11 +153,7 @@ where let accumulator = state.accumulator.left().unwrap(); - match state.committee_exchange.accumulate_vote( - accumulator, - &vote, - &vote.payload_commitment, - ) { + match accumulator.accumulate(&vote, state.committee_exchange.membership()) { Left(new_accumulator) => { state.accumulator = either::Left(new_accumulator); } @@ -260,18 +260,21 @@ where Ok(None) => { debug!("We were not chosen for DA committee on {:?}", view); } - Ok(Some(vote_token)) => { + Ok(Some(_vote_token)) => { // Generate and send vote - let vote = self.committee_exchange.create_da_message( - payload_commitment, + let vote = DAVote2::create_signed_vote( + DAData { + payload_commit: payload_commitment, + }, view, - vote_token, + self.committee_exchange.public_key(), + self.committee_exchange.private_key(), ); // ED Don't think this is necessary? // self.cur_view = view; - debug!("Sending vote to the DA leader {:?}", vote.current_view); + debug!("Sending vote to the DA leader {:?}", vote.get_view_number()); self.event_stream .publish(HotShotEvent::DAVoteSend(vote)) .await; @@ -294,9 +297,9 @@ where } } HotShotEvent::DAVoteRecv(vote) => { - debug!("DA vote recv, Main Task {:?}", vote.current_view,); + debug!("DA vote recv, Main Task {:?}", vote.get_view_number(),); // Check if we are the leader and the vote is from the sender. - let view = vote.current_view; + let view = vote.get_view_number(); if !self.committee_exchange.is_leader(view) { error!("We are not the committee leader for view {} are we leader for next view? {}", *view, self.committee_exchange.is_leader(view + 1)); return None; @@ -317,19 +320,15 @@ where TYPES::Time::new(0) }; - let new_accumulator = DAVoteAccumulator { - da_vote_outcomes: HashMap::new(), - success_threshold: self.committee_exchange.success_threshold(), + let new_accumulator = VoteAccumulator2 { + vote_outcomes: HashMap::new(), sig_lists: Vec::new(), signers: bitvec![0; self.committee_exchange.total_nodes()], phantom: PhantomData, }; - let accumulator = self.committee_exchange.accumulate_vote( - new_accumulator, - &vote, - &vote.clone().payload_commitment, - ); + let accumulator = + new_accumulator.accumulate(&vote, self.committee_exchange.membership()); if view > collection_view { let state = DAVoteCollectionTaskState { diff --git a/crates/task-impls/src/events.rs b/crates/task-impls/src/events.rs index 8bf8db5de2..6b502afabb 100644 --- a/crates/task-impls/src/events.rs +++ b/crates/task-impls/src/events.rs @@ -3,15 +3,16 @@ use crate::view_sync::ViewSyncPhase; use commit::Commitment; use either::Either; use hotshot_types::{ - certificate::{DACertificate, TimeoutCertificate, VIDCertificate}, + certificate::{TimeoutCertificate, VIDCertificate}, data::{DAProposal, VidDisperse}, message::Proposal, - simple_certificate::QuorumCertificate2, - simple_vote::QuorumVote, + simple_certificate::{DACertificate2, QuorumCertificate2}, + simple_vote::{DAVote2, QuorumVote}, traits::node_implementation::{ - NodeImplementation, NodeType, QuorumMembership, QuorumProposalType, ViewSyncProposalType, + CommitteeMembership, NodeImplementation, NodeType, QuorumMembership, QuorumProposalType, + ViewSyncProposalType, }, - vote::{DAVote, TimeoutVote, VIDVote, ViewSyncVote}, + vote::{TimeoutVote, VIDVote, ViewSyncVote}, }; /// All of the possible events that can be passed between Sequecning `HotShot` tasks @@ -30,9 +31,9 @@ pub enum HotShotEvent> { /// 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 - DAVoteRecv(DAVote), + DAVoteRecv(DAVote2>), /// A Data Availability Certificate (DAC) has been recieved by the network; handled by the consensus task - DACRecv(DACertificate), + DACRecv(DACertificate2), /// 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 @@ -40,11 +41,11 @@ pub enum HotShotEvent> { /// 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), + DAVoteSend(DAVote2>), /// 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(Either, TimeoutCertificate>), /// 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), + DACSend(DACertificate2, 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 ViewChange(TYPES::Time), /// Timeout for the view sync protocol; emitted by a replica in the view sync task diff --git a/crates/task-impls/src/network.rs b/crates/task-impls/src/network.rs index 217030cfd6..8ddbe5ede1 100644 --- a/crates/task-impls/src/network.rs +++ b/crates/task-impls/src/network.rs @@ -239,12 +239,12 @@ impl< Some(membership.get_leader(vote.get_view())), // TODO who is VID leader? https://github.com/EspressoSystems/HotShot/issues/1699 ), HotShotEvent::DAVoteSend(vote) => ( - vote.signature_key(), + vote.get_signing_key(), MessageKind::::from_consensus_message(SequencingMessage(Right( CommitteeConsensusMessage::DAVote(vote.clone()), ))), TransmitType::Direct, - Some(membership.get_leader(vote.get_view())), + Some(membership.get_leader(vote.get_view_number())), ), HotShotEvent::VidCertSend(certificate, sender) => ( sender, diff --git a/crates/testing/src/task_helpers.rs b/crates/testing/src/task_helpers.rs index 719e2203d4..4ba8243908 100644 --- a/crates/testing/src/task_helpers.rs +++ b/crates/testing/src/task_helpers.rs @@ -134,7 +134,6 @@ async fn build_quorum_proposal_and_signature( justify_qc: QuorumCertificate2::genesis(), timeout_certificate: None, proposer_id: leaf.proposer_id, - dac: None, }; (proposal, signature) diff --git a/crates/testing/tests/da_task.rs b/crates/testing/tests/da_task.rs index 3994c14b19..ff755286e0 100644 --- a/crates/testing/tests/da_task.rs +++ b/crates/testing/tests/da_task.rs @@ -8,6 +8,7 @@ use hotshot_testing::{ use hotshot_types::{ block_impl::VIDTransaction, data::{DAProposal, VidSchemeTrait, ViewNumber}, + simple_vote::{DAData, DAVote2}, traits::{ consensus_api::ConsensusSharedApi, election::ConsensusExchange, node_implementation::ExchangesType, state::ConsensusTime, @@ -79,12 +80,14 @@ async fn test_da_task() { ); output.insert(HotShotEvent::SendPayloadCommitment(block.commit()), 1); output.insert(HotShotEvent::DAProposalSend(message.clone(), pub_key), 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); + let da_vote = DAVote2::create_signed_vote( + DAData { + payload_commit: block.commit(), + }, + ViewNumber::new(2), + committee_exchange.public_key(), + committee_exchange.private_key(), + ); output.insert(HotShotEvent::DAVoteSend(da_vote), 1); output.insert(HotShotEvent::DAProposalRecv(message, pub_key), 1); diff --git a/crates/types/src/data.rs b/crates/types/src/data.rs index 824d965422..af6e9dc8f3 100644 --- a/crates/types/src/data.rs +++ b/crates/types/src/data.rs @@ -4,7 +4,7 @@ //! `HotShot`'s version of a block, and proposals, messages upon which to reach the consensus. use crate::{ - certificate::{AssembledSignature, DACertificate, TimeoutCertificate, ViewSyncCertificate}, + certificate::{AssembledSignature, TimeoutCertificate, ViewSyncCertificate}, simple_certificate::QuorumCertificate2, traits::{ block_contents::BlockHeader, @@ -180,10 +180,6 @@ pub struct QuorumProposal> { /// the propser id pub proposer_id: EncodedPublicKey, - - /// Data availibity certificate - // TODO We should be able to remove this - pub dac: Option>, } impl ProposalType for DAProposal { diff --git a/crates/types/src/message.rs b/crates/types/src/message.rs index cc1acc80f7..fe207befc9 100644 --- a/crates/types/src/message.rs +++ b/crates/types/src/message.rs @@ -3,9 +3,12 @@ //! This module contains types used to represent the various types of messages that //! `HotShot` nodes can send among themselves. +use crate::simple_certificate::DACertificate2; +use crate::simple_vote::DAVote2; +use crate::traits::node_implementation::CommitteeMembership; use crate::vote2::HasViewNumber; use crate::{ - certificate::{DACertificate, VIDCertificate}, + certificate::VIDCertificate, data::{DAProposal, ProposalType, VidDisperse}, simple_vote::QuorumVote, traits::{ @@ -16,7 +19,7 @@ use crate::{ }, signature_key::EncodedSignature, }, - vote::{DAVote, TimeoutVote, VIDVote, ViewSyncVote, VoteType}, + vote::{TimeoutVote, VIDVote, ViewSyncVote, VoteType}, }; use derivative::Derivative; @@ -214,13 +217,16 @@ where /// A processed consensus message for the DA committee in sequencing consensus. #[derive(Serialize, Clone, Debug, PartialEq)] #[serde(bound(deserialize = ""))] -pub enum ProcessedCommitteeConsensusMessage { +pub enum ProcessedCommitteeConsensusMessage> { /// Proposal for the DA committee. DAProposal(Proposal>, TYPES::SignatureKey), /// Vote from the DA committee. - DAVote(DAVote, TYPES::SignatureKey), + DAVote( + DAVote2>, + TYPES::SignatureKey, + ), /// Certificate for the DA. - DACertificate(DACertificate, TYPES::SignatureKey), + DACertificate(DACertificate2, TYPES::SignatureKey), /// VID dispersal data. Like [`DAProposal`] VidDisperseMsg(Proposal>, TYPES::SignatureKey), /// Vote from VID storage node. Like [`DAVote`] @@ -229,10 +235,10 @@ pub enum ProcessedCommitteeConsensusMessage { VidCertificate(VIDCertificate, TYPES::SignatureKey), } -impl From> - for CommitteeConsensusMessage +impl> + From> for CommitteeConsensusMessage { - fn from(value: ProcessedCommitteeConsensusMessage) -> Self { + fn from(value: ProcessedCommitteeConsensusMessage) -> Self { match value { ProcessedCommitteeConsensusMessage::DAProposal(p, _) => { CommitteeConsensusMessage::DAProposal(p) @@ -256,9 +262,9 @@ impl From> } } -impl ProcessedCommitteeConsensusMessage { +impl> ProcessedCommitteeConsensusMessage { /// Create a [`ProcessedCommitteeConsensusMessage`] from a [`CommitteeConsensusMessage`]. - pub fn new(value: CommitteeConsensusMessage, sender: TYPES::SignatureKey) -> Self { + pub fn new(value: CommitteeConsensusMessage, sender: TYPES::SignatureKey) -> Self { match value { CommitteeConsensusMessage::DAProposal(p) => { ProcessedCommitteeConsensusMessage::DAProposal(p, sender) @@ -283,8 +289,10 @@ impl ProcessedCommitteeConsensusMessage { } /// A processed consensus message for sequencing consensus. -pub type ProcessedSequencingMessage = - Either, ProcessedCommitteeConsensusMessage>; +pub type ProcessedSequencingMessage = Either< + ProcessedGeneralConsensusMessage, + ProcessedCommitteeConsensusMessage, +>; impl< TYPES: NodeType, @@ -339,15 +347,15 @@ where #[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Hash, Eq)] #[serde(bound(deserialize = "", serialize = ""))] /// Messages related to the sequencing consensus protocol for the DA committee. -pub enum CommitteeConsensusMessage { +pub enum CommitteeConsensusMessage> { /// Proposal for data availability committee DAProposal(Proposal>), /// vote for data availability committee - DAVote(DAVote), + DAVote(DAVote2>), /// Certificate data is available - DACertificate(DACertificate), + DACertificate(DACertificate2), /// Initiate VID dispersal. /// @@ -394,7 +402,7 @@ pub trait SequencingMessageType>: pub struct SequencingMessage< TYPES: NodeType, I: NodeImplementation>, ->(pub Either, CommitteeConsensusMessage>); +>(pub Either, CommitteeConsensusMessage>); impl< TYPES: NodeType, @@ -433,7 +441,9 @@ impl< // this should match replica upon receipt p.data.get_view_number() } - CommitteeConsensusMessage::DAVote(vote_message) => vote_message.get_view(), + CommitteeConsensusMessage::DAVote(vote_message) => { + vote_message.get_view_number() + } CommitteeConsensusMessage::DACertificate(cert) => cert.view_number, CommitteeConsensusMessage::VidCertificate(cert) => cert.view_number, CommitteeConsensusMessage::VidDisperseMsg(disperse) => { @@ -475,7 +485,7 @@ impl< I: NodeImplementation>, > SequencingMessageType for SequencingMessage { - type CommitteeConsensusMessage = CommitteeConsensusMessage; + type CommitteeConsensusMessage = CommitteeConsensusMessage; } #[derive(Serialize, Deserialize, Derivative, Clone, Debug, PartialEq, Eq, Hash)] diff --git a/crates/types/src/simple_certificate.rs b/crates/types/src/simple_certificate.rs index 18bf1d0259..eb834e00c4 100644 --- a/crates/types/src/simple_certificate.rs +++ b/crates/types/src/simple_certificate.rs @@ -10,7 +10,7 @@ use commit::{Commitment, CommitmentBoundsArkless, Committable}; use ethereum_types::U256; use crate::{ - simple_vote::{QuorumData, Voteable}, + simple_vote::{DAData, QuorumData, Voteable}, traits::{ election::Membership, node_implementation::NodeType, signature_key::SignatureKey, state::ConsensusTime, @@ -41,7 +41,6 @@ impl Certificate2 for SimpleCertificate { type Voteable = VOTEABLE; - // type Membership = MEMBERSHIP; fn create_signed_certificate( vote_commitment: Commitment, @@ -127,3 +126,6 @@ impl< /// Type alias for a `QuorumCertificate`, which is a `SimpleCertificate` of `QuorumVotes` pub type QuorumCertificate2 = SimpleCertificate>; +/// Type alias for a DA certificate over `DAData` +pub type DACertificate2 = + SimpleCertificate::BlockPayload>>; diff --git a/crates/types/src/simple_vote.rs b/crates/types/src/simple_vote.rs index 62438ea4e9..b0285cf0bf 100644 --- a/crates/types/src/simple_vote.rs +++ b/crates/types/src/simple_vote.rs @@ -212,9 +212,9 @@ impl = SimpleVote, M>; /// DA vote type alias -pub type DAVote = SimpleVote, M>; +pub type DAVote2 = SimpleVote::BlockPayload>, M>; /// VID vote type alias -pub type VIDVote = SimpleVote, M>; +pub type VIDVote = SimpleVote::BlockPayload>, M>; /// Timeout Vote type alias pub type TimeoutVote = SimpleVote, M>; /// View Sync Commit Vote type alias diff --git a/crates/types/src/traits/election.rs b/crates/types/src/traits/election.rs index d2872cc2f5..fa8415acb2 100644 --- a/crates/types/src/traits/election.rs +++ b/crates/types/src/traits/election.rs @@ -492,23 +492,6 @@ pub trait CommitteeExchangeType: &self, payload_commitment: &Commitment, ) -> EncodedSignature; - - /// Sign a vote on DA proposal. - /// - /// The block payload commitment and the type of the vote (DA) are signed, which is the minimum amount - /// of information necessary for checking that this node voted on that block. - fn sign_da_vote( - &self, - payload_commitment: Commitment, - ) -> (EncodedPublicKey, EncodedSignature); - - /// Create a message with a vote on DA proposal. - fn create_da_message( - &self, - payload_commitment: Commitment, - current_view: TYPES::Time, - vote_token: TYPES::VoteTokenType, - ) -> DAVote; } /// Standard implementation of [`CommitteeExchangeType`] utilizing a DA committee. @@ -550,36 +533,6 @@ impl< let signature = TYPES::SignatureKey::sign(&self.private_key, payload_commitment.as_ref()); signature } - /// Sign a vote on DA proposal. - /// - /// The block payload commitment and the type of the vote (DA) are signed, which is the minimum amount - /// of information necessary for checking that this node voted on that block. - fn sign_da_vote( - &self, - payload_commitment: Commitment, - ) -> (EncodedPublicKey, EncodedSignature) { - let signature = TYPES::SignatureKey::sign( - &self.private_key, - VoteData::DA(payload_commitment).commit().as_ref(), - ); - (self.public_key.to_bytes(), signature) - } - /// Create a message with a vote on DA proposal. - fn create_da_message( - &self, - payload_commitment: Commitment, - current_view: TYPES::Time, - vote_token: TYPES::VoteTokenType, - ) -> DAVote { - let signature = self.sign_da_vote(payload_commitment); - DAVote { - signature, - payload_commitment, - current_view, - vote_token, - vote_data: VoteData::DA(payload_commitment), - } - } } impl< From 3c33b4dba6c2d5dc0300600cf4bb62b09c0676fd Mon Sep 17 00:00:00 2001 From: Brendon Fish Date: Fri, 3 Nov 2023 13:59:19 -0400 Subject: [PATCH 2/2] remove one unused line --- crates/testing/tests/consensus_task.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/testing/tests/consensus_task.rs b/crates/testing/tests/consensus_task.rs index 968fba31eb..ed8d549f42 100644 --- a/crates/testing/tests/consensus_task.rs +++ b/crates/testing/tests/consensus_task.rs @@ -35,7 +35,6 @@ async fn build_vote( inner: handle.hotshot.inner.clone(), }; let quorum_exchange = api.inner.exchanges.quorum_exchange().clone(); - let _vote_token = quorum_exchange.make_vote_token(view).unwrap().unwrap(); let justify_qc = proposal.justify_qc.clone(); let view = ViewNumber::new(*proposal.view_number);