Skip to content

Commit

Permalink
Merge pull request #52 from jsign/jsign/exhaustive-fixes
Browse files Browse the repository at this point in the history
Exhaustive check fixes
  • Loading branch information
jsign authored Sep 12, 2024
2 parents 4bc9b7f + 0fcff0d commit cfa073f
Show file tree
Hide file tree
Showing 21 changed files with 283 additions and 309 deletions.
28 changes: 21 additions & 7 deletions src/ethereum_test_forks/forks/forks.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,9 @@ def call_opcodes(
"""
At Homestead, DELEGATECALL opcode was introduced.
"""
return [(Opcodes.DELEGATECALL, EVMCodeType.LEGACY),] + super(
return [
(Opcodes.DELEGATECALL, EVMCodeType.LEGACY),
] + super(
Homestead, cls
).call_opcodes(block_number, timestamp)

Expand Down Expand Up @@ -449,7 +451,9 @@ def call_opcodes(
"""
At Byzantium, STATICCALL opcode was introduced.
"""
return [(Opcodes.STATICCALL, EVMCodeType.LEGACY),] + super(
return [
(Opcodes.STATICCALL, EVMCodeType.LEGACY),
] + super(
Byzantium, cls
).call_opcodes(block_number, timestamp)

Expand Down Expand Up @@ -483,7 +487,9 @@ def create_opcodes(
"""
At Constantinople, `CREATE2` opcode is added.
"""
return [(Opcodes.CREATE2, EVMCodeType.LEGACY),] + super(
return [
(Opcodes.CREATE2, EVMCodeType.LEGACY),
] + super(
Constantinople, cls
).create_opcodes(block_number, timestamp)

Expand Down Expand Up @@ -974,7 +980,7 @@ def pre_allocation_blockchain(cls) -> Mapping:
type tests.
"""
new_allocation = {
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE: {
Address(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE): {
"nonce": 1,
"code": (
"0x60203611603157600143035f35116029575f35612000014311602957612000"
Expand Down Expand Up @@ -1020,7 +1026,10 @@ def evm_code_types(cls, block_number: int = 0, timestamp: int = 0) -> List[EVMCo
"""
EOF V1 is supported starting from this fork.
"""
return super(CancunEIP7692, cls,).evm_code_types( # noqa: SC200
return super(
CancunEIP7692,
cls,
).evm_code_types( # noqa: SC200
block_number,
timestamp,
) + [EVMCodeType.EOF_V1]
Expand Down Expand Up @@ -1049,7 +1058,9 @@ def create_opcodes(
"""
EOF V1 introduces `EOFCREATE`.
"""
return [(Opcodes.EOFCREATE, EVMCodeType.EOF_V1),] + super(
return [
(Opcodes.EOFCREATE, EVMCodeType.EOF_V1),
] + super(
CancunEIP7692, cls # noqa: SC200
).create_opcodes(block_number, timestamp)

Expand Down Expand Up @@ -1084,7 +1095,10 @@ def evm_code_types(cls, block_number: int = 0, timestamp: int = 0) -> List[EVMCo
"""
EOF V1 is supported starting from this fork.
"""
return super(PragueEIP7692, cls,).evm_code_types( # noqa: SC200
return super(
PragueEIP7692,
cls,
).evm_code_types( # noqa: SC200
block_number,
timestamp,
) + [EVMCodeType.EOF_V1]
Expand Down
49 changes: 26 additions & 23 deletions tests/verkle/eip4762_verkle_gas_witness/test_balance.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,23 @@
Block,
BlockchainTestFiller,
Environment,
Hash,
TestAddress,
TestAddress2,
Transaction,
WitnessCheck,
)
from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_forks import Fork
from ethereum_test_types.verkle.helpers import chunkify_code

# TODO(verkle): Update reference spec version
REFERENCE_SPEC_GIT_PATH = "EIPS/eip-4762.md"
REFERENCE_SPEC_VERSION = "2f8299df31bb8173618901a03a8366a3183479b0"

precompile_address = Address("0x04")
system_contract_address = Address("0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02")
system_contract_address = Address("0xfffffffffffffffffffffffffffffffffffffffe")
example_address = Address("0xd94f5374fce5edbc8e2a8697c15331677e6ebf0c")


# TODO(verkle): update to Osaka when t8n supports the fork.
@pytest.mark.valid_from("Verkle")
@pytest.mark.parametrize(
"target",
Expand All @@ -43,28 +41,27 @@
],
)
@pytest.mark.parametrize("warm", [True, False])
def test_balance(blockchain_test: BlockchainTestFiller, fork: str, target, warm):
def test_balance(blockchain_test: BlockchainTestFiller, fork: Fork, target, warm):
"""
Test BALANCE witness with/without WARM access.
"""
_balance(blockchain_test, fork, target, [target], warm=warm)
_balance(blockchain_test, fork, target, True, warm=warm)


# TODO(verkle): update to Osaka when t8n supports the fork.
@pytest.mark.valid_from("Verkle")
@pytest.mark.parametrize("target", [example_address, precompile_address])
def test_balance_insufficient_gas(blockchain_test: BlockchainTestFiller, fork: str, target):
def test_balance_insufficient_gas(blockchain_test: BlockchainTestFiller, fork: Fork, target):
"""
Test BALANCE with insufficient gas.
"""
_balance(blockchain_test, fork, target, [], 21_042)
_balance(blockchain_test, fork, target, False, 21_042)


def _balance(
blockchain_test: BlockchainTestFiller,
fork: str,
fork: Fork,
target: Address,
exp_addr_basic_data: list[Address],
exp_target_basic_data: bool,
gas_limit=1_000_000,
warm=False,
):
Expand All @@ -78,10 +75,12 @@ def _balance(
pre = {
TestAddress: Account(balance=1000000000000000000000),
TestAddress2: Account(code=Op.BALANCE(target) * (2 if warm else 1) + Op.PUSH0 + Op.SSTORE),
target: Account(balance=0xF1),
precompile_address: Account(balance=0xF2),
precompile_address: Account(balance=0xF0),
}

if target != precompile_address and target != system_contract_address:
pre[target] = Account(balance=0xF2)

tx = Transaction(
ty=0x0,
chain_id=0x01,
Expand All @@ -92,19 +91,23 @@ def _balance(
)

witness_check = WitnessCheck(fork=Verkle)
witness_check.add_account_full(address=TestAddress, account=pre[TestAddress])
witness_check.add_account_full(address=TestAddress2, account=pre[TestAddress2])
witness_check.add_storage_slot(address=TestAddress2, storage_slot=0, value=None)
for address in [TestAddress, TestAddress2, env.fee_recipient]:
witness_check.add_account_full(address=address, account=pre.get(address))

code_chunks = chunkify_code(pre[TestAddress2].code)
for i, chunk in enumerate(code_chunks, start=0):
witness_check.add_code_chunk(address=TestAddress2, chunk_number=i, value=chunk)

witness_check.add_account_full(address=env.fee_recipient, account=None)
for address in exp_addr_basic_data:
witness_check.add_account_basic_data(
address=address,
account=pre[address],
)
witness_check.add_storage_slot(address=TestAddress2, storage_slot=0, value=None)

target_account = (
pre[target]
if target != system_contract_address
else Account(**fork.pre_allocation_blockchain()[system_contract_address])
)

if exp_target_basic_data:
witness_check.add_account_basic_data(address=target, account=target_account)

blocks = [
Block(
Expand All @@ -114,7 +117,7 @@ def _balance(
]

post = {
TestAddress2: Account(code=pre[TestAddress2].code, storage={0: pre[target].balance}),
TestAddress2: Account(code=pre[TestAddress2].code, storage={0: target_account.balance}),
}

blockchain_test(
Expand Down
58 changes: 28 additions & 30 deletions tests/verkle/eip4762_verkle_gas_witness/test_calls.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import pytest

from ethereum_test_forks import Verkle
from ethereum_test_tools import (
Account,
Address,
Expand All @@ -21,17 +22,16 @@
WitnessCheck,
)
from ethereum_test_tools.vm.opcode import Opcodes as Op
from ethereum_test_types.verkle.helpers import chunkify_code

# TODO(verkle): Update reference spec version
REFERENCE_SPEC_GIT_PATH = "EIPS/eip-4762.md"
REFERENCE_SPEC_VERSION = "2f8299df31bb8173618901a03a8366a3183479b0"

caller_address = Address("0xd94f5374fce5edbc8e2a8697c15331677e6ebf0c")
system_contract_address = Address("0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02")
system_contract_address = Address("0xfffffffffffffffffffffffffffffffffffffffe")
precompile_address = Address("0x04")


# TODO(verkle): update to Osaka when t8n supports the fork.
@pytest.mark.valid_from("Verkle")
@pytest.mark.parametrize(
"call_instruction, value",
Expand All @@ -48,9 +48,9 @@
@pytest.mark.parametrize(
"target",
[
TestAddress2,
# TestAddress2,
precompile_address,
system_contract_address,
# system_contract_address,
],
)
def test_calls(
Expand All @@ -66,7 +66,6 @@ def test_calls(
_generic_call(blockchain_test, call_instruction, target, value)


# TODO(verkle): update to Osaka when t8n supports the fork.
@pytest.mark.valid_from("Verkle")
@pytest.mark.parametrize(
"call_instruction",
Expand All @@ -84,7 +83,6 @@ def test_calls_warm(blockchain_test: BlockchainTestFiller, fork: str, call_instr
_generic_call(blockchain_test, call_instruction, TestAddress2, 0, warm=True)


# TODO(verkle): update to Osaka when t8n supports the fork.
@pytest.mark.valid_from("Verkle")
@pytest.mark.skip("Pending TBD gas limits")
@pytest.mark.parametrize(
Expand Down Expand Up @@ -174,17 +172,20 @@ def _generic_call(
value=tx_value,
)

witness_check = WitnessCheck()
witness_check = WitnessCheck(fork=Verkle)
for address in [TestAddress, caller_address, env.fee_recipient]:
witness_check.add_account_full(
address=address,
account=(None if address == env.fee_recipient else pre[address]),
)
if target != precompile_address and enough_gas_read_witness:
witness_check.add_account_basic_data(
address=target,
account=pre[target],
)
witness_check.add_account_full(address=address, account=pre.get(address))
if enough_gas_read_witness:
if value > 0 or (target != precompile_address and target != precompile_address):
witness_check.add_account_basic_data(address=target, account=pre[target])

code_chunks = chunkify_code(pre[caller_address].code)
for i, chunk in enumerate(code_chunks, start=0):
witness_check.add_code_chunk(address=caller_address, chunk_number=i, value=chunk)
code_chunks = chunkify_code(pre[target].code)
if target != precompile_address and target != system_contract_address:
for i, chunk in enumerate(code_chunks, start=0):
witness_check.add_code_chunk(address=target, chunk_number=i, value=chunk)

blocks = [
Block(
Expand Down Expand Up @@ -213,7 +214,6 @@ def _generic_call(
)


# TODO(verkle): update to Osaka when t8n supports the fork.
@pytest.mark.valid_from("Verkle")
@pytest.mark.parametrize(
"call_instruction, gas_limit, enough_gas_account_creation",
Expand All @@ -231,7 +231,7 @@ def test_call_non_existent_account(
enough_gas_account_creation: bool,
):
"""
Test *CALL witness assertion when there's insufficient gas for different scenarios.
Test *CALL witness assertion when target account does not exist.
"""
env = Environment(
fee_recipient="0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
Expand Down Expand Up @@ -260,14 +260,16 @@ def test_call_non_existent_account(
gas_price=10,
)

witness_check = WitnessCheck()
witness_check = WitnessCheck(fork=Verkle)
for address in [TestAddress, caller_address, env.fee_recipient]:
witness_check.add_account_full(
address=address,
account=(None if address == env.fee_recipient else pre[address]),
)
witness_check.add_account_full(address=address, account=pre.get(address))

code_chunks = chunkify_code(pre[caller_address].code)
for i, chunk in enumerate(code_chunks, start=0):
witness_check.add_code_chunk(address=caller_address, chunk_number=i, value=chunk)

if enough_gas_account_creation:
witness_check.add_account_basic_data(address=TestAddress2, account=None)
witness_check.add_account_full(address=TestAddress2, account=None)

blocks = [
Block(
Expand All @@ -278,11 +280,7 @@ def test_call_non_existent_account(

post: Alloc = Alloc()
if enough_gas_account_creation:
post = Alloc(
{
TestAddress2: Account(balance=call_value),
}
)
post = Alloc({TestAddress2: Account(balance=call_value)})

blockchain_test(
genesis_environment=env,
Expand Down
Loading

0 comments on commit cfa073f

Please sign in to comment.