From 1f9ac4b111a4a398e3b2ac8f62f74faccc520b2a Mon Sep 17 00:00:00 2001 From: Jeongseup Date: Sun, 6 Aug 2023 17:55:09 +0900 Subject: [PATCH 1/3] add misbehavior.rs --- vetomint/src/misbehavior.rs | 98 +++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 vetomint/src/misbehavior.rs diff --git a/vetomint/src/misbehavior.rs b/vetomint/src/misbehavior.rs new file mode 100644 index 00000000..20384811 --- /dev/null +++ b/vetomint/src/misbehavior.rs @@ -0,0 +1,98 @@ +use super::*; +use state::*; + +use std::collections::HashMap; + +pub(crate) fn check_misbehavior( + state: &ConsensusState, + check_round: Round, + check_proposal: BlockIdentifier, +) -> Vec { + let mut misbehavior: Vec = vec![]; + + if let Some(m) = check_double_proposals(state, check_round) { + misbehavior.push(m); + } else { + println!("not found double proposals in this round"); + } + + if let Some(m) = check_double_prevote(state, check_round, check_proposal) { + misbehavior.push(m); + } else { + println!("not found double prevote in this round"); + } + + if let Some(m) = check_double_precommit(state, check_round, check_proposal) { + misbehavior.push(m); + } else { + println!("not found double precommit in this round"); + } + + misbehavior +} + +fn check_double_proposals(state: &ConsensusState, check_round: Round) -> Option { + let proposals: Vec<_> = state + .proposals + .iter() + .filter(|(_, proposal)| proposal.round == check_round) + .map(|(_, proposal)| proposal) + .collect(); + + if proposals.len() > 1 { + // returnSome(result[0].1.proposer) + return Some(Misbehavior::DoubleProposal { + byzantine_node: proposals[0].proposer, + round: check_round, + proposals: (proposals[0].proposal, proposals[1].proposal), + }); + } + + None +} + +fn check_double_prevote( + state: &ConsensusState, + check_round: Round, + check_proposal: BlockIdentifier, +) -> Option { + let mut validators_map = HashMap::new(); + + for vote in state.prevotes.iter() { + let count = validators_map.entry(vote.signer).or_insert(0); + *count += 1; + + if *count == 2 { + return Some(Misbehavior::DoublePrevote { + byzantine_node: vote.signer, + round: check_round, + proposals: (Some(check_proposal), Some(check_proposal)), + }); + } + } + + None +} + +fn check_double_precommit( + state: &ConsensusState, + check_round: Round, + check_proposal: BlockIdentifier, +) -> Option { + let mut validators_map = HashMap::new(); + + for vote in state.precommits.iter() { + let count = validators_map.entry(vote.signer).or_insert(0); + *count += 1; + + if *count == 2 { + return Some(Misbehavior::DoublePrecommit { + byzantine_node: vote.signer, + round: check_round, + proposals: (Some(check_proposal), Some(check_proposal)), + }); + } + } + + None +} From def58735a2282cb3b657c8baf35a933faaa0abd2 Mon Sep 17 00:00:00 2001 From: Jeongseup Date: Sat, 12 Aug 2023 01:23:19 +0900 Subject: [PATCH 2/3] update misbehavior --- vetomint/src/misbehavior.rs | 88 ++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) diff --git a/vetomint/src/misbehavior.rs b/vetomint/src/misbehavior.rs index 20384811..99f433ab 100644 --- a/vetomint/src/misbehavior.rs +++ b/vetomint/src/misbehavior.rs @@ -28,6 +28,24 @@ pub(crate) fn check_misbehavior( println!("not found double precommit in this round"); } + if let Some(m) = check_invalid_proposal(state, check_proposal) { + misbehavior.push(m); + } else { + println!("not found invalid proposal in this round"); + } + + if let Some(m) = check_invalid_prevote(state, check_round, check_proposal) { + misbehavior.push(m); + } else { + println!("not found double precommit in this round"); + } + + if let Some(m) = check_invalid_precommit(state, check_round, check_proposal) { + misbehavior.push(m); + } else { + println!("not found double precommit in this round"); + } + misbehavior } @@ -40,7 +58,6 @@ fn check_double_proposals(state: &ConsensusState, check_round: Round) -> Option< .collect(); if proposals.len() > 1 { - // returnSome(result[0].1.proposer) return Some(Misbehavior::DoubleProposal { byzantine_node: proposals[0].proposer, round: check_round, @@ -96,3 +113,72 @@ fn check_double_precommit( None } + +fn check_invalid_proposal( + state: &ConsensusState, + check_proposal: BlockIdentifier, +) -> Option { + if let Some(proposal) = state.proposals.get(&check_proposal) { + if proposal.valid == false { + return Some(Misbehavior::InvalidProposal { + byzantine_node: proposal.proposer, + round: proposal.round, + proposal: proposal.proposal, + }); + } + } + + None +} + +fn check_invalid_prevote( + state: &ConsensusState, + check_round: Round, + check_proposal: BlockIdentifier, +) -> Option { + let valid_prevotes: Vec<_> = state + .prevotes + .iter() + .filter(|prevote| prevote.round == check_round) + .collect(); + + for prevote in valid_prevotes.iter() { + if let Some(proposal) = prevote.proposal { + if proposal == check_proposal { + return Some(Misbehavior::InvalidPrevote { + byzantine_node: prevote.signer, + round: prevote.round, + proposal: proposal, + }); + } + } + } + + None +} + +fn check_invalid_precommit( + state: &ConsensusState, + check_round: Round, + check_proposal: BlockIdentifier, +) -> Option { + let valid_precommits: Vec<_> = state + .precommits + .iter() + .filter(|prevote| prevote.round == check_round) + .collect(); + + for precommit in valid_precommits.iter() { + if let Some(proposal) = precommit.proposal { + if proposal == check_proposal { + return Some(Misbehavior::InvalidPrecommit { + byzantine_node: precommit.signer, + round: precommit.round, + proposal: proposal, + }); + } + } + } + + None +} From 3e047e69a77da9550c9773ed25028a397fb5b365 Mon Sep 17 00:00:00 2001 From: Jeongseup Date: Sun, 27 Aug 2023 17:42:49 +0900 Subject: [PATCH 3/3] modify misbehavior module in vetomint --- vetomint/src/lib.rs | 1 + vetomint/src/misbehavior.rs | 215 ++++++++++++++---------------------- vetomint/src/progress.rs | 7 ++ 3 files changed, 89 insertions(+), 134 deletions(-) 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 index 99f433ab..501a7423 100644 --- a/vetomint/src/misbehavior.rs +++ b/vetomint/src/misbehavior.rs @@ -3,182 +3,129 @@ use state::*; use std::collections::HashMap; -pub(crate) fn check_misbehavior( +/// comment for check_double_proposal +pub(crate) fn check_double_proposal( state: &ConsensusState, - check_round: Round, - check_proposal: BlockIdentifier, -) -> Vec { - let mut misbehavior: Vec = vec![]; - - if let Some(m) = check_double_proposals(state, check_round) { - misbehavior.push(m); - } else { - println!("not found double proposals in this round"); - } - - if let Some(m) = check_double_prevote(state, check_round, check_proposal) { - misbehavior.push(m); - } else { - println!("not found double prevote in this round"); - } - - if let Some(m) = check_double_precommit(state, check_round, check_proposal) { - misbehavior.push(m); - } else { - println!("not found double precommit in this round"); - } - - if let Some(m) = check_invalid_proposal(state, check_proposal) { - misbehavior.push(m); - } else { - println!("not found invalid proposal in this round"); - } - - if let Some(m) = check_invalid_prevote(state, check_round, check_proposal) { - misbehavior.push(m); - } else { - println!("not found double precommit in this round"); - } - - if let Some(m) = check_invalid_precommit(state, check_round, check_proposal) { - misbehavior.push(m); - } else { - println!("not found double precommit in this round"); - } - - misbehavior -} - -fn check_double_proposals(state: &ConsensusState, check_round: Round) -> Option { + target_round: Round, +) -> Vec { let proposals: Vec<_> = state .proposals .iter() - .filter(|(_, proposal)| proposal.round == check_round) + .filter(|(_, proposal)| proposal.round == target_round) .map(|(_, proposal)| proposal) .collect(); if proposals.len() > 1 { - return Some(Misbehavior::DoubleProposal { - byzantine_node: proposals[0].proposer, - round: check_round, - proposals: (proposals[0].proposal, proposals[1].proposal), - }); + 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), + }, + }]; } - None + Vec::new() } -fn check_double_prevote( +/// comment for check_double_prevote +pub(crate) fn check_double_prevote( state: &ConsensusState, - check_round: Round, - check_proposal: BlockIdentifier, -) -> Option { + target_round: Round, +) -> Vec { let mut validators_map = HashMap::new(); for vote in state.prevotes.iter() { - let count = validators_map.entry(vote.signer).or_insert(0); + let (count, origin_proposal) = validators_map + .entry(vote.signer) + .or_insert((0, vote.proposal)); + *count += 1; if *count == 2 { - return Some(Misbehavior::DoublePrevote { - byzantine_node: vote.signer, - round: check_round, - proposals: (Some(check_proposal), Some(check_proposal)), - }); + 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), + }, + }]; } } - None + Vec::new() } -fn check_double_precommit( +/// comment for check_double_precommit +pub(crate) fn check_double_precommit( state: &ConsensusState, - check_round: Round, - check_proposal: BlockIdentifier, -) -> Option { + target_round: Round, +) -> Vec { let mut validators_map = HashMap::new(); for vote in state.precommits.iter() { - let count = validators_map.entry(vote.signer).or_insert(0); + let (count, origin_proposal) = validators_map + .entry(vote.signer) + .or_insert((0, vote.proposal)); + *count += 1; if *count == 2 { - return Some(Misbehavior::DoublePrecommit { - byzantine_node: vote.signer, - round: check_round, - proposals: (Some(check_proposal), Some(check_proposal)), - }); + 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), + }, + }]; } } - None + Vec::new() } -fn check_invalid_proposal( - state: &ConsensusState, - check_proposal: BlockIdentifier, -) -> Option { - if let Some(proposal) = state.proposals.get(&check_proposal) { - if proposal.valid == false { - return Some(Misbehavior::InvalidProposal { - byzantine_node: proposal.proposer, - round: proposal.round, - proposal: proposal.proposal, - }); - } - } - - None +/// 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, + }, + }]; } -fn check_invalid_prevote( +/// comment for check_invalid_prevote +pub(crate) fn check_invalid_prevote( state: &ConsensusState, - check_round: Round, - check_proposal: BlockIdentifier, -) -> Option { - let valid_prevotes: Vec<_> = state - .prevotes - .iter() - .filter(|prevote| prevote.round == check_round) - .collect(); - - for prevote in valid_prevotes.iter() { - if let Some(proposal) = prevote.proposal { - if proposal == check_proposal { - return Some(Misbehavior::InvalidPrevote { - byzantine_node: prevote.signer, - round: prevote.round, - proposal: proposal, - }); - } - } - } - - None + target_round: Round, + target_proposal: BlockIdentifier, +) -> Vec { + unimplemented!() } -fn check_invalid_precommit( +/// comment for check_invalid_precommit +pub(crate) fn check_invalid_precommit( state: &ConsensusState, check_round: Round, check_proposal: BlockIdentifier, -) -> Option { - let valid_precommits: Vec<_> = state - .precommits - .iter() - .filter(|prevote| prevote.round == check_round) - .collect(); - - for precommit in valid_precommits.iter() { - if let Some(proposal) = precommit.proposal { - if proposal == check_proposal { - return Some(Misbehavior::InvalidPrecommit { - byzantine_node: precommit.signer, - round: precommit.round, - proposal: proposal, - }); - } - } - } - - None +) -> 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 => {