Skip to content

Commit d4c57ba

Browse files
author
3alpha
committed
Ensure that proof and proof facts differ for different blocks
1 parent da1c112 commit d4c57ba

3 files changed

Lines changed: 85 additions & 3 deletions

File tree

‎crates/starknet-devnet-core/src/starknet/proofs.rs‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,12 @@ pub fn generate_proof(
7777

7878
debug!("Computed invoke transaction hash for proof generation: {tx_hash:#x}");
7979

80-
let proof_felt = Pedersen::hash_array(&[tx_hash, DEVNET_PROOF_MAGIC.into(), messages_hash]);
80+
let proof_felt = Pedersen::hash_array(&[
81+
block.block_hash(),
82+
tx_hash,
83+
DEVNET_PROOF_MAGIC.into(),
84+
messages_hash,
85+
]);
8186
let proof = felt_to_proof(proof_felt);
8287

8388
let last_field = Pedersen::hash_array(&[

‎tests/integration/common/background_devnet.rs‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,9 +270,10 @@ impl BackgroundDevnet {
270270
}
271271
}
272272

273-
pub async fn prove_transaction(
273+
pub async fn prove_transaction_at_block(
274274
&self,
275275
transaction: BroadcastedInvokeTransaction,
276+
block_id: BlockId,
276277
) -> ProveTransactionResult {
277278
let mut transaction = serde_json::to_value(transaction)
278279
.expect("Failed to serialize transaction for proveTransaction");
@@ -286,7 +287,7 @@ impl BackgroundDevnet {
286287
.send_custom_rpc(
287288
"starknet_proveTransaction",
288289
json!({
289-
"block_id": "latest",
290+
"block_id": serde_json::to_value(block_id).expect("Failed to serialize block_id"),
290291
"transaction": transaction
291292
}),
292293
)
@@ -345,6 +346,13 @@ impl BackgroundDevnet {
345346
}
346347
}
347348

349+
pub async fn prove_transaction(
350+
&self,
351+
transaction: BroadcastedInvokeTransaction,
352+
) -> ProveTransactionResult {
353+
self.prove_transaction_at_block(transaction, BlockId::Tag(BlockTag::Latest)).await
354+
}
355+
348356
pub fn clone_provider(&self) -> JsonRpcClient<HttpTransport> {
349357
JsonRpcClient::new(HttpTransport::new(self.rpc_url.clone()))
350358
}

‎tests/integration/prove_transaction.rs‎

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,75 @@ async fn prove_transaction_is_deterministic() {
397397
);
398398
}
399399

400+
#[tokio::test]
401+
async fn prove_transaction_differs_on_different_block_ids() {
402+
let devnet = BackgroundDevnet::spawn_forkable_devnet()
403+
.await
404+
.expect("Could not start Devnet with full state archive");
405+
406+
// First, create at least 15 blocks to ensure we have sufficient chain history
407+
for _ in 0..15 {
408+
devnet.create_block().await.unwrap();
409+
}
410+
411+
let (signer, account_address) = devnet.get_first_predeployed_account().await;
412+
let mut account = SingleOwnerAccount::new(
413+
&devnet.json_rpc_client,
414+
signer,
415+
account_address,
416+
constants::CHAIN_ID,
417+
ExecutionEncoding::New,
418+
);
419+
account.set_block_id(BlockId::Tag(BlockTag::Latest));
420+
421+
let calls = vec![transfer_call(Felt::ONE, Felt::from(1000u64))];
422+
let nonce = devnet
423+
.json_rpc_client
424+
.get_nonce(BlockId::Tag(BlockTag::Latest), account_address)
425+
.await
426+
.unwrap();
427+
428+
let block = devnet
429+
.json_rpc_client
430+
.get_block_with_tx_hashes(BlockId::Tag(BlockTag::Latest))
431+
.await
432+
.unwrap();
433+
434+
let prepared = account
435+
.execute_v3(calls)
436+
.l1_gas(5_000_000)
437+
.l1_data_gas(1_000_000)
438+
.l2_gas(2_500_000_000)
439+
.l1_gas_price(felt_to_u128(block.l1_gas_price().price_in_fri))
440+
.l1_data_gas_price(felt_to_u128(block.l1_data_gas_price().price_in_fri))
441+
.l2_gas_price(felt_to_u128(block.l2_gas_price().price_in_fri))
442+
.nonce(nonce)
443+
.tip(0)
444+
.prepared()
445+
.unwrap();
446+
447+
let invoke_for_prove = prepared.get_invoke_request(false, false).await.unwrap();
448+
449+
// Prove at block 10
450+
let block_id_10 = BlockId::Number(10u64);
451+
let result_at_block_10 =
452+
devnet.prove_transaction_at_block(invoke_for_prove.clone(), block_id_10).await;
453+
454+
// Prove the same transaction at block 15 (no blocks created between)
455+
let block_id_15 = BlockId::Number(15u64);
456+
let result_at_block_15 = devnet.prove_transaction_at_block(invoke_for_prove, block_id_15).await;
457+
458+
// Proofs should differ because they include different block numbers and hashes
459+
assert_ne!(
460+
result_at_block_10.proof_base64, result_at_block_15.proof_base64,
461+
"Proofs should differ for different block numbers (10 vs 15)"
462+
);
463+
assert_ne!(
464+
result_at_block_10.proof_facts_hex, result_at_block_15.proof_facts_hex,
465+
"Proof facts should differ for different block numbers"
466+
);
467+
}
468+
400469
#[tokio::test]
401470
async fn invoke_in_proof_mode_none_accepts_without_proof_or_with_wrong_proof() {
402471
let devnet_none = BackgroundDevnet::spawn_with_additional_args(&["--proof-mode", "none"])

0 commit comments

Comments
 (0)