diff --git a/README.md b/README.md index 48857b8..d158126 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [ ![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) #Status -This project is now in what i'd consider v1 stage as such i dont believe there is much to add to stratum. so as of now this code is in bug fix stage only and should be considered unmaintained. +Riecoin support just implemented, needs testing. #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. @@ -28,15 +28,7 @@ The goal is to make a reliable stratum mining server for a wide range of coins u * Transaction Messaging Support #Donations -* BTC: 18Xg4qP6RUvpeajanKPt5PDvvcqvU2pP6d -* BTE: 8UJLskr8eDYATvYzmaCBw3vbRmeNweT3rW -* DGC: DSBb5KmGWYKMJjxk3rETtvpk9sPqgCCYAw -* LTC: Lg4kXMqPsmMHrGr81LLe8oHpbsMiWiuMSB -* WDC: WeVFgZQsKSKXGak7NJPp9SrcUexghzTPGJ -* Doge: DLtBRYtNCzfiZfcpUeEr8KPvy5k1aR7jca -* SRC: sMP2wHN5H2ik7FQDPjhSzFZUWux75BYZGe -* ARG: AQvXPWVqGzcpH2j2XSRG7X5R9nA3y9D9aQ -* Cryptsy Trade Key: ec13d183e304326ebd41258d6ae7188e303866fe +Please see riecoin.org #Requirements @@ -70,8 +62,8 @@ 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, and #worldcoin channels on freenode. -Although i am willing to provide support through IRC please file issues on the repo. +See riecoin.org +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. @@ -81,7 +73,8 @@ Please research and attempt to debug first. * Original version by Slush0 and ArtForz (original stratum code) * More Features added by GeneralFault, Wadee Womersley, Viperaus, TheSeven and Moopless * Multi Algo, Vardiff, DB and MPOS support done by Ahmed_Bodi, penner42 and Obigal +* Riecoin support by gatra #License -This software is provides AS-IS without any warranties of any kind. Please use at your own risk. +This software is provided 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 e34cd60..9f938fd 100644 --- a/conf/config_sample.py +++ b/conf/config_sample.py @@ -12,17 +12,17 @@ You NEED to set the parameters in BASIC SETTINGS CENTRAL_WALLET = 'set_valid_addresss_in_config!' # Local coin address where money goes COINDAEMON_TRUSTED_HOST = 'localhost' -COINDAEMON_TRUSTED_PORT = 8332 +COINDAEMON_TRUSTED_PORT = 28332 COINDAEMON_TRUSTED_USER = 'user' COINDAEMON_TRUSTED_PASSWORD = 'somepassword' # Coin algorithm is the option used to determine the algorithm used by stratum # This currently works with POW and POS coins # The available options are: -# scrypt, sha256d, scrypt-jane, skeinhash, and quark +# scrypt, sha256d, scrypt-jane, skeinhash, quark and riecoin # If the option does not meet either of these criteria stratum defaults to scrypt # For Coins which support TX Messages please enter yes in the TX selection -COINDAEMON_ALGO = 'scrypt' +COINDAEMON_ALGO = 'riecoin' COINDAEMON_TX = 'no' # ******************** BASIC SETTINGS *************** @@ -30,12 +30,12 @@ COINDAEMON_TX = 'no' # You can have up to 99 #COINDAEMON_TRUSTED_HOST_1 = 'localhost' -#COINDAEMON_TRUSTED_PORT_1 = 8332 +#COINDAEMON_TRUSTED_PORT_1 = 28332 #COINDAEMON_TRUSTED_USER_1 = 'user' #COINDAEMON_TRUSTED_PASSWORD_1 = 'somepassword' #COINDAEMON_TRUSTED_HOST_2 = 'localhost' -#COINDAEMON_TRUSTED_PORT_2 = 8332 +#COINDAEMON_TRUSTED_PORT_2 = 28332 #COINDAEMON_TRUSTED_USER_2 = 'user' #COINDAEMON_TRUSTED_PASSWORD_2 = 'somepassword' @@ -142,7 +142,7 @@ VDIFF_X2_TYPE = True # Powers of 2 e.g. 2,4,8,16,32,64,128,256,512,10 VDIFF_FLOAT = False # Use float difficulty # Pool Target (Base Difficulty) -POOL_TARGET = 32 # Pool-wide difficulty target int >= 1 +POOL_TARGET = 4 # Pool-wide difficulty target int >= 1 # Variable Difficulty Enable VARIABLE_DIFF = True # Master variable difficulty enable diff --git a/lib/block_template.py b/lib/block_template.py index bb67bca..3b8bb06 100644 --- a/lib/block_template.py +++ b/lib/block_template.py @@ -139,8 +139,12 @@ class BlockTemplate(halfnode.CBlock): r = struct.pack(">i", self.nVersion) r += self.prevhash_bin r += util.ser_uint256_be(merkle_root_int) - r += ntime_bin - r += struct.pack(">I", self.nBits) + if settings.COINDAEMON_ALGO == 'riecoin': + r += struct.pack(">I", self.nBits) + r += ntime_bin + else: + r += ntime_bin + r += struct.pack(">I", self.nBits) r += nonce_bin return r diff --git a/lib/config_default.py b/lib/config_default.py index 935748f..815cb75 100755 --- a/lib/config_default.py +++ b/lib/config_default.py @@ -109,7 +109,7 @@ COINDAEMON_TRUSTED_PASSWORD = '***somepassword***' # Until AutoReward Selecting Code has been implemented the below options are us$ # For Reward type there is POW and POS. please ensure you choose the currect ty$ # For SHA256 PoS Coins which support TX Messages please enter yes in the TX sel$ -COINDAEMON_ALGO = 'scrypt' +COINDAEMON_ALGO = 'riecoin' COINDAEMON_Reward = 'POW' COINDAEMON_SHA256_TX = 'yes' diff --git a/lib/halfnode.py b/lib/halfnode.py index eb29c4e..a3cfa13 100644 --- a/lib/halfnode.py +++ b/lib/halfnode.py @@ -239,6 +239,8 @@ class CBlock(object): self.scrypt = None elif settings.COINDAEMON_ALGO == 'quark': self.quark = None + elif settings.COINDAEMON_ALGO == 'riecoin': + self.riecoin = None else: pass if settings.COINDAEMON_Reward == 'POS': self.signature = b"" @@ -248,8 +250,12 @@ class CBlock(object): self.nVersion = struct.unpack(" target: return False diff --git a/lib/template_registry.py b/lib/template_registry.py index ae13a00..de3693c 100644 --- a/lib/template_registry.py +++ b/lib/template_registry.py @@ -154,6 +154,8 @@ class TemplateRegistry(object): diff1 = 0x0000ffff00000000000000000000000000000000000000000000000000000000 elif settings.COINDAEMON_ALGO == 'quark': diff1 = 0x000000ffff000000000000000000000000000000000000000000000000000000 + elif settings.COINDAEMON_ALGO == 'riecoin': + return difficulty; else: diff1 = 0x00000000ffff0000000000000000000000000000000000000000000000000000 @@ -202,15 +204,23 @@ class TemplateRegistry(object): raise SubmitException("Job '%s' not found" % job_id) # Check if ntime looks correct - if len(ntime) != 8: - raise SubmitException("Incorrect size of ntime. Expected 8 chars") + if settings.COINDAEMON_ALGO == 'riecoin': + if len(ntime) != 16: + raise SubmitException("Incorrect size of ntime. Expected 16 chars") + else: + if len(ntime) != 8: + raise SubmitException("Incorrect size of ntime. Expected 8 chars") if not job.check_ntime(int(ntime, 16)): raise SubmitException("Ntime out of range") # Check nonce - if len(nonce) != 8: - raise SubmitException("Incorrect size of nonce. Expected 8 chars") + if settings.COINDAEMON_ALGO == 'riecoin': + if len(nonce) != 64: + raise SubmitException("Incorrect size of nonce. Expected 64 chars") + else: + if len(nonce) != 8: + raise SubmitException("Incorrect size of nonce. Expected 8 chars") # Check for duplicated submit if not job.register_submit(extranonce1_bin, extranonce2, ntime, nonce): @@ -238,7 +248,7 @@ class TemplateRegistry(object): header_bin = job.serialize_header(merkle_root_int, ntime_bin, nonce_bin) # 4. Reverse header and compare it with target of the user - if settings.COINDAEMON_ALGO == 'scrypt': + elif settings.COINDAEMON_ALGO == 'scrypt': hash_bin = ltc_scrypt.getPoWHash(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ])) elif settings.COINDAEMON_ALGO == 'scrypt-jane': hash_bin = yac_scrypt.getPoWHash(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]), int(ntime, 16)) @@ -249,42 +259,62 @@ class TemplateRegistry(object): else: hash_bin = util.doublesha(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ])) - hash_int = util.uint256_from_str(hash_bin) + if settings.COINDAEMON_ALGO == 'riecoin': + # hash_bin already has doublesha + # this is kind of an ugly hack: we use hash_int to store the number of primes + hash_int = util.riecoinPoW( hash_bin, job.target, int(nonce, 16) ) + else: + hash_int = util.uint256_from_str(hash_bin) scrypt_hash_hex = "%064x" % hash_int + header_hex = binascii.hexlify(header_bin) if settings.COINDAEMON_ALGO == 'scrypt' or settings.COINDAEMON_ALGO == 'scrypt-jane': header_hex = header_hex+"000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000" elif settings.COINDAEMON_ALGO == 'quark': header_hex = header_hex+"000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000" + elif settings.COINDAEMON_ALGO == 'riecoin': + header_hex = header_hex+"00000080000000000000000080030000" else: pass + target_user = self.diff_to_target(difficulty) - if hash_int > target_user: - raise SubmitException("Share is above target") - - # Mostly for debugging purposes - target_info = self.diff_to_target(100000) - if hash_int <= target_info: - log.info("Yay, share with diff above 100000") + if settings.COINDAEMON_ALGO == 'riecoin': + if hash_int < target_user: + raise SubmitException("Share does not meet target") + else: + if hash_int > target_user: + raise SubmitException("Share is above target") + # Mostly for debugging purposes + target_info = self.diff_to_target(100000) + if hash_int <= target_info: + log.info("Yay, share with diff above 100000") # Algebra tells us the diff_to_target is the same as hash_to_diff share_diff = int(self.diff_to_target(hash_int)) # 5. Compare hash with target of the network - if hash_int <= job.target: + isBlockCandidate = False + if settings.COINDAEMON_ALGO == 'riecoin': + if hash_int == 6 + isBlockCandidate = True + else: + if hash_int <= job.target: + isBlockCandidate = True + + if isBlockCandidate == True: # Yay! It is block candidate! log.info("We found a block candidate! %s" % scrypt_hash_hex) # Reverse the header and get the potential block hash (for scrypt only) - #if settings.COINDAEMON_ALGO == 'scrypt' or settings.COINDAEMON_ALGO == 'sha256d': - # if settings.COINDAEMON_Reward == 'POW': - block_hash_bin = util.doublesha(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ])) + if settings.COINDAEMON_ALGO == 'riecoin': + block_hash_bin = util.doublesha(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 28) ])) + else: + block_hash_bin = util.doublesha(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ])) block_hash_hex = block_hash_bin[::-1].encode('hex_codec') - #else: block_hash_hex = hash_bin[::-1].encode('hex_codec') - #else: block_hash_hex = hash_bin[::-1].encode('hex_codec') + # 6. Finalize and serialize block object job.finalize(merkle_root_int, extranonce1_bin, extranonce2_bin, int(ntime, 16), int(nonce, 16)) - + if not job.is_valid(): # Should not happen log.exception("FINAL JOB VALIDATION FAILED!(Try enabling/disabling tx messages)") @@ -302,7 +332,10 @@ class TemplateRegistry(object): if settings.SOLUTION_BLOCK_HASH: # Reverse the header and get the potential block hash (for scrypt only) only do this if we want to send in the block hash to the shares table - block_hash_bin = util.doublesha(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ])) + if settings.COINDAEMON_ALGO == 'riecoin': + block_hash_bin = util.doublesha(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 28) ])) + else: + block_hash_bin = util.doublesha(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ])) block_hash_hex = block_hash_bin[::-1].encode('hex_codec') return (header_hex, block_hash_hex, share_diff, None) else: diff --git a/lib/util.py b/lib/util.py index f902b0a..0035d85 100644 --- a/lib/util.py +++ b/lib/util.py @@ -211,6 +211,56 @@ def ser_number(n): s.append(n) return bytes(s) + +def isPrime( n ) + if pow( 2, n-1, n ) == 1: + return True + return False + +def riecoinPoW( hash_bin, diff, nNonce ) + base = 1 << 8 + for i in range(256) + base = base << 1 + base = base | (hash_bin & 1) + hash_bin = hash_bin >> 1 + trailingZeros = diff - 1 - 8 - 256 + if trailingZeros < 16 or trailingZeros > 20000 + return 0 + base = base << trailingZeros + + base += nNonce + primes = 0 + + if (base % 210) != 97: + return 0 + + if !isPrime( base ): + return primes + primes++ + + base += 4 + if !isPrime( base ): + return primes + primes++ + + base += 2 + if isPrime( base ): + primes++ + + base += 4 + if !isPrime( base ): + primes++ + + base += 2 + if !isPrime( base ): + primes++ + + base += 4 + if !isPrime( base ): + primes++ + + return primes + #if settings.COINDAEMON_Reward == 'POW': def script_to_address(addr): d = address_to_pubkeyhash(addr)