Skip to content

Commit b86febd

Browse files
central_systest_blobs: implement block production, given txs
1 parent 502ad26 commit b86febd

3 files changed

Lines changed: 119 additions & 13 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
@@ -23,6 +23,7 @@ serde_json.workspace = true
2323
starknet_api = { workspace = true, features = ["testing"] }
2424
starknet_committer = { workspace = true, features = ["testing"] }
2525
starknet_patricia_storage = { workspace = true, features = ["testing"] }
26+
starknet_transaction_prover.workspace = true
2627
tokio.workspace = true
2728

2829
[lints]

crates/central_systest_blobs/src/cende_blob_regression_test.rs

Lines changed: 117 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,18 @@ use apollo_consensus_orchestrator::cende::{
1818
InternalTransactionWithReceipt,
1919
};
2020
use apollo_infra_utils::compile_time_cargo_manifest_dir;
21+
use blockifier::abi::constants::STORED_BLOCK_HASH_BUFFER;
22+
use blockifier::blockifier::config::TransactionExecutorConfig;
23+
use blockifier::blockifier::transaction_executor::TransactionExecutor;
2124
use blockifier::blockifier_versioned_constants::VersionedConstants;
2225
use blockifier::bouncer::BouncerConfig;
2326
use blockifier::context::{BlockContext, ChainInfo};
24-
use blockifier::state::cached_state::{CachedState, StateMaps};
27+
use blockifier::state::cached_state::{CachedState, CommitmentStateDiff, StateMaps};
28+
use blockifier::state::state_api::UpdatableState;
2529
use blockifier::test_utils::contracts::FeatureContractTrait;
2630
use blockifier::test_utils::dict_state_reader::DictStateReader;
2731
use blockifier::transaction::account_transaction::AccountTransaction as BlockifierAccountTx;
32+
use blockifier::transaction::transaction_execution::Transaction as BlockifierTx;
2833
use blockifier::transaction::transactions::ExecutableTransaction;
2934
use blockifier_test_utils::contracts::FeatureContract;
3035
use expect_test::expect_file;
@@ -35,23 +40,30 @@ use google_cloud_storage::http::objects::get::GetObjectRequest;
3540
use google_cloud_storage::http::objects::upload::{Media, UploadObjectRequest, UploadType};
3641
use google_cloud_storage::http::Error as GcsError;
3742
use mockall::predicate::eq;
38-
use starknet_api::block::{BlockHash, BlockInfo, BlockNumber, BlockTimestamp};
39-
use starknet_api::block_hash::block_hash_calculator::PartialBlockHashComponents;
43+
use starknet_api::block::{BlockHash, BlockHashAndNumber, BlockInfo, BlockNumber, BlockTimestamp};
44+
use starknet_api::block_hash::block_hash_calculator::{
45+
calculate_block_commitments,
46+
calculate_block_hash,
47+
PartialBlockHashComponents,
48+
TransactionHashingData,
49+
};
4050
use starknet_api::consensus_transaction::InternalConsensusTransaction;
4151
use starknet_api::contract_address;
4252
use starknet_api::contract_class::compiled_class_hash::HashVersion;
4353
use starknet_api::core::{ChainId, Nonce, OsChainInfo};
44-
use starknet_api::data_availability::DataAvailabilityMode;
54+
use starknet_api::data_availability::{DataAvailabilityMode, L1DataAvailabilityMode};
4555
use starknet_api::executable_transaction::{
4656
AccountTransaction as ExecutableAccountTx,
47-
DeclareTransaction as ExecutableDeclareTransaction,
57+
DeclareTransaction as ExecutableDeclareTx,
58+
Transaction as ExecutableTx,
4859
};
4960
use starknet_api::hash::StateRoots;
5061
use starknet_api::rpc_transaction::{
5162
InternalRpcDeclareTransactionV3,
5263
InternalRpcTransaction,
5364
InternalRpcTransactionWithoutTxHash,
5465
};
66+
use starknet_api::state::ThinStateDiff;
5567
use starknet_api::test_utils::TEST_SEQUENCER_ADDRESS;
5668
use starknet_api::transaction::fields::{
5769
AccountDeploymentData,
@@ -66,9 +78,11 @@ use starknet_api::transaction::{
6678
TransactionOffsetInBlock,
6779
TransactionVersion,
6880
};
81+
use starknet_committer::block_committer::input::StateDiff;
6982
use starknet_committer::db::facts_db::FactsDb;
7083
use starknet_committer::db::forest_trait::StorageInitializer;
7184
use starknet_patricia_storage::map_storage::MapStorage;
85+
use starknet_transaction_prover::running::committer_utils::commit_state_diff;
7286

7387
const GCS_ERROR_CODE_NOT_FOUND: u16 = 404;
7488

@@ -121,7 +135,6 @@ struct BlobFactory {
121135

122136
// Context.
123137
state: DictStateReader,
124-
#[expect(dead_code)]
125138
committer_storage: FactsDb<MapStorage>,
126139
}
127140

@@ -140,13 +153,106 @@ impl BlobFactory {
140153
}
141154

142155
/// Executes the unblocked transactions and applies the changes to the state.
156+
/// Any subsequent transaction added will end up in the next block.
143157
#[expect(dead_code)]
144-
fn close_block(&mut self) {
145-
unimplemented!()
158+
async fn close_block(&mut self) {
159+
let block_context = self.next_block_context();
160+
let block_info = block_context.block_info().clone();
161+
let block_number = block_info.block_number;
162+
163+
// Execute the transactions.
164+
// If the block number is after the block hash buffer, set the previous block hash and
165+
// number, so they appear in the state diff.
166+
let old_block_number_and_hash = if block_number.0 < STORED_BLOCK_HASH_BUFFER {
167+
None
168+
} else {
169+
let old_block_number = block_number.0 - STORED_BLOCK_HASH_BUFFER;
170+
Some(BlockHashAndNumber {
171+
number: BlockNumber(old_block_number),
172+
// If we are past the block hash buffer, this should never panic.
173+
hash: self.blocks[usize::try_from(old_block_number).unwrap()].block_hash,
174+
})
175+
};
176+
let state_clone = self.state.clone();
177+
let mut executor = TransactionExecutor::pre_process_and_create(
178+
state_clone,
179+
block_context.clone(),
180+
old_block_number_and_hash,
181+
TransactionExecutorConfig::create_for_testing(false),
182+
)
183+
.unwrap();
184+
let mut transactions_with_receipts = Vec::new();
185+
// Consume the transactions list (next block starts empty).
186+
for (executable, internal) in std::mem::take(&mut self.next_txs).into_iter() {
187+
let (execution_info, _state_changes) = executor
188+
.execute(&BlockifierTx::new_for_sequencing(ExecutableTx::Account(executable)))
189+
.unwrap();
190+
assert!(!execution_info.is_reverted(), "Got a reverted tx: {execution_info:?}");
191+
192+
transactions_with_receipts
193+
.push(InternalTransactionWithReceipt { transaction: internal, execution_info });
194+
}
195+
let summary = executor.non_consuming_finalize().unwrap();
196+
197+
// Apply changes to state and create the multitude of state-diff-like objects required...
198+
// The [CommitterStateDiff] type is the blockifier representation of the committer's state
199+
// diff, whereas [StateDiff] is the committer's representation of the state diff.
200+
let committer_state_diff: CommitmentStateDiff = summary.state_diff.clone();
201+
let thin_state_diff = ThinStateDiff::from(committer_state_diff.clone());
202+
let state_diff = StateDiff::from(thin_state_diff.clone());
203+
let state_maps = StateMaps::from(committer_state_diff.clone());
204+
let class_mapping = executor.block_state.unwrap().class_hash_to_class.borrow().clone();
205+
self.state.apply_writes(&state_maps, &class_mapping);
206+
207+
// Commit the block.
208+
let prev_state_roots = self.last_finalized_state_roots();
209+
let state_roots = commit_state_diff(
210+
&mut self.committer_storage,
211+
prev_state_roots.contracts_trie_root_hash,
212+
prev_state_roots.classes_trie_root_hash,
213+
state_diff,
214+
)
215+
.await
216+
.expect("Failed to commit state diff.");
217+
218+
// Compute the block hash.
219+
let transaction_hashing_data: Vec<_> = transactions_with_receipts
220+
.iter()
221+
.map(|tx| TransactionHashingData {
222+
transaction_signature: tx.transaction.tx_signature_for_commitment().unwrap(),
223+
transaction_output: tx.execution_info.output_for_hashing(),
224+
transaction_hash: tx.transaction.tx_hash(),
225+
})
226+
.collect();
227+
let (block_header_commitments, _) = calculate_block_commitments(
228+
&transaction_hashing_data,
229+
thin_state_diff,
230+
L1DataAvailabilityMode::from_use_kzg_da(block_info.use_kzg_da),
231+
&block_info.starknet_version,
232+
)
233+
.await;
234+
let partial_block_hash_components =
235+
PartialBlockHashComponents::new(&block_info, block_header_commitments);
236+
let block_hash = calculate_block_hash(
237+
&partial_block_hash_components,
238+
state_roots.global_root(),
239+
self.last_finalized_block_hash(),
240+
)
241+
.unwrap();
242+
243+
// Create and push block data.
244+
self.blocks.push(BlockData {
245+
block_context,
246+
transactions_with_receipts,
247+
partial_block_hash_components,
248+
block_hash,
249+
state_maps,
250+
state_roots,
251+
});
146252
}
147253

148254
/// Creates blobs for all finalized blocks, and a preconfirmed block with the remaining txs that
149-
/// were not included in a block.
255+
/// were not included in a block. See [Self::close_block] for details on how to close a block.
150256
async fn finalize(self) -> (Vec<AerospikeBlob>, CendeWritePreconfirmedBlock) {
151257
// TODO(Dori): Create the blob vector.
152258
let blobs = vec![];
@@ -157,12 +263,10 @@ impl BlobFactory {
157263
(blobs, preconfirmed_block)
158264
}
159265

160-
#[expect(dead_code)]
161266
fn last_finalized_block_hash(&self) -> BlockHash {
162267
self.blocks.last().map(|block| block.block_hash).unwrap_or(BlockHash::GENESIS_PARENT_HASH)
163268
}
164269

165-
#[expect(dead_code)]
166270
fn last_finalized_state_roots(&self) -> StateRoots {
167271
self.blocks.last().map(|block| block.state_roots).unwrap_or_default()
168272
}
@@ -173,7 +277,7 @@ impl BlobFactory {
173277

174278
#[expect(dead_code)]
175279
fn boostrap_declare_tx(&mut self, contract: FeatureContract) {
176-
let sender_address = ExecutableDeclareTransaction::bootstrap_address();
280+
let sender_address = ExecutableDeclareTx::bootstrap_address();
177281
let sierra = contract.get_sierra();
178282
let class_hash = sierra.calculate_class_hash();
179283
let compiled_class_hash = contract.get_compiled_class_hash(&HashVersion::V2);
@@ -203,7 +307,7 @@ impl BlobFactory {
203307
});
204308

205309
// Create executable tx.
206-
let executable = ExecutableDeclareTransaction::create(
310+
let executable = ExecutableDeclareTx::create(
207311
DeclareTransaction::V3(internal_declare_without_hash.into()),
208312
contract.get_class_info(),
209313
&CHAIN_ID,

0 commit comments

Comments
 (0)