Skip to content

Commit

Permalink
Update EIP-6493: Cleanups for latest StableContainer specs
Browse files Browse the repository at this point in the history
Merged by EIP-Bot.
  • Loading branch information
etan-status authored Jun 12, 2024
1 parent a763aff commit ec89dd6
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 84 deletions.
76 changes: 37 additions & 39 deletions EIPS/eip-6493.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ class TransactionPayload(StableContainer[MAX_TRANSACTION_PAYLOAD_FIELDS]):
gas: Optional[uint64]
to: Optional[ExecutionAddress]
value: Optional[uint256]
input_: ByteList[MAX_CALLDATA_SIZE]
input_: Optional[ByteList[MAX_CALLDATA_SIZE]]

# EIP-2930
access_list: Optional[List[AccessTuple, MAX_ACCESS_LIST_SIZE]]
Expand Down Expand Up @@ -147,6 +147,10 @@ class BlobFeesPerGas(Profile[FeesPerGas]):
regular: FeePerGas
blob: FeePerGas

class EcdsaTransactionSignature(Profile[TransactionSignature]):
from_: Optional[ExecutionAddress]
ecdsa_signature: Optional[ByteVector[ECDSA_SIGNATURE_SIZE]]

class ReplayableTransactionPayload(Profile[TransactionPayload]):
type_: TransactionType
nonce: uint64
Expand All @@ -158,7 +162,7 @@ class ReplayableTransactionPayload(Profile[TransactionPayload]):

class ReplayableTransaction(Container):
payload: ReplayableTransactionPayload
signature: TransactionSignature
signature: EcdsaTransactionSignature

class LegacyTransactionPayload(Profile[TransactionPayload]):
type_: TransactionType
Expand All @@ -172,7 +176,7 @@ class LegacyTransactionPayload(Profile[TransactionPayload]):

class LegacyTransaction(Container):
payload: LegacyTransactionPayload
signature: TransactionSignature
signature: EcdsaTransactionSignature

class Eip2930TransactionPayload(Profile[TransactionPayload]):
type_: TransactionType
Expand All @@ -187,7 +191,7 @@ class Eip2930TransactionPayload(Profile[TransactionPayload]):

class Eip2930Transaction(Container):
payload: Eip2930TransactionPayload
signature: TransactionSignature
signature: EcdsaTransactionSignature

class Eip1559TransactionPayload(Profile[TransactionPayload]):
type_: TransactionType
Expand All @@ -203,7 +207,7 @@ class Eip1559TransactionPayload(Profile[TransactionPayload]):

class Eip1559Transaction(Container):
payload: Eip1559TransactionPayload
signature: TransactionSignature
signature: EcdsaTransactionSignature

class Eip4844TransactionPayload(Profile[TransactionPayload]):
type_: TransactionType
Expand All @@ -220,7 +224,7 @@ class Eip4844TransactionPayload(Profile[TransactionPayload]):

class Eip4844Transaction(Container):
payload: Eip4844TransactionPayload
signature: TransactionSignature
signature: EcdsaTransactionSignature

class BasicTransactionPayload(Profile[TransactionPayload]):
chain_id: ChainId
Expand All @@ -235,7 +239,7 @@ class BasicTransactionPayload(Profile[TransactionPayload]):

class BasicTransaction(Container):
payload: BasicTransactionPayload
signature: TransactionSignature
signature: EcdsaTransactionSignature

class BlobTransactionPayload(Profile[TransactionPayload]):
chain_id: ChainId
Expand All @@ -251,36 +255,33 @@ class BlobTransactionPayload(Profile[TransactionPayload]):

class BlobTransaction(Container):
payload: BlobTransactionPayload
signature: TransactionSignature
signature: EcdsaTransactionSignature

class AnyTransaction(OneOf[Transaction]):
@classmethod
def select_from_base(cls, value: Transaction) -> Type[Transaction]:
if value.payload.type_ is None:
if value.payload.blob_versioned_hashes is not None:
return BlobTransaction
return BasicTransaction
def select_transaction_profile(cls, value: Transaction) -> Type[Profile]:
if value.payload.type_ is None:
if value.payload.blob_versioned_hashes is not None:
return BlobTransaction
return BasicTransaction

if value.payload.type_ == TRANSACTION_TYPE_EIP4844:
return Eip4844Transaction
if value.payload.type_ == TRANSACTION_TYPE_EIP4844:
return Eip4844Transaction

if value.payload.type_ == TRANSACTION_TYPE_EIP1559:
return Eip1559Transaction
if value.payload.type_ == TRANSACTION_TYPE_EIP1559:
return Eip1559Transaction

if value.payload.type_ == TRANSACTION_TYPE_EIP2930:
return Eip2930Transaction
if value.payload.type_ == TRANSACTION_TYPE_EIP2930:
return Eip2930Transaction

if value.payload.chain_id is not None:
return LegacyTransaction
if value.payload.chain_id is not None:
return LegacyTransaction

return ReplayableTransaction
return ReplayableTransaction
```

Future specifications MAY:

- Append fields to `TransactionPayload` and `TransactionSignature`
- Convert existing fields to `Optional`
- Define new `Profile` types and update `select_from_base` logic
- Adjust `Profile` types and update `select_transaction_profile` logic

Such changes [do not affect](./eip-7495.md) how existing transactions serialize or merkleize.

Expand Down Expand Up @@ -344,7 +345,7 @@ def ecdsa_recover_from_address(signature: ByteVector[ECDSA_SIGNATURE_SIZE],
uncompressed = public_key.serialize(compressed=False)
return ExecutionAddress(keccak(uncompressed[1:])[12:])

def validate_transaction(tx: AnyTransaction):
def validate_transaction(tx):
ecdsa_validate_signature(tx.signature.ecdsa_signature)
assert tx.signature.from_ == ecdsa_recover_from_address(
tx.signature.ecdsa_signature,
Expand Down Expand Up @@ -401,10 +402,10 @@ class Log(Container):

class Receipt(StableContainer[MAX_RECEIPT_FIELDS]):
root: Optional[Hash32]
gas_used: uint64
gas_used: Optional[uint64]
contract_address: Optional[ExecutionAddress]
logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM]
logs: List[Log, MAX_LOGS_PER_RECEIPT]
logs_bloom: Optional[ByteVector[BYTES_PER_LOGS_BLOOM]]
logs: Optional[List[Log, MAX_LOGS_PER_RECEIPT]]

# EIP-658
status: Optional[boolean]
Expand All @@ -427,20 +428,17 @@ class BasicReceipt(Profile[Receipt]):
logs: List[Log, MAX_LOGS_PER_RECEIPT]
status: boolean

class AnyReceipt(OneOf[Receipt]):
@classmethod
def select_from_base(cls, value: Receipt) -> Type[Receipt]:
if value.status is not None:
return BasicReceipt
def select_receipt_profile(value: Receipt) -> Type[Profile]:
if value.status is not None:
return BasicReceipt

return HomesteadReceipt
return HomesteadReceipt
```

Future specifications MAY:

- Add fields to the end of `Receipt`
- Convert existing fields to `Optional`
- Define new `Profile` types and update `select_from_base` logic
- Adjust `Profile` types and update `select_receipt_profile` logic

Such changes [do not affect](./eip-7495.md) how existing receipts serialize or merkleize.

Expand Down Expand Up @@ -539,7 +537,7 @@ If other SSZ objects are being signed in the future, e.g., messages, it must be

### What about EIP-2718 transaction types?

All SSZ transactions (including future ones) share the single [EIP-2718](./eip-2718.md) transaction type `TRANSACTION_TYPE_SSZ`. Future features can introduce new optional fields as well as new allowed combination of optional fields, as determined by `select_from_base` in `AnyTransaction`.
All SSZ transactions (including future ones) share the single [EIP-2718](./eip-2718.md) transaction type `TRANSACTION_TYPE_SSZ`. Future features can introduce new optional fields as well as new allowed combination of optional fields, as determined by `select_transaction_profile`.

This also reduces combinatorial explosion; for example, the `access_list` property could be made optional for all SSZ transactions without having to double the number of defined transaction types.

Expand Down
16 changes: 8 additions & 8 deletions assets/eip-6493/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from rlp_types import *
from ssz_types import *

def upgrade_rlp_transaction_to_ssz(pre_bytes: bytes) -> AnyTransaction:
def upgrade_rlp_transaction_to_ssz(pre_bytes: bytes):
type_ = pre_bytes[0]

if type_ == 0x03: # EIP-4844
Expand Down Expand Up @@ -39,7 +39,7 @@ def upgrade_rlp_transaction_to_ssz(pre_bytes: bytes) -> AnyTransaction:
),
blob_versioned_hashes=pre.blob_versioned_hashes,
),
signature=TransactionSignature(
signature=EcdsaTransactionSignature(
from_=from_,
ecdsa_signature=ecdsa_signature,
),
Expand Down Expand Up @@ -75,7 +75,7 @@ def upgrade_rlp_transaction_to_ssz(pre_bytes: bytes) -> AnyTransaction:
regular=pre.max_priority_fee_per_gas,
),
),
signature=TransactionSignature(
signature=EcdsaTransactionSignature(
from_=from_,
ecdsa_signature=ecdsa_signature,
),
Expand Down Expand Up @@ -108,7 +108,7 @@ def upgrade_rlp_transaction_to_ssz(pre_bytes: bytes) -> AnyTransaction:
storage_keys=access_tuple[1]
) for access_tuple in pre.accessList],
),
signature=TransactionSignature(
signature=EcdsaTransactionSignature(
from_=from_,
ecdsa_signature=ecdsa_signature,
),
Expand Down Expand Up @@ -138,7 +138,7 @@ def upgrade_rlp_transaction_to_ssz(pre_bytes: bytes) -> AnyTransaction:
value=pre.value,
input_=pre.data,
),
signature=TransactionSignature(
signature=EcdsaTransactionSignature(
from_=from_,
ecdsa_signature=ecdsa_signature,
),
Expand All @@ -156,7 +156,7 @@ def upgrade_rlp_transaction_to_ssz(pre_bytes: bytes) -> AnyTransaction:
value=pre.value,
input_=pre.data,
),
signature=TransactionSignature(
signature=EcdsaTransactionSignature(
from_=from_,
ecdsa_signature=ecdsa_signature,
),
Expand All @@ -179,7 +179,7 @@ def compute_contract_address(from_: ExecutionAddress,

def upgrade_rlp_receipt_to_ssz(pre_bytes: bytes,
prev_cumulative_gas_used: uint64,
transaction: AnyTransaction) -> AnyReceipt:
transaction):
type_ = pre_bytes[0]

if type_ in (0x03, 0x02, 0x01): # EIP-4844, EIP-1559, EIP-2930
Expand Down Expand Up @@ -224,7 +224,7 @@ def upgrade_rlp_receipt_to_ssz(pre_bytes: bytes,
)

def upgrade_rlp_receipts_to_ssz(pre_bytes_list: PyList[bytes],
transactions: PyList[AnyTransaction]) -> PyList[AnyReceipt]:
transactions: PyList) -> PyList:
receipts = []
cumulative_gas_used = 0
for i, pre_bytes in enumerate(pre_bytes_list):
Expand Down
16 changes: 16 additions & 0 deletions assets/eip-6493/convert_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,19 @@ class Test:

stable_receipt = Receipt(backing=receipts[i].get_backing())
assert stable_receipt.encode_bytes() == tests[i].ssz_receipt_bytes

transactions_stable = [Transaction(backing=transaction.get_backing()) for transaction in transactions]
assert select_transaction_profile(transactions_stable[0]) is ReplayableTransaction
assert select_transaction_profile(transactions_stable[1]) is ReplayableTransaction
assert select_transaction_profile(transactions_stable[2]) is LegacyTransaction
assert select_transaction_profile(transactions_stable[3]) is Eip2930Transaction
assert select_transaction_profile(transactions_stable[4]) is Eip1559Transaction
assert select_transaction_profile(transactions_stable[5]) is Eip1559Transaction

receipts_stable = [Receipt(backing=receipt.get_backing()) for receipt in receipts]
assert select_receipt_profile(receipts_stable[0]) is HomesteadReceipt
assert select_receipt_profile(receipts_stable[1]) is BasicReceipt
assert select_receipt_profile(receipts_stable[2]) is BasicReceipt
assert select_receipt_profile(receipts_stable[3]) is BasicReceipt
assert select_receipt_profile(receipts_stable[4]) is BasicReceipt
assert select_receipt_profile(receipts_stable[5]) is BasicReceipt
Loading

0 comments on commit ec89dd6

Please sign in to comment.