use bitcoin timestamp to judge shares
authorforrest <forrest@470744a7-cac9-478e-843e-5ec1b25c69e8>
Mon, 18 Jul 2011 08:25:25 +0000 (08:25 +0000)
committerforrest <forrest@470744a7-cac9-478e-843e-5ec1b25c69e8>
Mon, 18 Jul 2011 08:25:25 +0000 (08:25 +0000)
git-svn-id: svn://forre.st/p2pool@1401 470744a7-cac9-478e-843e-5ec1b25c69e8

p2pool/data.py
p2pool/main.py

index 7d62fac..1a3d5cd 100644 (file)
@@ -185,14 +185,13 @@ class Share(object):
     def as_share1b(self):
         return dict(header=self.header, share_info=self.share_info, other_txs=self.other_txs)
     
-    def check(self, tracker, net):
+    def check(self, tracker, now, net):
         import time
         if self.previous_share_hash is not None:
             if self.header['timestamp'] <= math.median((s.timestamp for s in itertools.islice(tracker.get_chain_to_root(self.previous_share_hash), 11)), use_float=False):
                 raise ValueError('share from too far in the past!')
         
-        # XXX use adjusted time
-        if self.header['timestamp'] > time.time() + 2*60*60:
+        if self.header['timestamp'] > now + 2*60*60:
             raise ValueError('share from too far in the future!')
         
         gentx = share_info_to_gentx(self.share_info, self.header['target'], tracker, net)
@@ -225,20 +224,19 @@ class Share2(object):
     def flag_shared(self):
         self.shared = True
 
-def generate_transaction(tracker, previous_share_hash, new_script, subsidy, nonce, block_target, net):
-    previous_share2 = tracker.shares[previous_share_hash] if previous_share_hash is not None else None
-    
+def generate_transaction(tracker, previous_share_hash, new_script, subsidy, nonce, block_target, net):    
     chain = list(itertools.islice(tracker.get_chain_to_root(previous_share_hash), net.TARGET_LOOKBEHIND))
     if len(chain) < net.TARGET_LOOKBEHIND:
         target2 = bitcoin_data.FloatingIntegerType().truncate_to(2**256//2**20 - 1)
     else:
+        previous_share = tracker.shares[previous_share_hash] if previous_share_hash is not None else None
         attempts = sum(bitcoin_data.target_to_average_attempts(share.target2) for share in chain[:-1])
         time = chain[0].timestamp - chain[-1].timestamp
         if time == 0:
             time = 1
         attempts_per_second = attempts//time
         pre_target = 2**256//(net.SHARE_PERIOD*attempts_per_second) - 1
-        pre_target2 = math.clip(pre_target, (previous_share2.target2*9//10, previous_share2.target2*11//10))
+        pre_target2 = math.clip(pre_target, (previous_share.target2*9//10, previous_share.target2*11//10))
         pre_target3 = math.clip(pre_target2, (0, 2**256//2**20 - 1))
         target2 = bitcoin_data.FloatingIntegerType().truncate_to(pre_target3)
         print attempts_per_second//1000, 'KHASH'
@@ -309,14 +307,14 @@ class OkayTracker(bitcoin_data.Tracker):
         
         self.get_cumulative_weights = skiplist.WeightsSkipList(self)
     
-    def attempt_verify(self, share):
+    def attempt_verify(self, share, now):
+        if share.hash in self.verified.shares:
+            return True
         height, last = self.get_height_and_last(share.hash)
         if height < self.net.CHAIN_LENGTH and last is not None:
             raise AssertionError()
-        if share.hash in self.verified.shares:
-            return True
         try:
-            share.check(self, self.net)
+            share.check(self, now, self.net)
         except:
             print
             print 'Share check failed:'
@@ -327,7 +325,7 @@ class OkayTracker(bitcoin_data.Tracker):
             self.verified.add(share)
             return True
     
-    def think(self, ht):
+    def think(self, ht, now):
         desired = set()
         
         # O(len(self.heads))
@@ -339,7 +337,7 @@ class OkayTracker(bitcoin_data.Tracker):
             head_height, last = self.get_height_and_last(head)
             
             for share in itertools.islice(self.get_chain_known(head), None if last is None else max(0, head_height - self.net.CHAIN_LENGTH)):
-                if self.attempt_verify(share):
+                if self.attempt_verify(share, now):
                     break
             else:
                 desired.add((self.shares[random.choice(list(self.reverse_shares[last]))].peer, last))
@@ -354,7 +352,7 @@ class OkayTracker(bitcoin_data.Tracker):
             get = min(want, can)
             #print 'Z', head_height, last_hash is None, last_height, last_last_hash is None, want, can, get
             for share in itertools.islice(self.get_chain_known(last_hash), get):
-                if not self.attempt_verify(share):
+                if not self.attempt_verify(share, now):
                     break
             if head_height < self.net.CHAIN_LENGTH and last_last_hash is not None:
                 desired.add((self.verified.shares[random.choice(list(self.verified.reverse_shares[last_hash]))].peer, last_last_hash))
index 0aae47c..184c36c 100644 (file)
@@ -107,7 +107,10 @@ def main(args):
         @defer.inlineCallbacks
         def set_real_work():
             work, height = yield getwork(bitcoind)
-            best, desired = tracker.think(ht)
+            current_work2.set(dict(
+                time=work.timestamp,
+            ))
+            best, desired = tracker.think(ht, current_work2.value['time'])
             for peer2, share_hash in desired:
                 if peer2 is None:
                     continue
@@ -126,14 +129,9 @@ def main(args):
                 version=work.version,
                 previous_block=work.previous_block,
                 target=work.target,
-                
-                height=height + 1,
-                
+                height=height,
                 best_share_hash=best,
             ))
-            current_work2.set(dict(
-                timestamp=work.timestamp,
-            ))
         
         print 'Initializing work...'
         yield set_real_work()
@@ -156,7 +154,7 @@ def main(args):
             #print 'Received share %x' % (share.hash,)
             
             tracker.add(share)
-            best, desired = tracker.think(ht)
+            best, desired = tracker.think(ht, current_work2.value['time'])
             #for peer2, share_hash in desired:
             #    print 'Requesting parent share %x' % (share_hash,)
             #    peer2.send_getshares(hashes=[share_hash], parents=2000)
@@ -261,7 +259,7 @@ def main(args):
                 tracker=tracker,
                 previous_share_hash=state['best_share_hash'],
                 new_script=my_script,
-                subsidy=(50*100000000 >> state['height']//210000) + sum(tx.value_in - tx.value_out for tx in extra_txs),
+                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)),
                 block_target=state['target'],
                 net=args.net,
@@ -273,7 +271,7 @@ def main(args):
             merkle_root = bitcoin.data.merkle_hash(transactions)
             merkle_root_to_transactions[merkle_root] = transactions # will stay for 1000 seconds
             
-            timestamp = current_work2.value['timestamp']
+            timestamp = current_work2.value['time']
             if state['best_share_hash'] is not None:
                 timestamp2 = math.median((s.timestamp for s in itertools.islice(tracker.get_chain_to_root(state['best_share_hash']), 11)), use_float=False) + 1
                 if timestamp2 > timestamp: