Skip to content

feat: block witness checks and test fixes #857

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
a0bbc35
basic witness checks
spencer-tb Aug 22, 2024
d297732
feat(fw): add verkle chunkify code helper.
spencer-tb Aug 26, 2024
0f1ef24
feat(fw): add all verkle sub commands.
spencer-tb Aug 26, 2024
b20c457
chore: add chunkify code to init.
spencer-tb Aug 26, 2024
59d3403
chore: remove witness.
spencer-tb Aug 26, 2024
99532e8
chore: remove old witness check.
spencer-tb Aug 26, 2024
31b202a
feat(fw): add witness checks init api.
spencer-tb Aug 26, 2024
4234dff
chore: fix filling tmp.
spencer-tb Aug 26, 2024
5ff6b98
refactor(fw|evm): use WitnessCheck as temp data struct pre-filling.
spencer-tb Aug 27, 2024
441e2a2
chore(fw|evm): fix witness check during fill.
spencer-tb Aug 27, 2024
4616579
feat(fw): verify witness function.
spencer-tb Aug 30, 2024
de4586f
tests: witness check test_balance.
spencer-tb Aug 30, 2024
b057561
tests: update witness check test_blockhash_instruction.
spencer-tb Aug 30, 2024
e99b1de
tests: update witness check for remaining tests.
spencer-tb Aug 30, 2024
16ef1a9
chore: rename basic mpt to vkt test as transition.
spencer-tb Aug 30, 2024
c7c4387
tests: temp fix test_contract_execution.
spencer-tb Sep 3, 2024
079e8de
chore: fix format witness check function.
spencer-tb Sep 3, 2024
2f7d116
feat: add basic data values big-endian encoding.
spencer-tb Sep 4, 2024
1d567a2
chore: improve and fix error messages.
spencer-tb Sep 4, 2024
ff22863
chore: more improvements to error messages.
spencer-tb Sep 4, 2024
9461df2
chore: fix code hash for witness check.
spencer-tb Sep 4, 2024
9b508b1
chore: more improvements to error messages 2.
spencer-tb Sep 4, 2024
641801a
chore: more improvements to error messages 3.
spencer-tb Sep 4, 2024
9f4302c
chore: temp test fix.
spencer-tb Sep 4, 2024
028ea8a
chore: skip blockhash storage slot check temp.
spencer-tb Sep 4, 2024
79b61a8
chore: fix eip4762 test calls.
spencer-tb Sep 4, 2024
f858ec6
tests: small changes.
spencer-tb Sep 4, 2024
42a60df
verkle: fix test
jsign Sep 5, 2024
4f48425
verkle: test fix
jsign Sep 5, 2024
8ab7393
verkle: fix selfdestruct tests
jsign Sep 5, 2024
0e65ebe
verkle: fix sstore
jsign Sep 5, 2024
2007dc1
verkle: fix extcodesize test
jsign Sep 5, 2024
7e16825
verkle: fix extcodehash tests
jsign Sep 5, 2024
ce226bd
verkle: contract execution fixes
jsign Sep 6, 2024
8750f95
fixes
jsign Sep 6, 2024
c6613f7
verkle: many contract execution fixes
jsign Sep 9, 2024
3347b58
verkle: fix more tests bugs
jsign Sep 9, 2024
b8f4950
verkle: fix create tests
jsign Sep 9, 2024
d5656df
verkle: add create with insufficient balance value-bearing
jsign Sep 9, 2024
3ea183c
verkle: create with big calldata fixes
jsign Sep 9, 2024
cc982bd
verkle: fix sload test
jsign Sep 9, 2024
98ac1a4
verkle: uncomment contract execution subtests
jsign Sep 9, 2024
d55ce57
chore: typing bytes fix.
spencer-tb Sep 9, 2024
928ed2a
verkle: more fixes
jsign Sep 10, 2024
aa5cda3
verkle: enable all code execution tests
jsign Sep 10, 2024
aba15a6
feat: make witness checks exhaustive.
spencer-tb Sep 10, 2024
be90705
fix: bug in code chunk.
spencer-tb Sep 10, 2024
72fa6ef
feat: test_balance exhaustive checks example.
spencer-tb Sep 10, 2024
4bc9b7f
temp-fix: check hist. storage cont.
spencer-tb Sep 10, 2024
6c04643
compilation fixes
jsign Sep 10, 2024
820f66d
more fixes
jsign Sep 10, 2024
bc144d8
verkle: fixes
jsign Sep 10, 2024
9c56c4a
verkle: call warm fixes
jsign Sep 10, 2024
fd637be
verkle: fixes
jsign Sep 11, 2024
129251d
fixes
jsign Sep 11, 2024
ac10705
simplify
jsign Sep 11, 2024
94620c9
verkle: fixes
jsign Sep 11, 2024
5089d6a
verkle: codecopy/extcodecopy fixes
jsign Sep 11, 2024
3754d51
verkle: remove noisy comments
jsign Sep 11, 2024
148845b
verkle: fix coinbase assertions
jsign Sep 11, 2024
eab6961
verkle: fixes
jsign Sep 11, 2024
656a4c6
verkle: fix creates tests
jsign Sep 11, 2024
38accf2
verkle: fixes
jsign Sep 11, 2024
17400d8
verkle: extcodesize fixes
jsign Sep 11, 2024
d58e1eb
verkle: selfdestruct fixes
jsign Sep 11, 2024
cfc623e
verkle: fix sload
jsign Sep 11, 2024
617a9af
verkle: sstore fixes
jsign Sep 11, 2024
d444e43
verkle: fix transfer
jsign Sep 11, 2024
0730d9f
verkle: more calls fixes
jsign Sep 12, 2024
340683e
verkle: more fixes
jsign Sep 12, 2024
eb7a9e6
verkle: more fixes
jsign Sep 12, 2024
0fcff0d
verkle: more fixes
jsign Sep 12, 2024
cfa073f
Merge pull request #52 from jsign/jsign/exhaustive-fixes
jsign Sep 12, 2024
3abe304
disable temporarily 7709 tests
jsign Sep 13, 2024
aa1c8ae
verkle: reenable sub-test
jsign Sep 20, 2024
d0e104e
verkle: enable sub-tests with partial witness charging
jsign Sep 20, 2024
7ea89a9
verkle: reenable call subtests
jsign Sep 20, 2024
ce31c99
verkle: add eip-7709 test
jsign Sep 24, 2024
07475f7
verkle: 7709 fixes
jsign Sep 24, 2024
c2e9d9c
verkle: update 7709 blockhash values
jsign Sep 25, 2024
ce684e1
fixes
jsign Sep 25, 2024
9edf6ea
fixes
jsign Sep 25, 2024
35c79c8
fixes
jsign Sep 25, 2024
5694e15
Merge pull request #53 from jsign/jsign-7709
jsign Sep 25, 2024
12010a5
verkle: add codecopy test with size bigger than contract
jsign Sep 26, 2024
86cb3ee
verkle: add system contract execution test via CALL
jsign Oct 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions src/ethereum_test_base_types/base_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,18 +181,20 @@ class Sized(cls): # type: ignore

return Sized

def __new__(cls, input: NumberConvertible | N):
def __new__(cls, input: NumberConvertible | N | None):
"""
Creates a new Number object.
"""
i = to_number(input)
if i > cls.max_value:
raise ValueError(f"Value {i} is too large for {cls.byte_length} bytes")
if i < 0:
i += cls.max_value + 1
if i <= 0:
raise ValueError(f"Value {i} is too small for {cls.byte_length} bytes")
return super(FixedSizeHexNumber, cls).__new__(cls, i)
if input is not None:
i = to_number(input)
if i > cls.max_value:
raise ValueError(f"Value {i} is too large for {cls.byte_length} bytes")
if i < 0:
i += cls.max_value + 1
if i <= 0:
raise ValueError(f"Value {i} is too small for {cls.byte_length} bytes")
return super(FixedSizeHexNumber, cls).__new__(cls, i)
return None

def __str__(self) -> str:
"""
Expand Down
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
142 changes: 130 additions & 12 deletions src/ethereum_test_specs/blockchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Ethereum blockchain test spec definition and filler.
"""

from pprint import pprint
from pprint import pformat
from typing import Any, Callable, ClassVar, Dict, Generator, List, Optional, Tuple, Type

from pydantic import ConfigDict, Field, field_validator
Expand Down Expand Up @@ -48,7 +48,7 @@
Withdrawal,
WithdrawalRequest,
)
from ethereum_test_types.verkle import VerkleTree, Witness
from ethereum_test_types.verkle import StateDiff, VerkleTree, Witness, WitnessCheck
from evm_transition_tool import TransitionTool

from .base import BaseTest, verify_result, verify_transactions
Expand Down Expand Up @@ -258,6 +258,10 @@ class Block(Header):
"""
Custom list of requests to embed in this block.
"""
witness_check: WitnessCheck | None = None
"""
Verkle execution witness check for the block.
"""

def set_environment(self, env: Environment) -> Environment:
"""
Expand Down Expand Up @@ -452,20 +456,52 @@ def generate_block_data(
debug_output_path=self.get_next_transition_tool_output_path(),
)

try:
try: # General checks for the transition tool output
rejected_txs = verify_transactions(txs, transition_tool_output.result)
verify_result(transition_tool_output.result, env)
# TODO: add verify witness (against vkt)
# verify_witness(transition_tool_output.witness, transition_tool_output.vkt)
if block.witness_check:
if transition_tool_output.result.state_diff is None:
raise Exception(
"no state diff in transition tool output, cannot verify witness"
)
# TODO: hack for now, temp addition to check hist. storage contract
block.witness_check.add_storage_slot(
address=Address(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE),
storage_slot=env.number - 1,
# value=env.parent_hash,
value=None,
)
self.verify_witness(
t8n=t8n,
state_diff=transition_tool_output.result.state_diff,
witness_check=block.witness_check,
)
except Exception as e:
print_traces(t8n.get_traces())
pprint(transition_tool_output.result)
pprint(previous_alloc)
pprint(transition_tool_output.alloc)
print(
"\nTransition tool output result:\n"
f"{pformat(transition_tool_output.result.model_dump_json())}"
)
print(
"\nPrevious transition tool alloc:\n"
f"{pformat(previous_alloc.model_dump_json())}"
)
if transition_tool_output.alloc is not None:
print(
"\nTransition tool output alloc:\n"
f"{pformat(transition_tool_output.alloc.model_dump_json())}"
)
if transition_tool_output.vkt is not None:
pprint(transition_tool_output.vkt)
if transition_tool_output.witness is not None:
pprint(transition_tool_output.witness)
print(
"\nTransition tools output verkle tree:\n"
f"{pformat(transition_tool_output.vkt.model_dump_json())}"
)
# TODO: t8n has the witness state diff from the result for now
# if transition_tool_output.witness is not None:
# print(
# "\nTransition tools output witness:\n"
# f"{pformat(transition_tool_output.witness.model_dump_json())}"
# )
raise e

if len(rejected_txs) > 0 and block.exception is None:
Expand Down Expand Up @@ -538,7 +574,7 @@ def generate_block_data(
)
)
transition_tool_output.alloc = previous_alloc
# TODO: hack for now
# TODO: hack for now, replace with actual witness output once available from t8n
transition_tool_output.witness = Witness(
verkle_proof=transition_tool_output.result.verkle_proof,
state_diff=transition_tool_output.result.state_diff,
Expand Down Expand Up @@ -587,6 +623,87 @@ def verify_post_state(
print_traces(t8n.get_traces())
raise e

def verify_witness(
self,
t8n: TransitionTool,
state_diff: StateDiff,
witness_check: WitnessCheck,
) -> None:
"""
Compares the expected witness check allocation account against the values updated
in the block execution witness state diff.
"""
witness_check_state_diff, witness_check_address_mapping = t8n.get_witness_check_mapping(
witness_check
)
print("\nExpected witness check state diff:")
print(witness_check_state_diff.model_dump_json(indent=4))

for stem_state_diff in state_diff.root:
actual_stem = stem_state_diff.stem
address = witness_check_address_mapping.get(actual_stem, None)
print(f"\nChecking witness for stem: {actual_stem} at address: {address}")
# check for stem in the expected witness check
expected_stem_state_diff = next(
(sd for sd in witness_check_state_diff.root if sd.stem == actual_stem), None
)
if not expected_stem_state_diff:
raise ValueError(
"Witness check failed - missing stem not found in expected witness check.\n\n"
+ pformat(
{
"test_account_address": str(address),
"stem": str(actual_stem),
},
indent=4,
)
)
for suffix_diff in stem_state_diff.suffix_diffs:
actual_suffix = suffix_diff.suffix
actual_current_value = suffix_diff.current_value
# check for suffix in the expected witness check
expected_suffix_state_diff = next(
(
sd
for sd in expected_stem_state_diff.suffix_diffs
if sd.suffix == actual_suffix
),
None,
)
if not expected_suffix_state_diff:
raise ValueError(
"Witness check failed - actual suffix not found in expected witness"
" check.\n\n"
+ pformat(
{
"test_account_address": str(address),
"stem": str(actual_stem),
"suffix": actual_suffix,
"value_actual": str(actual_current_value),
"value_expected": "value not found",
},
indent=4,
)
)
# check the current value of the actual suffix state diff matches the expected
if str(actual_current_value) != str(
expected_suffix_state_diff.current_value
): # TODO: temp fix str casting
raise ValueError(
"Witness check failed - current value mismatch. The stem and suffix"
" exist.\n\n"
+ pformat(
{
"test_account_address": str(address),
"stem": str(actual_stem),
"suffix": actual_suffix,
"value_actual": str(actual_current_value),
"value_expected": str(expected_suffix_state_diff.current_value),
},
indent=4,
)
)

def make_fixture(
self,
t8n: TransitionTool,
Expand Down Expand Up @@ -841,4 +958,5 @@ def generate(


BlockchainTestSpec = Callable[[str], Generator[BlockchainTest, None, None]]

BlockchainTestFiller = Type[BlockchainTest]
6 changes: 6 additions & 0 deletions src/ethereum_test_tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,11 @@
Storage,
TestParameterGroup,
Transaction,
VerkleTree,
Withdrawal,
WithdrawalRequest,
Witness,
WitnessCheck,
add_kzg_version,
ceiling_division,
compute_create2_address,
Expand Down Expand Up @@ -136,6 +139,9 @@
"TestPrivateKey2",
"Transaction",
"TransactionException",
"VerkleTree",
"Witness",
"WitnessCheck",
"Withdrawal",
"WithdrawalRequest",
"Yul",
Expand Down
4 changes: 4 additions & 0 deletions src/ethereum_test_types/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
Withdrawal,
WithdrawalRequest,
)
from .verkle import VerkleTree, Witness, WitnessCheck

__all__ = (
"AccessList",
Expand All @@ -53,8 +54,11 @@
"TestPrivateKey",
"TestPrivateKey2",
"Transaction",
"VerkleTree",
"Withdrawal",
"WithdrawalRequest",
"Witness",
"WitnessCheck",
"ZeroPaddedHexNumber",
"add_kzg_version",
"ceiling_division",
Expand Down
17 changes: 16 additions & 1 deletion src/ethereum_test_types/verkle/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,28 @@
Ethereum Verkle Test Types.
"""

from .types import IpaProof, StateDiff, SuffixStateDiff, VerkleProof, VerkleTree, Witness
from .helpers import chunkify_code
from .types import (
IpaProof,
StateDiff,
Stem,
StemStateDiff,
SuffixStateDiff,
VerkleProof,
VerkleTree,
Witness,
WitnessCheck,
)

__all__ = (
"IpaProof",
"StateDiff",
"StemStateDiff",
"SuffixStateDiff",
"Stem",
"VerkleProof",
"VerkleTree",
"Witness",
"WitnessCheck",
"chunkify_code",
)
Loading
Loading