Skip to content

Commit 625686c

Browse files
frisitanogreged93
andauthored
fix: database prepare on startup (#341)
* fix database prepare on startup * Update crates/database/db/src/db.rs Co-authored-by: greg <[email protected]> * Update crates/database/db/src/operations.rs Co-authored-by: greg <[email protected]> * fmt --------- Co-authored-by: greg <[email protected]>
1 parent d95e959 commit 625686c

File tree

2 files changed

+102
-12
lines changed

2 files changed

+102
-12
lines changed

crates/database/db/src/db.rs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -869,4 +869,96 @@ mod test {
869869
assert_eq!(updated_block_info, block_info);
870870
assert_eq!(updated_batch_info, batch_info_2);
871871
}
872+
873+
#[tokio::test]
874+
async fn test_prepare_on_startup() {
875+
let db = setup_test_db().await;
876+
let tx = db.tx_mut().await.unwrap();
877+
878+
// Generate unstructured bytes.
879+
let mut bytes = [0u8; 1024];
880+
rand::rng().fill(bytes.as_mut_slice());
881+
let mut u = Unstructured::new(&bytes);
882+
883+
// Insert batch 1 and associate it with two blocks in the database
884+
let batch_data_1 =
885+
BatchCommitData { index: 1, block_number: 10, ..Arbitrary::arbitrary(&mut u).unwrap() };
886+
let block_1 = L2BlockInfoWithL1Messages {
887+
block_info: BlockInfo { number: 1, hash: B256::arbitrary(&mut u).unwrap() },
888+
l1_messages: vec![],
889+
};
890+
let block_2 = L2BlockInfoWithL1Messages {
891+
block_info: BlockInfo { number: 2, hash: B256::arbitrary(&mut u).unwrap() },
892+
l1_messages: vec![],
893+
};
894+
tx.insert_batch(batch_data_1.clone()).await.unwrap();
895+
tx.insert_block(block_1.clone(), batch_data_1.clone().into()).await.unwrap();
896+
tx.insert_block(block_2.clone(), batch_data_1.clone().into()).await.unwrap();
897+
898+
// Insert batch 2 and associate it with one block in the database
899+
let batch_data_2 =
900+
BatchCommitData { index: 2, block_number: 20, ..Arbitrary::arbitrary(&mut u).unwrap() };
901+
let block_3 = L2BlockInfoWithL1Messages {
902+
block_info: BlockInfo { number: 3, hash: B256::arbitrary(&mut u).unwrap() },
903+
l1_messages: vec![],
904+
};
905+
tx.insert_batch(batch_data_2.clone()).await.unwrap();
906+
tx.insert_block(block_3.clone(), batch_data_2.clone().into()).await.unwrap();
907+
908+
// Insert batch 3 produced at the same block number as batch 2 and associate it with one
909+
// block
910+
let batch_data_3 =
911+
BatchCommitData { index: 3, block_number: 20, ..Arbitrary::arbitrary(&mut u).unwrap() };
912+
let block_4 = L2BlockInfoWithL1Messages {
913+
block_info: BlockInfo { number: 4, hash: B256::arbitrary(&mut u).unwrap() },
914+
l1_messages: vec![],
915+
};
916+
tx.insert_batch(batch_data_3.clone()).await.unwrap();
917+
tx.insert_block(block_4.clone(), batch_data_3.clone().into()).await.unwrap();
918+
919+
tx.set_latest_finalized_l1_block_number(21).await.unwrap();
920+
tx.commit().await.unwrap();
921+
922+
// Verify the batches and blocks were inserted correctly
923+
let tx = db.tx().await.unwrap();
924+
let retrieved_batch_1 = tx.get_batch_by_index(1).await.unwrap().unwrap();
925+
let retrieved_batch_2 = tx.get_batch_by_index(2).await.unwrap().unwrap();
926+
let retrieved_batch_3 = tx.get_batch_by_index(3).await.unwrap().unwrap();
927+
let retried_block_1 = tx.get_l2_block_info_by_number(1).await.unwrap().unwrap();
928+
let retried_block_2 = tx.get_l2_block_info_by_number(2).await.unwrap().unwrap();
929+
let retried_block_3 = tx.get_l2_block_info_by_number(3).await.unwrap().unwrap();
930+
let retried_block_4 = tx.get_l2_block_info_by_number(4).await.unwrap().unwrap();
931+
drop(tx);
932+
933+
assert_eq!(retrieved_batch_1, batch_data_1);
934+
assert_eq!(retrieved_batch_2, batch_data_2);
935+
assert_eq!(retrieved_batch_3, batch_data_3);
936+
assert_eq!(retried_block_1, block_1.block_info);
937+
assert_eq!(retried_block_2, block_2.block_info);
938+
assert_eq!(retried_block_3, block_3.block_info);
939+
assert_eq!(retried_block_4, block_4.block_info);
940+
941+
// Call prepare_on_startup which should not error
942+
let tx = db.tx_mut().await.unwrap();
943+
let result = tx.prepare_on_startup(Default::default()).await.unwrap();
944+
tx.commit().await.unwrap();
945+
946+
// verify the result
947+
assert_eq!(result, (Some(block_2.block_info), Some(11)));
948+
949+
// Verify that batches 2 and 3 are deleted
950+
let tx = db.tx().await.unwrap();
951+
let batch_1 = tx.get_batch_by_index(1).await.unwrap();
952+
let batch_2 = tx.get_batch_by_index(2).await.unwrap();
953+
let batch_3 = tx.get_batch_by_index(3).await.unwrap();
954+
assert!(batch_1.is_some());
955+
assert!(batch_2.is_none());
956+
assert!(batch_3.is_none());
957+
958+
// Verify that blocks 3 and 4 are deleted
959+
let retried_block_3 = tx.get_l2_block_info_by_number(3).await.unwrap();
960+
let retried_block_4 = tx.get_l2_block_info_by_number(4).await.unwrap();
961+
assert!(retried_block_3.is_none());
962+
assert!(retried_block_4.is_none());
963+
}
872964
}

crates/database/db/src/operations.rs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -205,25 +205,23 @@ pub trait DatabaseWriteOperations: WriteConnectionProvider + DatabaseReadOperati
205205

206206
// Delete all unprocessed batches from the database and return starting l2 safe head and l1
207207
// head.
208-
let safe = if let Some(batch_info) = self
208+
if let Some(batch_info) = self
209209
.get_latest_safe_l2_info()
210210
.await?
211211
.map(|(_, batch_info)| batch_info)
212212
.filter(|b| b.index > 1)
213213
{
214-
let previous_batch_index = batch_info.index - 1;
215-
let previous_batch = self
216-
.get_batch_by_index(previous_batch_index)
217-
.await?
218-
.expect("Batch info must be present due to database query arguments");
219-
self.delete_batches_gt_batch_index(previous_batch_index).await?;
220-
let l2_block = self.get_highest_block_for_batch_hash(previous_batch.hash).await?;
221-
(l2_block, Some(previous_batch.block_number))
222-
} else {
223-
(None, None)
214+
let batch = self.get_batch_by_index(batch_info.index).await?.expect("batch must exist");
215+
self.delete_batches_gt_block_number(batch.block_number.saturating_sub(1)).await?;
224216
};
225217

226-
Ok(safe)
218+
let Some((block_info, batch_info)) =
219+
self.get_latest_safe_l2_info().await?.filter(|(block_info, _)| block_info.number > 0)
220+
else {
221+
return Ok((None, None))
222+
};
223+
let batch = self.get_batch_by_index(batch_info.index).await?.expect("batch must exist");
224+
Ok((Some(block_info), Some(batch.block_number.saturating_add(1))))
227225
}
228226

229227
/// Delete all L2 blocks with a block number greater than the provided block number.

0 commit comments

Comments
 (0)