diff --git a/crates/apollo_consensus_orchestrator/resources/central_invoke_tx_client_side_proving.json b/crates/apollo_consensus_orchestrator/resources/central_invoke_tx_client_side_proving.json index aeff6467e1f..f688708c96b 100644 --- a/crates/apollo_consensus_orchestrator/resources/central_invoke_tx_client_side_proving.json +++ b/crates/apollo_consensus_orchestrator/resources/central_invoke_tx_client_side_proving.json @@ -35,9 +35,12 @@ "proof_facts": [ "0x5649525455414c5f534e4f53", "0x130206a40921880628605041292e995870334451179c63090221210893986a2", + "0x0", "0x7a0", "0x2fa80", - "0x1" + "0x1", + "0x10", + "0x0" ], "type": "INVOKE_FUNCTION" }, diff --git a/crates/apollo_consensus_orchestrator/resources/central_preconfirmed_block.json b/crates/apollo_consensus_orchestrator/resources/central_preconfirmed_block.json index efe6cf6b492..7e159a86bf8 100644 --- a/crates/apollo_consensus_orchestrator/resources/central_preconfirmed_block.json +++ b/crates/apollo_consensus_orchestrator/resources/central_preconfirmed_block.json @@ -60,9 +60,12 @@ "proof_facts": [ "0x5649525455414c5f534e4f53", "0x130206a40921880628605041292e995870334451179c63090221210893986a2", + "0x0", "0x7a0", "0x2fa80", - "0x1" + "0x1", + "0x10", + "0x0" ], "type":"INVOKE_FUNCTION" }, diff --git a/crates/apollo_http_server/resources/deprecated_gateway/invoke_tx_client_side_proving.json b/crates/apollo_http_server/resources/deprecated_gateway/invoke_tx_client_side_proving.json index 53b19ff2f2c..fd85d565282 100644 --- a/crates/apollo_http_server/resources/deprecated_gateway/invoke_tx_client_side_proving.json +++ b/crates/apollo_http_server/resources/deprecated_gateway/invoke_tx_client_side_proving.json @@ -29,9 +29,12 @@ "proof_facts": [ "0x5649525455414c5f534e4f53", "0x130206a40921880628605041292e995870334451179c63090221210893986a2", + "0x0", "0x7a0", "0x2fa80", - "0x1" + "0x1", + "0x10", + "0x0" ], "proof": [ 1, diff --git a/crates/apollo_starknet_client/resources/reader/invoke_v3_client_side_proving.json b/crates/apollo_starknet_client/resources/reader/invoke_v3_client_side_proving.json index d82b088f37b..d62ebfcfcbf 100644 --- a/crates/apollo_starknet_client/resources/reader/invoke_v3_client_side_proving.json +++ b/crates/apollo_starknet_client/resources/reader/invoke_v3_client_side_proving.json @@ -35,8 +35,11 @@ "proof_facts": [ "0x5649525455414c5f534e4f53", "0x130206a40921880628605041292e995870334451179c63090221210893986a2", + "0x0", "0x7a0", "0x2fa80", - "0x1" + "0x1", + "0x10", + "0x0" ] } diff --git a/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/os_utils__virtual.cairo b/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/os_utils__virtual.cairo index ac80565b58d..ae427520ae5 100644 --- a/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/os_utils__virtual.cairo +++ b/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/os_utils__virtual.cairo @@ -3,11 +3,11 @@ from starkware.cairo.common.bool import FALSE, TRUE from starkware.cairo.common.cairo_builtins import EcOpBuiltin, PoseidonBuiltin from starkware.cairo.common.dict_access import DictAccess from starkware.cairo.common.memcpy import memcpy -from starkware.cairo.common.serialize import serialize_word from starkware.starknet.core.os.block_context import BlockContext, OsGlobalContext, VirtualOsConfig from starkware.starknet.core.os.block_hash import get_block_hashes from starkware.starknet.core.os.output import OsOutput, OsOutputHeader from starkware.starknet.core.os.state.commitment import CommitmentUpdate +from starkware.starknet.core.os.virtual_os_output import VirtualOsOutputHeader const VIRTUAL_OS_OUTPUT_VERSION = 0; @@ -66,20 +66,28 @@ func process_os_output{ assert n_blocks = 1; let os_output = os_outputs[0]; - // Serialize the header. + // Serialize the header using memcpy to enforce struct field order. let header = os_output.header; - serialize_word(VIRTUAL_OS_OUTPUT_VERSION); - serialize_word(header.prev_block_number); - serialize_word(header.prev_block_hash); - serialize_word(header.starknet_os_config_hash); - serialize_word(os_global_context.virtual_os_config.authorized_account_address); // TODO(Yoni): output the hash of the messages instead. let messages_to_l1_segment_size = ( os_output.final_carried_outputs.messages_to_l1 - os_output.initial_carried_outputs.messages_to_l1 ); - serialize_word(messages_to_l1_segment_size); + + // Create the virtual OS output header. + tempvar virtual_os_output_header = new VirtualOsOutputHeader( + version=VIRTUAL_OS_OUTPUT_VERSION, + base_block_number=header.prev_block_number, + base_block_hash=header.prev_block_hash, + starknet_os_config_hash=os_global_context.starknet_os_config_hash, + authorized_account_address=os_global_context.virtual_os_config.authorized_account_address, + messages_to_l1_segment_size=messages_to_l1_segment_size, + ); + + // Copy the header to the output. + memcpy(dst=output_ptr, src=virtual_os_output_header, len=VirtualOsOutputHeader.SIZE); + let output_ptr = &output_ptr[VirtualOsOutputHeader.SIZE]; // Copy 'messages_to_l1_segment' to the correct place in the output segment. memcpy( diff --git a/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/virtual_os_output.cairo b/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/virtual_os_output.cairo new file mode 100644 index 00000000000..0a0d50e2ab5 --- /dev/null +++ b/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/virtual_os_output.cairo @@ -0,0 +1,11 @@ +// The header of the virtual OS output. +struct VirtualOsOutputHeader { + version: felt, + // The block number and hash that this run is based on. + base_block_number: felt, + base_block_hash: felt, + starknet_os_config_hash: felt, + // The account address that is authorized to run transactions. + authorized_account_address: felt, + messages_to_l1_segment_size: felt, +} diff --git a/crates/apollo_starknet_os_program/src/program_hash.json b/crates/apollo_starknet_os_program/src/program_hash.json index 063833f298e..622af7eba68 100644 --- a/crates/apollo_starknet_os_program/src/program_hash.json +++ b/crates/apollo_starknet_os_program/src/program_hash.json @@ -1,6 +1,6 @@ { "os": "0x24a4dbf1caa00186a70b56470ae920f7ce49fbd5b57263a279ebdb7a355f0ed", - "virtual_os": "0x40693cd3a5ac9ba9ed620892170da34bb22ba9dbc5cc203ab1cc758de782495", + "virtual_os": "0x7433ebe51a1de5b09532d2efa53b7a33658567ba7eef3a4743292a28e5a2ab2", "aggregator": "0x63868c8dbf389119d95bae88b80043f5d237d3ddec072fb8f2095fcfacb9b1c", "aggregator_with_prefix": "0xd892fd2fd978d8c2749a6678457ca99161f3d1822e4c3b8c03914817c6de1a" } \ No newline at end of file diff --git a/crates/apollo_starknet_os_program/src/virtual_os_test.rs b/crates/apollo_starknet_os_program/src/virtual_os_test.rs index cf9fd675efa..622a62be08f 100644 --- a/crates/apollo_starknet_os_program/src/virtual_os_test.rs +++ b/crates/apollo_starknet_os_program/src/virtual_os_test.rs @@ -22,7 +22,7 @@ fn test_program_bytecode_lengths() { "#]] .assert_debug_eq(&OS_PROGRAM.data_len()); expect![[r#" - 11621 + 11610 "#]] .assert_debug_eq(&VIRTUAL_OS_PROGRAM.data_len()); } diff --git a/crates/starknet_api/src/rpc_transaction_test.rs b/crates/starknet_api/src/rpc_transaction_test.rs index 214c8efda32..5a2db480a9b 100644 --- a/crates/starknet_api/src/rpc_transaction_test.rs +++ b/crates/starknet_api/src/rpc_transaction_test.rs @@ -146,7 +146,7 @@ fn test_invoke_tx_size_of() { // + tx_v3.proof.dynamic_size(); // Check the size of the V3 invoke transaction. - assert_eq!(tx_v3.size_bytes(), 696); + assert_eq!(tx_v3.size_bytes(), 792); } else { panic!("Expected RpcTransaction::Invoke"); } diff --git a/crates/starknet_api/src/test_utils.rs b/crates/starknet_api/src/test_utils.rs index 1546ca6958c..fdc7cc2c69e 100644 --- a/crates/starknet_api/src/test_utils.rs +++ b/crates/starknet_api/src/test_utils.rs @@ -381,6 +381,7 @@ impl ProofFacts { /// /// See [`crate::transaction::fields::ProofFacts`]. pub fn snos_proof_facts_for_testing() -> Self { + let version = Felt::ZERO; let block_hash_history_start = CURRENT_BLOCK_NUMBER - BLOCK_HASH_HISTORY_RANGE; let block_number = felt!(block_hash_history_start + 2); let block_hash = block_number * felt!(100_u64); @@ -391,12 +392,18 @@ impl ProofFacts { ); // TODO(AvivG): Change to valid values when available. let config_hash = felt!("0x1"); + // These fields are not verified by the OS (they are application-related). + let authorized_account_address = felt!("0x10"); + let messages_to_l1_segment_size = Felt::ZERO; proof_facts![ felt!(VIRTUAL_SNOS), VIRTUAL_OS_PROGRAM_HASH, + version, block_number, block_hash, - config_hash + config_hash, + authorized_account_address, + messages_to_l1_segment_size ] } } diff --git a/crates/starknet_api/src/transaction/fields.rs b/crates/starknet_api/src/transaction/fields.rs index 591cb72cb13..b52d32268a5 100644 --- a/crates/starknet_api/src/transaction/fields.rs +++ b/crates/starknet_api/src/transaction/fields.rs @@ -662,7 +662,8 @@ impl TryFrom<&ProofFacts> for ProofFactsVariant { ))); } - let [program_hash, block_number_felt, block_hash, config_hash, ..] = snos_fields else { + let [program_hash, _version, block_number_felt, block_hash, config_hash, ..] = snos_fields + else { return Err(StarknetApiError::InvalidProofFacts(format!( "SNOS proof facts must have at least 5 fields, got {}", proof_facts.0.len()