Skip to content

Commit 23b61db

Browse files
committed
apollo_batcher: full revert commitment flow
1 parent 50f3ee0 commit 23b61db

File tree

5 files changed

+111
-16
lines changed

5 files changed

+111
-16
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/apollo_batcher/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ apollo_infra_utils.workspace = true
2323
apollo_l1_provider_types.workspace = true
2424
apollo_mempool_types.workspace = true
2525
apollo_metrics.workspace = true
26+
apollo_proc_macros.workspace = true
2627
apollo_reverts.workspace = true
2728
apollo_starknet_client.workspace = true
2829
apollo_state_reader.workspace = true

crates/apollo_batcher/src/batcher.rs

Lines changed: 85 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use apollo_batcher_types::batcher_types::{
2626
use apollo_batcher_types::errors::BatcherError;
2727
use apollo_class_manager_types::transaction_converter::TransactionConverter;
2828
use apollo_class_manager_types::SharedClassManagerClient;
29+
use apollo_committer_types::committer_types::RevertBlockResponse;
2930
use apollo_committer_types::communication::SharedCommitterClient;
3031
use apollo_infra::component_definitions::{default_component_start_fn, ComponentStarter};
3132
use apollo_l1_provider_types::errors::{L1ProviderClientError, L1ProviderError};
@@ -35,7 +36,7 @@ use apollo_mempool_types::mempool_types::CommitBlockArgs;
3536
use apollo_reverts::revert_block;
3637
use apollo_state_sync_types::state_sync_types::SyncBlock;
3738
use apollo_storage::block_hash::{BlockHashStorageReader, BlockHashStorageWriter};
38-
use apollo_storage::global_root::GlobalRootStorageWriter;
39+
use apollo_storage::global_root::{GlobalRootStorageReader, GlobalRootStorageWriter};
3940
use apollo_storage::global_root_marker::{
4041
GlobalRootMarkerStorageReader,
4142
GlobalRootMarkerStorageWriter,
@@ -86,7 +87,11 @@ use crate::commitment_manager::commitment_manager_impl::{
8687
ApolloCommitmentManager,
8788
CommitmentManager,
8889
};
89-
use crate::commitment_manager::types::FinalBlockCommitment;
90+
use crate::commitment_manager::types::{
91+
CommitmentTaskOutput,
92+
FinalBlockCommitment,
93+
RevertTaskOutput,
94+
};
9095
use crate::metrics::{
9196
register_metrics,
9297
ProposalMetricsHandle,
@@ -478,6 +483,7 @@ impl Batcher {
478483
}
479484

480485
/// Clear all the proposals from the previous height.
486+
#[cfg_attr(any(test, feature = "testing"), apollo_proc_macros::make_visibility(pub))]
481487
async fn abort_active_height(&mut self) {
482488
self.abort_active_proposal().await;
483489
self.executed_proposals.lock().await.clear();
@@ -708,7 +714,7 @@ impl Batcher {
708714
.expect("The commitment offset unexpectedly doesn't match the given block height.");
709715

710716
// Write ready commitments to storage.
711-
self.write_commitment_results_to_storage().await?;
717+
self.get_and_write_commitment_results_to_storage().await?;
712718

713719
LAST_SYNCED_BLOCK_HEIGHT.set_lossy(block_number.0);
714720
SYNCED_TRANSACTIONS.increment(
@@ -773,7 +779,7 @@ impl Batcher {
773779
.expect("The commitment offset unexpectedly doesn't match the given block height.");
774780

775781
// Write ready commitments to storage.
776-
self.write_commitment_results_to_storage().await?;
782+
self.get_and_write_commitment_results_to_storage().await?;
777783

778784
let execution_infos = block_execution_artifacts
779785
.execution_data
@@ -1107,6 +1113,9 @@ impl Batcher {
11071113
self.abort_active_height().await;
11081114
}
11091115

1116+
// Wait for the revert commitment to be completed before reverting the storage.
1117+
self.revert_commitment(height).await;
1118+
11101119
self.storage_writer.revert_block(height);
11111120
BUILDING_HEIGHT.decrement(1);
11121121
GLOBAL_ROOT_HEIGHT.decrement(1);
@@ -1156,8 +1165,17 @@ impl Batcher {
11561165
}
11571166

11581167
/// Writes the ready commitment results to storage.
1159-
async fn write_commitment_results_to_storage(&mut self) -> BatcherResult<()> {
1168+
async fn get_and_write_commitment_results_to_storage(&mut self) -> BatcherResult<()> {
11601169
let commitment_results = self.commitment_manager.get_commitment_results().await;
1170+
self.write_commitment_results_to_storage(commitment_results).await?;
1171+
Ok(())
1172+
}
1173+
1174+
/// Writes the given commitment results to storage.
1175+
async fn write_commitment_results_to_storage(
1176+
&mut self,
1177+
commitment_results: Vec<CommitmentTaskOutput>,
1178+
) -> BatcherResult<()> {
11611179
for commitment_task_output in commitment_results.into_iter() {
11621180
let height = commitment_task_output.height;
11631181
info!("Writing commitment results to storage for height {}.", height);
@@ -1217,6 +1235,62 @@ impl Batcher {
12171235
Ok(())
12181236
}
12191237

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

1418+
fn global_root(&self, height: BlockNumber) -> StorageResult<Option<GlobalRoot>>;
1419+
13441420
fn get_state_diff(&self, height: BlockNumber) -> StorageResult<Option<ThinStateDiff>>;
13451421

13461422
/// Returns the state diff that undoes the state diff at the given height.
@@ -1367,6 +1443,10 @@ impl BatcherStorageReader for StorageReader {
13671443
self.begin_ro_txn()?.get_global_root_marker()
13681444
}
13691445

1446+
fn global_root(&self, height: BlockNumber) -> StorageResult<Option<GlobalRoot>> {
1447+
self.begin_ro_txn()?.get_global_root(&height)
1448+
}
1449+
13701450
fn get_state_diff(&self, height: BlockNumber) -> StorageResult<Option<ThinStateDiff>> {
13711451
self.begin_ro_txn()?.get_state_diff(height)
13721452
}

crates/apollo_batcher/src/batcher_test.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ use starknet_api::block::{
4848
use starknet_api::block_hash::block_hash_calculator::PartialBlockHashComponents;
4949
use starknet_api::block_hash::state_diff_hash::calculate_state_diff_hash;
5050
use starknet_api::consensus_transaction::InternalConsensusTransaction;
51-
use starknet_api::core::{ClassHash, CompiledClassHash, Nonce};
51+
use starknet_api::core::{ClassHash, CompiledClassHash, GlobalRoot, Nonce};
5252
use starknet_api::state::ThinStateDiff;
5353
use starknet_api::test_utils::CHAIN_ID_FOR_TESTS;
5454
use starknet_api::transaction::TransactionHash;
@@ -287,6 +287,15 @@ fn mock_create_builder_for_validate_block(
287287
);
288288
}
289289

290+
fn mock_storage_reader_for_revert() -> MockBatcherStorageReader {
291+
let mut storage_reader = MockBatcherStorageReader::new();
292+
storage_reader.expect_reversed_state_diff().returning(|_| Ok(test_state_diff()));
293+
storage_reader.expect_global_root_height().returning(|| Ok(INITIAL_HEIGHT));
294+
storage_reader.expect_global_root().returning(|_| Ok(Some(GlobalRoot::default())));
295+
storage_reader.expect_state_diff_height().returning(|| Ok(INITIAL_HEIGHT));
296+
storage_reader
297+
}
298+
290299
fn mock_create_builder_for_propose_block(
291300
block_builder_factory: &mut MockBlockBuilderFactoryTrait,
292301
output_txs: Vec<InternalConsensusTransaction>,
@@ -777,14 +786,10 @@ async fn multiple_proposals_with_l1_every_n_proposals() {
777786
);
778787
}
779788

780-
let mut storage_writer = MockBatcherStorageWriter::new();
781-
storage_writer.expect_revert_block().times(N_PROPOSALS).returning(|_| ());
782-
783789
let mut l1_provider_client = MockL1ProviderClient::new();
784790
l1_provider_client.expect_start_block().times(N_PROPOSALS).returning(|_, _| Ok(()));
785791

786792
let mock_dependencies = MockDependencies {
787-
storage_writer,
788793
clients: MockClients { block_builder_factory, l1_provider_client, ..Default::default() },
789794
..Default::default()
790795
};
@@ -810,10 +815,7 @@ async fn multiple_proposals_with_l1_every_n_proposals() {
810815
}
811816

812817
batcher.await_active_proposal(DUMMY_FINAL_N_EXECUTED_TXS).await.unwrap();
813-
batcher
814-
.revert_block(RevertBlockInput { height: INITIAL_HEIGHT.prev().unwrap() })
815-
.await
816-
.unwrap();
818+
batcher.abort_active_height().await;
817819
}
818820
}
819821

@@ -1297,14 +1299,17 @@ async fn revert_block() {
12971299
.with(eq(LATEST_BLOCK_IN_STORAGE))
12981300
.returning(|_| ());
12991301

1300-
let mock_dependencies = MockDependencies { storage_writer, ..Default::default() };
1302+
let storage_reader = mock_storage_reader_for_revert();
1303+
let mock_dependencies =
1304+
MockDependencies { storage_reader, storage_writer, ..Default::default() };
13011305

13021306
let mut batcher = create_batcher(mock_dependencies).await;
13031307

13041308
let metrics = recorder.handle().render();
13051309
assert_eq!(BUILDING_HEIGHT.parse_numeric_metric::<u64>(&metrics), Some(INITIAL_HEIGHT.0));
13061310

13071311
let revert_input = RevertBlockInput { height: LATEST_BLOCK_IN_STORAGE };
1312+
13081313
batcher.revert_block(revert_input).await.unwrap();
13091314

13101315
let metrics = recorder.handle().render();

crates/apollo_batcher/src/test_utils.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,8 +276,16 @@ impl Default for MockClients {
276276
(mock_writer, non_working_candidate_tx_sender, non_working_pre_confirmed_tx_sender)
277277
});
278278

279+
let mut committer_client = MockCommitterClient::new();
280+
committer_client
281+
.expect_commit_block()
282+
.returning(|_| Box::pin(async { Ok(CommitBlockResponse::default()) }));
283+
committer_client.expect_revert_block().returning(|_| {
284+
Box::pin(async { Ok(RevertBlockResponse::RevertedTo(GlobalRoot::default())) })
285+
});
286+
279287
Self {
280-
committer_client: MockCommitterClient::new(),
288+
committer_client,
281289
l1_provider_client: MockL1ProviderClient::new(),
282290
mempool_client,
283291
block_builder_factory,

0 commit comments

Comments
 (0)