moved stale skiplist to tracker's delta object
authorForrest Voight <forrest@forre.st>
Sat, 21 Jan 2012 04:05:49 +0000 (23:05 -0500)
committerForrest Voight <forrest@forre.st>
Sat, 21 Jan 2012 04:05:56 +0000 (23:05 -0500)
p2pool/data.py
p2pool/main.py
p2pool/skiplists.py

index 6c695f6..2d16871 100644 (file)
@@ -265,11 +265,51 @@ def generate_transaction(tracker, share_data, block_target, desired_timestamp, n
     )
 
 
+class OkayTrackerDelta(object):
+    __slots__ = 'head height work my_count my_doa_count my_orphan_announce_count my_dead_announce_count tail'.split(' ')
+    
+    @classmethod
+    def get_none(cls, element_id):
+        return cls(element_id, 0, 0, 0, 0, 0, 0, element_id)
+    
+    @classmethod
+    def from_element(cls, share):
+        return cls(share.hash,
+            1, bitcoin_data.target_to_average_attempts(share.target),
+            1 if share.hash in cls.my_share_hashes else 0,
+            1 if share.hash in cls.my_doa_share_hashes else 0,
+            1 if share.hash in cls.my_share_hashes and share.share_data['stale_info'] == 253 else 0,
+            1 if share.hash in cls.my_share_hashes and share.share_data['stale_info'] == 254 else 0,
+        share.previous_hash)
+    
+    def __init__(self, head, height, work, my_count, my_doa_count, my_orphan_announce_count, my_dead_announce_count, tail):
+        self.head, self.height, self.work, self.tail = head, height, work, tail
+        self.my_count, self.my_doa_count, self.my_orphan_announce_count, self.my_dead_announce_count = my_count, my_doa_count, my_orphan_announce_count, my_dead_announce_count
+    
+    def __add__(self, other):
+        assert self.tail == other.head
+        return OkayTrackerDelta(self.head,
+            self.height + other.height, self.work + other.work,
+            self.my_count + other.my_count, self.my_doa_count + other.my_doa_count, self.my_orphan_announce_count + other.my_orphan_announce_count, self.my_dead_announce_count + other.my_dead_announce_count,
+        other.tail)
+    
+    def __sub__(self, other):
+        if self.head == other.head:
+            return OkayTrackerDelta(other.tail, self.height - other.height, self.work - other.work,
+                self.my_count - other.my_count, self.my_doa_count - other.my_doa_count, self.my_orphan_announce_count - other.my_orphan_announce_count, self.my_dead_announce_count - other.my_dead_announce_count,
+            self.tail)
+        elif self.tail == other.tail:
+            return OkayTrackerDelta(self.head, self.height - other.height, self.work - other.work,
+                self.my_count - other.my_count, self.my_doa_count - other.my_doa_count, self.my_orphan_announce_count - other.my_orphan_announce_count, self.my_dead_announce_count - other.my_dead_announce_count,
+            other.head)
+        else:
+            raise AssertionError()
+
 class OkayTracker(forest.Tracker):
     def __init__(self, net):
         forest.Tracker.__init__(self)
         self.net = net
-        self.verified = forest.Tracker()
+        self.verified = forest.Tracker(delta_type=OkayTrackerDelta)
         self.verified.get_nth_parent_hash = self.get_nth_parent_hash # self is a superset of self.verified
         
         self.get_cumulative_weights = skiplists.WeightsSkipList(self)
index 37a14b5..59d0393 100644 (file)
@@ -23,7 +23,7 @@ from nattraverso import portmapper, ipdiscover
 import bitcoin.p2p as bitcoin_p2p, bitcoin.getwork as bitcoin_getwork, bitcoin.data as bitcoin_data
 from bitcoin import worker_interface
 from util import expiring_dict, jsonrpc, variable, deferral, math
-from . import p2p, skiplists, networks, graphs
+from . import p2p, networks, graphs
 import p2pool, p2pool.data as p2pool_data
 
 @deferral.retry('Error getting work from bitcoind:', 3)
@@ -42,6 +42,11 @@ def getwork(bitcoind):
 @defer.inlineCallbacks
 def main(args, net, datadir_path):
     try:
+        my_share_hashes = set()
+        my_doa_share_hashes = set()
+        p2pool_data.OkayTrackerDelta.my_share_hashes = my_share_hashes
+        p2pool_data.OkayTrackerDelta.my_doa_share_hashes = my_doa_share_hashes
+        
         print 'p2pool (version %s)' % (p2pool.__version__,)
         print
         try:
@@ -378,33 +383,21 @@ def main(args, net, datadir_path):
             if share.hash in my_doa_share_hashes and tracker.is_child_of(share.hash, current_work.value['best_share_hash']):
                 removed_doa_unstales.set(removed_doa_unstales.value + 1)
         
-        stale_counter = skiplists.SumSkipList(tracker, lambda share: (
-            1 if share.hash in my_share_hashes else 0,
-            1 if share.hash in my_doa_share_hashes else 0,
-            1 if share.hash in my_share_hashes and share.share_data['stale_info'] == 253 else 0,
-            1 if share.hash in my_share_hashes and share.share_data['stale_info'] == 254 else 0,
-        ), (0, 0, 0, 0), math.add_tuples)
         def get_stale_counts():
             '''Returns (orphans, doas), total, (orphans_recorded_in_chain, doas_recorded_in_chain)'''
             my_shares = len(my_share_hashes)
             my_doa_shares = len(my_doa_share_hashes)
-            my_shares_in_chain, my_doa_shares_in_chain, orphans_recorded_in_chain, doas_recorded_in_chain = stale_counter(
-                current_work.value['best_share_hash'],
-                tracker.verified.get_height(current_work.value['best_share_hash']),
-            )
-            my_shares_in_chain += removed_unstales_var.value[0]
-            my_doa_shares_in_chain += removed_doa_unstales_var.value
-            orphans_recorded_in_chain += removed_unstales_var.value[1]
-            doas_recorded_in_chain += removed_unstales_var.value[2]
+            delta = tracker.verified.get_delta(current_work.value['best_share_hash'])
+            my_shares_in_chain = delta.my_count + removed_unstales_var.value[0]
+            my_doa_shares_in_chain = delta.my_doa_count + removed_doa_unstales_var.value
+            orphans_recorded_in_chain = delta.my_orphan_announce_count + removed_unstales_var.value[1]
+            doas_recorded_in_chain = delta.my_dead_announce_count + removed_unstales_var.value[2]
             
             my_shares_not_in_chain = my_shares - my_shares_in_chain
             my_doa_shares_not_in_chain = my_doa_shares - my_doa_shares_in_chain
             
             return (my_shares_not_in_chain - my_doa_shares_not_in_chain, my_doa_shares_not_in_chain), my_shares, (orphans_recorded_in_chain, doas_recorded_in_chain)
         
-        my_share_hashes = set()
-        my_doa_share_hashes = set()
-        
         class WorkerBridge(worker_interface.WorkerBridge):
             def __init__(self):
                 worker_interface.WorkerBridge.__init__(self)
index db7e9f7..95e85b0 100644 (file)
@@ -38,31 +38,3 @@ class WeightsSkipList(forest.TrackerSkipList):
         assert share_count <= max_shares and total_weight <= desired_weight
         assert share_count == max_shares or total_weight == desired_weight
         return math.add_dicts(*math.flatten_linked_list(weights_list)), total_weight, total_donation_weight
-
-class SumSkipList(forest.TrackerSkipList):
-    def __init__(self, tracker, value_func, identity_value=0, add_func=operator.add):
-        forest.TrackerSkipList.__init__(self, tracker)
-        self.value_func = value_func
-        self.identity_value = identity_value
-        self.add_func = add_func
-    
-    
-    def get_delta(self, element):
-        return self.value_func(self.tracker.shares[element]), 1
-    
-    def combine_deltas(self, (result1, count1), (result2, count2)):
-        return self.add_func(result1, result2), count1 + count2
-    
-    
-    def initial_solution(self, start_hash, (desired_count,)):
-        return self.identity_value, 0
-    
-    def apply_delta(self, (result, count), (d_result, d_count), (desired_count,)):
-        return self.add_func(result, d_result), count + d_count
-    
-    def judge(self, (result, count), (desired_count,)):
-        return cmp(count, desired_count)
-    
-    def finalize(self, (result, count), (desired_count,)):
-        assert count == desired_count
-        return result