@@ -256,7 +256,11 @@ void run_context_tests(void) {
256256}
257257
258258void run_scratch_tests (void ) {
259+ const size_t adj_alloc = ((500 + ALIGNMENT - 1 ) / ALIGNMENT ) * ALIGNMENT ;
260+
259261 int32_t ecount = 0 ;
262+ size_t checkpoint ;
263+ size_t checkpoint_2 ;
260264 secp256k1_context * none = secp256k1_context_create (SECP256K1_CONTEXT_NONE );
261265 secp256k1_scratch_space * scratch ;
262266 secp256k1_scratch_space local_scratch ;
@@ -271,43 +275,54 @@ void run_scratch_tests(void) {
271275
272276 /* Test internal API */
273277 CHECK (secp256k1_scratch_max_allocation (& none -> error_callback , scratch , 0 ) == 1000 );
274- CHECK (secp256k1_scratch_max_allocation (& none -> error_callback , scratch , 1 ) < 1000 );
275-
276- /* Allocating 500 bytes with no frame fails */
277- CHECK (secp256k1_scratch_alloc (& none -> error_callback , scratch , 500 ) == NULL );
278- CHECK (secp256k1_scratch_max_allocation (& none -> error_callback , scratch , 0 ) == 1000 );
278+ CHECK (secp256k1_scratch_max_allocation (& none -> error_callback , scratch , 1 ) == 1000 - (ALIGNMENT - 1 ));
279+ CHECK (scratch -> alloc_size == 0 );
280+ CHECK (scratch -> alloc_size % ALIGNMENT == 0 );
279281
280- /* ...but pushing a new stack frame does affect the max allocation */
281- CHECK (secp256k1_scratch_allocate_frame (& none -> error_callback , scratch , 500 , 1 ) == 1 );
282- CHECK (secp256k1_scratch_max_allocation (& none -> error_callback , scratch , 1 ) < 500 ); /* 500 - (ALIGNMENT - 1) */
282+ /* Allocating 500 bytes succeeds */
283+ checkpoint = secp256k1_scratch_checkpoint (& none -> error_callback , scratch );
283284 CHECK (secp256k1_scratch_alloc (& none -> error_callback , scratch , 500 ) != NULL );
284- CHECK (secp256k1_scratch_alloc (& none -> error_callback , scratch , 500 ) == NULL );
285-
286- CHECK (secp256k1_scratch_allocate_frame (& none -> error_callback , scratch , 500 , 1 ) == 0 );
285+ CHECK (secp256k1_scratch_max_allocation (& none -> error_callback , scratch , 0 ) == 1000 - adj_alloc );
286+ CHECK (secp256k1_scratch_max_allocation (& none -> error_callback , scratch , 1 ) == 1000 - adj_alloc - (ALIGNMENT - 1 ));
287+ CHECK (scratch -> alloc_size != 0 );
288+ CHECK (scratch -> alloc_size % ALIGNMENT == 0 );
287289
288- /* ...and this effect is undone by popping the frame */
289- secp256k1_scratch_deallocate_frame (& none -> error_callback , scratch );
290- CHECK (secp256k1_scratch_max_allocation (& none -> error_callback , scratch , 0 ) == 1000 );
290+ /* Allocating another 500 bytes fails */
291291 CHECK (secp256k1_scratch_alloc (& none -> error_callback , scratch , 500 ) == NULL );
292+ CHECK (secp256k1_scratch_max_allocation (& none -> error_callback , scratch , 0 ) == 1000 - adj_alloc );
293+ CHECK (secp256k1_scratch_max_allocation (& none -> error_callback , scratch , 1 ) == 1000 - adj_alloc - (ALIGNMENT - 1 ));
294+ CHECK (scratch -> alloc_size != 0 );
295+ CHECK (scratch -> alloc_size % ALIGNMENT == 0 );
296+
297+ /* ...but it succeeds once we apply the checkpoint to undo it */
298+ secp256k1_scratch_apply_checkpoint (& none -> error_callback , scratch , checkpoint );
299+ CHECK (scratch -> alloc_size == 0 );
300+ CHECK (secp256k1_scratch_max_allocation (& none -> error_callback , scratch , 0 ) == 1000 );
301+ CHECK (secp256k1_scratch_alloc (& none -> error_callback , scratch , 500 ) != NULL );
302+ CHECK (scratch -> alloc_size != 0 );
292303
293- /* cleanup */
294- secp256k1_scratch_space_destroy (none , scratch );
304+ /* try to apply a bad checkpoint */
305+ checkpoint_2 = secp256k1_scratch_checkpoint (& none -> error_callback , scratch );
306+ secp256k1_scratch_apply_checkpoint (& none -> error_callback , scratch , checkpoint );
295307 CHECK (ecount == 0 );
308+ secp256k1_scratch_apply_checkpoint (& none -> error_callback , scratch , checkpoint_2 ); /* checkpoint_2 is after checkpoint */
309+ CHECK (ecount == 1 );
310+ secp256k1_scratch_apply_checkpoint (& none -> error_callback , scratch , (size_t ) -1 ); /* this is just wildly invalid */
311+ CHECK (ecount == 2 );
296312
297313 /* try to use badly initialized scratch space */
298314 memset (& local_scratch , 0 , sizeof (local_scratch ));
299315 scratch = & local_scratch ;
300316 CHECK (!secp256k1_scratch_max_allocation (& none -> error_callback , scratch , 0 ));
301- CHECK (ecount == 1 );
302- CHECK (secp256k1_scratch_allocate_frame (& none -> error_callback , scratch , 500 , 1 ) == 0 );
303- CHECK (ecount == 2 );
304- CHECK (secp256k1_scratch_alloc (& none -> error_callback , scratch , 500 ) == NULL );
305317 CHECK (ecount == 3 );
306- secp256k1_scratch_deallocate_frame ( & none -> error_callback , scratch );
318+ CHECK ( secp256k1_scratch_alloc ( & none -> error_callback , scratch , 500 ) == NULL );
307319 CHECK (ecount == 4 );
308320 secp256k1_scratch_space_destroy (none , scratch );
309321 CHECK (ecount == 5 );
310322
323+ /* cleanup */
324+ secp256k1_scratch_space_destroy (none , scratch );
325+ secp256k1_scratch_space_destroy (none , NULL ); /* no-op */
311326 secp256k1_context_destroy (none );
312327}
313328
@@ -2857,16 +2872,26 @@ void test_ecmult_multi_pippenger_max_points(void) {
28572872 int bucket_window = 0 ;
28582873
28592874 for (; scratch_size < max_size ; scratch_size += 256 ) {
2875+ size_t i ;
2876+ size_t total_alloc ;
2877+ size_t checkpoint ;
28602878 scratch = secp256k1_scratch_create (& ctx -> error_callback , scratch_size );
28612879 CHECK (scratch != NULL );
2880+ checkpoint = secp256k1_scratch_checkpoint (& ctx -> error_callback , scratch );
28622881 n_points_supported = secp256k1_pippenger_max_points (& ctx -> error_callback , scratch );
28632882 if (n_points_supported == 0 ) {
28642883 secp256k1_scratch_destroy (& ctx -> error_callback , scratch );
28652884 continue ;
28662885 }
28672886 bucket_window = secp256k1_pippenger_bucket_window (n_points_supported );
2868- CHECK (secp256k1_scratch_allocate_frame (& ctx -> error_callback , scratch , secp256k1_pippenger_scratch_size (n_points_supported , bucket_window ), PIPPENGER_SCRATCH_OBJECTS ));
2869- secp256k1_scratch_deallocate_frame (& ctx -> error_callback , scratch );
2887+ /* allocate `total_alloc` bytes over `PIPPENGER_SCRATCH_OBJECTS` many allocations */
2888+ total_alloc = secp256k1_pippenger_scratch_size (n_points_supported , bucket_window );
2889+ for (i = 0 ; i < PIPPENGER_SCRATCH_OBJECTS - 1 ; i ++ ) {
2890+ CHECK (secp256k1_scratch_alloc (& ctx -> error_callback , scratch , 1 ));
2891+ total_alloc -- ;
2892+ }
2893+ CHECK (secp256k1_scratch_alloc (& ctx -> error_callback , scratch , total_alloc ));
2894+ secp256k1_scratch_apply_checkpoint (& ctx -> error_callback , scratch , checkpoint );
28702895 secp256k1_scratch_destroy (& ctx -> error_callback , scratch );
28712896 }
28722897 CHECK (bucket_window == PIPPENGER_MAX_BUCKET_WINDOW );
0 commit comments