mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-02-11 17:55:53 +00:00
Add Litecoin support
This commit is contained in:
parent
de30a8e0c9
commit
a3910134f8
@ -248,12 +248,15 @@ public class AltcoinBlock extends org.bitcoinj.core.Block {
|
||||
protected boolean checkProofOfWork(boolean throwException) throws VerificationException {
|
||||
if (params instanceof AltcoinNetworkParameters) {
|
||||
BigInteger target = getDifficultyTargetAsInteger();
|
||||
|
||||
final AuxPoWNetworkParameters altParams = (AuxPoWNetworkParameters)this.params;
|
||||
if (altParams.isAuxPoWBlockVersion(getRawVersion()) && null != auxpow) {
|
||||
return auxpow.checkProofOfWork(this.getHash(), target, throwException);
|
||||
|
||||
if (params instanceof AuxPoWNetworkParameters) {
|
||||
final AuxPoWNetworkParameters auxParams = (AuxPoWNetworkParameters)this.params;
|
||||
if (auxParams.isAuxPoWBlockVersion(getRawVersion()) && null != auxpow) {
|
||||
return auxpow.checkProofOfWork(this.getHash(), target, throwException);
|
||||
}
|
||||
}
|
||||
|
||||
final AltcoinNetworkParameters altParams = (AltcoinNetworkParameters)this.params;
|
||||
BigInteger h = altParams.getBlockDifficultyHash(this).toBigInteger();
|
||||
if (h.compareTo(target) > 0) {
|
||||
// Proof of work check failed!
|
||||
|
252
src/main/java/org/libdohj/params/AbstractLitecoinParams.java
Normal file
252
src/main/java/org/libdohj/params/AbstractLitecoinParams.java
Normal file
@ -0,0 +1,252 @@
|
||||
/*
|
||||
* Copyright 2013 Google Inc.
|
||||
*
|
||||
* 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 java.math.BigInteger;
|
||||
import org.bitcoinj.core.AltcoinBlock;
|
||||
|
||||
import org.bitcoinj.core.Block;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import static org.bitcoinj.core.Coin.COIN;
|
||||
import org.bitcoinj.core.NetworkParameters;
|
||||
import org.bitcoinj.core.Sha256Hash;
|
||||
import org.bitcoinj.core.VerificationException;
|
||||
import org.bitcoinj.store.BlockStore;
|
||||
import org.bitcoinj.store.BlockStoreException;
|
||||
import org.bitcoinj.core.StoredBlock;
|
||||
import org.bitcoinj.core.Utils;
|
||||
import org.bitcoinj.utils.MonetaryFormat;
|
||||
import org.libdohj.core.AltcoinNetworkParameters;
|
||||
import org.libdohj.core.AltcoinSerializer;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Common parameters for Litecoin networks.
|
||||
*/
|
||||
public abstract class AbstractLitecoinParams extends NetworkParameters implements AltcoinNetworkParameters {
|
||||
/** Standard format for the LITE denomination. */
|
||||
public static final MonetaryFormat LITE;
|
||||
/** Standard format for the mLITE denomination. */
|
||||
public static final MonetaryFormat MLITE;
|
||||
/** Standard format for the Liteoshi denomination. */
|
||||
public static final MonetaryFormat LITEOSHI;
|
||||
|
||||
public static final int LITE_TARGET_TIMESPAN = (int) (3.5 * 24 * 60 * 60); // 3.5 days
|
||||
public static final int LITE_TARGET_SPACING = (int) (2.5 * 60); // 2.5 minutes
|
||||
public static final int LITE_INTERVAL = LITE_TARGET_TIMESPAN / LITE_TARGET_SPACING;
|
||||
|
||||
/**
|
||||
* The maximum number of coins to be generated
|
||||
*/
|
||||
public static final long MAX_LITECOINS = 21000000; // TODO: Needs to be 840000000
|
||||
|
||||
/**
|
||||
* The maximum money to be generated
|
||||
*/
|
||||
public static final Coin MAX_LITECOIN_MONEY = COIN.multiply(MAX_LITECOINS);
|
||||
|
||||
/** Currency code for base 1 Litecoin. */
|
||||
public static final String CODE_LITE = "LITE";
|
||||
/** Currency code for base 1/1,000 Litecoin. */
|
||||
public static final String CODE_MLITE = "mLITE";
|
||||
/** Currency code for base 1/100,000,000 Litecoin. */
|
||||
public static final String CODE_LITEOSHI = "Liteoshi";
|
||||
|
||||
static {
|
||||
LITE = MonetaryFormat.BTC.noCode()
|
||||
.code(0, CODE_LITE)
|
||||
.code(3, CODE_MLITE)
|
||||
.code(7, CODE_LITEOSHI);
|
||||
MLITE = LITE.shift(3).minDecimals(2).optionalDecimals(2);
|
||||
LITEOSHI = LITE.shift(7).minDecimals(0).optionalDecimals(2);
|
||||
}
|
||||
|
||||
/** The string returned by getId() for the main, production network where people trade things. */
|
||||
public static final String ID_LITE_MAINNET = "org.litecoin.production";
|
||||
/** 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;
|
||||
|
||||
public AbstractLitecoinParams() {
|
||||
super();
|
||||
interval = LITE_INTERVAL;
|
||||
targetTimespan = LITE_TARGET_TIMESPAN;
|
||||
maxTarget = Utils.decodeCompactBits(0x1e0fffffL);
|
||||
|
||||
packetMagic = 0xfbc0b6db;
|
||||
bip32HeaderPub = 0x0488C42E; //The 4 byte header that serializes in base58 to "xpub". (?)
|
||||
bip32HeaderPriv = 0x0488E1F4; //The 4 byte header that serializes in base58 to "xprv" (?)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hash to use for a block.
|
||||
*/
|
||||
@Override
|
||||
public Sha256Hash getBlockDifficultyHash(Block block) {
|
||||
return ((AltcoinBlock) block).getScryptHash();
|
||||
}
|
||||
|
||||
public MonetaryFormat getMonetaryFormat() {
|
||||
return LITE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Coin getMaxMoney() {
|
||||
return MAX_LITECOIN_MONEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Coin getMinNonDustOutput() {
|
||||
return Coin.COIN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUriScheme() {
|
||||
return "litecoin";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMaxMoney() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkDifficultyTransitions(StoredBlock storedPrev, Block nextBlock, BlockStore blockStore)
|
||||
throws VerificationException, BlockStoreException {
|
||||
final Block prev = storedPrev.getHeader();
|
||||
final int previousHeight = storedPrev.getHeight();
|
||||
final int retargetInterval = this.getInterval();
|
||||
|
||||
// Is this supposed to be a difficulty transition point?
|
||||
if ((storedPrev.getHeight() + 1) % retargetInterval != 0) {
|
||||
// No ... so check the difficulty didn't actually change.
|
||||
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;
|
||||
}
|
||||
|
||||
// We need to find a block far back in the chain. It's OK that this is expensive because it only occurs every
|
||||
// two weeks after the initial block chain download.
|
||||
StoredBlock cursor = blockStore.get(prev.getHash());
|
||||
int goBack = retargetInterval - 1;
|
||||
if (cursor.getHeight()+1 != retargetInterval)
|
||||
goBack = retargetInterval;
|
||||
|
||||
for (int i = 0; i < goBack; i++) {
|
||||
if (cursor == null) {
|
||||
// This should never happen. If it does, it means we are following an incorrect or busted chain.
|
||||
throw new VerificationException(
|
||||
"Difficulty transition point but we did not find a way back to the genesis block.");
|
||||
}
|
||||
cursor = blockStore.get(cursor.getHeader().getPrevBlockHash());
|
||||
}
|
||||
|
||||
//We used checkpoints...
|
||||
if (cursor == null) {
|
||||
log.debug("Difficulty transition: Hit checkpoint!");
|
||||
return;
|
||||
}
|
||||
|
||||
Block blockIntervalAgo = cursor.getHeader();
|
||||
long receivedTargetCompact = nextBlock.getDifficultyTarget();
|
||||
long newTargetCompact = this.getNewDifficultyTarget(previousHeight, prev,
|
||||
nextBlock, blockIntervalAgo);
|
||||
|
||||
if (newTargetCompact != receivedTargetCompact)
|
||||
throw new VerificationException("Network provided difficulty bits do not match what was calculated: " +
|
||||
newTargetCompact + " vs " + receivedTargetCompact);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @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, final Block nextBlock,
|
||||
final Block blockIntervalAgo) {
|
||||
return this.getNewDifficultyTarget(previousHeight, prev.getTimeSeconds(),
|
||||
prev.getDifficultyTarget(), blockIntervalAgo.getTimeSeconds(),
|
||||
nextBlock.getDifficultyTarget());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param previousHeight Height of the block immediately previous to the one we're calculating difficulty of.
|
||||
* @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.
|
||||
*/
|
||||
protected long getNewDifficultyTarget(int previousHeight, long previousBlockTime,
|
||||
final long lastDifficultyTarget, final long lastRetargetTime,
|
||||
final long nextDifficultyTarget) {
|
||||
final int retargetTimespan = this.getTargetTimespan();
|
||||
int actualTime = (int) (previousBlockTime - lastRetargetTime);
|
||||
final int minTimespan = retargetTimespan / 4;
|
||||
final int maxTimespan = retargetTimespan * 4;
|
||||
|
||||
actualTime = Math.min(maxTimespan, Math.max(minTimespan, actualTime));
|
||||
|
||||
BigInteger newTarget = Utils.decodeCompactBits(lastDifficultyTarget);
|
||||
newTarget = newTarget.multiply(BigInteger.valueOf(actualTime));
|
||||
newTarget = newTarget.divide(BigInteger.valueOf(retargetTimespan));
|
||||
|
||||
if (newTarget.compareTo(this.getMaxTarget()) > 0) {
|
||||
log.info("Difficulty hit proof of work limit: {}", newTarget.toString(16));
|
||||
newTarget = this.getMaxTarget();
|
||||
}
|
||||
|
||||
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);
|
||||
newTarget = newTarget.and(mask);
|
||||
return Utils.encodeCompactBits(newTarget);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AltcoinSerializer getSerializer(boolean parseRetain) {
|
||||
return new AltcoinSerializer(this, parseRetain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProtocolVersionNum(final ProtocolVersion version) {
|
||||
switch (version) {
|
||||
case PONG:
|
||||
case BLOOM_FILTER:
|
||||
return version.getBitcoinProtocolVersion();
|
||||
case CURRENT:
|
||||
return LITECOIN_PROTOCOL_VERSION_CURRENT;
|
||||
case MINIMUM:
|
||||
default:
|
||||
return LITECOIN_PROTOCOL_VERSION_MINIMUM;
|
||||
}
|
||||
}
|
||||
}
|
123
src/main/java/org/libdohj/params/LitecoinMainNetParams.java
Normal file
123
src/main/java/org/libdohj/params/LitecoinMainNetParams.java
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright 2013 Google Inc.
|
||||
* Copyright 2014 Andreas Schildbach
|
||||
*
|
||||
* 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.Utils;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import org.bitcoinj.core.AltcoinBlock;
|
||||
import org.bitcoinj.core.Block;
|
||||
import static org.bitcoinj.core.Coin.COIN;
|
||||
import org.bitcoinj.core.NetworkParameters;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
import org.bitcoinj.core.TransactionInput;
|
||||
import org.bitcoinj.core.TransactionOutput;
|
||||
import org.bitcoinj.script.Script;
|
||||
import org.bitcoinj.script.ScriptOpCodes;
|
||||
|
||||
/**
|
||||
* Parameters for the Litecoin main production network on which people trade
|
||||
* 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 LitecoinMainNetParams() {
|
||||
super();
|
||||
id = ID_LITE_MAINNET;
|
||||
// Genesis hash is 12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2
|
||||
packetMagic = 0xfbc0b6db;
|
||||
|
||||
maxTarget = Utils.decodeCompactBits(0x1e0fffffL);
|
||||
port = 9333;
|
||||
addressHeader = 48;
|
||||
p2shHeader = 5;
|
||||
acceptableAddressCodes = new int[] { addressHeader, p2shHeader };
|
||||
dumpedPrivateKeyHeader = 176;
|
||||
|
||||
this.genesisBlock = createGenesis(this);
|
||||
spendableCoinbaseDepth = 30;
|
||||
subsidyDecreaseBlockCount = 100000;
|
||||
|
||||
String genesisHash = genesisBlock.getHashAsString();
|
||||
checkState(genesisHash.equals("12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2"));
|
||||
alertSigningKey = Hex.decode("040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9");
|
||||
|
||||
majorityEnforceBlockUpgrade = MAINNET_MAJORITY_ENFORCE_BLOCK_UPGRADE;
|
||||
majorityRejectBlockOutdated = MAINNET_MAJORITY_REJECT_BLOCK_OUTDATED;
|
||||
majorityWindow = MAINNET_MAJORITY_WINDOW;
|
||||
|
||||
dnsSeeds = new String[] {
|
||||
"dnsseed.litecointools.com",
|
||||
"dnsseed.litecoinpool.org",
|
||||
"dnsseed.ltc.xurious.com",
|
||||
"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;
|
||||
}
|
||||
|
||||
private static AltcoinBlock createGenesis(NetworkParameters params) {
|
||||
AltcoinBlock genesisBlock = new AltcoinBlock(params, Block.BLOCK_VERSION_GENESIS);
|
||||
Transaction t = new Transaction(params);
|
||||
try {
|
||||
byte[] bytes = Hex.decode
|
||||
("04ffff001d0104404e592054696d65732030352f4f63742f32303131205374657665204a6f62732c204170706c65e280997320566973696f6e6172792c2044696573206174203536");
|
||||
t.addInput(new TransactionInput(params, t, bytes));
|
||||
ByteArrayOutputStream scriptPubKeyBytes = new ByteArrayOutputStream();
|
||||
Script.writeBytes(scriptPubKeyBytes, Hex.decode
|
||||
("040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9"));
|
||||
scriptPubKeyBytes.write(ScriptOpCodes.OP_CHECKSIG);
|
||||
t.addOutput(new TransactionOutput(params, t, COIN.multiply(50), scriptPubKeyBytes.toByteArray()));
|
||||
} catch (Exception e) {
|
||||
// Cannot happen.
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
genesisBlock.addTransaction(t);
|
||||
genesisBlock.setTime(1317972665L);
|
||||
genesisBlock.setDifficultyTarget(0x1e0ffff0L);
|
||||
genesisBlock.setNonce(2084524493);
|
||||
return genesisBlock;
|
||||
}
|
||||
|
||||
private static LitecoinMainNetParams instance;
|
||||
public static synchronized LitecoinMainNetParams get() {
|
||||
if (instance == null) {
|
||||
instance = new LitecoinMainNetParams();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPaymentProtocolId() {
|
||||
// TODO: CHANGE ME
|
||||
return PAYMENT_PROTOCOL_ID_MAINNET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTestNet() {
|
||||
return false;
|
||||
}
|
||||
}
|
122
src/main/java/org/libdohj/params/LitecoinTestNet3Params.java
Normal file
122
src/main/java/org/libdohj/params/LitecoinTestNet3Params.java
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2013 Google Inc.
|
||||
* Copyright 2014 Andreas Schildbach
|
||||
*
|
||||
* 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.Utils;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import org.bitcoinj.core.AltcoinBlock;
|
||||
import org.bitcoinj.core.Block;
|
||||
import static org.bitcoinj.core.Coin.COIN;
|
||||
import org.bitcoinj.core.NetworkParameters;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
import org.bitcoinj.core.TransactionInput;
|
||||
import org.bitcoinj.core.TransactionOutput;
|
||||
import org.bitcoinj.script.Script;
|
||||
import org.bitcoinj.script.ScriptOpCodes;
|
||||
|
||||
/**
|
||||
* Parameters for the testnet, a separate public instance of Litecoin that has
|
||||
* relaxed rules suitable for development and testing of applications and new
|
||||
* 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 LitecoinTestNet3Params() {
|
||||
super();
|
||||
id = ID_LITE_TESTNET;
|
||||
// Genesis hash is f5ae71e26c74beacc88382716aced69cddf3dffff24f384e1808905e0188f68f
|
||||
packetMagic = 0xfcc1b7dc;
|
||||
|
||||
maxTarget = Utils.decodeCompactBits(0x1e0fffffL);
|
||||
port = 19333;
|
||||
addressHeader = 111;
|
||||
p2shHeader = 196;
|
||||
acceptableAddressCodes = new int[] { addressHeader, p2shHeader };
|
||||
dumpedPrivateKeyHeader = 239;
|
||||
|
||||
this.genesisBlock = createGenesis(this);
|
||||
spendableCoinbaseDepth = 30;
|
||||
subsidyDecreaseBlockCount = 100000;
|
||||
|
||||
String genesisHash = genesisBlock.getHashAsString();
|
||||
checkState(genesisHash.equals("f5ae71e26c74beacc88382716aced69cddf3dffff24f384e1808905e0188f68f"));
|
||||
alertSigningKey = Hex.decode("0449623fc74489a947c4b15d579115591add020e53b3490bf47297dfa3762250625f8ecc2fb4fc59f69bdce8f7080f3167808276ed2c79d297054367566038aa82");
|
||||
|
||||
majorityEnforceBlockUpgrade = TESTNET_MAJORITY_ENFORCE_BLOCK_UPGRADE;
|
||||
majorityRejectBlockOutdated = TESTNET_MAJORITY_REJECT_BLOCK_OUTDATED;
|
||||
majorityWindow = TESTNET_MAJORITY_WINDOW;
|
||||
|
||||
dnsSeeds = new String[] {
|
||||
"testnet-seed.litecointools.com",
|
||||
"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;
|
||||
}
|
||||
|
||||
private static AltcoinBlock createGenesis(NetworkParameters params) {
|
||||
AltcoinBlock genesisBlock = new AltcoinBlock(params, Block.BLOCK_VERSION_GENESIS);
|
||||
Transaction t = new Transaction(params);
|
||||
try {
|
||||
byte[] bytes = Hex.decode
|
||||
("04ffff001d0104404e592054696d65732030352f4f63742f32303131205374657665204a6f62732c204170706c65e280997320566973696f6e6172792c2044696573206174203536");
|
||||
t.addInput(new TransactionInput(params, t, bytes));
|
||||
ByteArrayOutputStream scriptPubKeyBytes = new ByteArrayOutputStream();
|
||||
Script.writeBytes(scriptPubKeyBytes, Hex.decode
|
||||
("040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9"));
|
||||
scriptPubKeyBytes.write(ScriptOpCodes.OP_CHECKSIG);
|
||||
t.addOutput(new TransactionOutput(params, t, COIN.multiply(50), scriptPubKeyBytes.toByteArray()));
|
||||
} catch (Exception e) {
|
||||
// Cannot happen.
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
genesisBlock.addTransaction(t);
|
||||
genesisBlock.setTime(1317798646L);
|
||||
genesisBlock.setDifficultyTarget(0x1e0ffff0L);
|
||||
genesisBlock.setNonce(385270584);
|
||||
return genesisBlock;
|
||||
}
|
||||
|
||||
private static LitecoinTestNet3Params instance;
|
||||
public static synchronized LitecoinTestNet3Params get() {
|
||||
if (instance == null) {
|
||||
instance = new LitecoinTestNet3Params();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPaymentProtocolId() {
|
||||
// TODO: CHANGE ME
|
||||
return PAYMENT_PROTOCOL_ID_TESTNET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTestNet() {
|
||||
return true;
|
||||
}
|
||||
}
|
41
src/test/java/org/bitcoinj/core/LitecoinBlockTest.java
Normal file
41
src/test/java/org/bitcoinj/core/LitecoinBlockTest.java
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.bitcoinj.core;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.libdohj.core.AltcoinSerializer;
|
||||
import org.libdohj.params.LitecoinMainNetParams;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jrn
|
||||
*/
|
||||
public class LitecoinBlockTest {
|
||||
private NetworkParameters params = LitecoinMainNetParams.get();
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
Context context = new Context(params);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldParseBlock1() throws IOException {
|
||||
byte[] payload = Util.getBytes(getClass().getResourceAsStream("litecoin_block1.bin"));
|
||||
AltcoinSerializer serializer = (AltcoinSerializer)params.getDefaultSerializer();
|
||||
final AltcoinBlock block = (AltcoinBlock)serializer.makeBlock(payload);
|
||||
assertEquals("80ca095ed10b02e53d769eb6eaf92cd04e9e0759e5be4a8477b42911ba49c78f", block.getHashAsString());
|
||||
assertEquals(params.getGenesisBlock().getHash(), block.getPrevBlockHash());
|
||||
assertEquals(1, block.getTransactions().size());
|
||||
assertEquals(0x1e0ffff0L, block.getDifficultyTarget());
|
||||
assertTrue(block.checkProofOfWork(false));
|
||||
}
|
||||
}
|
BIN
src/test/resources/org/bitcoinj/core/litecoin_block1.bin
Normal file
BIN
src/test/resources/org/bitcoinj/core/litecoin_block1.bin
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user