Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
12fa1a4e97 | ||
|
|
1ec817b248 | ||
|
|
4a68da7bcd | ||
|
|
5f8a1ff51d | ||
|
|
7e4f9cd58f | ||
|
|
67f74ff9ef | ||
|
|
56cd8940b1 | ||
|
|
5e5d6b9b14 | ||
|
|
73385d3f79 | ||
|
|
0d1e796517 | ||
|
|
96e4fa20e4 | ||
|
|
dfe2da32b5 | ||
|
|
396f966d70 | ||
|
|
c8142e3297 | ||
|
|
909aec6cb6 | ||
|
|
12b6b696ef | ||
|
|
e8521991af | ||
|
|
bf3c4b84bc | ||
|
|
dfc3b800d1 | ||
|
|
bb78d0e128 | ||
|
|
9191786fe5 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,4 +2,3 @@
|
|||||||
conf/config.py
|
conf/config.py
|
||||||
*.log
|
*.log
|
||||||
LOG
|
LOG
|
||||||
*.bak
|
|
||||||
|
|||||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -10,3 +10,6 @@
|
|||||||
[submodule "externals/quarkcoin-hash"]
|
[submodule "externals/quarkcoin-hash"]
|
||||||
path = externals/quarkcoin-hash
|
path = externals/quarkcoin-hash
|
||||||
url = https://github.com/Neisklar/quarkcoin-hash-python
|
url = https://github.com/Neisklar/quarkcoin-hash-python
|
||||||
|
[submodule "externals/vertcoin_scrypt"]
|
||||||
|
path = externals/vertcoin_scrypt
|
||||||
|
url = https://github.com/scr34m/vertcoin_scrypt.git
|
||||||
|
|||||||
@ -1,9 +0,0 @@
|
|||||||
language: python
|
|
||||||
python:
|
|
||||||
- "2.6"
|
|
||||||
- "2.7"
|
|
||||||
- "3.2"
|
|
||||||
- "3.3"
|
|
||||||
# command to install dependencies
|
|
||||||
install:
|
|
||||||
- "pip install -r requirements.txt"
|
|
||||||
36
README.md
36
README.md
@ -1,4 +1,5 @@
|
|||||||
# Description
|
[ ](https://www.codeship.io/projects/12274)
|
||||||
|
#Description
|
||||||
Stratum-mining is a pooled mining protocol. It is a replacement for *getwork* based pooling servers by allowing clients to generate work. The stratum protocol is described [here](http://mining.bitcoin.cz/stratum-mining) in full detail.
|
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.
|
||||||
@ -7,7 +8,7 @@ The goal is to make a reliable stratum mining server for a wide range of coins u
|
|||||||
|
|
||||||
**NOTE:** This fork is still in development. Many features may be broken. Please report any broken features or issues.
|
**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
|
||||||
@ -23,14 +24,25 @@ The goal is to make a reliable stratum mining server for a wide range of coins u
|
|||||||
* Proof Of Work and Proof of Stake Coin Support
|
* 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
|
||||||
* CoinD's
|
* SHA256 or Scrypt CoinDaemon
|
||||||
|
|
||||||
Other coins have been known to work with this implementation. I have tested with the following coins, but there may be many others that work.
|
Other coins have been known to work with this implementation. I have tested with the following coins, but there may be many others that work.
|
||||||
|
|
||||||
@ -50,17 +62,23 @@ Other coins have been known to work with this implementation. I have tested with
|
|||||||
* Quark
|
* 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.
|
||||||
|
|
||||||
# Credits
|
#Contact
|
||||||
|
I am available in the #MPOS, #crypto-expert, #digitalcoin, and #worldcoin channels on freenode.
|
||||||
|
Although i am willing to provide support through IRC please file issues on the repo.
|
||||||
|
Issues as a direct result of stratum will be helped with as much as possible
|
||||||
|
However issues related to a coin daemon's setup and other non stratum issues,
|
||||||
|
Please research and attempt to debug first.
|
||||||
|
|
||||||
|
#Credits
|
||||||
|
|
||||||
* Original version by Slush0 and ArtForz (original stratum code)
|
* 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 provided AS-IS without any warranties of any kind. Please use at your own risk.
|
This software is provides AS-IS without any warranties of any kind. Please use at your own risk.
|
||||||
|
|
||||||
|
|||||||
@ -5,37 +5,33 @@ Please rename it to config.py and fill correct values.
|
|||||||
This is already setup with sane values for solomining.
|
This is already setup with sane values for solomining.
|
||||||
You NEED to set the parameters in BASIC SETTINGS
|
You NEED to set the parameters in BASIC SETTINGS
|
||||||
'''
|
'''
|
||||||
|
#********************* Config Version ***************
|
||||||
|
CONFIG_VERSION = 0.1
|
||||||
# ******************** 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 = 28332
|
COINDAEMON_TRUSTED_PORT = 8332
|
||||||
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
|
COINDAEMON_ALGO = 'scrypt' # The available options are: scrypt, sha256d, scrypt-jane, skeinhash, and quark
|
||||||
# This currently works with POW and POS coins
|
SCRYPTJANE_NAME = 'vtc_scrypt'# Set this to the Scrypt jane module name e.g. yac_scrypt or vtc_scrypt
|
||||||
# The available options are:
|
COINDAEMON_TX = False # For Coins which support TX Messages please enter yes in the TX selection
|
||||||
# scrypt, sha256d, scrypt-jane, skeinhash, quark and riecoin
|
|
||||||
# If the option does not meet either of these criteria stratum defaults to scrypt
|
|
||||||
# For Coins which support TX Messages please enter yes in the TX selection
|
|
||||||
COINDAEMON_ALGO = 'riecoin'
|
|
||||||
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 = 28332
|
#COINDAEMON_TRUSTED_PORT_1 = 8332
|
||||||
#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 = 28332
|
#COINDAEMON_TRUSTED_PORT_2 = 8332
|
||||||
#COINDAEMON_TRUSTED_USER_2 = 'user'
|
#COINDAEMON_TRUSTED_USER_2 = 'user'
|
||||||
#COINDAEMON_TRUSTED_PASSWORD_2 = 'somepassword'
|
#COINDAEMON_TRUSTED_PASSWORD_2 = 'somepassword'
|
||||||
|
|
||||||
@ -55,7 +51,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 configure the variables
|
# For built in log rotation set LOG_ROTATION = True and configrue 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
|
||||||
@ -66,6 +62,7 @@ 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,8 +84,9 @@ 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_EXTEND = False # SQLite and PGSQL Only!
|
DATABASE_DRIVER = 'mysql' # Options: none, sqlite, postgresql or mysql
|
||||||
|
DATABASE_EXTEND = False # SQLite and PGSQL Only!
|
||||||
|
|
||||||
# SQLite
|
# SQLite
|
||||||
DB_SQLITE_FILE = 'pooldb.sqlite'
|
DB_SQLITE_FILE = 'pooldb.sqlite'
|
||||||
@ -103,7 +101,7 @@ DB_MYSQL_HOST = 'localhost'
|
|||||||
DB_MYSQL_DBNAME = 'pooldb'
|
DB_MYSQL_DBNAME = 'pooldb'
|
||||||
DB_MYSQL_USER = 'pooldb'
|
DB_MYSQL_USER = 'pooldb'
|
||||||
DB_MYSQL_PASS = '**empty**'
|
DB_MYSQL_PASS = '**empty**'
|
||||||
DB_MYSQL_PORT = 3306 # Default port for MySQL
|
DB_MYSQL_PORT = 3306 # Default port for MySQL
|
||||||
|
|
||||||
# ******************** Adv. DB Settings *********************
|
# ******************** Adv. DB Settings *********************
|
||||||
# Don't change these unless you know what you are doing
|
# Don't change these unless you know what you are doing
|
||||||
@ -119,7 +117,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 database when they connect.
|
USERS_AUTOADD = False # Automatically add users to db 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)
|
||||||
|
|
||||||
@ -128,69 +126,70 @@ COINBASE_EXTRAS = '/stratumPool/' # Extra Descriptive String to incorp
|
|||||||
ALLOW_NONLOCAL_WALLET = False # Allow valid, but NON-Local wallet's
|
ALLOW_NONLOCAL_WALLET = False # Allow valid, but NON-Local wallet's
|
||||||
|
|
||||||
# Coin Daemon communication polling settings (In Seconds)
|
# Coin Daemon communication polling settings (In Seconds)
|
||||||
PREVHASH_REFRESH_INTERVAL = 5 # How often to check for new Blocks
|
PREVHASH_REFRESH_INTERVAL = 5 # How often to check for new Blocks
|
||||||
# If using the blocknotify script (recommended) set = to MERKLE_REFRESH_INTERVAL
|
# If using the blocknotify script (recommended) set = to MERKLE_REFRESH_INTERVAL
|
||||||
# (No reason to poll if we're getting pushed notifications)
|
# (No reason to poll if we're getting pushed notifications)
|
||||||
MERKLE_REFRESH_INTERVAL = 60 # How often check memorypool
|
MERKLE_REFRESH_INTERVAL = 60 # How often check memorypool
|
||||||
# This effectively resets the template and incorporates new transactions.
|
# This effectively resets the template and incorporates new transactions.
|
||||||
# This should be "slow"
|
# This should be "slow"
|
||||||
|
|
||||||
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 = False # 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 = 4 # Pool-wide difficulty target int >= 1
|
POOL_TARGET = 32 # 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 coindaemons 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 Liteconin's difficulty)
|
||||||
USE_COINDAEMON_DIFF = False # Set the maximum difficulty to the coindaemon difficulty.
|
USE_COINDAEMON_DIFF = False # Set the maximum difficulty to the litecoin difficulty.
|
||||||
DIFF_UPDATE_FREQUENCY = 86400 # Update the coindaemon difficulty once a day for the VARDIFF maximum
|
DIFF_UPDATE_FREQUENCY = 86400 # Update the litecoin 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 should be done by your front end software
|
#for min or max limits this sould 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 likelihood 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 liklihood 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 invalid 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 invaild 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
|
||||||
|
|
||||||
# ******************** E-Mail Notification Settings *********************
|
# ******************** E-Mail Notification Settings *********************
|
||||||
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 Settings *********************
|
#### Memcache ####
|
||||||
# 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
|
||||||
|
|
||||||
|
|||||||
1
externals/vertcoin_scrypt
vendored
Submodule
1
externals/vertcoin_scrypt
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 4a3d789cf4fd713308f26610e39e81cb7d86423f
|
||||||
@ -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(), '.'),os.path.join(os.getcwd(), 'externals', 'stratum-mining-proxy'),] + sys.path
|
sys.path = [os.path.join(os.getcwd(), 'conf'),os.path.join(os.getcwd(), 'externals', 'stratum-mining-proxy'),] + sys.path
|
||||||
|
|
||||||
from twisted.internet import defer
|
from twisted.internet import defer
|
||||||
from twisted.application.service import Application, IProcess
|
from twisted.application.service import Application, IProcess
|
||||||
|
|||||||
@ -141,16 +141,12 @@ class BitcoinRPC(object):
|
|||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def prevhash(self):
|
def prevhash(self):
|
||||||
|
resp = (yield self._call('getwork', []))
|
||||||
try:
|
try:
|
||||||
resp = (yield self._call('getblocktemplate', [{}]))
|
defer.returnValue(json.loads(resp)['result']['data'][8:72])
|
||||||
defer.returnValue(json.loads(resp)['result']['previousblockhash'])
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if (str(e) == "500 Internal Server Error"):
|
log.exception("Cannot decode prevhash %s" % str(e))
|
||||||
resp = (yield self._call('getblocktemplate', []))
|
raise
|
||||||
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,7 +69,6 @@ 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
|
||||||
@ -140,12 +139,8 @@ 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 += ntime_bin
|
||||||
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
|
||||||
|
|
||||||
|
|||||||
@ -39,8 +39,8 @@ class CoinbaseTransactionPOW(halfnode.CTransaction):
|
|||||||
tx_out.nValue = value
|
tx_out.nValue = value
|
||||||
tx_out.scriptPubKey = coinbaser.get_script_pubkey()
|
tx_out.scriptPubKey = coinbaser.get_script_pubkey()
|
||||||
|
|
||||||
if settings.COINDAEMON_TX == 'yes':
|
if settings.COINDAEMON_TX != False:
|
||||||
self.strTxComment = "RanchiMall mining"
|
self.strTxComment = "http://github.com/ahmedbodi/stratum-mining"
|
||||||
self.vin.append(tx_in)
|
self.vin.append(tx_in)
|
||||||
self.vout.append(tx_out)
|
self.vout.append(tx_out)
|
||||||
|
|
||||||
@ -87,8 +87,8 @@ class CoinbaseTransactionPOS(halfnode.CTransaction):
|
|||||||
tx_out.scriptPubKey = coinbaser.get_script_pubkey()
|
tx_out.scriptPubKey = coinbaser.get_script_pubkey()
|
||||||
|
|
||||||
self.nTime = ntime
|
self.nTime = ntime
|
||||||
if settings.COINDAEMON_SHA256_TX == 'yes':
|
if settings.COINDAEMON_SHA256_TX != False:
|
||||||
self.strTxComment = "RanchiMall mining"
|
self.strTxComment = "http://github.com/ahmedbodi/stratum-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 = 'riecoin'
|
COINDAEMON_ALGO = 'scrypt'
|
||||||
COINDAEMON_Reward = 'POW'
|
COINDAEMON_Reward = 'POW'
|
||||||
COINDAEMON_SHA256_TX = 'yes'
|
COINDAEMON_SHA256_TX = 'yes'
|
||||||
|
|
||||||
|
|||||||
105
lib/halfnode.py
105
lib/halfnode.py
@ -23,20 +23,18 @@ log.debug("Got to Halfnode")
|
|||||||
if settings.COINDAEMON_ALGO == 'scrypt':
|
if settings.COINDAEMON_ALGO == 'scrypt':
|
||||||
log.debug("########################################### Loading LTC Scrypt #########################################################")
|
log.debug("########################################### Loading LTC Scrypt #########################################################")
|
||||||
import ltc_scrypt
|
import ltc_scrypt
|
||||||
|
elif settings.COINDAEMON_ALGO == 'scrypt-jane':
|
||||||
|
__import__(settings.SCRYPTJANE_NAME)
|
||||||
|
log.debug("########################################### LoadingScrypt jane #########################################################")
|
||||||
elif settings.COINDAEMON_ALGO == 'quark':
|
elif settings.COINDAEMON_ALGO == 'quark':
|
||||||
log.debug("########################################### Loading Quark Support #########################################################")
|
log.debug("########################################### Loading Quark Support #########################################################")
|
||||||
import quark_hash
|
import quark_hash
|
||||||
|
elif settings.COINDAEMON_ALGO == 'skeinhash':
|
||||||
|
import skeinhash
|
||||||
|
|
||||||
else:
|
else:
|
||||||
log.debug("########################################### Loading SHA256 Support ######################################################")
|
log.debug("########################################### Loading SHA256 Support ######################################################")
|
||||||
|
if settings.COINDAEMON_TX != False:
|
||||||
#if settings.COINDAEMON_Reward == 'POS':
|
|
||||||
# log.debug("########################################### Loading POS Support #########################################################")
|
|
||||||
# pass
|
|
||||||
#else:
|
|
||||||
# log.debug("########################################### Loading POW Support ######################################################")
|
|
||||||
# pass
|
|
||||||
|
|
||||||
if settings.COINDAEMON_TX == 'yes':
|
|
||||||
log.debug("########################################### Loading SHA256 Transaction Message Support #########################################################")
|
log.debug("########################################### Loading SHA256 Transaction Message Support #########################################################")
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
@ -158,7 +156,7 @@ class CTransaction(object):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
if settings.COINDAEMON_Reward == 'POW':
|
if settings.COINDAEMON_Reward == 'POW':
|
||||||
self.nVersion = 1
|
self.nVersion = 1
|
||||||
if settings.COINDAEMON_TX == 'yes':
|
if settings.COINDAEMON_TX != False:
|
||||||
self.nVersion = 2
|
self.nVersion = 2
|
||||||
self.vin = []
|
self.vin = []
|
||||||
self.vout = []
|
self.vout = []
|
||||||
@ -166,14 +164,14 @@ class CTransaction(object):
|
|||||||
self.sha256 = None
|
self.sha256 = None
|
||||||
elif settings.COINDAEMON_Reward == 'POS':
|
elif settings.COINDAEMON_Reward == 'POS':
|
||||||
self.nVersion = 1
|
self.nVersion = 1
|
||||||
if settings.COINDAEMON_TX == 'yes':
|
if settings.COINDAEMON_TX != False:
|
||||||
self.nVersion = 2
|
self.nVersion = 2
|
||||||
self.nTime = 0
|
self.nTime = 0
|
||||||
self.vin = []
|
self.vin = []
|
||||||
self.vout = []
|
self.vout = []
|
||||||
self.nLockTime = 0
|
self.nLockTime = 0
|
||||||
self.sha256 = None
|
self.sha256 = None
|
||||||
if settings.COINDAEMON_TX == 'yes':
|
if settings.COINDAEMON_TX != False:
|
||||||
self.strTxComment = ""
|
self.strTxComment = ""
|
||||||
|
|
||||||
def deserialize(self, f):
|
def deserialize(self, f):
|
||||||
@ -190,7 +188,7 @@ class CTransaction(object):
|
|||||||
self.vout = deser_vector(f, CTxOut)
|
self.vout = deser_vector(f, CTxOut)
|
||||||
self.nLockTime = struct.unpack("<I", f.read(4))[0]
|
self.nLockTime = struct.unpack("<I", f.read(4))[0]
|
||||||
self.sha256 = None
|
self.sha256 = None
|
||||||
if settings.COINDAEMON_TX == 'yes':
|
if settings.COINDAEMON_TX != False:
|
||||||
self.strTxComment = deser_string(f)
|
self.strTxComment = deser_string(f)
|
||||||
|
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
@ -207,7 +205,7 @@ class CTransaction(object):
|
|||||||
r += ser_vector(self.vin)
|
r += ser_vector(self.vin)
|
||||||
r += ser_vector(self.vout)
|
r += ser_vector(self.vout)
|
||||||
r += struct.pack("<I", self.nLockTime)
|
r += struct.pack("<I", self.nLockTime)
|
||||||
if settings.COINDAEMON_TX == 'yes':
|
if settings.COINDAEMON_TX != False:
|
||||||
r += ser_string(self.strTxComment)
|
r += ser_string(self.strTxComment)
|
||||||
return r
|
return r
|
||||||
|
|
||||||
@ -236,12 +234,13 @@ class CBlock(object):
|
|||||||
self.vtx = []
|
self.vtx = []
|
||||||
self.sha256 = None
|
self.sha256 = None
|
||||||
if settings.COINDAEMON_ALGO == 'scrypt':
|
if settings.COINDAEMON_ALGO == 'scrypt':
|
||||||
self.scrypt = None
|
self.scrypt= None
|
||||||
|
elif settings.COINDAEMON_ALGO == 'scrypt-jane':
|
||||||
|
self.scryptjane = None
|
||||||
elif settings.COINDAEMON_ALGO == 'quark':
|
elif settings.COINDAEMON_ALGO == 'quark':
|
||||||
self.quark = None
|
self.quark = None
|
||||||
elif settings.COINDAEMON_ALGO == 'riecoin':
|
elif settings.COINDAEMON_ALGO == 'skein':
|
||||||
self.riecoin = None
|
self.skein = None
|
||||||
else: pass
|
|
||||||
if settings.COINDAEMON_Reward == 'POS':
|
if settings.COINDAEMON_Reward == 'POS':
|
||||||
self.signature = b""
|
self.signature = b""
|
||||||
else: pass
|
else: pass
|
||||||
@ -250,14 +249,9 @@ 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.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.nTime = struct.unpack("<II", f.read(8))[0]
|
self.nNonce = struct.unpack("<I", f.read(4))[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)
|
||||||
@ -268,14 +262,9 @@ 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.nTime))
|
||||||
r.append(struct.pack("<I", self.nBits))
|
r.append(struct.pack("<I", self.nBits))
|
||||||
r.append(struct.pack("<Q", self.nTime))
|
r.append(struct.pack("<I", self.nNonce))
|
||||||
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))
|
||||||
@ -306,18 +295,30 @@ 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':
|
elif settings.COINDAEMON_ALGO == 'scrypt-jane':
|
||||||
def calc_riecoin(self):
|
def calc_scryptjane(self):
|
||||||
if self.riecoin is None:
|
if self.scryptjane is None:
|
||||||
r = []
|
r = []
|
||||||
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))
|
||||||
r.append(struct.pack("<I", self.nBits))
|
r.append(struct.pack("<I", self.nBits))
|
||||||
r.append(struct.pack("<Q", self.nTime))
|
r.append(struct.pack("<I", self.nNonce))
|
||||||
sha256 = uint256_from_str(SHA256.new(SHA256.new(''.join(r)).digest()).digest())
|
self.scryptjane = uint256_from_str(settings.SCRYPTJANE_NAME.getPoWHash(''.join(r)))
|
||||||
self.riecoin = riecoinPoW( sha256, uint256_from_compact(self.nBits), self.nNonce )
|
return self.scryptjane
|
||||||
return self.riecoin
|
elif settings.COINDAEMON_ALGO == 'skein':
|
||||||
|
def calc_skein(self):
|
||||||
|
if self.skein is None:
|
||||||
|
r = []
|
||||||
|
r.append(struct.pack("<i", self.nVersion))
|
||||||
|
r.append(ser_uint256(self.hashPrevBlock))
|
||||||
|
r.append(ser_uint256(self.hashMerkleRoot))
|
||||||
|
r.append(struct.pack("<I", self.nTime))
|
||||||
|
r.append(struct.pack("<I", self.nBits))
|
||||||
|
r.append(struct.pack("<I", self.nNonce))
|
||||||
|
self.skein = uint256_from_str(skeinhash.skeinhash(''.join(r)))
|
||||||
|
return self.skein
|
||||||
else:
|
else:
|
||||||
def calc_sha256(self):
|
def calc_sha256(self):
|
||||||
if self.sha256 is None:
|
if self.sha256 is None:
|
||||||
@ -333,29 +334,31 @@ class CBlock(object):
|
|||||||
|
|
||||||
|
|
||||||
def is_valid(self):
|
def is_valid(self):
|
||||||
if settings.COINDAEMON_ALGO == 'riecoin':
|
if settings.COINDAEMON_ALGO == 'scrypt':
|
||||||
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()
|
||||||
|
elif settings.COINDAEMON_ALGO == 'scrypt-jane':
|
||||||
|
self.calc_scryptjane
|
||||||
|
elif settings.COINDAEMON_ALGO == 'skein':
|
||||||
|
self.calc_skein
|
||||||
else:
|
else:
|
||||||
self.calc_sha256()
|
self.calc_sha256()
|
||||||
|
|
||||||
if settings.COINDAEMON_ALGO == 'riecoin':
|
target = uint256_from_compact(self.nBits)
|
||||||
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
|
||||||
elif settings.COINDAEMON_ALGO == 'quark':
|
elif settings.COINDAEMON_ALGO == 'quark':
|
||||||
if self.quark > target:
|
if self.quark > target:
|
||||||
return False
|
return False
|
||||||
|
elif settings.COINDAEMON_ALGO == 'scrypt-jane':
|
||||||
|
if self.scryptjane > target:
|
||||||
|
return False
|
||||||
|
elif settings.COINDAEMON_ALGO == 'skein':
|
||||||
|
if self.skein > target:
|
||||||
|
return False
|
||||||
else:
|
else:
|
||||||
if self.sha256 > target:
|
if self.sha256 > target:
|
||||||
return False
|
return False
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import settings
|
|||||||
if settings.COINDAEMON_ALGO == 'scrypt':
|
if settings.COINDAEMON_ALGO == 'scrypt':
|
||||||
import ltc_scrypt
|
import ltc_scrypt
|
||||||
elif settings.COINDAEMON_ALGO == 'scrypt-jane':
|
elif settings.COINDAEMON_ALGO == 'scrypt-jane':
|
||||||
import yac_scrypt
|
scryptjane = __import__(settings.SCRYPTJANE_NAME)
|
||||||
elif settings.COINDAEMON_ALGO == 'quark':
|
elif settings.COINDAEMON_ALGO == 'quark':
|
||||||
import quark_hash
|
import quark_hash
|
||||||
elif settings.COINDAEMON_ALGO == 'skeinhash':
|
elif settings.COINDAEMON_ALGO == 'skeinhash':
|
||||||
@ -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 Extranonce")
|
log.debug("Getting Unique Extronance")
|
||||||
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,25 +150,25 @@ 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':
|
if settings.COINDAEMON_ALGO == 'scrypt' or 'scrypt-jane':
|
||||||
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
|
||||||
|
|
||||||
return diff1 / difficulty
|
return diff1 / difficulty
|
||||||
|
|
||||||
def get_job(self, job_id):
|
def get_job(self, job_id, worker_name, ip=False):
|
||||||
'''For given job_id returns BlockTemplate instance or None'''
|
'''For given job_id returns BlockTemplate instance or None'''
|
||||||
try:
|
try:
|
||||||
j = self.jobs[job_id]
|
j = self.jobs[job_id]
|
||||||
except:
|
except:
|
||||||
log.info("Job id '%s' not found" % job_id)
|
log.info("Job id '%s' not found, worker_name: '%s'" % (job_id, worker_name))
|
||||||
|
|
||||||
|
if ip:
|
||||||
|
log.info("Worker submited invalid Job id: IP %s", str(ip))
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Now we have to check if job is still valid.
|
# Now we have to check if job is still valid.
|
||||||
@ -185,7 +185,7 @@ class TemplateRegistry(object):
|
|||||||
return j
|
return j
|
||||||
|
|
||||||
def submit_share(self, job_id, worker_name, session, extranonce1_bin, extranonce2, ntime, nonce,
|
def submit_share(self, job_id, worker_name, session, extranonce1_bin, extranonce2, ntime, nonce,
|
||||||
difficulty):
|
difficulty, ip=False):
|
||||||
'''Check parameters and finalize block template. If it leads
|
'''Check parameters and finalize block template. If it leads
|
||||||
to valid block candidate, asynchronously submits the block
|
to valid block candidate, asynchronously submits the block
|
||||||
back to the bitcoin network.
|
back to the bitcoin network.
|
||||||
@ -201,28 +201,20 @@ class TemplateRegistry(object):
|
|||||||
raise SubmitException("Incorrect size of extranonce2. Expected %d chars" % (self.extranonce2_size*2))
|
raise SubmitException("Incorrect size of extranonce2. Expected %d chars" % (self.extranonce2_size*2))
|
||||||
|
|
||||||
# Check for job
|
# Check for job
|
||||||
job = self.get_job(job_id)
|
job = self.get_job(job_id, worker_name, ip)
|
||||||
if job == None:
|
if job == None:
|
||||||
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) != 8:
|
||||||
if len(ntime) != 16:
|
raise SubmitException("Incorrect size of ntime. Expected 8 chars")
|
||||||
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 settings.COINDAEMON_ALGO == 'riecoin':
|
if len(nonce) != 8:
|
||||||
if len(nonce) != 64:
|
raise SubmitException("Incorrect size of nonce. Expected 8 chars")
|
||||||
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):
|
||||||
@ -237,9 +229,6 @@ 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)
|
||||||
@ -256,7 +245,10 @@ class TemplateRegistry(object):
|
|||||||
if settings.COINDAEMON_ALGO == 'scrypt':
|
if settings.COINDAEMON_ALGO == 'scrypt':
|
||||||
hash_bin = ltc_scrypt.getPoWHash(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]))
|
hash_bin = ltc_scrypt.getPoWHash(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]))
|
||||||
elif settings.COINDAEMON_ALGO == 'scrypt-jane':
|
elif settings.COINDAEMON_ALGO == 'scrypt-jane':
|
||||||
hash_bin = yac_scrypt.getPoWHash(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]), int(ntime, 16))
|
if settings.SCRYPTJANE_NAME == 'vtc_scrypt':
|
||||||
|
hash_bin = scryptjane.getPoWHash(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]))
|
||||||
|
else:
|
||||||
|
hash_bin = scryptjane.getPoWHash(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]), int(ntime, 16))
|
||||||
elif settings.COINDAEMON_ALGO == 'quark':
|
elif settings.COINDAEMON_ALGO == 'quark':
|
||||||
hash_bin = quark_hash.getPoWHash(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]))
|
hash_bin = quark_hash.getPoWHash(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 20) ]))
|
||||||
elif settings.COINDAEMON_ALGO == 'skeinhash':
|
elif settings.COINDAEMON_ALGO == 'skeinhash':
|
||||||
@ -266,58 +258,40 @@ 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:
|
||||||
if hash_int < target_user:
|
raise SubmitException("Share is above target")
|
||||||
raise SubmitException("Share does not meet target")
|
|
||||||
else:
|
# Mostly for debugging purposes
|
||||||
if hash_int > target_user:
|
target_info = self.diff_to_target(100000)
|
||||||
raise SubmitException("Share is above target")
|
if hash_int <= target_info:
|
||||||
# Mostly for debugging purposes
|
log.info("Yay, share with diff above 100000")
|
||||||
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
|
||||||
isBlockCandidate = False
|
if hash_int <= job.target:
|
||||||
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 == 'riecoin':
|
#if settings.COINDAEMON_ALGO == 'scrypt' or settings.COINDAEMON_ALGO == 'sha256d':
|
||||||
block_hash_bin = util.doublesha(''.join([ header_bin[i*4:i*4+4][::-1] for i in range(0, 28) ]))
|
# if settings.COINDAEMON_Reward == 'POW':
|
||||||
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))
|
||||||
|
|
||||||
if not job.is_valid():
|
if not job.is_valid():
|
||||||
# Should not happen
|
# Should not happen
|
||||||
log.exception("FINAL JOB VALIDATION FAILED!(Try enabling/disabling tx messages)")
|
log.exception("FINAL JOB VALIDATION FAILED!(Try enabling/disabling tx messages)")
|
||||||
@ -335,10 +309,7 @@ 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, 20) ]))
|
||||||
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,10 +56,7 @@ 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 * (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):
|
||||||
@ -214,54 +211,6 @@ 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,13 +179,6 @@ 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
|
||||||
@ -194,10 +187,7 @@ class DBInterface():
|
|||||||
return self.dbi.list_users()
|
return self.dbi.list_users()
|
||||||
|
|
||||||
def get_user(self, id):
|
def get_user(self, id):
|
||||||
if self.cache.get(id) is None:
|
return self.dbi.get_user(id)
|
||||||
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:
|
||||||
|
|||||||
@ -342,13 +342,28 @@ 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)
|
||||||
query = "INSERT INTO pool_worker"
|
query = "INSERT INTO pool_worker"
|
||||||
self.execute(query + '(account_id, username, password) VALUES (%s, %s, %s);', (account_id, username, password))
|
self.execute(query + '(account_id, username, password) VALUES (%s, %s, %s);', (account_id, username, password))
|
||||||
self.dbh.commit()
|
self.dbh.commit()
|
||||||
return str(username)
|
return str(username)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
self.dbh.close()
|
self.dbh.close()
|
||||||
|
|||||||
@ -7,7 +7,6 @@ import simplejson as json
|
|||||||
from twisted.internet import reactor
|
from twisted.internet import reactor
|
||||||
import threading
|
import threading
|
||||||
from mining.work_log_pruner import WorkLogPruner
|
from mining.work_log_pruner import WorkLogPruner
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def setup(on_startup):
|
def setup(on_startup):
|
||||||
'''Setup mining service internal environment.
|
'''Setup mining service internal environment.
|
||||||
@ -17,11 +16,13 @@ def setup(on_startup):
|
|||||||
*before* you call setup() in the launcher script.'''
|
*before* you call setup() in the launcher script.'''
|
||||||
|
|
||||||
import lib.settings as settings
|
import lib.settings as settings
|
||||||
|
|
||||||
# Get logging online as soon as possible
|
# Get logging online as soon as possible
|
||||||
import lib.logger
|
import lib.logger
|
||||||
log = lib.logger.get_logger('mining')
|
log = lib.logger.get_logger('mining')
|
||||||
|
if settings.CONFIG_VERSION == None:
|
||||||
|
settings.CONFIG_VERSION = 0
|
||||||
|
else: pass
|
||||||
from interfaces import Interfaces
|
from interfaces import Interfaces
|
||||||
|
|
||||||
from lib.block_updater import BlockUpdater
|
from lib.block_updater import BlockUpdater
|
||||||
@ -31,7 +32,6 @@ def setup(on_startup):
|
|||||||
from lib.coinbaser import SimpleCoinbaser
|
from lib.coinbaser import SimpleCoinbaser
|
||||||
|
|
||||||
bitcoin_rpc = BitcoinRPCManager()
|
bitcoin_rpc = BitcoinRPCManager()
|
||||||
|
|
||||||
# Check litecoind
|
# Check litecoind
|
||||||
# Check we can connect (sleep)
|
# Check we can connect (sleep)
|
||||||
# Check the results:
|
# Check the results:
|
||||||
@ -41,7 +41,7 @@ def setup(on_startup):
|
|||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
result = (yield bitcoin_rpc.check_submitblock())
|
result = (yield bitcoin_rpc.check_submitblock())
|
||||||
if result == True:
|
if result == True:
|
||||||
log.info("Found submitblock")
|
log.info("Found submitblock")
|
||||||
elif result == False:
|
elif result == False:
|
||||||
log.info("Did not find submitblock")
|
log.info("Did not find submitblock")
|
||||||
@ -98,7 +98,12 @@ def setup(on_startup):
|
|||||||
time.sleep(1) # If we didn't get a result or the connect failed
|
time.sleep(1) # If we didn't get a result or the connect failed
|
||||||
|
|
||||||
log.info('Connected to the coind - Begining to load Address and Module Checks!')
|
log.info('Connected to the coind - Begining to load Address and Module Checks!')
|
||||||
|
try:
|
||||||
|
if settings.CONFIG_VERSION != 0.1:
|
||||||
|
log.exception("Config File Out OF Date")
|
||||||
|
reactor.stop()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
# Start the coinbaser
|
# Start the coinbaser
|
||||||
coinbaser = SimpleCoinbaser(bitcoin_rpc, getattr(settings, 'CENTRAL_WALLET'))
|
coinbaser = SimpleCoinbaser(bitcoin_rpc, getattr(settings, 'CENTRAL_WALLET'))
|
||||||
(yield coinbaser.on_load)
|
(yield coinbaser.on_load)
|
||||||
|
|||||||
@ -87,7 +87,7 @@ class MiningService(GenericService):
|
|||||||
else:
|
else:
|
||||||
session['difficulty'] = settings.POOL_TARGET
|
session['difficulty'] = settings.POOL_TARGET
|
||||||
# worker_log = (valid, invalid, is_banned, diff, is_ext_diff, timestamp)
|
# worker_log = (valid, invalid, is_banned, diff, is_ext_diff, timestamp)
|
||||||
Interfaces.worker_manager.worker_log['authorized'][worker_name] = (0, 0, False, session['difficulty'], is_ext_diff, Interfaces.timestamper.time())
|
Interfaces.worker_manager.worker_log['authorized'][worker_name] = (0, 0, False, session['difficulty'], is_ext_diff, Interfaces.timestamper.time())
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
ip = self.connection_ref()._get_ip()
|
ip = self.connection_ref()._get_ip()
|
||||||
@ -169,7 +169,7 @@ class MiningService(GenericService):
|
|||||||
# and it is valid proof of work.
|
# and it is valid proof of work.
|
||||||
try:
|
try:
|
||||||
(block_header, block_hash, share_diff, on_submit) = Interfaces.template_registry.submit_share(job_id,
|
(block_header, block_hash, share_diff, on_submit) = Interfaces.template_registry.submit_share(job_id,
|
||||||
worker_name, session, extranonce1_bin, extranonce2, ntime, nonce, difficulty)
|
worker_name, session, extranonce1_bin, extranonce2, ntime, nonce, difficulty, ip)
|
||||||
except SubmitException as e:
|
except SubmitException as e:
|
||||||
# block_header and block_hash are None when submitted data are corrupted
|
# block_header and block_hash are None when submitted data are corrupted
|
||||||
invalid += 1
|
invalid += 1
|
||||||
|
|||||||
@ -1,34 +1,48 @@
|
|||||||
|
# This File is used to create a list of requirements needed for testing stratum-mining or to create a clone install
|
||||||
BeautifulSoup==3.2.1
|
BeautifulSoup==3.2.1
|
||||||
Jinja2==2.7.2
|
#Brlapi==0.5.7
|
||||||
Magic-file-extensions==0.2
|
#GnuPGInterface==0.3.2
|
||||||
MarkupSafe==0.18
|
MySQL-python==1.2.3
|
||||||
MySQL-python==1.2.5
|
#PAM==0.4.2
|
||||||
PyYAML==3.10
|
#Pyste==0.9.10
|
||||||
Twisted==13.2.0
|
#SOAPpy==0.12.0
|
||||||
ansible==1.4.5
|
Twisted==12.0.0
|
||||||
|
#Twisted-Conch==12.0.0
|
||||||
|
#Twisted-Core==12.0.0
|
||||||
|
#Twisted-Lore==12.0.0
|
||||||
|
#Twisted-Mail==12.0.0
|
||||||
|
#Twisted-Names==12.0.0
|
||||||
|
#Twisted-News==12.0.0
|
||||||
|
#Twisted-Runner==12.0.0
|
||||||
|
#Twisted-Web==12.0.0
|
||||||
|
#Twisted-Words==12.0.0
|
||||||
|
#apt-xapian-index==0.45
|
||||||
argparse==1.2.1
|
argparse==1.2.1
|
||||||
autobahn==0.8.4-3
|
autobahn==0.6.5
|
||||||
cffi==0.8.2
|
#chardet==2.0.1
|
||||||
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.3
|
feedparser==5.1.2
|
||||||
fpconst==0.7.2
|
fpconst==0.7.2
|
||||||
httplib2==0.8
|
httplib2==0.7.4
|
||||||
numpy==1.7.1
|
#louis==2.4.1
|
||||||
paramiko==1.12.1
|
#ltc-scrypt==1.0
|
||||||
pyOpenSSL==0.14
|
#numpy==1.6.2
|
||||||
pyasn1==0.1.7
|
pyOpenSSL==0.13
|
||||||
pycparser==2.10
|
pyasn1==0.1.3
|
||||||
pycrypto==2.6.1
|
pycrypto==2.6
|
||||||
pylibmc==1.2.3
|
#pycurl==7.19.0
|
||||||
pyserial==2.7
|
pyserial==2.5
|
||||||
python-dateutil==2.1
|
#python-apt==0.8.8.2
|
||||||
python-memcached==1.53
|
#python-debian==0.1.21
|
||||||
pyxdg==0.25
|
#python-debianbts==1.11
|
||||||
requests==2.2.0
|
python-memcached==1.48
|
||||||
simplejson==3.3.3
|
pyxdg==0.19
|
||||||
six==1.4.1
|
#reportbug==6.4.4
|
||||||
wsgiref==0.1.2
|
simplejson==2.5.2
|
||||||
zope.interface==4.1.0
|
#stratum==0.2.13
|
||||||
stratum==0.2.15
|
#uTidylib==0.2
|
||||||
|
#unattended-upgrades==0.1
|
||||||
|
#wsgiref==0.1.2
|
||||||
|
zope.interface==3.6.1
|
||||||
|
|||||||
@ -1,260 +0,0 @@
|
|||||||
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
|
|
||||||
SET time_zone = "+00:00";
|
|
||||||
|
|
||||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
|
||||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
|
||||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
|
||||||
/*!40101 SET NAMES utf8 */;
|
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `accounts` (
|
|
||||||
`id` int(255) NOT NULL AUTO_INCREMENT,
|
|
||||||
`is_admin` tinyint(1) NOT NULL DEFAULT '0',
|
|
||||||
`is_anonymous` tinyint(1) NOT NULL DEFAULT '0',
|
|
||||||
`no_fees` tinyint(1) NOT NULL DEFAULT '0',
|
|
||||||
`username` varchar(40) NOT NULL,
|
|
||||||
`pass` varchar(255) NOT NULL,
|
|
||||||
`email` varchar(255) DEFAULT NULL COMMENT 'Assocaited email: used for validating users, and re-setting passwords',
|
|
||||||
`timezone` varchar(35) NOT NULL DEFAULT '415',
|
|
||||||
`notify_email` VARCHAR( 255 ) NULL DEFAULT NULL,
|
|
||||||
`loggedIp` varchar(255) DEFAULT NULL,
|
|
||||||
`is_locked` tinyint(1) NOT NULL DEFAULT '0',
|
|
||||||
`failed_logins` int(5) unsigned DEFAULT '0',
|
|
||||||
`failed_pins` int(5) unsigned DEFAULT '0',
|
|
||||||
`signup_timestamp` int(10) DEFAULT '0',
|
|
||||||
`last_login` int(10) DEFAULT NULL,
|
|
||||||
`pin` varchar(255) NOT NULL COMMENT 'four digit pin to allow account changes',
|
|
||||||
`api_key` varchar(255) DEFAULT NULL,
|
|
||||||
`token` varchar(65) DEFAULT NULL,
|
|
||||||
`donate_percent` float DEFAULT '0',
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `username` (`username`),
|
|
||||||
UNIQUE KEY `email` (`email`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `blocks` (
|
|
||||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
|
||||||
`height` int(10) unsigned NOT NULL,
|
|
||||||
`blockhash` char(65) NOT NULL,
|
|
||||||
`confirmations` int(10) NOT NULL,
|
|
||||||
`amount` double NOT NULL,
|
|
||||||
`difficulty` double NOT NULL,
|
|
||||||
`time` int(11) NOT NULL,
|
|
||||||
`accounted` tinyint(1) NOT NULL DEFAULT '0',
|
|
||||||
`account_id` int(255) unsigned DEFAULT NULL,
|
|
||||||
`worker_name` varchar(50) DEFAULT 'unknown',
|
|
||||||
`shares` double unsigned DEFAULT NULL,
|
|
||||||
`share_id` bigint(30) DEFAULT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `height` (`height`,`blockhash`),
|
|
||||||
KEY `time` (`time`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Discovered blocks persisted from Litecoin Service';
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `coin_addresses` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`account_id` int(11) NOT NULL,
|
|
||||||
`currency` varchar(5) NOT NULL,
|
|
||||||
`coin_address` varchar(255) NOT NULL,
|
|
||||||
`ap_threshold` float DEFAULT '0',
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `coin_address` (`coin_address`),
|
|
||||||
KEY `account_id` (`account_id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `invitations` (
|
|
||||||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
|
||||||
`account_id` int(11) unsigned NOT NULL,
|
|
||||||
`email` varchar(50) NOT NULL,
|
|
||||||
`token_id` int(11) NOT NULL,
|
|
||||||
`is_activated` tinyint(1) NOT NULL DEFAULT '0',
|
|
||||||
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `monitoring` (
|
|
||||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
|
||||||
`name` varchar(30) NOT NULL,
|
|
||||||
`type` varchar(15) NOT NULL,
|
|
||||||
`value` varchar(255) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `name` (`name`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Monitoring events from cronjobs';
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `news` (
|
|
||||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
|
||||||
`account_id` int(10) unsigned NOT NULL,
|
|
||||||
`header` varchar(255) NOT NULL,
|
|
||||||
`content` text NOT NULL,
|
|
||||||
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
`active` tinyint(1) NOT NULL DEFAULT '0',
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `notifications` (
|
|
||||||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
|
||||||
`type` varchar(25) NOT NULL,
|
|
||||||
`data` varchar(255) NOT NULL,
|
|
||||||
`active` tinyint(1) NOT NULL DEFAULT '1',
|
|
||||||
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
`account_id` int(10) unsigned DEFAULT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `active` (`active`),
|
|
||||||
KEY `data` (`data`),
|
|
||||||
KEY `account_id` (`account_id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `notification_settings` (
|
|
||||||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
|
||||||
`type` varchar(15) NOT NULL,
|
|
||||||
`account_id` int(11) NOT NULL,
|
|
||||||
`active` tinyint(1) NOT NULL DEFAULT '0',
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `account_id` (`account_id`),
|
|
||||||
UNIQUE KEY `account_id_type` (`account_id`,`type`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `payouts` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`account_id` int(11) NOT NULL,
|
|
||||||
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
`completed` tinyint(1) NOT NULL DEFAULT '0',
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `account_id` (`account_id`,`completed`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `pool_worker` (
|
|
||||||
`id` int(255) NOT NULL AUTO_INCREMENT,
|
|
||||||
`account_id` int(255) NOT NULL,
|
|
||||||
`username` char(50) DEFAULT NULL,
|
|
||||||
`password` char(255) DEFAULT NULL,
|
|
||||||
`difficulty` float NOT NULL DEFAULT '0',
|
|
||||||
`monitor` tinyint(1) NOT NULL DEFAULT '0',
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `username` (`username`),
|
|
||||||
KEY `account_id` (`account_id`),
|
|
||||||
KEY `pool_worker_username` (`username`(10))
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `settings` (
|
|
||||||
`name` varchar(255) NOT NULL,
|
|
||||||
`value` text DEFAULT NULL,
|
|
||||||
PRIMARY KEY (`name`),
|
|
||||||
UNIQUE KEY `setting` (`name`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
INSERT INTO `settings` (`name`, `value`) VALUES ('DB_VERSION', '1.0.3');
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `shares` (
|
|
||||||
`id` bigint(30) NOT NULL AUTO_INCREMENT,
|
|
||||||
`rem_host` varchar(255) NOT NULL,
|
|
||||||
`username` varchar(120) NOT NULL,
|
|
||||||
`our_result` enum('Y','N') NOT NULL,
|
|
||||||
`upstream_result` enum('Y','N') DEFAULT NULL,
|
|
||||||
`reason` varchar(50) DEFAULT NULL,
|
|
||||||
`solution` varchar(257) NOT NULL,
|
|
||||||
`difficulty` float NOT NULL DEFAULT '0',
|
|
||||||
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `time` (`time`),
|
|
||||||
KEY `upstream_result` (`upstream_result`),
|
|
||||||
KEY `our_result` (`our_result`),
|
|
||||||
KEY `username` (`username`),
|
|
||||||
KEY `shares_username` (`username`(10))
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `shares_archive` (
|
|
||||||
`id` bigint(30) unsigned NOT NULL AUTO_INCREMENT,
|
|
||||||
`share_id` bigint(30) unsigned NOT NULL,
|
|
||||||
`username` varchar(120) NOT NULL,
|
|
||||||
`our_result` enum('Y','N') DEFAULT NULL,
|
|
||||||
`upstream_result` enum('Y','N') DEFAULT NULL,
|
|
||||||
`block_id` int(10) unsigned NOT NULL,
|
|
||||||
`difficulty` float NOT NULL DEFAULT '0',
|
|
||||||
`time` datetime NOT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `share_id` (`share_id`),
|
|
||||||
KEY `time` (`time`),
|
|
||||||
KEY `our_result` (`our_result`),
|
|
||||||
KEY `username` (`username`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Archive shares for potential later debugging purposes';
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `statistics_shares` (
|
|
||||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
|
||||||
`account_id` int(10) unsigned NOT NULL,
|
|
||||||
`block_id` int(10) unsigned NOT NULL,
|
|
||||||
`valid` float unsigned NOT NULL DEFAULT '0',
|
|
||||||
`invalid` float unsigned NOT NULL DEFAULT '0',
|
|
||||||
`pplns_valid` float unsigned NOT NULL DEFAULT '0',
|
|
||||||
`pplns_invalid` float unsigned NOT NULL DEFAULT '0',
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `account_id` (`account_id`),
|
|
||||||
KEY `block_id` (`block_id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `tokens` (
|
|
||||||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
|
||||||
`account_id` int(11) NOT NULL,
|
|
||||||
`token` varchar(65) NOT NULL,
|
|
||||||
`type` tinyint(4) NOT NULL,
|
|
||||||
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `token` (`token`),
|
|
||||||
KEY `account_id` (`account_id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `token_types` (
|
|
||||||
`id` tinyint(4) unsigned NOT NULL AUTO_INCREMENT,
|
|
||||||
`name` varchar(25) NOT NULL,
|
|
||||||
`expiration` INT NULL DEFAULT '0',
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `name` (`name`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
INSERT INTO `token_types` (`id`, `name`, `expiration`) VALUES
|
|
||||||
(1, 'password_reset', 3600),
|
|
||||||
(2, 'confirm_email', 0),
|
|
||||||
(3, 'invitation', 0),
|
|
||||||
(4, 'account_unlock', 0),
|
|
||||||
(5, 'account_edit', 3600),
|
|
||||||
(6, 'change_pw', 3600),
|
|
||||||
(7, 'withdraw_funds', 3600);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `transactions` (
|
|
||||||
`id` int(255) NOT NULL AUTO_INCREMENT,
|
|
||||||
`account_id` int(255) unsigned NOT NULL,
|
|
||||||
`type` varchar(25) DEFAULT NULL,
|
|
||||||
`coin_address` varchar(255) DEFAULT NULL,
|
|
||||||
`amount` decimal(50,30) DEFAULT '0',
|
|
||||||
`block_id` int(255) DEFAULT NULL,
|
|
||||||
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
`txid` varchar(256) DEFAULT NULL,
|
|
||||||
`archived` tinyint(1) NOT NULL DEFAULT '0',
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `block_id` (`block_id`),
|
|
||||||
KEY `account_id` (`account_id`),
|
|
||||||
KEY `type` (`type`),
|
|
||||||
KEY `archived` (`archived`),
|
|
||||||
KEY `account_id_archived` (`account_id`,`archived`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
CREATE TABLE `statistics_users` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`account_id` int(11) NOT NULL,
|
|
||||||
`hashrate` bigint(20) unsigned NOT NULL,
|
|
||||||
`workers` int(11) NOT NULL,
|
|
||||||
`sharerate` float NOT NULL,
|
|
||||||
`timestamp` int(11) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `account_id_timestamp` (`account_id`,`timestamp`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `user_settings` (
|
|
||||||
`account_id` int(11) NOT NULL,
|
|
||||||
`name` varchar(50) NOT NULL,
|
|
||||||
`value` text DEFAULT NULL,
|
|
||||||
PRIMARY KEY (`account_id`,`name`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
|
|
||||||
|
|
||||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
|
||||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
|
||||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
|
||||||
Loading…
Reference in New Issue
Block a user