Skip to content

Commit f5dde71

Browse files
committed
feat(tasm_object): Verify correct Option<T> discriminant value
1 parent 7edf8ca commit f5dde71

File tree

3 files changed

+134
-27
lines changed

3 files changed

+134
-27
lines changed

tasm-lib/benchmarks/tasmlib_structure_verify_nd_si_integrity___TransactionKernelLookalike.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,21 @@
22
{
33
"name": "tasmlib_structure_verify_nd_si_integrity___TransactionKernelLookalike",
44
"benchmark_result": {
5-
"clock_cycle_count": 270,
6-
"hash_table_height": 384,
5+
"clock_cycle_count": 278,
6+
"hash_table_height": 390,
77
"u32_table_height": 240,
8-
"op_stack_table_height": 176,
8+
"op_stack_table_height": 184,
99
"ram_table_height": 15
1010
},
1111
"case": "CommonCase"
1212
},
1313
{
1414
"name": "tasmlib_structure_verify_nd_si_integrity___TransactionKernelLookalike",
1515
"benchmark_result": {
16-
"clock_cycle_count": 236,
17-
"hash_table_height": 384,
16+
"clock_cycle_count": 244,
17+
"hash_table_height": 390,
1818
"u32_table_height": 212,
19-
"op_stack_table_height": 156,
19+
"op_stack_table_height": 164,
2020
"ram_table_height": 14
2121
},
2222
"case": "WorstCase"

tasm-lib/src/structure/manual_tasm_object_implementations.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,18 @@ impl<T: TasmObject + BFieldCodec> TasmObject for Option<T> {
654654
addi 2
655655
// _ discriminant (*discriminant + 1)
656656

657+
/* Ensure discriminant has legal value */
658+
dup 1
659+
push 0
660+
eq
661+
dup 2
662+
push 1
663+
eq
664+
add
665+
// _ discriminant (*discriminant + 1) ((discriminant == 0) || (discriminant == 1))
666+
667+
assert
668+
657669
swap 1
658670
// _ (*discriminant + 1) discriminant
659671

tasm-lib/src/structure/verify_nd_si_integrity.rs

Lines changed: 116 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::fmt::Debug;
12
use std::marker::PhantomData;
23

34
use triton_vm::prelude::*;
@@ -7,11 +8,12 @@ use crate::library::Library;
78
use crate::prelude::BasicSnippet;
89
use crate::prelude::TasmObject;
910

10-
pub struct VerifyNdSiIntegrity<T: TasmObject + BFieldCodec> {
11+
#[derive(Clone, Debug)]
12+
pub struct VerifyNdSiIntegrity<T: TasmObject + BFieldCodec + Clone + Debug> {
1113
_phantom_data: PhantomData<T>,
1214
}
1315

14-
impl<T: TasmObject + BFieldCodec> BasicSnippet for VerifyNdSiIntegrity<T> {
16+
impl<T: TasmObject + BFieldCodec + Clone + Debug> BasicSnippet for VerifyNdSiIntegrity<T> {
1517
fn inputs(&self) -> Vec<(DataType, String)> {
1618
vec![(DataType::VoidPointer, "*struct".to_owned())]
1719
}
@@ -83,7 +85,7 @@ mod tests {
8385

8486
use super::*;
8587

86-
impl<T: TasmObject + BFieldCodec + for<'a> Arbitrary<'a> + Debug> VerifyNdSiIntegrity<T> {
88+
impl<T: TasmObject + BFieldCodec + for<'a> Arbitrary<'a> + Debug + Clone> VerifyNdSiIntegrity<T> {
8789
fn initial_state(&self, address: BFieldElement, t: T) -> AccessorInitialState {
8890
let mut memory = HashMap::default();
8991
encode_to_memory(&mut memory, address, &t);
@@ -100,7 +102,7 @@ mod tests {
100102
}
101103
}
102104

103-
impl<T: TasmObject + BFieldCodec + for<'a> Arbitrary<'a> + Debug> Accessor
105+
impl<T: TasmObject + BFieldCodec + for<'a> Arbitrary<'a> + Debug + Clone> Accessor
104106
for VerifyNdSiIntegrity<T>
105107
{
106108
fn rust_shadow(
@@ -237,7 +239,7 @@ mod tests {
237239

238240
let begin_address = bfe!(4);
239241
let mut init_state =
240-
snippet.initial_state(begin_address, snippet.prepare_random_object(&[42u8; 200]));
242+
snippet.initial_state(begin_address, snippet.prepare_random_object(&[42u8; 20000]));
241243
let vec_digest_len_indicator = begin_address + bfe!(1);
242244
let true_value = init_state.memory[&vec_digest_len_indicator];
243245
init_state
@@ -251,31 +253,124 @@ mod tests {
251253
}
252254
}
253255

254-
#[test]
255-
fn test_option_stat_sized_elem() {
256+
mod option_types {
257+
use crate::test_helpers::negative_test;
258+
use rand::thread_rng;
259+
use rand::RngCore;
260+
261+
use super::*;
262+
256263
#[derive(Debug, Clone, TasmObject, BFieldCodec, Arbitrary)]
257-
struct TestStruct {
264+
struct StatSizedPayload {
258265
a: Option<Digest>,
259266
}
260-
let snippet: VerifyNdSiIntegrity<TestStruct> = VerifyNdSiIntegrity {
261-
_phantom_data: PhantomData,
262-
};
263-
ShadowedAccessor::new(snippet).test();
264-
}
265267

266-
#[test]
267-
fn test_option_dyn_sized_elem() {
268-
#[derive(Debug, Clone, TasmObject, BFieldCodec, Arbitrary)]
269-
struct TestStruct {
268+
#[derive(Debug, Clone, TasmObject, BFieldCodec, Arbitrary, Default)]
269+
struct DynSizedPayload {
270270
a: Option<Vec<u128>>,
271271
b: Digest,
272272
c: Vec<Vec<BFieldElement>>,
273273
d: Option<Vec<Option<BFieldElement>>>,
274274
}
275-
let snippet: VerifyNdSiIntegrity<TestStruct> = VerifyNdSiIntegrity {
276-
_phantom_data: PhantomData,
277-
};
278-
ShadowedAccessor::new(snippet).test();
275+
276+
#[test]
277+
fn test_option_stat_sized_elem() {
278+
let snippet: VerifyNdSiIntegrity<StatSizedPayload> = VerifyNdSiIntegrity {
279+
_phantom_data: PhantomData,
280+
};
281+
ShadowedAccessor::new(snippet).test();
282+
}
283+
284+
#[test]
285+
fn test_option_dyn_sized_elem() {
286+
let snippet: VerifyNdSiIntegrity<DynSizedPayload> = VerifyNdSiIntegrity {
287+
_phantom_data: PhantomData,
288+
};
289+
ShadowedAccessor::new(snippet).test();
290+
}
291+
292+
#[test]
293+
fn lie_about_option_payload_field_size() {
294+
let snippet: VerifyNdSiIntegrity<DynSizedPayload> = VerifyNdSiIntegrity {
295+
_phantom_data: PhantomData,
296+
};
297+
298+
let begin_address = bfe!(4);
299+
let mut randomness = [0u8; 100_000];
300+
thread_rng().fill_bytes(&mut randomness);
301+
let obj = snippet.prepare_random_object(&randomness);
302+
let true_init_state = snippet.initial_state(begin_address, obj.clone());
303+
304+
/* Lie about size of field 'd'*/
305+
let mut manipulated_si_outer = true_init_state.clone();
306+
let outer_option_payload_si_ptr = begin_address; // The field size-indicator of `d` field
307+
let true_value = true_init_state.memory[&outer_option_payload_si_ptr];
308+
manipulated_si_outer
309+
.memory
310+
.insert(outer_option_payload_si_ptr, true_value + bfe!(1));
311+
negative_test(
312+
&ShadowedAccessor::new(snippet),
313+
manipulated_si_outer.into(),
314+
&[InstructionError::AssertionFailed],
315+
);
316+
}
317+
318+
#[test]
319+
fn illegal_discriminant_value_for_option() {
320+
let snippet: VerifyNdSiIntegrity<DynSizedPayload> = VerifyNdSiIntegrity {
321+
_phantom_data: PhantomData,
322+
};
323+
324+
let obj = DynSizedPayload::default();
325+
let begin_address = bfe!(4);
326+
let mut manipulated_init_state = snippet.initial_state(begin_address, obj.clone());
327+
let option_discriminant_ptr = begin_address + bfe!(1);
328+
manipulated_init_state
329+
.memory
330+
.insert(option_discriminant_ptr, bfe!(2));
331+
negative_test(
332+
&ShadowedAccessor::new(snippet.clone()),
333+
manipulated_init_state.into(),
334+
&[InstructionError::AssertionFailed],
335+
);
336+
}
337+
338+
#[test]
339+
fn lie_about_option_payload_size() {
340+
let snippet: VerifyNdSiIntegrity<DynSizedPayload> = VerifyNdSiIntegrity {
341+
_phantom_data: PhantomData,
342+
};
343+
344+
let obj = DynSizedPayload {
345+
d: Some(vec![Some(bfe!(14)), None, Some(bfe!(15))]),
346+
..Default::default()
347+
};
348+
let begin_address = bfe!(4);
349+
let true_init_state = snippet.initial_state(begin_address, obj.clone());
350+
351+
/* Lie about size of payload of outer Some(...)*/
352+
let mut add_one = true_init_state.clone();
353+
let len_of_dyn_sized_list_elem_0 = begin_address + bfe!(3);
354+
let true_value = true_init_state.memory[&len_of_dyn_sized_list_elem_0];
355+
add_one
356+
.memory
357+
.insert(len_of_dyn_sized_list_elem_0, true_value + bfe!(1));
358+
negative_test(
359+
&ShadowedAccessor::new(snippet.clone()),
360+
add_one.into(),
361+
&[InstructionError::AssertionFailed],
362+
);
363+
364+
let mut sub_one = true_init_state.clone();
365+
sub_one
366+
.memory
367+
.insert(len_of_dyn_sized_list_elem_0, true_value - bfe!(1));
368+
negative_test(
369+
&ShadowedAccessor::new(snippet),
370+
sub_one.into(),
371+
&[InstructionError::AssertionFailed],
372+
);
373+
}
279374
}
280375

281376
#[test]

0 commit comments

Comments
 (0)