-
Notifications
You must be signed in to change notification settings - Fork 454
feat(benchmarks): add eth transfer cases for repricing #2837
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
Open
jochem-brouwer
wants to merge
10
commits into
ethereum:forks/amsterdam
Choose a base branch
from
jochem-brouwer:eth-transfer-bench-repricing
base: forks/amsterdam
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+182
−0
Open
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
8c8c2fe
(Claude): add eth transfer cases for repricing
jochem-brouwer e662356
refactor: split test based on pre-alloc
LouisTsai-Csie 4c02234
refactor: bump execution cost for contract ether reception
LouisTsai-Csie a8807d8
chore: remove unnecessary parametrization
LouisTsai-Csie 71783bc
refactor: move new benchmark under stateful folder
LouisTsai-Csie 7d841f0
fix: apply suggested changes
LouisTsai-Csie 6892eb2
feat: add receipt check
LouisTsai-Csie 16b73da
(Claude): add distinct senders
jochem-brouwer df4d140
(Claude): do not limit distinct senders
jochem-brouwer 147b123
(Claude): add uniq jumpdest contract test
jochem-brouwer File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
182 changes: 182 additions & 0 deletions
182
tests/benchmark/stateful/bloatnet/test_transaction_types.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,182 @@ | ||
| """Benchmark ether transfers to receivers that exist on-chain.""" | ||
|
|
||
| import itertools | ||
| from typing import Generator | ||
|
|
||
| import pytest | ||
| from execution_testing import ( | ||
| EOA, | ||
| Address, | ||
| Alloc, | ||
| BenchmarkTestFiller, | ||
| Block, | ||
| Fork, | ||
| Transaction, | ||
| compute_create2_address, | ||
| compute_create_address, | ||
| ) | ||
|
|
||
| # Deterministic sender pool: keys start at 0x111...111 (32 bytes) and | ||
| # increment by 1. Accounts are assumed to be pre-funded on bloatnet | ||
| # (e.g. by Spamoor), so they are intentionally NOT added to the pre-alloc. | ||
| SENDER_BASE_KEY = ( | ||
| 0x1111111111111111111111111111111111111111111111111111111111111111 | ||
| ) | ||
|
|
||
|
|
||
| def yield_distinct_sender() -> Generator[EOA, None, None]: | ||
| """Yield deterministic sender EOAs pre-funded on-chain.""" | ||
| for i in itertools.count(0): | ||
| yield EOA(key=SENDER_BASE_KEY + i) | ||
|
|
||
|
|
||
| # Bittrex controller mainnet address | ||
| # Creates 1.5M contracts with deterministic address via CREATE | ||
| # It is guaranteed no contract is destructed | ||
| # Used for existing contract targets in benchmark | ||
| BITTREX_CONTROLLER_ADDRESS = Address( | ||
| 0xA3C1E324CA1CE40DB73ED6026C4A177F099B5770 | ||
| ) | ||
|
|
||
|
|
||
| # Ether reception cost for Bittrex-created contracts | ||
| RECEIVER_CONTRACT_EXECUTION_GAS = 51 | ||
|
|
||
|
|
||
| # Arachnid's deterministic deployment proxy. Assumed to have already | ||
| # deployed the unique-code contracts via CREATE2 with salts 0, 1, 2, ... | ||
| DETERMINISTIC_FACTORY_ADDRESS = Address( | ||
| 0x4E59B44847B379578588920CA78FBF26C0B4956C | ||
| ) | ||
|
|
||
|
|
||
| # Initcode deployed by DETERMINISTIC_FACTORY_ADDRESS for each | ||
| # diff_to_unique_code_jumpdest_contract receiver. Returns a 24,576-byte | ||
| # runtime whose entry is PUSH2 0x5fff; JUMP, landing on a JUMPDEST near | ||
| # the end of code (then implicit STOP). Each contract embeds its own | ||
| # address in code, so the deployed code is unique per address while | ||
| # initcode (and therefore the CREATE2 hash input) is shared. | ||
| UNIQUE_CODE_JUMPDEST_INITCODE = bytes.fromhex( | ||
| "7f5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b6000" | ||
| "526020600060205e6040600060405e6080600060805e61010060006101005e61020060" | ||
| "006102005e61040060006104005e61080060006108005e61100060006110005e612000" | ||
| "60006120005e61400060006140005e7f615fff565b5b5b5b5b5b5b5b5b5b5b5b5b5b5b" | ||
| "5b5b5b5b5b5b5b5b5b5b5b5b5b6000527f5b5b5b5b5b5b5b5b5b5b5b5b000000000000" | ||
| "000000000000000000000000000030176020526160006000f3" | ||
| ) | ||
|
|
||
|
|
||
| # Runtime gas cost: PUSH2 (3) + JUMP (8) + JUMPDEST (1) = 12. | ||
| RECEIVER_JUMPDEST_EXECUTION_GAS = 3 + 8 + 1 | ||
|
|
||
|
|
||
| def yield_distinct_contract_receiver() -> Generator[Address, None, None]: | ||
| """Yield contract account created by Bittrex controller via CREATE.""" | ||
| for nonce in itertools.count(2): | ||
| yield compute_create_address( | ||
| address=BITTREX_CONTROLLER_ADDRESS, nonce=nonce | ||
| ) | ||
|
|
||
|
|
||
| def yield_distinct_unique_code_jumpdest_receiver() -> ( | ||
| Generator[Address, None, None] | ||
| ): | ||
| """ | ||
| Yield contract addresses deployed by the deterministic CREATE2 factory. | ||
|
|
||
| Each address corresponds to a contract with unique deployed code whose | ||
| runtime executes PUSH2 + JUMP + JUMPDEST (12 gas). | ||
| """ | ||
| for salt in itertools.count(0): | ||
| yield compute_create2_address( | ||
| address=DETERMINISTIC_FACTORY_ADDRESS, | ||
| salt=salt, | ||
| initcode=UNIQUE_CODE_JUMPDEST_INITCODE, | ||
| ) | ||
|
|
||
|
|
||
| def yield_distinct_existent_receiver() -> Generator[Address, None, None]: | ||
| """ | ||
| Yield existing balance-only EOA on bloatnet. pre-funded by Spamoor | ||
| (https://github.com/CPerezz/spamoor/pull/12). | ||
| """ | ||
| for address in itertools.count(0x1000): | ||
| yield Address(address) | ||
|
|
||
|
|
||
| def yield_distinct_nonexistent_receiver() -> Generator[Address, None, None]: | ||
| """Yield non-existent accounts starting from keccak256('random').""" | ||
| for address in itertools.count(0xF3CF193BB4AF1022AF7D2089F37D8BAE7157B85F): | ||
| yield Address(address) | ||
|
|
||
|
|
||
| @pytest.mark.repricing | ||
| @pytest.mark.parametrize( | ||
| "case_id", | ||
| [ | ||
| "diff_to_nonexistent", | ||
| "diff_to_existent", | ||
| "diff_to_contract", | ||
| "diff_to_unique_code_jumpdest_contract", | ||
| ], | ||
| ) | ||
| @pytest.mark.parametrize("transfer_amount", [0, 1]) | ||
| def test_ether_transfers_onchain_receivers( | ||
| benchmark_test: BenchmarkTestFiller, | ||
| pre: Alloc, | ||
| case_id: str, | ||
| transfer_amount: int, | ||
| fork: Fork, | ||
| gas_benchmark_value: int, | ||
| ) -> None: | ||
| """ | ||
| Ether transfers to receivers that exist on-chain at run time. | ||
|
|
||
| Scenarios: | ||
| - diff_to_nonexistent: distinct nonexistent receivers | ||
| (matches AccountMode.NON_EXISTING_ACCOUNT) | ||
| - diff_to_existent: distinct existent EOA receivers | ||
| (matches AccountMode.EXISTING_EOA) | ||
| - diff_to_contract: distinct contract receivers | ||
| (matches AccountMode.EXISTING_CONTRACT) | ||
| - diff_to_unique_code_jumpdest_contract: distinct CREATE2 contract | ||
| receivers each holding unique deployed code; runtime executes | ||
| PUSH2 + JUMP + JUMPDEST. | ||
| """ | ||
| senders = yield_distinct_sender() | ||
| receiver_execution_gas = 0 | ||
| if case_id == "diff_to_nonexistent": | ||
| receivers = yield_distinct_nonexistent_receiver() | ||
| elif case_id == "diff_to_existent": | ||
| receivers = yield_distinct_existent_receiver() | ||
| elif case_id == "diff_to_contract": | ||
| receivers = yield_distinct_contract_receiver() | ||
| receiver_execution_gas = RECEIVER_CONTRACT_EXECUTION_GAS | ||
| elif case_id == "diff_to_unique_code_jumpdest_contract": | ||
| receivers = yield_distinct_unique_code_jumpdest_receiver() | ||
| receiver_execution_gas = RECEIVER_JUMPDEST_EXECUTION_GAS | ||
| else: | ||
| raise ValueError(f"Unknown case: {case_id}") | ||
|
|
||
| iteration_cost = ( | ||
| fork.transaction_intrinsic_cost_calculator()() + receiver_execution_gas | ||
| ) | ||
| iteration_count = gas_benchmark_value // iteration_cost | ||
|
|
||
| txs = [ | ||
| Transaction( | ||
| to=next(receivers), | ||
| value=transfer_amount, | ||
| gas_limit=iteration_cost, | ||
| sender=next(senders), | ||
| ) | ||
| for _ in range(iteration_count) | ||
| ] | ||
|
|
||
| benchmark_test( | ||
| pre=pre, | ||
| post={}, | ||
| blocks=[Block(txs=txs)], | ||
| expected_benchmark_gas_used=iteration_count * iteration_cost, | ||
| expected_receipt_status=1, | ||
| ) | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.