Skip to content

Commit f53991f

Browse files
starknet_os_flow_tests: fuzz test get block hash scenario
1 parent 04c43c5 commit f53991f

7 files changed

Lines changed: 223 additions & 53 deletions

File tree

crates/blockifier_test_utils/resources/feature_contracts/cairo0/compiled/fuzz_revert_compiled.json

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
],
5050
"EXTERNAL": [
5151
{
52-
"offset": 716,
52+
"offset": 728,
5353
"selector": "0x8e64dfac867f301a439703710296f437e9f91d1bba17cfea5ad7f137a5acd"
5454
},
5555
{
@@ -157,18 +157,36 @@
157157
"__main__",
158158
"__main__.test_revert_fuzz"
159159
],
160-
"end_pc": 712,
160+
"end_pc": 716,
161161
"flow_tracking_data": {
162162
"ap_tracking": {
163163
"group": 27,
164-
"offset": 73
164+
"offset": 74
165+
},
166+
"reference_ids": {}
167+
},
168+
"name": "error_message",
169+
"start_pc": 712,
170+
"value": "get_block_hash_cairo0"
171+
},
172+
{
173+
"accessible_scopes": [
174+
"__main__",
175+
"__main__",
176+
"__main__.test_revert_fuzz"
177+
],
178+
"end_pc": 724,
179+
"flow_tracking_data": {
180+
"ap_tracking": {
181+
"group": 27,
182+
"offset": 74
165183
},
166184
"reference_ids": {
167185
"__main__.test_revert_fuzz.scenario": 9
168186
}
169187
},
170188
"name": "error_message",
171-
"start_pc": 708,
189+
"start_pc": 720,
172190
"value": "Unknown scenario: {scenario}."
173191
}
174192
],
@@ -886,20 +904,32 @@
886904
"0x1104800180018000",
887905
"0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe42",
888906
"0x208b7fff7fff7ffe",
907+
"0x4826800180018000",
908+
"0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff0",
909+
"0x20680017fff7fff",
910+
"0xa",
911+
"0x480680017fff8000",
912+
"0x1",
913+
"0x400680017fff7fff",
914+
"0x0",
915+
"0x48127fe97fff8000",
916+
"0x48127fe97fff8000",
917+
"0x48127fe97fff8000",
918+
"0x208b7fff7fff7ffe",
889919
"0x480680017fff8000",
890920
"0x0",
891921
"0x400680017fff7fff",
892922
"0x1",
893-
"0x48127fea7fff8000",
894-
"0x48127fea7fff8000",
895-
"0x48127fea7fff8000",
923+
"0x48127fe97fff8000",
924+
"0x48127fe97fff8000",
925+
"0x48127fe97fff8000",
896926
"0x208b7fff7fff7ffe",
897927
"0x402b7ffd7ffc7ffd",
898928
"0x480280007ffb8000",
899929
"0x480280017ffb8000",
900930
"0x480280027ffb8000",
901931
"0x1104800180018000",
902-
"0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe33",
932+
"0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffe27",
903933
"0x40780017fff7fff",
904934
"0x1",
905935
"0x48127ffc7fff8000",
@@ -1126,7 +1156,7 @@
11261156
}
11271157
}
11281158
],
1129-
"722": [
1159+
"734": [
11301160
{
11311161
"accessible_scopes": [
11321162
"__main__",
@@ -1256,6 +1286,10 @@
12561286
"type": "const",
12571287
"value": 16
12581288
},
1289+
"__main__.SCENARIO_GET_BLOCK_HASH": {
1290+
"type": "const",
1291+
"value": 17
1292+
},
12591293
"__main__.SCENARIO_INCREMENT_COUNTER": {
12601294
"type": "const",
12611295
"value": 7
@@ -1906,7 +1940,7 @@
19061940
"decorators": [
19071941
"external"
19081942
],
1909-
"pc": 716,
1943+
"pc": 728,
19101944
"type": "function"
19111945
},
19121946
"__wrappers__.test_revert_fuzz.Args": {

crates/blockifier_test_utils/resources/feature_contracts/cairo0/fuzz_revert.cairo

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const SCENARIO_CALL_UNDEPLOYED = 13;
3030
const SCENARIO_CALL_NON_EXISTING_ENTRY_POINT = 14;
3131
const SCENARIO_LIBRARY_CALL_NON_EXISTING_ENTRY_POINT = 15;
3232
const SCENARIO_EMIT_EVENT = 16;
33+
const SCENARIO_GET_BLOCK_HASH = 17;
3334

3435
// selector_from_name("pop_front").
3536
const POP_FRONT_SELECTOR = 0x289c2d7d6351cd03d4f928bde75fa14d5f52e32bdbc750d5296e1b48c12f1c3;
@@ -256,6 +257,13 @@ func test_revert_fuzz{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_chec
256257
return ();
257258
}
258259

260+
if (scenario == SCENARIO_GET_BLOCK_HASH) {
261+
with_attr error_message("get_block_hash_cairo0") {
262+
assert 0 = 1;
263+
}
264+
return ();
265+
}
266+
259267
with_attr error_message("Unknown scenario: {scenario}.") {
260268
assert 1 = 0;
261269
}

crates/blockifier_test_utils/resources/feature_contracts/cairo1/fuzz_revert.cairo

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ trait IOrchestrator<TContractState> {
77
fn should_fail_undeployed_panic_message(ref self: TContractState) -> felt252;
88
fn should_fail_call_no_entrypoint_panic_message(ref self: TContractState) -> felt252;
99
fn should_fail_libcall_no_entrypoint_panic_message(ref self: TContractState) -> felt252;
10+
fn should_fail_get_block_hash_panic_message(ref self: TContractState) -> felt252;
11+
fn should_succeed_get_block_hash_panic_message(ref self: TContractState) -> felt252;
1012
}
1113

1214
#[starknet::contract]
@@ -39,6 +41,7 @@ mod FuzzRevertContract {
3941
CallNonExistingEntryPoint,
4042
LibraryCallNonExistingEntryPoint,
4143
EmitEvent,
44+
GetBlockHash,
4245
}
4346

4447
impl FeltTryIntoScenario of TryInto<felt252, Scenario> {
@@ -64,6 +67,7 @@ mod FuzzRevertContract {
6467
14 => Some(Scenario::CallNonExistingEntryPoint),
6568
15 => Some(Scenario::LibraryCallNonExistingEntryPoint),
6669
16 => Some(Scenario::EmitEvent),
70+
17 => Some(Scenario::GetBlockHash),
6771
_ => None,
6872
}
6973
}
@@ -112,6 +116,19 @@ mod FuzzRevertContract {
112116
}
113117
}
114118

119+
/// If should_unwrap is true, prepends the orchestrator index to the error and panics.
120+
fn maybe_unwrap_error(ref self: ContractState, error: Array<felt252>, should_unwrap: bool) {
121+
if should_unwrap {
122+
// The inner error does not contain the orchestrator index, so to propagate
123+
// the error the index must be prepended.
124+
let mut new_error: Array<felt252> = array![self.orchestrator().get_index()];
125+
for elem in error {
126+
new_error.append(elem);
127+
}
128+
panic(new_error);
129+
}
130+
}
131+
115132
/// Handle a syscall that immediately fails (e.g. calling a non-existing entry point).
116133
fn handle_syscall_immediate_failure(
117134
ref self: ContractState,
@@ -121,20 +138,7 @@ mod FuzzRevertContract {
121138
) {
122139
match result {
123140
Result::Ok(_) => panic_with_felt252(panic_message_if_ok),
124-
Result::Err(mut error) => {
125-
// Syscall failed immediately, so no inner calls could have modified the
126-
// orchestrator index. No need to handle index propagation (the !should_unwrap
127-
// case).
128-
if should_unwrap {
129-
// The inner error does not contain the orchestrator index, so to propagate
130-
// the error the index must be prepended.
131-
let mut new_error: Array<felt252> = array![self.orchestrator().get_index()];
132-
for elem in error {
133-
new_error.append(elem);
134-
}
135-
panic(new_error);
136-
}
137-
}
141+
Result::Err(error) => self.maybe_unwrap_error(error, should_unwrap),
138142
}
139143
}
140144
}
@@ -272,6 +276,22 @@ mod FuzzRevertContract {
272276
);
273277
},
274278
Scenario::EmitEvent => { self.emit(FuzzEvent { data: orchestrator.pop_front() }); },
279+
Scenario::GetBlockHash => {
280+
let block_number: u64 = orchestrator.pop_front().try_into().unwrap();
281+
let expect_panic: bool = orchestrator.pop_front() != 0;
282+
let should_unwrap = true;
283+
match syscalls::get_block_hash_syscall(block_number) {
284+
Result::Ok(_) => assert(
285+
!expect_panic, orchestrator.should_fail_get_block_hash_panic_message()
286+
),
287+
Result::Err(error) => {
288+
assert(
289+
expect_panic, orchestrator.should_succeed_get_block_hash_panic_message()
290+
);
291+
self.maybe_unwrap_error(error, should_unwrap);
292+
}
293+
}
294+
},
275295
}
276296

277297
// Unless explicitly stated otherwise, the next operation should be in the current call

crates/blockifier_test_utils/resources/feature_contracts/cairo1/fuzz_revert_2.cairo

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ trait IOrchestrator<TContractState> {
99
fn should_fail_undeployed_panic_message(ref self: TContractState) -> felt252;
1010
fn should_fail_call_no_entrypoint_panic_message(ref self: TContractState) -> felt252;
1111
fn should_fail_libcall_no_entrypoint_panic_message(ref self: TContractState) -> felt252;
12+
fn should_fail_get_block_hash_panic_message(ref self: TContractState) -> felt252;
13+
fn should_succeed_get_block_hash_panic_message(ref self: TContractState) -> felt252;
1214
}
1315

1416
#[starknet::contract]
@@ -41,6 +43,7 @@ mod FuzzRevertContract {
4143
CallNonExistingEntryPoint,
4244
LibraryCallNonExistingEntryPoint,
4345
EmitEvent,
46+
GetBlockHash,
4447
}
4548

4649
impl FeltTryIntoScenario of TryInto<felt252, Scenario> {
@@ -66,6 +69,7 @@ mod FuzzRevertContract {
6669
14 => Some(Scenario::CallNonExistingEntryPoint),
6770
15 => Some(Scenario::LibraryCallNonExistingEntryPoint),
6871
16 => Some(Scenario::EmitEvent),
72+
17 => Some(Scenario::GetBlockHash),
6973
_ => None,
7074
}
7175
}
@@ -114,6 +118,19 @@ mod FuzzRevertContract {
114118
}
115119
}
116120

121+
/// If should_unwrap is true, prepends the orchestrator index to the error and panics.
122+
fn maybe_unwrap_error(ref self: ContractState, error: Array<felt252>, should_unwrap: bool) {
123+
if should_unwrap {
124+
// The inner error does not contain the orchestrator index, so to propagate
125+
// the error the index must be prepended.
126+
let mut new_error: Array<felt252> = array![self.orchestrator().get_index()];
127+
for elem in error {
128+
new_error.append(elem);
129+
}
130+
panic(new_error);
131+
}
132+
}
133+
117134
/// Handle a syscall that immediately fails (e.g. calling a non-existing entry point).
118135
fn handle_syscall_immediate_failure(
119136
ref self: ContractState,
@@ -123,20 +140,7 @@ mod FuzzRevertContract {
123140
) {
124141
match result {
125142
Result::Ok(_) => panic_with_felt252(panic_message_if_ok),
126-
Result::Err(mut error) => {
127-
// Syscall failed immediately, so no inner calls could have modified the
128-
// orchestrator index. No need to handle index propagation (the !should_unwrap
129-
// case).
130-
if should_unwrap {
131-
// The inner error does not contain the orchestrator index, so to propagate
132-
// the error the index must be prepended.
133-
let mut new_error: Array<felt252> = array![self.orchestrator().get_index()];
134-
for elem in error {
135-
new_error.append(elem);
136-
}
137-
panic(new_error);
138-
}
139-
}
143+
Result::Err(error) => self.maybe_unwrap_error(error, should_unwrap),
140144
}
141145
}
142146
}
@@ -274,6 +278,22 @@ mod FuzzRevertContract {
274278
);
275279
},
276280
Scenario::EmitEvent => { self.emit(FuzzEvent { data: orchestrator.pop_front() }); },
281+
Scenario::GetBlockHash => {
282+
let block_number: u64 = orchestrator.pop_front().try_into().unwrap();
283+
let expect_panic: bool = orchestrator.pop_front() != 0;
284+
let should_unwrap = true;
285+
match syscalls::get_block_hash_syscall(block_number) {
286+
Result::Ok(_) => assert(
287+
!expect_panic, orchestrator.should_fail_get_block_hash_panic_message()
288+
),
289+
Result::Err(error) => {
290+
assert(
291+
expect_panic, orchestrator.should_succeed_get_block_hash_panic_message()
292+
);
293+
self.maybe_unwrap_error(error, should_unwrap);
294+
}
295+
}
296+
},
277297
}
278298

279299
// Unless explicitly stated otherwise, the next operation should be in the current call

crates/blockifier_test_utils/resources/feature_contracts/cairo1/fuzz_revert_orchestrator.cairo

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ mod FuzzRevertOrchestratorContract {
1010
const UNEXPECTED_FAIL_UNDEPLOYED: felt252 = 'should_fail_undeployed';
1111
const UNEXPECTED_FAIL_CALL_NO_ENTRYPOINT: felt252 = 'call_no_entrypoint';
1212
const UNEXPECTED_FAIL_LIBCALL_NO_ENTRYPOINT: felt252 = 'libcall_no_entrypoint';
13+
const UNEXPECTED_SUCCESS_GET_BLOCK_HASH: felt252 = 'get_block_hash_success';
14+
const UNEXPECTED_FAIL_GET_BLOCK_HASH: felt252 = 'get_block_hash_fail';
1315

1416
#[storage]
1517
struct Storage {
@@ -52,11 +54,14 @@ mod FuzzRevertOrchestratorContract {
5254
/// will panic (this can happen if an unexpected error occurs and is propagated).
5355
#[external(v0)]
5456
fn set_index(ref self: ContractState, index: felt252) {
57+
let error = array![OOB_ERROR, index];
5558
let index_u64: u64 = match index.try_into() {
5659
Option::Some(val) => val,
57-
Option::None => panic_with_felt252(OOB_ERROR),
60+
Option::None => panic(error),
5861
};
59-
assert(index_u64 <= self.scenarios.len(), OOB_ERROR);
62+
if index_u64 > self.scenarios.len() {
63+
panic(error);
64+
}
6065
self.front_index.write(index_u64);
6166
}
6267

@@ -83,26 +88,49 @@ mod FuzzRevertOrchestratorContract {
8388
UNEXPECTED_FAIL_LIBCALL_NO_ENTRYPOINT
8489
}
8590

91+
#[external(v0)]
92+
fn should_fail_get_block_hash_panic_message(ref self: ContractState) -> felt252 {
93+
UNEXPECTED_SUCCESS_GET_BLOCK_HASH
94+
}
95+
96+
#[external(v0)]
97+
fn should_succeed_get_block_hash_panic_message(ref self: ContractState) -> felt252 {
98+
UNEXPECTED_FAIL_GET_BLOCK_HASH
99+
}
100+
86101
/// Start the test. The first address must be an initialized fuzz test contract.
87102
#[external(v0)]
88103
fn start_test(ref self: ContractState, first_address: ContractAddress) {
89104
match syscalls::call_contract_syscall(
90105
first_address, selector!("test_revert_fuzz"), array![].span(),
91106
) {
92107
Result::Ok(_) => (),
93-
Result::Err(mut error) => {
94-
// Assert the error is not any unexpected error.
95-
let error_value = error.pop_front().unwrap();
96-
for unexpected_error in array![
108+
Result::Err(error) => {
109+
// Assert the error does not contain any unexpected error.
110+
let unexpected_errors = array![
97111
UNEXPECTED_FAIL_INVALID_SCENARIO,
98112
OOB_ERROR,
99113
UNEXPECTED_FAIL_UNDEPLOYED,
100114
UNEXPECTED_FAIL_CALL_NO_ENTRYPOINT,
101-
UNEXPECTED_FAIL_LIBCALL_NO_ENTRYPOINT
115+
UNEXPECTED_FAIL_LIBCALL_NO_ENTRYPOINT,
116+
UNEXPECTED_SUCCESS_GET_BLOCK_HASH,
117+
UNEXPECTED_FAIL_GET_BLOCK_HASH
102118
]
119+
.span();
120+
let mut contains_unexpected_error = false;
121+
for error_value in error
103122
.span() {
104-
assert(error_value != *unexpected_error, *unexpected_error);
123+
for unexpected_error in unexpected_errors {
124+
if error_value == unexpected_error {
125+
contains_unexpected_error = true;
126+
break;
127+
}
128+
}
105129
}
130+
131+
if contains_unexpected_error {
132+
panic(error);
133+
}
106134
}
107135
}
108136
}

0 commit comments

Comments
 (0)