Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions code/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions code/crates/core-consensus/src/effect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,6 @@ where
Decide(
CommitCertificate<Ctx>,
VoteExtensions<Ctx>,
malachitebft_core_driver::EvidenceMap<Ctx>,
malachitebft_core_votekeeper::EvidenceMap<Ctx>,
resume::Continue,
),

Expand Down
14 changes: 7 additions & 7 deletions code/crates/core-consensus/src/handle/decide.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::MisbehaviorEvidence;
use crate::{handle::signature::verify_commit_certificate, prelude::*};

#[cfg_attr(not(feature = "metrics"), allow(unused_variables))]
Expand Down Expand Up @@ -100,15 +101,14 @@ where
}
}

let _evidence = MisbehaviorEvidence {
proposals: state.driver.proposal_evidence().clone(),
votes: state.driver.vote_evidence().clone(),
};

perform!(
co,
Effect::Decide(
certificate,
extensions,
state.driver.evidence().clone(),
state.driver.votes().evidence().clone(),
Default::default()
)
Effect::Decide(certificate, extensions, Default::default())
);

Ok(())
Expand Down
12 changes: 12 additions & 0 deletions code/crates/core-consensus/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,15 @@ pub enum VoteExtensionError {
#[error("Invalid vote extension")]
InvalidVoteExtension,
}

#[derive_where(Clone, Debug)]
pub struct MisbehaviorEvidence<Ctx: Context> {
pub proposals: malachitebft_core_driver::EvidenceMap<Ctx>,
pub votes: malachitebft_core_votekeeper::EvidenceMap<Ctx>,
}

impl<Ctx: Context> MisbehaviorEvidence<Ctx> {
pub fn is_empty(&self) -> bool {
self.proposals.is_empty() && self.votes.is_empty()
}
}
1 change: 1 addition & 0 deletions code/crates/core-driver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ malachitebft-core-votekeeper = { workspace = true }

derive-where = { workspace = true }
thiserror = { workspace = true, default-features = false }
tracing = { workspace = true }

[dev-dependencies]
malachitebft-test = { workspace = true }
70 changes: 8 additions & 62 deletions code/crates/core-driver/src/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ use malachitebft_core_types::{
SignedProposal, SignedVote, Timeout, TimeoutKind, Validator, ValidatorSet, Validity, Value,
ValueId, Vote, VoteType,
};
use malachitebft_core_votekeeper::keeper::Output as VKOutput;
use malachitebft_core_votekeeper::keeper::VoteKeeper;
use malachitebft_core_votekeeper::keeper::{Output as VKOutput, RecordVoteError};

use crate::input::Input;
use crate::output::Output;
use crate::proposal_keeper::{EvidenceMap, ProposalKeeper};
use crate::proposal_keeper::{self, ProposalKeeper};
use crate::Error;
use crate::ThresholdParams;

Expand Down Expand Up @@ -45,23 +45,9 @@ where
/// The proposals to decide on.
pub(crate) proposal_keeper: ProposalKeeper<Ctx>,

/// The evidence of equivocation (if any) after processing a proposal.
pub(crate) proposal_equivocation_evidence: Option<(
Ctx::Height,
Ctx::Address,
(SignedProposal<Ctx>, SignedProposal<Ctx>),
)>,

/// The vote keeper.
pub(crate) vote_keeper: VoteKeeper<Ctx>,

/// The evidence of equivocation (if any) after processing a vote.
pub(crate) vote_equivocation_evidence: Option<(
Ctx::Height,
Ctx::Address,
(SignedVote<Ctx>, SignedVote<Ctx>),
)>,

/// The commit certificates
pub(crate) commit_certificates: Vec<CommitCertificate<Ctx>>,

Expand Down Expand Up @@ -104,9 +90,7 @@ where
threshold_params,
validator_set,
proposal_keeper,
proposal_equivocation_evidence: None,
vote_keeper,
vote_equivocation_evidence: None,
round_state,
proposer: None,
pending_inputs: vec![],
Expand Down Expand Up @@ -208,41 +192,14 @@ where
&self.validator_set
}

/// Return recorded evidence of equivocation for this height.
pub fn evidence(&self) -> &EvidenceMap<Ctx> {
/// Return recorded evidence of proposal equivocation for this height.
pub fn proposal_evidence(&self) -> &proposal_keeper::EvidenceMap<Ctx> {
self.proposal_keeper.evidence()
}

/// Return proposal equivocation evidence, if any.
pub fn proposal_equivocation_evidence(
&self,
) -> Option<(
Ctx::Height,
Ctx::Address,
(SignedProposal<Ctx>, SignedProposal<Ctx>),
)> {
self.proposal_equivocation_evidence.clone()
}

/// Clear the proposal equivocation evidence.
pub fn clear_proposal_equivocation_evidence(&mut self) {
self.proposal_equivocation_evidence = None;
}

/// Return vote equivocation evidence, if any.
pub fn vote_equivocation_evidence(
&self,
) -> Option<(
Ctx::Height,
Ctx::Address,
(SignedVote<Ctx>, SignedVote<Ctx>),
)> {
self.vote_equivocation_evidence.clone()
}

/// Clear the vote equivocation evidence.
pub fn clear_vote_equivocation_evidence(&mut self) {
self.vote_equivocation_evidence = None;
/// Return recorded evidence of vote equivocation for this height.
pub fn vote_evidence(&self) -> &malachitebft_core_votekeeper::EvidenceMap<Ctx> {
self.votes().evidence()
}

/// Return the proposer for the current round.
Expand Down Expand Up @@ -497,21 +454,10 @@ where
let vote_round = vote.round();
let this_round = self.round();

let validator_address = vote.validator_address().clone();
let height = vote.height();

let output = match self.vote_keeper.apply_vote(vote, this_round) {
Ok(Some(output)) => output,
Ok(None) => return Ok(None),
Err(RecordVoteError::ConflictingVote {
existing,
conflicting,
}) => {
self.vote_equivocation_evidence =
Some((height, validator_address, (existing, conflicting)));

return Ok(None);
}
Err(_) => return Ok(None),
};

if let VKOutput::PolkaValue(val) = &output {
Expand Down
15 changes: 2 additions & 13 deletions code/crates/core-driver/src/mux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ use malachitebft_core_votekeeper::keeper::Output as VKOutput;
use malachitebft_core_votekeeper::keeper::VoteKeeper;
use malachitebft_core_votekeeper::Threshold;

use crate::proposal_keeper::RecordProposalError;
use crate::Driver;

impl<Ctx> Driver<Ctx>
Expand Down Expand Up @@ -200,19 +199,9 @@ where
let proposal = signed_proposal.message.clone();

// Store the proposal and its validity
if let Err(RecordProposalError::ConflictingProposal {
existing,
conflicting,
}) = self
let _ = self
.proposal_keeper
.store_proposal(signed_proposal, validity)
{
let validator_address = existing.validator_address().clone();
let height = existing.height();

self.proposal_equivocation_evidence =
Some((height, validator_address, (existing, conflicting)));
}
.store_proposal(signed_proposal, validity);

self.multiplex_proposal(proposal, validity)
}
Expand Down
6 changes: 6 additions & 0 deletions code/crates/core-driver/src/proposal_keeper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use derive_where::derive_where;
use thiserror::Error;

use malachitebft_core_types::{Context, Proposal, Round, SignedProposal, Validity};
use tracing::warn;

/// Errors can that be yielded when recording a proposal.
#[derive_where(Debug)]
Expand Down Expand Up @@ -143,6 +144,11 @@ where
// This is an equivocating proposal
self.evidence.add(existing.clone(), conflicting.clone());

warn!(
"Conflicting proposal: existing: {:?}, conflicting: {:?}",
existing, conflicting
);

Err(RecordProposalError::ConflictingProposal {
existing,
conflicting,
Expand Down
1 change: 1 addition & 0 deletions code/crates/core-votekeeper/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ malachitebft-core-types = { workspace = true }

derive-where = { workspace = true }
thiserror = { workspace = true, default-features = false }
tracing = { workspace = true }

[dev-dependencies]
malachitebft-test = { workspace = true }
7 changes: 7 additions & 0 deletions code/crates/core-votekeeper/src/keeper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use alloc::collections::{BTreeMap, BTreeSet};
use malachitebft_core_types::{
Context, NilOrVal, Round, SignedVote, Validator, ValidatorSet, ValueId, Vote, VoteType,
};
use tracing::warn;

use crate::evidence::EvidenceMap;
use crate::round_votes::RoundVotes;
Expand Down Expand Up @@ -234,6 +235,12 @@ where
}) => {
// This is an equivocating vote
self.evidence.add(existing.clone(), conflicting);

warn!(
"Conflicting vote: existing: {:?}, conflicting: {:?}",
existing, vote
);

return Err(RecordVoteError::ConflictingVote {
existing,
conflicting: vote,
Expand Down
41 changes: 2 additions & 39 deletions code/crates/engine/src/consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -564,18 +564,6 @@ where
{
error!(%from, "Error when processing vote: {e}");
}

if let Some((vote_height, validator_address, evidence)) =
state.consensus.driver.vote_equivocation_evidence()
{
self.tx_event.send(|| Event::VoteEquivocationEvidence {
vote_height,
address: validator_address,
evidence,
});

state.consensus.driver.clear_vote_equivocation_evidence();
}
}

NetworkEvent::Proposal(from, proposal) => {
Expand All @@ -590,21 +578,6 @@ where
{
error!(%from, "Error when processing proposal: {e}");
}

if let Some((proposal_height, validator_address, evidence)) =
state.consensus.driver.proposal_equivocation_evidence()
{
self.tx_event.send(|| Event::ProposalEquivocationEvidence {
proposal_height,
address: validator_address,
evidence,
});

state
.consensus
.driver
.clear_proposal_equivocation_evidence();
}
}

NetworkEvent::ProposalPart(from, part) => {
Expand Down Expand Up @@ -1151,22 +1124,12 @@ where
Ok(r.resume_with(()))
}

Effect::Decide(
certificate,
extensions,
proposal_equivocation_evidence_map,
vote_equivocation_evidence_map,
r,
) => {
Effect::Decide(certificate, extensions, r) => {
assert!(!certificate.commit_signatures.is_empty());

self.wal_flush(state.phase).await?;

self.tx_event.send(|| Event::Decided {
commit_certificate: certificate.clone(),
proposal_equivocation_evidence_map,
vote_equivocation_evidence_map,
});
self.tx_event.send(|| Event::Decided(certificate.clone()));

let height = certificate.height;

Expand Down
Loading
Loading