diff --git a/lib/bitcoin_rpc.py b/lib/bitcoin_rpc.py index 3023729..a7c8919 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,10 +41,10 @@ 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.debug("Submitting Block with Submit Block ") log.info([block_hex,]) resp = (yield self._call('submitblock', [block_hex,])) except Exception: @@ -53,11 +54,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)) + 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) @@ -83,20 +85,20 @@ class BitcoinRPC(object): @defer.inlineCallbacks def validateaddress(self, address): resp = (yield self._call('validateaddress', [address,])) - defer.returnValue(json.loads(resp)['result']) - + defer.returnValue(json.loads(resp)['result']) + @defer.inlineCallbacks def getdifficulty(self): resp = (yield self._call('getdifficulty', [])) 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..14ac107 100644 --- a/lib/block_template.py +++ b/lib/block_template.py @@ -7,6 +7,10 @@ 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 import settings @@ -19,7 +23,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..5ce42cf 100644 --- a/lib/block_updater.py +++ b/lib/block_updater.py @@ -17,6 +17,7 @@ class BlockUpdater(object): ''' def __init__(self, registry, bitcoin_rpc): + log.debug("Got to Block Updater") self.bitcoin_rpc = bitcoin_rpc self.registry = registry self.clock = None diff --git a/lib/coinbaser.py b/lib/coinbaser.py index 932bdf8..6cde8f9 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 coinbaser") # Fire Callback when the coinbaser is ready self.on_load = defer.Deferred() @@ -31,49 +31,71 @@ class SimpleCoinbaser(object): d.addErrback(self._failure) def _POW_address_check(self, result): - 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("Is Script = %s" % result['isscript']) + log.debug("PubKey = %s " % result['pubkey']) + log.debug("Is Compressed = %s " % result['iscompressed']) + log.debug("Account = %s " % result['account']) + if result['isvalid'] and result['ismine']: + self.is_valid = True + log.info("Wallet address '%s' is valid" % self.address) - if not self.on_load.called: - self.on_load.callback(True) + 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) + elif result['isvalid'] and settings.ALLOW_NONLOCAL_WALLET == True : + self.is_valid = True + log.warning("!!! Wallet address '%s' is valid BUT it is not local" % self.address) - if not self.on_load.called: - self.on_load.callback(True) + 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) - + log.exception("Wallet 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'] == True: + log.debug("Is Valid = %s" % result['isvalid']) + log.debug("Address = %s " % result['address']) + log.debug("Is Script = %s" % result['isscript']) + log.debug("PubKey = %s " % result['pubkey']) + log.debug("Is Compressed = %s " % result['iscompressed']) + log.debug("Account = %s " % result['account']) + if result['isvalid'] and result['ismine']: + self.is_valid = True + log.info("Wallet address '%s' is valid" % self.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("!!! Wallet 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.exception("Wallet address '%s' is NOT valid!" % self.address) + #def on_new_block(self): # pass #def on_new_template(self): # pass def _failure(self, failure): - log.error("Cannot validate Bitcoin address '%s'" % self.address) + log.exception("Cannot validate Wallet address '%s'" % self.address) raise def get_script_pubkey(self): if settings.COINDAEMON_Reward == 'POW': - if not self.is_valid: - self._validate() - raise Exception("Wallet Address is Wrong") + self._validate() return util.script_to_address(self.address) - else: - return util.script_to_pubkey(self.pubkey) + else: return util.script_to_pubkey(self.pubkey) def get_coinbase_data(self): return '' diff --git a/lib/coinbasetx.py b/lib/coinbasetx.py index c999ebc..26beb0a 100644 --- a/lib/coinbasetx.py +++ b/lib/coinbasetx.py @@ -3,6 +3,10 @@ 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 +19,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: @@ -62,7 +66,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: @@ -110,7 +114,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..bb89edb 100644 --- a/lib/extranonce_counter.py +++ b/lib/extranonce_counter.py @@ -1,4 +1,7 @@ import struct +import lib.logger +log = lib.logger.get_logger('extronance') + class ExtranonceCounter(object): '''Implementation of a counter producing @@ -9,7 +12,8 @@ class ExtranonceCounter(object): def __init__(self, instance_id): if instance_id < 0 or instance_id > 31: raise Exception("Current ExtranonceCounter implementation needs an instance_id in <0, 31>.") - + log.debug("Got To Extronance") + # Last 5 most-significant bits represents instance_id # The rest is just an iterator of jobs. self.counter = instance_id << 27 @@ -22,4 +26,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 1399ad7..8cf1654 100644 --- a/lib/halfnode.py +++ b/lib/halfnode.py @@ -14,35 +14,36 @@ from Crypto.Hash import SHA256 from twisted.internet.protocol import Protocol from util import * - import settings -if settings.COINDAEMON_ALGO == 'scrypt': - print("########################################### Loading LTC Scrypt Module #########################################################") - import ltc_scrypt -elif settings.COINDAEMON_ALGO == 'quark': - print("########################################### Loading Quark Module #########################################################") - import quark_hash -else: - print("########################################### NOT Loading LTC Scrypt Module ######################################################") - pass - -if settings.COINDAEMON_Reward == 'POS': - print("########################################### Loading POS Support #########################################################") - pass -else: - print("########################################### NOT Loading POS Support ######################################################") - pass - -if settings.COINDAEMON_TX_MSG == 'yes': - print("########################################### Loading SHA256 Transaction Message Support #########################################################") - print(settings.Tx_Message) - pass -else: - print("########################################### NOT Loading SHA256 Transaction Message Support ######################################################") - pass import lib.logger log = lib.logger.get_logger('halfnode') +log.debug("Got to Halfnode") + +if settings.COINDAEMON_ALGO == 'scrypt': + log.debug("########################################### Loading LTC Scrypt #########################################################") + import ltc_scrypt +elif settings.COINDAEMON_ALGO == 'quark': + log.debug("########################################### Loading Quark Support #########################################################") + import quark_hash +else: + log.debug("########################################### Loading SHA256 Support ######################################################") + pass + +if settings.COINDAEMON_Reward == 'POS': + log.debug("########################################### Loading POS Support #########################################################") + pass +else: + log.debug("########################################### Loading POW Support ######################################################") + pass + +if settings.COINDAEMON_TX_MSG == 'yes': + log.debug("########################################### Loading Transaction Message Support #########################################################") + log.info(settings.Tx_Message) + pass +else: + pass + MY_VERSION = 31402 MY_SUBVERSION = ".4" diff --git a/lib/template_registry.py b/lib/template_registry.py index 141c2cf..e7a0233 100644 --- a/lib/template_registry.py +++ b/lib/template_registry.py @@ -46,7 +46,7 @@ class TemplateRegistry(object): self.extranonce_counter = ExtranonceCounter(instance_id) self.extranonce2_size = block_template_class.coinbase_transaction_class.extranonce_size \ - self.extranonce_counter.get_size() - + log.debug("Got to Template Registry") self.coinbaser = coinbaser self.block_template_class = block_template_class self.bitcoin_rpc = bitcoin_rpc @@ -63,11 +63,13 @@ class TemplateRegistry(object): def get_new_extranonce1(self): '''Generates unique extranonce1 (e.g. for newly subscribed connection.''' + log.debug("Getting Unique 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 arguments needed for mining.notify") 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,15 @@ class TemplateRegistry(object): if not job.is_valid(): # Should not happen - log.error("Final job validation failed!") + log.info("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) + 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() diff --git a/lib/util.py b/lib/util.py index 1b41659..4a823f7 100644 --- a/lib/util.py +++ b/lib/util.py @@ -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' diff --git a/mining/DBInterface.py b/mining/DBInterface.py index 2749166..f494713 100644 --- a/mining/DBInterface.py +++ b/mining/DBInterface.py @@ -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() diff --git a/mining/DB_Mysql.py b/mining/DB_Mysql.py index e1eda17..54730c5 100644 --- a/mining/DB_Mysql.py +++ b/mining/DB_Mysql.py @@ -81,11 +81,11 @@ 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, 'N', %(reason)s, %(solution)s, %(difficulty)s) """, { "time": v[4], @@ -93,7 +93,8 @@ class DB_Mysql(): "uname": v[0], "lres": v[5], "reason": v[9], - "solution": v[2] + "solution": v[2], + "difficulty": v[3] } ) @@ -344,5 +345,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?") diff --git a/mining/__init__.py b/mining/__init__.py index c65a812..110af1b 100644 --- a/mining/__init__.py +++ b/mining/__init__.py @@ -44,11 +44,13 @@ def setup(on_startup): if isinstance(result, dict): # litecoind implements version 1 of getblocktemplate if result['version'] >= 1: - result = (yield bitcoin_rpc.getinfo()) + 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!") @@ -64,19 +66,23 @@ def setup(on_startup): except Exception, e: if isinstance(e[2], str): - 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 aa8a5ef..3e8324f 100644 --- a/mining/basic_share_limiter.py +++ b/mining/basic_share_limiter.py @@ -103,11 +103,11 @@ class BasicShareLimiter(object): # Set up and log our check self.worker_stats[worker_name]['last_rtc'] = ts avg = self.worker_stats[worker_name]['buffer'].avg() - log.info("Checking Retarget for %s (%i) avg. %i target %i+-%i" % (worker_name, current_difficulty, avg, + log.debug("Checking Retarget for %s (%i) avg. %i target %i+-%i" % (worker_name, current_difficulty, avg, self.target, self.variance)) if avg < 1: - log.info("Reseting avg = 1 since it's SOOO low") + log.warning("Reseting avg = 1 since it's SOOO low") avg = 1 # Figure out our Delta-Diff @@ -163,7 +163,7 @@ class BasicShareLimiter(object): new_diff = current_difficulty * ddiff else: new_diff = current_difficulty + ddiff - log.info("Retarget for %s %i old: %i new: %i" % (worker_name, ddiff, current_difficulty, new_diff)) + log.debug("Retarget for %s %i old: %i new: %i" % (worker_name, ddiff, current_difficulty, new_diff)) self.worker_stats[worker_name]['buffer'].clear() session = connection_ref().get_session() @@ -174,6 +174,8 @@ class BasicShareLimiter(object): session['difficulty'] = new_diff connection_ref().rpc('mining.set_difficulty', [new_diff, ], is_notification=True) + log.debug("Notified of New Difficulty") connection_ref().rpc('mining.notify', [work_id, prevhash, coinb1, coinb2, merkle_branch, version, nbits, ntime, False, ], is_notification=True) - dbi.update_worker_diff(worker_name, new_diff) + log.debug("Sent new work") + dbi.update_worker_diff(worker_name, new_diff) diff --git a/mining/interfaces.py b/mining/interfaces.py index 70a73b8..4a1d8c1 100644 --- a/mining/interfaces.py +++ b/mining/interfaces.py @@ -76,7 +76,7 @@ class ShareManagerInterface(object): pass def on_submit_share(self, worker_name, block_header, block_hash, difficulty, timestamp, is_valid, ip, invalid_reason, share_diff): - log.info("%s (%s) %s %s" % (block_hash, share_diff, 'valid' if is_valid else 'INVALID', worker_name)) + log.debug("%s (%s) %s %s" % (block_hash, share_diff, 'valid' if is_valid else 'INVALID', worker_name)) dbi.queue_share([worker_name, block_header, block_hash, difficulty, timestamp, is_valid, ip, self.block_height, self.prev_hash, invalid_reason, share_diff ]) diff --git a/mining/work_log_pruner.py b/mining/work_log_pruner.py index c4b86a3..d245c67 100644 --- a/mining/work_log_pruner.py +++ b/mining/work_log_pruner.py @@ -12,7 +12,7 @@ def _WorkLogPruner_I(wl): if now > userwork[wli][2] + 120: del userwork[wli] pruned += 1 - log.debug('Pruned %d jobs' % (pruned,)) + log.info('Pruned %d jobs' % (pruned,)) def WorkLogPruner(wl): while True: