def get_next_work_required(self, blkprevhash, block): blkprev = self.database.get_block_handle(blkprevhash) # Difficulty changes only once every TARGET_INTERVAL blocks (except for testnet) if ((blkprev.get_height() + 1) % TARGET_INTERVAL): # Special rules for testnet after 15 Feb 2012 if ((self.database.runmode == TESTNET and (block.blockheader.time > 1329264000)) or (self.database.runmode == TESTNET3)): return self.get_testnet_work_required_15feb1012(blkprev, block) # Difficulty unchanged return (blkprev.get_blockheader().bits) # Locate the block 2 weeks ago blk2weekago = blkprev for i in range(TARGET_INTERVAL-1): blk2weekago = self.database.get_block_handle(blk2weekago.get_blockheader().hash_prev) header_block2weekago = blk2weekago.get_blockheader() header_blocknow = blkprev.get_blockheader() actual_timespan = header_blocknow.time - header_block2weekago.time # Limit adjustment step if actual_timespan < TARGET_TIMESPAN/4: actual_timespan = TARGET_TIMESPAN/4; if actual_timespan > TARGET_TIMESPAN*4: actual_timespan = TARGET_TIMESPAN*4; # Retarget new_target = Uint256.from_bignum(header_blocknow.target().get_bignum() * actual_timespan / TARGET_TIMESPAN) if new_target > PROOF_OF_WORK_LIMIT[self.database.runmode]: new_target = PROOF_OF_WORK_LIMIT[self.database.runmode] new_bits = compact_difficulty(new_target) self.log.info("Retarget: targetTimespan:%d actualTimespan:%d, %08x -> %08x " % (TARGET_TIMESPAN, actual_timespan, header_blocknow.bits, new_bits)) return (new_bits)
def retarget(time_2weekago, time_now, target_timespan, current_target, # compact format proof_of_work_limit): actual_timespan = time_now - time_2weekago # Limit adjustment step if actual_timespan < target_timespan/4: actual_timespan = target_timespan/4; if actual_timespan > target_timespan*4: actual_timespan = target_timespan*4; # Retarget new_target = Uint256.from_bignum(uint256_difficulty(current_target).get_bignum() * actual_timespan / target_timespan) if new_target > proof_of_work_limit: new_target = proof_of_work_limit return compact_difficulty(new_target)
def retarget( time_2weekago, time_now, target_timespan, current_target, # compact format proof_of_work_limit): actual_timespan = time_now - time_2weekago # Limit adjustment step if actual_timespan < target_timespan / 4: actual_timespan = target_timespan / 4 if actual_timespan > target_timespan * 4: actual_timespan = target_timespan * 4 # Retarget new_target = Uint256.from_bignum( uint256_difficulty(current_target).get_bignum() * actual_timespan / target_timespan) if new_target > proof_of_work_limit: new_target = proof_of_work_limit return compact_difficulty(new_target)
def test_compact_difficulty(self): value = compact_difficulty(Uint256.from_bignum(0x00000000FFFF0000000000000000000000000000000000000000000000000000)) assert value == 0x1d00ffff value = compact_difficulty(Uint256.from_bignum(0x00000000000404cb000000000000000000000000000000000000000000000000)) assert value == 0x1b0404cb
def test_uint256_difficulty(self): value = uint256_difficulty(0x1d00ffff) assert value == Uint256.from_bignum(0x00000000FFFF0000000000000000000000000000000000000000000000000000) value = uint256_difficulty(0x1b0404cb) assert value == Uint256.from_bignum(0x00000000000404cb000000000000000000000000000000000000000000000000)
import unittest from coinpy.lib.blocks.difficulty import uint256_difficulty, compact_difficulty from coinpy.model.protocol.structures.uint256 import Uint256 class TestDifficulty(unittest.TestCase): def setUp(self): pass def test_compact_difficulty(self): value = compact_difficulty(Uint256.from_bignum(0x00000000FFFF0000000000000000000000000000000000000000000000000000)) assert value == 0x1d00ffff value = compact_difficulty(Uint256.from_bignum(0x00000000000404cb000000000000000000000000000000000000000000000000)) assert value == 0x1b0404cb def test_uint256_difficulty(self): value = uint256_difficulty(0x1d00ffff) assert value == Uint256.from_bignum(0x00000000FFFF0000000000000000000000000000000000000000000000000000) value = uint256_difficulty(0x1b0404cb) assert value == Uint256.from_bignum(0x00000000000404cb000000000000000000000000000000000000000000000000) if __name__ == '__main__': value = compact_difficulty(Uint256.from_bignum(0x00000000FFFF0000000000000000000000000000000000000000000000000000)) #print value #print 0x1d00ffff unittest.main()
def uint256_difficulty(bits): exp, value = bits >> 24, bits & 0xFFFFFF return (Uint256.from_bignum(value * 2 ** (8 * (exp - 3))))
COIN = 100000000 CENT = 1000000 MAX_MONEY = 21000000 * COIN TARGET_TIMESPAN = 14 * 24 * 60 * 60 # 2 weeks TARGET_SPACING = 10 * 60 # 10 minutes TARGET_INTERVAL = TARGET_TIMESPAN / TARGET_SPACING # 2016 blocks / 2weeks # block_time must be larger than the median of past "MEDIAN_TIME_SPAN" block_time's. MEDIAN_TIME_SPAN=11 # when smaller, locktime is treated as a blockheight, otherwise as a blocktime LOCKTIME_THRESHOLD = 500000000; # Tue Nov 5 00:53:20 1985 UTC COINBASE_MATURITY=100 CONFIRMATIONS=6 MAX_BLOCK_SIZE = 1000000 #MAX_BLOCK_SIZE PROOF_OF_WORK_LIMIT = {MAIN: Uint256.from_bignum((1 << (256 - 32)) - 1), #~uint256(0) >> 32 TESTNET : Uint256.from_bignum((1 << (256 - 28)) - 1), TESTNET3 : Uint256.from_bignum((1 << (256 - 28)) - 1), UNITNET: Uint256.from_bignum((1 << (256 - 10)) - 1)} def is_money_range(value): return (value >= 0 and value <= MAX_MONEY)
def target(self): exp, value = self.bits >> 24, self.bits & 0xFFFFFF return Uint256.from_bignum(value * 2**(8 * (exp - 3)))
CENT = 1000000 MAX_MONEY = 21000000 * COIN TARGET_TIMESPAN = 14 * 24 * 60 * 60 # 2 weeks TARGET_SPACING = 10 * 60 # 10 minutes TARGET_INTERVAL = TARGET_TIMESPAN / TARGET_SPACING # 2016 blocks / 2weeks # block_time must be larger than the median of past "MEDIAN_TIME_SPAN" block_time's. MEDIAN_TIME_SPAN = 11 # when smaller, locktime is treated as a blockheight, otherwise as a blocktime LOCKTIME_THRESHOLD = 500000000 # Tue Nov 5 00:53:20 1985 UTC COINBASE_MATURITY = 100 CONFIRMATIONS = 6 MAX_BLOCK_SIZE = 1000000 #MAX_BLOCK_SIZE PROOF_OF_WORK_LIMIT = { MAIN: Uint256.from_bignum((1 << (256 - 32)) - 1), #~uint256(0) >> 32 TESTNET: Uint256.from_bignum((1 << (256 - 28)) - 1), TESTNET3: Uint256.from_bignum((1 << (256 - 28)) - 1), UNITNET: Uint256.from_bignum((1 << (256 - 10)) - 1) } def is_money_range(value): return (value >= 0 and value <= MAX_MONEY)