Skip to content

Commit 8be6ac9

Browse files
authored
Merge pull request #3145 from AleoHQ/gc-on-bootup
Properly set the `gc_round` on `Storage` initialization
2 parents 39fbf98 + f54d3bb commit 8be6ac9

File tree

4 files changed

+101
-0
lines changed

4 files changed

+101
-0
lines changed

node/bft/src/bft.rs

+67
Original file line numberDiff line numberDiff line change
@@ -1226,4 +1226,71 @@ mod tests {
12261226
assert_eq!(result.unwrap_err().to_string(), error_msg);
12271227
Ok(())
12281228
}
1229+
1230+
#[tokio::test]
1231+
#[tracing_test::traced_test]
1232+
async fn test_bft_gc_on_commit() -> Result<()> {
1233+
let rng = &mut TestRng::default();
1234+
1235+
// Initialize the round parameters.
1236+
let max_gc_rounds = 1;
1237+
let committee_round = 0;
1238+
let commit_round = 2;
1239+
let current_round = commit_round + 1;
1240+
1241+
// Sample the certificates.
1242+
let (_, certificates) = snarkvm::ledger::narwhal::batch_certificate::test_helpers::sample_batch_certificate_with_previous_certificates(
1243+
current_round,
1244+
rng,
1245+
);
1246+
1247+
// Initialize the committee.
1248+
let committee = snarkvm::ledger::committee::test_helpers::sample_committee_for_round_and_members(
1249+
committee_round,
1250+
vec![
1251+
certificates[0].author(),
1252+
certificates[1].author(),
1253+
certificates[2].author(),
1254+
certificates[3].author(),
1255+
],
1256+
rng,
1257+
);
1258+
1259+
// Initialize the ledger.
1260+
let ledger = Arc::new(MockLedgerService::new(committee.clone()));
1261+
1262+
// Initialize the storage.
1263+
let transmissions = Arc::new(BFTMemoryService::new());
1264+
let storage = Storage::new(ledger.clone(), transmissions, max_gc_rounds);
1265+
// Insert the certificates into the storage.
1266+
for certificate in certificates.iter() {
1267+
storage.testing_only_insert_certificate_testing_only(certificate.clone());
1268+
}
1269+
1270+
// Get the leader certificate.
1271+
let leader = committee.get_leader(commit_round).unwrap();
1272+
let leader_certificate = storage.get_certificate_for_round_with_author(commit_round, leader).unwrap();
1273+
1274+
// Initialize the BFT.
1275+
let account = Account::new(rng)?;
1276+
let bft = BFT::new(account, storage.clone(), ledger, None, &[], None)?;
1277+
// Insert a mock DAG in the BFT.
1278+
*bft.dag.write() = crate::helpers::dag::test_helpers::mock_dag_with_modified_last_committed_round(commit_round);
1279+
1280+
// Ensure that the `gc_round` has not been updated yet.
1281+
assert_eq!(bft.storage().gc_round(), committee_round.saturating_sub(max_gc_rounds));
1282+
1283+
// Insert the certificates into the BFT.
1284+
for certificate in certificates {
1285+
assert!(bft.update_dag::<false>(certificate).await.is_ok());
1286+
}
1287+
1288+
// Commit the leader certificate.
1289+
bft.commit_leader_certificate::<false, false>(leader_certificate).await.unwrap();
1290+
1291+
// Ensure that the `gc_round` has been updated.
1292+
assert_eq!(bft.storage().gc_round(), commit_round - max_gc_rounds);
1293+
1294+
Ok(())
1295+
}
12291296
}

node/bft/src/helpers/storage.rs

+2
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ impl<N: Network> Storage<N> {
114114
}));
115115
// Update the storage to the current round.
116116
storage.update_current_round(current_round);
117+
// Perform GC on the current round.
118+
storage.garbage_collect_certificates(current_round);
117119
// Return the storage.
118120
storage
119121
}

node/bft/src/sync/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ impl<N: Network> Sync<N> {
212212
self.storage.sync_height_with_block(latest_block.height());
213213
// Sync the round with the block.
214214
self.storage.sync_round_with_block(latest_block.round());
215+
// Perform GC on the latest block round.
216+
self.storage.garbage_collect_certificates(latest_block.round());
215217
// Iterate over the blocks.
216218
for block in &blocks {
217219
// If the block authority is a subdag, then sync the batch certificates with the block.

node/bft/src/worker.rs

+30
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,8 @@ mod tests {
486486

487487
type CurrentNetwork = snarkvm::prelude::MainnetV0;
488488

489+
const ITERATIONS: usize = 100;
490+
489491
mock! {
490492
Gateway<N: Network> {}
491493
#[async_trait]
@@ -868,6 +870,34 @@ mod tests {
868870
assert!(!worker.pending.contains(transmission_id));
869871
assert!(worker.ready.contains(transmission_id));
870872
}
873+
874+
#[tokio::test]
875+
async fn test_storage_gc_on_initialization() {
876+
let rng = &mut TestRng::default();
877+
878+
for _ in 0..ITERATIONS {
879+
// Mock the ledger round.
880+
let max_gc_rounds = rng.gen_range(50..=100);
881+
let latest_ledger_round = rng.gen_range((max_gc_rounds + 1)..1000);
882+
let expected_gc_round = latest_ledger_round - max_gc_rounds;
883+
884+
// Sample a committee.
885+
let committee =
886+
snarkvm::ledger::committee::test_helpers::sample_committee_for_round(latest_ledger_round, rng);
887+
888+
// Setup the mock gateway and ledger.
889+
let mut mock_ledger = MockLedger::default();
890+
mock_ledger.expect_current_committee().returning(move || Ok(committee.clone()));
891+
892+
let ledger: Arc<dyn LedgerService<CurrentNetwork>> = Arc::new(mock_ledger);
893+
// Initialize the storage.
894+
let storage =
895+
Storage::<CurrentNetwork>::new(ledger.clone(), Arc::new(BFTMemoryService::new()), max_gc_rounds);
896+
897+
// Ensure that the storage GC round is correct.
898+
assert_eq!(storage.gc_round(), expected_gc_round);
899+
}
900+
}
871901
}
872902

873903
#[cfg(test)]

0 commit comments

Comments
 (0)