diff --git a/README.md b/README.md index 2d50e3e..cb9410d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +[ ![Codeship Status for ahmedbodi/php-mpos](https://www.codeship.io/projects/b3003a70-61a3-0131-231e-26f75a0c690d/status?branch=master)](https://www.codeship.io/projects/12274) #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. @@ -33,7 +34,7 @@ The goal is to make a reliable stratum mining server for scrypt based coins. Ove * Doge: DLtBRYtNCzfiZfcpUeEr8KPvy5k1aR7jca * SRC: sMP2wHN5H2ik7FQDPjhSzFZUWux75BYZGe * ARG: AQvXPWVqGzcpH2j2XSRG7X5R9nA3y9D9aQ - +* CryptsyTradeKey: ec13d183e304326ebd41258d6ae7188e303866fe #Requirements @@ -61,6 +62,7 @@ Other coins have been known to work with this implementation. I have tested with * Franko * Quark * Securecoin + #Installation The installation of this *stratum-mining* can be found in the Repo Wiki. @@ -68,16 +70,10 @@ The installation of this *stratum-mining* can be found in the Repo Wiki. #Contact 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. -<<<<<<< HEAD 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. -======= -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) diff --git a/TODO b/TODO new file mode 100644 index 0000000..7c4b1f1 --- /dev/null +++ b/TODO @@ -0,0 +1,2 @@ +1) Flush shares on block find +2) Add Autoloading of databases diff --git a/conf/config_sample.py b/conf/config_sample.py index 85d29d2..c3ba8bd 100644 --- a/conf/config_sample.py +++ b/conf/config_sample.py @@ -21,11 +21,8 @@ COINDAEMON_TRUSTED_PASSWORD = 'somepassword' # The available options are: # scrypt, sha256d, scrypt-jane and quark # If the option does not meet either of these criteria stratum defaults to scrypt -# Until AutoReward Selecting Code has been implemented the below options are used to select the type of coin -# For Reward type there is POW and POS. please ensure you choose the currect type. # For Coins which support TX Messages please enter yes in the TX selection COINDAEMON_ALGO = 'scrypt' -COINDAEMON_Reward = 'POW' COINDAEMON_TX = 'no' # ******************** BASIC SETTINGS *************** # Backup Coin Daemon address's (consider having at least 1 backup) diff --git a/lib/block_template.py b/lib/block_template.py index 4e00675..9a55f50 100644 --- a/lib/block_template.py +++ b/lib/block_template.py @@ -5,6 +5,8 @@ import struct import util import merkletree import halfnode +from coinbasetx import CoinbaseTransactionPOW +from coinbasetx import CoinbaseTransactionPOS from coinbasetx import CoinbaseTransaction import lib.logger log = lib.logger.get_logger('block_template') @@ -55,10 +57,10 @@ class BlockTemplate(halfnode.CBlock): txhashes = [None] + [ util.ser_uint256(int(t['hash'], 16)) for t in data['transactions'] ] mt = merkletree.MerkleTree(txhashes) if settings.COINDAEMON_Reward == 'POW': - coinbase = self.coinbase_transaction_class(self.timestamper, self.coinbaser, data['coinbasevalue'], data['coinbaseaux']['flags'], data['height'], + coinbase = CoinbaseTransactionPOW(self.timestamper, self.coinbaser, data['coinbasevalue'], data['coinbaseaux']['flags'], data['height'], settings.COINBASE_EXTRAS) else: - coinbase = self.coinbase_transaction_class(self.timestamper, self.coinbaser, data['coinbasevalue'], data['coinbaseaux']['flags'], data['height'], + coinbase = CoinbaseTransactionPOS(self.timestamper, self.coinbaser, data['coinbasevalue'], data['coinbaseaux']['flags'], data['height'], settings.COINBASE_EXTRAS, data['curtime']) self.height = data['height'] diff --git a/lib/coinbasetx.py b/lib/coinbasetx.py index 4f3c187..905582b 100644 --- a/lib/coinbasetx.py +++ b/lib/coinbasetx.py @@ -6,8 +6,8 @@ import settings import lib.logger log = lib.logger.get_logger('coinbasetx') -if settings.COINDAEMON_Reward == 'POW': - class CoinbaseTransaction(halfnode.CTransaction): +#if settings.COINDAEMON_Reward == 'POW': +class CoinbaseTransactionPOW(halfnode.CTransaction): '''Construct special transaction used for coinbase tx. It also implements quick serialization using pre-cached scriptSig template.''' @@ -17,8 +17,8 @@ if settings.COINDAEMON_Reward == 'POW': extranonce_size = struct.calcsize(extranonce_type) def __init__(self, timestamper, coinbaser, value, flags, height, data): - super(CoinbaseTransaction, self).__init__() - log.debug("Got to CoinBaseTX") + super(CoinbaseTransactionPOW, self).__init__() + log.debug("Got to CoinBaseTX") #self.extranonce = 0 if len(self.extranonce_placeholder) != self.extranonce_size: @@ -45,7 +45,7 @@ if settings.COINDAEMON_Reward == 'POW': self.vout.append(tx_out) # Two parts of serialized coinbase, just put part1 + extranonce + part2 to have final serialized tx - self._serialized = super(CoinbaseTransaction, self).serialize().split(self.extranonce_placeholder) + self._serialized = super(CoinbaseTransactionPOW, self).serialize().split(self.extranonce_placeholder) def set_extranonce(self, extranonce): if len(extranonce) != self.extranonce_size: @@ -53,8 +53,56 @@ if settings.COINDAEMON_Reward == 'POW': (part1, part2) = self.vin[0]._scriptSig_template self.vin[0].scriptSig = part1 + extranonce + part2 -elif settings.COINDAEMON_Reward == 'POS': - class CoinbaseTransaction(halfnode.CTransaction): +#elif settings.COINDAEMON_Reward == 'POS': +class CoinbaseTransactionPOS(halfnode.CTransaction): + '''Construct special transaction used for coinbase tx. + It also implements quick serialization using pre-cached + scriptSig template.''' + + extranonce_type = '>Q' + extranonce_placeholder = struct.pack(extranonce_type, int('f000000ff111111f', 16)) + extranonce_size = struct.calcsize(extranonce_type) + + def __init__(self, timestamper, coinbaser, value, flags, height, data, ntime): + super(CoinbaseTransactionPOS, self).__init__() + log.debug("Got to CoinBaseTX") + #self.extranonce = 0 + + if len(self.extranonce_placeholder) != self.extranonce_size: + raise Exception("Extranonce placeholder don't match expected length!") + + tx_in = halfnode.CTxIn() + tx_in.prevout.hash = 0L + tx_in.prevout.n = 2**32-1 + tx_in._scriptSig_template = ( + util.ser_number(height) + binascii.unhexlify(flags) + util.ser_number(int(timestamper.time())) + \ + chr(self.extranonce_size), + util.ser_string(coinbaser.get_coinbase_data() + data) + ) + + tx_in.scriptSig = tx_in._scriptSig_template[0] + self.extranonce_placeholder + tx_in._scriptSig_template[1] + + tx_out = halfnode.CTxOut() + tx_out.nValue = value + tx_out.scriptPubKey = coinbaser.get_script_pubkey() + + self.nTime = ntime + if settings.COINDAEMON_SHA256_TX == 'yes': + self.strTxComment = "http://github.com/ahmedbodi/stratum-mining" + self.vin.append(tx_in) + self.vout.append(tx_out) + + # Two parts of serialized coinbase, just put part1 + extranonce + part2 to have final serialized tx + self._serialized = super(CoinbaseTransactionPOS, self).serialize().split(self.extranonce_placeholder) + + def set_extranonce(self, extranonce): + if len(extranonce) != self.extranonce_size: + raise Exception("Incorrect extranonce size") + + (part1, part2) = self.vin[0]._scriptSig_template + self.vin[0].scriptSig = part1 + extranonce + part2 +#else: +class CoinbaseTransaction(halfnode.CTransaction): '''Construct special transaction used for coinbase tx. It also implements quick serialization using pre-cached scriptSig template.''' @@ -86,54 +134,6 @@ elif settings.COINDAEMON_Reward == 'POS': tx_out.nValue = value tx_out.scriptPubKey = coinbaser.get_script_pubkey() - self.nTime = ntime - if settings.COINDAEMON_SHA256_TX == 'yes': - self.strTxComment = "http://github.com/ahmedbodi/stratum-mining" - self.vin.append(tx_in) - self.vout.append(tx_out) - - # Two parts of serialized coinbase, just put part1 + extranonce + part2 to have final serialized tx - self._serialized = super(CoinbaseTransaction, self).serialize().split(self.extranonce_placeholder) - - def set_extranonce(self, extranonce): - if len(extranonce) != self.extranonce_size: - raise Exception("Incorrect extranonce size") - - (part1, part2) = self.vin[0]._scriptSig_template - self.vin[0].scriptSig = part1 + extranonce + part2 -else: - class CoinbaseTransaction(halfnode.CTransaction): - '''Construct special transaction used for coinbase tx. - It also implements quick serialization using pre-cached - scriptSig template.''' - - extranonce_type = '>Q' - extranonce_placeholder = struct.pack(extranonce_type, int('f000000ff111111f', 16)) - extranonce_size = struct.calcsize(extranonce_type) - - 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: - raise Exception("Extranonce placeholder don't match expected length!") - - tx_in = halfnode.CTxIn() - tx_in.prevout.hash = 0L - tx_in.prevout.n = 2**32-1 - tx_in._scriptSig_template = ( - util.ser_number(height) + binascii.unhexlify(flags) + util.ser_number(int(timestamper.time())) + \ - chr(self.extranonce_size), - util.ser_string(coinbaser.get_coinbase_data() + data) - ) - - tx_in.scriptSig = tx_in._scriptSig_template[0] + self.extranonce_placeholder + tx_in._scriptSig_template[1] - - tx_out = halfnode.CTxOut() - tx_out.nValue = value - tx_out.scriptPubKey = coinbaser.get_script_pubkey() - self.nTime = ntime self.vin.append(tx_in) self.vout.append(tx_out) diff --git a/lib/halfnode.py b/lib/halfnode.py index 2642be1..9975e34 100644 --- a/lib/halfnode.py +++ b/lib/halfnode.py @@ -21,27 +21,27 @@ log = lib.logger.get_logger('halfnode') log.debug("Got to Halfnode") if settings.COINDAEMON_ALGO == 'scrypt': - log.debug("########################################### Loading LTC Scrypt #########################################################") - import ltc_scrypt + log.debug("########################################### Loading LTC Scrypt #########################################################") + import ltc_scrypt elif settings.COINDAEMON_ALGO == 'quark': - log.debug("########################################### Loading Quark Support #########################################################") - import quark_hash + log.debug("########################################### Loading Quark Support #########################################################") + import quark_hash else: - log.debug("########################################### Loading SHA256 Support ######################################################") + log.debug("########################################### Loading SHA256 Support ######################################################") -if settings.COINDAEMON_Reward == 'POS': - log.debug("########################################### Loading POS Support #########################################################") - pass -else: - log.debug("########################################### Loading POW Support ######################################################") - pass +#if settings.COINDAEMON_Reward == 'POS': +# log.debug("########################################### Loading POS Support #########################################################") +# pass +#else: +# log.debug("########################################### Loading POW Support ######################################################") +# pass if settings.COINDAEMON_TX == 'yes': - log.debug("########################################### Loading SHA256 Transaction Message Support #########################################################") - pass + log.debug("########################################### Loading SHA256 Transaction Message Support #########################################################") + pass else: - log.debug("########################################### NOT Loading SHA256 Transaction Message Support ######################################################") - pass + log.debug("########################################### NOT Loading SHA256 Transaction Message Support ######################################################") + pass MY_VERSION = 31402 diff --git a/lib/util.py b/lib/util.py index 4a823f7..4e93fec 100644 --- a/lib/util.py +++ b/lib/util.py @@ -211,15 +211,15 @@ def ser_number(n): s.append(n) return bytes(s) -if settings.COINDAEMON_Reward == 'POW': - def script_to_address(addr): - d = address_to_pubkeyhash(addr) - if not d: - raise ValueError('invalid address') - (ver, pubkeyhash) = d - return b'\x76\xa9\x14' + pubkeyhash + b'\x88\xac' -else: - def script_to_pubkey(key): - if len(key) == 66: key = binascii.unhexlify(key) - if len(key) != 33: raise Exception('Invalid Address') - return b'\x21' + key + b'\xac' +#if settings.COINDAEMON_Reward == 'POW': +def script_to_address(addr): + d = address_to_pubkeyhash(addr) + if not d: + raise ValueError('invalid address') + (ver, pubkeyhash) = d + return b'\x76\xa9\x14' + pubkeyhash + b'\x88\xac' +#else: +def script_to_pubkey(key): + if len(key) == 66: key = binascii.unhexlify(key) + if len(key) != 33: raise Exception('Invalid Address') + return b'\x21' + key + b'\xac' diff --git a/mining/__init__.py b/mining/__init__.py index 110af1b..abb49b9 100644 --- a/mining/__init__.py +++ b/mining/__init__.py @@ -44,17 +44,16 @@ def setup(on_startup): if isinstance(result, dict): # litecoind implements version 1 of getblocktemplate if result['version'] >= 1: - 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() + result = (yield bitcoin_rpc.getdifficulty()) + if isinstance(result,dict): + if 'proof-of-stake' in result: + settings.COINDAEMON_Reward = 'POS' + log.info("Coin detected as POS") + break; + else: + settings.COINDAEMON_Reward = 'POW' + log.info("Coin detected as POW") + break; else: log.error("Block Version mismatch: %s" % result['version']) diff --git a/update_submodules b/update_submodules index a57cd81..3e50b55 100755 --- a/update_submodules +++ b/update_submodules @@ -1,3 +1,4 @@ #!/bin/sh - +git submodule init +git submodule update git submodule foreach git pull origin master