From c1f45f8b4caa4e12716863943a473dc4bdd6ec23 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 13 Feb 2017 12:07:09 +0100 Subject: [PATCH 01/21] Propose RETURNDATACOPY and RETURNDATASIZE. --- EIPS/returndatacopy.md | 61 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 EIPS/returndatacopy.md diff --git a/EIPS/returndatacopy.md b/EIPS/returndatacopy.md new file mode 100644 index 00000000..2d4c7e8d --- /dev/null +++ b/EIPS/returndatacopy.md @@ -0,0 +1,61 @@ +## Preamble + + EIP: + Title: New opcodes: RETURNDATASIZE and RETURNDATACOPY + Author: Christian Reitwiessner + Type: Standard Track + Category Core + Status: Draft + Created: 2017-02-13 + Requires: + Replaces: 5/8 + + +## Simple Summary + +A mechanism to allow returning arbitrary-length data inside the EVM has been requested for quite a while now. Existing proposals always had very intricate problems associated with charging gas. This proposal solves the same problem while at the same time, it has a very simple gas charging mechanism and reqires minimal changes to the call opcodes. Its workings are very similar to the way calldata is handled already: After a call, return data is kept inside a virtual buffer from which the caller can copy it (or parts thereof) into memory. At the next call, the buffer is overwritten. This mechanism is 100% backwards compatible. + +## Abstract + +Please see summary. + +## Motivation + +In some situations, it is vital for a function to be able to return data whose length cannot be anticipated before the call. In principle, this can be solved without alterations to the EVM, for example by splitting the call into two calls where the first is used to compute only the size. All of these mechanisms, though, are very expensive in at least some situations. A very useful example of such a worst-case situation is a generic forwarding contract: A contract that takes call data, potentially makes some checks and then forwards it as is to another contract. The return data should of course be transferred in a similar way to the original caller. Since the contract is generic and does not know about the contract it calls, there is no way to determine the size of the output without adapting the called contract accordingly or trying a logarithmic number of calls. + +Compiler implementors are advised to reserve a zero-length area for return data if the size of the return data is unknown before the call and then use `RETURNDATACOPY` in conjunction with `RETURNDATASIZE` to actually retrieve the data. + +Note that this proposal also makes the EIP that proposes to allow to return data in case of an intentional state reversion (EIP [206](https://github.com/ethereum/EIPs/pull/206)) much more useful. Since the size of the failure data might be larger than the regular return data (or even unknown), it is possible to retrieve the failure data after the CALL opcode has signalled a failure, even if the regular output area is not large enough to hold the data. + +## Specification + +Add two new opcodes: + +`RETURNDATASIZE`: `0xd` + +Pushes the size of the return data (or the failure return data, see EIP [206](https://github.com/ethereum/EIPs/pull/206)) of the previous call onto the stack. If there was no previous call, pushes zero. +Gas costs: 2 (same as `CALLDATASIZE`) + +`RETURNDATACOPY`: `0xe` + +This opcode has similar semantics to `CALLDATACOPY`, but instead of copying data from the call data, it copies data from the return data of the previous call. If the return data is accessed beyond its length, it is considered to be filled with zeros. If there was no previous call, copies zeros. +Gas costs: `3 + 3 * ceil(amount / 32)` (same as `CALLDATACOPY`) + +## Rationale + +Other solutions that would allow returning dynamic data were considered, but they all had to deduct the gas from the call opcode and thus were both complicated to implement and specify ([5/8](https://github.com/ethereum/EIPs/issues/8)). Since this proposal is very similar to the way calldata is handled, it fits nicely into the concept. Furthermore, the eWASM architecture already handles return data in exactly the same way. + +Note that the EVM implementation needs to keep the return data until the next call or the return from the current call. Since this resource was already paid for as part of the memory of the callee, it should not be a problem. Implementations may either choose to keep the full memory of the callee alive until the next call or copy only the return data to a special memory area. + +The number values of the opcodes were allocated in the same nibble block that also contains `CALLDATASIZE` and `CALLDATACOPY`. + +## Backwards Compatibility + +This proposal introduces two new opcodes and stays fully backwards compatible apart from that. + +## Test Cases + +## Implementation + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From d10be75eabedcebcc91f1e64916cf1ee4777fe19 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 25 Apr 2017 12:46:22 +0200 Subject: [PATCH 02/21] Assign number and add clarifictaions. --- EIPS/returndatacopy.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/EIPS/returndatacopy.md b/EIPS/returndatacopy.md index 2d4c7e8d..66bbd3e1 100644 --- a/EIPS/returndatacopy.md +++ b/EIPS/returndatacopy.md @@ -1,6 +1,6 @@ ## Preamble - EIP: + EIP: 211 Title: New opcodes: RETURNDATASIZE and RETURNDATACOPY Author: Christian Reitwiessner Type: Standard Track @@ -29,16 +29,21 @@ Note that this proposal also makes the EIP that proposes to allow to return data ## Specification -Add two new opcodes: +Add two new opcodes and amend the semantics of any opcode that creates a new call frame (like `CALL`, `CREATE`, `DELEGATECALL`, ...) called call-like opcodes in the following. It is assumed that the EVM (to be more specific: an EVM call frame) has a new internal buffer of variable size, called the return data buffer. This buffer is created empty for each new call frame. Upon executing any call-like opcode, the buffer is cleared (its size is set to zero). After executing a call-like opcode, the complete return data (or failure data, see EIP [206](https://github.com/ethereum/EIPs/pull/206)) of the call is stored in the return data buffer (of the caller), and its size changed accordingly. As an exception, `CREATE` is considered to return the empty buffer in the success case and the failure data in the failure case. + +As an optimization, it is possible to share the return data buffer across call frames because only one will be non-empty at any time. `RETURNDATASIZE`: `0xd` -Pushes the size of the return data (or the failure return data, see EIP [206](https://github.com/ethereum/EIPs/pull/206)) of the previous call onto the stack. If there was no previous call, pushes zero. +Pushes the size of the return data buffer onto the stack. Gas costs: 2 (same as `CALLDATASIZE`) `RETURNDATACOPY`: `0xe` -This opcode has similar semantics to `CALLDATACOPY`, but instead of copying data from the call data, it copies data from the return data of the previous call. If the return data is accessed beyond its length, it is considered to be filled with zeros. If there was no previous call, copies zeros. +This opcode has similar semantics to `CALLDATACOPY`, but instead of copying data from the call data, it copies data from the return data buffer. If the return data buffer is accessed beyond its size, it is considered to be filled with zeros. + +ALTERNATIVE: If the return data is accessed beyond its size, results in failure. + Gas costs: `3 + 3 * ceil(amount / 32)` (same as `CALLDATACOPY`) ## Rationale @@ -47,6 +52,8 @@ Other solutions that would allow returning dynamic data were considered, but the Note that the EVM implementation needs to keep the return data until the next call or the return from the current call. Since this resource was already paid for as part of the memory of the callee, it should not be a problem. Implementations may either choose to keep the full memory of the callee alive until the next call or copy only the return data to a special memory area. +Keeping the memory of the callee until the next call-like opcode does not increase the peak memory usage in the following sense: Any memory allocation in the caller's frame that happens after the return from the call can be moved before the call without a change in gas costs, but will add this allocation to the peak allocation. + The number values of the opcodes were allocated in the same nibble block that also contains `CALLDATASIZE` and `CALLDATACOPY`. ## Backwards Compatibility From e07cff53904063012eb77a577bc9ab595feacf93 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 18 May 2017 11:50:03 +0200 Subject: [PATCH 03/21] Change codes to 0x3d and 0x3e --- EIPS/returndatacopy.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/EIPS/returndatacopy.md b/EIPS/returndatacopy.md index 66bbd3e1..07635c84 100644 --- a/EIPS/returndatacopy.md +++ b/EIPS/returndatacopy.md @@ -33,12 +33,12 @@ Add two new opcodes and amend the semantics of any opcode that creates a new cal As an optimization, it is possible to share the return data buffer across call frames because only one will be non-empty at any time. -`RETURNDATASIZE`: `0xd` +`RETURNDATASIZE`: `0x3d` Pushes the size of the return data buffer onto the stack. Gas costs: 2 (same as `CALLDATASIZE`) -`RETURNDATACOPY`: `0xe` +`RETURNDATACOPY`: `0x3e` This opcode has similar semantics to `CALLDATACOPY`, but instead of copying data from the call data, it copies data from the return data buffer. If the return data buffer is accessed beyond its size, it is considered to be filled with zeros. From 71ace16fcd34e962096a49d7dc81af2315d5f199 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 18 May 2017 15:05:11 +0200 Subject: [PATCH 04/21] Added CREATE2 --- EIPS/returndatacopy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/returndatacopy.md b/EIPS/returndatacopy.md index 07635c84..9689f459 100644 --- a/EIPS/returndatacopy.md +++ b/EIPS/returndatacopy.md @@ -29,7 +29,7 @@ Note that this proposal also makes the EIP that proposes to allow to return data ## Specification -Add two new opcodes and amend the semantics of any opcode that creates a new call frame (like `CALL`, `CREATE`, `DELEGATECALL`, ...) called call-like opcodes in the following. It is assumed that the EVM (to be more specific: an EVM call frame) has a new internal buffer of variable size, called the return data buffer. This buffer is created empty for each new call frame. Upon executing any call-like opcode, the buffer is cleared (its size is set to zero). After executing a call-like opcode, the complete return data (or failure data, see EIP [206](https://github.com/ethereum/EIPs/pull/206)) of the call is stored in the return data buffer (of the caller), and its size changed accordingly. As an exception, `CREATE` is considered to return the empty buffer in the success case and the failure data in the failure case. +Add two new opcodes and amend the semantics of any opcode that creates a new call frame (like `CALL`, `CREATE`, `DELEGATECALL`, ...) called call-like opcodes in the following. It is assumed that the EVM (to be more specific: an EVM call frame) has a new internal buffer of variable size, called the return data buffer. This buffer is created empty for each new call frame. Upon executing any call-like opcode, the buffer is cleared (its size is set to zero). After executing a call-like opcode, the complete return data (or failure data, see EIP [206](https://github.com/ethereum/EIPs/pull/206)) of the call is stored in the return data buffer (of the caller), and its size changed accordingly. As an exception, `CREATE` and `CREATE2` are considered to return the empty buffer in the success case and the failure data in the failure case. As an optimization, it is possible to share the return data buffer across call frames because only one will be non-empty at any time. From 28f1709777cbd99dc96dcdbbef8c532674bfbc86 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 6 Jun 2017 14:58:32 +0200 Subject: [PATCH 05/21] Fail on access beyond end. --- EIPS/returndatacopy.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/EIPS/returndatacopy.md b/EIPS/returndatacopy.md index 9689f459..11c80fba 100644 --- a/EIPS/returndatacopy.md +++ b/EIPS/returndatacopy.md @@ -40,9 +40,7 @@ Gas costs: 2 (same as `CALLDATASIZE`) `RETURNDATACOPY`: `0x3e` -This opcode has similar semantics to `CALLDATACOPY`, but instead of copying data from the call data, it copies data from the return data buffer. If the return data buffer is accessed beyond its size, it is considered to be filled with zeros. - -ALTERNATIVE: If the return data is accessed beyond its size, results in failure. +This opcode has similar semantics to `CALLDATACOPY`, but instead of copying data from the call data, it copies data from the return data buffer. Furthermore, accessing the return data buffer beyond its size results in a failure, i.e. if `start + length` overflows or results in a value larger than `RETURNDATASIZE`, the current call stops in an out-of-gas condition. Gas costs: `3 + 3 * ceil(amount / 32)` (same as `CALLDATACOPY`) From aeaffcca26fa688f5015da7ce059c886e90ef374 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 6 Jun 2017 17:04:58 +0200 Subject: [PATCH 06/21] Clarified reading from the end. --- EIPS/returndatacopy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/returndatacopy.md b/EIPS/returndatacopy.md index 11c80fba..1201df21 100644 --- a/EIPS/returndatacopy.md +++ b/EIPS/returndatacopy.md @@ -40,7 +40,7 @@ Gas costs: 2 (same as `CALLDATASIZE`) `RETURNDATACOPY`: `0x3e` -This opcode has similar semantics to `CALLDATACOPY`, but instead of copying data from the call data, it copies data from the return data buffer. Furthermore, accessing the return data buffer beyond its size results in a failure, i.e. if `start + length` overflows or results in a value larger than `RETURNDATASIZE`, the current call stops in an out-of-gas condition. +This opcode has similar semantics to `CALLDATACOPY`, but instead of copying data from the call data, it copies data from the return data buffer. Furthermore, accessing the return data buffer beyond its size results in a failure, i.e. if `start + length` overflows or results in a value larger than `RETURNDATASIZE`, the current call stops in an out-of-gas condition. In particular, reading 0 bytes from the end of the buffer will read 0 bytes; reading 0 bytes from one-byte out of the buffer causes an exception. Gas costs: `3 + 3 * ceil(amount / 32)` (same as `CALLDATACOPY`) From e3dff831121549e850fa662a0e6944878dc1ce22 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 24 Aug 2017 12:16:06 +0200 Subject: [PATCH 07/21] Clarify return data buffer for failed calls. --- EIPS/returndatacopy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/returndatacopy.md b/EIPS/returndatacopy.md index 1201df21..f8b94085 100644 --- a/EIPS/returndatacopy.md +++ b/EIPS/returndatacopy.md @@ -29,7 +29,7 @@ Note that this proposal also makes the EIP that proposes to allow to return data ## Specification -Add two new opcodes and amend the semantics of any opcode that creates a new call frame (like `CALL`, `CREATE`, `DELEGATECALL`, ...) called call-like opcodes in the following. It is assumed that the EVM (to be more specific: an EVM call frame) has a new internal buffer of variable size, called the return data buffer. This buffer is created empty for each new call frame. Upon executing any call-like opcode, the buffer is cleared (its size is set to zero). After executing a call-like opcode, the complete return data (or failure data, see EIP [206](https://github.com/ethereum/EIPs/pull/206)) of the call is stored in the return data buffer (of the caller), and its size changed accordingly. As an exception, `CREATE` and `CREATE2` are considered to return the empty buffer in the success case and the failure data in the failure case. +Add two new opcodes and amend the semantics of any opcode that creates a new call frame (like `CALL`, `CREATE`, `DELEGATECALL`, ...) called call-like opcodes in the following. It is assumed that the EVM (to be more specific: an EVM call frame) has a new internal buffer of variable size, called the return data buffer. This buffer is created empty for each new call frame. Upon executing any call-like opcode, the buffer is cleared (its size is set to zero). After executing a call-like opcode, the complete return data (or failure data, see EIP [206](https://github.com/ethereum/EIPs/pull/206)) of the call is stored in the return data buffer (of the caller), and its size changed accordingly. As an exception, `CREATE` and `CREATE2` are considered to return the empty buffer in the success case and the failure data in the failure case. If the call-like opcode is executed but does not really instanciate a call frame (for example due to insufficient funds for a value transfer or if the called contract does not exist), the return data buffer is empty. As an optimization, it is possible to share the return data buffer across call frames because only one will be non-empty at any time. From c9e53026aa4da67df0c95bd902f0f3981da29b99 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Sat, 21 Oct 2017 09:29:39 -0700 Subject: [PATCH 08/21] eip-55 checksum_encode spec typo --- EIPS/eip-55.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/eip-55.md b/EIPS/eip-55.md index d7f0369c..e60dc159 100644 --- a/EIPS/eip-55.md +++ b/EIPS/eip-55.md @@ -26,7 +26,7 @@ def checksum_encode(addr): # Takes a 20-byte binary address as input return '0x'+o def test(addrstr): - assert(addrstr == checksum_encode2(bytes.fromhex(addrstr[2:]))) + assert(addrstr == checksum_encode(bytes.fromhex(addrstr[2:]))) test('0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed') test('0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359') From f37874200ad28bcf0cc3b171242174bdcf62559d Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Fri, 17 Nov 2017 19:46:47 +0100 Subject: [PATCH 09/21] Fix a typo https://github.com/ethereum/EIPs/pull/211#pullrequestreview-58334736 --- EIPS/returndatacopy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/returndatacopy.md b/EIPS/returndatacopy.md index f8b94085..2a8a358d 100644 --- a/EIPS/returndatacopy.md +++ b/EIPS/returndatacopy.md @@ -29,7 +29,7 @@ Note that this proposal also makes the EIP that proposes to allow to return data ## Specification -Add two new opcodes and amend the semantics of any opcode that creates a new call frame (like `CALL`, `CREATE`, `DELEGATECALL`, ...) called call-like opcodes in the following. It is assumed that the EVM (to be more specific: an EVM call frame) has a new internal buffer of variable size, called the return data buffer. This buffer is created empty for each new call frame. Upon executing any call-like opcode, the buffer is cleared (its size is set to zero). After executing a call-like opcode, the complete return data (or failure data, see EIP [206](https://github.com/ethereum/EIPs/pull/206)) of the call is stored in the return data buffer (of the caller), and its size changed accordingly. As an exception, `CREATE` and `CREATE2` are considered to return the empty buffer in the success case and the failure data in the failure case. If the call-like opcode is executed but does not really instanciate a call frame (for example due to insufficient funds for a value transfer or if the called contract does not exist), the return data buffer is empty. +Add two new opcodes and amend the semantics of any opcode that creates a new call frame (like `CALL`, `CREATE`, `DELEGATECALL`, ...) called call-like opcodes in the following. It is assumed that the EVM (to be more specific: an EVM call frame) has a new internal buffer of variable size, called the return data buffer. This buffer is created empty for each new call frame. Upon executing any call-like opcode, the buffer is cleared (its size is set to zero). After executing a call-like opcode, the complete return data (or failure data, see EIP [206](https://github.com/ethereum/EIPs/pull/206)) of the call is stored in the return data buffer (of the caller), and its size changed accordingly. As an exception, `CREATE` and `CREATE2` are considered to return the empty buffer in the success case and the failure data in the failure case. If the call-like opcode is executed but does not really instantiate a call frame (for example due to insufficient funds for a value transfer or if the called contract does not exist), the return data buffer is empty. As an optimization, it is possible to share the return data buffer across call frames because only one will be non-empty at any time. From 2f1e498112ce6d8f92f02a91a9714f09495ebd76 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Fri, 17 Nov 2017 19:47:23 +0100 Subject: [PATCH 10/21] Move returndatacopy.md to eip-211.md --- EIPS/{returndatacopy.md => eip-211.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename EIPS/{returndatacopy.md => eip-211.md} (100%) diff --git a/EIPS/returndatacopy.md b/EIPS/eip-211.md similarity index 100% rename from EIPS/returndatacopy.md rename to EIPS/eip-211.md From 14dc97daad12e204259a31632e20de3c3f199008 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Fri, 17 Nov 2017 20:04:39 +0100 Subject: [PATCH 11/21] Fix another typo --- EIPS/eip-211.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/eip-211.md b/EIPS/eip-211.md index 2a8a358d..0711f0ba 100644 --- a/EIPS/eip-211.md +++ b/EIPS/eip-211.md @@ -13,7 +13,7 @@ ## Simple Summary -A mechanism to allow returning arbitrary-length data inside the EVM has been requested for quite a while now. Existing proposals always had very intricate problems associated with charging gas. This proposal solves the same problem while at the same time, it has a very simple gas charging mechanism and reqires minimal changes to the call opcodes. Its workings are very similar to the way calldata is handled already: After a call, return data is kept inside a virtual buffer from which the caller can copy it (or parts thereof) into memory. At the next call, the buffer is overwritten. This mechanism is 100% backwards compatible. +A mechanism to allow returning arbitrary-length data inside the EVM has been requested for quite a while now. Existing proposals always had very intricate problems associated with charging gas. This proposal solves the same problem while at the same time, it has a very simple gas charging mechanism and requires minimal changes to the call opcodes. Its workings are very similar to the way calldata is handled already: After a call, return data is kept inside a virtual buffer from which the caller can copy it (or parts thereof) into memory. At the next call, the buffer is overwritten. This mechanism is 100% backwards compatible. ## Abstract From 61a3f8292f9b8258415c3a72a2774f6380a80991 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Fri, 17 Nov 2017 20:04:50 +0100 Subject: [PATCH 12/21] Mention the Byzantium block number --- EIPS/eip-211.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/eip-211.md b/EIPS/eip-211.md index 0711f0ba..75b0e40f 100644 --- a/EIPS/eip-211.md +++ b/EIPS/eip-211.md @@ -29,7 +29,7 @@ Note that this proposal also makes the EIP that proposes to allow to return data ## Specification -Add two new opcodes and amend the semantics of any opcode that creates a new call frame (like `CALL`, `CREATE`, `DELEGATECALL`, ...) called call-like opcodes in the following. It is assumed that the EVM (to be more specific: an EVM call frame) has a new internal buffer of variable size, called the return data buffer. This buffer is created empty for each new call frame. Upon executing any call-like opcode, the buffer is cleared (its size is set to zero). After executing a call-like opcode, the complete return data (or failure data, see EIP [206](https://github.com/ethereum/EIPs/pull/206)) of the call is stored in the return data buffer (of the caller), and its size changed accordingly. As an exception, `CREATE` and `CREATE2` are considered to return the empty buffer in the success case and the failure data in the failure case. If the call-like opcode is executed but does not really instantiate a call frame (for example due to insufficient funds for a value transfer or if the called contract does not exist), the return data buffer is empty. +If `block.number >= BYZANTIUM_FORK_BLKNUM`, add two new opcodes and amend the semantics of any opcode that creates a new call frame (like `CALL`, `CREATE`, `DELEGATECALL`, ...) called call-like opcodes in the following. It is assumed that the EVM (to be more specific: an EVM call frame) has a new internal buffer of variable size, called the return data buffer. This buffer is created empty for each new call frame. Upon executing any call-like opcode, the buffer is cleared (its size is set to zero). After executing a call-like opcode, the complete return data (or failure data, see EIP [206](https://github.com/ethereum/EIPs/pull/206)) of the call is stored in the return data buffer (of the caller), and its size changed accordingly. As an exception, `CREATE` and `CREATE2` are considered to return the empty buffer in the success case and the failure data in the failure case. If the call-like opcode is executed but does not really instantiate a call frame (for example due to insufficient funds for a value transfer or if the called contract does not exist), the return data buffer is empty. As an optimization, it is possible to share the return data buffer across call frames because only one will be non-empty at any time. From c22ad19a7dc1f4a793363c414facc8a3f81fb43c Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Mon, 20 Nov 2017 12:13:52 +0100 Subject: [PATCH 13/21] Change how to refer to EIP-140 Following https://github.com/ethereum/EIPs/pull/211#discussion_r151791340 --- EIPS/eip-140.md | 1 + EIPS/eip-211.md | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 EIPS/eip-140.md diff --git a/EIPS/eip-140.md b/EIPS/eip-140.md new file mode 100644 index 00000000..c766244c --- /dev/null +++ b/EIPS/eip-140.md @@ -0,0 +1 @@ +Reserved for https://github.com/ethereum/EIPs/pull/206 diff --git a/EIPS/eip-211.md b/EIPS/eip-211.md index 75b0e40f..2bfb9228 100644 --- a/EIPS/eip-211.md +++ b/EIPS/eip-211.md @@ -25,11 +25,11 @@ In some situations, it is vital for a function to be able to return data whose l Compiler implementors are advised to reserve a zero-length area for return data if the size of the return data is unknown before the call and then use `RETURNDATACOPY` in conjunction with `RETURNDATASIZE` to actually retrieve the data. -Note that this proposal also makes the EIP that proposes to allow to return data in case of an intentional state reversion (EIP [206](https://github.com/ethereum/EIPs/pull/206)) much more useful. Since the size of the failure data might be larger than the regular return data (or even unknown), it is possible to retrieve the failure data after the CALL opcode has signalled a failure, even if the regular output area is not large enough to hold the data. +Note that this proposal also makes the EIP that proposes to allow to return data in case of an intentional state reversion ([EIP-140](./eip-140.md)) much more useful. Since the size of the failure data might be larger than the regular return data (or even unknown), it is possible to retrieve the failure data after the CALL opcode has signalled a failure, even if the regular output area is not large enough to hold the data. ## Specification -If `block.number >= BYZANTIUM_FORK_BLKNUM`, add two new opcodes and amend the semantics of any opcode that creates a new call frame (like `CALL`, `CREATE`, `DELEGATECALL`, ...) called call-like opcodes in the following. It is assumed that the EVM (to be more specific: an EVM call frame) has a new internal buffer of variable size, called the return data buffer. This buffer is created empty for each new call frame. Upon executing any call-like opcode, the buffer is cleared (its size is set to zero). After executing a call-like opcode, the complete return data (or failure data, see EIP [206](https://github.com/ethereum/EIPs/pull/206)) of the call is stored in the return data buffer (of the caller), and its size changed accordingly. As an exception, `CREATE` and `CREATE2` are considered to return the empty buffer in the success case and the failure data in the failure case. If the call-like opcode is executed but does not really instantiate a call frame (for example due to insufficient funds for a value transfer or if the called contract does not exist), the return data buffer is empty. +If `block.number >= BYZANTIUM_FORK_BLKNUM`, add two new opcodes and amend the semantics of any opcode that creates a new call frame (like `CALL`, `CREATE`, `DELEGATECALL`, ...) called call-like opcodes in the following. It is assumed that the EVM (to be more specific: an EVM call frame) has a new internal buffer of variable size, called the return data buffer. This buffer is created empty for each new call frame. Upon executing any call-like opcode, the buffer is cleared (its size is set to zero). After executing a call-like opcode, the complete return data (or failure data, see [EIP-140](./eip-140.md)) of the call is stored in the return data buffer (of the caller), and its size changed accordingly. As an exception, `CREATE` and `CREATE2` are considered to return the empty buffer in the success case and the failure data in the failure case. If the call-like opcode is executed but does not really instantiate a call frame (for example due to insufficient funds for a value transfer or if the called contract does not exist), the return data buffer is empty. As an optimization, it is possible to share the return data buffer across call frames because only one will be non-empty at any time. From d534a1bdb4afd052de68a21d0af58eb611cc041b Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Mon, 20 Nov 2017 15:12:34 +0100 Subject: [PATCH 14/21] A colon cannot separate sentences --- EIPS/eip-211.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/EIPS/eip-211.md b/EIPS/eip-211.md index 2bfb9228..caf6bb4c 100644 --- a/EIPS/eip-211.md +++ b/EIPS/eip-211.md @@ -13,7 +13,7 @@ ## Simple Summary -A mechanism to allow returning arbitrary-length data inside the EVM has been requested for quite a while now. Existing proposals always had very intricate problems associated with charging gas. This proposal solves the same problem while at the same time, it has a very simple gas charging mechanism and requires minimal changes to the call opcodes. Its workings are very similar to the way calldata is handled already: After a call, return data is kept inside a virtual buffer from which the caller can copy it (or parts thereof) into memory. At the next call, the buffer is overwritten. This mechanism is 100% backwards compatible. +A mechanism to allow returning arbitrary-length data inside the EVM has been requested for quite a while now. Existing proposals always had very intricate problems associated with charging gas. This proposal solves the same problem while at the same time, it has a very simple gas charging mechanism and requires minimal changes to the call opcodes. Its workings are very similar to the way calldata is handled already; after a call, return data is kept inside a virtual buffer from which the caller can copy it (or parts thereof) into memory. At the next call, the buffer is overwritten. This mechanism is 100% backwards compatible. ## Abstract @@ -21,7 +21,7 @@ Please see summary. ## Motivation -In some situations, it is vital for a function to be able to return data whose length cannot be anticipated before the call. In principle, this can be solved without alterations to the EVM, for example by splitting the call into two calls where the first is used to compute only the size. All of these mechanisms, though, are very expensive in at least some situations. A very useful example of such a worst-case situation is a generic forwarding contract: A contract that takes call data, potentially makes some checks and then forwards it as is to another contract. The return data should of course be transferred in a similar way to the original caller. Since the contract is generic and does not know about the contract it calls, there is no way to determine the size of the output without adapting the called contract accordingly or trying a logarithmic number of calls. +In some situations, it is vital for a function to be able to return data whose length cannot be anticipated before the call. In principle, this can be solved without alterations to the EVM, for example by splitting the call into two calls where the first is used to compute only the size. All of these mechanisms, though, are very expensive in at least some situations. A very useful example of such a worst-case situation is a generic forwarding contract; a contract that takes call data, potentially makes some checks and then forwards it as is to another contract. The return data should of course be transferred in a similar way to the original caller. Since the contract is generic and does not know about the contract it calls, there is no way to determine the size of the output without adapting the called contract accordingly or trying a logarithmic number of calls. Compiler implementors are advised to reserve a zero-length area for return data if the size of the return data is unknown before the call and then use `RETURNDATACOPY` in conjunction with `RETURNDATASIZE` to actually retrieve the data. @@ -50,7 +50,7 @@ Other solutions that would allow returning dynamic data were considered, but the Note that the EVM implementation needs to keep the return data until the next call or the return from the current call. Since this resource was already paid for as part of the memory of the callee, it should not be a problem. Implementations may either choose to keep the full memory of the callee alive until the next call or copy only the return data to a special memory area. -Keeping the memory of the callee until the next call-like opcode does not increase the peak memory usage in the following sense: Any memory allocation in the caller's frame that happens after the return from the call can be moved before the call without a change in gas costs, but will add this allocation to the peak allocation. +Keeping the memory of the callee until the next call-like opcode does not increase the peak memory usage in the following sense; any memory allocation in the caller's frame that happens after the return from the call can be moved before the call without a change in gas costs, but will add this allocation to the peak allocation. The number values of the opcodes were allocated in the same nibble block that also contains `CALLDATASIZE` and `CALLDATACOPY`. From 0fe1eb7c46663a74561f0920c352f7e15b4fd75f Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Mon, 20 Nov 2017 15:13:05 +0100 Subject: [PATCH 15/21] Status is now Final --- EIPS/eip-211.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/eip-211.md b/EIPS/eip-211.md index caf6bb4c..22d89bb5 100644 --- a/EIPS/eip-211.md +++ b/EIPS/eip-211.md @@ -5,7 +5,7 @@ Author: Christian Reitwiessner Type: Standard Track Category Core - Status: Draft + Status: Final Created: 2017-02-13 Requires: Replaces: 5/8 From f05cbebb1a43477bd3c6827ea4703295f25b6fc6 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Fri, 1 Dec 2017 13:03:29 +0100 Subject: [PATCH 16/21] Put eip-1.md under public domain --- EIPS/eip-1.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/EIPS/eip-1.md b/EIPS/eip-1.md index d70d1092..eb3315e1 100644 --- a/EIPS/eip-1.md +++ b/EIPS/eip-1.md @@ -254,3 +254,8 @@ February 1, 2016: EIP 1 has added editors, made draft improvements to process, a [README.md]: README.md "wikilink" [Bitcoin's BIP-0001]: https://github.com/bitcoin/bips [Python's PEP-0001]: https://www.python.org/dev/peps/ + +Copyright +--------- + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From 9930119df1e33731e1cbaea02328c66251efc654 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Fri, 1 Dec 2017 13:15:58 +0100 Subject: [PATCH 17/21] Fix a title of a Byzantium EIP --- EIPS/eip-609.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/EIPS/eip-609.md b/EIPS/eip-609.md index 4ac78781..45c7728e 100644 --- a/EIPS/eip-609.md +++ b/EIPS/eip-609.md @@ -21,15 +21,15 @@ This specifies the changes included in the hard fork named Byzantium. - Block >= 4,370,000 on Mainnet - Block >= 1,700,000 on Ropsten testnet - Included EIPs: - - EIP 100 (Change difficulty adjustment to target mean block time including uncles) + - [EIP 100](./eip-100.md) (Change difficulty adjustment to target mean block time including uncles) - EIP 140 (REVERT instruction in the Ethereum Virtual Machine) - EIP 196 (Precompiled contracts for addition and scalar multiplication on the elliptic curve alt_bn128) - EIP 197 (Precompiled contracts for optimal ate pairing check on the elliptic curve alt_bn128) - EIP 198 (Precompiled contract for bigint modular exponentiation) - EIP 211 (New opcodes: RETURNDATASIZE and RETURNDATACOPY) - EIP 214 (New opcode STATICCALL) - - EIP 649 (Difficulty Bomb Delay and Block Reward Reduction) - - EIP 658 (Embedding transaction return data in receipts) + - [EIP 649](./eip-649.md) (Difficulty Bomb Delay and Block Reward Reduction) + - [EIP 658](./eip-658.md) (Embedding transaction status code in receipts) ## References From cbe317dcd650c15e431f85410e3cbeda3bd31dc1 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Fri, 1 Dec 2017 17:54:17 +0100 Subject: [PATCH 18/21] Rather pedantic edits --- EIPS/eip-211.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/EIPS/eip-211.md b/EIPS/eip-211.md index 22d89bb5..14f65f91 100644 --- a/EIPS/eip-211.md +++ b/EIPS/eip-211.md @@ -31,7 +31,7 @@ Note that this proposal also makes the EIP that proposes to allow to return data If `block.number >= BYZANTIUM_FORK_BLKNUM`, add two new opcodes and amend the semantics of any opcode that creates a new call frame (like `CALL`, `CREATE`, `DELEGATECALL`, ...) called call-like opcodes in the following. It is assumed that the EVM (to be more specific: an EVM call frame) has a new internal buffer of variable size, called the return data buffer. This buffer is created empty for each new call frame. Upon executing any call-like opcode, the buffer is cleared (its size is set to zero). After executing a call-like opcode, the complete return data (or failure data, see [EIP-140](./eip-140.md)) of the call is stored in the return data buffer (of the caller), and its size changed accordingly. As an exception, `CREATE` and `CREATE2` are considered to return the empty buffer in the success case and the failure data in the failure case. If the call-like opcode is executed but does not really instantiate a call frame (for example due to insufficient funds for a value transfer or if the called contract does not exist), the return data buffer is empty. -As an optimization, it is possible to share the return data buffer across call frames because only one will be non-empty at any time. +As an optimization, it is possible to share the return data buffer across call frames because at most one will be non-empty at any time. `RETURNDATASIZE`: `0x3d` @@ -40,7 +40,7 @@ Gas costs: 2 (same as `CALLDATASIZE`) `RETURNDATACOPY`: `0x3e` -This opcode has similar semantics to `CALLDATACOPY`, but instead of copying data from the call data, it copies data from the return data buffer. Furthermore, accessing the return data buffer beyond its size results in a failure, i.e. if `start + length` overflows or results in a value larger than `RETURNDATASIZE`, the current call stops in an out-of-gas condition. In particular, reading 0 bytes from the end of the buffer will read 0 bytes; reading 0 bytes from one-byte out of the buffer causes an exception. +This opcode has similar semantics to `CALLDATACOPY`, but instead of copying data from the call data, it copies data from the return data buffer. Furthermore, accessing the return data buffer beyond its size results in a failure; i.e. if `start + length` overflows or results in a value larger than `RETURNDATASIZE`, the current call stops in an out-of-gas condition. In particular, reading 0 bytes from the end of the buffer will read 0 bytes; reading 0 bytes from one-byte out of the buffer causes an exception. Gas costs: `3 + 3 * ceil(amount / 32)` (same as `CALLDATACOPY`) From 18bdc96dcf39c13ae268dec565d7f99f1b9bd20a Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Fri, 1 Dec 2017 22:12:33 +0100 Subject: [PATCH 19/21] Fix EIP numbers --- EIPS/{eip-213.md => eip-196.md} | 2 +- EIPS/{eip-212.md => eip-197.md} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename EIPS/{eip-213.md => eip-196.md} (98%) rename EIPS/{eip-212.md => eip-197.md} (100%) diff --git a/EIPS/eip-213.md b/EIPS/eip-196.md similarity index 98% rename from EIPS/eip-213.md rename to EIPS/eip-196.md index 4b651fd1..d4300a21 100644 --- a/EIPS/eip-213.md +++ b/EIPS/eip-196.md @@ -15,7 +15,7 @@ Precompiled contracts for elliptic curve operations are required in order to per ## Abstract -This EIP suggests to add precompiled contracts for addition and scalar multiplication on a specific pairing-friendly elliptic curve. This can in turn be combined with [EIP-212](./eip-212.md) to verify zkSNARKs in Ethereum smart contracts. The general benefit of zkSNARKs for Ethereum is that it will increase the privacy for users (because of the Zero-Knowledge property) and might also be a scalability solution (because of the succinctness and efficient verifiability property). +This EIP suggests to add precompiled contracts for addition and scalar multiplication on a specific pairing-friendly elliptic curve. This can in turn be combined with [EIP-197](./eip-197.md) to verify zkSNARKs in Ethereum smart contracts. The general benefit of zkSNARKs for Ethereum is that it will increase the privacy for users (because of the Zero-Knowledge property) and might also be a scalability solution (because of the succinctness and efficient verifiability property). ## Motivation diff --git a/EIPS/eip-212.md b/EIPS/eip-197.md similarity index 100% rename from EIPS/eip-212.md rename to EIPS/eip-197.md From 7c448166de919e543cfaa002b75e94955f524734 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Fri, 1 Dec 2017 22:17:50 +0100 Subject: [PATCH 20/21] Fix a number in the header as well --- EIPS/eip-196.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/eip-196.md b/EIPS/eip-196.md index d4300a21..3eaa411e 100644 --- a/EIPS/eip-196.md +++ b/EIPS/eip-196.md @@ -1,6 +1,6 @@ ## Preamble - EIP: 213 + EIP: 196 Title: Precompiled contracts for addition and scalar multiplication on the elliptic curve alt_bn128 Author: Christian Reitwiessner From 9783ecdff7fa5d897d5e862a933e1a68a1a043e5 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Fri, 1 Dec 2017 23:13:52 +0100 Subject: [PATCH 21/21] EIP-100 is already active on the mainnet, so its status should be Final --- EIPS/eip-100.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/eip-100.md b/EIPS/eip-100.md index 6bb6dcfc..12d7dda2 100644 --- a/EIPS/eip-100.md +++ b/EIPS/eip-100.md @@ -4,7 +4,7 @@ Title: Change difficulty adjustment to target mean block time including uncles Author: Vitalik Buterin Type: Standard Track Category: Core -Status: Accepted +Status: Final Created: 2016-04-28 ```