From 08a967997ff1f3c47745bbd4b1fe95e74a8a3e2f Mon Sep 17 00:00:00 2001 From: cdetrio Date: Sun, 30 Apr 2017 10:59:06 -0400 Subject: [PATCH 1/3] copy EIP-150 from issues --- EIPS/eip-150.md | 72 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 EIPS/eip-150.md diff --git a/EIPS/eip-150.md b/EIPS/eip-150.md new file mode 100644 index 00000000..9e863e6a --- /dev/null +++ b/EIPS/eip-150.md @@ -0,0 +1,72 @@ +EDITOR NOTE: below is a copy of the EIP 150 https://github.com/ethereum/EIPs/issues/150#issue-179028421 raw text fetched on 2017-04-30. + +UPDATE: version 1c of this spec has been implemented and is active on the mainnet as of block 2463000. Spec is kept unmodified for archival purposes. +### Specification (version 1) + +If `block.number >= FORK_BLKNUM`, then: +- Increase the gas cost of EXTCODESIZE to 700 +- Increase the base gas cost of EXTCODECOPY to 700 +- Increase the gas cost of BALANCE to 400 +- Increase the gas cost of SLOAD to 200 +- Increase the gas cost of CALL, DELEGATECALL, CALLCODE to 700 +- Increase the gas cost of SUICIDE to 5000 +- Increase the recommended gas limit target to 5.5 million +- If a call asks for more gas than the maximum allowed amount, do not return an OOG error; instead, call with the maximum allowed amount of gas (this is equivalent to a version of #90) + +That is, substitute: + +``` + extra_gas = (not ext.account_exists(to)) * opcodes.GCALLNEWACCOUNT + \ + (value > 0) * opcodes.GCALLVALUETRANSFER + submsg_gas = gas + opcodes.GSTIPEND * (value > 0) + if compustate.gas < gas + extra_gas: + return vm_exception('OUT OF GAS', needed=gas+extra_gas) +``` + +With: + +``` + extra_gas = (not ext.account_exists(to)) * opcodes.GCALLNEWACCOUNT + \ + (value > 0) * opcodes.GCALLVALUETRANSFER + if compustate.gas < extra_gas: + return vm_exception('OUT OF GAS', needed=extra_gas) + if compustate.gas < gas + extra_gas: + gas = compustate.gas - extra_gas + submsg_gas = gas + opcodes.GSTIPEND * (value > 0) +``` +### Specification (version 1b) + +All of the above, but: +- Define "all but one 64th" of `N` as `N - floor(N / 64)` +- If a call asks for more gas than the maximum allowed amount (ie. total amount of gas remaining in the parent after subtracting the gas cost of the call and memory expansion), do not return an OOG error; instead, if a call asks for more gas than all but one 64th of the maximum allowed amount, call with all but one 64th of the maximum allowed amount of gas (this is equivalent to a version of #90 plus #114). CREATE only provides all but one 64th of the parent gas to the child call. +### Specification (version 1c) + +All of the above, and: + +If SUICIDE hits a newly created account, it triggers an additional gas cost of 25000 (similar to CALLs) +### Specification (version 2) + +If `block.number >= METROPOLIS_FORK_BLKNUM`, then: +- Increase the gas cost of EXTCODESIZE to 4000 +- Increase the base gas cost of EXTCODECOPY to 4000 +- Increase the gas cost of BALANCE to 400 +- Increase the gas cost of SLOAD to 200 +- Increase the gas cost of CALL, CALLDELEGATE, CALLCODE to 4000 +- Increase the gas cost of SUICIDE to 5000 +- If SUICIDE hits a newly created account, it triggers an additional gas cost of 25000 (similar to CALLs) +- Increase the recommended gas limit target to 5.5 million +- Define "all but one 64th" of `N` as `N - floor(N / 64)` +- If a call asks for more gas than the maximum allowed amount, do not return an OOG error; instead, if a call asks for more gas than all but one 64th of the maximum allowed amount, call with all but one 64th of the maximum allowed amount of gas (this is equivalent to a version of #90 plus #114). CREATE only provides all but one 64th of the parent gas to the child call. + +When executing EXTCODESIZE, EXTCODECOPY, CALL, CALLDELEGATE or CALLCODE (but NOT BALANCE), let CODELOADING_GAS be `int(400 + len(code) / 6)`. At the end of the call, refund an additional 4000 - CODELOADING_GAS (if CODELOADING < 0, refund nothing). CREATE only provides 63/64 of the parent gas to the child call. +### Rationale + +Recent denial-of-service attacks have shown that opcodes that read the state tree are under-priced relative to other opcodes. There are software changes that have been made, are being made and can be made in order to mitigate the situation; however, the fact will remain that such opcodes will be by a substantial margin the easiest known mechanism to degrade network performance via transaction spam. The concern arises because it takes a long time to read from disk, and is additionally a risk to future sharding proposals as the "attack transactions" that have so far been most successful in degrading network performance would also require tens of megabytes to provide Merkle proofs for. This EIP increases the cost of storage reading opcodes to address this concern. The costs have been derived from an updated version of the calculation table used to generate the 1.0 gas costs: https://docs.google.com/spreadsheets/d/15wghZr-Z6sRSMdmRmhls9dVXTOpxKy8Y64oy9MvDZEQ/edit#gid=0 ; the rules attempt to target a limit of 8 MB of data that needs to be read in order to process a block, and include an estimate of 500 bytes for a Merkle proof for SLOAD and 1000 for an account. + +The first version of the EIP aims to be simple, and adds a flat penalty of 300 gas on top of the costs calculated in this table to account for the cost of loading the code (~17-21 kb in the worst case). The second version of the EIP instead adds an explicit parameter to take into account the size of code loading. Note that this parameter is weighted ~60% below the computed weight; this is to account for the fact that loading a large contiguous of code is, on a per-byte basis, much more efficient in terms of disk seeks (which often have a minimum size of 4kb regardless of the size of the actual object) than making several Merkle queries. A worst-case contract would take 3000 gas to load; a contract 2kb in size would take ~720 gas. This also has the benefit that it prevents a potential DoS vector against precomputation-heavy JIT VMs, where an attacker calls a large contract, requires the VM to just-in-time compile its entire code, only executes for perhaps ten cycles and then leaves. Version 2b fixes a problem where EXTCODESIZE is called with a small amount of gas, so that execution tries to fetch the contract code but runs out-of-gas upon seeing its size, thereby adding a large number of bytes to the merkle proof (and required DB load unless proper caching is added) but still only costing a relatively small amount of gas. + +BALANCE is not affected by the per-byte changes because checking an account's balance does not require loading its code. + +The EIP 90 gas mechanic is introduced because without it, all current contracts that make calls would stop working as they use an expression like `msg.gas - 40` to determine how much gas to make a call with, relying on the gas cost of calls being 40. In the more complex version, EIP 114 is introduced because, given that we are making the cost of a call higher and less predictable, we have an opportunity to do it at no extra cost to currently available guarantees, and so we also achieve the benefit of replacing the call stack depth limit with a "softer" gas-based restriction, thereby eliminating call stack depth attacks as a class of attack that contract developers have to worry about and hence increasing contract programming safety. Note that with the given parameters, the de-facto maximum call stack depth is limited to ~340 (down from ~1024), mitigating the harm caused by any further potential quadratic-complexity DoS attacks that rely on calls. + +The gas limit increase is recommended so as to preserve the de-facto transactions-per-second processing capability of the system for average contracts. From 92b131b1905dc22ef9316ad74bfc5c3b65434871 Mon Sep 17 00:00:00 2001 From: cdetrio Date: Sun, 30 Apr 2017 11:27:34 -0400 Subject: [PATCH 2/3] add preamble --- EIPS/eip-150.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/EIPS/eip-150.md b/EIPS/eip-150.md index 9e863e6a..6aacf918 100644 --- a/EIPS/eip-150.md +++ b/EIPS/eip-150.md @@ -1,6 +1,16 @@ -EDITOR NOTE: below is a copy of the EIP 150 https://github.com/ethereum/EIPs/issues/150#issue-179028421 raw text fetched on 2017-04-30. - UPDATE: version 1c of this spec has been implemented and is active on the mainnet as of block 2463000. Spec is kept unmodified for archival purposes. + +## Preamble +``` +EIP: 150 +Title: Gas cost changes for IO-heavy operations +Author: Vitalik Buterin +Type: Standard Track +Category: Core +Status: Final +Created: 2016-09-24 +``` + ### Specification (version 1) If `block.number >= FORK_BLKNUM`, then: From a52b4c1b21fe0f54a2b972c8250cb6106a01a12c Mon Sep 17 00:00:00 2001 From: cdetrio Date: Sun, 30 Apr 2017 11:49:03 -0400 Subject: [PATCH 3/3] consolidate to version 1c, remove version 2 --- EIPS/eip-150.md | 47 ++++++++++++----------------------------------- 1 file changed, 12 insertions(+), 35 deletions(-) diff --git a/EIPS/eip-150.md b/EIPS/eip-150.md index 6aacf918..012f76e3 100644 --- a/EIPS/eip-150.md +++ b/EIPS/eip-150.md @@ -1,5 +1,3 @@ -UPDATE: version 1c of this spec has been implemented and is active on the mainnet as of block 2463000. Spec is kept unmodified for archival purposes. - ## Preamble ``` EIP: 150 @@ -11,7 +9,7 @@ Status: Final Created: 2016-09-24 ``` -### Specification (version 1) +### Specification If `block.number >= FORK_BLKNUM`, then: - Increase the gas cost of EXTCODESIZE to 700 @@ -19,64 +17,43 @@ If `block.number >= FORK_BLKNUM`, then: - Increase the gas cost of BALANCE to 400 - Increase the gas cost of SLOAD to 200 - Increase the gas cost of CALL, DELEGATECALL, CALLCODE to 700 -- Increase the gas cost of SUICIDE to 5000 +- Increase the gas cost of SELFDESTRUCT to 5000 +- If SELFDESTRUCT hits a newly created account, it triggers an additional gas cost of 25000 (similar to CALLs) - Increase the recommended gas limit target to 5.5 million -- If a call asks for more gas than the maximum allowed amount, do not return an OOG error; instead, call with the maximum allowed amount of gas (this is equivalent to a version of #90) +- Define "all but one 64th" of `N` as `N - floor(N / 64)` +- If a call asks for more gas than the maximum allowed amount (ie. total amount of gas remaining in the parent after subtracting the gas cost of the call and memory expansion), do not return an OOG error; instead, if a call asks for more gas than all but one 64th of the maximum allowed amount, call with all but one 64th of the maximum allowed amount of gas (this is equivalent to a version of #90 plus #114). CREATE only provides all but one 64th of the parent gas to the child call. That is, substitute: ``` extra_gas = (not ext.account_exists(to)) * opcodes.GCALLNEWACCOUNT + \ (value > 0) * opcodes.GCALLVALUETRANSFER - submsg_gas = gas + opcodes.GSTIPEND * (value > 0) if compustate.gas < gas + extra_gas: return vm_exception('OUT OF GAS', needed=gas+extra_gas) + submsg_gas = gas + opcodes.GSTIPEND * (value > 0) ``` With: ``` + def max_call_gas(gas): + return gas - (gas // 64) + extra_gas = (not ext.account_exists(to)) * opcodes.GCALLNEWACCOUNT + \ (value > 0) * opcodes.GCALLVALUETRANSFER if compustate.gas < extra_gas: return vm_exception('OUT OF GAS', needed=extra_gas) if compustate.gas < gas + extra_gas: - gas = compustate.gas - extra_gas + gas = min(gas, max_call_gas(compustate.gas - extra_gas)) submsg_gas = gas + opcodes.GSTIPEND * (value > 0) ``` -### Specification (version 1b) -All of the above, but: -- Define "all but one 64th" of `N` as `N - floor(N / 64)` -- If a call asks for more gas than the maximum allowed amount (ie. total amount of gas remaining in the parent after subtracting the gas cost of the call and memory expansion), do not return an OOG error; instead, if a call asks for more gas than all but one 64th of the maximum allowed amount, call with all but one 64th of the maximum allowed amount of gas (this is equivalent to a version of #90 plus #114). CREATE only provides all but one 64th of the parent gas to the child call. -### Specification (version 1c) - -All of the above, and: - -If SUICIDE hits a newly created account, it triggers an additional gas cost of 25000 (similar to CALLs) -### Specification (version 2) - -If `block.number >= METROPOLIS_FORK_BLKNUM`, then: -- Increase the gas cost of EXTCODESIZE to 4000 -- Increase the base gas cost of EXTCODECOPY to 4000 -- Increase the gas cost of BALANCE to 400 -- Increase the gas cost of SLOAD to 200 -- Increase the gas cost of CALL, CALLDELEGATE, CALLCODE to 4000 -- Increase the gas cost of SUICIDE to 5000 -- If SUICIDE hits a newly created account, it triggers an additional gas cost of 25000 (similar to CALLs) -- Increase the recommended gas limit target to 5.5 million -- Define "all but one 64th" of `N` as `N - floor(N / 64)` -- If a call asks for more gas than the maximum allowed amount, do not return an OOG error; instead, if a call asks for more gas than all but one 64th of the maximum allowed amount, call with all but one 64th of the maximum allowed amount of gas (this is equivalent to a version of #90 plus #114). CREATE only provides all but one 64th of the parent gas to the child call. - -When executing EXTCODESIZE, EXTCODECOPY, CALL, CALLDELEGATE or CALLCODE (but NOT BALANCE), let CODELOADING_GAS be `int(400 + len(code) / 6)`. At the end of the call, refund an additional 4000 - CODELOADING_GAS (if CODELOADING < 0, refund nothing). CREATE only provides 63/64 of the parent gas to the child call. ### Rationale Recent denial-of-service attacks have shown that opcodes that read the state tree are under-priced relative to other opcodes. There are software changes that have been made, are being made and can be made in order to mitigate the situation; however, the fact will remain that such opcodes will be by a substantial margin the easiest known mechanism to degrade network performance via transaction spam. The concern arises because it takes a long time to read from disk, and is additionally a risk to future sharding proposals as the "attack transactions" that have so far been most successful in degrading network performance would also require tens of megabytes to provide Merkle proofs for. This EIP increases the cost of storage reading opcodes to address this concern. The costs have been derived from an updated version of the calculation table used to generate the 1.0 gas costs: https://docs.google.com/spreadsheets/d/15wghZr-Z6sRSMdmRmhls9dVXTOpxKy8Y64oy9MvDZEQ/edit#gid=0 ; the rules attempt to target a limit of 8 MB of data that needs to be read in order to process a block, and include an estimate of 500 bytes for a Merkle proof for SLOAD and 1000 for an account. -The first version of the EIP aims to be simple, and adds a flat penalty of 300 gas on top of the costs calculated in this table to account for the cost of loading the code (~17-21 kb in the worst case). The second version of the EIP instead adds an explicit parameter to take into account the size of code loading. Note that this parameter is weighted ~60% below the computed weight; this is to account for the fact that loading a large contiguous of code is, on a per-byte basis, much more efficient in terms of disk seeks (which often have a minimum size of 4kb regardless of the size of the actual object) than making several Merkle queries. A worst-case contract would take 3000 gas to load; a contract 2kb in size would take ~720 gas. This also has the benefit that it prevents a potential DoS vector against precomputation-heavy JIT VMs, where an attacker calls a large contract, requires the VM to just-in-time compile its entire code, only executes for perhaps ten cycles and then leaves. Version 2b fixes a problem where EXTCODESIZE is called with a small amount of gas, so that execution tries to fetch the contract code but runs out-of-gas upon seeing its size, thereby adding a large number of bytes to the merkle proof (and required DB load unless proper caching is added) but still only costing a relatively small amount of gas. +This EIP aims to be simple, and adds a flat penalty of 300 gas on top of the costs calculated in this table to account for the cost of loading the code (~17-21 kb in the worst case). -BALANCE is not affected by the per-byte changes because checking an account's balance does not require loading its code. - -The EIP 90 gas mechanic is introduced because without it, all current contracts that make calls would stop working as they use an expression like `msg.gas - 40` to determine how much gas to make a call with, relying on the gas cost of calls being 40. In the more complex version, EIP 114 is introduced because, given that we are making the cost of a call higher and less predictable, we have an opportunity to do it at no extra cost to currently available guarantees, and so we also achieve the benefit of replacing the call stack depth limit with a "softer" gas-based restriction, thereby eliminating call stack depth attacks as a class of attack that contract developers have to worry about and hence increasing contract programming safety. Note that with the given parameters, the de-facto maximum call stack depth is limited to ~340 (down from ~1024), mitigating the harm caused by any further potential quadratic-complexity DoS attacks that rely on calls. +The EIP 90 gas mechanic is introduced because without it, all current contracts that make calls would stop working as they use an expression like `msg.gas - 40` to determine how much gas to make a call with, relying on the gas cost of calls being 40. Additionally, EIP 114 is introduced because, given that we are making the cost of a call higher and less predictable, we have an opportunity to do it at no extra cost to currently available guarantees, and so we also achieve the benefit of replacing the call stack depth limit with a "softer" gas-based restriction, thereby eliminating call stack depth attacks as a class of attack that contract developers have to worry about and hence increasing contract programming safety. Note that with the given parameters, the de-facto maximum call stack depth is limited to ~340 (down from ~1024), mitigating the harm caused by any further potential quadratic-complexity DoS attacks that rely on calls. The gas limit increase is recommended so as to preserve the de-facto transactions-per-second processing capability of the system for average contracts.