skiplist cleanup
authorForrest Voight <forrest@forre.st>
Sun, 31 Jul 2011 16:48:27 +0000 (12:48 -0400)
committerForrest Voight <forrest@forre.st>
Sun, 31 Jul 2011 16:48:27 +0000 (12:48 -0400)
p2pool/bitcoin/data.py
p2pool/bitcoin/skiplists.py [new file with mode: 0644]
p2pool/data.py
p2pool/main.py
p2pool/skiplists.py [new file with mode: 0644]
p2pool/util/skiplist.py

index 8ee3761..29ab0da 100644 (file)
@@ -4,7 +4,7 @@ import struct
 import hashlib
 import warnings
 
-from . import base58
+from . import base58, skiplists
 from p2pool.util import bases, math, skiplist, intern2
 import p2pool
 
@@ -460,7 +460,7 @@ class Tracker(object):
         self.tails_by_id = {}
         '''
         
-        self.get_nth_parent_hash = skiplist.DistanceSkipList(self)
+        self.get_nth_parent_hash = skiplists.DistanceSkipList(self)
     
     def add(self, share):
         assert not isinstance(share, (int, long, type(None)))
diff --git a/p2pool/bitcoin/skiplists.py b/p2pool/bitcoin/skiplists.py
new file mode 100644 (file)
index 0000000..b84d253
--- /dev/null
@@ -0,0 +1,49 @@
+from p2pool.util import skiplist
+
+class DistanceSkipList(skiplist.SkipList):
+    def __init__(self, tracker):
+        skiplist.SkipList.__init__(self)
+        self.tracker = tracker
+    
+    def previous(self, element):
+        return self.tracker.shares[element].previous_hash
+    
+    def get_delta(self, element):
+        return element, 1, self.tracker.shares[element].previous_hash
+    
+    def combine_deltas(self, (from_hash1, dist1, to_hash1), (from_hash2, dist2, to_hash2)):
+        if to_hash1 != from_hash2:
+            raise AssertionError()
+        return from_hash1, dist1 + dist2, to_hash2
+    
+    def initial_solution(self, start, (n,)):
+        return 0, start
+    
+    def apply_delta(self, (dist1, to_hash1), (from_hash2, dist2, to_hash2), (n,)):
+        if to_hash1 != from_hash2:
+            raise AssertionError()
+        return dist1 + dist2, to_hash2
+    
+    def judge(self, (dist, hash), (n,)):
+        if dist > n:
+            return 1
+        elif dist == n:
+            return 0
+        else:
+            return -1
+    
+    def finalize(self, (dist, hash)):
+        return hash
+
+if __name__ == '__main__':
+    import random
+    from p2pool.bitcoin import data
+    t = data.Tracker()
+    d = DistanceSkipList(t)
+    for i in xrange(2000):
+        t.add(data.FakeShare(hash=i, previous_hash=i - 1 if i > 0 else None))
+    for i in xrange(2000):
+        a = random.randrange(2000)
+        b = random.randrange(a + 1)
+        res = d(a, b)
+        assert res == a - b, (a, b, res)
index a0ad12e..3157efc 100644 (file)
@@ -7,10 +7,10 @@ import time
 from twisted.internet import defer
 from twisted.python import log
 
-from p2pool.bitcoin import data as bitcoin_data
-from p2pool.bitcoin import script
-from p2pool.util import memoize, expiring_dict, math, skiplist, deferral
 import p2pool
+from p2pool import skiplists
+from p2pool.bitcoin import data as bitcoin_data, script
+from p2pool.util import memoize, expiring_dict, math, deferral
 
 
 merkle_branch_type = bitcoin_data.ListType(bitcoin_data.ComposedType([
@@ -298,7 +298,7 @@ class OkayTracker(bitcoin_data.Tracker):
         self.net = net
         self.verified = bitcoin_data.Tracker()
         
-        self.get_cumulative_weights = skiplist.WeightsSkipList(self)
+        self.get_cumulative_weights = skiplists.WeightsSkipList(self)
     
     def attempt_verify(self, share, now):
         if share.hash in self.verified.shares:
index cac7c67..9de23bf 100644 (file)
@@ -17,8 +17,8 @@ from twisted.web import server
 from twisted.python import log
 
 import bitcoin.p2p, bitcoin.getwork, bitcoin.data
-from util import db, expiring_dict, jsonrpc, variable, deferral, math, skiplist
-from . import p2p, worker_interface
+from util import db, expiring_dict, jsonrpc, variable, deferral, math
+from . import p2p, worker_interface, skiplists
 import p2pool.data as p2pool
 import p2pool as p2pool_init
 
@@ -468,7 +468,7 @@ def main(args):
         work1_thread()
         work2_thread()
         
-        counter = skiplist.CountsSkipList(tracker, run_identifier)
+        counter = skiplists.CountsSkipList(tracker, run_identifier)
         
         while True:
             yield deferral.sleep(random.expovariate(1/1))
diff --git a/p2pool/skiplists.py b/p2pool/skiplists.py
new file mode 100644 (file)
index 0000000..6b0933f
--- /dev/null
@@ -0,0 +1,98 @@
+from p2pool.util import math, skiplist
+
+class WeightsSkipList(skiplist.SkipList):
+    # share_count, weights, total_weight
+    
+    def __init__(self, tracker):
+        skiplist.SkipList.__init__(self)
+        self.tracker = tracker
+    
+    def previous(self, element):
+        return self.tracker.shares[element].previous_hash
+    
+    def get_delta(self, element):
+        from p2pool.bitcoin import data as bitcoin_data
+        if element is None:
+            return (2**256, {}, 0) # XXX
+        share = self.tracker.shares[element]
+        att = bitcoin_data.target_to_average_attempts(share.target)
+        return 1, {share.new_script: att}, att
+    
+    def combine_deltas(self, (share_count1, weights1, total_weight1), (share_count2, weights2, total_weight2)):
+        return share_count1 + share_count2, math.add_dicts([weights1, weights2]), total_weight1 + total_weight2
+    
+    def initial_solution(self, start, (max_shares, desired_weight)):
+        return 0, {}, 0
+    
+    def apply_delta(self, (share_count1, weights1, total_weight1), (share_count2, weights2, total_weight2), (max_shares, desired_weight)):
+        if total_weight1 + total_weight2 > desired_weight and len(weights2) == 1:
+            script, = weights2.iterkeys()
+            new_weights = dict(weights1)
+            new_weights[script] = new_weights.get(script, 0) + desired_weight - total_weight1
+            return share_count1 + share_count2, new_weights, desired_weight
+        return share_count1 + share_count2, math.add_dicts([weights1, weights2]), total_weight1 + total_weight2
+    
+    def judge(self, (share_count, weights, total_weight), (max_shares, desired_weight)):
+        if share_count > max_shares or total_weight > desired_weight:
+            return 1
+        elif share_count == max_shares or total_weight == desired_weight:
+            return 0
+        else:
+            return -1
+    
+    def finalize(self, (share_count, weights, total_weight)):
+        return weights, total_weight
+
+class CountsSkipList(skiplist.SkipList):
+    # share_count, counts, total_count
+    
+    def __init__(self, tracker, run_identifier):
+        skiplist.SkipList.__init__(self)
+        self.tracker = tracker
+        self.run_identifier = run_identifier
+    
+    def previous(self, element):
+        return self.tracker.shares[element].previous_hash
+    
+    def get_delta(self, element):
+        from p2pool.bitcoin import data as bitcoin_data
+        if element is None:
+            return 0 # XXX
+        share = self.tracker.shares[element]
+        weight = 1 if share.nonce[:8] == self.run_identifier else 0
+        return 1, weight, 1
+    
+    def combine_deltas(self, (share_count1, weights1, total_weight1), (share_count2, weights2, total_weight2)):
+        return share_count1 + share_count2, weights1 + weights2, total_weight1 + total_weight2
+    
+    def initial_solution(self, start, (max_shares, desired_weight)):
+        return 0, 0, 0
+    
+    
+    def apply_delta(self, (share_count1, weights1, total_weight1), (share_count2, weights2, total_weight2), (max_shares, desired_weight)):
+        return share_count1 + share_count2, weights1 + weights2, total_weight1 + total_weight2
+    
+    def judge(self, (share_count, weights, total_weight), (max_shares, desired_weight)):
+        if share_count > max_shares or total_weight > desired_weight:
+            return 1
+        elif share_count == max_shares or total_weight == desired_weight:
+            return 0
+        else:
+            return -1
+    
+    def finalize(self, (share_count, weights, total_weight)):
+        if share_count != total_weight:
+            raise AssertionError()
+        return weights
+
+if __name__ == '__main__':
+    import random
+    from p2pool.bitcoin import data
+    t = data.Tracker()
+    d = WeightsSkipList(t)
+    for i in xrange(2000):
+        t.add(data.FakeShare(hash=i, previous_hash=i - 1 if i > 0 else None, new_script=i, target=random.randrange(2**249, 2**250)))
+    for i in xrange(2000):
+        #a = random.randrange(2000)
+        a = 1999
+        print d(a, a, 1000000)[1]
index abb046f..db45bd8 100644 (file)
@@ -5,6 +5,8 @@ class Base(object):
         return sol
 
 class SkipList(Base):
+    P = .5
+    
     def __init__(self):
         self.skips = expiring_dict.ExpiringDict(600)
     
@@ -16,7 +18,7 @@ class SkipList(Base):
             return self.finalize(sol)
         while True:
             if pos not in self.skips:
-                self.skips[pos] = math.geometric(.5), [(self.previous(pos), self.get_delta(pos))]
+                self.skips[pos] = math.geometric(self.P), [(self.previous(pos), self.get_delta(pos))]
             skip_length, skip = self.skips[pos]
             
             # fill previous updates
@@ -56,7 +58,7 @@ class SkipList(Base):
         
         return item_hash
 
-class DumbSkipList(Base):
+class NotSkipList(Base):
     def __call__(self, start, *args):
         pos = start
         sol = self.initial_solution(start, args)
@@ -71,148 +73,3 @@ class DumbSkipList(Base):
             sol = self.apply_delta(sol, delta, args)
             
             pos = self.previous(pos)
-
-class DistanceSkipList(SkipList):
-    def __init__(self, tracker):
-        SkipList.__init__(self)
-        self.tracker = tracker
-    
-    def previous(self, element):
-        return self.tracker.shares[element].previous_hash
-    
-    def get_delta(self, element):
-        return element, 1, self.tracker.shares[element].previous_hash
-    
-    def combine_deltas(self, (from_hash1, dist1, to_hash1), (from_hash2, dist2, to_hash2)):
-        if to_hash1 != from_hash2:
-            raise AssertionError()
-        return from_hash1, dist1 + dist2, to_hash2
-    
-    def initial_solution(self, start, (n,)):
-        return 0, start
-    
-    def apply_delta(self, (dist1, to_hash1), (from_hash2, dist2, to_hash2), (n,)):
-        if to_hash1 != from_hash2:
-            raise AssertionError()
-        return dist1 + dist2, to_hash2
-    
-    def judge(self, (dist, hash), (n,)):
-        if dist > n:
-            return 1
-        elif dist == n:
-            return 0
-        else:
-            return -1
-    
-    def finalize(self, (dist, hash)):
-        return hash
-
-if __name__ == '__main__':
-    import random
-    from p2pool.bitcoin import data
-    t = data.Tracker()
-    d = DistanceSkipList(t)
-    for i in xrange(2000):
-        t.add(data.FakeShare(hash=i, previous_hash=i - 1 if i > 0 else None))
-    for i in xrange(2000):
-        a = random.randrange(2000)
-        b = random.randrange(a + 1)
-        res = d(a, b)
-        assert res == a - b, (a, b, res)
-
-class WeightsSkipList(SkipList):
-    # share_count, weights, total_weight
-    
-    def __init__(self, tracker):
-        SkipList.__init__(self)
-        self.tracker = tracker
-    
-    def previous(self, element):
-        return self.tracker.shares[element].previous_hash
-    
-    def get_delta(self, element):
-        from p2pool.bitcoin import data as bitcoin_data
-        if element is None:
-            return (2**256, {}, 0) # XXX
-        share = self.tracker.shares[element]
-        att = bitcoin_data.target_to_average_attempts(share.target)
-        return 1, {share.new_script: att}, att
-    
-    def combine_deltas(self, (share_count1, weights1, total_weight1), (share_count2, weights2, total_weight2)):
-        return share_count1 + share_count2, math.add_dicts([weights1, weights2]), total_weight1 + total_weight2
-    
-    def initial_solution(self, start, (max_shares, desired_weight)):
-        return 0, {}, 0
-    
-    def apply_delta(self, (share_count1, weights1, total_weight1), (share_count2, weights2, total_weight2), (max_shares, desired_weight)):
-        if total_weight1 + total_weight2 > desired_weight and len(weights2) == 1:
-            script, = weights2.iterkeys()
-            new_weights = dict(weights1)
-            new_weights[script] = new_weights.get(script, 0) + desired_weight - total_weight1
-            return share_count1 + share_count2, new_weights, desired_weight
-        return share_count1 + share_count2, math.add_dicts([weights1, weights2]), total_weight1 + total_weight2
-    
-    def judge(self, (share_count, weights, total_weight), (max_shares, desired_weight)):
-        if share_count > max_shares or total_weight > desired_weight:
-            return 1
-        elif share_count == max_shares or total_weight == desired_weight:
-            return 0
-        else:
-            return -1
-    
-    def finalize(self, (share_count, weights, total_weight)):
-        return weights, total_weight
-
-class CountsSkipList(SkipList):
-    # share_count, counts, total_count
-    
-    def __init__(self, tracker, run_identifier):
-        SkipList.__init__(self)
-        self.tracker = tracker
-        self.run_identifier = run_identifier
-    
-    def previous(self, element):
-        return self.tracker.shares[element].previous_hash
-    
-    def get_delta(self, element):
-        from p2pool.bitcoin import data as bitcoin_data
-        if element is None:
-            return 0 # XXX
-        share = self.tracker.shares[element]
-        weight = 1 if share.nonce[:8] == self.run_identifier else 0
-        return 1, weight, 1
-    
-    def combine_deltas(self, (share_count1, weights1, total_weight1), (share_count2, weights2, total_weight2)):
-        return share_count1 + share_count2, weights1 + weights2, total_weight1 + total_weight2
-    
-    def initial_solution(self, start, (max_shares, desired_weight)):
-        return 0, 0, 0
-    
-    
-    def apply_delta(self, (share_count1, weights1, total_weight1), (share_count2, weights2, total_weight2), (max_shares, desired_weight)):
-        return share_count1 + share_count2, weights1 + weights2, total_weight1 + total_weight2
-    
-    def judge(self, (share_count, weights, total_weight), (max_shares, desired_weight)):
-        if share_count > max_shares or total_weight > desired_weight:
-            return 1
-        elif share_count == max_shares or total_weight == desired_weight:
-            return 0
-        else:
-            return -1
-    
-    def finalize(self, (share_count, weights, total_weight)):
-        if share_count != total_weight:
-            raise AssertionError()
-        return weights
-
-if __name__ == '__main__':
-    import random
-    from p2pool.bitcoin import data
-    t = data.Tracker()
-    d = WeightsSkipList(t)
-    for i in xrange(2000):
-        t.add(data.FakeShare(hash=i, previous_hash=i - 1 if i > 0 else None, new_script=i, target=random.randrange(2**249, 2**250)))
-    for i in xrange(2000):
-        #a = random.randrange(2000)
-        a = 1999
-        print d(a, a, 1000000)[1]