Last active
March 30, 2020 07:11
-
-
Save jwinterm/c417d05d819bbefd22d0 to your computer and use it in GitHub Desktop.
Monero pool hashrate checker
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import requests | |
import json | |
import re | |
import datetime | |
import sys | |
import matplotlib as mpl | |
mpl.use('Agg') | |
import matplotlib.pyplot as plt | |
from math import cos, sin, pi | |
# Get time and make string for title | |
utc = datetime.datetime.utcnow() | |
utc_string = utc.strftime("%Y-%m-%d %H:%M:%S") | |
# Define regular pool list | |
server_dict = { | |
'cryptonotepool.org.uk': 'http://80.71.13.55:8117/stats', | |
'extremehash.com': 'http://107.170.148.200:8117/stats', | |
'minexmr.com': 'http://pool.minexmr.com:8117/stats', | |
'monero.coolmining.club': 'http://xmr1.coolmining.club:8117/stats', | |
'monero.crypto-pool.fr': 'http://xmr.crypto-pool.fr:8090/stats', | |
'monero.graymines.net': 'http://monero.graymines.net:8117/stats', | |
'monero.kippo.eu': 'http://monero.kippo.eu:8117/stats', | |
'monero.xminingpool.com': 'http://xmr.xminingpool.com:2117/stats', | |
'moneropool.com': 'http://api.moneropool.com:8080/stats', | |
'moneropool.org': 'http://192.99.44.150:8117/stats', | |
'moneropool.net': 'http://moneropool.net:8118/stats', | |
'moneropool.ru': 'http://alxxxer.ru:8200/stats', | |
# 'mro.bitnonce.com': 'http://mro.bitnonce.com/api/stats', # for some reason hangs | |
'mro.extremepool.org': 'http://mro.extremepool.org:8117/stats', | |
'nomp.freeyy.me': 'http://nomp.freeyy.me:8117/stats', | |
'pool.cryptograben.com': 'http://xmr.cryptograben.com:8117/stats', | |
'www2.coinmine.pl': 'http://mine1.coinmine.pl:8117/stats', | |
# 'xmr.ext-pool.net': 'http://xmr.ext-pool.net:8417/stats', # for some reason hangs | |
'xmr.farm': 'http://xmr.farm:8117/stats', | |
'xmr.alimabi.cn': 'http://xmrapinew.alimabi.cn:80/stats', | |
'xmr.hashinvest.net': 'http://xmr.hashinvest.net:8117/stats', | |
'xmr.poolto.be': 'http://mro.poolto.be:8117/stats', | |
'xmr.prohash.net': 'http://xmr.prohash.net:8117/stats' | |
} | |
hashrate_list = [] #List of pool hashrates | |
name_list = [] #Ordered (to match hashrate) list of pool names | |
responded = 0 | |
# Connect to each server and get pool hashrate | |
for key, val in server_dict.items(): | |
print "Trying: " + key | |
try: | |
resp = requests.get(val, timeout=13) | |
output = json.loads(resp.text) | |
if float(output[u'pool'][u'hashrate']) != 0: | |
name_list.append(key) | |
hashrate_list.append(float(output[u'pool'][u'hashrate'])/1e6) | |
print key + " responded" | |
responded += 1 | |
except: | |
print key + " did not respond" | |
# Use last pool connects data to calculate network hashrate from diff | |
network_hash = float(output[u'network'][u'difficulty'])/60e6 | |
# Begin hack for dwarfpool | |
dwarf_url = 'http://dwarfpool.com/' | |
resp = requests.get(dwarf_url) | |
lines = resp.text.encode("utf-8").split('\n') | |
target_line = -1 | |
# Find XMR pool data and then grab hashrate | |
try: | |
for line_number, line in enumerate(lines): | |
if "Code: XMR" in line: | |
target_line = line_number + 3 | |
if line_number == target_line: | |
name_list.append('dwarfpool.com') | |
hashrate_list.append(float(re.sub("[^0-9.]", "", line))/1e3) | |
responded += 1 | |
print "dwarfpool responded" | |
except: | |
print "dwarfpool did not respond" | |
print "Out of {0} pools, {1} responded.".format(len(server_dict), responded) | |
# Calculate unknown hash | |
known_hash = sum(hashrate_list) | |
unknown_hash = network_hash - known_hash | |
print "Unknown hash = {0}".format(unknown_hash) | |
if unknown_hash < 0: | |
unknown_hash = abs(unknown_hash) | |
print "WARNING - negative nethash" | |
name_list.append('Unknown/Minergate') | |
hashrate_list.append(unknown_hash) | |
# Calculate normalized hash rates | |
normalized_list = [x/network_hash for x in hashrate_list] | |
# Setup lists | |
smallpools_names = [] | |
smallpools_hash = [] | |
smallpools_normhash = [] | |
majorpools_names = [] | |
majorpools_hash = [] | |
majorpools_normhash = [] | |
smalllabellist = [] | |
majorlabellist = [] | |
# Print pools and separate to small or major | |
print "Total network hash = " + str(network_hash) | |
for idx, val in enumerate(hashrate_list): | |
print name_list[idx], val | |
if 0.0003 < normalized_list[idx] < 0.03: | |
smallpools_names.append(name_list[idx]) | |
smallpools_hash.append(val) | |
smallpools_normhash.append(normalized_list[idx]) | |
smalllabellist.append("{0} {1:.0f} kh/s".format( | |
name_list[idx], val*1e3)) | |
elif normalized_list[idx] >= 0.03: | |
majorpools_names.append(name_list[idx]) | |
majorpools_hash.append(val) | |
majorpools_normhash.append(normalized_list[idx]) | |
majorlabellist.append("{0} {1:.2f} Mh/s".format( | |
name_list[idx], val)) | |
# Make normalized small hash for plot | |
smallpool_hashtotal = sum(smallpools_hash) | |
smallpool_normtotal = smallpool_hashtotal/network_hash | |
smallpool_smallnorm = [x/smallpool_hashtotal for x in smallpools_hash] | |
# Add small pool total to major pools | |
majorpools_names.append('Small pools (<3.5%)') | |
majorpools_hash.append(smallpool_hashtotal) | |
majorpools_normhash.append(smallpool_normtotal) | |
majorlabellist.append("{0} {1:.2f} Mh/s".format( | |
'Small pools', smallpool_hashtotal)) | |
# Make color list | |
colors = ('b', 'g', 'r', 'c', 'm', 'y', 'w', 'DeepPink', 'ForestGreen') | |
# Reorder slices to try and accomodate tiny pools | |
tmp_norm, tmp_names = (list(t) for t in zip(*sorted(zip(majorpools_normhash, majorlabellist)))) | |
large_norm, large_names = tmp_norm[:len(tmp_norm) / 2], tmp_names[:len(tmp_names) / 2] | |
small_norm, small_names = tmp_norm[len(tmp_norm) / 2:], tmp_names[len(tmp_names) / 2:] | |
reordered_norm = large_norm[::2] + small_norm[::2] + large_norm[1::2] + small_norm[1::2] | |
reordered_names = large_names[::2] + small_names[::2] + large_names[1::2] + small_names[1::2] | |
#Plot and save major pools | |
plt.figure(1, figsize=(12,10)) | |
ax1 = plt.axes([0.25, 0.2, 0.5, 0.5]) | |
pie_wedge_collection = ax1.pie(reordered_norm, | |
# explode=[0.07]*len(majorlabellist), | |
explode=[0.026*(1/(z+0.001)**0.4) for z in reordered_norm], | |
labels=reordered_names, | |
labeldistance=1.07, | |
autopct='%1.0f%%', | |
shadow=True, | |
startangle=90, | |
colors=colors) | |
for pie_wedge in pie_wedge_collection[0]: | |
pie_wedge.set_edgecolor('0.3') | |
for i in pie_wedge_collection[1]: | |
i.set_fontsize('small') | |
plt.title('Monero network hashrate: {0:.1f} Mh/s\nTime recorded:{1}'.format(network_hash, utc_string)) | |
plt.savefig('bigpools.png') | |
plt.close() | |
# Reorder slices to try and accomodate tiny pools | |
tmp_norm, tmp_names = (list(t) for t in zip(*sorted(zip(smallpool_smallnorm, smalllabellist)))) | |
large_norm, large_names = tmp_norm[:len(tmp_norm) / 2], tmp_names[:len(tmp_names) / 2] | |
small_norm, small_names = tmp_norm[len(tmp_norm) / 2:], tmp_names[len(tmp_names) / 2:] | |
reordered_norm = large_norm[::2] + small_norm[::2] + large_norm[1::2] + small_norm[1::2] | |
reordered_names = large_names[::2] + small_names[::2] + large_names[1::2] + small_names[1::2] | |
# Plot and save minor pool figure | |
plt.figure(2, figsize=(12,10)) | |
ax2 = plt.axes([0.25, 0.2, 0.5, 0.5]) | |
p = ax2.pie(reordered_norm, | |
# explode=[0.08]*len(smalllabellist), | |
explode=[0.036*(1/(z+0.001)**0.4) for z in reordered_norm], | |
labels=reordered_names, | |
labeldistance=1.05, | |
autopct='%1.1f%%', | |
shadow=True, | |
# startangle=90, | |
colors=colors) | |
for i in p[1]: | |
i.set_fontsize('small') | |
plt.title('Monero smaller pools (<3%) hash rate: {0:.0f} kh/s'.format(smallpool_hashtotal*1e3)) | |
plt.savefig('smallpools.png') | |
plt.close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
i think it's 2