From 8c4dab77ba48dc68073fe1df79e7000043c0f966 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Mon, 14 Sep 2015 09:35:57 +0200 Subject: [PATCH 1/4] all: move common.Database to package ethdb --- cmd/geth/blocktestcmd.go | 3 +- cmd/geth/chaincmd.go | 3 +- cmd/geth/js_test.go | 2 +- cmd/utils/flags.go | 2 +- common/natspec/natspec_e2e_test.go | 2 +- core/bench_test.go | 2 +- core/block_processor.go | 5 ++-- core/chain_makers.go | 7 +++-- core/chain_manager.go | 5 ++-- core/chain_manager_test.go | 4 +-- core/chain_util.go | 45 +++++++++++++++--------------- core/genesis.go | 9 +++--- core/helper_test.go | 6 ++-- core/manager.go | 6 ++-- core/state/state_object.go | 7 +++-- core/state/statedb.go | 5 ++-- core/transaction_util.go | 10 +++---- eth/backend.go | 16 +++++------ eth/handler.go | 5 ++-- common/db.go => ethdb/interface.go | 3 +- miner/agent.go | 5 ++-- miner/worker.go | 3 +- tests/block_test_util.go | 2 +- tests/util.go | 3 +- 24 files changed, 85 insertions(+), 75 deletions(-) rename common/db.go => ethdb/interface.go (96%) diff --git a/cmd/geth/blocktestcmd.go b/cmd/geth/blocktestcmd.go index 4eff82e3d..a667cfd60 100644 --- a/cmd/geth/blocktestcmd.go +++ b/cmd/geth/blocktestcmd.go @@ -22,7 +22,6 @@ import ( "github.com/codegangsta/cli" "github.com/ethereum/go-ethereum/cmd/utils" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/tests" @@ -103,7 +102,7 @@ func runBlockTest(ctx *cli.Context) { func runOneBlockTest(ctx *cli.Context, test *tests.BlockTest) (*eth.Ethereum, error) { cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx) - cfg.NewDB = func(path string) (common.Database, error) { return ethdb.NewMemDatabase() } + cfg.NewDB = func(path string) (ethdb.Database, error) { return ethdb.NewMemDatabase() } cfg.MaxPeers = 0 // disable network cfg.Shh = false // disable whisper cfg.NAT = nil // disable port mapping diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index c42045918..c5bc4b66a 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -29,6 +29,7 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/logger/glog" ) @@ -191,7 +192,7 @@ func hashish(x string) bool { return err != nil } -func closeAll(dbs ...common.Database) { +func closeAll(dbs ...ethdb.Database) { for _, db := range dbs { db.Close() } diff --git a/cmd/geth/js_test.go b/cmd/geth/js_test.go index 67c36dfe7..2fd5a531d 100644 --- a/cmd/geth/js_test.go +++ b/cmd/geth/js_test.go @@ -103,7 +103,7 @@ func testREPL(t *testing.T, config func(*eth.Config)) (string, *testjethre, *eth Name: "test", SolcPath: testSolcPath, PowTest: true, - NewDB: func(path string) (common.Database, error) { return db, nil }, + NewDB: func(path string) (ethdb.Database, error) { return db, nil }, } if config != nil { config(conf) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 95fb649e6..b45ef0af2 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -508,7 +508,7 @@ func SetupEth(ctx *cli.Context) { } // MakeChain creates a chain manager from set command line flags. -func MakeChain(ctx *cli.Context) (chain *core.ChainManager, chainDb common.Database) { +func MakeChain(ctx *cli.Context) (chain *core.ChainManager, chainDb ethdb.Database) { datadir := ctx.GlobalString(DataDirFlag.Name) cache := ctx.GlobalInt(CacheFlag.Name) diff --git a/common/natspec/natspec_e2e_test.go b/common/natspec/natspec_e2e_test.go index fc8ca6af2..ea28b457e 100644 --- a/common/natspec/natspec_e2e_test.go +++ b/common/natspec/natspec_e2e_test.go @@ -143,7 +143,7 @@ func testEth(t *testing.T) (ethereum *eth.Ethereum, err error) { MaxPeers: 0, PowTest: true, Etherbase: common.HexToAddress(testAddress), - NewDB: func(path string) (common.Database, error) { return db, nil }, + NewDB: func(path string) (ethdb.Database, error) { return db, nil }, }) if err != nil { diff --git a/core/bench_test.go b/core/bench_test.go index baae8a7a5..d05b7d30b 100644 --- a/core/bench_test.go +++ b/core/bench_test.go @@ -144,7 +144,7 @@ func genUncles(i int, gen *BlockGen) { func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) { // Create the database in memory or in a temporary directory. - var db common.Database + var db ethdb.Database if !disk { db, _ = ethdb.NewMemDatabase() } else { diff --git a/core/block_processor.go b/core/block_processor.go index 1238fda7b..1d3bc6656 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -26,6 +26,7 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" @@ -41,7 +42,7 @@ const ( ) type BlockProcessor struct { - chainDb common.Database + chainDb ethdb.Database // Mutex for locking the block processor. Blocks can only be handled one at a time mutex sync.Mutex // Canonical block chain @@ -68,7 +69,7 @@ type GasPool interface { SubGas(gas, price *big.Int) error } -func NewBlockProcessor(db common.Database, pow pow.PoW, chainManager *ChainManager, eventMux *event.TypeMux) *BlockProcessor { +func NewBlockProcessor(db ethdb.Database, pow pow.PoW, chainManager *ChainManager, eventMux *event.TypeMux) *BlockProcessor { sm := &BlockProcessor{ chainDb: db, mem: make(map[string]*big.Int), diff --git a/core/chain_makers.go b/core/chain_makers.go index f89218f82..d3b7c42b6 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -22,6 +22,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/pow" ) @@ -142,7 +143,7 @@ func (b *BlockGen) PrevBlock(index int) *types.Block { // Blocks created by GenerateChain do not contain valid proof of work // values. Inserting them into ChainManager requires use of FakePow or // a similar non-validating proof of work implementation. -func GenerateChain(parent *types.Block, db common.Database, n int, gen func(int, *BlockGen)) []*types.Block { +func GenerateChain(parent *types.Block, db ethdb.Database, n int, gen func(int, *BlockGen)) []*types.Block { statedb := state.New(parent.Root(), db) blocks := make(types.Blocks, n) genblock := func(i int, h *types.Header) *types.Block { @@ -185,7 +186,7 @@ func makeHeader(parent *types.Block, state *state.StateDB) *types.Header { // newCanonical creates a new deterministic canonical chain by running // InsertChain on the result of makeChain. -func newCanonical(n int, db common.Database) (*BlockProcessor, error) { +func newCanonical(n int, db ethdb.Database) (*BlockProcessor, error) { evmux := &event.TypeMux{} WriteTestNetGenesisBlock(db, 0) @@ -201,7 +202,7 @@ func newCanonical(n int, db common.Database) (*BlockProcessor, error) { return bman, err } -func makeChain(parent *types.Block, n int, db common.Database, seed int) []*types.Block { +func makeChain(parent *types.Block, n int, db ethdb.Database, seed int) []*types.Block { return GenerateChain(parent, db, n, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)}) }) diff --git a/core/chain_manager.go b/core/chain_manager.go index 407945f8e..1218b1a6e 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -30,6 +30,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" @@ -60,7 +61,7 @@ const ( type ChainManager struct { //eth EthManager - chainDb common.Database + chainDb ethdb.Database processor types.BlockProcessor eventMux *event.TypeMux genesisBlock *types.Block @@ -90,7 +91,7 @@ type ChainManager struct { pow pow.PoW } -func NewChainManager(chainDb common.Database, pow pow.PoW, mux *event.TypeMux) (*ChainManager, error) { +func NewChainManager(chainDb ethdb.Database, pow pow.PoW, mux *event.TypeMux) (*ChainManager, error) { headerCache, _ := lru.New(headerCacheLimit) bodyCache, _ := lru.New(bodyCacheLimit) bodyRLPCache, _ := lru.New(bodyCacheLimit) diff --git a/core/chain_manager_test.go b/core/chain_manager_test.go index a20480de8..67ca41f00 100644 --- a/core/chain_manager_test.go +++ b/core/chain_manager_test.go @@ -46,7 +46,7 @@ func thePow() pow.PoW { return pow } -func theChainManager(db common.Database, t *testing.T) *ChainManager { +func theChainManager(db ethdb.Database, t *testing.T) *ChainManager { var eventMux event.TypeMux WriteTestNetGenesisBlock(db, 0) chainMan, err := NewChainManager(db, thePow(), &eventMux) @@ -380,7 +380,7 @@ func makeChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Block return chain } -func chm(genesis *types.Block, db common.Database) *ChainManager { +func chm(genesis *types.Block, db ethdb.Database) *ChainManager { var eventMux event.TypeMux bc := &ChainManager{chainDb: db, genesisBlock: genesis, eventMux: &eventMux, pow: FakePow{}} bc.headerCache, _ = lru.New(100) diff --git a/core/chain_util.go b/core/chain_util.go index 0e3fa31f9..33d94cebd 100644 --- a/core/chain_util.go +++ b/core/chain_util.go @@ -22,6 +22,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/params" @@ -111,7 +112,7 @@ func CalcGasLimit(parent *types.Block) *big.Int { } // GetCanonicalHash retrieves a hash assigned to a canonical block number. -func GetCanonicalHash(db common.Database, number uint64) common.Hash { +func GetCanonicalHash(db ethdb.Database, number uint64) common.Hash { data, _ := db.Get(append(blockNumPrefix, big.NewInt(int64(number)).Bytes()...)) if len(data) == 0 { return common.Hash{} @@ -124,7 +125,7 @@ func GetCanonicalHash(db common.Database, number uint64) common.Hash { // last block hash is only updated upon a full block import, the last header // hash is updated already at header import, allowing head tracking for the // fast synchronization mechanism. -func GetHeadHeaderHash(db common.Database) common.Hash { +func GetHeadHeaderHash(db ethdb.Database) common.Hash { data, _ := db.Get(headHeaderKey) if len(data) == 0 { return common.Hash{} @@ -133,7 +134,7 @@ func GetHeadHeaderHash(db common.Database) common.Hash { } // GetHeadBlockHash retrieves the hash of the current canonical head block. -func GetHeadBlockHash(db common.Database) common.Hash { +func GetHeadBlockHash(db ethdb.Database) common.Hash { data, _ := db.Get(headBlockKey) if len(data) == 0 { return common.Hash{} @@ -143,14 +144,14 @@ func GetHeadBlockHash(db common.Database) common.Hash { // GetHeaderRLP retrieves a block header in its raw RLP database encoding, or nil // if the header's not found. -func GetHeaderRLP(db common.Database, hash common.Hash) rlp.RawValue { +func GetHeaderRLP(db ethdb.Database, hash common.Hash) rlp.RawValue { data, _ := db.Get(append(append(blockPrefix, hash[:]...), headerSuffix...)) return data } // GetHeader retrieves the block header corresponding to the hash, nil if none // found. -func GetHeader(db common.Database, hash common.Hash) *types.Header { +func GetHeader(db ethdb.Database, hash common.Hash) *types.Header { data := GetHeaderRLP(db, hash) if len(data) == 0 { return nil @@ -164,14 +165,14 @@ func GetHeader(db common.Database, hash common.Hash) *types.Header { } // GetBodyRLP retrieves the block body (transactions and uncles) in RLP encoding. -func GetBodyRLP(db common.Database, hash common.Hash) rlp.RawValue { +func GetBodyRLP(db ethdb.Database, hash common.Hash) rlp.RawValue { data, _ := db.Get(append(append(blockPrefix, hash[:]...), bodySuffix...)) return data } // GetBody retrieves the block body (transactons, uncles) corresponding to the // hash, nil if none found. -func GetBody(db common.Database, hash common.Hash) *types.Body { +func GetBody(db ethdb.Database, hash common.Hash) *types.Body { data := GetBodyRLP(db, hash) if len(data) == 0 { return nil @@ -186,7 +187,7 @@ func GetBody(db common.Database, hash common.Hash) *types.Body { // GetTd retrieves a block's total difficulty corresponding to the hash, nil if // none found. -func GetTd(db common.Database, hash common.Hash) *big.Int { +func GetTd(db ethdb.Database, hash common.Hash) *big.Int { data, _ := db.Get(append(append(blockPrefix, hash.Bytes()...), tdSuffix...)) if len(data) == 0 { return nil @@ -201,7 +202,7 @@ func GetTd(db common.Database, hash common.Hash) *big.Int { // GetBlock retrieves an entire block corresponding to the hash, assembling it // back from the stored header and body. -func GetBlock(db common.Database, hash common.Hash) *types.Block { +func GetBlock(db ethdb.Database, hash common.Hash) *types.Block { // Retrieve the block header and body contents header := GetHeader(db, hash) if header == nil { @@ -216,7 +217,7 @@ func GetBlock(db common.Database, hash common.Hash) *types.Block { } // WriteCanonicalHash stores the canonical hash for the given block number. -func WriteCanonicalHash(db common.Database, hash common.Hash, number uint64) error { +func WriteCanonicalHash(db ethdb.Database, hash common.Hash, number uint64) error { key := append(blockNumPrefix, big.NewInt(int64(number)).Bytes()...) if err := db.Put(key, hash.Bytes()); err != nil { glog.Fatalf("failed to store number to hash mapping into database: %v", err) @@ -226,7 +227,7 @@ func WriteCanonicalHash(db common.Database, hash common.Hash, number uint64) err } // WriteHeadHeaderHash stores the head header's hash. -func WriteHeadHeaderHash(db common.Database, hash common.Hash) error { +func WriteHeadHeaderHash(db ethdb.Database, hash common.Hash) error { if err := db.Put(headHeaderKey, hash.Bytes()); err != nil { glog.Fatalf("failed to store last header's hash into database: %v", err) return err @@ -235,7 +236,7 @@ func WriteHeadHeaderHash(db common.Database, hash common.Hash) error { } // WriteHeadBlockHash stores the head block's hash. -func WriteHeadBlockHash(db common.Database, hash common.Hash) error { +func WriteHeadBlockHash(db ethdb.Database, hash common.Hash) error { if err := db.Put(headBlockKey, hash.Bytes()); err != nil { glog.Fatalf("failed to store last block's hash into database: %v", err) return err @@ -244,7 +245,7 @@ func WriteHeadBlockHash(db common.Database, hash common.Hash) error { } // WriteHeader serializes a block header into the database. -func WriteHeader(db common.Database, header *types.Header) error { +func WriteHeader(db ethdb.Database, header *types.Header) error { data, err := rlp.EncodeToBytes(header) if err != nil { return err @@ -259,7 +260,7 @@ func WriteHeader(db common.Database, header *types.Header) error { } // WriteBody serializes the body of a block into the database. -func WriteBody(db common.Database, hash common.Hash, body *types.Body) error { +func WriteBody(db ethdb.Database, hash common.Hash, body *types.Body) error { data, err := rlp.EncodeToBytes(body) if err != nil { return err @@ -274,7 +275,7 @@ func WriteBody(db common.Database, hash common.Hash, body *types.Body) error { } // WriteTd serializes the total difficulty of a block into the database. -func WriteTd(db common.Database, hash common.Hash, td *big.Int) error { +func WriteTd(db ethdb.Database, hash common.Hash, td *big.Int) error { data, err := rlp.EncodeToBytes(td) if err != nil { return err @@ -289,7 +290,7 @@ func WriteTd(db common.Database, hash common.Hash, td *big.Int) error { } // WriteBlock serializes a block into the database, header and body separately. -func WriteBlock(db common.Database, block *types.Block) error { +func WriteBlock(db ethdb.Database, block *types.Block) error { // Store the body first to retain database consistency if err := WriteBody(db, block.Hash(), &types.Body{block.Transactions(), block.Uncles()}); err != nil { return err @@ -302,27 +303,27 @@ func WriteBlock(db common.Database, block *types.Block) error { } // DeleteCanonicalHash removes the number to hash canonical mapping. -func DeleteCanonicalHash(db common.Database, number uint64) { +func DeleteCanonicalHash(db ethdb.Database, number uint64) { db.Delete(append(blockNumPrefix, big.NewInt(int64(number)).Bytes()...)) } // DeleteHeader removes all block header data associated with a hash. -func DeleteHeader(db common.Database, hash common.Hash) { +func DeleteHeader(db ethdb.Database, hash common.Hash) { db.Delete(append(append(blockPrefix, hash.Bytes()...), headerSuffix...)) } // DeleteBody removes all block body data associated with a hash. -func DeleteBody(db common.Database, hash common.Hash) { +func DeleteBody(db ethdb.Database, hash common.Hash) { db.Delete(append(append(blockPrefix, hash.Bytes()...), bodySuffix...)) } // DeleteTd removes all block total difficulty data associated with a hash. -func DeleteTd(db common.Database, hash common.Hash) { +func DeleteTd(db ethdb.Database, hash common.Hash) { db.Delete(append(append(blockPrefix, hash.Bytes()...), tdSuffix...)) } // DeleteBlock removes all block data associated with a hash. -func DeleteBlock(db common.Database, hash common.Hash) { +func DeleteBlock(db ethdb.Database, hash common.Hash) { DeleteHeader(db, hash) DeleteBody(db, hash) DeleteTd(db, hash) @@ -333,7 +334,7 @@ func DeleteBlock(db common.Database, hash common.Hash) { // or nil if not found. This method is only used by the upgrade mechanism to // access the old combined block representation. It will be dropped after the // network transitions to eth/63. -func GetBlockByHashOld(db common.Database, hash common.Hash) *types.Block { +func GetBlockByHashOld(db ethdb.Database, hash common.Hash) *types.Block { data, _ := db.Get(append(blockHashPre, hash[:]...)) if len(data) == 0 { return nil diff --git a/core/genesis.go b/core/genesis.go index 3a8f0af0c..727e2c75f 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -27,13 +27,14 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/params" ) // WriteGenesisBlock writes the genesis block to the database as block number 0 -func WriteGenesisBlock(chainDb common.Database, reader io.Reader) (*types.Block, error) { +func WriteGenesisBlock(chainDb ethdb.Database, reader io.Reader) (*types.Block, error) { contents, err := ioutil.ReadAll(reader) if err != nil { return nil, err @@ -110,7 +111,7 @@ func WriteGenesisBlock(chainDb common.Database, reader io.Reader) (*types.Block, // GenesisBlockForTesting creates a block in which addr has the given wei balance. // The state trie of the block is written to db. -func GenesisBlockForTesting(db common.Database, addr common.Address, balance *big.Int) *types.Block { +func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big.Int) *types.Block { statedb := state.New(common.Hash{}, db) obj := statedb.GetOrNewStateObject(addr) obj.SetBalance(balance) @@ -124,7 +125,7 @@ func GenesisBlockForTesting(db common.Database, addr common.Address, balance *bi return block } -func WriteGenesisBlockForTesting(db common.Database, addr common.Address, balance *big.Int) *types.Block { +func WriteGenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big.Int) *types.Block { testGenesis := fmt.Sprintf(`{ "nonce":"0x%x", "gasLimit":"0x%x", @@ -137,7 +138,7 @@ func WriteGenesisBlockForTesting(db common.Database, addr common.Address, balanc return block } -func WriteTestNetGenesisBlock(chainDb common.Database, nonce uint64) (*types.Block, error) { +func WriteTestNetGenesisBlock(chainDb ethdb.Database, nonce uint64) (*types.Block, error) { testGenesis := fmt.Sprintf(`{ "nonce":"0x%x", "gasLimit":"0x%x", diff --git a/core/helper_test.go b/core/helper_test.go index b21f31d7c..81ea6fc22 100644 --- a/core/helper_test.go +++ b/core/helper_test.go @@ -22,7 +22,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" // "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" ) @@ -32,7 +32,7 @@ type TestManager struct { // stateManager *StateManager eventMux *event.TypeMux - db common.Database + db ethdb.Database txPool *TxPool blockChain *ChainManager Blocks []*types.Block @@ -74,7 +74,7 @@ func (tm *TestManager) EventMux() *event.TypeMux { // return nil // } -func (tm *TestManager) Db() common.Database { +func (tm *TestManager) Db() ethdb.Database { return tm.db } diff --git a/core/manager.go b/core/manager.go index 8b0401b03..0f108a6de 100644 --- a/core/manager.go +++ b/core/manager.go @@ -18,7 +18,7 @@ package core import ( "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" ) @@ -28,7 +28,7 @@ type Backend interface { BlockProcessor() *BlockProcessor ChainManager() *ChainManager TxPool() *TxPool - ChainDb() common.Database - DappDb() common.Database + ChainDb() ethdb.Database + DappDb() ethdb.Database EventMux() *event.TypeMux } diff --git a/core/state/state_object.go b/core/state/state_object.go index 69c64ae40..353f2357b 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -23,6 +23,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/rlp" @@ -56,7 +57,7 @@ func (self Storage) Copy() Storage { type StateObject struct { // State database for storing state changes - db common.Database + db ethdb.Database trie *trie.SecureTrie // Address belonging to this account @@ -87,7 +88,7 @@ type StateObject struct { dirty bool } -func NewStateObject(address common.Address, db common.Database) *StateObject { +func NewStateObject(address common.Address, db ethdb.Database) *StateObject { object := &StateObject{db: db, address: address, balance: new(big.Int), gasPool: new(big.Int), dirty: true} object.trie = trie.NewSecure((common.Hash{}).Bytes(), db) object.storage = make(Storage) @@ -96,7 +97,7 @@ func NewStateObject(address common.Address, db common.Database) *StateObject { return object } -func NewStateObjectFromBytes(address common.Address, data []byte, db common.Database) *StateObject { +func NewStateObjectFromBytes(address common.Address, data []byte, db ethdb.Database) *StateObject { // TODO clean me up var extobject struct { Nonce uint64 diff --git a/core/state/statedb.go b/core/state/statedb.go index b754f0887..24f97e32a 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -21,6 +21,7 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/trie" @@ -32,7 +33,7 @@ import ( // * Contracts // * Accounts type StateDB struct { - db common.Database + db ethdb.Database trie *trie.SecureTrie root common.Hash @@ -47,7 +48,7 @@ type StateDB struct { } // Create a new state from a given trie -func New(root common.Hash, db common.Database) *StateDB { +func New(root common.Hash, db ethdb.Database) *StateDB { trie := trie.NewSecure(root[:], db) return &StateDB{root: root, db: db, trie: trie, stateObjects: make(map[string]*StateObject), refund: new(big.Int), logs: make(map[common.Hash]Logs)} } diff --git a/core/transaction_util.go b/core/transaction_util.go index ce2ceac46..69c6bc36f 100644 --- a/core/transaction_util.go +++ b/core/transaction_util.go @@ -32,7 +32,7 @@ var ( ) // PutTransactions stores the transactions in the given database -func PutTransactions(db common.Database, block *types.Block, txs types.Transactions) { +func PutTransactions(db ethdb.Database, block *types.Block, txs types.Transactions) { batch := new(leveldb.Batch) _, batchWrite := db.(*ethdb.LDBDatabase) @@ -78,7 +78,7 @@ func PutTransactions(db common.Database, block *types.Block, txs types.Transacti } // PutReceipts stores the receipts in the current database -func PutReceipts(db common.Database, receipts types.Receipts) error { +func PutReceipts(db ethdb.Database, receipts types.Receipts) error { batch := new(leveldb.Batch) _, batchWrite := db.(*ethdb.LDBDatabase) @@ -108,7 +108,7 @@ func PutReceipts(db common.Database, receipts types.Receipts) error { } // GetReceipt returns a receipt by hash -func GetReceipt(db common.Database, txHash common.Hash) *types.Receipt { +func GetReceipt(db ethdb.Database, txHash common.Hash) *types.Receipt { data, _ := db.Get(append(receiptsPre, txHash[:]...)) if len(data) == 0 { return nil @@ -124,7 +124,7 @@ func GetReceipt(db common.Database, txHash common.Hash) *types.Receipt { // GetBlockReceipts returns the receipts generated by the transactions // included in block's given hash. -func GetBlockReceipts(db common.Database, hash common.Hash) types.Receipts { +func GetBlockReceipts(db ethdb.Database, hash common.Hash) types.Receipts { data, _ := db.Get(append(blockReceiptsPre, hash[:]...)) if len(data) == 0 { return nil @@ -141,7 +141,7 @@ func GetBlockReceipts(db common.Database, hash common.Hash) types.Receipts { // PutBlockReceipts stores the block's transactions associated receipts // and stores them by block hash in a single slice. This is required for // forks and chain reorgs -func PutBlockReceipts(db common.Database, block *types.Block, receipts types.Receipts) error { +func PutBlockReceipts(db ethdb.Database, block *types.Block, receipts types.Receipts) error { rs := make([]*types.ReceiptForStorage, len(receipts)) for i, receipt := range receipts { rs[i] = (*types.ReceiptForStorage)(receipt) diff --git a/eth/backend.go b/eth/backend.go index deb6d3d0f..a923cfa78 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -128,7 +128,7 @@ type Config struct { // NewDB is used to create databases. // If nil, the default is to create leveldb databases on disk. - NewDB func(path string) (common.Database, error) + NewDB func(path string) (ethdb.Database, error) } func (cfg *Config) parseBootNodes() []*discover.Node { @@ -210,8 +210,8 @@ type Ethereum struct { shutdownChan chan bool // DB interfaces - chainDb common.Database // Block chain databe - dappDb common.Database // Dapp database + chainDb ethdb.Database // Block chain database + dappDb ethdb.Database // Dapp database // Closed when databases are flushed and closed databasesClosed chan bool @@ -267,7 +267,7 @@ func New(config *Config) (*Ethereum, error) { newdb := config.NewDB if newdb == nil { - newdb = func(path string) (common.Database, error) { return ethdb.NewLDBDatabase(path, config.DatabaseCache) } + newdb = func(path string) (ethdb.Database, error) { return ethdb.NewLDBDatabase(path, config.DatabaseCache) } } // Open the chain database and perform any upgrades needed @@ -527,8 +527,8 @@ func (s *Ethereum) BlockProcessor() *core.BlockProcessor { return s.blockProcess func (s *Ethereum) TxPool() *core.TxPool { return s.txPool } func (s *Ethereum) Whisper() *whisper.Whisper { return s.whisper } func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux } -func (s *Ethereum) ChainDb() common.Database { return s.chainDb } -func (s *Ethereum) DappDb() common.Database { return s.dappDb } +func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb } +func (s *Ethereum) DappDb() ethdb.Database { return s.dappDb } func (s *Ethereum) IsListening() bool { return true } // Always listening func (s *Ethereum) PeerCount() int { return s.net.PeerCount() } func (s *Ethereum) Peers() []*p2p.Peer { return s.net.Peers() } @@ -717,7 +717,7 @@ func dagFiles(epoch uint64) (string, string) { return dag, "full-R" + dag } -func saveBlockchainVersion(db common.Database, bcVersion int) { +func saveBlockchainVersion(db ethdb.Database, bcVersion int) { d, _ := db.Get([]byte("BlockchainVersion")) blockchainVersion := common.NewValue(d).Uint() @@ -728,7 +728,7 @@ func saveBlockchainVersion(db common.Database, bcVersion int) { // upgradeChainDatabase ensures that the chain database stores block split into // separate header and body entries. -func upgradeChainDatabase(db common.Database) error { +func upgradeChainDatabase(db ethdb.Database) error { // Short circuit if the head block is stored already as separate header and body data, err := db.Get([]byte("LastBlock")) if err != nil { diff --git a/eth/handler.go b/eth/handler.go index 4aef69043..0a06ea335 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -28,6 +28,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/fetcher" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" @@ -61,7 +62,7 @@ func (ep extProt) GetBlock(hashes []common.Hash) error { return ep.getBlocks(has type ProtocolManager struct { txpool txPool chainman *core.ChainManager - chaindb common.Database + chaindb ethdb.Database downloader *downloader.Downloader fetcher *fetcher.Fetcher @@ -86,7 +87,7 @@ type ProtocolManager struct { // NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable // with the ethereum network. -func NewProtocolManager(networkId int, mux *event.TypeMux, txpool txPool, pow pow.PoW, chainman *core.ChainManager, chaindb common.Database) *ProtocolManager { +func NewProtocolManager(networkId int, mux *event.TypeMux, txpool txPool, pow pow.PoW, chainman *core.ChainManager, chaindb ethdb.Database) *ProtocolManager { // Create the protocol manager with the base fields manager := &ProtocolManager{ eventMux: mux, diff --git a/common/db.go b/ethdb/interface.go similarity index 96% rename from common/db.go rename to ethdb/interface.go index 60c090cdc..598e8eaa3 100644 --- a/common/db.go +++ b/ethdb/interface.go @@ -14,9 +14,8 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -package common +package ethdb -// Database interface type Database interface { Put(key []byte, value []byte) error Get(key []byte) ([]byte, error) diff --git a/miner/agent.go b/miner/agent.go index 7ccf8d2e0..e80b222c8 100644 --- a/miner/agent.go +++ b/miner/agent.go @@ -19,11 +19,12 @@ package miner import ( "sync" + "sync/atomic" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/pow" - "sync/atomic" ) type CpuAgent struct { @@ -63,7 +64,7 @@ func (self *CpuAgent) Stop() { func (self *CpuAgent) Start() { self.mu.Lock() defer self.mu.Unlock() - + if !atomic.CompareAndSwapInt32(&self.isMining, 0, 1) { return // agent already started } diff --git a/miner/worker.go b/miner/worker.go index 2f43b110f..96c42c292 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -29,6 +29,7 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" @@ -100,7 +101,7 @@ type worker struct { eth core.Backend chain *core.ChainManager proc *core.BlockProcessor - chainDb common.Database + chainDb ethdb.Database coinbase common.Address gasPrice *big.Int diff --git a/tests/block_test_util.go b/tests/block_test_util.go index 30488951d..e31ca6344 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -197,7 +197,7 @@ func (test *BlockTest) makeEthConfig() *eth.Config { Verbosity: 5, Etherbase: common.Address{}, AccountManager: accounts.NewManager(ks), - NewDB: func(path string) (common.Database, error) { return ethdb.NewMemDatabase() }, + NewDB: func(path string) (ethdb.Database, error) { return ethdb.NewMemDatabase() }, } } diff --git a/tests/util.go b/tests/util.go index a9b5011a9..72d927ada 100644 --- a/tests/util.go +++ b/tests/util.go @@ -27,6 +27,7 @@ import ( "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/ethdb" ) func checkLogs(tlog []Log, logs state.Logs) error { @@ -87,7 +88,7 @@ func (self Log) Topics() [][]byte { return t } -func StateObjectFromAccount(db common.Database, addr string, account Account) *state.StateObject { +func StateObjectFromAccount(db ethdb.Database, addr string, account Account) *state.StateObject { obj := state.NewStateObject(common.HexToAddress(addr), db) obj.SetBalance(common.Big(account.Balance)) From 8b32f10f16f19c0b8985399fafdfe31af29493a1 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 18 Aug 2015 13:42:21 +0200 Subject: [PATCH 2/4] ethdb: add NewBatch --- ethdb/database.go | 20 ++++++++++++++++++++ ethdb/interface.go | 6 ++++++ ethdb/memory_database.go | 23 +++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/ethdb/database.go b/ethdb/database.go index 9e80e5409..ad87f853d 100644 --- a/ethdb/database.go +++ b/ethdb/database.go @@ -268,3 +268,23 @@ func (self *LDBDatabase) meter(refresh time.Duration) { } } } + +// TODO: remove this stuff and expose leveldb directly + +func (db *LDBDatabase) NewBatch() Batch { + return &ldbBatch{db: db.db, b: new(leveldb.Batch)} +} + +type ldbBatch struct { + db *leveldb.DB + b *leveldb.Batch +} + +func (b *ldbBatch) Put(key, value []byte) error { + b.b.Put(key, value) + return nil +} + +func (b *ldbBatch) Write() error { + return b.db.Write(b.b, nil) +} diff --git a/ethdb/interface.go b/ethdb/interface.go index 598e8eaa3..acb1b57c0 100644 --- a/ethdb/interface.go +++ b/ethdb/interface.go @@ -22,4 +22,10 @@ type Database interface { Delete(key []byte) error Close() Flush() error + NewBatch() Batch +} + +type Batch interface { + Put(key, value []byte) error + Write() error } diff --git a/ethdb/memory_database.go b/ethdb/memory_database.go index d50f8f9d4..4fcce1812 100644 --- a/ethdb/memory_database.go +++ b/ethdb/memory_database.go @@ -95,3 +95,26 @@ func (db *MemDatabase) LastKnownTD() []byte { func (db *MemDatabase) Flush() error { return nil } + +func (db *MemDatabase) NewBatch() Batch { + return &memBatch{db: db} +} + +type kv struct{ k, v []byte } + +type memBatch struct { + db *MemDatabase + writes []kv +} + +func (w *memBatch) Put(key, value []byte) error { + w.writes = append(w.writes, kv{key, common.CopyBytes(value)}) + return nil +} + +func (w *memBatch) Write() error { + for _, kv := range w.writes { + w.db.db[string(kv.k)] = kv.v + } + return nil +} From d581dfee5fbd46f3e6c54e3fab2717105e6bd510 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Mon, 6 Jul 2015 01:19:16 +0200 Subject: [PATCH 3/4] ethdb: copy stored memdb values Storing a value in LevelDB copies the bytes, modifying the value afterwards does not affect the content of the database. This commit ensures that MemDatabase satisfies the same property. --- ethdb/memory_database.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ethdb/memory_database.go b/ethdb/memory_database.go index 4fcce1812..fd5663fec 100644 --- a/ethdb/memory_database.go +++ b/ethdb/memory_database.go @@ -36,8 +36,7 @@ func NewMemDatabase() (*MemDatabase, error) { } func (db *MemDatabase) Put(key []byte, value []byte) error { - db.db[string(key)] = value - + db.db[string(key)] = common.CopyBytes(value) return nil } From b25258996059439df82687cc653ed14a5a9edce1 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Mon, 14 Sep 2015 09:45:40 +0200 Subject: [PATCH 4/4] ethdb: remove Flush --- eth/backend.go | 35 ++--------------------------------- ethdb/database.go | 21 ++++++++------------- ethdb/interface.go | 1 - ethdb/memory_database.go | 4 ---- 4 files changed, 10 insertions(+), 51 deletions(-) diff --git a/eth/backend.go b/eth/backend.go index a923cfa78..349dfa613 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -213,9 +213,6 @@ type Ethereum struct { chainDb ethdb.Database // Block chain database dappDb ethdb.Database // Dapp database - // Closed when databases are flushed and closed - databasesClosed chan bool - //*** SERVICES *** // State manager for processing new blocks and managing the over all states blockProcessor *core.BlockProcessor @@ -337,7 +334,6 @@ func New(config *Config) (*Ethereum, error) { eth := &Ethereum{ shutdownChan: make(chan bool), - databasesClosed: make(chan bool), chainDb: chainDb, dappDb: dappDb, eventMux: &event.TypeMux{}, @@ -549,8 +545,6 @@ func (s *Ethereum) Start() error { if err != nil { return err } - // periodically flush databases - go s.syncDatabases() if s.AutoDAG { s.StartAutoDAG() @@ -566,32 +560,6 @@ func (s *Ethereum) Start() error { return nil } -// sync databases every minute. If flushing fails we exit immediatly. The system -// may not continue under any circumstances. -func (s *Ethereum) syncDatabases() { - ticker := time.NewTicker(1 * time.Minute) -done: - for { - select { - case <-ticker.C: - // don't change the order of database flushes - if err := s.dappDb.Flush(); err != nil { - glog.Fatalf("fatal error: flush dappDb: %v (Restart your node. We are aware of this issue)\n", err) - } - if err := s.chainDb.Flush(); err != nil { - glog.Fatalf("fatal error: flush chainDb: %v (Restart your node. We are aware of this issue)\n", err) - } - case <-s.shutdownChan: - break done - } - } - - s.chainDb.Close() - s.dappDb.Close() - - close(s.databasesClosed) -} - func (s *Ethereum) StartForTest() { jsonlogger.LogJson(&logger.LogStarting{ ClientString: s.net.Name, @@ -622,12 +590,13 @@ func (s *Ethereum) Stop() { } s.StopAutoDAG() + s.chainDb.Close() + s.dappDb.Close() close(s.shutdownChan) } // This function will wait for a shutdown and resumes main thread execution func (s *Ethereum) WaitForShutdown() { - <-s.databasesClosed <-s.shutdownChan } diff --git a/ethdb/database.go b/ethdb/database.go index ad87f853d..047821c30 100644 --- a/ethdb/database.go +++ b/ethdb/database.go @@ -61,9 +61,7 @@ type LDBDatabase struct { quitChan chan chan error // Quit channel to stop the metrics collection before closing the database } -// NewLDBDatabase returns a LevelDB wrapped object. LDBDatabase does not persist data by -// it self but requires a background poller which syncs every X. `Flush` should be called -// when data needs to be stored and written to disk. +// NewLDBDatabase returns a LevelDB wrapped object. func NewLDBDatabase(file string, cache int) (*LDBDatabase, error) { // Calculate the cache allowance for this particular database cache = int(float64(cache) * cacheRatio[filepath.Base(file)]) @@ -142,11 +140,6 @@ func (self *LDBDatabase) NewIterator() iterator.Iterator { return self.db.NewIterator(nil, nil) } -// Flush flushes out the queue to leveldb -func (self *LDBDatabase) Flush() error { - return nil -} - func (self *LDBDatabase) Close() { // Stop the metrics collection to avoid internal database races self.quitLock.Lock() @@ -159,12 +152,14 @@ func (self *LDBDatabase) Close() { glog.V(logger.Error).Infof("metrics failure in '%s': %v\n", self.fn, err) } } - // Flush and close the database - if err := self.Flush(); err != nil { - glog.V(logger.Error).Infof("flushing '%s' failed: %v\n", self.fn, err) + err := self.db.Close() + if glog.V(logger.Error) { + if err == nil { + glog.Infoln("closed db:", self.fn) + } else { + glog.Errorf("error closing db %s: %v", self.fn, err) + } } - self.db.Close() - glog.V(logger.Error).Infoln("flushed and closed db:", self.fn) } func (self *LDBDatabase) LDB() *leveldb.DB { diff --git a/ethdb/interface.go b/ethdb/interface.go index acb1b57c0..f4b787a52 100644 --- a/ethdb/interface.go +++ b/ethdb/interface.go @@ -21,7 +21,6 @@ type Database interface { Get(key []byte) ([]byte, error) Delete(key []byte) error Close() - Flush() error NewBatch() Batch } diff --git a/ethdb/memory_database.go b/ethdb/memory_database.go index fd5663fec..81911f23f 100644 --- a/ethdb/memory_database.go +++ b/ethdb/memory_database.go @@ -91,10 +91,6 @@ func (db *MemDatabase) LastKnownTD() []byte { return data } -func (db *MemDatabase) Flush() error { - return nil -} - func (db *MemDatabase) NewBatch() Batch { return &memBatch{db: db} }