Improve batch handling (#316)

* restrict batch size to ~25kb

* add batch size check to node

* rate limit batches to 1 per serai block

* add support for multiple batches for block

* fix review comments

* Misc fixes

Doesn't yet update tests/processor until data flow is inspected.

* Move the block from SignId to ProcessorMessage::BatchPreprocesses

* Misc clean up

---------

Co-authored-by: Luke Parker <lukeparker5132@gmail.com>
This commit is contained in:
akildemir
2023-08-14 18:57:38 +03:00
committed by GitHub
parent a3441a6871
commit e680eabb62
17 changed files with 234 additions and 155 deletions

View File

@@ -18,10 +18,7 @@ use frost_schnorrkel::Schnorrkel;
use log::{info, debug, warn};
use serai_client::{
primitives::BlockHash,
in_instructions::primitives::{Batch, SignedBatch, batch_message},
};
use serai_client::in_instructions::primitives::{Batch, SignedBatch, batch_message};
use messages::{sign::SignId, coordinator::*};
use crate::{Get, DbTxn, Db};
@@ -149,7 +146,9 @@ impl<D: Db> SubstrateSigner<D> {
}
// Start this attempt
if !self.signable.contains_key(&id) {
let block = if let Some(batch) = self.signable.get(&id) {
batch.block
} else {
warn!("told to attempt signing a batch we aren't currently signing for");
return;
};
@@ -162,7 +161,7 @@ impl<D: Db> SubstrateSigner<D> {
self.attempt.insert(id, attempt);
let id = SignId { key: self.keys.group_key().to_bytes().to_vec(), id, attempt };
info!("signing batch {}, attempt #{}", hex::encode(id.id), id.attempt);
info!("signing batch {} #{}", hex::encode(id.id), id.attempt);
// If we reboot mid-sign, the current design has us abort all signs and wait for latter
// attempts/new signing protocols
@@ -199,19 +198,21 @@ impl<D: Db> SubstrateSigner<D> {
// Broadcast our preprocess
self.events.push_back(SubstrateSignerEvent::ProcessorMessage(
ProcessorMessage::BatchPreprocess { id, preprocess: preprocess.serialize() },
ProcessorMessage::BatchPreprocess { id, block, preprocess: preprocess.serialize() },
));
}
pub async fn sign(&mut self, txn: &mut D::Transaction<'_>, batch: Batch) {
if SubstrateSignerDb::<D>::completed(txn, batch.block.0) {
// Use the batch id as the ID
let mut id = [0u8; 32];
id[.. 4].copy_from_slice(&batch.id.to_le_bytes());
if SubstrateSignerDb::<D>::completed(txn, id) {
debug!("Sign batch order for ID we've already completed signing");
// See batch_signed for commentary on why this simply returns
return;
}
// Use the block hash as the ID
let id = batch.block.0;
self.signable.insert(id, batch);
self.attempt(txn, id, 0).await;
}
@@ -335,14 +336,19 @@ impl<D: Db> SubstrateSigner<D> {
}
}
pub fn batch_signed(&mut self, txn: &mut D::Transaction<'_>, block: BlockHash) {
// Stop trying to sign for this batch
SubstrateSignerDb::<D>::complete(txn, block.0);
pub fn batch_signed(&mut self, txn: &mut D::Transaction<'_>, batch_id: u32) {
// Convert into 32-byte ID
// TODO: Add a BatchSignId so we don't have this inefficiency
let mut id = [0u8; 32];
id[.. 4].copy_from_slice(&batch_id.to_le_bytes());
self.signable.remove(&block.0);
self.attempt.remove(&block.0);
self.preprocessing.remove(&block.0);
self.signing.remove(&block.0);
// Stop trying to sign for this batch
SubstrateSignerDb::<D>::complete(txn, id);
self.signable.remove(&id);
self.attempt.remove(&id);
self.preprocessing.remove(&id);
self.signing.remove(&id);
// This doesn't emit SignedBatch because it doesn't have access to the SignedBatch
// This function is expected to only be called once Substrate acknowledges this block,