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
3e1000fd
Commit
3e1000fd
authored
Nov 26, 2015
by
Péter Szilágyi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
cmd, eth, node, rpc, xeth: use single-instance services
parent
1e806c4c
Changes
17
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
329 additions
and
294 deletions
+329
-294
js.go
cmd/geth/js.go
+2
-2
js_test.go
cmd/geth/js_test.go
+7
-7
main.go
cmd/geth/main.go
+1
-1
main.go
cmd/gethrpctest/main.go
+3
-3
flags.go
cmd/utils/flags.go
+7
-3
backend.go
eth/backend.go
+2
-2
errors.go
node/errors.go
+17
-3
node.go
node/node.go
+39
-87
node_example_test.go
node/node_example_test.go
+1
-1
node_test.go
node/node_test.go
+98
-130
service.go
node/service.go
+14
-24
service_test.go
node/service_test.go
+14
-23
utils_test.go
node/utils_test.go
+117
-0
admin.go
rpc/api/admin.go
+1
-1
utils.go
rpc/api/utils.go
+1
-1
state.go
xeth/state.go
+1
-2
xeth.go
xeth/xeth.go
+4
-4
No files found.
cmd/geth/js.go
View file @
3e1000fd
...
@@ -345,7 +345,7 @@ func (self *jsre) AskPassword() (string, bool) {
...
@@ -345,7 +345,7 @@ func (self *jsre) AskPassword() (string, bool) {
func
(
self
*
jsre
)
ConfirmTransaction
(
tx
string
)
bool
{
func
(
self
*
jsre
)
ConfirmTransaction
(
tx
string
)
bool
{
// Retrieve the Ethereum instance from the node
// Retrieve the Ethereum instance from the node
var
ethereum
*
eth
.
Ethereum
var
ethereum
*
eth
.
Ethereum
if
_
,
err
:=
self
.
stack
.
Singleton
Service
(
&
ethereum
);
err
!=
nil
{
if
err
:=
self
.
stack
.
Service
(
&
ethereum
);
err
!=
nil
{
return
false
return
false
}
}
// If natspec is enabled, ask for permission
// If natspec is enabled, ask for permission
...
@@ -367,7 +367,7 @@ func (self *jsre) UnlockAccount(addr []byte) bool {
...
@@ -367,7 +367,7 @@ func (self *jsre) UnlockAccount(addr []byte) bool {
}
}
// TODO: allow retry
// TODO: allow retry
var
ethereum
*
eth
.
Ethereum
var
ethereum
*
eth
.
Ethereum
if
_
,
err
:=
self
.
stack
.
Singleton
Service
(
&
ethereum
);
err
!=
nil
{
if
err
:=
self
.
stack
.
Service
(
&
ethereum
);
err
!=
nil
{
return
false
return
false
}
}
if
err
:=
ethereum
.
AccountManager
()
.
Unlock
(
common
.
BytesToAddress
(
addr
),
pass
);
err
!=
nil
{
if
err
:=
ethereum
.
AccountManager
()
.
Unlock
(
common
.
BytesToAddress
(
addr
),
pass
);
err
!=
nil
{
...
...
cmd/geth/js_test.go
View file @
3e1000fd
...
@@ -68,7 +68,7 @@ type testjethre struct {
...
@@ -68,7 +68,7 @@ type testjethre struct {
func
(
self
*
testjethre
)
UnlockAccount
(
acc
[]
byte
)
bool
{
func
(
self
*
testjethre
)
UnlockAccount
(
acc
[]
byte
)
bool
{
var
ethereum
*
eth
.
Ethereum
var
ethereum
*
eth
.
Ethereum
self
.
stack
.
S
ingletonS
ervice
(
&
ethereum
)
self
.
stack
.
Service
(
&
ethereum
)
err
:=
ethereum
.
AccountManager
()
.
Unlock
(
common
.
BytesToAddress
(
acc
),
""
)
err
:=
ethereum
.
AccountManager
()
.
Unlock
(
common
.
BytesToAddress
(
acc
),
""
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -79,7 +79,7 @@ func (self *testjethre) UnlockAccount(acc []byte) bool {
...
@@ -79,7 +79,7 @@ func (self *testjethre) UnlockAccount(acc []byte) bool {
func
(
self
*
testjethre
)
ConfirmTransaction
(
tx
string
)
bool
{
func
(
self
*
testjethre
)
ConfirmTransaction
(
tx
string
)
bool
{
var
ethereum
*
eth
.
Ethereum
var
ethereum
*
eth
.
Ethereum
self
.
stack
.
S
ingletonS
ervice
(
&
ethereum
)
self
.
stack
.
Service
(
&
ethereum
)
if
ethereum
.
NatSpec
{
if
ethereum
.
NatSpec
{
self
.
lastConfirm
=
natspec
.
GetNotice
(
self
.
xeth
,
tx
,
self
.
client
)
self
.
lastConfirm
=
natspec
.
GetNotice
(
self
.
xeth
,
tx
,
self
.
client
)
...
@@ -118,7 +118,7 @@ func testREPL(t *testing.T, config func(*eth.Config)) (string, *testjethre, *nod
...
@@ -118,7 +118,7 @@ func testREPL(t *testing.T, config func(*eth.Config)) (string, *testjethre, *nod
if
config
!=
nil
{
if
config
!=
nil
{
config
(
ethConf
)
config
(
ethConf
)
}
}
if
err
:=
stack
.
Register
(
"ethereum"
,
func
(
ctx
*
node
.
ServiceContext
)
(
node
.
Service
,
error
)
{
return
eth
.
New
(
ctx
,
ethConf
)
});
err
!=
nil
{
if
err
:=
stack
.
Register
(
func
(
ctx
*
node
.
ServiceContext
)
(
node
.
Service
,
error
)
{
return
eth
.
New
(
ctx
,
ethConf
)
});
err
!=
nil
{
t
.
Fatalf
(
"failed to register ethereum protocol: %v"
,
err
)
t
.
Fatalf
(
"failed to register ethereum protocol: %v"
,
err
)
}
}
// Initialize all the keys for testing
// Initialize all the keys for testing
...
@@ -138,7 +138,7 @@ func testREPL(t *testing.T, config func(*eth.Config)) (string, *testjethre, *nod
...
@@ -138,7 +138,7 @@ func testREPL(t *testing.T, config func(*eth.Config)) (string, *testjethre, *nod
t
.
Fatalf
(
"failed to start test stack: %v"
,
err
)
t
.
Fatalf
(
"failed to start test stack: %v"
,
err
)
}
}
var
ethereum
*
eth
.
Ethereum
var
ethereum
*
eth
.
Ethereum
stack
.
S
ingletonS
ervice
(
&
ethereum
)
stack
.
Service
(
&
ethereum
)
assetPath
:=
filepath
.
Join
(
os
.
Getenv
(
"GOPATH"
),
"src"
,
"github.com"
,
"ethereum"
,
"go-ethereum"
,
"cmd"
,
"mist"
,
"assets"
,
"ext"
)
assetPath
:=
filepath
.
Join
(
os
.
Getenv
(
"GOPATH"
),
"src"
,
"github.com"
,
"ethereum"
,
"go-ethereum"
,
"cmd"
,
"mist"
,
"assets"
,
"ext"
)
client
:=
comms
.
NewInProcClient
(
codec
.
JSON
)
client
:=
comms
.
NewInProcClient
(
codec
.
JSON
)
...
@@ -202,7 +202,7 @@ func TestBlockChain(t *testing.T) {
...
@@ -202,7 +202,7 @@ func TestBlockChain(t *testing.T) {
tmpfileq
:=
strconv
.
Quote
(
tmpfile
)
tmpfileq
:=
strconv
.
Quote
(
tmpfile
)
var
ethereum
*
eth
.
Ethereum
var
ethereum
*
eth
.
Ethereum
node
.
S
ingletonS
ervice
(
&
ethereum
)
node
.
Service
(
&
ethereum
)
ethereum
.
BlockChain
()
.
Reset
()
ethereum
.
BlockChain
()
.
Reset
()
checkEvalJSON
(
t
,
repl
,
`admin.exportChain(`
+
tmpfileq
+
`)`
,
`true`
)
checkEvalJSON
(
t
,
repl
,
`admin.exportChain(`
+
tmpfileq
+
`)`
,
`true`
)
...
@@ -436,7 +436,7 @@ multiply7 = Multiply7.at(contractaddress);
...
@@ -436,7 +436,7 @@ multiply7 = Multiply7.at(contractaddress);
func
pendingTransactions
(
repl
*
testjethre
,
t
*
testing
.
T
)
(
txc
int64
,
err
error
)
{
func
pendingTransactions
(
repl
*
testjethre
,
t
*
testing
.
T
)
(
txc
int64
,
err
error
)
{
var
ethereum
*
eth
.
Ethereum
var
ethereum
*
eth
.
Ethereum
repl
.
stack
.
S
ingletonS
ervice
(
&
ethereum
)
repl
.
stack
.
Service
(
&
ethereum
)
txs
:=
ethereum
.
TxPool
()
.
GetTransactions
()
txs
:=
ethereum
.
TxPool
()
.
GetTransactions
()
return
int64
(
len
(
txs
)),
nil
return
int64
(
len
(
txs
)),
nil
...
@@ -464,7 +464,7 @@ func processTxs(repl *testjethre, t *testing.T, expTxc int) bool {
...
@@ -464,7 +464,7 @@ func processTxs(repl *testjethre, t *testing.T, expTxc int) bool {
return
false
return
false
}
}
var
ethereum
*
eth
.
Ethereum
var
ethereum
*
eth
.
Ethereum
repl
.
stack
.
S
ingletonS
ervice
(
&
ethereum
)
repl
.
stack
.
Service
(
&
ethereum
)
err
=
ethereum
.
StartMining
(
runtime
.
NumCPU
(),
""
)
err
=
ethereum
.
StartMining
(
runtime
.
NumCPU
(),
""
)
if
err
!=
nil
{
if
err
!=
nil
{
...
...
cmd/geth/main.go
View file @
3e1000fd
...
@@ -489,7 +489,7 @@ func startNode(ctx *cli.Context, stack *node.Node) {
...
@@ -489,7 +489,7 @@ func startNode(ctx *cli.Context, stack *node.Node) {
// Unlock any account specifically requested
// Unlock any account specifically requested
var
ethereum
*
eth
.
Ethereum
var
ethereum
*
eth
.
Ethereum
if
_
,
err
:=
stack
.
Singleton
Service
(
&
ethereum
);
err
!=
nil
{
if
err
:=
stack
.
Service
(
&
ethereum
);
err
!=
nil
{
utils
.
Fatalf
(
"ethereum service not running: %v"
,
err
)
utils
.
Fatalf
(
"ethereum service not running: %v"
,
err
)
}
}
accman
:=
ethereum
.
AccountManager
()
accman
:=
ethereum
.
AccountManager
()
...
...
cmd/gethrpctest/main.go
View file @
3e1000fd
...
@@ -126,11 +126,11 @@ func MakeSystemNode(keydir string, privkey string, test *tests.BlockTest) (*node
...
@@ -126,11 +126,11 @@ func MakeSystemNode(keydir string, privkey string, test *tests.BlockTest) (*node
TestGenesisBlock
:
test
.
Genesis
,
TestGenesisBlock
:
test
.
Genesis
,
AccountManager
:
accman
,
AccountManager
:
accman
,
}
}
if
err
:=
stack
.
Register
(
"ethereum"
,
func
(
ctx
*
node
.
ServiceContext
)
(
node
.
Service
,
error
)
{
return
eth
.
New
(
ctx
,
ethConf
)
});
err
!=
nil
{
if
err
:=
stack
.
Register
(
func
(
ctx
*
node
.
ServiceContext
)
(
node
.
Service
,
error
)
{
return
eth
.
New
(
ctx
,
ethConf
)
});
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
// Initialize and register the Whisper protocol
// Initialize and register the Whisper protocol
if
err
:=
stack
.
Register
(
"whisper"
,
func
(
*
node
.
ServiceContext
)
(
node
.
Service
,
error
)
{
return
whisper
.
New
(),
nil
});
err
!=
nil
{
if
err
:=
stack
.
Register
(
func
(
*
node
.
ServiceContext
)
(
node
.
Service
,
error
)
{
return
whisper
.
New
(),
nil
});
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
return
stack
,
nil
return
stack
,
nil
...
@@ -140,7 +140,7 @@ func MakeSystemNode(keydir string, privkey string, test *tests.BlockTest) (*node
...
@@ -140,7 +140,7 @@ func MakeSystemNode(keydir string, privkey string, test *tests.BlockTest) (*node
// stack to ensure basic checks pass before running RPC tests.
// stack to ensure basic checks pass before running RPC tests.
func
RunTest
(
stack
*
node
.
Node
,
test
*
tests
.
BlockTest
)
error
{
func
RunTest
(
stack
*
node
.
Node
,
test
*
tests
.
BlockTest
)
error
{
var
ethereum
*
eth
.
Ethereum
var
ethereum
*
eth
.
Ethereum
stack
.
S
ingletonS
ervice
(
&
ethereum
)
stack
.
Service
(
&
ethereum
)
blockchain
:=
ethereum
.
BlockChain
()
blockchain
:=
ethereum
.
BlockChain
()
// Process the blocks and verify the imported headers
// Process the blocks and verify the imported headers
...
...
cmd/utils/flags.go
View file @
3e1000fd
...
@@ -686,13 +686,13 @@ func MakeSystemNode(name, version string, extra []byte, ctx *cli.Context) *node.
...
@@ -686,13 +686,13 @@ func MakeSystemNode(name, version string, extra []byte, ctx *cli.Context) *node.
if
err
!=
nil
{
if
err
!=
nil
{
Fatalf
(
"Failed to create the protocol stack: %v"
,
err
)
Fatalf
(
"Failed to create the protocol stack: %v"
,
err
)
}
}
if
err
:=
stack
.
Register
(
"eth"
,
func
(
ctx
*
node
.
ServiceContext
)
(
node
.
Service
,
error
)
{
if
err
:=
stack
.
Register
(
func
(
ctx
*
node
.
ServiceContext
)
(
node
.
Service
,
error
)
{
return
eth
.
New
(
ctx
,
ethConf
)
return
eth
.
New
(
ctx
,
ethConf
)
});
err
!=
nil
{
});
err
!=
nil
{
Fatalf
(
"Failed to register the Ethereum service: %v"
,
err
)
Fatalf
(
"Failed to register the Ethereum service: %v"
,
err
)
}
}
if
shhEnable
{
if
shhEnable
{
if
err
:=
stack
.
Register
(
"shh"
,
func
(
*
node
.
ServiceContext
)
(
node
.
Service
,
error
)
{
return
whisper
.
New
(),
nil
});
err
!=
nil
{
if
err
:=
stack
.
Register
(
func
(
*
node
.
ServiceContext
)
(
node
.
Service
,
error
)
{
return
whisper
.
New
(),
nil
});
err
!=
nil
{
Fatalf
(
"Failed to register the Whisper service: %v"
,
err
)
Fatalf
(
"Failed to register the Whisper service: %v"
,
err
)
}
}
}
}
...
@@ -786,7 +786,11 @@ func StartIPC(stack *node.Node, ctx *cli.Context) error {
...
@@ -786,7 +786,11 @@ func StartIPC(stack *node.Node, ctx *cli.Context) error {
}
}
initializer
:=
func
(
conn
net
.
Conn
)
(
comms
.
Stopper
,
shared
.
EthereumApi
,
error
)
{
initializer
:=
func
(
conn
net
.
Conn
)
(
comms
.
Stopper
,
shared
.
EthereumApi
,
error
)
{
fe
:=
useragent
.
NewRemoteFrontend
(
conn
,
stack
.
Service
(
"eth"
)
.
(
*
eth
.
Ethereum
)
.
AccountManager
())
var
ethereum
*
eth
.
Ethereum
if
err
:=
stack
.
Service
(
&
ethereum
);
err
!=
nil
{
return
nil
,
nil
,
err
}
fe
:=
useragent
.
NewRemoteFrontend
(
conn
,
ethereum
.
AccountManager
())
xeth
:=
xeth
.
New
(
stack
,
fe
)
xeth
:=
xeth
.
New
(
stack
,
fe
)
apis
,
err
:=
api
.
ParseApiString
(
ctx
.
GlobalString
(
IPCApiFlag
.
Name
),
codec
.
JSON
,
xeth
,
stack
)
apis
,
err
:=
api
.
ParseApiString
(
ctx
.
GlobalString
(
IPCApiFlag
.
Name
),
codec
.
JSON
,
xeth
,
stack
)
if
err
!=
nil
{
if
err
!=
nil
{
...
...
eth/backend.go
View file @
3e1000fd
...
@@ -135,7 +135,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
...
@@ -135,7 +135,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
ethdb
.
OpenFileLimit
=
128
/
(
dbCount
+
1
)
ethdb
.
OpenFileLimit
=
128
/
(
dbCount
+
1
)
// Open the chain database and perform any upgrades needed
// Open the chain database and perform any upgrades needed
chainDb
,
err
:=
ctx
.
Database
(
"chaindata"
,
config
.
DatabaseCache
)
chainDb
,
err
:=
ctx
.
Open
Database
(
"chaindata"
,
config
.
DatabaseCache
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -149,7 +149,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
...
@@ -149,7 +149,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
return
nil
,
err
return
nil
,
err
}
}
dappDb
,
err
:=
ctx
.
Database
(
"dapp"
,
config
.
DatabaseCache
)
dappDb
,
err
:=
ctx
.
Open
Database
(
"dapp"
,
config
.
DatabaseCache
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
...
node/errors.go
View file @
3e1000fd
...
@@ -16,13 +16,27 @@
...
@@ -16,13 +16,27 @@
package
node
package
node
import
"fmt"
import
(
"fmt"
"reflect"
)
// StopError is returned if a node fails to stop either any of its registered
// DuplicateServiceError is returned during Node startup if a registered service
// constructor returns a service of the same type that was already started.
type
DuplicateServiceError
struct
{
Kind
reflect
.
Type
}
// Error generates a textual representation of the duplicate service error.
func
(
e
*
DuplicateServiceError
)
Error
()
string
{
return
fmt
.
Sprintf
(
"duplicate service: %v"
,
e
.
Kind
)
}
// StopError is returned if a Node fails to stop either any of its registered
// services or itself.
// services or itself.
type
StopError
struct
{
type
StopError
struct
{
Server
error
Server
error
Services
map
[
string
]
error
Services
map
[
reflect
.
Type
]
error
}
}
// Error generates a textual representation of the stop error.
// Error generates a textual representation of the stop error.
...
...
node/node.go
View file @
3e1000fd
...
@@ -30,16 +30,16 @@ import (
...
@@ -30,16 +30,16 @@ import (
)
)
var
(
var
(
ErrDatadirUsed
=
errors
.
New
(
"datadir already used"
)
ErrDatadirUsed
=
errors
.
New
(
"datadir already used"
)
ErrNodeStopped
=
errors
.
New
(
"node not started"
)
ErrNodeStopped
=
errors
.
New
(
"node not started"
)
ErrNodeRunning
=
errors
.
New
(
"node already running"
)
ErrNodeRunning
=
errors
.
New
(
"node already running"
)
ErrServiceUnknown
=
errors
.
New
(
"service not registered"
)
ErrServiceUnknown
=
errors
.
New
(
"unknown service"
)
ErrServiceRegistered
=
errors
.
New
(
"service already registered"
)
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 services might be registered.
// Node represents a P2P node into which arbitrary (uniquely typed) services might
// be registered.
type
Node
struct
{
type
Node
struct
{
datadir
string
// Path to the currently used data directory
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
...
@@ -47,9 +47,8 @@ type Node struct {
...
@@ -47,9 +47,8 @@ type Node struct {
serverConfig
*
p2p
.
Server
// Configuration of the underlying P2P networking layer
serverConfig
*
p2p
.
Server
// Configuration of the underlying P2P networking layer
server
*
p2p
.
Server
// Currently running P2P networking layer
server
*
p2p
.
Server
// Currently running P2P networking layer
serviceIndex
map
[
string
]
ServiceConstructor
// Set of services currently registered in the node
serviceFuncs
[]
ServiceConstructor
// Service constructors (in dependency order)
serviceOrder
[]
string
// Service construction order to handle dependencies
services
map
[
reflect
.
Type
]
Service
// Currently running services
services
map
[
string
]
Service
// Currently running services
stop
chan
struct
{}
// Channel to wait for termination notifications
stop
chan
struct
{}
// Channel to wait for termination notifications
lock
sync
.
RWMutex
lock
sync
.
RWMutex
...
@@ -85,52 +84,21 @@ func New(conf *Config) (*Node, error) {
...
@@ -85,52 +84,21 @@ func New(conf *Config) (*Node, error) {
MaxPeers
:
conf
.
MaxPeers
,
MaxPeers
:
conf
.
MaxPeers
,
MaxPendingPeers
:
conf
.
MaxPendingPeers
,
MaxPendingPeers
:
conf
.
MaxPendingPeers
,
},
},
serviceIndex
:
make
(
map
[
string
]
ServiceConstructor
),
serviceFuncs
:
[]
ServiceConstructor
{},
serviceOrder
:
[]
string
{},
eventmux
:
new
(
event
.
TypeMux
),
eventmux
:
new
(
event
.
TypeMux
),
},
nil
},
nil
}
}
// Register injects a new service into the node's stack.
// Register injects a new service into the node's stack. The service created by
func
(
n
*
Node
)
Register
(
id
string
,
constructor
ServiceConstructor
)
error
{
// the passed constructor must be unique in its type with regard to sibling ones.
func
(
n
*
Node
)
Register
(
constructor
ServiceConstructor
)
error
{
n
.
lock
.
Lock
()
n
.
lock
.
Lock
()
defer
n
.
lock
.
Unlock
()
defer
n
.
lock
.
Unlock
()
// Short circuit if the node is running or if the id is taken
if
n
.
server
!=
nil
{
if
n
.
server
!=
nil
{
return
ErrNodeRunning
return
ErrNodeRunning
}
}
if
_
,
ok
:=
n
.
serviceIndex
[
id
];
ok
{
n
.
serviceFuncs
=
append
(
n
.
serviceFuncs
,
constructor
)
return
ErrServiceRegistered
}
// Otherwise register the service and return
n
.
serviceOrder
=
append
(
n
.
serviceOrder
,
id
)
n
.
serviceIndex
[
id
]
=
constructor
return
nil
}
// Unregister removes a service from a node's stack. If the node is currently
// running, an error will be returned.
func
(
n
*
Node
)
Unregister
(
id
string
)
error
{
n
.
lock
.
Lock
()
defer
n
.
lock
.
Unlock
()
// Short circuit if the node is running, or if the service is unknown
if
n
.
server
!=
nil
{
return
ErrNodeRunning
}
if
_
,
ok
:=
n
.
serviceIndex
[
id
];
!
ok
{
return
ErrServiceUnknown
}
// Otherwise drop the service and return
delete
(
n
.
serviceIndex
,
id
)
for
i
,
service
:=
range
n
.
serviceOrder
{
if
service
==
id
{
n
.
serviceOrder
=
append
(
n
.
serviceOrder
[
:
i
],
n
.
serviceOrder
[
i
+
1
:
]
...
)
break
}
}
return
nil
return
nil
}
}
...
@@ -147,25 +115,27 @@ func (n *Node) Start() error {
...
@@ -147,25 +115,27 @@ func (n *Node) Start() error {
running
:=
new
(
p2p
.
Server
)
running
:=
new
(
p2p
.
Server
)
*
running
=
*
n
.
serverConfig
*
running
=
*
n
.
serverConfig
services
:=
make
(
map
[
string
]
Service
)
services
:=
make
(
map
[
reflect
.
Type
]
Service
)
for
_
,
id
:=
range
n
.
serviceOrder
{
for
_
,
constructor
:=
range
n
.
serviceFuncs
{
constructor
:=
n
.
serviceIndex
[
id
]
// Create a new context for the particular service
// Create a new context for the particular service
ctx
:=
&
ServiceContext
{
ctx
:=
&
ServiceContext
{
datadir
:
n
.
datadir
,
datadir
:
n
.
datadir
,
services
:
make
(
map
[
string
]
Service
),
services
:
make
(
map
[
reflect
.
Type
]
Service
),
EventMux
:
n
.
eventmux
,
EventMux
:
n
.
eventmux
,
}
}
for
i
d
,
s
:=
range
services
{
// copy needed for threaded access
for
kin
d
,
s
:=
range
services
{
// copy needed for threaded access
ctx
.
services
[
i
d
]
=
s
ctx
.
services
[
kin
d
]
=
s
}
}
// Construct and save the service
// Construct and save the service
service
,
err
:=
constructor
(
ctx
)
service
,
err
:=
constructor
(
ctx
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
services
[
id
]
=
service
kind
:=
reflect
.
TypeOf
(
service
)
if
_
,
exists
:=
services
[
kind
];
exists
{
return
&
DuplicateServiceError
{
Kind
:
kind
}
}
services
[
kind
]
=
service
}
}
// Gather the protocols and start the freshly assembled P2P server
// Gather the protocols and start the freshly assembled P2P server
for
_
,
service
:=
range
services
{
for
_
,
service
:=
range
services
{
...
@@ -178,19 +148,19 @@ func (n *Node) Start() error {
...
@@ -178,19 +148,19 @@ func (n *Node) Start() error {
return
err
return
err
}
}
// Start each of the services
// Start each of the services
started
:=
[]
string
{}
started
:=
[]
reflect
.
Type
{}
for
i
d
,
service
:=
range
services
{
for
kin
d
,
service
:=
range
services
{
// Start the next service, stopping all previous upon failure
// Start the next service, stopping all previous upon failure
if
err
:=
service
.
Start
(
running
);
err
!=
nil
{
if
err
:=
service
.
Start
(
running
);
err
!=
nil
{
for
_
,
i
d
:=
range
started
{
for
_
,
kin
d
:=
range
started
{
services
[
i
d
]
.
Stop
()
services
[
kin
d
]
.
Stop
()
}
}
running
.
Stop
()
running
.
Stop
()
return
err
return
err
}
}
// Mark the service started for potential cleanup
// Mark the service started for potential cleanup
started
=
append
(
started
,
i
d
)
started
=
append
(
started
,
kin
d
)
}
}
// Finish initializing the startup
// Finish initializing the startup
n
.
services
=
services
n
.
services
=
services
...
@@ -212,11 +182,11 @@ func (n *Node) Stop() error {
...
@@ -212,11 +182,11 @@ func (n *Node) Stop() error {
}
}
// Otherwise terminate all the services and the P2P server too
// Otherwise terminate all the services and the P2P server too
failure
:=
&
StopError
{
failure
:=
&
StopError
{
Services
:
make
(
map
[
string
]
error
),
Services
:
make
(
map
[
reflect
.
Type
]
error
),
}
}
for
i
d
,
service
:=
range
n
.
services
{
for
kin
d
,
service
:=
range
n
.
services
{
if
err
:=
service
.
Stop
();
err
!=
nil
{
if
err
:=
service
.
Stop
();
err
!=
nil
{
failure
.
Services
[
i
d
]
=
err
failure
.
Services
[
kin
d
]
=
err
}
}
}
}
n
.
server
.
Stop
()
n
.
server
.
Stop
()
...
@@ -266,40 +236,22 @@ func (n *Node) Server() *p2p.Server {
...
@@ -266,40 +236,22 @@ func (n *Node) Server() *p2p.Server {
return
n
.
server
return
n
.
server
}
}
// Service retrieves a currently running service registered under a given id.
// Service retrieves a currently running service registered of a specific type.
func
(
n
*
Node
)
Service
(
id
string
)
Service
{
func
(
n
*
Node
)
Service
(
service
interface
{})
error
{
n
.
lock
.
RLock
()
defer
n
.
lock
.
RUnlock
()
// Short circuit if the node's not running
if
n
.
server
==
nil
{
return
nil
}
return
n
.
services
[
id
]
}
// SingletonService retrieves a currently running service using a specific type
// implementing the Service interface. This is a utility function for scenarios
// where it is known that only one instance of a given service type is running,
// allowing to access services without needing to know their specific id with
// which they were registered. Note, this method uses reflection, so do not run
// in a tight loop.
func
(
n
*
Node
)
SingletonService
(
service
interface
{})
(
string
,
error
)
{
n
.
lock
.
RLock
()
n
.
lock
.
RLock
()
defer
n
.
lock
.
RUnlock
()
defer
n
.
lock
.
RUnlock
()
// Short circuit if the node's not running
// Short circuit if the node's not running
if
n
.
server
==
nil
{
if
n
.
server
==
nil
{
return
""
,
ErrServiceUnknown
return
ErrNodeStopped
}
}
// Otherwise try to find the service to return
// Otherwise try to find the service to return
for
id
,
running
:=
range
n
.
services
{
element
:=
reflect
.
ValueOf
(
service
)
.
Elem
()
if
reflect
.
TypeOf
(
running
)
==
reflect
.
ValueOf
(
service
)
.
Elem
()
.
Type
()
{
if
running
,
ok
:=
n
.
services
[
element
.
Type
()];
ok
{
reflect
.
ValueOf
(
service
)
.
Elem
()
.
Set
(
reflect
.
ValueOf
(
running
))
element
.
Set
(
reflect
.
ValueOf
(
running
))
return
id
,
nil
return
nil
}
}
}
return
""
,
ErrServiceUnknown
return
ErrServiceUnknown
}
}
// DataDir retrieves the current datadir used by the protocol stack.
// DataDir retrieves the current datadir used by the protocol stack.
...
...
node/node_example_test.go
View file @
3e1000fd
...
@@ -66,7 +66,7 @@ func ExampleUsage() {
...
@@ -66,7 +66,7 @@ func ExampleUsage() {
constructor
:=
func
(
context
*
node
.
ServiceContext
)
(
node
.
Service
,
error
)
{
constructor
:=
func
(
context
*
node
.
ServiceContext
)
(
node
.
Service
,
error
)
{
return
new
(
SampleService
),
nil
return
new
(
SampleService
),
nil
}
}
if
err
:=
stack
.
Register
(
"my sample service"
,
constructor
);
err
!=
nil
{
if
err
:=
stack
.
Register
(
constructor
);
err
!=
nil
{
log
.
Fatalf
(
"Failed to register service: %v"
,
err
)
log
.
Fatalf
(
"Failed to register service: %v"
,
err
)
}
}
// Boot up the entire protocol stack, do a restart and terminate
// Boot up the entire protocol stack, do a restart and terminate
...
...
node/node_test.go
View file @
3e1000fd
This diff is collapsed.
Click to expand it.
node/service.go
View file @
3e1000fd
...
@@ -29,39 +29,29 @@ import (
...
@@ -29,39 +29,29 @@ 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
datadir
string
// Data directory for protocol persistence
services
map
[
string
]
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
}
}
//
Database opens an existing database with the given name (or creates one if no
//
OpenDatabase opens an existing database with the given name (or creates one
//
previous can be found) from within the node's data directory. If the node is
//
if no previous can be found) from within the node's data directory. If the
// an ephemeral one, a memory database is returned.
//
node is
an ephemeral one, a memory database is returned.
func
(
ctx
*
ServiceContext
)
Database
(
name
string
,
cache
int
)
(
ethdb
.
Database
,
error
)
{
func
(
ctx
*
ServiceContext
)
Open
Database
(
name
string
,
cache
int
)
(
ethdb
.
Database
,
error
)
{
if
ctx
.
datadir
==
""
{
if
ctx
.
datadir
==
""
{
return
ethdb
.
NewMemDatabase
()
return
ethdb
.
NewMemDatabase
()
}
}
return
ethdb
.
NewLDBDatabase
(
filepath
.
Join
(
ctx
.
datadir
,
name
),
cache
)
return
ethdb
.
NewLDBDatabase
(
filepath
.
Join
(
ctx
.
datadir
,
name
),
cache
)
}
}
// Service retrieves an already constructed service registered under a given id.
// Service retrieves a currently running service registered of a specific type.
func
(
ctx
*
ServiceContext
)
Service
(
id
string
)
Service
{
func
(
ctx
*
ServiceContext
)
Service
(
service
interface
{})
error
{
return
ctx
.
services
[
id
]
element
:=
reflect
.
ValueOf
(
service
)
.
Elem
()
}
if
running
,
ok
:=
ctx
.
services
[
element
.
Type
()];
ok
{
element
.
Set
(
reflect
.
ValueOf
(
running
))
// SingletonService retrieves an already constructed service using a specific type
return
nil
// implementing the Service interface. This is a utility function for scenarios
// where it is known that only one instance of a given service type is running,
// allowing to access services without needing to know their specific id with
// which they were registered.
func
(
ctx
*
ServiceContext
)
SingletonService
(
service
interface
{})
(
string
,
error
)
{
for
id
,
running
:=
range
ctx
.
services
{
if
reflect
.
TypeOf
(
running
)
==
reflect
.
ValueOf
(
service
)
.
Elem
()
.
Type
()
{
reflect
.
ValueOf
(
service
)
.
Elem
()
.
Set
(
reflect
.
ValueOf
(
running
))
return
id
,
nil
}
}
}
return
""
,
ErrServiceUnknown
return
ErrServiceUnknown
}
}
// ServiceConstructor is the function signature of the constructors needed to be
// ServiceConstructor is the function signature of the constructors needed to be
...
...
node/service_test.go
View file @
3e1000fd
...
@@ -39,7 +39,7 @@ func TestContextDatabases(t *testing.T) {
...
@@ -39,7 +39,7 @@ func TestContextDatabases(t *testing.T) {
}
}
// 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
{
datadir
:
dir
}
db
,
err
:=
ctx
.
Database
(
"persistent"
,
0
)
db
,
err
:=
ctx
.
Open
Database
(
"persistent"
,
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
)
}
}
...
@@ -50,7 +50,7 @@ func TestContextDatabases(t *testing.T) {
...
@@ -50,7 +50,7 @@ func TestContextDatabases(t *testing.T) {
}
}
// 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
{
datadir
:
""
}
db
,
err
=
ctx
.
Database
(
"ephemeral"
,
0
)
db
,
err
=
ctx
.
Open
Database
(
"ephemeral"
,
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
)
}
}
...
@@ -67,36 +67,27 @@ func TestContextServices(t *testing.T) {
...
@@ -67,36 +67,27 @@ func TestContextServices(t *testing.T) {
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"failed to create protocol stack: %v"
,
err
)
t
.
Fatalf
(
"failed to create protocol stack: %v"
,
err
)
}
}
// Define a set of services, constructed before/after a verifier
// Define a verifier that ensures a NoopA is before it and NoopB after
formers
:=
[]
string
{
"A"
,
"B"
,
"C"
,
"D"
,
"E"
,
"F"
,
"G"
,
"H"
,
"I"
,
"J"
}
latters
:=
[]
string
{
"0"
,
"1"
,
"2"
,
"3"
,
"4"
,
"5"
,
"6"
,
"7"
,
"8"
,
"9"
}
verifier
:=
func
(
ctx
*
ServiceContext
)
(
Service
,
error
)
{
verifier
:=
func
(
ctx
*
ServiceContext
)
(
Service
,
error
)
{
for
i
,
id
:=
range
formers
{
var
objA
*
NoopServiceA
if
ctx
.
Service
(
id
)
==
nil
{
if
ctx
.
Service
(
&
objA
)
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"former %d: service not found"
,
i
)
return
nil
,
fmt
.
Errorf
(
"former service not found"
)
}
}
}
for
i
,
id
:=
range
latters
{
var
objB
*
NoopServiceB
if
ctx
.
Service
(
id
)
!=
nil
{
if
err
:=
ctx
.
Service
(
&
objB
);
err
!=
ErrServiceUnknown
{
return
nil
,
fmt
.
Errorf
(
"latters %d: service found"
,
i
)
return
nil
,
fmt
.
Errorf
(
"latters lookup error mismatch: have %v, want %v"
,
err
,
ErrServiceUnknown
)
}
}
}
return
new
(
NoopService
),
nil
return
new
(
NoopService
),
nil
}
}
// Register the collection of services
// Register the collection of services
for
i
,
id
:=
range
formers
{
if
err
:=
stack
.
Register
(
NewNoopServiceA
);
err
!=
nil
{
if
err
:=
stack
.
Register
(
id
,
NewNoopService
);
err
!=
nil
{
t
.
Fatalf
(
"former failed to register service: %v"
,
err
)
t
.
Fatalf
(
"former #%d: failed to register service: %v"
,
i
,
err
)
}
}
}
if
err
:=
stack
.
Register
(
"verifier"
,
verifier
);
err
!=
nil
{
if
err
:=
stack
.
Register
(
verifier
);
err
!=
nil
{
t
.
Fatalf
(
"failed to register service verifier: %v"
,
err
)
t
.
Fatalf
(
"failed to register service verifier: %v"
,
err
)
}
}
for
i
,
id
:=
range
latters
{
if
err
:=
stack
.
Register
(
NewNoopServiceB
);
err
!=
nil
{
if
err
:=
stack
.
Register
(
id
,
NewNoopService
);
err
!=
nil
{
t
.
Fatalf
(
"latter failed to register service: %v"
,
err
)
t
.
Fatalf
(
"latter #%d: failed to register service: %v"
,
i
,
err
)
}
}
}
// Start the protocol stack and ensure services are constructed in order
// Start the protocol stack and ensure services are constructed in order
if
err
:=
stack
.
Start
();
err
!=
nil
{
if
err
:=
stack
.
Start
();
err
!=
nil
{
...
...
node/utils_test.go
0 → 100644
View file @
3e1000fd
// Copyright 2015 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/>.
// Contains a batch of utility type declarations used by the tests. As the node
// operates on unique types, a lot of them are needed to check various features.
package
node
import
(
"reflect"
"github.com/ethereum/go-ethereum/p2p"
)
// NoopService is a trivial implementation of the Service interface.
type
NoopService
struct
{}
func
(
s
*
NoopService
)
Protocols
()
[]
p2p
.
Protocol
{
return
nil
}
func
(
s
*
NoopService
)
Start
(
*
p2p
.
Server
)
error
{
return
nil
}
func
(
s
*
NoopService
)
Stop
()
error
{
return
nil
}
func
NewNoopService
(
*
ServiceContext
)
(
Service
,
error
)
{
return
new
(
NoopService
),
nil
}
// Set of services all wrapping the base NoopService resulting in the same method
// signatures but different outer types.
type
NoopServiceA
struct
{
NoopService
}
type
NoopServiceB
struct
{
NoopService
}
type
NoopServiceC
struct
{
NoopService
}
type
NoopServiceD
struct
{
NoopService
}
func
NewNoopServiceA
(
*
ServiceContext
)
(
Service
,
error
)
{
return
new
(
NoopServiceA
),
nil
}
func
NewNoopServiceB
(
*
ServiceContext
)
(
Service
,
error
)
{
return
new
(
NoopServiceB
),
nil
}
func
NewNoopServiceC
(
*
ServiceContext
)
(
Service
,
error
)
{
return
new
(
NoopServiceC
),
nil
}
func
NewNoopServiceD
(
*
ServiceContext
)
(
Service
,
error
)
{
return
new
(
NoopServiceD
),
nil
}
// InstrumentedService is an implementation of Service for which all interface
// methods can be instrumented both return value as well as event hook wise.
type
InstrumentedService
struct
{
protocols
[]
p2p
.
Protocol
start
error
stop
error
protocolsHook
func
()
startHook
func
(
*
p2p
.
Server
)
stopHook
func
()
}
func
NewInstrumentedService
(
*
ServiceContext
)
(
Service
,
error
)
{
return
new
(
InstrumentedService
),
nil
}
func
(
s
*
InstrumentedService
)
Protocols
()
[]
p2p
.
Protocol
{
if
s
.
protocolsHook
!=
nil
{
s
.
protocolsHook
()
}
return
s
.
protocols
}
func
(
s
*
InstrumentedService
)
Start
(
server
*
p2p
.
Server
)
error
{
if
s
.
startHook
!=
nil
{
s
.
startHook
(
server
)
}
return
s
.
start
}
func
(
s
*
InstrumentedService
)
Stop
()
error
{
if
s
.
stopHook
!=
nil
{
s
.
stopHook
()
}
return
s
.
stop
}
// InstrumentingWrapper is a method to specialize a service constructor returning
// a generic InstrumentedService into one returning a wrapping specific one.
type
InstrumentingWrapper
func
(
base
ServiceConstructor
)
ServiceConstructor
func
InstrumentingWrapperMaker
(
base
ServiceConstructor
,
kind
reflect
.
Type
)
ServiceConstructor
{
return
func
(
ctx
*
ServiceContext
)
(
Service
,
error
)
{
obj
,
err
:=
base
(
ctx
)
if
err
!=
nil
{
return
nil
,
err
}
wrapper
:=
reflect
.
New
(
kind
)
wrapper
.
Elem
()
.
Field
(
0
)
.
Set
(
reflect
.
ValueOf
(
obj
)
.
Elem
())
return
wrapper
.
Interface
()
.
(
Service
),
nil
}
}
// Set of services all wrapping the base InstrumentedService resulting in the
// same method signatures but different outer types.
type
InstrumentedServiceA
struct
{
InstrumentedService
}
type
InstrumentedServiceB
struct
{
InstrumentedService
}
type
InstrumentedServiceC
struct
{
InstrumentedService
}
func
InstrumentedServiceMakerA
(
base
ServiceConstructor
)
ServiceConstructor
{
return
InstrumentingWrapperMaker
(
base
,
reflect
.
TypeOf
(
InstrumentedServiceA
{}))
}
func
InstrumentedServiceMakerB
(
base
ServiceConstructor
)
ServiceConstructor
{
return
InstrumentingWrapperMaker
(
base
,
reflect
.
TypeOf
(
InstrumentedServiceB
{}))
}
func
InstrumentedServiceMakerC
(
base
ServiceConstructor
)
ServiceConstructor
{
return
InstrumentingWrapperMaker
(
base
,
reflect
.
TypeOf
(
InstrumentedServiceC
{}))
}
rpc/api/admin.go
View file @
3e1000fd
...
@@ -97,7 +97,7 @@ func NewAdminApi(xeth *xeth.XEth, stack *node.Node, codec codec.Codec) *adminApi
...
@@ -97,7 +97,7 @@ func NewAdminApi(xeth *xeth.XEth, stack *node.Node, codec codec.Codec) *adminApi
coder
:
codec
.
New
(
nil
),
coder
:
codec
.
New
(
nil
),
}
}
if
stack
!=
nil
{
if
stack
!=
nil
{
stack
.
S
ingletonS
ervice
(
&
api
.
ethereum
)
stack
.
Service
(
&
api
.
ethereum
)
}
}
return
api
return
api
}
}
...
...
rpc/api/utils.go
View file @
3e1000fd
...
@@ -165,7 +165,7 @@ func ParseApiString(apistr string, codec codec.Codec, xeth *xeth.XEth, stack *no
...
@@ -165,7 +165,7 @@ func ParseApiString(apistr string, codec codec.Codec, xeth *xeth.XEth, stack *no
var
eth
*
eth
.
Ethereum
var
eth
*
eth
.
Ethereum
if
stack
!=
nil
{
if
stack
!=
nil
{
if
_
,
err
:=
stack
.
Singleton
Service
(
&
eth
);
err
!=
nil
{
if
err
:=
stack
.
Service
(
&
eth
);
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
}
}
...
...
xeth/state.go
View file @
3e1000fd
...
@@ -19,7 +19,6 @@ package xeth
...
@@ -19,7 +19,6 @@ package xeth
import
(
import
(
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/eth"
)
)
type
State
struct
{
type
State
struct
{
...
@@ -46,7 +45,7 @@ func (self *State) SafeGet(addr string) *Object {
...
@@ -46,7 +45,7 @@ func (self *State) SafeGet(addr string) *Object {
func
(
self
*
State
)
safeGet
(
addr
string
)
*
state
.
StateObject
{
func
(
self
*
State
)
safeGet
(
addr
string
)
*
state
.
StateObject
{
object
:=
self
.
state
.
GetStateObject
(
common
.
HexToAddress
(
addr
))
object
:=
self
.
state
.
GetStateObject
(
common
.
HexToAddress
(
addr
))
if
object
==
nil
{
if
object
==
nil
{
object
=
state
.
NewStateObject
(
common
.
HexToAddress
(
addr
),
self
.
xeth
.
backend
.
Service
(
"eth"
)
.
(
*
eth
.
Ethereum
)
.
ChainDb
())
object
=
state
.
NewStateObject
(
common
.
HexToAddress
(
addr
),
self
.
xeth
.
EthereumService
(
)
.
ChainDb
())
}
}
return
object
return
object
}
}
xeth/xeth.go
View file @
3e1000fd
...
@@ -100,8 +100,8 @@ func New(stack *node.Node, frontend Frontend) *XEth {
...
@@ -100,8 +100,8 @@ func New(stack *node.Node, frontend Frontend) *XEth {
ethereum
*
eth
.
Ethereum
ethereum
*
eth
.
Ethereum
whisper
*
whisper
.
Whisper
whisper
*
whisper
.
Whisper
)
)
stack
.
S
ingletonS
ervice
(
&
ethereum
)
stack
.
Service
(
&
ethereum
)
stack
.
S
ingletonS
ervice
(
&
whisper
)
stack
.
Service
(
&
whisper
)
xeth
:=
&
XEth
{
xeth
:=
&
XEth
{
backend
:
stack
,
backend
:
stack
,
...
@@ -130,7 +130,7 @@ func New(stack *node.Node, frontend Frontend) *XEth {
...
@@ -130,7 +130,7 @@ func New(stack *node.Node, frontend Frontend) *XEth {
func
(
self
*
XEth
)
EthereumService
()
*
eth
.
Ethereum
{
func
(
self
*
XEth
)
EthereumService
()
*
eth
.
Ethereum
{
var
ethereum
*
eth
.
Ethereum
var
ethereum
*
eth
.
Ethereum
if
_
,
err
:=
self
.
backend
.
Singleton
Service
(
&
ethereum
);
err
!=
nil
{
if
err
:=
self
.
backend
.
Service
(
&
ethereum
);
err
!=
nil
{
return
nil
return
nil
}
}
return
ethereum
return
ethereum
...
@@ -138,7 +138,7 @@ func (self *XEth) EthereumService() *eth.Ethereum {
...
@@ -138,7 +138,7 @@ func (self *XEth) EthereumService() *eth.Ethereum {
func
(
self
*
XEth
)
WhisperService
()
*
whisper
.
Whisper
{
func
(
self
*
XEth
)
WhisperService
()
*
whisper
.
Whisper
{
var
whisper
*
whisper
.
Whisper
var
whisper
*
whisper
.
Whisper
if
_
,
err
:=
self
.
backend
.
Singleton
Service
(
&
whisper
);
err
!=
nil
{
if
err
:=
self
.
backend
.
Service
(
&
whisper
);
err
!=
nil
{
return
nil
return
nil
}
}
return
whisper
return
whisper
...
...
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