Skip to content

Commit d3164c7

Browse files
starknet_os_flow_tests: generate proof fixtures for the integration tests (#13781)
1 parent 63a0306 commit d3164c7

9 files changed

Lines changed: 127 additions & 18 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.
290 KB
Binary file not shown.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[
2+
"0x50524f4f4630",
3+
"0x5649525455414c5f534e4f53",
4+
"0x3e98c2d7703b03a7edb73ed7f075f97f1dcbaa8f717cdf6e1a57bf058265473",
5+
"0x5649525455414c5f534e4f5330",
6+
"0x0",
7+
"0x3dca758e4b12ec76dae108bd909d6783b3193a427a2f8f7c86d257ac225e384",
8+
"0xa076790848f1f566e0ea5d75fd38cca24de30337471171f480c7f16fe33d42",
9+
"0x0"
10+
]

crates/starknet_os_flow_tests/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ fuzz_test_debug = []
1212
long_fuzz_test = []
1313

1414
[dev-dependencies]
15+
apollo_integration_tests.workspace = true
1516
assert_matches.workspace = true
1617
blockifier = { workspace = true, features = ["reexecution", "testing"] }
1718
blockifier_test_utils.workspace = true

crates/starknet_os_flow_tests/src/test_manager.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -992,6 +992,23 @@ impl TestBuilder<DictStateReader> {
992992
Self::new_with_default_initial_state(extra_contracts, TestBuilderConfig::default(), true)
993993
.await
994994
}
995+
996+
/// Virtual OS builder that overrides the block context.
997+
pub(crate) async fn create_virtual_with_block_info(
998+
block_info: BlockInfo,
999+
config: TestBuilderConfig,
1000+
) -> Self {
1001+
let (mut initial_state_data, []) =
1002+
create_default_initial_state_data::<DictStateReader, 0>([]).await;
1003+
let block_context = &initial_state_data.initial_state.block_context;
1004+
initial_state_data.initial_state.block_context = BlockContext::new(
1005+
block_info,
1006+
block_context.chain_info().clone(),
1007+
block_context.versioned_constants().clone(),
1008+
block_context.bouncer_config.clone(),
1009+
);
1010+
Self::new_with_initial_state_data(initial_state_data, config, true)
1011+
}
9951012
}
9961013

9971014
/// Returns a BlockContext of the given block number with the with the STRK fee token address that

crates/starknet_os_flow_tests/src/virtual_os_test.rs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::path::Path;
2+
13
use blockifier::execution::contract_class::TrackedResource;
24
use blockifier::test_utils::dict_state_reader::DictStateReader;
35
use blockifier::test_utils::get_valid_virtual_os_program_hash;
@@ -7,7 +9,7 @@ use blockifier_test_utils::calldata::create_calldata;
79
use blockifier_test_utils::contracts::FeatureContract;
810
use rstest::rstest;
911
use starknet_api::abi::abi_utils::selector_from_name;
10-
use starknet_api::block::BlockTimestamp;
12+
use starknet_api::block::{BlockInfo, BlockNumber, BlockTimestamp};
1113
use starknet_api::core::EthAddress;
1214
use starknet_api::test_utils::{CURRENT_BLOCK_TIMESTAMP, TEST_SEQUENCER_ADDRESS};
1315
use starknet_api::transaction::fields::{ProofFacts, TransactionSignature};
@@ -271,3 +273,38 @@ async fn test_reverted_tx_os_error() {
271273
.await
272274
.run_virtual_expect_error("Reverted transactions are not supported in virtual OS mode");
273275
}
276+
277+
/// Generates proof fixtures for the proof-flow integration test.
278+
/// To run manually: `cargo +nightly-2025-07-14 test -p starknet_os_flow_tests --features
279+
/// starknet_transaction_prover/stwo_proving --release generate_proof_fixtures -- --ignored`
280+
#[tokio::test(flavor = "multi_thread")]
281+
#[ignore]
282+
async fn generate_proof_fixtures() {
283+
let block_info = BlockInfo {
284+
block_number: BlockNumber(0),
285+
block_timestamp: BlockTimestamp(0),
286+
..BlockInfo::create_for_testing()
287+
};
288+
let mut test_builder = TestBuilder::<DictStateReader>::create_virtual_with_block_info(
289+
block_info,
290+
TestBuilderConfig::default(),
291+
)
292+
.await;
293+
294+
test_builder.add_fund_address_tx_with_default_amount(*FUNDED_ACCOUNT_ADDRESS);
295+
296+
let test_runner = test_builder.build().await;
297+
let output = test_runner.run_virtual().prove().await;
298+
299+
let fixtures_dir = Path::new(env!("CARGO_MANIFEST_DIR"))
300+
.join("../apollo_integration_tests/resources/proof_flow");
301+
std::fs::create_dir_all(&fixtures_dir).expect("create proof_flow dir");
302+
let proof_facts_path = fixtures_dir.join("proof_facts.json");
303+
let proof_path = fixtures_dir.join("proof.bin");
304+
std::fs::write(
305+
&proof_facts_path,
306+
serde_json::to_string_pretty(&output.proof_facts).expect("serialize proof_facts"),
307+
)
308+
.expect("write proof_facts.json");
309+
std::fs::write(&proof_path, output.proof.0.as_slice()).expect("write proof.bin");
310+
}

crates/starknet_os_flow_tests/src/virtual_os_test_manager.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
use starknet_api::transaction::fields::VIRTUAL_OS_OUTPUT_VERSION;
2+
use starknet_api::transaction::MessageToL1;
23
use starknet_os::io::virtual_os_output::{
34
compute_messages_to_l1_hashes,
45
VirtualOsOutput,
56
VirtualOsRunnerOutput,
67
};
78
use starknet_os::runner::run_virtual_os;
9+
use starknet_transaction_prover::proving::virtual_snos_prover::{
10+
prove_virtual_snos_run,
11+
ProveTransactionResult,
12+
};
13+
use starknet_transaction_prover::running::runner::RunnerOutput;
814

915
use crate::initial_state::FlowTestState;
1016
use crate::test_manager::TestRunner;
@@ -15,6 +21,8 @@ pub(crate) struct VirtualOsTestOutput {
1521
pub(crate) runner_output: VirtualOsRunnerOutput,
1622
/// The expected values computed from the OS hints.
1723
pub(crate) expected_virtual_os_output: VirtualOsOutput,
24+
/// The messages sent from L2 to L1 during execution.
25+
pub(crate) messages_to_l1: Vec<MessageToL1>,
1826
// TODO(Yoni): consider adding more data for sanity checks, such as the expected state diff.
1927
}
2028

@@ -26,6 +34,13 @@ impl VirtualOsTestOutput {
2634

2735
assert_eq!(virtual_os_output, self.expected_virtual_os_output);
2836
}
37+
pub(crate) async fn prove(self) -> ProveTransactionResult {
38+
let runner_output = RunnerOutput {
39+
cairo_pie: self.runner_output.cairo_pie,
40+
l2_to_l1_messages: self.messages_to_l1,
41+
};
42+
prove_virtual_snos_run(runner_output).await.expect("Proving virtual OS should not fail.")
43+
}
2944
}
3045

3146
impl<S: FlowTestState> TestRunner<S> {
@@ -38,6 +53,7 @@ impl<S: FlowTestState> TestRunner<S> {
3853
self.os_hints.os_hints_config.chain_info.compute_virtual_os_config_hash().unwrap();
3954

4055
let messages_to_l1_hashes = compute_messages_to_l1_hashes(&self.messages_to_l1);
56+
let messages_to_l1 = self.messages_to_l1;
4157
let expected_virtual_os_output = VirtualOsOutput {
4258
version: VIRTUAL_OS_OUTPUT_VERSION,
4359
base_block_number: first_block.block_info.block_number,
@@ -50,7 +66,7 @@ impl<S: FlowTestState> TestRunner<S> {
5066
let runner_output =
5167
run_virtual_os(self.os_hints).expect("Running virtual OS should not fail.");
5268

53-
VirtualOsTestOutput { runner_output, expected_virtual_os_output }
69+
VirtualOsTestOutput { runner_output, expected_virtual_os_output, messages_to_l1 }
5470
}
5571

5672
/// Runs the virtual OS and validates the output against expected values.

crates/starknet_transaction_prover/src/proving/virtual_snos_prover.rs

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub struct ProveTransactionResult {
4747
/// The prover is generic over the runner, allowing different implementations
4848
/// (RPC-based, mock, etc.) to be used interchangeably.
4949
#[derive(Clone)]
50-
pub(crate) struct VirtualSnosProver<R: VirtualSnosRunner> {
50+
pub struct VirtualSnosProver<R: VirtualSnosRunner> {
5151
/// Runner for executing the virtual OS.
5252
runner: R,
5353
/// Whether to validate that fee-related fields (resource bounds, tip) are zero.
@@ -60,7 +60,7 @@ pub(crate) struct VirtualSnosProver<R: VirtualSnosRunner> {
6060
}
6161

6262
/// Type alias for the RPC-based virtual SNOS prover.
63-
pub(crate) type RpcVirtualSnosProver = VirtualSnosProver<RpcRunnerFactory>;
63+
pub type RpcVirtualSnosProver = VirtualSnosProver<RpcRunnerFactory>;
6464

6565
impl VirtualSnosProver<RpcRunnerFactory> {
6666
/// Creates a new VirtualSnosProver from configuration.
@@ -292,24 +292,51 @@ impl<R: VirtualSnosRunner + 'static> VirtualSnosProver<R> {
292292
/// Generates a proof from the given [`RunnerOutput`] and converts the program output into
293293
/// proof facts.
294294
#[cfg(feature = "stwo_proving")]
295-
async fn prove_virtual_snos_run(
295+
pub async fn prove_virtual_snos_run(
296296
&self,
297297
runner_output: RunnerOutput,
298298
) -> Result<ProveTransactionResult, VirtualSnosProverError> {
299-
use starknet_api::transaction::fields::VIRTUAL_SNOS;
299+
prove_virtual_snos_run_with_precomputes(runner_output, self.precomputes.clone()).await
300+
}
301+
}
302+
303+
/// Proves a Virtual Starknet OS run fdirectly from a `RunnerOutput`.
304+
#[cfg(feature = "stwo_proving")]
305+
pub async fn prove_virtual_snos_run(
306+
runner_output: RunnerOutput,
307+
) -> Result<ProveTransactionResult, VirtualSnosProverError> {
308+
let precomputes = prepare_recursive_prover_precomputes()
309+
.expect("Failed to prepare recursive prover precomputes");
310+
prove_virtual_snos_run_with_precomputes(runner_output, precomputes).await
311+
}
300312

301-
use crate::proving::prover::prove;
313+
#[cfg(not(feature = "stwo_proving"))]
314+
pub async fn prove_virtual_snos_run(
315+
_runner_output: RunnerOutput,
316+
) -> Result<ProveTransactionResult, VirtualSnosProverError> {
317+
unimplemented!(
318+
"In-memory proving requires the `stwo_proving` feature flag and a nightly Rust toolchain."
319+
);
320+
}
321+
322+
#[cfg(feature = "stwo_proving")]
323+
async fn prove_virtual_snos_run_with_precomputes(
324+
runner_output: RunnerOutput,
325+
precomputes: Arc<RecursiveProverPrecomputes>,
326+
) -> Result<ProveTransactionResult, VirtualSnosProverError> {
327+
use starknet_api::transaction::fields::VIRTUAL_SNOS;
302328

303-
let prover_output = prove(runner_output.cairo_pie, self.precomputes.clone()).await?;
304-
// Convert program output to proof facts using VIRTUAL_SNOS variant marker.
305-
let proof_facts = prover_output.program_output.try_into_proof_facts(VIRTUAL_SNOS)?;
329+
use crate::proving::prover::prove;
306330

307-
Ok(ProveTransactionResult {
308-
proof: prover_output.proof,
309-
proof_facts,
310-
l2_to_l1_messages: runner_output.l2_to_l1_messages,
311-
})
312-
}
331+
let prover_output = prove(runner_output.cairo_pie, precomputes).await?;
332+
// Convert program output to proof facts using VIRTUAL_SNOS variant marker.
333+
let proof_facts = prover_output.program_output.try_into_proof_facts(VIRTUAL_SNOS)?;
334+
335+
Ok(ProveTransactionResult {
336+
proof: prover_output.proof,
337+
proof_facts,
338+
l2_to_l1_messages: runner_output.l2_to_l1_messages,
339+
})
313340
}
314341

315342
/// Extracts the RPC Invoke V3 transaction, rejecting other transaction types.

crates/starknet_transaction_prover/src/running/runner.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ where
338338
/// allowing different runner implementations (RPC-based, mock, etc.) to be used
339339
/// interchangeably.
340340
#[async_trait]
341-
pub(crate) trait VirtualSnosRunner: Clone + Send + Sync {
341+
pub trait VirtualSnosRunner: Clone + Send + Sync {
342342
/// Runs the Starknet virtual OS with the given transactions on top of the specified block.
343343
async fn run_virtual_os(
344344
&self,
@@ -379,7 +379,7 @@ pub(crate) type RpcRunner = Runner<
379379
/// let output = runner.run_virtual_os(txs).await?;
380380
/// ```
381381
#[derive(Clone)]
382-
pub(crate) struct RpcRunnerFactory {
382+
pub struct RpcRunnerFactory {
383383
/// URL of the RPC node.
384384
node_url: Url,
385385
chain_info: ChainInfo,

0 commit comments

Comments
 (0)