github.com/theQRL/go-zond@v0.2.1/cmd/gzond/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  	gzond := runGzond(t, "account", "list")
    47  	gzond.ExpectExit()
    48  }
    49  
    50  func TestAccountList(t *testing.T) {
    51  	datadir := tmpDatadirWithKeystore(t)
    52  	var want = `
    53  Account #0: {Z2099d76d9a34cdd2694c4dc703930a6fbbc1d402} keystore://{{.Datadir}}/keystore/UTC--2024-05-27T07-48-33.872599000Z--Z2099d76d9a34cdd2694c4dc703930a6fbbc1d402
    54  Account #1: {Z205547ba6232eec096770f7161d57dea54fd13d0} keystore://{{.Datadir}}/keystore/aaa
    55  Account #2: {Z206f5f53d348954856a6d2cde75ad6381945fb46} keystore://{{.Datadir}}/keystore/zzz
    56  `
    57  	if runtime.GOOS == "windows" {
    58  		want = `
    59  Account #0: {Z2099d76d9a34cdd2694c4dc703930a6fbbc1d402} keystore://{{.Datadir}}\keystore\UTC--2024-05-27T07-48-33.872599000Z--Z2099d76d9a34cdd2694c4dc703930a6fbbc1d402
    60  Account #1: {Z205547ba6232eec096770f7161d57dea54fd13d0} keystore://{{.Datadir}}\keystore\aaa
    61  Account #2: {Z206f5f53d348954856a6d2cde75ad6381945fb46} keystore://{{.Datadir}}\keystore\zzz
    62  `
    63  	}
    64  	{
    65  		gzond := runGzond(t, "account", "list", "--datadir", datadir)
    66  		gzond.Expect(want)
    67  		gzond.ExpectExit()
    68  	}
    69  	{
    70  		gzond := runGzond(t, "--datadir", datadir, "account", "list")
    71  		gzond.Expect(want)
    72  		gzond.ExpectExit()
    73  	}
    74  }
    75  
    76  func TestAccountNew(t *testing.T) {
    77  	gzond := runGzond(t, "account", "new", "--lightkdf")
    78  	defer gzond.ExpectExit()
    79  	gzond.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  	gzond.ExpectRegexp(`
    88  Public address of the key:   Z[0-9a-fA-F]{40}
    89  Path of the secret key file: .*UTC--.+--Z[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, seed, output string }{
   100  		{
   101  			name:   "correct account",
   102  			seed:   "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdeffcad0b19bb29d4674531d6f115237e16",
   103  			output: "Address: {Z20b0ebf635349c8167daac7d7246b8e0d892926f}\n",
   104  		},
   105  		{
   106  			name:   "invalid character",
   107  			seed:   "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdeffcad0b19bb29d4674531d6f115237e161",
   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.seed, test.output)
   116  		})
   117  	}
   118  }
   119  
   120  func TestAccountHelp(t *testing.T) {
   121  	gzond := runGzond(t, "account", "-h")
   122  	gzond.WaitExit()
   123  	if have, want := gzond.ExitStatus(), 0; have != want {
   124  		t.Errorf("exit error, have %d want %d", have, want)
   125  	}
   126  
   127  	gzond = runGzond(t, "account", "import", "-h")
   128  	gzond.WaitExit()
   129  	if have, want := gzond.ExitStatus(), 0; have != want {
   130  		t.Errorf("exit error, have %d want %d", have, want)
   131  	}
   132  }
   133  
   134  func importAccountWithExpect(t *testing.T, seed string, expected string) {
   135  	dir := t.TempDir()
   136  	seedfile := filepath.Join(dir, "seed.txt")
   137  	if err := os.WriteFile(seedfile, []byte(seed), 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  	gzond := runGzond(t, "--lightkdf", "account", "import", "-password", passwordFile, seedfile)
   145  	defer gzond.ExpectExit()
   146  	gzond.Expect(expected)
   147  }
   148  
   149  func TestAccountNewBadRepeat(t *testing.T) {
   150  	gzond := runGzond(t, "account", "new", "--lightkdf")
   151  	defer gzond.ExpectExit()
   152  	gzond.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  	gzond := runGzond(t, "account", "update",
   164  		"--datadir", datadir, "--lightkdf",
   165  		"Z206f5f53d348954856a6d2cde75ad6381945fb46")
   166  	defer gzond.ExpectExit()
   167  	gzond.Expect(`
   168  Unlocking account Z206f5f53d348954856a6d2cde75ad6381945fb46 | Attempt 1/3
   169  !! Unsupported terminal, password will be echoed.
   170  Password: {{.InputLine "1234567890"}}
   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 TestUnlockFlag(t *testing.T) {
   178  	gzond := runMinimalGzond(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
   179  		"--unlock", "Z206f5f53d348954856a6d2cde75ad6381945fb46", "console", "--exec", "loadScript('testdata/empty.js')")
   180  	gzond.Expect(`
   181  Unlocking account Z206f5f53d348954856a6d2cde75ad6381945fb46 | Attempt 1/3
   182  !! Unsupported terminal, password will be echoed.
   183  Password: {{.InputLine "1234567890"}}
   184  undefined
   185  `)
   186  	gzond.ExpectExit()
   187  
   188  	wantMessages := []string{
   189  		"Unlocked account",
   190  		"=Z206f5f53D348954856a6D2cDe75Ad6381945fB46",
   191  	}
   192  	for _, m := range wantMessages {
   193  		if !strings.Contains(gzond.StderrText(), m) {
   194  			t.Errorf("stderr text does not contain %q", m)
   195  		}
   196  	}
   197  }
   198  
   199  func TestUnlockFlagWrongPassword(t *testing.T) {
   200  	gzond := runMinimalGzond(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
   201  		"--unlock", "Z205547ba6232eec096770f7161d57dea54fd13d0", "console", "--exec", "loadScript('testdata/empty.js')")
   202  
   203  	defer gzond.ExpectExit()
   204  	gzond.Expect(`
   205  Unlocking account Z205547ba6232eec096770f7161d57dea54fd13d0 | Attempt 1/3
   206  !! Unsupported terminal, password will be echoed.
   207  Password: {{.InputLine "wrong1"}}
   208  Unlocking account Z205547ba6232eec096770f7161d57dea54fd13d0 | Attempt 2/3
   209  Password: {{.InputLine "wrong2"}}
   210  Unlocking account Z205547ba6232eec096770f7161d57dea54fd13d0 | Attempt 3/3
   211  Password: {{.InputLine "wrong3"}}
   212  Fatal: Failed to unlock account Z205547ba6232eec096770f7161d57dea54fd13d0 (could not decrypt key with given password)
   213  `)
   214  }
   215  
   216  func TestUnlockFlagMultiIndex(t *testing.T) {
   217  	gzond := runMinimalGzond(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
   218  		"--unlock", "Z205547ba6232eec096770f7161d57dea54fd13d0", "--unlock", "0,2", "console", "--exec", "loadScript('testdata/empty.js')")
   219  
   220  	gzond.Expect(`
   221  Unlocking account 0 | Attempt 1/3
   222  !! Unsupported terminal, password will be echoed.
   223  Password: {{.InputLine "1234567890"}}
   224  Unlocking account 2 | Attempt 1/3
   225  Password: {{.InputLine "1234567890"}}
   226  undefined
   227  `)
   228  	gzond.ExpectExit()
   229  
   230  	wantMessages := []string{
   231  		"Unlocked account",
   232  		"=Z2099d76D9a34cDd2694c4DC703930A6fBbc1d402",
   233  		"=Z206f5f53D348954856a6D2cDe75Ad6381945fB46",
   234  	}
   235  	for _, m := range wantMessages {
   236  		if !strings.Contains(gzond.StderrText(), m) {
   237  			t.Errorf("stderr text does not contain %q", m)
   238  		}
   239  	}
   240  }
   241  
   242  func TestUnlockFlagPasswordFile(t *testing.T) {
   243  	gzond := runMinimalGzond(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
   244  		"--unlock", "Z205547ba6232eec096770f7161d57dea54fd13d0", "--password", "testdata/passwords.txt", "--unlock", "0,2", "console", "--exec", "loadScript('testdata/empty.js')")
   245  
   246  	gzond.Expect(`
   247  undefined
   248  `)
   249  	gzond.ExpectExit()
   250  
   251  	wantMessages := []string{
   252  		"Unlocked account",
   253  		"=Z2099d76D9a34cDd2694c4DC703930A6fBbc1d402",
   254  		"=Z206f5f53D348954856a6D2cDe75Ad6381945fB46",
   255  	}
   256  	for _, m := range wantMessages {
   257  		if !strings.Contains(gzond.StderrText(), m) {
   258  			t.Errorf("stderr text does not contain %q", m)
   259  		}
   260  	}
   261  }
   262  
   263  func TestUnlockFlagPasswordFileWrongPassword(t *testing.T) {
   264  	gzond := runMinimalGzond(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
   265  		"--unlock", "Z205547ba6232eec096770f7161d57dea54fd13d0", "--password",
   266  		"testdata/wrong-passwords.txt", "--unlock", "0,2")
   267  	defer gzond.ExpectExit()
   268  	gzond.Expect(`
   269  Fatal: Failed to unlock account 0 (could not decrypt key with given password)
   270  `)
   271  }
   272  
   273  func TestUnlockFlagAmbiguous(t *testing.T) {
   274  	store := filepath.Join("..", "..", "accounts", "keystore", "testdata", "dupes")
   275  	gzond := runMinimalGzond(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
   276  		"--unlock", "Z205547ba6232eec096770f7161d57dea54fd13d0", "--keystore",
   277  		store, "--unlock", "Z205547ba6232eec096770f7161d57dea54fd13d0",
   278  		"console", "--exec", "loadScript('testdata/empty.js')")
   279  	defer gzond.ExpectExit()
   280  
   281  	// Helper for the expect template, returns absolute keystore path.
   282  	gzond.SetTemplateFunc("keypath", func(file string) string {
   283  		abs, _ := filepath.Abs(filepath.Join(store, file))
   284  		return abs
   285  	})
   286  	gzond.Expect(`
   287  Unlocking account Z205547ba6232eec096770f7161d57dea54fd13d0 | Attempt 1/3
   288  !! Unsupported terminal, password will be echoed.
   289  Password: {{.InputLine ""}}
   290  Multiple key files exist for address Z205547ba6232eec096770f7161d57dea54fd13d0:
   291     keystore://{{keypath "1"}}
   292     keystore://{{keypath "2"}}
   293  Testing your password against all of them...
   294  Your password unlocked keystore://{{keypath "1"}}
   295  In order to avoid this warning, you need to remove the following duplicate key files:
   296     keystore://{{keypath "2"}}
   297  undefined
   298  `)
   299  	gzond.ExpectExit()
   300  
   301  	wantMessages := []string{
   302  		"Unlocked account",
   303  		"=Z205547bA6232eEc096770f7161d57dEA54FD13D0",
   304  	}
   305  	for _, m := range wantMessages {
   306  		if !strings.Contains(gzond.StderrText(), m) {
   307  			t.Errorf("stderr text does not contain %q", m)
   308  		}
   309  	}
   310  }
   311  
   312  func TestUnlockFlagAmbiguousWrongPassword(t *testing.T) {
   313  	store := filepath.Join("..", "..", "accounts", "keystore", "testdata", "dupes")
   314  	gzond := runMinimalGzond(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t),
   315  		"--unlock", "Z205547ba6232eec096770f7161d57dea54fd13d0", "--keystore",
   316  		store, "--unlock", "Z205547ba6232eec096770f7161d57dea54fd13d0")
   317  
   318  	defer gzond.ExpectExit()
   319  
   320  	// Helper for the expect template, returns absolute keystore path.
   321  	gzond.SetTemplateFunc("keypath", func(file string) string {
   322  		abs, _ := filepath.Abs(filepath.Join(store, file))
   323  		return abs
   324  	})
   325  	gzond.Expect(`
   326  Unlocking account Z205547ba6232eec096770f7161d57dea54fd13d0 | Attempt 1/3
   327  !! Unsupported terminal, password will be echoed.
   328  Password: {{.InputLine "wrong"}}
   329  Multiple key files exist for address Z205547ba6232eec096770f7161d57dea54fd13d0:
   330     keystore://{{keypath "1"}}
   331     keystore://{{keypath "2"}}
   332  Testing your password against all of them...
   333  Fatal: None of the listed files could be unlocked.
   334  `)
   335  	gzond.ExpectExit()
   336  }