Appearance
Abstract
This EIP defines a signature scheme for native Simple Serialize (SSZ) encoded transactions.
Motivation
EIP-6404 introduces SSZ transactions by converting from RLP transactions. Defining a signature scheme for native SSZ transactions further reduces required conversions and unlocks the forward compatibility benefits of SSZ ProgressiveContainer.
Specification
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.
Transaction signature scheme
Native SSZ transactions are based on the TransactionPayload defined in EIP-6404 and emit an EIP-6466 Receipt. To distinguish native SSZ transactions from those converted from RLP, native SSZ transactions do not contain the RLP TransactionType field in their TransactionPayload.
All native SSZ transactions follow a scheme based on hash_tree_root to compute their signing hash (sig_hash). Likewise, native SSZ authorizations use such a scheme to derive their signing hash (auth_hash).
Additional information is mixed into sig_hash and auth_hash to uniquely identify the underlying specification and avoid hash collisions across different signature kinds. Vendor-defined networks MUST use a different DomainType for signing custom transaction or authorization types.
| Name | Value | Description |
|---|---|---|
DOMAIN_TX_SSZ | DomainType('0x01000008') | DomainType for signing native SSZ transactions compatible with this EIP |
DOMAIN_AUTH_SSZ | DomainType('0x02000008') | DomainType for signing native SSZ authorizations compatible with this EIP |
python
class ExecutionSigningData(Container):
object_root: Root
domain_type: DomainType
def compute_ssz_sig_hash(payload: SszTransactionPayload) -> Hash32:
return Hash32(ExecutionSigningData(
object_root=payload.hash_tree_root(),
domain_type=DOMAIN_TX_SSZ,
).hash_tree_root())
def compute_ssz_auth_hash(payload: SszAuthorizationPayload) -> Hash32:
return Hash32(ExecutionSigningData(
object_root=payload.hash_tree_root(),
domain_type=DOMAIN_AUTH_SSZ,
).hash_tree_root())Native transactions
New EIP-6404 TransactionPayload definitions are introduced to represent native SSZ transactions:
BasicTransactionPayloadandCreateTransactionPayloadshare the functionality of EIP-1559 fee market transactionsBlobTransactionPayloadshares the functionality of EIP-4844 blob transactionsSetCodeTransactionPayloadshares the functionality of EIP-7702 set code transactions; native SSZ types are introduced for authorizations
python
class BasicTransactionPayload(
ProgressiveContainer(active_fields=[0, 1, 1, 1, 1, 1, 1, 1, 1, 1])
):
chain_id: ChainId
nonce: uint64
max_fees_per_gas: BasicFeesPerGas
gas: GasAmount
to: ExecutionAddress
value: uint256
input_: ProgressiveByteList
access_list: ProgressiveList[AccessTuple]
max_priority_fees_per_gas: BasicFeesPerGas
class CreateTransactionPayload(
ProgressiveContainer(active_fields=[0, 1, 1, 1, 1, 0, 1, 1, 1, 1])
):
chain_id: ChainId
nonce: uint64
max_fees_per_gas: BasicFeesPerGas
gas: GasAmount
value: uint256
input_: ProgressiveByteList
access_list: ProgressiveList[AccessTuple]
max_priority_fees_per_gas: BasicFeesPerGas
class BlobTransactionPayload(
ProgressiveContainer(active_fields=[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
):
chain_id: ChainId
nonce: uint64
max_fees_per_gas: BlobFeesPerGas
gas: GasAmount
to: ExecutionAddress
value: uint256
input_: ProgressiveByteList
access_list: ProgressiveList[AccessTuple]
max_priority_fees_per_gas: BasicFeesPerGas
blob_versioned_hashes: ProgressiveList[VersionedHash]
class ReplayableBasicAuthorizationPayload(ProgressiveContainer(active_fields=[0, 0, 1, 1])):
address: ExecutionAddress
nonce: uint64
class BasicAuthorizationPayload(ProgressiveContainer(active_fields=[0, 1, 1, 1])):
chain_id: ChainId
address: ExecutionAddress
nonce: uint64
class SetCodeAuthorizationPayload(CompatibleUnion({
0x01: RlpReplayableBasicAuthorizationPayload,
0x02: RlpBasicAuthorizationPayload,
# [New in EIP-6493]
0x11: ReplayableBasicAuthorizationPayload,
0x12: BasicAuthorizationPayload,
})):
pass
class SetCodeAuthorization(Container):
payload: SetCodeAuthorizationPayload
signature: ExecutionSignature
class SetCodeTransactionPayload(
ProgressiveContainer(active_fields=[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1])
):
chain_id: ChainId
nonce: uint64
max_fees_per_gas: BasicFeesPerGas
gas: GasAmount
to: ExecutionAddress
value: uint256
input_: ProgressiveByteList
access_list: ProgressiveList[AccessTuple]
max_priority_fees_per_gas: BasicFeesPerGas
authorization_list: ProgressiveList[SetCodeAuthorization]
SszTransactionPayload = (
BasicTransactionPayload |
CreateTransactionPayload |
BlobTransactionPayload |
SetCodeTransactionPayload
)
SszAuthorizationPayload = (
ReplayableBasicAuthorizationPayload |
BasicAuthorizationPayload
)Transaction helpers
The helpers from EIP-6404 are updated to support native SSZ transactions.
python
class TransactionPayload(CompatibleUnion({
0x01: RlpLegacyReplayableBasicTransactionPayload,
0x02: RlpLegacyReplayableCreateTransactionPayload,
0x03: RlpLegacyBasicTransactionPayload,
0x04: RlpLegacyCreateTransactionPayload,
0x05: RlpAccessListBasicTransactionPayload,
0x06: RlpAccessListCreateTransactionPayload,
0x07: RlpBasicTransactionPayload,
0x08: RlpCreateTransactionPayload,
0x09: RlpBlobTransactionPayload,
0x0a: RlpSetCodeTransactionPayload,
# [New in EIP-6493]
0x11: BasicTransactionPayload,
0x12: CreateTransactionPayload,
0x13: BlobTransactionPayload,
0x14: SetCodeTransactionPayload,
})):
passJSON-RPC
| Name | Value | Description |
|---|---|---|
SSZ_TX_TYPE | TransactionType(0x1f) | Endpoint specific SSZ object |
Certain JSON-RPC endpoints such as eth_getTransactionByHash indicate the corresponding EIP-2718 envelope type prefix in a type field.
When representing native SSZ transactions on such endpoints, SSZ_TX_TYPE SHOULD be indicated as their type. Omitting the type is NOT RECOMMENDED as certain client applications could confuse the omission with untyped LegacyTransaction.
Unique transaction identifier
The unique RPC transaction identifier tx_hash for native SSZ transactions is defined to match the EIP-6404 tx_root value.
Rationale
The SSZ signature scheme reduces hashing overhead and ensures that tx_hash commitments are available on-chain. It also provides a flexible basis for future transaction functionality.
Backwards Compatibility
The new transaction signature scheme is solely used for native SSZ transactions and is representable using a unique EIP-2718 envelope type prefix (SSZ_TX_TYPE) different from existing RLP transactions.
Security Considerations
SSZ signatures MUST NOT collide with RLP transaction and message hashes.
As RLP messages are hashed using keccak256, and all SSZ objects are hashed using SHA256. These two hashing algorithms are both considered cryptographically secure and are based on fundamentally different approaches, minimizing the risk of hash collision between those two hashing algorithms.
Furthermore, RLP messages are hashed linearly across their serialization, while SSZ objects are hashed using a recursive Merkle tree. Having a different mechanism further reduces the risk of hash collisions.
Copyright
Copyright and related rights waived via CC0.