Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

internal/cli/server, eth: add option to disable personal wallet endpoints #394

Merged
merged 4 commits into from
May 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -667,7 +671,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 @@ -693,6 +697,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