1 from p2pool.util import math, skiplist
3 class WeightsSkipList(skiplist.SkipList):
4 # share_count, weights, total_weight
6 def __init__(self, tracker):
7 skiplist.SkipList.__init__(self)
10 def previous(self, element):
11 return self.tracker.shares[element].previous_hash
13 def get_delta(self, element):
14 from p2pool.bitcoin import data as bitcoin_data
16 return (2**256, {}, 0, 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*(65535-share.donation)}, att*65535, att*share.donation
21 def combine_deltas(self, (share_count1, weights1, total_weight1, total_donation_weight1), (share_count2, weights2, total_weight2, total_donation_weight2)):
22 return share_count1 + share_count2, math.add_dicts([weights1, weights2]), total_weight1 + total_weight2, total_donation_weight1 + total_donation_weight2
24 def initial_solution(self, start, (max_shares, desired_weight)):
25 assert desired_weight % 65535 == 0, divmod(desired_weight, 65535)
28 def apply_delta(self, (share_count1, weights1, total_weight1, total_donation_weight1), (share_count2, weights2, total_weight2, total_donation_weight2), (max_shares, desired_weight)):
29 if total_weight1 + total_weight2 > desired_weight and share_count2 == 1:
30 script, = weights2.iterkeys()
31 new_weights = dict(weights1)
32 assert (desired_weight - total_weight1) % 65535 == 0
33 new_weights[script] = new_weights.get(script, 0) + (desired_weight - total_weight1)//65535*weights2[script]//(total_weight2//65535)
34 return share_count1 + share_count2, new_weights, desired_weight, total_donation_weight1 + (desired_weight - total_weight1)//65535*total_donation_weight2//(total_weight2//65535)
35 return share_count1 + share_count2, math.add_dicts([weights1, weights2]), total_weight1 + total_weight2, total_donation_weight1 + total_donation_weight2
37 def judge(self, (share_count, weights, total_weight, total_donation_weight), (max_shares, desired_weight)):
38 if share_count > max_shares or total_weight > desired_weight:
40 elif share_count == max_shares or total_weight == desired_weight:
45 def finalize(self, (share_count, weights, total_weight, total_donation_weight)):
46 return weights, total_weight, total_donation_weight
48 class CountsSkipList(skiplist.SkipList):
49 # share_count, counts, total_count
51 def __init__(self, tracker, run_identifier):
52 skiplist.SkipList.__init__(self)
53 self.tracker = tracker
54 self.run_identifier = run_identifier
56 def previous(self, element):
57 return self.tracker.shares[element].previous_hash
59 def get_delta(self, element):
61 raise AssertionError()
62 share = self.tracker.shares[element]
63 return 1, set([share.hash]) if share.nonce.startswith(self.run_identifier) else set()
65 def combine_deltas(self, (share_count1, share_hashes1), (share_count2, share_hashes2)):
66 if share_hashes1 & share_hashes2:
67 raise AssertionError()
68 return share_count1 + share_count2, share_hashes1 | share_hashes2
70 def initial_solution(self, start, (desired_shares,)):
73 def apply_delta(self, (share_count1, share_hashes1), (share_count2, share_hashes2), (desired_shares,)):
74 if share_hashes1 & share_hashes2:
75 raise AssertionError()
76 return share_count1 + share_count2, share_hashes1 | share_hashes2
78 def judge(self, (share_count, share_hashes), (desired_shares,)):
79 if share_count > desired_shares:
81 elif share_count == desired_shares:
86 def finalize(self, (share_count, share_hashes)):
89 if __name__ == '__main__':
91 from p2pool.bitcoin import data
93 d = WeightsSkipList(t)
94 for i in xrange(2000):
95 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)))
96 for i in xrange(2000):
97 #a = random.randrange(2000)
99 print d(a, a, 1000000)[1]