Fix blob transaction serialization to use RLP

EIP-4844 uses RLP not SSZ for blob transactions.
This commit is contained in:
Etan Kissling 2024-08-28 12:46:53 +02:00
parent 423bb4d0eb
commit d61f95e138
No known key found for this signature in database
GPG Key ID: B21DA824C5A3D03D
11 changed files with 75 additions and 94 deletions

View File

@ -10,8 +10,8 @@ from eth2spec.test.context import (
expect_assertion_error,
with_deneb_and_later
)
from eth2spec.test.helpers.sharding import (
get_sample_opaque_tx,
from eth2spec.test.helpers.blob import (
get_sample_blob_tx,
)
@ -74,7 +74,7 @@ def test_incorrect_blob_tx_type(spec, state):
"""
execution_payload = build_empty_execution_payload(spec, state)
opaque_tx, _, blob_kzg_commitments, _ = get_sample_opaque_tx(spec)
opaque_tx, _, blob_kzg_commitments, _ = get_sample_blob_tx(spec)
opaque_tx = b'\x04' + opaque_tx[1:] # incorrect tx type
execution_payload.transactions = [opaque_tx]
@ -91,7 +91,7 @@ def test_incorrect_transaction_length_1_extra_byte(spec, state):
"""
execution_payload = build_empty_execution_payload(spec, state)
opaque_tx, _, blob_kzg_commitments, _ = get_sample_opaque_tx(spec)
opaque_tx, _, blob_kzg_commitments, _ = get_sample_blob_tx(spec)
opaque_tx = opaque_tx + b'\x12' # incorrect tx length, longer
execution_payload.transactions = [opaque_tx]
@ -108,7 +108,7 @@ def test_incorrect_transaction_length_1_byte_short(spec, state):
"""
execution_payload = build_empty_execution_payload(spec, state)
opaque_tx, _, blob_kzg_commitments, _ = get_sample_opaque_tx(spec)
opaque_tx, _, blob_kzg_commitments, _ = get_sample_blob_tx(spec)
opaque_tx = opaque_tx[:-1] # incorrect tx length, shorter
execution_payload.transactions = [opaque_tx]
@ -125,7 +125,7 @@ def test_incorrect_transaction_length_empty(spec, state):
"""
execution_payload = build_empty_execution_payload(spec, state)
opaque_tx, _, blob_kzg_commitments, _ = get_sample_opaque_tx(spec)
opaque_tx, _, blob_kzg_commitments, _ = get_sample_blob_tx(spec)
opaque_tx = opaque_tx[0:0] # incorrect tx length, empty
execution_payload.transactions = [opaque_tx]
@ -142,7 +142,7 @@ def test_incorrect_transaction_length_32_extra_bytes(spec, state):
"""
execution_payload = build_empty_execution_payload(spec, state)
opaque_tx, _, blob_kzg_commitments, _ = get_sample_opaque_tx(spec)
opaque_tx, _, blob_kzg_commitments, _ = get_sample_blob_tx(spec)
opaque_tx = opaque_tx + b'\x12' * 32 # incorrect tx length
execution_payload.transactions = [opaque_tx]
@ -159,7 +159,7 @@ def test_no_transactions_with_commitments(spec, state):
"""
execution_payload = build_empty_execution_payload(spec, state)
_, _, blob_kzg_commitments, _ = get_sample_opaque_tx(spec)
_, _, blob_kzg_commitments, _ = get_sample_blob_tx(spec)
execution_payload.transactions = []
execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state)
@ -175,7 +175,7 @@ def test_incorrect_commitment(spec, state):
"""
execution_payload = build_empty_execution_payload(spec, state)
opaque_tx, _, blob_kzg_commitments, _ = get_sample_opaque_tx(spec)
opaque_tx, _, blob_kzg_commitments, _ = get_sample_blob_tx(spec)
blob_kzg_commitments[0] = b'\x12' * 48 # incorrect commitment
execution_payload.transactions = [opaque_tx]
@ -192,7 +192,7 @@ def test_incorrect_commitments_order(spec, state):
"""
execution_payload = build_empty_execution_payload(spec, state)
opaque_tx, _, blob_kzg_commitments, _ = get_sample_opaque_tx(spec, blob_count=2, rng=Random(1111))
opaque_tx, _, blob_kzg_commitments, _ = get_sample_blob_tx(spec, blob_count=2, rng=Random(1111))
blob_kzg_commitments = [blob_kzg_commitments[1], blob_kzg_commitments[0]] # incorrect order
execution_payload.transactions = [opaque_tx]
@ -206,7 +206,7 @@ def test_incorrect_commitments_order(spec, state):
def test_incorrect_block_hash(spec, state):
execution_payload = build_empty_execution_payload(spec, state)
opaque_tx, _, blob_kzg_commitments, _ = get_sample_opaque_tx(spec)
opaque_tx, _, blob_kzg_commitments, _ = get_sample_blob_tx(spec)
execution_payload.transactions = [opaque_tx]
execution_payload.block_hash = b'\x12' * 32 # incorrect block hash
@ -223,7 +223,7 @@ def test_zeroed_commitment(spec, state):
"""
execution_payload = build_empty_execution_payload(spec, state)
opaque_tx, _, blob_kzg_commitments, _ = get_sample_opaque_tx(spec, blob_count=1, is_valid_blob=False)
opaque_tx, _, blob_kzg_commitments, _ = get_sample_blob_tx(spec, blob_count=1, is_valid_blob=False)
assert all(commitment == b'\x00' * 48 for commitment in blob_kzg_commitments)
execution_payload.transactions = [opaque_tx]
@ -240,7 +240,7 @@ def test_invalid_correct_input__execution_invalid(spec, state):
"""
execution_payload = build_empty_execution_payload(spec, state)
opaque_tx, _, blob_kzg_commitments, _ = get_sample_opaque_tx(spec)
opaque_tx, _, blob_kzg_commitments, _ = get_sample_blob_tx(spec)
execution_payload.transactions = [opaque_tx]
execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state)
@ -254,7 +254,7 @@ def test_invalid_correct_input__execution_invalid(spec, state):
def test_invalid_exceed_max_blobs_per_block(spec, state):
execution_payload = build_empty_execution_payload(spec, state)
opaque_tx, _, blob_kzg_commitments, _ = get_sample_opaque_tx(spec, blob_count=spec.config.MAX_BLOBS_PER_BLOCK + 1)
opaque_tx, _, blob_kzg_commitments, _ = get_sample_blob_tx(spec, blob_count=spec.config.MAX_BLOBS_PER_BLOCK + 1)
execution_payload.transactions = [opaque_tx]
execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state)

View File

@ -25,14 +25,14 @@ from eth2spec.test.helpers.fork_choice import (
from eth2spec.test.helpers.state import (
state_transition_and_sign_block,
)
from eth2spec.test.helpers.sharding import (
get_sample_opaque_tx,
from eth2spec.test.helpers.blob import (
get_sample_blob_tx,
)
def get_block_with_blob(spec, state, rng=None):
block = build_empty_block_for_next_slot(spec, state)
opaque_tx, blobs, blob_kzg_commitments, blob_kzg_proofs = get_sample_opaque_tx(spec, blob_count=1, rng=rng)
opaque_tx, blobs, blob_kzg_commitments, blob_kzg_proofs = get_sample_blob_tx(spec, blob_count=1, rng=rng)
block.body.execution_payload.transactions = [opaque_tx]
block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state)
block.body.blob_kzg_commitments = blob_kzg_commitments

View File

@ -12,8 +12,8 @@ from eth2spec.test.helpers.block import (
from eth2spec.test.helpers.execution_payload import (
compute_el_block_hash,
)
from eth2spec.test.helpers.sharding import (
get_sample_opaque_tx,
from eth2spec.test.helpers.blob import (
get_sample_blob_tx,
)
from eth2spec.debug.random_value import (
RandomizationMode,
@ -22,7 +22,7 @@ from eth2spec.debug.random_value import (
def _run_blob_kzg_commitment_merkle_proof_test(spec, state, rng=None):
opaque_tx, blobs, blob_kzg_commitments, proofs = get_sample_opaque_tx(spec, blob_count=1)
opaque_tx, blobs, blob_kzg_commitments, proofs = get_sample_blob_tx(spec, blob_count=1)
if rng is None:
block = build_empty_block_for_next_slot(spec, state)
else:

View File

@ -14,8 +14,8 @@ from eth2spec.test.helpers.execution_payload import (
compute_el_block_hash,
get_random_tx,
)
from eth2spec.test.helpers.sharding import (
get_sample_opaque_tx,
from eth2spec.test.helpers.blob import (
get_sample_blob_tx,
)
@ -27,7 +27,7 @@ def run_block_with_blobs(spec, state, blob_count, tx_count=1, blob_gas_used=1, e
txs = []
blob_kzg_commitments = []
for _ in range(tx_count):
opaque_tx, _, commits, _ = get_sample_opaque_tx(spec, blob_count=blob_count)
opaque_tx, _, commits, _ = get_sample_blob_tx(spec, blob_count=blob_count)
txs.append(opaque_tx)
blob_kzg_commitments += commits

View File

@ -7,7 +7,7 @@ from eth2spec.test.context import (
expect_assertion_error,
always_bls
)
from eth2spec.test.helpers.sharding import (
from eth2spec.test.helpers.blob import (
get_sample_blob,
get_poly_in_both_forms,
eval_poly_in_coeff_form,

View File

@ -6,8 +6,8 @@ from eth2spec.test.context import (
from eth2spec.test.helpers.execution_payload import (
compute_el_block_hash,
)
from eth2spec.test.helpers.sharding import (
get_sample_opaque_tx,
from eth2spec.test.helpers.blob import (
get_sample_blob_tx,
)
from eth2spec.test.helpers.block import (
build_empty_block_for_next_slot,
@ -20,8 +20,8 @@ def _get_sample_sidecars(spec, state, rng):
# 2 txs, each has 2 blobs
blob_count = 2
opaque_tx_1, blobs_1, blob_kzg_commitments_1, proofs_1 = get_sample_opaque_tx(spec, blob_count=blob_count, rng=rng)
opaque_tx_2, blobs_2, blob_kzg_commitments_2, proofs_2 = get_sample_opaque_tx(spec, blob_count=blob_count, rng=rng)
opaque_tx_1, blobs_1, blob_kzg_commitments_1, proofs_1 = get_sample_blob_tx(spec, blob_count=blob_count, rng=rng)
opaque_tx_2, blobs_2, blob_kzg_commitments_2, proofs_2 = get_sample_blob_tx(spec, blob_count=blob_count, rng=rng)
assert opaque_tx_1 != opaque_tx_2
block.body.blob_kzg_commitments = blob_kzg_commitments_1 + blob_kzg_commitments_2

View File

@ -12,8 +12,8 @@ from eth2spec.test.helpers.block import (
from eth2spec.test.helpers.execution_payload import (
compute_el_block_hash,
)
from eth2spec.test.helpers.sharding import (
get_sample_opaque_tx,
from eth2spec.test.helpers.blob import (
get_sample_blob_tx,
)
from eth2spec.debug.random_value import (
RandomizationMode,
@ -22,7 +22,7 @@ from eth2spec.debug.random_value import (
def _run_blob_kzg_commitments_merkle_proof_test(spec, state, rng=None):
opaque_tx, blobs, blob_kzg_commitments, _ = get_sample_opaque_tx(spec, blob_count=1)
opaque_tx, blobs, blob_kzg_commitments, _ = get_sample_blob_tx(spec, blob_count=1)
if rng is None:
block = build_empty_block_for_next_slot(spec, state)
else:

View File

@ -6,7 +6,7 @@ from eth2spec.test.context import (
with_config_overrides,
with_eip7594_and_later,
)
from eth2spec.test.helpers.sharding import (
from eth2spec.test.helpers.blob import (
get_sample_blob,
)

View File

@ -5,7 +5,7 @@ from eth2spec.test.context import (
expect_assertion_error,
with_eip7594_and_later,
)
from eth2spec.test.helpers.sharding import (
from eth2spec.test.helpers.blob import (
get_sample_blob,
)
from eth2spec.utils.bls import BLS_MODULUS

View File

@ -1,57 +1,28 @@
import random
from eth2spec.utils.ssz.ssz_typing import (
Container,
Bytes20, Bytes32,
ByteList,
List,
Union,
boolean,
uint256, uint64,
uint8,
)
from eth2spec.utils.ssz.ssz_impl import serialize
from rlp import encode, Serializable
from rlp.sedes import Binary, CountableList, List as RLPList, big_endian_int, binary
#
# Containers from EIP-4844
#
MAX_CALLDATA_SIZE = 2**24
MAX_VERSIONED_HASHES_LIST_SIZE = 2**24
MAX_ACCESS_LIST_STORAGE_KEYS = 2**24
MAX_ACCESS_LIST_SIZE = 2**24
BLOB_TX_TYPE = uint8(0x03)
class AccessTuple(Container):
address: Bytes20 # Address = Bytes20
storage_keys: List[Bytes32, MAX_ACCESS_LIST_STORAGE_KEYS]
class ECDSASignature(Container):
y_parity: boolean
r: uint256
s: uint256
class BlobTransaction(Container):
chain_id: uint256
nonce: uint64
max_priority_fee_per_gas: uint256
max_fee_per_gas: uint256
gas: uint64
to: Union[None, Bytes20] # Address = Bytes20
value: uint256
data: ByteList[MAX_CALLDATA_SIZE]
access_list: List[AccessTuple, MAX_ACCESS_LIST_SIZE]
max_fee_per_blob_gas: uint256
blob_versioned_hashes: List[Bytes32, MAX_VERSIONED_HASHES_LIST_SIZE]
class SignedBlobTransaction(Container):
message: BlobTransaction
signature: ECDSASignature
class Eip4844RlpTransaction(Serializable):
fields = (
('chain_id', big_endian_int),
('nonce', big_endian_int),
('max_priority_fee_per_gas', big_endian_int),
('max_fee_per_gas', big_endian_int),
('gas_limit', big_endian_int),
('to', Binary(20, 20)),
('value', big_endian_int),
('data', binary),
('access_list', CountableList(RLPList([
Binary(20, 20),
CountableList(Binary(32, 32)),
]))),
('max_fee_per_blob_gas', big_endian_int),
('blob_versioned_hashes', CountableList(Binary(32, 32))),
('signature_y_parity', big_endian_int),
('signature_r', big_endian_int),
('signature_s', big_endian_int),
)
def get_sample_blob(spec, rng=random.Random(5566), is_valid_blob=True):
@ -99,7 +70,7 @@ def get_poly_in_both_forms(spec, rng=None):
return coeffs, evals
def get_sample_opaque_tx(spec, blob_count=1, rng=random.Random(5566), is_valid_blob=True):
def get_sample_blob_tx(spec, blob_count=1, rng=random.Random(5566), is_valid_blob=True):
blobs = []
blob_kzg_commitments = []
blob_kzg_proofs = []
@ -118,11 +89,21 @@ def get_sample_opaque_tx(spec, blob_count=1, rng=random.Random(5566), is_valid_b
blob_kzg_proofs.append(blob_kzg_proof)
blob_versioned_hashes.append(blob_versioned_hash)
signed_blob_tx = SignedBlobTransaction(
message=BlobTransaction(
blob_versioned_hashes=blob_versioned_hashes,
)
signed_blob_tx = Eip4844RlpTransaction(
chain_id=0,
nonce=0,
max_priority_fee_per_gas=0,
max_fee_per_gas=0,
gas_limit=0,
to=bytes.fromhex("0000000000000000000000000000000000000000"),
value=0,
data=bytes.fromhex(""),
access_list=[],
max_fee_per_blob_gas=0,
blob_versioned_hashes=[bytes(h) for h in blob_versioned_hashes],
signature_y_parity=0,
signature_r=0,
signature_s=0,
)
serialized_tx = serialize(signed_blob_tx)
opaque_tx = spec.uint_to_bytes(BLOB_TX_TYPE) + serialized_tx
opaque_tx = bytes([0x03]) + encode(signed_blob_tx)
return opaque_tx, blobs, blob_kzg_commitments, blob_kzg_proofs

View File

@ -24,8 +24,8 @@ from eth2spec.test.helpers.random import (
randomize_state as randomize_state_helper,
patch_state_to_non_leaking,
)
from eth2spec.test.helpers.sharding import (
get_sample_opaque_tx,
from eth2spec.test.helpers.blob import (
get_sample_blob_tx,
)
from eth2spec.test.helpers.state import (
next_slot,
@ -250,7 +250,7 @@ def random_block_capella(spec, state, signed_blocks, scenario_state, rng=Random(
def random_block_deneb(spec, state, signed_blocks, scenario_state, rng=Random(3456)):
block = random_block_capella(spec, state, signed_blocks, scenario_state, rng=rng)
# TODO: more commitments. blob_kzg_commitments: List[KZGCommitment, MAX_BLOBS_PER_BLOCK]
opaque_tx, _, blob_kzg_commitments, _ = get_sample_opaque_tx(
opaque_tx, _, blob_kzg_commitments, _ = get_sample_blob_tx(
spec, blob_count=rng.randint(0, spec.config.MAX_BLOBS_PER_BLOCK), rng=rng)
block.body.execution_payload.transactions.append(opaque_tx)
block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state)