Commit 34521106 authored by bitcoinj-sv's avatar bitcoinj-sv

ported needed stuff for cash

parent b131cc77
...@@ -21,6 +21,9 @@ import com.google.common.base.*; ...@@ -21,6 +21,9 @@ import com.google.common.base.*;
import com.google.common.collect.*; import com.google.common.collect.*;
import com.google.common.util.concurrent.*; import com.google.common.util.concurrent.*;
import org.bitcoinj.core.listeners.*; import org.bitcoinj.core.listeners.*;
import org.bitcoinj.pow.AbstractPowRulesChecker;
import org.bitcoinj.pow.AbstractRuleCheckerFactory;
import org.bitcoinj.pow.factory.RuleCheckerFactory;
import org.bitcoinj.store.*; import org.bitcoinj.store.*;
import org.bitcoinj.utils.*; import org.bitcoinj.utils.*;
import org.bitcoinj.wallet.Wallet; import org.bitcoinj.wallet.Wallet;
...@@ -104,7 +107,7 @@ public abstract class AbstractBlockChain { ...@@ -104,7 +107,7 @@ public abstract class AbstractBlockChain {
private final CopyOnWriteArrayList<ListenerRegistration<NewBestBlockListener>> newBestBlockListeners; private final CopyOnWriteArrayList<ListenerRegistration<NewBestBlockListener>> newBestBlockListeners;
private final CopyOnWriteArrayList<ListenerRegistration<ReorganizeListener>> reorganizeListeners; private final CopyOnWriteArrayList<ListenerRegistration<ReorganizeListener>> reorganizeListeners;
private final CopyOnWriteArrayList<ListenerRegistration<TransactionReceivedInBlockListener>> transactionReceivedListeners; private final CopyOnWriteArrayList<ListenerRegistration<TransactionReceivedInBlockListener>> transactionReceivedListeners;
protected final AbstractRuleCheckerFactory ruleCheckerFactory;
// Holds a block header and, optionally, a list of tx hashes or block's transactions // Holds a block header and, optionally, a list of tx hashes or block's transactions
class OrphanBlock { class OrphanBlock {
final Block block; final Block block;
...@@ -149,7 +152,7 @@ public abstract class AbstractBlockChain { ...@@ -149,7 +152,7 @@ public abstract class AbstractBlockChain {
chainHead = blockStore.getChainHead(); chainHead = blockStore.getChainHead();
log.info("chain head is at height {}:\n{}", chainHead.getHeight(), chainHead.getHeader()); log.info("chain head is at height {}:\n{}", chainHead.getHeight(), chainHead.getHeader());
this.params = context.getParams(); this.params = context.getParams();
this.ruleCheckerFactory = RuleCheckerFactory.create(this.params);
this.newBestBlockListeners = new CopyOnWriteArrayList<ListenerRegistration<NewBestBlockListener>>(); this.newBestBlockListeners = new CopyOnWriteArrayList<ListenerRegistration<NewBestBlockListener>>();
this.reorganizeListeners = new CopyOnWriteArrayList<ListenerRegistration<ReorganizeListener>>(); this.reorganizeListeners = new CopyOnWriteArrayList<ListenerRegistration<ReorganizeListener>>();
this.transactionReceivedListeners = new CopyOnWriteArrayList<ListenerRegistration<TransactionReceivedInBlockListener>>(); this.transactionReceivedListeners = new CopyOnWriteArrayList<ListenerRegistration<TransactionReceivedInBlockListener>>();
...@@ -485,7 +488,8 @@ public abstract class AbstractBlockChain { ...@@ -485,7 +488,8 @@ public abstract class AbstractBlockChain {
} else { } else {
checkState(lock.isHeldByCurrentThread()); checkState(lock.isHeldByCurrentThread());
// It connects to somewhere on the chain. Not necessarily the top of the best known chain. // It connects to somewhere on the chain. Not necessarily the top of the best known chain.
params.checkDifficultyTransitions(storedPrev, block, blockStore); AbstractPowRulesChecker rulesChecker = ruleCheckerFactory.getRuleChecker(storedPrev, block);
rulesChecker.checkRules(storedPrev, block, blockStore, this);
connectBlock(block, storedPrev, shouldVerifyTransactions(), filteredTxHashList, filteredTxn); connectBlock(block, storedPrev, shouldVerifyTransactions(), filteredTxHashList, filteredTxn);
} }
...@@ -714,7 +718,7 @@ public abstract class AbstractBlockChain { ...@@ -714,7 +718,7 @@ public abstract class AbstractBlockChain {
/** /**
* Gets the median timestamp of the last 11 blocks * Gets the median timestamp of the last 11 blocks
*/ */
private static long getMedianTimestampOfRecentBlocks(StoredBlock storedBlock, public static long getMedianTimestampOfRecentBlocks(StoredBlock storedBlock,
BlockStore store) throws BlockStoreException { BlockStore store) throws BlockStoreException {
long[] timestamps = new long[11]; long[] timestamps = new long[11];
int unused = 9; int unused = 9;
......
...@@ -88,6 +88,13 @@ public abstract class NetworkParameters { ...@@ -88,6 +88,13 @@ public abstract class NetworkParameters {
protected int majorityRejectBlockOutdated; protected int majorityRejectBlockOutdated;
protected int majorityWindow; protected int majorityWindow;
// Aug, 1 2017 hard fork
protected int uahfHeight;
// Nov, 13 2017 hard fork
protected int daaUpdateHeight;
// May, 15 2018 hard fork
protected long monolithActivationTime = 1526400000L;
/** /**
* See getId(). This may be null for old deserialized wallets. In that case we derive it heuristically * See getId(). This may be null for old deserialized wallets. In that case we derive it heuristically
* by looking at the port number. * by looking at the port number.
...@@ -106,6 +113,7 @@ public abstract class NetworkParameters { ...@@ -106,6 +113,7 @@ public abstract class NetworkParameters {
protected HttpDiscovery.Details[] httpSeeds = {}; protected HttpDiscovery.Details[] httpSeeds = {};
protected Map<Integer, Sha256Hash> checkpoints = new HashMap<Integer, Sha256Hash>(); protected Map<Integer, Sha256Hash> checkpoints = new HashMap<Integer, Sha256Hash>();
protected transient MessageSerializer defaultSerializer = null; protected transient MessageSerializer defaultSerializer = null;
protected String cashAddrPrefix;
protected NetworkParameters() { protected NetworkParameters() {
alertSigningKey = SATOSHI_KEY; alertSigningKey = SATOSHI_KEY;
...@@ -253,9 +261,9 @@ public abstract class NetworkParameters { ...@@ -253,9 +261,9 @@ public abstract class NetworkParameters {
* Throws an exception if the block's difficulty is not correct. * Throws an exception if the block's difficulty is not correct.
* *
* @throws VerificationException if the block's difficulty is not correct. * @throws VerificationException if the block's difficulty is not correct.
*/
public abstract void checkDifficultyTransitions(StoredBlock storedPrev, Block next, final BlockStore blockStore) throws VerificationException, BlockStoreException;
public abstract void checkDifficultyTransitions(StoredBlock storedPrev, Block next, final BlockStore blockStore) throws VerificationException, BlockStoreException;
*/
/** /**
* Returns true if the block height is either not a checkpoint, or is a checkpoint and the hash matches. * Returns true if the block height is either not a checkpoint, or is a checkpoint and the hash matches.
*/ */
...@@ -495,6 +503,15 @@ public abstract class NetworkParameters { ...@@ -495,6 +503,15 @@ public abstract class NetworkParameters {
return flags; return flags;
} }
public int getDAAUpdateHeight(){
return daaUpdateHeight;
}
/** MTP activation time for May 15th, 2018 upgrade **/
public long getMonolithActivationTime() {
return monolithActivationTime;
}
/** /**
* The flags indicating which script validation tests should be applied to * The flags indicating which script validation tests should be applied to
* the given transaction. Enables support for alternative blockchains which enable * the given transaction. Enables support for alternative blockchains which enable
......
...@@ -53,7 +53,8 @@ public class Utils { ...@@ -53,7 +53,8 @@ public class Utils {
/** The string that prefixes all text messages signed using Bitcoin keys. */ /** The string that prefixes all text messages signed using Bitcoin keys. */
public static final String BITCOIN_SIGNED_MESSAGE_HEADER = "Bitcoin Signed Message:\n"; public static final String BITCOIN_SIGNED_MESSAGE_HEADER = "Bitcoin Signed Message:\n";
public static final byte[] BITCOIN_SIGNED_MESSAGE_HEADER_BYTES = BITCOIN_SIGNED_MESSAGE_HEADER.getBytes(Charsets.UTF_8); public static final byte[] BITCOIN_SIGNED_MESSAGE_HEADER_BYTES = BITCOIN_SIGNED_MESSAGE_HEADER.getBytes(Charsets.UTF_8);
// zero length arrays are immutable so we can save some object allocation by reusing the same instance.
public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
private static final Joiner SPACE_JOINER = Joiner.on(" "); private static final Joiner SPACE_JOINER = Joiner.on(" ");
private static BlockingQueue<Boolean> mockSleepQueue; private static BlockingQueue<Boolean> mockSleepQueue;
...@@ -254,7 +255,102 @@ public class Utils { ...@@ -254,7 +255,102 @@ public class Utils {
BigInteger result = new BigInteger(buf); BigInteger result = new BigInteger(buf);
return isNegative ? result.negate() : result; return isNegative ? result.negate() : result;
} }
/**
* Returns a minimally encoded encoded version of the data. That is, a version will pass the check
* in checkMinimallyEncodedLE(byte[] bytesLE).
*
* If the data is already minimally encoded the original byte array will be returned.
*
* inspired by: https://reviews.bitcoinabc.org/D1219
*
* @param dataLE
* @return
*/
public static byte[] minimallyEncodeLE(byte[] dataLE) {
if (dataLE.length == 0) {
return dataLE;
}
// If the last byte is not 0x00 or 0x80, we are minimally encoded.
int last = dataLE[dataLE.length - 1];
if ((last & 0x7f) != 0) {
return dataLE;
}
// If the script is one byte long, then we have a zero, which encodes as an
// empty array.
if (dataLE.length == 1) {
return EMPTY_BYTE_ARRAY;
}
// If the next byte has it sign bit set, then we are minimaly encoded.
if ((dataLE[dataLE.length - 2] & 0x80) != 0) {
return dataLE;
}
//we might modify the array so clone it
dataLE = dataLE.clone();
// We are not minimally encoded, we need to figure out how much to trim.
// we are using i - 1 indexes here as we want to ignore the last byte (first byte in BE)
for (int i = dataLE.length - 1; i > 0; i--) {
// We found a non zero byte, time to encode.
if (dataLE[i - 1] != 0) {
if ((dataLE[i - 1] & 0x80) != 0) {
// We found a byte with it's sign bit set so we need one more
// byte.
dataLE[i++] = (byte) last;
} else {
// the sign bit is clear, we can use it.
// add the sign bit from the last byte
dataLE[i - 1] |= last;
}
return Arrays.copyOf(dataLE, i);
}
}
// If we the whole thing is zeros, then we have a zero.
return EMPTY_BYTE_ARRAY;
}
/**
* checks that LE encoded number is minimally represented. That is that there are no leading zero bytes except in
* the case: if there's more than one byte and the most significant bit of the second-most-significant-byte is set it
* would conflict with the sign bit.
* @param bytesLE
* @return
*/
public static boolean checkMinimallyEncodedLE(byte[] bytesLE, int maxNumSize) {
if (bytesLE.length > maxNumSize) {
return false;
}
if (bytesLE.length > 0) {
// Check that the number is encoded with the minimum possible number
// of bytes.
//
// If the most-significant-byte - excluding the sign bit - is zero
// then we're not minimal. Note how this test also rejects the
// negative-zero encoding, 0x80.
if ((bytesLE[bytesLE.length - 1] & 0x7f) == 0) {
// One exception: if there's more than one byte and the most
// significant bit of the second-most-significant-byte is set it
// would conflict with the sign bit. An example of this case is
// +-255, which encode to 0xff00 and 0xff80 respectively.
// (big-endian).
if (bytesLE.length <= 1 || (bytesLE[bytesLE.length - 2] & 0x80) == 0) {
return false;
}
}
}
return true;
}
/** /**
* MPI encoded numbers are produced by the OpenSSL BN_bn2mpi function. They consist of * MPI encoded numbers are produced by the OpenSSL BN_bn2mpi function. They consist of
* a 4 byte big endian length field, followed by the stated number of bytes representing * a 4 byte big endian length field, followed by the stated number of bytes representing
......
...@@ -48,6 +48,10 @@ public class TransactionSignature extends ECKey.ECDSASignature { ...@@ -48,6 +48,10 @@ public class TransactionSignature extends ECKey.ECDSASignature {
super(r, s); super(r, s);
this.sighashFlags = sighashFlags; this.sighashFlags = sighashFlags;
} }
public TransactionSignature(ECKey.ECDSASignature signature, Transaction.SigHash mode, boolean anyoneCanPay, boolean useForkId) {
super(signature.r, signature.s);
sighashFlags = calcSigHashValue(mode, anyoneCanPay, useForkId);
}
/** Constructs a transaction signature based on the ECDSA signature. */ /** Constructs a transaction signature based on the ECDSA signature. */
public TransactionSignature(ECKey.ECDSASignature signature, Transaction.SigHash mode, boolean anyoneCanPay) { public TransactionSignature(ECKey.ECDSASignature signature, Transaction.SigHash mode, boolean anyoneCanPay) {
...@@ -75,6 +79,16 @@ public class TransactionSignature extends ECKey.ECDSASignature { ...@@ -75,6 +79,16 @@ public class TransactionSignature extends ECKey.ECDSASignature {
return sighashFlags; return sighashFlags;
} }
public static int calcSigHashValue(Transaction.SigHash mode, boolean anyoneCanPay, boolean useForkId) {
Preconditions.checkArgument(SigHash.ALL == mode || SigHash.NONE == mode || SigHash.SINGLE == mode); // enforce compatibility since this code was made before the SigHash enum was updated
int sighashFlags = mode.value;
if (anyoneCanPay)
sighashFlags |= Transaction.SigHash.ANYONECANPAY.value;
if(useForkId)
sighashFlags |= SigHash.FORKID.value;
return sighashFlags;
}
/** /**
* Returns true if the given signature is has canonical encoding, and will thus be accepted as standard by * Returns true if the given signature is has canonical encoding, and will thus be accepted as standard by
* Bitcoin Core. DER and the SIGHASH encoding allow for quite some flexibility in how the same structures * Bitcoin Core. DER and the SIGHASH encoding allow for quite some flexibility in how the same structures
...@@ -162,7 +176,7 @@ public class TransactionSignature extends ECKey.ECDSASignature { ...@@ -162,7 +176,7 @@ public class TransactionSignature extends ECKey.ECDSASignature {
* @param requireCanonicalEncoding if the encoding of the signature must * @param requireCanonicalEncoding if the encoding of the signature must
* be canonical. * be canonical.
* @throws RuntimeException if the signature is invalid or unparseable in some way. * @throws RuntimeException if the signature is invalid or unparseable in some way.
* @deprecated use {@link #decodeFromBitcoin(byte[], boolean, boolean} instead}. * @deprecated use {@link #decodeFromBitcoin(byte[], boolean, boolean}}.
*/ */
@Deprecated @Deprecated
public static TransactionSignature decodeFromBitcoin(byte[] bytes, public static TransactionSignature decodeFromBitcoin(byte[] bytes,
......
...@@ -20,14 +20,8 @@ package org.bitcoinj.params; ...@@ -20,14 +20,8 @@ package org.bitcoinj.params;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.bitcoinj.core.Block; import org.bitcoinj.core.*;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.core.StoredBlock;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.Utils;
import org.bitcoinj.utils.MonetaryFormat; import org.bitcoinj.utils.MonetaryFormat;
import org.bitcoinj.core.VerificationException;
import org.bitcoinj.store.BlockStore; import org.bitcoinj.store.BlockStore;
import org.bitcoinj.store.BlockStoreException; import org.bitcoinj.store.BlockStoreException;
import org.slf4j.Logger; import org.slf4j.Logger;
...@@ -35,12 +29,48 @@ import org.slf4j.LoggerFactory; ...@@ -35,12 +29,48 @@ import org.slf4j.LoggerFactory;
import com.google.common.base.Stopwatch; import com.google.common.base.Stopwatch;
import org.bitcoinj.core.BitcoinSerializer;
/** /**
* Parameters for Bitcoin-like networks. * Parameters for Bitcoin-like networks.
*/ */
public abstract class AbstractBitcoinNetParams extends NetworkParameters { public abstract class AbstractBitcoinNetParams extends NetworkParameters {
/**
* Checks if we are at a difficulty transition point.
* @param storedPrev The previous stored block
* @param parameters The network parameters
* @return If this is a difficulty transition point
*/
public static boolean isDifficultyTransitionPoint(StoredBlock storedPrev, NetworkParameters parameters) {
return ((storedPrev.getHeight() + 1) % parameters.getInterval()) == 0;
}
/**
* determines whether monolith upgrade is activated based on MTP
* @param storedPrev The previous stored block
* @param store BlockStore containing at least 11 blocks
* @param parameters The network parameters
* @return
*/
public static boolean isMonolithEnabled(StoredBlock storedPrev, BlockStore store, NetworkParameters parameters) {
if (storedPrev.getHeight() < 524626) { //current height at time of writing, well below the activation block height
return false;
}
try {
long mtp = BlockChain.getMedianTimestampOfRecentBlocks(storedPrev, store);
return isMonolithEnabled(mtp, parameters);
} catch (BlockStoreException e) {
throw new RuntimeException("Cannot determine monolith activation without BlockStore");
}
}
/**
* determines whether monolith upgrade is activated based on the given MTP. Useful for overriding MTP for testing.
* @param medianTimePast
* @param parameters The network parameters
* @return
*/
public static boolean isMonolithEnabled(long medianTimePast, NetworkParameters parameters) {
return medianTimePast >= parameters.getMonolithActivationTime();
}
/** /**
* Scheme part for Bitcoin URIs. * Scheme part for Bitcoin URIs.
*/ */
...@@ -61,69 +91,6 @@ public abstract class AbstractBitcoinNetParams extends NetworkParameters { ...@@ -61,69 +91,6 @@ public abstract class AbstractBitcoinNetParams extends NetworkParameters {
return ((storedPrev.getHeight() + 1) % this.getInterval()) == 0; return ((storedPrev.getHeight() + 1) % this.getInterval()) == 0;
} }
@Override
public void checkDifficultyTransitions(final StoredBlock storedPrev, final Block nextBlock,
final BlockStore blockStore) throws VerificationException, BlockStoreException {
Block prev = storedPrev.getHeader();
// Is this supposed to be a difficulty transition point?
if (!isDifficultyTransitionPoint(storedPrev)) {
// 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.
final Stopwatch watch = Stopwatch.createStarted();
StoredBlock cursor = blockStore.get(prev.getHash());
for (int i = 0; i < this.getInterval() - 1; 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());
}
watch.stop();
if (watch.elapsed(TimeUnit.MILLISECONDS) > 50)
log.info("Difficulty transition traversal took {}", watch);
Block blockIntervalAgo = cursor.getHeader();
int timespan = (int) (prev.getTimeSeconds() - blockIntervalAgo.getTimeSeconds());
// Limit the adjustment step.
final int targetTimespan = this.getTargetTimespan();
if (timespan < targetTimespan / 4)
timespan = targetTimespan / 4;
if (timespan > targetTimespan * 4)
timespan = targetTimespan * 4;
BigInteger newTarget = Utils.decodeCompactBits(prev.getDifficultyTarget());
newTarget = newTarget.multiply(BigInteger.valueOf(timespan));
newTarget = newTarget.divide(BigInteger.valueOf(targetTimespan));
if (newTarget.compareTo(this.getMaxTarget()) > 0) {
log.info("Difficulty hit proof of work limit: {}", newTarget.toString(16));
newTarget = this.getMaxTarget();
}
int accuracyBytes = (int) (nextBlock.getDifficultyTarget() >>> 24) - 3;
long receivedTargetCompact = nextBlock.getDifficultyTarget();
// 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);
long newTargetCompact = Utils.encodeCompactBits(newTarget);
if (newTargetCompact != receivedTargetCompact)
throw new VerificationException("Network provided difficulty bits do not match what was calculated: " +
Long.toHexString(newTargetCompact) + " vs " + Long.toHexString(receivedTargetCompact));
}
@Override @Override
public Coin getMaxMoney() { public Coin getMaxMoney() {
return MAX_MONEY; return MAX_MONEY;
......
...@@ -71,24 +71,21 @@ public class MainNetParams extends AbstractBitcoinNetParams { ...@@ -71,24 +71,21 @@ public class MainNetParams extends AbstractBitcoinNetParams {
checkpoints.put(200000, Sha256Hash.wrap("000000000000034a7dedef4a161fa058a2d67a173a90155f3a2fe6fc132e0ebf")); checkpoints.put(200000, Sha256Hash.wrap("000000000000034a7dedef4a161fa058a2d67a173a90155f3a2fe6fc132e0ebf"));
dnsSeeds = new String[] { dnsSeeds = new String[] {
"seed.bitcoin.sipa.be", // Pieter Wuille "seed.bitcoinsv.io", // Bitcoin SV seeder
"dnsseed.bluematt.me", // Matt Corallo "btccash-seeder.bitcoinunlimited.info", // BU backed seeder
"dnsseed.bitcoin.dashjr.org", // Luke Dashjr "seed.bitprim.org", // Bitprim
"seed.bitcoinstats.com", // Chris Decker "seed.deadalnix.me",// Amaury SÉCHET
"seed.bitnodes.io", // Addy Yeow "seeder.criptolayer.net",// criptolayer.net
"bitseed.xf2.org", // Jeff Garzik
"seed.bitcoin.jonasschnelli.ch",// Jonas Schnelli
"bitcoin.bloqseeds.net", // Bloq
}; };
httpSeeds = new HttpDiscovery.Details[] { httpSeeds = null; /* new HttpDiscovery.Details[] {
// Andreas Schildbach // Andreas Schildbach
new HttpDiscovery.Details( new HttpDiscovery.Details(
ECKey.fromPublicOnly(Utils.HEX.decode("0238746c59d46d5408bf8b1d0af5740fe1a6e1703fcb56b2953f0b965c740d256f")), ECKey.fromPublicOnly(Utils.HEX.decode("0238746c59d46d5408bf8b1d0af5740fe1a6e1703fcb56b2953f0b965c740d256f")),
URI.create("http://httpseed.bitcoin.schildbach.de/peers") URI.create("http://httpseed.bitcoin.schildbach.de/peers")
) )
}; };*/
addrSeeds = new int[] { addrSeeds = null; /*new int[] {
0x1ddb1032, 0x6242ce40, 0x52d6a445, 0x2dd7a445, 0x8a53cd47, 0x73263750, 0xda23c257, 0xecd4ed57, 0x1ddb1032, 0x6242ce40, 0x52d6a445, 0x2dd7a445, 0x8a53cd47, 0x73263750, 0xda23c257, 0xecd4ed57,
0x0a40ec59, 0x75dce160, 0x7df76791, 0x89370bad, 0xa4f214ad, 0x767700ae, 0x638b0418, 0x868a1018, 0x0a40ec59, 0x75dce160, 0x7df76791, 0x89370bad, 0xa4f214ad, 0x767700ae, 0x638b0418, 0x868a1018,
0xcd9f332e, 0x0129653e, 0xcc92dc3e, 0x96671640, 0x56487e40, 0x5b66f440, 0xb1d01f41, 0xf1dc6041, 0xcd9f332e, 0x0129653e, 0xcc92dc3e, 0x96671640, 0x56487e40, 0x5b66f440, 0xb1d01f41, 0xf1dc6041,
...@@ -129,7 +126,12 @@ public class MainNetParams extends AbstractBitcoinNetParams { ...@@ -129,7 +126,12 @@ public class MainNetParams extends AbstractBitcoinNetParams {
0x6d27c257, 0x977fffad, 0x7baa5d5d, 0x1213be43, 0xb167e5a9, 0x640fe8ca, 0xbc9ea655, 0x0f820a4c, 0x6d27c257, 0x977fffad, 0x7baa5d5d, 0x1213be43, 0xb167e5a9, 0x640fe8ca, 0xbc9ea655, 0x0f820a4c,
0x0f097059, 0x69ac957c, 0x366d8453, 0xb1ba2844, 0x8857f081, 0x70b5be63, 0xc545454b, 0xaf36ded1, 0x0f097059, 0x69ac957c, 0x366d8453, 0xb1ba2844, 0x8857f081, 0x70b5be63, 0xc545454b, 0xaf36ded1,
0xb5a4b052, 0x21f062d1, 0x72ab89b2, 0x74a45318, 0x8312e6bc, 0xb916965f, 0x8aa7c858, 0xfe7effad, 0xb5a4b052, 0x21f062d1, 0x72ab89b2, 0x74a45318, 0x8312e6bc, 0xb916965f, 0x8aa7c858, 0xfe7effad,
}; };*/
// Aug, 1 hard fork
uahfHeight = 478559;
// Nov, 13 hard fork
daaUpdateHeight = 504031;
cashAddrPrefix = "bitcoincash";
} }
private static MainNetParams instance; private static MainNetParams instance;
......
...@@ -89,35 +89,8 @@ public class TestNet3Params extends AbstractBitcoinNetParams { ...@@ -89,35 +89,8 @@ public class TestNet3Params extends AbstractBitcoinNetParams {
// February 16th 2012 // February 16th 2012
private static final Date testnetDiffDate = new Date(1329264000000L); private static final Date testnetDiffDate = new Date(1329264000000L);
@Override public static boolean isValidTestnetDateBlock(Block block){
public void checkDifficultyTransitions(final StoredBlock storedPrev, final Block nextBlock, return block.getTime().after(testnetDiffDate);
final BlockStore blockStore) throws VerificationException, BlockStoreException {
if (!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
// and then leaving, making it too hard to mine a block. On non-difficulty transition points, easy
// blocks are allowed if there has been a span of 20 minutes without one.
final long timeDelta = nextBlock.getTimeSeconds() - prev.getTimeSeconds();
// There is an integer underflow bug in bitcoin-qt that means mindiff blocks are accepted when time
// goes backwards.
if (timeDelta >= 0 && timeDelta <= NetworkParameters.TARGET_SPACING * 2) {
// Walk backwards until we find a block that doesn't have the easiest proof of work, then check
// that difficulty is equal to that one.
StoredBlock cursor = storedPrev;
while (!cursor.getHeader().equals(getGenesisBlock()) &&
cursor.getHeight() % getInterval() != 0 &&
cursor.getHeader().getDifficultyTargetAsInteger().equals(getMaxTarget()))
cursor = cursor.getPrev(blockStore);
BigInteger cursorTarget = cursor.getHeader().getDifficultyTargetAsInteger();
BigInteger newTarget = nextBlock.getDifficultyTargetAsInteger();
if (!cursorTarget.equals(newTarget))
throw new VerificationException("Testnet block transition that is not allowed: " +
Long.toHexString(cursor.getHeader().getDifficultyTarget()) + " vs " +
Long.toHexString(nextBlock.getDifficultyTarget()));
}
} else {
super.checkDifficultyTransitions(storedPrev, nextBlock, blockStore);
}
} }
} }
/*
* Copyright 2018 the bitcoinj-cash developers
*
* 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.bitcoinj.pow;
import org.bitcoinj.core.*;
import org.bitcoinj.store.BlockStore;
import org.bitcoinj.store.BlockStoreException;
import java.math.BigInteger;
public abstract class AbstractPowRulesChecker {
protected NetworkParameters networkParameters;
public AbstractPowRulesChecker(NetworkParameters networkParameters) {
this.networkParameters = networkParameters;
}
public abstract void checkRules(StoredBlock storedPrev, Block nextBlock, BlockStore blockStore,
AbstractBlockChain blockChain) throws VerificationException, BlockStoreException;
public static boolean hasEqualDifficulty(Block prevBlock, Block nextBlock) {
return prevBlock.getDifficultyTarget() == nextBlock.getDifficultyTarget();
}
public static boolean hasEqualDifficulty(long a, BigInteger b) {
return a == Utils.encodeCompactBits(b);
}
}
/*
* Copyright 2018 the bitcoinj-cash developers
*
* 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.bitcoinj.pow;
import org.bitcoinj.core.Block;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.core.StoredBlock;
public abstract class AbstractRuleCheckerFactory {
protected NetworkParameters networkParameters;
public AbstractRuleCheckerFactory(NetworkParameters networkParameters) {
this.networkParameters = networkParameters;
}
public abstract RulesPoolChecker getRuleChecker(StoredBlock storedPrev, Block nextBlock);
protected boolean isTestNet() {
return NetworkParameters.ID_TESTNET.equals(networkParameters.getId());
}
}
/*
* Copyright 2018 the bitcoinj-cash developers
*
* 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.bitcoinj.pow;
import org.bitcoinj.core.*;
import org.bitcoinj.store.BlockStore;
import org.bitcoinj.store.BlockStoreException;
import java.util.ArrayList;
import java.util.List;
public class RulesPoolChecker extends AbstractPowRulesChecker {
private List<AbstractPowRulesChecker> rules;
public RulesPoolChecker(NetworkParameters networkParameters) {