github.com/reapchain/go-reapchain@v0.2.15-0.20210609012950-9735c110c705/cmd/geth/accountcmd.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 "fmt" 21 "io/ioutil" 22 23 "github.com/ethereum/go-ethereum/accounts" 24 "github.com/ethereum/go-ethereum/accounts/keystore" 25 "github.com/ethereum/go-ethereum/cmd/utils" 26 "github.com/ethereum/go-ethereum/console" 27 "github.com/ethereum/go-ethereum/crypto" 28 "github.com/ethereum/go-ethereum/log" 29 "gopkg.in/urfave/cli.v1" 30 ) 31 32 var ( 33 walletCommand = cli.Command{ 34 Name: "wallet", 35 Usage: "Manage Ethereum presale wallets", 36 ArgsUsage: "", 37 Category: "ACCOUNT COMMANDS", 38 Description: ` 39 geth wallet import /path/to/my/presale.wallet 40 41 will prompt for your password and imports your ether presale account. 42 It can be used non-interactively with the --password option taking a 43 passwordfile as argument containing the wallet password in plaintext.`, 44 Subcommands: []cli.Command{ 45 { 46 47 Name: "import", 48 Usage: "Import Ethereum presale wallet", 49 ArgsUsage: "<keyFile>", 50 Action: utils.MigrateFlags(importWallet), 51 Category: "ACCOUNT COMMANDS", 52 Flags: []cli.Flag{ 53 utils.DataDirFlag, 54 utils.KeyStoreDirFlag, 55 utils.PasswordFileFlag, 56 utils.LightKDFFlag, 57 }, 58 Description: ` 59 geth wallet [options] /path/to/my/presale.wallet 60 61 will prompt for your password and imports your ether presale account. 62 It can be used non-interactively with the --password option taking a 63 passwordfile as argument containing the wallet password in plaintext.`, 64 }, 65 }, 66 } 67 68 accountCommand = cli.Command{ 69 Name: "account", 70 Usage: "Manage accounts", 71 Category: "ACCOUNT COMMANDS", 72 Description: ` 73 74 Manage accounts, list all existing accounts, import a private key into a new 75 account, create a new account or update an existing account. 76 77 It supports interactive mode, when you are prompted for password as well as 78 non-interactive mode where passwords are supplied via a given password file. 79 Non-interactive mode is only meant for scripted use on test networks or known 80 safe environments. 81 82 Make sure you remember the password you gave when creating a new account (with 83 either new or import). Without it you are not able to unlock your account. 84 85 Note that exporting your key in unencrypted format is NOT supported. 86 87 Keys are stored under <DATADIR>/keystore. 88 It is safe to transfer the entire directory or the individual keys therein 89 between ethereum nodes by simply copying. 90 91 Make sure you backup your keys regularly.`, 92 Subcommands: []cli.Command{ 93 { 94 Name: "list", 95 Usage: "Print summary of existing accounts", 96 Action: utils.MigrateFlags(accountList), 97 Flags: []cli.Flag{ 98 utils.DataDirFlag, 99 utils.KeyStoreDirFlag, 100 }, 101 Description: ` 102 Print a short summary of all accounts`, 103 }, 104 { 105 Name: "new", 106 Usage: "Create a new account", 107 Action: utils.MigrateFlags(accountCreate), 108 Flags: []cli.Flag{ 109 utils.DataDirFlag, 110 utils.KeyStoreDirFlag, 111 utils.PasswordFileFlag, 112 utils.LightKDFFlag, 113 }, 114 Description: ` 115 geth account new 116 117 Creates a new account and prints the address. 118 119 The account is saved in encrypted format, you are prompted for a passphrase. 120 121 You must remember this passphrase to unlock your account in the future. 122 123 For non-interactive use the passphrase can be specified with the --password flag: 124 125 Note, this is meant to be used for testing only, it is a bad idea to save your 126 password to file or expose in any other way. 127 `, 128 }, 129 { 130 Name: "update", 131 Usage: "Update an existing account", 132 Action: utils.MigrateFlags(accountUpdate), 133 ArgsUsage: "<address>", 134 Flags: []cli.Flag{ 135 utils.DataDirFlag, 136 utils.KeyStoreDirFlag, 137 utils.LightKDFFlag, 138 }, 139 Description: ` 140 geth account update <address> 141 142 Update an existing account. 143 144 The account is saved in the newest version in encrypted format, you are prompted 145 for a passphrase to unlock the account and another to save the updated file. 146 147 This same command can therefore be used to migrate an account of a deprecated 148 format to the newest format or change the password for an account. 149 150 For non-interactive use the passphrase can be specified with the --password flag: 151 152 geth account update [options] <address> 153 154 Since only one password can be given, only format update can be performed, 155 changing your password is only possible interactively. 156 `, 157 }, 158 { 159 Name: "import", 160 Usage: "Import a private key into a new account", 161 Action: utils.MigrateFlags(accountImport), 162 Flags: []cli.Flag{ 163 utils.DataDirFlag, 164 utils.KeyStoreDirFlag, 165 utils.PasswordFileFlag, 166 utils.LightKDFFlag, 167 }, 168 ArgsUsage: "<keyFile>", 169 Description: ` 170 geth account import <keyfile> 171 172 Imports an unencrypted private key from <keyfile> and creates a new account. 173 Prints the address. 174 175 The keyfile is assumed to contain an unencrypted private key in hexadecimal format. 176 177 The account is saved in encrypted format, you are prompted for a passphrase. 178 179 You must remember this passphrase to unlock your account in the future. 180 181 For non-interactive use the passphrase can be specified with the -password flag: 182 183 geth account import [options] <keyfile> 184 185 Note: 186 As you can directly copy your encrypted accounts to another ethereum instance, 187 this import mechanism is not needed when you transfer an account between 188 nodes. 189 `, 190 }, 191 }, 192 } 193 ) 194 195 func accountList(ctx *cli.Context) error { 196 stack, _ := makeConfigNode(ctx) 197 var index int 198 for _, wallet := range stack.AccountManager().Wallets() { 199 for _, account := range wallet.Accounts() { 200 fmt.Printf("Account #%d: {%x} %s\n", index, account.Address, &account.URL) 201 index++ 202 } 203 } 204 return nil 205 } 206 207 // tries unlocking the specified account a few times. 208 func unlockAccount(ctx *cli.Context, ks *keystore.KeyStore, address string, i int, passwords []string) (accounts.Account, string) { 209 account, err := utils.MakeAddress(ks, address) 210 if err != nil { 211 utils.Fatalf("Could not list accounts: %v", err) //Fatal: Could not list accounts: index 0 higher than number of accounts 0 212 //account new를 안하고, account import만 했을때, 계정이 없어서, 에러남. 213 } 214 for trials := 0; trials < 3; trials++ { 215 prompt := fmt.Sprintf("Unlocking account %s | Attempt %d/%d", address, trials+1, 3) 216 password := getPassPhrase(prompt, false, i, passwords) 217 err = ks.Unlock(account, password) 218 if err == nil { 219 log.Info("Unlocked account", "address", account.Address.Hex()) 220 return account, password 221 } 222 if err, ok := err.(*keystore.AmbiguousAddrError); ok { 223 log.Info("Unlocked account", "address", account.Address.Hex()) 224 return ambiguousAddrRecovery(ks, err, password), password 225 } 226 if err != keystore.ErrDecrypt { 227 // No need to prompt again if the error is not decryption-related. 228 break 229 } 230 } 231 // All trials expended to unlock account, bail out 232 utils.Fatalf("Failed to unlock account %s (%v)", address, err) 233 234 return accounts.Account{}, "" 235 } 236 237 // getPassPhrase retrieves the password associated with an account, either fetched 238 // from a list of preloaded passphrases, or requested interactively from the user. 239 func getPassPhrase(prompt string, confirmation bool, i int, passwords []string) string { 240 // If a list of passwords was supplied, retrieve from them 241 if len(passwords) > 0 { 242 if i < len(passwords) { 243 return passwords[i] 244 } 245 return passwords[len(passwords)-1] 246 } 247 // Otherwise prompt the user for the password 248 if prompt != "" { 249 fmt.Println(prompt) 250 } 251 password, err := console.Stdin.PromptPassword("Passphrase: ") 252 if err != nil { 253 utils.Fatalf("Failed to read passphrase: %v", err) 254 } 255 if confirmation { 256 confirm, err := console.Stdin.PromptPassword("Repeat passphrase: ") 257 if err != nil { 258 utils.Fatalf("Failed to read passphrase confirmation: %v", err) 259 } 260 if password != confirm { 261 utils.Fatalf("Passphrases do not match") 262 } 263 } 264 return password 265 } 266 267 func ambiguousAddrRecovery(ks *keystore.KeyStore, err *keystore.AmbiguousAddrError, auth string) accounts.Account { 268 fmt.Printf("Multiple key files exist for address %x:\n", err.Addr) 269 for _, a := range err.Matches { 270 fmt.Println(" ", a.URL) 271 } 272 fmt.Println("Testing your passphrase against all of them...") 273 var match *accounts.Account 274 for _, a := range err.Matches { 275 if err := ks.Unlock(a, auth); err == nil { 276 match = &a 277 break 278 } 279 } 280 if match == nil { 281 utils.Fatalf("None of the listed files could be unlocked.") 282 } 283 fmt.Printf("Your passphrase unlocked %s\n", match.URL) 284 fmt.Println("In order to avoid this warning, you need to remove the following duplicate key files:") 285 for _, a := range err.Matches { 286 if a != *match { 287 fmt.Println(" ", a.URL) 288 } 289 } 290 return *match 291 } 292 293 // accountCreate creates a new account into the keystore defined by the CLI flags. 294 func accountCreate(ctx *cli.Context) error { //keystore에 계정 만들기.. 295 stack, _ := makeConfigNode(ctx) 296 password := getPassPhrase("Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordList(ctx)) 297 298 ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) 299 account, err := ks.NewAccount(password) 300 if err != nil { 301 utils.Fatalf("Failed to create account: %v", err) 302 } 303 fmt.Printf("Address: {%x}\n", account.Address) 304 return nil 305 } 306 307 // accountCreate creates a new account into the keystore defined by the CLI flags. 308 // 개발시 쓰는 함수 geth account and import를 하나로 구동시키기위한 함수. 릴리즈 단계에서는 제거 예정. 309 /* 310 func accountImport(ctx *cli.Context) error { //keystore에 계정 만들기.. 311 keyfile := ctx.Args().First() 312 if len(keyfile) == 0 { 313 utils.Fatalf("keyfile must be given as argument") 314 } 315 key, err := crypto.LoadECDSA(keyfile) 316 if err != nil { 317 utils.Fatalf("Failed to load the private key: %v", err) 318 } 319 320 acct, err := ks.ImportECDSA(key, passphrase) 321 if err != nil { 322 utils.Fatalf("Could not create the account: %v", err) 323 } 324 325 stack, _ := makeConfigNode(ctx) 326 password := getPassPhrase("Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordList(ctx)) 327 328 ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) 329 account, err := ks.ImportAccount(password) 330 if err != nil { 331 utils.Fatalf("Failed to create account: %v", err) 332 } 333 fmt.Printf("Address: {%x}\n", account.Address) 334 return nil 335 } 336 // ----------- 337 func accountImportas(ctx *cli.Context) error { 338 keyfile := ctx.Args().First() // 339 if len(keyfile) == 0 { 340 utils.Fatalf("keyfile must be given as argument") 341 } 342 key, err := crypto.LoadECDSA(keyfile) 343 if err != nil { 344 utils.Fatalf("Failed to load the private key: %v", err) 345 } 346 stack, _ := makeConfigNode(ctx) 347 passphrase := getPassPhrase("Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordList(ctx)) 348 349 ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) 350 351 acct, err := ks.ImportECDSA(key, passphrase) 352 if err != nil { 353 utils.Fatalf("Could not create the account: %v", err) 354 } 355 fmt.Printf("Address: {%x}\n", acct.Address) 356 357 //account, err := ks.ImportAccount(key, passphrase) 358 //if err != nil { 359 // utils.Fatalf("Failed to create account: %v", err) 360 //} 361 // fmt.Printf("Address: {%x}\n", account.Address) 362 363 364 365 366 367 return nil 368 } 369 */ 370 371 // accountUpdate transitions an account from a previous format to the current 372 // one, also providing the possibility to change the pass-phrase. 373 func accountUpdate(ctx *cli.Context) error { 374 if len(ctx.Args()) == 0 { 375 utils.Fatalf("No accounts specified to update") 376 } 377 stack, _ := makeConfigNode(ctx) 378 ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) 379 380 for _, addr := range ctx.Args() { 381 account, oldPassword := unlockAccount(ctx, ks, addr, 0, nil) 382 newPassword := getPassPhrase("Please give a new password. Do not forget this password.", true, 0, nil) 383 if err := ks.Update(account, oldPassword, newPassword); err != nil { 384 utils.Fatalf("Could not update the account: %v", err) 385 } 386 } 387 return nil 388 } 389 390 func importWallet(ctx *cli.Context) error { 391 keyfile := ctx.Args().First() 392 if len(keyfile) == 0 { 393 utils.Fatalf("keyfile must be given as argument") 394 } 395 keyJson, err := ioutil.ReadFile(keyfile) 396 if err != nil { 397 utils.Fatalf("Could not read wallet file: %v", err) 398 } 399 400 stack, _ := makeConfigNode(ctx) 401 passphrase := getPassPhrase("", false, 0, utils.MakePasswordList(ctx)) 402 403 ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) 404 acct, err := ks.ImportPreSaleKey(keyJson, passphrase) 405 if err != nil { 406 utils.Fatalf("%v", err) 407 } 408 fmt.Printf("Address: {%x}\n", acct.Address) 409 return nil 410 } 411 412 // ../bin/geth --datadir node9/data account import --password passwd.txt ./node9/data/geth/nodekey 413 414 func accountImport(ctx *cli.Context) error { 415 keyfile := ctx.Args().First() 416 if len(keyfile) == 0 { 417 utils.Fatalf("keyfile must be given as argument") 418 } 419 key, err := crypto.LoadECDSA(keyfile) 420 if err != nil { 421 utils.Fatalf("Failed to load the private key: %v", err) 422 } 423 stack, _ := makeConfigNode(ctx) 424 passphrase := getPassPhrase("Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordList(ctx)) 425 426 ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) 427 acct, err := ks.ImportECDSA(key, passphrase) 428 if err != nil { 429 utils.Fatalf("Could not create the account: %v", err) 430 } 431 fmt.Printf("Address: {%x}\n", acct.Address) 432 return nil 433 }