From bce63c395fb7e0a5016ca462b7dbc7595b49d983 Mon Sep 17 00:00:00 2001 From: ron-starkware Date: Wed, 15 Jul 2026 11:42:36 +0300 Subject: [PATCH] apollo_starknet_os_program,starknet_os: add the deploy_v2 syscall to the OS --- .../starknet/common/new_syscalls.cairo | 3 + .../starknet/core/os/constants.cairo | 4 +- .../starknet/core/os/constants_template.txt | 2 + .../core/os/execution/execute_syscalls.cairo | 14 +++ .../core/os/execution/syscall_impls.cairo | 94 ++++++++++++++++++- .../src/constants_test.rs | 3 + .../src/program_hash.json | 2 +- .../src/virtual_os_test.rs | 2 +- ...blockifier_versioned_constants_0_14_5.json | 2 +- .../0.14.4_0.14.5.txt | 1 + .../syscalls/syscall_tests/meta_tx.rs | 4 +- 11 files changed, 124 insertions(+), 7 deletions(-) diff --git a/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/common/new_syscalls.cairo b/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/common/new_syscalls.cairo index 59d489e4ebc..a6bc19b41ae 100644 --- a/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/common/new_syscalls.cairo +++ b/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/common/new_syscalls.cairo @@ -7,6 +7,9 @@ from starkware.cairo.common.uint256 import Uint256 const CALL_CONTRACT_SELECTOR = 'CallContract'; const DEPLOY_SELECTOR = 'Deploy'; +// Same request/response layout as `Deploy`; the contract address is derived with Blake2 (plus +// the Pedersen-image escape) instead of Pedersen. +const DEPLOY_V2_SELECTOR = 'DeployV2'; const EMIT_EVENT_SELECTOR = 'EmitEvent'; const GET_BLOCK_HASH_SELECTOR = 'GetBlockHash'; const GET_EXECUTION_INFO_SELECTOR = 'GetExecutionInfo'; diff --git a/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/constants.cairo b/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/constants.cairo index e304b606429..952d8198fa5 100644 --- a/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/constants.cairo +++ b/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/constants.cairo @@ -107,6 +107,8 @@ const SYSCALL_BASE_GAS_COST = 10000; const CALL_CONTRACT_GAS_COST = 91360; const DEPLOY_GAS_COST = 147120; const DEPLOY_CALLDATA_FACTOR_GAS_COST = 4850; +const DEPLOY_V2_GAS_COST = 147120; +const DEPLOY_V2_CALLDATA_FACTOR_GAS_COST = 4850; const GET_BLOCK_HASH_GAS_COST = 10810; const GET_CLASS_HASH_AT_GAS_COST = 10000; const GET_EXECUTION_INFO_GAS_COST = 11240; @@ -118,7 +120,7 @@ const STORAGE_WRITE_GAS_COST = 59970; const EMIT_EVENT_GAS_COST = 10000; const SEND_MESSAGE_TO_L1_GAS_COST = 12770; const SEND_MESSAGE_TO_L1_PAYLOAD_FACTOR_GAS_COST = 600; -const META_TX_V0_GAS_COST = 168550; +const META_TX_V0_GAS_COST = 168750; const META_TX_V0_CALLDATA_FACTOR_GAS_COST = 4850; // Note the the following costs include `SYSCALL_BASE_GAS_COST` implicitly. diff --git a/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/constants_template.txt b/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/constants_template.txt index 2b89739e688..bf69b249ac5 100644 --- a/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/constants_template.txt +++ b/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/constants_template.txt @@ -89,6 +89,8 @@ const SYSCALL_BASE_GAS_COST = {SYSCALL_BASE_GAS_COST}; const CALL_CONTRACT_GAS_COST = {CALL_CONTRACT_GAS_COST}; const DEPLOY_GAS_COST = {DEPLOY_GAS_COST}; const DEPLOY_CALLDATA_FACTOR_GAS_COST = {DEPLOY_CALLDATA_FACTOR_GAS_COST}; +const DEPLOY_V2_GAS_COST = {DEPLOY_V2_GAS_COST}; +const DEPLOY_V2_CALLDATA_FACTOR_GAS_COST = {DEPLOY_V2_CALLDATA_FACTOR_GAS_COST}; const GET_BLOCK_HASH_GAS_COST = {GET_BLOCK_HASH_GAS_COST}; const GET_CLASS_HASH_AT_GAS_COST = {GET_CLASS_HASH_AT_GAS_COST}; const GET_EXECUTION_INFO_GAS_COST = {GET_EXECUTION_INFO_GAS_COST}; diff --git a/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/execution/execute_syscalls.cairo b/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/execution/execute_syscalls.cairo index ebd1f5c6710..31ac7be774f 100644 --- a/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/execution/execute_syscalls.cairo +++ b/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/execution/execute_syscalls.cairo @@ -7,6 +7,7 @@ from starkware.cairo.common.uint256 import Uint256 from starkware.starknet.common.new_syscalls import ( CALL_CONTRACT_SELECTOR, DEPLOY_SELECTOR, + DEPLOY_V2_SELECTOR, EMIT_EVENT_SELECTOR, GET_BLOCK_HASH_SELECTOR, GET_CLASS_HASH_AT_SELECTOR, @@ -44,6 +45,7 @@ from starkware.starknet.core.os.execution.revert import RevertLogEntry from starkware.starknet.core.os.execution.syscall_impls import ( execute_call_contract, execute_deploy, + execute_deploy_v2, execute_get_block_hash, execute_get_class_hash_at, execute_get_execution_info, @@ -352,6 +354,18 @@ func execute_syscalls{ ); } + // Placed last (before the meta_tx fallthrough) so adding this arm doesn't add a comparison to + // any pre-existing syscall's dispatch path. + if (selector == DEPLOY_V2_SELECTOR) { + execute_deploy_v2(block_context=block_context, caller_execution_context=execution_context); + %{ OsLoggerExitSyscall %} + return execute_syscalls( + block_context=block_context, + execution_context=execution_context, + syscall_ptr_end=syscall_ptr_end, + ); + } + assert selector = META_TX_V0_SELECTOR; execute_meta_tx_v0(block_context=block_context, caller_execution_context=execution_context); %{ OsLoggerExitSyscall %} diff --git a/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/execution/syscall_impls.cairo b/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/execution/syscall_impls.cairo index 295eaa61cad..b605bd6c383 100644 --- a/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/execution/syscall_impls.cairo +++ b/crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/execution/syscall_impls.cairo @@ -89,6 +89,8 @@ from starkware.starknet.core.os.constants import ( CONSTRUCTOR_ENTRY_POINT_SELECTOR, DEPLOY_CALLDATA_FACTOR_GAS_COST, DEPLOY_GAS_COST, + DEPLOY_V2_CALLDATA_FACTOR_GAS_COST, + DEPLOY_V2_GAS_COST, ENTRY_POINT_TYPE_CONSTRUCTOR, ENTRY_POINT_TYPE_EXTERNAL, ERROR_BLOCK_NUMBER_OUT_OF_RANGE, @@ -124,7 +126,10 @@ from starkware.starknet.core.os.constants import ( STORED_BLOCK_HASH_BUFFER, SYSCALL_BASE_GAS_COST, ) -from starkware.starknet.core.os.contract_address.contract_address import get_contract_address +from starkware.starknet.core.os.contract_address.contract_address import ( + get_contract_address, + get_contract_address_blake_escaped, +) from starkware.starknet.core.os.execution.account_backward_compatibility import ( check_tip_for_v1_bound_accounts, exclude_data_gas_of_resource_bounds, @@ -560,6 +565,93 @@ func execute_deploy{ return (); } +// Same as `execute_deploy`, but derives the contract address with Blake2 plus the +// Pedersen-image escape (see `get_contract_address_blake_escaped`) instead of Pedersen. +func execute_deploy_v2{ + range_check_ptr, + syscall_ptr: felt*, + builtin_ptrs: BuiltinPointers*, + contract_state_changes: DictAccess*, + contract_class_changes: DictAccess*, + revert_log: RevertLogEntry*, + outputs: OsCarriedOutputs*, +}(block_context: BlockContext*, caller_execution_context: ExecutionContext*) { + alloc_locals; + let request = cast(syscall_ptr + RequestHeader.SIZE, DeployRequest*); + local constructor_calldata_start: felt* = request.constructor_calldata_start; + local constructor_calldata_size = request.constructor_calldata_end - constructor_calldata_start; + + let specific_base_gas_cost = DEPLOY_V2_GAS_COST + DEPLOY_V2_CALLDATA_FACTOR_GAS_COST * + constructor_calldata_size; + let (success, remaining_gas) = reduce_syscall_base_gas( + specific_base_gas_cost=specific_base_gas_cost, request_struct_size=DeployRequest.SIZE + ); + if (success == FALSE) { + // Not enough gas to execute the syscall. + return (); + } + + local caller_execution_info: ExecutionInfo* = caller_execution_context.execution_info; + local caller_address = caller_execution_info.contract_address; + + // Verify deploy_from_zero is either 0 (FALSE) or 1 (TRUE). + tempvar deploy_from_zero = request.deploy_from_zero; + assert deploy_from_zero * (deploy_from_zero - 1) = 0; + // Set deployer_address to 0 if request.deploy_from_zero is TRUE. + let deployer_address = (1 - deploy_from_zero) * caller_address; + + let (contract_address) = get_contract_address_blake_escaped( + salt=request.contract_address_salt, + class_hash=request.class_hash, + constructor_calldata_size=constructor_calldata_size, + constructor_calldata=constructor_calldata_start, + deployer_address=deployer_address, + ); + + tempvar constructor_execution_context = new ExecutionContext( + entry_point_type=ENTRY_POINT_TYPE_CONSTRUCTOR, + class_hash=request.class_hash, + calldata_size=constructor_calldata_size, + calldata=constructor_calldata_start, + execution_info=new ExecutionInfo( + block_info=caller_execution_info.block_info, + tx_info=caller_execution_info.tx_info, + caller_address=caller_address, + contract_address=contract_address, + selector=CONSTRUCTOR_ENTRY_POINT_SELECTOR, + ), + deprecated_tx_info=caller_execution_context.deprecated_tx_info, + ); + + with remaining_gas { + let (retdata_size, retdata) = deploy_contract( + block_context=block_context, constructor_execution_context=constructor_execution_context + ); + } + + let response_header = cast(syscall_ptr, ResponseHeader*); + let syscall_ptr = syscall_ptr + ResponseHeader.SIZE; + + // Write the response header. + assert [response_header] = ResponseHeader(gas=remaining_gas, failure_flag=0); + + let response = cast(syscall_ptr, DeployResponse*); + // Advance syscall pointer to the next syscall. + let syscall_ptr = syscall_ptr + DeployResponse.SIZE; + + %{ CheckNewDeployResponse %} + + // Write the response. + relocate_segment(src_ptr=response.constructor_retdata_start, dest_ptr=retdata); + assert [response] = DeployResponse( + contract_address=contract_address, + constructor_retdata_start=retdata, + constructor_retdata_end=retdata + retdata_size, + ); + + return (); +} + // Reads the class hash of the given contract address. func execute_get_class_hash_at{ range_check_ptr, syscall_ptr: felt*, contract_state_changes: DictAccess* diff --git a/crates/apollo_starknet_os_program/src/constants_test.rs b/crates/apollo_starknet_os_program/src/constants_test.rs index 407cd647daa..6caaaac08fe 100644 --- a/crates/apollo_starknet_os_program/src/constants_test.rs +++ b/crates/apollo_starknet_os_program/src/constants_test.rs @@ -150,6 +150,9 @@ fn generate_constants_file() -> String { DEPLOY_GAS_COST = os_constants.gas_costs.syscalls.deploy.get_syscall_cost(0), DEPLOY_CALLDATA_FACTOR_GAS_COST = os_constants.gas_costs.syscalls.deploy.linear_syscall_cost(), + DEPLOY_V2_GAS_COST = os_constants.gas_costs.syscalls.deploy_v2.get_syscall_cost(0), + DEPLOY_V2_CALLDATA_FACTOR_GAS_COST = + os_constants.gas_costs.syscalls.deploy_v2.linear_syscall_cost(), GET_BLOCK_HASH_GAS_COST = base_only_syscall_cost(SyscallSelector::GetBlockHash, os_constants), GET_CLASS_HASH_AT_GAS_COST = diff --git a/crates/apollo_starknet_os_program/src/program_hash.json b/crates/apollo_starknet_os_program/src/program_hash.json index e5a96240f8d..4ec6d03ff72 100644 --- a/crates/apollo_starknet_os_program/src/program_hash.json +++ b/crates/apollo_starknet_os_program/src/program_hash.json @@ -1,5 +1,5 @@ { - "os": "0x4d4d99c7abc2923a05921f83a7c14bad8e0a701fb9064bd86a4bc58d93310a7", + "os": "0x270d10aed5049dc32cd2aa4f85e4eb4c3bc386b6ed4459a0f7bf7a6284750e0", "virtual_os": "0xfedbf2b6504b9217026ba2bf9b2a33e8e28ed38e5b0f84eef59075b02174b8", "aggregator": "0x3e4ce8340259e374200ed856e597a0c0b268d1021119d33573d7c759c5320f9", "aggregator_with_prefix": "0x2526c12112a2d7f57f7ae74af7be1fe1b2766e4c34b0c88ceda16b70ed2d6c2" 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 e4965e1a267..23c308819ba 100644 --- a/crates/apollo_starknet_os_program/src/virtual_os_test.rs +++ b/crates/apollo_starknet_os_program/src/virtual_os_test.rs @@ -19,7 +19,7 @@ fn test_virtual_os_swapped_files() { #[test] fn test_program_bytecode_lengths() { expect![[r#" - 16564 + 16686 "#]] .assert_debug_eq(&OS_PROGRAM.data_len()); expect![[r#" diff --git a/crates/blockifier/resources/blockifier_versioned_constants_0_14_5.json b/crates/blockifier/resources/blockifier_versioned_constants_0_14_5.json index f535466eb2c..6af6f785888 100644 --- a/crates/blockifier/resources/blockifier_versioned_constants_0_14_5.json +++ b/crates/blockifier/resources/blockifier_versioned_constants_0_14_5.json @@ -381,7 +381,7 @@ }, "MetaTxV0": { "constant": { - "n_steps": 1307, + "n_steps": 1309, "n_memory_holes": 0, "builtin_instance_counter": { "range_check_builtin": 20, diff --git a/crates/blockifier/resources/versioned_constants_diff_regression/0.14.4_0.14.5.txt b/crates/blockifier/resources/versioned_constants_diff_regression/0.14.4_0.14.5.txt index b35c49c8840..ce1a9ebbfba 100644 --- a/crates/blockifier/resources/versioned_constants_diff_regression/0.14.4_0.14.5.txt +++ b/crates/blockifier/resources/versioned_constants_diff_regression/0.14.4_0.14.5.txt @@ -4,6 +4,7 @@ - /os_resources/execute_syscalls/DeployV2/builtin_instance_counter - /os_resources/execute_syscalls/DeployV2/n_memory_holes - /os_resources/execute_syscalls/DeployV2/n_steps +~ /os_resources/execute_syscalls/MetaTxV0/constant/n_steps: 1309 ~ /os_resources/execute_txs_inner/Declare/n_steps: 3946 ~ /os_resources/execute_txs_inner/DeployAccount/constant/n_steps: 5017 ~ /os_resources/execute_txs_inner/InvokeFunction/constant/n_steps: 4787 diff --git a/crates/blockifier/src/execution/syscalls/syscall_tests/meta_tx.rs b/crates/blockifier/src/execution/syscalls/syscall_tests/meta_tx.rs index be078210aa2..756a1ad61b3 100644 --- a/crates/blockifier/src/execution/syscalls/syscall_tests/meta_tx.rs +++ b/crates/blockifier/src/execution/syscalls/syscall_tests/meta_tx.rs @@ -176,7 +176,7 @@ fn test_meta_tx_v0( assert_eq!(call_info.execution.gas_consumed, 0); expect![[r#" DeterministicExecutionResources { - n_steps: 14795, + n_steps: 14797, n_memory_holes: 10, builtin_instance_counter: { "pedersen_builtin": 12, @@ -197,7 +197,7 @@ fn test_meta_tx_v0( l2_to_l1_messages: [], cairo_native: false, failed: false, - gas_consumed: 1533250, + gas_consumed: 1533450, } "#]] .assert_debug_eq(&call_info.execution);