def test_blockchain_adjust(self): # normal case, last not specific difficulty (2016 here) difficulty_history1 = StaticDifficultyHistory({ 2015: DifficultyIterator.Difficulty(time=1357060298, bits=473464683), 2016: DifficultyIterator.Difficulty(time=1357060898, bits=473464684), 2017: DifficultyIterator.Difficulty(time=1357061498, bits=compact_difficulty( PROOF_OF_WORK_LIMIT[TESTNET])), 2018: DifficultyIterator.Difficulty(time=1357062098, bits=compact_difficulty( PROOF_OF_WORK_LIMIT[TESTNET])) }) self.assertEquals( adjust(2019, difficulty_history1, 1357062698, PROOF_OF_WORK_LIMIT[TESTNET]), 473464684) # no block mined since 2*TARGET_SPACING => reset to PROOF_OF_WORK_LIMIT difficulty_history2 = StaticDifficultyHistory({ 3500: DifficultyIterator.Difficulty(time=1357060298, bits=373464683) }) self.assertEquals( adjust(3501, difficulty_history2, 1357061499, PROOF_OF_WORK_LIMIT[TESTNET]), compact_difficulty(PROOF_OF_WORK_LIMIT[TESTNET]))
def test_blockchain_retarget(self): # Standard case retarget (taken from block 46368) self.assertEquals(retarget(1268010873, 1269211443, TARGET_TIMESPAN, 473464687, PROOF_OF_WORK_LIMIT[MAIN]), 473437045) # Limit adjustment step as in block 68544 "actual_timespan < TARGET_TIMESPAN/4" self.assertEquals(retarget(1279008237, 1279297671, TARGET_TIMESPAN, 470131700, PROOF_OF_WORK_LIMIT[MAIN]), 469854461) # Limit adjustment step "actual_timespan > TARGET_TIMESPAN/4" self.assertEquals(retarget(1357060298, 1363713098, TARGET_TIMESPAN, 470131700, PROOF_OF_WORK_LIMIT[MAIN]), 471240656) # Min to the proof of work limit self.assertEquals(retarget(1357060298, int(1357060298+TARGET_TIMESPAN*1.5), TARGET_TIMESPAN, compact_difficulty(PROOF_OF_WORK_LIMIT[MAIN]), PROOF_OF_WORK_LIMIT[MAIN]), compact_difficulty(PROOF_OF_WORK_LIMIT[MAIN]))
def test_blockchain_adjust(self): # normal case, last not specific difficulty (2016 here) difficulty_history1 = StaticDifficultyHistory({ 2015 : DifficultyIterator.Difficulty(time=1357060298, bits=473464683), 2016 : DifficultyIterator.Difficulty(time=1357060898, bits=473464684), 2017 : DifficultyIterator.Difficulty(time=1357061498, bits=compact_difficulty(PROOF_OF_WORK_LIMIT[TESTNET])), 2018 : DifficultyIterator.Difficulty(time=1357062098, bits=compact_difficulty(PROOF_OF_WORK_LIMIT[TESTNET]))}) self.assertEquals(adjust(2019, difficulty_history1, 1357062698, PROOF_OF_WORK_LIMIT[TESTNET]), 473464684) # no block mined since 2*TARGET_SPACING => reset to PROOF_OF_WORK_LIMIT difficulty_history2 = StaticDifficultyHistory({ 3500 : DifficultyIterator.Difficulty(time=1357060298, bits=373464683)}) self.assertEquals(adjust(3501, difficulty_history2, 1357061499, PROOF_OF_WORK_LIMIT[TESTNET]), compact_difficulty(PROOF_OF_WORK_LIMIT[TESTNET]))
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 adjust(height, difficulty_history, current_time, proof_of_work_limit): """ Testnet>1329264000 and Testnet3 difficulty adjusting algorithm. If there is not block during 2*TARGET_SPACING, reset difficulty to min-difficulty """ prevblocktime = difficulty_history.get_item(height-1).time if (current_time - prevblocktime > TARGET_SPACING * 2 or current_time < prevblocktime): #reset difficulty to min-difficulty return compact_difficulty(proof_of_work_limit) else: #keep the last non-special difficulty h = height - 1 d = difficulty_history.get_item(h).bits while (h % TARGET_INTERVAL != 0 and d == compact_difficulty(proof_of_work_limit)): h -= 1 d = difficulty_history.get_item(h).bits return d
def test_blockchain_get_work_required_testnet(self): # testnet adjusting algorithm (Min to the proof of work limit) difficulty_history = StaticDifficultyHistory({ 3500: DifficultyIterator.Difficulty(time=1357060298, bits=373464683) }) self.assertEquals( get_work_required(3501, difficulty_history, 1357061499, TESTNET), compact_difficulty(PROOF_OF_WORK_LIMIT[TESTNET]))
def adjust(height, difficulty_history, current_time, proof_of_work_limit): """ Testnet>1329264000 and Testnet3 difficulty adjusting algorithm. If there is not block during 2*TARGET_SPACING, reset difficulty to min-difficulty """ prevblocktime = difficulty_history.get_item(height - 1).time if (current_time - prevblocktime > TARGET_SPACING * 2 or current_time < prevblocktime): #reset difficulty to min-difficulty return compact_difficulty(proof_of_work_limit) else: #keep the last non-special difficulty h = height - 1 d = difficulty_history.get_item(h).bits while (h % TARGET_INTERVAL != 0 and d == compact_difficulty(proof_of_work_limit)): h -= 1 d = difficulty_history.get_item(h).bits return d
def get_testnet_work_required_15feb1012(self, blkprev, block): #If there is not block during 2*TARGET_SPACING, reset difficulty to min-difficilty if (block.blockheader.time - blkprev.get_blockheader().time > TARGET_SPACING * 2 or block.blockheader.time < blkprev.get_blockheader().time): new_target = PROOF_OF_WORK_LIMIT[self.database.runmode] else: #otherwise, keep the last non-special difficulty while blkprev and blkprev.get_height() % TARGET_INTERVAL != 0 and blkprev.get_blockheader().bits == compact_difficulty(PROOF_OF_WORK_LIMIT[self.database.runmode]): blkprev = self.database.get_block_handle(blkprev.get_blockheader().hash_prev) new_target = blkprev.get_blockheader().target() return compact_difficulty(new_target)
def test_blockchain_retarget(self): # Standard case retarget (taken from block 46368) self.assertEquals( retarget(1268010873, 1269211443, TARGET_TIMESPAN, 473464687, PROOF_OF_WORK_LIMIT[MAIN]), 473437045) # Limit adjustment step as in block 68544 "actual_timespan < TARGET_TIMESPAN/4" self.assertEquals( retarget(1279008237, 1279297671, TARGET_TIMESPAN, 470131700, PROOF_OF_WORK_LIMIT[MAIN]), 469854461) # Limit adjustment step "actual_timespan > TARGET_TIMESPAN/4" self.assertEquals( retarget(1357060298, 1363713098, TARGET_TIMESPAN, 470131700, PROOF_OF_WORK_LIMIT[MAIN]), 471240656) # Min to the proof of work limit self.assertEquals( retarget(1357060298, int(1357060298 + TARGET_TIMESPAN * 1.5), TARGET_TIMESPAN, compact_difficulty(PROOF_OF_WORK_LIMIT[MAIN]), PROOF_OF_WORK_LIMIT[MAIN]), compact_difficulty(PROOF_OF_WORK_LIMIT[MAIN]))
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
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 test_blockchain_get_work_required_testnet(self): # testnet adjusting algorithm (Min to the proof of work limit) difficulty_history = StaticDifficultyHistory({ 3500 : DifficultyIterator.Difficulty(time=1357060298, bits=373464683)}) self.assertEquals(get_work_required(3501, difficulty_history, 1357061499, TESTNET), compact_difficulty(PROOF_OF_WORK_LIMIT[TESTNET]))