changed Tracker.get_chain_known to the new, more explicit get_chain
authorForrest Voight <forrest@forre.st>
Mon, 12 Dec 2011 04:12:45 +0000 (23:12 -0500)
committerForrest Voight <forrest@forre.st>
Mon, 12 Dec 2011 04:12:45 +0000 (23:12 -0500)
p2pool/data.py
p2pool/main.py
p2pool/test/util/test_forest.py
p2pool/util/forest.py
p2pool/util/math.py

index b1d2fa8..25a3d88 100644 (file)
@@ -287,7 +287,7 @@ class OkayTracker(forest.Tracker):
         for head in set(self.heads) - set(self.verified.heads):
             head_height, last = self.get_height_and_last(head)
             
-            for share in itertools.islice(self.get_chain_known(head), None if last is None else min(5, max(0, head_height - self.net.CHAIN_LENGTH))):
+            for share in self.get_chain(head, head_height if last is None else min(5, max(0, head_height - self.net.CHAIN_LENGTH))):
                 if self.attempt_verify(share, now):
                     break
                 if share.hash in self.heads:
@@ -311,7 +311,7 @@ class OkayTracker(forest.Tracker):
             can = max(last_height - 1 - self.net.CHAIN_LENGTH, 0) if last_last_hash is not None else last_height
             get = min(want, can)
             #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):
+            for share in self.get_chain(last_hash, get):
                 if not self.attempt_verify(share, now):
                     break
             if head_height < self.net.CHAIN_LENGTH and last_last_hash is not None:
@@ -409,7 +409,7 @@ class OkayTracker(forest.Tracker):
         score2 = 0
         block_height = -1000000
         max_height = min(self.net.CHAIN_LENGTH, head_height)
-        for share in reversed(list(itertools.islice(self.verified.get_chain_known(self.verified.get_nth_parent_hash(share_hash, max_height//2)), max_height//2))):
+        for share in math.reversed(self.verified.get_chain(self.verified.get_nth_parent_hash(share_hash, max_height//2), max_height//2)):
             block_height = max(block_height, ht.get_height_rel_highest(share.header['previous_block']))
             this_score = (self.verified.get_work(share_hash) - self.verified.get_work(share.hash))//(0 - block_height + 1)
             if this_score > score2:
index 13287e4..03eb106 100644 (file)
@@ -280,7 +280,7 @@ def main(args, net, datadir_path):
             stops = set(stops)
             shares = []
             for share_hash in share_hashes:
-                for share in itertools.islice(tracker.get_chain_known(share_hash), parents + 1):
+                for share in tracker.get_chain(share_hash, min(parents + 1, tracker.get_height(share_hash))):
                     if share.hash in stops:
                         break
                     shares.append(share)
@@ -341,7 +341,7 @@ def main(args, net, datadir_path):
         def work_changed(new_work):
             #print 'Work changed:', new_work
             shares = []
-            for share in tracker.get_chain_known(new_work['best_share_hash']):
+            for share in tracker.get_chain(new_work['best_share_hash'], tracker.get_height(new_work['best_share_hash'])):
                 if share.hash in shared_share_hashes:
                     break
                 shared_share_hashes.add(share.hash)
@@ -353,7 +353,7 @@ def main(args, net, datadir_path):
         current_work.changed.watch(work_changed)
         
         def save_shares():
-            for share in itertools.islice(tracker.get_chain_known(current_work.value['best_share_hash']), 2*net.CHAIN_LENGTH):
+            for share in tracker.get_chain(current_work.value['best_share_hash'], min(tracker.get_height(current_work.value['best_share_hash']), 2*net.CHAIN_LENGTH)):
                 ss.add_share(share)
                 if share.hash in tracker.verified.shares:
                     ss.add_verified_hash(share.hash)
@@ -539,7 +539,7 @@ def main(args, net, datadir_path):
             if current_work.value['best_share_hash'] is not None:
                 height, last = tracker.get_height_and_last(current_work.value['best_share_hash'])
                 att_s = p2pool_data.get_pool_attempts_per_second(tracker, current_work.value['best_share_hash'], min(height - 1, 720))
-                fracs = [share.stale_frac for share in itertools.islice(tracker.get_chain_known(current_work.value['best_share_hash']), 120) if share.stale_frac is not None]
+                fracs = [share.stale_frac for share in tracker.get_chain(current_work.value['best_share_hash'], min(120, height)) if share.stale_frac is not None]
                 return json.dumps(int(att_s / (1. - (math.median(fracs) if fracs else 0))))
             return json.dumps(None)
         
@@ -626,7 +626,7 @@ def main(args, net, datadir_path):
                         weights, total_weight, donation_weight = tracker.get_cumulative_weights(current_work.value['best_share_hash'], min(height, 720), 65535*2**256)
                         shares, stale_doa_shares, stale_not_doa_shares = get_share_counts(True)
                         stale_shares = stale_doa_shares + stale_not_doa_shares
-                        fracs = [share.stale_frac for share in itertools.islice(tracker.get_chain_known(current_work.value['best_share_hash']), 120) if share.stale_frac is not None]
+                        fracs = [share.stale_frac for share in tracker.get_chain(current_work.value['best_share_hash'], min(120, height)) if share.stale_frac is not None]
                         this_str = 'Pool: %sH/s in %i shares (%i/%i verified) Recent: %.02f%% >%sH/s Shares: %i (%i orphan, %i dead) Peers: %i' % (
                             math.format(int(att_s / (1. - (math.median(fracs) if fracs else 0)))),
                             height,
index 681e0e0..95815f5 100644 (file)
@@ -65,6 +65,13 @@ class DumbTracker(object):
             work += work_inc
         return height, work, share_hash
     
+    def get_chain(self, start_hash, length):
+        # same implementation :/
+        assert length <= self.get_height(start_hash)
+        for i in xrange(length):
+            yield self.shares[start_hash]
+            start_hash = self.shares[start_hash].previous_hash
+    
     def is_child_of(self, share_hash, possible_child_hash):
         if self.get_last(share_hash) != self.get_last(possible_child_hash):
             return None
@@ -100,6 +107,8 @@ def test_tracker(self):
         other = random.choice(self.shares.keys())
         assert self.is_child_of(start, other) == t.is_child_of(start, other)
         assert self.is_child_of(other, start) == t.is_child_of(other, start)
+        
+        assert list(self.get_chain(start, min(a[0], 10))) == list(t.get_chain(start, min(a[0], 10)))
 
 def generate_tracker_simple(n):
     t = forest.Tracker(math.shuffled(FakeShare(hash=i, previous_hash=i - 1 if i > 0 else None) for i in xrange(n)))
index 421ed72..788de07 100644 (file)
@@ -223,19 +223,11 @@ class Tracker(object):
             self._set_height_jump(update_hash, height - height_then, share_hash, work - work_then)
         return height, work, 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
-        '''
-        item_hash_to_get = start_hash
-        while True:
-            if item_hash_to_get not in self.shares:
-                break
-            share = self.shares[item_hash_to_get]
-            assert not isinstance(share, long)
-            yield share
-            item_hash_to_get = share.previous_hash
+    def get_chain(self, start_hash, length):
+        assert length <= self.get_height(start_hash)
+        for i in xrange(length):
+            yield self.shares[start_hash]
+            start_hash = self.shares[start_hash].previous_hash
     
     def is_child_of(self, share_hash, possible_child_hash):
         height, last = self.get_height_and_last(share_hash)
index 6eb8303..68f3f26 100644 (file)
@@ -1,5 +1,6 @@
 from __future__ import absolute_import, division
 
+import __builtin__
 import math
 import random
 
@@ -111,6 +112,12 @@ def binomial_conf_interval(x, n, conf=0.95):
 def interval_to_center_radius((low, high)):
     return (high+low)/2, (high-low)/2
 
+def reversed(x):
+    try:
+        return __builtin__.reversed(x)
+    except TypeError:
+        return reversed(list(x))
+
 if __name__ == '__main__':
     import random
     a = 1