tMerge pull request #1558 from fanatid/spv - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit 4112e2c3fac36d5384e5a9734d8f808acb0acb78 DIR parent 4195001aed9a5a307cbd83b19f9e66af390643b6 HTML 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: M lib/blockchain.py | 49 ++++++++++++++++--------------- 1 file changed, 25 insertions(+), 24 deletions(-) --- DIR diff --git a/lib/blockchain.py b/lib/blockchain.py t@@ -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'))) t@@ -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 t@@ -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