5
5
""" # noqa: E501
6
6
7
7
from itertools import permutations
8
- from typing import Any , Generator , List
8
+ from typing import Any , Dict , Generator , List , Tuple
9
9
10
10
import pytest
11
11
18
18
BlockchainTestFiller ,
19
19
BlockException ,
20
20
Bytecode ,
21
+ Bytes ,
21
22
Environment ,
22
23
Header ,
23
24
Requests ,
26
27
Transaction ,
27
28
)
28
29
from ethereum_test_tools import Opcodes as Op
30
+ from pytest_plugins import fork_covariant_parametrize
29
31
30
32
from ..eip6110_deposits .helpers import DepositContract , DepositRequest , DepositTransaction
31
33
from ..eip6110_deposits .spec import Spec as Spec_EIP6110
@@ -214,6 +216,10 @@ def get_contract_permutations(n: int = 3) -> Generator[Any, None, None]:
214
216
],
215
217
id = "withdrawal_from_eoa+consolidation_from_eoa+withdrawal_from_contract" ,
216
218
),
219
+ pytest .param (
220
+ [],
221
+ id = "empty_requests" ,
222
+ ),
217
223
],
218
224
)
219
225
def test_valid_deposit_withdrawal_consolidation_requests (
@@ -320,148 +326,136 @@ def test_valid_deposit_withdrawal_consolidation_request_from_same_tx(
320
326
)
321
327
322
328
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"" ,
329
+ def invalid_requests_block_combinations (fork : Fork ) -> List [Any ]:
330
+ """
331
+ Return a list of invalid request combinations for the given fork.
332
+
333
+ In the event of a new request type, the `all_request_types` dictionary should be updated
334
+ with the new request type and its corresponding request-generating transaction.
335
+ """
336
+ assert fork .max_request_type () == 2 , "Test update is needed for new request types"
337
+
338
+ all_request_types : Dict [
339
+ str ,
340
+ Tuple [
341
+ DepositTransaction | WithdrawalRequestTransaction | ConsolidationRequestTransaction ,
342
+ DepositRequest | WithdrawalRequest | ConsolidationRequest ,
358
343
],
359
- BlockException .INVALID_REQUESTS ,
360
- id = "single_deposit_incorrect_order_1" ,
361
- ),
362
- pytest .param (
363
- [
344
+ ] = {
345
+ "deposit" : (
364
346
single_deposit_from_eoa (0 ),
365
- ],
366
- [
367
- b"" ,
368
- b"" ,
369
347
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
- [
348
+ ),
349
+ "withdrawal" : (
388
350
single_withdrawal_from_eoa (0 ),
389
- ],
390
- [
391
- b"" ,
392
- b"" ,
393
351
single_withdrawal (0 ).with_source_address (TestAddress ),
394
- ],
395
- BlockException .INVALID_REQUESTS ,
396
- id = "single_withdrawal_incorrect_order_2" ,
397
- ),
398
- pytest .param (
399
- [
400
- single_consolidation_from_eoa (0 ),
401
- ],
402
- [
403
- 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
- [
352
+ ),
353
+ "consolidation" : (
412
354
single_consolidation_from_eoa (0 ),
413
- ],
414
- [
415
- b"" ,
416
355
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
- ]
356
+ ),
357
+ }
459
358
359
+ # - Empty requests list with invalid hash
360
+ combinations = [
361
+ pytest .param (
362
+ [],
363
+ [
364
+ bytes ([i ]) for i in range (fork .max_request_type () + 1 )
365
+ ], # Using empty requests, calculate the hash using an invalid calculation method:
366
+ # sha256(sha256(b"\0") ++ sha256(b"\1") ++ sha256(b"\2") ++ ...)
367
+ BlockException .INVALID_REQUESTS ,
368
+ id = "no_requests_invalid_hash_calculation_method" ,
369
+ ),
370
+ pytest .param (
371
+ [],
372
+ [
373
+ bytes ([]) for _ in range (fork .max_request_type () + 1 )
374
+ ], # Using empty requests, calculate the hash using an invalid calculation method:
375
+ # sha256(sha256(b"") ++ sha256(b"") ++ sha256(b"") ++ ...)
376
+ BlockException .INVALID_REQUESTS ,
377
+ id = "no_requests_invalid_hash_calculation_method_2" ,
378
+ ),
379
+ ]
460
380
461
- @pytest .mark .parametrize (
462
- "requests,block_body_override_requests,exception" ,
463
- invalid_requests_block_combinations ,
464
- indirect = ["block_body_override_requests" ],
381
+ # - Missing request or request type byte tests
382
+ for request_type , (eoa_request , block_request ) in all_request_types .items ():
383
+ combinations .extend (
384
+ [
385
+ pytest .param (
386
+ [eoa_request ],
387
+ [
388
+ block_request
389
+ ], # The request type byte missing because we need to use the `Requests` class
390
+ BlockException .INVALID_REQUESTS ,
391
+ id = f"single_{ request_type } _missing_type_byte" ,
392
+ ),
393
+ pytest .param (
394
+ [eoa_request ],
395
+ [],
396
+ BlockException .INVALID_REQUESTS ,
397
+ id = f"single_{ request_type } _empty_requests_list" ,
398
+ ),
399
+ ]
400
+ )
401
+
402
+ # - Incorrect order tests
403
+ correct_order : List [Bytes ] = Requests (
404
+ * [r [1 ] for r in all_request_types .values ()]
405
+ ).requests_list # Requests automatically adds the type byte
406
+ correct_order_transactions : List [
407
+ DepositTransaction | WithdrawalRequestTransaction | ConsolidationRequestTransaction
408
+ ] = [r [0 ] for r in all_request_types .values ()]
409
+
410
+ # Send first element to the end
411
+ combinations .append (
412
+ pytest .param (
413
+ correct_order_transactions [1 :] + [correct_order_transactions [0 ]],
414
+ correct_order [1 :] + [correct_order [0 ]],
415
+ BlockException .INVALID_REQUESTS ,
416
+ id = "incorrect_order_first_request_at_end" ,
417
+ ),
418
+ )
419
+
420
+ # Send second element to the end
421
+ combinations .append (
422
+ pytest .param (
423
+ [correct_order_transactions [0 ]]
424
+ + correct_order_transactions [2 :]
425
+ + [correct_order_transactions [1 ]],
426
+ [correct_order [0 ]] + correct_order [2 :] + [correct_order [1 ]],
427
+ BlockException .INVALID_REQUESTS ,
428
+ id = "incorrect_order_second_request_at_end" ,
429
+ ),
430
+ )
431
+
432
+ # Bring last element to the beginning
433
+ combinations .append (
434
+ pytest .param (
435
+ [correct_order_transactions [- 1 ]] + correct_order_transactions [:- 1 ],
436
+ [correct_order [- 1 ]] + correct_order [:- 1 ],
437
+ BlockException .INVALID_REQUESTS ,
438
+ id = "incorrect_order_last_request_at_beginning" ,
439
+ ),
440
+ )
441
+
442
+ # - Duplicate request tests
443
+ for request_type , (eoa_request , block_request ) in all_request_types .items ():
444
+ combinations .append (
445
+ pytest .param (
446
+ [eoa_request ],
447
+ Requests (block_request ).requests_list * 2 ,
448
+ BlockException .INVALID_REQUESTS ,
449
+ id = f"duplicate_{ request_type } _request" ,
450
+ ),
451
+ )
452
+
453
+ return combinations
454
+
455
+
456
+ @fork_covariant_parametrize (
457
+ parameter_names = "requests,block_body_override_requests,exception" ,
458
+ fn = invalid_requests_block_combinations ,
465
459
)
466
460
def test_invalid_deposit_withdrawal_consolidation_requests (
467
461
blockchain_test : BlockchainTestFiller ,
@@ -484,10 +478,9 @@ def test_invalid_deposit_withdrawal_consolidation_requests(
484
478
)
485
479
486
480
487
- @pytest .mark .parametrize (
488
- "requests,block_body_override_requests,exception" ,
489
- invalid_requests_block_combinations ,
490
- indirect = ["block_body_override_requests" ],
481
+ @fork_covariant_parametrize (
482
+ parameter_names = "requests,block_body_override_requests,exception" ,
483
+ fn = invalid_requests_block_combinations ,
491
484
)
492
485
@pytest .mark .parametrize ("correct_requests_hash_in_header" , [True ])
493
486
def test_invalid_deposit_withdrawal_consolidation_requests_engine (
0 commit comments