forked from cosmos/mainnet
-
Notifications
You must be signed in to change notification settings - Fork 0
/
btc_main.go
168 lines (142 loc) · 3.3 KB
/
btc_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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"github.com/alfg/blockchain"
"github.com/cosmos/launch/pkg"
)
const (
exodusAddress = "35ty8iaSbWsj4YVkoHzs9pZMze6dapeoZ8"
startHeight = 460654
endHeight = 460661
atomsPerBTC = 11635
satoshiPerBTC = 100 * 1000 * 1000
btcAtomsFile = "btc_atoms.json"
btcDonationsFile = "btc_donations.json"
)
type BTCContribution struct {
BlockHeight int
TxIndex int
Amount int // satoshis
Address string
}
func (contrib BTCContribution) String() string {
return fmt.Sprintf("%d/%d: %d %s", contrib.BlockHeight, contrib.TxIndex, contrib.BTC, contrib.Address)
}
func (contrib BTCContribution) BTC() float64 {
return float64(contrib.Amount) / satoshiPerBTC
}
func main() {
args := os.Args
if len(args) < 2 {
fmt.Println("requires 'data' or 'atoms' argument")
os.Exit(1)
}
switch args[1] {
case "data":
getBTCData()
case "atoms":
writeBTCAtoms()
default:
fmt.Println("requires 'data' or 'atoms' argument")
}
}
func getBTCData() {
client, err := blockchain.New()
if err != nil {
panic(err)
}
var contribs []BTCContribution
for height := startHeight; height < endHeight+1; height++ {
b, err := client.GetBlockHeight(fmt.Sprintf("%d", height))
if err != nil {
panic(err)
}
if len(b.Blocks) > 1 {
fmt.Println("DETECTED FORK!")
}
block := b.Blocks[0]
txs := block.Tx
for txIndex, tx := range txs {
out := tx.Out
// valid tx has two outputs
if len(out) != 2 {
continue
}
out1, out2 := out[0], out[1]
// first output should be to exodus
if out1.Addr != exodusAddress {
if out2.Addr == exodusAddress {
fmt.Println("found exodus addr in output 2!", tx)
}
continue
}
// second output should be empty
if out2.Value != 0 {
fmt.Println("found value in out 2!", tx)
continue
}
contrib := BTCContribution{
BlockHeight: height,
TxIndex: txIndex,
Amount: out1.Value,
Address: out2.Script[4:], // shave the op codes
}
contribs = append(contribs, contrib)
}
}
bz, err := json.Marshal(contribs)
if err != nil {
panic(err)
}
err = ioutil.WriteFile(btcDonationsFile, bz, 0600)
if err != nil {
panic(err)
}
}
func writeBTCAtoms() {
bz, err := ioutil.ReadFile(btcDonationsFile)
if err != nil {
panic(err)
}
var contribs []BTCContribution
err = json.Unmarshal(bz, &contribs)
if err != nil {
panic(err)
}
var totalSatoshi int
var totalBTC float64
var totalATOM float64
addrs := make(map[string]float64)
for _, contrib := range contribs {
satoshi := contrib.Amount
btc := contrib.BTC()
// atoms := pkg.Round2(btc * atomsPerBTC)
atoms := float64(satoshi*atomsPerBTC) / satoshiPerBTC
if _, ok := addrs[contrib.Address]; ok {
fmt.Println("Duplicate addr", contrib)
}
addrs[contrib.Address] += atoms
totalSatoshi += satoshi
totalBTC += btc
totalATOM += atoms
}
for addr, amt := range addrs {
addrs[addr] = pkg.Round2(amt)
}
fmt.Println("total contributions", len(contribs))
fmt.Println("total addrs", len(addrs))
fmt.Println("total satoshi", totalSatoshi)
fmt.Println("total btc", totalBTC)
fmt.Println("total atom", totalATOM)
bz, err = json.MarshalIndent(addrs, "", " ")
if err != nil {
panic(err)
}
err = ioutil.WriteFile(btcAtomsFile, bz, 0600)
if err != nil {
panic(err)
}
}