diff --git a/crates/example-types/src/storage_types.rs b/crates/example-types/src/storage_types.rs index acedb42007..1a666c737e 100644 --- a/crates/example-types/src/storage_types.rs +++ b/crates/example-types/src/storage_types.rs @@ -14,7 +14,9 @@ use async_lock::RwLock; use async_trait::async_trait; use hotshot_types::{ consensus::CommitmentMap, - data::{DaProposal, Leaf, Leaf2, QuorumProposal, QuorumProposal2, VidDisperseShare}, + data::{ + DaProposal, DaProposal2, Leaf, Leaf2, QuorumProposal, QuorumProposal2, VidDisperseShare, + }, event::HotShotAction, message::Proposal, simple_certificate::{QuorumCertificate2, UpgradeCertificate}, @@ -38,6 +40,7 @@ type VidShares = HashMap< pub struct TestStorageState { vids: VidShares, das: HashMap>>, + da2s: HashMap>>, proposals: BTreeMap>>, proposals2: BTreeMap>>, high_qc: Option>, @@ -51,6 +54,7 @@ impl Default for TestStorageState { Self { vids: HashMap::new(), das: HashMap::new(), + da2s: HashMap::new(), proposals: BTreeMap::new(), proposals2: BTreeMap::new(), high_qc: None, @@ -142,6 +146,21 @@ impl Storage for TestStorage { .insert(proposal.data.view_number, proposal.clone()); Ok(()) } + async fn append_da2( + &self, + proposal: &Proposal>, + _vid_commit: ::Commit, + ) -> Result<()> { + if self.should_return_err { + bail!("Failed to append VID proposal to storage"); + } + Self::run_delay_settings_from_config(&self.delay_config).await; + let mut inner = self.inner.write().await; + inner + .da2s + .insert(proposal.data.view_number, proposal.clone()); + Ok(()) + } async fn append_proposal( &self, proposal: &Proposal>, diff --git a/crates/task-impls/src/da.rs b/crates/task-impls/src/da.rs index 2c503d2b13..923b15e010 100644 --- a/crates/task-impls/src/da.rs +++ b/crates/task-impls/src/da.rs @@ -12,11 +12,11 @@ use async_trait::async_trait; use hotshot_task::task::TaskState; use hotshot_types::{ consensus::{Consensus, OuterConsensus}, - data::{DaProposal, PackedBundle}, + data::{DaProposal2, PackedBundle}, event::{Event, EventType}, message::{Proposal, UpgradeLock}, - simple_certificate::DaCertificate, - simple_vote::{DaData, DaVote}, + simple_certificate::DaCertificate2, + simple_vote::{DaData2, DaVote2}, traits::{ block_contents::vid_commitment, election::Membership, @@ -61,7 +61,7 @@ pub struct DaTaskState, V: Version pub network: Arc, /// A map of `DaVote` collector tasks. - pub vote_collectors: VoteCollectorsMap, DaCertificate, V>, + pub vote_collectors: VoteCollectorsMap, DaCertificate2, V>, /// This Nodes public key pub public_key: TYPES::SignatureKey, @@ -143,8 +143,11 @@ impl, V: Versions> DaTaskState { let cur_view = self.consensus.read().await.cur_view(); + let view_number = proposal.data.view_number(); + let epoch_number = proposal.data.epoch_number; + ensure!( - cur_view <= proposal.data.view_number() + 1, + cur_view <= view_number + 1, debug!( "Validated DA proposal for prior view but it's too old now Current view {:?}, DA Proposal view {:?}", cur_view, @@ -155,7 +158,7 @@ impl, V: Versions> DaTaskState, V: Versions> DaTaskState, V: Versions> DaTaskState, V: Versions> DaTaskState, V: Versions> DaTaskState = DaProposal { + let data: DaProposal2 = DaProposal2 { encoded_transactions: Arc::clone(encoded_transactions), metadata: metadata.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, + epoch_number: *epoch_number, }; let message = Proposal { diff --git a/crates/task-impls/src/events.rs b/crates/task-impls/src/events.rs index 721a8b9cc0..c75ef7c752 100644 --- a/crates/task-impls/src/events.rs +++ b/crates/task-impls/src/events.rs @@ -11,18 +11,18 @@ use either::Either; use hotshot_task::task::TaskEvent; use hotshot_types::{ data::{ - DaProposal, Leaf2, PackedBundle, QuorumProposal2, UpgradeProposal, VidDisperse, + DaProposal2, Leaf2, PackedBundle, QuorumProposal2, UpgradeProposal, VidDisperse, VidDisperseShare, }, message::Proposal, request_response::ProposalRequestPayload, simple_certificate::{ - DaCertificate, QuorumCertificate, QuorumCertificate2, TimeoutCertificate, - UpgradeCertificate, ViewSyncCommitCertificate2, ViewSyncFinalizeCertificate2, - ViewSyncPreCommitCertificate2, + DaCertificate2, QuorumCertificate, QuorumCertificate2, TimeoutCertificate, + UpgradeCertificate, ViewSyncCommitCertificate, ViewSyncFinalizeCertificate, + ViewSyncPreCommitCertificate, }, simple_vote::{ - DaVote, QuorumVote2, TimeoutVote, UpgradeVote, ViewSyncCommitVote, ViewSyncFinalizeVote, + DaVote2, QuorumVote2, TimeoutVote, UpgradeVote, ViewSyncCommitVote, ViewSyncFinalizeVote, ViewSyncPreCommitVote, }, traits::{ @@ -80,15 +80,15 @@ pub enum HotShotEvent { /// Send a timeout vote to the network; emitted by consensus task replicas TimeoutVoteSend(TimeoutVote), /// A DA proposal has been received from the network; handled by the DA task - DaProposalRecv(Proposal>, TYPES::SignatureKey), + DaProposalRecv(Proposal>, TYPES::SignatureKey), /// A DA proposal has been validated; handled by the DA task and VID task - DaProposalValidated(Proposal>, TYPES::SignatureKey), + DaProposalValidated(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 received by the network; handled by the consensus task - DaCertificateRecv(DaCertificate), + DaCertificateRecv(DaCertificate2), /// A DAC is validated. - DaCertificateValidated(DaCertificate), + DaCertificateValidated(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 @@ -117,15 +117,15 @@ pub enum HotShotEvent { /// A quorum proposal was requested by a node for a view. QuorumProposalResponseRecv(Proposal>), /// 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), + 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 next leader has collected enough votes to form a QC; emitted by the next leader in the consensus task; an internal event only Qc2Formed(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::View, TYPES::Epoch), /// Timeout for the view sync protocol; emitted by a replica in the view sync task @@ -145,19 +145,19 @@ pub enum HotShotEvent { /// Send a `ViewSyncFinalizeVote` from the network; emitted by a replica in the view sync task ViewSyncFinalizeVoteSend(ViewSyncFinalizeVote), - /// Receive a `ViewSyncPreCommitCertificate2` from the network; received by a replica in the view sync task - ViewSyncPreCommitCertificate2Recv(ViewSyncPreCommitCertificate2), - /// Receive a `ViewSyncCommitCertificate2` from the network; received by a replica in the view sync task - ViewSyncCommitCertificate2Recv(ViewSyncCommitCertificate2), - /// Receive a `ViewSyncFinalizeCertificate2` from the network; received by a replica in the view sync task - ViewSyncFinalizeCertificate2Recv(ViewSyncFinalizeCertificate2), + /// Receive a `ViewSyncPreCommitCertificate` from the network; received by a replica in the view sync task + ViewSyncPreCommitCertificateRecv(ViewSyncPreCommitCertificate), + /// Receive a `ViewSyncCommitCertificate` from the network; received by a replica in the view sync task + ViewSyncCommitCertificateRecv(ViewSyncCommitCertificate), + /// Receive a `ViewSyncFinalizeCertificate` from the network; received by a replica in the view sync task + ViewSyncFinalizeCertificateRecv(ViewSyncFinalizeCertificate), - /// Send a `ViewSyncPreCommitCertificate2` from the network; emitted by a relay in the view sync task - ViewSyncPreCommitCertificate2Send(ViewSyncPreCommitCertificate2, TYPES::SignatureKey), - /// Send a `ViewSyncCommitCertificate2` from the network; emitted by a relay in the view sync task - ViewSyncCommitCertificate2Send(ViewSyncCommitCertificate2, TYPES::SignatureKey), - /// Send a `ViewSyncFinalizeCertificate2` from the network; emitted by a relay in the view sync task - ViewSyncFinalizeCertificate2Send(ViewSyncFinalizeCertificate2, TYPES::SignatureKey), + /// Send a `ViewSyncPreCommitCertificate` from the network; emitted by a relay in the view sync task + ViewSyncPreCommitCertificateSend(ViewSyncPreCommitCertificate, TYPES::SignatureKey), + /// Send a `ViewSyncCommitCertificate` from the network; emitted by a relay in the view sync task + ViewSyncCommitCertificateSend(ViewSyncCommitCertificate, TYPES::SignatureKey), + /// Send a `ViewSyncFinalizeCertificate` from the network; emitted by a relay in the view sync task + ViewSyncFinalizeCertificateSend(ViewSyncFinalizeCertificate, TYPES::SignatureKey), /// Trigger the start of the view sync protocol; emitted by view sync task; internal trigger only ViewSyncTrigger(TYPES::View), @@ -289,12 +289,12 @@ impl HotShotEvent { | HotShotEvent::ViewSyncPreCommitVoteSend(vote) => Some(vote.view_number()), HotShotEvent::ViewSyncFinalizeVoteRecv(vote) | HotShotEvent::ViewSyncFinalizeVoteSend(vote) => Some(vote.view_number()), - HotShotEvent::ViewSyncPreCommitCertificate2Recv(cert) - | HotShotEvent::ViewSyncPreCommitCertificate2Send(cert, _) => Some(cert.view_number()), - HotShotEvent::ViewSyncCommitCertificate2Recv(cert) - | HotShotEvent::ViewSyncCommitCertificate2Send(cert, _) => Some(cert.view_number()), - HotShotEvent::ViewSyncFinalizeCertificate2Recv(cert) - | HotShotEvent::ViewSyncFinalizeCertificate2Send(cert, _) => Some(cert.view_number()), + HotShotEvent::ViewSyncPreCommitCertificateRecv(cert) + | HotShotEvent::ViewSyncPreCommitCertificateSend(cert, _) => Some(cert.view_number()), + HotShotEvent::ViewSyncCommitCertificateRecv(cert) + | HotShotEvent::ViewSyncCommitCertificateSend(cert, _) => Some(cert.view_number()), + HotShotEvent::ViewSyncFinalizeCertificateRecv(cert) + | HotShotEvent::ViewSyncFinalizeCertificateSend(cert, _) => Some(cert.view_number()), HotShotEvent::SendPayloadCommitmentAndMetadata(_, _, _, view_number, _, _) => { Some(*view_number) } @@ -451,45 +451,45 @@ impl Display for HotShotEvent { "ViewSyncFinalizeVoteSend(view_number={:?})", vote.view_number() ), - HotShotEvent::ViewSyncPreCommitCertificate2Recv(cert) => { + HotShotEvent::ViewSyncPreCommitCertificateRecv(cert) => { write!( f, - "ViewSyncPreCommitCertificate2Recv(view_number={:?})", + "ViewSyncPreCommitCertificateRecv(view_number={:?})", cert.view_number() ) } - HotShotEvent::ViewSyncCommitCertificate2Recv(cert) => { + HotShotEvent::ViewSyncCommitCertificateRecv(cert) => { write!( f, - "ViewSyncCommitCertificate2Recv(view_number={:?})", + "ViewSyncCommitCertificateRecv(view_number={:?})", cert.view_number() ) } - HotShotEvent::ViewSyncFinalizeCertificate2Recv(cert) => { + HotShotEvent::ViewSyncFinalizeCertificateRecv(cert) => { write!( f, - "ViewSyncFinalizeCertificate2Recv(view_number={:?})", + "ViewSyncFinalizeCertificateRecv(view_number={:?})", cert.view_number() ) } - HotShotEvent::ViewSyncPreCommitCertificate2Send(cert, _) => { + HotShotEvent::ViewSyncPreCommitCertificateSend(cert, _) => { write!( f, - "ViewSyncPreCommitCertificate2Send(view_number={:?})", + "ViewSyncPreCommitCertificateSend(view_number={:?})", cert.view_number() ) } - HotShotEvent::ViewSyncCommitCertificate2Send(cert, _) => { + HotShotEvent::ViewSyncCommitCertificateSend(cert, _) => { write!( f, - "ViewSyncCommitCertificate2Send(view_number={:?})", + "ViewSyncCommitCertificateSend(view_number={:?})", cert.view_number() ) } - HotShotEvent::ViewSyncFinalizeCertificate2Send(cert, _) => { + HotShotEvent::ViewSyncFinalizeCertificateSend(cert, _) => { write!( f, - "ViewSyncFinalizeCertificate2Send(view_number={:?})", + "ViewSyncFinalizeCertificateSend(view_number={:?})", cert.view_number() ) } diff --git a/crates/task-impls/src/network.rs b/crates/task-impls/src/network.rs index ad9dcd4168..b885e2f7e5 100644 --- a/crates/task-impls/src/network.rs +++ b/crates/task-impls/src/network.rs @@ -36,6 +36,7 @@ use hotshot_types::{ use tokio::{spawn, task::JoinHandle}; use tracing::instrument; use utils::anytrace::*; +use vbs::version::StaticVersionType; use crate::{ events::{HotShotEvent, HotShotTaskCompleted}, @@ -88,22 +89,20 @@ impl NetworkMessageTaskState { } GeneralConsensusMessage::ViewSyncPreCommitCertificate( view_sync_message, - ) => HotShotEvent::ViewSyncPreCommitCertificate2Recv(view_sync_message), + ) => HotShotEvent::ViewSyncPreCommitCertificateRecv(view_sync_message), GeneralConsensusMessage::ViewSyncCommitVote(view_sync_message) => { HotShotEvent::ViewSyncCommitVoteRecv(view_sync_message) } GeneralConsensusMessage::ViewSyncCommitCertificate(view_sync_message) => { - HotShotEvent::ViewSyncCommitCertificate2Recv(view_sync_message) + HotShotEvent::ViewSyncCommitCertificateRecv(view_sync_message) } - GeneralConsensusMessage::ViewSyncFinalizeVote(view_sync_message) => { HotShotEvent::ViewSyncFinalizeVoteRecv(view_sync_message) } GeneralConsensusMessage::ViewSyncFinalizeCertificate(view_sync_message) => { - HotShotEvent::ViewSyncFinalizeCertificate2Recv(view_sync_message) + HotShotEvent::ViewSyncFinalizeCertificateRecv(view_sync_message) } - GeneralConsensusMessage::TimeoutVote(message) => { HotShotEvent::TimeoutVoteRecv(message) } @@ -115,18 +114,34 @@ impl NetworkMessageTaskState { HotShotEvent::UpgradeVoteRecv(message) } GeneralConsensusMessage::HighQc(qc) => HotShotEvent::HighQcRecv(qc, sender), + GeneralConsensusMessage::Proposal2(proposal) => { + HotShotEvent::QuorumProposalRecv(proposal, sender) + } + GeneralConsensusMessage::Vote2(vote) => HotShotEvent::QuorumVoteRecv(vote), + GeneralConsensusMessage::Proposal2Response(proposal) => { + HotShotEvent::QuorumProposalResponseRecv(proposal) + } }, SequencingMessage::Da(da_message) => match da_message { DaConsensusMessage::DaProposal(proposal) => { - HotShotEvent::DaProposalRecv(proposal, sender) + HotShotEvent::DaProposalRecv(convert_proposal(proposal), sender) + } + DaConsensusMessage::DaVote(vote) => { + HotShotEvent::DaVoteRecv(vote.clone().to_vote2()) } - DaConsensusMessage::DaVote(vote) => HotShotEvent::DaVoteRecv(vote.clone()), DaConsensusMessage::DaCertificate(cert) => { - HotShotEvent::DaCertificateRecv(cert) + HotShotEvent::DaCertificateRecv(cert.to_dac2()) } DaConsensusMessage::VidDisperseMsg(proposal) => { HotShotEvent::VidShareRecv(sender, proposal) } + DaConsensusMessage::DaProposal2(proposal) => { + HotShotEvent::DaProposalRecv(proposal, sender) + } + DaConsensusMessage::DaVote2(vote) => HotShotEvent::DaVoteRecv(vote.clone()), + DaConsensusMessage::DaCertificate2(cert) => { + HotShotEvent::DaCertificateRecv(cert) + } }, }; broadcast_event(Arc::new(event), &self.internal_event_stream).await; @@ -374,13 +389,23 @@ impl< match event.as_ref().clone() { HotShotEvent::QuorumProposalSend(proposal, sender) => { *maybe_action = Some(HotShotAction::Propose); - Some(( - sender, + + let message = if self + .upgrade_lock + .version_infallible(proposal.data.view_number()) + .await + >= V::Epochs::VERSION + { + MessageKind::::from_consensus_message(SequencingMessage::General( + GeneralConsensusMessage::Proposal2(proposal), + )) + } else { MessageKind::::from_consensus_message(SequencingMessage::General( GeneralConsensusMessage::Proposal(convert_proposal(proposal)), - )), - TransmitType::Broadcast, - )) + )) + }; + + Some((sender, message, TransmitType::Broadcast)) } // ED Each network task is subscribed to all these message types. Need filters per network task @@ -399,23 +424,41 @@ impl< } }; - Some(( - vote.signing_key(), + let message = if self + .upgrade_lock + .version_infallible(vote.view_number()) + .await + >= V::Epochs::VERSION + { + MessageKind::::from_consensus_message(SequencingMessage::General( + GeneralConsensusMessage::Vote2(vote.clone()), + )) + } else { MessageKind::::from_consensus_message(SequencingMessage::General( GeneralConsensusMessage::Vote(vote.clone().to_vote()), - )), - TransmitType::Direct(leader), - )) + )) + }; + + Some((vote.signing_key(), message, TransmitType::Direct(leader))) } HotShotEvent::ExtendedQuorumVoteSend(vote) => { *maybe_action = Some(HotShotAction::Vote); - Some(( - vote.signing_key(), + let message = if self + .upgrade_lock + .version_infallible(vote.view_number()) + .await + >= V::Epochs::VERSION + { + MessageKind::::from_consensus_message(SequencingMessage::General( + GeneralConsensusMessage::Vote2(vote.clone()), + )) + } else { MessageKind::::from_consensus_message(SequencingMessage::General( GeneralConsensusMessage::Vote(vote.clone().to_vote()), - )), - TransmitType::Broadcast, - )) + )) + }; + + Some((vote.signing_key(), message, TransmitType::Broadcast)) } HotShotEvent::QuorumProposalRequestSend(req, signature) => Some(( req.key.clone(), @@ -437,13 +480,23 @@ impl< } HotShotEvent::DaProposalSend(proposal, sender) => { *maybe_action = Some(HotShotAction::DaPropose); - Some(( - sender, + + let message = if self + .upgrade_lock + .version_infallible(proposal.data.view_number()) + .await + >= V::Epochs::VERSION + { MessageKind::::from_consensus_message(SequencingMessage::Da( - DaConsensusMessage::DaProposal(proposal), - )), - TransmitType::DaCommitteeBroadcast, - )) + DaConsensusMessage::DaProposal2(proposal), + )) + } else { + MessageKind::::from_consensus_message(SequencingMessage::Da( + DaConsensusMessage::DaProposal(convert_proposal(proposal)), + )) + }; + + Some((sender, message, TransmitType::DaCommitteeBroadcast)) } HotShotEvent::DaVoteSend(vote) => { *maybe_action = Some(HotShotAction::DaVote); @@ -460,23 +513,38 @@ impl< } }; - Some(( - vote.signing_key(), + let message = if self.upgrade_lock.version_infallible(view_number).await + >= V::Epochs::VERSION + { MessageKind::::from_consensus_message(SequencingMessage::Da( - DaConsensusMessage::DaVote(vote.clone()), - )), - TransmitType::Direct(leader), - )) + DaConsensusMessage::DaVote2(vote.clone()), + )) + } else { + MessageKind::::from_consensus_message(SequencingMessage::Da( + DaConsensusMessage::DaVote(vote.clone().to_vote()), + )) + }; + + Some((vote.signing_key(), message, TransmitType::Direct(leader))) } HotShotEvent::DacSend(certificate, sender) => { *maybe_action = Some(HotShotAction::DaCert); - Some(( - sender, + let message = if self + .upgrade_lock + .version_infallible(certificate.view_number()) + .await + >= V::Epochs::VERSION + { MessageKind::::from_consensus_message(SequencingMessage::Da( - DaConsensusMessage::DaCertificate(certificate), - )), - TransmitType::Broadcast, - )) + DaConsensusMessage::DaCertificate2(certificate), + )) + } else { + MessageKind::::from_consensus_message(SequencingMessage::Da( + DaConsensusMessage::DaCertificate(certificate.to_dac()), + )) + }; + + Some((sender, message, TransmitType::Broadcast)) } HotShotEvent::ViewSyncPreCommitVoteSend(vote) => { let view_number = vote.view_number() + vote.date().relay; @@ -546,21 +614,21 @@ impl< TransmitType::Direct(leader), )) } - HotShotEvent::ViewSyncPreCommitCertificate2Send(certificate, sender) => Some(( + HotShotEvent::ViewSyncPreCommitCertificateSend(certificate, sender) => Some(( sender, MessageKind::::from_consensus_message(SequencingMessage::General( GeneralConsensusMessage::ViewSyncPreCommitCertificate(certificate), )), TransmitType::Broadcast, )), - HotShotEvent::ViewSyncCommitCertificate2Send(certificate, sender) => Some(( + HotShotEvent::ViewSyncCommitCertificateSend(certificate, sender) => Some(( sender, MessageKind::::from_consensus_message(SequencingMessage::General( GeneralConsensusMessage::ViewSyncCommitCertificate(certificate), )), TransmitType::Broadcast, )), - HotShotEvent::ViewSyncFinalizeCertificate2Send(certificate, sender) => Some(( + HotShotEvent::ViewSyncFinalizeCertificateSend(certificate, sender) => Some(( sender, MessageKind::::from_consensus_message(SequencingMessage::General( GeneralConsensusMessage::ViewSyncFinalizeCertificate(certificate), diff --git a/crates/task-impls/src/quorum_proposal/handlers.rs b/crates/task-impls/src/quorum_proposal/handlers.rs index b1cc8e36fa..e8b124b1e2 100644 --- a/crates/task-impls/src/quorum_proposal/handlers.rs +++ b/crates/task-impls/src/quorum_proposal/handlers.rs @@ -20,7 +20,8 @@ use committable::Committable; use hotshot_task::dependency_task::HandleDepOutput; use hotshot_types::{ consensus::{CommitmentAndMetadata, OuterConsensus}, - data::{Leaf2, QuorumProposal, VidDisperse, ViewChangeEvidence}, + data::{Leaf2, QuorumProposal2, VidDisperse, ViewChangeEvidence}, + drb::{INITIAL_DRB_RESULT, INITIAL_DRB_SEED_INPUT}, message::Proposal, simple_certificate::{QuorumCertificate2, UpgradeCertificate}, traits::{ @@ -50,7 +51,7 @@ pub(crate) enum ProposalDependency { /// For the `Qc2Formed` event. Qc, - /// For the `ViewSyncFinalizeCertificate2Recv` event. + /// For the `ViewSyncFinalizeCertificateRecv` event. ViewSyncCert, /// For the `Qc2Formed` event timeout branch. @@ -296,14 +297,15 @@ impl ProposalDependencyHandle { .context(warn!("Failed to construct marketplace block header"))? }; - let proposal = QuorumProposal { + let proposal = QuorumProposal2 { block_header, view_number: self.view_number, - justify_qc: parent_qc.to_qc(), + justify_qc: parent_qc, upgrade_certificate, - proposal_certificate, - } - .into(); + view_change_evidence: proposal_certificate, + drb_seed: INITIAL_DRB_SEED_INPUT, + drb_result: INITIAL_DRB_RESULT, + }; let proposed_leaf = Leaf2::from_quorum_proposal(&proposal); ensure!( @@ -376,7 +378,7 @@ impl HandleDepOutput for ProposalDependencyHandle< parent_qc = Some(qc.clone()); } }, - HotShotEvent::ViewSyncFinalizeCertificate2Recv(cert) => { + HotShotEvent::ViewSyncFinalizeCertificateRecv(cert) => { view_sync_finalize_cert = Some(cert.clone()); } HotShotEvent::VidDisperseSend(share, _) => { diff --git a/crates/task-impls/src/quorum_proposal/mod.rs b/crates/task-impls/src/quorum_proposal/mod.rs index 06150dff97..49875c6480 100644 --- a/crates/task-impls/src/quorum_proposal/mod.rs +++ b/crates/task-impls/src/quorum_proposal/mod.rs @@ -117,8 +117,7 @@ impl, V: Versions> } } ProposalDependency::ViewSyncCert => { - if let HotShotEvent::ViewSyncFinalizeCertificate2Recv(view_sync_cert) = - event + if let HotShotEvent::ViewSyncFinalizeCertificateRecv(view_sync_cert) = event { view_sync_cert.view_number() } else { @@ -225,7 +224,7 @@ impl, V: Versions> qc_dependency.mark_as_completed(event); } }, - HotShotEvent::ViewSyncFinalizeCertificate2Recv(_) => { + HotShotEvent::ViewSyncFinalizeCertificateRecv(_) => { view_sync_dependency.mark_as_completed(event); } HotShotEvent::VidDisperseSend(_, _) => { @@ -437,7 +436,7 @@ impl, V: Versions> Arc::clone(&event), )?; } - HotShotEvent::ViewSyncFinalizeCertificate2Recv(certificate) => { + HotShotEvent::ViewSyncFinalizeCertificateRecv(certificate) => { let epoch_number = self.consensus.read().await.cur_epoch(); ensure!( diff --git a/crates/task-impls/src/quorum_proposal_recv/handlers.rs b/crates/task-impls/src/quorum_proposal_recv/handlers.rs index 3d5c010058..528fc04562 100644 --- a/crates/task-impls/src/quorum_proposal_recv/handlers.rs +++ b/crates/task-impls/src/quorum_proposal_recv/handlers.rs @@ -156,10 +156,10 @@ pub(crate) async fn handle_quorum_proposal_recv< .is_valid_cert( validation_info .quorum_membership - .stake_table(validation_info.cur_epoch), + .stake_table(justify_qc.data.epoch), validation_info .quorum_membership - .success_threshold(validation_info.cur_epoch), + .success_threshold(justify_qc.data.epoch), &validation_info.upgrade_lock, ) .await diff --git a/crates/task-impls/src/quorum_vote/handlers.rs b/crates/task-impls/src/quorum_vote/handlers.rs index 56804f1d52..c41b4d82ca 100644 --- a/crates/task-impls/src/quorum_vote/handlers.rs +++ b/crates/task-impls/src/quorum_vote/handlers.rs @@ -358,12 +358,17 @@ pub(crate) async fn submit_vote, V private_key: ::PrivateKey, upgrade_lock: UpgradeLock, view_number: TYPES::View, - epoch_number: TYPES::Epoch, + epoch_height: u64, storage: Arc>, leaf: Leaf2, vid_share: Proposal>, extended_vote: bool, ) -> Result<()> { + let epoch_number = TYPES::Epoch::new(epoch_from_block_number( + leaf.block_header().block_number(), + epoch_height, + )); + ensure!( quorum_membership.has_stake(&public_key, epoch_number), info!( @@ -376,6 +381,7 @@ pub(crate) async fn submit_vote, V let vote = QuorumVote2::::create_signed_vote( QuorumData2 { leaf_commit: leaf.commit(), + epoch: epoch_number, }, view_number, &public_key, diff --git a/crates/task-impls/src/quorum_vote/mod.rs b/crates/task-impls/src/quorum_vote/mod.rs index 4162969397..68361be938 100644 --- a/crates/task-impls/src/quorum_vote/mod.rs +++ b/crates/task-impls/src/quorum_vote/mod.rs @@ -234,7 +234,7 @@ impl + 'static, V: Versions> Handl self.private_key.clone(), self.upgrade_lock.clone(), self.view_number, - current_epoch, + self.epoch_height, Arc::clone(&self.storage), leaf, vid_share, @@ -709,7 +709,7 @@ impl, V: Versions> QuorumVoteTaskS self.private_key.clone(), self.upgrade_lock.clone(), proposal.data.view_number(), - current_epoch, + self.epoch_height, Arc::clone(&self.storage), proposed_leaf, updated_vid, diff --git a/crates/task-impls/src/transactions.rs b/crates/task-impls/src/transactions.rs index f6da7ffec0..ffe9290d73 100644 --- a/crates/task-impls/src/transactions.rs +++ b/crates/task-impls/src/transactions.rs @@ -127,6 +127,7 @@ impl, V: Versions> TransactionTask &mut self, event_stream: &Sender>>, block_view: TYPES::View, + block_epoch: TYPES::Epoch, ) -> Option { let version = match self.upgrade_lock.version(block_view).await { Ok(v) => v, @@ -137,10 +138,10 @@ impl, V: Versions> TransactionTask }; if version < V::Marketplace::VERSION { - self.handle_view_change_legacy(event_stream, block_view) + self.handle_view_change_legacy(event_stream, block_view, block_epoch) .await } else { - self.handle_view_change_marketplace(event_stream, block_view) + self.handle_view_change_marketplace(event_stream, block_view, block_epoch) .await } } @@ -151,6 +152,7 @@ impl, V: Versions> TransactionTask &mut self, event_stream: &Sender>>, block_view: TYPES::View, + block_epoch: TYPES::Epoch, ) -> Option { let version = match self.upgrade_lock.version(block_view).await { Ok(v) => v, @@ -188,6 +190,7 @@ impl, V: Versions> TransactionTask block_payload.encode(), metadata, block_view, + block_epoch, vec1::vec1![fee], precompute_data, None, @@ -231,6 +234,7 @@ impl, V: Versions> TransactionTask vec![].into(), metadata, block_view, + block_epoch, vec1::vec1![null_fee], Some(precompute_data), None, @@ -251,6 +255,7 @@ impl, V: Versions> TransactionTask async fn produce_block_marketplace( &mut self, block_view: TYPES::View, + block_epoch: TYPES::Epoch, task_start_time: Instant, ) -> Result> { ensure!( @@ -343,6 +348,7 @@ impl, V: Versions> TransactionTask block_payload.encode(), metadata, block_view, + block_epoch, sequencing_fees, None, Some(auction_result), @@ -353,6 +359,7 @@ impl, V: Versions> TransactionTask pub fn null_block( &self, block_view: TYPES::View, + block_epoch: TYPES::Epoch, version: Version, ) -> Option> { let membership_total_nodes = self.membership.total_nodes(self.cur_epoch); @@ -374,6 +381,7 @@ impl, V: Versions> TransactionTask vec![].into(), metadata, block_view, + block_epoch, vec1::vec1![null_fee], Some(precompute_data), Some(TYPES::AuctionResult::default()), @@ -386,6 +394,7 @@ impl, V: Versions> TransactionTask &mut self, event_stream: &Sender>>, block_view: TYPES::View, + block_epoch: TYPES::Epoch, ) -> Option { let task_start_time = Instant::now(); @@ -398,7 +407,7 @@ impl, V: Versions> TransactionTask }; let packed_bundle = match self - .produce_block_marketplace(block_view, task_start_time) + .produce_block_marketplace(block_view, block_epoch, task_start_time) .await { Ok(b) => b, @@ -409,7 +418,7 @@ impl, V: Versions> TransactionTask e ); - let null_block = self.null_block(block_view, version)?; + let null_block = self.null_block(block_view, block_epoch, version)?; // Increment the metric for number of empty blocks proposed self.consensus @@ -438,12 +447,13 @@ impl, V: Versions> TransactionTask &mut self, event_stream: &Sender>>, block_view: TYPES::View, + block_epoch: TYPES::Epoch, ) -> Option { if self.consensus.read().await.is_high_qc_forming_eqc() { tracing::info!("Reached end of epoch. Not getting a new block until we form an eQC."); None } else { - self.handle_view_change_marketplace(event_stream, block_view) + self.handle_view_change_marketplace(event_stream, block_view, block_epoch) .await } } @@ -481,7 +491,7 @@ impl, V: Versions> TransactionTask ); self.cur_view = view; if self.membership.leader(view, self.cur_epoch)? == self.public_key { - self.handle_view_change(&event_stream, view).await; + self.handle_view_change(&event_stream, view, *epoch).await; return Ok(()); } } diff --git a/crates/task-impls/src/view_sync.rs b/crates/task-impls/src/view_sync.rs index 6bb83dfc53..3574fe0ee6 100644 --- a/crates/task-impls/src/view_sync.rs +++ b/crates/task-impls/src/view_sync.rs @@ -18,7 +18,7 @@ use hotshot_task::task::TaskState; use hotshot_types::{ message::{GeneralConsensusMessage, UpgradeLock}, simple_certificate::{ - ViewSyncCommitCertificate2, ViewSyncFinalizeCertificate2, ViewSyncPreCommitCertificate2, + ViewSyncCommitCertificate, ViewSyncFinalizeCertificate, ViewSyncPreCommitCertificate, }, simple_vote::{ ViewSyncCommitData, ViewSyncCommitVote, ViewSyncFinalizeData, ViewSyncFinalizeVote, @@ -92,17 +92,16 @@ pub struct ViewSyncTaskState { /// Map of pre-commit vote accumulates for the relay pub pre_commit_relay_map: RwLock< - RelayMap, ViewSyncPreCommitCertificate2, V>, + RelayMap, ViewSyncPreCommitCertificate, V>, >, /// Map of commit vote accumulates for the relay pub commit_relay_map: - RwLock, ViewSyncCommitCertificate2, V>>, + RwLock, ViewSyncCommitCertificate, V>>, /// Map of finalize vote accumulates for the relay - pub finalize_relay_map: RwLock< - RelayMap, ViewSyncFinalizeCertificate2, V>, - >, + pub finalize_relay_map: + RwLock, ViewSyncFinalizeCertificate, V>>, /// Timeout duration for view sync rounds pub view_sync_timeout: Duration, @@ -263,19 +262,19 @@ impl ViewSyncTaskState { event_stream: Sender>>, ) -> Result<()> { match event.as_ref() { - HotShotEvent::ViewSyncPreCommitCertificate2Recv(certificate) => { + HotShotEvent::ViewSyncPreCommitCertificateRecv(certificate) => { tracing::debug!("Received view sync cert for phase {:?}", certificate); let view = certificate.view_number(); self.send_to_or_create_replica(event, view, &event_stream) .await; } - HotShotEvent::ViewSyncCommitCertificate2Recv(certificate) => { + HotShotEvent::ViewSyncCommitCertificateRecv(certificate) => { tracing::debug!("Received view sync cert for phase {:?}", certificate); let view = certificate.view_number(); self.send_to_or_create_replica(event, view, &event_stream) .await; } - HotShotEvent::ViewSyncFinalizeCertificate2Recv(certificate) => { + HotShotEvent::ViewSyncFinalizeCertificateRecv(certificate) => { tracing::debug!("Received view sync cert for phase {:?}", certificate); let view = certificate.view_number(); self.send_to_or_create_replica(event, view, &event_stream) @@ -521,7 +520,7 @@ impl ViewSyncReplicaTaskState { event_stream: Sender>>, ) -> Option { match event.as_ref() { - HotShotEvent::ViewSyncPreCommitCertificate2Recv(certificate) => { + HotShotEvent::ViewSyncPreCommitCertificateRecv(certificate) => { let last_seen_certificate = ViewSyncPhase::PreCommit; // Ignore certificate if it is for an older round @@ -607,7 +606,7 @@ impl ViewSyncReplicaTaskState { })); } - HotShotEvent::ViewSyncCommitCertificate2Recv(certificate) => { + HotShotEvent::ViewSyncCommitCertificateRecv(certificate) => { let last_seen_certificate = ViewSyncPhase::Commit; // Ignore certificate if it is for an older round @@ -706,7 +705,7 @@ impl ViewSyncReplicaTaskState { })); } - HotShotEvent::ViewSyncFinalizeCertificate2Recv(certificate) => { + HotShotEvent::ViewSyncFinalizeCertificateRecv(certificate) => { // Ignore certificate if it is for an older round if certificate.view_number() < self.next_view { tracing::warn!("We're already in a higher round"); diff --git a/crates/task-impls/src/vote_collection.rs b/crates/task-impls/src/vote_collection.rs index e0fc96040b..d7ad469746 100644 --- a/crates/task-impls/src/vote_collection.rs +++ b/crates/task-impls/src/vote_collection.rs @@ -17,12 +17,12 @@ use either::Either::{self, Left, Right}; use hotshot_types::{ message::UpgradeLock, simple_certificate::{ - DaCertificate, QuorumCertificate, QuorumCertificate2, TimeoutCertificate, - UpgradeCertificate, ViewSyncCommitCertificate2, ViewSyncFinalizeCertificate2, - ViewSyncPreCommitCertificate2, + DaCertificate2, QuorumCertificate, QuorumCertificate2, TimeoutCertificate, + UpgradeCertificate, ViewSyncCommitCertificate, ViewSyncFinalizeCertificate, + ViewSyncPreCommitCertificate, }, simple_vote::{ - DaVote, QuorumVote, QuorumVote2, TimeoutVote, UpgradeVote, ViewSyncCommitVote, + DaVote2, QuorumVote, QuorumVote2, TimeoutVote, UpgradeVote, ViewSyncCommitVote, ViewSyncFinalizeVote, ViewSyncPreCommitVote, }, traits::{ @@ -307,7 +307,8 @@ where type QuorumVoteState = VoteCollectionTaskState, QuorumCertificate2, V>; /// Alias for DA vote accumulator -type DaVoteState = VoteCollectionTaskState, DaCertificate, V>; +type DaVoteState = + VoteCollectionTaskState, DaCertificate2, V>; /// Alias for Timeout vote accumulator type TimeoutVoteState = VoteCollectionTaskState, TimeoutCertificate, V>; @@ -318,17 +319,17 @@ type UpgradeVoteState = type ViewSyncPreCommitState = VoteCollectionTaskState< TYPES, ViewSyncPreCommitVote, - ViewSyncPreCommitCertificate2, + ViewSyncPreCommitCertificate, V, >; /// Alias for View Sync Commit vote accumulator type ViewSyncCommitVoteState = - VoteCollectionTaskState, ViewSyncCommitCertificate2, V>; + VoteCollectionTaskState, ViewSyncCommitCertificate, V>; /// Alias for View Sync Finalize vote accumulator type ViewSyncFinalizeVoteState = VoteCollectionTaskState< TYPES, ViewSyncFinalizeVote, - ViewSyncFinalizeCertificate2, + ViewSyncFinalizeCertificate, V, >; @@ -386,8 +387,8 @@ impl AggregatableVote, UpgradeCertifi } } -impl AggregatableVote, DaCertificate> - for DaVote +impl AggregatableVote, DaCertificate2> + for DaVote2 { fn leader( &self, @@ -397,7 +398,7 @@ impl AggregatableVote, DaCertificate, + certificate: DaCertificate2, key: &TYPES::SignatureKey, ) -> HotShotEvent { HotShotEvent::DacSend(certificate, key.clone()) @@ -423,7 +424,7 @@ impl AggregatableVote, TimeoutCertifi } impl - AggregatableVote, ViewSyncCommitCertificate2> + AggregatableVote, ViewSyncCommitCertificate> for ViewSyncCommitVote { fn leader( @@ -434,15 +435,15 @@ impl membership.leader(self.date().round + self.date().relay, epoch) } fn make_cert_event( - certificate: ViewSyncCommitCertificate2, + certificate: ViewSyncCommitCertificate, key: &TYPES::SignatureKey, ) -> HotShotEvent { - HotShotEvent::ViewSyncCommitCertificate2Send(certificate, key.clone()) + HotShotEvent::ViewSyncCommitCertificateSend(certificate, key.clone()) } } impl - AggregatableVote, ViewSyncPreCommitCertificate2> + AggregatableVote, ViewSyncPreCommitCertificate> for ViewSyncPreCommitVote { fn leader( @@ -453,15 +454,15 @@ impl membership.leader(self.date().round + self.date().relay, epoch) } fn make_cert_event( - certificate: ViewSyncPreCommitCertificate2, + certificate: ViewSyncPreCommitCertificate, key: &TYPES::SignatureKey, ) -> HotShotEvent { - HotShotEvent::ViewSyncPreCommitCertificate2Send(certificate, key.clone()) + HotShotEvent::ViewSyncPreCommitCertificateSend(certificate, key.clone()) } } impl - AggregatableVote, ViewSyncFinalizeCertificate2> + AggregatableVote, ViewSyncFinalizeCertificate> for ViewSyncFinalizeVote { fn leader( @@ -472,10 +473,10 @@ impl membership.leader(self.date().round + self.date().relay, epoch) } fn make_cert_event( - certificate: ViewSyncFinalizeCertificate2, + certificate: ViewSyncFinalizeCertificate, key: &TYPES::SignatureKey, ) -> HotShotEvent { - HotShotEvent::ViewSyncFinalizeCertificate2Send(certificate, key.clone()) + HotShotEvent::ViewSyncFinalizeCertificateSend(certificate, key.clone()) } } @@ -522,14 +523,14 @@ impl } #[async_trait] -impl HandleVoteEvent, DaCertificate> +impl HandleVoteEvent, DaCertificate2> for DaVoteState { async fn handle_vote_event( &mut self, event: Arc>, sender: &Sender>>, - ) -> Result>> { + ) -> Result>> { match event.as_ref() { HotShotEvent::DaVoteRecv(vote) => self.accumulate_vote(vote, sender).await, _ => Ok(None), @@ -562,14 +563,14 @@ impl #[async_trait] impl - HandleVoteEvent, ViewSyncPreCommitCertificate2> + HandleVoteEvent, ViewSyncPreCommitCertificate> for ViewSyncPreCommitState { async fn handle_vote_event( &mut self, event: Arc>, sender: &Sender>>, - ) -> Result>> { + ) -> Result>> { match event.as_ref() { HotShotEvent::ViewSyncPreCommitVoteRecv(vote) => { self.accumulate_vote(vote, sender).await @@ -584,14 +585,14 @@ impl #[async_trait] impl - HandleVoteEvent, ViewSyncCommitCertificate2> + HandleVoteEvent, ViewSyncCommitCertificate> for ViewSyncCommitVoteState { async fn handle_vote_event( &mut self, event: Arc>, sender: &Sender>>, - ) -> Result>> { + ) -> Result>> { match event.as_ref() { HotShotEvent::ViewSyncCommitVoteRecv(vote) => self.accumulate_vote(vote, sender).await, _ => Ok(None), @@ -604,14 +605,14 @@ impl #[async_trait] impl - HandleVoteEvent, ViewSyncFinalizeCertificate2> + HandleVoteEvent, ViewSyncFinalizeCertificate> for ViewSyncFinalizeVoteState { async fn handle_vote_event( &mut self, event: Arc>, sender: &Sender>>, - ) -> Result>> { + ) -> Result>> { match event.as_ref() { HotShotEvent::ViewSyncFinalizeVoteRecv(vote) => { self.accumulate_vote(vote, sender).await diff --git a/crates/testing/src/helpers.rs b/crates/testing/src/helpers.rs index cc468a1859..9097f38d02 100644 --- a/crates/testing/src/helpers.rs +++ b/crates/testing/src/helpers.rs @@ -27,8 +27,8 @@ use hotshot_types::{ consensus::ConsensusMetricsValue, data::{Leaf, Leaf2, QuorumProposal, VidDisperse, VidDisperseShare}, message::{GeneralConsensusMessage, Proposal, UpgradeLock}, - simple_certificate::DaCertificate, - simple_vote::{DaData, DaVote, QuorumData, QuorumVote, SimpleVote, VersionedVoteData}, + simple_certificate::DaCertificate2, + simple_vote::{DaData2, DaVote2, QuorumData, QuorumVote, SimpleVote, VersionedVoteData}, traits::{ block_contents::vid_commitment, consensus_api::ConsensusApi, @@ -364,17 +364,18 @@ pub async fn build_da_certificate( public_key: &TYPES::SignatureKey, private_key: &::PrivateKey, upgrade_lock: &UpgradeLock, -) -> DaCertificate { +) -> DaCertificate2 { let encoded_transactions = TestTransaction::encode(&transactions); let da_payload_commitment = vid_commitment(&encoded_transactions, membership.total_nodes(epoch_number)); - let da_data = DaData { + let da_data = DaData2 { payload_commit: da_payload_commitment, + epoch: epoch_number, }; - build_cert::, DaCertificate>( + build_cert::, DaVote2, DaCertificate2>( da_data, membership, view_number, diff --git a/crates/testing/src/view_generator.rs b/crates/testing/src/view_generator.rs index a6651ad55d..e31f98364f 100644 --- a/crates/testing/src/view_generator.rs +++ b/crates/testing/src/view_generator.rs @@ -22,17 +22,17 @@ use hotshot_example_types::{ }; use hotshot_types::{ data::{ - DaProposal, EpochNumber, Leaf, Leaf2, QuorumProposal2, VidDisperse, VidDisperseShare, + DaProposal2, EpochNumber, Leaf, Leaf2, QuorumProposal2, VidDisperse, VidDisperseShare, ViewChangeEvidence, ViewNumber, }, drb::{INITIAL_DRB_RESULT, INITIAL_DRB_SEED_INPUT}, message::{Proposal, UpgradeLock}, simple_certificate::{ - DaCertificate, QuorumCertificate, QuorumCertificate2, TimeoutCertificate, - UpgradeCertificate, ViewSyncFinalizeCertificate2, + DaCertificate2, QuorumCertificate, QuorumCertificate2, TimeoutCertificate, + UpgradeCertificate, ViewSyncFinalizeCertificate, }, simple_vote::{ - DaData, DaVote, QuorumData2, QuorumVote2, TimeoutData, TimeoutVote, UpgradeProposalData, + DaData2, DaVote2, QuorumData2, QuorumVote2, TimeoutData, TimeoutVote, UpgradeProposalData, UpgradeVote, ViewSyncFinalizeData, ViewSyncFinalizeVote, }, traits::{ @@ -40,6 +40,7 @@ use hotshot_types::{ node_implementation::{ConsensusTime, NodeType}, BlockPayload, }, + utils::epoch_from_block_number, }; use rand::{thread_rng, Rng}; use sha2::{Digest, Sha256}; @@ -50,7 +51,7 @@ use crate::helpers::{ #[derive(Clone)] pub struct TestView { - pub da_proposal: Proposal>, + pub da_proposal: Proposal>, pub quorum_proposal: Proposal>, pub leaf: Leaf2, pub view_number: ViewNumber, @@ -62,7 +63,7 @@ pub struct TestView { ::SignatureKey, ), pub leader_public_key: ::SignatureKey, - pub da_certificate: DaCertificate, + pub da_certificate: DaCertificate2, pub transactions: Vec, upgrade_data: Option>, formed_upgrade_certificate: Option>, @@ -74,7 +75,7 @@ pub struct TestView { impl TestView { pub async fn genesis(membership: &::Membership) -> Self { let genesis_view = ViewNumber::new(1); - let genesis_epoch = EpochNumber::new(1); + let genesis_epoch = EpochNumber::new(0); let upgrade_lock = UpgradeLock::new(); let transactions = Vec::new(); @@ -152,10 +153,11 @@ impl TestView { ::SignatureKey::sign(&private_key, &encoded_transactions_hash) .expect("Failed to sign block payload"); - let da_proposal_inner = DaProposal:: { + let da_proposal_inner = DaProposal2:: { encoded_transactions: encoded_transactions.clone(), metadata, view_number: genesis_view, + epoch_number: genesis_epoch, }; let da_proposal = Proposal { @@ -217,6 +219,7 @@ impl TestView { let quorum_data = QuorumData2 { leaf_commit: old.leaf.commit(), + epoch: EpochNumber::new(0), }; let (old_private_key, old_public_key) = key_pair_for_id::(*old_view); @@ -306,7 +309,7 @@ impl TestView { TestVersions, ViewSyncFinalizeData, ViewSyncFinalizeVote, - ViewSyncFinalizeCertificate2, + ViewSyncFinalizeCertificate, >( data.clone(), membership, @@ -393,10 +396,11 @@ impl TestView { ::SignatureKey::sign(&private_key, &encoded_transactions_hash) .expect("Failed to sign block payload"); - let da_proposal_inner = DaProposal:: { + let da_proposal_inner = DaProposal2:: { encoded_transactions: encoded_transactions.clone(), metadata, view_number: next_view, + epoch_number: self.epoch_number, }; let da_proposal = Proposal { @@ -442,6 +446,10 @@ impl TestView { QuorumVote2::::create_signed_vote( QuorumData2 { leaf_commit: self.leaf.commit(), + epoch: EpochNumber::new(epoch_from_block_number( + self.leaf.height(), + handle.hotshot.config.epoch_height, + )), }, self.view_number, &handle.public_key(), @@ -470,10 +478,10 @@ impl TestView { pub async fn create_da_vote( &self, - data: DaData, + data: DaData2, handle: &SystemContextHandle, - ) -> DaVote { - DaVote::create_signed_vote( + ) -> DaVote2 { + DaVote2::create_signed_vote( data, self.view_number, &handle.public_key(), diff --git a/crates/testing/src/view_sync_task.rs b/crates/testing/src/view_sync_task.rs index 733164d341..914c8279cd 100644 --- a/crates/testing/src/view_sync_task.rs +++ b/crates/testing/src/view_sync_task.rs @@ -48,12 +48,12 @@ impl> TestTaskState | HotShotEvent::ViewSyncPreCommitVoteSend(_) | HotShotEvent::ViewSyncCommitVoteSend(_) | HotShotEvent::ViewSyncFinalizeVoteSend(_) - | HotShotEvent::ViewSyncPreCommitCertificate2Recv(_) - | HotShotEvent::ViewSyncCommitCertificate2Recv(_) - | HotShotEvent::ViewSyncFinalizeCertificate2Recv(_) - | HotShotEvent::ViewSyncPreCommitCertificate2Send(_, _) - | HotShotEvent::ViewSyncCommitCertificate2Send(_, _) - | HotShotEvent::ViewSyncFinalizeCertificate2Send(_, _) + | HotShotEvent::ViewSyncPreCommitCertificateRecv(_) + | HotShotEvent::ViewSyncCommitCertificateRecv(_) + | HotShotEvent::ViewSyncFinalizeCertificateRecv(_) + | HotShotEvent::ViewSyncPreCommitCertificateSend(_, _) + | HotShotEvent::ViewSyncCommitCertificateSend(_, _) + | HotShotEvent::ViewSyncFinalizeCertificateSend(_, _) | HotShotEvent::ViewSyncTrigger(_) => { self.hit_view_sync.insert(id); } diff --git a/crates/testing/tests/tests_1/da_task.rs b/crates/testing/tests/tests_1/da_task.rs index 6f4c2a38df..e672ff24e3 100644 --- a/crates/testing/tests/tests_1/da_task.rs +++ b/crates/testing/tests/tests_1/da_task.rs @@ -23,7 +23,7 @@ use hotshot_testing::{ }; use hotshot_types::{ data::{null_block, EpochNumber, PackedBundle, ViewNumber}, - simple_vote::DaData, + simple_vote::DaData2, traits::{ block_contents::precompute_vid_commitment, election::Membership, @@ -63,8 +63,14 @@ async fn test_da_task() { proposals.push(view.da_proposal.clone()); leaders.push(view.leader_public_key); votes.push( - view.create_da_vote(DaData { payload_commit }, &handle) - .await, + view.create_da_vote( + DaData2 { + payload_commit, + epoch: EpochNumber::new(0), + }, + &handle, + ) + .await, ); dacs.push(view.da_certificate.clone()); vids.push(view.vid_proposal.clone()); @@ -76,8 +82,14 @@ async fn test_da_task() { proposals.push(view.da_proposal.clone()); leaders.push(view.leader_public_key); votes.push( - view.create_da_vote(DaData { payload_commit }, &handle) - .await, + view.create_da_vote( + DaData2 { + payload_commit, + epoch: EpochNumber::new(0), + }, + &handle, + ) + .await, ); dacs.push(view.da_certificate.clone()); vids.push(view.vid_proposal.clone()); @@ -85,14 +97,15 @@ async fn test_da_task() { let inputs = vec![ serial![ - ViewChange(ViewNumber::new(1), EpochNumber::new(1)), - ViewChange(ViewNumber::new(2), EpochNumber::new(1)), + ViewChange(ViewNumber::new(1), EpochNumber::new(0)), + ViewChange(ViewNumber::new(2), EpochNumber::new(0)), BlockRecv(PackedBundle::new( encoded_transactions.clone(), TestMetadata { num_transactions: transactions.len() as u64 }, ViewNumber::new(2), + EpochNumber::new(0), vec1::vec1![null_block::builder_fee::( membership.total_nodes(EpochNumber::new(0)), ::Base::VERSION, @@ -158,8 +171,14 @@ async fn test_da_task_storage_failure() { proposals.push(view.da_proposal.clone()); leaders.push(view.leader_public_key); votes.push( - view.create_da_vote(DaData { payload_commit }, &handle) - .await, + view.create_da_vote( + DaData2 { + payload_commit, + epoch: EpochNumber::new(0), + }, + &handle, + ) + .await, ); dacs.push(view.da_certificate.clone()); vids.push(view.vid_proposal.clone()); @@ -171,8 +190,14 @@ async fn test_da_task_storage_failure() { proposals.push(view.da_proposal.clone()); leaders.push(view.leader_public_key); votes.push( - view.create_da_vote(DaData { payload_commit }, &handle) - .await, + view.create_da_vote( + DaData2 { + payload_commit, + epoch: EpochNumber::new(0), + }, + &handle, + ) + .await, ); dacs.push(view.da_certificate.clone()); vids.push(view.vid_proposal.clone()); @@ -180,14 +205,15 @@ async fn test_da_task_storage_failure() { let inputs = vec![ serial![ - ViewChange(ViewNumber::new(1), EpochNumber::new(1)), - ViewChange(ViewNumber::new(2), EpochNumber::new(1)), + ViewChange(ViewNumber::new(1), EpochNumber::new(0)), + ViewChange(ViewNumber::new(2), EpochNumber::new(0)), BlockRecv(PackedBundle::new( encoded_transactions.clone(), TestMetadata { num_transactions: transactions.len() as u64 }, ViewNumber::new(2), + EpochNumber::new(0), vec1::vec1![null_block::builder_fee::( membership.total_nodes(EpochNumber::new(0)), ::Base::VERSION, diff --git a/crates/testing/tests/tests_1/quorum_proposal_task.rs b/crates/testing/tests/tests_1/quorum_proposal_task.rs index 0124e10b5a..25e70fc6c2 100644 --- a/crates/testing/tests/tests_1/quorum_proposal_task.rs +++ b/crates/testing/tests/tests_1/quorum_proposal_task.rs @@ -440,7 +440,7 @@ async fn test_quorum_proposal_task_view_sync() { }; let inputs = vec![random![ - ViewSyncFinalizeCertificate2Recv(cert.clone()), + ViewSyncFinalizeCertificateRecv(cert.clone()), SendPayloadCommitmentAndMetadata( payload_commitment, builder_commitment, diff --git a/crates/testing/tests/tests_1/transaction_task.rs b/crates/testing/tests/tests_1/transaction_task.rs index 43773e63da..e4ed70be64 100644 --- a/crates/testing/tests/tests_1/transaction_task.rs +++ b/crates/testing/tests/tests_1/transaction_task.rs @@ -52,6 +52,7 @@ async fn test_transaction_task_leader_two_views_in_a_row() { num_transactions: 0, }, current_view, + EpochNumber::new(1), vec1::vec1![ null_block::builder_fee::( handle.hotshot.memberships.total_nodes(EpochNumber::new(0)), diff --git a/crates/testing/tests/tests_1/vid_task.rs b/crates/testing/tests/tests_1/vid_task.rs index 81f9ac2999..3bf19bbc38 100644 --- a/crates/testing/tests/tests_1/vid_task.rs +++ b/crates/testing/tests/tests_1/vid_task.rs @@ -108,6 +108,7 @@ async fn test_vid_task() { num_transactions: transactions.len() as u64 }, ViewNumber::new(2), + EpochNumber::new(0), vec1::vec1![null_block::builder_fee::( membership.total_nodes(EpochNumber::new(0)), ::Base::VERSION, diff --git a/crates/types/src/consensus.rs b/crates/types/src/consensus.rs index 2d2e814e9f..0c2e8d936f 100644 --- a/crates/types/src/consensus.rs +++ b/crates/types/src/consensus.rs @@ -25,7 +25,7 @@ use crate::{ error::HotShotError, event::{HotShotAction, LeafInfo}, message::Proposal, - simple_certificate::{DaCertificate, QuorumCertificate2}, + simple_certificate::{DaCertificate2, QuorumCertificate2}, traits::{ block_contents::BuilderFee, metrics::{Counter, Gauge, Histogram, Metrics, NoMetrics}, @@ -281,7 +281,7 @@ pub struct Consensus { /// All the DA certs we've received for current and future views. /// view -> DA cert - saved_da_certs: HashMap>, + saved_da_certs: HashMap>, /// View number that is currently on. cur_view: TYPES::View, @@ -479,7 +479,7 @@ impl Consensus { } /// Get the saved DA certs. - pub fn saved_da_certs(&self) -> &HashMap> { + pub fn saved_da_certs(&self) -> &HashMap> { &self.saved_da_certs } @@ -747,7 +747,7 @@ impl Consensus { } /// Add a new entry to the da_certs map. - pub fn update_saved_da_certs(&mut self, view_number: TYPES::View, cert: DaCertificate) { + pub fn update_saved_da_certs(&mut self, view_number: TYPES::View, cert: DaCertificate2) { self.saved_da_certs.insert(view_number, cert); } diff --git a/crates/types/src/data.rs b/crates/types/src/data.rs index 422f2887cb..b6ec66f16a 100644 --- a/crates/types/src/data.rs +++ b/crates/types/src/data.rs @@ -34,7 +34,7 @@ use crate::{ message::{Proposal, UpgradeLock}, simple_certificate::{ QuorumCertificate, QuorumCertificate2, TimeoutCertificate, UpgradeCertificate, - ViewSyncFinalizeCertificate2, + ViewSyncFinalizeCertificate, }, simple_vote::{QuorumData, UpgradeProposalData, VersionedVoteData}, traits::{ @@ -147,6 +147,41 @@ pub struct DaProposal { pub view_number: TYPES::View, } +/// A proposal to start providing data availability for a block. +#[derive(derive_more::Debug, Serialize, Deserialize, Clone, Eq, PartialEq, Hash)] +#[serde(bound = "TYPES: NodeType")] +pub struct DaProposal2 { + /// Encoded transactions in the block to be applied. + pub encoded_transactions: Arc<[u8]>, + /// Metadata of the block to be applied. + pub metadata: >::Metadata, + /// View this proposal applies to + pub view_number: TYPES::View, + /// Epoch this proposal applies to + pub epoch_number: TYPES::Epoch, +} + +impl From> for DaProposal2 { + fn from(da_proposal: DaProposal) -> Self { + Self { + encoded_transactions: da_proposal.encoded_transactions, + metadata: da_proposal.metadata, + view_number: da_proposal.view_number, + epoch_number: TYPES::Epoch::new(0), + } + } +} + +impl From> for DaProposal { + fn from(da_proposal2: DaProposal2) -> Self { + Self { + encoded_transactions: da_proposal2.encoded_transactions, + metadata: da_proposal2.metadata, + view_number: da_proposal2.view_number, + } + } +} + /// A proposal to upgrade the network #[derive(derive_more::Debug, Serialize, Deserialize, Clone, Eq, PartialEq, Hash)] #[serde(bound = "TYPES: NodeType")] @@ -239,7 +274,7 @@ pub enum ViewChangeEvidence { /// Holds a timeout certificate. Timeout(TimeoutCertificate), /// Holds a view sync finalized certificate. - ViewSync(ViewSyncFinalizeCertificate2), + ViewSync(ViewSyncFinalizeCertificate), } impl ViewChangeEvidence { @@ -420,13 +455,13 @@ impl From> for QuorumProposal2 { } impl From> for QuorumProposal { - fn from(quorum_proposal: QuorumProposal2) -> Self { + fn from(quorum_proposal2: QuorumProposal2) -> Self { Self { - block_header: quorum_proposal.block_header, - view_number: quorum_proposal.view_number, - justify_qc: quorum_proposal.justify_qc.to_qc(), - upgrade_certificate: quorum_proposal.upgrade_certificate, - proposal_certificate: quorum_proposal.view_change_evidence, + block_header: quorum_proposal2.block_header, + view_number: quorum_proposal2.view_number, + justify_qc: quorum_proposal2.justify_qc.to_qc(), + upgrade_certificate: quorum_proposal2.upgrade_certificate, + proposal_certificate: quorum_proposal2.view_change_evidence, } } } @@ -455,6 +490,12 @@ impl HasViewNumber for DaProposal { } } +impl HasViewNumber for DaProposal2 { + fn view_number(&self) -> TYPES::View { + self.view_number + } +} + impl HasViewNumber for VidDisperse { fn view_number(&self) -> TYPES::View { self.view_number @@ -1226,6 +1267,9 @@ pub struct PackedBundle { /// The view number that this block is associated with. pub view_number: TYPES::View, + /// The view number that this block is associated with. + pub epoch_number: TYPES::Epoch, + /// The sequencing fee for submitting bundles. pub sequencing_fees: Vec1>, @@ -1242,6 +1286,7 @@ impl PackedBundle { encoded_transactions: Arc<[u8]>, metadata: >::Metadata, view_number: TYPES::View, + epoch_number: TYPES::Epoch, sequencing_fees: Vec1>, vid_precompute: Option, auction_result: Option, @@ -1250,6 +1295,7 @@ impl PackedBundle { encoded_transactions, metadata, view_number, + epoch_number, sequencing_fees, vid_precompute, auction_result, diff --git a/crates/types/src/event.rs b/crates/types/src/event.rs index c4ae586866..0a79913d88 100644 --- a/crates/types/src/event.rs +++ b/crates/types/src/event.rs @@ -11,12 +11,13 @@ use std::sync::Arc; use serde::{Deserialize, Serialize}; use crate::{ - data::{DaProposal, Leaf2, QuorumProposal2, UpgradeProposal, VidDisperseShare}, + data::{DaProposal2, Leaf2, QuorumProposal2, UpgradeProposal, VidDisperseShare}, error::HotShotError, message::Proposal, simple_certificate::QuorumCertificate2, traits::{node_implementation::NodeType, ValidatedState}, }; + /// A status event emitted by a `HotShot` instance /// /// This includes some metadata, such as the stage and view number that the event was generated in, @@ -151,7 +152,7 @@ pub enum EventType { /// or submitted to the network by us DaProposal { /// Contents of the proposal - proposal: Proposal>, + proposal: Proposal>, /// Public key of the leader submitting the proposal sender: TYPES::SignatureKey, }, diff --git a/crates/types/src/message.rs b/crates/types/src/message.rs index eb4861d22e..062ae9c96f 100644 --- a/crates/types/src/message.rs +++ b/crates/types/src/message.rs @@ -26,16 +26,17 @@ use vbs::{ use crate::{ data::{ - DaProposal, Leaf, Leaf2, QuorumProposal, QuorumProposal2, UpgradeProposal, VidDisperseShare, + DaProposal, DaProposal2, Leaf, Leaf2, QuorumProposal, QuorumProposal2, UpgradeProposal, + VidDisperseShare, }, request_response::ProposalRequestPayload, simple_certificate::{ - DaCertificate, QuorumCertificate2, UpgradeCertificate, ViewSyncCommitCertificate2, - ViewSyncFinalizeCertificate2, ViewSyncPreCommitCertificate2, + DaCertificate, DaCertificate2, QuorumCertificate2, UpgradeCertificate, + ViewSyncCommitCertificate, ViewSyncFinalizeCertificate, ViewSyncPreCommitCertificate, }, simple_vote::{ - DaVote, QuorumVote, TimeoutVote, UpgradeVote, ViewSyncCommitVote, ViewSyncFinalizeVote, - ViewSyncPreCommitVote, + DaVote, DaVote2, QuorumVote, QuorumVote2, TimeoutVote, UpgradeVote, ViewSyncCommitVote, + ViewSyncFinalizeVote, ViewSyncPreCommitVote, }, traits::{ election::Membership, @@ -183,13 +184,13 @@ pub enum GeneralConsensusMessage { ViewSyncFinalizeVote(ViewSyncFinalizeVote), /// Message with a view sync pre-commit certificate - ViewSyncPreCommitCertificate(ViewSyncPreCommitCertificate2), + ViewSyncPreCommitCertificate(ViewSyncPreCommitCertificate), /// Message with a view sync commit certificate - ViewSyncCommitCertificate(ViewSyncCommitCertificate2), + ViewSyncCommitCertificate(ViewSyncCommitCertificate), /// Message with a view sync finalize certificate - ViewSyncFinalizeCertificate(ViewSyncFinalizeCertificate2), + ViewSyncFinalizeCertificate(ViewSyncFinalizeCertificate), /// Message with a Timeout vote TimeoutVote(TimeoutVote), @@ -200,6 +201,15 @@ pub enum GeneralConsensusMessage { /// Message with an upgrade vote UpgradeVote(UpgradeVote), + /// Message for the next leader containing our highest QC + HighQc(QuorumCertificate2), + + /// Message with a quorum proposal. + Proposal2(Proposal>), + + /// Message with a quorum vote. + Vote2(QuorumVote2), + /// A peer node needs a proposal from the leader. ProposalRequested( ProposalRequestPayload, @@ -209,8 +219,8 @@ pub enum GeneralConsensusMessage { /// A replica has responded with a valid proposal. ProposalResponse(Proposal>), - /// Message for the next leader containing our highest QC - HighQc(QuorumCertificate2), + /// A replica has responded with a valid proposal. + Proposal2Response(Proposal>), } #[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Hash, Eq)] @@ -230,6 +240,15 @@ pub enum DaConsensusMessage { /// /// Like [`DaProposal`]. Use `Msg` suffix to distinguish from `VidDisperse`. VidDisperseMsg(Proposal>), + + /// Proposal for data availability committee + DaProposal2(Proposal>), + + /// vote for data availability committee + DaVote2(DaVote2), + + /// Certificate data is available + DaCertificate2(DaCertificate2), } /// Messages for sequencing consensus. @@ -258,6 +277,9 @@ impl SequencingMessage { GeneralConsensusMessage::ProposalResponse(proposal) => { proposal.data.view_number() } + GeneralConsensusMessage::Proposal2Response(proposal) => { + proposal.data.view_number() + } GeneralConsensusMessage::Vote(vote_message) => vote_message.view_number(), GeneralConsensusMessage::TimeoutVote(message) => message.view_number(), GeneralConsensusMessage::ViewSyncPreCommitVote(message) => { @@ -277,6 +299,12 @@ impl SequencingMessage { GeneralConsensusMessage::UpgradeProposal(message) => message.data.view_number(), GeneralConsensusMessage::UpgradeVote(message) => message.view_number(), GeneralConsensusMessage::HighQc(qc) => qc.view_number(), + GeneralConsensusMessage::Proposal2(p) => { + // view of leader in the leaf when proposal + // this should match replica upon receipt + p.data.view_number() + } + GeneralConsensusMessage::Vote2(vote_message) => vote_message.view_number(), } } SequencingMessage::Da(da_message) => { @@ -289,6 +317,13 @@ impl SequencingMessage { DaConsensusMessage::DaVote(vote_message) => vote_message.view_number(), DaConsensusMessage::DaCertificate(cert) => cert.view_number, DaConsensusMessage::VidDisperseMsg(disperse) => disperse.data.view_number(), + DaConsensusMessage::DaProposal2(p) => { + // view of leader in the leaf when proposal + // this should match replica upon receipt + p.data.view_number() + } + DaConsensusMessage::DaVote2(vote_message) => vote_message.view_number(), + DaConsensusMessage::DaCertificate2(cert) => cert.view_number, } } } diff --git a/crates/types/src/simple_certificate.rs b/crates/types/src/simple_certificate.rs index f2cc8cd689..f88e549ede 100644 --- a/crates/types/src/simple_certificate.rs +++ b/crates/types/src/simple_certificate.rs @@ -24,8 +24,9 @@ use crate::{ data::serialize_signature2, message::UpgradeLock, simple_vote::{ - DaData, QuorumData, QuorumData2, QuorumMarker, TimeoutData, UpgradeProposalData, - VersionedVoteData, ViewSyncCommitData, ViewSyncFinalizeData, ViewSyncPreCommitData, + DaData, DaData2, QuorumData, QuorumData2, QuorumMarker, TimeoutData, TimeoutData2, + UpgradeProposalData, VersionedVoteData, ViewSyncCommitData, ViewSyncCommitData2, + ViewSyncFinalizeData, ViewSyncFinalizeData2, ViewSyncPreCommitData, ViewSyncPreCommitData2, Voteable, }, traits::{ @@ -225,6 +226,94 @@ impl> Certificate } } +impl> Certificate> + for SimpleCertificate, THRESHOLD> +{ + type Voteable = DaData2; + type Threshold = THRESHOLD; + + fn create_signed_certificate( + vote_commitment: Commitment, V>>, + data: Self::Voteable, + sig: ::QcType, + view: TYPES::View, + ) -> Self { + let vote_commitment_bytes: [u8; 32] = vote_commitment.into(); + + SimpleCertificate { + data, + vote_commitment: Commitment::from_raw(vote_commitment_bytes), + view_number: view, + signatures: Some(sig), + _pd: PhantomData, + } + } + async fn is_valid_cert( + &self, + stake_table: Vec<::StakeTableEntry>, + threshold: NonZeroU64, + upgrade_lock: &UpgradeLock, + ) -> bool { + if self.view_number == TYPES::View::genesis() { + return true; + } + let real_qc_pp = ::public_parameter( + stake_table, + U256::from(u64::from(threshold)), + ); + let Ok(commit) = self.data_commitment(upgrade_lock).await else { + return false; + }; + ::check( + &real_qc_pp, + commit.as_ref(), + self.signatures.as_ref().unwrap(), + ) + } + /// Proxy's to `Membership.stake` + fn stake_table_entry>( + membership: &MEMBERSHIP, + pub_key: &TYPES::SignatureKey, + epoch: TYPES::Epoch, + ) -> Option<::StakeTableEntry> { + membership.da_stake(pub_key, epoch) + } + + /// Proxy's to `Membership.da_stake_table` + fn stake_table>( + membership: &MEMBERSHIP, + epoch: TYPES::Epoch, + ) -> Vec<::StakeTableEntry> { + membership.da_stake_table(epoch) + } + /// Proxy's to `Membership.da_total_nodes` + fn total_nodes>( + membership: &MEMBERSHIP, + epoch: TYPES::Epoch, + ) -> usize { + membership.da_total_nodes(epoch) + } + fn threshold>( + membership: &MEMBERSHIP, + epoch: TYPES::Epoch, + ) -> u64 { + membership.da_success_threshold(epoch).into() + } + fn data(&self) -> &Self::Voteable { + &self.data + } + async fn data_commitment( + &self, + upgrade_lock: &UpgradeLock, + ) -> Result, V>>> { + Ok( + VersionedVoteData::new(self.data.clone(), self.view_number, upgrade_lock) + .await? + .commit(), + ) + } +} + impl> Certificate for SimpleCertificate { @@ -388,6 +477,7 @@ impl QuorumCertificate { let bytes: [u8; 32] = self.data.leaf_commit.into(); let data = QuorumData2 { leaf_commit: Commitment::from_raw(bytes), + epoch: TYPES::Epoch::new(0), }; let bytes: [u8; 32] = self.vote_commitment.into(); @@ -424,23 +514,248 @@ impl QuorumCertificate2 { } } +impl DaCertificate { + /// Convert a `DaCertificate` into a `DaCertificate2` + pub fn to_dac2(self) -> DaCertificate2 { + let data = DaData2 { + payload_commit: self.data.payload_commit, + epoch: TYPES::Epoch::new(0), + }; + + let bytes: [u8; 32] = self.vote_commitment.into(); + let vote_commitment = Commitment::from_raw(bytes); + + SimpleCertificate { + data, + vote_commitment, + view_number: self.view_number, + signatures: self.signatures.clone(), + _pd: PhantomData, + } + } +} + +impl DaCertificate2 { + /// Convert a `DaCertificate` into a `DaCertificate2` + pub fn to_dac(self) -> DaCertificate { + let data = DaData { + payload_commit: self.data.payload_commit, + }; + + let bytes: [u8; 32] = self.vote_commitment.into(); + let vote_commitment = Commitment::from_raw(bytes); + + SimpleCertificate { + data, + vote_commitment, + view_number: self.view_number, + signatures: self.signatures.clone(), + _pd: PhantomData, + } + } +} + +impl ViewSyncPreCommitCertificate { + /// Convert a `DaCertificate` into a `DaCertificate2` + pub fn to_vsc2(self) -> ViewSyncPreCommitCertificate2 { + let data = ViewSyncPreCommitData2 { + relay: self.data.relay, + round: self.data.round, + epoch: TYPES::Epoch::new(0), + }; + + let bytes: [u8; 32] = self.vote_commitment.into(); + let vote_commitment = Commitment::from_raw(bytes); + + SimpleCertificate { + data, + vote_commitment, + view_number: self.view_number, + signatures: self.signatures.clone(), + _pd: PhantomData, + } + } +} + +impl ViewSyncPreCommitCertificate2 { + /// Convert a `DaCertificate` into a `DaCertificate2` + pub fn to_vsc(self) -> ViewSyncPreCommitCertificate { + let data = ViewSyncPreCommitData { + relay: self.data.relay, + round: self.data.round, + }; + + let bytes: [u8; 32] = self.vote_commitment.into(); + let vote_commitment = Commitment::from_raw(bytes); + + SimpleCertificate { + data, + vote_commitment, + view_number: self.view_number, + signatures: self.signatures.clone(), + _pd: PhantomData, + } + } +} + +impl ViewSyncCommitCertificate { + /// Convert a `DaCertificate` into a `DaCertificate2` + pub fn to_vsc2(self) -> ViewSyncCommitCertificate2 { + let data = ViewSyncCommitData2 { + relay: self.data.relay, + round: self.data.round, + epoch: TYPES::Epoch::new(0), + }; + + let bytes: [u8; 32] = self.vote_commitment.into(); + let vote_commitment = Commitment::from_raw(bytes); + + SimpleCertificate { + data, + vote_commitment, + view_number: self.view_number, + signatures: self.signatures.clone(), + _pd: PhantomData, + } + } +} + +impl ViewSyncCommitCertificate2 { + /// Convert a `DaCertificate` into a `DaCertificate2` + pub fn to_vsc(self) -> ViewSyncCommitCertificate { + let data = ViewSyncCommitData { + relay: self.data.relay, + round: self.data.round, + }; + + let bytes: [u8; 32] = self.vote_commitment.into(); + let vote_commitment = Commitment::from_raw(bytes); + + SimpleCertificate { + data, + vote_commitment, + view_number: self.view_number, + signatures: self.signatures.clone(), + _pd: PhantomData, + } + } +} + +impl ViewSyncFinalizeCertificate { + /// Convert a `DaCertificate` into a `DaCertificate2` + pub fn to_vsc2(self) -> ViewSyncFinalizeCertificate2 { + let data = ViewSyncFinalizeData2 { + relay: self.data.relay, + round: self.data.round, + epoch: TYPES::Epoch::new(0), + }; + + let bytes: [u8; 32] = self.vote_commitment.into(); + let vote_commitment = Commitment::from_raw(bytes); + + SimpleCertificate { + data, + vote_commitment, + view_number: self.view_number, + signatures: self.signatures.clone(), + _pd: PhantomData, + } + } +} + +impl ViewSyncFinalizeCertificate2 { + /// Convert a `DaCertificate` into a `DaCertificate2` + pub fn to_vsc(self) -> ViewSyncFinalizeCertificate { + let data = ViewSyncFinalizeData { + relay: self.data.relay, + round: self.data.round, + }; + + let bytes: [u8; 32] = self.vote_commitment.into(); + let vote_commitment = Commitment::from_raw(bytes); + + SimpleCertificate { + data, + vote_commitment, + view_number: self.view_number, + signatures: self.signatures.clone(), + _pd: PhantomData, + } + } +} + +impl TimeoutCertificate { + /// Convert a `DaCertificate` into a `DaCertificate2` + pub fn to_vsc2(self) -> TimeoutCertificate2 { + let data = TimeoutData2 { + view: self.data.view, + epoch: TYPES::Epoch::new(0), + }; + + let bytes: [u8; 32] = self.vote_commitment.into(); + let vote_commitment = Commitment::from_raw(bytes); + + SimpleCertificate { + data, + vote_commitment, + view_number: self.view_number, + signatures: self.signatures.clone(), + _pd: PhantomData, + } + } +} + +impl TimeoutCertificate2 { + /// Convert a `DaCertificate` into a `DaCertificate2` + pub fn to_vsc(self) -> TimeoutCertificate { + let data = TimeoutData { + view: self.data.view, + }; + + let bytes: [u8; 32] = self.vote_commitment.into(); + let vote_commitment = Commitment::from_raw(bytes); + + SimpleCertificate { + data, + vote_commitment, + view_number: self.view_number, + signatures: self.signatures.clone(), + _pd: PhantomData, + } + } +} + /// Type alias for a `QuorumCertificate`, which is a `SimpleCertificate` over `QuorumData` pub type QuorumCertificate = SimpleCertificate, SuccessThreshold>; /// Type alias for a `QuorumCertificate2`, which is a `SimpleCertificate` over `QuorumData2` pub type QuorumCertificate2 = SimpleCertificate, SuccessThreshold>; -/// Type alias for a DA certificate over `DaData` +/// Type alias for a `DaCertificate`, which is a `SimpleCertificate` over `DaData` pub type DaCertificate = SimpleCertificate; +/// Type alias for a `DaCertificate2`, which is a `SimpleCertificate` over `DaData2` +pub type DaCertificate2 = SimpleCertificate, SuccessThreshold>; /// Type alias for a Timeout certificate over a view number pub type TimeoutCertificate = SimpleCertificate, SuccessThreshold>; +/// Type alias for a `TimeoutCertificate2`, which is a `SimpleCertificate` over `TimeoutData2` +pub type TimeoutCertificate2 = + SimpleCertificate, SuccessThreshold>; /// Type alias for a `ViewSyncPreCommit` certificate over a view number -pub type ViewSyncPreCommitCertificate2 = +pub type ViewSyncPreCommitCertificate = SimpleCertificate, OneHonestThreshold>; +/// Type alias for a `ViewSyncPreCommitCertificate2`, which is a `SimpleCertificate` over `ViewSyncPreCommitData2` +pub type ViewSyncPreCommitCertificate2 = + SimpleCertificate, OneHonestThreshold>; /// Type alias for a `ViewSyncCommit` certificate over a view number -pub type ViewSyncCommitCertificate2 = +pub type ViewSyncCommitCertificate = SimpleCertificate, SuccessThreshold>; +/// Type alias for a `ViewSyncCommitCertificate2`, which is a `SimpleCertificate` over `ViewSyncCommitData2` +pub type ViewSyncCommitCertificate2 = + SimpleCertificate, SuccessThreshold>; /// Type alias for a `ViewSyncFinalize` certificate over a view number -pub type ViewSyncFinalizeCertificate2 = +pub type ViewSyncFinalizeCertificate = SimpleCertificate, SuccessThreshold>; +/// Type alias for a `ViewSyncFinalizeCertificate2`, which is a `SimpleCertificate` over `ViewSyncFinalizeData2` +pub type ViewSyncFinalizeCertificate2 = + SimpleCertificate, SuccessThreshold>; /// Type alias for a `UpgradeCertificate`, which is a `SimpleCertificate` of `UpgradeProposalData` pub type UpgradeCertificate = SimpleCertificate, UpgradeThreshold>; diff --git a/crates/types/src/simple_vote.rs b/crates/types/src/simple_vote.rs index 138f730fb9..ef69520785 100644 --- a/crates/types/src/simple_vote.rs +++ b/crates/types/src/simple_vote.rs @@ -17,7 +17,7 @@ use crate::{ data::{Leaf, Leaf2}, message::UpgradeLock, traits::{ - node_implementation::{NodeType, Versions}, + node_implementation::{ConsensusTime, NodeType, Versions}, signature_key::SignatureKey, }, vid::VidCommitment, @@ -40,6 +40,8 @@ pub struct QuorumData { pub struct QuorumData2 { /// Commitment to the leaf pub leaf_commit: Commitment>, + /// Epoch number + pub epoch: TYPES::Epoch, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)] /// Data used for a DA vote. @@ -48,12 +50,27 @@ pub struct DaData { pub payload_commit: VidCommitment, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)] +/// Data used for a DA vote. +pub struct DaData2 { + /// Commitment to a block payload + pub payload_commit: VidCommitment, + /// Epoch number + pub epoch: TYPES::Epoch, +} +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)] /// Data used for a timeout vote. pub struct TimeoutData { /// View the timeout is for pub view: TYPES::View, } - +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)] +/// Data used for a timeout vote. +pub struct TimeoutData2 { + /// View the timeout is for + pub view: TYPES::View, + /// Epoch number + pub epoch: TYPES::Epoch, +} #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)] /// Data used for a Pre Commit vote. pub struct ViewSyncPreCommitData { @@ -63,6 +80,16 @@ pub struct ViewSyncPreCommitData { pub round: TYPES::View, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)] +/// Data used for a Pre Commit vote. +pub struct ViewSyncPreCommitData2 { + /// The relay this vote is intended for + pub relay: u64, + /// The view number we are trying to sync on + pub round: TYPES::View, + /// Epoch number + pub epoch: TYPES::Epoch, +} +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)] /// Data used for a Commit vote. pub struct ViewSyncCommitData { /// The relay this vote is intended for @@ -71,6 +98,16 @@ pub struct ViewSyncCommitData { pub round: TYPES::View, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)] +/// Data used for a Commit vote. +pub struct ViewSyncCommitData2 { + /// The relay this vote is intended for + pub relay: u64, + /// The view number we are trying to sync on + pub round: TYPES::View, + /// Epoch number + pub epoch: TYPES::Epoch, +} +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)] /// Data used for a Finalize vote. pub struct ViewSyncFinalizeData { /// The relay this vote is intended for @@ -79,6 +116,16 @@ pub struct ViewSyncFinalizeData { pub round: TYPES::View, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)] +/// Data used for a Finalize vote. +pub struct ViewSyncFinalizeData2 { + /// The relay this vote is intended for + pub relay: u64, + /// The view number we are trying to sync on + pub round: TYPES::View, + /// Epoch number + pub epoch: TYPES::Epoch, +} +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)] /// Data used for a Upgrade vote. pub struct UpgradeProposalData { /// The old version that we are upgrading from. @@ -96,6 +143,18 @@ pub struct UpgradeProposalData { pub new_version_first_view: TYPES::View, } +/// Data used for an upgrade once epochs are implemented +pub struct UpgradeData2 { + /// The old version that we are upgrading from + pub old_version: Version, + /// The new version that we are upgrading to + pub new_version: Version, + /// A unique identifier for the specific protocol being voted on + pub hash: Vec, + /// The first epoch in which the upgrade will be in effect + pub epoch: TYPES::Epoch, +} + /// Marker trait for data or commitments that can be voted on. /// Only structs in this file can implement voteable. This is enforced with the `Sealed` trait /// Sealing this trait prevents creating new vote types outside this file. @@ -120,9 +179,13 @@ mod sealed { impl QuorumMarker for QuorumData {} impl QuorumMarker for QuorumData2 {} impl QuorumMarker for TimeoutData {} +impl QuorumMarker for TimeoutData2 {} impl QuorumMarker for ViewSyncPreCommitData {} impl QuorumMarker for ViewSyncCommitData {} impl QuorumMarker for ViewSyncFinalizeData {} +impl QuorumMarker for ViewSyncPreCommitData2 {} +impl QuorumMarker for ViewSyncCommitData2 {} +impl QuorumMarker for ViewSyncFinalizeData2 {} impl QuorumMarker for UpgradeProposalData {} /// A simple yes vote over some votable type. @@ -272,9 +335,18 @@ impl Committable for QuorumData { impl Committable for QuorumData2 { fn commit(&self) -> Commitment { - committable::RawCommitmentBuilder::new("Quorum data") - .var_size_bytes(self.leaf_commit.as_ref()) - .finalize() + let QuorumData2 { leaf_commit, epoch } = self; + + if **epoch == 0 { + committable::RawCommitmentBuilder::new("Quorum data") + .var_size_bytes(leaf_commit.as_ref()) + .finalize() + } else { + committable::RawCommitmentBuilder::new("Quorum data") + .var_size_bytes(leaf_commit.as_ref()) + .u64(**epoch) + .finalize() + } } } @@ -286,6 +358,23 @@ impl Committable for TimeoutData { } } +impl Committable for TimeoutData2 { + fn commit(&self) -> Commitment { + let TimeoutData2 { view, epoch } = self; + + if **epoch == 0 { + committable::RawCommitmentBuilder::new("Timeout data") + .u64(**view) + .finalize() + } else { + committable::RawCommitmentBuilder::new("Timeout data") + .u64(**view) + .u64(**epoch) + .finalize() + } + } +} + impl Committable for DaData { fn commit(&self) -> Commitment { committable::RawCommitmentBuilder::new("DA data") @@ -294,6 +383,25 @@ impl Committable for DaData { } } +impl Committable for DaData2 { + fn commit(&self) -> Commitment { + let DaData2 { + payload_commit, + epoch, + } = self; + if **epoch == 0 { + committable::RawCommitmentBuilder::new("DA data") + .var_size_bytes(payload_commit.as_ref()) + .finalize() + } else { + committable::RawCommitmentBuilder::new("DA data") + .var_size_bytes(payload_commit.as_ref()) + .u64(**epoch) + .finalize() + } + } +} + impl Committable for UpgradeProposalData { fn commit(&self) -> Commitment { let builder = committable::RawCommitmentBuilder::new("Upgrade data"); @@ -310,6 +418,26 @@ impl Committable for UpgradeProposalData { } } +impl Committable for UpgradeData2 { + fn commit(&self) -> Commitment { + let UpgradeData2 { + old_version, + new_version, + hash, + epoch, + } = self; + + committable::RawCommitmentBuilder::new("Upgrade data") + .u16(old_version.minor) + .u16(old_version.major) + .u16(new_version.minor) + .u16(new_version.major) + .var_size_bytes(hash.as_slice()) + .u64(**epoch) + .finalize() + } +} + /// This implements commit for all the types which contain a view and relay public key. fn view_and_relay_commit( view: TYPES::View, @@ -326,17 +454,78 @@ impl Committable for ViewSyncPreCommitData { } } +impl Committable for ViewSyncPreCommitData2 { + fn commit(&self) -> Commitment { + let ViewSyncPreCommitData2 { + relay, + round, + epoch, + } = self; + + if **epoch == 0 { + view_and_relay_commit::(*round, *relay, "View Sync Precommit") + } else { + committable::RawCommitmentBuilder::new("View Sync Precommit") + .u64(*relay) + .u64(**round) + .u64(**epoch) + .finalize() + } + } +} + impl Committable for ViewSyncFinalizeData { fn commit(&self) -> Commitment { view_and_relay_commit::(self.round, self.relay, "View Sync Finalize") } } + +impl Committable for ViewSyncFinalizeData2 { + fn commit(&self) -> Commitment { + let ViewSyncFinalizeData2 { + relay, + round, + epoch, + } = self; + + if **epoch == 0 { + view_and_relay_commit::(*round, *relay, "View Sync Finalize") + } else { + committable::RawCommitmentBuilder::new("View Sync Finalize") + .u64(*relay) + .u64(**round) + .u64(**epoch) + .finalize() + } + } +} + impl Committable for ViewSyncCommitData { fn commit(&self) -> Commitment { view_and_relay_commit::(self.round, self.relay, "View Sync Commit") } } +impl Committable for ViewSyncCommitData2 { + fn commit(&self) -> Commitment { + let ViewSyncCommitData2 { + relay, + round, + epoch, + } = self; + + if **epoch == 0 { + view_and_relay_commit::(*round, *relay, "View Sync Commit") + } else { + committable::RawCommitmentBuilder::new("View Sync Commit") + .u64(*relay) + .u64(**round) + .u64(**epoch) + .finalize() + } + } +} + // impl votable for all the data types in this file sealed marker should ensure nothing is accidently // implemented for structs that aren't "voteable" impl Voteable @@ -352,6 +541,7 @@ impl QuorumVote { let signature = self.signature; let data = QuorumData2 { leaf_commit: Commitment::from_raw(bytes), + epoch: TYPES::Epoch::new(0), }; let view_number = self.view_number; @@ -382,21 +572,73 @@ impl QuorumVote2 { } } +impl DaVote { + /// Convert a `QuorumVote` to a `QuorumVote2` + pub fn to_vote2(self) -> DaVote2 { + let signature = self.signature; + let data = DaData2 { + payload_commit: self.data.payload_commit, + epoch: TYPES::Epoch::new(0), + }; + let view_number = self.view_number; + + SimpleVote { + signature, + data, + view_number, + } + } +} + +impl DaVote2 { + /// Convert a `QuorumVote2` to a `QuorumVote` + pub fn to_vote(self) -> DaVote { + let signature = self.signature; + let data = DaData { + payload_commit: self.data.payload_commit, + }; + let view_number = self.view_number; + + SimpleVote { + signature, + data, + view_number, + } + } +} + // Type aliases for simple use of all the main votes. We should never see `SimpleVote` outside this file + /// Quorum vote Alias pub type QuorumVote = SimpleVote>; // Type aliases for simple use of all the main votes. We should never see `SimpleVote` outside this file /// Quorum vote Alias pub type QuorumVote2 = SimpleVote>; + /// DA vote type alias pub type DaVote = SimpleVote; +/// DA vote 2 type alias +pub type DaVote2 = SimpleVote>; + /// Timeout Vote type alias pub type TimeoutVote = SimpleVote>; -/// View Sync Commit Vote type alias -pub type ViewSyncCommitVote = SimpleVote>; +/// Timeout Vote 2 type alias +pub type TimeoutVote2 = SimpleVote>; + /// View Sync Pre Commit Vote type alias pub type ViewSyncPreCommitVote = SimpleVote>; +/// View Sync Pre Commit Vote 2 type alias +pub type ViewSyncPreCommitVote2 = SimpleVote>; /// View Sync Finalize Vote type alias pub type ViewSyncFinalizeVote = SimpleVote>; +/// View Sync Finalize Vote 2 type alias +pub type ViewSyncFinalizeVote2 = SimpleVote>; +/// View Sync Commit Vote type alias +pub type ViewSyncCommitVote = SimpleVote>; +/// View Sync Commit Vote 2 type alias +pub type ViewSyncCommitVote2 = SimpleVote>; + /// Upgrade proposal vote pub type UpgradeVote = SimpleVote>; +/// Upgrade proposal 2 vote +pub type UpgradeVote2 = SimpleVote>; diff --git a/crates/types/src/traits/storage.rs b/crates/types/src/traits/storage.rs index 7782ef0101..a0e226cdbd 100644 --- a/crates/types/src/traits/storage.rs +++ b/crates/types/src/traits/storage.rs @@ -18,7 +18,9 @@ use jf_vid::VidScheme; use super::node_implementation::NodeType; use crate::{ consensus::{CommitmentMap, View}, - data::{DaProposal, Leaf, Leaf2, QuorumProposal, QuorumProposal2, VidDisperseShare}, + data::{ + DaProposal, DaProposal2, Leaf, Leaf2, QuorumProposal, QuorumProposal2, VidDisperseShare, + }, event::HotShotAction, message::Proposal, simple_certificate::{QuorumCertificate, QuorumCertificate2, UpgradeCertificate}, @@ -36,6 +38,12 @@ pub trait Storage: Send + Sync + Clone { proposal: &Proposal>, vid_commit: ::Commit, ) -> Result<()>; + /// Add a proposal to the stored DA proposals. + async fn append_da2( + &self, + proposal: &Proposal>, + vid_commit: ::Commit, + ) -> Result<()>; /// Add a proposal we sent to the store async fn append_proposal( &self,