Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Refactor VoteCollector #4101

Merged
merged 53 commits into from
Jan 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
f5c769e
dir
Dec 13, 2016
89b118d
simple validator list
Dec 13, 2016
e8bca5f
stub validator contract
Dec 13, 2016
dea819f
make the engine hold Weak<Client> instead of IoChannel
Dec 13, 2016
a831786
validator set factory
Dec 13, 2016
1b18472
register weak client with ValidatorContract
Dec 13, 2016
9087ed6
Merge branch 'check-updates' into validator-lookup
Dec 13, 2016
f62733a
check chain security
Dec 13, 2016
4de9be7
Merge branch 'check-updates' into validator-lookup
Dec 13, 2016
afa1279
add address array to generator
Dec 14, 2016
9d408e2
register provider contract
Dec 14, 2016
03099ee
update validator set on notify
Dec 14, 2016
c65e413
add validator contract spec
Dec 14, 2016
133fb62
simple list test
Dec 14, 2016
350219c
split update and contract test
Dec 14, 2016
e400398
contract change
Dec 15, 2016
70334f6
Merge branch 'check-updates' into validator-lookup
Dec 15, 2016
f9404f6
use client in tendermint
Dec 16, 2016
4a1c996
Merge branch 'check-updates' into validator-lookup
Dec 16, 2016
53ce079
Merge branch 'master' into validator-lookup
Dec 19, 2016
16ddb88
fix deadlock
Dec 19, 2016
474463e
step duration in params
Dec 19, 2016
1bb0e60
adapt tendermint tests
Dec 19, 2016
bc270c1
Merge branch 'master' into validator-lookup
Dec 19, 2016
d8e2139
add storage fields to test spec
Dec 19, 2016
881c26e
constructor spec
Dec 20, 2016
3ad9b73
execute under wrong address
Dec 20, 2016
96104e5
create under correct address
Dec 21, 2016
d4329b1
revert
Dec 21, 2016
1954472
Merge branch 'spec-constructor' into validator-lookup
Dec 21, 2016
bc4421a
validator contract constructor
Dec 21, 2016
ad6f3fd
move genesis block lookup
Dec 21, 2016
13e757e
Merge branch 'spec-constructor' into validator-lookup
Dec 21, 2016
c3e0653
Merge branch 'master' into validator-lookup
Dec 21, 2016
674bba6
add removal ability to contract
Dec 21, 2016
314e0cd
validator contract adding validators
Dec 21, 2016
bf262fc
fix basic authority
Dec 21, 2016
56fac53
validator changing test
Dec 21, 2016
bf7e056
more docs
Dec 21, 2016
b2ada8d
update sync tests
Dec 21, 2016
ff8f9b8
remove env_logger
Dec 21, 2016
9d68740
another env_logger
Dec 21, 2016
b7996fa
cameltoe
Dec 22, 2016
4e669c8
Merge branch 'master' into validator-lookup
Dec 23, 2016
38ea976
Merge branch 'master' into validator-lookup
Jan 3, 2017
68b9a3d
hold EngineClient instead of Client
Jan 5, 2017
70cd023
return error on misbehaviour
Jan 9, 2017
cfb6fc5
nicer return
Jan 9, 2017
f2efa34
sprinkle docs
Jan 10, 2017
9c71adb
Merge branch 'master' into report-misbehaviour
Jan 10, 2017
0166ec9
Merge branch 'master' into report-misbehaviour
Jan 10, 2017
1ebea42
Merge branch 'master' into report-misbehaviour
Jan 11, 2017
10acd83
Merge branch 'master' into report-misbehaviour
Jan 11, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 72 additions & 75 deletions ethcore/src/engines/tendermint/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,35 @@ use header::Header;
use rlp::*;
use ethkey::{recover, public_to_address};

#[derive(Debug, PartialEq, Eq, Clone)]
/// Message transmitted between consensus participants.
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub struct ConsensusMessage {
pub vote_step: VoteStep,
pub block_hash: Option<BlockHash>,
pub signature: H520,
}

/// Complete step of the consensus process.
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub struct VoteStep {
pub height: Height,
pub round: Round,
pub step: Step,
pub block_hash: Option<BlockHash>,
}

impl VoteStep {
pub fn new(height: Height, round: Round, step: Step) -> Self {
VoteStep { height: height, round: round, step: step }
}

pub fn is_height(&self, height: Height) -> bool {
self.height == height
}

pub fn is_round(&self, height: Height, round: Round) -> bool {
self.height == height && self.round == round
}
}

fn consensus_round(header: &Header) -> Result<Round, ::rlp::DecoderError> {
let round_rlp = header.seal().get(0).expect("seal passed basic verification; seal has 3 fields; qed");
Expand All @@ -42,53 +62,29 @@ impl ConsensusMessage {
pub fn new(signature: H520, height: Height, round: Round, step: Step, block_hash: Option<BlockHash>) -> Self {
ConsensusMessage {
signature: signature,
height: height,
round: round,
step: step,
block_hash: block_hash,
vote_step: VoteStep::new(height, round, step),
}
}

pub fn new_proposal(header: &Header) -> Result<Self, ::rlp::DecoderError> {
Ok(ConsensusMessage {
vote_step: VoteStep::new(header.number() as Height, consensus_round(header)?, Step::Propose),
signature: UntrustedRlp::new(header.seal().get(1).expect("seal passed basic verification; seal has 3 fields; qed").as_slice()).as_val()?,
height: header.number() as Height,
round: consensus_round(header)?,
step: Step::Propose,
block_hash: Some(header.bare_hash()),
})
}

pub fn new_commit(proposal: &ConsensusMessage, signature: H520) -> Self {
let mut vote_step = proposal.vote_step.clone();
vote_step.step = Step::Precommit;
ConsensusMessage {
signature: signature,
height: proposal.height,
round: proposal.round,
step: Step::Precommit,
vote_step: vote_step,
block_hash: proposal.block_hash,
signature: signature,
}
}

pub fn is_height(&self, height: Height) -> bool {
self.height == height
}

pub fn is_round(&self, height: Height, round: Round) -> bool {
self.height == height && self.round == round
}

pub fn is_step(&self, height: Height, round: Round, step: Step) -> bool {
self.height == height && self.round == round && self.step == step
}

pub fn is_block_hash(&self, h: Height, r: Round, s: Step, block_hash: Option<BlockHash>) -> bool {
self.height == h && self.round == r && self.step == s && self.block_hash == block_hash
}

pub fn is_aligned(&self, m: &ConsensusMessage) -> bool {
self.is_block_hash(m.height, m.round, m.step, m.block_hash)
}

pub fn verify(&self) -> Result<Address, Error> {
let full_rlp = ::rlp::encode(self);
let block_info = Rlp::new(&full_rlp).at(1);
Expand All @@ -97,16 +93,30 @@ impl ConsensusMessage {
}

pub fn precommit_hash(&self) -> H256 {
message_info_rlp(self.height, self.round, Step::Precommit, self.block_hash).sha3()
let mut vote_step = self.vote_step.clone();
vote_step.step = Step::Precommit;
message_info_rlp(&vote_step, self.block_hash).sha3()
}
}

impl PartialOrd for ConsensusMessage {
fn partial_cmp(&self, m: &ConsensusMessage) -> Option<Ordering> {
impl PartialOrd for VoteStep {
fn partial_cmp(&self, m: &VoteStep) -> Option<Ordering> {
Some(self.cmp(m))
}
}

impl Ord for VoteStep {
fn cmp(&self, m: &VoteStep) -> Ordering {
if self.height != m.height {
self.height.cmp(&m.height)
} else if self.round != m.round {
self.round.cmp(&m.round)
} else {
self.step.number().cmp(&m.step.number())
}
}
}

impl Step {
fn number(&self) -> u8 {
match *self {
Expand All @@ -118,20 +128,6 @@ impl Step {
}
}

impl Ord for ConsensusMessage {
fn cmp(&self, m: &ConsensusMessage) -> Ordering {
if self.height != m.height {
self.height.cmp(&m.height)
} else if self.round != m.round {
self.round.cmp(&m.round)
} else if self.step != m.step {
self.step.number().cmp(&m.step.number())
} else {
self.signature.cmp(&m.signature)
}
}
}

impl Decodable for Step {
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
match decoder.as_rlp().as_val()? {
Expand All @@ -149,42 +145,39 @@ impl Encodable for Step {
}
}

/// (signature, height, round, step, block_hash)
/// (signature, (height, round, step, block_hash))
impl Decodable for ConsensusMessage {
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
let rlp = decoder.as_rlp();
let m = rlp.at(1)?;
let block_message: H256 = m.val_at(3)?;
Ok(ConsensusMessage {
signature: rlp.val_at(0)?,
height: m.val_at(0)?,
round: m.val_at(1)?,
step: m.val_at(2)?,
vote_step: VoteStep::new(m.val_at(0)?, m.val_at(1)?, m.val_at(2)?),
block_hash: match block_message.is_zero() {
true => None,
false => Some(block_message),
}
},
signature: rlp.val_at(0)?,
})
}
}

impl Encodable for ConsensusMessage {
fn rlp_append(&self, s: &mut RlpStream) {
let info = message_info_rlp(self.height, self.round, self.step, self.block_hash);
let info = message_info_rlp(&self.vote_step, self.block_hash);
s.begin_list(2)
.append(&self.signature)
.append_raw(&info, 1);
}
}

pub fn message_info_rlp(height: Height, round: Round, step: Step, block_hash: Option<BlockHash>) -> Bytes {
pub fn message_info_rlp(vote_step: &VoteStep, block_hash: Option<BlockHash>) -> Bytes {
// TODO: figure out whats wrong with nested list encoding
let mut s = RlpStream::new_list(5);
s.append(&height).append(&round).append(&step).append(&block_hash.unwrap_or_else(H256::zero));
s.append(&vote_step.height).append(&vote_step.round).append(&vote_step.step).append(&block_hash.unwrap_or_else(H256::zero));
s.out()
}


pub fn message_full_rlp(signature: &H520, vote_info: &Bytes) -> Bytes {
let mut s = RlpStream::new_list(2);
s.append(signature).append_raw(vote_info, 1);
Expand All @@ -204,21 +197,25 @@ mod tests {
#[test]
fn encode_decode() {
let message = ConsensusMessage {
signature: H520::default(),
height: 10,
round: 123,
step: Step::Precommit,
signature: H520::default(),
vote_step: VoteStep {
height: 10,
round: 123,
step: Step::Precommit,
},
block_hash: Some("1".sha3())
};
let raw_rlp = ::rlp::encode(&message).to_vec();
let rlp = Rlp::new(&raw_rlp);
assert_eq!(message, rlp.as_val());

let message = ConsensusMessage {
signature: H520::default(),
height: 1314,
round: 0,
step: Step::Prevote,
signature: H520::default(),
vote_step: VoteStep {
height: 1314,
round: 0,
step: Step::Prevote,
},
block_hash: None
};
let raw_rlp = ::rlp::encode(&message);
Expand All @@ -232,7 +229,7 @@ mod tests {
let addr = tap.insert_account(Secret::from_slice(&"0".sha3()).unwrap(), "0").unwrap();
tap.unlock_account_permanently(addr, "0".into()).unwrap();

let mi = message_info_rlp(123, 2, Step::Precommit, Some(H256::default()));
let mi = message_info_rlp(&VoteStep::new(123, 2, Step::Precommit), Some(H256::default()));

let raw_rlp = message_full_rlp(&tap.sign(addr, None, mi.sha3()).unwrap().into(), &mi);

Expand All @@ -255,9 +252,11 @@ mod tests {
message,
ConsensusMessage {
signature: Default::default(),
height: 0,
round: 0,
step: Step::Propose,
vote_step: VoteStep {
height: 0,
round: 0,
step: Step::Propose,
},
block_hash: Some(header.bare_hash())
}
);
Expand All @@ -268,12 +267,10 @@ mod tests {
let header = Header::default();
let pro = ConsensusMessage {
signature: Default::default(),
height: 0,
round: 0,
step: Step::Propose,
vote_step: VoteStep::new(0, 0, Step::Propose),
block_hash: Some(header.bare_hash())
};
let pre = message_info_rlp(0, 0, Step::Precommit, Some(header.bare_hash()));
let pre = message_info_rlp(&VoteStep::new(0, 0, Step::Precommit), Some(header.bare_hash()));

assert_eq!(pro.precommit_hash(), pre.sha3());
}
Expand Down
Loading