1717package main
1818
1919import (
20+ "errors"
2021 "fmt"
2122 "os"
23+ "strings"
2224
2325 "github.com/ethereum/go-ethereum/accounts"
2426 "github.com/ethereum/go-ethereum/accounts/keystore"
2527 "github.com/ethereum/go-ethereum/cmd/utils"
28+ "github.com/ethereum/go-ethereum/common"
2629 "github.com/ethereum/go-ethereum/crypto"
2730 "github.com/ethereum/go-ethereum/log"
2831 "github.com/urfave/cli/v2"
@@ -191,7 +194,7 @@ nodes.
191194// makeAccountManager creates an account manager with backends
192195func makeAccountManager (ctx * cli.Context ) * accounts.Manager {
193196 cfg := loadBaseConfig (ctx )
194- am := accounts .NewManager (& accounts. Config { InsecureUnlockAllowed : cfg . Node . InsecureUnlockAllowed } )
197+ am := accounts .NewManager (nil )
195198 keydir , isEphemeral , err := cfg .Node .GetKeyStoreDir ()
196199 if err != nil {
197200 utils .Fatalf ("Failed to get the keystore directory: %v" , err )
@@ -275,6 +278,24 @@ func ambiguousAddrRecovery(ks *keystore.KeyStore, err *keystore.AmbiguousAddrErr
275278 return * match
276279}
277280
281+ // readPasswordFromFile reads the first line of the given file, trims line endings,
282+ // and returns the password and whether the reading was successful.
283+ func readPasswordFromFile (path string ) (string , bool ) {
284+ if path == "" {
285+ return "" , false
286+ }
287+ text , err := os .ReadFile (path )
288+ if err != nil {
289+ utils .Fatalf ("Failed to read password file: %v" , err )
290+ }
291+ lines := strings .Split (string (text ), "\n " )
292+ if len (lines ) == 0 {
293+ return "" , false
294+ }
295+ // Sanitise DOS line endings.
296+ return strings .TrimRight (lines [0 ], "\r " ), true
297+ }
298+
278299// accountCreate creates a new account into the keystore defined by the CLI flags.
279300func accountCreate (ctx * cli.Context ) error {
280301 cfg := loadBaseConfig (ctx )
@@ -292,8 +313,10 @@ func accountCreate(ctx *cli.Context) error {
292313 scryptP = keystore .LightScryptP
293314 }
294315
295- password := utils .GetPassPhraseWithList ("Your new account is locked with a password. Please give a password. Do not forget this password." , true , 0 , utils .MakePasswordList (ctx ))
296-
316+ password , ok := readPasswordFromFile (ctx .Path (utils .PasswordFileFlag .Name ))
317+ if ! ok {
318+ password = utils .GetPassPhrase ("Your new account is locked with a password. Please give a password. Do not forget this password." , true )
319+ }
297320 account , err := keystore .StoreKey (keydir , password , scryptN , scryptP )
298321
299322 if err != nil {
@@ -323,10 +346,23 @@ func accountUpdate(ctx *cli.Context) error {
323346 ks := backends [0 ].(* keystore.KeyStore )
324347
325348 for _ , addr := range ctx .Args ().Slice () {
326- account , oldPassword := unlockAccount (ks , addr , 0 , nil )
327- newPassword := utils .GetPassPhraseWithList ("Please give a new password. Do not forget this password." , true , 0 , nil )
328- if err := ks .Update (account , oldPassword , newPassword ); err != nil {
329- utils .Fatalf ("Could not update the account: %v" , err )
349+ if ! common .IsHexAddress (addr ) {
350+ return errors .New ("address must be specified in hexadecimal form" )
351+ }
352+ account := accounts.Account {Address : common .HexToAddress (addr )}
353+ newPassword := utils .GetPassPhrase ("Please give a NEW password. Do not forget this password." , true )
354+ updateFn := func (attempt int ) error {
355+ prompt := fmt .Sprintf ("Please provide the OLD password for account %s | Attempt %d/%d" , addr , attempt + 1 , 3 )
356+ password := utils .GetPassPhrase (prompt , false )
357+ return ks .Update (account , password , newPassword )
358+ }
359+ // let user attempt unlock thrice.
360+ err := updateFn (0 )
361+ for attempts := 1 ; attempts < 3 && errors .Is (err , keystore .ErrDecrypt ); attempts ++ {
362+ err = updateFn (attempts )
363+ }
364+ if err != nil {
365+ return fmt .Errorf ("could not update account: %w" , err )
330366 }
331367 }
332368 return nil
@@ -347,10 +383,12 @@ func importWallet(ctx *cli.Context) error {
347383 if len (backends ) == 0 {
348384 utils .Fatalf ("Keystore is not available" )
349385 }
386+ password , ok := readPasswordFromFile (ctx .Path (utils .PasswordFileFlag .Name ))
387+ if ! ok {
388+ password = utils .GetPassPhrase ("" , false )
389+ }
350390 ks := backends [0 ].(* keystore.KeyStore )
351- passphrase := utils .GetPassPhraseWithList ("" , false , 0 , utils .MakePasswordList (ctx ))
352-
353- acct , err := ks .ImportPreSaleKey (keyJSON , passphrase )
391+ acct , err := ks .ImportPreSaleKey (keyJSON , password )
354392 if err != nil {
355393 utils .Fatalf ("%v" , err )
356394 }
@@ -373,9 +411,11 @@ func accountImport(ctx *cli.Context) error {
373411 utils .Fatalf ("Keystore is not available" )
374412 }
375413 ks := backends [0 ].(* keystore.KeyStore )
376- passphrase := utils .GetPassPhraseWithList ("Your new account is locked with a password. Please give a password. Do not forget this password." , true , 0 , utils .MakePasswordList (ctx ))
377-
378- acct , err := ks .ImportECDSA (key , passphrase )
414+ password , ok := readPasswordFromFile (ctx .Path (utils .PasswordFileFlag .Name ))
415+ if ! ok {
416+ password = utils .GetPassPhrase ("Your new account is locked with a password. Please give a password. Do not forget this password." , true )
417+ }
418+ acct , err := ks .ImportECDSA (key , password )
379419 if err != nil {
380420 utils .Fatalf ("Could not create the account: %v" , err )
381421 }
0 commit comments