Skip to content

Commit

Permalink
Rudimentary refactoring of gas_test
Browse files Browse the repository at this point in the history
  • Loading branch information
pdobacz committed Sep 11, 2024
1 parent 7fa7f18 commit 13c513e
Show file tree
Hide file tree
Showing 3 changed files with 9 additions and 146 deletions.
6 changes: 0 additions & 6 deletions tests/prague/eip7692_eof_v1/eip7069_extcall/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@
slot_call_status = next(_slot)
slot_calldata_1 = next(_slot)
slot_calldata_2 = next(_slot)
slot_cold_gas = next(_slot)
slot_warm_gas = next(_slot)
slot_oog_call_result = next(_slot)
slot_sanity_call_result = next(_slot)

slot_last_slot = next(_slot)

Expand All @@ -28,8 +24,6 @@

"""Storage values for common testing fields"""
value_code_worked = 0x2015
value_call_legacy_abort = 0
value_call_legacy_success = 1

"""Memory and storage value for calldata"""
value_calldata_1 = 0xC1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1
Expand Down
134 changes: 2 additions & 132 deletions tests/prague/eip7692_eof_v1/eip7069_extcall/test_gas.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,13 @@

import pytest

from ethereum_test_tools import Account, Alloc, Environment, StateTestFiller, Transaction
from ethereum_test_tools import Alloc, Environment, StateTestFiller
from ethereum_test_tools.eof.v1 import Container
from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.eof.v1 import Section
from ethereum_test_types.types import EOA
from ethereum_test_vm import Bytecode, EVMCodeType

from .. import EOF_FORK_NAME
from ..gas_test import gas_test
from . import REFERENCE_SPEC_GIT_PATH, REFERENCE_SPEC_VERSION
from .helpers import (
slot_cold_gas,
slot_oog_call_result,
slot_sanity_call_result,
slot_warm_gas,
value_call_legacy_abort,
value_call_legacy_success,
)

REFERENCE_SPEC_GIT_PATH = REFERENCE_SPEC_GIT_PATH
REFERENCE_SPEC_VERSION = REFERENCE_SPEC_VERSION
Expand All @@ -47,126 +37,6 @@ def state_env() -> Environment:
return Environment()


def gas_test(
state_test: StateTestFiller,
env: Environment,
pre: Alloc,
setup_code: Bytecode,
subject_code: Bytecode,
tear_down_code: Bytecode,
cold_gas: int,
warm_gas: int | None = None,
subject_subcontainer: Container | None = None,
sender: EOA | None = None,
subject_balance: int = 0,
oog_difference: int = 1,
):
"""
Creates a State Test to check the gas cost of a sequence of EOF code.
`setup_code` and `tear_down_code` are called multiple times during the test, and MUST NOT have
any side-effects which persist across message calls, and in particular, any effects on the gas
usage of `subject_code`.
"""
if cold_gas <= 0:
raise ValueError(f"Target gas allocations (cold_gas) must be > 0, got {cold_gas}")
if warm_gas is None:
warm_gas = cold_gas

if not sender:
sender = pre.fund_eoa()

address_baseline = pre.deploy_contract(Container.Code(setup_code + tear_down_code))
code_subject = setup_code + subject_code + tear_down_code
address_subject = pre.deploy_contract(
Container.Code(code_subject)
if not subject_subcontainer
else Container(
sections=[
Section.Code(code_subject),
Section.Container(subject_subcontainer),
]
),
balance=subject_balance,
)
# 2 times GAS, POP, CALL, 6 times PUSH1 - instructions charged for at every gas run
gas_single_gas_run = 2 * 2 + 2 + WARM_ACCOUNT_ACCESS_GAS + 6 * 3
address_legacy_harness = pre.deploy_contract(
code=(
# warm subject and baseline without executing
(Op.BALANCE(address_subject) + Op.POP + Op.BALANCE(address_baseline) + Op.POP)
# Baseline gas run
+ (
Op.GAS
+ Op.CALL(address=address_baseline, gas=Op.GAS)
+ Op.POP
+ Op.GAS
+ Op.SWAP1
+ Op.SUB
)
# cold gas run
+ (
Op.GAS
+ Op.CALL(address=address_subject, gas=Op.GAS)
+ Op.POP
+ Op.GAS
+ Op.SWAP1
+ Op.SUB
)
# warm gas run
+ (
Op.GAS
+ Op.CALL(address=address_subject, gas=Op.GAS)
+ Op.POP
+ Op.GAS
+ Op.SWAP1
+ Op.SUB
)
# Store warm gas: DUP3 is the gas of the baseline gas run
+ (Op.DUP3 + Op.SWAP1 + Op.SUB + Op.PUSH2(slot_warm_gas) + Op.SSTORE)
# store cold gas: DUP2 is the gas of the baseline gas run
+ (Op.DUP2 + Op.SWAP1 + Op.SUB + Op.PUSH2(slot_cold_gas) + Op.SSTORE)
# oog gas run:
# - DUP7 is the gas of the baseline gas run, after other CALL args were pushed
# - subtract the gas charged by the harness
# - add warm gas charged by the subject
# - subtract `oog_difference` to cause OOG exception (1 by default)
+ Op.SSTORE(
slot_oog_call_result,
Op.CALL(
gas=Op.ADD(warm_gas - gas_single_gas_run - oog_difference, Op.DUP7),
address=address_subject,
),
)
# sanity gas run: not subtracting 1 to see if enough gas makes the call succeed
+ Op.SSTORE(
slot_sanity_call_result,
Op.CALL(
gas=Op.ADD(warm_gas - gas_single_gas_run, Op.DUP7),
address=address_subject,
),
)
+ Op.STOP
),
evm_code_type=EVMCodeType.LEGACY, # Needs to be legacy to use GAS opcode
)

post = {
address_legacy_harness: Account(
storage={
slot_warm_gas: warm_gas,
slot_cold_gas: cold_gas,
slot_oog_call_result: value_call_legacy_abort,
slot_sanity_call_result: value_call_legacy_success,
},
),
}

tx = Transaction(to=address_legacy_harness, gas_limit=env.gas_limit, sender=sender)

state_test(env=env, pre=pre, tx=tx, post=post)


@pytest.mark.parametrize(
["opcode", "pre_setup", "cold_gas", "warm_gas", "new_account"],
[
Expand Down
15 changes: 7 additions & 8 deletions tests/prague/eip7692_eof_v1/eip7620_eof_create/test_gas.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from ethereum_test_tools.vm.opcode import Opcodes as Op

from .. import EOF_FORK_NAME
from ..eip7069_extcall.test_gas import gas_test
from ..gas_test import gas_test
from .helpers import (
aborting_container,
big_runtime_subcontainer,
Expand All @@ -33,17 +33,13 @@

pytestmark = pytest.mark.valid_from(EOF_FORK_NAME)


COLD_ACCOUNT_ACCESS_GAS = 2600
WARM_ACCOUNT_ACCESS_GAS = 100
CALL_WITH_VALUE_GAS = 9000
ACCOUNT_CREATION_GAS = 25000


EOFCREATE_GAS = 32000


def make_initcode(runtime: Container):
"""
Wraps a runtime container into a minimal initcontainer
"""
return Container(
name="Initcode Subcontainer",
sections=[
Expand All @@ -54,6 +50,9 @@ def make_initcode(runtime: Container):


def make_factory(initcode: Container):
"""
Wraps an initcontainer into a minimal runtime container
"""
return Container(
name="Factory Subcontainer",
sections=[
Expand Down

0 comments on commit 13c513e

Please sign in to comment.