Merge BlockWithAcknowledgedBatch and BatchWithoutAcknowledgeBatch

Offers a simpler API to the coordinator.
This commit is contained in:
Luke Parker 2024-09-19 03:16:17 -04:00
parent 53567e91c8
commit c27aaf8658
6 changed files with 59 additions and 62 deletions

View file

@ -270,32 +270,43 @@ pub async fn main_loop<
// This is a cheap call // This is a cheap call
signers.retire_session(txn, session, &key) signers.retire_session(txn, session, &key)
} }
messages::substrate::CoordinatorMessage::BlockWithBatchAcknowledgement { messages::substrate::CoordinatorMessage::Block {
block: _, serai_block_number: _,
batch_id, batches,
in_instruction_succeededs, mut burns,
burns,
} => { } => {
let mut txn = txn.take().unwrap();
let scanner = scanner.as_mut().unwrap(); let scanner = scanner.as_mut().unwrap();
let key_to_activate = KeyToActivate::<KeyFor<S>>::try_recv(&mut txn).map(|key| key.0);
// Substrate sets this limit to prevent DoSs from malicious validator sets
// That bound lets us consume this txn in the following loop body, as an optimization
assert!(batches.len() <= 1);
for messages::substrate::ExecutedBatch { id, in_instructions } in batches {
let key_to_activate =
KeyToActivate::<KeyFor<S>>::try_recv(txn.as_mut().unwrap()).map(|key| key.0);
/*
`acknowledge_batch` takes burns to optimize handling returns with standard payments.
That's why handling these with a Batch (and not waiting until the following potential
`queue_burns` call makes sense. As for which Batch, the first is equally valid unless
we want to start introspecting (and should be our only Batch anyways).
*/
let mut this_batchs_burns = vec![];
std::mem::swap(&mut burns, &mut this_batchs_burns);
// This is a cheap call as it internally just queues this to be done later
let _: () = scanner.acknowledge_batch(
txn.take().unwrap(),
id,
in_instructions,
this_batchs_burns,
key_to_activate,
);
}
// This is a cheap call as it internally just queues this to be done later // This is a cheap call as it internally just queues this to be done later
scanner.acknowledge_batch( if !burns.is_empty() {
txn, let _: () = scanner.queue_burns(txn.take().unwrap(), burns);
batch_id, }
in_instruction_succeededs,
burns,
key_to_activate,
)
}
messages::substrate::CoordinatorMessage::BlockWithoutBatchAcknowledgement {
block: _,
burns,
} => {
let txn = txn.take().unwrap();
let scanner = scanner.as_mut().unwrap();
// This is a cheap call as it internally just queues this to be done later
scanner.queue_burns(txn, burns)
} }
}, },
}; };

View file

@ -181,7 +181,6 @@ pub mod coordinator {
pub mod substrate { pub mod substrate {
use super::*; use super::*;
/* TODO
#[derive(Clone, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)] #[derive(Clone, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)]
pub enum InInstructionResult { pub enum InInstructionResult {
Succeeded, Succeeded,
@ -189,15 +188,9 @@ pub mod substrate {
} }
#[derive(Clone, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)] #[derive(Clone, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)]
pub struct ExecutedBatch { pub struct ExecutedBatch {
batch_id: u32, pub id: u32,
in_instructions: Vec<InInstructionResult>, pub in_instructions: Vec<InInstructionResult>,
} }
Block {
block: u64,
batches: Vec<ExecutedBatch>,
burns: Vec<OutInstructionWithBalance>,
}
*/
#[derive(Clone, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)] #[derive(Clone, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)]
pub enum CoordinatorMessage { pub enum CoordinatorMessage {
@ -205,15 +198,12 @@ pub mod substrate {
SetKeys { serai_time: u64, session: Session, key_pair: KeyPair }, SetKeys { serai_time: u64, session: Session, key_pair: KeyPair },
/// Slashes reported on the Serai blockchain OR the process timed out. /// Slashes reported on the Serai blockchain OR the process timed out.
SlashesReported { session: Session }, SlashesReported { session: Session },
/// The data from a block which acknowledged a Batch. /// A block from Serai with relevance to this processor.
BlockWithBatchAcknowledgement { Block {
block: u64, serai_block_number: u64,
batch_id: u32, batches: Vec<ExecutedBatch>,
in_instruction_succeededs: Vec<bool>,
burns: Vec<OutInstructionWithBalance>, burns: Vec<OutInstructionWithBalance>,
}, },
/// The data from a block which didn't acknowledge a Batch.
BlockWithoutBatchAcknowledgement { block: u64, burns: Vec<OutInstructionWithBalance> },
} }
#[derive(Clone, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)] #[derive(Clone, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)]
@ -323,11 +313,8 @@ impl CoordinatorMessage {
let (sub, id) = match msg { let (sub, id) = match msg {
substrate::CoordinatorMessage::SetKeys { session, .. } => (0, session.encode()), substrate::CoordinatorMessage::SetKeys { session, .. } => (0, session.encode()),
substrate::CoordinatorMessage::SlashesReported { session } => (1, session.encode()), substrate::CoordinatorMessage::SlashesReported { session } => (1, session.encode()),
substrate::CoordinatorMessage::BlockWithBatchAcknowledgement { block, .. } => { substrate::CoordinatorMessage::Block { serai_block_number, .. } => {
(2, block.encode()) (2, serai_block_number.encode())
}
substrate::CoordinatorMessage::BlockWithoutBatchAcknowledgement { block, .. } => {
(3, block.encode())
} }
}; };

View file

@ -31,6 +31,8 @@ tokio = { version = "1", default-features = false, features = ["rt-multi-thread"
serai-db = { path = "../../common/db" } serai-db = { path = "../../common/db" }
messages = { package = "serai-processor-messages", path = "../messages" }
serai-primitives = { path = "../../substrate/primitives", default-features = false, features = ["std"] } serai-primitives = { path = "../../substrate/primitives", default-features = false, features = ["std"] }
serai-in-instructions-primitives = { path = "../../substrate/in-instructions/primitives", default-features = false, features = ["std", "borsh"] } serai-in-instructions-primitives = { path = "../../substrate/in-instructions/primitives", default-features = false, features = ["std", "borsh"] }
serai-coins-primitives = { path = "../../substrate/coins/primitives", default-features = false, features = ["std", "borsh"] } serai-coins-primitives = { path = "../../substrate/coins/primitives", default-features = false, features = ["std", "borsh"] }

View file

@ -429,9 +429,6 @@ impl<S: ScannerFeed> Scanner<S> {
/// This means the specified Batch was ordered on Serai in relation to Burn events, and all /// This means the specified Batch was ordered on Serai in relation to Burn events, and all
/// validators have achieved synchrony on it. /// validators have achieved synchrony on it.
/// ///
/// `in_instruction_succeededs` is the result of executing each InInstruction within this batch,
/// true if it succeeded and false if it did not (and did not cause any state changes on Serai).
///
/// `burns` is a list of Burns to queue with the acknowledgement of this Batch for efficiency's /// `burns` is a list of Burns to queue with the acknowledgement of this Batch for efficiency's
/// sake. Any Burns passed here MUST NOT be passed into any other call of `acknowledge_batch` nor /// sake. Any Burns passed here MUST NOT be passed into any other call of `acknowledge_batch` nor
/// `queue_burns`. Doing so will cause them to be executed multiple times. /// `queue_burns`. Doing so will cause them to be executed multiple times.
@ -441,7 +438,7 @@ impl<S: ScannerFeed> Scanner<S> {
&mut self, &mut self,
mut txn: impl DbTxn, mut txn: impl DbTxn,
batch_id: u32, batch_id: u32,
in_instruction_succeededs: Vec<bool>, in_instruction_results: Vec<messages::substrate::InInstructionResult>,
burns: Vec<OutInstructionWithBalance>, burns: Vec<OutInstructionWithBalance>,
key_to_activate: Option<KeyFor<S>>, key_to_activate: Option<KeyFor<S>>,
) { ) {
@ -451,7 +448,7 @@ impl<S: ScannerFeed> Scanner<S> {
substrate::queue_acknowledge_batch::<S>( substrate::queue_acknowledge_batch::<S>(
&mut txn, &mut txn,
batch_id, batch_id,
in_instruction_succeededs, in_instruction_results,
burns, burns,
key_to_activate, key_to_activate,
); );

View file

@ -12,7 +12,7 @@ use crate::{ScannerFeed, KeyFor};
#[derive(BorshSerialize, BorshDeserialize)] #[derive(BorshSerialize, BorshDeserialize)]
struct AcknowledgeBatchEncodable { struct AcknowledgeBatchEncodable {
batch_id: u32, batch_id: u32,
in_instruction_succeededs: Vec<bool>, in_instruction_results: Vec<messages::substrate::InInstructionResult>,
burns: Vec<OutInstructionWithBalance>, burns: Vec<OutInstructionWithBalance>,
key_to_activate: Option<Vec<u8>>, key_to_activate: Option<Vec<u8>>,
} }
@ -25,7 +25,7 @@ enum ActionEncodable {
pub(crate) struct AcknowledgeBatch<S: ScannerFeed> { pub(crate) struct AcknowledgeBatch<S: ScannerFeed> {
pub(crate) batch_id: u32, pub(crate) batch_id: u32,
pub(crate) in_instruction_succeededs: Vec<bool>, pub(crate) in_instruction_results: Vec<messages::substrate::InInstructionResult>,
pub(crate) burns: Vec<OutInstructionWithBalance>, pub(crate) burns: Vec<OutInstructionWithBalance>,
pub(crate) key_to_activate: Option<KeyFor<S>>, pub(crate) key_to_activate: Option<KeyFor<S>>,
} }
@ -46,7 +46,7 @@ impl<S: ScannerFeed> SubstrateDb<S> {
pub(crate) fn queue_acknowledge_batch( pub(crate) fn queue_acknowledge_batch(
txn: &mut impl DbTxn, txn: &mut impl DbTxn,
batch_id: u32, batch_id: u32,
in_instruction_succeededs: Vec<bool>, in_instruction_results: Vec<messages::substrate::InInstructionResult>,
burns: Vec<OutInstructionWithBalance>, burns: Vec<OutInstructionWithBalance>,
key_to_activate: Option<KeyFor<S>>, key_to_activate: Option<KeyFor<S>>,
) { ) {
@ -54,7 +54,7 @@ impl<S: ScannerFeed> SubstrateDb<S> {
txn, txn,
&ActionEncodable::AcknowledgeBatch(AcknowledgeBatchEncodable { &ActionEncodable::AcknowledgeBatch(AcknowledgeBatchEncodable {
batch_id, batch_id,
in_instruction_succeededs, in_instruction_results,
burns, burns,
key_to_activate: key_to_activate.map(|key| key.to_bytes().as_ref().to_vec()), key_to_activate: key_to_activate.map(|key| key.to_bytes().as_ref().to_vec()),
}), }),
@ -69,12 +69,12 @@ impl<S: ScannerFeed> SubstrateDb<S> {
Some(match action_encodable { Some(match action_encodable {
ActionEncodable::AcknowledgeBatch(AcknowledgeBatchEncodable { ActionEncodable::AcknowledgeBatch(AcknowledgeBatchEncodable {
batch_id, batch_id,
in_instruction_succeededs, in_instruction_results,
burns, burns,
key_to_activate, key_to_activate,
}) => Action::AcknowledgeBatch(AcknowledgeBatch { }) => Action::AcknowledgeBatch(AcknowledgeBatch {
batch_id, batch_id,
in_instruction_succeededs, in_instruction_results,
burns, burns,
key_to_activate: key_to_activate.map(|key| { key_to_activate: key_to_activate.map(|key| {
let mut repr = <KeyFor<S> as GroupEncoding>::Repr::default(); let mut repr = <KeyFor<S> as GroupEncoding>::Repr::default();

View file

@ -16,14 +16,14 @@ use db::*;
pub(crate) fn queue_acknowledge_batch<S: ScannerFeed>( pub(crate) fn queue_acknowledge_batch<S: ScannerFeed>(
txn: &mut impl DbTxn, txn: &mut impl DbTxn,
batch_id: u32, batch_id: u32,
in_instruction_succeededs: Vec<bool>, in_instruction_results: Vec<messages::substrate::InInstructionResult>,
burns: Vec<OutInstructionWithBalance>, burns: Vec<OutInstructionWithBalance>,
key_to_activate: Option<KeyFor<S>>, key_to_activate: Option<KeyFor<S>>,
) { ) {
SubstrateDb::<S>::queue_acknowledge_batch( SubstrateDb::<S>::queue_acknowledge_batch(
txn, txn,
batch_id, batch_id,
in_instruction_succeededs, in_instruction_results,
burns, burns,
key_to_activate, key_to_activate,
) )
@ -67,7 +67,7 @@ impl<D: Db, S: ScannerFeed> ContinuallyRan for SubstrateTask<D, S> {
match action { match action {
Action::AcknowledgeBatch(AcknowledgeBatch { Action::AcknowledgeBatch(AcknowledgeBatch {
batch_id, batch_id,
in_instruction_succeededs, in_instruction_results,
mut burns, mut burns,
key_to_activate, key_to_activate,
}) => { }) => {
@ -127,16 +127,16 @@ impl<D: Db, S: ScannerFeed> ContinuallyRan for SubstrateTask<D, S> {
let return_information = report::take_return_information::<S>(&mut txn, batch_id) let return_information = report::take_return_information::<S>(&mut txn, batch_id)
.expect("didn't save the return information for Batch we published"); .expect("didn't save the return information for Batch we published");
assert_eq!( assert_eq!(
in_instruction_succeededs.len(), in_instruction_results.len(),
return_information.len(), return_information.len(),
"amount of InInstruction succeededs differed from amount of return information saved" "amount of InInstruction succeededs differed from amount of return information saved"
); );
// We map these into standard Burns // We map these into standard Burns
for (succeeded, return_information) in for (result, return_information) in
in_instruction_succeededs.into_iter().zip(return_information) in_instruction_results.into_iter().zip(return_information)
{ {
if succeeded { if result == messages::substrate::InInstructionResult::Succeeded {
continue; continue;
} }