github.com/bcnmy/go-ethereum@v1.10.27/cmd/geth/accountcmd_test.go (about)

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