made FloatingInteger usage explicit
authorForrest Voight <forrest@forre.st>
Thu, 15 Dec 2011 13:25:59 +0000 (08:25 -0500)
committerForrest Voight <forrest@forre.st>
Sat, 17 Dec 2011 09:37:50 +0000 (04:37 -0500)
p2pool/bitcoin/data.py
p2pool/bitcoin/getwork.py
p2pool/data.py
p2pool/main.py
p2pool/test/bitcoin/test_data.py

index c8d9743..2c2b629 100644 (file)
@@ -322,7 +322,7 @@ class ChecksummedType(Type):
         return (file, data), hashlib.sha256(hashlib.sha256(data).digest()).digest()[:4]
 
 class FloatingInteger(object):
-    __slots__ = ['_bits']
+    __slots__ = ['bits', '_target']
     
     @classmethod
     def from_target_upper_bound(cls, target):
@@ -333,60 +333,33 @@ class FloatingInteger(object):
         bits = struct.unpack('<I', bits2)[0]
         return cls(bits)
     
-    def __init__(self, bits, value=None):
-        self._bits = bits
-        if value is not None and self._value != value:
-            raise ValueError('value does not match')
+    def __init__(self, bits, target=None):
+        self.bits = bits
+        self._target = None
+        if target is not None and self.target != target:
+            raise ValueError('target does not match')
     
     @property
-    def _value(self):
-        return math.shift_left(self._bits & 0x00ffffff, 8 * ((self._bits >> 24) - 3))
+    def target(self):
+        res = self._target
+        if res is None:
+            res = self._target = math.shift_left(self.bits & 0x00ffffff, 8 * ((self.bits >> 24) - 3))
+        return res
     
     def __hash__(self):
-        return hash(self._value)
+        return hash(self.bits)
     
-    def __cmp__(self, other):
-        if isinstance(other, FloatingInteger):
-            return cmp(self._value, other._value)
-        elif isinstance(other, (int, long)):
-            return cmp(self._value, other)
-        else:
-            raise NotImplementedError(other)
+    def __eq__(self, other):
+        return self.bits == other.bits
     
-    def __int__(self):
-        return self._value
+    def __ne__(self, other):
+        return not (self == other)
+    
+    def __cmp__(self, other):
+        assert False
     
     def __repr__(self):
-        return 'FloatingInteger(bits=%s, value=%s)' % (hex(self._bits), hex(self._value))
-    
-    def __add__(self, other):
-        if isinstance(other, (int, long)):
-            return self._value + other
-        raise NotImplementedError()
-    __radd__ = __add__
-    def __mul__(self, other):
-        if isinstance(other, (int, long)):
-            return self._value * other
-        raise NotImplementedError()
-    __rmul__ = __mul__
-    def __truediv__(self, other):
-        if isinstance(other, (int, long)):
-            return self._value / other
-        raise NotImplementedError()
-    def __floordiv__(self, other):
-        if isinstance(other, (int, long)):
-            return self._value // other
-        raise NotImplementedError()
-    __div__ = __truediv__
-    def __rtruediv__(self, other):
-        if isinstance(other, (int, long)):
-            return other / self._value
-        raise NotImplementedError()
-    def __rfloordiv__(self, other):
-        if isinstance(other, (int, long)):
-            return other // self._value
-        raise NotImplementedError()
-    __rdiv__ = __rtruediv__
+        return 'FloatingInteger(bits=%s, target=%s)' % (hex(self.bits), hex(self.target))
 
 class FloatingIntegerType(Type):
     _inner = StructType('<I')
@@ -396,7 +369,7 @@ class FloatingIntegerType(Type):
         return FloatingInteger(bits), file
     
     def write(self, file, item):
-        return self._inner.write(file, item._bits)
+        return self._inner.write(file, item.bits)
 
 class PossiblyNoneType(Type):
     def __init__(self, none_value, inner):
@@ -449,7 +422,7 @@ block_header_type = ComposedType([
     ('previous_block', PossiblyNoneType(0, HashType())),
     ('merkle_root', HashType()),
     ('timestamp', StructType('<I')),
-    ('target', FloatingIntegerType()),
+    ('bits', FloatingIntegerType()),
     ('nonce', StructType('<I')),
 ])
 
index df4eb7c..9beefd8 100644 (file)
@@ -13,11 +13,11 @@ def _swap4(s):
     return ''.join(s[x:x+4][::-1] for x in xrange(0, len(s), 4))
 
 class BlockAttempt(object):
-    def __init__(self, version, previous_block, merkle_root, timestamp, block_target, share_target):
-        self.version, self.previous_block, self.merkle_root, self.timestamp, self.block_target, self.share_target = version, previous_block, merkle_root, timestamp, block_target, share_target
+    def __init__(self, version, previous_block, merkle_root, timestamp, bits, share_target):
+        self.version, self.previous_block, self.merkle_root, self.timestamp, self.bits, self.share_target = version, previous_block, merkle_root, timestamp, bits, share_target
     
     def __hash__(self):
-        return hash((self.version, self.previous_block, self.merkle_root, self.timestamp, self.block_target, self.share_target))
+        return hash((self.version, self.previous_block, self.merkle_root, self.timestamp, self.bits, self.share_target))
     
     def __eq__(self, other):
         if not isinstance(other, BlockAttempt):
@@ -39,7 +39,7 @@ class BlockAttempt(object):
             previous_block=self.previous_block,
             merkle_root=self.merkle_root,
             timestamp=self.timestamp,
-            target=self.block_target,
+            bits=self.bits,
             nonce=0,
         ))
         
@@ -69,7 +69,7 @@ class BlockAttempt(object):
             previous_block=attrs['previous_block'],
             merkle_root=attrs['merkle_root'],
             timestamp=attrs['timestamp'],
-            block_target=attrs['target'],
+            bits=attrs['bits'],
             share_target=bitcoin_data.HashType().unpack(getwork['target'].decode('hex')),
         )
         
index 06a1319..448e40c 100644 (file)
@@ -24,7 +24,7 @@ share_data_type = bitcoin_data.ComposedType([
 
 share_info_type = bitcoin_data.ComposedType([
     ('share_data', share_data_type),
-    ('target', bitcoin_data.FloatingIntegerType()),
+    ('bits', bitcoin_data.FloatingIntegerType()),
     ('timestamp', bitcoin_data.StructType('<I')),
 ])
 
@@ -56,12 +56,12 @@ class Share(object):
     def from_share(cls, share, net):
         if share['type'] == 0:
             res = cls.from_share1a(share1a_type.unpack(share['contents']), net)
-            if not (res.pow_hash > res.header['target']):
+            if not (res.pow_hash > res.header['bits'].target):
                 raise ValueError('invalid share type')
             return res
         elif share['type'] == 1:
             res = cls.from_share1b(share1b_type.unpack(share['contents']), net)
-            if not (res.pow_hash <= res.header['target']):
+            if not (res.pow_hash <= res.header['bits'].target):
                 raise ValueError('invalid share type')
             return res
         else:
@@ -96,7 +96,7 @@ class Share(object):
         self.merkle_branch = merkle_branch
         
         self.share_data = self.share_info['share_data']
-        self.target = self.share_info['target']
+        self.target = self.share_info['bits'].target
         self.timestamp = self.share_info['timestamp']
         
         self.new_script = self.share_data['new_script']
@@ -127,7 +127,7 @@ class Share(object):
         
         self.stale_frac = self.share_data['stale_frac']/254 if self.share_data['stale_frac'] != 255 else None
         
-        self.other_txs = other_txs if self.pow_hash <= self.header['target'] else None
+        self.other_txs = other_txs if self.pow_hash <= self.header['bits'].target else None
         
         # XXX eww
         self.time_seen = time.time()
@@ -140,7 +140,7 @@ class Share(object):
         if script.get_sigop_count(self.new_script) > 1:
             raise ValueError('too many sigops!')
         
-        share_info, gentx = generate_transaction(tracker, self.share_info['share_data'], self.header['target'], self.share_info['timestamp'], self.net)
+        share_info, gentx = generate_transaction(tracker, self.share_info['share_data'], self.header['bits'].target, self.share_info['timestamp'], self.net)
         if share_info != self.share_info:
             raise ValueError('share difficulty invalid')
         
@@ -148,9 +148,9 @@ class Share(object):
             raise ValueError('''gentx doesn't match header via merkle_branch''')
     
     def as_share(self):
-        if self.pow_hash > self.header['target']: # share1a
+        if self.pow_hash > self.header['bits'].target: # share1a
             return dict(type=0, contents=share1a_type.pack(self.as_share1a()))
-        elif self.pow_hash <= self.header['target']: # share1b
+        elif self.pow_hash <= self.header['bits'].target: # share1b
             return dict(type=1, contents=share1b_type.pack(self.as_share1b()))
         else:
             raise AssertionError()
@@ -168,7 +168,7 @@ class Share(object):
         if self.other_txs is None:
             raise ValueError('share does not contain all txs')
         
-        share_info, gentx = generate_transaction(tracker, self.share_info['share_data'], self.header['target'], self.share_info['timestamp'], self.net)
+        share_info, gentx = generate_transaction(tracker, self.share_info['share_data'], self.header['bits'].target, self.share_info['timestamp'], self.net)
         assert share_info == self.share_info
         
         return dict(header=self.header, txs=[gentx] + self.other_txs)
@@ -199,18 +199,18 @@ def generate_transaction(tracker, share_data, block_target, desired_timestamp, n
     height, last = tracker.get_height_and_last(previous_share_hash)
     assert height >= chain_length or last is None
     if height < net.TARGET_LOOKBEHIND:
-        target = bitcoin_data.FloatingInteger.from_target_upper_bound(net.MAX_TARGET)
+        bits = bitcoin_data.FloatingInteger.from_target_upper_bound(net.MAX_TARGET)
     else:
         attempts_per_second = get_pool_attempts_per_second(tracker, previous_share_hash, net.TARGET_LOOKBEHIND)
         pre_target = 2**256//(net.SHARE_PERIOD*attempts_per_second) - 1
         pre_target2 = math.clip(pre_target, (previous_share.target*9//10, previous_share.target*11//10))
         pre_target3 = math.clip(pre_target2, (0, net.MAX_TARGET))
-        target = bitcoin_data.FloatingInteger.from_target_upper_bound(pre_target3)
+        bits = bitcoin_data.FloatingInteger.from_target_upper_bound(pre_target3)
     
     attempts_to_block = bitcoin_data.target_to_average_attempts(block_target)
     max_att = net.SPREAD * attempts_to_block
     
-    this_att = min(bitcoin_data.target_to_average_attempts(target), max_att)
+    this_att = min(bitcoin_data.target_to_average_attempts(bits.target), max_att)
     other_weights, other_total_weight, other_donation_weight = tracker.get_cumulative_weights(previous_share_hash, min(height, chain_length), 65535*max(0, max_att - this_att))
     assert other_total_weight == sum(other_weights.itervalues()) + other_donation_weight, (other_total_weight, sum(other_weights.itervalues()) + other_donation_weight)
     weights, total_weight, donation_weight = math.add_dicts({new_script: this_att*(65535-donation)}, other_weights), this_att*65535 + other_total_weight, this_att*donation + other_donation_weight
@@ -234,7 +234,7 @@ def generate_transaction(tracker, share_data, block_target, desired_timestamp, n
     
     share_info = dict(
         share_data=share_data,
-        target=target,
+        bits=bits,
         timestamp=math.clip(desired_timestamp, (previous_share.timestamp - 60, previous_share.timestamp + 60)) if previous_share is not None else desired_timestamp,
     )
     
index db8fde7..75c1896 100644 (file)
@@ -36,7 +36,7 @@ def getwork(bitcoind):
         transactions=[bitcoin_data.tx_type.unpack(x.decode('hex')) for x in work['transactions']],
         subsidy=work['coinbasevalue'],
         time=work['time'],
-        target=bitcoin_data.FloatingIntegerType().unpack(work['bits'].decode('hex')[::-1]) if isinstance(work['bits'], (str, unicode)) else bitcoin_data.FloatingInteger(work['bits']),
+        bits=bitcoin_data.FloatingIntegerType().unpack(work['bits'].decode('hex')[::-1]) if isinstance(work['bits'], (str, unicode)) else bitcoin_data.FloatingInteger(work['bits']),
     ))
 
 @deferral.retry('Error creating payout script:', 10)
@@ -152,7 +152,7 @@ def main(args, net, datadir_path):
             pre_current_work.set(dict(
                 version=work['version'],
                 previous_block=work['previous_block_hash'],
-                target=work['target'],
+                bits=work['bits'],
             ))
         
         def set_real_work2():
@@ -247,7 +247,7 @@ def main(args, net, datadir_path):
         
         @tracker.verified.added.watch
         def _(share):
-            if share.pow_hash <= share.header['target']:
+            if share.pow_hash <= share.header['bits'].target:
                 if factory.conn.value is not None:
                     factory.conn.value.send_block(block=share.as_block(tracker))
                 else:
@@ -442,14 +442,14 @@ def main(args, net, datadir_path):
                         255 if shares == 0 else math.perfect_round(254*stales/shares)
                     )(*get_share_counts()),
                 ),
-                block_target=state['target'],
+                block_target=state['bits'].target,
                 desired_timestamp=int(time.time() - current_work2.value['clock_offset']),
                 net=net,
             )
             
             print 'New work for worker %s! Difficulty: %.06f Payout if block: %.6f %s Total block value: %.6f %s including %i transactions' % (
                 user,
-                bitcoin_data.target_to_difficulty(share_info['target']),
+                bitcoin_data.target_to_difficulty(share_info['bits'].target),
                 (sum(t['value'] for t in generate_tx['tx_outs'] if t['script'] == payout_script) - subsidy//200)*1e-8, net.BITCOIN_SYMBOL,
                 subsidy*1e-8, net.BITCOIN_SYMBOL,
                 len(current_work2.value['transactions']),
@@ -459,7 +459,7 @@ def main(args, net, datadir_path):
             merkle_root = bitcoin_data.merkle_hash(map(bitcoin_data.tx_type.hash256, transactions))
             merkle_root_to_transactions[merkle_root] = share_info, transactions, time.time()
             
-            return bitcoin_getwork.BlockAttempt(state['version'], state['previous_block'], merkle_root, current_work2.value['time'], state['target'], share_info['target']), state['best_share_hash']
+            return bitcoin_getwork.BlockAttempt(state['version'], state['previous_block'], merkle_root, current_work2.value['time'], state['bits'], share_info['bits'].target), state['best_share_hash']
         
         my_shares = set()
         doa_shares = set()
@@ -478,12 +478,12 @@ def main(args, net, datadir_path):
                 
                 pow_hash = net.BITCOIN_POW_FUNC(header)
                 
-                if pow_hash <= header['target'] or p2pool.DEBUG:
+                if pow_hash <= header['bits'].target or p2pool.DEBUG:
                     if factory.conn.value is not None:
                         factory.conn.value.send_block(block=dict(header=header, txs=transactions))
                     else:
                         print 'No bitcoind connection! Erp!'
-                    if pow_hash <= header['target']:
+                    if pow_hash <= header['bits'].target:
                         print
                         print 'GOT BLOCK! Passing to bitcoind! bitcoin: %x' % (hash_,)
                         print
@@ -511,9 +511,8 @@ def main(args, net, datadir_path):
                     except:
                         log.err(None, 'Error while processing merged mining POW:')
                 
-                target = share_info['target']
-                if pow_hash > target:
-                    print 'Worker submitted share with hash > target:\nhash  : %x\ntarget: %x' % (pow_hash, target)
+                if pow_hash > share_info['bits'].target:
+                    print 'Worker submitted share with hash > target:\nhash  : %x\ntarget: %x' % (pow_hash, share_info['bits'].target)
                     return False
                 share = p2pool_data.Share(net, header, share_info, other_txs=transactions[1:])
                 my_shares.add(share.hash)
index a005518..a29c965 100644 (file)
@@ -10,7 +10,7 @@ class Test(unittest.TestCase):
             previous_block=0x000000000000038a2a86b72387f93c51298298a732079b3b686df3603d2f6282,
             merkle_root=0x37a43a3b812e4eb665975f46393b4360008824aab180f27d642de8c28073bc44,
             timestamp=1323752685,
-            target=data.FloatingInteger(437159528),
+            bits=data.FloatingInteger(437159528),
             nonce=3658685446,
         )) == 0x000000000000003aaaf7638f9f9c0d0c60e8b0eb817dcdb55fd2b1964efc5175