3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-01-30 23:02:15 +00:00

Modified Dogecoin difficulty calculations to use next expected target to determine precision.

This commit is contained in:
Ross Nicoll 2015-10-16 22:44:47 +01:00
parent 95db3b960e
commit 355ea2d50e
4 changed files with 64 additions and 28 deletions

View File

@ -211,7 +211,8 @@ public abstract class AbstractDogecoinParams extends NetworkParameters implement
Block blockIntervalAgo = cursor.getHeader();
long receivedTargetCompact = nextBlock.getDifficultyTarget();
long newTargetCompact = this.getNewDifficultyTarget(previousHeight, prev, blockIntervalAgo);
long newTargetCompact = this.getNewDifficultyTarget(previousHeight, prev,
nextBlock, blockIntervalAgo);
if (newTargetCompact != receivedTargetCompact)
throw new VerificationException("Network provided difficulty bits do not match what was calculated: " +
@ -220,14 +221,17 @@ public abstract class AbstractDogecoinParams extends NetworkParameters implement
/**
*
* @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.
*/
public long getNewDifficultyTarget(int previousHeight, final Block prev,
public long getNewDifficultyTarget(int previousHeight, final Block prev, final Block nextBlock,
final Block blockIntervalAgo) {
return this.getNewDifficultyTarget(previousHeight, prev.getTimeSeconds(),
blockIntervalAgo.getDifficultyTarget(), blockIntervalAgo.getTimeSeconds());
prev.getDifficultyTarget(), blockIntervalAgo.getTimeSeconds(),
nextBlock.getDifficultyTarget());
}
/**
@ -236,10 +240,13 @@ public abstract class AbstractDogecoinParams extends NetworkParameters implement
* @param previousBlockTime Time of the block immediately previous to the one we're calculating difficulty of.
* @param lastDifficultyTarget Compact difficulty target of the last retarget block.
* @param lastRetargetTime Time of the last difficulty retarget.
* @param nextDifficultyTarget The expected difficulty target of the next
* block, used for determining precision of the result.
* @return New difficulty target as compact bytes.
*/
public long getNewDifficultyTarget(int previousHeight, long previousBlockTime,
final long lastDifficultyTarget, final long lastRetargetTime) {
protected long getNewDifficultyTarget(int previousHeight, long previousBlockTime,
final long lastDifficultyTarget, final long lastRetargetTime,
final long nextDifficultyTarget) {
final int height = previousHeight + 1;
final boolean digishieldAlgorithm = height >= this.getDigishieldBlockHeight();
final int retargetTimespan = digishieldAlgorithm
@ -287,7 +294,7 @@ public abstract class AbstractDogecoinParams extends NetworkParameters implement
newTarget = this.getMaxTarget();
}
int accuracyBytes = (int) (lastDifficultyTarget >>> 24) - 3;
int accuracyBytes = (int) (nextDifficultyTarget >>> 24) - 3;
// The calculated difficulty is to a higher precision than received, so reduce here.
BigInteger mask = BigInteger.valueOf(0xFFFFFFL).shiftLeft(accuracyBytes * 8);

View File

@ -18,6 +18,7 @@ package org.libdohj.params;
import java.io.IOException;
import org.bitcoinj.core.AltcoinBlock;
import org.bitcoinj.core.Context;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.Util;
import static org.junit.Assert.assertEquals;
import org.junit.Before;
@ -42,14 +43,20 @@ public class AbstractDogecoinParamsTest {
long previousBlockTime = 1386475638; // Block 239
long lastRetargetDifficulty = 0x1e0ffff0;
long lastRetargetTime = 1386474927; // Block 1
long newDifficulty = params.getNewDifficultyTarget(previousHeight, previousBlockTime, lastRetargetDifficulty, lastRetargetTime);
long nextDifficulty = 0x1e00ffff;
long newDifficulty =
params.getNewDifficultyTarget(previousHeight, previousBlockTime,
lastRetargetDifficulty, lastRetargetTime, nextDifficulty);
assertEquals(0x1e00ffff, newDifficulty);
previousHeight = 9599;
previousBlockTime = 1386954113;
lastRetargetDifficulty = 0x1c1a1206;
lastRetargetTime = 1386942008; // Block 9359
newDifficulty = params.getNewDifficultyTarget(previousHeight, previousBlockTime, lastRetargetDifficulty, lastRetargetTime);
nextDifficulty = 0x1c15ea59;
newDifficulty =
params.getNewDifficultyTarget(previousHeight, previousBlockTime,
lastRetargetDifficulty, lastRetargetTime, nextDifficulty);
assertEquals(0x1c15ea59, newDifficulty);
}
@ -59,51 +66,73 @@ public class AbstractDogecoinParamsTest {
*/
@Test
public void shouldConstrainActualTime() {
int previousHeight = 719;
long previousBlockTime = 1386476362; // Block 719
long lastRetargetDifficulty = 0x1e00ffff;
long lastRetargetTime = 1386475840; // Block 439
long newDifficulty = params.getNewDifficultyTarget(previousHeight, previousBlockTime, lastRetargetDifficulty, lastRetargetTime);
final int previousHeight = 719;
final long previousBlockTime = 1386476362; // Block 719
final long lastRetargetDifficulty = 0x1e00ffff;
final long lastRetargetTime = 1386475840; // Block 479
final long nextDifficulty = 0x1d0ffff0; // Block 720
final long newDifficulty =
params.getNewDifficultyTarget(previousHeight, previousBlockTime,
lastRetargetDifficulty, lastRetargetTime, nextDifficulty);
assertEquals(0x1d0ffff0, newDifficulty);
}
@Test
public void shouldCalculateDigishieldDifficulty() {
int previousHeight = 145000;
long previousBlockTime = 1395094679;
long lastRetargetDifficulty = 0x1b499dfd;
long lastRetargetTime = 1395094427;
long newDifficulty = params.getNewDifficultyTarget(previousHeight, previousBlockTime, lastRetargetDifficulty, lastRetargetTime);
final int previousHeight = 145000;
final long previousBlockTime = 1395094679;
final long lastRetargetDifficulty = 0x1b499dfd;
final long lastRetargetTime = 1395094427;
final long nextDifficulty = 0x1b671062;
final long newDifficulty =
params.getNewDifficultyTarget(previousHeight, previousBlockTime,
lastRetargetDifficulty, lastRetargetTime, nextDifficulty);
assertEquals(0x1b671062, newDifficulty);
}
@Test
public void shouldCalculateDigishieldDifficultyRounding() {
// Test case for correct rounding of modulated time
int previousHeight = 145001;
long previousBlockTime = 1395094727;
long lastRetargetDifficulty = 0x1b671062;
long lastRetargetTime = 1395094679;
long newDifficulty = params.getNewDifficultyTarget(previousHeight, previousBlockTime, lastRetargetDifficulty, lastRetargetTime);
final int previousHeight = 145001;
final long previousBlockTime = 1395094727;
final long lastRetargetDifficulty = 0x1b671062;
final long lastRetargetTime = 1395094679;
final long nextDifficulty = 0x1b6558a4;
final long newDifficulty =
params.getNewDifficultyTarget(previousHeight, previousBlockTime,
lastRetargetDifficulty, lastRetargetTime, nextDifficulty);
assertEquals(0x1b6558a4, newDifficulty);
}
@Test
public void shouldCalculateRetarget() throws IOException {
// Do a more in-depth test for the first retarget
byte[] payload = Util.getBytes(getClass().getResourceAsStream("dogecoin_block239.bin"));
byte[] payload;
AltcoinSerializer serializer = (AltcoinSerializer)params.getDefaultSerializer();
final AltcoinBlock block239 = (AltcoinBlock)serializer.makeBlock(payload);
final AltcoinBlock block239;
final AltcoinBlock block479;
final AltcoinBlock block480;
final AltcoinBlock block719;
final AltcoinBlock block720;
payload = Util.getBytes(getClass().getResourceAsStream("dogecoin_block239.bin"));
block239 = (AltcoinBlock)serializer.makeBlock(payload);
payload = Util.getBytes(getClass().getResourceAsStream("dogecoin_block479.bin"));
block479 = (AltcoinBlock)serializer.makeBlock(payload);
payload = Util.getBytes(getClass().getResourceAsStream("dogecoin_block480.bin"));
block480 = (AltcoinBlock)serializer.makeBlock(payload);
payload = Util.getBytes(getClass().getResourceAsStream("dogecoin_block719.bin"));
block719 = (AltcoinBlock)serializer.makeBlock(payload);
payload = Util.getBytes(getClass().getResourceAsStream("dogecoin_block720.bin"));
block720 = (AltcoinBlock)serializer.makeBlock(payload);
assertEquals(0x1e00ffff, params.getNewDifficultyTarget(479, block239, block479));
assertEquals(0x1d0ffff0, params.getNewDifficultyTarget(719, block479, block719));
assertEquals(Sha256Hash.wrap("f9533416310fc4484cf43405a858b06afc9763ad401d267c1835d77e7d225a4e"), block239.getHash());
assertEquals(Sha256Hash.wrap("ed83c923b532835f6597f70def42910aa9e06880e8a19b68f6b4a787f2b4b69f"), block479.getHash());
assertEquals(Sha256Hash.wrap("a0e6d1cdef02b394d31628c3281f67e8534bec74fda1a4294b58be80c3fdf3f3"), block480.getHash());
assertEquals(Sha256Hash.wrap("82e56e141ccfe019d475382d9a108ef86afeb297d95443dfd7250e57af805696"), block719.getHash());
assertEquals(Sha256Hash.wrap("6b34f1a7de1954beb0ddf100bb2b618ff0183b6ae2b4a9376721ef8e04ab3b39"), block720.getHash());
assertEquals(block480.getDifficultyTarget(), params.getNewDifficultyTarget(479, block479, block480, block239));
assertEquals(block720.getDifficultyTarget(), params.getNewDifficultyTarget(719, block719, block720, block479));
}
}