good chain choosing scheme
authorforrest <forrest@470744a7-cac9-478e-843e-5ec1b25c69e8>
Wed, 13 Jul 2011 13:35:59 +0000 (13:35 +0000)
committerforrest <forrest@470744a7-cac9-478e-843e-5ec1b25c69e8>
Wed, 13 Jul 2011 13:35:59 +0000 (13:35 +0000)
git-svn-id: svn://forre.st/p2pool@1384 470744a7-cac9-478e-843e-5ec1b25c69e8

p2pool/bitcoin/data.py
p2pool/bitcoin/p2p.py
p2pool/data.py
p2pool/main.py

index 0fa7432..3351b56 100644 (file)
@@ -403,6 +403,7 @@ class Tracker(object):
         self.heights = {} # share_hash -> height_to, other_share_hash
     
     def add(self, share):
+        assert not isinstance(share, (int, long, type(None)))
         if share.hash in self.shares:
             return # XXX raise exception?
         
@@ -427,6 +428,7 @@ class Tracker(object):
             self.heads[head] = tail
     
     def get_height_and_last(self, share_hash):
+        assert isinstance(share_hash, (int, long, type(None)))
         orig = share_hash
         height = 0
         updates = []
@@ -445,6 +447,7 @@ class Tracker(object):
         return height, share_hash
     
     def get_height_and_last2(self, share_hash):
+        assert isinstance(share_hash, (int, long, type(None)))
         height = 0
         while True:
             if share_hash not in self.shares:
@@ -454,6 +457,7 @@ class Tracker(object):
         return height, share_hash
     
     def get_chain_known(self, start_hash):
+        assert isinstance(start_hash, (int, long, type(None)))
         '''
         Chain starting with item of hash I{start_hash} of items that this Tracker contains
         '''
@@ -467,6 +471,8 @@ class Tracker(object):
             item_hash_to_get = share.previous_hash
     
     def get_chain_to_root(self, start_hash, root=None):
+        assert isinstance(start_hash, (int, long, type(None)))
+        assert isinstance(root, (int, long, type(None)))
         '''
         Chain of hashes starting with share_hash of shares to the root (doesn't include root)
         Raises an error if one is missing
@@ -484,6 +490,9 @@ class Tracker(object):
         if not self.heads:
             return None
         return max(self.heads, key=self.get_height_and_last)
+    
+    def get_highest_height(self):
+        return max(self.get_height_and_last(head)[0] for head in self.heads) if self.heads else 0
 
 # network definitions
 
index 3156fa2..dab765a 100644 (file)
@@ -390,6 +390,9 @@ class HeightTracker(object):
         if last is not None:
             self.request([], last)
         return height
+    
+    def get_highest_height(self):
+        return self.tracker.get_highest_height()
 
 if __name__ == '__main__':
     factory = ClientFactory(bitcoin_data.Mainnet)
index 7ab598a..d463521 100644 (file)
@@ -231,9 +231,9 @@ def generate_transaction(tracker, previous_share_hash, new_script, subsidy, nonc
         if time == 0:
             time = 1
         attempts_per_second = attempts//time
-        pre_target = 2**256//(net.SHARE_PERIOD*attempts_per_sec4nd) - 1
+        pre_target = 2**256//(net.SHARE_PERIOD*attempts_per_second) - 1
         pre_target2 = math.clip(pre_target, (previous_share2.target2*9//10, previous_share2.target2*11//10))
-        pre_target3 = math.clip(pre_target2, (0, 2**256//2**25 - 1))
+        pre_target3 = math.clip(pre_target2, (0, 2**256//2**24 - 1))
         target2 = bitcoin_data.FloatingIntegerType().truncate_to(pre_target3)
         print attempts_per_second//1000, "KHASH"
         #print "TARGET", 2**256//target2, 2**256/pre_target
@@ -380,21 +380,38 @@ class OkayTracker(bitcoin_data.Tracker):
                 if self.attempt_verify(share):
                     break
         
+        last = object
+        
         # try to get at least CHAIN_LENGTH height for each verified head, requesting parents if needed
         for head in self.verified.heads:
-            head_height, last = self.verified.get_height_and_last(head)
-            last_height, last_last = self.get_height_and_last(last)
-            for share in itertools.islice(self.get_chain_known(last), max(0, min(self.net.CHAIN_LENGTH - head_height, last_height - 1 - self.net.CHAIN_LENGTH))):
+            head_height, last_hash = self.verified.get_height_and_last(head)
+            last_height, last_last_hash = self.get_height_and_last(last_hash)
+            # XXX review boundary conditions
+            want = self.net.CHAIN_LENGTH - head_height
+            can = max(last_height - 1 - self.net.CHAIN_LENGTH, 0) if last_last_hash is not None else last_height
+            if want > can:
+                get = can
+            else:
+                get = want
+            #print "Z", head_height, last_hash is None, last_height, last_last_hash is None, want, can, get
+            for share in itertools.islice(self.get_chain_known(last_hash), get):
                 if not self.attempt_verify(share):
                     break
-            if head_height < self.net.CHAIN_LENGTH and last_last is not None:
-                desired.add((self.verified.shares[random.choice(list(self.verified.reverse_shares[last]))].peer, last_last))
+            if head_height < self.net.CHAIN_LENGTH and last_last_hash is not None:
+                desired.add((self.verified.shares[random.choice(list(self.verified.reverse_shares[last_hash]))].peer, last_last_hash))
         
         # decide best verified head
         def score(share_hash):
-            share = self.verified.shares[share_hash]
-            head_height, last = self.verified.get_height_and_last(share)
-            score2 = sum(ht.get_min_height(share.header['previous_block']) for share in itertools.islice(self.verified.get_chain_known(share_hash), self.net.CHAIN_LENGTH))
+            head_height, last = self.verified.get_height_and_last(share_hash)
+            score2 = 0
+            attempts = 0
+            max_height = 0
+            for share in itertools.islice(self.verified.get_chain_known(share_hash), self.net.CHAIN_LENGTH):
+                max_height = max(max_height, ht.get_min_height(share.header['previous_block']))
+                attempts += bitcoin_data.target_to_average_attempts(share.target2)
+                this_score = attempts//(ht.get_highest_height() - max_height + 1)
+                if this_score > score2:
+                    score2 = this_score
             res = (min(head_height, self.net.CHAIN_LENGTH), score2)
             print res
             return res
index 639cb9f..1ff37e4 100644 (file)
@@ -296,7 +296,10 @@ def main(args):
             else:
                 return x, args.net.P2P_PORT
         
-        nodes = [('72.14.191.28', args.net.P2P_PORT)]
+        nodes = [
+            ('72.14.191.28', args.net.P2P_PORT),
+            ('62.204.197.159', args.net.P2P_PORT),
+        ]
         try:
             nodes.append(((yield reactor.resolve('p2pool.forre.st')), args.net.P2P_PORT))
         except: