Skip to content

Commit

Permalink
cmd, eth: added light client and light server modes
Browse files Browse the repository at this point in the history
  • Loading branch information
zsfelfoldi authored and fjl committed Nov 9, 2016
1 parent 9f8d192 commit 7db7109
Show file tree
Hide file tree
Showing 17 changed files with 298 additions and 94 deletions.
2 changes: 1 addition & 1 deletion cmd/geth/chaincmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ func exportChain(ctx *cli.Context) error {

func removeDB(ctx *cli.Context) error {
stack := utils.MakeNode(ctx, clientIdentifier, gitCommit)
dbdir := stack.ResolvePath("chaindata")
dbdir := stack.ResolvePath(utils.ChainDbName(ctx))
if !common.FileExist(dbdir) {
fmt.Println(dbdir, "does not exist")
return nil
Expand Down
30 changes: 30 additions & 0 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import (
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p/discover"
"gopkg.in/urfave/cli.v1"
)

Expand Down Expand Up @@ -118,6 +119,10 @@ participating.
utils.KeyStoreDirFlag,
utils.OlympicFlag,
utils.FastSyncFlag,
utils.LightModeFlag,
utils.NoDefSrvFlag,
utils.LightServFlag,
utils.LightPeersFlag,
utils.LightKDFFlag,
utils.CacheFlag,
utils.TrieCacheGenFlag,
Expand Down Expand Up @@ -280,6 +285,31 @@ func startNode(ctx *cli.Context, stack *node.Node) {
// Start up the node itself
utils.StartNode(stack)

if ctx.GlobalBool(utils.LightModeFlag.Name) && !ctx.GlobalBool(utils.NoDefSrvFlag.Name) {
// add default light server; test phase only
addPeer := func(url string) {
node, err := discover.ParseNode(url)
if err == nil {
stack.Server().AddPeer(node)
}
}

if ctx.GlobalBool(utils.TestNetFlag.Name) {
// TestNet (John Gerryts @phonikg)
addPeer("enode://d72af45ba9b60851a8077a4eb07700484b585e5f2e55024e0c93b7ec7d114f2e3fa3c8f3a3358f89da00a609f5a062415deb857ada863b8cdad02b0b0bc90da3@50.112.52.169:30301")
} else {
if ctx.GlobalBool(utils.OpposeDAOFork.Name) {
// Classic (Azure)
addPeer("enode://fc3d7b57e5d317946bf421411632ec98d5ffcbf94548cd7bc10088e4fef176670f8ec70280d301a9d0b22fe498203f62b323da15b3acc18b02a1fee2a06b7d3f@40.118.3.223:30305")
} else {
// MainNet (Azure)
addPeer("enode://feaf206a308a669a789be45f4dadcb351246051727f12415ad69e44f8080daf0569c10fe1d9944d245dd1f3e1c89cedda8ce03d7e3d5ed8975a35cad4b4f7ec1@40.118.3.223:30303")
// MainNet (John Gerryts @phonikg)
addPeer("enode://02b80f0d47c7c157c069d0584067a284cdf188b9267666234b872e70d936a803ad20ea27f78ef1fd6425ae4b7108907e1875adbca96b038004114ac4d1e529a3@50.112.52.169:30300")
}
}
}

// Unlock any account specifically requested
accman := stack.AccountManager()
passwords := utils.MakePasswordList(ctx)
Expand Down
4 changes: 4 additions & 0 deletions cmd/geth/usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ var AppHelpFlagGroups = []flagGroup{
utils.DevModeFlag,
utils.IdentityFlag,
utils.FastSyncFlag,
utils.LightModeFlag,
utils.NoDefSrvFlag,
utils.LightServFlag,
utils.LightPeersFlag,
utils.LightKDFFlag,
},
},
Expand Down
58 changes: 53 additions & 5 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ import (
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/les"
"github.com/ethereum/go-ethereum/light"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/metrics"
Expand Down Expand Up @@ -145,6 +147,24 @@ var (
Name: "fast",
Usage: "Enable fast syncing through state downloads",
}
LightModeFlag = cli.BoolFlag{
Name: "light",
Usage: "Enable light client mode",
}
NoDefSrvFlag = cli.BoolFlag{
Name: "nodefsrv",
Usage: "Don't add default LES server (only for test version)",
}
LightServFlag = cli.IntFlag{
Name: "lightserv",
Usage: "Maximum percentage of time allowed for serving LES requests (0-90)",
Value: 0,
}
LightPeersFlag = cli.IntFlag{
Name: "lightpeers",
Usage: "Maximum number of LES client peers",
Value: 20,
}
LightKDFFlag = cli.BoolFlag{
Name: "lightkdf",
Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
Expand Down Expand Up @@ -680,6 +700,11 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {
Etherbase: MakeEtherbase(stack.AccountManager(), ctx),
ChainConfig: MakeChainConfig(ctx, stack),
FastSync: ctx.GlobalBool(FastSyncFlag.Name),
LightMode: ctx.GlobalBool(LightModeFlag.Name),
NoDefSrv: ctx.GlobalBool(NoDefSrvFlag.Name),
LightServ: ctx.GlobalInt(LightServFlag.Name),
LightPeers: ctx.GlobalInt(LightPeersFlag.Name),
MaxPeers: ctx.GlobalInt(MaxPeersFlag.Name),
DatabaseCache: ctx.GlobalInt(CacheFlag.Name),
DatabaseHandles: MakeDatabaseHandles(),
NetworkId: ctx.GlobalInt(NetworkIdFlag.Name),
Expand Down Expand Up @@ -714,6 +739,7 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {
}
ethConf.Genesis = core.TestNetGenesisBlock()
state.StartingNonce = 1048576 // (2**20)
light.StartingNonce = 1048576 // (2**20)

case ctx.GlobalBool(DevModeFlag.Name):
ethConf.Genesis = core.OlympicGenesisBlock()
Expand All @@ -727,10 +753,23 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {
state.MaxTrieCacheGen = uint16(gen)
}

if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
return eth.New(ctx, ethConf)
}); err != nil {
Fatalf("Failed to register the Ethereum service: %v", err)
if ethConf.LightMode {
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
return les.New(ctx, ethConf)
}); err != nil {
Fatalf("Failed to register the Ethereum light node service: %v", err)
}
} else {
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
fullNode, err := eth.New(ctx, ethConf)
if fullNode != nil && ethConf.LightServ > 0 {
ls, _ := les.NewLesServer(fullNode, ethConf)
fullNode.AddLesServer(ls)
}
return fullNode, err
}); err != nil {
Fatalf("Failed to register the Ethereum full node service: %v", err)
}
}
}

Expand Down Expand Up @@ -830,14 +869,23 @@ func MakeChainConfigFromDb(ctx *cli.Context, db ethdb.Database) *core.ChainConfi
return config
}

func ChainDbName(ctx *cli.Context) string {
if ctx.GlobalBool(LightModeFlag.Name) {
return "lightchaindata"
} else {
return "chaindata"
}
}

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

chainDb, err := stack.OpenDatabase("chaindata", cache, handles)
chainDb, err := stack.OpenDatabase(name, cache, handles)
if err != nil {
Fatalf("Could not open database: %v", err)
}
Expand Down
16 changes: 13 additions & 3 deletions contracts/release/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/les"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/node"
Expand Down Expand Up @@ -60,12 +62,20 @@ type ReleaseService struct {
// releases and notify the user of such.
func NewReleaseService(ctx *node.ServiceContext, config Config) (node.Service, error) {
// Retrieve the Ethereum service dependency to access the blockchain
var apiBackend ethapi.Backend
var ethereum *eth.Ethereum
if err := ctx.Service(&ethereum); err != nil {
return nil, err
if err := ctx.Service(&ethereum); err == nil {
apiBackend = ethereum.ApiBackend
} else {
var ethereum *les.LightEthereum
if err := ctx.Service(&ethereum); err == nil {
apiBackend = ethereum.ApiBackend
} else {
return nil, err
}
}
// Construct the release service
contract, err := NewReleaseOracle(config.Oracle, eth.NewContractBackend(ethereum))
contract, err := NewReleaseOracle(config.Oracle, eth.NewContractBackend(apiBackend))
if err != nil {
return nil, err
}
Expand Down
61 changes: 49 additions & 12 deletions eth/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,14 @@ var (
type Config struct {
ChainConfig *core.ChainConfig // chain configuration

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

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

type LesServer interface {
Start()
Stop()
Protocols() []p2p.Protocol
}

// Ethereum implements the Ethereum full node service.
type Ethereum struct {
chainConfig *core.ChainConfig
Expand All @@ -111,6 +122,7 @@ type Ethereum struct {
txMu sync.Mutex
blockchain *core.BlockChain
protocolManager *ProtocolManager
lesServer LesServer
// DB interfaces
chainDb ethdb.Database // Block chain database

Expand All @@ -119,7 +131,7 @@ type Ethereum struct {
httpclient *httpclient.HTTPClient
accountManager *accounts.Manager

apiBackend *EthApiBackend
ApiBackend *EthApiBackend

miner *miner.Miner
Mining bool
Expand All @@ -135,10 +147,14 @@ type Ethereum struct {
netRPCService *ethapi.PublicNetAPI
}

func (s *Ethereum) AddLesServer(ls LesServer) {
s.lesServer = ls
}

// New creates a new Ethereum object (including the
// initialisation of the common Ethereum object)
func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
chainDb, err := createDB(ctx, config)
chainDb, err := CreateDB(ctx, config, "chaindata")
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -217,7 +233,18 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
newPool := core.NewTxPool(eth.chainConfig, eth.EventMux(), eth.blockchain.State, eth.blockchain.GasLimit)
eth.txPool = newPool

if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.FastSync, config.NetworkId, eth.eventMux, eth.txPool, eth.pow, eth.blockchain, chainDb); err != nil {
maxPeers := config.MaxPeers
if config.LightServ > 0 {
// if we are running a light server, limit the number of ETH peers so that we reserve some space for incoming LES connections
// temporary solution until the new peer connectivity API is finished
halfPeers := maxPeers / 2
maxPeers -= config.LightPeers
if maxPeers < halfPeers {
maxPeers = halfPeers
}
}

if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.FastSync, config.NetworkId, maxPeers, eth.eventMux, eth.txPool, eth.pow, eth.blockchain, chainDb); err != nil {
return nil, err
}
eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.pow)
Expand All @@ -233,14 +260,14 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
GpobaseCorrectionFactor: config.GpobaseCorrectionFactor,
}
gpo := gasprice.NewGasPriceOracle(eth.blockchain, chainDb, eth.eventMux, gpoParams)
eth.apiBackend = &EthApiBackend{eth, gpo}
eth.ApiBackend = &EthApiBackend{eth, gpo}

return eth, nil
}

// createDB creates the chain database.
func createDB(ctx *node.ServiceContext, config *Config) (ethdb.Database, error) {
db, err := ctx.OpenDatabase("chaindata", config.DatabaseCache, config.DatabaseHandles)
// CreateDB creates the chain database.
func CreateDB(ctx *node.ServiceContext, config *Config, name string) (ethdb.Database, error) {
db, err := ctx.OpenDatabase(name, config.DatabaseCache, config.DatabaseHandles)
if db, ok := db.(*ethdb.LDBDatabase); ok {
db.Meter("eth/db/chaindata/")
}
Expand Down Expand Up @@ -288,7 +315,7 @@ func CreatePoW(config *Config) (*ethash.Ethash, error) {
// APIs returns the collection of RPC services the ethereum package offers.
// NOTE, some of these services probably need to be moved to somewhere else.
func (s *Ethereum) APIs() []rpc.API {
return append(ethapi.GetAPIs(s.apiBackend, s.solcPath), []rpc.API{
return append(ethapi.GetAPIs(s.ApiBackend, s.solcPath), []rpc.API{
{
Namespace: "eth",
Version: "1.0",
Expand Down Expand Up @@ -391,7 +418,11 @@ func (s *Ethereum) Downloader() *downloader.Downloader { return s.protocolManage
// Protocols implements node.Service, returning all the currently configured
// network protocols to start.
func (s *Ethereum) Protocols() []p2p.Protocol {
return s.protocolManager.SubProtocols
if s.lesServer == nil {
return s.protocolManager.SubProtocols
} else {
return append(s.protocolManager.SubProtocols, s.lesServer.Protocols()...)
}
}

// Start implements node.Service, starting all internal goroutines needed by the
Expand All @@ -402,6 +433,9 @@ func (s *Ethereum) Start(srvr *p2p.Server) error {
s.StartAutoDAG()
}
s.protocolManager.Start()
if s.lesServer != nil {
s.lesServer.Start()
}
return nil
}

Expand All @@ -413,6 +447,9 @@ func (s *Ethereum) Stop() error {
}
s.blockchain.Stop()
s.protocolManager.Stop()
if s.lesServer != nil {
s.lesServer.Stop()
}
s.txPool.Stop()
s.miner.Stop()
s.eventMux.Stop()
Expand Down
8 changes: 4 additions & 4 deletions eth/bind.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ type ContractBackend struct {

// NewContractBackend creates a new native contract backend using an existing
// Etheruem object.
func NewContractBackend(eth *Ethereum) *ContractBackend {
func NewContractBackend(apiBackend ethapi.Backend) *ContractBackend {
return &ContractBackend{
eapi: ethapi.NewPublicEthereumAPI(eth.apiBackend),
bcapi: ethapi.NewPublicBlockChainAPI(eth.apiBackend),
txapi: ethapi.NewPublicTransactionPoolAPI(eth.apiBackend),
eapi: ethapi.NewPublicEthereumAPI(apiBackend),
bcapi: ethapi.NewPublicBlockChainAPI(apiBackend),
txapi: ethapi.NewPublicTransactionPoolAPI(apiBackend),
}
}

Expand Down
Loading

0 comments on commit 7db7109

Please sign in to comment.