- 
                Notifications
    
You must be signed in to change notification settings  - Fork 185
 
feat(benchmark): Add reversed bloatnet multi-opcode benchmarks with BALANCE-EXTCODE_ variants #2242
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(benchmark): Add reversed bloatnet multi-opcode benchmarks with BALANCE-EXTCODE_ variants #2242
Conversation
| 
           cc: @LouisTsai-Csie as you're the one with the most background on this, you might be the best reviewer.  | 
    
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only difference between this PR and PR #2186  is the order of operations. Instead of duplicating tests for each case, I recommend using parametrize feature in pytest framework to avoid repetitive code.
For example, in test_worst_zero_param, the test logic is shared across multiple opcodes. Rather than rewriting the test for each opcode, the implementation parametrizes the opcode argument and passes it into the test function, making it available inside the test:
# Parametrization example
@pytest.mark.parametrize(
    "opcode",
    [
        Op.ADDRESS,
        Op.ORIGIN,
        Op.CALLER,
        Op.CODESIZE,
        Op.GASPRICE,
        Op.COINBASE,
        Op.TIMESTAMP,
        Op.NUMBER,
        Op.PREVRANDAO,
        Op.GASLIMIT,
        Op.CHAINID,
        Op.BASEFEE,
        Op.BLOBBASEFEE,
        Op.GAS,
    ],
)
def test_worst_zero_param(
    state_test: StateTestFiller,
    pre: Alloc,
    opcode: Op,   # The parametrized opcode is passed here
    fork: Fork,
    gas_benchmark_value: int,
):
    # The opcode can be accessed directly in the testWe can also parametrize multiple values. For instance, test_worst_callvalue parametrizes both non_zero_value and from_origin. With two distinct values each, pytest generates 4 test combinations automatically.
For the current case, we can do the same with the operation order by introducing an op_order parameter:
@pytest.mark.parametrize("op_order", [True, False])
@pytest.mark.valid_from("Prague")
def test_bloatnet_balance_extcodecopy(
    blockchain_test: BlockchainTestFiller,
    pre: Alloc,
    fork: Fork,
    gas_benchmark_value: int,
    op_order: bool,  # Pass in the function
):Then, extract the operations whose order changes:
extcodecopy_op = (
    Op.PUSH1(1)  # size (1 byte)
    + Op.PUSH2(max_contract_size - 1)  # code offset (last byte)
    + Op.ADD(Op.MLOAD(32), 96)         # unique memory offset
    + Op.DUP4                          # address (duplicated earlier)
    + Op.EXTCODECOPY
    + Op.POP                           # clean up address
)
balance_op = Op.POP(Op.BALANCE)  # cold access
benchmark_op = extcodecopy_op + balance_op if op_order else balance_op + extcodecopy_opFinally, replace the sequence in the implementation with benchmark_op.
| 
           Hi @CPerezz, PR #2186 was merged, please rebase your changes! Some additional notes regarding the comments: if you want to run a specific subset of parameters, you can use the  For example, in  @pytest.mark.parametrize(
    "opcode",   # variable name
    [
        Op.ADDRESS,  # value
        ...
    ],
)If you only want to run the  fill -v tests/benchmark/test_worst_compute.py::test_worst_zero_param -m benchmark --clean --gas-benchmark-values 1 -k "opcode_ADDRESS"For multiple conditions, you can combine them with logical operators. For instance, in   | 
    
| 
           Thanks for the suggestion @LouisTsai-Csie ! I appreciate a lot the help with this one! It made everything much better!  | 
    
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @CPerezz , thanks for the changes. There are some folder restructuring due to recent PR merge (#2169 and #2186 ). It would be nice if you could help migrate the file in the PR to new location, so we would not have duplicate tests here.
The CI is failing due to linting issue, you could run uvx --with=tox-uv tox -e lint, and resolve the error displayed, thanks
For the bloatnet marker, now you should run -m stateful instead of -m benchmark, for all the tests under the stateful folder. This is required for future CI/CD integration for stateful cases, including bloatnet and XEN.
Otherwise, there are no more suggested changes!
… BloatNet tests Replace duplicate test functions with parametrized versions to avoid repetitive code. Each test now accepts a `balance_first` parameter that controls the order of operations, eliminating the need for separate `_extcodesize_balance`, `_extcodecopy_balance`, and `_extcodehash_balance` variants. Changes: - Add @pytest.mark.parametrize to test_bloatnet_balance_extcodesize, test_bloatnet_balance_extcodecopy, and test_bloatnet_balance_extcodehash - Each test now generates two variants via parametrization with descriptive IDs (e.g., "balance_extcodesize" and "extcodesize_balance") - Extract operation sequences into variables and conditionally compose them based on balance_first parameter - Remove test_bloatnet_extcodesize_balance, test_bloatnet_extcodecopy_balance, and test_bloatnet_extcodehash_balance (now covered by parametrization) This reduces the file from 793 lines to 462 lines while maintaining the same test coverage (6 tests total: 3 test functions × 2 parametrization values). To run specific parameter variants, use the -k flag: fill -k "balance_extcodesize" tests/benchmark/bloatnet/test_multi_opcode.py fill -k "extcodesize_balance" tests/benchmark/bloatnet/test_multi_opcode.py Co-Authored-By: LouisTsai-Csie <[email protected]>
ed323b0    to
    2ad25ea      
    Compare
  
    There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this!
… BloatNet tests (ethereum#2242) Replace duplicate test functions with parametrized versions to avoid repetitive code. Each test now accepts a `balance_first` parameter that controls the order of operations, eliminating the need for separate `_extcodesize_balance`, `_extcodecopy_balance`, and `_extcodehash_balance` variants. Changes: - Add @pytest.mark.parametrize to test_bloatnet_balance_extcodesize, test_bloatnet_balance_extcodecopy, and test_bloatnet_balance_extcodehash - Each test now generates two variants via parametrization with descriptive IDs (e.g., "balance_extcodesize" and "extcodesize_balance") - Extract operation sequences into variables and conditionally compose them based on balance_first parameter - Remove test_bloatnet_extcodesize_balance, test_bloatnet_extcodecopy_balance, and test_bloatnet_extcodehash_balance (now covered by parametrization) This reduces the file from 793 lines to 462 lines while maintaining the same test coverage (6 tests total: 3 test functions × 2 parametrization values). To run specific parameter variants, use the -k flag: fill -k "balance_extcodesize" tests/benchmark/bloatnet/test_multi_opcode.py fill -k "extcodesize_balance" tests/benchmark/bloatnet/test_multi_opcode.py
🗒️ Description
This PR completes the work started in #2186 whose goal was to implement all the variants (and orderings) of BALANCE <-> EXTCODE_ opcode abuse. No new setup scripts nor anything is required.
✅ Checklist
toxchecks to avoid unnecessary CI fails, see also Code Standards and Enabling Pre-commit Checks:uvx --with=tox-uv tox -e lint,typecheck,spellcheck,markdownlinttype(scope):.mkdocs servelocally and verified the auto-generated docs for new tests in the Test Case Reference are correctly formatted.@ported_frommarker.