* initial draft of transaction package eip * added url for discussion thread * assigned to eip-2733 * fix typo and update to use return opcodes instead of call data * fix incorrect hex for returndatasize
4.7 KiB
eip | title | author | discussions-to | status | type | category | created | requires |
---|---|---|---|---|---|---|---|---|
2733 | Transaction package | Matt Garnett (@lightclient) | https://ethereum-magicians.org/t/eip-transaction-package/4365 | Draft | Standards Track | Core | 2020-06-16 | 2718 |
Simple Summary
Creates a new transaction type which executes a package of one or more transactions.
Abstract
After FORK_BLOCK
, a new EIP-2718
transaction of type N
is recognized. Transactions of type N
will define a
list of transactions, which must be executed serially by clients. Execution
information (e.g. success
, gas_used
, etc.) will be propagated forward to
the next transaction.
Motivation
Meta-transaction relay contracts have historically been designed to catch reversions in their inner transactions by only passing a portion of the available gas to the subcall. This has been considered bad practice for a long time, but in the case of untrust subcalls -- it is the only available solution. Transaction packages are an alternative solution which allow multiple transactions to be bundled into one package and executed atomically.
Specification
Definitions
N = TBD transaction type number
INTRINSIC_COST = TBD
TOTAL_COST = INTRINSIC_COST + inner_txs.reduce(|itx, acc| acc += itx.value + itx.gas_price * itx.gas_limit)
TOTAL_GAS_LIMIT = inner_txs.reduce(|itx, acc| acc += itx.gas_limit)
TX_HASH = hash of transaction as defined below
SENDER = ecrecover(hash, v, r, s)
RESULT = result as defined below for the previous transaction, empty if its the first tx in a package
Serialization
After FORK_BLOCK
, a new EIP-2718
transaction type N
will be interpreted as follows:
rlp([N, rlp([nonce, v, r, s, [inner_tx_0, ..., inner_tx_n]])
where inner_tx_n
is defined as:
[chain_id, to, value, data, gas_limit, gas_price]
Hashing
The hash of transaction type N
is defined to be the Keccak-256 hash of the
rlp encoding of the entire transaction with v
, r
, and s
values omitted.
Results
Subsequent transactions will be able to receive the result of the previous
transaction via RETURNDATACOPY (0x3E)
in first frame of exeuction, before
making any subcalls. Each element except the last will be 0
-padded left to 32
bytes.
Name | Type | Description |
---|---|---|
success |
bool | Status of the previous transaction |
gas_used |
uint256 | Total gas used by the previous transaction |
cum_gas_used |
uint256 | Cumulative gas used by previous transactions |
return_size |
uint256 | The size of the return value |
return_value |
bytes | The return value of the previous transaction |
Validation
- (v, r, s) are a valid signature of the hash of the transaction
- The nonce is one greater than recovered address' current nonce
- The recovered address has a balance of at least
TOTAL_COST
- The
TOTAL_GAS_LIMIT
is less than the current block'sgas_limit
Execution
Transaction packages should be executed as follows:
- Deduct
TOTAL_COST
fromSENDER
's balance - Execute the first inner transaction in the list
- Refund any unused
gas
- If there are no more transaction, stop
- Compute
RESULT
for the previously executed transaction - Prepare
RESULT
to be available via return opcodes in the next transaction's first frame - Execute the transaction
- Goto
3
Rationale
Non-recursive inner transactions
For simplicity, inner transactions are fully defined within this EIP. However, there is value in supporting recursive transaction definitions. For example, suppose there is a transaction type which can become invalid after a certain block number. It would be beneficial to support those types of transactions within a package, but the complexity of this EIP would dramatically increase.
Appending result data to transaction input data
An alternative to using return opcodes to propagate RESULT
would be to append
the RESULT
to the subsequent transaction's data
field. Unfortunately, in
many cases contracts generated using Solidity will
fail
to resolve the intended function if additional data is present. Another
alternative is introducing new opcodes to expose the result data were not
proposed.
Backwards Compatibility
Contracts which rely on ORIGIN (0x32) == CALLER (0x33) && RETURNDATASIZE (0x3D) == 0x00
will now always fail in transaction packages, unless they are
the first executed transaction. It's unknown if any contracts conduct this
check.
Test Cases
TBD
Implementation
TBD
Security Considerations
TBD
Copyright
Copyright and related rights waived via CC0.