mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 12:19:24 +00:00
Call fatal_slash where easy and appropriate
This commit is contained in:
@@ -79,19 +79,24 @@ impl<D: Db> TributaryDb<D> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If a validator has been fatally slashed
|
// If a validator has been fatally slashed
|
||||||
fn fatal_slash_key(genesis: [u8; 32]) -> Vec<u8> {
|
fn fatal_slashes_key(genesis: [u8; 32]) -> Vec<u8> {
|
||||||
Self::tributary_key(b"fatal_slash", genesis)
|
Self::tributary_key(b"fatal_slashes", genesis)
|
||||||
}
|
}
|
||||||
pub fn set_fatally_slashed(txn: &mut D::Transaction<'_>, genesis: [u8; 32], id: [u8; 32]) {
|
fn fatally_slashed_key(account: [u8; 32]) -> Vec<u8> {
|
||||||
let key = Self::fatal_slash_key(genesis);
|
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![]);
|
let mut existing = txn.get(&key).unwrap_or(vec![]);
|
||||||
|
|
||||||
// Don't append if we already have it
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
existing.extend(id);
|
existing.extend(account);
|
||||||
txn.put(key, existing);
|
txn.put(key, existing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use rand_core::SeedableRng;
|
|||||||
use rand_chacha::ChaCha20Rng;
|
use rand_chacha::ChaCha20Rng;
|
||||||
|
|
||||||
use transcript::{Transcript, RecommendedTranscript};
|
use transcript::{Transcript, RecommendedTranscript};
|
||||||
use ciphersuite::{Ciphersuite, Ristretto};
|
use ciphersuite::{group::GroupEncoding, Ciphersuite, Ristretto};
|
||||||
use frost::{
|
use frost::{
|
||||||
FrostError,
|
FrostError,
|
||||||
dkg::{Participant, musig::musig},
|
dkg::{Participant, musig::musig},
|
||||||
@@ -235,6 +235,17 @@ pub fn generated_key_pair<D: Db>(
|
|||||||
DkgConfirmer::share(spec, key, attempt, preprocesses, key_pair)
|
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<
|
pub(crate) async fn handle_application_tx<
|
||||||
D: Db,
|
D: Db,
|
||||||
Pro: Processors,
|
Pro: Processors,
|
||||||
@@ -253,20 +264,24 @@ pub(crate) async fn handle_application_tx<
|
|||||||
) {
|
) {
|
||||||
let genesis = spec.genesis();
|
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 {
|
let Some(curr_attempt) = TributaryDb::<D>::attempt(txn, genesis, data_spec.topic) else {
|
||||||
// TODO: Full slash
|
// Premature publication of a valid ID/publication of an invalid ID
|
||||||
todo!();
|
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 they've already published a TX for this attempt, slash
|
||||||
if let Some(data) = TributaryDb::<D>::data(txn, genesis, data_spec, signed.signer) {
|
if let Some(_) = TributaryDb::<D>::data(txn, genesis, data_spec, signed.signer) {
|
||||||
if data != bytes {
|
fatal_slash::<D>(txn, genesis, signed.signer.to_bytes(), "published data multiple times");
|
||||||
// TODO: Full slash
|
|
||||||
todo!();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Slash
|
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,9 +290,15 @@ pub(crate) async fn handle_application_tx<
|
|||||||
// TODO: Slash for being late
|
// TODO: Slash for being late
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
// If the attempt is greater, this is a premature publication, full slash
|
||||||
if data_spec.attempt > curr_attempt {
|
if data_spec.attempt > curr_attempt {
|
||||||
// TODO: Full slash
|
fatal_slash::<D>(
|
||||||
todo!();
|
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
|
// 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 } => {
|
Transaction::DkgShares { attempt, mut shares, confirmation_nonces, signed } => {
|
||||||
if shares.len() != (usize::from(spec.n()) - 1) {
|
if shares.len() != (usize::from(spec.n()) - 1) {
|
||||||
// TODO: Full slash
|
fatal_slash::<D>(txn, genesis, signed.signer.to_bytes(), "invalid amount of DKG shares");
|
||||||
todo!();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let sender_i = spec
|
let sender_i = spec
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ use serai_db::DbTxn;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Db,
|
Db,
|
||||||
tributary::handle::handle_application_tx,
|
tributary::handle::{fatal_slash, handle_application_tx},
|
||||||
processors::Processors,
|
processors::Processors,
|
||||||
tributary::{TributaryDb, TributarySpec, Transaction},
|
tributary::{TributaryDb, TributarySpec, Transaction},
|
||||||
P2p,
|
P2p,
|
||||||
@@ -84,9 +84,12 @@ async fn handle_block<
|
|||||||
|
|
||||||
// Since anything with evidence is fundamentally faulty behavior, not just temporal errors,
|
// Since anything with evidence is fundamentally faulty behavior, not just temporal errors,
|
||||||
// mark the node as fatally slashed
|
// mark the node as fatally slashed
|
||||||
TributaryDb::<D>::set_fatally_slashed(&mut txn, genesis, msgs.0.msg.sender);
|
fatal_slash::<D>(
|
||||||
|
&mut txn,
|
||||||
// TODO2: disconnect the node from network/ban from further participation in Tributary
|
genesis,
|
||||||
|
msgs.0.msg.sender,
|
||||||
|
&format!("invalid tendermint messages: {:?}", msgs),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
TributaryTransaction::Application(tx) => {
|
TributaryTransaction::Application(tx) => {
|
||||||
handle_application_tx::<D, _, _, _, _, _>(
|
handle_application_tx::<D, _, _, _, _, _>(
|
||||||
|
|||||||
Reference in New Issue
Block a user