Fixing Master (1)

This commit is contained in:
Ahmed Bodiwala 2014-01-05 20:55:21 +00:00
parent 905dcf68fd
commit bf8a01a616
20 changed files with 222 additions and 118 deletions

View File

@ -1,7 +1,7 @@
#Description
Stratum-mining is a pooled mining protocol. It is a replacement for *getwork* based pooling servers by allowing clients to generate work. The stratum protocol is described [here](http://mining.bitcoin.cz/stratum-mining) in full detail.
This is a implementation of stratum-mining for scrypt based coins. It is compatible with *MPOS* as well as *mmcfe*, as it complies with the standards of *pushpool*. The end goal is to build on these standards to come up with a more stable solution.
This is a implementation of stratum-mining for scrypt based coins. It is compatible with *MPOS* as it complies with the standards of *pushpool*. The end goal is to build on these standards to come up with a more stable solution.
The goal is to make a reliable stratum mining server for scrypt based coins. Over time I will develop this to be more feature rich and very stable. If you would like to see a feature please file a feature request.
@ -22,6 +22,7 @@ The goal is to make a reliable stratum mining server for scrypt based coins. Ove
* Adjustable database commit parameters
* Bypass password check for workers
* Proof Of Work and Proof of Stake Coin Support
* Transaction Messaging Support
#Donations
* BTC: 18uj5SzQaYVAPX96JZt1VE4K43m5VeYekP
@ -30,9 +31,9 @@ The goal is to make a reliable stratum mining server for scrypt based coins. Ove
* LTC: LVDbDHPUF13YZQeJE6AtxDwiF2RyNBsmXh
* WDC: WeVFgZQsKSKXGak7NJPp9SrcUexghzTPGJ
* Doge: DLtBRYtNCzfiZfcpUeEr8KPvy5k1aR7jca
#Requirements
*stratum-mining* is built in python. I have been testing it with 2.7.3, but it should work with other versions. The requirements for running the software are below.
* Python 2.7+
* python-twisted
* stratum
@ -60,16 +61,19 @@ Other coins have been known to work with this implementation. I have tested with
The installation of this *stratum-mining* can be found in the Repo Wiki.
#Contact
I am available in the #MPOS, #crypto-expert, #digitalcoin, #bytecoin and #worldcoin channels on freenode. Although i am willing to provide support through IRC please file issues on the repo
I am available in the #MPOS, #crypto-expert, #digitalcoin, and #worldcoin channels on freenode.
Although i am willing to provide support through IRC please file issues on the repo.
issues as a direct result of stratum will be helped with as much as possible
However issues related to a coin daemon's setup and other non stratum issues,
Please research and attempt to debug first.
#Credits
* Original version by Slush0 (original stratum code)
* More Features added by GeneralFault, Wadee Womersley and Moopless
* Scrypt conversion from work done by viperaus
* PoS conversion done by TheSeven
* Modifications to make it more user friendly and easier to setup for multiple coins done by Ahmed_Bodi
* Multi Algo, Vardiff, DB and MPOS support done by Ahmed_Bodi and Obigal
#License
This software is provides AS-IS without any warranties of any kind. Please use at your own risk.

View File

@ -26,7 +26,7 @@ COINDAEMON_TRUSTED_PASSWORD = 'somepassword'
# For SHA256 PoS Coins which support TX Messages please enter yes in the TX selection
COINDAEMON_ALGO = 'scrypt'
COINDAEMON_Reward = 'POW'
COINDAEMON_SHA256_TX = 'no'
COINDAEMON_TX = 'no'
# ******************** BASIC SETTINGS ***************
# Backup Coin Daemon address's (consider having at least 1 backup)
# You can have up to 99
@ -42,6 +42,8 @@ COINDAEMON_SHA256_TX = 'no'
#COINDAEMON_TRUSTED_PASSWORD_2 = 'somepassword'
# ******************** GENERAL SETTINGS ***************
# Set process name of twistd, much more comfortable if you run multiple processes on one machine
STRATUM_MINING_PROCESS_NAME= 'twistd-stratum-mining'
# Enable some verbose debug (logging requests and responses).
DEBUG = False
@ -51,7 +53,7 @@ LOGDIR = 'log/'
# Main application log file.
LOGFILE = None # eg. 'stratum.log'
LOGLEVEL = 'DEBUG'
# Logging Rotation can be enabled with the following settings
# It if not enabled here, you can set up logrotate to rotate the files.
# For built in log rotation set LOG_ROTATION = True and configrue the variables
@ -89,6 +91,7 @@ PASSWORD_SALT = 'some_crazy_string'
# ******************** Database *********************
DATABASE_DRIVER = 'sqlite' # Options: none, sqlite, postgresql or mysql
DATABASE_EXTEND = False
# SQLite
DB_SQLITE_FILE = 'pooldb.sqlite'
@ -103,7 +106,7 @@ DB_MYSQL_HOST = 'localhost'
DB_MYSQL_DBNAME = 'pooldb'
DB_MYSQL_USER = 'pooldb'
DB_MYSQL_PASS = '**empty**'
DB_MYSQL_PORT = 3306
# ******************** Adv. DB Settings *********************
# Don't change these unless you know what you are doing
@ -151,7 +154,7 @@ VARIABLE_DIFF = True # Master variable difficulty enable
# Variable diff tuning variables
#VARDIFF will start at the POOL_TARGET. It can go as low as the VDIFF_MIN and as high as min(VDIFF_MAX or Liteconin's difficulty)
USE_LITECOIN_DIFF = False # Set the maximum difficulty to the litecoin difficulty.
USE_COINDAEMON_DIFF = False # Set the maximum difficulty to the litecoin difficulty.
DIFF_UPDATE_FREQUENCY = 86400 # Update the litecoin difficulty once a day for the VARDIFF maximum
VDIFF_MIN_TARGET = 16 # Minimum Target difficulty
VDIFF_MAX_TARGET = 1024 # Maximum Target difficulty
@ -185,7 +188,11 @@ ENABLE_WORKER_BANNING = True # enable/disable temporary worker banning
WORKER_CACHE_TIME = 600 # How long the worker stats cache is good before we check and refresh
WORKER_BAN_TIME = 300 # How long we temporarily ban worker
INVALID_SHARES_PERCENT = 50 # Allow average invalid shares vary this % before we ban
#Pass scrypt hash to submit block check.
#Use if submit block is returning errors and marking submitted blocks invaild upstream, but the submitted blocks are being a accepted by the coin daemon into the block chain.
BLOCK_CHECK_SCRYPT_HASH = False
# ******************** E-Mail Notification Settings *********************
NOTIFY_EMAIL_TO = '' # Where to send Start/Found block notifications
NOTIFY_EMAIL_TO_DEADMINER = '' # Where to send dead miner notifications

View File

@ -6,6 +6,7 @@ import os, sys
sys.path = [os.path.join(os.getcwd(), 'conf'),os.path.join(os.getcwd(), 'externals', 'stratum-mining-proxy'),] + sys.path
from twisted.internet import defer
from twisted.application.service import Application, IProcess
# Run listening when mining service is ready
on_startup = defer.Deferred()
@ -14,6 +15,7 @@ import stratum
import lib.settings as settings
# Bootstrap Stratum framework
application = stratum.setup(on_startup)
IProcess(application).processName = settings.STRATUM_MINING_PROCESS_NAME
# Load mining service into stratum framework
import mining
@ -35,6 +37,3 @@ Interfaces.set_timestamper(TimestamperInterface())
mining.setup(on_startup)
if settings.GW_ENABLE == True :
from lib.getwork_proxy import GetworkProxy
GetworkProxy(on_startup)

View File

@ -14,6 +14,7 @@ log = lib.logger.get_logger('bitcoin_rpc')
class BitcoinRPC(object):
def __init__(self, host, port, username, password):
log.debug("Got to Bitcoin RPC")
self.bitcoin_url = 'http://%s:%d' % (host, port)
self.credentials = base64.b64encode("%s:%s" % (username, password))
self.headers = {
@ -40,11 +41,11 @@ class BitcoinRPC(object):
}))
@defer.inlineCallbacks
def submitblock(self, block_hex, block_hash_hex):
def submitblock(self, block_hex, hash_hex):
# Try submitblock if that fails, go to getblocktemplate
try:
log.info("Submitting Block with Submit Block ")
log.info([block_hex,])
log.debug("Submitting Block with Submit Block ")
log.debug([block_hex,])
resp = (yield self._call('submitblock', [block_hex,]))
except Exception:
try:
@ -52,11 +53,12 @@ class BitcoinRPC(object):
resp = (yield self._call('getblocktemplate', [{'mode': 'submit', 'data': block_hex}]))
except Exception as e:
log.exception("Both SubmitBlock and GetBlockTemplate failed. Problem Submitting block %s" % str(e))
raise
log.exception("Try Enabling TX Messages in config.py")
raise
if json.loads(resp)['result'] == None:
# make sure the block was created.
defer.returnValue((yield self.blockexists(block_hash_hex)))
defer.returnValue((yield self.blockexists(hash_hex)))
else:
defer.returnValue(False)
@ -90,12 +92,12 @@ class BitcoinRPC(object):
defer.returnValue(json.loads(resp)['result'])
@defer.inlineCallbacks
def blockexists(self, block_hash_hex):
resp = (yield self._call('getblock', [block_hash_hex,]))
if "hash" in json.loads(resp)['result'] and json.loads(resp)['result']['hash'] == block_hash_hex:
log.debug("Block Confirmed: %s" % block_hash_hex)
def blockexists(self, hash_hex):
resp = (yield self._call('getblock', [hash_hex,]))
if "hash" in json.loads(resp)['result'] and json.loads(resp)['result']['hash'] == hash_hex:
log.debug("Block Confirmed: %s" % hash_hex)
defer.returnValue(True)
else:
log.info("Cannot find block for %s" % block_hash_hex)
log.info("Cannot find block for %s" % hash_hex)
defer.returnValue(False)

View File

@ -19,6 +19,7 @@ from lib.bitcoin_rpc import BitcoinRPC
class BitcoinRPCManager(object):
def __init__(self):
log.debug("Got to Bitcoin RPC Manager")
self.conns = {}
self.conns[0] = BitcoinRPC(settings.COINDAEMON_TRUSTED_HOST,
settings.COINDAEMON_TRUSTED_PORT,
@ -88,10 +89,10 @@ class BitcoinRPCManager(object):
except:
self.next_connection()
def submitblock(self, block_hex, block_hash_hex):
def submitblock(self, block_hex, hash_hex):
while True:
try:
return self.conns[self.curr_conn].submitblock(block_hex, block_hash_hex)
return self.conns[self.curr_conn].submitblock(block_hex, hash_hex)
except:
self.next_connection()

View File

@ -6,6 +6,8 @@ import util
import merkletree
import halfnode
from coinbasetx import CoinbaseTransaction
import lib.logger
log = lib.logger.get_logger('block_template')
# Remove dependency to settings, coinbase extras should be
# provided from coinbaser
@ -19,7 +21,7 @@ class BlockTemplate(halfnode.CBlock):
coinbase_transaction_class = CoinbaseTransaction
def __init__(self, timestamper, coinbaser, job_id):
print("Hit Block_template.py")
log.debug("Got To Block_template.py")
super(BlockTemplate, self).__init__()
self.job_id = job_id

View File

@ -17,7 +17,8 @@ class BlockUpdater(object):
'''
def __init__(self, registry, bitcoin_rpc):
self.bitcoin_rpc = bitcoin_rpc
log.debug("Got To Block Updater")
self.bitcoin_rpc = bitcoin_rpc
self.registry = registry
self.clock = None
self.schedule()

View File

@ -13,7 +13,7 @@ class SimpleCoinbaser(object):
for all generated blocks.'''
def __init__(self, bitcoin_rpc, address):
print("hit the coinbaser")
log.debug("Got to the coinbaser")
# Fire Callback when the coinbaser is ready
self.on_load = defer.Deferred()
@ -31,32 +31,53 @@ class SimpleCoinbaser(object):
d.addErrback(self._failure)
def _POW_address_check(self, result):
if result['isvalid'] and result['ismine']:
if result['isvalid'] and result['ismine']:
self.is_valid = True
log.info("Coinbase address '%s' is valid" % self.address)
if not self.on_load.called:
self.on_load.callback(True)
log.info("Coinbase address '%s' is valid" % self.address)
if result['isvalid'] == True:
log.debug("Is Valid = %s" % result['isvalid'])
log.debug("Address = %s " % result['address'])
log.debug("PubKey = %s " % result['pubkey'])
log.debug("Is Compressed = %s " % result['iscompressed'])
log.debug("Account = %s " % result['account'])
self.address = result['address']
if not self.on_load.called:
self.on_load.callback(True)
elif result['isvalid'] and settings.ALLOW_NONLOCAL_WALLET == True :
self.is_valid = True
log.warning("!!! Coinbase address '%s' is valid BUT it is not local" % self.address)
if not self.on_load.called:
self.on_load.callback(True)
else:
self.is_valid = False
log.error("Coinbase address '%s' is NOT valid!" % self.address)
elif result['isvalid'] and settings.ALLOW_NONLOCAL_WALLET == True :
self.is_valid = True
log.warning("!!! Coinbase address '%s' is valid BUT it is not local" % self.address)
if not self.on_load.called:
self.on_load.callback(True)
else:
self.is_valid = False
log.error("Coinbase address '%s' is NOT valid!" % self.address)
def _POS_address_check(self, result):
print(result)
print(result['pubkey'])
self.pubkey = result['pubkey']
print("You're PUBKEY is : ", self.pubkey)
# Fire callback when coinbaser is ready
self.on_load.callback(True)
if result['isvalid'] and result['ismine']:
self.is_valid = True
log.info("Coinbase address '%s' is valid" % self.address)
if result['isvalid'] == True:
log.debug("Is Valid = %s" % result['isvalid'])
log.debug("Address = %s " % result['address'])
log.debug("PubKey = %s " % result['pubkey'])
log.debug("Is Compressed = %s " % result['iscompressed'])
log.debug("Account = %s " % result['account'])
self.pubkey = result['pubkey']
if not self.on_load.called:
self.on_load.callback(True)
elif result['isvalid'] and settings.ALLOW_NONLOCAL_WALLET == True :
self.is_valid = True
log.warning("!!! Coinbase address '%s' is valid BUT it is not local" % self.address)
self.pubkey = result['pubkey']
if not self.on_load.called:
self.on_load.callback(True)
else:
self.is_valid = False
#def on_new_block(self):
# pass

View File

@ -3,6 +3,9 @@ import halfnode
import struct
import util
import settings
import lib.logger
log = lib.logger.get_logger('coinbasetx')
if settings.COINDAEMON_Reward == 'POW':
class CoinbaseTransaction(halfnode.CTransaction):
'''Construct special transaction used for coinbase tx.
@ -15,7 +18,7 @@ if settings.COINDAEMON_Reward == 'POW':
def __init__(self, timestamper, coinbaser, value, flags, height, data):
super(CoinbaseTransaction, self).__init__()
log.debug("Got to CoinBaseTX")
#self.extranonce = 0
if len(self.extranonce_placeholder) != self.extranonce_size:
@ -36,8 +39,8 @@ if settings.COINDAEMON_Reward == 'POW':
tx_out.nValue = value
tx_out.scriptPubKey = coinbaser.get_script_pubkey()
if settings.COINDAEMON_SHA256_TX == 'yes':
self.strTxComment = ""
if settings.COINDAEMON_TX == 'yes':
self.strTxComment = "http://github.com/ahmedbodi/stratum-mining"
self.vin.append(tx_in)
self.vout.append(tx_out)
@ -62,7 +65,7 @@ elif settings.COINDAEMON_Reward == 'POS':
def __init__(self, timestamper, coinbaser, value, flags, height, data, ntime):
super(CoinbaseTransaction, self).__init__()
log.debug("Got to CoinBaseTX")
#self.extranonce = 0
if len(self.extranonce_placeholder) != self.extranonce_size:
@ -85,7 +88,7 @@ elif settings.COINDAEMON_Reward == 'POS':
self.nTime = ntime
if settings.COINDAEMON_SHA256_TX == 'yes':
self.strTxComment = ""
self.strTxComment = "http://github.com/ahmedbodi/stratum-mining"
self.vin.append(tx_in)
self.vout.append(tx_out)
@ -110,7 +113,7 @@ else:
def __init__(self, timestamper, coinbaser, value, flags, height, data, ntime):
super(CoinbaseTransaction, self).__init__()
log.debug("Got to CoinBaseTX")
#self.extranonce = 0
if len(self.extranonce_placeholder) != self.extranonce_size:

View File

@ -1,5 +1,7 @@
import struct
import lib.logger
log = lib.logger.get_logger('extronance')
class ExtranonceCounter(object):
'''Implementation of a counter producing
unique extranonce across all pool instances.
@ -7,7 +9,8 @@ class ExtranonceCounter(object):
but it can be changed at any time without breaking anything.'''
def __init__(self, instance_id):
if instance_id < 0 or instance_id > 31:
log.debug("Got to Extronance Counter")
if instance_id < 0 or instance_id > 31:
raise Exception("Current ExtranonceCounter implementation needs an instance_id in <0, 31>.")
# Last 5 most-significant bits represents instance_id
@ -22,4 +25,4 @@ class ExtranonceCounter(object):
def get_new_bin(self):
self.counter += 1
return struct.pack('>L', self.counter)

View File

@ -16,32 +16,34 @@ from twisted.internet.protocol import Protocol
from util import *
import settings
import lib.logger
log = lib.logger.get_logger('halfnode')
log.debug("Got to Halfnode")
if settings.COINDAEMON_ALGO == 'scrypt':
print("########################################### Loading LTC Scrypt Module #########################################################")
log.debug("########################################### Loading LTC Scrypt Module #########################################################")
import ltc_scrypt
elif settings.COINDAEMON_ALGO == 'quark':
print("########################################### Loading Quark Module #########################################################")
log.debug("########################################### Loading Quark Module #########################################################")
import quark_hash
else:
print("########################################### NOT Loading LTC Scrypt Module ######################################################")
log.debug("########################################### NOT Loading LTC Scrypt Module ######################################################")
pass
if settings.COINDAEMON_Reward == 'POS':
print("########################################### Loading POS Support #########################################################")
log.debug("########################################### Loading POS Support #########################################################")
pass
else:
print("########################################### NOT Loading POS Support ######################################################")
log.debug("########################################### NOT Loading POS Support ######################################################")
pass
if settings.COINDAEMON_SHA256_TX == 'yes':
print("########################################### Loading SHA256 Transaction Message Support #########################################################")
if settings.COINDAEMON_TX == 'yes':
log.debug("########################################### Loading SHA256 Transaction Message Support #########################################################")
pass
else:
print("########################################### NOT Loading SHA256 Transaction Message Support ######################################################")
log.debug("########################################### NOT Loading SHA256 Transaction Message Support ######################################################")
pass
import lib.logger
log = lib.logger.get_logger('halfnode')
MY_VERSION = 31402
MY_SUBVERSION = ".4"
@ -157,7 +159,7 @@ class CTransaction(object):
def __init__(self):
if settings.COINDAEMON_Reward == 'POW':
self.nVersion = 1
if settings.COINDAEMON_SHA256_TX == 'yes':
if settings.COINDAEMON_TX == 'yes':
self.nVersion = 2
self.vin = []
self.vout = []
@ -165,14 +167,14 @@ class CTransaction(object):
self.sha256 = None
elif settings.COINDAEMON_Reward == 'POS':
self.nVersion = 1
if settings.COINDAEMON_SHA256_TX == 'yes':
if settings.COINDAEMON_TX == 'yes':
self.nVersion = 2
self.nTime = 0
self.vin = []
self.vout = []
self.nLockTime = 0
self.sha256 = None
if settings.COINDAEMON_SHA256_TX == 'yes':
if settings.COINDAEMON_TX == 'yes':
self.strTxComment = ""
def deserialize(self, f):
@ -189,7 +191,7 @@ class CTransaction(object):
self.vout = deser_vector(f, CTxOut)
self.nLockTime = struct.unpack("<I", f.read(4))[0]
self.sha256 = None
if settings.COINDAEMON_SHA256_TX == 'yes':
if settings.COINDAEMON_TX == 'yes':
self.strTxComment = deser_string(f)
def serialize(self):
@ -206,7 +208,7 @@ class CTransaction(object):
r += ser_vector(self.vin)
r += ser_vector(self.vout)
r += struct.pack("<I", self.nLockTime)
if settings.COINDAEMON_SHA256_TX == 'yes':
if settings.COINDAEMON_TX == 'yes':
r += ser_string(self.strTxComment)
return r

View File

@ -15,7 +15,7 @@ from lib.exceptions import SubmitException
import lib.logger
log = lib.logger.get_logger('template_registry')
log.debug("Got to Template Registry")
from mining.interfaces import Interfaces
from extranonce_counter import ExtranonceCounter
import lib.settings as settings
@ -63,11 +63,13 @@ class TemplateRegistry(object):
def get_new_extranonce1(self):
'''Generates unique extranonce1 (e.g. for newly
subscribed connection.'''
log.debug("Getting New Extronance")
return self.extranonce_counter.get_new_bin()
def get_last_broadcast_args(self):
'''Returns arguments for mining.notify
from last known template.'''
log.debug("Getting Laat Template")
return self.last_block.broadcast_args
def add_template(self, block,block_height):
@ -135,7 +137,6 @@ class TemplateRegistry(object):
start = Interfaces.timestamper.time()
template = self.block_template_class(Interfaces.timestamper, self.coinbaser, JobIdGenerator.get_new_id())
print("hit template registry")
log.info(template.fill_from_rpc(data))
self.add_template(template,data['height'])
@ -275,11 +276,16 @@ class TemplateRegistry(object):
if not job.is_valid():
# Should not happen
log.error("Final job validation failed!")
log.exception("Final job validation failed!")
# 7. Submit block to the network
serialized = binascii.hexlify(job.serialize())
on_submit = self.bitcoin_rpc.submitblock(serialized, block_hash_hex)
on_submit = self.bitcoin_rpc.
if settings.BLOCK_CHECK_SCRYPT_HASH:
on_submit = self.bitcoin_rpc.submitblock(serialized, scrypt_hash_hex)
else:
on_submit = self.bitcoin_rpc.submitblock(serialized, block_hash_hex)
if on_submit:
self.update_block()

View File

@ -221,5 +221,5 @@ if settings.COINDAEMON_Reward == 'POW':
else:
def script_to_pubkey(key):
if len(key) == 66: key = binascii.unhexlify(key)
if len(key) != 33: raise Exception('invalid pubkey passed to script_to_pubkey')
if len(key) != 33: raise Exception('Invalid Address')
return b'\x21' + key + b'\xac'

View File

@ -31,7 +31,7 @@ class DBInterface():
signal.signal(signal.SIGINT, self.signal_handler)
def signal_handler(self, signal, frame):
print "SIGINT Detected, shutting down"
log.warning("SIGINT Detected, shutting down")
self.do_import(self.dbi, True)
reactor.stop()

View File

@ -12,7 +12,7 @@ class DB_Mysql():
required_settings = ['PASSWORD_SALT', 'DB_MYSQL_HOST',
'DB_MYSQL_USER', 'DB_MYSQL_PASS',
'DB_MYSQL_DBNAME']
'DB_MYSQL_DBNAME', 'DB_MYSQL_PORT']
for setting_name in required_settings:
if not hasattr(settings, setting_name):
@ -26,7 +26,8 @@ class DB_Mysql():
getattr(settings, 'DB_MYSQL_HOST'),
getattr(settings, 'DB_MYSQL_USER'),
getattr(settings, 'DB_MYSQL_PASS'),
getattr(settings, 'DB_MYSQL_DBNAME')
getattr(settings, 'DB_MYSQL_DBNAME'),
getattr(settings, 'DB_MYSQL_PORT')
)
self.dbc = self.dbh.cursor()
self.dbh.autocommit(True)
@ -69,8 +70,10 @@ class DB_Mysql():
checkin_times = {}
total_shares = 0
best_diff = 0
lof.debug(data)
for k, v in enumerate(data):
log.debug(v)
# for database compatibility we are converting our_worker to Y/N format
if v[5]:
v[5] = 'Y'
@ -81,19 +84,21 @@ class DB_Mysql():
"""
INSERT INTO `shares`
(time, rem_host, username, our_result,
upstream_result, reason, solution)
upstream_result, reason, solution, difficulty)
VALUES
(FROM_UNIXTIME(%(time)s), %(host)s,
%(uname)s,
%(lres)s, 'N', %(reason)s, %(solution)s)
%(lres)s, %(result)s, %(reason)s, %(solution)s, %(difficulty)s )
""",
{
"time": v[4],
"host": v[6],
"uname": v[0],
"lres": v[5],
"reason": v[9],
"solution": v[2]
"time": data[4],
"host": data[6],
"uname": data[0],
"lres": data[5],
"result": data[5],
"reason": data[9],
"solution": data[2],
"difficulty": data[3]
}
)
@ -343,5 +348,5 @@ class DB_Mysql():
data = self.dbc.fetchone()
if data[0] <= 0:
raise Exception("There is no shares table. Have you imported the schema?")
raise Exception("There is no shares table. Have you imported the MPOS schema?")

View File

@ -45,13 +45,14 @@ class DB_Mysql_Vardiff(DB_Mysql.DB_Mysql):
VALUES
(FROM_UNIXTIME(%(time)s), %(host)s,
%(uname)s,
%(lres)s, 'N', %(reason)s, %(solution)s, %(difficulty)s)
%(lres)s, %(result)s, %(reason)s, %(solution)s, %(difficulty)s)
""",
{
"time": v[4],
"host": v[6],
"uname": v[0],
"lres": v[5],
"result": data[5],
"reason": v[9],
"solution": v[2],
"difficulty": v[3]

View File

@ -42,36 +42,47 @@ def setup(on_startup):
try:
result = (yield bitcoin_rpc.getblocktemplate())
if isinstance(result, dict):
print(result)
# litecoind implements version 1 of getblocktemplate
if result['version'] >= 1:
break
result = (yield bitcoin_rpc.getinfo())
if isinstance(result,dict):
if 'stake' in result and settings.COINDAEMON_Reward == 'POS':
log.info("CoinD looks to be a POS Coin, Config for POS looks correct")
break
elif 'stake' not in result and settings.COINDAEMON_Reward == 'POW':
log.info("CoinD looks to be a POW Coin, Config looks to be correct")
break
else:
log.error("Wrong Algo Selected, Switch to appropriate POS/POW in config.py!")
reactor.stop()
else:
log.error("Block Version mismatch: %s" % result['version'])
except ConnectionRefusedError, e:
log.error("Connection refused while trying to connect to litecoin (are your COIND_* settings correct?)")
log.error("Connection refused while trying to connect to the coind (are your COIND_* settings correct?)")
reactor.stop()
break
except Exception, e:
print(e)
if isinstance(e[2], str):
print(e[2])
if isinstance(json.loads(e[2])['error']['message'], str):
error = json.loads(e[2])['error']['message']
if error == "Method not found":
log.error("Litecoind does not support getblocktemplate!!! (time to upgrade.)")
reactor.stop()
elif error == "Litecoind is downloading blocks...":
log.error("Litecoind downloading blockchain... will check back in 30 sec")
time.sleep(29)
else:
log.error("Litecoind Error: %s", error)
try:
if isinstance(json.loads(e[2])['error']['message'], str):
error = json.loads(e[2])['error']['message']
if error == "Method not found":
log.error("CoinD does not support getblocktemplate!!! (time to upgrade.)")
reactor.stop()
elif "downloading blocks" in error:
log.error("CoinD downloading blockchain... will check back in 30 sec")
time.sleep(29)
else:
log.error("Coind Error: %s", error)
except ValueError:
log.error("Failed Connect(HTTP 500 or Invalid JSON), Check Username and Password!")
reactor.stop()
time.sleep(1) # If we didn't get a result or the connect failed
log.info('Connected to litecoind - Ready to GO!')
log.info('Connected to the coind - Begining to load Address and Module Checks!')
# Start the coinbaser
coinbaser = SimpleCoinbaser(bitcoin_rpc, getattr(settings, 'CENTRAL_WALLET'))

View File

@ -134,7 +134,7 @@ class BasicShareLimiter(object):
if settings.VDIFF_X2_TYPE:
ddiff = 2
# Don't go above LITECOIN or VDIFF_MAX_TARGET
if settings.USE_LITECOIN_DIFF:
if settings.USE_COINDAEMON_DIFF:
self.update_litecoin_difficulty()
diff_max = min([settings.VDIFF_MAX_TARGET, self.litecoin_diff])
else:
@ -146,7 +146,7 @@ class BasicShareLimiter(object):
if ddiff < 1:
ddiff = 1
# Don't go above LITECOIN or VDIFF_MAX_TARGET
if settings.USE_LITECOIN_DIFF:
if settings.USE_COINDAEMON_DIFF:
self.update_litecoin_difficulty()
diff_max = min([settings.VDIFF_MAX_TARGET, self.litecoin_diff])
else:

View File

@ -30,10 +30,10 @@ class WorkerManagerInterface(object):
def get_user_difficulty(self, worker_name):
wd = dbi.get_user(worker_name)
if len(wd) > 6:
#dbi.update_worker_diff(worker_name, wd[6])
return (True, wd[6])
else:
return (False, settings.POOL_TARGET)
if wd[6] != 0:
return (True, wd[6])
#dbi.update_worker_diff(worker_name, wd[6])
return (False, settings.POOL_TARGET)
def register_work(self, worker_name, job_id, difficulty):
now = Interfaces.timestamper.time()
@ -105,7 +105,13 @@ class Interfaces(object):
share_limiter = None
timestamper = None
template_registry = None
lib.settings = None
@classmethod
def set_settings(cls, settings):
lib.settings.setup()
cls.settings = lib.settings
@classmethod
def set_worker_manager(cls, manager):
cls.worker_manager = manager

View File

@ -7,7 +7,7 @@ from stratum.pubsub import Pubsub
from interfaces import Interfaces
from subscription import MiningSubscription
from lib.exceptions import SubmitException
import json
import lib.logger
log = lib.logger.get_logger('mining')
@ -21,7 +21,37 @@ class MiningService(GenericService):
service_type = 'mining'
service_vendor = 'stratum'
is_default = True
event = 'mining.notify'
@admin
def get_server_stats(self):
serialized = ''
for subscription in Pubsub.iterate_subscribers(self.event):
try:
if subscription != None:
session = subscription.connection_ref().get_session()
session.setdefault('authorized', {})
if session['authorized'].keys():
worker_name = session['authorized'].keys()[0]
difficulty = session['difficulty']
ip = subscription.connection_ref()._get_ip()
serialized += json.dumps({'worker_name': worker_name, 'ip': ip, 'difficulty': difficulty})
else:
pass
except Exception as e:
log.exception("Error getting subscriptions %s" % str(e))
pass
log.debug("Server stats request: %s" % serialized)
return '%s' % serialized
@admin
def refresh_config(self):
settings.setup()
log.info("Updated Config")
return True
@admin
def update_block(self):
'''Connect this RPC call to 'litecoind -blocknotify' for