forked from KMDLabs/pos64staker
-
Notifications
You must be signed in to change notification settings - Fork 0
/
staker.py
executable file
·174 lines (153 loc) · 5.56 KB
/
staker.py
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
169
170
171
172
173
174
#!/usr/bin/env python3
import sys
import random
import json
import stakerlib
BESTBLOCKHASH = sys.argv[1]
CHAIN = sys.argv[2]
TXFEE = 5000
#bitcoin.params = CoinParams
#BESTBLOCKHASH = kmdrpc.getbestblockhash_rpc(CHAIN)
# function to get first and last outputs from latest block
def latest_block_txs(chain, getblock_ret):
# get txs in latest block
getblock_txs = getblock_ret['tx']
output_addresses = {}
first_address = getblock_txs[0]['vout'][0]['scriptPubKey']['addresses'][0]
last_address = getblock_txs[-1]['vout'][0]['scriptPubKey']['addresses'][0]
output_addresses[first_address] = getblock_txs[0]['txid']
output_addresses[last_address] = getblock_txs[-1]['txid']
return(output_addresses)
# function to find address that staked
def staked_from_address(chain, getblock_ret):
# get txs in latest block
pep8fu = getblock_ret['tx'][-1]
return(pep8fu['vout'][0]['scriptPubKey']['addresses'][0])
try:
rpc_connection = stakerlib.def_credentials(CHAIN)
except:
print('Could not get connection to daemon. Exiting')
sys.exit(0)
try:
with open('list.json') as list:
segid_addresses = json.load(list)
except:
print('Could not load list.json please make sure it is in the directory where komodod is located. Exiting')
sys.exit(0)
# Get pubkey being mined to.
try:
pubkey = rpc_connection.getinfo()['pubkey']
except:
print('PubKey not set. Exiting')
sys.exit(0)
# Get the address of this pubkey.
try:
setpubkey_result = rpc_connection.setpubkey(pubkey)
address = setpubkey_result['address']
except:
print('Could not get address. Exiting')
sys.exit(0)
# Get the block and all transactions in it and save for later use.
try:
getblock_result = rpc_connection.getblock(BESTBLOCKHASH, 2)
coinbase_address = getblock_result['tx'][0]['vout'][0]['scriptPubKey']['addresses'][0]
except:
print('Could not get block. Exiting')
sys.exit(0)
# If the address of our pubkey matches the coinbase address we mined this block.
if coinbase_address == address:
segid = getblock_result['segid']
if segid == -2:
print('SegId not set in block, this should not happen. Exiting.')
sys.exit(0)
else:
print('Not our block, exit.')
sys.exit(0)
txid_list = []
tx_value = 0
createraw_list = []
if segid == -1:
# This means we PoW mined the block
tx_value = getblock_result['tx'][0]['vout'][0]['valueZat']
input_dict = {
"txid": getblock_result['tx'][0]['txid'],
"vout": 0
}
createraw_list.append(input_dict)
try:
listunspent_result = rpc_connection.listunspent()
except Exception as e:
sys.exit(e)
listunspent_result = sorted(listunspent_result,key=lambda x : (x['amount'], x['confirmations']))
for unspent in listunspent_result:
# Check the utxo is spendable and has been notarised at least once, to prevent problems with reorgs.
if unspent['spendable'] and unspent['confirmations'] > 2:
input_dict = {
"txid": unspent['txid'],
"vout": unspent['vout']
}
tx_value += unspent['amount'] * 100000000
break
createraw_list.append(input_dict)
# check height so we dont count early chain or throw an error.
if getblock_result['height'] > 1800:
# find out what segids have staked the least in the last day and randomly choose one to send our funds too.
try:
getlastsegidstakes_result = rpc_connection.getlastsegidstakes(1440)
except Exception as e:
sys.exit(e)
usable_segids = []
averagestakes = int((1440 - int(getlastsegidstakes_result['PoW'])) / 64)
for _segid, stakes in getlastsegidstakes_result['SegIds'].items():
if stakes < averagestakes:
usable_segids.append(_segid)
segid_to_use = int(usable_segids[random.randint(0,len(usable_segids)-1)])
else:
segid_to_use = random.randint(0,63)
staked_from = segid_addresses[segid_to_use][3]
else:
# This means it was staked.
block_txs = latest_block_txs(CHAIN, getblock_result)
for address in block_txs:
try:
validateaddress_result = rpc_connection.validateaddress(address)
except Exception as e:
sys.exit(e)
if validateaddress_result['ismine']:
try:
getrawtx_result = rpc_connection.getrawtransaction(block_txs[address],1)
except Exception as e:
sys.exit(e)
txid_list.append(block_txs[address])
tx_value += getrawtx_result['vout'][0]['valueSat']
staked_from = staked_from_address(CHAIN, getblock_result)
else:
print('The address is not imported. Please check you imported list.json. Exiting.')
sys.exit(0)
for txid in txid_list:
input_dict = {
"txid": txid,
"vout": 0
}
createraw_list.append(input_dict)
output_dict = {
staked_from: ((tx_value - TXFEE) / 100000000)
}
try:
unsigned_hex = rpc_connection.createrawtransaction(createraw_list, output_dict)
except Exception as e:
sys.exit(e)
try:
signrawtx_result = rpc_connection.signrawtransaction(unsigned_hex)
except Exception as e:
sys.exit(e)
signed_hex = signrawtx_result['hex']
try:
sendrawtx_result = rpc_connection.sendrawtransaction(signed_hex)
except Exception as e:
sys.exit(e)
sendrawtxid = sendrawtx_result
if segid != -1:
print('Staked from segid ' + str(segid) + ' ' + sendrawtxid)
else:
print('Mined block combined to ' + str(segid_to_use) + ' ' + sendrawtxid)