mirror of https://github.com/status-im/op-geth.git
cmd/geth, core: add support for recording SHA3 preimages (#3543)
This commit is contained in:
parent
26d385c18b
commit
17d92233d9
|
@ -61,7 +61,7 @@ type SimulatedBackend struct {
|
||||||
func NewSimulatedBackend(accounts ...core.GenesisAccount) *SimulatedBackend {
|
func NewSimulatedBackend(accounts ...core.GenesisAccount) *SimulatedBackend {
|
||||||
database, _ := ethdb.NewMemDatabase()
|
database, _ := ethdb.NewMemDatabase()
|
||||||
core.WriteGenesisBlockForTesting(database, accounts...)
|
core.WriteGenesisBlockForTesting(database, accounts...)
|
||||||
blockchain, _ := core.NewBlockChain(database, chainConfig, new(core.FakePow), new(event.TypeMux))
|
blockchain, _ := core.NewBlockChain(database, chainConfig, new(core.FakePow), new(event.TypeMux), vm.Config{})
|
||||||
backend := &SimulatedBackend{database: database, blockchain: blockchain}
|
backend := &SimulatedBackend{database: database, blockchain: blockchain}
|
||||||
backend.rollback()
|
backend.rollback()
|
||||||
return backend
|
return backend
|
||||||
|
|
|
@ -132,6 +132,7 @@ func init() {
|
||||||
utils.VMForceJitFlag,
|
utils.VMForceJitFlag,
|
||||||
utils.VMJitCacheFlag,
|
utils.VMJitCacheFlag,
|
||||||
utils.VMEnableJitFlag,
|
utils.VMEnableJitFlag,
|
||||||
|
utils.VMEnableDebugFlag,
|
||||||
utils.NetworkIdFlag,
|
utils.NetworkIdFlag,
|
||||||
utils.RPCCORSDomainFlag,
|
utils.RPCCORSDomainFlag,
|
||||||
utils.EthStatsURLFlag,
|
utils.EthStatsURLFlag,
|
||||||
|
|
|
@ -155,6 +155,7 @@ var AppHelpFlagGroups = []flagGroup{
|
||||||
utils.VMEnableJitFlag,
|
utils.VMEnableJitFlag,
|
||||||
utils.VMForceJitFlag,
|
utils.VMForceJitFlag,
|
||||||
utils.VMJitCacheFlag,
|
utils.VMJitCacheFlag,
|
||||||
|
utils.VMEnableDebugFlag,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,6 +33,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
@ -230,6 +231,10 @@ var (
|
||||||
Name: "jitvm",
|
Name: "jitvm",
|
||||||
Usage: "Enable the JIT VM",
|
Usage: "Enable the JIT VM",
|
||||||
}
|
}
|
||||||
|
VMEnableDebugFlag = cli.BoolFlag{
|
||||||
|
Name: "vmdebug",
|
||||||
|
Usage: "Record information useful for VM and contract debugging",
|
||||||
|
}
|
||||||
// Logging and debug settings
|
// Logging and debug settings
|
||||||
EthStatsURLFlag = cli.StringFlag{
|
EthStatsURLFlag = cli.StringFlag{
|
||||||
Name: "ethstats",
|
Name: "ethstats",
|
||||||
|
@ -741,6 +746,7 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {
|
||||||
GpobaseCorrectionFactor: ctx.GlobalInt(GpobaseCorrectionFactorFlag.Name),
|
GpobaseCorrectionFactor: ctx.GlobalInt(GpobaseCorrectionFactorFlag.Name),
|
||||||
SolcPath: ctx.GlobalString(SolcPathFlag.Name),
|
SolcPath: ctx.GlobalString(SolcPathFlag.Name),
|
||||||
AutoDAG: ctx.GlobalBool(AutoDAGFlag.Name) || ctx.GlobalBool(MiningEnabledFlag.Name),
|
AutoDAG: ctx.GlobalBool(AutoDAGFlag.Name) || ctx.GlobalBool(MiningEnabledFlag.Name),
|
||||||
|
EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Override any default configs in dev mode or the test net
|
// Override any default configs in dev mode or the test net
|
||||||
|
@ -912,7 +918,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chai
|
||||||
if !ctx.GlobalBool(FakePoWFlag.Name) {
|
if !ctx.GlobalBool(FakePoWFlag.Name) {
|
||||||
pow = ethash.New()
|
pow = ethash.New()
|
||||||
}
|
}
|
||||||
chain, err = core.NewBlockChain(chainDb, chainConfig, pow, new(event.TypeMux))
|
chain, err = core.NewBlockChain(chainDb, chainConfig, pow, new(event.TypeMux), vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatalf("Could not start chainmanager: %v", err)
|
Fatalf("Could not start chainmanager: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
|
@ -168,7 +169,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
|
||||||
// Time the insertion of the new chain.
|
// Time the insertion of the new chain.
|
||||||
// State and blocks are stored in the same DB.
|
// State and blocks are stored in the same DB.
|
||||||
evmux := new(event.TypeMux)
|
evmux := new(event.TypeMux)
|
||||||
chainman, _ := NewBlockChain(db, ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}, FakePow{}, evmux)
|
chainman, _ := NewBlockChain(db, ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}, FakePow{}, evmux, vm.Config{})
|
||||||
defer chainman.Stop()
|
defer chainman.Stop()
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
@ -278,7 +279,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("error opening database at %v: %v", dir, err)
|
b.Fatalf("error opening database at %v: %v", dir, err)
|
||||||
}
|
}
|
||||||
chain, err := NewBlockChain(db, testChainConfig(), FakePow{}, new(event.TypeMux))
|
chain, err := NewBlockChain(db, testChainConfig(), FakePow{}, new(event.TypeMux), vm.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("error creating chain: %v", err)
|
b.Fatalf("error creating chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
@ -39,7 +40,7 @@ func proc() (Validator, *BlockChain) {
|
||||||
var mux event.TypeMux
|
var mux event.TypeMux
|
||||||
|
|
||||||
WriteTestNetGenesisBlock(db)
|
WriteTestNetGenesisBlock(db)
|
||||||
blockchain, err := NewBlockChain(db, testChainConfig(), thePow(), &mux)
|
blockchain, err := NewBlockChain(db, testChainConfig(), thePow(), &mux, vm.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,12 +107,13 @@ type BlockChain struct {
|
||||||
pow pow.PoW
|
pow pow.PoW
|
||||||
processor Processor // block processor interface
|
processor Processor // block processor interface
|
||||||
validator Validator // block and state validator interface
|
validator Validator // block and state validator interface
|
||||||
|
vmConfig vm.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBlockChain returns a fully initialised block chain using information
|
// NewBlockChain returns a fully initialised block chain using information
|
||||||
// available in the database. It initialiser the default Ethereum Validator and
|
// available in the database. It initialiser the default Ethereum Validator and
|
||||||
// Processor.
|
// Processor.
|
||||||
func NewBlockChain(chainDb ethdb.Database, config *params.ChainConfig, pow pow.PoW, mux *event.TypeMux) (*BlockChain, error) {
|
func NewBlockChain(chainDb ethdb.Database, config *params.ChainConfig, pow pow.PoW, mux *event.TypeMux, vmConfig vm.Config) (*BlockChain, error) {
|
||||||
bodyCache, _ := lru.New(bodyCacheLimit)
|
bodyCache, _ := lru.New(bodyCacheLimit)
|
||||||
bodyRLPCache, _ := lru.New(bodyCacheLimit)
|
bodyRLPCache, _ := lru.New(bodyCacheLimit)
|
||||||
blockCache, _ := lru.New(blockCacheLimit)
|
blockCache, _ := lru.New(blockCacheLimit)
|
||||||
|
@ -128,6 +129,7 @@ func NewBlockChain(chainDb ethdb.Database, config *params.ChainConfig, pow pow.P
|
||||||
blockCache: blockCache,
|
blockCache: blockCache,
|
||||||
futureBlocks: futureBlocks,
|
futureBlocks: futureBlocks,
|
||||||
pow: pow,
|
pow: pow,
|
||||||
|
vmConfig: vmConfig,
|
||||||
}
|
}
|
||||||
bc.SetValidator(NewBlockValidator(config, bc, pow))
|
bc.SetValidator(NewBlockValidator(config, bc, pow))
|
||||||
bc.SetProcessor(NewStateProcessor(config, bc))
|
bc.SetProcessor(NewStateProcessor(config, bc))
|
||||||
|
@ -954,7 +956,7 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
|
||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
// Process block using the parent state as reference point.
|
// Process block using the parent state as reference point.
|
||||||
receipts, logs, usedGas, err := self.processor.Process(block, self.stateCache, vm.Config{})
|
receipts, logs, usedGas, err := self.processor.Process(block, self.stateCache, self.vmConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
self.reportBlock(block, receipts, err)
|
self.reportBlock(block, receipts, err)
|
||||||
return i, err
|
return i, err
|
||||||
|
@ -1004,6 +1006,10 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
|
||||||
if err := WriteMipmapBloom(self.chainDb, block.NumberU64(), receipts); err != nil {
|
if err := WriteMipmapBloom(self.chainDb, block.NumberU64(), receipts); err != nil {
|
||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
|
// Write hash preimages
|
||||||
|
if err := WritePreimages(self.chainDb, block.NumberU64(), self.stateCache.Preimages()); err != nil {
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
case SideStatTy:
|
case SideStatTy:
|
||||||
if glog.V(logger.Detail) {
|
if glog.V(logger.Detail) {
|
||||||
glog.Infof("inserted forked block #%d [%x…] (TD=%v) in %9v: %3d txs %d uncles.", block.Number(), block.Hash().Bytes()[0:4], block.Difficulty(), common.PrettyDuration(time.Since(bstart)), len(block.Transactions()), len(block.Uncles()))
|
glog.Infof("inserted forked block #%d [%x…] (TD=%v) in %9v: %3d txs %d uncles.", block.Number(), block.Hash().Bytes()[0:4], block.Difficulty(), common.PrettyDuration(time.Since(bstart)), len(block.Transactions()), len(block.Uncles()))
|
||||||
|
|
|
@ -53,7 +53,7 @@ func thePow() pow.PoW {
|
||||||
func theBlockChain(db ethdb.Database, t *testing.T) *BlockChain {
|
func theBlockChain(db ethdb.Database, t *testing.T) *BlockChain {
|
||||||
var eventMux event.TypeMux
|
var eventMux event.TypeMux
|
||||||
WriteTestNetGenesisBlock(db)
|
WriteTestNetGenesisBlock(db)
|
||||||
blockchain, err := NewBlockChain(db, testChainConfig(), thePow(), &eventMux)
|
blockchain, err := NewBlockChain(db, testChainConfig(), thePow(), &eventMux, vm.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("failed creating blockchain:", err)
|
t.Error("failed creating blockchain:", err)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
|
@ -614,7 +614,7 @@ func testReorgBadHashes(t *testing.T, full bool) {
|
||||||
defer func() { delete(BadHashes, headers[3].Hash()) }()
|
defer func() { delete(BadHashes, headers[3].Hash()) }()
|
||||||
}
|
}
|
||||||
// Create a new chain manager and check it rolled back the state
|
// Create a new chain manager and check it rolled back the state
|
||||||
ncm, err := NewBlockChain(db, testChainConfig(), FakePow{}, new(event.TypeMux))
|
ncm, err := NewBlockChain(db, testChainConfig(), FakePow{}, new(event.TypeMux), vm.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create new chain manager: %v", err)
|
t.Fatalf("failed to create new chain manager: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -735,7 +735,7 @@ func TestFastVsFullChains(t *testing.T) {
|
||||||
archiveDb, _ := ethdb.NewMemDatabase()
|
archiveDb, _ := ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds})
|
WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds})
|
||||||
|
|
||||||
archive, _ := NewBlockChain(archiveDb, testChainConfig(), FakePow{}, new(event.TypeMux))
|
archive, _ := NewBlockChain(archiveDb, testChainConfig(), FakePow{}, new(event.TypeMux), vm.Config{})
|
||||||
|
|
||||||
if n, err := archive.InsertChain(blocks); err != nil {
|
if n, err := archive.InsertChain(blocks); err != nil {
|
||||||
t.Fatalf("failed to process block %d: %v", n, err)
|
t.Fatalf("failed to process block %d: %v", n, err)
|
||||||
|
@ -743,7 +743,7 @@ func TestFastVsFullChains(t *testing.T) {
|
||||||
// Fast import the chain as a non-archive node to test
|
// Fast import the chain as a non-archive node to test
|
||||||
fastDb, _ := ethdb.NewMemDatabase()
|
fastDb, _ := ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds})
|
WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds})
|
||||||
fast, _ := NewBlockChain(fastDb, testChainConfig(), FakePow{}, new(event.TypeMux))
|
fast, _ := NewBlockChain(fastDb, testChainConfig(), FakePow{}, new(event.TypeMux), vm.Config{})
|
||||||
|
|
||||||
headers := make([]*types.Header, len(blocks))
|
headers := make([]*types.Header, len(blocks))
|
||||||
for i, block := range blocks {
|
for i, block := range blocks {
|
||||||
|
@ -819,7 +819,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
|
||||||
archiveDb, _ := ethdb.NewMemDatabase()
|
archiveDb, _ := ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds})
|
WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds})
|
||||||
|
|
||||||
archive, _ := NewBlockChain(archiveDb, testChainConfig(), FakePow{}, new(event.TypeMux))
|
archive, _ := NewBlockChain(archiveDb, testChainConfig(), FakePow{}, new(event.TypeMux), vm.Config{})
|
||||||
|
|
||||||
if n, err := archive.InsertChain(blocks); err != nil {
|
if n, err := archive.InsertChain(blocks); err != nil {
|
||||||
t.Fatalf("failed to process block %d: %v", n, err)
|
t.Fatalf("failed to process block %d: %v", n, err)
|
||||||
|
@ -831,7 +831,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
|
||||||
// Import the chain as a non-archive node and ensure all pointers are updated
|
// Import the chain as a non-archive node and ensure all pointers are updated
|
||||||
fastDb, _ := ethdb.NewMemDatabase()
|
fastDb, _ := ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds})
|
WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds})
|
||||||
fast, _ := NewBlockChain(fastDb, testChainConfig(), FakePow{}, new(event.TypeMux))
|
fast, _ := NewBlockChain(fastDb, testChainConfig(), FakePow{}, new(event.TypeMux), vm.Config{})
|
||||||
|
|
||||||
headers := make([]*types.Header, len(blocks))
|
headers := make([]*types.Header, len(blocks))
|
||||||
for i, block := range blocks {
|
for i, block := range blocks {
|
||||||
|
@ -850,7 +850,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
|
||||||
// Import the chain as a light node and ensure all pointers are updated
|
// Import the chain as a light node and ensure all pointers are updated
|
||||||
lightDb, _ := ethdb.NewMemDatabase()
|
lightDb, _ := ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(lightDb, GenesisAccount{address, funds})
|
WriteGenesisBlockForTesting(lightDb, GenesisAccount{address, funds})
|
||||||
light, _ := NewBlockChain(lightDb, testChainConfig(), FakePow{}, new(event.TypeMux))
|
light, _ := NewBlockChain(lightDb, testChainConfig(), FakePow{}, new(event.TypeMux), vm.Config{})
|
||||||
|
|
||||||
if n, err := light.InsertHeaderChain(headers, 1); err != nil {
|
if n, err := light.InsertHeaderChain(headers, 1); err != nil {
|
||||||
t.Fatalf("failed to insert header %d: %v", n, err)
|
t.Fatalf("failed to insert header %d: %v", n, err)
|
||||||
|
@ -916,7 +916,7 @@ func TestChainTxReorgs(t *testing.T) {
|
||||||
})
|
})
|
||||||
// Import the chain. This runs all block validation rules.
|
// Import the chain. This runs all block validation rules.
|
||||||
evmux := &event.TypeMux{}
|
evmux := &event.TypeMux{}
|
||||||
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux)
|
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux, vm.Config{})
|
||||||
if i, err := blockchain.InsertChain(chain); err != nil {
|
if i, err := blockchain.InsertChain(chain); err != nil {
|
||||||
t.Fatalf("failed to insert original chain[%d]: %v", i, err)
|
t.Fatalf("failed to insert original chain[%d]: %v", i, err)
|
||||||
}
|
}
|
||||||
|
@ -990,7 +990,7 @@ func TestLogReorgs(t *testing.T) {
|
||||||
)
|
)
|
||||||
|
|
||||||
evmux := &event.TypeMux{}
|
evmux := &event.TypeMux{}
|
||||||
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux)
|
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux, vm.Config{})
|
||||||
|
|
||||||
subs := evmux.Subscribe(RemovedLogsEvent{})
|
subs := evmux.Subscribe(RemovedLogsEvent{})
|
||||||
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 2, func(i int, gen *BlockGen) {
|
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 2, func(i int, gen *BlockGen) {
|
||||||
|
@ -1027,7 +1027,7 @@ func TestReorgSideEvent(t *testing.T) {
|
||||||
)
|
)
|
||||||
|
|
||||||
evmux := &event.TypeMux{}
|
evmux := &event.TypeMux{}
|
||||||
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux)
|
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux, vm.Config{})
|
||||||
|
|
||||||
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 3, func(i int, gen *BlockGen) {})
|
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 3, func(i int, gen *BlockGen) {})
|
||||||
if _, err := blockchain.InsertChain(chain); err != nil {
|
if _, err := blockchain.InsertChain(chain); err != nil {
|
||||||
|
@ -1103,7 +1103,7 @@ func TestCanonicalBlockRetrieval(t *testing.T) {
|
||||||
)
|
)
|
||||||
|
|
||||||
evmux := &event.TypeMux{}
|
evmux := &event.TypeMux{}
|
||||||
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux)
|
blockchain, _ := NewBlockChain(db, testChainConfig(), FakePow{}, evmux, vm.Config{})
|
||||||
|
|
||||||
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 10, func(i int, gen *BlockGen) {})
|
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 10, func(i int, gen *BlockGen) {})
|
||||||
|
|
||||||
|
@ -1146,7 +1146,7 @@ func TestEIP155Transition(t *testing.T) {
|
||||||
mux event.TypeMux
|
mux event.TypeMux
|
||||||
)
|
)
|
||||||
|
|
||||||
blockchain, _ := NewBlockChain(db, config, FakePow{}, &mux)
|
blockchain, _ := NewBlockChain(db, config, FakePow{}, &mux, vm.Config{})
|
||||||
blocks, _ := GenerateChain(config, genesis, db, 4, func(i int, block *BlockGen) {
|
blocks, _ := GenerateChain(config, genesis, db, 4, func(i int, block *BlockGen) {
|
||||||
var (
|
var (
|
||||||
tx *types.Transaction
|
tx *types.Transaction
|
||||||
|
@ -1250,7 +1250,7 @@ func TestEIP161AccountRemoval(t *testing.T) {
|
||||||
}
|
}
|
||||||
mux event.TypeMux
|
mux event.TypeMux
|
||||||
|
|
||||||
blockchain, _ = NewBlockChain(db, config, FakePow{}, &mux)
|
blockchain, _ = NewBlockChain(db, config, FakePow{}, &mux, vm.Config{})
|
||||||
)
|
)
|
||||||
blocks, _ := GenerateChain(config, genesis, db, 3, func(i int, block *BlockGen) {
|
blocks, _ := GenerateChain(config, genesis, db, 3, func(i int, block *BlockGen) {
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -256,7 +256,7 @@ func newCanonical(n int, full bool) (ethdb.Database, *BlockChain, error) {
|
||||||
// Initialize a fresh chain with only a genesis block
|
// Initialize a fresh chain with only a genesis block
|
||||||
genesis, _ := WriteTestNetGenesisBlock(db)
|
genesis, _ := WriteTestNetGenesisBlock(db)
|
||||||
|
|
||||||
blockchain, _ := NewBlockChain(db, MakeChainConfig(), FakePow{}, evmux)
|
blockchain, _ := NewBlockChain(db, MakeChainConfig(), FakePow{}, evmux, vm.Config{})
|
||||||
// Create and inject the requested chain
|
// Create and inject the requested chain
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return db, blockchain, nil
|
return db, blockchain, nil
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
|
@ -81,7 +82,7 @@ func ExampleGenerateChain() {
|
||||||
|
|
||||||
// Import the chain. This runs all block validation rules.
|
// Import the chain. This runs all block validation rules.
|
||||||
evmux := &event.TypeMux{}
|
evmux := &event.TypeMux{}
|
||||||
blockchain, _ := NewBlockChain(db, chainConfig, FakePow{}, evmux)
|
blockchain, _ := NewBlockChain(db, chainConfig, FakePow{}, evmux, vm.Config{})
|
||||||
if i, err := blockchain.InsertChain(chain); err != nil {
|
if i, err := blockchain.InsertChain(chain); err != nil {
|
||||||
fmt.Printf("insert error (block %d): %v\n", chain[i].NumberU64(), err)
|
fmt.Printf("insert error (block %d): %v\n", chain[i].NumberU64(), err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
@ -39,12 +40,12 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
proDb, _ := ethdb.NewMemDatabase()
|
proDb, _ := ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(proDb)
|
WriteGenesisBlockForTesting(proDb)
|
||||||
proConf := ¶ms.ChainConfig{HomesteadBlock: big.NewInt(0), DAOForkBlock: forkBlock, DAOForkSupport: true}
|
proConf := ¶ms.ChainConfig{HomesteadBlock: big.NewInt(0), DAOForkBlock: forkBlock, DAOForkSupport: true}
|
||||||
proBc, _ := NewBlockChain(proDb, proConf, new(FakePow), new(event.TypeMux))
|
proBc, _ := NewBlockChain(proDb, proConf, new(FakePow), new(event.TypeMux), vm.Config{})
|
||||||
|
|
||||||
conDb, _ := ethdb.NewMemDatabase()
|
conDb, _ := ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(conDb)
|
WriteGenesisBlockForTesting(conDb)
|
||||||
conConf := ¶ms.ChainConfig{HomesteadBlock: big.NewInt(0), DAOForkBlock: forkBlock, DAOForkSupport: false}
|
conConf := ¶ms.ChainConfig{HomesteadBlock: big.NewInt(0), DAOForkBlock: forkBlock, DAOForkSupport: false}
|
||||||
conBc, _ := NewBlockChain(conDb, conConf, new(FakePow), new(event.TypeMux))
|
conBc, _ := NewBlockChain(conDb, conConf, new(FakePow), new(event.TypeMux), vm.Config{})
|
||||||
|
|
||||||
if _, err := proBc.InsertChain(prefix); err != nil {
|
if _, err := proBc.InsertChain(prefix); err != nil {
|
||||||
t.Fatalf("pro-fork: failed to import chain prefix: %v", err)
|
t.Fatalf("pro-fork: failed to import chain prefix: %v", err)
|
||||||
|
@ -57,7 +58,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
// Create a pro-fork block, and try to feed into the no-fork chain
|
// Create a pro-fork block, and try to feed into the no-fork chain
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db, _ = ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(db)
|
WriteGenesisBlockForTesting(db)
|
||||||
bc, _ := NewBlockChain(db, conConf, new(FakePow), new(event.TypeMux))
|
bc, _ := NewBlockChain(db, conConf, new(FakePow), new(event.TypeMux), vm.Config{})
|
||||||
|
|
||||||
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64()+1))
|
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64()+1))
|
||||||
for j := 0; j < len(blocks)/2; j++ {
|
for j := 0; j < len(blocks)/2; j++ {
|
||||||
|
@ -78,7 +79,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
// Create a no-fork block, and try to feed into the pro-fork chain
|
// Create a no-fork block, and try to feed into the pro-fork chain
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db, _ = ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(db)
|
WriteGenesisBlockForTesting(db)
|
||||||
bc, _ = NewBlockChain(db, proConf, new(FakePow), new(event.TypeMux))
|
bc, _ = NewBlockChain(db, proConf, new(FakePow), new(event.TypeMux), vm.Config{})
|
||||||
|
|
||||||
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64()+1))
|
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64()+1))
|
||||||
for j := 0; j < len(blocks)/2; j++ {
|
for j := 0; j < len(blocks)/2; j++ {
|
||||||
|
@ -100,7 +101,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
// Verify that contra-forkers accept pro-fork extra-datas after forking finishes
|
// Verify that contra-forkers accept pro-fork extra-datas after forking finishes
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db, _ = ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(db)
|
WriteGenesisBlockForTesting(db)
|
||||||
bc, _ := NewBlockChain(db, conConf, new(FakePow), new(event.TypeMux))
|
bc, _ := NewBlockChain(db, conConf, new(FakePow), new(event.TypeMux), vm.Config{})
|
||||||
|
|
||||||
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64()+1))
|
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64()+1))
|
||||||
for j := 0; j < len(blocks)/2; j++ {
|
for j := 0; j < len(blocks)/2; j++ {
|
||||||
|
@ -116,7 +117,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
// Verify that pro-forkers accept contra-fork extra-datas after forking finishes
|
// Verify that pro-forkers accept contra-fork extra-datas after forking finishes
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db, _ = ethdb.NewMemDatabase()
|
||||||
WriteGenesisBlockForTesting(db)
|
WriteGenesisBlockForTesting(db)
|
||||||
bc, _ = NewBlockChain(db, proConf, new(FakePow), new(event.TypeMux))
|
bc, _ = NewBlockChain(db, proConf, new(FakePow), new(event.TypeMux), vm.Config{})
|
||||||
|
|
||||||
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64()+1))
|
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64()+1))
|
||||||
for j := 0; j < len(blocks)/2; j++ {
|
for j := 0; j < len(blocks)/2; j++ {
|
||||||
|
|
|
@ -30,6 +30,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
"github.com/ethereum/go-ethereum/logger/glog"
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
)
|
)
|
||||||
|
@ -39,12 +40,13 @@ var (
|
||||||
headBlockKey = []byte("LastBlock")
|
headBlockKey = []byte("LastBlock")
|
||||||
headFastKey = []byte("LastFast")
|
headFastKey = []byte("LastFast")
|
||||||
|
|
||||||
headerPrefix = []byte("h") // headerPrefix + num (uint64 big endian) + hash -> header
|
headerPrefix = []byte("h") // headerPrefix + num (uint64 big endian) + hash -> header
|
||||||
tdSuffix = []byte("t") // headerPrefix + num (uint64 big endian) + hash + tdSuffix -> td
|
tdSuffix = []byte("t") // headerPrefix + num (uint64 big endian) + hash + tdSuffix -> td
|
||||||
numSuffix = []byte("n") // headerPrefix + num (uint64 big endian) + numSuffix -> hash
|
numSuffix = []byte("n") // headerPrefix + num (uint64 big endian) + numSuffix -> hash
|
||||||
blockHashPrefix = []byte("H") // blockHashPrefix + hash -> num (uint64 big endian)
|
blockHashPrefix = []byte("H") // blockHashPrefix + hash -> num (uint64 big endian)
|
||||||
bodyPrefix = []byte("b") // bodyPrefix + num (uint64 big endian) + hash -> block body
|
bodyPrefix = []byte("b") // bodyPrefix + num (uint64 big endian) + hash -> block body
|
||||||
blockReceiptsPrefix = []byte("r") // blockReceiptsPrefix + num (uint64 big endian) + hash -> block receipts
|
blockReceiptsPrefix = []byte("r") // blockReceiptsPrefix + num (uint64 big endian) + hash -> block receipts
|
||||||
|
preimagePrefix = "secure-key-" // preimagePrefix + hash -> preimage
|
||||||
|
|
||||||
txMetaSuffix = []byte{0x01}
|
txMetaSuffix = []byte{0x01}
|
||||||
receiptsPrefix = []byte("receipts-")
|
receiptsPrefix = []byte("receipts-")
|
||||||
|
@ -66,6 +68,9 @@ var (
|
||||||
ChainConfigNotFoundErr = errors.New("ChainConfig not found") // general config not found error
|
ChainConfigNotFoundErr = errors.New("ChainConfig not found") // general config not found error
|
||||||
|
|
||||||
mipmapBloomMu sync.Mutex // protect against race condition when updating mipmap blooms
|
mipmapBloomMu sync.Mutex // protect against race condition when updating mipmap blooms
|
||||||
|
|
||||||
|
preimageCounter = metrics.NewCounter("db/preimage/total")
|
||||||
|
preimageHitCounter = metrics.NewCounter("db/preimage/hits")
|
||||||
)
|
)
|
||||||
|
|
||||||
// encodeBlockNumber encodes a block number as big endian uint64
|
// encodeBlockNumber encodes a block number as big endian uint64
|
||||||
|
@ -595,6 +600,34 @@ func GetMipmapBloom(db ethdb.Database, number, level uint64) types.Bloom {
|
||||||
return types.BytesToBloom(bloomDat)
|
return types.BytesToBloom(bloomDat)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PreimageTable returns a Database instance with the key prefix for preimage entries.
|
||||||
|
func PreimageTable(db ethdb.Database) ethdb.Database {
|
||||||
|
return ethdb.NewTable(db, preimagePrefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WritePreimages writes the provided set of preimages to the database. `number` is the
|
||||||
|
// current block number, and is used for debug messages only.
|
||||||
|
func WritePreimages(db ethdb.Database, number uint64, preimages map[common.Hash][]byte) error {
|
||||||
|
table := PreimageTable(db)
|
||||||
|
batch := table.NewBatch()
|
||||||
|
hitCount := 0
|
||||||
|
for hash, preimage := range preimages {
|
||||||
|
if _, err := table.Get(hash.Bytes()); err != nil {
|
||||||
|
batch.Put(hash.Bytes(), preimage)
|
||||||
|
hitCount += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
preimageCounter.Inc(int64(len(preimages)))
|
||||||
|
preimageHitCounter.Inc(int64(hitCount))
|
||||||
|
if hitCount > 0 {
|
||||||
|
if err := batch.Write(); err != nil {
|
||||||
|
return fmt.Errorf("preimage write fail for block %d: %v", number, err)
|
||||||
|
}
|
||||||
|
glog.V(logger.Debug).Infof("%d preimages in block %d, including %d new", len(preimages), number, hitCount)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetBlockChainVersion reads the version number from db.
|
// GetBlockChainVersion reads the version number from db.
|
||||||
func GetBlockChainVersion(db ethdb.Database) int {
|
func GetBlockChainVersion(db ethdb.Database) int {
|
||||||
var vsn uint
|
var vsn uint
|
||||||
|
|
|
@ -67,6 +67,9 @@ type (
|
||||||
addLogChange struct {
|
addLogChange struct {
|
||||||
txhash common.Hash
|
txhash common.Hash
|
||||||
}
|
}
|
||||||
|
addPreimageChange struct {
|
||||||
|
hash common.Hash
|
||||||
|
}
|
||||||
touchChange struct {
|
touchChange struct {
|
||||||
account *common.Address
|
account *common.Address
|
||||||
prev bool
|
prev bool
|
||||||
|
@ -127,3 +130,7 @@ func (ch addLogChange) undo(s *StateDB) {
|
||||||
s.logs[ch.txhash] = logs[:len(logs)-1]
|
s.logs[ch.txhash] = logs[:len(logs)-1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ch addPreimageChange) undo(s *StateDB) {
|
||||||
|
delete(s.preimages, ch.hash)
|
||||||
|
}
|
||||||
|
|
|
@ -75,6 +75,8 @@ type StateDB struct {
|
||||||
logs map[common.Hash][]*types.Log
|
logs map[common.Hash][]*types.Log
|
||||||
logSize uint
|
logSize uint
|
||||||
|
|
||||||
|
preimages map[common.Hash][]byte
|
||||||
|
|
||||||
// Journal of state modifications. This is the backbone of
|
// Journal of state modifications. This is the backbone of
|
||||||
// Snapshot and RevertToSnapshot.
|
// Snapshot and RevertToSnapshot.
|
||||||
journal journal
|
journal journal
|
||||||
|
@ -99,6 +101,7 @@ func New(root common.Hash, db ethdb.Database) (*StateDB, error) {
|
||||||
stateObjectsDirty: make(map[common.Address]struct{}),
|
stateObjectsDirty: make(map[common.Address]struct{}),
|
||||||
refund: new(big.Int),
|
refund: new(big.Int),
|
||||||
logs: make(map[common.Hash][]*types.Log),
|
logs: make(map[common.Hash][]*types.Log),
|
||||||
|
preimages: make(map[common.Hash][]byte),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,6 +123,7 @@ func (self *StateDB) New(root common.Hash) (*StateDB, error) {
|
||||||
stateObjectsDirty: make(map[common.Address]struct{}),
|
stateObjectsDirty: make(map[common.Address]struct{}),
|
||||||
refund: new(big.Int),
|
refund: new(big.Int),
|
||||||
logs: make(map[common.Hash][]*types.Log),
|
logs: make(map[common.Hash][]*types.Log),
|
||||||
|
preimages: make(map[common.Hash][]byte),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,6 +145,7 @@ func (self *StateDB) Reset(root common.Hash) error {
|
||||||
self.txIndex = 0
|
self.txIndex = 0
|
||||||
self.logs = make(map[common.Hash][]*types.Log)
|
self.logs = make(map[common.Hash][]*types.Log)
|
||||||
self.logSize = 0
|
self.logSize = 0
|
||||||
|
self.preimages = make(map[common.Hash][]byte)
|
||||||
self.clearJournalAndRefund()
|
self.clearJournalAndRefund()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -199,6 +204,21 @@ func (self *StateDB) Logs() []*types.Log {
|
||||||
return logs
|
return logs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddPreimage records a SHA3 preimage seen by the VM.
|
||||||
|
func (self *StateDB) AddPreimage(hash common.Hash, preimage []byte) {
|
||||||
|
if _, ok := self.preimages[hash]; !ok {
|
||||||
|
self.journal = append(self.journal, addPreimageChange{hash: hash})
|
||||||
|
pi := make([]byte, len(preimage))
|
||||||
|
copy(pi, preimage)
|
||||||
|
self.preimages[hash] = pi
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preimages returns a list of SHA3 preimages that have been submitted.
|
||||||
|
func (self *StateDB) Preimages() map[common.Hash][]byte {
|
||||||
|
return self.preimages
|
||||||
|
}
|
||||||
|
|
||||||
func (self *StateDB) AddRefund(gas *big.Int) {
|
func (self *StateDB) AddRefund(gas *big.Int) {
|
||||||
self.journal = append(self.journal, refundChange{prev: new(big.Int).Set(self.refund)})
|
self.journal = append(self.journal, refundChange{prev: new(big.Int).Set(self.refund)})
|
||||||
self.refund.Add(self.refund, gas)
|
self.refund.Add(self.refund, gas)
|
||||||
|
@ -477,8 +497,9 @@ func (self *StateDB) Copy() *StateDB {
|
||||||
refund: new(big.Int).Set(self.refund),
|
refund: new(big.Int).Set(self.refund),
|
||||||
logs: make(map[common.Hash][]*types.Log, len(self.logs)),
|
logs: make(map[common.Hash][]*types.Log, len(self.logs)),
|
||||||
logSize: self.logSize,
|
logSize: self.logSize,
|
||||||
|
preimages: make(map[common.Hash][]byte),
|
||||||
}
|
}
|
||||||
// Copy the dirty states and logs
|
// Copy the dirty states, logs, and preimages
|
||||||
for addr := range self.stateObjectsDirty {
|
for addr := range self.stateObjectsDirty {
|
||||||
state.stateObjects[addr] = self.stateObjects[addr].deepCopy(state, state.MarkStateObjectDirty)
|
state.stateObjects[addr] = self.stateObjects[addr].deepCopy(state, state.MarkStateObjectDirty)
|
||||||
state.stateObjectsDirty[addr] = struct{}{}
|
state.stateObjectsDirty[addr] = struct{}{}
|
||||||
|
@ -487,6 +508,9 @@ func (self *StateDB) Copy() *StateDB {
|
||||||
state.logs[hash] = make([]*types.Log, len(logs))
|
state.logs[hash] = make([]*types.Log, len(logs))
|
||||||
copy(state.logs[hash], logs)
|
copy(state.logs[hash], logs)
|
||||||
}
|
}
|
||||||
|
for hash, preimage := range self.preimages {
|
||||||
|
state.preimages[hash] = preimage
|
||||||
|
}
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,7 @@ func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, gp *GasPool, s
|
||||||
context := NewEVMContext(msg, header, bc)
|
context := NewEVMContext(msg, header, bc)
|
||||||
// Create a new environment which holds all relevant information
|
// Create a new environment which holds all relevant information
|
||||||
// about the transaction and calling mechanisms.
|
// about the transaction and calling mechanisms.
|
||||||
vmenv := vm.NewEVM(context, statedb, config, vm.Config{})
|
vmenv := vm.NewEVM(context, statedb, config, cfg)
|
||||||
// Apply the transaction to the current state (included in the env)
|
// Apply the transaction to the current state (included in the env)
|
||||||
_, gas, err := ApplyMessage(vmenv, msg, gp)
|
_, gas, err := ApplyMessage(vmenv, msg, gp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -247,7 +247,12 @@ func opMulmod(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *S
|
||||||
|
|
||||||
func opSha3(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
func opSha3(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||||
offset, size := stack.pop(), stack.pop()
|
offset, size := stack.pop(), stack.pop()
|
||||||
hash := crypto.Keccak256(memory.Get(offset.Int64(), size.Int64()))
|
data := memory.Get(offset.Int64(), size.Int64())
|
||||||
|
hash := crypto.Keccak256(data)
|
||||||
|
|
||||||
|
if env.vmConfig.EnablePreimageRecording {
|
||||||
|
env.StateDB.AddPreimage(common.BytesToHash(hash), data)
|
||||||
|
}
|
||||||
|
|
||||||
stack.push(common.BytesToBig(hash))
|
stack.push(common.BytesToBig(hash))
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
|
@ -60,6 +60,7 @@ type StateDB interface {
|
||||||
Snapshot() int
|
Snapshot() int
|
||||||
|
|
||||||
AddLog(*types.Log)
|
AddLog(*types.Log)
|
||||||
|
AddPreimage(common.Hash, []byte)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Account represents a contract or basic ethereum account.
|
// Account represents a contract or basic ethereum account.
|
||||||
|
|
|
@ -67,3 +67,4 @@ func (NoopStateDB) Empty(common.Address) bool { return f
|
||||||
func (NoopStateDB) RevertToSnapshot(int) {}
|
func (NoopStateDB) RevertToSnapshot(int) {}
|
||||||
func (NoopStateDB) Snapshot() int { return 0 }
|
func (NoopStateDB) Snapshot() int { return 0 }
|
||||||
func (NoopStateDB) AddLog(*types.Log) {}
|
func (NoopStateDB) AddLog(*types.Log) {}
|
||||||
|
func (NoopStateDB) AddPreimage(common.Hash, []byte) {}
|
||||||
|
|
|
@ -44,6 +44,8 @@ type Config struct {
|
||||||
NoRecursion bool
|
NoRecursion bool
|
||||||
// Disable gas metering
|
// Disable gas metering
|
||||||
DisableGasMetering bool
|
DisableGasMetering bool
|
||||||
|
// Enable recording of SHA3/keccak preimages
|
||||||
|
EnablePreimageRecording bool
|
||||||
// JumpTable contains the EVM instruction table. This
|
// JumpTable contains the EVM instruction table. This
|
||||||
// may me left uninitialised and will be set the default
|
// may me left uninitialised and will be set the default
|
||||||
// table.
|
// table.
|
||||||
|
|
|
@ -560,3 +560,9 @@ func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, txHash common.
|
||||||
}
|
}
|
||||||
return nil, errors.New("database inconsistency")
|
return nil, errors.New("database inconsistency")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Preimage is a debug API function that returns the preimage for a sha3 hash, if known.
|
||||||
|
func (api *PrivateDebugAPI) Preimage(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
|
||||||
|
db := core.PreimageTable(api.eth.ChainDb())
|
||||||
|
return db.Get(hash.Bytes())
|
||||||
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||||
"github.com/ethereum/go-ethereum/eth/filters"
|
"github.com/ethereum/go-ethereum/eth/filters"
|
||||||
"github.com/ethereum/go-ethereum/eth/gasprice"
|
"github.com/ethereum/go-ethereum/eth/gasprice"
|
||||||
|
@ -97,8 +98,7 @@ type Config struct {
|
||||||
GpobaseStepUp int
|
GpobaseStepUp int
|
||||||
GpobaseCorrectionFactor int
|
GpobaseCorrectionFactor int
|
||||||
|
|
||||||
EnableJit bool
|
EnablePreimageRecording bool
|
||||||
ForceJit bool
|
|
||||||
|
|
||||||
TestGenesisBlock *types.Block // Genesis block to seed the chain database with (testing only!)
|
TestGenesisBlock *types.Block // Genesis block to seed the chain database with (testing only!)
|
||||||
TestGenesisState ethdb.Database // Genesis state to seed the database with (testing only!)
|
TestGenesisState ethdb.Database // Genesis state to seed the database with (testing only!)
|
||||||
|
@ -218,7 +218,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
||||||
|
|
||||||
glog.V(logger.Info).Infoln("Chain config:", eth.chainConfig)
|
glog.V(logger.Info).Infoln("Chain config:", eth.chainConfig)
|
||||||
|
|
||||||
eth.blockchain, err = core.NewBlockChain(chainDb, eth.chainConfig, eth.pow, eth.EventMux())
|
eth.blockchain, err = core.NewBlockChain(chainDb, eth.chainConfig, eth.pow, eth.EventMux(), vm.Config{EnablePreimageRecording: config.EnablePreimageRecording})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == core.ErrNoGenesis {
|
if err == core.ErrNoGenesis {
|
||||||
return nil, fmt.Errorf(`No chain found. Please initialise a new chain using the "init" subcommand.`)
|
return nil, fmt.Errorf(`No chain found. Please initialise a new chain using the "init" subcommand.`)
|
||||||
|
|
|
@ -27,6 +27,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
@ -469,7 +470,7 @@ func testDAOChallenge(t *testing.T, localForked, remoteForked bool, timeout bool
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db, _ = ethdb.NewMemDatabase()
|
||||||
genesis = core.WriteGenesisBlockForTesting(db)
|
genesis = core.WriteGenesisBlockForTesting(db)
|
||||||
config = ¶ms.ChainConfig{DAOForkBlock: big.NewInt(1), DAOForkSupport: localForked}
|
config = ¶ms.ChainConfig{DAOForkBlock: big.NewInt(1), DAOForkSupport: localForked}
|
||||||
blockchain, _ = core.NewBlockChain(db, config, pow, evmux)
|
blockchain, _ = core.NewBlockChain(db, config, pow, evmux, vm.Config{})
|
||||||
)
|
)
|
||||||
pm, err := NewProtocolManager(config, false, NetworkId, 1000, evmux, new(testTxPool), pow, blockchain, db)
|
pm, err := NewProtocolManager(config, false, NetworkId, 1000, evmux, new(testTxPool), pow, blockchain, db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -30,6 +30,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
|
@ -56,7 +57,7 @@ func newTestProtocolManager(fastSync bool, blocks int, generator func(int, *core
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db, _ = ethdb.NewMemDatabase()
|
||||||
genesis = core.WriteGenesisBlockForTesting(db, testBank)
|
genesis = core.WriteGenesisBlockForTesting(db, testBank)
|
||||||
chainConfig = ¶ms.ChainConfig{HomesteadBlock: big.NewInt(0)} // homestead set to 0 because of chain maker
|
chainConfig = ¶ms.ChainConfig{HomesteadBlock: big.NewInt(0)} // homestead set to 0 because of chain maker
|
||||||
blockchain, _ = core.NewBlockChain(db, chainConfig, pow, evmux)
|
blockchain, _ = core.NewBlockChain(db, chainConfig, pow, evmux, vm.Config{})
|
||||||
)
|
)
|
||||||
chain, _ := core.GenerateChain(chainConfig, genesis, db, blocks, generator)
|
chain, _ := core.GenerateChain(chainConfig, genesis, db, blocks, generator)
|
||||||
if _, err := blockchain.InsertChain(chain); err != nil {
|
if _, err := blockchain.InsertChain(chain); err != nil {
|
||||||
|
|
|
@ -385,6 +385,12 @@ web3._extend({
|
||||||
call: 'debug_traceTransaction',
|
call: 'debug_traceTransaction',
|
||||||
params: 2,
|
params: 2,
|
||||||
inputFormatter: [null, null]
|
inputFormatter: [null, null]
|
||||||
|
}),
|
||||||
|
new web3._extend.Method({
|
||||||
|
name: 'preimage',
|
||||||
|
call: 'debug_preimage',
|
||||||
|
params: 1,
|
||||||
|
inputFormatter: [null]
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
properties: []
|
properties: []
|
||||||
|
|
|
@ -30,6 +30,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
|
@ -143,7 +144,7 @@ func newTestProtocolManager(lightSync bool, blocks int, generator func(int, *cor
|
||||||
odr = NewLesOdr(db)
|
odr = NewLesOdr(db)
|
||||||
chain, _ = light.NewLightChain(odr, chainConfig, pow, evmux)
|
chain, _ = light.NewLightChain(odr, chainConfig, pow, evmux)
|
||||||
} else {
|
} else {
|
||||||
blockchain, _ := core.NewBlockChain(db, chainConfig, pow, evmux)
|
blockchain, _ := core.NewBlockChain(db, chainConfig, pow, evmux, vm.Config{})
|
||||||
gchain, _ := core.GenerateChain(chainConfig, genesis, db, blocks, generator)
|
gchain, _ := core.GenerateChain(chainConfig, genesis, db, blocks, generator)
|
||||||
if _, err := blockchain.InsertChain(gchain); err != nil {
|
if _, err := blockchain.InsertChain(gchain); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|
|
@ -251,7 +251,7 @@ func testChainOdr(t *testing.T, protocol int, expFail uint64, fn odrTestFn) {
|
||||||
)
|
)
|
||||||
core.WriteGenesisBlockForTesting(ldb, core.GenesisAccount{Address: testBankAddress, Balance: testBankFunds})
|
core.WriteGenesisBlockForTesting(ldb, core.GenesisAccount{Address: testBankAddress, Balance: testBankFunds})
|
||||||
// Assemble the test environment
|
// Assemble the test environment
|
||||||
blockchain, _ := core.NewBlockChain(sdb, testChainConfig(), pow, evmux)
|
blockchain, _ := core.NewBlockChain(sdb, testChainConfig(), pow, evmux, vm.Config{})
|
||||||
chainConfig := ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}
|
chainConfig := ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}
|
||||||
gchain, _ := core.GenerateChain(chainConfig, genesis, sdb, 4, testChainGen)
|
gchain, _ := core.GenerateChain(chainConfig, genesis, sdb, 4, testChainGen)
|
||||||
if _, err := blockchain.InsertChain(gchain); err != nil {
|
if _, err := blockchain.InsertChain(gchain); err != nil {
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
@ -88,7 +89,7 @@ func TestTxPool(t *testing.T) {
|
||||||
)
|
)
|
||||||
core.WriteGenesisBlockForTesting(ldb, core.GenesisAccount{Address: testBankAddress, Balance: testBankFunds})
|
core.WriteGenesisBlockForTesting(ldb, core.GenesisAccount{Address: testBankAddress, Balance: testBankFunds})
|
||||||
// Assemble the test environment
|
// Assemble the test environment
|
||||||
blockchain, _ := core.NewBlockChain(sdb, testChainConfig(), pow, evmux)
|
blockchain, _ := core.NewBlockChain(sdb, testChainConfig(), pow, evmux, vm.Config{})
|
||||||
chainConfig := ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}
|
chainConfig := ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}
|
||||||
gchain, _ := core.GenerateChain(chainConfig, genesis, sdb, poolTestBlocks, txPoolTestChainGen)
|
gchain, _ := core.GenerateChain(chainConfig, genesis, sdb, poolTestBlocks, txPoolTestChainGen)
|
||||||
if _, err := blockchain.InsertChain(gchain); err != nil {
|
if _, err := blockchain.InsertChain(gchain); err != nil {
|
||||||
|
|
|
@ -45,6 +45,8 @@ func (s *VMState) Error() error {
|
||||||
|
|
||||||
func (s *VMState) AddLog(log *types.Log) {}
|
func (s *VMState) AddLog(log *types.Log) {}
|
||||||
|
|
||||||
|
func (s *VMState) AddPreimage(hash common.Hash, preimage []byte) {}
|
||||||
|
|
||||||
// errHandler handles and stores any state error that happens during execution.
|
// errHandler handles and stores any state error that happens during execution.
|
||||||
func (s *VMState) errHandler(err error) {
|
func (s *VMState) errHandler(err error) {
|
||||||
if err != nil && s.err == nil {
|
if err != nil && s.err == nil {
|
||||||
|
|
|
@ -31,6 +31,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
|
@ -172,7 +173,7 @@ func runBlockTest(homesteadBlock, daoForkBlock, gasPriceFork *big.Int, test *Blo
|
||||||
core.WriteHeadBlockHash(db, test.Genesis.Hash())
|
core.WriteHeadBlockHash(db, test.Genesis.Hash())
|
||||||
evmux := new(event.TypeMux)
|
evmux := new(event.TypeMux)
|
||||||
config := ¶ms.ChainConfig{HomesteadBlock: homesteadBlock, DAOForkBlock: daoForkBlock, DAOForkSupport: true, EIP150Block: gasPriceFork}
|
config := ¶ms.ChainConfig{HomesteadBlock: homesteadBlock, DAOForkBlock: daoForkBlock, DAOForkSupport: true, EIP150Block: gasPriceFork}
|
||||||
chain, err := core.NewBlockChain(db, config, ethash.NewShared(), evmux)
|
chain, err := core.NewBlockChain(db, config, ethash.NewShared(), evmux, vm.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue