From 40f7d7cefeac0c7e97583548a2ab31ba7c050db5 Mon Sep 17 00:00:00 2001 From: Roy Lee Date: Fri, 19 Aug 2022 16:16:46 -0700 Subject: [PATCH] prompt: ask birthday for user provided seed --- internal/prompt/prompt.go | 69 +++++++++++++++++++++++++++++++-------- walletsetup.go | 8 +++-- 2 files changed, 60 insertions(+), 17 deletions(-) diff --git a/internal/prompt/prompt.go b/internal/prompt/prompt.go index 8aff7f2..293f869 100644 --- a/internal/prompt/prompt.go +++ b/internal/prompt/prompt.go @@ -13,7 +13,9 @@ import ( "encoding/hex" "fmt" "os" + "strconv" "strings" + "time" "github.com/lbryio/lbcutil/hdkeychain" "github.com/lbryio/lbcwallet/internal/legacy/keystore" @@ -120,6 +122,32 @@ func promptListBool(reader *bufio.Reader, prefix string, return response == "yes" || response == "y", nil } +// promptBirhdayUnixTimeStamp prompts the user a Unix timestamp in second. +func promptUnixTimestamp(reader *bufio.Reader, prefix string, + defaultEntry string) (time.Time, error) { // nolint:unparam + + prompt := fmt.Sprintf("%s [%s]: ", prefix, defaultEntry) + + for { + fmt.Print(prompt) + reply, err := reader.ReadString('\n') + if err != nil { + return time.Time{}, err + } + reply = strings.TrimSpace(strings.ToLower(reply)) + if reply == "" { + reply = defaultEntry + } + ts, err := strconv.ParseInt(reply, 10, 64) + if err != nil { + fmt.Print(prompt) + continue + } + + return time.Unix(ts, 0), nil + } +} + // promptPass prompts the user for a passphrase with the given prefix. The // function will ask the user to confirm the passphrase and will repeat the // prompts until they enter a matching response. @@ -158,6 +186,12 @@ func promptPass(_ *bufio.Reader, prefix string, confirm bool) ([]byte, error) { } } +func birthday(reader *bufio.Reader) (time.Time, error) { + prompt := "Enter the birthday of the seed in Unix timestamp " + + "(the walllet will scan the chain from this time)" + return promptUnixTimestamp(reader, prompt, "0") +} + // PrivatePass prompts the user for a private passphrase with varying behavior // depending on whether the passed legacy keystore exists. When it does, the // user is prompted for the existing passphrase which is then used to unlock it. @@ -248,34 +282,31 @@ func PublicPass(reader *bufio.Reader, privPass []byte, // the user along with prompting them for confirmation. When the user answers // yes, a the user is prompted for it. All prompts are repeated until the user // enters a valid response. -func Seed(reader *bufio.Reader) ([]byte, error) { +func Seed(reader *bufio.Reader) ([]byte, time.Time, error) { + bday := time.Now() // Ascertain the wallet generation seed. useUserSeed, err := promptListBool(reader, "Do you have an "+ "existing wallet seed you want to use?", "no") if err != nil { - return nil, err + return nil, bday, err } if !useUserSeed { seed, err := hdkeychain.GenerateSeed(hdkeychain.RecommendedSeedLen) if err != nil { - return nil, err + return nil, bday, err } - fmt.Println("Your wallet generation seed is:") - fmt.Printf("%x\n", seed) - fmt.Println("IMPORTANT: Keep the seed in a safe place as you\n" + - "will NOT be able to restore your wallet without it.") - fmt.Println("Please keep in mind that anyone who has access\n" + - "to the seed can also restore your wallet thereby\n" + - "giving them access to all your funds, so it is\n" + - "imperative that you keep it in a secure location.") + fmt.Printf("Your wallet generation seed is: %x\n", seed) + + fmt.Printf("\nIMPORTANT: Keep the seed in a safe place as you " + + "will NOT be able to restore your wallet without it.\n\n") for { fmt.Print(`Once you have stored the seed in a safe ` + `and secure location, enter "OK" to continue: `) confirmSeed, err := reader.ReadString('\n') if err != nil { - return nil, err + return nil, bday, err } confirmSeed = strings.TrimSpace(confirmSeed) confirmSeed = strings.Trim(confirmSeed, `"`) @@ -284,8 +315,18 @@ func Seed(reader *bufio.Reader) ([]byte, error) { } } - return seed, nil + return seed, bday, nil } - return provideSeed(reader) + seed, err := provideSeed(reader) + if err != nil { + return nil, bday, err + } + + bday, err = birthday(reader) + if err != nil { + return nil, bday, err + } + + return seed, bday, nil } diff --git a/walletsetup.go b/walletsetup.go index 2305fe3..8092079 100644 --- a/walletsetup.go +++ b/walletsetup.go @@ -182,19 +182,21 @@ func createWallet(cfg *config) error { // Ascertain the wallet generation seed. This will either be an // automatically generated value the user has already confirmed or a // value the user has entered which has already been validated. - seed, err := prompt.Seed(reader) + seed, bday, err := prompt.Seed(reader) if err != nil { return err } fmt.Println("Creating the wallet...") - w, err := loader.CreateNewWallet(pubPass, privPass, seed, time.Now()) + w, err := loader.CreateNewWallet(pubPass, privPass, seed, bday) if err != nil { return err } w.Manager.Close() - fmt.Println("The wallet has been created successfully.") + + fmt.Println("The wallet has been created successfully with birthday:", bday.Format(time.UnixDate)) + return nil }