diff --git a/vetomint/src/lib.rs b/vetomint/src/lib.rs index f1d89a41..ada62202 100644 --- a/vetomint/src/lib.rs +++ b/vetomint/src/lib.rs @@ -1,3 +1,4 @@ +mod misbehavior; mod progress; mod state; diff --git a/vetomint/src/misbehavior.rs b/vetomint/src/misbehavior.rs new file mode 100644 index 00000000..501a7423 --- /dev/null +++ b/vetomint/src/misbehavior.rs @@ -0,0 +1,131 @@ +use super::*; +use state::*; + +use std::collections::HashMap; + +/// comment for check_double_proposal +pub(crate) fn check_double_proposal( + state: &ConsensusState, + target_round: Round, +) -> Vec { + let proposals: Vec<_> = state + .proposals + .iter() + .filter(|(_, proposal)| proposal.round == target_round) + .map(|(_, proposal)| proposal) + .collect(); + + if proposals.len() > 1 { + let byzantine_signer = proposals[0].proposer; + let (origin_proposal, new_proposal) = (proposals[0].proposal, proposals[1].proposal); + + return vec![ConsensusResponse::ViolationReport { + violator: 0, + misbehavior: Misbehavior::DoubleProposal { + byzantine_node: byzantine_signer, + round: target_round, + proposals: (origin_proposal, new_proposal), + }, + }]; + } + + Vec::new() +} + +/// comment for check_double_prevote +pub(crate) fn check_double_prevote( + state: &ConsensusState, + target_round: Round, +) -> Vec { + let mut validators_map = HashMap::new(); + + for vote in state.prevotes.iter() { + let (count, origin_proposal) = validators_map + .entry(vote.signer) + .or_insert((0, vote.proposal)); + + *count += 1; + + if *count == 2 { + let new_proposal = vote.proposal; + let byzantine_signer = vote.signer; + + return vec![ConsensusResponse::ViolationReport { + violator: byzantine_signer, + misbehavior: Misbehavior::DoublePrevote { + byzantine_node: byzantine_signer, + round: target_round, + proposals: (*origin_proposal, new_proposal), + }, + }]; + } + } + + Vec::new() +} + +/// comment for check_double_precommit +pub(crate) fn check_double_precommit( + state: &ConsensusState, + target_round: Round, +) -> Vec { + let mut validators_map = HashMap::new(); + + for vote in state.precommits.iter() { + let (count, origin_proposal) = validators_map + .entry(vote.signer) + .or_insert((0, vote.proposal)); + + *count += 1; + + if *count == 2 { + let byzantine_signer = vote.signer; + let new_proposal = vote.proposal; + + return vec![ConsensusResponse::ViolationReport { + violator: byzantine_signer, + misbehavior: Misbehavior::DoublePrecommit { + byzantine_node: byzantine_signer, + round: target_round, + proposals: (*origin_proposal, new_proposal), + }, + }]; + } + } + + Vec::new() +} + +/// comment for check_invalid_proposal +pub(crate) fn check_invalid_proposal( + byzantine_proposer: usize, + target_round: Round, + target_proposal: BlockIdentifier, +) -> Vec { + return vec![ConsensusResponse::ViolationReport { + violator: byzantine_proposer, + misbehavior: Misbehavior::InvalidProposal { + byzantine_node: byzantine_proposer, + round: target_round, + proposal: target_proposal, + }, + }]; +} + +/// comment for check_invalid_prevote +pub(crate) fn check_invalid_prevote( + state: &ConsensusState, + target_round: Round, + target_proposal: BlockIdentifier, +) -> Vec { + unimplemented!() +} + +/// comment for check_invalid_precommit +pub(crate) fn check_invalid_precommit( + state: &ConsensusState, + check_round: Round, + check_proposal: BlockIdentifier, +) -> Vec { + unimplemented!() +} diff --git a/vetomint/src/progress.rs b/vetomint/src/progress.rs index 24978407..7679b2ca 100644 --- a/vetomint/src/progress.rs +++ b/vetomint/src/progress.rs @@ -23,6 +23,10 @@ pub(crate) fn progress( round, favor, } => { + if valid == false { + // TODO: add possible invalid proposal logcis + return misbehavior::check_invalid_proposal(proposer, round, proposal); + } state.proposals.insert( proposal, Proposal { @@ -46,6 +50,7 @@ pub(crate) fn progress( state, round, proposal, )); response.extend(on_4f_non_nil_precommit(state, round, proposal)); + response.extend(misbehavior::check_double_proposal(state, round)); response } ConsensusEvent::SkipRound { round } => progress( @@ -86,6 +91,7 @@ pub(crate) fn progress( response.extend(on_4f_nil_prevote(state, round)); } response.extend(on_5f_prevote(state, round, proposal)); + response.extend(misbehavior::check_double_prevote(state, round)); response } ConsensusEvent::Precommit { @@ -104,6 +110,7 @@ pub(crate) fn progress( if let Some(proposal) = proposal { response.extend(on_4f_non_nil_precommit(state, round, proposal)); } + response.extend(misbehavior::check_double_precommit(state, round)); response } ConsensusEvent::Timer => {