Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 91 additions & 4 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,13 @@ import (
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/logger"
"github.com/peterh/liner"
"path"
)

const (
Expand Down Expand Up @@ -205,12 +207,18 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
Name: "export",
Usage: `export blockchain into file`,
},
{
Action: upgradeDb,
Name: "upgradedb",
Usage: "upgrade chainblock database",
},
}
app.Flags = []cli.Flag{
utils.UnlockedAccountFlag,
utils.PasswordFileFlag,
utils.BootnodesFlag,
utils.DataDirFlag,
utils.BlockchainVersionFlag,
utils.JSpathFlag,
utils.ListenPortFlag,
utils.MaxPeersFlag,
Expand Down Expand Up @@ -429,30 +437,109 @@ func importchain(ctx *cli.Context) {
if len(ctx.Args()) != 1 {
utils.Fatalf("This command requires an argument.")
}
chainmgr, _, _ := 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()
err := utils.ImportChain(chainmgr, ctx.Args().First())
err = utils.ImportChain(chainmgr, ctx.Args().First())
if err != nil {
utils.Fatalf("Import error: %v\n", err)
}

// force database flush
ethereum.BlockDb().Close()
ethereum.StateDb().Close()
ethereum.ExtraDb().Close()

fmt.Printf("Import done in %v", time.Since(start))

return
}

func exportchain(ctx *cli.Context) {
if len(ctx.Args()) != 1 {
utils.Fatalf("This command requires an argument.")
}
chainmgr, _, _ := 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()
err := utils.ExportChain(chainmgr, ctx.Args().First())
err = utils.ExportChain(chainmgr, ctx.Args().First())
if err != nil {
utils.Fatalf("Export error: %v\n", err)
}
fmt.Printf("Export done in %v", time.Since(start))
return
}

func upgradeDb(ctx *cli.Context) {
fmt.Println("Upgrade blockchain DB")

cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx)
cfg.SkipBcVersionCheck = true

ethereum, err := eth.New(cfg)
if err != nil {
utils.Fatalf("%v\n", err)
}

v, _ := ethereum.BlockDb().Get([]byte("BlockchainVersion"))
bcVersion := int(common.NewValue(v).Uint())

if bcVersion == 0 {
bcVersion = core.BlockChainVersion
}

filename := fmt.Sprintf("blockchain_%d_%s.chain", bcVersion, time.Now().Format("2006-01-02_15:04:05"))
exportFile := path.Join(ctx.GlobalString(utils.DataDirFlag.Name), filename)

err = utils.ExportChain(ethereum.ChainManager(), exportFile)
if err != nil {
utils.Fatalf("Unable to export chain for reimport %s\n", err)
}

ethereum.BlockDb().Close()
ethereum.StateDb().Close()
ethereum.ExtraDb().Close()

os.RemoveAll(path.Join(ctx.GlobalString(utils.DataDirFlag.Name), "blockchain"))

ethereum, err = eth.New(cfg)
if err != nil {
utils.Fatalf("%v\n", err)
}

ethereum.BlockDb().Put([]byte("BlockchainVersion"), common.NewValue(core.BlockChainVersion).Bytes())

err = utils.ImportChain(ethereum.ChainManager(), exportFile)
if err != nil {
utils.Fatalf("Import error %v (a backup is made in %s, use the import command to import it)\n", err, exportFile)
}

// force database flush
ethereum.BlockDb().Close()
ethereum.StateDb().Close()
ethereum.ExtraDb().Close()

os.Remove(exportFile)

fmt.Println("Import finished")
}

func dump(ctx *cli.Context) {
chainmgr, _, stateDb := utils.GetChain(ctx)
for _, arg := range ctx.Args() {
Expand Down
25 changes: 22 additions & 3 deletions cmd/utils/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,18 +155,37 @@ func ImportChain(chainmgr *core.ChainManager, fn string) error {

chainmgr.Reset()
stream := rlp.NewStream(fh)
var i int
var i, n int

batchSize := 2500
blocks := make(types.Blocks, batchSize)

for ; ; i++ {
var b types.Block
if err := stream.Decode(&b); err == io.EOF {
break
} else if err != nil {
return fmt.Errorf("at block %d: %v", i, err)
}
if err := chainmgr.InsertChain(types.Blocks{&b}); err != nil {
return fmt.Errorf("invalid block %d: %v", i, err)

blocks[n] = &b
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 n > 0 {
if err := chainmgr.InsertChain(blocks[:n]); err != nil {
return fmt.Errorf("invalid block %v", err)
}
}

fmt.Printf("imported %d blocks\n", i)
return nil
}
Expand Down
60 changes: 41 additions & 19 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"runtime"

"github.com/codegangsta/cli"
"github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
Expand Down Expand Up @@ -83,6 +84,11 @@ var (
Usage: "Network Id",
Value: eth.NetworkId,
}
BlockchainVersionFlag = cli.IntFlag{
Name: "blockchainversion",
Usage: "Blockchain version",
Value: core.BlockChainVersion,
}

// miner settings
MinerThreadsFlag = cli.IntFlag{
Expand Down Expand Up @@ -237,29 +243,32 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config {
glog.SetLogDir(ctx.GlobalString(LogFileFlag.Name))

return &eth.Config{
Name: common.MakeName(clientID, version),
DataDir: ctx.GlobalString(DataDirFlag.Name),
ProtocolVersion: ctx.GlobalInt(ProtocolVersionFlag.Name),
NetworkId: ctx.GlobalInt(NetworkIdFlag.Name),
LogFile: ctx.GlobalString(LogFileFlag.Name),
LogLevel: ctx.GlobalInt(LogLevelFlag.Name),
LogJSON: ctx.GlobalString(LogJSONFlag.Name),
Etherbase: ctx.GlobalString(EtherbaseFlag.Name),
MinerThreads: ctx.GlobalInt(MinerThreadsFlag.Name),
AccountManager: GetAccountManager(ctx),
VmDebug: ctx.GlobalBool(VMDebugFlag.Name),
MaxPeers: ctx.GlobalInt(MaxPeersFlag.Name),
Port: ctx.GlobalString(ListenPortFlag.Name),
NAT: GetNAT(ctx),
NodeKey: GetNodeKey(ctx),
Shh: true,
Dial: true,
BootNodes: ctx.GlobalString(BootnodesFlag.Name),
Name: common.MakeName(clientID, version),
DataDir: ctx.GlobalString(DataDirFlag.Name),
ProtocolVersion: ctx.GlobalInt(ProtocolVersionFlag.Name),
BlockChainVersion: ctx.GlobalInt(BlockchainVersionFlag.Name),
SkipBcVersionCheck: false,
NetworkId: ctx.GlobalInt(NetworkIdFlag.Name),
LogFile: ctx.GlobalString(LogFileFlag.Name),
LogLevel: ctx.GlobalInt(LogLevelFlag.Name),
LogJSON: ctx.GlobalString(LogJSONFlag.Name),
Etherbase: ctx.GlobalString(EtherbaseFlag.Name),
MinerThreads: ctx.GlobalInt(MinerThreadsFlag.Name),
AccountManager: GetAccountManager(ctx),
VmDebug: ctx.GlobalBool(VMDebugFlag.Name),
MaxPeers: ctx.GlobalInt(MaxPeersFlag.Name),
Port: ctx.GlobalString(ListenPortFlag.Name),
NAT: GetNAT(ctx),
NodeKey: GetNodeKey(ctx),
Shh: true,
Dial: true,
BootNodes: ctx.GlobalString(BootnodesFlag.Name),
}
}

func GetChain(ctx *cli.Context) (*core.ChainManager, common.Database, common.Database) {
dataDir := ctx.GlobalString(DataDirFlag.Name)

blockDb, err := ethdb.NewLDBDatabase(path.Join(dataDir, "blockchain"))
if err != nil {
Fatalf("Could not open database: %v", err)
Expand All @@ -269,7 +278,20 @@ func GetChain(ctx *cli.Context) (*core.ChainManager, common.Database, common.Dat
if err != nil {
Fatalf("Could not open database: %v", err)
}
return core.NewChainManager(blockDb, stateDb, new(event.TypeMux)), blockDb, stateDb

extraDb, err := ethdb.NewLDBDatabase(path.Join(dataDir, "extra"))
if err != nil {
Fatalf("Could not open database: %v", err)
}

eventMux := new(event.TypeMux)
chainManager := core.NewChainManager(blockDb, stateDb, eventMux)
pow := ethash.New(chainManager)
txPool := core.NewTxPool(eventMux, chainManager.State)
blockProcessor := core.NewBlockProcessor(stateDb, extraDb, pow, txPool, chainManager, eventMux)
chainManager.SetProcessor(blockProcessor)

return chainManager, blockDb, stateDb
}

func GetAccountManager(ctx *cli.Context) *accounts.Manager {
Expand Down
6 changes: 6 additions & 0 deletions core/block_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ import (
"gopkg.in/fatih/set.v0"
)

const (
// must be bumped when consensus algorithm is changed, this forces the upgradedb
// command to be run (forces the blocks to be imported again using the new algorithm)
BlockChainVersion = 1
)

var statelogger = logger.NewLogger("BLOCK")

type BlockProcessor struct {
Expand Down
7 changes: 5 additions & 2 deletions core/chain_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,11 +284,14 @@ func (self *ChainManager) Export(w io.Writer) error {
defer self.mu.RUnlock()
glog.V(logger.Info).Infof("exporting %v blocks...\n", self.currentBlock.Header().Number)

for block := self.currentBlock; block != nil; block = self.GetBlock(block.Header().ParentHash) {
if err := block.EncodeRLP(w); err != nil {
last := self.currentBlock.NumberU64()

for nr := uint64(0); nr <= last; nr++ {
if err := self.GetBlockByNumber(nr).EncodeRLP(w); err != nil {
return err
}
}

return nil
}

Expand Down
24 changes: 23 additions & 1 deletion eth/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ type Config struct {
ProtocolVersion int
NetworkId int

BlockChainVersion int
SkipBcVersionCheck bool // e.g. blockchain export

DataDir string
LogFile string
LogLevel int
Expand Down Expand Up @@ -149,7 +152,7 @@ type Ethereum struct {
}

func New(config *Config) (*Ethereum, error) {
// Boostrap database
// Bootstrap database
logger.New(config.DataDir, config.LogFile, config.LogLevel)
if len(config.LogJSON) > 0 {
logger.NewJSONsystem(config.DataDir, config.LogJSON)
Expand Down Expand Up @@ -179,6 +182,16 @@ func New(config *Config) (*Ethereum, error) {
saveProtocolVersion(blockDb, config.ProtocolVersion)
glog.V(logger.Info).Infof("Protocol Version: %v, Network Id: %v", config.ProtocolVersion, config.NetworkId)

if !config.SkipBcVersionCheck {
b, _ := blockDb.Get([]byte("BlockchainVersion"))
bcVersion := int(common.NewValue(b).Uint())
if bcVersion != config.BlockChainVersion && bcVersion != 0 {
return nil, fmt.Errorf("Blockchain DB version mismatch (%d / %d). Run geth upgradedb.\n", bcVersion, config.BlockChainVersion)
}
saveBlockchainVersion(blockDb, config.BlockChainVersion)
}
glog.V(logger.Info).Infof("Blockchain DB Version: %d", config.BlockChainVersion)

eth := &Ethereum{
shutdownChan: make(chan bool),
blockDb: blockDb,
Expand Down Expand Up @@ -472,3 +485,12 @@ func saveProtocolVersion(db common.Database, protov int) {
db.Put([]byte("ProtocolVersion"), common.NewValue(protov).Bytes())
}
}

func saveBlockchainVersion(db common.Database, bcVersion int) {
d, _ := db.Get([]byte("BlockchainVersion"))
blockchainVersion := common.NewValue(d).Uint()

if blockchainVersion == 0 {
db.Put([]byte("BlockchainVersion"), common.NewValue(bcVersion).Bytes())
}
}