Compare commits

...

30 Commits

Author SHA1 Message Date
sairajzero
878e5f23fd Update flo-data text when for mined tx 2023-07-23 20:07:29 +05:30
Sai Raj
76077630aa
Replace getwork call with getblocktemplate 2021-06-06 03:04:46 +05:30
Sai Raj
a19ae3444a
Update launcher.tac 2021-06-06 03:01:23 +05:30
Sai Raj
83d92719bb
Rename base_structure to base_structure.sql 2021-06-06 02:29:52 +05:30
Sai Raj
8df9fc4c58
Create base_structure 2021-06-06 02:29:29 +05:30
Sai Raj
03dc1e3201
Update README.md 2021-06-06 01:45:31 +05:30
ahmedbodi
33f65ae2a8 Update .travis.yml 2014-04-20 15:07:17 +01:00
ahmedbodi
62fa7d504c Update requirements.txt 2014-04-20 14:57:38 +01:00
ahmedbodi
42d3d8a398 Update .travis.yml 2014-04-20 14:56:39 +01:00
ahmedbodi
45b20392af Add Stratum 2014-04-20 14:50:46 +01:00
Ahmed Bodiwala
a2dce6593a Add Travis 2014-04-20 13:28:03 +00:00
Ahmed Bodiwala
d6b5625321 Fix Requirements 2014-04-20 13:23:56 +00:00
ahmedbodi
7e3019259c Merge pull request #5 from youjying/patch-1
user nonexistance error
2014-03-21 14:29:09 +00:00
youjying
a8a0b09be2 user nonexistance error
some servers like to allow people to connect with no signup. this avoids the issue of not having a user created. perhaps missing a uid generator?
2014-03-20 14:03:30 -06:00
ahmedbodi
652dd310f2 Update README.md 2014-03-18 09:52:16 +00:00
ahmedbodi
836b9a3432 Merge pull request #4 from gatra/master
Riecoin Support
2014-03-18 09:49:09 +00:00
gatra
574a9b1e4d submit block bug fixes 2014-03-18 01:14:37 -03:00
gatra
60e4eb6149 readme updates 2014-03-13 23:32:37 -03:00
gatra
d6729c10e1 riecoin bug fixes 2014-03-13 23:29:04 -03:00
ahmedbodi
8c1f3d255c Merge pull request #3 from mrbr1ghtside/patch-1
Update template_registry.py
2014-03-07 19:24:18 +00:00
mrbr1ghtside
1b6f5a1127 Update template_registry.py
Typo ;)
2014-03-07 20:16:03 +01:00
gatra
77e05277e2 some fixes 2014-03-06 18:35:41 -03:00
gatra
94276a8132 riecoin support fixes 2014-03-06 00:14:53 -03:00
gatra
05d3f1789a riecoin support 2014-03-05 12:42:52 -03:00
ahmedbodi
88a1499685 Status Update 2014-02-28 23:38:35 +00:00
ahmedbodi
ab3a04a011 Merge pull request #227 from daygle/patch-1
Update config_sample.py
2014-02-19 15:28:33 +00:00
ahmedbodi
6285aad778 Merge pull request #225 from slaveofmoney/patch-1
Removed double function declaration (get_uid)
2014-02-12 15:42:09 +00:00
ahmedbodi
52db8210d8 Fix Get User Call 2014-02-10 12:56:59 +00:00
Glen
60492a2ae4 Update config_sample.py
Clean-up config template.
2014-02-03 22:47:51 +11:00
slaveofmoney
11843fd9e1 Removed double function declaration (get_uid) 2014-02-03 13:25:57 +06:00
17 changed files with 539 additions and 180 deletions

1
.gitignore vendored
View File

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

9
.travis.yml Normal file
View 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"

View File

@ -1,5 +1,4 @@
[ ![Codeship Status for ahmedbodi/php-mpos](https://www.codeship.io/projects/b3003a70-61a3-0131-231e-26f75a0c690d/status?branch=master)](https://www.codeship.io/projects/12274) # Description
#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.

View File

@ -9,32 +9,33 @@ You NEED to set the parameters in BASIC SETTINGS
# ******************** BASIC SETTINGS *************** # ******************** BASIC SETTINGS ***************
# These are the MUST BE SET parameters! # These are the MUST BE SET parameters!
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 algortithm 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 ***************
# Backup Coin Daemon address's (consider having at least 1 backup) # Backup Coin Daemon address's (consider having at least 1 backup)
# 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'
@ -54,7 +55,7 @@ LOGFILE = None # eg. 'stratum.log'
LOGLEVEL = 'DEBUG' LOGLEVEL = 'DEBUG'
# Logging Rotation can be enabled with the following settings # Logging Rotation can be enabled with the following settings
# It if not enabled here, you can set up logrotate to rotate the files. # It if not enabled here, you can set up logrotate to rotate the files.
# For built in log rotation set LOG_ROTATION = True and configrue the variables # For built in log rotation set LOG_ROTATION = True and configure the variables
LOG_ROTATION = True LOG_ROTATION = True
LOG_SIZE = 10485760 # Rotate every 10M LOG_SIZE = 10485760 # Rotate every 10M
LOG_RETENTION = 10 # Keep 10 Logs LOG_RETENTION = 10 # Keep 10 Logs
@ -65,7 +66,6 @@ LOG_RETENTION = 10 # Keep 10 Logs
THREAD_POOL_SIZE = 300 THREAD_POOL_SIZE = 300
# ******************** TRANSPORTS ********************* # ******************** TRANSPORTS *********************
# Hostname or external IP to expose # Hostname or external IP to expose
HOSTNAME = 'localhost' HOSTNAME = 'localhost'
@ -87,7 +87,6 @@ LISTEN_WSS_TRANSPORT = None
PASSWORD_SALT = 'some_crazy_string' PASSWORD_SALT = 'some_crazy_string'
# ******************** Database ********************* # ******************** Database *********************
DATABASE_DRIVER = 'mysql' # Options: none, sqlite, postgresql or mysql DATABASE_DRIVER = 'mysql' # Options: none, sqlite, postgresql or mysql
DATABASE_EXTEND = False # SQLite and PGSQL Only! DATABASE_EXTEND = False # SQLite and PGSQL Only!
@ -120,7 +119,7 @@ DB_USERCACHE_TIME = 600 # How long the usercache is good for before we r
# ******************** Pool Settings ********************* # ******************** Pool Settings *********************
# User Auth Options # User Auth Options
USERS_AUTOADD = False # Automatically add users to db when they connect. USERS_AUTOADD = False # Automatically add users to database when they connect.
# This basically disables User Auth for the pool. # This basically disables User Auth for the pool.
USERS_CHECK_PASSWORD = False # Check the workers password? (Many pools don't) USERS_CHECK_PASSWORD = False # Check the workers password? (Many pools don't)
@ -139,43 +138,43 @@ MERKLE_REFRESH_INTERVAL = 60 # How often check memorypool
INSTANCE_ID = 31 # Used for extranonce and needs to be 0-31 INSTANCE_ID = 31 # Used for extranonce and needs to be 0-31
# ******************** Pool Difficulty Settings ********************* # ******************** Pool Difficulty Settings *********************
VDIFF_X2_TYPE = True # powers of 2 e.g. 2,4,8,16,32,64,128,256,512,1024 VDIFF_X2_TYPE = True # Powers of 2 e.g. 2,4,8,16,32,64,128,256,512,1024
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
# Variable diff tuning variables # Variable diff tuning variables
#VARDIFF will start at the POOL_TARGET. It can go as low as the VDIFF_MIN and as high as min(VDIFF_MAX or Liteconin's difficulty) #VARDIFF will start at the POOL_TARGET. It can go as low as the VDIFF_MIN and as high as min(VDIFF_MAX or coindaemons difficulty)
USE_COINDAEMON_DIFF = False # Set the maximum difficulty to the litecoin difficulty. USE_COINDAEMON_DIFF = False # Set the maximum difficulty to the coindaemon difficulty.
DIFF_UPDATE_FREQUENCY = 86400 # Update the litecoin difficulty once a day for the VARDIFF maximum DIFF_UPDATE_FREQUENCY = 86400 # Update the coindaemon difficulty once a day for the VARDIFF maximum
VDIFF_MIN_TARGET = 16 # Minimum Target difficulty VDIFF_MIN_TARGET = 16 # Minimum target difficulty
VDIFF_MAX_TARGET = 1024 # Maximum Target difficulty VDIFF_MAX_TARGET = 1024 # Maximum target difficulty
VDIFF_TARGET_TIME = 15 # Target time per share (i.e. try to get 1 share per this many seconds) VDIFF_TARGET_TIME = 15 # Target time per share (i.e. try to get 1 share per this many seconds)
VDIFF_RETARGET_TIME = 120 # Check to see if we should retarget this often VDIFF_RETARGET_TIME = 120 # Check to see if we should retarget this often
VDIFF_VARIANCE_PERCENT = 30 # Allow average time to very this % from target without retarget VDIFF_VARIANCE_PERCENT = 30 # Allow average time to very this % from target without retarget
# Allow external setting of worker difficulty, checks pool_worker table datarow[6] position for target difficulty # Allow external setting of worker difficulty, checks pool_worker table datarow[6] position for target difficulty
# if present or else defaults to pool target, over rides all other difficulty settings, no checks are made # if present or else defaults to pool target, over rides all other difficulty settings, no checks are made
#for min or max limits this sould be done by your front end software # for min or max limits this should be done by your front end software
ALLOW_EXTERNAL_DIFFICULTY = False ALLOW_EXTERNAL_DIFFICULTY = False
#### Advanced Option ##### #### Advanced Option #####
# For backwards compatibility, we send the scrypt hash to the solutions column in the shares table # For backwards compatibility, we send the scrypt hash to the solutions column in the shares table
# For block confirmation, we have an option to send the block hash in # For block confirmation, we have an option to send the block hash in
# Please make sure your front end is compatible with the block hash in the solutions table. # Please make sure your front end is compatible with the block hash in the solutions table.
# For People using the MPOS frontend enabling this is recommended. It allows the frontend to compare the block hash to the coin daemon reducing the liklihood of missing share error's for blocks # For People using the MPOS frontend enabling this is recommended. It allows the frontend to compare the block hash to the coin daemon reducing the likelihood of missing share error's for blocks
SOLUTION_BLOCK_HASH = True # If enabled, enter the block hash. If false enter the scrypt/sha hash into the shares table SOLUTION_BLOCK_HASH = True # If enabled, enter the block hash. If false enter the scrypt/sha hash into the shares table
#Pass scrypt hash to submit block check. #Pass scrypt hash to submit block check.
#Use if submit block is returning errors and marking submitted blocks invaild upstream, but the submitted blocks are being a accepted by the coin daemon into the block chain. #Use if submit block is returning errors and marking submitted blocks invalid upstream, but the submitted blocks are being a accepted by the coin daemon into the block chain.
BLOCK_CHECK_SCRYPT_HASH = False BLOCK_CHECK_SCRYPT_HASH = False
# ******************** Worker Ban Options ********************* # ******************** Worker Ban Options *********************
ENABLE_WORKER_BANNING = True # enable/disable temporary worker banning ENABLE_WORKER_BANNING = True # Enable/disable temporary worker banning
WORKER_CACHE_TIME = 600 # How long the worker stats cache is good before we check and refresh WORKER_CACHE_TIME = 600 # How long the worker stats cache is good before we check and refresh
WORKER_BAN_TIME = 300 # How long we temporarily ban worker WORKER_BAN_TIME = 300 # How long we temporarily ban worker
INVALID_SHARES_PERCENT = 50 # Allow average invalid shares vary this % before we ban INVALID_SHARES_PERCENT = 50 # Allow average invalid shares vary this % before we ban
@ -184,15 +183,14 @@ INVALID_SHARES_PERCENT = 50 # Allow average invalid shares vary this % before
NOTIFY_EMAIL_TO = '' # Where to send Start/Found block notifications NOTIFY_EMAIL_TO = '' # Where to send Start/Found block notifications
NOTIFY_EMAIL_TO_DEADMINER = '' # Where to send dead miner notifications NOTIFY_EMAIL_TO_DEADMINER = '' # Where to send dead miner notifications
NOTIFY_EMAIL_FROM = 'root@localhost' # Sender address NOTIFY_EMAIL_FROM = 'root@localhost' # Sender address
NOTIFY_EMAIL_SERVER = 'localhost' # E-Mail Sender NOTIFY_EMAIL_SERVER = 'localhost' # E-Mail sender
NOTIFY_EMAIL_USERNAME = '' # E-Mail server SMTP Logon NOTIFY_EMAIL_USERNAME = '' # E-Mail server SMTP logon
NOTIFY_EMAIL_PASSWORD = '' NOTIFY_EMAIL_PASSWORD = ''
NOTIFY_EMAIL_USETLS = True NOTIFY_EMAIL_USETLS = True
#### Memcache #### # ******************** Memcache Settings *********************
# Memcahce is a requirement. Enter the settings below # Memcahce is a requirement. Enter the settings below
MEMCACHE_HOST = "localhost" # hostname or IP that runs memcached MEMCACHE_HOST = "localhost" # Hostname or IP that runs memcached
MEMCACHE_PORT = 11211 # Port MEMCACHE_PORT = 11211 # Port
MEMCACHE_TIMEOUT = 900 # Key timeout MEMCACHE_TIMEOUT = 900 # Key timeout
MEMCACHE_PREFIX = "stratum_" # Prefix for keys MEMCACHE_PREFIX = "stratum_" # Prefix for keys

View File

@ -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

View File

@ -141,10 +141,14 @@ 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:
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)) log.exception("Cannot decode prevhash %s" % str(e))
raise raise

View File

@ -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,6 +140,10 @@ 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)
if settings.COINDAEMON_ALGO == 'riecoin':
r += struct.pack(">I", self.nBits)
r += ntime_bin
else:
r += ntime_bin r += ntime_bin
r += struct.pack(">I", self.nBits) r += struct.pack(">I", self.nBits)
r += nonce_bin r += nonce_bin

View File

@ -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)

View File

@ -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'

View File

@ -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,6 +250,11 @@ 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)
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.nTime = struct.unpack("<I", f.read(4))[0]
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.nNonce = struct.unpack("<I", f.read(4))[0]
@ -261,6 +268,11 @@ 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))
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.nTime))
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("<I", self.nNonce))
@ -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()
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 settings.COINDAEMON_ALGO == 'scrypt':
if self.scrypt > target: if self.scrypt > target:
return False return False

View File

@ -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,6 +206,10 @@ 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 settings.COINDAEMON_ALGO == 'riecoin':
if len(ntime) != 16:
raise SubmitException("Incorrect size of ntime. Expected 16 chars")
else:
if len(ntime) != 8: if len(ntime) != 8:
raise SubmitException("Incorrect size of ntime. Expected 8 chars") raise SubmitException("Incorrect size of ntime. Expected 8 chars")
@ -209,6 +217,10 @@ class TemplateRegistry(object):
raise SubmitException("Ntime out of range") raise SubmitException("Ntime out of range")
# Check nonce # 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: if len(nonce) != 8:
raise SubmitException("Incorrect size of nonce. Expected 8 chars") raise SubmitException("Incorrect size of nonce. Expected 8 chars")
@ -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,17 +266,27 @@ 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 settings.COINDAEMON_ALGO == 'riecoin':
if hash_int < target_user:
raise SubmitException("Share does not meet target")
else:
if hash_int > target_user: if hash_int > target_user:
raise SubmitException("Share is above target") raise SubmitException("Share is above target")
# Mostly for debugging purposes # Mostly for debugging purposes
target_info = self.diff_to_target(100000) target_info = self.diff_to_target(100000)
if hash_int <= target_info: if hash_int <= target_info:
@ -271,17 +296,25 @@ class TemplateRegistry(object):
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
isBlockCandidate = False
if settings.COINDAEMON_ALGO == 'riecoin':
if hash_int == 6:
isBlockCandidate = True
else:
if hash_int <= job.target: 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) ]))
else:
block_hash_bin = util.doublesha(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ])) 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,6 +335,9 @@ 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
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_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)

View File

@ -56,6 +56,9 @@ def uint256_from_str_be(s):
def uint256_from_compact(c): def uint256_from_compact(c):
nbytes = (c >> 24) & 0xFF 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 return v
@ -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)

View File

@ -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
@ -187,7 +194,10 @@ class DBInterface():
return self.dbi.list_users() return self.dbi.list_users()
def get_user(self, id): def get_user(self, id):
return self.dbi.get_user(id) if self.cache.get(id) is None:
self.cache.set(id,self.dbi.get_user(id))
return self.cache.get(id)
def user_exists(self, username): def user_exists(self, username):
if self.cache.get(username) is not None: if self.cache.get(username) is not None:

View File

@ -342,19 +342,6 @@ class DB_Mysql():
} }
return ret return ret
def get_uid(self, id_or_username):
log.debug("Finding user id of %s", id_or_username)
uname = id_or_username.split(".", 1)[0]
self.execute("SELECT `id` FROM `accounts` where username = %s", (uname))
row = self.dbc.fetchone()
if row is None:
return False
else:
uid = row[0]
return uid
def insert_worker(self, account_id, username, password): def insert_worker(self, account_id, username, password):
log.debug("Adding new worker %s", username) log.debug("Adding new worker %s", username)
@ -363,8 +350,6 @@ class DB_Mysql():
self.dbh.commit() self.dbh.commit()
return str(username) return str(username)
def close(self): def close(self):
self.dbh.close() self.dbh.close()

View File

@ -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
View 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 */;