Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions supernode/cmd/helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package cmd

import (
"fmt"
"strings"

"github.com/LumeraProtocol/supernode/pkg/keyring"
"github.com/LumeraProtocol/supernode/supernode/config"
cKeyring "github.com/cosmos/cosmos-sdk/crypto/keyring"
sdk "github.com/cosmos/cosmos-sdk/types"
)

// initKeyringFromConfig initializes keyring using app configuration
func initKeyringFromConfig(config *config.Config) (cKeyring.Keyring, error) {
return keyring.InitKeyring(config.KeyringConfig.Backend, config.GetKeyringDir())
}

// getAddressFromKeyName extracts address from keyring using key name
func getAddressFromKeyName(kr cKeyring.Keyring, keyName string) (sdk.AccAddress, error) {
keyInfo, err := kr.Key(keyName)
if err != nil {
return nil, fmt.Errorf("key not found: %w", err)
}

address, err := keyInfo.GetAddress()
if err != nil {
return nil, fmt.Errorf("failed to get address from key: %w", err)
}

return address, nil
}

// processAndValidateMnemonic processes and validates a mnemonic phrase
func processAndValidateMnemonic(mnemonic string) (string, error) {
// Normalize whitespace (replace multiple spaces with single space)
processed := strings.TrimSpace(mnemonic)
processed = strings.Join(strings.Fields(processed), " ")

// Validate BIP39 mnemonic word count
wordCount := len(strings.Fields(processed))
if !isValidBIP39WordCount(wordCount) {
return "", fmt.Errorf("invalid mnemonic word count: %d. Valid BIP39 mnemonic lengths are 12, 15, 18, 21, or 24 words", wordCount)
}

return processed, nil
}

// isValidBIP39WordCount checks if the word count is valid for BIP39 mnemonics
func isValidBIP39WordCount(wordCount int) bool {
validCounts := []int{12, 15, 18, 21, 24}
for _, count := range validCounts {
if wordCount == count {
return true
}
}
return false
}
103 changes: 11 additions & 92 deletions supernode/cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,7 @@ Example:
return fmt.Errorf("failed to create directories: %w", err)
}

// Initialize keyring
kr, err := keyring.InitKeyring(
appConfig.KeyringConfig.Backend,
appConfig.GetKeyringDir(),
)
kr, err := initKeyringFromConfig(appConfig)
if err != nil {
return fmt.Errorf("failed to initialize keyring: %w", err)
}
Expand All @@ -95,17 +91,20 @@ Example:
return fmt.Errorf("mnemonic is required when --recover is specified")
}

// Process the mnemonic to ensure proper formatting
initMnemonic = processAndValidateMnemonic(initMnemonic)
// Process and validate mnemonic using helper function
processedMnemonic, err := processAndValidateMnemonic(initMnemonic)
if err != nil {
fmt.Printf("Warning: %v\n", err)
// Continue with original mnemonic if validation fails
processedMnemonic = initMnemonic
}

// Recover account from mnemonic
info, err := keyring.RecoverAccountFromMnemonic(kr, initKeyName, initMnemonic)
info, err := keyring.RecoverAccountFromMnemonic(kr, initKeyName, processedMnemonic)
if err != nil {
return fmt.Errorf("failed to recover account: %w", err)
}

// Get address
addr, err := info.GetAddress()
addr, err := getAddressFromKeyName(kr, initKeyName)
if err != nil {
return fmt.Errorf("failed to get address: %w", err)
}
Expand All @@ -122,8 +121,7 @@ Example:
return fmt.Errorf("failed to create new account: %w", err)
}

// Get address
addr, err := info.GetAddress()
addr, err := getAddressFromKeyName(kr, initKeyName)
if err != nil {
return fmt.Errorf("failed to get address: %w", err)
}
Expand Down Expand Up @@ -154,85 +152,6 @@ Example:
},
}

// processAndValidateMnemonic processes and validates the mnemonic
func processAndValidateMnemonic(mnemonic string) string {
// Normalize whitespace (replace multiple spaces with single space)
processed := normalizeWhitespace(mnemonic)

// Validate BIP39 mnemonic word count
wordCount := countWords(processed)
if !isValidBIP39WordCount(wordCount) {
fmt.Printf("Warning: Invalid mnemonic word count: %d. Valid BIP39 mnemonic lengths are 12, 15, 18, 21, or 24 words\n", wordCount)
}

return processed
}

// normalizeWhitespace replaces multiple spaces with a single space
func normalizeWhitespace(s string) string {
return normalizeWhitespaceImpl(s)
}

// countWords counts the number of words in a string
func countWords(s string) int {
return len(splitWords(s))
}

// splitWords splits a string into words
func splitWords(s string) []string {
return splitWordsImpl(s)
}

// normalizeWhitespaceImpl is the implementation of normalizeWhitespace
// It's a separate function to make it easier to test
func normalizeWhitespaceImpl(s string) string {
// Import strings package locally to avoid adding it to the imports
// if it's not already there
return normalizeWhitespaceWithStrings(s)
}

// normalizeWhitespaceWithStrings normalizes whitespace using the strings package
func normalizeWhitespaceWithStrings(s string) string {
// This is a simplified implementation
// In a real implementation, we would use the strings package
words := splitWordsImpl(s)
return joinWords(words, " ")
}

// splitWordsImpl is the implementation of splitWords
func splitWordsImpl(s string) []string {
// This is a simplified implementation
// In a real implementation, we would use the strings package
var words []string
var word string
for _, c := range s {
if c == ' ' || c == '\t' || c == '\n' || c == '\r' {
if word != "" {
words = append(words, word)
word = ""
}
} else {
word += string(c)
}
}
if word != "" {
words = append(words, word)
}
return words
}

// joinWords joins words with a separator
func joinWords(words []string, sep string) string {
if len(words) == 0 {
return ""
}
result := words[0]
for _, word := range words[1:] {
result += sep + word
}
return result
}

func init() {
rootCmd.AddCommand(initCmd)

Expand Down
11 changes: 4 additions & 7 deletions supernode/cmd/keys_add.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,8 @@ Example:
return fmt.Errorf("key name is required")
}

// Initialize keyring using config values
kr, err := keyring.InitKeyring(
appConfig.KeyringConfig.Backend,
appConfig.GetKeyringDir(),
)
// Initialize keyring using helper function
kr, err := initKeyringFromConfig(appConfig)
if err != nil {
return fmt.Errorf("failed to initialize keyring: %w", err)
}
Expand All @@ -48,8 +45,8 @@ Example:
return fmt.Errorf("failed to create new account: %w", err)
}

// Get address
address, err := info.GetAddress()
// Get address using helper function
address, err := getAddressFromKeyName(kr, keyName)
if err != nil {
return fmt.Errorf("failed to get address: %w", err)
}
Expand Down
8 changes: 2 additions & 6 deletions supernode/cmd/keys_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"sort"
"text/tabwriter"

snkeyring "github.com/LumeraProtocol/supernode/pkg/keyring"
"github.com/spf13/cobra"
)

Expand All @@ -20,11 +19,8 @@ This command displays a table with key names, types, and addresses.
Example:
supernode keys list`,
RunE: func(cmd *cobra.Command, args []string) error {
// Initialize keyring using config values
kr, err := snkeyring.InitKeyring(
appConfig.KeyringConfig.Backend,
appConfig.GetKeyringDir(),
)
// Initialize keyring using helper function
kr, err := initKeyringFromConfig(appConfig)
if err != nil {
return fmt.Errorf("failed to initialize keyring: %w", err)
}
Expand Down
41 changes: 11 additions & 30 deletions supernode/cmd/keys_recover.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,8 @@ Example:
return fmt.Errorf("key name is required")
}

// Initialize keyring using config values
kr, err := keyring.InitKeyring(
appConfig.KeyringConfig.Backend,
appConfig.GetKeyringDir(),
)
// Initialize keyring using helper function
kr, err := initKeyringFromConfig(appConfig)
if err != nil {
return fmt.Errorf("failed to initialize keyring: %w", err)
}
Expand All @@ -59,32 +56,27 @@ Example:
if err != nil {
return fmt.Errorf("failed to read mnemonic: %w", err)
}
mnemonic = strings.TrimSpace(mnemonic)
}

// Process the mnemonic to ensure proper formatting
mnemonic = strings.TrimSpace(mnemonic)
// Normalize whitespace (replace multiple spaces with single space)
mnemonic = strings.Join(strings.Fields(mnemonic), " ")
// Process and validate mnemonic using helper function
processedMnemonic, err := processAndValidateMnemonic(mnemonic)
if err != nil {
return err
}

// Add debug output to see what's being processed
wordCount := len(strings.Fields(mnemonic))
wordCount := len(strings.Fields(processedMnemonic))
fmt.Printf("Processing mnemonic with %d words\n", wordCount)

// Validate BIP39 mnemonic word count
if !isValidBIP39WordCount(wordCount) {
return fmt.Errorf("invalid mnemonic word count: %d. Valid BIP39 mnemonic lengths are 12, 15, 18, 21, or 24 words", wordCount)
}

// Recover account from mnemonic
info, err := keyring.RecoverAccountFromMnemonic(kr, keyName, mnemonic)
info, err := keyring.RecoverAccountFromMnemonic(kr, keyName, processedMnemonic)
if err != nil {
// Check if the error is due to an invalid mnemonic
return fmt.Errorf("failed to recover account: %w", err)
}

// Get address
address, err := info.GetAddress()
// Get address using helper function
address, err := getAddressFromKeyName(kr, keyName)
if err != nil {
return fmt.Errorf("failed to get address: %w", err)
}
Expand All @@ -99,17 +91,6 @@ Example:
},
}

// isValidBIP39WordCount checks if the word count is valid for BIP39 mnemonics
func isValidBIP39WordCount(wordCount int) bool {
validCounts := []int{12, 15, 18, 21, 24}
for _, count := range validCounts {
if wordCount == count {
return true
}
}
return false
}

func init() {
keysCmd.AddCommand(keysRecoverCmd)
// Add flag for mnemonic
Expand Down
Loading