Fix tendermint distinct precommit bug (#517)

* fix tendermint distinct precommit bug

* remove conflicting precommit error
This commit is contained in:
akildemir
2024-02-08 21:47:37 +03:00
committed by GitHub
parent aaff74575f
commit 347d4cf413
4 changed files with 3 additions and 84 deletions

View File

@@ -136,7 +136,6 @@ pub enum SlashReason {
#[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)]
pub enum Evidence {
ConflictingMessages(Vec<u8>, Vec<u8>),
ConflictingPrecommit(Vec<u8>, Vec<u8>),
InvalidPrecommit(Vec<u8>),
InvalidValidRound(Vec<u8>),
}
@@ -179,30 +178,6 @@ pub fn verify_tendermint_evience<N: Network>(
Err(TendermintError::InvalidEvidence)?;
}
}
Evidence::ConflictingPrecommit(first, second) => {
let first = decode_and_verify_signed_message::<N>(first, schema)?.msg;
let second = decode_and_verify_signed_message::<N>(second, schema)?.msg;
if (first.sender != second.sender) || (first.block != second.block) {
Err(TendermintError::InvalidEvidence)?;
}
// check whether messages are precommits to different blocks
// The inner signatures don't need to be verified since the outer signatures were
// While the inner signatures may be invalid, that would've yielded a invalid precommit
// signature slash instead of distinct precommit slash
if let Data::Precommit(Some((h1, _))) = first.data {
if let Data::Precommit(Some((h2, _))) = second.data {
if h1 == h2 {
Err(TendermintError::InvalidEvidence)?;
}
return Ok(());
}
}
// No fault identified
Err(TendermintError::InvalidEvidence)?;
}
Evidence::InvalidPrecommit(msg) => {
let msg = decode_and_verify_signed_message::<N>(msg, schema)?.msg;

View File

@@ -3,18 +3,17 @@ use std::{sync::Arc, collections::HashMap};
use log::debug;
use parity_scale_codec::Encode;
use crate::{ext::*, RoundNumber, Step, Data, DataFor, TendermintError, SignedMessageFor, Evidence};
use crate::{ext::*, RoundNumber, Step, DataFor, TendermintError, SignedMessageFor, Evidence};
type RoundLog<N> = HashMap<<N as Network>::ValidatorId, HashMap<Step, SignedMessageFor<N>>>;
pub(crate) struct MessageLog<N: Network> {
weights: Arc<N::Weights>,
precommitted: HashMap<N::ValidatorId, SignedMessageFor<N>>,
pub(crate) log: HashMap<RoundNumber, RoundLog<N>>,
}
impl<N: Network> MessageLog<N> {
pub(crate) fn new(weights: Arc<N::Weights>) -> MessageLog<N> {
MessageLog { weights, precommitted: HashMap::new(), log: HashMap::new() }
MessageLog { weights, log: HashMap::new() }
}
// Returns true if it's a new message
@@ -40,24 +39,6 @@ impl<N: Network> MessageLog<N> {
return Ok(false);
}
// If they already precommitted to a distinct hash, error
if let Data::Precommit(Some((hash, _))) = msg.data {
if let Some(prev) = self.precommitted.get(&msg.sender) {
if let Data::Precommit(Some((prev_hash, _))) = prev.msg.data {
if hash != prev_hash {
debug!(target: "tendermint", "Validator precommitted to multiple blocks");
Err(TendermintError::Malicious(
msg.sender,
Some(Evidence::ConflictingPrecommit(prev.encode(), signed.encode())),
))?;
}
} else {
panic!("message in precommitted wasn't Precommit");
}
}
self.precommitted.insert(msg.sender, signed.clone());
}
msgs.insert(step, signed);
Ok(true)
}