Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
44bc2e80
Commit
44bc2e80
authored
Sep 29, 2016
by
Felix Lange
Committed by
GitHub
Sep 29, 2016
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2914 from fjl/node-coinhabit
cmd/utils, node: make datadir reusable for bzzd
parents
4e8cec05
b42a5b11
Changes
19
Show whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
470 additions
and
239 deletions
+470
-239
chaincmd.go
cmd/geth/chaincmd.go
+35
-16
consolecmd.go
cmd/geth/consolecmd.go
+2
-2
dao_test.go
cmd/geth/dao_test.go
+2
-2
main.go
cmd/geth/main.go
+5
-11
monitorcmd.go
cmd/geth/monitorcmd.go
+1
-1
main.go
cmd/gethrpctest/main.go
+5
-6
customflags.go
cmd/utils/customflags.go
+12
-2
flags.go
cmd/utils/flags.go
+34
-32
path.go
common/path.go
+0
-27
database.go
ethdb/database.go
+5
-0
api.go
node/api.go
+11
-11
config.go
node/config.go
+108
-25
config_test.go
node/config_test.go
+20
-22
defaults.go
node/defaults.go
+14
-2
doc.go
node/doc.go
+90
-0
node.go
node/node.go
+112
-63
service.go
node/service.go
+10
-9
service_test.go
node/service_test.go
+3
-3
nat.go
p2p/nat/nat.go
+1
-5
No files found.
cmd/geth/chaincmd.go
View file @
44bc2e80
...
@@ -79,7 +79,8 @@ func importChain(ctx *cli.Context) error {
...
@@ -79,7 +79,8 @@ func importChain(ctx *cli.Context) error {
if
ctx
.
GlobalBool
(
utils
.
TestNetFlag
.
Name
)
{
if
ctx
.
GlobalBool
(
utils
.
TestNetFlag
.
Name
)
{
state
.
StartingNonce
=
1048576
// (2**20)
state
.
StartingNonce
=
1048576
// (2**20)
}
}
chain
,
chainDb
:=
utils
.
MakeChain
(
ctx
)
stack
:=
makeFullNode
(
ctx
)
chain
,
chainDb
:=
utils
.
MakeChain
(
ctx
,
stack
)
start
:=
time
.
Now
()
start
:=
time
.
Now
()
err
:=
utils
.
ImportChain
(
chain
,
ctx
.
Args
()
.
First
())
err
:=
utils
.
ImportChain
(
chain
,
ctx
.
Args
()
.
First
())
chainDb
.
Close
()
chainDb
.
Close
()
...
@@ -94,7 +95,8 @@ func exportChain(ctx *cli.Context) error {
...
@@ -94,7 +95,8 @@ func exportChain(ctx *cli.Context) error {
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
.
MakeChain
(
ctx
)
stack
:=
makeFullNode
(
ctx
)
chain
,
_
:=
utils
.
MakeChain
(
ctx
,
stack
)
start
:=
time
.
Now
()
start
:=
time
.
Now
()
var
err
error
var
err
error
...
@@ -122,20 +124,25 @@ func exportChain(ctx *cli.Context) error {
...
@@ -122,20 +124,25 @@ func exportChain(ctx *cli.Context) error {
}
}
func
removeDB
(
ctx
*
cli
.
Context
)
error
{
func
removeDB
(
ctx
*
cli
.
Context
)
error
{
confirm
,
err
:=
console
.
Stdin
.
PromptConfirm
(
"Remove local database?"
)
stack
:=
utils
.
MakeNode
(
ctx
,
clientIdentifier
,
gitCommit
)
if
err
!=
nil
{
dbdir
:=
stack
.
ResolvePath
(
"chaindata"
)
utils
.
Fatalf
(
"%v"
,
err
)
if
!
common
.
FileExist
(
dbdir
)
{
fmt
.
Println
(
dbdir
,
"does not exist"
)
return
nil
}
}
if
confirm
{
fmt
.
Println
(
dbdir
)
fmt
.
Println
(
"Removing chaindata..."
)
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
()
start
:=
time
.
Now
()
os
.
RemoveAll
(
dbdir
)
os
.
RemoveAll
(
filepath
.
Join
(
ctx
.
GlobalString
(
utils
.
DataDirFlag
.
Name
),
"chaindata"
))
fmt
.
Printf
(
"Removed in %v
\n
"
,
time
.
Since
(
start
))
fmt
.
Printf
(
"Removed in %v
\n
"
,
time
.
Since
(
start
))
}
else
{
fmt
.
Println
(
"Operation aborted"
)
}
}
return
nil
return
nil
}
}
...
@@ -143,7 +150,8 @@ func removeDB(ctx *cli.Context) error {
...
@@ -143,7 +150,8 @@ func removeDB(ctx *cli.Context) error {
func
upgradeDB
(
ctx
*
cli
.
Context
)
error
{
func
upgradeDB
(
ctx
*
cli
.
Context
)
error
{
glog
.
Infoln
(
"Upgrading blockchain database"
)
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
)
bcVersion
:=
core
.
GetBlockChainVersion
(
chainDb
)
if
bcVersion
==
0
{
if
bcVersion
==
0
{
bcVersion
=
core
.
BlockChainVersion
bcVersion
=
core
.
BlockChainVersion
...
@@ -156,10 +164,12 @@ func upgradeDB(ctx *cli.Context) error {
...
@@ -156,10 +164,12 @@ func upgradeDB(ctx *cli.Context) error {
utils
.
Fatalf
(
"Unable to export chain for reimport %s"
,
err
)
utils
.
Fatalf
(
"Unable to export chain for reimport %s"
,
err
)
}
}
chainDb
.
Close
()
chainDb
.
Close
()
os
.
RemoveAll
(
filepath
.
Join
(
ctx
.
GlobalString
(
utils
.
DataDirFlag
.
Name
),
"chaindata"
))
if
dir
:=
dbDirectory
(
chainDb
);
dir
!=
""
{
os
.
RemoveAll
(
dir
)
}
// Import the chain file.
// Import the chain file.
chain
,
chainDb
=
utils
.
MakeChain
(
ctx
)
chain
,
chainDb
=
utils
.
MakeChain
(
ctx
,
stack
)
core
.
WriteBlockChainVersion
(
chainDb
,
core
.
BlockChainVersion
)
core
.
WriteBlockChainVersion
(
chainDb
,
core
.
BlockChainVersion
)
err
:=
utils
.
ImportChain
(
chain
,
exportFile
)
err
:=
utils
.
ImportChain
(
chain
,
exportFile
)
chainDb
.
Close
()
chainDb
.
Close
()
...
@@ -172,8 +182,17 @@ func upgradeDB(ctx *cli.Context) error {
...
@@ -172,8 +182,17 @@ func upgradeDB(ctx *cli.Context) error {
return
nil
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
{
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
()
{
for
_
,
arg
:=
range
ctx
.
Args
()
{
var
block
*
types
.
Block
var
block
*
types
.
Block
if
hashish
(
arg
)
{
if
hashish
(
arg
)
{
...
...
cmd/geth/consolecmd.go
View file @
44bc2e80
...
@@ -107,7 +107,7 @@ func remoteConsole(ctx *cli.Context) error {
...
@@ -107,7 +107,7 @@ func remoteConsole(ctx *cli.Context) error {
utils
.
Fatalf
(
"Unable to attach to remote geth: %v"
,
err
)
utils
.
Fatalf
(
"Unable to attach to remote geth: %v"
,
err
)
}
}
config
:=
console
.
Config
{
config
:=
console
.
Config
{
DataDir
:
utils
.
M
ustM
akeDataDir
(
ctx
),
DataDir
:
utils
.
MakeDataDir
(
ctx
),
DocRoot
:
ctx
.
GlobalString
(
utils
.
JSpathFlag
.
Name
),
DocRoot
:
ctx
.
GlobalString
(
utils
.
JSpathFlag
.
Name
),
Client
:
client
,
Client
:
client
,
Preload
:
utils
.
MakeConsolePreloads
(
ctx
),
Preload
:
utils
.
MakeConsolePreloads
(
ctx
),
...
@@ -135,7 +135,7 @@ func remoteConsole(ctx *cli.Context) error {
...
@@ -135,7 +135,7 @@ func remoteConsole(ctx *cli.Context) error {
// for "geth attach" and "geth monitor" with no argument.
// for "geth attach" and "geth monitor" with no argument.
func
dialRPC
(
endpoint
string
)
(
*
rpc
.
Client
,
error
)
{
func
dialRPC
(
endpoint
string
)
(
*
rpc
.
Client
,
error
)
{
if
endpoint
==
""
{
if
endpoint
==
""
{
endpoint
=
node
.
DefaultIPCEndpoint
()
endpoint
=
node
.
DefaultIPCEndpoint
(
clientIdentifier
)
}
else
if
strings
.
HasPrefix
(
endpoint
,
"rpc:"
)
||
strings
.
HasPrefix
(
endpoint
,
"ipc:"
)
{
}
else
if
strings
.
HasPrefix
(
endpoint
,
"rpc:"
)
||
strings
.
HasPrefix
(
endpoint
,
"ipc:"
)
{
// Backwards compatibility with geth < 1.5 which required
// Backwards compatibility with geth < 1.5 which required
// these prefixes.
// these prefixes.
...
...
cmd/geth/dao_test.go
View file @
44bc2e80
...
@@ -195,9 +195,9 @@ func testDAOForkBlockNewChain(t *testing.T, testnet bool, genesis string, votes
...
@@ -195,9 +195,9 @@ func testDAOForkBlockNewChain(t *testing.T, testnet bool, genesis string, votes
geth
.
cmd
.
Wait
()
geth
.
cmd
.
Wait
()
}
}
// Retrieve the DAO config flag from the database
// Retrieve the DAO config flag from the database
path
:=
filepath
.
Join
(
datadir
,
"chaindata"
)
path
:=
filepath
.
Join
(
datadir
,
"
geth"
,
"
chaindata"
)
if
testnet
&&
genesis
==
""
{
if
testnet
&&
genesis
==
""
{
path
=
filepath
.
Join
(
datadir
,
"testnet"
,
"chaindata"
)
path
=
filepath
.
Join
(
datadir
,
"testnet"
,
"
geth"
,
"
chaindata"
)
}
}
db
,
err
:=
ethdb
.
NewLDBDatabase
(
path
,
0
,
0
)
db
,
err
:=
ethdb
.
NewLDBDatabase
(
path
,
0
,
0
)
if
err
!=
nil
{
if
err
!=
nil
{
...
...
cmd/geth/main.go
View file @
44bc2e80
...
@@ -36,7 +36,6 @@ import (
...
@@ -36,7 +36,6 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/internal/debug"
"github.com/ethereum/go-ethereum/internal/debug"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/logger/glog"
...
@@ -46,7 +45,7 @@ import (
...
@@ -46,7 +45,7 @@ import (
)
)
const
(
const
(
clientIdentifier
=
"
G
eth"
// Client identifier to advertise over the network
clientIdentifier
=
"
g
eth"
// Client identifier to advertise over the network
)
)
var
(
var
(
...
@@ -245,17 +244,15 @@ func initGenesis(ctx *cli.Context) error {
...
@@ -245,17 +244,15 @@ func initGenesis(ctx *cli.Context) error {
state
.
StartingNonce
=
1048576
// (2**20)
state
.
StartingNonce
=
1048576
// (2**20)
}
}
chainDb
,
err
:=
ethdb
.
NewLDBDatabase
(
filepath
.
Join
(
utils
.
MustMakeDataDir
(
ctx
),
"chaindata"
),
0
,
0
)
stack
:=
makeFullNode
(
ctx
)
if
err
!=
nil
{
chaindb
:=
utils
.
MakeChainDatabase
(
ctx
,
stack
)
utils
.
Fatalf
(
"could not open database: %v"
,
err
)
}
genesisFile
,
err
:=
os
.
Open
(
genesisPath
)
genesisFile
,
err
:=
os
.
Open
(
genesisPath
)
if
err
!=
nil
{
if
err
!=
nil
{
utils
.
Fatalf
(
"failed to read genesis file: %v"
,
err
)
utils
.
Fatalf
(
"failed to read genesis file: %v"
,
err
)
}
}
block
,
err
:=
core
.
WriteGenesisBlock
(
chain
D
b
,
genesisFile
)
block
,
err
:=
core
.
WriteGenesisBlock
(
chain
d
b
,
genesisFile
)
if
err
!=
nil
{
if
err
!=
nil
{
utils
.
Fatalf
(
"failed to write genesis block: %v"
,
err
)
utils
.
Fatalf
(
"failed to write genesis block: %v"
,
err
)
}
}
...
@@ -296,9 +293,6 @@ func makeFullNode(ctx *cli.Context) *node.Node {
...
@@ -296,9 +293,6 @@ func makeFullNode(ctx *cli.Context) *node.Node {
// it unlocks any requested accounts, and starts the RPC/IPC interfaces and the
// it unlocks any requested accounts, and starts the RPC/IPC interfaces and the
// miner.
// miner.
func
startNode
(
ctx
*
cli
.
Context
,
stack
*
node
.
Node
)
{
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
// Start up the node itself
utils
.
StartNode
(
stack
)
utils
.
StartNode
(
stack
)
...
@@ -379,7 +373,7 @@ func gpubench(ctx *cli.Context) error {
...
@@ -379,7 +373,7 @@ func gpubench(ctx *cli.Context) error {
}
}
func
version
(
c
*
cli
.
Context
)
error
{
func
version
(
c
*
cli
.
Context
)
error
{
fmt
.
Println
(
clientIdentifier
)
fmt
.
Println
(
strings
.
Title
(
clientIdentifier
)
)
fmt
.
Println
(
"Version:"
,
utils
.
Version
)
fmt
.
Println
(
"Version:"
,
utils
.
Version
)
if
gitCommit
!=
""
{
if
gitCommit
!=
""
{
fmt
.
Println
(
"Git Commit:"
,
gitCommit
)
fmt
.
Println
(
"Git Commit:"
,
gitCommit
)
...
...
cmd/geth/monitorcmd.go
View file @
44bc2e80
...
@@ -35,7 +35,7 @@ import (
...
@@ -35,7 +35,7 @@ import (
var
(
var
(
monitorCommandAttachFlag
=
cli
.
StringFlag
{
monitorCommandAttachFlag
=
cli
.
StringFlag
{
Name
:
"attach"
,
Name
:
"attach"
,
Value
:
node
.
DefaultIPCEndpoint
(),
Value
:
node
.
DefaultIPCEndpoint
(
clientIdentifier
),
Usage
:
"API endpoint to attach to"
,
Usage
:
"API endpoint to attach to"
,
}
}
monitorCommandRowsFlag
=
cli
.
IntFlag
{
monitorCommandRowsFlag
=
cli
.
IntFlag
{
...
...
cmd/gethrpctest/main.go
View file @
44bc2e80
...
@@ -23,7 +23,6 @@ import (
...
@@ -23,7 +23,6 @@ import (
"os"
"os"
"os/signal"
"os/signal"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth"
...
@@ -88,12 +87,12 @@ func MakeSystemNode(privkey string, test *tests.BlockTest) (*node.Node, error) {
...
@@ -88,12 +87,12 @@ func MakeSystemNode(privkey string, test *tests.BlockTest) (*node.Node, error) {
// Create a networkless protocol stack
// Create a networkless protocol stack
stack
,
err
:=
node
.
New
(
&
node
.
Config
{
stack
,
err
:=
node
.
New
(
&
node
.
Config
{
UseLightweightKDF
:
true
,
UseLightweightKDF
:
true
,
IPCPath
:
node
.
DefaultIPCEndpoint
(),
IPCPath
:
node
.
DefaultIPCEndpoint
(
""
),
HTTPHost
:
common
.
DefaultHTTPHost
,
HTTPHost
:
node
.
DefaultHTTPHost
,
HTTPPort
:
common
.
DefaultHTTPPort
,
HTTPPort
:
node
.
DefaultHTTPPort
,
HTTPModules
:
[]
string
{
"admin"
,
"db"
,
"eth"
,
"debug"
,
"miner"
,
"net"
,
"shh"
,
"txpool"
,
"personal"
,
"web3"
},
HTTPModules
:
[]
string
{
"admin"
,
"db"
,
"eth"
,
"debug"
,
"miner"
,
"net"
,
"shh"
,
"txpool"
,
"personal"
,
"web3"
},
WSHost
:
common
.
DefaultWSHost
,
WSHost
:
node
.
DefaultWSHost
,
WSPort
:
common
.
DefaultWSPort
,
WSPort
:
node
.
DefaultWSPort
,
WSModules
:
[]
string
{
"admin"
,
"db"
,
"eth"
,
"debug"
,
"miner"
,
"net"
,
"shh"
,
"txpool"
,
"personal"
,
"web3"
},
WSModules
:
[]
string
{
"admin"
,
"db"
,
"eth"
,
"debug"
,
"miner"
,
"net"
,
"shh"
,
"txpool"
,
"personal"
,
"web3"
},
NoDiscovery
:
true
,
NoDiscovery
:
true
,
})
})
...
...
cmd/utils/customflags.go
View file @
44bc2e80
...
@@ -137,9 +137,19 @@ func (self *DirectoryFlag) Set(value string) {
...
@@ -137,9 +137,19 @@ func (self *DirectoryFlag) Set(value string) {
// Note, it has limitations, e.g. ~someuser/tmp will not be expanded
// Note, it has limitations, e.g. ~someuser/tmp will not be expanded
func
expandPath
(
p
string
)
string
{
func
expandPath
(
p
string
)
string
{
if
strings
.
HasPrefix
(
p
,
"~/"
)
||
strings
.
HasPrefix
(
p
,
"~
\\
"
)
{
if
strings
.
HasPrefix
(
p
,
"~/"
)
||
strings
.
HasPrefix
(
p
,
"~
\\
"
)
{
if
user
,
err
:=
user
.
Current
();
err
==
nil
{
if
home
:=
homeDir
();
home
!=
""
{
p
=
user
.
HomeDir
+
p
[
1
:
]
p
=
home
+
p
[
1
:
]
}
}
}
}
return
path
.
Clean
(
os
.
ExpandEnv
(
p
))
return
path
.
Clean
(
os
.
ExpandEnv
(
p
))
}
}
func
homeDir
()
string
{
if
home
:=
os
.
Getenv
(
"HOME"
);
home
!=
""
{
return
home
}
if
usr
,
err
:=
user
.
Current
();
err
==
nil
{
return
usr
.
HomeDir
}
return
""
}
cmd/utils/flags.go
View file @
44bc2e80
...
@@ -105,7 +105,7 @@ var (
...
@@ -105,7 +105,7 @@ var (
DataDirFlag
=
DirectoryFlag
{
DataDirFlag
=
DirectoryFlag
{
Name
:
"datadir"
,
Name
:
"datadir"
,
Usage
:
"Data directory for the databases and keystore"
,
Usage
:
"Data directory for the databases and keystore"
,
Value
:
DirectoryString
{
common
.
DefaultDataDir
()},
Value
:
DirectoryString
{
node
.
DefaultDataDir
()},
}
}
KeyStoreDirFlag
=
DirectoryFlag
{
KeyStoreDirFlag
=
DirectoryFlag
{
Name
:
"keystore"
,
Name
:
"keystore"
,
...
@@ -139,7 +139,7 @@ var (
...
@@ -139,7 +139,7 @@ var (
DocRootFlag
=
DirectoryFlag
{
DocRootFlag
=
DirectoryFlag
{
Name
:
"docroot"
,
Name
:
"docroot"
,
Usage
:
"Document Root for HTTPClient file scheme"
,
Usage
:
"Document Root for HTTPClient file scheme"
,
Value
:
DirectoryString
{
common
.
H
omeDir
()},
Value
:
DirectoryString
{
h
omeDir
()},
}
}
CacheFlag
=
cli
.
IntFlag
{
CacheFlag
=
cli
.
IntFlag
{
Name
:
"cache"
,
Name
:
"cache"
,
...
@@ -245,12 +245,12 @@ var (
...
@@ -245,12 +245,12 @@ var (
RPCListenAddrFlag
=
cli
.
StringFlag
{
RPCListenAddrFlag
=
cli
.
StringFlag
{
Name
:
"rpcaddr"
,
Name
:
"rpcaddr"
,
Usage
:
"HTTP-RPC server listening interface"
,
Usage
:
"HTTP-RPC server listening interface"
,
Value
:
common
.
DefaultHTTPHost
,
Value
:
node
.
DefaultHTTPHost
,
}
}
RPCPortFlag
=
cli
.
IntFlag
{
RPCPortFlag
=
cli
.
IntFlag
{
Name
:
"rpcport"
,
Name
:
"rpcport"
,
Usage
:
"HTTP-RPC server listening port"
,
Usage
:
"HTTP-RPC server listening port"
,
Value
:
common
.
DefaultHTTPPort
,
Value
:
node
.
DefaultHTTPPort
,
}
}
RPCCORSDomainFlag
=
cli
.
StringFlag
{
RPCCORSDomainFlag
=
cli
.
StringFlag
{
Name
:
"rpccorsdomain"
,
Name
:
"rpccorsdomain"
,
...
@@ -268,13 +268,13 @@ var (
...
@@ -268,13 +268,13 @@ var (
}
}
IPCApiFlag
=
cli
.
StringFlag
{
IPCApiFlag
=
cli
.
StringFlag
{
Name
:
"ipcapi"
,
Name
:
"ipcapi"
,
Usage
:
"API
'
s offered over the IPC-RPC interface"
,
Usage
:
"APIs offered over the IPC-RPC interface"
,
Value
:
rpc
.
DefaultIPCApis
,
Value
:
rpc
.
DefaultIPCApis
,
}
}
IPCPathFlag
=
DirectoryFlag
{
IPCPathFlag
=
DirectoryFlag
{
Name
:
"ipcpath"
,
Name
:
"ipcpath"
,
Usage
:
"Filename for IPC socket/pipe within the datadir (explicit paths escape it)"
,
Usage
:
"Filename for IPC socket/pipe within the datadir (explicit paths escape it)"
,
Value
:
DirectoryString
{
common
.
DefaultIPCSocket
},
Value
:
DirectoryString
{
"geth.ipc"
},
}
}
WSEnabledFlag
=
cli
.
BoolFlag
{
WSEnabledFlag
=
cli
.
BoolFlag
{
Name
:
"ws"
,
Name
:
"ws"
,
...
@@ -283,12 +283,12 @@ var (
...
@@ -283,12 +283,12 @@ var (
WSListenAddrFlag
=
cli
.
StringFlag
{
WSListenAddrFlag
=
cli
.
StringFlag
{
Name
:
"wsaddr"
,
Name
:
"wsaddr"
,
Usage
:
"WS-RPC server listening interface"
,
Usage
:
"WS-RPC server listening interface"
,
Value
:
common
.
DefaultWSHost
,
Value
:
node
.
DefaultWSHost
,
}
}
WSPortFlag
=
cli
.
IntFlag
{
WSPortFlag
=
cli
.
IntFlag
{
Name
:
"wsport"
,
Name
:
"wsport"
,
Usage
:
"WS-RPC server listening port"
,
Usage
:
"WS-RPC server listening port"
,
Value
:
common
.
DefaultWSPort
,
Value
:
node
.
DefaultWSPort
,
}
}
WSApiFlag
=
cli
.
StringFlag
{
WSApiFlag
=
cli
.
StringFlag
{
Name
:
"wsapi"
,
Name
:
"wsapi"
,
...
@@ -396,13 +396,14 @@ var (
...
@@ -396,13 +396,14 @@ var (
}
}
)
)
// M
ustM
akeDataDir 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,
// 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.
// the a subdirectory of the specified datadir will be used.
func
M
ustM
akeDataDir
(
ctx
*
cli
.
Context
)
string
{
func
MakeDataDir
(
ctx
*
cli
.
Context
)
string
{
if
path
:=
ctx
.
GlobalString
(
DataDirFlag
.
Name
);
path
!=
""
{
if
path
:=
ctx
.
GlobalString
(
DataDirFlag
.
Name
);
path
!=
""
{
// TODO: choose a different location outside of the regular datadir.
if
ctx
.
GlobalBool
(
TestNetFlag
.
Name
)
{
if
ctx
.
GlobalBool
(
TestNetFlag
.
Name
)
{
return
filepath
.
Join
(
path
,
"
/
testnet"
)
return
filepath
.
Join
(
path
,
"testnet"
)
}
}
return
path
return
path
}
}
...
@@ -447,16 +448,16 @@ func MakeNodeKey(ctx *cli.Context) *ecdsa.PrivateKey {
...
@@ -447,16 +448,16 @@ func MakeNodeKey(ctx *cli.Context) *ecdsa.PrivateKey {
return
key
return
key
}
}
//
MakeNodeName creates a node name from a base set and the command line
flags.
//
makeNodeUserIdent creates the user identifier from CLI
flags.
func
MakeNodeName
(
client
,
version
string
,
ctx
*
cli
.
Context
)
string
{
func
makeNodeUserIdent
(
ctx
*
cli
.
Context
)
string
{
name
:=
common
.
MakeName
(
client
,
version
)
var
comps
[]
string
if
identity
:=
ctx
.
GlobalString
(
IdentityFlag
.
Name
);
len
(
identity
)
>
0
{
if
identity
:=
ctx
.
GlobalString
(
IdentityFlag
.
Name
);
len
(
identity
)
>
0
{
name
+=
"/"
+
identity
comps
=
append
(
comps
,
identity
)
}
}
if
ctx
.
GlobalBool
(
VMEnableJitFlag
.
Name
)
{
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
// MakeBootstrapNodes creates a list of bootstrap nodes from the command line
...
@@ -612,11 +613,13 @@ func MakeNode(ctx *cli.Context, name, gitCommit string) *node.Node {
...
@@ -612,11 +613,13 @@ func MakeNode(ctx *cli.Context, name, gitCommit string) *node.Node {
}
}
config
:=
&
node
.
Config
{
config
:=
&
node
.
Config
{
DataDir
:
M
ustM
akeDataDir
(
ctx
),
DataDir
:
MakeDataDir
(
ctx
),
KeyStoreDir
:
ctx
.
GlobalString
(
KeyStoreDirFlag
.
Name
),
KeyStoreDir
:
ctx
.
GlobalString
(
KeyStoreDirFlag
.
Name
),
UseLightweightKDF
:
ctx
.
GlobalBool
(
LightKDFFlag
.
Name
),
UseLightweightKDF
:
ctx
.
GlobalBool
(
LightKDFFlag
.
Name
),
PrivateKey
:
MakeNodeKey
(
ctx
),
PrivateKey
:
MakeNodeKey
(
ctx
),
Name
:
MakeNodeName
(
name
,
vsn
,
ctx
),
Name
:
name
,
Version
:
vsn
,
UserIdent
:
makeNodeUserIdent
(
ctx
),
NoDiscovery
:
ctx
.
GlobalBool
(
NoDiscoverFlag
.
Name
),
NoDiscovery
:
ctx
.
GlobalBool
(
NoDiscoverFlag
.
Name
),
BootstrapNodes
:
MakeBootstrapNodes
(
ctx
),
BootstrapNodes
:
MakeBootstrapNodes
(
ctx
),
ListenAddr
:
MakeListenAddress
(
ctx
),
ListenAddr
:
MakeListenAddress
(
ctx
),
...
@@ -674,7 +677,7 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {
...
@@ -674,7 +677,7 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {
ethConf
:=
&
eth
.
Config
{
ethConf
:=
&
eth
.
Config
{
Etherbase
:
MakeEtherbase
(
stack
.
AccountManager
(),
ctx
),
Etherbase
:
MakeEtherbase
(
stack
.
AccountManager
(),
ctx
),
ChainConfig
:
M
ustMakeChainConfig
(
ctx
),
ChainConfig
:
M
akeChainConfig
(
ctx
,
stack
),
FastSync
:
ctx
.
GlobalBool
(
FastSyncFlag
.
Name
),
FastSync
:
ctx
.
GlobalBool
(
FastSyncFlag
.
Name
),
DatabaseCache
:
ctx
.
GlobalInt
(
CacheFlag
.
Name
),
DatabaseCache
:
ctx
.
GlobalInt
(
CacheFlag
.
Name
),
DatabaseHandles
:
MakeDatabaseHandles
(),
DatabaseHandles
:
MakeDatabaseHandles
(),
...
@@ -748,16 +751,16 @@ func SetupNetwork(ctx *cli.Context) {
...
@@ -748,16 +751,16 @@ func SetupNetwork(ctx *cli.Context) {
params
.
TargetGasLimit
=
common
.
String2Big
(
ctx
.
GlobalString
(
TargetGasLimitFlag
.
Name
))
params
.
TargetGasLimit
=
common
.
String2Big
(
ctx
.
GlobalString
(
TargetGasLimitFlag
.
Name
))
}
}
// M
ustM
akeChainConfig reads the chain configuration from the database in ctx.Datadir.
// MakeChainConfig reads the chain configuration from the database in ctx.Datadir.
func
M
ustMakeChainConfig
(
ctx
*
cli
.
Context
)
*
core
.
ChainConfig
{
func
M
akeChainConfig
(
ctx
*
cli
.
Context
,
stack
*
node
.
Node
)
*
core
.
ChainConfig
{
db
:=
MakeChainDatabase
(
ctx
)
db
:=
MakeChainDatabase
(
ctx
,
stack
)
defer
db
.
Close
()
defer
db
.
Close
()
return
M
ustM
akeChainConfigFromDb
(
ctx
,
db
)
return
MakeChainConfigFromDb
(
ctx
,
db
)
}
}
// M
ustM
akeChainConfigFromDb reads the chain configuration from the given database.
// MakeChainConfigFromDb reads the chain configuration from the given database.
func
M
ustM
akeChainConfigFromDb
(
ctx
*
cli
.
Context
,
db
ethdb
.
Database
)
*
core
.
ChainConfig
{
func
MakeChainConfigFromDb
(
ctx
*
cli
.
Context
,
db
ethdb
.
Database
)
*
core
.
ChainConfig
{
// If the chain is already initialized, use any existing chain configs
// If the chain is already initialized, use any existing chain configs
config
:=
new
(
core
.
ChainConfig
)
config
:=
new
(
core
.
ChainConfig
)
...
@@ -800,14 +803,13 @@ func MustMakeChainConfigFromDb(ctx *cli.Context, db ethdb.Database) *core.ChainC
...
@@ -800,14 +803,13 @@ 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.
// 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
(
var
(
datadir
=
MustMakeDataDir
(
ctx
)
cache
=
ctx
.
GlobalInt
(
CacheFlag
.
Name
)
cache
=
ctx
.
GlobalInt
(
CacheFlag
.
Name
)
handles
=
MakeDatabaseHandles
()
handles
=
MakeDatabaseHandles
()
)
)
chainDb
,
err
:=
ethdb
.
NewLDBDatabase
(
filepath
.
Join
(
datadir
,
"chaindata"
)
,
cache
,
handles
)
chainDb
,
err
:=
stack
.
OpenDatabase
(
"chaindata"
,
cache
,
handles
)
if
err
!=
nil
{
if
err
!=
nil
{
Fatalf
(
"Could not open database: %v"
,
err
)
Fatalf
(
"Could not open database: %v"
,
err
)
}
}
...
@@ -815,9 +817,9 @@ func MakeChainDatabase(ctx *cli.Context) ethdb.Database {
...
@@ -815,9 +817,9 @@ func MakeChainDatabase(ctx *cli.Context) ethdb.Database {
}
}
// 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
)
(
chain
*
core
.
BlockChain
,
chainDb
ethdb
.
Database
)
{
func
MakeChain
(
ctx
*
cli
.
Context
,
stack
*
node
.
Node
)
(
chain
*
core
.
BlockChain
,
chainDb
ethdb
.
Database
)
{
var
err
error
var
err
error
chainDb
=
MakeChainDatabase
(
ctx
)
chainDb
=
MakeChainDatabase
(
ctx
,
stack
)
if
ctx
.
GlobalBool
(
OlympicFlag
.
Name
)
{
if
ctx
.
GlobalBool
(
OlympicFlag
.
Name
)
{
_
,
err
:=
core
.
WriteTestNetGenesisBlock
(
chainDb
)
_
,
err
:=
core
.
WriteTestNetGenesisBlock
(
chainDb
)
...
@@ -825,7 +827,7 @@ func MakeChain(ctx *cli.Context) (chain *core.BlockChain, chainDb ethdb.Database
...
@@ -825,7 +827,7 @@ func MakeChain(ctx *cli.Context) (chain *core.BlockChain, chainDb ethdb.Database
glog
.
Fatalln
(
err
)
glog
.
Fatalln
(
err
)
}
}
}
}
chainConfig
:=
M
ustM
akeChainConfigFromDb
(
ctx
,
chainDb
)
chainConfig
:=
MakeChainConfigFromDb
(
ctx
,
chainDb
)
pow
:=
pow
.
PoW
(
core
.
FakePow
{})
pow
:=
pow
.
PoW
(
core
.
FakePow
{})
if
!
ctx
.
GlobalBool
(
FakePoWFlag
.
Name
)
{
if
!
ctx
.
GlobalBool
(
FakePoWFlag
.
Name
)
{
...
...
common/path.go
View file @
44bc2e80
...
@@ -19,10 +19,8 @@ package common
...
@@ -19,10 +19,8 @@ package common
import
(
import
(
"fmt"
"fmt"
"os"
"os"
"os/user"
"path/filepath"
"path/filepath"
"runtime"
"runtime"
"strings"
)
)
// MakeName creates a node name that follows the ethereum convention
// MakeName creates a node name that follows the ethereum convention
...
@@ -32,21 +30,6 @@ func MakeName(name, version string) string {
...
@@ -32,21 +30,6 @@ func MakeName(name, version string) string {
return
fmt
.
Sprintf
(
"%s/v%s/%s/%s"
,
name
,
version
,
runtime
.
GOOS
,
runtime
.
Version
())
return
fmt
.
Sprintf
(
"%s/v%s/%s/%s"
,
name
,
version
,
runtime
.
GOOS
,
runtime
.
Version
())
}
}
func
ExpandHomePath
(
p
string
)
(
path
string
)
{
path
=
p
sep
:=
string
(
os
.
PathSeparator
)
// Check in case of paths like "/something/~/something/"
if
len
(
p
)
>
1
&&
p
[
:
1
+
len
(
sep
)]
==
"~"
+
sep
{
usr
,
_
:=
user
.
Current
()
dir
:=
usr
.
HomeDir
path
=
strings
.
Replace
(
p
,
"~"
,
dir
,
1
)
}
return
}
func
FileExist
(
filePath
string
)
bool
{
func
FileExist
(
filePath
string
)
bool
{
_
,
err
:=
os
.
Stat
(
filePath
)
_
,
err
:=
os
.
Stat
(
filePath
)
if
err
!=
nil
&&
os
.
IsNotExist
(
err
)
{
if
err
!=
nil
&&
os
.
IsNotExist
(
err
)
{
...
@@ -62,13 +45,3 @@ func AbsolutePath(Datadir string, filename string) string {
...
@@ -62,13 +45,3 @@ func AbsolutePath(Datadir string, filename string) string {
}
}
return
filepath
.
Join
(
Datadir
,
filename
)
return
filepath
.
Join
(
Datadir
,
filename
)
}
}
func
HomeDir
()
string
{
if
home
:=
os
.
Getenv
(
"HOME"
);
home
!=
""
{
return
home
}
if
usr
,
err
:=
user
.
Current
();
err
==
nil
{
return
usr
.
HomeDir
}
return
""
}
ethdb/database.go
View file @
44bc2e80
...
@@ -100,6 +100,11 @@ func NewLDBDatabase(file string, cache int, handles int) (*LDBDatabase, error) {
...
@@ -100,6 +100,11 @@ func NewLDBDatabase(file string, cache int, handles int) (*LDBDatabase, error) {
},
nil
},
nil
}
}
// 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
// Put puts the given key / value to the queue
func
(
self
*
LDBDatabase
)
Put
(
key
[]
byte
,
value
[]
byte
)
error
{
func
(
self
*
LDBDatabase
)
Put
(
key
[]
byte
,
value
[]
byte
)
error
{
// Measure the database put latency, if requested
// Measure the database put latency, if requested
...
...
node/api.go
View file @
44bc2e80
...
@@ -84,17 +84,17 @@ func (api *PrivateAdminAPI) StartRPC(host *string, port *rpc.HexNumber, cors *st
...
@@ -84,17 +84,17 @@ func (api *PrivateAdminAPI) StartRPC(host *string, port *rpc.HexNumber, cors *st
}
}
if
host
==
nil
{
if
host
==
nil
{
h
:=
common
.
DefaultHTTPHost
h
:=
DefaultHTTPHost
if
api
.
node
.
http
Host
!=
""
{
if
api
.
node
.
config
.
HTTP
Host
!=
""
{
h
=
api
.
node
.
http
Host
h
=
api
.
node
.
config
.
HTTP
Host
}
}
host
=
&
h
host
=
&
h
}
}
if
port
==
nil
{
if
port
==
nil
{
port
=
rpc
.
NewHexNumber
(
api
.
node
.
http
Port
)
port
=
rpc
.
NewHexNumber
(
api
.
node
.
config
.
HTTP
Port
)
}
}
if
cors
==
nil
{
if
cors
==
nil
{
cors
=
&
api
.
node
.
http
Cors
cors
=
&
api
.
node
.
config
.
HTTP
Cors
}
}
modules
:=
api
.
node
.
httpWhitelist
modules
:=
api
.
node
.
httpWhitelist
...
@@ -133,20 +133,20 @@ func (api *PrivateAdminAPI) StartWS(host *string, port *rpc.HexNumber, allowedOr
...
@@ -133,20 +133,20 @@ func (api *PrivateAdminAPI) StartWS(host *string, port *rpc.HexNumber, allowedOr
}
}
if
host
==
nil
{
if
host
==
nil
{
h
:=
common
.
DefaultWSHost
h
:=
DefaultWSHost
if
api
.
node
.
ws
Host
!=
""
{
if
api
.
node
.
config
.
WS
Host
!=
""
{
h
=
api
.
node
.
ws
Host
h
=
api
.
node
.
config
.
WS
Host
}
}
host
=
&
h
host
=
&
h
}
}
if
port
==
nil
{
if
port
==
nil
{
port
=
rpc
.
NewHexNumber
(
api
.
node
.
ws
Port
)
port
=
rpc
.
NewHexNumber
(
api
.
node
.
config
.
WS
Port
)
}
}
if
allowedOrigins
==
nil
{
if
allowedOrigins
==
nil
{
allowedOrigins
=
&
api
.
node
.
ws
Origins
allowedOrigins
=
&
api
.
node
.
config
.
WS
Origins
}
}
modules
:=
api
.
node
.
wsWhitelist
modules
:=
api
.
node
.
config
.
WSModules
if
apis
!=
nil
{
if
apis
!=
nil
{
modules
=
nil
modules
=
nil
for
_
,
m
:=
range
strings
.
Split
(
*
apis
,
","
)
{
for
_
,
m
:=
range
strings
.
Split
(
*
apis
,
","
)
{
...
...
node/config.go
View file @
44bc2e80
...
@@ -18,7 +18,6 @@ package node
...
@@ -18,7 +18,6 @@ package node
import
(
import
(
"crypto/ecdsa"
"crypto/ecdsa"
"encoding/json"
"fmt"
"fmt"
"io/ioutil"
"io/ioutil"
"net"
"net"
...
@@ -48,6 +47,18 @@ var (
...
@@ -48,6 +47,18 @@ var (
// P2P network layer of a protocol stack. These values can be further extended by
// P2P network layer of a protocol stack. These values can be further extended by
// all registered services.
// all registered services.
type
Config
struct
{
type
Config
struct
{
// Name sets the instance name of the node. It must not contain the / character and is
// used in the devp2p node identifier. The instance name of geth is "geth". If no
// value is specified, the basename of the current executable is used.
Name
string
// UserIdent, if set, is used as an additional component in the devp2p node identifier.
UserIdent
string
// Version should be set to the version number of the program. It is used
// in the devp2p node identifier.
Version
string
// DataDir is the file system folder the node should use for any data storage
// DataDir is the file system folder the node should use for any data storage
// requirements. The configured data directory will not be directly shared with
// requirements. The configured data directory will not be directly shared with
// registered services, instead those can use utility methods to create/access
// registered services, instead those can use utility methods to create/access
...
@@ -80,10 +91,6 @@ type Config struct {
...
@@ -80,10 +91,6 @@ type Config struct {
// needed.
// needed.
PrivateKey
*
ecdsa
.
PrivateKey
PrivateKey
*
ecdsa
.
PrivateKey
// Name sets the node name of this server. Use common.MakeName to create a name
// that follows existing conventions.
Name
string
// NoDiscovery specifies whether the peer discovery mechanism should be started
// NoDiscovery specifies whether the peer discovery mechanism should be started
// or not. Disabling is usually useful for protocol debugging (manual topology).
// or not. Disabling is usually useful for protocol debugging (manual topology).
NoDiscovery
bool
NoDiscovery
bool
...
@@ -178,9 +185,23 @@ func (c *Config) IPCEndpoint() string {
...
@@ -178,9 +185,23 @@ func (c *Config) IPCEndpoint() string {
return
c
.
IPCPath
return
c
.
IPCPath
}
}
// NodeDB returns the path to the discovery node database.
func
(
c
*
Config
)
NodeDB
()
string
{
if
c
.
DataDir
==
""
{
return
""
// ephemeral
}
return
c
.
resolvePath
(
"nodes"
)
}
// DefaultIPCEndpoint returns the IPC path used by default.
// DefaultIPCEndpoint returns the IPC path used by default.
func
DefaultIPCEndpoint
()
string
{
func
DefaultIPCEndpoint
(
clientIdentifier
string
)
string
{
config
:=
&
Config
{
DataDir
:
common
.
DefaultDataDir
(),
IPCPath
:
common
.
DefaultIPCSocket
}
if
clientIdentifier
==
""
{
clientIdentifier
=
strings
.
TrimSuffix
(
filepath
.
Base
(
os
.
Args
[
0
]),
".exe"
)
if
clientIdentifier
==
""
{
panic
(
"empty executable name"
)
}
}
config
:=
&
Config
{
DataDir
:
DefaultDataDir
(),
IPCPath
:
clientIdentifier
+
".ipc"
}
return
config
.
IPCEndpoint
()
return
config
.
IPCEndpoint
()
}
}
...
@@ -195,7 +216,7 @@ func (c *Config) HTTPEndpoint() string {
...
@@ -195,7 +216,7 @@ func (c *Config) HTTPEndpoint() string {
// DefaultHTTPEndpoint returns the HTTP endpoint used by default.
// DefaultHTTPEndpoint returns the HTTP endpoint used by default.
func
DefaultHTTPEndpoint
()
string
{
func
DefaultHTTPEndpoint
()
string
{
config
:=
&
Config
{
HTTPHost
:
common
.
DefaultHTTPHost
,
HTTPPort
:
common
.
DefaultHTTPPort
}
config
:=
&
Config
{
HTTPHost
:
DefaultHTTPHost
,
HTTPPort
:
DefaultHTTPPort
}
return
config
.
HTTPEndpoint
()
return
config
.
HTTPEndpoint
()
}
}
...
@@ -210,19 +231,80 @@ func (c *Config) WSEndpoint() string {
...
@@ -210,19 +231,80 @@ func (c *Config) WSEndpoint() string {
// DefaultWSEndpoint returns the websocket endpoint used by default.
// DefaultWSEndpoint returns the websocket endpoint used by default.
func
DefaultWSEndpoint
()
string
{
func
DefaultWSEndpoint
()
string
{
config
:=
&
Config
{
WSHost
:
common
.
DefaultWSHost
,
WSPort
:
common
.
DefaultWSPort
}
config
:=
&
Config
{
WSHost
:
DefaultWSHost
,
WSPort
:
DefaultWSPort
}
return
config
.
WSEndpoint
()
return
config
.
WSEndpoint
()
}
}
// NodeName returns the devp2p node identifier.
func
(
c
*
Config
)
NodeName
()
string
{
name
:=
c
.
name
()
// Backwards compatibility: previous versions used title-cased "Geth", keep that.
if
name
==
"geth"
||
name
==
"geth-testnet"
{
name
=
"Geth"
}
if
c
.
UserIdent
!=
""
{
name
+=
"/"
+
c
.
UserIdent
}
if
c
.
Version
!=
""
{
name
+=
"/v"
+
c
.
Version
}
name
+=
"/"
+
runtime
.
GOOS
name
+=
"/"
+
runtime
.
Version
()
return
name
}
func
(
c
*
Config
)
name
()
string
{
if
c
.
Name
==
""
{
progname
:=
strings
.
TrimSuffix
(
filepath
.
Base
(
os
.
Args
[
0
]),
".exe"
)
if
progname
==
""
{
panic
(
"empty executable name, set Config.Name"
)
}
return
progname
}
return
c
.
Name
}
// These resources are resolved differently for the "geth" and "geth-testnet" instances.
var
isOldGethResource
=
map
[
string
]
bool
{
"chaindata"
:
true
,
"nodes"
:
true
,
"nodekey"
:
true
,
"static-nodes.json"
:
true
,
"trusted-nodes.json"
:
true
,
}
// resolvePath resolves path in the instance directory.
func
(
c
*
Config
)
resolvePath
(
path
string
)
string
{
if
filepath
.
IsAbs
(
path
)
{
return
path
}
if
c
.
DataDir
==
""
{
return
""
}
// Backwards-compatibility: ensure that data directory files created
// by geth 1.4 are used if they exist.
if
c
.
name
()
==
"geth"
&&
isOldGethResource
[
path
]
{
oldpath
:=
""
if
c
.
Name
==
"geth"
{
oldpath
=
filepath
.
Join
(
c
.
DataDir
,
path
)
}
if
oldpath
!=
""
&&
common
.
FileExist
(
oldpath
)
{
// TODO: print warning
return
oldpath
}
}
return
filepath
.
Join
(
c
.
DataDir
,
c
.
name
(),
path
)
}
// NodeKey retrieves the currently configured private key of the node, checking
// NodeKey retrieves the currently configured private key of the node, checking
// first any manually set key, falling back to the one found in the configured
// first any manually set key, falling back to the one found in the configured
// data folder. If no key can be found, a new one is generated.
// data folder. If no key can be found, a new one is generated.
func
(
c
*
Config
)
NodeKey
()
*
ecdsa
.
PrivateKey
{
func
(
c
*
Config
)
NodeKey
()
*
ecdsa
.
PrivateKey
{
// Use any specifically configured key
// Use any specifically configured key
.
if
c
.
PrivateKey
!=
nil
{
if
c
.
PrivateKey
!=
nil
{
return
c
.
PrivateKey
return
c
.
PrivateKey
}
}
// Generate ephemeral key if no datadir is being used
// Generate ephemeral key if no datadir is being used
.
if
c
.
DataDir
==
""
{
if
c
.
DataDir
==
""
{
key
,
err
:=
crypto
.
GenerateKey
()
key
,
err
:=
crypto
.
GenerateKey
()
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -230,16 +312,22 @@ func (c *Config) NodeKey() *ecdsa.PrivateKey {
...
@@ -230,16 +312,22 @@ func (c *Config) NodeKey() *ecdsa.PrivateKey {
}
}
return
key
return
key
}
}
// Fall back to persistent key from the data directory
keyfile
:=
filepath
.
Join
(
c
.
DataDir
,
datadirPrivateKey
)
keyfile
:=
c
.
resolvePath
(
datadirPrivateKey
)
if
key
,
err
:=
crypto
.
LoadECDSA
(
keyfile
);
err
==
nil
{
if
key
,
err
:=
crypto
.
LoadECDSA
(
keyfile
);
err
==
nil
{
return
key
return
key
}
}
// No persistent key found, generate and store a new one
// No persistent key found, generate and store a new one
.
key
,
err
:=
crypto
.
GenerateKey
()
key
,
err
:=
crypto
.
GenerateKey
()
if
err
!=
nil
{
if
err
!=
nil
{
glog
.
Fatalf
(
"Failed to generate node key: %v"
,
err
)
glog
.
Fatalf
(
"Failed to generate node key: %v"
,
err
)
}
}
instanceDir
:=
filepath
.
Join
(
c
.
DataDir
,
c
.
name
())
if
err
:=
os
.
MkdirAll
(
instanceDir
,
0700
);
err
!=
nil
{
glog
.
V
(
logger
.
Error
)
.
Infof
(
"Failed to persist node key: %v"
,
err
)
return
key
}
keyfile
=
filepath
.
Join
(
instanceDir
,
datadirPrivateKey
)
if
err
:=
crypto
.
SaveECDSA
(
keyfile
,
key
);
err
!=
nil
{
if
err
:=
crypto
.
SaveECDSA
(
keyfile
,
key
);
err
!=
nil
{
glog
.
V
(
logger
.
Error
)
.
Infof
(
"Failed to persist node key: %v"
,
err
)
glog
.
V
(
logger
.
Error
)
.
Infof
(
"Failed to persist node key: %v"
,
err
)
}
}
...
@@ -248,12 +336,12 @@ func (c *Config) NodeKey() *ecdsa.PrivateKey {
...
@@ -248,12 +336,12 @@ func (c *Config) NodeKey() *ecdsa.PrivateKey {
// StaticNodes returns a list of node enode URLs configured as static nodes.
// StaticNodes returns a list of node enode URLs configured as static nodes.
func
(
c
*
Config
)
StaticNodes
()
[]
*
discover
.
Node
{
func
(
c
*
Config
)
StaticNodes
()
[]
*
discover
.
Node
{
return
c
.
parsePersistentNodes
(
datadirStaticNodes
)
return
c
.
parsePersistentNodes
(
c
.
resolvePath
(
datadirStaticNodes
)
)
}
}
// TrusterNodes returns a list of node enode URLs configured as trusted nodes.
// TrusterNodes returns a list of node enode URLs configured as trusted nodes.
func
(
c
*
Config
)
TrusterNodes
()
[]
*
discover
.
Node
{
func
(
c
*
Config
)
TrusterNodes
()
[]
*
discover
.
Node
{
return
c
.
parsePersistentNodes
(
datadirTrustedNodes
)
return
c
.
parsePersistentNodes
(
c
.
resolvePath
(
datadirTrustedNodes
)
)
}
}
// parsePersistentNodes parses a list of discovery node URLs loaded from a .json
// parsePersistentNodes parses a list of discovery node URLs loaded from a .json
...
@@ -267,15 +355,10 @@ func (c *Config) parsePersistentNodes(file string) []*discover.Node {
...
@@ -267,15 +355,10 @@ func (c *Config) parsePersistentNodes(file string) []*discover.Node {
if
_
,
err
:=
os
.
Stat
(
path
);
err
!=
nil
{
if
_
,
err
:=
os
.
Stat
(
path
);
err
!=
nil
{
return
nil
return
nil
}
}
// Load the nodes from the config file
// Load the nodes from the config file.
blob
,
err
:=
ioutil
.
ReadFile
(
path
)
var
nodelist
[]
string
if
err
!=
nil
{
if
err
:=
common
.
LoadJSON
(
path
,
&
nodelist
);
err
!=
nil
{
glog
.
V
(
logger
.
Error
)
.
Infof
(
"Failed to access nodes: %v"
,
err
)
glog
.
V
(
logger
.
Error
)
.
Infof
(
"Can't load node file %s: %v"
,
path
,
err
)
return
nil
}
nodelist
:=
[]
string
{}
if
err
:=
json
.
Unmarshal
(
blob
,
&
nodelist
);
err
!=
nil
{
glog
.
V
(
logger
.
Error
)
.
Infof
(
"Failed to load nodes: %v"
,
err
)
return
nil
return
nil
}
}
// Interpret the list as a discovery node array
// Interpret the list as a discovery node array
...
...
node/config_test.go
View file @
44bc2e80
...
@@ -96,57 +96,55 @@ func TestIPCPathResolution(t *testing.T) {
...
@@ -96,57 +96,55 @@ func TestIPCPathResolution(t *testing.T) {
// ephemeral.
// ephemeral.
func
TestNodeKeyPersistency
(
t
*
testing
.
T
)
{
func
TestNodeKeyPersistency
(
t
*
testing
.
T
)
{
// Create a temporary folder and make sure no key is present
// Create a temporary folder and make sure no key is present
dir
,
err
:=
ioutil
.
TempDir
(
""
,
""
)
dir
,
err
:=
ioutil
.
TempDir
(
""
,
"
node-test
"
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"failed to create temporary data directory: %v"
,
err
)
t
.
Fatalf
(
"failed to create temporary data directory: %v"
,
err
)
}
}
defer
os
.
RemoveAll
(
dir
)
defer
os
.
RemoveAll
(
dir
)
if
_
,
err
:=
os
.
Stat
(
filepath
.
Join
(
dir
,
datadirPrivateKey
));
err
==
nil
{
keyfile
:=
filepath
.
Join
(
dir
,
"unit-test"
,
datadirPrivateKey
)
t
.
Fatalf
(
"non-created node key already exists"
)
}
// Configure a node with a preset key and ensure it's not persisted
// Configure a node with a preset key and ensure it's not persisted
key
,
err
:=
crypto
.
GenerateKey
()
key
,
err
:=
crypto
.
GenerateKey
()
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"failed to generate one-shot node key: %v"
,
err
)
t
.
Fatalf
(
"failed to generate one-shot node key: %v"
,
err
)
}
}
if
_
,
err
:=
New
(
&
Config
{
DataDir
:
dir
,
PrivateKey
:
key
});
err
!=
nil
{
config
:=
&
Config
{
Name
:
"unit-test"
,
DataDir
:
dir
,
PrivateKey
:
key
}
t
.
Fatalf
(
"failed to create empty stack: %v"
,
err
)
config
.
NodeKey
()
}
if
_
,
err
:=
os
.
Stat
(
filepath
.
Join
(
keyfile
));
err
==
nil
{
if
_
,
err
:=
os
.
Stat
(
filepath
.
Join
(
dir
,
datadirPrivateKey
));
err
==
nil
{
t
.
Fatalf
(
"one-shot node key persisted to data directory"
)
t
.
Fatalf
(
"one-shot node key persisted to data directory"
)
}
}
// Configure a node with no preset key and ensure it is persisted this time
// Configure a node with no preset key and ensure it is persisted this time
if
_
,
err
:=
New
(
&
Config
{
DataDir
:
dir
});
err
!=
nil
{
config
=
&
Config
{
Name
:
"unit-test"
,
DataDir
:
dir
}
t
.
Fatalf
(
"failed to create newly keyed stack: %v"
,
err
)
config
.
NodeKey
()
}
if
_
,
err
:=
os
.
Stat
(
keyfile
);
err
!=
nil
{
if
_
,
err
:=
os
.
Stat
(
filepath
.
Join
(
dir
,
datadirPrivateKey
));
err
!=
nil
{
t
.
Fatalf
(
"node key not persisted to data directory: %v"
,
err
)
t
.
Fatalf
(
"node key not persisted to data directory: %v"
,
err
)
}
}
key
,
err
=
crypto
.
LoadECDSA
(
filepath
.
Join
(
dir
,
datadirPrivateKey
)
)
key
,
err
=
crypto
.
LoadECDSA
(
keyfile
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"failed to load freshly persisted node key: %v"
,
err
)
t
.
Fatalf
(
"failed to load freshly persisted node key: %v"
,
err
)
}
}
blob1
,
err
:=
ioutil
.
ReadFile
(
filepath
.
Join
(
dir
,
datadirPrivateKey
)
)
blob1
,
err
:=
ioutil
.
ReadFile
(
keyfile
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"failed to read freshly persisted node key: %v"
,
err
)
t
.
Fatalf
(
"failed to read freshly persisted node key: %v"
,
err
)
}
}
// Configure a new node and ensure the previously persisted key is loaded
// Configure a new node and ensure the previously persisted key is loaded
if
_
,
err
:=
New
(
&
Config
{
DataDir
:
dir
});
err
!=
nil
{
config
=
&
Config
{
Name
:
"unit-test"
,
DataDir
:
dir
}
t
.
Fatalf
(
"failed to create previously keyed stack: %v"
,
err
)
config
.
NodeKey
()
}
blob2
,
err
:=
ioutil
.
ReadFile
(
filepath
.
Join
(
keyfile
))
blob2
,
err
:=
ioutil
.
ReadFile
(
filepath
.
Join
(
dir
,
datadirPrivateKey
))
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"failed to read previously persisted node key: %v"
,
err
)
t
.
Fatalf
(
"failed to read previously persisted node key: %v"
,
err
)
}
}
if
bytes
.
Compare
(
blob1
,
blob2
)
!=
0
{
if
bytes
.
Compare
(
blob1
,
blob2
)
!=
0
{
t
.
Fatalf
(
"persisted node key mismatch: have %x, want %x"
,
blob2
,
blob1
)
t
.
Fatalf
(
"persisted node key mismatch: have %x, want %x"
,
blob2
,
blob1
)
}
}
// Configure ephemeral node and ensure no key is dumped locally
// Configure ephemeral node and ensure no key is dumped locally
if
_
,
err
:=
New
(
&
Config
{
DataDir
:
""
});
err
!=
nil
{
config
=
&
Config
{
Name
:
"unit-test"
,
DataDir
:
""
}
t
.
Fatalf
(
"failed to create ephemeral stack: %v"
,
err
)
config
.
NodeKey
()
}
if
_
,
err
:=
os
.
Stat
(
filepath
.
Join
(
"."
,
"unit-test"
,
datadirPrivateKey
));
err
==
nil
{
if
_
,
err
:=
os
.
Stat
(
filepath
.
Join
(
"."
,
datadirPrivateKey
));
err
==
nil
{
t
.
Fatalf
(
"ephemeral node key persisted to disk"
)
t
.
Fatalf
(
"ephemeral node key persisted to disk"
)
}
}
}
}
common
/defaults.go
→
node
/defaults.go
View file @
44bc2e80
...
@@ -14,9 +14,11 @@
...
@@ -14,9 +14,11 @@
// 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
common
package
node
import
(
import
(
"os"
"os/user"
"path/filepath"
"path/filepath"
"runtime"
"runtime"
)
)
...
@@ -33,7 +35,7 @@ const (
...
@@ -33,7 +35,7 @@ const (
// persistence requirements.
// persistence requirements.
func
DefaultDataDir
()
string
{
func
DefaultDataDir
()
string
{
// Try to place the data folder in the user's home dir
// Try to place the data folder in the user's home dir
home
:=
H
omeDir
()
home
:=
h
omeDir
()
if
home
!=
""
{
if
home
!=
""
{
if
runtime
.
GOOS
==
"darwin"
{
if
runtime
.
GOOS
==
"darwin"
{
return
filepath
.
Join
(
home
,
"Library"
,
"Ethereum"
)
return
filepath
.
Join
(
home
,
"Library"
,
"Ethereum"
)
...
@@ -46,3 +48,13 @@ func DefaultDataDir() string {
...
@@ -46,3 +48,13 @@ func DefaultDataDir() string {
// As we cannot guess a stable location, return empty and handle later
// As we cannot guess a stable location, return empty and handle later
return
""
return
""
}
}
func
homeDir
()
string
{
if
home
:=
os
.
Getenv
(
"HOME"
);
home
!=
""
{
return
home
}
if
usr
,
err
:=
user
.
Current
();
err
==
nil
{
return
usr
.
HomeDir
}
return
""
}
node/doc.go
0 → 100644
View file @
44bc2e80
// Copyright 2016 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 node sets up multi-protocol Ethereum nodes.
In the model exposed by this package, a node is a collection of services which use shared
resources to provide RPC APIs. Services can also offer devp2p protocols, which are wired
up to the devp2p network when the node instance is started.
Resources Managed By Node
All file-system resources used by a node instance are located in a directory called the
data directory. The location of each resource can be overridden through additional node
configuration. The data directory is optional. If it is not set and the location of a
resource is otherwise unspecified, package node will create the resource in memory.
To access to the devp2p network, Node configures and starts p2p.Server. Each host on the
devp2p network has a unique identifier, the node key. The Node instance persists this key
across restarts. Node also loads static and trusted node lists and ensures that knowledge
about other hosts is persisted.
JSON-RPC servers which run HTTP, WebSocket or IPC can be started on a Node. RPC modules
offered by registered services will be offered on those endpoints. Users can restrict any
endpoint to a subset of RPC modules. Node itself offers the "debug", "admin" and "web3"
modules.
Service implementations can open LevelDB databases through the service context. Package
node chooses the file system location of each database. If the node is configured to run
without a data directory, databases are opened in memory instead.
Node also creates the shared store of encrypted Ethereum account keys. Services can access
the account manager through the service context.
Sharing Data Directory Among Instances
Multiple node instances can share a single data directory if they have distinct instance
names (set through the Name config option). Sharing behaviour depends on the type of
resource.
devp2p-related resources (node key, static/trusted node lists, known hosts database) are
stored in a directory with the same name as the instance. Thus, multiple node instances
using the same data directory will store this information in different subdirectories of
the data directory.
LevelDB databases are also stored within the instance subdirectory. If multiple node
instances use the same data directory, openening the databases with identical names will
create one database for each instance.
The account key store is shared among all node instances using the same data directory
unless its location is changed through the KeyStoreDir configuration option.
Data Directory Sharing Example
In this exanple, two node instances named A and B are started with the same data
directory. Mode instance A opens the database "db", node instance B opens the databases
"db" and "db-2". The following files will be created in the data directory:
data-directory/
A/
nodekey -- devp2p node key of instance A
nodes/ -- devp2p discovery knowledge database of instance A
db/ -- LevelDB content for "db"
A.ipc -- JSON-RPC UNIX domain socket endpoint of instance A
B/
nodekey -- devp2p node key of node B
nodes/ -- devp2p discovery knowledge database of instance B
static-nodes.json -- devp2p static node list of instance B
db/ -- LevelDB content for "db"
db-2/ -- LevelDB content for "db-2"
B.ipc -- JSON-RPC UNIX domain socket endpoint of instance A
keystore/ -- account key store, used by both instances
*/
package
node
node/node.go
View file @
44bc2e80
...
@@ -14,7 +14,6 @@
...
@@ -14,7 +14,6 @@
// 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 node represents the Ethereum protocol stack container.
package
node
package
node
import
(
import
(
...
@@ -23,16 +22,19 @@ import (
...
@@ -23,16 +22,19 @@ import (
"os"
"os"
"path/filepath"
"path/filepath"
"reflect"
"reflect"
"strings"
"sync"
"sync"
"syscall"
"syscall"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/internal/debug"
"github.com/ethereum/go-ethereum/internal/debug"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/rpc"
"github.com/syndtr/goleveldb/leveldb/storage"
)
)
var
(
var
(
...
@@ -44,14 +46,14 @@ var (
...
@@ -44,14 +46,14 @@ var (
datadirInUseErrnos
=
map
[
uint
]
bool
{
11
:
true
,
32
:
true
,
35
:
true
}
datadirInUseErrnos
=
map
[
uint
]
bool
{
11
:
true
,
32
:
true
,
35
:
true
}
)
)
// Node represents a P2P node into which arbitrary (uniquely typed) services might
// Node is a container on which services can be registered.
// be registered.
type
Node
struct
{
type
Node
struct
{
datadir
string
// Path to the currently used data directory
eventmux
*
event
.
TypeMux
// Event multiplexer used between the services of a stack
eventmux
*
event
.
TypeMux
// Event multiplexer used between the services of a stack
config
*
Config
accman
*
accounts
.
Manager
accman
*
accounts
.
Manager
ephemeralKeystore
string
// if non-empty, the key directory that will be removed by Stop
ephemeralKeystore
string
// if non-empty, the key directory that will be removed by Stop
instanceDirLock
storage
.
Storage
// prevents concurrent use of instance directory
serverConfig
p2p
.
Config
serverConfig
p2p
.
Config
server
*
p2p
.
Server
// Currently running P2P networking layer
server
*
p2p
.
Server
// Currently running P2P networking layer
...
@@ -66,19 +68,12 @@ type Node struct {
...
@@ -66,19 +68,12 @@ type Node struct {
ipcListener
net
.
Listener
// IPC RPC listener socket to serve API requests
ipcListener
net
.
Listener
// IPC RPC listener socket to serve API requests
ipcHandler
*
rpc
.
Server
// IPC RPC request handler to process the API requests
ipcHandler
*
rpc
.
Server
// IPC RPC request handler to process the API requests
httpHost
string
// HTTP hostname
httpPort
int
// HTTP post
httpEndpoint
string
// HTTP endpoint (interface + port) to listen at (empty = HTTP disabled)
httpEndpoint
string
// HTTP endpoint (interface + port) to listen at (empty = HTTP disabled)
httpWhitelist
[]
string
// HTTP RPC modules to allow through this endpoint
httpWhitelist
[]
string
// HTTP RPC modules to allow through this endpoint
httpCors
string
// HTTP RPC Cross-Origin Resource Sharing header
httpListener
net
.
Listener
// HTTP RPC listener socket to server API requests
httpListener
net
.
Listener
// HTTP RPC listener socket to server API requests
httpHandler
*
rpc
.
Server
// HTTP RPC request handler to process the API requests
httpHandler
*
rpc
.
Server
// HTTP RPC request handler to process the API requests
wsHost
string
// Websocket host
wsPort
int
// Websocket post
wsEndpoint
string
// Websocket endpoint (interface + port) to listen at (empty = websocket disabled)
wsEndpoint
string
// Websocket endpoint (interface + port) to listen at (empty = websocket disabled)
wsWhitelist
[]
string
// Websocket RPC modules to allow through this endpoint
wsOrigins
string
// Websocket RPC allowed origin domains
wsListener
net
.
Listener
// Websocket RPC listener socket to server API requests
wsListener
net
.
Listener
// Websocket RPC listener socket to server API requests
wsHandler
*
rpc
.
Server
// Websocket RPC request handler to process the API requests
wsHandler
*
rpc
.
Server
// Websocket RPC request handler to process the API requests
...
@@ -88,53 +83,44 @@ type Node struct {
...
@@ -88,53 +83,44 @@ type Node struct {
// New creates a new P2P node, ready for protocol registration.
// New creates a new P2P node, ready for protocol registration.
func
New
(
conf
*
Config
)
(
*
Node
,
error
)
{
func
New
(
conf
*
Config
)
(
*
Node
,
error
)
{
// Ensure the data directory exists, failing if it cannot be created
// Copy config and resolve the datadir so future changes to the current
// working directory don't affect the node.
confCopy
:=
*
conf
conf
=
&
confCopy
if
conf
.
DataDir
!=
""
{
if
conf
.
DataDir
!=
""
{
if
err
:=
os
.
MkdirAll
(
conf
.
DataDir
,
0700
);
err
!=
nil
{
absdatadir
,
err
:=
filepath
.
Abs
(
conf
.
DataDir
)
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
conf
.
DataDir
=
absdatadir
}
// Ensure that the instance name doesn't cause weird conflicts with
// other files in the data directory.
if
strings
.
ContainsAny
(
conf
.
Name
,
`/\`
)
{
return
nil
,
errors
.
New
(
`Config.Name must not contain '/' or '\'`
)
}
if
conf
.
Name
==
datadirDefaultKeyStore
{
return
nil
,
errors
.
New
(
`Config.Name cannot be "`
+
datadirDefaultKeyStore
+
`"`
)
}
}
if
strings
.
HasSuffix
(
conf
.
Name
,
".ipc"
)
{
return
nil
,
errors
.
New
(
`Config.Name cannot end in ".ipc"`
)
}
// Ensure that the AccountManager method works before the node has started.
// We rely on this in cmd/geth.
am
,
ephemeralKeystore
,
err
:=
makeAccountManager
(
conf
)
am
,
ephemeralKeystore
,
err
:=
makeAccountManager
(
conf
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
// Note: any interaction with Config that would create/touch files
// Assemble the networking layer and the node itself
// in the data directory or instance directory is delayed until Start.
nodeDbPath
:=
""
if
conf
.
DataDir
!=
""
{
nodeDbPath
=
filepath
.
Join
(
conf
.
DataDir
,
datadirNodeDatabase
)
}
return
&
Node
{
return
&
Node
{
datadir
:
conf
.
DataDir
,
accman
:
am
,
accman
:
am
,
ephemeralKeystore
:
ephemeralKeystore
,
ephemeralKeystore
:
ephemeralKeystore
,
serverConfig
:
p2p
.
Config
{
config
:
conf
,
PrivateKey
:
conf
.
NodeKey
(),
Name
:
conf
.
Name
,
Discovery
:
!
conf
.
NoDiscovery
,
BootstrapNodes
:
conf
.
BootstrapNodes
,
StaticNodes
:
conf
.
StaticNodes
(),
TrustedNodes
:
conf
.
TrusterNodes
(),
NodeDatabase
:
nodeDbPath
,
ListenAddr
:
conf
.
ListenAddr
,
NAT
:
conf
.
NAT
,
Dialer
:
conf
.
Dialer
,
NoDial
:
conf
.
NoDial
,
MaxPeers
:
conf
.
MaxPeers
,
MaxPendingPeers
:
conf
.
MaxPendingPeers
,
},
serviceFuncs
:
[]
ServiceConstructor
{},
serviceFuncs
:
[]
ServiceConstructor
{},
ipcEndpoint
:
conf
.
IPCEndpoint
(),
ipcEndpoint
:
conf
.
IPCEndpoint
(),
httpHost
:
conf
.
HTTPHost
,
httpPort
:
conf
.
HTTPPort
,
httpEndpoint
:
conf
.
HTTPEndpoint
(),
httpEndpoint
:
conf
.
HTTPEndpoint
(),
httpWhitelist
:
conf
.
HTTPModules
,
httpCors
:
conf
.
HTTPCors
,
wsHost
:
conf
.
WSHost
,
wsPort
:
conf
.
WSPort
,
wsEndpoint
:
conf
.
WSEndpoint
(),
wsEndpoint
:
conf
.
WSEndpoint
(),
wsWhitelist
:
conf
.
WSModules
,
wsOrigins
:
conf
.
WSOrigins
,
eventmux
:
new
(
event
.
TypeMux
),
eventmux
:
new
(
event
.
TypeMux
),
},
nil
},
nil
}
}
...
@@ -161,13 +147,36 @@ func (n *Node) Start() error {
...
@@ -161,13 +147,36 @@ func (n *Node) Start() error {
if
n
.
server
!=
nil
{
if
n
.
server
!=
nil
{
return
ErrNodeRunning
return
ErrNodeRunning
}
}
// Otherwise copy and specialize the P2P configuration
if
err
:=
n
.
openDataDir
();
err
!=
nil
{
return
err
}
// Initialize the p2p server. This creates the node key and
// discovery databases.
n
.
serverConfig
=
p2p
.
Config
{
PrivateKey
:
n
.
config
.
NodeKey
(),
Name
:
n
.
config
.
NodeName
(),
Discovery
:
!
n
.
config
.
NoDiscovery
,
BootstrapNodes
:
n
.
config
.
BootstrapNodes
,
StaticNodes
:
n
.
config
.
StaticNodes
(),
TrustedNodes
:
n
.
config
.
TrusterNodes
(),
NodeDatabase
:
n
.
config
.
NodeDB
(),
ListenAddr
:
n
.
config
.
ListenAddr
,
NAT
:
n
.
config
.
NAT
,
Dialer
:
n
.
config
.
Dialer
,
NoDial
:
n
.
config
.
NoDial
,
MaxPeers
:
n
.
config
.
MaxPeers
,
MaxPendingPeers
:
n
.
config
.
MaxPendingPeers
,
}
running
:=
&
p2p
.
Server
{
Config
:
n
.
serverConfig
}
running
:=
&
p2p
.
Server
{
Config
:
n
.
serverConfig
}
glog
.
V
(
logger
.
Info
)
.
Infoln
(
"instance:"
,
n
.
serverConfig
.
Name
)
// Otherwise copy and specialize the P2P configuration
services
:=
make
(
map
[
reflect
.
Type
]
Service
)
services
:=
make
(
map
[
reflect
.
Type
]
Service
)
for
_
,
constructor
:=
range
n
.
serviceFuncs
{
for
_
,
constructor
:=
range
n
.
serviceFuncs
{
// Create a new context for the particular service
// Create a new context for the particular service
ctx
:=
&
ServiceContext
{
ctx
:=
&
ServiceContext
{
datadir
:
n
.
datadir
,
config
:
n
.
config
,
services
:
make
(
map
[
reflect
.
Type
]
Service
),
services
:
make
(
map
[
reflect
.
Type
]
Service
),
EventMux
:
n
.
eventmux
,
EventMux
:
n
.
eventmux
,
AccountManager
:
n
.
accman
,
AccountManager
:
n
.
accman
,
...
@@ -227,6 +236,26 @@ func (n *Node) Start() error {
...
@@ -227,6 +236,26 @@ func (n *Node) Start() error {
return
nil
return
nil
}
}
func
(
n
*
Node
)
openDataDir
()
error
{
if
n
.
config
.
DataDir
==
""
{
return
nil
// ephemeral
}
instdir
:=
filepath
.
Join
(
n
.
config
.
DataDir
,
n
.
config
.
name
())
if
err
:=
os
.
MkdirAll
(
instdir
,
0700
);
err
!=
nil
{
return
err
}
// Try to open the instance directory as LevelDB storage. This creates a lock file
// which prevents concurrent use by another instance as well as accidental use of the
// instance directory as a database.
storage
,
err
:=
storage
.
OpenFile
(
instdir
,
true
)
if
err
!=
nil
{
return
err
}
n
.
instanceDirLock
=
storage
return
nil
}
// startRPC is a helper method to start all the various RPC endpoint during node
// startRPC is a helper method to start all the various RPC endpoint during node
// startup. It's not meant to be called at any time afterwards as it makes certain
// startup. It's not meant to be called at any time afterwards as it makes certain
// assumptions about the state of the node.
// assumptions about the state of the node.
...
@@ -244,12 +273,12 @@ func (n *Node) startRPC(services map[reflect.Type]Service) error {
...
@@ -244,12 +273,12 @@ func (n *Node) startRPC(services map[reflect.Type]Service) error {
n
.
stopInProc
()
n
.
stopInProc
()
return
err
return
err
}
}
if
err
:=
n
.
startHTTP
(
n
.
httpEndpoint
,
apis
,
n
.
httpWhitelist
,
n
.
http
Cors
);
err
!=
nil
{
if
err
:=
n
.
startHTTP
(
n
.
httpEndpoint
,
apis
,
n
.
config
.
HTTPModules
,
n
.
config
.
HTTP
Cors
);
err
!=
nil
{
n
.
stopIPC
()
n
.
stopIPC
()
n
.
stopInProc
()
n
.
stopInProc
()
return
err
return
err
}
}
if
err
:=
n
.
startWS
(
n
.
wsEndpoint
,
apis
,
n
.
wsWhitelist
,
n
.
ws
Origins
);
err
!=
nil
{
if
err
:=
n
.
startWS
(
n
.
wsEndpoint
,
apis
,
n
.
config
.
WSModules
,
n
.
config
.
WS
Origins
);
err
!=
nil
{
n
.
stopHTTP
()
n
.
stopHTTP
()
n
.
stopIPC
()
n
.
stopIPC
()
n
.
stopInProc
()
n
.
stopInProc
()
...
@@ -381,7 +410,6 @@ func (n *Node) startHTTP(endpoint string, apis []rpc.API, modules []string, cors
...
@@ -381,7 +410,6 @@ func (n *Node) startHTTP(endpoint string, apis []rpc.API, modules []string, cors
n
.
httpEndpoint
=
endpoint
n
.
httpEndpoint
=
endpoint
n
.
httpListener
=
listener
n
.
httpListener
=
listener
n
.
httpHandler
=
handler
n
.
httpHandler
=
handler
n
.
httpCors
=
cors
return
nil
return
nil
}
}
...
@@ -436,7 +464,6 @@ func (n *Node) startWS(endpoint string, apis []rpc.API, modules []string, wsOrig
...
@@ -436,7 +464,6 @@ func (n *Node) startWS(endpoint string, apis []rpc.API, modules []string, wsOrig
n
.
wsEndpoint
=
endpoint
n
.
wsEndpoint
=
endpoint
n
.
wsListener
=
listener
n
.
wsListener
=
listener
n
.
wsHandler
=
handler
n
.
wsHandler
=
handler
n
.
wsOrigins
=
wsOrigins
return
nil
return
nil
}
}
...
@@ -465,12 +492,12 @@ func (n *Node) Stop() error {
...
@@ -465,12 +492,12 @@ func (n *Node) Stop() error {
if
n
.
server
==
nil
{
if
n
.
server
==
nil
{
return
ErrNodeStopped
return
ErrNodeStopped
}
}
// Otherwise terminate the API, all services and the P2P server too
// Terminate the API, services and the p2p server.
n
.
stopWS
()
n
.
stopWS
()
n
.
stopHTTP
()
n
.
stopHTTP
()
n
.
stopIPC
()
n
.
stopIPC
()
n
.
rpcAPIs
=
nil
n
.
rpcAPIs
=
nil
failure
:=
&
StopError
{
failure
:=
&
StopError
{
Services
:
make
(
map
[
reflect
.
Type
]
error
),
Services
:
make
(
map
[
reflect
.
Type
]
error
),
}
}
...
@@ -480,9 +507,16 @@ func (n *Node) Stop() error {
...
@@ -480,9 +507,16 @@ func (n *Node) Stop() error {
}
}
}
}
n
.
server
.
Stop
()
n
.
server
.
Stop
()
n
.
services
=
nil
n
.
services
=
nil
n
.
server
=
nil
n
.
server
=
nil
// Release instance directory lock.
if
n
.
instanceDirLock
!=
nil
{
n
.
instanceDirLock
.
Close
()
n
.
instanceDirLock
=
nil
}
// unblock n.Wait
close
(
n
.
stop
)
close
(
n
.
stop
)
// Remove the keystore if it was created ephemerally.
// Remove the keystore if it was created ephemerally.
...
@@ -566,7 +600,7 @@ func (n *Node) Service(service interface{}) error {
...
@@ -566,7 +600,7 @@ func (n *Node) Service(service interface{}) error {
// DataDir retrieves the current datadir used by the protocol stack.
// DataDir retrieves the current datadir used by the protocol stack.
func
(
n
*
Node
)
DataDir
()
string
{
func
(
n
*
Node
)
DataDir
()
string
{
return
n
.
datad
ir
return
n
.
config
.
DataD
ir
}
}
// AccountManager retrieves the account manager used by the protocol stack.
// AccountManager retrieves the account manager used by the protocol stack.
...
@@ -595,6 +629,21 @@ func (n *Node) EventMux() *event.TypeMux {
...
@@ -595,6 +629,21 @@ func (n *Node) EventMux() *event.TypeMux {
return
n
.
eventmux
return
n
.
eventmux
}
}
// OpenDatabase opens an existing database with the given name (or creates one if no
// previous can be found) from within the node's instance directory. If the node is
// ephemeral, a memory database is returned.
func
(
n
*
Node
)
OpenDatabase
(
name
string
,
cache
,
handles
int
)
(
ethdb
.
Database
,
error
)
{
if
n
.
config
.
DataDir
==
""
{
return
ethdb
.
NewMemDatabase
()
}
return
ethdb
.
NewLDBDatabase
(
n
.
config
.
resolvePath
(
name
),
cache
,
handles
)
}
// ResolvePath returns the absolute path of a resource in the instance directory.
func
(
n
*
Node
)
ResolvePath
(
x
string
)
string
{
return
n
.
config
.
resolvePath
(
x
)
}
// apis returns the collection of RPC descriptors this node offers.
// apis returns the collection of RPC descriptors this node offers.
func
(
n
*
Node
)
apis
()
[]
rpc
.
API
{
func
(
n
*
Node
)
apis
()
[]
rpc
.
API
{
return
[]
rpc
.
API
{
return
[]
rpc
.
API
{
...
...
node/service.go
View file @
44bc2e80
...
@@ -17,7 +17,6 @@
...
@@ -17,7 +17,6 @@
package
node
package
node
import
(
import
(
"path/filepath"
"reflect"
"reflect"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts"
...
@@ -31,7 +30,7 @@ import (
...
@@ -31,7 +30,7 @@ import (
// the protocol stack, that is passed to all constructors to be optionally used;
// the protocol stack, that is passed to all constructors to be optionally used;
// as well as utility methods to operate on the service environment.
// as well as utility methods to operate on the service environment.
type
ServiceContext
struct
{
type
ServiceContext
struct
{
datadir
string
// Data directory for protocol persistence
config
*
Config
services
map
[
reflect
.
Type
]
Service
// Index of the already constructed services
services
map
[
reflect
.
Type
]
Service
// Index of the already constructed services
EventMux
*
event
.
TypeMux
// Event multiplexer used for decoupled notifications
EventMux
*
event
.
TypeMux
// Event multiplexer used for decoupled notifications
AccountManager
*
accounts
.
Manager
// Account manager created by the node.
AccountManager
*
accounts
.
Manager
// Account manager created by the node.
...
@@ -41,10 +40,10 @@ type ServiceContext struct {
...
@@ -41,10 +40,10 @@ type ServiceContext struct {
// if no previous can be found) from within the node's data directory. If the
// if no previous can be found) from within the node's data directory. If the
// node is an ephemeral one, a memory database is returned.
// node is an ephemeral one, a memory database is returned.
func
(
ctx
*
ServiceContext
)
OpenDatabase
(
name
string
,
cache
int
,
handles
int
)
(
ethdb
.
Database
,
error
)
{
func
(
ctx
*
ServiceContext
)
OpenDatabase
(
name
string
,
cache
int
,
handles
int
)
(
ethdb
.
Database
,
error
)
{
if
ctx
.
datad
ir
==
""
{
if
ctx
.
config
.
DataD
ir
==
""
{
return
ethdb
.
NewMemDatabase
()
return
ethdb
.
NewMemDatabase
()
}
}
return
ethdb
.
NewLDBDatabase
(
filepath
.
Join
(
ctx
.
datadir
,
name
),
cache
,
handles
)
return
ethdb
.
NewLDBDatabase
(
ctx
.
config
.
resolvePath
(
name
),
cache
,
handles
)
}
}
// Service retrieves a currently running service registered of a specific type.
// Service retrieves a currently running service registered of a specific type.
...
@@ -64,10 +63,12 @@ type ServiceConstructor func(ctx *ServiceContext) (Service, error)
...
@@ -64,10 +63,12 @@ type ServiceConstructor func(ctx *ServiceContext) (Service, error)
// Service is an individual protocol that can be registered into a node.
// Service is an individual protocol that can be registered into a node.
//
//
// Notes:
// Notes:
// - Service life-cycle management is delegated to the node. The service is
//
// allowed to initialize itself upon creation, but no goroutines should be
// • Service life-cycle management is delegated to the node. The service is allowed to
// spun up outside of the Start method.
// initialize itself upon creation, but no goroutines should be spun up outside of the
// - Restart logic is not required as the node will create a fresh instance
// Start method.
//
// • Restart logic is not required as the node will create a fresh instance
// every time a service is started.
// every time a service is started.
type
Service
interface
{
type
Service
interface
{
// Protocols retrieves the P2P protocols the service wishes to start.
// Protocols retrieves the P2P protocols the service wishes to start.
...
...
node/service_test.go
View file @
44bc2e80
...
@@ -38,18 +38,18 @@ func TestContextDatabases(t *testing.T) {
...
@@ -38,18 +38,18 @@ func TestContextDatabases(t *testing.T) {
t
.
Fatalf
(
"non-created database already exists"
)
t
.
Fatalf
(
"non-created database already exists"
)
}
}
// Request the opening/creation of a database and ensure it persists to disk
// Request the opening/creation of a database and ensure it persists to disk
ctx
:=
&
ServiceContext
{
datadir
:
dir
}
ctx
:=
&
ServiceContext
{
config
:
&
Config
{
Name
:
"unit-test"
,
DataDir
:
dir
}
}
db
,
err
:=
ctx
.
OpenDatabase
(
"persistent"
,
0
,
0
)
db
,
err
:=
ctx
.
OpenDatabase
(
"persistent"
,
0
,
0
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"failed to open persistent database: %v"
,
err
)
t
.
Fatalf
(
"failed to open persistent database: %v"
,
err
)
}
}
db
.
Close
()
db
.
Close
()
if
_
,
err
:=
os
.
Stat
(
filepath
.
Join
(
dir
,
"persistent"
));
err
!=
nil
{
if
_
,
err
:=
os
.
Stat
(
filepath
.
Join
(
dir
,
"
unit-test"
,
"
persistent"
));
err
!=
nil
{
t
.
Fatalf
(
"persistent database doesn't exists: %v"
,
err
)
t
.
Fatalf
(
"persistent database doesn't exists: %v"
,
err
)
}
}
// Request th opening/creation of an ephemeral database and ensure it's not persisted
// Request th opening/creation of an ephemeral database and ensure it's not persisted
ctx
=
&
ServiceContext
{
datadir
:
""
}
ctx
=
&
ServiceContext
{
config
:
&
Config
{
DataDir
:
""
}
}
db
,
err
=
ctx
.
OpenDatabase
(
"ephemeral"
,
0
,
0
)
db
,
err
=
ctx
.
OpenDatabase
(
"ephemeral"
,
0
,
0
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"failed to open ephemeral database: %v"
,
err
)
t
.
Fatalf
(
"failed to open ephemeral database: %v"
,
err
)
...
...
p2p/nat/nat.go
View file @
44bc2e80
...
@@ -197,11 +197,7 @@ type autodisc struct {
...
@@ -197,11 +197,7 @@ type autodisc struct {
func
startautodisc
(
what
string
,
doit
func
()
Interface
)
Interface
{
func
startautodisc
(
what
string
,
doit
func
()
Interface
)
Interface
{
// TODO: monitor network configuration and rerun doit when it changes.
// TODO: monitor network configuration and rerun doit when it changes.
ad
:=
&
autodisc
{
what
:
what
,
doit
:
doit
}
return
&
autodisc
{
what
:
what
,
doit
:
doit
}
// Start the auto discovery as early as possible so it is already
// in progress when the rest of the stack calls the methods.
go
ad
.
wait
()
return
ad
}
}
func
(
n
*
autodisc
)
AddMapping
(
protocol
string
,
extport
,
intport
int
,
name
string
,
lifetime
time
.
Duration
)
error
{
func
(
n
*
autodisc
)
AddMapping
(
protocol
string
,
extport
,
intport
int
,
name
string
,
lifetime
time
.
Duration
)
error
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment