commit
7eff92e941
10
README.md
10
README.md
@ -1,3 +1,4 @@
|
||||
[ ](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.
|
||||
|
||||
@ -33,7 +34,7 @@ The goal is to make a reliable stratum mining server for scrypt based coins. Ove
|
||||
* Doge: DLtBRYtNCzfiZfcpUeEr8KPvy5k1aR7jca
|
||||
* SRC: sMP2wHN5H2ik7FQDPjhSzFZUWux75BYZGe
|
||||
* ARG: AQvXPWVqGzcpH2j2XSRG7X5R9nA3y9D9aQ
|
||||
|
||||
* CryptsyTradeKey: ec13d183e304326ebd41258d6ae7188e303866fe
|
||||
|
||||
|
||||
#Requirements
|
||||
@ -61,6 +62,7 @@ Other coins have been known to work with this implementation. I have tested with
|
||||
* Franko
|
||||
* Quark
|
||||
* Securecoin
|
||||
|
||||
#Installation
|
||||
|
||||
The installation of this *stratum-mining* can be found in the Repo Wiki.
|
||||
@ -68,16 +70,10 @@ The installation of this *stratum-mining* can be found in the Repo Wiki.
|
||||
#Contact
|
||||
I am available in the #MPOS, #crypto-expert, #digitalcoin, and #worldcoin channels on freenode.
|
||||
Although i am willing to provide support through IRC please file issues on the repo.
|
||||
<<<<<<< HEAD
|
||||
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.
|
||||
|
||||
=======
|
||||
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 (original stratum code)
|
||||
|
||||
2
TODO
Normal file
2
TODO
Normal file
@ -0,0 +1,2 @@
|
||||
1) Flush shares on block find
|
||||
2) Add Autoloading of databases
|
||||
@ -21,11 +21,8 @@ COINDAEMON_TRUSTED_PASSWORD = 'somepassword'
|
||||
# The available options are:
|
||||
# scrypt, sha256d, scrypt-jane and quark
|
||||
# If the option does not meet either of these criteria stratum defaults to scrypt
|
||||
# Until AutoReward Selecting Code has been implemented the below options are used to select the type of coin
|
||||
# For Reward type there is POW and POS. please ensure you choose the currect type.
|
||||
# For Coins which support TX Messages please enter yes in the TX selection
|
||||
COINDAEMON_ALGO = 'scrypt'
|
||||
COINDAEMON_Reward = 'POW'
|
||||
COINDAEMON_TX = 'no'
|
||||
# ******************** BASIC SETTINGS ***************
|
||||
# Backup Coin Daemon address's (consider having at least 1 backup)
|
||||
|
||||
@ -5,6 +5,8 @@ import struct
|
||||
import util
|
||||
import merkletree
|
||||
import halfnode
|
||||
from coinbasetx import CoinbaseTransactionPOW
|
||||
from coinbasetx import CoinbaseTransactionPOS
|
||||
from coinbasetx import CoinbaseTransaction
|
||||
import lib.logger
|
||||
log = lib.logger.get_logger('block_template')
|
||||
@ -55,10 +57,10 @@ class BlockTemplate(halfnode.CBlock):
|
||||
txhashes = [None] + [ util.ser_uint256(int(t['hash'], 16)) for t in data['transactions'] ]
|
||||
mt = merkletree.MerkleTree(txhashes)
|
||||
if settings.COINDAEMON_Reward == 'POW':
|
||||
coinbase = self.coinbase_transaction_class(self.timestamper, self.coinbaser, data['coinbasevalue'], data['coinbaseaux']['flags'], data['height'],
|
||||
coinbase = CoinbaseTransactionPOW(self.timestamper, self.coinbaser, data['coinbasevalue'], data['coinbaseaux']['flags'], data['height'],
|
||||
settings.COINBASE_EXTRAS)
|
||||
else:
|
||||
coinbase = self.coinbase_transaction_class(self.timestamper, self.coinbaser, data['coinbasevalue'], data['coinbaseaux']['flags'], data['height'],
|
||||
coinbase = CoinbaseTransactionPOS(self.timestamper, self.coinbaser, data['coinbasevalue'], data['coinbaseaux']['flags'], data['height'],
|
||||
settings.COINBASE_EXTRAS, data['curtime'])
|
||||
|
||||
self.height = data['height']
|
||||
|
||||
@ -6,8 +6,8 @@ import settings
|
||||
import lib.logger
|
||||
log = lib.logger.get_logger('coinbasetx')
|
||||
|
||||
if settings.COINDAEMON_Reward == 'POW':
|
||||
class CoinbaseTransaction(halfnode.CTransaction):
|
||||
#if settings.COINDAEMON_Reward == 'POW':
|
||||
class CoinbaseTransactionPOW(halfnode.CTransaction):
|
||||
'''Construct special transaction used for coinbase tx.
|
||||
It also implements quick serialization using pre-cached
|
||||
scriptSig template.'''
|
||||
@ -17,8 +17,8 @@ if settings.COINDAEMON_Reward == 'POW':
|
||||
extranonce_size = struct.calcsize(extranonce_type)
|
||||
|
||||
def __init__(self, timestamper, coinbaser, value, flags, height, data):
|
||||
super(CoinbaseTransaction, self).__init__()
|
||||
log.debug("Got to CoinBaseTX")
|
||||
super(CoinbaseTransactionPOW, self).__init__()
|
||||
log.debug("Got to CoinBaseTX")
|
||||
#self.extranonce = 0
|
||||
|
||||
if len(self.extranonce_placeholder) != self.extranonce_size:
|
||||
@ -45,7 +45,7 @@ if settings.COINDAEMON_Reward == 'POW':
|
||||
self.vout.append(tx_out)
|
||||
|
||||
# Two parts of serialized coinbase, just put part1 + extranonce + part2 to have final serialized tx
|
||||
self._serialized = super(CoinbaseTransaction, self).serialize().split(self.extranonce_placeholder)
|
||||
self._serialized = super(CoinbaseTransactionPOW, self).serialize().split(self.extranonce_placeholder)
|
||||
|
||||
def set_extranonce(self, extranonce):
|
||||
if len(extranonce) != self.extranonce_size:
|
||||
@ -53,8 +53,56 @@ if settings.COINDAEMON_Reward == 'POW':
|
||||
|
||||
(part1, part2) = self.vin[0]._scriptSig_template
|
||||
self.vin[0].scriptSig = part1 + extranonce + part2
|
||||
elif settings.COINDAEMON_Reward == 'POS':
|
||||
class CoinbaseTransaction(halfnode.CTransaction):
|
||||
#elif settings.COINDAEMON_Reward == 'POS':
|
||||
class CoinbaseTransactionPOS(halfnode.CTransaction):
|
||||
'''Construct special transaction used for coinbase tx.
|
||||
It also implements quick serialization using pre-cached
|
||||
scriptSig template.'''
|
||||
|
||||
extranonce_type = '>Q'
|
||||
extranonce_placeholder = struct.pack(extranonce_type, int('f000000ff111111f', 16))
|
||||
extranonce_size = struct.calcsize(extranonce_type)
|
||||
|
||||
def __init__(self, timestamper, coinbaser, value, flags, height, data, ntime):
|
||||
super(CoinbaseTransactionPOS, self).__init__()
|
||||
log.debug("Got to CoinBaseTX")
|
||||
#self.extranonce = 0
|
||||
|
||||
if len(self.extranonce_placeholder) != self.extranonce_size:
|
||||
raise Exception("Extranonce placeholder don't match expected length!")
|
||||
|
||||
tx_in = halfnode.CTxIn()
|
||||
tx_in.prevout.hash = 0L
|
||||
tx_in.prevout.n = 2**32-1
|
||||
tx_in._scriptSig_template = (
|
||||
util.ser_number(height) + binascii.unhexlify(flags) + util.ser_number(int(timestamper.time())) + \
|
||||
chr(self.extranonce_size),
|
||||
util.ser_string(coinbaser.get_coinbase_data() + data)
|
||||
)
|
||||
|
||||
tx_in.scriptSig = tx_in._scriptSig_template[0] + self.extranonce_placeholder + tx_in._scriptSig_template[1]
|
||||
|
||||
tx_out = halfnode.CTxOut()
|
||||
tx_out.nValue = value
|
||||
tx_out.scriptPubKey = coinbaser.get_script_pubkey()
|
||||
|
||||
self.nTime = ntime
|
||||
if settings.COINDAEMON_SHA256_TX == 'yes':
|
||||
self.strTxComment = "http://github.com/ahmedbodi/stratum-mining"
|
||||
self.vin.append(tx_in)
|
||||
self.vout.append(tx_out)
|
||||
|
||||
# Two parts of serialized coinbase, just put part1 + extranonce + part2 to have final serialized tx
|
||||
self._serialized = super(CoinbaseTransactionPOS, self).serialize().split(self.extranonce_placeholder)
|
||||
|
||||
def set_extranonce(self, extranonce):
|
||||
if len(extranonce) != self.extranonce_size:
|
||||
raise Exception("Incorrect extranonce size")
|
||||
|
||||
(part1, part2) = self.vin[0]._scriptSig_template
|
||||
self.vin[0].scriptSig = part1 + extranonce + part2
|
||||
#else:
|
||||
class CoinbaseTransaction(halfnode.CTransaction):
|
||||
'''Construct special transaction used for coinbase tx.
|
||||
It also implements quick serialization using pre-cached
|
||||
scriptSig template.'''
|
||||
@ -86,54 +134,6 @@ elif settings.COINDAEMON_Reward == 'POS':
|
||||
tx_out.nValue = value
|
||||
tx_out.scriptPubKey = coinbaser.get_script_pubkey()
|
||||
|
||||
self.nTime = ntime
|
||||
if settings.COINDAEMON_SHA256_TX == 'yes':
|
||||
self.strTxComment = "http://github.com/ahmedbodi/stratum-mining"
|
||||
self.vin.append(tx_in)
|
||||
self.vout.append(tx_out)
|
||||
|
||||
# Two parts of serialized coinbase, just put part1 + extranonce + part2 to have final serialized tx
|
||||
self._serialized = super(CoinbaseTransaction, self).serialize().split(self.extranonce_placeholder)
|
||||
|
||||
def set_extranonce(self, extranonce):
|
||||
if len(extranonce) != self.extranonce_size:
|
||||
raise Exception("Incorrect extranonce size")
|
||||
|
||||
(part1, part2) = self.vin[0]._scriptSig_template
|
||||
self.vin[0].scriptSig = part1 + extranonce + part2
|
||||
else:
|
||||
class CoinbaseTransaction(halfnode.CTransaction):
|
||||
'''Construct special transaction used for coinbase tx.
|
||||
It also implements quick serialization using pre-cached
|
||||
scriptSig template.'''
|
||||
|
||||
extranonce_type = '>Q'
|
||||
extranonce_placeholder = struct.pack(extranonce_type, int('f000000ff111111f', 16))
|
||||
extranonce_size = struct.calcsize(extranonce_type)
|
||||
|
||||
def __init__(self, timestamper, coinbaser, value, flags, height, data, ntime):
|
||||
super(CoinbaseTransaction, self).__init__()
|
||||
log.debug("Got to CoinBaseTX")
|
||||
#self.extranonce = 0
|
||||
|
||||
if len(self.extranonce_placeholder) != self.extranonce_size:
|
||||
raise Exception("Extranonce placeholder don't match expected length!")
|
||||
|
||||
tx_in = halfnode.CTxIn()
|
||||
tx_in.prevout.hash = 0L
|
||||
tx_in.prevout.n = 2**32-1
|
||||
tx_in._scriptSig_template = (
|
||||
util.ser_number(height) + binascii.unhexlify(flags) + util.ser_number(int(timestamper.time())) + \
|
||||
chr(self.extranonce_size),
|
||||
util.ser_string(coinbaser.get_coinbase_data() + data)
|
||||
)
|
||||
|
||||
tx_in.scriptSig = tx_in._scriptSig_template[0] + self.extranonce_placeholder + tx_in._scriptSig_template[1]
|
||||
|
||||
tx_out = halfnode.CTxOut()
|
||||
tx_out.nValue = value
|
||||
tx_out.scriptPubKey = coinbaser.get_script_pubkey()
|
||||
|
||||
self.nTime = ntime
|
||||
self.vin.append(tx_in)
|
||||
self.vout.append(tx_out)
|
||||
|
||||
@ -21,27 +21,27 @@ log = lib.logger.get_logger('halfnode')
|
||||
log.debug("Got to Halfnode")
|
||||
|
||||
if settings.COINDAEMON_ALGO == 'scrypt':
|
||||
log.debug("########################################### Loading LTC Scrypt #########################################################")
|
||||
import ltc_scrypt
|
||||
log.debug("########################################### Loading LTC Scrypt #########################################################")
|
||||
import ltc_scrypt
|
||||
elif settings.COINDAEMON_ALGO == 'quark':
|
||||
log.debug("########################################### Loading Quark Support #########################################################")
|
||||
import quark_hash
|
||||
log.debug("########################################### Loading Quark Support #########################################################")
|
||||
import quark_hash
|
||||
else:
|
||||
log.debug("########################################### Loading SHA256 Support ######################################################")
|
||||
log.debug("########################################### Loading SHA256 Support ######################################################")
|
||||
|
||||
if settings.COINDAEMON_Reward == 'POS':
|
||||
log.debug("########################################### Loading POS Support #########################################################")
|
||||
pass
|
||||
else:
|
||||
log.debug("########################################### Loading POW Support ######################################################")
|
||||
pass
|
||||
#if settings.COINDAEMON_Reward == 'POS':
|
||||
# log.debug("########################################### Loading POS Support #########################################################")
|
||||
# pass
|
||||
#else:
|
||||
# log.debug("########################################### Loading POW Support ######################################################")
|
||||
# pass
|
||||
|
||||
if settings.COINDAEMON_TX == 'yes':
|
||||
log.debug("########################################### Loading SHA256 Transaction Message Support #########################################################")
|
||||
pass
|
||||
log.debug("########################################### Loading SHA256 Transaction Message Support #########################################################")
|
||||
pass
|
||||
else:
|
||||
log.debug("########################################### NOT Loading SHA256 Transaction Message Support ######################################################")
|
||||
pass
|
||||
log.debug("########################################### NOT Loading SHA256 Transaction Message Support ######################################################")
|
||||
pass
|
||||
|
||||
|
||||
MY_VERSION = 31402
|
||||
|
||||
24
lib/util.py
24
lib/util.py
@ -211,15 +211,15 @@ def ser_number(n):
|
||||
s.append(n)
|
||||
return bytes(s)
|
||||
|
||||
if settings.COINDAEMON_Reward == 'POW':
|
||||
def script_to_address(addr):
|
||||
d = address_to_pubkeyhash(addr)
|
||||
if not d:
|
||||
raise ValueError('invalid address')
|
||||
(ver, pubkeyhash) = d
|
||||
return b'\x76\xa9\x14' + pubkeyhash + b'\x88\xac'
|
||||
else:
|
||||
def script_to_pubkey(key):
|
||||
if len(key) == 66: key = binascii.unhexlify(key)
|
||||
if len(key) != 33: raise Exception('Invalid Address')
|
||||
return b'\x21' + key + b'\xac'
|
||||
#if settings.COINDAEMON_Reward == 'POW':
|
||||
def script_to_address(addr):
|
||||
d = address_to_pubkeyhash(addr)
|
||||
if not d:
|
||||
raise ValueError('invalid address')
|
||||
(ver, pubkeyhash) = d
|
||||
return b'\x76\xa9\x14' + pubkeyhash + b'\x88\xac'
|
||||
#else:
|
||||
def script_to_pubkey(key):
|
||||
if len(key) == 66: key = binascii.unhexlify(key)
|
||||
if len(key) != 33: raise Exception('Invalid Address')
|
||||
return b'\x21' + key + b'\xac'
|
||||
|
||||
@ -44,17 +44,16 @@ def setup(on_startup):
|
||||
if isinstance(result, dict):
|
||||
# litecoind implements version 1 of getblocktemplate
|
||||
if result['version'] >= 1:
|
||||
result = (yield bitcoin_rpc.getinfo())
|
||||
if isinstance(result,dict):
|
||||
if 'stake' in result and settings.COINDAEMON_Reward == 'POS':
|
||||
log.info("CoinD looks to be a POS Coin, Config for POS looks correct")
|
||||
break
|
||||
elif 'stake' not in result and settings.COINDAEMON_Reward == 'POW':
|
||||
log.info("CoinD looks to be a POW Coin, Config looks to be correct")
|
||||
break
|
||||
else:
|
||||
log.error("Wrong Algo Selected, Switch to appropriate POS/POW in config.py!")
|
||||
reactor.stop()
|
||||
result = (yield bitcoin_rpc.getdifficulty())
|
||||
if isinstance(result,dict):
|
||||
if 'proof-of-stake' in result:
|
||||
settings.COINDAEMON_Reward = 'POS'
|
||||
log.info("Coin detected as POS")
|
||||
break;
|
||||
else:
|
||||
settings.COINDAEMON_Reward = 'POW'
|
||||
log.info("Coin detected as POW")
|
||||
break;
|
||||
else:
|
||||
log.error("Block Version mismatch: %s" % result['version'])
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
git submodule init
|
||||
git submodule update
|
||||
git submodule foreach git pull origin master
|
||||
|
||||
Loading…
Reference in New Issue
Block a user