func (ks *KeyStore) SignHash(a accounts.Account, hash []byte) ([]byte, error) {
	ks.mu.RLock()
	defer ks.mu.RUnlock()
	unlockedKey, found := ks.unlocked[a.Address]
	if !found {
		return nil, ErrLocked
	}
	return crypto.Sign(hash, unlockedKey.PrivateKey)
}
SignHash calculates a ECDSA signature for the given hash. The produced
signature is in the [R || S || V] format where V is 0 or 1.
package keystore
import (
	"crypto/ecdsa"
	crand "crypto/rand"
	"errors"
	"fmt"
	"github.com/DSiSc/craft/types"
	"github.com/DSiSc/crypto-suite/crypto"
	"github.com/DSiSc/wallet/accounts"
	"github.com/DSiSc/wallet/common"
	local "github.com/DSiSc/wallet/core/types"
	"math/big"
	"os"
	"path/filepath"
	"reflect"
	"runtime"
	"sync"
	"time"
)
var (
	ErrLocked  = accounts.NewAuthNeededError("password or unlock")
	ErrNoMatch = errors.New("no key for given address or file")
	ErrDecrypt = errors.New("could not decrypt key with given passphrase")
)
var KeyStoreType = reflect.TypeOf(&KeyStore{})
const KeyStoreScheme = "keystore"
const walletRefreshCycle = 3 * time.Second
type KeyStore struct {
	storage  keyStore                      
	cache    *accountCache                 
	changes  chan struct{}                 
	unlocked map[common.Address]*unlocked  
	wallets []accounts.Wallet  
	mu sync.RWMutex
}
type unlocked struct {
	*Key
	abort chan struct{}
}
func NewKeyStore(keydir string, scryptN, scryptP int) *KeyStore {
	keydir, _ = filepath.Abs(keydir)
	ks := &KeyStore{storage: &keyStorePassphrase{keydir, scryptN, scryptP, false}}
	ks.init(keydir)
	return ks
}
func (ks *KeyStore) init(keydir string) {
	ks.mu.Lock()
	defer ks.mu.Unlock()
	ks.unlocked = make(map[common.Address]*unlocked)
	ks.cache, ks.changes = newAccountCache(keydir)
	runtime.SetFinalizer(ks, func(m *KeyStore) {
		m.cache.close()
	})
	accs := ks.cache.accounts()
	ks.wallets = make([]accounts.Wallet, len(accs))
	for i := 0; i < len(accs); i++ {
		ks.wallets[i] = &keystoreWallet{account: accs[i], keystore: ks}
	}
}
func (ks *KeyStore) Wallets() []accounts.Wallet {
	ks.refreshWallets()
	ks.mu.RLock()
	defer ks.mu.RUnlock()
	cpy := make([]accounts.Wallet, len(ks.wallets))
	copy(cpy, ks.wallets)
	return cpy
}
func (ks *KeyStore) refreshWallets() {
	ks.mu.Lock()
	accs := ks.cache.accounts()
	wallets := make([]accounts.Wallet, 0, len(accs))
	events := []accounts.WalletEvent{}
	for _, account := range accs {
		for len(ks.wallets) > 0 && ks.wallets[0].URL().Cmp(account.URL) < 0 {
			events = append(events, accounts.WalletEvent{Wallet: ks.wallets[0], Kind: accounts.WalletDropped})
			ks.wallets = ks.wallets[1:]
		}
		if len(ks.wallets) == 0 || ks.wallets[0].URL().Cmp(account.URL) > 0 {
			wallet := &keystoreWallet{account: account, keystore: ks}
			events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletArrived})
			wallets = append(wallets, wallet)
			continue
		}
		if ks.wallets[0].Accounts()[0] == account {
			wallets = append(wallets, ks.wallets[0])
			ks.wallets = ks.wallets[1:]
			continue
		}
	}
	for _, wallet := range ks.wallets {
		events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletDropped})
	}
	ks.wallets = wallets
	ks.mu.Unlock()
}
func (ks *KeyStore) HasAddress(addr common.Address) bool {
	return ks.cache.hasAddress(addr)
}
func (ks *KeyStore) Accounts() []accounts.Account {
	return ks.cache.accounts()
}
func (ks *KeyStore) Delete(a accounts.Account, passphrase string) error {
	a, key, err := ks.GetDecryptedKey(a, passphrase)
	if key != nil {
		zeroKey(key.PrivateKey)
	}
	if err != nil {
		return err
	}
	err = os.Remove(a.URL.Path)
	if err == nil {
		ks.cache.delete(a)
		ks.refreshWallets()
	}
	return err
}