@Override /** the testnet rules don't work for regtest, where difficulty stays the same */ public long calculateNewDifficultyTarget(StoredBlock storedPrev, Block nextBlock, BlockStore blockStore) throws VerificationException, BlockStoreException { final Block prev = storedPrev.getHeader(); return prev.getDifficultyTarget(); } }
private void checkTestnetDifficulty(StoredBlock storedPrev, Block prev, Block next) throws VerificationException, BlockStoreException { checkState(lock.isHeldByCurrentThread()); // After 15th February 2012 the rules on the testnet change to avoid people running up the difficulty // and then leaving, making it too hard to mine a block. On non-difficulty transition points, easy // blocks are allowed if there has been a span of 20 minutes without one. final long timeDelta = next.getTimeSeconds() - prev.getTimeSeconds(); // There is an integer underflow bug in bitcoin-qt that means mindiff blocks are accepted when time // goes backwards. if (timeDelta >= 0 && timeDelta > NetworkParameters.TARGET_SPACING * 2) { if (next.getDifficultyTargetAsInteger().equals(params.getMaxTarget())) return; else throw new VerificationException("Unexpected change in difficulty"); } else { // Walk backwards until we find a block that doesn't have the easiest proof of work, then check // that difficulty is equal to that one. StoredBlock cursor = storedPrev; while (!cursor.getHeader().equals(params.getGenesisBlock()) && cursor.getHeight() % params.getInterval() != 0 && cursor.getHeader().getDifficultyTargetAsInteger().equals(params.getMaxTarget())) cursor = cursor.getPrev(blockStore); BigInteger cursorTarget = cursor.getHeader().getDifficultyTargetAsInteger(); BigInteger newTarget = next.getDifficultyTargetAsInteger(); if (!cursorTarget.equals(newTarget)) throw new VerificationException("Testnet block transition that is not allowed: " + Long.toHexString(cursor.getHeader().getDifficultyTarget()) + " vs " + Long.toHexString(next.getDifficultyTarget())); } }
calcDiff = params.getMaxTarget(); int accuracyBytes = (int) (nextBlock.getDifficultyTarget() >>> 24) - 3; BigInteger receivedDifficulty = nextBlock.getDifficultyTargetAsInteger(); long nBitsNext = nextBlock.getDifficultyTarget();
void verifyDifficulty(BigInteger newTarget, Block nextBlock) { if (newTarget.compareTo(this.getMaxTarget()) > 0) { log.info("Difficulty hit proof of work limit: {}", newTarget.toString(16)); newTarget = this.getMaxTarget(); } int accuracyBytes = (int) (nextBlock.getDifficultyTarget() >>> 24) - 3; long receivedTargetCompact = nextBlock.getDifficultyTarget(); // The calculated difficulty is to a higher precision than received, so reduce here. BigInteger mask = BigInteger.valueOf(0xFFFFFFL).shiftLeft(accuracyBytes * 8); newTarget = newTarget.and(mask); long newTargetCompact = Utils.encodeCompactBits(newTarget); if (newTargetCompact != receivedTargetCompact) throw new VerificationException("Network provided difficulty bits do not match what was calculated: " + Long.toHexString(newTargetCompact) + " vs " + Long.toHexString(receivedTargetCompact)); }
if (!cursorTarget.equals(newTarget)) throw new VerificationException("Testnet block transition that is not allowed: " + Long.toHexString(cursor.getHeader().getDifficultyTarget()) + " vs " + Long.toHexString(nextBlock.getDifficultyTarget()));
/** * Calculate the difficulty target expected for the next block after a normal * recalculation interval. Does not handle special cases such as testnet blocks * being setting the target to maximum for blocks after a long interval. * * @param previousHeight height of the block immediately before the retarget. * @param prev the block immediately before the retarget block. * @param nextBlock the block the retarget happens at. * @param blockIntervalAgo The last retarget block. * @return New difficulty target as compact bytes. */ protected long calculateNewDifficultyTargetInner(int previousHeight, final Block prev, final Block nextBlock, final Block blockIntervalAgo) { return this.calculateNewDifficultyTargetInner(previousHeight, prev.getTimeSeconds(), prev.getDifficultyTarget(), blockIntervalAgo.getTimeSeconds(), nextBlock.getDifficultyTarget()); }
if (!cursorTarget.equals(newTarget)) throw new VerificationException("Testnet block transition that is not allowed: " + Long.toHexString(cursor.getHeader().getDifficultyTarget()) + " vs " + Long.toHexString(nextBlock.getDifficultyTarget()));
/** * Calculate the difficulty target expected for the next block after a normal * recalculation interval. Does not handle special cases such as testnet blocks * being setting the target to maximum for blocks after a long interval. * * @param previousHeight height of the block immediately before the retarget. * @param prev the block immediately before the retarget block. * @param nextBlock the block the retarget happens at. * @param blockIntervalAgo The last retarget block. * @return New difficulty target as compact bytes. */ protected long calculateNewDifficultyTargetInner(int previousHeight, final Block prev, final Block nextBlock, final Block blockIntervalAgo) { return this.calculateNewDifficultyTargetInner(previousHeight, prev.getTimeSeconds(), prev.getDifficultyTarget(), blockIntervalAgo.getTimeSeconds(), nextBlock.getDifficultyTarget()); }
@Override public void checkDifficultyTransitions(final StoredBlock storedPrev, final Block nextBlock, final BlockStore blockStore) throws VerificationException, BlockStoreException { if (!isDifficultyTransitionPoint(storedPrev.getHeight()) && nextBlock.getTime().after(testnetDiffDate)) { Block prev = storedPrev.getHeader(); // After 15th February 2012 the rules on the testnet change to avoid people running up the difficulty // and then leaving, making it too hard to mine a block. On non-difficulty transition points, easy // blocks are allowed if there has been a span of 20 minutes without one. final long timeDelta = nextBlock.getTimeSeconds() - prev.getTimeSeconds(); // There is an integer underflow bug in bitcoin-qt that means mindiff blocks are accepted when time // goes backwards. if (timeDelta >= 0 && timeDelta <= NetworkParameters.TARGET_SPACING * 2) { // Walk backwards until we find a block that doesn't have the easiest proof of work, then check // that difficulty is equal to that one. StoredBlock cursor = storedPrev; while (!cursor.getHeader().equals(getGenesisBlock()) && cursor.getHeight() % getInterval() != 0 && cursor.getHeader().getDifficultyTargetAsInteger().equals(getMaxTarget())) cursor = cursor.getPrev(blockStore); BigInteger cursorTarget = cursor.getHeader().getDifficultyTargetAsInteger(); BigInteger newTarget = nextBlock.getDifficultyTargetAsInteger(); if (!cursorTarget.equals(newTarget)) throw new VerificationException("Testnet block transition that is not allowed: " + Long.toHexString(cursor.getHeader().getDifficultyTarget()) + " vs " + Long.toHexString(nextBlock.getDifficultyTarget())); } } else { super.checkDifficultyTransitions(storedPrev, nextBlock, blockStore); } }
@Override public void checkDifficultyTransitions(StoredBlock storedPrev, Block nextBlock, BlockStore blockStore) throws VerificationException, BlockStoreException { try { final long newTargetCompact = calculateNewDifficultyTarget(storedPrev, nextBlock, blockStore); final long receivedTargetCompact = nextBlock.getDifficultyTarget(); if (newTargetCompact != receivedTargetCompact) throw new VerificationException("Network provided difficulty bits do not match what was calculated: " + newTargetCompact + " vs " + receivedTargetCompact); } catch (CheckpointEncounteredException ex) { // Just have to take it on trust then } }
@Override public void checkDifficultyTransitions(final StoredBlock storedPrev, final Block nextBlock, final BlockStore blockStore) throws VerificationException, BlockStoreException { if (!isDifficultyTransitionPoint(storedPrev.getHeight()) && nextBlock.getTime().after(testnetDiffDate)) { Block prev = storedPrev.getHeader(); // After 15th February 2012 the rules on the testnet change to avoid people running up the difficulty // and then leaving, making it too hard to mine a block. On non-difficulty transition points, easy // blocks are allowed if there has been a span of 20 minutes without one. final long timeDelta = nextBlock.getTimeSeconds() - prev.getTimeSeconds(); // There is an integer underflow bug in bitcoin-qt that means mindiff blocks are accepted when time // goes backwards. if (timeDelta >= 0 && timeDelta <= NetworkParameters.TARGET_SPACING * 2) { // Walk backwards until we find a block that doesn't have the easiest proof of work, then check // that difficulty is equal to that one. StoredBlock cursor = storedPrev; while (!cursor.getHeader().equals(getGenesisBlock()) && cursor.getHeight() % getInterval() != 0 && cursor.getHeader().getDifficultyTargetAsInteger().equals(getMaxTarget())) cursor = cursor.getPrev(blockStore); BigInteger cursorTarget = cursor.getHeader().getDifficultyTargetAsInteger(); BigInteger newTarget = nextBlock.getDifficultyTargetAsInteger(); if (!cursorTarget.equals(newTarget)) throw new VerificationException("Testnet block transition that is not allowed: " + Long.toHexString(cursor.getHeader().getDifficultyTarget()) + " vs " + Long.toHexString(nextBlock.getDifficultyTarget())); } } else { super.checkDifficultyTransitions(storedPrev, nextBlock, blockStore); } }
@Override public void checkDifficultyTransitions(StoredBlock storedPrev, Block nextBlock, BlockStore blockStore) throws VerificationException, BlockStoreException { try { final long newTargetCompact = calculateNewDifficultyTarget(storedPrev, nextBlock, blockStore); final long receivedTargetCompact = nextBlock.getDifficultyTarget(); if (newTargetCompact != receivedTargetCompact) throw new VerificationException("Network provided difficulty bits do not match what was calculated: " + newTargetCompact + " vs " + receivedTargetCompact); } catch (CheckpointEncounteredException ex) { // Just have to take it on trust then } }
throw new VerificationException("Testnet block transition that is not allowed: " + Long.toHexString(Utils.encodeCompactBits(maxTarget)) + " (required min difficulty) vs " + Long.toHexString(nextBlock.getDifficultyTarget())); return;
if (nextBlock.getDifficultyTarget() != prev.getDifficultyTarget()) throw new VerificationException("Unexpected change in difficulty at height " + storedPrev.getHeight() + ": " + Long.toHexString(nextBlock.getDifficultyTarget()) + " vs " + Long.toHexString(prev.getDifficultyTarget())); return; timespan = targetTimespan * 4; BigInteger newTarget = Utils.decodeCompactBits(prev.getDifficultyTarget()); newTarget = newTarget.multiply(BigInteger.valueOf(timespan)); newTarget = newTarget.divide(BigInteger.valueOf(targetTimespan)); int accuracyBytes = (int) (nextBlock.getDifficultyTarget() >>> 24) - 3; long receivedTargetCompact = nextBlock.getDifficultyTarget();
if (nextBlock.getDifficultyTarget() != prev.getDifficultyTarget()) throw new VerificationException("Unexpected change in difficulty at height " + storedPrev.getHeight() + ": " + Long.toHexString(nextBlock.getDifficultyTarget()) + " vs " + Long.toHexString(prev.getDifficultyTarget())); return; timespan = targetTimespan * 4; BigInteger newTarget = Utils.decodeCompactBits(prev.getDifficultyTarget()); newTarget = newTarget.multiply(BigInteger.valueOf(timespan)); newTarget = newTarget.divide(BigInteger.valueOf(targetTimespan)); int accuracyBytes = (int) (nextBlock.getDifficultyTarget() >>> 24) - 3; long receivedTargetCompact = nextBlock.getDifficultyTarget();
if (nextBlock.getDifficultyTarget() != prev.getDifficultyTarget()) throw new VerificationException("Unexpected change in difficulty at height " + storedPrev.getHeight() + ": " + Long.toHexString(nextBlock.getDifficultyTarget()) + " vs " + Long.toHexString(prev.getDifficultyTarget())); return; timespan = targetTimespan * 4; BigInteger newTarget = Utils.decodeCompactBits(prev.getDifficultyTarget()); newTarget = newTarget.multiply(BigInteger.valueOf(timespan)); newTarget = newTarget.divide(BigInteger.valueOf(targetTimespan)); int accuracyBytes = (int) (nextBlock.getDifficultyTarget() >>> 24) - 3; long receivedTargetCompact = nextBlock.getDifficultyTarget();
if (nextBlock.getDifficultyTarget() != prev.getDifficultyTarget()) throw new VerificationException("Unexpected change in difficulty at height " + storedPrev.getHeight() + ": " + Long.toHexString(nextBlock.getDifficultyTarget()) + " vs " + Long.toHexString(prev.getDifficultyTarget())); return; timespan = targetTimespan * 4; BigInteger newTarget = Utils.decodeCompactBits(prev.getDifficultyTarget()); newTarget = newTarget.multiply(BigInteger.valueOf(timespan)); newTarget = newTarget.divide(BigInteger.valueOf(targetTimespan)); int accuracyBytes = (int) (nextBlock.getDifficultyTarget() >>> 24) - 3; long receivedTargetCompact = nextBlock.getDifficultyTarget();
if (nextBlock.getDifficultyTarget() != prev.getDifficultyTarget()) throw new VerificationException("Unexpected change in difficulty at height " + storedPrev.getHeight() + ": " + Long.toHexString(nextBlock.getDifficultyTarget()) + " vs " + Long.toHexString(prev.getDifficultyTarget())); return; timespan = targetTimespan * 4; BigInteger newTarget = Utils.decodeCompactBits(prev.getDifficultyTarget()); newTarget = newTarget.multiply(BigInteger.valueOf(timespan)); newTarget = newTarget.divide(BigInteger.valueOf(targetTimespan)); int accuracyBytes = (int) (nextBlock.getDifficultyTarget() >>> 24) - 3; long receivedTargetCompact = nextBlock.getDifficultyTarget();
&& cursor.getHeader().getDifficultyTarget() == Utils.encodeCompactBits(this.getMaxTarget())) { StoredBlock prevCursor = cursor.getPrev(blockStore); if (prevCursor == null) { return cursor.getHeader().getDifficultyTarget(); return prev.getDifficultyTarget(); prev.getDifficultyTarget(), blockIntervalAgo.getTimeSeconds(), nextBlock.getDifficultyTarget());
&& cursor.getHeader().getDifficultyTarget() == Utils.encodeCompactBits(this.getMaxTarget())) { StoredBlock prevCursor = cursor.getPrev(blockStore); if (prevCursor == null) { return cursor.getHeader().getDifficultyTarget(); return prev.getDifficultyTarget(); prev.getDifficultyTarget(), blockIntervalAgo.getTimeSeconds(), nextBlock.getDifficultyTarget());