Commit 3b9808f2 authored by Felix Lange's avatar Felix Lange

cmd/geth, cmd/utils: don't use Ethereum for import, export and upgradedb

The blockchain commands don't need the full stack. With this change,
p2p, miner, downloader, etc are no longer started for blockchain
operations.
parent 27e0d2a9
...@@ -41,6 +41,7 @@ import ( ...@@ -41,6 +41,7 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/mattn/go-colorable" "github.com/mattn/go-colorable"
"github.com/mattn/go-isatty" "github.com/mattn/go-isatty"
) )
...@@ -282,17 +283,12 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso ...@@ -282,17 +283,12 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
utils.SolcPathFlag, utils.SolcPathFlag,
} }
app.Before = func(ctx *cli.Context) error { app.Before = func(ctx *cli.Context) error {
utils.SetupLogger(ctx)
if ctx.GlobalBool(utils.PProfEanbledFlag.Name) { if ctx.GlobalBool(utils.PProfEanbledFlag.Name) {
utils.StartPProf(ctx) utils.StartPProf(ctx)
} }
return nil return nil
} }
// missing:
// flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file")
// flag.BoolVar(&DiffTool, "difftool", false, "creates output for diff'ing. Sets LogLevel=0")
// flag.StringVar(&DiffType, "diff", "all", "sets the level of diff output [vm, all]. Has no effect if difftool=false")
} }
func main() { func main() {
...@@ -516,53 +512,25 @@ func importchain(ctx *cli.Context) { ...@@ -516,53 +512,25 @@ func importchain(ctx *cli.Context) {
if len(ctx.Args()) != 1 { if len(ctx.Args()) != 1 {
utils.Fatalf("This command requires an argument.") utils.Fatalf("This command requires an argument.")
} }
chain, blockDB, stateDB, extraDB := utils.GetChain(ctx)
cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx)
cfg.SkipBcVersionCheck = true
ethereum, err := eth.New(cfg)
if err != nil {
utils.Fatalf("%v\n", err)
}
chainmgr := ethereum.ChainManager()
start := time.Now() start := time.Now()
err = utils.ImportChain(chainmgr, ctx.Args().First()) if err := utils.ImportChain(chain, ctx.Args().First()); err != nil {
if err != nil {
utils.Fatalf("Import error: %v\n", err) utils.Fatalf("Import error: %v\n", err)
} }
flushAll(blockDB, stateDB, extraDB)
// force database flush
ethereum.BlockDb().Flush()
ethereum.StateDb().Flush()
ethereum.ExtraDb().Flush()
fmt.Printf("Import done in %v", time.Since(start)) fmt.Printf("Import done in %v", time.Since(start))
return
} }
func exportchain(ctx *cli.Context) { func exportchain(ctx *cli.Context) {
if len(ctx.Args()) != 1 { if len(ctx.Args()) != 1 {
utils.Fatalf("This command requires an argument.") utils.Fatalf("This command requires an argument.")
} }
chain, _, _, _ := utils.GetChain(ctx)
cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx)
cfg.SkipBcVersionCheck = true
ethereum, err := eth.New(cfg)
if err != nil {
utils.Fatalf("%v\n", err)
}
chainmgr := ethereum.ChainManager()
start := time.Now() start := time.Now()
err = utils.ExportChain(chainmgr, ctx.Args().First()) if err := utils.ExportChain(chain, ctx.Args().First()); err != nil {
if err != nil {
utils.Fatalf("Export error: %v\n", err) utils.Fatalf("Export error: %v\n", err)
} }
fmt.Printf("Export done in %v", time.Since(start)) fmt.Printf("Export done in %v", time.Since(start))
return
} }
func removeDb(ctx *cli.Context) { func removeDb(ctx *cli.Context) {
...@@ -585,76 +553,54 @@ func removeDb(ctx *cli.Context) { ...@@ -585,76 +553,54 @@ func removeDb(ctx *cli.Context) {
} }
func upgradeDb(ctx *cli.Context) { func upgradeDb(ctx *cli.Context) {
fmt.Println("Upgrade blockchain DB") glog.Infoln("Upgrading blockchain database")
cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx)
cfg.SkipBcVersionCheck = true
ethereum, err := eth.New(cfg) chain, blockDB, stateDB, extraDB := utils.GetChain(ctx)
if err != nil { v, _ := blockDB.Get([]byte("BlockchainVersion"))
utils.Fatalf("%v\n", err)
}
v, _ := ethereum.BlockDb().Get([]byte("BlockchainVersion"))
bcVersion := int(common.NewValue(v).Uint()) bcVersion := int(common.NewValue(v).Uint())
if bcVersion == 0 { if bcVersion == 0 {
bcVersion = core.BlockChainVersion bcVersion = core.BlockChainVersion
} }
// Export the current chain.
filename := fmt.Sprintf("blockchain_%d_%s.chain", bcVersion, time.Now().Format("20060102_150405")) filename := fmt.Sprintf("blockchain_%d_%s.chain", bcVersion, time.Now().Format("20060102_150405"))
exportFile := filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), filename) exportFile := filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), filename)
if err := utils.ExportChain(chain, exportFile); err != nil {
err = utils.ExportChain(ethereum.ChainManager(), exportFile)
if err != nil {
utils.Fatalf("Unable to export chain for reimport %s\n", err) utils.Fatalf("Unable to export chain for reimport %s\n", err)
} }
flushAll(blockDB, stateDB, extraDB)
ethereum.BlockDb().Close()
ethereum.StateDb().Close()
ethereum.ExtraDb().Close()
os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "blockchain")) os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "blockchain"))
os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "state")) os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "state"))
ethereum, err = eth.New(cfg) // Import the chain file.
if err != nil { chain, blockDB, stateDB, extraDB = utils.GetChain(ctx)
utils.Fatalf("%v\n", err) blockDB.Put([]byte("BlockchainVersion"), common.NewValue(core.BlockChainVersion).Bytes())
} err := utils.ImportChain(chain, exportFile)
flushAll(blockDB, stateDB, extraDB)
ethereum.BlockDb().Put([]byte("BlockchainVersion"), common.NewValue(core.BlockChainVersion).Bytes())
err = utils.ImportChain(ethereum.ChainManager(), exportFile)
if err != nil { if err != nil {
utils.Fatalf("Import error %v (a backup is made in %s, use the import command to import it)\n", err, exportFile) utils.Fatalf("Import error %v (a backup is made in %s, use the import command to import it)\n", err, exportFile)
} } else {
// force database flush
ethereum.BlockDb().Flush()
ethereum.StateDb().Flush()
ethereum.ExtraDb().Flush()
os.Remove(exportFile) os.Remove(exportFile)
glog.Infoln("Import finished")
fmt.Println("Import finished") }
} }
func dump(ctx *cli.Context) { func dump(ctx *cli.Context) {
chainmgr, _, stateDb := utils.GetChain(ctx) chain, _, stateDB, _ := utils.GetChain(ctx)
for _, arg := range ctx.Args() { for _, arg := range ctx.Args() {
var block *types.Block var block *types.Block
if hashish(arg) { if hashish(arg) {
block = chainmgr.GetBlock(common.HexToHash(arg)) block = chain.GetBlock(common.HexToHash(arg))
} else { } else {
num, _ := strconv.Atoi(arg) num, _ := strconv.Atoi(arg)
block = chainmgr.GetBlockByNumber(uint64(num)) block = chain.GetBlockByNumber(uint64(num))
} }
if block == nil { if block == nil {
fmt.Println("{}") fmt.Println("{}")
utils.Fatalf("block not found") utils.Fatalf("block not found")
} else { } else {
statedb := state.New(block.Root(), stateDb) state := state.New(block.Root(), stateDB)
fmt.Printf("%s\n", statedb.Dump()) fmt.Printf("%s\n", state.Dump())
} }
} }
} }
...@@ -707,3 +653,10 @@ func hashish(x string) bool { ...@@ -707,3 +653,10 @@ func hashish(x string) bool {
_, err := strconv.Atoi(x) _, err := strconv.Atoi(x)
return err != nil return err != nil
} }
func flushAll(dbs ...common.Database) {
for _, db := range dbs {
db.Flush()
db.Close()
}
}
...@@ -167,7 +167,7 @@ func FormatTransactionData(data string) []byte { ...@@ -167,7 +167,7 @@ func FormatTransactionData(data string) []byte {
} }
func ImportChain(chainmgr *core.ChainManager, fn string) error { func ImportChain(chainmgr *core.ChainManager, fn string) error {
fmt.Printf("importing blockchain '%s'\n", fn) glog.Infoln("Importing blockchain", fn)
fh, err := os.OpenFile(fn, os.O_RDONLY, os.ModePerm) fh, err := os.OpenFile(fn, os.O_RDONLY, os.ModePerm)
if err != nil { if err != nil {
return err return err
...@@ -176,43 +176,36 @@ func ImportChain(chainmgr *core.ChainManager, fn string) error { ...@@ -176,43 +176,36 @@ func ImportChain(chainmgr *core.ChainManager, fn string) error {
chainmgr.Reset() chainmgr.Reset()
stream := rlp.NewStream(fh, 0) stream := rlp.NewStream(fh, 0)
var i, n int
batchSize := 2500 batchSize := 2500
blocks := make(types.Blocks, batchSize) blocks := make(types.Blocks, batchSize)
n := 0
for ; ; i++ { for {
// Load a batch of RLP blocks.
i := 0
for ; i < batchSize; i++ {
var b types.Block var b types.Block
if err := stream.Decode(&b); err == io.EOF { if err := stream.Decode(&b); err == io.EOF {
break break
} else if err != nil { } else if err != nil {
return fmt.Errorf("at block %d: %v", i, err) return fmt.Errorf("at block %d: %v", n, err)
} }
blocks[i] = &b
blocks[n] = &b
n++ n++
if n == batchSize {
if _, err := chainmgr.InsertChain(blocks); err != nil {
return fmt.Errorf("invalid block %v", err)
}
n = 0
blocks = make(types.Blocks, batchSize)
} }
if i == 0 {
break
} }
// Import the batch.
if n > 0 { if _, err := chainmgr.InsertChain(blocks[:i]); err != nil {
if _, err := chainmgr.InsertChain(blocks[:n]); err != nil { return fmt.Errorf("invalid block %d: %v", n, err)
return fmt.Errorf("invalid block %v", err)
} }
} }
fmt.Printf("imported %d blocks\n", i)
return nil return nil
} }
func ExportChain(chainmgr *core.ChainManager, fn string) error { func ExportChain(chainmgr *core.ChainManager, fn string) error {
fmt.Printf("exporting blockchain '%s'\n", fn) glog.Infoln("Exporting blockchain to", fn)
fh, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm) fh, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
if err != nil { if err != nil {
return err return err
...@@ -221,6 +214,6 @@ func ExportChain(chainmgr *core.ChainManager, fn string) error { ...@@ -221,6 +214,6 @@ func ExportChain(chainmgr *core.ChainManager, fn string) error {
if err := chainmgr.Export(fh); err != nil { if err := chainmgr.Export(fh); err != nil {
return err return err
} }
fmt.Printf("exported blockchain\n") glog.Infoln("Exported blockchain to", fn)
return nil return nil
} }
...@@ -283,20 +283,10 @@ func GetNodeKey(ctx *cli.Context) (key *ecdsa.PrivateKey) { ...@@ -283,20 +283,10 @@ func GetNodeKey(ctx *cli.Context) (key *ecdsa.PrivateKey) {
} }
func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config { func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config {
// Set verbosity on glog
glog.SetV(ctx.GlobalInt(VerbosityFlag.Name))
glog.CopyStandardLogTo("INFO")
// Set the log type
//glog.SetToStderr(ctx.GlobalBool(LogToStdErrFlag.Name))
glog.SetToStderr(true)
// Set the log dir
glog.SetLogDir(ctx.GlobalString(LogFileFlag.Name))
customName := ctx.GlobalString(IdentityFlag.Name) customName := ctx.GlobalString(IdentityFlag.Name)
if len(customName) > 0 { if len(customName) > 0 {
clientID += "/" + customName clientID += "/" + customName
} }
return &eth.Config{ return &eth.Config{
Name: common.MakeName(clientID, version), Name: common.MakeName(clientID, version),
DataDir: ctx.GlobalString(DataDirFlag.Name), DataDir: ctx.GlobalString(DataDirFlag.Name),
...@@ -327,32 +317,34 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config { ...@@ -327,32 +317,34 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config {
} }
} }
func GetChain(ctx *cli.Context) (*core.ChainManager, common.Database, common.Database) { // SetupLogger configures glog from the logging-related command line flags.
dataDir := ctx.GlobalString(DataDirFlag.Name) func SetupLogger(ctx *cli.Context) {
glog.SetV(ctx.GlobalInt(VerbosityFlag.Name))
glog.CopyStandardLogTo("INFO")
glog.SetToStderr(true)
glog.SetLogDir(ctx.GlobalString(LogFileFlag.Name))
}
blockDb, err := ethdb.NewLDBDatabase(filepath.Join(dataDir, "blockchain")) func GetChain(ctx *cli.Context) (chain *core.ChainManager, blockDB, stateDB, extraDB common.Database) {
if err != nil { dd := ctx.GlobalString(DataDirFlag.Name)
var err error
if blockDB, err = ethdb.NewLDBDatabase(filepath.Join(dd, "blockchain")); err != nil {
Fatalf("Could not open database: %v", err) Fatalf("Could not open database: %v", err)
} }
if stateDB, err = ethdb.NewLDBDatabase(filepath.Join(dd, "state")); err != nil {
stateDb, err := ethdb.NewLDBDatabase(filepath.Join(dataDir, "state"))
if err != nil {
Fatalf("Could not open database: %v", err) Fatalf("Could not open database: %v", err)
} }
if extraDB, err = ethdb.NewLDBDatabase(filepath.Join(dd, "extra")); err != nil {
extraDb, err := ethdb.NewLDBDatabase(filepath.Join(dataDir, "extra"))
if err != nil {
Fatalf("Could not open database: %v", err) Fatalf("Could not open database: %v", err)
} }
eventMux := new(event.TypeMux) eventMux := new(event.TypeMux)
pow := ethash.New() pow := ethash.New()
chainManager := core.NewChainManager(blockDb, stateDb, pow, eventMux) chain = core.NewChainManager(blockDB, stateDB, pow, eventMux)
txPool := core.NewTxPool(eventMux, chainManager.State, chainManager.GasLimit) txpool := core.NewTxPool(eventMux, chain.State, chain.GasLimit)
blockProcessor := core.NewBlockProcessor(stateDb, extraDb, pow, txPool, chainManager, eventMux) proc := core.NewBlockProcessor(stateDB, extraDB, pow, txpool, chain, eventMux)
chainManager.SetProcessor(blockProcessor) chain.SetProcessor(proc)
return chain, blockDB, stateDB, extraDB
return chainManager, blockDb, stateDb
} }
func GetAccountManager(ctx *cli.Context) *accounts.Manager { func GetAccountManager(ctx *cli.Context) *accounts.Manager {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment