Skip to content

Commit

Permalink
fillers/eips/eip4844: Add Blob commitment version kzg to blob version…
Browse files Browse the repository at this point in the history
…ed hashes. (#126)

* fillers/eips/eip4844: Add Kzg Version to Blob Hashes.

* fillers/eips/eip4844: Add invalid blob test case for no kzg version in blobs.

* fillers/eips/eip4844: Refactor and fix incorrect kzg versioning.

* src/eth_test_tools/common/helpers: Update kzg version function to not use str.
  • Loading branch information
spencer-tb authored May 17, 2023
1 parent 7c2da98 commit a44609b
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 26 deletions.
42 changes: 29 additions & 13 deletions fillers/eips/eip4844/datahash_opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
TestAddress,
Transaction,
Yul,
add_kzg_version,
compute_create2_address,
compute_create_address,
test_from,
Expand All @@ -28,6 +29,7 @@
REFERENCE_SPEC_GIT_PATH = "EIPS/eip-4844.md"
REFERENCE_SPEC_VERSION = "ac003985b9be74ff48bd897770e6d5f2e4318715"

BLOB_COMMITMENT_VERSION_KZG = 1
DATAHASH_GAS_COST = 3
MAX_BLOB_PER_BLOCK = 4
BLOB_HASHES = [
Expand Down Expand Up @@ -199,9 +201,10 @@ def test_datahash_opcode_contexts(_: Fork):
initcode_datahash_sstore_bytecode.assemble(),
)

b_hashes: Sequence[bytes] = [
to_hash_bytes(1 << x) for x in range(MAX_BLOB_PER_BLOCK)
]
b_hashes: Sequence[bytes] = add_kzg_version(
[(1 << x) for x in range(MAX_BLOB_PER_BLOCK)],
BLOB_COMMITMENT_VERSION_KZG,
)

tags = [
"at_top_level_call_stack",
Expand Down Expand Up @@ -485,7 +488,7 @@ def test_datahash_gas_cost(_: Fork):
to=address,
nonce=i,
max_priority_fee_per_gas=10,
blob_versioned_hashes=[BLOB_HASHES[i % MAX_BLOB_PER_BLOCK]],
access_list=[],
)
)
txs_type_3.append(
Expand All @@ -494,7 +497,10 @@ def test_datahash_gas_cost(_: Fork):
to=address,
nonce=i,
max_priority_fee_per_gas=10,
blob_versioned_hashes=[BLOB_HASHES[i % MAX_BLOB_PER_BLOCK]],
blob_versioned_hashes=add_kzg_version(
[BLOB_HASHES[i % MAX_BLOB_PER_BLOCK]],
BLOB_COMMITMENT_VERSION_KZG,
),
)
)
post[address] = Account(storage={0: DATAHASH_GAS_COST})
Expand Down Expand Up @@ -537,11 +543,14 @@ def test_datahash_blob_versioned_hash(_: Fork):

# Create an arbitrary repeated list of blob hashes
# with length MAX_BLOB_PER_BLOCK * TOTAL_BLOCKS
b_hashes = list(
itertools.islice(
itertools.cycle(BLOB_HASHES),
MAX_BLOB_PER_BLOCK * TOTAL_BLOCKS,
)
b_hashes = add_kzg_version(
list(
itertools.islice(
itertools.cycle(BLOB_HASHES),
MAX_BLOB_PER_BLOCK * TOTAL_BLOCKS,
)
),
BLOB_COMMITMENT_VERSION_KZG,
)

# `DATAHASH` sstore template helper
Expand Down Expand Up @@ -678,7 +687,10 @@ def test_datahash_invalid_blob_index(_: Fork):
address = to_address(0x100 + i * 0x100)
pre[address] = Account(code=datahash_invalid_calls)
blob_per_block = (i % MAX_BLOB_PER_BLOCK) + 1
blob_hashes = [BLOB_HASHES[blob] for blob in range(blob_per_block)]
blob_hashes = add_kzg_version(
[BLOB_HASHES[blob] for blob in range(blob_per_block)],
BLOB_COMMITMENT_VERSION_KZG,
)
blocks.append(
Block(
txs=[
Expand Down Expand Up @@ -735,14 +747,18 @@ def test_datahash_multiple_txs_in_block(_: Fork):
}
pre[TestAddress] = Account(balance=10000000000000000000000)

b_hashes = add_kzg_version(
BLOB_HASHES[0:MAX_BLOB_PER_BLOCK], BLOB_COMMITMENT_VERSION_KZG
)

tx = Transaction(
data=to_hash_bytes(0),
gas_limit=3000000,
max_fee_per_gas=10,
max_priority_fee_per_gas=10,
max_fee_per_data_gas=10,
access_list=[],
blob_versioned_hashes=BLOB_HASHES[0:MAX_BLOB_PER_BLOCK],
blob_versioned_hashes=b_hashes,
)

blocks = [
Expand All @@ -768,7 +784,7 @@ def test_datahash_multiple_txs_in_block(_: Fork):

post = {
to_address(address): Account(
storage={i: BLOB_HASHES[i] for i in range(MAX_BLOB_PER_BLOCK)}
storage={i: b_hashes[i] for i in range(MAX_BLOB_PER_BLOCK)}
)
if address in (0x200, 0x400)
else Account(storage={i: 0 for i in range(MAX_BLOB_PER_BLOCK)})
Expand Down
51 changes: 38 additions & 13 deletions fillers/eips/eip4844/excess_data_gas.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
Header,
TestAddress,
Transaction,
add_kzg_version,
test_from,
test_only,
to_address,
Expand All @@ -29,6 +30,7 @@
REFERENCE_SPEC_GIT_PATH = "EIPS/eip-4844.md"
REFERENCE_SPEC_VERSION = "ac003985b9be74ff48bd897770e6d5f2e4318715"

BLOB_COMMITMENT_VERSION_KZG = 1
DATAHASH_GAS_COST = 3
MIN_DATA_GASPRICE = 1
DATA_GAS_PER_BLOB = 2**17
Expand Down Expand Up @@ -155,9 +157,10 @@ def generate(self) -> BlockchainTest:
max_priority_fee_per_gas=0,
max_fee_per_data_gas=data_gasprice,
access_list=[],
blob_versioned_hashes=[
to_hash_bytes(x) for x in range(self.blobs)
],
blob_versioned_hashes=add_kzg_version(
[to_hash_bytes(x) for x in range(self.blobs)],
BLOB_COMMITMENT_VERSION_KZG,
),
)
else:
tx = Transaction(
Expand Down Expand Up @@ -374,9 +377,10 @@ def generate(self) -> BlockchainTest:
excess_data_gas=parent_excess_data_gas
),
access_list=[],
blob_versioned_hashes=[
to_hash_bytes(x) for x in range(self.new_blobs)
],
blob_versioned_hashes=add_kzg_version(
[to_hash_bytes(x) for x in range(self.new_blobs)],
BLOB_COMMITMENT_VERSION_KZG,
),
)

return BlockchainTest(
Expand Down Expand Up @@ -603,10 +607,13 @@ def test_fork_transition_excess_data_gas_in_header(_: Fork):
excess_data_gas=parent_excess_data_gas
),
access_list=[],
blob_versioned_hashes=[
to_hash_bytes(x)
for x in range(MAX_BLOBS_PER_BLOCK)
],
blob_versioned_hashes=add_kzg_version(
[
to_hash_bytes(x)
for x in range(MAX_BLOBS_PER_BLOCK)
],
BLOB_COMMITMENT_VERSION_KZG,
),
)
],
)
Expand Down Expand Up @@ -647,6 +654,7 @@ class InvalidBlobTransactionTestCase:
tx_count: int = 1
parent_excess_blobs: Optional[int] = None
tx_max_data_gas_cost: Optional[int] = None
total_kzg_versioning: int = MAX_BLOBS_PER_BLOCK
account_balance_modifier: int = 0
block_base_fee: int = 7

Expand Down Expand Up @@ -681,6 +689,13 @@ def generate(self) -> BlockchainTest:
else data_gasprice
)

b_hashes = [to_hash_bytes(x) for x in range(self.blobs_per_tx)]
if self.total_kzg_versioning > 0:
b_hashes[0 : self.total_kzg_versioning] = add_kzg_version(
b_hashes[0 : self.total_kzg_versioning],
BLOB_COMMITMENT_VERSION_KZG,
)

txs: List[Transaction] = []
for tx_i in range(self.tx_count):
tx = Transaction(
Expand All @@ -693,9 +708,7 @@ def generate(self) -> BlockchainTest:
max_priority_fee_per_gas=0,
max_fee_per_data_gas=max_fee_per_data_gas,
access_list=[],
blob_versioned_hashes=[
to_hash_bytes(x) for x in range(self.blobs_per_tx)
],
blob_versioned_hashes=b_hashes,
error=self.tx_error if tx_i == (self.tx_count - 1) else None,
)
txs.append(tx)
Expand Down Expand Up @@ -778,6 +791,18 @@ def test_invalid_blob_txs(fork: Fork):
tx_error="too_few_blobs",
blobs_per_tx=0,
),
InvalidBlobTransactionTestCase(
tag="no_kzg_versioning",
tx_error="all_blob_hashes_unversioned",
blobs_per_tx=MAX_BLOBS_PER_BLOCK,
total_kzg_versioning=0,
),
InvalidBlobTransactionTestCase(
tag="partial_kzg_versioning",
tx_error="some_blob_hashes_unversioned",
blobs_per_tx=MAX_BLOBS_PER_BLOCK,
total_kzg_versioning=2,
),
]
else:
# Pre-Cancun, blocks with type 3 txs must be rejected
Expand Down
2 changes: 2 additions & 0 deletions src/ethereum_test_tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
TestAddress,
Transaction,
Withdrawal,
add_kzg_version,
ceiling_division,
compute_create2_address,
compute_create_address,
Expand Down Expand Up @@ -52,6 +53,7 @@
"Transaction",
"Withdrawal",
"Yul",
"add_kzg_version",
"ceiling_division",
"compute_create_address",
"compute_create2_address",
Expand Down
2 changes: 2 additions & 0 deletions src/ethereum_test_tools/common/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
TestPrivateKey,
)
from .helpers import (
add_kzg_version,
ceiling_division,
compute_create2_address,
compute_create_address,
Expand Down Expand Up @@ -59,6 +60,7 @@
"TestPrivateKey",
"Transaction",
"Withdrawal",
"add_kzg_version",
"alloc_to_accounts",
"ceiling_division",
"compute_create_address",
Expand Down
21 changes: 21 additions & 0 deletions src/ethereum_test_tools/common/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,24 @@ def to_hash(input: int | str) -> str:
Converts an int or str into proper 32-byte hash hex string.
"""
return "0x" + to_hash_bytes(input).hex()


def add_kzg_version(b_hashes, kzg_version):
"""
Adds the Kzg Version to each blob hash.
"""
kzg_version_hex = bytes([kzg_version])
kzg_versioned_hashes = []

for hash in b_hashes:
if isinstance(hash, int) or isinstance(hash, str):
kzg_versioned_hashes.append(
kzg_version_hex + to_hash_bytes(hash)[1:]
)
elif isinstance(hash, bytes):
kzg_versioned_hashes.append(kzg_version_hex + hash[1:])
else:
raise TypeError(
"Blob hash must be either an integer, string or bytes"
)
return kzg_versioned_hashes

0 comments on commit a44609b

Please sign in to comment.