Appearance
Abstract
Typed Transactions can be sent over devp2p as TransactionType || TransactionPayload
. The exact contents of the TransactionPayload
are defined by the TransactionType
in future EIPs, and clients may start supporting their gossip without incrementing the devp2p version. If a client receives a TransactionType
that it doesn't recognize, it SHOULD disconnect from the peer who sent it. Clients MUST NOT send new transaction types before they believe the fork block is reached.
Motivation
EIP-2718 introduced new transaction types for blocks (which presents itself in the makeup of a block header's transaction root and receipts root). However, without a mechanism for gossiping these transactions, no one can actually include them in a block. By updating devp2p to support the gossip of Typed Transactions, we can benefit from these new transaction types.
Note: See EIP-2718 for additional motivations of Typed Transactions.
Specification
All changes specified below apply to all protocol/versions retroactively.
Definitions
||
is the byte/byte-array concatenation operator.|
is the type union operator.DEVP2P_VERSION = TBD
Transaction
is eitherTypedTransaction
orLegacyTransaction
TypedTransaction
is a byte array containingTransactionType || TransactionPayload
TypedTransactionHash
iskeccak256(TypedTransaction)
TransactionType
is a positive unsigned 8-bit number between0
and0x7f
that represents the type of the transcationTransactionPayload
is an opaque byte array whose interpretation is dependent on theTransactionType
and defined in future EIPsLegacyTransaction
is an array of the form[nonce, gasPrice, gasLimit, to, value, data, v, r, s]
LegacyTransactionHash
iskeccak256(rlp(LegacyTransaction))
TransactionId
iskeccak256(TypedTransactionHash | LegacyTransactionHash)
Receipt
is eitherTypedReceipt
orLegacyReceipt
TypedReceipt
is a byte array containingTransactionType || ReceiptPayload
ReceiptPayload
is an opaque byte array whose interpretation is dependent on theTransactionType
and defined in future EIPsLegacyReceipt
is an array of the form[status, cumulativeGasUsed, logsBloom, logs]
LegacyReceiptHash
iskeccak256(rlp(LegacyReceipt))
Protocol Behavior
If a client receives a TransactionType
it doesn't recognize via any message, it SHOULD disconnect the peer that sent it.
If a client receives a TransactionPayload
that isn't valid for the TransactionType
, it SHOULD disconnect the peer that sent it.
Clients MUST NOT send transactions of a new TransactionType
until that transaction type's introductory fork block.
Clients MAY disconnect peers who send transactions of a new TransactionType
significantly before that transaction type's introductory fork block.
Protocol Messages
Transactions (0x02)
: [Transaction_0, Transaction_1, ..., Transaction_n]
BlockBodies (0x06)
: [BlockBody_0, BlockBody_1, ..., BlockBody_n]
where:
BlockBody
is[TransactionList, UncleList]
TransactionList
is[Transaction_0, Transaction_1, ..., Transaction_n]
UnclesList
is defined in previous versions of the devp2p specification
NewBlock (0x07)
: [[BlockHeader, TransactionList, UncleList], TotalDifficulty]
where:
BlockHeader
is defined in previous versions of the devp2 specificationTransactionList
is[Transaction_0, Transaction_1, ..., Transaction_n]
UnclesList
is defined in previous versions of the devp2p specificationTotalDifficulty
is defined in previous versions of the devp2p specification
NewPooledTransactionIds (0x08)
: [TransactionId_0, TransactionId_1, ..., TransactionId_n]
GetPooledTransactions (0x09)
: [TransactionId_0, TransactionId_1, ..., TransactionId_n]
PooledTransactions (0x0a)
: [Transaction_0, Transaction_1, ..., Transaction_n]
Receipts (0x10)
: [ReceiptList_0, ReceiptList_1, ..., ReceiptList_n]
where:
ReceiptList
is[Receipt_0, Receipt_1, ..., Receipt_n]
Rationale
Why not specify each transaction type at the protocol layer?
We could have chosen to make the protocol aware of the shape of the transaction payloads. The authors felt that it would be too much maintenance burden long term to have every new transaction type require an update to devp2p, so instead we merely define that typed transactions are supported.
Why have peers disconnect if they receive an unknown transaction type?
We could encourage peers to remain connected to peers that submit an unknown transaction type, in case the transaction is some new transaction type that the receiver isn't aware of it. However, doing so may open clients up to DoS attacks where someone would send them transactions of an undefined TransactionType
in order to avoid being disconnected for spamming. Also, in most cases we expect that by the time new transaction types are being sent over devp2p, a hard fork that requires all connected clients to be aware of the new transaction type is almost certainly imminent.
Backwards Compatibility
Legacy transactions are still supported.
Security Considerations
If a client chooses to ignore the SHOULD recommendation for disconnecting peers that send unknown transaction types they may be susceptible to DoS attacks. Ignoring this recommendation should be limited to trusted peers only, or other situations where the risk of DoS is extremely low.
Copyright
Copyright and related rights waived via CC0.