From 2880ec9bdd023952545ef098823af729e21d6ee0 Mon Sep 17 00:00:00 2001 From: Jim McDonald Date: Mon, 5 Jun 2023 20:39:10 +0100 Subject: [PATCH] Allow short form mnemonics. --- CHANGELOG.md | 1 + util/mnemonic.go | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c1818a..27a6142 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ dev: - fix incorrect error when "deposit veirfy" is not given a withdrawal address + - allow truncated mnemonics (first four characters of each word) 1.31.0: - initial support for deneb diff --git a/util/mnemonic.go b/util/mnemonic.go index 3433871..63bc36b 100644 --- a/util/mnemonic.go +++ b/util/mnemonic.go @@ -14,6 +14,7 @@ package util import ( + "fmt" "regexp" "strings" @@ -64,11 +65,41 @@ func SeedFromMnemonic(mnemonic string) ([]byte, error) { // Try with the various word lists. for _, wl := range mnemonicWordLists { bip39.SetWordList(wl) - seed, err := bip39.NewSeedWithErrorChecking(mnemonic, mnemonicPassphrase) + seed, err := bip39.NewSeedWithErrorChecking(expandMnemonic(mnemonic), mnemonicPassphrase) if err == nil { + fmt.Printf("Seed is %#x\n", seed) return seed, nil } } return nil, errors.New("mnemonic is invalid") } + +// expandMnmenonic expands mnemonics from their 4-letter versions. +func expandMnemonic(input string) string { + wordList := bip39.GetWordList() + truncatedWords := make(map[string]string, len(wordList)) + for _, word := range wordList { + if len(word) > 4 { + truncatedWords[firstFour(word)] = word + } + } + mnemonicWords := strings.Split(input, " ") + for i := range mnemonicWords { + if fullWord, exists := truncatedWords[norm.NFKC.String(mnemonicWords[i])]; exists { + mnemonicWords[i] = fullWord + } + } + return strings.Join(mnemonicWords, " ") +} + +// firstFour provides the first four letters for a potentially longer word. +func firstFour(s string) string { + // Use NFKC here for composition, to avoid accents counting as their own characters. + s = norm.NFKC.String(s) + r := []rune(s) + if len(r) > 4 { + return string(r[:4]) + } + return s +}