github.com/murrekatt/go-ethereum@v1.5.8-0.20170123175102-fc52f2c007fb/accounts/accounts_test.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package accounts 18 19 import ( 20 "io/ioutil" 21 "os" 22 "runtime" 23 "strings" 24 "testing" 25 "time" 26 27 "github.com/ethereum/go-ethereum/common" 28 ) 29 30 var testSigData = make([]byte, 32) 31 32 func TestManager(t *testing.T) { 33 dir, am := tmpManager(t, true) 34 defer os.RemoveAll(dir) 35 36 a, err := am.NewAccount("foo") 37 if err != nil { 38 t.Fatal(err) 39 } 40 if !strings.HasPrefix(a.File, dir) { 41 t.Errorf("account file %s doesn't have dir prefix", a.File) 42 } 43 stat, err := os.Stat(a.File) 44 if err != nil { 45 t.Fatalf("account file %s doesn't exist (%v)", a.File, 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 !am.HasAddress(a.Address) { 51 t.Errorf("HasAccount(%x) should've returned true", a.Address) 52 } 53 if err := am.Update(a, "foo", "bar"); err != nil { 54 t.Errorf("Update error: %v", err) 55 } 56 if err := am.Delete(a, "bar"); err != nil { 57 t.Errorf("Delete error: %v", err) 58 } 59 if common.FileExist(a.File) { 60 t.Errorf("account file %s should be gone after Delete", a.File) 61 } 62 if am.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, am := tmpManager(t, true) 69 defer os.RemoveAll(dir) 70 71 pass := "" // not used but required by API 72 a1, err := am.NewAccount(pass) 73 if err != nil { 74 t.Fatal(err) 75 } 76 if err := am.Unlock(a1, ""); err != nil { 77 t.Fatal(err) 78 } 79 if _, err := am.Sign(a1.Address, testSigData); err != nil { 80 t.Fatal(err) 81 } 82 } 83 84 func TestSignWithPassphrase(t *testing.T) { 85 dir, am := tmpManager(t, true) 86 defer os.RemoveAll(dir) 87 88 pass := "passwd" 89 acc, err := am.NewAccount(pass) 90 if err != nil { 91 t.Fatal(err) 92 } 93 94 if _, unlocked := am.unlocked[acc.Address]; unlocked { 95 t.Fatal("expected account to be locked") 96 } 97 98 _, err = am.SignWithPassphrase(acc, pass, testSigData) 99 if err != nil { 100 t.Fatal(err) 101 } 102 103 if _, unlocked := am.unlocked[acc.Address]; unlocked { 104 t.Fatal("expected account to be locked") 105 } 106 107 if _, err = am.SignWithPassphrase(acc, "invalid passwd", testSigData); err == nil { 108 t.Fatal("expected SignHash to fail with invalid password") 109 } 110 } 111 112 func TestTimedUnlock(t *testing.T) { 113 dir, am := tmpManager(t, true) 114 defer os.RemoveAll(dir) 115 116 pass := "foo" 117 a1, err := am.NewAccount(pass) 118 if err != nil { 119 t.Fatal(err) 120 } 121 122 // Signing without passphrase fails because account is locked 123 _, err = am.Sign(a1.Address, testSigData) 124 if err != ErrLocked { 125 t.Fatal("Signing should've failed with ErrLocked before unlocking, got ", err) 126 } 127 128 // Signing with passphrase works 129 if err = am.TimedUnlock(a1, pass, 100*time.Millisecond); err != nil { 130 t.Fatal(err) 131 } 132 133 // Signing without passphrase works because account is temp unlocked 134 _, err = am.Sign(a1.Address, testSigData) 135 if err != nil { 136 t.Fatal("Signing shouldn't return an error after unlocking, got ", err) 137 } 138 139 // Signing fails again after automatic locking 140 time.Sleep(250 * time.Millisecond) 141 _, err = am.Sign(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, am := tmpManager(t, false) 149 defer os.RemoveAll(dir) 150 151 pass := "foo" 152 a1, err := am.NewAccount(pass) 153 if err != nil { 154 t.Fatal(err) 155 } 156 157 // Unlock indefinitely. 158 if err = am.TimedUnlock(a1, pass, 5*time.Minute); err != nil { 159 t.Fatal(err) 160 } 161 162 // Signing without passphrase works because account is temp unlocked 163 _, err = am.Sign(a1.Address, testSigData) 164 if err != nil { 165 t.Fatal("Signing shouldn't return an error after unlocking, got ", err) 166 } 167 168 // reset unlock to a shorter period, invalidates the previous unlock 169 if err = am.TimedUnlock(a1, pass, 100*time.Millisecond); err != nil { 170 t.Fatal(err) 171 } 172 173 // Signing without passphrase still works because account is temp unlocked 174 _, err = am.Sign(a1.Address, testSigData) 175 if err != nil { 176 t.Fatal("Signing shouldn't return an error after unlocking, got ", err) 177 } 178 179 // Signing fails again after automatic locking 180 time.Sleep(250 * time.Millisecond) 181 _, err = am.Sign(a1.Address, testSigData) 182 if err != ErrLocked { 183 t.Fatal("Signing should've failed with ErrLocked timeout expired, got ", err) 184 } 185 } 186 187 // This test should fail under -race if signing races the expiration goroutine. 188 func TestSignRace(t *testing.T) { 189 dir, am := tmpManager(t, false) 190 defer os.RemoveAll(dir) 191 192 // Create a test account. 193 a1, err := am.NewAccount("") 194 if err != nil { 195 t.Fatal("could not create the test account", err) 196 } 197 198 if err := am.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 := am.Sign(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 func tmpManager(t *testing.T, encrypted bool) (string, *Manager) { 215 d, err := ioutil.TempDir("", "eth-keystore-test") 216 if err != nil { 217 t.Fatal(err) 218 } 219 new := NewPlaintextManager 220 if encrypted { 221 new = func(kd string) *Manager { return NewManager(kd, veryLightScryptN, veryLightScryptP) } 222 } 223 return d, new(d) 224 }