Skip to content

Commit

Permalink
internal/cli/server, eth: add option to disable personal wallet endpo…
Browse files Browse the repository at this point in the history
…ints (ethereum#394)

* initial disable-bor-wallet implementation

* fixes and enhancements

* update docs using clidoc

* fixes in clique auth
  • Loading branch information
manav2401 committed May 23, 2022
1 parent cd1a899 commit 1b53044
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 42 deletions.
2 changes: 2 additions & 0 deletions docs/cli/server.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ The ```bor server``` command runs the Bor client.

- ```gpo.ignoreprice```: Gas price below which gpo will ignore transactions

- ```disable-bor-wallet```: Disable the personal wallet endpoints

- ```grpc.addr```: Address and port to bind the GRPC server

- ```dev```: Enable developer mode with ephemeral proof-of-authority network and a pre-funded developer account, mining enabled
Expand Down
53 changes: 34 additions & 19 deletions eth/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ type Ethereum struct {
eventMux *event.TypeMux
engine consensus.Engine
accountManager *accounts.Manager
authorized bool // If consensus engine is authorized with keystore

bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests
bloomIndexer *core.ChainIndexer // Bloom indexer operating during block imports
Expand Down Expand Up @@ -153,6 +154,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
chainDb: chainDb,
eventMux: stack.EventMux(),
accountManager: stack.AccountManager(),
authorized: false,
engine: nil,
closeBloomHandler: make(chan struct{}),
networkID: config.NetworkId,
Expand Down Expand Up @@ -485,29 +487,34 @@ func (s *Ethereum) StartMining(threads int) error {
log.Error("Cannot start mining without etherbase", "err", err)
return fmt.Errorf("etherbase missing: %v", err)
}
var cli *clique.Clique
if c, ok := s.engine.(*clique.Clique); ok {
cli = c
} else if cl, ok := s.engine.(*beacon.Beacon); ok {
if c, ok := cl.InnerEngine().(*clique.Clique); ok {

// If personal endpoints are disabled, the server creating
// this Ethereum instance has already Authorized consensus.
if !s.authorized {
var cli *clique.Clique
if c, ok := s.engine.(*clique.Clique); ok {
cli = c
} else if cl, ok := s.engine.(*beacon.Beacon); ok {
if c, ok := cl.InnerEngine().(*clique.Clique); ok {
cli = c
}
}
}
if cli != nil {
wallet, err := s.accountManager.Find(accounts.Account{Address: eb})
if wallet == nil || err != nil {
log.Error("Etherbase account unavailable locally", "err", err)
return fmt.Errorf("signer missing: %v", err)
if cli != nil {
wallet, err := s.accountManager.Find(accounts.Account{Address: eb})
if wallet == nil || err != nil {
log.Error("Etherbase account unavailable locally", "err", err)
return fmt.Errorf("signer missing: %v", err)
}
cli.Authorize(eb, wallet.SignData)
}
cli.Authorize(eb, wallet.SignData)
}
if bor, ok := s.engine.(*bor.Bor); ok {
wallet, err := s.accountManager.Find(accounts.Account{Address: eb})
if wallet == nil || err != nil {
log.Error("Etherbase account unavailable locally", "err", err)
return fmt.Errorf("signer missing: %v", err)
if bor, ok := s.engine.(*bor.Bor); ok {
wallet, err := s.accountManager.Find(accounts.Account{Address: eb})
if wallet == nil || err != nil {
log.Error("Etherbase account unavailable locally", "err", err)
return fmt.Errorf("signer missing: %v", err)
}
bor.Authorize(eb, wallet.SignData)
}
bor.Authorize(eb, wallet.SignData)
}
// If mining is started, we can disable the transaction rejection mechanism
// introduced to speed sync times.
Expand Down Expand Up @@ -553,6 +560,14 @@ func (s *Ethereum) SyncMode() downloader.SyncMode {
return mode
}

// SetAuthorized sets the authorized bool variable
// denoting that consensus has been authorized while creation
func (s *Ethereum) SetAuthorized(authorized bool) {
s.lock.Lock()
s.authorized = authorized
s.lock.Unlock()
}

// Protocols returns all the currently configured
// network protocols to start.
func (s *Ethereum) Protocols() []p2p.Protocol {
Expand Down
12 changes: 10 additions & 2 deletions internal/cli/server/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,9 @@ type AccountsConfig struct {

// UseLightweightKDF enables a faster but less secure encryption of accounts
UseLightweightKDF bool `hcl:"use-lightweight-kdf,optional"`

// DisableBorWallet disables the personal wallet endpoints
DisableBorWallet bool `hcl:"disable-bor-wallet,optional"`
}

type DeveloperConfig struct {
Expand Down Expand Up @@ -496,6 +499,7 @@ func DefaultConfig() *Config {
PasswordFile: "",
AllowInsecureUnlock: false,
UseLightweightKDF: false,
DisableBorWallet: false,
},
GRPC: &GRPCConfig{
Addr: ":3131",
Expand Down Expand Up @@ -611,7 +615,7 @@ func (c *Config) loadChain() error {
return nil
}

func (c *Config) buildEth(stack *node.Node) (*ethconfig.Config, error) {
func (c *Config) buildEth(accountManager *accounts.Manager) (*ethconfig.Config, error) {
dbHandles, err := makeDatabaseHandles()
if err != nil {
return nil, err
Expand Down Expand Up @@ -686,7 +690,7 @@ func (c *Config) buildEth(stack *node.Node) (*ethconfig.Config, error) {
if c.Developer.Enabled {
// Get a keystore
var ks *keystore.KeyStore
if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 {
if keystores := accountManager.Backends(keystore.KeyStoreType); len(keystores) > 0 {
ks = keystores[0].(*keystore.KeyStore)
}

Expand All @@ -712,6 +716,10 @@ func (c *Config) buildEth(stack *node.Node) (*ethconfig.Config, error) {
}
log.Info("Using developer account", "address", developer.Address)

// Set the Etherbase
c.Sealer.Etherbase = developer.Address.Hex()
n.Miner.Etherbase = developer.Address

// get developer mode chain config
c.chain = chains.GetDeveloperChain(c.Developer.Period, developer.Address)

Expand Down
5 changes: 5 additions & 0 deletions internal/cli/server/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,11 @@ func (c *Command) Flags() *flagset.Flagset {
Value: &c.cliConfig.Accounts.UseLightweightKDF,
Group: "Account Management",
})
f.BoolFlag((&flagset.BoolFlag{
Name: "disable-bor-wallet",
Usage: "Disable the personal wallet endpoints",
Value: &c.cliConfig.Accounts.DisableBorWallet,
}))

// grpc
f.StringFlag(&flagset.StringFlag{
Expand Down
114 changes: 93 additions & 21 deletions internal/cli/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ import (
"strings"
"time"

"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/consensus/beacon"
"github.com/ethereum/go-ethereum/consensus/bor"
"github.com/ethereum/go-ethereum/consensus/clique"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/ethstats"
Expand Down Expand Up @@ -67,50 +71,115 @@ func NewServer(config *Config) (*Server, error) {
if err != nil {
return nil, err
}
srv.node = stack

// setup account manager (only keystore)
{
keydir := stack.KeyStoreDir()
n, p := keystore.StandardScryptN, keystore.StandardScryptP
if config.Accounts.UseLightweightKDF {
n, p = keystore.LightScryptN, keystore.LightScryptP
}
stack.AccountManager().AddBackend(keystore.NewKeyStore(keydir, n, p))
// create a new account manager, only for the scope of this function
accountManager := accounts.NewManager(&accounts.Config{})

// register backend to account manager with keystore for signing
keydir := stack.KeyStoreDir()
n, p := keystore.StandardScryptN, keystore.StandardScryptP
if config.Accounts.UseLightweightKDF {
n, p = keystore.LightScryptN, keystore.LightScryptP
}

// register the ethereum backend
ethCfg, err := config.buildEth(stack)
if err != nil {
return nil, err
}
// proceed to authorize the local account manager in any case
accountManager.AddBackend(keystore.NewKeyStore(keydir, n, p))

backend, err := eth.New(stack, ethCfg)
if err != nil {
return nil, err
// flag to set if we're authorizing consensus here
authorized := false

// check if personal wallet endpoints are disabled or not
if !config.Accounts.DisableBorWallet {
// add keystore globally to the node's account manager if personal wallet is enabled
stack.AccountManager().AddBackend(keystore.NewKeyStore(keydir, n, p))

// register the ethereum backend
ethCfg, err := config.buildEth(stack.AccountManager())
if err != nil {
return nil, err
}
backend, err := eth.New(stack, ethCfg)
if err != nil {
return nil, err
}
srv.backend = backend
} else {
// register the ethereum backend (with temporary created account manager)
ethCfg, err := config.buildEth(accountManager)
if err != nil {
return nil, err
}
backend, err := eth.New(stack, ethCfg)
if err != nil {
return nil, err
}
srv.backend = backend

// authorize only if mining or in developer mode
if config.Sealer.Enabled || config.Developer.Enabled {
// get the etherbase
eb, err := srv.backend.Etherbase()
if err != nil {
log.Error("Cannot start mining without etherbase", "err", err)
return nil, fmt.Errorf("etherbase missing: %v", err)
}

// Authorize the clique consensus (if chosen) to sign using wallet signer
var cli *clique.Clique
if c, ok := srv.backend.Engine().(*clique.Clique); ok {
cli = c
} else if cl, ok := srv.backend.Engine().(*beacon.Beacon); ok {
if c, ok := cl.InnerEngine().(*clique.Clique); ok {
cli = c
}
}
if cli != nil {
wallet, err := accountManager.Find(accounts.Account{Address: eb})
if wallet == nil || err != nil {
log.Error("Etherbase account unavailable locally", "err", err)
return nil, fmt.Errorf("signer missing: %v", err)
}
cli.Authorize(eb, wallet.SignData)
authorized = true
}

// Authorize the bor consensus (if chosen) to sign using wallet signer
if bor, ok := srv.backend.Engine().(*bor.Bor); ok {
wallet, err := accountManager.Find(accounts.Account{Address: eb})
if wallet == nil || err != nil {
log.Error("Etherbase account unavailable locally", "err", err)
return nil, fmt.Errorf("signer missing: %v", err)
}
bor.Authorize(eb, wallet.SignData)
authorized = true
}
}
}
srv.backend = backend

// set the auth status in backend
srv.backend.SetAuthorized(authorized)

// debug tracing is enabled by default
stack.RegisterAPIs(tracers.APIs(backend.APIBackend))
stack.RegisterAPIs(tracers.APIs(srv.backend.APIBackend))

// graphql is started from another place
if config.JsonRPC.Graphql.Enabled {
if err := graphql.New(stack, backend.APIBackend, config.JsonRPC.Cors, config.JsonRPC.VHost); err != nil {
if err := graphql.New(stack, srv.backend.APIBackend, config.JsonRPC.Cors, config.JsonRPC.VHost); err != nil {
return nil, fmt.Errorf("failed to register the GraphQL service: %v", err)
}
}

// register ethash service
if config.Ethstats != "" {
if err := ethstats.New(stack, backend.APIBackend, backend.Engine(), config.Ethstats); err != nil {
if err := ethstats.New(stack, srv.backend.APIBackend, srv.backend.Engine(), config.Ethstats); err != nil {
return nil, err
}
}

// sealing (if enabled) or in dev mode
if config.Sealer.Enabled || config.Developer.Enabled {
if err := backend.StartMining(1); err != nil {
if err := srv.backend.StartMining(1); err != nil {
return nil, err
}
}
Expand All @@ -119,6 +188,9 @@ func NewServer(config *Config) (*Server, error) {
return nil, err
}

// Set the node instance
srv.node = stack

// start the node
if err := srv.node.Start(); err != nil {
return nil, err
Expand Down

0 comments on commit 1b53044

Please sign in to comment.