refactor move manager.go into seperated package to avoid cyclic import

This commit is contained in:
Huiyi Li 2020-04-06 14:43:52 -07:00
parent 7f6c0fb601
commit 276e13dc01
19 changed files with 115 additions and 71 deletions

View file

@ -21,7 +21,6 @@ import (
crand "crypto/rand"
"fmt"
"math/big"
"reflect"
"sync"
"time"
@ -33,9 +32,6 @@ import (
"github.com/pborman/uuid"
)
// DBKeyStoreType is the reflect type of a keystore backend.
var DBKeyStoreType = reflect.TypeOf(&keyStoreDB{})
type keyStoreDB struct {
storage *keyStorePassphraseDB // storage backend, might be mysql or postgres
unlocked map[common.Address]*unlocked // Currently unlocked account (decrypted private keys)

View file

@ -26,7 +26,6 @@ import (
"fmt"
"math/big"
"os"
"reflect"
"runtime"
"sync"
"time"
@ -38,9 +37,6 @@ import (
"github.com/ethereum/go-ethereum/event"
)
// FSKeyStoreType is the reflect type of a keystore backend.
var FSKeyStoreType = reflect.TypeOf(&keyStoreFS{})
// Maximum time between wallet refreshes (if filesystem notifications don't work).
const walletRefreshCycle = 3 * time.Second

View file

@ -5,6 +5,7 @@ import (
"errors"
"math/big"
"path/filepath"
"reflect"
"time"
"github.com/ethereum/go-ethereum/accounts"
@ -25,6 +26,12 @@ const KeyStoreScheme = "keystore"
const keystoreDBTableName = "keystore"
// DBKeyStoreType is the reflect type of a keystore backend.
var DBKeyStoreType = reflect.TypeOf(&keyStoreDB{})
// FSKeyStoreType is the reflect type of a keystore backend.
var FSKeyStoreType = reflect.TypeOf(&keyStoreFS{})
// KeyStore is the interface which abstracts all needed operations required
type KeyStore interface {
// Wallets implements accounts.Backend, returning all single-key wallets from the KeyStore.

View file

@ -14,13 +14,15 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package accounts
package manager
import (
"reflect"
"sort"
"sync"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/event"
)
@ -36,11 +38,11 @@ type Config struct {
// Manager is an overarching account manager that can communicate with various
// backends for signing transactions.
type Manager struct {
config *Config // Global account manager configurations
backends map[reflect.Type][]Backend // Index of backends currently registered
updaters []event.Subscription // Wallet update subscriptions for all backends
updates chan WalletEvent // Subscription sink for backend wallet changes
wallets []Wallet // Cache of all wallets from all registered backends
config *Config // Global account manager configurations
backends map[reflect.Type][]accounts.Backend // Index of backends currently registered
updaters []event.Subscription // Wallet update subscriptions for all backends
updates chan accounts.WalletEvent // Subscription sink for backend wallet changes
wallets []accounts.Wallet // Cache of all wallets from all registered backends
feed event.Feed // Wallet feed notifying of arrivals/departures
@ -50,14 +52,17 @@ type Manager struct {
// NewManager creates a generic account manager to sign transaction via various
// supported backends.
func NewManager(config *Config, backends ...Backend) *Manager {
func NewManager(config *Config, backends ...accounts.Backend) *Manager {
// Retrieve the initial list of wallets from the backends and sort by URL
var wallets []Wallet
var wallets []accounts.Wallet
for _, backend := range backends {
wallets = merge(wallets, backend.Wallets()...)
// if we are using db backed keystore, it doesn't make sense to cache the potential millions of keys in our memory
if reflect.TypeOf(backend) != keystore.DBKeyStoreType {
wallets = backend.Wallets()
}
}
// Subscribe to wallet notifications from all backends
updates := make(chan WalletEvent, 4*len(backends))
updates := make(chan accounts.WalletEvent, 4*len(backends))
subs := make([]event.Subscription, len(backends))
for i, backend := range backends {
@ -66,7 +71,7 @@ func NewManager(config *Config, backends ...Backend) *Manager {
// Assemble the account manager and return
am := &Manager{
config: config,
backends: make(map[reflect.Type][]Backend),
backends: make(map[reflect.Type][]accounts.Backend),
updaters: subs,
updates: updates,
wallets: wallets,
@ -113,9 +118,9 @@ func (am *Manager) update() {
// Wallet event arrived, update local cache
am.lock.Lock()
switch event.Kind {
case WalletArrived:
case accounts.WalletArrived:
am.wallets = merge(am.wallets, event.Wallet)
case WalletDropped:
case accounts.WalletDropped:
am.wallets = drop(am.wallets, event.Wallet)
}
am.lock.Unlock()
@ -132,8 +137,8 @@ func (am *Manager) update() {
}
// Backends retrieves the backend(s) with the given type from the account manager.
func (am *Manager) Backends(kinds ...reflect.Type) []Backend {
backends := make([]Backend, 0)
func (am *Manager) Backends(kinds ...reflect.Type) []accounts.Backend {
backends := make([]accounts.Backend, 0)
for _, kind := range kinds {
backends = append(backends, am.backends[kind]...)
}
@ -141,21 +146,27 @@ func (am *Manager) Backends(kinds ...reflect.Type) []Backend {
}
// Wallets returns all signer accounts registered under this account manager.
func (am *Manager) Wallets() []Wallet {
func (am *Manager) Wallets() []accounts.Wallet {
am.lock.RLock()
defer am.lock.RUnlock()
cpy := make([]Wallet, len(am.wallets))
copy(cpy, am.wallets)
return cpy
dbBackends := am.Backends(keystore.DBKeyStoreType)
var wallets []accounts.Wallet
if len(dbBackends) == 1 {
wallets = dbBackends[0].Wallets()
} else {
wallets = make([]accounts.Wallet, 0)
}
wallets = append(wallets, am.wallets...)
return wallets
}
// Wallet retrieves the wallet associated with a particular URL.
func (am *Manager) Wallet(url string) (Wallet, error) {
func (am *Manager) Wallet(url string) (accounts.Wallet, error) {
am.lock.RLock()
defer am.lock.RUnlock()
parsed, err := parseURL(url)
parsed, err := accounts.ParseURL(url)
if err != nil {
return nil, err
}
@ -164,7 +175,7 @@ func (am *Manager) Wallet(url string) (Wallet, error) {
return wallet, nil
}
}
return nil, ErrUnknownWallet
return nil, accounts.ErrUnknownWallet
}
// Accounts returns all account addresses of all wallets within the account manager
@ -172,7 +183,19 @@ func (am *Manager) Accounts() []common.Address {
am.lock.RLock()
defer am.lock.RUnlock()
addresses := make([]common.Address, 0) // return [] instead of nil if empty
var addresses []common.Address
dbBackends := am.Backends(keystore.DBKeyStoreType)
if len(dbBackends) == 1 {
dbWallets := dbBackends[0].Wallets()
addresses = make([]common.Address, len(dbWallets))
for i, wallet := range dbWallets {
// one dbWallet only have one account inside
addresses[i] = wallet.Accounts()[0].Address
}
} else {
addresses = make([]common.Address, 0) // return [] instead of nil if empty
}
for _, wallet := range am.wallets {
for _, account := range wallet.Accounts() {
addresses = append(addresses, account.Address)
@ -184,21 +207,33 @@ func (am *Manager) Accounts() []common.Address {
// Find attempts to locate the wallet corresponding to a specific account. Since
// accounts can be dynamically added to and removed from wallets, this method has
// a linear runtime in the number of wallets.
func (am *Manager) Find(account Account) (Wallet, error) {
func (am *Manager) Find(account accounts.Account) (accounts.Wallet, error) {
am.lock.RLock()
defer am.lock.RUnlock()
dbBackends := am.Backends(keystore.DBKeyStoreType)
if len(dbBackends) == 1 {
dbKeyStore, _ := dbBackends[0].(keystore.KeyStore)
// TODO here
dbKeyStore.Accounts()
return nil, nil
// acc, err := dbKeyStore.Find(account)
// if err == nil {
// return &keystore.keystoreWalletDB{}, nil
// }
}
for _, wallet := range am.wallets {
if wallet.Contains(account) {
return wallet, nil
}
}
return nil, ErrUnknownAccount
return nil, accounts.ErrUnknownAccount
}
// Subscribe creates an async subscription to receive notifications when the
// manager detects the arrival or departure of a wallet from any of its backends.
func (am *Manager) Subscribe(sink chan<- WalletEvent) event.Subscription {
func (am *Manager) Subscribe(sink chan<- accounts.WalletEvent) event.Subscription {
return am.feed.Subscribe(sink)
}
@ -206,21 +241,21 @@ func (am *Manager) Subscribe(sink chan<- WalletEvent) event.Subscription {
// origin list is preserved by inserting new wallets at the correct position.
//
// The original slice is assumed to be already sorted by URL.
func merge(slice []Wallet, wallets ...Wallet) []Wallet {
func merge(slice []accounts.Wallet, wallets ...accounts.Wallet) []accounts.Wallet {
for _, wallet := range wallets {
n := sort.Search(len(slice), func(i int) bool { return slice[i].URL().Cmp(wallet.URL()) >= 0 })
if n == len(slice) {
slice = append(slice, wallet)
continue
}
slice = append(slice[:n], append([]Wallet{wallet}, slice[n:]...)...)
slice = append(slice[:n], append([]accounts.Wallet{wallet}, slice[n:]...)...)
}
return slice
}
// drop is the couterpart of merge, which looks up wallets from within the sorted
// cache and removes the ones specified.
func drop(slice []Wallet, wallets ...Wallet) []Wallet {
func drop(slice []accounts.Wallet, wallets ...accounts.Wallet) []accounts.Wallet {
for _, wallet := range wallets {
n := sort.Search(len(slice), func(i int) bool { return slice[i].URL().Cmp(wallet.URL()) >= 0 })
if n == len(slice) {

View file

@ -41,7 +41,7 @@ type URL struct {
}
// parseURL converts a user supplied URL into the accounts specific structure.
func parseURL(url string) (URL, error) {
func ParseURL(url string) (URL, error) {
parts := strings.Split(url, "://")
if len(parts) != 2 || parts[0] == "" {
return URL{}, errors.New("protocol scheme missing")
@ -81,7 +81,7 @@ func (u *URL) UnmarshalJSON(input []byte) error {
if err != nil {
return err
}
url, err := parseURL(textURL)
url, err := ParseURL(textURL)
if err != nil {
return err
}

View file

@ -21,7 +21,7 @@ import (
)
func TestURLParsing(t *testing.T) {
url, err := parseURL("https://ethereum.org")
url, err := ParseURL("https://ethereum.org")
if err != nil {
t.Errorf("unexpected error: %v", err)
}
@ -32,7 +32,7 @@ func TestURLParsing(t *testing.T) {
t.Errorf("expected: %v, got: %v", "ethereum.org", url.Path)
}
_, err = parseURL("ethereum.org")
_, err = ParseURL("ethereum.org")
if err == nil {
t.Error("expected err, got: nil")
}

View file

@ -21,7 +21,7 @@ import (
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/manager"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core"
@ -283,7 +283,7 @@ func (b *EthAPIBackend) EventMux() *event.TypeMux {
return b.eth.EventMux()
}
func (b *EthAPIBackend) AccountManager() *accounts.Manager {
func (b *EthAPIBackend) AccountManager() *manager.Manager {
return b.eth.AccountManager()
}

View file

@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/manager"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus"
@ -80,7 +81,7 @@ type Ethereum struct {
eventMux *event.TypeMux
engine consensus.Engine
accountManager *accounts.Manager
accountManager *manager.Manager
bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests
bloomIndexer *core.ChainIndexer // Bloom indexer operating during block imports
@ -490,7 +491,7 @@ func (s *Ethereum) StopMining() {
func (s *Ethereum) IsMining() bool { return s.miner.Mining() }
func (s *Ethereum) Miner() *miner.Miner { return s.miner }
func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager }
func (s *Ethereum) AccountManager() *manager.Manager { return s.accountManager }
func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain }
func (s *Ethereum) TxPool() *core.TxPool { return s.txPool }
func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux }

View file

@ -28,6 +28,7 @@ import (
"github.com/davecgh/go-spew/spew"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/accounts/manager"
"github.com/ethereum/go-ethereum/accounts/scwallet"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
@ -181,11 +182,11 @@ func (s *PublicTxPoolAPI) Inspect() map[string]map[string]map[string]string {
// PublicAccountAPI provides an API to access accounts managed by this node.
// It offers only methods that can retrieve accounts.
type PublicAccountAPI struct {
am *accounts.Manager
am *manager.Manager
}
// NewPublicAccountAPI creates a new PublicAccountAPI.
func NewPublicAccountAPI(am *accounts.Manager) *PublicAccountAPI {
func NewPublicAccountAPI(am *manager.Manager) *PublicAccountAPI {
return &PublicAccountAPI{am: am}
}
@ -198,7 +199,7 @@ func (s *PublicAccountAPI) Accounts() []common.Address {
// It offers methods to create, (un)lock en list accounts. Some methods accept
// passwords and are therefore considered private by default.
type PrivateAccountAPI struct {
am *accounts.Manager
am *manager.Manager
nonceLock *AddrLocker
b Backend
}
@ -291,7 +292,7 @@ func (s *PrivateAccountAPI) NewAccount(password string) (common.Address, error)
}
// fetchKeystore retrives the encrypted keystore from the account manager.
func fetchKeystore(am *accounts.Manager) keystore.KeyStore {
func fetchKeystore(am *manager.Manager) keystore.KeyStore {
return am.Backends(keystore.FSKeyStoreType, keystore.DBKeyStoreType)[0].(keystore.KeyStore)
}

View file

@ -21,7 +21,7 @@ import (
"context"
"math/big"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/manager"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/bloombits"
@ -43,7 +43,7 @@ type Backend interface {
ProtocolVersion() int
SuggestPrice(ctx context.Context) (*big.Int, error)
ChainDb() ethdb.Database
AccountManager() *accounts.Manager
AccountManager() *manager.Manager
ExtRPCEnabled() bool
RPCGasCap() *big.Int // global gas cap for eth_call over rpc: DoS protection

View file

@ -21,7 +21,7 @@ import (
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/manager"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core"
@ -252,7 +252,7 @@ func (b *LesApiBackend) ChainDb() ethdb.Database {
return b.eth.chainDb
}
func (b *LesApiBackend) AccountManager() *accounts.Manager {
func (b *LesApiBackend) AccountManager() *manager.Manager {
return b.eth.accountManager
}

View file

@ -20,8 +20,8 @@ package les
import (
"fmt"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/manager"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/mclock"
@ -64,7 +64,7 @@ type LightEthereum struct {
ApiBackend *LesApiBackend
eventMux *event.TypeMux
engine consensus.Engine
accountManager *accounts.Manager
accountManager *manager.Manager
netRPCService *ethapi.PublicNetAPI
}

View file

@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/external"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/accounts/manager"
"github.com/ethereum/go-ethereum/accounts/scwallet"
"github.com/ethereum/go-ethereum/accounts/usbwallet"
"github.com/ethereum/go-ethereum/common"
@ -463,7 +464,7 @@ func (c *Config) AccountConfig() (int, int, string, error) {
return scryptN, scryptP, keydir, err
}
func makeAccountManager(conf *Config) (*accounts.Manager, string, error) {
func makeAccountManager(conf *Config) (*manager.Manager, string, error) {
scryptN, scryptP, keydir, err := conf.AccountConfig()
var ephemeral string
if keydir == "" {
@ -524,7 +525,7 @@ func makeAccountManager(conf *Config) (*accounts.Manager, string, error) {
}
}
return accounts.NewManager(&accounts.Config{InsecureUnlockAllowed: conf.InsecureUnlockAllowed}, backends...), ephemeral, nil
return manager.NewManager(&manager.Config{InsecureUnlockAllowed: conf.InsecureUnlockAllowed}, backends...), ephemeral, nil
}
var warnLock sync.Mutex

View file

@ -26,7 +26,7 @@ import (
"strings"
"sync"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/manager"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
@ -41,7 +41,7 @@ import (
type Node struct {
eventmux *event.TypeMux // Event multiplexer used between the services of a stack
config *Config
accman *accounts.Manager
accman *manager.Manager
ephemeralKeystore string // if non-empty, the key directory that will be removed by Stop
instanceDirLock fileutil.Releaser // prevents concurrent use of instance directory
@ -566,7 +566,7 @@ func (n *Node) InstanceDir() string {
}
// AccountManager retrieves the account manager used by the protocol stack.
func (n *Node) AccountManager() *accounts.Manager {
func (n *Node) AccountManager() *manager.Manager {
return n.accman
}

View file

@ -20,7 +20,7 @@ import (
"path/filepath"
"reflect"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/manager"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
@ -35,7 +35,7 @@ type ServiceContext struct {
config *Config
services map[reflect.Type]Service // Index of the already constructed services
EventMux *event.TypeMux // Event multiplexer used for decoupled notifications
AccountManager *accounts.Manager // Account manager created by the node.
AccountManager *manager.Manager // Account manager created by the node.
}
// OpenDatabase opens an existing database with the given name (or creates one

View file

@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/accounts/manager"
"github.com/ethereum/go-ethereum/accounts/scwallet"
"github.com/ethereum/go-ethereum/accounts/usbwallet"
"github.com/ethereum/go-ethereum/common"
@ -110,7 +111,7 @@ type Validator interface {
// SignerAPI defines the actual implementation of ExternalAPI
type SignerAPI struct {
chainID *big.Int
am *accounts.Manager
am *manager.Manager
UI UIClientAPI
validator Validator
rejectMode bool
@ -127,7 +128,7 @@ type Metadata struct {
}
// StartClefAccountManager initializes and start clef Account Manager
func StartClefAccountManager(ksLocation string, nousb, lightKDF bool, scpath string) (*accounts.Manager, error) {
func StartClefAccountManager(ksLocation string, nousb, lightKDF bool, scpath string) (*manager.Manager, error) {
var (
backends []accounts.Backend
n, p = keystore.StandardScryptN, keystore.StandardScryptP
@ -202,7 +203,7 @@ func StartClefAccountManager(ksLocation string, nousb, lightKDF bool, scpath str
}
// Clef doesn't allow insecure http account unlock.
return accounts.NewManager(&accounts.Config{InsecureUnlockAllowed: false}, backends...), nil
return manager.NewManager(&manager.Config{InsecureUnlockAllowed: false}, backends...), nil
}
// MetadataFromContext extracts Metadata from a given context.Context
@ -297,7 +298,7 @@ var ErrRequestDenied = errors.New("request denied")
// key that is generated when a new Account is created.
// noUSB disables USB support that is required to support hardware devices such as
// ledger and trezor.
func NewSignerAPI(am *accounts.Manager, chainID int64, noUSB bool, ui UIClientAPI, validator Validator, advancedMode bool, credentials storage.Storage) *SignerAPI {
func NewSignerAPI(am *manager.Manager, chainID int64, noUSB bool, ui UIClientAPI, validator Validator, advancedMode bool, credentials storage.Storage) *SignerAPI {
if advancedMode {
log.Info("Clef is in advanced mode: will warn instead of reject")
}
@ -393,16 +394,18 @@ func (api *SignerAPI) startUSBListener() {
// multiple accounts.
func (api *SignerAPI) List(ctx context.Context) ([]common.Address, error) {
var accs []accounts.Account
log.Error(fmt.Sprint(len(api.am.Wallets())))
for _, wallet := range api.am.Wallets() {
log.Error(fmt.Sprint(len(wallet.Accounts())))
accs = append(accs, wallet.Accounts()...)
}
log.Error(fmt.Sprint(len(accs)))
result, err := api.UI.ApproveListing(&ListRequest{Accounts: accs, Meta: MetadataFromContext(ctx)})
if err != nil {
return nil, err
}
if result.Accounts == nil {
return nil, ErrRequestDenied
}
addresses := make([]common.Address, 0)
for _, acc := range result.Accounts {

View file

@ -37,6 +37,8 @@ import (
"github.com/ethereum/go-ethereum/signer/core"
"github.com/ethereum/go-ethereum/signer/fourbyte"
"github.com/ethereum/go-ethereum/signer/storage"
_ "github.com/mattn/go-sqlite3"
)
//Used for testing
@ -232,7 +234,7 @@ func TestNewAcc(t *testing.T) {
testNewAcc(api, control, t)
// test db keystore
ksLoc := "sqlite3#" + filepath.Join(tmpDir, "test_new_account.db")
ksLoc := "testdata/dbconfig.yaml"
api, control = setup(ksLoc, t)
testNewAcc(api, control, t)
}
@ -343,7 +345,7 @@ func TestSignTx(t *testing.T) {
testSignTx(api, control, t)
// test db keystore
ksLoc := "sqlite3#" + filepath.Join(tmpDir, "test_sign_tx.db")
ksLoc := "testdata/dbconfig.yaml"
api, control = setup(ksLoc, t)
testSignTx(api, control, t)
}

1
signer/core/testdata/dbconfig.yaml vendored Normal file
View file

@ -0,0 +1 @@
adapter: sqlite3

View file

@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/accounts/manager"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/crypto"
@ -40,7 +41,7 @@ import (
// registry.
type UIServerAPI struct {
extApi *SignerAPI
am *accounts.Manager
am *manager.Manager
}
// NewUIServerAPI creates a new UIServerAPI
@ -110,7 +111,7 @@ func (s *UIServerAPI) DeriveAccount(url string, path string, pin *bool) (account
}
// fetchKeystore retrives the encrypted keystore from the account manager.
func fetchKeystore(am *accounts.Manager) keystore.KeyStore {
func fetchKeystore(am *manager.Manager) keystore.KeyStore {
return am.Backends(keystore.FSKeyStoreType, keystore.DBKeyStoreType)[0].(keystore.KeyStore)
}