EIP-6404: SSZ Transactions

Thanks for the PR! Appreciate the feedback.

Regarding the blob priority fee: The idea is indeed to integrate the EIP-7706 multidimensional fee concept into the SSZ package (EIP-7919 for full scope), so that the fee profiles can be extended for future fee types, rather than having tons of different fee fields like in RLP.

The RlpBlobTransactionPayload is converted from the RLP transaction and imported as having a 0 blob prio fee, and there is a check to only allow 0 initially. That makes the handling of various kinds of fees the same, and future-proofs for additional fees such as calldata fees.

See discussion in EIP-7706:


As for the ChainID change for EIP-7702:

In RLP, 0 is used as a special value for chain-agnostic authorizations. With SSZ, it becomes possible to express the concept of not being locked to a specific chain ID explicitly. RLP authorizations with chain ID 0 would convert to a RlpSetCodeAuthorizationPayload without a chain ID.

Ah ok gotcha!

For the gas, it currently says this:
if (tx.payload.max_priority_fees_per_gas or FeesPerGas()).blob != 0: (if this is true then this is an error). I understand that FeesPerGas() then creates a new FeesPerGas container/object? With all values thus “optional”? Would these then default to 0? (Or is Optional a ‘special’ value?)

For the 7702 stuff, a RLP 0 would thus yield “undefined” in the SSZ version of it? I’m somewhat new to SSZ and I guess this is a gotcha. Is it “by default” we convert zeros to nothing and not to a zero value?

tx.payload.max_priority_fees_per_gas could be None, so dereferencing tx.payload.max_priority_fees_per_gas.blob would result in an error (as it becomes None.blob).

So, (tx.payload.max_priority_fees_per_gas or FeesPerGas()) just means you always have some FeesPerGas instance that you can access the blob property from.

FeesPerGas() creates a new object with everything set to None (not 0).

RlpBlobTransaction is expected to contain an explicit 0 for the blob priority fee, at this time, meaning any value besides 0 (including None) gets rejected. Note RlpBlobTransaction is originally created by converting an actual RLP blob transaction into SSZ. As part of that conversion, the 0 value is set.

1 Like
  • Adopt latest EIP-7495: no optionals / profiles / field capacities
  • Adopt EIP-7916 ProgressiveList: no capacities
  • Update engine API to be based on ssz.serialize
  • Drop networking changes, such efforts can be adopted separately
  • Adopt EIP-7916 ProgressiveByteList for signatures: Makes it simpler to add more algorithms without changing transaction types
  • Fix EIP-7702 SetCode transaction: The definition for authorizations was incomplete
  • Update test vectors for latest specs
  • Move union layer into the payload, so that signature lives outside
  • Refactor validate_transaction to check RLP type and auth list separately
  • Define tx_root

In the current draft compute_sig_hash is not defined. Is it the root hash of the TransactionPayload for all but Legacy types, and for those it’s the RLP? Or is it all the RLP forms of the transactions? or TralsactionPayload hash for all cases?

The compute_sig_hash has to match the historical one, one has to recover the exact data that was originally signed. There’s an assets folder in the EIP: EIPs/assets/eip-6404 at master · ethereum/EIPs · GitHub

If we are re-stating historical transactions yes, but what about future transactions or TXes not in the inital set of types? Probably the cleanest way would be for the pre-ssz types it’s the RLP signature form and post-SSZ types (possibly with a new combo-type) it is the root hash of the type data.

native SSZ tx is eip-6493