Skip to content

Commit

Permalink
Add multiple wallets and accounts generation to Sleevage. Remove vani…
Browse files Browse the repository at this point in the history
…ty. Recompile all binaries
  • Loading branch information
bernardo-xxnet committed Nov 8, 2021
1 parent e69abac commit d3135bd
Show file tree
Hide file tree
Showing 12 changed files with 46 additions and 64 deletions.
Binary file modified cli-generator/bin/sleeve-arm-linux
Binary file not shown.
Binary file modified cli-generator/bin/sleeve-linux
Binary file not shown.
Binary file modified cli-generator/bin/sleeve-mac
Binary file not shown.
Binary file modified cli-generator/bin/sleeve-mac-m1
Binary file not shown.
Binary file modified cli-generator/bin/sleeve-windows.exe
Binary file not shown.
Binary file modified sleevage/bin/sleevage-arm-linux
Binary file not shown.
Binary file modified sleevage/bin/sleevage-linux
Binary file not shown.
Binary file modified sleevage/bin/sleevage-mac
Binary file not shown.
Binary file modified sleevage/bin/sleevage-mac-m1
Binary file not shown.
Binary file modified sleevage/bin/sleevage-windows.exe
Binary file not shown.
27 changes: 15 additions & 12 deletions sleevage/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ var quantumPhrase string
var passphrase string
var account uint32
var wotsSecurityLevel string
var numWallets uint32
var numAccounts uint32

// Input files flags
var quantumPhraseFile string
Expand All @@ -29,8 +31,6 @@ var outputFile string
var outputType string
var testnet bool

var vanity string

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "sleevage",
Expand Down Expand Up @@ -69,14 +69,13 @@ func init() {
// Get arguments from files if needed
cobra.OnInitialize(readInputFiles)

// Vanity address generation string
rootCmd.PersistentFlags().StringVarP(&vanity,"vanity", "v", "", "specify a string (non case sensitive) that should appear at the beginning of the generated wallet address")

// Input flags
rootCmd.PersistentFlags().StringVarP(&quantumPhrase, "quantum", "q", "", "specify the quantum recovery phrase. Leave empty to generate a new Sleeve from scratch")
rootCmd.PersistentFlags().StringVarP(&passphrase, "pass", "p", "", "specify a passphrase")
rootCmd.PersistentFlags().Uint32VarP(&account, "account", "a", 0, "specify the account number")
rootCmd.PersistentFlags().StringVarP(&wotsSecurityLevel, "security", "s", "level0", "specify the WOTS+ security level. One of [level0, level1, level2, level3]")
rootCmd.PersistentFlags().Uint32VarP(&numWallets, "wallets", "w", 1, "specify the number of Sleeve wallets to generate")
rootCmd.PersistentFlags().Uint32VarP(&numAccounts, "num-accounts", "n", 1, "specify the number of accounts to derive for each wallet")

// Input from file
rootCmd.PersistentFlags().StringVar(&quantumPhraseFile, "quantum-file", "", "specify the quantum recovery phrase from a file. Overwrites the value of --quantum")
Expand All @@ -89,9 +88,9 @@ func init() {
}

func checkArgs() bool {
// Don't allow vanity generation with a quantum recovery phrase
if vanity != "" && quantumPhrase != "" {
fmt.Println("Can't do vanity generation when a quantum recovery phrase is specified")
// Can't recover multiple wallets
if quantumPhrase != "" && numWallets != 1 {
fmt.Println("Can't use a given quantum recovery phrase with more than 1 wallet")
return false
}
// Check output type
Expand Down Expand Up @@ -131,13 +130,15 @@ func readInputFiles() {
}
}

func handleOutput(sl SleeveJson) {
func handleOutput(sl []SleeveJson) {
// Get output according to type
var out []byte
var err error
switch outputType {
case "text":
out = []byte(sl.String())
for _, s := range sl {
out = append(out, fmt.Sprintf("%s\n\n", s.String())...)
}
case "json":
// noop
out, err = json.MarshalIndent(sl, "", " ")
Expand All @@ -153,8 +154,10 @@ func handleOutput(sl SleeveJson) {
if err != nil {
panic(fmt.Sprintf("error writing sleeve data to file: %s", err))
}
// Write just address to stdout
fmt.Println(sl.Address)
// Write just addresses to stdout
for _, s := range sl {
fmt.Println(s.Address)
}
} else {
// Write to stdout
fmt.Println(string(out))
Expand Down
83 changes: 31 additions & 52 deletions sleevage/cmd/sleeve.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@ import (
"crypto/rand"
"errors"
"fmt"
"github.com/xx-labs/sleeve/hasher"
"github.com/xx-labs/sleeve/wallet"
"github.com/xx-labs/sleeve/wots"
"strings"
)

type SleeveJson struct {
Expand Down Expand Up @@ -72,10 +70,10 @@ func parseArgs() (args, error) {

return args{
generate: generate,
quantum: quantumPhrase,
pass: passphrase,
spec: spec,
path: path.String(),
quantum: quantumPhrase,
pass: passphrase,
spec: spec,
path: path.String(),
}, nil
}

Expand Down Expand Up @@ -114,57 +112,38 @@ func getJson(path string, sleeve *wallet.Sleeve) SleeveJson {
}
}

func sleeve() (SleeveJson, error) {
func sleeve() ([]SleeveJson, error) {
// Parse args
args, err := parseArgs()
if err != nil {
return SleeveJson{}, err
return nil, err
}

// Vanity generator
if vanity != "" {
return vanityGen(args)
}

// Regular generation
return getSleeve(args)
}

func vanityGen(args args) (SleeveJson, error) {
tries := uint32(0)
entropy := make([]byte, wallet.EntropySize)
n, err := rand.Read(entropy)
if err != nil {
return SleeveJson{}, err
}
if n != wallet.EntropySize {
return SleeveJson{}, errors.New("couldn't read 32 bytes of entropy")
}
h := hasher.BLAKE2B_256.New()
for {
sleeve, err := wallet.NewSleeveFromEntropy(entropy, args.pass, args.spec)
if err != nil {
return SleeveJson{}, err
}
json := getJson(args.path, sleeve)
if addressHasVanity(json.Address) {
return json, nil
}
h.Write(entropy)
entropy = h.Sum(nil)
tries++
// Uint32 wrapped around
if tries == 0 {
return SleeveJson{}, errors.New("couldn't generate vanity address after trying 2^32 seeds")
// Sleeve generation
wallets := make([]SleeveJson, numWallets*numAccounts)
// Keep start account
startAccount := account
for i := uint32(0); i < numWallets; i++ {
for j := uint32(0); j < numAccounts; j++ {
// Increase account number
account = startAccount + j
// Reparse args
args, err = parseArgs()
if err != nil {
return nil, err
}
// Generate wallet
wallets[i*numAccounts+j], err = getSleeve(args)
if err != nil {
return nil, err
}
// Set the quantum phrase if this is first wallet
if j == 0 {
quantumPhrase = wallets[i*numAccounts+j].Quantum
}
}
// Reset quantum phrase to generate new wallet on next iteration
quantumPhrase = ""
}
}

func addressHasVanity(address string) bool {
// Convert address to lower case
lowerAddress := strings.ToLower(address)
// Convert vanity to lower case
lowerVanity := strings.ToLower(vanity)
idx := strings.Index(lowerAddress, lowerVanity)
return idx == 1
return wallets, nil
}

0 comments on commit d3135bd

Please sign in to comment.