Merge pull request #158 from penner42/master

Auto-detect POW/POS
This commit is contained in:
ahmedbodi 2014-01-19 10:33:17 -08:00
commit 7eff92e941
9 changed files with 103 additions and 106 deletions

View File

@ -1,3 +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.
@ -33,7 +34,7 @@ The goal is to make a reliable stratum mining server for scrypt based coins. Ove
* Doge: DLtBRYtNCzfiZfcpUeEr8KPvy5k1aR7jca * Doge: DLtBRYtNCzfiZfcpUeEr8KPvy5k1aR7jca
* SRC: sMP2wHN5H2ik7FQDPjhSzFZUWux75BYZGe * SRC: sMP2wHN5H2ik7FQDPjhSzFZUWux75BYZGe
* ARG: AQvXPWVqGzcpH2j2XSRG7X5R9nA3y9D9aQ * ARG: AQvXPWVqGzcpH2j2XSRG7X5R9nA3y9D9aQ
* CryptsyTradeKey: ec13d183e304326ebd41258d6ae7188e303866fe
#Requirements #Requirements
@ -61,6 +62,7 @@ Other coins have been known to work with this implementation. I have tested with
* Franko * Franko
* 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.
@ -68,16 +70,10 @@ The installation of this *stratum-mining* can be found in the Repo Wiki.
#Contact #Contact
I am available in the #MPOS, #crypto-expert, #digitalcoin, and #worldcoin channels on freenode. 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. 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 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, However issues related to a coin daemon's setup and other non stratum issues,
Please research and attempt to debug first. 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 #Credits
* Original version by Slush0 (original stratum code) * Original version by Slush0 (original stratum code)

2
TODO Normal file
View File

@ -0,0 +1,2 @@
1) Flush shares on block find
2) Add Autoloading of databases

View File

@ -21,11 +21,8 @@ COINDAEMON_TRUSTED_PASSWORD = 'somepassword'
# The available options are: # The available options are:
# scrypt, sha256d, scrypt-jane and quark # scrypt, sha256d, scrypt-jane and quark
# 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
# 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 # For Coins which support TX Messages please enter yes in the TX selection
COINDAEMON_ALGO = 'scrypt' COINDAEMON_ALGO = 'scrypt'
COINDAEMON_Reward = 'POW'
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)

View File

@ -5,6 +5,8 @@ import struct
import util import util
import merkletree import merkletree
import halfnode import halfnode
from coinbasetx import CoinbaseTransactionPOW
from coinbasetx import CoinbaseTransactionPOS
from coinbasetx import CoinbaseTransaction from coinbasetx import CoinbaseTransaction
import lib.logger import lib.logger
log = lib.logger.get_logger('block_template') 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'] ] txhashes = [None] + [ util.ser_uint256(int(t['hash'], 16)) for t in data['transactions'] ]
mt = merkletree.MerkleTree(txhashes) mt = merkletree.MerkleTree(txhashes)
if settings.COINDAEMON_Reward == 'POW': 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) settings.COINBASE_EXTRAS)
else: 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']) settings.COINBASE_EXTRAS, data['curtime'])
self.height = data['height'] self.height = data['height']

View File

@ -6,8 +6,8 @@ import settings
import lib.logger import lib.logger
log = lib.logger.get_logger('coinbasetx') log = lib.logger.get_logger('coinbasetx')
if settings.COINDAEMON_Reward == 'POW': #if settings.COINDAEMON_Reward == 'POW':
class CoinbaseTransaction(halfnode.CTransaction): class CoinbaseTransactionPOW(halfnode.CTransaction):
'''Construct special transaction used for coinbase tx. '''Construct special transaction used for coinbase tx.
It also implements quick serialization using pre-cached It also implements quick serialization using pre-cached
scriptSig template.''' scriptSig template.'''
@ -17,8 +17,8 @@ if settings.COINDAEMON_Reward == 'POW':
extranonce_size = struct.calcsize(extranonce_type) extranonce_size = struct.calcsize(extranonce_type)
def __init__(self, timestamper, coinbaser, value, flags, height, data): def __init__(self, timestamper, coinbaser, value, flags, height, data):
super(CoinbaseTransaction, self).__init__() super(CoinbaseTransactionPOW, self).__init__()
log.debug("Got to CoinBaseTX") log.debug("Got to CoinBaseTX")
#self.extranonce = 0 #self.extranonce = 0
if len(self.extranonce_placeholder) != self.extranonce_size: if len(self.extranonce_placeholder) != self.extranonce_size:
@ -45,7 +45,7 @@ if settings.COINDAEMON_Reward == 'POW':
self.vout.append(tx_out) self.vout.append(tx_out)
# Two parts of serialized coinbase, just put part1 + extranonce + part2 to have final serialized tx # 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): def set_extranonce(self, extranonce):
if len(extranonce) != self.extranonce_size: if len(extranonce) != self.extranonce_size:
@ -53,8 +53,56 @@ if settings.COINDAEMON_Reward == 'POW':
(part1, part2) = self.vin[0]._scriptSig_template (part1, part2) = self.vin[0]._scriptSig_template
self.vin[0].scriptSig = part1 + extranonce + part2 self.vin[0].scriptSig = part1 + extranonce + part2
elif settings.COINDAEMON_Reward == 'POS': #elif settings.COINDAEMON_Reward == 'POS':
class CoinbaseTransaction(halfnode.CTransaction): 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. '''Construct special transaction used for coinbase tx.
It also implements quick serialization using pre-cached It also implements quick serialization using pre-cached
scriptSig template.''' scriptSig template.'''
@ -86,54 +134,6 @@ elif settings.COINDAEMON_Reward == 'POS':
tx_out.nValue = value tx_out.nValue = value
tx_out.scriptPubKey = coinbaser.get_script_pubkey() 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.nTime = ntime
self.vin.append(tx_in) self.vin.append(tx_in)
self.vout.append(tx_out) self.vout.append(tx_out)

View File

@ -21,27 +21,27 @@ log = lib.logger.get_logger('halfnode')
log.debug("Got to Halfnode") 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 == 'quark': elif settings.COINDAEMON_ALGO == 'quark':
log.debug("########################################### Loading Quark Support #########################################################") log.debug("########################################### Loading Quark Support #########################################################")
import quark_hash import quark_hash
else: else:
log.debug("########################################### Loading SHA256 Support ######################################################") log.debug("########################################### Loading SHA256 Support ######################################################")
if settings.COINDAEMON_Reward == 'POS': #if settings.COINDAEMON_Reward == 'POS':
log.debug("########################################### Loading POS Support #########################################################") # log.debug("########################################### Loading POS Support #########################################################")
pass # pass
else: #else:
log.debug("########################################### Loading POW Support ######################################################") # log.debug("########################################### Loading POW Support ######################################################")
pass # pass
if settings.COINDAEMON_TX == 'yes': if settings.COINDAEMON_TX == 'yes':
log.debug("########################################### Loading SHA256 Transaction Message Support #########################################################") log.debug("########################################### Loading SHA256 Transaction Message Support #########################################################")
pass pass
else: else:
log.debug("########################################### NOT Loading SHA256 Transaction Message Support ######################################################") log.debug("########################################### NOT Loading SHA256 Transaction Message Support ######################################################")
pass pass
MY_VERSION = 31402 MY_VERSION = 31402

View File

@ -211,15 +211,15 @@ def ser_number(n):
s.append(n) s.append(n)
return bytes(s) return bytes(s)
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)
if not d: if not d:
raise ValueError('invalid address') raise ValueError('invalid address')
(ver, pubkeyhash) = d (ver, pubkeyhash) = d
return b'\x76\xa9\x14' + pubkeyhash + b'\x88\xac' return b'\x76\xa9\x14' + pubkeyhash + b'\x88\xac'
else: #else:
def script_to_pubkey(key): def script_to_pubkey(key):
if len(key) == 66: key = binascii.unhexlify(key) if len(key) == 66: key = binascii.unhexlify(key)
if len(key) != 33: raise Exception('Invalid Address') if len(key) != 33: raise Exception('Invalid Address')
return b'\x21' + key + b'\xac' return b'\x21' + key + b'\xac'

View File

@ -44,17 +44,16 @@ def setup(on_startup):
if isinstance(result, dict): if isinstance(result, dict):
# litecoind implements version 1 of getblocktemplate # litecoind implements version 1 of getblocktemplate
if result['version'] >= 1: if result['version'] >= 1:
result = (yield bitcoin_rpc.getinfo()) result = (yield bitcoin_rpc.getdifficulty())
if isinstance(result,dict): if isinstance(result,dict):
if 'stake' in result and settings.COINDAEMON_Reward == 'POS': if 'proof-of-stake' in result:
log.info("CoinD looks to be a POS Coin, Config for POS looks correct") settings.COINDAEMON_Reward = 'POS'
break log.info("Coin detected as POS")
elif 'stake' not in result and settings.COINDAEMON_Reward == 'POW': break;
log.info("CoinD looks to be a POW Coin, Config looks to be correct") else:
break settings.COINDAEMON_Reward = 'POW'
else: log.info("Coin detected as POW")
log.error("Wrong Algo Selected, Switch to appropriate POS/POW in config.py!") break;
reactor.stop()
else: else:
log.error("Block Version mismatch: %s" % result['version']) log.error("Block Version mismatch: %s" % result['version'])

View File

@ -1,3 +1,4 @@
#!/bin/sh #!/bin/sh
git submodule init
git submodule update
git submodule foreach git pull origin master git submodule foreach git pull origin master