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

* initial disable-bor-wallet implementation

* fixes and enhancements

* update docs using clidoc

* fixes in clique auth
This commit is contained in:
Manav Darji 2022-05-23 14:06:51 +05:30 committed by GitHub
parent cd1a8990ae
commit 1b53044055
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 145 additions and 43 deletions

View file

@ -36,6 +36,8 @@ The ```bor server``` command runs the Bor client.
- ```gpo.ignoreprice```: Gas price below which gpo will ignore transactions - ```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 - ```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 - ```dev```: Enable developer mode with ephemeral proof-of-authority network and a pre-funded developer account, mining enabled

View file

@ -82,6 +82,7 @@ type Ethereum struct {
eventMux *event.TypeMux eventMux *event.TypeMux
engine consensus.Engine engine consensus.Engine
accountManager *accounts.Manager accountManager *accounts.Manager
authorized bool // If consensus engine is authorized with keystore
bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests
bloomIndexer *core.ChainIndexer // Bloom indexer operating during block imports bloomIndexer *core.ChainIndexer // Bloom indexer operating during block imports
@ -153,6 +154,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
chainDb: chainDb, chainDb: chainDb,
eventMux: stack.EventMux(), eventMux: stack.EventMux(),
accountManager: stack.AccountManager(), accountManager: stack.AccountManager(),
authorized: false,
engine: nil, engine: nil,
closeBloomHandler: make(chan struct{}), closeBloomHandler: make(chan struct{}),
networkID: config.NetworkId, networkID: config.NetworkId,
@ -485,29 +487,34 @@ func (s *Ethereum) StartMining(threads int) error {
log.Error("Cannot start mining without etherbase", "err", err) log.Error("Cannot start mining without etherbase", "err", err)
return fmt.Errorf("etherbase missing: %v", err) return fmt.Errorf("etherbase missing: %v", err)
} }
var cli *clique.Clique
if c, ok := s.engine.(*clique.Clique); ok { // If personal endpoints are disabled, the server creating
cli = c // this Ethereum instance has already Authorized consensus.
} else if cl, ok := s.engine.(*beacon.Beacon); ok { if !s.authorized {
if c, ok := cl.InnerEngine().(*clique.Clique); ok { var cli *clique.Clique
if c, ok := s.engine.(*clique.Clique); ok {
cli = c cli = c
} else if cl, ok := s.engine.(*beacon.Beacon); ok {
if c, ok := cl.InnerEngine().(*clique.Clique); ok {
cli = c
}
} }
} if cli != nil {
if cli != nil { wallet, err := s.accountManager.Find(accounts.Account{Address: eb})
wallet, err := s.accountManager.Find(accounts.Account{Address: eb}) if wallet == nil || err != nil {
if wallet == nil || err != nil { log.Error("Etherbase account unavailable locally", "err", err)
log.Error("Etherbase account unavailable locally", "err", err) return fmt.Errorf("signer missing: %v", 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 bor, ok := s.engine.(*bor.Bor); ok { if wallet == nil || err != nil {
wallet, err := s.accountManager.Find(accounts.Account{Address: eb}) log.Error("Etherbase account unavailable locally", "err", err)
if wallet == nil || err != nil { return fmt.Errorf("signer missing: %v", err)
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 // If mining is started, we can disable the transaction rejection mechanism
// introduced to speed sync times. // introduced to speed sync times.
@ -553,6 +560,14 @@ func (s *Ethereum) SyncMode() downloader.SyncMode {
return mode 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 // Protocols returns all the currently configured
// network protocols to start. // network protocols to start.
func (s *Ethereum) Protocols() []p2p.Protocol { func (s *Ethereum) Protocols() []p2p.Protocol {

View file

@ -368,6 +368,9 @@ type AccountsConfig struct {
// UseLightweightKDF enables a faster but less secure encryption of accounts // UseLightweightKDF enables a faster but less secure encryption of accounts
UseLightweightKDF bool `hcl:"use-lightweight-kdf,optional"` UseLightweightKDF bool `hcl:"use-lightweight-kdf,optional"`
// DisableBorWallet disables the personal wallet endpoints
DisableBorWallet bool `hcl:"disable-bor-wallet,optional"`
} }
type DeveloperConfig struct { type DeveloperConfig struct {
@ -496,6 +499,7 @@ func DefaultConfig() *Config {
PasswordFile: "", PasswordFile: "",
AllowInsecureUnlock: false, AllowInsecureUnlock: false,
UseLightweightKDF: false, UseLightweightKDF: false,
DisableBorWallet: false,
}, },
GRPC: &GRPCConfig{ GRPC: &GRPCConfig{
Addr: ":3131", Addr: ":3131",
@ -611,7 +615,7 @@ func (c *Config) loadChain() error {
return nil 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() dbHandles, err := makeDatabaseHandles()
if err != nil { if err != nil {
return nil, err return nil, err
@ -686,7 +690,7 @@ func (c *Config) buildEth(stack *node.Node) (*ethconfig.Config, error) {
if c.Developer.Enabled { if c.Developer.Enabled {
// Get a keystore // Get a keystore
var ks *keystore.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) ks = keystores[0].(*keystore.KeyStore)
} }
@ -712,6 +716,10 @@ func (c *Config) buildEth(stack *node.Node) (*ethconfig.Config, error) {
} }
log.Info("Using developer account", "address", developer.Address) 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 // get developer mode chain config
c.chain = chains.GetDeveloperChain(c.Developer.Period, developer.Address) c.chain = chains.GetDeveloperChain(c.Developer.Period, developer.Address)

View file

@ -530,6 +530,11 @@ func (c *Command) Flags() *flagset.Flagset {
Value: &c.cliConfig.Accounts.UseLightweightKDF, Value: &c.cliConfig.Accounts.UseLightweightKDF,
Group: "Account Management", Group: "Account Management",
}) })
f.BoolFlag((&flagset.BoolFlag{
Name: "disable-bor-wallet",
Usage: "Disable the personal wallet endpoints",
Value: &c.cliConfig.Accounts.DisableBorWallet,
}))
// grpc // grpc
f.StringFlag(&flagset.StringFlag{ f.StringFlag(&flagset.StringFlag{

View file

@ -10,7 +10,11 @@ import (
"strings" "strings"
"time" "time"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore" "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"
"github.com/ethereum/go-ethereum/eth/tracers" "github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/ethstats" "github.com/ethereum/go-ethereum/ethstats"
@ -67,50 +71,115 @@ func NewServer(config *Config) (*Server, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
srv.node = stack
// setup account manager (only keystore) // setup account manager (only keystore)
{ // create a new account manager, only for the scope of this function
keydir := stack.KeyStoreDir() accountManager := accounts.NewManager(&accounts.Config{})
n, p := keystore.StandardScryptN, keystore.StandardScryptP
if config.Accounts.UseLightweightKDF { // register backend to account manager with keystore for signing
n, p = keystore.LightScryptN, keystore.LightScryptP keydir := stack.KeyStoreDir()
} n, p := keystore.StandardScryptN, keystore.StandardScryptP
if config.Accounts.UseLightweightKDF {
n, p = keystore.LightScryptN, keystore.LightScryptP
}
// proceed to authorize the local account manager in any case
accountManager.AddBackend(keystore.NewKeyStore(keydir, n, p))
// 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)) 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
}
}
} }
// register the ethereum backend // set the auth status in backend
ethCfg, err := config.buildEth(stack) srv.backend.SetAuthorized(authorized)
if err != nil {
return nil, err
}
backend, err := eth.New(stack, ethCfg)
if err != nil {
return nil, err
}
srv.backend = backend
// debug tracing is enabled by default // 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 // graphql is started from another place
if config.JsonRPC.Graphql.Enabled { 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) return nil, fmt.Errorf("failed to register the GraphQL service: %v", err)
} }
} }
// register ethash service // register ethash service
if config.Ethstats != "" { 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 return nil, err
} }
} }
// sealing (if enabled) or in dev mode // sealing (if enabled) or in dev mode
if config.Sealer.Enabled || config.Developer.Enabled { 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 return nil, err
} }
} }
@ -119,6 +188,9 @@ func NewServer(config *Config) (*Server, error) {
return nil, err return nil, err
} }
// Set the node instance
srv.node = stack
// start the node // start the node
if err := srv.node.Start(); err != nil { if err := srv.node.Start(); err != nil {
return nil, err return nil, err