Lock/unlock all account wallets.
Now that it has been decided that all account wallets will share the same passphrase, the walletlock and walletpassphrase RPC handlers now go through the accountstore to lock or unlock all account wallets, rather than only changing the default account.
This commit is contained in:
parent
e2bf9a03da
commit
b09e4f5200
3 changed files with 61 additions and 57 deletions
22
account.go
22
account.go
|
@ -122,23 +122,31 @@ func (a *Account) Lock() error {
|
||||||
a.mtx.Lock()
|
a.mtx.Lock()
|
||||||
defer a.mtx.Unlock()
|
defer a.mtx.Unlock()
|
||||||
|
|
||||||
err := a.Wallet.Lock()
|
switch err := a.Wallet.Lock(); err {
|
||||||
if err == nil {
|
case nil:
|
||||||
NotifyWalletLockStateChange(a.Name(), true)
|
NotifyWalletLockStateChange(a.Name(), true)
|
||||||
}
|
return nil
|
||||||
|
|
||||||
|
case wallet.ErrWalletLocked:
|
||||||
|
// Do not pass wallet already locked errors to the caller.
|
||||||
|
return nil
|
||||||
|
|
||||||
|
default:
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Unlock unlocks the underlying wallet for an account.
|
// Unlock unlocks the underlying wallet for an account.
|
||||||
func (a *Account) Unlock(passphrase []byte) error {
|
func (a *Account) Unlock(passphrase []byte) error {
|
||||||
a.mtx.Lock()
|
a.mtx.Lock()
|
||||||
defer a.mtx.Unlock()
|
defer a.mtx.Unlock()
|
||||||
|
|
||||||
err := a.Wallet.Unlock(passphrase)
|
if err := a.Wallet.Unlock(passphrase); err != nil {
|
||||||
if err == nil {
|
return err
|
||||||
NotifyWalletLockStateChange(a.Name(), false)
|
|
||||||
}
|
}
|
||||||
return a.Wallet.Unlock(passphrase)
|
|
||||||
|
NotifyWalletLockStateChange(a.Name(), false)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rollback reverts each stored Account to a state before the block
|
// Rollback reverts each stored Account to a state before the block
|
||||||
|
|
|
@ -295,6 +295,42 @@ func (store *AccountStore) ChangePassphrase(old, new []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LockWallets locks all account's wallets in the store.
|
||||||
|
func (store *AccountStore) LockWallets() error {
|
||||||
|
store.RLock()
|
||||||
|
defer store.RUnlock()
|
||||||
|
|
||||||
|
for _, a := range store.accounts {
|
||||||
|
if err := a.Lock(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnlockWallets unlocks all account's wallets in the store with the provided
|
||||||
|
// passphrase. If any wallet unlocks fail, all successfully unlocked wallets
|
||||||
|
// are locked again.
|
||||||
|
func (store *AccountStore) UnlockWallets(passphrase string) error {
|
||||||
|
store.RLock()
|
||||||
|
defer store.RUnlock()
|
||||||
|
|
||||||
|
unlockedAccts := make([]*Account, 0, len(store.accounts))
|
||||||
|
for _, a := range store.accounts {
|
||||||
|
if err := a.Unlock([]byte(passphrase)); err != nil {
|
||||||
|
for _, ua := range unlockedAccts {
|
||||||
|
ua.Lock()
|
||||||
|
}
|
||||||
|
return fmt.Errorf("cannot unlock account %v: %v",
|
||||||
|
a.name, err)
|
||||||
|
}
|
||||||
|
unlockedAccts = append(unlockedAccts, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// DumpKeys returns all WIF-encoded private keys associated with all
|
// DumpKeys returns all WIF-encoded private keys associated with all
|
||||||
// accounts. All wallets must be unlocked for this operation to succeed.
|
// accounts. All wallets must be unlocked for this operation to succeed.
|
||||||
func (store *AccountStore) DumpKeys() ([]string, error) {
|
func (store *AccountStore) DumpKeys() ([]string, error) {
|
||||||
|
|
54
cmdmgr.go
54
cmdmgr.go
|
@ -1213,26 +1213,11 @@ func WalletIsLocked(icmd btcjson.Cmd) (interface{}, *btcjson.Error) {
|
||||||
return locked, nil
|
return locked, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WalletLock handles a walletlock request by locking the wallet,
|
// WalletLock handles a walletlock request by locking the all account
|
||||||
// returning an error if the wallet is already locked.
|
// wallets, returning an error if any wallet is not encrypted (for example,
|
||||||
//
|
// a watching-only wallet).
|
||||||
// TODO(jrick): figure out how multiple wallets/accounts will work
|
|
||||||
// with this. Lock all the wallets, like if all accounts are locked
|
|
||||||
// for one bitcoind wallet?
|
|
||||||
func WalletLock(icmd btcjson.Cmd) (interface{}, *btcjson.Error) {
|
func WalletLock(icmd btcjson.Cmd) (interface{}, *btcjson.Error) {
|
||||||
a, err := accountstore.Account("")
|
if err := accountstore.LockWallets(); err != nil {
|
||||||
switch err {
|
|
||||||
case nil:
|
|
||||||
break
|
|
||||||
|
|
||||||
case ErrAcctNotExist:
|
|
||||||
e := btcjson.Error{
|
|
||||||
Code: btcjson.ErrWallet.Code,
|
|
||||||
Message: "default account does not exist",
|
|
||||||
}
|
|
||||||
return nil, &e
|
|
||||||
|
|
||||||
default: // all other non-nil errors
|
|
||||||
e := btcjson.Error{
|
e := btcjson.Error{
|
||||||
Code: btcjson.ErrWallet.Code,
|
Code: btcjson.ErrWallet.Code,
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
|
@ -1240,17 +1225,12 @@ func WalletLock(icmd btcjson.Cmd) (interface{}, *btcjson.Error) {
|
||||||
return nil, &e
|
return nil, &e
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := a.Lock(); err != nil {
|
|
||||||
return nil, &btcjson.ErrWalletWrongEncState
|
|
||||||
}
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WalletPassphrase responds to the walletpassphrase request by unlocking
|
// WalletPassphrase responds to the walletpassphrase request by unlocking
|
||||||
// the wallet. The decryption key is saved in the wallet until timeout
|
// the wallet. The decryption key is saved in the wallet until timeout
|
||||||
// seconds expires, after which the wallet is locked.
|
// seconds expires, after which the wallet is locked.
|
||||||
//
|
|
||||||
// TODO(jrick): figure out how to do this for non-default accounts.
|
|
||||||
func WalletPassphrase(icmd btcjson.Cmd) (interface{}, *btcjson.Error) {
|
func WalletPassphrase(icmd btcjson.Cmd) (interface{}, *btcjson.Error) {
|
||||||
// Type assert icmd to access parameters.
|
// Type assert icmd to access parameters.
|
||||||
cmd, ok := icmd.(*btcjson.WalletPassphraseCmd)
|
cmd, ok := icmd.(*btcjson.WalletPassphraseCmd)
|
||||||
|
@ -1258,19 +1238,7 @@ func WalletPassphrase(icmd btcjson.Cmd) (interface{}, *btcjson.Error) {
|
||||||
return nil, &btcjson.ErrInternal
|
return nil, &btcjson.ErrInternal
|
||||||
}
|
}
|
||||||
|
|
||||||
a, err := accountstore.Account("")
|
if err := accountstore.UnlockWallets(cmd.Passphrase); err != nil {
|
||||||
switch err {
|
|
||||||
case nil:
|
|
||||||
break
|
|
||||||
|
|
||||||
case ErrAcctNotExist:
|
|
||||||
e := btcjson.Error{
|
|
||||||
Code: btcjson.ErrWallet.Code,
|
|
||||||
Message: "default account does not exist",
|
|
||||||
}
|
|
||||||
return nil, &e
|
|
||||||
|
|
||||||
default: // all other non-nil errors
|
|
||||||
e := btcjson.Error{
|
e := btcjson.Error{
|
||||||
Code: btcjson.ErrWallet.Code,
|
Code: btcjson.ErrWallet.Code,
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
|
@ -1278,20 +1246,12 @@ func WalletPassphrase(icmd btcjson.Cmd) (interface{}, *btcjson.Error) {
|
||||||
return nil, &e
|
return nil, &e
|
||||||
}
|
}
|
||||||
|
|
||||||
switch err := a.Unlock([]byte(cmd.Passphrase)); err {
|
|
||||||
case nil:
|
|
||||||
go func(timeout int64) {
|
go func(timeout int64) {
|
||||||
time.Sleep(time.Second * time.Duration(timeout))
|
time.Sleep(time.Second * time.Duration(timeout))
|
||||||
_ = a.Lock()
|
_ = accountstore.LockWallets()
|
||||||
}(cmd.Timeout)
|
}(cmd.Timeout)
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
||||||
case ErrAcctNotExist:
|
|
||||||
return nil, &btcjson.ErrWalletInvalidAccountName
|
|
||||||
|
|
||||||
default: // all other non-nil errors
|
|
||||||
return nil, &btcjson.ErrWalletPassphraseIncorrect
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WalletPassphraseChange responds to the walletpassphrasechange request
|
// WalletPassphraseChange responds to the walletpassphrasechange request
|
||||||
|
|
Loading…
Reference in a new issue