forked from cerc-io/plugeth
Merge pull request #19438 from karalabe/ledger-new-derivation-path
accounts: switch Ledger derivation path to canonical one
This commit is contained in:
commit
7c91038bff
@ -92,9 +92,13 @@ type Wallet interface {
|
|||||||
// opposed to decending into a child path to allow discovering accounts starting
|
// opposed to decending into a child path to allow discovering accounts starting
|
||||||
// from non zero components.
|
// from non zero components.
|
||||||
//
|
//
|
||||||
|
// Some hardware wallets switched derivation paths through their evolution, so
|
||||||
|
// this method supports providing multiple bases to discover old user accounts
|
||||||
|
// too. Only the last base will be used to derive the next empty account.
|
||||||
|
//
|
||||||
// You can disable automatic account discovery by calling SelfDerive with a nil
|
// You can disable automatic account discovery by calling SelfDerive with a nil
|
||||||
// chain state reader.
|
// chain state reader.
|
||||||
SelfDerive(base DerivationPath, chain ethereum.ChainStateReader)
|
SelfDerive(bases []DerivationPath, chain ethereum.ChainStateReader)
|
||||||
|
|
||||||
// SignData requests the wallet to sign the hash of the given data
|
// SignData requests the wallet to sign the hash of the given data
|
||||||
// It looks up the account specified either solely via its address contained within,
|
// It looks up the account specified either solely via its address contained within,
|
||||||
|
2
accounts/external/backend.go
vendored
2
accounts/external/backend.go
vendored
@ -143,7 +143,7 @@ func (api *ExternalSigner) Derive(path accounts.DerivationPath, pin bool) (accou
|
|||||||
return accounts.Account{}, fmt.Errorf("operation not supported on external signers")
|
return accounts.Account{}, fmt.Errorf("operation not supported on external signers")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *ExternalSigner) SelfDerive(base accounts.DerivationPath, chain ethereum.ChainStateReader) {
|
func (api *ExternalSigner) SelfDerive(bases []accounts.DerivationPath, chain ethereum.ChainStateReader) {
|
||||||
log.Error("operation SelfDerive not supported on external signers")
|
log.Error("operation SelfDerive not supported on external signers")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,10 +35,10 @@ var DefaultRootDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60,
|
|||||||
// at m/44'/60'/0'/0/1, etc.
|
// at m/44'/60'/0'/0/1, etc.
|
||||||
var DefaultBaseDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0, 0}
|
var DefaultBaseDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0, 0}
|
||||||
|
|
||||||
// DefaultLedgerBaseDerivationPath is the base path from which custom derivation endpoints
|
// LegacyLedgerBaseDerivationPath is the legacy base path from which custom derivation
|
||||||
// are incremented. As such, the first account will be at m/44'/60'/0'/0, the second
|
// endpoints are incremented. As such, the first account will be at m/44'/60'/0'/0, the
|
||||||
// at m/44'/60'/0'/1, etc.
|
// second at m/44'/60'/0'/1, etc.
|
||||||
var DefaultLedgerBaseDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0}
|
var LegacyLedgerBaseDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0}
|
||||||
|
|
||||||
// DerivationPath represents the computer friendly version of a hierarchical
|
// DerivationPath represents the computer friendly version of a hierarchical
|
||||||
// deterministic wallet account derivaion path.
|
// deterministic wallet account derivaion path.
|
||||||
|
@ -77,7 +77,8 @@ func (w *keystoreWallet) Derive(path accounts.DerivationPath, pin bool) (account
|
|||||||
|
|
||||||
// SelfDerive implements accounts.Wallet, but is a noop for plain wallets since
|
// SelfDerive implements accounts.Wallet, but is a noop for plain wallets since
|
||||||
// there is no notion of hierarchical account derivation for plain keystore accounts.
|
// there is no notion of hierarchical account derivation for plain keystore accounts.
|
||||||
func (w *keystoreWallet) SelfDerive(base accounts.DerivationPath, chain ethereum.ChainStateReader) {}
|
func (w *keystoreWallet) SelfDerive(bases []accounts.DerivationPath, chain ethereum.ChainStateReader) {
|
||||||
|
}
|
||||||
|
|
||||||
// signHash attempts to sign the given hash with
|
// signHash attempts to sign the given hash with
|
||||||
// the given account. If the wallet does not wrap this particular account, an
|
// the given account. If the wallet does not wrap this particular account, an
|
||||||
|
@ -119,11 +119,11 @@ type Wallet struct {
|
|||||||
session *Session // The secure communication session with the card
|
session *Session // The secure communication session with the card
|
||||||
log log.Logger // Contextual logger to tag the base with its id
|
log log.Logger // Contextual logger to tag the base with its id
|
||||||
|
|
||||||
deriveNextPath accounts.DerivationPath // Next derivation path for account auto-discovery
|
deriveNextPaths []accounts.DerivationPath // Next derivation paths for account auto-discovery (multiple bases supported)
|
||||||
deriveNextAddr common.Address // Next derived account address for auto-discovery
|
deriveNextAddrs []common.Address // Next derived account addresses for auto-discovery (multiple bases supported)
|
||||||
deriveChain ethereum.ChainStateReader // Blockchain state reader to discover used account with
|
deriveChain ethereum.ChainStateReader // Blockchain state reader to discover used account with
|
||||||
deriveReq chan chan struct{} // Channel to request a self-derivation on
|
deriveReq chan chan struct{} // Channel to request a self-derivation on
|
||||||
deriveQuit chan chan error // Channel to terminate the self-deriver with
|
deriveQuit chan chan error // Channel to terminate the self-deriver with
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWallet constructs and returns a new Wallet instance.
|
// NewWallet constructs and returns a new Wallet instance.
|
||||||
@ -390,7 +390,7 @@ func (w *Wallet) Open(passphrase string) error {
|
|||||||
w.deriveReq = make(chan chan struct{})
|
w.deriveReq = make(chan chan struct{})
|
||||||
w.deriveQuit = make(chan chan error)
|
w.deriveQuit = make(chan chan error)
|
||||||
|
|
||||||
go w.selfDerive(0)
|
go w.selfDerive()
|
||||||
|
|
||||||
// Notify anyone listening for wallet events that a new device is accessible
|
// Notify anyone listening for wallet events that a new device is accessible
|
||||||
go w.Hub.updateFeed.Send(accounts.WalletEvent{Wallet: w, Kind: accounts.WalletOpened})
|
go w.Hub.updateFeed.Send(accounts.WalletEvent{Wallet: w, Kind: accounts.WalletOpened})
|
||||||
@ -426,9 +426,8 @@ func (w *Wallet) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// selfDerive is an account derivation loop that upon request attempts to find
|
// selfDerive is an account derivation loop that upon request attempts to find
|
||||||
// new non-zero accounts. maxEmpty specifies the number of empty accounts that
|
// new non-zero accounts.
|
||||||
// should be derived once an initial empty account has been found.
|
func (w *Wallet) selfDerive() {
|
||||||
func (w *Wallet) selfDerive(maxEmpty int) {
|
|
||||||
w.log.Debug("Smart card wallet self-derivation started")
|
w.log.Debug("Smart card wallet self-derivation started")
|
||||||
defer w.log.Debug("Smart card wallet self-derivation stopped")
|
defer w.log.Debug("Smart card wallet self-derivation stopped")
|
||||||
|
|
||||||
@ -461,56 +460,59 @@ func (w *Wallet) selfDerive(maxEmpty int) {
|
|||||||
paths []accounts.DerivationPath
|
paths []accounts.DerivationPath
|
||||||
nextAcc accounts.Account
|
nextAcc accounts.Account
|
||||||
|
|
||||||
nextAddr = w.deriveNextAddr
|
nextPaths = append([]accounts.DerivationPath{}, w.deriveNextPaths...)
|
||||||
nextPath = w.deriveNextPath
|
nextAddrs = append([]common.Address{}, w.deriveNextAddrs...)
|
||||||
|
|
||||||
context = context.Background()
|
context = context.Background()
|
||||||
)
|
)
|
||||||
for empty, emptyCount := false, maxEmpty+1; !empty || emptyCount > 0; {
|
for i := 0; i < len(nextAddrs); i++ {
|
||||||
// Retrieve the next derived Ethereum account
|
for empty := false; !empty; {
|
||||||
if nextAddr == (common.Address{}) {
|
// Retrieve the next derived Ethereum account
|
||||||
if nextAcc, err = w.session.derive(nextPath); err != nil {
|
if nextAddrs[i] == (common.Address{}) {
|
||||||
w.log.Warn("Smartcard wallet account derivation failed", "err", err)
|
if nextAcc, err = w.session.derive(nextPaths[i]); err != nil {
|
||||||
|
w.log.Warn("Smartcard wallet account derivation failed", "err", err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
nextAddrs[i] = nextAcc.Address
|
||||||
|
}
|
||||||
|
// Check the account's status against the current chain state
|
||||||
|
var (
|
||||||
|
balance *big.Int
|
||||||
|
nonce uint64
|
||||||
|
)
|
||||||
|
balance, err = w.deriveChain.BalanceAt(context, nextAddrs[i], nil)
|
||||||
|
if err != nil {
|
||||||
|
w.log.Warn("Smartcard wallet balance retrieval failed", "err", err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
nextAddr = nextAcc.Address
|
nonce, err = w.deriveChain.NonceAt(context, nextAddrs[i], nil)
|
||||||
}
|
if err != nil {
|
||||||
// Check the account's status against the current chain state
|
w.log.Warn("Smartcard wallet nonce retrieval failed", "err", err)
|
||||||
var (
|
break
|
||||||
balance *big.Int
|
}
|
||||||
nonce uint64
|
// If the next account is empty, stop self-derivation, but add for the last base path
|
||||||
)
|
if balance.Sign() == 0 && nonce == 0 {
|
||||||
balance, err = w.deriveChain.BalanceAt(context, nextAddr, nil)
|
empty = true
|
||||||
if err != nil {
|
if i < len(nextAddrs)-1 {
|
||||||
w.log.Warn("Smartcard wallet balance retrieval failed", "err", err)
|
break
|
||||||
break
|
}
|
||||||
}
|
}
|
||||||
nonce, err = w.deriveChain.NonceAt(context, nextAddr, nil)
|
// We've just self-derived a new account, start tracking it locally
|
||||||
if err != nil {
|
path := make(accounts.DerivationPath, len(nextPaths[i]))
|
||||||
w.log.Warn("Smartcard wallet nonce retrieval failed", "err", err)
|
copy(path[:], nextPaths[i][:])
|
||||||
break
|
paths = append(paths, path)
|
||||||
}
|
|
||||||
// If the next account is empty and no more empty accounts are
|
|
||||||
// allowed, stop self-derivation. Add the current one nonetheless.
|
|
||||||
if balance.Sign() == 0 && nonce == 0 {
|
|
||||||
empty = true
|
|
||||||
emptyCount--
|
|
||||||
}
|
|
||||||
// We've just self-derived a new account, start tracking it locally
|
|
||||||
path := make(accounts.DerivationPath, len(nextPath))
|
|
||||||
copy(path[:], nextPath[:])
|
|
||||||
paths = append(paths, path)
|
|
||||||
|
|
||||||
// Display a log message to the user for new (or previously empty accounts)
|
// Display a log message to the user for new (or previously empty accounts)
|
||||||
if _, known := pairing.Accounts[nextAddr]; !known || !empty || nextAddr != w.deriveNextAddr {
|
if _, known := pairing.Accounts[nextAddrs[i]]; !known || !empty || nextAddrs[i] != w.deriveNextAddrs[i] {
|
||||||
w.log.Info("Smartcard wallet discovered new account", "address", nextAddr, "path", path, "balance", balance, "nonce", nonce)
|
w.log.Info("Smartcard wallet discovered new account", "address", nextAddrs[i], "path", path, "balance", balance, "nonce", nonce)
|
||||||
}
|
}
|
||||||
pairing.Accounts[nextAddr] = path
|
pairing.Accounts[nextAddrs[i]] = path
|
||||||
|
|
||||||
// Fetch the next potential account
|
// Fetch the next potential account
|
||||||
if !empty || emptyCount > 0 {
|
if !empty {
|
||||||
nextAddr = common.Address{}
|
nextAddrs[i] = common.Address{}
|
||||||
nextPath[len(nextPath)-1]++
|
nextPaths[i][len(nextPaths[i])-1]++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If there are new accounts, write them out
|
// If there are new accounts, write them out
|
||||||
@ -518,8 +520,8 @@ func (w *Wallet) selfDerive(maxEmpty int) {
|
|||||||
err = w.Hub.setPairing(w, pairing)
|
err = w.Hub.setPairing(w, pairing)
|
||||||
}
|
}
|
||||||
// Shift the self-derivation forward
|
// Shift the self-derivation forward
|
||||||
w.deriveNextAddr = nextAddr
|
w.deriveNextAddrs = nextAddrs
|
||||||
w.deriveNextPath = nextPath
|
w.deriveNextPaths = nextPaths
|
||||||
|
|
||||||
// Self derivation complete, release device lock
|
// Self derivation complete, release device lock
|
||||||
w.lock.Unlock()
|
w.lock.Unlock()
|
||||||
@ -592,7 +594,7 @@ func (w *Wallet) Contains(account accounts.Account) bool {
|
|||||||
|
|
||||||
// Initialize installs a keypair generated from the provided key into the wallet.
|
// Initialize installs a keypair generated from the provided key into the wallet.
|
||||||
func (w *Wallet) Initialize(seed []byte) error {
|
func (w *Wallet) Initialize(seed []byte) error {
|
||||||
go w.selfDerive(0)
|
go w.selfDerive()
|
||||||
// DO NOT lock at this stage, as the initialize
|
// DO NOT lock at this stage, as the initialize
|
||||||
// function relies on Status()
|
// function relies on Status()
|
||||||
return w.session.initialize(seed)
|
return w.session.initialize(seed)
|
||||||
@ -629,16 +631,22 @@ func (w *Wallet) Derive(path accounts.DerivationPath, pin bool) (accounts.Accoun
|
|||||||
// opposed to decending into a child path to allow discovering accounts starting
|
// opposed to decending into a child path to allow discovering accounts starting
|
||||||
// from non zero components.
|
// from non zero components.
|
||||||
//
|
//
|
||||||
|
// Some hardware wallets switched derivation paths through their evolution, so
|
||||||
|
// this method supports providing multiple bases to discover old user accounts
|
||||||
|
// too. Only the last base will be used to derive the next empty account.
|
||||||
|
//
|
||||||
// You can disable automatic account discovery by calling SelfDerive with a nil
|
// You can disable automatic account discovery by calling SelfDerive with a nil
|
||||||
// chain state reader.
|
// chain state reader.
|
||||||
func (w *Wallet) SelfDerive(base accounts.DerivationPath, chain ethereum.ChainStateReader) {
|
func (w *Wallet) SelfDerive(bases []accounts.DerivationPath, chain ethereum.ChainStateReader) {
|
||||||
w.lock.Lock()
|
w.lock.Lock()
|
||||||
defer w.lock.Unlock()
|
defer w.lock.Unlock()
|
||||||
|
|
||||||
w.deriveNextPath = make(accounts.DerivationPath, len(base))
|
w.deriveNextPaths = make([]accounts.DerivationPath, len(bases))
|
||||||
copy(w.deriveNextPath[:], base[:])
|
for i, base := range bases {
|
||||||
|
w.deriveNextPaths[i] = make(accounts.DerivationPath, len(base))
|
||||||
w.deriveNextAddr = common.Address{}
|
copy(w.deriveNextPaths[i][:], base[:])
|
||||||
|
}
|
||||||
|
w.deriveNextAddrs = make([]common.Address, len(bases))
|
||||||
w.deriveChain = chain
|
w.deriveChain = chain
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,11 +83,11 @@ type wallet struct {
|
|||||||
accounts []accounts.Account // List of derive accounts pinned on the hardware wallet
|
accounts []accounts.Account // List of derive accounts pinned on the hardware wallet
|
||||||
paths map[common.Address]accounts.DerivationPath // Known derivation paths for signing operations
|
paths map[common.Address]accounts.DerivationPath // Known derivation paths for signing operations
|
||||||
|
|
||||||
deriveNextPath accounts.DerivationPath // Next derivation path for account auto-discovery
|
deriveNextPaths []accounts.DerivationPath // Next derivation paths for account auto-discovery (multiple bases supported)
|
||||||
deriveNextAddr common.Address // Next derived account address for auto-discovery
|
deriveNextAddrs []common.Address // Next derived account addresses for auto-discovery (multiple bases supported)
|
||||||
deriveChain ethereum.ChainStateReader // Blockchain state reader to discover used account with
|
deriveChain ethereum.ChainStateReader // Blockchain state reader to discover used account with
|
||||||
deriveReq chan chan struct{} // Channel to request a self-derivation on
|
deriveReq chan chan struct{} // Channel to request a self-derivation on
|
||||||
deriveQuit chan chan error // Channel to terminate the self-deriver with
|
deriveQuit chan chan error // Channel to terminate the self-deriver with
|
||||||
|
|
||||||
healthQuit chan chan error
|
healthQuit chan chan error
|
||||||
|
|
||||||
@ -339,57 +339,62 @@ func (w *wallet) selfDerive() {
|
|||||||
accs []accounts.Account
|
accs []accounts.Account
|
||||||
paths []accounts.DerivationPath
|
paths []accounts.DerivationPath
|
||||||
|
|
||||||
nextAddr = w.deriveNextAddr
|
nextPaths = append([]accounts.DerivationPath{}, w.deriveNextPaths...)
|
||||||
nextPath = w.deriveNextPath
|
nextAddrs = append([]common.Address{}, w.deriveNextAddrs...)
|
||||||
|
|
||||||
context = context.Background()
|
context = context.Background()
|
||||||
)
|
)
|
||||||
for empty := false; !empty; {
|
for i := 0; i < len(nextAddrs); i++ {
|
||||||
// Retrieve the next derived Ethereum account
|
for empty := false; !empty; {
|
||||||
if nextAddr == (common.Address{}) {
|
// Retrieve the next derived Ethereum account
|
||||||
if nextAddr, err = w.driver.Derive(nextPath); err != nil {
|
if nextAddrs[i] == (common.Address{}) {
|
||||||
w.log.Warn("USB wallet account derivation failed", "err", err)
|
if nextAddrs[i], err = w.driver.Derive(nextPaths[i]); err != nil {
|
||||||
|
w.log.Warn("USB wallet account derivation failed", "err", err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check the account's status against the current chain state
|
||||||
|
var (
|
||||||
|
balance *big.Int
|
||||||
|
nonce uint64
|
||||||
|
)
|
||||||
|
balance, err = w.deriveChain.BalanceAt(context, nextAddrs[i], nil)
|
||||||
|
if err != nil {
|
||||||
|
w.log.Warn("USB wallet balance retrieval failed", "err", err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
nonce, err = w.deriveChain.NonceAt(context, nextAddrs[i], nil)
|
||||||
// Check the account's status against the current chain state
|
if err != nil {
|
||||||
var (
|
w.log.Warn("USB wallet nonce retrieval failed", "err", err)
|
||||||
balance *big.Int
|
break
|
||||||
nonce uint64
|
}
|
||||||
)
|
// If the next account is empty, stop self-derivation, but add for the last base path
|
||||||
balance, err = w.deriveChain.BalanceAt(context, nextAddr, nil)
|
if balance.Sign() == 0 && nonce == 0 {
|
||||||
if err != nil {
|
empty = true
|
||||||
w.log.Warn("USB wallet balance retrieval failed", "err", err)
|
if i < len(nextAddrs)-1 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
nonce, err = w.deriveChain.NonceAt(context, nextAddr, nil)
|
}
|
||||||
if err != nil {
|
// We've just self-derived a new account, start tracking it locally
|
||||||
w.log.Warn("USB wallet nonce retrieval failed", "err", err)
|
path := make(accounts.DerivationPath, len(nextPaths[i]))
|
||||||
break
|
copy(path[:], nextPaths[i][:])
|
||||||
}
|
paths = append(paths, path)
|
||||||
// If the next account is empty, stop self-derivation, but add it nonetheless
|
|
||||||
if balance.Sign() == 0 && nonce == 0 {
|
|
||||||
empty = true
|
|
||||||
}
|
|
||||||
// We've just self-derived a new account, start tracking it locally
|
|
||||||
path := make(accounts.DerivationPath, len(nextPath))
|
|
||||||
copy(path[:], nextPath[:])
|
|
||||||
paths = append(paths, path)
|
|
||||||
|
|
||||||
account := accounts.Account{
|
account := accounts.Account{
|
||||||
Address: nextAddr,
|
Address: nextAddrs[i],
|
||||||
URL: accounts.URL{Scheme: w.url.Scheme, Path: fmt.Sprintf("%s/%s", w.url.Path, path)},
|
URL: accounts.URL{Scheme: w.url.Scheme, Path: fmt.Sprintf("%s/%s", w.url.Path, path)},
|
||||||
}
|
}
|
||||||
accs = append(accs, account)
|
accs = append(accs, account)
|
||||||
|
|
||||||
// Display a log message to the user for new (or previously empty accounts)
|
// Display a log message to the user for new (or previously empty accounts)
|
||||||
if _, known := w.paths[nextAddr]; !known || (!empty && nextAddr == w.deriveNextAddr) {
|
if _, known := w.paths[nextAddrs[i]]; !known || (!empty && nextAddrs[i] == w.deriveNextAddrs[i]) {
|
||||||
w.log.Info("USB wallet discovered new account", "address", nextAddr, "path", path, "balance", balance, "nonce", nonce)
|
w.log.Info("USB wallet discovered new account", "address", nextAddrs[i], "path", path, "balance", balance, "nonce", nonce)
|
||||||
}
|
}
|
||||||
// Fetch the next potential account
|
// Fetch the next potential account
|
||||||
if !empty {
|
if !empty {
|
||||||
nextAddr = common.Address{}
|
nextAddrs[i] = common.Address{}
|
||||||
nextPath[len(nextPath)-1]++
|
nextPaths[i][len(nextPaths[i])-1]++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Self derivation complete, release device lock
|
// Self derivation complete, release device lock
|
||||||
@ -406,8 +411,8 @@ func (w *wallet) selfDerive() {
|
|||||||
}
|
}
|
||||||
// Shift the self-derivation forward
|
// Shift the self-derivation forward
|
||||||
// TODO(karalabe): don't overwrite changes from wallet.SelfDerive
|
// TODO(karalabe): don't overwrite changes from wallet.SelfDerive
|
||||||
w.deriveNextAddr = nextAddr
|
w.deriveNextAddrs = nextAddrs
|
||||||
w.deriveNextPath = nextPath
|
w.deriveNextPaths = nextPaths
|
||||||
w.stateLock.Unlock()
|
w.stateLock.Unlock()
|
||||||
|
|
||||||
// Notify the user of termination and loop after a bit of time (to avoid trashing)
|
// Notify the user of termination and loop after a bit of time (to avoid trashing)
|
||||||
@ -479,18 +484,30 @@ func (w *wallet) Derive(path accounts.DerivationPath, pin bool) (accounts.Accoun
|
|||||||
return account, nil
|
return account, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SelfDerive implements accounts.Wallet, trying to discover accounts that the
|
// SelfDerive sets a base account derivation path from which the wallet attempts
|
||||||
// user used previously (based on the chain state), but ones that he/she did not
|
// to discover non zero accounts and automatically add them to list of tracked
|
||||||
// explicitly pin to the wallet manually. To avoid chain head monitoring, self
|
// accounts.
|
||||||
// derivation only runs during account listing (and even then throttled).
|
//
|
||||||
func (w *wallet) SelfDerive(base accounts.DerivationPath, chain ethereum.ChainStateReader) {
|
// Note, self derivaton will increment the last component of the specified path
|
||||||
|
// opposed to decending into a child path to allow discovering accounts starting
|
||||||
|
// from non zero components.
|
||||||
|
//
|
||||||
|
// Some hardware wallets switched derivation paths through their evolution, so
|
||||||
|
// this method supports providing multiple bases to discover old user accounts
|
||||||
|
// too. Only the last base will be used to derive the next empty account.
|
||||||
|
//
|
||||||
|
// You can disable automatic account discovery by calling SelfDerive with a nil
|
||||||
|
// chain state reader.
|
||||||
|
func (w *wallet) SelfDerive(bases []accounts.DerivationPath, chain ethereum.ChainStateReader) {
|
||||||
w.stateLock.Lock()
|
w.stateLock.Lock()
|
||||||
defer w.stateLock.Unlock()
|
defer w.stateLock.Unlock()
|
||||||
|
|
||||||
w.deriveNextPath = make(accounts.DerivationPath, len(base))
|
w.deriveNextPaths = make([]accounts.DerivationPath, len(bases))
|
||||||
copy(w.deriveNextPath[:], base[:])
|
for i, base := range bases {
|
||||||
|
w.deriveNextPaths[i] = make(accounts.DerivationPath, len(base))
|
||||||
w.deriveNextAddr = common.Address{}
|
copy(w.deriveNextPaths[i][:], base[:])
|
||||||
|
}
|
||||||
|
w.deriveNextAddrs = make([]common.Address, len(bases))
|
||||||
w.deriveChain = chain
|
w.deriveChain = chain
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,11 +342,13 @@ func startNode(ctx *cli.Context, stack *node.Node) {
|
|||||||
status, _ := event.Wallet.Status()
|
status, _ := event.Wallet.Status()
|
||||||
log.Info("New wallet appeared", "url", event.Wallet.URL(), "status", status)
|
log.Info("New wallet appeared", "url", event.Wallet.URL(), "status", status)
|
||||||
|
|
||||||
derivationPath := accounts.DefaultBaseDerivationPath
|
var derivationPaths []accounts.DerivationPath
|
||||||
if event.Wallet.URL().Scheme == "ledger" {
|
if event.Wallet.URL().Scheme == "ledger" {
|
||||||
derivationPath = accounts.DefaultLedgerBaseDerivationPath
|
derivationPaths = append(derivationPaths, accounts.LegacyLedgerBaseDerivationPath)
|
||||||
}
|
}
|
||||||
event.Wallet.SelfDerive(derivationPath, stateReader)
|
derivationPaths = append(derivationPaths, accounts.DefaultBaseDerivationPath)
|
||||||
|
|
||||||
|
event.Wallet.SelfDerive(derivationPaths, stateReader)
|
||||||
|
|
||||||
case accounts.WalletDropped:
|
case accounts.WalletDropped:
|
||||||
log.Info("Old wallet dropped", "url", event.Wallet.URL())
|
log.Info("Old wallet dropped", "url", event.Wallet.URL())
|
||||||
|
@ -319,12 +319,10 @@ func (api *SignerAPI) startUSBListener() {
|
|||||||
status, _ := event.Wallet.Status()
|
status, _ := event.Wallet.Status()
|
||||||
log.Info("New wallet appeared", "url", event.Wallet.URL(), "status", status)
|
log.Info("New wallet appeared", "url", event.Wallet.URL(), "status", status)
|
||||||
|
|
||||||
derivationPath := accounts.DefaultBaseDerivationPath
|
|
||||||
if event.Wallet.URL().Scheme == "ledger" {
|
|
||||||
derivationPath = accounts.DefaultLedgerBaseDerivationPath
|
|
||||||
}
|
|
||||||
var nextPath = derivationPath
|
|
||||||
// Derive first N accounts, hardcoded for now
|
// Derive first N accounts, hardcoded for now
|
||||||
|
var nextPath = make(accounts.DerivationPath, len(accounts.DefaultBaseDerivationPath))
|
||||||
|
copy(nextPath[:], accounts.DefaultBaseDerivationPath[:])
|
||||||
|
|
||||||
for i := 0; i < numberOfAccountsToDerive; i++ {
|
for i := 0; i < numberOfAccountsToDerive; i++ {
|
||||||
acc, err := event.Wallet.Derive(nextPath, true)
|
acc, err := event.Wallet.Derive(nextPath, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user