-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
153 lines (128 loc) · 3.86 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package main
import (
"errors"
"fmt"
"log"
"os"
"regexp"
"strings"
"sync"
"text/template"
"time"
"github.com/dustin/go-humanize"
"github.com/hako/durafmt"
"github.com/logrusorgru/aurora"
"github.com/spf13/cobra"
"github.com/stellar/go/keypair"
)
const maxConcurrency = 10
const txtTemplate = `
Address: {{.Address}}
Seed: {{.Seed}}
`
var positions = []string{
"anywhere",
"end",
"start",
}
var position string
var wg sync.WaitGroup
var throttle = make(chan int, maxConcurrency)
var verbose, writeToFile bool
var start time.Time
func main() {
var RootCmd = &cobra.Command{
Use: "stellar-vanity-address [flags] text",
Short: "Stellar vanity address generator",
Long: `Generate a stellar vanity address.`,
RunE: search,
}
RootCmd.PersistentFlags().StringVarP(&position, "position", "p", "anywhere", "position of searched text in the address: anywhere, start, end")
RootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose output that adds a bit of extra info, like the number or pairs searched")
RootCmd.PersistentFlags().BoolVarP(&writeToFile, "writetofile", "f", false, "flag for writing resulted address/seed pair into a file")
RootCmd.Execute()
}
func search(cmd *cobra.Command, args []string) error {
// regex that checks that seaerchstring does not contain any invalid chacters
isValid := regexp.MustCompile(`^[A-Za-z0-9]+$`).MatchString
if len(args) == 0 || !isValid(args[0]) {
return errors.New("Please enter a valid string to search for")
}
// check that the position has a predefined value, it can and should be improved
if !strings.Contains(strings.Join(positions, ","), position) {
return errors.New("Position to search at can be: anywhere, start, end")
}
var index int64
index = 1
start = time.Now()
fmt.Println("Start search for", args[0], "at position:", position)
u := strings.ToUpper(args[0])
for {
if verbose == true && index%100000 == 0 {
fmt.Printf("\rSearched %s pairs", humanize.Comma(index))
}
throttle <- 1
wg.Add(1)
go generatePair(u, index)
index++
}
return nil
}
func generatePair(text string, index int64) {
var r bool
pair, err := keypair.Random()
if err != nil {
log.Fatal(err)
}
switch position {
case "start":
r = checkStart(pair.Address(), text)
case "end":
r = checkEnd(pair.Address(), text)
default:
r = checkMiddle(pair.Address(), text)
}
if r == true {
writeFinalMessage(pair, index, text)
}
wg.Done()
<-throttle
}
func checkStart(s, substr string) bool {
if strings.HasPrefix(substr, "GA") || strings.HasPrefix(substr, "GB") || strings.HasPrefix(substr, "GC") || strings.HasPrefix(substr, "GD") {
return strings.HasPrefix(s, substr)
}
s = s[1:]
if strings.HasPrefix(substr, "A") || strings.HasPrefix(substr, "B") || strings.HasPrefix(substr, "C") || strings.HasPrefix(substr, "D") {
return strings.HasPrefix(s, substr)
}
return strings.HasPrefix(s[1:], substr)
}
func checkMiddle(s, substr string) bool {
return strings.Contains(s, substr)
}
func checkEnd(s, suffix string) bool {
return strings.HasSuffix(s, suffix)
}
func writeFinalMessage(pair *keypair.Full, index int64, u string) {
end := time.Now().Sub(start)
if verbose == true {
d, _ := durafmt.ParseString(end.String())
fmt.Printf("\rChecked a total of %s pairs in: %s\n", humanize.Comma(index), d)
}
c := strings.Split(pair.Address(), u)
fmt.Printf("\nSearch successful! Results:\n\nAddress: %s%s%s\nSeed:\t %s\n", c[0], aurora.Green(u), c[1], pair.Seed())
if writeToFile == true {
f, err := os.OpenFile("result.txt", os.O_CREATE|os.O_WRONLY, 0666)
if err != nil {
log.Fatalf("error opening file: %v", err)
}
defer f.Close()
t := template.Must(template.New("t2").Parse(txtTemplate))
if err := t.Execute(f, struct{ Address, Seed string }{pair.Address(), pair.Seed()}); err != nil {
log.Fatal(err)
}
}
//this could probably be handled more gracefully, ¯\_(ツ)_/¯
os.Exit(0)
}