Skip to content

Commit

Permalink
add upgrade cert to leaf + cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
ss-es committed Mar 27, 2024
1 parent 59b9bb1 commit c1d01d3
Show file tree
Hide file tree
Showing 10 changed files with 137 additions and 170 deletions.
2 changes: 1 addition & 1 deletion crates/example-types/src/block_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ impl<TYPES: NodeType<BlockHeader = Self, BlockPayload = TestBlockPayload>> Block
payload_commitment: VidCommitment,
_metadata: <TYPES::BlockPayload as BlockPayload>::Metadata,
) -> Self {
let parent = &parent_leaf.block_header;
let parent = parent_leaf.get_block_header();

let mut timestamp = OffsetDateTime::now_utc().unix_timestamp() as u64;
if timestamp < parent.timestamp {
Expand Down
2 changes: 1 addition & 1 deletion crates/hotshot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>> SystemContext<TYPES, I> {
let validated_state = match initializer.validated_state {
Some(state) => state,
None => Arc::new(TYPES::ValidatedState::from_header(
&anchored_leaf.block_header,
anchored_leaf.get_block_header(),
)),
};

Expand Down
104 changes: 46 additions & 58 deletions crates/task-impls/src/consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,13 +195,12 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>, A: ConsensusApi<TYPES, I> +
};
let parent_commitment = parent.commit();

let leaf: Leaf<_> = Leaf {
view_number: view,
justify_qc: proposal.justify_qc.clone(),
parent_commitment,
block_header: proposal.block_header.clone(),
block_payload: None,
};
let proposed_leaf = Leaf::from_quorum_proposal(proposal);

if proposed_leaf.get_parent_commitment() != parent_commitment {
info!("Quorum proposal's parent commitment does not match expected parent commitment!");
return false;
}

// Validate the DAC.
let message = if cert.is_valid_cert(self.committee_membership.as_ref()) {
Expand All @@ -215,7 +214,7 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>, A: ConsensusApi<TYPES, I> +
}
if let Ok(vote) = QuorumVote::<TYPES>::create_signed_vote(
QuorumData {
leaf_commit: leaf.commit(),
leaf_commit: proposed_leaf.commit(),
},
view,
&self.public_key,
Expand Down Expand Up @@ -501,7 +500,7 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>, A: ConsensusApi<TYPES, I> +
{
Some(leaf) => {
if let (Some(state), _) =
consensus.get_state_and_delta(leaf.view_number)
consensus.get_state_and_delta(leaf.get_view_number())
{
Some((leaf, state.clone()))
} else {
Expand Down Expand Up @@ -539,13 +538,8 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>, A: ConsensusApi<TYPES, I> +
"Proposal's parent missing from storage with commitment: {:?}",
justify_qc.get_data().leaf_commit
);
let leaf = Leaf {
view_number: view,
justify_qc: justify_qc.clone(),
parent_commitment: justify_qc.get_data().leaf_commit,
block_header: proposal.data.block_header.clone(),
block_payload: None,
};
let leaf = Leaf::from_proposal(proposal);

let state = Arc::new(
<TYPES::ValidatedState as ValidatedState<TYPES>>::from_header(
&proposal.data.block_header,
Expand Down Expand Up @@ -626,20 +620,20 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>, A: ConsensusApi<TYPES, I> +
let state = Arc::new(validated_state);
let delta = Arc::new(state_delta);
let parent_commitment = parent_leaf.commit();
let leaf: Leaf<_> = Leaf {
view_number: view,
justify_qc: justify_qc.clone(),
parent_commitment,
block_header: proposal.data.block_header.clone(),
block_payload: None,
};
let leaf_commitment = leaf.commit();

let proposed_leaf = Leaf::from_quorum_proposal(&proposal.data);

if proposed_leaf.get_parent_commitment() != parent_commitment {
info!("Quorum proposal's parent commitment does not match expected parent commitment!");
return;
}

// Validate the signature. This should also catch if the leaf_commitment does not equal our calculated parent commitment
if !view_leader_key.validate(&proposal.signature, leaf_commitment.as_ref()) {
if !view_leader_key.validate(&proposal.signature, proposed_leaf.commit().as_ref()) {
error!(?proposal.signature, "Could not verify proposal.");
return;
}

// Create a positive vote if either liveness or safety check
// passes.

Expand All @@ -655,7 +649,7 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>, A: ConsensusApi<TYPES, I> +
|leaf, _, _| {
// if leaf view no == locked view no then we're done, report success by
// returning true
leaf.view_number != consensus.locked_view
leaf.get_view_number() != consensus.locked_view
},
);
let safety_check = outcome.is_ok();
Expand Down Expand Up @@ -703,7 +697,7 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>, A: ConsensusApi<TYPES, I> +
let mut leafs_decided = Vec::new();
let mut included_txns = HashSet::new();
let old_anchor_view = consensus.last_decided_view;
let parent_view = leaf.justify_qc.get_view_number();
let parent_view = proposed_leaf.get_justify_qc().get_view_number();
let mut current_chain_length = 0usize;
if parent_view + 1 == view {
current_chain_length += 1;
Expand All @@ -713,17 +707,17 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>, A: ConsensusApi<TYPES, I> +
true,
|leaf, state, delta| {
if !new_decide_reached {
if last_view_number_visited == leaf.view_number + 1 {
last_view_number_visited = leaf.view_number;
if last_view_number_visited == leaf.get_view_number() + 1 {
last_view_number_visited = leaf.get_view_number();
current_chain_length += 1;
if current_chain_length == 2 {
new_locked_view = leaf.view_number;
new_locked_view = leaf.get_view_number();
new_commit_reached = true;
// The next leaf in the chain, if there is one, is decided, so this
// leaf's justify_qc would become the QC for the decided chain.
new_decide_qc = Some(leaf.justify_qc.clone());
new_decide_qc = Some(leaf.get_justify_qc().clone());
} else if current_chain_length == 3 {
new_anchor_view = leaf.view_number;
new_anchor_view = leaf.get_view_number();
new_decide_reached = true;
}
} else {
Expand All @@ -734,7 +728,7 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>, A: ConsensusApi<TYPES, I> +
// starting from the first iteration with a three chain, e.g. right after the else if case nested in the if case above
if new_decide_reached {
let mut leaf = leaf.clone();
if leaf.view_number == new_anchor_view {
if leaf.get_view_number() == new_anchor_view {
consensus
.metrics
.last_synced_block_height
Expand Down Expand Up @@ -768,7 +762,7 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>, A: ConsensusApi<TYPES, I> +

leaf_views.push(LeafInfo::new(leaf.clone(), state.clone(), delta.clone(), vid));
leafs_decided.push(leaf.clone());
if let Some(ref payload) = leaf.block_payload {
if let Some(ref payload) = leaf.get_block_payload() {
for txn in payload
.transaction_commitments(leaf.get_block_header().metadata())
{
Expand Down Expand Up @@ -801,13 +795,13 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>, A: ConsensusApi<TYPES, I> +
view,
View {
view_inner: ViewInner::Leaf {
leaf: leaf.commit(),
leaf: proposed_leaf.commit(),
state: state.clone(),
delta: Some(delta.clone()),
},
},
);
consensus.saved_leaves.insert(leaf.commit(), leaf.clone());
consensus.saved_leaves.insert(proposed_leaf.commit(), proposed_leaf.clone());

if let Err(e) = self
.storage
Expand Down Expand Up @@ -1339,7 +1333,7 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>, A: ConsensusApi<TYPES, I> +
error!("Failed to find high QC of parent.");
return false;
};
if leaf.view_number == consensus.last_decided_view {
if leaf.get_view_number() == consensus.last_decided_view {
reached_decided = true;
}

Expand All @@ -1353,10 +1347,10 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>, A: ConsensusApi<TYPES, I> +
if !reached_decided {
debug!("We have not reached decide from view {:?}", self.cur_view);
while let Some(next_parent_leaf) = consensus.saved_leaves.get(&next_parent_hash) {
if next_parent_leaf.view_number <= consensus.last_decided_view {
if next_parent_leaf.get_view_number() <= consensus.last_decided_view {
break;
}
next_parent_hash = next_parent_leaf.parent_commitment;
next_parent_hash = next_parent_leaf.get_parent_commitment();
}
debug!("updated saved leaves");
// TODO do some sort of sanity check on the view number that it matches decided
Expand All @@ -1371,21 +1365,6 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>, A: ConsensusApi<TYPES, I> +
commit_and_metadata.metadata.clone(),
)
.await;
let leaf = Leaf {
view_number: view,
justify_qc: consensus.high_qc.clone(),
parent_commitment: parent_leaf.commit(),
block_header: block_header.clone(),
block_payload: None,
};

let Ok(signature) =
TYPES::SignatureKey::sign(&self.private_key, leaf.commit().as_ref())
else {
error!("Failed to sign leaf.commit()!");
return false;
};

let upgrade_cert = if self
.upgrade_cert
.as_ref()
Expand All @@ -1410,11 +1389,20 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>, A: ConsensusApi<TYPES, I> +

// TODO: DA cert is sent as part of the proposal here, we should split this out so we don't have to wait for it.
let proposal = QuorumProposal {
block_header,
view_number: leaf.view_number,
block_header: block_header.clone(),
view_number: view,
justify_qc: consensus.high_qc.clone(),
proposal_certificate,
upgrade_certificate: upgrade_cert,
upgrade_certificate: upgrade_cert.clone(),
};

let new_leaf = Leaf::from_quorum_proposal(&proposal);

let Ok(signature) =
TYPES::SignatureKey::sign(&self.private_key, new_leaf.commit().as_ref())
else {
error!("Failed to sign new_leaf.commit()!");
return false;
};

self.proposal_cert = None;
Expand All @@ -1423,7 +1411,7 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>, A: ConsensusApi<TYPES, I> +
signature,
_pd: PhantomData,
};
debug!("Sending proposal for view {:?}", leaf.view_number);
debug!("Sending proposal for view {:?}", view);

broadcast_event(
Arc::new(HotShotEvent::QuorumProposalSend(
Expand Down
2 changes: 1 addition & 1 deletion crates/task-impls/src/transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ impl<TYPES: NodeType, I: NodeImplementation<TYPES>, A: ConsensusApi<TYPES, I> +
let mut included_txn_size = 0;
let mut included_txn_count = 0;
for leaf in leaf_chain {
if let Some(ref payload) = leaf.block_payload {
if let Some(ref payload) = leaf.get_block_payload() {
for txn in
payload.transaction_commitments(leaf.get_block_header().metadata())
{
Expand Down
2 changes: 1 addition & 1 deletion crates/testing/src/block_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ impl TaskState for SimpleBuilderTask {
HotShotEvent::LeafDecided(leaf_chain) => {
let mut queue = this.transactions.write().await;
for leaf in leaf_chain.iter() {
if let Some(ref payload) = leaf.block_payload {
if let Some(ref payload) = leaf.get_block_payload() {
for txn in payload.transaction_commitments(&()) {
queue.remove(&txn);
}
Expand Down
65 changes: 11 additions & 54 deletions crates/testing/src/task_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ async fn build_quorum_proposal_and_signature(
handle.hotshot.memberships.quorum_membership.total_nodes(),
);
let mut parent_state = Arc::new(
<TestValidatedState as ValidatedState<TestTypes>>::from_header(&parent_leaf.block_header),
<TestValidatedState as ValidatedState<TestTypes>>::from_header(parent_leaf.get_block_header()),
);
let block_header = TestBlockHeader::new(
&*parent_state,
Expand All @@ -250,24 +250,18 @@ async fn build_quorum_proposal_and_signature(
(),
)
.await;
// current leaf that can be re-assigned everytime when entering a new view
let mut leaf = Leaf {
view_number: ViewNumber::new(1),
justify_qc: consensus.high_qc.clone(),
parent_commitment: parent_leaf.commit(),
block_header: block_header.clone(),
block_payload: None,
};

let mut signature = <BLSPubKey as SignatureKey>::sign(private_key, leaf.commit().as_ref())
.expect("Failed to sign leaf commitment!");
let mut proposal = QuorumProposal::<TestTypes> {
block_header: block_header.clone(),
view_number: ViewNumber::new(1),
justify_qc: QuorumCertificate::genesis(),
upgrade_certificate: None,
proposal_certificate: None,
};
// current leaf that can be re-assigned everytime when entering a new view
let mut leaf = Leaf::from_quorum_proposal(&proposal);

let mut signature = <BLSPubKey as SignatureKey>::sign(private_key, leaf.commit().as_ref())
.expect("Failed to sign leaf commitment!");

// Only view 2 is tested, higher views are not tested
for cur_view in 2..=view {
Expand Down Expand Up @@ -307,24 +301,17 @@ async fn build_quorum_proposal_and_signature(
private_key,
);
// create a new leaf for the current view
let parent_leaf = leaf.clone();
let leaf_new_view = Leaf {
view_number: ViewNumber::new(cur_view),
justify_qc: created_qc.clone(),
parent_commitment: parent_leaf.commit(),
block_header: block_header.clone(),
block_payload: None,
};
let signature_new_view =
<BLSPubKey as SignatureKey>::sign(private_key, leaf_new_view.commit().as_ref())
.expect("Failed to sign leaf commitment!");
let proposal_new_view = QuorumProposal::<TestTypes> {
block_header: block_header.clone(),
view_number: ViewNumber::new(cur_view),
justify_qc: created_qc,
upgrade_certificate: None,
proposal_certificate: None,
};
let leaf_new_view = Leaf::from_quorum_proposal(&proposal_new_view);
let signature_new_view =
<BLSPubKey as SignatureKey>::sign(private_key, leaf_new_view.commit().as_ref())
.expect("Failed to sign leaf commitment!");
proposal = proposal_new_view;
signature = signature_new_view;
leaf = leaf_new_view;
Expand Down Expand Up @@ -443,39 +430,9 @@ pub async fn build_vote(
handle: &SystemContextHandle<TestTypes, MemoryImpl>,
proposal: QuorumProposal<TestTypes>,
) -> GeneralConsensusMessage<TestTypes> {
let consensus_lock = handle.get_consensus();
let consensus = consensus_lock.read().await;

let justify_qc = proposal.justify_qc.clone();
let view = ViewNumber::new(*proposal.view_number);
let parent = if justify_qc.is_genesis {
let Some(genesis_view) = consensus.validated_state_map.get(&ViewNumber::new(0)) else {
panic!("Couldn't find genesis view in state map.");
};
let Some(leaf) = genesis_view.get_leaf_commitment() else {
panic!("Genesis view points to a view without a leaf");
};
let Some(leaf) = consensus.saved_leaves.get(&leaf) else {
panic!("Failed to find genesis leaf.");
};
leaf.clone()
} else {
consensus
.saved_leaves
.get(&justify_qc.get_data().leaf_commit)
.cloned()
.unwrap()
};

let parent_commitment = parent.commit();

let leaf: Leaf<_> = Leaf {
view_number: view,
justify_qc: proposal.justify_qc.clone(),
parent_commitment,
block_header: proposal.block_header,
block_payload: None,
};
let leaf: Leaf<_> = Leaf::from_quorum_proposal(&proposal);
let vote = QuorumVote::<TestTypes>::create_signed_vote(
QuorumData {
leaf_commit: leaf.commit(),
Expand Down
Loading

0 comments on commit c1d01d3

Please sign in to comment.