forked from tamasvegera/ProtoPool
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mining.py
123 lines (94 loc) · 3.71 KB
/
mining.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
import threading
import time
import server
shares_of_current_block = 0
miners = {} # "account": number_of_shares
shares = {} # dict of pplns_shares objects, every account has an element + pool has one
# TODO miner object for every miner/account,
# collect every miner related function to that
# TODO future feature: collect shares worker-by-worker for detailed stat
hr_shares = {} # shares log for hashrate calculation for each account; example = {"1111":{"1":[timestamp1, timestamp2, timestamp3, ...], "32":[timestamp1, timestamp2, timestamp3, ..]}}
hr_avrg_shares = 30 # number of shares to calculated average hashrate
share_timeout = 240 # shares older than this will be deleted
class miner_conn():
"""Miner connection class. Stores a miner with all of it's details"""
def __init__(self, connection, address):
self.conn = connection
self.addr = address
self.timestamps = {}
self.account = ""
def set_account(self, account):
self.account = account
def add_share(self, timestamp, difficulty):
self.timestamps[timestamp] = difficulty
miner_conns = []
def print_stat():
"""Prints pool statistics every minute"""
global shares_of_current_block, miner_conns
print("Number of connected miners: " + str(len(miner_conns)) + " Running threads: " + str(threading.active_count()))
threading.Timer(60, print_stat).start()
def add_share_for_hr_calc(account, difficulty):
"""Adds shares to global list of hr_shares for hashrate calculation"""
global hr_shares
account = str(account)
difficulty = str(difficulty)
diffs = []
for diff in server.get_server_diffs():
diffs.append(str(diff))
if account in hr_shares:
for diff in diffs:
if len(hr_shares[account][diff]) == hr_avrg_shares:
del hr_shares[account][diff][0]
else:
hr_shares[account] = {}
for diff in diffs:
hr_shares[account][diff] = []
hr_shares[account][difficulty].append(time.time())
def get_hr(account):
"""
Get hashrate for an account.
Hashrate formula:
hashrate = difficulty * 2**32 / avrg_share_time
:param account:
:return:
"""
global hr_shares
account = str(account) # using account as str
if account not in hr_shares:
return 0
diffs = []
for diff in server.get_server_diffs(): # using diffs as str
diffs.append(str(diff))
hrs = [] # hashrate for every difficulty, then sum them for account hashrate
for diff in diffs:
if len(hr_shares[account][diff]) < 2: # can't calculate from 0 or 1 shares
continue
# delete old shares
new_timestamps = []
for i in range(len(hr_shares[account][diff])):
ts = hr_shares[account][diff][i]
if (time.time() - ts) <= share_timeout:
new_timestamps.append(ts)
hr_shares[account][diff] = new_timestamps
if len(hr_shares[account][diff]) < 2: # can't calculate from 0 or 1 shares
continue
# get average share time
last_share = hr_shares[account][diff][-1]
first_share = hr_shares[account][diff][0]
avrg_time = (last_share - first_share) / (len(hr_shares[account][diff]) - 1)
new_hr = float(diff) * 2**32 / avrg_time
hrs.append(new_hr)
sum_hr = 0
for hr in hrs:
sum_hr += hr
return sum_hr
def get_pool_hr():
"""Gets pool hashrate by adding up individual hashrates"""
global hr_shares
pool_hr = 0
for account in hr_shares:
pool_hr += get_hr(account)
return pool_hr
def No_miners():
"""Returns the number of active miner connections"""
return len(miner_conns)