diff --git a/core/src/main/java/org/altcoinj/core/AltcoinBlock.java b/core/src/main/java/org/altcoinj/core/AltcoinBlock.java
new file mode 100644
index 00000000..a3f19bd4
--- /dev/null
+++ b/core/src/main/java/org/altcoinj/core/AltcoinBlock.java
@@ -0,0 +1,229 @@
+/**
+ * Copyright 2011 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.bitcoinj.core;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nullable;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.bitcoinj.core.Coin.FIFTY_COINS;
+import static org.bitcoinj.core.Utils.doubleDigest;
+import static org.bitcoinj.core.Utils.doubleDigestTwoBuffers;
+
+/**
+ *
A block is a group of transactions, and is one of the fundamental data structures of the Bitcoin system.
+ * It records a set of {@link Transaction}s together with some data that links it into a place in the global block
+ * chain, and proves that a difficult calculation was done over its contents. See
+ * the Bitcoin technical paper for
+ * more detail on blocks.
+ *
+ * To get a block, you can either build one from the raw bytes you can get from another implementation, or request one
+ * specifically using {@link Peer#getBlock(Sha256Hash)}, or grab one from a downloaded {@link BlockChain}.
+ */
+public class AltcoinBlock extends org.bitcoinj.core.Block {
+ /** Bit used to indicate that a block contains an AuxPoW section, where the network supports AuxPoW */
+ public static final int BLOCK_FLAG_AUXPOW = (1 << 8);
+
+ private boolean auxpowParsed = false;
+ private boolean auxpowBytesValid = false;
+
+ /** AuxPoW header element, if applicable. */
+ @Nullable private AuxPoW auxpow;
+
+ /** Special case constructor, used for the genesis node, cloneAsHeader and unit tests. */
+ AltcoinBlock(NetworkParameters params) {
+ super(params);
+ }
+
+ /** Constructs a block object from the Bitcoin wire format. */
+ public AltcoinBlock(NetworkParameters params, byte[] payloadBytes) throws ProtocolException {
+ super(params, payloadBytes, 0, false, false, payloadBytes.length);
+ }
+
+ /**
+ * Contruct a block object from the Bitcoin wire format.
+ * @param params NetworkParameters object.
+ * @param parseLazy Whether to perform a full parse immediately or delay until a read is requested.
+ * @param parseRetain Whether to retain the backing byte array for quick reserialization.
+ * If true and the backing byte array is invalidated due to modification of a field then
+ * the cached bytes may be repopulated and retained if the message is serialized again in the future.
+ * @param length The length of message if known. Usually this is provided when deserializing of the wire
+ * as the length will be provided as part of the header. If unknown then set to Message.UNKNOWN_LENGTH
+ * @throws ProtocolException
+ */
+ public AltcoinBlock(NetworkParameters params, byte[] payloadBytes, boolean parseLazy, boolean parseRetain, int length)
+ throws ProtocolException {
+ super(params, payloadBytes, 0, parseLazy, parseRetain, length);
+ }
+
+ /**
+ * Contruct a block object from the Bitcoin wire format. Used in the case of a block
+ * contained within another message (i.e. for AuxPoW header).
+ *
+ * @param params NetworkParameters object.
+ * @param payloadBytes Bitcoin protocol formatted byte array containing message content.
+ * @param offset The location of the first payload byte within the array.
+ * @param parent The message element which contains this block, maybe null for no parent.
+ * @param parseLazy Whether to perform a full parse immediately or delay until a read is requested.
+ * @param parseRetain Whether to retain the backing byte array for quick reserialization.
+ * If true and the backing byte array is invalidated due to modification of a field then
+ * the cached bytes may be repopulated and retained if the message is serialized again in the future.
+ * @param length The length of message if known. Usually this is provided when deserializing of the wire
+ * as the length will be provided as part of the header. If unknown then set to Message.UNKNOWN_LENGTH
+ * @throws ProtocolException
+ */
+ public AltcoinBlock(NetworkParameters params, byte[] payloadBytes, int offset, @Nullable Message parent, boolean parseLazy, boolean parseRetain, int length)
+ throws ProtocolException {
+ // TODO: Keep the parent
+ super(params, payloadBytes, offset, parseLazy, parseRetain, length);
+ }
+
+
+ /**
+ * Construct a block initialized with all the given fields.
+ * @param params Which network the block is for.
+ * @param version This should usually be set to 1 or 2, depending on if the height is in the coinbase input.
+ * @param prevBlockHash Reference to previous block in the chain or {@link Sha256Hash#ZERO_HASH} if genesis.
+ * @param merkleRoot The root of the merkle tree formed by the transactions.
+ * @param time UNIX time when the block was mined.
+ * @param difficultyTarget Number which this block hashes lower than.
+ * @param nonce Arbitrary number to make the block hash lower than the target.
+ * @param transactions List of transactions including the coinbase.
+ */
+ public AltcoinBlock(NetworkParameters params, long version, Sha256Hash prevBlockHash, Sha256Hash merkleRoot, long time,
+ long difficultyTarget, long nonce, List transactions) {
+ super(params, version, prevBlockHash, merkleRoot, time, difficultyTarget, nonce, transactions);
+ }
+
+ @Override
+ protected void parseAuxPoW() throws ProtocolException {
+ if (this.auxpowParsed)
+ return;
+
+ if (this.params.isAuxPoWBlockVersion(this.version)) {
+ // The following is used in dogecoinj, but I don't think we necessarily need it
+ // payload.length >= 160) { // We have at least 2 headers in an Aux block. Workaround for StoredBlocks
+ this.auxpow = new AuxPoW(params, payload, cursor, this, parseLazy, parseRetain);
+ } else {
+ this.auxpow = null;
+ }
+
+ this.auxpowParsed = true;
+ this.auxpowBytesValid = parseRetain;
+ }
+
+ @Override
+ void parse() throws ProtocolException {
+ parseHeader();
+ parseAuxPoW();
+ parseTransactions();
+ length = cursor - offset;
+ }
+
+ @Override
+ protected void parseLite() throws ProtocolException {
+ // Ignore the header since it has fixed length. If length is not provided we will have to
+ // invoke a light parse of transactions to calculate the length.
+ if (length == UNKNOWN_LENGTH) {
+ Preconditions.checkState(parseLazy,
+ "Performing lite parse of block transaction as block was initialised from byte array " +
+ "without providing length. This should never need to happen.");
+ parseTransactions();
+ // TODO: Handle AuxPoW header space
+ length = cursor - offset;
+ } else {
+ transactionBytesValid = !transactionsParsed || parseRetain && length > HEADER_SIZE;
+ }
+ headerBytesValid = !headerParsed || parseRetain && length >= HEADER_SIZE;
+ }
+
+ @Override
+ void writeHeader(OutputStream stream) throws IOException {
+ super.writeHeader(stream);
+ // TODO: Write the AuxPoW header
+ }
+
+ /** Returns a copy of the block, but without any transactions. */
+ @Override
+ public Block cloneAsHeader() {
+ maybeParseHeader();
+ AltcoinBlock block = new AltcoinBlock(params);
+ block.nonce = nonce;
+ block.prevBlockHash = prevBlockHash;
+ block.merkleRoot = getMerkleRoot();
+ block.version = version;
+ block.time = time;
+ block.difficultyTarget = difficultyTarget;
+ block.transactions = null;
+ block.hash = getHash();
+ block.auxpow = auxpow;
+ return block;
+ }
+
+ /** Returns true if the hash of the block is OK (lower than difficulty target). */
+ protected boolean checkProofOfWork(boolean throwException) throws VerificationException {
+ // TODO: Add AuxPoW support
+
+ // This part is key - it is what proves the block was as difficult to make as it claims
+ // to be. Note however that in the context of this function, the block can claim to be
+ // as difficult as it wants to be .... if somebody was able to take control of our network
+ // connection and fork us onto a different chain, they could send us valid blocks with
+ // ridiculously easy difficulty and this function would accept them.
+ //
+ // To prevent this attack from being possible, elsewhere we check that the difficultyTarget
+ // field is of the right value. This requires us to have the preceeding blocks.
+ BigInteger target = getDifficultyTargetAsInteger();
+
+ BigInteger h = getHash().toBigInteger();
+ if (h.compareTo(target) > 0) {
+ // Proof of work check failed!
+ if (throwException)
+ throw new VerificationException("Hash is higher than target: " + getHashAsString() + " vs "
+ + target.toString(16));
+ else
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Checks the block data to ensure it follows the rules laid out in the network parameters. Specifically,
+ * throws an exception if the proof of work is invalid, or if the timestamp is too far from what it should be.
+ * This is not everything that is required for a block to be valid, only what is checkable independent
+ * of the chain and without a transaction index.
+ *
+ * @throws VerificationException
+ */
+ @Override
+ public void verifyHeader() throws VerificationException {
+ super.verifyHeader();
+ }
+}
diff --git a/core/src/main/java/org/altcoinj/core/AuxPoW.java b/core/src/main/java/org/altcoinj/core/AuxPoW.java
new file mode 100644
index 00000000..82484c49
--- /dev/null
+++ b/core/src/main/java/org/altcoinj/core/AuxPoW.java
@@ -0,0 +1,274 @@
+/**
+ * Copyright 2011 Google Inc.
+ * Copyright 2014 Andreas Schildbach
+ * 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.bitcoinj.core;
+
+import org.bitcoinj.crypto.TransactionSignature;
+import org.bitcoinj.script.Script;
+import org.bitcoinj.script.ScriptBuilder;
+import org.bitcoinj.script.ScriptOpCodes;
+import org.bitcoinj.utils.ExchangeRate;
+import org.bitcoinj.wallet.WalletTransaction.Pool;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.primitives.Ints;
+import com.google.common.primitives.Longs;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nullable;
+import java.io.*;
+import java.util.*;
+
+import static org.bitcoinj.core.Utils.*;
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * An AuxPoW header wraps a block header from another coin, enabling the foreign
+ * chain's proof of work to be used for this chain as well.
+ */
+public class AuxPoW extends ChildMessage implements Serializable {
+
+ private static final Logger log = LoggerFactory.getLogger(AuxPoW.class);
+ private static final long serialVersionUID = -8567546957352643140L;
+
+ private Transaction transaction;
+ private Sha256Hash hashBlock;
+ private MerkleBranch coinbaseBranch;
+ private MerkleBranch blockchainBranch;
+ private Block parentBlockHeader;
+
+ // Transactions can be encoded in a way that will use more bytes than is optimal
+ // (due to VarInts having multiple encodings)
+ // MAX_BLOCK_SIZE must be compared to the optimal encoding, not the actual encoding, so when parsing, we keep track
+ // of the size of the ideal encoding in addition to the actual message size (which Message needs) so that Blocks
+ // can properly keep track of optimal encoded size
+ private transient int optimalEncodingMessageSize;
+
+ public AuxPoW(NetworkParameters params, @Nullable Message parent) {
+ super(params);
+ transaction = new Transaction(params);
+ hashBlock = Sha256Hash.ZERO_HASH;
+ coinbaseBranch = new MerkleBranch(params, this);
+ blockchainBranch = new MerkleBranch(params, this);
+ parentBlockHeader = null;
+ }
+
+ /**
+ * Creates an AuxPoW header by reading payload starting from offset bytes in. Length of header is fixed.
+ * @param params NetworkParameters object.1
+ * @param payload Bitcoin protocol formatted byte array containing message content.
+ * @param offset The location of the first payload byte within the array.
+ * @param parent The message element which contains this header.
+ * @param parseLazy Whether to perform a full parse immediately or delay until a read is requested.
+ * @param parseRetain Whether to retain the backing byte array for quick reserialization.
+ * If true and the backing byte array is invalidated due to modification of a field then
+ * the cached bytes may be repopulated and retained if the message is serialized again in the future.
+ * @throws ProtocolException
+ */
+ public AuxPoW(NetworkParameters params, byte[] payload, int offset, Message parent, boolean parseLazy, boolean parseRetain)
+ throws ProtocolException {
+ super(params, payload, offset, parent, parseLazy, parseRetain, Message.UNKNOWN_LENGTH);
+ }
+
+ /**
+ * Creates an AuxPoW header by reading payload starting from offset bytes in. Length of header is fixed.
+ */
+ public AuxPoW(NetworkParameters params, byte[] payload, @Nullable Message parent, boolean parseLazy, boolean parseRetain)
+ throws ProtocolException {
+ super(params, payload, 0, parent, parseLazy, parseRetain, Message.UNKNOWN_LENGTH);
+ }
+
+ @Override
+ protected void parseLite() throws ProtocolException {
+ length = calcLength(payload, offset);
+ cursor = offset + length;
+ }
+
+ protected static int calcLength(byte[] buf, int offset) {
+ VarInt varint;
+ // jump past transaction
+ int cursor = offset + Transaction.calcLength(buf, offset);
+
+ // jump past header hash
+ cursor += 4;
+
+ // Coin base branch
+ cursor += MerkleBranch.calcLength(buf, offset);
+
+ // Block chain branch
+ cursor += MerkleBranch.calcLength(buf, offset);
+
+ // Block header
+ cursor += Block.HEADER_SIZE;
+
+ return cursor - offset + 4;
+ }
+
+ @Override
+ void parse() throws ProtocolException {
+
+ if (parsed)
+ return;
+
+ cursor = offset;
+ transaction = new Transaction(params, payload, cursor, this, parseLazy, parseRetain, Message.UNKNOWN_LENGTH);
+ cursor += transaction.getOptimalEncodingMessageSize();
+ optimalEncodingMessageSize = transaction.getOptimalEncodingMessageSize();
+
+ hashBlock = readHash();
+ optimalEncodingMessageSize += 32; // Add the hash size to the optimal encoding
+
+ coinbaseBranch = new MerkleBranch(params, this, payload, cursor, parseLazy, parseRetain);
+ cursor += coinbaseBranch.getOptimalEncodingMessageSize();
+ optimalEncodingMessageSize += coinbaseBranch.getOptimalEncodingMessageSize();
+
+ blockchainBranch = new MerkleBranch(params, this, payload, cursor, parseLazy, parseRetain);
+ cursor += blockchainBranch.getOptimalEncodingMessageSize();
+ optimalEncodingMessageSize += blockchainBranch.getOptimalEncodingMessageSize();
+
+ // Make a copy of JUST the contained block header, so the block parser doesn't try reading
+ // transactions past the end
+ byte[] blockBytes = Arrays.copyOfRange(payload, cursor, cursor + Block.HEADER_SIZE);
+ cursor += Block.HEADER_SIZE;
+ parentBlockHeader = new AltcoinBlock(params, blockBytes, 0, this, parseLazy, parseRetain, Block.HEADER_SIZE);
+
+ length = cursor - offset;
+ }
+
+ public int getOptimalEncodingMessageSize() {
+ if (optimalEncodingMessageSize != 0)
+ return optimalEncodingMessageSize;
+ maybeParse();
+ if (optimalEncodingMessageSize != 0)
+ return optimalEncodingMessageSize;
+ optimalEncodingMessageSize = getMessageSize();
+ return optimalEncodingMessageSize;
+ }
+
+ @Override
+ public String toString() {
+ return toString(null);
+ }
+
+ /**
+ * A human readable version of the transaction useful for debugging. The format is not guaranteed to be stable.
+ * @param chain If provided, will be used to estimate lock times (if set). Can be null.
+ */
+ public String toString(@Nullable AbstractBlockChain chain) {
+ return transaction.toString(chain);
+ }
+
+ @Override
+ protected void bitcoinSerializeToStream(OutputStream stream) throws IOException {
+ transaction.bitcoinSerialize(stream);
+ stream.write(Utils.reverseBytes(hashBlock.getBytes()));
+
+ coinbaseBranch.bitcoinSerialize(stream);
+ blockchainBranch.bitcoinSerialize(stream);
+
+ parentBlockHeader.bitcoinSerializeToStream(stream);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ AuxPoW input = (AuxPoW) o;
+ if (!transaction.equals(input.transaction)) return false;
+ if (!hashBlock.equals(input.hashBlock)) return false;
+ if (!coinbaseBranch.equals(input.hashBlock)) return false;
+ if (!blockchainBranch.equals(input.hashBlock)) return false;
+ if (!parentBlockHeader.equals(input.hashBlock)) return false;
+ return getHash().equals(input.getHash());
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = 31 * result + transaction.hashCode();
+ result = 31 * result + hashBlock.hashCode();
+ result = 31 * result + coinbaseBranch.hashCode();
+ result = 31 * result + blockchainBranch.hashCode();
+ result = 31 * result + parentBlockHeader.hashCode();
+ return result;
+ }
+
+ /**
+ * Ensure object is fully parsed before invoking java serialization. The backing byte array
+ * is transient so if the object has parseLazy = true and hasn't invoked checkParse yet
+ * then data will be lost during serialization.
+ */
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ maybeParse();
+ out.defaultWriteObject();
+ }
+
+ /**
+ * Get the block header from the parent blockchain. The hash of the header
+ * is the value which should match the difficulty target. Note that blocks are
+ * not necessarily part of the parent blockchain, they simply must be valid
+ * blocks at the difficulty of the child blockchain.
+ */
+ public Block getParentBlockHeader() {
+ return parentBlockHeader;
+ }
+
+ /**
+ * Get the coinbase transaction from the AuxPoW header. This should contain a
+ * reference back to the block hash in its input scripts, to prove that the
+ * transaction was created after the block.
+ */
+ public Transaction getCoinbase() {
+ return transaction;
+ }
+
+ /**
+ * Get the Merkle branch used to connect the AuXPow header with this blockchain.
+ */
+ public MerkleBranch getBlockchainBranch() {
+ return blockchainBranch;
+ }
+
+ /**
+ * Get the Merkle branch used to connect the coinbase transaction with this blockchain.
+ */
+ public MerkleBranch getCoinbaseBranch() {
+ return coinbaseBranch;
+ }
+
+ /**
+ * Checks the transaction contents for sanity, in ways that can be done in a standalone manner.
+ * Does not perform all checks on a transaction such as whether the inputs are already spent.
+ * Specifically this method verifies:
+ *
+ *
+ * - That there is at least one input and output.
+ * - That the serialized size is not larger than the max block size.
+ * - That no outputs have negative value.
+ * - That the outputs do not sum to larger than the max allowed quantity of coin in the system.
+ * - If the tx is a coinbase tx, the coinbase scriptSig size is within range. Otherwise that there are no
+ * coinbase inputs in the tx.
+ *
+ *
+ * @throws VerificationException
+ */
+ public void verify() throws VerificationException {
+ maybeParse();
+ // TODO: Verify the AuxPoW data
+ }
+}
diff --git a/core/src/main/java/org/altcoinj/core/MerkleBranch.java b/core/src/main/java/org/altcoinj/core/MerkleBranch.java
new file mode 100644
index 00000000..9c6131d1
--- /dev/null
+++ b/core/src/main/java/org/altcoinj/core/MerkleBranch.java
@@ -0,0 +1,223 @@
+/**
+ * Copyright 2011 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.bitcoinj.core;
+
+import static org.bitcoinj.core.Utils.doubleDigestTwoBuffers;
+import static org.bitcoinj.core.Utils.reverseBytes;
+
+import javax.annotation.Nullable;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A Merkle branch contains the hashes from a leaf of a Merkle tree
+ * up to its root, plus a bitset used to define how the hashes are applied.
+ * Given the hash of the leaf, this can be used to calculate the tree
+ * root. This is useful for proving that a leaf belongs to a given tree.
+ */
+public class MerkleBranch extends ChildMessage implements Serializable {
+ private static final long serialVersionUID = 2;
+
+ // Merkle branches can be encoded in a way that will use more bytes than is optimal
+ // (due to VarInts having multiple encodings)
+ // MAX_BLOCK_SIZE must be compared to the optimal encoding, not the actual encoding, so when parsing, we keep track
+ // of the size of the ideal encoding in addition to the actual message size (which Message needs) so that Blocks
+ // can properly keep track of optimal encoded size
+ private transient int optimalEncodingMessageSize;
+
+ private List branchHashes;
+ private long branchSideMask;
+
+ public MerkleBranch(NetworkParameters params, @Nullable ChildMessage parent) {
+ super(params);
+ setParent(parent);
+
+ this.branchHashes = new ArrayList();
+ this.branchSideMask = 0;
+ }
+
+ /**
+ * Deserializes an input message. This is usually part of a merkle branch message.
+ */
+ public MerkleBranch(NetworkParameters params, @Nullable ChildMessage parent, byte[] payload, int offset) throws ProtocolException {
+ super(params, payload, offset);
+ setParent(parent);
+ }
+
+ /**
+ * Deserializes an input message. This is usually part of a merkle branch message.
+ * @param params NetworkParameters object.
+ * @param payload Bitcoin protocol formatted byte array containing message content.
+ * @param offset The location of the first payload byte within the array.
+ * @param parseLazy Whether to perform a full parse immediately or delay until a read is requested.
+ * @param parseRetain Whether to retain the backing byte array for quick reserialization.
+ * If true and the backing byte array is invalidated due to modification of a field then
+ * the cached bytes may be repopulated and retained if the message is serialized again in the future.
+ * as the length will be provided as part of the header. If unknown then set to Message.UNKNOWN_LENGTH
+ * @throws ProtocolException
+ */
+ public MerkleBranch(NetworkParameters params, ChildMessage parent, byte[] payload, int offset,
+ boolean parseLazy, boolean parseRetain)
+ throws ProtocolException {
+ super(params, payload, offset, parent, parseLazy, parseRetain, UNKNOWN_LENGTH);
+ }
+
+ public MerkleBranch(NetworkParameters params, @Nullable ChildMessage parent,
+ final List hashes, final long branchSideMask) {
+ super(params);
+ setParent(parent);
+
+ this.branchHashes = hashes;
+ this.branchSideMask = branchSideMask;
+ }
+
+ @Override
+ protected void parseLite() throws ProtocolException {
+ length = calcLength(payload, offset);
+ cursor = offset + length;
+ }
+
+ protected static int calcLength(byte[] buf, int offset) {
+ VarInt varint = new VarInt(buf, offset);
+
+ return ((int) varint.value) * 4 + 4;
+ }
+
+ @Override
+ void parse() throws ProtocolException {
+ if (parsed)
+ return;
+
+ cursor = offset;
+
+ final int hashCount = (int) readVarInt();
+ optimalEncodingMessageSize += VarInt.sizeOf(hashCount);
+ branchHashes = new ArrayList(hashCount);
+ for (int hashIdx = 0; hashIdx < hashCount; hashIdx++) {
+ branchHashes.add(readHash());
+ }
+ optimalEncodingMessageSize += 32 * hashCount;
+ branchSideMask = readUint32();
+ optimalEncodingMessageSize += 4;
+ }
+
+ @Override
+ protected void bitcoinSerializeToStream(OutputStream stream) throws IOException {
+ stream.write(new VarInt(branchHashes.size()).encode());
+ for (Sha256Hash hash: branchHashes) {
+ stream.write(Utils.reverseBytes(hash.getBytes()));
+ }
+ Utils.uint32ToByteStreamLE(branchSideMask, stream);
+ }
+
+ /**
+ * Calculate the merkle branch root based on the supplied hashes and the given leaf hash.
+ * Used to verify that the given leaf and root are part of the same tree.
+ */
+ public Sha256Hash calculateMerkleRoot(final Sha256Hash leaf) {
+ byte[] target = reverseBytes(leaf.getBytes());
+ long mask = branchSideMask;
+
+ for (Sha256Hash hash: branchHashes) {
+ target = (mask & 1) == 0
+ ? doubleDigestTwoBuffers(target, 0, 32, reverseBytes(hash.getBytes()), 0, 32)
+ : doubleDigestTwoBuffers(reverseBytes(hash.getBytes()), 0, 32, target, 0, 32);
+ mask >>= 1;
+ }
+ return new Sha256Hash(reverseBytes(target));
+ }
+
+ /**
+ * Get the hashes which make up this branch.
+ */
+ public List getHashes() {
+ return Collections.unmodifiableList(this.branchHashes);
+ }
+
+ /**
+ * Get the number of hashes in this branch.
+ */
+ public int getSize() {
+ return branchHashes.size();
+ }
+
+ public int getOptimalEncodingMessageSize() {
+ if (optimalEncodingMessageSize != 0)
+ return optimalEncodingMessageSize;
+ maybeParse();
+ if (optimalEncodingMessageSize != 0)
+ return optimalEncodingMessageSize;
+ optimalEncodingMessageSize = getMessageSize();
+ return optimalEncodingMessageSize;
+ }
+
+ /**
+ * Returns a human readable debug string.
+ */
+ @Override
+ public String toString() {
+ return "Merkle branch";
+ }
+
+ /**
+ * Ensure object is fully parsed before invoking java serialization. The backing byte array
+ * is transient so if the object has parseLazy = true and hasn't invoked checkParse yet
+ * then data will be lost during serialization.
+ */
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ maybeParse();
+ out.defaultWriteObject();
+ }
+
+ /**
+ * Should check that the merkle branch side bits are not wider than the
+ * provided hashes.
+ * @throws VerificationException If the branch is invalid.
+ */
+ public void verify() throws VerificationException {
+ maybeParse();
+ // TODO: Check the flags make sense for the inputs
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ MerkleBranch input = (MerkleBranch) o;
+
+ if (!branchHashes.equals(input.branchHashes)) return false;
+ if (branchSideMask != input.branchSideMask) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = 31 * result + branchHashes.hashCode();
+ result = 31 * result + (int) branchSideMask;
+ return result;
+ }
+}
diff --git a/core/src/main/java/org/altcoinj/params/AbstractDogecoinParams.java b/core/src/main/java/org/altcoinj/params/AbstractDogecoinParams.java
index 2b8168c4..5e70bbf4 100644
--- a/core/src/main/java/org/altcoinj/params/AbstractDogecoinParams.java
+++ b/core/src/main/java/org/altcoinj/params/AbstractDogecoinParams.java
@@ -16,9 +16,14 @@
package org.altcoinj.params;
-import org.altcoinj.core.NetworkParameters;
-import org.altcoinj.core.Sha256Hash;
-import org.altcoinj.core.Utils;
+import java.math.RoundingMode;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.bitcoinj.core.NetworkParameters;
+import org.bitcoinj.core.Sha256Hash;
+import org.bitcoinj.core.Utils;
+import org.bitcoinj.utils.MonetaryFormat;
import static com.google.common.base.Preconditions.checkState;
@@ -26,27 +31,55 @@ import static com.google.common.base.Preconditions.checkState;
* Parameters for the main Dogecoin production network on which people trade goods and services.
*/
public class AbstractDogecoinParams extends NetworkParameters {
+ /** Standard format for the DOGE denomination. */
+ public static final MonetaryFormat DOGE;
+ /** Standard format for the mDOGE denomination. */
+ public static final MonetaryFormat MDOGE;
+ /** Standard format for the Koinu denomination. */
+ public static final MonetaryFormat KOINU;
+
public static final int DOGE_TARGET_TIMESPAN = 4 * 60 * 60; // 4 hours per difficulty cycle, on average.
public static final int DOGE_TARGET_TIMESPAN_NEW = 60; // 60s per difficulty cycle, on average. Kicks in after block 145k.
public static final int DOGE_TARGET_SPACING = 1 * 60; // 1 minute per block.
- public static final int DOGE_INTERVAL = TARGET_TIMESPAN / TARGET_SPACING;
- public static final int DOGE_INTERVAL_NEW = TARGET_TIMESPAN_NEW / TARGET_SPACING;
+ public static final int DOGE_INTERVAL = DOGE_TARGET_TIMESPAN / DOGE_TARGET_SPACING;
+ public static final int DOGE_INTERVAL_NEW = DOGE_TARGET_TIMESPAN_NEW / DOGE_TARGET_SPACING;
+
+ /** Currency code for base 1 Dogecoin. */
+ public static final String CODE_DOGE = "DOGE";
+ /** Currency code for base 1/1,000 Dogecoin. */
+ public static final String CODE_MDOGE = "mDOGE";
+ /** Currency code for base 1/100,000,000 Dogecoin. */
+ public static final String CODE_KOINU = "Koinu";
+
+ private static final Map CURRENCY_CODES = new HashMap();
+
+ static {
+ CURRENCY_CODES.put(0, CODE_DOGE);
+ CURRENCY_CODES.put(3, CODE_MDOGE);
+ CURRENCY_CODES.put(8, CODE_KOINU);
+
+ DOGE = MonetaryFormat.BTC.replaceCodes(CURRENCY_CODES);
+ MDOGE = DOGE.shift(3).minDecimals(2).optionalDecimals(2);
+ KOINU = DOGE.shift(6).minDecimals(0).optionalDecimals(2);
+ }
/** The string returned by getId() for the main, production network where people trade things. */
public static final String ID_DOGE_MAINNET = "org.dogecoin.production";
/** The string returned by getId() for the testnet. */
public static final String ID_DOGE_TESTNET = "org.dogecoin.test";
- protected int newInterval;
- protected int newTargetTimespan;
+ protected final int newInterval;
+ protected final int newTargetTimespan;
+ protected final int diffChangeTarget;
- public AbstractDogecoinParams() {
+ public AbstractDogecoinParams(final int setDiffChangeTarget) {
super();
interval = DOGE_INTERVAL;
newInterval = DOGE_INTERVAL_NEW;
targetTimespan = DOGE_TARGET_TIMESPAN;
newTargetTimespan = DOGE_TARGET_TIMESPAN_NEW;
maxTarget = Utils.decodeCompactBits(0x1e0fffffL);
+ diffChangeTarget = setDiffChangeTarget;
packetMagic = 0xc0c0c0c0;
bip32HeaderPub = 0x0488C42E; //The 4 byte header that serializes in base58 to "xpub". (?)
@@ -67,5 +100,7 @@ public class AbstractDogecoinParams extends NetworkParameters {
return newTargetTimespan;
}
- public MonetaryFormat
+ public MonetaryFormat getMonetaryFormat() {
+ return DOGE;
+ }
}
diff --git a/core/src/main/java/org/altcoinj/params/DogecoinMainNetParams.java b/core/src/main/java/org/altcoinj/params/DogecoinMainNetParams.java
index 41766852..149d9902 100644
--- a/core/src/main/java/org/altcoinj/params/DogecoinMainNetParams.java
+++ b/core/src/main/java/org/altcoinj/params/DogecoinMainNetParams.java
@@ -16,9 +16,12 @@
package org.altcoinj.params;
-import org.altcoinj.core.NetworkParameters;
-import org.altcoinj.core.Sha256Hash;
-import org.altcoinj.core.Utils;
+import java.util.Map;
+
+import org.bitcoinj.core.NetworkParameters;
+import org.bitcoinj.core.Sha256Hash;
+import org.bitcoinj.core.Utils;
+import org.bitcoinj.utils.MonetaryFormat;
import static com.google.common.base.Preconditions.checkState;
@@ -26,8 +29,10 @@ import static com.google.common.base.Preconditions.checkState;
* Parameters for the main production network on which people trade goods and services.
*/
public class DogecoinMainNetParams extends AbstractDogecoinParams {
+ protected static final int DIFFICULTY_CHANGE_TARGET = 145000;
+
public DogecoinMainNetParams() {
- super();
+ super(DIFFICULTY_CHANGE_TARGET);
dumpedPrivateKeyHeader = 158; //This is always addressHeader + 128
addressHeader = 30;
p2shHeader = 22;
@@ -43,8 +48,6 @@ public class DogecoinMainNetParams extends AbstractDogecoinParams {
subsidyDecreaseBlockCount = 100000;
spendableCoinbaseDepth = 100;
- diffChangeTarget = 145000;
-
String genesisHash = genesisBlock.getHashAsString();
checkState(genesisHash.equals("1a91e3dace36e2be3bf030a65679fe821aa1d6ef92e7c9902eb318182c355691"),
genesisHash);
diff --git a/core/src/main/java/org/altcoinj/params/DogecoinTestNet3Params.java b/core/src/main/java/org/altcoinj/params/DogecoinTestNet3Params.java
index 60de54ca..6b654a19 100644
--- a/core/src/main/java/org/altcoinj/params/DogecoinTestNet3Params.java
+++ b/core/src/main/java/org/altcoinj/params/DogecoinTestNet3Params.java
@@ -17,8 +17,8 @@
package org.altcoinj.params;
-import org.altcoinj.core.NetworkParameters;
-import org.altcoinj.core.Utils;
+import org.bitcoinj.core.NetworkParameters;
+import org.bitcoinj.core.Utils;
import org.spongycastle.util.encoders.Hex;
import static com.google.common.base.Preconditions.checkState;
@@ -28,8 +28,10 @@ import static com.google.common.base.Preconditions.checkState;
* and testing of applications and new Bitcoin versions.
*/
public class DogecoinTestNet3Params extends AbstractDogecoinParams {
+ protected static final int DIFFICULTY_CHANGE_TARGET = 145000;
+
public DogecoinTestNet3Params() {
- super();
+ super(DIFFICULTY_CHANGE_TARGET);
id = ID_DOGE_TESTNET;
// Genesis hash is bb0a78264637406b6360aad926284d544d7049f45189db5664f3c4d07350559e
packetMagic = 0xfcc1b7dc;
@@ -49,8 +51,6 @@ public class DogecoinTestNet3Params extends AbstractDogecoinParams {
checkState(genesisHash.equals("bb0a78264637406b6360aad926284d544d7049f45189db5664f3c4d07350559e"));
alertSigningKey = Hex.decode("042756726da3c7ef515d89212ee1705023d14be389e25fe15611585661b9a20021908b2b80a3c7200a0139dd2b26946606aab0eef9aa7689a6dc2c7eee237fa834");
- diffChangeTarget = 145000;
-
dnsSeeds = new String[] {
"testnets.chain.so" // Chain.so
};
@@ -61,7 +61,7 @@ public class DogecoinTestNet3Params extends AbstractDogecoinParams {
private static DogecoinTestNet3Params instance;
public static synchronized DogecoinTestNet3Params get() {
if (instance == null) {
- instance = new TestNet3Params();
+ instance = new DogecoinTestNet3Params();
}
return instance;
}
diff --git a/core/src/main/java/org/altcoinj/protocols/payments/PaymentProtocol.java b/core/src/main/java/org/altcoinj/protocols/payments/PaymentProtocol.java
deleted file mode 100644
index dfc1ce02..00000000
--- a/core/src/main/java/org/altcoinj/protocols/payments/PaymentProtocol.java
+++ /dev/null
@@ -1,423 +0,0 @@
-/**
- * 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 com.dogecoin.dogecoinj.protocols.payments;
-
-import com.dogecoin.dogecoinj.core.*;
-import com.dogecoin.dogecoinj.crypto.X509Utils;
-import com.dogecoin.dogecoinj.script.ScriptBuilder;
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import com.google.protobuf.ByteString;
-import com.google.protobuf.InvalidProtocolBufferException;
-import org.bitcoin.protocols.payments.Protos;
-
-import javax.annotation.Nullable;
-import java.io.Serializable;
-import java.security.*;
-import java.security.cert.*;
-import java.security.cert.Certificate;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Utility methods and constants for working with
- * BIP 70 aka the payment protocol. These are low level wrappers around the protocol buffers. If you're implementing
- * a wallet app, look at {@link PaymentSession} for a higher level API that should simplify working with the protocol.
- *
- * BIP 70 defines a binary, protobuf based protocol that runs directly between sender and receiver of funds. Payment
- * protocol data does not flow over the Bitcoin P2P network or enter the block chain. It's instead for data that is only
- * of interest to the parties involved but isn't otherwise needed for consensus.
- */
-public class PaymentProtocol {
-
- // MIME types as defined in DIP71.
- public static final String MIMETYPE_PAYMENTREQUEST = "application/vnd.doge.payment.request";
- public static final String MIMETYPE_PAYMENT = "application/vnd.doge.payment.payment";
- public static final String MIMETYPE_PAYMENTACK = "application/vnd.doge.payment.ack";
-
- /**
- * Create a payment request with one standard pay to address output. You may want to sign the request using
- * {@link #signPaymentRequest}. Use {@link Protos.PaymentRequest.Builder#build} to get the actual payment
- * request.
- *
- * @param params network parameters
- * @param amount amount of coins to request, or null
- * @param toAddress address to request coins to
- * @param memo arbitrary, user readable memo, or null if none
- * @param paymentUrl URL to send payment message to, or null if none
- * @param merchantData arbitrary merchant data, or null if none
- * @return created payment request, in its builder form
- */
- public static Protos.PaymentRequest.Builder createPaymentRequest(NetworkParameters params,
- @Nullable Coin amount, Address toAddress, @Nullable String memo, @Nullable String paymentUrl,
- @Nullable byte[] merchantData) {
- return createPaymentRequest(params, ImmutableList.of(createPayToAddressOutput(amount, toAddress)), memo,
- paymentUrl, merchantData);
- }
-
- /**
- * Create a payment request. You may want to sign the request using {@link #signPaymentRequest}. Use
- * {@link Protos.PaymentRequest.Builder#build} to get the actual payment request.
- *
- * @param params network parameters
- * @param outputs list of outputs to request coins to
- * @param memo arbitrary, user readable memo, or null if none
- * @param paymentUrl URL to send payment message to, or null if none
- * @param merchantData arbitrary merchant data, or null if none
- * @return created payment request, in its builder form
- */
- public static Protos.PaymentRequest.Builder createPaymentRequest(NetworkParameters params,
- List outputs, @Nullable String memo, @Nullable String paymentUrl,
- @Nullable byte[] merchantData) {
- final Protos.PaymentDetails.Builder paymentDetails = Protos.PaymentDetails.newBuilder();
- paymentDetails.setNetwork(params.getPaymentProtocolId());
- for (Protos.Output output : outputs)
- paymentDetails.addOutputs(output);
- if (memo != null)
- paymentDetails.setMemo(memo);
- if (paymentUrl != null)
- paymentDetails.setPaymentUrl(paymentUrl);
- if (merchantData != null)
- paymentDetails.setMerchantData(ByteString.copyFrom(merchantData));
- paymentDetails.setTime(Utils.currentTimeSeconds());
-
- final Protos.PaymentRequest.Builder paymentRequest = Protos.PaymentRequest.newBuilder();
- paymentRequest.setSerializedPaymentDetails(paymentDetails.build().toByteString());
- return paymentRequest;
- }
-
- /**
- * Parse a payment request.
- *
- * @param paymentRequest payment request to parse
- * @return instance of {@link PaymentSession}, used as a value object
- * @throws PaymentProtocolException
- */
- public static PaymentSession parsePaymentRequest(Protos.PaymentRequest paymentRequest)
- throws PaymentProtocolException {
- return new PaymentSession(paymentRequest, false, null);
- }
-
- /**
- * Sign the provided payment request.
- *
- * @param paymentRequest Payment request to sign, in its builder form.
- * @param certificateChain Certificate chain to send with the payment request, ordered from client certificate to root
- * certificate. The root certificate itself may be omitted.
- * @param privateKey The key to sign with. Must match the public key from the first certificate of the certificate chain.
- */
- public static void signPaymentRequest(Protos.PaymentRequest.Builder paymentRequest,
- X509Certificate[] certificateChain, PrivateKey privateKey) {
- try {
- final Protos.X509Certificates.Builder certificates = Protos.X509Certificates.newBuilder();
- for (final Certificate certificate : certificateChain)
- certificates.addCertificate(ByteString.copyFrom(certificate.getEncoded()));
-
- paymentRequest.setPkiType("x509+sha256");
- paymentRequest.setPkiData(certificates.build().toByteString());
- paymentRequest.setSignature(ByteString.EMPTY);
- final Protos.PaymentRequest paymentRequestToSign = paymentRequest.build();
-
- final String algorithm;
- if (privateKey.getAlgorithm().equalsIgnoreCase("RSA"))
- algorithm = "SHA256withRSA";
- else
- throw new IllegalStateException(privateKey.getAlgorithm());
-
- final Signature signature = Signature.getInstance(algorithm);
- signature.initSign(privateKey);
- signature.update(paymentRequestToSign.toByteArray());
-
- paymentRequest.setSignature(ByteString.copyFrom(signature.sign()));
- } catch (final GeneralSecurityException x) {
- // Should never happen so don't make users have to think about it.
- throw new RuntimeException(x);
- }
- }
-
- /**
- * Uses the provided PKI method to find the corresponding public key and verify the provided signature.
- *
- * @param paymentRequest Payment request to verify.
- * @param trustStore KeyStore of trusted root certificate authorities.
- * @return verification data, or null if no PKI method was specified in the {@link Protos.PaymentRequest}.
- * @throws PaymentProtocolException if payment request could not be verified.
- */
- public static @Nullable PkiVerificationData verifyPaymentRequestPki(Protos.PaymentRequest paymentRequest, KeyStore trustStore)
- throws PaymentProtocolException {
- List certs = null;
- try {
- final String pkiType = paymentRequest.getPkiType();
- if (pkiType.equals("none"))
- // Nothing to verify. Everything is fine. Move along.
- return null;
-
- String algorithm;
- if (pkiType.equals("x509+sha256"))
- algorithm = "SHA256withRSA";
- else if (pkiType.equals("x509+sha1"))
- algorithm = "SHA1withRSA";
- else
- throw new PaymentProtocolException.InvalidPkiType("Unsupported PKI type: " + pkiType);
-
- Protos.X509Certificates protoCerts = Protos.X509Certificates.parseFrom(paymentRequest.getPkiData());
- if (protoCerts.getCertificateCount() == 0)
- throw new PaymentProtocolException.InvalidPkiData("No certificates provided in message: server config error");
-
- // Parse the certs and turn into a certificate chain object. Cert factories can parse both DER and base64.
- // The ordering of certificates is defined by the payment protocol spec to be the same as what the Java
- // crypto API requires - convenient!
- CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
- certs = Lists.newArrayList();
- for (ByteString bytes : protoCerts.getCertificateList())
- certs.add((X509Certificate) certificateFactory.generateCertificate(bytes.newInput()));
- CertPath path = certificateFactory.generateCertPath(certs);
-
- // Retrieves the most-trusted CAs from keystore.
- PKIXParameters params = new PKIXParameters(trustStore);
- // Revocation not supported in the current version.
- params.setRevocationEnabled(false);
-
- // Now verify the certificate chain is correct and trusted. This let's us get an identity linked pubkey.
- CertPathValidator validator = CertPathValidator.getInstance("PKIX");
- PKIXCertPathValidatorResult result = (PKIXCertPathValidatorResult) validator.validate(path, params);
- PublicKey publicKey = result.getPublicKey();
- // OK, we got an identity, now check it was used to sign this message.
- Signature signature = Signature.getInstance(algorithm);
- // Note that we don't use signature.initVerify(certs.get(0)) here despite it being the most obvious
- // way to set it up, because we don't care about the constraints specified on the certificates: any
- // cert that links a key to a domain name or other identity will do for us.
- signature.initVerify(publicKey);
- Protos.PaymentRequest.Builder reqToCheck = paymentRequest.toBuilder();
- reqToCheck.setSignature(ByteString.EMPTY);
- signature.update(reqToCheck.build().toByteArray());
- if (!signature.verify(paymentRequest.getSignature().toByteArray()))
- throw new PaymentProtocolException.PkiVerificationException("Invalid signature, this payment request is not valid.");
-
- // Signature verifies, get the names from the identity we just verified for presentation to the user.
- final X509Certificate cert = certs.get(0);
- String displayName = X509Utils.getDisplayNameFromCertificate(cert, true);
- if (displayName == null)
- throw new PaymentProtocolException.PkiVerificationException("Could not extract name from certificate");
- // Everything is peachy. Return some useful data to the caller.
- return new PkiVerificationData(displayName, publicKey, result.getTrustAnchor());
- } catch (InvalidProtocolBufferException e) {
- // Data structures are malformed.
- throw new PaymentProtocolException.InvalidPkiData(e);
- } catch (CertificateException e) {
- // The X.509 certificate data didn't parse correctly.
- throw new PaymentProtocolException.PkiVerificationException(e);
- } catch (NoSuchAlgorithmException e) {
- // Should never happen so don't make users have to think about it. PKIX is always present.
- throw new RuntimeException(e);
- } catch (InvalidAlgorithmParameterException e) {
- throw new RuntimeException(e);
- } catch (CertPathValidatorException e) {
- // The certificate chain isn't known or trusted, probably, the server is using an SSL root we don't
- // know about and the user needs to upgrade to a new version of the software (or import a root cert).
- throw new PaymentProtocolException.PkiVerificationException(e, certs);
- } catch (InvalidKeyException e) {
- // Shouldn't happen if the certs verified correctly.
- throw new PaymentProtocolException.PkiVerificationException(e);
- } catch (SignatureException e) {
- // Something went wrong during hashing (yes, despite the name, this does not mean the sig was invalid).
- throw new PaymentProtocolException.PkiVerificationException(e);
- } catch (KeyStoreException e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * Information about the X.509 signature's issuer and subject.
- */
- public static class PkiVerificationData {
- /** Display name of the payment requestor, could be a domain name, email address, legal name, etc */
- public final String displayName;
- /** SSL public key that was used to sign. */
- public final PublicKey merchantSigningKey;
- /** Object representing the CA that verified the merchant's ID */
- public final TrustAnchor rootAuthority;
- /** String representing the display name of the CA that verified the merchant's ID */
- public final String rootAuthorityName;
-
- private PkiVerificationData(@Nullable String displayName, PublicKey merchantSigningKey,
- TrustAnchor rootAuthority) throws PaymentProtocolException.PkiVerificationException {
- try {
- this.displayName = displayName;
- this.merchantSigningKey = merchantSigningKey;
- this.rootAuthority = rootAuthority;
- this.rootAuthorityName = X509Utils.getDisplayNameFromCertificate(rootAuthority.getTrustedCert(), true);
- } catch (CertificateParsingException x) {
- throw new PaymentProtocolException.PkiVerificationException(x);
- }
- }
-
- @Override
- public String toString() {
- return Objects.toStringHelper(this)
- .add("displayName", displayName)
- .add("rootAuthorityName", rootAuthorityName)
- .add("merchantSigningKey", merchantSigningKey)
- .add("rootAuthority", rootAuthority)
- .toString();
- }
- }
-
- /**
- * Create a payment message with one standard pay to address output.
- *
- * @param transactions one or more transactions that satisfy the requested outputs.
- * @param refundAmount amount of coins to request as a refund, or null if no refund.
- * @param refundAddress address to refund coins to
- * @param memo arbitrary, user readable memo, or null if none
- * @param merchantData arbitrary merchant data, or null if none
- * @return created payment message
- */
- public static Protos.Payment createPaymentMessage(List transactions,
- @Nullable Coin refundAmount, @Nullable Address refundAddress, @Nullable String memo,
- @Nullable byte[] merchantData) {
- if (refundAddress != null) {
- if (refundAmount == null)
- throw new IllegalArgumentException("Specify refund amount if refund address is specified.");
- return createPaymentMessage(transactions,
- ImmutableList.of(createPayToAddressOutput(refundAmount, refundAddress)), memo, merchantData);
- } else {
- return createPaymentMessage(transactions, null, memo, merchantData);
- }
- }
-
- /**
- * Create a payment message. This wraps up transaction data along with anything else useful for making a payment.
- *
- * @param transactions transactions to include with the payment message
- * @param refundOutputs list of outputs to refund coins to, or null
- * @param memo arbitrary, user readable memo, or null if none
- * @param merchantData arbitrary merchant data, or null if none
- * @return created payment message
- */
- public static Protos.Payment createPaymentMessage(List transactions,
- @Nullable List refundOutputs, @Nullable String memo, @Nullable byte[] merchantData) {
- Protos.Payment.Builder builder = Protos.Payment.newBuilder();
- for (Transaction transaction : transactions) {
- transaction.verify();
- builder.addTransactions(ByteString.copyFrom(transaction.unsafeBitcoinSerialize()));
- }
- if (refundOutputs != null) {
- for (Protos.Output output : refundOutputs)
- builder.addRefundTo(output);
- }
- if (memo != null)
- builder.setMemo(memo);
- if (merchantData != null)
- builder.setMerchantData(ByteString.copyFrom(merchantData));
- return builder.build();
- }
-
- /**
- * Parse transactions from payment message.
- *
- * @param params network parameters (needed for transaction deserialization)
- * @param paymentMessage payment message to parse
- * @return list of transactions
- */
- public static List parseTransactionsFromPaymentMessage(NetworkParameters params,
- Protos.Payment paymentMessage) {
- final List transactions = new ArrayList(paymentMessage.getTransactionsCount());
- for (final ByteString transaction : paymentMessage.getTransactionsList())
- transactions.add(new Transaction(params, transaction.toByteArray()));
- return transactions;
- }
-
- /**
- * Message returned by the merchant in response to a Payment message.
- */
- public static class Ack {
- @Nullable private final String memo;
-
- Ack(@Nullable String memo) {
- this.memo = memo;
- }
-
- /**
- * Returns the memo included by the merchant in the payment ack. This message is typically displayed to the user
- * as a notification (e.g. "Your payment was received and is being processed"). If none was provided, returns
- * null.
- */
- @Nullable public String getMemo() {
- return memo;
- }
- }
-
- /**
- * Create a payment ack.
- *
- * @param paymentMessage payment message to send with the ack
- * @param memo arbitrary, user readable memo, or null if none
- * @return created payment ack
- */
- public static Protos.PaymentACK createPaymentAck(Protos.Payment paymentMessage, @Nullable String memo) {
- final Protos.PaymentACK.Builder builder = Protos.PaymentACK.newBuilder();
- builder.setPayment(paymentMessage);
- if (memo != null)
- builder.setMemo(memo);
- return builder.build();
- }
-
- /**
- * Parse payment ack into an object.
- */
- public static Ack parsePaymentAck(Protos.PaymentACK paymentAck) {
- final String memo = paymentAck.hasMemo() ? paymentAck.getMemo() : null;
- return new Ack(memo);
- }
-
- /**
- * Create a standard pay to address output for usage in {@link #createPaymentRequest} and
- * {@link #createPaymentMessage}.
- *
- * @param amount amount to pay, or null
- * @param address address to pay to
- * @return output
- */
- public static Protos.Output createPayToAddressOutput(@Nullable Coin amount, Address address) {
- Protos.Output.Builder output = Protos.Output.newBuilder();
- if (amount != null) {
- if (amount.compareTo(NetworkParameters.MAX_MONEY) > 0)
- throw new IllegalArgumentException("Amount too big: " + amount);
- output.setAmount(amount.value);
- } else {
- output.setAmount(0);
- }
- output.setScript(ByteString.copyFrom(ScriptBuilder.createOutputScript(address).getProgram()));
- return output.build();
- }
-
- /**
- * Value object to hold amount/script pairs.
- */
- public static class Output implements Serializable {
- public final @Nullable Coin amount;
- public final byte[] scriptData;
-
- public Output(@Nullable Coin amount, byte[] scriptData) {
- this.amount = amount;
- this.scriptData = scriptData;
- }
- }
-}
diff --git a/core/src/main/java/org/altcoinj/protocols/payments/package-info.java b/core/src/main/java/org/altcoinj/protocols/payments/package-info.java
deleted file mode 100644
index fb419735..00000000
--- a/core/src/main/java/org/altcoinj/protocols/payments/package-info.java
+++ /dev/null
@@ -1,5 +0,0 @@
-/**
- * The BIP70 payment protocol wraps Bitcoin transactions and adds various useful features like memos, refund addresses
- * and authentication.
- */
-package com.dogecoin.dogecoinj.protocols.payments;
\ No newline at end of file
diff --git a/core/src/main/java/org/altcoinj/utils/MonetaryFormat.java b/core/src/main/java/org/altcoinj/utils/MonetaryFormat.java
deleted file mode 100644
index 1b090c1b..00000000
--- a/core/src/main/java/org/altcoinj/utils/MonetaryFormat.java
+++ /dev/null
@@ -1,451 +0,0 @@
-/*
- * 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.altcoinj.utils;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.math.LongMath.checkedMultiply;
-import static com.google.common.math.LongMath.checkedPow;
-import static com.google.common.math.LongMath.divide;
-
-import java.math.RoundingMode;
-import java.text.DecimalFormatSymbols;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-import org.altcoinj.core.Coin;
-import org.altcoinj.core.Monetary;
-
-/**
- *
- * Utility for formatting and parsing coin values to and from human readable form.
- *
- *
- *
- * MonetaryFormat instances are immutable. Invoking a configuration method has no effect on the receiving instance; you
- * must store and use the new instance it returns, instead. Instances are thread safe, so they may be stored safely as
- * static constants.
- *
- */
-public class DogecoinMonetaryFormat extends org.bitcoinj.utils.MonetaryFormat {
-
- /** Standard format for the BTC denomination. */
- public static final MonetaryFormat BTC = new MonetaryFormat().shift(0).minDecimals(2).repeatOptionalDecimals(2, 3);
- /** Standard format for the mBTC denomination. */
- public static final MonetaryFormat MBTC = new MonetaryFormat().shift(3).minDecimals(2).optionalDecimals(2);
- /** Standard format for the µBTC denomination. */
- public static final MonetaryFormat UBTC = new MonetaryFormat().shift(6).minDecimals(0).optionalDecimals(2);
- /** Standard format for fiat amounts. */
- public static final MonetaryFormat FIAT = new MonetaryFormat().shift(0).minDecimals(2).repeatOptionalDecimals(2, 1);
- /** Currency code for base 1 Dogecoin. */
- public static final String CODE_BTC = "DOGE";
- /** Currency code for base 1/1000 Dogecoin. */
- public static final String CODE_MBTC = "mDOGE";
- /** Currency code for base 1/1000000 Dogecoin. */
- public static final String CODE_UBTC = "µDOGE";
-
- private final char negativeSign;
- private final char positiveSign;
- private final char zeroDigit;
- private final char decimalMark;
- private final int minDecimals;
- private final List decimalGroups;
- private final int shift;
- private final RoundingMode roundingMode;
- private final Map codes;
- private final char codeSeparator;
- private final boolean codePrefixed;
-
- private static final String DECIMALS_PADDING = "0000000000000000"; // a few more than necessary for Bitcoin
-
- /**
- * Set character to prefix negative values.
- */
- public MonetaryFormat negativeSign(char negativeSign) {
- checkArgument(!Character.isDigit(negativeSign));
- checkArgument(negativeSign > 0);
- if (negativeSign == this.negativeSign)
- return this;
- else
- return new MonetaryFormat(negativeSign, positiveSign, zeroDigit, decimalMark, minDecimals, decimalGroups,
- shift, roundingMode, codes, codeSeparator, codePrefixed);
- }
-
- /**
- * Set character to prefix positive values. A zero value means no sign is used in this case. For parsing, a missing
- * sign will always be interpreted as if the positive sign was used.
- */
- public MonetaryFormat positiveSign(char positiveSign) {
- checkArgument(!Character.isDigit(positiveSign));
- if (positiveSign == this.positiveSign)
- return this;
- else
- return new MonetaryFormat(negativeSign, positiveSign, zeroDigit, decimalMark, minDecimals, decimalGroups,
- shift, roundingMode, codes, codeSeparator, codePrefixed);
- }
-
- /**
- * Set character range to use for representing digits. It starts with the specified character representing zero.
- */
- public MonetaryFormat digits(char zeroDigit) {
- if (zeroDigit == this.zeroDigit)
- return this;
- else
- return new MonetaryFormat(negativeSign, positiveSign, zeroDigit, decimalMark, minDecimals, decimalGroups,
- shift, roundingMode, codes, codeSeparator, codePrefixed);
- }
-
- /**
- * Set character to use as the decimal mark. If the formatted value does not have any decimals, no decimal mark is
- * used either.
- */
- public MonetaryFormat decimalMark(char decimalMark) {
- checkArgument(!Character.isDigit(decimalMark));
- checkArgument(decimalMark > 0);
- if (decimalMark == this.decimalMark)
- return this;
- else
- return new MonetaryFormat(negativeSign, positiveSign, zeroDigit, decimalMark, minDecimals, decimalGroups,
- shift, roundingMode, codes, codeSeparator, codePrefixed);
- }
-
- /**
- * Set minimum number of decimals to use for formatting. If the value precision exceeds all decimals specified
- * (including additional decimals specified by {@link #optionalDecimals(int...)} or
- * {@link #repeatOptionalDecimals(int, int)}), the value will be rounded. This configuration is not relevant for
- * parsing.
- */
- public MonetaryFormat minDecimals(int minDecimals) {
- if (minDecimals == this.minDecimals)
- return this;
- else
- return new MonetaryFormat(negativeSign, positiveSign, zeroDigit, decimalMark, minDecimals, decimalGroups,
- shift, roundingMode, codes, codeSeparator, codePrefixed);
- }
-
- /**
- *
- * Set additional groups of decimals to use after the minimum decimals, if they are useful for expressing precision.
- * Each value is a number of decimals in that group. If the value precision exceeds all decimals specified
- * (including minimum decimals), the value will be rounded. This configuration is not relevant for parsing.
- *
- *
- *
- * For example, if you pass 4,2 it will add four decimals to your formatted string if needed, and then add
- * another two decimals if needed. At this point, rather than adding further decimals the value will be rounded.
- *
- *
- * @param groups
- * any number numbers of decimals, one for each group
- */
- public MonetaryFormat optionalDecimals(int... groups) {
- List decimalGroups = new ArrayList(groups.length);
- for (int group : groups)
- decimalGroups.add(group);
- return new MonetaryFormat(negativeSign, positiveSign, zeroDigit, decimalMark, minDecimals, decimalGroups,
- shift, roundingMode, codes, codeSeparator, codePrefixed);
- }
-
- /**
- *
- * Set repeated additional groups of decimals to use after the minimum decimals, if they are useful for expressing
- * precision. If the value precision exceeds all decimals specified (including minimum decimals), the value will be
- * rounded. This configuration is not relevant for parsing.
- *
- *
- *
- * For example, if you pass 1,8 it will up to eight decimals to your formatted string if needed. After
- * these have been used up, rather than adding further decimals the value will be rounded.
- *
- *
- * @param decimals
- * value of the group to be repeated
- * @param repetitions
- * number of repetitions
- */
- public MonetaryFormat repeatOptionalDecimals(int decimals, int repetitions) {
- checkArgument(repetitions >= 0);
- List decimalGroups = new ArrayList(repetitions);
- for (int i = 0; i < repetitions; i++)
- decimalGroups.add(decimals);
- return new MonetaryFormat(negativeSign, positiveSign, zeroDigit, decimalMark, minDecimals, decimalGroups,
- shift, roundingMode, codes, codeSeparator, codePrefixed);
- }
-
- /**
- * Set number of digits to shift the decimal separator to the right, coming from the standard BTC notation that was
- * common pre-2014. Note this will change the currency code if enabled.
- */
- public MonetaryFormat shift(int shift) {
- if (shift == this.shift)
- return this;
- else
- return new MonetaryFormat(negativeSign, positiveSign, zeroDigit, decimalMark, minDecimals, decimalGroups,
- shift, roundingMode, codes, codeSeparator, codePrefixed);
- }
-
- /**
- * Set rounding mode to use when it becomes necessary.
- */
- public MonetaryFormat roundingMode(RoundingMode roundingMode) {
- if (roundingMode == this.roundingMode)
- return this;
- else
- return new MonetaryFormat(negativeSign, positiveSign, zeroDigit, decimalMark, minDecimals, decimalGroups,
- shift, roundingMode, codes, codeSeparator, codePrefixed);
- }
-
- /**
- * Don't display currency code when formatting. This configuration is not relevant for parsing.
- */
- public MonetaryFormat noCode() {
- if (codes == null)
- return this;
- else
- return new MonetaryFormat(negativeSign, positiveSign, zeroDigit, decimalMark, minDecimals, decimalGroups,
- shift, roundingMode, null, codeSeparator, codePrefixed);
- }
-
- /**
- * Configure currency code for given decimal separator shift. This configuration is not relevant for parsing.
- *
- * @param codeShift
- * decimal separator shift, see {@link #shift()}
- * @param code
- * currency code
- */
- public MonetaryFormat code(int codeShift, String code) {
- checkArgument(codeShift >= 0);
- Map codes = new HashMap();
- if (this.codes != null)
- codes.putAll(this.codes);
- codes.put(codeShift, code);
- return new MonetaryFormat(negativeSign, positiveSign, zeroDigit, decimalMark, minDecimals, decimalGroups,
- shift, roundingMode, codes, codeSeparator, codePrefixed);
- }
-
- /**
- * Separator between currency code and formatted value. This configuration is not relevant for parsing.
- */
- public MonetaryFormat codeSeparator(char codeSeparator) {
- checkArgument(!Character.isDigit(codeSeparator));
- checkArgument(codeSeparator > 0);
- if (codeSeparator == this.codeSeparator)
- return this;
- else
- return new MonetaryFormat(negativeSign, positiveSign, zeroDigit, decimalMark, minDecimals, decimalGroups,
- shift, roundingMode, codes, codeSeparator, codePrefixed);
- }
-
- /**
- * Prefix formatted output by currency code. This configuration is not relevant for parsing.
- */
- public MonetaryFormat prefixCode() {
- if (codePrefixed)
- return this;
- else
- return new MonetaryFormat(negativeSign, positiveSign, zeroDigit, decimalMark, minDecimals, decimalGroups,
- shift, roundingMode, codes, codeSeparator, true);
- }
-
- /**
- * Postfix formatted output with currency code. This configuration is not relevant for parsing.
- */
- public MonetaryFormat postfixCode() {
- if (!codePrefixed)
- return this;
- else
- return new MonetaryFormat(negativeSign, positiveSign, zeroDigit, decimalMark, minDecimals, decimalGroups,
- shift, roundingMode, codes, codeSeparator, false);
- }
-
- /**
- * Configure this instance with values from a {@link Locale}.
- */
- public MonetaryFormat withLocale(Locale locale) {
- DecimalFormatSymbols dfs = new DecimalFormatSymbols(locale);
- char negativeSign = dfs.getMinusSign();
- char zeroDigit = dfs.getZeroDigit();
- char decimalMark = dfs.getMonetaryDecimalSeparator();
- return new MonetaryFormat(negativeSign, positiveSign, zeroDigit, decimalMark, minDecimals, decimalGroups,
- shift, roundingMode, codes, codeSeparator, codePrefixed);
- }
-
- public MonetaryFormat() {
- // defaults
- this.negativeSign = '-';
- this.positiveSign = 0; // none
- this.zeroDigit = '0';
- this.decimalMark = '.';
- this.minDecimals = 2;
- this.decimalGroups = null;
- this.shift = 0;
- this.roundingMode = RoundingMode.HALF_UP;
- this.codes = new HashMap();
- this.codes.put(0, CODE_BTC);
- this.codes.put(3, CODE_MBTC);
- this.codes.put(6, CODE_UBTC);
- this.codeSeparator = ' ';
- this.codePrefixed = true;
- }
-
- private MonetaryFormat(char negativeSign, char positiveSign, char zeroDigit, char decimalMark, int minDecimals,
- List decimalGroups, int shift, RoundingMode roundingMode, Map codes,
- char codeSeparator, boolean codePrefixed) {
- this.negativeSign = negativeSign;
- this.positiveSign = positiveSign;
- this.zeroDigit = zeroDigit;
- this.decimalMark = decimalMark;
- this.minDecimals = minDecimals;
- this.decimalGroups = decimalGroups;
- this.shift = shift;
- this.roundingMode = roundingMode;
- this.codes = codes;
- this.codeSeparator = codeSeparator;
- this.codePrefixed = codePrefixed;
- }
-
- /**
- * Format the given monetary value to a human readable form.
- */
- public CharSequence format(Monetary monetary) {
- // preparation
- int maxDecimals = minDecimals;
- if (decimalGroups != null)
- for (int group : decimalGroups)
- maxDecimals += group;
- checkState(maxDecimals <= monetary.smallestUnitExponent());
-
- // rounding
- long satoshis = Math.abs(monetary.getValue());
- long precisionDivisor = checkedPow(10, monetary.smallestUnitExponent() - shift - maxDecimals);
- satoshis = checkedMultiply(divide(satoshis, precisionDivisor, roundingMode), precisionDivisor);
-
- // shifting
- long shiftDivisor = checkedPow(10, monetary.smallestUnitExponent() - shift);
- long numbers = satoshis / shiftDivisor;
- long decimals = satoshis % shiftDivisor;
-
- // formatting
- String decimalsStr = String.format(Locale.US, "%0" + (monetary.smallestUnitExponent() - shift) + "d", decimals);
- StringBuilder str = new StringBuilder(decimalsStr);
- while (str.length() > minDecimals && str.charAt(str.length() - 1) == '0')
- str.setLength(str.length() - 1); // trim trailing zero
- int i = minDecimals;
- if (decimalGroups != null) {
- for (int group : decimalGroups) {
- if (str.length() > i && str.length() < i + group) {
- while (str.length() < i + group)
- str.append('0');
- break;
- }
- i += group;
- }
- }
- if (str.length() > 0)
- str.insert(0, decimalMark);
- str.insert(0, numbers);
- if (monetary.getValue() < 0)
- str.insert(0, negativeSign);
- else if (positiveSign != 0)
- str.insert(0, positiveSign);
- if (codes != null) {
- if (codePrefixed) {
- str.insert(0, codeSeparator);
- str.insert(0, code());
- } else {
- str.append(codeSeparator);
- str.append(code());
- }
- }
-
- // Convert to non-arabic digits.
- if (zeroDigit != '0') {
- int offset = zeroDigit - '0';
- for (int d = 0; d < str.length(); d++) {
- char c = str.charAt(d);
- if (Character.isDigit(c))
- str.setCharAt(d, (char) (c + offset));
- }
- }
- return str;
- }
-
- /**
- * Parse a human readable coin value to a {@link org.altcoinj.core.Coin} instance.
- *
- * @throws NumberFormatException
- * if the string cannot be parsed for some reason
- */
- public Coin parse(String str) throws NumberFormatException {
- return Coin.valueOf(parseValue(str, Coin.SMALLEST_UNIT_EXPONENT));
- }
-
- /**
- * Parse a human readable fiat value to a {@link org.altcoinj.core.Fiat} instance.
- *
- * @throws NumberFormatException
- * if the string cannot be parsed for some reason
- */
- public Fiat parseFiat(String currencyCode, String str) throws NumberFormatException {
- return Fiat.valueOf(currencyCode, parseValue(str, Fiat.SMALLEST_UNIT_EXPONENT));
- }
-
- private long parseValue(String str, int smallestUnitExponent) {
- checkState(DECIMALS_PADDING.length() >= smallestUnitExponent);
- if (str.isEmpty())
- throw new NumberFormatException("empty string");
- char first = str.charAt(0);
- if (first == negativeSign || first == positiveSign)
- str = str.substring(1);
- String numbers;
- String decimals;
- int decimalMarkIndex = str.indexOf(decimalMark);
- if (decimalMarkIndex != -1) {
- numbers = str.substring(0, decimalMarkIndex);
- decimals = (str + DECIMALS_PADDING).substring(decimalMarkIndex + 1);
- if (decimals.indexOf(decimalMark) != -1)
- throw new NumberFormatException("more than one decimal mark");
- } else {
- numbers = str;
- decimals = DECIMALS_PADDING;
- }
- String satoshis = numbers + decimals.substring(0, smallestUnitExponent - shift);
- for (char c : satoshis.toCharArray())
- if (!Character.isDigit(c))
- throw new NumberFormatException("illegal character: " + c);
- long value = Long.parseLong(satoshis); // Non-arabic digits allowed here.
- if (first == negativeSign)
- value = -value;
- return value;
- }
-
- /**
- * Get currency code that will be used for current shift.
- */
- public String code() {
- if (codes == null)
- return null;
- String code = codes.get(shift);
- if (code == null)
- throw new NumberFormatException("missing code for shift: " + shift);
- return code;
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/AbstractFullPrunedBlockChainTest.java b/core/src/test/java/com/dogecoin/dogecoinj/core/AbstractFullPrunedBlockChainTest.java
deleted file mode 100644
index 9b70fd76..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/AbstractFullPrunedBlockChainTest.java
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- * Copyright 2012 Matt Corallo.
- *
- * 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 com.dogecoin.dogecoinj.core;
-
-import com.google.common.collect.Lists;
-import com.dogecoin.dogecoinj.params.MainNetParams;
-import com.dogecoin.dogecoinj.params.UnitTestParams;
-import com.dogecoin.dogecoinj.script.Script;
-import com.dogecoin.dogecoinj.store.BlockStoreException;
-import com.dogecoin.dogecoinj.store.FullPrunedBlockStore;
-import com.dogecoin.dogecoinj.utils.BlockFileLoader;
-import com.dogecoin.dogecoinj.utils.BriefLogFormatter;
-import com.dogecoin.dogecoinj.wallet.WalletTransaction;
-import org.junit.Before;
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.File;
-import java.lang.ref.WeakReference;
-import java.util.Arrays;
-import java.util.List;
-
-import static com.dogecoin.dogecoinj.core.Coin.FIFTY_COINS;
-import static org.junit.Assert.*;
-
-/**
- * We don't do any wallet tests here, we leave that to {@link ChainSplitTest}
- */
-
-public abstract class AbstractFullPrunedBlockChainTest
-{
- private static final Logger log = LoggerFactory.getLogger(AbstractFullPrunedBlockChainTest.class);
-
- protected NetworkParameters params;
- protected FullPrunedBlockChain chain;
- protected FullPrunedBlockStore store;
-
- @Before
- public void setUp() throws Exception {
- BriefLogFormatter.init();
- params = new UnitTestParams() {
- @Override public int getInterval() {
- return 10000;
- }
- };
- }
-
- public abstract FullPrunedBlockStore createStore(NetworkParameters params, int blockCount)
- throws BlockStoreException;
-
- public abstract void resetStore(FullPrunedBlockStore store) throws BlockStoreException;
-
- @Test
- public void testGeneratedChain() throws Exception {
- // Tests various test cases from FullBlockTestGenerator
- FullBlockTestGenerator generator = new FullBlockTestGenerator(params);
- RuleList blockList = generator.getBlocksToTest(false, false, null);
-
- store = createStore(params, blockList.maximumReorgBlockCount);
- chain = new FullPrunedBlockChain(params, store);
-
- for (Rule rule : blockList.list) {
- if (!(rule instanceof FullBlockTestGenerator.BlockAndValidity))
- continue;
- FullBlockTestGenerator.BlockAndValidity block = (FullBlockTestGenerator.BlockAndValidity) rule;
- log.info("Testing rule " + block.ruleName + " with block hash " + block.block.getHash());
- boolean threw = false;
- try {
- if (chain.add(block.block) != block.connects) {
- log.error("Block didn't match connects flag on block " + block.ruleName);
- fail();
- }
- } catch (VerificationException e) {
- threw = true;
- if (!block.throwsException) {
- log.error("Block didn't match throws flag on block " + block.ruleName);
- throw e;
- }
- if (block.connects) {
- log.error("Block didn't match connects flag on block " + block.ruleName);
- fail();
- }
- }
- if (!threw && block.throwsException) {
- log.error("Block didn't match throws flag on block " + block.ruleName);
- fail();
- }
- if (!chain.getChainHead().getHeader().getHash().equals(block.hashChainTipAfterBlock)) {
- log.error("New block head didn't match the correct value after block " + block.ruleName);
- fail();
- }
- if (chain.getChainHead().getHeight() != block.heightAfterBlock) {
- log.error("New block head didn't match the correct height after block " + block.ruleName);
- fail();
- }
- }
- try {
- store.close();
- } catch (Exception e) {}
- }
-
- @Test
- public void skipScripts() throws Exception {
- store = createStore(params, 10);
- chain = new FullPrunedBlockChain(params, store);
-
- // Check that we aren't accidentally leaving any references
- // to the full StoredUndoableBlock's lying around (ie memory leaks)
-
- ECKey outKey = new ECKey();
-
- // Build some blocks on genesis block to create a spendable output
- Block rollingBlock = params.getGenesisBlock().createNextBlockWithCoinbase(outKey.getPubKey());
- chain.add(rollingBlock);
- TransactionOutput spendableOutput = rollingBlock.getTransactions().get(0).getOutput(0);
- for (int i = 1; i < params.getSpendableCoinbaseDepth(); i++) {
- rollingBlock = rollingBlock.createNextBlockWithCoinbase(outKey.getPubKey());
- chain.add(rollingBlock);
- }
-
- rollingBlock = rollingBlock.createNextBlock(null);
- Transaction t = new Transaction(params);
- t.addOutput(new TransactionOutput(params, t, FIFTY_COINS, new byte[] {}));
- TransactionInput input = t.addInput(spendableOutput);
- // Invalid script.
- input.setScriptBytes(new byte[]{});
- rollingBlock.addTransaction(t);
- rollingBlock.solve();
- chain.setRunScripts(false);
- try {
- chain.add(rollingBlock);
- } catch (VerificationException e) {
- fail();
- }
- try {
- store.close();
- } catch (Exception e) {}
- }
-
- @Test
- public void testFinalizedBlocks() throws Exception {
- final int UNDOABLE_BLOCKS_STORED = 10;
- store = createStore(params, UNDOABLE_BLOCKS_STORED);
- chain = new FullPrunedBlockChain(params, store);
-
- // Check that we aren't accidentally leaving any references
- // to the full StoredUndoableBlock's lying around (ie memory leaks)
-
- ECKey outKey = new ECKey();
-
- // Build some blocks on genesis block to create a spendable output
- Block rollingBlock = params.getGenesisBlock().createNextBlockWithCoinbase(outKey.getPubKey());
- chain.add(rollingBlock);
- TransactionOutPoint spendableOutput = new TransactionOutPoint(params, 0, rollingBlock.getTransactions().get(0).getHash());
- byte[] spendableOutputScriptPubKey = rollingBlock.getTransactions().get(0).getOutputs().get(0).getScriptBytes();
- for (int i = 1; i < params.getSpendableCoinbaseDepth(); i++) {
- rollingBlock = rollingBlock.createNextBlockWithCoinbase(outKey.getPubKey());
- chain.add(rollingBlock);
- }
-
- WeakReference out = new WeakReference
- (store.getTransactionOutput(spendableOutput.getHash(), spendableOutput.getIndex()));
- rollingBlock = rollingBlock.createNextBlock(null);
-
- Transaction t = new Transaction(params);
- // Entirely invalid scriptPubKey
- t.addOutput(new TransactionOutput(params, t, FIFTY_COINS, new byte[]{}));
- t.addSignedInput(spendableOutput, new Script(spendableOutputScriptPubKey), outKey);
- rollingBlock.addTransaction(t);
- rollingBlock.solve();
-
- chain.add(rollingBlock);
- WeakReference undoBlock = new WeakReference(store.getUndoBlock(rollingBlock.getHash()));
-
- StoredUndoableBlock storedUndoableBlock = undoBlock.get();
- assertNotNull(storedUndoableBlock);
- assertNull(storedUndoableBlock.getTransactions());
- WeakReference changes = new WeakReference(storedUndoableBlock.getTxOutChanges());
- assertNotNull(changes.get());
- storedUndoableBlock = null; // Blank the reference so it can be GCd.
-
- // Create a chain longer than UNDOABLE_BLOCKS_STORED
- for (int i = 0; i < UNDOABLE_BLOCKS_STORED; i++) {
- rollingBlock = rollingBlock.createNextBlock(null);
- chain.add(rollingBlock);
- }
- // Try to get the garbage collector to run
- System.gc();
- assertNull(undoBlock.get());
- assertNull(changes.get());
- assertNull(out.get());
- try {
- store.close();
- } catch (Exception e) {}
- }
-
- @Test
- public void testFirst100KBlocks() throws Exception {
- NetworkParameters params = MainNetParams.get();
- File blockFile = new File(getClass().getResource("first-100k-blocks.dat").getFile());
- BlockFileLoader loader = new BlockFileLoader(params, Arrays.asList(blockFile));
-
- store = createStore(params, 10);
- resetStore(store);
- chain = new FullPrunedBlockChain(params, store);
- for (Block block : loader)
- chain.add(block);
- try {
- store.close();
- } catch (Exception e) {}
- }
-
- @Test
- public void testGetOpenTransactionOutputs() throws Exception {
- final int UNDOABLE_BLOCKS_STORED = 10;
- store = createStore(params, UNDOABLE_BLOCKS_STORED);
- chain = new FullPrunedBlockChain(params, store);
-
- // Check that we aren't accidentally leaving any references
- // to the full StoredUndoableBlock's lying around (ie memory leaks)
- ECKey outKey = new ECKey();
-
- // Build some blocks on genesis block to create a spendable output
- Block rollingBlock = params.getGenesisBlock().createNextBlockWithCoinbase(outKey.getPubKey());
- chain.add(rollingBlock);
- Transaction transaction = rollingBlock.getTransactions().get(0);
- TransactionOutPoint spendableOutput = new TransactionOutPoint(params, 0, transaction.getHash());
- byte[] spendableOutputScriptPubKey = transaction.getOutputs().get(0).getScriptBytes();
- for (int i = 1; i < params.getSpendableCoinbaseDepth(); i++) {
- rollingBlock = rollingBlock.createNextBlockWithCoinbase(outKey.getPubKey());
- chain.add(rollingBlock);
- }
- rollingBlock = rollingBlock.createNextBlock(null);
-
- // Create bitcoin spend of 1 BTC.
- ECKey toKey = new ECKey();
- Coin amount = Coin.valueOf(100000000);
- Address address = new Address(params, toKey.getPubKeyHash());
- Coin totalAmount = Coin.ZERO;
-
- Transaction t = new Transaction(params);
- t.addOutput(new TransactionOutput(params, t, amount, toKey));
- t.addSignedInput(spendableOutput, new Script(spendableOutputScriptPubKey), outKey);
- rollingBlock.addTransaction(t);
- rollingBlock.solve();
- chain.add(rollingBlock);
- totalAmount = totalAmount.add(amount);
-
- List outputs = store.getOpenTransactionOutputs(Lists.newArrayList(address));
- assertNotNull(outputs);
- assertEquals("Wrong Number of Outputs", 1, outputs.size());
- UTXO output = outputs.get(0);
- assertEquals("The address is not equal", address.toString(), output.getAddress());
- assertEquals("The amount is not equal", totalAmount, output.getValue());
-
- outputs = null;
- output = null;
- try {
- store.close();
- } catch (Exception e) {}
- }
-
- @Test
- public void testUTXOProviderWithWallet() throws Exception {
- final int UNDOABLE_BLOCKS_STORED = 10;
- store = createStore(params, UNDOABLE_BLOCKS_STORED);
- chain = new FullPrunedBlockChain(params, store);
-
- // Check that we aren't accidentally leaving any references
- // to the full StoredUndoableBlock's lying around (ie memory leaks)
- ECKey outKey = new ECKey();
-
- // Build some blocks on genesis block to create a spendable output.
- Block rollingBlock = params.getGenesisBlock().createNextBlockWithCoinbase(outKey.getPubKey());
- chain.add(rollingBlock);
- Transaction transaction = rollingBlock.getTransactions().get(0);
- TransactionOutPoint spendableOutput = new TransactionOutPoint(params, 0, transaction.getHash());
- byte[] spendableOutputScriptPubKey = transaction.getOutputs().get(0).getScriptBytes();
- for (int i = 1; i < params.getSpendableCoinbaseDepth(); i++) {
- rollingBlock = rollingBlock.createNextBlockWithCoinbase(outKey.getPubKey());
- chain.add(rollingBlock);
- }
- rollingBlock = rollingBlock.createNextBlock(null);
-
- // Create 1 BTC spend to a key in this wallet (to ourselves).
- Wallet wallet = new Wallet(params);
- assertEquals("Available balance is incorrect", Coin.ZERO, wallet.getBalance(Wallet.BalanceType.AVAILABLE));
- assertEquals("Estimated balance is incorrect", Coin.ZERO, wallet.getBalance(Wallet.BalanceType.ESTIMATED));
-
- wallet.setUTXOProvider(store);
- ECKey toKey = wallet.freshReceiveKey();
- Coin amount = Coin.valueOf(100000000);
-
- Transaction t = new Transaction(params);
- t.addOutput(new TransactionOutput(params, t, amount, toKey));
- t.addSignedInput(spendableOutput, new Script(spendableOutputScriptPubKey), outKey);
- rollingBlock.addTransaction(t);
- rollingBlock.solve();
- chain.add(rollingBlock);
-
- // Create another spend of 1/2 the value of BTC we have available using the wallet (store coin selector).
- ECKey toKey2 = new ECKey();
- Coin amount2 = amount.divide(2);
- Address address2 = new Address(params, toKey2.getPubKeyHash());
- Wallet.SendRequest req = Wallet.SendRequest.to(address2, amount2);
- wallet.completeTx(req);
- wallet.commitTx(req.tx);
- Coin fee = req.fee;
-
- // There should be one pending tx (our spend).
- assertEquals("Wrong number of PENDING.4", 1, wallet.getPoolSize(WalletTransaction.Pool.PENDING));
- Coin totalPendingTxAmount = Coin.ZERO;
- for (Transaction tx : wallet.getPendingTransactions()) {
- totalPendingTxAmount = totalPendingTxAmount.add(tx.getValueSentToMe(wallet));
- }
-
- // The availbale balance should be the 0 (as we spent the 1 BTC that's pending) and estimated should be 1/2 - fee BTC
- assertEquals("Available balance is incorrect", Coin.ZERO, wallet.getBalance(Wallet.BalanceType.AVAILABLE));
- assertEquals("Estimated balance is incorrect", amount2.subtract(fee), wallet.getBalance(Wallet.BalanceType.ESTIMATED));
- assertEquals("Pending tx amount is incorrect", amount2.subtract(fee), totalPendingTxAmount);
- try {
- store.close();
- } catch (Exception e) {}
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/AlertMessageTest.java b/core/src/test/java/com/dogecoin/dogecoinj/core/AlertMessageTest.java
deleted file mode 100644
index 000d8263..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/AlertMessageTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2011 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 com.dogecoin.dogecoinj.core;
-
-import com.dogecoin.dogecoinj.params.UnitTestParams;
-import org.junit.Before;
-import org.junit.Test;
-
-import static com.dogecoin.dogecoinj.core.Utils.HEX;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-public class AlertMessageTest {
- private static final byte[] TEST_KEY_PRIV = HEX.decode("6421e091445ade4b24658e96aa60959ce800d8ea9e7bd8613335aa65ba8d840b");
- private NetworkParameters params;
-
- @Before
- public void setUp() throws Exception {
- final ECKey key = ECKey.fromPrivate(TEST_KEY_PRIV);
- params = new UnitTestParams() {
- @Override
- public byte[] getAlertSigningKey() {
- return key.getPubKey();
- }
- };
- }
-
- @Test
- public void deserialize() throws Exception {
- // A CAlert taken from the reference implementation.
- // TODO: This does not check the subVer or set fields. Support proper version matching.
- final byte[] payload = HEX.decode("5c010000004544eb4e000000004192ec4e00000000eb030000e9030000000000000048ee00000088130000002f43416c6572742073797374656d20746573743a2020202020202020207665722e302e352e3120617661696c61626c6500473045022100ec799908c008b272d5e5cd5a824abaaac53d210cc1fa517d8e22a701ecdb9e7002206fa1e7e7c251d5ba0d7c1fe428fc1870662f2927531d1cad8d4581b45bc4f8a7");
- AlertMessage alert = new AlertMessage(params, payload);
- assertEquals(1324041285, alert.getRelayUntil().getTime() / 1000);
- assertEquals(1324126785, alert.getExpiration().getTime() / 1000);
- assertEquals(1003, alert.getId());
- assertEquals(1001, alert.getCancel());
- assertEquals(0, alert.getMinVer());
- assertEquals(61000, alert.getMaxVer());
- assertEquals(5000, alert.getPriority());
- assertEquals("CAlert system test: ver.0.5.1 available", alert.getStatusBar());
- assertTrue(alert.isSignatureValid());
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/Base58Test.java b/core/src/test/java/com/dogecoin/dogecoinj/core/Base58Test.java
deleted file mode 100644
index aa752479..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/Base58Test.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/**
- * Copyright 2011 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 com.dogecoin.dogecoinj.core;
-
-import junit.framework.TestCase;
-import org.junit.Test;
-
-import java.math.BigInteger;
-import java.util.Arrays;
-
-public class Base58Test extends TestCase {
- @Test
- public void testEncode() throws Exception {
- byte[] testbytes = "Hello World".getBytes();
- assertEquals("JxF12TrwUP45BMd", Base58.encode(testbytes));
-
- BigInteger bi = BigInteger.valueOf(3471844090L);
- assertEquals("16Ho7Hs", Base58.encode(bi.toByteArray()));
-
- byte[] zeroBytes1 = new byte[1];
- assertEquals("1", Base58.encode(zeroBytes1));
-
- byte[] zeroBytes7 = new byte[7];
- assertEquals("1111111", Base58.encode(zeroBytes7));
-
- // test empty encode
- assertEquals("", Base58.encode(new byte[0]));
- }
-
- @Test
- public void testDecode() throws Exception {
- byte[] testbytes = "Hello World".getBytes();
- byte[] actualbytes = Base58.decode("JxF12TrwUP45BMd");
- assertTrue(new String(actualbytes), Arrays.equals(testbytes, actualbytes));
-
- assertTrue("1", Arrays.equals(Base58.decode("1"), new byte[1]));
- assertTrue("1111", Arrays.equals(Base58.decode("1111"), new byte[4]));
-
- try {
- Base58.decode("This isn't valid base58");
- fail();
- } catch (AddressFormatException e) {
- // expected
- }
-
- Base58.decodeChecked("4stwEBjT6FYyVV");
-
- // Checksum should fail.
- try {
- Base58.decodeChecked("4stwEBjT6FYyVW");
- fail();
- } catch (AddressFormatException e) {
- // expected
- }
-
- // Input is too short.
- try {
- Base58.decodeChecked("4s");
- fail();
- } catch (AddressFormatException e) {
- // expected
- }
-
- // Test decode of empty String.
- assertEquals(0, Base58.decode("").length);
-
- // Now check we can correctly decode the case where the high bit of the first byte is not zero, so BigInteger
- // sign extends. Fix for a bug that stopped us parsing keys exported using sipas patch.
- Base58.decodeChecked("93VYUMzRG9DdbRP72uQXjaWibbQwygnvaCu9DumcqDjGybD864T");
- }
-
- @Test
- public void testDecodeToBigInteger() throws AddressFormatException {
- byte[] input = Base58.decode("129");
- assertEquals(new BigInteger(1, input), Base58.decodeToBigInteger("129"));
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/BitcoinSerializerTest.java b/core/src/test/java/com/dogecoin/dogecoinj/core/BitcoinSerializerTest.java
deleted file mode 100644
index b8c5e2e0..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/BitcoinSerializerTest.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/**
- * Copyright 2011 Noa Resare
- * 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 com.dogecoin.dogecoinj.core;
-
-import com.dogecoin.dogecoinj.params.MainNetParams;
-import org.junit.Test;
-
-import java.io.ByteArrayOutputStream;
-import java.net.InetAddress;
-import java.nio.BufferUnderflowException;
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-
-import static com.dogecoin.dogecoinj.core.Utils.HEX;
-import static org.junit.Assert.*;
-
-public class BitcoinSerializerTest {
- private final byte[] addrMessage = HEX.decode("f9beb4d96164647200000000000000001f000000" +
- "ed52399b01e215104d010000000000000000000000000000000000ffff0a000001208d");
-
- private final byte[] txMessage = HEX.withSeparator(" ", 2).decode(
- "f9 be b4 d9 74 78 00 00 00 00 00 00 00 00 00 00" +
- "02 01 00 00 e2 93 cd be 01 00 00 00 01 6d bd db" +
- "08 5b 1d 8a f7 51 84 f0 bc 01 fa d5 8d 12 66 e9" +
- "b6 3b 50 88 19 90 e4 b4 0d 6a ee 36 29 00 00 00" +
- "00 8b 48 30 45 02 21 00 f3 58 1e 19 72 ae 8a c7" +
- "c7 36 7a 7a 25 3b c1 13 52 23 ad b9 a4 68 bb 3a" +
- "59 23 3f 45 bc 57 83 80 02 20 59 af 01 ca 17 d0" +
- "0e 41 83 7a 1d 58 e9 7a a3 1b ae 58 4e de c2 8d" +
- "35 bd 96 92 36 90 91 3b ae 9a 01 41 04 9c 02 bf" +
- "c9 7e f2 36 ce 6d 8f e5 d9 40 13 c7 21 e9 15 98" +
- "2a cd 2b 12 b6 5d 9b 7d 59 e2 0a 84 20 05 f8 fc" +
- "4e 02 53 2e 87 3d 37 b9 6f 09 d6 d4 51 1a da 8f" +
- "14 04 2f 46 61 4a 4c 70 c0 f1 4b ef f5 ff ff ff" +
- "ff 02 40 4b 4c 00 00 00 00 00 19 76 a9 14 1a a0" +
- "cd 1c be a6 e7 45 8a 7a ba d5 12 a9 d9 ea 1a fb" +
- "22 5e 88 ac 80 fa e9 c7 00 00 00 00 19 76 a9 14" +
- "0e ab 5b ea 43 6a 04 84 cf ab 12 48 5e fd a0 b7" +
- "8b 4e cc 52 88 ac 00 00 00 00");
-
- @Test
- public void testAddr() throws Exception {
- BitcoinSerializer bs = new BitcoinSerializer(MainNetParams.get());
- // the actual data from https://en.bitcoin.it/wiki/Protocol_specification#addr
- AddressMessage a = (AddressMessage)bs.deserialize(ByteBuffer.wrap(addrMessage));
- assertEquals(1, a.getAddresses().size());
- PeerAddress pa = a.getAddresses().get(0);
- assertEquals(8333, pa.getPort());
- assertEquals("10.0.0.1", pa.getAddr().getHostAddress());
- ByteArrayOutputStream bos = new ByteArrayOutputStream(addrMessage.length);
- bs.serialize(a, bos);
-
- assertEquals(31, a.getMessageSize());
- a.addAddress(new PeerAddress(InetAddress.getLocalHost()));
- assertEquals(61, a.getMessageSize());
- a.removeAddress(0);
- assertEquals(31, a.getMessageSize());
-
- //this wont be true due to dynamic timestamps.
- //assertTrue(LazyParseByteCacheTest.arrayContains(bos.toByteArray(), addrMessage));
- }
-
- @Test
- public void testLazyParsing() throws Exception {
- BitcoinSerializer bs = new BitcoinSerializer(MainNetParams.get(), true, false);
-
- Transaction tx = (Transaction)bs.deserialize(ByteBuffer.wrap(txMessage));
- assertNotNull(tx);
- assertEquals(false, tx.isParsed());
- assertEquals(true, tx.isCached());
- tx.getInputs();
- assertEquals(true, tx.isParsed());
-
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- bs.serialize(tx, bos);
- assertEquals(true, Arrays.equals(txMessage, bos.toByteArray()));
- }
-
- @Test
- public void testCachedParsing() throws Exception {
- testCachedParsing(true);
- testCachedParsing(false);
- }
-
- private void testCachedParsing(boolean lazy) throws Exception {
- BitcoinSerializer bs = new BitcoinSerializer(MainNetParams.get(), lazy, true);
-
- //first try writing to a fields to ensure uncaching and children are not affected
- Transaction tx = (Transaction)bs.deserialize(ByteBuffer.wrap(txMessage));
- assertNotNull(tx);
- assertEquals(!lazy, tx.isParsed());
- assertEquals(true, tx.isCached());
-
- tx.setLockTime(1);
- //parent should have been uncached
- assertEquals(false, tx.isCached());
- //child should remain cached.
- assertEquals(true, tx.getInputs().get(0).isCached());
-
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- bs.serialize(tx, bos);
- assertEquals(true, !Arrays.equals(txMessage, bos.toByteArray()));
-
- //now try writing to a child to ensure uncaching is propagated up to parent but not to siblings
- tx = (Transaction)bs.deserialize(ByteBuffer.wrap(txMessage));
- assertNotNull(tx);
- assertEquals(!lazy, tx.isParsed());
- assertEquals(true, tx.isCached());
-
- tx.getInputs().get(0).setSequenceNumber(1);
- //parent should have been uncached
- assertEquals(false, tx.isCached());
- //so should child
- assertEquals(false, tx.getInputs().get(0).isCached());
-
- bos = new ByteArrayOutputStream();
- bs.serialize(tx, bos);
- assertEquals(true, !Arrays.equals(txMessage, bos.toByteArray()));
-
- //deserialize/reserialize to check for equals.
- tx = (Transaction)bs.deserialize(ByteBuffer.wrap(txMessage));
- assertNotNull(tx);
- assertEquals(!lazy, tx.isParsed());
- assertEquals(true, tx.isCached());
- bos = new ByteArrayOutputStream();
- bs.serialize(tx, bos);
- assertEquals(true, Arrays.equals(txMessage, bos.toByteArray()));
-
- //deserialize/reserialize to check for equals. Set a field to it's existing value to trigger uncache
- tx = (Transaction)bs.deserialize(ByteBuffer.wrap(txMessage));
- assertNotNull(tx);
- assertEquals(!lazy, tx.isParsed());
- assertEquals(true, tx.isCached());
-
- tx.getInputs().get(0).setSequenceNumber(tx.getInputs().get(0).getSequenceNumber());
-
- bos = new ByteArrayOutputStream();
- bs.serialize(tx, bos);
- assertEquals(true, Arrays.equals(txMessage, bos.toByteArray()));
-
- }
-
-
- /**
- * Get 1 header of the block number 1 (the first one is 0) in the chain
- */
- @Test
- public void testHeaders1() throws Exception {
- BitcoinSerializer bs = new BitcoinSerializer(MainNetParams.get());
-
- HeadersMessage hm = (HeadersMessage) bs.deserialize(ByteBuffer.wrap(HEX.decode("f9beb4d9686561" +
- "646572730000000000520000005d4fab8101010000006fe28c0ab6f1b372c1a6a246ae6" +
- "3f74f931e8365e15a089c68d6190000000000982051fd1e4ba744bbbe680e1fee14677b" +
- "a1a3c3540bf7b1cdb606e857233e0e61bc6649ffff001d01e3629900")));
-
- // The first block after the genesis
- // http://blockexplorer.com/b/1
- Block block = hm.getBlockHeaders().get(0);
- String hash = block.getHashAsString();
- assertEquals(hash, "00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048");
-
- assertNull(block.transactions);
-
- assertEquals(Utils.HEX.encode(block.getMerkleRoot().getBytes()),
- "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098");
- }
-
-
- @Test
- /**
- * Get 6 headers of blocks 1-6 in the chain
- */
- public void testHeaders2() throws Exception {
- BitcoinSerializer bs = new BitcoinSerializer(MainNetParams.get());
-
- HeadersMessage hm = (HeadersMessage) bs.deserialize(ByteBuffer.wrap(HEX.decode("f9beb4d96865616465" +
- "72730000000000e701000085acd4ea06010000006fe28c0ab6f1b372c1a6a246ae63f74f931e" +
- "8365e15a089c68d6190000000000982051fd1e4ba744bbbe680e1fee14677ba1a3c3540bf7b1c" +
- "db606e857233e0e61bc6649ffff001d01e3629900010000004860eb18bf1b1620e37e9490fc8a" +
- "427514416fd75159ab86688e9a8300000000d5fdcc541e25de1c7a5addedf24858b8bb665c9f36" +
- "ef744ee42c316022c90f9bb0bc6649ffff001d08d2bd610001000000bddd99ccfda39da1b108ce1" +
- "a5d70038d0a967bacb68b6b63065f626a0000000044f672226090d85db9a9f2fbfe5f0f9609b387" +
- "af7be5b7fbb7a1767c831c9e995dbe6649ffff001d05e0ed6d00010000004944469562ae1c2c74" +
- "d9a535e00b6f3e40ffbad4f2fda3895501b582000000007a06ea98cd40ba2e3288262b28638cec" +
- "5337c1456aaf5eedc8e9e5a20f062bdf8cc16649ffff001d2bfee0a9000100000085144a84488e" +
- "a88d221c8bd6c059da090e88f8a2c99690ee55dbba4e00000000e11c48fecdd9e72510ca84f023" +
- "370c9a38bf91ac5cae88019bee94d24528526344c36649ffff001d1d03e4770001000000fc33f5" +
- "96f822a0a1951ffdbf2a897b095636ad871707bf5d3162729b00000000379dfb96a5ea8c81700ea4" +
- "ac6b97ae9a9312b2d4301a29580e924ee6761a2520adc46649ffff001d189c4c9700")));
-
- int nBlocks = hm.getBlockHeaders().size();
- assertEquals(nBlocks, 6);
-
- // index 0 block is the number 1 block in the block chain
- // http://blockexplorer.com/b/1
- Block zeroBlock = hm.getBlockHeaders().get(0);
- String zeroBlockHash = zeroBlock.getHashAsString();
-
- assertEquals("00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048",
- zeroBlockHash);
- assertEquals(zeroBlock.getNonce(), 2573394689L);
-
-
- Block thirdBlock = hm.getBlockHeaders().get(3);
- String thirdBlockHash = thirdBlock.getHashAsString();
-
- // index 3 block is the number 4 block in the block chain
- // http://blockexplorer.com/b/4
- assertEquals("000000004ebadb55ee9096c9a2f8880e09da59c0d68b1c228da88e48844a1485",
- thirdBlockHash);
- assertEquals(thirdBlock.getNonce(), 2850094635L);
- }
-
- @Test
- public void testBitcoinPacketHeader() {
- try {
- new BitcoinSerializer.BitcoinPacketHeader(ByteBuffer.wrap(new byte[]{0}));
- fail();
- } catch (BufferUnderflowException e) {
- }
-
- // Message with a Message size which is 1 too big, in little endian format.
- byte[] wrongMessageLength = HEX.decode("000000000000000000000000010000020000000000");
- try {
- new BitcoinSerializer.BitcoinPacketHeader(ByteBuffer.wrap(wrongMessageLength));
- fail();
- } catch (ProtocolException e) {
- // expected
- }
- }
-
- @Test
- public void testSeekPastMagicBytes() {
- // Fail in another way, there is data in the stream but no magic bytes.
- byte[] brokenMessage = HEX.decode("000000");
- try {
- new BitcoinSerializer(MainNetParams.get()).seekPastMagicBytes(ByteBuffer.wrap(brokenMessage));
- fail();
- } catch (BufferUnderflowException e) {
- // expected
- }
- }
-
- @Test
- /**
- * Tests serialization of an unknown message.
- */
- public void testSerializeUnknownMessage() {
- BitcoinSerializer bs = new BitcoinSerializer(MainNetParams.get());
-
- UnknownMessage a = new UnknownMessage();
- ByteArrayOutputStream bos = new ByteArrayOutputStream(addrMessage.length);
- try {
- bs.serialize(a, bos);
- fail();
- } catch (Throwable e) {
- }
- }
-
- /**
- * Unknown message for testSerializeUnknownMessage.
- */
- class UnknownMessage extends Message {
- @Override
- void parse() throws ProtocolException {
- }
-
- @Override
- protected void parseLite() throws ProtocolException {
- }
- }
-
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/BitcoindComparisonTool.java b/core/src/test/java/com/dogecoin/dogecoinj/core/BitcoindComparisonTool.java
deleted file mode 100644
index 5c65ffd4..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/BitcoindComparisonTool.java
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- * Copyright 2012 Matt Corallo.
- * 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 com.dogecoin.dogecoinj.core;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Iterables;
-import com.google.common.util.concurrent.SettableFuture;
-import com.google.common.util.concurrent.Uninterruptibles;
-import com.dogecoin.dogecoinj.net.NioClient;
-import com.dogecoin.dogecoinj.params.RegTestParams;
-import com.dogecoin.dogecoinj.store.BlockStoreException;
-import com.dogecoin.dogecoinj.store.FullPrunedBlockStore;
-import com.dogecoin.dogecoinj.store.H2FullPrunedBlockStore;
-import com.dogecoin.dogecoinj.store.MemoryBlockStore;
-import com.dogecoin.dogecoinj.utils.BlockFileLoader;
-import com.dogecoin.dogecoinj.utils.BriefLogFormatter;
-import com.dogecoin.dogecoinj.utils.Threading;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.File;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.util.*;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * A tool for comparing the blocks which are accepted/rejected by bitcoind/dogecoinj
- * It is designed to run as a testnet-in-a-box network between a single bitcoind node and dogecoinj
- * It is not an automated unit-test because it requires a bit more set-up...read comments below
- */
-public class BitcoindComparisonTool {
- private static final Logger log = LoggerFactory.getLogger(BitcoindComparisonTool.class);
-
- private static NetworkParameters params;
- private static FullPrunedBlockStore store;
- private static FullPrunedBlockChain chain;
- private static Sha256Hash bitcoindChainHead;
- private static volatile InventoryMessage mostRecentInv = null;
-
- static class BlockWrapper {
- public Block block;
- }
-
- public static void main(String[] args) throws Exception {
- BriefLogFormatter.init();
- System.out.println("USAGE: bitcoinjBlockStoreLocation runExpensiveTests(1/0) [port=18444]");
- boolean runExpensiveTests = args.length > 1 && Integer.parseInt(args[1]) == 1;
-
- params = RegTestParams.get();
-
- File blockFile = File.createTempFile("testBlocks", ".dat");
- blockFile.deleteOnExit();
-
- FullBlockTestGenerator generator = new FullBlockTestGenerator(params);
- final RuleList blockList = generator.getBlocksToTest(false, runExpensiveTests, blockFile);
- final Map preloadedBlocks = new HashMap();
- final Iterator blocks = new BlockFileLoader(params, Arrays.asList(blockFile));
-
- try {
- store = new H2FullPrunedBlockStore(params, args.length > 0 ? args[0] : "BitcoindComparisonTool", blockList.maximumReorgBlockCount);
- ((H2FullPrunedBlockStore)store).resetStore();
- //store = new MemoryFullPrunedBlockStore(params, blockList.maximumReorgBlockCount);
- chain = new FullPrunedBlockChain(params, store);
- } catch (BlockStoreException e) {
- e.printStackTrace();
- System.exit(1);
- }
-
- VersionMessage ver = new VersionMessage(params, 42);
- ver.appendToSubVer("BlockAcceptanceComparisonTool", "1.1", null);
- ver.localServices = VersionMessage.NODE_NETWORK;
- final Peer bitcoind = new Peer(params, ver, new BlockChain(params, new MemoryBlockStore(params)), new PeerAddress(InetAddress.getLocalHost()));
- Preconditions.checkState(bitcoind.getVersionMessage().hasBlockChain());
-
- final BlockWrapper currentBlock = new BlockWrapper();
-
- final Set blocksRequested = Collections.synchronizedSet(new HashSet());
- final Set blocksPendingSend = Collections.synchronizedSet(new HashSet());
- final AtomicInteger unexpectedInvs = new AtomicInteger(0);
- final SettableFuture connectedFuture = SettableFuture.create();
- bitcoind.addEventListener(new AbstractPeerEventListener() {
- @Override
- public void onPeerConnected(Peer peer, int peerCount) {
- if (!peer.getPeerVersionMessage().subVer.contains("Satoshi")) {
- System.out.println();
- System.out.println("************************************************************************************************************************\n" +
- "WARNING: You appear to be using this to test an alternative implementation with full validation rules. You should go\n" +
- "think hard about what you're doing. Seriously, no one has gotten even close to correctly reimplementing Bitcoin\n" +
- "consensus rules, despite serious investment in trying. It is a huge task and the slightest difference is a huge bug.\n" +
- "Instead, go work on making Bitcoin Core consensus rules a shared library and use that. Seriously, you wont get it right,\n" +
- "and starting with this tester as a way to try to do so will simply end in pain and lost coins.\n" +
- "************************************************************************************************************************");
- System.out.println();
- System.out.println("Giving you 30 seconds to think about the above warning...");
- Uninterruptibles.sleepUninterruptibly(30, TimeUnit.SECONDS);
- }
- log.info("bitcoind connected");
- // Make sure bitcoind has no blocks
- bitcoind.setDownloadParameters(0, false);
- bitcoind.startBlockChainDownload();
- connectedFuture.set(null);
- }
-
- @Override
- public void onPeerDisconnected(Peer peer, int peerCount) {
- log.error("bitcoind node disconnected!");
- System.exit(1);
- }
-
- @Override
- public Message onPreMessageReceived(Peer peer, Message m) {
- if (m instanceof HeadersMessage) {
- if (!((HeadersMessage) m).getBlockHeaders().isEmpty()) {
- Block b = Iterables.getLast(((HeadersMessage) m).getBlockHeaders());
- log.info("Got header from bitcoind " + b.getHashAsString());
- bitcoindChainHead = b.getHash();
- } else
- log.info("Got empty header message from bitcoind");
- return null;
- } else if (m instanceof Block) {
- log.error("bitcoind sent us a block it already had, make sure bitcoind has no blocks!");
- System.exit(1);
- } else if (m instanceof GetDataMessage) {
- for (InventoryItem item : ((GetDataMessage) m).items)
- if (item.type == InventoryItem.Type.Block) {
- log.info("Requested " + item.hash);
- if (currentBlock.block.getHash().equals(item.hash))
- bitcoind.sendMessage(currentBlock.block);
- else {
- Block nextBlock = preloadedBlocks.get(item.hash);
- if (nextBlock != null)
- bitcoind.sendMessage(nextBlock);
- else {
- blocksPendingSend.add(item.hash);
- log.info("...which we will not provide yet");
- }
- }
- blocksRequested.add(item.hash);
- }
- return null;
- } else if (m instanceof GetHeadersMessage) {
- try {
- if (currentBlock.block == null) {
- log.info("Got a request for a header before we had even begun processing blocks!");
- return null;
- }
- LinkedList headers = new LinkedList();
- Block it = blockList.hashHeaderMap.get(currentBlock.block.getHash());
- while (it != null) {
- headers.addFirst(it);
- it = blockList.hashHeaderMap.get(it.getPrevBlockHash());
- }
- LinkedList sendHeaders = new LinkedList();
- boolean found = false;
- for (Sha256Hash hash : ((GetHeadersMessage) m).getLocator()) {
- for (Block b : headers) {
- if (found) {
- sendHeaders.addLast(b);
- log.info("Sending header (" + b.getPrevBlockHash() + ") -> " + b.getHash());
- if (b.getHash().equals(((GetHeadersMessage) m).getStopHash()))
- break;
- } else if (b.getHash().equals(hash)) {
- log.info("Found header " + b.getHashAsString());
- found = true;
- }
- }
- if (found)
- break;
- }
- if (!found)
- sendHeaders = headers;
- bitcoind.sendMessage(new HeadersMessage(params, sendHeaders));
- InventoryMessage i = new InventoryMessage(params);
- for (Block b : sendHeaders)
- i.addBlock(b);
- bitcoind.sendMessage(i);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- return null;
- } else if (m instanceof InventoryMessage) {
- if (mostRecentInv != null) {
- log.error("Got an inv when we weren't expecting one");
- unexpectedInvs.incrementAndGet();
- }
- mostRecentInv = (InventoryMessage) m;
- }
- return m;
- }
- }, Threading.SAME_THREAD);
-
-
- bitcoindChainHead = params.getGenesisBlock().getHash();
-
- // bitcoind MUST be on localhost or we will get banned as a DoSer
- new NioClient(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), args.length > 2 ? Integer.parseInt(args[2]) : params.getPort()), bitcoind, 1000);
-
- connectedFuture.get();
-
- ArrayList locator = new ArrayList(1);
- locator.add(params.getGenesisBlock().getHash());
- Sha256Hash hashTo = new Sha256Hash("0000000000000000000000000000000000000000000000000000000000000000");
-
- int rulesSinceFirstFail = 0;
- for (Rule rule : blockList.list) {
- if (rule instanceof FullBlockTestGenerator.BlockAndValidity) {
- FullBlockTestGenerator.BlockAndValidity block = (FullBlockTestGenerator.BlockAndValidity) rule;
- boolean threw = false;
- Block nextBlock = preloadedBlocks.get(((FullBlockTestGenerator.BlockAndValidity) rule).blockHash);
- // Often load at least one block because sometimes we have duplicates with the same hash (b56/57)
- for (int i = 0; i < 1
- || nextBlock == null || !nextBlock.getHash().equals(block.blockHash);
- i++) {
- try {
- Block b = blocks.next();
- Block oldBlockWithSameHash = preloadedBlocks.put(b.getHash(), b);
- if (oldBlockWithSameHash != null && oldBlockWithSameHash.getTransactions().size() != b.getTransactions().size())
- blocksRequested.remove(b.getHash());
- nextBlock = preloadedBlocks.get(block.blockHash);
- } catch (NoSuchElementException e) {
- if (nextBlock == null || !nextBlock.getHash().equals(block.blockHash))
- throw e;
- }
- }
- currentBlock.block = nextBlock;
- log.info("Testing block {} {}", block.ruleName, currentBlock.block.getHash());
- try {
- if (chain.add(nextBlock) != block.connects) {
- log.error("ERROR: Block didn't match connects flag on block \"" + block.ruleName + "\"");
- rulesSinceFirstFail++;
- }
- } catch (VerificationException e) {
- threw = true;
- if (!block.throwsException) {
- log.error("ERROR: Block didn't match throws flag on block \"" + block.ruleName + "\"");
- e.printStackTrace();
- rulesSinceFirstFail++;
- } else if (block.connects) {
- log.error("ERROR: Block didn't match connects flag on block \"" + block.ruleName + "\"");
- e.printStackTrace();
- rulesSinceFirstFail++;
- }
- }
- if (!threw && block.throwsException) {
- log.error("ERROR: Block didn't match throws flag on block \"" + block.ruleName + "\"");
- rulesSinceFirstFail++;
- } else if (!chain.getChainHead().getHeader().getHash().equals(block.hashChainTipAfterBlock)) {
- log.error("ERROR: New block head didn't match the correct value after block \"" + block.ruleName + "\"");
- rulesSinceFirstFail++;
- } else if (chain.getChainHead().getHeight() != block.heightAfterBlock) {
- log.error("ERROR: New block head didn't match the correct height after block " + block.ruleName);
- rulesSinceFirstFail++;
- }
-
- // Shouldnt double-request
- boolean shouldntRequest = blocksRequested.contains(nextBlock.getHash());
- if (shouldntRequest)
- blocksRequested.remove(nextBlock.getHash());
- InventoryMessage message = new InventoryMessage(params);
- message.addBlock(nextBlock);
- bitcoind.sendMessage(message);
- log.info("Sent inv with block " + nextBlock.getHashAsString());
- if (blocksPendingSend.contains(nextBlock.getHash())) {
- bitcoind.sendMessage(nextBlock);
- log.info("Sent full block " + nextBlock.getHashAsString());
- }
- // bitcoind doesn't request blocks inline so we can't rely on a ping for synchronization
- for (int i = 0; !shouldntRequest && !blocksRequested.contains(nextBlock.getHash()); i++) {
- int SLEEP_TIME = 1;
- if (i % 1000/SLEEP_TIME == 1000/SLEEP_TIME - 1)
- log.error("bitcoind still hasn't requested block " + block.ruleName + " with hash " + nextBlock.getHash());
- Thread.sleep(SLEEP_TIME);
- if (i > 60000/SLEEP_TIME) {
- log.error("bitcoind failed to request block " + block.ruleName);
- System.exit(1);
- }
- }
- if (shouldntRequest) {
- Thread.sleep(100);
- if (blocksRequested.contains(nextBlock.getHash())) {
- log.error("ERROR: bitcoind re-requested block " + block.ruleName + " with hash " + nextBlock.getHash());
- rulesSinceFirstFail++;
- }
- }
- // If the block throws, we may want to get bitcoind to request the same block again
- if (block.throwsException)
- blocksRequested.remove(nextBlock.getHash());
- //bitcoind.sendMessage(nextBlock);
- locator.clear();
- locator.add(bitcoindChainHead);
- bitcoind.sendMessage(new GetHeadersMessage(params, locator, hashTo));
- bitcoind.ping().get();
- if (!chain.getChainHead().getHeader().getHash().equals(bitcoindChainHead)) {
- rulesSinceFirstFail++;
- log.error("ERROR: bitcoind and bitcoinj acceptance differs on block \"" + block.ruleName + "\"");
- }
- if (block.sendOnce)
- preloadedBlocks.remove(nextBlock.getHash());
- log.info("Block \"" + block.ruleName + "\" completed processing");
- } else if (rule instanceof MemoryPoolState) {
- MemoryPoolMessage message = new MemoryPoolMessage();
- bitcoind.sendMessage(message);
- bitcoind.ping().get();
- if (mostRecentInv == null && !((MemoryPoolState) rule).mempool.isEmpty()) {
- log.error("ERROR: bitcoind had an empty mempool, but we expected some transactions on rule " + rule.ruleName);
- rulesSinceFirstFail++;
- } else if (mostRecentInv != null && ((MemoryPoolState) rule).mempool.isEmpty()) {
- log.error("ERROR: bitcoind had a non-empty mempool, but we expected an empty one on rule " + rule.ruleName);
- rulesSinceFirstFail++;
- } else if (mostRecentInv != null) {
- Set originalRuleSet = new HashSet(((MemoryPoolState)rule).mempool);
- boolean matches = mostRecentInv.items.size() == ((MemoryPoolState)rule).mempool.size();
- for (InventoryItem item : mostRecentInv.items)
- if (!((MemoryPoolState) rule).mempool.remove(item))
- matches = false;
- if (matches)
- continue;
- log.error("bitcoind's mempool didn't match what we were expecting on rule " + rule.ruleName);
- log.info(" bitcoind's mempool was: ");
- for (InventoryItem item : mostRecentInv.items)
- log.info(" " + item.hash);
- log.info(" The expected mempool was: ");
- for (InventoryItem item : originalRuleSet)
- log.info(" " + item.hash);
- rulesSinceFirstFail++;
- }
- mostRecentInv = null;
- } else if (rule instanceof UTXORule) {
- if (bitcoind.getPeerVersionMessage().isGetUTXOsSupported()) {
- UTXORule r = (UTXORule) rule;
- UTXOsMessage result = bitcoind.getUTXOs(r.query).get();
- if (!result.equals(r.result)) {
- log.error("utxo result was not what we expected.");
- log.error("Wanted {}", r.result);
- log.error("but got {}", result);
- rulesSinceFirstFail++;
- } else {
- log.info("Successful utxo query {}: {}", r.ruleName, result);
- }
- }
- } else {
- throw new RuntimeException("Unknown rule");
- }
- if (rulesSinceFirstFail > 0)
- rulesSinceFirstFail++;
- if (rulesSinceFirstFail > 6)
- System.exit(1);
- }
-
- if (unexpectedInvs.get() > 0)
- log.error("ERROR: Got " + unexpectedInvs.get() + " unexpected invs from bitcoind");
- log.info("Done testing.");
- System.exit(rulesSinceFirstFail > 0 || unexpectedInvs.get() > 0 ? 1 : 0);
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/BlockChainTest.java b/core/src/test/java/com/dogecoin/dogecoinj/core/BlockChainTest.java
deleted file mode 100644
index 028579e0..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/BlockChainTest.java
+++ /dev/null
@@ -1,458 +0,0 @@
-/**
- * Copyright 2011 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 com.dogecoin.dogecoinj.core;
-
-import com.dogecoin.dogecoinj.core.Wallet.BalanceType;
-import com.dogecoin.dogecoinj.params.MainNetParams;
-import com.dogecoin.dogecoinj.params.TestNet2Params;
-import com.dogecoin.dogecoinj.params.UnitTestParams;
-import com.dogecoin.dogecoinj.store.BlockStore;
-import com.dogecoin.dogecoinj.store.MemoryBlockStore;
-import com.dogecoin.dogecoinj.testing.FakeTxBuilder;
-import com.dogecoin.dogecoinj.utils.BriefLogFormatter;
-import com.google.common.util.concurrent.ListenableFuture;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.math.BigInteger;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-
-import static com.dogecoin.dogecoinj.core.Coin.*;
-import static com.dogecoin.dogecoinj.testing.FakeTxBuilder.createFakeBlock;
-import static com.dogecoin.dogecoinj.testing.FakeTxBuilder.createFakeTx;
-import static org.junit.Assert.*;
-
-// Handling of chain splits/reorgs are in ChainSplitTests.
-
-public class BlockChainTest {
- private BlockChain testNetChain;
-
- private Wallet wallet;
- private BlockChain chain;
- private BlockStore blockStore;
- private Address coinbaseTo;
- private NetworkParameters unitTestParams;
- private final StoredBlock[] block = new StoredBlock[1];
- private Transaction coinbaseTransaction;
-
- private static class TweakableTestNet2Params extends TestNet2Params {
- public void setMaxTarget(BigInteger limit) {
- maxTarget = limit;
- }
- }
- private static final TweakableTestNet2Params testNet = new TweakableTestNet2Params();
-
- private void resetBlockStore() {
- blockStore = new MemoryBlockStore(unitTestParams);
- }
-
- @Before
- public void setUp() throws Exception {
- BriefLogFormatter.initVerbose();
- testNetChain = new BlockChain(testNet, new Wallet(testNet), new MemoryBlockStore(testNet));
- Wallet.SendRequest.DEFAULT_FEE_PER_KB = Coin.ZERO;
-
- unitTestParams = UnitTestParams.get();
- wallet = new Wallet(unitTestParams) {
- @Override
- public void receiveFromBlock(Transaction tx, StoredBlock block, BlockChain.NewBlockType blockType,
- int relativityOffset) throws VerificationException {
- super.receiveFromBlock(tx, block, blockType, relativityOffset);
- BlockChainTest.this.block[0] = block;
- if (tx.isCoinBase()) {
- BlockChainTest.this.coinbaseTransaction = tx;
- }
- }
- };
- wallet.freshReceiveKey();
-
- resetBlockStore();
- chain = new BlockChain(unitTestParams, wallet, blockStore);
-
- coinbaseTo = wallet.currentReceiveKey().toAddress(unitTestParams);
- }
-
- @After
- public void tearDown() {
- Wallet.SendRequest.DEFAULT_FEE_PER_KB = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
- }
-
- @Test
- public void testBasicChaining() throws Exception {
- // Check that we can plug a few blocks together and the futures work.
- ListenableFuture future = testNetChain.getHeightFuture(2);
- // Block 1 from the testnet.
- Block b1 = getBlock1();
- assertTrue(testNetChain.add(b1));
- assertFalse(future.isDone());
- // Block 2 from the testnet.
- Block b2 = getBlock2();
-
- // Let's try adding an invalid block.
- long n = b2.getNonce();
- try {
- b2.setNonce(12345);
- testNetChain.add(b2);
- fail();
- } catch (VerificationException e) {
- b2.setNonce(n);
- }
-
- // Now it works because we reset the nonce.
- assertTrue(testNetChain.add(b2));
- assertTrue(future.isDone());
- assertEquals(2, future.get().getHeight());
- }
-
- @Test
- public void receiveCoins() throws Exception {
- // Quick check that we can actually receive coins.
- Transaction tx1 = createFakeTx(unitTestParams,
- COIN,
- wallet.currentReceiveKey().toAddress(unitTestParams));
- Block b1 = createFakeBlock(blockStore, tx1).block;
- chain.add(b1);
- assertTrue(wallet.getBalance().signum() > 0);
- }
-
- @Test
- public void merkleRoots() throws Exception {
- // Test that merkle root verification takes place when a relevant transaction is present and doesn't when
- // there isn't any such tx present (as an optimization).
- Transaction tx1 = createFakeTx(unitTestParams,
- COIN,
- wallet.currentReceiveKey().toAddress(unitTestParams));
- Block b1 = createFakeBlock(blockStore, tx1).block;
- chain.add(b1);
- resetBlockStore();
- Sha256Hash hash = b1.getMerkleRoot();
- b1.setMerkleRoot(Sha256Hash.ZERO_HASH);
- try {
- chain.add(b1);
- fail();
- } catch (VerificationException e) {
- // Expected.
- b1.setMerkleRoot(hash);
- }
- // Now add a second block with no relevant transactions and then break it.
- Transaction tx2 = createFakeTx(unitTestParams, COIN,
- new ECKey().toAddress(unitTestParams));
- Block b2 = createFakeBlock(blockStore, tx2).block;
- b2.getMerkleRoot();
- b2.setMerkleRoot(Sha256Hash.ZERO_HASH);
- b2.solve();
- chain.add(b2); // Broken block is accepted because its contents don't matter to us.
- }
-
- @Test
- public void unconnectedBlocks() throws Exception {
- Block b1 = unitTestParams.getGenesisBlock().createNextBlock(coinbaseTo);
- Block b2 = b1.createNextBlock(coinbaseTo);
- Block b3 = b2.createNextBlock(coinbaseTo);
- // Connected.
- assertTrue(chain.add(b1));
- // Unconnected but stored. The head of the chain is still b1.
- assertFalse(chain.add(b3));
- assertEquals(chain.getChainHead().getHeader(), b1.cloneAsHeader());
- // Add in the middle block.
- assertTrue(chain.add(b2));
- assertEquals(chain.getChainHead().getHeader(), b3.cloneAsHeader());
- }
-
- @Test
- public void difficultyTransitions() throws Exception {
- // Add a bunch of blocks in a loop until we reach a difficulty transition point. The unit test params have an
- // artificially shortened period.
- Block prev = unitTestParams.getGenesisBlock();
- Utils.setMockClock(System.currentTimeMillis()/1000);
- for (int i = 0; i < unitTestParams.getInterval() - 1; i++) {
- Block newBlock = prev.createNextBlock(coinbaseTo, Utils.currentTimeSeconds());
- assertTrue(chain.add(newBlock));
- prev = newBlock;
- // The fake chain should seem to be "fast" for the purposes of difficulty calculations.
- Utils.rollMockClock(2);
- }
- // Now add another block that has no difficulty adjustment, it should be rejected.
- try {
- chain.add(prev.createNextBlock(coinbaseTo, Utils.currentTimeSeconds()));
- fail();
- } catch (VerificationException e) {
- }
- // Create a new block with the right difficulty target given our blistering speed relative to the huge amount
- // of time it's supposed to take (set in the unit test network parameters).
- Block b = prev.createNextBlock(coinbaseTo, Utils.currentTimeSeconds());
- b.setDifficultyTarget(0x201fFFFFL);
- b.solve();
- assertTrue(chain.add(b));
- // Successfully traversed a difficulty transition period.
- }
-
- @Test
- public void badDifficulty() throws Exception {
- assertTrue(testNetChain.add(getBlock1()));
- Block b2 = getBlock2();
- assertTrue(testNetChain.add(b2));
- Block bad = new Block(testNet);
- // Merkle root can be anything here, doesn't matter.
- bad.setMerkleRoot(new Sha256Hash("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
- // Nonce was just some number that made the hash < difficulty limit set below, it can be anything.
- bad.setNonce(140548933);
- bad.setTime(1279242649);
- bad.setPrevBlockHash(b2.getHash());
- // We're going to make this block so easy 50% of solutions will pass, and check it gets rejected for having a
- // bad difficulty target. Unfortunately the encoding mechanism means we cannot make one that accepts all
- // solutions.
- bad.setDifficultyTarget(Block.EASIEST_DIFFICULTY_TARGET);
- try {
- testNetChain.add(bad);
- // The difficulty target above should be rejected on the grounds of being easier than the networks
- // allowable difficulty.
- fail();
- } catch (VerificationException e) {
- assertTrue(e.getMessage(), e.getCause().getMessage().contains("Difficulty target is bad"));
- }
-
- // Accept any level of difficulty now.
- BigInteger oldVal = testNet.getMaxTarget();
- testNet.setMaxTarget(new BigInteger("00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16));
- try {
- testNetChain.add(bad);
- // We should not get here as the difficulty target should not be changing at this point.
- fail();
- } catch (VerificationException e) {
- assertTrue(e.getMessage(), e.getCause().getMessage().contains("Unexpected change in difficulty"));
- }
- testNet.setMaxTarget(oldVal);
-
- // TODO: Test difficulty change is not out of range when a transition period becomes valid.
- }
-
- @Test
- public void duplicates() throws Exception {
- // Adding a block twice should not have any effect, in particular it should not send the block to the wallet.
- Block b1 = unitTestParams.getGenesisBlock().createNextBlock(coinbaseTo);
- Block b2 = b1.createNextBlock(coinbaseTo);
- Block b3 = b2.createNextBlock(coinbaseTo);
- assertTrue(chain.add(b1));
- assertEquals(b1, block[0].getHeader());
- assertTrue(chain.add(b2));
- assertEquals(b2, block[0].getHeader());
- assertTrue(chain.add(b3));
- assertEquals(b3, block[0].getHeader());
- assertEquals(b3, chain.getChainHead().getHeader());
- assertTrue(chain.add(b2));
- assertEquals(b3, chain.getChainHead().getHeader());
- // Wallet was NOT called with the new block because the duplicate add was spotted.
- assertEquals(b3, block[0].getHeader());
- }
-
- @Test
- public void intraBlockDependencies() throws Exception {
- // Covers issue 166 in which transactions that depend on each other inside a block were not always being
- // considered relevant.
- Address somebodyElse = new ECKey().toAddress(unitTestParams);
- Block b1 = unitTestParams.getGenesisBlock().createNextBlock(somebodyElse);
- ECKey key = wallet.freshReceiveKey();
- Address addr = key.toAddress(unitTestParams);
- // Create a tx that gives us some coins, and another that spends it to someone else in the same block.
- Transaction t1 = FakeTxBuilder.createFakeTx(unitTestParams, COIN, addr);
- Transaction t2 = new Transaction(unitTestParams);
- t2.addInput(t1.getOutputs().get(0));
- t2.addOutput(valueOf(2, 0), somebodyElse);
- b1.addTransaction(t1);
- b1.addTransaction(t2);
- b1.solve();
- chain.add(b1);
- assertEquals(Coin.ZERO, wallet.getBalance());
- }
-
- @Test
- public void coinbaseTransactionAvailability() throws Exception {
- // Check that a coinbase transaction is only available to spend after NetworkParameters.getSpendableCoinbaseDepth() blocks.
-
- // Create a second wallet to receive the coinbase spend.
- Wallet wallet2 = new Wallet(unitTestParams);
- ECKey receiveKey = wallet2.freshReceiveKey();
- chain.addWallet(wallet2);
-
- Address addressToSendTo = receiveKey.toAddress(unitTestParams);
-
- // Create a block, sending the coinbase to the coinbaseTo address (which is in the wallet).
- Block b1 = unitTestParams.getGenesisBlock().createNextBlockWithCoinbase(wallet.currentReceiveKey().getPubKey());
- chain.add(b1);
-
- // Check a transaction has been received.
- assertNotNull(coinbaseTransaction);
-
- // The coinbase tx is not yet available to spend.
- assertEquals(Coin.ZERO, wallet.getBalance());
- assertEquals(wallet.getBalance(BalanceType.ESTIMATED), FIFTY_COINS);
- assertTrue(!coinbaseTransaction.isMature());
-
- // Attempt to spend the coinbase - this should fail as the coinbase is not mature yet.
- try {
- wallet.createSend(addressToSendTo, valueOf(49, 0));
- fail();
- } catch (InsufficientMoneyException e) {
- }
-
- // Check that the coinbase is unavailable to spend for the next spendableCoinbaseDepth - 2 blocks.
- for (int i = 0; i < unitTestParams.getSpendableCoinbaseDepth() - 2; i++) {
- // Non relevant tx - just for fake block creation.
- Transaction tx2 = createFakeTx(unitTestParams, COIN,
- new ECKey().toAddress(unitTestParams));
-
- Block b2 = createFakeBlock(blockStore, tx2).block;
- chain.add(b2);
-
- // Wallet still does not have the coinbase transaction available for spend.
- assertEquals(Coin.ZERO, wallet.getBalance());
- assertEquals(wallet.getBalance(BalanceType.ESTIMATED), FIFTY_COINS);
-
- // The coinbase transaction is still not mature.
- assertTrue(!coinbaseTransaction.isMature());
-
- // Attempt to spend the coinbase - this should fail.
- try {
- wallet.createSend(addressToSendTo, valueOf(49, 0));
- fail();
- } catch (InsufficientMoneyException e) {
- }
- }
-
- // Give it one more block - should now be able to spend coinbase transaction. Non relevant tx.
- Transaction tx3 = createFakeTx(unitTestParams, COIN, new ECKey().toAddress(unitTestParams));
- Block b3 = createFakeBlock(blockStore, tx3).block;
- chain.add(b3);
-
- // Wallet now has the coinbase transaction available for spend.
- assertEquals(wallet.getBalance(), FIFTY_COINS);
- assertEquals(wallet.getBalance(BalanceType.ESTIMATED), FIFTY_COINS);
- assertTrue(coinbaseTransaction.isMature());
-
- // Create a spend with the coinbase BTC to the address in the second wallet - this should now succeed.
- Transaction coinbaseSend2 = wallet.createSend(addressToSendTo, valueOf(49, 0));
- assertNotNull(coinbaseSend2);
-
- // Commit the coinbaseSpend to the first wallet and check the balances decrement.
- wallet.commitTx(coinbaseSend2);
- assertEquals(wallet.getBalance(BalanceType.ESTIMATED), COIN);
- // Available balance is zero as change has not been received from a block yet.
- assertEquals(wallet.getBalance(BalanceType.AVAILABLE), ZERO);
-
- // Give it one more block - change from coinbaseSpend should now be available in the first wallet.
- Block b4 = createFakeBlock(blockStore, coinbaseSend2).block;
- chain.add(b4);
- assertEquals(wallet.getBalance(BalanceType.AVAILABLE), COIN);
-
- // Check the balances in the second wallet.
- assertEquals(wallet2.getBalance(BalanceType.ESTIMATED), valueOf(49, 0));
- assertEquals(wallet2.getBalance(BalanceType.AVAILABLE), valueOf(49, 0));
- }
-
- // Some blocks from the test net.
- private static Block getBlock2() throws Exception {
- Block b2 = new Block(testNet);
- b2.setMerkleRoot(new Sha256Hash("addc858a17e21e68350f968ccd384d6439b64aafa6c193c8b9dd66320470838b"));
- b2.setNonce(2642058077L);
- b2.setTime(1296734343L);
- b2.setPrevBlockHash(new Sha256Hash("000000033cc282bc1fa9dcae7a533263fd7fe66490f550d80076433340831604"));
- assertEquals("000000037b21cac5d30fc6fda2581cf7b2612908aed2abbcc429c45b0557a15f", b2.getHashAsString());
- b2.verifyHeader();
- return b2;
- }
-
- private static Block getBlock1() throws Exception {
- Block b1 = new Block(testNet);
- b1.setMerkleRoot(new Sha256Hash("0e8e58ecdacaa7b3c6304a35ae4ffff964816d2b80b62b58558866ce4e648c10"));
- b1.setNonce(236038445);
- b1.setTime(1296734340);
- b1.setPrevBlockHash(new Sha256Hash("00000007199508e34a9ff81e6ec0c477a4cccff2a4767a8eee39c11db367b008"));
- assertEquals("000000033cc282bc1fa9dcae7a533263fd7fe66490f550d80076433340831604", b1.getHashAsString());
- b1.verifyHeader();
- return b1;
- }
-
- @Test
- public void estimatedBlockTime() throws Exception {
- NetworkParameters params = MainNetParams.get();
- BlockChain prod = new BlockChain(params, new MemoryBlockStore(params));
- Date d = prod.estimateBlockTime(200000);
- // The actual date of block 200,000 was 2012-09-22 10:47:00
- assertEquals(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US).parse("2012-10-23T08:35:05.000-0700"), d);
- }
-
- @Test
- public void falsePositives() throws Exception {
- double decay = AbstractBlockChain.FP_ESTIMATOR_ALPHA;
- assertTrue(0 == chain.getFalsePositiveRate()); // Exactly
- chain.trackFalsePositives(55);
- assertEquals(decay * 55, chain.getFalsePositiveRate(), 1e-4);
- chain.trackFilteredTransactions(550);
- double rate1 = chain.getFalsePositiveRate();
- // Run this scenario a few more time for the filter to converge
- for (int i = 1 ; i < 10 ; i++) {
- chain.trackFalsePositives(55);
- chain.trackFilteredTransactions(550);
- }
-
- // Ensure we are within 10%
- assertEquals(0.1, chain.getFalsePositiveRate(), 0.01);
-
- // Check that we get repeatable results after a reset
- chain.resetFalsePositiveEstimate();
- assertTrue(0 == chain.getFalsePositiveRate()); // Exactly
-
- chain.trackFalsePositives(55);
- assertEquals(decay * 55, chain.getFalsePositiveRate(), 1e-4);
- chain.trackFilteredTransactions(550);
- assertEquals(rate1, chain.getFalsePositiveRate(), 1e-4);
- }
-
- @Test
- public void rollbackBlockStore() throws Exception {
- // This test simulates an issue on Android, that causes the VM to crash while receiving a block, so that the
- // block store is persisted but the wallet is not.
- Block b1 = unitTestParams.getGenesisBlock().createNextBlock(coinbaseTo);
- Block b2 = b1.createNextBlock(coinbaseTo);
- // Add block 1, no frills.
- assertTrue(chain.add(b1));
- assertEquals(b1.cloneAsHeader(), chain.getChainHead().getHeader());
- assertEquals(1, chain.getBestChainHeight());
- assertEquals(1, wallet.getLastBlockSeenHeight());
- // Add block 2 while wallet is disconnected, to simulate crash.
- chain.removeWallet(wallet);
- assertTrue(chain.add(b2));
- assertEquals(b2.cloneAsHeader(), chain.getChainHead().getHeader());
- assertEquals(2, chain.getBestChainHeight());
- assertEquals(1, wallet.getLastBlockSeenHeight());
- // Add wallet back. This will detect the height mismatch and repair the damage done.
- chain.addWallet(wallet);
- assertEquals(b1.cloneAsHeader(), chain.getChainHead().getHeader());
- assertEquals(1, chain.getBestChainHeight());
- assertEquals(1, wallet.getLastBlockSeenHeight());
- // Now add block 2 correctly.
- assertTrue(chain.add(b2));
- assertEquals(b2.cloneAsHeader(), chain.getChainHead().getHeader());
- assertEquals(2, chain.getBestChainHeight());
- assertEquals(2, wallet.getLastBlockSeenHeight());
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/BlockTest.java b/core/src/test/java/com/dogecoin/dogecoinj/core/BlockTest.java
deleted file mode 100644
index 0ae3bfc2..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/BlockTest.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/**
- * Copyright 2011 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 com.dogecoin.dogecoinj.core;
-
-import com.dogecoin.dogecoinj.params.TestNet2Params;
-import com.dogecoin.dogecoinj.params.UnitTestParams;
-import com.dogecoin.dogecoinj.script.ScriptOpCodes;
-import org.junit.Test;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.math.BigInteger;
-import java.util.Arrays;
-
-import static com.dogecoin.dogecoinj.core.Utils.HEX;
-import static org.junit.Assert.*;
-
-public class BlockTest {
- static final NetworkParameters params = TestNet2Params.get();
-
- public static final byte[] blockBytes;
-
- static {
- // Block 00000000a6e5eb79dcec11897af55e90cd571a4335383a3ccfbc12ec81085935
- // One with lots of transactions in, so a good test of the merkle tree hashing.
- blockBytes = HEX.decode("0100000040f11b68435988807d64dff20261f7d9827825fbb37542601fb94d45000000000f28f7c69e2669981f92ff081c129e196200c60f4fad7911d93a682de0b49ea2ecd9d24c1844011d00d361050c01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07041844011d0142ffffffff0100f2052a01000000434104a313febd5f91b6a13bd9c5317030518fee96d1319a0eb10076917294933d09c17dc1588a06953a264738f2acea0c66b99e796caa4f28158e0dd5f6fed69a185bac000000000100000001aa18a952c3f73e5d7440bc570b2aa78f72059887b25b6a1790514b7feedec090000000008b483045022100a970ee6e96fa8bea1cf76d3bda3fb70441a6ec50014d4ea3adcdeae9fbfb5129022025ce9e090366dd6175071a0a5b4a4727571b9bd7bdd5a74d3d3bad7f63eb5dd4014104ac44bdf511477465cb70fef1d06b9241e74d26047ccbdfa641ec9a0115ad35594cbb58a61a6fd56893a405bcffbf6555995ddedc7e6cd4e5ceb83a37e1cf8f98ffffffff02004d92d86a0000001976a914b8083945473bc8289efb681f94de7b07a5b851ad88ac00743ba40b0000001976a914ef01911c9efec6799d1ee5f7c6fb072d9669da8088ac000000000100000001438bd97cb2172e0dd6f341e455e00b7d089747bd4e7f54bd802afe6a6d006c7c000000008a47304402207db94026c96572519101a08e2c864bbe51c987eda6266079a35286df68f123ca02202d7d24c616776a70cce6cb2f97a424e47c30d466e96b750ca03564810249073c014104880286646dab4c894a5ff1bf62bd80047a50b86446b326f2155de94a54d01f9058d4cbc7452563a7c18b2bfb353262fc5adac6307a9446e8c4669daa58e97071ffffffff0200743ba40b0000001976a914fce443c743b456606d1e70ff0d98c4609addc10688ac00ba1dd2050000001976a91411e3e67c08e5d791c97b3d49a8d52025d3f78d3a88ac000000000100000001dc4a6300b6eca8d7ab8e119e9fc4b18890c0e26ec950e681b8d5e46c214aee24010000008b48304502202bcf8632a11192f6b4998343c13589771e6715a080236087dcb1771cbab01809022100edcc38488dd70cd38c058994f143ca5d259071b8fe54c66bf67e55d4468dcacb01410475106e33e14e9cf35bc359dd4120b580ecf5412bb8803f2a927aecd4218d1346e242c7056dca2e4c114fcf2f60799bc5e79107bd1a8b8d5135c92f02bdb59834ffffffff0200f2052a010000001976a9146c9715e09fb00ba84af1ff916ff409b4a5dc9ae288ac00c817a8040000001976a914f7be161206700eb7be1bca5768232c61e4694f4788ac000000000100000001b6cc12ff76247895cb7a604d888012136f06bba64654262044ecb93ff7762c2f000000008b48304502206d795045622c7cdfb4a211c5b41d477920437c21e69214ab4a14f10fe0306b78022100840e55114d6922f3c5e44c7cdcf85dc800d1caef64e7846998423e4ba86714e6014104f88ae9067bc05136cb53a8c18f8549f544ff55ab87ada8f3ba7e2aea773ec73585b61f18ade1c0ddd6c447788578be5fb785c245a64d29b7ff5d28b85cbec58cffffffff0200743ba40b0000001976a914c8081083a8b741da2da260bc0656b88c7bfa6fbf88ac00743ba40b0000001976a914fce443c743b456606d1e70ff0d98c4609addc10688ac0000000001000000019a8d70c7a27560b28dfe778db9ce7f2ff235faf98d5123c07991682be90a4c16000000008b483045022100a118c34f63854ee03d15cca2918d592c295035c42e03be7b0c7e86e66d40ea790220558336d2583a1da00ed5bcad2de5d3b9d485431f702bf2f002267b35ab0b41a0014104f88ae9067bc05136cb53a8c18f8549f544ff55ab87ada8f3ba7e2aea773ec73585b61f18ade1c0ddd6c447788578be5fb785c245a64d29b7ff5d28b85cbec58cffffffff0200743ba40b0000001976a914a440ef00c2e1d39be93607da66568caa26e0501888ac00743ba40b0000001976a914e1d3e65f78f962c4e9dfd04db2119aeefa4e111088ac000000000100000001883acd4bff920f19c4e570e6b3e2d7503d1072d3ca098a124e23534ecdc879d5000000008a473044022040677305de69fd8c18e2c54d5b3c67c5c05735cf6b73d420ccd306762c4bfda2022032cd32ac15ac1820265ffce82654a6008cda22a79fb619ebb65e0af806e14f9b0141044423ef78a2859eb57c4a59dc0878141cf5a4b1fdef71d649d3fb5cf8ea6b1114f4086e5d684a0999d4435db99217a994cc3cf7ad435c8f4e44613d9d160916c4ffffffff0100743ba40b0000001976a914fce443c743b456606d1e70ff0d98c4609addc10688ac000000000100000001ceb27fb142ce3bf9a1f263653dc3971332c71dd10e0e83d647037f608c459f12000000008b4830450220389218287e87d0d7b7113eb20cc1cbf1a00d7acdca32bba7f184cd066db74d6a022100b0998058e5a242699a48f931004cf5550f4e8802b866ce1baf1a0b2616861f27014104255a048d416984101c17514a89289a7d5d3dc8c562850c7a3599f0c7c39bcf9c3a43df75e1e614e51d70c5f85212c99298a21f087be93ecba7ef3900d02c0e8bffffffff0200743ba40b0000001976a914211fd13b614521ed566ddd42738381e42c3c2b2088ac00d956345f0000001976a914d3cc345ba8bdf51d7097955f0f259731f4c34f4388ac000000000100000001703701493f08e82bf6d8cb7c517070eee9f62d14904e14636a7b4af4f34180c7010000008a4730440220061a61eae90ffcf13c10c88a88c085b02954f488823c2f5c81e83a5a833e9f3b02204a61498a9668b2793e77fe3b68585f2daff4dd5daf6097a82615035325ada4730141040db6308d6170333e2c50dee4c9f18f0ab84a7a5c4c88a6836a91f39cb8f4712e08bd72979c542d4b3b60e8dc2021c1b3cc45ffaa83f36a9dec3c4473ea2aa2f3ffffffff0200f2052a010000001976a9143e7e087b9b09149e0266b7a416da2709b4ccf58788ac00d6117e030000001976a914777af71a3b2a48e48f2e467f65028d85c1b5eb5288ac0000000001000000014bdc82abc7db9c06613a712e488685c6feb4522d25017b856222171c17d144e0000000008b4830450221009eb7edcbf8d6be63529264b07bb9f40cf1a0ca779235999e40f5311d70706f1102207f65c5f66982519e6d82e13ca3e61f4f071c73da6c5830b3c4461252012b474e0141045af9665878e6696fd069669951acc54a87c5e3b256a9e20cd8858e0dc5a8c53624e0c979096c00af8a8c60136eef9ffa3d511309417b8315b7f9e3e41e805e8fffffffff0100743ba40b0000001976a914e1d3e65f78f962c4e9dfd04db2119aeefa4e111088ac000000000100000001a854b2b84a76e43de59db647121cdfe481bd8ae9623a345c2188369775b533f7010000008c493046022100c4db6ecf679264c9b525628ec5a983710ff45a1d2d4aa0b54ee218ca9a1ad4df022100dc2e0077cfdd3cbeb28f7463632902ad5306f6d5c77c8149e5b9249bfea8060e014104f9a476b612bb9788c64b9b1e4c9d2deaae1ef0baf6eb593a95d00e2ef8a2beb897ea1fb7c3832e842dd6307fd162816c19c8f458fd8dae331dbc9062fb02e5d8ffffffff0200651b90530000001976a914d5c7c9aec292a807005f013c4d2122f7126e257788ac00743ba40b0000001976a914211fd13b614521ed566ddd42738381e42c3c2b2088ac0000000001000000012908482e9f7d31e9dd392bb6e788a329458a3bc95230b468e4b8c578d27a63b3000000008a4730440220549a7b422fc2020671acabfb937349bd87d985b2e4b9698e4ccacc985f61aee102204dc272322079e9114746db2f8d035d82b64523a69cd7be674173e063090cc8ac014104011a6c220a5549ff112c92c6c38dec93f66ef1f0a21d1409b92f0ccf0fb159aa8173a5b2413a45140fc02b45d63775bae03691d9dc87fd7a10d709a04922900cffffffff0200743ba40b0000001976a914211fd13b614521ed566ddd42738381e42c3c2b2088ac00f1dfeb470000001976a9140adcb4e90cc87f53d7618294222a8a4e193ae9f088ac00000000");
- }
-
- @Test
- public void testWork() throws Exception {
- BigInteger work = params.getGenesisBlock().getWork();
- // This number is printed by the official client at startup as the calculated value of chainWork on testnet:
- //
- // SetBestChain: new best=00000007199508e34a9f height=0 work=536879104
- assertEquals(BigInteger.valueOf(536879104L), work);
- }
-
- @Test
- public void testBlockVerification() throws Exception {
- Block block = new Block(params, blockBytes);
- block.verify();
- assertEquals("00000000a6e5eb79dcec11897af55e90cd571a4335383a3ccfbc12ec81085935", block.getHashAsString());
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testDate() throws Exception {
- Block block = new Block(params, blockBytes);
- assertEquals("4 Nov 2010 16:06:04 GMT", block.getTime().toGMTString());
- }
-
- @Test
- public void testProofOfWork() throws Exception {
- // This params accepts any difficulty target.
- NetworkParameters params = UnitTestParams.get();
- Block block = new Block(params, blockBytes);
- block.setNonce(12346);
- try {
- block.verify();
- fail();
- } catch (VerificationException e) {
- // Expected.
- }
- // Blocks contain their own difficulty target. The BlockChain verification mechanism is what stops real blocks
- // from containing artificially weak difficulties.
- block.setDifficultyTarget(Block.EASIEST_DIFFICULTY_TARGET);
- // Now it should pass.
- block.verify();
- // Break the nonce again at the lower difficulty level so we can try solving for it.
- block.setNonce(1);
- try {
- block.verify();
- fail();
- } catch (VerificationException e) {
- // Expected to fail as the nonce is no longer correct.
- }
- // Should find an acceptable nonce.
- block.solve();
- block.verify();
- assertEquals(block.getNonce(), 2);
- }
-
- @Test
- public void testBadTransactions() throws Exception {
- Block block = new Block(params, blockBytes);
- // Re-arrange so the coinbase transaction is not first.
- Transaction tx1 = block.transactions.get(0);
- Transaction tx2 = block.transactions.get(1);
- block.transactions.set(0, tx2);
- block.transactions.set(1, tx1);
- try {
- block.verify();
- fail();
- } catch (VerificationException e) {
- // We should get here.
- }
- }
-
- @Test
- public void testHeaderParse() throws Exception {
- Block block = new Block(params, blockBytes);
- Block header = block.cloneAsHeader();
- Block reparsed = new Block(params, header.bitcoinSerialize());
- assertEquals(reparsed, header);
- }
-
- @Test
- public void testBitCoinSerialization() throws Exception {
- // We have to be able to reserialize everything exactly as we found it for hashing to work. This test also
- // proves that transaction serialization works, along with all its subobjects like scripts and in/outpoints.
- //
- // NB: This tests the BITCOIN proprietary serialization protocol. A different test checks Java serialization
- // of transactions.
- Block block = new Block(params, blockBytes);
- assertTrue(Arrays.equals(blockBytes, block.bitcoinSerialize()));
- }
-
- @Test
- public void testJavaSerialiazation() throws Exception {
- Block block = new Block(params, blockBytes);
- Transaction tx = block.transactions.get(1);
-
- // Serialize using Java.
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- ObjectOutputStream oos = new ObjectOutputStream(bos);
- oos.writeObject(tx);
- oos.close();
- byte[] javaBits = bos.toByteArray();
- // Deserialize again.
- ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(javaBits));
- Transaction tx2 = (Transaction) ois.readObject();
- ois.close();
-
- // Note that this will actually check the transactions are equal by doing bitcoin serialization and checking
- // the bytestreams are the same! A true "deep equals" is not implemented for Transaction. The primary purpose
- // of this test is to ensure no errors occur during the Java serialization/deserialization process.
- assertEquals(tx, tx2);
- }
-
- @Test
- public void testUpdateLength() {
- NetworkParameters params = UnitTestParams.get();
- Block block = params.getGenesisBlock().createNextBlockWithCoinbase(new ECKey().getPubKey());
- assertEquals(block.bitcoinSerialize().length, block.length);
- final int origBlockLen = block.length;
- Transaction tx = new Transaction(params);
- // this is broken until the transaction has > 1 input + output (which is required anyway...)
- //assertTrue(tx.length == tx.bitcoinSerialize().length && tx.length == 8);
- byte[] outputScript = new byte[10];
- Arrays.fill(outputScript, (byte) ScriptOpCodes.OP_FALSE);
- tx.addOutput(new TransactionOutput(params, null, Coin.SATOSHI, outputScript));
- tx.addInput(new TransactionInput(params, null, new byte[] {(byte) ScriptOpCodes.OP_FALSE},
- new TransactionOutPoint(params, 0, Sha256Hash.create(new byte[] {1}))));
- int origTxLength = 8 + 2 + 8 + 1 + 10 + 40 + 1 + 1;
- assertEquals(tx.bitcoinSerialize().length, tx.length);
- assertEquals(origTxLength, tx.length);
- block.addTransaction(tx);
- assertEquals(block.bitcoinSerialize().length, block.length);
- assertEquals(origBlockLen + tx.length, block.length);
- block.getTransactions().get(1).getInputs().get(0).setScriptBytes(new byte[] {(byte) ScriptOpCodes.OP_FALSE, (byte) ScriptOpCodes.OP_FALSE});
- assertEquals(block.length, origBlockLen + tx.length);
- assertEquals(tx.length, origTxLength + 1);
- block.getTransactions().get(1).getInputs().get(0).setScriptBytes(new byte[] {});
- assertEquals(block.length, block.bitcoinSerialize().length);
- assertEquals(block.length, origBlockLen + tx.length);
- assertEquals(tx.length, origTxLength - 1);
- block.getTransactions().get(1).addInput(new TransactionInput(params, null, new byte[] {(byte) ScriptOpCodes.OP_FALSE},
- new TransactionOutPoint(params, 0, Sha256Hash.create(new byte[] {1}))));
- assertEquals(block.length, origBlockLen + tx.length);
- assertEquals(tx.length, origTxLength + 41); // - 1 + 40 + 1 + 1
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/BloomFilterTest.java b/core/src/test/java/com/dogecoin/dogecoinj/core/BloomFilterTest.java
deleted file mode 100644
index 69180ed7..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/BloomFilterTest.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright 2012 Matt Corallo
- * 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 com.dogecoin.dogecoinj.core;
-
-import com.dogecoin.dogecoinj.params.MainNetParams;
-import com.dogecoin.dogecoinj.wallet.KeyChainGroup;
-import org.junit.Test;
-
-import java.util.Arrays;
-
-import static com.dogecoin.dogecoinj.core.Utils.HEX;
-import static org.junit.Assert.*;
-
-public class BloomFilterTest {
- @Test
- public void insertSerializeTest() {
- BloomFilter filter = new BloomFilter(3, 0.01, 0, BloomFilter.BloomUpdate.UPDATE_ALL);
-
- filter.insert(HEX.decode("99108ad8ed9bb6274d3980bab5a85c048f0950c8"));
- assertTrue (filter.contains(HEX.decode("99108ad8ed9bb6274d3980bab5a85c048f0950c8")));
- // One bit different in first byte
- assertFalse(filter.contains(HEX.decode("19108ad8ed9bb6274d3980bab5a85c048f0950c8")));
-
- filter.insert(HEX.decode("b5a2c786d9ef4658287ced5914b37a1b4aa32eee"));
- assertTrue(filter.contains(HEX.decode("b5a2c786d9ef4658287ced5914b37a1b4aa32eee")));
-
- filter.insert(HEX.decode("b9300670b4c5366e95b2699e8b18bc75e5f729c5"));
- assertTrue(filter.contains(HEX.decode("b9300670b4c5366e95b2699e8b18bc75e5f729c5")));
-
- // Value generated by the reference client
- assertTrue(Arrays.equals(HEX.decode("03614e9b050000000000000001"), filter.bitcoinSerialize()));
- }
-
- @Test
- public void insertSerializeTestWithTweak() {
- BloomFilter filter = new BloomFilter(3, 0.01, 2147483649L);
-
- filter.insert(HEX.decode("99108ad8ed9bb6274d3980bab5a85c048f0950c8"));
- assertTrue (filter.contains(HEX.decode("99108ad8ed9bb6274d3980bab5a85c048f0950c8")));
- // One bit different in first byte
- assertFalse(filter.contains(HEX.decode("19108ad8ed9bb6274d3980bab5a85c048f0950c8")));
-
- filter.insert(HEX.decode("b5a2c786d9ef4658287ced5914b37a1b4aa32eee"));
- assertTrue(filter.contains(HEX.decode("b5a2c786d9ef4658287ced5914b37a1b4aa32eee")));
-
- filter.insert(HEX.decode("b9300670b4c5366e95b2699e8b18bc75e5f729c5"));
- assertTrue(filter.contains(HEX.decode("b9300670b4c5366e95b2699e8b18bc75e5f729c5")));
-
- // Value generated by the reference client
- assertTrue(Arrays.equals(HEX.decode("03ce4299050000000100008002"), filter.bitcoinSerialize()));
- }
-
- @Test
- public void walletTest() throws Exception {
- NetworkParameters params = MainNetParams.get();
-
- DumpedPrivateKey privKey = new DumpedPrivateKey(params, "5Kg1gnAjaLfKiwhhPpGS3QfRg2m6awQvaj98JCZBZQ5SuS2F15C");
-
- Address addr = privKey.getKey().toAddress(params);
- assertTrue(addr.toString().equals("17Wx1GQfyPTNWpQMHrTwRSMTCAonSiZx9e"));
-
- KeyChainGroup group = new KeyChainGroup(params);
- // Add a random key which happens to have been used in a recent generation
- group.importKeys(privKey.getKey(), ECKey.fromPublicOnly(HEX.decode("03cb219f69f1b49468bd563239a86667e74a06fcba69ac50a08a5cbc42a5808e99")));
- Wallet wallet = new Wallet(params, group);
- wallet.commitTx(new Transaction(params, HEX.decode("01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0d038754030114062f503253482fffffffff01c05e559500000000232103cb219f69f1b49468bd563239a86667e74a06fcba69ac50a08a5cbc42a5808e99ac00000000")));
-
- // We should have 2 per pubkey, and one for the pay-2-pubkey output we have
- assertEquals(5, wallet.getBloomFilterElementCount());
-
- BloomFilter filter = wallet.getBloomFilter(wallet.getBloomFilterElementCount(), 0.001, 0);
-
- // Value generated by the reference client
- assertTrue(Arrays.equals(HEX.decode("082ae5edc8e51d4a03080000000000000002"), filter.bitcoinSerialize()));
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/ChainSplitTest.java b/core/src/test/java/com/dogecoin/dogecoinj/core/ChainSplitTest.java
deleted file mode 100644
index bd42bd85..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/ChainSplitTest.java
+++ /dev/null
@@ -1,688 +0,0 @@
-/*
- * Copyright 2012 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 com.dogecoin.dogecoinj.core;
-
-import com.dogecoin.dogecoinj.core.TransactionConfidence.ConfidenceType;
-import com.dogecoin.dogecoinj.params.UnitTestParams;
-import com.dogecoin.dogecoinj.store.MemoryBlockStore;
-import com.dogecoin.dogecoinj.testing.FakeTxBuilder;
-import com.dogecoin.dogecoinj.utils.BriefLogFormatter;
-import com.dogecoin.dogecoinj.utils.Threading;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.math.BigInteger;
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import static com.dogecoin.dogecoinj.core.Coin.*;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.junit.Assert.*;
-
-public class ChainSplitTest {
- private static final Logger log = LoggerFactory.getLogger(ChainSplitTest.class);
-
- private NetworkParameters unitTestParams;
- private Wallet wallet;
- private BlockChain chain;
- private Address coinsTo;
- private Address coinsTo2;
- private Address someOtherGuy;
- private MemoryBlockStore blockStore;
-
- @Before
- public void setUp() throws Exception {
- BriefLogFormatter.init();
- Utils.setMockClock(); // Use mock clock
- Wallet.SendRequest.DEFAULT_FEE_PER_KB = Coin.ZERO;
- unitTestParams = UnitTestParams.get();
- wallet = new Wallet(unitTestParams);
- ECKey key1 = wallet.freshReceiveKey();
- ECKey key2 = wallet.freshReceiveKey();
- blockStore = new MemoryBlockStore(unitTestParams);
- chain = new BlockChain(unitTestParams, wallet, blockStore);
- coinsTo = key1.toAddress(unitTestParams);
- coinsTo2 = key2.toAddress(unitTestParams);
- someOtherGuy = new ECKey().toAddress(unitTestParams);
- }
-
- @Test
- public void testForking1() throws Exception {
- // Check that if the block chain forks, we end up using the right chain. Only tests inbound transactions
- // (receiving coins). Checking that we understand reversed spends is in testForking2.
- final AtomicBoolean reorgHappened = new AtomicBoolean();
- final AtomicInteger walletChanged = new AtomicInteger();
- wallet.addEventListener(new AbstractWalletEventListener() {
- @Override
- public void onReorganize(Wallet wallet) {
- reorgHappened.set(true);
- }
-
- @Override
- public void onWalletChanged(Wallet wallet) {
- walletChanged.incrementAndGet();
- }
- });
-
- // Start by building a couple of blocks on top of the genesis block.
- Block b1 = unitTestParams.getGenesisBlock().createNextBlock(coinsTo);
- Block b2 = b1.createNextBlock(coinsTo);
- assertTrue(chain.add(b1));
- assertTrue(chain.add(b2));
- Threading.waitForUserCode();
- assertFalse(reorgHappened.get());
- assertEquals(2, walletChanged.get());
- // We got two blocks which sent 50 coins each to us.
- assertEquals(Coin.valueOf(100, 0), wallet.getBalance());
- // We now have the following chain:
- // genesis -> b1 -> b2
- //
- // so fork like this:
- //
- // genesis -> b1 -> b2
- // \-> b3
- //
- // Nothing should happen at this point. We saw b2 first so it takes priority.
- Block b3 = b1.createNextBlock(someOtherGuy);
- assertTrue(chain.add(b3));
- Threading.waitForUserCode();
- assertFalse(reorgHappened.get()); // No re-org took place.
- assertEquals(2, walletChanged.get());
- assertEquals(Coin.valueOf(100, 0), wallet.getBalance());
- // Check we can handle multi-way splits: this is almost certainly going to be extremely rare, but we have to
- // handle it anyway. The same transaction appears in b7/b8 (side chain) but not b2 or b3.
- // genesis -> b1--> b2
- // |-> b3
- // |-> b7 (x)
- // \-> b8 (x)
- Block b7 = b1.createNextBlock(coinsTo);
- assertTrue(chain.add(b7));
- Block b8 = b1.createNextBlock(coinsTo);
- final Transaction t = b7.getTransactions().get(1);
- final Sha256Hash tHash = t.getHash();
- b8.addTransaction(t);
- b8.solve();
- assertTrue(chain.add(roundtrip(b8)));
- Threading.waitForUserCode();
- assertEquals(2, wallet.getTransaction(tHash).getAppearsInHashes().size());
- assertFalse(reorgHappened.get()); // No re-org took place.
- assertEquals(5, walletChanged.get());
- assertEquals(Coin.valueOf(100, 0), wallet.getBalance());
- // Now we add another block to make the alternative chain longer.
- assertTrue(chain.add(b3.createNextBlock(someOtherGuy)));
- Threading.waitForUserCode();
- assertTrue(reorgHappened.get()); // Re-org took place.
- assertEquals(6, walletChanged.get());
- reorgHappened.set(false);
- //
- // genesis -> b1 -> b2
- // \-> b3 -> b4
- // We lost some coins! b2 is no longer a part of the best chain so our available balance should drop to 50.
- // It's now pending reconfirmation.
- assertEquals(FIFTY_COINS, wallet.getBalance());
- // ... and back to the first chain.
- Block b5 = b2.createNextBlock(coinsTo);
- Block b6 = b5.createNextBlock(coinsTo);
- assertTrue(chain.add(b5));
- assertTrue(chain.add(b6));
- //
- // genesis -> b1 -> b2 -> b5 -> b6
- // \-> b3 -> b4
- //
- Threading.waitForUserCode();
- assertTrue(reorgHappened.get());
- assertEquals(9, walletChanged.get());
- assertEquals(Coin.valueOf(200, 0), wallet.getBalance());
- }
-
- @Test
- public void testForking2() throws Exception {
- // Check that if the chain forks and new coins are received in the alternate chain our balance goes up
- // after the re-org takes place.
- Block b1 = unitTestParams.getGenesisBlock().createNextBlock(someOtherGuy);
- Block b2 = b1.createNextBlock(someOtherGuy);
- assertTrue(chain.add(b1));
- assertTrue(chain.add(b2));
- // genesis -> b1 -> b2
- // \-> b3 -> b4
- assertEquals(Coin.ZERO, wallet.getBalance());
- Block b3 = b1.createNextBlock(coinsTo);
- Block b4 = b3.createNextBlock(someOtherGuy);
- assertTrue(chain.add(b3));
- assertEquals(Coin.ZERO, wallet.getBalance());
- assertTrue(chain.add(b4));
- assertEquals(FIFTY_COINS, wallet.getBalance());
- }
-
- @Test
- public void testForking3() throws Exception {
- // Check that we can handle our own spends being rolled back by a fork.
- Block b1 = unitTestParams.getGenesisBlock().createNextBlock(coinsTo);
- chain.add(b1);
- assertEquals(FIFTY_COINS, wallet.getBalance());
- Address dest = new ECKey().toAddress(unitTestParams);
- Transaction spend = wallet.createSend(dest, valueOf(10, 0));
- wallet.commitTx(spend);
- // Waiting for confirmation ... make it eligible for selection.
- assertEquals(Coin.ZERO, wallet.getBalance());
- spend.getConfidence().markBroadcastBy(new PeerAddress(InetAddress.getByAddress(new byte[]{1, 2, 3, 4})));
- spend.getConfidence().markBroadcastBy(new PeerAddress(InetAddress.getByAddress(new byte[]{5,6,7,8})));
- assertEquals(ConfidenceType.PENDING, spend.getConfidence().getConfidenceType());
- assertEquals(valueOf(40, 0), wallet.getBalance());
- Block b2 = b1.createNextBlock(someOtherGuy);
- b2.addTransaction(spend);
- b2.solve();
- chain.add(roundtrip(b2));
- // We have 40 coins in change.
- assertEquals(ConfidenceType.BUILDING, spend.getConfidence().getConfidenceType());
- // genesis -> b1 (receive coins) -> b2 (spend coins)
- // \-> b3 -> b4
- Block b3 = b1.createNextBlock(someOtherGuy);
- Block b4 = b3.createNextBlock(someOtherGuy);
- chain.add(b3);
- chain.add(b4);
- // b4 causes a re-org that should make our spend go pending again.
- assertEquals(valueOf(40, 0), wallet.getBalance());
- assertEquals(ConfidenceType.PENDING, spend.getConfidence().getConfidenceType());
- }
-
- @Test
- public void testForking4() throws Exception {
- // Check that we can handle external spends on an inactive chain becoming active. An external spend is where
- // we see a transaction that spends our own coins but we did not broadcast it ourselves. This happens when
- // keys are being shared between wallets.
- Block b1 = unitTestParams.getGenesisBlock().createNextBlock(coinsTo);
- chain.add(b1);
- assertEquals(FIFTY_COINS, wallet.getBalance());
- Address dest = new ECKey().toAddress(unitTestParams);
- Transaction spend = wallet.createSend(dest, FIFTY_COINS);
- // We do NOT confirm the spend here. That means it's not considered to be pending because createSend is
- // stateless. For our purposes it is as if some other program with our keys created the tx.
- //
- // genesis -> b1 (receive 50) --> b2
- // \-> b3 (external spend) -> b4
- Block b2 = b1.createNextBlock(someOtherGuy);
- chain.add(b2);
- Block b3 = b1.createNextBlock(someOtherGuy);
- b3.addTransaction(spend);
- b3.solve();
- chain.add(roundtrip(b3));
- // The external spend is now pending.
- assertEquals(ZERO, wallet.getBalance());
- Transaction tx = wallet.getTransaction(spend.getHash());
- assertEquals(ConfidenceType.PENDING, tx.getConfidence().getConfidenceType());
- Block b4 = b3.createNextBlock(someOtherGuy);
- chain.add(b4);
- // The external spend is now active.
- assertEquals(ZERO, wallet.getBalance());
- assertEquals(ConfidenceType.BUILDING, tx.getConfidence().getConfidenceType());
- }
-
- @Test
- public void testForking5() throws Exception {
- // Test the standard case in which a block containing identical transactions appears on a side chain.
- Block b1 = unitTestParams.getGenesisBlock().createNextBlock(coinsTo);
- chain.add(b1);
- final Transaction t = b1.transactions.get(1);
- assertEquals(FIFTY_COINS, wallet.getBalance());
- // genesis -> b1
- // -> b2
- Block b2 = unitTestParams.getGenesisBlock().createNextBlock(coinsTo);
- Transaction b2coinbase = b2.transactions.get(0);
- b2.transactions.clear();
- b2.addTransaction(b2coinbase);
- b2.addTransaction(t);
- b2.solve();
- chain.add(roundtrip(b2));
- assertEquals(FIFTY_COINS, wallet.getBalance());
- assertTrue(wallet.isConsistent());
- assertEquals(2, wallet.getTransaction(t.getHash()).getAppearsInHashes().size());
- // -> b2 -> b3
- Block b3 = b2.createNextBlock(someOtherGuy);
- chain.add(b3);
- assertEquals(FIFTY_COINS, wallet.getBalance());
-
- }
-
- private Block roundtrip(Block b2) throws ProtocolException {
- return new Block(unitTestParams, b2.bitcoinSerialize());
- }
-
- @Test
- public void testForking6() throws Exception {
- // Test the case in which a side chain block contains a tx, and then it appears in the main chain too.
- Block b1 = unitTestParams.getGenesisBlock().createNextBlock(someOtherGuy);
- chain.add(b1);
- // genesis -> b1
- // -> b2
- Block b2 = unitTestParams.getGenesisBlock().createNextBlock(coinsTo);
- chain.add(b2);
- assertEquals(Coin.ZERO, wallet.getBalance());
- // genesis -> b1 -> b3
- // -> b2
- Block b3 = b1.createNextBlock(someOtherGuy);
- b3.addTransaction(b2.transactions.get(1));
- b3.solve();
- chain.add(roundtrip(b3));
- assertEquals(FIFTY_COINS, wallet.getBalance());
- }
-
- @Test
- public void testDoubleSpendOnFork() throws Exception {
- // Check what happens when a re-org happens and one of our confirmed transactions becomes invalidated by a
- // double spend on the new best chain.
-
- final boolean[] eventCalled = new boolean[1];
- wallet.addEventListener(new AbstractWalletEventListener() {
- @Override
- public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx) {
- super.onTransactionConfidenceChanged(wallet, tx);
- if (tx.getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.DEAD)
- eventCalled[0] = true;
- }
- });
-
- Block b1 = unitTestParams.getGenesisBlock().createNextBlock(coinsTo);
- chain.add(b1);
-
- Transaction t1 = wallet.createSend(someOtherGuy, valueOf(10, 0));
- Address yetAnotherGuy = new ECKey().toAddress(unitTestParams);
- Transaction t2 = wallet.createSend(yetAnotherGuy, valueOf(20, 0));
- wallet.commitTx(t1);
- // Receive t1 as confirmed by the network.
- Block b2 = b1.createNextBlock(new ECKey().toAddress(unitTestParams));
- b2.addTransaction(t1);
- b2.solve();
- chain.add(roundtrip(b2));
-
- // Now we make a double spend become active after a re-org.
- Block b3 = b1.createNextBlock(new ECKey().toAddress(unitTestParams));
- b3.addTransaction(t2);
- b3.solve();
- chain.add(roundtrip(b3)); // Side chain.
- Block b4 = b3.createNextBlock(new ECKey().toAddress(unitTestParams));
- chain.add(b4); // New best chain.
- Threading.waitForUserCode();
- // Should have seen a double spend.
- assertTrue(eventCalled[0]);
- assertEquals(valueOf(30, 0), wallet.getBalance());
- }
-
- @Test
- public void testDoubleSpendOnForkPending() throws Exception {
- // Check what happens when a re-org happens and one of our unconfirmed transactions becomes invalidated by a
- // double spend on the new best chain.
- final Transaction[] eventDead = new Transaction[1];
- final Transaction[] eventReplacement = new Transaction[1];
- wallet.addEventListener(new AbstractWalletEventListener() {
- @Override
- public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx) {
- super.onTransactionConfidenceChanged(wallet, tx);
- if (tx.getConfidence().getConfidenceType() ==
- TransactionConfidence.ConfidenceType.DEAD) {
- eventDead[0] = tx;
- eventReplacement[0] = tx.getConfidence().getOverridingTransaction();
- }
- }
- });
-
- // Start with 50 coins.
- Block b1 = unitTestParams.getGenesisBlock().createNextBlock(coinsTo);
- chain.add(b1);
-
- Transaction t1 = checkNotNull(wallet.createSend(someOtherGuy, valueOf(10, 0)));
- Address yetAnotherGuy = new ECKey().toAddress(unitTestParams);
- Transaction t2 = checkNotNull(wallet.createSend(yetAnotherGuy, valueOf(20, 0)));
- wallet.commitTx(t1);
- // t1 is still pending ...
- Block b2 = b1.createNextBlock(new ECKey().toAddress(unitTestParams));
- chain.add(b2);
- assertEquals(ZERO, wallet.getBalance());
- assertEquals(valueOf(40, 0), wallet.getBalance(Wallet.BalanceType.ESTIMATED));
-
- // Now we make a double spend become active after a re-org.
- // genesis -> b1 -> b2 [t1 pending]
- // \-> b3 (t2) -> b4
- Block b3 = b1.createNextBlock(new ECKey().toAddress(unitTestParams));
- b3.addTransaction(t2);
- b3.solve();
- chain.add(roundtrip(b3)); // Side chain.
- Block b4 = b3.createNextBlock(new ECKey().toAddress(unitTestParams));
- chain.add(b4); // New best chain.
- Threading.waitForUserCode();
- // Should have seen a double spend against the pending pool.
- // genesis -> b1 -> b2 [t1 dead and exited the miners mempools]
- // \-> b3 (t2) -> b4
- assertEquals(t1, eventDead[0]);
- assertEquals(t2, eventReplacement[0]);
- assertEquals(valueOf(30, 0), wallet.getBalance());
-
- // ... and back to our own parallel universe.
- Block b5 = b2.createNextBlock(new ECKey().toAddress(unitTestParams));
- chain.add(b5);
- Block b6 = b5.createNextBlock(new ECKey().toAddress(unitTestParams));
- chain.add(b6);
- // genesis -> b1 -> b2 -> b5 -> b6 [t1 still dead]
- // \-> b3 [t2 resurrected and now pending] -> b4
- assertEquals(ZERO, wallet.getBalance());
- // t2 is pending - resurrected double spends take precedence over our dead transactions (which are in nobodies
- // mempool by this point).
- t1 = checkNotNull(wallet.getTransaction(t1.getHash()));
- t2 = checkNotNull(wallet.getTransaction(t2.getHash()));
- assertEquals(ConfidenceType.DEAD, t1.getConfidence().getConfidenceType());
- assertEquals(ConfidenceType.PENDING, t2.getConfidence().getConfidenceType());
- }
-
- @Test
- public void txConfidenceLevels() throws Exception {
- // Check that as the chain forks and re-orgs, the confidence data associated with each transaction is
- // maintained correctly.
- final ArrayList txns = new ArrayList(3);
- wallet.addEventListener(new AbstractWalletEventListener() {
- @Override
- public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
- txns.add(tx);
- }
- });
-
- // Start by building three blocks on top of the genesis block. All send to us.
- Block b1 = unitTestParams.getGenesisBlock().createNextBlock(coinsTo);
- BigInteger work1 = b1.getWork();
- Block b2 = b1.createNextBlock(coinsTo2);
- BigInteger work2 = b2.getWork();
- Block b3 = b2.createNextBlock(coinsTo2);
- BigInteger work3 = b3.getWork();
-
- assertTrue(chain.add(b1));
- assertTrue(chain.add(b2));
- assertTrue(chain.add(b3));
- Threading.waitForUserCode();
- // Check the transaction confidence levels are correct.
- assertEquals(3, txns.size());
-
- assertEquals(1, txns.get(0).getConfidence().getAppearedAtChainHeight());
- assertEquals(2, txns.get(1).getConfidence().getAppearedAtChainHeight());
- assertEquals(3, txns.get(2).getConfidence().getAppearedAtChainHeight());
-
- assertEquals(3, txns.get(0).getConfidence().getDepthInBlocks());
- assertEquals(2, txns.get(1).getConfidence().getDepthInBlocks());
- assertEquals(1, txns.get(2).getConfidence().getDepthInBlocks());
-
- // We now have the following chain:
- // genesis -> b1 -> b2 -> b3
- //
- // so fork like this:
- //
- // genesis -> b1 -> b2 -> b3
- // \-> b4 -> b5
- //
- // Nothing should happen at this point. We saw b2 and b3 first so it takes priority.
- Block b4 = b1.createNextBlock(someOtherGuy);
- BigInteger work4 = b4.getWork();
-
- Block b5 = b4.createNextBlock(someOtherGuy);
- BigInteger work5 = b5.getWork();
-
- assertTrue(chain.add(b4));
- assertTrue(chain.add(b5));
- Threading.waitForUserCode();
- assertEquals(3, txns.size());
-
- assertEquals(1, txns.get(0).getConfidence().getAppearedAtChainHeight());
- assertEquals(2, txns.get(1).getConfidence().getAppearedAtChainHeight());
- assertEquals(3, txns.get(2).getConfidence().getAppearedAtChainHeight());
-
- assertEquals(3, txns.get(0).getConfidence().getDepthInBlocks());
- assertEquals(2, txns.get(1).getConfidence().getDepthInBlocks());
- assertEquals(1, txns.get(2).getConfidence().getDepthInBlocks());
-
- // Now we add another block to make the alternative chain longer.
- Block b6 = b5.createNextBlock(someOtherGuy);
- BigInteger work6 = b6.getWork();
- assertTrue(chain.add(b6));
- //
- // genesis -> b1 -> b2 -> b3
- // \-> b4 -> b5 -> b6
- //
-
- assertEquals(3, txns.size());
- assertEquals(1, txns.get(0).getConfidence().getAppearedAtChainHeight());
- assertEquals(4, txns.get(0).getConfidence().getDepthInBlocks());
-
- // Transaction 1 (in block b2) is now on a side chain, so it goes pending (not see in chain).
- assertEquals(ConfidenceType.PENDING, txns.get(1).getConfidence().getConfidenceType());
- try {
- txns.get(1).getConfidence().getAppearedAtChainHeight();
- fail();
- } catch (IllegalStateException e) {}
- assertEquals(0, txns.get(1).getConfidence().getDepthInBlocks());
-
- // ... and back to the first chain.
- Block b7 = b3.createNextBlock(coinsTo);
- BigInteger work7 = b7.getWork();
- Block b8 = b7.createNextBlock(coinsTo);
- BigInteger work8 = b7.getWork();
-
- assertTrue(chain.add(b7));
- assertTrue(chain.add(b8));
- //
- // genesis -> b1 -> b2 -> b3 -> b7 -> b8
- // \-> b4 -> b5 -> b6
- //
-
- // This should be enabled, once we figure out the best way to inform the user of how the wallet is changing
- // during the re-org.
- //assertEquals(5, txns.size());
-
- assertEquals(1, txns.get(0).getConfidence().getAppearedAtChainHeight());
- assertEquals(2, txns.get(1).getConfidence().getAppearedAtChainHeight());
- assertEquals(3, txns.get(2).getConfidence().getAppearedAtChainHeight());
-
- assertEquals(5, txns.get(0).getConfidence().getDepthInBlocks());
- assertEquals(4, txns.get(1).getConfidence().getDepthInBlocks());
- assertEquals(3, txns.get(2).getConfidence().getDepthInBlocks());
-
- assertEquals(Coin.valueOf(250, 0), wallet.getBalance());
-
- // Now add two more blocks that don't send coins to us. Despite being irrelevant the wallet should still update.
- Block b9 = b8.createNextBlock(someOtherGuy);
- Block b10 = b9.createNextBlock(someOtherGuy);
- chain.add(b9);
- chain.add(b10);
- BigInteger extraWork = b9.getWork().add(b10.getWork());
- assertEquals(7, txns.get(0).getConfidence().getDepthInBlocks());
- assertEquals(6, txns.get(1).getConfidence().getDepthInBlocks());
- assertEquals(5, txns.get(2).getConfidence().getDepthInBlocks());
- }
-
- @Test
- public void orderingInsideBlock() throws Exception {
- // Test that transactions received in the same block have their ordering preserved when reorganising.
- // This covers issue 468.
-
- // Receive some money to the wallet.
- Transaction t1 = FakeTxBuilder.createFakeTx(unitTestParams, COIN, coinsTo);
- final Block b1 = FakeTxBuilder.makeSolvedTestBlock(unitTestParams.genesisBlock, t1);
- chain.add(b1);
-
- // Send a couple of payments one after the other (so the second depends on the change output of the first).
- wallet.allowSpendingUnconfirmedTransactions();
- Transaction t2 = checkNotNull(wallet.createSend(new ECKey().toAddress(unitTestParams), CENT));
- wallet.commitTx(t2);
- Transaction t3 = checkNotNull(wallet.createSend(new ECKey().toAddress(unitTestParams), CENT));
- wallet.commitTx(t3);
- chain.add(FakeTxBuilder.makeSolvedTestBlock(b1, t2, t3));
-
- final Coin coins0point98 = COIN.subtract(CENT).subtract(CENT);
- assertEquals(coins0point98, wallet.getBalance());
-
- // Now round trip the wallet and force a re-org.
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- wallet.saveToFileStream(bos);
- wallet = Wallet.loadFromFileStream(new ByteArrayInputStream(bos.toByteArray()));
- final Block b2 = FakeTxBuilder.makeSolvedTestBlock(b1, t2, t3);
- final Block b3 = FakeTxBuilder.makeSolvedTestBlock(b2);
- chain.add(b2);
- chain.add(b3);
-
- // And verify that the balance is as expected. Because signatures are currently non-deterministic if the order
- // isn't being stored correctly this should fail 50% of the time.
- assertEquals(coins0point98, wallet.getBalance());
- }
-
- @Test
- public void coinbaseDeath() throws Exception {
- // Check that a coinbase tx is marked as dead after a reorg rather than pending as normal non-double-spent
- // transactions would be. Also check that a dead coinbase on a sidechain is resurrected if the sidechain
- // becomes the best chain once more. Finally, check that dependent transactions are killed recursively.
- final ArrayList txns = new ArrayList(3);
- wallet.addEventListener(new AbstractWalletEventListener() {
- @Override
- public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
- txns.add(tx);
- }
- }, Threading.SAME_THREAD);
-
- Block b1 = unitTestParams.getGenesisBlock().createNextBlock(someOtherGuy);
- final ECKey coinsTo2 = wallet.freshReceiveKey();
- Block b2 = b1.createNextBlockWithCoinbase(coinsTo2.getPubKey());
- Block b3 = b2.createNextBlock(someOtherGuy);
-
- log.debug("Adding block b1");
- assertTrue(chain.add(b1));
- log.debug("Adding block b2");
- assertTrue(chain.add(b2));
- log.debug("Adding block b3");
- assertTrue(chain.add(b3));
-
- // We now have the following chain:
- // genesis -> b1 -> b2 -> b3
- //
-
- // Check we have seen the coinbase.
- assertEquals(1, txns.size());
-
- // Check the coinbase transaction is building and in the unspent pool only.
- final Transaction coinbase = txns.get(0);
- assertEquals(ConfidenceType.BUILDING, coinbase.getConfidence().getConfidenceType());
- assertTrue(!wallet.pending.containsKey(coinbase.getHash()));
- assertTrue(wallet.unspent.containsKey(coinbase.getHash()));
- assertTrue(!wallet.spent.containsKey(coinbase.getHash()));
- assertTrue(!wallet.dead.containsKey(coinbase.getHash()));
-
- // Add blocks to b3 until we can spend the coinbase.
- Block firstTip = b3;
- for (int i = 0; i < unitTestParams.getSpendableCoinbaseDepth() - 2; i++) {
- firstTip = firstTip.createNextBlock(someOtherGuy);
- chain.add(firstTip);
- }
- // ... and spend.
- Transaction fodder = wallet.createSend(new ECKey().toAddress(unitTestParams), FIFTY_COINS);
- wallet.commitTx(fodder);
- final AtomicBoolean fodderIsDead = new AtomicBoolean(false);
- fodder.getConfidence().addEventListener(new TransactionConfidence.Listener() {
- @Override
- public void onConfidenceChanged(TransactionConfidence confidence, ChangeReason reason) {
- fodderIsDead.set(confidence.getConfidenceType() == ConfidenceType.DEAD);
- }
- }, Threading.SAME_THREAD);
-
- // Fork like this:
- //
- // genesis -> b1 -> b2 -> b3 -> [...]
- // \-> b4 -> b5 -> b6 -> [...]
- //
- // The b4/ b5/ b6 is now the best chain
- Block b4 = b1.createNextBlock(someOtherGuy);
- Block b5 = b4.createNextBlock(someOtherGuy);
- Block b6 = b5.createNextBlock(someOtherGuy);
-
- log.debug("Adding block b4");
- assertTrue(chain.add(b4));
- log.debug("Adding block b5");
- assertTrue(chain.add(b5));
- log.debug("Adding block b6");
- assertTrue(chain.add(b6));
-
- Block secondTip = b6;
- for (int i = 0; i < unitTestParams.getSpendableCoinbaseDepth() - 2; i++) {
- secondTip = secondTip.createNextBlock(someOtherGuy);
- chain.add(secondTip);
- }
-
- // Transaction 1 (in block b2) is now on a side chain and should have confidence type of dead and be in
- // the dead pool only.
- assertEquals(TransactionConfidence.ConfidenceType.DEAD, coinbase.getConfidence().getConfidenceType());
- assertTrue(!wallet.pending.containsKey(coinbase.getHash()));
- assertTrue(!wallet.unspent.containsKey(coinbase.getHash()));
- assertTrue(!wallet.spent.containsKey(coinbase.getHash()));
- assertTrue(wallet.dead.containsKey(coinbase.getHash()));
- assertTrue(fodderIsDead.get());
-
- // ... and back to the first chain.
- Block b7 = firstTip.createNextBlock(someOtherGuy);
- Block b8 = b7.createNextBlock(someOtherGuy);
-
- log.debug("Adding block b7");
- assertTrue(chain.add(b7));
- log.debug("Adding block b8");
- assertTrue(chain.add(b8));
-
- //
- // genesis -> b1 -> b2 -> b3 -> [...] -> b7 -> b8
- // \-> b4 -> b5 -> b6 -> [...]
- //
-
- // The coinbase transaction should now have confidence type of building once more and in the unspent pool only.
- assertEquals(TransactionConfidence.ConfidenceType.BUILDING, coinbase.getConfidence().getConfidenceType());
- assertTrue(!wallet.pending.containsKey(coinbase.getHash()));
- assertTrue(wallet.unspent.containsKey(coinbase.getHash()));
- assertTrue(!wallet.spent.containsKey(coinbase.getHash()));
- assertTrue(!wallet.dead.containsKey(coinbase.getHash()));
- // However, fodder is still dead. Bitcoin Core doesn't keep killed transactions around in case they become
- // valid again later. They are just deleted from the mempool for good.
-
- // ... make the side chain dominant again.
- Block b9 = secondTip.createNextBlock(someOtherGuy);
- Block b10 = b9.createNextBlock(someOtherGuy);
-
- log.debug("Adding block b9");
- assertTrue(chain.add(b9));
- log.debug("Adding block b10");
- assertTrue(chain.add(b10));
-
- //
- // genesis -> b1 -> b2 -> b3 -> [...] -> b7 -> b8
- // \-> b4 -> b5 -> b6 -> [...] -> b9 -> b10
- //
-
- // The coinbase transaction should now have the confidence type of dead and be in the dead pool only.
- assertEquals(TransactionConfidence.ConfidenceType.DEAD, coinbase.getConfidence().getConfidenceType());
- assertTrue(!wallet.pending.containsKey(coinbase.getHash()));
- assertTrue(!wallet.unspent.containsKey(coinbase.getHash()));
- assertTrue(!wallet.spent.containsKey(coinbase.getHash()));
- assertTrue(wallet.dead.containsKey(coinbase.getHash()));
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/CoinTest.java b/core/src/test/java/com/dogecoin/dogecoinj/core/CoinTest.java
deleted file mode 100644
index d8adf36b..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/CoinTest.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/**
- * 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 com.dogecoin.dogecoinj.core;
-
-import static com.dogecoin.dogecoinj.core.Coin.*;
-import static com.dogecoin.dogecoinj.core.NetworkParameters.MAX_MONEY;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.fail;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-public class CoinTest {
-
- @Test
- public void testParseCoin() {
- // String version
- assertEquals(CENT, parseCoin("0.01"));
- assertEquals(CENT, parseCoin("1E-2"));
- assertEquals(COIN.add(CENT), parseCoin("1.01"));
- assertEquals(COIN.negate(), parseCoin("-1"));
- try {
- parseCoin("2E-20");
- org.junit.Assert.fail("should not have accepted fractional satoshis");
- } catch (IllegalArgumentException expected) {
- } catch (Exception e) {
- org.junit.Assert.fail("should throw IllegalArgumentException");
- }
- }
-
- @Test
- public void testValueOf() {
- // int version
- assertEquals(CENT, valueOf(0, 1));
- assertEquals(SATOSHI, valueOf(1));
- assertEquals(NEGATIVE_SATOSHI, valueOf(-1));
- assertEquals(MAX_MONEY, valueOf(MAX_MONEY.value));
- assertEquals(MAX_MONEY.negate(), valueOf(MAX_MONEY.value * -1));
- try {
- valueOf(MAX_MONEY.value + 1);
- org.junit.Assert.fail("should not have accepted too-great a monetary value");
- } catch (IllegalArgumentException e) {
- }
- try {
- valueOf( (MAX_MONEY.value * -1) - 1);
- org.junit.Assert.fail("should not have accepted too-little a monetary value");
- } catch (IllegalArgumentException e) {
- }
-
- try {
- valueOf(Long.MIN_VALUE);
- fail();
- } catch (IllegalArgumentException e) {}
-
- try {
- valueOf(1, -1);
- fail();
- } catch (IllegalArgumentException e) {}
- try {
- valueOf(-1, 0);
- fail();
- } catch (IllegalArgumentException e) {}
- }
-
- @Test
- public void testOperators() {
- assertTrue(SATOSHI.isPositive());
- assertFalse(SATOSHI.isNegative());
- assertFalse(SATOSHI.isZero());
- assertFalse(NEGATIVE_SATOSHI.isPositive());
- assertTrue(NEGATIVE_SATOSHI.isNegative());
- assertFalse(NEGATIVE_SATOSHI.isZero());
- assertFalse(ZERO.isPositive());
- assertFalse(ZERO.isNegative());
- assertTrue(ZERO.isZero());
-
- assertTrue(valueOf(2).isGreaterThan(valueOf(1)));
- assertFalse(valueOf(2).isGreaterThan(valueOf(2)));
- assertFalse(valueOf(1).isGreaterThan(valueOf(2)));
- assertTrue(valueOf(1).isLessThan(valueOf(2)));
- assertFalse(valueOf(2).isLessThan(valueOf(2)));
- assertFalse(valueOf(2).isLessThan(valueOf(1)));
- }
-
- @Test
- public void testToFriendlyString() {
- assertEquals("1.00 DOGE", COIN.toFriendlyString());
- assertEquals("1.23 DOGE", valueOf(1, 23).toFriendlyString());
- assertEquals("0.001 DOGE", COIN.divide(1000).toFriendlyString());
- assertEquals("-1.23 DOGE", valueOf(1, 23).negate().toFriendlyString());
- }
-
- /**
- * Test the bitcoinValueToPlainString amount formatter
- */
- @Test
- public void testToPlainString() {
- assertEquals("0.0015", Coin.valueOf(150000).toPlainString());
- assertEquals("1.23", parseCoin("1.23").toPlainString());
-
- assertEquals("0.1", parseCoin("0.1").toPlainString());
- assertEquals("1.1", parseCoin("1.1").toPlainString());
- assertEquals("21.12", parseCoin("21.12").toPlainString());
- assertEquals("321.123", parseCoin("321.123").toPlainString());
- assertEquals("4321.1234", parseCoin("4321.1234").toPlainString());
- assertEquals("54321.12345", parseCoin("54321.12345").toPlainString());
- assertEquals("654321.123456", parseCoin("654321.123456").toPlainString());
- assertEquals("7654321.1234567", parseCoin("7654321.1234567").toPlainString());
-
- // More than MAX_MONEY. This will overlow to 0
- assertEquals("0", parseCoin(String.valueOf(Long.MAX_VALUE + 1)).toPlainString());
-
- // check there are no trailing zeros
- assertEquals("1", parseCoin("1.0").toPlainString());
- assertEquals("2", parseCoin("2.00").toPlainString());
- assertEquals("3", parseCoin("3.000").toPlainString());
- assertEquals("4", parseCoin("4.0000").toPlainString());
- assertEquals("5", parseCoin("5.00000").toPlainString());
- assertEquals("6", parseCoin("6.000000").toPlainString());
- assertEquals("7", parseCoin("7.0000000").toPlainString());
- assertEquals("8", parseCoin("8.00000000").toPlainString());
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/CoinbaseBlockTest.java b/core/src/test/java/com/dogecoin/dogecoinj/core/CoinbaseBlockTest.java
deleted file mode 100644
index 92823753..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/CoinbaseBlockTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/**
- * Copyright 2012 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 com.dogecoin.dogecoinj.core;
-
-import com.dogecoin.dogecoinj.core.AbstractBlockChain.NewBlockType;
-import com.dogecoin.dogecoinj.core.Wallet.BalanceType;
-import com.dogecoin.dogecoinj.params.MainNetParams;
-import org.junit.Test;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-/**
- * Test that an example mainnet coinbase transactions can be added to a wallet ok.
- */
-public class CoinbaseBlockTest {
- static final NetworkParameters params = MainNetParams.get();
-
- // The address for this private key is 1GqtGtn4fctXuKxsVzRPSLmYWN1YioLi9y.
- private static final String MINING_PRIVATE_KEY = "5JDxPrBRghF1EvSBjDigywqfmAjpHPmTJxYtQTYJxJRHLLQA4mG";
-
- private static final int BLOCK_OF_INTEREST = 169482;
- private static final int BLOCK_LENGTH_AS_HEX = 37357;
- private static final long BLOCK_NONCE = 3973947400L;
- private static final Coin BALANCE_AFTER_BLOCK = Coin.valueOf(22223642);
-
- @Test
- public void testReceiveCoinbaseTransaction() throws Exception {
- // Block 169482 (hash 0000000000000756935f1ee9d5987857b604046f846d3df56d024cdb5f368665)
- // contains coinbase transactions that are mining pool shares.
- // The private key MINERS_KEY is used to check transactions are received by a wallet correctly.
-
- byte[] blockAsBytes = getBytes(getClass().getResourceAsStream("block169482.dat"));
-
- // Create block 169482.
- Block block = new Block(params, blockAsBytes);
-
- // Check block.
- assertNotNull(block);
- block.verify();
- assertEquals(BLOCK_NONCE, block.getNonce());
-
- StoredBlock storedBlock = new StoredBlock(block, BigInteger.ONE, BLOCK_OF_INTEREST); // Nonsense work - not used in test.
-
- // Create a wallet contain the miner's key that receives a spend from a coinbase.
- ECKey miningKey = (new DumpedPrivateKey(params, MINING_PRIVATE_KEY)).getKey();
- assertNotNull(miningKey);
-
- Wallet wallet = new Wallet(params);
- wallet.importKey(miningKey);
-
- // Initial balance should be zero by construction.
- assertEquals(Coin.ZERO, wallet.getBalance());
-
- // Give the wallet the first transaction in the block - this is the coinbase tx.
- List transactions = block.getTransactions();
- assertNotNull(transactions);
- wallet.receiveFromBlock(transactions.get(0), storedBlock, NewBlockType.BEST_CHAIN, 0);
-
- // Coinbase transaction should have been received successfully but be unavailable to spend (too young).
- assertEquals(BALANCE_AFTER_BLOCK, wallet.getBalance(BalanceType.ESTIMATED));
- assertEquals(Coin.ZERO, wallet.getBalance(BalanceType.AVAILABLE));
- }
-
- /**
- * Returns the contents of the InputStream as a byte array.
- */
- private byte[] getBytes(InputStream inputStream) throws IOException {
- ByteArrayOutputStream buffer = new ByteArrayOutputStream();
-
- int numberRead;
- byte[] data = new byte[BLOCK_LENGTH_AS_HEX];
-
- while ((numberRead = inputStream.read(data, 0, data.length)) != -1) {
- buffer.write(data, 0, numberRead);
- }
-
- buffer.flush();
-
- return buffer.toByteArray();
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/ECKeyTest.java b/core/src/test/java/com/dogecoin/dogecoinj/core/ECKeyTest.java
deleted file mode 100644
index 09d765af..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/ECKeyTest.java
+++ /dev/null
@@ -1,464 +0,0 @@
-/**
- * Copyright 2011 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 com.dogecoin.dogecoinj.core;
-
-import com.dogecoin.dogecoinj.core.ECKey.ECDSASignature;
-import com.dogecoin.dogecoinj.crypto.EncryptedData;
-import com.dogecoin.dogecoinj.crypto.KeyCrypter;
-import com.dogecoin.dogecoinj.crypto.KeyCrypterScrypt;
-import com.dogecoin.dogecoinj.crypto.TransactionSignature;
-import com.dogecoin.dogecoinj.params.MainNetParams;
-import com.dogecoin.dogecoinj.params.TestNet3Params;
-import com.dogecoin.dogecoinj.params.UnitTestParams;
-import com.dogecoin.dogecoinj.utils.BriefLogFormatter;
-import com.google.common.collect.Lists;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
-import com.google.protobuf.ByteString;
-import com.dogecoin.dogecoinj.wallet.Protos;
-import com.dogecoin.dogecoinj.wallet.Protos.ScryptParameters;
-import org.junit.Before;
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.spongycastle.crypto.params.KeyParameter;
-
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.security.SecureRandom;
-import java.security.SignatureException;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Random;
-import java.util.concurrent.Callable;
-import java.util.concurrent.Executors;
-
-import static com.dogecoin.dogecoinj.core.Utils.HEX;
-import static com.dogecoin.dogecoinj.core.Utils.reverseBytes;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.junit.Assert.*;
-
-public class ECKeyTest {
- private static final Logger log = LoggerFactory.getLogger(ECKeyTest.class);
-
- private SecureRandom secureRandom;
-
- private KeyCrypter keyCrypter;
-
- private static CharSequence PASSWORD1 = "my hovercraft has eels";
- private static CharSequence WRONG_PASSWORD = "it is a snowy day today";
-
- @Before
- public void setUp() throws Exception {
- secureRandom = new SecureRandom();
-
- byte[] salt = new byte[KeyCrypterScrypt.SALT_LENGTH];
- secureRandom.nextBytes(salt);
- Protos.ScryptParameters.Builder scryptParametersBuilder = Protos.ScryptParameters.newBuilder().setSalt(ByteString.copyFrom(salt));
- ScryptParameters scryptParameters = scryptParametersBuilder.build();
- keyCrypter = new KeyCrypterScrypt(scryptParameters);
-
- BriefLogFormatter.init();
- }
-
- @Test
- public void sValue() throws Exception {
- // Check that we never generate an S value that is larger than half the curve order. This avoids a malleability
- // issue that can allow someone to change a transaction [hash] without invalidating the signature.
- final int ITERATIONS = 10;
- ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(ITERATIONS));
- List> sigFutures = Lists.newArrayList();
- final ECKey key = new ECKey();
- for (byte i = 0; i < ITERATIONS; i++) {
- final Sha256Hash hash = Sha256Hash.create(new byte[]{i});
- sigFutures.add(executor.submit(new Callable() {
- @Override
- public ECKey.ECDSASignature call() throws Exception {
- return key.sign(hash);
- }
- }));
- }
- List sigs = Futures.allAsList(sigFutures).get();
- for (ECKey.ECDSASignature signature : sigs) {
- assertTrue(signature.isCanonical());
- }
- final ECDSASignature first = sigs.get(0);
- final ECKey.ECDSASignature duplicate = new ECKey.ECDSASignature(first.r, first.s);
- assertEquals(first, duplicate);
- assertEquals(first.hashCode(), duplicate.hashCode());
-
- final ECKey.ECDSASignature highS = new ECKey.ECDSASignature(first.r, ECKey.CURVE.getN().subtract(first.s));
- assertFalse(highS.isCanonical());
- }
-
- @Test
- public void testSignatures() throws Exception {
- // Test that we can construct an ECKey from a private key (deriving the public from the private), then signing
- // a message with it.
- BigInteger privkey = new BigInteger(1, HEX.decode("180cb41c7c600be951b5d3d0a7334acc7506173875834f7a6c4c786a28fcbb19"));
- ECKey key = ECKey.fromPrivate(privkey);
- byte[] output = key.sign(Sha256Hash.ZERO_HASH).encodeToDER();
- assertTrue(key.verify(Sha256Hash.ZERO_HASH.getBytes(), output));
-
- // Test interop with a signature from elsewhere.
- byte[] sig = HEX.decode(
- "3046022100dffbc26774fc841bbe1c1362fd643609c6e42dcb274763476d87af2c0597e89e022100c59e3c13b96b316cae9fa0ab0260612c7a133a6fe2b3445b6bf80b3123bf274d");
- assertTrue(key.verify(Sha256Hash.ZERO_HASH.getBytes(), sig));
- }
-
- @Test
- public void testASN1Roundtrip() throws Exception {
- byte[] privkeyASN1 = HEX.decode(
- "3082011302010104205c0b98e524ad188ddef35dc6abba13c34a351a05409e5d285403718b93336a4aa081a53081a2020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101a144034200042af7a2aafe8dafd7dc7f9cfb58ce09bda7dce28653ab229b98d1d3d759660c672dd0db18c8c2d76aa470448e876fc2089ab1354c01a6e72cefc50915f4a963ee");
- ECKey decodedKey = ECKey.fromASN1(privkeyASN1);
-
- // Now re-encode and decode the ASN.1 to see if it is equivalent (it does not produce the exact same byte
- // sequence, some integers are padded now).
- ECKey roundtripKey = ECKey.fromASN1(decodedKey.toASN1());
-
- assertArrayEquals(decodedKey.getPrivKeyBytes(), roundtripKey.getPrivKeyBytes());
-
- for (ECKey key : new ECKey[] {decodedKey, roundtripKey}) {
- byte[] message = reverseBytes(HEX.decode(
- "11da3761e86431e4a54c176789e41f1651b324d240d599a7067bee23d328ec2a"));
- byte[] output = key.sign(new Sha256Hash(message)).encodeToDER();
- assertTrue(key.verify(message, output));
-
- output = HEX.decode(
- "304502206faa2ebc614bf4a0b31f0ce4ed9012eb193302ec2bcaccc7ae8bb40577f47549022100c73a1a1acc209f3f860bf9b9f5e13e9433db6f8b7bd527a088a0e0cd0a4c83e9");
- assertTrue(key.verify(message, output));
- }
-
- // Try to sign with one key and verify with the other.
- byte[] message = reverseBytes(HEX.decode(
- "11da3761e86431e4a54c176789e41f1651b324d240d599a7067bee23d328ec2a"));
- assertTrue(roundtripKey.verify(message, decodedKey.sign(new Sha256Hash(message)).encodeToDER()));
- assertTrue(decodedKey.verify(message, roundtripKey.sign(new Sha256Hash(message)).encodeToDER()));
- }
-
- @Test
- public void testKeyPairRoundtrip() throws Exception {
- byte[] privkeyASN1 = HEX.decode(
- "3082011302010104205c0b98e524ad188ddef35dc6abba13c34a351a05409e5d285403718b93336a4aa081a53081a2020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101a144034200042af7a2aafe8dafd7dc7f9cfb58ce09bda7dce28653ab229b98d1d3d759660c672dd0db18c8c2d76aa470448e876fc2089ab1354c01a6e72cefc50915f4a963ee");
- ECKey decodedKey = ECKey.fromASN1(privkeyASN1);
-
- // Now re-encode and decode the ASN.1 to see if it is equivalent (it does not produce the exact same byte
- // sequence, some integers are padded now).
- ECKey roundtripKey =
- ECKey.fromPrivateAndPrecalculatedPublic(decodedKey.getPrivKey(), decodedKey.getPubKeyPoint());
-
- for (ECKey key : new ECKey[] {decodedKey, roundtripKey}) {
- byte[] message = reverseBytes(HEX.decode(
- "11da3761e86431e4a54c176789e41f1651b324d240d599a7067bee23d328ec2a"));
- byte[] output = key.sign(new Sha256Hash(message)).encodeToDER();
- assertTrue(key.verify(message, output));
-
- output = HEX.decode(
- "304502206faa2ebc614bf4a0b31f0ce4ed9012eb193302ec2bcaccc7ae8bb40577f47549022100c73a1a1acc209f3f860bf9b9f5e13e9433db6f8b7bd527a088a0e0cd0a4c83e9");
- assertTrue(key.verify(message, output));
- }
-
- // Try to sign with one key and verify with the other.
- byte[] message = reverseBytes(HEX.decode(
- "11da3761e86431e4a54c176789e41f1651b324d240d599a7067bee23d328ec2a"));
- assertTrue(roundtripKey.verify(message, decodedKey.sign(new Sha256Hash(message)).encodeToDER()));
- assertTrue(decodedKey.verify(message, roundtripKey.sign(new Sha256Hash(message)).encodeToDER()));
-
- // Verify bytewise equivalence of public keys (i.e. compression state is preserved)
- ECKey key = new ECKey();
- ECKey key2 = ECKey.fromASN1(key.toASN1());
- assertArrayEquals(key.getPubKey(), key2.getPubKey());
- }
-
- @Test
- public void base58Encoding() throws Exception {
- String addr = "mqAJmaxMcG5pPHHc3H3NtyXzY7kGbJLuMF";
- String privkey = "92shANodC6Y4evT5kFzjNFQAdjqTtHAnDTLzqBBq4BbKUPyx6CD";
- ECKey key = new DumpedPrivateKey(TestNet3Params.get(), privkey).getKey();
- assertEquals(privkey, key.getPrivateKeyEncoded(TestNet3Params.get()).toString());
- assertEquals(addr, key.toAddress(TestNet3Params.get()).toString());
- }
-
- @Test
- public void base58Encoding_leadingZero() throws Exception {
- String privkey = "91axuYLa8xK796DnBXXsMbjuc8pDYxYgJyQMvFzrZ6UfXaGYuqL";
- ECKey key = new DumpedPrivateKey(TestNet3Params.get(), privkey).getKey();
- assertEquals(privkey, key.getPrivateKeyEncoded(TestNet3Params.get()).toString());
- assertEquals(0, key.getPrivKeyBytes()[0]);
- }
-
- @Test
- public void base58Encoding_stress() throws Exception {
- // Replace the loop bound with 1000 to get some keys with leading zero byte
- for (int i = 0 ; i < 20 ; i++) {
- ECKey key = new ECKey();
- ECKey key1 = new DumpedPrivateKey(TestNet3Params.get(),
- key.getPrivateKeyEncoded(TestNet3Params.get()).toString()).getKey();
- assertEquals(Utils.HEX.encode(key.getPrivKeyBytes()),
- Utils.HEX.encode(key1.getPrivKeyBytes()));
- }
- }
-
- @Test
- public void signTextMessage() throws Exception {
- ECKey key = new ECKey();
- String message = "聡中本";
- String signatureBase64 = key.signMessage(message);
- log.info("Message signed with " + key.toAddress(MainNetParams.get()) + ": " + signatureBase64);
- // Should verify correctly.
- key.verifyMessage(message, signatureBase64);
- try {
- key.verifyMessage("Evil attacker says hello!", signatureBase64);
- fail();
- } catch (SignatureException e) {
- // OK.
- }
- }
-
- @Test
- public void verifyMessage() throws Exception {
- // Test vector generated by Bitcoin-Qt.
- String message = "hello";
- String sigBase64 = "HxNZdo6ggZ41hd3mM3gfJRqOQPZYcO8z8qdX2BwmpbF11CaOQV+QiZGGQxaYOncKoNW61oRuSMMF8udfK54XqI8=";
- Address expectedAddress = new Address(MainNetParams.get(), "14YPSNPi6NSXnUxtPAsyJSuw3pv7AU3Cag");
- ECKey key = ECKey.signedMessageToKey(message, sigBase64);
- Address gotAddress = key.toAddress(MainNetParams.get());
- assertEquals(expectedAddress, gotAddress);
- }
-
- @Test
- public void keyRecovery() throws Exception {
- ECKey key = new ECKey();
- String message = "Hello World!";
- Sha256Hash hash = Sha256Hash.create(message.getBytes());
- ECKey.ECDSASignature sig = key.sign(hash);
- key = ECKey.fromPublicOnly(key.getPubKeyPoint());
- boolean found = false;
- for (int i = 0; i < 4; i++) {
- ECKey key2 = ECKey.recoverFromSignature(i, sig, hash, true);
- checkNotNull(key2);
- if (key.equals(key2)) {
- found = true;
- break;
- }
- }
- assertTrue(found);
- }
-
- @Test
- public void testUnencryptedCreate() throws Exception {
- Utils.setMockClock();
- ECKey key = new ECKey();
- long time = key.getCreationTimeSeconds();
- assertNotEquals(0, time);
- assertTrue(!key.isEncrypted());
- byte[] originalPrivateKeyBytes = key.getPrivKeyBytes();
- ECKey encryptedKey = key.encrypt(keyCrypter, keyCrypter.deriveKey(PASSWORD1));
- assertEquals(time, encryptedKey.getCreationTimeSeconds());
- assertTrue(encryptedKey.isEncrypted());
- assertNull(encryptedKey.getSecretBytes());
- key = encryptedKey.decrypt(keyCrypter.deriveKey(PASSWORD1));
- assertTrue(!key.isEncrypted());
- assertArrayEquals(originalPrivateKeyBytes, key.getPrivKeyBytes());
- }
-
- @Test
- public void testEncryptedCreate() throws Exception {
- ECKey unencryptedKey = new ECKey();
- byte[] originalPrivateKeyBytes = checkNotNull(unencryptedKey.getPrivKeyBytes());
- log.info("Original private key = " + Utils.HEX.encode(originalPrivateKeyBytes));
- EncryptedData encryptedPrivateKey = keyCrypter.encrypt(unencryptedKey.getPrivKeyBytes(), keyCrypter.deriveKey(PASSWORD1));
- ECKey encryptedKey = ECKey.fromEncrypted(encryptedPrivateKey, keyCrypter, unencryptedKey.getPubKey());
- assertTrue(encryptedKey.isEncrypted());
- assertNull(encryptedKey.getSecretBytes());
- ECKey rebornUnencryptedKey = encryptedKey.decrypt(keyCrypter.deriveKey(PASSWORD1));
- assertTrue(!rebornUnencryptedKey.isEncrypted());
- assertArrayEquals(originalPrivateKeyBytes, rebornUnencryptedKey.getPrivKeyBytes());
- }
-
- @Test
- public void testEncryptionIsReversible() throws Exception {
- ECKey originalUnencryptedKey = new ECKey();
- EncryptedData encryptedPrivateKey = keyCrypter.encrypt(originalUnencryptedKey.getPrivKeyBytes(), keyCrypter.deriveKey(PASSWORD1));
- ECKey encryptedKey = ECKey.fromEncrypted(encryptedPrivateKey, keyCrypter, originalUnencryptedKey.getPubKey());
-
- // The key should be encrypted
- assertTrue("Key not encrypted at start", encryptedKey.isEncrypted());
-
- // Check that the key can be successfully decrypted back to the original.
- assertTrue("Key encryption is not reversible but it should be", ECKey.encryptionIsReversible(originalUnencryptedKey, encryptedKey, keyCrypter, keyCrypter.deriveKey(PASSWORD1)));
-
- // Check that key encryption is not reversible if a password other than the original is used to generate the AES key.
- assertTrue("Key encryption is reversible with wrong password", !ECKey.encryptionIsReversible(originalUnencryptedKey, encryptedKey, keyCrypter, keyCrypter.deriveKey(WRONG_PASSWORD)));
-
- // Change one of the encrypted key bytes (this is to simulate a faulty keyCrypter).
- // Encryption should not be reversible
- byte[] goodEncryptedPrivateKeyBytes = encryptedPrivateKey.encryptedBytes;
-
- // Break the encrypted private key and check it is broken.
- byte[] badEncryptedPrivateKeyBytes = new byte[goodEncryptedPrivateKeyBytes.length];
- encryptedPrivateKey = new EncryptedData(encryptedPrivateKey.initialisationVector, badEncryptedPrivateKeyBytes);
- ECKey badEncryptedKey = ECKey.fromEncrypted(encryptedPrivateKey, keyCrypter, originalUnencryptedKey.getPubKey());
- assertTrue("Key encryption is reversible with faulty encrypted bytes", !ECKey.encryptionIsReversible(originalUnencryptedKey, badEncryptedKey, keyCrypter, keyCrypter.deriveKey(PASSWORD1)));
- }
-
- @Test
- public void testToString() throws Exception {
- ECKey key = ECKey.fromPrivate(BigInteger.TEN).decompress(); // An example private key.
- NetworkParameters params = MainNetParams.get();
- assertEquals("ECKey{pub HEX=04a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7, isEncrypted=false, isPubKeyOnly=false}", key.toString());
- assertEquals("ECKey{pub HEX=04a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7, priv HEX=000000000000000000000000000000000000000000000000000000000000000a, priv WIF=5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreBoNWTw6, isEncrypted=false, isPubKeyOnly=false}", key.toStringWithPrivate(params));
- }
-
- @Test
- public void testGetPrivateKeyAsHex() throws Exception {
- ECKey key = ECKey.fromPrivate(BigInteger.TEN).decompress(); // An example private key.
- assertEquals("000000000000000000000000000000000000000000000000000000000000000a", key.getPrivateKeyAsHex());
- }
-
- @Test
- public void testGetPublicKeyAsHex() throws Exception {
- ECKey key = ECKey.fromPrivate(BigInteger.TEN).decompress(); // An example private key.
- assertEquals("04a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7", key.getPublicKeyAsHex());
- }
-
- @Test
- public void keyRecoveryWithEncryptedKey() throws Exception {
- ECKey unencryptedKey = new ECKey();
- KeyParameter aesKey = keyCrypter.deriveKey(PASSWORD1);
- ECKey encryptedKey = unencryptedKey.encrypt(keyCrypter, aesKey);
-
- String message = "Goodbye Jupiter!";
- Sha256Hash hash = Sha256Hash.create(message.getBytes());
- ECKey.ECDSASignature sig = encryptedKey.sign(hash, aesKey);
- unencryptedKey = ECKey.fromPublicOnly(unencryptedKey.getPubKeyPoint());
- boolean found = false;
- for (int i = 0; i < 4; i++) {
- ECKey key2 = ECKey.recoverFromSignature(i, sig, hash, true);
- checkNotNull(key2);
- if (unencryptedKey.equals(key2)) {
- found = true;
- break;
- }
- }
- assertTrue(found);
- }
-
- @Test
- public void roundTripDumpedPrivKey() throws Exception {
- ECKey key = new ECKey();
- assertTrue(key.isCompressed());
- NetworkParameters params = UnitTestParams.get();
- String base58 = key.getPrivateKeyEncoded(params).toString();
- ECKey key2 = new DumpedPrivateKey(params, base58).getKey();
- assertTrue(key2.isCompressed());
- assertTrue(Arrays.equals(key.getPrivKeyBytes(), key2.getPrivKeyBytes()));
- assertTrue(Arrays.equals(key.getPubKey(), key2.getPubKey()));
- }
-
- @Test
- public void clear() throws Exception {
- ECKey unencryptedKey = new ECKey();
- ECKey encryptedKey = (new ECKey()).encrypt(keyCrypter, keyCrypter.deriveKey(PASSWORD1));
-
- checkSomeBytesAreNonZero(unencryptedKey.getPrivKeyBytes());
-
- // The encryptedPrivateKey should be null in an unencrypted ECKey anyhow but check all the same.
- assertTrue(unencryptedKey.getEncryptedPrivateKey() == null);
-
- checkSomeBytesAreNonZero(encryptedKey.getSecretBytes());
- checkSomeBytesAreNonZero(encryptedKey.getEncryptedPrivateKey().encryptedBytes);
- checkSomeBytesAreNonZero(encryptedKey.getEncryptedPrivateKey().initialisationVector);
- }
-
- @Test
- public void testCanonicalSigs() throws Exception {
- // Tests the canonical sigs from the reference client unit tests
- InputStream in = getClass().getResourceAsStream("sig_canonical.json");
-
- // Poor man's JSON parser (because pulling in a lib for this is overkill)
- while (in.available() > 0) {
- while (in.available() > 0 && in.read() != '"') ;
- if (in.available() < 1)
- break;
-
- StringBuilder sig = new StringBuilder();
- int c;
- while (in.available() > 0 && (c = in.read()) != '"')
- sig.append((char)c);
-
- assertTrue(TransactionSignature.isEncodingCanonical(HEX.decode(sig.toString())));
- }
- in.close();
- }
-
- @Test
- public void testNonCanonicalSigs() throws Exception {
- // Tests the noncanonical sigs from the reference client unit tests
- InputStream in = getClass().getResourceAsStream("sig_noncanonical.json");
-
- // Poor man's JSON parser (because pulling in a lib for this is overkill)
- while (in.available() > 0) {
- while (in.available() > 0 && in.read() != '"') ;
- if (in.available() < 1)
- break;
-
- StringBuilder sig = new StringBuilder();
- int c;
- while (in.available() > 0 && (c = in.read()) != '"')
- sig.append((char)c);
-
- try {
- final String sigStr = sig.toString();
- assertFalse(TransactionSignature.isEncodingCanonical(HEX.decode(sigStr)));
- } catch (IllegalArgumentException e) {
- // Expected for non-hex strings in the JSON that we should ignore
- }
- }
- in.close();
- }
-
- @Test
- public void testCreatedSigAndPubkeyAreCanonical() throws Exception {
- // Tests that we will not generate non-canonical pubkeys or signatures
- // We dump failed data to error log because this test is not expected to be deterministic
- ECKey key = new ECKey();
- if (!ECKey.isPubKeyCanonical(key.getPubKey())) {
- log.error(Utils.HEX.encode(key.getPubKey()));
- fail();
- }
-
- byte[] hash = new byte[32];
- new Random().nextBytes(hash);
- byte[] sigBytes = key.sign(new Sha256Hash(hash)).encodeToDER();
- byte[] encodedSig = Arrays.copyOf(sigBytes, sigBytes.length + 1);
- encodedSig[sigBytes.length] = (byte) (Transaction.SigHash.ALL.ordinal() + 1);
- if (!TransactionSignature.isEncodingCanonical(encodedSig)) {
- log.error(Utils.HEX.encode(sigBytes));
- fail();
- }
- }
-
- private static boolean checkSomeBytesAreNonZero(byte[] bytes) {
- if (bytes == null) return false;
- for (byte b : bytes) if (b != 0) return true;
- return false;
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/FilteredBlockAndPartialMerkleTreeTests.java b/core/src/test/java/com/dogecoin/dogecoinj/core/FilteredBlockAndPartialMerkleTreeTests.java
deleted file mode 100644
index 1af8772d..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/FilteredBlockAndPartialMerkleTreeTests.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/**
- * Copyright 2012 Matt Corallo
- * 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 com.dogecoin.dogecoinj.core;
-
-import com.google.common.collect.Lists;
-import com.dogecoin.dogecoinj.core.TransactionConfidence.ConfidenceType;
-import com.dogecoin.dogecoinj.params.UnitTestParams;
-import com.dogecoin.dogecoinj.store.MemoryBlockStore;
-import com.dogecoin.dogecoinj.testing.FakeTxBuilder;
-import com.dogecoin.dogecoinj.testing.InboundMessageQueuer;
-import com.dogecoin.dogecoinj.testing.TestWithPeerGroup;
-import com.dogecoin.dogecoinj.wallet.KeyChainGroup;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-
-import java.math.BigInteger;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-
-import static com.dogecoin.dogecoinj.core.Utils.HEX;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-@RunWith(value = Parameterized.class)
-public class FilteredBlockAndPartialMerkleTreeTests extends TestWithPeerGroup {
- @Parameterized.Parameters
- public static Collection parameters() {
- return Arrays.asList(new ClientType[] {ClientType.NIO_CLIENT_MANAGER},
- new ClientType[] {ClientType.BLOCKING_CLIENT_MANAGER});
- }
-
- public FilteredBlockAndPartialMerkleTreeTests(ClientType clientType) {
- super(clientType);
- }
-
- @Test
- public void deserializeFilteredBlock() throws Exception {
- NetworkParameters params = UnitTestParams.get();
-
- // Random real block (000000000000dab0130bbcc991d3d7ae6b81aa6f50a798888dfe62337458dc45)
- // With one tx
- FilteredBlock block = new FilteredBlock(params, HEX.decode("0100000079cda856b143d9db2c1caff01d1aecc8630d30625d10e8b4b8b0000000000000b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f196367291b4d4c86041b8fa45d630100000001b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f19630101"));
-
- // Check that the header was properly deserialized
- assertTrue(block.getBlockHeader().getHash().equals(new Sha256Hash("000000000000dab0130bbcc991d3d7ae6b81aa6f50a798888dfe62337458dc45")));
-
- // Check that the partial merkle tree is correct
- List txesMatched = block.getTransactionHashes();
- assertTrue(txesMatched.size() == 1);
- assertTrue(txesMatched.contains(new Sha256Hash("63194f18be0af63f2c6bc9dc0f777cbefed3d9415c4af83f3ee3a3d669c00cb5")));
-
- // Check round tripping.
- assertEquals(block, new FilteredBlock(params, block.bitcoinSerialize()));
- }
-
- @Test
- public void createFilteredBlock() throws Exception {
- ECKey key1 = new ECKey();
- ECKey key2 = new ECKey();
- Transaction tx1 = FakeTxBuilder.createFakeTx(params, Coin.COIN, key1);
- Transaction tx2 = FakeTxBuilder.createFakeTx(params, Coin.FIFTY_COINS, key2.toAddress(params));
- Block block = FakeTxBuilder.makeSolvedTestBlock(params.getGenesisBlock(), new Address(params, "msg2t2V2sWNd85LccoddtWysBTR8oPnkzW"), tx1, tx2);
- BloomFilter filter = new BloomFilter(4, 0.1, 1);
- filter.insert(key1);
- filter.insert(key2);
- FilteredBlock filteredBlock = filter.applyAndUpdate(block);
- assertEquals(4, filteredBlock.getTransactionCount());
- // This call triggers verification of the just created data.
- List txns = filteredBlock.getTransactionHashes();
- assertTrue(txns.contains(tx1.getHash()));
- assertTrue(txns.contains(tx2.getHash()));
- }
-
- private Sha256Hash numAsHash(int num) {
- byte[] bits = new byte[32];
- bits[0] = (byte) num;
- return new Sha256Hash(bits);
- }
-
- @Test(expected = VerificationException.class)
- public void merkleTreeMalleability() throws Exception {
- List hashes = Lists.newArrayList();
- for (byte i = 1; i <= 10; i++) hashes.add(numAsHash(i));
- hashes.add(numAsHash(9));
- hashes.add(numAsHash(10));
- byte[] includeBits = new byte[2];
- Utils.setBitLE(includeBits, 9);
- Utils.setBitLE(includeBits, 10);
- PartialMerkleTree pmt = PartialMerkleTree.buildFromLeaves(params, includeBits, hashes);
- List matchedHashes = Lists.newArrayList();
- pmt.getTxnHashAndMerkleRoot(matchedHashes);
- }
-
- @Test
- public void serializeDownloadBlockWithWallet() throws Exception {
- unitTestParams = UnitTestParams.get();
-
- // First we create all the neccessary objects, including lots of serialization and double-checks
- // Note that all serialized forms here are generated by the reference client/pulled from block explorer
- Block block = new Block(unitTestParams, HEX.decode("0100000006e533fd1ada86391f3f6c343204b0d278d4aaec1c0b20aa27ba0300000000006abbb3eb3d733a9fe18967fd7d4c117e4ccbbac5bec4d910d900b3ae0793e77f54241b4d4c86041b4089cc9b0c01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07044c86041b010dffffffff0100f2052a01000000434104b27f7e9475ccf5d9a431cb86d665b8302c140144ec2397fce792f4a4e7765fecf8128534eaa71df04f93c74676ae8279195128a1506ebf7379d23dab8fca0f63ac000000000100000001d992e5a888a86d4c7a6a69167a4728ee69497509740fc5f456a24528c340219a000000008b483045022100f0519bdc9282ff476da1323b8ef7ffe33f495c1a8d52cc522b437022d83f6a230220159b61d197fbae01b4a66622a23bc3f1def65d5fa24efd5c26fa872f3a246b8e014104839f9023296a1fabb133140128ca2709f6818c7d099491690bd8ac0fd55279def6a2ceb6ab7b5e4a71889b6e739f09509565eec789e86886f6f936fa42097adeffffffff02000fe208010000001976a914948c765a6914d43f2a7ac177da2c2f6b52de3d7c88ac00e32321000000001976a9140c34f4e29ab5a615d5ea28d4817f12b137d62ed588ac0000000001000000059daf0abe7a92618546a9dbcfd65869b6178c66ec21ccfda878c1175979cfd9ef000000004a493046022100c2f7f25be5de6ce88ac3c1a519514379e91f39b31ddff279a3db0b1a229b708b022100b29efbdbd9837cc6a6c7318aa4900ed7e4d65662c34d1622a2035a3a5534a99a01ffffffffd516330ebdf075948da56db13d22632a4fb941122df2884397dda45d451acefb0000000048473044022051243debe6d4f2b433bee0cee78c5c4073ead0e3bde54296dbed6176e128659c022044417bfe16f44eb7b6eb0cdf077b9ce972a332e15395c09ca5e4f602958d266101ffffffffe1f5aa33961227b3c344e57179417ce01b7ccd421117fe2336289b70489883f900000000484730440220593252bb992ce3c85baf28d6e3aa32065816271d2c822398fe7ee28a856bc943022066d429dd5025d3c86fd8fd8a58e183a844bd94aa312cefe00388f57c85b0ca3201ffffffffe207e83718129505e6a7484831442f668164ae659fddb82e9e5421a081fb90d50000000049483045022067cf27eb733e5bcae412a586b25a74417c237161a084167c2a0b439abfebdcb2022100efcc6baa6824b4c5205aa967e0b76d31abf89e738d4b6b014e788c9a8cccaf0c01ffffffffe23b8d9d80a9e9d977fab3c94dbe37befee63822443c3ec5ae5a713ede66c3940000000049483045022020f2eb35036666b1debe0d1d2e77a36d5d9c4e96c1dba23f5100f193dbf524790221008ce79bc1321fb4357c6daee818038d41544749127751726e46b2b320c8b565a201ffffffff0200ba1dd2050000001976a914366a27645806e817a6cd40bc869bdad92fe5509188ac40420f00000000001976a914ee8bd501094a7d5ca318da2506de35e1cb025ddc88ac0000000001000000010abad2dc0c9b4b1dbb023077da513f81e5a71788d8680fca98ef1c37356c459c000000004a493046022100a894e521c87b3dbe23007079db4ac2896e9e791f8b57317ba6c0d99a7becd27a022100bc40981393eafeb33e89079f857c728701a9af4523c3f857cd96a500f240780901ffffffff024026ee22010000001976a914d28f9cefb58c1f7a5f97aa6b79047585f58fbd4388acc0cb1707000000001976a9142229481696e417aa5f51ad751d8cd4c6a669e4fe88ac000000000100000001f66d89b3649e0b18d84db056930676cb81c0168042fc4324c3682e252ea9410d0000000048473044022038e0b55b37c9253bfeda59c76c0134530f91fb586d6eb21738a77a984f370a44022048d4d477aaf97ef9c8275bbc5cb19b9c8a0e9b1f9fdafdd39bc85bf6c2f04a4d01ffffffff024041a523010000001976a914955f70ac8792b48b7bd52b15413bd8500ecf32c888ac00f36f06000000001976a91486116d15f3dbb23a2b58346f36e6ec2d867eba2b88ac00000000010000000126c384984f63446a4f2be8dd6531ba9837bd5f2c3d37403c5f51fb9192ee754e010000008b48304502210083af8324456f052ff1b2597ff0e6a8cce8b006e379a410cf781be7874a2691c2022072259e2f7292960dea0ffc361bbad0b861f719beb8550476f22ce0f82c023449014104f3ed46a81cba02af0593e8572a9130adb0d348b538c829ccaaf8e6075b78439b2746a76891ce7ba71abbcbb7ca76e8a220782738a6789562827c1065b0ce911dffffffff02c0dd9107000000001976a91463d4dd1b29d95ed601512b487bfc1c49d84d057988ac00a0491a010000001976a91465746bef92511df7b34abf71c162efb7ae353de388ac0000000001000000011b56cf3aab3286d582c055a42af3a911ee08423f276da702bb67f1222ac1a5b6000000008c4930460221009e9fba682e162c9627b96b7df272006a727988680b956c61baff869f0907b8fb022100a9c19adc7c36144bafe526630783845e5cb9554d30d3edfb56f0740274d507f30141046e0efbfac7b1615ad553a6f097615bc63b7cdb3b8e1cb3263b619ba63740012f51c7c5b09390e3577e377b7537e61226e315f95f926444fc5e5f2978c112e448ffffffff02c0072b11010000001976a914b73e9e01933351ca076faf8e0d94dd58079d0b1f88ac80b63908000000001976a9141aca0bdf0d2cee63db19aa4a484f45a4e26a880c88ac000000000100000001251b187504ea873b2c3915fad401f7a7734cc13567e0417708e86294a29f4f68010000008b4830450221009bef423141ed1ae60d0a5bcaa57b1673fc96001f0d4e105535cca817ba5a7724022037c399bd30374f22481ffc81327cfca4951c7264b227f765fcd6a429f3d9d2080141044d0d1b4f194c31a73dbce41c42b4b3946849117c5bb320467e014bad3b1532f28a9a1568ba7108f188e7823b6e618e91d974306701379a27b9339e646e156e7bffffffff02c00fd103010000001976a914ef7f5d9e1bc6ed68cfe0b1db9d8f09cef0f3ba4a88ac004dd208000000001976a914c22420641cea028c9e06c4d9104c1646f8b1769088ac0000000001000000013486dd5f0a2f3efcc04f64cb03872c021f98ee39f514747ce5336b874bbe47a7010000008b48304502201cadddc2838598fee7dc35a12b340c6bde8b389f7bfd19a1252a17c4b5ed2d71022100c1a251bbecb14b058a8bd77f65de87e51c47e95904f4c0e9d52eddc21c1415ac014104fe7df86d58aafa9246ca6fd30c905714533c25f700e2329b8ecec8aa52083b844baa3a8acd5d6b9732dcb39079bb56ba2711a3580dec824955fce0596a460c11ffffffff02c011f6e1000000001976a91490fac83c9adde91d670dde8755f8b475ab9e427d88acc0f9df15000000001976a91437f691b3e8ee5dcb56c2e31af4c80caa2df3b09b88ac00000000010000000170016bd1274b795b262f32a53003a4714b22b62f9057adf5fbe6ed939003b5190100000089463043022061456499582170a94d6b54308f792e37dad28bf0ed7aa61021f0301d2774d378021f4224b33f707efd810a01dd34ea86d6069cd599cc435513a0eef8c83c137bf7014104a2c95d6b98e745448eb45ed0ba95cf24dd7c3b16386e1028e24a0358ee4afc33e2f0199139853edaf32845d8a42254c75f7dc8add3286c682c650fbd93f0a4a1ffffffff02001bd2b7000000001976a9141b11c6acaa5223013f3a3240fdb024ecd9f8135488ac8023ad18000000001976a914ada27ca87bbaa1ee6fb1cb61bb0a29baaf6da2c988ac000000000100000001c8ff91f031ec6a5aba4baee6549e61dd01f26f61b70e2f1574f24cd680f464ad000000008b48304502210082235e21a2300022738dabb8e1bbd9d19cfb1e7ab8c30a23b0afbb8d178abcf3022024bf68e256c534ddfaf966bf908deb944305596f7bdcc38d69acad7f9c868724014104174f9eef1157dc1ad5eac198250b70d1c3b04b2fca12ad1483f07358486f02909b088bbc83f4de55f767f6cdf9d424aa02b5eeaffa08394d39b717895fc08d0affffffff0200ea3b43000000001976a914fb32df708f0610901f6d1b6df8c9c368fe0d981c88ac800f1777000000001976a914462c501c70fb996d15ac0771e7fc8d3ca3f7201888ac000000000100000001c67323867de802402e780a70e0deba3c708c4d87497e17590afee9c321f1c680010000008a473044022042734b25f54845d662e6499b75ff8529ff47f42fd224498a9f752d212326dbfa0220523e4b7b570bbb1f3af02baa2c04ea8eb7b0fccb1522cced130b666ae9a9d014014104b5a23b922949877e9eaf7512897ed091958e2e8cf05b0d0eb9064e7976043fde6023b4e2c188b7e38ef94eec6845dc4933f5e8635f1f6a3702290956aa9e284bffffffff0280041838030000001976a91436e5884215f7d3044be5d37bdd8c987d9d942c8488ac404b4c00000000001976a91460085d6838f8a44a21a0de56ff963cfa6242a96188ac00000000"));
- FilteredBlock filteredBlock = new FilteredBlock(unitTestParams, HEX.decode("0100000006e533fd1ada86391f3f6c343204b0d278d4aaec1c0b20aa27ba0300000000006abbb3eb3d733a9fe18967fd7d4c117e4ccbbac5bec4d910d900b3ae0793e77f54241b4d4c86041b4089cc9b0c000000084c30b63cfcdc2d35e3329421b9805ef0c6565d35381ca857762ea0b3a5a128bbca5065ff9617cbcba45eb23726df6498a9b9cafed4f54cbab9d227b0035ddefbbb15ac1d57d0182aaee61c74743a9c4f785895e563909bafec45c9a2b0ff3181d77706be8b1dcc91112eada86d424e2d0a8907c3488b6e44fda5a74a25cbc7d6bb4fa04245f4ac8a1a571d5537eac24adca1454d65eda446055479af6c6d4dd3c9ab658448c10b6921b7a4ce3021eb22ed6bb6a7fde1e5bcc4b1db6615c6abc5ca042127bfaf9f44ebce29cb29c6df9d05b47f35b2edff4f0064b578ab741fa78276222651209fe1a2c4c0fa1c58510aec8b090dd1eb1f82f9d261b8273b525b02ff1a"));
-
- // Block 100001
- assertTrue(block.getHash().equals(new Sha256Hash("00000000000080b66c911bd5ba14a74260057311eaeb1982802f7010f1a9f090")));
- assertTrue(filteredBlock.getHash().equals(block.getHash()));
-
- List txHashList = filteredBlock.getTransactionHashes();
- assertTrue(txHashList.size() == 4);
- // Four transactions (0, 1, 2, 6) from block 100001
- Transaction tx0 = new Transaction(unitTestParams, HEX.decode("01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07044c86041b010dffffffff0100f2052a01000000434104b27f7e9475ccf5d9a431cb86d665b8302c140144ec2397fce792f4a4e7765fecf8128534eaa71df04f93c74676ae8279195128a1506ebf7379d23dab8fca0f63ac00000000"));
- assertTrue(tx0.getHash().equals(new Sha256Hash("bb28a1a5b3a02e7657a81c38355d56c6f05e80b9219432e3352ddcfc3cb6304c")));
- assertEquals(tx0.getHash(), txHashList.get(0));
-
- Transaction tx1 = new Transaction(unitTestParams, HEX.decode("0100000001d992e5a888a86d4c7a6a69167a4728ee69497509740fc5f456a24528c340219a000000008b483045022100f0519bdc9282ff476da1323b8ef7ffe33f495c1a8d52cc522b437022d83f6a230220159b61d197fbae01b4a66622a23bc3f1def65d5fa24efd5c26fa872f3a246b8e014104839f9023296a1fabb133140128ca2709f6818c7d099491690bd8ac0fd55279def6a2ceb6ab7b5e4a71889b6e739f09509565eec789e86886f6f936fa42097adeffffffff02000fe208010000001976a914948c765a6914d43f2a7ac177da2c2f6b52de3d7c88ac00e32321000000001976a9140c34f4e29ab5a615d5ea28d4817f12b137d62ed588ac00000000"));
- assertTrue(tx1.getHash().equals(new Sha256Hash("fbde5d03b027d2b9ba4cf5d4fecab9a99864df2637b25ea4cbcb1796ff6550ca")));
- assertEquals(tx1.getHash(), txHashList.get(1));
-
- Transaction tx2 = new Transaction(unitTestParams, HEX.decode("01000000059daf0abe7a92618546a9dbcfd65869b6178c66ec21ccfda878c1175979cfd9ef000000004a493046022100c2f7f25be5de6ce88ac3c1a519514379e91f39b31ddff279a3db0b1a229b708b022100b29efbdbd9837cc6a6c7318aa4900ed7e4d65662c34d1622a2035a3a5534a99a01ffffffffd516330ebdf075948da56db13d22632a4fb941122df2884397dda45d451acefb0000000048473044022051243debe6d4f2b433bee0cee78c5c4073ead0e3bde54296dbed6176e128659c022044417bfe16f44eb7b6eb0cdf077b9ce972a332e15395c09ca5e4f602958d266101ffffffffe1f5aa33961227b3c344e57179417ce01b7ccd421117fe2336289b70489883f900000000484730440220593252bb992ce3c85baf28d6e3aa32065816271d2c822398fe7ee28a856bc943022066d429dd5025d3c86fd8fd8a58e183a844bd94aa312cefe00388f57c85b0ca3201ffffffffe207e83718129505e6a7484831442f668164ae659fddb82e9e5421a081fb90d50000000049483045022067cf27eb733e5bcae412a586b25a74417c237161a084167c2a0b439abfebdcb2022100efcc6baa6824b4c5205aa967e0b76d31abf89e738d4b6b014e788c9a8cccaf0c01ffffffffe23b8d9d80a9e9d977fab3c94dbe37befee63822443c3ec5ae5a713ede66c3940000000049483045022020f2eb35036666b1debe0d1d2e77a36d5d9c4e96c1dba23f5100f193dbf524790221008ce79bc1321fb4357c6daee818038d41544749127751726e46b2b320c8b565a201ffffffff0200ba1dd2050000001976a914366a27645806e817a6cd40bc869bdad92fe5509188ac40420f00000000001976a914ee8bd501094a7d5ca318da2506de35e1cb025ddc88ac00000000"));
- assertTrue(tx2.getHash().equals(new Sha256Hash("8131ffb0a2c945ecaf9b9063e59558784f9c3a74741ce6ae2a18d0571dac15bb")));
- assertEquals(tx2.getHash(), txHashList.get(2));
-
-
- Transaction tx3 = new Transaction(unitTestParams, HEX.decode("01000000011b56cf3aab3286d582c055a42af3a911ee08423f276da702bb67f1222ac1a5b6000000008c4930460221009e9fba682e162c9627b96b7df272006a727988680b956c61baff869f0907b8fb022100a9c19adc7c36144bafe526630783845e5cb9554d30d3edfb56f0740274d507f30141046e0efbfac7b1615ad553a6f097615bc63b7cdb3b8e1cb3263b619ba63740012f51c7c5b09390e3577e377b7537e61226e315f95f926444fc5e5f2978c112e448ffffffff02c0072b11010000001976a914b73e9e01933351ca076faf8e0d94dd58079d0b1f88ac80b63908000000001976a9141aca0bdf0d2cee63db19aa4a484f45a4e26a880c88ac00000000"));
- assertTrue(tx3.getHash().equals(new Sha256Hash("c5abc61566dbb1c4bce5e1fda7b66bed22eb2130cea4b721690bc1488465abc9")));
- assertEquals(tx3.getHash(),txHashList.get(3));
-
- // A wallet which contains a pubkey used in each transaction from above
- KeyChainGroup group = new KeyChainGroup(unitTestParams);
- group.importKeys(ECKey.fromPublicOnly(HEX.decode("04b27f7e9475ccf5d9a431cb86d665b8302c140144ec2397fce792f4a4e7765fecf8128534eaa71df04f93c74676ae8279195128a1506ebf7379d23dab8fca0f63")),
- ECKey.fromPublicOnly(HEX.decode("04732012cb962afa90d31b25d8fb0e32c94e513ab7a17805c14ca4c3423e18b4fb5d0e676841733cb83abaf975845c9f6f2a8097b7d04f4908b18368d6fc2d68ec")),
- ECKey.fromPublicOnly(HEX.decode("04cfb4113b3387637131ebec76871fd2760fc430dd16de0110f0eb07bb31ffac85e2607c189cb8582ea1ccaeb64ffd655409106589778f3000fdfe3263440b0350")),
- ECKey.fromPublicOnly(HEX.decode("04b2f30018908a59e829c1534bfa5010d7ef7f79994159bba0f534d863ef9e4e973af6a8de20dc41dbea50bc622263ec8a770b2c9406599d39e4c9afe61f8b1613")));
- Wallet wallet = new Wallet(unitTestParams, group);
-
- BloomFilter filter = wallet.getBloomFilter(wallet.getKeychainSize()*2, 0.001, 0xDEADBEEF);
- // Compare the serialized bloom filter to a known-good value
- assertTrue(Arrays.equals(filter.bitcoinSerialize(), HEX.decode("0e1b091ca195e45a9164889b6bc46a09000000efbeadde02")));
-
- // Cheat and place the previous block (block 100000) at the head of the block store without supporting blocks
- blockStore = new MemoryBlockStore(UnitTestParams.get());
- blockStore.put(new StoredBlock(new Block(unitTestParams, HEX.decode("0100000050120119172a610421a6c3011dd330d9df07b63616c2cc1f1cd00200000000006657a9252aacd5c0b2940996ecff952228c3067cc38d4885efb5a4ac4247e9f337221b4d4c86041b0f2b5710")),
- BigInteger.valueOf(1), 100000));
- blockStore.setChainHead(blockStore.get(new Sha256Hash("000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506")));
- super.setUp(blockStore);
-
- peerGroup.addWallet(wallet);
- peerGroup.setUseLocalhostPeerWhenPossible(false); // Prevents from connecting to bitcoin nodes on localhost.
-
- blockChain.addWallet(wallet);
-
- peerGroup.start();
-
- // Create a peer.
- InboundMessageQueuer p1 = connectPeer(1);
- assertEquals(1, peerGroup.numConnectedPeers());
- // Send an inv for block 100001
- InventoryMessage inv = new InventoryMessage(unitTestParams);
- inv.addBlock(block);
- inbound(p1, inv);
-
- // Check that we properly requested the correct FilteredBlock
- Object getData = outbound(p1);
- assertTrue(getData instanceof GetDataMessage);
- assertTrue(((GetDataMessage)getData).getItems().size() == 1);
- assertTrue(((GetDataMessage)getData).getItems().get(0).hash.equals(block.getHash()));
- assertTrue(((GetDataMessage)getData).getItems().get(0).type == InventoryItem.Type.FilteredBlock);
-
- // Check that we then immediately pinged.
- Object ping = outbound(p1);
- assertTrue(ping instanceof Ping);
-
- // Respond with transactions and the filtered block
- inbound(p1, filteredBlock);
- inbound(p1, tx0);
- inbound(p1, tx1);
- inbound(p1, tx2);
- inbound(p1, tx3);
- inbound(p1, new Pong(((Ping)ping).getNonce()));
-
- pingAndWait(p1);
-
- Set transactions = wallet.getTransactions(false);
- assertTrue(transactions.size() == 4);
- for (Transaction tx : transactions) {
- assertTrue(tx.getConfidence().getConfidenceType() == ConfidenceType.BUILDING);
- assertTrue(tx.getConfidence().getDepthInBlocks() == 1);
- assertTrue(tx.getAppearsInHashes().keySet().contains(block.getHash()));
- assertTrue(tx.getAppearsInHashes().size() == 1);
- }
-
- // Peer 1 goes away.
- closePeer(peerOf(p1));
- super.tearDown();
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/FullBlockTestGenerator.java b/core/src/test/java/com/dogecoin/dogecoinj/core/FullBlockTestGenerator.java
deleted file mode 100644
index ab0b201f..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/FullBlockTestGenerator.java
+++ /dev/null
@@ -1,1869 +0,0 @@
-package com.dogecoin.dogecoinj.core;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import com.dogecoin.dogecoinj.core.Transaction.SigHash;
-import com.dogecoin.dogecoinj.crypto.TransactionSignature;
-import com.dogecoin.dogecoinj.script.Script;
-import com.dogecoin.dogecoinj.script.ScriptBuilder;
-import com.google.common.base.Preconditions;
-
-import javax.annotation.Nullable;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.util.*;
-
-import static com.dogecoin.dogecoinj.core.Coin.*;
-import static com.dogecoin.dogecoinj.script.ScriptOpCodes.*;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-
-/**
- * YOU ARE READING THIS CODE BECAUSE EITHER...
- *
- * a) You are testing an alternative implementation with full validation rules. If you are doing this, you should go
- * rethink your life. Seriously, why are you reimplementing Bitcoin consensus rules? Instead, go work on making
- * Bitcoin Core consensus rules a shared library and use that. Seriously, you wont get it right, and starting with
- * this tester as a way to try to do so will simply end in pain and lost coins. SERIOUSLY, JUST STOP!
- *
- * b) Bitcoin Core is faling some test in here and you're wondering what test is causing failure. Just stop. There is no
- * hope trying to read this file and decipher it. Give up and ping BlueMatt. Seriously, this stuff is a huge mess.
- *
- * c) You are trying to add a new test. STOP! WHY THE HELL WOULD YOU EVEN DO THAT? GO REWRITE THIS TESTER!
- *
- * d) You are BlueMatt and you're trying to hack more crap onto this multi-headed lopsided Proof Of Stake. Why are you
- * doing this? Seriously, why have you not rewritten this thing yet? WTF man...
- *
- * IN ANY CASE, STOP READING NOW. IT WILL SAVE YOU MUCH PAIN AND MISERY LATER
- */
-
-class NewBlock {
- public Block block;
- private TransactionOutPointWithValue spendableOutput;
- public NewBlock(Block block, TransactionOutPointWithValue spendableOutput) {
- this.block = block; this.spendableOutput = spendableOutput;
- }
- // Wrappers to make it more block-like
- public Sha256Hash getHash() { return block.getHash(); }
- public void solve() { block.solve(); }
- public void addTransaction(Transaction tx) { block.addTransaction(tx); }
-
- public TransactionOutPointWithValue getCoinbaseOutput() {
- return new TransactionOutPointWithValue(block.getTransactions().get(0), 0);
- }
-
- public TransactionOutPointWithValue getSpendableOutput() {
- return spendableOutput;
- }
-}
-
-class TransactionOutPointWithValue {
- public TransactionOutPoint outpoint;
- public Coin value;
- public Script scriptPubKey;
-
- public TransactionOutPointWithValue(TransactionOutPoint outpoint, Coin value, Script scriptPubKey) {
- this.outpoint = outpoint;
- this.value = value;
- this.scriptPubKey = scriptPubKey;
- }
-
- public TransactionOutPointWithValue(Transaction tx, int output) {
- this(new TransactionOutPoint(tx.getParams(), output, tx.getHash()),
- tx.getOutput(output).getValue(), tx.getOutput(output).getScriptPubKey());
- }
-}
-
-/** An arbitrary rule which the testing client must match */
-class Rule {
- String ruleName;
- Rule(String ruleName) {
- this.ruleName = ruleName;
- }
-}
-
-/**
- * A test which checks the mempool state (ie defined which transactions should be in memory pool
- */
-class MemoryPoolState extends Rule {
- Set mempool;
- public MemoryPoolState(Set mempool, String ruleName) {
- super(ruleName);
- this.mempool = mempool;
- }
-}
-
-class UTXORule extends Rule {
- List query;
- UTXOsMessage result;
-
- public UTXORule(String ruleName, TransactionOutPoint query, UTXOsMessage result) {
- super(ruleName);
- this.query = Collections.singletonList(query);
- this.result = result;
- }
-
- public UTXORule(String ruleName, List query, UTXOsMessage result) {
- super(ruleName);
- this.query = query;
- this.result = result;
- }
-}
-
-class RuleList {
- public List list;
- public int maximumReorgBlockCount;
- Map hashHeaderMap;
- public RuleList(List list, Map hashHeaderMap, int maximumReorgBlockCount) {
- this.list = list;
- this.hashHeaderMap = hashHeaderMap;
- this.maximumReorgBlockCount = maximumReorgBlockCount;
- }
-}
-
-public class FullBlockTestGenerator {
- // Used by BitcoindComparisonTool and AbstractFullPrunedBlockChainTest to create test cases
- private NetworkParameters params;
- private ECKey coinbaseOutKey;
- private byte[] coinbaseOutKeyPubKey;
-
- // Used to double-check that we are always using the right next-height
- private Map blockToHeightMap = new HashMap();
-
- private Map hashHeaderMap = new HashMap();
- private Map coinbaseBlockMap = new HashMap();
-
- public FullBlockTestGenerator(NetworkParameters params) {
- this.params = params;
- coinbaseOutKey = new ECKey();
- coinbaseOutKeyPubKey = coinbaseOutKey.getPubKey();
- Utils.setMockClock();
- }
-
- public RuleList getBlocksToTest(boolean runBarelyExpensiveTests, boolean runExpensiveTests, File blockStorageFile) throws ScriptException, ProtocolException, IOException {
- final FileOutputStream outStream = blockStorageFile != null ? new FileOutputStream(blockStorageFile) : null;
-
- final Script OP_TRUE_SCRIPT = new ScriptBuilder().op(OP_TRUE).build();
- final Script OP_NOP_SCRIPT = new ScriptBuilder().op(OP_NOP).build();
-
- // TODO: Rename this variable.
- List blocks = new LinkedList() {
- @Override
- public boolean add(Rule element) {
- if (outStream != null && element instanceof BlockAndValidity) {
- try {
- outStream.write((int) (params.getPacketMagic() >>> 24));
- outStream.write((int) (params.getPacketMagic() >>> 16));
- outStream.write((int) (params.getPacketMagic() >>> 8));
- outStream.write((int) (params.getPacketMagic() >>> 0));
- byte[] block = ((BlockAndValidity)element).block.bitcoinSerialize();
- byte[] length = new byte[4];
- Utils.uint32ToByteArrayBE(block.length, length, 0);
- outStream.write(Utils.reverseBytes(length));
- outStream.write(block);
- ((BlockAndValidity)element).block = null;
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- return super.add(element);
- }
- };
- RuleList ret = new RuleList(blocks, hashHeaderMap, 10);
-
- Queue spendableOutputs = new LinkedList();
-
- int chainHeadHeight = 1;
- Block chainHead = params.getGenesisBlock().createNextBlockWithCoinbase(coinbaseOutKeyPubKey);
- blocks.add(new BlockAndValidity(chainHead, true, false, chainHead.getHash(), 1, "Initial Block"));
- spendableOutputs.offer(new TransactionOutPointWithValue(
- new TransactionOutPoint(params, 0, chainHead.getTransactions().get(0).getHash()),
- FIFTY_COINS, chainHead.getTransactions().get(0).getOutputs().get(0).getScriptPubKey()));
- for (int i = 1; i < params.getSpendableCoinbaseDepth(); i++) {
- chainHead = chainHead.createNextBlockWithCoinbase(coinbaseOutKeyPubKey);
- chainHeadHeight++;
- blocks.add(new BlockAndValidity(chainHead, true, false, chainHead.getHash(), i+1, "Initial Block chain output generation"));
- spendableOutputs.offer(new TransactionOutPointWithValue(
- new TransactionOutPoint(params, 0, chainHead.getTransactions().get(0).getHash()),
- FIFTY_COINS, chainHead.getTransactions().get(0).getOutputs().get(0).getScriptPubKey()));
- }
-
- // Start by building a couple of blocks on top of the genesis block.
- NewBlock b1 = createNextBlock(chainHead, chainHeadHeight + 1, spendableOutputs.poll(), null);
- blocks.add(new BlockAndValidity(b1, true, false, b1.getHash(), chainHeadHeight + 1, "b1"));
- spendableOutputs.offer(b1.getCoinbaseOutput());
-
- TransactionOutPointWithValue out1 = spendableOutputs.poll(); checkState(out1 != null);
- NewBlock b2 = createNextBlock(b1, chainHeadHeight + 2, out1, null);
- blocks.add(new BlockAndValidity(b2, true, false, b2.getHash(), chainHeadHeight + 2, "b2"));
- // Make sure nothing funky happens if we try to re-add b2
- blocks.add(new BlockAndValidity(b2, true, false, b2.getHash(), chainHeadHeight + 2, "b2"));
- spendableOutputs.offer(b2.getCoinbaseOutput());
- // We now have the following chain (which output is spent is in parentheses):
- // genesis -> b1 (0) -> b2 (1)
- //
- // so fork like this:
- //
- // genesis -> b1 (0) -> b2 (1)
- // \-> b3 (1)
- //
- // Nothing should happen at this point. We saw b2 first so it takes priority.
- NewBlock b3 = createNextBlock(b1, chainHeadHeight + 2, out1, null);
- blocks.add(new BlockAndValidity(b3, true, false, b2.getHash(), chainHeadHeight + 2, "b3"));
- // Make sure nothing breaks if we add b3 twice
- blocks.add(new BlockAndValidity(b3, true, false, b2.getHash(), chainHeadHeight + 2, "b3"));
-
- // Do a simple UTXO query.
- UTXORule utxo1;
- {
- Transaction coinbase = b2.block.getTransactions().get(0);
- TransactionOutPoint outpoint = new TransactionOutPoint(params, 0, coinbase.getHash());
- long[] heights = new long[] {chainHeadHeight + 2};
- UTXOsMessage result = new UTXOsMessage(params, ImmutableList.of(coinbase.getOutput(0)), heights, b2.getHash(), chainHeadHeight + 2);
- utxo1 = new UTXORule("utxo1", outpoint, result);
- blocks.add(utxo1);
- }
-
- // Now we add another block to make the alternative chain longer.
- //
- // genesis -> b1 (0) -> b2 (1)
- // \-> b3 (1) -> b4 (2)
- //
- TransactionOutPointWithValue out2 = checkNotNull(spendableOutputs.poll());
- NewBlock b4 = createNextBlock(b3, chainHeadHeight + 3, out2, null);
- blocks.add(new BlockAndValidity(b4, true, false, b4.getHash(), chainHeadHeight + 3, "b4"));
-
- // Check that the old coinbase is no longer in the UTXO set and the new one is.
- {
- Transaction coinbase = b4.block.getTransactions().get(0);
- TransactionOutPoint outpoint = new TransactionOutPoint(params, 0, coinbase.getHash());
- List queries = ImmutableList.of(utxo1.query.get(0), outpoint);
- List results = Lists.asList(null, coinbase.getOutput(0), new TransactionOutput[]{});
- long[] heights = new long[] {chainHeadHeight + 3};
- UTXOsMessage result = new UTXOsMessage(params, results, heights, b4.getHash(), chainHeadHeight + 3);
- UTXORule utxo2 = new UTXORule("utxo2", queries, result);
- blocks.add(utxo2);
- }
-
- // ... and back to the first chain.
- NewBlock b5 = createNextBlock(b2, chainHeadHeight + 3, out2, null);
- blocks.add(new BlockAndValidity(b5, true, false, b4.getHash(), chainHeadHeight + 3, "b5"));
- spendableOutputs.offer(b5.getCoinbaseOutput());
-
- TransactionOutPointWithValue out3 = spendableOutputs.poll();
-
- NewBlock b6 = createNextBlock(b5, chainHeadHeight + 4, out3, null);
- blocks.add(new BlockAndValidity(b6, true, false, b6.getHash(), chainHeadHeight + 4, "b6"));
- //
- // genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
- // \-> b3 (1) -> b4 (2)
- //
-
- // Try to create a fork that double-spends
- // genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
- // \-> b7 (2) -> b8 (4)
- // \-> b3 (1) -> b4 (2)
- //
- NewBlock b7 = createNextBlock(b5, chainHeadHeight + 5, out2, null);
- blocks.add(new BlockAndValidity(b7, true, false, b6.getHash(), chainHeadHeight + 4, "b7"));
-
- TransactionOutPointWithValue out4 = spendableOutputs.poll();
-
- NewBlock b8 = createNextBlock(b7, chainHeadHeight + 6, out4, null);
- blocks.add(new BlockAndValidity(b8, false, true, b6.getHash(), chainHeadHeight + 4, "b8"));
-
- // Try to create a block that has too much fee
- // genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
- // \-> b9 (4)
- // \-> b3 (1) -> b4 (2)
- //
- NewBlock b9 = createNextBlock(b6, chainHeadHeight + 5, out4, SATOSHI);
- blocks.add(new BlockAndValidity(b9, false, true, b6.getHash(), chainHeadHeight + 4, "b9"));
-
- // Create a fork that ends in a block with too much fee (the one that causes the reorg)
- // genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
- // \-> b10 (3) -> b11 (4)
- // \-> b3 (1) -> b4 (2)
- //
- NewBlock b10 = createNextBlock(b5, chainHeadHeight + 4, out3, null);
- blocks.add(new BlockAndValidity(b10, true, false, b6.getHash(), chainHeadHeight + 4, "b10"));
-
- NewBlock b11 = createNextBlock(b10, chainHeadHeight + 5, out4, SATOSHI);
- blocks.add(new BlockAndValidity(b11, false, true, b6.getHash(), chainHeadHeight + 4, "b11"));
-
- // Try again, but with a valid fork first
- // genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
- // \-> b12 (3) -> b13 (4) -> b14 (5)
- // (b12 added last)
- // \-> b3 (1) -> b4 (2)
- //
- NewBlock b12 = createNextBlock(b5, chainHeadHeight + 4, out3, null);
- spendableOutputs.offer(b12.getCoinbaseOutput());
-
- NewBlock b13 = createNextBlock(b12, chainHeadHeight + 5, out4, null);
- blocks.add(new BlockAndValidity(b13, false, false, b6.getHash(), chainHeadHeight + 4, "b13"));
- // Make sure we dont die if an orphan gets added twice
- blocks.add(new BlockAndValidity(b13, false, false, b6.getHash(), chainHeadHeight + 4, "b13"));
- spendableOutputs.offer(b13.getCoinbaseOutput());
-
- TransactionOutPointWithValue out5 = spendableOutputs.poll();
-
- NewBlock b14 = createNextBlock(b13, chainHeadHeight + 6, out5, SATOSHI);
- // This will be "validly" added, though its actually invalid, it will just be marked orphan
- // and will be discarded when an attempt is made to reorg to it.
- // TODO: Use a WeakReference to check that it is freed properly after the reorg
- blocks.add(new BlockAndValidity(b14, false, false, b6.getHash(), chainHeadHeight + 4, "b14"));
- // Make sure we dont die if an orphan gets added twice
- blocks.add(new BlockAndValidity(b14, false, false, b6.getHash(), chainHeadHeight + 4, "b14"));
-
- blocks.add(new BlockAndValidity(b12, false, true, b13.getHash(), chainHeadHeight + 5, "b12"));
-
- // Add a block with MAX_BLOCK_SIGOPS and one with one more sigop
- // genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
- // \-> b12 (3) -> b13 (4) -> b15 (5) -> b16 (6)
- // \-> b3 (1) -> b4 (2)
- //
- NewBlock b15 = createNextBlock(b13, chainHeadHeight + 6, out5, null);
- {
- int sigOps = 0;
- for (Transaction tx : b15.block.getTransactions())
- sigOps += tx.getSigOpCount();
- Transaction tx = new Transaction(params);
- byte[] outputScript = new byte[Block.MAX_BLOCK_SIGOPS - sigOps];
- Arrays.fill(outputScript, (byte) OP_CHECKSIG);
- tx.addOutput(new TransactionOutput(params, tx, SATOSHI, outputScript));
- addOnlyInputToTransaction(tx, b15);
- b15.addTransaction(tx);
-
- sigOps = 0;
- for (Transaction tx2 : b15.block.getTransactions())
- sigOps += tx2.getSigOpCount();
- checkState(sigOps == Block.MAX_BLOCK_SIGOPS);
- }
- b15.solve();
-
- blocks.add(new BlockAndValidity(b15, true, false, b15.getHash(), chainHeadHeight + 6, "b15"));
- spendableOutputs.offer(b15.getCoinbaseOutput());
-
- TransactionOutPointWithValue out6 = spendableOutputs.poll();
-
- NewBlock b16 = createNextBlock(b15, chainHeadHeight + 7, out6, null);
- {
- int sigOps = 0;
- for (Transaction tx : b16.block.getTransactions()) {
- sigOps += tx.getSigOpCount();
- }
- Transaction tx = new Transaction(params);
- byte[] outputScript = new byte[Block.MAX_BLOCK_SIGOPS - sigOps + 1];
- Arrays.fill(outputScript, (byte) OP_CHECKSIG);
- tx.addOutput(new TransactionOutput(params, tx, SATOSHI, outputScript));
- addOnlyInputToTransaction(tx, b16);
- b16.addTransaction(tx);
-
- sigOps = 0;
- for (Transaction tx2 : b16.block.getTransactions())
- sigOps += tx2.getSigOpCount();
- checkState(sigOps == Block.MAX_BLOCK_SIGOPS + 1);
- }
- b16.solve();
-
- blocks.add(new BlockAndValidity(b16, false, true, b15.getHash(), chainHeadHeight + 6, "b16"));
-
- // Attempt to spend a transaction created on a different fork
- // genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
- // \-> b12 (3) -> b13 (4) -> b15 (5) -> b17 (6)
- // \-> b3 (1) -> b4 (2)
- //
- NewBlock b17 = createNextBlock(b15, chainHeadHeight + 7, out6, null);
- {
- Transaction tx = new Transaction(params);
- tx.addOutput(new TransactionOutput(params, tx, SATOSHI, new byte[] {}));
- addOnlyInputToTransaction(tx, b3);
- b17.addTransaction(tx);
- }
- b17.solve();
- blocks.add(new BlockAndValidity(b17, false, true, b15.getHash(), chainHeadHeight + 6, "b17"));
-
- // Attempt to spend a transaction created on a different fork (on a fork this time)
- // genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
- // \-> b12 (3) -> b13 (4) -> b15 (5)
- // \-> b18 (5) -> b19 (6)
- // \-> b3 (1) -> b4 (2)
- //
- NewBlock b18 = createNextBlock(b13, chainHeadHeight + 6, out5, null);
- {
- Transaction tx = new Transaction(params);
- tx.addOutput(new TransactionOutput(params, tx, SATOSHI, new byte[] {}));
- addOnlyInputToTransaction(tx, b3);
- b18.addTransaction(tx);
- }
- b18.solve();
- blocks.add(new BlockAndValidity(b18, true, false, b15.getHash(), chainHeadHeight + 6, "b17"));
-
- NewBlock b19 = createNextBlock(b18, chainHeadHeight + 7, out6, null);
- blocks.add(new BlockAndValidity(b19, false, true, b15.getHash(), chainHeadHeight + 6, "b19"));
-
- // Attempt to spend a coinbase at depth too low
- // genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
- // \-> b12 (3) -> b13 (4) -> b15 (5) -> b20 (7)
- // \-> b3 (1) -> b4 (2)
- //
- TransactionOutPointWithValue out7 = spendableOutputs.poll();
-
- NewBlock b20 = createNextBlock(b15.block, chainHeadHeight + 7, out7, null);
- blocks.add(new BlockAndValidity(b20, false, true, b15.getHash(), chainHeadHeight + 6, "b20"));
-
- // Attempt to spend a coinbase at depth too low (on a fork this time)
- // genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
- // \-> b12 (3) -> b13 (4) -> b15 (5)
- // \-> b21 (6) -> b22 (5)
- // \-> b3 (1) -> b4 (2)
- //
- NewBlock b21 = createNextBlock(b13, chainHeadHeight + 6, out6, null);
- blocks.add(new BlockAndValidity(b21.block, true, false, b15.getHash(), chainHeadHeight + 6, "b21"));
- NewBlock b22 = createNextBlock(b21, chainHeadHeight + 7, out5, null);
- blocks.add(new BlockAndValidity(b22.block, false, true, b15.getHash(), chainHeadHeight + 6, "b22"));
-
- // Create a block on either side of MAX_BLOCK_SIZE and make sure its accepted/rejected
- // genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
- // \-> b12 (3) -> b13 (4) -> b15 (5) -> b23 (6)
- // \-> b24 (6) -> b25 (7)
- // \-> b3 (1) -> b4 (2)
- //
- NewBlock b23 = createNextBlock(b15, chainHeadHeight + 7, out6, null);
- {
- Transaction tx = new Transaction(params);
- byte[] outputScript = new byte[Block.MAX_BLOCK_SIZE - b23.block.getMessageSize() - 65];
- Arrays.fill(outputScript, (byte) OP_FALSE);
- tx.addOutput(new TransactionOutput(params, tx, ZERO, outputScript));
- addOnlyInputToTransaction(tx, b23);
- b23.addTransaction(tx);
- }
- b23.solve();
- checkState(b23.block.getMessageSize() == Block.MAX_BLOCK_SIZE);
- blocks.add(new BlockAndValidity(b23, true, false, b23.getHash(), chainHeadHeight + 7, "b23"));
- spendableOutputs.offer(b23.getCoinbaseOutput());
-
- NewBlock b24 = createNextBlock(b15, chainHeadHeight + 7, out6, null);
- {
- Transaction tx = new Transaction(params);
- byte[] outputScript = new byte[Block.MAX_BLOCK_SIZE - b24.block.getMessageSize() - 64];
- Arrays.fill(outputScript, (byte) OP_FALSE);
- tx.addOutput(new TransactionOutput(params, tx, ZERO, outputScript));
- addOnlyInputToTransaction(tx, b24);
- b24.addTransaction(tx);
- }
- b24.solve();
- checkState(b24.block.getMessageSize() == Block.MAX_BLOCK_SIZE + 1);
- blocks.add(new BlockAndValidity(b24, false, true, b23.getHash(), chainHeadHeight + 7, "b24"));
-
- // Extend the b24 chain to make sure bitcoind isn't accepting b24
- NewBlock b25 = createNextBlock(b24, chainHeadHeight + 8, out7, null);
- blocks.add(new BlockAndValidity(b25, false, false, b23.getHash(), chainHeadHeight + 7, "b25"));
-
- // Create blocks with a coinbase input script size out of range
- // genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
- // \-> b12 (3) -> b13 (4) -> b15 (5) -> b23 (6) -> b30 (7)
- // \-> ... (6) -> ... (7)
- // \-> b3 (1) -> b4 (2)
- //
- NewBlock b26 = createNextBlock(b15, chainHeadHeight + 7, out6, null);
- // 1 is too small, but we already generate every other block with 2, so that is tested
- b26.block.getTransactions().get(0).getInputs().get(0).setScriptBytes(new byte[] {0});
- b26.block.setMerkleRoot(null);
- b26.solve();
- blocks.add(new BlockAndValidity(b26, false, true, b23.getHash(), chainHeadHeight + 7, "b26"));
-
- // Extend the b26 chain to make sure bitcoind isn't accepting b26
- NewBlock b27 = createNextBlock(b26, chainHeadHeight + 8, out7, null);
- blocks.add(new BlockAndValidity(b27, false, false, b23.getHash(), chainHeadHeight + 7, "b27"));
-
- NewBlock b28 = createNextBlock(b15, chainHeadHeight + 7, out6, null);
- {
- byte[] coinbase = new byte[101];
- Arrays.fill(coinbase, (byte)0);
- b28.block.getTransactions().get(0).getInputs().get(0).setScriptBytes(coinbase);
- }
- b28.block.setMerkleRoot(null);
- b28.solve();
- blocks.add(new BlockAndValidity(b28, false, true, b23.getHash(), chainHeadHeight + 7, "b28"));
-
- // Extend the b28 chain to make sure bitcoind isn't accepting b28
- NewBlock b29 = createNextBlock(b28, chainHeadHeight + 8, out7, null);
- blocks.add(new BlockAndValidity(b29, false, false, b23.getHash(), chainHeadHeight + 7, "b29"));
-
- NewBlock b30 = createNextBlock(b23, chainHeadHeight + 8, out7, null);
- {
- byte[] coinbase = new byte[100];
- Arrays.fill(coinbase, (byte)0);
- b30.block.getTransactions().get(0).getInputs().get(0).setScriptBytes(coinbase);
- }
- b30.block.setMerkleRoot(null);
- b30.solve();
- blocks.add(new BlockAndValidity(b30, true, false, b30.getHash(), chainHeadHeight + 8, "b30"));
- spendableOutputs.offer(b30.getCoinbaseOutput());
-
- // Check sigops of OP_CHECKMULTISIG/OP_CHECKMULTISIGVERIFY/OP_CHECKSIGVERIFY
- // 6 (3)
- // 12 (3) -> b13 (4) -> b15 (5) -> b23 (6) -> b30 (7) -> b31 (8) -> b33 (9) -> b35 (10)
- // \-> b36 (11)
- // \-> b34 (10)
- // \-> b32 (9)
- //
- TransactionOutPointWithValue out8 = spendableOutputs.poll();
-
- NewBlock b31 = createNextBlock(b30, chainHeadHeight + 9, out8, null);
- {
- int sigOps = 0;
- for (Transaction tx : b31.block.transactions) {
- sigOps += tx.getSigOpCount();
- }
- Transaction tx = new Transaction(params);
- byte[] outputScript = new byte[(Block.MAX_BLOCK_SIGOPS - sigOps)/20];
- Arrays.fill(outputScript, (byte) OP_CHECKMULTISIG);
- tx.addOutput(new TransactionOutput(params, tx, SATOSHI, outputScript));
- addOnlyInputToTransaction(tx, b31);
- b31.addTransaction(tx);
- }
- b31.solve();
-
- blocks.add(new BlockAndValidity(b31, true, false, b31.getHash(), chainHeadHeight + 9, "b31"));
- spendableOutputs.offer(b31.getCoinbaseOutput());
-
- TransactionOutPointWithValue out9 = spendableOutputs.poll();
-
- NewBlock b32 = createNextBlock(b31, chainHeadHeight + 10, out9, null);
- {
- int sigOps = 0;
- for (Transaction tx : b32.block.transactions) {
- sigOps += tx.getSigOpCount();
- }
- Transaction tx = new Transaction(params);
- byte[] outputScript = new byte[(Block.MAX_BLOCK_SIGOPS - sigOps)/20 + (Block.MAX_BLOCK_SIGOPS - sigOps)%20 + 1];
- Arrays.fill(outputScript, (byte) OP_CHECKMULTISIG);
- for (int i = 0; i < (Block.MAX_BLOCK_SIGOPS - sigOps)%20; i++)
- outputScript[i] = (byte) OP_CHECKSIG;
- tx.addOutput(new TransactionOutput(params, tx, SATOSHI, outputScript));
- addOnlyInputToTransaction(tx, b32);
- b32.addTransaction(tx);
- }
- b32.solve();
- blocks.add(new BlockAndValidity(b32, false, true, b31.getHash(), chainHeadHeight + 9, "b32"));
-
- NewBlock b33 = createNextBlock(b31, chainHeadHeight + 10, out9, null);
- {
- int sigOps = 0;
- for (Transaction tx : b33.block.transactions) {
- sigOps += tx.getSigOpCount();
- }
- Transaction tx = new Transaction(params);
- byte[] outputScript = new byte[(Block.MAX_BLOCK_SIGOPS - sigOps)/20];
- Arrays.fill(outputScript, (byte) OP_CHECKMULTISIGVERIFY);
- tx.addOutput(new TransactionOutput(params, tx, SATOSHI, outputScript));
- addOnlyInputToTransaction(tx, b33);
- b33.addTransaction(tx);
- }
- b33.solve();
-
- blocks.add(new BlockAndValidity(b33, true, false, b33.getHash(), chainHeadHeight + 10, "b33"));
- spendableOutputs.offer(b33.getCoinbaseOutput());
-
- TransactionOutPointWithValue out10 = spendableOutputs.poll();
-
- NewBlock b34 = createNextBlock(b33, chainHeadHeight + 11, out10, null);
- {
- int sigOps = 0;
- for (Transaction tx : b34.block.getTransactions()) {
- sigOps += tx.getSigOpCount();
- }
- Transaction tx = new Transaction(params);
- byte[] outputScript = new byte[(Block.MAX_BLOCK_SIGOPS - sigOps)/20 + (Block.MAX_BLOCK_SIGOPS - sigOps)%20 + 1];
- Arrays.fill(outputScript, (byte) OP_CHECKMULTISIGVERIFY);
- for (int i = 0; i < (Block.MAX_BLOCK_SIGOPS - sigOps)%20; i++)
- outputScript[i] = (byte) OP_CHECKSIG;
- tx.addOutput(new TransactionOutput(params, tx, SATOSHI, outputScript));
- addOnlyInputToTransaction(tx, b34);
- b34.addTransaction(tx);
- }
- b34.solve();
- blocks.add(new BlockAndValidity(b34, false, true, b33.getHash(), chainHeadHeight + 10, "b34"));
-
- NewBlock b35 = createNextBlock(b33, chainHeadHeight + 11, out10, null);
- {
- int sigOps = 0;
- for (Transaction tx : b35.block.getTransactions()) {
- sigOps += tx.getSigOpCount();
- }
- Transaction tx = new Transaction(params);
- byte[] outputScript = new byte[Block.MAX_BLOCK_SIGOPS - sigOps];
- Arrays.fill(outputScript, (byte) OP_CHECKSIGVERIFY);
- tx.addOutput(new TransactionOutput(params, tx, SATOSHI, outputScript));
- addOnlyInputToTransaction(tx, b35);
- b35.addTransaction(tx);
- }
- b35.solve();
-
- blocks.add(new BlockAndValidity(b35, true, false, b35.getHash(), chainHeadHeight + 11, "b35"));
- spendableOutputs.offer(b35.getCoinbaseOutput());
-
- TransactionOutPointWithValue out11 = spendableOutputs.poll();
-
- NewBlock b36 = createNextBlock(b35, chainHeadHeight + 12, out11, null);
- {
- int sigOps = 0;
- for (Transaction tx : b36.block.getTransactions()) {
- sigOps += tx.getSigOpCount();
- }
- Transaction tx = new Transaction(params);
- byte[] outputScript = new byte[Block.MAX_BLOCK_SIGOPS - sigOps + 1];
- Arrays.fill(outputScript, (byte) OP_CHECKSIGVERIFY);
- tx.addOutput(new TransactionOutput(params, tx, SATOSHI, outputScript));
- addOnlyInputToTransaction(tx, b36);
- b36.addTransaction(tx);
- }
- b36.solve();
-
- blocks.add(new BlockAndValidity(b36, false, true, b35.getHash(), chainHeadHeight + 11, "b36"));
-
- // Check spending of a transaction in a block which failed to connect
- // (test block store transaction abort handling, not that it should get this far if that's broken...)
- // 6 (3)
- // 12 (3) -> b13 (4) -> b15 (5) -> b23 (6) -> b30 (7) -> b31 (8) -> b33 (9) -> b35 (10)
- // \-> b37 (11)
- // \-> b38 (11)
- //
- NewBlock b37 = createNextBlock(b35, chainHeadHeight + 12, out11, null);
- {
- Transaction tx = new Transaction(params);
- tx.addOutput(new TransactionOutput(params, tx, SATOSHI, new byte[] {}));
- addOnlyInputToTransaction(tx, out11); // double spend out11
- b37.addTransaction(tx);
- }
- b37.solve();
- blocks.add(new BlockAndValidity(b37, false, true, b35.getHash(), chainHeadHeight + 11, "b37"));
-
- NewBlock b38 = createNextBlock(b35, chainHeadHeight + 12, out11, null);
- {
- Transaction tx = new Transaction(params);
- tx.addOutput(new TransactionOutput(params, tx, SATOSHI, new byte[] {}));
- // Attempt to spend b37's first non-coinbase tx, at which point b37 was still considered valid
- addOnlyInputToTransaction(tx, b37);
- b38.addTransaction(tx);
- }
- b38.solve();
- blocks.add(new BlockAndValidity(b38, false, true, b35.getHash(), chainHeadHeight + 11, "b38"));
-
- // Check P2SH SigOp counting
- // 13 (4) -> b15 (5) -> b23 (6) -> b30 (7) -> b31 (8) -> b33 (9) -> b35 (10) -> b39 (11) -> b41 (12)
- // \-> b40 (12)
- //
- // Create some P2SH outputs that will require 6 sigops to spend
- byte[] b39p2shScriptPubKey;
- int b39numP2SHOutputs = 0, b39sigOpsPerOutput = 6;
- NewBlock b39 = createNextBlock(b35, chainHeadHeight + 12, null, null);
- {
- ByteArrayOutputStream p2shScriptPubKey = new UnsafeByteArrayOutputStream();
- try {
- Script.writeBytes(p2shScriptPubKey, coinbaseOutKeyPubKey);
- p2shScriptPubKey.write(OP_2DUP);
- p2shScriptPubKey.write(OP_CHECKSIGVERIFY);
- p2shScriptPubKey.write(OP_2DUP);
- p2shScriptPubKey.write(OP_CHECKSIGVERIFY);
- p2shScriptPubKey.write(OP_2DUP);
- p2shScriptPubKey.write(OP_CHECKSIGVERIFY);
- p2shScriptPubKey.write(OP_2DUP);
- p2shScriptPubKey.write(OP_CHECKSIGVERIFY);
- p2shScriptPubKey.write(OP_2DUP);
- p2shScriptPubKey.write(OP_CHECKSIGVERIFY);
- p2shScriptPubKey.write(OP_CHECKSIG);
- } catch (IOException e) {
- throw new RuntimeException(e); // Cannot happen.
- }
- b39p2shScriptPubKey = p2shScriptPubKey.toByteArray();
-
- byte[] scriptHash = Utils.sha256hash160(b39p2shScriptPubKey);
- UnsafeByteArrayOutputStream scriptPubKey = new UnsafeByteArrayOutputStream(scriptHash.length + 3);
- scriptPubKey.write(OP_HASH160);
- try {
- Script.writeBytes(scriptPubKey, scriptHash);
- } catch (IOException e) {
- throw new RuntimeException(e); // Cannot happen.
- }
- scriptPubKey.write(OP_EQUAL);
-
- Coin lastOutputValue = out11.value.subtract(SATOSHI);
- TransactionOutPoint lastOutPoint;
- {
- Transaction tx = new Transaction(params);
- tx.addOutput(new TransactionOutput(params, tx, SATOSHI, scriptPubKey.toByteArray()));
- tx.addOutput(new TransactionOutput(params, tx, lastOutputValue, new byte[]{OP_1}));
- addOnlyInputToTransaction(tx, out11);
- lastOutPoint = new TransactionOutPoint(params, 1, tx.getHash());
- b39.addTransaction(tx);
- }
- b39numP2SHOutputs++;
-
- while (b39.block.getMessageSize() < Block.MAX_BLOCK_SIZE)
- {
- Transaction tx = new Transaction(params);
-
- lastOutputValue = lastOutputValue.subtract(SATOSHI);
- tx.addOutput(new TransactionOutput(params, tx, SATOSHI, scriptPubKey.toByteArray()));
- tx.addOutput(new TransactionOutput(params, tx, lastOutputValue, new byte[]{OP_1}));
- tx.addInput(new TransactionInput(params, tx, new byte[]{OP_1}, lastOutPoint));
- lastOutPoint = new TransactionOutPoint(params, 1, tx.getHash());
-
- if (b39.block.getMessageSize() + tx.getMessageSize() < Block.MAX_BLOCK_SIZE) {
- b39.addTransaction(tx);
- b39numP2SHOutputs++;
- } else
- break;
- }
- }
- b39.solve();
- blocks.add(new BlockAndValidity(b39, true, false, b39.getHash(), chainHeadHeight + 12, "b39"));
- spendableOutputs.offer(b39.getCoinbaseOutput());
-
- TransactionOutPointWithValue out12 = spendableOutputs.poll();
-
- NewBlock b40 = createNextBlock(b39, chainHeadHeight + 13, out12, null);
- {
- int sigOps = 0;
- for (Transaction tx : b40.block.getTransactions()) {
- sigOps += tx.getSigOpCount();
- }
-
- int numTxes = (Block.MAX_BLOCK_SIGOPS - sigOps) / b39sigOpsPerOutput;
- checkState(numTxes <= b39numP2SHOutputs);
-
- TransactionOutPoint lastOutPoint = new TransactionOutPoint(params, 1, b40.block.getTransactions().get(1).getHash());
-
- byte[] scriptSig = null;
- for (int i = 1; i <= numTxes; i++) {
- Transaction tx = new Transaction(params);
- tx.addOutput(new TransactionOutput(params, tx, SATOSHI, new byte[] {OP_1}));
- tx.addInput(new TransactionInput(params, tx, new byte[]{OP_1}, lastOutPoint));
-
- TransactionInput input = new TransactionInput(params, tx, new byte[]{},
- new TransactionOutPoint(params, 0, b39.block.getTransactions().get(i).getHash()));
- tx.addInput(input);
-
- if (scriptSig == null) {
- // Exploit the SigHash.SINGLE bug to avoid having to make more than one signature
- Sha256Hash hash = tx.hashForSignature(1, b39p2shScriptPubKey, SigHash.SINGLE, false);
-
- // Sign input
- try {
- ByteArrayOutputStream bos = new UnsafeByteArrayOutputStream(73);
- bos.write(coinbaseOutKey.sign(hash).encodeToDER());
- bos.write(SigHash.SINGLE.ordinal() + 1);
- byte[] signature = bos.toByteArray();
-
- ByteArrayOutputStream scriptSigBos = new UnsafeByteArrayOutputStream(signature.length + b39p2shScriptPubKey.length + 3);
- Script.writeBytes(scriptSigBos, new byte[] {(byte) OP_CHECKSIG});
- scriptSigBos.write(Script.createInputScript(signature));
- Script.writeBytes(scriptSigBos, b39p2shScriptPubKey);
-
- scriptSig = scriptSigBos.toByteArray();
- } catch (IOException e) {
- throw new RuntimeException(e); // Cannot happen.
- }
- }
-
- input.setScriptBytes(scriptSig);
-
- lastOutPoint = new TransactionOutPoint(params, 0, tx.getHash());
-
- b40.addTransaction(tx);
- }
-
- sigOps += numTxes * b39sigOpsPerOutput;
- Transaction tx = new Transaction(params);
- tx.addInput(new TransactionInput(params, tx, new byte[]{OP_1}, lastOutPoint));
- byte[] scriptPubKey = new byte[Block.MAX_BLOCK_SIGOPS - sigOps + 1];
- Arrays.fill(scriptPubKey, (byte) OP_CHECKSIG);
- tx.addOutput(new TransactionOutput(params, tx, ZERO, scriptPubKey));
- b40.addTransaction(tx);
- }
- b40.solve();
- blocks.add(new BlockAndValidity(b40, false, true, b39.getHash(), chainHeadHeight + 12, "b40"));
-
- NewBlock b41 = null;
- if (runBarelyExpensiveTests) {
- b41 = createNextBlock(b39, chainHeadHeight + 13, out12, null);
- {
- int sigOps = 0;
- for (Transaction tx : b41.block.getTransactions()) {
- sigOps += tx.getSigOpCount();
- }
-
- int numTxes = (Block.MAX_BLOCK_SIGOPS - sigOps)
- / b39sigOpsPerOutput;
- checkState(numTxes <= b39numP2SHOutputs);
-
- TransactionOutPoint lastOutPoint = new TransactionOutPoint(
- params, 1, b41.block.getTransactions().get(1).getHash());
-
- byte[] scriptSig = null;
- for (int i = 1; i <= numTxes; i++) {
- Transaction tx = new Transaction(params);
- tx.addOutput(new TransactionOutput(params, tx, Coin
- .SATOSHI, new byte[] {OP_1}));
- tx.addInput(new TransactionInput(params, tx,
- new byte[] {OP_1}, lastOutPoint));
-
- TransactionInput input = new TransactionInput(params, tx,
- new byte[] {}, new TransactionOutPoint(params, 0,
- b39.block.getTransactions().get(i).getHash()));
- tx.addInput(input);
-
- if (scriptSig == null) {
- // Exploit the SigHash.SINGLE bug to avoid having to make more than one signature
- Sha256Hash hash = tx.hashForSignature(1,
- b39p2shScriptPubKey, SigHash.SINGLE, false);
-
- // Sign input
- try {
- ByteArrayOutputStream bos = new UnsafeByteArrayOutputStream(
- 73);
- bos.write(coinbaseOutKey.sign(hash).encodeToDER());
- bos.write(SigHash.SINGLE.ordinal() + 1);
- byte[] signature = bos.toByteArray();
-
- ByteArrayOutputStream scriptSigBos = new UnsafeByteArrayOutputStream(
- signature.length
- + b39p2shScriptPubKey.length + 3);
- Script.writeBytes(scriptSigBos,
- new byte[] { (byte) OP_CHECKSIG});
- scriptSigBos.write(Script
- .createInputScript(signature));
- Script.writeBytes(scriptSigBos, b39p2shScriptPubKey);
-
- scriptSig = scriptSigBos.toByteArray();
- } catch (IOException e) {
- throw new RuntimeException(e); // Cannot happen.
- }
- }
-
- input.setScriptBytes(scriptSig);
-
- lastOutPoint = new TransactionOutPoint(params, 0,
- tx.getHash());
-
- b41.addTransaction(tx);
- }
-
- sigOps += numTxes * b39sigOpsPerOutput;
- Transaction tx = new Transaction(params);
- tx.addInput(new TransactionInput(params, tx,
- new byte[] {OP_1}, lastOutPoint));
- byte[] scriptPubKey = new byte[Block.MAX_BLOCK_SIGOPS - sigOps];
- Arrays.fill(scriptPubKey, (byte) OP_CHECKSIG);
- tx.addOutput(new TransactionOutput(params, tx, ZERO, scriptPubKey));
- b41.addTransaction(tx);
- }
- b41.solve();
- blocks.add(new BlockAndValidity(b41, true, false, b41.getHash(), chainHeadHeight + 13, "b41"));
- }
-
- // Fork off of b39 to create a constant base again
- // b23 (6) -> b30 (7) -> b31 (8) -> b33 (9) -> b35 (10) -> b39 (11) -> b42 (12) -> b43 (13)
- // \-> b41 (12)
- //
- NewBlock b42 = createNextBlock(b39, chainHeadHeight + 13, out12, null);
- blocks.add(new BlockAndValidity(b42, true, false, b41 == null ? b42.getHash() : b41.getHash(), chainHeadHeight + 13, "b42"));
- spendableOutputs.offer(b42.getCoinbaseOutput());
-
- TransactionOutPointWithValue out13 = spendableOutputs.poll();
-
- NewBlock b43 = createNextBlock(b42, chainHeadHeight + 14, out13, null);
- blocks.add(new BlockAndValidity(b43, true, false, b43.getHash(), chainHeadHeight + 14, "b43"));
- spendableOutputs.offer(b43.getCoinbaseOutput());
-
- // Test a number of really invalid scenarios
- // -> b31 (8) -> b33 (9) -> b35 (10) -> b39 (11) -> b42 (12) -> b43 (13) -> b44 (14)
- // \-> ??? (15)
- //
- TransactionOutPointWithValue out14 = spendableOutputs.poll();
-
- // A valid block created exactly like b44 to make sure the creation itself works
- Block b44 = new Block(params);
- byte[] outScriptBytes = ScriptBuilder.createOutputScript(ECKey.fromPublicOnly(coinbaseOutKeyPubKey)).getProgram();
- {
- b44.setDifficultyTarget(b43.block.getDifficultyTarget());
- b44.addCoinbaseTransaction(coinbaseOutKeyPubKey, ZERO);
-
- Transaction t = new Transaction(params);
- // Entirely invalid scriptPubKey to ensure we aren't pre-verifying too much
- t.addOutput(new TransactionOutput(params, t, ZERO, new byte[] {OP_PUSHDATA1 - 1 }));
- t.addOutput(new TransactionOutput(params, t, SATOSHI, outScriptBytes));
- // Spendable output
- t.addOutput(new TransactionOutput(params, t, ZERO, new byte[] {OP_1}));
- addOnlyInputToTransaction(t, out14);
- b44.addTransaction(t);
-
- b44.setPrevBlockHash(b43.getHash());
- b44.setTime(b43.block.getTimeSeconds() + 1);
- }
- b44.solve();
- blocks.add(new BlockAndValidity(b44, true, false, b44.getHash(), chainHeadHeight + 15, "b44"));
-
- TransactionOutPointWithValue out15 = spendableOutputs.poll();
-
- // A block with a non-coinbase as the first tx
- Block b45 = new Block(params);
- {
- b45.setDifficultyTarget(b44.getDifficultyTarget());
- //b45.addCoinbaseTransaction(pubKey, coinbaseValue);
-
- Transaction t = new Transaction(params);
- // Entirely invalid scriptPubKey to ensure we aren't pre-verifying too much
- t.addOutput(new TransactionOutput(params, t, ZERO, new byte[] {OP_PUSHDATA1 - 1 }));
- t.addOutput(new TransactionOutput(params, t, SATOSHI, outScriptBytes));
- // Spendable output
- t.addOutput(new TransactionOutput(params, t, ZERO, new byte[] {OP_1}));
- addOnlyInputToTransaction(t, out15);
- try {
- b45.addTransaction(t);
- } catch (RuntimeException e) { } // Should happen
- if (b45.getTransactions().size() > 0)
- throw new RuntimeException("addTransaction doesn't properly check for adding a non-coinbase as first tx");
- b45.addTransaction(t, false);
-
- b45.setPrevBlockHash(b44.getHash());
- b45.setTime(b44.getTimeSeconds() + 1);
- }
- b45.solve();
- blocks.add(new BlockAndValidity(b45, false, true, b44.getHash(), chainHeadHeight + 15, "b45"));
-
- // A block with no txn
- Block b46 = new Block(params);
- {
- b46.transactions = new ArrayList();
- b46.setDifficultyTarget(b44.getDifficultyTarget());
- b46.setMerkleRoot(Sha256Hash.ZERO_HASH);
-
- b46.setPrevBlockHash(b44.getHash());
- b46.setTime(b44.getTimeSeconds() + 1);
- }
- b46.solve();
- blocks.add(new BlockAndValidity(b46, false, true, b44.getHash(), chainHeadHeight + 15, "b46"));
-
- // A block with invalid work
- NewBlock b47 = createNextBlock(b44, chainHeadHeight + 16, out15, null);
- {
- try {
- // Inverse solve
- BigInteger target = b47.block.getDifficultyTargetAsInteger();
- while (true) {
- BigInteger h = b47.getHash().toBigInteger();
- if (h.compareTo(target) > 0) // if invalid
- break;
- // increment the nonce and try again.
- b47.block.setNonce(b47.block.getNonce() + 1);
- }
- } catch (VerificationException e) {
- throw new RuntimeException(e); // Cannot happen.
- }
- }
- blocks.add(new BlockAndValidity(b47, false, true, b44.getHash(), chainHeadHeight + 15, "b47"));
-
- // Block with timestamp > 2h in the future
- NewBlock b48 = createNextBlock(b44, chainHeadHeight + 16, out15, null);
- b48.block.setTime(Utils.currentTimeSeconds() + 60 * 60 * 3);
- b48.solve();
- blocks.add(new BlockAndValidity(b48, false, true, b44.getHash(), chainHeadHeight + 15, "b48"));
-
- // Block with invalid merkle hash
- NewBlock b49 = createNextBlock(b44, chainHeadHeight + 16, out15, null);
- byte[] b49MerkleHash = Sha256Hash.ZERO_HASH.getBytes().clone();
- b49MerkleHash[1] = (byte) 0xDE;
- b49.block.setMerkleRoot(Sha256Hash.create(b49MerkleHash));
- b49.solve();
- blocks.add(new BlockAndValidity(b49, false, true, b44.getHash(), chainHeadHeight + 15, "b49"));
-
- // Block with incorrect POW limit
- NewBlock b50 = createNextBlock(b44, chainHeadHeight + 16, out15, null);
- {
- long diffTarget = b44.getDifficultyTarget();
- diffTarget &= 0xFFBFFFFF; // Make difficulty one bit harder
- b50.block.setDifficultyTarget(diffTarget);
- }
- b50.solve();
- blocks.add(new BlockAndValidity(b50, false, true, b44.getHash(), chainHeadHeight + 15, "b50"));
-
- // A block with two coinbase txn
- NewBlock b51 = createNextBlock(b44, chainHeadHeight + 16, out15, null);
- {
- Transaction coinbase = new Transaction(params);
- coinbase.addInput(new TransactionInput(params, coinbase, new byte[]{(byte) 0xff, 110, 1}));
- coinbase.addOutput(new TransactionOutput(params, coinbase, SATOSHI, outScriptBytes));
- b51.block.addTransaction(coinbase, false);
- }
- b51.solve();
- blocks.add(new BlockAndValidity(b51, false, true, b44.getHash(), chainHeadHeight + 15, "b51"));
-
- // A block with duplicate txn
- NewBlock b52 = createNextBlock(b44, chainHeadHeight + 16, out15, null);
- {
- Transaction tx = new Transaction(params);
- tx.addOutput(new TransactionOutput(params, tx, SATOSHI, new byte[] {}));
- addOnlyInputToTransaction(tx, b52);
- b52.addTransaction(tx);
- b52.addTransaction(tx);
- }
- b52.solve();
- blocks.add(new BlockAndValidity(b52, false, true, b44.getHash(), chainHeadHeight + 15, "b52"));
-
- // Test block timestamp
- // -> b31 (8) -> b33 (9) -> b35 (10) -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15)
- // \-> b54 (15)
- // \-> b44 (14)
- //
- NewBlock b53 = createNextBlock(b43, chainHeadHeight + 15, out14, null);
- blocks.add(new BlockAndValidity(b53, true, false, b44.getHash(), chainHeadHeight + 15, "b53"));
- spendableOutputs.offer(b53.getCoinbaseOutput());
-
- // Block with invalid timestamp
- NewBlock b54 = createNextBlock(b53, chainHeadHeight + 16, out15, null);
- b54.block.setTime(b35.block.getTimeSeconds() - 1);
- b54.solve();
- blocks.add(new BlockAndValidity(b54, false, true, b44.getHash(), chainHeadHeight + 15, "b54"));
-
- // Block with valid timestamp
- NewBlock b55 = createNextBlock(b53, chainHeadHeight + 16, out15, null);
- b55.block.setTime(b35.block.getTimeSeconds());
- b55.solve();
- blocks.add(new BlockAndValidity(b55, true, false, b55.getHash(), chainHeadHeight + 16, "b55"));
- spendableOutputs.offer(b55.getCoinbaseOutput());
-
- // Test CVE-2012-2459
- // -> b33 (9) -> b35 (10) -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16)
- // \-> b56 (16)
- //
- TransactionOutPointWithValue out16 = spendableOutputs.poll();
-
- NewBlock b57 = createNextBlock(b55, chainHeadHeight + 17, out16, null);
- Transaction b56txToDuplicate;
- {
- b56txToDuplicate = new Transaction(params);
- b56txToDuplicate.addOutput(new TransactionOutput(params, b56txToDuplicate, SATOSHI, new byte[] {}));
- addOnlyInputToTransaction(b56txToDuplicate, b57);
- b57.addTransaction(b56txToDuplicate);
- }
- b57.solve();
-
- Block b56;
- try {
- b56 = new Block(params, b57.block.bitcoinSerialize());
- } catch (ProtocolException e) {
- throw new RuntimeException(e); // Cannot happen.
- }
- b56.addTransaction(b56txToDuplicate);
- checkState(b56.getHash().equals(b57.getHash()));
- blocks.add(new BlockAndValidity(b56, false, true, b55.getHash(), chainHeadHeight + 16, "b56"));
-
- NewBlock b57p2 = createNextBlock(b55, chainHeadHeight + 17, out16, null);
- Transaction b56p2txToDuplicate1, b56p2txToDuplicate2;
- {
- Transaction tx1 = new Transaction(params);
- tx1.addOutput(new TransactionOutput(params, tx1, SATOSHI, new byte[] {OP_TRUE}));
- addOnlyInputToTransaction(tx1, b57p2);
- b57p2.addTransaction(tx1);
-
- Transaction tx2 = new Transaction(params);
- tx2.addOutput(new TransactionOutput(params, tx2, SATOSHI, new byte[] {OP_TRUE}));
- addOnlyInputToTransaction(tx2, new TransactionOutPointWithValue(
- new TransactionOutPoint(params, 0, tx1.getHash()),
- SATOSHI, tx1.getOutputs().get(0).getScriptPubKey()));
- b57p2.addTransaction(tx2);
-
- b56p2txToDuplicate1 = new Transaction(params);
- b56p2txToDuplicate1.addOutput(new TransactionOutput(params, b56p2txToDuplicate1, SATOSHI, new byte[]{OP_TRUE}));
- addOnlyInputToTransaction(b56p2txToDuplicate1, new TransactionOutPointWithValue(
- new TransactionOutPoint(params, 0, tx2.getHash()),
- SATOSHI, tx2.getOutputs().get(0).getScriptPubKey()));
- b57p2.addTransaction(b56p2txToDuplicate1);
-
- b56p2txToDuplicate2 = new Transaction(params);
- b56p2txToDuplicate2.addOutput(new TransactionOutput(params, b56p2txToDuplicate2, SATOSHI, new byte[]{}));
- addOnlyInputToTransaction(b56p2txToDuplicate2, new TransactionOutPointWithValue(
- new TransactionOutPoint(params, 0, b56p2txToDuplicate1.getHash()),
- SATOSHI, b56p2txToDuplicate1.getOutputs().get(0).getScriptPubKey()));
- b57p2.addTransaction(b56p2txToDuplicate2);
- }
- b57p2.solve();
-
- Block b56p2;
- try {
- b56p2 = new Block(params, b57p2.block.bitcoinSerialize());
- } catch (ProtocolException e) {
- throw new RuntimeException(e); // Cannot happen.
- }
- b56p2.addTransaction(b56p2txToDuplicate1);
- b56p2.addTransaction(b56p2txToDuplicate2);
- checkState(b56p2.getHash().equals(b57p2.getHash()));
- blocks.add(new BlockAndValidity(b56p2, false, true, b55.getHash(), chainHeadHeight + 16, "b56p2"));
- blocks.add(new BlockAndValidity(b57p2, true, false, b57p2.getHash(), chainHeadHeight + 17, "b57p2"));
-
- blocks.add(new BlockAndValidity(b57, true, false, b57p2.getHash(), chainHeadHeight + 17, "b57"));
- spendableOutputs.offer(b57.getCoinbaseOutput());
-
- // Test a few invalid tx types
- // -> b35 (10) -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17)
- // \-> ??? (17)
- //
- TransactionOutPointWithValue out17 = spendableOutputs.poll();
-
- // tx with prevout.n out of range
- NewBlock b58 = createNextBlock(b57, chainHeadHeight + 18, out17, null);
- {
- Transaction tx = new Transaction(params);
- tx.addOutput(new TransactionOutput(params, tx, ZERO, new byte[] {}));
- b58.getSpendableOutput().outpoint.setIndex(42);
- addOnlyInputToTransaction(tx, b58);
- b58.addTransaction(tx);
- }
- b58.solve();
- blocks.add(new BlockAndValidity(b58, false, true, b57p2.getHash(), chainHeadHeight + 17, "b58"));
-
- // tx with output value > input value out of range
- NewBlock b59 = createNextBlock(b57, chainHeadHeight + 18, out17, null);
- {
- Transaction tx = new Transaction(params);
- tx.addOutput(new TransactionOutput(params, tx,
- b59.getSpendableOutput().value.add(SATOSHI), new byte[]{}));
- addOnlyInputToTransaction(tx, b59);
- b59.addTransaction(tx);
- }
- b59.solve();
- blocks.add(new BlockAndValidity(b59, false, true, b57p2.getHash(), chainHeadHeight + 17, "b59"));
-
- NewBlock b60 = createNextBlock(b57, chainHeadHeight + 18, out17, null);
- blocks.add(new BlockAndValidity(b60, true, false, b60.getHash(), chainHeadHeight + 18, "b60"));
- spendableOutputs.offer(b60.getCoinbaseOutput());
-
- // Test BIP30
- // -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17)
- // \-> b61 (18)
- //
- TransactionOutPointWithValue out18 = spendableOutputs.poll();
-
- NewBlock b61 = createNextBlock(b60, chainHeadHeight + 19, out18, null);
- {
- b61.block.getTransactions().get(0).getInput(0).setScriptBytes(b60.block.getTransactions().get(0).getInput(0).getScriptBytes());
- b61.block.unCache();
- checkState(b61.block.getTransactions().get(0).equals(b60.block.getTransactions().get(0)));
- }
- b61.solve();
- blocks.add(new BlockAndValidity(b61, false, true, b60.getHash(), chainHeadHeight + 18, "b61"));
-
- // Test tx.isFinal is properly rejected (not an exhaustive tx.isFinal test, that should be in data-driven transaction tests)
- // -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17)
- // \-> b62 (18)
- //
- NewBlock b62 = createNextBlock(b60, chainHeadHeight + 19, null, null);
- {
- Transaction tx = new Transaction(params);
- tx.setLockTime(0xffffffffL);
- tx.addOutput(ZERO, OP_TRUE_SCRIPT);
- addOnlyInputToTransaction(tx, out18, 0);
- b62.addTransaction(tx);
- checkState(!tx.isFinal(chainHeadHeight + 17, b62.block.getTimeSeconds()));
- }
- b62.solve();
- blocks.add(new BlockAndValidity(b62, false, true, b60.getHash(), chainHeadHeight + 18, "b62"));
-
- // Test a non-final coinbase is also rejected
- // -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17)
- // \-> b63 (-)
- //
- NewBlock b63 = createNextBlock(b60, chainHeadHeight + 19, null, null);
- {
- b63.block.getTransactions().get(0).setLockTime(0xffffffffL);
- b63.block.getTransactions().get(0).getInputs().get(0).setSequenceNumber(0xDEADBEEF);
- checkState(!b63.block.getTransactions().get(0).isFinal(chainHeadHeight + 17, b63.block.getTimeSeconds()));
- }
- b63.solve();
- blocks.add(new BlockAndValidity(b63, false, true, b60.getHash(), chainHeadHeight + 18, "b63"));
-
- // Check that a block which is (when properly encoded) <= MAX_BLOCK_SIZE is accepted
- // Even when it is encoded with varints that make its encoded size actually > MAX_BLOCK_SIZE
- // -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18)
- //
- Block b64; NewBlock b64Original;
- {
- b64Original = createNextBlock(b60, chainHeadHeight + 19, out18, null);
- Transaction tx = new Transaction(params);
- byte[] outputScript = new byte[Block.MAX_BLOCK_SIZE - b64Original.block.getMessageSize() - 65];
- Arrays.fill(outputScript, (byte) OP_FALSE);
- tx.addOutput(new TransactionOutput(params, tx, ZERO, outputScript));
- addOnlyInputToTransaction(tx, b64Original);
- b64Original.addTransaction(tx);
- b64Original.solve();
- checkState(b64Original.block.getMessageSize() == Block.MAX_BLOCK_SIZE);
-
- UnsafeByteArrayOutputStream stream = new UnsafeByteArrayOutputStream(b64Original.block.getMessageSize() + 8);
- b64Original.block.writeHeader(stream);
-
- byte[] varIntBytes = new byte[9];
- varIntBytes[0] = (byte) 255;
- Utils.uint32ToByteArrayLE((long)b64Original.block.getTransactions().size(), varIntBytes, 1);
- Utils.uint32ToByteArrayLE(((long)b64Original.block.getTransactions().size()) >>> 32, varIntBytes, 5);
- stream.write(varIntBytes);
- checkState(new VarInt(varIntBytes, 0).value == b64Original.block.getTransactions().size());
-
- for (Transaction transaction : b64Original.block.getTransactions())
- transaction.bitcoinSerialize(stream);
- b64 = new Block(params, stream.toByteArray(), false, true, stream.size());
-
- // The following checks are checking to ensure block serialization functions in the way needed for this test
- // If they fail, it is likely not an indication of error, but an indication that this test needs rewritten
- checkState(stream.size() == b64Original.block.getMessageSize() + 8);
- checkState(stream.size() == b64.getMessageSize());
- checkState(Arrays.equals(stream.toByteArray(), b64.bitcoinSerialize()));
- checkState(b64.getOptimalEncodingMessageSize() == b64Original.block.getMessageSize());
- }
- blocks.add(new BlockAndValidity(b64, true, false, b64.getHash(), chainHeadHeight + 19, "b64"));
- spendableOutputs.offer(b64Original.getCoinbaseOutput());
-
- // Spend an output created in the block itself
- // -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19)
- //
- TransactionOutPointWithValue out19 = spendableOutputs.poll(); checkState(out19 != null);//TODO preconditions all the way up
-
- NewBlock b65 = createNextBlock(b64, chainHeadHeight + 20, null, null);
- {
- Transaction tx1 = new Transaction(params);
- tx1.addOutput(out19.value, OP_TRUE_SCRIPT);
- addOnlyInputToTransaction(tx1, out19, 0);
- b65.addTransaction(tx1);
- Transaction tx2 = new Transaction(params);
- tx2.addOutput(ZERO, OP_TRUE_SCRIPT);
- tx2.addInput(tx1.getHash(), 0, OP_TRUE_SCRIPT);
- b65.addTransaction(tx2);
- }
- b65.solve();
- blocks.add(new BlockAndValidity(b65, true, false, b65.getHash(), chainHeadHeight + 20, "b65"));
- spendableOutputs.offer(b65.getCoinbaseOutput());
-
- // Attempt to spend an output created later in the same block
- // -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19)
- // \-> b66 (20)
- //
- TransactionOutPointWithValue out20 = spendableOutputs.poll(); checkState(out20 != null);
-
- NewBlock b66 = createNextBlock(b65, chainHeadHeight + 21, null, null);
- {
- Transaction tx1 = new Transaction(params);
- tx1.addOutput(out20.value, OP_TRUE_SCRIPT);
- addOnlyInputToTransaction(tx1, out20, 0);
- Transaction tx2 = new Transaction(params);
- tx2.addOutput(ZERO, OP_TRUE_SCRIPT);
- tx2.addInput(tx1.getHash(), 0, OP_NOP_SCRIPT);
- b66.addTransaction(tx2);
- b66.addTransaction(tx1);
- }
- b66.solve();
- blocks.add(new BlockAndValidity(b66, false, true, b65.getHash(), chainHeadHeight + 20, "b66"));
-
- // Attempt to double-spend a transaction created in a block
- // -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19)
- // \-> b67 (20)
- //
- NewBlock b67 = createNextBlock(b65, chainHeadHeight + 21, null, null);
- {
- Transaction tx1 = new Transaction(params);
- tx1.addOutput(out20.value, OP_TRUE_SCRIPT);
- addOnlyInputToTransaction(tx1, out20, 0);
- b67.addTransaction(tx1);
- Transaction tx2 = new Transaction(params);
- tx2.addOutput(ZERO, OP_TRUE_SCRIPT);
- tx2.addInput(tx1.getHash(), 0, OP_NOP_SCRIPT);
- b67.addTransaction(tx2);
- Transaction tx3 = new Transaction(params);
- tx3.addOutput(out20.value, OP_TRUE_SCRIPT);
- tx3.addInput(tx1.getHash(), 0, OP_NOP_SCRIPT);
- b67.addTransaction(tx3);
- }
- b67.solve();
- blocks.add(new BlockAndValidity(b67, false, true, b65.getHash(), chainHeadHeight + 20, "b67"));
-
- // A few more tests of block subsidy
- // -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) -> b69 (20)
- // \-> b68 (20)
- //
- NewBlock b68 = createNextBlock(b65, chainHeadHeight + 21, null, SATOSHI.multiply(10));
- {
- Transaction tx = new Transaction(params);
- tx.addOutput(out20.value.subtract(Coin.valueOf(9)), OP_TRUE_SCRIPT);
- addOnlyInputToTransaction(tx, out20, 0);
- b68.addTransaction(tx);
- }
- b68.solve();
- blocks.add(new BlockAndValidity(b68, false, true, b65.getHash(), chainHeadHeight + 20, "b68"));
-
- NewBlock b69 = createNextBlock(b65, chainHeadHeight + 21, null, SATOSHI.multiply(10));
- {
- Transaction tx = new Transaction(params);
- tx.addOutput(out20.value.subtract(Coin.valueOf(10)), OP_TRUE_SCRIPT);
- addOnlyInputToTransaction(tx, out20, 0);
- b69.addTransaction(tx);
- }
- b69.solve();
- blocks.add(new BlockAndValidity(b69, true, false, b69.getHash(), chainHeadHeight + 21, "b69"));
- spendableOutputs.offer(b69.getCoinbaseOutput());
-
- // Test spending the outpoint of a non-existent transaction
- // -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) -> b69 (20)
- // \-> b70 (21)
- //
- TransactionOutPointWithValue out21 = spendableOutputs.poll(); checkState(out21 != null);
- NewBlock b70 = createNextBlock(b69, chainHeadHeight + 22, out21, null);
- {
- Transaction tx = new Transaction(params);
- tx.addOutput(ZERO, OP_TRUE_SCRIPT);
- tx.addInput(new Sha256Hash("23c70ed7c0506e9178fc1a987f40a33946d4ad4c962b5ae3a52546da53af0c5c"), 0,
- OP_NOP_SCRIPT);
- b70.addTransaction(tx);
- }
- b70.solve();
- blocks.add(new BlockAndValidity(b70, false, true, b69.getHash(), chainHeadHeight + 21, "b70"));
-
- // Test accepting an invalid block which has the same hash as a valid one (via merkle tree tricks)
- // -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) -> b69 (20) -> b71 (21)
- // \-> b72 (21)
- //
- NewBlock b72 = createNextBlock(b69, chainHeadHeight + 22, out21, null);
- {
- Transaction tx = new Transaction(params);
- tx.addOutput(ZERO, OP_TRUE_SCRIPT);
- addOnlyInputToTransaction(tx, b72);
- b72.addTransaction(tx);
- }
- b72.solve();
-
- Block b71 = new Block(params, b72.block.bitcoinSerialize());
- b71.addTransaction(b72.block.getTransactions().get(2));
- checkState(b71.getHash().equals(b72.getHash()));
- blocks.add(new BlockAndValidity(b71, false, true, b69.getHash(), chainHeadHeight + 21, "b71"));
- blocks.add(new BlockAndValidity(b72, true, false, b72.getHash(), chainHeadHeight + 22, "b72"));
- spendableOutputs.offer(b72.getCoinbaseOutput());
-
- // Have some fun with invalid scripts and MAX_BLOCK_SIGOPS
- // -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) -> b69 (20) -> b72 (21)
- // \-> b** (22)
- //
- TransactionOutPointWithValue out22 = spendableOutputs.poll(); checkState(out22 != null);
-
- NewBlock b73 = createNextBlock(b72, chainHeadHeight + 23, out22, null);
- {
- int sigOps = 0;
- for (Transaction tx : b73.block.getTransactions()) {
- sigOps += tx.getSigOpCount();
- }
- Transaction tx = new Transaction(params);
- byte[] outputScript = new byte[Block.MAX_BLOCK_SIGOPS - sigOps + (int)Script.MAX_SCRIPT_ELEMENT_SIZE + 1 + 5 + 1];
- Arrays.fill(outputScript, (byte) OP_CHECKSIG);
- // If we push an element that is too large, the CHECKSIGs after that push are still counted
- outputScript[Block.MAX_BLOCK_SIGOPS - sigOps] = OP_PUSHDATA4;
- Utils.uint32ToByteArrayLE(Script.MAX_SCRIPT_ELEMENT_SIZE + 1, outputScript, Block.MAX_BLOCK_SIGOPS - sigOps + 1);
- tx.addOutput(new TransactionOutput(params, tx, SATOSHI, outputScript));
- addOnlyInputToTransaction(tx, b73);
- b73.addTransaction(tx);
- }
- b73.solve();
- blocks.add(new BlockAndValidity(b73, false, true, b72.getHash(), chainHeadHeight + 22, "b73"));
-
- NewBlock b74 = createNextBlock(b72, chainHeadHeight + 23, out22, null);
- {
- int sigOps = 0;
- for (Transaction tx : b74.block.getTransactions()) {
- sigOps += tx.getSigOpCount();
- }
- Transaction tx = new Transaction(params);
- byte[] outputScript = new byte[Block.MAX_BLOCK_SIGOPS - sigOps + (int)Script.MAX_SCRIPT_ELEMENT_SIZE + 42];
- Arrays.fill(outputScript, (byte) OP_CHECKSIG);
- // If we push an invalid element, all previous CHECKSIGs are counted
- outputScript[Block.MAX_BLOCK_SIGOPS - sigOps + 1] = OP_PUSHDATA4;
- outputScript[Block.MAX_BLOCK_SIGOPS - sigOps + 2] = (byte)0xfe;
- outputScript[Block.MAX_BLOCK_SIGOPS - sigOps + 3] = (byte)0xff;
- outputScript[Block.MAX_BLOCK_SIGOPS - sigOps + 4] = (byte)0xff;
- outputScript[Block.MAX_BLOCK_SIGOPS - sigOps + 5] = (byte)0xff;
- tx.addOutput(new TransactionOutput(params, tx, SATOSHI, outputScript));
- addOnlyInputToTransaction(tx, b74);
- b74.addTransaction(tx);
- }
- b74.solve();
- blocks.add(new BlockAndValidity(b74, false, true, b72.getHash(), chainHeadHeight + 22, "b74"));
-
- NewBlock b75 = createNextBlock(b72, chainHeadHeight + 23, out22, null);
- {
- int sigOps = 0;
- for (Transaction tx : b75.block.getTransactions()) {
- sigOps += tx.getSigOpCount();
- }
- Transaction tx = new Transaction(params);
- byte[] outputScript = new byte[Block.MAX_BLOCK_SIGOPS - sigOps + (int)Script.MAX_SCRIPT_ELEMENT_SIZE + 42];
- Arrays.fill(outputScript, (byte) OP_CHECKSIG);
- // If we push an invalid element, all subsequent CHECKSIGs are not counted
- outputScript[Block.MAX_BLOCK_SIGOPS - sigOps] = OP_PUSHDATA4;
- outputScript[Block.MAX_BLOCK_SIGOPS - sigOps + 1] = (byte)0xff;
- outputScript[Block.MAX_BLOCK_SIGOPS - sigOps + 2] = (byte)0xff;
- outputScript[Block.MAX_BLOCK_SIGOPS - sigOps + 3] = (byte)0xff;
- outputScript[Block.MAX_BLOCK_SIGOPS - sigOps + 4] = (byte)0xff;
- tx.addOutput(new TransactionOutput(params, tx, SATOSHI, outputScript));
- addOnlyInputToTransaction(tx, b75);
- b75.addTransaction(tx);
- }
- b75.solve();
- blocks.add(new BlockAndValidity(b75, true, false, b75.getHash(), chainHeadHeight + 23, "b75"));
- spendableOutputs.offer(b75.getCoinbaseOutput());
-
- TransactionOutPointWithValue out23 = spendableOutputs.poll(); checkState(out23 != null);
-
- NewBlock b76 = createNextBlock(b75, chainHeadHeight + 24, out23, null);
- {
- int sigOps = 0;
- for (Transaction tx : b76.block.getTransactions()) {
- sigOps += tx.getSigOpCount();
- }
- Transaction tx = new Transaction(params);
- byte[] outputScript = new byte[Block.MAX_BLOCK_SIGOPS - sigOps + (int)Script.MAX_SCRIPT_ELEMENT_SIZE + 1 + 5];
- Arrays.fill(outputScript, (byte) OP_CHECKSIG);
- // If we push an element that is filled with CHECKSIGs, they (obviously) arent counted
- outputScript[Block.MAX_BLOCK_SIGOPS - sigOps] = OP_PUSHDATA4;
- Utils.uint32ToByteArrayLE(Block.MAX_BLOCK_SIGOPS, outputScript, Block.MAX_BLOCK_SIGOPS - sigOps + 1);
- tx.addOutput(new TransactionOutput(params, tx, SATOSHI, outputScript));
- addOnlyInputToTransaction(tx, b76);
- b76.addTransaction(tx);
- }
- b76.solve();
- blocks.add(new BlockAndValidity(b76, true, false, b76.getHash(), chainHeadHeight + 24, "b76"));
- spendableOutputs.offer(b76.getCoinbaseOutput());
-
- // Test transaction resurrection
- // -> b77 (24) -> b78 (25) -> b79 (26)
- // \-> b80 (25) -> b81 (26) -> b82 (27)
- // b78 creates a tx, which is spent in b79. after b82, both should be in mempool
- //
- TransactionOutPointWithValue out24 = checkNotNull(spendableOutputs.poll());
- TransactionOutPointWithValue out25 = checkNotNull(spendableOutputs.poll());
- TransactionOutPointWithValue out26 = checkNotNull(spendableOutputs.poll());
- TransactionOutPointWithValue out27 = checkNotNull(spendableOutputs.poll());
-
- NewBlock b77 = createNextBlock(b76, chainHeadHeight + 25, out24, null);
- blocks.add(new BlockAndValidity(b77, true, false, b77.getHash(), chainHeadHeight + 25, "b77"));
- spendableOutputs.offer(b77.getCoinbaseOutput());
-
- NewBlock b78 = createNextBlock(b77, chainHeadHeight + 26, out25, null);
- Transaction b78tx = new Transaction(params);
- {
- b78tx.addOutput(ZERO, OP_TRUE_SCRIPT);
- addOnlyInputToTransaction(b78tx, b77);
- b78.addTransaction(b78tx);
- }
- b78.solve();
- blocks.add(new BlockAndValidity(b78, true, false, b78.getHash(), chainHeadHeight + 26, "b78"));
-
- NewBlock b79 = createNextBlock(b78, chainHeadHeight + 27, out26, null);
- Transaction b79tx = new Transaction(params);
-
- {
- b79tx.addOutput(ZERO, OP_TRUE_SCRIPT);
- b79tx.addInput(b78tx.getHash(), 0, OP_NOP_SCRIPT);
- b79.addTransaction(b79tx);
- }
- b79.solve();
- blocks.add(new BlockAndValidity(b79, true, false, b79.getHash(), chainHeadHeight + 27, "b79"));
-
- blocks.add(new MemoryPoolState(new HashSet(), "post-b79 empty mempool"));
-
- NewBlock b80 = createNextBlock(b77, chainHeadHeight + 26, out25, null);
- blocks.add(new BlockAndValidity(b80, true, false, b79.getHash(), chainHeadHeight + 27, "b80"));
- spendableOutputs.offer(b80.getCoinbaseOutput());
-
- NewBlock b81 = createNextBlock(b80, chainHeadHeight + 27, out26, null);
- blocks.add(new BlockAndValidity(b81, true, false, b79.getHash(), chainHeadHeight + 27, "b81"));
- spendableOutputs.offer(b81.getCoinbaseOutput());
-
- NewBlock b82 = createNextBlock(b81, chainHeadHeight + 28, out27, null);
- blocks.add(new BlockAndValidity(b82, true, false, b82.getHash(), chainHeadHeight + 28, "b82"));
- spendableOutputs.offer(b82.getCoinbaseOutput());
-
- HashSet post82Mempool = new HashSet();
- post82Mempool.add(new InventoryItem(InventoryItem.Type.Transaction, b78tx.getHash()));
- post82Mempool.add(new InventoryItem(InventoryItem.Type.Transaction, b79tx.getHash()));
- blocks.add(new MemoryPoolState(post82Mempool, "post-b82 tx resurrection"));
-
- // Check the UTXO query takes mempool into account.
- {
- TransactionOutPoint outpoint = new TransactionOutPoint(params, 0, b79tx.getHash());
- long[] heights = new long[] { UTXOsMessage.MEMPOOL_HEIGHT };
- UTXOsMessage result = new UTXOsMessage(params, ImmutableList.of(b79tx.getOutput(0)), heights, b82.getHash(), chainHeadHeight + 28);
- UTXORule utxo3 = new UTXORule("utxo3", outpoint, result);
- blocks.add(utxo3);
- }
-
- // Test invalid opcodes in dead execution paths.
- // -> b81 (26) -> b82 (27) -> b83 (28)
- // b83 creates a tx which contains a transaction script with an invalid opcode in a dead execution path:
- // OP_FALSE OP_IF OP_INVALIDOPCODE OP_ELSE OP_TRUE OP_ENDIF
- //
- TransactionOutPointWithValue out28 = spendableOutputs.poll(); Preconditions.checkState(out28 != null);
-
- NewBlock b83 = createNextBlock(b82, chainHeadHeight + 29, null, null);
- {
- Transaction tx1 = new Transaction(params);
- tx1.addOutput(new TransactionOutput(params, tx1, out28.value,
- new byte[]{OP_IF, (byte) OP_INVALIDOPCODE, OP_ELSE, OP_TRUE, OP_ENDIF}));
- addOnlyInputToTransaction(tx1, out28, 0);
- b83.addTransaction(tx1);
- Transaction tx2 = new Transaction(params);
- tx2.addOutput(new TransactionOutput(params, tx2, ZERO, new byte[]{OP_TRUE}));
- tx2.addInput(new TransactionInput(params, tx2, new byte[]{OP_FALSE},
- new TransactionOutPoint(params, 0, tx1.getHash())));
- b83.addTransaction(tx2);
- }
- b83.solve();
- blocks.add(new BlockAndValidity(b83, true, false, b83.getHash(), chainHeadHeight + 29, "b83"));
- spendableOutputs.offer(b83.getCoinbaseOutput());
-
- // Reorg on/off blocks that have OP_RETURN in them (and try to spend them)
- // -> b81 (26) -> b82 (27) -> b83 (28) -> b84 (29) -> b87 (30) -> b88 (31)
- // \-> b85 (29) -> b86 (30) \-> b89 (32)
- //
- TransactionOutPointWithValue out29 = spendableOutputs.poll(); Preconditions.checkState(out29 != null);
- TransactionOutPointWithValue out30 = spendableOutputs.poll(); Preconditions.checkState(out30 != null);
- TransactionOutPointWithValue out31 = spendableOutputs.poll(); Preconditions.checkState(out31 != null);
- TransactionOutPointWithValue out32 = spendableOutputs.poll(); Preconditions.checkState(out32 != null);
-
- NewBlock b84 = createNextBlock(b83, chainHeadHeight + 30, out29, null);
- Transaction b84tx1 = new Transaction(params);
- {
- b84tx1.addOutput(new TransactionOutput(params, b84tx1, ZERO, new byte[]{OP_RETURN}));
- b84tx1.addOutput(new TransactionOutput(params, b84tx1, ZERO, new byte[]{OP_TRUE}));
- b84tx1.addOutput(new TransactionOutput(params, b84tx1, ZERO, new byte[]{OP_TRUE}));
- b84tx1.addOutput(new TransactionOutput(params, b84tx1, ZERO, new byte[]{OP_TRUE}));
- b84tx1.addOutput(new TransactionOutput(params, b84tx1, ZERO, new byte[]{OP_TRUE}));
- addOnlyInputToTransaction(b84tx1, b84);
- b84.addTransaction(b84tx1);
-
- Transaction tx2 = new Transaction(params);
- tx2.addOutput(new TransactionOutput(params, tx2, ZERO, new byte[]{OP_RETURN}));
- tx2.addOutput(new TransactionOutput(params, tx2, ZERO, new byte[]{OP_RETURN}));
- tx2.addInput(new TransactionInput(params, tx2, new byte[]{OP_TRUE}, new TransactionOutPoint(params, 1, b84tx1)));
- b84.addTransaction(tx2);
-
- Transaction tx3 = new Transaction(params);
- tx3.addOutput(new TransactionOutput(params, tx3, ZERO, new byte[]{OP_RETURN}));
- tx3.addOutput(new TransactionOutput(params, tx3, ZERO, new byte[]{OP_TRUE}));
- tx3.addInput(new TransactionInput(params, tx3, new byte[]{OP_TRUE}, new TransactionOutPoint(params, 2, b84tx1)));
- b84.addTransaction(tx3);
-
- Transaction tx4 = new Transaction(params);
- tx4.addOutput(new TransactionOutput(params, tx4, ZERO, new byte[]{OP_TRUE}));
- tx4.addOutput(new TransactionOutput(params, tx4, ZERO, new byte[]{OP_RETURN}));
- tx4.addInput(new TransactionInput(params, tx4, new byte[]{OP_TRUE}, new TransactionOutPoint(params, 3, b84tx1)));
- b84.addTransaction(tx4);
-
- Transaction tx5 = new Transaction(params);
- tx5.addOutput(new TransactionOutput(params, tx5, ZERO, new byte[]{OP_RETURN}));
- tx5.addInput(new TransactionInput(params, tx5, new byte[]{OP_TRUE}, new TransactionOutPoint(params, 4, b84tx1)));
- b84.addTransaction(tx5);
- }
- b84.solve();
- blocks.add(new BlockAndValidity(b84, true, false, b84.getHash(), chainHeadHeight + 30, "b84"));
- spendableOutputs.offer(b84.getCoinbaseOutput());
-
- NewBlock b85 = createNextBlock(b83, chainHeadHeight + 30, out29, null);
- blocks.add(new BlockAndValidity(b85, true, false, b84.getHash(), chainHeadHeight + 30, "b85"));
-
- NewBlock b86 = createNextBlock(b85, chainHeadHeight + 31, out30, null);
- blocks.add(new BlockAndValidity(b86, true, false, b86.getHash(), chainHeadHeight + 31, "b86"));
-
- NewBlock b87 = createNextBlock(b84, chainHeadHeight + 31, out30, null);
- blocks.add(new BlockAndValidity(b87, true, false, b86.getHash(), chainHeadHeight + 31, "b87"));
- spendableOutputs.offer(b87.getCoinbaseOutput());
-
- NewBlock b88 = createNextBlock(b87, chainHeadHeight + 32, out31, null);
- blocks.add(new BlockAndValidity(b88, true, false, b88.getHash(), chainHeadHeight + 32, "b88"));
- spendableOutputs.offer(b88.getCoinbaseOutput());
-
- NewBlock b89 = createNextBlock(b88, chainHeadHeight + 33, out32, null);
- {
- Transaction tx = new Transaction(params);
- tx.addOutput(new TransactionOutput(params, tx, ZERO, new byte[] {OP_TRUE}));
- tx.addInput(new TransactionInput(params, tx, new byte[]{OP_TRUE}, new TransactionOutPoint(params, 0, b84tx1)));
- b89.addTransaction(tx);
- b89.solve();
- }
- blocks.add(new BlockAndValidity(b89, false, true, b88.getHash(), chainHeadHeight + 32, "b89"));
-
- // The remaining tests arent designed to fit in the standard flow, and thus must always come last
- // Add new tests here.
-
- //TODO: Explicitly address MoneyRange() checks
-
- if (!runBarelyExpensiveTests) {
- if (outStream != null)
- outStream.close();
-
- // (finally) return the created chain
- return ret;
- }
-
- // Test massive reorgs (in terms of block count/size)
- // -> b81 (26) -> b82 (27) -> b83 (28) -> b84 (29) -> b87 (30) -> b88 (31) -> lots of blocks -> b1000
- // \-> b85 (29) -> b86 (30) \-> lots more blocks
- //
- NewBlock largeReorgFinal;
- int LARGE_REORG_SIZE = 1008; // +/- a week of blocks
- int largeReorgLastHeight = chainHeadHeight + 33 + LARGE_REORG_SIZE + 1;
- {
- NewBlock nextBlock = b88;
- int nextHeight = chainHeadHeight + 33;
- TransactionOutPointWithValue largeReorgOutput = out32;
- for (int i = 0; i < LARGE_REORG_SIZE; i++) {
- nextBlock = createNextBlock(nextBlock, nextHeight, largeReorgOutput, null);
- Transaction tx = new Transaction(params);
- byte[] outputScript = new byte[Block.MAX_BLOCK_SIZE - nextBlock.block.getMessageSize() - 65];
- Arrays.fill(outputScript, (byte) OP_FALSE);
- tx.addOutput(new TransactionOutput(params, tx, ZERO, outputScript));
- addOnlyInputToTransaction(tx, nextBlock);
- nextBlock.addTransaction(tx);
- nextBlock.solve();
- blocks.add(new BlockAndValidity(nextBlock, true, false, nextBlock.getHash(), nextHeight++, "large reorg initial blocks " + i));
- spendableOutputs.offer(nextBlock.getCoinbaseOutput());
- largeReorgOutput = spendableOutputs.poll();
- }
- NewBlock reorgBase = b88;
- int reorgBaseHeight = chainHeadHeight + 33;
- for (int i = 0; i < LARGE_REORG_SIZE; i++) {
- reorgBase = createNextBlock(reorgBase, reorgBaseHeight++, null, null);
- blocks.add(new BlockAndValidity(reorgBase, true, false, nextBlock.getHash(), nextHeight - 1, "large reorg reorg block " + i));
- }
- reorgBase = createNextBlock(reorgBase, reorgBaseHeight, null, null);
- blocks.add(new BlockAndValidity(reorgBase, true, false, reorgBase.getHash(), reorgBaseHeight, "large reorg reorging block"));
- nextBlock = createNextBlock(nextBlock, nextHeight, null, null);
- blocks.add(new BlockAndValidity(nextBlock, true, false, reorgBase.getHash(), nextHeight++, "large reorg second reorg initial"));
- spendableOutputs.offer(nextBlock.getCoinbaseOutput());
- nextBlock = createNextBlock(nextBlock, nextHeight, null, null); spendableOutputs.poll();
- blocks.add(new BlockAndValidity(nextBlock, true, false, nextBlock.getHash(), nextHeight++, "large reorg second reorg"));
- spendableOutputs.offer(nextBlock.getCoinbaseOutput());
- largeReorgFinal = nextBlock;
- }
- ret.maximumReorgBlockCount = Math.max(ret.maximumReorgBlockCount, LARGE_REORG_SIZE + 2);
-
- // Test massive reorgs (in terms of tx count)
- // -> b60 (17) -> b64 (18) -> b65 (19) -> b69 (20) -> b72 (21) -> b1001 (22) -> lots of outputs -> lots of spends
- // Reorg back to:
- // -> b60 (17) -> b64 (18) -> b65 (19) -> b69 (20) -> b72 (21) -> b1001 (22) -> empty blocks
- //
- NewBlock b1001 = createNextBlock(largeReorgFinal, largeReorgLastHeight + 1, spendableOutputs.poll(), null);
- blocks.add(new BlockAndValidity(b1001, true, false, b1001.getHash(), largeReorgLastHeight + 1, "b1001"));
- spendableOutputs.offer(b1001.getCoinbaseOutput());
- int heightAfter1001 = largeReorgLastHeight + 2;
-
- if (runExpensiveTests) {
- // No way you can fit this test in memory
- Preconditions.checkArgument(blockStorageFile != null);
-
- NewBlock lastBlock = b1001;
- TransactionOutPoint lastOutput = new TransactionOutPoint(params, 1, b1001.block.getTransactions().get(1).getHash());
- int blockCountAfter1001;
- int nextHeight = heightAfter1001;
-
- List hashesToSpend = new LinkedList(); // all index 0
- final int TRANSACTION_CREATION_BLOCKS = 100;
- for (blockCountAfter1001 = 0; blockCountAfter1001 < TRANSACTION_CREATION_BLOCKS; blockCountAfter1001++) {
- NewBlock block = createNextBlock(lastBlock, nextHeight++, null, null);
- while (block.block.getMessageSize() < Block.MAX_BLOCK_SIZE - 500) {
- Transaction tx = new Transaction(params);
- tx.addInput(lastOutput.getHash(), lastOutput.getIndex(), OP_NOP_SCRIPT);
- tx.addOutput(ZERO, OP_TRUE_SCRIPT);
- tx.addOutput(ZERO, OP_TRUE_SCRIPT);
- lastOutput = new TransactionOutPoint(params, 1, tx.getHash());
- hashesToSpend.add(tx.getHash());
- block.addTransaction(tx);
- }
- block.solve();
- blocks.add(new BlockAndValidity(block, true, false, block.getHash(), nextHeight-1,
- "post-b1001 repeated transaction generator " + blockCountAfter1001 + "/" + TRANSACTION_CREATION_BLOCKS).setSendOnce(true));
- lastBlock = block;
- }
-
- Iterator hashes = hashesToSpend.iterator();
- for (int i = 0; hashes.hasNext(); i++) {
- NewBlock block = createNextBlock(lastBlock, nextHeight++, null, null);
- while (block.block.getMessageSize() < Block.MAX_BLOCK_SIZE - 500 && hashes.hasNext()) {
- Transaction tx = new Transaction(params);
- tx.addInput(hashes.next(), 0, OP_NOP_SCRIPT);
- tx.addOutput(ZERO, OP_TRUE_SCRIPT);
- block.addTransaction(tx);
- }
- block.solve();
- blocks.add(new BlockAndValidity(block, true, false, block.getHash(), nextHeight-1,
- "post-b1001 repeated transaction spender " + i).setSendOnce(true));
- lastBlock = block;
- blockCountAfter1001++;
- }
-
- // Reorg back to b1001 + empty blocks
- Sha256Hash firstHash = lastBlock.getHash();
- int height = nextHeight-1;
- nextHeight = heightAfter1001;
- lastBlock = b1001;
- for (int i = 0; i < blockCountAfter1001; i++) {
- NewBlock block = createNextBlock(lastBlock, nextHeight++, null, null);
- blocks.add(new BlockAndValidity(block, true, false, firstHash, height, "post-b1001 empty reorg block " + i + "/" + blockCountAfter1001));
- lastBlock = block;
- }
-
- // Try to spend from the other chain
- NewBlock b1002 = createNextBlock(lastBlock, nextHeight, null, null);
- {
- Transaction tx = new Transaction(params);
- tx.addInput(hashesToSpend.get(0), 0, OP_NOP_SCRIPT);
- tx.addOutput(ZERO, OP_TRUE_SCRIPT);
- b1002.addTransaction(tx);
- }
- b1002.solve();
- blocks.add(new BlockAndValidity(b1002, false, true, firstHash, height, "b1002"));
-
- // Now actually reorg
- NewBlock b1003 = createNextBlock(lastBlock, nextHeight, null, null);
- blocks.add(new BlockAndValidity(b1003, true, false, b1003.getHash(), nextHeight, "b1003"));
-
- // Now try to spend again
- NewBlock b1004 = createNextBlock(b1003, nextHeight + 1, null, null);
- {
- Transaction tx = new Transaction(params);
- tx.addInput(hashesToSpend.get(0), 0, OP_NOP_SCRIPT);
- tx.addOutput(ZERO, OP_TRUE_SCRIPT);
- b1004.addTransaction(tx);
- }
- b1004.solve();
- blocks.add(new BlockAndValidity(b1004, false, true, b1003.getHash(), nextHeight, "b1004"));
-
- ret.maximumReorgBlockCount = Math.max(ret.maximumReorgBlockCount, blockCountAfter1001);
- }
-
- if (outStream != null)
- outStream.close();
-
- // (finally) return the created chain
- return ret;
- }
-
- private byte uniquenessCounter = 0;
- private NewBlock createNextBlock(Block baseBlock, int nextBlockHeight, @Nullable TransactionOutPointWithValue prevOut,
- Coin additionalCoinbaseValue) throws ScriptException {
- Integer height = blockToHeightMap.get(baseBlock.getHash());
- if (height != null)
- checkState(height == nextBlockHeight - 1);
- Coin coinbaseValue = FIFTY_COINS.shiftRight(nextBlockHeight / params.getSubsidyDecreaseBlockCount())
- .add((prevOut != null ? prevOut.value.subtract(SATOSHI) : ZERO))
- .add(additionalCoinbaseValue == null ? ZERO : additionalCoinbaseValue);
- Block block = baseBlock.createNextBlockWithCoinbase(coinbaseOutKeyPubKey, coinbaseValue);
- Transaction t = new Transaction(params);
- if (prevOut != null) {
- // Entirely invalid scriptPubKey to ensure we aren't pre-verifying too much
- t.addOutput(new TransactionOutput(params, t, ZERO, new byte[] {(byte)(new Random().nextInt() & 0xff), uniquenessCounter++}));
- // Spendable output
- t.addOutput(new TransactionOutput(params, t, SATOSHI, new byte[] {OP_1}));
- addOnlyInputToTransaction(t, prevOut);
- block.addTransaction(t);
- block.solve();
- }
- return new NewBlock(block, prevOut == null ? null : new TransactionOutPointWithValue(t, 1));
- }
- private NewBlock createNextBlock(NewBlock baseBlock, int nextBlockHeight, @Nullable TransactionOutPointWithValue prevOut,
- Coin additionalCoinbaseValue) throws ScriptException {
- return createNextBlock(baseBlock.block, nextBlockHeight, prevOut, additionalCoinbaseValue);
- }
-
- private void addOnlyInputToTransaction(Transaction t, NewBlock block) throws ScriptException {
- addOnlyInputToTransaction(t, block.getSpendableOutput(), TransactionInput.NO_SEQUENCE);
- }
-
- private void addOnlyInputToTransaction(Transaction t, TransactionOutPointWithValue prevOut) throws ScriptException {
- addOnlyInputToTransaction(t, prevOut, TransactionInput.NO_SEQUENCE);
- }
-
- private void addOnlyInputToTransaction(Transaction t, TransactionOutPointWithValue prevOut, long sequence) throws ScriptException {
- TransactionInput input = new TransactionInput(params, t, new byte[]{}, prevOut.outpoint);
- input.setSequenceNumber(sequence);
- t.addInput(input);
-
- if (prevOut.scriptPubKey.getChunks().get(0).equalsOpCode(OP_TRUE)) {
- input.setScriptSig(new ScriptBuilder().op(OP_1).build());
- } else {
- // Sign input
- checkState(prevOut.scriptPubKey.isSentToRawPubKey());
- Sha256Hash hash = t.hashForSignature(0, prevOut.scriptPubKey, SigHash.ALL, false);
- input.setScriptSig(ScriptBuilder.createInputScript(
- new TransactionSignature(coinbaseOutKey.sign(hash), SigHash.ALL, false))
- );
- }
- }
-
- /**
- * Represents a block which is sent to the tested application and which the application must either reject or accept,
- * depending on the flags in the rule
- */
- class BlockAndValidity extends Rule {
- Block block;
- Sha256Hash blockHash;
- boolean connects;
- boolean throwsException;
- boolean sendOnce; // We can throw away the memory for this block once we send it the first time (if bitcoind asks again, its broken)
- Sha256Hash hashChainTipAfterBlock;
- int heightAfterBlock;
-
- public BlockAndValidity(Block block, boolean connects, boolean throwsException, Sha256Hash hashChainTipAfterBlock, int heightAfterBlock, String blockName) {
- super(blockName);
- if (connects && throwsException)
- throw new RuntimeException("A block cannot connect if an exception was thrown while adding it.");
- this.block = block;
- this.blockHash = block.getHash();
- this.connects = connects;
- this.throwsException = throwsException;
- this.hashChainTipAfterBlock = hashChainTipAfterBlock;
- this.heightAfterBlock = heightAfterBlock;
-
- // Keep track of the set of blocks indexed by hash
- hashHeaderMap.put(block.getHash(), block.cloneAsHeader());
-
- // Double-check that we are always marking any given block at the same height
- Integer height = blockToHeightMap.get(hashChainTipAfterBlock);
- if (height != null)
- checkState(height == heightAfterBlock);
- else
- blockToHeightMap.put(hashChainTipAfterBlock, heightAfterBlock);
- }
-
- public BlockAndValidity(NewBlock block, boolean connects, boolean throwsException, Sha256Hash hashChainTipAfterBlock, int heightAfterBlock, String blockName) {
- this(block.block, connects, throwsException, hashChainTipAfterBlock, heightAfterBlock, blockName);
- coinbaseBlockMap.put(block.getCoinbaseOutput().outpoint.getHash(), block.getHash());
- Integer blockHeight = blockToHeightMap.get(block.block.getPrevBlockHash());
- if (blockHeight != null) {
- blockHeight++;
- for (Transaction t : block.block.getTransactions())
- for (TransactionInput in : t.getInputs()) {
- Sha256Hash blockSpendingHash = coinbaseBlockMap.get(in.getOutpoint().getHash());
- checkState(blockSpendingHash == null || blockToHeightMap.get(blockSpendingHash) == null ||
- blockToHeightMap.get(blockSpendingHash) == blockHeight - params.getSpendableCoinbaseDepth());
- }
- }
- }
-
- public BlockAndValidity setSendOnce(boolean sendOnce) {
- this.sendOnce = sendOnce;
- return this;
- }
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/H2FullPrunedBlockChainTest.java b/core/src/test/java/com/dogecoin/dogecoinj/core/H2FullPrunedBlockChainTest.java
deleted file mode 100644
index f2f24efd..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/H2FullPrunedBlockChainTest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.dogecoin.dogecoinj.core;
-
-import com.dogecoin.dogecoinj.store.BlockStoreException;
-import com.dogecoin.dogecoinj.store.FullPrunedBlockStore;
-import com.dogecoin.dogecoinj.store.H2FullPrunedBlockStore;
-import org.junit.After;
-
-import java.io.File;
-
-/**
- * An H2 implementation of the FullPrunedBlockStoreTest
- */
-public class H2FullPrunedBlockChainTest extends AbstractFullPrunedBlockChainTest {
- @After
- public void tearDown() throws Exception {
- deleteFiles();
- }
-
- @Override
- public FullPrunedBlockStore createStore(NetworkParameters params, int blockCount) throws BlockStoreException {
- deleteFiles();
- return new H2FullPrunedBlockStore(params, "test", blockCount);
- }
-
- private void deleteFiles() {
- maybeDelete("test.h2.db");
- maybeDelete("test.trace.db");
- maybeDelete("test.lock.db");
- }
-
- private void maybeDelete(String s) {
- new File(s).delete();
- }
-
- @Override
- public void resetStore(FullPrunedBlockStore store) throws BlockStoreException {
- ((H2FullPrunedBlockStore)store).resetStore();
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/LazyParseByteCacheTest.java b/core/src/test/java/com/dogecoin/dogecoinj/core/LazyParseByteCacheTest.java
deleted file mode 100644
index dae088b6..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/LazyParseByteCacheTest.java
+++ /dev/null
@@ -1,529 +0,0 @@
-/**
- * Copyright 2011 Steve Coughlan.
- * 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 com.dogecoin.dogecoinj.core;
-
-import com.dogecoin.dogecoinj.params.MainNetParams;
-import com.dogecoin.dogecoinj.params.UnitTestParams;
-import com.dogecoin.dogecoinj.store.BlockStore;
-import com.dogecoin.dogecoinj.store.MemoryBlockStore;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.ByteArrayOutputStream;
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-
-import static com.dogecoin.dogecoinj.core.Coin.*;
-import static com.dogecoin.dogecoinj.core.Utils.HEX;
-import static com.dogecoin.dogecoinj.testing.FakeTxBuilder.createFakeBlock;
-import static com.dogecoin.dogecoinj.testing.FakeTxBuilder.createFakeTx;
-import static org.junit.Assert.*;
-
-public class LazyParseByteCacheTest {
-
- private final byte[] txMessage = HEX.withSeparator(" ", 2).decode(
- "f9 be b4 d9 74 78 00 00 00 00 00 00 00 00 00 00" +
- "02 01 00 00 e2 93 cd be 01 00 00 00 01 6d bd db" +
- "08 5b 1d 8a f7 51 84 f0 bc 01 fa d5 8d 12 66 e9" +
- "b6 3b 50 88 19 90 e4 b4 0d 6a ee 36 29 00 00 00" +
- "00 8b 48 30 45 02 21 00 f3 58 1e 19 72 ae 8a c7" +
- "c7 36 7a 7a 25 3b c1 13 52 23 ad b9 a4 68 bb 3a" +
- "59 23 3f 45 bc 57 83 80 02 20 59 af 01 ca 17 d0" +
- "0e 41 83 7a 1d 58 e9 7a a3 1b ae 58 4e de c2 8d" +
- "35 bd 96 92 36 90 91 3b ae 9a 01 41 04 9c 02 bf" +
- "c9 7e f2 36 ce 6d 8f e5 d9 40 13 c7 21 e9 15 98" +
- "2a cd 2b 12 b6 5d 9b 7d 59 e2 0a 84 20 05 f8 fc" +
- "4e 02 53 2e 87 3d 37 b9 6f 09 d6 d4 51 1a da 8f" +
- "14 04 2f 46 61 4a 4c 70 c0 f1 4b ef f5 ff ff ff" +
- "ff 02 40 4b 4c 00 00 00 00 00 19 76 a9 14 1a a0" +
- "cd 1c be a6 e7 45 8a 7a ba d5 12 a9 d9 ea 1a fb" +
- "22 5e 88 ac 80 fa e9 c7 00 00 00 00 19 76 a9 14" +
- "0e ab 5b ea 43 6a 04 84 cf ab 12 48 5e fd a0 b7" +
- "8b 4e cc 52 88 ac 00 00 00 00");
-
- private final byte[] txMessagePart = HEX.withSeparator(" ", 2).decode(
- "08 5b 1d 8a f7 51 84 f0 bc 01 fa d5 8d 12 66 e9" +
- "b6 3b 50 88 19 90 e4 b4 0d 6a ee 36 29 00 00 00" +
- "00 8b 48 30 45 02 21 00 f3 58 1e 19 72 ae 8a c7" +
- "c7 36 7a 7a 25 3b c1 13 52 23 ad b9 a4 68 bb 3a");
-
- private Wallet wallet;
- private BlockStore blockStore;
- private NetworkParameters unitTestParams;
-
- private byte[] b1Bytes;
- private byte[] b1BytesWithHeader;
-
- private byte[] tx1Bytes;
- private byte[] tx1BytesWithHeader;
-
- private byte[] tx2Bytes;
- private byte[] tx2BytesWithHeader;
-
- private void resetBlockStore() {
- blockStore = new MemoryBlockStore(unitTestParams);
- }
-
- @Before
- public void setUp() throws Exception {
- unitTestParams = UnitTestParams.get();
- wallet = new Wallet(unitTestParams);
- wallet.freshReceiveKey();
-
- resetBlockStore();
-
- Transaction tx1 = createFakeTx(unitTestParams,
- valueOf(2, 0),
- wallet.currentReceiveKey().toAddress(unitTestParams));
-
- //add a second input so can test granularity of byte cache.
- Transaction prevTx = new Transaction(unitTestParams);
- TransactionOutput prevOut = new TransactionOutput(unitTestParams, prevTx, COIN, wallet.currentReceiveKey().toAddress(unitTestParams));
- prevTx.addOutput(prevOut);
- // Connect it.
- tx1.addInput(prevOut);
-
- Transaction tx2 = createFakeTx(unitTestParams, COIN,
- new ECKey().toAddress(unitTestParams));
-
- Block b1 = createFakeBlock(blockStore, tx1, tx2).block;
-
- BitcoinSerializer bs = new BitcoinSerializer(unitTestParams);
-
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- bs.serialize(tx1, bos);
- tx1BytesWithHeader = bos.toByteArray();
- tx1Bytes = tx1.bitcoinSerialize();
-
- bos.reset();
- bs.serialize(tx2, bos);
- tx2BytesWithHeader = bos.toByteArray();
- tx2Bytes = tx2.bitcoinSerialize();
-
- bos.reset();
- bs.serialize(b1, bos);
- b1BytesWithHeader = bos.toByteArray();
- b1Bytes = b1.bitcoinSerialize();
- }
-
- @Test
- public void validateSetup() {
- byte[] b1 = new byte[] {1, 1, 1, 2, 3, 4, 5, 6, 7};
- byte[] b2 = new byte[] {1, 2, 3};
- assertTrue(arrayContains(b1, b2));
- assertTrue(arrayContains(txMessage, txMessagePart));
- assertTrue(arrayContains(tx1BytesWithHeader, tx1Bytes));
- assertTrue(arrayContains(tx2BytesWithHeader, tx2Bytes));
- assertTrue(arrayContains(b1BytesWithHeader, b1Bytes));
- assertTrue(arrayContains(b1BytesWithHeader, tx1Bytes));
- assertTrue(arrayContains(b1BytesWithHeader, tx2Bytes));
- assertFalse(arrayContains(tx1BytesWithHeader, b1Bytes));
- }
-
- @Test
- public void testTransactionsLazyRetain() throws Exception {
- testTransaction(MainNetParams.get(), txMessage, false, true, true);
- testTransaction(unitTestParams, tx1BytesWithHeader, false, true, true);
- testTransaction(unitTestParams, tx2BytesWithHeader, false, true, true);
- }
-
- @Test
- public void testTransactionsLazyNoRetain() throws Exception {
- testTransaction(MainNetParams.get(), txMessage, false, true, false);
- testTransaction(unitTestParams, tx1BytesWithHeader, false, true, false);
- testTransaction(unitTestParams, tx2BytesWithHeader, false, true, false);
- }
-
- @Test
- public void testTransactionsNoLazyNoRetain() throws Exception {
- testTransaction(MainNetParams.get(), txMessage, false, false, false);
- testTransaction(unitTestParams, tx1BytesWithHeader, false, false, false);
- testTransaction(unitTestParams, tx2BytesWithHeader, false, false, false);
- }
-
- @Test
- public void testTransactionsNoLazyRetain() throws Exception {
- testTransaction(MainNetParams.get(), txMessage, false, false, true);
- testTransaction(unitTestParams, tx1BytesWithHeader, false, false, true);
- testTransaction(unitTestParams, tx2BytesWithHeader, false, false, true);
- }
-
- @Test
- public void testBlockAll() throws Exception {
- testBlock(b1BytesWithHeader, false, false, false);
- testBlock(b1BytesWithHeader, false, true, true);
- testBlock(b1BytesWithHeader, false, true, false);
- testBlock(b1BytesWithHeader, false, false, true);
- }
-
-
- public void testBlock(byte[] blockBytes, boolean isChild, boolean lazy, boolean retain) throws Exception {
- //reference serializer to produce comparison serialization output after changes to
- //message structure.
- BitcoinSerializer bsRef = new BitcoinSerializer(unitTestParams, false, false);
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
-
- BitcoinSerializer bs = new BitcoinSerializer(unitTestParams, lazy, retain);
- Block b1;
- Block bRef;
- b1 = (Block) bs.deserialize(ByteBuffer.wrap(blockBytes));
- bRef = (Block) bsRef.deserialize(ByteBuffer.wrap(blockBytes));
-
- //verify our reference BitcoinSerializer produces matching byte array.
- bos.reset();
- bsRef.serialize(bRef, bos);
- assertTrue(Arrays.equals(bos.toByteArray(), blockBytes));
-
- //check lazy and retain status survive both before and after a serialization
- assertEquals(!lazy, b1.isParsedTransactions());
- assertEquals(!lazy, b1.isParsedHeader());
- if (b1.isParsedHeader())
- assertEquals(retain, b1.isHeaderBytesValid());
- if (b1.isParsedTransactions())
- assertEquals(retain, b1.isTransactionBytesValid());
-
- serDeser(bs, b1, blockBytes, null, null);
-
- assertEquals(!lazy, b1.isParsedTransactions());
- assertEquals(!lazy, b1.isParsedHeader());
- if (b1.isParsedHeader())
- assertEquals(retain, b1.isHeaderBytesValid());
- if (b1.isParsedTransactions())
- assertEquals(retain, b1.isTransactionBytesValid());
-
- //compare to ref block
- bos.reset();
- bsRef.serialize(bRef, bos);
- serDeser(bs, b1, bos.toByteArray(), null, null);
-
- //retrieve a value from a child
- b1.getTransactions();
- assertTrue(b1.isParsedTransactions());
- if (b1.getTransactions().size() > 0) {
- assertTrue(b1.isParsedTransactions());
- Transaction tx1 = b1.getTransactions().get(0);
-
- //this will always be true for all children of a block once they are retrieved.
- //the tx child inputs/outputs may not be parsed however.
-
- //no longer forced to parse if length not provided.
- //assertEquals(true, tx1.isParsed());
- if (tx1.isParsed())
- assertEquals(retain, tx1.isCached());
- else
- assertTrue(tx1.isCached());
-
- //does it still match ref block?
- serDeser(bs, b1, bos.toByteArray(), null, null);
- }
-
- //refresh block
- b1 = (Block) bs.deserialize(ByteBuffer.wrap(blockBytes));
- bRef = (Block) bsRef.deserialize(ByteBuffer.wrap(blockBytes));
-
- //retrieve a value from header
- b1.getDifficultyTarget();
- assertTrue(b1.isParsedHeader());
- assertEquals(lazy, !b1.isParsedTransactions());
-
- //does it still match ref block?
- serDeser(bs, b1, bos.toByteArray(), null, null);
-
-
- //refresh block
- b1 = (Block) bs.deserialize(ByteBuffer.wrap(blockBytes));
- bRef = (Block) bsRef.deserialize(ByteBuffer.wrap(blockBytes));
-
- //retrieve a value from a child and header
- b1.getDifficultyTarget();
- assertTrue(b1.isParsedHeader());
- assertEquals(lazy, !b1.isParsedTransactions());
-
- b1.getTransactions();
- assertTrue(b1.isParsedTransactions());
- if (b1.getTransactions().size() > 0) {
- assertTrue(b1.isParsedTransactions());
- Transaction tx1 = b1.getTransactions().get(0);
-
- //no longer forced to parse if length not provided.
- //assertEquals(true, tx1.isParsed());
-
- if (tx1.isParsed())
- assertEquals(retain, tx1.isCached());
- else
- assertTrue(tx1.isCached());
- }
- //does it still match ref block?
- serDeser(bs, b1, bos.toByteArray(), null, null);
-
- //refresh block
- b1 = (Block) bs.deserialize(ByteBuffer.wrap(blockBytes));
- bRef = (Block) bsRef.deserialize(ByteBuffer.wrap(blockBytes));
-
- //change a value in header
- b1.setNonce(23);
- bRef.setNonce(23);
- assertTrue(b1.isParsedHeader());
- assertEquals(lazy, !b1.isParsedTransactions());
- assertFalse(b1.isHeaderBytesValid());
- if (b1.isParsedTransactions())
- assertEquals(retain , b1.isTransactionBytesValid());
- else
- assertEquals(true, b1.isTransactionBytesValid());
- //does it still match ref block?
- bos.reset();
- bsRef.serialize(bRef, bos);
- serDeser(bs, b1, bos.toByteArray(), null, null);
-
- //refresh block
- b1 = (Block) bs.deserialize(ByteBuffer.wrap(blockBytes));
- bRef = (Block) bsRef.deserialize(ByteBuffer.wrap(blockBytes));
-
- //retrieve a value from a child of a child
- b1.getTransactions();
- if (b1.getTransactions().size() > 0) {
- Transaction tx1 = b1.getTransactions().get(0);
-
- TransactionInput tin = tx1.getInputs().get(0);
-
- assertTrue(tx1.isParsed());
- assertTrue(b1.isParsedTransactions());
- assertEquals(!lazy, b1.isParsedHeader());
-
- assertEquals(!lazy, tin.isParsed());
- assertEquals(tin.isParsed() ? retain : true, tin.isCached());
-
- //does it still match ref tx?
- bos.reset();
- bsRef.serialize(bRef, bos);
- serDeser(bs, b1, bos.toByteArray(), null, null);
- }
-
- //refresh block
- b1 = (Block) bs.deserialize(ByteBuffer.wrap(blockBytes));
- bRef = (Block) bsRef.deserialize(ByteBuffer.wrap(blockBytes));
-
- //add an input
- b1.getTransactions();
- if (b1.getTransactions().size() > 0) {
- Transaction tx1 = b1.getTransactions().get(0);
-
- if (tx1.getInputs().size() > 0) {
- tx1.addInput(tx1.getInputs().get(0));
- //replicate on reference tx
- bRef.getTransactions().get(0).addInput(bRef.getTransactions().get(0).getInputs().get(0));
-
- assertFalse(tx1.isCached());
- assertTrue(tx1.isParsed());
- assertFalse(b1.isTransactionBytesValid());
- assertTrue(b1.isParsedHeader());
-
- //confirm sibling cache status was unaffected
- if (tx1.getInputs().size() > 1) {
- boolean parsed = tx1.getInputs().get(1).isParsed();
- assertEquals(parsed ? retain : true, tx1.getInputs().get(1).isCached());
- assertEquals(!lazy, parsed);
- }
-
- //this has to be false. Altering a tx invalidates the merkle root.
- //when we have seperate merkle caching then the entire header won't need to be
- //invalidated.
- assertFalse(b1.isHeaderBytesValid());
-
- bos.reset();
- bsRef.serialize(bRef, bos);
- byte[] source = bos.toByteArray();
- //confirm we still match the reference tx.
- serDeser(bs, b1, source, null, null);
- }
-
- //does it still match ref tx?
- bos.reset();
- bsRef.serialize(bRef, bos);
- serDeser(bs, b1, bos.toByteArray(), null, null);
- }
-
- //refresh block
- b1 = (Block) bs.deserialize(ByteBuffer.wrap(blockBytes));
- Block b2 = (Block) bs.deserialize(ByteBuffer.wrap(blockBytes));
- bRef = (Block) bsRef.deserialize(ByteBuffer.wrap(blockBytes));
- Block bRef2 = (Block) bsRef.deserialize(ByteBuffer.wrap(blockBytes));
-
- //reparent an input
- b1.getTransactions();
- if (b1.getTransactions().size() > 0) {
- Transaction tx1 = b1.getTransactions().get(0);
- Transaction tx2 = b2.getTransactions().get(0);
-
- if (tx1.getInputs().size() > 0) {
- TransactionInput fromTx1 = tx1.getInputs().get(0);
- tx2.addInput(fromTx1);
-
- //replicate on reference tx
- TransactionInput fromTxRef = bRef.getTransactions().get(0).getInputs().get(0);
- bRef2.getTransactions().get(0).addInput(fromTxRef);
-
- //b1 hasn't changed but it's no longer in the parent
- //chain of fromTx1 so has to have been uncached since it won't be
- //notified of changes throught the parent chain anymore.
- assertFalse(b1.isTransactionBytesValid());
-
- //b2 should have it's cache invalidated because it has changed.
- assertFalse(b2.isTransactionBytesValid());
-
- bos.reset();
- bsRef.serialize(bRef2, bos);
- byte[] source = bos.toByteArray();
- //confirm altered block matches altered ref block.
- serDeser(bs, b2, source, null, null);
- }
-
- //does unaltered block still match ref block?
- bos.reset();
- bsRef.serialize(bRef, bos);
- serDeser(bs, b1, bos.toByteArray(), null, null);
-
- //how about if we refresh it?
- bRef = (Block) bsRef.deserialize(ByteBuffer.wrap(blockBytes));
- bos.reset();
- bsRef.serialize(bRef, bos);
- serDeser(bs, b1, bos.toByteArray(), null, null);
- }
-
- }
-
- public void testTransaction(NetworkParameters params, byte[] txBytes, boolean isChild, boolean lazy, boolean retain) throws Exception {
-
- //reference serializer to produce comparison serialization output after changes to
- //message structure.
- BitcoinSerializer bsRef = new BitcoinSerializer(params, false, false);
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
-
- BitcoinSerializer bs = new BitcoinSerializer(params, lazy, retain);
- Transaction t1;
- Transaction tRef;
- t1 = (Transaction) bs.deserialize(ByteBuffer.wrap(txBytes));
- tRef = (Transaction) bsRef.deserialize(ByteBuffer.wrap(txBytes));
-
- //verify our reference BitcoinSerializer produces matching byte array.
- bos.reset();
- bsRef.serialize(tRef, bos);
- assertTrue(Arrays.equals(bos.toByteArray(), txBytes));
-
- //check lazy and retain status survive both before and after a serialization
- assertEquals(!lazy, t1.isParsed());
- if (t1.isParsed())
- assertEquals(retain, t1.isCached());
-
- serDeser(bs, t1, txBytes, null, null);
-
- assertEquals(lazy, !t1.isParsed());
- if (t1.isParsed())
- assertEquals(retain, t1.isCached());
-
- //compare to ref tx
- bos.reset();
- bsRef.serialize(tRef, bos);
- serDeser(bs, t1, bos.toByteArray(), null, null);
-
- //retrieve a value from a child
- t1.getInputs();
- assertTrue(t1.isParsed());
- if (t1.getInputs().size() > 0) {
- assertTrue(t1.isParsed());
- TransactionInput tin = t1.getInputs().get(0);
- assertEquals(!lazy, tin.isParsed());
- if (tin.isParsed())
- assertEquals(retain, tin.isCached());
-
- //does it still match ref tx?
- serDeser(bs, t1, bos.toByteArray(), null, null);
- }
-
- //refresh tx
- t1 = (Transaction) bs.deserialize(ByteBuffer.wrap(txBytes));
- tRef = (Transaction) bsRef.deserialize(ByteBuffer.wrap(txBytes));
-
- //add an input
- if (t1.getInputs().size() > 0) {
-
- t1.addInput(t1.getInputs().get(0));
-
- //replicate on reference tx
- tRef.addInput(tRef.getInputs().get(0));
-
- assertFalse(t1.isCached());
- assertTrue(t1.isParsed());
-
- bos.reset();
- bsRef.serialize(tRef, bos);
- byte[] source = bos.toByteArray();
- //confirm we still match the reference tx.
- serDeser(bs, t1, source, null, null);
- }
-
- }
-
- private void serDeser(BitcoinSerializer bs, Message message, byte[] sourceBytes, byte[] containedBytes, byte[] containingBytes) throws Exception {
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- bs.serialize(message, bos);
- byte[] b1 = bos.toByteArray();
-
- Message m2 = bs.deserialize(ByteBuffer.wrap(b1));
-
- assertEquals(message, m2);
-
- bos.reset();
- bs.serialize(m2, bos);
- byte[] b2 = bos.toByteArray();
- assertTrue(Arrays.equals(b1, b2));
-
- if (sourceBytes != null) {
- assertTrue(arrayContains(sourceBytes, b1));
-
- assertTrue(arrayContains(sourceBytes, b2));
- }
-
- if (containedBytes != null) {
- assertTrue(arrayContains(b1, containedBytes));
- }
- if (containingBytes != null) {
- assertTrue(arrayContains(containingBytes, b1));
- }
- }
-
- public static boolean arrayContains(byte[] sup, byte[] sub) {
- if (sup.length < sub.length)
- return false;
-
- String superstring = Utils.HEX.encode(sup);
- String substring = Utils.HEX.encode(sub);
-
- int ind = superstring.indexOf(substring);
-
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < superstring.indexOf(substring); i++)
- sb.append(" ");
-
- //System.out.println(superstring);
- //System.out.println(sb.append(substring).toString());
- //System.out.println();
- return ind > -1;
-
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/MemoryFullPrunedBlockChainTest.java b/core/src/test/java/com/dogecoin/dogecoinj/core/MemoryFullPrunedBlockChainTest.java
deleted file mode 100644
index 6cdf66a4..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/MemoryFullPrunedBlockChainTest.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.dogecoin.dogecoinj.core;
-
-import com.dogecoin.dogecoinj.store.BlockStoreException;
-import com.dogecoin.dogecoinj.store.FullPrunedBlockStore;
-import com.dogecoin.dogecoinj.store.MemoryFullPrunedBlockStore;
-
-/**
- * A MemoryStore implementation of the FullPrunedBlockStoreTest
- */
-public class MemoryFullPrunedBlockChainTest extends AbstractFullPrunedBlockChainTest
-{
- @Override
- public FullPrunedBlockStore createStore(NetworkParameters params, int blockCount) throws BlockStoreException
- {
- return new MemoryFullPrunedBlockStore(params, blockCount);
- }
-
- @Override
- public void resetStore(FullPrunedBlockStore store) throws BlockStoreException
- {
- //No-op for memory store, because it's not persistent
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/MemoryPoolTest.java b/core/src/test/java/com/dogecoin/dogecoinj/core/MemoryPoolTest.java
deleted file mode 100644
index 3d0b2564..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/MemoryPoolTest.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2012 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 com.dogecoin.dogecoinj.core;
-
-import com.dogecoin.dogecoinj.params.UnitTestParams;
-import com.dogecoin.dogecoinj.testing.FakeTxBuilder;
-import com.dogecoin.dogecoinj.utils.BriefLogFormatter;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.net.InetAddress;
-
-import static com.dogecoin.dogecoinj.core.Coin.COIN;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-public class MemoryPoolTest {
- private NetworkParameters params = UnitTestParams.get();
- private Transaction tx1, tx2;
- private PeerAddress address1, address2, address3;
-
- @Before
- public void setup() throws Exception {
- BriefLogFormatter.init();
- tx1 = FakeTxBuilder.createFakeTx(params, COIN, new ECKey().toAddress(params));
- tx2 = new Transaction(params, tx1.bitcoinSerialize());
-
- address1 = new PeerAddress(InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 }));
- address2 = new PeerAddress(InetAddress.getByAddress(new byte[] { 127, 0, 0, 2 }));
- address3 = new PeerAddress(InetAddress.getByAddress(new byte[] { 127, 0, 0, 3 }));
- }
-
- @Test
- public void canonicalInstance() throws Exception {
- TxConfidenceTable table = new TxConfidenceTable();
- // Check that if we repeatedly send it the same transaction but with different objects, we get back the same
- // canonical instance with the confidences update.
- assertEquals(0, table.numBroadcastPeers(tx1.getHash()));
- assertEquals(tx1, table.seen(tx1, address1));
- assertEquals(1, tx1.getConfidence().numBroadcastPeers());
- assertEquals(1, table.numBroadcastPeers(tx1.getHash()));
- assertEquals(tx1, table.seen(tx2, address2));
- assertEquals(2, tx1.getConfidence().numBroadcastPeers());
- assertEquals(2, table.numBroadcastPeers(tx1.getHash()));
- assertEquals(tx1, table.get(tx1.getHash()));
- }
-
- @Test
- public void invAndDownload() throws Exception {
- TxConfidenceTable table = new TxConfidenceTable();
- // Base case: we see a transaction announced twice and then download it. The count is in the confidence object.
- assertEquals(0, table.numBroadcastPeers(tx1.getHash()));
- table.seen(tx1.getHash(), address1);
- assertEquals(1, table.numBroadcastPeers(tx1.getHash()));
- assertTrue(table.maybeWasSeen(tx1.getHash()));
- table.seen(tx1.getHash(), address2);
- assertEquals(2, table.numBroadcastPeers(tx1.getHash()));
- Transaction t = table.seen(tx1, address1);
- assertEquals(2, t.getConfidence().numBroadcastPeers());
- // And now we see another inv.
- table.seen(tx1.getHash(), address3);
- assertEquals(3, t.getConfidence().numBroadcastPeers());
- assertEquals(3, table.numBroadcastPeers(tx1.getHash()));
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/MessageTest.java b/core/src/test/java/com/dogecoin/dogecoinj/core/MessageTest.java
deleted file mode 100644
index 8d18ad36..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/MessageTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2014 Piotr Włodarek
- *
- * 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 com.dogecoin.dogecoinj.core;
-
-import com.dogecoin.dogecoinj.params.UnitTestParams;
-import org.junit.Test;
-
-public class MessageTest {
-
- // If readStr() is vulnerable this causes OutOfMemory
- @Test(expected = ProtocolException.class)
- public void readStrOfExtremeLength() throws Exception {
- NetworkParameters params = UnitTestParams.get();
- VarInt length = new VarInt(Integer.MAX_VALUE);
- byte[] payload = length.encode();
- new VarStrMessage(params, payload);
- }
-
- static class VarStrMessage extends Message {
- public VarStrMessage(NetworkParameters params, byte[] payload) {
- super(params, payload, 0);
- }
-
- @Override
- void parse() throws ProtocolException {
- readStr();
- }
-
- @Override
- protected void parseLite() throws ProtocolException {}
- }
-
- // If readBytes() is vulnerable this causes OutOfMemory
- @Test(expected = ProtocolException.class)
- public void readByteArrayOfExtremeLength() throws Exception {
- NetworkParameters params = UnitTestParams.get();
- VarInt length = new VarInt(Integer.MAX_VALUE);
- byte[] payload = length.encode();
- new VarBytesMessage(params, payload);
- }
-
- static class VarBytesMessage extends Message {
- public VarBytesMessage(NetworkParameters params, byte[] payload) {
- super(params, payload, 0);
- }
-
- @Override
- void parse() throws ProtocolException {
- readByteArray();
- }
-
- @Override
- protected void parseLite() throws ProtocolException {}
- }
-
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/MySQLFullPrunedBlockChainTest.java b/core/src/test/java/com/dogecoin/dogecoinj/core/MySQLFullPrunedBlockChainTest.java
deleted file mode 100644
index 9b361b4c..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/MySQLFullPrunedBlockChainTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2014 Kalpesh Parmar.
- *
- * 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 com.dogecoin.dogecoinj.core;
-
-import com.dogecoin.dogecoinj.store.BlockStoreException;
-import com.dogecoin.dogecoinj.store.FullPrunedBlockStore;
-import com.dogecoin.dogecoinj.store.MySQLFullPrunedBlockStore;
-import org.junit.After;
-import org.junit.Ignore;
-
-/**
- * A MySQL implementation of the {@link AbstractFullPrunedBlockChainTest}
- */
-@Ignore("enable the mysql driver dependency in the maven POM")
-public class MySQLFullPrunedBlockChainTest extends AbstractFullPrunedBlockChainTest {
-
- @After
- public void tearDown() throws Exception {
- ((MySQLFullPrunedBlockStore)store).deleteStore();
- }
-
- // Replace these with your mysql location/credentials and remove @Ignore to test
- private static final String DB_HOSTNAME = "localhost";
- private static final String DB_NAME = "bitcoinj_test";
- private static final String DB_USERNAME = "bitcoinj";
- private static final String DB_PASSWORD = "password";
-
- @Override
- public FullPrunedBlockStore createStore(NetworkParameters params, int blockCount)
- throws BlockStoreException {
- return new MySQLFullPrunedBlockStore(params, blockCount, DB_HOSTNAME, DB_NAME, DB_USERNAME, DB_PASSWORD);
- }
-
- @Override
- public void resetStore(FullPrunedBlockStore store) throws BlockStoreException {
- ((MySQLFullPrunedBlockStore)store).resetStore();
- }
-}
\ No newline at end of file
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/PeerAddressTest.java b/core/src/test/java/com/dogecoin/dogecoinj/core/PeerAddressTest.java
deleted file mode 100644
index ae8a19a3..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/PeerAddressTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2011 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 com.dogecoin.dogecoinj.core;
-
-import com.dogecoin.dogecoinj.params.MainNetParams;
-import org.junit.Test;
-
-import java.net.InetAddress;
-
-import static com.dogecoin.dogecoinj.core.Utils.HEX;
-import static org.junit.Assert.assertEquals;
-
-public class PeerAddressTest
-{
- @Test
- public void testPeerAddressRoundtrip() throws Exception {
- // copied verbatim from https://en.bitcoin.it/wiki/Protocol_specification#Network_address
- String fromSpec = "010000000000000000000000000000000000ffff0a000001208d";
- PeerAddress pa = new PeerAddress(MainNetParams.get(),
- HEX.decode(fromSpec), 0, 0);
- String reserialized = Utils.HEX.encode(pa.bitcoinSerialize());
- assertEquals(reserialized,fromSpec );
- }
-
- @Test
- public void testBitcoinSerialize() throws Exception {
- PeerAddress pa = new PeerAddress(InetAddress.getByName(null), 8333, 0);
- assertEquals("000000000000000000000000000000000000ffff7f000001208d",
- Utils.HEX.encode(pa.bitcoinSerialize()));
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/PeerTest.java b/core/src/test/java/com/dogecoin/dogecoinj/core/PeerTest.java
deleted file mode 100644
index 8f446c07..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/PeerTest.java
+++ /dev/null
@@ -1,872 +0,0 @@
-/*
- * Copyright 2011 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 com.dogecoin.dogecoinj.core;
-
-import com.dogecoin.dogecoinj.params.TestNet3Params;
-import com.dogecoin.dogecoinj.testing.FakeTxBuilder;
-import com.dogecoin.dogecoinj.testing.InboundMessageQueuer;
-import com.dogecoin.dogecoinj.testing.TestWithNetworkConnections;
-import com.dogecoin.dogecoinj.utils.Threading;
-import com.google.common.collect.Lists;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.SettableFuture;
-import com.google.common.util.concurrent.Uninterruptibles;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.net.InetSocketAddress;
-import java.net.SocketException;
-import java.nio.channels.CancelledKeyException;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import static com.dogecoin.dogecoinj.core.Coin.*;
-import static com.dogecoin.dogecoinj.testing.FakeTxBuilder.*;
-import static org.junit.Assert.*;
-
-@RunWith(value = Parameterized.class)
-public class PeerTest extends TestWithNetworkConnections {
- private Peer peer;
- private InboundMessageQueuer writeTarget;
- private static final int OTHER_PEER_CHAIN_HEIGHT = 110;
- private TxConfidenceTable confidenceTable;
- private final AtomicBoolean fail = new AtomicBoolean(false);
-
-
- @Parameterized.Parameters
- public static Collection parameters() {
- return Arrays.asList(new ClientType[] {ClientType.NIO_CLIENT_MANAGER},
- new ClientType[] {ClientType.BLOCKING_CLIENT_MANAGER},
- new ClientType[] {ClientType.NIO_CLIENT},
- new ClientType[] {ClientType.BLOCKING_CLIENT});
- }
-
- public PeerTest(ClientType clientType) {
- super(clientType);
- }
-
- @Override
- @Before
- public void setUp() throws Exception {
- super.setUp();
-
- confidenceTable = blockChain.getContext().getConfidenceTable();
- VersionMessage ver = new VersionMessage(unitTestParams, 100);
- InetSocketAddress address = new InetSocketAddress("127.0.0.1", 4000);
- peer = new Peer(unitTestParams, ver, new PeerAddress(address), blockChain);
- peer.addWallet(wallet);
- }
-
- @Override
- @After
- public void tearDown() throws Exception {
- super.tearDown();
- assertFalse(fail.get());
- }
-
- private void connect() throws Exception {
- connectWithVersion(70001);
- }
-
- private void connectWithVersion(int version) throws Exception {
- VersionMessage peerVersion = new VersionMessage(unitTestParams, OTHER_PEER_CHAIN_HEIGHT);
- peerVersion.clientVersion = version;
- peerVersion.localServices = VersionMessage.NODE_NETWORK;
- writeTarget = connect(peer, peerVersion);
- }
-
- @Test
- public void testAddEventListener() throws Exception {
- connect();
- PeerEventListener listener = new AbstractPeerEventListener();
- peer.addEventListener(listener);
- assertTrue(peer.removeEventListener(listener));
- assertFalse(peer.removeEventListener(listener));
- }
-
- // Check that it runs through the event loop and shut down correctly
- @Test
- public void shutdown() throws Exception {
- closePeer(peer);
- }
-
- @Test
- public void chainDownloadEnd2End() throws Exception {
- // A full end-to-end test of the chain download process, with a new block being solved in the middle.
- Block b1 = createFakeBlock(blockStore).block;
- blockChain.add(b1);
- Block b2 = makeSolvedTestBlock(b1);
- Block b3 = makeSolvedTestBlock(b2);
- Block b4 = makeSolvedTestBlock(b3);
- Block b5 = makeSolvedTestBlock(b4);
-
- connect();
-
- peer.startBlockChainDownload();
- GetBlocksMessage getblocks = (GetBlocksMessage)outbound(writeTarget);
- assertEquals(blockStore.getChainHead().getHeader().getHash(), getblocks.getLocator().get(0));
- assertEquals(Sha256Hash.ZERO_HASH, getblocks.getStopHash());
- // Remote peer sends us an inv with some blocks.
- InventoryMessage inv = new InventoryMessage(unitTestParams);
- inv.addBlock(b2);
- inv.addBlock(b3);
- // We do a getdata on them.
- inbound(writeTarget, inv);
- GetDataMessage getdata = (GetDataMessage)outbound(writeTarget);
- assertEquals(b2.getHash(), getdata.getItems().get(0).hash);
- assertEquals(b3.getHash(), getdata.getItems().get(1).hash);
- assertEquals(2, getdata.getItems().size());
- // Remote peer sends us the blocks. The act of doing a getdata for b3 results in getting an inv with just the
- // best chain head in it.
- inbound(writeTarget, b2);
- inbound(writeTarget, b3);
-
- inv = new InventoryMessage(unitTestParams);
- inv.addBlock(b5);
- // We request the head block.
- inbound(writeTarget, inv);
- getdata = (GetDataMessage)outbound(writeTarget);
- assertEquals(b5.getHash(), getdata.getItems().get(0).hash);
- assertEquals(1, getdata.getItems().size());
- // Peer sends us the head block. The act of receiving the orphan block triggers a getblocks to fill in the
- // rest of the chain.
- inbound(writeTarget, b5);
- getblocks = (GetBlocksMessage)outbound(writeTarget);
- assertEquals(b5.getHash(), getblocks.getStopHash());
- assertEquals(b3.getHash(), getblocks.getLocator().get(0));
- // At this point another block is solved and broadcast. The inv triggers a getdata but we do NOT send another
- // getblocks afterwards, because that would result in us receiving the same set of blocks twice which is a
- // timewaste. The getblocks message that would have been generated is set to be the same as the previous
- // because we walk backwards down the orphan chain and then discover we already asked for those blocks, so
- // nothing is done.
- Block b6 = makeSolvedTestBlock(b5);
- inv = new InventoryMessage(unitTestParams);
- inv.addBlock(b6);
- inbound(writeTarget, inv);
- getdata = (GetDataMessage)outbound(writeTarget);
- assertEquals(1, getdata.getItems().size());
- assertEquals(b6.getHash(), getdata.getItems().get(0).hash);
- inbound(writeTarget, b6);
- assertNull(outbound(writeTarget)); // Nothing is sent at this point.
- // We're still waiting for the response to the getblocks (b3,b5) sent above.
- inv = new InventoryMessage(unitTestParams);
- inv.addBlock(b4);
- inv.addBlock(b5);
- inbound(writeTarget, inv);
- getdata = (GetDataMessage)outbound(writeTarget);
- assertEquals(1, getdata.getItems().size());
- assertEquals(b4.getHash(), getdata.getItems().get(0).hash);
- // We already have b5 from before, so it's not requested again.
- inbound(writeTarget, b4);
- assertNull(outbound(writeTarget));
- // b5 and b6 are now connected by the block chain and we're done.
- assertNull(outbound(writeTarget));
- closePeer(peer);
- }
-
- // Check that an inventory tickle is processed correctly when downloading missing blocks is active.
- @Test
- public void invTickle() throws Exception {
- connect();
-
- Block b1 = createFakeBlock(blockStore).block;
- blockChain.add(b1);
- // Make a missing block.
- Block b2 = makeSolvedTestBlock(b1);
- Block b3 = makeSolvedTestBlock(b2);
- inbound(writeTarget, b3);
- InventoryMessage inv = new InventoryMessage(unitTestParams);
- InventoryItem item = new InventoryItem(InventoryItem.Type.Block, b3.getHash());
- inv.addItem(item);
- inbound(writeTarget, inv);
-
- GetBlocksMessage getblocks = (GetBlocksMessage)outbound(writeTarget);
- List expectedLocator = new ArrayList();
- expectedLocator.add(b1.getHash());
- expectedLocator.add(unitTestParams.getGenesisBlock().getHash());
-
- assertEquals(getblocks.getLocator(), expectedLocator);
- assertEquals(getblocks.getStopHash(), b3.getHash());
- assertNull(outbound(writeTarget));
- }
-
- // Check that an inv to a peer that is not set to download missing blocks does nothing.
- @Test
- public void invNoDownload() throws Exception {
- // Don't download missing blocks.
- peer.setDownloadData(false);
-
- connect();
-
- // Make a missing block that we receive.
- Block b1 = createFakeBlock(blockStore).block;
- blockChain.add(b1);
- Block b2 = makeSolvedTestBlock(b1);
-
- // Receive an inv.
- InventoryMessage inv = new InventoryMessage(unitTestParams);
- InventoryItem item = new InventoryItem(InventoryItem.Type.Block, b2.getHash());
- inv.addItem(item);
- inbound(writeTarget, inv);
-
- // Peer does nothing with it.
- assertNull(outbound(writeTarget));
- }
-
- @Test
- public void invDownloadTx() throws Exception {
- connect();
-
- peer.setDownloadData(true);
- // Make a transaction and tell the peer we have it.
- Coin value = COIN;
- Transaction tx = createFakeTx(unitTestParams, value, address);
- InventoryMessage inv = new InventoryMessage(unitTestParams);
- InventoryItem item = new InventoryItem(InventoryItem.Type.Transaction, tx.getHash());
- inv.addItem(item);
- inbound(writeTarget, inv);
- // Peer hasn't seen it before, so will ask for it.
- GetDataMessage getdata = (GetDataMessage) outbound(writeTarget);
- assertEquals(1, getdata.getItems().size());
- assertEquals(tx.getHash(), getdata.getItems().get(0).hash);
- inbound(writeTarget, tx);
- // Ask for the dependency, it's not in the mempool (in chain).
- getdata = (GetDataMessage) outbound(writeTarget);
- inbound(writeTarget, new NotFoundMessage(unitTestParams, getdata.getItems()));
- pingAndWait(writeTarget);
- assertEquals(value, wallet.getBalance(Wallet.BalanceType.ESTIMATED));
- }
-
- @Test
- public void invDownloadTxMultiPeer() throws Exception {
- // Check co-ordination of which peer to download via the memory pool.
- VersionMessage ver = new VersionMessage(unitTestParams, 100);
- InetSocketAddress address = new InetSocketAddress("127.0.0.1", 4242);
- Peer peer2 = new Peer(unitTestParams, ver, new PeerAddress(address), blockChain);
- peer2.addWallet(wallet);
- VersionMessage peerVersion = new VersionMessage(unitTestParams, OTHER_PEER_CHAIN_HEIGHT);
- peerVersion.clientVersion = 70001;
- peerVersion.localServices = VersionMessage.NODE_NETWORK;
-
- connect();
- InboundMessageQueuer writeTarget2 = connect(peer2, peerVersion);
-
- // Make a tx and advertise it to one of the peers.
- Coin value = COIN;
- Transaction tx = createFakeTx(unitTestParams, value, this.address);
- InventoryMessage inv = new InventoryMessage(unitTestParams);
- InventoryItem item = new InventoryItem(InventoryItem.Type.Transaction, tx.getHash());
- inv.addItem(item);
-
- inbound(writeTarget, inv);
-
- // We got a getdata message.
- GetDataMessage message = (GetDataMessage)outbound(writeTarget);
- assertEquals(1, message.getItems().size());
- assertEquals(tx.getHash(), message.getItems().get(0).hash);
- assertTrue(confidenceTable.maybeWasSeen(tx.getHash()));
-
- // Advertising to peer2 results in no getdata message.
- inbound(writeTarget2, inv);
- pingAndWait(writeTarget2);
- assertNull(outbound(writeTarget2));
- }
-
- // Check that inventory message containing blocks we want is processed correctly.
- @Test
- public void newBlock() throws Exception {
- Block b1 = createFakeBlock(blockStore).block;
- blockChain.add(b1);
- final Block b2 = makeSolvedTestBlock(b1);
- // Receive notification of a new block.
- final InventoryMessage inv = new InventoryMessage(unitTestParams);
- InventoryItem item = new InventoryItem(InventoryItem.Type.Block, b2.getHash());
- inv.addItem(item);
-
- final AtomicInteger newBlockMessagesReceived = new AtomicInteger(0);
-
- connect();
- // Round-trip a ping so that we never see the response verack if we attach too quick
- pingAndWait(writeTarget);
- peer.addEventListener(new AbstractPeerEventListener() {
- @Override
- public synchronized Message onPreMessageReceived(Peer p, Message m) {
- if (p != peer)
- fail.set(true);
- if (m instanceof Pong)
- return m;
- int newValue = newBlockMessagesReceived.incrementAndGet();
- if (newValue == 1 && !inv.equals(m))
- fail.set(true);
- else if (newValue == 2 && !b2.equals(m))
- fail.set(true);
- else if (newValue > 3)
- fail.set(true);
- return m;
- }
-
- @Override
- public synchronized void onBlocksDownloaded(Peer p, Block block, int blocksLeft) {
- int newValue = newBlockMessagesReceived.incrementAndGet();
- if (newValue != 3 || p != peer || !block.equals(b2) || blocksLeft != OTHER_PEER_CHAIN_HEIGHT - 2)
- fail.set(true);
- }
- }, Threading.SAME_THREAD);
- long height = peer.getBestHeight();
-
- inbound(writeTarget, inv);
- pingAndWait(writeTarget);
- assertEquals(height + 1, peer.getBestHeight());
- // Response to the getdata message.
- inbound(writeTarget, b2);
-
- pingAndWait(writeTarget);
- Threading.waitForUserCode();
- pingAndWait(writeTarget);
- assertEquals(3, newBlockMessagesReceived.get());
-
- GetDataMessage getdata = (GetDataMessage) outbound(writeTarget);
- List items = getdata.getItems();
- assertEquals(1, items.size());
- assertEquals(b2.getHash(), items.get(0).hash);
- assertEquals(InventoryItem.Type.Block, items.get(0).type);
- }
-
- // Check that it starts downloading the block chain correctly on request.
- @Test
- public void startBlockChainDownload() throws Exception {
- Block b1 = createFakeBlock(blockStore).block;
- blockChain.add(b1);
- Block b2 = makeSolvedTestBlock(b1);
- blockChain.add(b2);
-
- connect();
- fail.set(true);
- peer.addEventListener(new AbstractPeerEventListener() {
- @Override
- public void onChainDownloadStarted(Peer p, int blocksLeft) {
- if (p == peer && blocksLeft == 108)
- fail.set(false);
- }
- }, Threading.SAME_THREAD);
- peer.startBlockChainDownload();
-
- List expectedLocator = new ArrayList();
- expectedLocator.add(b2.getHash());
- expectedLocator.add(b1.getHash());
- expectedLocator.add(unitTestParams.getGenesisBlock().getHash());
-
- GetBlocksMessage message = (GetBlocksMessage) outbound(writeTarget);
- assertEquals(message.getLocator(), expectedLocator);
- assertEquals(Sha256Hash.ZERO_HASH, message.getStopHash());
- }
-
- @Test
- public void getBlock() throws Exception {
- connect();
-
- Block b1 = createFakeBlock(blockStore).block;
- blockChain.add(b1);
- Block b2 = makeSolvedTestBlock(b1);
- Block b3 = makeSolvedTestBlock(b2);
-
- // Request the block.
- Future resultFuture = peer.getBlock(b3.getHash());
- assertFalse(resultFuture.isDone());
- // Peer asks for it.
- GetDataMessage message = (GetDataMessage) outbound(writeTarget);
- assertEquals(message.getItems().get(0).hash, b3.getHash());
- assertFalse(resultFuture.isDone());
- // Peer receives it.
- inbound(writeTarget, b3);
- Block b = resultFuture.get();
- assertEquals(b, b3);
- }
-
- @Test
- public void getLargeBlock() throws Exception {
- connect();
-
- Block b1 = createFakeBlock(blockStore).block;
- blockChain.add(b1);
- Block b2 = makeSolvedTestBlock(b1);
- Transaction t = new Transaction(unitTestParams);
- t.addInput(b1.getTransactions().get(0).getOutput(0));
- t.addOutput(new TransactionOutput(unitTestParams, t, Coin.ZERO, new byte[Block.MAX_BLOCK_SIZE - 1000]));
- b2.addTransaction(t);
-
- // Request the block.
- Future resultFuture = peer.getBlock(b2.getHash());
- assertFalse(resultFuture.isDone());
- // Peer asks for it.
- GetDataMessage message = (GetDataMessage) outbound(writeTarget);
- assertEquals(message.getItems().get(0).hash, b2.getHash());
- assertFalse(resultFuture.isDone());
- // Peer receives it.
- inbound(writeTarget, b2);
- Block b = resultFuture.get();
- assertEquals(b, b2);
- }
-
- @Test
- public void fastCatchup() throws Exception {
- connect();
- Utils.setMockClock();
- // Check that blocks before the fast catchup point are retrieved using getheaders, and after using getblocks.
- // This test is INCOMPLETE because it does not check we handle >2000 blocks correctly.
- Block b1 = createFakeBlock(blockStore).block;
- blockChain.add(b1);
- Utils.rollMockClock(60 * 10); // 10 minutes later.
- Block b2 = makeSolvedTestBlock(b1);
- b2.setTime(Utils.currentTimeSeconds());
- b2.solve();
- Utils.rollMockClock(60 * 10); // 10 minutes later.
- Block b3 = makeSolvedTestBlock(b2);
- b3.setTime(Utils.currentTimeSeconds());
- b3.solve();
- Utils.rollMockClock(60 * 10);
- Block b4 = makeSolvedTestBlock(b3);
- b4.setTime(Utils.currentTimeSeconds());
- b4.solve();
-
- // Request headers until the last 2 blocks.
- peer.setDownloadParameters(Utils.currentTimeSeconds() - (600*2) + 1, false);
- peer.startBlockChainDownload();
- GetHeadersMessage getheaders = (GetHeadersMessage) outbound(writeTarget);
- List expectedLocator = new ArrayList();
- expectedLocator.add(b1.getHash());
- expectedLocator.add(unitTestParams.getGenesisBlock().getHash());
- assertEquals(getheaders.getLocator(), expectedLocator);
- assertEquals(getheaders.getStopHash(), Sha256Hash.ZERO_HASH);
- // Now send all the headers.
- HeadersMessage headers = new HeadersMessage(unitTestParams, b2.cloneAsHeader(),
- b3.cloneAsHeader(), b4.cloneAsHeader());
- // We expect to be asked for b3 and b4 again, but this time, with a body.
- expectedLocator.clear();
- expectedLocator.add(b2.getHash());
- expectedLocator.add(b1.getHash());
- expectedLocator.add(unitTestParams.getGenesisBlock().getHash());
- inbound(writeTarget, headers);
- GetBlocksMessage getblocks = (GetBlocksMessage) outbound(writeTarget);
- assertEquals(expectedLocator, getblocks.getLocator());
- assertEquals(Sha256Hash.ZERO_HASH, getblocks.getStopHash());
- // We're supposed to get an inv here.
- InventoryMessage inv = new InventoryMessage(unitTestParams);
- inv.addItem(new InventoryItem(InventoryItem.Type.Block, b3.getHash()));
- inbound(writeTarget, inv);
- GetDataMessage getdata = (GetDataMessage) outbound(writeTarget);
- assertEquals(b3.getHash(), getdata.getItems().get(0).hash);
- // All done.
- inbound(writeTarget, b3);
- pingAndWait(writeTarget);
- closePeer(peer);
- }
-
- @Test
- public void pingPong() throws Exception {
- connect();
- Utils.setMockClock();
- // No ping pong happened yet.
- assertEquals(Long.MAX_VALUE, peer.getLastPingTime());
- assertEquals(Long.MAX_VALUE, peer.getPingTime());
- ListenableFuture future = peer.ping();
- assertEquals(Long.MAX_VALUE, peer.getLastPingTime());
- assertEquals(Long.MAX_VALUE, peer.getPingTime());
- assertFalse(future.isDone());
- Ping pingMsg = (Ping) outbound(writeTarget);
- Utils.rollMockClock(5);
- // The pong is returned.
- inbound(writeTarget, new Pong(pingMsg.getNonce()));
- pingAndWait(writeTarget);
- assertTrue(future.isDone());
- long elapsed = future.get();
- assertTrue("" + elapsed, elapsed > 1000);
- assertEquals(elapsed, peer.getLastPingTime());
- assertEquals(elapsed, peer.getPingTime());
- // Do it again and make sure it affects the average.
- future = peer.ping();
- pingMsg = (Ping) outbound(writeTarget);
- Utils.rollMockClock(50);
- inbound(writeTarget, new Pong(pingMsg.getNonce()));
- elapsed = future.get();
- assertEquals(elapsed, peer.getLastPingTime());
- assertEquals(7250, peer.getPingTime());
- }
-
- @Test
- public void recursiveDependencyDownloadDisabled() throws Exception {
- peer.setDownloadTxDependencies(false);
- connect();
- // Check that if we request dependency download to be disabled and receive a relevant tx, things work correctly.
- Transaction tx = FakeTxBuilder.createFakeTx(unitTestParams, COIN, address);
- final Transaction[] result = new Transaction[1];
- wallet.addEventListener(new AbstractWalletEventListener() {
- @Override
- public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
- result[0] = tx;
- }
- });
- inbound(writeTarget, tx);
- pingAndWait(writeTarget);
- assertEquals(tx, result[0]);
- }
-
- @Test
- public void recursiveDependencyDownload() throws Exception {
- // Using ping or notfound?
- connectWithVersion(70001);
- // Check that we can download all dependencies of an unconfirmed relevant transaction from the mempool.
- ECKey to = new ECKey();
-
- final Transaction[] onTx = new Transaction[1];
- peer.addEventListener(new AbstractPeerEventListener() {
- @Override
- public void onTransaction(Peer peer1, Transaction t) {
- onTx[0] = t;
- }
- }, Threading.SAME_THREAD);
-
- // Make the some fake transactions in the following graph:
- // t1 -> t2 -> [t5]
- // -> t3 -> t4 -> [t6]
- // -> [t7]
- // -> [t8]
- // The ones in brackets are assumed to be in the chain and are represented only by hashes.
- Transaction t2 = FakeTxBuilder.createFakeTx(unitTestParams, COIN, to);
- Sha256Hash t5 = t2.getInput(0).getOutpoint().getHash();
- Transaction t4 = FakeTxBuilder.createFakeTx(unitTestParams, COIN, new ECKey());
- Sha256Hash t6 = t4.getInput(0).getOutpoint().getHash();
- t4.addOutput(COIN, new ECKey());
- Transaction t3 = new Transaction(unitTestParams);
- t3.addInput(t4.getOutput(0));
- t3.addOutput(COIN, new ECKey());
- Transaction t1 = new Transaction(unitTestParams);
- t1.addInput(t2.getOutput(0));
- t1.addInput(t3.getOutput(0));
- Sha256Hash someHash = new Sha256Hash("2b801dd82f01d17bbde881687bf72bc62e2faa8ab8133d36fcb8c3abe7459da6");
- t1.addInput(new TransactionInput(unitTestParams, t1, new byte[]{}, new TransactionOutPoint(unitTestParams, 0, someHash)));
- Sha256Hash anotherHash = new Sha256Hash("3b801dd82f01d17bbde881687bf72bc62e2faa8ab8133d36fcb8c3abe7459da6");
- t1.addInput(new TransactionInput(unitTestParams, t1, new byte[]{}, new TransactionOutPoint(unitTestParams, 1, anotherHash)));
- t1.addOutput(COIN, to);
- t1 = FakeTxBuilder.roundTripTransaction(unitTestParams, t1);
- t2 = FakeTxBuilder.roundTripTransaction(unitTestParams, t2);
- t3 = FakeTxBuilder.roundTripTransaction(unitTestParams, t3);
- t4 = FakeTxBuilder.roundTripTransaction(unitTestParams, t4);
-
- // Announce the first one. Wait for it to be downloaded.
- InventoryMessage inv = new InventoryMessage(unitTestParams);
- inv.addTransaction(t1);
- inbound(writeTarget, inv);
- GetDataMessage getdata = (GetDataMessage) outbound(writeTarget);
- Threading.waitForUserCode();
- assertEquals(t1.getHash(), getdata.getItems().get(0).hash);
- inbound(writeTarget, t1);
- pingAndWait(writeTarget);
- assertEquals(t1, onTx[0]);
- // We want its dependencies so ask for them.
- ListenableFuture> futures = peer.downloadDependencies(t1);
- assertFalse(futures.isDone());
- // It will recursively ask for the dependencies of t1: t2, t3, someHash and anotherHash.
- getdata = (GetDataMessage) outbound(writeTarget);
- assertEquals(4, getdata.getItems().size());
- assertEquals(t2.getHash(), getdata.getItems().get(0).hash);
- assertEquals(t3.getHash(), getdata.getItems().get(1).hash);
- assertEquals(someHash, getdata.getItems().get(2).hash);
- assertEquals(anotherHash, getdata.getItems().get(3).hash);
- long nonce = -1;
- // For some random reason, t4 is delivered at this point before it's needed - perhaps it was a Bloom filter
- // false positive. We do this to check that the mempool is being checked for seen transactions before
- // requesting them.
- inbound(writeTarget, t4);
- // Deliver the requested transactions.
- inbound(writeTarget, t2);
- inbound(writeTarget, t3);
- NotFoundMessage notFound = new NotFoundMessage(unitTestParams);
- notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, someHash));
- notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, anotherHash));
- inbound(writeTarget, notFound);
- assertFalse(futures.isDone());
- // It will recursively ask for the dependencies of t2: t5 and t4, but not t3 because it already found t4.
- getdata = (GetDataMessage) outbound(writeTarget);
- assertEquals(getdata.getItems().get(0).hash, t2.getInput(0).getOutpoint().getHash());
- // t5 isn't found and t4 is.
- notFound = new NotFoundMessage(unitTestParams);
- notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, t5));
- inbound(writeTarget, notFound);
- assertFalse(futures.isDone());
- // Continue to explore the t4 branch and ask for t6, which is in the chain.
- getdata = (GetDataMessage) outbound(writeTarget);
- assertEquals(t6, getdata.getItems().get(0).hash);
- notFound = new NotFoundMessage(unitTestParams);
- notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, t6));
- inbound(writeTarget, notFound);
- pingAndWait(writeTarget);
- // That's it, we explored the entire tree.
- assertTrue(futures.isDone());
- List results = futures.get();
- assertTrue(results.contains(t2));
- assertTrue(results.contains(t3));
- assertTrue(results.contains(t4));
- }
-
- @Test
- public void timeLockedTransactionNew() throws Exception {
- connectWithVersion(70001);
- // Test that if we receive a relevant transaction that has a lock time, it doesn't result in a notification
- // until we explicitly opt in to seeing those.
- Wallet wallet = new Wallet(unitTestParams);
- ECKey key = wallet.freshReceiveKey();
- peer.addWallet(wallet);
- final Transaction[] vtx = new Transaction[1];
- wallet.addEventListener(new AbstractWalletEventListener() {
- @Override
- public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
- vtx[0] = tx;
- }
- });
- // Send a normal relevant transaction, it's received correctly.
- Transaction t1 = FakeTxBuilder.createFakeTx(unitTestParams, COIN, key);
- inbound(writeTarget, t1);
- GetDataMessage getdata = (GetDataMessage) outbound(writeTarget);
- inbound(writeTarget, new NotFoundMessage(unitTestParams, getdata.getItems()));
- pingAndWait(writeTarget);
- Threading.waitForUserCode();
- assertNotNull(vtx[0]);
- vtx[0] = null;
- // Send a timelocked transaction, nothing happens.
- Transaction t2 = FakeTxBuilder.createFakeTx(unitTestParams, valueOf(2, 0), key);
- t2.setLockTime(999999);
- inbound(writeTarget, t2);
- Threading.waitForUserCode();
- assertNull(vtx[0]);
- // Now we want to hear about them. Send another, we are told about it.
- wallet.setAcceptRiskyTransactions(true);
- inbound(writeTarget, t2);
- getdata = (GetDataMessage) outbound(writeTarget);
- inbound(writeTarget, new NotFoundMessage(unitTestParams, getdata.getItems()));
- pingAndWait(writeTarget);
- Threading.waitForUserCode();
- assertEquals(t2, vtx[0]);
- }
-
- @Test
- public void rejectTimeLockedDependency() throws Exception {
- // Check that we also verify the lock times of dependencies. Otherwise an attacker could still build a tx that
- // looks legitimate and useful but won't actually ever confirm, by sending us a normal tx that spends a
- // timelocked tx.
- checkTimeLockedDependency(false);
- }
-
- @Test
- public void acceptTimeLockedDependency() throws Exception {
- checkTimeLockedDependency(true);
- }
-
- private void checkTimeLockedDependency(boolean shouldAccept) throws Exception {
- // Initial setup.
- connectWithVersion(70001);
- Wallet wallet = new Wallet(unitTestParams);
- ECKey key = wallet.freshReceiveKey();
- wallet.setAcceptRiskyTransactions(shouldAccept);
- peer.addWallet(wallet);
- final Transaction[] vtx = new Transaction[1];
- wallet.addEventListener(new AbstractWalletEventListener() {
- @Override
- public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
- vtx[0] = tx;
- }
- });
- // t1 -> t2 [locked] -> t3 (not available)
- Transaction t2 = new Transaction(unitTestParams);
- t2.setLockTime(999999);
- // Add a fake input to t3 that goes nowhere.
- Sha256Hash t3 = Sha256Hash.create("abc".getBytes(Charset.forName("UTF-8")));
- t2.addInput(new TransactionInput(unitTestParams, t2, new byte[]{}, new TransactionOutPoint(unitTestParams, 0, t3)));
- t2.getInput(0).setSequenceNumber(0xDEADBEEF);
- t2.addOutput(COIN, new ECKey());
- Transaction t1 = new Transaction(unitTestParams);
- t1.addInput(t2.getOutput(0));
- t1.addOutput(COIN, key); // Make it relevant.
- // Announce t1.
- InventoryMessage inv = new InventoryMessage(unitTestParams);
- inv.addTransaction(t1);
- inbound(writeTarget, inv);
- // Send it.
- GetDataMessage getdata = (GetDataMessage) outbound(writeTarget);
- assertEquals(t1.getHash(), getdata.getItems().get(0).hash);
- inbound(writeTarget, t1);
- // Nothing arrived at our event listener yet.
- assertNull(vtx[0]);
- // We request t2.
- getdata = (GetDataMessage) outbound(writeTarget);
- assertEquals(t2.getHash(), getdata.getItems().get(0).hash);
- inbound(writeTarget, t2);
- // We request t3.
- getdata = (GetDataMessage) outbound(writeTarget);
- assertEquals(t3, getdata.getItems().get(0).hash);
- // Can't find it: bottom of tree.
- NotFoundMessage notFound = new NotFoundMessage(unitTestParams);
- notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction, t3));
- inbound(writeTarget, notFound);
- pingAndWait(writeTarget);
- Threading.waitForUserCode();
- // We're done but still not notified because it was timelocked.
- if (shouldAccept)
- assertNotNull(vtx[0]);
- else
- assertNull(vtx[0]);
- }
-
- @Test
- public void disconnectOldVersions1() throws Exception {
- // Set up the connection with an old version.
- final SettableFuture connectedFuture = SettableFuture.create();
- final SettableFuture disconnectedFuture = SettableFuture.create();
- peer.addEventListener(new AbstractPeerEventListener() {
- @Override
- public void onPeerConnected(Peer peer, int peerCount) {
- connectedFuture.set(null);
- }
-
- @Override
- public void onPeerDisconnected(Peer peer, int peerCount) {
- disconnectedFuture.set(null);
- }
- });
- connectWithVersion(500);
- // We must wait uninterruptibly here because connect[WithVersion] generates a peer that interrupts the current
- // thread when it disconnects.
- Uninterruptibles.getUninterruptibly(connectedFuture);
- Uninterruptibles.getUninterruptibly(disconnectedFuture);
- try {
- peer.writeTarget.writeBytes(new byte[1]);
- fail();
- } catch (IOException e) {
- assertTrue((e.getCause() != null && e.getCause() instanceof CancelledKeyException)
- || (e instanceof SocketException && e.getMessage().equals("Socket is closed")));
- }
- }
-
- @Test
- public void exceptionListener() throws Exception {
- wallet.addEventListener(new AbstractWalletEventListener() {
- @Override
- public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
- throw new NullPointerException("boo!");
- }
- });
- final Throwable[] throwables = new Throwable[1];
- Threading.uncaughtExceptionHandler = new Thread.UncaughtExceptionHandler() {
- @Override
- public void uncaughtException(Thread thread, Throwable throwable) {
- throwables[0] = throwable;
- }
- };
- // In real usage we're not really meant to adjust the uncaught exception handler after stuff started happening
- // but in the unit test environment other tests have just run so the thread is probably still kicking around.
- // Force it to crash so it'll be recreated with our new handler.
- Threading.USER_THREAD.execute(new Runnable() {
- @Override
- public void run() {
- throw new RuntimeException();
- }
- });
- connect();
- Transaction t1 = new Transaction(unitTestParams);
- t1.addInput(new TransactionInput(unitTestParams, t1, new byte[]{}));
- t1.addOutput(COIN, new ECKey().toAddress(unitTestParams));
- Transaction t2 = new Transaction(unitTestParams);
- t2.addInput(t1.getOutput(0));
- t2.addOutput(COIN, wallet.getChangeAddress());
- inbound(writeTarget, t2);
- final InventoryItem inventoryItem = new InventoryItem(InventoryItem.Type.Transaction, t2.getInput(0).getOutpoint().getHash());
- final NotFoundMessage nfm = new NotFoundMessage(unitTestParams, Lists.newArrayList(inventoryItem));
- inbound(writeTarget, nfm);
- pingAndWait(writeTarget);
- Threading.waitForUserCode();
- assertTrue(throwables[0] instanceof NullPointerException);
- Threading.uncaughtExceptionHandler = null;
- }
-
- @Test
- public void badMessage() throws Exception {
- // Bring up an actual network connection and feed it bogus data.
- final SettableFuture result = SettableFuture.create();
- Threading.uncaughtExceptionHandler = new Thread.UncaughtExceptionHandler() {
- @Override
- public void uncaughtException(Thread thread, Throwable throwable) {
- result.setException(throwable);
- }
- };
- connect(); // Writes out a verack+version.
- final SettableFuture peerDisconnected = SettableFuture.create();
- writeTarget.peer.addEventListener(new AbstractPeerEventListener() {
- @Override
- public void onPeerDisconnected(Peer p, int peerCount) {
- peerDisconnected.set(null);
- }
- });
- final NetworkParameters params = TestNet3Params.get();
- BitcoinSerializer serializer = new BitcoinSerializer(params);
- // Now write some bogus truncated message.
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- serializer.serialize("inv", new InventoryMessage(params) {
- @Override
- public void bitcoinSerializeToStream(OutputStream stream) throws IOException {
- // Add some hashes.
- addItem(new InventoryItem(InventoryItem.Type.Transaction, Sha256Hash.create(new byte[] { 1 })));
- addItem(new InventoryItem(InventoryItem.Type.Transaction, Sha256Hash.create(new byte[] { 2 })));
- addItem(new InventoryItem(InventoryItem.Type.Transaction, Sha256Hash.create(new byte[] { 3 })));
-
- // Write out a copy that's truncated in the middle.
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- super.bitcoinSerializeToStream(bos);
- byte[] bits = bos.toByteArray();
- bits = Arrays.copyOf(bits, bits.length / 2);
- stream.write(bits);
- }
- }.bitcoinSerialize(), out);
- writeTarget.writeTarget.writeBytes(out.toByteArray());
- try {
- result.get();
- fail();
- } catch (ExecutionException e) {
- assertTrue(e.getCause() instanceof ProtocolException);
- }
- peerDisconnected.get();
- try {
- peer.writeTarget.writeBytes(new byte[1]);
- fail();
- } catch (IOException e) {
- assertTrue((e.getCause() != null && e.getCause() instanceof CancelledKeyException)
- || (e instanceof SocketException && e.getMessage().equals("Socket is closed")));
- }
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/PostgresFullPrunedBlockChainTest.java b/core/src/test/java/com/dogecoin/dogecoinj/core/PostgresFullPrunedBlockChainTest.java
deleted file mode 100644
index c614f425..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/PostgresFullPrunedBlockChainTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.dogecoin.dogecoinj.core;
-
-import com.dogecoin.dogecoinj.store.BlockStoreException;
-import com.dogecoin.dogecoinj.store.FullPrunedBlockStore;
-import com.dogecoin.dogecoinj.store.PostgresFullPrunedBlockStore;
-import org.junit.After;
-import org.junit.Ignore;
-import org.junit.Test;
-
-/**
- * A Postgres implementation of the {@link AbstractFullPrunedBlockChainTest}
- */
-@Ignore("enable the postgres driver dependency in the maven POM")
-public class PostgresFullPrunedBlockChainTest extends AbstractFullPrunedBlockChainTest
-{
- // Replace these with your postgres location/credentials and remove @Ignore to test
- // You can set up a fresh postgres with the command: create user bitcoinj superuser password 'password';
- private static final String DB_HOSTNAME = "localhost";
- private static final String DB_NAME = "dogecoinj_test";
- private static final String DB_USERNAME = "dogecoinj";
- private static final String DB_PASSWORD = "password";
- private static final String DB_SCHEMA = "blockstore_schema";
-
- // whether to run the test with a schema name
- private boolean useSchema = false;
-
- @After
- public void tearDown() throws Exception {
- ((PostgresFullPrunedBlockStore)store).deleteStore();
- }
-
- @Override
- public FullPrunedBlockStore createStore(NetworkParameters params, int blockCount)
- throws BlockStoreException {
- if(useSchema) {
- return new PostgresFullPrunedBlockStore(params, blockCount, DB_HOSTNAME, DB_NAME, DB_USERNAME, DB_PASSWORD, DB_SCHEMA);
- }
- else {
- return new PostgresFullPrunedBlockStore(params, blockCount, DB_HOSTNAME, DB_NAME, DB_USERNAME, DB_PASSWORD);
- }
- }
-
- @Override
- public void resetStore(FullPrunedBlockStore store) throws BlockStoreException {
- ((PostgresFullPrunedBlockStore)store).resetStore();
- }
-
- @Test
- public void testFirst100kBlocksWithCustomSchema() throws Exception {
- boolean oldSchema = useSchema;
- useSchema = true;
- try {
- super.testFirst100KBlocks();
- } finally {
- useSchema = oldSchema;
- }
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/TransactionOutputTest.java b/core/src/test/java/com/dogecoin/dogecoinj/core/TransactionOutputTest.java
deleted file mode 100644
index 95d8525a..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/TransactionOutputTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package com.dogecoin.dogecoinj.core;
-
-import com.google.common.collect.ImmutableList;
-import com.dogecoin.dogecoinj.params.MainNetParams;
-import com.dogecoin.dogecoinj.script.Script;
-import com.dogecoin.dogecoinj.script.ScriptBuilder;
-import com.dogecoin.dogecoinj.script.ScriptOpCodes;
-import com.dogecoin.dogecoinj.testing.TestWithWallet;
-import org.hamcrest.CoreMatchers;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-public class TransactionOutputTest extends TestWithWallet {
-
- @Before
- public void setUp() throws Exception {
- super.setUp();
- }
-
- @After
- public void tearDown() throws Exception {
- super.tearDown();
- }
-
- @Test
- public void testMultiSigOutputToString() throws Exception {
- sendMoneyToWallet(Coin.COIN, AbstractBlockChain.NewBlockType.BEST_CHAIN);
- ECKey myKey = new ECKey();
- this.wallet.importKey(myKey);
-
- // Simulate another signatory
- ECKey otherKey = new ECKey();
-
- // Create multi-sig transaction
- Transaction multiSigTransaction = new Transaction(params);
- ImmutableList keys = ImmutableList.of(myKey, otherKey);
-
- Script scriptPubKey = ScriptBuilder.createMultiSigOutputScript(2, keys);
- multiSigTransaction.addOutput(Coin.COIN, scriptPubKey);
-
- Wallet.SendRequest req = Wallet.SendRequest.forTx(multiSigTransaction);
- this.wallet.completeTx(req);
- TransactionOutput multiSigTransactionOutput = multiSigTransaction.getOutput(0);
-
- assertThat(multiSigTransactionOutput.toString(), CoreMatchers.containsString("CHECKMULTISIG"));
- }
-
- @Test
- public void testP2SHOutputScript() throws Exception {
- String P2SHAddressString = "35b9vsyH1KoFT5a5KtrKusaCcPLkiSo1tU";
- Address P2SHAddress = new Address(MainNetParams.get(), P2SHAddressString);
- Script script = ScriptBuilder.createOutputScript(P2SHAddress);
- Transaction tx = new Transaction(MainNetParams.get());
- tx.addOutput(Coin.COIN, script);
- assertEquals(P2SHAddressString, tx.getOutput(0).getAddressFromP2SH(MainNetParams.get()).toString());
- }
-
- @Test
- public void getAddressTests() throws Exception {
- Transaction tx = new Transaction(MainNetParams.get());
- Script script = new ScriptBuilder().op(ScriptOpCodes.OP_RETURN).data("hello world!".getBytes()).build();
- tx.addOutput(Coin.CENT, script);
- assertNull(tx.getOutput(0).getAddressFromP2SH(params));
- assertNull(tx.getOutput(0).getAddressFromP2PKHScript(params));
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/TransactionTest.java b/core/src/test/java/com/dogecoin/dogecoinj/core/TransactionTest.java
deleted file mode 100644
index 0f69727a..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/TransactionTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package com.dogecoin.dogecoinj.core;
-
-import com.dogecoin.dogecoinj.params.UnitTestParams;
-import com.dogecoin.dogecoinj.script.ScriptBuilder;
-import com.dogecoin.dogecoinj.testing.FakeTxBuilder;
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- * Just check the Transaction.verify() method. Most methods that have complicated logic in Transaction are tested
- * elsewhere, e.g. signing and hashing are well exercised by the wallet tests, the full block chain tests and so on.
- * The verify method is also exercised by the full block chain tests, but it can also be used by API users alone,
- * so we make sure to cover it here as well.
- */
-public class TransactionTest {
- private static final NetworkParameters PARAMS = UnitTestParams.get();
- private Transaction tx;
- private Transaction dummy;
-
- public static final Address ADDRESS = new ECKey().toAddress(PARAMS);
-
- @Before
- public void setUp() throws Exception {
- dummy = FakeTxBuilder.createFakeTx(PARAMS, Coin.COIN, ADDRESS);
- tx = new Transaction(PARAMS);
- tx.addOutput(Coin.COIN, ADDRESS);
- tx.addInput(dummy.getOutput(0));
- }
-
- @Test(expected = VerificationException.EmptyInputsOrOutputs.class)
- public void emptyOutputs() throws Exception {
- tx.clearOutputs();
- tx.verify();
- }
-
- @Test(expected = VerificationException.EmptyInputsOrOutputs.class)
- public void emptyInputs() throws Exception {
- tx.clearInputs();
- tx.verify();
- }
-
- @Test(expected = VerificationException.LargerThanMaxBlockSize.class)
- public void tooHuge() throws Exception {
- tx.addInput(dummy.getOutput(0)).setScriptBytes(new byte[Block.MAX_BLOCK_SIZE]);
- tx.verify();
- }
-
- @Test(expected = VerificationException.DuplicatedOutPoint.class)
- public void duplicateOutPoint() throws Exception {
- TransactionInput input = tx.getInput(0);
- input.setScriptBytes(new byte[1]);
- tx.addInput(input.duplicateDetached());
- tx.verify();
- }
-
- @Test(expected = VerificationException.NegativeValueOutput.class)
- public void negativeOutput() throws Exception {
- tx.getOutput(0).setValue(Coin.NEGATIVE_SATOSHI);
- tx.verify();
- }
-
- @Test(expected = VerificationException.ExcessiveValue.class)
- public void exceedsMaxMoney2() throws Exception {
- Coin half = NetworkParameters.MAX_MONEY.divide(2).add(Coin.SATOSHI);
- tx.getOutput(0).setValue(half);
- tx.addOutput(half, ADDRESS);
- tx.verify();
- }
-
- @Test(expected = VerificationException.UnexpectedCoinbaseInput.class)
- public void coinbaseInputInNonCoinbaseTX() throws Exception {
- tx.addInput(Sha256Hash.ZERO_HASH, 0xFFFFFFFFL, new ScriptBuilder().data(new byte[10]).build());
- tx.verify();
- }
-
- @Test(expected = VerificationException.CoinbaseScriptSizeOutOfRange.class)
- public void coinbaseScriptSigTooSmall() throws Exception {
- tx.clearInputs();
- tx.addInput(Sha256Hash.ZERO_HASH, 0xFFFFFFFFL, new ScriptBuilder().build());
- tx.verify();
- }
-
- @Test(expected = VerificationException.CoinbaseScriptSizeOutOfRange.class)
- public void coinbaseScriptSigTooLarge() throws Exception {
- tx.clearInputs();
- TransactionInput input = tx.addInput(Sha256Hash.ZERO_HASH, 0xFFFFFFFFL, new ScriptBuilder().data(new byte[99]).build());
- assertEquals(101, input.getScriptBytes().length);
- tx.verify();
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/UtilsTest.java b/core/src/test/java/com/dogecoin/dogecoinj/core/UtilsTest.java
deleted file mode 100644
index 8bd7f097..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/UtilsTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * Copyright 2011 Thilo Planz
- * 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 com.dogecoin.dogecoinj.core;
-
-import java.math.BigInteger;
-import java.util.Date;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-
-public class UtilsTest {
-
- @Test
- public void testReverseBytes() {
- assertArrayEquals(new byte[]{1, 2, 3, 4, 5}, Utils.reverseBytes(new byte[]{5, 4, 3, 2, 1}));
- }
-
- @Test
- public void testReverseDwordBytes() {
- assertArrayEquals(new byte[]{1, 2, 3, 4, 5, 6, 7, 8}, Utils.reverseDwordBytes(new byte[]{4, 3, 2, 1, 8, 7, 6, 5}, -1));
- assertArrayEquals(new byte[]{1, 2, 3, 4}, Utils.reverseDwordBytes(new byte[]{4, 3, 2, 1, 8, 7, 6, 5}, 4));
- assertArrayEquals(new byte[0], Utils.reverseDwordBytes(new byte[]{4, 3, 2, 1, 8, 7, 6, 5}, 0));
- assertArrayEquals(new byte[0], Utils.reverseDwordBytes(new byte[0], 0));
- }
-
- @Test
- public void testMaxOfMostFreq() throws Exception {
- assertEquals(0, Utils.maxOfMostFreq());
- assertEquals(0, Utils.maxOfMostFreq(0, 0, 1));
- assertEquals(2, Utils.maxOfMostFreq(1, 1, 2, 2));
- assertEquals(1, Utils.maxOfMostFreq(1, 1, 2, 2, 1));
- assertEquals(-1, Utils.maxOfMostFreq(-1, -1, 2, 2, -1));
- }
-
- @Test
- public void compactEncoding() throws Exception {
- assertEquals(new BigInteger("1234560000", 16), Utils.decodeCompactBits(0x05123456L));
- assertEquals(new BigInteger("c0de000000", 16), Utils.decodeCompactBits(0x0600c0de));
- assertEquals(0x05123456L, Utils.encodeCompactBits(new BigInteger("1234560000", 16)));
- assertEquals(0x0600c0deL, Utils.encodeCompactBits(new BigInteger("c0de000000", 16)));
- }
-
- @Test
- public void dateTimeFormat() {
- assertEquals("2014-11-16T10:54:33Z", Utils.dateTimeFormat(1416135273781L));
- assertEquals("2014-11-16T10:54:33Z", Utils.dateTimeFormat(new Date(1416135273781L)));
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/VarIntTest.java b/core/src/test/java/com/dogecoin/dogecoinj/core/VarIntTest.java
deleted file mode 100644
index f77b3a73..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/VarIntTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * Copyright 2011 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 com.dogecoin.dogecoinj.core;
-
-import junit.framework.TestCase;
-
-public class VarIntTest extends TestCase {
- public void testBytes() throws Exception {
- VarInt a = new VarInt(10);
- assertEquals(1, a.getSizeInBytes());
- assertEquals(1, a.encode().length);
- assertEquals(10, new VarInt(a.encode(), 0).value);
- }
-
- public void testShorts() throws Exception {
- VarInt a = new VarInt(64000);
- assertEquals(3, a.getSizeInBytes());
- assertEquals(3, a.encode().length);
- assertEquals(64000, new VarInt(a.encode(), 0).value);
- }
-
- public void testShortFFFF() throws Exception {
- VarInt a = new VarInt(0xFFFFL);
- assertEquals(3, a.getSizeInBytes());
- assertEquals(3, a.encode().length);
- assertEquals(0xFFFFL, new VarInt(a.encode(), 0).value);
- }
-
- public void testInts() throws Exception {
- VarInt a = new VarInt(0xAABBCCDDL);
- assertEquals(5, a.getSizeInBytes());
- assertEquals(5, a.encode().length);
- byte[] bytes = a.encode();
- assertEquals(0xAABBCCDDL, 0xFFFFFFFFL & new VarInt(bytes, 0).value);
- }
-
- public void testIntFFFFFFFF() throws Exception {
- VarInt a = new VarInt(0xFFFFFFFFL);
- assertEquals(5, a.getSizeInBytes());
- assertEquals(5, a.encode().length);
- byte[] bytes = a.encode();
- assertEquals(0xFFFFFFFFL, 0xFFFFFFFFL & new VarInt(bytes, 0).value);
- }
-
- public void testLong() throws Exception {
- VarInt a = new VarInt(0xCAFEBABEDEADBEEFL);
- assertEquals(9, a.getSizeInBytes());
- assertEquals(9, a.encode().length);
- byte[] bytes = a.encode();
- assertEquals(0xCAFEBABEDEADBEEFL, new VarInt(bytes, 0).value);
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/VersionMessageTest.java b/core/src/test/java/com/dogecoin/dogecoinj/core/VersionMessageTest.java
deleted file mode 100644
index 13e69342..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/VersionMessageTest.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2012 Matt Corallo
- * 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 com.dogecoin.dogecoinj.core;
-
-import com.dogecoin.dogecoinj.params.UnitTestParams;
-import org.junit.Test;
-
-import static com.dogecoin.dogecoinj.core.Utils.HEX;
-import static org.junit.Assert.assertTrue;
-
-public class VersionMessageTest {
- @Test
- // Test that we can decode version messages which miss data which some old nodes may not include
- public void testDecode() throws Exception {
- NetworkParameters params = UnitTestParams.get();
-
- VersionMessage ver = new VersionMessage(params, HEX.decode("71110100000000000000000048e5e95000000000000000000000000000000000000000000000ffff7f000001479d000000000000000000000000000000000000ffff7f000001479d0000000000000000172f426974436f696e4a3a302e372d534e415053484f542f0004000000"));
- assertTrue(!ver.relayTxesBeforeFilter);
- assertTrue(ver.bestHeight == 1024);
- assertTrue(ver.subVer.equals("/BitCoinJ:0.7-SNAPSHOT/"));
-
- ver = new VersionMessage(params, HEX.decode("71110100000000000000000048e5e95000000000000000000000000000000000000000000000ffff7f000001479d000000000000000000000000000000000000ffff7f000001479d0000000000000000172f426974436f696e4a3a302e372d534e415053484f542f00040000"));
- assertTrue(ver.relayTxesBeforeFilter);
- assertTrue(ver.bestHeight == 1024);
- assertTrue(ver.subVer.equals("/BitCoinJ:0.7-SNAPSHOT/"));
-
- ver = new VersionMessage(params, HEX.decode("71110100000000000000000048e5e95000000000000000000000000000000000000000000000ffff7f000001479d000000000000000000000000000000000000ffff7f000001479d0000000000000000172f426974436f696e4a3a302e372d534e415053484f542f"));
- assertTrue(ver.relayTxesBeforeFilter);
- assertTrue(ver.bestHeight == 0);
- assertTrue(ver.subVer.equals("/BitCoinJ:0.7-SNAPSHOT/"));
-
- ver = new VersionMessage(params, HEX.decode("71110100000000000000000048e5e95000000000000000000000000000000000000000000000ffff7f000001479d000000000000000000000000000000000000ffff7f000001479d0000000000000000"));
- assertTrue(ver.relayTxesBeforeFilter);
- assertTrue(ver.bestHeight == 0);
- assertTrue(ver.subVer.equals(""));
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/core/WalletExtensionsTest.java b/core/src/test/java/com/dogecoin/dogecoinj/core/WalletExtensionsTest.java
deleted file mode 100644
index 3d8ccaf2..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/core/WalletExtensionsTest.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.dogecoin.dogecoinj.core;
-
-import com.dogecoin.dogecoinj.testing.FooWalletExtension;
-import com.dogecoin.dogecoinj.testing.TestWithWallet;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class WalletExtensionsTest extends TestWithWallet {
-
- @Before
- @Override
- public void setUp() throws Exception {
- super.setUp();
- }
-
- @After
- @Override
- public void tearDown() throws Exception {
- super.tearDown();
- }
-
- @Test(expected = java.lang.IllegalStateException.class)
- public void duplicateWalletExtensionTest() {
- wallet.addExtension(new FooWalletExtension("com.whatever.required", true));
- wallet.addExtension(new FooWalletExtension("com.whatever.required", true));
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/crypto/BIP32Test.java b/core/src/test/java/com/dogecoin/dogecoinj/crypto/BIP32Test.java
deleted file mode 100644
index 962d3221..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/crypto/BIP32Test.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/**
- * Copyright 2013 Matija Mazi.
- * 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 com.dogecoin.dogecoinj.crypto;
-
-import com.dogecoin.dogecoinj.core.AddressFormatException;
-import com.dogecoin.dogecoinj.core.Base58;
-import com.google.common.base.Functions;
-import com.google.common.base.Joiner;
-import com.google.common.collect.Iterables;
-import com.dogecoin.dogecoinj.core.NetworkParameters;
-import com.dogecoin.dogecoinj.params.MainNetParams;
-import com.dogecoin.dogecoinj.params.UnitTestParams;
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Arrays;
-import java.util.List;
-
-import static com.dogecoin.dogecoinj.core.Utils.HEX;
-import static org.junit.Assert.assertEquals;
-
-/**
- * A test with test vectors as per BIP 32 spec: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#Test_Vectors
- */
-public class BIP32Test {
- private static final Logger log = LoggerFactory.getLogger(BIP32Test.class);
-
- HDWTestVector[] tvs = {
- new HDWTestVector(
- "000102030405060708090a0b0c0d0e0f",
- "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi",
- "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8",
- Arrays.asList(
- new HDWTestVector.DerivedTestCase(
- "Test1 m/0H",
- new ChildNumber[]{new ChildNumber(0, true)},
- "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7",
- "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw"
- ),
- new HDWTestVector.DerivedTestCase(
- "Test1 m/0H/1",
- new ChildNumber[]{new ChildNumber(0, true), new ChildNumber(1, false)},
- "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs",
- "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ"
- ),
- new HDWTestVector.DerivedTestCase(
- "Test1 m/0H/1/2H",
- new ChildNumber[]{new ChildNumber(0, true), new ChildNumber(1, false), new ChildNumber(2, true)},
- "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM",
- "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5"
- ),
- new HDWTestVector.DerivedTestCase(
- "Test1 m/0H/1/2H/2",
- new ChildNumber[]{new ChildNumber(0, true), new ChildNumber(1, false), new ChildNumber(2, true), new ChildNumber(2, false)},
- "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334",
- "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV"
- ),
- new HDWTestVector.DerivedTestCase(
- "Test1 m/0H/1/2H/2/1000000000",
- new ChildNumber[]{new ChildNumber(0, true), new ChildNumber(1, false), new ChildNumber(2, true), new ChildNumber(2, false), new ChildNumber(1000000000, false)},
- "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76",
- "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy"
- )
- )
- ),
- new HDWTestVector(
- "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542",
- "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U",
- "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB",
- Arrays.asList(
- new HDWTestVector.DerivedTestCase(
- "Test2 m/0",
- new ChildNumber[]{new ChildNumber(0, false)},
- "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt",
- "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH"
- ),
- new HDWTestVector.DerivedTestCase(
- "Test2 m/0/2147483647H",
- new ChildNumber[]{new ChildNumber(0, false), new ChildNumber(2147483647, true)},
- "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9",
- "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a"
- ),
- new HDWTestVector.DerivedTestCase(
- "Test2 m/0/2147483647H/1",
- new ChildNumber[]{new ChildNumber(0, false), new ChildNumber(2147483647, true), new ChildNumber(1, false)},
- "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef",
- "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon"
- ),
- new HDWTestVector.DerivedTestCase(
- "Test2 m/0/2147483647H/1/2147483646H",
- new ChildNumber[]{new ChildNumber(0, false), new ChildNumber(2147483647, true), new ChildNumber(1, false), new ChildNumber(2147483646, true)},
- "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc",
- "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL"
- ),
- new HDWTestVector.DerivedTestCase(
- "Test2 m/0/2147483647H/1/2147483646H/2",
- new ChildNumber[]{new ChildNumber(0, false), new ChildNumber(2147483647, true), new ChildNumber(1, false), new ChildNumber(2147483646, true), new ChildNumber(2, false)},
- "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j",
- "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt"
- )
- )
- )
- };
-
- @Test
- public void testVector1() throws Exception {
- testVector(0);
- }
-
- @Test
- public void testVector2() throws Exception {
- testVector(1);
- }
-
- private void testVector(int testCase) throws AddressFormatException {
- log.info("======= Test vector {}", testCase);
- HDWTestVector tv = tvs[testCase];
- NetworkParameters params = MainNetParams.get();
- DeterministicKey masterPrivateKey = HDKeyDerivation.createMasterPrivateKey(HEX.decode(tv.seed));
- assertEquals(testEncode(tv.priv), testEncode(masterPrivateKey.serializePrivB58(params)));
- assertEquals(testEncode(tv.pub), testEncode(masterPrivateKey.serializePubB58(params)));
- DeterministicHierarchy dh = new DeterministicHierarchy(masterPrivateKey);
- for (int i = 0; i < tv.derived.size(); i++) {
- HDWTestVector.DerivedTestCase tc = tv.derived.get(i);
- log.info("{}", tc.name);
- assertEquals(tc.name, String.format("Test%d %s", testCase + 1, tc.getPathDescription()));
- int depth = tc.path.length - 1;
- DeterministicKey ehkey = dh.deriveChild(Arrays.asList(tc.path).subList(0, depth), false, true, tc.path[depth]);
- assertEquals(testEncode(tc.priv), testEncode(ehkey.serializePrivB58(params)));
- assertEquals(testEncode(tc.pub), testEncode(ehkey.serializePubB58(params)));
- }
- }
-
- private String testEncode(String what) throws AddressFormatException {
- return HEX.encode(Base58.decodeChecked(what));
- }
-
- static class HDWTestVector {
- final String seed;
- final String priv;
- final String pub;
- final List derived;
-
- HDWTestVector(String seed, String priv, String pub, List derived) {
- this.seed = seed;
- this.priv = priv;
- this.pub = pub;
- this.derived = derived;
- }
-
- static class DerivedTestCase {
- final String name;
- final ChildNumber[] path;
- final String pub;
- final String priv;
-
- DerivedTestCase(String name, ChildNumber[] path, String priv, String pub) {
- this.name = name;
- this.path = path;
- this.pub = pub;
- this.priv = priv;
- }
-
- String getPathDescription() {
- return "m/" + Joiner.on("/").join(Iterables.transform(Arrays.asList(path), Functions.toStringFunction()));
- }
- }
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/crypto/BIP38PrivateKeyTest.java b/core/src/test/java/com/dogecoin/dogecoinj/crypto/BIP38PrivateKeyTest.java
deleted file mode 100644
index 4c9336bc..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/crypto/BIP38PrivateKeyTest.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * 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 com.dogecoin.dogecoinj.crypto;
-
-import com.dogecoin.dogecoinj.core.ECKey;
-import com.dogecoin.dogecoinj.crypto.BIP38PrivateKey.BadPassphraseException;
-import com.dogecoin.dogecoinj.params.MainNetParams;
-import com.dogecoin.dogecoinj.params.TestNet3Params;
-import org.junit.Test;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotSame;
-
-public class BIP38PrivateKeyTest {
-
- private static final MainNetParams MAINNET = MainNetParams.get();
- private static final TestNet3Params TESTNET = TestNet3Params.get();
-
- @Test
- public void bip38testvector_noCompression_noEcMultiply_test1() throws Exception {
- BIP38PrivateKey encryptedKey = new BIP38PrivateKey(MAINNET,
- "6PRVWUbkzzsbcVac2qwfssoUJAN1Xhrg6bNk8J7Nzm5H7kxEbn2Nh2ZoGg");
- ECKey key = encryptedKey.decrypt("TestingOneTwoThree");
- assertEquals("5KN7MzqK5wt2TP1fQCYyHBtDrXdJuXbUzm4A9rKAteGu3Qi5CVR", key.getPrivateKeyEncoded(MAINNET)
- .toString());
- }
-
- @Test
- public void bip38testvector_noCompression_noEcMultiply_test2() throws Exception {
- BIP38PrivateKey encryptedKey = new BIP38PrivateKey(MAINNET,
- "6PRNFFkZc2NZ6dJqFfhRoFNMR9Lnyj7dYGrzdgXXVMXcxoKTePPX1dWByq");
- ECKey key = encryptedKey.decrypt("Satoshi");
- assertEquals("5HtasZ6ofTHP6HCwTqTkLDuLQisYPah7aUnSKfC7h4hMUVw2gi5", key.getPrivateKeyEncoded(MAINNET)
- .toString());
- }
-
- @Test
- public void bip38testvector_noCompression_noEcMultiply_test3() throws Exception {
- BIP38PrivateKey encryptedKey = new BIP38PrivateKey(MAINNET,
- "6PRW5o9FLp4gJDDVqJQKJFTpMvdsSGJxMYHtHaQBF3ooa8mwD69bapcDQn");
- StringBuilder passphrase = new StringBuilder();
- passphrase.appendCodePoint(0x03d2); // GREEK UPSILON WITH HOOK
- passphrase.appendCodePoint(0x0301); // COMBINING ACUTE ACCENT
- passphrase.appendCodePoint(0x0000); // NULL
- passphrase.appendCodePoint(0x010400); // DESERET CAPITAL LETTER LONG I
- passphrase.appendCodePoint(0x01f4a9); // PILE OF POO
- ECKey key = encryptedKey.decrypt(passphrase.toString());
- assertEquals("5Jajm8eQ22H3pGWLEVCXyvND8dQZhiQhoLJNKjYXk9roUFTMSZ4", key.getPrivateKeyEncoded(MAINNET)
- .toString());
- }
-
- @Test
- public void bip38testvector_compression_noEcMultiply_test1() throws Exception {
- BIP38PrivateKey encryptedKey = new BIP38PrivateKey(MainNetParams.get(),
- "6PYNKZ1EAgYgmQfmNVamxyXVWHzK5s6DGhwP4J5o44cvXdoY7sRzhtpUeo");
- ECKey key = encryptedKey.decrypt("TestingOneTwoThree");
- assertEquals("L44B5gGEpqEDRS9vVPz7QT35jcBG2r3CZwSwQ4fCewXAhAhqGVpP", key.getPrivateKeyEncoded(MAINNET)
- .toString());
- }
-
- @Test
- public void bip38testvector_compression_noEcMultiply_test2() throws Exception {
- BIP38PrivateKey encryptedKey = new BIP38PrivateKey(MainNetParams.get(),
- "6PYLtMnXvfG3oJde97zRyLYFZCYizPU5T3LwgdYJz1fRhh16bU7u6PPmY7");
- ECKey key = encryptedKey.decrypt("Satoshi");
- assertEquals("KwYgW8gcxj1JWJXhPSu4Fqwzfhp5Yfi42mdYmMa4XqK7NJxXUSK7", key.getPrivateKeyEncoded(MAINNET)
- .toString());
- }
-
- @Test
- public void bip38testvector_ecMultiply_noCompression_noLotAndSequence_test1() throws Exception {
- BIP38PrivateKey encryptedKey = new BIP38PrivateKey(MainNetParams.get(),
- "6PfQu77ygVyJLZjfvMLyhLMQbYnu5uguoJJ4kMCLqWwPEdfpwANVS76gTX");
- ECKey key = encryptedKey.decrypt("TestingOneTwoThree");
- assertEquals("5K4caxezwjGCGfnoPTZ8tMcJBLB7Jvyjv4xxeacadhq8nLisLR2", key.getPrivateKeyEncoded(MAINNET)
- .toString());
- }
-
- @Test
- public void bip38testvector_ecMultiply_noCompression_noLotAndSequence_test2() throws Exception {
- BIP38PrivateKey encryptedKey = new BIP38PrivateKey(MainNetParams.get(),
- "6PfLGnQs6VZnrNpmVKfjotbnQuaJK4KZoPFrAjx1JMJUa1Ft8gnf5WxfKd");
- ECKey key = encryptedKey.decrypt("Satoshi");
- assertEquals("5KJ51SgxWaAYR13zd9ReMhJpwrcX47xTJh2D3fGPG9CM8vkv5sH", key.getPrivateKeyEncoded(MAINNET)
- .toString());
- }
-
- @Test
- public void bip38testvector_ecMultiply_noCompression_lotAndSequence_test1() throws Exception {
- BIP38PrivateKey encryptedKey = new BIP38PrivateKey(MainNetParams.get(),
- "6PgNBNNzDkKdhkT6uJntUXwwzQV8Rr2tZcbkDcuC9DZRsS6AtHts4Ypo1j");
- ECKey key = encryptedKey.decrypt("MOLON LABE");
- assertEquals("5JLdxTtcTHcfYcmJsNVy1v2PMDx432JPoYcBTVVRHpPaxUrdtf8", key.getPrivateKeyEncoded(MAINNET)
- .toString());
- }
-
- @Test
- public void bip38testvector_ecMultiply_noCompression_lotAndSequence_test2() throws Exception {
- BIP38PrivateKey encryptedKey = new BIP38PrivateKey(MainNetParams.get(),
- "6PgGWtx25kUg8QWvwuJAgorN6k9FbE25rv5dMRwu5SKMnfpfVe5mar2ngH");
- ECKey key = encryptedKey.decrypt("ΜΟΛΩΝ ΛΑΒΕ");
- assertEquals("5KMKKuUmAkiNbA3DazMQiLfDq47qs8MAEThm4yL8R2PhV1ov33D", key.getPrivateKeyEncoded(MAINNET)
- .toString());
- }
-
- @Test
- public void bitcoinpaperwallet_testnet() throws Exception {
- // values taken from bitcoinpaperwallet.com
- BIP38PrivateKey encryptedKey = new BIP38PrivateKey(TESTNET,
- "6PRPhQhmtw6dQu6jD8E1KS4VphwJxBS9Eh9C8FQELcrwN3vPvskv9NKvuL");
- ECKey key = encryptedKey.decrypt("password");
- assertEquals("93MLfjbY6ugAsLeQfFY6zodDa8izgm1XAwA9cpMbUTwLkDitopg", key.getPrivateKeyEncoded(TESTNET)
- .toString());
- }
-
- @Test
- public void bitaddress_testnet() throws Exception {
- // values taken from bitaddress.org
- BIP38PrivateKey encryptedKey = new BIP38PrivateKey(TESTNET,
- "6PfMmVHn153N3x83Yiy4Nf76dHUkXufe2Adr9Fw5bewrunGNeaw2QCpifb");
- ECKey key = encryptedKey.decrypt("password");
- assertEquals("91tCpdaGr4Khv7UAuUxa6aMqeN5GcPVJxzLtNsnZHTCndxkRcz2", key.getPrivateKeyEncoded(TESTNET)
- .toString());
- }
-
- @Test(expected = BadPassphraseException.class)
- public void badPassphrase() throws Exception {
- BIP38PrivateKey encryptedKey = new BIP38PrivateKey(MAINNET,
- "6PRVWUbkzzsbcVac2qwfssoUJAN1Xhrg6bNk8J7Nzm5H7kxEbn2Nh2ZoGg");
- encryptedKey.decrypt("BAD");
- }
-
- @Test
- public void testJavaSerialization() throws Exception {
- BIP38PrivateKey key = new BIP38PrivateKey(TESTNET, "6PfMmVHn153N3x83Yiy4Nf76dHUkXufe2Adr9Fw5bewrunGNeaw2QCpifb");
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- new ObjectOutputStream(os).writeObject(key);
- BIP38PrivateKey keyCopy = (BIP38PrivateKey) new ObjectInputStream(new ByteArrayInputStream(os.toByteArray()))
- .readObject();
- assertEquals(key, keyCopy);
- }
-
- @Test
- public void cloning() throws Exception {
- BIP38PrivateKey a = new BIP38PrivateKey(TESTNET, "6PfMmVHn153N3x83Yiy4Nf76dHUkXufe2Adr9Fw5bewrunGNeaw2QCpifb");
- // TODO: Consider overriding clone() in BIP38PrivateKey to narrow the type
- BIP38PrivateKey b = (BIP38PrivateKey) a.clone();
-
- assertEquals(a, b);
- assertNotSame(a, b);
- }
-
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/crypto/ChildKeyDerivationTest.java b/core/src/test/java/com/dogecoin/dogecoinj/crypto/ChildKeyDerivationTest.java
deleted file mode 100644
index 1ab249c0..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/crypto/ChildKeyDerivationTest.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/**
- * Copyright 2013 Matija Mazi.
- * 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 com.dogecoin.dogecoinj.crypto;
-
-import com.dogecoin.dogecoinj.core.ECKey;
-import com.dogecoin.dogecoinj.core.NetworkParameters;
-import com.dogecoin.dogecoinj.core.Sha256Hash;
-import com.dogecoin.dogecoinj.params.MainNetParams;
-import com.dogecoin.dogecoinj.params.TestNet3Params;
-import com.dogecoin.dogecoinj.params.UnitTestParams;
-import org.junit.Test;
-import org.spongycastle.crypto.params.KeyParameter;
-
-import static com.dogecoin.dogecoinj.core.Utils.HEX;
-import static org.junit.Assert.*;
-
-/**
- * This test is adapted from Armory's BIP 32 tests.
- */
-public class ChildKeyDerivationTest {
- private static final int HDW_CHAIN_EXTERNAL = 0;
- private static final int HDW_CHAIN_INTERNAL = 1;
-
- @Test
- public void testChildKeyDerivation() throws Exception {
- String ckdTestVectors[] = {
- // test case 1:
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
- "04" + "6a04ab98d9e4774ad806e302dddeb63b" +
- "ea16b5cb5f223ee77478e861bb583eb3" +
- "36b6fbcb60b5b3d4f1551ac45e5ffc49" +
- "36466e7d98f6c7c0ec736539f74691a6",
- "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
-
- // test case 2:
- "be05d9ded0a73f81b814c93792f753b35c575fe446760005d44e0be13ba8935a",
- "02" + "b530da16bbff1428c33020e87fc9e699" +
- "cc9c753a63b8678ce647b7457397acef",
- "7012bc411228495f25d666d55fdce3f10a93908b5f9b9b7baa6e7573603a7bda"
- };
-
- for(int i = 0; i < 1; i++) {
- byte[] priv = HEX.decode(ckdTestVectors[3 * i]);
- byte[] pub = HEX.decode(ckdTestVectors[3 * i + 1]);
- byte[] chain = HEX.decode(ckdTestVectors[3 * i + 2]); // chain code
-
- //////////////////////////////////////////////////////////////////////////
- // Start with an extended PRIVATE key
- DeterministicKey ekprv = HDKeyDerivation.createMasterPrivKeyFromBytes(priv, chain);
-
- // Create two accounts
- DeterministicKey ekprv_0 = HDKeyDerivation.deriveChildKey(ekprv, 0);
- DeterministicKey ekprv_1 = HDKeyDerivation.deriveChildKey(ekprv, 1);
-
- // Create internal and external chain on Account 0
- DeterministicKey ekprv_0_EX = HDKeyDerivation.deriveChildKey(ekprv_0, HDW_CHAIN_EXTERNAL);
- DeterministicKey ekprv_0_IN = HDKeyDerivation.deriveChildKey(ekprv_0, HDW_CHAIN_INTERNAL);
-
- // Create three addresses on external chain
- DeterministicKey ekprv_0_EX_0 = HDKeyDerivation.deriveChildKey(ekprv_0_EX, 0);
- DeterministicKey ekprv_0_EX_1 = HDKeyDerivation.deriveChildKey(ekprv_0_EX, 1);
- DeterministicKey ekprv_0_EX_2 = HDKeyDerivation.deriveChildKey(ekprv_0_EX, 2);
-
- // Create three addresses on internal chain
- DeterministicKey ekprv_0_IN_0 = HDKeyDerivation.deriveChildKey(ekprv_0_IN, 0);
- DeterministicKey ekprv_0_IN_1 = HDKeyDerivation.deriveChildKey(ekprv_0_IN, 1);
- DeterministicKey ekprv_0_IN_2 = HDKeyDerivation.deriveChildKey(ekprv_0_IN, 2);
-
- // Now add a few more addresses with very large indices
- DeterministicKey ekprv_1_IN = HDKeyDerivation.deriveChildKey(ekprv_1, HDW_CHAIN_INTERNAL);
- DeterministicKey ekprv_1_IN_4095 = HDKeyDerivation.deriveChildKey(ekprv_1_IN, 4095);
-// ExtendedHierarchicKey ekprv_1_IN_4bil = HDKeyDerivation.deriveChildKey(ekprv_1_IN, 4294967295L);
-
- //////////////////////////////////////////////////////////////////////////
- // Repeat the above with PUBLIC key
- DeterministicKey ekpub = HDKeyDerivation.createMasterPubKeyFromBytes(HDUtils.toCompressed(pub), chain);
-
- // Create two accounts
- DeterministicKey ekpub_0 = HDKeyDerivation.deriveChildKey(ekpub, 0);
- DeterministicKey ekpub_1 = HDKeyDerivation.deriveChildKey(ekpub, 1);
-
- // Create internal and external chain on Account 0
- DeterministicKey ekpub_0_EX = HDKeyDerivation.deriveChildKey(ekpub_0, HDW_CHAIN_EXTERNAL);
- DeterministicKey ekpub_0_IN = HDKeyDerivation.deriveChildKey(ekpub_0, HDW_CHAIN_INTERNAL);
-
- // Create three addresses on external chain
- DeterministicKey ekpub_0_EX_0 = HDKeyDerivation.deriveChildKey(ekpub_0_EX, 0);
- DeterministicKey ekpub_0_EX_1 = HDKeyDerivation.deriveChildKey(ekpub_0_EX, 1);
- DeterministicKey ekpub_0_EX_2 = HDKeyDerivation.deriveChildKey(ekpub_0_EX, 2);
-
- // Create three addresses on internal chain
- DeterministicKey ekpub_0_IN_0 = HDKeyDerivation.deriveChildKey(ekpub_0_IN, 0);
- DeterministicKey ekpub_0_IN_1 = HDKeyDerivation.deriveChildKey(ekpub_0_IN, 1);
- DeterministicKey ekpub_0_IN_2 = HDKeyDerivation.deriveChildKey(ekpub_0_IN, 2);
-
- // Now add a few more addresses with very large indices
- DeterministicKey ekpub_1_IN = HDKeyDerivation.deriveChildKey(ekpub_1, HDW_CHAIN_INTERNAL);
- DeterministicKey ekpub_1_IN_4095 = HDKeyDerivation.deriveChildKey(ekpub_1_IN, 4095);
-// ExtendedHierarchicKey ekpub_1_IN_4bil = HDKeyDerivation.deriveChildKey(ekpub_1_IN, 4294967295L);
-
- assertEquals(hexEncodePub(ekprv.getPubOnly()), hexEncodePub(ekpub));
- assertEquals(hexEncodePub(ekprv_0.getPubOnly()), hexEncodePub(ekpub_0));
- assertEquals(hexEncodePub(ekprv_1.getPubOnly()), hexEncodePub(ekpub_1));
- assertEquals(hexEncodePub(ekprv_0_IN.getPubOnly()), hexEncodePub(ekpub_0_IN));
- assertEquals(hexEncodePub(ekprv_0_IN_0.getPubOnly()), hexEncodePub(ekpub_0_IN_0));
- assertEquals(hexEncodePub(ekprv_0_IN_1.getPubOnly()), hexEncodePub(ekpub_0_IN_1));
- assertEquals(hexEncodePub(ekprv_0_IN_2.getPubOnly()), hexEncodePub(ekpub_0_IN_2));
- assertEquals(hexEncodePub(ekprv_0_EX_0.getPubOnly()), hexEncodePub(ekpub_0_EX_0));
- assertEquals(hexEncodePub(ekprv_0_EX_1.getPubOnly()), hexEncodePub(ekpub_0_EX_1));
- assertEquals(hexEncodePub(ekprv_0_EX_2.getPubOnly()), hexEncodePub(ekpub_0_EX_2));
- assertEquals(hexEncodePub(ekprv_1_IN.getPubOnly()), hexEncodePub(ekpub_1_IN));
- assertEquals(hexEncodePub(ekprv_1_IN_4095.getPubOnly()), hexEncodePub(ekpub_1_IN_4095));
- //assertEquals(hexEncodePub(ekprv_1_IN_4bil.getPubOnly()), hexEncodePub(ekpub_1_IN_4bil));
- }
- }
-
- @Test
- public void inverseEqualsNormal() throws Exception {
- DeterministicKey key1 = HDKeyDerivation.createMasterPrivateKey("Wired / Aug 13th 2014 / Snowden: I Left the NSA Clues, But They Couldn't Find Them".getBytes());
- HDKeyDerivation.RawKeyBytes key2 = HDKeyDerivation.deriveChildKeyBytesFromPublic(key1.getPubOnly(), ChildNumber.ZERO, HDKeyDerivation.PublicDeriveMode.NORMAL);
- HDKeyDerivation.RawKeyBytes key3 = HDKeyDerivation.deriveChildKeyBytesFromPublic(key1.getPubOnly(), ChildNumber.ZERO, HDKeyDerivation.PublicDeriveMode.WITH_INVERSION);
- assertArrayEquals(key2.keyBytes, key3.keyBytes);
- assertArrayEquals(key2.chainCode, key3.chainCode);
- }
-
- @Test
- public void encryptedDerivation() throws Exception {
- // Check that encrypting a parent key in the heirarchy and then deriving from it yields a DeterministicKey
- // with no private key component, and that the private key bytes are derived on demand.
- KeyCrypter scrypter = new KeyCrypterScrypt();
- KeyParameter aesKey = scrypter.deriveKey("we never went to the moon");
-
- DeterministicKey key1 = HDKeyDerivation.createMasterPrivateKey("it was all a hoax".getBytes());
- DeterministicKey encryptedKey1 = key1.encrypt(scrypter, aesKey, null);
- DeterministicKey decryptedKey1 = encryptedKey1.decrypt(aesKey);
- assertEquals(key1, decryptedKey1);
-
- DeterministicKey key2 = HDKeyDerivation.deriveChildKey(key1, ChildNumber.ZERO);
- DeterministicKey derivedKey2 = HDKeyDerivation.deriveChildKey(encryptedKey1, ChildNumber.ZERO);
- assertTrue(derivedKey2.isEncrypted()); // parent is encrypted.
- DeterministicKey decryptedKey2 = derivedKey2.decrypt(aesKey);
- assertFalse(decryptedKey2.isEncrypted());
- assertEquals(key2, decryptedKey2);
-
- Sha256Hash hash = Sha256Hash.create("the mainstream media won't cover it. why is that?".getBytes());
- try {
- derivedKey2.sign(hash);
- fail();
- } catch (ECKey.KeyIsEncryptedException e) {
- // Ignored.
- }
- ECKey.ECDSASignature signature = derivedKey2.sign(hash, aesKey);
- assertTrue(derivedKey2.verify(hash, signature));
- }
-
- @Test
- public void pubOnlyDerivation() throws Exception {
- DeterministicKey key1 = HDKeyDerivation.createMasterPrivateKey("satoshi lives!".getBytes());
- DeterministicKey key2 = HDKeyDerivation.deriveChildKey(key1, ChildNumber.ZERO_HARDENED);
- DeterministicKey key3 = HDKeyDerivation.deriveChildKey(key2, ChildNumber.ZERO);
- DeterministicKey pubkey3 = HDKeyDerivation.deriveChildKey(key2.getPubOnly(), ChildNumber.ZERO);
- assertEquals(key3.getPubKeyPoint(), pubkey3.getPubKeyPoint());
- }
-
- @Test
- public void testSerializationMainAndTestNetworks() {
- DeterministicKey key1 = HDKeyDerivation.createMasterPrivateKey("satoshi lives!".getBytes());
- NetworkParameters params = MainNetParams.get();
- String pub58 = key1.serializePubB58(params);
- String priv58 = key1.serializePrivB58(params);
- assertEquals("xpub661MyMwAqRbcF7mq7Aejj5xZNzFfgi3ABamE9FedDHVmViSzSxYTgAQGcATDo2J821q7Y9EAagjg5EP3L7uBZk11PxZU3hikL59dexfLkz3", pub58);
- assertEquals("xprv9s21ZrQH143K2dhN197jMx1ppxRBHFKJpMqdLsF1ewxncv7quRED8N5nksxphju3W7naj1arF56L5PUEWfuSk8h73Sb2uh7bSwyXNrjzhAZ", priv58);
- params = TestNet3Params.get();
- pub58 = key1.serializePubB58(params);
- priv58 = key1.serializePrivB58(params);
- assertEquals("tpubD6NzVbkrYhZ4WuxgZMdpw1Hvi7MKg6YDjDMXVohmZCFfF17hXBPYpc56rCY1KXFMovN29ik37nZimQseiykRTBTJTZJmjENyv2k3R12BJ1M", pub58);
- assertEquals("tprv8ZgxMBicQKsPdSvtfhyEXbdp95qPWmMK9ukkDHfU8vTGQWrvtnZxe7TEg48Ui7HMsZKMj7CcQRg8YF1ydtFPZBxha5oLa3qeN3iwpYhHPVZ", priv58);
- }
-
- @Test
- public void serializeToTextAndBytes() {
- DeterministicKey key1 = HDKeyDerivation.createMasterPrivateKey("satoshi lives!".getBytes());
- DeterministicKey key2 = HDKeyDerivation.deriveChildKey(key1, ChildNumber.ZERO_HARDENED);
-
- // Creation time can't survive the xpub serialization format unfortunately.
- key1.setCreationTimeSeconds(0);
- NetworkParameters params = MainNetParams.get();
-
- {
- final String pub58 = key1.serializePubB58(params);
- final String priv58 = key1.serializePrivB58(params);
- final byte[] pub = key1.serializePublic(params);
- final byte[] priv = key1.serializePrivate(params);
- assertEquals("xpub661MyMwAqRbcF7mq7Aejj5xZNzFfgi3ABamE9FedDHVmViSzSxYTgAQGcATDo2J821q7Y9EAagjg5EP3L7uBZk11PxZU3hikL59dexfLkz3", pub58);
- assertEquals("xprv9s21ZrQH143K2dhN197jMx1ppxRBHFKJpMqdLsF1ewxncv7quRED8N5nksxphju3W7naj1arF56L5PUEWfuSk8h73Sb2uh7bSwyXNrjzhAZ", priv58);
- assertArrayEquals(new byte[]{4, -120, -78, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, -68, 93, -104, -97, 31, -105, -18, 109, 112, 104, 45, -77, -77, 18, 85, -29, -120, 86, -113, 26, 48, -18, -79, -110, -6, -27, 87, 86, 24, 124, 99, 3, 96, -33, -14, 67, -19, -47, 16, 76, -49, -11, -30, -123, 7, 56, 101, 91, 74, 125, -127, 61, 42, -103, 90, -93, 66, -36, 2, -126, -107, 30, 24, -111}, pub);
- assertArrayEquals(new byte[]{4, -120, -83, -28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, -68, 93, -104, -97, 31, -105, -18, 109, 112, 104, 45, -77, -77, 18, 85, -29, -120, 86, -113, 26, 48, -18, -79, -110, -6, -27, 87, 86, 24, 124, 99, 0, -96, -75, 47, 90, -49, 92, -74, 92, -128, -125, 23, 38, -10, 97, -66, -19, 50, -112, 30, -111, -57, -124, 118, -86, 126, -35, -4, -51, 19, 109, 67, 116}, priv);
- assertEquals(DeterministicKey.deserializeB58(null, priv58, params), key1);
- assertEquals(DeterministicKey.deserializeB58(priv58, params), key1);
- assertEquals(DeterministicKey.deserializeB58(null, pub58, params).getPubKeyPoint(), key1.getPubKeyPoint());
- assertEquals(DeterministicKey.deserializeB58(pub58, params).getPubKeyPoint(), key1.getPubKeyPoint());
- assertEquals(DeterministicKey.deserialize(params, priv, null), key1);
- assertEquals(DeterministicKey.deserialize(params, priv), key1);
- assertEquals(DeterministicKey.deserialize(params, pub, null).getPubKeyPoint(), key1.getPubKeyPoint());
- assertEquals(DeterministicKey.deserialize(params, pub).getPubKeyPoint(), key1.getPubKeyPoint());
- }
- {
- final String pub58 = key2.serializePubB58(params);
- final String priv58 = key2.serializePrivB58(params);
- final byte[] pub = key2.serializePublic(params);
- final byte[] priv = key2.serializePrivate(params);
- assertEquals(DeterministicKey.deserializeB58(key1, priv58, params), key2);
- assertEquals(DeterministicKey.deserializeB58(key1, pub58, params).getPubKeyPoint(), key2.getPubKeyPoint());
- assertEquals(DeterministicKey.deserialize(params, priv, key1), key2);
- assertEquals(DeterministicKey.deserialize(params, pub, key1).getPubKeyPoint(), key2.getPubKeyPoint());
- }
- }
-
- @Test
- public void parentlessDeserialization() {
- NetworkParameters params = UnitTestParams.get();
- DeterministicKey key1 = HDKeyDerivation.createMasterPrivateKey("satoshi lives!".getBytes());
- DeterministicKey key2 = HDKeyDerivation.deriveChildKey(key1, ChildNumber.ZERO_HARDENED);
- DeterministicKey key3 = HDKeyDerivation.deriveChildKey(key2, ChildNumber.ZERO_HARDENED);
- DeterministicKey key4 = HDKeyDerivation.deriveChildKey(key3, ChildNumber.ZERO_HARDENED);
- assertEquals(key4.getPath().size(), 3);
- assertEquals(DeterministicKey.deserialize(params, key4.serializePrivate(params), key3).getPath().size(), 3);
- assertEquals(DeterministicKey.deserialize(params, key4.serializePrivate(params), null).getPath().size(), 1);
- assertEquals(DeterministicKey.deserialize(params, key4.serializePrivate(params)).getPath().size(), 1);
- }
-
- private static String hexEncodePub(DeterministicKey pubKey) {
- return HEX.encode(pubKey.getPubKey());
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/crypto/HDUtilsTest.java b/core/src/test/java/com/dogecoin/dogecoinj/crypto/HDUtilsTest.java
deleted file mode 100644
index ee861444..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/crypto/HDUtilsTest.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright 2013 Matija Mazi
- * 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 com.dogecoin.dogecoinj.crypto;
-
-import com.google.common.collect.ImmutableList;
-import org.junit.Assert;
-import org.junit.Test;
-
-import static com.dogecoin.dogecoinj.core.Utils.HEX;
-import java.util.List;
-
-public class HDUtilsTest {
- @Test
- public void testHmac() throws Exception {
- String tv[] = {
- "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b" +
- "0b0b0b0b",
- "4869205468657265",
- "87aa7cdea5ef619d4ff0b4241a1d6cb0" +
- "2379f4e2ce4ec2787ad0b30545e17cde" +
- "daa833b7d6b8a702038b274eaea3f4e4" +
- "be9d914eeb61f1702e696c203a126854",
-
- "4a656665",
- "7768617420646f2079612077616e7420" +
- "666f72206e6f7468696e673f",
- "164b7a7bfcf819e2e395fbe73b56e0a3" +
- "87bd64222e831fd610270cd7ea250554" +
- "9758bf75c05a994a6d034f65f8f0e6fd" +
- "caeab1a34d4a6b4b636e070a38bce737",
-
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaa",
- "dddddddddddddddddddddddddddddddd" +
- "dddddddddddddddddddddddddddddddd" +
- "dddddddddddddddddddddddddddddddd" +
- "dddd",
- "fa73b0089d56a284efb0f0756c890be9" +
- "b1b5dbdd8ee81a3655f83e33b2279d39" +
- "bf3e848279a722c806b485a47e67c807" +
- "b946a337bee8942674278859e13292fb",
-
- "0102030405060708090a0b0c0d0e0f10" +
- "111213141516171819",
- "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" +
- "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" +
- "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" +
- "cdcd",
- "b0ba465637458c6990e5a8c5f61d4af7" +
- "e576d97ff94b872de76f8050361ee3db" +
- "a91ca5c11aa25eb4d679275cc5788063" +
- "a5f19741120c4f2de2adebeb10a298dd",
-
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaa",
- "54657374205573696e67204c61726765" +
- "72205468616e20426c6f636b2d53697a" +
- "65204b6579202d2048617368204b6579" +
- "204669727374",
- "80b24263c7c1a3ebb71493c1dd7be8b4" +
- "9b46d1f41b4aeec1121b013783f8f352" +
- "6b56d037e05f2598bd0fd2215d6a1e52" +
- "95e64f73f63f0aec8b915a985d786598",
-
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
- "aaaaaa",
- "54686973206973206120746573742075" +
- "73696e672061206c6172676572207468" +
- "616e20626c6f636b2d73697a65206b65" +
- "7920616e642061206c61726765722074" +
- "68616e20626c6f636b2d73697a652064" +
- "6174612e20546865206b6579206e6565" +
- "647320746f2062652068617368656420" +
- "6265666f7265206265696e6720757365" +
- "642062792074686520484d414320616c" +
- "676f726974686d2e",
- "e37b6a775dc87dbaa4dfa9f96e5e3ffd" +
- "debd71f8867289865df5a32d20cdc944" +
- "b6022cac3c4982b10d5eeb55c3e4de15" +
- "134676fb6de0446065c97440fa8c6a58"
- };
-
- for (int i = 0; i < tv.length; i += 3) {
- Assert.assertArrayEquals("Case " + i, getBytes(tv, i + 2), HDUtils.hmacSha512(getBytes(tv, i), getBytes(tv, i + 1)));
- }
- }
-
- private static byte[] getBytes(String[] hmacTestVectors, int i) {
- return HEX.decode(hmacTestVectors[i]);
- }
-
- @Test
- public void testLongToByteArray() throws Exception {
- byte[] bytes = HDUtils.longTo4ByteArray(1026);
- Assert.assertEquals("00000402", HEX.encode(bytes));
- }
-
-
- @Test
- public void testFormatPath() {
- Object tv[] = {
- "M/44H/0H/0H/1/1",
- ImmutableList.of(new ChildNumber(44, true), new ChildNumber(0, true), new ChildNumber(0, true),
- new ChildNumber(1, false), new ChildNumber(1, false)),
-
- "M/7H/3/3/1H",
- ImmutableList.of(new ChildNumber(7, true), new ChildNumber(3, false), new ChildNumber(3, false),
- new ChildNumber(1, true)),
-
- "M/1H/2H/3H",
- ImmutableList.of(new ChildNumber(1, true), new ChildNumber(2, true), new ChildNumber(3, true)),
-
- "M/1/2/3",
- ImmutableList.of(new ChildNumber(1, false), new ChildNumber(2, false), new ChildNumber(3, false))
- };
-
- for (int i = 0; i < tv.length; i += 2) {
- String expectedStrPath = (String) tv[i];
- List path = (List) tv[i+1];
-
- String generatedStrPath = HDUtils.formatPath(path);
-
- Assert.assertEquals(generatedStrPath, expectedStrPath);
- }
-
- }
-
- @Test
- public void testParsePath() {
- Object tv[] = {
- "M / 44H / 0H / 0H / 1 / 1",
- ImmutableList.of(new ChildNumber(44, true), new ChildNumber(0, true), new ChildNumber(0, true),
- new ChildNumber(1, false), new ChildNumber(1, false)),
-
- "M/7H/3/3/1H/",
- ImmutableList.of(new ChildNumber(7, true), new ChildNumber(3, false), new ChildNumber(3, false),
- new ChildNumber(1, true)),
-
- "1 H / 2 H / 3 H /",
- ImmutableList.of(new ChildNumber(1, true), new ChildNumber(2, true), new ChildNumber(3, true)),
-
- "1 / 2 / 3 /",
- ImmutableList.of(new ChildNumber(1, false), new ChildNumber(2, false), new ChildNumber(3, false))
- };
-
- for (int i = 0; i < tv.length; i += 2) {
- String strPath = (String) tv[i];
- List expectedPath = (List) tv[i+1];
-
- List path = HDUtils.parsePath(strPath);
-
- Assert.assertEquals(path, expectedPath);
- }
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/crypto/KeyCrypterScryptTest.java b/core/src/test/java/com/dogecoin/dogecoinj/crypto/KeyCrypterScryptTest.java
deleted file mode 100644
index 6efc3562..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/crypto/KeyCrypterScryptTest.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/**
- * Copyright 2013 Jim Burton.
- * Copyright 2014 Andreas Schildbach
- *
- * Licensed under the MIT license (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://opensource.org/licenses/mit-license.php
- *
- * 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 com.dogecoin.dogecoinj.crypto;
-
-import com.dogecoin.dogecoinj.core.Utils;
-import com.dogecoin.dogecoinj.utils.BriefLogFormatter;
-import com.google.protobuf.ByteString;
-
-import com.dogecoin.dogecoinj.wallet.Protos;
-import com.dogecoin.dogecoinj.wallet.Protos.ScryptParameters;
-import org.junit.Before;
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.UnsupportedEncodingException;
-import java.security.SecureRandom;
-import java.util.Random;
-import java.util.UUID;
-
-import static org.junit.Assert.*;
-
-public class KeyCrypterScryptTest {
-
- private static final Logger log = LoggerFactory.getLogger(KeyCrypterScryptTest.class);
-
- // Nonsense bytes for encryption test.
- private static final byte[] TEST_BYTES1 = {0, -101, 2, 103, -4, 105, 6, 107, 8, -109, 10, 111, -12, 113, 14, -115, 16, 117, -18, 119, 20, 121, 22, 123, -24, 125, 26, 127, -28, 29, -30, 31};
-
- private static final CharSequence PASSWORD1 = "aTestPassword";
- private static final CharSequence PASSWORD2 = "0123456789";
-
- private static final CharSequence WRONG_PASSWORD = "thisIsTheWrongPassword";
-
- private ScryptParameters scryptParameters;
-
- @Before
- public void setUp() throws Exception {
- byte[] salt = new byte[KeyCrypterScrypt.SALT_LENGTH];
- new SecureRandom().nextBytes(salt);
- Protos.ScryptParameters.Builder scryptParametersBuilder = Protos.ScryptParameters.newBuilder().setSalt(ByteString.copyFrom(salt));
- scryptParameters = scryptParametersBuilder.build();
-
- BriefLogFormatter.init();
- }
-
- @Test
- public void testKeyCrypterGood1() throws KeyCrypterException {
- KeyCrypterScrypt keyCrypter = new KeyCrypterScrypt(scryptParameters);
-
- // Encrypt.
- EncryptedData encryptedPrivateKey = keyCrypter.encrypt(TEST_BYTES1, keyCrypter.deriveKey(PASSWORD1));
- assertNotNull(encryptedPrivateKey);
-
- // Decrypt.
- byte[] reborn = keyCrypter.decrypt(encryptedPrivateKey, keyCrypter.deriveKey(PASSWORD1));
- log.debug("Original: " + Utils.HEX.encode(TEST_BYTES1));
- log.debug("Reborn : " + Utils.HEX.encode(reborn));
- assertEquals(Utils.HEX.encode(TEST_BYTES1), Utils.HEX.encode(reborn));
- }
-
- /**
- * Test with random plain text strings and random passwords.
- * UUIDs are used and hence will only cover hex characters (and the separator hyphen).
- * @throws KeyCrypterException
- * @throws UnsupportedEncodingException
- */
- @Test
- public void testKeyCrypterGood2() throws Exception {
- KeyCrypterScrypt keyCrypter = new KeyCrypterScrypt(scryptParameters);
-
- System.out.print("EncrypterDecrypterTest: Trying random UUIDs for plainText and passwords :");
- int numberOfTests = 16;
- for (int i = 0; i < numberOfTests; i++) {
- // Create a UUID as the plaintext and use another for the password.
- String plainText = UUID.randomUUID().toString();
- CharSequence password = UUID.randomUUID().toString();
-
- EncryptedData encryptedPrivateKey = keyCrypter.encrypt(plainText.getBytes(), keyCrypter.deriveKey(password));
-
- assertNotNull(encryptedPrivateKey);
-
- byte[] reconstructedPlainBytes = keyCrypter.decrypt(encryptedPrivateKey,keyCrypter.deriveKey(password));
- assertEquals(Utils.HEX.encode(plainText.getBytes()), Utils.HEX.encode(reconstructedPlainBytes));
- System.out.print('.');
- }
- System.out.println(" Done.");
- }
-
- @Test
- public void testKeyCrypterWrongPassword() throws KeyCrypterException {
- KeyCrypterScrypt keyCrypter = new KeyCrypterScrypt(scryptParameters);
-
- // create a longer encryption string
- StringBuilder stringBuffer = new StringBuilder();
- for (int i = 0; i < 100; i++) {
- stringBuffer.append(i).append(" ").append("The quick brown fox");
- }
-
- EncryptedData encryptedPrivateKey = keyCrypter.encrypt(stringBuffer.toString().getBytes(), keyCrypter.deriveKey(PASSWORD2));
- assertNotNull(encryptedPrivateKey);
-
- try {
- keyCrypter.decrypt(encryptedPrivateKey, keyCrypter.deriveKey(WRONG_PASSWORD));
- // TODO: This test sometimes fails due to relying on padding.
- fail("Decrypt with wrong password did not throw exception");
- } catch (KeyCrypterException ede) {
- assertTrue(ede.getMessage().contains("Could not decrypt"));
- }
- }
-
- @Test
- public void testEncryptDecryptBytes1() throws KeyCrypterException {
- KeyCrypterScrypt keyCrypter = new KeyCrypterScrypt(scryptParameters);
-
- // Encrypt bytes.
- EncryptedData encryptedPrivateKey = keyCrypter.encrypt(TEST_BYTES1, keyCrypter.deriveKey(PASSWORD1));
- assertNotNull(encryptedPrivateKey);
- log.debug("\nEncrypterDecrypterTest: cipherBytes = \nlength = " + encryptedPrivateKey.encryptedBytes.length + "\n---------------\n" + Utils.HEX.encode(encryptedPrivateKey.encryptedBytes) + "\n---------------\n");
-
- byte[] rebornPlainBytes = keyCrypter.decrypt(encryptedPrivateKey, keyCrypter.deriveKey(PASSWORD1));
-
- log.debug("Original: " + Utils.HEX.encode(TEST_BYTES1));
- log.debug("Reborn1 : " + Utils.HEX.encode(rebornPlainBytes));
- assertEquals(Utils.HEX.encode(TEST_BYTES1), Utils.HEX.encode(rebornPlainBytes));
- }
-
- @Test
- public void testEncryptDecryptBytes2() throws KeyCrypterException {
- KeyCrypterScrypt keyCrypter = new KeyCrypterScrypt(scryptParameters);
-
- // Encrypt random bytes of various lengths up to length 50.
- Random random = new Random();
-
- for (int i = 0; i < 50; i++) {
- byte[] plainBytes = new byte[i];
- random.nextBytes(plainBytes);
-
- EncryptedData encryptedPrivateKey = keyCrypter.encrypt(plainBytes, keyCrypter.deriveKey(PASSWORD1));
- assertNotNull(encryptedPrivateKey);
- //log.debug("\nEncrypterDecrypterTest: cipherBytes = \nlength = " + cipherBytes.length + "\n---------------\n" + Utils.HEX.encode(cipherBytes) + "\n---------------\n");
-
- byte[] rebornPlainBytes = keyCrypter.decrypt(encryptedPrivateKey, keyCrypter.deriveKey(PASSWORD1));
-
- log.debug("Original: (" + i + ") " + Utils.HEX.encode(plainBytes));
- log.debug("Reborn1 : (" + i + ") " + Utils.HEX.encode(rebornPlainBytes));
- assertEquals(Utils.HEX.encode(plainBytes), Utils.HEX.encode(rebornPlainBytes));
- }
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/crypto/MnemonicCodeTest.java b/core/src/test/java/com/dogecoin/dogecoinj/crypto/MnemonicCodeTest.java
deleted file mode 100644
index 7b8a9b17..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/crypto/MnemonicCodeTest.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright 2013 Ken Sedgwick
- * 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 com.dogecoin.dogecoinj.crypto;
-
-import com.google.common.base.Joiner;
-import com.google.common.collect.Lists;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import static com.dogecoin.dogecoinj.core.Utils.HEX;
-import static org.junit.Assert.assertEquals;
-
-public class MnemonicCodeTest {
- // These vectors are from https://github.com/trezor/python-mnemonic/blob/master/vectors.json
- String vectors[] = {
- "00000000000000000000000000000000",
- "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
- "c55257c360c07c72029aebc1b53c05ed0362ada38ead3e3e9efa3708e53495531f09a6987599d18264c1e1c92f2cf141630c7a3c4ab7c81b2f001698e7463b04",
-
- "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
- "legal winner thank year wave sausage worth useful legal winner thank yellow",
- "2e8905819b8723fe2c1d161860e5ee1830318dbf49a83bd451cfb8440c28bd6fa457fe1296106559a3c80937a1c1069be3a3a5bd381ee6260e8d9739fce1f607",
-
-
- "80808080808080808080808080808080",
- "letter advice cage absurd amount doctor acoustic avoid letter advice cage above",
- "d71de856f81a8acc65e6fc851a38d4d7ec216fd0796d0a6827a3ad6ed5511a30fa280f12eb2e47ed2ac03b5c462a0358d18d69fe4f985ec81778c1b370b652a8",
-
-
- "ffffffffffffffffffffffffffffffff",
- "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong",
- "ac27495480225222079d7be181583751e86f571027b0497b5b5d11218e0a8a13332572917f0f8e5a589620c6f15b11c61dee327651a14c34e18231052e48c069",
-
-
- "000000000000000000000000000000000000000000000000",
- "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent",
- "035895f2f481b1b0f01fcf8c289c794660b289981a78f8106447707fdd9666ca06da5a9a565181599b79f53b844d8a71dd9f439c52a3d7b3e8a79c906ac845fa",
-
-
- "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
- "legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal will",
- "f2b94508732bcbacbcc020faefecfc89feafa6649a5491b8c952cede496c214a0c7b3c392d168748f2d4a612bada0753b52a1c7ac53c1e93abd5c6320b9e95dd",
-
-
- "808080808080808080808080808080808080808080808080",
- "letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter always",
- "107d7c02a5aa6f38c58083ff74f04c607c2d2c0ecc55501dadd72d025b751bc27fe913ffb796f841c49b1d33b610cf0e91d3aa239027f5e99fe4ce9e5088cd65",
-
-
- "ffffffffffffffffffffffffffffffffffffffffffffffff",
- "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo when",
- "0cd6e5d827bb62eb8fc1e262254223817fd068a74b5b449cc2f667c3f1f985a76379b43348d952e2265b4cd129090758b3e3c2c49103b5051aac2eaeb890a528",
-
-
- "0000000000000000000000000000000000000000000000000000000000000000",
- "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art",
- "bda85446c68413707090a52022edd26a1c9462295029f2e60cd7c4f2bbd3097170af7a4d73245cafa9c3cca8d561a7c3de6f5d4a10be8ed2a5e608d68f92fcc8",
-
-
- "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
- "legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth title",
- "bc09fca1804f7e69da93c2f2028eb238c227f2e9dda30cd63699232578480a4021b146ad717fbb7e451ce9eb835f43620bf5c514db0f8add49f5d121449d3e87",
-
-
- "8080808080808080808080808080808080808080808080808080808080808080",
- "letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic bless",
- "c0c519bd0e91a2ed54357d9d1ebef6f5af218a153624cf4f2da911a0ed8f7a09e2ef61af0aca007096df430022f7a2b6fb91661a9589097069720d015e4e982f",
-
-
- "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
- "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo vote",
- "dd48c104698c30cfe2b6142103248622fb7bb0ff692eebb00089b32d22484e1613912f0a5b694407be899ffd31ed3992c456cdf60f5d4564b8ba3f05a69890ad",
-
-
- "77c2b00716cec7213839159e404db50d",
- "jelly better achieve collect unaware mountain thought cargo oxygen act hood bridge",
- "b5b6d0127db1a9d2226af0c3346031d77af31e918dba64287a1b44b8ebf63cdd52676f672a290aae502472cf2d602c051f3e6f18055e84e4c43897fc4e51a6ff",
-
-
- "b63a9c59a6e641f288ebc103017f1da9f8290b3da6bdef7b",
- "renew stay biology evidence goat welcome casual join adapt armor shuffle fault little machine walk stumble urge swap",
- "9248d83e06f4cd98debf5b6f010542760df925ce46cf38a1bdb4e4de7d21f5c39366941c69e1bdbf2966e0f6e6dbece898a0e2f0a4c2b3e640953dfe8b7bbdc5",
-
-
- "3e141609b97933b66a060dcddc71fad1d91677db872031e85f4c015c5e7e8982",
- "dignity pass list indicate nasty swamp pool script soccer toe leaf photo multiply desk host tomato cradle drill spread actor shine dismiss champion exotic",
- "ff7f3184df8696d8bef94b6c03114dbee0ef89ff938712301d27ed8336ca89ef9635da20af07d4175f2bf5f3de130f39c9d9e8dd0472489c19b1a020a940da67",
-
-
- "0460ef47585604c5660618db2e6a7e7f",
- "afford alter spike radar gate glance object seek swamp infant panel yellow",
- "65f93a9f36b6c85cbe634ffc1f99f2b82cbb10b31edc7f087b4f6cb9e976e9faf76ff41f8f27c99afdf38f7a303ba1136ee48a4c1e7fcd3dba7aa876113a36e4",
-
-
- "72f60ebac5dd8add8d2a25a797102c3ce21bc029c200076f",
- "indicate race push merry suffer human cruise dwarf pole review arch keep canvas theme poem divorce alter left",
- "3bbf9daa0dfad8229786ace5ddb4e00fa98a044ae4c4975ffd5e094dba9e0bb289349dbe2091761f30f382d4e35c4a670ee8ab50758d2c55881be69e327117ba",
-
-
- "2c85efc7f24ee4573d2b81a6ec66cee209b2dcbd09d8eddc51e0215b0b68e416",
- "clutch control vehicle tonight unusual clog visa ice plunge glimpse recipe series open hour vintage deposit universe tip job dress radar refuse motion taste",
- "fe908f96f46668b2d5b37d82f558c77ed0d69dd0e7e043a5b0511c48c2f1064694a956f86360c93dd04052a8899497ce9e985ebe0c8c52b955e6ae86d4ff4449",
-
-
- "eaebabb2383351fd31d703840b32e9e2",
- "turtle front uncle idea crush write shrug there lottery flower risk shell",
- "bdfb76a0759f301b0b899a1e3985227e53b3f51e67e3f2a65363caedf3e32fde42a66c404f18d7b05818c95ef3ca1e5146646856c461c073169467511680876c",
-
-
- "7ac45cfe7722ee6c7ba84fbc2d5bd61b45cb2fe5eb65aa78",
- "kiss carry display unusual confirm curtain upgrade antique rotate hello void custom frequent obey nut hole price segment",
- "ed56ff6c833c07982eb7119a8f48fd363c4a9b1601cd2de736b01045c5eb8ab4f57b079403485d1c4924f0790dc10a971763337cb9f9c62226f64fff26397c79",
-
-
- "4fa1a8bc3e6d80ee1316050e862c1812031493212b7ec3f3bb1b08f168cabeef",
- "exile ask congress lamp submit jacket era scheme attend cousin alcohol catch course end lucky hurt sentence oven short ball bird grab wing top",
- "095ee6f817b4c2cb30a5a797360a81a40ab0f9a4e25ecd672a3f58a0b5ba0687c096a6b14d2c0deb3bdefce4f61d01ae07417d502429352e27695163f7447a8c",
-
-
- "18ab19a9f54a9274f03e5209a2ac8a91",
- "board flee heavy tunnel powder denial science ski answer betray cargo cat",
- "6eff1bb21562918509c73cb990260db07c0ce34ff0e3cc4a8cb3276129fbcb300bddfe005831350efd633909f476c45c88253276d9fd0df6ef48609e8bb7dca8",
-
-
- "18a2e1d81b8ecfb2a333adcb0c17a5b9eb76cc5d05db91a4",
- "board blade invite damage undo sun mimic interest slam gaze truly inherit resist great inject rocket museum chief",
- "f84521c777a13b61564234bf8f8b62b3afce27fc4062b51bb5e62bdfecb23864ee6ecf07c1d5a97c0834307c5c852d8ceb88e7c97923c0a3b496bedd4e5f88a9",
-
-
- "15da872c95a13dd738fbf50e427583ad61f18fd99f628c417a61cf8343c90419",
- "beyond stage sleep clip because twist token leaf atom beauty genius food business side grid unable middle armed observe pair crouch tonight away coconut",
- "b15509eaa2d09d3efd3e006ef42151b30367dc6e3aa5e44caba3fe4d3e352e65101fbdb86a96776b91946ff06f8eac594dc6ee1d3e82a42dfe1b40fef6bcc3fd"
- };
-
- private MnemonicCode mc;
-
- @Before
- public void setup() throws IOException {
- mc = new MnemonicCode();
- }
-
- @Test
- public void testVectors() throws Exception {
- for (int ii = 0; ii < vectors.length; ii += 3) {
- String vecData = vectors[ii];
- String vecCode = vectors[ii+1];
- String vecSeed = vectors[ii+2];
-
- List code = mc.toMnemonic(HEX.decode(vecData));
- byte[] seed = MnemonicCode.toSeed(code, "TREZOR");
- byte[] entropy = mc.toEntropy(split(vecCode));
-
- assertEquals(vecData, HEX.encode(entropy));
- assertEquals(vecCode, Joiner.on(' ').join(code));
- assertEquals(vecSeed, HEX.encode(seed));
- }
- }
-
- @Test(expected = MnemonicException.MnemonicLengthException.class)
- public void testBadEntropyLength() throws Exception {
- byte[] entropy = HEX.decode("7f7f7f7f7f7f7f7f7f7f7f7f7f7f");
- mc.toMnemonic(entropy);
- }
-
- @Test(expected = MnemonicException.MnemonicLengthException.class)
- public void testBadLength() throws Exception {
- List words = split("risk tiger venture dinner age assume float denial penalty hello");
- mc.check(words);
- }
-
- @Test(expected = MnemonicException.MnemonicWordException.class)
- public void testBadWord() throws Exception {
- List words = split("risk tiger venture dinner xyzzy assume float denial penalty hello game wing");
- mc.check(words);
- }
-
- @Test(expected = MnemonicException.MnemonicChecksumException.class)
- public void testBadChecksum() throws Exception {
- List words = split("bless cloud wheel regular tiny venue bird web grief security dignity zoo");
- mc.check(words);
- }
-
- @Test(expected = MnemonicException.MnemonicLengthException.class)
- public void testEmptyMnemonic() throws Exception {
- List words = Lists.newArrayList();
- mc.check(words);
- }
-
- @Test(expected = MnemonicException.MnemonicLengthException.class)
- public void testEmptyEntropy() throws Exception {
- byte[] entropy = new byte[]{};
- mc.toMnemonic(entropy);
- }
-
- static public List split(String words) {
- return new ArrayList(Arrays.asList(words.split("\\s+")));
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/crypto/X509UtilsTest.java b/core/src/test/java/com/dogecoin/dogecoinj/crypto/X509UtilsTest.java
deleted file mode 100644
index c22484a9..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/crypto/X509UtilsTest.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * 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 com.dogecoin.dogecoinj.crypto;
-
-import org.junit.Test;
-
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-
-import static org.junit.Assert.assertEquals;
-
-public class X509UtilsTest {
-
- @Test
- public void testDisplayName() throws Exception {
- CertificateFactory cf = CertificateFactory.getInstance("X.509");
-
- X509Certificate clientCert = (X509Certificate) cf.generateCertificate(getClass().getResourceAsStream(
- "startssl-client.crt"));
- assertEquals("Andreas Schildbach", X509Utils.getDisplayNameFromCertificate(clientCert, false));
-
- X509Certificate comodoCert = (X509Certificate) cf.generateCertificate(getClass().getResourceAsStream(
- "comodo-smime.crt"));
- assertEquals("comodo.com@schildbach.de", X509Utils.getDisplayNameFromCertificate(comodoCert, true));
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/net/NetworkAbstractionTests.java b/core/src/test/java/com/dogecoin/dogecoinj/net/NetworkAbstractionTests.java
deleted file mode 100644
index 1e29b6a2..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/net/NetworkAbstractionTests.java
+++ /dev/null
@@ -1,662 +0,0 @@
-/*
- * 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 com.dogecoin.dogecoinj.net;
-
-import com.dogecoin.dogecoinj.core.Utils;
-import com.google.common.util.concurrent.SettableFuture;
-import com.google.protobuf.ByteString;
-import org.bitcoin.paymentchannel.Protos;
-import org.bitcoin.paymentchannel.Protos.TwoWayChannelMessage;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-
-import javax.net.SocketFactory;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.SocketAddress;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import static com.google.common.base.Preconditions.checkState;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-
-@RunWith(value = Parameterized.class)
-public class NetworkAbstractionTests {
- private static final int CLIENT_MAJOR_VERSION = 1;
- private AtomicBoolean fail;
- private final int clientType;
- private final ClientConnectionManager channels;
-
- @Parameterized.Parameters
- public static Collection parameters() {
- return Arrays.asList(new Integer[]{0}, new Integer[]{1}, new Integer[]{2}, new Integer[]{3});
- }
-
- public NetworkAbstractionTests(Integer clientType) throws Exception {
- this.clientType = clientType;
- if (clientType == 0) {
- channels = new NioClientManager();
- channels.startAsync();
- } else if (clientType == 1) {
- channels = new BlockingClientManager();
- channels.startAsync();
- } else
- channels = null;
- }
-
- private MessageWriteTarget openConnection(SocketAddress addr, ProtobufParser parser) throws Exception {
- if (clientType == 0 || clientType == 1) {
- channels.openConnection(addr, parser);
- if (parser.writeTarget.get() == null)
- Thread.sleep(100);
- return (MessageWriteTarget) parser.writeTarget.get();
- } else if (clientType == 2)
- return new NioClient(addr, parser, 100);
- else if (clientType == 3)
- return new BlockingClient(addr, parser, 100, SocketFactory.getDefault(), null);
- else
- throw new RuntimeException();
- }
-
- @Before
- public void setUp() {
- fail = new AtomicBoolean(false);
- }
-
- @After
- public void checkFail() {
- assertFalse(fail.get());
- }
-
- @Test
- public void testNullGetNewParser() throws Exception {
- final SettableFuture client1ConnectionOpened = SettableFuture.create();
- final SettableFuture client1Disconnected = SettableFuture.create();
- final SettableFuture client2MessageReceived = SettableFuture.create();
- final SettableFuture serverConnectionOpen = SettableFuture.create();
- final SettableFuture client2ConnectionOpened = SettableFuture.create();
- final SettableFuture serverConnectionClosed = SettableFuture.create();
- final SettableFuture client2Disconnected = SettableFuture.create();
- NioServer server = new NioServer(new StreamParserFactory() {
- boolean finishedFirst = false;
- @Override
- public ProtobufParser getNewParser(InetAddress inetAddress, int port) {
- if (!finishedFirst) {
- finishedFirst = true;
- return null;
- }
-
- return new ProtobufParser(new ProtobufParser.Listener() {
- @Override
- public void messageReceived(ProtobufParser handler, Protos.TwoWayChannelMessage msg) {
- handler.write(msg);
- }
-
- @Override
- public void connectionOpen(ProtobufParser handler) {
- serverConnectionOpen.set(null);
- }
-
- @Override
- public void connectionClosed(ProtobufParser handler) {
- serverConnectionClosed.set(null);
- }
- }, Protos.TwoWayChannelMessage.getDefaultInstance(), 1000, 0);
- }
- }, new InetSocketAddress("localhost", 4243));
- server.startAsync();
- server.awaitRunning();
-
- ProtobufParser clientHandler = new ProtobufParser(
- new ProtobufParser.Listener() {
- @Override
- public synchronized void messageReceived(ProtobufParser handler, Protos.TwoWayChannelMessage msg) {
- fail.set(true);
- }
-
- @Override
- public void connectionOpen(ProtobufParser handler) {
- client1ConnectionOpened.set(null);
- }
-
- @Override
- public void connectionClosed(ProtobufParser handler) {
- client1Disconnected.set(null);
- }
- }, Protos.TwoWayChannelMessage.getDefaultInstance(), 1000, 0);
- openConnection(new InetSocketAddress("localhost", 4243), clientHandler);
-
- client1ConnectionOpened.get();
- client1Disconnected.get();
-
- clientHandler = new ProtobufParser(
- new ProtobufParser.Listener() {
- @Override
- public synchronized void messageReceived(ProtobufParser handler, Protos.TwoWayChannelMessage msg) {
- if (client2MessageReceived.isDone())
- fail.set(true);
- client2MessageReceived.set(msg);
- }
-
- @Override
- public void connectionOpen(ProtobufParser handler) {
- client2ConnectionOpened.set(null);
- }
-
- @Override
- public void connectionClosed(ProtobufParser handler) {
- client2Disconnected.set(null);
- }
- }, Protos.TwoWayChannelMessage.getDefaultInstance(), 1000, 0);
- MessageWriteTarget client = openConnection(new InetSocketAddress("localhost", 4243), clientHandler);
-
- serverConnectionOpen.get();
- client2ConnectionOpened.get();
-
- Protos.TwoWayChannelMessage msg = Protos.TwoWayChannelMessage.newBuilder().setType(Protos.TwoWayChannelMessage.MessageType.CHANNEL_OPEN).build();
- clientHandler.write(msg);
-
- assertEquals(msg, client2MessageReceived.get());
-
- client.closeConnection();
- serverConnectionClosed.get();
- client2Disconnected.get();
-
- server.stopAsync().awaitTerminated();
- }
-
- @Test
- public void basicClientServerTest() throws Exception {
- // Tests creating a basic server, opening a client connection and sending a few messages
-
- final SettableFuture serverConnectionOpen = SettableFuture.create();
- final SettableFuture clientConnectionOpen = SettableFuture.create();
- final SettableFuture serverConnectionClosed = SettableFuture.create();
- final SettableFuture clientConnectionClosed = SettableFuture.create();
- final SettableFuture clientMessage1Received = SettableFuture.create();
- final SettableFuture clientMessage2Received = SettableFuture.create();
- NioServer server = new NioServer(new StreamParserFactory() {
- @Override
- public ProtobufParser getNewParser(InetAddress inetAddress, int port) {
- return new ProtobufParser(new ProtobufParser.Listener() {
- @Override
- public void messageReceived(ProtobufParser handler, Protos.TwoWayChannelMessage msg) {
- handler.write(msg);
- handler.write(msg);
- }
-
- @Override
- public void connectionOpen(ProtobufParser handler) {
- serverConnectionOpen.set(null);
- }
-
- @Override
- public void connectionClosed(ProtobufParser handler) {
- serverConnectionClosed.set(null);
- }
- }, Protos.TwoWayChannelMessage.getDefaultInstance(), 1000, 0);
- }
- }, new InetSocketAddress("localhost", 4243));
- server.startAsync();
- server.awaitRunning();
-
- ProtobufParser clientHandler = new ProtobufParser(
- new ProtobufParser.Listener() {
- @Override
- public synchronized void messageReceived(ProtobufParser handler, Protos.TwoWayChannelMessage msg) {
- if (clientMessage1Received.isDone())
- clientMessage2Received.set(msg);
- else
- clientMessage1Received.set(msg);
- }
-
- @Override
- public void connectionOpen(ProtobufParser handler) {
- clientConnectionOpen.set(null);
- }
-
- @Override
- public void connectionClosed(ProtobufParser handler) {
- clientConnectionClosed.set(null);
- }
- }, Protos.TwoWayChannelMessage.getDefaultInstance(), 1000, 0);
-
- MessageWriteTarget client = openConnection(new InetSocketAddress("localhost", 4243), clientHandler);
-
- clientConnectionOpen.get();
- serverConnectionOpen.get();
-
- Protos.TwoWayChannelMessage msg = Protos.TwoWayChannelMessage.newBuilder().setType(Protos.TwoWayChannelMessage.MessageType.CHANNEL_OPEN).build();
- clientHandler.write(msg);
- assertEquals(msg, clientMessage1Received.get());
- assertEquals(msg, clientMessage2Received.get());
-
- client.closeConnection();
- serverConnectionClosed.get();
- clientConnectionClosed.get();
-
- server.stopAsync();
- server.awaitTerminated();
- assertFalse(server.isRunning());
- }
-
- @Test
- public void basicTimeoutTest() throws Exception {
- // Tests various timeout scenarios
-
- final SettableFuture serverConnection1Open = SettableFuture.create();
- final SettableFuture clientConnection1Open = SettableFuture.create();
- final SettableFuture serverConnection1Closed = SettableFuture.create();
- final SettableFuture clientConnection1Closed = SettableFuture.create();
-
- final SettableFuture serverConnection2Open = SettableFuture.create();
- final SettableFuture clientConnection2Open = SettableFuture.create();
- final SettableFuture serverConnection2Closed = SettableFuture.create();
- final SettableFuture clientConnection2Closed = SettableFuture.create();
- NioServer server = new NioServer(new StreamParserFactory() {
- @Override
- public ProtobufParser getNewParser(InetAddress inetAddress, int port) {
- return new ProtobufParser(new ProtobufParser.Listener() {
- @Override
- public void messageReceived(ProtobufParser handler, Protos.TwoWayChannelMessage msg) {
- fail.set(true);
- }
-
- @Override
- public synchronized void connectionOpen(ProtobufParser handler) {
- if (serverConnection1Open.isDone()) {
- handler.setSocketTimeout(0);
- serverConnection2Open.set(null);
- } else
- serverConnection1Open.set(null);
- }
-
- @Override
- public synchronized void connectionClosed(ProtobufParser handler) {
- if (serverConnection1Closed.isDone()) {
- serverConnection2Closed.set(null);
- } else
- serverConnection1Closed.set(null);
- }
- }, Protos.TwoWayChannelMessage.getDefaultInstance(), 1000, 10);
- }
- }, new InetSocketAddress("localhost", 4243));
- server.startAsync();
- server.awaitRunning();
-
- openConnection(new InetSocketAddress("localhost", 4243), new ProtobufParser(
- new ProtobufParser.Listener() {
- @Override
- public void messageReceived(ProtobufParser handler, Protos.TwoWayChannelMessage msg) {
- fail.set(true);
- }
-
- @Override
- public void connectionOpen(ProtobufParser handler) {
- clientConnection1Open.set(null);
- }
-
- @Override
- public void connectionClosed(ProtobufParser handler) {
- clientConnection1Closed.set(null);
- }
- }, Protos.TwoWayChannelMessage.getDefaultInstance(), 1000, 0));
-
- clientConnection1Open.get();
- serverConnection1Open.get();
- long closeDelayStart = System.currentTimeMillis();
- clientConnection1Closed.get();
- serverConnection1Closed.get();
- long closeDelayFinish = System.currentTimeMillis();
-
- ProtobufParser client2Handler = new ProtobufParser(
- new ProtobufParser.Listener() {
- @Override
- public void messageReceived(ProtobufParser handler, Protos.TwoWayChannelMessage msg) {
- fail.set(true);
- }
-
- @Override
- public void connectionOpen(ProtobufParser handler) {
- clientConnection2Open.set(null);
- }
-
- @Override
- public void connectionClosed(ProtobufParser handler) {
- clientConnection2Closed.set(null);
- }
- }, Protos.TwoWayChannelMessage.getDefaultInstance(), 1000, 0);
- openConnection(new InetSocketAddress("localhost", 4243), client2Handler);
-
- clientConnection2Open.get();
- serverConnection2Open.get();
- Thread.sleep((closeDelayFinish - closeDelayStart) * 10);
- assertFalse(clientConnection2Closed.isDone() || serverConnection2Closed.isDone());
-
- client2Handler.setSocketTimeout(10);
- clientConnection2Closed.get();
- serverConnection2Closed.get();
-
- server.stopAsync();
- server.awaitTerminated();
- }
-
- @Test
- public void largeDataTest() throws Exception {
- /** Test various large-data handling, essentially testing {@link ProtobufParser#receiveBytes(java.nio.ByteBuffer)} */
- final SettableFuture serverConnectionOpen = SettableFuture.create();
- final SettableFuture clientConnectionOpen = SettableFuture.create();
- final SettableFuture serverConnectionClosed = SettableFuture.create();
- final SettableFuture clientConnectionClosed = SettableFuture.create();
- final SettableFuture clientMessage1Received = SettableFuture.create();
- final SettableFuture clientMessage2Received = SettableFuture.create();
- final SettableFuture clientMessage3Received = SettableFuture.create();
- final SettableFuture clientMessage4Received = SettableFuture.create();
- NioServer server = new NioServer(new StreamParserFactory() {
- @Override
- public ProtobufParser getNewParser(InetAddress inetAddress, int port) {
- return new ProtobufParser(new ProtobufParser.Listener() {
- @Override
- public void messageReceived(ProtobufParser handler, Protos.TwoWayChannelMessage msg) {
- handler.write(msg);
- }
-
- @Override
- public void connectionOpen(ProtobufParser handler) {
- serverConnectionOpen.set(null);
- }
-
- @Override
- public void connectionClosed(ProtobufParser handler) {
- serverConnectionClosed.set(null);
- }
- }, Protos.TwoWayChannelMessage.getDefaultInstance(), 0x10000, 0);
- }
- }, new InetSocketAddress("localhost", 4243));
- server.startAsync();
- server.awaitRunning();
-
- ProtobufParser clientHandler = new ProtobufParser(
- new ProtobufParser.Listener() {
- @Override
- public synchronized void messageReceived(ProtobufParser handler, Protos.TwoWayChannelMessage msg) {
- if (clientMessage1Received.isDone()) {
- if (clientMessage2Received.isDone()) {
- if (clientMessage3Received.isDone()) {
- if (clientMessage4Received.isDone())
- fail.set(true);
- clientMessage4Received.set(msg);
- } else
- clientMessage3Received.set(msg);
- } else
- clientMessage2Received.set(msg);
- } else
- clientMessage1Received.set(msg);
- }
-
- @Override
- public void connectionOpen(ProtobufParser handler) {
- clientConnectionOpen.set(null);
- }
-
- @Override
- public void connectionClosed(ProtobufParser handler) {
- clientConnectionClosed.set(null);
- }
- }, Protos.TwoWayChannelMessage.getDefaultInstance(), 0x10000, 0);
-
- MessageWriteTarget client = openConnection(new InetSocketAddress("localhost", 4243), clientHandler);
-
- clientConnectionOpen.get();
- serverConnectionOpen.get();
-
- // Large message that is larger than buffer and equal to maximum message size
- Protos.TwoWayChannelMessage msg = Protos.TwoWayChannelMessage.newBuilder()
- .setType(Protos.TwoWayChannelMessage.MessageType.CHANNEL_OPEN)
- .setClientVersion(Protos.ClientVersion.newBuilder()
- .setMajor(CLIENT_MAJOR_VERSION)
- .setPreviousChannelContractHash(ByteString.copyFrom(new byte[0x10000 - 12])))
- .build();
- // Small message that fits in the buffer
- Protos.TwoWayChannelMessage msg2 = Protos.TwoWayChannelMessage.newBuilder()
- .setType(Protos.TwoWayChannelMessage.MessageType.CHANNEL_OPEN)
- .setClientVersion(Protos.ClientVersion.newBuilder()
- .setMajor(CLIENT_MAJOR_VERSION)
- .setPreviousChannelContractHash(ByteString.copyFrom(new byte[1])))
- .build();
- // Break up the message into chunks to simulate packet network (with strange MTUs...)
- byte[] messageBytes = msg.toByteArray();
- byte[] messageLength = new byte[4];
- Utils.uint32ToByteArrayBE(messageBytes.length, messageLength, 0);
- client.writeBytes(new byte[]{messageLength[0], messageLength[1]});
- Thread.sleep(10);
- client.writeBytes(new byte[]{messageLength[2], messageLength[3]});
- Thread.sleep(10);
- client.writeBytes(new byte[]{messageBytes[0], messageBytes[1]});
- Thread.sleep(10);
- client.writeBytes(Arrays.copyOfRange(messageBytes, 2, messageBytes.length - 1));
- Thread.sleep(10);
-
- // Now send the end of msg + msg2 + msg3 all at once
- byte[] messageBytes2 = msg2.toByteArray();
- byte[] messageLength2 = new byte[4];
- Utils.uint32ToByteArrayBE(messageBytes2.length, messageLength2, 0);
- byte[] sendBytes = Arrays.copyOf(new byte[] {messageBytes[messageBytes.length-1]}, 1 + messageBytes2.length*2 + messageLength2.length*2);
- System.arraycopy(messageLength2, 0, sendBytes, 1, 4);
- System.arraycopy(messageBytes2, 0, sendBytes, 5, messageBytes2.length);
- System.arraycopy(messageLength2, 0, sendBytes, 5 + messageBytes2.length, 4);
- System.arraycopy(messageBytes2, 0, sendBytes, 9 + messageBytes2.length, messageBytes2.length);
- client.writeBytes(sendBytes);
- assertEquals(msg, clientMessage1Received.get());
- assertEquals(msg2, clientMessage2Received.get());
- assertEquals(msg2, clientMessage3Received.get());
-
- // Now resent msg2 in chunks, by itself
- Utils.uint32ToByteArrayBE(messageBytes2.length, messageLength2, 0);
- client.writeBytes(new byte[]{messageLength2[0], messageLength2[1]});
- Thread.sleep(10);
- client.writeBytes(new byte[]{messageLength2[2], messageLength2[3]});
- Thread.sleep(10);
- client.writeBytes(new byte[]{messageBytes2[0], messageBytes2[1]});
- Thread.sleep(10);
- client.writeBytes(new byte[]{messageBytes2[2], messageBytes2[3]});
- Thread.sleep(10);
- client.writeBytes(Arrays.copyOfRange(messageBytes2, 4, messageBytes2.length));
- assertEquals(msg2, clientMessage4Received.get());
-
- Protos.TwoWayChannelMessage msg5 = Protos.TwoWayChannelMessage.newBuilder()
- .setType(Protos.TwoWayChannelMessage.MessageType.CHANNEL_OPEN)
- .setClientVersion(Protos.ClientVersion.newBuilder()
- .setMajor(CLIENT_MAJOR_VERSION)
- .setPreviousChannelContractHash(ByteString.copyFrom(new byte[0x10000 - 11])))
- .build();
- try {
- clientHandler.write(msg5);
- } catch (IllegalStateException e) {}
-
- // Override max size and make sure the server drops our connection
- byte[] messageLength5 = new byte[4];
- Utils.uint32ToByteArrayBE(msg5.toByteArray().length, messageLength5, 0);
- client.writeBytes(messageLength5);
-
- serverConnectionClosed.get();
- clientConnectionClosed.get();
-
- server.stopAsync();
- server.awaitTerminated();
- }
-
- @Test
- public void testConnectionEventHandlers() throws Exception {
- final SettableFuture serverConnection1Open = SettableFuture.create();
- final SettableFuture serverConnection2Open = SettableFuture.create();
- final SettableFuture serverConnection3Open = SettableFuture.create();
- final SettableFuture client1ConnectionOpen = SettableFuture.create();
- final SettableFuture client2ConnectionOpen = SettableFuture.create();
- final SettableFuture client3ConnectionOpen = SettableFuture.create();
- final SettableFuture serverConnectionClosed1 = SettableFuture.create();
- final SettableFuture serverConnectionClosed2 = SettableFuture.create();
- final SettableFuture serverConnectionClosed3 = SettableFuture.create();
- final SettableFuture client1ConnectionClosed = SettableFuture.create();
- final SettableFuture client2ConnectionClosed = SettableFuture.create();
- final SettableFuture client3ConnectionClosed = SettableFuture.create();
- final SettableFuture client1MessageReceived = SettableFuture.create();
- final SettableFuture client2MessageReceived = SettableFuture.create();
- final SettableFuture client3MessageReceived = SettableFuture.create();
- NioServer server = new NioServer(new StreamParserFactory() {
- @Override
- public ProtobufParser getNewParser(InetAddress inetAddress, int port) {
- return new ProtobufParser(new ProtobufParser.Listener() {
- @Override
- public void messageReceived(ProtobufParser handler, Protos.TwoWayChannelMessage msg) {
- handler.write(msg);
- }
-
- @Override
- public synchronized void connectionOpen(ProtobufParser handler) {
- if (serverConnection1Open.isDone()) {
- if (serverConnection2Open.isDone())
- serverConnection3Open.set(null);
- else
- serverConnection2Open.set(null);
- } else
- serverConnection1Open.set(null);
- }
-
- @Override
- public synchronized void connectionClosed(ProtobufParser handler) {
- if (serverConnectionClosed1.isDone()) {
- if (serverConnectionClosed2.isDone()) {
- checkState(!serverConnectionClosed3.isDone());
- serverConnectionClosed3.set(null);
- } else
- serverConnectionClosed2.set(null);
- } else
- serverConnectionClosed1.set(null);
- }
- }, Protos.TwoWayChannelMessage.getDefaultInstance(), 1000, 0);
- }
- }, new InetSocketAddress("localhost", 4243));
- server.startAsync();
- server.awaitRunning();
-
- ProtobufParser client1Handler = new ProtobufParser(
- new ProtobufParser.Listener() {
- @Override
- public void messageReceived(ProtobufParser handler, Protos.TwoWayChannelMessage msg) {
- client1MessageReceived.set(msg);
- }
-
- @Override
- public void connectionOpen(ProtobufParser handler) {
- client1ConnectionOpen.set(null);
- }
-
- @Override
- public void connectionClosed(ProtobufParser handler) {
- client1ConnectionClosed.set(null);
- }
- }, Protos.TwoWayChannelMessage.getDefaultInstance(), 1000, 0);
- MessageWriteTarget client1 = openConnection(new InetSocketAddress("localhost", 4243), client1Handler);
-
- client1ConnectionOpen.get();
- serverConnection1Open.get();
-
- ProtobufParser client2Handler = new ProtobufParser(
- new ProtobufParser.Listener() {
- @Override
- public void messageReceived(ProtobufParser handler, Protos.TwoWayChannelMessage msg) {
- client2MessageReceived.set(msg);
- }
-
- @Override
- public void connectionOpen(ProtobufParser handler) {
- client2ConnectionOpen.set(null);
- }
-
- @Override
- public void connectionClosed(ProtobufParser handler) {
- client2ConnectionClosed.set(null);
- }
- }, Protos.TwoWayChannelMessage.getDefaultInstance(), 1000, 0);
- openConnection(new InetSocketAddress("localhost", 4243), client2Handler);
-
- client2ConnectionOpen.get();
- serverConnection2Open.get();
-
- ProtobufParser client3Handler = new ProtobufParser(
- new ProtobufParser.Listener() {
- @Override
- public void messageReceived(ProtobufParser handler, Protos.TwoWayChannelMessage msg) {
- client3MessageReceived.set(msg);
- }
-
- @Override
- public void connectionOpen(ProtobufParser handler) {
- client3ConnectionOpen.set(null);
- }
-
- @Override
- public synchronized void connectionClosed(ProtobufParser handler) {
- checkState(!client3ConnectionClosed.isDone());
- client3ConnectionClosed.set(null);
- }
- }, Protos.TwoWayChannelMessage.getDefaultInstance(), 1000, 0);
- NioClient client3 = new NioClient(new InetSocketAddress("localhost", 4243), client3Handler, 0);
-
- client3ConnectionOpen.get();
- serverConnection3Open.get();
-
- Protos.TwoWayChannelMessage msg = Protos.TwoWayChannelMessage.newBuilder().setType(Protos.TwoWayChannelMessage.MessageType.CHANNEL_OPEN).build();
- client1Handler.write(msg);
- assertEquals(msg, client1MessageReceived.get());
-
- Protos.TwoWayChannelMessage msg2 = Protos.TwoWayChannelMessage.newBuilder().setType(Protos.TwoWayChannelMessage.MessageType.INITIATE).build();
- client2Handler.write(msg2);
- assertEquals(msg2, client2MessageReceived.get());
-
- client1.closeConnection();
- serverConnectionClosed1.get();
- client1ConnectionClosed.get();
-
- Protos.TwoWayChannelMessage msg3 = Protos.TwoWayChannelMessage.newBuilder().setType(Protos.TwoWayChannelMessage.MessageType.CLOSE).build();
- client3Handler.write(msg3);
- assertEquals(msg3, client3MessageReceived.get());
-
- // Try to create a race condition by triggering handlerThread closing and client3 closing at the same time
- // This often triggers ClosedByInterruptException in handleKey
- server.stopAsync();
- server.selector.wakeup();
- client3.closeConnection();
- client3ConnectionClosed.get();
- serverConnectionClosed3.get();
-
- server.stopAsync();
- server.awaitTerminated();
- client2ConnectionClosed.get();
- serverConnectionClosed2.get();
-
- server.stopAsync();
- server.awaitTerminated();
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/net/discovery/SeedPeersTest.java b/core/src/test/java/com/dogecoin/dogecoinj/net/discovery/SeedPeersTest.java
deleted file mode 100644
index cfdc198f..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/net/discovery/SeedPeersTest.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * Copyright 2011 Micheal Swiggs
- *
- * 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 com.dogecoin.dogecoinj.net.discovery;
-
-import com.dogecoin.dogecoinj.params.MainNetParams;
-import org.junit.Test;
-
-import java.net.InetSocketAddress;
-import java.util.concurrent.TimeUnit;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.junit.Assert.assertThat;
-
-public class SeedPeersTest {
- @Test
- public void getPeer_one() throws Exception{
- SeedPeers seedPeers = new SeedPeers(MainNetParams.get());
- assertThat(seedPeers.getPeer(), notNullValue());
- }
-
- @Test
- public void getPeer_all() throws Exception{
- SeedPeers seedPeers = new SeedPeers(MainNetParams.get());
- for(int i = 0; i < SeedPeers.seedAddrs.length; ++i){
- assertThat("Failed on index: "+i, seedPeers.getPeer(), notNullValue());
- }
- assertThat(seedPeers.getPeer(), equalTo(null));
- }
-
- @Test
- public void getPeers_length() throws Exception{
- SeedPeers seedPeers = new SeedPeers(MainNetParams.get());
- InetSocketAddress[] addresses = seedPeers.getPeers(0, TimeUnit.SECONDS);
- assertThat(addresses.length, equalTo(SeedPeers.seedAddrs.length));
- }
-}
diff --git a/core/src/test/java/com/dogecoin/dogecoinj/protocols/channels/ChannelConnectionTest.java b/core/src/test/java/com/dogecoin/dogecoinj/protocols/channels/ChannelConnectionTest.java
deleted file mode 100644
index 13b615c3..00000000
--- a/core/src/test/java/com/dogecoin/dogecoinj/protocols/channels/ChannelConnectionTest.java
+++ /dev/null
@@ -1,781 +0,0 @@
-/*
- * 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 com.dogecoin.dogecoinj.protocols.channels;
-
-import com.dogecoin.dogecoinj.core.*;
-import com.dogecoin.dogecoinj.store.WalletProtobufSerializer;
-import com.dogecoin.dogecoinj.testing.TestWithWallet;
-import com.dogecoin.dogecoinj.utils.Threading;
-import com.dogecoin.dogecoinj.wallet.WalletFiles;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.SettableFuture;
-import com.google.protobuf.ByteString;
-import org.bitcoin.paymentchannel.Protos;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.spongycastle.crypto.params.KeyParameter;
-
-import javax.annotation.Nullable;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.net.InetSocketAddress;
-import java.net.SocketAddress;
-import java.util.Arrays;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import static com.dogecoin.dogecoinj.core.Coin.*;
-import static com.dogecoin.dogecoinj.protocols.channels.PaymentChannelCloseException.CloseReason;
-import static com.dogecoin.dogecoinj.testing.FakeTxBuilder.createFakeBlock;
-import static org.bitcoin.paymentchannel.Protos.TwoWayChannelMessage.MessageType;
-import static org.junit.Assert.*;
-
-public class ChannelConnectionTest extends TestWithWallet {
- private static final int CLIENT_MAJOR_VERSION = 1;
- private Wallet serverWallet;
- private BlockChain serverChain;
- private AtomicBoolean fail;
- private BlockingQueue