cleaned up AttributeDelta handling
authorForrest Voight <forrest.voight@gmail.com>
Sat, 28 Jan 2012 21:26:35 +0000 (16:26 -0500)
committerForrest Voight <forrest@forre.st>
Sat, 28 Jan 2012 23:58:52 +0000 (18:58 -0500)
p2pool/data.py
p2pool/main.py
p2pool/util/forest.py

index 8082daf..8c07ad2 100644 (file)
@@ -264,52 +264,16 @@ def generate_transaction(tracker, share_data, block_target, desired_timestamp, n
         lock_time=0,
     )
 
-
-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):
+    def __init__(self, net, my_share_hashes, my_doa_share_hashes):
         forest.Tracker.__init__(self)
         self.net = net
-        self.verified = forest.Tracker(delta_type=OkayTrackerDelta)
+        self.verified = forest.Tracker(delta_type=forest.get_attributedelta_type(dict(forest.AttributeDelta.attrs,
+            my_count=lambda share: 1 if share.hash in my_share_hashes else 0,
+            my_doa_count=lambda share: 1 if share.hash in my_doa_share_hashes else 0,
+            my_orphan_announce_count=lambda share: 1 if share.hash in my_share_hashes and share.share_data['stale_info'] == 253 else 0,
+            my_dead_announce_count=lambda share: 1 if share.hash in my_share_hashes and share.share_data['stale_info'] == 254 else 0,
+        )))
         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 2e40a76..1a07441 100644 (file)
@@ -43,11 +43,6 @@ 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:
@@ -92,7 +87,10 @@ def main(args, net, datadir_path):
         
         ht = bitcoin_p2p.HeightTracker(bitcoind, factory)
         
-        tracker = p2pool_data.OkayTracker(net)
+        my_share_hashes = set()
+        my_doa_share_hashes = set()
+        
+        tracker = p2pool_data.OkayTracker(net, my_share_hashes, my_doa_share_hashes)
         shared_share_hashes = set()
         ss = p2pool_data.ShareStore(os.path.join(datadir_path, 'shares.'), net)
         known_verified = set()
index 56175d4..6e4b4db 100644 (file)
@@ -50,35 +50,44 @@ class DistanceSkipList(TrackerSkipList):
         assert dist == n
         return hash
 
+def get_attributedelta_type(attrs): # attrs: {name: func}
+    class ProtoAttributeDelta(object):
+        __slots__ = ['head', 'tail'] + attrs.keys()
+        
+        @classmethod
+        def get_none(cls, element_id):
+            return cls(element_id, element_id, **dict((k, 0) for k in attrs))
+        
+        @classmethod
+        def from_element(cls, share):
+            return cls(share.hash, share.previous_hash, **dict((k, v(share)) for k, v in attrs.iteritems()))
+        
+        def __init__(self, head, tail, **kwargs):
+            self.head, self.tail = head, tail
+            for k, v in kwargs.iteritems():
+                setattr(self, k, v)
+        
+        def __add__(self, other):
+            assert self.tail == other.head
+            return self.__class__(self.head, other.tail, **dict((k, getattr(self, k) + getattr(other, k)) for k in attrs))
+        
+        def __sub__(self, other):
+            if self.head == other.head:
+                return self.__class__(other.tail, self.tail, **dict((k, getattr(self, k) - getattr(other, k)) for k in attrs))
+            elif self.tail == other.tail:
+                return self.__class__(self.head, other.head, **dict((k, getattr(self, k) - getattr(other, k)) for k in attrs))
+            else:
+                raise AssertionError()
+        
+        def __repr__(self):
+            return '%s(%r, %r%s)' % (self.__class__, self.head, self.tail, ''.join(', %s=%r' % (k, getattr(self, k)) for k in attrs))
+    ProtoAttributeDelta.attrs = attrs
+    return ProtoAttributeDelta
 
-class AttributeDelta(object):
-    __slots__ = 'head height work tail'.split(' ')
-    
-    @classmethod
-    def get_none(cls, element_id):
-        return cls(element_id, 0, 0, element_id)
-    
-    @classmethod
-    def from_element(cls, share):
-        return cls(share.hash, 1, bitcoin_data.target_to_average_attempts(share.target), share.previous_hash)
-    
-    def __init__(self, head, height, work, tail):
-        self.head, self.height, self.work, self.tail = head, height, work, tail
-    
-    def __add__(self, other):
-        assert self.tail == other.head
-        return AttributeDelta(self.head, self.height + other.height, self.work + other.work, other.tail)
-    
-    def __sub__(self, other):
-        if self.head == other.head:
-            return AttributeDelta(other.tail, self.height - other.height, self.work - other.work, self.tail)
-        elif self.tail == other.tail:
-            return AttributeDelta(self.head, self.height - other.height, self.work - other.work, other.head)
-        else:
-            raise AssertionError()
-    
-    def __repr__(self):
-        return str(self.__class__) + str((self.head, self.height, self.work, self.tail))
+AttributeDelta = get_attributedelta_type(dict(
+    height=lambda share: 1,
+    work=lambda share: bitcoin_data.target_to_average_attempts(share.target),
+))
 
 class Tracker(object):
     def __init__(self, shares=[], delta_type=AttributeDelta):