@@ -201,6 +201,73 @@ fn transaction_storage_runtime_sizes() {
201201 } ) ;
202202}
203203
204+ /// Test maximum write throughput: 8 transactions of 1 MiB each in a single block (8 MiB total).
205+ #[ test]
206+ fn transaction_storage_max_throughput ( ) {
207+ use bulletin_westend_runtime as runtime;
208+ use bulletin_westend_runtime:: BuildStorage ;
209+ use frame_support:: assert_ok;
210+ use pallet_transaction_storage:: { AuthorizationExtent , Call as TxStorageCall } ;
211+ use sp_keyring:: Sr25519Keyring ;
212+
213+ const NUM_TRANSACTIONS : u32 = 8 ;
214+ const TRANSACTION_SIZE : usize = 1 * 1024 * 1024 ; // 1 MiB
215+ const TOTAL_BYTES : u64 = ( NUM_TRANSACTIONS as u64 ) * ( TRANSACTION_SIZE as u64 ) ; // 8 MiB
216+
217+ sp_io:: TestExternalities :: new (
218+ runtime:: RuntimeGenesisConfig :: default ( ) . build_storage ( ) . unwrap ( ) ,
219+ )
220+ . execute_with ( || {
221+ let account = Sr25519Keyring :: Alice ;
222+ let who: AccountId = account. to_account_id ( ) ;
223+
224+ // fund Alice to cover length-based tx fees
225+ let initial: Balance = 10_000_000_000_000_000_000u128 ;
226+ <pallet_balances:: Pallet < Runtime > as FungibleMutate < _ > >:: set_balance ( & who, initial) ;
227+
228+ // authorize 8 transactions of 1 MiB each
229+ assert_ok ! ( runtime:: TransactionStorage :: authorize_account(
230+ RuntimeOrigin :: root( ) ,
231+ who. clone( ) ,
232+ NUM_TRANSACTIONS ,
233+ TOTAL_BYTES ,
234+ ) ) ;
235+ assert_eq ! (
236+ runtime:: TransactionStorage :: account_authorization_extent( who. clone( ) ) ,
237+ AuthorizationExtent { transactions: NUM_TRANSACTIONS , bytes: TOTAL_BYTES } ,
238+ ) ;
239+
240+ // Advance to a fresh block
241+ advance_block ( ) ;
242+
243+ // Store all 8 transactions in the same block (no advance_block between them)
244+ for index in 0 ..NUM_TRANSACTIONS {
245+ tracing:: info!( "Storing 1 MiB transaction {}/{}" , index + 1 , NUM_TRANSACTIONS ) ;
246+ let res = construct_and_apply_extrinsic (
247+ account. pair ( ) ,
248+ RuntimeCall :: TransactionStorage ( TxStorageCall :: < Runtime > :: store {
249+ data : vec ! [ 0u8 ; TRANSACTION_SIZE ] ,
250+ } ) ,
251+ ) ;
252+ assert_ok ! ( res) ;
253+ assert_ok ! ( res. unwrap( ) ) ;
254+ }
255+
256+ // Verify all authorizations were consumed
257+ assert_eq ! (
258+ runtime:: TransactionStorage :: account_authorization_extent( who. clone( ) ) ,
259+ AuthorizationExtent { transactions: 0 , bytes: 0 } ,
260+ ) ;
261+
262+ tracing:: info!(
263+ "Successfully stored {} transactions of {} bytes each ({} MiB total) in a single block" ,
264+ NUM_TRANSACTIONS ,
265+ TRANSACTION_SIZE ,
266+ TOTAL_BYTES / ( 1024 * 1024 )
267+ ) ;
268+ } ) ;
269+ }
270+
204271#[ test]
205272fn location_conversion_works ( ) {
206273 // the purpose of hardcoded values is to catch an unintended location conversion logic change.
0 commit comments