d272553bc40ef7a106321b35ab3f673f150c94e4
[p2pool.git] / p2pool / skiplists.py
1 from p2pool.util import math, skiplist
2
3 class WeightsSkipList(skiplist.SkipList):
4     # share_count, weights, total_weight
5     
6     def __init__(self, tracker):
7         skiplist.SkipList.__init__(self)
8         self.tracker = tracker
9     
10     def previous(self, element):
11         return self.tracker.shares[element].previous_hash
12     
13     def get_delta(self, element):
14         from p2pool.bitcoin import data as bitcoin_data
15         if element is None:
16             return (2**256, {}, 0) # XXX
17         share = self.tracker.shares[element]
18         att = bitcoin_data.target_to_average_attempts(share.target)
19         return 1, {share.new_script: att}, att
20     
21     def combine_deltas(self, (share_count1, weights1, total_weight1), (share_count2, weights2, total_weight2)):
22         return share_count1 + share_count2, math.add_dicts([weights1, weights2]), total_weight1 + total_weight2
23     
24     def initial_solution(self, start, (max_shares, desired_weight)):
25         return 0, {}, 0
26     
27     def apply_delta(self, (share_count1, weights1, total_weight1), (share_count2, weights2, total_weight2), (max_shares, desired_weight)):
28         if total_weight1 + total_weight2 > desired_weight and len(weights2) == 1:
29             script, = weights2.iterkeys()
30             new_weights = dict(weights1)
31             new_weights[script] = new_weights.get(script, 0) + desired_weight - total_weight1
32             return share_count1 + share_count2, new_weights, desired_weight
33         return share_count1 + share_count2, math.add_dicts([weights1, weights2]), total_weight1 + total_weight2
34     
35     def judge(self, (share_count, weights, total_weight), (max_shares, desired_weight)):
36         if share_count > max_shares or total_weight > desired_weight:
37             return 1
38         elif share_count == max_shares or total_weight == desired_weight:
39             return 0
40         else:
41             return -1
42     
43     def finalize(self, (share_count, weights, total_weight)):
44         return weights, total_weight
45
46 class CountsSkipList(skiplist.SkipList):
47     # share_count, counts, total_count
48     
49     def __init__(self, tracker, run_identifier):
50         skiplist.SkipList.__init__(self)
51         self.tracker = tracker
52         self.run_identifier = run_identifier
53     
54     def previous(self, element):
55         return self.tracker.shares[element].previous_hash
56     
57     def get_delta(self, element):
58         if element is None:
59             raise AssertionError()
60         share = self.tracker.shares[element]
61         return 1, set([share.hash]) if share.nonce[:8] == self.run_identifier else set() 
62     
63     def combine_deltas(self, (share_count1, share_hashes1), (share_count2, share_hashes2)):
64         if share_hashes1 & share_hashes2:
65             raise AssertionError()
66         return share_count1 + share_count2, share_hashes1 | share_hashes2
67     
68     def initial_solution(self, start, (desired_shares,)):
69         return 0, set()
70     
71     def apply_delta(self, (share_count1, share_hashes1), (share_count2, share_hashes2), (desired_shares,)):
72         if share_hashes1 & share_hashes2:
73             raise AssertionError()
74         return share_count1 + share_count2, share_hashes1 | share_hashes2
75     
76     def judge(self, (share_count, share_hashes), (desired_shares,)):
77         if share_count > desired_shares:
78             return 1
79         elif share_count == desired_shares:
80             return 0
81         else:
82             return -1
83     
84     def finalize(self, (share_count, share_hashes)):
85         return share_hashes
86
87 if __name__ == '__main__':
88     import random
89     from p2pool.bitcoin import data
90     t = data.Tracker()
91     d = WeightsSkipList(t)
92     for i in xrange(2000):
93         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)))
94     for i in xrange(2000):
95         #a = random.randrange(2000)
96         a = 1999
97         print d(a, a, 1000000)[1]