all: integrate chain freezer and polish database accesses

This commit is contained in:
Péter Szilágyi 2018-10-02 10:46:46 +03:00
parent 39ac0e38e8
commit 2955566655
No known key found for this signature in database
GPG key ID: E9AE538CEDF8293D
121 changed files with 2061 additions and 1917 deletions

View file

@ -35,8 +35,8 @@ import (
"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/core/vm"
"github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/eth/filters" "github.com/ethereum/go-ethereum/eth/filters"
"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"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
@ -51,7 +51,7 @@ var errGasEstimationFailed = errors.New("gas required exceeds allowance or alway
// SimulatedBackend implements bind.ContractBackend, simulating a blockchain in // SimulatedBackend implements bind.ContractBackend, simulating a blockchain in
// the background. Its main purpose is to allow easily testing contract bindings. // the background. Its main purpose is to allow easily testing contract bindings.
type SimulatedBackend struct { type SimulatedBackend struct {
database ethdb.Database // In memory database to store our testing data database database.Database // In memory database to store our testing data
blockchain *core.BlockChain // Ethereum blockchain to handle the consensus blockchain *core.BlockChain // Ethereum blockchain to handle the consensus
mu sync.Mutex mu sync.Mutex
@ -66,7 +66,7 @@ type SimulatedBackend struct {
// NewSimulatedBackend creates a new binding backend using a simulated blockchain // NewSimulatedBackend creates a new binding backend using a simulated blockchain
// for testing purposes. // for testing purposes.
func NewSimulatedBackend(alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend { func NewSimulatedBackend(alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend {
database := ethdb.NewMemDatabase() database := rawdb.NewMemoryDatabase()
genesis := core.Genesis{Config: params.AllEthashProtocolChanges, GasLimit: gasLimit, Alloc: alloc} genesis := core.Genesis{Config: params.AllEthashProtocolChanges, GasLimit: gasLimit, Alloc: alloc}
genesis.MustCommit(database) genesis.MustCommit(database)
blockchain, _ := core.NewBlockChain(database, nil, genesis.Config, ethash.NewFaker(), vm.Config{}, nil) blockchain, _ := core.NewBlockChain(database, nil, genesis.Config, ethash.NewFaker(), vm.Config{}, nil)
@ -422,11 +422,11 @@ func (m callmsg) Data() []byte { return m.CallMsg.Data }
// filterBackend implements filters.Backend to support filtering for logs without // filterBackend implements filters.Backend to support filtering for logs without
// taking bloom-bits acceleration structures into account. // taking bloom-bits acceleration structures into account.
type filterBackend struct { type filterBackend struct {
db ethdb.Database db database.Database
bc *core.BlockChain bc *core.BlockChain
} }
func (fb *filterBackend) ChainDb() ethdb.Database { return fb.db } func (fb *filterBackend) ChainDb() database.Database { return fb.db }
func (fb *filterBackend) EventMux() *event.TypeMux { panic("not supported") } func (fb *filterBackend) EventMux() *event.TypeMux { panic("not supported") }
func (fb *filterBackend) HeaderByNumber(ctx context.Context, block rpc.BlockNumber) (*types.Header, error) { func (fb *filterBackend) HeaderByNumber(ctx context.Context, block rpc.BlockNumber) (*types.Header, error) {

View file

@ -31,10 +31,10 @@ import (
"github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/cmd/utils"
"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/rawdb"
"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/core/vm"
"github.com/ethereum/go-ethereum/core/vm/runtime" "github.com/ethereum/go-ethereum/core/vm/runtime"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
cli "gopkg.in/urfave/cli.v1" cli "gopkg.in/urfave/cli.v1"
@ -99,12 +99,12 @@ func runCmd(ctx *cli.Context) error {
if ctx.GlobalString(GenesisFlag.Name) != "" { if ctx.GlobalString(GenesisFlag.Name) != "" {
gen := readGenesis(ctx.GlobalString(GenesisFlag.Name)) gen := readGenesis(ctx.GlobalString(GenesisFlag.Name))
genesisConfig = gen genesisConfig = gen
db := ethdb.NewMemDatabase() db := rawdb.NewMemoryDatabase()
genesis := gen.ToBlock(db) genesis := gen.ToBlock(db)
statedb, _ = state.New(genesis.Root(), state.NewDatabase(db)) statedb, _ = state.New(genesis.Root(), state.NewDatabase(db))
chainConfig = gen.Config chainConfig = gen.Config
} else { } else {
statedb, _ = state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) statedb, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
genesisConfig = new(core.Genesis) genesisConfig = new(core.Genesis)
} }
if ctx.GlobalString(SenderFlag.Name) != "" { if ctx.GlobalString(SenderFlag.Name) != "" {

View file

@ -29,14 +29,13 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/console" "github.com/ethereum/go-ethereum/console"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"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/eth/downloader" "github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
"github.com/syndtr/goleveldb/leveldb/util"
"gopkg.in/urfave/cli.v1" "gopkg.in/urfave/cli.v1"
) )
@ -193,7 +192,7 @@ func initGenesis(ctx *cli.Context) error {
defer stack.Close() defer stack.Close()
for _, name := range []string{"chaindata", "lightchaindata"} { for _, name := range []string{"chaindata", "lightchaindata"} {
chaindb, err := stack.OpenDatabase(name, 0, 0) chaindb, err := stack.OpenDatabase(name, 0, 0, "")
if err != nil { if err != nil {
utils.Fatalf("Failed to open database: %v", err) utils.Fatalf("Failed to open database: %v", err)
} }
@ -201,6 +200,7 @@ func initGenesis(ctx *cli.Context) error {
if err != nil { if err != nil {
utils.Fatalf("Failed to write genesis block: %v", err) utils.Fatalf("Failed to write genesis block: %v", err)
} }
chaindb.Close()
log.Info("Successfully wrote genesis state", "database", name, "hash", hash) log.Info("Successfully wrote genesis state", "database", name, "hash", hash)
} }
return nil return nil
@ -213,8 +213,8 @@ func importChain(ctx *cli.Context) error {
stack := makeFullNode(ctx) stack := makeFullNode(ctx)
defer stack.Close() defer stack.Close()
chain, chainDb := utils.MakeChain(ctx, stack) chain, db := utils.MakeChain(ctx, stack)
defer chainDb.Close() defer db.Close()
// Start periodically gathering memory profiles // Start periodically gathering memory profiles
var peakMemAlloc, peakMemSys uint64 var peakMemAlloc, peakMemSys uint64
@ -249,15 +249,13 @@ func importChain(ctx *cli.Context) error {
fmt.Printf("Import done in %v.\n\n", time.Since(start)) fmt.Printf("Import done in %v.\n\n", time.Since(start))
// Output pre-compaction stats mostly to see the import trashing // Output pre-compaction stats mostly to see the import trashing
db := chainDb.(*ethdb.LDBDatabase) stats, err := db.Stat("leveldb.stats")
stats, err := db.LDB().GetProperty("leveldb.stats")
if err != nil { if err != nil {
utils.Fatalf("Failed to read database stats: %v", err) utils.Fatalf("Failed to read database stats: %v", err)
} }
fmt.Println(stats) fmt.Println(stats)
ioStats, err := db.LDB().GetProperty("leveldb.iostats") ioStats, err := db.Stat("leveldb.iostats")
if err != nil { if err != nil {
utils.Fatalf("Failed to read database iostats: %v", err) utils.Fatalf("Failed to read database iostats: %v", err)
} }
@ -280,24 +278,24 @@ func importChain(ctx *cli.Context) error {
} }
// Compact the entire database to more accurately measure disk io and print the stats // Compact the entire database to more accurately measure disk io and print the stats
start = time.Now() /*start = time.Now()
fmt.Println("Compacting entire database...") fmt.Println("Compacting entire database...")
if err = db.LDB().CompactRange(util.Range{}); err != nil { if err = db.LDB().CompactRange(util.Range{}); err != nil {
utils.Fatalf("Compaction failed: %v", err) utils.Fatalf("Compaction failed: %v", err)
} }
fmt.Printf("Compaction done in %v.\n\n", time.Since(start)) fmt.Printf("Compaction done in %v.\n\n", time.Since(start))
stats, err = db.LDB().GetProperty("leveldb.stats") stats, err = db.Stat("leveldb.stats")
if err != nil { if err != nil {
utils.Fatalf("Failed to read database stats: %v", err) utils.Fatalf("Failed to read database stats: %v", err)
} }
fmt.Println(stats) fmt.Println(stats)
ioStats, err = db.LDB().GetProperty("leveldb.iostats") ioStats, err = db.Stat("leveldb.iostats")
if err != nil { if err != nil {
utils.Fatalf("Failed to read database iostats: %v", err) utils.Fatalf("Failed to read database iostats: %v", err)
} }
fmt.Println(ioStats) fmt.Println(ioStats)*/
return nil return nil
} }
@ -344,10 +342,10 @@ func importPreimages(ctx *cli.Context) error {
stack := makeFullNode(ctx) stack := makeFullNode(ctx)
defer stack.Close() defer stack.Close()
diskdb := utils.MakeChainDatabase(ctx, stack).(*ethdb.LDBDatabase) db := utils.MakeChainDatabase(ctx, stack)
start := time.Now() start := time.Now()
if err := utils.ImportPreimages(diskdb, ctx.Args().First()); err != nil { if err := utils.ImportPreimages(db, ctx.Args().First()); err != nil {
utils.Fatalf("Import error: %v\n", err) utils.Fatalf("Import error: %v\n", err)
} }
fmt.Printf("Import done in %v\n", time.Since(start)) fmt.Printf("Import done in %v\n", time.Since(start))
@ -362,10 +360,10 @@ func exportPreimages(ctx *cli.Context) error {
stack := makeFullNode(ctx) stack := makeFullNode(ctx)
defer stack.Close() defer stack.Close()
diskdb := utils.MakeChainDatabase(ctx, stack).(*ethdb.LDBDatabase) db := utils.MakeChainDatabase(ctx, stack)
start := time.Now() start := time.Now()
if err := utils.ExportPreimages(diskdb, ctx.Args().First()); err != nil { if err := utils.ExportPreimages(db, ctx.Args().First()); err != nil {
utils.Fatalf("Export error: %v\n", err) utils.Fatalf("Export error: %v\n", err)
} }
fmt.Printf("Export done in %v\n", time.Since(start)) fmt.Printf("Export done in %v\n", time.Since(start))
@ -374,9 +372,12 @@ func exportPreimages(ctx *cli.Context) error {
func copyDb(ctx *cli.Context) error { func copyDb(ctx *cli.Context) error {
// Ensure we have a source chain directory to copy // Ensure we have a source chain directory to copy
if len(ctx.Args()) != 1 { if len(ctx.Args()) < 1 {
utils.Fatalf("Source chaindata directory path argument missing") utils.Fatalf("Source chaindata directory path argument missing")
} }
if len(ctx.Args()) < 2 {
utils.Fatalf("Source ancient chain directory path argument missing")
}
// Initialize a new chain for the running node to sync into // Initialize a new chain for the running node to sync into
stack := makeFullNode(ctx) stack := makeFullNode(ctx)
defer stack.Close() defer stack.Close()
@ -386,7 +387,7 @@ func copyDb(ctx *cli.Context) error {
dl := downloader.New(syncmode, chainDb, new(event.TypeMux), chain, nil, nil) dl := downloader.New(syncmode, chainDb, new(event.TypeMux), chain, nil, nil)
// Create a source peer to satisfy downloader requests from // Create a source peer to satisfy downloader requests from
db, err := ethdb.NewLDBDatabase(ctx.Args().First(), ctx.GlobalInt(utils.CacheFlag.Name), 256) db, err := rawdb.NewLeveldbDatabaseWithFreezer(ctx.Args().First(), ctx.GlobalInt(utils.CacheFlag.Name), 256, ctx.Args().Get(1), "")
if err != nil { if err != nil {
return err return err
} }
@ -411,12 +412,12 @@ func copyDb(ctx *cli.Context) error {
fmt.Printf("Database copy done in %v\n", time.Since(start)) fmt.Printf("Database copy done in %v\n", time.Since(start))
// Compact the entire database to remove any sync overhead // Compact the entire database to remove any sync overhead
start = time.Now() /*start = time.Now()
fmt.Println("Compacting entire database...") fmt.Println("Compacting entire database...")
if err = chainDb.(*ethdb.LDBDatabase).LDB().CompactRange(util.Range{}); err != nil { if err = chainDb.(*ethdb.LDBDatabase).LDB().CompactRange(util.Range{}); err != nil {
utils.Fatalf("Compaction failed: %v", err) utils.Fatalf("Compaction failed: %v", err)
} }
fmt.Printf("Compaction done in %v.\n\n", time.Since(start)) fmt.Printf("Compaction done in %v.\n\n", time.Since(start))*/
return nil return nil
} }

View file

@ -25,7 +25,6 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
) )
@ -121,7 +120,7 @@ func testDAOForkBlockNewChain(t *testing.T, test int, genesis string, expectBloc
} }
// Retrieve the DAO config flag from the database // Retrieve the DAO config flag from the database
path := filepath.Join(datadir, "geth", "chaindata") path := filepath.Join(datadir, "geth", "chaindata")
db, err := ethdb.NewLDBDatabase(path, 0, 0) db, err := rawdb.NewLeveldbDatabase(path, 0, 0, "")
if err != nil { if err != nil {
t.Fatalf("test %d: failed to open test database: %v", test, err) t.Fatalf("test %d: failed to open test database: %v", test, err)
} }

View file

@ -61,6 +61,7 @@ var (
utils.BootnodesV4Flag, utils.BootnodesV4Flag,
utils.BootnodesV5Flag, utils.BootnodesV5Flag,
utils.DataDirFlag, utils.DataDirFlag,
utils.AncientFlag,
utils.KeyStoreDirFlag, utils.KeyStoreDirFlag,
utils.ExternalSignerFlag, utils.ExternalSignerFlag,
utils.NoUSBFlag, utils.NoUSBFlag,

View file

@ -69,6 +69,7 @@ var AppHelpFlagGroups = []flagGroup{
Flags: []cli.Flag{ Flags: []cli.Flag{
configFileFlag, configFileFlag,
utils.DataDirFlag, utils.DataDirFlag,
utils.AncientFlag,
utils.KeyStoreDirFlag, utils.KeyStoreDirFlag,
utils.NoUSBFlag, utils.NoUSBFlag,
utils.NetworkIdFlag, utils.NetworkIdFlag,

View file

@ -32,7 +32,7 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/internal/debug" "github.com/ethereum/go-ethereum/internal/debug"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/node"
@ -238,7 +238,7 @@ func ExportAppendChain(blockchain *core.BlockChain, fn string, first uint64, las
} }
// ImportPreimages imports a batch of exported hash preimages into the database. // ImportPreimages imports a batch of exported hash preimages into the database.
func ImportPreimages(db *ethdb.LDBDatabase, fn string) error { func ImportPreimages(db database.Database, fn string) error {
log.Info("Importing preimages", "file", fn) log.Info("Importing preimages", "file", fn)
// Open the file handle and potentially unwrap the gzip stream // Open the file handle and potentially unwrap the gzip stream
@ -285,7 +285,7 @@ func ImportPreimages(db *ethdb.LDBDatabase, fn string) error {
// ExportPreimages exports all known hash preimages into the specified file, // ExportPreimages exports all known hash preimages into the specified file,
// truncating any data already present in the file. // truncating any data already present in the file.
func ExportPreimages(db *ethdb.LDBDatabase, fn string) error { func ExportPreimages(db database.Database, fn string) error {
log.Info("Exporting preimages", "file", fn) log.Info("Exporting preimages", "file", fn)
// Open the file handle and potentially wrap with a gzip stream // Open the file handle and potentially wrap with a gzip stream

View file

@ -41,10 +41,10 @@ import (
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/dashboard" "github.com/ethereum/go-ethereum/dashboard"
"github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/gasprice" "github.com/ethereum/go-ethereum/eth/gasprice"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethstats" "github.com/ethereum/go-ethereum/ethstats"
"github.com/ethereum/go-ethereum/les" "github.com/ethereum/go-ethereum/les"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
@ -120,6 +120,10 @@ var (
Usage: "Data directory for the databases and keystore", Usage: "Data directory for the databases and keystore",
Value: DirectoryString{node.DefaultDataDir()}, Value: DirectoryString{node.DefaultDataDir()},
} }
AncientFlag = DirectoryFlag{
Name: "datadir.ancient",
Usage: "Data directory for ancient chain segments (default = inside chaindata)",
}
KeyStoreDirFlag = DirectoryFlag{ KeyStoreDirFlag = DirectoryFlag{
Name: "keystore", Name: "keystore",
Usage: "Directory for the keystore (default = inside the datadir)", Usage: "Directory for the keystore (default = inside the datadir)",
@ -1317,6 +1321,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100 cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100
} }
cfg.DatabaseHandles = makeDatabaseHandles() cfg.DatabaseHandles = makeDatabaseHandles()
if ctx.GlobalIsSet(AncientFlag.Name) {
cfg.DatabaseFreezer = ctx.GlobalString(AncientFlag.Name)
}
if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
@ -1526,7 +1533,7 @@ func SplitTagsFlag(tagsFlag string) map[string]string {
} }
// MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails. // MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database { func MakeChainDatabase(ctx *cli.Context, stack *node.Node) database.Database {
var ( var (
cache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100 cache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100
handles = makeDatabaseHandles() handles = makeDatabaseHandles()
@ -1535,7 +1542,7 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
if ctx.GlobalString(SyncModeFlag.Name) == "light" { if ctx.GlobalString(SyncModeFlag.Name) == "light" {
name = "lightchaindata" name = "lightchaindata"
} }
chainDb, err := stack.OpenDatabase(name, cache, handles) chainDb, err := stack.OpenDatabase(name, cache, handles, "")
if err != nil { if err != nil {
Fatalf("Could not open database: %v", err) Fatalf("Could not open database: %v", err)
} }
@ -1558,7 +1565,7 @@ func MakeGenesis(ctx *cli.Context) *core.Genesis {
} }
// MakeChain creates a chain manager from set command line flags. // MakeChain creates a chain manager from set command line flags.
func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) { func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb database.Database) {
var err error var err error
chainDb = MakeChainDatabase(ctx, stack) chainDb = MakeChainDatabase(ctx, stack)
config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx)) config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx))

View file

@ -34,7 +34,7 @@ import (
"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/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
@ -170,7 +170,7 @@ func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, er
// Ethereum testnet following the Ropsten attacks. // Ethereum testnet following the Ropsten attacks.
type Clique struct { type Clique struct {
config *params.CliqueConfig // Consensus engine configuration parameters config *params.CliqueConfig // Consensus engine configuration parameters
db ethdb.Database // Database to store and retrieve snapshot checkpoints db database.Database // Database to store and retrieve snapshot checkpoints
recents *lru.ARCCache // Snapshots for recent block to speed up reorgs recents *lru.ARCCache // Snapshots for recent block to speed up reorgs
signatures *lru.ARCCache // Signatures of recent blocks to speed up mining signatures *lru.ARCCache // Signatures of recent blocks to speed up mining
@ -187,7 +187,7 @@ type Clique struct {
// New creates a Clique proof-of-authority consensus engine with the initial // New creates a Clique proof-of-authority consensus engine with the initial
// signers set to the ones provided by the user. // signers set to the ones provided by the user.
func New(config *params.CliqueConfig, db ethdb.Database) *Clique { func New(config *params.CliqueConfig, db database.Database) *Clique {
// Set any missing consensus parameters to their defaults // Set any missing consensus parameters to their defaults
conf := *config conf := *config
if conf.Epoch == 0 { if conf.Epoch == 0 {

View file

@ -23,7 +23,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/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
lru "github.com/hashicorp/golang-lru" lru "github.com/hashicorp/golang-lru"
) )
@ -84,7 +84,7 @@ func newSnapshot(config *params.CliqueConfig, sigcache *lru.ARCCache, number uin
} }
// loadSnapshot loads an existing snapshot from the database. // loadSnapshot loads an existing snapshot from the database.
func loadSnapshot(config *params.CliqueConfig, sigcache *lru.ARCCache, db ethdb.Database, hash common.Hash) (*Snapshot, error) { func loadSnapshot(config *params.CliqueConfig, sigcache *lru.ARCCache, db database.Database, hash common.Hash) (*Snapshot, error) {
blob, err := db.Get(append([]byte("clique-"), hash[:]...)) blob, err := db.Get(append([]byte("clique-"), hash[:]...))
if err != nil { if err != nil {
return nil, err return nil, err
@ -100,7 +100,7 @@ func loadSnapshot(config *params.CliqueConfig, sigcache *lru.ARCCache, db ethdb.
} }
// store inserts the snapshot into the database. // store inserts the snapshot into the database.
func (s *Snapshot) store(db ethdb.Database) error { func (s *Snapshot) store(db database.Database) error {
blob, err := json.Marshal(s) blob, err := json.Marshal(s)
if err != nil { if err != nil {
return err return err

View file

@ -24,10 +24,10 @@ 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/rawdb"
"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/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/params" "github.com/ethereum/go-ethereum/params"
) )
@ -400,7 +400,7 @@ func TestClique(t *testing.T) {
copy(genesis.ExtraData[extraVanity+j*common.AddressLength:], signer[:]) copy(genesis.ExtraData[extraVanity+j*common.AddressLength:], signer[:])
} }
// Create a pristine blockchain with the genesis injected // Create a pristine blockchain with the genesis injected
db := ethdb.NewMemDatabase() db := rawdb.NewMemoryDatabase()
genesis.Commit(db) genesis.Commit(db)
// Assemble a chain of headers from the cast votes // Assemble a chain of headers from the cast votes

View file

@ -30,7 +30,7 @@ import (
"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/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/database"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
) )
@ -148,16 +148,16 @@ func genUncles(i int, gen *BlockGen) {
func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) { func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
// Create the database in memory or in a temporary directory. // Create the database in memory or in a temporary directory.
var db ethdb.Database var db database.Database
if !disk { if !disk {
db = ethdb.NewMemDatabase() db = rawdb.NewMemoryDatabase()
} else { } else {
dir, err := ioutil.TempDir("", "eth-core-bench") dir, err := ioutil.TempDir("", "eth-core-bench")
if err != nil { if err != nil {
b.Fatalf("cannot create temporary directory: %v", err) b.Fatalf("cannot create temporary directory: %v", err)
} }
defer os.RemoveAll(dir) defer os.RemoveAll(dir)
db, err = ethdb.NewLDBDatabase(dir, 128, 128) db, err = rawdb.NewLeveldbDatabase(dir, 128, 128, "")
if err != nil { if err != nil {
b.Fatalf("cannot create temporary database: %v", err) b.Fatalf("cannot create temporary database: %v", err)
} }
@ -223,7 +223,7 @@ func BenchmarkChainWrite_full_500k(b *testing.B) {
// makeChainForBench writes a given number of headers or empty blocks/receipts // makeChainForBench writes a given number of headers or empty blocks/receipts
// into a database. // into a database.
func makeChainForBench(db ethdb.Database, full bool, count uint64) { func makeChainForBench(db database.Database, full bool, count uint64) {
var hash common.Hash var hash common.Hash
for n := uint64(0); n < count; n++ { for n := uint64(0); n < count; n++ {
header := &types.Header{ header := &types.Header{
@ -255,7 +255,7 @@ func benchWriteChain(b *testing.B, full bool, count uint64) {
if err != nil { if err != nil {
b.Fatalf("cannot create temporary directory: %v", err) b.Fatalf("cannot create temporary directory: %v", err)
} }
db, err := ethdb.NewLDBDatabase(dir, 128, 1024) db, err := rawdb.NewLeveldbDatabase(dir, 128, 1024, "")
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)
} }
@ -272,7 +272,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
} }
defer os.RemoveAll(dir) defer os.RemoveAll(dir)
db, err := ethdb.NewLDBDatabase(dir, 128, 1024) db, err := rawdb.NewLeveldbDatabase(dir, 128, 1024, "")
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)
} }
@ -283,7 +283,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
db, err := ethdb.NewLDBDatabase(dir, 128, 1024) db, err := rawdb.NewLeveldbDatabase(dir, 128, 1024, "")
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)
} }

View file

@ -22,9 +22,9 @@ import (
"time" "time"
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core/rawdb"
"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/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
) )
@ -32,7 +32,7 @@ import (
func TestHeaderVerification(t *testing.T) { func TestHeaderVerification(t *testing.T) {
// Create a simple chain to verify // Create a simple chain to verify
var ( var (
testdb = ethdb.NewMemDatabase() testdb = rawdb.NewMemoryDatabase()
gspec = &Genesis{Config: params.TestChainConfig} gspec = &Genesis{Config: params.TestChainConfig}
genesis = gspec.MustCommit(testdb) genesis = gspec.MustCommit(testdb)
blocks, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), testdb, 8, nil) blocks, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), testdb, 8, nil)
@ -84,7 +84,7 @@ func TestHeaderConcurrentVerification32(t *testing.T) { testHeaderConcurrentVeri
func testHeaderConcurrentVerification(t *testing.T, threads int) { func testHeaderConcurrentVerification(t *testing.T, threads int) {
// Create a simple chain to verify // Create a simple chain to verify
var ( var (
testdb = ethdb.NewMemDatabase() testdb = rawdb.NewMemoryDatabase()
gspec = &Genesis{Config: params.TestChainConfig} gspec = &Genesis{Config: params.TestChainConfig}
genesis = gspec.MustCommit(testdb) genesis = gspec.MustCommit(testdb)
blocks, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), testdb, 8, nil) blocks, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), testdb, 8, nil)
@ -156,7 +156,7 @@ func TestHeaderConcurrentAbortion32(t *testing.T) { testHeaderConcurrentAbortion
func testHeaderConcurrentAbortion(t *testing.T, threads int) { func testHeaderConcurrentAbortion(t *testing.T, threads int) {
// Create a simple chain to verify // Create a simple chain to verify
var ( var (
testdb = ethdb.NewMemDatabase() testdb = rawdb.NewMemoryDatabase()
gspec = &Genesis{Config: params.TestChainConfig} gspec = &Genesis{Config: params.TestChainConfig}
genesis = gspec.MustCommit(testdb) genesis = gspec.MustCommit(testdb)
blocks, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), testdb, 1024, nil) blocks, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), testdb, 1024, nil)

View file

@ -36,7 +36,7 @@ import (
"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/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/database"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"
@ -95,7 +95,7 @@ type BlockChain struct {
chainConfig *params.ChainConfig // Chain & network configuration chainConfig *params.ChainConfig // Chain & network configuration
cacheConfig *CacheConfig // Cache configuration for pruning cacheConfig *CacheConfig // Cache configuration for pruning
db ethdb.Database // Low level persistent database to store final content in db database.Database // Low level persistent database to store final content in
triegc *prque.Prque // Priority queue mapping block numbers to tries to gc triegc *prque.Prque // Priority queue mapping block numbers to tries to gc
gcproc time.Duration // Accumulates canonical block processing for trie dumping gcproc time.Duration // Accumulates canonical block processing for trie dumping
@ -140,7 +140,7 @@ type BlockChain struct {
// NewBlockChain returns a fully initialised block chain using information // NewBlockChain returns a fully initialised block chain using information
// available in the database. It initialises the default Ethereum Validator and // available in the database. It initialises the default Ethereum Validator and
// Processor. // Processor.
func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, engine consensus.Engine, vmConfig vm.Config, shouldPreserve func(block *types.Block) bool) (*BlockChain, error) { func NewBlockChain(db database.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, engine consensus.Engine, vmConfig vm.Config, shouldPreserve func(block *types.Block) bool) (*BlockChain, error) {
if cacheConfig == nil { if cacheConfig == nil {
cacheConfig = &CacheConfig{ cacheConfig = &CacheConfig{
TrieCleanLimit: 256, TrieCleanLimit: 256,
@ -284,7 +284,7 @@ func (bc *BlockChain) SetHead(head uint64) error {
defer bc.chainmu.Unlock() defer bc.chainmu.Unlock()
// Rewind the header chain, deleting all block bodies until then // Rewind the header chain, deleting all block bodies until then
delFn := func(db rawdb.DatabaseDeleter, hash common.Hash, num uint64) { delFn := func(db database.Deleter, hash common.Hash, num uint64) {
rawdb.DeleteBody(db, hash, num) rawdb.DeleteBody(db, hash, num)
} }
bc.hc.SetHead(head, delFn) bc.hc.SetHead(head, delFn)
@ -866,7 +866,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
stats.processed++ stats.processed++
if batch.ValueSize() >= ethdb.IdealBatchSize { if batch.ValueSize() >= database.IdealBatchSize {
if err := batch.Write(); err != nil { if err := batch.Write(); err != nil {
return 0, err return 0, err
} }
@ -976,7 +976,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
limit = common.StorageSize(bc.cacheConfig.TrieDirtyLimit) * 1024 * 1024 limit = common.StorageSize(bc.cacheConfig.TrieDirtyLimit) * 1024 * 1024
) )
if nodes > limit || imgs > 4*1024*1024 { if nodes > limit || imgs > 4*1024*1024 {
triedb.Cap(limit - ethdb.IdealBatchSize) triedb.Cap(limit - database.IdealBatchSize)
} }
// Find the next state trie we need to commit // Find the next state trie we need to commit
chosen := current - triesInMemory chosen := current - triesInMemory

View file

@ -32,7 +32,7 @@ import (
"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/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/database"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
) )
@ -45,9 +45,9 @@ var (
// newCanonical creates a chain database, and injects a deterministic canonical // newCanonical creates a chain database, and injects a deterministic canonical
// chain. Depending on the full flag, if creates either a full block chain or a // chain. Depending on the full flag, if creates either a full block chain or a
// header only chain. // header only chain.
func newCanonical(engine consensus.Engine, n int, full bool) (ethdb.Database, *BlockChain, error) { func newCanonical(engine consensus.Engine, n int, full bool) (database.Database, *BlockChain, error) {
var ( var (
db = ethdb.NewMemDatabase() db = rawdb.NewMemoryDatabase()
genesis = new(Genesis).MustCommit(db) genesis = new(Genesis).MustCommit(db)
) )
@ -603,7 +603,7 @@ func testInsertNonceError(t *testing.T, full bool) {
func TestFastVsFullChains(t *testing.T) { func TestFastVsFullChains(t *testing.T) {
// Configure and generate a sample block chain // Configure and generate a sample block chain
var ( var (
gendb = ethdb.NewMemDatabase() gendb = rawdb.NewMemoryDatabase()
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
address = crypto.PubkeyToAddress(key.PublicKey) address = crypto.PubkeyToAddress(key.PublicKey)
funds = big.NewInt(1000000000) funds = big.NewInt(1000000000)
@ -633,7 +633,7 @@ func TestFastVsFullChains(t *testing.T) {
} }
}) })
// Import the chain as an archive node for the comparison baseline // Import the chain as an archive node for the comparison baseline
archiveDb := ethdb.NewMemDatabase() archiveDb := rawdb.NewMemoryDatabase()
gspec.MustCommit(archiveDb) gspec.MustCommit(archiveDb)
archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil)
defer archive.Stop() defer archive.Stop()
@ -642,7 +642,7 @@ func TestFastVsFullChains(t *testing.T) {
t.Fatalf("failed to process block %d: %v", n, err) t.Fatalf("failed to process block %d: %v", n, err)
} }
// 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 := rawdb.NewMemoryDatabase()
gspec.MustCommit(fastDb) gspec.MustCommit(fastDb)
fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil)
defer fast.Stop() defer fast.Stop()
@ -691,7 +691,7 @@ func TestFastVsFullChains(t *testing.T) {
func TestLightVsFastVsFullChainHeads(t *testing.T) { func TestLightVsFastVsFullChainHeads(t *testing.T) {
// Configure and generate a sample block chain // Configure and generate a sample block chain
var ( var (
gendb = ethdb.NewMemDatabase() gendb = rawdb.NewMemoryDatabase()
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
address = crypto.PubkeyToAddress(key.PublicKey) address = crypto.PubkeyToAddress(key.PublicKey)
funds = big.NewInt(1000000000) funds = big.NewInt(1000000000)
@ -719,7 +719,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
} }
} }
// Import the chain as an archive node and ensure all pointers are updated // Import the chain as an archive node and ensure all pointers are updated
archiveDb := ethdb.NewMemDatabase() archiveDb := rawdb.NewMemoryDatabase()
gspec.MustCommit(archiveDb) gspec.MustCommit(archiveDb)
archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil)
@ -733,7 +733,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
assert(t, "archive", archive, height/2, height/2, height/2) assert(t, "archive", archive, height/2, height/2, height/2)
// 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 := rawdb.NewMemoryDatabase()
gspec.MustCommit(fastDb) gspec.MustCommit(fastDb)
fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil)
defer fast.Stop() defer fast.Stop()
@ -753,7 +753,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
assert(t, "fast", fast, height/2, height/2, 0) assert(t, "fast", fast, height/2, height/2, 0)
// 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 := rawdb.NewMemoryDatabase()
gspec.MustCommit(lightDb) gspec.MustCommit(lightDb)
light, _ := NewBlockChain(lightDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) light, _ := NewBlockChain(lightDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil)
@ -776,7 +776,7 @@ func TestChainTxReorgs(t *testing.T) {
addr1 = crypto.PubkeyToAddress(key1.PublicKey) addr1 = crypto.PubkeyToAddress(key1.PublicKey)
addr2 = crypto.PubkeyToAddress(key2.PublicKey) addr2 = crypto.PubkeyToAddress(key2.PublicKey)
addr3 = crypto.PubkeyToAddress(key3.PublicKey) addr3 = crypto.PubkeyToAddress(key3.PublicKey)
db = ethdb.NewMemDatabase() db = rawdb.NewMemoryDatabase()
gspec = &Genesis{ gspec = &Genesis{
Config: params.TestChainConfig, Config: params.TestChainConfig,
GasLimit: 3141592, GasLimit: 3141592,
@ -888,7 +888,7 @@ func TestLogReorgs(t *testing.T) {
var ( var (
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
addr1 = crypto.PubkeyToAddress(key1.PublicKey) addr1 = crypto.PubkeyToAddress(key1.PublicKey)
db = ethdb.NewMemDatabase() db = rawdb.NewMemoryDatabase()
// this code generates a log // this code generates a log
code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00")
gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}} gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}}
@ -932,7 +932,7 @@ func TestLogReorgs(t *testing.T) {
func TestReorgSideEvent(t *testing.T) { func TestReorgSideEvent(t *testing.T) {
var ( var (
db = ethdb.NewMemDatabase() db = rawdb.NewMemoryDatabase()
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
addr1 = crypto.PubkeyToAddress(key1.PublicKey) addr1 = crypto.PubkeyToAddress(key1.PublicKey)
gspec = &Genesis{ gspec = &Genesis{
@ -1060,7 +1060,7 @@ func TestCanonicalBlockRetrieval(t *testing.T) {
func TestEIP155Transition(t *testing.T) { func TestEIP155Transition(t *testing.T) {
// Configure and generate a sample block chain // Configure and generate a sample block chain
var ( var (
db = ethdb.NewMemDatabase() db = rawdb.NewMemoryDatabase()
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
address = crypto.PubkeyToAddress(key.PublicKey) address = crypto.PubkeyToAddress(key.PublicKey)
funds = big.NewInt(1000000000) funds = big.NewInt(1000000000)
@ -1163,7 +1163,7 @@ func TestEIP155Transition(t *testing.T) {
func TestEIP161AccountRemoval(t *testing.T) { func TestEIP161AccountRemoval(t *testing.T) {
// Configure and generate a sample block chain // Configure and generate a sample block chain
var ( var (
db = ethdb.NewMemDatabase() db = rawdb.NewMemoryDatabase()
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
address = crypto.PubkeyToAddress(key.PublicKey) address = crypto.PubkeyToAddress(key.PublicKey)
funds = big.NewInt(1000000000) funds = big.NewInt(1000000000)
@ -1235,7 +1235,7 @@ func TestBlockchainHeaderchainReorgConsistency(t *testing.T) {
// Generate a canonical chain to act as the main dataset // Generate a canonical chain to act as the main dataset
engine := ethash.NewFaker() engine := ethash.NewFaker()
db := ethdb.NewMemDatabase() db := rawdb.NewMemoryDatabase()
genesis := new(Genesis).MustCommit(db) genesis := new(Genesis).MustCommit(db)
blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) })
@ -1251,7 +1251,7 @@ func TestBlockchainHeaderchainReorgConsistency(t *testing.T) {
} }
// Import the canonical and fork chain side by side, verifying the current block // Import the canonical and fork chain side by side, verifying the current block
// and current header consistency // and current header consistency
diskdb := ethdb.NewMemDatabase() diskdb := rawdb.NewMemoryDatabase()
new(Genesis).MustCommit(diskdb) new(Genesis).MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil)
@ -1280,7 +1280,7 @@ func TestTrieForkGC(t *testing.T) {
// Generate a canonical chain to act as the main dataset // Generate a canonical chain to act as the main dataset
engine := ethash.NewFaker() engine := ethash.NewFaker()
db := ethdb.NewMemDatabase() db := rawdb.NewMemoryDatabase()
genesis := new(Genesis).MustCommit(db) genesis := new(Genesis).MustCommit(db)
blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*triesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*triesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) })
@ -1295,7 +1295,7 @@ func TestTrieForkGC(t *testing.T) {
forks[i] = fork[0] forks[i] = fork[0]
} }
// Import the canonical and fork chain side by side, forcing the trie cache to cache both // Import the canonical and fork chain side by side, forcing the trie cache to cache both
diskdb := ethdb.NewMemDatabase() diskdb := rawdb.NewMemoryDatabase()
new(Genesis).MustCommit(diskdb) new(Genesis).MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil)
@ -1326,7 +1326,7 @@ func TestLargeReorgTrieGC(t *testing.T) {
// Generate the original common chain segment and the two competing forks // Generate the original common chain segment and the two competing forks
engine := ethash.NewFaker() engine := ethash.NewFaker()
db := ethdb.NewMemDatabase() db := rawdb.NewMemoryDatabase()
genesis := new(Genesis).MustCommit(db) genesis := new(Genesis).MustCommit(db)
shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) })
@ -1334,7 +1334,7 @@ func TestLargeReorgTrieGC(t *testing.T) {
competitor, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*triesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) }) competitor, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*triesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) })
// Import the shared chain and the original canonical one // Import the shared chain and the original canonical one
diskdb := ethdb.NewMemDatabase() diskdb := rawdb.NewMemoryDatabase()
new(Genesis).MustCommit(diskdb) new(Genesis).MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil)
@ -1394,7 +1394,7 @@ func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks in
) )
// Generate the original common chain segment and the two competing forks // Generate the original common chain segment and the two competing forks
engine := ethash.NewFaker() engine := ethash.NewFaker()
db := ethdb.NewMemDatabase() db := rawdb.NewMemoryDatabase()
genesis := gspec.MustCommit(db) genesis := gspec.MustCommit(db)
blockGenerator := func(i int, block *BlockGen) { blockGenerator := func(i int, block *BlockGen) {
@ -1416,7 +1416,7 @@ func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks in
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
// Import the shared chain and the original canonical one // Import the shared chain and the original canonical one
diskdb := ethdb.NewMemDatabase() diskdb := rawdb.NewMemoryDatabase()
gspec.MustCommit(diskdb) gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil)
@ -1494,7 +1494,7 @@ func BenchmarkBlockChain_1x1000Executions(b *testing.B) {
func TestLowDiffLongChain(t *testing.T) { func TestLowDiffLongChain(t *testing.T) {
// Generate a canonical chain to act as the main dataset // Generate a canonical chain to act as the main dataset
engine := ethash.NewFaker() engine := ethash.NewFaker()
db := ethdb.NewMemDatabase() db := rawdb.NewMemoryDatabase()
genesis := new(Genesis).MustCommit(db) genesis := new(Genesis).MustCommit(db)
// We must use a pretty long chain to ensure that the fork doesn't overtake us // We must use a pretty long chain to ensure that the fork doesn't overtake us
@ -1505,7 +1505,7 @@ func TestLowDiffLongChain(t *testing.T) {
}) })
// Import the canonical chain // Import the canonical chain
diskdb := ethdb.NewMemDatabase() diskdb := rawdb.NewMemoryDatabase()
new(Genesis).MustCommit(diskdb) new(Genesis).MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil)

View file

@ -27,7 +27,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
@ -67,8 +67,8 @@ type ChainIndexerChain interface {
// after an entire section has been finished or in case of rollbacks that might // after an entire section has been finished or in case of rollbacks that might
// affect already finished sections. // affect already finished sections.
type ChainIndexer struct { type ChainIndexer struct {
chainDb ethdb.Database // Chain database to index the data from chainDb database.Database // Chain database to index the data from
indexDb ethdb.Database // Prefixed table-view of the db to write index metadata into indexDb database.Database // Prefixed table-view of the db to write index metadata into
backend ChainIndexerBackend // Background processor generating the index data content backend ChainIndexerBackend // Background processor generating the index data content
children []*ChainIndexer // Child indexers to cascade chain updates to children []*ChainIndexer // Child indexers to cascade chain updates to
@ -97,7 +97,7 @@ type ChainIndexer struct {
// NewChainIndexer creates a new chain indexer to do background processing on // NewChainIndexer creates a new chain indexer to do background processing on
// chain segments of a given size after certain number of confirmations passed. // chain segments of a given size after certain number of confirmations passed.
// The throttling parameter might be used to prevent database thrashing. // The throttling parameter might be used to prevent database thrashing.
func NewChainIndexer(chainDb, indexDb ethdb.Database, backend ChainIndexerBackend, section, confirm uint64, throttling time.Duration, kind string) *ChainIndexer { func NewChainIndexer(chainDb database.Database, indexDb database.Database, backend ChainIndexerBackend, section, confirm uint64, throttling time.Duration, kind string) *ChainIndexer {
c := &ChainIndexer{ c := &ChainIndexer{
chainDb: chainDb, chainDb: chainDb,
indexDb: indexDb, indexDb: indexDb,

View file

@ -27,7 +27,6 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
) )
// Runs multiple tests with randomized parameters. // Runs multiple tests with randomized parameters.
@ -49,7 +48,7 @@ func TestChainIndexerWithChildren(t *testing.T) {
// multiple backends. The section size and required confirmation count parameters // multiple backends. The section size and required confirmation count parameters
// are randomized. // are randomized.
func testChainIndexer(t *testing.T, count int) { func testChainIndexer(t *testing.T, count int) {
db := ethdb.NewMemDatabase() db := rawdb.NewMemoryDatabase()
defer db.Close() defer db.Close()
// Create a chain of indexers and ensure they all report empty // Create a chain of indexers and ensure they all report empty
@ -60,7 +59,7 @@ func testChainIndexer(t *testing.T, count int) {
confirmsReq = uint64(rand.Intn(10)) confirmsReq = uint64(rand.Intn(10))
) )
backends[i] = &testChainIndexBackend{t: t, processCh: make(chan uint64)} backends[i] = &testChainIndexBackend{t: t, processCh: make(chan uint64)}
backends[i].indexer = NewChainIndexer(db, ethdb.NewTable(db, string([]byte{byte(i)})), backends[i], sectionSize, confirmsReq, 0, fmt.Sprintf("indexer-%d", i)) backends[i].indexer = NewChainIndexer(db, rawdb.NewTable(db, string([]byte{byte(i)})), backends[i], sectionSize, confirmsReq, 0, fmt.Sprintf("indexer-%d", i))
if sections, _, _ := backends[i].indexer.Sections(); sections != 0 { if sections, _, _ := backends[i].indexer.Sections(); sections != 0 {
t.Fatalf("Canonical section count mismatch: have %v, want %v", sections, 0) t.Fatalf("Canonical section count mismatch: have %v, want %v", sections, 0)

View file

@ -26,7 +26,7 @@ import (
"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/core/vm"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
) )
@ -169,7 +169,7 @@ func (b *BlockGen) OffsetTime(seconds int64) {
// Blocks created by GenerateChain do not contain valid proof of work // Blocks created by GenerateChain do not contain valid proof of work
// values. Inserting them into BlockChain requires use of FakePow or // values. Inserting them into BlockChain requires use of FakePow or
// a similar non-validating proof of work implementation. // a similar non-validating proof of work implementation.
func GenerateChain(config *params.ChainConfig, parent *types.Block, engine consensus.Engine, db ethdb.Database, n int, gen func(int, *BlockGen)) ([]*types.Block, []types.Receipts) { func GenerateChain(config *params.ChainConfig, parent *types.Block, engine consensus.Engine, db database.Database, n int, gen func(int, *BlockGen)) ([]*types.Block, []types.Receipts) {
if config == nil { if config == nil {
config = params.TestChainConfig config = params.TestChainConfig
} }
@ -249,7 +249,7 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.S
} }
// makeHeaderChain creates a deterministic chain of headers rooted at parent. // makeHeaderChain creates a deterministic chain of headers rooted at parent.
func makeHeaderChain(parent *types.Header, n int, engine consensus.Engine, db ethdb.Database, seed int) []*types.Header { func makeHeaderChain(parent *types.Header, n int, engine consensus.Engine, db database.Database, seed int) []*types.Header {
blocks := makeBlockChain(types.NewBlockWithHeader(parent), n, engine, db, seed) blocks := makeBlockChain(types.NewBlockWithHeader(parent), n, engine, db, seed)
headers := make([]*types.Header, len(blocks)) headers := make([]*types.Header, len(blocks))
for i, block := range blocks { for i, block := range blocks {
@ -259,7 +259,7 @@ func makeHeaderChain(parent *types.Header, n int, engine consensus.Engine, db et
} }
// makeBlockChain creates a deterministic chain of blocks rooted at parent. // makeBlockChain creates a deterministic chain of blocks rooted at parent.
func makeBlockChain(parent *types.Block, n int, engine consensus.Engine, db ethdb.Database, seed int) []*types.Block { func makeBlockChain(parent *types.Block, n int, engine consensus.Engine, db database.Database, seed int) []*types.Block {
blocks, _ := GenerateChain(params.TestChainConfig, parent, engine, db, n, func(i int, b *BlockGen) { blocks, _ := GenerateChain(params.TestChainConfig, parent, engine, db, n, func(i int, b *BlockGen) {
b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)}) b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)})
}) })

View file

@ -21,10 +21,10 @@ import (
"math/big" "math/big"
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core/rawdb"
"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/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/params" "github.com/ethereum/go-ethereum/params"
) )
@ -36,7 +36,7 @@ func ExampleGenerateChain() {
addr1 = crypto.PubkeyToAddress(key1.PublicKey) addr1 = crypto.PubkeyToAddress(key1.PublicKey)
addr2 = crypto.PubkeyToAddress(key2.PublicKey) addr2 = crypto.PubkeyToAddress(key2.PublicKey)
addr3 = crypto.PubkeyToAddress(key3.PublicKey) addr3 = crypto.PubkeyToAddress(key3.PublicKey)
db = ethdb.NewMemDatabase() db = rawdb.NewMemoryDatabase()
) )
// Ensure that key1 has some funds in the genesis block. // Ensure that key1 has some funds in the genesis block.

View file

@ -21,8 +21,8 @@ import (
"testing" "testing"
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
) )
@ -32,13 +32,13 @@ func TestDAOForkRangeExtradata(t *testing.T) {
forkBlock := big.NewInt(32) forkBlock := big.NewInt(32)
// Generate a common prefix for both pro-forkers and non-forkers // Generate a common prefix for both pro-forkers and non-forkers
db := ethdb.NewMemDatabase() db := rawdb.NewMemoryDatabase()
gspec := new(Genesis) gspec := new(Genesis)
genesis := gspec.MustCommit(db) genesis := gspec.MustCommit(db)
prefix, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, int(forkBlock.Int64()-1), func(i int, gen *BlockGen) {}) prefix, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, int(forkBlock.Int64()-1), func(i int, gen *BlockGen) {})
// Create the concurrent, conflicting two nodes // Create the concurrent, conflicting two nodes
proDb := ethdb.NewMemDatabase() proDb := rawdb.NewMemoryDatabase()
gspec.MustCommit(proDb) gspec.MustCommit(proDb)
proConf := *params.TestChainConfig proConf := *params.TestChainConfig
@ -48,7 +48,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
proBc, _ := NewBlockChain(proDb, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil) proBc, _ := NewBlockChain(proDb, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil)
defer proBc.Stop() defer proBc.Stop()
conDb := ethdb.NewMemDatabase() conDb := rawdb.NewMemoryDatabase()
gspec.MustCommit(conDb) gspec.MustCommit(conDb)
conConf := *params.TestChainConfig conConf := *params.TestChainConfig
@ -67,7 +67,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
// Try to expand both pro-fork and non-fork chains iteratively with other camp's blocks // Try to expand both pro-fork and non-fork chains iteratively with other camp's blocks
for i := int64(0); i < params.DAOForkExtraRange.Int64(); i++ { for i := int64(0); i < params.DAOForkExtraRange.Int64(); i++ {
// 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 = rawdb.NewMemoryDatabase()
gspec.MustCommit(db) gspec.MustCommit(db)
bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{}, nil) bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{}, nil)
defer bc.Stop() defer bc.Stop()
@ -92,7 +92,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
t.Fatalf("contra-fork chain didn't accepted no-fork block: %v", err) t.Fatalf("contra-fork chain didn't accepted no-fork block: %v", err)
} }
// 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 = rawdb.NewMemoryDatabase()
gspec.MustCommit(db) gspec.MustCommit(db)
bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil) bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil)
defer bc.Stop() defer bc.Stop()
@ -118,7 +118,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 = rawdb.NewMemoryDatabase()
gspec.MustCommit(db) gspec.MustCommit(db)
bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{}, nil) bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{}, nil)
defer bc.Stop() defer bc.Stop()
@ -138,7 +138,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
t.Fatalf("contra-fork chain didn't accept pro-fork block post-fork: %v", err) t.Fatalf("contra-fork chain didn't accept pro-fork block post-fork: %v", err)
} }
// 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 = rawdb.NewMemoryDatabase()
gspec.MustCommit(db) gspec.MustCommit(db)
bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil) bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil)
defer bc.Stop() defer bc.Stop()

View file

@ -31,7 +31,7 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"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/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
@ -134,7 +134,7 @@ type GenesisMismatchError struct {
} }
func (e *GenesisMismatchError) Error() string { func (e *GenesisMismatchError) Error() string {
return fmt.Sprintf("database already contains an incompatible genesis block (have %x, new %x)", e.Stored[:8], e.New[:8]) return fmt.Sprintf("database contains incompatible genesis (have %x, new %x)", e.Stored, e.New)
} }
// SetupGenesisBlock writes or updates the genesis block in db. // SetupGenesisBlock writes or updates the genesis block in db.
@ -150,10 +150,10 @@ func (e *GenesisMismatchError) Error() string {
// error is a *params.ConfigCompatError and the new, unwritten config is returned. // error is a *params.ConfigCompatError and the new, unwritten config is returned.
// //
// The returned chain configuration is never nil. // The returned chain configuration is never nil.
func SetupGenesisBlock(db ethdb.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, error) { func SetupGenesisBlock(db database.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, error) {
return SetupGenesisBlockWithOverride(db, genesis, nil) return SetupGenesisBlockWithOverride(db, genesis, nil)
} }
func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, constantinopleOverride *big.Int) (*params.ChainConfig, common.Hash, error) { func SetupGenesisBlockWithOverride(db database.Database, genesis *Genesis, constantinopleOverride *big.Int) (*params.ChainConfig, common.Hash, error) {
if genesis != nil && genesis.Config == nil { if genesis != nil && genesis.Config == nil {
return params.AllEthashProtocolChanges, common.Hash{}, errGenesisNoConfig return params.AllEthashProtocolChanges, common.Hash{}, errGenesisNoConfig
} }
@ -226,9 +226,9 @@ func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
// ToBlock creates the genesis block and writes state of a genesis specification // ToBlock creates the genesis block and writes state of a genesis specification
// to the given database (or discards it if nil). // to the given database (or discards it if nil).
func (g *Genesis) ToBlock(db ethdb.Database) *types.Block { func (g *Genesis) ToBlock(db database.Database) *types.Block {
if db == nil { if db == nil {
db = ethdb.NewMemDatabase() db = rawdb.NewMemoryDatabase()
} }
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
for addr, account := range g.Alloc { for addr, account := range g.Alloc {
@ -267,7 +267,7 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
// Commit writes the block and state of a genesis specification to the database. // Commit writes the block and state of a genesis specification to the database.
// The block is committed as the canonical head block. // The block is committed as the canonical head block.
func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) { func (g *Genesis) Commit(db database.Database) (*types.Block, error) {
block := g.ToBlock(db) block := g.ToBlock(db)
if block.Number().Sign() != 0 { if block.Number().Sign() != 0 {
return nil, fmt.Errorf("can't commit genesis block with number > 0") return nil, fmt.Errorf("can't commit genesis block with number > 0")
@ -289,7 +289,7 @@ func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) {
// MustCommit writes the genesis block and state to db, panicking on error. // MustCommit writes the genesis block and state to db, panicking on error.
// The block is committed as the canonical head block. // The block is committed as the canonical head block.
func (g *Genesis) MustCommit(db ethdb.Database) *types.Block { func (g *Genesis) MustCommit(db database.Database) *types.Block {
block, err := g.Commit(db) block, err := g.Commit(db)
if err != nil { if err != nil {
panic(err) panic(err)
@ -298,7 +298,7 @@ func (g *Genesis) MustCommit(db ethdb.Database) *types.Block {
} }
// GenesisBlockForTesting creates and writes a block in which addr has the given wei balance. // GenesisBlockForTesting creates and writes a block in which addr has the given wei balance.
func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big.Int) *types.Block { func GenesisBlockForTesting(db database.Database, addr common.Address, balance *big.Int) *types.Block {
g := Genesis{Alloc: GenesisAlloc{addr: {Balance: balance}}} g := Genesis{Alloc: GenesisAlloc{addr: {Balance: balance}}}
return g.MustCommit(db) return g.MustCommit(db)
} }

View file

@ -26,7 +26,7 @@ import (
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
) )
@ -55,14 +55,14 @@ func TestSetupGenesis(t *testing.T) {
oldcustomg.Config = &params.ChainConfig{HomesteadBlock: big.NewInt(2)} oldcustomg.Config = &params.ChainConfig{HomesteadBlock: big.NewInt(2)}
tests := []struct { tests := []struct {
name string name string
fn func(ethdb.Database) (*params.ChainConfig, common.Hash, error) fn func(database.Database) (*params.ChainConfig, common.Hash, error)
wantConfig *params.ChainConfig wantConfig *params.ChainConfig
wantHash common.Hash wantHash common.Hash
wantErr error wantErr error
}{ }{
{ {
name: "genesis without ChainConfig", name: "genesis without ChainConfig",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { fn: func(db database.Database) (*params.ChainConfig, common.Hash, error) {
return SetupGenesisBlock(db, new(Genesis)) return SetupGenesisBlock(db, new(Genesis))
}, },
wantErr: errGenesisNoConfig, wantErr: errGenesisNoConfig,
@ -70,7 +70,7 @@ func TestSetupGenesis(t *testing.T) {
}, },
{ {
name: "no block in DB, genesis == nil", name: "no block in DB, genesis == nil",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { fn: func(db database.Database) (*params.ChainConfig, common.Hash, error) {
return SetupGenesisBlock(db, nil) return SetupGenesisBlock(db, nil)
}, },
wantHash: params.MainnetGenesisHash, wantHash: params.MainnetGenesisHash,
@ -78,7 +78,7 @@ func TestSetupGenesis(t *testing.T) {
}, },
{ {
name: "mainnet block in DB, genesis == nil", name: "mainnet block in DB, genesis == nil",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { fn: func(db database.Database) (*params.ChainConfig, common.Hash, error) {
DefaultGenesisBlock().MustCommit(db) DefaultGenesisBlock().MustCommit(db)
return SetupGenesisBlock(db, nil) return SetupGenesisBlock(db, nil)
}, },
@ -87,7 +87,7 @@ func TestSetupGenesis(t *testing.T) {
}, },
{ {
name: "custom block in DB, genesis == nil", name: "custom block in DB, genesis == nil",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { fn: func(db database.Database) (*params.ChainConfig, common.Hash, error) {
customg.MustCommit(db) customg.MustCommit(db)
return SetupGenesisBlock(db, nil) return SetupGenesisBlock(db, nil)
}, },
@ -96,7 +96,7 @@ func TestSetupGenesis(t *testing.T) {
}, },
{ {
name: "custom block in DB, genesis == testnet", name: "custom block in DB, genesis == testnet",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { fn: func(db database.Database) (*params.ChainConfig, common.Hash, error) {
customg.MustCommit(db) customg.MustCommit(db)
return SetupGenesisBlock(db, DefaultTestnetGenesisBlock()) return SetupGenesisBlock(db, DefaultTestnetGenesisBlock())
}, },
@ -106,7 +106,7 @@ func TestSetupGenesis(t *testing.T) {
}, },
{ {
name: "compatible config in DB", name: "compatible config in DB",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { fn: func(db database.Database) (*params.ChainConfig, common.Hash, error) {
oldcustomg.MustCommit(db) oldcustomg.MustCommit(db)
return SetupGenesisBlock(db, &customg) return SetupGenesisBlock(db, &customg)
}, },
@ -115,7 +115,7 @@ func TestSetupGenesis(t *testing.T) {
}, },
{ {
name: "incompatible config in DB", name: "incompatible config in DB",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { fn: func(db database.Database) (*params.ChainConfig, common.Hash, error) {
// Commit the 'old' genesis block with Homestead transition at #2. // Commit the 'old' genesis block with Homestead transition at #2.
// Advance to block #4, past the homestead transition block of customg. // Advance to block #4, past the homestead transition block of customg.
genesis := oldcustomg.MustCommit(db) genesis := oldcustomg.MustCommit(db)
@ -141,7 +141,7 @@ func TestSetupGenesis(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
db := ethdb.NewMemDatabase() db := rawdb.NewMemoryDatabase()
config, hash, err := test.fn(db) config, hash, err := test.fn(db)
// Check the return values. // Check the return values.
if !reflect.DeepEqual(err, test.wantErr) { if !reflect.DeepEqual(err, test.wantErr) {

View file

@ -30,7 +30,7 @@ import (
"github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/hashicorp/golang-lru" "github.com/hashicorp/golang-lru"
@ -50,7 +50,7 @@ const (
type HeaderChain struct { type HeaderChain struct {
config *params.ChainConfig config *params.ChainConfig
chainDb ethdb.Database chainDb database.Database
genesisHeader *types.Header genesisHeader *types.Header
currentHeader atomic.Value // Current head of the header chain (may be above the block chain!) currentHeader atomic.Value // Current head of the header chain (may be above the block chain!)
@ -70,7 +70,7 @@ type HeaderChain struct {
// getValidator should return the parent's validator // getValidator should return the parent's validator
// procInterrupt points to the parent's interrupt semaphore // procInterrupt points to the parent's interrupt semaphore
// wg points to the parent's shutdown wait group // wg points to the parent's shutdown wait group
func NewHeaderChain(chainDb ethdb.Database, config *params.ChainConfig, engine consensus.Engine, procInterrupt func() bool) (*HeaderChain, error) { func NewHeaderChain(chainDb database.Database, config *params.ChainConfig, engine consensus.Engine, procInterrupt func() bool) (*HeaderChain, error) {
headerCache, _ := lru.New(headerCacheLimit) headerCache, _ := lru.New(headerCacheLimit)
tdCache, _ := lru.New(tdCacheLimit) tdCache, _ := lru.New(tdCacheLimit)
numberCache, _ := lru.New(numberCacheLimit) numberCache, _ := lru.New(numberCacheLimit)
@ -455,7 +455,7 @@ func (hc *HeaderChain) SetCurrentHeader(head *types.Header) {
// DeleteCallback is a callback function that is called by SetHead before // DeleteCallback is a callback function that is called by SetHead before
// each header is deleted. // each header is deleted.
type DeleteCallback func(rawdb.DatabaseDeleter, common.Hash, uint64) type DeleteCallback func(database.Deleter, common.Hash, uint64)
// SetHead rewinds the local chain to a new head. Everything above the new head // SetHead rewinds the local chain to a new head. Everything above the new head
// will be deleted and the new one set. // will be deleted and the new one set.

View file

@ -19,8 +19,9 @@ package core
import ( import (
"container/list" "container/list"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
) )
@ -29,7 +30,7 @@ type TestManager struct {
// stateManager *StateManager // stateManager *StateManager
eventMux *event.TypeMux eventMux *event.TypeMux
db ethdb.Database db database.Database
txPool *TxPool txPool *TxPool
blockChain *BlockChain blockChain *BlockChain
Blocks []*types.Block Blocks []*types.Block
@ -71,14 +72,14 @@ func (tm *TestManager) EventMux() *event.TypeMux {
// return nil // return nil
// } // }
func (tm *TestManager) Db() ethdb.Database { func (tm *TestManager) Db() database.Database {
return tm.db return tm.db
} }
func NewTestManager() *TestManager { func NewTestManager() *TestManager {
testManager := &TestManager{} testManager := &TestManager{}
testManager.eventMux = new(event.TypeMux) testManager.eventMux = new(event.TypeMux)
testManager.db = ethdb.NewMemDatabase() testManager.db = rawdb.NewMemoryDatabase()
// testManager.txPool = NewTxPool(testManager) // testManager.txPool = NewTxPool(testManager)
// testManager.blockChain = NewBlockChain(testManager) // testManager.blockChain = NewBlockChain(testManager)
// testManager.stateManager = NewStateManager(testManager) // testManager.stateManager = NewStateManager(testManager)

View file

@ -23,13 +23,17 @@ 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/database"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
) )
// ReadCanonicalHash retrieves the hash assigned to a canonical block number. // ReadCanonicalHash retrieves the hash assigned to a canonical block number.
func ReadCanonicalHash(db DatabaseReader, number uint64) common.Hash { func ReadCanonicalHash(db database.AncientReader, number uint64) common.Hash {
data, _ := db.Get(headerHashKey(number)) data, _ := db.Ancient("hashes", number)
if len(data) == 0 {
data, _ = db.Get(headerHashKey(number))
}
if len(data) == 0 { if len(data) == 0 {
return common.Hash{} return common.Hash{}
} }
@ -37,21 +41,39 @@ func ReadCanonicalHash(db DatabaseReader, number uint64) common.Hash {
} }
// WriteCanonicalHash stores the hash assigned to a canonical block number. // WriteCanonicalHash stores the hash assigned to a canonical block number.
func WriteCanonicalHash(db DatabaseWriter, hash common.Hash, number uint64) { func WriteCanonicalHash(db database.Writer, hash common.Hash, number uint64) {
if err := db.Put(headerHashKey(number), hash.Bytes()); err != nil { if err := db.Put(headerHashKey(number), hash.Bytes()); err != nil {
log.Crit("Failed to store number to hash mapping", "err", err) log.Crit("Failed to store number to hash mapping", "err", err)
} }
} }
// DeleteCanonicalHash removes the number to hash canonical mapping. // DeleteCanonicalHash removes the number to hash canonical mapping.
func DeleteCanonicalHash(db DatabaseDeleter, number uint64) { func DeleteCanonicalHash(db database.Deleter, number uint64) {
if err := db.Delete(headerHashKey(number)); err != nil { if err := db.Delete(headerHashKey(number)); err != nil {
log.Crit("Failed to delete number to hash mapping", "err", err) log.Crit("Failed to delete number to hash mapping", "err", err)
} }
} }
// readAllHashes retrieves all the hashes assigned to blocks at a certain heights,
// both canonical and reorged forks included.
//
// This method is a helper for the chain reader. It should never be exposed to the
// outside world.
func readAllHashes(db database.Iteratorer, number uint64) []common.Hash {
prefix := headerKeyPrefix(number)
hashes := make([]common.Hash, 0, 1)
it := db.NewIteratorWithPrefix(prefix)
for it.Next() {
if key := it.Key(); len(key) == len(prefix)+32 {
hashes = append(hashes, common.BytesToHash(key[len(key)-32:]))
}
}
return hashes
}
// ReadHeaderNumber returns the header number assigned to a hash. // ReadHeaderNumber returns the header number assigned to a hash.
func ReadHeaderNumber(db DatabaseReader, hash common.Hash) *uint64 { func ReadHeaderNumber(db database.Reader, hash common.Hash) *uint64 {
data, _ := db.Get(headerNumberKey(hash)) data, _ := db.Get(headerNumberKey(hash))
if len(data) != 8 { if len(data) != 8 {
return nil return nil
@ -61,7 +83,7 @@ func ReadHeaderNumber(db DatabaseReader, hash common.Hash) *uint64 {
} }
// ReadHeadHeaderHash retrieves the hash of the current canonical head header. // ReadHeadHeaderHash retrieves the hash of the current canonical head header.
func ReadHeadHeaderHash(db DatabaseReader) common.Hash { func ReadHeadHeaderHash(db database.Reader) common.Hash {
data, _ := db.Get(headHeaderKey) data, _ := db.Get(headHeaderKey)
if len(data) == 0 { if len(data) == 0 {
return common.Hash{} return common.Hash{}
@ -70,14 +92,14 @@ func ReadHeadHeaderHash(db DatabaseReader) common.Hash {
} }
// WriteHeadHeaderHash stores the hash of the current canonical head header. // WriteHeadHeaderHash stores the hash of the current canonical head header.
func WriteHeadHeaderHash(db DatabaseWriter, hash common.Hash) { func WriteHeadHeaderHash(db database.Writer, hash common.Hash) {
if err := db.Put(headHeaderKey, hash.Bytes()); err != nil { if err := db.Put(headHeaderKey, hash.Bytes()); err != nil {
log.Crit("Failed to store last header's hash", "err", err) log.Crit("Failed to store last header's hash", "err", err)
} }
} }
// ReadHeadBlockHash retrieves the hash of the current canonical head block. // ReadHeadBlockHash retrieves the hash of the current canonical head block.
func ReadHeadBlockHash(db DatabaseReader) common.Hash { func ReadHeadBlockHash(db database.Reader) common.Hash {
data, _ := db.Get(headBlockKey) data, _ := db.Get(headBlockKey)
if len(data) == 0 { if len(data) == 0 {
return common.Hash{} return common.Hash{}
@ -86,14 +108,14 @@ func ReadHeadBlockHash(db DatabaseReader) common.Hash {
} }
// WriteHeadBlockHash stores the head block's hash. // WriteHeadBlockHash stores the head block's hash.
func WriteHeadBlockHash(db DatabaseWriter, hash common.Hash) { func WriteHeadBlockHash(db database.Writer, hash common.Hash) {
if err := db.Put(headBlockKey, hash.Bytes()); err != nil { if err := db.Put(headBlockKey, hash.Bytes()); err != nil {
log.Crit("Failed to store last block's hash", "err", err) log.Crit("Failed to store last block's hash", "err", err)
} }
} }
// ReadHeadFastBlockHash retrieves the hash of the current fast-sync head block. // ReadHeadFastBlockHash retrieves the hash of the current fast-sync head block.
func ReadHeadFastBlockHash(db DatabaseReader) common.Hash { func ReadHeadFastBlockHash(db database.Reader) common.Hash {
data, _ := db.Get(headFastBlockKey) data, _ := db.Get(headFastBlockKey)
if len(data) == 0 { if len(data) == 0 {
return common.Hash{} return common.Hash{}
@ -102,7 +124,7 @@ func ReadHeadFastBlockHash(db DatabaseReader) common.Hash {
} }
// WriteHeadFastBlockHash stores the hash of the current fast-sync head block. // WriteHeadFastBlockHash stores the hash of the current fast-sync head block.
func WriteHeadFastBlockHash(db DatabaseWriter, hash common.Hash) { func WriteHeadFastBlockHash(db database.Writer, hash common.Hash) {
if err := db.Put(headFastBlockKey, hash.Bytes()); err != nil { if err := db.Put(headFastBlockKey, hash.Bytes()); err != nil {
log.Crit("Failed to store last fast block's hash", "err", err) log.Crit("Failed to store last fast block's hash", "err", err)
} }
@ -110,7 +132,7 @@ func WriteHeadFastBlockHash(db DatabaseWriter, hash common.Hash) {
// ReadFastTrieProgress retrieves the number of tries nodes fast synced to allow // ReadFastTrieProgress retrieves the number of tries nodes fast synced to allow
// reporting correct numbers across restarts. // reporting correct numbers across restarts.
func ReadFastTrieProgress(db DatabaseReader) uint64 { func ReadFastTrieProgress(db database.Reader) uint64 {
data, _ := db.Get(fastTrieProgressKey) data, _ := db.Get(fastTrieProgressKey)
if len(data) == 0 { if len(data) == 0 {
return 0 return 0
@ -120,20 +142,26 @@ func ReadFastTrieProgress(db DatabaseReader) uint64 {
// WriteFastTrieProgress stores the fast sync trie process counter to support // WriteFastTrieProgress stores the fast sync trie process counter to support
// retrieving it across restarts. // retrieving it across restarts.
func WriteFastTrieProgress(db DatabaseWriter, count uint64) { func WriteFastTrieProgress(db database.Writer, count uint64) {
if err := db.Put(fastTrieProgressKey, new(big.Int).SetUint64(count).Bytes()); err != nil { if err := db.Put(fastTrieProgressKey, new(big.Int).SetUint64(count).Bytes()); err != nil {
log.Crit("Failed to store fast sync trie progress", "err", err) log.Crit("Failed to store fast sync trie progress", "err", err)
} }
} }
// ReadHeaderRLP retrieves a block header in its raw RLP database encoding. // ReadHeaderRLP retrieves a block header in its raw RLP database encoding.
func ReadHeaderRLP(db DatabaseReader, hash common.Hash, number uint64) rlp.RawValue { func ReadHeaderRLP(db database.AncientReader, hash common.Hash, number uint64) rlp.RawValue {
data, _ := db.Get(headerKey(number, hash)) data, _ := db.Ancient("headers", number)
if len(data) == 0 {
data, _ = db.Get(headerKey(number, hash))
}
return data return data
} }
// HasHeader verifies the existence of a block header corresponding to the hash. // HasHeader verifies the existence of a block header corresponding to the hash.
func HasHeader(db DatabaseReader, hash common.Hash, number uint64) bool { func HasHeader(db database.AncientReader, hash common.Hash, number uint64) bool {
if has, err := db.Ancient("hashes", number); err == nil && common.BytesToHash(has) == hash {
return true
}
if has, err := db.Has(headerKey(number, hash)); !has || err != nil { if has, err := db.Has(headerKey(number, hash)); !has || err != nil {
return false return false
} }
@ -141,7 +169,7 @@ func HasHeader(db DatabaseReader, hash common.Hash, number uint64) bool {
} }
// ReadHeader retrieves the block header corresponding to the hash. // ReadHeader retrieves the block header corresponding to the hash.
func ReadHeader(db DatabaseReader, hash common.Hash, number uint64) *types.Header { func ReadHeader(db database.AncientReader, hash common.Hash, number uint64) *types.Header {
data := ReadHeaderRLP(db, hash, number) data := ReadHeaderRLP(db, hash, number)
if len(data) == 0 { if len(data) == 0 {
return nil return nil
@ -156,7 +184,7 @@ func ReadHeader(db DatabaseReader, hash common.Hash, number uint64) *types.Heade
// WriteHeader stores a block header into the database and also stores the hash- // WriteHeader stores a block header into the database and also stores the hash-
// to-number mapping. // to-number mapping.
func WriteHeader(db DatabaseWriter, header *types.Header) { func WriteHeader(db database.Writer, header *types.Header) {
// Write the hash -> number mapping // Write the hash -> number mapping
var ( var (
hash = header.Hash() hash = header.Hash()
@ -179,30 +207,42 @@ func WriteHeader(db DatabaseWriter, header *types.Header) {
} }
// DeleteHeader removes all block header data associated with a hash. // DeleteHeader removes all block header data associated with a hash.
func DeleteHeader(db DatabaseDeleter, hash common.Hash, number uint64) { func DeleteHeader(db database.Deleter, hash common.Hash, number uint64) {
if err := db.Delete(headerKey(number, hash)); err != nil { deleteHeaderWithoutNumber(db, hash, number)
log.Crit("Failed to delete header", "err", err)
}
if err := db.Delete(headerNumberKey(hash)); err != nil { if err := db.Delete(headerNumberKey(hash)); err != nil {
log.Crit("Failed to delete hash to number mapping", "err", err) log.Crit("Failed to delete hash to number mapping", "err", err)
} }
} }
// deleteHeaderWithoutNumber removes only the block header but does not remove
// the hash to number mapping.
func deleteHeaderWithoutNumber(db database.Deleter, hash common.Hash, number uint64) {
if err := db.Delete(headerKey(number, hash)); err != nil {
log.Crit("Failed to delete header", "err", err)
}
}
// ReadBodyRLP retrieves the block body (transactions and uncles) in RLP encoding. // ReadBodyRLP retrieves the block body (transactions and uncles) in RLP encoding.
func ReadBodyRLP(db DatabaseReader, hash common.Hash, number uint64) rlp.RawValue { func ReadBodyRLP(db database.AncientReader, hash common.Hash, number uint64) rlp.RawValue {
data, _ := db.Get(blockBodyKey(number, hash)) data, _ := db.Ancient("bodies", number)
if len(data) == 0 {
data, _ = db.Get(blockBodyKey(number, hash))
}
return data return data
} }
// WriteBodyRLP stores an RLP encoded block body into the database. // WriteBodyRLP stores an RLP encoded block body into the database.
func WriteBodyRLP(db DatabaseWriter, hash common.Hash, number uint64, rlp rlp.RawValue) { func WriteBodyRLP(db database.Writer, hash common.Hash, number uint64, rlp rlp.RawValue) {
if err := db.Put(blockBodyKey(number, hash), rlp); err != nil { if err := db.Put(blockBodyKey(number, hash), rlp); err != nil {
log.Crit("Failed to store block body", "err", err) log.Crit("Failed to store block body", "err", err)
} }
} }
// HasBody verifies the existence of a block body corresponding to the hash. // HasBody verifies the existence of a block body corresponding to the hash.
func HasBody(db DatabaseReader, hash common.Hash, number uint64) bool { func HasBody(db database.AncientReader, hash common.Hash, number uint64) bool {
if has, err := db.Ancient("hashes", number); err == nil && common.BytesToHash(has) == hash {
return true
}
if has, err := db.Has(blockBodyKey(number, hash)); !has || err != nil { if has, err := db.Has(blockBodyKey(number, hash)); !has || err != nil {
return false return false
} }
@ -210,7 +250,7 @@ func HasBody(db DatabaseReader, hash common.Hash, number uint64) bool {
} }
// ReadBody retrieves the block body corresponding to the hash. // ReadBody retrieves the block body corresponding to the hash.
func ReadBody(db DatabaseReader, hash common.Hash, number uint64) *types.Body { func ReadBody(db database.AncientReader, hash common.Hash, number uint64) *types.Body {
data := ReadBodyRLP(db, hash, number) data := ReadBodyRLP(db, hash, number)
if len(data) == 0 { if len(data) == 0 {
return nil return nil
@ -224,7 +264,7 @@ func ReadBody(db DatabaseReader, hash common.Hash, number uint64) *types.Body {
} }
// WriteBody storea a block body into the database. // WriteBody storea a block body into the database.
func WriteBody(db DatabaseWriter, hash common.Hash, number uint64, body *types.Body) { func WriteBody(db database.Writer, hash common.Hash, number uint64, body *types.Body) {
data, err := rlp.EncodeToBytes(body) data, err := rlp.EncodeToBytes(body)
if err != nil { if err != nil {
log.Crit("Failed to RLP encode body", "err", err) log.Crit("Failed to RLP encode body", "err", err)
@ -233,15 +273,24 @@ func WriteBody(db DatabaseWriter, hash common.Hash, number uint64, body *types.B
} }
// DeleteBody removes all block body data associated with a hash. // DeleteBody removes all block body data associated with a hash.
func DeleteBody(db DatabaseDeleter, hash common.Hash, number uint64) { func DeleteBody(db database.Deleter, hash common.Hash, number uint64) {
if err := db.Delete(blockBodyKey(number, hash)); err != nil { if err := db.Delete(blockBodyKey(number, hash)); err != nil {
log.Crit("Failed to delete block body", "err", err) log.Crit("Failed to delete block body", "err", err)
} }
} }
// ReadTdRLP retrieves a block's total difficulty corresponding to the hash in RLP encoding.
func ReadTdRLP(db database.AncientReader, hash common.Hash, number uint64) rlp.RawValue {
data, _ := db.Ancient("diffs", number)
if len(data) == 0 {
data, _ = db.Get(headerTDKey(number, hash))
}
return data
}
// ReadTd retrieves a block's total difficulty corresponding to the hash. // ReadTd retrieves a block's total difficulty corresponding to the hash.
func ReadTd(db DatabaseReader, hash common.Hash, number uint64) *big.Int { func ReadTd(db database.AncientReader, hash common.Hash, number uint64) *big.Int {
data, _ := db.Get(headerTDKey(number, hash)) data := ReadTdRLP(db, hash, number)
if len(data) == 0 { if len(data) == 0 {
return nil return nil
} }
@ -254,7 +303,7 @@ func ReadTd(db DatabaseReader, hash common.Hash, number uint64) *big.Int {
} }
// WriteTd stores the total difficulty of a block into the database. // WriteTd stores the total difficulty of a block into the database.
func WriteTd(db DatabaseWriter, hash common.Hash, number uint64, td *big.Int) { func WriteTd(db database.Writer, hash common.Hash, number uint64, td *big.Int) {
data, err := rlp.EncodeToBytes(td) data, err := rlp.EncodeToBytes(td)
if err != nil { if err != nil {
log.Crit("Failed to RLP encode block total difficulty", "err", err) log.Crit("Failed to RLP encode block total difficulty", "err", err)
@ -265,7 +314,7 @@ func WriteTd(db DatabaseWriter, hash common.Hash, number uint64, td *big.Int) {
} }
// DeleteTd removes all block total difficulty data associated with a hash. // DeleteTd removes all block total difficulty data associated with a hash.
func DeleteTd(db DatabaseDeleter, hash common.Hash, number uint64) { func DeleteTd(db database.Deleter, hash common.Hash, number uint64) {
if err := db.Delete(headerTDKey(number, hash)); err != nil { if err := db.Delete(headerTDKey(number, hash)); err != nil {
log.Crit("Failed to delete block total difficulty", "err", err) log.Crit("Failed to delete block total difficulty", "err", err)
} }
@ -273,17 +322,29 @@ func DeleteTd(db DatabaseDeleter, hash common.Hash, number uint64) {
// HasReceipts verifies the existence of all the transaction receipts belonging // HasReceipts verifies the existence of all the transaction receipts belonging
// to a block. // to a block.
func HasReceipts(db DatabaseReader, hash common.Hash, number uint64) bool { func HasReceipts(db database.AncientReader, hash common.Hash, number uint64) bool {
if has, err := db.Ancient("hashes", number); err == nil && common.BytesToHash(has) == hash {
return true
}
if has, err := db.Has(blockReceiptsKey(number, hash)); !has || err != nil { if has, err := db.Has(blockReceiptsKey(number, hash)); !has || err != nil {
return false return false
} }
return true return true
} }
// ReadReceiptsRLP retrieves all the transaction receipts belonging to a block in RLP encoding.
func ReadReceiptsRLP(db database.AncientReader, hash common.Hash, number uint64) rlp.RawValue {
data, _ := db.Ancient("receipts", number)
if len(data) == 0 {
data, _ = db.Get(blockReceiptsKey(number, hash))
}
return data
}
// ReadReceipts retrieves all the transaction receipts belonging to a block. // ReadReceipts retrieves all the transaction receipts belonging to a block.
func ReadReceipts(db DatabaseReader, hash common.Hash, number uint64) types.Receipts { func ReadReceipts(db database.AncientReader, hash common.Hash, number uint64) types.Receipts {
// Retrieve the flattened receipt slice // Retrieve the flattened receipt slice
data, _ := db.Get(blockReceiptsKey(number, hash)) data := ReadReceiptsRLP(db, hash, number)
if len(data) == 0 { if len(data) == 0 {
return nil return nil
} }
@ -301,7 +362,7 @@ func ReadReceipts(db DatabaseReader, hash common.Hash, number uint64) types.Rece
} }
// WriteReceipts stores all the transaction receipts belonging to a block. // WriteReceipts stores all the transaction receipts belonging to a block.
func WriteReceipts(db DatabaseWriter, hash common.Hash, number uint64, receipts types.Receipts) { func WriteReceipts(db database.Writer, hash common.Hash, number uint64, receipts types.Receipts) {
// Convert the receipts into their storage form and serialize them // Convert the receipts into their storage form and serialize them
storageReceipts := make([]*types.ReceiptForStorage, len(receipts)) storageReceipts := make([]*types.ReceiptForStorage, len(receipts))
for i, receipt := range receipts { for i, receipt := range receipts {
@ -318,7 +379,7 @@ func WriteReceipts(db DatabaseWriter, hash common.Hash, number uint64, receipts
} }
// DeleteReceipts removes all receipt data associated with a block hash. // DeleteReceipts removes all receipt data associated with a block hash.
func DeleteReceipts(db DatabaseDeleter, hash common.Hash, number uint64) { func DeleteReceipts(db database.Deleter, hash common.Hash, number uint64) {
if err := db.Delete(blockReceiptsKey(number, hash)); err != nil { if err := db.Delete(blockReceiptsKey(number, hash)); err != nil {
log.Crit("Failed to delete block receipts", "err", err) log.Crit("Failed to delete block receipts", "err", err)
} }
@ -330,7 +391,7 @@ func DeleteReceipts(db DatabaseDeleter, hash common.Hash, number uint64) {
// //
// Note, due to concurrent download of header and block body the header and thus // Note, due to concurrent download of header and block body the header and thus
// canonical hash can be stored in the database but the body data not (yet). // canonical hash can be stored in the database but the body data not (yet).
func ReadBlock(db DatabaseReader, hash common.Hash, number uint64) *types.Block { func ReadBlock(db database.AncientReader, hash common.Hash, number uint64) *types.Block {
header := ReadHeader(db, hash, number) header := ReadHeader(db, hash, number)
if header == nil { if header == nil {
return nil return nil
@ -343,21 +404,30 @@ func ReadBlock(db DatabaseReader, hash common.Hash, number uint64) *types.Block
} }
// WriteBlock serializes a block into the database, header and body separately. // WriteBlock serializes a block into the database, header and body separately.
func WriteBlock(db DatabaseWriter, block *types.Block) { func WriteBlock(db database.Writer, block *types.Block) {
WriteBody(db, block.Hash(), block.NumberU64(), block.Body()) WriteBody(db, block.Hash(), block.NumberU64(), block.Body())
WriteHeader(db, block.Header()) WriteHeader(db, block.Header())
} }
// DeleteBlock removes all block data associated with a hash. // DeleteBlock removes all block data associated with a hash.
func DeleteBlock(db DatabaseDeleter, hash common.Hash, number uint64) { func DeleteBlock(db database.Deleter, hash common.Hash, number uint64) {
DeleteReceipts(db, hash, number) DeleteReceipts(db, hash, number)
DeleteHeader(db, hash, number) DeleteHeader(db, hash, number)
DeleteBody(db, hash, number) DeleteBody(db, hash, number)
DeleteTd(db, hash, number) DeleteTd(db, hash, number)
} }
// deleteBlockWithoutNumber removes all block data associated with a hash, except
// the hash to number mapping.
func deleteBlockWithoutNumber(db database.Deleter, hash common.Hash, number uint64) {
DeleteReceipts(db, hash, number)
deleteHeaderWithoutNumber(db, hash, number)
DeleteBody(db, hash, number)
DeleteTd(db, hash, number)
}
// FindCommonAncestor returns the last common ancestor of two block headers // FindCommonAncestor returns the last common ancestor of two block headers
func FindCommonAncestor(db DatabaseReader, a, b *types.Header) *types.Header { func FindCommonAncestor(db database.AncientReader, a, b *types.Header) *types.Header {
for bn := b.Number.Uint64(); a.Number.Uint64() > bn; { for bn := b.Number.Uint64(); a.Number.Uint64() > bn; {
a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1) a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1)
if a == nil { if a == nil {

View file

@ -23,14 +23,13 @@ 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/ethdb"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"golang.org/x/crypto/sha3" "golang.org/x/crypto/sha3"
) )
// Tests block header storage and retrieval operations. // Tests block header storage and retrieval operations.
func TestHeaderStorage(t *testing.T) { func TestHeaderStorage(t *testing.T) {
db := ethdb.NewMemDatabase() db := NewMemoryDatabase()
// Create a test header to move around the database and make sure it's really new // Create a test header to move around the database and make sure it's really new
header := &types.Header{Number: big.NewInt(42), Extra: []byte("test header")} header := &types.Header{Number: big.NewInt(42), Extra: []byte("test header")}
@ -63,7 +62,7 @@ func TestHeaderStorage(t *testing.T) {
// Tests block body storage and retrieval operations. // Tests block body storage and retrieval operations.
func TestBodyStorage(t *testing.T) { func TestBodyStorage(t *testing.T) {
db := ethdb.NewMemDatabase() db := NewMemoryDatabase()
// Create a test body to move around the database and make sure it's really new // Create a test body to move around the database and make sure it's really new
body := &types.Body{Uncles: []*types.Header{{Extra: []byte("test header")}}} body := &types.Body{Uncles: []*types.Header{{Extra: []byte("test header")}}}
@ -101,7 +100,7 @@ func TestBodyStorage(t *testing.T) {
// Tests block storage and retrieval operations. // Tests block storage and retrieval operations.
func TestBlockStorage(t *testing.T) { func TestBlockStorage(t *testing.T) {
db := ethdb.NewMemDatabase() db := NewMemoryDatabase()
// Create a test block to move around the database and make sure it's really new // Create a test block to move around the database and make sure it's really new
block := types.NewBlockWithHeader(&types.Header{ block := types.NewBlockWithHeader(&types.Header{
@ -151,7 +150,7 @@ func TestBlockStorage(t *testing.T) {
// Tests that partial block contents don't get reassembled into full blocks. // Tests that partial block contents don't get reassembled into full blocks.
func TestPartialBlockStorage(t *testing.T) { func TestPartialBlockStorage(t *testing.T) {
db := ethdb.NewMemDatabase() db := NewMemoryDatabase()
block := types.NewBlockWithHeader(&types.Header{ block := types.NewBlockWithHeader(&types.Header{
Extra: []byte("test block"), Extra: []byte("test block"),
UncleHash: types.EmptyUncleHash, UncleHash: types.EmptyUncleHash,
@ -185,7 +184,7 @@ func TestPartialBlockStorage(t *testing.T) {
// Tests block total difficulty storage and retrieval operations. // Tests block total difficulty storage and retrieval operations.
func TestTdStorage(t *testing.T) { func TestTdStorage(t *testing.T) {
db := ethdb.NewMemDatabase() db := NewMemoryDatabase()
// Create a test TD to move around the database and make sure it's really new // Create a test TD to move around the database and make sure it's really new
hash, td := common.Hash{}, big.NewInt(314) hash, td := common.Hash{}, big.NewInt(314)
@ -208,7 +207,7 @@ func TestTdStorage(t *testing.T) {
// Tests that canonical numbers can be mapped to hashes and retrieved. // Tests that canonical numbers can be mapped to hashes and retrieved.
func TestCanonicalMappingStorage(t *testing.T) { func TestCanonicalMappingStorage(t *testing.T) {
db := ethdb.NewMemDatabase() db := NewMemoryDatabase()
// Create a test canonical number and assinged hash to move around // Create a test canonical number and assinged hash to move around
hash, number := common.Hash{0: 0xff}, uint64(314) hash, number := common.Hash{0: 0xff}, uint64(314)
@ -231,7 +230,7 @@ func TestCanonicalMappingStorage(t *testing.T) {
// Tests that head headers and head blocks can be assigned, individually. // Tests that head headers and head blocks can be assigned, individually.
func TestHeadStorage(t *testing.T) { func TestHeadStorage(t *testing.T) {
db := ethdb.NewMemDatabase() db := NewMemoryDatabase()
blockHead := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block header")}) blockHead := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block header")})
blockFull := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block full")}) blockFull := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block full")})
@ -266,7 +265,7 @@ func TestHeadStorage(t *testing.T) {
// Tests that receipts associated with a single block can be stored and retrieved. // Tests that receipts associated with a single block can be stored and retrieved.
func TestBlockReceiptStorage(t *testing.T) { func TestBlockReceiptStorage(t *testing.T) {
db := ethdb.NewMemDatabase() db := NewMemoryDatabase()
receipt1 := &types.Receipt{ receipt1 := &types.Receipt{
Status: types.ReceiptStatusFailed, Status: types.ReceiptStatusFailed,

View file

@ -19,13 +19,14 @@ package rawdb
import ( 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/database"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
) )
// ReadTxLookupEntry retrieves the positional metadata associated with a transaction // ReadTxLookupEntry retrieves the positional metadata associated with a transaction
// hash to allow retrieving the transaction or receipt by hash. // hash to allow retrieving the transaction or receipt by hash.
func ReadTxLookupEntry(db DatabaseReader, hash common.Hash) (common.Hash, uint64, uint64) { func ReadTxLookupEntry(db database.Reader, hash common.Hash) (common.Hash, uint64, uint64) {
data, _ := db.Get(txLookupKey(hash)) data, _ := db.Get(txLookupKey(hash))
if len(data) == 0 { if len(data) == 0 {
return common.Hash{}, 0, 0 return common.Hash{}, 0, 0
@ -40,7 +41,7 @@ func ReadTxLookupEntry(db DatabaseReader, hash common.Hash) (common.Hash, uint64
// WriteTxLookupEntries stores a positional metadata for every transaction from // WriteTxLookupEntries stores a positional metadata for every transaction from
// a block, enabling hash based transaction and receipt lookups. // a block, enabling hash based transaction and receipt lookups.
func WriteTxLookupEntries(db DatabaseWriter, block *types.Block) { func WriteTxLookupEntries(db database.Writer, block *types.Block) {
for i, tx := range block.Transactions() { for i, tx := range block.Transactions() {
entry := TxLookupEntry{ entry := TxLookupEntry{
BlockHash: block.Hash(), BlockHash: block.Hash(),
@ -58,13 +59,13 @@ func WriteTxLookupEntries(db DatabaseWriter, block *types.Block) {
} }
// DeleteTxLookupEntry removes all transaction data associated with a hash. // DeleteTxLookupEntry removes all transaction data associated with a hash.
func DeleteTxLookupEntry(db DatabaseDeleter, hash common.Hash) { func DeleteTxLookupEntry(db database.Deleter, hash common.Hash) {
db.Delete(txLookupKey(hash)) db.Delete(txLookupKey(hash))
} }
// ReadTransaction retrieves a specific transaction from the database, along with // ReadTransaction retrieves a specific transaction from the database, along with
// its added positional metadata. // its added positional metadata.
func ReadTransaction(db DatabaseReader, hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) { func ReadTransaction(db database.AncientReader, hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) {
blockHash, blockNumber, txIndex := ReadTxLookupEntry(db, hash) blockHash, blockNumber, txIndex := ReadTxLookupEntry(db, hash)
if blockHash == (common.Hash{}) { if blockHash == (common.Hash{}) {
return nil, common.Hash{}, 0, 0 return nil, common.Hash{}, 0, 0
@ -79,7 +80,7 @@ func ReadTransaction(db DatabaseReader, hash common.Hash) (*types.Transaction, c
// ReadReceipt retrieves a specific transaction receipt from the database, along with // ReadReceipt retrieves a specific transaction receipt from the database, along with
// its added positional metadata. // its added positional metadata.
func ReadReceipt(db DatabaseReader, hash common.Hash) (*types.Receipt, common.Hash, uint64, uint64) { func ReadReceipt(db database.AncientReader, hash common.Hash) (*types.Receipt, common.Hash, uint64, uint64) {
blockHash, blockNumber, receiptIndex := ReadTxLookupEntry(db, hash) blockHash, blockNumber, receiptIndex := ReadTxLookupEntry(db, hash)
if blockHash == (common.Hash{}) { if blockHash == (common.Hash{}) {
return nil, common.Hash{}, 0, 0 return nil, common.Hash{}, 0, 0
@ -94,13 +95,13 @@ func ReadReceipt(db DatabaseReader, hash common.Hash) (*types.Receipt, common.Ha
// ReadBloomBits retrieves the compressed bloom bit vector belonging to the given // ReadBloomBits retrieves the compressed bloom bit vector belonging to the given
// section and bit index from the. // section and bit index from the.
func ReadBloomBits(db DatabaseReader, bit uint, section uint64, head common.Hash) ([]byte, error) { func ReadBloomBits(db database.Reader, bit uint, section uint64, head common.Hash) ([]byte, error) {
return db.Get(bloomBitsKey(bit, section, head)) return db.Get(bloomBitsKey(bit, section, head))
} }
// WriteBloomBits stores the compressed bloom bits vector belonging to the given // WriteBloomBits stores the compressed bloom bits vector belonging to the given
// section and bit index. // section and bit index.
func WriteBloomBits(db DatabaseWriter, bit uint, section uint64, head common.Hash, bits []byte) { func WriteBloomBits(db database.Writer, bit uint, section uint64, head common.Hash, bits []byte) {
if err := db.Put(bloomBitsKey(bit, section, head), bits); err != nil { if err := db.Put(bloomBitsKey(bit, section, head), bits); err != nil {
log.Crit("Failed to store bloom bits", "err", err) log.Crit("Failed to store bloom bits", "err", err)
} }

View file

@ -22,12 +22,11 @@ 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/ethdb"
) )
// Tests that positional lookup metadata can be stored and retrieved. // Tests that positional lookup metadata can be stored and retrieved.
func TestLookupStorage(t *testing.T) { func TestLookupStorage(t *testing.T) {
db := ethdb.NewMemDatabase() db := NewMemoryDatabase()
tx1 := types.NewTransaction(1, common.BytesToAddress([]byte{0x11}), big.NewInt(111), 1111, big.NewInt(11111), []byte{0x11, 0x11, 0x11}) tx1 := types.NewTransaction(1, common.BytesToAddress([]byte{0x11}), big.NewInt(111), 1111, big.NewInt(11111), []byte{0x11, 0x11, 0x11})
tx2 := types.NewTransaction(2, common.BytesToAddress([]byte{0x22}), big.NewInt(222), 2222, big.NewInt(22222), []byte{0x22, 0x22, 0x22}) tx2 := types.NewTransaction(2, common.BytesToAddress([]byte{0x22}), big.NewInt(222), 2222, big.NewInt(22222), []byte{0x22, 0x22, 0x22})

View file

@ -20,13 +20,14 @@ import (
"encoding/json" "encoding/json"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
) )
// ReadDatabaseVersion retrieves the version number of the database. // ReadDatabaseVersion retrieves the version number of the database.
func ReadDatabaseVersion(db DatabaseReader) *uint64 { func ReadDatabaseVersion(db database.Reader) *uint64 {
var version uint64 var version uint64
enc, _ := db.Get(databaseVerisionKey) enc, _ := db.Get(databaseVerisionKey)
@ -41,7 +42,7 @@ func ReadDatabaseVersion(db DatabaseReader) *uint64 {
} }
// WriteDatabaseVersion stores the version number of the database // WriteDatabaseVersion stores the version number of the database
func WriteDatabaseVersion(db DatabaseWriter, version uint64) { func WriteDatabaseVersion(db database.Writer, version uint64) {
enc, err := rlp.EncodeToBytes(version) enc, err := rlp.EncodeToBytes(version)
if err != nil { if err != nil {
log.Crit("Failed to encode database version", "err", err) log.Crit("Failed to encode database version", "err", err)
@ -52,7 +53,7 @@ func WriteDatabaseVersion(db DatabaseWriter, version uint64) {
} }
// ReadChainConfig retrieves the consensus settings based on the given genesis hash. // ReadChainConfig retrieves the consensus settings based on the given genesis hash.
func ReadChainConfig(db DatabaseReader, hash common.Hash) *params.ChainConfig { func ReadChainConfig(db database.Reader, hash common.Hash) *params.ChainConfig {
data, _ := db.Get(configKey(hash)) data, _ := db.Get(configKey(hash))
if len(data) == 0 { if len(data) == 0 {
return nil return nil
@ -66,7 +67,7 @@ func ReadChainConfig(db DatabaseReader, hash common.Hash) *params.ChainConfig {
} }
// WriteChainConfig writes the chain config settings to the database. // WriteChainConfig writes the chain config settings to the database.
func WriteChainConfig(db DatabaseWriter, hash common.Hash, cfg *params.ChainConfig) { func WriteChainConfig(db database.Writer, hash common.Hash, cfg *params.ChainConfig) {
if cfg == nil { if cfg == nil {
return return
} }
@ -80,13 +81,13 @@ func WriteChainConfig(db DatabaseWriter, hash common.Hash, cfg *params.ChainConf
} }
// ReadPreimage retrieves a single preimage of the provided hash. // ReadPreimage retrieves a single preimage of the provided hash.
func ReadPreimage(db DatabaseReader, hash common.Hash) []byte { func ReadPreimage(db database.Reader, hash common.Hash) []byte {
data, _ := db.Get(preimageKey(hash)) data, _ := db.Get(preimageKey(hash))
return data return data
} }
// WritePreimages writes the provided set of preimages to the database. // WritePreimages writes the provided set of preimages to the database.
func WritePreimages(db DatabaseWriter, preimages map[common.Hash][]byte) { func WritePreimages(db database.Writer, preimages map[common.Hash][]byte) {
for hash, preimage := range preimages { for hash, preimage := range preimages {
if err := db.Put(preimageKey(hash), preimage); err != nil { if err := db.Put(preimageKey(hash), preimage); err != nil {
log.Crit("Failed to store trie preimage", "err", err) log.Crit("Failed to store trie preimage", "err", err)

100
core/rawdb/database.go Normal file
View file

@ -0,0 +1,100 @@
// Copyright 2018 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package rawdb
import (
"github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/internal/keyvalue"
)
// freezerdb is a databse wrapper that enabled freezer data retrievals.
type freezerdb struct {
database.KeyValueStore
database.Ancienter
}
// nofreezedb is a database wrapper that disables freezer data retrievals.
type nofreezedb struct {
database.KeyValueStore
}
// Frozen returns nil as we don't have a backing chain freezer.
func (db *nofreezedb) Ancient(kind string, number uint64) ([]byte, error) {
return nil, errOutOfBounds
}
// NewDatabase creates a high level database on top of a given key-value data
// store without a freezer moving immutable chain segments into cold storage.
func NewDatabase(db database.KeyValueStore) database.Database {
return &nofreezedb{
KeyValueStore: db,
}
}
// NewDatabaseWithFreezer creates a high level database on top of a given key-
// value data store with a freezer moving immutable chain segments into cold
// storage.
func NewDatabaseWithFreezer(db database.KeyValueStore, freezer string, namespace string) (database.Database, error) {
frdb, err := newFreezer(freezer, namespace)
if err != nil {
return nil, err
}
go frdb.freeze(db)
return &freezerdb{
KeyValueStore: db,
Ancienter: frdb,
}, nil
}
// NewMemoryDatabase creates an ephemeral in-memory key-value database without a
// freezer moving immutable chain segments into cold storage.
func NewMemoryDatabase() database.Database {
return NewDatabase(keyvalue.NewMemoryDatabase())
}
// NewMemoryDatabaseWithCap creates an ephemeral in-memory key-value database with
// an initial starting capacity, but without a freezer moving immutable chain
// segments into cold storage.
func NewMemoryDatabaseWithCap(size int) database.Database {
return NewDatabase(keyvalue.NewMemoryDatabaseWithCap(size))
}
// NewLeveldbDatabase creates a persistent key-value database without a freezer
// moving immutable chain segments into cold storage.
func NewLeveldbDatabase(file string, cache int, handles int, namespace string) (database.Database, error) {
db, err := keyvalue.NewLeveldbDatabase(file, cache, handles, namespace)
if err != nil {
return nil, err
}
return NewDatabase(db), nil
}
// NewLeveldbDatabaseWithFreezer creates a persistent key-value database with a freezer
// moving immutable chain segments into cold storage.
func NewLeveldbDatabaseWithFreezer(file string, cache int, handles int, freezer string, namespace string) (database.Database, error) {
kvdb, err := keyvalue.NewLeveldbDatabase(file, cache, handles, namespace)
if err != nil {
return nil, err
}
frdb, err := NewDatabaseWithFreezer(kvdb, freezer, namespace)
if err != nil {
kvdb.Close()
return nil, err
}
return frdb, nil
}

276
core/rawdb/freezer.go Normal file
View file

@ -0,0 +1,276 @@
// Copyright 2018 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package rawdb
import (
"errors"
"fmt"
"math"
"sync/atomic"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
)
// errUnknownTable is returned if the user attempts to read from a table that is
// not tracked by the freezer.
var errUnknownTable = errors.New("unknown table")
const (
// freezerRecheckInterval is the frequency to check the key-value database for
// chain progression that might permit new blocks to be frozen into immutable
// storage.
freezerRecheckInterval = time.Minute
// freezerBlockGraduation is the number of confirmations a block must achieve
// before it becomes elligible for chain freezing. This must exceed any chain
// reorg depth, since the freezer also deletes all block siblings.
freezerBlockGraduation = 60000
// freezerBatchLimit is the maximum number of blocks to freeze in one batch
// before doing an fsync and deleting it from the key-value store.
freezerBatchLimit = 30000
)
// freezer is an memory mapped append-only database to store immutable chain data
// into flat files:
//
// - The append only nature ensures that disk writes are minimized.
// - The memory mapping ensures we can max out system memory for caching without
// reserving it for go-ethereum. This would also reduce the memory requirements
// of Geth, and thus also GC overhead.
type freezer struct {
tables map[string]*freezerTable // Data tables for storing everything
frozen uint64 // Number of blocks already frozen
}
// newFreezer creates a chain freezer that moves ancient chain data into
// append-only flat file containers.
func newFreezer(datadir string, namespace string) (*freezer, error) {
// Create the initial freezer object
var (
readMeter = metrics.NewRegisteredMeter(namespace+"ancient/read", nil)
writeMeter = metrics.NewRegisteredMeter(namespace+"ancient/write", nil)
)
// Open all the supported data tables
freezer := &freezer{
tables: make(map[string]*freezerTable),
}
for _, name := range []string{"hashes", "headers", "bodies", "receipts", "diffs"} {
table, err := newTable(datadir, name, readMeter, writeMeter)
if err != nil {
for _, table := range freezer.tables {
table.Close()
}
return nil, err
}
freezer.tables[name] = table
}
// Truncate all data tables to the same length
freezer.frozen = math.MaxUint64
for _, table := range freezer.tables {
if freezer.frozen > table.items {
freezer.frozen = table.items
}
}
for _, table := range freezer.tables {
if err := table.truncate(freezer.frozen); err != nil {
for _, table := range freezer.tables {
table.Close()
}
return nil, err
}
}
return freezer, nil
}
// Close terminates the chain freezer, unmapping all the data files.
func (f *freezer) Close() error {
var errs []error
for _, table := range f.tables {
if err := table.Close(); err != nil {
errs = append(errs, err)
}
}
if errs != nil {
return fmt.Errorf("%v", errs)
}
return nil
}
// sync flushes all data tables to disk.
func (f *freezer) sync() error {
var errs []error
for _, table := range f.tables {
if err := table.Sync(); err != nil {
errs = append(errs, err)
}
}
if errs != nil {
return fmt.Errorf("%v", errs)
}
return nil
}
// Ancient retrieves an ancient binary blob from the append-only immutable files.
func (f *freezer) Ancient(kind string, number uint64) ([]byte, error) {
if table := f.tables[kind]; table != nil {
return table.Retrieve(number)
}
return nil, errUnknownTable
}
// freeze is a background thread that periodically checks the blockchain for any
// import progress and moves ancient data from the fast database into the freezer.
//
// This functionality is deliberately broken off from block importing to avoid
// incurring additional data shuffling delays on block propagation.
func (f *freezer) freeze(db database.KeyValueStore) {
nfdb := &nofreezedb{KeyValueStore: db}
for {
// Retrieve the freezing threshold. In theory we're interested only in full
// blocks post-sync, but that would keep the live database enormous during
// dast sync. By picking the fast block, we still get to deep freeze all the
// final immutable data without having to wait for sync to finish.
hash := ReadHeadFastBlockHash(nfdb)
if hash == (common.Hash{}) {
log.Debug("Current fast block hash unavailable") // new chain, empty database
time.Sleep(freezerRecheckInterval)
continue
}
number := ReadHeaderNumber(nfdb, hash)
switch {
case number == nil:
log.Error("Current fast block number unavailable", "hash", hash)
time.Sleep(freezerRecheckInterval)
continue
case *number < freezerBlockGraduation:
log.Debug("Current fast block not old enough", "number", *number, "hash", hash, "delay", freezerBlockGraduation)
time.Sleep(freezerRecheckInterval)
continue
case *number-freezerBlockGraduation <= f.frozen:
log.Debug("Ancient blocks frozen already", "number", *number, "hash", hash, "frozen", f.frozen)
time.Sleep(freezerRecheckInterval)
continue
}
head := ReadHeader(nfdb, hash, *number)
if head == nil {
log.Error("Current fast block unavailable", "number", *number, "hash", hash)
time.Sleep(freezerRecheckInterval)
continue
}
// Seems we have data ready to be frozen, process in usable batches
limit := *number - freezerBlockGraduation
if limit-f.frozen > freezerBatchLimit {
limit = f.frozen + freezerBatchLimit
}
var (
start = time.Now()
first = f.frozen
ancients = make([]common.Hash, 0, limit)
)
for f.frozen < limit {
// Retrieves all the components of the canonical block
hash := ReadCanonicalHash(nfdb, f.frozen)
if hash == (common.Hash{}) {
log.Error("Canonical hash missing, can't freeze", "number", f.frozen)
break
}
header := ReadHeaderRLP(nfdb, hash, f.frozen)
if len(header) == 0 {
log.Error("Block header missing, can't freeze", "number", f.frozen, "hash", hash)
break
}
body := ReadBodyRLP(nfdb, hash, f.frozen)
if len(body) == 0 {
log.Error("Block body missing, can't freeze", "number", f.frozen, "hash", hash)
break
}
receipts := ReadReceiptsRLP(nfdb, hash, f.frozen)
if len(receipts) == 0 {
log.Error("Block receipts missing, can't freeze", "number", f.frozen, "hash", hash)
break
}
td := ReadTdRLP(nfdb, hash, f.frozen)
if len(td) == 0 {
log.Error("Total difficulty missing, can't freeze", "number", f.frozen, "hash", hash)
break
}
// Inject all the components into the relevant data tables
if err := f.tables["hashes"].Append(f.frozen, hash[:]); err != nil {
log.Error("Failed to deep freeze hash", "number", f.frozen, "hash", hash, "err", err)
break
}
if err := f.tables["headers"].Append(f.frozen, header); err != nil {
log.Error("Failed to deep freeze header", "number", f.frozen, "hash", hash, "err", err)
break
}
if err := f.tables["bodies"].Append(f.frozen, body); err != nil {
log.Error("Failed to deep freeze body", "number", f.frozen, "hash", hash, "err", err)
break
}
if err := f.tables["receipts"].Append(f.frozen, receipts); err != nil {
log.Error("Failed to deep freeze receipts", "number", f.frozen, "hash", hash, "err", err)
break
}
if err := f.tables["diffs"].Append(f.frozen, td); err != nil {
log.Error("Failed to deep freeze difficulty", "number", f.frozen, "hash", hash, "err", err)
break
}
log.Trace("Deep froze ancient block", "number", f.frozen, "hash", hash)
atomic.AddUint64(&f.frozen, 1) // Only modify atomically
ancients = append(ancients, hash)
}
// Batch of blocks have been frozen, flush them before wiping from leveldb
if err := f.sync(); err != nil {
log.Crit("Failed to flush frozen tables", "err", err)
}
// Wipe out all data from the active database
batch := db.NewBatch()
for number := first; number < f.frozen; number++ {
for _, hash := range readAllHashes(db, number) {
if hash == ancients[number-first] {
deleteBlockWithoutNumber(batch, hash, number)
} else {
DeleteBlock(batch, hash, number)
}
}
}
if err := batch.Write(); err != nil {
log.Crit("Failed to delete frozen items", "err", err)
}
// Log something friendly for the user
context := []interface{}{
"blocks", f.frozen - first, "elapsed", common.PrettyDuration(time.Since(start)), "number", f.frozen - 1,
}
if n := len(ancients); n > 0 {
context = append(context, []interface{}{"hash", ancients[n-1]}...)
}
log.Info("Deep froze chain segment", context...)
// Avoid database thrashing with tiny writes
if f.frozen-first < freezerBatchLimit {
time.Sleep(freezerRecheckInterval)
}
}
}

284
core/rawdb/freezer_table.go Normal file
View file

@ -0,0 +1,284 @@
// Copyright 2018 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package rawdb
import (
"encoding/binary"
"errors"
"fmt"
"os"
"path/filepath"
"sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/golang/snappy"
)
var (
// errClosed is returned if an operation attempts to read from or write to the
// freezer table after it has already been closed.
errClosed = errors.New("closed")
// errOutOfBounds is returned if the item requested is not contained within the
// freezer table.
errOutOfBounds = errors.New("out of bounds")
)
// freezerTable represents a single chained data table within the freezer (e.g. blocks).
// It consists of a data file (snappy encoded arbitrary data blobs) and an index
// file (uncompressed 64 bit indices into the data file).
type freezerTable struct {
content *os.File // File descriptor for the data content of the table
offsets *os.File // File descriptor for the index file of the table
items uint64 // Number of items stored in the table
bytes uint64 // Number of content bytes stored in the table
readMeter metrics.Meter // Meter for measuring the effective amount of data read
writeMeter metrics.Meter // Meter for measuring the effective amount of data written
logger log.Logger // Logger with database path and table name ambedded
lock sync.RWMutex // Mutex protecting the data file descriptors
}
// newTable opens a freezer table, creating the data and index files if they are
// non existent. Both files are truncated to the shortest common length to ensure
// they don't go out of sync.
func newTable(path string, name string, readMeter metrics.Meter, writeMeter metrics.Meter) (*freezerTable, error) {
// Ensure the containing directory exists and open the two data files
if err := os.MkdirAll(path, 0755); err != nil {
return nil, err
}
content, err := os.OpenFile(filepath.Join(path, name+".dat"), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
return nil, err
}
offsets, err := os.OpenFile(filepath.Join(path, name+".idx"), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
content.Close()
return nil, err
}
// Create the table and repair any past inconsistency
tab := &freezerTable{
content: content,
offsets: offsets,
readMeter: readMeter,
writeMeter: writeMeter,
logger: log.New("database", path, "table", name),
}
if err := tab.repair(); err != nil {
offsets.Close()
content.Close()
return nil, err
}
return tab, nil
}
// repair cross checks the content and the offsets file and truncates them to
// be in sync with each other after a potential crash / data loss.
func (t *freezerTable) repair() error {
// Create a temporary offset buffer to init files with and read offsts into
offset := make([]byte, 8)
// If we've just created the files, initialize the offsets with the 0 index
stat, err := t.offsets.Stat()
if err != nil {
return err
}
if stat.Size() == 0 {
if _, err := t.offsets.Write(offset); err != nil {
return err
}
}
// Ensure the offsets are a multiple of 8 bytes
if overflow := stat.Size() % 8; overflow != 0 {
t.offsets.Truncate(stat.Size() - overflow) // New file can't trigger this path
}
// Retrieve the file sizes and prepare for truncation
if stat, err = t.offsets.Stat(); err != nil {
return err
}
offsetsSize := stat.Size()
if stat, err = t.content.Stat(); err != nil {
return err
}
contentSize := stat.Size()
// Keep truncating both files until they come in sync
t.offsets.ReadAt(offset, offsetsSize-8)
contentExp := int64(binary.LittleEndian.Uint64(offset))
for contentExp != contentSize {
// Truncate the content file to the last offset pointer
if contentExp < contentSize {
t.logger.Warn("Truncating dangling content", "indexed", common.StorageSize(contentExp), "stored", common.StorageSize(contentSize))
if err := t.content.Truncate(contentExp); err != nil {
return err
}
contentSize = contentExp
}
// Truncate the offsets to point within the content file
if contentExp > contentSize {
t.logger.Warn("Truncating dangling offsets", "indexed", common.StorageSize(contentExp), "stored", common.StorageSize(contentSize))
if err := t.offsets.Truncate(offsetsSize - 8); err != nil {
return err
}
offsetsSize -= 8
t.offsets.ReadAt(offset, offsetsSize-8)
contentExp = int64(binary.LittleEndian.Uint64(offset))
}
}
// Ensure all reparation changes have been written to disk
if err := t.offsets.Sync(); err != nil {
return err
}
if err := t.content.Sync(); err != nil {
return err
}
// Update the item and byte counters and return
t.items = uint64(offsetsSize/8 - 1) // last index points to the end of the data file
t.bytes = uint64(contentSize)
t.logger.Debug("Chain freezer table opened", "items", t.items, "size", common.StorageSize(t.bytes))
return nil
}
// truncate discards any recent data above the provided threashold number.
func (t *freezerTable) truncate(items uint64) error {
// If out item count is corrent, don't do anything
if t.items <= items {
return nil
}
// Something's out of sync, truncate the table's offset index
t.logger.Warn("Truncating freezer table", "items", t.items, "limit", items)
if err := t.offsets.Truncate(int64(items+1) * 8); err != nil {
return err
}
// Calculate the new expected size of the data file and truncate it
offset := make([]byte, 8)
t.offsets.ReadAt(offset, int64(items)*8)
expected := binary.LittleEndian.Uint64(offset)
if err := t.content.Truncate(int64(expected)); err != nil {
return err
}
// All data files truncated, set internal counters and return
t.items, t.bytes = items, expected
return nil
}
// Close unmaps all active memory mapped regions.
func (t *freezerTable) Close() error {
t.lock.Lock()
defer t.lock.Unlock()
var errs []error
if err := t.offsets.Close(); err != nil {
errs = append(errs, err)
}
t.offsets = nil
if err := t.content.Close(); err != nil {
errs = append(errs, err)
}
t.content = nil
if errs != nil {
return fmt.Errorf("%v", errs)
}
return nil
}
// Append injects a binary blob at the end of the freezer table. The item index
// is a precautionary parameter to ensure data correctness, but the table will
// reject already existing data.
//
// Note, this method will *not* flush any data to disk so be sure to explicitly
// fsync before irreversibly deleting data from the database.
func (t *freezerTable) Append(item uint64, blob []byte) error {
// Ensure the table is still accessible
if t.offsets == nil || t.content == nil {
return errClosed
}
// Ensure only the next item can be written, nothing else
if t.items != item {
panic(fmt.Sprintf("appending unexpected item: want %d, have %d", t.items, item))
}
// Encode the blob and write it into the data file
blob = snappy.Encode(nil, blob)
if _, err := t.content.Write(blob); err != nil {
return err
}
t.bytes += uint64(len(blob))
offset := make([]byte, 8)
binary.LittleEndian.PutUint64(offset, t.bytes)
if _, err := t.offsets.Write(offset); err != nil {
return err
}
t.items++
t.writeMeter.Mark(int64(len(blob) + 8)) // 8 = 1 x 8 byte offset
return nil
}
// Retrieve looks up the data offset of an item with the given index and retrieves
// the raw binary blob from the data file.
func (t *freezerTable) Retrieve(item uint64) ([]byte, error) {
t.lock.RLock()
defer t.lock.RUnlock()
// Ensure the table and the item is accessible
if t.offsets == nil || t.content == nil {
return nil, errClosed
}
if t.items <= item {
return nil, errOutOfBounds
}
// Item reachable, retrieve the data content boundaries
offset := make([]byte, 8)
if _, err := t.offsets.ReadAt(offset, int64(item*8)); err != nil {
return nil, err
}
start := binary.LittleEndian.Uint64(offset)
if _, err := t.offsets.ReadAt(offset, int64((item+1)*8)); err != nil {
return nil, err
}
end := binary.LittleEndian.Uint64(offset)
// Retrieve the data itself, decompress and return
blob := make([]byte, end-start)
if _, err := t.content.ReadAt(blob, int64(start)); err != nil {
return nil, err
}
t.readMeter.Mark(int64(len(blob) + 16)) // 16 = 2 x 8 byte offset
return snappy.Decode(nil, blob)
}
// Sync pushes any pending data from memory out to disk. This is an expensive
// operation, so use it with care.
func (t *freezerTable) Sync() error {
if err := t.offsets.Sync(); err != nil {
return err
}
return t.content.Sync()
}

View file

@ -1,33 +0,0 @@
// Copyright 2018 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package rawdb
// DatabaseReader wraps the Has and Get method of a backing data store.
type DatabaseReader interface {
Has(key []byte) (bool, error)
Get(key []byte) ([]byte, error)
}
// DatabaseWriter wraps the Put method of a backing data store.
type DatabaseWriter interface {
Put(key []byte, value []byte) error
}
// DatabaseDeleter wraps the Delete method of a backing data store.
type DatabaseDeleter interface {
Delete(key []byte) error
}

View file

@ -78,6 +78,11 @@ func encodeBlockNumber(number uint64) []byte {
return enc return enc
} }
// headerKeyPrefix = headerPrefix + num (uint64 big endian)
func headerKeyPrefix(number uint64) []byte {
return append(headerPrefix, encodeBlockNumber(number)...)
}
// headerKey = headerPrefix + num (uint64 big endian) + hash // headerKey = headerPrefix + num (uint64 big endian) + hash
func headerKey(number uint64, hash common.Hash) []byte { func headerKey(number uint64, hash common.Hash) []byte {
return append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...) return append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...)

124
core/rawdb/table.go Normal file
View file

@ -0,0 +1,124 @@
// Copyright 2018 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package rawdb
import (
"github.com/ethereum/go-ethereum/database"
)
// table is a wrapper around a database that prefixes each key access with a pre-
// configured string.
type table struct {
db database.Database
prefix string
}
// NewTable returns a database object that prefixes all keys with a given string.
func NewTable(db database.Database, prefix string) database.Database {
return &table{
db: db,
prefix: prefix,
}
}
// Close is a noop to implement the Database interface.
func (t *table) Close() error {
return nil
}
// Has retrieves if a prefixed version of a key is present in the database.
func (t *table) Has(key []byte) (bool, error) {
return t.db.Has(append([]byte(t.prefix), key...))
}
// Get retrieves the given prefixed key if it's present in the database.
func (t *table) Get(key []byte) ([]byte, error) {
return t.db.Get(append([]byte(t.prefix), key...))
}
// Ancient is a noop passthrough that just forwards the request to the underlying
// database.
func (t *table) Ancient(kind string, number uint64) ([]byte, error) {
return t.db.Ancient(kind, number)
}
// Put inserts the given value into the database at a prefixed version of the
// provided key.
func (t *table) Put(key []byte, value []byte) error {
return t.db.Put(append([]byte(t.prefix), key...), value)
}
// Delete removes the given prefixed key from the database.
func (t *table) Delete(key []byte) error {
return t.db.Delete(append([]byte(t.prefix), key...))
}
// NewIterator creates a binary-alphabetical iterator over the entire keyspace
// contained within the database.
func (t *table) NewIterator() database.Iterator {
return t.NewIteratorWithPrefix(nil)
}
// NewIteratorWithPrefix creates a binary-alphabetical iterator over a subset
// of database content with a particular key prefix.
func (t *table) NewIteratorWithPrefix(prefix []byte) database.Iterator {
return t.db.NewIteratorWithPrefix(append([]byte(t.prefix), prefix...))
}
// Stat returns a particular internal stat of the database.
func (t *table) Stat(property string) (string, error) {
return t.db.Stat(property)
}
// NewBatch creates a write-only database that buffers changes to its host db
// until a final write is called, each operation prefixing all keys with the
// pre-configured string.
func (t *table) NewBatch() database.Batch {
return &tableBatch{t.db.NewBatch(), t.prefix}
}
// tableBatch is a wrapper around a database batch that prefixes each key access
// with a pre-configured string.
type tableBatch struct {
batch database.Batch
prefix string
}
// Put inserts the given value into the batch for later committing.
func (b *tableBatch) Put(key, value []byte) error {
return b.batch.Put(append([]byte(b.prefix), key...), value)
}
// Delete inserts the a key removal into the batch for later committing.
func (b *tableBatch) Delete(key []byte) error {
return b.batch.Delete(append([]byte(b.prefix), key...))
}
// ValueSize retrieves the amount of data queued up for writing.
func (b *tableBatch) ValueSize() int {
return b.batch.ValueSize()
}
// Write flushes any accumulated data to disk.
func (b *tableBatch) Write() error {
return b.batch.Write()
}
// Reset resets the batch for reuse.
func (b *tableBatch) Reset() {
b.batch.Reset()
}

View file

@ -21,7 +21,7 @@ import (
"sync" "sync"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
lru "github.com/hashicorp/golang-lru" lru "github.com/hashicorp/golang-lru"
) )
@ -68,20 +68,20 @@ type Trie interface {
Hash() common.Hash Hash() common.Hash
NodeIterator(startKey []byte) trie.NodeIterator NodeIterator(startKey []byte) trie.NodeIterator
GetKey([]byte) []byte // TODO(fjl): remove this when SecureTrie is removed GetKey([]byte) []byte // TODO(fjl): remove this when SecureTrie is removed
Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error Prove(key []byte, fromLevel uint, proofDb database.Writer) error
} }
// NewDatabase creates a backing store for state. The returned database is safe for // NewDatabase creates a backing store for state. The returned database is safe for
// concurrent use and retains a few recent expanded trie nodes in memory. To keep // concurrent use and retains a few recent expanded trie nodes in memory. To keep
// more historical state in memory, use the NewDatabaseWithCache constructor. // more historical state in memory, use the NewDatabaseWithCache constructor.
func NewDatabase(db ethdb.Database) Database { func NewDatabase(db database.Database) Database {
return NewDatabaseWithCache(db, 0) return NewDatabaseWithCache(db, 0)
} }
// NewDatabase creates a backing store for state. The returned database is safe for // NewDatabase creates a backing store for state. The returned database is safe for
// concurrent use and retains both a few recent expanded trie nodes in memory, as // concurrent use and retains both a few recent expanded trie nodes in memory, as
// well as a lot of collapsed RLP trie nodes in a large memory cache. // well as a lot of collapsed RLP trie nodes in a large memory cache.
func NewDatabaseWithCache(db ethdb.Database, cache int) Database { func NewDatabaseWithCache(db database.Database, cache int) Database {
csc, _ := lru.New(codeSizeCacheSize) csc, _ := lru.New(codeSizeCacheSize)
return &cachingDB{ return &cachingDB{
db: trie.NewDatabaseWithCache(db, cache), db: trie.NewDatabaseWithCache(db, cache),
@ -179,6 +179,6 @@ func (m cachedTrie) Commit(onleaf trie.LeafCallback) (common.Hash, error) {
return root, err return root, err
} }
func (m cachedTrie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error { func (m cachedTrie) Prove(key []byte, fromLevel uint, proofDb database.Writer) error {
return m.SecureTrie.Prove(key, fromLevel, proofDb) return m.SecureTrie.Prove(key, fromLevel, proofDb)
} }

View file

@ -21,7 +21,7 @@ import (
"testing" "testing"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
) )
// Tests that the node iterator indeed walks over the entire database contents. // Tests that the node iterator indeed walks over the entire database contents.
@ -51,7 +51,9 @@ func TestNodeIteratorCoverage(t *testing.T) {
t.Errorf("state entry not reported %x", hash) t.Errorf("state entry not reported %x", hash)
} }
} }
for _, key := range db.TrieDB().DiskDB().(*ethdb.MemDatabase).Keys() { it := db.TrieDB().DiskDB().(database.Database).NewIterator()
for it.Next() {
key := it.Key()
if bytes.HasPrefix(key, []byte("secure-key-")) { if bytes.HasPrefix(key, []byte("secure-key-")) {
continue continue
} }
@ -59,4 +61,5 @@ func TestNodeIteratorCoverage(t *testing.T) {
t.Errorf("state entry not reported %x", key) t.Errorf("state entry not reported %x", key)
} }
} }
it.Release()
} }

View file

@ -20,13 +20,13 @@ import (
"testing" "testing"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/core/rawdb"
) )
var addr = common.BytesToAddress([]byte("test")) var addr = common.BytesToAddress([]byte("test"))
func create() (*ManagedState, *account) { func create() (*ManagedState, *account) {
statedb, _ := New(common.Hash{}, NewDatabase(ethdb.NewMemDatabase())) statedb, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()))
ms := ManageState(statedb) ms := ManageState(statedb)
ms.StateDB.SetNonce(addr, 100) ms.StateDB.SetNonce(addr, 100)
ms.accounts[addr] = newAccount(ms.StateDB.getStateObject(addr)) ms.accounts[addr] = newAccount(ms.StateDB.getStateObject(addr))

View file

@ -22,13 +22,14 @@ import (
"testing" "testing"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
checker "gopkg.in/check.v1" checker "gopkg.in/check.v1"
) )
type StateSuite struct { type StateSuite struct {
db *ethdb.MemDatabase db database.Database
state *StateDB state *StateDB
} }
@ -87,7 +88,7 @@ func (s *StateSuite) TestDump(c *checker.C) {
} }
func (s *StateSuite) SetUpTest(c *checker.C) { func (s *StateSuite) SetUpTest(c *checker.C) {
s.db = ethdb.NewMemDatabase() s.db = rawdb.NewMemoryDatabase()
s.state, _ = New(common.Hash{}, NewDatabase(s.db)) s.state, _ = New(common.Hash{}, NewDatabase(s.db))
} }
@ -141,7 +142,7 @@ func (s *StateSuite) TestSnapshotEmpty(c *checker.C) {
// use testing instead of checker because checker does not support // use testing instead of checker because checker does not support
// printing/logging in tests (-check.vv does not work) // printing/logging in tests (-check.vv does not work)
func TestSnapshot2(t *testing.T) { func TestSnapshot2(t *testing.T) {
state, _ := New(common.Hash{}, NewDatabase(ethdb.NewMemDatabase())) state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()))
stateobjaddr0 := toAddr([]byte("so0")) stateobjaddr0 := toAddr([]byte("so0"))
stateobjaddr1 := toAddr([]byte("so1")) stateobjaddr1 := toAddr([]byte("so1"))

View file

@ -31,15 +31,15 @@ import (
check "gopkg.in/check.v1" check "gopkg.in/check.v1"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
) )
// Tests that updating a state trie does not leak any database writes prior to // Tests that updating a state trie does not leak any database writes prior to
// actually committing the state. // actually committing the state.
func TestUpdateLeaks(t *testing.T) { func TestUpdateLeaks(t *testing.T) {
// Create an empty state database // Create an empty state database
db := ethdb.NewMemDatabase() db := rawdb.NewMemoryDatabase()
state, _ := New(common.Hash{}, NewDatabase(db)) state, _ := New(common.Hash{}, NewDatabase(db))
// Update it with some accounts // Update it with some accounts
@ -56,18 +56,19 @@ func TestUpdateLeaks(t *testing.T) {
state.IntermediateRoot(false) state.IntermediateRoot(false)
} }
// Ensure that no data was leaked into the database // Ensure that no data was leaked into the database
for _, key := range db.Keys() { it := db.NewIterator()
value, _ := db.Get(key) for it.Next() {
t.Errorf("State leaked into database: %x -> %x", key, value) t.Errorf("State leaked into database: %x -> %x", it.Key(), it.Value())
} }
it.Release()
} }
// Tests that no intermediate state of an object is stored into the database, // Tests that no intermediate state of an object is stored into the database,
// only the one right before the commit. // only the one right before the commit.
func TestIntermediateLeaks(t *testing.T) { func TestIntermediateLeaks(t *testing.T) {
// Create two state databases, one transitioning to the final state, the other final from the beginning // Create two state databases, one transitioning to the final state, the other final from the beginning
transDb := ethdb.NewMemDatabase() transDb := rawdb.NewMemoryDatabase()
finalDb := ethdb.NewMemDatabase() finalDb := rawdb.NewMemoryDatabase()
transState, _ := New(common.Hash{}, NewDatabase(transDb)) transState, _ := New(common.Hash{}, NewDatabase(transDb))
finalState, _ := New(common.Hash{}, NewDatabase(finalDb)) finalState, _ := New(common.Hash{}, NewDatabase(finalDb))
@ -103,16 +104,20 @@ func TestIntermediateLeaks(t *testing.T) {
if _, err := finalState.Commit(false); err != nil { if _, err := finalState.Commit(false); err != nil {
t.Fatalf("failed to commit final state: %v", err) t.Fatalf("failed to commit final state: %v", err)
} }
for _, key := range finalDb.Keys() { it := finalDb.NewIterator()
for it.Next() {
key := it.Key()
if _, err := transDb.Get(key); err != nil { if _, err := transDb.Get(key); err != nil {
val, _ := finalDb.Get(key) t.Errorf("entry missing from the transition database: %x -> %x", key, it.Value())
t.Errorf("entry missing from the transition database: %x -> %x", key, val)
} }
} }
for _, key := range transDb.Keys() { it.Release()
it = transDb.NewIterator()
for it.Next() {
key := it.Key()
if _, err := finalDb.Get(key); err != nil { if _, err := finalDb.Get(key); err != nil {
val, _ := transDb.Get(key) t.Errorf("extra entry in the transition database: %x -> %x", key, it.Value())
t.Errorf("extra entry in the transition database: %x -> %x", key, val)
} }
} }
} }
@ -122,7 +127,7 @@ func TestIntermediateLeaks(t *testing.T) {
// https://github.com/ethereum/go-ethereum/pull/15549. // https://github.com/ethereum/go-ethereum/pull/15549.
func TestCopy(t *testing.T) { func TestCopy(t *testing.T) {
// Create a random state test to copy and modify "independently" // Create a random state test to copy and modify "independently"
orig, _ := New(common.Hash{}, NewDatabase(ethdb.NewMemDatabase())) orig, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()))
for i := byte(0); i < 255; i++ { for i := byte(0); i < 255; i++ {
obj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i})) obj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
@ -342,7 +347,7 @@ func (test *snapshotTest) String() string {
func (test *snapshotTest) run() bool { func (test *snapshotTest) run() bool {
// Run all actions and create snapshots. // Run all actions and create snapshots.
var ( var (
state, _ = New(common.Hash{}, NewDatabase(ethdb.NewMemDatabase())) state, _ = New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()))
snapshotRevs = make([]int, len(test.snapshots)) snapshotRevs = make([]int, len(test.snapshots))
sindex = 0 sindex = 0
) )
@ -433,7 +438,7 @@ func (s *StateSuite) TestTouchDelete(c *check.C) {
// TestCopyOfCopy tests that modified objects are carried over to the copy, and the copy of the copy. // TestCopyOfCopy tests that modified objects are carried over to the copy, and the copy of the copy.
// See https://github.com/ethereum/go-ethereum/pull/15225#issuecomment-380191512 // See https://github.com/ethereum/go-ethereum/pull/15225#issuecomment-380191512
func TestCopyOfCopy(t *testing.T) { func TestCopyOfCopy(t *testing.T) {
sdb, _ := New(common.Hash{}, NewDatabase(ethdb.NewMemDatabase())) sdb, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()))
addr := common.HexToAddress("aaaa") addr := common.HexToAddress("aaaa")
sdb.SetBalance(addr, big.NewInt(42)) sdb.SetBalance(addr, big.NewInt(42))

View file

@ -20,12 +20,13 @@ import (
"bytes" "bytes"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
) )
// NewStateSync create a new state trie download scheduler. // NewStateSync create a new state trie download scheduler.
func NewStateSync(root common.Hash, database trie.DatabaseReader) *trie.Sync { func NewStateSync(root common.Hash, database database.Reader) *trie.Sync {
var syncer *trie.Sync var syncer *trie.Sync
callback := func(leaf []byte, parent common.Hash) error { callback := func(leaf []byte, parent common.Hash) error {
var obj Account var obj Account

View file

@ -22,8 +22,9 @@ import (
"testing" "testing"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
) )
@ -38,7 +39,7 @@ type testAccount struct {
// makeTestState create a sample test state to test node-wise reconstruction. // makeTestState create a sample test state to test node-wise reconstruction.
func makeTestState() (Database, common.Hash, []*testAccount) { func makeTestState() (Database, common.Hash, []*testAccount) {
// Create an empty state // Create an empty state
db := NewDatabase(ethdb.NewMemDatabase()) db := NewDatabase(rawdb.NewMemoryDatabase())
state, _ := New(common.Hash{}, db) state, _ := New(common.Hash{}, db)
// Fill it with some arbitrary data // Fill it with some arbitrary data
@ -68,7 +69,7 @@ func makeTestState() (Database, common.Hash, []*testAccount) {
// checkStateAccounts cross references a reconstructed state with an expected // checkStateAccounts cross references a reconstructed state with an expected
// account array. // account array.
func checkStateAccounts(t *testing.T, db ethdb.Database, root common.Hash, accounts []*testAccount) { func checkStateAccounts(t *testing.T, db database.Database, root common.Hash, accounts []*testAccount) {
// Check root availability and state contents // Check root availability and state contents
state, err := New(root, NewDatabase(db)) state, err := New(root, NewDatabase(db))
if err != nil { if err != nil {
@ -91,7 +92,7 @@ func checkStateAccounts(t *testing.T, db ethdb.Database, root common.Hash, accou
} }
// checkTrieConsistency checks that all nodes in a (sub-)trie are indeed present. // checkTrieConsistency checks that all nodes in a (sub-)trie are indeed present.
func checkTrieConsistency(db ethdb.Database, root common.Hash) error { func checkTrieConsistency(db database.Database, root common.Hash) error {
if v, _ := db.Get(root[:]); v == nil { if v, _ := db.Get(root[:]); v == nil {
return nil // Consider a non existent state consistent. return nil // Consider a non existent state consistent.
} }
@ -106,7 +107,7 @@ func checkTrieConsistency(db ethdb.Database, root common.Hash) error {
} }
// checkStateConsistency checks that all data of a state root is present. // checkStateConsistency checks that all data of a state root is present.
func checkStateConsistency(db ethdb.Database, root common.Hash) error { func checkStateConsistency(db database.Database, root common.Hash) error {
// Create and iterate a state trie rooted in a sub-node // Create and iterate a state trie rooted in a sub-node
if _, err := db.Get(root.Bytes()); err != nil { if _, err := db.Get(root.Bytes()); err != nil {
return nil // Consider a non existent state consistent. return nil // Consider a non existent state consistent.
@ -124,7 +125,7 @@ func checkStateConsistency(db ethdb.Database, root common.Hash) error {
// Tests that an empty state is not scheduled for syncing. // Tests that an empty state is not scheduled for syncing.
func TestEmptyStateSync(t *testing.T) { func TestEmptyStateSync(t *testing.T) {
empty := common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") empty := common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
if req := NewStateSync(empty, ethdb.NewMemDatabase()).Missing(1); len(req) != 0 { if req := NewStateSync(empty, rawdb.NewMemoryDatabase()).Missing(1); len(req) != 0 {
t.Errorf("content requested for empty state: %v", req) t.Errorf("content requested for empty state: %v", req)
} }
} }
@ -139,7 +140,7 @@ func testIterativeStateSync(t *testing.T, batch int) {
srcDb, srcRoot, srcAccounts := makeTestState() srcDb, srcRoot, srcAccounts := makeTestState()
// Create a destination state and sync with the scheduler // Create a destination state and sync with the scheduler
dstDb := ethdb.NewMemDatabase() dstDb := rawdb.NewMemoryDatabase()
sched := NewStateSync(srcRoot, dstDb) sched := NewStateSync(srcRoot, dstDb)
queue := append([]common.Hash{}, sched.Missing(batch)...) queue := append([]common.Hash{}, sched.Missing(batch)...)
@ -171,7 +172,7 @@ func TestIterativeDelayedStateSync(t *testing.T) {
srcDb, srcRoot, srcAccounts := makeTestState() srcDb, srcRoot, srcAccounts := makeTestState()
// Create a destination state and sync with the scheduler // Create a destination state and sync with the scheduler
dstDb := ethdb.NewMemDatabase() dstDb := rawdb.NewMemoryDatabase()
sched := NewStateSync(srcRoot, dstDb) sched := NewStateSync(srcRoot, dstDb)
queue := append([]common.Hash{}, sched.Missing(0)...) queue := append([]common.Hash{}, sched.Missing(0)...)
@ -208,7 +209,7 @@ func testIterativeRandomStateSync(t *testing.T, batch int) {
srcDb, srcRoot, srcAccounts := makeTestState() srcDb, srcRoot, srcAccounts := makeTestState()
// Create a destination state and sync with the scheduler // Create a destination state and sync with the scheduler
dstDb := ethdb.NewMemDatabase() dstDb := rawdb.NewMemoryDatabase()
sched := NewStateSync(srcRoot, dstDb) sched := NewStateSync(srcRoot, dstDb)
queue := make(map[common.Hash]struct{}) queue := make(map[common.Hash]struct{})
@ -248,7 +249,7 @@ func TestIterativeRandomDelayedStateSync(t *testing.T) {
srcDb, srcRoot, srcAccounts := makeTestState() srcDb, srcRoot, srcAccounts := makeTestState()
// Create a destination state and sync with the scheduler // Create a destination state and sync with the scheduler
dstDb := ethdb.NewMemDatabase() dstDb := rawdb.NewMemoryDatabase()
sched := NewStateSync(srcRoot, dstDb) sched := NewStateSync(srcRoot, dstDb)
queue := make(map[common.Hash]struct{}) queue := make(map[common.Hash]struct{})
@ -292,10 +293,10 @@ func TestIncompleteStateSync(t *testing.T) {
// Create a random state to copy // Create a random state to copy
srcDb, srcRoot, srcAccounts := makeTestState() srcDb, srcRoot, srcAccounts := makeTestState()
checkTrieConsistency(srcDb.TrieDB().DiskDB().(ethdb.Database), srcRoot) checkTrieConsistency(srcDb.TrieDB().DiskDB().(database.Database), srcRoot)
// Create a destination state and sync with the scheduler // Create a destination state and sync with the scheduler
dstDb := ethdb.NewMemDatabase() dstDb := rawdb.NewMemoryDatabase()
sched := NewStateSync(srcRoot, dstDb) sched := NewStateSync(srcRoot, dstDb)
added := []common.Hash{} added := []common.Hash{}

View file

@ -27,10 +27,10 @@ import (
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"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/crypto" "github.com/ethereum/go-ethereum/crypto"
"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"
) )
@ -78,7 +78,7 @@ func pricedTransaction(nonce uint64, gaslimit uint64, gasprice *big.Int, key *ec
} }
func setupTxPool() (*TxPool, *ecdsa.PrivateKey) { func setupTxPool() (*TxPool, *ecdsa.PrivateKey) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
key, _ := crypto.GenerateKey() key, _ := crypto.GenerateKey()
@ -163,7 +163,7 @@ func (c *testChain) State() (*state.StateDB, error) {
// a state change between those fetches. // a state change between those fetches.
stdb := c.statedb stdb := c.statedb
if *c.trigger { if *c.trigger {
c.statedb, _ = state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) c.statedb, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
// simulate that the new head block included tx0 and tx1 // simulate that the new head block included tx0 and tx1
c.statedb.SetNonce(c.address, 2) c.statedb.SetNonce(c.address, 2)
c.statedb.SetBalance(c.address, new(big.Int).SetUint64(params.Ether)) c.statedb.SetBalance(c.address, new(big.Int).SetUint64(params.Ether))
@ -181,7 +181,7 @@ func TestStateChangeDuringTransactionPoolReset(t *testing.T) {
var ( var (
key, _ = crypto.GenerateKey() key, _ = crypto.GenerateKey()
address = crypto.PubkeyToAddress(key.PublicKey) address = crypto.PubkeyToAddress(key.PublicKey)
statedb, _ = state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) statedb, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
trigger = false trigger = false
) )
@ -335,7 +335,7 @@ func TestTransactionChainFork(t *testing.T) {
addr := crypto.PubkeyToAddress(key.PublicKey) addr := crypto.PubkeyToAddress(key.PublicKey)
resetState := func() { resetState := func() {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
statedb.AddBalance(addr, big.NewInt(100000000000000)) statedb.AddBalance(addr, big.NewInt(100000000000000))
pool.chain = &testBlockChain{statedb, 1000000, new(event.Feed)} pool.chain = &testBlockChain{statedb, 1000000, new(event.Feed)}
@ -364,7 +364,7 @@ func TestTransactionDoubleNonce(t *testing.T) {
addr := crypto.PubkeyToAddress(key.PublicKey) addr := crypto.PubkeyToAddress(key.PublicKey)
resetState := func() { resetState := func() {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
statedb.AddBalance(addr, big.NewInt(100000000000000)) statedb.AddBalance(addr, big.NewInt(100000000000000))
pool.chain = &testBlockChain{statedb, 1000000, new(event.Feed)} pool.chain = &testBlockChain{statedb, 1000000, new(event.Feed)}
@ -554,7 +554,7 @@ func TestTransactionPostponing(t *testing.T) {
t.Parallel() t.Parallel()
// Create the pool to test the postponing with // Create the pool to test the postponing with
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
@ -769,7 +769,7 @@ func testTransactionQueueGlobalLimiting(t *testing.T, nolocals bool) {
t.Parallel() t.Parallel()
// Create the pool to test the limit enforcement with // Create the pool to test the limit enforcement with
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig config := testTxPoolConfig
@ -857,7 +857,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
evictionInterval = time.Second evictionInterval = time.Second
// Create the pool to test the non-expiration enforcement // Create the pool to test the non-expiration enforcement
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig config := testTxPoolConfig
@ -1011,7 +1011,7 @@ func TestTransactionPendingGlobalLimiting(t *testing.T) {
t.Parallel() t.Parallel()
// Create the pool to test the limit enforcement with // Create the pool to test the limit enforcement with
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig config := testTxPoolConfig
@ -1057,7 +1057,7 @@ func TestTransactionCapClearsFromAll(t *testing.T) {
t.Parallel() t.Parallel()
// Create the pool to test the limit enforcement with // Create the pool to test the limit enforcement with
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig config := testTxPoolConfig
@ -1091,7 +1091,7 @@ func TestTransactionPendingMinimumAllowance(t *testing.T) {
t.Parallel() t.Parallel()
// Create the pool to test the limit enforcement with // Create the pool to test the limit enforcement with
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig config := testTxPoolConfig
@ -1139,7 +1139,7 @@ func TestTransactionPoolRepricing(t *testing.T) {
t.Parallel() t.Parallel()
// Create the pool to test the pricing enforcement with // Create the pool to test the pricing enforcement with
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
@ -1260,7 +1260,7 @@ func TestTransactionPoolRepricingKeepsLocals(t *testing.T) {
t.Parallel() t.Parallel()
// Create the pool to test the pricing enforcement with // Create the pool to test the pricing enforcement with
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
@ -1322,7 +1322,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
t.Parallel() t.Parallel()
// Create the pool to test the pricing enforcement with // Create the pool to test the pricing enforcement with
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig config := testTxPoolConfig
@ -1428,7 +1428,7 @@ func TestTransactionPoolStableUnderpricing(t *testing.T) {
t.Parallel() t.Parallel()
// Create the pool to test the pricing enforcement with // Create the pool to test the pricing enforcement with
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig config := testTxPoolConfig
@ -1494,7 +1494,7 @@ func TestTransactionReplacement(t *testing.T) {
t.Parallel() t.Parallel()
// Create the pool to test the pricing enforcement with // Create the pool to test the pricing enforcement with
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
@ -1588,7 +1588,7 @@ func testTransactionJournaling(t *testing.T, nolocals bool) {
os.Remove(journal) os.Remove(journal)
// Create the original pool to inject transaction into the journal // Create the original pool to inject transaction into the journal
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
config := testTxPoolConfig config := testTxPoolConfig
@ -1686,7 +1686,7 @@ func TestTransactionStatusCheck(t *testing.T) {
t.Parallel() t.Parallel()
// Create the pool to test the status retrievals with // Create the pool to test the status retrievals with
statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)

View file

@ -22,10 +22,10 @@ import (
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"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/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/params" "github.com/ethereum/go-ethereum/params"
) )
@ -99,7 +99,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
setDefaults(cfg) setDefaults(cfg)
if cfg.State == nil { if cfg.State == nil {
cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
} }
var ( var (
address = common.BytesToAddress([]byte("contract")) address = common.BytesToAddress([]byte("contract"))
@ -129,7 +129,7 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) {
setDefaults(cfg) setDefaults(cfg)
if cfg.State == nil { if cfg.State == nil {
cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
} }
var ( var (
vmenv = NewEnv(cfg) vmenv = NewEnv(cfg)

View file

@ -23,9 +23,9 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"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/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
) )
@ -95,7 +95,7 @@ func TestExecute(t *testing.T) {
} }
func TestCall(t *testing.T) { func TestCall(t *testing.T) {
state, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) state, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
address := common.HexToAddress("0x0a") address := common.HexToAddress("0x0a")
state.SetCode(address, []byte{ state.SetCode(address, []byte{
byte(vm.PUSH1), 10, byte(vm.PUSH1), 10,
@ -151,7 +151,7 @@ func BenchmarkCall(b *testing.B) {
} }
func benchmarkEVM_Create(bench *testing.B, code string) { func benchmarkEVM_Create(bench *testing.B, code string) {
var ( var (
statedb, _ = state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) statedb, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
sender = common.BytesToAddress([]byte("sender")) sender = common.BytesToAddress([]byte("sender"))
receiver = common.BytesToAddress([]byte("receiver")) receiver = common.BytesToAddress([]byte("receiver"))
) )

View file

@ -1,4 +1,4 @@
// Copyright 2014 The go-ethereum Authors // Copyright 2018 The go-ethereum Authors
// This file is part of the go-ethereum library. // This file is part of the go-ethereum library.
// //
// The go-ethereum library is free software: you can redistribute it and/or modify // The go-ethereum library is free software: you can redistribute it and/or modify
@ -14,39 +14,31 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package ethdb package database
// Code using batches should try to add this much data to the batch. // IdealBatchSize defines the size of the data batches should ideally add in one
// The value was determined empirically. // write.
const IdealBatchSize = 100 * 1024 const IdealBatchSize = 100 * 1024
// Putter wraps the database write operation supported by both batches and regular databases.
type Putter interface {
Put(key []byte, value []byte) error
}
// Deleter wraps the database delete operation supported by both batches and regular databases.
type Deleter interface {
Delete(key []byte) error
}
// Database wraps all database operations. All methods are safe for concurrent use.
type Database interface {
Putter
Deleter
Get(key []byte) ([]byte, error)
Has(key []byte) (bool, error)
Close()
NewBatch() Batch
}
// Batch is a write-only database that commits changes to its host database // Batch is a write-only database that commits changes to its host database
// when Write is called. Batch cannot be used concurrently. // when Write is called. A batch cannot be used concurrently.
type Batch interface { type Batch interface {
Putter Writer
Deleter Deleter
ValueSize() int // amount of data in the batch
// ValueSize retrieves the amount of data queued up for writing.
ValueSize() int
// Write flushes any accumulated data to disk.
Write() error Write() error
// Reset resets the batch for reuse // Reset resets the batch for reuse
Reset() Reset()
} }
// Batcher wraps the NewBatch method of a backing data store.
type Batcher interface {
// NewBatch creates a write-only database that buffers changes to its host db
// until a final write is called.
NewBatch() Batch
}

84
database/database.go Normal file
View file

@ -0,0 +1,84 @@
// Copyright 2018 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package database defines the interfaces for an Ethereum data store.
package database
import "io"
// Reader wraps the Has and Get method of a backing data store.
type Reader interface {
// Has retrieves if a key is present in the key-value data store.
Has(key []byte) (bool, error)
// Get retrieves the given key if it's present in the key-value data store.
Get(key []byte) ([]byte, error)
}
// Writer wraps the Put method of a backing data store.
type Writer interface {
// Put inserts the given value into the key-value data store.
Put(key []byte, value []byte) error
}
// Deleter wraps the Delete method of a backing data store.
type Deleter interface {
// Delete removes the key from the key-value data store.
Delete(key []byte) error
}
// Stater wraps the Stat method of a backing data store.
type Stater interface {
// Stat returns a particular internal stat of the database.
Stat(property string) (string, error)
}
// KeyValueStore contains all the methods required to allow handling different
// key-value data stores backing the high level database.
type KeyValueStore interface {
Reader
Writer
Deleter
Batcher
Iteratorer
Stater
io.Closer
}
// Ancienter wraps the Ancient method for a backing immutable chain data store.
type Ancienter interface {
// Ancient retrieves an ancient binary blob from the append-only immutable files.
Ancient(kind string, number uint64) ([]byte, error)
}
// AncientReader contains the methods required to access both key-value as well as
// immutable ancient data.
type AncientReader interface {
Reader
Ancienter
}
// Database contains all the methods required by the high level database to not
// only access
type Database interface {
AncientReader
Writer
Deleter
Batcher
Iteratorer
Stater
io.Closer
}

57
database/iterator.go Normal file
View file

@ -0,0 +1,57 @@
// Copyright 2018 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package database
// Iterator iterates over a databases key/value pairs in key order.
//
// When it encounters an error any seek will return false and will yield no key/
// value pairs. The error can be queried by calling the Error method. Calling
// Release is still necessary.
//
// An iterator must be released after use, but it is not necessary to read an
// iterator until exhaustion. An iterator is not safe for concurrent use, but it
// is safe to use multiple iterators concurrently.
type Iterator interface {
// Next moves the iterator to the next key/value pair. It returns whether the
// iterator is exhausted.
Next() bool
// Key returns the key of the current key/value pair, or nil if done. The caller
// should not modify the contents of the returned slice, and its contents may
// change on the next call to Next.
Key() []byte
// Value returns the value of the current key/value pair, or nil if done. The
// caller should not modify the contents of the returned slice, and its contents
// may change on the next call to Next.
Value() []byte
// Release releases associated resources. Release should always succeed and can
// be called multiple times without causing error.
Release()
}
// Iteratorer wraps the NewIterator methods of a backing data store.
type Iteratorer interface {
// NewIterator creates a binary-alphabetical iterator over the entire keyspace
// contained within the key-value database.
NewIterator() Iterator
// NewIteratorWithPrefix creates a binary-alphabetical iterator over a subset
// of database content with a particular key prefix.
NewIteratorWithPrefix(prefix []byte) Iterator
}

View file

@ -28,9 +28,9 @@ import (
"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/core/vm"
"github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/gasprice" "github.com/ethereum/go-ethereum/eth/gasprice"
"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"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
@ -201,7 +201,7 @@ func (b *EthAPIBackend) SuggestPrice(ctx context.Context) (*big.Int, error) {
return b.gpo.SuggestPrice(ctx) return b.gpo.SuggestPrice(ctx)
} }
func (b *EthAPIBackend) ChainDb() ethdb.Database { func (b *EthAPIBackend) ChainDb() database.Database {
return b.eth.ChainDb() return b.eth.ChainDb()
} }

View file

@ -22,8 +22,8 @@ import (
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/ethdb"
) )
var dumper = spew.ConfigState{Indent: " "} var dumper = spew.ConfigState{Indent: " "}
@ -31,7 +31,7 @@ var dumper = spew.ConfigState{Indent: " "}
func TestStorageRangeAt(t *testing.T) { func TestStorageRangeAt(t *testing.T) {
// Create a state where account 0x010000... has a few storage entries. // Create a state where account 0x010000... has a few storage entries.
var ( var (
state, _ = state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) state, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))
addr = common.Address{0x01} addr = common.Address{0x01}
keys = []common.Hash{ // hashes of Keys of storage keys = []common.Hash{ // hashes of Keys of storage
common.HexToHash("340dd630ad21bf010b4e676dbfa9ba9a02175262d1fa356232cfde6cb5b47ef2"), common.HexToHash("340dd630ad21bf010b4e676dbfa9ba9a02175262d1fa356232cfde6cb5b47ef2"),

View file

@ -24,7 +24,6 @@ import (
"runtime" "runtime"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time"
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -37,12 +36,11 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"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/core/vm"
"github.com/ethereum/go-ethereum/database"
"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"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/freezer"
"github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/miner" "github.com/ethereum/go-ethereum/miner"
@ -71,12 +69,11 @@ type Ethereum struct {
// Handlers // Handlers
txPool *core.TxPool txPool *core.TxPool
blockchain *core.BlockChain blockchain *core.BlockChain
freezer *freezer.Freezer
protocolManager *ProtocolManager protocolManager *ProtocolManager
lesServer LesServer lesServer LesServer
// DB interfaces // DB interfaces
chainDb ethdb.Database // Block chain database chainDb database.Database // Block chain database
eventMux *event.TypeMux eventMux *event.TypeMux
engine consensus.Engine engine consensus.Engine
@ -123,7 +120,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
log.Info("Allocated trie memory caches", "clean", common.StorageSize(config.TrieCleanCache)*1024*1024, "dirty", common.StorageSize(config.TrieDirtyCache)*1024*1024) log.Info("Allocated trie memory caches", "clean", common.StorageSize(config.TrieCleanCache)*1024*1024, "dirty", common.StorageSize(config.TrieDirtyCache)*1024*1024)
// Assemble the Ethereum object // Assemble the Ethereum object
chainDb, err := CreateDB(ctx, config, "chaindata") chainDb, err := ctx.OpenDatabaseWithFreezer("chaindata", config.DatabaseCache, config.DatabaseHandles, config.DatabaseFreezer, "eth/db/chaindata/")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -171,12 +168,6 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
eth.freezer, err = freezer.New(ctx.ResolvePath("freezer"))
if err != nil {
return nil, err
}
go eth.freezer.Freeze(eth.blockchain, chainDb, time.Minute, 60000)
// Rewind the chain in case of an incompatible config upgrade. // Rewind the chain in case of an incompatible config upgrade.
if compat, ok := genesisErr.(*params.ConfigCompatError); ok { if compat, ok := genesisErr.(*params.ConfigCompatError); ok {
log.Warn("Rewinding chain to upgrade configuration", "err", compat) log.Warn("Rewinding chain to upgrade configuration", "err", compat)
@ -224,20 +215,8 @@ func makeExtraData(extra []byte) []byte {
return extra return extra
} }
// CreateDB creates the chain database.
func CreateDB(ctx *node.ServiceContext, config *Config, name string) (ethdb.Database, error) {
db, err := ctx.OpenDatabase(name, config.DatabaseCache, config.DatabaseHandles)
if err != nil {
return nil, err
}
if db, ok := db.(*ethdb.LDBDatabase); ok {
db.Meter("eth/db/chaindata/")
}
return db, nil
}
// CreateConsensusEngine creates the required type of consensus engine instance for an Ethereum service // CreateConsensusEngine creates the required type of consensus engine instance for an Ethereum service
func CreateConsensusEngine(ctx *node.ServiceContext, chainConfig *params.ChainConfig, config *ethash.Config, notify []string, noverify bool, db ethdb.Database) consensus.Engine { func CreateConsensusEngine(ctx *node.ServiceContext, chainConfig *params.ChainConfig, config *ethash.Config, notify []string, noverify bool, db database.Database) consensus.Engine {
// If proof-of-authority is requested, set it up // If proof-of-authority is requested, set it up
if chainConfig.Clique != nil { if chainConfig.Clique != nil {
return clique.New(chainConfig.Clique, db) return clique.New(chainConfig.Clique, db)
@ -482,7 +461,7 @@ func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain }
func (s *Ethereum) TxPool() *core.TxPool { return s.txPool } func (s *Ethereum) TxPool() *core.TxPool { return s.txPool }
func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux } func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux }
func (s *Ethereum) Engine() consensus.Engine { return s.engine } func (s *Ethereum) Engine() consensus.Engine { return s.engine }
func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb } func (s *Ethereum) ChainDb() database.Database { return s.chainDb }
func (s *Ethereum) IsListening() bool { return true } // Always listening func (s *Ethereum) IsListening() bool { return true } // Always listening
func (s *Ethereum) EthVersion() int { return int(s.protocolManager.SubProtocols[0].Version) } func (s *Ethereum) EthVersion() int { return int(s.protocolManager.SubProtocols[0].Version) }
func (s *Ethereum) NetVersion() uint64 { return s.networkID } func (s *Ethereum) NetVersion() uint64 { return s.networkID }

View file

@ -26,7 +26,7 @@ import (
"github.com/ethereum/go-ethereum/core/bloombits" "github.com/ethereum/go-ethereum/core/bloombits"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
) )
const ( const (
@ -89,7 +89,7 @@ const (
// for the Ethereum header bloom filters, permitting blazing fast filtering. // for the Ethereum header bloom filters, permitting blazing fast filtering.
type BloomIndexer struct { type BloomIndexer struct {
size uint64 // section size to generate bloombits for size uint64 // section size to generate bloombits for
db ethdb.Database // database instance to write index data and metadata into db database.Database // database instance to write index data and metadata into
gen *bloombits.Generator // generator to rotate the bloom bits crating the bloom index gen *bloombits.Generator // generator to rotate the bloom bits crating the bloom index
section uint64 // Section is the section number being processed currently section uint64 // Section is the section number being processed currently
head common.Hash // Head is the hash of the last header processed head common.Hash // Head is the hash of the last header processed
@ -97,12 +97,12 @@ type BloomIndexer struct {
// NewBloomIndexer returns a chain indexer that generates bloom bits data for the // NewBloomIndexer returns a chain indexer that generates bloom bits data for the
// canonical chain for fast logs filtering. // canonical chain for fast logs filtering.
func NewBloomIndexer(db ethdb.Database, size, confirms uint64) *core.ChainIndexer { func NewBloomIndexer(db database.Database, size, confirms uint64) *core.ChainIndexer {
backend := &BloomIndexer{ backend := &BloomIndexer{
db: db, db: db,
size: size, size: size,
} }
table := ethdb.NewTable(db, string(rawdb.BloomBitsIndexPrefix)) table := rawdb.NewTable(db, string(rawdb.BloomBitsIndexPrefix))
return core.NewChainIndexer(db, table, backend, size, confirms, bloomThrottling, "bloombits") return core.NewChainIndexer(db, table, backend, size, confirms, bloomThrottling, "bloombits")
} }

View file

@ -102,6 +102,8 @@ type Config struct {
SkipBcVersionCheck bool `toml:"-"` SkipBcVersionCheck bool `toml:"-"`
DatabaseHandles int `toml:"-"` DatabaseHandles int `toml:"-"`
DatabaseCache int DatabaseCache int
DatabaseFreezer string
TrieCleanCache int TrieCleanCache int
TrieDirtyCache int TrieDirtyCache int
TrieTimeout time.Duration TrieTimeout time.Duration

View file

@ -29,7 +29,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"
@ -102,7 +102,7 @@ type Downloader struct {
genesis uint64 // Genesis block number to limit sync to (e.g. light client CHT) genesis uint64 // Genesis block number to limit sync to (e.g. light client CHT)
queue *queue // Scheduler for selecting the hashes to download queue *queue // Scheduler for selecting the hashes to download
peers *peerSet // Set of active peers from which download can proceed peers *peerSet // Set of active peers from which download can proceed
stateDB ethdb.Database stateDB database.Database
rttEstimate uint64 // Round trip time to target for download requests rttEstimate uint64 // Round trip time to target for download requests
rttConfidence uint64 // Confidence in the estimated RTT (unit: millionths to allow atomic ops) rttConfidence uint64 // Confidence in the estimated RTT (unit: millionths to allow atomic ops)
@ -205,7 +205,7 @@ type BlockChain interface {
} }
// New creates a new downloader to fetch hashes and blocks from remote peers. // New creates a new downloader to fetch hashes and blocks from remote peers.
func New(mode SyncMode, stateDb ethdb.Database, mux *event.TypeMux, chain BlockChain, lightchain LightChain, dropPeer peerDropFn) *Downloader { func New(mode SyncMode, stateDb database.Database, mux *event.TypeMux, chain BlockChain, lightchain LightChain, dropPeer peerDropFn) *Downloader {
if lightchain == nil { if lightchain == nil {
lightchain = chain lightchain = chain
} }

View file

@ -28,8 +28,9 @@ import (
ethereum "github.com/ethereum/go-ethereum" ethereum "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
) )
@ -46,8 +47,8 @@ type downloadTester struct {
downloader *Downloader downloader *Downloader
genesis *types.Block // Genesis blocks used by the tester and peers genesis *types.Block // Genesis blocks used by the tester and peers
stateDb ethdb.Database // Database used by the tester for syncing from peers stateDb database.Database // Database used by the tester for syncing from peers
peerDb ethdb.Database // Database of the peers containing all data peerDb database.Database // Database of the peers containing all data
peers map[string]*downloadTesterPeer peers map[string]*downloadTesterPeer
ownHashes []common.Hash // Hash chain belonging to the tester ownHashes []common.Hash // Hash chain belonging to the tester
@ -71,8 +72,9 @@ func newTester() *downloadTester {
ownReceipts: map[common.Hash]types.Receipts{testGenesis.Hash(): nil}, ownReceipts: map[common.Hash]types.Receipts{testGenesis.Hash(): nil},
ownChainTd: map[common.Hash]*big.Int{testGenesis.Hash(): testGenesis.Difficulty()}, ownChainTd: map[common.Hash]*big.Int{testGenesis.Hash(): testGenesis.Difficulty()},
} }
tester.stateDb = ethdb.NewMemDatabase() tester.stateDb = rawdb.NewMemoryDatabase()
tester.stateDb.Put(testGenesis.Root().Bytes(), []byte{0x00}) tester.stateDb.Put(testGenesis.Root().Bytes(), []byte{0x00})
tester.downloader = New(FullSync, tester.stateDb, new(event.TypeMux), tester, nil, tester.dropPeer) tester.downloader = New(FullSync, tester.stateDb, new(event.TypeMux), tester, nil, tester.dropPeer)
return tester return tester
} }

View file

@ -23,7 +23,7 @@ import (
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
) )
// FakePeer is a mock downloader peer that operates on a local database instance // FakePeer is a mock downloader peer that operates on a local database instance
@ -31,13 +31,13 @@ import (
// sync commands from an existing local database. // sync commands from an existing local database.
type FakePeer struct { type FakePeer struct {
id string id string
db ethdb.Database db database.Database
hc *core.HeaderChain hc *core.HeaderChain
dl *Downloader dl *Downloader
} }
// NewFakePeer creates a new mock downloader peer with the given data sources. // NewFakePeer creates a new mock downloader peer with the given data sources.
func NewFakePeer(id string, db ethdb.Database, hc *core.HeaderChain, dl *Downloader) *FakePeer { func NewFakePeer(id string, db database.Database, hc *core.HeaderChain, dl *Downloader) *FakePeer {
return &FakePeer{id: id, db: db, hc: hc, dl: dl} return &FakePeer{id: id, db: db, hc: hc, dl: dl}
} }

View file

@ -25,7 +25,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
"golang.org/x/crypto/sha3" "golang.org/x/crypto/sha3"
@ -325,7 +325,7 @@ func (s *stateSync) loop() (err error) {
} }
func (s *stateSync) commit(force bool) error { func (s *stateSync) commit(force bool) error {
if !force && s.bytesUncommitted < ethdb.IdealBatchSize { if !force && s.bytesUncommitted < database.IdealBatchSize {
return nil return nil
} }
start := time.Now() start := time.Now()

View file

@ -24,9 +24,9 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
) )
@ -34,7 +34,7 @@ import (
var ( var (
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
testAddress = crypto.PubkeyToAddress(testKey.PublicKey) testAddress = crypto.PubkeyToAddress(testKey.PublicKey)
testDB = ethdb.NewMemDatabase() testDB = rawdb.NewMemoryDatabase()
testGenesis = core.GenesisBlockForTesting(testDB, testAddress, big.NewInt(1000000000)) testGenesis = core.GenesisBlockForTesting(testDB, testAddress, big.NewInt(1000000000))
) )

View file

@ -27,14 +27,14 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
) )
var ( var (
testdb = ethdb.NewMemDatabase() testdb = rawdb.NewMemoryDatabase()
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
testAddress = crypto.PubkeyToAddress(testKey.PublicKey) testAddress = crypto.PubkeyToAddress(testKey.PublicKey)
genesis = core.GenesisBlockForTesting(testdb, testAddress, big.NewInt(1000000000)) genesis = core.GenesisBlockForTesting(testdb, testAddress, big.NewInt(1000000000))

View file

@ -29,7 +29,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
) )
@ -55,7 +55,7 @@ type PublicFilterAPI struct {
backend Backend backend Backend
mux *event.TypeMux mux *event.TypeMux
quit chan struct{} quit chan struct{}
chainDb ethdb.Database chainDb database.Database
events *EventSystem events *EventSystem
filtersMu sync.Mutex filtersMu sync.Mutex
filters map[rpc.ID]*filter filters map[rpc.ID]*filter

View file

@ -17,7 +17,6 @@
package filters package filters
import ( import (
"bytes"
"context" "context"
"fmt" "fmt"
"testing" "testing"
@ -28,7 +27,7 @@ import (
"github.com/ethereum/go-ethereum/core/bloombits" "github.com/ethereum/go-ethereum/core/bloombits"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/node"
) )
@ -67,7 +66,7 @@ func benchmarkBloomBits(b *testing.B, sectionSize uint64) {
benchDataDir := node.DefaultDataDir() + "/geth/chaindata" benchDataDir := node.DefaultDataDir() + "/geth/chaindata"
fmt.Println("Running bloombits benchmark section size:", sectionSize) fmt.Println("Running bloombits benchmark section size:", sectionSize)
db, err := ethdb.NewLDBDatabase(benchDataDir, 128, 1024) db, err := rawdb.NewLeveldbDatabase(benchDataDir, 128, 1024, "")
if err != nil { if err != nil {
b.Fatalf("error opening database at %v: %v", benchDataDir, err) b.Fatalf("error opening database at %v: %v", benchDataDir, err)
} }
@ -129,7 +128,7 @@ func benchmarkBloomBits(b *testing.B, sectionSize uint64) {
for i := 0; i < benchFilterCnt; i++ { for i := 0; i < benchFilterCnt; i++ {
if i%20 == 0 { if i%20 == 0 {
db.Close() db.Close()
db, _ = ethdb.NewLDBDatabase(benchDataDir, 128, 1024) db, _ = rawdb.NewLeveldbDatabase(benchDataDir, 128, 1024, "")
backend = &testBackend{mux, db, cnt, new(event.Feed), new(event.Feed), new(event.Feed), new(event.Feed)} backend = &testBackend{mux, db, cnt, new(event.Feed), new(event.Feed), new(event.Feed), new(event.Feed)}
} }
var addr common.Address var addr common.Address
@ -146,37 +145,21 @@ func benchmarkBloomBits(b *testing.B, sectionSize uint64) {
db.Close() db.Close()
} }
func forEachKey(db ethdb.Database, startPrefix, endPrefix []byte, fn func(key []byte)) {
it := db.(*ethdb.LDBDatabase).NewIterator()
it.Seek(startPrefix)
for it.Valid() {
key := it.Key()
cmpLen := len(key)
if len(endPrefix) < cmpLen {
cmpLen = len(endPrefix)
}
if bytes.Compare(key[:cmpLen], endPrefix) == 1 {
break
}
fn(common.CopyBytes(key))
it.Next()
}
it.Release()
}
var bloomBitsPrefix = []byte("bloomBits-") var bloomBitsPrefix = []byte("bloomBits-")
func clearBloomBits(db ethdb.Database) { func clearBloomBits(db database.Database) {
fmt.Println("Clearing bloombits data...") fmt.Println("Clearing bloombits data...")
forEachKey(db, bloomBitsPrefix, bloomBitsPrefix, func(key []byte) { it := db.NewIteratorWithPrefix(bloomBitsPrefix)
db.Delete(key) for it.Next() {
}) db.Delete(it.Key())
}
it.Release()
} }
func BenchmarkNoBloomBits(b *testing.B) { func BenchmarkNoBloomBits(b *testing.B) {
benchDataDir := node.DefaultDataDir() + "/geth/chaindata" benchDataDir := node.DefaultDataDir() + "/geth/chaindata"
fmt.Println("Running benchmark without bloombits") fmt.Println("Running benchmark without bloombits")
db, err := ethdb.NewLDBDatabase(benchDataDir, 128, 1024) db, err := rawdb.NewLeveldbDatabase(benchDataDir, 128, 1024, "")
if err != nil { if err != nil {
b.Fatalf("error opening database at %v: %v", benchDataDir, err) b.Fatalf("error opening database at %v: %v", benchDataDir, err)
} }

View file

@ -25,13 +25,13 @@ import (
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/bloombits" "github.com/ethereum/go-ethereum/core/bloombits"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
) )
type Backend interface { type Backend interface {
ChainDb() ethdb.Database ChainDb() database.Database
EventMux() *event.TypeMux EventMux() *event.TypeMux
HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error)
HeaderByHash(ctx context.Context, blockHash common.Hash) (*types.Header, error) HeaderByHash(ctx context.Context, blockHash common.Hash) (*types.Header, error)
@ -51,7 +51,7 @@ type Backend interface {
type Filter struct { type Filter struct {
backend Backend backend Backend
db ethdb.Database db database.Database
addresses []common.Address addresses []common.Address
topics [][]common.Hash topics [][]common.Hash

View file

@ -32,7 +32,7 @@ import (
"github.com/ethereum/go-ethereum/core/bloombits" "github.com/ethereum/go-ethereum/core/bloombits"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
@ -40,7 +40,7 @@ import (
type testBackend struct { type testBackend struct {
mux *event.TypeMux mux *event.TypeMux
db ethdb.Database db database.Database
sections uint64 sections uint64
txFeed *event.Feed txFeed *event.Feed
rmLogsFeed *event.Feed rmLogsFeed *event.Feed
@ -48,7 +48,7 @@ type testBackend struct {
chainFeed *event.Feed chainFeed *event.Feed
} }
func (b *testBackend) ChainDb() ethdb.Database { func (b *testBackend) ChainDb() database.Database {
return b.db return b.db
} }
@ -161,7 +161,7 @@ func TestBlockSubscription(t *testing.T) {
var ( var (
mux = new(event.TypeMux) mux = new(event.TypeMux)
db = ethdb.NewMemDatabase() db = rawdb.NewMemoryDatabase()
txFeed = new(event.Feed) txFeed = new(event.Feed)
rmLogsFeed = new(event.Feed) rmLogsFeed = new(event.Feed)
logsFeed = new(event.Feed) logsFeed = new(event.Feed)
@ -218,7 +218,7 @@ func TestPendingTxFilter(t *testing.T) {
var ( var (
mux = new(event.TypeMux) mux = new(event.TypeMux)
db = ethdb.NewMemDatabase() db = rawdb.NewMemoryDatabase()
txFeed = new(event.Feed) txFeed = new(event.Feed)
rmLogsFeed = new(event.Feed) rmLogsFeed = new(event.Feed)
logsFeed = new(event.Feed) logsFeed = new(event.Feed)
@ -278,7 +278,7 @@ func TestPendingTxFilter(t *testing.T) {
func TestLogFilterCreation(t *testing.T) { func TestLogFilterCreation(t *testing.T) {
var ( var (
mux = new(event.TypeMux) mux = new(event.TypeMux)
db = ethdb.NewMemDatabase() db = rawdb.NewMemoryDatabase()
txFeed = new(event.Feed) txFeed = new(event.Feed)
rmLogsFeed = new(event.Feed) rmLogsFeed = new(event.Feed)
logsFeed = new(event.Feed) logsFeed = new(event.Feed)
@ -327,7 +327,7 @@ func TestInvalidLogFilterCreation(t *testing.T) {
var ( var (
mux = new(event.TypeMux) mux = new(event.TypeMux)
db = ethdb.NewMemDatabase() db = rawdb.NewMemoryDatabase()
txFeed = new(event.Feed) txFeed = new(event.Feed)
rmLogsFeed = new(event.Feed) rmLogsFeed = new(event.Feed)
logsFeed = new(event.Feed) logsFeed = new(event.Feed)
@ -354,7 +354,7 @@ func TestInvalidLogFilterCreation(t *testing.T) {
func TestInvalidGetLogsRequest(t *testing.T) { func TestInvalidGetLogsRequest(t *testing.T) {
var ( var (
mux = new(event.TypeMux) mux = new(event.TypeMux)
db = ethdb.NewMemDatabase() db = rawdb.NewMemoryDatabase()
txFeed = new(event.Feed) txFeed = new(event.Feed)
rmLogsFeed = new(event.Feed) rmLogsFeed = new(event.Feed)
logsFeed = new(event.Feed) logsFeed = new(event.Feed)
@ -384,7 +384,7 @@ func TestLogFilter(t *testing.T) {
var ( var (
mux = new(event.TypeMux) mux = new(event.TypeMux)
db = ethdb.NewMemDatabase() db = rawdb.NewMemoryDatabase()
txFeed = new(event.Feed) txFeed = new(event.Feed)
rmLogsFeed = new(event.Feed) rmLogsFeed = new(event.Feed)
logsFeed = new(event.Feed) logsFeed = new(event.Feed)
@ -503,7 +503,7 @@ func TestPendingLogsSubscription(t *testing.T) {
var ( var (
mux = new(event.TypeMux) mux = new(event.TypeMux)
db = ethdb.NewMemDatabase() db = rawdb.NewMemoryDatabase()
txFeed = new(event.Feed) txFeed = new(event.Feed)
rmLogsFeed = new(event.Feed) rmLogsFeed = new(event.Feed)
logsFeed = new(event.Feed) logsFeed = new(event.Feed)

View file

@ -29,7 +29,6 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"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"
) )
@ -51,7 +50,7 @@ func BenchmarkFilters(b *testing.B) {
defer os.RemoveAll(dir) defer os.RemoveAll(dir)
var ( var (
db, _ = ethdb.NewLDBDatabase(dir, 0, 0) db, _ = rawdb.NewLeveldbDatabase(dir, 0, 0, "")
mux = new(event.TypeMux) mux = new(event.TypeMux)
txFeed = new(event.Feed) txFeed = new(event.Feed)
rmLogsFeed = new(event.Feed) rmLogsFeed = new(event.Feed)
@ -110,7 +109,7 @@ func TestFilters(t *testing.T) {
defer os.RemoveAll(dir) defer os.RemoveAll(dir)
var ( var (
db, _ = ethdb.NewLDBDatabase(dir, 0, 0) db, _ = rawdb.NewLeveldbDatabase(dir, 0, 0, "")
mux = new(event.TypeMux) mux = new(event.TypeMux)
txFeed = new(event.Feed) txFeed = new(event.Feed)
rmLogsFeed = new(event.Feed) rmLogsFeed = new(event.Feed)

View file

@ -31,9 +31,9 @@ import (
"github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/consensus/misc"
"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/database"
"github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/fetcher" "github.com/ethereum/go-ethereum/eth/fetcher"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
@ -103,7 +103,7 @@ type ProtocolManager struct {
// NewProtocolManager returns a new Ethereum sub protocol manager. The Ethereum sub protocol manages peers capable // NewProtocolManager returns a new Ethereum sub protocol manager. The Ethereum sub protocol manages peers capable
// with the Ethereum network. // with the Ethereum network.
func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, networkID uint64, mux *event.TypeMux, txpool txPool, engine consensus.Engine, blockchain *core.BlockChain, chaindb ethdb.Database, whitelist map[uint64]common.Hash) (*ProtocolManager, error) { func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, networkID uint64, mux *event.TypeMux, txpool txPool, engine consensus.Engine, blockchain *core.BlockChain, chaindb database.Database, whitelist map[uint64]common.Hash) (*ProtocolManager, error) {
// Create the protocol manager with the base fields // Create the protocol manager with the base fields
manager := &ProtocolManager{ manager := &ProtocolManager{
networkID: networkID, networkID: networkID,

View file

@ -27,12 +27,12 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"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/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/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
@ -344,11 +344,15 @@ func testGetNodeData(t *testing.T, protocol int) {
// Fetch for now the entire chain db // Fetch for now the entire chain db
hashes := []common.Hash{} hashes := []common.Hash{}
for _, key := range db.Keys() {
if len(key) == len(common.Hash{}) { it := db.NewIterator()
for it.Next() {
if key := it.Key(); len(key) == common.HashLength {
hashes = append(hashes, common.BytesToHash(key)) hashes = append(hashes, common.BytesToHash(key))
} }
} }
it.Release()
p2p.Send(peer.app, 0x0d, hashes) p2p.Send(peer.app, 0x0d, hashes)
msg, err := peer.app.ReadMsg() msg, err := peer.app.ReadMsg()
if err != nil { if err != nil {
@ -367,7 +371,7 @@ func testGetNodeData(t *testing.T, protocol int) {
t.Errorf("data hash mismatch: have %x, want %x", hash, want) t.Errorf("data hash mismatch: have %x, want %x", hash, want)
} }
} }
statedb := ethdb.NewMemDatabase() statedb := rawdb.NewMemoryDatabase()
for i := 0; i < len(data); i++ { for i := 0; i < len(data); i++ {
statedb.Put(hashes[i].Bytes(), data[i]) statedb.Put(hashes[i].Bytes(), data[i])
} }
@ -469,7 +473,7 @@ func testDAOChallenge(t *testing.T, localForked, remoteForked bool, timeout bool
var ( var (
evmux = new(event.TypeMux) evmux = new(event.TypeMux)
pow = ethash.NewFaker() pow = ethash.NewFaker()
db = ethdb.NewMemDatabase() db = rawdb.NewMemoryDatabase()
config = &params.ChainConfig{DAOForkBlock: big.NewInt(1), DAOForkSupport: localForked} config = &params.ChainConfig{DAOForkBlock: big.NewInt(1), DAOForkSupport: localForked}
gspec = &core.Genesis{Config: config} gspec = &core.Genesis{Config: config}
genesis = gspec.MustCommit(db) genesis = gspec.MustCommit(db)
@ -550,7 +554,7 @@ func testBroadcastBlock(t *testing.T, totalPeers, broadcastExpected int) {
var ( var (
evmux = new(event.TypeMux) evmux = new(event.TypeMux)
pow = ethash.NewFaker() pow = ethash.NewFaker()
db = ethdb.NewMemDatabase() db = rawdb.NewMemoryDatabase()
config = &params.ChainConfig{} config = &params.ChainConfig{}
gspec = &core.Genesis{Config: config} gspec = &core.Genesis{Config: config}
genesis = gspec.MustCommit(db) genesis = gspec.MustCommit(db)

View file

@ -30,11 +30,12 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"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/core/vm"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/database"
"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/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
@ -49,11 +50,11 @@ var (
// newTestProtocolManager creates a new protocol manager for testing purposes, // newTestProtocolManager creates a new protocol manager for testing purposes,
// with the given number of blocks already known, and potential notification // with the given number of blocks already known, and potential notification
// channels for different events. // channels for different events.
func newTestProtocolManager(mode downloader.SyncMode, blocks int, generator func(int, *core.BlockGen), newtx chan<- []*types.Transaction) (*ProtocolManager, *ethdb.MemDatabase, error) { func newTestProtocolManager(mode downloader.SyncMode, blocks int, generator func(int, *core.BlockGen), newtx chan<- []*types.Transaction) (*ProtocolManager, database.Database, error) {
var ( var (
evmux = new(event.TypeMux) evmux = new(event.TypeMux)
engine = ethash.NewFaker() engine = ethash.NewFaker()
db = ethdb.NewMemDatabase() db = rawdb.NewMemoryDatabase()
gspec = &core.Genesis{ gspec = &core.Genesis{
Config: params.TestChainConfig, Config: params.TestChainConfig,
Alloc: core.GenesisAlloc{testBank: {Balance: big.NewInt(1000000)}}, Alloc: core.GenesisAlloc{testBank: {Balance: big.NewInt(1000000)}},
@ -78,7 +79,7 @@ func newTestProtocolManager(mode downloader.SyncMode, blocks int, generator func
// with the given number of blocks already known, and potential notification // with the given number of blocks already known, and potential notification
// channels for different events. In case of an error, the constructor force- // channels for different events. In case of an error, the constructor force-
// fails the test. // fails the test.
func newTestProtocolManagerMust(t *testing.T, mode downloader.SyncMode, blocks int, generator func(int, *core.BlockGen), newtx chan<- []*types.Transaction) (*ProtocolManager, *ethdb.MemDatabase) { func newTestProtocolManagerMust(t *testing.T, mode downloader.SyncMode, blocks int, generator func(int, *core.BlockGen), newtx chan<- []*types.Transaction) (*ProtocolManager, database.Database) {
pm, db, err := newTestProtocolManager(mode, blocks, generator, newtx) pm, db, err := newTestProtocolManager(mode, blocks, generator, newtx)
if err != nil { if err != nil {
t.Fatalf("Failed to create protocol manager: %v", err) t.Fatalf("Failed to create protocol manager: %v", err)

View file

@ -31,10 +31,10 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"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/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/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/tests" "github.com/ethereum/go-ethereum/tests"
@ -155,6 +155,7 @@ func TestPrestateTracerCreate2(t *testing.T) {
GasPrice: big.NewInt(1), GasPrice: big.NewInt(1),
} }
alloc := core.GenesisAlloc{} alloc := core.GenesisAlloc{}
// The code pushes 'deadbeef' into memory, then the other params, and calls CREATE2, then returns // The code pushes 'deadbeef' into memory, then the other params, and calls CREATE2, then returns
// the address // the address
alloc[common.HexToAddress("0x00000000000000000000000000000000deadbeef")] = core.GenesisAccount{ alloc[common.HexToAddress("0x00000000000000000000000000000000deadbeef")] = core.GenesisAccount{
@ -167,7 +168,8 @@ func TestPrestateTracerCreate2(t *testing.T) {
Code: []byte{}, Code: []byte{},
Balance: big.NewInt(500000000000000), Balance: big.NewInt(500000000000000),
} }
statedb := tests.MakePreState(ethdb.NewMemDatabase(), alloc) statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), alloc)
// Create the tracer, the EVM environment and run it // Create the tracer, the EVM environment and run it
tracer, err := New("prestateTracer") tracer, err := New("prestateTracer")
if err != nil { if err != nil {
@ -240,7 +242,7 @@ func TestCallTracer(t *testing.T) {
GasLimit: uint64(test.Context.GasLimit), GasLimit: uint64(test.Context.GasLimit),
GasPrice: tx.GasPrice(), GasPrice: tx.GasPrice(),
} }
statedb := tests.MakePreState(ethdb.NewMemDatabase(), test.Genesis.Alloc) statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc)
// Create the tracer, the EVM environment and run it // Create the tracer, the EVM environment and run it
tracer, err := New("callTracer") tracer, err := New("callTracer")

12
ethdb/.gitignore vendored
View file

@ -1,12 +0,0 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.
#
# If you find yourself ignoring temporary files generated by your text editor
# or operating system, you probably want to add a global ignore instead:
# git config --global core.excludesfile ~/.gitignore_global
/tmp
*/**/*un~
*un~
.DS_Store
*/**/.DS_Store

View file

@ -1,68 +0,0 @@
// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// +build js
package ethdb
import (
"errors"
)
var errNotSupported = errors.New("ethdb: not supported")
type LDBDatabase struct {
}
// NewLDBDatabase returns a LevelDB wrapped object.
func NewLDBDatabase(file string, cache int, handles int) (*LDBDatabase, error) {
return nil, errNotSupported
}
// Path returns the path to the database directory.
func (db *LDBDatabase) Path() string {
return ""
}
// Put puts the given key / value to the queue
func (db *LDBDatabase) Put(key []byte, value []byte) error {
return errNotSupported
}
func (db *LDBDatabase) Has(key []byte) (bool, error) {
return false, errNotSupported
}
// Get returns the given key if it's present.
func (db *LDBDatabase) Get(key []byte) ([]byte, error) {
return nil, errNotSupported
}
// Delete deletes the key from the queue and database
func (db *LDBDatabase) Delete(key []byte) error {
return errNotSupported
}
func (db *LDBDatabase) Close() {
}
// Meter configures the database metrics collectors and
func (db *LDBDatabase) Meter(prefix string) {
}
func (db *LDBDatabase) NewBatch() Batch {
return nil
}

View file

@ -1,25 +0,0 @@
// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// +build js
package ethdb_test
import (
"github.com/ethereum/go-ethereum/ethdb"
)
var _ ethdb.Database = &ethdb.LDBDatabase{}

View file

@ -1,214 +0,0 @@
// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// +build !js
package ethdb_test
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"strconv"
"sync"
"testing"
"github.com/ethereum/go-ethereum/ethdb"
)
func newTestLDB() (*ethdb.LDBDatabase, func()) {
dirname, err := ioutil.TempDir(os.TempDir(), "ethdb_test_")
if err != nil {
panic("failed to create test file: " + err.Error())
}
db, err := ethdb.NewLDBDatabase(dirname, 0, 0)
if err != nil {
panic("failed to create test database: " + err.Error())
}
return db, func() {
db.Close()
os.RemoveAll(dirname)
}
}
var test_values = []string{"", "a", "1251", "\x00123\x00"}
func TestLDB_PutGet(t *testing.T) {
db, remove := newTestLDB()
defer remove()
testPutGet(db, t)
}
func TestMemoryDB_PutGet(t *testing.T) {
testPutGet(ethdb.NewMemDatabase(), t)
}
func testPutGet(db ethdb.Database, t *testing.T) {
t.Parallel()
for _, k := range test_values {
err := db.Put([]byte(k), nil)
if err != nil {
t.Fatalf("put failed: %v", err)
}
}
for _, k := range test_values {
data, err := db.Get([]byte(k))
if err != nil {
t.Fatalf("get failed: %v", err)
}
if len(data) != 0 {
t.Fatalf("get returned wrong result, got %q expected nil", string(data))
}
}
_, err := db.Get([]byte("non-exist-key"))
if err == nil {
t.Fatalf("expect to return a not found error")
}
for _, v := range test_values {
err := db.Put([]byte(v), []byte(v))
if err != nil {
t.Fatalf("put failed: %v", err)
}
}
for _, v := range test_values {
data, err := db.Get([]byte(v))
if err != nil {
t.Fatalf("get failed: %v", err)
}
if !bytes.Equal(data, []byte(v)) {
t.Fatalf("get returned wrong result, got %q expected %q", string(data), v)
}
}
for _, v := range test_values {
err := db.Put([]byte(v), []byte("?"))
if err != nil {
t.Fatalf("put override failed: %v", err)
}
}
for _, v := range test_values {
data, err := db.Get([]byte(v))
if err != nil {
t.Fatalf("get failed: %v", err)
}
if !bytes.Equal(data, []byte("?")) {
t.Fatalf("get returned wrong result, got %q expected ?", string(data))
}
}
for _, v := range test_values {
orig, err := db.Get([]byte(v))
if err != nil {
t.Fatalf("get failed: %v", err)
}
orig[0] = byte(0xff)
data, err := db.Get([]byte(v))
if err != nil {
t.Fatalf("get failed: %v", err)
}
if !bytes.Equal(data, []byte("?")) {
t.Fatalf("get returned wrong result, got %q expected ?", string(data))
}
}
for _, v := range test_values {
err := db.Delete([]byte(v))
if err != nil {
t.Fatalf("delete %q failed: %v", v, err)
}
}
for _, v := range test_values {
_, err := db.Get([]byte(v))
if err == nil {
t.Fatalf("got deleted value %q", v)
}
}
}
func TestLDB_ParallelPutGet(t *testing.T) {
db, remove := newTestLDB()
defer remove()
testParallelPutGet(db, t)
}
func TestMemoryDB_ParallelPutGet(t *testing.T) {
testParallelPutGet(ethdb.NewMemDatabase(), t)
}
func testParallelPutGet(db ethdb.Database, t *testing.T) {
const n = 8
var pending sync.WaitGroup
pending.Add(n)
for i := 0; i < n; i++ {
go func(key string) {
defer pending.Done()
err := db.Put([]byte(key), []byte("v"+key))
if err != nil {
panic("put failed: " + err.Error())
}
}(strconv.Itoa(i))
}
pending.Wait()
pending.Add(n)
for i := 0; i < n; i++ {
go func(key string) {
defer pending.Done()
data, err := db.Get([]byte(key))
if err != nil {
panic("get failed: " + err.Error())
}
if !bytes.Equal(data, []byte("v"+key)) {
panic(fmt.Sprintf("get failed, got %q expected %q", []byte(data), []byte("v"+key)))
}
}(strconv.Itoa(i))
}
pending.Wait()
pending.Add(n)
for i := 0; i < n; i++ {
go func(key string) {
defer pending.Done()
err := db.Delete([]byte(key))
if err != nil {
panic("delete failed: " + err.Error())
}
}(strconv.Itoa(i))
}
pending.Wait()
pending.Add(n)
for i := 0; i < n; i++ {
go func(key string) {
defer pending.Done()
_, err := db.Get([]byte(key))
if err == nil {
panic("get succeeded")
}
}(strconv.Itoa(i))
}
pending.Wait()
}

View file

@ -1,143 +0,0 @@
// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package ethdb
import (
"errors"
"sync"
"github.com/ethereum/go-ethereum/common"
)
/*
* This is a test memory database. Do not use for any production it does not get persisted
*/
type MemDatabase struct {
db map[string][]byte
lock sync.RWMutex
}
func NewMemDatabase() *MemDatabase {
return &MemDatabase{
db: make(map[string][]byte),
}
}
func NewMemDatabaseWithCap(size int) *MemDatabase {
return &MemDatabase{
db: make(map[string][]byte, size),
}
}
func (db *MemDatabase) Put(key []byte, value []byte) error {
db.lock.Lock()
defer db.lock.Unlock()
db.db[string(key)] = common.CopyBytes(value)
return nil
}
func (db *MemDatabase) Has(key []byte) (bool, error) {
db.lock.RLock()
defer db.lock.RUnlock()
_, ok := db.db[string(key)]
return ok, nil
}
func (db *MemDatabase) Get(key []byte) ([]byte, error) {
db.lock.RLock()
defer db.lock.RUnlock()
if entry, ok := db.db[string(key)]; ok {
return common.CopyBytes(entry), nil
}
return nil, errors.New("not found")
}
func (db *MemDatabase) Keys() [][]byte {
db.lock.RLock()
defer db.lock.RUnlock()
keys := [][]byte{}
for key := range db.db {
keys = append(keys, []byte(key))
}
return keys
}
func (db *MemDatabase) Delete(key []byte) error {
db.lock.Lock()
defer db.lock.Unlock()
delete(db.db, string(key))
return nil
}
func (db *MemDatabase) Close() {}
func (db *MemDatabase) NewBatch() Batch {
return &memBatch{db: db}
}
func (db *MemDatabase) Len() int { return len(db.db) }
type kv struct {
k, v []byte
del bool
}
type memBatch struct {
db *MemDatabase
writes []kv
size int
}
func (b *memBatch) Put(key, value []byte) error {
b.writes = append(b.writes, kv{common.CopyBytes(key), common.CopyBytes(value), false})
b.size += len(value)
return nil
}
func (b *memBatch) Delete(key []byte) error {
b.writes = append(b.writes, kv{common.CopyBytes(key), nil, true})
b.size += 1
return nil
}
func (b *memBatch) Write() error {
b.db.lock.Lock()
defer b.db.lock.Unlock()
for _, kv := range b.writes {
if kv.del {
delete(b.db.db, string(kv.k))
continue
}
b.db.db[string(kv.k)] = kv.v
}
return nil
}
func (b *memBatch) ValueSize() int {
return b.size
}
func (b *memBatch) Reset() {
b.writes = b.writes[:0]
b.size = 0
}

View file

@ -1,51 +0,0 @@
// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package ethdb
type table struct {
db Database
prefix string
}
// NewTable returns a Database object that prefixes all keys with a given
// string.
func NewTable(db Database, prefix string) Database {
return &table{
db: db,
prefix: prefix,
}
}
func (dt *table) Put(key []byte, value []byte) error {
return dt.db.Put(append([]byte(dt.prefix), key...), value)
}
func (dt *table) Has(key []byte) (bool, error) {
return dt.db.Has(append([]byte(dt.prefix), key...))
}
func (dt *table) Get(key []byte) ([]byte, error) {
return dt.db.Get(append([]byte(dt.prefix), key...))
}
func (dt *table) Delete(key []byte) error {
return dt.db.Delete(append([]byte(dt.prefix), key...))
}
func (dt *table) Close() {
// Do nothing; don't close the underlying DB.
}

View file

@ -1,51 +0,0 @@
// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package ethdb
type tableBatch struct {
batch Batch
prefix string
}
// NewTableBatch returns a Batch object which prefixes all keys with a given string.
func NewTableBatch(db Database, prefix string) Batch {
return &tableBatch{db.NewBatch(), prefix}
}
func (dt *table) NewBatch() Batch {
return &tableBatch{dt.db.NewBatch(), dt.prefix}
}
func (tb *tableBatch) Put(key, value []byte) error {
return tb.batch.Put(append([]byte(tb.prefix), key...), value)
}
func (tb *tableBatch) Delete(key []byte) error {
return tb.batch.Delete(append([]byte(tb.prefix), key...))
}
func (tb *tableBatch) Write() error {
return tb.batch.Write()
}
func (tb *tableBatch) ValueSize() int {
return tb.batch.ValueSize()
}
func (tb *tableBatch) Reset() {
tb.batch.Reset()
}

View file

@ -1,213 +0,0 @@
// Copyright 2018 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package freezer implements an append-only immutable mmap chain database.
package freezer
import (
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/rlp"
)
// Freezer is an memory mapped append-only database to store immutable chain data
// into flat files:
//
// - The append only nature ensures that disk writes are minimized.
// - The memory mapping ensures we can max out system memory for caching without
// reserving it for go-ethereum. This would also reduce the memory requirements
// of Geth, and thus also GC overhead.
type Freezer struct {
frozen uint64 // Number of blocks already frozen
headers *table // Data table for storing the block headers
bodies *table // Data table for storing the block bodies
receipts *table // Data table for storing the block receipts
diffs *table // Data table for storing the block tds
logger log.Logger // Contextual logger for the freezer database
}
// New creates a chain freezer that moves ancient chain data into immutable flat
// file containers.
func New(datadir string) (*Freezer, error) {
// Create the initial freezer object
var (
freezer = &Freezer{
logger: log.New("path", datadir),
}
readMeter = metrics.NewRegisteredMeter("eth/db/freezer/read", nil)
writeMeter = metrics.NewRegisteredMeter("eth/db/freezer/write", nil)
err error
)
// Open all the supported data tables
if freezer.headers, err = newTable(datadir, "headers", readMeter, writeMeter); err != nil {
return nil, err
}
if freezer.bodies, err = newTable(datadir, "bodies", readMeter, writeMeter); err != nil {
freezer.headers.Close()
return nil, err
}
if freezer.receipts, err = newTable(datadir, "receipts", readMeter, writeMeter); err != nil {
freezer.bodies.Close()
freezer.headers.Close()
return nil, err
}
if freezer.diffs, err = newTable(datadir, "diffs", readMeter, writeMeter); err != nil {
freezer.receipts.Close()
freezer.bodies.Close()
freezer.headers.Close()
return nil, err
}
return freezer, nil
}
// Close terminates the chain freezer, unmapping all the data files.
func (f *Freezer) Close() error {
f.diffs.Close()
f.receipts.Close()
f.bodies.Close()
f.headers.Close()
return nil
}
// Freeze is a background thread that periodically checks the blockchain for any
// import progress and moves ancient data from the fast database into the freezer.
//
// This functionality is deliberately broken off from block importing to avoid
// incurring additional data shuffling delays on block propagation.
func (f *Freezer) Freeze(chain *core.BlockChain, db ethdb.Database, recheck time.Duration, delay uint64) {
for {
// Retrieve the freezing threshold. In theory we're interested only in full
// blocks post-sync, but that would keep the live database enormous during
// dast sync. By picking the fast block, we still get to deep freeze all the
// final immutable data without having to wait for sync to finish.
head := chain.CurrentFastBlock()
if head == nil {
log.Error("Current fast block is nil")
time.Sleep(recheck)
continue
}
if head.NumberU64() < delay {
log.Debug("Current block not old enough", "number", head.Number(), "hash", head.Hash(), "age", common.PrettyAge(time.Unix(head.Time().Int64(), 0)), "delay", delay)
time.Sleep(recheck)
continue
}
limit := head.NumberU64() - delay
if limit <= f.frozen {
log.Debug("Ancient blocks frozen already")
time.Sleep(recheck)
continue
}
// Seems we have data ready to be frozen, process in usable batches
if limit-f.frozen > 30000 {
limit = f.frozen + 30000
}
var (
start = time.Now()
first = f.frozen
last *types.Block
)
for f.frozen < limit {
// Deep freeze the next canonical block if it's available
if block := chain.GetBlockByNumber(f.frozen); block != nil {
// Deep freeze the block header and body
blob, _ := rlp.EncodeToBytes(block.Header())
if err := f.headers.Append(f.frozen, blob); err != nil {
log.Error("Failed to deep freeze header", "number", block.Number(), "hash", block.Hash(), "age", common.PrettyAge(time.Unix(block.Time().Int64(), 0)), "err", err)
break
}
blob, _ = rlp.EncodeToBytes(block.Body())
if err := f.bodies.Append(f.frozen, blob); err != nil {
log.Error("Failed to deep freeze body", "number", block.Number(), "hash", block.Hash(), "age", common.PrettyAge(time.Unix(block.Time().Int64(), 0)), "err", err)
break
}
// Deep freeze the block receipts and total difficulty
if receipts := chain.GetReceiptsByHash(block.Hash()); receipts != nil {
blob, _ = rlp.EncodeToBytes(receipts)
if err := f.receipts.Append(f.frozen, blob); err != nil {
log.Error("Failed to deep freeze receipts", "number", block.Number(), "hash", block.Hash(), "age", common.PrettyAge(time.Unix(block.Time().Int64(), 0)), "err", err)
break
}
}
if td := chain.GetTd(block.Hash(), block.NumberU64()); td != nil {
blob, _ = rlp.EncodeToBytes(td)
if err := f.diffs.Append(f.frozen, blob); err != nil {
log.Error("Failed to deep freeze difficulty", "number", block.Number(), "hash", block.Hash(), "age", common.PrettyAge(time.Unix(block.Time().Int64(), 0)), "err", err)
break
}
}
log.Trace("Deep froze ancient block", "number", block.Number(), "hash", block.Hash(), "age", common.PrettyAge(time.Unix(block.Time().Int64(), 0)))
f.frozen++
// If it's the last block, save for reporting
if f.frozen == limit-1 {
last = block
}
}
}
// Batch of blocks have been frozen, flush them before wiping from leveldb
if err := f.headers.Flush(); err != nil {
f.logger.Error("Failed to flush frozen headers", "err", err)
time.Sleep(recheck)
continue
}
if err := f.bodies.Flush(); err != nil {
f.logger.Error("Failed to flush frozen bodies", "err", err)
time.Sleep(recheck)
continue
}
if err := f.receipts.Flush(); err != nil {
f.logger.Error("Failed to flush frozen receipts", "err", err)
time.Sleep(recheck)
continue
}
if err := f.diffs.Flush(); err != nil {
f.logger.Error("Failed to flush frozen diffs", "err", err)
time.Sleep(recheck)
continue
}
// Wipe out all data from the active database
for number := first; number < f.frozen; number++ {
if number == 0 {
// Skip deleting the genesis for the PoC
continue
}
rawdb.DeleteBlock(db, rawdb.ReadCanonicalHash(db, number), number)
}
// Log something friendly for the user
context := []interface{}{
"count", f.frozen - first, "elapsed", common.PrettyDuration(time.Since(start)), "number", f.frozen - 1,
}
if last != nil {
context = append(context, []interface{}{"hash", last.Hash(), "age", common.PrettyAge(time.Unix(last.Time().Int64(), 0))}...)
}
log.Info("Deep froze chain segment", context...)
// Avoid database thrashing with tiny writes
if f.frozen-first < 30000 {
time.Sleep(recheck)
}
}
}

View file

@ -1,86 +0,0 @@
// Copyright 2018 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package freezer
import (
"os"
"reflect"
"unsafe"
"github.com/edsrzf/mmap-go"
)
// openWithSize opens a file and ensures it is at least the provided bytes in
// size, growing it if necessary.
func openWithSize(path string, size uint64) (*os.File, error) {
// Open the file for writing, potentially creating it
file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
return nil, err
}
// Ensure the file's size is at least as much as requested
info, err := file.Stat()
if err != nil {
file.Close()
return nil, err
}
if info.Size() < int64(size) {
if err := file.Truncate(int64(size)); err != nil {
file.Close()
return nil, err
}
}
// File is correctly open and of the correct size
return file, err
}
// mmapBytes tries to memory map a file, creating it if it's non existent.
func mmapBytes(path string, size uint64) (*os.File, mmap.MMap, []byte, error) {
// Open the file to memory map and ensure it's large enough
file, err := openWithSize(path, size)
if err != nil {
return nil, nil, nil, err
}
// Memory map the file, cast to a byte slice and return
mem, err := mmap.Map(file, mmap.RDWR, 0)
if err != nil {
file.Close()
return nil, nil, nil, err
}
header := *(*reflect.SliceHeader)(unsafe.Pointer(&mem))
return file, mem, *(*[]byte)(unsafe.Pointer(&header)), nil
}
// mmapUints tries to memory map a file, creating it if it's non existent.
func mmapUints(path string, size uint64) (*os.File, mmap.MMap, []uint64, error) {
// Open the file to memory map and ensure it's large enough
file, err := openWithSize(path, size)
if err != nil {
return nil, nil, nil, err
}
// Memory map the file, cast to an uint64 slice and return
mem, err := mmap.Map(file, mmap.RDWR, 0)
if err != nil {
file.Close()
return nil, nil, nil, err
}
header := *(*reflect.SliceHeader)(unsafe.Pointer(&mem))
header.Len /= 8
header.Cap /= 8
return file, mem, *(*[]uint64)(unsafe.Pointer(&header)), nil
}

View file

@ -1,290 +0,0 @@
// Copyright 2018 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package freezer
import (
"errors"
"os"
"path/filepath"
"sync"
"github.com/edsrzf/mmap-go"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/golang/snappy"
)
const (
growthIndex uint64 = 1024 * 1024 // Growth rate of the index file when remapping
growthData uint64 = 128 * 1024 * 1024 // Growth rate of the data file when remapping
)
var (
// errAlreadyExists is returned if the user attempts to append an item to the
// freezer table that already exists (i.e. it's offset is lower or equal to
// the head of the immutable file).
errAlreadyExists = errors.New("item already exists")
// errGappedWrite is returned if the user attempts to append an item to the
// freezer table that would produce a data gap (i.e. it's offset is larger than
// the head of the immutable file).
errGappedWrite = errors.New("item produces data gap")
// errTableInaccessible is returned if a previously well functioning freezer
// table becomes non-accessible after a memory remap (resize).
errTableInaccessible = errors.New("table not accessible")
// errOutOfBounds is returned if the item requested is not contained within the
// freezer table.
errOutOfBounds = errors.New("out of bounds")
)
// table represents a single chained data table within the freezer (e.g. blocks).
// It consists of a data file (snappy encoded arbitrary data blobs) and an index
// file (uncompressed 64 bit indices into the data file). In addition a counter
// (binary) file is also created which simply contains the number of items.
type table struct {
path string // Database folder to store the files into
name string // Table name to multiplex multiple tables into the same folder
fileData *os.File // File descriptor for the data region
fileIndex *os.File // File descriptor for the offset region
fileCounter *os.File // File descriptor for the counter region
mmapData mmap.MMap // Memory mapping for the data region
mmapIndex mmap.MMap // Memory mapping for the offset region
mmapCounter mmap.MMap // Memory mapping for the counter region
rawData []byte // Direct memory region for the data file
rawIndex []uint64 // Direct memory region for the offset file
rawCounter []uint64 // Direct memory region for the counter (single item)
readMeter metrics.Meter // Meter for measuring the effective amount of data read
writeMeter metrics.Meter // Meter for measuring the effective amount of data written
logger log.Logger // Logger with database path and table name ambedded
lock sync.RWMutex // Lock protecting the reads from remaps
}
// newTable attempts to new freezer table by memory mapping the composing files.
// If no file exists, it will create new ones.
func newTable(path string, name string, readMeter metrics.Meter, writeMeter metrics.Meter) (*table, error) {
if err := os.MkdirAll(path, 0755); err != nil {
return nil, err
}
tab := &table{
path: path,
name: name,
readMeter: readMeter,
writeMeter: writeMeter,
logger: log.New("path", path, "table", name),
}
if err := tab.ensure(); err != nil {
return nil, err
}
return tab, nil
}
// ensure checks all the memory region limits and ensures that they conform to
// the required data counts. If anything is off, this method will recreate and
// remap accordingly.
func (t *table) ensure() error {
// Figure out if we need to remap or not
// If the regions are already open and large enough, leave as is
if t.rawCounter != nil {
// Ensure the data file is large enough, unmap it otherwise
wantData := (t.rawIndex[t.rawCounter[0]]/growthData + 1) * growthData
if uint64(len(t.rawData)) < wantData {
if err := t.mmapData.Unmap(); err != nil {
t.logger.Error("Failed to unmap freezer datastore", "err", err)
}
if err := t.fileData.Close(); err != nil {
t.logger.Error("Failed to close freezer datastore", "err", err)
}
t.fileData, t.mmapData, t.rawData = nil, nil, nil
}
// Ensure the index file is large enough, unmap it otherwise
wantIndex := (((t.rawCounter[0]+1)*8)/growthIndex + 1) * growthIndex
if uint64(len(t.rawIndex)) < wantIndex {
if err := t.mmapIndex.Unmap(); err != nil {
t.logger.Error("Failed to unmap freezer index", "err", err)
}
if err := t.fileIndex.Close(); err != nil {
t.logger.Error("Failed to close freezer index", "err", err)
}
t.fileIndex, t.mmapIndex, t.rawIndex = nil, nil, nil
}
}
// Memory map the counter and retrieve the size of the offset file
var err error
if t.rawCounter == nil {
if t.fileCounter, t.mmapCounter, t.rawCounter, err = mmapUints(filepath.Join(t.path, t.name+".len"), 8); err != nil {
return err
}
}
// Memory map the index file and retrieve the size of the data file
if t.rawIndex == nil {
size := (((t.rawCounter[0]+1)*8)/growthIndex + 1) * growthIndex
if t.fileIndex, t.mmapIndex, t.rawIndex, err = mmapUints(filepath.Join(t.path, t.name+".idx"), size); err != nil {
if err := t.mmapCounter.Unmap(); err != nil {
t.logger.Error("Failed to unmap freezer counter", "err", err)
}
if err := t.fileCounter.Close(); err != nil {
t.logger.Error("Failed to close freezer counter", "err", err)
}
t.fileCounter, t.mmapCounter, t.rawCounter = nil, nil, nil
return err
}
}
// Memory map the data file and return the final freezer table
if t.rawData == nil {
size := growthData
if t.rawCounter[0] > 0 {
size = (t.rawIndex[t.rawCounter[0]]/growthData + 1) * growthData
}
if t.fileData, t.mmapData, t.rawData, err = mmapBytes(filepath.Join(t.path, t.name+".dat"), size); err != nil {
if err := t.mmapIndex.Unmap(); err != nil {
t.logger.Error("Failed to unmap freezer index", "err", err)
}
if err := t.fileIndex.Close(); err != nil {
t.logger.Error("Failed to close freezer index", "err", err)
}
t.fileIndex, t.mmapIndex, t.rawIndex = nil, nil, nil
if err := t.mmapCounter.Unmap(); err != nil {
t.logger.Error("Failed to unmap freezer counter", "err", err)
}
if err := t.fileCounter.Close(); err != nil {
t.logger.Error("Failed to close freezer counter", "err", err)
}
t.fileCounter, t.mmapCounter, t.rawCounter = nil, nil, nil
return err
}
}
return nil
}
// Close unmaps all active memory mapped regions.
func (t *table) Close() error {
t.lock.Lock()
defer t.lock.Unlock()
if t.mmapData != nil {
if err := t.mmapData.Unmap(); err != nil {
t.logger.Error("Failed to unmap freezer datastore", "err", err)
}
if err := t.fileData.Close(); err != nil {
t.logger.Error("Failed to close freezer datastore", "err", err)
}
t.fileData, t.mmapData, t.rawData = nil, nil, nil
}
if t.mmapIndex != nil {
if err := t.mmapIndex.Unmap(); err != nil {
t.logger.Error("Failed to unmap freezer index", "err", err)
}
if err := t.fileIndex.Close(); err != nil {
t.logger.Error("Failed to close freezer index", "err", err)
}
t.fileIndex, t.mmapIndex, t.rawIndex = nil, nil, nil
}
if t.mmapCounter != nil {
if err := t.mmapCounter.Unmap(); err != nil {
t.logger.Error("Failed to unmap freezer counter", "err", err)
}
if err := t.fileCounter.Close(); err != nil {
t.logger.Error("Failed to close freezer counter", "err", err)
}
t.fileCounter, t.mmapCounter, t.rawCounter = nil, nil, nil
}
return nil
}
// Append injects a binary blob at the end of the freezer table. The item index
// is a precautionary parameter to ensure data correctness, but the table will
// reject already existing data.
//
// Note, this method will *not* flush any data to disk (unless the files need to
// be resized). Be sure to explicitly flush before irreversibly deleting data
// from the fast chain database.
func (t *table) Append(item uint64, blob []byte) error {
t.lock.Lock()
defer t.lock.Unlock()
// Ensure the table is still accessible
if t.rawCounter == nil {
if err := t.ensure(); err != nil {
t.logger.Error("Failed to re-access table", "err", err)
return errTableInaccessible
}
}
// Ensure only the next item can be written, nothing else
items := t.rawCounter[0]
if items > item {
return errAlreadyExists
}
if items < item {
return errGappedWrite
}
// Encode the blob and write it into the data file
blob = snappy.Encode(nil, blob)
t.rawIndex[items+1] = t.rawIndex[items] + uint64(len(blob))
copy(t.rawData[t.rawIndex[items]:], blob)
t.rawCounter[0]++
t.writeMeter.Mark(int64(len(blob)))
// Ensure we have enough space for future appends
return t.ensure()
}
// Retrieve looks up the data offset of an item with the given index and retrieves
// the raw binary blob from the data file.
func (t *table) Retrieve(item uint64) ([]byte, error) {
t.lock.RLock()
defer t.lock.RUnlock()
// Ensure the table and the item is accessible
if t.rawCounter == nil {
return nil, errTableInaccessible
}
if t.rawCounter[0] <= item {
return nil, errOutOfBounds
}
// Item reachable, retrive and return to the user
blob := t.rawData[t.rawIndex[item]:t.rawIndex[item+1]]
t.writeMeter.Mark(int64(len(blob)))
return snappy.Decode(nil, blob)
}
// Flush pushes any pending data from memory out to disk. This is an expensive
// operation, so use it with care.
func (t *table) Flush() error {
if err := t.mmapData.Flush(); err != nil {
return err
}
if err := t.mmapIndex.Flush(); err != nil {
return err
}
if err := t.mmapCounter.Flush(); err != nil {
return err
}
return nil
}

View file

@ -27,8 +27,8 @@ import (
"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/core/vm"
"github.com/ethereum/go-ethereum/database"
"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/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
@ -41,7 +41,7 @@ type Backend interface {
Downloader() *downloader.Downloader Downloader() *downloader.Downloader
ProtocolVersion() int ProtocolVersion() int
SuggestPrice(ctx context.Context) (*big.Int, error) SuggestPrice(ctx context.Context) (*big.Int, error)
ChainDb() ethdb.Database ChainDb() database.Database
EventMux() *event.TypeMux EventMux() *event.TypeMux
AccountManager() *accounts.Manager AccountManager() *accounts.Manager

View file

@ -16,7 +16,7 @@
// +build !js // +build !js
package ethdb package keyvalue
import ( import (
"fmt" "fmt"
@ -26,23 +26,38 @@ import (
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"
"github.com/syndtr/goleveldb/leveldb" "github.com/syndtr/goleveldb/leveldb"
"github.com/syndtr/goleveldb/leveldb/errors" "github.com/syndtr/goleveldb/leveldb/errors"
"github.com/syndtr/goleveldb/leveldb/filter" "github.com/syndtr/goleveldb/leveldb/filter"
"github.com/syndtr/goleveldb/leveldb/iterator"
"github.com/syndtr/goleveldb/leveldb/opt" "github.com/syndtr/goleveldb/leveldb/opt"
"github.com/syndtr/goleveldb/leveldb/util" "github.com/syndtr/goleveldb/leveldb/util"
) )
const ( const (
writePauseWarningThrottler = 1 * time.Minute // leveldbDegradationWarnInterval specifies how often warning should be printed
// if the leveldb database cannot keep up with requested writes.
leveldbDegradationWarnInterval = time.Minute
// leveldbMinCache is the minimum amount of memory in megabytes to allocate to
// leveldb read and write caching, split half and half.
leveldbMinCache = 16
// leveldbMinHandles is the minimum number of files handles to allocate to the
// open database files.
leveldbMinHandles = 16
// metricsGatheringInterval specifies the interval to retrieve leveldb database
// compaction, io and pause stats to report to the user.
metricsGatheringInterval = 3 * time.Second
) )
var OpenFileLimit = 64 // LeveldbDatabase is a persistent key-value store. Apart from basic data storage
// functionality it also supports batch writes and iterating over the keyspace in
type LDBDatabase struct { // binary-alphabetical order.
type LeveldbDatabase struct {
fn string // filename for reporting fn string // filename for reporting
db *leveldb.DB // LevelDB instance db *leveldb.DB // LevelDB instance
@ -60,17 +75,16 @@ type LDBDatabase struct {
log log.Logger // Contextual logger tracking the database path log log.Logger // Contextual logger tracking the database path
} }
// NewLDBDatabase returns a LevelDB wrapped object. // NewLeveldbDatabase returns a wrapped LevelDB object.
func NewLDBDatabase(file string, cache int, handles int) (*LDBDatabase, error) { func NewLeveldbDatabase(file string, cache int, handles int, namespace string) (database.KeyValueStore, error) {
logger := log.New("database", file)
// Ensure we have some minimal caching and file guarantees // Ensure we have some minimal caching and file guarantees
if cache < 16 { if cache < leveldbMinCache {
cache = 16 cache = leveldbMinCache
} }
if handles < 16 { if handles < leveldbMinHandles {
handles = 16 handles = leveldbMinHandles
} }
logger := log.New("database", file)
logger.Info("Allocated cache and file handles", "cache", common.StorageSize(cache*1024*1024), "handles", handles) logger.Info("Allocated cache and file handles", "cache", common.StorageSize(cache*1024*1024), "handles", handles)
// Open the db and recover any potential corruptions // Open the db and recover any potential corruptions
@ -83,56 +97,32 @@ func NewLDBDatabase(file string, cache int, handles int) (*LDBDatabase, error) {
if _, corrupted := err.(*errors.ErrCorrupted); corrupted { if _, corrupted := err.(*errors.ErrCorrupted); corrupted {
db, err = leveldb.RecoverFile(file, nil) db, err = leveldb.RecoverFile(file, nil)
} }
// (Re)check for errors and abort if opening of the db failed
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &LDBDatabase{ // Assemble the wrapper with all the registered metrics
ldb := &LeveldbDatabase{
fn: file, fn: file,
db: db, db: db,
log: logger, log: logger,
}, nil quitChan: make(chan chan error),
}
// Path returns the path to the database directory.
func (db *LDBDatabase) Path() string {
return db.fn
}
// Put puts the given key / value to the queue
func (db *LDBDatabase) Put(key []byte, value []byte) error {
return db.db.Put(key, value, nil)
}
func (db *LDBDatabase) Has(key []byte) (bool, error) {
return db.db.Has(key, nil)
}
// Get returns the given key if it's present.
func (db *LDBDatabase) Get(key []byte) ([]byte, error) {
dat, err := db.db.Get(key, nil)
if err != nil {
return nil, err
} }
return dat, nil ldb.compTimeMeter = metrics.NewRegisteredMeter(namespace+"compact/time", nil)
ldb.compReadMeter = metrics.NewRegisteredMeter(namespace+"compact/input", nil)
ldb.compWriteMeter = metrics.NewRegisteredMeter(namespace+"compact/output", nil)
ldb.diskReadMeter = metrics.NewRegisteredMeter(namespace+"disk/read", nil)
ldb.diskWriteMeter = metrics.NewRegisteredMeter(namespace+"disk/write", nil)
ldb.writeDelayMeter = metrics.NewRegisteredMeter(namespace+"compact/writedelay/duration", nil)
ldb.writeDelayNMeter = metrics.NewRegisteredMeter(namespace+"compact/writedelay/counter", nil)
// Start up the metrics gathering and return
go ldb.meter(metricsGatheringInterval)
return ldb, nil
} }
// Delete deletes the key from the queue and database // Close stops th emetrics collection, flushes any pending data to disk and closes
func (db *LDBDatabase) Delete(key []byte) error { // all io access to the underlying key-value store.
return db.db.Delete(key, nil) func (db *LeveldbDatabase) Close() error {
}
func (db *LDBDatabase) NewIterator() iterator.Iterator {
return db.db.NewIterator(nil, nil)
}
// NewIteratorWithPrefix returns a iterator to iterate over subset of database content with a particular prefix.
func (db *LDBDatabase) NewIteratorWithPrefix(prefix []byte) iterator.Iterator {
return db.db.NewIterator(util.BytesPrefix(prefix), nil)
}
func (db *LDBDatabase) Close() {
// Stop the metrics collection to avoid internal database races
db.quitLock.Lock() db.quitLock.Lock()
defer db.quitLock.Unlock() defer db.quitLock.Unlock()
@ -144,41 +134,68 @@ func (db *LDBDatabase) Close() {
} }
db.quitChan = nil db.quitChan = nil
} }
err := db.db.Close() return db.db.Close()
if err == nil { }
db.log.Info("Database closed")
} else { // Has retrieves if a key is present in the key-value store.
db.log.Error("Failed to close database", "err", err) func (db *LeveldbDatabase) Has(key []byte) (bool, error) {
return db.db.Has(key, nil)
}
// Get retrieves the given key if it's present in the key-value store.
func (db *LeveldbDatabase) Get(key []byte) ([]byte, error) {
dat, err := db.db.Get(key, nil)
if err != nil {
return nil, err
}
return dat, nil
}
// Put inserts the given value into the key-value store.
func (db *LeveldbDatabase) Put(key []byte, value []byte) error {
return db.db.Put(key, value, nil)
}
// Delete removes the key from the key-value store.
func (db *LeveldbDatabase) Delete(key []byte) error {
return db.db.Delete(key, nil)
}
// NewBatch creates a write-only key-value store that buffers changes to its host
// database until a final write is called.
func (db *LeveldbDatabase) NewBatch() database.Batch {
return &leveldbBatch{
db: db.db,
b: new(leveldb.Batch),
} }
} }
func (db *LDBDatabase) LDB() *leveldb.DB { // NewIterator creates a binary-alphabetical iterator over the entire keyspace
return db.db // contained within the leveldb database.
func (db *LeveldbDatabase) NewIterator() database.Iterator {
return db.NewIteratorWithPrefix(nil)
} }
// Meter configures the database metrics collectors and // NewIteratorWithPrefix creates a binary-alphabetical iterator over a subset
func (db *LDBDatabase) Meter(prefix string) { // of database content with a particular key prefix.
// Initialize all the metrics collector at the requested prefix func (db *LeveldbDatabase) NewIteratorWithPrefix(prefix []byte) database.Iterator {
db.compTimeMeter = metrics.NewRegisteredMeter(prefix+"compact/time", nil) return db.db.NewIterator(util.BytesPrefix(prefix), nil)
db.compReadMeter = metrics.NewRegisteredMeter(prefix+"compact/input", nil) }
db.compWriteMeter = metrics.NewRegisteredMeter(prefix+"compact/output", nil)
db.diskReadMeter = metrics.NewRegisteredMeter(prefix+"disk/read", nil)
db.diskWriteMeter = metrics.NewRegisteredMeter(prefix+"disk/write", nil)
db.writeDelayMeter = metrics.NewRegisteredMeter(prefix+"compact/writedelay/duration", nil)
db.writeDelayNMeter = metrics.NewRegisteredMeter(prefix+"compact/writedelay/counter", nil)
// Create a quit channel for the periodic collector and run it // Stat returns a particular internal stat of the database.
db.quitLock.Lock() func (db *LeveldbDatabase) Stat(property string) (string, error) {
db.quitChan = make(chan chan error) return db.db.GetProperty(property)
db.quitLock.Unlock() }
go db.meter(3 * time.Second) // Path returns the path to the database directory.
func (db *LeveldbDatabase) Path() string {
return db.fn
} }
// meter periodically retrieves internal leveldb counters and reports them to // meter periodically retrieves internal leveldb counters and reports them to
// the metrics subsystem. // the metrics subsystem.
// //
// This is how a stats table look like (currently): // This is how a stats leveldbTable look like (currently):
// Compactions // Compactions
// Level | Tables | Size(MB) | Time(sec) | Read(MB) | Write(MB) // Level | Tables | Size(MB) | Time(sec) | Read(MB) | Write(MB)
// -------+------------+---------------+---------------+---------------+--------------- // -------+------------+---------------+---------------+---------------+---------------
@ -192,7 +209,7 @@ func (db *LDBDatabase) Meter(prefix string) {
// //
// This is how the iostats look like (currently): // This is how the iostats look like (currently):
// Read(MB):3895.04860 Write(MB):3654.64712 // Read(MB):3895.04860 Write(MB):3654.64712
func (db *LDBDatabase) meter(refresh time.Duration) { func (db *LeveldbDatabase) meter(refresh time.Duration) {
// Create the counters to store current and previous compaction values // Create the counters to store current and previous compaction values
compactions := make([][]float64, 2) compactions := make([][]float64, 2)
for i := 0; i < 2; i++ { for i := 0; i < 2; i++ {
@ -221,19 +238,19 @@ func (db *LDBDatabase) meter(refresh time.Duration) {
merr = err merr = err
continue continue
} }
// Find the compaction table, skip the header // Find the compaction leveldbTable, skip the header
lines := strings.Split(stats, "\n") lines := strings.Split(stats, "\n")
for len(lines) > 0 && strings.TrimSpace(lines[0]) != "Compactions" { for len(lines) > 0 && strings.TrimSpace(lines[0]) != "Compactions" {
lines = lines[1:] lines = lines[1:]
} }
if len(lines) <= 3 { if len(lines) <= 3 {
db.log.Error("Compaction table not found") db.log.Error("Compaction leveldbTable not found")
merr = errors.New("compaction table not found") merr = errors.New("compaction leveldbTable not found")
continue continue
} }
lines = lines[3:] lines = lines[3:]
// Iterate over all the table rows, and accumulate the entries // Iterate over all the leveldbTable rows, and accumulate the entries
for j := 0; j < len(compactions[i%2]); j++ { for j := 0; j < len(compactions[i%2]); j++ {
compactions[i%2][j] = 0 compactions[i%2][j] = 0
} }
@ -296,7 +313,7 @@ func (db *LDBDatabase) meter(refresh time.Duration) {
// If a warning that db is performing compaction has been displayed, any subsequent // If a warning that db is performing compaction has been displayed, any subsequent
// warnings will be withheld for one minute not to overwhelm the user. // warnings will be withheld for one minute not to overwhelm the user.
if paused && delayN-delaystats[0] == 0 && duration.Nanoseconds()-delaystats[1] == 0 && if paused && delayN-delaystats[0] == 0 && duration.Nanoseconds()-delaystats[1] == 0 &&
time.Now().After(lastWritePaused.Add(writePauseWarningThrottler)) { time.Now().After(lastWritePaused.Add(leveldbDegradationWarnInterval)) {
db.log.Warn("Database compacting, degraded performance") db.log.Warn("Database compacting, degraded performance")
lastWritePaused = time.Now() lastWritePaused = time.Now()
} }
@ -349,37 +366,40 @@ func (db *LDBDatabase) meter(refresh time.Duration) {
errc <- merr errc <- merr
} }
func (db *LDBDatabase) NewBatch() Batch { // leveldbBatch is a write-only leveldb batch that commits changes to its host
return &ldbBatch{db: db.db, b: new(leveldb.Batch)} // database when Write is called. A batch cannot be used concurrently.
} type leveldbBatch struct {
type ldbBatch struct {
db *leveldb.DB db *leveldb.DB
b *leveldb.Batch b *leveldb.Batch
size int size int
} }
func (b *ldbBatch) Put(key, value []byte) error { // Put inserts the given value into the batch for later committing.
func (b *leveldbBatch) Put(key, value []byte) error {
b.b.Put(key, value) b.b.Put(key, value)
b.size += len(value) b.size += len(value)
return nil return nil
} }
func (b *ldbBatch) Delete(key []byte) error { // Delete inserts the a key removal into the batch for later committing.
func (b *leveldbBatch) Delete(key []byte) error {
b.b.Delete(key) b.b.Delete(key)
b.size += 1 b.size += 1
return nil return nil
} }
func (b *ldbBatch) Write() error { // ValueSize retrieves the amount of data queued up for writing.
return b.db.Write(b.b, nil) func (b *leveldbBatch) ValueSize() int {
}
func (b *ldbBatch) ValueSize() int {
return b.size return b.size
} }
func (b *ldbBatch) Reset() { // Write flushes any accumulated data to disk.
func (b *leveldbBatch) Write() error {
return b.db.Write(b.b, nil)
}
// Reset resets the batch for reuse.
func (b *leveldbBatch) Reset() {
b.b.Reset() b.b.Reset()
b.size = 0 b.size = 0
} }

View file

@ -0,0 +1,295 @@
// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package keyvalue
import (
"errors"
"sort"
"strings"
"sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/database"
)
var (
// errMemorydbClosed is returned if a memory database was already closed at the
// invocation of a data access operation.
errMemorydbClosed = errors.New("database closed")
// errMemorydbNotFound is returned if a key is requested that is not found in
// the provided memory database.
errMemorydbNotFound = errors.New("not found")
)
// MemoryDatabase is an ephemeral key-value store. Apart from basic data storage
// functionality it also supports batch writes and iterating over the keyspace in
// binary-alphabetical order.
type MemoryDatabase struct {
db map[string][]byte
lock sync.RWMutex
}
// NewMemoryDatabase returns a wrapped map with all the required database interface
// methods implemented.
func NewMemoryDatabase() *MemoryDatabase {
return &MemoryDatabase{
db: make(map[string][]byte),
}
}
// NewMemoryDatabaseWithCap returns a wrapped map pre-allocated to the provided
// capcity with all the required database interface methods implemented.
func NewMemoryDatabaseWithCap(size int) database.KeyValueStore {
return &MemoryDatabase{
db: make(map[string][]byte, size),
}
}
// Close deallocates the internal map and ensures any consecutive data access op
// failes with an error.
func (db *MemoryDatabase) Close() error {
db.lock.Lock()
defer db.lock.Unlock()
db.db = nil
return nil
}
// Has retrieves if a key is present in the key-value store.
func (db *MemoryDatabase) Has(key []byte) (bool, error) {
db.lock.RLock()
defer db.lock.RUnlock()
if db.db == nil {
return false, errMemorydbClosed
}
_, ok := db.db[string(key)]
return ok, nil
}
// Get retrieves the given key if it's present in the key-value store.
func (db *MemoryDatabase) Get(key []byte) ([]byte, error) {
db.lock.RLock()
defer db.lock.RUnlock()
if db.db == nil {
return nil, errMemorydbClosed
}
if entry, ok := db.db[string(key)]; ok {
return common.CopyBytes(entry), nil
}
return nil, errMemorydbNotFound
}
// Put inserts the given value into the key-value store.
func (db *MemoryDatabase) Put(key []byte, value []byte) error {
db.lock.Lock()
defer db.lock.Unlock()
if db.db == nil {
return errMemorydbClosed
}
db.db[string(key)] = common.CopyBytes(value)
return nil
}
// Delete removes the key from the key-value store.
func (db *MemoryDatabase) Delete(key []byte) error {
db.lock.Lock()
defer db.lock.Unlock()
if db.db == nil {
return errMemorydbClosed
}
delete(db.db, string(key))
return nil
}
// NewBatch creates a write-only key-value store that buffers changes to its host
// database until a final write is called.
func (db *MemoryDatabase) NewBatch() database.Batch {
return &memoryBatch{
db: db,
}
}
// NewIterator creates a binary-alphabetical iterator over the entire keyspace
// contained within the memory database.
func (db *MemoryDatabase) NewIterator() database.Iterator {
return db.NewIteratorWithPrefix(nil)
}
// NewIteratorWithPrefix creates a binary-alphabetical iterator over a subset
// of database content with a particular key prefix.
func (db *MemoryDatabase) NewIteratorWithPrefix(prefix []byte) database.Iterator {
db.lock.RLock()
defer db.lock.RUnlock()
var (
pr = string(prefix)
keys = []string{"FAKE KEY TO SIMPLIFY NEXT"}
values = [][]byte{[]byte("FAKE VAL TO SIMPLIFY NEXT")}
)
// Collect the keys from the memory database corresponding to the given prefix
for key, _ := range db.db {
if strings.HasPrefix(key, pr) {
keys = append(keys, key)
}
}
// Sort the items and retrieve the associated values
sort.Strings(keys[1:])
for _, key := range keys[1:] {
values = append(values, db.db[key])
}
return &memoryIterator{
keys: keys,
values: values,
}
}
// Stat returns a particular internal stat of the database.
func (db *MemoryDatabase) Stat(property string) (string, error) {
return "", errors.New("unknown property")
}
// Len returns the number of entries currently present in the memory database.
//
// Note, this method is only used for testing (i.e. not public in general) and
// does not have explicit checks for closed-ness to allow simpler testing code.
func (db *MemoryDatabase) Len() int {
db.lock.RLock()
defer db.lock.RUnlock()
return len(db.db)
}
/*
// Keys retrieves a copy of all the keys present in the database.
//
// Note, this method is only used for testing (i.e. not public in general) and
// does not have explicit checks for closed-ness to allow simpler testing code.
func (db *MemoryDatabase) Keys() [][]byte {
db.lock.RLock()
defer db.lock.RUnlock()
keys := [][]byte{}
for key := range db.db {
keys = append(keys, []byte(key))
}
return keys
}*/
// keyvalue is a key-value tuple tagged with a deletion field to allow creating
// memory-database write batches.
type keyvalue struct {
key []byte
value []byte
delete bool
}
// memoryBatch is a write-only memory batch that commits changes to its host
// database when Write is called. A batch cannot be used concurrently.
type memoryBatch struct {
db *MemoryDatabase
writes []keyvalue
size int
}
// Put inserts the given value into the batch for later committing.
func (b *memoryBatch) Put(key, value []byte) error {
b.writes = append(b.writes, keyvalue{common.CopyBytes(key), common.CopyBytes(value), false})
b.size += len(value)
return nil
}
// Delete inserts the a key removal into the batch for later committing.
func (b *memoryBatch) Delete(key []byte) error {
b.writes = append(b.writes, keyvalue{common.CopyBytes(key), nil, true})
b.size += 1
return nil
}
// ValueSize retrieves the amount of data queued up for writing.
func (b *memoryBatch) ValueSize() int {
return b.size
}
// Write flushes any accumulated data to the memory database.
func (b *memoryBatch) Write() error {
b.db.lock.Lock()
defer b.db.lock.Unlock()
for _, keyvalue := range b.writes {
if keyvalue.delete {
delete(b.db.db, string(keyvalue.key))
continue
}
b.db.db[string(keyvalue.key)] = keyvalue.value
}
return nil
}
// Reset resets the batch for reuse.
func (b *memoryBatch) Reset() {
b.writes = b.writes[:0]
b.size = 0
}
// memoryIterator can walk over the (potentially partial) keyspace of a memory
// key value store. Internally it is a deep copy of the entire iterated state,
// sorted by keys.
type memoryIterator struct {
keys []string
values [][]byte
}
// Next moves the iterator to the next key/value pair. It returns whether the
// iterator is exhausted.
func (it *memoryIterator) Next() bool {
if len(it.keys) > 0 {
it.keys = it.keys[1:]
it.values = it.values[1:]
}
return len(it.keys) > 0
}
// Key returns the key of the current key/value pair, or nil if done. The caller
// should not modify the contents of the returned slice, and its contents may
// change on the next call to Next.
func (it *memoryIterator) Key() []byte {
if len(it.keys) > 0 {
return []byte(it.keys[0])
}
return nil
}
// Value returns the value of the current key/value pair, or nil if done. The
// caller should not modify the contents of the returned slice, and its contents
// may change on the next call to Next.
func (it *memoryIterator) Value() []byte {
if len(it.values) > 0 {
return it.values[0]
}
return nil
}
// Release releases associated resources. Release should always succeed and can
// be called multiple times without causing error.
func (it *memoryIterator) Release() {
it.keys, it.values = nil, nil
}

View file

@ -29,9 +29,9 @@ import (
"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/core/vm"
"github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/gasprice" "github.com/ethereum/go-ethereum/eth/gasprice"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/light"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
@ -175,7 +175,7 @@ func (b *LesApiBackend) SuggestPrice(ctx context.Context) (*big.Int, error) {
return b.gpo.SuggestPrice(ctx) return b.gpo.SuggestPrice(ctx)
} }
func (b *LesApiBackend) ChainDb() ethdb.Database { func (b *LesApiBackend) ChainDb() database.Database {
return b.eth.chainDb return b.eth.chainDb
} }

View file

@ -78,7 +78,7 @@ type LightEthereum struct {
} }
func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) { func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
chainDb, err := eth.CreateDB(ctx, config, "lightchaindata") chainDb, err := ctx.OpenDatabase("lightchaindata", config.DatabaseCache, config.DatabaseHandles, "eth/db/chaindata/")
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -22,8 +22,8 @@ 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/database"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/light"
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
@ -34,7 +34,7 @@ import (
type lesCommons struct { type lesCommons struct {
config *eth.Config config *eth.Config
iConfig *light.IndexerConfig iConfig *light.IndexerConfig
chainDb ethdb.Database chainDb database.Database
protocolManager *ProtocolManager protocolManager *ProtocolManager
chtIndexer, bloomTrieIndexer *core.ChainIndexer chtIndexer, bloomTrieIndexer *core.ChainIndexer
} }

View file

@ -25,7 +25,7 @@ import (
"github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/common/mclock"
"github.com/ethereum/go-ethereum/common/prque" "github.com/ethereum/go-ethereum/common/prque"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
) )
@ -44,7 +44,7 @@ import (
// value for the client. Currently the LES protocol manager uses IP addresses // value for the client. Currently the LES protocol manager uses IP addresses
// (without port address) to identify clients. // (without port address) to identify clients.
type freeClientPool struct { type freeClientPool struct {
db ethdb.Database db database.Database
lock sync.Mutex lock sync.Mutex
clock mclock.Clock clock mclock.Clock
closed bool closed bool
@ -64,7 +64,7 @@ const (
) )
// newFreeClientPool creates a new free client pool // newFreeClientPool creates a new free client pool
func newFreeClientPool(db ethdb.Database, connectedLimit, totalLimit int, clock mclock.Clock) *freeClientPool { func newFreeClientPool(db database.Database, connectedLimit, totalLimit int, clock mclock.Clock) *freeClientPool {
pool := &freeClientPool{ pool := &freeClientPool{
db: db, db: db,
clock: clock, clock: clock,

View file

@ -25,7 +25,7 @@ import (
"time" "time"
"github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/common/mclock"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/core/rawdb"
) )
func TestFreeClientPoolL10C100(t *testing.T) { func TestFreeClientPoolL10C100(t *testing.T) {
@ -45,7 +45,7 @@ const testFreeClientPoolTicks = 500000
func testFreeClientPool(t *testing.T, connLimit, clientCount int) { func testFreeClientPool(t *testing.T, connLimit, clientCount int) {
var ( var (
clock mclock.Simulated clock mclock.Simulated
db = ethdb.NewMemDatabase() db = rawdb.NewMemoryDatabase()
pool = newFreeClientPool(db, connLimit, 10000, &clock) pool = newFreeClientPool(db, connLimit, 10000, &clock)
connected = make([]bool, clientCount) connected = make([]bool, clientCount)
connTicks = make([]int, clientCount) connTicks = make([]int, clientCount)

View file

@ -33,9 +33,9 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"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/database"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
"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/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/light"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
@ -97,7 +97,7 @@ type ProtocolManager struct {
chainConfig *params.ChainConfig chainConfig *params.ChainConfig
iConfig *light.IndexerConfig iConfig *light.IndexerConfig
blockchain BlockChain blockchain BlockChain
chainDb ethdb.Database chainDb database.Database
odr *LesOdr odr *LesOdr
server *LesServer server *LesServer
serverPool *serverPool serverPool *serverPool
@ -136,7 +136,7 @@ func NewProtocolManager(
peers *peerSet, peers *peerSet,
blockchain BlockChain, blockchain BlockChain,
txpool txPool, txpool txPool,
chainDb ethdb.Database, chainDb database.Database,
odr *LesOdr, odr *LesOdr,
txrelay *LesTxRelay, txrelay *LesTxRelay,
serverPool *serverPool, serverPool *serverPool,
@ -907,7 +907,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
if reject(uint64(reqCnt), MaxHelperTrieProofsFetch) { if reject(uint64(reqCnt), MaxHelperTrieProofsFetch) {
return errResp(ErrRequestRejected, "") return errResp(ErrRequestRejected, "")
} }
trieDb := trie.NewDatabase(ethdb.NewTable(pm.chainDb, light.ChtTablePrefix)) trieDb := trie.NewDatabase(rawdb.NewTable(pm.chainDb, light.ChtTablePrefix))
for _, req := range req.Reqs { for _, req := range req.Reqs {
if header := pm.blockchain.GetHeaderByNumber(req.BlockNum); header != nil { if header := pm.blockchain.GetHeaderByNumber(req.BlockNum); header != nil {
sectionHead := rawdb.ReadCanonicalHash(pm.chainDb, req.ChtNum*pm.iConfig.ChtSize-1) sectionHead := rawdb.ReadCanonicalHash(pm.chainDb, req.ChtNum*pm.iConfig.ChtSize-1)
@ -966,7 +966,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
var prefix string var prefix string
if root, prefix = pm.getHelperTrie(req.Type, req.TrieIdx); root != (common.Hash{}) { if root, prefix = pm.getHelperTrie(req.Type, req.TrieIdx); root != (common.Hash{}) {
auxTrie, _ = trie.New(root, trie.NewDatabase(ethdb.NewTable(pm.chainDb, prefix))) auxTrie, _ = trie.New(root, trie.NewDatabase(rawdb.NewTable(pm.chainDb, prefix)))
} }
} }
if req.AuxReq == auxRoot { if req.AuxReq == auxRoot {

View file

@ -30,7 +30,6 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"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/light" "github.com/ethereum/go-ethereum/light"
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
@ -405,7 +404,7 @@ func testGetCHTProofs(t *testing.T, protocol int) {
switch protocol { switch protocol {
case 1: case 1:
root := light.GetChtRoot(server.db, 0, bc.GetHeaderByNumber(frequency-1).Hash()) root := light.GetChtRoot(server.db, 0, bc.GetHeaderByNumber(frequency-1).Hash())
trie, _ := trie.New(root, trie.NewDatabase(ethdb.NewTable(server.db, light.ChtTablePrefix))) trie, _ := trie.New(root, trie.NewDatabase(rawdb.NewTable(server.db, light.ChtTablePrefix)))
var proof light.NodeList var proof light.NodeList
trie.Prove(key, 0, &proof) trie.Prove(key, 0, &proof)
@ -413,7 +412,7 @@ func testGetCHTProofs(t *testing.T, protocol int) {
case 2: case 2:
root := light.GetChtRoot(server.db, (frequency/config.ChtSize)-1, bc.GetHeaderByNumber(frequency-1).Hash()) root := light.GetChtRoot(server.db, (frequency/config.ChtSize)-1, bc.GetHeaderByNumber(frequency-1).Hash())
trie, _ := trie.New(root, trie.NewDatabase(ethdb.NewTable(server.db, light.ChtTablePrefix))) trie, _ := trie.New(root, trie.NewDatabase(rawdb.NewTable(server.db, light.ChtTablePrefix)))
trie.Prove(key, 0, &proofsV2.Proofs) trie.Prove(key, 0, &proofsV2.Proofs)
} }
// Assemble the requests for the different protocols // Assemble the requests for the different protocols
@ -480,7 +479,7 @@ func TestGetBloombitsProofs(t *testing.T) {
var proofs HelperTrieResps var proofs HelperTrieResps
root := light.GetBloomTrieRoot(server.db, 0, bc.GetHeaderByNumber(config.BloomTrieSize-1).Hash()) root := light.GetBloomTrieRoot(server.db, 0, bc.GetHeaderByNumber(config.BloomTrieSize-1).Hash())
trie, _ := trie.New(root, trie.NewDatabase(ethdb.NewTable(server.db, light.BloomTrieTablePrefix))) trie, _ := trie.New(root, trie.NewDatabase(rawdb.NewTable(server.db, light.BloomTrieTablePrefix)))
trie.Prove(key, 0, &proofs.Proofs) trie.Prove(key, 0, &proofs.Proofs)
// Send the proof request and verify the response // Send the proof request and verify the response
@ -493,7 +492,7 @@ func TestGetBloombitsProofs(t *testing.T) {
} }
func TestTransactionStatusLes2(t *testing.T) { func TestTransactionStatusLes2(t *testing.T) {
db := ethdb.NewMemDatabase() db := rawdb.NewMemoryDatabase()
pm := newTestProtocolManagerMust(t, false, 0, nil, nil, nil, db, nil) pm := newTestProtocolManagerMust(t, false, 0, nil, nil, nil, db, nil)
chain := pm.blockchain.(*core.BlockChain) chain := pm.blockchain.(*core.BlockChain)
config := core.DefaultTxPoolConfig config := core.DefaultTxPoolConfig

View file

@ -29,11 +29,12 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"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/core/vm"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/les/flowcontrol" "github.com/ethereum/go-ethereum/les/flowcontrol"
"github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/light"
@ -125,7 +126,7 @@ func testChainGen(i int, block *core.BlockGen) {
} }
// testIndexers creates a set of indexers with specified params for testing purpose. // testIndexers creates a set of indexers with specified params for testing purpose.
func testIndexers(db ethdb.Database, odr light.OdrBackend, iConfig *light.IndexerConfig) (*core.ChainIndexer, *core.ChainIndexer, *core.ChainIndexer) { func testIndexers(db database.Database, odr light.OdrBackend, iConfig *light.IndexerConfig) (*core.ChainIndexer, *core.ChainIndexer, *core.ChainIndexer) {
chtIndexer := light.NewChtIndexer(db, odr, iConfig.ChtSize, iConfig.ChtConfirms) chtIndexer := light.NewChtIndexer(db, odr, iConfig.ChtSize, iConfig.ChtConfirms)
bloomIndexer := eth.NewBloomIndexer(db, iConfig.BloomSize, iConfig.BloomConfirms) bloomIndexer := eth.NewBloomIndexer(db, iConfig.BloomSize, iConfig.BloomConfirms)
bloomTrieIndexer := light.NewBloomTrieIndexer(db, odr, iConfig.BloomSize, iConfig.BloomTrieSize) bloomTrieIndexer := light.NewBloomTrieIndexer(db, odr, iConfig.BloomSize, iConfig.BloomTrieSize)
@ -146,7 +147,7 @@ func testRCL() RequestCostList {
// newTestProtocolManager creates a new protocol manager for testing purposes, // newTestProtocolManager creates a new protocol manager for testing purposes,
// with the given number of blocks already known, potential notification // with the given number of blocks already known, potential notification
// channels for different events and relative chain indexers array. // channels for different events and relative chain indexers array.
func newTestProtocolManager(lightSync bool, blocks int, generator func(int, *core.BlockGen), odr *LesOdr, peers *peerSet, db ethdb.Database, ulcConfig *eth.ULCConfig) (*ProtocolManager, error) { func newTestProtocolManager(lightSync bool, blocks int, generator func(int, *core.BlockGen), odr *LesOdr, peers *peerSet, db database.Database, ulcConfig *eth.ULCConfig) (*ProtocolManager, error) {
var ( var (
evmux = new(event.TypeMux) evmux = new(event.TypeMux)
engine = ethash.NewFaker() engine = ethash.NewFaker()
@ -200,7 +201,7 @@ func newTestProtocolManager(lightSync bool, blocks int, generator func(int, *cor
// with the given number of blocks already known, potential notification // with the given number of blocks already known, potential notification
// channels for different events and relative chain indexers array. In case of an error, the constructor force- // channels for different events and relative chain indexers array. In case of an error, the constructor force-
// fails the test. // fails the test.
func newTestProtocolManagerMust(t *testing.T, lightSync bool, blocks int, generator func(int, *core.BlockGen), odr *LesOdr, peers *peerSet, db ethdb.Database, ulcConfig *eth.ULCConfig) *ProtocolManager { func newTestProtocolManagerMust(t *testing.T, lightSync bool, blocks int, generator func(int, *core.BlockGen), odr *LesOdr, peers *peerSet, db database.Database, ulcConfig *eth.ULCConfig) *ProtocolManager {
pm, err := newTestProtocolManager(lightSync, blocks, generator, odr, peers, db, ulcConfig) pm, err := newTestProtocolManager(lightSync, blocks, generator, odr, peers, db, ulcConfig)
if err != nil { if err != nil {
t.Fatalf("Failed to create protocol manager: %v", err) t.Fatalf("Failed to create protocol manager: %v", err)
@ -327,7 +328,7 @@ func (p *testPeer) close() {
// TestEntity represents a network entity for testing with necessary auxiliary fields. // TestEntity represents a network entity for testing with necessary auxiliary fields.
type TestEntity struct { type TestEntity struct {
db ethdb.Database db database.Database
rPeer *peer rPeer *peer
tPeer *testPeer tPeer *testPeer
peers *peerSet peers *peerSet
@ -340,7 +341,7 @@ type TestEntity struct {
// newServerEnv creates a server testing environment with a connected test peer for testing purpose. // newServerEnv creates a server testing environment with a connected test peer for testing purpose.
func newServerEnv(t *testing.T, blocks int, protocol int, waitIndexers func(*core.ChainIndexer, *core.ChainIndexer, *core.ChainIndexer)) (*TestEntity, func()) { func newServerEnv(t *testing.T, blocks int, protocol int, waitIndexers func(*core.ChainIndexer, *core.ChainIndexer, *core.ChainIndexer)) (*TestEntity, func()) {
db := ethdb.NewMemDatabase() db := rawdb.NewMemoryDatabase()
cIndexer, bIndexer, btIndexer := testIndexers(db, nil, light.TestServerIndexerConfig) cIndexer, bIndexer, btIndexer := testIndexers(db, nil, light.TestServerIndexerConfig)
pm := newTestProtocolManagerMust(t, false, blocks, testChainGen, nil, nil, db, nil) pm := newTestProtocolManagerMust(t, false, blocks, testChainGen, nil, nil, db, nil)
@ -372,7 +373,7 @@ func newServerEnv(t *testing.T, blocks int, protocol int, waitIndexers func(*cor
// newClientServerEnv creates a client/server arch environment with a connected les server and light client pair // newClientServerEnv creates a client/server arch environment with a connected les server and light client pair
// for testing purpose. // for testing purpose.
func newClientServerEnv(t *testing.T, blocks int, protocol int, waitIndexers func(*core.ChainIndexer, *core.ChainIndexer, *core.ChainIndexer), newPeer bool) (*TestEntity, *TestEntity, func()) { func newClientServerEnv(t *testing.T, blocks int, protocol int, waitIndexers func(*core.ChainIndexer, *core.ChainIndexer, *core.ChainIndexer), newPeer bool) (*TestEntity, *TestEntity, func()) {
db, ldb := ethdb.NewMemDatabase(), ethdb.NewMemDatabase() db, ldb := rawdb.NewMemoryDatabase(), rawdb.NewMemoryDatabase()
peers, lPeers := newPeerSet(), newPeerSet() peers, lPeers := newPeerSet(), newPeerSet()
dist := newRequestDistributor(lPeers, make(chan struct{})) dist := newRequestDistributor(lPeers, make(chan struct{}))

View file

@ -20,21 +20,21 @@ import (
"context" "context"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/light"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
// LesOdr implements light.OdrBackend // LesOdr implements light.OdrBackend
type LesOdr struct { type LesOdr struct {
db ethdb.Database db database.Database
indexerConfig *light.IndexerConfig indexerConfig *light.IndexerConfig
chtIndexer, bloomTrieIndexer, bloomIndexer *core.ChainIndexer chtIndexer, bloomTrieIndexer, bloomIndexer *core.ChainIndexer
retriever *retrieveManager retriever *retrieveManager
stop chan struct{} stop chan struct{}
} }
func NewLesOdr(db ethdb.Database, config *light.IndexerConfig, retriever *retrieveManager) *LesOdr { func NewLesOdr(db database.Database, config *light.IndexerConfig, retriever *retrieveManager) *LesOdr {
return &LesOdr{ return &LesOdr{
db: db, db: db,
indexerConfig: config, indexerConfig: config,
@ -49,7 +49,7 @@ func (odr *LesOdr) Stop() {
} }
// Database returns the backing database // Database returns the backing database
func (odr *LesOdr) Database() ethdb.Database { func (odr *LesOdr) Database() database.Database {
return odr.db return odr.db
} }

View file

@ -27,7 +27,7 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/light"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
@ -51,7 +51,7 @@ type LesOdrRequest interface {
GetCost(*peer) uint64 GetCost(*peer) uint64
CanSend(*peer) bool CanSend(*peer) bool
Request(uint64, *peer) error Request(uint64, *peer) error
Validate(ethdb.Database, *Msg) error Validate(database.Database, *Msg) error
} }
func LesRequest(req light.OdrRequest) LesOdrRequest { func LesRequest(req light.OdrRequest) LesOdrRequest {
@ -96,7 +96,7 @@ func (r *BlockRequest) Request(reqID uint64, peer *peer) error {
// Valid processes an ODR request reply message from the LES network // Valid processes an ODR request reply message from the LES network
// returns true and stores results in memory if the message was a valid reply // returns true and stores results in memory if the message was a valid reply
// to the request (implementation of LesOdrRequest) // to the request (implementation of LesOdrRequest)
func (r *BlockRequest) Validate(db ethdb.Database, msg *Msg) error { func (r *BlockRequest) Validate(db database.Database, msg *Msg) error {
log.Debug("Validating block body", "hash", r.Hash) log.Debug("Validating block body", "hash", r.Hash)
// Ensure we have a correct message with a single block body // Ensure we have a correct message with a single block body
@ -152,7 +152,7 @@ func (r *ReceiptsRequest) Request(reqID uint64, peer *peer) error {
// Valid processes an ODR request reply message from the LES network // Valid processes an ODR request reply message from the LES network
// returns true and stores results in memory if the message was a valid reply // returns true and stores results in memory if the message was a valid reply
// to the request (implementation of LesOdrRequest) // to the request (implementation of LesOdrRequest)
func (r *ReceiptsRequest) Validate(db ethdb.Database, msg *Msg) error { func (r *ReceiptsRequest) Validate(db database.Database, msg *Msg) error {
log.Debug("Validating block receipts", "hash", r.Hash) log.Debug("Validating block receipts", "hash", r.Hash)
// Ensure we have a correct message with a single block receipt // Ensure we have a correct message with a single block receipt
@ -219,7 +219,7 @@ func (r *TrieRequest) Request(reqID uint64, peer *peer) error {
// Valid processes an ODR request reply message from the LES network // Valid processes an ODR request reply message from the LES network
// returns true and stores results in memory if the message was a valid reply // returns true and stores results in memory if the message was a valid reply
// to the request (implementation of LesOdrRequest) // to the request (implementation of LesOdrRequest)
func (r *TrieRequest) Validate(db ethdb.Database, msg *Msg) error { func (r *TrieRequest) Validate(db database.Database, msg *Msg) error {
log.Debug("Validating trie proof", "root", r.Id.Root, "key", r.Key) log.Debug("Validating trie proof", "root", r.Id.Root, "key", r.Key)
switch msg.MsgType { switch msg.MsgType {
@ -288,7 +288,7 @@ func (r *CodeRequest) Request(reqID uint64, peer *peer) error {
// Valid processes an ODR request reply message from the LES network // Valid processes an ODR request reply message from the LES network
// returns true and stores results in memory if the message was a valid reply // returns true and stores results in memory if the message was a valid reply
// to the request (implementation of LesOdrRequest) // to the request (implementation of LesOdrRequest)
func (r *CodeRequest) Validate(db ethdb.Database, msg *Msg) error { func (r *CodeRequest) Validate(db database.Database, msg *Msg) error {
log.Debug("Validating code data", "hash", r.Hash) log.Debug("Validating code data", "hash", r.Hash)
// Ensure we have a correct message with a single code element // Ensure we have a correct message with a single code element
@ -399,7 +399,7 @@ func (r *ChtRequest) Request(reqID uint64, peer *peer) error {
// Valid processes an ODR request reply message from the LES network // Valid processes an ODR request reply message from the LES network
// returns true and stores results in memory if the message was a valid reply // returns true and stores results in memory if the message was a valid reply
// to the request (implementation of LesOdrRequest) // to the request (implementation of LesOdrRequest)
func (r *ChtRequest) Validate(db ethdb.Database, msg *Msg) error { func (r *ChtRequest) Validate(db database.Database, msg *Msg) error {
log.Debug("Validating CHT", "cht", r.ChtNum, "block", r.BlockNum) log.Debug("Validating CHT", "cht", r.ChtNum, "block", r.BlockNum)
switch msg.MsgType { switch msg.MsgType {
@ -523,7 +523,7 @@ func (r *BloomRequest) Request(reqID uint64, peer *peer) error {
// Valid processes an ODR request reply message from the LES network // Valid processes an ODR request reply message from the LES network
// returns true and stores results in memory if the message was a valid reply // returns true and stores results in memory if the message was a valid reply
// to the request (implementation of LesOdrRequest) // to the request (implementation of LesOdrRequest)
func (r *BloomRequest) Validate(db ethdb.Database, msg *Msg) error { func (r *BloomRequest) Validate(db database.Database, msg *Msg) error {
log.Debug("Validating BloomBits", "bloomTrie", r.BloomTrieNum, "bitIdx", r.BitIdx, "sections", r.SectionIndexList) log.Debug("Validating BloomBits", "bloomTrie", r.BloomTrieNum, "bitIdx", r.BitIdx, "sections", r.SectionIndexList)
// Ensure we have a correct message with a single proof element // Ensure we have a correct message with a single proof element
@ -560,7 +560,7 @@ func (r *BloomRequest) Validate(db ethdb.Database, msg *Msg) error {
// readTraceDB stores the keys of database reads. We use this to check that received node // readTraceDB stores the keys of database reads. We use this to check that received node
// sets contain only the trie nodes necessary to make proofs pass. // sets contain only the trie nodes necessary to make proofs pass.
type readTraceDB struct { type readTraceDB struct {
db trie.DatabaseReader db database.Reader
reads map[string]struct{} reads map[string]struct{}
} }

View file

@ -30,19 +30,19 @@ import (
"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/core/vm"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/light"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
) )
type odrTestFn func(ctx context.Context, db ethdb.Database, config *params.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte type odrTestFn func(ctx context.Context, db database.Database, config *params.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte
func TestOdrGetBlockLes1(t *testing.T) { testOdr(t, 1, 1, odrGetBlock) } func TestOdrGetBlockLes1(t *testing.T) { testOdr(t, 1, 1, odrGetBlock) }
func TestOdrGetBlockLes2(t *testing.T) { testOdr(t, 2, 1, odrGetBlock) } func TestOdrGetBlockLes2(t *testing.T) { testOdr(t, 2, 1, odrGetBlock) }
func odrGetBlock(ctx context.Context, db ethdb.Database, config *params.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte { func odrGetBlock(ctx context.Context, db database.Database, config *params.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte {
var block *types.Block var block *types.Block
if bc != nil { if bc != nil {
block = bc.GetBlockByHash(bhash) block = bc.GetBlockByHash(bhash)
@ -60,7 +60,7 @@ func TestOdrGetReceiptsLes1(t *testing.T) { testOdr(t, 1, 1, odrGetReceipts) }
func TestOdrGetReceiptsLes2(t *testing.T) { testOdr(t, 2, 1, odrGetReceipts) } func TestOdrGetReceiptsLes2(t *testing.T) { testOdr(t, 2, 1, odrGetReceipts) }
func odrGetReceipts(ctx context.Context, db ethdb.Database, config *params.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte { func odrGetReceipts(ctx context.Context, db database.Database, config *params.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte {
var receipts types.Receipts var receipts types.Receipts
if bc != nil { if bc != nil {
if number := rawdb.ReadHeaderNumber(db, bhash); number != nil { if number := rawdb.ReadHeaderNumber(db, bhash); number != nil {
@ -82,7 +82,7 @@ func TestOdrAccountsLes1(t *testing.T) { testOdr(t, 1, 1, odrAccounts) }
func TestOdrAccountsLes2(t *testing.T) { testOdr(t, 2, 1, odrAccounts) } func TestOdrAccountsLes2(t *testing.T) { testOdr(t, 2, 1, odrAccounts) }
func odrAccounts(ctx context.Context, db ethdb.Database, config *params.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte { func odrAccounts(ctx context.Context, db database.Database, config *params.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte {
dummyAddr := common.HexToAddress("1234567812345678123456781234567812345678") dummyAddr := common.HexToAddress("1234567812345678123456781234567812345678")
acc := []common.Address{testBankAddress, acc1Addr, acc2Addr, dummyAddr} acc := []common.Address{testBankAddress, acc1Addr, acc2Addr, dummyAddr}
@ -118,7 +118,7 @@ type callmsg struct {
func (callmsg) CheckNonce() bool { return false } func (callmsg) CheckNonce() bool { return false }
func odrContractCall(ctx context.Context, db ethdb.Database, config *params.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte { func odrContractCall(ctx context.Context, db database.Database, config *params.ChainConfig, bc *core.BlockChain, lc *light.LightChain, bhash common.Hash) []byte {
data := common.Hex2Bytes("60CD26850000000000000000000000000000000000000000000000000000000000000000") data := common.Hex2Bytes("60CD26850000000000000000000000000000000000000000000000000000000000000000")
var res []byte var res []byte

View file

@ -24,7 +24,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/light"
) )
@ -34,13 +34,13 @@ func secAddr(addr common.Address) []byte {
return crypto.Keccak256(addr[:]) return crypto.Keccak256(addr[:])
} }
type accessTestFn func(db ethdb.Database, bhash common.Hash, number uint64) light.OdrRequest type accessTestFn func(db database.Database, bhash common.Hash, number uint64) light.OdrRequest
func TestBlockAccessLes1(t *testing.T) { testAccess(t, 1, tfBlockAccess) } func TestBlockAccessLes1(t *testing.T) { testAccess(t, 1, tfBlockAccess) }
func TestBlockAccessLes2(t *testing.T) { testAccess(t, 2, tfBlockAccess) } func TestBlockAccessLes2(t *testing.T) { testAccess(t, 2, tfBlockAccess) }
func tfBlockAccess(db ethdb.Database, bhash common.Hash, number uint64) light.OdrRequest { func tfBlockAccess(db database.Database, bhash common.Hash, number uint64) light.OdrRequest {
return &light.BlockRequest{Hash: bhash, Number: number} return &light.BlockRequest{Hash: bhash, Number: number}
} }
@ -48,7 +48,7 @@ func TestReceiptsAccessLes1(t *testing.T) { testAccess(t, 1, tfReceiptsAccess) }
func TestReceiptsAccessLes2(t *testing.T) { testAccess(t, 2, tfReceiptsAccess) } func TestReceiptsAccessLes2(t *testing.T) { testAccess(t, 2, tfReceiptsAccess) }
func tfReceiptsAccess(db ethdb.Database, bhash common.Hash, number uint64) light.OdrRequest { func tfReceiptsAccess(db database.Database, bhash common.Hash, number uint64) light.OdrRequest {
return &light.ReceiptsRequest{Hash: bhash, Number: number} return &light.ReceiptsRequest{Hash: bhash, Number: number}
} }
@ -56,7 +56,7 @@ func TestTrieEntryAccessLes1(t *testing.T) { testAccess(t, 1, tfTrieEntryAccess)
func TestTrieEntryAccessLes2(t *testing.T) { testAccess(t, 2, tfTrieEntryAccess) } func TestTrieEntryAccessLes2(t *testing.T) { testAccess(t, 2, tfTrieEntryAccess) }
func tfTrieEntryAccess(db ethdb.Database, bhash common.Hash, number uint64) light.OdrRequest { func tfTrieEntryAccess(db database.Database, bhash common.Hash, number uint64) light.OdrRequest {
if number := rawdb.ReadHeaderNumber(db, bhash); number != nil { if number := rawdb.ReadHeaderNumber(db, bhash); number != nil {
return &light.TrieRequest{Id: light.StateTrieID(rawdb.ReadHeader(db, bhash, *number)), Key: testBankSecureTrieKey} return &light.TrieRequest{Id: light.StateTrieID(rawdb.ReadHeader(db, bhash, *number)), Key: testBankSecureTrieKey}
} }
@ -67,7 +67,7 @@ func TestCodeAccessLes1(t *testing.T) { testAccess(t, 1, tfCodeAccess) }
func TestCodeAccessLes2(t *testing.T) { testAccess(t, 2, tfCodeAccess) } func TestCodeAccessLes2(t *testing.T) { testAccess(t, 2, tfCodeAccess) }
func tfCodeAccess(db ethdb.Database, bhash common.Hash, num uint64) light.OdrRequest { func tfCodeAccess(db database.Database, bhash common.Hash, num uint64) light.OdrRequest {
number := rawdb.ReadHeaderNumber(db, bhash) number := rawdb.ReadHeaderNumber(db, bhash)
if number != nil { if number != nil {
return nil return nil

View file

@ -27,8 +27,8 @@ import (
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/les/flowcontrol" "github.com/ethereum/go-ethereum/les/flowcontrol"
"github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/light"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
@ -247,7 +247,7 @@ func linRegFromBytes(data []byte) *linReg {
type requestCostStats struct { type requestCostStats struct {
lock sync.RWMutex lock sync.RWMutex
db ethdb.Database db database.Database
stats map[uint64]*linReg stats map[uint64]*linReg
} }
@ -258,7 +258,7 @@ type requestCostStatsRlp []struct {
var rcStatsKey = []byte("_requestCostStats") var rcStatsKey = []byte("_requestCostStats")
func newCostStats(db ethdb.Database) *requestCostStats { func newCostStats(db database.Database) *requestCostStats {
stats := make(map[uint64]*linReg) stats := make(map[uint64]*linReg)
for _, code := range reqList { for _, code := range reqList {
stats[code] = &linReg{cnt: 100} stats[code] = &linReg{cnt: 100}

View file

@ -30,7 +30,7 @@ import (
"github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/common/mclock"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/discv5" "github.com/ethereum/go-ethereum/p2p/discv5"
@ -113,7 +113,7 @@ type registerReq struct {
// known light server nodes. It received discovered nodes, stores statistics about // known light server nodes. It received discovered nodes, stores statistics about
// known nodes and takes care of always having enough good quality servers connected. // known nodes and takes care of always having enough good quality servers connected.
type serverPool struct { type serverPool struct {
db ethdb.Database db database.Database
dbKey []byte dbKey []byte
server *p2p.Server server *p2p.Server
quit chan struct{} quit chan struct{}
@ -141,7 +141,7 @@ type serverPool struct {
} }
// newServerPool creates a new serverPool instance // newServerPool creates a new serverPool instance
func newServerPool(db ethdb.Database, quit chan struct{}, wg *sync.WaitGroup, trustedNodes []string) *serverPool { func newServerPool(db database.Database, quit chan struct{}, wg *sync.WaitGroup, trustedNodes []string) *serverPool {
pool := &serverPool{ pool := &serverPool{
db: db, db: db,
quit: quit, quit: quit,

View file

@ -1,20 +1,18 @@
package les package les
import ( import (
"crypto/ecdsa"
"fmt" "fmt"
"math/big"
"net"
"reflect" "reflect"
"testing" "testing"
"time" "time"
"net"
"crypto/ecdsa"
"math/big"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"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/light" "github.com/ethereum/go-ethereum/light"
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
@ -197,7 +195,7 @@ func connectPeers(full, light pairPeer, version int) (*peer, *peer, error) {
// newFullPeerPair creates node with full sync mode // newFullPeerPair creates node with full sync mode
func newFullPeerPair(t *testing.T, index int, numberOfblocks int, chainGen func(int, *core.BlockGen)) pairPeer { func newFullPeerPair(t *testing.T, index int, numberOfblocks int, chainGen func(int, *core.BlockGen)) pairPeer {
db := ethdb.NewMemDatabase() db := rawdb.NewMemoryDatabase()
pmFull := newTestProtocolManagerMust(t, false, numberOfblocks, chainGen, nil, nil, db, nil) pmFull := newTestProtocolManagerMust(t, false, numberOfblocks, chainGen, nil, nil, db, nil)
@ -219,7 +217,7 @@ func newLightPeer(t *testing.T, ulcConfig *eth.ULCConfig) pairPeer {
peers := newPeerSet() peers := newPeerSet()
dist := newRequestDistributor(peers, make(chan struct{})) dist := newRequestDistributor(peers, make(chan struct{}))
rm := newRetrieveManager(peers, dist, nil) rm := newRetrieveManager(peers, dist, nil)
ldb := ethdb.NewMemDatabase() ldb := rawdb.NewMemoryDatabase()
odr := NewLesOdr(ldb, light.DefaultClientIndexerConfig, rm) odr := NewLesOdr(ldb, light.DefaultClientIndexerConfig, rm)

View file

@ -30,7 +30,7 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"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/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
@ -49,7 +49,7 @@ var (
type LightChain struct { type LightChain struct {
hc *core.HeaderChain hc *core.HeaderChain
indexerConfig *IndexerConfig indexerConfig *IndexerConfig
chainDb ethdb.Database chainDb database.Database
engine consensus.Engine engine consensus.Engine
odr OdrBackend odr OdrBackend
chainFeed event.Feed chainFeed event.Feed

View file

@ -26,7 +26,7 @@ import (
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
) )
@ -37,7 +37,7 @@ var (
) )
// makeHeaderChain creates a deterministic chain of headers rooted at parent. // makeHeaderChain creates a deterministic chain of headers rooted at parent.
func makeHeaderChain(parent *types.Header, n int, db ethdb.Database, seed int) []*types.Header { func makeHeaderChain(parent *types.Header, n int, db database.Database, seed int) []*types.Header {
blocks, _ := core.GenerateChain(params.TestChainConfig, types.NewBlockWithHeader(parent), ethash.NewFaker(), db, n, func(i int, b *core.BlockGen) { blocks, _ := core.GenerateChain(params.TestChainConfig, types.NewBlockWithHeader(parent), ethash.NewFaker(), db, n, func(i int, b *core.BlockGen) {
b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)}) b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)})
}) })
@ -51,8 +51,8 @@ func makeHeaderChain(parent *types.Header, n int, db ethdb.Database, seed int) [
// newCanonical creates a chain database, and injects a deterministic canonical // newCanonical creates a chain database, and injects a deterministic canonical
// chain. Depending on the full flag, if creates either a full block chain or a // chain. Depending on the full flag, if creates either a full block chain or a
// header only chain. // header only chain.
func newCanonical(n int) (ethdb.Database, *LightChain, error) { func newCanonical(n int) (database.Database, *LightChain, error) {
db := ethdb.NewMemDatabase() db := rawdb.NewMemoryDatabase()
gspec := core.Genesis{Config: params.TestChainConfig} gspec := core.Genesis{Config: params.TestChainConfig}
genesis := gspec.MustCommit(db) genesis := gspec.MustCommit(db)
blockchain, _ := NewLightChain(&dummyOdr{db: db, indexerConfig: TestClientIndexerConfig}, gspec.Config, ethash.NewFaker()) blockchain, _ := NewLightChain(&dummyOdr{db: db, indexerConfig: TestClientIndexerConfig}, gspec.Config, ethash.NewFaker())
@ -69,7 +69,7 @@ func newCanonical(n int) (ethdb.Database, *LightChain, error) {
// newTestLightChain creates a LightChain that doesn't validate anything. // newTestLightChain creates a LightChain that doesn't validate anything.
func newTestLightChain() *LightChain { func newTestLightChain() *LightChain {
db := ethdb.NewMemDatabase() db := rawdb.NewMemoryDatabase()
gspec := &core.Genesis{ gspec := &core.Genesis{
Difficulty: big.NewInt(1), Difficulty: big.NewInt(1),
Config: params.TestChainConfig, Config: params.TestChainConfig,
@ -265,11 +265,11 @@ func makeHeaderChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.
type dummyOdr struct { type dummyOdr struct {
OdrBackend OdrBackend
db ethdb.Database db database.Database
indexerConfig *IndexerConfig indexerConfig *IndexerConfig
} }
func (odr *dummyOdr) Database() ethdb.Database { func (odr *dummyOdr) Database() database.Database {
return odr.db return odr.db
} }

View file

@ -22,7 +22,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
) )
@ -106,7 +106,7 @@ func (db *NodeSet) NodeList() NodeList {
} }
// Store writes the contents of the set to the given database // Store writes the contents of the set to the given database
func (db *NodeSet) Store(target ethdb.Putter) { func (db *NodeSet) Store(target database.Writer) {
db.lock.RLock() db.lock.RLock()
defer db.lock.RUnlock() defer db.lock.RUnlock()
@ -115,11 +115,11 @@ func (db *NodeSet) Store(target ethdb.Putter) {
} }
} }
// NodeList stores an ordered list of trie nodes. It implements ethdb.Putter. // NodeList stores an ordered list of trie nodes. It implements database.Writer.
type NodeList []rlp.RawValue type NodeList []rlp.RawValue
// Store writes the contents of the list to the given database // Store writes the contents of the list to the given database
func (n NodeList) Store(db ethdb.Putter) { func (n NodeList) Store(db database.Writer) {
for _, node := range n { for _, node := range n {
db.Put(crypto.Keccak256(node), node) db.Put(crypto.Keccak256(node), node)
} }

View file

@ -27,7 +27,7 @@ import (
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/database"
) )
// NoOdr is the default context passed to an ODR capable function when the ODR // NoOdr is the default context passed to an ODR capable function when the ODR
@ -39,7 +39,7 @@ var ErrNoPeers = errors.New("no suitable peers available")
// OdrBackend is an interface to a backend service that handles ODR retrievals type // OdrBackend is an interface to a backend service that handles ODR retrievals type
type OdrBackend interface { type OdrBackend interface {
Database() ethdb.Database Database() database.Database
ChtIndexer() *core.ChainIndexer ChtIndexer() *core.ChainIndexer
BloomTrieIndexer() *core.ChainIndexer BloomTrieIndexer() *core.ChainIndexer
BloomIndexer() *core.ChainIndexer BloomIndexer() *core.ChainIndexer
@ -49,7 +49,7 @@ type OdrBackend interface {
// OdrRequest is an interface for retrieval requests // OdrRequest is an interface for retrieval requests
type OdrRequest interface { type OdrRequest interface {
StoreResult(db ethdb.Database) StoreResult(db database.Database)
} }
// TrieID identifies a state or account storage trie // TrieID identifies a state or account storage trie
@ -91,7 +91,7 @@ type TrieRequest struct {
} }
// StoreResult stores the retrieved data in local database // StoreResult stores the retrieved data in local database
func (req *TrieRequest) StoreResult(db ethdb.Database) { func (req *TrieRequest) StoreResult(db database.Database) {
req.Proof.Store(db) req.Proof.Store(db)
} }
@ -104,7 +104,7 @@ type CodeRequest struct {
} }
// StoreResult stores the retrieved data in local database // StoreResult stores the retrieved data in local database
func (req *CodeRequest) StoreResult(db ethdb.Database) { func (req *CodeRequest) StoreResult(db database.Database) {
db.Put(req.Hash[:], req.Data) db.Put(req.Hash[:], req.Data)
} }
@ -117,7 +117,7 @@ type BlockRequest struct {
} }
// StoreResult stores the retrieved data in local database // StoreResult stores the retrieved data in local database
func (req *BlockRequest) StoreResult(db ethdb.Database) { func (req *BlockRequest) StoreResult(db database.Database) {
rawdb.WriteBodyRLP(db, req.Hash, req.Number, req.Rlp) rawdb.WriteBodyRLP(db, req.Hash, req.Number, req.Rlp)
} }
@ -130,7 +130,7 @@ type ReceiptsRequest struct {
} }
// StoreResult stores the retrieved data in local database // StoreResult stores the retrieved data in local database
func (req *ReceiptsRequest) StoreResult(db ethdb.Database) { func (req *ReceiptsRequest) StoreResult(db database.Database) {
rawdb.WriteReceipts(db, req.Hash, req.Number, req.Receipts) rawdb.WriteReceipts(db, req.Hash, req.Number, req.Receipts)
} }
@ -146,7 +146,7 @@ type ChtRequest struct {
} }
// StoreResult stores the retrieved data in local database // StoreResult stores the retrieved data in local database
func (req *ChtRequest) StoreResult(db ethdb.Database) { func (req *ChtRequest) StoreResult(db database.Database) {
hash, num := req.Header.Hash(), req.Header.Number.Uint64() hash, num := req.Header.Hash(), req.Header.Number.Uint64()
rawdb.WriteHeader(db, req.Header) rawdb.WriteHeader(db, req.Header)
@ -167,7 +167,7 @@ type BloomRequest struct {
} }
// StoreResult stores the retrieved data in local database // StoreResult stores the retrieved data in local database
func (req *BloomRequest) StoreResult(db ethdb.Database) { func (req *BloomRequest) StoreResult(db database.Database) {
for i, sectionIdx := range req.SectionIndexList { for i, sectionIdx := range req.SectionIndexList {
sectionHead := rawdb.ReadCanonicalHash(db, (sectionIdx+1)*req.Config.BloomTrieSize-1) sectionHead := rawdb.ReadCanonicalHash(db, (sectionIdx+1)*req.Config.BloomTrieSize-1)
// if we don't have the canonical hash stored for this section head number, we'll still store it under // if we don't have the canonical hash stored for this section head number, we'll still store it under

Some files were not shown because too many files have changed in this diff Show more