Updated EIP-6404 with metrics, comparing to the union based approach.
Personal conclusion:
SSZ Union’s primary advantage is that inside the consensus ExecutionPayload
, it needs about ~50 bytes less compared to the normalized transaction. At the typical 200 transactions per block, that’s a difference of about ~10 KB per block.
Furthermore, engine_getPayload
/ engine_newPayload
don’t require conversion in case of the SSZ Union, for SSZ transactions. However, this API is used via JSON, so already goes through a double conversion process, and is sometimes used remotely. So the performance argument here is moot.
Finally, arguments can be made regarding a different design space for future transaction types. However, note that all transactions are also exposed via JSON-RPC, where they are represented in a normalized way. Therefore, any restrictions that a normalized transaction representation brings, already apply, even if the transactions are represented in an SSZ Union format.
The SSZ Union has some noteworthy flaws when representing non-SSZ transactions:
-
It is impossible to recover a non-SSZ transaction’s from
address without downloading the full transaction. In my tests, an incorrect value is recovered to simulate behaviour as if all transactions were SSZ.
-
It is also impossible to determine the address of a newly deployed contract for a non-SSZ transaction without downloading the full transaction, as that depends on the from
address.
-
The txid of a non-SSZ transaction is computed differently than it originally had. This means that a transaction-in-a-bottle with a precomputed txid can no longer be identified through that txid, and tooling needs to change.
-
Non-SSZ transaction restrictions also apply, if we ever want to change the hashing algorithm, to, say, Poseidon. The SSZ Union approach closely links the original transaction representation with the way how it is represented in the transactions_root
tree. If there is a Poseidon transaction, it has the same issue as RLP transactions if the tree stays SSZ. If the tree changes to Poseidon as well, all existing SSZ transactions will have the same problem.
Besides those flaws, the SSZ Union also is less friendly for consumption by light clients.
-
Most SSZ union proofs are bigger than their normalized transaction counterpart, despite the union including less information. The exception is a proof that simply looks up the index of a transaction inside a block by its original transaction hash, but that size benefit comes at a cost that the lookup simply doesn’t work for non-SSZ transactions.
-
The proof complexity is higher for SSZ union proofs, due to each transaction type needing a separate path in the logic and the basic information about the sender of a transaction requiring secp256k1 public key recovery. Adding new transaction types gradually raises verifier complexity. As for execution speed, they are mostly slower to verify, with the exception once more being the lookup of sequential index inside a block by original hash, which is incorrect for non-SSZ transactions in SSZ union case.
-
JSON-RPC lookups on execution clients might be slower with the SSZ Union, because the JSON-RPC API provides access to a transaction’s from
field, which in turn requires secp256k1 public key recovery. All required data to answer a JSON-RPC lookup is readily available in the normalized transaction format without any expensive computation.
Note that, once more, EIP-6404 is only about normalizing the transaction representation after inclusion into the consensus ExecutionPayload
.
For the mempool representation of transactions, they can continue to use whatever signature scheme, hashing method, combination of fields and blob specific network wrappers, as they currently do. EIP-6493 proposes a signature scheme that SSZ transactions should use as part of the mempool, that is both compatible with the SSZ Union as well as the normalized representation for EIP-6404.