Skip to content

Commit b757ad4

Browse files
avi-starkwareclaude
andcommitted
align sierra-emu StarknetSyscallHandler trait/types with cairo-native
Sierra-emu adopts cairo-native's syscall surface so the two traits/types match name-for-name. Prerequisite for extracting them into a shared crate (next PR). - Slice signatures: deploy/library_call/call_contract/emit_event/ send_message_to_l1/keccak/meta_tx_v0/cheatcode now take &[Felt] / &[u64] rather than owned Vec. - Secp256{k1,r1}Point gain an explicit is_infinity flag. The Sierra Value encoding canonicalizes (0, 0) for the identity element so the round-trip via from_value/into_value is lossless: into_value forces (x, y) = (0, 0) when is_infinity is set; from_value recovers the flag from the sentinel. (0, 0) is not a real curve point, so the aliasing is unambiguous. - Stub secp arithmetic now handles `Coordinates::Identity` from to_encoded_point(false), returning the canonical (0, 0) + is_infinity point instead of tripping unreachable!(). Pre-existing bug surfaced by the trait alignment. - sha256_process_block matches cairo-native's mutating signature (&mut [u32; 8], &[u32; 16]) -> SyscallResult<()>. - Add ExecutionInfoV3 / TxV3Info types and a get_execution_info_v3 trait method. The Sierra-level Value lowering for v3 isn't wired in the VM yet -- eval_get_execution_info_v3 soft-fails with a descriptive felt rather than panicking with todo!(), so any contract calling the v3 syscall sees a graceful syscall error. Full v3 wiring is a separate effort. - cairo-native: cheatcode trait method becomes unconditional (was gated behind with-cheatcode). The default impl is unimplemented!(), so this is backwards-compatible for existing impls; only the runtime/codegen side stays feature-gated. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 07d0bc0 commit b757ad4

8 files changed

Lines changed: 223 additions & 68 deletions

File tree

debug_utils/sierra-emu/src/starknet.rs

Lines changed: 91 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ use std::{
55

66
pub use self::{
77
block_info::BlockInfo, execution_info::ExecutionInfo, execution_info_v2::ExecutionInfoV2,
8-
resource_bounds::ResourceBounds, secp256k1_point::Secp256k1Point,
9-
secp256r1_point::Secp256r1Point, tx_info::TxInfo, tx_v2_info::TxV2Info, u256::U256,
8+
execution_info_v3::ExecutionInfoV3, resource_bounds::ResourceBounds,
9+
secp256k1_point::Secp256k1Point, secp256r1_point::Secp256r1Point, tx_info::TxInfo,
10+
tx_v2_info::TxV2Info, tx_v3_info::TxV3Info, u256::U256,
1011
};
1112
use k256::elliptic_curve::{
1213
generic_array::GenericArray,
@@ -19,11 +20,13 @@ use starknet_types_core::felt::Felt;
1920
mod block_info;
2021
mod execution_info;
2122
mod execution_info_v2;
23+
mod execution_info_v3;
2224
mod resource_bounds;
2325
mod secp256k1_point;
2426
mod secp256r1_point;
2527
mod tx_info;
2628
mod tx_v2_info;
29+
mod tx_v3_info;
2730
mod u256;
2831

2932
pub type SyscallResult<T> = Result<T, Vec<Felt>>;
@@ -36,11 +39,18 @@ pub trait StarknetSyscallHandler {
3639

3740
fn get_execution_info_v2(&mut self, remaining_gas: &mut u64) -> SyscallResult<ExecutionInfoV2>;
3841

42+
fn get_execution_info_v3(
43+
&mut self,
44+
_remaining_gas: &mut u64,
45+
) -> SyscallResult<ExecutionInfoV3> {
46+
unimplemented!()
47+
}
48+
3949
fn deploy(
4050
&mut self,
4151
class_hash: Felt,
4252
contract_address_salt: Felt,
43-
calldata: Vec<Felt>,
53+
calldata: &[Felt],
4454
deploy_from_zero: bool,
4555
remaining_gas: &mut u64,
4656
) -> SyscallResult<(Felt, Vec<Felt>)>;
@@ -51,15 +61,15 @@ pub trait StarknetSyscallHandler {
5161
&mut self,
5262
class_hash: Felt,
5363
function_selector: Felt,
54-
calldata: Vec<Felt>,
64+
calldata: &[Felt],
5565
remaining_gas: &mut u64,
5666
) -> SyscallResult<Vec<Felt>>;
5767

5868
fn call_contract(
5969
&mut self,
6070
address: Felt,
6171
entry_point_selector: Felt,
62-
calldata: Vec<Felt>,
72+
calldata: &[Felt],
6373
remaining_gas: &mut u64,
6474
) -> SyscallResult<Vec<Felt>>;
6575

@@ -80,19 +90,19 @@ pub trait StarknetSyscallHandler {
8090

8191
fn emit_event(
8292
&mut self,
83-
keys: Vec<Felt>,
84-
data: Vec<Felt>,
93+
keys: &[Felt],
94+
data: &[Felt],
8595
remaining_gas: &mut u64,
8696
) -> SyscallResult<()>;
8797

8898
fn send_message_to_l1(
8999
&mut self,
90100
to_address: Felt,
91-
payload: Vec<Felt>,
101+
payload: &[Felt],
92102
remaining_gas: &mut u64,
93103
) -> SyscallResult<()>;
94104

95-
fn keccak(&mut self, input: Vec<u64>, remaining_gas: &mut u64) -> SyscallResult<U256>;
105+
fn keccak(&mut self, input: &[u64], remaining_gas: &mut u64) -> SyscallResult<U256>;
96106

97107
fn secp256k1_new(
98108
&mut self,
@@ -164,10 +174,10 @@ pub trait StarknetSyscallHandler {
164174

165175
fn sha256_process_block(
166176
&mut self,
167-
prev_state: [u32; 8],
168-
current_block: [u32; 16],
177+
prev_state: &mut [u32; 8],
178+
current_block: &[u32; 16],
169179
remaining_gas: &mut u64,
170-
) -> SyscallResult<[u32; 8]>;
180+
) -> SyscallResult<()>;
171181

172182
fn sha512_process_block(
173183
&mut self,
@@ -180,8 +190,8 @@ pub trait StarknetSyscallHandler {
180190
&mut self,
181191
_address: Felt,
182192
_entry_point_selector: Felt,
183-
_calldata: Vec<Felt>,
184-
_signature: Vec<Felt>,
193+
_calldata: &[Felt],
194+
_signature: &[Felt],
185195
_remaining_gas: &mut u64,
186196
) -> SyscallResult<Vec<Felt>> {
187197
unimplemented!();
@@ -195,7 +205,7 @@ pub trait StarknetSyscallHandler {
195205
unimplemented!()
196206
}
197207

198-
fn cheatcode(&mut self, _selector: Felt, _input: Vec<Felt>) -> Vec<Felt> {
208+
fn cheatcode(&mut self, _selector: Felt, _input: &[Felt]) -> Vec<Felt> {
199209
unimplemented!()
200210
}
201211
}
@@ -299,7 +309,7 @@ impl StarknetSyscallHandler for StubSyscallHandler {
299309
&mut self,
300310
_class_hash: Felt,
301311
_contract_address_salt: Felt,
302-
_calldata: Vec<Felt>,
312+
_calldata: &[Felt],
303313
_deploy_from_zero: bool,
304314
_remaining_gas: &mut u64,
305315
) -> SyscallResult<(Felt, Vec<Felt>)> {
@@ -314,7 +324,7 @@ impl StarknetSyscallHandler for StubSyscallHandler {
314324
&mut self,
315325
_class_hash: Felt,
316326
_function_selector: Felt,
317-
_calldata: Vec<Felt>,
327+
_calldata: &[Felt],
318328
_remaining_gas: &mut u64,
319329
) -> SyscallResult<Vec<Felt>> {
320330
unimplemented!()
@@ -324,7 +334,7 @@ impl StarknetSyscallHandler for StubSyscallHandler {
324334
&mut self,
325335
_address: Felt,
326336
_entry_point_selector: Felt,
327-
_calldata: Vec<Felt>,
337+
_calldata: &[Felt],
328338
_remaining_gas: &mut u64,
329339
) -> SyscallResult<Vec<Felt>> {
330340
unimplemented!()
@@ -356,8 +366,8 @@ impl StarknetSyscallHandler for StubSyscallHandler {
356366

357367
fn emit_event(
358368
&mut self,
359-
keys: Vec<Felt>,
360-
data: Vec<Felt>,
369+
keys: &[Felt],
370+
data: &[Felt],
361371
_remaining_gas: &mut u64,
362372
) -> SyscallResult<()> {
363373
self.events.push(StubEvent {
@@ -370,13 +380,13 @@ impl StarknetSyscallHandler for StubSyscallHandler {
370380
fn send_message_to_l1(
371381
&mut self,
372382
_to_address: Felt,
373-
_payload: Vec<Felt>,
383+
_payload: &[Felt],
374384
_remaining_gas: &mut u64,
375385
) -> SyscallResult<()> {
376386
unimplemented!()
377387
}
378388

379-
fn keccak(&mut self, input: Vec<u64>, gas: &mut u64) -> SyscallResult<U256> {
389+
fn keccak(&mut self, input: &[u64], gas: &mut u64) -> SyscallResult<U256> {
380390
let length = input.len();
381391

382392
if length % 17 != 0 {
@@ -435,7 +445,11 @@ impl StarknetSyscallHandler for StubSyscallHandler {
435445
);
436446

437447
if bool::from(point.is_some()) {
438-
Ok(Some(Secp256k1Point { x, y }))
448+
Ok(Some(Secp256k1Point {
449+
x,
450+
y,
451+
is_infinity: false,
452+
}))
439453
} else {
440454
Ok(None)
441455
}
@@ -496,9 +510,17 @@ impl StarknetSyscallHandler for StubSyscallHandler {
496510
let p = p.to_encoded_point(false);
497511
let (x, y) = match p.coordinates() {
498512
Coordinates::Uncompressed { x, y } => (x, y),
513+
Coordinates::Identity => {
514+
// P + (-P) yields the identity. Return the canonical (0, 0) +
515+
// is_infinity encoding (see Secp256k1Point::into_value).
516+
return Ok(Secp256k1Point {
517+
x: U256 { lo: 0, hi: 0 },
518+
y: U256 { lo: 0, hi: 0 },
519+
is_infinity: true,
520+
});
521+
}
499522
_ => {
500-
// This should be unreachable because we explicitly asked for the uncompressed
501-
// encoding.
523+
// We explicitly asked for the uncompressed encoding.
502524
unreachable!()
503525
}
504526
};
@@ -516,6 +538,7 @@ impl StarknetSyscallHandler for StubSyscallHandler {
516538
hi: u128::from_be_bytes(y[0..16].try_into().unwrap()),
517539
lo: u128::from_be_bytes(y[16..32].try_into().unwrap()),
518540
},
541+
is_infinity: false,
519542
})
520543
}
521544

@@ -560,9 +583,16 @@ impl StarknetSyscallHandler for StubSyscallHandler {
560583
let p = p.to_encoded_point(false);
561584
let (x, y) = match p.coordinates() {
562585
Coordinates::Uncompressed { x, y } => (x, y),
586+
Coordinates::Identity => {
587+
// m * P can be the identity (e.g. m = ord(P)).
588+
return Ok(Secp256k1Point {
589+
x: U256 { lo: 0, hi: 0 },
590+
y: U256 { lo: 0, hi: 0 },
591+
is_infinity: true,
592+
});
593+
}
563594
_ => {
564-
// This should be unreachable because we explicitly asked for the uncompressed
565-
// encoding.
595+
// We explicitly asked for the uncompressed encoding.
566596
unreachable!()
567597
}
568598
};
@@ -580,6 +610,7 @@ impl StarknetSyscallHandler for StubSyscallHandler {
580610
hi: u128::from_be_bytes(y[0..16].try_into().unwrap()),
581611
lo: u128::from_be_bytes(y[16..32].try_into().unwrap()),
582612
},
613+
is_infinity: false,
583614
})
584615
}
585616

@@ -628,6 +659,7 @@ impl StarknetSyscallHandler for StubSyscallHandler {
628659
hi: u128::from_be_bytes(y[0..16].try_into().unwrap()),
629660
lo: u128::from_be_bytes(y[16..32].try_into().unwrap()),
630661
},
662+
is_infinity: false,
631663
}))
632664
} else {
633665
Ok(None)
@@ -665,7 +697,11 @@ impl StarknetSyscallHandler for StubSyscallHandler {
665697
);
666698

667699
if bool::from(point.is_some()) {
668-
Ok(Some(Secp256r1Point { x, y }))
700+
Ok(Some(Secp256r1Point {
701+
x,
702+
y,
703+
is_infinity: false,
704+
}))
669705
} else {
670706
Ok(None)
671707
}
@@ -726,9 +762,17 @@ impl StarknetSyscallHandler for StubSyscallHandler {
726762
let p = p.to_encoded_point(false);
727763
let (x, y) = match p.coordinates() {
728764
Coordinates::Uncompressed { x, y } => (x, y),
765+
Coordinates::Identity => {
766+
// P + (-P) yields the identity. Return the canonical (0, 0) +
767+
// is_infinity encoding (see Secp256r1Point::into_value).
768+
return Ok(Secp256r1Point {
769+
x: U256 { lo: 0, hi: 0 },
770+
y: U256 { lo: 0, hi: 0 },
771+
is_infinity: true,
772+
});
773+
}
729774
_ => {
730-
// This should be unreachable because we explicitly asked for the uncompressed
731-
// encoding.
775+
// We explicitly asked for the uncompressed encoding.
732776
unreachable!()
733777
}
734778
};
@@ -746,6 +790,7 @@ impl StarknetSyscallHandler for StubSyscallHandler {
746790
hi: u128::from_be_bytes(y[0..16].try_into().unwrap()),
747791
lo: u128::from_be_bytes(y[16..32].try_into().unwrap()),
748792
},
793+
is_infinity: false,
749794
})
750795
}
751796

@@ -789,9 +834,16 @@ impl StarknetSyscallHandler for StubSyscallHandler {
789834
let p = p.to_encoded_point(false);
790835
let (x, y) = match p.coordinates() {
791836
Coordinates::Uncompressed { x, y } => (x, y),
837+
Coordinates::Identity => {
838+
// m * P can be the identity (e.g. m = ord(P)).
839+
return Ok(Secp256r1Point {
840+
x: U256 { lo: 0, hi: 0 },
841+
y: U256 { lo: 0, hi: 0 },
842+
is_infinity: true,
843+
});
844+
}
792845
_ => {
793-
// This should be unreachable because we explicitly asked for the uncompressed
794-
// encoding.
846+
// We explicitly asked for the uncompressed encoding.
795847
unreachable!()
796848
}
797849
};
@@ -809,6 +861,7 @@ impl StarknetSyscallHandler for StubSyscallHandler {
809861
hi: u128::from_be_bytes(y[0..16].try_into().unwrap()),
810862
lo: u128::from_be_bytes(y[16..32].try_into().unwrap()),
811863
},
864+
is_infinity: false,
812865
})
813866
}
814867

@@ -846,6 +899,7 @@ impl StarknetSyscallHandler for StubSyscallHandler {
846899
hi: u128::from_be_bytes(y[0..16].try_into().unwrap()),
847900
lo: u128::from_be_bytes(y[16..32].try_into().unwrap()),
848901
},
902+
is_infinity: false,
849903
}))
850904
} else {
851905
Ok(None)
@@ -862,17 +916,16 @@ impl StarknetSyscallHandler for StubSyscallHandler {
862916

863917
fn sha256_process_block(
864918
&mut self,
865-
prev_state: [u32; 8],
866-
current_block: [u32; 16],
919+
prev_state: &mut [u32; 8],
920+
current_block: &[u32; 16],
867921
_remaining_gas: &mut u64,
868-
) -> SyscallResult<[u32; 8]> {
869-
let mut state = prev_state;
922+
) -> SyscallResult<()> {
870923
let data_as_bytes = sha2::digest::generic_array::GenericArray::from_exact_iter(
871924
current_block.iter().flat_map(|x| x.to_be_bytes()),
872925
)
873926
.unwrap();
874-
sha2::compress256(&mut state, &[data_as_bytes]);
875-
Ok(state)
927+
sha2::compress256(prev_state, &[data_as_bytes]);
928+
Ok(())
876929
}
877930

878931
fn sha512_process_block(
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
use super::{BlockInfo, TxV3Info};
2+
use serde::Serialize;
3+
use starknet_types_core::felt::Felt;
4+
5+
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
6+
pub struct ExecutionInfoV3 {
7+
pub block_info: BlockInfo,
8+
pub tx_info: TxV3Info,
9+
pub caller_address: Felt,
10+
pub contract_address: Felt,
11+
pub entry_point_selector: Felt,
12+
}

0 commit comments

Comments
 (0)