diff --git a/coordinator/src/tributary/db.rs b/coordinator/src/tributary/db.rs index 31ae2e1e..fbcfcc01 100644 --- a/coordinator/src/tributary/db.rs +++ b/coordinator/src/tributary/db.rs @@ -189,6 +189,8 @@ create_db!( // The latest Substrate block to cosign. LatestSubstrateBlockToCosign: (set: ValidatorSet) -> [u8; 32], + // If we're actively cosigning or not. + ActivelyCosigning: (set: ValidatorSet) -> (), // The weight accumulated for a topic. AccumulatedWeight: (set: ValidatorSet, topic: Topic) -> u64, @@ -236,6 +238,33 @@ impl TributaryDb { ) { LatestSubstrateBlockToCosign::set(txn, set, &substrate_block_hash); } + pub(crate) fn actively_cosigning(txn: &mut impl DbTxn, set: ValidatorSet) -> bool { + ActivelyCosigning::get(txn, set).is_some() + } + pub(crate) fn start_cosigning( + txn: &mut impl DbTxn, + set: ValidatorSet, + substrate_block_number: u64, + ) { + assert!( + ActivelyCosigning::get(txn, set).is_none(), + "starting cosigning while already cosigning" + ); + ActivelyCosigning::set(txn, set, &()); + + TributaryDb::recognize_topic( + txn, + set, + Topic::Sign { + id: VariantSignId::Cosign(substrate_block_number), + attempt: 0, + round: SigningProtocolRound::Preprocess, + }, + ); + } + pub(crate) fn finish_cosigning(txn: &mut impl DbTxn, set: ValidatorSet) { + assert!(ActivelyCosigning::take(txn, set).is_some(), "finished cosigning but not cosigning"); + } pub(crate) fn recognize_topic(txn: &mut impl DbTxn, set: ValidatorSet, topic: Topic) { AccumulatedWeight::set(txn, set, topic, &0); diff --git a/coordinator/src/tributary/scan.rs b/coordinator/src/tributary/scan.rs index 1a53bdda..bfc9760b 100644 --- a/coordinator/src/tributary/scan.rs +++ b/coordinator/src/tributary/scan.rs @@ -36,6 +36,34 @@ struct ScanBlock<'a, D: DbTxn, TD: Db> { tributary: &'a TributaryReader, } impl<'a, D: DbTxn, TD: Db> ScanBlock<'a, D, TD> { + fn potentially_start_cosign(&mut self) { + // Don't start a new cosigning instance if we're actively running one + if TributaryDb::actively_cosigning(self.txn, self.set) { + return; + } + + // Start cosigning the latest intended-to-be-cosigned block + let Some(latest_substrate_block_to_cosign) = + TributaryDb::latest_substrate_block_to_cosign(self.txn, self.set) + else { + return; + }; + + let substrate_block_number = todo!("TODO"); + + // Mark us as actively cosigning + TributaryDb::start_cosigning(self.txn, self.set, substrate_block_number); + // Send the message for the processor to start signing + TributaryDb::send_message( + self.txn, + self.set, + messages::coordinator::CoordinatorMessage::CosignSubstrateBlock { + session: self.set.session, + block_number: substrate_block_number, + block: latest_substrate_block_to_cosign, + }, + ); + } fn handle_application_tx(&mut self, block_number: u64, tx: Transaction) { let signer = |signed: Signed| SeraiAddress(signed.signer.to_bytes()); @@ -105,41 +133,25 @@ impl<'a, D: DbTxn, TD: Db> ScanBlock<'a, D, TD> { Transaction::Cosign { substrate_block_hash } => { // Update the latest intended-to-be-cosigned Substrate block TributaryDb::set_latest_substrate_block_to_cosign(self.txn, self.set, substrate_block_hash); - - // TODO: If we aren't currently cosigning a block, start cosigning this one + // Start a new cosign if we weren't already working on one + self.potentially_start_cosign(); } Transaction::Cosigned { substrate_block_hash } => { - // Start cosigning the latest intended-to-be-cosigned block + TributaryDb::finish_cosigning(self.txn, self.set); + + // Fetch the latest intended-to-be-cosigned block let Some(latest_substrate_block_to_cosign) = TributaryDb::latest_substrate_block_to_cosign(self.txn, self.set) else { return; }; - // If this is the block we just cosigned, return + // If this is the block we just cosigned, return, preventing us from signing it again if latest_substrate_block_to_cosign == substrate_block_hash { return; } - let substrate_block_number = todo!("TODO"); - // Whitelist the topic - TributaryDb::recognize_topic( - self.txn, - self.set, - Topic::Sign { - id: VariantSignId::Cosign(substrate_block_number), - attempt: 0, - round: SigningProtocolRound::Preprocess, - }, - ); - // Send the message for the processor to start signing - TributaryDb::send_message( - self.txn, - self.set, - messages::coordinator::CoordinatorMessage::CosignSubstrateBlock { - session: self.set.session, - block_number: substrate_block_number, - block: substrate_block_hash, - }, - ); + + // Since we do have a new cosign to work on, start it + self.potentially_start_cosign(); } Transaction::SubstrateBlock { hash } => { // Whitelist all of the IDs this Substrate block causes to be signed