-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
132 lines (118 loc) · 2.82 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
package main
import (
"bufio"
"encoding/csv"
"fmt"
"github.com/ethereum/go-ethereum/crypto"
"io"
"log"
"math/rand"
"os"
"runtime"
"strings"
"sync"
"time"
)
type concurrentMap struct {
sync.Mutex
addresses map[string]bool
}
var path = "addresses"
var partitions = 7
var count int64
var oldCount int64
var addressesMap = concurrentMap{addresses: make(map[string]bool),}
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
count = int64(0)
loadAddresses()
value, _ := time.ParseDuration("1s")
checkTimer := time.NewTimer(value)
go func() {
for {
select {
case <-checkTimer.C:
log.Printf("Checked: %d, Speed: %d per second", count, count-oldCount)
oldCount = count
checkTimer.Reset(value)
}
}
}()
var wg sync.WaitGroup
for i := 0; i < partitions; i++ {
wg.Add(1)
addr := generateSeedAddress()
log.Printf("Seed addr: %v\n", addr)
go generateAddresses(addr)
}
wg.Wait()
}
func loadAddresses() {
count := int64(0)
addressPath := path + string(os.PathSeparator) + "addresses.csv"
log.Printf("Loading addresses from '%s'\n", addressPath)
c, _ := os.Open(addressPath)
r := csv.NewReader(bufio.NewReader(c))
for {
record, err := r.Read()
if err == io.EOF {
break
}
count++
if count % 1000000000 == 0 {
log.Printf("Loaded %d\n", count)
}
addressesMap.addresses[record[0]] = true
}
if err := c.Close(); err != nil {
log.Fatal(err)
}
log.Printf("Loaded %d addresses.\n", count)
}
func generateSeedAddress() []byte {
privKey := make([]byte, 32)
for i := 0; i < 32; i++ {
privKey[i] = byte(rand.Intn(256))
}
return privKey
}
func generateAddresses(seedPrivKey []byte) {
for ; ; {
// Move backward through those bytes
for i := 31; i > 0; i-- {
if seedPrivKey[i]+1 == 255 {
seedPrivKey[i] = 0
} else {
seedPrivKey[i] += 1
break
}
}
// If this could be more optimized, this is where we'd get the most speed-up
priv := crypto.ToECDSAUnsafe(seedPrivKey)
address := crypto.PubkeyToAddress(priv.PublicKey)
addressesMap.Lock()
// Check to see if we have an address with a balance --
if ok := addressesMap.addresses[strings.ToLower(address.Hex())]; ok {
log.Printf("Found address with ETH balance, priv: %s, addr: %s", priv.D, address.Hex())
writeToFound(fmt.Sprintf("Private: %s, Address: %s\n", priv.D, address.Hex()))
}
addressesMap.Unlock()
count++
}
}
func writeToFound(text string) {
// TODO: Again ENV variable of where to store? Would like this to be kubes compat
foundFileName := path + string(os.PathSeparator) + "found.txt"
if _, err := os.Stat(foundFileName); os.IsNotExist(err) {
_, _ = os.Create(foundFileName)
}
f, err := os.OpenFile(foundFileName, os.O_APPEND|os.O_WRONLY, os.ModeAppend)
defer f.Close()
if err != nil {
log.Printf(err.Error())
}
_, err = f.WriteString(text)
if err != nil {
log.Printf(err.Error())
}
}