3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-07 06:44:16 +00:00

Clean up network parameters

Correct block subsidy calculations for Dogecoin and Litecoin and add test
coverage for both networks.
Change Litecoin block version check parameters to match Litecoin Core.
Add checkpoints for Dogecoin main and test, and Litecoin main network.
This commit is contained in:
Ross Nicoll 2015-12-28 21:17:47 +00:00
parent 9261271b3d
commit 24f1ffe459
12 changed files with 166 additions and 16 deletions

View File

@ -28,6 +28,7 @@ import java.math.BigInteger;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.util.BitSet; import java.util.BitSet;
import java.util.List; import java.util.List;
import static org.bitcoinj.core.Coin.FIFTY_COINS;
import org.libdohj.core.ScryptHash; import org.libdohj.core.ScryptHash;
import static org.libdohj.core.Utils.scryptDigest; import static org.libdohj.core.Utils.scryptDigest;
@ -149,6 +150,12 @@ public class AltcoinBlock extends org.bitcoinj.core.Block {
return getScryptHash().toString(); return getScryptHash().toString();
} }
@Override
public Coin getBlockInflation(int height) {
final AltcoinNetworkParameters altParams = (AltcoinNetworkParameters) params;
return altParams.getBlockSubsidy(height);
}
/** /**
* Get the chain ID (upper 16 bits) from an AuxPoW version number. * Get the chain ID (upper 16 bits) from an AuxPoW version number.
*/ */

View File

@ -16,6 +16,7 @@
package org.libdohj.core; package org.libdohj.core;
import org.bitcoinj.core.Block; import org.bitcoinj.core.Block;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.Sha256Hash; import org.bitcoinj.core.Sha256Hash;
/** /**
@ -31,4 +32,10 @@ public interface AltcoinNetworkParameters {
Sha256Hash getBlockDifficultyHash(Block block); Sha256Hash getBlockDifficultyHash(Block block);
public boolean isTestNet(); public boolean isTestNet();
/**
* Get the subsidy (i.e. maximum number of coins that can be generated
* by the coinbase transaction) for a block at the given height.
*/
public Coin getBlockSubsidy(final int height);
} }

View File

@ -94,6 +94,9 @@ public abstract class AbstractDogecoinParams extends NetworkParameters implement
public static final int DOGECOIN_PROTOCOL_VERSION_AUXPOW = 70003; public static final int DOGECOIN_PROTOCOL_VERSION_AUXPOW = 70003;
public static final int DOGECOIN_PROTOCOL_VERSION_CURRENT = 70004; public static final int DOGECOIN_PROTOCOL_VERSION_CURRENT = 70004;
private static final Coin BASE_SUBSIDY = COIN.multiply(500000);
private static final Coin STABLE_SUBSIDY = COIN.multiply(10000);
public AbstractDogecoinParams(final int setDiffChangeTarget) { public AbstractDogecoinParams(final int setDiffChangeTarget) {
super(); super();
genesisBlock = createGenesis(this); genesisBlock = createGenesis(this);
@ -129,6 +132,21 @@ public abstract class AbstractDogecoinParams extends NetworkParameters implement
return genesisBlock; return genesisBlock;
} }
@Override
public Coin getBlockSubsidy(final int height) {
if (height < DIGISHIELD_BLOCK_HEIGHT) {
// Up until the Digishield hard fork, subsidy was based on the
// previous block hash. Rather than actually recalculating that, we
// simply use the maximum possible here, and let checkpoints enforce
// that new blocks with different values can't be mined
return BASE_SUBSIDY.shiftRight(height / getSubsidyDecreaseBlockCount()).multiply(2);
} else if (height < 600000) {
return BASE_SUBSIDY.shiftRight(height / getSubsidyDecreaseBlockCount());
} else {
return STABLE_SUBSIDY;
}
}
/** How many blocks pass between difficulty adjustment periods. After new diff algo. */ /** How many blocks pass between difficulty adjustment periods. After new diff algo. */
public int getNewInterval() { public int getNewInterval() {
return newInterval; return newInterval;

View File

@ -83,10 +83,13 @@ public abstract class AbstractLitecoinParams extends NetworkParameters implement
/** The string returned by getId() for the testnet. */ /** The string returned by getId() for the testnet. */
public static final String ID_LITE_TESTNET = "org.litecoin.test"; public static final String ID_LITE_TESTNET = "org.litecoin.test";
protected Logger log = LoggerFactory.getLogger(AbstractLitecoinParams.class);
public static final int LITECOIN_PROTOCOL_VERSION_MINIMUM = 70002; public static final int LITECOIN_PROTOCOL_VERSION_MINIMUM = 70002;
public static final int LITECOIN_PROTOCOL_VERSION_CURRENT = 70003; public static final int LITECOIN_PROTOCOL_VERSION_CURRENT = 70003;
private static final Coin BASE_SUBSIDY = COIN.multiply(50);
protected Logger log = LoggerFactory.getLogger(AbstractLitecoinParams.class);
public AbstractLitecoinParams() { public AbstractLitecoinParams() {
super(); super();
interval = LITE_INTERVAL; interval = LITE_INTERVAL;
@ -98,6 +101,11 @@ public abstract class AbstractLitecoinParams extends NetworkParameters implement
bip32HeaderPriv = 0x0488E1F4; //The 4 byte header that serializes in base58 to "xprv" (?) bip32HeaderPriv = 0x0488E1F4; //The 4 byte header that serializes in base58 to "xprv" (?)
} }
@Override
public Coin getBlockSubsidy(final int height) {
return BASE_SUBSIDY.shiftRight(height / getSubsidyDecreaseBlockCount());
}
/** /**
* Get the hash to use for a block. * Get the hash to use for a block.
*/ */

View File

@ -29,6 +29,7 @@ import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.core.Transaction; import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.TransactionInput; import org.bitcoinj.core.TransactionInput;
import org.bitcoinj.core.TransactionOutput; import org.bitcoinj.core.TransactionOutput;
import org.bitcoinj.params.MainNetParams;
import org.bitcoinj.script.Script; import org.bitcoinj.script.Script;
import org.bitcoinj.script.ScriptOpCodes; import org.bitcoinj.script.ScriptOpCodes;
@ -37,9 +38,9 @@ import org.bitcoinj.script.ScriptOpCodes;
* goods and services. * goods and services.
*/ */
public class LitecoinMainNetParams extends AbstractLitecoinParams { public class LitecoinMainNetParams extends AbstractLitecoinParams {
public static final int MAINNET_MAJORITY_WINDOW = 1000; public static final int MAINNET_MAJORITY_WINDOW = MainNetParams.MAINNET_MAJORITY_WINDOW;
public static final int MAINNET_MAJORITY_REJECT_BLOCK_OUTDATED = 950; public static final int MAINNET_MAJORITY_REJECT_BLOCK_OUTDATED = MainNetParams.MAINNET_MAJORITY_REJECT_BLOCK_OUTDATED;
public static final int MAINNET_MAJORITY_ENFORCE_BLOCK_UPGRADE = 750; public static final int MAINNET_MAJORITY_ENFORCE_BLOCK_UPGRADE = MainNetParams.MAINNET_MAJORITY_ENFORCE_BLOCK_UPGRADE;
public LitecoinMainNetParams() { public LitecoinMainNetParams() {
super(); super();
@ -55,8 +56,8 @@ public class LitecoinMainNetParams extends AbstractLitecoinParams {
dumpedPrivateKeyHeader = 176; dumpedPrivateKeyHeader = 176;
this.genesisBlock = createGenesis(this); this.genesisBlock = createGenesis(this);
spendableCoinbaseDepth = 30; spendableCoinbaseDepth = 100;
subsidyDecreaseBlockCount = 100000; subsidyDecreaseBlockCount = 840000;
String genesisHash = genesisBlock.getHashAsString(); String genesisHash = genesisBlock.getHashAsString();
checkState(genesisHash.equals("12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2")); checkState(genesisHash.equals("12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2"));
@ -73,10 +74,8 @@ public class LitecoinMainNetParams extends AbstractLitecoinParams {
"dnsseed.koin-project.com", "dnsseed.koin-project.com",
"dnsseed.weminemnc.com" "dnsseed.weminemnc.com"
}; };
// Note this is the same as the BIP32 testnet, as BIP44 makes HD wallets bip32HeaderPub = 0x0488B21E;
// chain agnostic. Litecoin mainnet has its own headers for legacy reasons. bip32HeaderPriv = 0x0488ADE4;
bip32HeaderPub = 0x043587CF;
bip32HeaderPriv = 0x04358394;
} }
private static AltcoinBlock createGenesis(NetworkParameters params) { private static AltcoinBlock createGenesis(NetworkParameters params) {

View File

@ -38,9 +38,9 @@ import org.bitcoinj.script.ScriptOpCodes;
* Litecoin versions. * Litecoin versions.
*/ */
public class LitecoinTestNet3Params extends AbstractLitecoinParams { public class LitecoinTestNet3Params extends AbstractLitecoinParams {
public static final int TESTNET_MAJORITY_WINDOW = 1000; public static final int TESTNET_MAJORITY_WINDOW = 100;
public static final int TESTNET_MAJORITY_REJECT_BLOCK_OUTDATED = 750; public static final int TESTNET_MAJORITY_REJECT_BLOCK_OUTDATED = 75;
public static final int TESTNET_MAJORITY_ENFORCE_BLOCK_UPGRADE = 501; public static final int TESTNET_MAJORITY_ENFORCE_BLOCK_UPGRADE = 51;
public LitecoinTestNet3Params() { public LitecoinTestNet3Params() {
super(); super();
@ -72,8 +72,7 @@ public class LitecoinTestNet3Params extends AbstractLitecoinParams {
"testnet-seed.ltc.xurious.com", "testnet-seed.ltc.xurious.com",
"dnsseed.wemine-testnet.com" "dnsseed.wemine-testnet.com"
}; };
// Note this is the same as the BIP32 testnet, as BIP44 makes HD wallets
// chain agnostic. Litecoin mainnet has its own headers for legacy reasons.
bip32HeaderPub = 0x043587CF; bip32HeaderPub = 0x043587CF;
bip32HeaderPriv = 0x04358394; bip32HeaderPriv = 0x04358394;
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -17,6 +17,7 @@ package org.libdohj.params;
import java.io.IOException; import java.io.IOException;
import org.bitcoinj.core.AltcoinBlock; import org.bitcoinj.core.AltcoinBlock;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.Context; import org.bitcoinj.core.Context;
import org.bitcoinj.core.Sha256Hash; import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.Util; import org.bitcoinj.core.Util;
@ -27,7 +28,7 @@ import org.libdohj.core.AltcoinSerializer;
/** /**
* *
* @author jrn * @author Ross Nicoll
*/ */
public class AbstractDogecoinParamsTest { public class AbstractDogecoinParamsTest {
private static final AbstractDogecoinParams params = DogecoinMainNetParams.get(); private static final AbstractDogecoinParams params = DogecoinMainNetParams.get();
@ -136,6 +137,29 @@ public class AbstractDogecoinParamsTest {
assertEquals(block720.getDifficultyTarget(), params.calculateNewDifficultyTargetInner(719, block719, block720, block479)); assertEquals(block720.getDifficultyTarget(), params.calculateNewDifficultyTargetInner(719, block719, block720, block479));
} }
/**
* Confirm subsidy rules follow Dogecoin pattern.
*/
@Test
public void shouldCalculateSubsidy() {
assertEquals(Coin.COIN.multiply(1000000), params.getBlockSubsidy(0));
assertEquals(Coin.COIN.multiply(1000000), params.getBlockSubsidy(99999));
assertEquals(Coin.COIN.multiply(500000), params.getBlockSubsidy(100000));
assertEquals(Coin.COIN.multiply(500000), params.getBlockSubsidy(144999));
assertEquals(Coin.COIN.multiply(250000), params.getBlockSubsidy(145000));
assertEquals(Coin.COIN.multiply(250000), params.getBlockSubsidy(199999));
assertEquals(Coin.COIN.multiply(125000), params.getBlockSubsidy(200000));
assertEquals(Coin.COIN.multiply(125000), params.getBlockSubsidy(299999));
assertEquals(Coin.COIN.multiply(62500), params.getBlockSubsidy(300000));
assertEquals(Coin.COIN.multiply(62500), params.getBlockSubsidy(399999));
assertEquals(Coin.COIN.multiply(31250), params.getBlockSubsidy(400000));
assertEquals(Coin.COIN.multiply(31250), params.getBlockSubsidy(499999));
assertEquals(Coin.COIN.multiply(15625), params.getBlockSubsidy(500000));
assertEquals(Coin.COIN.multiply(15625), params.getBlockSubsidy(599999));
assertEquals(Coin.COIN.multiply(10000), params.getBlockSubsidy(600000));
assertEquals(Coin.COIN.multiply(10000), params.getBlockSubsidy(699999));
}
@Test @Test
public void targetSpacingShouldBe60() { public void targetSpacingShouldBe60() {
// The getTargetSpacing() method only really exists for future expansion, // The getTargetSpacing() method only really exists for future expansion,

View File

@ -0,0 +1,46 @@
/*
* Copyright 2015 J. Ross Nicoll
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.libdohj.params;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.Context;
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
/**
*
* @author Ross Nicoll
*/
public class AbstractLitecoinParamsTest {
private static final AbstractLitecoinParams params = LitecoinMainNetParams.get();
@Before
public void setUp() throws Exception {
Context context = new Context(params);
}
/**
* Confirm subsidy rules follow Litecoin pattern.
*/
@Test
public void shouldCalculateSubsidy() {
assertEquals(Coin.COIN.multiply(50), params.getBlockSubsidy(0));
assertEquals(Coin.COIN.multiply(50), params.getBlockSubsidy(839999));
assertEquals(Coin.COIN.multiply(25), params.getBlockSubsidy(840000));
assertEquals(Coin.COIN.multiply(25), params.getBlockSubsidy(1679999));
}
}

View File

@ -0,0 +1,42 @@
/*
* Copyright 2015 J. Ross Nicoll
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.libdohj.params;
import org.bitcoinj.core.Context;
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
/**
*
* @author Ross Nicoll
*/
public class LitecoinTestNet3ParamsTest {
private static final LitecoinTestNet3Params params = LitecoinTestNet3Params.get();
@Before
public void setUp() throws Exception {
Context context = new Context(params);
}
// Confirm subsidy rules follow Dogecoin pattern
@Test
public void shouldHaveCorrectValues() {
assertEquals(100, params.getMajorityWindow());
assertEquals(51, params.getMajorityEnforceBlockUpgrade());
assertEquals(75, params.getMajorityRejectBlockOutdated());
}
}