commit 4112e2c3fac36d5384e5a9734d8f808acb0acb78
parent 4195001aed9a5a307cbd83b19f9e66af390643b6
Author: ThomasV <thomasv@electrum.org>
Date: Fri, 11 Dec 2015 10:09:11 +0100
Merge pull request #1558 from fanatid/spv
Improve get_target
Diffstat:
1 file changed, 25 insertions(+), 24 deletions(-)
diff --git a/lib/blockchain.py b/lib/blockchain.py
@@ -50,7 +50,11 @@ class Blockchain(util.PrintError):
self.print_error("prev hash mismatch: %s vs %s"
% (prev_hash, header.get('prev_block_hash')))
return False
- bits, target = self.get_target(height/2016, chain)
+ try:
+ bits, target = self.get_target(height/2016, chain)
+ except AssertionError as e:
+ self.print_error("target calculation error: %s" % (str(e)))
+ return False
if bits != header.get('bits'):
self.print_error("bits mismatch: %s vs %s"
% (bits, header.get('bits')))
@@ -88,7 +92,7 @@ class Blockchain(util.PrintError):
_hash = self.hash_header(header)
assert previous_hash == header.get('prev_block_hash')
assert bits == header.get('bits')
- assert int('0x'+_hash,16) < target
+ assert int('0x'+_hash,16) <= target
previous_header = header
previous_hash = _hash
@@ -190,36 +194,33 @@ class Blockchain(util.PrintError):
if h.get('block_height') == index*2016-1:
last = h
+ # bits to target
+ bits = last.get('bits')
+ bitsN = (bits >> 24) & 0xff
+ assert bitsN >= 0x03 and bitsN <= 0x1d, "First part of bits should be in [0x03, 0x1d]"
+ bitsBase = bits & 0xffffff
+ assert bitsN >= 0x8000 and bitsN <= 0x7fffff, "Second part of bits should be in [0x8000, 0x7fffff]"
+ target = bitsBase << (8*(bitsN-3))
+
+ # new target
nActualTimespan = last.get('timestamp') - first.get('timestamp')
nTargetTimespan = 14*24*60*60
nActualTimespan = max(nActualTimespan, nTargetTimespan/4)
nActualTimespan = min(nActualTimespan, nTargetTimespan*4)
+ new_target = min(max_target, (target * nActualTimespan)/nTargetTimespan)
- bits = last.get('bits')
- # convert to bignum
- MM = 256*256*256
- a = bits%MM
- if a < 0x8000:
- a *= 256
- target = (a) * pow(2, 8 * (bits/MM - 3))
-
- # new target
- new_target = min( max_target, (target * nActualTimespan)/nTargetTimespan )
-
- # convert it to bits
- c = ("%064X"%new_target)[2:]
- i = 31
- while c[0:2]=="00":
+ # convert new target to bits
+ c = ("%064x" % new_target)[2:]
+ while c[:2] == '00' and len(c) > 6:
c = c[2:]
- i -= 1
- c = int('0x'+c[0:6],16)
- if c >= 0x800000:
- c /= 256
- i += 1
+ bitsN, bitsBase = len(c)/2, int('0x'+c[:6], 16)
+ if bitsBase >= 0x800000:
+ bitsN += 1
+ bitsBase >>= 8
- new_bits = c + MM * i
- return new_bits, new_target
+ new_bits = bitsN << 24 | bitsBase
+ return new_bits, bitsBase << (8*(bitsN-3))
def connect_header(self, chain, header):
'''Builds a header chain until it connects. Returns True if it has