close stratum connection if get_work fails to let miner know something is wrong inste...
[p2pool.git] / p2pool / bitcoin / stratum.py
index 82bdb2a..ca2aa94 100644 (file)
@@ -1,26 +1,31 @@
 import random
+import sys
 
 from twisted.internet import protocol, reactor
+from twisted.python import log
 
 from p2pool.bitcoin import data as bitcoin_data, getwork
 from p2pool.util import expiring_dict, jsonrpc, pack
 
 
 class StratumRPCMiningProvider(object):
-    def __init__(self, wb, other):
+    def __init__(self, wb, other, transport):
         self.wb = wb
         self.other = other
+        self.transport = transport
         
         self.username = None
         self.handler_map = expiring_dict.ExpiringDict(300)
         
         self.watch_id = self.wb.new_work_event.watch(self._send_work)
     
-    def rpc_subscribe(self):
+    def rpc_subscribe(self, miner_version=None, session_id=None):
+        reactor.callLater(0, self._send_work)
+        
         return [
             ["mining.notify", "ae6812eb4cd7735a302a8a9dd95cf71f"], # subscription details
             "", # extranonce1
-            4, # extranonce2_size
+            self.wb.COINBASE_NONCE_LENGTH, # extranonce2_size
         ]
     
     def rpc_authorize(self, username, password):
@@ -29,12 +34,14 @@ class StratumRPCMiningProvider(object):
         reactor.callLater(0, self._send_work)
     
     def _send_work(self):
-        if self.username is None: # authorize hasn't been received yet
+        try:
+            x, got_response = self.wb.get_work(*self.wb.preprocess_request('' if self.username is None else self.username))
+        except:
+            log.err()
+            self.transport.loseConnection()
             return
-        
-        x, got_response = self.wb.get_work(*self.wb.preprocess_request(self.username))
         jobid = str(random.randrange(2**128))
-        self.other.svc_mining.rpc_set_difficulty(bitcoin_data.target_to_difficulty(x['share_target'])).addErrback(lambda err: None)
+        self.other.svc_mining.rpc_set_difficulty(bitcoin_data.target_to_difficulty(x['share_target'])*self.wb.net.DUMB_SCRYPT_DIFF).addErrback(lambda err: None)
         self.other.svc_mining.rpc_notify(
             jobid, # jobid
             getwork._swap4(pack.IntType(256).pack(x['previous_block'])).encode('hex'), # prevhash
@@ -49,9 +56,13 @@ class StratumRPCMiningProvider(object):
         self.handler_map[jobid] = x, got_response
     
     def rpc_submit(self, worker_name, job_id, extranonce2, ntime, nonce):
+        if job_id not in self.handler_map:
+            print >>sys.stderr, '''Couldn't link returned work's job id with its handler. This should only happen if this process was recently restarted!'''
+            return False
         x, got_response = self.handler_map[job_id]
-        coinb_nonce = pack.IntType(32).unpack(extranonce2.decode('hex'))
-        new_packed_gentx = x['coinb1'] + pack.IntType(32).pack(coinb_nonce) + x['coinb2']
+        coinb_nonce = extranonce2.decode('hex')
+        assert len(coinb_nonce) == self.wb.COINBASE_NONCE_LENGTH
+        new_packed_gentx = x['coinb1'] + coinb_nonce + x['coinb2']
         header = dict(
             version=x['version'],
             previous_block=x['previous_block'],
@@ -67,7 +78,7 @@ class StratumRPCMiningProvider(object):
 
 class StratumProtocol(jsonrpc.LineBasedPeer):
     def connectionMade(self):
-        self.svc_mining = StratumRPCMiningProvider(self.factory.wb, self.other)
+        self.svc_mining = StratumRPCMiningProvider(self.factory.wb, self.other, self.transport)
     
     def connectionLost(self, reason):
         self.svc_mining.close()