Call fatal_slash where easy and appropriate

This commit is contained in:
Luke Parker 2023-10-15 00:32:51 -04:00
parent a300a1029a
commit 3483f7fa73
No known key found for this signature in database
3 changed files with 54 additions and 25 deletions

View file

@ -79,19 +79,24 @@ impl<D: Db> TributaryDb<D> {
}
// If a validator has been fatally slashed
fn fatal_slash_key(genesis: [u8; 32]) -> Vec<u8> {
Self::tributary_key(b"fatal_slash", genesis)
fn fatal_slashes_key(genesis: [u8; 32]) -> Vec<u8> {
Self::tributary_key(b"fatal_slashes", genesis)
}
pub fn set_fatally_slashed(txn: &mut D::Transaction<'_>, genesis: [u8; 32], id: [u8; 32]) {
let key = Self::fatal_slash_key(genesis);
fn fatally_slashed_key(account: [u8; 32]) -> Vec<u8> {
Self::tributary_key(b"fatally_slashed", account)
}
pub fn set_fatally_slashed(txn: &mut D::Transaction<'_>, genesis: [u8; 32], account: [u8; 32]) {
txn.put(Self::fatally_slashed_key(account), []);
let key = Self::fatal_slashes_key(genesis);
let mut existing = txn.get(&key).unwrap_or(vec![]);
// Don't append if we already have it
if existing.chunks(32).any(|ex_id| ex_id == id) {
if existing.chunks(32).any(|existing| existing == account) {
return;
}
existing.extend(id);
existing.extend(account);
txn.put(key, existing);
}

View file

@ -7,7 +7,7 @@ use rand_core::SeedableRng;
use rand_chacha::ChaCha20Rng;
use transcript::{Transcript, RecommendedTranscript};
use ciphersuite::{Ciphersuite, Ristretto};
use ciphersuite::{group::GroupEncoding, Ciphersuite, Ristretto};
use frost::{
FrostError,
dkg::{Participant, musig::musig},
@ -235,6 +235,17 @@ pub fn generated_key_pair<D: Db>(
DkgConfirmer::share(spec, key, attempt, preprocesses, key_pair)
}
pub(crate) fn fatal_slash<D: Db>(
txn: &mut D::Transaction<'_>,
genesis: [u8; 32],
account: [u8; 32],
reason: &str,
) {
log::warn!("fatally slashing {}. reason: {}", hex::encode(account), reason);
TributaryDb::<D>::set_fatally_slashed(txn, genesis, account);
// TODO: disconnect the node from network/ban from further participation in all Tributaries
}
pub(crate) async fn handle_application_tx<
D: Db,
Pro: Processors,
@ -253,20 +264,24 @@ pub(crate) async fn handle_application_tx<
) {
let genesis = spec.genesis();
let handle = |txn: &mut _, data_spec: &DataSpecification, bytes: Vec<u8>, signed: &Signed| {
let handle = |txn: &mut <D as Db>::Transaction<'_>,
data_spec: &DataSpecification,
bytes: Vec<u8>,
signed: &Signed| {
let Some(curr_attempt) = TributaryDb::<D>::attempt(txn, genesis, data_spec.topic) else {
// TODO: Full slash
todo!();
// Premature publication of a valid ID/publication of an invalid ID
fatal_slash::<D>(
txn,
genesis,
signed.signer.to_bytes(),
"published data for ID without an attempt",
);
return None;
};
// If they've already published a TX for this attempt, slash
if let Some(data) = TributaryDb::<D>::data(txn, genesis, data_spec, signed.signer) {
if data != bytes {
// TODO: Full slash
todo!();
}
// TODO: Slash
if let Some(_) = TributaryDb::<D>::data(txn, genesis, data_spec, signed.signer) {
fatal_slash::<D>(txn, genesis, signed.signer.to_bytes(), "published data multiple times");
return None;
}
@ -275,9 +290,15 @@ pub(crate) async fn handle_application_tx<
// TODO: Slash for being late
return None;
}
// If the attempt is greater, this is a premature publication, full slash
if data_spec.attempt > curr_attempt {
// TODO: Full slash
todo!();
fatal_slash::<D>(
txn,
genesis,
signed.signer.to_bytes(),
"published data with an attempt which hasn't started",
);
return None;
}
// TODO: We can also full slash if shares before all commitments, or share before the
@ -324,8 +345,8 @@ pub(crate) async fn handle_application_tx<
Transaction::DkgShares { attempt, mut shares, confirmation_nonces, signed } => {
if shares.len() != (usize::from(spec.n()) - 1) {
// TODO: Full slash
todo!();
fatal_slash::<D>(txn, genesis, signed.signer.to_bytes(), "invalid amount of DKG shares");
return;
}
let sender_i = spec

View file

@ -22,7 +22,7 @@ use serai_db::DbTxn;
use crate::{
Db,
tributary::handle::handle_application_tx,
tributary::handle::{fatal_slash, handle_application_tx},
processors::Processors,
tributary::{TributaryDb, TributarySpec, Transaction},
P2p,
@ -84,9 +84,12 @@ async fn handle_block<
// Since anything with evidence is fundamentally faulty behavior, not just temporal errors,
// mark the node as fatally slashed
TributaryDb::<D>::set_fatally_slashed(&mut txn, genesis, msgs.0.msg.sender);
// TODO2: disconnect the node from network/ban from further participation in Tributary
fatal_slash::<D>(
&mut txn,
genesis,
msgs.0.msg.sender,
&format!("invalid tendermint messages: {:?}", msgs),
);
}
TributaryTransaction::Application(tx) => {
handle_application_tx::<D, _, _, _, _, _>(