Skip to content

Commit

Permalink
3967 QuorumProposalWrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
pls148 committed Jan 16, 2025
1 parent acb217a commit 1a9b798
Show file tree
Hide file tree
Showing 26 changed files with 371 additions and 243 deletions.
33 changes: 25 additions & 8 deletions crates/example-types/src/storage_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ use async_trait::async_trait;
use hotshot_types::{
consensus::CommitmentMap,
data::{
DaProposal, DaProposal2, Leaf, Leaf2, QuorumProposal, QuorumProposal2, VidDisperseShare,
VidDisperseShare2,
DaProposal, DaProposal2, Leaf, Leaf2, QuorumProposal, QuorumProposal2,
QuorumProposalWrapper, VidDisperseShare, VidDisperseShare2,
},
event::HotShotAction,
message::Proposal,
Expand Down Expand Up @@ -50,6 +50,7 @@ pub struct TestStorageState<TYPES: NodeType> {
da2s: HashMap<TYPES::View, Proposal<TYPES, DaProposal2<TYPES>>>,
proposals: BTreeMap<TYPES::View, Proposal<TYPES, QuorumProposal<TYPES>>>,
proposals2: BTreeMap<TYPES::View, Proposal<TYPES, QuorumProposal2<TYPES>>>,
proposals_wrapper: BTreeMap<TYPES::View, Proposal<TYPES, QuorumProposalWrapper<TYPES>>>,
high_qc: Option<hotshot_types::simple_certificate::QuorumCertificate<TYPES>>,
high_qc2: Option<hotshot_types::simple_certificate::QuorumCertificate2<TYPES>>,
next_epoch_high_qc2:
Expand All @@ -67,6 +68,7 @@ impl<TYPES: NodeType> Default for TestStorageState<TYPES> {
da2s: HashMap::new(),
proposals: BTreeMap::new(),
proposals2: BTreeMap::new(),
proposals_wrapper: BTreeMap::new(),
high_qc: None,
next_epoch_high_qc2: None,
high_qc2: None,
Expand Down Expand Up @@ -109,8 +111,8 @@ impl<TYPES: NodeType> TestableDelay for TestStorage<TYPES> {
impl<TYPES: NodeType> TestStorage<TYPES> {
pub async fn proposals_cloned(
&self,
) -> BTreeMap<TYPES::View, Proposal<TYPES, QuorumProposal2<TYPES>>> {
self.inner.read().await.proposals2.clone()
) -> BTreeMap<TYPES::View, Proposal<TYPES, QuorumProposalWrapper<TYPES>>> {
self.inner.read().await.proposals_wrapper.clone()
}

pub async fn high_qc_cloned(&self) -> Option<QuorumCertificate2<TYPES>> {
Expand Down Expand Up @@ -176,7 +178,7 @@ impl<TYPES: NodeType> Storage<TYPES> for TestStorage<TYPES> {
_vid_commit: <VidSchemeType as VidScheme>::Commit,
) -> Result<()> {
if self.should_return_err {
bail!("Failed to append VID proposal to storage");
bail!("Failed to append DA proposal to storage");
}
Self::run_delay_settings_from_config(&self.delay_config).await;
let mut inner = self.inner.write().await;
Expand All @@ -192,7 +194,7 @@ impl<TYPES: NodeType> Storage<TYPES> for TestStorage<TYPES> {
_vid_commit: <VidSchemeType as VidScheme>::Commit,
) -> Result<()> {
if self.should_return_err {
bail!("Failed to append VID proposal to storage");
bail!("Failed to append DA proposal (2) to storage");
}
Self::run_delay_settings_from_config(&self.delay_config).await;
let mut inner = self.inner.write().await;
Expand All @@ -207,7 +209,7 @@ impl<TYPES: NodeType> Storage<TYPES> for TestStorage<TYPES> {
proposal: &Proposal<TYPES, QuorumProposal<TYPES>>,
) -> Result<()> {
if self.should_return_err {
bail!("Failed to append VID proposal to storage");
bail!("Failed to append Quorum proposal (1) to storage");
}
Self::run_delay_settings_from_config(&self.delay_config).await;
let mut inner = self.inner.write().await;
Expand All @@ -222,7 +224,7 @@ impl<TYPES: NodeType> Storage<TYPES> for TestStorage<TYPES> {
proposal: &Proposal<TYPES, QuorumProposal2<TYPES>>,
) -> Result<()> {
if self.should_return_err {
bail!("Failed to append VID proposal to storage");
bail!("Failed to append Quorum proposal (2) to storage");
}
Self::run_delay_settings_from_config(&self.delay_config).await;
let mut inner = self.inner.write().await;
Expand All @@ -232,6 +234,21 @@ impl<TYPES: NodeType> Storage<TYPES> for TestStorage<TYPES> {
Ok(())
}

async fn append_proposal_wrapper(
&self,
proposal: &Proposal<TYPES, QuorumProposalWrapper<TYPES>>,
) -> Result<()> {
if self.should_return_err {
bail!("Failed to append Quorum proposal (wrapped) to storage");
}
Self::run_delay_settings_from_config(&self.delay_config).await;
let mut inner = self.inner.write().await;
inner
.proposals_wrapper
.insert(proposal.data.view_number(), proposal.clone());
Ok(())
}

async fn record_action(
&self,
view: <TYPES as NodeType>::View,
Expand Down
22 changes: 17 additions & 5 deletions crates/hotshot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub mod traits;
pub mod types;

pub mod tasks;
use hotshot_types::data::QuorumProposalWrapper;

/// Contains helper functions for the crate
pub mod helpers;
Expand Down Expand Up @@ -69,7 +70,6 @@ use hotshot_types::{
pub use rand;
use tokio::{spawn, time::sleep};
use tracing::{debug, instrument, trace};
use vbs::version::StaticVersionType;

// -- Rexports
// External
Expand Down Expand Up @@ -237,6 +237,7 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> SystemContext<T
internal_chan,
external_chan,
)
.await
}

/// Creates a new [`Arc<SystemContext>`] with the given configuration options.
Expand All @@ -247,7 +248,7 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> SystemContext<T
/// Use this function if you want to use some preexisting channels and to spin up the tasks
/// and start consensus manually. Mostly useful for tests
#[allow(clippy::too_many_arguments, clippy::type_complexity)]
pub fn new_from_channels(
pub async fn new_from_channels(
public_key: TYPES::SignatureKey,
private_key: <TYPES::SignatureKey as SignatureKey>::PrivateKey,
nonce: u64,
Expand Down Expand Up @@ -294,7 +295,9 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> SystemContext<T

// #3967 REVIEW NOTE: Should this actually be Some()? How do we know?
let epoch = option_epoch_from_block_number::<TYPES>(
V::Base::VERSION >= V::Epochs::VERSION,
upgrade_lock
.epochs_enabled(anchored_leaf.view_number())
.await,
anchored_leaf.height(),
config.epoch_height,
);
Expand Down Expand Up @@ -1015,26 +1018,35 @@ pub struct HotShotInitializer<TYPES: NodeType> {

/// Starting view number that should be equivalent to the view the node shut down with last.
start_view: TYPES::View,

/// Starting epoch number that should be equivalent to the epoch the node shut down with last.
start_epoch: Option<TYPES::Epoch>,

/// The view we last performed an action in. An action is Proposing or voting for
/// Either the quorum or DA.
actioned_view: TYPES::View,

/// Highest QC that was seen, for genesis it's the genesis QC. It should be for a view greater
/// than `inner`s view number for the non genesis case because we must have seen higher QCs
/// to decide on the leaf.
high_qc: QuorumCertificate2<TYPES>,

/// Next epoch highest QC that was seen. This is needed to propose during epoch transition after restart.
next_epoch_high_qc: Option<NextEpochQuorumCertificate2<TYPES>>,

/// Previously decided upgrade certificate; this is necessary if an upgrade has happened and we are not restarting with the new version
decided_upgrade_certificate: Option<UpgradeCertificate<TYPES>>,

/// Undecided leaves that were seen, but not yet decided on. These allow a restarting node
/// to vote and propose right away if they didn't miss anything while down.
undecided_leaves: Vec<Leaf2<TYPES>>,

/// Not yet decided state
undecided_state: BTreeMap<TYPES::View, View<TYPES>>,

/// Proposals we have sent out to provide to others for catchup
saved_proposals: BTreeMap<TYPES::View, Proposal<TYPES, QuorumProposal2<TYPES>>>,
saved_proposals: BTreeMap<TYPES::View, Proposal<TYPES, QuorumProposalWrapper<TYPES>>>,

/// Saved VID shares
saved_vid_shares: Option<VidShares<TYPES>>,
}
Expand Down Expand Up @@ -1083,7 +1095,7 @@ impl<TYPES: NodeType> HotShotInitializer<TYPES> {
start_view: TYPES::View,
start_epoch: Option<TYPES::Epoch>,
actioned_view: TYPES::View,
saved_proposals: BTreeMap<TYPES::View, Proposal<TYPES, QuorumProposal2<TYPES>>>,
saved_proposals: BTreeMap<TYPES::View, Proposal<TYPES, QuorumProposalWrapper<TYPES>>>,
high_qc: QuorumCertificate2<TYPES>,
next_epoch_high_qc: Option<NextEpochQuorumCertificate2<TYPES>>,
decided_upgrade_certificate: Option<UpgradeCertificate<TYPES>>,
Expand Down
5 changes: 2 additions & 3 deletions crates/hotshot/src/types/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use hotshot_task::{
use hotshot_task_impls::{events::HotShotEvent, helpers::broadcast_event};
use hotshot_types::{
consensus::Consensus,
data::{Leaf2, QuorumProposal2},
data::{Leaf2, QuorumProposalWrapper},
error::HotShotError,
message::{Message, MessageKind, Proposal, RecipientList},
request_response::ProposalRequestPayload,
Expand All @@ -31,7 +31,6 @@ use hotshot_types::{
node_implementation::NodeType,
signature_key::SignatureKey,
},
vote::HasViewNumber,
};
use tracing::instrument;

Expand Down Expand Up @@ -141,7 +140,7 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES> + 'static, V: Versions>
&self,
view: TYPES::View,
leaf_commitment: Commitment<Leaf2<TYPES>>,
) -> Result<impl futures::Future<Output = Result<Proposal<TYPES, QuorumProposal2<TYPES>>>>>
) -> Result<impl futures::Future<Output = Result<Proposal<TYPES, QuorumProposalWrapper<TYPES>>>>>
{
// We need to be able to sign this request before submitting it to the network. Compute the
// payload first.
Expand Down
33 changes: 21 additions & 12 deletions crates/task-impls/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use either::Either;
use hotshot_task::task::TaskEvent;
use hotshot_types::{
data::{
DaProposal2, Leaf2, PackedBundle, QuorumProposal2, UpgradeProposal, VidDisperse,
VidDisperseShare2,
DaProposal2, Leaf2, PackedBundle, QuorumProposal2, QuorumProposalWrapper, UpgradeProposal,
VidDisperse, VidDisperseShare2,
},
message::Proposal,
request_response::ProposalRequestPayload,
Expand Down Expand Up @@ -72,7 +72,10 @@ pub enum HotShotEvent<TYPES: NodeType> {
/// Shutdown the task
Shutdown,
/// A quorum proposal has been received from the network; handled by the consensus task
QuorumProposalRecv(Proposal<TYPES, QuorumProposal2<TYPES>>, TYPES::SignatureKey),
QuorumProposalRecv(
Proposal<TYPES, QuorumProposalWrapper<TYPES>>,
TYPES::SignatureKey,
),
/// A quorum vote has been received from the network; handled by the consensus task
QuorumVoteRecv(QuorumVote2<TYPES>),
/// A timeout vote received from the network; handled by consensus task
Expand All @@ -90,7 +93,10 @@ pub enum HotShotEvent<TYPES: NodeType> {
/// A DAC is validated.
DaCertificateValidated(DaCertificate2<TYPES>),
/// Send a quorum proposal to the network; emitted by the leader in the consensus task
QuorumProposalSend(Proposal<TYPES, QuorumProposal2<TYPES>>, TYPES::SignatureKey),
QuorumProposalSend(
Proposal<TYPES, QuorumProposalWrapper<TYPES>>,
TYPES::SignatureKey,
),
/// Send a quorum vote to the next leader; emitted by a replica in the consensus task after seeing a valid quorum proposal
QuorumVoteSend(QuorumVote2<TYPES>),
/// Broadcast a quorum vote to form an eQC; emitted by a replica in the consensus task after seeing a valid quorum proposal
Expand All @@ -101,7 +107,7 @@ pub enum HotShotEvent<TYPES: NodeType> {
/// 2. The proposal has been correctly signed by the leader of the current view
/// 3. The justify QC is valid
/// 4. The proposal passes either liveness or safety check.
QuorumProposalValidated(Proposal<TYPES, QuorumProposal2<TYPES>>, Leaf2<TYPES>),
QuorumProposalValidated(Proposal<TYPES, QuorumProposalWrapper<TYPES>>, Leaf2<TYPES>),
/// A quorum proposal is missing for a view that we need.
QuorumProposalRequestSend(
ProposalRequestPayload<TYPES>,
Expand All @@ -113,9 +119,12 @@ pub enum HotShotEvent<TYPES: NodeType> {
<TYPES::SignatureKey as SignatureKey>::PureAssembledSignatureType,
),
/// A quorum proposal was missing for a view. As the leader, we send a reply to the recipient with their key.
QuorumProposalResponseSend(TYPES::SignatureKey, Proposal<TYPES, QuorumProposal2<TYPES>>),
QuorumProposalResponseSend(
TYPES::SignatureKey,
Proposal<TYPES, QuorumProposalWrapper<TYPES>>,
),
/// A quorum proposal was requested by a node for a view.
QuorumProposalResponseRecv(Proposal<TYPES, QuorumProposal2<TYPES>>),
QuorumProposalResponseRecv(Proposal<TYPES, QuorumProposalWrapper<TYPES>>),
/// 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, DaProposal2<TYPES>>, 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
Expand Down Expand Up @@ -208,7 +217,7 @@ pub enum HotShotEvent<TYPES: NodeType> {
/// 1. The proposal is not for an old view
/// 2. The proposal has been correctly signed by the leader of the current view
/// 3. The justify QC is valid
QuorumProposalPreliminarilyValidated(Proposal<TYPES, QuorumProposal2<TYPES>>),
QuorumProposalPreliminarilyValidated(Proposal<TYPES, QuorumProposalWrapper<TYPES>>),

/// Send a VID request to the network; emitted to on of the members of DA committee.
/// Includes the data request, node's public key and signature as well as public key of DA committee who we want to send to.
Expand Down Expand Up @@ -570,14 +579,14 @@ impl<TYPES: NodeType> Display for HotShotEvent<TYPES> {
write!(
f,
"QuorumProposalResponseSend(view_number={:?})",
proposal.data.view_number
proposal.data.view_number()
)
}
HotShotEvent::QuorumProposalResponseRecv(proposal) => {
write!(
f,
"QuorumProposalResponseRecv(view_number={:?})",
proposal.data.view_number
proposal.data.view_number()
)
}
HotShotEvent::QuorumProposalPreliminarilyValidated(proposal) => {
Expand All @@ -597,14 +606,14 @@ impl<TYPES: NodeType> Display for HotShotEvent<TYPES> {
write!(
f,
"VidResponseSend(view_number={:?}",
proposal.data.view_number
proposal.data.view_number()
)
}
HotShotEvent::VidResponseRecv(_, proposal) => {
write!(
f,
"VidResponseRecv(view_number={:?}",
proposal.data.view_number
proposal.data.view_number()
)
}
HotShotEvent::HighQcRecv(qc, _) => {
Expand Down
Loading

0 comments on commit 1a9b798

Please sign in to comment.