Skip to content

Commit e1a7539

Browse files
committed
Add Commit message in Tendermint
Before this commit, Tendermint extension only requests current height and view's votes. Handling only the current view's message makes code simple. However, there may be a commit before the current view. This creates a liveness problem. After this commit, a node requests a Commit message if some of its peer's height is higher than the node. The commit message is not related to the node's current view. The Commit message fixes the liveness problem.
1 parent 011ca48 commit e1a7539

File tree

3 files changed

+465
-44
lines changed

3 files changed

+465
-44
lines changed

core/src/consensus/tendermint/message.rs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ const MESSAGE_ID_PROPOSAL_BLOCK: u8 = 0x02;
7979
const MESSAGE_ID_STEP_STATE: u8 = 0x03;
8080
const MESSAGE_ID_REQUEST_MESSAGE: u8 = 0x04;
8181
const MESSAGE_ID_REQUEST_PROPOSAL: u8 = 0x05;
82+
const MESSAGE_ID_REQUEST_COMMIT: u8 = 0x06;
83+
const MESSAGE_ID_COMMIT: u8 = 0x07;
8284

8385
#[derive(Debug, PartialEq)]
8486
pub enum TendermintMessage {
@@ -102,6 +104,14 @@ pub enum TendermintMessage {
102104
height: Height,
103105
view: View,
104106
},
107+
RequestCommit {
108+
height: Height,
109+
},
110+
Commit {
111+
height: Height,
112+
block: Bytes,
113+
votes: Vec<ConsensusMessage>,
114+
},
105115
}
106116

107117
impl Encodable for TendermintMessage {
@@ -160,6 +170,24 @@ impl Encodable for TendermintMessage {
160170
s.append(height);
161171
s.append(view);
162172
}
173+
TendermintMessage::RequestCommit {
174+
height,
175+
} => {
176+
s.begin_list(2);
177+
s.append(&MESSAGE_ID_REQUEST_COMMIT);
178+
s.append(height);
179+
}
180+
TendermintMessage::Commit {
181+
height,
182+
block,
183+
votes,
184+
} => {
185+
s.begin_list(4);
186+
s.append(&MESSAGE_ID_COMMIT);
187+
s.append(height);
188+
s.append(block);
189+
s.append_list(votes);
190+
}
163191
}
164192
}
165193
}
@@ -253,6 +281,36 @@ impl Decodable for TendermintMessage {
253281
view,
254282
}
255283
}
284+
MESSAGE_ID_REQUEST_COMMIT => {
285+
let item_count = rlp.item_count()?;
286+
if item_count != 2 {
287+
return Err(DecoderError::RlpIncorrectListLen {
288+
got: item_count,
289+
expected: 2,
290+
})
291+
}
292+
let height = rlp.at(1)?.as_val()?;
293+
TendermintMessage::RequestCommit {
294+
height,
295+
}
296+
}
297+
MESSAGE_ID_COMMIT => {
298+
let item_count = rlp.item_count()?;
299+
if item_count != 4 {
300+
return Err(DecoderError::RlpIncorrectListLen {
301+
got: item_count,
302+
expected: 4,
303+
})
304+
}
305+
let height = rlp.at(1)?.as_val()?;
306+
let block = rlp.at(2)?.as_val()?;
307+
let votes = rlp.at(3)?.as_list()?;
308+
TendermintMessage::Commit {
309+
height,
310+
block,
311+
votes,
312+
}
313+
}
256314
_ => return Err(DecoderError::Custom("Unknown message id detected")),
257315
})
258316
}
@@ -408,6 +466,43 @@ mod tests {
408466
});
409467
}
410468

469+
#[test]
470+
fn encode_and_decode_tendermint_message_6() {
471+
rlp_encode_and_decode_test!(TendermintMessage::RequestCommit {
472+
height: 3,
473+
});
474+
}
475+
476+
#[test]
477+
fn encode_and_decode_tendermint_message_7() {
478+
rlp_encode_and_decode_test!(TendermintMessage::Commit {
479+
height: 3,
480+
block: vec![1u8, 2u8],
481+
votes: vec![
482+
ConsensusMessage {
483+
signature: SchnorrSignature::random(),
484+
signer_index: 0x1234,
485+
on: VoteOn {
486+
step: VoteStep::new(2, 3, Step::Commit),
487+
block_hash: Some(H256::from(
488+
"07feab4c39250abf60b77d7589a5b61fdf409bd837e936376381d19db1e1f050"
489+
)),
490+
},
491+
},
492+
ConsensusMessage {
493+
signature: SchnorrSignature::random(),
494+
signer_index: 0x1235,
495+
on: VoteOn {
496+
step: VoteStep::new(2, 3, Step::Commit),
497+
block_hash: Some(H256::from(
498+
"07feab4c39250abf60b77d7589a5b61fdf409bd837e936376381d19db1e1f050"
499+
)),
500+
},
501+
}
502+
]
503+
});
504+
}
505+
411506
#[test]
412507
fn encode_and_decode_consensus_message_1() {
413508
let message = ConsensusMessage::default();

core/src/consensus/tendermint/network.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,45 @@ impl NetworkExtension<Event> for TendermintExtension {
352352
self.send_votes(token, votes);
353353
}
354354
}
355+
Ok(TendermintMessage::RequestCommit {
356+
height,
357+
}) => {
358+
ctrace!(ENGINE, "Received RequestCommit for {} from {:?}", height, token);
359+
let (result, receiver) = crossbeam::unbounded();
360+
self.inner
361+
.send(worker::Event::RequestCommit {
362+
height,
363+
result,
364+
})
365+
.unwrap();
366+
367+
if let Ok(message) = receiver.recv() {
368+
ctrace!(ENGINE, "Send commit for {} to {:?}", height, token);
369+
self.api.send(token, Arc::new(message));
370+
}
371+
}
372+
Ok(TendermintMessage::Commit {
373+
height,
374+
block,
375+
votes,
376+
}) => {
377+
ctrace!(ENGINE, "Received Commit for {:?} from {:?}", height, token);
378+
let (result, receiver) = crossbeam::unbounded();
379+
self.inner
380+
.send(worker::Event::GetCommit {
381+
height,
382+
block: block.clone(),
383+
votes,
384+
result,
385+
})
386+
.unwrap();
387+
388+
if let Some(c) = receiver.recv().unwrap() {
389+
if let Err(e) = c.import_block(block) {
390+
cinfo!(ENGINE, "Failed to import committed block {:?}", e);
391+
}
392+
}
393+
}
355394
_ => cinfo!(ENGINE, "Invalid message from peer {}", token),
356395
}
357396
}

0 commit comments

Comments
 (0)