Skip to content

Commit 445feae

Browse files
committed
core, core/state, trie: EIP158, reprice & skip empty account write
This commit implements EIP158 part 1, 2, 3 & 4 1. If an account is empty it's no longer written to the trie. An empty account is defined as (balance=0, nonce=0, storage=0, code=0). 2. Delete an empty account if it's touched 3. An empty account is redefined as either non-existent or empty. 4. Zero value calls and zero value suicides no longer consume the 25k reation costs. params: moved core/config to params Signed-off-by: Jeffrey Wilcke <jeffrey@ethereum.org>
1 parent 932d973 commit 445feae

Some content is hidden

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

74 files changed

+717
-561
lines changed

accounts/abi/bind/backends/simulated.go

+6-3
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,12 @@ import (
3131
"github.com/ethereum/go-ethereum/core/vm"
3232
"github.com/ethereum/go-ethereum/ethdb"
3333
"github.com/ethereum/go-ethereum/event"
34+
"github.com/ethereum/go-ethereum/params"
3435
"golang.org/x/net/context"
3536
)
3637

3738
// Default chain configuration which sets homestead phase at block 0 (i.e. no frontier)
38-
var chainConfig = &core.ChainConfig{HomesteadBlock: big.NewInt(0)}
39+
var chainConfig = &params.ChainConfig{HomesteadBlock: big.NewInt(0), EIP150Block: new(big.Int), EIP158Block: new(big.Int)}
3940

4041
// This nil assignment ensures compile time that SimulatedBackend implements bind.ContractBackend.
4142
var _ bind.ContractBackend = (*SimulatedBackend)(nil)
@@ -51,6 +52,8 @@ type SimulatedBackend struct {
5152
mu sync.Mutex
5253
pendingBlock *types.Block // Currently pending block that will be imported on request
5354
pendingState *state.StateDB // Currently pending state that will be the active on on request
55+
56+
config *params.ChainConfig
5457
}
5558

5659
// NewSimulatedBackend creates a new binding backend using a simulated blockchain
@@ -85,7 +88,7 @@ func (b *SimulatedBackend) Rollback() {
8588
}
8689

8790
func (b *SimulatedBackend) rollback() {
88-
blocks, _ := core.GenerateChain(nil, b.blockchain.CurrentBlock(), b.database, 1, func(int, *core.BlockGen) {})
91+
blocks, _ := core.GenerateChain(chainConfig, b.blockchain.CurrentBlock(), b.database, 1, func(int, *core.BlockGen) {})
8992
b.pendingBlock = blocks[0]
9093
b.pendingState, _ = state.New(b.pendingBlock.Root(), b.database)
9194
}
@@ -243,7 +246,7 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa
243246
panic(fmt.Errorf("invalid transaction nonce: got %d, want %d", tx.Nonce(), nonce))
244247
}
245248

246-
blocks, _ := core.GenerateChain(nil, b.blockchain.CurrentBlock(), b.database, 1, func(number int, block *core.BlockGen) {
249+
blocks, _ := core.GenerateChain(chainConfig, b.blockchain.CurrentBlock(), b.database, 1, func(number int, block *core.BlockGen) {
247250
for _, tx := range b.pendingBlock.Transactions() {
248251
block.AddTx(tx)
249252
}

cmd/ethtest/main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ func runTestWithReader(test string, r io.Reader) error {
7676
case "bk", "block", "blocktest", "blockchaintest", "blocktests", "blockchaintests":
7777
err = tests.RunBlockTestWithReader(params.MainNetHomesteadBlock, params.MainNetDAOForkBlock, params.MainNetHomesteadGasRepriceBlock, r, skipTests)
7878
case "st", "state", "statetest", "statetests":
79-
rs := tests.RuleSet{HomesteadBlock: params.MainNetHomesteadBlock, DAOForkBlock: params.MainNetDAOForkBlock, DAOForkSupport: true}
79+
rs := &params.ChainConfig{HomesteadBlock: params.MainNetHomesteadBlock, DAOForkBlock: params.MainNetDAOForkBlock, DAOForkSupport: true, EIP150Block: params.MainNetHomesteadGasRepriceBlock}
8080
err = tests.RunStateTestWithReader(rs, r, skipTests)
8181
case "tx", "transactiontest", "transactiontests":
8282
err = tests.RunTransactionTestsWithReader(r, skipTests)

cmd/evm/main.go

+18-18
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ func run(ctx *cli.Context) error {
191191
vmdone := time.Since(tstart)
192192

193193
if ctx.GlobalBool(DumpFlag.Name) {
194-
statedb.Commit()
194+
statedb.Commit(true)
195195
fmt.Println(string(statedb.Dump()))
196196
}
197197
vm.StdErrFormat(logger.StructLogs())
@@ -251,30 +251,30 @@ func NewEnv(state *state.StateDB, transactor common.Address, value *big.Int, cfg
251251
return env
252252
}
253253

254-
// ruleSet implements vm.RuleSet and will always default to the homestead rule set.
254+
// ruleSet implements vm.ChainConfig and will always default to the homestead rule set.
255255
type ruleSet struct{}
256256

257257
func (ruleSet) IsHomestead(*big.Int) bool { return true }
258258
func (ruleSet) GasTable(*big.Int) params.GasTable {
259259
return params.GasTableHomesteadGasRepriceFork
260260
}
261261

262-
func (self *VMEnv) RuleSet() vm.RuleSet { return ruleSet{} }
263-
func (self *VMEnv) Vm() vm.Vm { return self.evm }
264-
func (self *VMEnv) Db() vm.Database { return self.state }
265-
func (self *VMEnv) SnapshotDatabase() int { return self.state.Snapshot() }
266-
func (self *VMEnv) RevertToSnapshot(snap int) { self.state.RevertToSnapshot(snap) }
267-
func (self *VMEnv) Origin() common.Address { return *self.transactor }
268-
func (self *VMEnv) BlockNumber() *big.Int { return common.Big0 }
269-
func (self *VMEnv) Coinbase() common.Address { return *self.transactor }
270-
func (self *VMEnv) Time() *big.Int { return self.time }
271-
func (self *VMEnv) Difficulty() *big.Int { return common.Big1 }
272-
func (self *VMEnv) BlockHash() []byte { return make([]byte, 32) }
273-
func (self *VMEnv) Value() *big.Int { return self.value }
274-
func (self *VMEnv) GasLimit() *big.Int { return big.NewInt(1000000000) }
275-
func (self *VMEnv) VmType() vm.Type { return vm.StdVmTy }
276-
func (self *VMEnv) Depth() int { return 0 }
277-
func (self *VMEnv) SetDepth(i int) { self.depth = i }
262+
func (self *VMEnv) ChainConfig() *params.ChainConfig { return params.TestChainConfig }
263+
func (self *VMEnv) Vm() vm.Vm { return self.evm }
264+
func (self *VMEnv) Db() vm.Database { return self.state }
265+
func (self *VMEnv) SnapshotDatabase() int { return self.state.Snapshot() }
266+
func (self *VMEnv) RevertToSnapshot(snap int) { self.state.RevertToSnapshot(snap) }
267+
func (self *VMEnv) Origin() common.Address { return *self.transactor }
268+
func (self *VMEnv) BlockNumber() *big.Int { return common.Big0 }
269+
func (self *VMEnv) Coinbase() common.Address { return *self.transactor }
270+
func (self *VMEnv) Time() *big.Int { return self.time }
271+
func (self *VMEnv) Difficulty() *big.Int { return common.Big1 }
272+
func (self *VMEnv) BlockHash() []byte { return make([]byte, 32) }
273+
func (self *VMEnv) Value() *big.Int { return self.value }
274+
func (self *VMEnv) GasLimit() *big.Int { return big.NewInt(1000000000) }
275+
func (self *VMEnv) VmType() vm.Type { return vm.StdVmTy }
276+
func (self *VMEnv) Depth() int { return 0 }
277+
func (self *VMEnv) SetDepth(i int) { self.depth = i }
278278
func (self *VMEnv) GetHash(n uint64) common.Hash {
279279
if self.block.Number().Cmp(big.NewInt(int64(n))) == 0 {
280280
return self.block.Hash()

cmd/gethrpctest/main.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323
"os"
2424
"os/signal"
2525

26-
"github.com/ethereum/go-ethereum/core"
2726
"github.com/ethereum/go-ethereum/crypto"
2827
"github.com/ethereum/go-ethereum/eth"
2928
"github.com/ethereum/go-ethereum/ethdb"
@@ -122,7 +121,7 @@ func MakeSystemNode(privkey string, test *tests.BlockTest) (*node.Node, error) {
122121
ethConf := &eth.Config{
123122
TestGenesisState: db,
124123
TestGenesisBlock: test.Genesis,
125-
ChainConfig: &core.ChainConfig{HomesteadBlock: params.MainNetHomesteadBlock},
124+
ChainConfig: &params.ChainConfig{HomesteadBlock: params.MainNetHomesteadBlock},
126125
}
127126
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { return eth.New(ctx, ethConf) }); err != nil {
128127
return nil, err

cmd/utils/flags.go

+16-15
Original file line numberDiff line numberDiff line change
@@ -801,17 +801,17 @@ func SetupNetwork(ctx *cli.Context) {
801801
}
802802

803803
// MakeChainConfig reads the chain configuration from the database in ctx.Datadir.
804-
func MakeChainConfig(ctx *cli.Context, stack *node.Node) *core.ChainConfig {
804+
func MakeChainConfig(ctx *cli.Context, stack *node.Node) *params.ChainConfig {
805805
db := MakeChainDatabase(ctx, stack)
806806
defer db.Close()
807807

808808
return MakeChainConfigFromDb(ctx, db)
809809
}
810810

811811
// MakeChainConfigFromDb reads the chain configuration from the given database.
812-
func MakeChainConfigFromDb(ctx *cli.Context, db ethdb.Database) *core.ChainConfig {
812+
func MakeChainConfigFromDb(ctx *cli.Context, db ethdb.Database) *params.ChainConfig {
813813
// If the chain is already initialized, use any existing chain configs
814-
config := new(core.ChainConfig)
814+
config := new(params.ChainConfig)
815815

816816
genesis := core.GetBlock(db, core.GetCanonicalHash(db, 0), 0)
817817
if genesis != nil {
@@ -849,19 +849,20 @@ func MakeChainConfigFromDb(ctx *cli.Context, db ethdb.Database) *core.ChainConfi
849849
}
850850
config.DAOForkSupport = true
851851
}
852-
if config.HomesteadGasRepriceBlock == nil {
853-
if ctx.GlobalBool(TestNetFlag.Name) {
854-
config.HomesteadGasRepriceBlock = params.TestNetHomesteadGasRepriceBlock
855-
} else {
856-
config.HomesteadGasRepriceBlock = params.MainNetHomesteadGasRepriceBlock
857-
}
852+
config.DAOForkSupport = true
853+
}
854+
if config.EIP150Block == nil {
855+
if ctx.GlobalBool(TestNetFlag.Name) {
856+
config.EIP150Block = params.TestNetHomesteadGasRepriceBlock
857+
} else {
858+
config.EIP150Block = params.MainNetHomesteadGasRepriceBlock
858859
}
859-
if config.HomesteadGasRepriceHash == (common.Hash{}) {
860-
if ctx.GlobalBool(TestNetFlag.Name) {
861-
config.HomesteadGasRepriceHash = params.TestNetHomesteadGasRepriceHash
862-
} else {
863-
config.HomesteadGasRepriceHash = params.MainNetHomesteadGasRepriceHash
864-
}
860+
}
861+
if config.EIP150Hash == (common.Hash{}) {
862+
if ctx.GlobalBool(TestNetFlag.Name) {
863+
config.EIP150Hash = params.TestNetHomesteadGasRepriceHash
864+
} else {
865+
config.EIP150Hash = params.MainNetHomesteadGasRepriceHash
865866
}
866867
}
867868
// Force override any existing configs if explicitly requested

common/registrar/ethreg/api.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,12 @@ import (
3232
"github.com/ethereum/go-ethereum/ethdb"
3333
"github.com/ethereum/go-ethereum/logger"
3434
"github.com/ethereum/go-ethereum/logger/glog"
35+
"github.com/ethereum/go-ethereum/params"
3536
)
3637

3738
// registryAPIBackend is a backend for an Ethereum Registry.
3839
type registryAPIBackend struct {
39-
config *core.ChainConfig
40+
config *params.ChainConfig
4041
bc *core.BlockChain
4142
chainDb ethdb.Database
4243
txPool *core.TxPool
@@ -45,12 +46,12 @@ type registryAPIBackend struct {
4546

4647
// PrivateRegistarAPI offers various functions to access the Ethereum registry.
4748
type PrivateRegistarAPI struct {
48-
config *core.ChainConfig
49+
config *params.ChainConfig
4950
be *registryAPIBackend
5051
}
5152

5253
// NewPrivateRegistarAPI creates a new PrivateRegistarAPI instance.
53-
func NewPrivateRegistarAPI(config *core.ChainConfig, bc *core.BlockChain, chainDb ethdb.Database, txPool *core.TxPool, am *accounts.Manager) *PrivateRegistarAPI {
54+
func NewPrivateRegistarAPI(config *params.ChainConfig, bc *core.BlockChain, chainDb ethdb.Database, txPool *core.TxPool, am *accounts.Manager) *PrivateRegistarAPI {
5455
return &PrivateRegistarAPI{
5556
config: config,
5657
be: &registryAPIBackend{

console/console_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ import (
2828
"time"
2929

3030
"github.com/ethereum/go-ethereum/common"
31-
"github.com/ethereum/go-ethereum/core"
3231
"github.com/ethereum/go-ethereum/eth"
3332
"github.com/ethereum/go-ethereum/internal/jsre"
3433
"github.com/ethereum/go-ethereum/node"
34+
"github.com/ethereum/go-ethereum/params"
3535
)
3636

3737
const (
@@ -97,7 +97,7 @@ func newTester(t *testing.T, confOverride func(*eth.Config)) *tester {
9797
t.Fatalf("failed to create node: %v", err)
9898
}
9999
ethConf := &eth.Config{
100-
ChainConfig: &core.ChainConfig{HomesteadBlock: new(big.Int)},
100+
ChainConfig: &params.ChainConfig{HomesteadBlock: new(big.Int)},
101101
Etherbase: common.HexToAddress(testAddress),
102102
PowTest: true,
103103
}

core/bench_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -163,12 +163,12 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
163163
// Generate a chain of b.N blocks using the supplied block
164164
// generator function.
165165
genesis := WriteGenesisBlockForTesting(db, GenesisAccount{benchRootAddr, benchRootFunds})
166-
chain, _ := GenerateChain(nil, genesis, db, b.N, gen)
166+
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, b.N, gen)
167167

168168
// Time the insertion of the new chain.
169169
// State and blocks are stored in the same DB.
170170
evmux := new(event.TypeMux)
171-
chainman, _ := NewBlockChain(db, &ChainConfig{HomesteadBlock: new(big.Int)}, FakePow{}, evmux)
171+
chainman, _ := NewBlockChain(db, &params.ChainConfig{HomesteadBlock: new(big.Int)}, FakePow{}, evmux)
172172
defer chainman.Stop()
173173
b.ReportAllocs()
174174
b.ResetTimer()

core/block_validator.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,13 @@ var (
4141
//
4242
// BlockValidator implements Validator.
4343
type BlockValidator struct {
44-
config *ChainConfig // Chain configuration options
45-
bc *BlockChain // Canonical block chain
46-
Pow pow.PoW // Proof of work used for validating
44+
config *params.ChainConfig // Chain configuration options
45+
bc *BlockChain // Canonical block chain
46+
Pow pow.PoW // Proof of work used for validating
4747
}
4848

4949
// NewBlockValidator returns a new block validator which is safe for re-use
50-
func NewBlockValidator(config *ChainConfig, blockchain *BlockChain, pow pow.PoW) *BlockValidator {
50+
func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain, pow pow.PoW) *BlockValidator {
5151
validator := &BlockValidator{
5252
config: config,
5353
Pow: pow,
@@ -128,7 +128,7 @@ func (v *BlockValidator) ValidateState(block, parent *types.Block, statedb *stat
128128
}
129129
// Validate the state root against the received state root and throw
130130
// an error if they don't match.
131-
if root := statedb.IntermediateRoot(); header.Root != root {
131+
if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root {
132132
return fmt.Errorf("invalid merkle root: header=%x computed=%x", header.Root, root)
133133
}
134134
return nil
@@ -203,7 +203,7 @@ func (v *BlockValidator) ValidateHeader(header, parent *types.Header, checkPow b
203203
// Validates a header. Returns an error if the header is invalid.
204204
//
205205
// See YP section 4.3.4. "Block Header Validity"
206-
func ValidateHeader(config *ChainConfig, pow pow.PoW, header *types.Header, parent *types.Header, checkPow, uncle bool) error {
206+
func ValidateHeader(config *params.ChainConfig, pow pow.PoW, header *types.Header, parent *types.Header, checkPow, uncle bool) error {
207207
if big.NewInt(int64(len(header.Extra))).Cmp(params.MaximumExtraDataSize) == 1 {
208208
return fmt.Errorf("Header extra data too long (%d)", len(header.Extra))
209209
}
@@ -251,9 +251,9 @@ func ValidateHeader(config *ChainConfig, pow pow.PoW, header *types.Header, pare
251251
if err := ValidateDAOHeaderExtraData(config, header); err != nil {
252252
return err
253253
}
254-
if config.HomesteadGasRepriceBlock != nil && config.HomesteadGasRepriceBlock.Cmp(header.Number) == 0 {
255-
if config.HomesteadGasRepriceHash != (common.Hash{}) && config.HomesteadGasRepriceHash != header.Hash() {
256-
return ValidationError("Homestead gas reprice fork hash mismatch: have 0x%x, want 0x%x", header.Hash(), config.HomesteadGasRepriceHash)
254+
if config.EIP150Block != nil && config.EIP150Block.Cmp(header.Number) == 0 {
255+
if config.EIP150Hash != (common.Hash{}) && config.EIP150Hash != header.Hash() {
256+
return ValidationError("Homestead gas reprice fork hash mismatch: have 0x%x, want 0x%x", header.Hash(), config.EIP150Hash)
257257
}
258258
}
259259
return nil
@@ -262,7 +262,7 @@ func ValidateHeader(config *ChainConfig, pow pow.PoW, header *types.Header, pare
262262
// CalcDifficulty is the difficulty adjustment algorithm. It returns
263263
// the difficulty that a new block should have when created at time
264264
// given the parent block's time and difficulty.
265-
func CalcDifficulty(config *ChainConfig, time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
265+
func CalcDifficulty(config *params.ChainConfig, time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
266266
if config.IsHomestead(new(big.Int).Add(parentNumber, common.Big1)) {
267267
return calcDifficultyHomestead(time, parentTime, parentNumber, parentDiff)
268268
} else {

core/block_validator_test.go

+7-5
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,13 @@ import (
2727
"github.com/ethereum/go-ethereum/core/vm"
2828
"github.com/ethereum/go-ethereum/ethdb"
2929
"github.com/ethereum/go-ethereum/event"
30+
"github.com/ethereum/go-ethereum/params"
3031
"github.com/ethereum/go-ethereum/pow/ezp"
3132
)
3233

33-
func testChainConfig() *ChainConfig {
34-
return &ChainConfig{HomesteadBlock: big.NewInt(0)}
34+
func testChainConfig() *params.ChainConfig {
35+
return params.TestChainConfig
36+
//return &params.ChainConfig{HomesteadBlock: big.NewInt(0)}
3537
}
3638

3739
func proc() (Validator, *BlockChain) {
@@ -51,15 +53,15 @@ func TestNumber(t *testing.T) {
5153
_, chain := proc()
5254

5355
statedb, _ := state.New(chain.Genesis().Root(), chain.chainDb)
54-
header := makeHeader(chain.Genesis(), statedb)
55-
header.Number = big.NewInt(3)
5656
cfg := testChainConfig()
57+
header := makeHeader(cfg, chain.Genesis(), statedb)
58+
header.Number = big.NewInt(3)
5759
err := ValidateHeader(cfg, pow, header, chain.Genesis().Header(), false, false)
5860
if err != BlockNumberErr {
5961
t.Errorf("expected block number error, got %q", err)
6062
}
6163

62-
header = makeHeader(chain.Genesis(), statedb)
64+
header = makeHeader(cfg, chain.Genesis(), statedb)
6365
err = ValidateHeader(cfg, pow, header, chain.Genesis().Header(), false, false)
6466
if err == BlockNumberErr {
6567
t.Errorf("didn't expect block number error")

core/blockchain.go

+6-5
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import (
3838
"github.com/ethereum/go-ethereum/logger"
3939
"github.com/ethereum/go-ethereum/logger/glog"
4040
"github.com/ethereum/go-ethereum/metrics"
41+
"github.com/ethereum/go-ethereum/params"
4142
"github.com/ethereum/go-ethereum/pow"
4243
"github.com/ethereum/go-ethereum/rlp"
4344
"github.com/ethereum/go-ethereum/trie"
@@ -78,7 +79,7 @@ const (
7879
// included in the canonical one where as GetBlockByNumber always represents the
7980
// canonical chain.
8081
type BlockChain struct {
81-
config *ChainConfig // chain & network configuration
82+
config *params.ChainConfig // chain & network configuration
8283

8384
hc *HeaderChain
8485
chainDb ethdb.Database
@@ -113,7 +114,7 @@ type BlockChain struct {
113114
// NewBlockChain returns a fully initialised block chain using information
114115
// available in the database. It initialiser the default Ethereum Validator and
115116
// Processor.
116-
func NewBlockChain(chainDb ethdb.Database, config *ChainConfig, pow pow.PoW, mux *event.TypeMux) (*BlockChain, error) {
117+
func NewBlockChain(chainDb ethdb.Database, config *params.ChainConfig, pow pow.PoW, mux *event.TypeMux) (*BlockChain, error) {
117118
bodyCache, _ := lru.New(bodyCacheLimit)
118119
bodyRLPCache, _ := lru.New(bodyCacheLimit)
119120
blockCache, _ := lru.New(blockCacheLimit)
@@ -924,7 +925,7 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
924925
return i, err
925926
}
926927
// Process block using the parent state as reference point.
927-
receipts, logs, usedGas, err := self.processor.Process(block, self.stateCache, self.config.VmConfig)
928+
receipts, logs, usedGas, err := self.processor.Process(block, self.stateCache, vm.Config{})
928929
if err != nil {
929930
reportBlock(block, err)
930931
return i, err
@@ -936,7 +937,7 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
936937
return i, err
937938
}
938939
// Write state changes to database
939-
_, err = self.stateCache.Commit()
940+
_, err = self.stateCache.Commit(self.config.IsEIP158(block.Number()))
940941
if err != nil {
941942
return i, err
942943
}
@@ -1309,4 +1310,4 @@ func (self *BlockChain) GetHeaderByNumber(number uint64) *types.Header {
13091310
}
13101311

13111312
// Config retrieves the blockchain's chain configuration.
1312-
func (self *BlockChain) Config() *ChainConfig { return self.config }
1313+
func (self *BlockChain) Config() *params.ChainConfig { return self.config }

0 commit comments

Comments
 (0)