Skip to content

Commit 1cdf338

Browse files
committed
apollo_batcher: full revert commitment flow
1 parent 39094bb commit 1cdf338

File tree

2 files changed

+90
-5
lines changed

2 files changed

+90
-5
lines changed

crates/apollo_batcher/src/batcher.rs

Lines changed: 86 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use apollo_batcher_types::batcher_types::{
3030
use apollo_batcher_types::errors::BatcherError;
3131
use apollo_class_manager_types::transaction_converter::TransactionConverter;
3232
use apollo_class_manager_types::SharedClassManagerClient;
33+
use apollo_committer_types::committer_types::RevertBlockResponse;
3334
use apollo_committer_types::communication::SharedCommitterClient;
3435
use apollo_infra::component_definitions::{default_component_start_fn, ComponentStarter};
3536
use apollo_l1_provider_types::errors::{L1ProviderClientError, L1ProviderError};
@@ -39,7 +40,7 @@ use apollo_mempool_types::mempool_types::CommitBlockArgs;
3940
use apollo_reverts::revert_block;
4041
use apollo_state_sync_types::state_sync_types::SyncBlock;
4142
use apollo_storage::block_hash::{BlockHashStorageReader, BlockHashStorageWriter};
42-
use apollo_storage::global_root::GlobalRootStorageWriter;
43+
use apollo_storage::global_root::{GlobalRootStorageReader, GlobalRootStorageWriter};
4344
use apollo_storage::global_root_marker::{
4445
GlobalRootMarkerStorageReader,
4546
GlobalRootMarkerStorageWriter,
@@ -89,7 +90,11 @@ use crate::commitment_manager::commitment_manager_impl::{
8990
ApolloCommitmentManager,
9091
CommitmentManager,
9192
};
92-
use crate::commitment_manager::types::FinalBlockCommitment;
93+
use crate::commitment_manager::types::{
94+
CommitmentTaskOutput,
95+
FinalBlockCommitment,
96+
RevertTaskOutput,
97+
};
9398
use crate::metrics::{
9499
register_metrics,
95100
ProposalMetricsHandle,
@@ -708,7 +713,7 @@ impl Batcher {
708713
.expect("The commitment offset unexpectedly doesn't match the given block height.");
709714

710715
// Write ready commitments to storage.
711-
self.write_commitment_results_to_storage().await?;
716+
self.get_and_write_commitment_results_to_storage().await?;
712717

713718
LAST_SYNCED_BLOCK_HEIGHT.set_lossy(block_number.0);
714719
SYNCED_TRANSACTIONS.increment(
@@ -773,7 +778,7 @@ impl Batcher {
773778
.expect("The commitment offset unexpectedly doesn't match the given block height.");
774779

775780
// Write ready commitments to storage.
776-
self.write_commitment_results_to_storage().await?;
781+
self.get_and_write_commitment_results_to_storage().await?;
777782

778783
let execution_infos = block_execution_artifacts
779784
.execution_data
@@ -1107,6 +1112,9 @@ impl Batcher {
11071112
self.abort_active_height().await;
11081113
}
11091114

1115+
// Wait for the revert commitment to be completed before reverting the storage.
1116+
self.revert_commitment(height).await;
1117+
11101118
self.storage_writer.revert_block(height);
11111119
STORAGE_HEIGHT.decrement(1);
11121120
REVERTED_BLOCKS.increment(1);
@@ -1155,8 +1163,17 @@ impl Batcher {
11551163
}
11561164

11571165
/// Writes the ready commitment results to storage.
1158-
async fn write_commitment_results_to_storage(&mut self) -> BatcherResult<()> {
1166+
async fn get_and_write_commitment_results_to_storage(&mut self) -> BatcherResult<()> {
11591167
let commitment_results = self.commitment_manager.get_commitment_results().await;
1168+
self.write_commitment_results_to_storage(commitment_results).await?;
1169+
Ok(())
1170+
}
1171+
1172+
/// Writes the given commitment results to storage.
1173+
async fn write_commitment_results_to_storage(
1174+
&mut self,
1175+
commitment_results: Vec<CommitmentTaskOutput>,
1176+
) -> BatcherResult<()> {
11601177
for commitment_task_output in commitment_results.into_iter() {
11611178
let height = commitment_task_output.height;
11621179

@@ -1215,6 +1232,64 @@ impl Batcher {
12151232
Ok(())
12161233
}
12171234

1235+
/// Reverts the commitment for the given height.
1236+
/// Adds a revert task to the commitment manager channel and waits for the result.
1237+
/// Writes commitment results to storage and handles the revert task result.
1238+
async fn revert_commitment(&mut self, height: BlockNumber) {
1239+
let reversed_state_diff = self
1240+
.storage_reader
1241+
.reversed_state_diff(height)
1242+
.expect("Failed to get reversed state diff from storage.");
1243+
self.commitment_manager
1244+
.add_revert_task(height, reversed_state_diff)
1245+
.await
1246+
.expect("Failed to add revert task to commitment manager.");
1247+
let (commitment_results, revert_task_result) =
1248+
self.commitment_manager.wait_for_revert_results().await;
1249+
self.write_commitment_results_to_storage(commitment_results)
1250+
.await
1251+
// Consider continuing the revert and not panicking here.
1252+
.expect("Failed to write commitment results to storage.");
1253+
1254+
self.validate_revert_task_result(revert_task_result, height).await;
1255+
self.commitment_manager.decrease_commitment_task_offset();
1256+
info!("Reverted commitment for height {height}.");
1257+
}
1258+
1259+
async fn validate_revert_task_result(
1260+
&self,
1261+
revert_task_output: RevertTaskOutput,
1262+
request_height: BlockNumber,
1263+
) {
1264+
assert_eq!(
1265+
revert_task_output.height, request_height,
1266+
"The task output height does not match the request height."
1267+
);
1268+
1269+
match revert_task_output.response {
1270+
RevertBlockResponse::RevertedTo(global_root)
1271+
| RevertBlockResponse::AlreadyReverted(global_root) => {
1272+
// Verify the global root matches the stored global root.
1273+
let new_latest_height = revert_task_output
1274+
.height
1275+
.prev()
1276+
.expect("Can't revert before the genesis block.");
1277+
let stored_global_root = self
1278+
.storage_reader
1279+
.global_root(new_latest_height)
1280+
// Consider continuing the revert and not panicking here.
1281+
.expect("Failed to get global root from storage.")
1282+
.expect("Global root is not set for height {new_latest_height}.");
1283+
assert_eq!(
1284+
global_root, stored_global_root,
1285+
"The given global root does not match the stored global root for height \
1286+
{new_latest_height}."
1287+
);
1288+
}
1289+
RevertBlockResponse::Uncommitted => {}
1290+
}
1291+
}
1292+
12181293
pub fn get_block_hash(&self, block_number: BlockNumber) -> BatcherResult<BlockHash> {
12191294
self.storage_reader
12201295
.get_block_hash(block_number)
@@ -1336,6 +1411,8 @@ pub trait BatcherStorageReader: Send + Sync {
13361411
/// Returns the first height the committer has finished calculating commitments for.
13371412
fn global_root_height(&self) -> StorageResult<BlockNumber>;
13381413

1414+
fn global_root(&self, height: BlockNumber) -> StorageResult<Option<GlobalRoot>>;
1415+
13391416
fn get_state_diff(&self, height: BlockNumber) -> StorageResult<Option<ThinStateDiff>>;
13401417

13411418
/// Returns the state diff that undoes the state diff at the given height.
@@ -1362,6 +1439,10 @@ impl BatcherStorageReader for StorageReader {
13621439
self.begin_ro_txn()?.get_global_root_marker()
13631440
}
13641441

1442+
fn global_root(&self, height: BlockNumber) -> StorageResult<Option<GlobalRoot>> {
1443+
self.begin_ro_txn()?.get_global_root(&height)
1444+
}
1445+
13651446
fn get_state_diff(&self, height: BlockNumber) -> StorageResult<Option<ThinStateDiff>> {
13661447
self.begin_ro_txn()?.get_state_diff(height)
13671448
}

crates/apollo_batcher/src/commitment_manager/commitment_manager_impl.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,10 @@ impl<S: StateCommitterTrait> CommitmentManager<S> {
211211
self.commitment_task_offset =
212212
self.commitment_task_offset.next().expect("Block number overflowed.");
213213
}
214+
pub(crate) fn decrease_commitment_task_offset(&mut self) {
215+
self.commitment_task_offset =
216+
self.commitment_task_offset.prev().expect("Can't revert before the genesis block.");
217+
}
214218

215219
async fn read_commitment_input_and_add_task<R: BatcherStorageReader>(
216220
&mut self,

0 commit comments

Comments
 (0)