stale tracking
authorForrest Voight <forrest@forre.st>
Wed, 20 Jul 2011 11:51:55 +0000 (07:51 -0400)
committerForrest Voight <forrest@forre.st>
Wed, 20 Jul 2011 11:51:55 +0000 (07:51 -0400)
p2pool/main.py
p2pool/util/skiplist.py

index de7b63e..8decf3c 100644 (file)
@@ -265,6 +265,7 @@ def main(args):
         # setup worker logic
         
         merkle_root_to_transactions = expiring_dict.ExpiringDict(300)
+        run_identifier = struct.pack('<Q', random.randrange(2**64))
         
         def compute(state, all_targets):
             pre_extra_txs = [tx for tx in tx_pool.itervalues() if tx.is_good()]
@@ -284,7 +285,7 @@ def main(args):
                 previous_share_hash=state['best_share_hash'],
                 new_script=my_script,
                 subsidy=(50*100000000 >> (state['height'] + 1)//210000) + sum(tx.value_in - tx.value_out for tx in extra_txs),
-                nonce=struct.pack('<Q', random.randrange(2**64)),
+                nonce=run_identifier + struct.pack('<Q', random.randrange(2**64)),
                 block_target=state['target'],
                 net=args.net,
             )
@@ -308,6 +309,8 @@ def main(args):
                 target = min(2**256//2**32 - 1, target)
             return ba.getwork(target)
         
+        my_shares = set()
+        
         def got_response(data):
             try:
                 # match up with transactions
@@ -327,6 +330,7 @@ def main(args):
                     else:
                         print 'No bitcoind connection! Erp!'
                 share = p2pool.Share.from_block(block)
+                my_shares.add(share.hash)
                 print 'GOT SHARE! %x' % (share.hash,)
                 p2p_shares([share])
             except:
@@ -455,20 +459,29 @@ def main(args):
         work1_thread()
         work2_thread()
         
+        counter = skiplist.CountsSkipList(tracker, my_script, run_identifier)
+        
         while True:
             yield deferral.sleep(random.expovariate(1/1))
             try:
                 if current_work.value['best_share_hash'] is not None:
                     height, last = tracker.get_height_and_last(current_work.value['best_share_hash'])
-                    att_s = p2pool.get_pool_attempts_per_second(tracker, current_work.value['best_share_hash'], args.net)
                     if height > 5:
+                        print "narg"
+                        att_s = p2pool.get_pool_attempts_per_second(tracker, current_work.value['best_share_hash'], args.net)
                         weights, total_weight = tracker.get_cumulative_weights(current_work.value['best_share_hash'], min(height, 1000), 2**100)
-                        print 'Pool rate: %i mhash/s %i shares Contribution: %.02f%% >%i mhash/s' % (
+                        count = counter(current_work.value['best_share_hash'], height, 2**100)
+                        print 'Pool: %i mhash/s in %i shares Recent: %.02f%% >%i mhash/s Known: %i shares (so %i stales)' % (
                             att_s//1000000,
                             height,
                             weights.get(my_script, 0)/total_weight*100,
                             weights.get(my_script, 0)/total_weight*att_s//1000000,
+                            count,
+                            len(my_shares) - count,
                         )
+                        #weights, total_weight = tracker.get_cumulative_weights(current_work.value['best_share_hash'], min(height, 100), 2**100)
+                        #for k, v in weights.iteritems():
+                        #    print k.encode('hex'), v/total_weight
             except:
                 log.err()
     except:
index e57eeda..2aa86ed 100644 (file)
@@ -139,14 +139,10 @@ class WeightsSkipList(SkipList):
         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, dict((k, weights1.get(k, 0) + weights2.get(k, 0)) for k in set(weights1.keys() + weights2.keys())), total_weight1 + 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 combine_deltas(self, (share_count1, weights1, total_weight1), (share_count2, weights2, total_weight2)):
-        return share_count1 + share_count2, dict((k, weights1.get(k, 0) + weights2.get(k, 0)) for k in set(weights1.keys() + weights2.keys())), total_weight1 + total_weight2
-    
+        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:
@@ -154,7 +150,7 @@ class WeightsSkipList(SkipList):
             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, dict((k, weights1.get(k, 0) + weights2.get(k, 0)) for k in set(weights1.keys() + weights2.keys())), total_weight1 + total_weight2
+        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:
@@ -167,6 +163,49 @@ class WeightsSkipList(SkipList):
     def finalize(self, (share_count, weights, total_weight)):
         return weights, total_weight
 
+class CountsSkipList(SkipList):
+    # share_count, counts, total_count
+    
+    def __init__(self, tracker, script, run_identifier):
+        SkipList.__init__(self)
+        self.tracker = tracker
+        self.script = script
+        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.new_script == self.script and 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