Skip to content

Commit 6f48b03

Browse files
central_systest_blobs: refactor skeleton into structured factory
1 parent 42786bd commit 6f48b03

3 files changed

Lines changed: 123 additions & 132 deletions

File tree

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/central_systest_blobs/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ google-cloud-storage.workspace = true
2020
http.workspace = true
2121
serde_json.workspace = true
2222
starknet_api = { workspace = true, features = ["testing"] }
23+
starknet_committer = { workspace = true, features = ["testing"] }
2324
starknet_patricia_storage = { workspace = true, features = ["testing"] }
2425
tokio.workspace = true
2526

crates/central_systest_blobs/src/cende_blob_regression_test.rs

Lines changed: 121 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
use std::path::PathBuf;
2-
use std::sync::{Arc, LazyLock};
2+
use std::sync::LazyLock;
33
use std::{env, fs};
44

55
use apollo_batcher::cende_client_types::{CendeBlockMetadata, CendePreconfirmedBlock};
66
use apollo_batcher::pre_confirmed_cende_client::CendeWritePreconfirmedBlock;
77
use apollo_batcher_types::batcher_types::Round;
8-
use apollo_class_manager_types::{MockClassManagerClient, SharedClassManagerClient};
9-
use apollo_consensus::types::ProposalCommitment;
8+
use apollo_class_manager_types::MockClassManagerClient;
109
use apollo_consensus_orchestrator::cende::{
1110
AerospikeBlob,
1211
BlobParameters,
@@ -26,15 +25,16 @@ use google_cloud_storage::http::objects::download::Range;
2625
use google_cloud_storage::http::objects::get::GetObjectRequest;
2726
use google_cloud_storage::http::objects::upload::{Media, UploadObjectRequest, UploadType};
2827
use google_cloud_storage::http::Error as GcsError;
29-
use starknet_api::block::{BlockHash, BlockHashAndNumber, BlockInfo, BlockNumber, BlockTimestamp};
28+
use starknet_api::block::{BlockHash, BlockInfo, BlockNumber, BlockTimestamp};
3029
use starknet_api::block_hash::block_hash_calculator::PartialBlockHashComponents;
3130
use starknet_api::consensus_transaction::InternalConsensusTransaction;
3231
use starknet_api::contract_address;
3332
use starknet_api::core::{ChainId, OsChainInfo};
3433
use starknet_api::executable_transaction::AccountTransaction as ExecutableAccountTx;
3534
use starknet_api::hash::StateRoots;
36-
use starknet_api::state::ThinStateDiff;
3735
use starknet_api::test_utils::TEST_SEQUENCER_ADDRESS;
36+
use starknet_committer::db::facts_db::FactsDb;
37+
use starknet_committer::db::forest_trait::StorageInitializer;
3838
use starknet_patricia_storage::map_storage::MapStorage;
3939

4040
const GCS_ERROR_CODE_NOT_FOUND: u16 = 404;
@@ -45,11 +45,8 @@ static BLOBS_GENERATION_FILE: LazyLock<PathBuf> = LazyLock::new(|| {
4545
PathBuf::from(compile_time_cargo_manifest_dir!()).join("resources/blob_file_generation")
4646
});
4747

48-
const N_TXS_PER_BLOCK: usize = 1;
4948
static CHAIN_ID: LazyLock<ChainId> =
5049
LazyLock::new(|| ChainId::Other("SN_PREINTEGRATION_SEPOLIA".to_string()));
51-
static CHAIN_INFO: LazyLock<ChainInfo> =
52-
LazyLock::new(|| ChainInfo { chain_id: CHAIN_ID.clone(), ..ChainInfo::create_for_testing() });
5350

5451
const CHAIN_INFO_PATH: &str = "../resources/chain_info.json";
5552
const PRECONFIRMED_BLOCK_PATH: &str = "../resources/preconfirmed_block.json";
@@ -69,145 +66,135 @@ fn blobs_object_path(generation: usize) -> String {
6966
format!("{generation}/{BLOBS_FILE_NAME}")
7067
}
7168

72-
// =====================
73-
// Tx generation
74-
// =====================
75-
7669
#[expect(dead_code)]
77-
fn boostrap_declare_tx(
78-
_class_manager: &mut MockClassManagerClient,
79-
_contract: FeatureContract,
80-
) -> TxPair {
81-
unimplemented!()
70+
struct BlockData {
71+
block_context: BlockContext,
72+
transactions_with_receipts: Vec<InternalTransactionWithReceipt>,
73+
partial_block_hash_components: PartialBlockHashComponents,
74+
block_hash: BlockHash,
75+
state_maps: StateMaps,
76+
state_roots: StateRoots,
8277
}
8378

84-
fn make_txs() -> (MockClassManagerClient, Vec<TxPair>) {
85-
// TODO(Dori): implement.
86-
(MockClassManagerClient::default(), vec![])
87-
}
79+
struct BlobFactory {
80+
chain_info: ChainInfo,
81+
#[expect(dead_code)]
82+
class_manager: MockClassManagerClient,
8883

89-
// =====================
90-
// Data generation
91-
// =====================
84+
// Finalized blocks.
85+
blocks: Vec<BlockData>,
9286

93-
#[expect(dead_code)]
94-
fn make_block_context(block_number: usize) -> BlockContext {
95-
BlockContext::new(
96-
BlockInfo {
97-
block_number: BlockNumber(u64::try_from(block_number).unwrap()),
98-
block_timestamp: BlockTimestamp(1000 + u64::try_from(block_number).unwrap()),
99-
sequencer_address: contract_address!(TEST_SEQUENCER_ADDRESS),
100-
..Default::default()
101-
},
102-
CHAIN_INFO.clone(),
103-
VersionedConstants::create_for_testing(),
104-
BouncerConfig::max(),
105-
)
106-
}
87+
// Transactions for the next block.
88+
#[expect(dead_code)]
89+
next_txs: Vec<TxPair>,
10790

108-
/// Executes the transactions and applies the changes to the state.
109-
#[expect(dead_code)]
110-
fn execute_block(
111-
_state: &mut DictStateReader,
112-
_block_context: &BlockContext,
113-
_old_block_number_and_hash: Option<BlockHashAndNumber>,
114-
_txs: &[TxPair],
115-
) -> (Vec<InternalTransactionWithReceipt>, StateMaps) {
116-
unimplemented!()
91+
// Context.
92+
#[expect(dead_code)]
93+
state: DictStateReader,
94+
#[expect(dead_code)]
95+
committer_storage: FactsDb<MapStorage>,
11796
}
11897

119-
#[expect(dead_code)]
120-
async fn compute_block_hash_components(
121-
_block_info: &BlockInfo,
122-
_state_diff: &ThinStateDiff,
123-
_txs: &[InternalTransactionWithReceipt],
124-
) -> PartialBlockHashComponents {
125-
unimplemented!()
126-
}
98+
impl BlobFactory {
99+
pub fn new() -> Self {
100+
let chain_info =
101+
ChainInfo { chain_id: CHAIN_ID.clone(), ..ChainInfo::create_for_testing() };
102+
Self {
103+
chain_info,
104+
class_manager: MockClassManagerClient::default(),
105+
blocks: vec![],
106+
next_txs: vec![],
107+
state: DictStateReader::default(),
108+
committer_storage: FactsDb::new(MapStorage::default()),
109+
}
110+
}
127111

128-
/// Given previous state and partial components, commits the changes and finalizes the block hash.
129-
/// Returns the block hash, the new state roots and the updated committer storage.
130-
#[expect(dead_code)]
131-
async fn compute_block_commitments(
132-
_committer_storage: MapStorage,
133-
_prev_state_roots: &StateRoots,
134-
_state_maps: &StateMaps,
135-
_block_hash_components: PartialBlockHashComponents,
136-
_prev_block_hash: BlockHash,
137-
) -> (BlockHash, StateRoots, MapStorage) {
138-
unimplemented!()
139-
}
112+
/// Executes the unblocked transactions and applies the changes to the state.
113+
#[expect(dead_code)]
114+
fn close_block(&mut self) {
115+
unimplemented!()
116+
}
140117

141-
/// Creates a blob for the given block.
142-
/// If this is not the first block, also sets the parent proposal commitment and populates the
143-
/// recent block hashes with the last block hash (of the previous block).
144-
/// Returns the current proposal commitment and the block hash components (for use in block hash
145-
/// computation of the current block).
146-
#[expect(dead_code)]
147-
async fn make_blob_parameters(
148-
_block_context: &BlockContext,
149-
_txs_with_exec: Vec<InternalTransactionWithReceipt>,
150-
_state_maps: &StateMaps,
151-
_parent_data: (BlockHash, ProposalCommitment),
152-
) -> (BlobParameters, PartialBlockHashComponents, ProposalCommitment) {
153-
unimplemented!()
154-
}
118+
/// Creates blobs for all finalized blocks, and a preconfirmed block with the remaining txs that
119+
/// were not included in a block.
120+
async fn finalize(self) -> (Vec<AerospikeBlob>, CendeWritePreconfirmedBlock) {
121+
// TODO(Dori): Create the blob vector.
122+
let blobs = vec![];
155123

156-
/// Creates a preconfirmed block for the given block. Should be called for the last block only - no
157-
/// commitment is computed.
158-
fn make_preconfirmed_block(
159-
block_number: usize,
160-
_state: &mut DictStateReader,
161-
_txs: &[TxPair],
162-
) -> CendeWritePreconfirmedBlock {
163-
// TODO(Dori): implement.
164-
CendeWritePreconfirmedBlock {
165-
block_number: BlockNumber(u64::try_from(block_number).unwrap()),
166-
round: Round::default(),
167-
write_iteration: 0,
168-
pre_confirmed_block: CendePreconfirmedBlock {
169-
metadata: CendeBlockMetadata::new(BlockInfo::default()),
170-
transactions: vec![],
171-
transaction_receipts: vec![],
172-
transaction_state_diffs: vec![],
173-
},
124+
// For the last block, create a preconfirmed block.
125+
let preconfirmed_block = self.make_preconfirmed_block_from_remaining_txs();
126+
127+
(blobs, preconfirmed_block)
174128
}
175-
}
176129

177-
/// Given a list of blocks (block number and contents), executes the transactions and creates the
178-
/// blobs.
179-
async fn make_blobs(
180-
_blocks_to_commit: &[(usize, &[TxPair])],
181-
_state: &mut DictStateReader,
182-
_shared_class_manager: SharedClassManagerClient,
183-
) -> Vec<AerospikeBlob> {
184-
// TODO(Dori): implement.
185-
vec![]
186-
}
130+
#[expect(dead_code)]
131+
fn parent_block_hash(&self) -> BlockHash {
132+
self.blocks.last().map(|block| block.block_hash).unwrap_or(BlockHash::GENESIS_PARENT_HASH)
133+
}
187134

188-
/// Generates a fixed set of blob data, and one preconfirmed block, with a deterministic list of
189-
/// transactions.
190-
async fn make_data() -> (Vec<AerospikeBlob>, CendeWritePreconfirmedBlock) {
191-
let (class_manager, transactions) = make_txs();
192-
let shared_class_manager = Arc::new(class_manager);
193-
let mut state = DictStateReader::default();
135+
#[expect(dead_code)]
136+
fn current_state_roots(&self) -> StateRoots {
137+
self.blocks.last().map(|block| block.state_roots).unwrap_or_default()
138+
}
194139

195-
// TODO(Dori): remove this case, it should never happen when the test is done.
196-
if transactions.is_empty() {
197-
(vec![], make_preconfirmed_block(0, &mut state, &[]))
198-
} else {
199-
let block_iterator = transactions.chunks(N_TXS_PER_BLOCK).enumerate().collect::<Vec<_>>();
200-
// Split the block iterator into two iterators: one for the blocks to be committed, and one
201-
// for the last block.
202-
let (blocks_to_commit, last_block) = block_iterator.split_at(block_iterator.len() - 1);
203-
let (last_block_number, last_block_txs) = last_block.last().unwrap();
140+
// =====================
141+
// Tx generation
142+
// =====================
204143

205-
let blobs = make_blobs(blocks_to_commit, &mut state, shared_class_manager.clone()).await;
206-
// For the last block, create a preconfirmed block.
207-
let preconfirmed_block =
208-
make_preconfirmed_block(*last_block_number, &mut state, last_block_txs);
144+
#[expect(dead_code)]
145+
fn boostrap_declare_tx(&mut self, _contract: FeatureContract) {
146+
unimplemented!()
147+
}
209148

210-
(blobs, preconfirmed_block)
149+
// =====================
150+
// Data generation
151+
// =====================
152+
153+
fn next_block_number(&self) -> usize {
154+
self.blocks.len()
155+
}
156+
157+
#[expect(dead_code)]
158+
fn next_block_context(&self) -> BlockContext {
159+
let block_number = BlockNumber(u64::try_from(self.blocks.len()).unwrap());
160+
BlockContext::new(
161+
BlockInfo {
162+
block_number,
163+
block_timestamp: BlockTimestamp(1000 + block_number.0),
164+
sequencer_address: contract_address!(TEST_SEQUENCER_ADDRESS),
165+
..Default::default()
166+
},
167+
self.chain_info.clone(),
168+
VersionedConstants::create_for_testing(),
169+
BouncerConfig::max(),
170+
)
171+
}
172+
173+
/// Creates a blob for the given block.
174+
/// If this is not the first block, also sets the parent proposal commitment and populates the
175+
/// recent block hashes with the last block hash (of the previous block).
176+
/// Returns the current proposal commitment and the block hash components (for use in block hash
177+
/// computation of the current block).
178+
#[expect(dead_code)]
179+
async fn make_blob_parameters(&self, _block: &BlockData) -> BlobParameters {
180+
unimplemented!()
181+
}
182+
183+
/// Creates a preconfirmed block for the given block. Should be called for the last block only -
184+
/// no commitment is computed.
185+
fn make_preconfirmed_block_from_remaining_txs(&self) -> CendeWritePreconfirmedBlock {
186+
// TODO(Dori): implement.
187+
CendeWritePreconfirmedBlock {
188+
block_number: BlockNumber(u64::try_from(self.next_block_number()).unwrap()),
189+
round: Round::default(),
190+
write_iteration: 0,
191+
pre_confirmed_block: CendePreconfirmedBlock {
192+
metadata: CendeBlockMetadata::new(BlockInfo::default()),
193+
transactions: vec![],
194+
transaction_receipts: vec![],
195+
transaction_state_diffs: vec![],
196+
},
197+
}
211198
}
212199
}
213200

@@ -286,8 +273,10 @@ async fn fetch_blob_file(client: &Client) -> Vec<AerospikeBlob> {
286273

287274
#[tokio::test]
288275
async fn test_make_data() {
289-
let (blobs, preconfirmed_block) = make_data().await;
290-
let chain_info = OsChainInfo::from(&*CHAIN_INFO).to_hex_map();
276+
let blob_factory = BlobFactory::new();
277+
let chain_info = OsChainInfo::from(&blob_factory.chain_info).to_hex_map();
278+
// TODO(Dori): create txs.
279+
let (blobs, preconfirmed_block) = blob_factory.finalize().await;
291280
expect_file![CHAIN_INFO_PATH].assert_eq(&serde_json::to_string_pretty(&chain_info).unwrap());
292281
expect_file![PRECONFIRMED_BLOCK_PATH]
293282
.assert_eq(&serde_json::to_string_pretty(&preconfirmed_block).unwrap());

0 commit comments

Comments
 (0)