@@ -40,7 +40,16 @@ use frame_support::{
4040} ;
4141use frame_system:: RawOrigin ;
4242use pallet_revive_uapi:: { pack_hi_lo, CallFlags , ReturnErrorCode , StorageFlags } ;
43- use sp_runtime:: traits:: { Bounded , Hash } ;
43+ use sp_consensus_aura:: AURA_ENGINE_ID ;
44+ use sp_consensus_babe:: {
45+ digests:: { PreDigest , PrimaryPreDigest } ,
46+ BABE_ENGINE_ID ,
47+ } ;
48+ use sp_consensus_slots:: Slot ;
49+ use sp_runtime:: {
50+ generic:: { Digest , DigestItem } ,
51+ traits:: { Bounded , Hash } ,
52+ } ;
4453
4554/// How many runs we do per API benchmark.
4655///
@@ -886,6 +895,59 @@ mod benchmarks {
886895 assert_eq ! ( U256 :: from_little_endian( & memory[ ..] ) , runtime. ext( ) . block_number( ) ) ;
887896 }
888897
898+ #[ benchmark( pov_mode = Measured ) ]
899+ fn seal_block_author ( ) {
900+ build_runtime ! ( runtime, memory: [ [ 123u8 ; 20 ] , ] ) ;
901+
902+ let mut digest = Digest :: default ( ) ;
903+
904+ // The pre-runtime digest log is unbounded; usually around 3 items but it can vary.
905+ // To get safe benchmark results despite that, populate it with a bunch of random logs to
906+ // ensure iteration over many items (we just overestimate the cost of the API).
907+ for i in 0 ..16 {
908+ digest. push ( DigestItem :: PreRuntime ( [ i, i, i, i] , vec ! [ i; 128 ] ) ) ;
909+ digest. push ( DigestItem :: Consensus ( [ i, i, i, i] , vec ! [ i; 128 ] ) ) ;
910+ digest. push ( DigestItem :: Seal ( [ i, i, i, i] , vec ! [ i; 128 ] ) ) ;
911+ digest. push ( DigestItem :: Other ( vec ! [ i; 128 ] ) ) ;
912+ }
913+
914+ // The content of the pre-runtime digest log depends on the configured consensus.
915+ // However, mismatching logs are simply ignored. Thus we construct fixtures which will
916+ // let the API to return a value in both BABE and AURA consensus.
917+
918+ // Construct a `Digest` log fixture returning some value in BABE
919+ let primary_pre_digest = vec ! [ 0 ; <PrimaryPreDigest as MaxEncodedLen >:: max_encoded_len( ) ] ;
920+ let pre_digest =
921+ PreDigest :: Primary ( PrimaryPreDigest :: decode ( & mut & primary_pre_digest[ ..] ) . unwrap ( ) ) ;
922+ digest. push ( DigestItem :: PreRuntime ( BABE_ENGINE_ID , pre_digest. encode ( ) ) ) ;
923+ digest. push ( DigestItem :: Seal ( BABE_ENGINE_ID , pre_digest. encode ( ) ) ) ;
924+
925+ // Construct a `Digest` log fixture returning some value in AURA
926+ let slot = Slot :: default ( ) ;
927+ digest. push ( DigestItem :: PreRuntime ( AURA_ENGINE_ID , slot. encode ( ) ) ) ;
928+ digest. push ( DigestItem :: Seal ( AURA_ENGINE_ID , slot. encode ( ) ) ) ;
929+
930+ frame_system:: Pallet :: < T > :: initialize (
931+ & BlockNumberFor :: < T > :: from ( 1u32 ) ,
932+ & Default :: default ( ) ,
933+ & digest,
934+ ) ;
935+
936+ let result;
937+ #[ block]
938+ {
939+ result = runtime. bench_block_author ( memory. as_mut_slice ( ) , 0 ) ;
940+ }
941+ assert_ok ! ( result) ;
942+
943+ let block_author = runtime
944+ . ext ( )
945+ . block_author ( )
946+ . map ( |account| T :: AddressMapper :: to_address ( & account) )
947+ . unwrap_or ( H160 :: zero ( ) ) ;
948+ assert_eq ! ( & memory[ ..] , block_author. as_bytes( ) ) ;
949+ }
950+
889951 #[ benchmark( pov_mode = Measured ) ]
890952 fn seal_block_hash ( ) {
891953 let mut memory = vec ! [ 0u8 ; 64 ] ;
0 commit comments