diff --git a/src/main/java/org/bitcoinj/core/AltcoinBlock.java b/src/main/java/org/bitcoinj/core/AltcoinBlock.java index 496576d3..62e320cf 100644 --- a/src/main/java/org/bitcoinj/core/AltcoinBlock.java +++ b/src/main/java/org/bitcoinj/core/AltcoinBlock.java @@ -28,6 +28,7 @@ import java.math.BigInteger; import java.security.GeneralSecurityException; import java.util.BitSet; import java.util.List; +import static org.bitcoinj.core.Coin.FIFTY_COINS; import org.libdohj.core.ScryptHash; import static org.libdohj.core.Utils.scryptDigest; @@ -149,6 +150,12 @@ public class AltcoinBlock extends org.bitcoinj.core.Block { 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. */ diff --git a/src/main/java/org/libdohj/core/AltcoinNetworkParameters.java b/src/main/java/org/libdohj/core/AltcoinNetworkParameters.java index 384cb0f1..980df013 100644 --- a/src/main/java/org/libdohj/core/AltcoinNetworkParameters.java +++ b/src/main/java/org/libdohj/core/AltcoinNetworkParameters.java @@ -16,6 +16,7 @@ package org.libdohj.core; import org.bitcoinj.core.Block; +import org.bitcoinj.core.Coin; import org.bitcoinj.core.Sha256Hash; /** @@ -31,4 +32,10 @@ public interface AltcoinNetworkParameters { Sha256Hash getBlockDifficultyHash(Block block); 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); } diff --git a/src/main/java/org/libdohj/params/AbstractDogecoinParams.java b/src/main/java/org/libdohj/params/AbstractDogecoinParams.java index 4975f620..6127ba6d 100644 --- a/src/main/java/org/libdohj/params/AbstractDogecoinParams.java +++ b/src/main/java/org/libdohj/params/AbstractDogecoinParams.java @@ -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_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) { super(); genesisBlock = createGenesis(this); @@ -129,6 +132,21 @@ public abstract class AbstractDogecoinParams extends NetworkParameters implement 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. */ public int getNewInterval() { return newInterval; diff --git a/src/main/java/org/libdohj/params/AbstractLitecoinParams.java b/src/main/java/org/libdohj/params/AbstractLitecoinParams.java index 01a3e5c2..bb41f23e 100644 --- a/src/main/java/org/libdohj/params/AbstractLitecoinParams.java +++ b/src/main/java/org/libdohj/params/AbstractLitecoinParams.java @@ -83,10 +83,13 @@ public abstract class AbstractLitecoinParams extends NetworkParameters implement /** The string returned by getId() for the testnet. */ 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_CURRENT = 70003; + private static final Coin BASE_SUBSIDY = COIN.multiply(50); + + protected Logger log = LoggerFactory.getLogger(AbstractLitecoinParams.class); + public AbstractLitecoinParams() { super(); 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" (?) } + @Override + public Coin getBlockSubsidy(final int height) { + return BASE_SUBSIDY.shiftRight(height / getSubsidyDecreaseBlockCount()); + } + /** * Get the hash to use for a block. */ diff --git a/src/main/java/org/libdohj/params/LitecoinMainNetParams.java b/src/main/java/org/libdohj/params/LitecoinMainNetParams.java index 542b8a41..35b05228 100644 --- a/src/main/java/org/libdohj/params/LitecoinMainNetParams.java +++ b/src/main/java/org/libdohj/params/LitecoinMainNetParams.java @@ -29,6 +29,7 @@ import org.bitcoinj.core.NetworkParameters; import org.bitcoinj.core.Transaction; import org.bitcoinj.core.TransactionInput; import org.bitcoinj.core.TransactionOutput; +import org.bitcoinj.params.MainNetParams; import org.bitcoinj.script.Script; import org.bitcoinj.script.ScriptOpCodes; @@ -37,9 +38,9 @@ import org.bitcoinj.script.ScriptOpCodes; * goods and services. */ public class LitecoinMainNetParams extends AbstractLitecoinParams { - public static final int MAINNET_MAJORITY_WINDOW = 1000; - public static final int MAINNET_MAJORITY_REJECT_BLOCK_OUTDATED = 950; - public static final int MAINNET_MAJORITY_ENFORCE_BLOCK_UPGRADE = 750; + public static final int MAINNET_MAJORITY_WINDOW = MainNetParams.MAINNET_MAJORITY_WINDOW; + public static final int MAINNET_MAJORITY_REJECT_BLOCK_OUTDATED = MainNetParams.MAINNET_MAJORITY_REJECT_BLOCK_OUTDATED; + public static final int MAINNET_MAJORITY_ENFORCE_BLOCK_UPGRADE = MainNetParams.MAINNET_MAJORITY_ENFORCE_BLOCK_UPGRADE; public LitecoinMainNetParams() { super(); @@ -55,8 +56,8 @@ public class LitecoinMainNetParams extends AbstractLitecoinParams { dumpedPrivateKeyHeader = 176; this.genesisBlock = createGenesis(this); - spendableCoinbaseDepth = 30; - subsidyDecreaseBlockCount = 100000; + spendableCoinbaseDepth = 100; + subsidyDecreaseBlockCount = 840000; String genesisHash = genesisBlock.getHashAsString(); checkState(genesisHash.equals("12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2")); @@ -73,10 +74,8 @@ public class LitecoinMainNetParams extends AbstractLitecoinParams { "dnsseed.koin-project.com", "dnsseed.weminemnc.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; - bip32HeaderPriv = 0x04358394; + bip32HeaderPub = 0x0488B21E; + bip32HeaderPriv = 0x0488ADE4; } private static AltcoinBlock createGenesis(NetworkParameters params) { diff --git a/src/main/java/org/libdohj/params/LitecoinTestNet3Params.java b/src/main/java/org/libdohj/params/LitecoinTestNet3Params.java index 3de4fa9d..e9b8dc7e 100644 --- a/src/main/java/org/libdohj/params/LitecoinTestNet3Params.java +++ b/src/main/java/org/libdohj/params/LitecoinTestNet3Params.java @@ -38,9 +38,9 @@ import org.bitcoinj.script.ScriptOpCodes; * Litecoin versions. */ public class LitecoinTestNet3Params extends AbstractLitecoinParams { - public static final int TESTNET_MAJORITY_WINDOW = 1000; - public static final int TESTNET_MAJORITY_REJECT_BLOCK_OUTDATED = 750; - public static final int TESTNET_MAJORITY_ENFORCE_BLOCK_UPGRADE = 501; + public static final int TESTNET_MAJORITY_WINDOW = 100; + public static final int TESTNET_MAJORITY_REJECT_BLOCK_OUTDATED = 75; + public static final int TESTNET_MAJORITY_ENFORCE_BLOCK_UPGRADE = 51; public LitecoinTestNet3Params() { super(); @@ -72,8 +72,7 @@ public class LitecoinTestNet3Params extends AbstractLitecoinParams { "testnet-seed.ltc.xurious.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; bip32HeaderPriv = 0x04358394; } diff --git a/src/main/resources/org.dogecoin.production.checkpoints b/src/main/resources/org.dogecoin.production.checkpoints new file mode 100644 index 00000000..19a3fee9 Binary files /dev/null and b/src/main/resources/org.dogecoin.production.checkpoints differ diff --git a/src/main/resources/org.dogecoin.test.checkpoints b/src/main/resources/org.dogecoin.test.checkpoints new file mode 100644 index 00000000..45fbc6d2 Binary files /dev/null and b/src/main/resources/org.dogecoin.test.checkpoints differ diff --git a/src/main/resources/org.litecoin.production.checkpoints b/src/main/resources/org.litecoin.production.checkpoints new file mode 100644 index 00000000..267ab42c Binary files /dev/null and b/src/main/resources/org.litecoin.production.checkpoints differ diff --git a/src/test/java/org/libdohj/params/AbstractDogecoinParamsTest.java b/src/test/java/org/libdohj/params/AbstractDogecoinParamsTest.java index eb14143b..444e259c 100644 --- a/src/test/java/org/libdohj/params/AbstractDogecoinParamsTest.java +++ b/src/test/java/org/libdohj/params/AbstractDogecoinParamsTest.java @@ -17,6 +17,7 @@ package org.libdohj.params; import java.io.IOException; import org.bitcoinj.core.AltcoinBlock; +import org.bitcoinj.core.Coin; import org.bitcoinj.core.Context; import org.bitcoinj.core.Sha256Hash; import org.bitcoinj.core.Util; @@ -27,7 +28,7 @@ import org.libdohj.core.AltcoinSerializer; /** * - * @author jrn + * @author Ross Nicoll */ public class AbstractDogecoinParamsTest { private static final AbstractDogecoinParams params = DogecoinMainNetParams.get(); @@ -136,6 +137,29 @@ public class AbstractDogecoinParamsTest { 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 public void targetSpacingShouldBe60() { // The getTargetSpacing() method only really exists for future expansion, diff --git a/src/test/java/org/libdohj/params/AbstractLitecoinParamsTest.java b/src/test/java/org/libdohj/params/AbstractLitecoinParamsTest.java new file mode 100644 index 00000000..3f71928b --- /dev/null +++ b/src/test/java/org/libdohj/params/AbstractLitecoinParamsTest.java @@ -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)); + } +} diff --git a/src/test/java/org/libdohj/params/LitecoinTestNet3ParamsTest.java b/src/test/java/org/libdohj/params/LitecoinTestNet3ParamsTest.java new file mode 100644 index 00000000..fefc877f --- /dev/null +++ b/src/test/java/org/libdohj/params/LitecoinTestNet3ParamsTest.java @@ -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()); + } +}