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
- ```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

View file

@ -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
@ -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,
@ -485,6 +487,10 @@ func (s *Ethereum) StartMining(threads int) error {
log.Error("Cannot start mining without etherbase", "err", err)
return fmt.Errorf("etherbase missing: %v", err)
}
// 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
@ -509,6 +515,7 @@ func (s *Ethereum) StartMining(threads int) error {
}
bor.Authorize(eb, wallet.SignData)
}
}
// If mining is started, we can disable the transaction rejection mechanism
// introduced to speed sync times.
atomic.StoreUint32(&s.handler.acceptTxs, 1)
@ -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 {

View file

@ -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 {
@ -496,6 +499,7 @@ func DefaultConfig() *Config {
PasswordFile: "",
AllowInsecureUnlock: false,
UseLightweightKDF: false,
DisableBorWallet: false,
},
GRPC: &GRPCConfig{
Addr: ":3131",
@ -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
@ -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)
}
@ -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)

View file

@ -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{

View file

@ -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"
@ -67,50 +71,115 @@ func NewServer(config *Config) (*Server, error) {
if err != nil {
return nil, err
}
srv.node = stack
// setup account manager (only keystore)
{
// 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
}
// 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))
}
// register the ethereum backend
ethCfg, err := config.buildEth(stack)
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
}
}
}
// 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
}
}
@ -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