11use std:: path:: PathBuf ;
2- use std:: sync:: { Arc , LazyLock } ;
2+ use std:: sync:: LazyLock ;
33use std:: { env, fs} ;
44
55use apollo_batcher:: cende_client_types:: { CendeBlockMetadata , CendePreconfirmedBlock } ;
66use apollo_batcher:: pre_confirmed_cende_client:: CendeWritePreconfirmedBlock ;
77use 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 ;
109use apollo_consensus_orchestrator:: cende:: {
1110 AerospikeBlob ,
1211 BlobParameters ,
@@ -26,15 +25,16 @@ use google_cloud_storage::http::objects::download::Range;
2625use google_cloud_storage:: http:: objects:: get:: GetObjectRequest ;
2726use google_cloud_storage:: http:: objects:: upload:: { Media , UploadObjectRequest , UploadType } ;
2827use 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 } ;
3029use starknet_api:: block_hash:: block_hash_calculator:: PartialBlockHashComponents ;
3130use starknet_api:: consensus_transaction:: InternalConsensusTransaction ;
3231use starknet_api:: contract_address;
3332use starknet_api:: core:: { ChainId , OsChainInfo } ;
3433use starknet_api:: executable_transaction:: AccountTransaction as ExecutableAccountTx ;
3534use starknet_api:: hash:: StateRoots ;
36- use starknet_api:: state:: ThinStateDiff ;
3735use starknet_api:: test_utils:: TEST_SEQUENCER_ADDRESS ;
36+ use starknet_committer:: db:: facts_db:: FactsDb ;
37+ use starknet_committer:: db:: forest_trait:: StorageInitializer ;
3838use starknet_patricia_storage:: map_storage:: MapStorage ;
3939
4040const 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 ;
4948static 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
5451const CHAIN_INFO_PATH : & str = "../resources/chain_info.json" ;
5552const 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 last_finalized_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 last_finalized_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]
288275async 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