@@ -83,18 +83,172 @@ mod tests {
83
83
84
84
use super :: * ;
85
85
86
- #[ test]
87
- fn test_pbt_simple_struct ( ) {
86
+ impl < T : TasmObject + BFieldCodec + for < ' a > Arbitrary < ' a > + Debug > VerifyNdSiIntegrity < T > {
87
+ fn initial_state ( & self , address : BFieldElement , t : T ) -> AccessorInitialState {
88
+ let mut memory = HashMap :: default ( ) ;
89
+ encode_to_memory ( & mut memory, address, & t) ;
90
+
91
+ AccessorInitialState {
92
+ stack : [ self . init_stack_for_isolated_run ( ) , vec ! [ address] ] . concat ( ) ,
93
+ memory,
94
+ }
95
+ }
96
+
97
+ fn prepare_random_object ( & self , randomness : & [ u8 ] ) -> T {
98
+ let unstructured = Unstructured :: new ( randomness) ;
99
+ T :: arbitrary_take_rest ( unstructured) . unwrap ( )
100
+ }
101
+ }
102
+
103
+ impl < T : TasmObject + BFieldCodec + for < ' a > Arbitrary < ' a > + Debug > Accessor
104
+ for VerifyNdSiIntegrity < T >
105
+ {
106
+ fn rust_shadow (
107
+ & self ,
108
+ stack : & mut Vec < BFieldElement > ,
109
+ memory : & HashMap < BFieldElement , BFieldElement > ,
110
+ ) {
111
+ // If the type can be decoded then it must have valid size indicators
112
+ let pointer = stack. pop ( ) . unwrap ( ) ;
113
+ let obj = T :: decode_from_memory ( memory, pointer) . unwrap ( ) ;
114
+ let encoding_len = obj. encode ( ) . len ( ) ;
115
+ let encoding_len: u32 = encoding_len. try_into ( ) . unwrap ( ) ;
116
+
117
+ // Verify contained in ND-region
118
+ let start_address: u32 = pointer. value ( ) . try_into ( ) . unwrap ( ) ;
119
+ let _end_address = start_address. checked_add ( encoding_len) . unwrap ( ) ;
120
+
121
+ stack. push ( bfe ! ( obj. encode( ) . len( ) as u64 ) ) ;
122
+ }
123
+
124
+ fn pseudorandom_initial_state (
125
+ & self ,
126
+ seed : [ u8 ; 32 ] ,
127
+ _bench_case : Option < BenchmarkCase > ,
128
+ ) -> AccessorInitialState {
129
+ let mut rng: StdRng = SeedableRng :: from_seed ( seed) ;
130
+
131
+ let t: T = {
132
+ let mut randomness = [ 0u8 ; 100000 ] ;
133
+ rng. fill ( & mut randomness) ;
134
+ self . prepare_random_object ( & randomness)
135
+ } ;
136
+
137
+ let address: u32 = rng. gen_range ( 0 ..( 1 << 30 ) ) ;
138
+ let address = bfe ! ( address) ;
139
+ self . initial_state ( address, t)
140
+ }
141
+
142
+ fn corner_case_initial_states ( & self ) -> Vec < AccessorInitialState > {
143
+ // This *should* always return `None` if `T: Option<S>`, and empty
144
+ // vec if type is Vec<T>. So some notion of "empty" or default.
145
+ let empty_struct: T = {
146
+ let unstructured = Unstructured :: new ( & [ ] ) ;
147
+ T :: arbitrary_take_rest ( unstructured) . unwrap ( )
148
+ } ;
149
+
150
+ println ! ( "empty_struct:\n {empty_struct:?}" ) ;
151
+ let empty_struct_at_zero = self . initial_state ( BFieldElement :: ZERO , empty_struct) ;
152
+
153
+ vec ! [ empty_struct_at_zero]
154
+ }
155
+ }
156
+
157
+ mod simple_struct {
158
+ use crate :: test_helpers:: negative_test;
159
+
160
+ use super :: * ;
161
+
88
162
#[ derive( Debug , Clone , TasmObject , BFieldCodec , Arbitrary ) ]
89
163
struct TestStruct {
90
164
a : Vec < u128 > ,
91
165
b : Digest ,
92
166
c : Vec < Digest > ,
93
167
}
94
- let snippet: VerifyNdSiIntegrity < TestStruct > = VerifyNdSiIntegrity {
95
- _phantom_data : PhantomData ,
96
- } ;
97
- ShadowedAccessor :: new ( snippet) . test ( ) ;
168
+
169
+ #[ test]
170
+ fn test_pbt_simple_struct ( ) {
171
+ let snippet: VerifyNdSiIntegrity < TestStruct > = VerifyNdSiIntegrity {
172
+ _phantom_data : PhantomData ,
173
+ } ;
174
+ ShadowedAccessor :: new ( snippet) . test ( ) ;
175
+ }
176
+
177
+ #[ test]
178
+ fn struct_not_contained_in_nd_region ( ) {
179
+ let snippet: VerifyNdSiIntegrity < TestStruct > = VerifyNdSiIntegrity {
180
+ _phantom_data : PhantomData ,
181
+ } ;
182
+
183
+ let t: TestStruct = snippet. prepare_random_object ( & [ ] ) ;
184
+ let begin_address = bfe ! ( ( 1u64 << 32 ) - 4 ) ;
185
+ let init_state = snippet. initial_state ( begin_address, t. clone ( ) ) ;
186
+
187
+ let actual_size = t. encode ( ) . len ( ) ;
188
+ let end_address = begin_address + bfe ! ( actual_size as u64 ) ;
189
+ negative_test (
190
+ & ShadowedAccessor :: new ( snippet) ,
191
+ init_state. into ( ) ,
192
+ & [ InstructionError :: FailedU32Conversion ( end_address) ] ,
193
+ )
194
+ }
195
+
196
+ #[ test]
197
+ fn struct_does_not_start_in_nd_region ( ) {
198
+ let snippet: VerifyNdSiIntegrity < TestStruct > = VerifyNdSiIntegrity {
199
+ _phantom_data : PhantomData ,
200
+ } ;
201
+
202
+ let begin_address = bfe ! ( -4 ) ;
203
+ let init_state =
204
+ snippet. initial_state ( begin_address, snippet. prepare_random_object ( & [ ] ) ) ;
205
+ negative_test (
206
+ & ShadowedAccessor :: new ( snippet) ,
207
+ init_state. into ( ) ,
208
+ & [ InstructionError :: FailedU32Conversion ( begin_address) ] ,
209
+ )
210
+ }
211
+
212
+ #[ test]
213
+ fn lie_about_digest_vec_size ( ) {
214
+ let snippet: VerifyNdSiIntegrity < TestStruct > = VerifyNdSiIntegrity {
215
+ _phantom_data : PhantomData ,
216
+ } ;
217
+
218
+ let begin_address = bfe ! ( 4 ) ;
219
+ let mut init_state =
220
+ snippet. initial_state ( begin_address, snippet. prepare_random_object ( & [ ] ) ) ;
221
+ let true_value = init_state. memory [ & begin_address] ;
222
+ init_state
223
+ . memory
224
+ . insert ( begin_address, true_value + bfe ! ( 1 ) ) ;
225
+ negative_test (
226
+ & ShadowedAccessor :: new ( snippet) ,
227
+ init_state. into ( ) ,
228
+ & [ InstructionError :: AssertionFailed ] ,
229
+ )
230
+ }
231
+
232
+ #[ test]
233
+ fn lie_about_digest_vec_len ( ) {
234
+ let snippet: VerifyNdSiIntegrity < TestStruct > = VerifyNdSiIntegrity {
235
+ _phantom_data : PhantomData ,
236
+ } ;
237
+
238
+ let begin_address = bfe ! ( 4 ) ;
239
+ let mut init_state =
240
+ snippet. initial_state ( begin_address, snippet. prepare_random_object ( & [ 42u8 ; 200 ] ) ) ;
241
+ let vec_digest_len_indicator = begin_address + bfe ! ( 1 ) ;
242
+ let true_value = init_state. memory [ & vec_digest_len_indicator] ;
243
+ init_state
244
+ . memory
245
+ . insert ( vec_digest_len_indicator, true_value + bfe ! ( 1 ) ) ;
246
+ negative_test (
247
+ & ShadowedAccessor :: new ( snippet) ,
248
+ init_state. into ( ) ,
249
+ & [ InstructionError :: AssertionFailed ] ,
250
+ )
251
+ }
98
252
}
99
253
100
254
#[ test]
@@ -409,71 +563,6 @@ mod tests {
409
563
} ;
410
564
ShadowedAccessor :: new ( snippet) . test ( ) ;
411
565
}
412
-
413
- impl < T : TasmObject + BFieldCodec > VerifyNdSiIntegrity < T > {
414
- fn initial_state ( & self , address : BFieldElement , t : T ) -> AccessorInitialState {
415
- let mut memory = HashMap :: default ( ) ;
416
- encode_to_memory ( & mut memory, address, & t) ;
417
-
418
- AccessorInitialState {
419
- stack : [ self . init_stack_for_isolated_run ( ) , vec ! [ address] ] . concat ( ) ,
420
- memory,
421
- }
422
- }
423
- }
424
-
425
- impl < T : TasmObject + BFieldCodec + for < ' a > Arbitrary < ' a > + Debug > Accessor
426
- for VerifyNdSiIntegrity < T >
427
- {
428
- fn rust_shadow (
429
- & self ,
430
- stack : & mut Vec < BFieldElement > ,
431
- memory : & HashMap < BFieldElement , BFieldElement > ,
432
- ) {
433
- // If the type can be decoded then it must have valid size indicators
434
- let pointer = stack. pop ( ) . unwrap ( ) ;
435
- let obj = T :: decode_from_memory ( memory, pointer) . unwrap ( ) ;
436
-
437
- stack. push ( bfe ! ( obj. encode( ) . len( ) as u64 ) ) ;
438
- }
439
-
440
- fn pseudorandom_initial_state (
441
- & self ,
442
- seed : [ u8 ; 32 ] ,
443
- _bench_case : Option < BenchmarkCase > ,
444
- ) -> AccessorInitialState {
445
- fn prepare_random_object < T : for < ' a > Arbitrary < ' a > > ( randomness : & [ u8 ; 100000 ] ) -> T {
446
- let unstructured = Unstructured :: new ( randomness) ;
447
- T :: arbitrary_take_rest ( unstructured) . unwrap ( )
448
- }
449
-
450
- let mut rng: StdRng = SeedableRng :: from_seed ( seed) ;
451
-
452
- let t: T = {
453
- let mut randomness = [ 0u8 ; 100000 ] ;
454
- rng. fill ( & mut randomness) ;
455
- prepare_random_object ( & randomness)
456
- } ;
457
-
458
- let address: u32 = rng. gen_range ( 0 ..( 1 << 30 ) ) ;
459
- let address = bfe ! ( address) ;
460
- self . initial_state ( address, t)
461
- }
462
-
463
- fn corner_case_initial_states ( & self ) -> Vec < AccessorInitialState > {
464
- // This *should* always return `None` if `T: Option<S>`, and empty
465
- // vec if type is Vec<T>. So some notion of "empty" or default.
466
- let empty_struct: T = {
467
- let unstructured = Unstructured :: new ( & [ ] ) ;
468
- T :: arbitrary_take_rest ( unstructured) . unwrap ( )
469
- } ;
470
-
471
- println ! ( "empty_struct:\n {empty_struct:?}" ) ;
472
- let empty_struct_at_zero = self . initial_state ( BFieldElement :: ZERO , empty_struct) ;
473
-
474
- vec ! [ empty_struct_at_zero]
475
- }
476
- }
477
566
}
478
567
479
568
#[ cfg( test) ]
0 commit comments