diff --git a/core/src/main/java/org/bitcoinj/params/AbstractBitcoinNetParams.java b/core/src/main/java/org/bitcoinj/params/AbstractBitcoinNetParams.java index e73e8e63e16..cca21ba9100 100644 --- a/core/src/main/java/org/bitcoinj/params/AbstractBitcoinNetParams.java +++ b/core/src/main/java/org/bitcoinj/params/AbstractBitcoinNetParams.java @@ -45,6 +45,7 @@ public abstract class AbstractBitcoinNetParams extends NetworkParameters { int uahfHeight = 478559; /** Activation time at which the cash HF kicks in. */ protected long cashHardForkActivationTime; + protected int daaHeight; public AbstractBitcoinNetParams() { super(); @@ -64,7 +65,7 @@ public void checkDifficultyTransitions(final StoredBlock storedPrev, final Block final BlockStore blockStore, AbstractBlockChain blockChain) throws VerificationException, BlockStoreException { Block prev = storedPrev.getHeader(); - if (blockChain.getMedianTimestampOfRecentBlocks(storedPrev, blockStore) >= cashHardForkActivationTime) { + if (storedPrev.getHeight() +1 >= daaHeight) { checkNextCashWorkRequired(storedPrev, nextBlock, blockStore); return; } @@ -300,7 +301,7 @@ StoredBlock GetSuitableBlock(StoredBlock pindex, BlockStore blockStore) throws B * block. Because timestamps are the least trustworthy information we have as * input, this ensures the algorithm is more resistant to malicious inputs. */ - void checkNextCashWorkRequired(StoredBlock pindexPrev, + protected void checkNextCashWorkRequired(StoredBlock pindexPrev, Block pblock, BlockStore blockStore) { // This cannot handle the genesis block and early blocks in general. //assert(pindexPrev); diff --git a/core/src/main/java/org/bitcoinj/params/TestNet2Params.java b/core/src/main/java/org/bitcoinj/params/TestNet2Params.java index e77021ed5aa..d99d3684908 100644 --- a/core/src/main/java/org/bitcoinj/params/TestNet2Params.java +++ b/core/src/main/java/org/bitcoinj/params/TestNet2Params.java @@ -58,6 +58,10 @@ public TestNet2Params() { majorityEnforceBlockUpgrade = TESTNET_MAJORITY_ENFORCE_BLOCK_UPGRADE; majorityRejectBlockOutdated = TESTNET_MAJORITY_REJECT_BLOCK_OUTDATED; majorityWindow = TESTNET_MAJORITY_WINDOW; + + /** Activation time at which the cash HF kicks in. */ + cashHardForkActivationTime = 1510600000; + daaHeight = 1188697; } private static TestNet2Params instance; diff --git a/core/src/main/java/org/bitcoinj/params/TestNet3Params.java b/core/src/main/java/org/bitcoinj/params/TestNet3Params.java index a6d93330f8b..e8a9e43d76b 100644 --- a/core/src/main/java/org/bitcoinj/params/TestNet3Params.java +++ b/core/src/main/java/org/bitcoinj/params/TestNet3Params.java @@ -20,6 +20,7 @@ import java.math.BigInteger; import java.util.Date; +import com.google.common.base.Preconditions; import org.bitcoinj.core.AbstractBlockChain; import org.bitcoinj.core.Block; import org.bitcoinj.core.NetworkParameters; @@ -79,6 +80,7 @@ public TestNet3Params() { /** Activation time at which the cash HF kicks in. */ cashHardForkActivationTime = 1510600000; + daaHeight = 1188697; } private static TestNet3Params instance; @@ -100,7 +102,7 @@ public String getPaymentProtocolId() { @Override public void checkDifficultyTransitions(final StoredBlock storedPrev, final Block nextBlock, final BlockStore blockStore, AbstractBlockChain blockChain) throws VerificationException, BlockStoreException { - if (!isDifficultyTransitionPoint(storedPrev) && nextBlock.getTime().after(testnetDiffDate)) { + if (storedPrev.getHeight() < daaHeight && !isDifficultyTransitionPoint(storedPrev) && 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 @@ -128,4 +130,65 @@ public void checkDifficultyTransitions(final StoredBlock storedPrev, final Block super.checkDifficultyTransitions(storedPrev, nextBlock, blockStore, blockChain); } } + @Override + protected void checkNextCashWorkRequired(StoredBlock storedPrev, + Block nextBlock, BlockStore blockStore) { + // This cannot handle the genesis block and early blocks in general. + //assert(pindexPrev); + + + + // Compute the difficulty based on the full adjustement interval. + int nHeight = storedPrev.getHeight(); + Preconditions.checkState(nHeight >= this.interval); + + // Get the last suitable block of the difficulty interval. + try { + + // Special difficulty rule for testnet: + // If the new block's timestamp is more than 2* 10 minutes then allow + // mining of a min-difficulty block. + + Block prev = storedPrev.getHeader(); + + + final long timeDelta = nextBlock.getTimeSeconds() - prev.getTimeSeconds(); + if (timeDelta >= 0 && timeDelta > NetworkParameters.TARGET_SPACING * 2) { + if (!maxTarget.equals(nextBlock.getDifficultyTargetAsInteger())) + throw new VerificationException("Testnet block transition that is not allowed: " + + Long.toHexString(Utils.encodeCompactBits(maxTarget)) + " (required min difficulty) vs " + + Long.toHexString(nextBlock.getDifficultyTarget())); + return; + } + + StoredBlock pindexLast = GetSuitableBlock(storedPrev, blockStore); + //assert (pindexLast); + + // Get the first suitable block of the difficulty interval. + int nHeightFirst = nHeight - 144; + + StoredBlock pindexFirst = storedPrev; + + for (int i = 144; i > 0; --i) + { + pindexFirst = pindexFirst.getPrev(blockStore); + if(pindexFirst == null) + return; + } + + pindexFirst = GetSuitableBlock(pindexFirst, blockStore); + //assert (pindexFirst); + + // Compute the target based on time and work done during the interval. + BigInteger nextTarget = + ComputeTarget(pindexFirst, pindexLast); + + verifyDifficulty(nextTarget, nextBlock); + } + catch (BlockStoreException x) + { + //this means we don't have enough blocks, yet. let it go until we do. + return; + } + } } diff --git a/core/src/main/java/org/bitcoinj/params/UnitTestParams.java b/core/src/main/java/org/bitcoinj/params/UnitTestParams.java index 1952c59767c..5e80f3c56a5 100644 --- a/core/src/main/java/org/bitcoinj/params/UnitTestParams.java +++ b/core/src/main/java/org/bitcoinj/params/UnitTestParams.java @@ -55,8 +55,9 @@ public UnitTestParams() { majorityRejectBlockOutdated = 4; majorityWindow = 7; - // support for legacy tests - dont test BCH 2017-11-1 hardfork by default + // support for legacy tests - dont test BCH 2017-11-13 hardfork by default cashHardForkActivationTime = (System.currentTimeMillis()/1000)+24*60*60; + daaHeight = 1000000; } private static UnitTestParams instance;