diff --git a/coordinator/src/db.rs b/coordinator/src/db.rs index aac6a513..a7edd3cc 100644 --- a/coordinator/src/db.rs +++ b/coordinator/src/db.rs @@ -92,7 +92,7 @@ impl<'a, D: Db> MainDb<'a, D> { } txn.put(key, preprocess); } - pub fn first_preprocess(getter: &G, id: [u8; 32]) -> Vec { - getter.get(Self::first_preprocess_key(id)).expect("asked for first preprocess we never saved") + pub fn first_preprocess(getter: &G, id: [u8; 32]) -> Option> { + getter.get(Self::first_preprocess_key(id)) } } diff --git a/coordinator/src/main.rs b/coordinator/src/main.rs index 221baf7f..e9a89e33 100644 --- a/coordinator/src/main.rs +++ b/coordinator/src/main.rs @@ -694,6 +694,20 @@ pub async fn run( let key = key.clone(); let tributaries = tributaries.clone(); async move { + // SubstrateBlockAck is fired before Preprocess, creating a race between Tributary ack + // of the SubstrateBlock and the sending of all Preprocesses + // A similar race condition exists when multiple Batches are present in a block + // This waits until the necessary preprocess is available + let get_preprocess = |raw_db, id| async move { + loop { + let Some(preprocess) = MainDb::::first_preprocess(raw_db, id) else { + sleep(Duration::from_millis(100)).await; + continue; + }; + return preprocess; + } + }; + let (ids, txs) = match id_type { RecognizedIdType::Block => { let block = id; @@ -704,7 +718,7 @@ pub async fn run( txs.push(Transaction::BatchPreprocess(SignData { plan: *id, attempt: 0, - data: MainDb::::first_preprocess(&raw_db, *id), + data: get_preprocess(&raw_db, *id).await, signed: Transaction::empty_signed(), })); } @@ -716,7 +730,7 @@ pub async fn run( vec![Transaction::SignPreprocess(SignData { plan: id, attempt: 0, - data: MainDb::::first_preprocess(&raw_db, id), + data: get_preprocess(&raw_db, id).await, signed: Transaction::empty_signed(), })], ),