accountcmd_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  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{ key, output string }{
  82. {
  83. key: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
  84. output: "Address: {fcad0b19bb29d4674531d6f115237e16afce377c}\n",
  85. },
  86. {
  87. key: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef1",
  88. output: "Fatal: Failed to load the private key: invalid character '1' at end of key file\n",
  89. },
  90. }
  91. for _, test := range tests {
  92. importAccountWithExpect(t, test.key, test.output)
  93. }
  94. }
  95. func importAccountWithExpect(t *testing.T, key string, expected string) {
  96. dir := tmpdir(t)
  97. keyfile := filepath.Join(dir, "key.prv")
  98. if err := ioutil.WriteFile(keyfile, []byte(key), 0600); err != nil {
  99. t.Error(err)
  100. }
  101. passwordFile := filepath.Join(dir, "password.txt")
  102. if err := ioutil.WriteFile(passwordFile, []byte("foobar"), 0600); err != nil {
  103. t.Error(err)
  104. }
  105. geth := runGeth(t, "account", "import", keyfile, "-password", passwordFile)
  106. defer geth.ExpectExit()
  107. geth.Expect(expected)
  108. }
  109. func TestAccountNewBadRepeat(t *testing.T) {
  110. geth := runGeth(t, "account", "new", "--lightkdf")
  111. defer geth.ExpectExit()
  112. geth.Expect(`
  113. Your new account is locked with a password. Please give a password. Do not forget this password.
  114. !! Unsupported terminal, password will be echoed.
  115. Password: {{.InputLine "something"}}
  116. Repeat password: {{.InputLine "something else"}}
  117. Fatal: Passwords do not match
  118. `)
  119. }
  120. func TestAccountUpdate(t *testing.T) {
  121. datadir := tmpDatadirWithKeystore(t)
  122. geth := runGeth(t, "account", "update",
  123. "--datadir", datadir, "--lightkdf",
  124. "f466859ead1932d743d622cb74fc058882e8648a")
  125. defer geth.ExpectExit()
  126. geth.Expect(`
  127. Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3
  128. !! Unsupported terminal, password will be echoed.
  129. Password: {{.InputLine "foobar"}}
  130. Please give a new password. Do not forget this password.
  131. Password: {{.InputLine "foobar2"}}
  132. Repeat password: {{.InputLine "foobar2"}}
  133. `)
  134. }
  135. func TestWalletImport(t *testing.T) {
  136. geth := runGeth(t, "wallet", "import", "--lightkdf", "testdata/guswallet.json")
  137. defer geth.ExpectExit()
  138. geth.Expect(`
  139. !! Unsupported terminal, password will be echoed.
  140. Password: {{.InputLine "foo"}}
  141. Address: {d4584b5f6229b7be90727b0fc8c6b91bb427821f}
  142. `)
  143. files, err := ioutil.ReadDir(filepath.Join(geth.Datadir, "keystore"))
  144. if len(files) != 1 {
  145. t.Errorf("expected one key file in keystore directory, found %d files (error: %v)", len(files), err)
  146. }
  147. }
  148. func TestWalletImportBadPassword(t *testing.T) {
  149. geth := runGeth(t, "wallet", "import", "--lightkdf", "testdata/guswallet.json")
  150. defer geth.ExpectExit()
  151. geth.Expect(`
  152. !! Unsupported terminal, password will be echoed.
  153. Password: {{.InputLine "wrong"}}
  154. Fatal: could not decrypt key with given password
  155. `)
  156. }
  157. func TestUnlockFlag(t *testing.T) {
  158. datadir := tmpDatadirWithKeystore(t)
  159. geth := runGeth(t,
  160. "--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0",
  161. "--unlock", "f466859ead1932d743d622cb74fc058882e8648a",
  162. "js", "testdata/empty.js")
  163. geth.Expect(`
  164. Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3
  165. !! Unsupported terminal, password will be echoed.
  166. Password: {{.InputLine "foobar"}}
  167. `)
  168. geth.ExpectExit()
  169. wantMessages := []string{
  170. "Unlocked account",
  171. "=0xf466859eAD1932D743d622CB74FC058882E8648A",
  172. }
  173. for _, m := range wantMessages {
  174. if !strings.Contains(geth.StderrText(), m) {
  175. t.Errorf("stderr text does not contain %q", m)
  176. }
  177. }
  178. }
  179. func TestUnlockFlagWrongPassword(t *testing.T) {
  180. datadir := tmpDatadirWithKeystore(t)
  181. geth := runGeth(t,
  182. "--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0",
  183. "--unlock", "f466859ead1932d743d622cb74fc058882e8648a")
  184. defer geth.ExpectExit()
  185. geth.Expect(`
  186. Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3
  187. !! Unsupported terminal, password will be echoed.
  188. Password: {{.InputLine "wrong1"}}
  189. Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 2/3
  190. Password: {{.InputLine "wrong2"}}
  191. Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 3/3
  192. Password: {{.InputLine "wrong3"}}
  193. Fatal: Failed to unlock account f466859ead1932d743d622cb74fc058882e8648a (could not decrypt key with given password)
  194. `)
  195. }
  196. // https://github.com/ethereum/go-ethereum/issues/1785
  197. func TestUnlockFlagMultiIndex(t *testing.T) {
  198. datadir := tmpDatadirWithKeystore(t)
  199. geth := runGeth(t,
  200. "--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0",
  201. "--unlock", "0,2",
  202. "js", "testdata/empty.js")
  203. geth.Expect(`
  204. Unlocking account 0 | Attempt 1/3
  205. !! Unsupported terminal, password will be echoed.
  206. Password: {{.InputLine "foobar"}}
  207. Unlocking account 2 | Attempt 1/3
  208. Password: {{.InputLine "foobar"}}
  209. `)
  210. geth.ExpectExit()
  211. wantMessages := []string{
  212. "Unlocked account",
  213. "=0x7EF5A6135f1FD6a02593eEdC869c6D41D934aef8",
  214. "=0x289d485D9771714CCe91D3393D764E1311907ACc",
  215. }
  216. for _, m := range wantMessages {
  217. if !strings.Contains(geth.StderrText(), m) {
  218. t.Errorf("stderr text does not contain %q", m)
  219. }
  220. }
  221. }
  222. func TestUnlockFlagPasswordFile(t *testing.T) {
  223. datadir := tmpDatadirWithKeystore(t)
  224. geth := runGeth(t,
  225. "--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0",
  226. "--password", "testdata/passwords.txt", "--unlock", "0,2",
  227. "js", "testdata/empty.js")
  228. geth.ExpectExit()
  229. wantMessages := []string{
  230. "Unlocked account",
  231. "=0x7EF5A6135f1FD6a02593eEdC869c6D41D934aef8",
  232. "=0x289d485D9771714CCe91D3393D764E1311907ACc",
  233. }
  234. for _, m := range wantMessages {
  235. if !strings.Contains(geth.StderrText(), m) {
  236. t.Errorf("stderr text does not contain %q", m)
  237. }
  238. }
  239. }
  240. func TestUnlockFlagPasswordFileWrongPassword(t *testing.T) {
  241. datadir := tmpDatadirWithKeystore(t)
  242. geth := runGeth(t,
  243. "--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0",
  244. "--password", "testdata/wrong-passwords.txt", "--unlock", "0,2")
  245. defer geth.ExpectExit()
  246. geth.Expect(`
  247. Fatal: Failed to unlock account 0 (could not decrypt key with given password)
  248. `)
  249. }
  250. func TestUnlockFlagAmbiguous(t *testing.T) {
  251. store := filepath.Join("..", "..", "accounts", "keystore", "testdata", "dupes")
  252. geth := runGeth(t,
  253. "--keystore", store, "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0",
  254. "--unlock", "f466859ead1932d743d622cb74fc058882e8648a",
  255. "js", "testdata/empty.js")
  256. defer geth.ExpectExit()
  257. // Helper for the expect template, returns absolute keystore path.
  258. geth.SetTemplateFunc("keypath", func(file string) string {
  259. abs, _ := filepath.Abs(filepath.Join(store, file))
  260. return abs
  261. })
  262. geth.Expect(`
  263. Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3
  264. !! Unsupported terminal, password will be echoed.
  265. Password: {{.InputLine "foobar"}}
  266. Multiple key files exist for address f466859ead1932d743d622cb74fc058882e8648a:
  267. keystore://{{keypath "1"}}
  268. keystore://{{keypath "2"}}
  269. Testing your password against all of them...
  270. Your password unlocked keystore://{{keypath "1"}}
  271. In order to avoid this warning, you need to remove the following duplicate key files:
  272. keystore://{{keypath "2"}}
  273. `)
  274. geth.ExpectExit()
  275. wantMessages := []string{
  276. "Unlocked account",
  277. "=0xf466859eAD1932D743d622CB74FC058882E8648A",
  278. }
  279. for _, m := range wantMessages {
  280. if !strings.Contains(geth.StderrText(), m) {
  281. t.Errorf("stderr text does not contain %q", m)
  282. }
  283. }
  284. }
  285. func TestUnlockFlagAmbiguousWrongPassword(t *testing.T) {
  286. store := filepath.Join("..", "..", "accounts", "keystore", "testdata", "dupes")
  287. geth := runGeth(t,
  288. "--keystore", store, "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0",
  289. "--unlock", "f466859ead1932d743d622cb74fc058882e8648a")
  290. defer geth.ExpectExit()
  291. // Helper for the expect template, returns absolute keystore path.
  292. geth.SetTemplateFunc("keypath", func(file string) string {
  293. abs, _ := filepath.Abs(filepath.Join(store, file))
  294. return abs
  295. })
  296. geth.Expect(`
  297. Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3
  298. !! Unsupported terminal, password will be echoed.
  299. Password: {{.InputLine "wrong"}}
  300. Multiple key files exist for address f466859ead1932d743d622cb74fc058882e8648a:
  301. keystore://{{keypath "1"}}
  302. keystore://{{keypath "2"}}
  303. Testing your password against all of them...
  304. Fatal: None of the listed files could be unlocked.
  305. `)
  306. geth.ExpectExit()
  307. }