github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/accounts/keystore/keystore_test.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 26 27 import ( 28 "io/ioutil" 29 "math/rand" 30 "os" 31 "runtime" 32 "sort" 33 "strings" 34 "testing" 35 "time" 36 37 "github.com/ethereum/go-ethereum/accounts" 38 "github.com/ethereum/go-ethereum/common" 39 "github.com/ethereum/go-ethereum/event" 40 ) 41 42 var testSigData = make([]byte, 32) 43 44 func TestKeyStore(t *testing.T) { 45 dir, ks := tmpKeyStore(t, true) 46 defer os.RemoveAll(dir) 47 48 a, err := ks.NewAccount("foo") 49 if err != nil { 50 t.Fatal(err) 51 } 52 if !strings.HasPrefix(a.URL.Path, dir) { 53 t.Errorf("account file %s doesn't have dir prefix", a.URL) 54 } 55 stat, err := os.Stat(a.URL.Path) 56 if err != nil { 57 t.Fatalf("account file %s doesn't exist (%v)", a.URL, err) 58 } 59 if runtime.GOOS != "windows" && stat.Mode() != 0600 { 60 t.Fatalf("account file has wrong mode: got %o, want %o", stat.Mode(), 0600) 61 } 62 if !ks.HasAddress(a.Address) { 63 t.Errorf("HasAccount(%x) should've returned true", a.Address) 64 } 65 if err := ks.Update(a, "foo", "bar"); err != nil { 66 t.Errorf("Update error: %v", err) 67 } 68 if err := ks.Delete(a, "bar"); err != nil { 69 t.Errorf("Delete error: %v", err) 70 } 71 if common.FileExist(a.URL.Path) { 72 t.Errorf("account file %s should be gone after Delete", a.URL) 73 } 74 if ks.HasAddress(a.Address) { 75 t.Errorf("HasAccount(%x) should've returned true after Delete", a.Address) 76 } 77 } 78 79 func TestSign(t *testing.T) { 80 dir, ks := tmpKeyStore(t, true) 81 defer os.RemoveAll(dir) 82 83 pass := "" //未使用,但API要求 84 a1, err := ks.NewAccount(pass) 85 if err != nil { 86 t.Fatal(err) 87 } 88 if err := ks.Unlock(a1, ""); err != nil { 89 t.Fatal(err) 90 } 91 if _, err := ks.SignHash(accounts.Account{Address: a1.Address}, testSigData); err != nil { 92 t.Fatal(err) 93 } 94 } 95 96 func TestSignWithPassphrase(t *testing.T) { 97 dir, ks := tmpKeyStore(t, true) 98 defer os.RemoveAll(dir) 99 100 pass := "passwd" 101 acc, err := ks.NewAccount(pass) 102 if err != nil { 103 t.Fatal(err) 104 } 105 106 if _, unlocked := ks.unlocked[acc.Address]; unlocked { 107 t.Fatal("expected account to be locked") 108 } 109 110 _, err = ks.SignHashWithPassphrase(acc, pass, testSigData) 111 if err != nil { 112 t.Fatal(err) 113 } 114 115 if _, unlocked := ks.unlocked[acc.Address]; unlocked { 116 t.Fatal("expected account to be locked") 117 } 118 119 if _, err = ks.SignHashWithPassphrase(acc, "invalid passwd", testSigData); err == nil { 120 t.Fatal("expected SignHashWithPassphrase to fail with invalid password") 121 } 122 } 123 124 func TestTimedUnlock(t *testing.T) { 125 dir, ks := tmpKeyStore(t, true) 126 defer os.RemoveAll(dir) 127 128 pass := "foo" 129 a1, err := ks.NewAccount(pass) 130 if err != nil { 131 t.Fatal(err) 132 } 133 134 //没有密码的签名失败,因为帐户已锁定 135 _, err = ks.SignHash(accounts.Account{Address: a1.Address}, testSigData) 136 if err != ErrLocked { 137 t.Fatal("Signing should've failed with ErrLocked before unlocking, got ", err) 138 } 139 140 //用密码签名工作 141 if err = ks.TimedUnlock(a1, pass, 100*time.Millisecond); err != nil { 142 t.Fatal(err) 143 } 144 145 //没有密码的签名有效,因为帐户是临时解锁的 146 _, err = ks.SignHash(accounts.Account{Address: a1.Address}, testSigData) 147 if err != nil { 148 t.Fatal("Signing shouldn't return an error after unlocking, got ", err) 149 } 150 151 //自动锁定后签名再次失败 152 time.Sleep(250 * time.Millisecond) 153 _, err = ks.SignHash(accounts.Account{Address: a1.Address}, testSigData) 154 if err != ErrLocked { 155 t.Fatal("Signing should've failed with ErrLocked timeout expired, got ", err) 156 } 157 } 158 159 func TestOverrideUnlock(t *testing.T) { 160 dir, ks := tmpKeyStore(t, false) 161 defer os.RemoveAll(dir) 162 163 pass := "foo" 164 a1, err := ks.NewAccount(pass) 165 if err != nil { 166 t.Fatal(err) 167 } 168 169 //无限期解锁。 170 if err = ks.TimedUnlock(a1, pass, 5*time.Minute); err != nil { 171 t.Fatal(err) 172 } 173 174 //没有密码的签名有效,因为帐户是临时解锁的 175 _, err = ks.SignHash(accounts.Account{Address: a1.Address}, testSigData) 176 if err != nil { 177 t.Fatal("Signing shouldn't return an error after unlocking, got ", err) 178 } 179 180 //将解锁重置为较短的时间,使以前的解锁无效 181 if err = ks.TimedUnlock(a1, pass, 100*time.Millisecond); err != nil { 182 t.Fatal(err) 183 } 184 185 //没有密码的签名仍然有效,因为帐户是临时解锁的 186 _, err = ks.SignHash(accounts.Account{Address: a1.Address}, testSigData) 187 if err != nil { 188 t.Fatal("Signing shouldn't return an error after unlocking, got ", err) 189 } 190 191 //自动锁定后签名再次失败 192 time.Sleep(250 * time.Millisecond) 193 _, err = ks.SignHash(accounts.Account{Address: a1.Address}, testSigData) 194 if err != ErrLocked { 195 t.Fatal("Signing should've failed with ErrLocked timeout expired, got ", err) 196 } 197 } 198 199 //如果签名超过有效期,则此测试将在竞速下失败。 200 func TestSignRace(t *testing.T) { 201 dir, ks := tmpKeyStore(t, false) 202 defer os.RemoveAll(dir) 203 204 //创建测试帐户。 205 a1, err := ks.NewAccount("") 206 if err != nil { 207 t.Fatal("could not create the test account", err) 208 } 209 210 if err := ks.TimedUnlock(a1, "", 15*time.Millisecond); err != nil { 211 t.Fatal("could not unlock the test account", err) 212 } 213 end := time.Now().Add(500 * time.Millisecond) 214 for time.Now().Before(end) { 215 if _, err := ks.SignHash(accounts.Account{Address: a1.Address}, testSigData); err == ErrLocked { 216 return 217 } else if err != nil { 218 t.Errorf("Sign error: %v", err) 219 return 220 } 221 time.Sleep(1 * time.Millisecond) 222 } 223 t.Errorf("Account did not lock within the timeout") 224 } 225 226 //测试钱包通知循环是否根据 227 //钱包事件订阅的添加和删除。 228 func TestWalletNotifierLifecycle(t *testing.T) { 229 //创建要测试的临时Kesytore 230 dir, ks := tmpKeyStore(t, false) 231 defer os.RemoveAll(dir) 232 233 //确保通知更新程序尚未运行 234 time.Sleep(250 * time.Millisecond) 235 ks.mu.RLock() 236 updating := ks.updating 237 ks.mu.RUnlock() 238 239 if updating { 240 t.Errorf("wallet notifier running without subscribers") 241 } 242 //订阅Wallet Feed并确保更新程序启动 243 updates := make(chan accounts.WalletEvent) 244 245 subs := make([]event.Subscription, 2) 246 for i := 0; i < len(subs); i++ { 247 //创建新订阅 248 subs[i] = ks.Subscribe(updates) 249 250 //确保通知程序联机 251 time.Sleep(250 * time.Millisecond) 252 ks.mu.RLock() 253 updating = ks.updating 254 ks.mu.RUnlock() 255 256 if !updating { 257 t.Errorf("sub %d: wallet notifier not running after subscription", i) 258 } 259 } 260 //取消订阅并确保更新程序最终终止 261 for i := 0; i < len(subs); i++ { 262 //关闭现有订阅 263 subs[i].Unsubscribe() 264 265 //确保通知程序仅在最后一次关闭时关闭。 266 for k := 0; k < int(walletRefreshCycle/(250*time.Millisecond))+2; k++ { 267 ks.mu.RLock() 268 updating = ks.updating 269 ks.mu.RUnlock() 270 271 if i < len(subs)-1 && !updating { 272 t.Fatalf("sub %d: event notifier stopped prematurely", i) 273 } 274 if i == len(subs)-1 && !updating { 275 return 276 } 277 time.Sleep(250 * time.Millisecond) 278 } 279 } 280 t.Errorf("wallet notifier didn't terminate after unsubscribe") 281 } 282 283 type walletEvent struct { 284 accounts.WalletEvent 285 a accounts.Account 286 } 287 288 //测试钱包通知并在添加帐户时正确触发 289 //或者从密钥库中删除。 290 func TestWalletNotifications(t *testing.T) { 291 dir, ks := tmpKeyStore(t, false) 292 defer os.RemoveAll(dir) 293 294 //订阅钱包订阅和收集活动。 295 var ( 296 events []walletEvent 297 updates = make(chan accounts.WalletEvent) 298 sub = ks.Subscribe(updates) 299 ) 300 defer sub.Unsubscribe() 301 go func() { 302 for { 303 select { 304 case ev := <-updates: 305 events = append(events, walletEvent{ev, ev.Wallet.Accounts()[0]}) 306 case <-sub.Err(): 307 close(updates) 308 return 309 } 310 } 311 }() 312 313 //随机添加和删除帐户。 314 var ( 315 live = make(map[common.Address]accounts.Account) 316 wantEvents []walletEvent 317 ) 318 for i := 0; i < 1024; i++ { 319 if create := len(live) == 0 || rand.Int()%4 > 0; create { 320 //添加新帐户并确保收到钱包通知 321 account, err := ks.NewAccount("") 322 if err != nil { 323 t.Fatalf("failed to create test account: %v", err) 324 } 325 live[account.Address] = account 326 wantEvents = append(wantEvents, walletEvent{accounts.WalletEvent{Kind: accounts.WalletArrived}, account}) 327 } else { 328 //删除随机帐户。 329 var account accounts.Account 330 for _, a := range live { 331 account = a 332 break 333 } 334 if err := ks.Delete(account, ""); err != nil { 335 t.Fatalf("failed to delete test account: %v", err) 336 } 337 delete(live, account.Address) 338 wantEvents = append(wantEvents, walletEvent{accounts.WalletEvent{Kind: accounts.WalletDropped}, account}) 339 } 340 } 341 342 //关闭事件收集器并检查事件。 343 sub.Unsubscribe() 344 <-updates 345 checkAccounts(t, live, ks.Wallets()) 346 checkEvents(t, wantEvents, events) 347 } 348 349 //支票帐户检查钱包列表中是否存在所有已知的实时帐户。 350 func checkAccounts(t *testing.T, live map[common.Address]accounts.Account, wallets []accounts.Wallet) { 351 if len(live) != len(wallets) { 352 t.Errorf("wallet list doesn't match required accounts: have %d, want %d", len(wallets), len(live)) 353 return 354 } 355 liveList := make([]accounts.Account, 0, len(live)) 356 for _, account := range live { 357 liveList = append(liveList, account) 358 } 359 sort.Sort(accountsByURL(liveList)) 360 for j, wallet := range wallets { 361 if accs := wallet.Accounts(); len(accs) != 1 { 362 t.Errorf("wallet %d: contains invalid number of accounts: have %d, want 1", j, len(accs)) 363 } else if accs[0] != liveList[j] { 364 t.Errorf("wallet %d: account mismatch: have %v, want %v", j, accs[0], liveList[j]) 365 } 366 } 367 } 368 369 //checkevents检查“want”中的所有事件是否都存在于“have”中。事件可能出现多次。 370 func checkEvents(t *testing.T, want []walletEvent, have []walletEvent) { 371 for _, wantEv := range want { 372 nmatch := 0 373 for ; len(have) > 0; nmatch++ { 374 if have[0].Kind != wantEv.Kind || have[0].a != wantEv.a { 375 break 376 } 377 have = have[1:] 378 } 379 if nmatch == 0 { 380 t.Fatalf("can't find event with Kind=%v for %x", wantEv.Kind, wantEv.a.Address) 381 } 382 } 383 } 384 385 func tmpKeyStore(t *testing.T, encrypted bool) (string, *KeyStore) { 386 d, err := ioutil.TempDir("", "eth-keystore-test") 387 if err != nil { 388 t.Fatal(err) 389 } 390 new := NewPlaintextKeyStore 391 if encrypted { 392 new = func(kd string) *KeyStore { return NewKeyStore(kd, veryLightScryptN, veryLightScryptP) } 393 } 394 return d, new(d) 395 }