55""" # noqa: E501
66
77from itertools import permutations
8- from typing import Any , Generator , List
8+ from typing import Any , Dict , Generator , List , Tuple
99
1010import pytest
1111
1818 BlockchainTestFiller ,
1919 BlockException ,
2020 Bytecode ,
21+ Bytes ,
2122 Environment ,
2223 Header ,
2324 Requests ,
@@ -214,6 +215,10 @@ def get_contract_permutations(n: int = 3) -> Generator[Any, None, None]:
214215 ],
215216 id = "withdrawal_from_eoa+consolidation_from_eoa+withdrawal_from_contract" ,
216217 ),
218+ pytest .param (
219+ [],
220+ id = "empty_requests" ,
221+ ),
217222 ],
218223)
219224def test_valid_deposit_withdrawal_consolidation_requests (
@@ -320,148 +325,154 @@ def test_valid_deposit_withdrawal_consolidation_request_from_same_tx(
320325 )
321326
322327
323- invalid_requests_block_combinations = [
324- pytest .param (
325- [],
326- [], # Even with no requests, the requests hash is not sha256(b""),
327- # but sha256(sha256(b"\0") ++ sha256(b"\1") ++ sha256(b"\2") ++ ...)
328- BlockException .INVALID_REQUESTS ,
329- id = "no_requests_empty_list" ,
330- ),
331- pytest .param (
332- [
333- single_deposit_from_eoa (0 ),
334- ],
335- [
336- single_deposit (0 ),
337- ],
338- BlockException .INVALID_REQUESTS ,
339- id = "single_deposit_incomplete_requests_list" ,
340- ),
341- pytest .param (
342- [
343- single_deposit_from_eoa (0 ),
344- ],
345- [],
346- BlockException .INVALID_REQUESTS ,
347- id = "single_deposit_empty_requests_list" ,
348- ),
349- # Incorrect order tests
350- pytest .param (
351- [
352- single_deposit_from_eoa (0 ),
353- ],
354- [
355- b"" ,
356- single_deposit (0 ),
357- b"" ,
328+ def invalid_requests_block_combinations (fork : Fork ) -> List [Any ]:
329+ """
330+ Return a list of invalid request combinations for the given fork.
331+
332+ In the event of a new request type, the `all_request_types` dictionary should be updated
333+ with the new request type and its corresponding request-generating transaction.
334+ """
335+ assert fork .max_request_type () == 2 , "Test update is needed for new request types"
336+
337+ all_request_types : Dict [
338+ str ,
339+ Tuple [
340+ DepositTransaction | WithdrawalRequestTransaction | ConsolidationRequestTransaction ,
341+ DepositRequest | WithdrawalRequest | ConsolidationRequest ,
358342 ],
359- BlockException .INVALID_REQUESTS ,
360- id = "single_deposit_incorrect_order_1" ,
361- ),
362- pytest .param (
363- [
343+ ] = {
344+ "deposit" : (
364345 single_deposit_from_eoa (0 ),
365- ],
366- [
367- b"" ,
368- b"" ,
369346 single_deposit (0 ),
370- ],
371- BlockException .INVALID_REQUESTS ,
372- id = "single_deposit_incorrect_order_2" ,
373- ),
374- pytest .param (
375- [
376- single_withdrawal_from_eoa (0 ),
377- ],
378- [
379- single_withdrawal (0 ).with_source_address (TestAddress ),
380- b"" ,
381- b"" ,
382- ],
383- BlockException .INVALID_REQUESTS ,
384- id = "single_withdrawal_incorrect_order_1" ,
385- ),
386- pytest .param (
387- [
347+ ),
348+ "withdrawal" : (
388349 single_withdrawal_from_eoa (0 ),
389- ],
390- [
391- b"" ,
392- b"" ,
393350 single_withdrawal (0 ).with_source_address (TestAddress ),
394- ],
395- BlockException .INVALID_REQUESTS ,
396- id = "single_withdrawal_incorrect_order_2" ,
397- ),
398- pytest .param (
399- [
351+ ),
352+ "consolidation" : (
400353 single_consolidation_from_eoa (0 ),
401- ],
402- [
403354 single_consolidation (0 ).with_source_address (TestAddress ),
404- b"" ,
405- b"" ,
406- ],
407- BlockException .INVALID_REQUESTS ,
408- id = "single_consolidation_incorrect_order_1" ,
409- ),
410- pytest .param (
411- [
412- single_consolidation_from_eoa (0 ),
413- ],
414- [
415- b"" ,
416- single_consolidation (0 ).with_source_address (TestAddress ),
417- b"" ,
418- ],
419- BlockException .INVALID_REQUESTS ,
420- id = "single_consolidation_incorrect_order_2" ,
421- ),
422- pytest .param (
423- [
424- single_deposit_from_eoa (0 ),
425- single_withdrawal_from_eoa (0 ),
426- ],
427- [
428- single_deposit (0 ),
429- single_withdrawal (0 ).with_source_address (TestAddress ),
430- ],
431- BlockException .INVALID_REQUESTS ,
432- id = "single_deposit_single_withdrawal_incomplete_requests_list" ,
433- ),
434- pytest .param (
435- [
436- single_deposit_from_eoa (0 ),
437- single_withdrawal_from_eoa (0 ),
438- ],
439- [
440- single_deposit (0 ),
441- ],
442- BlockException .INVALID_REQUESTS ,
443- id = "single_deposit_single_withdrawal_incomplete_requests_list_2" ,
444- ),
445- pytest .param (
446- [
447- single_deposit_from_eoa (0 ),
448- single_withdrawal_from_eoa (0 ),
449- single_consolidation_from_eoa (0 ),
450- ],
451- [
452- single_deposit (0 ),
453- single_withdrawal (0 ).with_source_address (TestAddress ),
454- ],
455- BlockException .INVALID_REQUESTS ,
456- id = "single_deposit_single_withdrawal_single_consolidation_incomplete_requests_list" ,
457- ),
458- ]
355+ ),
356+ }
357+
358+ # - Empty requests list with invalid hash
359+ combinations = [
360+ pytest .param (
361+ [],
362+ [
363+ bytes ([i ]) for i in range (fork .max_request_type () + 1 )
364+ ], # Using empty requests, calculate the hash using an invalid calculation method:
365+ # sha256(sha256(b"\0") ++ sha256(b"\1") ++ sha256(b"\2") ++ ...)
366+ BlockException .INVALID_REQUESTS ,
367+ id = "no_requests_invalid_hash_calculation_method" ,
368+ ),
369+ pytest .param (
370+ [],
371+ [
372+ bytes ([]) for _ in range (fork .max_request_type () + 1 )
373+ ], # Using empty requests, calculate the hash using an invalid calculation method:
374+ # sha256(sha256(b"") ++ sha256(b"") ++ sha256(b"") ++ ...)
375+ BlockException .INVALID_REQUESTS ,
376+ id = "no_requests_invalid_hash_calculation_method_2" ,
377+ ),
378+ ]
459379
380+ # - Missing request or request type byte tests
381+ for request_type , (eoa_request , block_request ) in all_request_types .items ():
382+ combinations .extend (
383+ [
384+ pytest .param (
385+ [eoa_request ],
386+ [
387+ block_request
388+ ], # The request type byte missing because we need to use the `Requests` class
389+ BlockException .INVALID_REQUESTS ,
390+ id = f"single_{ request_type } _missing_type_byte" ,
391+ ),
392+ pytest .param (
393+ [eoa_request ],
394+ [],
395+ BlockException .INVALID_REQUESTS ,
396+ id = f"single_{ request_type } _empty_requests_list" ,
397+ ),
398+ ]
399+ )
460400
461- @pytest .mark .parametrize (
401+ # - Incorrect order tests
402+ correct_order : List [Bytes ] = Requests (
403+ * [r [1 ] for r in all_request_types .values ()]
404+ ).requests_list # Requests automatically adds the type byte
405+ correct_order_transactions : List [
406+ DepositTransaction | WithdrawalRequestTransaction | ConsolidationRequestTransaction
407+ ] = [r [0 ] for r in all_request_types .values ()]
408+
409+ # Send first element to the end
410+ combinations .append (
411+ pytest .param (
412+ correct_order_transactions [1 :] + [correct_order_transactions [0 ]],
413+ correct_order [1 :] + [correct_order [0 ]],
414+ BlockException .INVALID_REQUESTS ,
415+ id = "incorrect_order_first_request_at_end" ,
416+ ),
417+ )
418+
419+ # Send second element to the end
420+ combinations .append (
421+ pytest .param (
422+ [correct_order_transactions [0 ]]
423+ + correct_order_transactions [2 :]
424+ + [correct_order_transactions [1 ]],
425+ [correct_order [0 ]] + correct_order [2 :] + [correct_order [1 ]],
426+ BlockException .INVALID_REQUESTS ,
427+ id = "incorrect_order_second_request_at_end" ,
428+ ),
429+ )
430+
431+ # Bring last element to the beginning
432+ combinations .append (
433+ pytest .param (
434+ [correct_order_transactions [- 1 ]] + correct_order_transactions [:- 1 ],
435+ [correct_order [- 1 ]] + correct_order [:- 1 ],
436+ BlockException .INVALID_REQUESTS ,
437+ id = "incorrect_order_last_request_at_beginning" ,
438+ ),
439+ )
440+
441+ # - Duplicate request tests
442+ for request_type , (eoa_request , block_request ) in all_request_types .items ():
443+ combinations .append (
444+ pytest .param (
445+ [eoa_request ],
446+ Requests (block_request ).requests_list * 2 ,
447+ BlockException .INVALID_REQUESTS ,
448+ id = f"duplicate_{ request_type } _request" ,
449+ ),
450+ )
451+
452+ # - Extra invalid request tests
453+ combinations .append (
454+ pytest .param (
455+ correct_order_transactions ,
456+ correct_order + [b"" ],
457+ BlockException .INVALID_REQUESTS ,
458+ id = "extra_empty_request" ,
459+ ),
460+ )
461+ combinations .append (
462+ pytest .param (
463+ correct_order_transactions ,
464+ correct_order + [bytes ([fork .max_request_type () + 1 ])],
465+ BlockException .INVALID_REQUESTS ,
466+ id = "extra_invalid_type_request" ,
467+ ),
468+ )
469+
470+ return combinations
471+
472+
473+ @pytest .mark .parametrize_by_fork (
462474 "requests,block_body_override_requests,exception" ,
463475 invalid_requests_block_combinations ,
464- indirect = ["block_body_override_requests" ],
465476)
466477def test_invalid_deposit_withdrawal_consolidation_requests (
467478 blockchain_test : BlockchainTestFiller ,
@@ -484,10 +495,9 @@ def test_invalid_deposit_withdrawal_consolidation_requests(
484495 )
485496
486497
487- @pytest .mark .parametrize (
498+ @pytest .mark .parametrize_by_fork (
488499 "requests,block_body_override_requests,exception" ,
489500 invalid_requests_block_combinations ,
490- indirect = ["block_body_override_requests" ],
491501)
492502@pytest .mark .parametrize ("correct_requests_hash_in_header" , [True ])
493503def test_invalid_deposit_withdrawal_consolidation_requests_engine (
0 commit comments