Skip to content

Commit 594650c

Browse files
apollo_starknet_os_program: output the sender address (virtual OS) (#11491)
1 parent e9f7c03 commit 594650c

File tree

12 files changed

+119
-43
lines changed

12 files changed

+119
-43
lines changed

crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/block_context.cairo

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ from starkware.starknet.core.os.os_config.os_config import StarknetOsConfig
1919
// This mode should be disabled in the Starknet sequencer.
2020
struct VirtualOsConfig {
2121
enabled: felt,
22+
// The address of the account authorized to run transactions in virtual OS mode.
23+
// All the transactions in the block must be sent by this account.
24+
authorized_account_address: felt,
2225
}
2326

2427
// Struct to group compiled class facts parameters.
@@ -37,7 +40,7 @@ struct OsGlobalContext {
3740
starknet_os_config_hash: felt,
3841
3942
// Configuration for the virtual OS.
40-
virtual_os_config: VirtualOsConfig,
43+
virtual_os_config: VirtualOsConfig*,
4144
4245
// Compiled class facts available globally for all blocks.
4346
compiled_class_facts_bundle: CompiledClassFactsBundle,

crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/execution/execute_transactions.cairo

Lines changed: 52 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,11 @@ from starkware.starknet.core.os.execution.execute_transaction_utils import (
6565
run_validate,
6666
update_class_hash_in_execution_context,
6767
)
68-
from starkware.starknet.core.os.execution.execution_constraints import check_n_txs, check_tx_type
68+
from starkware.starknet.core.os.execution.execution_constraints import (
69+
check_n_txs,
70+
check_sender_address,
71+
check_tx_type,
72+
)
6973
from starkware.starknet.core.os.execution.revert import init_revert_log
7074
from starkware.starknet.core.os.output import (
7175
MessageToL2Header,
@@ -212,29 +216,38 @@ func execute_transactions_inner{
212216

213217
check_tx_type(tx_type=tx_type);
214218

219+
local sender_address: felt;
215220
if (tx_type == 'INVOKE_FUNCTION') {
216221
// Handle the invoke-function transaction.
217-
execute_invoke_function_transaction(block_context=block_context);
218-
%{ ExitTx %}
219-
return execute_transactions_inner(block_context=block_context, n_txs=n_txs - 1);
220-
}
221-
if (tx_type == 'L1_HANDLER') {
222-
// Handle the L1-handler transaction.
223-
execute_l1_handler_transaction(block_context=block_context);
222+
let (tx_sender_address) = execute_invoke_function_transaction(block_context=block_context);
224223
%{ ExitTx %}
225-
return execute_transactions_inner(block_context=block_context, n_txs=n_txs - 1);
226-
}
227-
if (tx_type == 'DEPLOY_ACCOUNT') {
228-
// Handle the deploy-account transaction.
229-
execute_deploy_account_transaction(block_context=block_context);
230-
%{ ExitTx %}
231-
return execute_transactions_inner(block_context=block_context, n_txs=n_txs - 1);
224+
assert sender_address = tx_sender_address;
225+
} else {
226+
if (tx_type == 'L1_HANDLER') {
227+
// Handle the L1-handler transaction.
228+
let (tx_sender_address) = execute_l1_handler_transaction(block_context=block_context);
229+
%{ ExitTx %}
230+
assert sender_address = tx_sender_address;
231+
} else {
232+
if (tx_type == 'DEPLOY_ACCOUNT') {
233+
// Handle the deploy-account transaction.
234+
let (tx_sender_address) = execute_deploy_account_transaction(
235+
block_context=block_context
236+
);
237+
%{ ExitTx %}
238+
assert sender_address = tx_sender_address;
239+
} else {
240+
assert tx_type = 'DECLARE';
241+
// Handle the declare transaction.
242+
let (tx_sender_address) = execute_declare_transaction(block_context=block_context);
243+
%{ ExitTx %}
244+
assert sender_address = tx_sender_address;
245+
}
246+
}
232247
}
233248

234-
assert tx_type = 'DECLARE';
235-
// Handle the declare transaction.
236-
execute_declare_transaction(block_context=block_context);
237-
%{ ExitTx %}
249+
check_sender_address(sender_address=sender_address, block_context=block_context);
250+
238251
return execute_transactions_inner(block_context=block_context, n_txs=n_txs - 1);
239252
}
240253

@@ -408,13 +421,16 @@ func fill_account_tx_info{range_check_ptr}(
408421
//
409422
// Arguments:
410423
// block_context - a global context that is fixed throughout the block.
424+
//
425+
// Returns:
426+
// sender_address - the address of the transaction sender.
411427
func execute_invoke_function_transaction{
412428
range_check_ptr,
413429
builtin_ptrs: BuiltinPointers*,
414430
contract_state_changes: DictAccess*,
415431
contract_class_changes: DictAccess*,
416432
outputs: OsCarriedOutputs*,
417-
}(block_context: BlockContext*) {
433+
}(block_context: BlockContext*) -> (sender_address: felt) {
418434
alloc_locals;
419435

420436
// TODO(Yoni): consider not sharing this code with L1 handler.
@@ -424,13 +440,14 @@ func execute_invoke_function_transaction{
424440
entry_point_selector=EXECUTE_ENTRY_POINT_SELECTOR,
425441
);
426442
local tx_execution_info: ExecutionInfo* = tx_execution_context.execution_info;
443+
let sender_address = tx_execution_info.contract_address;
427444

428445
// Guess transaction fields.
429446
// The version validation is done in `compute_invoke_transaction_hash()`.
430447
let common_tx_fields = get_account_tx_common_fields(
431448
block_context=block_context,
432449
tx_hash_prefix=INVOKE_HASH_PREFIX,
433-
sender_address=tx_execution_info.contract_address,
450+
sender_address=sender_address,
434451
);
435452
local account_deployment_data_size;
436453
local account_deployment_data: felt*;
@@ -513,7 +530,7 @@ func execute_invoke_function_transaction{
513530

514531
%{ EndTx %}
515532

516-
return ();
533+
return (sender_address=sender_address);
517534
}
518535

519536
// Executes an L1-handler transaction.
@@ -528,7 +545,7 @@ func execute_l1_handler_transaction{
528545
contract_state_changes: DictAccess*,
529546
contract_class_changes: DictAccess*,
530547
outputs: OsCarriedOutputs*,
531-
}(block_context: BlockContext*) {
548+
}(block_context: BlockContext*) -> (sender_address: felt) {
532549
alloc_locals;
533550

534551
%{ StartTx %}
@@ -537,7 +554,7 @@ func execute_l1_handler_transaction{
537554
// Skip the execution step for reverted transaction.
538555
if (is_reverted != FALSE) {
539556
%{ EndTx %}
540-
return ();
557+
return (sender_address=0);
541558
}
542559

543560
// TODO(Yoni): currently, the contract state is not fetched for reverted L1 handlers.
@@ -599,7 +616,7 @@ func execute_l1_handler_transaction{
599616
);
600617

601618
%{ EndTx %}
602-
return ();
619+
return (sender_address=0);
603620
}
604621

605622
// Guess the execution context of an invoke transaction (either invoke function or L1 handler).
@@ -718,13 +735,15 @@ func prepare_constructor_execution_context{range_check_ptr, builtin_ptrs: Builti
718735
);
719736
}
720737

738+
// Returns:
739+
// sender_address - the address of the transaction sender.
721740
func execute_deploy_account_transaction{
722741
range_check_ptr,
723742
builtin_ptrs: BuiltinPointers*,
724743
contract_state_changes: DictAccess*,
725744
contract_class_changes: DictAccess*,
726745
outputs: OsCarriedOutputs*,
727-
}(block_context: BlockContext*) {
746+
}(block_context: BlockContext*) -> (sender_address: felt) {
728747
alloc_locals;
729748

730749
// Calculate address and prepare constructor execution context.
@@ -838,23 +857,25 @@ func execute_deploy_account_transaction{
838857
charge_fee(block_context=block_context, tx_execution_context=validate_deploy_execution_context);
839858

840859
%{ EndTx %}
841-
return ();
860+
return (sender_address=sender_address);
842861
}
843862

863+
// Returns:
864+
// sender_address - the address of the transaction sender.
844865
func execute_declare_transaction{
845866
range_check_ptr,
846867
builtin_ptrs: BuiltinPointers*,
847868
contract_state_changes: DictAccess*,
848869
contract_class_changes: DictAccess*,
849870
outputs: OsCarriedOutputs*,
850-
}(block_context: BlockContext*) {
871+
}(block_context: BlockContext*) -> (sender_address: felt) {
851872
alloc_locals;
852873

853874
local tx_version;
854875
%{ TxVersion %}
855876
if (tx_version == 0) {
856877
%{ SkipTx %}
857-
return ();
878+
return (sender_address=0);
858879
}
859880

860881
// Guess transaction fields.
@@ -922,7 +943,7 @@ func execute_declare_transaction{
922943
key=[class_hash_ptr], prev_value=0, new_value=compiled_class_hash
923944
);
924945
%{ SkipTx %}
925-
return ();
946+
return (sender_address=sender_address);
926947
}
927948
}
928949

@@ -975,5 +996,5 @@ func execute_declare_transaction{
975996
);
976997
%{ EndTx %}
977998

978-
return ();
999+
return (sender_address=sender_address);
9791000
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
// Execution constraints for transaction execution.
22
// These are no-op implementations for the Sequencer OS.
33

4+
from starkware.starknet.core.os.block_context import BlockContext
5+
46
func check_n_txs(n_txs: felt) {
57
return ();
68
}
79

810
func check_tx_type(tx_type: felt) {
911
return ();
1012
}
13+
14+
func check_sender_address(sender_address: felt, block_context: BlockContext*) {
15+
return ();
16+
}

crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/execution/execution_constraints__virtual.cairo

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// Execution constraints for transaction execution (virtual OS version).
22

3+
from starkware.starknet.core.os.block_context import BlockContext
4+
35
// Checks that the number of transactions is one.
46
func check_n_txs(n_txs: felt) {
57
with_attr error_message("Expected exactly one transaction") {
@@ -15,3 +17,12 @@ func check_tx_type(tx_type: felt) {
1517
}
1618
return ();
1719
}
20+
21+
// Checks that the sender address matches the authorized account address.
22+
func check_sender_address(sender_address: felt, block_context: BlockContext*) {
23+
let virtual_os_config = block_context.os_global_context.virtual_os_config;
24+
with_attr error_message("Sender address does not match authorized account address") {
25+
assert virtual_os_config.authorized_account_address = sender_address;
26+
}
27+
return ();
28+
}

crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/os.cairo

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ func main{
128128
os_outputs=os_outputs,
129129
n_public_keys=n_public_keys,
130130
public_keys=public_keys,
131+
os_global_context=os_global_context,
131132
);
132133

133134
// The following code deals with the problem that untrusted code (contract code) could

crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/os_utils.cairo

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,13 @@ func get_block_os_output_header{poseidon_ptr: PoseidonBuiltin*}(
147147
// Processes OS outputs by combining blocks and serializing the result.
148148
func process_os_output{
149149
output_ptr: felt*, range_check_ptr, ec_op_ptr: EcOpBuiltin*, poseidon_ptr: PoseidonBuiltin*
150-
}(n_blocks: felt, os_outputs: OsOutput*, n_public_keys: felt, public_keys: felt*) {
150+
}(
151+
n_blocks: felt,
152+
os_outputs: OsOutput*,
153+
n_public_keys: felt,
154+
public_keys: felt*,
155+
os_global_context: OsGlobalContext*,
156+
) {
151157
alloc_locals;
152158
// Guess whether to use KZG commitment scheme and whether to output the full state.
153159
// TODO(meshi): Once use_kzg_da field is used in the OS for the computation of fees and block
@@ -181,7 +187,9 @@ func process_os_output{
181187
}
182188

183189
// Returns the virtual OS config, which is always disabled in the Starknet sequencer OS.
184-
func get_virtual_os_config() -> VirtualOsConfig {
185-
let virtual_os_config = VirtualOsConfig(enabled=FALSE);
190+
func get_virtual_os_config() -> VirtualOsConfig* {
191+
tempvar virtual_os_config: VirtualOsConfig* = new VirtualOsConfig(
192+
enabled=FALSE, authorized_account_address=0
193+
);
186194
return virtual_os_config;
187195
}

crates/apollo_starknet_os_program/src/cairo/starkware/starknet/core/os/os_utils__virtual.cairo

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from starkware.cairo.common.alloc import alloc
12
from starkware.cairo.common.bool import FALSE, TRUE
23
from starkware.cairo.common.cairo_builtins import EcOpBuiltin, PoseidonBuiltin
34
from starkware.cairo.common.dict_access import DictAccess
@@ -51,7 +52,13 @@ func get_block_os_output_header{poseidon_ptr: PoseidonBuiltin*}(
5152
// Outputs the virtual OS header and the messages to L1.
5253
func process_os_output{
5354
output_ptr: felt*, range_check_ptr, ec_op_ptr: EcOpBuiltin*, poseidon_ptr: PoseidonBuiltin*
54-
}(n_blocks: felt, os_outputs: OsOutput*, n_public_keys: felt, public_keys: felt*) {
55+
}(
56+
n_blocks: felt,
57+
os_outputs: OsOutput*,
58+
n_public_keys: felt,
59+
public_keys: felt*,
60+
os_global_context: OsGlobalContext*,
61+
) {
5562
alloc_locals;
5663
assert n_public_keys = 0;
5764

@@ -65,7 +72,7 @@ func process_os_output{
6572
serialize_word(header.prev_block_number);
6673
serialize_word(header.prev_block_hash);
6774
serialize_word(header.starknet_os_config_hash);
68-
// TODO(Yoni): output the authorized account address.
75+
serialize_word(os_global_context.virtual_os_config.authorized_account_address);
6976

7077
// TODO(Yoni): output the hash of the messages instead.
7178
let messages_to_l1_segment_size = (
@@ -85,7 +92,10 @@ func process_os_output{
8592
}
8693

8794
// Returns the virtual OS config.
88-
func get_virtual_os_config() -> VirtualOsConfig {
89-
let virtual_os_config = VirtualOsConfig(enabled=TRUE);
95+
func get_virtual_os_config() -> VirtualOsConfig* {
96+
let (virtual_os_config: VirtualOsConfig*) = alloc();
97+
static_assert VirtualOsConfig.SIZE == 2;
98+
assert virtual_os_config.enabled = TRUE;
99+
// The authorized account address will be set during transaction execution.
90100
return virtual_os_config;
91101
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"os": "0x78179950037794503935395abfcc7446fbdee452d388a9cc047ef7201bc2278",
3-
"virtual_os": "0x6c33b6ac546a56d5f79fe7367a3c4ec550ba8bf627d97f5cfe0f6a6cf120e5c",
2+
"os": "0x7edaf9251ec7a175fe40f6831b301938db479ff67a3c817dc44ad1443188d52",
3+
"virtual_os": "0x3d95cf00f1d15c2dea45a3a0fbceda2560789b68283ed0480d9a6028d4ba84d",
44
"aggregator": "0x63868c8dbf389119d95bae88b80043f5d237d3ddec072fb8f2095fcfacb9b1c",
55
"aggregator_with_prefix": "0xd892fd2fd978d8c2749a6678457ca99161f3d1822e4c3b8c03914817c6de1a"
66
}

crates/apollo_starknet_os_program/src/virtual_os_test.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ fn test_virtual_os_swapped_files() {
1616
#[test]
1717
fn test_program_bytecode_lengths() {
1818
expect![[r#"
19-
15535
19+
15555
2020
"#]]
2121
.assert_debug_eq(&OS_PROGRAM.data_len());
2222
expect![[r#"
23-
13184
23+
13209
2424
"#]]
2525
.assert_debug_eq(&VIRTUAL_OS_PROGRAM.data_len());
2626
}

crates/starknet_os/src/io/virtual_os_output.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use cairo_vm::vm::runners::cairo_pie::CairoPie;
22
use starknet_api::block::BlockNumber;
3+
use starknet_api::core::ContractAddress;
34
use starknet_api::hash::StarkHash;
45
use starknet_api::transaction::MessageToL1;
56
use starknet_types_core::felt::Felt;
@@ -21,6 +22,8 @@ pub struct VirtualOsOutput {
2122
pub base_block_hash: StarkHash,
2223
/// The hash of the Starknet OS config.
2324
pub starknet_os_config_hash: StarkHash,
25+
/// The address of the authorized account.
26+
pub authorized_account_address: ContractAddress,
2427
/// Messages from L2 to L1.
2528
pub messages_to_l1: Vec<MessageToL1>,
2629
}
@@ -34,6 +37,8 @@ impl VirtualOsOutput {
3437
let base_block_number = BlockNumber(wrap_missing_as(iter.next(), "base_block_number")?);
3538
let base_block_hash = wrap_missing(iter.next(), "base_block_hash")?;
3639
let starknet_os_config_hash = wrap_missing(iter.next(), "starknet_os_config_hash")?;
40+
let authorized_account_address =
41+
wrap_missing_as(iter.next(), "authorized_account_address")?;
3742
let messages_to_l1 = parse_messages_to_l1(&mut iter)?;
3843

3944
// Verify that we have consumed all output.
@@ -46,6 +51,7 @@ impl VirtualOsOutput {
4651
base_block_number,
4752
base_block_hash,
4853
starknet_os_config_hash,
54+
authorized_account_address,
4955
messages_to_l1,
5056
})
5157
}

0 commit comments

Comments
 (0)