github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/accounts/keystore/keystore.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //版权所有2017 Go Ethereum作者
    10  //此文件是Go以太坊库的一部分。
    11  //
    12  //Go-Ethereum库是免费软件:您可以重新分发它和/或修改
    13  //根据GNU发布的较低通用公共许可证的条款
    14  //自由软件基金会,或者许可证的第3版,或者
    15  //(由您选择)任何更高版本。
    16  //
    17  //Go以太坊图书馆的发行目的是希望它会有用,
    18  //但没有任何保证;甚至没有
    19  //适销性或特定用途的适用性。见
    20  //GNU较低的通用公共许可证,了解更多详细信息。
    21  //
    22  //你应该收到一份GNU较低级别的公共许可证副本
    23  //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。
    24  
    25  //package keystore实现对secp256k1私钥的加密存储。
    26  //
    27  //根据Web3秘密存储规范,密钥存储为加密的JSON文件。
    28  //有关详细信息,请参阅https://github.com/ethereum/wiki/wiki/web3-secret-storage-definition。
    29  package keystore
    30  
    31  import (
    32  	"crypto/ecdsa"
    33  	crand "crypto/rand"
    34  	"errors"
    35  	"fmt"
    36  	"math/big"
    37  	"os"
    38  	"path/filepath"
    39  	"reflect"
    40  	"runtime"
    41  	"sync"
    42  	"time"
    43  
    44  	"github.com/ethereum/go-ethereum/accounts"
    45  	"github.com/ethereum/go-ethereum/common"
    46  	"github.com/ethereum/go-ethereum/core/types"
    47  	"github.com/ethereum/go-ethereum/crypto"
    48  	"github.com/ethereum/go-ethereum/event"
    49  )
    50  
    51  var (
    52  	ErrLocked  = accounts.NewAuthNeededError("password or unlock")
    53  	ErrNoMatch = errors.New("no key for given address or file")
    54  	ErrDecrypt = errors.New("could not decrypt key with given passphrase")
    55  )
    56  
    57  //keystore type是keystore后端的反射类型。
    58  var KeyStoreType = reflect.TypeOf(&KeyStore{})
    59  
    60  //keystorescheme是协议方案的前缀帐户和钱包URL。
    61  const KeyStoreScheme = "keystore"
    62  
    63  //钱包刷新之间的最长时间(如果文件系统通知不起作用)。
    64  const walletRefreshCycle = 3 * time.Second
    65  
    66  //keystore管理磁盘上的密钥存储目录。
    67  type KeyStore struct {
    68  storage  keyStore                     //存储后端,可能是明文或加密的
    69  cache    *accountCache                //文件系统存储上的内存帐户缓存
    70  changes  chan struct{}                //从缓存接收更改通知的通道
    71  unlocked map[common.Address]*unlocked //当前未锁定的帐户(解密的私钥)
    72  
    73  wallets     []accounts.Wallet       //单个钥匙文件周围的钱包包装纸
    74  updateFeed  event.Feed              //通知钱包添加/删除的事件源
    75  updateScope event.SubscriptionScope //订阅范围跟踪当前实时侦听器
    76  updating    bool                    //事件通知循环是否正在运行
    77  
    78  	mu sync.RWMutex
    79  }
    80  
    81  type unlocked struct {
    82  	*Key
    83  	abort chan struct{}
    84  }
    85  
    86  //newkeystore为给定目录创建一个keystore。
    87  func NewKeyStore(keydir string, scryptN, scryptP int) *KeyStore {
    88  	keydir, _ = filepath.Abs(keydir)
    89  	ks := &KeyStore{storage: &keyStorePassphrase{keydir, scryptN, scryptP}}
    90  	ks.init(keydir)
    91  	return ks
    92  }
    93  
    94  //newplaintextkeystore为给定目录创建一个keystore。
    95  //已弃用:使用newkeystore。
    96  func NewPlaintextKeyStore(keydir string) *KeyStore {
    97  	keydir, _ = filepath.Abs(keydir)
    98  	ks := &KeyStore{storage: &keyStorePlain{keydir}}
    99  	ks.init(keydir)
   100  	return ks
   101  }
   102  
   103  func (ks *KeyStore) init(keydir string) {
   104  //锁定互斥体,因为帐户缓存可能使用事件回调
   105  	ks.mu.Lock()
   106  	defer ks.mu.Unlock()
   107  
   108  //初始化一组未锁定的密钥和帐户缓存
   109  	ks.unlocked = make(map[common.Address]*unlocked)
   110  	ks.cache, ks.changes = newAccountCache(keydir)
   111  
   112  //TODO:要使此终结器工作,必须没有引用
   113  //对KS。AddressCache不保留引用,但未锁定的键会保留引用,
   114  //因此,在所有定时解锁过期之前,终结器不会触发。
   115  	runtime.SetFinalizer(ks, func(m *KeyStore) {
   116  		m.cache.close()
   117  	})
   118  //从缓存创建钱包的初始列表
   119  	accs := ks.cache.accounts()
   120  	ks.wallets = make([]accounts.Wallet, len(accs))
   121  	for i := 0; i < len(accs); i++ {
   122  		ks.wallets[i] = &keystoreWallet{account: accs[i], keystore: ks}
   123  	}
   124  }
   125  
   126  //钱包实现accounts.backend,从
   127  //密钥存储目录。
   128  func (ks *KeyStore) Wallets() []accounts.Wallet {
   129  //确保钱包列表与帐户缓存同步
   130  	ks.refreshWallets()
   131  
   132  	ks.mu.RLock()
   133  	defer ks.mu.RUnlock()
   134  
   135  	cpy := make([]accounts.Wallet, len(ks.wallets))
   136  	copy(cpy, ks.wallets)
   137  	return cpy
   138  }
   139  
   140  //刷新钱包检索当前帐户列表,并基于此执行任何操作
   141  //必要的钱包更新。
   142  func (ks *KeyStore) refreshWallets() {
   143  //检索当前帐户列表
   144  	ks.mu.Lock()
   145  	accs := ks.cache.accounts()
   146  
   147  //将当前钱包列表转换为新列表
   148  	wallets := make([]accounts.Wallet, 0, len(accs))
   149  	events := []accounts.WalletEvent{}
   150  
   151  	for _, account := range accs {
   152  //把钱包放在下一个账户前
   153  		for len(ks.wallets) > 0 && ks.wallets[0].URL().Cmp(account.URL) < 0 {
   154  			events = append(events, accounts.WalletEvent{Wallet: ks.wallets[0], Kind: accounts.WalletDropped})
   155  			ks.wallets = ks.wallets[1:]
   156  		}
   157  //如果没有更多的钱包或帐户在下一个之前,请包装新钱包
   158  		if len(ks.wallets) == 0 || ks.wallets[0].URL().Cmp(account.URL) > 0 {
   159  			wallet := &keystoreWallet{account: account, keystore: ks}
   160  
   161  			events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletArrived})
   162  			wallets = append(wallets, wallet)
   163  			continue
   164  		}
   165  //如果账户与第一个钱包相同,请保留它
   166  		if ks.wallets[0].Accounts()[0] == account {
   167  			wallets = append(wallets, ks.wallets[0])
   168  			ks.wallets = ks.wallets[1:]
   169  			continue
   170  		}
   171  	}
   172  //扔掉所有剩余的钱包,并设置新的一批
   173  	for _, wallet := range ks.wallets {
   174  		events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletDropped})
   175  	}
   176  	ks.wallets = wallets
   177  	ks.mu.Unlock()
   178  
   179  //启动所有钱包事件并返回
   180  	for _, event := range events {
   181  		ks.updateFeed.Send(event)
   182  	}
   183  }
   184  
   185  //subscribe实现accounts.backend,创建对的异步订阅
   186  //接收有关添加或删除密钥库钱包的通知。
   187  func (ks *KeyStore) Subscribe(sink chan<- accounts.WalletEvent) event.Subscription {
   188  //我们需要mutex来可靠地启动/停止更新循环
   189  	ks.mu.Lock()
   190  	defer ks.mu.Unlock()
   191  
   192  //订阅调用方并跟踪订阅方计数
   193  	sub := ks.updateScope.Track(ks.updateFeed.Subscribe(sink))
   194  
   195  //订阅服务器需要一个活动的通知循环,启动它
   196  	if !ks.updating {
   197  		ks.updating = true
   198  		go ks.updater()
   199  	}
   200  	return sub
   201  }
   202  
   203  //更新程序负责维护存储在
   204  //密钥库,用于启动钱包添加/删除事件。它倾听
   205  //来自基础帐户缓存的帐户更改事件,并且还定期
   206  //强制手动刷新(仅适用于文件系统通知程序所在的系统
   207  //没有运行)。
   208  func (ks *KeyStore) updater() {
   209  	for {
   210  //等待帐户更新或刷新超时
   211  		select {
   212  		case <-ks.changes:
   213  		case <-time.After(walletRefreshCycle):
   214  		}
   215  //运行钱包刷新程序
   216  		ks.refreshWallets()
   217  
   218  //如果我们所有的订户都离开了,请停止更新程序
   219  		ks.mu.Lock()
   220  		if ks.updateScope.Count() == 0 {
   221  			ks.updating = false
   222  			ks.mu.Unlock()
   223  			return
   224  		}
   225  		ks.mu.Unlock()
   226  	}
   227  }
   228  
   229  //hasAddress报告具有给定地址的密钥是否存在。
   230  func (ks *KeyStore) HasAddress(addr common.Address) bool {
   231  	return ks.cache.hasAddress(addr)
   232  }
   233  
   234  //帐户返回目录中存在的所有密钥文件。
   235  func (ks *KeyStore) Accounts() []accounts.Account {
   236  	return ks.cache.accounts()
   237  }
   238  
   239  //如果密码短语正确,则delete将删除与帐户匹配的密钥。
   240  //如果帐户不包含文件名,则地址必须与唯一键匹配。
   241  func (ks *KeyStore) Delete(a accounts.Account, passphrase string) error {
   242  //解密密钥不是真正必要的,但我们确实需要
   243  //不管怎样,检查密码然后把钥匙调零
   244  //紧接着。
   245  	a, key, err := ks.getDecryptedKey(a, passphrase)
   246  	if key != nil {
   247  		zeroKey(key.PrivateKey)
   248  	}
   249  	if err != nil {
   250  		return err
   251  	}
   252  //这里的秩序至关重要。钥匙从
   253  //文件消失后缓存,以便在
   254  //between不会再将其插入缓存。
   255  	err = os.Remove(a.URL.Path)
   256  	if err == nil {
   257  		ks.cache.delete(a)
   258  		ks.refreshWallets()
   259  	}
   260  	return err
   261  }
   262  
   263  //signhash为给定哈希计算ECDSA签名。产生的
   264  //签名采用[R S V]格式,其中V为0或1。
   265  func (ks *KeyStore) SignHash(a accounts.Account, hash []byte) ([]byte, error) {
   266  //查找要签名的密钥,如果找不到,则中止
   267  	ks.mu.RLock()
   268  	defer ks.mu.RUnlock()
   269  
   270  	unlockedKey, found := ks.unlocked[a.Address]
   271  	if !found {
   272  		return nil, ErrLocked
   273  	}
   274  //使用普通ECDSA操作对哈希进行签名
   275  	return crypto.Sign(hash, unlockedKey.PrivateKey)
   276  }
   277  
   278  //signtx用请求的帐户对给定的事务进行签名。
   279  func (ks *KeyStore) SignTx(a accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
   280  //查找要签名的密钥,如果找不到,则中止
   281  	ks.mu.RLock()
   282  	defer ks.mu.RUnlock()
   283  
   284  	unlockedKey, found := ks.unlocked[a.Address]
   285  	if !found {
   286  		return nil, ErrLocked
   287  	}
   288  //根据链ID的存在,用EIP155或宅基地签名
   289  	if chainID != nil {
   290  		return types.SignTx(tx, types.NewEIP155Signer(chainID), unlockedKey.PrivateKey)
   291  	}
   292  	return types.SignTx(tx, types.HomesteadSigner{}, unlockedKey.PrivateKey)
   293  }
   294  
   295  //如果私钥与给定地址匹配,则signhashwithpassphrase将对哈希进行签名
   296  //可以用给定的密码短语解密。生成的签名在
   297  //[R_S_V]格式,其中V为0或1。
   298  func (ks *KeyStore) SignHashWithPassphrase(a accounts.Account, passphrase string, hash []byte) (signature []byte, err error) {
   299  	_, key, err := ks.getDecryptedKey(a, passphrase)
   300  	if err != nil {
   301  		return nil, err
   302  	}
   303  	defer zeroKey(key.PrivateKey)
   304  	return crypto.Sign(hash, key.PrivateKey)
   305  }
   306  
   307  //如果私钥与
   308  //给定的地址可以用给定的密码短语解密。
   309  func (ks *KeyStore) SignTxWithPassphrase(a accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
   310  	_, key, err := ks.getDecryptedKey(a, passphrase)
   311  	if err != nil {
   312  		return nil, err
   313  	}
   314  	defer zeroKey(key.PrivateKey)
   315  
   316  //根据链ID的存在,用EIP155或宅基地签名
   317  	if chainID != nil {
   318  		return types.SignTx(tx, types.NewEIP155Signer(chainID), key.PrivateKey)
   319  	}
   320  	return types.SignTx(tx, types.HomesteadSigner{}, key.PrivateKey)
   321  }
   322  
   323  //解锁无限期地解锁给定的帐户。
   324  func (ks *KeyStore) Unlock(a accounts.Account, passphrase string) error {
   325  	return ks.TimedUnlock(a, passphrase, 0)
   326  }
   327  
   328  //lock从内存中删除具有给定地址的私钥。
   329  func (ks *KeyStore) Lock(addr common.Address) error {
   330  	ks.mu.Lock()
   331  	if unl, found := ks.unlocked[addr]; found {
   332  		ks.mu.Unlock()
   333  		ks.expire(addr, unl, time.Duration(0)*time.Nanosecond)
   334  	} else {
   335  		ks.mu.Unlock()
   336  	}
   337  	return nil
   338  }
   339  
   340  //timedunlock使用密码短语解锁给定的帐户。帐户
   341  //在超时期间保持解锁状态。超时0将解锁帐户
   342  //直到程序退出。帐户必须与唯一的密钥文件匹配。
   343  //
   344  //如果帐户地址在一段时间内已解锁,则TimedUnlock将扩展或
   345  //缩短活动解锁超时。如果地址以前是解锁的
   346  //无限期地超时不会改变。
   347  func (ks *KeyStore) TimedUnlock(a accounts.Account, passphrase string, timeout time.Duration) error {
   348  	a, key, err := ks.getDecryptedKey(a, passphrase)
   349  	if err != nil {
   350  		return err
   351  	}
   352  
   353  	ks.mu.Lock()
   354  	defer ks.mu.Unlock()
   355  	u, found := ks.unlocked[a.Address]
   356  	if found {
   357  		if u.abort == nil {
   358  //地址被无限期地解锁,所以解锁
   359  //超时会让人困惑。
   360  			zeroKey(key.PrivateKey)
   361  			return nil
   362  		}
   363  //终止过期的goroutine并在下面替换它。
   364  		close(u.abort)
   365  	}
   366  	if timeout > 0 {
   367  		u = &unlocked{Key: key, abort: make(chan struct{})}
   368  		go ks.expire(a.Address, u, timeout)
   369  	} else {
   370  		u = &unlocked{Key: key}
   371  	}
   372  	ks.unlocked[a.Address] = u
   373  	return nil
   374  }
   375  
   376  //find将给定帐户解析为密钥库中的唯一条目。
   377  func (ks *KeyStore) Find(a accounts.Account) (accounts.Account, error) {
   378  	ks.cache.maybeReload()
   379  	ks.cache.mu.Lock()
   380  	a, err := ks.cache.find(a)
   381  	ks.cache.mu.Unlock()
   382  	return a, err
   383  }
   384  
   385  func (ks *KeyStore) getDecryptedKey(a accounts.Account, auth string) (accounts.Account, *Key, error) {
   386  	a, err := ks.Find(a)
   387  	if err != nil {
   388  		return a, nil, err
   389  	}
   390  	key, err := ks.storage.GetKey(a.Address, a.URL.Path, auth)
   391  	return a, key, err
   392  }
   393  
   394  func (ks *KeyStore) expire(addr common.Address, u *unlocked, timeout time.Duration) {
   395  	t := time.NewTimer(timeout)
   396  	defer t.Stop()
   397  	select {
   398  	case <-u.abort:
   399  //刚刚辞职
   400  	case <-t.C:
   401  		ks.mu.Lock()
   402  //仅当它仍然是DropLater的同一个键实例时才删除
   403  //与一起启动。我们可以用指针相等来检查
   404  //因为每次键
   405  //解锁。
   406  		if ks.unlocked[addr] == u {
   407  			zeroKey(u.PrivateKey)
   408  			delete(ks.unlocked, addr)
   409  		}
   410  		ks.mu.Unlock()
   411  	}
   412  }
   413  
   414  //newaccount生成一个新密钥并将其存储到密钥目录中,
   415  //用密码短语加密。
   416  func (ks *KeyStore) NewAccount(passphrase string) (accounts.Account, error) {
   417  	_, account, err := storeNewKey(ks.storage, crand.Reader, passphrase)
   418  	if err != nil {
   419  		return accounts.Account{}, err
   420  	}
   421  //而是立即将帐户添加到缓存中
   422  //而不是等待文件系统通知来接收它。
   423  	ks.cache.add(account)
   424  	ks.refreshWallets()
   425  	return account, nil
   426  }
   427  
   428  //以json密钥的形式导出,并用newpassphrase加密。
   429  func (ks *KeyStore) Export(a accounts.Account, passphrase, newPassphrase string) (keyJSON []byte, err error) {
   430  	_, key, err := ks.getDecryptedKey(a, passphrase)
   431  	if err != nil {
   432  		return nil, err
   433  	}
   434  	var N, P int
   435  	if store, ok := ks.storage.(*keyStorePassphrase); ok {
   436  		N, P = store.scryptN, store.scryptP
   437  	} else {
   438  		N, P = StandardScryptN, StandardScryptP
   439  	}
   440  	return EncryptKey(key, newPassphrase, N, P)
   441  }
   442  
   443  //import将给定的加密JSON密钥存储到密钥目录中。
   444  func (ks *KeyStore) Import(keyJSON []byte, passphrase, newPassphrase string) (accounts.Account, error) {
   445  	key, err := DecryptKey(keyJSON, passphrase)
   446  	if key != nil && key.PrivateKey != nil {
   447  		defer zeroKey(key.PrivateKey)
   448  	}
   449  	if err != nil {
   450  		return accounts.Account{}, err
   451  	}
   452  	return ks.importKey(key, newPassphrase)
   453  }
   454  
   455  //importecdsa将给定的密钥存储到密钥目录中,并用密码短语对其进行加密。
   456  func (ks *KeyStore) ImportECDSA(priv *ecdsa.PrivateKey, passphrase string) (accounts.Account, error) {
   457  	key := newKeyFromECDSA(priv)
   458  	if ks.cache.hasAddress(key.Address) {
   459  		return accounts.Account{}, fmt.Errorf("account already exists")
   460  	}
   461  	return ks.importKey(key, passphrase)
   462  }
   463  
   464  func (ks *KeyStore) importKey(key *Key, passphrase string) (accounts.Account, error) {
   465  	a := accounts.Account{Address: key.Address, URL: accounts.URL{Scheme: KeyStoreScheme, Path: ks.storage.JoinPath(keyFileName(key.Address))}}
   466  	if err := ks.storage.StoreKey(a.URL.Path, key, passphrase); err != nil {
   467  		return accounts.Account{}, err
   468  	}
   469  	ks.cache.add(a)
   470  	ks.refreshWallets()
   471  	return a, nil
   472  }
   473  
   474  //更新更改现有帐户的密码。
   475  func (ks *KeyStore) Update(a accounts.Account, passphrase, newPassphrase string) error {
   476  	a, key, err := ks.getDecryptedKey(a, passphrase)
   477  	if err != nil {
   478  		return err
   479  	}
   480  	return ks.storage.StoreKey(a.URL.Path, key, newPassphrase)
   481  }
   482  
   483  //importpresalekey解密给定的以太坊预售钱包和商店
   484  //密钥目录中的密钥文件。密钥文件使用相同的密码短语加密。
   485  func (ks *KeyStore) ImportPreSaleKey(keyJSON []byte, passphrase string) (accounts.Account, error) {
   486  	a, _, err := importPreSaleKey(ks.storage, keyJSON, passphrase)
   487  	if err != nil {
   488  		return a, err
   489  	}
   490  	ks.cache.add(a)
   491  	ks.refreshWallets()
   492  	return a, nil
   493  }
   494  
   495  //zerokey使内存中的私钥归零。
   496  func zeroKey(k *ecdsa.PrivateKey) {
   497  	b := k.D.Bits()
   498  	for i := range b {
   499  		b[i] = 0
   500  	}
   501  }