aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/bench_test.go4
-rw-r--r--core/block_validator_test.go8
-rw-r--r--core/blockchain.go73
-rw-r--r--core/blockchain_test.go32
-rw-r--r--core/chain_makers.go2
-rw-r--r--core/chain_makers_test.go2
-rw-r--r--core/dao_test.go12
-rw-r--r--core/genesis.go2
-rw-r--r--core/genesis_test.go2
-rw-r--r--core/headerchain.go14
-rw-r--r--core/state/state_object.go44
-rw-r--r--core/state/state_test.go58
-rw-r--r--core/state/statedb.go38
-rw-r--r--core/state/statedb_test.go8
-rw-r--r--core/tx_pool.go4
-rw-r--r--core/vm/evm.go22
-rw-r--r--core/vm/gas_table.go77
-rw-r--r--core/vm/instructions.go2
-rw-r--r--core/vm/interface.go2
-rw-r--r--core/vm/interpreter.go5
-rw-r--r--core/vm/logger_test.go5
-rw-r--r--core/vm/memory.go2
-rw-r--r--core/vm/noop.go70
23 files changed, 283 insertions, 205 deletions
diff --git a/core/bench_test.go b/core/bench_test.go
index 8d95456e9..53cba0517 100644
--- a/core/bench_test.go
+++ b/core/bench_test.go
@@ -175,7 +175,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
// Time the insertion of the new chain.
// State and blocks are stored in the same DB.
- chainman, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
+ chainman, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil)
defer chainman.Stop()
b.ReportAllocs()
b.ResetTimer()
@@ -287,7 +287,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
if err != nil {
b.Fatalf("error opening database at %v: %v", dir, err)
}
- chain, err := NewBlockChain(db, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{})
+ chain, err := NewBlockChain(db, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil)
if err != nil {
b.Fatalf("error creating chain: %v", err)
}
diff --git a/core/block_validator_test.go b/core/block_validator_test.go
index 2a171218e..9319a7835 100644
--- a/core/block_validator_test.go
+++ b/core/block_validator_test.go
@@ -42,7 +42,7 @@ func TestHeaderVerification(t *testing.T) {
headers[i] = block.Header()
}
// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces
- chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{})
+ chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil)
defer chain.Stop()
for i := 0; i < len(blocks); i++ {
@@ -106,11 +106,11 @@ func testHeaderConcurrentVerification(t *testing.T, threads int) {
var results <-chan error
if valid {
- chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{})
+ chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil)
_, results = chain.engine.VerifyHeaders(chain, headers, seals)
chain.Stop()
} else {
- chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeFailer(uint64(len(headers)-1)), vm.Config{})
+ chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeFailer(uint64(len(headers)-1)), vm.Config{}, nil)
_, results = chain.engine.VerifyHeaders(chain, headers, seals)
chain.Stop()
}
@@ -173,7 +173,7 @@ func testHeaderConcurrentAbortion(t *testing.T, threads int) {
defer runtime.GOMAXPROCS(old)
// Start the verifications and immediately abort
- chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeDelayer(time.Millisecond), vm.Config{})
+ chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeDelayer(time.Millisecond), vm.Config{}, nil)
defer chain.Stop()
abort, results := chain.engine.VerifyHeaders(chain, headers, seals)
diff --git a/core/blockchain.go b/core/blockchain.go
index 63f60ca28..fe961e0c4 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -128,13 +128,14 @@ type BlockChain struct {
validator Validator // block and state validator interface
vmConfig vm.Config
- badBlocks *lru.Cache // Bad block cache
+ badBlocks *lru.Cache // Bad block cache
+ shouldPreserve func(*types.Block) bool // Function used to determine whether should preserve the given block.
}
// NewBlockChain returns a fully initialised block chain using information
// available in the database. It initialises the default Ethereum Validator and
// Processor.
-func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, engine consensus.Engine, vmConfig vm.Config) (*BlockChain, error) {
+func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, engine consensus.Engine, vmConfig vm.Config, shouldPreserve func(block *types.Block) bool) (*BlockChain, error) {
if cacheConfig == nil {
cacheConfig = &CacheConfig{
TrieNodeLimit: 256 * 1024 * 1024,
@@ -148,19 +149,20 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
badBlocks, _ := lru.New(badBlockLimit)
bc := &BlockChain{
- chainConfig: chainConfig,
- cacheConfig: cacheConfig,
- db: db,
- triegc: prque.New(nil),
- stateCache: state.NewDatabase(db),
- quit: make(chan struct{}),
- bodyCache: bodyCache,
- bodyRLPCache: bodyRLPCache,
- blockCache: blockCache,
- futureBlocks: futureBlocks,
- engine: engine,
- vmConfig: vmConfig,
- badBlocks: badBlocks,
+ chainConfig: chainConfig,
+ cacheConfig: cacheConfig,
+ db: db,
+ triegc: prque.New(nil),
+ stateCache: state.NewDatabase(db),
+ quit: make(chan struct{}),
+ shouldPreserve: shouldPreserve,
+ bodyCache: bodyCache,
+ bodyRLPCache: bodyRLPCache,
+ blockCache: blockCache,
+ futureBlocks: futureBlocks,
+ engine: engine,
+ vmConfig: vmConfig,
+ badBlocks: badBlocks,
}
bc.SetValidator(NewBlockValidator(chainConfig, bc, engine))
bc.SetProcessor(NewStateProcessor(chainConfig, bc, engine))
@@ -251,9 +253,9 @@ func (bc *BlockChain) loadLastState() error {
blockTd := bc.GetTd(currentBlock.Hash(), currentBlock.NumberU64())
fastTd := bc.GetTd(currentFastBlock.Hash(), currentFastBlock.NumberU64())
- log.Info("Loaded most recent local header", "number", currentHeader.Number, "hash", currentHeader.Hash(), "td", headerTd)
- log.Info("Loaded most recent local full block", "number", currentBlock.Number(), "hash", currentBlock.Hash(), "td", blockTd)
- log.Info("Loaded most recent local fast block", "number", currentFastBlock.Number(), "hash", currentFastBlock.Hash(), "td", fastTd)
+ log.Info("Loaded most recent local header", "number", currentHeader.Number, "hash", currentHeader.Hash(), "td", headerTd, "age", common.PrettyAge(time.Unix(currentHeader.Time.Int64(), 0)))
+ log.Info("Loaded most recent local full block", "number", currentBlock.Number(), "hash", currentBlock.Hash(), "td", blockTd, "age", common.PrettyAge(time.Unix(currentBlock.Time().Int64(), 0)))
+ log.Info("Loaded most recent local fast block", "number", currentFastBlock.Number(), "hash", currentFastBlock.Hash(), "td", fastTd, "age", common.PrettyAge(time.Unix(currentFastBlock.Time().Int64(), 0)))
return nil
}
@@ -850,13 +852,16 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
}
bc.mu.Unlock()
- log.Info("Imported new block receipts",
- "count", stats.processed,
- "elapsed", common.PrettyDuration(time.Since(start)),
- "number", head.Number(),
- "hash", head.Hash(),
+ context := []interface{}{
+ "count", stats.processed, "elapsed", common.PrettyDuration(time.Since(start)),
+ "number", head.Number(), "hash", head.Hash(), "age", common.PrettyAge(time.Unix(head.Time().Int64(), 0)),
"size", common.StorageSize(bytes),
- "ignored", stats.ignored)
+ }
+ if stats.ignored > 0 {
+ context = append(context, []interface{}{"ignored", stats.ignored}...)
+ }
+ log.Info("Imported new block receipts", context...)
+
return 0, nil
}
@@ -964,8 +969,17 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types.
reorg := externTd.Cmp(localTd) > 0
currentBlock = bc.CurrentBlock()
if !reorg && externTd.Cmp(localTd) == 0 {
- // Split same-difficulty blocks by number, then at random
- reorg = block.NumberU64() < currentBlock.NumberU64() || (block.NumberU64() == currentBlock.NumberU64() && mrand.Float64() < 0.5)
+ // Split same-difficulty blocks by number, then preferentially select
+ // the block generated by the local miner as the canonical block.
+ if block.NumberU64() < currentBlock.NumberU64() {
+ reorg = true
+ } else if block.NumberU64() == currentBlock.NumberU64() {
+ var currentPreserve, blockPreserve bool
+ if bc.shouldPreserve != nil {
+ currentPreserve, blockPreserve = bc.shouldPreserve(currentBlock), bc.shouldPreserve(block)
+ }
+ reorg = !currentPreserve && (blockPreserve || mrand.Float64() < 0.5)
+ }
}
if reorg {
// Reorganise the chain if the parent is not the head block
@@ -1229,8 +1243,13 @@ func (st *insertStats) report(chain []*types.Block, index int, cache common.Stor
context := []interface{}{
"blocks", st.processed, "txs", txs, "mgas", float64(st.usedGas) / 1000000,
"elapsed", common.PrettyDuration(elapsed), "mgasps", float64(st.usedGas) * 1000 / float64(elapsed),
- "number", end.Number(), "hash", end.Hash(), "cache", cache,
+ "number", end.Number(), "hash", end.Hash(),
+ }
+ if timestamp := time.Unix(end.Time().Int64(), 0); time.Since(timestamp) > time.Minute {
+ context = append(context, []interface{}{"age", common.PrettyAge(timestamp)}...)
}
+ context = append(context, []interface{}{"cache", cache}...)
+
if st.queued > 0 {
context = append(context, []interface{}{"queued", st.queued}...)
}
diff --git a/core/blockchain_test.go b/core/blockchain_test.go
index e452d6936..aef810050 100644
--- a/core/blockchain_test.go
+++ b/core/blockchain_test.go
@@ -52,7 +52,7 @@ func newCanonical(engine consensus.Engine, n int, full bool) (ethdb.Database, *B
)
// Initialize a fresh chain with only a genesis block
- blockchain, _ := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{})
+ blockchain, _ := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil)
// Create and inject the requested chain
if n == 0 {
return db, blockchain, nil
@@ -523,7 +523,7 @@ func testReorgBadHashes(t *testing.T, full bool) {
blockchain.Stop()
// Create a new BlockChain and check that it rolled back the state.
- ncm, err := NewBlockChain(blockchain.db, nil, blockchain.chainConfig, ethash.NewFaker(), vm.Config{})
+ ncm, err := NewBlockChain(blockchain.db, nil, blockchain.chainConfig, ethash.NewFaker(), vm.Config{}, nil)
if err != nil {
t.Fatalf("failed to create new chain manager: %v", err)
}
@@ -635,7 +635,7 @@ func TestFastVsFullChains(t *testing.T) {
// Import the chain as an archive node for the comparison baseline
archiveDb := ethdb.NewMemDatabase()
gspec.MustCommit(archiveDb)
- archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
+ archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil)
defer archive.Stop()
if n, err := archive.InsertChain(blocks); err != nil {
@@ -644,7 +644,7 @@ func TestFastVsFullChains(t *testing.T) {
// Fast import the chain as a non-archive node to test
fastDb := ethdb.NewMemDatabase()
gspec.MustCommit(fastDb)
- fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
+ fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil)
defer fast.Stop()
headers := make([]*types.Header, len(blocks))
@@ -722,7 +722,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
archiveDb := ethdb.NewMemDatabase()
gspec.MustCommit(archiveDb)
- archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
+ archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil)
if n, err := archive.InsertChain(blocks); err != nil {
t.Fatalf("failed to process block %d: %v", n, err)
}
@@ -735,7 +735,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
// Import the chain as a non-archive node and ensure all pointers are updated
fastDb := ethdb.NewMemDatabase()
gspec.MustCommit(fastDb)
- fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
+ fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil)
defer fast.Stop()
headers := make([]*types.Header, len(blocks))
@@ -756,7 +756,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
lightDb := ethdb.NewMemDatabase()
gspec.MustCommit(lightDb)
- light, _ := NewBlockChain(lightDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
+ light, _ := NewBlockChain(lightDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil)
if n, err := light.InsertHeaderChain(headers, 1); err != nil {
t.Fatalf("failed to insert header %d: %v", n, err)
}
@@ -825,7 +825,7 @@ func TestChainTxReorgs(t *testing.T) {
}
})
// Import the chain. This runs all block validation rules.
- blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
+ blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil)
if i, err := blockchain.InsertChain(chain); err != nil {
t.Fatalf("failed to insert original chain[%d]: %v", i, err)
}
@@ -896,7 +896,7 @@ func TestLogReorgs(t *testing.T) {
signer = types.NewEIP155Signer(gspec.Config.ChainID)
)
- blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
+ blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil)
defer blockchain.Stop()
rmLogsCh := make(chan RemovedLogsEvent)
@@ -943,7 +943,7 @@ func TestReorgSideEvent(t *testing.T) {
signer = types.NewEIP155Signer(gspec.Config.ChainID)
)
- blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
+ blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil)
defer blockchain.Stop()
chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {})
@@ -1072,7 +1072,7 @@ func TestEIP155Transition(t *testing.T) {
genesis = gspec.MustCommit(db)
)
- blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
+ blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil)
defer blockchain.Stop()
blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, block *BlockGen) {
@@ -1179,7 +1179,7 @@ func TestEIP161AccountRemoval(t *testing.T) {
}
genesis = gspec.MustCommit(db)
)
- blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
+ blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil)
defer blockchain.Stop()
blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, block *BlockGen) {
@@ -1254,7 +1254,7 @@ func TestBlockchainHeaderchainReorgConsistency(t *testing.T) {
diskdb := ethdb.NewMemDatabase()
new(Genesis).MustCommit(diskdb)
- chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{})
+ chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@@ -1298,7 +1298,7 @@ func TestTrieForkGC(t *testing.T) {
diskdb := ethdb.NewMemDatabase()
new(Genesis).MustCommit(diskdb)
- chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{})
+ chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@@ -1337,7 +1337,7 @@ func TestLargeReorgTrieGC(t *testing.T) {
diskdb := ethdb.NewMemDatabase()
new(Genesis).MustCommit(diskdb)
- chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{})
+ chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
@@ -1419,7 +1419,7 @@ func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks in
diskdb := ethdb.NewMemDatabase()
gspec.MustCommit(diskdb)
- chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{})
+ chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil)
if err != nil {
b.Fatalf("failed to create tester chain: %v", err)
}
diff --git a/core/chain_makers.go b/core/chain_makers.go
index 351673477..0bc453fdf 100644
--- a/core/chain_makers.go
+++ b/core/chain_makers.go
@@ -177,7 +177,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
genblock := func(i int, parent *types.Block, statedb *state.StateDB) (*types.Block, types.Receipts) {
// TODO(karalabe): This is needed for clique, which depends on multiple blocks.
// It's nonetheless ugly to spin up a blockchain here. Get rid of this somehow.
- blockchain, _ := NewBlockChain(db, nil, config, engine, vm.Config{})
+ blockchain, _ := NewBlockChain(db, nil, config, engine, vm.Config{}, nil)
defer blockchain.Stop()
b := &BlockGen{i: i, parent: parent, chain: blocks, chainReader: blockchain, statedb: statedb, config: config, engine: engine}
diff --git a/core/chain_makers_test.go b/core/chain_makers_test.go
index 5015d1f48..64b64fd6a 100644
--- a/core/chain_makers_test.go
+++ b/core/chain_makers_test.go
@@ -79,7 +79,7 @@ func ExampleGenerateChain() {
})
// Import the chain. This runs all block validation rules.
- blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{})
+ blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil)
defer blockchain.Stop()
if i, err := blockchain.InsertChain(chain); err != nil {
diff --git a/core/dao_test.go b/core/dao_test.go
index 284b1d98b..966139bce 100644
--- a/core/dao_test.go
+++ b/core/dao_test.go
@@ -45,7 +45,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
proConf.DAOForkBlock = forkBlock
proConf.DAOForkSupport = true
- proBc, _ := NewBlockChain(proDb, nil, &proConf, ethash.NewFaker(), vm.Config{})
+ proBc, _ := NewBlockChain(proDb, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil)
defer proBc.Stop()
conDb := ethdb.NewMemDatabase()
@@ -55,7 +55,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
conConf.DAOForkBlock = forkBlock
conConf.DAOForkSupport = false
- conBc, _ := NewBlockChain(conDb, nil, &conConf, ethash.NewFaker(), vm.Config{})
+ conBc, _ := NewBlockChain(conDb, nil, &conConf, ethash.NewFaker(), vm.Config{}, nil)
defer conBc.Stop()
if _, err := proBc.InsertChain(prefix); err != nil {
@@ -69,7 +69,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
// Create a pro-fork block, and try to feed into the no-fork chain
db = ethdb.NewMemDatabase()
gspec.MustCommit(db)
- bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{})
+ bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{}, nil)
defer bc.Stop()
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64()))
@@ -94,7 +94,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
// Create a no-fork block, and try to feed into the pro-fork chain
db = ethdb.NewMemDatabase()
gspec.MustCommit(db)
- bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{})
+ bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil)
defer bc.Stop()
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64()))
@@ -120,7 +120,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
// Verify that contra-forkers accept pro-fork extra-datas after forking finishes
db = ethdb.NewMemDatabase()
gspec.MustCommit(db)
- bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{})
+ bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{}, nil)
defer bc.Stop()
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64()))
@@ -140,7 +140,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
// Verify that pro-forkers accept contra-fork extra-datas after forking finishes
db = ethdb.NewMemDatabase()
gspec.MustCommit(db)
- bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{})
+ bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil)
defer bc.Stop()
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64()))
diff --git a/core/genesis.go b/core/genesis.go
index 9190e2ba2..6e71afd61 100644
--- a/core/genesis.go
+++ b/core/genesis.go
@@ -355,7 +355,7 @@ func DeveloperGenesisBlock(period uint64, faucet common.Address) *Genesis {
common.BytesToAddress([]byte{6}): {Balance: big.NewInt(1)}, // ECAdd
common.BytesToAddress([]byte{7}): {Balance: big.NewInt(1)}, // ECScalarMul
common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, // ECPairing
- faucet: {Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(9))},
+ faucet: {Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(9))},
},
}
}
diff --git a/core/genesis_test.go b/core/genesis_test.go
index 2d7f94f8f..c7d54f205 100644
--- a/core/genesis_test.go
+++ b/core/genesis_test.go
@@ -120,7 +120,7 @@ func TestSetupGenesis(t *testing.T) {
// Advance to block #4, past the homestead transition block of customg.
genesis := oldcustomg.MustCommit(db)
- bc, _ := NewBlockChain(db, nil, oldcustomg.Config, ethash.NewFullFaker(), vm.Config{})
+ bc, _ := NewBlockChain(db, nil, oldcustomg.Config, ethash.NewFullFaker(), vm.Config{}, nil)
defer bc.Stop()
blocks, _ := GenerateChain(oldcustomg.Config, genesis, ethash.NewFaker(), db, 4, nil)
diff --git a/core/headerchain.go b/core/headerchain.go
index 2bbec28bf..d2093113c 100644
--- a/core/headerchain.go
+++ b/core/headerchain.go
@@ -281,8 +281,18 @@ func (hc *HeaderChain) InsertHeaderChain(chain []*types.Header, writeHeader WhCa
}
// Report some public statistics so the user has a clue what's going on
last := chain[len(chain)-1]
- log.Info("Imported new block headers", "count", stats.processed, "elapsed", common.PrettyDuration(time.Since(start)),
- "number", last.Number, "hash", last.Hash(), "ignored", stats.ignored)
+
+ context := []interface{}{
+ "count", stats.processed, "elapsed", common.PrettyDuration(time.Since(start)),
+ "number", last.Number, "hash", last.Hash(),
+ }
+ if timestamp := time.Unix(last.Time.Int64(), 0); time.Since(timestamp) > time.Minute {
+ context = append(context, []interface{}{"age", common.PrettyAge(timestamp)}...)
+ }
+ if stats.ignored > 0 {
+ context = append(context, []interface{}{"ignored", stats.ignored}...)
+ }
+ log.Info("Imported new block headers", context...)
return 0, nil
}
diff --git a/core/state/state_object.go b/core/state/state_object.go
index 091d24184..f41ab0409 100644
--- a/core/state/state_object.go
+++ b/core/state/state_object.go
@@ -77,7 +77,7 @@ type stateObject struct {
trie Trie // storage trie, which becomes non-nil on first access
code Code // contract bytecode, which gets set when code is loaded
- cachedStorage Storage // Storage entry cache to avoid duplicate reads
+ originStorage Storage // Storage cache of original entries to dedup rewrites
dirtyStorage Storage // Storage entries that need to be flushed to disk
// Cache flags.
@@ -115,7 +115,7 @@ func newObject(db *StateDB, address common.Address, data Account) *stateObject {
address: address,
addrHash: crypto.Keccak256Hash(address[:]),
data: data,
- cachedStorage: make(Storage),
+ originStorage: make(Storage),
dirtyStorage: make(Storage),
}
}
@@ -159,13 +159,25 @@ func (c *stateObject) getTrie(db Database) Trie {
return c.trie
}
-// GetState returns a value in account storage.
+// GetState retrieves a value from the account storage trie.
func (self *stateObject) GetState(db Database, key common.Hash) common.Hash {
- value, exists := self.cachedStorage[key]
- if exists {
+ // If we have a dirty value for this state entry, return it
+ value, dirty := self.dirtyStorage[key]
+ if dirty {
return value
}
- // Load from DB in case it is missing.
+ // Otherwise return the entry's original value
+ return self.GetCommittedState(db, key)
+}
+
+// GetCommittedState retrieves a value from the committed account storage trie.
+func (self *stateObject) GetCommittedState(db Database, key common.Hash) common.Hash {
+ // If we have the original value cached, return that
+ value, cached := self.originStorage[key]
+ if cached {
+ return value
+ }
+ // Otherwise load the value from the database
enc, err := self.getTrie(db).TryGet(key[:])
if err != nil {
self.setError(err)
@@ -178,22 +190,27 @@ func (self *stateObject) GetState(db Database, key common.Hash) common.Hash {
}
value.SetBytes(content)
}
- self.cachedStorage[key] = value
+ self.originStorage[key] = value
return value
}
// SetState updates a value in account storage.
func (self *stateObject) SetState(db Database, key, value common.Hash) {
+ // If the new value is the same as old, don't set
+ prev := self.GetState(db, key)
+ if prev == value {
+ return
+ }
+ // New value is different, update and journal the change
self.db.journal.append(storageChange{
account: &self.address,
key: key,
- prevalue: self.GetState(db, key),
+ prevalue: prev,
})
self.setState(key, value)
}
func (self *stateObject) setState(key, value common.Hash) {
- self.cachedStorage[key] = value
self.dirtyStorage[key] = value
}
@@ -202,6 +219,13 @@ func (self *stateObject) updateTrie(db Database) Trie {
tr := self.getTrie(db)
for key, value := range self.dirtyStorage {
delete(self.dirtyStorage, key)
+
+ // Skip noop changes, persist actual changes
+ if value == self.originStorage[key] {
+ continue
+ }
+ self.originStorage[key] = value
+
if (value == common.Hash{}) {
self.setError(tr.TryDelete(key[:]))
continue
@@ -279,7 +303,7 @@ func (self *stateObject) deepCopy(db *StateDB) *stateObject {
}
stateObject.code = self.code
stateObject.dirtyStorage = self.dirtyStorage.Copy()
- stateObject.cachedStorage = self.dirtyStorage.Copy()
+ stateObject.originStorage = self.originStorage.Copy()
stateObject.suicided = self.suicided
stateObject.dirtyCode = self.dirtyCode
stateObject.deleted = self.deleted
diff --git a/core/state/state_test.go b/core/state/state_test.go
index 123559ea9..a09273f3b 100644
--- a/core/state/state_test.go
+++ b/core/state/state_test.go
@@ -96,11 +96,15 @@ func (s *StateSuite) TestNull(c *checker.C) {
s.state.CreateAccount(address)
//value := common.FromHex("0x823140710bf13990e4500136726d8b55")
var value common.Hash
+
s.state.SetState(address, common.Hash{}, value)
s.state.Commit(false)
- value = s.state.GetState(address, common.Hash{})
- if value != (common.Hash{}) {
- c.Errorf("expected empty hash. got %x", value)
+
+ if value := s.state.GetState(address, common.Hash{}); value != (common.Hash{}) {
+ c.Errorf("expected empty current value, got %x", value)
+ }
+ if value := s.state.GetCommittedState(address, common.Hash{}); value != (common.Hash{}) {
+ c.Errorf("expected empty committed value, got %x", value)
}
}
@@ -110,20 +114,24 @@ func (s *StateSuite) TestSnapshot(c *checker.C) {
data1 := common.BytesToHash([]byte{42})
data2 := common.BytesToHash([]byte{43})
+ // snapshot the genesis state
+ genesis := s.state.Snapshot()
+
// set initial state object value
s.state.SetState(stateobjaddr, storageaddr, data1)
- // get snapshot of current state
snapshot := s.state.Snapshot()
- // set new state object value
+ // set a new state object value, revert it and ensure correct content
s.state.SetState(stateobjaddr, storageaddr, data2)
- // restore snapshot
s.state.RevertToSnapshot(snapshot)
- // get state storage value
- res := s.state.GetState(stateobjaddr, storageaddr)
+ c.Assert(s.state.GetState(stateobjaddr, storageaddr), checker.DeepEquals, data1)
+ c.Assert(s.state.GetCommittedState(stateobjaddr, storageaddr), checker.DeepEquals, common.Hash{})
- c.Assert(data1, checker.DeepEquals, res)
+ // revert up to the genesis state and ensure correct content
+ s.state.RevertToSnapshot(genesis)
+ c.Assert(s.state.GetState(stateobjaddr, storageaddr), checker.DeepEquals, common.Hash{})
+ c.Assert(s.state.GetCommittedState(stateobjaddr, storageaddr), checker.DeepEquals, common.Hash{})
}
func (s *StateSuite) TestSnapshotEmpty(c *checker.C) {
@@ -208,24 +216,30 @@ func compareStateObjects(so0, so1 *stateObject, t *testing.T) {
t.Fatalf("Code mismatch: have %v, want %v", so0.code, so1.code)
}
- if len(so1.cachedStorage) != len(so0.cachedStorage) {
- t.Errorf("Storage size mismatch: have %d, want %d", len(so1.cachedStorage), len(so0.cachedStorage))
+ if len(so1.dirtyStorage) != len(so0.dirtyStorage) {
+ t.Errorf("Dirty storage size mismatch: have %d, want %d", len(so1.dirtyStorage), len(so0.dirtyStorage))
}
- for k, v := range so1.cachedStorage {
- if so0.cachedStorage[k] != v {
- t.Errorf("Storage key %x mismatch: have %v, want %v", k, so0.cachedStorage[k], v)
+ for k, v := range so1.dirtyStorage {
+ if so0.dirtyStorage[k] != v {
+ t.Errorf("Dirty storage key %x mismatch: have %v, want %v", k, so0.dirtyStorage[k], v)
}
}
- for k, v := range so0.cachedStorage {
- if so1.cachedStorage[k] != v {
- t.Errorf("Storage key %x mismatch: have %v, want none.", k, v)
+ for k, v := range so0.dirtyStorage {
+ if so1.dirtyStorage[k] != v {
+ t.Errorf("Dirty storage key %x mismatch: have %v, want none.", k, v)
}
}
-
- if so0.suicided != so1.suicided {
- t.Fatalf("suicided mismatch: have %v, want %v", so0.suicided, so1.suicided)
+ if len(so1.originStorage) != len(so0.originStorage) {
+ t.Errorf("Origin storage size mismatch: have %d, want %d", len(so1.originStorage), len(so0.originStorage))
+ }
+ for k, v := range so1.originStorage {
+ if so0.originStorage[k] != v {
+ t.Errorf("Origin storage key %x mismatch: have %v, want %v", k, so0.originStorage[k], v)
+ }
}
- if so0.deleted != so1.deleted {
- t.Fatalf("Deleted mismatch: have %v, want %v", so0.deleted, so1.deleted)
+ for k, v := range so0.originStorage {
+ if so1.originStorage[k] != v {
+ t.Errorf("Origin storage key %x mismatch: have %v, want none.", k, v)
+ }
}
}
diff --git a/core/state/statedb.go b/core/state/statedb.go
index 101b03a12..216667ce9 100644
--- a/core/state/statedb.go
+++ b/core/state/statedb.go
@@ -169,11 +169,22 @@ func (self *StateDB) Preimages() map[common.Hash][]byte {
return self.preimages
}
+// AddRefund adds gas to the refund counter
func (self *StateDB) AddRefund(gas uint64) {
self.journal.append(refundChange{prev: self.refund})
self.refund += gas
}
+// SubRefund removes gas from the refund counter.
+// This method will panic if the refund counter goes below zero
+func (self *StateDB) SubRefund(gas uint64) {
+ self.journal.append(refundChange{prev: self.refund})
+ if gas > self.refund {
+ panic("Refund counter below zero")
+ }
+ self.refund -= gas
+}
+
// Exist reports whether the given account address exists in the state.
// Notably this also returns true for suicided accounts.
func (self *StateDB) Exist(addr common.Address) bool {
@@ -236,10 +247,20 @@ func (self *StateDB) GetCodeHash(addr common.Address) common.Hash {
return common.BytesToHash(stateObject.CodeHash())
}
-func (self *StateDB) GetState(addr common.Address, bhash common.Hash) common.Hash {
+// GetState retrieves a value from the given account's storage trie.
+func (self *StateDB) GetState(addr common.Address, hash common.Hash) common.Hash {
+ stateObject := self.getStateObject(addr)
+ if stateObject != nil {
+ return stateObject.GetState(self.db, hash)
+ }
+ return common.Hash{}
+}
+
+// GetCommittedState retrieves a value from the given account's committed storage trie.
+func (self *StateDB) GetCommittedState(addr common.Address, hash common.Hash) common.Hash {
stateObject := self.getStateObject(addr)
if stateObject != nil {
- return stateObject.GetState(self.db, bhash)
+ return stateObject.GetCommittedState(self.db, hash)
}
return common.Hash{}
}
@@ -435,19 +456,14 @@ func (db *StateDB) ForEachStorage(addr common.Address, cb func(key, value common
if so == nil {
return
}
-
- // When iterating over the storage check the cache first
- for h, value := range so.cachedStorage {
- cb(h, value)
- }
-
it := trie.NewIterator(so.getTrie(db.db).NodeIterator(nil))
for it.Next() {
- // ignore cached values
key := common.BytesToHash(db.trie.GetKey(it.Key))
- if _, ok := so.cachedStorage[key]; !ok {
- cb(key, common.BytesToHash(it.Value))
+ if value, dirty := so.dirtyStorage[key]; dirty {
+ cb(key, value)
+ continue
}
+ cb(key, common.BytesToHash(it.Value))
}
}
diff --git a/core/state/statedb_test.go b/core/state/statedb_test.go
index e2b349de8..cbd5bc75e 100644
--- a/core/state/statedb_test.go
+++ b/core/state/statedb_test.go
@@ -381,11 +381,11 @@ func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error {
checkeq("GetCodeSize", state.GetCodeSize(addr), checkstate.GetCodeSize(addr))
// Check storage.
if obj := state.getStateObject(addr); obj != nil {
- state.ForEachStorage(addr, func(key, val common.Hash) bool {
- return checkeq("GetState("+key.Hex()+")", val, checkstate.GetState(addr, key))
+ state.ForEachStorage(addr, func(key, value common.Hash) bool {
+ return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value)
})
- checkstate.ForEachStorage(addr, func(key, checkval common.Hash) bool {
- return checkeq("GetState("+key.Hex()+")", state.GetState(addr, key), checkval)
+ checkstate.ForEachStorage(addr, func(key, value common.Hash) bool {
+ return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value)
})
}
if err != nil {
diff --git a/core/tx_pool.go b/core/tx_pool.go
index a0a6ff851..f6da5da2a 100644
--- a/core/tx_pool.go
+++ b/core/tx_pool.go
@@ -525,7 +525,7 @@ func (pool *TxPool) Content() (map[common.Address]types.Transactions, map[common
return pending, queued
}
-// Pending retrieves all currently processable transactions, groupped by origin
+// Pending retrieves all currently processable transactions, grouped by origin
// account and sorted by nonce. The returned transaction set is a copy and can be
// freely modified by calling code.
func (pool *TxPool) Pending() (map[common.Address]types.Transactions, error) {
@@ -547,7 +547,7 @@ func (pool *TxPool) Locals() []common.Address {
return pool.locals.flatten()
}
-// local retrieves all currently known local transactions, groupped by origin
+// local retrieves all currently known local transactions, grouped by origin
// account and sorted by nonce. The returned transaction set is a copy and can be
// freely modified by calling code.
func (pool *TxPool) local() map[common.Address]types.Transactions {
diff --git a/core/vm/evm.go b/core/vm/evm.go
index 58618f811..fc040c621 100644
--- a/core/vm/evm.go
+++ b/core/vm/evm.go
@@ -136,10 +136,28 @@ func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmCon
vmConfig: vmConfig,
chainConfig: chainConfig,
chainRules: chainConfig.Rules(ctx.BlockNumber),
- interpreters: make([]Interpreter, 1),
+ interpreters: make([]Interpreter, 0, 1),
}
- evm.interpreters[0] = NewEVMInterpreter(evm, vmConfig)
+ if chainConfig.IsEWASM(ctx.BlockNumber) {
+ // to be implemented by EVM-C and Wagon PRs.
+ // if vmConfig.EWASMInterpreter != "" {
+ // extIntOpts := strings.Split(vmConfig.EWASMInterpreter, ":")
+ // path := extIntOpts[0]
+ // options := []string{}
+ // if len(extIntOpts) > 1 {
+ // options = extIntOpts[1..]
+ // }
+ // evm.interpreters = append(evm.interpreters, NewEVMVCInterpreter(evm, vmConfig, options))
+ // } else {
+ // evm.interpreters = append(evm.interpreters, NewEWASMInterpreter(evm, vmConfig))
+ // }
+ panic("No supported ewasm interpreter yet.")
+ }
+
+ // vmConfig.EVMInterpreter will be used by EVM-C, it won't be checked here
+ // as we always want to have the built-in EVM as the failover option.
+ evm.interpreters = append(evm.interpreters, NewEVMInterpreter(evm, vmConfig))
evm.interpreter = evm.interpreters[0]
return evm
diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go
index f9eea319e..10b4f719a 100644
--- a/core/vm/gas_table.go
+++ b/core/vm/gas_table.go
@@ -117,24 +117,69 @@ func gasReturnDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *
func gasSStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
var (
- y, x = stack.Back(1), stack.Back(0)
- val = evm.StateDB.GetState(contract.Address(), common.BigToHash(x))
+ y, x = stack.Back(1), stack.Back(0)
+ current = evm.StateDB.GetState(contract.Address(), common.BigToHash(x))
)
- // This checks for 3 scenario's and calculates gas accordingly
- // 1. From a zero-value address to a non-zero value (NEW VALUE)
- // 2. From a non-zero value address to a zero-value address (DELETE)
- // 3. From a non-zero to a non-zero (CHANGE)
- if val == (common.Hash{}) && y.Sign() != 0 {
- // 0 => non 0
- return params.SstoreSetGas, nil
- } else if val != (common.Hash{}) && y.Sign() == 0 {
- // non 0 => 0
- evm.StateDB.AddRefund(params.SstoreRefundGas)
- return params.SstoreClearGas, nil
- } else {
- // non 0 => non 0 (or 0 => 0)
- return params.SstoreResetGas, nil
+ // The legacy gas metering only takes into consideration the current state
+ if !evm.chainRules.IsConstantinople {
+ // This checks for 3 scenario's and calculates gas accordingly:
+ //
+ // 1. From a zero-value address to a non-zero value (NEW VALUE)
+ // 2. From a non-zero value address to a zero-value address (DELETE)
+ // 3. From a non-zero to a non-zero (CHANGE)
+ switch {
+ case current == (common.Hash{}) && y.Sign() != 0: // 0 => non 0
+ return params.SstoreSetGas, nil
+ case current != (common.Hash{}) && y.Sign() == 0: // non 0 => 0
+ evm.StateDB.AddRefund(params.SstoreRefundGas)
+ return params.SstoreClearGas, nil
+ default: // non 0 => non 0 (or 0 => 0)
+ return params.SstoreResetGas, nil
+ }
+ }
+ // The new gas metering is based on net gas costs (EIP-1283):
+ //
+ // 1. If current value equals new value (this is a no-op), 200 gas is deducted.
+ // 2. If current value does not equal new value
+ // 2.1. If original value equals current value (this storage slot has not been changed by the current execution context)
+ // 2.1.1. If original value is 0, 20000 gas is deducted.
+ // 2.1.2. Otherwise, 5000 gas is deducted. If new value is 0, add 15000 gas to refund counter.
+ // 2.2. If original value does not equal current value (this storage slot is dirty), 200 gas is deducted. Apply both of the following clauses.
+ // 2.2.1. If original value is not 0
+ // 2.2.1.1. If current value is 0 (also means that new value is not 0), remove 15000 gas from refund counter. We can prove that refund counter will never go below 0.
+ // 2.2.1.2. If new value is 0 (also means that current value is not 0), add 15000 gas to refund counter.
+ // 2.2.2. If original value equals new value (this storage slot is reset)
+ // 2.2.2.1. If original value is 0, add 19800 gas to refund counter.
+ // 2.2.2.2. Otherwise, add 4800 gas to refund counter.
+ value := common.BigToHash(y)
+ if current == value { // noop (1)
+ return params.NetSstoreNoopGas, nil
+ }
+ original := evm.StateDB.GetCommittedState(contract.Address(), common.BigToHash(x))
+ if original == current {
+ if original == (common.Hash{}) { // create slot (2.1.1)
+ return params.NetSstoreInitGas, nil
+ }
+ if value == (common.Hash{}) { // delete slot (2.1.2b)
+ evm.StateDB.AddRefund(params.NetSstoreClearRefund)
+ }
+ return params.NetSstoreCleanGas, nil // write existing slot (2.1.2)
+ }
+ if original != (common.Hash{}) {
+ if current == (common.Hash{}) { // recreate slot (2.2.1.1)
+ evm.StateDB.SubRefund(params.NetSstoreClearRefund)
+ } else if value == (common.Hash{}) { // delete slot (2.2.1.2)
+ evm.StateDB.AddRefund(params.NetSstoreClearRefund)
+ }
+ }
+ if original == value {
+ if original == (common.Hash{}) { // reset to original inexistent slot (2.2.2.1)
+ evm.StateDB.AddRefund(params.NetSstoreResetClearRefund)
+ } else { // reset to original existing slot (2.2.2.2)
+ evm.StateDB.AddRefund(params.NetSstoreResetRefund)
+ }
}
+ return params.NetSstoreDirtyGas, nil
}
func makeGasLog(n uint64) gasFunc {
diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index ca9e775ac..4d1bd4a34 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -727,7 +727,7 @@ func opCreate2(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memo
}
func opCall(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- // Pop gas. The actual gas in in interpreter.evm.callGasTemp.
+ // Pop gas. The actual gas in interpreter.evm.callGasTemp.
interpreter.intPool.put(stack.pop())
gas := interpreter.evm.callGasTemp
// Pop other call parameters.
diff --git a/core/vm/interface.go b/core/vm/interface.go
index d176f5b39..fc15082f1 100644
--- a/core/vm/interface.go
+++ b/core/vm/interface.go
@@ -40,8 +40,10 @@ type StateDB interface {
GetCodeSize(common.Address) int
AddRefund(uint64)
+ SubRefund(uint64)
GetRefund() uint64
+ GetCommittedState(common.Address, common.Hash) common.Hash
GetState(common.Address, common.Hash) common.Hash
SetState(common.Address, common.Hash, common.Hash)
diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go
index 0f1b07342..8e934f60e 100644
--- a/core/vm/interpreter.go
+++ b/core/vm/interpreter.go
@@ -39,6 +39,11 @@ type Config struct {
// may be left uninitialised and will be set to the default
// table.
JumpTable [256]operation
+
+ // Type of the EWASM interpreter
+ EWASMInterpreter string
+ // Type of the EVM interpreter
+ EVMInterpreter string
}
// Interpreter is used to run Ethereum based contracts and will utilise the
diff --git a/core/vm/logger_test.go b/core/vm/logger_test.go
index 28830c445..cdbb70dc4 100644
--- a/core/vm/logger_test.go
+++ b/core/vm/logger_test.go
@@ -41,11 +41,6 @@ func (d *dummyContractRef) SetBalance(*big.Int) {}
func (d *dummyContractRef) SetNonce(uint64) {}
func (d *dummyContractRef) Balance() *big.Int { return new(big.Int) }
-type dummyStateDB struct {
- NoopStateDB
- ref *dummyContractRef
-}
-
func TestStoreCapture(t *testing.T) {
var (
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
diff --git a/core/vm/memory.go b/core/vm/memory.go
index 722862b1d..7e6f0eb94 100644
--- a/core/vm/memory.go
+++ b/core/vm/memory.go
@@ -29,7 +29,7 @@ type Memory struct {
lastGasCost uint64
}
-// NewMemory returns a new memory memory model.
+// NewMemory returns a new memory model.
func NewMemory() *Memory {
return &Memory{}
}
diff --git a/core/vm/noop.go b/core/vm/noop.go
deleted file mode 100644
index b71ead0d7..000000000
--- a/core/vm/noop.go
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2016 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-
-package vm
-
-import (
- "math/big"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/types"
-)
-
-func NoopCanTransfer(db StateDB, from common.Address, balance *big.Int) bool {
- return true
-}
-func NoopTransfer(db StateDB, from, to common.Address, amount *big.Int) {}
-
-type NoopEVMCallContext struct{}
-
-func (NoopEVMCallContext) Call(caller ContractRef, addr common.Address, data []byte, gas, value *big.Int) ([]byte, error) {
- return nil, nil
-}
-func (NoopEVMCallContext) CallCode(caller ContractRef, addr common.Address, data []byte, gas, value *big.Int) ([]byte, error) {
- return nil, nil
-}
-func (NoopEVMCallContext) Create(caller ContractRef, data []byte, gas, value *big.Int) ([]byte, common.Address, error) {
- return nil, common.Address{}, nil
-}
-func (NoopEVMCallContext) DelegateCall(me ContractRef, addr common.Address, data []byte, gas *big.Int) ([]byte, error) {
- return nil, nil
-}
-
-type NoopStateDB struct{}
-
-func (NoopStateDB) CreateAccount(common.Address) {}
-func (NoopStateDB) SubBalance(common.Address, *big.Int) {}
-func (NoopStateDB) AddBalance(common.Address, *big.Int) {}
-func (NoopStateDB) GetBalance(common.Address) *big.Int { return nil }
-func (NoopStateDB) GetNonce(common.Address) uint64 { return 0 }
-func (NoopStateDB) SetNonce(common.Address, uint64) {}
-func (NoopStateDB) GetCodeHash(common.Address) common.Hash { return common.Hash{} }
-func (NoopStateDB) GetCode(common.Address) []byte { return nil }
-func (NoopStateDB) SetCode(common.Address, []byte) {}
-func (NoopStateDB) GetCodeSize(common.Address) int { return 0 }
-func (NoopStateDB) AddRefund(uint64) {}
-func (NoopStateDB) GetRefund() uint64 { return 0 }
-func (NoopStateDB) GetState(common.Address, common.Hash) common.Hash { return common.Hash{} }
-func (NoopStateDB) SetState(common.Address, common.Hash, common.Hash) {}
-func (NoopStateDB) Suicide(common.Address) bool { return false }
-func (NoopStateDB) HasSuicided(common.Address) bool { return false }
-func (NoopStateDB) Exist(common.Address) bool { return false }
-func (NoopStateDB) Empty(common.Address) bool { return false }
-func (NoopStateDB) RevertToSnapshot(int) {}
-func (NoopStateDB) Snapshot() int { return 0 }
-func (NoopStateDB) AddLog(*types.Log) {}
-func (NoopStateDB) AddPreimage(common.Hash, []byte) {}
-func (NoopStateDB) ForEachStorage(common.Address, func(common.Hash, common.Hash) bool) {}