setup.py
[p2pool.git] / p2p.py
diff --git a/p2p.py b/p2p.py
index 9464e40..c0fec4e 100644 (file)
--- a/p2p.py
+++ b/p2p.py
@@ -4,43 +4,28 @@ import random
 import time
 import traceback
 
-from twisted.internet import defer, reactor, protocol, task
+from twisted.internet import defer, protocol, reactor
 
 import bitcoin_p2p
 import conv
-import util
 import p2pool
+import util
 
 # mode
 #     0: send hash first (high latency, low bandwidth)
 #     1: send entire share (low latency, high bandwidth)
 
-if 0:
-    import pygame
-    d = pygame.display.set_mode((512, 512))
-    task.LoopingCall(pygame.display.update).start(.1)
-    def draw_circle(id, color=(255,0,0)):
-        id = repr(id)
-        pygame.draw.circle(d, (255, 0, 0), (hash(id)%512, hash(id)//512%512), 4)
-    def draw_line(id, id2, color):
-        id = repr(id)
-        pygame.draw.line(d, color, (hash(id)%512, hash(id)//512%512), (hash(id2)%512, hash(id2)//512%512))
-else:
-    draw_circle = draw_line = lambda *args, **kwargs: None
-
 class Protocol(bitcoin_p2p.BaseProtocol):
-    version = 0
-    sub_version = ""
+    version = 1
+    sub_version = ''
     
     def __init__(self, node):
         self.node = node
-    
-    @property
-    def _prefix(self):
+        
         if self.node.testnet:
-            return 'f77cea5d16a2183f'.decode('hex')
+            self._prefix = 'f77cea5d16a2183f'.decode('hex')
         else:
-            return '95ec1eda53c5e716'.decode('hex')
+            self._prefix = '95ec1eda53c5e716'.decode('hex')
     
     use_checksum = True
     
@@ -114,8 +99,6 @@ class Protocol(bitcoin_p2p.BaseProtocol):
     
     def connectionMade(self):
         bitcoin_p2p.BaseProtocol.connectionMade(self)
-        if isinstance(self.factory, ClientFactory):
-            draw_line(self.node.port, self.transport.getPeer().port, (128, 128, 128))
         
         chain = self.node.current_work.value['current_chain']
         highest_share2 = chain.get_highest_share2()
@@ -146,14 +129,11 @@ class Protocol(bitcoin_p2p.BaseProtocol):
         
         self.node_var_watch = self.node.mode_var.changed.watch(lambda new_mode: self.send_set_mode(mode=new_mode))
         
-        self._think()
-        self._think2()
-        
         reactor.callLater(10, self._connect_timeout)
     
     def _connect_timeout(self):
         if not self.connected2 and self.transport.connected:
-            print "Handshake timed out, disconnecting"
+            print 'Handshake timed out, disconnecting from %s:%i' % (self.transport.getPeer().host, self.transport.getPeer().port)
             self.transport.loseConnection()
     
     @defer.inlineCallbacks
@@ -166,6 +146,7 @@ class Protocol(bitcoin_p2p.BaseProtocol):
     def _think2(self):
         while self.connected2:
             self.send_addrme(port=self.node.port)
+            #print 'sending addrme'
             yield util.sleep(random.expovariate(1/100))
     
     def handle_version(self, version, services, addr_to, addr_from, nonce, sub_version, mode, state):
@@ -174,11 +155,11 @@ class Protocol(bitcoin_p2p.BaseProtocol):
         self.other_mode_var = util.Variable(mode)
         
         if nonce == self.node.nonce:
-            #print "Detected connection to self, disconnecting"
+            #print 'Detected connection to self, disconnecting from %s:%i' % (self.transport.getPeer().host, self.transport.getPeer().port)
             self.transport.loseConnection()
             return
         if nonce in self.node.peers:
-            print "Detected duplicate connection, disconnecting"
+            print 'Detected duplicate connection, disconnecting from %s:%i' % (self.transport.getPeer().host, self.transport.getPeer().port)
             self.transport.loseConnection()
             return
         
@@ -186,14 +167,14 @@ class Protocol(bitcoin_p2p.BaseProtocol):
         self.connected2 = True
         self.node.got_conn(self)
         
+        self._think()
+        self._think2()
+        
         if state['highest']['hash'] != 2**256 - 1:
             self.handle_share0s(chains=[dict(
                 chain_id=state['chain_id'],
                 hashes=[state['highest']['hash']],
             )])
-        
-        if isinstance(self.factory, ClientFactory):
-            draw_line(self.node.port, self.transport.getPeer().port, (0, 255, 0))
     
     def handle_set_mode(self, mode):
         self.other_mode_var.set(mode)
@@ -202,13 +183,28 @@ class Protocol(bitcoin_p2p.BaseProtocol):
         pass
     
     def handle_addrme(self, port):
-        self.node.got_addr(('::ffff:' + self.transport.getPeer().host, port), self.other_services, int(time.time()))
-        if random.random() < .7 and self.node.peers:
-            random.choice(self.node.peers.values()).send_addrs(addrs=[dict(address=dict(services=self.other_services, address='::ffff:' + self.transport.getPeer().host, port=port), timestamp=int(time.time()))])
+        host = self.transport.getPeer().host
+        #print 'addrme from', host, port
+        if host == '127.0.0.1':
+            if random.random() < .8 and self.node.peers:
+                random.choice(self.node.peers.values()).send_addrme(port=port) # services...
+        else:
+            self.node.got_addr(('::ffff:' + self.transport.getPeer().host, port), self.other_services, int(time.time()))
+            if random.random() < .8 and self.node.peers:
+                random.choice(self.node.peers.values()).send_addrs(addrs=[
+                    dict(
+                        address=dict(
+                            services=self.other_services,
+                            address='::ffff:' + host,
+                            port=port,
+                        ),
+                        timestamp=int(time.time()),
+                    ),
+                ])
     def handle_addrs(self, addrs):
         for addr_record in addrs:
             self.node.got_addr((addr_record['address']['address'], addr_record['address']['port']), addr_record['address']['services'], min(int(time.time()), addr_record['timestamp']))
-            if random.random() < .7 and self.node.peers:
+            if random.random() < .8 and self.node.peers:
                 random.choice(self.node.peers.values()).send_addrs(addrs=[addr_record])
     def handle_getaddrs(self, count):
         self.send_addrs(addrs=[
@@ -237,7 +233,7 @@ class Protocol(bitcoin_p2p.BaseProtocol):
         for share1 in share1s:
             hash_ = bitcoin_p2p.block_hash(share1['header'])
             if hash_ <= conv.bits_to_target(share1['header']['bits']):
-                print "Dropping peer %s:%i due to invalid share" % (self.transport.getPeer().host, self.transport.getPeer().port)
+                print 'Dropping peer %s:%i due to invalid share' % (self.transport.getPeer().host, self.transport.getPeer().port)
                 self.transport.loseConnection()
                 return
             share = p2pool.Share(share1['header'], gentx=share1['gentx'])
@@ -246,7 +242,7 @@ class Protocol(bitcoin_p2p.BaseProtocol):
         for share2 in share2s:
             hash_ = bitcoin_p2p.block_hash(share2['header'])
             if not hash_ <= conv.bits_to_target(share2['header']['bits']):
-                print "Dropping peer %s:%i due to invalid share" % (self.transport.getPeer().host, self.transport.getPeer().port)
+                print 'Dropping peer %s:%i due to invalid share' % (self.transport.getPeer().host, self.transport.getPeer().port)
                 self.transport.loseConnection()
                 return
             share = p2pool.Share(share2['header'], txns=share2['txns'])
@@ -275,9 +271,6 @@ class Protocol(bitcoin_p2p.BaseProtocol):
         
         if self.connected2:
             self.node.lost_conn(self)
-        
-        if isinstance(self.factory, ClientFactory):
-            draw_line(self.node.port, self.transport.getPeer().port, (255, 0, 0))
 
 class ServerFactory(protocol.ServerFactory):
     def __init__(self, node):
@@ -347,12 +340,10 @@ class Node(object):
         self.attempts = {}
         self.peers = {}
         self.running = False
-        
-        draw_circle(self.port)
     
     def start(self):
         if self.running:
-            raise ValueError("already running")
+            raise ValueError('already running')
         
         self.running = True
         
@@ -372,11 +363,11 @@ class Node(object):
                         host2, port = random.choice(self.addr_store.keys())
                         prefix = '::ffff:'
                         if not host2.startswith(prefix):
-                            raise ValueError("invalid address")
+                            raise ValueError('invalid address')
                         host = host2[len(prefix):]
                     
                     if (host, port) not in self.attempts:
-                        #print "Trying to connect to", host, port
+                        #print 'Trying to connect to', host, port
                         reactor.connectTCP(host, port, ClientFactory(self), timeout=10)
             except:
                 traceback.print_exc()
@@ -396,7 +387,7 @@ class Node(object):
     
     def stop(self):
         if not self.running:
-            raise ValueError("already stopped")
+            raise ValueError('already stopped')
         
         self.running = False
         
@@ -406,7 +397,7 @@ class Node(object):
     def attempt_started(self, connector):
         host, port = connector.getDestination().host, connector.getDestination().port
         if (host, port) in self.attempts:
-            raise ValueError("already have attempt")
+            raise ValueError('already have attempt')
         self.attempts[host, port] = connector
     
     def attempt_failed(self, connector):
@@ -417,25 +408,25 @@ class Node(object):
         if (host, port) not in self.attempts:
             raise ValueError("don't have attempt")
         if connector is not self.attempts[host, port]:
-            raise ValueError("wrong connector")
+            raise ValueError('wrong connector')
         del self.attempts[host, port]
     
     
     def got_conn(self, conn):
         if conn.nonce in self.peers:
-            raise ValueError("already have peer")
+            raise ValueError('already have peer')
         self.peers[conn.nonce] = conn
         
-        print "Connected to peer %s:%i" % (conn.transport.getPeer().host, conn.transport.getPeer().port)
+        print 'Connected to peer %s:%i' % (conn.transport.getPeer().host, conn.transport.getPeer().port)
     
     def lost_conn(self, conn):
         if conn.nonce not in self.peers:
             raise ValueError("don't have peer")
         if conn is not self.peers[conn.nonce]:
-            raise ValueError("wrong conn")
+            raise ValueError('wrong conn')
         del self.peers[conn.nonce]
         
-        print "Lost peer %s:%i" % (conn.transport.getPeer().host, conn.transport.getPeer().port)
+        print 'Lost peer %s:%i' % (conn.transport.getPeer().host, conn.transport.getPeer().port)
     
     
     def got_addr(self, (host, port), services, timestamp):
@@ -445,14 +436,17 @@ class Node(object):
         else:
             self.addr_store[host, port] = services, timestamp, timestamp
     
+    def handle_share(self, share, peer):
+        print 'handle_share', (share, peer)
+    
+    def handle_share_hash(self, chain_id_data, hash, peer):
+        print 'handle_share_hash', (chain_id_data, hash, peer)
+    
     def handle_get_to_best(self, chain_id_data, have, peer):
-        pass
+        print 'handle_get_to_best', (chain_id_data, have, peer)
     
     def handle_get_shares(self, chain_id_data, hashes, peer):
-        pass
-    
-    def handle_share_hash(self, chain_id_data, hash, peer):
-        pass
+        print 'handle_get_shares', (chain_id_data, hashes, peer)
 
 if __name__ == '__main__':
     p = random.randrange(2**15, 2**16)