diff --git a/README.md b/README.md index 559f398..01fd8cf 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/conf/config_sample.py b/conf/config_sample.py index 7ff0905..d90c4e1 100644 --- a/conf/config_sample.py +++ b/conf/config_sample.py @@ -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 diff --git a/launcher.tac b/launcher.tac index dd85b5a..cbcff5d 100644 --- a/launcher.tac +++ b/launcher.tac @@ -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) diff --git a/lib/bitcoin_rpc.py b/lib/bitcoin_rpc.py index 73417c9..cbbf06a 100644 --- a/lib/bitcoin_rpc.py +++ b/lib/bitcoin_rpc.py @@ -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) diff --git a/lib/bitcoin_rpc_manager.py b/lib/bitcoin_rpc_manager.py index 9977e87..54a81ce 100644 --- a/lib/bitcoin_rpc_manager.py +++ b/lib/bitcoin_rpc_manager.py @@ -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() diff --git a/lib/block_template.py b/lib/block_template.py index e30bcf9..d166f42 100644 --- a/lib/block_template.py +++ b/lib/block_template.py @@ -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 diff --git a/lib/block_updater.py b/lib/block_updater.py index 4e76abe..f4f1609 100644 --- a/lib/block_updater.py +++ b/lib/block_updater.py @@ -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() diff --git a/lib/coinbaser.py b/lib/coinbaser.py index 932bdf8..12c5b38 100644 --- a/lib/coinbaser.py +++ b/lib/coinbaser.py @@ -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 diff --git a/lib/coinbasetx.py b/lib/coinbasetx.py index f1fa955..4f3c187 100644 --- a/lib/coinbasetx.py +++ b/lib/coinbasetx.py @@ -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: diff --git a/lib/extranonce_counter.py b/lib/extranonce_counter.py index 19254f4..0537f37 100644 --- a/lib/extranonce_counter.py +++ b/lib/extranonce_counter.py @@ -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) - \ No newline at end of file + diff --git a/lib/halfnode.py b/lib/halfnode.py index 1aa08f5..8cd8db4 100644 --- a/lib/halfnode.py +++ b/lib/halfnode.py @@ -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("= 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')) diff --git a/mining/basic_share_limiter.py b/mining/basic_share_limiter.py index 94c052d..aa8a5ef 100644 --- a/mining/basic_share_limiter.py +++ b/mining/basic_share_limiter.py @@ -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: diff --git a/mining/interfaces.py b/mining/interfaces.py index b3d44f5..b3a42db 100644 --- a/mining/interfaces.py +++ b/mining/interfaces.py @@ -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 diff --git a/mining/service.py b/mining/service.py index 4dbc9bd..3be4adb 100644 --- a/mining/service.py +++ b/mining/service.py @@ -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