accountcmd_test.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. // Copyright 2016 The go-ethereum Authors
  2. // This file is part of go-ethereum.
  3. //
  4. // go-ethereum is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU 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. // go-ethereum 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 General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
  16. package main
  17. import (
  18. "io/ioutil"
  19. "path/filepath"
  20. "runtime"
  21. "strings"
  22. "testing"
  23. "github.com/cespare/cp"
  24. )
  25. // These tests are 'smoke tests' for the account related
  26. // subcommands and flags.
  27. //
  28. // For most tests, the test files from package accounts
  29. // are copied into a temporary keystore directory.
  30. func tmpDatadirWithKeystore(t *testing.T) string {
  31. datadir := tmpdir(t)
  32. keystore := filepath.Join(datadir, "keystore")
  33. source := filepath.Join("..", "..", "accounts", "keystore", "testdata", "keystore")
  34. if err := cp.CopyAll(keystore, source); err != nil {
  35. t.Fatal(err)
  36. }
  37. return datadir
  38. }
  39. func TestAccountListEmpty(t *testing.T) {
  40. geth := runGeth(t, "account", "list")
  41. geth.ExpectExit()
  42. }
  43. func TestAccountList(t *testing.T) {
  44. datadir := tmpDatadirWithKeystore(t)
  45. geth := runGeth(t, "account", "list", "--datadir", datadir)
  46. defer geth.ExpectExit()
  47. if runtime.GOOS == "windows" {
  48. geth.Expect(`
  49. Account #0: {7ef5a6135f1fd6a02593eedc869c6d41d934aef8} keystore://{{.Datadir}}\keystore\UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8
  50. Account #1: {f466859ead1932d743d622cb74fc058882e8648a} keystore://{{.Datadir}}\keystore\aaa
  51. Account #2: {289d485d9771714cce91d3393d764e1311907acc} keystore://{{.Datadir}}\keystore\zzz
  52. `)
  53. } else {
  54. geth.Expect(`
  55. Account #0: {7ef5a6135f1fd6a02593eedc869c6d41d934aef8} keystore://{{.Datadir}}/keystore/UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8
  56. Account #1: {f466859ead1932d743d622cb74fc058882e8648a} keystore://{{.Datadir}}/keystore/aaa
  57. Account #2: {289d485d9771714cce91d3393d764e1311907acc} keystore://{{.Datadir}}/keystore/zzz
  58. `)
  59. }
  60. }
  61. func TestAccountNew(t *testing.T) {
  62. geth := runGeth(t, "account", "new", "--lightkdf")
  63. defer geth.ExpectExit()
  64. geth.Expect(`
  65. Your new account is locked with a password. Please give a password. Do not forget this password.
  66. !! Unsupported terminal, password will be echoed.
  67. Password: {{.InputLine "foobar"}}
  68. Repeat password: {{.InputLine "foobar"}}
  69. Your new key was generated
  70. `)
  71. geth.ExpectRegexp(`
  72. Public address of the key: 0x[0-9a-fA-F]{40}
  73. Path of the secret key file: .*UTC--.+--[0-9a-f]{40}
  74. - You can share your public address with anyone. Others need it to interact with you.
  75. - You must NEVER share the secret key with anyone! The key controls access to your funds!
  76. - You must BACKUP your key file! Without the key, it's impossible to access account funds!
  77. - You must REMEMBER your password! Without the password, it's impossible to decrypt the key!
  78. `)
  79. }
  80. func TestAccountImport(t *testing.T) {
  81. tests := []struct{ name, key, output string }{
  82. {
  83. name: "correct account",
  84. key: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
  85. output: "Address: {fcad0b19bb29d4674531d6f115237e16afce377c}\n",
  86. },
  87. {
  88. name: "invalid character",
  89. key: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef1",
  90. output: "Fatal: Failed to load the private key: invalid character '1' at end of key file\n",
  91. },
  92. }
  93. for _, test := range tests {
  94. test := test
  95. t.Run(test.name, func(t *testing.T) {
  96. t.Parallel()
  97. importAccountWithExpect(t, test.key, test.output)
  98. })
  99. }
  100. }
  101. func importAccountWithExpect(t *testing.T, key string, expected string) {
  102. dir := tmpdir(t)
  103. keyfile := filepath.Join(dir, "key.prv")
  104. if err := ioutil.WriteFile(keyfile, []byte(key), 0600); err != nil {
  105. t.Error(err)
  106. }
  107. passwordFile := filepath.Join(dir, "password.txt")
  108. if err := ioutil.WriteFile(passwordFile, []byte("foobar"), 0600); err != nil {
  109. t.Error(err)
  110. }
  111. geth := runGeth(t, "account", "import", keyfile, "-password", passwordFile)
  112. defer geth.ExpectExit()
  113. geth.Expect(expected)
  114. }
  115. func TestAccountNewBadRepeat(t *testing.T) {
  116. geth := runGeth(t, "account", "new", "--lightkdf")
  117. defer geth.ExpectExit()
  118. geth.Expect(`
  119. Your new account is locked with a password. Please give a password. Do not forget this password.
  120. !! Unsupported terminal, password will be echoed.
  121. Password: {{.InputLine "something"}}
  122. Repeat password: {{.InputLine "something else"}}
  123. Fatal: Passwords do not match
  124. `)
  125. }
  126. func TestAccountUpdate(t *testing.T) {
  127. datadir := tmpDatadirWithKeystore(t)
  128. geth := runGeth(t, "account", "update",
  129. "--datadir", datadir, "--lightkdf",
  130. "f466859ead1932d743d622cb74fc058882e8648a")
  131. defer geth.ExpectExit()
  132. geth.Expect(`
  133. Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3
  134. !! Unsupported terminal, password will be echoed.
  135. Password: {{.InputLine "foobar"}}
  136. Please give a new password. Do not forget this password.
  137. Password: {{.InputLine "foobar2"}}
  138. Repeat password: {{.InputLine "foobar2"}}
  139. `)
  140. }
  141. func TestWalletImport(t *testing.T) {
  142. geth := runGeth(t, "wallet", "import", "--lightkdf", "testdata/guswallet.json")
  143. defer geth.ExpectExit()
  144. geth.Expect(`
  145. !! Unsupported terminal, password will be echoed.
  146. Password: {{.InputLine "foo"}}
  147. Address: {d4584b5f6229b7be90727b0fc8c6b91bb427821f}
  148. `)
  149. files, err := ioutil.ReadDir(filepath.Join(geth.Datadir, "keystore"))
  150. if len(files) != 1 {
  151. t.Errorf("expected one key file in keystore directory, found %d files (error: %v)", len(files), err)
  152. }
  153. }
  154. func TestWalletImportBadPassword(t *testing.T) {
  155. geth := runGeth(t, "wallet", "import", "--lightkdf", "testdata/guswallet.json")
  156. defer geth.ExpectExit()
  157. geth.Expect(`
  158. !! Unsupported terminal, password will be echoed.
  159. Password: {{.InputLine "wrong"}}
  160. Fatal: could not decrypt key with given password
  161. `)
  162. }
  163. func TestUnlockFlag(t *testing.T) {
  164. geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
  165. "--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "js", "testdata/empty.js")
  166. geth.Expect(`
  167. Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3
  168. !! Unsupported terminal, password will be echoed.
  169. Password: {{.InputLine "foobar"}}
  170. `)
  171. geth.ExpectExit()
  172. wantMessages := []string{
  173. "Unlocked account",
  174. "=0xf466859eAD1932D743d622CB74FC058882E8648A",
  175. }
  176. for _, m := range wantMessages {
  177. if !strings.Contains(geth.StderrText(), m) {
  178. t.Errorf("stderr text does not contain %q", m)
  179. }
  180. }
  181. }
  182. func TestUnlockFlagWrongPassword(t *testing.T) {
  183. geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
  184. "--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "js", "testdata/empty.js")
  185. defer geth.ExpectExit()
  186. geth.Expect(`
  187. Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3
  188. !! Unsupported terminal, password will be echoed.
  189. Password: {{.InputLine "wrong1"}}
  190. Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 2/3
  191. Password: {{.InputLine "wrong2"}}
  192. Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 3/3
  193. Password: {{.InputLine "wrong3"}}
  194. Fatal: Failed to unlock account f466859ead1932d743d622cb74fc058882e8648a (could not decrypt key with given password)
  195. `)
  196. }
  197. // https://github.com/ethereum/go-ethereum/issues/1785
  198. func TestUnlockFlagMultiIndex(t *testing.T) {
  199. geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
  200. "--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "--unlock", "0,2", "js", "testdata/empty.js")
  201. geth.Expect(`
  202. Unlocking account 0 | Attempt 1/3
  203. !! Unsupported terminal, password will be echoed.
  204. Password: {{.InputLine "foobar"}}
  205. Unlocking account 2 | Attempt 1/3
  206. Password: {{.InputLine "foobar"}}
  207. `)
  208. geth.ExpectExit()
  209. wantMessages := []string{
  210. "Unlocked account",
  211. "=0x7EF5A6135f1FD6a02593eEdC869c6D41D934aef8",
  212. "=0x289d485D9771714CCe91D3393D764E1311907ACc",
  213. }
  214. for _, m := range wantMessages {
  215. if !strings.Contains(geth.StderrText(), m) {
  216. t.Errorf("stderr text does not contain %q", m)
  217. }
  218. }
  219. }
  220. func TestUnlockFlagPasswordFile(t *testing.T) {
  221. geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
  222. "--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "--password", "testdata/passwords.txt", "--unlock", "0,2", "js", "testdata/empty.js")
  223. geth.ExpectExit()
  224. wantMessages := []string{
  225. "Unlocked account",
  226. "=0x7EF5A6135f1FD6a02593eEdC869c6D41D934aef8",
  227. "=0x289d485D9771714CCe91D3393D764E1311907ACc",
  228. }
  229. for _, m := range wantMessages {
  230. if !strings.Contains(geth.StderrText(), m) {
  231. t.Errorf("stderr text does not contain %q", m)
  232. }
  233. }
  234. }
  235. func TestUnlockFlagPasswordFileWrongPassword(t *testing.T) {
  236. geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
  237. "--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "--password",
  238. "testdata/wrong-passwords.txt", "--unlock", "0,2")
  239. defer geth.ExpectExit()
  240. geth.Expect(`
  241. Fatal: Failed to unlock account 0 (could not decrypt key with given password)
  242. `)
  243. }
  244. func TestUnlockFlagAmbiguous(t *testing.T) {
  245. store := filepath.Join("..", "..", "accounts", "keystore", "testdata", "dupes")
  246. geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
  247. "--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "--keystore",
  248. store, "--unlock", "f466859ead1932d743d622cb74fc058882e8648a",
  249. "js", "testdata/empty.js")
  250. defer geth.ExpectExit()
  251. // Helper for the expect template, returns absolute keystore path.
  252. geth.SetTemplateFunc("keypath", func(file string) string {
  253. abs, _ := filepath.Abs(filepath.Join(store, file))
  254. return abs
  255. })
  256. geth.Expect(`
  257. Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3
  258. !! Unsupported terminal, password will be echoed.
  259. Password: {{.InputLine "foobar"}}
  260. Multiple key files exist for address f466859ead1932d743d622cb74fc058882e8648a:
  261. keystore://{{keypath "1"}}
  262. keystore://{{keypath "2"}}
  263. Testing your password against all of them...
  264. Your password unlocked keystore://{{keypath "1"}}
  265. In order to avoid this warning, you need to remove the following duplicate key files:
  266. keystore://{{keypath "2"}}
  267. `)
  268. geth.ExpectExit()
  269. wantMessages := []string{
  270. "Unlocked account",
  271. "=0xf466859eAD1932D743d622CB74FC058882E8648A",
  272. }
  273. for _, m := range wantMessages {
  274. if !strings.Contains(geth.StderrText(), m) {
  275. t.Errorf("stderr text does not contain %q", m)
  276. }
  277. }
  278. }
  279. func TestUnlockFlagAmbiguousWrongPassword(t *testing.T) {
  280. store := filepath.Join("..", "..", "accounts", "keystore", "testdata", "dupes")
  281. geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
  282. "--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "--keystore",
  283. store, "--unlock", "f466859ead1932d743d622cb74fc058882e8648a")
  284. defer geth.ExpectExit()
  285. // Helper for the expect template, returns absolute keystore path.
  286. geth.SetTemplateFunc("keypath", func(file string) string {
  287. abs, _ := filepath.Abs(filepath.Join(store, file))
  288. return abs
  289. })
  290. geth.Expect(`
  291. Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3
  292. !! Unsupported terminal, password will be echoed.
  293. Password: {{.InputLine "wrong"}}
  294. Multiple key files exist for address f466859ead1932d743d622cb74fc058882e8648a:
  295. keystore://{{keypath "1"}}
  296. keystore://{{keypath "2"}}
  297. Testing your password against all of them...
  298. Fatal: None of the listed files could be unlocked.
  299. `)
  300. geth.ExpectExit()
  301. }