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 }