import mining
from mining.interfaces import Interfaces
-from mining.interfaces import WorkerManagerInterface, ShareManagerInterface, TimestamperInterface
+from mining.interfaces import WorkerManagerInterface, TimestamperInterface, \
+ ShareManagerInterface, ShareLimiterInterface
Interfaces.set_share_manager(ShareManagerInterface())
+Interfaces.set_share_limiter(ShareLimiterInterface())
Interfaces.set_worker_manager(WorkerManagerInterface())
Interfaces.set_timestamper(TimestamperInterface())
service and implements block validation and submits.'''
def __init__(self, block_template_class, coinbaser, bitcoin_rpc, instance_id,
- on_block_callback):
+ on_template_callback, on_block_callback):
self.prevhashes = {}
self.jobs = weakref.WeakValueDictionary()
self.block_template_class = block_template_class
self.bitcoin_rpc = bitcoin_rpc
self.on_block_callback = on_block_callback
+ self.on_template_callback = on_template_callback
self.last_block = None
self.update_in_progress = False
del self.prevhashes[ph]
log.info("New template for %s" % prevhash)
- self.on_block_callback(new_block)
+
+ if new_block:
+ # Tell the system about new block
+ # It is mostly important for share manager
+ self.on_block_callback(prevhash)
+
+ # Everything is ready, let's broadcast jobs!
+ self.on_template_callback(new_block)
+
+
#from twisted.internet import reactor
#reactor.callLater(10, self.on_block_callback, new_block)
coinbaser,
bitcoin_rpc,
settings.INSTANCE_ID,
- MiningSubscription.on_block)
+ MiningSubscription.on_template,
+ Interfaces.share_manager.on_network_block)
# Template registry is the main interface between Stratum service
# and pool core logic
def authorize(self, worker_name, worker_password):
return True
+class ShareLimiterInterface(object):
+ '''Implement difficulty adjustments here'''
+
+ def submit(self, connection_ref, current_difficulty, timestamp):
+ '''connection - weak reference to Protocol instance
+ current_difficulty - difficulty of the connection
+ timestamp - submission time of current share
+
+ - raise SubmitException for stop processing this request
+ - call mining.set_difficulty on connection to adjust the difficulty'''
+ pass
+
class ShareManagerInterface(object):
def __init__(self):
# Fire deferred when manager is ready
self.on_load = defer.Deferred()
self.on_load.callback(True)
+ def on_network_block(self, prevhash):
+ '''Prints when there's new block coming from the network (possibly new round)'''
+ pass
+
def on_submit_share(self, worker_name, block_header, block_hash, shares, timestamp, is_valid):
log.info("%s %s %s" % (block_hash, 'valid' if is_valid else 'INVALID', worker_name))
class Interfaces(object):
worker_manager = None
share_manager = None
+ share_limiter = None
timestamper = None
template_registry = None
@classmethod
def set_share_manager(cls, manager):
cls.share_manager = manager
+
+ @classmethod
+ def set_share_limiter(cls, limiter):
+ cls.share_limiter = limiter
@classmethod
def set_timestamper(cls, manager):
'''Connect this RPC call to 'bitcoind -blocknotify' for
instant notification about new block on the network.
See blocknotify.sh in /scripts/ for more info.'''
+
+ log.info("New block notification received")
Interfaces.template_registry.update_block()
return True
extranonce1 = Interfaces.template_registry.get_new_extranonce1()
extranonce2_size = Interfaces.template_registry.extranonce2_size
-
+ extranonce1_hex = binascii.hexlify(extranonce1)
+
session = self.connection_ref().get_session()
session['extranonce1'] = extranonce1
session['difficulty'] = 1 # Following protocol specs, default diff is 1
- extranonce1_hex = binascii.hexlify(extranonce1)
-
return Pubsub.subscribe(self.connection_ref(), MiningSubscription()) + (extranonce1_hex, extranonce2_size)
'''
log.info("LEN %.03f" % (time.time() - start))
return ret
'''
-
+
def submit(self, worker_name, job_id, extranonce2, ntime, nonce):
'''Try to solve block candidate using given parameters.'''
raise SubmitException("Connection is not subscribed for mining")
difficulty = session['difficulty']
-
submit_time = Interfaces.timestamper.time()
-
+
+ Interfaces.share_limiter.submit(self.connection_ref, difficulty, submit_time)
+
# This checks if submitted share meet all requirements
# and it is valid proof of work.
try:
event = 'mining.notify'
@classmethod
- def on_block(cls, is_new_block):
+ def on_template(cls, is_new_block):
'''This is called when TemplateRegistry registers
new block which we have to broadcast clients.'''