From 881bc87d2936482eb0716126db4ec572c04cc0d5 Mon Sep 17 00:00:00 2001 From: Matt Garnett Date: Tue, 16 Jun 2020 17:32:25 -0600 Subject: [PATCH 1/5] initial draft of transaction package eip --- EIPS/eip-tx-package.md | 132 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 EIPS/eip-tx-package.md diff --git a/EIPS/eip-tx-package.md b/EIPS/eip-tx-package.md new file mode 100644 index 00000000000000..1a2f80a8313486 --- /dev/null +++ b/EIPS/eip-tx-package.md @@ -0,0 +1,132 @@ +--- +eip: +title: Transaction package +author: Matt Garnett (@lightclient) +discussions-to: +status: Draft +type: Standards Track +category: Core +created: 2020-06-16 +requires: 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](https://eips.ethereum.org/EIPS/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](https://eips.ethereum.org/EIPS/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 receive the result of the previous transaction via +call data. Each element will be `0`-padded to 32 bytes and appended to the end +of the inner transaction's `data` field before being passed to the EVM. Those +elements are: + +| type | Description | +|---|---| +| uint256 | Status code for the termination of the previous transaction | +| uint256 | Total amount of gas used by the previous transaction | +| uint256 | The size of the return value | +| bytes32 | 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's `gas_limit` + +### Execution + +Transaction packages should be executed as follows: + +1. Deduct `TOTAL_COST` from `SENDER`'s balance +2. Execute the first inner transaction in the list +3. Refund any unused `gas` +4. If there are no more transaction, stop +5. Compute `RESULT` for the previously executed transaction +6. Append `RESULT` to the next transaction's `data` +7. Execute the transaction +9. 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 +Transaction data is defined in the Yellow Paper as "an unlimited size byte +array specifying the input data of the message". Result data certainly falls +under the definition of "input data of the message", where the message is the +subsequent inner transaction. An alternative to this would be to hijack +`RETURNDATASIZE (0x3D)` and `RETURNDATACOPY (0x3E)` in the first frame of the +inner transaction's execution and return the `RESULT`. This was not initially +chosen since this would make it possible to determine if a transaction is +executing as part of a package. For similar reasons, adding new opcodes to +expose the result data were not proposed. + + +## Backwards Compatibility +Contracts which rely on `ORIGIN (0x32) == CALLER (0x33) && RETURNDATASIZE +(0x3E) == 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](https://creativecommons.org/publicdomain/zero/1.0/). From f78e0ebde41f6310dce543278b683fae2e0fcddb Mon Sep 17 00:00:00 2001 From: Matt Garnett Date: Tue, 16 Jun 2020 18:40:47 -0600 Subject: [PATCH 2/5] added url for discussion thread --- EIPS/eip-tx-package.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/eip-tx-package.md b/EIPS/eip-tx-package.md index 1a2f80a8313486..9126d11892a7e0 100644 --- a/EIPS/eip-tx-package.md +++ b/EIPS/eip-tx-package.md @@ -2,7 +2,7 @@ eip: title: Transaction package author: Matt Garnett (@lightclient) -discussions-to: +discussions-to: https://ethereum-magicians.org/t/eip-transaction-package/4365 status: Draft type: Standards Track category: Core From 926e4e762250773e0abcd3910140e1c4661b133a Mon Sep 17 00:00:00 2001 From: Matt Garnett Date: Tue, 16 Jun 2020 19:02:00 -0600 Subject: [PATCH 3/5] assigned to eip-2733 --- EIPS/{eip-tx-package.md => eip-2733.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename EIPS/{eip-tx-package.md => eip-2733.md} (99%) diff --git a/EIPS/eip-tx-package.md b/EIPS/eip-2733.md similarity index 99% rename from EIPS/eip-tx-package.md rename to EIPS/eip-2733.md index 9126d11892a7e0..0b5ffbf2314787 100644 --- a/EIPS/eip-tx-package.md +++ b/EIPS/eip-2733.md @@ -1,5 +1,5 @@ --- -eip: +eip: 2733 title: Transaction package author: Matt Garnett (@lightclient) discussions-to: https://ethereum-magicians.org/t/eip-transaction-package/4365 From 3fb49677904a3a7d1df82f897720a2e17f3d669a Mon Sep 17 00:00:00 2001 From: Matt Garnett Date: Wed, 17 Jun 2020 07:59:13 -0600 Subject: [PATCH 4/5] fix typo and update to use return opcodes instead of call data --- EIPS/eip-2733.md | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/EIPS/eip-2733.md b/EIPS/eip-2733.md index 0b5ffbf2314787..d57f8201cad956 100644 --- a/EIPS/eip-2733.md +++ b/EIPS/eip-2733.md @@ -58,17 +58,18 @@ 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 receive the result of the previous transaction via -call data. Each element will be `0`-padded to 32 bytes and appended to the end -of the inner transaction's `data` field before being passed to the EVM. Those -elements are: - -| type | Description | -|---|---| -| uint256 | Status code for the termination of the previous transaction | -| uint256 | Total amount of gas used by the previous transaction | -| uint256 | The size of the return value | -| bytes32 | The return value of the previous transaction +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 @@ -86,7 +87,8 @@ Transaction packages should be executed as follows: 3. Refund any unused `gas` 4. If there are no more transaction, stop 5. Compute `RESULT` for the previously executed transaction -6. Append `RESULT` to the next transaction's `data` +6. Prepare `RESULT` to be available via return opcodes in the next + transaction's first frame 7. Execute the transaction 9. Goto `3` @@ -102,15 +104,13 @@ within a package, but the complexity of this EIP would dramatically increase. #### Appending result data to transaction input data -Transaction data is defined in the Yellow Paper as "an unlimited size byte -array specifying the input data of the message". Result data certainly falls -under the definition of "input data of the message", where the message is the -subsequent inner transaction. An alternative to this would be to hijack -`RETURNDATASIZE (0x3D)` and `RETURNDATACOPY (0x3E)` in the first frame of the -inner transaction's execution and return the `RESULT`. This was not initially -chosen since this would make it possible to determine if a transaction is -executing as part of a package. For similar reasons, adding new opcodes to -expose the result data were not proposed. +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](https://solidity.readthedocs.io/en/v0.6.0/contracts.html#overload-resolution-and-argument-matching) +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 From 0b684e9f86ad82b5b7c424615931b473c2fcf1af Mon Sep 17 00:00:00 2001 From: Matt Garnett Date: Wed, 17 Jun 2020 08:01:19 -0600 Subject: [PATCH 5/5] fix incorrect hex for returndatasize --- EIPS/eip-2733.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/eip-2733.md b/EIPS/eip-2733.md index d57f8201cad956..2bad51d8409da7 100644 --- a/EIPS/eip-2733.md +++ b/EIPS/eip-2733.md @@ -115,7 +115,7 @@ proposed. ## Backwards Compatibility Contracts which rely on `ORIGIN (0x32) == CALLER (0x33) && RETURNDATASIZE -(0x3E) == 0x00` will now always fail in transaction packages, unless they are +(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.