Skip to content

Commit 084a8ec

Browse files
committed
cmd, eth: added light client and light server modes
1 parent e9e676a commit 084a8ec

File tree

18 files changed

+313
-106
lines changed

18 files changed

+313
-106
lines changed

cmd/geth/chaincmd.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ func exportChain(ctx *cli.Context) error {
142142

143143
func removeDB(ctx *cli.Context) error {
144144
stack := utils.MakeNode(ctx, clientIdentifier, gitCommit)
145-
dbdir := stack.ResolvePath("chaindata")
145+
dbdir := stack.ResolvePath(utils.ChainDbName(ctx))
146146
if !common.FileExist(dbdir) {
147147
fmt.Println(dbdir, "does not exist")
148148
return nil

cmd/geth/main.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import (
4141
"github.com/ethereum/go-ethereum/logger/glog"
4242
"github.com/ethereum/go-ethereum/metrics"
4343
"github.com/ethereum/go-ethereum/node"
44+
"github.com/ethereum/go-ethereum/p2p/discover"
4445
"gopkg.in/urfave/cli.v1"
4546
)
4647

@@ -134,6 +135,10 @@ participating.
134135
utils.KeyStoreDirFlag,
135136
utils.OlympicFlag,
136137
utils.FastSyncFlag,
138+
utils.LightModeFlag,
139+
utils.NoDefSrvFlag,
140+
utils.LightServFlag,
141+
utils.LightPeersFlag,
137142
utils.CacheFlag,
138143
utils.LightKDFFlag,
139144
utils.JSpathFlag,
@@ -296,6 +301,31 @@ func startNode(ctx *cli.Context, stack *node.Node) {
296301
// Start up the node itself
297302
utils.StartNode(stack)
298303

304+
if ctx.GlobalBool(utils.LightModeFlag.Name) && !ctx.GlobalBool(utils.NoDefSrvFlag.Name) {
305+
// add default light server; test phase only
306+
addPeer := func(url string) {
307+
node, err := discover.ParseNode(url)
308+
if err == nil {
309+
stack.Server().AddPeer(node)
310+
}
311+
}
312+
313+
if ctx.GlobalBool(utils.TestNetFlag.Name) {
314+
// TestNet (John Gerryts @phonikg)
315+
addPeer("enode://d72af45ba9b60851a8077a4eb07700484b585e5f2e55024e0c93b7ec7d114f2e3fa3c8f3a3358f89da00a609f5a062415deb857ada863b8cdad02b0b0bc90da3@50.112.52.169:30301")
316+
} else {
317+
if ctx.GlobalBool(utils.OpposeDAOFork.Name) {
318+
// Classic (Azure)
319+
addPeer("enode://fc3d7b57e5d317946bf421411632ec98d5ffcbf94548cd7bc10088e4fef176670f8ec70280d301a9d0b22fe498203f62b323da15b3acc18b02a1fee2a06b7d3f@40.118.3.223:30305")
320+
} else {
321+
// MainNet (Azure)
322+
addPeer("enode://feaf206a308a669a789be45f4dadcb351246051727f12415ad69e44f8080daf0569c10fe1d9944d245dd1f3e1c89cedda8ce03d7e3d5ed8975a35cad4b4f7ec1@40.118.3.223:30303")
323+
// MainNet (John Gerryts @phonikg)
324+
addPeer("enode://02b80f0d47c7c157c069d0584067a284cdf188b9267666234b872e70d936a803ad20ea27f78ef1fd6425ae4b7108907e1875adbca96b038004114ac4d1e529a3@50.112.52.169:30300")
325+
}
326+
}
327+
}
328+
299329
// Unlock any account specifically requested
300330
accman := stack.AccountManager()
301331
passwords := utils.MakePasswordList(ctx)

cmd/geth/usage.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ var AppHelpFlagGroups = []flagGroup{
7272
utils.DevModeFlag,
7373
utils.IdentityFlag,
7474
utils.FastSyncFlag,
75+
utils.LightModeFlag,
76+
utils.NoDefSrvFlag,
77+
utils.LightServFlag,
78+
utils.LightPeersFlag,
7579
utils.LightKDFFlag,
7680
utils.CacheFlag,
7781
},

cmd/utils/flags.go

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ import (
3939
"github.com/ethereum/go-ethereum/eth"
4040
"github.com/ethereum/go-ethereum/ethdb"
4141
"github.com/ethereum/go-ethereum/event"
42+
"github.com/ethereum/go-ethereum/les"
43+
"github.com/ethereum/go-ethereum/light"
4244
"github.com/ethereum/go-ethereum/logger"
4345
"github.com/ethereum/go-ethereum/logger/glog"
4446
"github.com/ethereum/go-ethereum/metrics"
@@ -150,6 +152,24 @@ var (
150152
Name: "fast",
151153
Usage: "Enable fast syncing through state downloads",
152154
}
155+
LightModeFlag = cli.BoolFlag{
156+
Name: "light",
157+
Usage: "Enable light client mode",
158+
}
159+
NoDefSrvFlag = cli.BoolFlag{
160+
Name: "nodefsrv",
161+
Usage: "Don't add default LES server (only for test version)",
162+
}
163+
LightServFlag = cli.IntFlag{
164+
Name: "lightserv",
165+
Usage: "Maximum percentage of time allowed for serving LES requests (0-90)",
166+
Value: 0,
167+
}
168+
LightPeersFlag = cli.IntFlag{
169+
Name: "lightpeers",
170+
Usage: "Maximum number of LES client peers",
171+
Value: 20,
172+
}
153173
LightKDFFlag = cli.BoolFlag{
154174
Name: "lightkdf",
155175
Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
@@ -679,6 +699,11 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {
679699
Etherbase: MakeEtherbase(stack.AccountManager(), ctx),
680700
ChainConfig: MakeChainConfig(ctx, stack),
681701
FastSync: ctx.GlobalBool(FastSyncFlag.Name),
702+
LightMode: ctx.GlobalBool(LightModeFlag.Name),
703+
NoDefSrv: ctx.GlobalBool(NoDefSrvFlag.Name),
704+
LightServ: ctx.GlobalInt(LightServFlag.Name),
705+
LightPeers: ctx.GlobalInt(LightPeersFlag.Name),
706+
MaxPeers: ctx.GlobalInt(MaxPeersFlag.Name),
682707
DatabaseCache: ctx.GlobalInt(CacheFlag.Name),
683708
DatabaseHandles: MakeDatabaseHandles(),
684709
NetworkId: ctx.GlobalInt(NetworkIdFlag.Name),
@@ -713,6 +738,7 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {
713738
}
714739
ethConf.Genesis = core.TestNetGenesisBlock()
715740
state.StartingNonce = 1048576 // (2**20)
741+
light.StartingNonce = 1048576 // (2**20)
716742

717743
case ctx.GlobalBool(DevModeFlag.Name):
718744
ethConf.Genesis = core.OlympicGenesisBlock()
@@ -722,10 +748,23 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {
722748
ethConf.PowTest = true
723749
}
724750

725-
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
726-
return eth.New(ctx, ethConf)
727-
}); err != nil {
728-
Fatalf("Failed to register the Ethereum service: %v", err)
751+
if ethConf.LightMode {
752+
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
753+
return les.New(ctx, ethConf)
754+
}); err != nil {
755+
Fatalf("Failed to register the Ethereum light node service: %v", err)
756+
}
757+
} else {
758+
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
759+
fullNode, err := eth.New(ctx, ethConf)
760+
if fullNode != nil && ethConf.LightServ > 0 {
761+
ls, _ := les.NewLesServer(fullNode, ethConf)
762+
fullNode.AddLesServer(ls)
763+
}
764+
return fullNode, err
765+
}); err != nil {
766+
Fatalf("Failed to register the Ethereum full node service: %v", err)
767+
}
729768
}
730769
}
731770

@@ -809,14 +848,23 @@ func MakeChainConfigFromDb(ctx *cli.Context, db ethdb.Database) *core.ChainConfi
809848
return config
810849
}
811850

851+
func ChainDbName(ctx *cli.Context) string {
852+
if ctx.GlobalBool(LightModeFlag.Name) {
853+
return "lightchaindata"
854+
} else {
855+
return "chaindata"
856+
}
857+
}
858+
812859
// MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
813860
func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
814861
var (
815862
cache = ctx.GlobalInt(CacheFlag.Name)
816863
handles = MakeDatabaseHandles()
864+
name = ChainDbName(ctx)
817865
)
818866

819-
chainDb, err := stack.OpenDatabase("chaindata", cache, handles)
867+
chainDb, err := stack.OpenDatabase(name, cache, handles)
820868
if err != nil {
821869
Fatalf("Could not open database: %v", err)
822870
}

contracts/release/release.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import (
2727
"github.com/ethereum/go-ethereum/accounts/abi/bind"
2828
"github.com/ethereum/go-ethereum/common"
2929
"github.com/ethereum/go-ethereum/eth"
30+
"github.com/ethereum/go-ethereum/internal/ethapi"
31+
"github.com/ethereum/go-ethereum/les"
3032
"github.com/ethereum/go-ethereum/logger"
3133
"github.com/ethereum/go-ethereum/logger/glog"
3234
"github.com/ethereum/go-ethereum/node"
@@ -60,12 +62,20 @@ type ReleaseService struct {
6062
// releases and notify the user of such.
6163
func NewReleaseService(ctx *node.ServiceContext, config Config) (node.Service, error) {
6264
// Retrieve the Ethereum service dependency to access the blockchain
65+
var apiBackend ethapi.Backend
6366
var ethereum *eth.Ethereum
64-
if err := ctx.Service(&ethereum); err != nil {
65-
return nil, err
67+
if err := ctx.Service(&ethereum); err == nil {
68+
apiBackend = ethereum.ApiBackend
69+
} else {
70+
var ethereum *les.LightEthereum
71+
if err := ctx.Service(&ethereum); err == nil {
72+
apiBackend = ethereum.ApiBackend
73+
} else {
74+
return nil, err
75+
}
6676
}
6777
// Construct the release service
68-
contract, err := NewReleaseOracle(config.Oracle, eth.NewContractBackend(ethereum))
78+
contract, err := NewReleaseOracle(config.Oracle, eth.NewContractBackend(apiBackend))
6979
if err != nil {
7080
return nil, err
7181
}

eth/backend.go

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,14 @@ var (
6666
type Config struct {
6767
ChainConfig *core.ChainConfig // chain configuration
6868

69-
NetworkId int // Network ID to use for selecting peers to connect to
70-
Genesis string // Genesis JSON to seed the chain database with
71-
FastSync bool // Enables the state download based fast synchronisation algorithm
69+
NetworkId int // Network ID to use for selecting peers to connect to
70+
Genesis string // Genesis JSON to seed the chain database with
71+
FastSync bool // Enables the state download based fast synchronisation algorithm
72+
LightMode bool // Running in light client mode
73+
NoDefSrv bool // No default LES server
74+
LightServ int // Maximum percentage of time allowed for serving LES requests
75+
LightPeers int // Maximum number of LES client peers
76+
MaxPeers int // Maximum number of global peers
7277

7378
SkipBcVersionCheck bool // e.g. blockchain export
7479
DatabaseCache int
@@ -100,6 +105,12 @@ type Config struct {
100105
TestGenesisState ethdb.Database // Genesis state to seed the database with (testing only!)
101106
}
102107

108+
type LesServer interface {
109+
Start()
110+
Stop()
111+
Protocols() []p2p.Protocol
112+
}
113+
103114
// Ethereum implements the Ethereum full node service.
104115
type Ethereum struct {
105116
chainConfig *core.ChainConfig
@@ -111,6 +122,7 @@ type Ethereum struct {
111122
txMu sync.Mutex
112123
blockchain *core.BlockChain
113124
protocolManager *ProtocolManager
125+
lesServer LesServer
114126
// DB interfaces
115127
chainDb ethdb.Database // Block chain database
116128

@@ -119,7 +131,7 @@ type Ethereum struct {
119131
httpclient *httpclient.HTTPClient
120132
accountManager *accounts.Manager
121133

122-
apiBackend *EthApiBackend
134+
ApiBackend *EthApiBackend
123135

124136
miner *miner.Miner
125137
Mining bool
@@ -135,10 +147,14 @@ type Ethereum struct {
135147
netRPCService *ethapi.PublicNetAPI
136148
}
137149

150+
func (s *Ethereum) AddLesServer(ls LesServer) {
151+
s.lesServer = ls
152+
}
153+
138154
// New creates a new Ethereum object (including the
139155
// initialisation of the common Ethereum object)
140156
func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
141-
chainDb, err := createDB(ctx, config)
157+
chainDb, err := CreateDB(ctx, config, "chaindata")
142158
if err != nil {
143159
return nil, err
144160
}
@@ -217,7 +233,18 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
217233
newPool := core.NewTxPool(eth.chainConfig, eth.EventMux(), eth.blockchain.State, eth.blockchain.GasLimit)
218234
eth.txPool = newPool
219235

220-
if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.FastSync, config.NetworkId, eth.eventMux, eth.txPool, eth.pow, eth.blockchain, chainDb); err != nil {
236+
maxPeers := config.MaxPeers
237+
if config.LightServ > 0 {
238+
// if we are running a light server, limit the number of ETH peers so that we reserve some space for incoming LES connections
239+
// temporary solution until the new peer connectivity API is finished
240+
halfPeers := maxPeers / 2
241+
maxPeers -= config.LightPeers
242+
if maxPeers < halfPeers {
243+
maxPeers = halfPeers
244+
}
245+
}
246+
247+
if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.FastSync, config.NetworkId, maxPeers, eth.eventMux, eth.txPool, eth.pow, eth.blockchain, chainDb); err != nil {
221248
return nil, err
222249
}
223250
eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.pow)
@@ -233,14 +260,14 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
233260
GpobaseCorrectionFactor: config.GpobaseCorrectionFactor,
234261
}
235262
gpo := gasprice.NewGasPriceOracle(eth.blockchain, chainDb, eth.eventMux, gpoParams)
236-
eth.apiBackend = &EthApiBackend{eth, gpo}
263+
eth.ApiBackend = &EthApiBackend{eth, gpo}
237264

238265
return eth, nil
239266
}
240267

241-
// createDB creates the chain database.
242-
func createDB(ctx *node.ServiceContext, config *Config) (ethdb.Database, error) {
243-
db, err := ctx.OpenDatabase("chaindata", config.DatabaseCache, config.DatabaseHandles)
268+
// CreateDB creates the chain database.
269+
func CreateDB(ctx *node.ServiceContext, config *Config, name string) (ethdb.Database, error) {
270+
db, err := ctx.OpenDatabase(name, config.DatabaseCache, config.DatabaseHandles)
244271
if db, ok := db.(*ethdb.LDBDatabase); ok {
245272
db.Meter("eth/db/chaindata/")
246273
}
@@ -288,7 +315,7 @@ func CreatePoW(config *Config) (*ethash.Ethash, error) {
288315
// APIs returns the collection of RPC services the ethereum package offers.
289316
// NOTE, some of these services probably need to be moved to somewhere else.
290317
func (s *Ethereum) APIs() []rpc.API {
291-
return append(ethapi.GetAPIs(s.apiBackend, s.solcPath), []rpc.API{
318+
return append(ethapi.GetAPIs(s.ApiBackend, s.solcPath), []rpc.API{
292319
{
293320
Namespace: "eth",
294321
Version: "1.0",
@@ -312,7 +339,7 @@ func (s *Ethereum) APIs() []rpc.API {
312339
}, {
313340
Namespace: "eth",
314341
Version: "1.0",
315-
Service: filters.NewPublicFilterAPI(s.chainDb, s.eventMux),
342+
Service: filters.NewPublicFilterAPI(s.ApiBackend, true),
316343
Public: true,
317344
}, {
318345
Namespace: "admin",
@@ -380,7 +407,11 @@ func (s *Ethereum) Downloader() *downloader.Downloader { return s.protocolManage
380407
// Protocols implements node.Service, returning all the currently configured
381408
// network protocols to start.
382409
func (s *Ethereum) Protocols() []p2p.Protocol {
383-
return s.protocolManager.SubProtocols
410+
if s.lesServer == nil {
411+
return s.protocolManager.SubProtocols
412+
} else {
413+
return append(s.protocolManager.SubProtocols, s.lesServer.Protocols()...)
414+
}
384415
}
385416

386417
// Start implements node.Service, starting all internal goroutines needed by the
@@ -391,6 +422,9 @@ func (s *Ethereum) Start(srvr *p2p.Server) error {
391422
s.StartAutoDAG()
392423
}
393424
s.protocolManager.Start()
425+
if s.lesServer != nil {
426+
s.lesServer.Start()
427+
}
394428
return nil
395429
}
396430

@@ -402,6 +436,9 @@ func (s *Ethereum) Stop() error {
402436
}
403437
s.blockchain.Stop()
404438
s.protocolManager.Stop()
439+
if s.lesServer != nil {
440+
s.lesServer.Stop()
441+
}
405442
s.txPool.Stop()
406443
s.miner.Stop()
407444
s.eventMux.Stop()

eth/bind.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ type ContractBackend struct {
4343

4444
// NewContractBackend creates a new native contract backend using an existing
4545
// Etheruem object.
46-
func NewContractBackend(eth *Ethereum) *ContractBackend {
46+
func NewContractBackend(apiBackend ethapi.Backend) *ContractBackend {
4747
return &ContractBackend{
48-
eapi: ethapi.NewPublicEthereumAPI(eth.apiBackend),
49-
bcapi: ethapi.NewPublicBlockChainAPI(eth.apiBackend),
50-
txapi: ethapi.NewPublicTransactionPoolAPI(eth.apiBackend),
48+
eapi: ethapi.NewPublicEthereumAPI(apiBackend),
49+
bcapi: ethapi.NewPublicBlockChainAPI(apiBackend),
50+
txapi: ethapi.NewPublicTransactionPoolAPI(apiBackend),
5151
}
5252
}
5353

0 commit comments

Comments
 (0)