-
Notifications
You must be signed in to change notification settings - Fork 20.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
core, core/vm: added gas price variance table (EIP #150) #3111
Conversation
@obscuren, thanks for your PR! By analyzing the history of the files in this pull request, we identified @karalabe, @Gustav-Simonsson and @Arachnid to be potential reviewers. |
7284c57
to
a3e87ea
Compare
80e4bdc
to
c65acc1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review in progress
@@ -35,6 +35,8 @@ type ChainConfig struct { | |||
DAOForkBlock *big.Int `json:"daoForkBlock"` // TheDAO hard-fork switch block (nil = no fork) | |||
DAOForkSupport bool `json:"daoForkSupport"` // Whether the nodes supports or opposes the DAO hard-fork | |||
|
|||
HomesteadGasPriceBlock *big.Int `json:"homesteadGasPriceBlock"` // homestead gas price switch block |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is essentially an API, I'd suggest a slight name change to better reflect what's happening. I.e. homesteadGasRepriceBlock
. This would make it clearer later on what happened here.
Also please add to the comment what the default (nil
and 0
) values mean.
@@ -45,3 +47,37 @@ func (c *ChainConfig) IsHomestead(num *big.Int) bool { | |||
} | |||
return num.Cmp(c.HomesteadBlock) >= 0 | |||
} | |||
|
|||
func (c *ChainConfig) GasTable(num *big.Int) vm.GasTable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add docs here and to the variable declarations below. Also please emphasize that the caller should not change any values as these are global ones.
} | ||
|
||
var ( | ||
GasChartHomestead = vm.GasTable{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please move these "constants" to the params
package. All other protocol parameters are there, including fork configs so I'd expect to find these there, not in the core
package.
CreateBySuicide: nil, | ||
} | ||
|
||
GasChartHomesteadGasPriceFork = vm.GasTable{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd recommend naming this similarly to my above suggestion, GasReprice
opposed to simply Price
. Also please add a link in a doc to the actual EIP with all the rationale so that anyone reading up on this and wondering where the values come from has an explanation.
@@ -26,6 +26,8 @@ import ( | |||
// execution of the EVM instructions (e.g. whether it's homestead) | |||
type RuleSet interface { | |||
IsHomestead(*big.Int) bool | |||
// GasChart returns the gas prices for this epoch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As agreed, please remove mentions of epoch
as they are too easy to be confused by the Ethereum notion of 30K block epochs.
@@ -31,6 +31,18 @@ import ( | |||
type ruleSet struct{} | |||
|
|||
func (ruleSet) IsHomestead(*big.Int) bool { return true } | |||
func (ruleSet) GasTable(*big.Int) vm.GasTable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you move these constants from core
to params
as suggested somewhere above, then you could reuse the same global variable and not have to redeclare the params here (potentially causing issues later down the line).
@@ -23,3 +23,17 @@ type ruleSet struct { | |||
} | |||
|
|||
func (r ruleSet) IsHomestead(n *big.Int) bool { return n.Cmp(r.hs) >= 0 } | |||
func (r ruleSet) GasTable(*big.Int) GasTable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, you could reuse these numbers from a global variable in params
.
CALLCODE: {7, params.CallGas, 1}, | ||
DELEGATECALL: {6, params.CallGas, 1}, | ||
JUMPDEST: {0, params.JumpdestGas, 0}, | ||
//BALANCE: {1, GasExtStep, 1}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't include commented out lines in the patch!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was an accident. Will remove.
DELEGATECALL: {6, params.CallGas, 1}, | ||
JUMPDEST: {0, params.JumpdestGas, 0}, | ||
//BALANCE: {1, GasExtStep, 1}, | ||
BALANCE: {1, Zero, 1}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to use a placeholder other than Zero? nil seems more suitable.
|
||
import "math/big" | ||
|
||
type GasTable struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use a map keyed by opcode, and handle CreateBySuicide separately?
@@ -234,7 +236,7 @@ func (evm *EVM) Run(contract *Contract, input []byte) (ret []byte, err error) { | |||
|
|||
// calculateGasAndSize calculates the required given the opcode and stack items calculates the new memorysize for | |||
// the operation. This does not reduce gas or resizes the memory. | |||
func calculateGasAndSize(env Environment, contract *Contract, caller ContractRef, op OpCode, statedb Database, mem *Memory, stack *Stack) (*big.Int, *big.Int, error) { | |||
func calculateGasAndSize(gasTable GasTable, env Environment, contract *Contract, caller ContractRef, op OpCode, statedb Database, mem *Memory, stack *Stack) (*big.Int, *big.Int, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since you're passing in env here, wouldn't it make more sense for it to fetch the gasTable itself?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because that require us to call the GasTable
method again which causes additional overhead and big int comparison.
// (availableGas - gas) * 63 / 64 | ||
// We replace the stack item so that it's available when the opCall instruction is | ||
// called. This information is otherwise lost due to the dependency on *current* | ||
// available cost. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/cost/gas/
g.Div(g, n64) | ||
if g.Cmp(callCost) < 0 { | ||
return g | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EIP150 currently says:
Define "all but one 64th" of N as N - floor(N / 64)
This code implements (N * 63) // 64
which compared to the EIP150 formula is off-by-one for some values: https://play.golang.org/p/QUbnDxCcq_
Either this code or EIP150 needs to change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code needs to change. We changed it ~4h ago.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it being the spec :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated the code now as well. PTAL
c329845
to
416d8d7
Compare
MainNetHomesteadBlock = big.NewInt(1150000) // Mainnet homestead block | ||
TestNetHomesteadBlock = big.NewInt(494000) // Testnet homestead block | ||
MainNetHomesteadBlock = big.NewInt(1150000) // Mainnet homestead block | ||
TestNetHomesteadGasRepriceBlock = big.NewInt(2648000) // Main net gas reprice block |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doc -> Testnet
b4a9d3b
to
6a484b2
Compare
// The cost of gas was changed during the homestead price change HF. To allow for EIP150 | ||
// to be implemented. The returned gas is gas - base * 63 / 64. | ||
func callGas(gasTable params.GasTable, availableGas, base, callCost *big.Int) *big.Int { | ||
if gasTable.CreateBySuicide != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add comment @karalabe
contract.UseGas(contract.Gas) | ||
if env.RuleSet().GasTable(env.BlockNumber()).CreateBySuicide != nil { | ||
gas.Div(gas, n64) | ||
gas = gas.Sub(contract.Gas, gas) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove assignment
|
||
import "math/big" | ||
|
||
type GasTable struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
godoc it
@@ -71,4 +71,5 @@ var ( | |||
SuicideRefundGas = big.NewInt(24000) // Refunded following a suicide operation. | |||
MemoryGas = big.NewInt(3) // Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL. | |||
TxDataNonZeroGas = big.NewInt(68) // Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions. | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove
b1d62fa
to
82daefa
Compare
This implements 1b & 1c of EIP150 by adding a new GasTable which must be returned from the RuleSet config method. This table is used to determine the gas prices for the current epoch. Please note that when the CreateBySuicide gas price is set it is assumed that we're in the new epoch phase. In addition this PR will serve as temporary basis while refactorisation in being done in the EVM64 PR, which will substentially overhaul the gas price code.
82daefa
to
64af2aa
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SGTM 👍
This implements 1b of ethereum/EIPs#150 by adding a new GasTable which must be
returned from the RuleSet config method. This table is used to determine
the gas prices for the current epoch.
Please note that when the CreateBySuicide gas price is set it is assumed
that we're in the new epoch phase.
In addition this PR will serve as temporary basis while refactorisation
in being done in the EVM64 PR, which will substentially overhaul the gas
price code.