def lwma_next_work_required(block_list):

    # T
    target_solvetime = 10 * 60
    # N For T=600, 300, 150 use approximately N=60, 90, 120
    average_window = 60
    # Define a k that will be used to get a proper average after weighting the solvetimes.
    k = int(average_window * (average_window + 1) * target_solvetime // 2)

    height = block_list[-1]['height']
    pow_limit = net['pow_limit']

    # New coins should just give away first N blocks before using this algorithm.
    if height < average_window:
        return ser.compact_from_uint256(pow_limit)

    average_target = 0
    prev_timestamp = block_list[-average_window - 1]['time']
    sum_weighted_solvetimes = 0
    solvetime_weight = 0

    # Loop through N most recent blocks.
    for i in range(height + 1 - average_window, height + 1):
        block = block_list[i - height - 1]
        # Prevent solvetimes from being negative in a safe way. It must be done like this.
        # In particular, do not attempt anything like  if(solvetime < 0) {solvetime=0;}
        # The +1 ensures new coins do not calculate nextTarget = 0.
        this_timestamp = block[
            'time'] if block['time'] > prev_timestamp else prev_timestamp + 1

        # A 6*T limit will prevent large drops in difficulty from long solvetimes.
        solve_time = min(6 * target_solvetime, this_timestamp - prev_timestamp)

        # The following is part of "preventing negative solvetimes".
        prev_timestamp = this_timestamp

        # Give linearly higher weight to more recent solvetimes.
        solvetime_weight = solvetime_weight + 1
        sum_weighted_solvetimes += solve_time * solvetime_weight

        target = ser.uint256_from_compact(block['nbits'])
        average_target += target // (
            average_window * k
        )  # Dividing by k here prevents an overflow below.

    # Desired equation in next line was nextTarget = avgTarget * sumWeightSolvetimes / k
    # but 1/k was moved to line above to prevent overflow in new coins
    next_target = sum_weighted_solvetimes * average_target

    if next_target > pow_limit:
        print('exceed pow limit')
        next_target = pow_limit

    next_nbits = ser.compact_from_uint256(next_target)
    print('lwma nbits:', hex(next_nbits))
    print('difficulty:', difficulty(next_nbits))

    return next_nbits
Example #2
0
 def _check_difficulty_target(self, header):
     parent = b2lx(header.hashPrevBlock)
     target = self.get_difficulty_target(parent)
     if (self.get_height() + 1) % 2016 == 0:
         end = self.get_timestamp(parent)
         min, max = (302400, 4838400)
         for i in range(2015):
             parent = self._get_parent(parent)
         start = self.get_timestamp(parent)
         difference = end - start
         if difference < min:
             difference = min
         elif difference > max:
             difference = max
         target = compact_from_uint256(long(uint256_from_compact(target) * (float(difference) / (60 * 60 * 24 * 14))))
     if self.testnet and header.nTime - self.get_timestamp(parent) >= 1200:
         return target
     if uint256_from_compact(header.nBits) > uint256_from_compact(target):
         raise CheckBlockHeaderError("Target difficutly is incorrect")
     return target
Example #3
0
 def _check_difficulty_target(self, header):
     parent = b2lx(header.hashPrevBlock)
     target = self.get_difficulty_target(parent)
     if (self.get_height() + 1) % 2016 == 0:
         end = self.get_timestamp(parent)
         min, max = (302400, 4838400)
         for i in range(2015):
             parent = self._get_parent(parent)
         start = self.get_timestamp(parent)
         difference = end - start
         if difference < min:
             difference = min
         elif difference > max:
             difference = max
         target = compact_from_uint256(
             long(
                 uint256_from_compact(target) * (float(difference) /
                                                 (60 * 60 * 24 * 14))))
     if self.testnet and header.nTime - self.get_timestamp(parent) >= 1200:
         return target
     if uint256_from_compact(header.nBits) > uint256_from_compact(target):
         raise CheckBlockHeaderError("Target difficutly is incorrect")
     return target
def get_next_work_required(block_list):
    global net
    fork_height = net['fork_height']
    adjust_interval = 72
    last_height = block_list[-1]['height']
    height_span = last_height + 1 - fork_height

    if height_span % adjust_interval != 0:
        print('Not time to adjust target.')
        return block_list[-1]['nbits']

    target_time_span = 72 * 10 * 60
    retarget_factor = 2
    real_time_span = block_list[-1]['time'] - block_list[-adjust_interval][
        'time']
    adjusted_time_span = real_time_span
    if adjusted_time_span < target_time_span // retarget_factor:
        adjusted_time_span = target_time_span // retarget_factor
    if adjusted_time_span > target_time_span * retarget_factor:
        adjusted_time_span = target_time_span * retarget_factor

    print('adjusted time span: %s, real time span: %s' %
          (adjusted_time_span, real_time_span))

    pow_limit = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
    last_target = ser.uint256_from_compact(block_list[-1]['nbits'])
    next_target = last_target * adjusted_time_span // target_time_span

    if next_target > pow_limit:
        print('exceed pow limit')
        next_target = pow_limit

    next_nbits = ser.compact_from_uint256(next_target)
    print('original nbits:', hex(next_nbits))
    print('difficulty:', difficulty(next_nbits))

    return next_nbits
Example #5
0
    def putoneblock(self, block, initsync=True):

        
        if not self.have_prevblock(block):
            self.orphans[block.GetHash()] = True
            self.orphan_deps[block.hashPrevBlock] = block
            self.log.warn("Orphan block %s (%d orphans)" % (b2lx(block.GetHash()), len(self.orphan_deps)))
            return False


        # if block.hashPrevBlock != self.gettophash():
        #     print("Cannot connect block to chain %s %s" % (b2lx(block.GetHash()), b2lx(self.gettophash())))
        #     return

        top_height = self.getheight()
        top_work = bytes_to_int(self.db.get(b'misc:total_work'))

        prevmeta = BlkMeta()
        if top_height >= 0:
            ser_prevhash = b2lx(block.hashPrevBlock)
            data = self.db.get(('blkmeta:'+ser_prevhash).encode())
            prevmeta.deserialize(data)
        else:
            ser_prevhash = ''

        # build network "block" msg, as canonical disk storage form
        msg = msg_block()
        msg.block = block
        msg_data = msg.to_bytes()

        # write "block" msg to storage
        fpos = self.blk_write.tell()
        self.blk_write.write(msg_data)
        self.blk_write.flush()
        
        with self.db.write_batch(transaction=True) as batch:

            # add index entry
            ser_hash = b2lx(block.GetHash())
            key = ('blocks:'+ser_hash).encode()
            value = struct.pack('i', fpos)
            batch.put(key, value)

            # store metadata related to this block
            blkmeta = BlkMeta()
            blkmeta.height = prevmeta.height + 1
            blkmeta.work = (prevmeta.work +
                    uint256_from_compact(block.nBits))
            batch.put(('blkmeta:'+ser_hash).encode(), blkmeta.serialize())

            # store list of blocks at this height
            heightidx = HeightIdx()
            heightstr = str(blkmeta.height)
            d = self.db.get(('height:'+heightstr).encode())
            if d:
                heightidx.deserialize(d)
            heightidx.blocks.append(block.GetHash())

            batch.put(('height:'+heightstr).encode(), heightidx.serialize())

        # print('height: %s' % blkmeta.height)
        # print('blk: %s' % blkmeta.work)
        # print('top: %s' % top_work)

        # if chain is not best chain, proceed no further
        if (blkmeta.work <= top_work):
            self.log.info("ChainDb: height %d (weak), block %s" % (blkmeta.height, b2lx(block.GetHash())))
            return True

        # update global chain pointers
        if not self.set_best_chain(ser_prevhash, ser_hash, block, blkmeta):
            return False

        return True
Example #6
0
 def hash_rate(self):
     bnTarget = uint256_from_compact(bytes_to_int(self.bits))
     diff = int('FFFF0000000000000000000000000000000000000000000000000000',
                16) / bnTarget
     return int(diff * (2**32 / 60))
Example #7
0
    def putoneblock(self, block):
        try:
            core.CheckBlock(block)
        except core.CheckBlockError:
            self.log.info(
                "Invalid block {}".format(block.GetHash().encode('hex')))
            return False

        if not self.have_prevblock(block):
            self.orphans[block.GetHash()] = True
            self.orphan_deps[block.hashPrevBlock] = block
            self.log.info("Orphan block {} ({} orphans)"
                          .format(block.GetHash().encode('hex'),
                                  len(self.orphan_deps)))
            return False

        top_height = self.getheight()
        top_work = long(self.db.Get(b'misc:total_work'), 16)

        # read metadata for previous block
        prevmeta = BlkMeta()
        if top_height >= 0:
            prevmeta.deserialize(self.db.Get(b'blkmeta:' + block.hashPrevBlock))

        batch = leveldb.WriteBatch()

        # build network "block" msg, as canonical disk storage form
        msg = msg_block()
        msg.block = block
        f = io.BytesIO()
        msg.msg_ser(f)
        msg_data = f.getvalue()

        # write "block" msg to storage
        fpos = self.blk_write.tell()
        self.blk_write.write(msg_data)
        self.blk_write.flush()

        # add index entry
        batch.Put(b'blocks:' + block.GetHash(), str(fpos))

        # store metadata related to this block
        blkmeta = BlkMeta()
        blkmeta.height = prevmeta.height + 1
        blkmeta.work = (prevmeta.work +
                        serialize.uint256_from_compact(block.nBits))
        batch.Put(b'blkmeta:' + block.GetHash(), blkmeta.serialize())

        # store list of blocks at this height
        heightidx = HeightIdx()
        heightstr = str(blkmeta.height)
        try:
            heightidx.deserialize(self.db.Get(b'height:' + heightstr))
        except KeyError:
            pass
        heightidx.blocks.append(block.GetHash())

        batch.Put(b'height:' + heightstr, heightidx.serialize())
        self.db.Write(batch)

        # if chain is not best chain, proceed no further
        if blkmeta.work <= top_work:
            self.log.info(
                "height {} (weak), block {}"
                .format(blkmeta.height, block.GetHash().encode('hex')))
            return True

        # update global chain pointers
        if not self.set_best_chain(block.hashPrevBlock, block.GetHash(),
                                   block, blkmeta):
            return False

        return True
Example #8
0
    def putoneblock(self, block):
        try:
            core.CheckBlock(block)
        except core.CheckBlockError:
            self.log.info("Invalid block {}".format(
                block.GetHash().encode('hex')))
            return False

        if not self.have_prevblock(block):
            self.orphans[block.GetHash()] = True
            self.orphan_deps[block.hashPrevBlock] = block
            self.log.info("Orphan block {} ({} orphans)".format(
                block.GetHash().encode('hex'), len(self.orphan_deps)))
            return False

        top_height = self.getheight()
        top_work = long(self.db.Get(b'misc:total_work'), 16)

        # read metadata for previous block
        prevmeta = BlkMeta()
        if top_height >= 0:
            prevmeta.deserialize(self.db.Get(b'blkmeta:' +
                                             block.hashPrevBlock))

        batch = leveldb.WriteBatch()

        # build network "block" msg, as canonical disk storage form
        msg = msg_block()
        msg.block = block
        f = io.BytesIO()
        msg.msg_ser(f)
        msg_data = f.getvalue()

        # write "block" msg to storage
        fpos = self.blk_write.tell()
        self.blk_write.write(msg_data)
        self.blk_write.flush()

        # add index entry
        batch.Put(b'blocks:' + block.GetHash(), str(fpos))

        # store metadata related to this block
        blkmeta = BlkMeta()
        blkmeta.height = prevmeta.height + 1
        blkmeta.work = (prevmeta.work +
                        serialize.uint256_from_compact(block.nBits))
        batch.Put(b'blkmeta:' + block.GetHash(), blkmeta.serialize())

        # store list of blocks at this height
        heightidx = HeightIdx()
        heightstr = str(blkmeta.height)
        try:
            heightidx.deserialize(self.db.Get(b'height:' + heightstr))
        except KeyError:
            pass
        heightidx.blocks.append(block.GetHash())

        batch.Put(b'height:' + heightstr, heightidx.serialize())
        self.db.Write(batch)

        # if chain is not best chain, proceed no further
        if blkmeta.work <= top_work:
            self.log.info("height {} (weak), block {}".format(
                blkmeta.height,
                block.GetHash().encode('hex')))
            return True

        # update global chain pointers
        if not self.set_best_chain(block.hashPrevBlock, block.GetHash(), block,
                                   blkmeta):
            return False

        return True