Hi, I'm a bot! This change was automatically merged because: - It only modifies existing Draft or Last Call EIP(s) - The PR was approved or written by at least one author of each modified EIP - The build is passing
8.7 KiB
eip | title | author | discussions-to | status | type | category | created | requires |
---|---|---|---|---|---|---|---|---|
2718 | Typed Transaction Envelope | Micah Zoltu (@MicahZoltu) | https://ethereum-magicians.org/t/eip-2718-typed-transaction-envelope/4355 | Draft | Standards Track | Core | 2020-06-13 | 155 |
Simple Summary
Defines a new transaction type that is an envelope for future transaction types.
Abstract
[TransactionType, ...Payload]
will become a valid transaction and [TransactionType, ...Payload]
will become a valid transaction receipt identifying the format of the transaction and Payload
is the transaction/receipt contents, whose definition is defined in future EIPs.
The first new transaction type will be a wrapped legacy transactions with the format leb128(6, nonce, gasPrice, gasLimit, to, value, v, r, s, ...data)
.
The first new receipt will be a wrapped legacy receipt with the format leb128(6, status, cumulativeGasUsed, logsBloom, ...logs)
.
Motivation
In the past, when we have wanted to add new transaction types we have had to ensure they were backward compatible with all other transactions, meaning that you could differentiate them based only on the encoded payload, and it was not possible to have a transaction that matched both types.
This was seen in EIP-155 where the new value was bit-packed into one of the encoded fields.
There are multiple proposals in discussion that define new transaction types such as one that allows EOA accounts to execute code directly within their context, one that enables someone besides msg.sender
to pay for gas, and proposals related to layer 0 multi-sig transactions.
These all need to be defined in a way that is mutually compatible, which quickly becomes burdensome to EIP authors and to clients who now have to follow complex rules for differentiating transaction type.
By introducing an envolope transaction type, we only need to ensure backward compatibility with existing transactions and from then on we just need to solve the much simpler problem of ensuring there is no numbering conflict between TransactionType
s.
Specification
Definitions
...
is the spread operator and []
represents an array, as seen in JavaScript.
When you see [byteVariable, ...byteArrayVariable]
it means you'll end up with a byte array whose first byte is byteVariable
followed by the bytes of byteArrayVariable
.
For example: [3, ...[5, 7, 11, 13]] => [3, 5, 7, 11, 13]
.
Transactions
As of FORK_BLOCK_NUMBER
, rlp([nonce, gasPrice, gasLimit, to, value, data, v, r, s])
(legacy transaction) will no longer be a valid Ethereum transaction over the devp2p protocol or in a block.
As of FORK_BLOCK_NUMBER
, all transactions sent over devp2p or included in a block MUST be of the form [TransactionType, ...Payload]
where TransactionType
is a positive unsigned number between 0
and 0x7f
(see Security Considerations for type 9) that represents the type of the transcation and Payload
is an opaque byte array whose interpretation is dependent on the TransactionType
.
Transactions SHOULD include the TransactionType
as the first byte in any signatures they include to minimize the chance of unintentional replay attacks between different transaction types.
The transaction hash of all transactions MUST be keccak256(TransactionType, ...Payload)
As of FORK_BLOCK_NUMBER
, leb128(6, nonce, gasPrice, gasLimit, to, value, v, r, s, ...data)
will be a valid transaction where the transaction will be signed/processed/handled exactly the same as legacy transactions were signed/processed/handled with the exception of the final encoding of the signed transaction.
Receipts
As of FORK_BLOCK_NUMBER
, rlp([status, cumulativeGasUsed, logsBloom, logs])
(legacy receipt) will no longer be a valid Ethereum transaction receipt over the devp2p protocol or as part of a block.
As of FORK_BLOCK_NUMBER
, all receipts sent over devp2p or included in a block MUST be of the form [TransactionType, ...Payload]
where TransactionType
is a number between 0
and 0x7f
that represents the type of the transaction and Payload
is an opaque byte array whose interpretation is dependent on the TransactionType
.
As of FORK_BLOCK_NUMBER
, leb128(6, status, cumulativeGasUsed, logsBloom, logs)
will be a valid receipt where the receipt will be processed/handled exactly the same as legacy receipts were processed/handled with the exception of its encoding.
Fork Block Transition
Between FORK_BLOCK_NUMBER - 1
and FORK_BLOCK_NUMBER
clients SHOULD convert all transactions in their local pending pool into type 6 transactions.
Clients MAY choose to flush their pending pool instead, if it is not possible to do the wrapping in time for the next block, though this is discouraged.
As of FORK_BLOCK_NUMBER
, clients SHOULD accept incoming transactions over user/application facing APIs such as JSON-RPC in both the new wrapped format and the legacy format.
If a legacy format transaction is received, the client MUST wrap it in a type 6 envelope before sending it over devp2p or including it in a block.
As of FORK_BLOCK_NUMBER
, clients SHOULD return type 6 receipts over user/application facing APIs such as JSON-RPC in the legacy format.
Clients SHOULD devise a long term strategy for deprecating the legacy format over APIs in favor of the typed receipt envelope format.
Rationale
Not including the type in type 6 signatures
While this EIP recommends that the envelope be included in any signatures, it also specifies that for Transaction Type 6 the envelope is not included in the signature. This EIP disobayes its own recommendation because we don't want all signing tools to break on the fork block and require updates to start working again.
First transaction type is type 6 instead of 0
Prior to EIP-155, the first byte of the signed payload for a transaction was 0x06
.
We MUST ensure that a signed legacy transaction cannot be interpreted as a type 6 transaction.
Since enveloped legacy transactions don't include the type in the signature, we can avoid having to worry about that problem.
TransactionType selection algorithm
There was discussion about defining the TransactionType
identifier assignment/selection algorithm in this standard.
While it would be nice to have a standardized mechanism for assignment, at the time of writing of this standard there is not a strong need for it so it was deemed out of scope.
A future EIP may introduce a standard for TransactionType identifier assignment if it is deemed necessary.
Opaque byte array rather than an RLP array
By having the second byte on be opaque bytes, rather than an RLP (or other encoding) list, we can support different encoding formats for the transaction payload in the future, such as SSZ, LEB128, or a fixed width format.
ORIGIN and CALLER
There was discussion about having ORIGIN and CALLER opcodes be dependent on the transaction type, so that each transaction type could define what those opcodes returned.
However, there is a desire to make transaction type opaque to the contracts to discourage contracts treating different different types of transactions differently and there also were concerns over backward compatibility with existing contracts which make assumptions about ORIGIN and CALLER opcodes.
Going forward, we will assume that all transaction types will have an address that reasonably represents a CALLER
of the first EVM frame and ORIGIN
will be the same address in all cases.
If a transaction type needs to supply additional information to contracts, they will need a new opcode.
Hashing the outer transaction
If you submit a transaction prior to the fork block and it is mined after the fork block, the transaction hash of the mined transaction will not match the the transaction hash of the transaction you originally submitted. This is because the mined transaction will be a wrapped one, while the submitted transaction will be unwrapped. Applications that use the transaction hash to lookup the transaction result will fail to ever find it or see it ever mined. Clients can optionally choose to track type 6 transactions internally by both hashes for a period of time so that lookups of the old hash won't fail for the user, but this is not required for consensus.
Backwards Compatibility
Clients can differentiate between the legacy transactions and typed transactions by TBD.
Test Cases
TBD
Implementation
TBD
Security Considerations
Post EIP-155 transactions were encoded (prior to signing) such that the first byte would be a 9
.
This means that transaction type 9
MUST take great care in ensuring that a signed legacy transaction is not also a valid signed type 9
transaction.
Copyright
Copyright and related rights waived via CC0.