Skip to content

Commit 731f5de

Browse files
starknet_os_runner: fetch base block data
1 parent 790ef0d commit 731f5de

File tree

8 files changed

+90
-45
lines changed

8 files changed

+90
-45
lines changed

Cargo.lock

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

crates/blockifier_reexecution/src/state_reader/rpc_state_reader.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,9 @@ impl Default for RetryConfig {
106106

107107
#[derive(Clone)]
108108
pub struct RpcStateReader {
109-
pub(crate) rpc_state_reader: GatewayRpcStateReader,
109+
pub rpc_state_reader: GatewayRpcStateReader,
110110
pub(crate) retry_config: RetryConfig,
111-
pub(crate) chain_id: ChainId,
111+
pub chain_id: ChainId,
112112
#[allow(dead_code)]
113113
pub(crate) contract_class_mapping_dumper: Arc<Mutex<Option<StarknetContractClassMapping>>>,
114114
}

crates/starknet_os_runner/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ description = "Runs transactions through the Starknet OS and returns Cairo PIE a
1010
cairo_native = ["blockifier/cairo_native"]
1111

1212
[dependencies]
13+
apollo_gateway.workspace = true
1314
async-trait.workspace = true
1415
blockifier.workspace = true
1516
blockifier_reexecution.workspace = true
@@ -18,6 +19,7 @@ cairo-lang-utils.workspace = true
1819
cairo-vm.workspace = true
1920
futures.workspace = true
2021
indexmap.workspace = true
22+
serde_json.workspace = true
2123
shared_execution_objects.workspace = true
2224
starknet-rust.workspace = true
2325
starknet-rust-core.workspace = true

crates/starknet_os_runner/src/errors.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use apollo_gateway::errors::RPCStateReaderError;
12
use blockifier::state::errors::StateError;
23
use blockifier_reexecution::errors::ReexecutionError;
34
use starknet_api::core::ClassHash;
@@ -10,12 +11,14 @@ pub enum VirtualBlockExecutorError {
1011
#[error(transparent)]
1112
// Boxed to reduce the size of Result on the stack (ReexecutionError is >128 bytes).
1213
ReexecutionError(#[from] Box<ReexecutionError>),
13-
1414
#[error("Transaction execution failed: {0}")]
1515
TransactionExecutionError(String),
16-
1716
#[error("Block state unavailable after execution")]
1817
StateUnavailable,
18+
#[error(transparent)]
19+
Serde(#[from] serde_json::Error),
20+
#[error(transparent)]
21+
Rpc(#[from] RPCStateReaderError),
1922
}
2023

2124
#[derive(Debug, Error)]

crates/starknet_os_runner/src/runner.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ pub struct VirtualOsBlockInput {
3333
pub tx_execution_infos: Vec<CentralTransactionExecutionInfo>,
3434
pub block_info: BlockInfo,
3535
pub initial_reads: StateMaps,
36+
pub base_block_hash: BlockHash,
3637
pub prev_base_block_hash: BlockHash,
3738
pub compiled_classes: BTreeMap<CompiledClassHash, CasmContractClass>,
3839
}
@@ -64,7 +65,7 @@ impl From<VirtualOsBlockInput> for StarknetOsInput {
6465
block_info: virtual_os_block_input.block_info,
6566
initial_reads: virtual_os_block_input.initial_reads,
6667
declared_class_hash_to_component_hashes: HashMap::new(),
67-
new_block_hash: BlockHash::default(),
68+
new_block_hash: virtual_os_block_input.base_block_hash,
6869
old_block_number_and_hash: None,
6970
class_hashes_to_migrate: HashMap::new(),
7071
};
@@ -114,7 +115,7 @@ where
114115
)?;
115116

116117
// Extract chain info from block context.
117-
let chain_info = execution_data.block_context.chain_info();
118+
let chain_info = execution_data.base_block_info.block_context.chain_info();
118119
let os_chain_info = OsChainInfo {
119120
chain_id: chain_info.chain_id.clone(),
120121
strk_fee_token_address: chain_info.fee_token_addresses.strk_fee_token_address,
@@ -148,9 +149,10 @@ where
148149
.classes_trie_commitment_info,
149150
transactions: txs,
150151
tx_execution_infos,
151-
block_info: execution_data.block_context.block_info().clone(),
152+
block_info: execution_data.base_block_info.block_context.block_info().clone(),
152153
initial_reads: execution_data.initial_reads,
153-
prev_base_block_hash: execution_data.prev_base_block_hash,
154+
base_block_hash: execution_data.base_block_info.base_block_hash,
155+
prev_base_block_hash: execution_data.base_block_info.prev_base_block_hash,
154156
compiled_classes: classes.compiled_classes,
155157
};
156158

crates/starknet_os_runner/src/storage_proofs_test.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use starknet_types_core::felt::Felt;
1111

1212
use crate::storage_proofs::{RpcStorageProofsProvider, StorageProofProvider};
1313
use crate::test_utils::{rpc_provider, STRK_TOKEN_ADDRESS};
14-
use crate::virtual_block_executor::VirtualBlockExecutionData;
14+
use crate::virtual_block_executor::{BaseBlockInfo, VirtualBlockExecutionData};
1515

1616
/// Fixture: Creates initial reads with the STRK contract and storage slot 0.
1717
#[rstest::fixture]
@@ -44,10 +44,13 @@ fn test_get_storage_proofs_from_rpc(
4444

4545
let execution_data = VirtualBlockExecutionData {
4646
execution_outputs: vec![],
47-
block_context: BlockContext::create_for_account_testing(),
47+
base_block_info: BaseBlockInfo {
48+
block_context: BlockContext::create_for_account_testing(),
49+
base_block_hash: BlockHash::default(),
50+
prev_base_block_hash: BlockHash::default(),
51+
},
4852
initial_reads: state_maps,
4953
executed_class_hashes: HashSet::new(),
50-
prev_base_block_hash: BlockHash::default(),
5154
};
5255

5356
let result = runtime.block_on(async {

crates/starknet_os_runner/src/virtual_block_executor.rs

Lines changed: 66 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
use std::collections::HashSet;
22

3+
use apollo_gateway::rpc_objects::{
4+
BlockHeader,
5+
BlockId as GatewayBlockId,
6+
GetBlockWithTxHashesParams,
7+
};
38
use blockifier::blockifier::config::TransactionExecutorConfig;
49
use blockifier::blockifier::transaction_executor::{
510
TransactionExecutionOutput,
611
TransactionExecutor,
712
};
13+
use blockifier::blockifier_versioned_constants::VersionedConstants;
14+
use blockifier::bouncer::BouncerConfig;
815
use blockifier::context::BlockContext;
916
use blockifier::state::cached_state::{CachedState, StateMaps};
1017
use blockifier::state::contract_class_manager::ContractClassManager;
@@ -14,29 +21,64 @@ use blockifier::state::state_reader_and_contract_manager::{
1421
};
1522
use blockifier::transaction::account_transaction::ExecutionFlags;
1623
use blockifier::transaction::transaction_execution::Transaction as BlockifierTransaction;
17-
use blockifier_reexecution::state_reader::reexecution_state_reader::ReexecutionStateReader;
1824
use blockifier_reexecution::state_reader::rpc_state_reader::RpcStateReader;
19-
use starknet_api::block::{BlockHash, BlockNumber};
25+
use blockifier_reexecution::utils::get_chain_info;
26+
use starknet_api::block::{BlockHash, BlockInfo, BlockNumber};
2027
use starknet_api::core::{ChainId, ClassHash};
2128
use starknet_api::transaction::fields::Fee;
2229
use starknet_api::transaction::{InvokeTransaction, Transaction, TransactionHash};
30+
use starknet_api::versioned_constants_logic::VersionedConstantsTrait;
2331

2432
use crate::errors::VirtualBlockExecutorError;
2533

2634
/// Captures execution data for a virtual block (multiple transactions).
2735
///
2836
/// This struct contains all the execution data needed for proof generation.
37+
pub struct BaseBlockInfo {
38+
pub(crate) block_context: BlockContext,
39+
/// The block hash of the base block,
40+
/// in which the virtual block is executed.
41+
pub(crate) base_block_hash: BlockHash,
42+
/// The block hash of the previous base block.
43+
/// Used to compute the base block hash in the os.
44+
pub(crate) prev_base_block_hash: BlockHash,
45+
}
46+
47+
impl TryFrom<(BlockHeader, ChainId)> for BaseBlockInfo {
48+
type Error = VirtualBlockExecutorError;
49+
50+
fn try_from((header, chain_id): (BlockHeader, ChainId)) -> Result<Self, Self::Error> {
51+
let base_block_hash = header.block_hash;
52+
let prev_base_block_hash = header.parent_hash;
53+
54+
let block_info: BlockInfo = header.try_into()?;
55+
let chain_info = get_chain_info(&chain_id);
56+
let versioned_constants =
57+
VersionedConstants::get(&block_info.starknet_version).map_err(|e| {
58+
VirtualBlockExecutorError::TransactionExecutionError(format!(
59+
"Failed to get versioned constants: {e}"
60+
))
61+
})?;
62+
let block_context = BlockContext::new(
63+
block_info,
64+
chain_info,
65+
versioned_constants.clone(),
66+
BouncerConfig::default(),
67+
);
68+
69+
Ok(BaseBlockInfo { block_context, base_block_hash, prev_base_block_hash })
70+
}
71+
}
72+
2973
pub struct VirtualBlockExecutionData {
3074
/// Execution outputs for all transactions in the virtual block.
3175
pub execution_outputs: Vec<TransactionExecutionOutput>,
32-
/// The block context in which the transactions were executed.
33-
pub block_context: BlockContext,
3476
/// The initial state reads (accessed state) during execution.
3577
pub initial_reads: StateMaps,
3678
/// The class hashes of all contracts executed in the virtual block.
3779
pub executed_class_hashes: HashSet<ClassHash>,
38-
/// The block hash of the state at the start of the virtual block.
39-
pub prev_base_block_hash: BlockHash,
80+
/// The base block info for the virtual block.
81+
pub base_block_info: BaseBlockInfo,
4082
}
4183

4284
/// Executes a virtual block of transactions.
@@ -85,9 +127,8 @@ pub trait VirtualBlockExecutor {
85127
txs: Vec<(InvokeTransaction, TransactionHash)>,
86128
) -> Result<VirtualBlockExecutionData, VirtualBlockExecutorError> {
87129
let blockifier_txs = self.convert_invoke_txs(txs)?;
88-
let block_context = self.block_context(block_number)?;
130+
let base_block_info = self.base_block_info(block_number)?;
89131
let state_reader = self.state_reader(block_number)?;
90-
let prev_base_block_hash = self.prev_base_block_hash(block_number)?;
91132

92133
// Create state reader with contract manager.
93134
let state_reader_and_contract_manager =
@@ -98,7 +139,7 @@ pub trait VirtualBlockExecutor {
98139
// Create executor WITHOUT preprocessing (no pre_process_block call).
99140
let mut transaction_executor = TransactionExecutor::new(
100141
block_state,
101-
block_context.clone(),
142+
base_block_info.block_context.clone(),
102143
TransactionExecutorConfig::default(),
103144
);
104145

@@ -131,10 +172,9 @@ pub trait VirtualBlockExecutor {
131172

132173
Ok(VirtualBlockExecutionData {
133174
execution_outputs,
134-
block_context,
175+
base_block_info,
135176
initial_reads,
136177
executed_class_hashes,
137-
prev_base_block_hash,
138178
})
139179
}
140180

@@ -169,17 +209,12 @@ pub trait VirtualBlockExecutor {
169209
})
170210
.collect()
171211
}
172-
/// Returns the block context for the given block number.
173-
fn block_context(
174-
&self,
175-
block_number: BlockNumber,
176-
) -> Result<BlockContext, VirtualBlockExecutorError>;
177212

178-
/// Returns the block hash of the state at the start of the virtual block.
179-
fn prev_base_block_hash(
213+
/// Returns the base block info for the given block number.
214+
fn base_block_info(
180215
&self,
181216
block_number: BlockNumber,
182-
) -> Result<BlockHash, VirtualBlockExecutorError>;
217+
) -> Result<BaseBlockInfo, VirtualBlockExecutorError>;
183218

184219
/// Returns a state reader that implements `FetchCompiledClasses` for the given block number.
185220
/// Must be `Send + Sync + 'static` to be used in the transaction executor.
@@ -194,6 +229,7 @@ pub trait VirtualBlockExecutor {
194229

195230
#[allow(dead_code)]
196231
pub(crate) struct RpcVirtualBlockExecutor {
232+
/// The state reader for the virtual block executor.
197233
pub rpc_state_reader: RpcStateReader,
198234
/// Whether transaction validation is enabled during execution.
199235
pub validate_txs: bool,
@@ -219,22 +255,19 @@ impl RpcVirtualBlockExecutor {
219255
/// without block preprocessing. Validation and fee charging are always skipped,
220256
/// making it suitable for simulation and OS input generation.
221257
impl VirtualBlockExecutor for RpcVirtualBlockExecutor {
222-
fn block_context(
223-
&self,
224-
_block_number: BlockNumber,
225-
) -> Result<BlockContext, VirtualBlockExecutorError> {
226-
self.rpc_state_reader
227-
.get_block_context()
228-
.map_err(|e| VirtualBlockExecutorError::ReexecutionError(Box::new(e)))
229-
}
230-
231-
fn prev_base_block_hash(
258+
fn base_block_info(
232259
&self,
233260
block_number: BlockNumber,
234-
) -> Result<BlockHash, VirtualBlockExecutorError> {
235-
self.rpc_state_reader
236-
.get_old_block_hash(block_number)
237-
.map_err(|e| VirtualBlockExecutorError::ReexecutionError(Box::new(e)))
261+
) -> Result<BaseBlockInfo, VirtualBlockExecutorError> {
262+
let get_block_params =
263+
GetBlockWithTxHashesParams { block_id: GatewayBlockId::Number(block_number) };
264+
let get_block_with_tx_hashes_result = self
265+
.rpc_state_reader
266+
.rpc_state_reader
267+
.send_rpc_request("starknet_getBlockWithTxHashes", get_block_params)?;
268+
let block_header: BlockHeader = serde_json::from_value(get_block_with_tx_hashes_result)?;
269+
270+
BaseBlockInfo::try_from((block_header, self.rpc_state_reader.chain_id.clone()))
238271
}
239272

240273
fn state_reader(

crates/starknet_os_runner/src/virtual_block_executor_test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ fn test_execute_constructed_balance_of_transaction(
124124

125125
// Verify block context was captured.
126126
assert_eq!(
127-
result.block_context.block_info().block_number,
127+
result.base_block_info.block_context.block_info().block_number,
128128
BlockNumber(TEST_BLOCK_NUMBER),
129129
"Block context should have the correct block number"
130130
);

0 commit comments

Comments
 (0)