Skip to content

Commit

Permalink
Merge pull request #2528 from EspressoSystems/feat/get-undecided-state
Browse files Browse the repository at this point in the history
[VALIDATED_STATE] Add method to get undecided state
  • Loading branch information
jbearer authored Feb 7, 2024
2 parents 63d118c + 905ad36 commit 171e22a
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 24 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,13 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}

- name: Download executables AMD
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: binaries-amd64-${{ matrix.just_variants }}
path: target/amd64/debug/examples

- name: Download executables ARM
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: binaries-aarch64-${{ matrix.just_variants }}
path: target/arm64/debug/examples
Expand Down
17 changes: 14 additions & 3 deletions crates/hotshot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>> SystemContext<TYPES, I> {

// insert genesis (or latest block) to state map
let mut validated_state_map = BTreeMap::default();
let validated_state = TYPES::ValidatedState::genesis(&instance_state);
let validated_state = Arc::new(TYPES::ValidatedState::genesis(&instance_state));
validated_state_map.insert(
anchored_leaf.get_view_number(),
View {
Expand Down Expand Up @@ -345,11 +345,11 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>> SystemContext<TYPES, I> {
.map(|guard| guard.get_decided_leaf())
}

/// Returns a copy of the last decided validated state.
/// Returns the last decided validated state.
///
/// # Panics
/// Panics if internal state for consensus is inconsistent
pub async fn get_decided_state(&self) -> TYPES::ValidatedState {
pub async fn get_decided_state(&self) -> Arc<TYPES::ValidatedState> {
self.inner
.consensus
.read()
Expand All @@ -358,6 +358,17 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>> SystemContext<TYPES, I> {
.clone()
}

/// Get the validated state from a given `view`.
///
/// Returns the requested state, if the [`SystemContext`] is tracking this view. Consensus
/// tracks views that have not yet been decided but could be in the future. This function may
/// return [`None`] if the requested view has already been decided (but see
/// [`get_decided_state`](Self::get_decided_state)) or if there is no path for the requested
/// view to ever be decided.
pub async fn get_state(&self, view: TYPES::Time) -> Option<Arc<TYPES::ValidatedState>> {
self.inner.consensus.read().await.get_state(view).cloned()
}

/// Initializes a new [`SystemContext`] and does the work of setting up all the background tasks
///
/// Assumes networking implementation is already primed.
Expand Down
13 changes: 12 additions & 1 deletion crates/hotshot/src/types/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,21 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES> + 'static> SystemContextHandl
///
/// # Panics
/// If the internal consensus is in an inconsistent state.
pub async fn get_decided_state(&self) -> TYPES::ValidatedState {
pub async fn get_decided_state(&self) -> Arc<TYPES::ValidatedState> {
self.hotshot.get_decided_state().await
}

/// Get the validated state from a given `view`.
///
/// Returns the requested state, if the [`SystemContext`] is tracking this view. Consensus
/// tracks views that have not yet been decided but could be in the future. This function may
/// return [`None`] if the requested view has already been decided (but see
/// [`get_decided_state`](Self::get_decided_state)) or if there is no path for the requested
/// view to ever be decided.
pub async fn get_state(&self, view: TYPES::Time) -> Option<Arc<TYPES::ValidatedState>> {
self.hotshot.get_state(view).await
}

/// Get the last decided leaf of the [`SystemContext`] instance.
///
/// # Panics
Expand Down
5 changes: 3 additions & 2 deletions crates/task-impls/src/consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -538,9 +538,9 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>, A: ConsensusApi<TYPES, I> +
block_payload: None,
proposer_id: sender,
};
let state = <TYPES::ValidatedState as ValidatedState>::from_header(
let state = Arc::new(<TYPES::ValidatedState as ValidatedState>::from_header(
&proposal.data.block_header,
);
));

consensus.validated_state_map.insert(
view,
Expand Down Expand Up @@ -600,6 +600,7 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>, A: ConsensusApi<TYPES, I> +
error!("Block header doesn't extend the proposal",);
return;
};
let state = Arc::new(state);
let parent_commitment = parent.commit();
let leaf: Leaf<_> = Leaf {
view_number: view,
Expand Down
17 changes: 10 additions & 7 deletions crates/testing/src/task_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ use hotshot_types::vote::Certificate;
use hotshot_types::vote::Vote;

use serde::Serialize;
use std::{fmt::Debug, hash::Hash};
use std::{fmt::Debug, hash::Hash, sync::Arc};

/// create the [`SystemContextHandle`] from a node id
/// # Panics
Expand Down Expand Up @@ -238,10 +238,11 @@ async fn build_quorum_proposal_and_signature(
.quorum_membership
.total_nodes(),
);
let mut parent_state =
<TestValidatedState as ValidatedState>::from_header(&parent_leaf.block_header);
let mut parent_state = Arc::new(<TestValidatedState as ValidatedState>::from_header(
&parent_leaf.block_header,
));
let block_header = TestBlockHeader::new(
&parent_state,
&*parent_state,
&TestInstanceState {},
&parent_leaf.block_header,
payload_commitment,
Expand Down Expand Up @@ -269,9 +270,11 @@ async fn build_quorum_proposal_and_signature(

// Only view 2 is tested, higher views are not tested
for cur_view in 2..=view {
let state_new_view = parent_state
.validate_and_apply_header(&TestInstanceState {}, &block_header, &block_header)
.unwrap();
let state_new_view = Arc::new(
parent_state
.validate_and_apply_header(&TestInstanceState {}, &block_header, &block_header)
.unwrap(),
);
// save states for the previous view to pass all the qc checks
// In the long term, we want to get rid of this, do not manually update consensus state
consensus.validated_state_map.insert(
Expand Down
4 changes: 2 additions & 2 deletions crates/types/src/consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ impl<TYPES: NodeType> Consensus<TYPES> {

/// Gets the validated state with the given view number, if in the state map.
#[must_use]
pub fn get_state(&self, view_number: TYPES::Time) -> Option<&TYPES::ValidatedState> {
pub fn get_state(&self, view_number: TYPES::Time) -> Option<&Arc<TYPES::ValidatedState>> {
match self.validated_state_map.get(&view_number) {
Some(view) => view.get_state(),
None => None,
Expand All @@ -354,7 +354,7 @@ impl<TYPES: NodeType> Consensus<TYPES> {
/// If the last decided view's state does not exist in the state map, which should never
/// happen.
#[must_use]
pub fn get_decided_state(&self) -> &TYPES::ValidatedState {
pub fn get_decided_state(&self) -> &Arc<TYPES::ValidatedState> {
let decided_view_num = self.last_decided_view;
self.get_state(decided_view_num)
.expect("Decided state not found! Consensus internally inconsistent")
Expand Down
2 changes: 1 addition & 1 deletion crates/types/src/traits/states.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub trait InstanceState: Clone + Debug + Send + Sync {}
/// produce a new state, with the modifications from the block applied
/// ([`validate_and_apply_header`](`ValidatedState::validate_and_apply_header))
pub trait ValidatedState:
Serialize + DeserializeOwned + Clone + Debug + Default + Hash + PartialEq + Eq + Send + Sync
Serialize + DeserializeOwned + Debug + Default + Hash + PartialEq + Eq + Send + Sync
{
/// The error type for this particular type of ledger state
type Error: Error + Debug + Send + Sync;
Expand Down
16 changes: 10 additions & 6 deletions crates/types/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use commit::Commitment;
use digest::OutputSizeUser;
use sha2::Digest;
use std::ops::Deref;
use std::{ops::Deref, sync::Arc};
use tagged_base64::tagged;
use typenum::Unsigned;

Expand All @@ -27,17 +27,21 @@ pub enum ViewInner<TYPES: NodeType> {
/// Undecided view
Leaf {
/// Proposed leaf
leaf: Commitment<Leaf<TYPES>>,
leaf: LeafCommitment<TYPES>,
/// Validated state.
state: TYPES::ValidatedState,
state: Arc<TYPES::ValidatedState>,
},
/// Leaf has failed
Failed,
}

/// The hash of a leaf.
pub type LeafCommitment<TYPES> = Commitment<Leaf<TYPES>>;

impl<TYPES: NodeType> ViewInner<TYPES> {
/// Return the underlying undecide leaf view if it exists.
pub fn get_leaf(&self) -> Option<(Commitment<Leaf<TYPES>>, &TYPES::ValidatedState)> {
#[must_use]
pub fn get_leaf(&self) -> Option<(LeafCommitment<TYPES>, &Arc<TYPES::ValidatedState>)> {
if let Self::Leaf { leaf, state } = self {
Some((*leaf, state))
} else {
Expand All @@ -47,7 +51,7 @@ impl<TYPES: NodeType> ViewInner<TYPES> {

/// return the underlying leaf hash if it exists
#[must_use]
pub fn get_leaf_commitment(&self) -> Option<Commitment<Leaf<TYPES>>> {
pub fn get_leaf_commitment(&self) -> Option<LeafCommitment<TYPES>> {
if let Self::Leaf { leaf, .. } = self {
Some(*leaf)
} else {
Expand All @@ -57,7 +61,7 @@ impl<TYPES: NodeType> ViewInner<TYPES> {

/// return the underlying validated state if it exists
#[must_use]
pub fn get_state(&self) -> Option<&TYPES::ValidatedState> {
pub fn get_state(&self) -> Option<&Arc<TYPES::ValidatedState>> {
if let Self::Leaf { state, .. } = self {
Some(state)
} else {
Expand Down

0 comments on commit 171e22a

Please sign in to comment.