@@ -174,6 +174,9 @@ where
174174
175175 let storage_size_diff = benchmarked_weight. abs_diff ( consumed_weight as u64 ) ;
176176
177+ let extrinsic_len = frame_system:: AllExtrinsicsLen :: < T > :: get ( ) . unwrap_or ( 0 ) ;
178+ let node_side_pov_size = post_dispatch_proof_size. saturating_add ( extrinsic_len. into ( ) ) ;
179+
177180 // This value will be reclaimed by [`frame_system::CheckWeight`], so we need to calculate
178181 // that in.
179182 frame_system:: BlockWeight :: < T > :: mutate ( |current| {
@@ -190,6 +193,19 @@ where
190193 ) ;
191194 current. reduce ( Weight :: from_parts ( 0 , storage_size_diff) , info. class )
192195 }
196+
197+ // If we encounter a situation where the node-side proof size is already higher than
198+ // what we have in the runtime bookkeeping, we add the difference to the `BlockWeight`.
199+ // This prevents that the proof size grows faster than the runtime proof size.
200+ let block_weight_proof_size = current. total ( ) . proof_size ( ) ;
201+ let missing_from_node = node_side_pov_size. saturating_sub ( block_weight_proof_size) ;
202+ if missing_from_node > 0 {
203+ log:: warn!(
204+ target: LOG_TARGET ,
205+ "Node-side PoV size higher than runtime proof size weight. node-side: {node_side_pov_size} extrinsic_len: {extrinsic_len} runtime: {block_weight_proof_size}, missing: {missing_from_node}. Setting to node-side proof size."
206+ ) ;
207+ current. accrue ( Weight :: from_parts ( 0 , missing_from_node) , info. class ) ;
208+ }
193209 } ) ;
194210 Ok ( ( ) )
195211 }
@@ -332,6 +348,82 @@ mod tests {
332348 } )
333349 }
334350
351+ #[ test]
352+ fn sets_to_node_storage_proof_if_higher ( ) {
353+ // The storage proof reported by the proof recorder is higher than what is stored on
354+ // the runtime side.
355+ {
356+ let mut test_ext = setup_test_externalities ( & [ 1000 , 1005 ] ) ;
357+
358+ test_ext. execute_with ( || {
359+ // Stored in BlockWeight is 5
360+ set_current_storage_weight ( 5 ) ;
361+
362+ // Benchmarked storage weight: 10
363+ let info = DispatchInfo { weight : Weight :: from_parts ( 0 , 10 ) , ..Default :: default ( ) } ;
364+ let post_info = PostDispatchInfo :: default ( ) ;
365+
366+ assert_ok ! ( CheckWeight :: <Test >:: do_pre_dispatch( & info, LEN ) ) ;
367+
368+ let pre = StorageWeightReclaim :: < Test > ( PhantomData )
369+ . pre_dispatch ( & ALICE , CALL , & info, LEN )
370+ . unwrap ( ) ;
371+ assert_eq ! ( pre, Some ( 1000 ) ) ;
372+
373+ assert_ok ! ( CheckWeight :: <Test >:: post_dispatch( None , & info, & post_info, 0 , & Ok ( ( ) ) ) ) ;
374+ assert_ok ! ( StorageWeightReclaim :: <Test >:: post_dispatch(
375+ Some ( pre) ,
376+ & info,
377+ & post_info,
378+ LEN ,
379+ & Ok ( ( ) )
380+ ) ) ;
381+
382+ // We expect that the storage weight was set to the node-side proof size (1005) +
383+ // extrinsics length (150)
384+ assert_eq ! ( get_storage_weight( ) . total( ) . proof_size( ) , 1155 ) ;
385+ } )
386+ }
387+
388+ // In this second scenario the proof size on the node side is only lower
389+ // after reclaim happened.
390+ {
391+ let mut test_ext = setup_test_externalities ( & [ 175 , 180 ] ) ;
392+ test_ext. execute_with ( || {
393+ set_current_storage_weight ( 85 ) ;
394+
395+ // Benchmarked storage weight: 100
396+ let info =
397+ DispatchInfo { weight : Weight :: from_parts ( 0 , 100 ) , ..Default :: default ( ) } ;
398+ let post_info = PostDispatchInfo :: default ( ) ;
399+
400+ // After this pre_dispatch, the BlockWeight proof size will be
401+ // 85 (initial) + 100 (benched) + 150 (tx length) = 335
402+ assert_ok ! ( CheckWeight :: <Test >:: do_pre_dispatch( & info, LEN ) ) ;
403+
404+ let pre = StorageWeightReclaim :: < Test > ( PhantomData )
405+ . pre_dispatch ( & ALICE , CALL , & info, LEN )
406+ . unwrap ( ) ;
407+ assert_eq ! ( pre, Some ( 175 ) ) ;
408+
409+ assert_ok ! ( CheckWeight :: <Test >:: post_dispatch( None , & info, & post_info, 0 , & Ok ( ( ) ) ) ) ;
410+
411+ // First we will reclaim 95, which leaves us with 240 BlockWeight. This is lower
412+ // than 180 (proof size hf) + 150 (length), so we expect it to be set to 330.
413+ assert_ok ! ( StorageWeightReclaim :: <Test >:: post_dispatch(
414+ Some ( pre) ,
415+ & info,
416+ & post_info,
417+ LEN ,
418+ & Ok ( ( ) )
419+ ) ) ;
420+
421+ // We expect that the storage weight was set to the node-side proof weight
422+ assert_eq ! ( get_storage_weight( ) . total( ) . proof_size( ) , 330 ) ;
423+ } )
424+ }
425+ }
426+
335427 #[ test]
336428 fn does_nothing_without_extension ( ) {
337429 let mut test_ext = new_test_ext ( ) ;
@@ -545,7 +637,7 @@ mod tests {
545637
546638 #[ test]
547639 fn test_nothing_relcaimed ( ) {
548- let mut test_ext = setup_test_externalities ( & [ 100 , 200 ] ) ;
640+ let mut test_ext = setup_test_externalities ( & [ 0 , 100 ] ) ;
549641
550642 test_ext. execute_with ( || {
551643 set_current_storage_weight ( 0 ) ;
@@ -568,7 +660,7 @@ mod tests {
568660 . pre_dispatch ( & ALICE , CALL , & info, LEN )
569661 . unwrap ( ) ;
570662 // Should return `setup_test_externalities` proof recorder value: 100.
571- assert_eq ! ( pre, Some ( 100 ) ) ;
663+ assert_eq ! ( pre, Some ( 0 ) ) ;
572664
573665 // The `CheckWeight` extension will refund `actual_weight` from `PostDispatchInfo`
574666 // we always need to call `post_dispatch` to verify that they interoperate correctly.
0 commit comments