Skip to content

Commit

Permalink
node: ensure datadir can be co-inhabited by different instances
Browse files Browse the repository at this point in the history
This change ensures that nodes started with different Name but same
DataDir values don't use the same nodekey and IPC socket.
  • Loading branch information
fjl committed Sep 16, 2016
1 parent 52ede09 commit eeb322a
Show file tree
Hide file tree
Showing 14 changed files with 422 additions and 186 deletions.
51 changes: 35 additions & 16 deletions cmd/geth/chaincmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ func importChain(ctx *cli.Context) error {
if ctx.GlobalBool(utils.TestNetFlag.Name) {
state.StartingNonce = 1048576 // (2**20)
}
chain, chainDb := utils.MakeChain(ctx)
stack := makeFullNode(ctx)
chain, chainDb := utils.MakeChain(ctx, stack)
start := time.Now()
err := utils.ImportChain(chain, ctx.Args().First())
chainDb.Close()
Expand All @@ -94,7 +95,8 @@ func exportChain(ctx *cli.Context) error {
if len(ctx.Args()) < 1 {
utils.Fatalf("This command requires an argument.")
}
chain, _ := utils.MakeChain(ctx)
stack := makeFullNode(ctx)
chain, _ := utils.MakeChain(ctx, stack)
start := time.Now()

var err error
Expand Down Expand Up @@ -122,28 +124,34 @@ func exportChain(ctx *cli.Context) error {
}

func removeDB(ctx *cli.Context) error {
confirm, err := console.Stdin.PromptConfirm("Remove local database?")
if err != nil {
utils.Fatalf("%v", err)
stack := utils.MakeNode(ctx, clientIdentifier, gitCommit)
dbdir := stack.ResolvePath("chaindata")
if !common.FileExist(dbdir) {
fmt.Println(dbdir, "does not exist")
return nil
}

if confirm {
fmt.Println("Removing chaindata...")
fmt.Println(dbdir)
confirm, err := console.Stdin.PromptConfirm("Remove this database?")
switch {
case err != nil:
utils.Fatalf("%v", err)
case !confirm:
fmt.Println("Operation aborted")
default:
fmt.Println("Removing...")
start := time.Now()

os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "chaindata"))

os.RemoveAll(dbdir)
fmt.Printf("Removed in %v\n", time.Since(start))
} else {
fmt.Println("Operation aborted")
}
return nil
}

func upgradeDB(ctx *cli.Context) error {
glog.Infoln("Upgrading blockchain database")

chain, chainDb := utils.MakeChain(ctx)
stack := utils.MakeNode(ctx, clientIdentifier, gitCommit)
chain, chainDb := utils.MakeChain(ctx, stack)
bcVersion := core.GetBlockChainVersion(chainDb)
if bcVersion == 0 {
bcVersion = core.BlockChainVersion
Expand All @@ -156,10 +164,12 @@ func upgradeDB(ctx *cli.Context) error {
utils.Fatalf("Unable to export chain for reimport %s", err)
}
chainDb.Close()
os.RemoveAll(filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), "chaindata"))
if dir := dbDirectory(chainDb); dir != "" {
os.RemoveAll(dir)
}

// Import the chain file.
chain, chainDb = utils.MakeChain(ctx)
chain, chainDb = utils.MakeChain(ctx, stack)
core.WriteBlockChainVersion(chainDb, core.BlockChainVersion)
err := utils.ImportChain(chain, exportFile)
chainDb.Close()
Expand All @@ -172,8 +182,17 @@ func upgradeDB(ctx *cli.Context) error {
return nil
}

func dbDirectory(db ethdb.Database) string {
ldb, ok := db.(*ethdb.LDBDatabase)
if !ok {
return ""
}
return ldb.Path()
}

func dump(ctx *cli.Context) error {
chain, chainDb := utils.MakeChain(ctx)
stack := makeFullNode(ctx)
chain, chainDb := utils.MakeChain(ctx, stack)
for _, arg := range ctx.Args() {
var block *types.Block
if hashish(arg) {
Expand Down
4 changes: 2 additions & 2 deletions cmd/geth/consolecmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func remoteConsole(ctx *cli.Context) error {
utils.Fatalf("Unable to attach to remote geth: %v", err)
}
config := console.Config{
DataDir: utils.MustMakeDataDir(ctx),
DataDir: utils.MakeDataDir(ctx),
DocRoot: ctx.GlobalString(utils.JSpathFlag.Name),
Client: client,
Preload: utils.MakeConsolePreloads(ctx),
Expand Down Expand Up @@ -135,7 +135,7 @@ func remoteConsole(ctx *cli.Context) error {
// for "geth attach" and "geth monitor" with no argument.
func dialRPC(endpoint string) (*rpc.Client, error) {
if endpoint == "" {
endpoint = node.DefaultIPCEndpoint()
endpoint = node.DefaultIPCEndpoint(clientIdentifier)
} else if strings.HasPrefix(endpoint, "rpc:") || strings.HasPrefix(endpoint, "ipc:") {
// Backwards compatibility with geth < 1.5 which required
// these prefixes.
Expand Down
4 changes: 2 additions & 2 deletions cmd/geth/dao_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,9 @@ func testDAOForkBlockNewChain(t *testing.T, testnet bool, genesis string, votes
geth.cmd.Wait()
}
// Retrieve the DAO config flag from the database
path := filepath.Join(datadir, "chaindata")
path := filepath.Join(datadir, "geth", "chaindata")
if testnet && genesis == "" {
path = filepath.Join(datadir, "testnet", "chaindata")
path = filepath.Join(datadir, "testnet", "geth", "chaindata")
}
db, err := ethdb.NewLDBDatabase(path, 0, 0)
if err != nil {
Expand Down
16 changes: 5 additions & 11 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/internal/debug"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
Expand All @@ -46,7 +45,7 @@ import (
)

const (
clientIdentifier = "Geth" // Client identifier to advertise over the network
clientIdentifier = "geth" // Client identifier to advertise over the network
)

var (
Expand Down Expand Up @@ -245,17 +244,15 @@ func initGenesis(ctx *cli.Context) error {
state.StartingNonce = 1048576 // (2**20)
}

chainDb, err := ethdb.NewLDBDatabase(filepath.Join(utils.MustMakeDataDir(ctx), "chaindata"), 0, 0)
if err != nil {
utils.Fatalf("could not open database: %v", err)
}
stack := makeFullNode(ctx)
chaindb := utils.MakeChainDatabase(ctx, stack)

genesisFile, err := os.Open(genesisPath)
if err != nil {
utils.Fatalf("failed to read genesis file: %v", err)
}

block, err := core.WriteGenesisBlock(chainDb, genesisFile)
block, err := core.WriteGenesisBlock(chaindb, genesisFile)
if err != nil {
utils.Fatalf("failed to write genesis block: %v", err)
}
Expand Down Expand Up @@ -296,9 +293,6 @@ func makeFullNode(ctx *cli.Context) *node.Node {
// it unlocks any requested accounts, and starts the RPC/IPC interfaces and the
// miner.
func startNode(ctx *cli.Context, stack *node.Node) {
// Report geth version
glog.V(logger.Info).Infof("instance: Geth/%s/%s/%s\n", utils.Version, runtime.Version(), runtime.GOOS)

// Start up the node itself
utils.StartNode(stack)

Expand Down Expand Up @@ -379,7 +373,7 @@ func gpubench(ctx *cli.Context) error {
}

func version(c *cli.Context) error {
fmt.Println(clientIdentifier)
fmt.Println(strings.Title(clientIdentifier))
fmt.Println("Version:", utils.Version)
if gitCommit != "" {
fmt.Println("Git Commit:", gitCommit)
Expand Down
2 changes: 1 addition & 1 deletion cmd/geth/monitorcmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import (
var (
monitorCommandAttachFlag = cli.StringFlag{
Name: "attach",
Value: node.DefaultIPCEndpoint(),
Value: node.DefaultIPCEndpoint(clientIdentifier),
Usage: "API endpoint to attach to",
}
monitorCommandRowsFlag = cli.IntFlag{
Expand Down
2 changes: 1 addition & 1 deletion cmd/gethrpctest/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func MakeSystemNode(privkey string, test *tests.BlockTest) (*node.Node, error) {
// Create a networkless protocol stack
stack, err := node.New(&node.Config{
UseLightweightKDF: true,
IPCPath: node.DefaultIPCEndpoint(),
IPCPath: node.DefaultIPCEndpoint(""),
HTTPHost: common.DefaultHTTPHost,
HTTPPort: common.DefaultHTTPPort,
HTTPModules: []string{"admin", "db", "eth", "debug", "miner", "net", "shh", "txpool", "personal", "web3"},
Expand Down
50 changes: 26 additions & 24 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,13 +396,14 @@ var (
}
)

// MustMakeDataDir retrieves the currently requested data directory, terminating
// MakeDataDir retrieves the currently requested data directory, terminating
// if none (or the empty string) is specified. If the node is starting a testnet,
// the a subdirectory of the specified datadir will be used.
func MustMakeDataDir(ctx *cli.Context) string {
func MakeDataDir(ctx *cli.Context) string {
if path := ctx.GlobalString(DataDirFlag.Name); path != "" {
// TODO: choose a different location outside of the regular datadir.
if ctx.GlobalBool(TestNetFlag.Name) {
return filepath.Join(path, "/testnet")
return filepath.Join(path, "testnet")
}
return path
}
Expand Down Expand Up @@ -447,16 +448,16 @@ func MakeNodeKey(ctx *cli.Context) *ecdsa.PrivateKey {
return key
}

// MakeNodeName creates a node name from a base set and the command line flags.
func MakeNodeName(client, version string, ctx *cli.Context) string {
name := common.MakeName(client, version)
// makeNodeUserIdent creates the user identifier from CLI flags.
func makeNodeUserIdent(ctx *cli.Context) string {
var comps []string
if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 {
name += "/" + identity
comps = append(comps, identity)
}
if ctx.GlobalBool(VMEnableJitFlag.Name) {
name += "/JIT"
comps = append(comps, "JIT")
}
return name
return strings.Join(comps, "/")
}

// MakeBootstrapNodes creates a list of bootstrap nodes from the command line
Expand Down Expand Up @@ -612,11 +613,13 @@ func MakeNode(ctx *cli.Context, name, gitCommit string) *node.Node {
}

config := &node.Config{
DataDir: MustMakeDataDir(ctx),
DataDir: MakeDataDir(ctx),
KeyStoreDir: ctx.GlobalString(KeyStoreDirFlag.Name),
UseLightweightKDF: ctx.GlobalBool(LightKDFFlag.Name),
PrivateKey: MakeNodeKey(ctx),
Name: MakeNodeName(name, vsn, ctx),
Name: name,
Version: vsn,
UserIdent: makeNodeUserIdent(ctx),
NoDiscovery: ctx.GlobalBool(NoDiscoverFlag.Name),
BootstrapNodes: MakeBootstrapNodes(ctx),
ListenAddr: MakeListenAddress(ctx),
Expand Down Expand Up @@ -674,7 +677,7 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {

ethConf := &eth.Config{
Etherbase: MakeEtherbase(stack.AccountManager(), ctx),
ChainConfig: MustMakeChainConfig(ctx),
ChainConfig: MakeChainConfig(ctx, stack),
FastSync: ctx.GlobalBool(FastSyncFlag.Name),
DatabaseCache: ctx.GlobalInt(CacheFlag.Name),
DatabaseHandles: MakeDatabaseHandles(),
Expand Down Expand Up @@ -748,16 +751,16 @@ func SetupNetwork(ctx *cli.Context) {
params.TargetGasLimit = common.String2Big(ctx.GlobalString(TargetGasLimitFlag.Name))
}

// MustMakeChainConfig reads the chain configuration from the database in ctx.Datadir.
func MustMakeChainConfig(ctx *cli.Context) *core.ChainConfig {
db := MakeChainDatabase(ctx)
// MakeChainConfig reads the chain configuration from the database in ctx.Datadir.
func MakeChainConfig(ctx *cli.Context, stack *node.Node) *core.ChainConfig {
db := MakeChainDatabase(ctx, stack)
defer db.Close()

return MustMakeChainConfigFromDb(ctx, db)
return MakeChainConfigFromDb(ctx, db)
}

// MustMakeChainConfigFromDb reads the chain configuration from the given database.
func MustMakeChainConfigFromDb(ctx *cli.Context, db ethdb.Database) *core.ChainConfig {
// MakeChainConfigFromDb reads the chain configuration from the given database.
func MakeChainConfigFromDb(ctx *cli.Context, db ethdb.Database) *core.ChainConfig {
// If the chain is already initialized, use any existing chain configs
config := new(core.ChainConfig)

Expand Down Expand Up @@ -800,32 +803,31 @@ func MustMakeChainConfigFromDb(ctx *cli.Context, db ethdb.Database) *core.ChainC
}

// MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
func MakeChainDatabase(ctx *cli.Context) ethdb.Database {
func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
var (
datadir = MustMakeDataDir(ctx)
cache = ctx.GlobalInt(CacheFlag.Name)
handles = MakeDatabaseHandles()
)

chainDb, err := ethdb.NewLDBDatabase(filepath.Join(datadir, "chaindata"), cache, handles)
chainDb, err := stack.OpenDatabase("chaindata", cache, handles)
if err != nil {
Fatalf("Could not open database: %v", err)
}
return chainDb
}

// MakeChain creates a chain manager from set command line flags.
func MakeChain(ctx *cli.Context) (chain *core.BlockChain, chainDb ethdb.Database) {
func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) {
var err error
chainDb = MakeChainDatabase(ctx)
chainDb = MakeChainDatabase(ctx, stack)

if ctx.GlobalBool(OlympicFlag.Name) {
_, err := core.WriteTestNetGenesisBlock(chainDb)
if err != nil {
glog.Fatalln(err)
}
}
chainConfig := MustMakeChainConfigFromDb(ctx, chainDb)
chainConfig := MakeChainConfigFromDb(ctx, chainDb)

pow := pow.PoW(core.FakePow{})
if !ctx.GlobalBool(FakePoWFlag.Name) {
Expand Down
18 changes: 9 additions & 9 deletions node/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,16 +85,16 @@ func (api *PrivateAdminAPI) StartRPC(host *string, port *rpc.HexNumber, cors *st

if host == nil {
h := common.DefaultHTTPHost
if api.node.httpHost != "" {
h = api.node.httpHost
if api.node.config.HTTPHost != "" {
h = api.node.config.HTTPHost
}
host = &h
}
if port == nil {
port = rpc.NewHexNumber(api.node.httpPort)
port = rpc.NewHexNumber(api.node.config.HTTPPort)
}
if cors == nil {
cors = &api.node.httpCors
cors = &api.node.config.HTTPCors
}

modules := api.node.httpWhitelist
Expand Down Expand Up @@ -134,19 +134,19 @@ func (api *PrivateAdminAPI) StartWS(host *string, port *rpc.HexNumber, allowedOr

if host == nil {
h := common.DefaultWSHost
if api.node.wsHost != "" {
h = api.node.wsHost
if api.node.config.WSHost != "" {
h = api.node.config.WSHost
}
host = &h
}
if port == nil {
port = rpc.NewHexNumber(api.node.wsPort)
port = rpc.NewHexNumber(api.node.config.WSPort)
}
if allowedOrigins == nil {
allowedOrigins = &api.node.wsOrigins
allowedOrigins = &api.node.config.WSOrigins
}

modules := api.node.wsWhitelist
modules := api.node.config.WSModules
if apis != nil {
modules = nil
for _, m := range strings.Split(*apis, ",") {
Expand Down
Loading

0 comments on commit eeb322a

Please sign in to comment.