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