Skip to content

Commit 858af44

Browse files
committed
✨ feat: zkevm - nom nom nom
1 parent ad4e4e9 commit 858af44

2 files changed

Lines changed: 54 additions & 55 deletions

File tree

tests/zkevm/__init__.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
1-
"""
2-
abstract: Tests for zkVMs
3-
"""
1+
"""Tests for zkEVM."""

tests/zkevm/test_proof_size.py

Lines changed: 53 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,21 @@
55
Large proofs are created by deploying contracts with
66
maximum allowed bytecode.
77
8-
These proofs are then "ingested" by an opcode or precompile.
9-
10-
First, the tests compute the "ingestion cost" for the proof.
11-
Next, they attempt to ingest the maximum possible number of
12-
proofs in a block with a given gas limit.
8+
Then, a pacman contract consumes (ᗧ•••) the maximum possible number of
9+
proofs in a block with a given gas limit using an opcode or precompile.
1310
"""
1411

15-
from typing import List
12+
from dataclasses import dataclass
13+
from typing import Callable
1614

1715
import pytest
1816

19-
from ethereum_test_forks import Fork
2017
from ethereum_test_tools import (
2118
Address,
2219
Alloc,
2320
Block,
2421
BlockchainTestFiller,
22+
Bytecode,
2523
Environment,
2624
Transaction,
2725
)
@@ -30,41 +28,54 @@
3028
REFERENCE_SPEC_GIT_PATH = "TODO"
3129
REFERENCE_SPEC_VERSION = "TODO"
3230

33-
3431
##############################
3532
# #
3633
# Config #
3734
# #
3835
##############################
39-
GAS_LIMITS = [
40-
30_000_000,
41-
]
42-
KiB = 1024
43-
CONTRACT_BYTECODE_MAX_SIZE = 24 * KiB
44-
45-
46-
##############################
47-
# #
48-
# Test Helpers #
49-
# #
50-
##############################
51-
def get_proofs(pre: Alloc, proof_count: int) -> List[Address]:
52-
"""
53-
Generate a list of proof addresses by deploying contracts
54-
with maximum allowed bytecode size.
55-
"""
56-
proofs = []
57-
for i in range(proof_count):
58-
code = Op.JUMPDEST * (CONTRACT_BYTECODE_MAX_SIZE - 1 - 10) + Op.PUSH10(i)
59-
proofs.append(pre.deploy_contract(code=code))
60-
return proofs
61-
62-
63-
def get_proof_eater(pre: Alloc, proof_count: int) -> Address:
64-
"""Generate a proof eater contract that ingests a given proofs."""
65-
proofs = get_proofs(pre, proof_count)
66-
code = sum([Op.EXTCODESIZE(proofs[i]) for i in range(proof_count)])
67-
return pre.deploy_contract(code=code)
36+
CONTRACT_BYTECODE_MAX_SIZE = 24 * 1024 # 24 KiB
37+
GAS_LIMITS = [30_000_000, 60_000_000, 100_000_000, 300_000_000]
38+
39+
40+
@dataclass
41+
class OpcodeConfig:
42+
"""Configuration for an opcode's proof eating behavior."""
43+
44+
gas_cost: int
45+
generate_bytecode: Callable[[Address], Bytecode]
46+
47+
def create_pacman(self, pre: Alloc, gas_limit: int) -> Address:
48+
"""
49+
Generate a pacman contract that ingests proofs using this opcode.
50+
ᗧ••• nom nom nom.
51+
"""
52+
proof_count = (gas_limit - 21_000) // self.gas_cost
53+
proof_count = 5 # TODO: REMOVE THIS LIMIT
54+
55+
# Generate proofs
56+
proofs = [
57+
pre.deploy_contract(
58+
code=Op.JUMPDEST * (CONTRACT_BYTECODE_MAX_SIZE - 11) + Op.PUSH10(i)
59+
)
60+
for i in range(proof_count)
61+
]
62+
63+
# Generate bytecode using the opcode's configuration
64+
code = sum(self.generate_bytecode(proof) for proof in proofs)
65+
return pre.deploy_contract(code=code)
66+
67+
68+
# Map opcodes to their configurations
69+
OPCODE_CONFIGS = {
70+
Op.EXTCODEHASH: OpcodeConfig(
71+
gas_cost=2603, # PUSH20[3] + EXTCODEHASH[2600]
72+
generate_bytecode=lambda addr: Op.EXTCODEHASH(addr),
73+
),
74+
Op.EXTCODESIZE: OpcodeConfig(
75+
gas_cost=2603, # PUSH20[3] + EXTCODESIZE[2600]
76+
generate_bytecode=lambda addr: Op.EXTCODESIZE(addr),
77+
),
78+
}
6879

6980

7081
##############################
@@ -75,28 +86,18 @@ def get_proof_eater(pre: Alloc, proof_count: int) -> Address:
7586
@pytest.mark.zkevm
7687
@pytest.mark.valid_from("Cancun")
7788
@pytest.mark.parametrize("gas_limit", GAS_LIMITS)
78-
@pytest.mark.parametrize(
79-
"num_called_contracts",
80-
[
81-
1,
82-
# 10,
83-
# MAX_NUM_CONTRACT_CALLS
84-
],
85-
)
89+
@pytest.mark.parametrize("opcode", OPCODE_CONFIGS.keys(), ids=str)
8690
def test_via_opcode(
8791
blockchain_test: BlockchainTestFiller,
8892
pre: Alloc,
89-
fork: Fork,
9093
gas_limit: int,
91-
num_called_contracts: int,
94+
opcode: Op,
9295
):
9396
"""Test zkEVM proof size limits using a specific opcode."""
94-
env = Environment(gas_limit=gas_limit)
95-
96-
# MAX_NUM_CONTRACT_CALLS = (gas_limit - 21_000) // (3 + 2600)
97+
config = OPCODE_CONFIGS[opcode]
9798

9899
tx = Transaction(
99-
to=get_proof_eater(pre, num_called_contracts),
100+
to=config.create_pacman(pre, gas_limit),
100101
gas_limit=gas_limit,
101102
gas_price=10,
102103
sender=pre.fund_eoa(),
@@ -105,7 +106,7 @@ def test_via_opcode(
105106
)
106107

107108
blockchain_test(
108-
env=env,
109+
env=Environment(gas_limit=gas_limit),
109110
pre=pre,
110111
post={},
111112
blocks=[Block(txs=[tx])],

0 commit comments

Comments
 (0)