Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
878e5f23fd | ||
|
|
76077630aa | ||
|
|
a19ae3444a | ||
|
|
83d92719bb | ||
|
|
8df9fc4c58 | ||
|
|
03dc1e3201 | ||
|
|
33f65ae2a8 | ||
|
|
62fa7d504c | ||
|
|
42d3d8a398 | ||
|
|
45b20392af | ||
|
|
a2dce6593a | ||
|
|
d6b5625321 | ||
|
|
7e3019259c | ||
|
|
a8a0b09be2 | ||
|
|
652dd310f2 | ||
|
|
836b9a3432 | ||
|
|
574a9b1e4d | ||
|
|
60e4eb6149 | ||
|
|
d6729c10e1 | ||
|
|
8c1f3d255c | ||
|
|
1b6f5a1127 | ||
|
|
77e05277e2 | ||
|
|
94276a8132 | ||
|
|
05d3f1789a | ||
|
|
88a1499685 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@
|
|||||||
conf/config.py
|
conf/config.py
|
||||||
*.log
|
*.log
|
||||||
LOG
|
LOG
|
||||||
|
*.bak
|
||||||
|
|||||||
9
.travis.yml
Normal file
9
.travis.yml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
language: python
|
||||||
|
python:
|
||||||
|
- "2.6"
|
||||||
|
- "2.7"
|
||||||
|
- "3.2"
|
||||||
|
- "3.3"
|
||||||
|
# command to install dependencies
|
||||||
|
install:
|
||||||
|
- "pip install -r requirements.txt"
|
||||||
36
README.md
36
README.md
@ -1,5 +1,4 @@
|
|||||||
[ ](https://www.codeship.io/projects/12274)
|
# Description
|
||||||
#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.
|
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.
|
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.
|
||||||
@ -8,7 +7,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.
|
**NOTE:** This fork is still in development. Many features may be broken. Please report any broken features or issues.
|
||||||
|
|
||||||
#Features
|
# Features
|
||||||
|
|
||||||
* Stratum Mining Pool
|
* Stratum Mining Pool
|
||||||
* Solved Block Confirmation
|
* Solved Block Confirmation
|
||||||
@ -24,25 +23,14 @@ 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
|
* Proof Of Work and Proof of Stake Coin Support
|
||||||
* Transaction Messaging 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.
|
*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 2.7+
|
||||||
* python-twisted
|
* python-twisted
|
||||||
* stratum
|
* stratum
|
||||||
* MySQL Server
|
* MySQL Server
|
||||||
* SHA256 or Scrypt CoinDaemon
|
* CoinD's
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
@ -62,23 +50,17 @@ Other coins have been known to work with this implementation. I have tested with
|
|||||||
* Quark
|
* Quark
|
||||||
* Securecoin
|
* Securecoin
|
||||||
|
|
||||||
#Installation
|
# Installation
|
||||||
|
|
||||||
The installation of this *stratum-mining* can be found in the Repo Wiki.
|
The installation of this *stratum-mining* can be found in the Repo Wiki.
|
||||||
|
|
||||||
#Contact
|
# Credits
|
||||||
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)
|
* Original version by Slush0 and ArtForz (original stratum code)
|
||||||
* More Features added by GeneralFault, Wadee Womersley, Viperaus, TheSeven and Moopless
|
* 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
|
* Multi Algo, Vardiff, DB and MPOS support done by Ahmed_Bodi, penner42 and Obigal
|
||||||
|
* Riecoin support implemented by gatra
|
||||||
|
|
||||||
#License
|
# 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.
|
||||||
|
|
||||||
|
|||||||
@ -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
|
CENTRAL_WALLET = 'set_valid_addresss_in_config!' # Local coin address where money goes
|
||||||
|
|
||||||
COINDAEMON_TRUSTED_HOST = 'localhost'
|
COINDAEMON_TRUSTED_HOST = 'localhost'
|
||||||
COINDAEMON_TRUSTED_PORT = 8332
|
COINDAEMON_TRUSTED_PORT = 28332
|
||||||
COINDAEMON_TRUSTED_USER = 'user'
|
COINDAEMON_TRUSTED_USER = 'user'
|
||||||
COINDAEMON_TRUSTED_PASSWORD = 'somepassword'
|
COINDAEMON_TRUSTED_PASSWORD = 'somepassword'
|
||||||
|
|
||||||
# Coin algorithm is the option used to determine the algorithm used by stratum
|
# Coin algorithm is the option used to determine the algorithm used by stratum
|
||||||
# This currently works with POW and POS coins
|
# This currently works with POW and POS coins
|
||||||
# The available options are:
|
# 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
|
# 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
|
# For Coins which support TX Messages please enter yes in the TX selection
|
||||||
COINDAEMON_ALGO = 'scrypt'
|
COINDAEMON_ALGO = 'riecoin'
|
||||||
COINDAEMON_TX = 'no'
|
COINDAEMON_TX = 'no'
|
||||||
|
|
||||||
# ******************** BASIC SETTINGS ***************
|
# ******************** BASIC SETTINGS ***************
|
||||||
@ -30,12 +30,12 @@ COINDAEMON_TX = 'no'
|
|||||||
# You can have up to 99
|
# You can have up to 99
|
||||||
|
|
||||||
#COINDAEMON_TRUSTED_HOST_1 = 'localhost'
|
#COINDAEMON_TRUSTED_HOST_1 = 'localhost'
|
||||||
#COINDAEMON_TRUSTED_PORT_1 = 8332
|
#COINDAEMON_TRUSTED_PORT_1 = 28332
|
||||||
#COINDAEMON_TRUSTED_USER_1 = 'user'
|
#COINDAEMON_TRUSTED_USER_1 = 'user'
|
||||||
#COINDAEMON_TRUSTED_PASSWORD_1 = 'somepassword'
|
#COINDAEMON_TRUSTED_PASSWORD_1 = 'somepassword'
|
||||||
|
|
||||||
#COINDAEMON_TRUSTED_HOST_2 = 'localhost'
|
#COINDAEMON_TRUSTED_HOST_2 = 'localhost'
|
||||||
#COINDAEMON_TRUSTED_PORT_2 = 8332
|
#COINDAEMON_TRUSTED_PORT_2 = 28332
|
||||||
#COINDAEMON_TRUSTED_USER_2 = 'user'
|
#COINDAEMON_TRUSTED_USER_2 = 'user'
|
||||||
#COINDAEMON_TRUSTED_PASSWORD_2 = 'somepassword'
|
#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
|
VDIFF_FLOAT = False # Use float difficulty
|
||||||
|
|
||||||
# Pool Target (Base 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 Difficulty Enable
|
||||||
VARIABLE_DIFF = True # Master variable difficulty enable
|
VARIABLE_DIFF = True # Master variable difficulty enable
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
# Add conf directory to python path.
|
# Add conf directory to python path.
|
||||||
# Configuration file is standard python module.
|
# Configuration file is standard python module.
|
||||||
import os, sys
|
import os, sys
|
||||||
sys.path = [os.path.join(os.getcwd(), 'conf'),os.path.join(os.getcwd(), 'externals', 'stratum-mining-proxy'),] + sys.path
|
sys.path = [os.path.join(os.getcwd(), 'conf'),os.path.join(os.getcwd(), '.'),os.path.join(os.getcwd(), 'externals', 'stratum-mining-proxy'),] + sys.path
|
||||||
|
|
||||||
from twisted.internet import defer
|
from twisted.internet import defer
|
||||||
from twisted.application.service import Application, IProcess
|
from twisted.application.service import Application, IProcess
|
||||||
|
|||||||
@ -141,12 +141,16 @@ class BitcoinRPC(object):
|
|||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def prevhash(self):
|
def prevhash(self):
|
||||||
resp = (yield self._call('getwork', []))
|
|
||||||
try:
|
try:
|
||||||
defer.returnValue(json.loads(resp)['result']['data'][8:72])
|
resp = (yield self._call('getblocktemplate', [{}]))
|
||||||
|
defer.returnValue(json.loads(resp)['result']['previousblockhash'])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.exception("Cannot decode prevhash %s" % str(e))
|
if (str(e) == "500 Internal Server Error"):
|
||||||
raise
|
resp = (yield self._call('getblocktemplate', []))
|
||||||
|
defer.returnValue(json.loads(resp)['result']['previousblockhash'])
|
||||||
|
else:
|
||||||
|
log.exception("Cannot decode prevhash %s" % str(e))
|
||||||
|
raise
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def validateaddress(self, address):
|
def validateaddress(self, address):
|
||||||
|
|||||||
@ -69,6 +69,7 @@ class BlockTemplate(halfnode.CBlock):
|
|||||||
self.nVersion = data['version']
|
self.nVersion = data['version']
|
||||||
self.hashPrevBlock = int(data['previousblockhash'], 16)
|
self.hashPrevBlock = int(data['previousblockhash'], 16)
|
||||||
self.nBits = int(data['bits'], 16)
|
self.nBits = int(data['bits'], 16)
|
||||||
|
|
||||||
self.hashMerkleRoot = 0
|
self.hashMerkleRoot = 0
|
||||||
self.nTime = 0
|
self.nTime = 0
|
||||||
self.nNonce = 0
|
self.nNonce = 0
|
||||||
@ -139,8 +140,12 @@ class BlockTemplate(halfnode.CBlock):
|
|||||||
r = struct.pack(">i", self.nVersion)
|
r = struct.pack(">i", self.nVersion)
|
||||||
r += self.prevhash_bin
|
r += self.prevhash_bin
|
||||||
r += util.ser_uint256_be(merkle_root_int)
|
r += util.ser_uint256_be(merkle_root_int)
|
||||||
r += ntime_bin
|
if settings.COINDAEMON_ALGO == 'riecoin':
|
||||||
r += struct.pack(">I", self.nBits)
|
r += struct.pack(">I", self.nBits)
|
||||||
|
r += ntime_bin
|
||||||
|
else:
|
||||||
|
r += ntime_bin
|
||||||
|
r += struct.pack(">I", self.nBits)
|
||||||
r += nonce_bin
|
r += nonce_bin
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
|||||||
@ -40,7 +40,7 @@ class CoinbaseTransactionPOW(halfnode.CTransaction):
|
|||||||
tx_out.scriptPubKey = coinbaser.get_script_pubkey()
|
tx_out.scriptPubKey = coinbaser.get_script_pubkey()
|
||||||
|
|
||||||
if settings.COINDAEMON_TX == 'yes':
|
if settings.COINDAEMON_TX == 'yes':
|
||||||
self.strTxComment = "http://github.com/ahmedbodi/stratum-mining"
|
self.strTxComment = "RanchiMall mining"
|
||||||
self.vin.append(tx_in)
|
self.vin.append(tx_in)
|
||||||
self.vout.append(tx_out)
|
self.vout.append(tx_out)
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ class CoinbaseTransactionPOS(halfnode.CTransaction):
|
|||||||
|
|
||||||
self.nTime = ntime
|
self.nTime = ntime
|
||||||
if settings.COINDAEMON_SHA256_TX == 'yes':
|
if settings.COINDAEMON_SHA256_TX == 'yes':
|
||||||
self.strTxComment = "http://github.com/ahmedbodi/stratum-mining"
|
self.strTxComment = "RanchiMall mining"
|
||||||
self.vin.append(tx_in)
|
self.vin.append(tx_in)
|
||||||
self.vout.append(tx_out)
|
self.vout.append(tx_out)
|
||||||
|
|
||||||
|
|||||||
@ -109,7 +109,7 @@ COINDAEMON_TRUSTED_PASSWORD = '***somepassword***'
|
|||||||
# Until AutoReward Selecting Code has been implemented the below options are us$
|
# 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 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$
|
# 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_Reward = 'POW'
|
||||||
COINDAEMON_SHA256_TX = 'yes'
|
COINDAEMON_SHA256_TX = 'yes'
|
||||||
|
|
||||||
|
|||||||
@ -239,6 +239,8 @@ class CBlock(object):
|
|||||||
self.scrypt = None
|
self.scrypt = None
|
||||||
elif settings.COINDAEMON_ALGO == 'quark':
|
elif settings.COINDAEMON_ALGO == 'quark':
|
||||||
self.quark = None
|
self.quark = None
|
||||||
|
elif settings.COINDAEMON_ALGO == 'riecoin':
|
||||||
|
self.riecoin = None
|
||||||
else: pass
|
else: pass
|
||||||
if settings.COINDAEMON_Reward == 'POS':
|
if settings.COINDAEMON_Reward == 'POS':
|
||||||
self.signature = b""
|
self.signature = b""
|
||||||
@ -248,9 +250,14 @@ class CBlock(object):
|
|||||||
self.nVersion = struct.unpack("<i", f.read(4))[0]
|
self.nVersion = struct.unpack("<i", f.read(4))[0]
|
||||||
self.hashPrevBlock = deser_uint256(f)
|
self.hashPrevBlock = deser_uint256(f)
|
||||||
self.hashMerkleRoot = deser_uint256(f)
|
self.hashMerkleRoot = deser_uint256(f)
|
||||||
self.nTime = struct.unpack("<I", f.read(4))[0]
|
if settings.COINDAEMON_ALGO == 'riecoin':
|
||||||
self.nBits = 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("<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.vtx = deser_vector(f, CTransaction)
|
self.vtx = deser_vector(f, CTransaction)
|
||||||
if settings.COINDAEMON_Reward == 'POS':
|
if settings.COINDAEMON_Reward == 'POS':
|
||||||
self.signature = deser_string(f)
|
self.signature = deser_string(f)
|
||||||
@ -261,9 +268,14 @@ class CBlock(object):
|
|||||||
r.append(struct.pack("<i", self.nVersion))
|
r.append(struct.pack("<i", self.nVersion))
|
||||||
r.append(ser_uint256(self.hashPrevBlock))
|
r.append(ser_uint256(self.hashPrevBlock))
|
||||||
r.append(ser_uint256(self.hashMerkleRoot))
|
r.append(ser_uint256(self.hashMerkleRoot))
|
||||||
r.append(struct.pack("<I", self.nTime))
|
if settings.COINDAEMON_ALGO == 'riecoin':
|
||||||
r.append(struct.pack("<I", self.nBits))
|
r.append(struct.pack("<I", self.nBits))
|
||||||
r.append(struct.pack("<I", self.nNonce))
|
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(ser_vector(self.vtx))
|
r.append(ser_vector(self.vtx))
|
||||||
if settings.COINDAEMON_Reward == 'POS':
|
if settings.COINDAEMON_Reward == 'POS':
|
||||||
r.append(ser_string(self.signature))
|
r.append(ser_string(self.signature))
|
||||||
@ -294,6 +306,18 @@ class CBlock(object):
|
|||||||
r.append(struct.pack("<I", self.nNonce))
|
r.append(struct.pack("<I", self.nNonce))
|
||||||
self.quark = uint256_from_str(quark_hash.getPoWHash(''.join(r)))
|
self.quark = uint256_from_str(quark_hash.getPoWHash(''.join(r)))
|
||||||
return self.quark
|
return self.quark
|
||||||
|
elif settings.COINDAEMON_ALGO == 'riecoin':
|
||||||
|
def calc_riecoin(self):
|
||||||
|
if self.riecoin 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.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
|
||||||
else:
|
else:
|
||||||
def calc_sha256(self):
|
def calc_sha256(self):
|
||||||
if self.sha256 is None:
|
if self.sha256 is None:
|
||||||
@ -309,15 +333,23 @@ class CBlock(object):
|
|||||||
|
|
||||||
|
|
||||||
def is_valid(self):
|
def is_valid(self):
|
||||||
if settings.COINDAEMON_ALGO == 'scrypt':
|
if settings.COINDAEMON_ALGO == 'riecoin':
|
||||||
|
self.calc_riecoin()
|
||||||
|
elif settings.COINDAEMON_ALGO == 'scrypt':
|
||||||
self.calc_scrypt()
|
self.calc_scrypt()
|
||||||
elif settings.COINDAEMON_ALGO == 'quark':
|
elif settings.COINDAEMON_ALGO == 'quark':
|
||||||
self.calc_quark()
|
self.calc_quark()
|
||||||
else:
|
else:
|
||||||
self.calc_sha256()
|
self.calc_sha256()
|
||||||
|
|
||||||
target = uint256_from_compact(self.nBits)
|
if settings.COINDAEMON_ALGO == 'riecoin':
|
||||||
|
target = settings.POOL_TARGET
|
||||||
|
else:
|
||||||
|
target = uint256_from_compact(self.nBits)
|
||||||
|
|
||||||
|
if settings.COINDAEMON_ALGO == 'riecoin':
|
||||||
|
if self.riecoin < target:
|
||||||
|
return False
|
||||||
if settings.COINDAEMON_ALGO == 'scrypt':
|
if settings.COINDAEMON_ALGO == 'scrypt':
|
||||||
if self.scrypt > target:
|
if self.scrypt > target:
|
||||||
return False
|
return False
|
||||||
|
|||||||
@ -65,7 +65,7 @@ class TemplateRegistry(object):
|
|||||||
def get_new_extranonce1(self):
|
def get_new_extranonce1(self):
|
||||||
'''Generates unique extranonce1 (e.g. for newly
|
'''Generates unique extranonce1 (e.g. for newly
|
||||||
subscribed connection.'''
|
subscribed connection.'''
|
||||||
log.debug("Getting Unique Extronance")
|
log.debug("Getting Unique Extranonce")
|
||||||
return self.extranonce_counter.get_new_bin()
|
return self.extranonce_counter.get_new_bin()
|
||||||
|
|
||||||
def get_last_broadcast_args(self):
|
def get_last_broadcast_args(self):
|
||||||
@ -150,10 +150,14 @@ class TemplateRegistry(object):
|
|||||||
|
|
||||||
def diff_to_target(self, difficulty):
|
def diff_to_target(self, difficulty):
|
||||||
'''Converts difficulty to target'''
|
'''Converts difficulty to target'''
|
||||||
if settings.COINDAEMON_ALGO == 'scrypt' or 'scrypt-jane':
|
if settings.COINDAEMON_ALGO == 'scrypt':
|
||||||
|
diff1 = 0x0000ffff00000000000000000000000000000000000000000000000000000000
|
||||||
|
elif settings.COINDAEMON_ALGO == 'scrypt-jane':
|
||||||
diff1 = 0x0000ffff00000000000000000000000000000000000000000000000000000000
|
diff1 = 0x0000ffff00000000000000000000000000000000000000000000000000000000
|
||||||
elif settings.COINDAEMON_ALGO == 'quark':
|
elif settings.COINDAEMON_ALGO == 'quark':
|
||||||
diff1 = 0x000000ffff000000000000000000000000000000000000000000000000000000
|
diff1 = 0x000000ffff000000000000000000000000000000000000000000000000000000
|
||||||
|
elif settings.COINDAEMON_ALGO == 'riecoin':
|
||||||
|
return difficulty
|
||||||
else:
|
else:
|
||||||
diff1 = 0x00000000ffff0000000000000000000000000000000000000000000000000000
|
diff1 = 0x00000000ffff0000000000000000000000000000000000000000000000000000
|
||||||
|
|
||||||
@ -202,15 +206,23 @@ class TemplateRegistry(object):
|
|||||||
raise SubmitException("Job '%s' not found" % job_id)
|
raise SubmitException("Job '%s' not found" % job_id)
|
||||||
|
|
||||||
# Check if ntime looks correct
|
# Check if ntime looks correct
|
||||||
if len(ntime) != 8:
|
if settings.COINDAEMON_ALGO == 'riecoin':
|
||||||
raise SubmitException("Incorrect size of ntime. Expected 8 chars")
|
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)):
|
if not job.check_ntime(int(ntime, 16)):
|
||||||
raise SubmitException("Ntime out of range")
|
raise SubmitException("Ntime out of range")
|
||||||
|
|
||||||
# Check nonce
|
# Check nonce
|
||||||
if len(nonce) != 8:
|
if settings.COINDAEMON_ALGO == 'riecoin':
|
||||||
raise SubmitException("Incorrect size of nonce. Expected 8 chars")
|
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
|
# Check for duplicated submit
|
||||||
if not job.register_submit(extranonce1_bin, extranonce2, ntime, nonce):
|
if not job.register_submit(extranonce1_bin, extranonce2, ntime, nonce):
|
||||||
@ -225,6 +237,9 @@ class TemplateRegistry(object):
|
|||||||
extranonce2_bin = binascii.unhexlify(extranonce2)
|
extranonce2_bin = binascii.unhexlify(extranonce2)
|
||||||
ntime_bin = binascii.unhexlify(ntime)
|
ntime_bin = binascii.unhexlify(ntime)
|
||||||
nonce_bin = binascii.unhexlify(nonce)
|
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
|
# 1. Build coinbase
|
||||||
coinbase_bin = job.serialize_coinbase(extranonce1_bin, extranonce2_bin)
|
coinbase_bin = job.serialize_coinbase(extranonce1_bin, extranonce2_bin)
|
||||||
@ -251,37 +266,55 @@ class TemplateRegistry(object):
|
|||||||
|
|
||||||
hash_int = util.uint256_from_str(hash_bin)
|
hash_int = util.uint256_from_str(hash_bin)
|
||||||
scrypt_hash_hex = "%064x" % hash_int
|
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)
|
header_hex = binascii.hexlify(header_bin)
|
||||||
if settings.COINDAEMON_ALGO == 'scrypt' or settings.COINDAEMON_ALGO == 'scrypt-jane':
|
if settings.COINDAEMON_ALGO == 'scrypt' or settings.COINDAEMON_ALGO == 'scrypt-jane':
|
||||||
header_hex = header_hex+"000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000"
|
header_hex = header_hex+"000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000"
|
||||||
elif settings.COINDAEMON_ALGO == 'quark':
|
elif settings.COINDAEMON_ALGO == 'quark':
|
||||||
header_hex = header_hex+"000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000"
|
header_hex = header_hex+"000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000"
|
||||||
|
elif settings.COINDAEMON_ALGO == 'riecoin':
|
||||||
|
header_hex = header_hex+"00000080000000000000000080030000"
|
||||||
else: pass
|
else: pass
|
||||||
|
|
||||||
target_user = self.diff_to_target(difficulty)
|
target_user = self.diff_to_target(difficulty)
|
||||||
if hash_int > target_user:
|
if settings.COINDAEMON_ALGO == 'riecoin':
|
||||||
raise SubmitException("Share is above target")
|
if hash_int < target_user:
|
||||||
|
raise SubmitException("Share does not meet target")
|
||||||
# Mostly for debugging purposes
|
else:
|
||||||
target_info = self.diff_to_target(100000)
|
if hash_int > target_user:
|
||||||
if hash_int <= target_info:
|
raise SubmitException("Share is above target")
|
||||||
log.info("Yay, share with diff above 100000")
|
# 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
|
# Algebra tells us the diff_to_target is the same as hash_to_diff
|
||||||
share_diff = int(self.diff_to_target(hash_int))
|
share_diff = int(self.diff_to_target(hash_int))
|
||||||
|
|
||||||
# 5. Compare hash with target of the network
|
# 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!
|
# Yay! It is block candidate!
|
||||||
log.info("We found a block candidate! %s" % scrypt_hash_hex)
|
log.info("We found a block candidate! %s" % scrypt_hash_hex)
|
||||||
|
|
||||||
# Reverse the header and get the potential block hash (for scrypt only)
|
# 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_ALGO == 'riecoin':
|
||||||
# if settings.COINDAEMON_Reward == 'POW':
|
block_hash_bin = util.doublesha(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 28) ]))
|
||||||
block_hash_bin = util.doublesha(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]))
|
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')
|
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
|
# 6. Finalize and serialize block object
|
||||||
job.finalize(merkle_root_int, extranonce1_bin, extranonce2_bin, int(ntime, 16), int(nonce, 16))
|
job.finalize(merkle_root_int, extranonce1_bin, extranonce2_bin, int(ntime, 16), int(nonce, 16))
|
||||||
|
|
||||||
@ -302,7 +335,10 @@ class TemplateRegistry(object):
|
|||||||
|
|
||||||
if settings.SOLUTION_BLOCK_HASH:
|
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
|
# 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')
|
block_hash_hex = block_hash_bin[::-1].encode('hex_codec')
|
||||||
return (header_hex, block_hash_hex, share_diff, None)
|
return (header_hex, block_hash_hex, share_diff, None)
|
||||||
else:
|
else:
|
||||||
|
|||||||
53
lib/util.py
53
lib/util.py
@ -56,7 +56,10 @@ def uint256_from_str_be(s):
|
|||||||
|
|
||||||
def uint256_from_compact(c):
|
def uint256_from_compact(c):
|
||||||
nbytes = (c >> 24) & 0xFF
|
nbytes = (c >> 24) & 0xFF
|
||||||
v = (c & 0xFFFFFFL) << (8 * (nbytes - 3))
|
if nbytes <= 3:
|
||||||
|
v = (c & 0xFFFFFFL) >> (8 * (3 - nbytes))
|
||||||
|
else:
|
||||||
|
v = (c & 0xFFFFFFL) << (8 * (nbytes - 3))
|
||||||
return v
|
return v
|
||||||
|
|
||||||
def deser_vector(f, c):
|
def deser_vector(f, c):
|
||||||
@ -211,6 +214,54 @@ def ser_number(n):
|
|||||||
s.append(n)
|
s.append(n)
|
||||||
return bytes(s)
|
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':
|
#if settings.COINDAEMON_Reward == 'POW':
|
||||||
def script_to_address(addr):
|
def script_to_address(addr):
|
||||||
d = address_to_pubkeyhash(addr)
|
d = address_to_pubkeyhash(addr)
|
||||||
|
|||||||
@ -179,6 +179,13 @@ class DBInterface():
|
|||||||
self.dbi.insert_worker(uid, username, password)
|
self.dbi.insert_worker(uid, username, password)
|
||||||
self.cache.set(username, password)
|
self.cache.set(username, password)
|
||||||
return True
|
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)
|
log.info("Authentication for %s failed" % username)
|
||||||
return False
|
return False
|
||||||
|
|||||||
@ -1,48 +1,34 @@
|
|||||||
# 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
|
BeautifulSoup==3.2.1
|
||||||
#Brlapi==0.5.7
|
Jinja2==2.7.2
|
||||||
#GnuPGInterface==0.3.2
|
Magic-file-extensions==0.2
|
||||||
MySQL-python==1.2.3
|
MarkupSafe==0.18
|
||||||
#PAM==0.4.2
|
MySQL-python==1.2.5
|
||||||
#Pyste==0.9.10
|
PyYAML==3.10
|
||||||
#SOAPpy==0.12.0
|
Twisted==13.2.0
|
||||||
Twisted==12.0.0
|
ansible==1.4.5
|
||||||
#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
|
argparse==1.2.1
|
||||||
autobahn==0.6.5
|
autobahn==0.8.4-3
|
||||||
#chardet==2.0.1
|
cffi==0.8.2
|
||||||
|
cryptography==0.2.2
|
||||||
defer==1.0.6
|
defer==1.0.6
|
||||||
distribute==0.6.28
|
|
||||||
ecdsa==0.10
|
ecdsa==0.10
|
||||||
feedparser==5.1.2
|
feedparser==5.1.3
|
||||||
fpconst==0.7.2
|
fpconst==0.7.2
|
||||||
httplib2==0.7.4
|
httplib2==0.8
|
||||||
#louis==2.4.1
|
numpy==1.7.1
|
||||||
#ltc-scrypt==1.0
|
paramiko==1.12.1
|
||||||
#numpy==1.6.2
|
pyOpenSSL==0.14
|
||||||
pyOpenSSL==0.13
|
pyasn1==0.1.7
|
||||||
pyasn1==0.1.3
|
pycparser==2.10
|
||||||
pycrypto==2.6
|
pycrypto==2.6.1
|
||||||
#pycurl==7.19.0
|
pylibmc==1.2.3
|
||||||
pyserial==2.5
|
pyserial==2.7
|
||||||
#python-apt==0.8.8.2
|
python-dateutil==2.1
|
||||||
#python-debian==0.1.21
|
python-memcached==1.53
|
||||||
#python-debianbts==1.11
|
pyxdg==0.25
|
||||||
python-memcached==1.48
|
requests==2.2.0
|
||||||
pyxdg==0.19
|
simplejson==3.3.3
|
||||||
#reportbug==6.4.4
|
six==1.4.1
|
||||||
simplejson==2.5.2
|
wsgiref==0.1.2
|
||||||
#stratum==0.2.13
|
zope.interface==4.1.0
|
||||||
#uTidylib==0.2
|
stratum==0.2.15
|
||||||
#unattended-upgrades==0.1
|
|
||||||
#wsgiref==0.1.2
|
|
||||||
zope.interface==3.6.1
|
|
||||||
|
|||||||
260
sql/base_structure.sql
Normal file
260
sql/base_structure.sql
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
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 */;
|
||||||
Loading…
Reference in New Issue
Block a user