Skip to content

Commit 6eb2bf5

Browse files
starknet_os_runner: build os input
1 parent 19edbe7 commit 6eb2bf5

File tree

6 files changed

+156
-40
lines changed

6 files changed

+156
-40
lines changed

crates/starknet_os_runner/src/classes_provider.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@ pub trait ClassesProvider {
2121
/// Fetches all classes required for the OS run based on the executed class hashes.
2222
fn get_classes(
2323
&self,
24-
executed_class_hashes: HashSet<ClassHash>,
24+
executed_class_hashes: &HashSet<ClassHash>,
2525
) -> Result<ClassesInput, ClassesProviderError>;
2626
}

crates/starknet_os_runner/src/errors.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,18 @@ pub enum VirtualBlockExecutorError {
1313

1414
#[error("Block state unavailable after execution")]
1515
StateUnavailable,
16+
}
1617

17-
#[error("Unsupported transaction type: only Invoke transactions are supported")]
18-
UnsupportedTransactionType,
18+
#[derive(Debug, Error)]
19+
pub enum RunnerError {
20+
#[error(transparent)]
21+
ClassesProvider(#[from] ClassesProviderError),
22+
#[error(transparent)]
23+
ProofProvider(#[from] ProofProviderError),
24+
#[error(transparent)]
25+
VirtualBlockExecutor(#[from] VirtualBlockExecutorError),
26+
#[error("OS Input generation failed: {0}")]
27+
InputGenerationError(String),
1928
}
2029

2130
#[derive(Debug, Error)]

crates/starknet_os_runner/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
pub mod classes_provider;
22
pub mod errors;
3+
pub mod runner;
34
pub mod storage_proofs;
45
pub mod virtual_block_executor;
56

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
use std::collections::HashMap;
2+
3+
use blockifier::state::contract_class_manager::ContractClassManager;
4+
use starknet_api::block::{BlockHash, BlockNumber};
5+
use starknet_api::block_hash::block_hash_calculator::BlockHeaderCommitments;
6+
use starknet_api::transaction::{InvokeTransaction, TransactionHash};
7+
use starknet_os::io::os_input::{OsBlockInput, StarknetOsInput};
8+
9+
use crate::classes_provider::ClassesProvider;
10+
use crate::errors::RunnerError;
11+
use crate::storage_proofs::StorageProofProvider;
12+
use crate::virtual_block_executor::VirtualBlockExecutor;
13+
14+
pub struct Runner<C, S, V>
15+
where
16+
C: ClassesProvider,
17+
S: StorageProofProvider,
18+
V: VirtualBlockExecutor,
19+
{
20+
pub classes_provider: C,
21+
pub storage_proofs_provider: S,
22+
pub virtual_block_executor: V,
23+
}
24+
25+
impl<C, S, V> Runner<C, S, V>
26+
where
27+
C: ClassesProvider,
28+
S: StorageProofProvider,
29+
V: VirtualBlockExecutor,
30+
{
31+
pub fn new(classes_provider: C, storage_proofs_provider: S, virtual_block_executor: V) -> Self {
32+
Self { classes_provider, storage_proofs_provider, virtual_block_executor }
33+
}
34+
35+
/// Creates the OS input hint required to run the given transactions virtually
36+
/// on top of the given block number.
37+
pub fn create_os_input(
38+
&self,
39+
block_number: BlockNumber,
40+
contract_class_manager: ContractClassManager,
41+
txs: Vec<(InvokeTransaction, TransactionHash)>,
42+
) -> Result<StarknetOsInput, RunnerError> {
43+
// Execute virtual block and get execution data.
44+
let mut execution_data = self.virtual_block_executor.execute(
45+
block_number,
46+
contract_class_manager,
47+
txs.clone(),
48+
)?;
49+
50+
// Fetch classes (consuming executed_class_hashes).
51+
let classes = self.classes_provider.get_classes(&execution_data.executed_class_hashes)?;
52+
53+
// Fetch storage proofs (pass execution_data by reference to avoid moving yet).
54+
let storage_proofs =
55+
self.storage_proofs_provider.get_storage_proofs(block_number, &execution_data)?;
56+
57+
// vert execution outputs to CentralTransactionExecutionInfo (consuming).
58+
let tx_execution_infos =
59+
execution_data.execution_outputs.into_iter().map(|output| output.0.into()).collect();
60+
61+
// Merge initial_reads with proof_state.
62+
execution_data.initial_reads.extend(&storage_proofs.proof_state);
63+
64+
// Assemble OsBlockInput.
65+
let os_block_input = OsBlockInput {
66+
// TODO(Aviv): Add block hash commitments.
67+
block_hash_commitments: BlockHeaderCommitments::default(),
68+
contract_state_commitment_info: storage_proofs
69+
.commitment_infos
70+
.contracts_trie_commitment_info,
71+
address_to_storage_commitment_info: storage_proofs
72+
.commitment_infos
73+
.storage_tries_commitment_infos,
74+
contract_class_commitment_info: storage_proofs
75+
.commitment_infos
76+
.classes_trie_commitment_info,
77+
transactions: txs
78+
.into_iter()
79+
.map(|(invoke_tx, tx_hash)| {
80+
starknet_api::executable_transaction::Transaction::Account(
81+
starknet_api::executable_transaction::AccountTransaction::Invoke(
82+
starknet_api::executable_transaction::InvokeTransaction {
83+
tx: invoke_tx,
84+
tx_hash,
85+
},
86+
),
87+
)
88+
})
89+
.collect(),
90+
tx_execution_infos,
91+
// We assume that no classes are declared.
92+
declared_class_hash_to_component_hashes: HashMap::new(),
93+
// We assume that no classes are migrated.
94+
class_hashes_to_migrate: HashMap::new(),
95+
// Virtual OS does not update the block hash mapping.
96+
old_block_number_and_hash: None,
97+
// Block info and hashes from execution context.
98+
block_info: execution_data.block_context.block_info().clone(),
99+
// TODO(Aviv): Add prev and new block hashes.
100+
prev_block_hash: BlockHash::default(),
101+
new_block_hash: BlockHash::default(),
102+
initial_reads: execution_data.initial_reads,
103+
};
104+
105+
// 7. Final StarknetOsInput (consuming classes).
106+
Ok(StarknetOsInput {
107+
os_block_inputs: vec![os_block_input],
108+
deprecated_compiled_classes: classes.deprecated_compiled_classes,
109+
compiled_classes: classes.compiled_classes,
110+
})
111+
}
112+
}

crates/starknet_os_runner/src/virtual_block_executor.rs

Lines changed: 25 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use blockifier_reexecution::state_reader::rpc_state_reader::RpcStateReader;
1818
use starknet_api::block::BlockNumber;
1919
use starknet_api::core::{ChainId, ClassHash};
2020
use starknet_api::transaction::fields::Fee;
21-
use starknet_api::transaction::{Transaction, TransactionHash};
21+
use starknet_api::transaction::{InvokeTransaction, Transaction, TransactionHash};
2222

2323
use crate::errors::VirtualBlockExecutorError;
2424

@@ -76,12 +76,12 @@ pub trait VirtualBlockExecutor {
7676
/// # Returns
7777
///
7878
/// Returns `VirtualBlockExecutionData` containing execution outputs for all
79-
/// transactions, or an error if any transaction fails or is not an Invoke.
79+
/// transactions, or an error if any transaction fails.
8080
fn execute(
8181
&self,
8282
block_number: BlockNumber,
8383
contract_class_manager: ContractClassManager,
84-
txs: Vec<(Transaction, TransactionHash)>,
84+
txs: Vec<(InvokeTransaction, TransactionHash)>,
8585
) -> Result<VirtualBlockExecutionData, VirtualBlockExecutorError> {
8686
let blockifier_txs = self.convert_invoke_txs(txs)?;
8787
let block_context = self.block_context(block_number)?;
@@ -137,39 +137,32 @@ pub trait VirtualBlockExecutor {
137137

138138
/// Converts Invoke transactions to blockifier transactions.
139139
///
140-
/// Uses execution flags that skip fee charging and nonce check.
141-
/// Returns an error if any transaction is not an Invoke.
140+
/// Uses execution flags that skip strict nonce check for virtual block execution.
142141
fn convert_invoke_txs(
143142
&self,
144-
txs: Vec<(Transaction, TransactionHash)>,
143+
txs: Vec<(InvokeTransaction, TransactionHash)>,
145144
) -> Result<Vec<BlockifierTransaction>, VirtualBlockExecutorError> {
146145
txs.into_iter()
147-
.map(|(tx, tx_hash)| {
148-
if let Transaction::Invoke(invoke_tx) = tx {
149-
// Execute with validation, conditional fee charging based on resource bounds,
150-
// but skip strict nonce check for virtual block execution.
151-
let execution_flags = ExecutionFlags {
152-
only_query: false,
153-
charge_fee: invoke_tx.resource_bounds().max_possible_fee(invoke_tx.tip())
154-
> Fee(0),
155-
validate: self.validate_txs_enabled()?,
156-
strict_nonce_check: false,
157-
};
158-
159-
BlockifierTransaction::from_api(
160-
Transaction::Invoke(invoke_tx),
161-
tx_hash,
162-
None, // class_info - not needed for Invoke.
163-
None, // paid_fee_on_l1 - not needed for Invoke.
164-
None, // deployed_contract_address - not needed for Invoke.
165-
execution_flags,
166-
)
167-
.map_err(|e| {
168-
VirtualBlockExecutorError::TransactionExecutionError(e.to_string())
169-
})
170-
} else {
171-
Err(VirtualBlockExecutorError::UnsupportedTransactionType)
172-
}
146+
.map(|(invoke_tx, tx_hash)| {
147+
// Execute with validation, conditional fee charging based on resource bounds,
148+
// but skip strict nonce check for virtual block execution.
149+
let execution_flags = ExecutionFlags {
150+
only_query: false,
151+
charge_fee: invoke_tx.resource_bounds().max_possible_fee(invoke_tx.tip())
152+
> Fee(0),
153+
validate: self.validate_txs_enabled()?,
154+
strict_nonce_check: false,
155+
};
156+
157+
BlockifierTransaction::from_api(
158+
Transaction::Invoke(invoke_tx),
159+
tx_hash,
160+
None, // class_info - not needed for Invoke.
161+
None, // paid_fee_on_l1 - not needed for Invoke.
162+
None, // deployed_contract_address - not needed for Invoke.
163+
execution_flags,
164+
)
165+
.map_err(|e| VirtualBlockExecutorError::TransactionExecutionError(e.to_string()))
173166
})
174167
.collect()
175168
}

crates/starknet_os_runner/src/virtual_block_executor_test.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use starknet_api::abi::abi_utils::{get_storage_var_address, selector_from_name};
55
use starknet_api::block::BlockNumber;
66
use starknet_api::core::{ChainId, ContractAddress, Nonce};
77
use starknet_api::test_utils::invoke::invoke_tx;
8-
use starknet_api::transaction::{Transaction, TransactionHash};
8+
use starknet_api::transaction::{InvokeTransaction, Transaction, TransactionHash};
99
use starknet_api::{calldata, felt, invoke_tx_args};
1010

1111
use crate::test_utils::{
@@ -20,7 +20,7 @@ use crate::virtual_block_executor::{RpcVirtualBlockExecutor, VirtualBlockExecuto
2020
///
2121
/// Since we skip validation and fee charging, we can use dummy values for signature,
2222
/// nonce, and resource bounds.
23-
fn construct_balance_of_invoke() -> (Transaction, TransactionHash) {
23+
fn construct_balance_of_invoke() -> (InvokeTransaction, TransactionHash) {
2424
let strk_token = ContractAddress::try_from(STRK_TOKEN_ADDRESS).unwrap();
2525
let sender = ContractAddress::try_from(SENDER_ADDRESS).unwrap();
2626

@@ -45,9 +45,10 @@ fn construct_balance_of_invoke() -> (Transaction, TransactionHash) {
4545
nonce: Nonce(felt!("0x1000000")),
4646
});
4747

48-
let tx = Transaction::Invoke(invoke_tx);
49-
let tx_hash = tx.calculate_transaction_hash(&ChainId::Mainnet).unwrap();
50-
(tx, tx_hash)
48+
let tx_hash = Transaction::Invoke(invoke_tx.clone())
49+
.calculate_transaction_hash(&ChainId::Mainnet)
50+
.unwrap();
51+
(invoke_tx, tx_hash)
5152
}
5253

5354
/// Integration test for RpcVirtualBlockExecutor with a constructed transaction.

0 commit comments

Comments
 (0)