Skip to content

Commit 64af2aa

Browse files
committed
core, core/vm: added gas price variance table
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.
1 parent eeb2a1a commit 64af2aa

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+77186
-67
lines changed

.zshrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/Users/jeffrey/dotfiles/zsh/zshrc

cmd/ethtest/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ func runTestWithReader(test string, r io.Reader) error {
7474
var err error
7575
switch strings.ToLower(test) {
7676
case "bk", "block", "blocktest", "blockchaintest", "blocktests", "blockchaintests":
77-
err = tests.RunBlockTestWithReader(params.MainNetHomesteadBlock, params.MainNetDAOForkBlock, r, skipTests)
77+
err = tests.RunBlockTestWithReader(params.MainNetHomesteadBlock, params.MainNetDAOForkBlock, params.MainNetHomesteadGasRepriceBlock, r, skipTests)
7878
case "st", "state", "statetest", "statetests":
7979
rs := tests.RuleSet{HomesteadBlock: params.MainNetHomesteadBlock, DAOForkBlock: params.MainNetDAOForkBlock, DAOForkSupport: true}
8080
err = tests.RunStateTestWithReader(rs, r, skipTests)

cmd/evm/main.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"github.com/ethereum/go-ethereum/crypto"
3434
"github.com/ethereum/go-ethereum/ethdb"
3535
"github.com/ethereum/go-ethereum/logger/glog"
36+
"github.com/ethereum/go-ethereum/params"
3637
"gopkg.in/urfave/cli.v1"
3738
)
3839

@@ -226,6 +227,9 @@ func NewEnv(state *state.StateDB, transactor common.Address, value *big.Int, cfg
226227
type ruleSet struct{}
227228

228229
func (ruleSet) IsHomestead(*big.Int) bool { return true }
230+
func (ruleSet) GasTable(*big.Int) params.GasTable {
231+
return params.GasTableHomesteadGasRepriceFork
232+
}
229233

230234
func (self *VMEnv) RuleSet() vm.RuleSet { return ruleSet{} }
231235
func (self *VMEnv) Vm() vm.Vm { return self.evm }

cmd/utils/flags.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,13 @@ func MakeChainConfigFromDb(ctx *cli.Context, db ethdb.Database) *core.ChainConfi
792792
}
793793
config.DAOForkSupport = true
794794
}
795+
if config.HomesteadGasRepriceBlock == nil {
796+
if ctx.GlobalBool(TestNetFlag.Name) {
797+
config.HomesteadGasRepriceBlock = params.TestNetHomesteadGasRepriceBlock
798+
} else {
799+
config.HomesteadGasRepriceBlock = params.MainNetHomesteadGasRepriceBlock
800+
}
801+
}
795802
// Force override any existing configs if explicitly requested
796803
switch {
797804
case ctx.GlobalBool(SupportDAOFork.Name):

core/config.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"math/big"
2222

2323
"github.com/ethereum/go-ethereum/core/vm"
24+
"github.com/ethereum/go-ethereum/params"
2425
)
2526

2627
var ChainConfigNotFoundErr = errors.New("ChainConfig not found") // general config not found error
@@ -35,6 +36,8 @@ type ChainConfig struct {
3536
DAOForkBlock *big.Int `json:"daoForkBlock"` // TheDAO hard-fork switch block (nil = no fork)
3637
DAOForkSupport bool `json:"daoForkSupport"` // Whether the nodes supports or opposes the DAO hard-fork
3738

39+
HomesteadGasRepriceBlock *big.Int `json:"homesteadGasRepriceBlock"` // Homestead gas reprice switch block (nil = no fork)
40+
3841
VmConfig vm.Config `json:"-"`
3942
}
4043

@@ -45,3 +48,14 @@ func (c *ChainConfig) IsHomestead(num *big.Int) bool {
4548
}
4649
return num.Cmp(c.HomesteadBlock) >= 0
4750
}
51+
52+
// GasTable returns the gas table corresponding to the current phase (homestead or homestead reprice).
53+
//
54+
// The returned GasTable's fields shouldn't, under any circumstances, be changed.
55+
func (c *ChainConfig) GasTable(num *big.Int) params.GasTable {
56+
if c.HomesteadGasRepriceBlock == nil || num == nil || num.Cmp(c.HomesteadGasRepriceBlock) < 0 {
57+
return params.GasTableHomestead
58+
}
59+
60+
return params.GasTableHomesteadGasRepriceFork
61+
}

core/vm/environment.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,16 @@ import (
2020
"math/big"
2121

2222
"github.com/ethereum/go-ethereum/common"
23+
"github.com/ethereum/go-ethereum/params"
2324
)
2425

2526
// RuleSet is an interface that defines the current rule set during the
2627
// execution of the EVM instructions (e.g. whether it's homestead)
2728
type RuleSet interface {
2829
IsHomestead(*big.Int) bool
30+
// GasTable returns the gas prices for this phase, which is based on
31+
// block number passed in.
32+
GasTable(*big.Int) params.GasTable
2933
}
3034

3135
// Environment is an EVM requirement and helper which allows access to outside

core/vm/gas.go

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,27 @@ var (
3535
GasStop = big.NewInt(0)
3636

3737
GasContractByte = big.NewInt(200)
38+
39+
n64 = big.NewInt(64)
3840
)
3941

42+
// calcGas returns the actual gas cost of the call.
43+
//
44+
// The cost of gas was changed during the homestead price change HF. To allow for EIP150
45+
// to be implemented. The returned gas is gas - base * 63 / 64.
46+
func callGas(gasTable params.GasTable, availableGas, base, callCost *big.Int) *big.Int {
47+
if gasTable.CreateBySuicide != nil {
48+
availableGas = new(big.Int).Sub(availableGas, base)
49+
g := new(big.Int).Div(availableGas, n64)
50+
g.Sub(availableGas, g)
51+
52+
if g.Cmp(callCost) < 0 {
53+
return g
54+
}
55+
}
56+
return callCost
57+
}
58+
4059
// baseCheck checks for any stack error underflows
4160
func baseCheck(op OpCode, stack *Stack, gas *big.Int) error {
4261
// PUSH and DUP are a bit special. They all cost the same but we do want to have checking on stack push limit
@@ -127,18 +146,19 @@ var _baseCheck = map[OpCode]req{
127146
MSIZE: {0, GasQuickStep, 1},
128147
GAS: {0, GasQuickStep, 1},
129148
BLOCKHASH: {1, GasExtStep, 1},
130-
BALANCE: {1, GasExtStep, 1},
131-
EXTCODESIZE: {1, GasExtStep, 1},
132-
EXTCODECOPY: {4, GasExtStep, 0},
149+
BALANCE: {1, Zero, 1},
150+
EXTCODESIZE: {1, Zero, 1},
151+
EXTCODECOPY: {4, Zero, 0},
133152
SLOAD: {1, params.SloadGas, 1},
134153
SSTORE: {2, Zero, 0},
135154
SHA3: {2, params.Sha3Gas, 1},
136155
CREATE: {3, params.CreateGas, 1},
137-
CALL: {7, params.CallGas, 1},
138-
CALLCODE: {7, params.CallGas, 1},
139-
DELEGATECALL: {6, params.CallGas, 1},
140-
JUMPDEST: {0, params.JumpdestGas, 0},
156+
// Zero is calculated in the gasSwitch
157+
CALL: {7, Zero, 1},
158+
CALLCODE: {7, Zero, 1},
159+
DELEGATECALL: {6, Zero, 1},
141160
SUICIDE: {1, Zero, 0},
161+
JUMPDEST: {0, params.JumpdestGas, 0},
142162
RETURN: {2, Zero, 0},
143163
PUSH1: {0, GasFastestStep, 1},
144164
DUP1: {0, Zero, 1},

core/vm/instructions.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,12 @@ func opCreate(instr instruction, pc *uint64, env Environment, contract *Contract
514514
input = memory.Get(offset.Int64(), size.Int64())
515515
gas = new(big.Int).Set(contract.Gas)
516516
)
517-
contract.UseGas(contract.Gas)
517+
if env.RuleSet().GasTable(env.BlockNumber()).CreateBySuicide != nil {
518+
gas.Div(gas, n64)
519+
gas = gas.Sub(contract.Gas, gas)
520+
}
521+
522+
contract.UseGas(gas)
518523
_, addr, suberr := env.Create(contract, input, gas, contract.Price, value)
519524
// Push item on the stack based on the returned error. If the ruleset is
520525
// homestead we must check for CodeStoreOutOfGasError (homestead only

core/vm/runtime/runtime.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,16 @@ import (
2525
"github.com/ethereum/go-ethereum/core/vm"
2626
"github.com/ethereum/go-ethereum/crypto"
2727
"github.com/ethereum/go-ethereum/ethdb"
28+
"github.com/ethereum/go-ethereum/params"
2829
)
2930

3031
// The default, always homestead, rule set for the vm env
3132
type ruleSet struct{}
3233

3334
func (ruleSet) IsHomestead(*big.Int) bool { return true }
35+
func (ruleSet) GasTable(*big.Int) params.GasTable {
36+
return params.GasTableHomesteadGasRepriceFork
37+
}
3438

3539
// Config is a basic type specifying certain configuration flags for running
3640
// the EVM.

core/vm/util_test.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,17 @@
1616

1717
package vm
1818

19-
import "math/big"
19+
import (
20+
"math/big"
21+
22+
"github.com/ethereum/go-ethereum/params"
23+
)
2024

2125
type ruleSet struct {
2226
hs *big.Int
2327
}
2428

2529
func (r ruleSet) IsHomestead(n *big.Int) bool { return n.Cmp(r.hs) >= 0 }
30+
func (r ruleSet) GasTable(*big.Int) params.GasTable {
31+
return params.GasTableHomestead
32+
}

0 commit comments

Comments
 (0)