Inside publish (for a Serai transaction from the coordinator), use RetiredDb over latest session

Not only is this more performant, the definition of retired won't be if a newer
session is active. It will be if the session has posted a slash report or the
stake for that session has unlocked.

Initial commit towards implementing SlashReports.
This commit is contained in:
Luke Parker 2024-01-05 23:36:33 -05:00
parent 1cff9b4264
commit f3429ec1ef
No known key found for this signature in database
4 changed files with 30 additions and 22 deletions

View file

@ -15,7 +15,7 @@ use serai_client::{
use tokio::time::sleep; use tokio::time::sleep;
use serai_db::{Db, MemDb, DbTxn}; use serai_db::{Get, DbTxn, Db, MemDb};
use processor_messages::{ use processor_messages::{
key_gen::{self, KeyGenId}, key_gen::{self, KeyGenId},
@ -349,6 +349,7 @@ async fn dkg_test() {
impl PublishSeraiTransaction for CheckPublishSetKeys { impl PublishSeraiTransaction for CheckPublishSetKeys {
async fn publish_set_keys( async fn publish_set_keys(
&self, &self,
_db: &(impl Sync + Get),
set: ValidatorSet, set: ValidatorSet,
removed: Vec<SeraiAddress>, removed: Vec<SeraiAddress>,
key_pair: KeyPair, key_pair: KeyPair,

View file

@ -30,6 +30,7 @@ mod sync;
impl PublishSeraiTransaction for () { impl PublishSeraiTransaction for () {
async fn publish_set_keys( async fn publish_set_keys(
&self, &self,
_db: &(impl Sync + serai_db::Get),
_set: ValidatorSet, _set: ValidatorSet,
_removed: Vec<SeraiAddress>, _removed: Vec<SeraiAddress>,
_key_pair: KeyPair, _key_pair: KeyPair,

View file

@ -77,13 +77,14 @@ fn unflatten(
} }
impl< impl<
D: Db,
T: DbTxn, T: DbTxn,
Pro: Processors, Pro: Processors,
PST: PublishSeraiTransaction, PST: PublishSeraiTransaction,
PTT: PTTTrait, PTT: PTTTrait,
RID: RIDTrait, RID: RIDTrait,
P: P2p, P: P2p,
> TributaryBlockHandler<'_, T, Pro, PST, PTT, RID, P> > TributaryBlockHandler<'_, D, T, Pro, PST, PTT, RID, P>
{ {
fn accumulate( fn accumulate(
&mut self, &mut self,
@ -548,6 +549,7 @@ impl<
self self
.publish_serai_tx .publish_serai_tx
.publish_set_keys( .publish_set_keys(
self.db,
self.spec.set(), self.spec.set(),
removed.into_iter().map(|key| key.to_bytes().into()).collect(), removed.into_iter().map(|key| key.to_bytes().into()).collect(),
key_pair, key_pair,

View file

@ -65,6 +65,7 @@ impl<
pub trait PublishSeraiTransaction { pub trait PublishSeraiTransaction {
async fn publish_set_keys( async fn publish_set_keys(
&self, &self,
db: &(impl Sync + Get),
set: ValidatorSet, set: ValidatorSet,
removed: Vec<SeraiAddress>, removed: Vec<SeraiAddress>,
key_pair: KeyPair, key_pair: KeyPair,
@ -84,6 +85,7 @@ mod impl_pst_for_serai {
($Meta: ty, $check: ident) => { ($Meta: ty, $check: ident) => {
async fn publish( async fn publish(
serai: &Serai, serai: &Serai,
db: &impl Get,
set: ValidatorSet, set: ValidatorSet,
tx: serai_client::Transaction, tx: serai_client::Transaction,
meta: $Meta, meta: $Meta,
@ -95,29 +97,25 @@ mod impl_pst_for_serai {
// creation // creation
// TODO2: Differentiate connection errors from invariants // TODO2: Differentiate connection errors from invariants
Err(e) => { Err(e) => {
// The following block is irrelevant, and can/likely will fail, if we're publishing
// a TX for an old session
// If we're on a newer session, move on
if crate::RetiredTributaryDb::get(db, set).is_some() {
log::warn!("trying to publish a TX relevant to set {set:?} which isn't the latest");
return false;
}
if let Ok(serai) = serai.as_of_latest_finalized_block().await { if let Ok(serai) = serai.as_of_latest_finalized_block().await {
let serai = serai.validator_sets(); let serai = serai.validator_sets();
// The following block is irrelevant, and can/likely will fail, if we're publishing
// a TX for an old session
// If we're on a newer session, move on
if let Ok(Some(current_session)) = serai.session(set.network).await {
if current_session.0 > set.session.0 {
log::warn!(
"trying to publish a TX relevant to set {set:?} which isn't the latest"
);
return false;
}
}
// Check if someone else published the TX in question // Check if someone else published the TX in question
if $check(serai, set, meta).await { if $check(serai, set, meta).await {
return false; return false;
} }
log::error!("couldn't connect to Serai node to publish TX: {e:?}");
tokio::time::sleep(core::time::Duration::from_secs(5)).await;
} }
log::error!("couldn't connect to Serai node to publish TX: {e:?}");
tokio::time::sleep(core::time::Duration::from_secs(5)).await;
} }
} }
} }
@ -129,6 +127,7 @@ mod impl_pst_for_serai {
impl PublishSeraiTransaction for Serai { impl PublishSeraiTransaction for Serai {
async fn publish_set_keys( async fn publish_set_keys(
&self, &self,
db: &(impl Sync + Get),
set: ValidatorSet, set: ValidatorSet,
removed: Vec<SeraiAddress>, removed: Vec<SeraiAddress>,
key_pair: KeyPair, key_pair: KeyPair,
@ -143,7 +142,7 @@ mod impl_pst_for_serai {
false false
} }
common_pst!((), check); common_pst!((), check);
if publish(self, set, tx, ()).await { if publish(self, db, set, tx, ()).await {
log::info!("published set keys for {set:?}"); log::info!("published set keys for {set:?}");
} }
} }
@ -163,6 +162,7 @@ impl<FPtt: Send + Future<Output = ()>, F: Sync + Fn(Transaction) -> FPtt> PTTTra
pub struct TributaryBlockHandler< pub struct TributaryBlockHandler<
'a, 'a,
D: Db,
T: DbTxn, T: DbTxn,
Pro: Processors, Pro: Processors,
PST: PublishSeraiTransaction, PST: PublishSeraiTransaction,
@ -170,6 +170,7 @@ pub struct TributaryBlockHandler<
RID: RIDTrait, RID: RIDTrait,
P: P2p, P: P2p,
> { > {
pub db: &'a D,
pub txn: &'a mut T, pub txn: &'a mut T,
pub our_key: &'a Zeroizing<<Ristretto as Ciphersuite>::F>, pub our_key: &'a Zeroizing<<Ristretto as Ciphersuite>::F>,
pub recognized_id: &'a RID, pub recognized_id: &'a RID,
@ -183,13 +184,14 @@ pub struct TributaryBlockHandler<
} }
impl< impl<
D: Db,
T: DbTxn, T: DbTxn,
Pro: Processors, Pro: Processors,
PST: PublishSeraiTransaction, PST: PublishSeraiTransaction,
PTT: PTTTrait, PTT: PTTTrait,
RID: RIDTrait, RID: RIDTrait,
P: P2p, P: P2p,
> TributaryBlockHandler<'_, T, Pro, PST, PTT, RID, P> > TributaryBlockHandler<'_, D, T, Pro, PST, PTT, RID, P>
{ {
pub fn fatal_slash(&mut self, slashing: [u8; 32], reason: &str) { pub fn fatal_slash(&mut self, slashing: [u8; 32], reason: &str) {
let genesis = self.spec.genesis(); let genesis = self.spec.genesis();
@ -204,7 +206,7 @@ impl<
// Tributary post-DKG // Tributary post-DKG
// https://github.com/serai-dex/serai/issues/426 // https://github.com/serai-dex/serai/issues/426
async fn handle<D: Db>(mut self) { async fn handle(mut self) {
log::info!("found block for Tributary {:?}", self.spec.set()); log::info!("found block for Tributary {:?}", self.spec.set());
let transactions = self.block.transactions.clone(); let transactions = self.block.transactions.clone();
@ -581,9 +583,11 @@ pub(crate) async fn handle_new_blocks<
} }
} }
let mut txn = db.txn(); let mut db_clone = db.clone();
let mut txn = db_clone.txn();
TributaryBlockNumber::set(&mut txn, next, &block_number); TributaryBlockNumber::set(&mut txn, next, &block_number);
(TributaryBlockHandler { (TributaryBlockHandler {
db,
txn: &mut txn, txn: &mut txn,
spec, spec,
our_key: key, our_key: key,
@ -595,7 +599,7 @@ pub(crate) async fn handle_new_blocks<
block_number, block_number,
_p2p: PhantomData::<P>, _p2p: PhantomData::<P>,
}) })
.handle::<D>() .handle()
.await; .await;
last_block = next; last_block = next;
LastHandledBlock::set(&mut txn, genesis, &next); LastHandledBlock::set(&mut txn, genesis, &next);