Skip to content
This repository was archived by the owner on Dec 26, 2024. It is now read-only.

Commit 4038a34

Browse files
feat(consensus): update consensus so that it runs with voting (#2189)
Currently the context is hard coded with 4 validators, so at least 3 must vote in favor.
1 parent 985a257 commit 4038a34

File tree

3 files changed

+89
-25
lines changed

3 files changed

+89
-25
lines changed

crates/papyrus_protobuf/src/consensus.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,12 @@ pub enum ConsensusMessage {
2929
Proposal(Proposal),
3030
Vote(Vote),
3131
}
32+
33+
impl ConsensusMessage {
34+
pub fn height(&self) -> u64 {
35+
match self {
36+
ConsensusMessage::Proposal(proposal) => proposal.height,
37+
ConsensusMessage::Vote(vote) => vote.height,
38+
}
39+
}
40+
}

crates/sequencing/papyrus_consensus/src/lib.rs

Lines changed: 72 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,69 @@ pub mod types;
2727

2828
use futures::StreamExt;
2929

30+
#[instrument(skip(context, validator_id, network_receiver, cached_messages), level = "info")]
31+
#[allow(missing_docs)]
32+
async fn run_height<BlockT: ConsensusBlock>(
33+
context: Arc<dyn ConsensusContext<Block = BlockT>>,
34+
height: BlockNumber,
35+
validator_id: ValidatorId,
36+
network_receiver: &mut SubscriberReceiver<ConsensusMessage>,
37+
cached_messages: &mut Vec<ConsensusMessage>,
38+
) -> Result<BlockT, ConsensusError>
39+
where
40+
ProposalWrapper:
41+
Into<(ProposalInit, mpsc::Receiver<BlockT::ProposalChunk>, oneshot::Receiver<BlockHash>)>,
42+
{
43+
let mut shc = SingleHeightConsensus::new(height, context, validator_id).await;
44+
45+
if let Some(decision) = shc.start().await? {
46+
return Ok(decision);
47+
}
48+
49+
let mut current_height_messages = Vec::new();
50+
for msg in std::mem::take(cached_messages) {
51+
match height.0.cmp(&msg.height()) {
52+
std::cmp::Ordering::Less => cached_messages.push(msg),
53+
std::cmp::Ordering::Equal => current_height_messages.push(msg),
54+
std::cmp::Ordering::Greater => {}
55+
}
56+
}
57+
58+
loop {
59+
let message = current_height_messages.pop().unwrap_or(
60+
// TODO(matan): Handle parsing failures and utilize ReportCallback.
61+
network_receiver
62+
.next()
63+
.await
64+
.expect("Network receiver closed unexpectedly")
65+
.0
66+
.expect("Failed to parse consensus message"),
67+
);
68+
69+
if message.height() != height.0 {
70+
debug!("Received a message for a different height. {:?}", message);
71+
if message.height() > height.0 {
72+
cached_messages.push(message);
73+
}
74+
continue;
75+
}
76+
77+
let maybe_block = match message {
78+
ConsensusMessage::Proposal(proposal) => {
79+
// Special case due to fake streaming.
80+
let (proposal_init, content_receiver, fin_receiver) =
81+
ProposalWrapper(proposal).into();
82+
shc.handle_proposal(proposal_init, content_receiver, fin_receiver).await?
83+
}
84+
_ => shc.handle_message(message).await?,
85+
};
86+
87+
if let Some(block) = maybe_block {
88+
return Ok(block);
89+
}
90+
}
91+
}
92+
3093
// TODO(dvir): add test for this.
3194
#[instrument(skip(context, start_height, network_receiver), level = "info")]
3295
#[allow(missing_docs)]
@@ -41,30 +104,16 @@ where
41104
Into<(ProposalInit, mpsc::Receiver<BlockT::ProposalChunk>, oneshot::Receiver<BlockHash>)>,
42105
{
43106
let mut current_height = start_height;
107+
let mut future_messages = Vec::new();
44108
loop {
45-
debug!("Starting consensus for height {current_height}");
46-
let mut shc =
47-
SingleHeightConsensus::new(current_height, context.clone(), validator_id).await;
48-
49-
let block = if let Some(block) = shc.start().await? {
50-
block
51-
} else {
52-
info!("Validator flow height {current_height}");
53-
let ConsensusMessage::Proposal(proposal) = network_receiver
54-
.next()
55-
.await
56-
.expect("Failed to receive a message from network")
57-
.0
58-
.expect("Network receiver closed unexpectedly")
59-
else {
60-
todo!("Handle votes");
61-
};
62-
let (proposal_init, content_receiver, fin_receiver) = ProposalWrapper(proposal).into();
63-
64-
shc.handle_proposal(proposal_init, content_receiver, fin_receiver)
65-
.await?
66-
.expect("Failed to handle proposal")
67-
};
109+
let block = run_height(
110+
Arc::clone(&context),
111+
current_height,
112+
validator_id,
113+
&mut network_receiver,
114+
&mut future_messages,
115+
)
116+
.await?;
68117

69118
info!(
70119
"Finished consensus for height: {current_height}. Agreed on block with id: {:x}",

crates/sequencing/papyrus_consensus/src/papyrus_consensus_context.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ impl ConsensusContext for PapyrusConsensusContext {
158158
}
159159

160160
async fn validators(&self, _height: BlockNumber) -> Vec<ValidatorId> {
161-
vec![0u8.into(), 1u8.into()]
161+
vec![0u8.into(), 1u8.into(), 2u8.into(), 3u8.into()]
162162
}
163163

164164
fn proposer(&self, _validators: &[ValidatorId], height: BlockNumber) -> ValidatorId {
@@ -193,7 +193,13 @@ impl ConsensusContext for PapyrusConsensusContext {
193193
transactions,
194194
block_hash,
195195
};
196-
debug!("Sending proposal: {proposal:?}");
196+
debug!(
197+
"Sending proposal: height={:?} id={:?} num_txs={} block_hash={:?}",
198+
proposal.height,
199+
proposal.proposer,
200+
proposal.transactions.len(),
201+
proposal.block_hash
202+
);
197203

198204
broadcast_sender
199205
.lock()

0 commit comments

Comments
 (0)