Skip to content

Commit afc3964

Browse files
committed
temp
1 parent b9d3b52 commit afc3964

File tree

6 files changed

+120
-52
lines changed

6 files changed

+120
-52
lines changed

core/src/consensus/sortition/mod.rs

+53-4
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,65 @@ use primitives::H256;
2727
use vrf::openssl::Error as VrfError;
2828

2929
use self::vrf_sortition::{PriorityInfo, VRFSortition};
30+
use crate::consensus::{Height, View};
3031

31-
pub type VRFSeed = H256;
32+
#[derive(Debug, PartialEq, Clone, Copy, RlpEncodable, RlpDecodable)]
33+
pub struct VRFSeed(H256);
3234

33-
#[derive(Debug, PartialEq, RlpEncodable, RlpDecodable)]
35+
impl AsRef<[u8]> for VRFSeed {
36+
#[inline]
37+
fn as_ref(&self) -> &[u8] {
38+
&self.0
39+
}
40+
}
41+
42+
impl ::core::ops::Deref for VRFSeed {
43+
type Target = [u8];
44+
45+
#[inline]
46+
fn deref(&self) -> &[u8] {
47+
&self.0
48+
}
49+
}
50+
51+
impl From<H256> for VRFSeed {
52+
fn from(hash: H256) -> Self {
53+
VRFSeed(hash)
54+
}
55+
}
56+
57+
#[cfg(test)]
58+
impl From<u64> for VRFSeed {
59+
fn from(mut value: u64) -> Self {
60+
let hash: H256 = value.into();
61+
hash.into()
62+
}
63+
}
64+
65+
impl VRFSeed {
66+
pub fn zero() -> Self {
67+
VRFSeed(H256::zero())
68+
}
69+
}
70+
71+
impl VRFSeed {
72+
/// Calculate the common message used in next seed generation.
73+
pub fn generate_next_msg(&self, height: Height, view: View) -> Vec<u8> {
74+
[&self[..], &height.to_be_bytes(), &view.to_be_bytes()].concat()
75+
}
76+
}
77+
78+
#[derive(Debug, PartialEq, Clone, RlpEncodable, RlpDecodable)]
3479
pub struct PriorityMessage {
3580
pub seed: VRFSeed,
3681
pub info: PriorityInfo,
3782
}
3883

3984
impl PriorityMessage {
85+
pub fn seed(&self) -> VRFSeed {
86+
self.seed
87+
}
88+
4089
pub fn verify(
4190
&self,
4291
signer_public: &Public,
@@ -80,7 +129,7 @@ mod priority_message_tests {
80129
sortition_scheme.create_highest_priority_info(seed, priv_key, voting_power).unwrap().unwrap();
81130

82131
let priority_message = PriorityMessage {
83-
seed,
132+
seed: seed.into(),
84133
info: priority_info,
85134
};
86135
assert!(priority_message.verify(&pub_key, voting_power, &sortition_scheme).unwrap());
@@ -104,7 +153,7 @@ mod priority_message_tests {
104153
sortition_scheme.create_highest_priority_info(seed, priv_key, voting_power).unwrap().unwrap();
105154

106155
let priority_message = PriorityMessage {
107-
seed,
156+
seed: seed.into(),
108157
info: priority_info,
109158
};
110159
rlp_encode_and_decode_test!(priority_message);

core/src/consensus/tendermint/message.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ pub enum TendermintMessage {
113113
ProposalBlock {
114114
signature: SchnorrSignature,
115115
view: View,
116+
priority: PriorityMessage,
116117
message: Bytes,
117118
},
118119
StepState {
@@ -149,12 +150,15 @@ impl Encodable for TendermintMessage {
149150
TendermintMessage::ProposalBlock {
150151
signature,
151152
view,
153+
priority,
152154
message,
153155
} => {
154156
s.begin_list(4);
155157
s.append(&MESSAGE_ID_PROPOSAL_BLOCK);
156158
s.append(signature);
157159
s.append(view);
160+
// FIXME: Consider compressing
161+
s.append(priority);
158162

159163
let compressed = {
160164
// TODO: Cache the Encoder object
@@ -238,15 +242,16 @@ impl Decodable for TendermintMessage {
238242
}
239243
MESSAGE_ID_PROPOSAL_BLOCK => {
240244
let item_count = rlp.item_count()?;
241-
if item_count != 4 {
245+
if item_count != 5 {
242246
return Err(DecoderError::RlpIncorrectListLen {
243247
got: item_count,
244-
expected: 4,
248+
expected: 5,
245249
})
246250
}
247251
let signature = rlp.at(1)?;
248252
let view = rlp.at(2)?;
249-
let compressed_message: Vec<u8> = rlp.val_at(3)?;
253+
let priority = rlp.at(3)?;
254+
let compressed_message: Vec<u8> = rlp.val_at(4)?;
250255
let uncompressed_message = {
251256
// TODO: Cache the Decoder object
252257
let mut snappy_decoder = snap::Decoder::new();
@@ -259,6 +264,7 @@ impl Decodable for TendermintMessage {
259264
TendermintMessage::ProposalBlock {
260265
signature: signature.as_val()?,
261266
view: view.as_val()?,
267+
priority: priority.as_val()?,
262268
message: uncompressed_message,
263269
}
264270
}

core/src/consensus/tendermint/network.rs

+2
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ impl NetworkExtension<Event> for TendermintExtension {
296296
Ok(TendermintMessage::ProposalBlock {
297297
signature,
298298
view,
299+
priority,
299300
message,
300301
}) => {
301302
let (result, receiver) = crossbeam::bounded(1);
@@ -304,6 +305,7 @@ impl NetworkExtension<Event> for TendermintExtension {
304305
signature,
305306
view,
306307
message: message.clone(),
308+
priority: priority.clone(),
307309
result,
308310
})
309311
.unwrap();

core/src/consensus/tendermint/params.rs

+6
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ impl From<cjson::scheme::TendermintParams> for TendermintParams {
4343
TendermintParams {
4444
validators: Arc::new(DynamicValidator::new(p.validators)),
4545
timeouts: TimeoutParams {
46+
promote: p.timeout_promote.map_or(dt.promote, to_duration),
47+
promote_delta: p.timeout_promote_delta.map_or(dt.promote_delta, to_duration),
4648
propose: p.timeout_propose.map_or(dt.propose, to_duration),
4749
propose_delta: p.timeout_propose_delta.map_or(dt.propose_delta, to_duration),
4850
prevote: p.timeout_prevote.map_or(dt.prevote, to_duration),
@@ -75,6 +77,8 @@ pub struct TimeGapParams {
7577
/// Base timeout of each step in ms.
7678
#[derive(Debug, Copy, Clone)]
7779
pub struct TimeoutParams {
80+
pub promote: Duration,
81+
pub promote_delta: Duration,
7882
pub propose: Duration,
7983
pub propose_delta: Duration,
8084
pub prevote: Duration,
@@ -87,6 +91,8 @@ pub struct TimeoutParams {
8791
impl Default for TimeoutParams {
8892
fn default() -> Self {
8993
TimeoutParams {
94+
promote: Duration::from_millis(2000),
95+
promote_delta: Duration::from_millis(500),
9096
propose: Duration::from_millis(1000),
9197
propose_delta: Duration::from_millis(500),
9298
prevote: Duration::from_millis(1000),

core/src/consensus/tendermint/worker.rs

+46-45
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use std::thread::{Builder, JoinHandle};
2222
use std::time::{Duration, SystemTime, UNIX_EPOCH};
2323

2424
use ccrypto::sha256;
25-
use ckey::{public_to_address, verify_schnorr, Address, SchnorrSignature};
25+
use ckey::{public_to_address, verify_schnorr, Address, Public, SchnorrSignature};
2626
use cnetwork::{EventSender, NodeId};
2727
use crossbeam_channel as crossbeam;
2828
use ctypes::transaction::{Action, Transaction};
@@ -32,7 +32,7 @@ use parking_lot::RwLock;
3232
use primitives::{u256_from_u128, Bytes, U256};
3333
use rlp::{Encodable, Rlp};
3434
use vrf::openssl::{CipherSuite, ECVRF};
35-
use vrf::VRF;
35+
use vrf::{openssl::Error as VRFError, VRF};
3636

3737
use super::super::BitSet;
3838
use super::backup::{backup, restore, BackupView};
@@ -160,6 +160,7 @@ pub enum Event {
160160
ProposalBlock {
161161
signature: SchnorrSignature,
162162
view: View,
163+
priority: PriorityMessage,
163164
message: Bytes,
164165
result: crossbeam::Sender<Option<Arc<dyn ConsensusClient>>>,
165166
},
@@ -344,22 +345,14 @@ impl Worker {
344345
inner.restore();
345346
result.send(()).unwrap();
346347
}
347-
Ok(Event::Priority {
348-
round,
349-
signer_idx,
350-
message,
351-
result,
352-
}) => {
353-
inner.on_priority_message(round, signer_idx, message);
354-
result.send(()).unwrap();
355-
}
356348
Ok(Event::ProposalBlock {
357349
signature,
358350
view,
351+
priority,
359352
message,
360353
result,
361354
}) => {
362-
let client = inner.on_proposal_message(signature, view, message);
355+
let client = inner.on_proposal_message(signature, view, priority, message);
363356
result.send(client).unwrap();
364357
}
365358
Ok(Event::StepState {
@@ -435,11 +428,12 @@ impl Worker {
435428
current_seed: &VRFSeed,
436429
prev_seed: &VRFSeed,
437430
prev_round: &SortitionRound,
431+
signer_pubkey: &Public,
438432
prev_proof: &[u8],
439-
) -> Result<(), Error> {
433+
) -> Result<bool, VRFError> {
440434
let vrf_inst = self.sortition_scheme.vrf_inst.write();
441-
let message = [&prev_seed[..], &prev_round.height.to_be_bytes(), &prev_round.view.to_be_bytes()].concat();
442-
Ok(())
435+
let message = prev_seed.generate_next_msg(prev_round.height, prev_round.view);
436+
vrf_inst.verify(signer_pubkey, prev_proof, &message).map(|expected_seed| expected_seed == current_seed.to_vec())
443437
}
444438

445439
fn fetch_vrf_seed(&self, block_hash: BlockHash) -> Option<VRFSeed> {
@@ -448,6 +442,12 @@ impl Worker {
448442
Some(TendermintSealView::new(&block_seal).vrf_seed().unwrap())
449443
}
450444

445+
fn fetch_vrf_seed_proof(&self, block_hash: BlockHash) -> Option<Vec<u8>> {
446+
let block_header = self.client().block_header(&block_hash.into())?;
447+
let block_seal = block_header.seal();
448+
Some(TendermintSealView::new(&block_seal).vrf_seed_proof().unwrap())
449+
}
450+
451451
fn prev_vrf_seed(&self) -> VRFSeed {
452452
let parent_header =
453453
self.prev_block_header_of_height(self.height).expect("Height is increased when previous block is imported");
@@ -1260,8 +1260,7 @@ impl Worker {
12601260
parent_seal_view.parent_block_finalized_view().map_err(|_| BlockError::InvalidSeal)?;
12611261
let current_vrf_proof = current_seal_view.vrf_seed_proof().map_err(|_| BlockError::InvalidSeal)?;
12621262

1263-
let message =
1264-
[&parent_vrf_seed[..], &parent.number().to_be_bytes(), &parent_fianlized_view.to_be_bytes()].concat();
1263+
let message = parent_vrf_seed.generate_next_msg(parent.number(), parent_fianlized_view);
12651264

12661265
let current_vrf_seed =
12671266
TendermintSealView::new(&current_seal).vrf_seed().map_err(|_| BlockError::InvalidSeal)?;
@@ -1843,40 +1842,15 @@ impl Worker {
18431842
result.send(message.rlp_bytes().into_vec()).unwrap();
18441843
}
18451844

1846-
//FIXME: Log errors
1847-
fn on_priority_message(&mut self, round: SortitionRound, signer_idx: usize, message: PriorityMessage) {
1848-
if let Some(c) = self.client.upgrade() {
1849-
let height = round.height;
1850-
let view = round.view;
1851-
if let Some(parent_hash) = c.block_hash(&BlockId::Number(height - 1)) {
1852-
let signer_public = self.validators.get(&parent_hash, signer_idx);
1853-
//FIXME: Do not recalculate seed values with heavy VRF operations.
1854-
//FIXME: store block_seed into each block.
1855-
let concatenated = [height.to_be_bytes(), view.to_be_bytes()].concat();
1856-
let expected_seed =
1857-
self.signer.vrf_hash(sha256(concatenated), &mut self.sortition_scheme.vrf_inst.write());
1858-
//FIXME: Handle errors
1859-
let voting_power = self
1860-
.validators
1861-
.normalized_voting_power(&parent_hash, signer_idx, self.sortition_scheme.total_power)
1862-
.unwrap();
1863-
match expected_seed.map(|seed| seed == message.seed.to_vec()) {
1864-
Ok(true) => match message.verify(&signer_public, voting_power, &self.sortition_scheme) {
1865-
Ok(true) => {}
1866-
_ => return,
1867-
},
1868-
_ => return,
1869-
};
1870-
1871-
self.sortition_infos.insert(&message, signer_idx, round);
1872-
}
1873-
}
1845+
fn get_voting_power(&self, block_hash: &BlockHash, signer_idx: usize) -> u64 {
1846+
self.validators.normalized_voting_power(block_hash, signer_idx, self.sortition_scheme.total_power).unwrap()
18741847
}
18751848

18761849
fn on_proposal_message(
18771850
&mut self,
18781851
signature: SchnorrSignature,
18791852
proposed_view: View,
1853+
priority: PriorityMessage,
18801854
bytes: Bytes,
18811855
) -> Option<Arc<dyn ConsensusClient>> {
18821856
let c = self.client.upgrade()?;
@@ -1935,6 +1909,33 @@ impl Worker {
19351909
_ => {}
19361910
}
19371911

1912+
// priority verification block
1913+
{
1914+
if let (Some(parent_seed), Some(parent_seed_proof)) =
1915+
(self.fetch_vrf_seed(*parent_hash), self.fetch_vrf_seed_proof(*parent_hash))
1916+
{
1917+
self.verify_vrf_seed(
1918+
&priority.seed(),
1919+
&parent_seed,
1920+
&SortitionRound {
1921+
height: self.height - 1,
1922+
view: self.finalized_view_of_previous_block,
1923+
},
1924+
&signer_public,
1925+
&parent_seed_proof,
1926+
);
1927+
1928+
let voting_power = self.get_voting_power(&parent_hash, message.signer_index());
1929+
match priority.verify(&signer_public, voting_power, &self.sortition_scheme) {
1930+
Ok(true) => {}
1931+
_ => {
1932+
cwarn!(ENGINE, "Proposal verification failed");
1933+
return None
1934+
}
1935+
}
1936+
}
1937+
}
1938+
19381939
if self.votes.is_old_or_known(&message) {
19391940
cdebug!(ENGINE, "Proposal is already known");
19401941
return None

json/src/scheme/tendermint.rs

+4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ use crate::uint::Uint;
2626
pub struct TendermintParams {
2727
/// Valid validators.
2828
pub validators: Vec<Public>,
29+
/// Promote step timeout in milliseconds.
30+
pub timeout_promote: Option<Uint>,
31+
/// Promote step timeout delta in milliseconds.
32+
pub timeout_promote_delta: Option<Uint>,
2933
/// Propose step timeout in milliseconds.
3034
pub timeout_propose: Option<Uint>,
3135
/// Propose step timeout delta in milliseconds.

0 commit comments

Comments
 (0)