Compare commits

..

10 Commits

Author SHA1 Message Date
ahmedbodi
094f8d464d Merge pull request #2 from ahmedbodi/master
Cleanup
2014-02-27 11:46:45 +00:00
ahmedbodi
e15f45ac95 Merge pull request #1 from Crypto-Expert/maxcoin
Maxcoin
2014-02-27 11:45:54 +00:00
ahmedbodi
2ebb24bac6 MaxCoin Main Fixes 2014-02-27 11:17:34 +00:00
ahmedbodi
2ed1bec0b4 MaxCoin Main Fixes 2014-02-27 11:11:31 +00:00
ahmedbodi
759532479f MaxCoin Main Fixes 2014-02-27 11:04:37 +00:00
ahmedbodi
098c99c3a1 Update bitcoin_rpc.py 2014-02-08 16:59:37 +00:00
ahmedbodi
e9d8e34ab4 MaxCoin 2014-02-08 15:47:47 +00:00
ahmedbodi
f5ee1f0b69 Update template_registry.py 2014-02-08 15:39:39 +00:00
ahmedbodi
5eb505331f MaxCoin 2014-02-08 15:38:13 +00:00
root
3c4f9d4537 Added MaxCoin Hash 2014-02-08 16:18:53 +01:00
19 changed files with 229 additions and 507 deletions

1
.gitignore vendored
View File

@ -2,4 +2,3 @@
conf/config.py
*.log
LOG
*.bak

3
.gitmodules vendored
View File

@ -10,3 +10,6 @@
[submodule "externals/quarkcoin-hash"]
path = externals/quarkcoin-hash
url = https://github.com/Neisklar/quarkcoin-hash-python
[submodule "externals/maxcoin-hash-python"]
path = externals/maxcoin-hash-python
url = https://github.com/Prydie/maxcoin-hash-python

View File

@ -1,9 +0,0 @@
language: python
python:
- "2.6"
- "2.7"
- "3.2"
- "3.3"
# command to install dependencies
install:
- "pip install -r requirements.txt"

View File

@ -1,4 +1,5 @@
# Description
[ ![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.
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.
@ -7,7 +8,7 @@ The goal is to make a reliable stratum mining server for a wide range of coins u
**NOTE:** This fork is still in development. Many features may be broken. Please report any broken features or issues.
# Features
#Features
* Stratum Mining Pool
* Solved Block Confirmation
@ -23,14 +24,25 @@ The goal is to make a reliable stratum mining server for a wide range of coins u
* Proof Of Work and Proof of Stake Coin Support
* Transaction Messaging Support
#Donations
* BTC: 18Xg4qP6RUvpeajanKPt5PDvvcqvU2pP6d
* BTE: 8UJLskr8eDYATvYzmaCBw3vbRmeNweT3rW
* DGC: DSBb5KmGWYKMJjxk3rETtvpk9sPqgCCYAw
* LTC: Lg4kXMqPsmMHrGr81LLe8oHpbsMiWiuMSB
* WDC: WeVFgZQsKSKXGak7NJPp9SrcUexghzTPGJ
* Doge: DLtBRYtNCzfiZfcpUeEr8KPvy5k1aR7jca
* SRC: sMP2wHN5H2ik7FQDPjhSzFZUWux75BYZGe
* ARG: AQvXPWVqGzcpH2j2XSRG7X5R9nA3y9D9aQ
* Cryptsy Trade Key: ec13d183e304326ebd41258d6ae7188e303866fe
# Requirements
#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
* MySQL Server
* CoinD's
* SHA256 or Scrypt CoinDaemon
Other coins have been known to work with this implementation. I have tested with the following coins, but there may be many others that work.
@ -50,17 +62,23 @@ Other coins have been known to work with this implementation. I have tested with
* Quark
* Securecoin
# Installation
#Installation
The installation of this *stratum-mining* can be found in the Repo Wiki.
# Credits
#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.
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 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 implemented by gatra
# License
This software is provided AS-IS without any warranties of any kind. Please use at your own risk.
#License
This software is provides AS-IS without any warranties of any kind. Please use at your own risk.

View File

@ -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 = 28332
COINDAEMON_TRUSTED_PORT = 8332
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, quark and riecoin
# scrypt, sha256d, scrypt-jane, skeinhash, and quark
# 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 = 'riecoin'
COINDAEMON_ALGO = 'scrypt'
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 = 28332
#COINDAEMON_TRUSTED_PORT_1 = 8332
#COINDAEMON_TRUSTED_USER_1 = 'user'
#COINDAEMON_TRUSTED_PASSWORD_1 = 'somepassword'
#COINDAEMON_TRUSTED_HOST_2 = 'localhost'
#COINDAEMON_TRUSTED_PORT_2 = 28332
#COINDAEMON_TRUSTED_PORT_2 = 8332
#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 = 4 # Pool-wide difficulty target int >= 1
POOL_TARGET = 32 # Pool-wide difficulty target int >= 1
# Variable Difficulty Enable
VARIABLE_DIFF = True # Master variable difficulty enable

1
externals/maxcoin-hash-python vendored Submodule

@ -0,0 +1 @@
Subproject commit 30cfcd105ae2914ae12b750ae7471e27f79c28ed

View File

@ -3,7 +3,7 @@
# Add conf directory to python path.
# Configuration file is standard python module.
import os, sys
sys.path = [os.path.join(os.getcwd(), 'conf'),os.path.join(os.getcwd(), '.'),os.path.join(os.getcwd(), 'externals', 'stratum-mining-proxy'),] + sys.path
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

View File

@ -34,6 +34,8 @@ class BitcoinRPC(object):
)
def _call(self, method, params):
#log.debug("RPC Call: %s" % json.dumps({'jsonrpc': '2.0', 'method':
#method,'params': params,'id': '1'}))
return self._call_raw(json.dumps({
'jsonrpc': '2.0',
'method': method,
@ -141,16 +143,12 @@ class BitcoinRPC(object):
@defer.inlineCallbacks
def prevhash(self):
resp = (yield self._call('getwork', []))
try:
resp = (yield self._call('getblocktemplate', [{}]))
defer.returnValue(json.loads(resp)['result']['previousblockhash'])
defer.returnValue(json.loads(resp)['result']['data'][8:72])
except Exception as e:
if (str(e) == "500 Internal Server Error"):
resp = (yield self._call('getblocktemplate', []))
defer.returnValue(json.loads(resp)['result']['previousblockhash'])
else:
log.exception("Cannot decode prevhash %s" % str(e))
raise
log.exception("Cannot decode prevhash %s" % str(e))
raise
@defer.inlineCallbacks
def validateaddress(self, address):

View File

@ -69,7 +69,6 @@ class BlockTemplate(halfnode.CBlock):
self.nVersion = data['version']
self.hashPrevBlock = int(data['previousblockhash'], 16)
self.nBits = int(data['bits'], 16)
self.hashMerkleRoot = 0
self.nTime = 0
self.nNonce = 0
@ -140,12 +139,8 @@ class BlockTemplate(halfnode.CBlock):
r = struct.pack(">i", self.nVersion)
r += self.prevhash_bin
r += util.ser_uint256_be(merkle_root_int)
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 += ntime_bin
r += struct.pack(">I", self.nBits)
r += nonce_bin
return r

View File

@ -40,7 +40,7 @@ class CoinbaseTransactionPOW(halfnode.CTransaction):
tx_out.scriptPubKey = coinbaser.get_script_pubkey()
if settings.COINDAEMON_TX == 'yes':
self.strTxComment = "RanchiMall mining"
self.strTxComment = "http://github.com/ahmedbodi/stratum-mining"
self.vin.append(tx_in)
self.vout.append(tx_out)
@ -88,7 +88,7 @@ class CoinbaseTransactionPOS(halfnode.CTransaction):
self.nTime = ntime
if settings.COINDAEMON_SHA256_TX == 'yes':
self.strTxComment = "RanchiMall mining"
self.strTxComment = "http://github.com/ahmedbodi/stratum-mining"
self.vin.append(tx_in)
self.vout.append(tx_out)

View File

@ -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 = 'riecoin'
COINDAEMON_ALGO = 'scrypt'
COINDAEMON_Reward = 'POW'
COINDAEMON_SHA256_TX = 'yes'

View File

@ -26,16 +26,15 @@ if settings.COINDAEMON_ALGO == 'scrypt':
elif settings.COINDAEMON_ALGO == 'quark':
log.debug("########################################### Loading Quark Support #########################################################")
import quark_hash
elif settings.COINDAEMON_ALGO == 'max':
log.debug("########################################### Loading Max Support #########################################################")
import max_hash
from sha3 import sha3_256
elif settings.COINDAEMON_ALGO == 'keccak':
import sha3
else:
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_TX == 'yes':
log.debug("########################################### Loading SHA256 Transaction Message Support #########################################################")
pass
@ -156,6 +155,8 @@ class CTxOut(object):
class CTransaction(object):
def __init__(self):
if settings.COINDAEMON_ALGO == 'max':
self.sha3 = None
if settings.COINDAEMON_Reward == 'POW':
self.nVersion = 1
if settings.COINDAEMON_TX == 'yes':
@ -239,8 +240,10 @@ class CBlock(object):
self.scrypt = None
elif settings.COINDAEMON_ALGO == 'quark':
self.quark = None
elif settings.COINDAEMON_ALGO == 'riecoin':
self.riecoin = None
elif settings.COINDAEMON_ALGO == 'max':
self.max = None
elif settings.COINDAEMON_ALGO == 'keccak':
self.sha3 = None
else: pass
if settings.COINDAEMON_Reward == 'POS':
self.signature = b""
@ -250,14 +253,9 @@ class CBlock(object):
self.nVersion = struct.unpack("<i", f.read(4))[0]
self.hashPrevBlock = deser_uint256(f)
self.hashMerkleRoot = deser_uint256(f)
if settings.COINDAEMON_ALGO == 'riecoin':
self.nBits = struct.unpack("<I", f.read(4))[0]
self.nTime = struct.unpack("<II", f.read(8))[0]
self.nNonce = struct.unpack("<IIIIIIII", f.read(32))[0]
else:
self.nTime = struct.unpack("<I", f.read(4))[0]
self.nBits = struct.unpack("<I", f.read(4))[0]
self.nNonce = struct.unpack("<I", f.read(4))[0]
self.nTime = struct.unpack("<I", f.read(4))[0]
self.nBits = struct.unpack("<I", f.read(4))[0]
self.nNonce = struct.unpack("<I", f.read(4))[0]
self.vtx = deser_vector(f, CTransaction)
if settings.COINDAEMON_Reward == 'POS':
self.signature = deser_string(f)
@ -268,14 +266,9 @@ class CBlock(object):
r.append(struct.pack("<i", self.nVersion))
r.append(ser_uint256(self.hashPrevBlock))
r.append(ser_uint256(self.hashMerkleRoot))
if settings.COINDAEMON_ALGO == 'riecoin':
r.append(struct.pack("<I", self.nBits))
r.append(struct.pack("<Q", self.nTime))
r.append(ser_uint256(self.nNonce))
else:
r.append(struct.pack("<I", self.nTime))
r.append(struct.pack("<I", self.nBits))
r.append(struct.pack("<I", self.nNonce))
r.append(struct.pack("<I", self.nTime))
r.append(struct.pack("<I", self.nBits))
r.append(struct.pack("<I", self.nNonce))
r.append(ser_vector(self.vtx))
if settings.COINDAEMON_Reward == 'POS':
r.append(ser_string(self.signature))
@ -306,18 +299,36 @@ class CBlock(object):
r.append(struct.pack("<I", self.nNonce))
self.quark = uint256_from_str(quark_hash.getPoWHash(''.join(r)))
return self.quark
elif settings.COINDAEMON_ALGO == 'riecoin':
def calc_riecoin(self):
if self.riecoin is None:
elif settings.COINDAEMON_ALGO == 'max':
def calc_max(self):
if self.max is None:
r = []
r.append(struct.pack("<i", self.nVersion))
r.append(ser_uint256(self.hashPrevBlock))
r.append(ser_uint256(self.hashMerkleRoot))
r.append(struct.pack("<I", self.nTime))
r.append(struct.pack("<I", self.nBits))
r.append(struct.pack("<Q", self.nTime))
sha256 = uint256_from_str(SHA256.new(SHA256.new(''.join(r)).digest()).digest())
self.riecoin = riecoinPoW( sha256, uint256_from_compact(self.nBits), self.nNonce )
return self.riecoin
r.append(struct.pack("<I", self.nNonce))
self.max = uint256_from_str(sha3_256(''.join(r)).digest())
return self.max
elif settings.COINDAEMON_ALGO == 'keccak':
def calc_sha3(self):
if self.sha3 is None:
r = []
r.append(struct.pack("<i", self.nVersion))
r.append(ser_uint256(self.hashPrevBlock))
r.append(ser_uint256(self.hashMerkleRoot))
r.append(struct.pack("<I", self.nTime))
r.append(struct.pack("<I", self.nBits))
r.append(struct.pack("<I", self.nNonce))
s = sha3.SHA3256()
s.update(''.join(r) + str(self.nTime))
# hash_bin_temp = s.hexdigest()
# s = sha3.SHA3256()
# s.update(hash_bin_temp)
block_hash_bin = s.hexdigest()
self.sha3 = uint256_from_str(block_hash_bin)
return self.sha3
else:
def calc_sha256(self):
if self.sha256 is None:
@ -333,29 +344,31 @@ class CBlock(object):
def is_valid(self):
if settings.COINDAEMON_ALGO == 'riecoin':
self.calc_riecoin()
elif settings.COINDAEMON_ALGO == 'scrypt':
if settings.COINDAEMON_ALGO == 'scrypt':
self.calc_scrypt()
elif settings.COINDAEMON_ALGO == 'quark':
self.calc_quark()
elif settings.COINDAEMON_ALGO == 'max':
self.calc_max()
elif settings.COINDAEMON_ALGO == 'keccak':
self.calc_sha3()
else:
self.calc_sha256()
if settings.COINDAEMON_ALGO == 'riecoin':
target = settings.POOL_TARGET
else:
target = uint256_from_compact(self.nBits)
target = uint256_from_compact(self.nBits)
if settings.COINDAEMON_ALGO == 'riecoin':
if self.riecoin < target:
return False
if settings.COINDAEMON_ALGO == 'scrypt':
if self.scrypt > target:
return False
elif settings.COINDAEMON_ALGO == 'quark':
if self.quark > target:
return False
elif settings.COINDAEMON_ALGO == 'max':
if self.max > target:
return False
elif settings.COINDAEMON_ALGO == 'sha3':
if self.sha3 > target:
return False
else:
if self.sha256 > target:
return False

View File

@ -3,18 +3,24 @@ import binascii
import util
import StringIO
import settings
from hashlib import sha256
if settings.COINDAEMON_ALGO == 'scrypt':
import ltc_scrypt
elif settings.COINDAEMON_ALGO == 'scrypt-jane':
import yac_scrypt
elif settings.COINDAEMON_ALGO == 'quark':
import quark_hash
elif settings.COINDAEMON_ALGO == 'max':
import max_hash
from sha3 import sha3_256
elif settings.COINDAEMON_ALGO == 'skeinhash':
import skeinhash
elif settings.COINDAEMON_ALGO == 'keccak':
import sha3
else: pass
from twisted.internet import defer
from lib.exceptions import SubmitException
import lib.logger
log = lib.logger.get_logger('template_registry')
log.debug("Got to Template Registry")
@ -22,7 +28,6 @@ from mining.interfaces import Interfaces
from extranonce_counter import ExtranonceCounter
import lib.settings as settings
class JobIdGenerator(object):
'''Generate pseudo-unique job_id. It does not need to be absolutely unique,
because pool sends "clean_jobs" flag to clients and they should drop all previous jobs.'''
@ -65,7 +70,7 @@ class TemplateRegistry(object):
def get_new_extranonce1(self):
'''Generates unique extranonce1 (e.g. for newly
subscribed connection.'''
log.debug("Getting Unique Extranonce")
log.debug("Getting Unique Extronance")
return self.extranonce_counter.get_new_bin()
def get_last_broadcast_args(self):
@ -126,8 +131,8 @@ class TemplateRegistry(object):
self.update_in_progress = True
self.last_update = Interfaces.timestamper.time()
d = self.bitcoin_rpc.getblocktemplate()
d = self.bitcoin_rpc.getblocktemplate()
d.addCallback(self._update_block)
d.addErrback(self._update_block_failed)
@ -137,8 +142,7 @@ class TemplateRegistry(object):
def _update_block(self, data):
start = Interfaces.timestamper.time()
template = self.block_template_class(Interfaces.timestamper, self.coinbaser, JobIdGenerator.get_new_id())
template = self.block_template_class(Interfaces.timestamper, self.coinbaser, JobIdGenerator.get_new_id())
log.info(template.fill_from_rpc(data))
self.add_template(template,data['height'])
@ -150,17 +154,16 @@ class TemplateRegistry(object):
def diff_to_target(self, difficulty):
'''Converts difficulty to target'''
if settings.COINDAEMON_ALGO == 'scrypt':
diff1 = 0x0000ffff00000000000000000000000000000000000000000000000000000000
elif settings.COINDAEMON_ALGO == 'scrypt-jane':
if settings.COINDAEMON_ALGO == 'scrypt' or 'scrypt-jane':
diff1 = 0x0000ffff00000000000000000000000000000000000000000000000000000000
elif settings.COINDAEMON_ALGO == 'quark':
diff1 = 0x000000ffff000000000000000000000000000000000000000000000000000000
elif settings.COINDAEMON_ALGO == 'riecoin':
return difficulty
elif settings.coindaemon_algo == 'max':
diff1 = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000
elif settings.COINDAEMON_ALGO == 'keccak':
diff1 = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000
else:
diff1 = 0x00000000ffff0000000000000000000000000000000000000000000000000000
return diff1 / difficulty
def get_job(self, job_id):
@ -206,23 +209,15 @@ class TemplateRegistry(object):
raise SubmitException("Job '%s' not found" % job_id)
# Check if ntime looks correct
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 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 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")
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):
@ -237,13 +232,13 @@ class TemplateRegistry(object):
extranonce2_bin = binascii.unhexlify(extranonce2)
ntime_bin = binascii.unhexlify(ntime)
nonce_bin = binascii.unhexlify(nonce)
if settings.COINDAEMON_ALGO == 'riecoin':
ntime_bin = (''.join([ ntime_bin[(1-i)*4:(1-i)*4+4] for i in range(0, 2) ]))
nonce_bin = (''.join([ nonce_bin[(7-i)*4:(7-i)*4+4] for i in range(0, 8) ]))
# 1. Build coinbase
coinbase_bin = job.serialize_coinbase(extranonce1_bin, extranonce2_bin)
coinbase_hash = util.doublesha(coinbase_bin)
if settings.COINDAEMON_ALGO == 'max':
coinbase_hash = sha256(coinbase_bin).digest()
else:
coinbase_hash = util.doublesha(coinbase_bin)
# 2. Calculate merkle root
merkle_root_bin = job.merkletree.withFirst(coinbase_hash)
@ -259,72 +254,71 @@ class TemplateRegistry(object):
hash_bin = yac_scrypt.getPoWHash(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]), int(ntime, 16))
elif settings.COINDAEMON_ALGO == 'quark':
hash_bin = quark_hash.getPoWHash(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]))
elif settings.COINDAEMON_ALGO == 'max':
hash_bin = max_hash.getPoWHash(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]))
hash_bin = sha3_256(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ])).digest()[0:33]
elif settings.COINDAEMON_ALGO == 'skeinhash':
hash_bin = skeinhash.skeinhash(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]))
else:
elif settings.COINDAEMON_ALGO == 'keccak':
s = sha3.sha3_256()
ntime1 = str(int(ntime, 16))
s.update(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]) + ntime1)
hash_bin = s.hexdigest()
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)
scrypt_hash_hex = "%064x" % hash_int
if settings.COINDAEMON_ALGO == 'riecoin':
# this is kind of an ugly hack: we use hash_int to store the number of primes
hash_int = util.riecoinPoW( hash_int, job.target, int(nonce, 16) )
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"
#elif settings.COINDAEMON_ALGO == 'max':
#header_hex = header_hex+"000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000"
else: pass
target_user = self.diff_to_target(difficulty)
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")
if hash_int > target_user:
raise SubmitException("Share is above target. Hash: %s",
scrypt_hash_hex)
# 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
isBlockCandidate = False
if settings.COINDAEMON_ALGO == 'riecoin':
if hash_int == 6:
isBlockCandidate = True
else:
if hash_int <= job.target:
isBlockCandidate = True
if isBlockCandidate == True:
if hash_int <= job.target:
# 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 == '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) ]))
if settings.COINDAEMON_ALGO == 'max':
block_hash_bin = sha3_256(''.join([ header_bin[i*4:i*4+4][::-1]
for i in range(0, 20) ]) + str(int(ntime, 16))).hexdigest()
elif settings.COINDAEMON_ALGO == 'keccak':
s = sha3.SHA3256()
ntime1 = str(int(ntime, 16))
s.update(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]) + ntime1)
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')
if settings.COINDAEMON_ALGO != 'max':
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)")
# 7. Submit block to the network
serialized = binascii.hexlify(job.serialize())
on_submit = self.bitcoin_rpc.submitblock(serialized, block_hash_hex, scrypt_hash_hex)
on_submit = self.bitcoin_rpc.submitblock(serialized, block_hash_hex, scrypt_hash_hex)
if on_submit:
self.update_block()
@ -335,11 +329,14 @@ 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
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)
if settings.COINDAEMON_ALGO == 'keccak':
s = sha3.sha3_256()
ntime1 = str(int(ntime, 16))
s.update(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]) + ntime1)
block_hash_bin = s.hexdigest()
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:
return (header_hex, scrypt_hash_hex, share_diff, None)

View File

@ -7,6 +7,11 @@ import settings
import bitcoin_rpc
from hashlib import sha256
if settings.COINDAEMON_ALGO == 'keccak':
import sha3
from sha3 import sha3_256
def deser_string(f):
nit = struct.unpack("<B", f.read(1))[0]
if nit == 253:
@ -56,10 +61,7 @@ def uint256_from_str_be(s):
def uint256_from_compact(c):
nbytes = (c >> 24) & 0xFF
if nbytes <= 3:
v = (c & 0xFFFFFFL) >> (8 * (3 - nbytes))
else:
v = (c & 0xFFFFFFL) << (8 * (nbytes - 3))
v = (c & 0xFFFFFFL) << (8 * (nbytes - 3))
return v
def deser_vector(f, c):
@ -179,14 +181,19 @@ def address_to_pubkeyhash(addr):
if addr is None:
return None
ver = addr[0]
cksumA = addr[-4:]
cksumB = doublesha(addr[:-4])[:4]
if settings.COINDAEMON_ALGO != 'max':
cksumB = doublesha(addr[:-4])[:4]
#TODO: We should clean this up so that it works with not Keccek implementations too.
else:
cksumB = sha3_256(addr[:-4]).digest()[:4]
if cksumA != cksumB:
return None
return (ver, addr[1:-4])
def ser_uint256_be(u):
@ -214,54 +221,6 @@ 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_int, diff, nNonce ):
base = 1 << 8
for i in range(256):
base = base << 1
base = base | (hash_int & 1)
hash_int = hash_int >> 1
trailingZeros = diff - 1 - 8 - 256
if trailingZeros < 16 or trailingZeros > 20000:
return 0
base = base << trailingZeros
base += nNonce
if (base % 210) != 97:
return 0
if not isPrime( base ):
return 0
primes = 1
base += 4
if isPrime( base ):
primes+=1
base += 2
if isPrime( base ):
primes+=1
base += 4
if isPrime( base ):
primes+=1
base += 2
if isPrime( base ):
primes+=1
base += 4
if isPrime( base ):
primes+=1
return primes
#if settings.COINDAEMON_Reward == 'POW':
def script_to_address(addr):
d = address_to_pubkeyhash(addr)

1
maxcoin-hash-python Submodule

@ -0,0 +1 @@
Subproject commit 30cfcd105ae2914ae12b750ae7471e27f79c28ed

View File

@ -179,13 +179,6 @@ class DBInterface():
self.dbi.insert_worker(uid, username, password)
self.cache.set(username, password)
return True
else:
self.dbi.insert_user(username, password)
if self.dbi.get_uid(username) != False:
uid = self.dbi.get_uid(username)
self.dbi.insert_worker(uid, username, password)
self.cache.set(username, password)
return True
log.info("Authentication for %s failed" % username)
return False

View File

@ -87,7 +87,7 @@ class MiningService(GenericService):
else:
session['difficulty'] = settings.POOL_TARGET
# worker_log = (valid, invalid, is_banned, diff, is_ext_diff, timestamp)
Interfaces.worker_manager.worker_log['authorized'][worker_name] = (0, 0, False, session['difficulty'], is_ext_diff, Interfaces.timestamper.time())
Interfaces.worker_manager.worker_log['authorized'][worker_name] = (0, 0, False, session['difficulty'], is_ext_diff, Interfaces.timestamper.time())
return True
else:
ip = self.connection_ref()._get_ip()

View File

@ -1,34 +1,48 @@
# This File is used to create a list of requirements needed for testing stratum-mining or to create a clone install
BeautifulSoup==3.2.1
Jinja2==2.7.2
Magic-file-extensions==0.2
MarkupSafe==0.18
MySQL-python==1.2.5
PyYAML==3.10
Twisted==13.2.0
ansible==1.4.5
#Brlapi==0.5.7
#GnuPGInterface==0.3.2
MySQL-python==1.2.3
#PAM==0.4.2
#Pyste==0.9.10
#SOAPpy==0.12.0
Twisted==12.0.0
#Twisted-Conch==12.0.0
#Twisted-Core==12.0.0
#Twisted-Lore==12.0.0
#Twisted-Mail==12.0.0
#Twisted-Names==12.0.0
#Twisted-News==12.0.0
#Twisted-Runner==12.0.0
#Twisted-Web==12.0.0
#Twisted-Words==12.0.0
#apt-xapian-index==0.45
argparse==1.2.1
autobahn==0.8.4-3
cffi==0.8.2
cryptography==0.2.2
autobahn==0.6.5
#chardet==2.0.1
defer==1.0.6
distribute==0.6.28
ecdsa==0.10
feedparser==5.1.3
feedparser==5.1.2
fpconst==0.7.2
httplib2==0.8
numpy==1.7.1
paramiko==1.12.1
pyOpenSSL==0.14
pyasn1==0.1.7
pycparser==2.10
pycrypto==2.6.1
pylibmc==1.2.3
pyserial==2.7
python-dateutil==2.1
python-memcached==1.53
pyxdg==0.25
requests==2.2.0
simplejson==3.3.3
six==1.4.1
wsgiref==0.1.2
zope.interface==4.1.0
stratum==0.2.15
httplib2==0.7.4
#louis==2.4.1
#ltc-scrypt==1.0
#numpy==1.6.2
pyOpenSSL==0.13
pyasn1==0.1.3
pycrypto==2.6
#pycurl==7.19.0
pyserial==2.5
#python-apt==0.8.8.2
#python-debian==0.1.21
#python-debianbts==1.11
python-memcached==1.48
pyxdg==0.19
#reportbug==6.4.4
simplejson==2.5.2
#stratum==0.2.13
#uTidylib==0.2
#unattended-upgrades==0.1
#wsgiref==0.1.2
zope.interface==3.6.1

View File

@ -1,260 +0,0 @@
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
CREATE TABLE IF NOT EXISTS `accounts` (
`id` int(255) NOT NULL AUTO_INCREMENT,
`is_admin` tinyint(1) NOT NULL DEFAULT '0',
`is_anonymous` tinyint(1) NOT NULL DEFAULT '0',
`no_fees` tinyint(1) NOT NULL DEFAULT '0',
`username` varchar(40) NOT NULL,
`pass` varchar(255) NOT NULL,
`email` varchar(255) DEFAULT NULL COMMENT 'Assocaited email: used for validating users, and re-setting passwords',
`timezone` varchar(35) NOT NULL DEFAULT '415',
`notify_email` VARCHAR( 255 ) NULL DEFAULT NULL,
`loggedIp` varchar(255) DEFAULT NULL,
`is_locked` tinyint(1) NOT NULL DEFAULT '0',
`failed_logins` int(5) unsigned DEFAULT '0',
`failed_pins` int(5) unsigned DEFAULT '0',
`signup_timestamp` int(10) DEFAULT '0',
`last_login` int(10) DEFAULT NULL,
`pin` varchar(255) NOT NULL COMMENT 'four digit pin to allow account changes',
`api_key` varchar(255) DEFAULT NULL,
`token` varchar(65) DEFAULT NULL,
`donate_percent` float DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`),
UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `blocks` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`height` int(10) unsigned NOT NULL,
`blockhash` char(65) NOT NULL,
`confirmations` int(10) NOT NULL,
`amount` double NOT NULL,
`difficulty` double NOT NULL,
`time` int(11) NOT NULL,
`accounted` tinyint(1) NOT NULL DEFAULT '0',
`account_id` int(255) unsigned DEFAULT NULL,
`worker_name` varchar(50) DEFAULT 'unknown',
`shares` double unsigned DEFAULT NULL,
`share_id` bigint(30) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `height` (`height`,`blockhash`),
KEY `time` (`time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Discovered blocks persisted from Litecoin Service';
CREATE TABLE IF NOT EXISTS `coin_addresses` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`account_id` int(11) NOT NULL,
`currency` varchar(5) NOT NULL,
`coin_address` varchar(255) NOT NULL,
`ap_threshold` float DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `coin_address` (`coin_address`),
KEY `account_id` (`account_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `invitations` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`account_id` int(11) unsigned NOT NULL,
`email` varchar(50) NOT NULL,
`token_id` int(11) NOT NULL,
`is_activated` tinyint(1) NOT NULL DEFAULT '0',
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `monitoring` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(30) NOT NULL,
`type` varchar(15) NOT NULL,
`value` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Monitoring events from cronjobs';
CREATE TABLE IF NOT EXISTS `news` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`account_id` int(10) unsigned NOT NULL,
`header` varchar(255) NOT NULL,
`content` text NOT NULL,
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`active` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `notifications` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`type` varchar(25) NOT NULL,
`data` varchar(255) NOT NULL,
`active` tinyint(1) NOT NULL DEFAULT '1',
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`account_id` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `active` (`active`),
KEY `data` (`data`),
KEY `account_id` (`account_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `notification_settings` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`type` varchar(15) NOT NULL,
`account_id` int(11) NOT NULL,
`active` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `account_id` (`account_id`),
UNIQUE KEY `account_id_type` (`account_id`,`type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `payouts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`account_id` int(11) NOT NULL,
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`completed` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `account_id` (`account_id`,`completed`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `pool_worker` (
`id` int(255) NOT NULL AUTO_INCREMENT,
`account_id` int(255) NOT NULL,
`username` char(50) DEFAULT NULL,
`password` char(255) DEFAULT NULL,
`difficulty` float NOT NULL DEFAULT '0',
`monitor` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`),
KEY `account_id` (`account_id`),
KEY `pool_worker_username` (`username`(10))
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `settings` (
`name` varchar(255) NOT NULL,
`value` text DEFAULT NULL,
PRIMARY KEY (`name`),
UNIQUE KEY `setting` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `settings` (`name`, `value`) VALUES ('DB_VERSION', '1.0.3');
CREATE TABLE IF NOT EXISTS `shares` (
`id` bigint(30) NOT NULL AUTO_INCREMENT,
`rem_host` varchar(255) NOT NULL,
`username` varchar(120) NOT NULL,
`our_result` enum('Y','N') NOT NULL,
`upstream_result` enum('Y','N') DEFAULT NULL,
`reason` varchar(50) DEFAULT NULL,
`solution` varchar(257) NOT NULL,
`difficulty` float NOT NULL DEFAULT '0',
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `time` (`time`),
KEY `upstream_result` (`upstream_result`),
KEY `our_result` (`our_result`),
KEY `username` (`username`),
KEY `shares_username` (`username`(10))
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `shares_archive` (
`id` bigint(30) unsigned NOT NULL AUTO_INCREMENT,
`share_id` bigint(30) unsigned NOT NULL,
`username` varchar(120) NOT NULL,
`our_result` enum('Y','N') DEFAULT NULL,
`upstream_result` enum('Y','N') DEFAULT NULL,
`block_id` int(10) unsigned NOT NULL,
`difficulty` float NOT NULL DEFAULT '0',
`time` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `share_id` (`share_id`),
KEY `time` (`time`),
KEY `our_result` (`our_result`),
KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Archive shares for potential later debugging purposes';
CREATE TABLE IF NOT EXISTS `statistics_shares` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`account_id` int(10) unsigned NOT NULL,
`block_id` int(10) unsigned NOT NULL,
`valid` float unsigned NOT NULL DEFAULT '0',
`invalid` float unsigned NOT NULL DEFAULT '0',
`pplns_valid` float unsigned NOT NULL DEFAULT '0',
`pplns_invalid` float unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `account_id` (`account_id`),
KEY `block_id` (`block_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `tokens` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`account_id` int(11) NOT NULL,
`token` varchar(65) NOT NULL,
`type` tinyint(4) NOT NULL,
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `token` (`token`),
KEY `account_id` (`account_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `token_types` (
`id` tinyint(4) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(25) NOT NULL,
`expiration` INT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `token_types` (`id`, `name`, `expiration`) VALUES
(1, 'password_reset', 3600),
(2, 'confirm_email', 0),
(3, 'invitation', 0),
(4, 'account_unlock', 0),
(5, 'account_edit', 3600),
(6, 'change_pw', 3600),
(7, 'withdraw_funds', 3600);
CREATE TABLE IF NOT EXISTS `transactions` (
`id` int(255) NOT NULL AUTO_INCREMENT,
`account_id` int(255) unsigned NOT NULL,
`type` varchar(25) DEFAULT NULL,
`coin_address` varchar(255) DEFAULT NULL,
`amount` decimal(50,30) DEFAULT '0',
`block_id` int(255) DEFAULT NULL,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`txid` varchar(256) DEFAULT NULL,
`archived` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `block_id` (`block_id`),
KEY `account_id` (`account_id`),
KEY `type` (`type`),
KEY `archived` (`archived`),
KEY `account_id_archived` (`account_id`,`archived`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `statistics_users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`account_id` int(11) NOT NULL,
`hashrate` bigint(20) unsigned NOT NULL,
`workers` int(11) NOT NULL,
`sharerate` float NOT NULL,
`timestamp` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `account_id_timestamp` (`account_id`,`timestamp`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `user_settings` (
`account_id` int(11) NOT NULL,
`name` varchar(50) NOT NULL,
`value` text DEFAULT NULL,
PRIMARY KEY (`account_id`,`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;