Skip to content

Commit

Permalink
update pyspecs to 1.0.5
Browse files Browse the repository at this point in the history
  • Loading branch information
winsvega committed Oct 3, 2023
1 parent 6613563 commit a39c597
Show file tree
Hide file tree
Showing 12 changed files with 475 additions and 131 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def post(self, test_case: str) -> Dict: # noqa: D102
if test_case == "tx_in_withdrawals_block":
return {}
if test_case == "tx_after_withdrawals_block":
return {TestAddress: Account(balance=ONE_GWEI)}
return {TestAddress: Account(balance=ONE_GWEI + 1)}
raise Exception("Invalid test case.")

def test_use_value_in_tx(
Expand All @@ -121,7 +121,7 @@ def test_use_value_in_tx(
"""
Test sending withdrawal value in a transaction.
"""
pre = {TestAddress: Account(balance=0)}
pre = {TestAddress: Account(balance=1)}
blockchain_test(pre=pre, post=post, blocks=blocks)


Expand All @@ -137,7 +137,7 @@ def test_use_value_in_contract(blockchain_test: BlockchainTestFiller):
pre = {
TestAddress: Account(balance=1000000000000000000000, nonce=0),
to_address(0x100): Account(balance=0, code=SEND_ONE_GWEI),
to_address(0x200): Account(balance=0),
to_address(0x200): Account(balance=1),
}
tx = Transaction(
# Transaction sent from the `TestAddress`, which has 0 balance at start
Expand Down Expand Up @@ -172,7 +172,7 @@ def test_use_value_in_contract(blockchain_test: BlockchainTestFiller):
}
),
to_address(0x200): Account(
balance=ONE_GWEI,
balance=ONE_GWEI + 1,
),
}

Expand Down Expand Up @@ -384,7 +384,7 @@ def test_self_destructing_account(blockchain_test: BlockchainTestFiller):
balance=(100 * ONE_GWEI),
),
to_address(0x200): Account(
balance=0,
balance=1,
),
}

Expand Down Expand Up @@ -417,7 +417,7 @@ def test_self_destructing_account(blockchain_test: BlockchainTestFiller):
),
to_address(0x200): Account(
code=None,
balance=(100 * ONE_GWEI),
balance=(100 * ONE_GWEI) + 1,
),
}

Expand Down
32 changes: 14 additions & 18 deletions src/EIPTestsFiller/Pyspecs/cancun/eip4788_beacon_root/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,7 @@
)
from ethereum_test_tools.vm.opcode import Opcodes as Op

from .common import (
BEACON_ROOT_CONTRACT_ADDRESS,
BEACON_ROOT_CONTRACT_CALL_GAS,
HISTORY_BUFFER_LENGTH,
SYSTEM_ADDRESS,
expected_storage,
)
from .spec import Spec, SpecHelpers

BLOB_COMMITMENT_VERSION_KZG = 1

Expand Down Expand Up @@ -88,7 +82,7 @@ def call_value() -> int: # noqa: D103

@pytest.fixture
def call_gas() -> int: # noqa: D103
return BEACON_ROOT_CONTRACT_CALL_GAS
return Spec.BEACON_ROOTS_CALL_GAS


@pytest.fixture
Expand All @@ -108,7 +102,7 @@ def contract_call_account(call_type: Op, call_value: int, call_gas: int) -> Acco
0x00, # store the result of the contract call in storage[0]
call_type(
call_gas,
BEACON_ROOT_CONTRACT_ADDRESS,
Spec.BEACON_ROOTS_ADDRESS,
call_value,
args_start,
args_length,
Expand All @@ -122,7 +116,7 @@ def contract_call_account(call_type: Op, call_value: int, call_gas: int) -> Acco
0x00,
call_type(
call_gas,
BEACON_ROOT_CONTRACT_ADDRESS,
Spec.BEACON_ROOTS_ADDRESS,
args_start,
args_length,
return_start,
Expand Down Expand Up @@ -189,17 +183,19 @@ def pre(
Prepares the pre state of all test cases, by setting the balance of the
source account of all test transactions, and the contract caller account.
"""
return {
pre_alloc = {
TestAddress: Account(
nonce=0,
balance=0x10**10,
),
caller_address: contract_call_account,
SYSTEM_ADDRESS: Account(
}
if system_address_balance > 0:
pre_alloc[to_address(Spec.SYSTEM_ADDRESS)] = Account(
nonce=0,
balance=system_address_balance,
),
}
)
return pre_alloc


@pytest.fixture
Expand All @@ -223,10 +219,10 @@ def access_list(auto_access_list: bool, timestamp: int) -> List[AccessList]:
if auto_access_list:
return [
AccessList(
address=BEACON_ROOT_CONTRACT_ADDRESS,
address=Spec.BEACON_ROOTS_ADDRESS,
storage_keys=[
timestamp,
timestamp + HISTORY_BUFFER_LENGTH,
timestamp + Spec.HISTORY_BUFFER_LENGTH,
],
),
]
Expand Down Expand Up @@ -262,7 +258,7 @@ def tx(
"""
Prepares transaction to call the beacon root contract caller account.
"""
to = BEACON_ROOT_CONTRACT_ADDRESS if call_beacon_root_contract else tx_to_address
to = Spec.BEACON_ROOTS_ADDRESS if call_beacon_root_contract else tx_to_address
kwargs: Dict = {
"ty": tx_type,
"nonce": 0,
Expand Down Expand Up @@ -305,7 +301,7 @@ def post(
"""
storage = Storage()
if not call_beacon_root_contract:
storage = expected_storage(
storage = SpecHelpers.expected_storage(
beacon_root=beacon_root,
valid_call=valid_call,
valid_input=valid_input,
Expand Down
78 changes: 78 additions & 0 deletions src/EIPTestsFiller/Pyspecs/cancun/eip4788_beacon_root/spec.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
"""
Defines EIP-4788 specification constants and functions.
"""
from dataclasses import dataclass

from ethereum_test_tools import Storage


@dataclass(frozen=True)
class ReferenceSpec:
"""
Defines the reference spec version and git path.
"""

git_path: str
version: str


ref_spec_4788 = ReferenceSpec("EIPS/eip-4788.md", "e7608fe8ac8a60934ca874f5aab7d5c1f4ff7782")


# Constants
@dataclass(frozen=True)
class Spec:
"""
Parameters from the EIP-4788 specifications as defined at
https://eips.ethereum.org/EIPS/eip-4788#specification
"""

BEACON_ROOTS_ADDRESS = 0x000F3DF6D732807EF1319FB7B8BB8522D0BEAC02
BEACON_ROOTS_CALL_GAS = 100_000
BEACON_ROOTS_DEPLOYER_ADDRESS = 0x0B799C86A49DEEB90402691F1041AA3AF2D3C875
HISTORY_BUFFER_LENGTH = 8_191
SYSTEM_ADDRESS = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE
FORK_TIMESTAMP = 15_000 # ShanghaiToCancun timestamp


@dataclass(frozen=True)
class SpecHelpers:
"""
Helper functions closely related to the EIP-4788 specification.
"""

def timestamp_index(self, timestamp: int) -> int:
"""
Derive the timestamp index into the timestamp ring buffer.
"""
return timestamp % Spec.HISTORY_BUFFER_LENGTH

def root_index(self, timestamp: int) -> int:
"""
Derive the root index into the root ring buffer.
"""
return self.timestamp_index(timestamp) + Spec.HISTORY_BUFFER_LENGTH

@staticmethod
def expected_storage(
*,
beacon_root: bytes,
valid_call: bool,
valid_input: bool,
) -> Storage:
"""
Derives the expected storage for a given beacon root contract call
dependent on:
- success or failure of the call
- validity of the timestamp input used within the call
"""
# By default assume the call is unsuccessful and all keys are zero
storage = Storage({k: 0 for k in range(4)})
if valid_call and valid_input:
# beacon root contract call is successful
storage[0] = 1
storage[1] = beacon_root
storage[2] = 32
storage[3] = beacon_root

return storage
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,29 @@

import pytest

from ethereum_test_tools import Environment, StateTestFiller, Transaction
from ethereum_test_tools import (
Account,
Environment,
StateTestFiller,
Storage,
Transaction,
to_address,
)
from ethereum_test_tools.vm.opcode import Opcodes as Op

from .common import BEACON_ROOT_CONTRACT_CALL_GAS, REF_SPEC_4788_GIT_PATH, REF_SPEC_4788_VERSION
from .spec import Spec, ref_spec_4788

REFERENCE_SPEC_GIT_PATH = REF_SPEC_4788_GIT_PATH
REFERENCE_SPEC_VERSION = REF_SPEC_4788_VERSION
REFERENCE_SPEC_GIT_PATH = ref_spec_4788.git_path
REFERENCE_SPEC_VERSION = ref_spec_4788.version


@pytest.mark.parametrize(
"call_gas, valid_call",
[
pytest.param(BEACON_ROOT_CONTRACT_CALL_GAS, True),
pytest.param(BEACON_ROOT_CONTRACT_CALL_GAS + 1, True),
pytest.param(Spec.BEACON_ROOTS_CALL_GAS, True),
pytest.param(Spec.BEACON_ROOTS_CALL_GAS + 1, True),
pytest.param(
BEACON_ROOT_CONTRACT_CALL_GAS - 1,
Spec.BEACON_ROOTS_CALL_GAS - 1,
False,
marks=pytest.mark.xfail(reason="gas calculation is incorrect"), # TODO
),
Expand Down Expand Up @@ -220,3 +227,66 @@ def test_tx_to_beacon_root_contract(
txs=[tx],
post=post,
)


@pytest.mark.parametrize(
"tx_data",
[
pytest.param(int.to_bytes(0, length=32, byteorder="big"), id="zero_calldata"),
],
)
@pytest.mark.parametrize("valid_call,valid_input", [(False, False)])
@pytest.mark.parametrize("timestamp", [12])
@pytest.mark.valid_from("Cancun")
def test_invalid_beacon_root_calldata_value(
state_test: StateTestFiller,
env: Environment,
pre: Dict,
tx: Transaction,
post: Dict,
):
"""
Tests the beacon root contract call using invalid input values:
- zero calldata.
Contract should revert.
"""
state_test(
env=env,
pre=pre,
txs=[tx],
post=post,
)


@pytest.mark.parametrize("timestamp", [12])
@pytest.mark.valid_from("Cancun")
def test_beacon_root_selfdestruct(
state_test: StateTestFiller,
env: Environment,
pre: Dict,
tx: Transaction,
post: Dict,
):
"""
Tests that self destructing the beacon root address transfers actors balance correctly.
"""
# self destruct actor
pre[to_address(0x1337)] = Account(
code=Op.SELFDESTRUCT(Spec.BEACON_ROOTS_ADDRESS),
balance=0xBA1,
)
# self destruct caller
pre[to_address(0xCC)] = Account(
code=Op.CALL(100000, Op.PUSH20(to_address(0x1337)), 0, 0, 0, 0, 0)
+ Op.SSTORE(0, Op.BALANCE(Spec.BEACON_ROOTS_ADDRESS)),
)
post[to_address(0xCC)] = Account(
storage=Storage({0: 0xBA1}),
)
state_test(
env=env,
pre=pre,
txs=[tx, Transaction(nonce=1, to=to_address(0xCC), gas_limit=100000, gas_price=10)],
post=post,
)
Loading

0 comments on commit a39c597

Please sign in to comment.