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

Wrap coin-ish BigIntegers into Coin class.

This commit is contained in:
Andreas Schildbach 2014-04-25 21:21:11 +02:00 committed by Mike Hearn
parent d2e1b14d4c
commit 022e7c27fe
66 changed files with 793 additions and 687 deletions

View File

@ -19,7 +19,6 @@ package com.google.bitcoin.core;
import com.google.bitcoin.script.Script; import com.google.bitcoin.script.Script;
import com.google.bitcoin.wallet.AbstractKeyChainEventListener; import com.google.bitcoin.wallet.AbstractKeyChainEventListener;
import java.math.BigInteger;
import java.util.List; import java.util.List;
/** /**
@ -27,12 +26,12 @@ import java.util.List;
*/ */
public abstract class AbstractWalletEventListener extends AbstractKeyChainEventListener implements WalletEventListener { public abstract class AbstractWalletEventListener extends AbstractKeyChainEventListener implements WalletEventListener {
@Override @Override
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
onChange(); onChange();
} }
@Override @Override
public void onCoinsSent(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { public void onCoinsSent(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
onChange(); onChange();
} }

View File

@ -166,7 +166,7 @@ public class Block extends Message {
* <p>The half-life is controlled by {@link com.google.bitcoin.core.NetworkParameters#getSubsidyDecreaseBlockCount()}. * <p>The half-life is controlled by {@link com.google.bitcoin.core.NetworkParameters#getSubsidyDecreaseBlockCount()}.
* </p> * </p>
*/ */
public BigInteger getBlockInflation(int height) { public Coin getBlockInflation(int height) {
return Utils.toNanoCoins(50, 0).shiftRight(height / params.getSubsidyDecreaseBlockCount()); return Utils.toNanoCoins(50, 0).shiftRight(height / params.getSubsidyDecreaseBlockCount());
} }
@ -953,7 +953,7 @@ public class Block extends Message {
static private int txCounter; static private int txCounter;
/** Adds a coinbase transaction to the block. This exists for unit tests. */ /** Adds a coinbase transaction to the block. This exists for unit tests. */
void addCoinbaseTransaction(byte[] pubKeyTo, BigInteger value) { void addCoinbaseTransaction(byte[] pubKeyTo, Coin value) {
unCacheTransactions(); unCacheTransactions();
transactions = new ArrayList<Transaction>(); transactions = new ArrayList<Transaction>();
Transaction coinbase = new Transaction(params); Transaction coinbase = new Transaction(params);
@ -989,7 +989,7 @@ public class Block extends Message {
* In this variant you can specify a public key (pubkey) for use in generating coinbase blocks. * In this variant you can specify a public key (pubkey) for use in generating coinbase blocks.
*/ */
Block createNextBlock(@Nullable Address to, @Nullable TransactionOutPoint prevOut, long time, Block createNextBlock(@Nullable Address to, @Nullable TransactionOutPoint prevOut, long time,
byte[] pubKey, BigInteger coinbaseValue) { byte[] pubKey, Coin coinbaseValue) {
Block b = new Block(params); Block b = new Block(params);
b.setDifficultyTarget(difficultyTarget); b.setDifficultyTarget(difficultyTarget);
b.addCoinbaseTransaction(pubKey, coinbaseValue); b.addCoinbaseTransaction(pubKey, coinbaseValue);
@ -1036,7 +1036,7 @@ public class Block extends Message {
} }
@VisibleForTesting @VisibleForTesting
public Block createNextBlock(@Nullable Address to, BigInteger value) { public Block createNextBlock(@Nullable Address to, Coin value) {
return createNextBlock(to, null, Utils.currentTimeSeconds(), pubkeyForTesting, value); return createNextBlock(to, null, Utils.currentTimeSeconds(), pubkeyForTesting, value);
} }
@ -1046,7 +1046,7 @@ public class Block extends Message {
} }
@VisibleForTesting @VisibleForTesting
public Block createNextBlockWithCoinbase(byte[] pubKey, BigInteger coinbaseValue) { public Block createNextBlockWithCoinbase(byte[] pubKey, Coin coinbaseValue) {
return createNextBlock(null, null, Utils.currentTimeSeconds(), pubKey, coinbaseValue); return createNextBlock(null, null, Utils.currentTimeSeconds(), pubKey, coinbaseValue);
} }

View File

@ -0,0 +1,132 @@
/**
* 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.google.bitcoin.core;
import java.io.Serializable;
import java.math.BigInteger;
/**
* Represents a monetary Bitcoin value. This class is immutable.
*/
public final class Coin implements Comparable<Coin>, Serializable {
public static final Coin ZERO = new Coin(BigInteger.ZERO);
public static final Coin ONE = new Coin(BigInteger.ONE);
public static final Coin TEN = new Coin(BigInteger.TEN);
private final BigInteger value;
public Coin(final BigInteger value) {
this.value = value;
}
public Coin(final String value, final int radix) {
this(new BigInteger(value, radix));
}
public Coin(final byte[] value) {
this(new BigInteger(value));
}
public static Coin valueOf(final long value) {
return new Coin(BigInteger.valueOf(value));
}
public Coin add(final Coin value) {
return new Coin(this.value.add(value.value));
}
public Coin subtract(final Coin value) {
return new Coin(this.value.subtract(value.value));
}
public Coin multiply(final Coin value) {
return new Coin(this.value.multiply(value.value));
}
public Coin multiply(final long value) {
return multiply(Coin.valueOf(value));
}
public Coin divide(final Coin value) {
return new Coin(this.value.divide(value.value));
}
public Coin[] divideAndRemainder(final Coin value) {
final BigInteger[] result = this.value.divideAndRemainder(value.value);
return new Coin[] { new Coin(result[0]), new Coin(result[1]) };
}
public Coin shiftLeft(final int n) {
return new Coin(this.value.shiftLeft(n));
}
public Coin shiftRight(final int n) {
return new Coin(this.value.shiftRight(n));
}
public int signum() {
return this.value.signum();
}
public Coin negate() {
return new Coin(this.value.negate());
}
public byte[] toByteArray() {
return this.value.toByteArray();
}
public long longValue() {
return this.value.longValue();
}
public double doubleValue() {
return this.value.doubleValue();
}
public BigInteger toBigInteger() {
return value;
}
@Override
public String toString() {
return value.toString();
}
@Override
public boolean equals(final Object o) {
if (o == this)
return true;
if (o == null || o.getClass() != getClass())
return false;
final Coin other = (Coin) o;
if (!this.value.equals(other.value))
return false;
return true;
}
@Override
public int hashCode() {
return this.value.hashCode();
}
@Override
public int compareTo(final Coin other) {
return this.value.compareTo(other.value);
}
}

View File

@ -23,7 +23,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.math.BigInteger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -175,12 +174,12 @@ public class FullPrunedBlockChain extends AbstractBlockChain {
sigOps += tx.getSigOpCount(); sigOps += tx.getSigOpCount();
} }
} }
BigInteger totalFees = BigInteger.ZERO; Coin totalFees = Coin.ZERO;
BigInteger coinbaseValue = null; Coin coinbaseValue = null;
for (final Transaction tx : block.transactions) { for (final Transaction tx : block.transactions) {
boolean isCoinBase = tx.isCoinBase(); boolean isCoinBase = tx.isCoinBase();
BigInteger valueIn = BigInteger.ZERO; Coin valueIn = Coin.ZERO;
BigInteger valueOut = BigInteger.ZERO; Coin valueOut = Coin.ZERO;
final List<Script> prevOutScripts = new LinkedList<Script>(); final List<Script> prevOutScripts = new LinkedList<Script>();
if (!isCoinBase) { if (!isCoinBase) {
// For each input of the transaction remove the corresponding output from the set of unspent // For each input of the transaction remove the corresponding output from the set of unspent
@ -300,16 +299,16 @@ public class FullPrunedBlockChain extends AbstractBlockChain {
throw new VerificationException("Block failed BIP30 test!"); throw new VerificationException("Block failed BIP30 test!");
} }
} }
BigInteger totalFees = BigInteger.ZERO; Coin totalFees = Coin.ZERO;
BigInteger coinbaseValue = null; Coin coinbaseValue = null;
if (scriptVerificationExecutor.isShutdown()) if (scriptVerificationExecutor.isShutdown())
scriptVerificationExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); scriptVerificationExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
List<Future<VerificationException>> listScriptVerificationResults = new ArrayList<Future<VerificationException>>(transactions.size()); List<Future<VerificationException>> listScriptVerificationResults = new ArrayList<Future<VerificationException>>(transactions.size());
for(final Transaction tx : transactions) { for(final Transaction tx : transactions) {
boolean isCoinBase = tx.isCoinBase(); boolean isCoinBase = tx.isCoinBase();
BigInteger valueIn = BigInteger.ZERO; Coin valueIn = Coin.ZERO;
BigInteger valueOut = BigInteger.ZERO; Coin valueOut = Coin.ZERO;
final List<Script> prevOutScripts = new LinkedList<Script>(); final List<Script> prevOutScripts = new LinkedList<Script>();
if (!isCoinBase) { if (!isCoinBase) {
for (int index = 0; index < tx.getInputs().size(); index++) { for (int index = 0; index < tx.getInputs().size(); index++) {

View File

@ -17,7 +17,6 @@
package com.google.bitcoin.core; package com.google.bitcoin.core;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.math.BigInteger;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -27,17 +26,17 @@ import static com.google.common.base.Preconditions.checkNotNull;
public class InsufficientMoneyException extends Exception { public class InsufficientMoneyException extends Exception {
/** Contains the number of satoshis that would have been required to complete the operation. */ /** Contains the number of satoshis that would have been required to complete the operation. */
@Nullable @Nullable
public final BigInteger missing; public final Coin missing;
protected InsufficientMoneyException() { protected InsufficientMoneyException() {
this.missing = null; this.missing = null;
} }
public InsufficientMoneyException(BigInteger missing) { public InsufficientMoneyException(Coin missing) {
this(missing, "Insufficient money, missing " + missing + " satoshis"); this(missing, "Insufficient money, missing " + missing + " satoshis");
} }
public InsufficientMoneyException(BigInteger missing, String message) { public InsufficientMoneyException(Coin missing, String message) {
super(message); super(message);
this.missing = checkNotNull(missing); this.missing = checkNotNull(missing);
} }

View File

@ -133,7 +133,7 @@ public abstract class NetworkParameters implements Serializable {
/** /**
* The maximum money to be generated * The maximum money to be generated
*/ */
public static final BigInteger MAX_MONEY = new BigInteger("21000000", 10).multiply(COIN); public static final Coin MAX_MONEY = new Coin("21000000", 10).multiply(COIN);
/** Alias for TestNet3Params.get(), use that instead. */ /** Alias for TestNet3Params.get(), use that instead. */
@Deprecated @Deprecated

View File

@ -45,7 +45,6 @@ import javax.annotation.Nullable;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.math.BigInteger;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.*; import java.util.*;
@ -179,7 +178,7 @@ public class PeerGroup extends AbstractExecutionThreadService implements Transac
} }
@Override @Override
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
// We received a relevant transaction. We MAY need to recalculate and resend the Bloom filter, but only // We received a relevant transaction. We MAY need to recalculate and resend the Bloom filter, but only
// if we have received a transaction that includes a relevant pay-to-pubkey output. // if we have received a transaction that includes a relevant pay-to-pubkey output.
// //

View File

@ -17,7 +17,6 @@
package com.google.bitcoin.core; package com.google.bitcoin.core;
import java.io.*; import java.io.*;
import java.math.BigInteger;
/** /**
* A StoredTransactionOutput message contains the information necessary to check a spending transaction. * A StoredTransactionOutput message contains the information necessary to check a spending transaction.
@ -31,7 +30,7 @@ public class StoredTransactionOutput implements Serializable {
* A transaction output has some value and a script used for authenticating that the redeemer is allowed to spend * A transaction output has some value and a script used for authenticating that the redeemer is allowed to spend
* this output. * this output.
*/ */
private BigInteger value; private Coin value;
private byte[] scriptBytes; private byte[] scriptBytes;
/** Hash of the transaction to which we refer. */ /** Hash of the transaction to which we refer. */
@ -53,7 +52,7 @@ public class StoredTransactionOutput implements Serializable {
* @param height the height this output was created in * @param height the height this output was created in
* @param scriptBytes * @param scriptBytes
*/ */
public StoredTransactionOutput(Sha256Hash hash, long index, BigInteger value, int height, boolean isCoinbase, byte[] scriptBytes) { public StoredTransactionOutput(Sha256Hash hash, long index, Coin value, int height, boolean isCoinbase, byte[] scriptBytes) {
this.hash = hash; this.hash = hash;
this.index = index; this.index = index;
this.value = value; this.value = value;
@ -73,7 +72,7 @@ public class StoredTransactionOutput implements Serializable {
byte[] valueBytes = new byte[8]; byte[] valueBytes = new byte[8];
if (in.read(valueBytes, 0, 8) != 8) if (in.read(valueBytes, 0, 8) != 8)
throw new EOFException(); throw new EOFException();
value = BigInteger.valueOf(Utils.readInt64(valueBytes, 0)); value = Coin.valueOf(Utils.readInt64(valueBytes, 0));
int scriptBytesLength = ((in.read() & 0xFF) << 0) | int scriptBytesLength = ((in.read() & 0xFF) << 0) |
((in.read() & 0xFF) << 8) | ((in.read() & 0xFF) << 8) |
@ -103,7 +102,7 @@ public class StoredTransactionOutput implements Serializable {
* The value which this Transaction output holds * The value which this Transaction output holds
* @return the value * @return the value
*/ */
public BigInteger getValue() { public Coin getValue() {
return value; return value;
} }
@ -157,7 +156,7 @@ public class StoredTransactionOutput implements Serializable {
} }
public void serializeToStream(OutputStream bos) throws IOException { public void serializeToStream(OutputStream bos) throws IOException {
Utils.uint64ToByteStreamLE(value, bos); Utils.uint64ToByteStreamLE(value.toBigInteger(), bos);
bos.write(0xFF & scriptBytes.length >> 0); bos.write(0xFF & scriptBytes.length >> 0);
bos.write(0xFF & scriptBytes.length >> 8); bos.write(0xFF & scriptBytes.length >> 8);

View File

@ -33,7 +33,6 @@ import org.spongycastle.crypto.params.KeyParameter;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.io.*; import java.io.*;
import java.math.BigInteger;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.*; import java.util.*;
@ -87,14 +86,14 @@ public class Transaction extends ChildMessage implements Serializable {
* If fee is lower than this value (in satoshis), a default reference client will treat it as if there were no fee. * If fee is lower than this value (in satoshis), a default reference client will treat it as if there were no fee.
* Currently this is 10000 satoshis. * Currently this is 10000 satoshis.
*/ */
public static final BigInteger REFERENCE_DEFAULT_MIN_TX_FEE = BigInteger.valueOf(10000); public static final Coin REFERENCE_DEFAULT_MIN_TX_FEE = Coin.valueOf(10000);
/** /**
* Any standard (ie pay-to-address) output smaller than this value (in satoshis) will most likely be rejected by the network. * Any standard (ie pay-to-address) output smaller than this value (in satoshis) will most likely be rejected by the network.
* This is calculated by assuming a standard output will be 34 bytes, and then using the formula used in * This is calculated by assuming a standard output will be 34 bytes, and then using the formula used in
* {@link TransactionOutput#getMinNonDustValue(BigInteger)}. Currently it's 5460 satoshis. * {@link TransactionOutput#getMinNonDustValue(Coin)}. Currently it's 5460 satoshis.
*/ */
public static final BigInteger MIN_NONDUST_OUTPUT = BigInteger.valueOf(5460); public static final Coin MIN_NONDUST_OUTPUT = Coin.valueOf(5460);
// These are serialized in both bitcoin and java serialization. // These are serialized in both bitcoin and java serialization.
private long version; private long version;
@ -237,10 +236,10 @@ public class Transaction extends ChildMessage implements Serializable {
* Calculates the sum of the outputs that are sending coins to a key in the wallet. The flag controls whether to * Calculates the sum of the outputs that are sending coins to a key in the wallet. The flag controls whether to
* include spent outputs or not. * include spent outputs or not.
*/ */
BigInteger getValueSentToMe(Wallet wallet, boolean includeSpent) { Coin getValueSentToMe(Wallet wallet, boolean includeSpent) {
maybeParse(); maybeParse();
// This is tested in WalletTest. // This is tested in WalletTest.
BigInteger v = BigInteger.ZERO; Coin v = Coin.ZERO;
for (TransactionOutput o : outputs) { for (TransactionOutput o : outputs) {
if (!o.isMineOrWatched(wallet)) continue; if (!o.isMineOrWatched(wallet)) continue;
if (!includeSpent && !o.isAvailableForSpending()) continue; if (!includeSpent && !o.isAvailableForSpending()) continue;
@ -275,7 +274,7 @@ public class Transaction extends ChildMessage implements Serializable {
/** /**
* Calculates the sum of the outputs that are sending coins to a key in the wallet. * Calculates the sum of the outputs that are sending coins to a key in the wallet.
*/ */
public BigInteger getValueSentToMe(Wallet wallet) { public Coin getValueSentToMe(Wallet wallet) {
return getValueSentToMe(wallet, true); return getValueSentToMe(wallet, true);
} }
@ -347,10 +346,10 @@ public class Transaction extends ChildMessage implements Serializable {
* *
* @return sum in nanocoins. * @return sum in nanocoins.
*/ */
public BigInteger getValueSentFromMe(Wallet wallet) throws ScriptException { public Coin getValueSentFromMe(Wallet wallet) throws ScriptException {
maybeParse(); maybeParse();
// This is tested in WalletTest. // This is tested in WalletTest.
BigInteger v = BigInteger.ZERO; Coin v = Coin.ZERO;
for (TransactionInput input : inputs) { for (TransactionInput input : inputs) {
// This input is taking value from a transaction in our wallet. To discover the value, // This input is taking value from a transaction in our wallet. To discover the value,
// we must find the connected transaction. // we must find the connected transaction.
@ -373,7 +372,7 @@ public class Transaction extends ChildMessage implements Serializable {
/** /**
* Returns the difference of {@link Transaction#getValueSentFromMe(Wallet)} and {@link Transaction#getValueSentToMe(Wallet)}. * Returns the difference of {@link Transaction#getValueSentFromMe(Wallet)} and {@link Transaction#getValueSentToMe(Wallet)}.
*/ */
public BigInteger getValue(Wallet wallet) throws ScriptException { public Coin getValue(Wallet wallet) throws ScriptException {
return getValueSentToMe(wallet).subtract(getValueSentFromMe(wallet)); return getValueSentToMe(wallet).subtract(getValueSentFromMe(wallet));
} }
@ -383,8 +382,8 @@ public class Transaction extends ChildMessage implements Serializable {
* *
* @return fee, or null if it cannot be determined * @return fee, or null if it cannot be determined
*/ */
public BigInteger getFee() { public Coin getFee() {
BigInteger fee = BigInteger.ZERO; Coin fee = Coin.ZERO;
for (TransactionInput input : inputs) { for (TransactionInput input : inputs) {
if (input.getValue() == null) if (input.getValue() == null)
return null; return null;
@ -807,7 +806,7 @@ public class Transaction extends ChildMessage implements Serializable {
/** /**
* Creates an output based on the given address and value, adds it to this transaction, and returns the new output. * Creates an output based on the given address and value, adds it to this transaction, and returns the new output.
*/ */
public TransactionOutput addOutput(BigInteger value, Address address) { public TransactionOutput addOutput(Coin value, Address address) {
return addOutput(new TransactionOutput(params, this, value, address)); return addOutput(new TransactionOutput(params, this, value, address));
} }
@ -815,7 +814,7 @@ public class Transaction extends ChildMessage implements Serializable {
* Creates an output that pays to the given pubkey directly (no address) with the given value, adds it to this * Creates an output that pays to the given pubkey directly (no address) with the given value, adds it to this
* transaction, and returns the new output. * transaction, and returns the new output.
*/ */
public TransactionOutput addOutput(BigInteger value, ECKey pubkey) { public TransactionOutput addOutput(Coin value, ECKey pubkey) {
return addOutput(new TransactionOutput(params, this, value, pubkey)); return addOutput(new TransactionOutput(params, this, value, pubkey));
} }
@ -823,7 +822,7 @@ public class Transaction extends ChildMessage implements Serializable {
* Creates an output that pays to the given script. The address and key forms are specialisations of this method, * Creates an output that pays to the given script. The address and key forms are specialisations of this method,
* you won't normally need to use it unless you're doing unusual things. * you won't normally need to use it unless you're doing unusual things.
*/ */
public TransactionOutput addOutput(BigInteger value, Script script) { public TransactionOutput addOutput(Coin value, Script script) {
return addOutput(new TransactionOutput(params, this, value, script.getProgram())); return addOutput(new TransactionOutput(params, this, value, script.getProgram()));
} }
@ -1263,7 +1262,7 @@ public class Transaction extends ChildMessage implements Serializable {
if (this.getMessageSize() > Block.MAX_BLOCK_SIZE) if (this.getMessageSize() > Block.MAX_BLOCK_SIZE)
throw new VerificationException("Transaction larger than MAX_BLOCK_SIZE"); throw new VerificationException("Transaction larger than MAX_BLOCK_SIZE");
BigInteger valueOut = BigInteger.ZERO; Coin valueOut = Coin.ZERO;
for (TransactionOutput output : outputs) { for (TransactionOutput output : outputs) {
if (output.getValue().signum() < 0) if (output.getValue().signum() < 0)
throw new VerificationException("Transaction output negative"); throw new VerificationException("Transaction output negative");

View File

@ -25,7 +25,6 @@ import java.io.ObjectOutputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.Serializable; import java.io.Serializable;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.math.BigInteger;
import java.util.Arrays; import java.util.Arrays;
import java.util.Map; import java.util.Map;
@ -58,7 +57,7 @@ public class TransactionInput extends ChildMessage implements Serializable {
transient private WeakReference<Script> scriptSig; transient private WeakReference<Script> scriptSig;
/** Value of the output connected to the input, if known. This field does not participate in equals()/hashCode(). */ /** Value of the output connected to the input, if known. This field does not participate in equals()/hashCode(). */
@Nullable @Nullable
private final BigInteger value; private final Coin value;
// A pointer to the transaction that owns this input. // A pointer to the transaction that owns this input.
private final Transaction parentTransaction; private final Transaction parentTransaction;
@ -75,7 +74,7 @@ public class TransactionInput extends ChildMessage implements Serializable {
} }
public TransactionInput(NetworkParameters params, @Nullable Transaction parentTransaction, byte[] scriptBytes, public TransactionInput(NetworkParameters params, @Nullable Transaction parentTransaction, byte[] scriptBytes,
TransactionOutPoint outpoint, @Nullable BigInteger value) { TransactionOutPoint outpoint, @Nullable Coin value) {
super(params); super(params);
this.scriptBytes = scriptBytes; this.scriptBytes = scriptBytes;
this.outpoint = outpoint; this.outpoint = outpoint;
@ -267,7 +266,7 @@ public class TransactionInput extends ChildMessage implements Serializable {
* @return Value of the output connected to this input, if known. Null if unknown. * @return Value of the output connected to this input, if known. Null if unknown.
*/ */
@Nullable @Nullable
public BigInteger getValue() { public Coin getValue() {
return value; return value;
} }

View File

@ -18,16 +18,17 @@ package com.google.bitcoin.core;
import com.google.bitcoin.script.Script; import com.google.bitcoin.script.Script;
import com.google.bitcoin.script.ScriptBuilder; import com.google.bitcoin.script.ScriptBuilder;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.io.IOException; import java.io.IOException;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.Serializable; import java.io.Serializable;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.math.BigInteger;
import java.util.Arrays; import java.util.Arrays;
import static com.google.common.base.Preconditions.*; import static com.google.common.base.Preconditions.*;
@ -42,7 +43,7 @@ public class TransactionOutput extends ChildMessage implements Serializable {
// A transaction output has some value and a script used for authenticating that the redeemer is allowed to spend // A transaction output has some value and a script used for authenticating that the redeemer is allowed to spend
// this output. // this output.
private BigInteger value; private Coin value;
private byte[] scriptBytes; private byte[] scriptBytes;
// The script bytes are parsed and turned into a Script on demand. // The script bytes are parsed and turned into a Script on demand.
@ -91,22 +92,22 @@ public class TransactionOutput extends ChildMessage implements Serializable {
/** /**
* Creates an output that sends 'value' to the given address (public key hash). The amount should be created with * Creates an output that sends 'value' to the given address (public key hash). The amount should be created with
* something like {@link Utils#toNanoCoins(int, int)}. Typically you would use * something like {@link Utils#toNanoCoins(int, int)}. Typically you would use
* {@link Transaction#addOutput(java.math.BigInteger, Address)} instead of creating a TransactionOutput directly. * {@link Transaction#addOutput(java.math.Coin, Address)} instead of creating a TransactionOutput directly.
*/ */
public TransactionOutput(NetworkParameters params, @Nullable Transaction parent, BigInteger value, Address to) { public TransactionOutput(NetworkParameters params, @Nullable Transaction parent, Coin value, Address to) {
this(params, parent, value, ScriptBuilder.createOutputScript(to).getProgram()); this(params, parent, value, ScriptBuilder.createOutputScript(to).getProgram());
} }
/** /**
* Creates an output that sends 'value' to the given public key using a simple CHECKSIG script (no addresses). The * Creates an output that sends 'value' to the given public key using a simple CHECKSIG script (no addresses). The
* amount should be created with something like {@link Utils#toNanoCoins(int, int)}. Typically you would use * amount should be created with something like {@link Utils#toNanoCoins(int, int)}. Typically you would use
* {@link Transaction#addOutput(java.math.BigInteger, ECKey)} instead of creating an output directly. * {@link Transaction#addOutput(java.math.Coin, ECKey)} instead of creating an output directly.
*/ */
public TransactionOutput(NetworkParameters params, @Nullable Transaction parent, BigInteger value, ECKey to) { public TransactionOutput(NetworkParameters params, @Nullable Transaction parent, Coin value, ECKey to) {
this(params, parent, value, ScriptBuilder.createOutputScript(to).getProgram()); this(params, parent, value, ScriptBuilder.createOutputScript(to).getProgram());
} }
public TransactionOutput(NetworkParameters params, @Nullable Transaction parent, BigInteger value, byte[] scriptBytes) { public TransactionOutput(NetworkParameters params, @Nullable Transaction parent, Coin value, byte[] scriptBytes) {
super(params); super(params);
// Negative values obviously make no sense, except for -1 which is used as a sentinel value when calculating // Negative values obviously make no sense, except for -1 which is used as a sentinel value when calculating
// SIGHASH_SINGLE signatures, so unfortunately we have to allow that here. // SIGHASH_SINGLE signatures, so unfortunately we have to allow that here.
@ -134,11 +135,11 @@ public class TransactionOutput extends ChildMessage implements Serializable {
} }
protected void parseLite() throws ProtocolException { protected void parseLite() throws ProtocolException {
// TODO: There is no reason to use BigInteger for values, they are always smaller than 21 million * COIN // TODO: There is no reason to use Coin for values, they are always smaller than 21 million * COIN
// The only reason to use BigInteger would be to properly read values from the reference implementation, however // The only reason to use Coin would be to properly read values from the reference implementation, however
// the reference implementation uses signed 64-bit integers for its values as well (though it probably shouldn't) // the reference implementation uses signed 64-bit integers for its values as well (though it probably shouldn't)
long outputValue = readInt64(); long outputValue = readInt64();
value = BigInteger.valueOf(outputValue); value = Coin.valueOf(outputValue);
scriptLen = (int) readVarInt(); scriptLen = (int) readVarInt();
length = cursor - offset + scriptLen; length = cursor - offset + scriptLen;
} }
@ -160,7 +161,7 @@ public class TransactionOutput extends ChildMessage implements Serializable {
* Returns the value of this output in nanocoins. This is the amount of currency that the destination address * Returns the value of this output in nanocoins. This is the amount of currency that the destination address
* receives. * receives.
*/ */
public BigInteger getValue() { public Coin getValue() {
maybeParse(); maybeParse();
return value; return value;
} }
@ -168,7 +169,7 @@ public class TransactionOutput extends ChildMessage implements Serializable {
/** /**
* Sets the value of this output in nanocoins. * Sets the value of this output in nanocoins.
*/ */
public void setValue(BigInteger value) { public void setValue(Coin value) {
checkNotNull(value); checkNotNull(value);
unCache(); unCache();
this.value = value; this.value = value;
@ -197,15 +198,15 @@ public class TransactionOutput extends ChildMessage implements Serializable {
* @param feePerKbRequired The fee required per kilobyte. Note that this is the same as the reference client's -minrelaytxfee * 3 * @param feePerKbRequired The fee required per kilobyte. Note that this is the same as the reference client's -minrelaytxfee * 3
* If you want a safe default, use {@link Transaction#REFERENCE_DEFAULT_MIN_TX_FEE}*3 * If you want a safe default, use {@link Transaction#REFERENCE_DEFAULT_MIN_TX_FEE}*3
*/ */
public BigInteger getMinNonDustValue(BigInteger feePerKbRequired) { public Coin getMinNonDustValue(Coin feePerKbRequired) {
// A typical output is 33 bytes (pubkey hash + opcodes) and requires an input of 148 bytes to spend so we add // A typical output is 33 bytes (pubkey hash + opcodes) and requires an input of 148 bytes to spend so we add
// that together to find out the total amount of data used to transfer this amount of value. Note that this // that together to find out the total amount of data used to transfer this amount of value. Note that this
// formula is wrong for anything that's not a pay-to-address output, unfortunately, we must follow the reference // formula is wrong for anything that's not a pay-to-address output, unfortunately, we must follow the reference
// clients wrongness in order to ensure we're considered standard. A better formula would either estimate the // clients wrongness in order to ensure we're considered standard. A better formula would either estimate the
// size of data needed to satisfy all different script types, or just hard code 33 below. // size of data needed to satisfy all different script types, or just hard code 33 below.
final BigInteger size = BigInteger.valueOf(this.bitcoinSerialize().length + 148); final long size = this.bitcoinSerialize().length + 148;
BigInteger[] nonDustAndRemainder = feePerKbRequired.multiply(size).divideAndRemainder(BigInteger.valueOf(1000)); Coin[] nonDustAndRemainder = feePerKbRequired.multiply(size).divideAndRemainder(Coin.valueOf(1000));
return nonDustAndRemainder[1].equals(BigInteger.ZERO) ? nonDustAndRemainder[0] : nonDustAndRemainder[0].add(BigInteger.ONE); return nonDustAndRemainder[1].equals(Coin.ZERO) ? nonDustAndRemainder[0] : nonDustAndRemainder[0].add(Coin.ONE);
} }
/** /**
@ -213,8 +214,8 @@ public class TransactionOutput extends ChildMessage implements Serializable {
* and mined by default miners. For normal pay to address outputs, this is 5460 satoshis, the same as * and mined by default miners. For normal pay to address outputs, this is 5460 satoshis, the same as
* {@link Transaction#MIN_NONDUST_OUTPUT}. * {@link Transaction#MIN_NONDUST_OUTPUT}.
*/ */
public BigInteger getMinNonDustValue() { public Coin getMinNonDustValue() {
return getMinNonDustValue(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(BigInteger.valueOf(3))); return getMinNonDustValue(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(Coin.valueOf(3)));
} }
/** /**

View File

@ -45,7 +45,7 @@ import static com.google.common.util.concurrent.Uninterruptibles.sleepUninterrup
* To enable debug logging from the library, run with -Dbitcoinj.logging=true on your command line. * To enable debug logging from the library, run with -Dbitcoinj.logging=true on your command line.
*/ */
public class Utils { public class Utils {
public static final BigInteger NEGATIVE_ONE = BigInteger.valueOf(-1); public static final Coin NEGATIVE_ONE = Coin.valueOf(-1);
private static final MessageDigest digest; private static final MessageDigest digest;
static { static {
try { try {
@ -68,7 +68,7 @@ public class Utils {
* The term nanocoin is very misleading, though, because there are only 100 million * The term nanocoin is very misleading, though, because there are only 100 million
* of them in a coin (whereas one would expect 1 billion. * of them in a coin (whereas one would expect 1 billion.
*/ */
public static final BigInteger COIN = new BigInteger("100000000", 10); public static final Coin COIN = new Coin("100000000", 10);
/** /**
* How many "nanocoins" there are in 0.01 BitCoins. * How many "nanocoins" there are in 0.01 BitCoins.
@ -77,19 +77,19 @@ public class Utils {
* The term nanocoin is very misleading, though, because there are only 100 million * The term nanocoin is very misleading, though, because there are only 100 million
* of them in a coin (whereas one would expect 1 billion). * of them in a coin (whereas one would expect 1 billion).
*/ */
public static final BigInteger CENT = new BigInteger("1000000", 10); public static final Coin CENT = new Coin("1000000", 10);
private static BlockingQueue<Boolean> mockSleepQueue; private static BlockingQueue<Boolean> mockSleepQueue;
/** /**
* Convert an amount expressed in the way humans are used to into nanocoins. * Convert an amount expressed in the way humans are used to into nanocoins.
*/ */
public static BigInteger toNanoCoins(int coins, int cents) { public static Coin toNanoCoins(int coins, int cents) {
checkArgument(cents < 100); checkArgument(cents < 100);
checkArgument(cents >= 0); checkArgument(cents >= 0);
checkArgument(coins >= 0); checkArgument(coins >= 0);
checkArgument(coins < NetworkParameters.MAX_MONEY.divide(Utils.COIN).longValue()); checkArgument(coins < NetworkParameters.MAX_MONEY.divide(Utils.COIN).longValue());
BigInteger bi = BigInteger.valueOf(coins).multiply(COIN); Coin bi = Coin.valueOf(coins).multiply(COIN);
bi = bi.add(BigInteger.valueOf(cents).multiply(CENT)); bi = bi.add(Coin.valueOf(cents).multiply(CENT));
return bi; return bi;
} }
@ -121,12 +121,12 @@ public class Utils {
* *
* @throws ArithmeticException if you try to specify fractional nanocoins, or nanocoins out of range. * @throws ArithmeticException if you try to specify fractional nanocoins, or nanocoins out of range.
*/ */
public static BigInteger toNanoCoins(String coins) { public static Coin toNanoCoins(String coins) {
BigInteger bigint = new BigDecimal(coins).movePointRight(8).toBigIntegerExact(); Coin bigint = new Coin(new BigDecimal(coins).movePointRight(8).toBigIntegerExact());
if (bigint.signum() < 0) if (bigint.signum() < 0)
throw new ArithmeticException("Negative coins specified"); throw new ArithmeticException("Negative coins specified");
if (bigint.compareTo(NetworkParameters.MAX_MONEY) > 0) if (bigint.compareTo(NetworkParameters.MAX_MONEY) > 0)
throw new ArithmeticException("Amount larger than the total quantity of Bitcoins possible specified."); throw new ArithmeticException("Coin larger than the total quantity of Bitcoins possible specified.");
return bigint; return bigint;
} }
@ -332,12 +332,12 @@ public class Utils {
* Returns the given value in nanocoins as a 0.12 type string. More digits after the decimal place will be used * Returns the given value in nanocoins as a 0.12 type string. More digits after the decimal place will be used
* if necessary, but two will always be present. * if necessary, but two will always be present.
*/ */
public static String bitcoinValueToFriendlyString(BigInteger value) { public static String bitcoinValueToFriendlyString(Coin value) {
// TODO: This API is crap. This method should go away when we encapsulate money values. // TODO: This API is crap. This method should go away when we encapsulate money values.
boolean negative = value.signum() < 0; boolean negative = value.signum() < 0;
if (negative) if (negative)
value = value.negate(); value = value.negate();
BigDecimal bd = new BigDecimal(value, 8); BigDecimal bd = new BigDecimal(value.toBigInteger(), 8);
String formatted = bd.toPlainString(); // Don't use scientific notation. String formatted = bd.toPlainString(); // Don't use scientific notation.
int decimalPoint = formatted.indexOf("."); int decimalPoint = formatted.indexOf(".");
// Drop unnecessary zeros from the end. // Drop unnecessary zeros from the end.
@ -355,19 +355,19 @@ public class Utils {
* <p> * <p>
* Returns the given value as a plain string denominated in BTC. * Returns the given value as a plain string denominated in BTC.
* The result is unformatted with no trailing zeroes. * The result is unformatted with no trailing zeroes.
* For instance, an input value of BigInteger.valueOf(150000) nanocoin gives an output string of "0.0015" BTC * For instance, an input value of Coin.valueOf(150000) nanocoin gives an output string of "0.0015" BTC
* </p> * </p>
* *
* @param value The value in nanocoins to convert to a string (denominated in BTC) * @param value The value in nanocoins to convert to a string (denominated in BTC)
* @throws IllegalArgumentException * @throws IllegalArgumentException
* If the input value is null * If the input value is null
*/ */
public static String bitcoinValueToPlainString(BigInteger value) { public static String bitcoinValueToPlainString(Coin value) {
if (value == null) { if (value == null) {
throw new IllegalArgumentException("Value cannot be null"); throw new IllegalArgumentException("Value cannot be null");
} }
BigDecimal valueInBTC = new BigDecimal(value).divide(new BigDecimal(Utils.COIN)); BigDecimal valueInBTC = new BigDecimal(value.toBigInteger()).divide(new BigDecimal(Utils.COIN.toBigInteger()));
return valueInBTC.toPlainString(); return valueInBTC.toPlainString();
} }

View File

@ -1094,8 +1094,8 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
log.warn("There are now {} risk dropped transactions being kept in memory", riskDropped.size()); log.warn("There are now {} risk dropped transactions being kept in memory", riskDropped.size());
return; return;
} }
BigInteger valueSentToMe = tx.getValueSentToMe(this); Coin valueSentToMe = tx.getValueSentToMe(this);
BigInteger valueSentFromMe = tx.getValueSentFromMe(this); Coin valueSentFromMe = tx.getValueSentFromMe(this);
if (log.isInfoEnabled()) { if (log.isInfoEnabled()) {
log.info(String.format("Received a pending transaction %s that spends %s BTC from our own wallet," + log.info(String.format("Received a pending transaction %s that spends %s BTC from our own wallet," +
" and sends us %s BTC", tx.getHashAsString(), Utils.bitcoinValueToFriendlyString(valueSentFromMe), " and sends us %s BTC", tx.getHashAsString(), Utils.bitcoinValueToFriendlyString(valueSentFromMe),
@ -1272,14 +1272,14 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
int relativityOffset) throws VerificationException { int relativityOffset) throws VerificationException {
// Runs in a peer thread. // Runs in a peer thread.
checkState(lock.isHeldByCurrentThread()); checkState(lock.isHeldByCurrentThread());
BigInteger prevBalance = getBalance(); Coin prevBalance = getBalance();
Sha256Hash txHash = tx.getHash(); Sha256Hash txHash = tx.getHash();
boolean bestChain = blockType == BlockChain.NewBlockType.BEST_CHAIN; boolean bestChain = blockType == BlockChain.NewBlockType.BEST_CHAIN;
boolean sideChain = blockType == BlockChain.NewBlockType.SIDE_CHAIN; boolean sideChain = blockType == BlockChain.NewBlockType.SIDE_CHAIN;
BigInteger valueSentFromMe = tx.getValueSentFromMe(this); Coin valueSentFromMe = tx.getValueSentFromMe(this);
BigInteger valueSentToMe = tx.getValueSentToMe(this); Coin valueSentToMe = tx.getValueSentToMe(this);
BigInteger valueDifference = valueSentToMe.subtract(valueSentFromMe); Coin valueDifference = valueSentToMe.subtract(valueSentFromMe);
log.info("Received tx{} for {} BTC: {} [{}] in block {}", sideChain ? " on a side chain" : "", log.info("Received tx{} for {} BTC: {} [{}] in block {}", sideChain ? " on a side chain" : "",
bitcoinValueToFriendlyString(valueDifference), tx.getHashAsString(), relativityOffset, bitcoinValueToFriendlyString(valueDifference), tx.getHashAsString(), relativityOffset,
@ -1364,7 +1364,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
// own spends. If users want to know when a broadcast tx becomes confirmed, they need to use tx confidence // own spends. If users want to know when a broadcast tx becomes confirmed, they need to use tx confidence
// listeners. // listeners.
if (!insideReorg && bestChain) { if (!insideReorg && bestChain) {
BigInteger newBalance = getBalance(); // This is slow. Coin newBalance = getBalance(); // This is slow.
log.info("Balance is now: " + bitcoinValueToFriendlyString(newBalance)); log.info("Balance is now: " + bitcoinValueToFriendlyString(newBalance));
if (!wasPending) { if (!wasPending) {
int diff = valueDifference.signum(); int diff = valueDifference.signum();
@ -1694,7 +1694,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
if (pending.containsKey(tx.getHash())) if (pending.containsKey(tx.getHash()))
return false; return false;
log.info("commitTx of {}", tx.getHashAsString()); log.info("commitTx of {}", tx.getHashAsString());
BigInteger balance = getBalance(); Coin balance = getBalance();
tx.setUpdateTime(Utils.now()); tx.setUpdateTime(Utils.now());
// Mark the outputs we're spending as spent so we won't try and use them in future creations. This will also // Mark the outputs we're spending as spent so we won't try and use them in future creations. This will also
// move any transactions that are now fully spent to the spent map so we can skip them when creating future // move any transactions that are now fully spent to the spent map so we can skip them when creating future
@ -1708,9 +1708,9 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
addWalletTransaction(Pool.PENDING, tx); addWalletTransaction(Pool.PENDING, tx);
try { try {
BigInteger valueSentFromMe = tx.getValueSentFromMe(this); Coin valueSentFromMe = tx.getValueSentFromMe(this);
BigInteger valueSentToMe = tx.getValueSentToMe(this); Coin valueSentToMe = tx.getValueSentToMe(this);
BigInteger newBalance = balance.add(valueSentToMe).subtract(valueSentFromMe); Coin newBalance = balance.add(valueSentToMe).subtract(valueSentFromMe);
if (valueSentToMe.signum() > 0) { if (valueSentToMe.signum() > 0) {
checkBalanceFuturesLocked(null); checkBalanceFuturesLocked(null);
queueOnCoinsReceived(tx, balance, newBalance); queueOnCoinsReceived(tx, balance, newBalance);
@ -2015,7 +2015,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
* fees) - the wallet will calculate all that for you and update tx later.</p> * fees) - the wallet will calculate all that for you and update tx later.</p>
* *
* <p>Be careful when adding outputs that you check the min output value * <p>Be careful when adding outputs that you check the min output value
* ({@link TransactionOutput#getMinNonDustValue(BigInteger)}) to avoid the whole transaction being rejected * ({@link TransactionOutput#getMinNonDustValue(Coin)}) to avoid the whole transaction being rejected
* because one output is dust.</p> * because one output is dust.</p>
* *
* <p>If there are already inputs to the transaction, make sure their out point has a connected output, * <p>If there are already inputs to the transaction, make sure their out point has a connected output,
@ -2056,7 +2056,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
* <p>You might also consider adding a {@link SendRequest#feePerKb} to set the fee per kb of transaction size * <p>You might also consider adding a {@link SendRequest#feePerKb} to set the fee per kb of transaction size
* (rounded down to the nearest kb) as that is how transactions are sorted when added to a block by miners.</p> * (rounded down to the nearest kb) as that is how transactions are sorted when added to a block by miners.</p>
*/ */
public BigInteger fee = null; public Coin fee = null;
/** /**
* <p>A transaction can have a fee attached, which is defined as the difference between the input values * <p>A transaction can have a fee attached, which is defined as the difference between the input values
@ -2072,13 +2072,13 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
* *
* <p>You might also consider using a {@link SendRequest#fee} to set the fee added for the first kb of size.</p> * <p>You might also consider using a {@link SendRequest#fee} to set the fee added for the first kb of size.</p>
*/ */
public BigInteger feePerKb = DEFAULT_FEE_PER_KB; public Coin feePerKb = DEFAULT_FEE_PER_KB;
/** /**
* If you want to modify the default fee for your entire app without having to change each SendRequest you make, * If you want to modify the default fee for your entire app without having to change each SendRequest you make,
* you can do it here. This is primarily useful for unit tests. * you can do it here. This is primarily useful for unit tests.
*/ */
public static BigInteger DEFAULT_FEE_PER_KB = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE; public static Coin DEFAULT_FEE_PER_KB = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
/** /**
* <p>Requires that there be enough fee for a default reference client to at least relay the transaction. * <p>Requires that there be enough fee for a default reference client to at least relay the transaction.
@ -2123,7 +2123,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
* <p>Be very careful when value is smaller than {@link Transaction#MIN_NONDUST_OUTPUT} as the transaction will * <p>Be very careful when value is smaller than {@link Transaction#MIN_NONDUST_OUTPUT} as the transaction will
* likely be rejected by the network in this case.</p> * likely be rejected by the network in this case.</p>
*/ */
public static SendRequest to(Address destination, BigInteger value) { public static SendRequest to(Address destination, Coin value) {
SendRequest req = new SendRequest(); SendRequest req = new SendRequest();
final NetworkParameters parameters = destination.getParameters(); final NetworkParameters parameters = destination.getParameters();
checkNotNull(parameters, "Address is for an unknown network"); checkNotNull(parameters, "Address is for an unknown network");
@ -2136,11 +2136,11 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
* <p>Creates a new SendRequest to the given pubkey for the given value.</p> * <p>Creates a new SendRequest to the given pubkey for the given value.</p>
* *
* <p>Be careful to check the output's value is reasonable using * <p>Be careful to check the output's value is reasonable using
* {@link TransactionOutput#getMinNonDustValue(BigInteger)} afterwards or you risk having the transaction * {@link TransactionOutput#getMinNonDustValue(Coin)} afterwards or you risk having the transaction
* rejected by the network. Note that using {@link SendRequest#to(Address, java.math.BigInteger)} will result * rejected by the network. Note that using {@link SendRequest#to(Address, java.math.Coin)} will result
* in a smaller output, and thus the ability to use a smaller output value without rejection.</p> * in a smaller output, and thus the ability to use a smaller output value without rejection.</p>
*/ */
public static SendRequest to(NetworkParameters params, ECKey destination, BigInteger value) { public static SendRequest to(NetworkParameters params, ECKey destination, Coin value) {
SendRequest req = new SendRequest(); SendRequest req = new SendRequest();
req.tx = new Transaction(params); req.tx = new Transaction(params);
req.tx.addOutput(value, destination); req.tx.addOutput(value, destination);
@ -2159,7 +2159,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
final NetworkParameters parameters = destination.getParameters(); final NetworkParameters parameters = destination.getParameters();
checkNotNull(parameters, "Address is for an unknown network"); checkNotNull(parameters, "Address is for an unknown network");
req.tx = new Transaction(parameters); req.tx = new Transaction(parameters);
req.tx.addOutput(BigInteger.ZERO, destination); req.tx.addOutput(Coin.ZERO, destination);
req.emptyWallet = true; req.emptyWallet = true;
return req; return req;
} }
@ -2170,11 +2170,11 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
* {@link Wallet#getChangeAddress()}, so you must have added at least one key.</p> * {@link Wallet#getChangeAddress()}, so you must have added at least one key.</p>
* *
* <p>If you just want to send money quickly, you probably want * <p>If you just want to send money quickly, you probably want
* {@link Wallet#sendCoins(TransactionBroadcaster, Address, java.math.BigInteger)} instead. That will create the sending * {@link Wallet#sendCoins(TransactionBroadcaster, Address, java.math.Coin)} instead. That will create the sending
* transaction, commit to the wallet and broadcast it to the network all in one go. This method is lower level * transaction, commit to the wallet and broadcast it to the network all in one go. This method is lower level
* and lets you see the proposed transaction before anything is done with it.</p> * and lets you see the proposed transaction before anything is done with it.</p>
* *
* <p>This is a helper method that is equivalent to using {@link Wallet.SendRequest#to(Address, java.math.BigInteger)} * <p>This is a helper method that is equivalent to using {@link Wallet.SendRequest#to(Address, java.math.Coin)}
* followed by {@link Wallet#completeTx(Wallet.SendRequest)} and returning the requests transaction object. * followed by {@link Wallet#completeTx(Wallet.SendRequest)} and returning the requests transaction object.
* Note that this means a fee may be automatically added if required, if you want more control over the process, * Note that this means a fee may be automatically added if required, if you want more control over the process,
* just do those two steps yourself.</p> * just do those two steps yourself.</p>
@ -2193,7 +2193,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
* coins as spent until commitTx is called on the result. * coins as spent until commitTx is called on the result.
* @throws InsufficientMoneyException if the request could not be completed due to not enough balance. * @throws InsufficientMoneyException if the request could not be completed due to not enough balance.
*/ */
public Transaction createSend(Address address, BigInteger nanocoins) throws InsufficientMoneyException { public Transaction createSend(Address address, Coin nanocoins) throws InsufficientMoneyException {
SendRequest req = SendRequest.to(address, nanocoins); SendRequest req = SendRequest.to(address, nanocoins);
if (params == UnitTestParams.get()) if (params == UnitTestParams.get())
req.shuffleOutputs = false; req.shuffleOutputs = false;
@ -2243,7 +2243,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
* @return An object containing the transaction that was created, and a future for the broadcast of it. * @return An object containing the transaction that was created, and a future for the broadcast of it.
* @throws InsufficientMoneyException if the request could not be completed due to not enough balance. * @throws InsufficientMoneyException if the request could not be completed due to not enough balance.
*/ */
public SendResult sendCoins(TransactionBroadcaster broadcaster, Address to, BigInteger value) throws InsufficientMoneyException { public SendResult sendCoins(TransactionBroadcaster broadcaster, Address to, Coin value) throws InsufficientMoneyException {
SendRequest request = SendRequest.to(to, value); SendRequest request = SendRequest.to(to, value);
return sendCoins(broadcaster, request); return sendCoins(broadcaster, request);
} }
@ -2335,17 +2335,17 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
try { try {
checkArgument(!req.completed, "Given SendRequest has already been completed."); checkArgument(!req.completed, "Given SendRequest has already been completed.");
// Calculate the amount of value we need to import. // Calculate the amount of value we need to import.
BigInteger value = BigInteger.ZERO; Coin value = Coin.ZERO;
for (TransactionOutput output : req.tx.getOutputs()) { for (TransactionOutput output : req.tx.getOutputs()) {
value = value.add(output.getValue()); value = value.add(output.getValue());
} }
BigInteger totalOutput = value; Coin totalOutput = value;
log.info("Completing send tx with {} outputs totalling {} satoshis (not including fees)", log.info("Completing send tx with {} outputs totalling {} satoshis (not including fees)",
req.tx.getOutputs().size(), value); req.tx.getOutputs().size(), value);
// If any inputs have already been added, we don't need to get their value from wallet // If any inputs have already been added, we don't need to get their value from wallet
BigInteger totalInput = BigInteger.ZERO; Coin totalInput = Coin.ZERO;
for (TransactionInput input : req.tx.getInputs()) for (TransactionInput input : req.tx.getInputs())
if (input.getConnectedOutput() != null) if (input.getConnectedOutput() != null)
totalInput = totalInput.add(input.getConnectedOutput().getValue()); totalInput = totalInput.add(input.getConnectedOutput().getValue());
@ -2397,8 +2397,8 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
req.tx.addInput(output); req.tx.addInput(output);
if (req.ensureMinRequiredFee && req.emptyWallet) { if (req.ensureMinRequiredFee && req.emptyWallet) {
final BigInteger baseFee = req.fee == null ? BigInteger.ZERO : req.fee; final Coin baseFee = req.fee == null ? Coin.ZERO : req.fee;
final BigInteger feePerKb = req.feePerKb == null ? BigInteger.ZERO : req.feePerKb; final Coin feePerKb = req.feePerKb == null ? Coin.ZERO : req.feePerKb;
Transaction tx = req.tx; Transaction tx = req.tx;
if (!adjustOutputDownwardsForFee(tx, bestCoinSelection, baseFee, feePerKb)) if (!adjustOutputDownwardsForFee(tx, bestCoinSelection, baseFee, feePerKb))
throw new CouldNotAdjustDownwards(); throw new CouldNotAdjustDownwards();
@ -2411,7 +2411,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
totalOutput = totalOutput.add(bestChangeOutput.getValue()); totalOutput = totalOutput.add(bestChangeOutput.getValue());
log.info(" with {} coins change", bitcoinValueToFriendlyString(bestChangeOutput.getValue())); log.info(" with {} coins change", bitcoinValueToFriendlyString(bestChangeOutput.getValue()));
} }
final BigInteger calculatedFee = totalInput.subtract(totalOutput); final Coin calculatedFee = totalInput.subtract(totalOutput);
if (calculatedFee.signum() > 0) { if (calculatedFee.signum() > 0) {
log.info(" with a fee of {}", bitcoinValueToFriendlyString(calculatedFee)); log.info(" with a fee of {}", bitcoinValueToFriendlyString(calculatedFee));
} }
@ -2445,12 +2445,12 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
} }
/** Reduce the value of the first output of a transaction to pay the given feePerKb as appropriate for its size. */ /** Reduce the value of the first output of a transaction to pay the given feePerKb as appropriate for its size. */
private boolean adjustOutputDownwardsForFee(Transaction tx, CoinSelection coinSelection, BigInteger baseFee, BigInteger feePerKb) { private boolean adjustOutputDownwardsForFee(Transaction tx, CoinSelection coinSelection, Coin baseFee, Coin feePerKb) {
TransactionOutput output = tx.getOutput(0); TransactionOutput output = tx.getOutput(0);
// Check if we need additional fee due to the transaction's size // Check if we need additional fee due to the transaction's size
int size = tx.bitcoinSerialize().length; int size = tx.bitcoinSerialize().length;
size += estimateBytesForSigning(coinSelection); size += estimateBytesForSigning(coinSelection);
BigInteger fee = baseFee.add(BigInteger.valueOf((size / 1000) + 1).multiply(feePerKb)); Coin fee = baseFee.add(Coin.valueOf((size / 1000) + 1).multiply(feePerKb));
output.setValue(output.getValue().subtract(fee)); output.setValue(output.getValue().subtract(fee));
// Check if we need additional fee due to the output's value // Check if we need additional fee due to the output's value
if (output.getValue().compareTo(Utils.CENT) < 0 && fee.compareTo(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE) < 0) if (output.getValue().compareTo(Utils.CENT) < 0 && fee.compareTo(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE) < 0)
@ -2538,21 +2538,21 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
* Returns the AVAILABLE balance of this wallet. See {@link BalanceType#AVAILABLE} for details on what this * Returns the AVAILABLE balance of this wallet. See {@link BalanceType#AVAILABLE} for details on what this
* means. * means.
*/ */
public BigInteger getBalance() { public Coin getBalance() {
return getBalance(BalanceType.AVAILABLE); return getBalance(BalanceType.AVAILABLE);
} }
/** /**
* Returns the balance of this wallet as calculated by the provided balanceType. * Returns the balance of this wallet as calculated by the provided balanceType.
*/ */
public BigInteger getBalance(BalanceType balanceType) { public Coin getBalance(BalanceType balanceType) {
lock.lock(); lock.lock();
try { try {
if (balanceType == BalanceType.AVAILABLE) { if (balanceType == BalanceType.AVAILABLE) {
return getBalance(coinSelector); return getBalance(coinSelector);
} else if (balanceType == BalanceType.ESTIMATED) { } else if (balanceType == BalanceType.ESTIMATED) {
LinkedList<TransactionOutput> all = calculateAllSpendCandidates(false); LinkedList<TransactionOutput> all = calculateAllSpendCandidates(false);
BigInteger value = BigInteger.ZERO; Coin value = Coin.ZERO;
for (TransactionOutput out : all) value = value.add(out.getValue()); for (TransactionOutput out : all) value = value.add(out.getValue());
return value; return value;
} else { } else {
@ -2567,7 +2567,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
* Returns the balance that would be considered spendable by the given coin selector. Just asks it to select * Returns the balance that would be considered spendable by the given coin selector. Just asks it to select
* as many coins as possible and returns the total. * as many coins as possible and returns the total.
*/ */
public BigInteger getBalance(CoinSelector selector) { public Coin getBalance(CoinSelector selector) {
lock.lock(); lock.lock();
try { try {
checkNotNull(selector); checkNotNull(selector);
@ -2580,7 +2580,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
} }
/** Returns the available balance, including any unspent balance at watched addresses */ /** Returns the available balance, including any unspent balance at watched addresses */
public BigInteger getWatchedBalance() { public Coin getWatchedBalance() {
return getWatchedBalance(coinSelector); return getWatchedBalance(coinSelector);
} }
@ -2588,7 +2588,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
* Returns the balance that would be considered spendable by the given coin selector, including * Returns the balance that would be considered spendable by the given coin selector, including
* any unspent balance at watched addresses. * any unspent balance at watched addresses.
*/ */
public BigInteger getWatchedBalance(CoinSelector selector) { public Coin getWatchedBalance(CoinSelector selector) {
lock.lock(); lock.lock();
try { try {
checkNotNull(selector); checkNotNull(selector);
@ -2619,8 +2619,8 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
lock.lock(); lock.lock();
try { try {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
BigInteger estimatedBalance = getBalance(BalanceType.ESTIMATED); Coin estimatedBalance = getBalance(BalanceType.ESTIMATED);
BigInteger availableBalance = getBalance(BalanceType.AVAILABLE); Coin availableBalance = getBalance(BalanceType.AVAILABLE);
builder.append(String.format("Wallet containing %s BTC (available: %s BTC) in:%n", builder.append(String.format("Wallet containing %s BTC (available: %s BTC) in:%n",
bitcoinValueToPlainString(estimatedBalance), bitcoinValueToPlainString(availableBalance))); bitcoinValueToPlainString(estimatedBalance), bitcoinValueToPlainString(availableBalance)));
builder.append(String.format(" %d pending transactions%n", pending.size())); builder.append(String.format(" %d pending transactions%n", pending.size()));
@ -2861,7 +2861,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
notifyNewBestBlock(block); notifyNewBestBlock(block);
} }
checkState(isConsistent()); checkState(isConsistent());
final BigInteger balance = getBalance(); final Coin balance = getBalance();
log.info("post-reorg balance is {}", Utils.bitcoinValueToFriendlyString(balance)); log.info("post-reorg balance is {}", Utils.bitcoinValueToFriendlyString(balance));
// Inform event listeners that a re-org took place. // Inform event listeners that a re-org took place.
queueOnReorganize(); queueOnReorganize();
@ -3307,8 +3307,8 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
} }
private static class BalanceFutureRequest { private static class BalanceFutureRequest {
public SettableFuture<BigInteger> future; public SettableFuture<Coin> future;
public BigInteger value; public Coin value;
public BalanceType type; public BalanceType type;
} }
@GuardedBy("lock") private List<BalanceFutureRequest> balanceFutureRequests = Lists.newLinkedList(); @GuardedBy("lock") private List<BalanceFutureRequest> balanceFutureRequests = Lists.newLinkedList();
@ -3327,11 +3327,11 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
* you can use {@link com.google.bitcoin.utils.Threading#waitForUserCode()} to block until the future had a * you can use {@link com.google.bitcoin.utils.Threading#waitForUserCode()} to block until the future had a
* chance to be updated.</p> * chance to be updated.</p>
*/ */
public ListenableFuture<BigInteger> getBalanceFuture(final BigInteger value, final BalanceType type) { public ListenableFuture<Coin> getBalanceFuture(final Coin value, final BalanceType type) {
lock.lock(); lock.lock();
try { try {
final SettableFuture<BigInteger> future = SettableFuture.create(); final SettableFuture<Coin> future = SettableFuture.create();
final BigInteger current = getBalance(type); final Coin current = getBalance(type);
if (current.compareTo(value) >= 0) { if (current.compareTo(value) >= 0) {
// Already have enough. // Already have enough.
future.set(current); future.set(current);
@ -3352,13 +3352,13 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
} }
// Runs any balance futures in the user code thread. // Runs any balance futures in the user code thread.
private void checkBalanceFuturesLocked(@Nullable BigInteger avail) { private void checkBalanceFuturesLocked(@Nullable Coin avail) {
checkState(lock.isHeldByCurrentThread()); checkState(lock.isHeldByCurrentThread());
BigInteger estimated = null; Coin estimated = null;
final ListIterator<BalanceFutureRequest> it = balanceFutureRequests.listIterator(); final ListIterator<BalanceFutureRequest> it = balanceFutureRequests.listIterator();
while (it.hasNext()) { while (it.hasNext()) {
final BalanceFutureRequest req = it.next(); final BalanceFutureRequest req = it.next();
BigInteger val = null; Coin val = null;
if (req.type == BalanceType.AVAILABLE) { if (req.type == BalanceType.AVAILABLE) {
if (avail == null) avail = getBalance(BalanceType.AVAILABLE); if (avail == null) avail = getBalance(BalanceType.AVAILABLE);
if (avail.compareTo(req.value) < 0) continue; if (avail.compareTo(req.value) < 0) continue;
@ -3370,7 +3370,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
} }
// Found one that's finished. // Found one that's finished.
it.remove(); it.remove();
final BigInteger v = checkNotNull(val); final Coin v = checkNotNull(val);
// Don't run any user-provided future listeners with our lock held. // Don't run any user-provided future listeners with our lock held.
Threading.USER_THREAD.execute(new Runnable() { Threading.USER_THREAD.execute(new Runnable() {
@Override public void run() { @Override public void run() {
@ -3483,7 +3483,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
} }
} }
private void queueOnCoinsReceived(final Transaction tx, final BigInteger balance, final BigInteger newBalance) { private void queueOnCoinsReceived(final Transaction tx, final Coin balance, final Coin newBalance) {
checkState(lock.isHeldByCurrentThread()); checkState(lock.isHeldByCurrentThread());
for (final ListenerRegistration<WalletEventListener> registration : eventListeners) { for (final ListenerRegistration<WalletEventListener> registration : eventListeners) {
registration.executor.execute(new Runnable() { registration.executor.execute(new Runnable() {
@ -3495,7 +3495,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
} }
} }
private void queueOnCoinsSent(final Transaction tx, final BigInteger prevBalance, final BigInteger newBalance) { private void queueOnCoinsSent(final Transaction tx, final Coin prevBalance, final Coin newBalance) {
checkState(lock.isHeldByCurrentThread()); checkState(lock.isHeldByCurrentThread());
for (final ListenerRegistration<WalletEventListener> registration : eventListeners) { for (final ListenerRegistration<WalletEventListener> registration : eventListeners) {
registration.executor.execute(new Runnable() { registration.executor.execute(new Runnable() {
@ -3540,7 +3540,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
private CoinSelection bestCoinSelection; private CoinSelection bestCoinSelection;
private TransactionOutput bestChangeOutput; private TransactionOutput bestChangeOutput;
public FeeCalculation(SendRequest req, BigInteger value, List<TransactionInput> originalInputs, public FeeCalculation(SendRequest req, Coin value, List<TransactionInput> originalInputs,
boolean needAtLeastReferenceFee, LinkedList<TransactionOutput> candidates) throws InsufficientMoneyException { boolean needAtLeastReferenceFee, LinkedList<TransactionOutput> candidates) throws InsufficientMoneyException {
checkState(lock.isHeldByCurrentThread()); checkState(lock.isHeldByCurrentThread());
// There are 3 possibilities for what adding change might do: // There are 3 possibilities for what adding change might do:
@ -3550,7 +3550,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
// If we get either of the last 2, we keep note of what the inputs looked like at the time and try to // If we get either of the last 2, we keep note of what the inputs looked like at the time and try to
// add inputs as we go up the list (keeping track of minimum inputs for each category). At the end, we pick // add inputs as we go up the list (keeping track of minimum inputs for each category). At the end, we pick
// the best input set as the one which generates the lowest total fee. // the best input set as the one which generates the lowest total fee.
BigInteger additionalValueForNextCategory = null; Coin additionalValueForNextCategory = null;
CoinSelection selection3 = null; CoinSelection selection3 = null;
CoinSelection selection2 = null; CoinSelection selection2 = null;
TransactionOutput selection2Change = null; TransactionOutput selection2Change = null;
@ -3559,14 +3559,14 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
// We keep track of the last size of the transaction we calculated but only if the act of adding inputs and // We keep track of the last size of the transaction we calculated but only if the act of adding inputs and
// change resulted in the size crossing a 1000 byte boundary. Otherwise it stays at zero. // change resulted in the size crossing a 1000 byte boundary. Otherwise it stays at zero.
int lastCalculatedSize = 0; int lastCalculatedSize = 0;
BigInteger valueNeeded, valueMissing = null; Coin valueNeeded, valueMissing = null;
while (true) { while (true) {
resetTxInputs(req, originalInputs); resetTxInputs(req, originalInputs);
BigInteger fees = req.fee == null ? BigInteger.ZERO : req.fee; Coin fees = req.fee == null ? Coin.ZERO : req.fee;
if (lastCalculatedSize > 0) { if (lastCalculatedSize > 0) {
// If the size is exactly 1000 bytes then we'll over-pay, but this should be rare. // If the size is exactly 1000 bytes then we'll over-pay, but this should be rare.
fees = fees.add(BigInteger.valueOf((lastCalculatedSize / 1000) + 1).multiply(req.feePerKb)); fees = fees.add(Coin.valueOf((lastCalculatedSize / 1000) + 1).multiply(req.feePerKb));
} else { } else {
fees = fees.add(req.feePerKb); // First time around the loop. fees = fees.add(req.feePerKb); // First time around the loop.
} }
@ -3576,7 +3576,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
valueNeeded = value.add(fees); valueNeeded = value.add(fees);
if (additionalValueForNextCategory != null) if (additionalValueForNextCategory != null)
valueNeeded = valueNeeded.add(additionalValueForNextCategory); valueNeeded = valueNeeded.add(additionalValueForNextCategory);
BigInteger additionalValueSelected = additionalValueForNextCategory; Coin additionalValueSelected = additionalValueForNextCategory;
// Of the coins we could spend, pick some that we actually will spend. // Of the coins we could spend, pick some that we actually will spend.
CoinSelector selector = req.coinSelector == null ? coinSelector : req.coinSelector; CoinSelector selector = req.coinSelector == null ? coinSelector : req.coinSelector;
@ -3598,12 +3598,12 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
boolean eitherCategory2Or3 = false; boolean eitherCategory2Or3 = false;
boolean isCategory3 = false; boolean isCategory3 = false;
BigInteger change = selection.valueGathered.subtract(valueNeeded); Coin change = selection.valueGathered.subtract(valueNeeded);
if (additionalValueSelected != null) if (additionalValueSelected != null)
change = change.add(additionalValueSelected); change = change.add(additionalValueSelected);
// If change is < 0.01 BTC, we will need to have at least minfee to be accepted by the network // If change is < 0.01 BTC, we will need to have at least minfee to be accepted by the network
if (req.ensureMinRequiredFee && !change.equals(BigInteger.ZERO) && if (req.ensureMinRequiredFee && !change.equals(Coin.ZERO) &&
change.compareTo(Utils.CENT) < 0 && fees.compareTo(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE) < 0) { change.compareTo(Utils.CENT) < 0 && fees.compareTo(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE) < 0) {
// This solution may fit into category 2, but it may also be category 3, we'll check that later // This solution may fit into category 2, but it may also be category 3, we'll check that later
eitherCategory2Or3 = true; eitherCategory2Or3 = true;
@ -3627,7 +3627,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
// This solution definitely fits in category 3 // This solution definitely fits in category 3
isCategory3 = true; isCategory3 = true;
additionalValueForNextCategory = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add( additionalValueForNextCategory = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(
Transaction.MIN_NONDUST_OUTPUT.add(BigInteger.ONE)); Transaction.MIN_NONDUST_OUTPUT.add(Coin.ONE));
} else { } else {
size += changeOutput.bitcoinSerialize().length + VarInt.sizeOf(req.tx.getOutputs().size()) - VarInt.sizeOf(req.tx.getOutputs().size() - 1); size += changeOutput.bitcoinSerialize().length + VarInt.sizeOf(req.tx.getOutputs().size()) - VarInt.sizeOf(req.tx.getOutputs().size() - 1);
// This solution is either category 1 or 2 // This solution is either category 1 or 2
@ -3638,7 +3638,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
if (eitherCategory2Or3) { if (eitherCategory2Or3) {
// This solution definitely fits in category 3 (we threw away change because it was smaller than MIN_TX_FEE) // This solution definitely fits in category 3 (we threw away change because it was smaller than MIN_TX_FEE)
isCategory3 = true; isCategory3 = true;
additionalValueForNextCategory = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(BigInteger.ONE); additionalValueForNextCategory = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Coin.ONE);
} }
} }
@ -3694,7 +3694,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
throw new InsufficientMoneyException(valueMissing); throw new InsufficientMoneyException(valueMissing);
} }
BigInteger lowestFee = null; Coin lowestFee = null;
bestCoinSelection = null; bestCoinSelection = null;
bestChangeOutput = null; bestChangeOutput = null;
if (selection1 != null) { if (selection1 != null) {
@ -3707,7 +3707,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
} }
if (selection2 != null) { if (selection2 != null) {
BigInteger fee = selection2.valueGathered.subtract(checkNotNull(selection2Change).getValue()); Coin fee = selection2.valueGathered.subtract(checkNotNull(selection2Change).getValue());
if (lowestFee == null || fee.compareTo(lowestFee) < 0) { if (lowestFee == null || fee.compareTo(lowestFee) < 0) {
lowestFee = fee; lowestFee = fee;
bestCoinSelection = selection2; bestCoinSelection = selection2;
@ -3896,14 +3896,14 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
// bug that was fixed in 0.10, thus, making a re-key transaction depend on those would cause it to // bug that was fixed in 0.10, thus, making a re-key transaction depend on those would cause it to
// never confirm at all. // never confirm at all.
CoinSelector selector = new KeyTimeCoinSelector(this, keyRotationTimestamp, true); CoinSelector selector = new KeyTimeCoinSelector(this, keyRotationTimestamp, true);
CoinSelection toMove = selector.select(BigInteger.ZERO, calculateAllSpendCandidates(true)); CoinSelection toMove = selector.select(Coin.ZERO, calculateAllSpendCandidates(true));
if (toMove.valueGathered.equals(BigInteger.ZERO)) return null; // Nothing to do. if (toMove.valueGathered.equals(Coin.ZERO)) return null; // Nothing to do.
rekeyTx = new Transaction(params); rekeyTx = new Transaction(params);
for (TransactionOutput output : toMove.gathered) { for (TransactionOutput output : toMove.gathered) {
rekeyTx.addInput(output); rekeyTx.addInput(output);
} }
rekeyTx.addOutput(toMove.valueGathered, safeKey); rekeyTx.addOutput(toMove.valueGathered, safeKey);
if (!adjustOutputDownwardsForFee(rekeyTx, toMove, BigInteger.ZERO, Transaction.REFERENCE_DEFAULT_MIN_TX_FEE)) { if (!adjustOutputDownwardsForFee(rekeyTx, toMove, Coin.ZERO, Transaction.REFERENCE_DEFAULT_MIN_TX_FEE)) {
log.error("Failed to adjust rekey tx for fees."); log.error("Failed to adjust rekey tx for fees.");
return null; return null;
} }

View File

@ -19,7 +19,6 @@ package com.google.bitcoin.core;
import com.google.bitcoin.script.Script; import com.google.bitcoin.script.Script;
import com.google.bitcoin.wallet.KeyChainEventListener; import com.google.bitcoin.wallet.KeyChainEventListener;
import java.math.BigInteger;
import java.util.List; import java.util.List;
/** /**
@ -40,7 +39,7 @@ public interface WalletEventListener extends KeyChainEventListener {
* @param prevBalance Balance before the coins were received. * @param prevBalance Balance before the coins were received.
* @param newBalance Current balance of the wallet. This is the 'estimated' balance. * @param newBalance Current balance of the wallet. This is the 'estimated' balance.
*/ */
void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance); void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance);
/** /**
* This is called when a transaction is seen that sends coins <b>from</b> this wallet, either * This is called when a transaction is seen that sends coins <b>from</b> this wallet, either
@ -58,7 +57,7 @@ public interface WalletEventListener extends KeyChainEventListener {
* @param prevBalance The wallets balance before this transaction was seen. * @param prevBalance The wallets balance before this transaction was seen.
* @param newBalance The wallets balance after this transaction was seen. This is the 'estimated' balance. * @param newBalance The wallets balance after this transaction was seen. This is the 'estimated' balance.
*/ */
void onCoinsSent(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance); void onCoinsSent(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance);
// TODO: Finish onReorganize to be more useful. // TODO: Finish onReorganize to be more useful.
/** /**

View File

@ -4,8 +4,6 @@ import com.google.bitcoin.core.*;
import com.google.bitcoin.protocols.channels.PaymentChannelCloseException; import com.google.bitcoin.protocols.channels.PaymentChannelCloseException;
import com.google.bitcoin.protocols.channels.ServerConnectionEventHandler; import com.google.bitcoin.protocols.channels.ServerConnectionEventHandler;
import java.math.BigInteger;
/** /**
* An event listener that relays events to a native C++ object. A pointer to that object is stored in * An event listener that relays events to a native C++ object. A pointer to that object is stored in
* this class using JNI on the native side, thus several instances of this can point to different actual * this class using JNI on the native side, thus several instances of this can point to different actual
@ -18,7 +16,7 @@ public class NativePaymentChannelServerConnectionEventHandler extends ServerConn
public native void channelOpen(Sha256Hash channelId); public native void channelOpen(Sha256Hash channelId);
@Override @Override
public native void paymentIncrease(BigInteger by, BigInteger to); public native void paymentIncrease(Coin by, Coin to);
@Override @Override
public native void channelClosed(PaymentChannelCloseException.CloseReason reason); public native void channelClosed(PaymentChannelCloseException.CloseReason reason);

View File

@ -16,13 +16,13 @@
package com.google.bitcoin.jni; package com.google.bitcoin.jni;
import com.google.bitcoin.core.Coin;
import com.google.bitcoin.core.ECKey; import com.google.bitcoin.core.ECKey;
import com.google.bitcoin.core.Transaction; import com.google.bitcoin.core.Transaction;
import com.google.bitcoin.core.Wallet; import com.google.bitcoin.core.Wallet;
import com.google.bitcoin.core.WalletEventListener; import com.google.bitcoin.core.WalletEventListener;
import com.google.bitcoin.script.Script; import com.google.bitcoin.script.Script;
import java.math.BigInteger;
import java.util.List; import java.util.List;
/** /**
@ -34,10 +34,10 @@ public class NativeWalletEventListener implements WalletEventListener {
public long ptr; public long ptr;
@Override @Override
public native void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance); public native void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance);
@Override @Override
public native void onCoinsSent(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance); public native void onCoinsSent(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance);
@Override @Override
public native void onReorganize(Wallet wallet); public native void onReorganize(Wallet wallet);

View File

@ -16,11 +16,11 @@
package com.google.bitcoin.protocols.channels; package com.google.bitcoin.protocols.channels;
import com.google.bitcoin.core.Coin;
import com.google.bitcoin.core.InsufficientMoneyException; import com.google.bitcoin.core.InsufficientMoneyException;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import org.bitcoin.paymentchannel.Protos;
import java.math.BigInteger; import org.bitcoin.paymentchannel.Protos;
/** /**
* A class implementing this interface supports the basic operations of a payment channel. An implementation is provided * A class implementing this interface supports the basic operations of a payment channel. An implementation is provided
@ -80,7 +80,7 @@ public interface IPaymentChannelClient {
* (see {@link PaymentChannelClientConnection#getChannelOpenFuture()} for the second) * (see {@link PaymentChannelClientConnection#getChannelOpenFuture()} for the second)
* @return a future that completes when the server acknowledges receipt and acceptance of the payment. * @return a future that completes when the server acknowledges receipt and acceptance of the payment.
*/ */
ListenableFuture<BigInteger> incrementPayment(BigInteger size) throws ValueOutOfRangeException, IllegalStateException; ListenableFuture<Coin> incrementPayment(Coin size) throws ValueOutOfRangeException, IllegalStateException;
/** /**
* Implements the connection between this client and the server, providing an interface which allows messages to be * Implements the connection between this client and the server, providing an interface which allows messages to be
@ -118,7 +118,7 @@ public interface IPaymentChannelClient {
/** /**
* <p>Indicates the channel has been successfully opened and * <p>Indicates the channel has been successfully opened and
* {@link com.google.bitcoin.protocols.channels.PaymentChannelClient#incrementPayment(java.math.BigInteger)} * {@link com.google.bitcoin.protocols.channels.PaymentChannelClient#incrementPayment(java.math.Coin)}
* may be called at will.</p> * may be called at will.</p>
* *
* <p>Called while holding a lock on the {@link com.google.bitcoin.protocols.channels.PaymentChannelClient} * <p>Called while holding a lock on the {@link com.google.bitcoin.protocols.channels.PaymentChannelClient}

View File

@ -29,7 +29,6 @@ import org.bitcoin.paymentchannel.Protos;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.math.BigInteger;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -85,14 +84,14 @@ public class PaymentChannelClient implements IPaymentChannelClient {
// Information used during channel initialization to send to the server or check what the server sends to us // Information used during channel initialization to send to the server or check what the server sends to us
private final ECKey myKey; private final ECKey myKey;
private final BigInteger maxValue; private final Coin maxValue;
private BigInteger missing; private Coin missing;
@GuardedBy("lock") private long minPayment; @GuardedBy("lock") private long minPayment;
@GuardedBy("lock") SettableFuture<BigInteger> increasePaymentFuture; @GuardedBy("lock") SettableFuture<Coin> increasePaymentFuture;
@GuardedBy("lock") BigInteger lastPaymentActualAmount; @GuardedBy("lock") Coin lastPaymentActualAmount;
/** /**
* <p>The maximum amount of time for which we will accept the server locking up our funds for the multisig * <p>The maximum amount of time for which we will accept the server locking up our funds for the multisig
@ -122,7 +121,7 @@ public class PaymentChannelClient implements IPaymentChannelClient {
* @param conn A callback listener which represents the connection to the server (forwards messages we generate to * @param conn A callback listener which represents the connection to the server (forwards messages we generate to
* the server) * the server)
*/ */
public PaymentChannelClient(Wallet wallet, ECKey myKey, BigInteger maxValue, Sha256Hash serverId, ClientConnection conn) { public PaymentChannelClient(Wallet wallet, ECKey myKey, Coin maxValue, Sha256Hash serverId, ClientConnection conn) {
this.wallet = checkNotNull(wallet); this.wallet = checkNotNull(wallet);
this.myKey = checkNotNull(myKey); this.myKey = checkNotNull(myKey);
this.maxValue = checkNotNull(maxValue); this.maxValue = checkNotNull(maxValue);
@ -136,13 +135,13 @@ public class PaymentChannelClient implements IPaymentChannelClient {
* <p>When InsufficientMoneyException is thrown due to the server requesting too much value, an instance of * <p>When InsufficientMoneyException is thrown due to the server requesting too much value, an instance of
* PaymentChannelClient needs access to how many satoshis are missing.</p> * PaymentChannelClient needs access to how many satoshis are missing.</p>
*/ */
public BigInteger getMissing() { public Coin getMissing() {
return missing; return missing;
} }
@Nullable @Nullable
@GuardedBy("lock") @GuardedBy("lock")
private CloseReason receiveInitiate(Protos.Initiate initiate, BigInteger contractValue, Protos.Error.Builder errorBuilder) throws VerificationException, InsufficientMoneyException { private CloseReason receiveInitiate(Protos.Initiate initiate, Coin contractValue, Protos.Error.Builder errorBuilder) throws VerificationException, InsufficientMoneyException {
log.info("Got INITIATE message:\n{}", initiate.toString()); log.info("Got INITIATE message:\n{}", initiate.toString());
checkState(initiate.getExpireTimeSecs() > 0 && initiate.getMinAcceptedChannelSize() >= 0); checkState(initiate.getExpireTimeSecs() > 0 && initiate.getMinAcceptedChannelSize() >= 0);
@ -156,7 +155,7 @@ public class PaymentChannelClient implements IPaymentChannelClient {
return CloseReason.TIME_WINDOW_TOO_LARGE; return CloseReason.TIME_WINDOW_TOO_LARGE;
} }
BigInteger minChannelSize = BigInteger.valueOf(initiate.getMinAcceptedChannelSize()); Coin minChannelSize = Coin.valueOf(initiate.getMinAcceptedChannelSize());
if (contractValue.compareTo(minChannelSize) < 0) { if (contractValue.compareTo(minChannelSize) < 0) {
log.error("Server requested too much value"); log.error("Server requested too much value");
errorBuilder.setCode(Protos.Error.ErrorCode.CHANNEL_VALUE_TOO_LARGE); errorBuilder.setCode(Protos.Error.ErrorCode.CHANNEL_VALUE_TOO_LARGE);
@ -171,7 +170,7 @@ public class PaymentChannelClient implements IPaymentChannelClient {
log.error("Server requested a min payment of {} but we expected {}", initiate.getMinPayment(), MIN_PAYMENT); log.error("Server requested a min payment of {} but we expected {}", initiate.getMinPayment(), MIN_PAYMENT);
errorBuilder.setCode(Protos.Error.ErrorCode.MIN_PAYMENT_TOO_LARGE); errorBuilder.setCode(Protos.Error.ErrorCode.MIN_PAYMENT_TOO_LARGE);
errorBuilder.setExpectedValue(MIN_PAYMENT); errorBuilder.setExpectedValue(MIN_PAYMENT);
missing = BigInteger.valueOf(initiate.getMinPayment() - MIN_PAYMENT); missing = Coin.valueOf(initiate.getMinPayment() - MIN_PAYMENT);
return CloseReason.SERVER_REQUESTED_TOO_MUCH_VALUE; return CloseReason.SERVER_REQUESTED_TOO_MUCH_VALUE;
} }
@ -218,7 +217,7 @@ public class PaymentChannelClient implements IPaymentChannelClient {
try { try {
// Make an initial payment of the dust limit, and put it into the message as well. The size of the // Make an initial payment of the dust limit, and put it into the message as well. The size of the
// server-requested dust limit was already sanity checked by this point. // server-requested dust limit was already sanity checked by this point.
PaymentChannelClientState.IncrementedPayment payment = state().incrementPaymentBy(BigInteger.valueOf(minPayment)); PaymentChannelClientState.IncrementedPayment payment = state().incrementPaymentBy(Coin.valueOf(minPayment));
Protos.UpdatePayment.Builder initialMsg = contractMsg.getInitialPaymentBuilder(); Protos.UpdatePayment.Builder initialMsg = contractMsg.getInitialPaymentBuilder();
initialMsg.setSignature(ByteString.copyFrom(payment.signature.encodeToBitcoin())); initialMsg.setSignature(ByteString.copyFrom(payment.signature.encodeToBitcoin()));
initialMsg.setClientChangeValue(state.getValueRefunded().longValue()); initialMsg.setClientChangeValue(state.getValueRefunded().longValue());
@ -470,7 +469,7 @@ public class PaymentChannelClient implements IPaymentChannelClient {
* @return a future that completes when the server acknowledges receipt and acceptance of the payment. * @return a future that completes when the server acknowledges receipt and acceptance of the payment.
*/ */
@Override @Override
public ListenableFuture<BigInteger> incrementPayment(BigInteger size) throws ValueOutOfRangeException, IllegalStateException { public ListenableFuture<Coin> incrementPayment(Coin size) throws ValueOutOfRangeException, IllegalStateException {
lock.lock(); lock.lock();
try { try {
if (state() == null || !connectionOpen || step != InitStep.CHANNEL_OPEN) if (state() == null || !connectionOpen || step != InitStep.CHANNEL_OPEN)
@ -505,8 +504,8 @@ public class PaymentChannelClient implements IPaymentChannelClient {
} }
private void receivePaymentAck() { private void receivePaymentAck() {
SettableFuture<BigInteger> future; SettableFuture<Coin> future;
BigInteger value; Coin value;
lock.lock(); lock.lock();
try { try {

View File

@ -16,6 +16,7 @@
package com.google.bitcoin.protocols.channels; package com.google.bitcoin.protocols.channels;
import com.google.bitcoin.core.Coin;
import com.google.bitcoin.core.ECKey; import com.google.bitcoin.core.ECKey;
import com.google.bitcoin.core.InsufficientMoneyException; import com.google.bitcoin.core.InsufficientMoneyException;
import com.google.bitcoin.core.Sha256Hash; import com.google.bitcoin.core.Sha256Hash;
@ -24,10 +25,10 @@ import com.google.bitcoin.net.NioClient;
import com.google.bitcoin.net.ProtobufParser; import com.google.bitcoin.net.ProtobufParser;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture; import com.google.common.util.concurrent.SettableFuture;
import org.bitcoin.paymentchannel.Protos; import org.bitcoin.paymentchannel.Protos;
import java.io.IOException; import java.io.IOException;
import java.math.BigInteger;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
/** /**
@ -60,7 +61,7 @@ public class PaymentChannelClientConnection {
* @throws ValueOutOfRangeException if the balance of wallet is lower than maxValue. * @throws ValueOutOfRangeException if the balance of wallet is lower than maxValue.
*/ */
public PaymentChannelClientConnection(InetSocketAddress server, int timeoutSeconds, Wallet wallet, ECKey myKey, public PaymentChannelClientConnection(InetSocketAddress server, int timeoutSeconds, Wallet wallet, ECKey myKey,
BigInteger maxValue, String serverId) throws IOException, ValueOutOfRangeException { Coin maxValue, String serverId) throws IOException, ValueOutOfRangeException {
// Glue the object which vends/ingests protobuf messages in order to manage state to the network object which // Glue the object which vends/ingests protobuf messages in order to manage state to the network object which
// reads/writes them to the wire in length prefixed form. // reads/writes them to the wire in length prefixed form.
channelClient = new PaymentChannelClient(wallet, myKey, maxValue, Sha256Hash.create(serverId.getBytes()), channelClient = new PaymentChannelClient(wallet, myKey, maxValue, Sha256Hash.create(serverId.getBytes()),
@ -119,7 +120,7 @@ public class PaymentChannelClientConnection {
* an error before the channel has reached the open state.</p> * an error before the channel has reached the open state.</p>
* *
* <p>After this future completes successfully, you may call * <p>After this future completes successfully, you may call
* {@link PaymentChannelClientConnection#incrementPayment(java.math.BigInteger)} to begin paying the server.</p> * {@link PaymentChannelClientConnection#incrementPayment(java.math.Coin)} to begin paying the server.</p>
*/ */
public ListenableFuture<PaymentChannelClientConnection> getChannelOpenFuture() { public ListenableFuture<PaymentChannelClientConnection> getChannelOpenFuture() {
return channelOpenFuture; return channelOpenFuture;
@ -134,7 +135,7 @@ public class PaymentChannelClientConnection {
* @throws IllegalStateException If the channel has been closed or is not yet open * @throws IllegalStateException If the channel has been closed or is not yet open
* (see {@link PaymentChannelClientConnection#getChannelOpenFuture()} for the second) * (see {@link PaymentChannelClientConnection#getChannelOpenFuture()} for the second)
*/ */
public ListenableFuture<BigInteger> incrementPayment(BigInteger size) throws ValueOutOfRangeException, IllegalStateException { public ListenableFuture<Coin> incrementPayment(Coin size) throws ValueOutOfRangeException, IllegalStateException {
return channelClient.incrementPayment(size); return channelClient.incrementPayment(size);
} }

View File

@ -31,7 +31,6 @@ import com.google.common.util.concurrent.ListenableFuture;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.math.BigInteger;
import java.util.List; import java.util.List;
import static com.google.common.base.Preconditions.*; import static com.google.common.base.Preconditions.*;
@ -75,20 +74,20 @@ public class PaymentChannelClientState {
// and transactions that spend it. // and transactions that spend it.
private final ECKey myKey, serverMultisigKey; private final ECKey myKey, serverMultisigKey;
// How much value (in satoshis) is locked up into the channel. // How much value (in satoshis) is locked up into the channel.
private final BigInteger totalValue; private final Coin totalValue;
// When the channel will automatically settle in favor of the client, if the server halts before protocol termination // When the channel will automatically settle in favor of the client, if the server halts before protocol termination
// specified in terms of block timestamps (so it can off real time by a few hours). // specified in terms of block timestamps (so it can off real time by a few hours).
private final long expiryTime; private final long expiryTime;
// The refund is a time locked transaction that spends all the money of the channel back to the client. // The refund is a time locked transaction that spends all the money of the channel back to the client.
private Transaction refundTx; private Transaction refundTx;
private BigInteger refundFees; private Coin refundFees;
// The multi-sig contract locks the value of the channel up such that the agreement of both parties is required // The multi-sig contract locks the value of the channel up such that the agreement of both parties is required
// to spend it. // to spend it.
private Transaction multisigContract; private Transaction multisigContract;
private Script multisigScript; private Script multisigScript;
// How much value is currently allocated to us. Starts as being same as totalValue. // How much value is currently allocated to us. Starts as being same as totalValue.
private BigInteger valueToMe; private Coin valueToMe;
/** /**
* The different logical states the channel can be in. The channel starts out as NEW, and then steps through the * The different logical states the channel can be in. The channel starts out as NEW, and then steps through the
@ -156,7 +155,7 @@ public class PaymentChannelClientState {
* @throws VerificationException If either myKey's pubkey or serverMultisigKey's pubkey are non-canonical (ie invalid) * @throws VerificationException If either myKey's pubkey or serverMultisigKey's pubkey are non-canonical (ie invalid)
*/ */
public PaymentChannelClientState(Wallet wallet, ECKey myKey, ECKey serverMultisigKey, public PaymentChannelClientState(Wallet wallet, ECKey myKey, ECKey serverMultisigKey,
BigInteger value, long expiryTimeInSeconds) throws VerificationException { Coin value, long expiryTimeInSeconds) throws VerificationException {
checkArgument(value.signum() > 0); checkArgument(value.signum() > 0);
this.wallet = checkNotNull(wallet); this.wallet = checkNotNull(wallet);
initWalletListeners(); initWalletListeners();
@ -174,7 +173,7 @@ public class PaymentChannelClientState {
} }
wallet.addEventListener(new AbstractWalletEventListener() { wallet.addEventListener(new AbstractWalletEventListener() {
@Override @Override
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
synchronized (PaymentChannelClientState.this) { synchronized (PaymentChannelClientState.this) {
if (multisigContract == null) return; if (multisigContract == null) return;
if (isSettlementTransaction(tx)) { if (isSettlementTransaction(tx)) {
@ -253,7 +252,7 @@ public class PaymentChannelClientState {
editContractSendRequest(req); editContractSendRequest(req);
req.shuffleOutputs = false; // TODO: Fix things so shuffling is usable. req.shuffleOutputs = false; // TODO: Fix things so shuffling is usable.
wallet.completeTx(req); wallet.completeTx(req);
BigInteger multisigFee = req.fee; Coin multisigFee = req.fee;
multisigContract = req.tx; multisigContract = req.tx;
// Build a refund transaction that protects us in the case of a bad server that's just trying to cause havoc // Build a refund transaction that protects us in the case of a bad server that's just trying to cause havoc
// by locking up peoples money (perhaps as a precursor to a ransom attempt). We time lock it so the server // by locking up peoples money (perhaps as a precursor to a ransom attempt). We time lock it so the server
@ -266,7 +265,7 @@ public class PaymentChannelClientState {
refundTx.setLockTime(expiryTime); refundTx.setLockTime(expiryTime);
if (totalValue.compareTo(Utils.CENT) < 0) { if (totalValue.compareTo(Utils.CENT) < 0) {
// Must pay min fee. // Must pay min fee.
final BigInteger valueAfterFee = totalValue.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE); final Coin valueAfterFee = totalValue.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE);
if (Transaction.MIN_NONDUST_OUTPUT.compareTo(valueAfterFee) > 0) if (Transaction.MIN_NONDUST_OUTPUT.compareTo(valueAfterFee) > 0)
throw new ValueOutOfRangeException("totalValue too small to use"); throw new ValueOutOfRangeException("totalValue too small to use");
refundTx.addOutput(valueAfterFee, myKey.toAddress(params)); refundTx.addOutput(valueAfterFee, myKey.toAddress(params));
@ -292,7 +291,7 @@ public class PaymentChannelClientState {
/** /**
* Returns the transaction that locks the money to the agreement of both parties. Do not mutate the result. * Returns the transaction that locks the money to the agreement of both parties. Do not mutate the result.
* Once this step is done, you can use {@link PaymentChannelClientState#incrementPaymentBy(java.math.BigInteger)} to * Once this step is done, you can use {@link PaymentChannelClientState#incrementPaymentBy(java.math.Coin)} to
* start paying the server. * start paying the server.
*/ */
public synchronized Transaction getMultisigContract() { public synchronized Transaction getMultisigContract() {
@ -348,7 +347,7 @@ public class PaymentChannelClientState {
state = State.SAVE_STATE_IN_WALLET; state = State.SAVE_STATE_IN_WALLET;
} }
private synchronized Transaction makeUnsignedChannelContract(BigInteger valueToMe) throws ValueOutOfRangeException { private synchronized Transaction makeUnsignedChannelContract(Coin valueToMe) throws ValueOutOfRangeException {
Transaction tx = new Transaction(wallet.getParams()); Transaction tx = new Transaction(wallet.getParams());
tx.addInput(multisigContract.getOutput(0)); tx.addInput(multisigContract.getOutput(0));
// Our output always comes first. // Our output always comes first.
@ -373,7 +372,7 @@ public class PaymentChannelClientState {
/** Container for a signature and an amount that was sent. */ /** Container for a signature and an amount that was sent. */
public static class IncrementedPayment { public static class IncrementedPayment {
public TransactionSignature signature; public TransactionSignature signature;
public BigInteger amount; public Coin amount;
} }
/** /**
@ -391,17 +390,17 @@ public class PaymentChannelClientState {
* @throws ValueOutOfRangeException If size is negative or the channel does not have sufficient money in it to * @throws ValueOutOfRangeException If size is negative or the channel does not have sufficient money in it to
* complete this payment. * complete this payment.
*/ */
public synchronized IncrementedPayment incrementPaymentBy(BigInteger size) throws ValueOutOfRangeException { public synchronized IncrementedPayment incrementPaymentBy(Coin size) throws ValueOutOfRangeException {
checkState(state == State.READY); checkState(state == State.READY);
checkNotExpired(); checkNotExpired();
checkNotNull(size); // Validity of size will be checked by makeUnsignedChannelContract. checkNotNull(size); // Validity of size will be checked by makeUnsignedChannelContract.
if (size.signum() < 0) if (size.signum() < 0)
throw new ValueOutOfRangeException("Tried to decrement payment"); throw new ValueOutOfRangeException("Tried to decrement payment");
BigInteger newValueToMe = valueToMe.subtract(size); Coin newValueToMe = valueToMe.subtract(size);
if (newValueToMe.compareTo(Transaction.MIN_NONDUST_OUTPUT) < 0 && newValueToMe.signum() > 0) { if (newValueToMe.compareTo(Transaction.MIN_NONDUST_OUTPUT) < 0 && newValueToMe.signum() > 0) {
log.info("New value being sent back as change was smaller than minimum nondust output, sending all"); log.info("New value being sent back as change was smaller than minimum nondust output, sending all");
size = valueToMe; size = valueToMe;
newValueToMe = BigInteger.ZERO; newValueToMe = Coin.ZERO;
} }
if (newValueToMe.signum() < 0) if (newValueToMe.signum() < 0)
throw new ValueOutOfRangeException("Channel has too little money to pay " + size + " satoshis"); throw new ValueOutOfRangeException("Channel has too little money to pay " + size + " satoshis");
@ -410,7 +409,7 @@ public class PaymentChannelClientState {
Transaction.SigHash mode; Transaction.SigHash mode;
// If we spent all the money we put into this channel, we (by definition) don't care what the outputs are, so // If we spent all the money we put into this channel, we (by definition) don't care what the outputs are, so
// we sign with SIGHASH_NONE to let the server do what it wants. // we sign with SIGHASH_NONE to let the server do what it wants.
if (newValueToMe.equals(BigInteger.ZERO)) if (newValueToMe.equals(Coin.ZERO))
mode = Transaction.SigHash.NONE; mode = Transaction.SigHash.NONE;
else else
mode = Transaction.SigHash.SINGLE; mode = Transaction.SigHash.SINGLE;
@ -500,7 +499,7 @@ public class PaymentChannelClientState {
* Returns the fees that will be paid if the refund transaction has to be claimed because the server failed to settle * Returns the fees that will be paid if the refund transaction has to be claimed because the server failed to settle
* the channel properly. May only be called after {@link PaymentChannelClientState#initiate()} * the channel properly. May only be called after {@link PaymentChannelClientState#initiate()}
*/ */
public synchronized BigInteger getRefundTxFees() { public synchronized Coin getRefundTxFees() {
checkState(state.compareTo(State.NEW) > 0); checkState(state.compareTo(State.NEW) > 0);
return refundFees; return refundFees;
} }
@ -518,14 +517,14 @@ public class PaymentChannelClientState {
/** /**
* Gets the total value of this channel (ie the maximum payment possible) * Gets the total value of this channel (ie the maximum payment possible)
*/ */
public BigInteger getTotalValue() { public Coin getTotalValue() {
return totalValue; return totalValue;
} }
/** /**
* Gets the current amount refunded to us from the multisig contract (ie totalValue-valueSentToServer) * Gets the current amount refunded to us from the multisig contract (ie totalValue-valueSentToServer)
*/ */
public synchronized BigInteger getValueRefunded() { public synchronized Coin getValueRefunded() {
checkState(state == State.READY); checkState(state == State.READY);
return valueToMe; return valueToMe;
} }
@ -533,7 +532,7 @@ public class PaymentChannelClientState {
/** /**
* Returns the amount of money sent on this channel so far. * Returns the amount of money sent on this channel so far.
*/ */
public synchronized BigInteger getValueSpent() { public synchronized Coin getValueSpent() {
return getTotalValue().subtract(getValueRefunded()); return getTotalValue().subtract(getValueRefunded());
} }
} }

View File

@ -27,7 +27,6 @@ import org.bitcoin.paymentchannel.Protos;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.math.BigInteger;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -102,7 +101,7 @@ public class PaymentChannelServer {
* @param by The increase in total payment * @param by The increase in total payment
* @param to The new total payment to us (not including fees which may be required to claim the payment) * @param to The new total payment to us (not including fees which may be required to claim the payment)
*/ */
public void paymentIncrease(BigInteger by, BigInteger to); public void paymentIncrease(Coin by, Coin to);
} }
private final ServerConnection conn; private final ServerConnection conn;
@ -119,7 +118,7 @@ public class PaymentChannelServer {
@GuardedBy("lock") private ECKey myKey; @GuardedBy("lock") private ECKey myKey;
// The minimum accepted channel value // The minimum accepted channel value
private final BigInteger minAcceptedChannelSize; private final Coin minAcceptedChannelSize;
// The state manager for this channel // The state manager for this channel
@GuardedBy("lock") private PaymentChannelServerState state; @GuardedBy("lock") private PaymentChannelServerState state;
@ -151,7 +150,7 @@ public class PaymentChannelServer {
* the client and will close the connection on request) * the client and will close the connection on request)
*/ */
public PaymentChannelServer(TransactionBroadcaster broadcaster, Wallet wallet, public PaymentChannelServer(TransactionBroadcaster broadcaster, Wallet wallet,
BigInteger minAcceptedChannelSize, ServerConnection conn) { Coin minAcceptedChannelSize, ServerConnection conn) {
this.broadcaster = checkNotNull(broadcaster); this.broadcaster = checkNotNull(broadcaster);
this.wallet = checkNotNull(wallet); this.wallet = checkNotNull(wallet);
this.minAcceptedChannelSize = checkNotNull(minAcceptedChannelSize); this.minAcceptedChannelSize = checkNotNull(minAcceptedChannelSize);
@ -310,10 +309,10 @@ public class PaymentChannelServer {
private void receiveUpdatePaymentMessage(Protos.UpdatePayment msg, boolean sendAck) throws VerificationException, ValueOutOfRangeException, InsufficientMoneyException { private void receiveUpdatePaymentMessage(Protos.UpdatePayment msg, boolean sendAck) throws VerificationException, ValueOutOfRangeException, InsufficientMoneyException {
log.info("Got a payment update"); log.info("Got a payment update");
BigInteger lastBestPayment = state.getBestValueToMe(); Coin lastBestPayment = state.getBestValueToMe();
final BigInteger refundSize = BigInteger.valueOf(msg.getClientChangeValue()); final Coin refundSize = Coin.valueOf(msg.getClientChangeValue());
boolean stillUsable = state.incrementPayment(refundSize, msg.getSignature().toByteArray()); boolean stillUsable = state.incrementPayment(refundSize, msg.getSignature().toByteArray());
BigInteger bestPaymentChange = state.getBestValueToMe().subtract(lastBestPayment); Coin bestPaymentChange = state.getBestValueToMe().subtract(lastBestPayment);
if (bestPaymentChange.signum() > 0) if (bestPaymentChange.signum() > 0)
conn.paymentIncrease(bestPaymentChange, state.getBestValueToMe()); conn.paymentIncrease(bestPaymentChange, state.getBestValueToMe());

View File

@ -17,17 +17,19 @@
package com.google.bitcoin.protocols.channels; package com.google.bitcoin.protocols.channels;
import com.google.bitcoin.core.Coin;
import com.google.bitcoin.core.Sha256Hash; import com.google.bitcoin.core.Sha256Hash;
import com.google.bitcoin.core.TransactionBroadcaster; import com.google.bitcoin.core.TransactionBroadcaster;
import com.google.bitcoin.core.Wallet; import com.google.bitcoin.core.Wallet;
import com.google.bitcoin.net.NioServer; import com.google.bitcoin.net.NioServer;
import com.google.bitcoin.net.ProtobufParser; import com.google.bitcoin.net.ProtobufParser;
import com.google.bitcoin.net.StreamParserFactory; import com.google.bitcoin.net.StreamParserFactory;
import org.bitcoin.paymentchannel.Protos; import org.bitcoin.paymentchannel.Protos;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.io.IOException; import java.io.IOException;
import java.math.BigInteger;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
@ -46,7 +48,7 @@ public class PaymentChannelServerListener {
// The event handler factory which creates new ServerConnectionEventHandler per connection // The event handler factory which creates new ServerConnectionEventHandler per connection
private final HandlerFactory eventHandlerFactory; private final HandlerFactory eventHandlerFactory;
private final BigInteger minAcceptedChannelSize; private final Coin minAcceptedChannelSize;
private NioServer server; private NioServer server;
private final int timeoutSeconds; private final int timeoutSeconds;
@ -80,7 +82,7 @@ public class PaymentChannelServerListener {
eventHandler.channelOpen(contractHash); eventHandler.channelOpen(contractHash);
} }
@Override public void paymentIncrease(BigInteger by, BigInteger to) { @Override public void paymentIncrease(Coin by, Coin to) {
eventHandler.paymentIncrease(by, to); eventHandler.paymentIncrease(by, to);
} }
}); });
@ -161,7 +163,7 @@ public class PaymentChannelServerListener {
* @param eventHandlerFactory A factory which generates event handlers which are created for each new connection * @param eventHandlerFactory A factory which generates event handlers which are created for each new connection
*/ */
public PaymentChannelServerListener(TransactionBroadcaster broadcaster, Wallet wallet, public PaymentChannelServerListener(TransactionBroadcaster broadcaster, Wallet wallet,
final int timeoutSeconds, BigInteger minAcceptedChannelSize, final int timeoutSeconds, Coin minAcceptedChannelSize,
HandlerFactory eventHandlerFactory) throws IOException { HandlerFactory eventHandlerFactory) throws IOException {
this.wallet = checkNotNull(wallet); this.wallet = checkNotNull(wallet);
this.broadcaster = checkNotNull(broadcaster); this.broadcaster = checkNotNull(broadcaster);

View File

@ -30,7 +30,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.math.BigInteger;
import java.util.Arrays; import java.util.Arrays;
import static com.google.common.base.Preconditions.*; import static com.google.common.base.Preconditions.*;
@ -101,9 +100,9 @@ public class PaymentChannelServerState {
private byte[] bestValueSignature; private byte[] bestValueSignature;
// The total value locked into the multi-sig output and the value to us in the last signature the client provided // The total value locked into the multi-sig output and the value to us in the last signature the client provided
private BigInteger totalValue; private Coin totalValue;
private BigInteger bestValueToMe = BigInteger.ZERO; private Coin bestValueToMe = Coin.ZERO;
private BigInteger feePaidForPayment; private Coin feePaidForPayment;
// The refund/change transaction output that goes back to the client // The refund/change transaction output that goes back to the client
private TransactionOutput clientOutput; private TransactionOutput clientOutput;
@ -126,7 +125,7 @@ public class PaymentChannelServerState {
this.totalValue = multisigContract.getOutput(0).getValue(); this.totalValue = multisigContract.getOutput(0).getValue();
this.bestValueToMe = checkNotNull(storedServerChannel.bestValueToMe); this.bestValueToMe = checkNotNull(storedServerChannel.bestValueToMe);
this.bestValueSignature = storedServerChannel.bestValueSignature; this.bestValueSignature = storedServerChannel.bestValueSignature;
checkArgument(bestValueToMe.equals(BigInteger.ZERO) || bestValueSignature != null); checkArgument(bestValueToMe.equals(Coin.ZERO) || bestValueSignature != null);
this.storedServerChannel = storedServerChannel; this.storedServerChannel = storedServerChannel;
storedServerChannel.state = this; storedServerChannel.state = this;
this.state = State.READY; this.state = State.READY;
@ -263,9 +262,9 @@ public class PaymentChannelServerState {
} }
// Create a payment transaction with valueToMe going back to us // Create a payment transaction with valueToMe going back to us
private synchronized Wallet.SendRequest makeUnsignedChannelContract(BigInteger valueToMe) { private synchronized Wallet.SendRequest makeUnsignedChannelContract(Coin valueToMe) {
Transaction tx = new Transaction(wallet.getParams()); Transaction tx = new Transaction(wallet.getParams());
if (!totalValue.subtract(valueToMe).equals(BigInteger.ZERO)) { if (!totalValue.subtract(valueToMe).equals(Coin.ZERO)) {
clientOutput.setValue(totalValue.subtract(valueToMe)); clientOutput.setValue(totalValue.subtract(valueToMe));
tx.addOutput(clientOutput); tx.addOutput(clientOutput);
} }
@ -283,17 +282,17 @@ public class PaymentChannelServerState {
* @throws VerificationException If the signature does not verify or size is out of range (incl being rejected by the network as dust). * @throws VerificationException If the signature does not verify or size is out of range (incl being rejected by the network as dust).
* @return true if there is more value left on the channel, false if it is now fully used up. * @return true if there is more value left on the channel, false if it is now fully used up.
*/ */
public synchronized boolean incrementPayment(BigInteger refundSize, byte[] signatureBytes) throws VerificationException, ValueOutOfRangeException, InsufficientMoneyException { public synchronized boolean incrementPayment(Coin refundSize, byte[] signatureBytes) throws VerificationException, ValueOutOfRangeException, InsufficientMoneyException {
checkState(state == State.READY); checkState(state == State.READY);
checkNotNull(refundSize); checkNotNull(refundSize);
checkNotNull(signatureBytes); checkNotNull(signatureBytes);
TransactionSignature signature = TransactionSignature.decodeFromBitcoin(signatureBytes, true); TransactionSignature signature = TransactionSignature.decodeFromBitcoin(signatureBytes, true);
// We allow snapping to zero for the payment amount because it's treated specially later, but not less than // We allow snapping to zero for the payment amount because it's treated specially later, but not less than
// the dust level because that would prevent the transaction from being relayed/mined. // the dust level because that would prevent the transaction from being relayed/mined.
final boolean fullyUsedUp = refundSize.equals(BigInteger.ZERO); final boolean fullyUsedUp = refundSize.equals(Coin.ZERO);
if (refundSize.compareTo(clientOutput.getMinNonDustValue()) < 0 && !fullyUsedUp) if (refundSize.compareTo(clientOutput.getMinNonDustValue()) < 0 && !fullyUsedUp)
throw new ValueOutOfRangeException("Attempt to refund negative value or value too small to be accepted by the network"); throw new ValueOutOfRangeException("Attempt to refund negative value or value too small to be accepted by the network");
BigInteger newValueToMe = totalValue.subtract(refundSize); Coin newValueToMe = totalValue.subtract(refundSize);
if (newValueToMe.signum() < 0) if (newValueToMe.signum() < 0)
throw new ValueOutOfRangeException("Attempt to refund more than the contract allows."); throw new ValueOutOfRangeException("Attempt to refund more than the contract allows.");
if (newValueToMe.compareTo(bestValueToMe) < 0) if (newValueToMe.compareTo(bestValueToMe) < 0)
@ -439,14 +438,14 @@ public class PaymentChannelServerState {
/** /**
* Gets the highest payment to ourselves (which we will receive on settle(), not including fees) * Gets the highest payment to ourselves (which we will receive on settle(), not including fees)
*/ */
public synchronized BigInteger getBestValueToMe() { public synchronized Coin getBestValueToMe() {
return bestValueToMe; return bestValueToMe;
} }
/** /**
* Gets the fee paid in the final payment transaction (only available if settle() did not throw an exception) * Gets the fee paid in the final payment transaction (only available if settle() did not throw an exception)
*/ */
public synchronized BigInteger getFeePaid() { public synchronized Coin getFeePaid() {
checkState(state == State.CLOSED || state == State.CLOSING); checkState(state == State.CLOSED || state == State.CLOSING);
return feePaidForPayment; return feePaidForPayment;
} }

View File

@ -16,10 +16,10 @@
package com.google.bitcoin.protocols.channels; package com.google.bitcoin.protocols.channels;
import java.math.BigInteger; import com.google.bitcoin.core.Coin;
import com.google.bitcoin.core.Sha256Hash; import com.google.bitcoin.core.Sha256Hash;
import com.google.bitcoin.net.ProtobufParser; import com.google.bitcoin.net.ProtobufParser;
import org.bitcoin.paymentchannel.Protos; import org.bitcoin.paymentchannel.Protos;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -70,7 +70,7 @@ public abstract class ServerConnectionEventHandler {
* @param by The increase in total payment * @param by The increase in total payment
* @param to The new total payment to us (not including fees which may be required to claim the payment) * @param to The new total payment to us (not including fees which may be required to claim the payment)
*/ */
public abstract void paymentIncrease(BigInteger by, BigInteger to); public abstract void paymentIncrease(Coin by, Coin to);
/** /**
* <p>Called when the channel was closed for some reason. May be called without a call to * <p>Called when the channel was closed for some reason. May be called without a call to

View File

@ -26,7 +26,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.math.BigInteger;
import java.util.Date; import java.util.Date;
import java.util.Set; import java.util.Set;
import java.util.Timer; import java.util.Timer;
@ -69,8 +68,8 @@ public class StoredPaymentChannelClientStates implements WalletExtension {
} }
/** Returns the outstanding amount of money sent back to us for all channels to this server added together. */ /** Returns the outstanding amount of money sent back to us for all channels to this server added together. */
public BigInteger getBalanceForServer(Sha256Hash id) { public Coin getBalanceForServer(Sha256Hash id) {
BigInteger balance = BigInteger.ZERO; Coin balance = Coin.ZERO;
lock.lock(); lock.lock();
try { try {
Set<StoredClientChannel> setChannels = mapChannels.get(id); Set<StoredClientChannel> setChannels = mapChannels.get(id);
@ -120,7 +119,7 @@ public class StoredPaymentChannelClientStates implements WalletExtension {
synchronized (channel) { synchronized (channel) {
// Check if the channel is usable (has money, inactive) and if so, activate it. // Check if the channel is usable (has money, inactive) and if so, activate it.
log.info("Considering channel {} contract {}", channel.hashCode(), channel.contract.getHash()); log.info("Considering channel {} contract {}", channel.hashCode(), channel.contract.getHash());
if (channel.close != null || channel.valueToMe.equals(BigInteger.ZERO)) { if (channel.close != null || channel.valueToMe.equals(Coin.ZERO)) {
log.info(" ... but is closed or empty"); log.info(" ... but is closed or empty");
continue; continue;
} }
@ -256,8 +255,8 @@ public class StoredPaymentChannelClientStates implements WalletExtension {
new Transaction(params, storedState.getContractTransaction().toByteArray()), new Transaction(params, storedState.getContractTransaction().toByteArray()),
refundTransaction, refundTransaction,
ECKey.fromPrivate(storedState.getMyKey().toByteArray()), ECKey.fromPrivate(storedState.getMyKey().toByteArray()),
BigInteger.valueOf(storedState.getValueToMe()), Coin.valueOf(storedState.getValueToMe()),
BigInteger.valueOf(storedState.getRefundFees()), false); Coin.valueOf(storedState.getRefundFees()), false);
if (storedState.hasCloseTransactionHash()) if (storedState.hasCloseTransactionHash())
channel.close = containingWallet.getTransaction(new Sha256Hash(storedState.toByteArray())); channel.close = containingWallet.getTransaction(new Sha256Hash(storedState.toByteArray()));
putChannel(channel, false); putChannel(channel, false);
@ -292,13 +291,13 @@ class StoredClientChannel {
// The transaction that closed the channel (generated by the server) // The transaction that closed the channel (generated by the server)
Transaction close; Transaction close;
ECKey myKey; ECKey myKey;
BigInteger valueToMe, refundFees; Coin valueToMe, refundFees;
// In-memory flag to indicate intent to resume this channel (or that the channel is already in use) // In-memory flag to indicate intent to resume this channel (or that the channel is already in use)
boolean active = false; boolean active = false;
StoredClientChannel(Sha256Hash id, Transaction contract, Transaction refund, ECKey myKey, BigInteger valueToMe, StoredClientChannel(Sha256Hash id, Transaction contract, Transaction refund, ECKey myKey, Coin valueToMe,
BigInteger refundFees, boolean active) { Coin refundFees, boolean active) {
this.id = id; this.id = id;
this.contract = contract; this.contract = contract;
this.refund = refund; this.refund = refund;

View File

@ -24,7 +24,6 @@ import net.jcip.annotations.GuardedBy;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.math.BigInteger;
import java.util.*; import java.util.*;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
@ -183,7 +182,7 @@ public class StoredPaymentChannelServerStates implements WalletExtension {
new TransactionOutput(params, null, storedState.getClientOutput().toByteArray(), 0), new TransactionOutput(params, null, storedState.getClientOutput().toByteArray(), 0),
storedState.getRefundTransactionUnlockTimeSecs(), storedState.getRefundTransactionUnlockTimeSecs(),
ECKey.fromPrivate(storedState.getMyKey().toByteArray()), ECKey.fromPrivate(storedState.getMyKey().toByteArray()),
BigInteger.valueOf(storedState.getBestValueToMe()), Coin.valueOf(storedState.getBestValueToMe()),
storedState.hasBestValueSignature() ? storedState.getBestValueSignature().toByteArray() : null); storedState.hasBestValueSignature() ? storedState.getBestValueSignature().toByteArray() : null);
putChannel(channel); putChannel(channel);
} }

View File

@ -19,7 +19,6 @@ package com.google.bitcoin.protocols.channels;
import com.google.bitcoin.core.*; import com.google.bitcoin.core.*;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.math.BigInteger;
import java.util.Date; import java.util.Date;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
@ -30,7 +29,7 @@ import static com.google.common.base.Preconditions.checkArgument;
* time approaches. * time approaches.
*/ */
public class StoredServerChannel { public class StoredServerChannel {
BigInteger bestValueToMe; Coin bestValueToMe;
byte[] bestValueSignature; byte[] bestValueSignature;
long refundTransactionUnlockTimeSecs; long refundTransactionUnlockTimeSecs;
Transaction contract; Transaction contract;
@ -43,7 +42,7 @@ public class StoredServerChannel {
PaymentChannelServerState state = null; PaymentChannelServerState state = null;
StoredServerChannel(@Nullable PaymentChannelServerState state, Transaction contract, TransactionOutput clientOutput, StoredServerChannel(@Nullable PaymentChannelServerState state, Transaction contract, TransactionOutput clientOutput,
long refundTransactionUnlockTimeSecs, ECKey myKey, BigInteger bestValueToMe, @Nullable byte[] bestValueSignature) { long refundTransactionUnlockTimeSecs, ECKey myKey, Coin bestValueToMe, @Nullable byte[] bestValueSignature) {
this.contract = contract; this.contract = contract;
this.clientOutput = clientOutput; this.clientOutput = clientOutput;
this.refundTransactionUnlockTimeSecs = refundTransactionUnlockTimeSecs; this.refundTransactionUnlockTimeSecs = refundTransactionUnlockTimeSecs;
@ -57,7 +56,7 @@ public class StoredServerChannel {
* <p>Updates the best value to the server to the given newValue and newSignature without any checking.</p> * <p>Updates the best value to the server to the given newValue and newSignature without any checking.</p>
* <p>Does <i>NOT</i> notify the wallet of an update to the {@link StoredPaymentChannelServerStates}.</p> * <p>Does <i>NOT</i> notify the wallet of an update to the {@link StoredPaymentChannelServerStates}.</p>
*/ */
synchronized void updateValueToMe(BigInteger newValue, byte[] newSignature) { synchronized void updateValueToMe(Coin newValue, byte[] newSignature) {
this.bestValueToMe = newValue; this.bestValueToMe = newValue;
this.bestValueSignature = newSignature; this.bestValueSignature = newSignature;
} }
@ -107,11 +106,11 @@ public class StoredServerChannel {
final String newline = String.format("%n"); final String newline = String.format("%n");
return String.format("Stored server channel (%s)%n" + return String.format("Stored server channel (%s)%n" +
" Key: %s%n" + " Key: %s%n" +
" Value to me: %d%n" + " Value to me: %s%n" +
" Client output: %s%n" + " Client output: %s%n" +
" Refund unlock: %s (%d unix time)%n" + " Refund unlock: %s (%d unix time)%n" +
" Contract: %s%n", " Contract: %s%n",
connectedHandler != null ? "connected" : "disconnected", myKey, bestValueToMe, connectedHandler != null ? "connected" : "disconnected", myKey, bestValueToMe.toString(),
clientOutput, new Date(refundTransactionUnlockTimeSecs * 1000), refundTransactionUnlockTimeSecs, clientOutput, new Date(refundTransactionUnlockTimeSecs * 1000), refundTransactionUnlockTimeSecs,
contract.toString().replaceAll(newline, newline + " ")); contract.toString().replaceAll(newline, newline + " "));
} }

View File

@ -18,6 +18,7 @@
package com.google.bitcoin.protocols.payments; package com.google.bitcoin.protocols.payments;
import com.google.bitcoin.core.Address; import com.google.bitcoin.core.Address;
import com.google.bitcoin.core.Coin;
import com.google.bitcoin.core.NetworkParameters; import com.google.bitcoin.core.NetworkParameters;
import com.google.bitcoin.core.Transaction; import com.google.bitcoin.core.Transaction;
import com.google.bitcoin.crypto.X509Utils; import com.google.bitcoin.crypto.X509Utils;
@ -30,7 +31,6 @@ import org.bitcoin.protocols.payments.Protos;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigInteger;
import java.security.*; import java.security.*;
import java.security.cert.*; import java.security.cert.*;
import java.security.cert.Certificate; import java.security.cert.Certificate;
@ -67,7 +67,7 @@ public class PaymentProtocol {
* @return created payment request, in its builder form * @return created payment request, in its builder form
*/ */
public static Protos.PaymentRequest.Builder createPaymentRequest(NetworkParameters params, public static Protos.PaymentRequest.Builder createPaymentRequest(NetworkParameters params,
@Nullable BigInteger amount, Address toAddress, @Nullable String memo, @Nullable String paymentUrl, @Nullable Coin amount, Address toAddress, @Nullable String memo, @Nullable String paymentUrl,
@Nullable byte[] merchantData) { @Nullable byte[] merchantData) {
return createPaymentRequest(params, ImmutableList.of(createPayToAddressOutput(amount, toAddress)), memo, return createPaymentRequest(params, ImmutableList.of(createPayToAddressOutput(amount, toAddress)), memo,
paymentUrl, merchantData); paymentUrl, merchantData);
@ -282,7 +282,7 @@ public class PaymentProtocol {
* @return created payment message * @return created payment message
*/ */
public static Protos.Payment createPaymentMessage(List<Transaction> transactions, public static Protos.Payment createPaymentMessage(List<Transaction> transactions,
@Nullable BigInteger refundAmount, @Nullable Address refundAddress, @Nullable String memo, @Nullable Coin refundAmount, @Nullable Address refundAddress, @Nullable String memo,
@Nullable byte[] merchantData) { @Nullable byte[] merchantData) {
if (refundAddress != null) { if (refundAddress != null) {
if (refundAmount == null) if (refundAmount == null)
@ -387,7 +387,7 @@ public class PaymentProtocol {
* @param address address to pay to * @param address address to pay to
* @return output * @return output
*/ */
public static Protos.Output createPayToAddressOutput(@Nullable BigInteger amount, Address address) { public static Protos.Output createPayToAddressOutput(@Nullable Coin amount, Address address) {
Protos.Output.Builder output = Protos.Output.newBuilder(); Protos.Output.Builder output = Protos.Output.newBuilder();
if (amount != null) { if (amount != null) {
if (amount.compareTo(NetworkParameters.MAX_MONEY) > 0) if (amount.compareTo(NetworkParameters.MAX_MONEY) > 0)
@ -404,10 +404,10 @@ public class PaymentProtocol {
* Value object to hold amount/script pairs. * Value object to hold amount/script pairs.
*/ */
public static class Output implements Serializable { public static class Output implements Serializable {
public final @Nullable BigInteger amount; public final @Nullable Coin amount;
public final byte[] scriptData; public final byte[] scriptData;
public Output(@Nullable BigInteger amount, byte[] scriptData) { public Output(@Nullable Coin amount, byte[] scriptData) {
this.amount = amount; this.amount = amount;
this.scriptData = scriptData; this.scriptData = scriptData;
} }

View File

@ -30,7 +30,6 @@ import org.bitcoin.protocols.payments.Protos;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.io.*; import java.io.*;
import java.math.BigInteger;
import java.net.*; import java.net.*;
import java.security.KeyStoreException; import java.security.KeyStoreException;
import java.util.ArrayList; import java.util.ArrayList;
@ -71,7 +70,7 @@ public class PaymentSession {
private final TrustStoreLoader trustStoreLoader; private final TrustStoreLoader trustStoreLoader;
private Protos.PaymentRequest paymentRequest; private Protos.PaymentRequest paymentRequest;
private Protos.PaymentDetails paymentDetails; private Protos.PaymentDetails paymentDetails;
private BigInteger totalValue = BigInteger.ZERO; private Coin totalValue = Coin.ZERO;
/** /**
* Stores the calculated PKI verification data, or null if none is available. * Stores the calculated PKI verification data, or null if none is available.
@ -224,7 +223,7 @@ public class PaymentSession {
public List<PaymentProtocol.Output> getOutputs() { public List<PaymentProtocol.Output> getOutputs() {
List<PaymentProtocol.Output> outputs = new ArrayList<PaymentProtocol.Output>(paymentDetails.getOutputsCount()); List<PaymentProtocol.Output> outputs = new ArrayList<PaymentProtocol.Output>(paymentDetails.getOutputsCount());
for (Protos.Output output : paymentDetails.getOutputsList()) { for (Protos.Output output : paymentDetails.getOutputsList()) {
BigInteger amount = output.hasAmount() ? BigInteger.valueOf(output.getAmount()) : null; Coin amount = output.hasAmount() ? Coin.valueOf(output.getAmount()) : null;
outputs.add(new PaymentProtocol.Output(amount, output.getScript().toByteArray())); outputs.add(new PaymentProtocol.Output(amount, output.getScript().toByteArray()));
} }
return outputs; return outputs;
@ -243,7 +242,7 @@ public class PaymentSession {
/** /**
* Returns the total amount of bitcoins requested. * Returns the total amount of bitcoins requested.
*/ */
public BigInteger getValue() { public Coin getValue() {
return totalValue; return totalValue;
} }
@ -297,7 +296,7 @@ public class PaymentSession {
public Wallet.SendRequest getSendRequest() { public Wallet.SendRequest getSendRequest() {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
for (Protos.Output output : paymentDetails.getOutputsList()) for (Protos.Output output : paymentDetails.getOutputsList())
tx.addOutput(new TransactionOutput(params, tx, BigInteger.valueOf(output.getAmount()), output.getScript().toByteArray())); tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(output.getAmount()), output.getScript().toByteArray()));
return Wallet.SendRequest.forTx(tx); return Wallet.SendRequest.forTx(tx);
} }
@ -397,7 +396,7 @@ public class PaymentSession {
throw new PaymentProtocolException.InvalidOutputs("No outputs"); throw new PaymentProtocolException.InvalidOutputs("No outputs");
for (Protos.Output output : paymentDetails.getOutputsList()) { for (Protos.Output output : paymentDetails.getOutputsList()) {
if (output.hasAmount()) if (output.hasAmount())
totalValue = totalValue.add(BigInteger.valueOf(output.getAmount())); totalValue = totalValue.add(Coin.valueOf(output.getAmount()));
} }
// This won't ever happen in practice. It would only happen if the user provided outputs // This won't ever happen in practice. It would only happen if the user provided outputs
// that are obviously invalid. Still, we don't want to silently overflow. // that are obviously invalid. Still, we don't want to silently overflow.

View File

@ -650,7 +650,7 @@ public class H2FullPrunedBlockStore implements FullPrunedBlockStore {
} }
// Parse it. // Parse it.
int height = results.getInt(1); int height = results.getInt(1);
BigInteger value = new BigInteger(results.getBytes(2)); Coin value = new Coin(results.getBytes(2));
// Tell the StoredTransactionOutput that we are a coinbase, as that is encoded in height // Tell the StoredTransactionOutput that we are a coinbase, as that is encoded in height
return new StoredTransactionOutput(hash, index, value, height, true, results.getBytes(3)); return new StoredTransactionOutput(hash, index, value, height, true, results.getBytes(3));
} catch (SQLException ex) { } catch (SQLException ex) {

View File

@ -744,7 +744,7 @@ public class PostgresFullPrunedBlockStore implements FullPrunedBlockStore {
} }
// Parse it. // Parse it.
int height = results.getInt(1); int height = results.getInt(1);
BigInteger value = new BigInteger(results.getBytes(2)); Coin value = new Coin(results.getBytes(2));
// Tell the StoredTransactionOutput that we are a coinbase, as that is encoded in height // Tell the StoredTransactionOutput that we are a coinbase, as that is encoded in height
StoredTransactionOutput txout = new StoredTransactionOutput(hash, index, value, height, true, results.getBytes(3)); StoredTransactionOutput txout = new StoredTransactionOutput(hash, index, value, height, true, results.getBytes(3));
return txout; return txout;

View File

@ -503,7 +503,7 @@ public class WalletProtobufSerializer {
} }
for (Protos.TransactionOutput outputProto : txProto.getTransactionOutputList()) { for (Protos.TransactionOutput outputProto : txProto.getTransactionOutputList()) {
BigInteger value = BigInteger.valueOf(outputProto.getValue()); Coin value = Coin.valueOf(outputProto.getValue());
byte[] scriptBytes = outputProto.getScriptBytes().toByteArray(); byte[] scriptBytes = outputProto.getScriptBytes().toByteArray();
TransactionOutput output = new TransactionOutput(params, tx, value, scriptBytes); TransactionOutput output = new TransactionOutput(params, tx, value, scriptBytes);
tx.addOutput(output); tx.addOutput(output);
@ -515,7 +515,7 @@ public class WalletProtobufSerializer {
inputProto.getTransactionOutPointIndex() & 0xFFFFFFFFL, inputProto.getTransactionOutPointIndex() & 0xFFFFFFFFL,
byteStringToHash(inputProto.getTransactionOutPointHash()) byteStringToHash(inputProto.getTransactionOutPointHash())
); );
BigInteger value = inputProto.hasValue() ? BigInteger.valueOf(inputProto.getValue()) : null; Coin value = inputProto.hasValue() ? Coin.valueOf(inputProto.getValue()) : null;
TransactionInput input = new TransactionInput(params, tx, scriptBytes, outpoint, value); TransactionInput input = new TransactionInput(params, tx, scriptBytes, outpoint, value);
if (inputProto.hasSequence()) { if (inputProto.hasSequence()) {
input.setSequenceNumber(inputProto.getSequence()); input.setSequenceNumber(inputProto.getSequence());

View File

@ -22,7 +22,6 @@ import com.google.bitcoin.store.BlockStoreException;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.math.BigInteger;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
/** /**
@ -33,7 +32,7 @@ public class FakeTxBuilder {
* Create a fake TX of sufficient realism to exercise the unit tests. Two outputs, one to us, one to somewhere * Create a fake TX of sufficient realism to exercise the unit tests. Two outputs, one to us, one to somewhere
* else to simulate change. There is one random input. * else to simulate change. There is one random input.
*/ */
public static Transaction createFakeTxWithChangeAddress(NetworkParameters params, BigInteger nanocoins, Address to, Address changeOutput) { public static Transaction createFakeTxWithChangeAddress(NetworkParameters params, Coin nanocoins, Address to, Address changeOutput) {
Transaction t = new Transaction(params); Transaction t = new Transaction(params);
TransactionOutput outputToMe = new TransactionOutput(params, t, nanocoins, to); TransactionOutput outputToMe = new TransactionOutput(params, t, nanocoins, to);
t.addOutput(outputToMe); t.addOutput(outputToMe);
@ -54,7 +53,7 @@ public class FakeTxBuilder {
* Create a fake TX of sufficient realism to exercise the unit tests. Two outputs, one to us, one to somewhere * Create a fake TX of sufficient realism to exercise the unit tests. Two outputs, one to us, one to somewhere
* else to simulate change. There is one random input. * else to simulate change. There is one random input.
*/ */
public static Transaction createFakeTx(NetworkParameters params, BigInteger nanocoins, Address to) { public static Transaction createFakeTx(NetworkParameters params, Coin nanocoins, Address to) {
return createFakeTxWithChangeAddress(params, nanocoins, to, new ECKey().toAddress(params)); return createFakeTxWithChangeAddress(params, nanocoins, to, new ECKey().toAddress(params));
} }
@ -62,7 +61,7 @@ public class FakeTxBuilder {
* Create a fake TX of sufficient realism to exercise the unit tests. Two outputs, one to us, one to somewhere * Create a fake TX of sufficient realism to exercise the unit tests. Two outputs, one to us, one to somewhere
* else to simulate change. There is one random input. * else to simulate change. There is one random input.
*/ */
public static Transaction createFakeTx(NetworkParameters params, BigInteger nanocoins, ECKey to) { public static Transaction createFakeTx(NetworkParameters params, Coin nanocoins, ECKey to) {
Transaction t = new Transaction(params); Transaction t = new Transaction(params);
TransactionOutput outputToMe = new TransactionOutput(params, t, nanocoins, to); TransactionOutput outputToMe = new TransactionOutput(params, t, nanocoins, to);
t.addOutput(outputToMe); t.addOutput(outputToMe);
@ -82,7 +81,7 @@ public class FakeTxBuilder {
/** /**
* Transaction[0] is a feeder transaction, supplying BTC to Transaction[1] * Transaction[0] is a feeder transaction, supplying BTC to Transaction[1]
*/ */
public static Transaction[] createFakeTx(NetworkParameters params, BigInteger nanocoins, public static Transaction[] createFakeTx(NetworkParameters params, Coin nanocoins,
Address to, Address from) { Address to, Address from) {
// Create fake TXes of sufficient realism to exercise the unit tests. This transaction send BTC from the // Create fake TXes of sufficient realism to exercise the unit tests. This transaction send BTC from the
// from address, to the to address with to one to somewhere else to simulate change. // from address, to the to address with to one to somewhere else to simulate change.
@ -134,7 +133,7 @@ public class FakeTxBuilder {
*/ */
public static DoubleSpends createFakeDoubleSpendTxns(NetworkParameters params, Address to) { public static DoubleSpends createFakeDoubleSpendTxns(NetworkParameters params, Address to) {
DoubleSpends doubleSpends = new DoubleSpends(); DoubleSpends doubleSpends = new DoubleSpends();
BigInteger value = Utils.toNanoCoins(1, 0); Coin value = Utils.toNanoCoins(1, 0);
Address someBadGuy = new ECKey().toAddress(params); Address someBadGuy = new ECKey().toAddress(params);
doubleSpends.t1 = new Transaction(params); doubleSpends.t1 = new Transaction(params);

View File

@ -29,7 +29,6 @@ import com.google.common.util.concurrent.SettableFuture;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.net.SocketFactory; import javax.net.SocketFactory;
import java.io.IOException; import java.io.IOException;
import java.math.BigInteger;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
@ -82,7 +81,7 @@ public class TestWithNetworkConnections {
BriefLogFormatter.init(); BriefLogFormatter.init();
unitTestParams = UnitTestParams.get(); unitTestParams = UnitTestParams.get();
Wallet.SendRequest.DEFAULT_FEE_PER_KB = BigInteger.ZERO; Wallet.SendRequest.DEFAULT_FEE_PER_KB = Coin.ZERO;
this.blockStore = blockStore; this.blockStore = blockStore;
wallet = new Wallet(unitTestParams); wallet = new Wallet(unitTestParams);
key = wallet.freshReceiveKey(); key = wallet.freshReceiveKey();

View File

@ -24,7 +24,6 @@ import com.google.bitcoin.utils.BriefLogFormatter;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.io.IOException; import java.io.IOException;
import java.math.BigInteger;
import static com.google.bitcoin.testing.FakeTxBuilder.createFakeBlock; import static com.google.bitcoin.testing.FakeTxBuilder.createFakeBlock;
import static com.google.bitcoin.testing.FakeTxBuilder.createFakeTx; import static com.google.bitcoin.testing.FakeTxBuilder.createFakeTx;
@ -49,7 +48,7 @@ public class TestWithWallet {
public void setUp() throws Exception { public void setUp() throws Exception {
BriefLogFormatter.init(); BriefLogFormatter.init();
Wallet.SendRequest.DEFAULT_FEE_PER_KB = BigInteger.ZERO; Wallet.SendRequest.DEFAULT_FEE_PER_KB = Coin.ZERO;
wallet = new Wallet(params); wallet = new Wallet(params);
myKey = wallet.currentReceiveKey(); myKey = wallet.currentReceiveKey();
myAddress = myKey.toAddress(params); myAddress = myKey.toAddress(params);
@ -83,17 +82,17 @@ public class TestWithWallet {
} }
@Nullable @Nullable
protected Transaction sendMoneyToWallet(Wallet wallet, BigInteger value, Address toAddress, AbstractBlockChain.NewBlockType type) throws IOException, VerificationException { protected Transaction sendMoneyToWallet(Wallet wallet, Coin value, Address toAddress, AbstractBlockChain.NewBlockType type) throws IOException, VerificationException {
return sendMoneyToWallet(wallet, createFakeTx(params, value, toAddress), type); return sendMoneyToWallet(wallet, createFakeTx(params, value, toAddress), type);
} }
@Nullable @Nullable
protected Transaction sendMoneyToWallet(Wallet wallet, BigInteger value, ECKey toPubKey, AbstractBlockChain.NewBlockType type) throws IOException, VerificationException { protected Transaction sendMoneyToWallet(Wallet wallet, Coin value, ECKey toPubKey, AbstractBlockChain.NewBlockType type) throws IOException, VerificationException {
return sendMoneyToWallet(wallet, createFakeTx(params, value, toPubKey), type); return sendMoneyToWallet(wallet, createFakeTx(params, value, toPubKey), type);
} }
@Nullable @Nullable
protected Transaction sendMoneyToWallet(BigInteger value, AbstractBlockChain.NewBlockType type) throws IOException, VerificationException { protected Transaction sendMoneyToWallet(Coin value, AbstractBlockChain.NewBlockType type) throws IOException, VerificationException {
return sendMoneyToWallet(this.wallet, createFakeTx(params, value, myAddress), type); return sendMoneyToWallet(this.wallet, createFakeTx(params, value, myAddress), type);
} }
} }

View File

@ -20,14 +20,16 @@ package com.google.bitcoin.uri;
import com.google.bitcoin.core.Address; import com.google.bitcoin.core.Address;
import com.google.bitcoin.core.AddressFormatException; import com.google.bitcoin.core.AddressFormatException;
import com.google.bitcoin.core.Coin;
import com.google.bitcoin.core.NetworkParameters; import com.google.bitcoin.core.NetworkParameters;
import com.google.bitcoin.core.Utils; import com.google.bitcoin.core.Utils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URLDecoder; import java.net.URLDecoder;
@ -207,7 +209,7 @@ public class BitcoinURI {
if (FIELD_AMOUNT.equals(nameToken)) { if (FIELD_AMOUNT.equals(nameToken)) {
// Decode the amount (contains an optional decimal component to 8dp). // Decode the amount (contains an optional decimal component to 8dp).
try { try {
BigInteger amount = Utils.toNanoCoins(valueToken); Coin amount = Utils.toNanoCoins(valueToken);
putWithValidation(FIELD_AMOUNT, amount); putWithValidation(FIELD_AMOUNT, amount);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new OptionalFieldValidationException(String.format("'%s' is not a valid amount", valueToken), e); throw new OptionalFieldValidationException(String.format("'%s' is not a valid amount", valueToken), e);
@ -263,8 +265,8 @@ public class BitcoinURI {
* @return The amount name encoded using a pure integer value based at * @return The amount name encoded using a pure integer value based at
* 10,000,000 units is 1 BTC. May be null if no amount is specified * 10,000,000 units is 1 BTC. May be null if no amount is specified
*/ */
public BigInteger getAmount() { public Coin getAmount() {
return (BigInteger) parameterMap.get(FIELD_AMOUNT); return (Coin) parameterMap.get(FIELD_AMOUNT);
} }
/** /**
@ -313,7 +315,7 @@ public class BitcoinURI {
return builder.toString(); return builder.toString();
} }
public static String convertToBitcoinURI(Address address, BigInteger amount, String label, String message) { public static String convertToBitcoinURI(Address address, Coin amount, String label, String message) {
return convertToBitcoinURI(address.toString(), amount, label, message); return convertToBitcoinURI(address.toString(), amount, label, message);
} }
@ -326,11 +328,11 @@ public class BitcoinURI {
* @param message A message * @param message A message
* @return A String containing the Bitcoin URI * @return A String containing the Bitcoin URI
*/ */
public static String convertToBitcoinURI(String address, @Nullable BigInteger amount, @Nullable String label, public static String convertToBitcoinURI(String address, @Nullable Coin amount, @Nullable String label,
@Nullable String message) { @Nullable String message) {
checkNotNull(address); checkNotNull(address);
if (amount != null && amount.signum() < 0) { if (amount != null && amount.signum() < 0) {
throw new IllegalArgumentException("Amount must be positive"); throw new IllegalArgumentException("Coin must be positive");
} }
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();

View File

@ -1,22 +1,22 @@
package com.google.bitcoin.wallet; package com.google.bitcoin.wallet;
import com.google.bitcoin.core.Coin;
import com.google.bitcoin.core.TransactionOutput; import com.google.bitcoin.core.TransactionOutput;
import java.math.BigInteger;
import java.util.Collection; import java.util.Collection;
/** /**
* Represents the results of a * Represents the results of a
* {@link com.google.bitcoin.wallet.CoinSelector#select(java.math.BigInteger, java.util.LinkedList)} operation. A * {@link com.google.bitcoin.wallet.CoinSelector#select(java.math.Coin, java.util.LinkedList)} operation. A
* coin selection represents a list of spendable transaction outputs that sum together to give valueGathered. * coin selection represents a list of spendable transaction outputs that sum together to give valueGathered.
* Different coin selections could be produced by different coin selectors from the same input set, according * Different coin selections could be produced by different coin selectors from the same input set, according
* to their varying policies. * to their varying policies.
*/ */
public class CoinSelection { public class CoinSelection {
public BigInteger valueGathered; public Coin valueGathered;
public Collection<TransactionOutput> gathered; public Collection<TransactionOutput> gathered;
public CoinSelection(BigInteger valueGathered, Collection<TransactionOutput> gathered) { public CoinSelection(Coin valueGathered, Collection<TransactionOutput> gathered) {
this.valueGathered = valueGathered; this.valueGathered = valueGathered;
this.gathered = gathered; this.gathered = gathered;
} }

View File

@ -1,8 +1,8 @@
package com.google.bitcoin.wallet; package com.google.bitcoin.wallet;
import com.google.bitcoin.core.Coin;
import com.google.bitcoin.core.TransactionOutput; import com.google.bitcoin.core.TransactionOutput;
import java.math.BigInteger;
import java.util.LinkedList; import java.util.LinkedList;
/** /**
@ -17,5 +17,5 @@ public interface CoinSelector {
* this call and can be edited freely. See the docs for CoinSelection to learn more, or look a the implementation * this call and can be edited freely. See the docs for CoinSelection to learn more, or look a the implementation
* of {@link com.google.bitcoin.wallet.DefaultCoinSelector}. * of {@link com.google.bitcoin.wallet.DefaultCoinSelector}.
*/ */
public CoinSelection select(BigInteger target, LinkedList<TransactionOutput> candidates); public CoinSelection select(Coin target, LinkedList<TransactionOutput> candidates);
} }

View File

@ -1,5 +1,6 @@
package com.google.bitcoin.wallet; package com.google.bitcoin.wallet;
import com.google.bitcoin.core.Coin;
import com.google.bitcoin.core.NetworkParameters; import com.google.bitcoin.core.NetworkParameters;
import com.google.bitcoin.core.Transaction; import com.google.bitcoin.core.Transaction;
import com.google.bitcoin.core.TransactionConfidence; import com.google.bitcoin.core.TransactionConfidence;
@ -16,7 +17,7 @@ import java.util.*;
* "spending" more priority than would be required to get the transaction we are creating confirmed. * "spending" more priority than would be required to get the transaction we are creating confirmed.
*/ */
public class DefaultCoinSelector implements CoinSelector { public class DefaultCoinSelector implements CoinSelector {
public CoinSelection select(BigInteger biTarget, LinkedList<TransactionOutput> candidates) { public CoinSelection select(Coin biTarget, LinkedList<TransactionOutput> candidates) {
long target = biTarget.longValue(); long target = biTarget.longValue();
HashSet<TransactionOutput> selected = new HashSet<TransactionOutput>(); HashSet<TransactionOutput> selected = new HashSet<TransactionOutput>();
// Sort the inputs by age*value so we get the highest "coindays" spent. // Sort the inputs by age*value so we get the highest "coindays" spent.
@ -39,7 +40,7 @@ public class DefaultCoinSelector implements CoinSelector {
} }
// Total may be lower than target here, if the given candidates were insufficient to create to requested // Total may be lower than target here, if the given candidates were insufficient to create to requested
// transaction. // transaction.
return new CoinSelection(BigInteger.valueOf(total), selected); return new CoinSelection(Coin.valueOf(total), selected);
} }
@VisibleForTesting static void sortOutputs(ArrayList<TransactionOutput> outputs) { @VisibleForTesting static void sortOutputs(ArrayList<TransactionOutput> outputs) {
@ -53,10 +54,10 @@ public class DefaultCoinSelector implements CoinSelector {
depth1 = conf1.getDepthInBlocks(); depth1 = conf1.getDepthInBlocks();
if (conf2.getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING) if (conf2.getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING)
depth2 = conf2.getDepthInBlocks(); depth2 = conf2.getDepthInBlocks();
BigInteger aValue = a.getValue(); Coin aValue = a.getValue();
BigInteger bValue = b.getValue(); Coin bValue = b.getValue();
BigInteger aCoinDepth = aValue.multiply(BigInteger.valueOf(depth1)); BigInteger aCoinDepth = aValue.toBigInteger().multiply(BigInteger.valueOf(depth1));
BigInteger bCoinDepth = bValue.multiply(BigInteger.valueOf(depth2)); BigInteger bCoinDepth = bValue.toBigInteger().multiply(BigInteger.valueOf(depth2));
int c1 = bCoinDepth.compareTo(aCoinDepth); int c1 = bCoinDepth.compareTo(aCoinDepth);
if (c1 != 0) return c1; if (c1 != 0) return c1;
// The "coin*days" destroyed are equal, sort by value alone to get the lowest transaction size. // The "coin*days" destroyed are equal, sort by value alone to get the lowest transaction size.

View File

@ -17,6 +17,7 @@
package com.google.bitcoin.wallet; package com.google.bitcoin.wallet;
import com.google.bitcoin.core.Coin;
import com.google.bitcoin.core.NetworkParameters; import com.google.bitcoin.core.NetworkParameters;
import com.google.bitcoin.core.Transaction; import com.google.bitcoin.core.Transaction;
import com.google.bitcoin.core.TransactionConfidence; import com.google.bitcoin.core.TransactionConfidence;
@ -24,13 +25,11 @@ import com.google.bitcoin.core.TransactionInput;
import com.google.bitcoin.core.TransactionOutput; import com.google.bitcoin.core.TransactionOutput;
import com.google.bitcoin.core.Wallet; import com.google.bitcoin.core.Wallet;
import com.google.bitcoin.script.ScriptChunk; import com.google.bitcoin.script.ScriptChunk;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.math.BigInteger;
import java.util.List; import java.util.List;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
@ -48,7 +47,7 @@ public class DefaultRiskAnalysis implements RiskAnalysis {
* rejected by the network. Currently it's 546 satoshis. This is different from {@link Transaction#MIN_NONDUST_OUTPUT} * rejected by the network. Currently it's 546 satoshis. This is different from {@link Transaction#MIN_NONDUST_OUTPUT}
* because of an upcoming fee change in Bitcoin Core 0.9. * because of an upcoming fee change in Bitcoin Core 0.9.
*/ */
public static final BigInteger MIN_ANALYSIS_NONDUST_OUTPUT = BigInteger.valueOf(546); public static final Coin MIN_ANALYSIS_NONDUST_OUTPUT = Coin.valueOf(546);
protected final Transaction tx; protected final Transaction tx;
protected final List<Transaction> dependencies; protected final List<Transaction> dependencies;

View File

@ -22,7 +22,6 @@ import com.google.common.collect.Lists;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.math.BigInteger;
import java.util.LinkedList; import java.util.LinkedList;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -48,10 +47,10 @@ public class KeyTimeCoinSelector implements CoinSelector {
} }
@Override @Override
public CoinSelection select(BigInteger target, LinkedList<TransactionOutput> candidates) { public CoinSelection select(Coin target, LinkedList<TransactionOutput> candidates) {
try { try {
LinkedList<TransactionOutput> gathered = Lists.newLinkedList(); LinkedList<TransactionOutput> gathered = Lists.newLinkedList();
BigInteger valueGathered = BigInteger.ZERO; Coin valueGathered = Coin.ZERO;
for (TransactionOutput output : candidates) { for (TransactionOutput output : candidates) {
if (ignorePending && !isConfirmed(output)) if (ignorePending && !isConfirmed(output))
continue; continue;

View File

@ -5978,7 +5978,7 @@ public final class Protos {
internal_static_payments_Output_fieldAccessorTable = new internal_static_payments_Output_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable( com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_payments_Output_descriptor, internal_static_payments_Output_descriptor,
new java.lang.String[] { "Amount", "Script", }); new java.lang.String[] { "Coin", "Script", });
internal_static_payments_PaymentDetails_descriptor = internal_static_payments_PaymentDetails_descriptor =
getDescriptor().getMessageTypes().get(1); getDescriptor().getMessageTypes().get(1);
internal_static_payments_PaymentDetails_fieldAccessorTable = new internal_static_payments_PaymentDetails_fieldAccessorTable = new

View File

@ -65,7 +65,7 @@ public class BlockChainTest {
public void setUp() throws Exception { public void setUp() throws Exception {
BriefLogFormatter.initVerbose(); BriefLogFormatter.initVerbose();
testNetChain = new BlockChain(testNet, new Wallet(testNet), new MemoryBlockStore(testNet)); testNetChain = new BlockChain(testNet, new Wallet(testNet), new MemoryBlockStore(testNet));
Wallet.SendRequest.DEFAULT_FEE_PER_KB = BigInteger.ZERO; Wallet.SendRequest.DEFAULT_FEE_PER_KB = Coin.ZERO;
unitTestParams = UnitTestParams.get(); unitTestParams = UnitTestParams.get();
wallet = new Wallet(unitTestParams) { wallet = new Wallet(unitTestParams) {
@ -278,7 +278,7 @@ public class BlockChainTest {
b1.addTransaction(t2); b1.addTransaction(t2);
b1.solve(); b1.solve();
chain.add(b1); chain.add(b1);
assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(Coin.ZERO, wallet.getBalance());
} }
@Test @Test
@ -300,7 +300,7 @@ public class BlockChainTest {
assertNotNull(coinbaseTransaction); assertNotNull(coinbaseTransaction);
// The coinbase tx is not yet available to spend. // The coinbase tx is not yet available to spend.
assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(Coin.ZERO, wallet.getBalance());
assertEquals(wallet.getBalance(BalanceType.ESTIMATED), Utils.toNanoCoins(50, 0)); assertEquals(wallet.getBalance(BalanceType.ESTIMATED), Utils.toNanoCoins(50, 0));
assertTrue(!coinbaseTransaction.isMature()); assertTrue(!coinbaseTransaction.isMature());
@ -321,7 +321,7 @@ public class BlockChainTest {
chain.add(b2); chain.add(b2);
// Wallet still does not have the coinbase transaction available for spend. // Wallet still does not have the coinbase transaction available for spend.
assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(Coin.ZERO, wallet.getBalance());
assertEquals(wallet.getBalance(BalanceType.ESTIMATED), Utils.toNanoCoins(50, 0)); assertEquals(wallet.getBalance(BalanceType.ESTIMATED), Utils.toNanoCoins(50, 0));
// The coinbase transaction is still not mature. // The coinbase transaction is still not mature.

View File

@ -164,7 +164,7 @@ public class BlockTest {
//assertTrue(tx.length == tx.bitcoinSerialize().length && tx.length == 8); //assertTrue(tx.length == tx.bitcoinSerialize().length && tx.length == 8);
byte[] outputScript = new byte[10]; byte[] outputScript = new byte[10];
Arrays.fill(outputScript, (byte) ScriptOpCodes.OP_FALSE); Arrays.fill(outputScript, (byte) ScriptOpCodes.OP_FALSE);
tx.addOutput(new TransactionOutput(params, null, BigInteger.valueOf(1), outputScript)); tx.addOutput(new TransactionOutput(params, null, Coin.valueOf(1), outputScript));
tx.addInput(new TransactionInput(params, null, new byte[] {(byte) ScriptOpCodes.OP_FALSE}, tx.addInput(new TransactionInput(params, null, new byte[] {(byte) ScriptOpCodes.OP_FALSE},
new TransactionOutPoint(params, 0, Sha256Hash.create(new byte[] {1})))); new TransactionOutPoint(params, 0, Sha256Hash.create(new byte[] {1}))));
int origTxLength = 8 + 2 + 8 + 1 + 10 + 40 + 1 + 1; int origTxLength = 8 + 2 + 8 + 1 + 10 + 40 + 1 + 1;

View File

@ -22,6 +22,7 @@ import com.google.bitcoin.store.MemoryBlockStore;
import com.google.bitcoin.testing.FakeTxBuilder; import com.google.bitcoin.testing.FakeTxBuilder;
import com.google.bitcoin.utils.BriefLogFormatter; import com.google.bitcoin.utils.BriefLogFormatter;
import com.google.bitcoin.utils.Threading; import com.google.bitcoin.utils.Threading;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -53,7 +54,7 @@ public class ChainSplitTest {
public void setUp() throws Exception { public void setUp() throws Exception {
BriefLogFormatter.init(); BriefLogFormatter.init();
Utils.setMockClock(); // Use mock clock Utils.setMockClock(); // Use mock clock
Wallet.SendRequest.DEFAULT_FEE_PER_KB = BigInteger.ZERO; Wallet.SendRequest.DEFAULT_FEE_PER_KB = Coin.ZERO;
unitTestParams = UnitTestParams.get(); unitTestParams = UnitTestParams.get();
wallet = new Wallet(unitTestParams); wallet = new Wallet(unitTestParams);
ECKey key1 = wallet.freshReceiveKey(); ECKey key1 = wallet.freshReceiveKey();
@ -164,11 +165,11 @@ public class ChainSplitTest {
assertTrue(chain.add(b2)); assertTrue(chain.add(b2));
// genesis -> b1 -> b2 // genesis -> b1 -> b2
// \-> b3 -> b4 // \-> b3 -> b4
assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(Coin.ZERO, wallet.getBalance());
Block b3 = b1.createNextBlock(coinsTo); Block b3 = b1.createNextBlock(coinsTo);
Block b4 = b3.createNextBlock(someOtherGuy); Block b4 = b3.createNextBlock(someOtherGuy);
assertTrue(chain.add(b3)); assertTrue(chain.add(b3));
assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(Coin.ZERO, wallet.getBalance());
assertTrue(chain.add(b4)); assertTrue(chain.add(b4));
assertEquals("50.00", Utils.bitcoinValueToFriendlyString(wallet.getBalance())); assertEquals("50.00", Utils.bitcoinValueToFriendlyString(wallet.getBalance()));
} }
@ -183,7 +184,7 @@ public class ChainSplitTest {
Transaction spend = wallet.createSend(dest, Utils.toNanoCoins(10, 0)); Transaction spend = wallet.createSend(dest, Utils.toNanoCoins(10, 0));
wallet.commitTx(spend); wallet.commitTx(spend);
// Waiting for confirmation ... make it eligible for selection. // Waiting for confirmation ... make it eligible for selection.
assertEquals(BigInteger.ZERO, wallet.getBalance()); 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[]{1, 2, 3, 4})));
spend.getConfidence().markBroadcastBy(new PeerAddress(InetAddress.getByAddress(new byte[]{5,6,7,8}))); spend.getConfidence().markBroadcastBy(new PeerAddress(InetAddress.getByAddress(new byte[]{5,6,7,8})));
assertEquals(ConfidenceType.PENDING, spend.getConfidence().getConfidenceType()); assertEquals(ConfidenceType.PENDING, spend.getConfidence().getConfidenceType());
@ -276,7 +277,7 @@ public class ChainSplitTest {
// -> b2 // -> b2
Block b2 = unitTestParams.getGenesisBlock().createNextBlock(coinsTo); Block b2 = unitTestParams.getGenesisBlock().createNextBlock(coinsTo);
chain.add(b2); chain.add(b2);
assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(Coin.ZERO, wallet.getBalance());
// genesis -> b1 -> b3 // genesis -> b1 -> b3
// -> b2 // -> b2
Block b3 = b1.createNextBlock(someOtherGuy); Block b3 = b1.createNextBlock(someOtherGuy);
@ -399,7 +400,7 @@ public class ChainSplitTest {
final ArrayList<Transaction> txns = new ArrayList<Transaction>(3); final ArrayList<Transaction> txns = new ArrayList<Transaction>(3);
wallet.addEventListener(new AbstractWalletEventListener() { wallet.addEventListener(new AbstractWalletEventListener() {
@Override @Override
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
txns.add(tx); txns.add(tx);
} }
}); });
@ -552,7 +553,7 @@ public class ChainSplitTest {
wallet.commitTx(t3); wallet.commitTx(t3);
chain.add(FakeTxBuilder.makeSolvedTestBlock(b1, t2, t3)); chain.add(FakeTxBuilder.makeSolvedTestBlock(b1, t2, t3));
final BigInteger coins0point98 = Utils.COIN.subtract(Utils.CENT).subtract(Utils.CENT); final Coin coins0point98 = Utils.COIN.subtract(Utils.CENT).subtract(Utils.CENT);
assertEquals(coins0point98, wallet.getBalance()); assertEquals(coins0point98, wallet.getBalance());
// Now round trip the wallet and force a re-org. // Now round trip the wallet and force a re-org.
@ -577,7 +578,7 @@ public class ChainSplitTest {
final ArrayList<Transaction> txns = new ArrayList<Transaction>(3); final ArrayList<Transaction> txns = new ArrayList<Transaction>(3);
wallet.addEventListener(new AbstractWalletEventListener() { wallet.addEventListener(new AbstractWalletEventListener() {
@Override @Override
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
txns.add(tx); txns.add(tx);
} }
}, Threading.SAME_THREAD); }, Threading.SAME_THREAD);

View File

@ -42,7 +42,7 @@ public class CoinbaseBlockTest {
private static final int BLOCK_OF_INTEREST = 169482; private static final int BLOCK_OF_INTEREST = 169482;
private static final int BLOCK_LENGTH_AS_HEX = 37357; private static final int BLOCK_LENGTH_AS_HEX = 37357;
private static final long BLOCK_NONCE = 3973947400L; private static final long BLOCK_NONCE = 3973947400L;
private static final BigInteger BALANCE_AFTER_BLOCK = BigInteger.valueOf(22223642); private static final Coin BALANCE_AFTER_BLOCK = Coin.valueOf(22223642);
@Test @Test
public void testReceiveCoinbaseTransaction() throws Exception { public void testReceiveCoinbaseTransaction() throws Exception {
@ -70,7 +70,7 @@ public class CoinbaseBlockTest {
wallet.importKey(miningKey); wallet.importKey(miningKey);
// Initial balance should be zero by construction. // Initial balance should be zero by construction.
assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(Coin.ZERO, wallet.getBalance());
// Give the wallet the first transaction in the block - this is the coinbase tx. // Give the wallet the first transaction in the block - this is the coinbase tx.
List<Transaction> transactions = block.getTransactions(); List<Transaction> transactions = block.getTransactions();
@ -79,7 +79,7 @@ public class CoinbaseBlockTest {
// Coinbase transaction should have been received successfully but be unavailable to spend (too young). // Coinbase transaction should have been received successfully but be unavailable to spend (too young).
assertEquals(BALANCE_AFTER_BLOCK, wallet.getBalance(BalanceType.ESTIMATED)); assertEquals(BALANCE_AFTER_BLOCK, wallet.getBalance(BalanceType.ESTIMATED));
assertEquals(BigInteger.ZERO, wallet.getBalance(BalanceType.AVAILABLE)); assertEquals(Coin.ZERO, wallet.getBalance(BalanceType.AVAILABLE));
} }
/** /**

View File

@ -65,9 +65,9 @@ class Rule {
class TransactionOutPointWithValue { class TransactionOutPointWithValue {
public TransactionOutPoint outpoint; public TransactionOutPoint outpoint;
public BigInteger value; public Coin value;
Script scriptPubKey; Script scriptPubKey;
public TransactionOutPointWithValue(TransactionOutPoint outpoint, BigInteger value, Script scriptPubKey) { public TransactionOutPointWithValue(TransactionOutPoint outpoint, Coin value, Script scriptPubKey) {
this.outpoint = outpoint; this.outpoint = outpoint;
this.value = value; this.value = value;
this.scriptPubKey = scriptPubKey; this.scriptPubKey = scriptPubKey;
@ -217,7 +217,7 @@ public class FullBlockTestGenerator {
// \-> b9 (4) // \-> b9 (4)
// \-> b3 (1) -> b4 (2) // \-> b3 (1) -> b4 (2)
// //
Block b9 = createNextBlock(b6, chainHeadHeight + 5, out4, BigInteger.valueOf(1)); Block b9 = createNextBlock(b6, chainHeadHeight + 5, out4, Coin.valueOf(1));
blocks.add(new BlockAndValidity(blockToHeightMap, b9, false, true, b6.getHash(), chainHeadHeight + 4, "b9")); blocks.add(new BlockAndValidity(blockToHeightMap, 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) // Create a fork that ends in a block with too much fee (the one that causes the reorg)
@ -228,7 +228,7 @@ public class FullBlockTestGenerator {
Block b10 = createNextBlock(b5, chainHeadHeight + 4, out3, null); Block b10 = createNextBlock(b5, chainHeadHeight + 4, out3, null);
blocks.add(new BlockAndValidity(blockToHeightMap, b10, true, false, b6.getHash(), chainHeadHeight + 4, "b10")); blocks.add(new BlockAndValidity(blockToHeightMap, b10, true, false, b6.getHash(), chainHeadHeight + 4, "b10"));
Block b11 = createNextBlock(b10, chainHeadHeight + 5, out4, BigInteger.valueOf(1)); Block b11 = createNextBlock(b10, chainHeadHeight + 5, out4, Coin.valueOf(1));
blocks.add(new BlockAndValidity(blockToHeightMap, b11, false, true, b6.getHash(), chainHeadHeight + 4, "b11")); blocks.add(new BlockAndValidity(blockToHeightMap, b11, false, true, b6.getHash(), chainHeadHeight + 4, "b11"));
// Try again, but with a valid fork first // Try again, but with a valid fork first
@ -254,7 +254,7 @@ public class FullBlockTestGenerator {
TransactionOutPointWithValue out5 = spendableOutputs.poll(); TransactionOutPointWithValue out5 = spendableOutputs.poll();
Block b14 = createNextBlock(b13, chainHeadHeight + 6, out5, BigInteger.valueOf(1)); Block b14 = createNextBlock(b13, chainHeadHeight + 6, out5, Coin.valueOf(1));
// This will be "validly" added, though its actually invalid, it will just be marked orphan // 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. // 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 // TODO: Use a WeakReference to check that it is freed properly after the reorg
@ -278,10 +278,10 @@ public class FullBlockTestGenerator {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
byte[] outputScript = new byte[Block.MAX_BLOCK_SIGOPS - sigOps]; byte[] outputScript = new byte[Block.MAX_BLOCK_SIGOPS - sigOps];
Arrays.fill(outputScript, (byte) OP_CHECKSIG); Arrays.fill(outputScript, (byte) OP_CHECKSIG);
tx.addOutput(new TransactionOutput(params, tx, BigInteger.valueOf(1), outputScript)); tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(1), outputScript));
addOnlyInputToTransaction(tx, new TransactionOutPointWithValue( addOnlyInputToTransaction(tx, new TransactionOutPointWithValue(
new TransactionOutPoint(params, 1, b15.getTransactions().get(1).getHash()), new TransactionOutPoint(params, 1, b15.getTransactions().get(1).getHash()),
BigInteger.valueOf(1), b15.getTransactions().get(1).getOutputs().get(1).getScriptPubKey())); Coin.valueOf(1), b15.getTransactions().get(1).getOutputs().get(1).getScriptPubKey()));
b15.addTransaction(tx); b15.addTransaction(tx);
} }
b15.solve(); b15.solve();
@ -303,10 +303,10 @@ public class FullBlockTestGenerator {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
byte[] outputScript = new byte[Block.MAX_BLOCK_SIGOPS - sigOps + 1]; byte[] outputScript = new byte[Block.MAX_BLOCK_SIGOPS - sigOps + 1];
Arrays.fill(outputScript, (byte) OP_CHECKSIG); Arrays.fill(outputScript, (byte) OP_CHECKSIG);
tx.addOutput(new TransactionOutput(params, tx, BigInteger.valueOf(1), outputScript)); tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(1), outputScript));
addOnlyInputToTransaction(tx, new TransactionOutPointWithValue( addOnlyInputToTransaction(tx, new TransactionOutPointWithValue(
new TransactionOutPoint(params, 1, b16.getTransactions().get(1).getHash()), new TransactionOutPoint(params, 1, b16.getTransactions().get(1).getHash()),
BigInteger.valueOf(1), b16.getTransactions().get(1).getOutputs().get(1).getScriptPubKey())); Coin.valueOf(1), b16.getTransactions().get(1).getOutputs().get(1).getScriptPubKey()));
b16.addTransaction(tx); b16.addTransaction(tx);
} }
b16.solve(); b16.solve();
@ -321,10 +321,10 @@ public class FullBlockTestGenerator {
Block b17 = createNextBlock(b15, chainHeadHeight + 7, out6, null); Block b17 = createNextBlock(b15, chainHeadHeight + 7, out6, null);
{ {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
tx.addOutput(new TransactionOutput(params, tx, BigInteger.valueOf(1), new byte[] {})); tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(1), new byte[] {}));
addOnlyInputToTransaction(tx, new TransactionOutPointWithValue( addOnlyInputToTransaction(tx, new TransactionOutPointWithValue(
new TransactionOutPoint(params, 1, b3.getTransactions().get(1).getHash()), new TransactionOutPoint(params, 1, b3.getTransactions().get(1).getHash()),
BigInteger.valueOf(1), b3.getTransactions().get(1).getOutputs().get(1).getScriptPubKey())); Coin.valueOf(1), b3.getTransactions().get(1).getOutputs().get(1).getScriptPubKey()));
b17.addTransaction(tx); b17.addTransaction(tx);
} }
b17.solve(); b17.solve();
@ -339,10 +339,10 @@ public class FullBlockTestGenerator {
Block b18 = createNextBlock(b13, chainHeadHeight + 6, out5, null); Block b18 = createNextBlock(b13, chainHeadHeight + 6, out5, null);
{ {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
tx.addOutput(new TransactionOutput(params, tx, BigInteger.valueOf(1), new byte[] {})); tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(1), new byte[] {}));
addOnlyInputToTransaction(tx, new TransactionOutPointWithValue( addOnlyInputToTransaction(tx, new TransactionOutPointWithValue(
new TransactionOutPoint(params, 1, b3.getTransactions().get(1).getHash()), new TransactionOutPoint(params, 1, b3.getTransactions().get(1).getHash()),
BigInteger.valueOf(1), b3.getTransactions().get(1).getOutputs().get(1).getScriptPubKey())); Coin.valueOf(1), b3.getTransactions().get(1).getOutputs().get(1).getScriptPubKey()));
b18.addTransaction(tx); b18.addTransaction(tx);
} }
b18.solve(); b18.solve();
@ -384,10 +384,10 @@ public class FullBlockTestGenerator {
// Signature size is non-deterministic, so it may take several runs before finding any off-by-one errors // Signature size is non-deterministic, so it may take several runs before finding any off-by-one errors
byte[] outputScript = new byte[Block.MAX_BLOCK_SIZE - b23.getMessageSize() - 138]; byte[] outputScript = new byte[Block.MAX_BLOCK_SIZE - b23.getMessageSize() - 138];
Arrays.fill(outputScript, (byte) OP_FALSE); Arrays.fill(outputScript, (byte) OP_FALSE);
tx.addOutput(new TransactionOutput(params, tx, BigInteger.valueOf(1), outputScript)); tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(1), outputScript));
addOnlyInputToTransaction(tx, new TransactionOutPointWithValue( addOnlyInputToTransaction(tx, new TransactionOutPointWithValue(
new TransactionOutPoint(params, 1, b23.getTransactions().get(1).getHash()), new TransactionOutPoint(params, 1, b23.getTransactions().get(1).getHash()),
BigInteger.valueOf(1), b23.getTransactions().get(1).getOutputs().get(1).getScriptPubKey())); Coin.valueOf(1), b23.getTransactions().get(1).getOutputs().get(1).getScriptPubKey()));
b23.addTransaction(tx); b23.addTransaction(tx);
} }
b23.solve(); b23.solve();
@ -403,10 +403,10 @@ public class FullBlockTestGenerator {
// Signature size is non-deterministic, so it may take several runs before finding any off-by-one errors // Signature size is non-deterministic, so it may take several runs before finding any off-by-one errors
byte[] outputScript = new byte[Block.MAX_BLOCK_SIZE - b24.getMessageSize() - 135]; byte[] outputScript = new byte[Block.MAX_BLOCK_SIZE - b24.getMessageSize() - 135];
Arrays.fill(outputScript, (byte) OP_FALSE); Arrays.fill(outputScript, (byte) OP_FALSE);
tx.addOutput(new TransactionOutput(params, tx, BigInteger.valueOf(1), outputScript)); tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(1), outputScript));
addOnlyInputToTransaction(tx, new TransactionOutPointWithValue( addOnlyInputToTransaction(tx, new TransactionOutPointWithValue(
new TransactionOutPoint(params, 1, b24.getTransactions().get(1).getHash()), new TransactionOutPoint(params, 1, b24.getTransactions().get(1).getHash()),
BigInteger.valueOf(1), b24.getTransactions().get(1).getOutputs().get(1).getScriptPubKey())); Coin.valueOf(1), b24.getTransactions().get(1).getOutputs().get(1).getScriptPubKey()));
b24.addTransaction(tx); b24.addTransaction(tx);
} }
b24.solve(); b24.solve();
@ -479,10 +479,10 @@ public class FullBlockTestGenerator {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
byte[] outputScript = new byte[(Block.MAX_BLOCK_SIGOPS - sigOps)/20]; byte[] outputScript = new byte[(Block.MAX_BLOCK_SIGOPS - sigOps)/20];
Arrays.fill(outputScript, (byte) OP_CHECKMULTISIG); Arrays.fill(outputScript, (byte) OP_CHECKMULTISIG);
tx.addOutput(new TransactionOutput(params, tx, BigInteger.valueOf(1), outputScript)); tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(1), outputScript));
addOnlyInputToTransaction(tx, new TransactionOutPointWithValue( addOnlyInputToTransaction(tx, new TransactionOutPointWithValue(
new TransactionOutPoint(params, 1, b31.getTransactions().get(1).getHash()), new TransactionOutPoint(params, 1, b31.getTransactions().get(1).getHash()),
BigInteger.valueOf(1), b31.getTransactions().get(1).getOutputs().get(1).getScriptPubKey())); Coin.valueOf(1), b31.getTransactions().get(1).getOutputs().get(1).getScriptPubKey()));
b31.addTransaction(tx); b31.addTransaction(tx);
} }
b31.solve(); b31.solve();
@ -506,10 +506,10 @@ public class FullBlockTestGenerator {
Arrays.fill(outputScript, (byte) OP_CHECKMULTISIG); Arrays.fill(outputScript, (byte) OP_CHECKMULTISIG);
for (int i = 0; i < (Block.MAX_BLOCK_SIGOPS - sigOps)%20; i++) for (int i = 0; i < (Block.MAX_BLOCK_SIGOPS - sigOps)%20; i++)
outputScript[i] = (byte) OP_CHECKSIG; outputScript[i] = (byte) OP_CHECKSIG;
tx.addOutput(new TransactionOutput(params, tx, BigInteger.valueOf(1), outputScript)); tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(1), outputScript));
addOnlyInputToTransaction(tx, new TransactionOutPointWithValue( addOnlyInputToTransaction(tx, new TransactionOutPointWithValue(
new TransactionOutPoint(params, 1, b32.getTransactions().get(1).getHash()), new TransactionOutPoint(params, 1, b32.getTransactions().get(1).getHash()),
BigInteger.valueOf(1), b32.getTransactions().get(1).getOutputs().get(1).getScriptPubKey())); Coin.valueOf(1), b32.getTransactions().get(1).getOutputs().get(1).getScriptPubKey()));
b32.addTransaction(tx); b32.addTransaction(tx);
} }
b32.solve(); b32.solve();
@ -526,10 +526,10 @@ public class FullBlockTestGenerator {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
byte[] outputScript = new byte[(Block.MAX_BLOCK_SIGOPS - sigOps)/20]; byte[] outputScript = new byte[(Block.MAX_BLOCK_SIGOPS - sigOps)/20];
Arrays.fill(outputScript, (byte) OP_CHECKMULTISIGVERIFY); Arrays.fill(outputScript, (byte) OP_CHECKMULTISIGVERIFY);
tx.addOutput(new TransactionOutput(params, tx, BigInteger.valueOf(1), outputScript)); tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(1), outputScript));
addOnlyInputToTransaction(tx, new TransactionOutPointWithValue( addOnlyInputToTransaction(tx, new TransactionOutPointWithValue(
new TransactionOutPoint(params, 1, b33.getTransactions().get(1).getHash()), new TransactionOutPoint(params, 1, b33.getTransactions().get(1).getHash()),
BigInteger.valueOf(1), b33.getTransactions().get(1).getOutputs().get(1).getScriptPubKey())); Coin.valueOf(1), b33.getTransactions().get(1).getOutputs().get(1).getScriptPubKey()));
b33.addTransaction(tx); b33.addTransaction(tx);
} }
b33.solve(); b33.solve();
@ -553,10 +553,10 @@ public class FullBlockTestGenerator {
Arrays.fill(outputScript, (byte) OP_CHECKMULTISIGVERIFY); Arrays.fill(outputScript, (byte) OP_CHECKMULTISIGVERIFY);
for (int i = 0; i < (Block.MAX_BLOCK_SIGOPS - sigOps)%20; i++) for (int i = 0; i < (Block.MAX_BLOCK_SIGOPS - sigOps)%20; i++)
outputScript[i] = (byte) OP_CHECKSIG; outputScript[i] = (byte) OP_CHECKSIG;
tx.addOutput(new TransactionOutput(params, tx, BigInteger.valueOf(1), outputScript)); tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(1), outputScript));
addOnlyInputToTransaction(tx, new TransactionOutPointWithValue( addOnlyInputToTransaction(tx, new TransactionOutPointWithValue(
new TransactionOutPoint(params, 1, b34.getTransactions().get(1).getHash()), new TransactionOutPoint(params, 1, b34.getTransactions().get(1).getHash()),
BigInteger.valueOf(1), b34.getTransactions().get(1).getOutputs().get(1).getScriptPubKey())); Coin.valueOf(1), b34.getTransactions().get(1).getOutputs().get(1).getScriptPubKey()));
b34.addTransaction(tx); b34.addTransaction(tx);
} }
b34.solve(); b34.solve();
@ -573,10 +573,10 @@ public class FullBlockTestGenerator {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
byte[] outputScript = new byte[Block.MAX_BLOCK_SIGOPS - sigOps]; byte[] outputScript = new byte[Block.MAX_BLOCK_SIGOPS - sigOps];
Arrays.fill(outputScript, (byte) OP_CHECKSIGVERIFY); Arrays.fill(outputScript, (byte) OP_CHECKSIGVERIFY);
tx.addOutput(new TransactionOutput(params, tx, BigInteger.valueOf(1), outputScript)); tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(1), outputScript));
addOnlyInputToTransaction(tx, new TransactionOutPointWithValue( addOnlyInputToTransaction(tx, new TransactionOutPointWithValue(
new TransactionOutPoint(params, 1, b35.getTransactions().get(1).getHash()), new TransactionOutPoint(params, 1, b35.getTransactions().get(1).getHash()),
BigInteger.valueOf(1), b35.getTransactions().get(1).getOutputs().get(1).getScriptPubKey())); Coin.valueOf(1), b35.getTransactions().get(1).getOutputs().get(1).getScriptPubKey()));
b35.addTransaction(tx); b35.addTransaction(tx);
} }
b35.solve(); b35.solve();
@ -598,10 +598,10 @@ public class FullBlockTestGenerator {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
byte[] outputScript = new byte[Block.MAX_BLOCK_SIGOPS - sigOps + 1]; byte[] outputScript = new byte[Block.MAX_BLOCK_SIGOPS - sigOps + 1];
Arrays.fill(outputScript, (byte) OP_CHECKSIGVERIFY); Arrays.fill(outputScript, (byte) OP_CHECKSIGVERIFY);
tx.addOutput(new TransactionOutput(params, tx, BigInteger.valueOf(1), outputScript)); tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(1), outputScript));
addOnlyInputToTransaction(tx, new TransactionOutPointWithValue( addOnlyInputToTransaction(tx, new TransactionOutPointWithValue(
new TransactionOutPoint(params, 1, b36.getTransactions().get(1).getHash()), new TransactionOutPoint(params, 1, b36.getTransactions().get(1).getHash()),
BigInteger.valueOf(1), b36.getTransactions().get(1).getOutputs().get(1).getScriptPubKey())); Coin.valueOf(1), b36.getTransactions().get(1).getOutputs().get(1).getScriptPubKey()));
b36.addTransaction(tx); b36.addTransaction(tx);
} }
b36.solve(); b36.solve();
@ -618,7 +618,7 @@ public class FullBlockTestGenerator {
Block b37 = createNextBlock(b35, chainHeadHeight + 12, out11, null); Block b37 = createNextBlock(b35, chainHeadHeight + 12, out11, null);
{ {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
tx.addOutput(new TransactionOutput(params, tx, BigInteger.valueOf(1), new byte[] {})); tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(1), new byte[] {}));
addOnlyInputToTransaction(tx, out11); // double spend out11 addOnlyInputToTransaction(tx, out11); // double spend out11
b37.addTransaction(tx); b37.addTransaction(tx);
} }
@ -628,11 +628,11 @@ public class FullBlockTestGenerator {
Block b38 = createNextBlock(b35, chainHeadHeight + 12, out11, null); Block b38 = createNextBlock(b35, chainHeadHeight + 12, out11, null);
{ {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
tx.addOutput(new TransactionOutput(params, tx, BigInteger.valueOf(1), new byte[] {})); tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(1), new byte[] {}));
// Attempt to spend b37's first non-coinbase tx, at which point b37 was still considered valid // Attempt to spend b37's first non-coinbase tx, at which point b37 was still considered valid
addOnlyInputToTransaction(tx, new TransactionOutPointWithValue( addOnlyInputToTransaction(tx, new TransactionOutPointWithValue(
new TransactionOutPoint(params, 1, b37.getTransactions().get(1).getHash()), new TransactionOutPoint(params, 1, b37.getTransactions().get(1).getHash()),
BigInteger.valueOf(1), b37.getTransactions().get(1).getOutputs().get(1).getScriptPubKey())); Coin.valueOf(1), b37.getTransactions().get(1).getOutputs().get(1).getScriptPubKey()));
b38.addTransaction(tx); b38.addTransaction(tx);
} }
b38.solve(); b38.solve();
@ -676,11 +676,11 @@ public class FullBlockTestGenerator {
} }
scriptPubKey.write(OP_EQUAL); scriptPubKey.write(OP_EQUAL);
BigInteger lastOutputValue = out11.value.subtract(BigInteger.valueOf(1)); Coin lastOutputValue = out11.value.subtract(Coin.valueOf(1));
TransactionOutPoint lastOutPoint; TransactionOutPoint lastOutPoint;
{ {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
tx.addOutput(new TransactionOutput(params, tx, BigInteger.valueOf(1), scriptPubKey.toByteArray())); tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(1), scriptPubKey.toByteArray()));
tx.addOutput(new TransactionOutput(params, tx, lastOutputValue, new byte[]{OP_1})); tx.addOutput(new TransactionOutput(params, tx, lastOutputValue, new byte[]{OP_1}));
addOnlyInputToTransaction(tx, out11); addOnlyInputToTransaction(tx, out11);
lastOutPoint = new TransactionOutPoint(params, 1, tx.getHash()); lastOutPoint = new TransactionOutPoint(params, 1, tx.getHash());
@ -692,8 +692,8 @@ public class FullBlockTestGenerator {
{ {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
lastOutputValue = lastOutputValue.subtract(BigInteger.valueOf(1)); lastOutputValue = lastOutputValue.subtract(Coin.valueOf(1));
tx.addOutput(new TransactionOutput(params, tx, BigInteger.valueOf(1), scriptPubKey.toByteArray())); tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(1), scriptPubKey.toByteArray()));
tx.addOutput(new TransactionOutput(params, tx, lastOutputValue, new byte[]{OP_1})); tx.addOutput(new TransactionOutput(params, tx, lastOutputValue, new byte[]{OP_1}));
tx.addInput(new TransactionInput(params, tx, new byte[]{OP_1}, lastOutPoint)); tx.addInput(new TransactionInput(params, tx, new byte[]{OP_1}, lastOutPoint));
lastOutPoint = new TransactionOutPoint(params, 1, tx.getHash()); lastOutPoint = new TransactionOutPoint(params, 1, tx.getHash());
@ -729,7 +729,7 @@ public class FullBlockTestGenerator {
byte[] scriptSig = null; byte[] scriptSig = null;
for (int i = 1; i <= numTxes; i++) { for (int i = 1; i <= numTxes; i++) {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
tx.addOutput(new TransactionOutput(params, tx, BigInteger.valueOf(1), new byte[] {OP_1})); tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(1), new byte[] {OP_1}));
tx.addInput(new TransactionInput(params, tx, new byte[]{OP_1}, lastOutPoint)); tx.addInput(new TransactionInput(params, tx, new byte[]{OP_1}, lastOutPoint));
TransactionInput input = new TransactionInput(params, tx, new byte[]{}, TransactionInput input = new TransactionInput(params, tx, new byte[]{},
@ -770,7 +770,7 @@ public class FullBlockTestGenerator {
tx.addInput(new TransactionInput(params, tx, new byte[]{OP_1}, lastOutPoint)); tx.addInput(new TransactionInput(params, tx, new byte[]{OP_1}, lastOutPoint));
byte[] scriptPubKey = new byte[Block.MAX_BLOCK_SIGOPS - sigOps + 1]; byte[] scriptPubKey = new byte[Block.MAX_BLOCK_SIGOPS - sigOps + 1];
Arrays.fill(scriptPubKey, (byte) OP_CHECKSIG); Arrays.fill(scriptPubKey, (byte) OP_CHECKSIG);
tx.addOutput(new TransactionOutput(params, tx, BigInteger.ZERO, scriptPubKey)); tx.addOutput(new TransactionOutput(params, tx, Coin.ZERO, scriptPubKey));
b40.addTransaction(tx); b40.addTransaction(tx);
} }
b40.solve(); b40.solve();
@ -795,7 +795,7 @@ public class FullBlockTestGenerator {
byte[] scriptSig = null; byte[] scriptSig = null;
for (int i = 1; i <= numTxes; i++) { for (int i = 1; i <= numTxes; i++) {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
tx.addOutput(new TransactionOutput(params, tx, BigInteger tx.addOutput(new TransactionOutput(params, tx, Coin
.valueOf(1), new byte[] {OP_1})); .valueOf(1), new byte[] {OP_1}));
tx.addInput(new TransactionInput(params, tx, tx.addInput(new TransactionInput(params, tx,
new byte[] {OP_1}, lastOutPoint)); new byte[] {OP_1}, lastOutPoint));
@ -847,7 +847,7 @@ public class FullBlockTestGenerator {
new byte[] {OP_1}, lastOutPoint)); new byte[] {OP_1}, lastOutPoint));
byte[] scriptPubKey = new byte[Block.MAX_BLOCK_SIGOPS - sigOps]; byte[] scriptPubKey = new byte[Block.MAX_BLOCK_SIGOPS - sigOps];
Arrays.fill(scriptPubKey, (byte) OP_CHECKSIG); Arrays.fill(scriptPubKey, (byte) OP_CHECKSIG);
tx.addOutput(new TransactionOutput(params, tx, BigInteger.ZERO, scriptPubKey)); tx.addOutput(new TransactionOutput(params, tx, Coin.ZERO, scriptPubKey));
b41.addTransaction(tx); b41.addTransaction(tx);
} }
b41.solve(); b41.solve();
@ -885,14 +885,14 @@ public class FullBlockTestGenerator {
byte[] outScriptBytes = ScriptBuilder.createOutputScript(ECKey.fromPublicOnly(coinbaseOutKeyPubKey)).getProgram(); byte[] outScriptBytes = ScriptBuilder.createOutputScript(ECKey.fromPublicOnly(coinbaseOutKeyPubKey)).getProgram();
{ {
b44.setDifficultyTarget(b43.getDifficultyTarget()); b44.setDifficultyTarget(b43.getDifficultyTarget());
b44.addCoinbaseTransaction(coinbaseOutKeyPubKey, BigInteger.ZERO); b44.addCoinbaseTransaction(coinbaseOutKeyPubKey, Coin.ZERO);
Transaction t = new Transaction(params); Transaction t = new Transaction(params);
// Entirely invalid scriptPubKey to ensure we aren't pre-verifying too much // Entirely invalid scriptPubKey to ensure we aren't pre-verifying too much
t.addOutput(new TransactionOutput(params, t, BigInteger.valueOf(0), new byte[] {OP_PUSHDATA1 - 1 })); t.addOutput(new TransactionOutput(params, t, Coin.valueOf(0), new byte[] {OP_PUSHDATA1 - 1 }));
t.addOutput(new TransactionOutput(params, t, BigInteger.valueOf(1), outScriptBytes)); t.addOutput(new TransactionOutput(params, t, Coin.valueOf(1), outScriptBytes));
// Spendable output // Spendable output
t.addOutput(new TransactionOutput(params, t, BigInteger.ZERO, new byte[] {OP_1})); t.addOutput(new TransactionOutput(params, t, Coin.ZERO, new byte[] {OP_1}));
addOnlyInputToTransaction(t, out14); addOnlyInputToTransaction(t, out14);
b44.addTransaction(t); b44.addTransaction(t);
@ -912,10 +912,10 @@ public class FullBlockTestGenerator {
Transaction t = new Transaction(params); Transaction t = new Transaction(params);
// Entirely invalid scriptPubKey to ensure we aren't pre-verifying too much // Entirely invalid scriptPubKey to ensure we aren't pre-verifying too much
t.addOutput(new TransactionOutput(params, t, BigInteger.valueOf(0), new byte[] {OP_PUSHDATA1 - 1 })); t.addOutput(new TransactionOutput(params, t, Coin.valueOf(0), new byte[] {OP_PUSHDATA1 - 1 }));
t.addOutput(new TransactionOutput(params, t, BigInteger.valueOf(1), outScriptBytes)); t.addOutput(new TransactionOutput(params, t, Coin.valueOf(1), outScriptBytes));
// Spendable output // Spendable output
t.addOutput(new TransactionOutput(params, t, BigInteger.ZERO, new byte[] {OP_1})); t.addOutput(new TransactionOutput(params, t, Coin.ZERO, new byte[] {OP_1}));
addOnlyInputToTransaction(t, out15); addOnlyInputToTransaction(t, out15);
try { try {
b45.addTransaction(t); b45.addTransaction(t);
@ -989,7 +989,7 @@ public class FullBlockTestGenerator {
{ {
Transaction coinbase = new Transaction(params); Transaction coinbase = new Transaction(params);
coinbase.addInput(new TransactionInput(params, coinbase, new byte[]{(byte) 0xff, 110, 1})); coinbase.addInput(new TransactionInput(params, coinbase, new byte[]{(byte) 0xff, 110, 1}));
coinbase.addOutput(new TransactionOutput(params, coinbase, BigInteger.ONE, outScriptBytes)); coinbase.addOutput(new TransactionOutput(params, coinbase, Coin.ONE, outScriptBytes));
b51.addTransaction(coinbase, false); b51.addTransaction(coinbase, false);
} }
b51.solve(); b51.solve();
@ -999,10 +999,10 @@ public class FullBlockTestGenerator {
Block b52 = createNextBlock(b44, chainHeadHeight + 16, out15, null); Block b52 = createNextBlock(b44, chainHeadHeight + 16, out15, null);
{ {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
tx.addOutput(new TransactionOutput(params, tx, BigInteger.valueOf(1), new byte[] {})); tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(1), new byte[] {}));
addOnlyInputToTransaction(tx, new TransactionOutPointWithValue( addOnlyInputToTransaction(tx, new TransactionOutPointWithValue(
new TransactionOutPoint(params, 1, b52.getTransactions().get(1).getHash()), new TransactionOutPoint(params, 1, b52.getTransactions().get(1).getHash()),
BigInteger.valueOf(1), b52.getTransactions().get(1).getOutputs().get(1).getScriptPubKey())); Coin.valueOf(1), b52.getTransactions().get(1).getOutputs().get(1).getScriptPubKey()));
b52.addTransaction(tx); b52.addTransaction(tx);
b52.addTransaction(tx); b52.addTransaction(tx);
} }
@ -1047,10 +1047,10 @@ public class FullBlockTestGenerator {
Transaction b56txToDuplicate; Transaction b56txToDuplicate;
{ {
b56txToDuplicate = new Transaction(params); b56txToDuplicate = new Transaction(params);
b56txToDuplicate.addOutput(new TransactionOutput(params, b56txToDuplicate, BigInteger.valueOf(1), new byte[] {})); b56txToDuplicate.addOutput(new TransactionOutput(params, b56txToDuplicate, Coin.valueOf(1), new byte[] {}));
addOnlyInputToTransaction(b56txToDuplicate, new TransactionOutPointWithValue( addOnlyInputToTransaction(b56txToDuplicate, new TransactionOutPointWithValue(
new TransactionOutPoint(params, 1, b57.getTransactions().get(1).getHash()), new TransactionOutPoint(params, 1, b57.getTransactions().get(1).getHash()),
BigInteger.valueOf(1), b57.getTransactions().get(1).getOutputs().get(1).getScriptPubKey())); Coin.valueOf(1), b57.getTransactions().get(1).getOutputs().get(1).getScriptPubKey()));
b57.addTransaction(b56txToDuplicate); b57.addTransaction(b56txToDuplicate);
} }
b57.solve(); b57.solve();
@ -1081,7 +1081,7 @@ public class FullBlockTestGenerator {
Block b58 = createNextBlock(b57, chainHeadHeight + 18, out17, null); Block b58 = createNextBlock(b57, chainHeadHeight + 18, out17, null);
{ {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
tx.addOutput(new TransactionOutput(params, tx, BigInteger.ZERO, new byte[] {})); tx.addOutput(new TransactionOutput(params, tx, Coin.ZERO, new byte[] {}));
tx.addInput(new TransactionInput(params, tx, new byte[] {OP_1}, tx.addInput(new TransactionInput(params, tx, new byte[] {OP_1},
new TransactionOutPoint(params, 3, b58.getTransactions().get(1).getHash()))); new TransactionOutPoint(params, 3, b58.getTransactions().get(1).getHash())));
b58.addTransaction(tx); b58.addTransaction(tx);
@ -1094,7 +1094,7 @@ public class FullBlockTestGenerator {
{ {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
tx.addOutput(new TransactionOutput(params, tx, tx.addOutput(new TransactionOutput(params, tx,
b59.getTransactions().get(1).getOutputs().get(2).getValue().add(BigInteger.ONE), new byte[] {})); b59.getTransactions().get(1).getOutputs().get(2).getValue().add(Coin.ONE), new byte[] {}));
tx.addInput(new TransactionInput(params, tx, new byte[] {OP_1}, tx.addInput(new TransactionInput(params, tx, new byte[] {OP_1},
new TransactionOutPoint(params, 2, b59.getTransactions().get(1).getHash()))); new TransactionOutPoint(params, 2, b59.getTransactions().get(1).getHash())));
b59.addTransaction(tx); b59.addTransaction(tx);
@ -1132,7 +1132,7 @@ public class FullBlockTestGenerator {
{ {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
tx.setLockTime(0xffffffffL); tx.setLockTime(0xffffffffL);
tx.addOutput(new TransactionOutput(params, tx, BigInteger.ZERO, new byte[] {OP_TRUE})); tx.addOutput(new TransactionOutput(params, tx, Coin.ZERO, new byte[] {OP_TRUE}));
addOnlyInputToTransaction(tx, out18, 0); addOnlyInputToTransaction(tx, out18, 0);
b62.addTransaction(tx); b62.addTransaction(tx);
Preconditions.checkState(!tx.isFinal(chainHeadHeight + 17, b62.getTimeSeconds())); Preconditions.checkState(!tx.isFinal(chainHeadHeight + 17, b62.getTimeSeconds()));
@ -1164,10 +1164,10 @@ public class FullBlockTestGenerator {
// Signature size is non-deterministic, so it may take several runs before finding any off-by-one errors // Signature size is non-deterministic, so it may take several runs before finding any off-by-one errors
byte[] outputScript = new byte[Block.MAX_BLOCK_SIZE - b64Created.getMessageSize() - 138]; byte[] outputScript = new byte[Block.MAX_BLOCK_SIZE - b64Created.getMessageSize() - 138];
Arrays.fill(outputScript, (byte) OP_FALSE); Arrays.fill(outputScript, (byte) OP_FALSE);
tx.addOutput(new TransactionOutput(params, tx, BigInteger.valueOf(1), outputScript)); tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(1), outputScript));
addOnlyInputToTransaction(tx, new TransactionOutPointWithValue( addOnlyInputToTransaction(tx, new TransactionOutPointWithValue(
new TransactionOutPoint(params, 1, b64Created.getTransactions().get(1).getHash()), new TransactionOutPoint(params, 1, b64Created.getTransactions().get(1).getHash()),
BigInteger.valueOf(1), b64Created.getTransactions().get(1).getOutputs().get(1).getScriptPubKey())); Coin.valueOf(1), b64Created.getTransactions().get(1).getOutputs().get(1).getScriptPubKey()));
b64Created.addTransaction(tx); b64Created.addTransaction(tx);
b64Created.solve(); b64Created.solve();
@ -1210,7 +1210,7 @@ public class FullBlockTestGenerator {
addOnlyInputToTransaction(tx1, out19, 0); addOnlyInputToTransaction(tx1, out19, 0);
b65.addTransaction(tx1); b65.addTransaction(tx1);
Transaction tx2 = new Transaction(params); Transaction tx2 = new Transaction(params);
tx2.addOutput(new TransactionOutput(params, tx2, BigInteger.ZERO, new byte[]{OP_TRUE})); tx2.addOutput(new TransactionOutput(params, tx2, Coin.ZERO, new byte[]{OP_TRUE}));
tx2.addInput(new TransactionInput(params, tx2, new byte[]{OP_TRUE}, tx2.addInput(new TransactionInput(params, tx2, new byte[]{OP_TRUE},
new TransactionOutPoint(params, 0, tx1.getHash()))); new TransactionOutPoint(params, 0, tx1.getHash())));
b65.addTransaction(tx2); b65.addTransaction(tx2);
@ -1234,7 +1234,7 @@ public class FullBlockTestGenerator {
tx1.addOutput(new TransactionOutput(params, tx1, out20.value, new byte[]{OP_TRUE})); tx1.addOutput(new TransactionOutput(params, tx1, out20.value, new byte[]{OP_TRUE}));
addOnlyInputToTransaction(tx1, out20, 0); addOnlyInputToTransaction(tx1, out20, 0);
Transaction tx2 = new Transaction(params); Transaction tx2 = new Transaction(params);
tx2.addOutput(new TransactionOutput(params, tx2, BigInteger.ZERO, new byte[]{OP_TRUE})); tx2.addOutput(new TransactionOutput(params, tx2, Coin.ZERO, new byte[]{OP_TRUE}));
tx2.addInput(new TransactionInput(params, tx2, new byte[]{OP_TRUE}, tx2.addInput(new TransactionInput(params, tx2, new byte[]{OP_TRUE},
new TransactionOutPoint(params, 0, tx1.getHash()))); new TransactionOutPoint(params, 0, tx1.getHash())));
b66.addTransaction(tx2); b66.addTransaction(tx2);
@ -1254,7 +1254,7 @@ public class FullBlockTestGenerator {
addOnlyInputToTransaction(tx1, out20, 0); addOnlyInputToTransaction(tx1, out20, 0);
b67.addTransaction(tx1); b67.addTransaction(tx1);
Transaction tx2 = new Transaction(params); Transaction tx2 = new Transaction(params);
tx2.addOutput(new TransactionOutput(params, tx2, BigInteger.ZERO, new byte[]{OP_TRUE})); tx2.addOutput(new TransactionOutput(params, tx2, Coin.ZERO, new byte[]{OP_TRUE}));
tx2.addInput(new TransactionInput(params, tx2, new byte[]{OP_TRUE}, tx2.addInput(new TransactionInput(params, tx2, new byte[]{OP_TRUE},
new TransactionOutPoint(params, 0, tx1.getHash()))); new TransactionOutPoint(params, 0, tx1.getHash())));
b67.addTransaction(tx2); b67.addTransaction(tx2);
@ -1271,20 +1271,20 @@ public class FullBlockTestGenerator {
// -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) -> b69 (20) // -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) -> b64 (18) -> b65 (19) -> b69 (20)
// \-> b68 (20) // \-> b68 (20)
// //
Block b68 = createNextBlock(b65, chainHeadHeight + 21, null, BigInteger.TEN); Block b68 = createNextBlock(b65, chainHeadHeight + 21, null, Coin.TEN);
{ {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
tx.addOutput(new TransactionOutput(params, tx, out20.value.subtract(BigInteger.valueOf(9)), new byte[]{OP_TRUE})); tx.addOutput(new TransactionOutput(params, tx, out20.value.subtract(Coin.valueOf(9)), new byte[]{OP_TRUE}));
addOnlyInputToTransaction(tx, out20, 0); addOnlyInputToTransaction(tx, out20, 0);
b68.addTransaction(tx); b68.addTransaction(tx);
} }
b68.solve(); b68.solve();
blocks.add(new BlockAndValidity(blockToHeightMap, b68, false, true, b65.getHash(), chainHeadHeight + 20, "b68")); blocks.add(new BlockAndValidity(blockToHeightMap, b68, false, true, b65.getHash(), chainHeadHeight + 20, "b68"));
Block b69 = createNextBlock(b65, chainHeadHeight + 21, null, BigInteger.TEN); Block b69 = createNextBlock(b65, chainHeadHeight + 21, null, Coin.TEN);
{ {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
tx.addOutput(new TransactionOutput(params, tx, out20.value.subtract(BigInteger.TEN), new byte[]{OP_TRUE})); tx.addOutput(new TransactionOutput(params, tx, out20.value.subtract(Coin.TEN), new byte[]{OP_TRUE}));
addOnlyInputToTransaction(tx, out20, 0); addOnlyInputToTransaction(tx, out20, 0);
b69.addTransaction(tx); b69.addTransaction(tx);
} }
@ -1304,7 +1304,7 @@ public class FullBlockTestGenerator {
Block b70 = createNextBlock(b69, chainHeadHeight + 22, out21, null); Block b70 = createNextBlock(b69, chainHeadHeight + 22, out21, null);
{ {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
tx.addOutput(new TransactionOutput(params, tx, BigInteger.ZERO, new byte[]{OP_TRUE})); tx.addOutput(new TransactionOutput(params, tx, Coin.ZERO, new byte[]{OP_TRUE}));
tx.addInput(new TransactionInput(params, tx, new byte[]{OP_TRUE}, tx.addInput(new TransactionInput(params, tx, new byte[]{OP_TRUE},
new TransactionOutPoint(params, 0, new Sha256Hash("23c70ed7c0506e9178fc1a987f40a33946d4ad4c962b5ae3a52546da53af0c5c")))); new TransactionOutPoint(params, 0, new Sha256Hash("23c70ed7c0506e9178fc1a987f40a33946d4ad4c962b5ae3a52546da53af0c5c"))));
b70.addTransaction(tx); b70.addTransaction(tx);
@ -1319,10 +1319,10 @@ public class FullBlockTestGenerator {
Block b72 = createNextBlock(b69, chainHeadHeight + 22, out21, null); Block b72 = createNextBlock(b69, chainHeadHeight + 22, out21, null);
{ {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
tx.addOutput(new TransactionOutput(params, tx, BigInteger.ZERO, new byte[]{OP_TRUE})); tx.addOutput(new TransactionOutput(params, tx, Coin.ZERO, new byte[]{OP_TRUE}));
addOnlyInputToTransaction(tx, new TransactionOutPointWithValue( addOnlyInputToTransaction(tx, new TransactionOutPointWithValue(
new TransactionOutPoint(params, 1, b72.getTransactions().get(1).getHash()), new TransactionOutPoint(params, 1, b72.getTransactions().get(1).getHash()),
BigInteger.valueOf(1), b72.getTransactions().get(1).getOutputs().get(1).getScriptPubKey())); Coin.valueOf(1), b72.getTransactions().get(1).getOutputs().get(1).getScriptPubKey()));
b72.addTransaction(tx); b72.addTransaction(tx);
} }
b72.solve(); b72.solve();
@ -1356,10 +1356,10 @@ public class FullBlockTestGenerator {
// If we push an element that is too large, the CHECKSIGs after that push are still counted // 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; outputScript[Block.MAX_BLOCK_SIGOPS - sigOps] = OP_PUSHDATA4;
Utils.uint32ToByteArrayLE(Script.MAX_SCRIPT_ELEMENT_SIZE + 1, outputScript, Block.MAX_BLOCK_SIGOPS - sigOps + 1); Utils.uint32ToByteArrayLE(Script.MAX_SCRIPT_ELEMENT_SIZE + 1, outputScript, Block.MAX_BLOCK_SIGOPS - sigOps + 1);
tx.addOutput(new TransactionOutput(params, tx, BigInteger.valueOf(1), outputScript)); tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(1), outputScript));
addOnlyInputToTransaction(tx, new TransactionOutPointWithValue( addOnlyInputToTransaction(tx, new TransactionOutPointWithValue(
new TransactionOutPoint(params, 1, b73.getTransactions().get(1).getHash()), new TransactionOutPoint(params, 1, b73.getTransactions().get(1).getHash()),
BigInteger.valueOf(1), b73.getTransactions().get(1).getOutputs().get(1).getScriptPubKey())); Coin.valueOf(1), b73.getTransactions().get(1).getOutputs().get(1).getScriptPubKey()));
b73.addTransaction(tx); b73.addTransaction(tx);
} }
b73.solve(); b73.solve();
@ -1380,10 +1380,10 @@ public class FullBlockTestGenerator {
outputScript[Block.MAX_BLOCK_SIGOPS - sigOps + 3] = (byte)0xff; outputScript[Block.MAX_BLOCK_SIGOPS - sigOps + 3] = (byte)0xff;
outputScript[Block.MAX_BLOCK_SIGOPS - sigOps + 4] = (byte)0xff; outputScript[Block.MAX_BLOCK_SIGOPS - sigOps + 4] = (byte)0xff;
outputScript[Block.MAX_BLOCK_SIGOPS - sigOps + 5] = (byte)0xff; outputScript[Block.MAX_BLOCK_SIGOPS - sigOps + 5] = (byte)0xff;
tx.addOutput(new TransactionOutput(params, tx, BigInteger.valueOf(1), outputScript)); tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(1), outputScript));
addOnlyInputToTransaction(tx, new TransactionOutPointWithValue( addOnlyInputToTransaction(tx, new TransactionOutPointWithValue(
new TransactionOutPoint(params, 1, b74.getTransactions().get(1).getHash()), new TransactionOutPoint(params, 1, b74.getTransactions().get(1).getHash()),
BigInteger.valueOf(1), b74.getTransactions().get(1).getOutputs().get(1).getScriptPubKey())); Coin.valueOf(1), b74.getTransactions().get(1).getOutputs().get(1).getScriptPubKey()));
b74.addTransaction(tx); b74.addTransaction(tx);
} }
b74.solve(); b74.solve();
@ -1404,10 +1404,10 @@ public class FullBlockTestGenerator {
outputScript[Block.MAX_BLOCK_SIGOPS - sigOps + 2] = (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 + 3] = (byte)0xff;
outputScript[Block.MAX_BLOCK_SIGOPS - sigOps + 4] = (byte)0xff; outputScript[Block.MAX_BLOCK_SIGOPS - sigOps + 4] = (byte)0xff;
tx.addOutput(new TransactionOutput(params, tx, BigInteger.valueOf(1), outputScript)); tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(1), outputScript));
addOnlyInputToTransaction(tx, new TransactionOutPointWithValue( addOnlyInputToTransaction(tx, new TransactionOutPointWithValue(
new TransactionOutPoint(params, 1, b75.getTransactions().get(1).getHash()), new TransactionOutPoint(params, 1, b75.getTransactions().get(1).getHash()),
BigInteger.valueOf(1), b75.getTransactions().get(1).getOutputs().get(1).getScriptPubKey())); Coin.valueOf(1), b75.getTransactions().get(1).getOutputs().get(1).getScriptPubKey()));
b75.addTransaction(tx); b75.addTransaction(tx);
} }
b75.solve(); b75.solve();
@ -1431,10 +1431,10 @@ public class FullBlockTestGenerator {
// If we push an element that is filled with CHECKSIGs, they (obviously) arent counted // If we push an element that is filled with CHECKSIGs, they (obviously) arent counted
outputScript[Block.MAX_BLOCK_SIGOPS - sigOps] = OP_PUSHDATA4; outputScript[Block.MAX_BLOCK_SIGOPS - sigOps] = OP_PUSHDATA4;
Utils.uint32ToByteArrayLE(Block.MAX_BLOCK_SIGOPS, outputScript, Block.MAX_BLOCK_SIGOPS - sigOps + 1); Utils.uint32ToByteArrayLE(Block.MAX_BLOCK_SIGOPS, outputScript, Block.MAX_BLOCK_SIGOPS - sigOps + 1);
tx.addOutput(new TransactionOutput(params, tx, BigInteger.valueOf(1), outputScript)); tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(1), outputScript));
addOnlyInputToTransaction(tx, new TransactionOutPointWithValue( addOnlyInputToTransaction(tx, new TransactionOutPointWithValue(
new TransactionOutPoint(params, 1, b76.getTransactions().get(1).getHash()), new TransactionOutPoint(params, 1, b76.getTransactions().get(1).getHash()),
BigInteger.valueOf(1), b76.getTransactions().get(1).getOutputs().get(1).getScriptPubKey())); Coin.valueOf(1), b76.getTransactions().get(1).getOutputs().get(1).getScriptPubKey()));
b76.addTransaction(tx); b76.addTransaction(tx);
} }
b76.solve(); b76.solve();
@ -1460,10 +1460,10 @@ public class FullBlockTestGenerator {
Block b78 = createNextBlock(b77, chainHeadHeight + 26, out25, null); Block b78 = createNextBlock(b77, chainHeadHeight + 26, out25, null);
Transaction b78tx = new Transaction(params); Transaction b78tx = new Transaction(params);
{ {
b78tx.addOutput(new TransactionOutput(params, b78tx, BigInteger.ZERO, new byte[]{OP_TRUE})); b78tx.addOutput(new TransactionOutput(params, b78tx, Coin.ZERO, new byte[]{OP_TRUE}));
addOnlyInputToTransaction(b78tx, new TransactionOutPointWithValue( addOnlyInputToTransaction(b78tx, new TransactionOutPointWithValue(
new TransactionOutPoint(params, 1, b77.getTransactions().get(1).getHash()), new TransactionOutPoint(params, 1, b77.getTransactions().get(1).getHash()),
BigInteger.valueOf(1), b77.getTransactions().get(1).getOutputs().get(1).getScriptPubKey())); Coin.valueOf(1), b77.getTransactions().get(1).getOutputs().get(1).getScriptPubKey()));
b78.addTransaction(b78tx); b78.addTransaction(b78tx);
} }
b78.solve(); b78.solve();
@ -1472,7 +1472,7 @@ public class FullBlockTestGenerator {
Block b79 = createNextBlock(b78, chainHeadHeight + 27, out26, null); Block b79 = createNextBlock(b78, chainHeadHeight + 27, out26, null);
Transaction b79tx = new Transaction(params); Transaction b79tx = new Transaction(params);
{ {
b79tx.addOutput(new TransactionOutput(params, b79tx, BigInteger.ZERO, new byte[]{OP_TRUE})); b79tx.addOutput(new TransactionOutput(params, b79tx, Coin.ZERO, new byte[]{OP_TRUE}));
b79tx.addInput(new TransactionInput(params, b79tx, new byte[]{OP_TRUE}, new TransactionOutPoint(params, 0, b78tx.getHash()))); b79tx.addInput(new TransactionInput(params, b79tx, new byte[]{OP_TRUE}, new TransactionOutPoint(params, 0, b78tx.getHash())));
b79.addTransaction(b79tx); b79.addTransaction(b79tx);
} }
@ -1541,8 +1541,8 @@ public class FullBlockTestGenerator {
while (block.getMessageSize() < Block.MAX_BLOCK_SIZE - 500) { while (block.getMessageSize() < Block.MAX_BLOCK_SIZE - 500) {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
tx.addInput(new TransactionInput(params, tx, new byte[] { OP_TRUE }, lastOutput)); tx.addInput(new TransactionInput(params, tx, new byte[] { OP_TRUE }, lastOutput));
tx.addOutput(new TransactionOutput(params, tx, BigInteger.ZERO, new byte[] { OP_TRUE })); tx.addOutput(new TransactionOutput(params, tx, Coin.ZERO, new byte[] { OP_TRUE }));
tx.addOutput(new TransactionOutput(params, tx, BigInteger.ZERO, new byte[] { OP_TRUE })); tx.addOutput(new TransactionOutput(params, tx, Coin.ZERO, new byte[] { OP_TRUE }));
lastOutput = new TransactionOutPoint(params, 1, tx.getHash()); lastOutput = new TransactionOutPoint(params, 1, tx.getHash());
hashesToSpend.add(tx.getHash()); hashesToSpend.add(tx.getHash());
block.addTransaction(tx); block.addTransaction(tx);
@ -1560,7 +1560,7 @@ public class FullBlockTestGenerator {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
tx.addInput(new TransactionInput(params, tx, new byte[] { OP_TRUE }, tx.addInput(new TransactionInput(params, tx, new byte[] { OP_TRUE },
new TransactionOutPoint(params, 0, hashes.next()))); new TransactionOutPoint(params, 0, hashes.next())));
tx.addOutput(new TransactionOutput(params, tx, BigInteger.ZERO, new byte[] { OP_TRUE })); tx.addOutput(new TransactionOutput(params, tx, Coin.ZERO, new byte[] { OP_TRUE }));
block.addTransaction(tx); block.addTransaction(tx);
} }
block.solve(); block.solve();
@ -1586,7 +1586,7 @@ public class FullBlockTestGenerator {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
tx.addInput(new TransactionInput(params, tx, new byte[] {OP_TRUE}, tx.addInput(new TransactionInput(params, tx, new byte[] {OP_TRUE},
new TransactionOutPoint(params, 0, hashesToSpend.get(0)))); new TransactionOutPoint(params, 0, hashesToSpend.get(0))));
tx.addOutput(new TransactionOutput(params, tx, BigInteger.ZERO, new byte[] { OP_TRUE })); tx.addOutput(new TransactionOutput(params, tx, Coin.ZERO, new byte[] { OP_TRUE }));
b1002.addTransaction(tx); b1002.addTransaction(tx);
} }
b1002.solve(); b1002.solve();
@ -1602,7 +1602,7 @@ public class FullBlockTestGenerator {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
tx.addInput(new TransactionInput(params, tx, new byte[] {OP_TRUE}, tx.addInput(new TransactionInput(params, tx, new byte[] {OP_TRUE},
new TransactionOutPoint(params, 0, hashesToSpend.get(0)))); new TransactionOutPoint(params, 0, hashesToSpend.get(0))));
tx.addOutput(new TransactionOutput(params, tx, BigInteger.ZERO, new byte[] { OP_TRUE })); tx.addOutput(new TransactionOutput(params, tx, Coin.ZERO, new byte[] { OP_TRUE }));
b1004.addTransaction(tx); b1004.addTransaction(tx);
} }
b1004.solve(); b1004.solve();
@ -1620,22 +1620,22 @@ public class FullBlockTestGenerator {
private byte uniquenessCounter = 0; private byte uniquenessCounter = 0;
private Block createNextBlock(Block baseBlock, int nextBlockHeight, TransactionOutPointWithValue prevOut, private Block createNextBlock(Block baseBlock, int nextBlockHeight, TransactionOutPointWithValue prevOut,
BigInteger additionalCoinbaseValue) throws ScriptException { Coin additionalCoinbaseValue) throws ScriptException {
Integer height = blockToHeightMap.get(baseBlock.getHash()); Integer height = blockToHeightMap.get(baseBlock.getHash());
if (height != null) if (height != null)
Preconditions.checkState(height == nextBlockHeight - 1); Preconditions.checkState(height == nextBlockHeight - 1);
BigInteger coinbaseValue = Utils.toNanoCoins(50, 0).shiftRight(nextBlockHeight / params.getSubsidyDecreaseBlockCount()) Coin coinbaseValue = Utils.toNanoCoins(50, 0).shiftRight(nextBlockHeight / params.getSubsidyDecreaseBlockCount())
.add((prevOut != null ? prevOut.value.subtract(BigInteger.ONE) : BigInteger.ZERO)) .add((prevOut != null ? prevOut.value.subtract(Coin.ONE) : Coin.ZERO))
.add(additionalCoinbaseValue == null ? BigInteger.ZERO : additionalCoinbaseValue); .add(additionalCoinbaseValue == null ? Coin.ZERO : additionalCoinbaseValue);
Block block = baseBlock.createNextBlockWithCoinbase(coinbaseOutKeyPubKey, coinbaseValue); Block block = baseBlock.createNextBlockWithCoinbase(coinbaseOutKeyPubKey, coinbaseValue);
if (prevOut != null) { if (prevOut != null) {
Transaction t = new Transaction(params); Transaction t = new Transaction(params);
// Entirely invalid scriptPubKey to ensure we aren't pre-verifying too much // Entirely invalid scriptPubKey to ensure we aren't pre-verifying too much
t.addOutput(new TransactionOutput(params, t, BigInteger.valueOf(0), new byte[] {OP_PUSHDATA1 - 1 })); t.addOutput(new TransactionOutput(params, t, Coin.valueOf(0), new byte[] {OP_PUSHDATA1 - 1 }));
t.addOutput(new TransactionOutput(params, t, BigInteger.valueOf(1), t.addOutput(new TransactionOutput(params, t, Coin.valueOf(1),
ScriptBuilder.createOutputScript(ECKey.fromPublicOnly(coinbaseOutKeyPubKey)).getProgram())); ScriptBuilder.createOutputScript(ECKey.fromPublicOnly(coinbaseOutKeyPubKey)).getProgram()));
// Spendable output // Spendable output
t.addOutput(new TransactionOutput(params, t, BigInteger.ZERO, new byte[] {OP_1, uniquenessCounter++})); t.addOutput(new TransactionOutput(params, t, Coin.ZERO, new byte[] {OP_1, uniquenessCounter++}));
addOnlyInputToTransaction(t, prevOut); addOnlyInputToTransaction(t, prevOut);
block.addTransaction(t); block.addTransaction(t);
block.solve(); block.solve();

View File

@ -34,7 +34,6 @@ import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.Parameterized; import org.junit.runners.Parameterized;
import java.math.BigInteger;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.*; import java.util.*;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
@ -179,7 +178,7 @@ public class PeerGroupTest extends TestWithPeerGroup {
expectedPeers.add(peerOf(p2)); expectedPeers.add(peerOf(p2));
assertEquals(tmp, expectedPeers); assertEquals(tmp, expectedPeers);
BigInteger value = Utils.toNanoCoins(1, 0); Coin value = Utils.toNanoCoins(1, 0);
Transaction t1 = FakeTxBuilder.createFakeTx(unitTestParams, value, address); Transaction t1 = FakeTxBuilder.createFakeTx(unitTestParams, value, address);
InventoryMessage inv = new InventoryMessage(unitTestParams); InventoryMessage inv = new InventoryMessage(unitTestParams);
inv.addTransaction(t1); inv.addTransaction(t1);

View File

@ -34,7 +34,6 @@ import org.junit.runners.Parameterized;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.math.BigInteger;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketException; import java.net.SocketException;
import java.nio.channels.CancelledKeyException; import java.nio.channels.CancelledKeyException;
@ -245,7 +244,7 @@ public class PeerTest extends TestWithNetworkConnections {
peer.setDownloadData(true); peer.setDownloadData(true);
// Make a transaction and tell the peer we have it. // Make a transaction and tell the peer we have it.
BigInteger value = Utils.toNanoCoins(1, 0); Coin value = Utils.toNanoCoins(1, 0);
Transaction tx = createFakeTx(unitTestParams, value, address); Transaction tx = createFakeTx(unitTestParams, value, address);
InventoryMessage inv = new InventoryMessage(unitTestParams); InventoryMessage inv = new InventoryMessage(unitTestParams);
InventoryItem item = new InventoryItem(InventoryItem.Type.Transaction, tx.getHash()); InventoryItem item = new InventoryItem(InventoryItem.Type.Transaction, tx.getHash());
@ -278,7 +277,7 @@ public class PeerTest extends TestWithNetworkConnections {
InboundMessageQueuer writeTarget2 = connect(peer2, peerVersion); InboundMessageQueuer writeTarget2 = connect(peer2, peerVersion);
// Make a tx and advertise it to one of the peers. // Make a tx and advertise it to one of the peers.
BigInteger value = Utils.toNanoCoins(1, 0); Coin value = Utils.toNanoCoins(1, 0);
Transaction tx = createFakeTx(unitTestParams, value, this.address); Transaction tx = createFakeTx(unitTestParams, value, this.address);
InventoryMessage inv = new InventoryMessage(unitTestParams); InventoryMessage inv = new InventoryMessage(unitTestParams);
InventoryItem item = new InventoryItem(InventoryItem.Type.Transaction, tx.getHash()); InventoryItem item = new InventoryItem(InventoryItem.Type.Transaction, tx.getHash());
@ -418,7 +417,7 @@ public class PeerTest extends TestWithNetworkConnections {
Block b2 = makeSolvedTestBlock(b1); Block b2 = makeSolvedTestBlock(b1);
Transaction t = new Transaction(unitTestParams); Transaction t = new Transaction(unitTestParams);
t.addInput(b1.getTransactions().get(0).getOutput(0)); t.addInput(b1.getTransactions().get(0).getOutput(0));
t.addOutput(new TransactionOutput(unitTestParams, t, BigInteger.ZERO, new byte[Block.MAX_BLOCK_SIZE - 1000])); t.addOutput(new TransactionOutput(unitTestParams, t, Coin.ZERO, new byte[Block.MAX_BLOCK_SIZE - 1000]));
b2.addTransaction(t); b2.addTransaction(t);
// Request the block. // Request the block.
@ -659,7 +658,7 @@ public class PeerTest extends TestWithNetworkConnections {
final Transaction[] vtx = new Transaction[1]; final Transaction[] vtx = new Transaction[1];
wallet.addEventListener(new AbstractWalletEventListener() { wallet.addEventListener(new AbstractWalletEventListener() {
@Override @Override
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
vtx[0] = tx; vtx[0] = tx;
} }
}); });
@ -732,7 +731,7 @@ public class PeerTest extends TestWithNetworkConnections {
final Transaction[] vtx = new Transaction[1]; final Transaction[] vtx = new Transaction[1];
wallet.addEventListener(new AbstractWalletEventListener() { wallet.addEventListener(new AbstractWalletEventListener() {
@Override @Override
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
vtx[0] = tx; vtx[0] = tx;
} }
}); });
@ -817,7 +816,7 @@ public class PeerTest extends TestWithNetworkConnections {
public void exceptionListener() throws Exception { public void exceptionListener() throws Exception {
wallet.addEventListener(new AbstractWalletEventListener() { wallet.addEventListener(new AbstractWalletEventListener() {
@Override @Override
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
throw new NullPointerException("boo!"); throw new NullPointerException("boo!");
} }
}); });

View File

@ -16,11 +16,10 @@
package com.google.bitcoin.core; package com.google.bitcoin.core;
import java.math.BigInteger;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import java.math.BigInteger;
import static com.google.bitcoin.core.Utils.*; import static com.google.bitcoin.core.Utils.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
@ -59,7 +58,7 @@ public class UtilsTest {
public void testFormatting() { public void testFormatting() {
assertEquals("1.00", bitcoinValueToFriendlyString(toNanoCoins(1, 0))); assertEquals("1.00", bitcoinValueToFriendlyString(toNanoCoins(1, 0)));
assertEquals("1.23", bitcoinValueToFriendlyString(toNanoCoins(1, 23))); assertEquals("1.23", bitcoinValueToFriendlyString(toNanoCoins(1, 23)));
assertEquals("0.001", bitcoinValueToFriendlyString(BigInteger.valueOf(COIN.longValue() / 1000))); assertEquals("0.001", bitcoinValueToFriendlyString(Coin.valueOf(COIN.longValue() / 1000)));
assertEquals("-1.23", bitcoinValueToFriendlyString(toNanoCoins(1, 23).negate())); assertEquals("-1.23", bitcoinValueToFriendlyString(toNanoCoins(1, 23).negate()));
} }
@ -76,7 +75,7 @@ public class UtilsTest {
assertTrue(e.getMessage().contains("Value cannot be null")); assertTrue(e.getMessage().contains("Value cannot be null"));
} }
assertEquals("0.0015", bitcoinValueToPlainString(BigInteger.valueOf(150000))); assertEquals("0.0015", bitcoinValueToPlainString(Coin.valueOf(150000)));
assertEquals("1.23", bitcoinValueToPlainString(toNanoCoins("1.23"))); assertEquals("1.23", bitcoinValueToPlainString(toNanoCoins("1.23")));
assertEquals("0.1", bitcoinValueToPlainString(toNanoCoins("0.1"))); assertEquals("0.1", bitcoinValueToPlainString(toNanoCoins("0.1")));

View File

@ -152,7 +152,7 @@ public class WalletTest extends TestWithWallet {
private Transaction cleanupCommon(Address destination) throws Exception { private Transaction cleanupCommon(Address destination) throws Exception {
receiveATransaction(wallet, myAddress); receiveATransaction(wallet, myAddress);
BigInteger v2 = toNanoCoins(0, 50); Coin v2 = toNanoCoins(0, 50);
SendRequest req = SendRequest.to(destination, v2); SendRequest req = SendRequest.to(destination, v2);
req.fee = toNanoCoins(0, 1); req.fee = toNanoCoins(0, 1);
wallet.completeTx(req); wallet.completeTx(req);
@ -164,7 +164,7 @@ public class WalletTest extends TestWithWallet {
// At this point we have one pending and one spent // At this point we have one pending and one spent
BigInteger v1 = toNanoCoins(0, 10); Coin v1 = toNanoCoins(0, 10);
Transaction t = sendMoneyToWallet(wallet, v1, myAddress, null); Transaction t = sendMoneyToWallet(wallet, v1, myAddress, null);
Threading.waitForUserCode(); Threading.waitForUserCode();
sendMoneyToWallet(wallet, t, null); sendMoneyToWallet(wallet, t, null);
@ -199,7 +199,7 @@ public class WalletTest extends TestWithWallet {
Transaction t = cleanupCommon(destination); Transaction t = cleanupCommon(destination);
// Now we have another incoming pending. Spend everything. // Now we have another incoming pending. Spend everything.
BigInteger v3 = toNanoCoins(0, 58); Coin v3 = toNanoCoins(0, 58);
SendRequest req = SendRequest.to(destination, v3); SendRequest req = SendRequest.to(destination, v3);
// Force selection of the incoming coin so that we can spend it // Force selection of the incoming coin so that we can spend it
@ -235,7 +235,7 @@ public class WalletTest extends TestWithWallet {
receiveATransaction(wallet, toAddress); receiveATransaction(wallet, toAddress);
// Try to send too much and fail. // Try to send too much and fail.
BigInteger vHuge = toNanoCoins(10, 0); Coin vHuge = toNanoCoins(10, 0);
Wallet.SendRequest req = Wallet.SendRequest.to(destination, vHuge); Wallet.SendRequest req = Wallet.SendRequest.to(destination, vHuge);
try { try {
wallet.completeTx(req); wallet.completeTx(req);
@ -245,7 +245,7 @@ public class WalletTest extends TestWithWallet {
} }
// Prepare to send. // Prepare to send.
BigInteger v2 = toNanoCoins(0, 50); Coin v2 = toNanoCoins(0, 50);
req = Wallet.SendRequest.to(destination, v2); req = Wallet.SendRequest.to(destination, v2);
req.fee = toNanoCoins(0, 1); req.fee = toNanoCoins(0, 1);
@ -306,9 +306,9 @@ public class WalletTest extends TestWithWallet {
} }
private void receiveATransaction(Wallet wallet, Address toAddress) throws Exception { private void receiveATransaction(Wallet wallet, Address toAddress) throws Exception {
BigInteger v1 = Utils.toNanoCoins(1, 0); Coin v1 = Utils.toNanoCoins(1, 0);
final ListenableFuture<BigInteger> availFuture = wallet.getBalanceFuture(v1, Wallet.BalanceType.AVAILABLE); final ListenableFuture<Coin> availFuture = wallet.getBalanceFuture(v1, Wallet.BalanceType.AVAILABLE);
final ListenableFuture<BigInteger> estimatedFuture = wallet.getBalanceFuture(v1, Wallet.BalanceType.ESTIMATED); final ListenableFuture<Coin> estimatedFuture = wallet.getBalanceFuture(v1, Wallet.BalanceType.ESTIMATED);
assertFalse(availFuture.isDone()); assertFalse(availFuture.isDone());
assertFalse(estimatedFuture.isDone()); assertFalse(estimatedFuture.isDone());
// Send some pending coins to the wallet. // Send some pending coins to the wallet.
@ -316,7 +316,7 @@ public class WalletTest extends TestWithWallet {
Threading.waitForUserCode(); Threading.waitForUserCode();
final ListenableFuture<Transaction> depthFuture = t1.getConfidence().getDepthFuture(1); final ListenableFuture<Transaction> depthFuture = t1.getConfidence().getDepthFuture(1);
assertFalse(depthFuture.isDone()); assertFalse(depthFuture.isDone());
assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(Coin.ZERO, wallet.getBalance());
assertEquals(v1, wallet.getBalance(Wallet.BalanceType.ESTIMATED)); assertEquals(v1, wallet.getBalance(Wallet.BalanceType.ESTIMATED));
assertFalse(availFuture.isDone()); assertFalse(availFuture.isDone());
// Our estimated balance has reached the requested level. // Our estimated balance has reached the requested level.
@ -352,7 +352,7 @@ public class WalletTest extends TestWithWallet {
final LinkedList<Transaction> txns = Lists.newLinkedList(); final LinkedList<Transaction> txns = Lists.newLinkedList();
wallet.addEventListener(new AbstractWalletEventListener() { wallet.addEventListener(new AbstractWalletEventListener() {
@Override @Override
public void onCoinsSent(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { public void onCoinsSent(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
txns.add(tx); txns.add(tx);
} }
}); });
@ -369,7 +369,7 @@ public class WalletTest extends TestWithWallet {
} }
private void spendUnconfirmedChange(Wallet wallet, Transaction t2, KeyParameter aesKey) throws Exception { private void spendUnconfirmedChange(Wallet wallet, Transaction t2, KeyParameter aesKey) throws Exception {
BigInteger v3 = toNanoCoins(0, 49); Coin v3 = toNanoCoins(0, 49);
assertEquals(v3, wallet.getBalance()); assertEquals(v3, wallet.getBalance());
Wallet.SendRequest req = Wallet.SendRequest.to(new ECKey().toAddress(params), toNanoCoins(0, 48)); Wallet.SendRequest req = Wallet.SendRequest.to(new ECKey().toAddress(params), toNanoCoins(0, 48));
req.aesKey = aesKey; req.aesKey = aesKey;
@ -395,7 +395,7 @@ public class WalletTest extends TestWithWallet {
// Having a test for deprecated method getFromAddress() is no evil so we suppress the warning here. // Having a test for deprecated method getFromAddress() is no evil so we suppress the warning here.
public void customTransactionSpending() throws Exception { public void customTransactionSpending() throws Exception {
// We'll set up a wallet that receives a coin, then sends a coin of lesser value and keeps the change. // We'll set up a wallet that receives a coin, then sends a coin of lesser value and keeps the change.
BigInteger v1 = Utils.toNanoCoins(3, 0); Coin v1 = Utils.toNanoCoins(3, 0);
sendMoneyToWallet(v1, AbstractBlockChain.NewBlockType.BEST_CHAIN); sendMoneyToWallet(v1, AbstractBlockChain.NewBlockType.BEST_CHAIN);
assertEquals(v1, wallet.getBalance()); assertEquals(v1, wallet.getBalance());
assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.UNSPENT)); assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.UNSPENT));
@ -403,9 +403,9 @@ public class WalletTest extends TestWithWallet {
ECKey k2 = new ECKey(); ECKey k2 = new ECKey();
Address a2 = k2.toAddress(params); Address a2 = k2.toAddress(params);
BigInteger v2 = toNanoCoins(0, 50); Coin v2 = toNanoCoins(0, 50);
BigInteger v3 = toNanoCoins(0, 75); Coin v3 = toNanoCoins(0, 75);
BigInteger v4 = toNanoCoins(1, 25); Coin v4 = toNanoCoins(1, 25);
Transaction t2 = new Transaction(params); Transaction t2 = new Transaction(params);
t2.addOutput(v2, a2); t2.addOutput(v2, a2);
@ -431,13 +431,13 @@ public class WalletTest extends TestWithWallet {
public void sideChain() throws Exception { public void sideChain() throws Exception {
// The wallet receives a coin on the main chain, then on a side chain. Balance is equal to both added together // The wallet receives a coin on the main chain, then on a side chain. Balance is equal to both added together
// as we assume the side chain tx is pending and will be included shortly. // as we assume the side chain tx is pending and will be included shortly.
BigInteger v1 = Utils.toNanoCoins(1, 0); Coin v1 = Utils.toNanoCoins(1, 0);
sendMoneyToWallet(v1, AbstractBlockChain.NewBlockType.BEST_CHAIN); sendMoneyToWallet(v1, AbstractBlockChain.NewBlockType.BEST_CHAIN);
assertEquals(v1, wallet.getBalance()); assertEquals(v1, wallet.getBalance());
assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.UNSPENT)); assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.UNSPENT));
assertEquals(1, wallet.getTransactions(true).size()); assertEquals(1, wallet.getTransactions(true).size());
BigInteger v2 = toNanoCoins(0, 50); Coin v2 = toNanoCoins(0, 50);
sendMoneyToWallet(v2, AbstractBlockChain.NewBlockType.SIDE_CHAIN); sendMoneyToWallet(v2, AbstractBlockChain.NewBlockType.SIDE_CHAIN);
assertEquals(2, wallet.getTransactions(true).size()); assertEquals(2, wallet.getTransactions(true).size());
assertEquals(v1, wallet.getBalance()); assertEquals(v1, wallet.getBalance());
@ -447,9 +447,9 @@ public class WalletTest extends TestWithWallet {
@Test @Test
public void balance() throws Exception { public void balance() throws Exception {
// Receive 5 coins then half a coin. // Receive 5 coins then half a coin.
BigInteger v1 = toNanoCoins(5, 0); Coin v1 = toNanoCoins(5, 0);
BigInteger v2 = toNanoCoins(0, 50); Coin v2 = toNanoCoins(0, 50);
BigInteger expected = toNanoCoins(5, 50); Coin expected = toNanoCoins(5, 50);
assertEquals(0, wallet.getTransactions(true).size()); assertEquals(0, wallet.getTransactions(true).size());
sendMoneyToWallet(v1, AbstractBlockChain.NewBlockType.BEST_CHAIN); sendMoneyToWallet(v1, AbstractBlockChain.NewBlockType.BEST_CHAIN);
assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.UNSPENT)); assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.UNSPENT));
@ -458,7 +458,7 @@ public class WalletTest extends TestWithWallet {
assertEquals(expected, wallet.getBalance()); assertEquals(expected, wallet.getBalance());
// Now spend one coin. // Now spend one coin.
BigInteger v3 = toNanoCoins(1, 0); Coin v3 = toNanoCoins(1, 0);
Transaction spend = wallet.createSend(new ECKey().toAddress(params), v3); Transaction spend = wallet.createSend(new ECKey().toAddress(params), v3);
wallet.commitTx(spend); wallet.commitTx(spend);
assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.PENDING)); assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.PENDING));
@ -474,7 +474,7 @@ public class WalletTest extends TestWithWallet {
wallet.receiveFromBlock(spend, b3, BlockChain.NewBlockType.BEST_CHAIN, 0); wallet.receiveFromBlock(spend, b3, BlockChain.NewBlockType.BEST_CHAIN, 0);
// Change is confirmed. We started with 5.50 so we should have 4.50 left. // Change is confirmed. We started with 5.50 so we should have 4.50 left.
BigInteger v4 = toNanoCoins(4, 50); Coin v4 = toNanoCoins(4, 50);
assertEquals(v4, wallet.getBalance(Wallet.BalanceType.AVAILABLE)); assertEquals(v4, wallet.getBalance(Wallet.BalanceType.AVAILABLE));
} }
@ -486,12 +486,12 @@ public class WalletTest extends TestWithWallet {
@Test @Test
public void blockChainCatchup() throws Exception { public void blockChainCatchup() throws Exception {
// Test that we correctly process transactions arriving from the chain, with callbacks for inbound and outbound. // Test that we correctly process transactions arriving from the chain, with callbacks for inbound and outbound.
final BigInteger bigints[] = new BigInteger[4]; final Coin bigints[] = new Coin[4];
final Transaction txn[] = new Transaction[2]; final Transaction txn[] = new Transaction[2];
final LinkedList<Transaction> confTxns = new LinkedList<Transaction>(); final LinkedList<Transaction> confTxns = new LinkedList<Transaction>();
wallet.addEventListener(new AbstractWalletEventListener() { wallet.addEventListener(new AbstractWalletEventListener() {
@Override @Override
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
super.onCoinsReceived(wallet, tx, prevBalance, newBalance); super.onCoinsReceived(wallet, tx, prevBalance, newBalance);
bigints[0] = prevBalance; bigints[0] = prevBalance;
bigints[1] = newBalance; bigints[1] = newBalance;
@ -499,7 +499,7 @@ public class WalletTest extends TestWithWallet {
} }
@Override @Override
public void onCoinsSent(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { public void onCoinsSent(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
super.onCoinsSent(wallet, tx, prevBalance, newBalance); super.onCoinsSent(wallet, tx, prevBalance, newBalance);
bigints[2] = prevBalance; bigints[2] = prevBalance;
bigints[3] = newBalance; bigints[3] = newBalance;
@ -514,13 +514,13 @@ public class WalletTest extends TestWithWallet {
}); });
// Receive some money. // Receive some money.
BigInteger oneCoin = Utils.toNanoCoins(1, 0); Coin oneCoin = Utils.toNanoCoins(1, 0);
Transaction tx1 = sendMoneyToWallet(oneCoin, AbstractBlockChain.NewBlockType.BEST_CHAIN); Transaction tx1 = sendMoneyToWallet(oneCoin, AbstractBlockChain.NewBlockType.BEST_CHAIN);
Threading.waitForUserCode(); Threading.waitForUserCode();
assertEquals(null, txn[1]); // onCoinsSent not called. assertEquals(null, txn[1]); // onCoinsSent not called.
assertEquals(tx1, confTxns.getFirst()); // onTransactionConfidenceChanged called assertEquals(tx1, confTxns.getFirst()); // onTransactionConfidenceChanged called
assertEquals(txn[0].getHash(), tx1.getHash()); assertEquals(txn[0].getHash(), tx1.getHash());
assertEquals(BigInteger.ZERO, bigints[0]); assertEquals(Coin.ZERO, bigints[0]);
assertEquals(oneCoin, bigints[1]); assertEquals(oneCoin, bigints[1]);
assertEquals(TransactionConfidence.ConfidenceType.BUILDING, tx1.getConfidence().getConfidenceType()); assertEquals(TransactionConfidence.ConfidenceType.BUILDING, tx1.getConfidence().getConfidenceType());
assertEquals(1, tx1.getConfidence().getAppearedAtChainHeight()); assertEquals(1, tx1.getConfidence().getAppearedAtChainHeight());
@ -555,7 +555,7 @@ public class WalletTest extends TestWithWallet {
@Test @Test
public void balances() throws Exception { public void balances() throws Exception {
BigInteger nanos = Utils.toNanoCoins(1, 0); Coin nanos = Utils.toNanoCoins(1, 0);
Transaction tx1 = sendMoneyToWallet(nanos, AbstractBlockChain.NewBlockType.BEST_CHAIN); Transaction tx1 = sendMoneyToWallet(nanos, AbstractBlockChain.NewBlockType.BEST_CHAIN);
assertEquals(nanos, tx1.getValueSentToMe(wallet, true)); assertEquals(nanos, tx1.getValueSentToMe(wallet, true));
// Send 0.10 to somebody else. // Send 0.10 to somebody else.
@ -563,7 +563,7 @@ public class WalletTest extends TestWithWallet {
// Reserialize. // Reserialize.
Transaction send2 = new Transaction(params, send1.bitcoinSerialize()); Transaction send2 = new Transaction(params, send1.bitcoinSerialize());
assertEquals(nanos, send2.getValueSentFromMe(wallet)); assertEquals(nanos, send2.getValueSentFromMe(wallet));
assertEquals(BigInteger.ZERO.subtract(toNanoCoins(0, 10)), send2.getValue(wallet)); assertEquals(Coin.ZERO.subtract(toNanoCoins(0, 10)), send2.getValue(wallet));
} }
@Test @Test
@ -640,11 +640,11 @@ public class WalletTest extends TestWithWallet {
public void bounce() throws Exception { public void bounce() throws Exception {
// This test covers bug 64 (False double spends). Check that if we create a spend and it's immediately sent // This test covers bug 64 (False double spends). Check that if we create a spend and it's immediately sent
// back to us, this isn't considered as a double spend. // back to us, this isn't considered as a double spend.
BigInteger coin1 = Utils.toNanoCoins(1, 0); Coin coin1 = Utils.toNanoCoins(1, 0);
sendMoneyToWallet(coin1, AbstractBlockChain.NewBlockType.BEST_CHAIN); sendMoneyToWallet(coin1, AbstractBlockChain.NewBlockType.BEST_CHAIN);
// Send half to some other guy. Sending only half then waiting for a confirm is important to ensure the tx is // Send half to some other guy. Sending only half then waiting for a confirm is important to ensure the tx is
// in the unspent pool, not pending or spent. // in the unspent pool, not pending or spent.
BigInteger coinHalf = Utils.toNanoCoins(0, 50); Coin coinHalf = Utils.toNanoCoins(0, 50);
assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.UNSPENT)); assertEquals(1, wallet.getPoolSize(WalletTransaction.Pool.UNSPENT));
assertEquals(1, wallet.getTransactions(true).size()); assertEquals(1, wallet.getTransactions(true).size());
Address someOtherGuy = new ECKey().toAddress(params); Address someOtherGuy = new ECKey().toAddress(params);
@ -675,7 +675,7 @@ public class WalletTest extends TestWithWallet {
send2 = new Transaction(params, send2.bitcoinSerialize()); send2 = new Transaction(params, send2.bitcoinSerialize());
// Broadcast send1, it's now pending. // Broadcast send1, it's now pending.
wallet.commitTx(send1); wallet.commitTx(send1);
assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(Coin.ZERO, wallet.getBalance());
// Receive a block that overrides the send1 using send2. // Receive a block that overrides the send1 using send2.
sendMoneyToWallet(send2, AbstractBlockChain.NewBlockType.BEST_CHAIN); sendMoneyToWallet(send2, AbstractBlockChain.NewBlockType.BEST_CHAIN);
// send1 got rolled back and replaced with a smaller send that only used one of our received coins, thus ... // send1 got rolled back and replaced with a smaller send that only used one of our received coins, thus ...
@ -691,8 +691,8 @@ public class WalletTest extends TestWithWallet {
// This can (and has!) happened when a wallet is cloned between devices, and both devices decide to make the // This can (and has!) happened when a wallet is cloned between devices, and both devices decide to make the
// same spend simultaneously - for example due a re-keying operation. It can also happen if there are malicious // same spend simultaneously - for example due a re-keying operation. It can also happen if there are malicious
// nodes in the P2P network that are mutating transactions on the fly as occurred during Feb 2014. // nodes in the P2P network that are mutating transactions on the fly as occurred during Feb 2014.
final BigInteger value = Utils.toNanoCoins(1, 0); final Coin value = Utils.toNanoCoins(1, 0);
final BigInteger value2 = Utils.toNanoCoins(2, 0); final Coin value2 = Utils.toNanoCoins(2, 0);
// Give us three coins and make sure we have some change. // Give us three coins and make sure we have some change.
sendMoneyToWallet(value.add(value2), AbstractBlockChain.NewBlockType.BEST_CHAIN); sendMoneyToWallet(value.add(value2), AbstractBlockChain.NewBlockType.BEST_CHAIN);
final Address address = new ECKey().toAddress(params); final Address address = new ECKey().toAddress(params);
@ -707,7 +707,7 @@ public class WalletTest extends TestWithWallet {
// Now spend the change. This transaction should die permanently when the mutant appears in the chain. // Now spend the change. This transaction should die permanently when the mutant appears in the chain.
Transaction send3 = checkNotNull(wallet.createSend(address, value)); Transaction send3 = checkNotNull(wallet.createSend(address, value));
wallet.commitTx(send3); wallet.commitTx(send3);
assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(Coin.ZERO, wallet.getBalance());
final LinkedList<Transaction> dead = new LinkedList<Transaction>(); final LinkedList<Transaction> dead = new LinkedList<Transaction>();
final TransactionConfidence.Listener listener = new TransactionConfidence.Listener() { final TransactionConfidence.Listener listener = new TransactionConfidence.Listener() {
@Override @Override
@ -758,7 +758,7 @@ public class WalletTest extends TestWithWallet {
}); });
// Receive 1 BTC. // Receive 1 BTC.
BigInteger nanos = Utils.toNanoCoins(1, 0); Coin nanos = Utils.toNanoCoins(1, 0);
sendMoneyToWallet(nanos, AbstractBlockChain.NewBlockType.BEST_CHAIN); sendMoneyToWallet(nanos, AbstractBlockChain.NewBlockType.BEST_CHAIN);
Transaction received = wallet.getTransactions(false).iterator().next(); Transaction received = wallet.getTransactions(false).iterator().next();
// Create a send to a merchant. // Create a send to a merchant.
@ -794,7 +794,7 @@ public class WalletTest extends TestWithWallet {
@Test @Test
public void pending1() throws Exception { public void pending1() throws Exception {
// Check that if we receive a pending transaction that is then confirmed, we are notified as appropriate. // Check that if we receive a pending transaction that is then confirmed, we are notified as appropriate.
final BigInteger nanos = Utils.toNanoCoins(1, 0); final Coin nanos = Utils.toNanoCoins(1, 0);
final Transaction t1 = createFakeTx(params, nanos, myAddress); final Transaction t1 = createFakeTx(params, nanos, myAddress);
// First one is "called" second is "pending". // First one is "called" second is "pending".
@ -803,11 +803,11 @@ public class WalletTest extends TestWithWallet {
final int[] walletChanged = new int[1]; final int[] walletChanged = new int[1];
wallet.addEventListener(new AbstractWalletEventListener() { wallet.addEventListener(new AbstractWalletEventListener() {
@Override @Override
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
// Check we got the expected transaction. // Check we got the expected transaction.
assertEquals(tx, t1); assertEquals(tx, t1);
// Check that it's considered to be pending inclusion in the block chain. // Check that it's considered to be pending inclusion in the block chain.
assertEquals(prevBalance, BigInteger.ZERO); assertEquals(prevBalance, Coin.ZERO);
assertEquals(newBalance, nanos); assertEquals(newBalance, nanos);
flags[0] = true; flags[0] = true;
flags[1] = tx.isPending(); flags[1] = tx.isPending();
@ -867,21 +867,21 @@ public class WalletTest extends TestWithWallet {
public void pending2() throws Exception { public void pending2() throws Exception {
// Check that if we receive a pending tx we did not send, it updates our spent flags correctly. // Check that if we receive a pending tx we did not send, it updates our spent flags correctly.
final Transaction txn[] = new Transaction[1]; final Transaction txn[] = new Transaction[1];
final BigInteger bigints[] = new BigInteger[2]; final Coin bigints[] = new Coin[2];
wallet.addEventListener(new AbstractWalletEventListener() { wallet.addEventListener(new AbstractWalletEventListener() {
@Override @Override
public void onCoinsSent(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { public void onCoinsSent(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
txn[0] = tx; txn[0] = tx;
bigints[0] = prevBalance; bigints[0] = prevBalance;
bigints[1] = newBalance; bigints[1] = newBalance;
} }
}); });
// Receive some coins. // Receive some coins.
BigInteger nanos = Utils.toNanoCoins(1, 0); Coin nanos = Utils.toNanoCoins(1, 0);
sendMoneyToWallet(nanos, AbstractBlockChain.NewBlockType.BEST_CHAIN); sendMoneyToWallet(nanos, AbstractBlockChain.NewBlockType.BEST_CHAIN);
// Create a spend with them, but don't commit it (ie it's from somewhere else but using our keys). This TX // Create a spend with them, but don't commit it (ie it's from somewhere else but using our keys). This TX
// will have change as we don't spend our entire balance. // will have change as we don't spend our entire balance.
BigInteger halfNanos = Utils.toNanoCoins(0, 50); Coin halfNanos = Utils.toNanoCoins(0, 50);
Transaction t2 = wallet.createSend(new ECKey().toAddress(params), halfNanos); Transaction t2 = wallet.createSend(new ECKey().toAddress(params), halfNanos);
// Now receive it as pending. // Now receive it as pending.
if (wallet.isPendingTransactionRelevant(t2)) if (wallet.isPendingTransactionRelevant(t2))
@ -900,7 +900,7 @@ public class WalletTest extends TestWithWallet {
// Check that if we receive a pending tx, and it's overridden by a double spend from the main chain, we // Check that if we receive a pending tx, and it's overridden by a double spend from the main chain, we
// are notified that it's dead. This should work even if the pending tx inputs are NOT ours, ie, they don't // are notified that it's dead. This should work even if the pending tx inputs are NOT ours, ie, they don't
// connect to anything. // connect to anything.
BigInteger nanos = Utils.toNanoCoins(1, 0); Coin nanos = Utils.toNanoCoins(1, 0);
// Create two transactions that share the same input tx. // Create two transactions that share the same input tx.
Address badGuy = new ECKey().toAddress(params); Address badGuy = new ECKey().toAddress(params);
@ -918,7 +918,7 @@ public class WalletTest extends TestWithWallet {
final Transaction[] called = new Transaction[2]; final Transaction[] called = new Transaction[2];
wallet.addEventListener(new AbstractWalletEventListener() { wallet.addEventListener(new AbstractWalletEventListener() {
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
called[0] = tx; called[0] = tx;
} }
@ -933,7 +933,7 @@ public class WalletTest extends TestWithWallet {
} }
}); });
assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(Coin.ZERO, wallet.getBalance());
if (wallet.isPendingTransactionRelevant(t1)) if (wallet.isPendingTransactionRelevant(t1))
wallet.receivePending(t1, null); wallet.receivePending(t1, null);
Threading.waitForUserCode(); Threading.waitForUserCode();
@ -943,7 +943,7 @@ public class WalletTest extends TestWithWallet {
called[0] = called[1] = null; called[0] = called[1] = null;
sendMoneyToWallet(t2, AbstractBlockChain.NewBlockType.BEST_CHAIN); sendMoneyToWallet(t2, AbstractBlockChain.NewBlockType.BEST_CHAIN);
Threading.waitForUserCode(); Threading.waitForUserCode();
assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(Coin.ZERO, wallet.getBalance());
assertEquals(t1, called[0]); // dead assertEquals(t1, called[0]); // dead
assertEquals(t2, called[1]); // replacement assertEquals(t2, called[1]); // replacement
} }
@ -1021,8 +1021,8 @@ public class WalletTest extends TestWithWallet {
// Test that a spend to the same wallet is dealt with correctly. // Test that a spend to the same wallet is dealt with correctly.
// It should appear in the wallet and confirm. // It should appear in the wallet and confirm.
// This is a bit of a silly thing to do in the real world as all it does is burn a fee but it is perfectly valid. // This is a bit of a silly thing to do in the real world as all it does is burn a fee but it is perfectly valid.
BigInteger coin1 = Utils.toNanoCoins(1, 0); Coin coin1 = Utils.toNanoCoins(1, 0);
BigInteger coinHalf = Utils.toNanoCoins(0, 50); Coin coinHalf = Utils.toNanoCoins(0, 50);
// Start by giving us 1 coin. // Start by giving us 1 coin.
sendMoneyToWallet(coin1, AbstractBlockChain.NewBlockType.BEST_CHAIN); sendMoneyToWallet(coin1, AbstractBlockChain.NewBlockType.BEST_CHAIN);
// Send half to ourselves. We should then have a balance available to spend of zero. // Send half to ourselves. We should then have a balance available to spend of zero.
@ -1031,7 +1031,7 @@ public class WalletTest extends TestWithWallet {
Transaction outbound1 = wallet.createSend(myAddress, coinHalf); Transaction outbound1 = wallet.createSend(myAddress, coinHalf);
wallet.commitTx(outbound1); wallet.commitTx(outbound1);
// We should have a zero available balance before the next block. // We should have a zero available balance before the next block.
assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(Coin.ZERO, wallet.getBalance());
sendMoneyToWallet(outbound1, AbstractBlockChain.NewBlockType.BEST_CHAIN); sendMoneyToWallet(outbound1, AbstractBlockChain.NewBlockType.BEST_CHAIN);
// We should have a balance of 1 BTC after the block is received. // We should have a balance of 1 BTC after the block is received.
assertEquals(coin1, wallet.getBalance()); assertEquals(coin1, wallet.getBalance());
@ -1039,9 +1039,9 @@ public class WalletTest extends TestWithWallet {
@Test @Test
public void lastBlockSeen() throws Exception { public void lastBlockSeen() throws Exception {
BigInteger v1 = toNanoCoins(5, 0); Coin v1 = toNanoCoins(5, 0);
BigInteger v2 = toNanoCoins(0, 50); Coin v2 = toNanoCoins(0, 50);
BigInteger v3 = toNanoCoins(0, 25); Coin v3 = toNanoCoins(0, 25);
Transaction t1 = createFakeTx(params, v1, myAddress); Transaction t1 = createFakeTx(params, v1, myAddress);
Transaction t2 = createFakeTx(params, v2, myAddress); Transaction t2 = createFakeTx(params, v2, myAddress);
Transaction t3 = createFakeTx(params, v3, myAddress); Transaction t3 = createFakeTx(params, v3, myAddress);
@ -1072,13 +1072,13 @@ public class WalletTest extends TestWithWallet {
public void pubkeyOnlyScripts() throws Exception { public void pubkeyOnlyScripts() throws Exception {
// Verify that we support outputs like OP_PUBKEY and the corresponding inputs. // Verify that we support outputs like OP_PUBKEY and the corresponding inputs.
ECKey key1 = wallet.freshReceiveKey(); ECKey key1 = wallet.freshReceiveKey();
BigInteger value = toNanoCoins(5, 0); Coin value = toNanoCoins(5, 0);
Transaction t1 = createFakeTx(params, value, key1); Transaction t1 = createFakeTx(params, value, key1);
if (wallet.isPendingTransactionRelevant(t1)) if (wallet.isPendingTransactionRelevant(t1))
wallet.receivePending(t1, null); wallet.receivePending(t1, null);
// TX should have been seen as relevant. // TX should have been seen as relevant.
assertEquals(value, wallet.getBalance(Wallet.BalanceType.ESTIMATED)); assertEquals(value, wallet.getBalance(Wallet.BalanceType.ESTIMATED));
assertEquals(BigInteger.ZERO, wallet.getBalance(Wallet.BalanceType.AVAILABLE)); assertEquals(Coin.ZERO, wallet.getBalance(Wallet.BalanceType.AVAILABLE));
Block b1 = createFakeBlock(blockStore, t1).block; Block b1 = createFakeBlock(blockStore, t1).block;
chain.add(b1); chain.add(b1);
// TX should have been seen as relevant, extracted and processed. // TX should have been seen as relevant, extracted and processed.
@ -1114,7 +1114,7 @@ public class WalletTest extends TestWithWallet {
ECKey key = new ECKey(); ECKey key = new ECKey();
Address watchedAddress = key.toAddress(params); Address watchedAddress = key.toAddress(params);
wallet.addWatchedAddress(watchedAddress); wallet.addWatchedAddress(watchedAddress);
BigInteger value = toNanoCoins(5, 0); Coin value = toNanoCoins(5, 0);
Transaction t1 = createFakeTx(params, value, watchedAddress); Transaction t1 = createFakeTx(params, value, watchedAddress);
assertTrue(wallet.isPendingTransactionRelevant(t1)); assertTrue(wallet.isPendingTransactionRelevant(t1));
} }
@ -1127,7 +1127,7 @@ public class WalletTest extends TestWithWallet {
Transaction t1 = createFakeTx(params, CENT, watchedAddress); Transaction t1 = createFakeTx(params, CENT, watchedAddress);
StoredBlock b3 = createFakeBlock(blockStore, t1).storedBlock; StoredBlock b3 = createFakeBlock(blockStore, t1).storedBlock;
wallet.receiveFromBlock(t1, b3, BlockChain.NewBlockType.BEST_CHAIN, 0); wallet.receiveFromBlock(t1, b3, BlockChain.NewBlockType.BEST_CHAIN, 0);
assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(Coin.ZERO, wallet.getBalance());
assertEquals(CENT, wallet.getWatchedBalance()); assertEquals(CENT, wallet.getWatchedBalance());
// We can't spend watched balances // We can't spend watched balances
@ -1273,11 +1273,11 @@ public class WalletTest extends TestWithWallet {
@Test @Test
public void spendOutputFromPendingTransaction() throws Exception { public void spendOutputFromPendingTransaction() throws Exception {
// We'll set up a wallet that receives a coin, then sends a coin of lesser value and keeps the change. // We'll set up a wallet that receives a coin, then sends a coin of lesser value and keeps the change.
BigInteger v1 = Utils.toNanoCoins(1, 0); Coin v1 = Utils.toNanoCoins(1, 0);
sendMoneyToWallet(v1, AbstractBlockChain.NewBlockType.BEST_CHAIN); sendMoneyToWallet(v1, AbstractBlockChain.NewBlockType.BEST_CHAIN);
// First create our current transaction // First create our current transaction
ECKey k2 = wallet.freshReceiveKey(); ECKey k2 = wallet.freshReceiveKey();
BigInteger v2 = toNanoCoins(0, 50); Coin v2 = toNanoCoins(0, 50);
Transaction t2 = new Transaction(params); Transaction t2 = new Transaction(params);
TransactionOutput o2 = new TransactionOutput(params, t2, v2, k2.toAddress(params)); TransactionOutput o2 = new TransactionOutput(params, t2, v2, k2.toAddress(params));
t2.addOutput(o2); t2.addOutput(o2);
@ -1293,7 +1293,7 @@ public class WalletTest extends TestWithWallet {
// Now try to the spend the output. // Now try to the spend the output.
ECKey k3 = new ECKey(); ECKey k3 = new ECKey();
BigInteger v3 = toNanoCoins(0, 25); Coin v3 = toNanoCoins(0, 25);
Transaction t3 = new Transaction(params); Transaction t3 = new Transaction(params);
t3.addOutput(v3, k3.toAddress(params)); t3.addOutput(v3, k3.toAddress(params));
t3.addInput(o2); t3.addInput(o2);
@ -1314,7 +1314,7 @@ public class WalletTest extends TestWithWallet {
// Check that if a pending transaction spends outputs of chain-included transactions, we mark them as spent. // Check that if a pending transaction spends outputs of chain-included transactions, we mark them as spent.
// See bug 345. This can happen if there is a pending transaction floating around and then you replay the // See bug 345. This can happen if there is a pending transaction floating around and then you replay the
// chain without emptying the memory pool (or refilling it from a peer). // chain without emptying the memory pool (or refilling it from a peer).
BigInteger value = Utils.toNanoCoins(1, 0); Coin value = Utils.toNanoCoins(1, 0);
Transaction tx1 = createFakeTx(params, value, myAddress); Transaction tx1 = createFakeTx(params, value, myAddress);
Transaction tx2 = new Transaction(params); Transaction tx2 = new Transaction(params);
tx2.addInput(tx1.getOutput(0)); tx2.addInput(tx1.getOutput(0));
@ -1325,7 +1325,7 @@ public class WalletTest extends TestWithWallet {
BlockPair bp = createFakeBlock(blockStore, tx1); BlockPair bp = createFakeBlock(blockStore, tx1);
wallet.receiveFromBlock(tx1, bp.storedBlock, AbstractBlockChain.NewBlockType.BEST_CHAIN, 0); wallet.receiveFromBlock(tx1, bp.storedBlock, AbstractBlockChain.NewBlockType.BEST_CHAIN, 0);
wallet.notifyNewBestBlock(bp.storedBlock); wallet.notifyNewBestBlock(bp.storedBlock);
assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(Coin.ZERO, wallet.getBalance());
assertEquals(1, wallet.getPoolSize(Pool.SPENT)); assertEquals(1, wallet.getPoolSize(Pool.SPENT));
assertEquals(1, wallet.getPoolSize(Pool.PENDING)); assertEquals(1, wallet.getPoolSize(Pool.PENDING));
assertEquals(0, wallet.getPoolSize(Pool.UNSPENT)); assertEquals(0, wallet.getPoolSize(Pool.UNSPENT));
@ -1461,7 +1461,7 @@ public class WalletTest extends TestWithWallet {
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
byte[] bits = new byte[20]; byte[] bits = new byte[20];
new Random().nextBytes(bits); new Random().nextBytes(bits);
BigInteger v = Utils.toNanoCoins(0, 1); Coin v = Utils.toNanoCoins(0, 1);
// 3100 outputs to a random address. // 3100 outputs to a random address.
for (int i = 0; i < 3100; i++) { for (int i = 0; i < 3100; i++) {
tx.addOutput(v, new Address(params, bits)); tx.addOutput(v, new Address(params, bits));
@ -1481,26 +1481,26 @@ public class WalletTest extends TestWithWallet {
// Generate a few outputs to us that are far too small to spend reasonably // Generate a few outputs to us that are far too small to spend reasonably
StoredBlock block = new StoredBlock(makeSolvedTestBlock(blockStore, notMyAddr), BigInteger.ONE, 1); StoredBlock block = new StoredBlock(makeSolvedTestBlock(blockStore, notMyAddr), BigInteger.ONE, 1);
Transaction tx1 = createFakeTx(params, BigInteger.ONE, myAddress); Transaction tx1 = createFakeTx(params, Coin.ONE, myAddress);
wallet.receiveFromBlock(tx1, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 0); wallet.receiveFromBlock(tx1, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 0);
Transaction tx2 = createFakeTx(params, BigInteger.ONE, myAddress); Transaction tx2 = createFakeTx(params, Coin.ONE, myAddress);
assertTrue(!tx1.getHash().equals(tx2.getHash())); assertTrue(!tx1.getHash().equals(tx2.getHash()));
wallet.receiveFromBlock(tx2, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 1); wallet.receiveFromBlock(tx2, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 1);
Transaction tx3 = createFakeTx(params, BigInteger.TEN, myAddress); Transaction tx3 = createFakeTx(params, Coin.TEN, myAddress);
wallet.receiveFromBlock(tx3, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 2); wallet.receiveFromBlock(tx3, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 2);
// Not allowed to send dust. // Not allowed to send dust.
try { try {
wallet.createSend(notMyAddr, BigInteger.ONE); wallet.createSend(notMyAddr, Coin.ONE);
fail(); fail();
} catch (Wallet.DustySendRequested e) { } catch (Wallet.DustySendRequested e) {
// Expected. // Expected.
} }
// Spend it all without fee enforcement // Spend it all without fee enforcement
SendRequest req = SendRequest.to(notMyAddr, BigInteger.TEN.add(BigInteger.ONE.add(BigInteger.ONE))); SendRequest req = SendRequest.to(notMyAddr, Coin.TEN.add(Coin.ONE.add(Coin.ONE)));
req.ensureMinRequiredFee = false; req.ensureMinRequiredFee = false;
assertNotNull(wallet.sendCoinsOffline(req)); assertNotNull(wallet.sendCoinsOffline(req));
assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(Coin.ZERO, wallet.getBalance());
// Add some reasonable-sized outputs // Add some reasonable-sized outputs
block = new StoredBlock(makeSolvedTestBlock(blockStore, notMyAddr), BigInteger.ONE, 1); block = new StoredBlock(makeSolvedTestBlock(blockStore, notMyAddr), BigInteger.ONE, 1);
@ -1508,7 +1508,7 @@ public class WalletTest extends TestWithWallet {
wallet.receiveFromBlock(tx4, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 0); wallet.receiveFromBlock(tx4, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 0);
// Simple test to make sure if we have an ouput < 0.01 we get a fee // Simple test to make sure if we have an ouput < 0.01 we get a fee
Transaction spend1 = wallet.createSend(notMyAddr, CENT.subtract(BigInteger.ONE)); Transaction spend1 = wallet.createSend(notMyAddr, CENT.subtract(Coin.ONE));
assertEquals(2, spend1.getOutputs().size()); assertEquals(2, spend1.getOutputs().size());
// We optimize for priority, so the output selected should be the largest one. // We optimize for priority, so the output selected should be the largest one.
// We should have paid the default minfee. // We should have paid the default minfee.
@ -1522,19 +1522,19 @@ public class WalletTest extends TestWithWallet {
assertEquals(Utils.COIN, spend2.getOutput(0).getValue().add(spend2.getOutput(1).getValue())); assertEquals(Utils.COIN, spend2.getOutput(0).getValue().add(spend2.getOutput(1).getValue()));
// ...but not more fee than what we request // ...but not more fee than what we request
SendRequest request3 = SendRequest.to(notMyAddr, CENT.subtract(BigInteger.ONE)); SendRequest request3 = SendRequest.to(notMyAddr, CENT.subtract(Coin.ONE));
request3.fee = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(BigInteger.ONE); request3.fee = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Coin.ONE);
wallet.completeTx(request3); wallet.completeTx(request3);
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(BigInteger.ONE), request3.fee); assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Coin.ONE), request3.fee);
Transaction spend3 = request3.tx; Transaction spend3 = request3.tx;
assertEquals(2, spend3.getOutputs().size()); assertEquals(2, spend3.getOutputs().size());
// We optimize for priority, so the output selected should be the largest one. // We optimize for priority, so the output selected should be the largest one.
assertEquals(spend3.getOutput(0).getValue().add(spend3.getOutput(1).getValue()), assertEquals(spend3.getOutput(0).getValue().add(spend3.getOutput(1).getValue()),
Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(BigInteger.ONE))); Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Coin.ONE)));
// ...unless we need it // ...unless we need it
SendRequest request4 = SendRequest.to(notMyAddr, CENT.subtract(BigInteger.ONE)); SendRequest request4 = SendRequest.to(notMyAddr, CENT.subtract(Coin.ONE));
request4.fee = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.subtract(BigInteger.ONE); request4.fee = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.subtract(Coin.ONE);
wallet.completeTx(request4); wallet.completeTx(request4);
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request4.fee); assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request4.fee);
Transaction spend4 = request4.tx; Transaction spend4 = request4.tx;
@ -1543,7 +1543,7 @@ public class WalletTest extends TestWithWallet {
assertEquals(spend4.getOutput(0).getValue().add(spend4.getOutput(1).getValue()), assertEquals(spend4.getOutput(0).getValue().add(spend4.getOutput(1).getValue()),
Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE)); Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
SendRequest request5 = SendRequest.to(notMyAddr, Utils.COIN.subtract(CENT.subtract(BigInteger.ONE))); SendRequest request5 = SendRequest.to(notMyAddr, Utils.COIN.subtract(CENT.subtract(Coin.ONE)));
wallet.completeTx(request5); wallet.completeTx(request5);
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request5.fee); assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request5.fee);
Transaction spend5 = request5.tx; Transaction spend5 = request5.tx;
@ -1555,15 +1555,15 @@ public class WalletTest extends TestWithWallet {
SendRequest request6 = SendRequest.to(notMyAddr, Utils.COIN.subtract(CENT)); SendRequest request6 = SendRequest.to(notMyAddr, Utils.COIN.subtract(CENT));
wallet.completeTx(request6); wallet.completeTx(request6);
assertEquals(BigInteger.ZERO, request6.fee); assertEquals(Coin.ZERO, request6.fee);
Transaction spend6 = request6.tx; Transaction spend6 = request6.tx;
// ...but not if change output == 0.01 // ...but not if change output == 0.01
assertEquals(2, spend6.getOutputs().size()); assertEquals(2, spend6.getOutputs().size());
// We optimize for priority, so the output selected should be the largest one // We optimize for priority, so the output selected should be the largest one
assertEquals(Utils.COIN, spend6.getOutput(0).getValue().add(spend6.getOutput(1).getValue())); assertEquals(Utils.COIN, spend6.getOutput(0).getValue().add(spend6.getOutput(1).getValue()));
SendRequest request7 = SendRequest.to(notMyAddr, Utils.COIN.subtract(CENT.subtract(BigInteger.valueOf(2)).multiply(BigInteger.valueOf(2)))); SendRequest request7 = SendRequest.to(notMyAddr, Utils.COIN.subtract(CENT.subtract(Coin.valueOf(2)).multiply(Coin.valueOf(2))));
request7.tx.addOutput(CENT.subtract(BigInteger.ONE), notMyAddr); request7.tx.addOutput(CENT.subtract(Coin.ONE), notMyAddr);
wallet.completeTx(request7); wallet.completeTx(request7);
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request7.fee); assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request7.fee);
Transaction spend7 = request7.tx; Transaction spend7 = request7.tx;
@ -1594,7 +1594,7 @@ public class WalletTest extends TestWithWallet {
Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT))); Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT)));
SendRequest request10 = SendRequest.to(notMyAddr, Utils.COIN.subtract( SendRequest request10 = SendRequest.to(notMyAddr, Utils.COIN.subtract(
Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT).add(BigInteger.ONE))); Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT).add(Coin.ONE)));
wallet.completeTx(request10); wallet.completeTx(request10);
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request10.fee); assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request10.fee);
Transaction spend10 = request10.tx; Transaction spend10 = request10.tx;
@ -1605,16 +1605,16 @@ public class WalletTest extends TestWithWallet {
Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE)); Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
SendRequest request11 = SendRequest.to(notMyAddr, Utils.COIN.subtract( SendRequest request11 = SendRequest.to(notMyAddr, Utils.COIN.subtract(
Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT).add(BigInteger.valueOf(2)))); Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT).add(Coin.valueOf(2))));
request11.fee = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(BigInteger.ONE); request11.fee = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Coin.ONE);
wallet.completeTx(request11); wallet.completeTx(request11);
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(BigInteger.ONE), request11.fee); assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Coin.ONE), request11.fee);
Transaction spend11 = request11.tx; Transaction spend11 = request11.tx;
// ...of course fee should be min(request.fee, MIN_TX_FEE) so we should get MIN_TX_FEE.add(ONE) here // ...of course fee should be min(request.fee, MIN_TX_FEE) so we should get MIN_TX_FEE.add(ONE) here
assertEquals(2, spend11.getOutputs().size()); assertEquals(2, spend11.getOutputs().size());
// We optimize for priority, so the output selected should be the largest one. // We optimize for priority, so the output selected should be the largest one.
assertEquals(spend11.getOutput(0).getValue().add(spend11.getOutput(1).getValue()), assertEquals(spend11.getOutput(0).getValue().add(spend11.getOutput(1).getValue()),
Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(BigInteger.ONE))); Utils.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Coin.ONE)));
// Remove the coin from our wallet // Remove the coin from our wallet
wallet.commitTx(spend11); wallet.commitTx(spend11);
@ -1658,30 +1658,30 @@ public class WalletTest extends TestWithWallet {
for (int i = 0; i < 29; i++) for (int i = 0; i < 29; i++)
request15.tx.addOutput(CENT, notMyAddr); request15.tx.addOutput(CENT, notMyAddr);
assertTrue(request15.tx.bitcoinSerialize().length > 1000); assertTrue(request15.tx.bitcoinSerialize().length > 1000);
request15.feePerKb = BigInteger.ONE; request15.feePerKb = Coin.ONE;
wallet.completeTx(request15); wallet.completeTx(request15);
assertEquals(BigInteger.valueOf(2), request15.fee); assertEquals(Coin.valueOf(2), request15.fee);
Transaction spend15 = request15.tx; Transaction spend15 = request15.tx;
// If a transaction is over 1kb, 2 satoshis should be added. // If a transaction is over 1kb, 2 satoshis should be added.
assertEquals(31, spend15.getOutputs().size()); assertEquals(31, spend15.getOutputs().size());
// We optimize for priority, so the output selected should be the largest one // We optimize for priority, so the output selected should be the largest one
BigInteger outValue15 = BigInteger.ZERO; Coin outValue15 = Coin.ZERO;
for (TransactionOutput out : spend15.getOutputs()) for (TransactionOutput out : spend15.getOutputs())
outValue15 = outValue15.add(out.getValue()); outValue15 = outValue15.add(out.getValue());
assertEquals(Utils.COIN.subtract(BigInteger.valueOf(2)), outValue15); assertEquals(Utils.COIN.subtract(Coin.valueOf(2)), outValue15);
SendRequest request16 = SendRequest.to(notMyAddr, CENT); SendRequest request16 = SendRequest.to(notMyAddr, CENT);
request16.feePerKb = BigInteger.ZERO; request16.feePerKb = Coin.ZERO;
for (int i = 0; i < 29; i++) for (int i = 0; i < 29; i++)
request16.tx.addOutput(CENT, notMyAddr); request16.tx.addOutput(CENT, notMyAddr);
assertTrue(request16.tx.bitcoinSerialize().length > 1000); assertTrue(request16.tx.bitcoinSerialize().length > 1000);
wallet.completeTx(request16); wallet.completeTx(request16);
// Of course the fee shouldn't be added if feePerKb == 0 // Of course the fee shouldn't be added if feePerKb == 0
assertEquals(BigInteger.ZERO, request16.fee); assertEquals(Coin.ZERO, request16.fee);
Transaction spend16 = request16.tx; Transaction spend16 = request16.tx;
assertEquals(31, spend16.getOutputs().size()); assertEquals(31, spend16.getOutputs().size());
// We optimize for priority, so the output selected should be the largest one // We optimize for priority, so the output selected should be the largest one
BigInteger outValue16 = BigInteger.ZERO; Coin outValue16 = Coin.ZERO;
for (TransactionOutput out : spend16.getOutputs()) for (TransactionOutput out : spend16.getOutputs())
outValue16 = outValue16.add(out.getValue()); outValue16 = outValue16.add(out.getValue());
assertEquals(Utils.COIN, outValue16); assertEquals(Utils.COIN, outValue16);
@ -1691,9 +1691,9 @@ public class WalletTest extends TestWithWallet {
for (int i = 0; i < 22; i++) for (int i = 0; i < 22; i++)
request17.tx.addOutput(CENT, notMyAddr); request17.tx.addOutput(CENT, notMyAddr);
request17.tx.addOutput(new TransactionOutput(params, request17.tx, CENT, new byte[15])); request17.tx.addOutput(new TransactionOutput(params, request17.tx, CENT, new byte[15]));
request17.feePerKb = BigInteger.ONE; request17.feePerKb = Coin.ONE;
wallet.completeTx(request17); wallet.completeTx(request17);
assertEquals(BigInteger.ONE, request17.fee); assertEquals(Coin.ONE, request17.fee);
assertEquals(1, request17.tx.getInputs().size()); assertEquals(1, request17.tx.getInputs().size());
// Calculate its max length to make sure it is indeed 999 // Calculate its max length to make sure it is indeed 999
int theoreticalMaxLength17 = request17.tx.bitcoinSerialize().length + myKey.getPubKey().length + 75; int theoreticalMaxLength17 = request17.tx.bitcoinSerialize().length + myKey.getPubKey().length + 75;
@ -1709,19 +1709,19 @@ public class WalletTest extends TestWithWallet {
// Now check that it got a fee of 1 since its max size is 999 (1kb). // Now check that it got a fee of 1 since its max size is 999 (1kb).
assertEquals(25, spend17.getOutputs().size()); assertEquals(25, spend17.getOutputs().size());
// We optimize for priority, so the output selected should be the largest one // We optimize for priority, so the output selected should be the largest one
BigInteger outValue17 = BigInteger.ZERO; Coin outValue17 = Coin.ZERO;
for (TransactionOutput out : spend17.getOutputs()) for (TransactionOutput out : spend17.getOutputs())
outValue17 = outValue17.add(out.getValue()); outValue17 = outValue17.add(out.getValue());
assertEquals(Utils.COIN.subtract(BigInteger.ONE), outValue17); assertEquals(Utils.COIN.subtract(Coin.ONE), outValue17);
// Create a transaction who's max size could be up to 1001 (if signatures were maximum size) // Create a transaction who's max size could be up to 1001 (if signatures were maximum size)
SendRequest request18 = SendRequest.to(notMyAddr, CENT); SendRequest request18 = SendRequest.to(notMyAddr, CENT);
for (int i = 0; i < 22; i++) for (int i = 0; i < 22; i++)
request18.tx.addOutput(CENT, notMyAddr); request18.tx.addOutput(CENT, notMyAddr);
request18.tx.addOutput(new TransactionOutput(params, request18.tx, CENT, new byte[17])); request18.tx.addOutput(new TransactionOutput(params, request18.tx, CENT, new byte[17]));
request18.feePerKb = BigInteger.ONE; request18.feePerKb = Coin.ONE;
wallet.completeTx(request18); wallet.completeTx(request18);
assertEquals(BigInteger.valueOf(2), request18.fee); assertEquals(Coin.valueOf(2), request18.fee);
assertEquals(1, request18.tx.getInputs().size()); assertEquals(1, request18.tx.getInputs().size());
// Calculate its max length to make sure it is indeed 1001 // Calculate its max length to make sure it is indeed 1001
Transaction spend18 = request18.tx; Transaction spend18 = request18.tx;
@ -1735,31 +1735,31 @@ public class WalletTest extends TestWithWallet {
// Now check that it did get a fee since its max size is 1000 // Now check that it did get a fee since its max size is 1000
assertEquals(25, spend18.getOutputs().size()); assertEquals(25, spend18.getOutputs().size());
// We optimize for priority, so the output selected should be the largest one // We optimize for priority, so the output selected should be the largest one
BigInteger outValue18 = BigInteger.ZERO; Coin outValue18 = Coin.ZERO;
for (TransactionOutput out : spend18.getOutputs()) for (TransactionOutput out : spend18.getOutputs())
outValue18 = outValue18.add(out.getValue()); outValue18 = outValue18.add(out.getValue());
assertEquals(outValue18, Utils.COIN.subtract(BigInteger.valueOf(2))); assertEquals(outValue18, Utils.COIN.subtract(Coin.valueOf(2)));
// Now create a transaction that will spend COIN + fee, which makes it require both inputs // Now create a transaction that will spend COIN + fee, which makes it require both inputs
assertEquals(wallet.getBalance(), CENT.add(Utils.COIN)); assertEquals(wallet.getBalance(), CENT.add(Utils.COIN));
SendRequest request19 = SendRequest.to(notMyAddr, CENT); SendRequest request19 = SendRequest.to(notMyAddr, CENT);
request19.feePerKb = BigInteger.ZERO; request19.feePerKb = Coin.ZERO;
for (int i = 0; i < 99; i++) for (int i = 0; i < 99; i++)
request19.tx.addOutput(CENT, notMyAddr); request19.tx.addOutput(CENT, notMyAddr);
// If we send now, we shouldn't need a fee and should only have to spend our COIN // If we send now, we shouldn't need a fee and should only have to spend our COIN
wallet.completeTx(request19); wallet.completeTx(request19);
assertEquals(BigInteger.ZERO, request19.fee); assertEquals(Coin.ZERO, request19.fee);
assertEquals(1, request19.tx.getInputs().size()); assertEquals(1, request19.tx.getInputs().size());
assertEquals(100, request19.tx.getOutputs().size()); assertEquals(100, request19.tx.getOutputs().size());
// Now reset request19 and give it a fee per kb // Now reset request19 and give it a fee per kb
request19.tx.clearInputs(); request19.tx.clearInputs();
request19 = SendRequest.forTx(request19.tx); request19 = SendRequest.forTx(request19.tx);
request19.feePerKb = BigInteger.ONE; request19.feePerKb = Coin.ONE;
request19.shuffleOutputs = false; request19.shuffleOutputs = false;
wallet.completeTx(request19); wallet.completeTx(request19);
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request19.fee); assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request19.fee);
assertEquals(2, request19.tx.getInputs().size()); assertEquals(2, request19.tx.getInputs().size());
BigInteger outValue19 = BigInteger.ZERO; Coin outValue19 = Coin.ZERO;
for (TransactionOutput out : request19.tx.getOutputs()) for (TransactionOutput out : request19.tx.getOutputs())
outValue19 = outValue19.add(out.getValue()); outValue19 = outValue19.add(out.getValue());
// But now our change output is CENT-minfee, so we have to pay min fee // But now our change output is CENT-minfee, so we have to pay min fee
@ -1768,12 +1768,12 @@ public class WalletTest extends TestWithWallet {
// Create another transaction that will spend COIN + fee, which makes it require both inputs // Create another transaction that will spend COIN + fee, which makes it require both inputs
SendRequest request20 = SendRequest.to(notMyAddr, CENT); SendRequest request20 = SendRequest.to(notMyAddr, CENT);
request20.feePerKb = BigInteger.ZERO; request20.feePerKb = Coin.ZERO;
for (int i = 0; i < 99; i++) for (int i = 0; i < 99; i++)
request20.tx.addOutput(CENT, notMyAddr); request20.tx.addOutput(CENT, notMyAddr);
// If we send now, we shouldn't have a fee and should only have to spend our COIN // If we send now, we shouldn't have a fee and should only have to spend our COIN
wallet.completeTx(request20); wallet.completeTx(request20);
assertEquals(BigInteger.ZERO, request20.fee); assertEquals(Coin.ZERO, request20.fee);
assertEquals(1, request20.tx.getInputs().size()); assertEquals(1, request20.tx.getInputs().size());
assertEquals(100, request20.tx.getOutputs().size()); assertEquals(100, request20.tx.getOutputs().size());
// Now reset request19 and give it a fee per kb // Now reset request19 and give it a fee per kb
@ -1782,18 +1782,18 @@ public class WalletTest extends TestWithWallet {
request20.feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE; request20.feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
wallet.completeTx(request20); wallet.completeTx(request20);
// 4kb tx. // 4kb tx.
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(BigInteger.valueOf(4)), request20.fee); assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(Coin.valueOf(4)), request20.fee);
assertEquals(2, request20.tx.getInputs().size()); assertEquals(2, request20.tx.getInputs().size());
BigInteger outValue20 = BigInteger.ZERO; Coin outValue20 = Coin.ZERO;
for (TransactionOutput out : request20.tx.getOutputs()) for (TransactionOutput out : request20.tx.getOutputs())
outValue20 = outValue20.add(out.getValue()); outValue20 = outValue20.add(out.getValue());
// This time the fee we wanted to pay was more, so that should be what we paid // This time the fee we wanted to pay was more, so that should be what we paid
assertEquals(outValue20, Utils.COIN.add(CENT).subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(BigInteger.valueOf(4)))); assertEquals(outValue20, Utils.COIN.add(CENT).subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(Coin.valueOf(4))));
// Same as request 19, but make the change 0 (so it doesnt force fee) and make us require min fee as a // Same as request 19, but make the change 0 (so it doesnt force fee) and make us require min fee as a
// result of an output < CENT. // result of an output < CENT.
SendRequest request21 = SendRequest.to(notMyAddr, CENT); SendRequest request21 = SendRequest.to(notMyAddr, CENT);
request21.feePerKb = BigInteger.ZERO; request21.feePerKb = Coin.ZERO;
for (int i = 0; i < 99; i++) for (int i = 0; i < 99; i++)
request21.tx.addOutput(CENT, notMyAddr); request21.tx.addOutput(CENT, notMyAddr);
request21.tx.addOutput(CENT.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE), notMyAddr); request21.tx.addOutput(CENT.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE), notMyAddr);
@ -1801,7 +1801,7 @@ public class WalletTest extends TestWithWallet {
wallet.completeTx(request21); wallet.completeTx(request21);
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request21.fee); assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request21.fee);
assertEquals(2, request21.tx.getInputs().size()); assertEquals(2, request21.tx.getInputs().size());
BigInteger outValue21 = BigInteger.ZERO; Coin outValue21 = Coin.ZERO;
for (TransactionOutput out : request21.tx.getOutputs()) for (TransactionOutput out : request21.tx.getOutputs())
outValue21 = outValue21.add(out.getValue()); outValue21 = outValue21.add(out.getValue());
assertEquals(outValue21, Utils.COIN.add(CENT).subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE)); assertEquals(outValue21, Utils.COIN.add(CENT).subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
@ -1809,30 +1809,30 @@ public class WalletTest extends TestWithWallet {
// Test feePerKb when we aren't using ensureMinRequiredFee // Test feePerKb when we aren't using ensureMinRequiredFee
// Same as request 19 // Same as request 19
SendRequest request25 = SendRequest.to(notMyAddr, CENT); SendRequest request25 = SendRequest.to(notMyAddr, CENT);
request25.feePerKb = BigInteger.ZERO; request25.feePerKb = Coin.ZERO;
for (int i = 0; i < 70; i++) for (int i = 0; i < 70; i++)
request25.tx.addOutput(CENT, notMyAddr); request25.tx.addOutput(CENT, notMyAddr);
// If we send now, we shouldn't need a fee and should only have to spend our COIN // If we send now, we shouldn't need a fee and should only have to spend our COIN
wallet.completeTx(request25); wallet.completeTx(request25);
assertEquals(BigInteger.ZERO, request25.fee); assertEquals(Coin.ZERO, request25.fee);
assertEquals(1, request25.tx.getInputs().size()); assertEquals(1, request25.tx.getInputs().size());
assertEquals(72, request25.tx.getOutputs().size()); assertEquals(72, request25.tx.getOutputs().size());
// Now reset request19 and give it a fee per kb // Now reset request19 and give it a fee per kb
request25.tx.clearInputs(); request25.tx.clearInputs();
request25 = SendRequest.forTx(request25.tx); request25 = SendRequest.forTx(request25.tx);
request25.feePerKb = CENT.divide(BigInteger.valueOf(3)); request25.feePerKb = CENT.divide(Coin.valueOf(3));
request25.ensureMinRequiredFee = false; request25.ensureMinRequiredFee = false;
request25.shuffleOutputs = false; request25.shuffleOutputs = false;
wallet.completeTx(request25); wallet.completeTx(request25);
assertEquals(CENT.subtract(BigInteger.ONE), request25.fee); assertEquals(CENT.subtract(Coin.ONE), request25.fee);
assertEquals(2, request25.tx.getInputs().size()); assertEquals(2, request25.tx.getInputs().size());
BigInteger outValue25 = BigInteger.ZERO; Coin outValue25 = Coin.ZERO;
for (TransactionOutput out : request25.tx.getOutputs()) for (TransactionOutput out : request25.tx.getOutputs())
outValue25 = outValue25.add(out.getValue()); outValue25 = outValue25.add(out.getValue());
// Our change output should be one satoshi // Our change output should be one satoshi
assertEquals(BigInteger.ONE, request25.tx.getOutput(request25.tx.getOutputs().size() - 1).getValue()); assertEquals(Coin.ONE, request25.tx.getOutput(request25.tx.getOutputs().size() - 1).getValue());
// and our fee should be CENT-1 satoshi // and our fee should be CENT-1 satoshi
assertEquals(outValue25, Utils.COIN.add(BigInteger.ONE)); assertEquals(outValue25, Utils.COIN.add(Coin.ONE));
// Spend our CENT output. // Spend our CENT output.
Transaction spendTx5 = new Transaction(params); Transaction spendTx5 = new Transaction(params);
@ -1849,14 +1849,14 @@ public class WalletTest extends TestWithWallet {
request26.tx.addOutput(CENT.subtract( request26.tx.addOutput(CENT.subtract(
Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT)), notMyAddr); Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT)), notMyAddr);
assertTrue(request26.tx.bitcoinSerialize().length > 1000); assertTrue(request26.tx.bitcoinSerialize().length > 1000);
request26.feePerKb = BigInteger.ONE; request26.feePerKb = Coin.ONE;
wallet.completeTx(request26); wallet.completeTx(request26);
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT), request26.fee); assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT), request26.fee);
Transaction spend26 = request26.tx; Transaction spend26 = request26.tx;
// If a transaction is over 1kb, the set fee should be added // If a transaction is over 1kb, the set fee should be added
assertEquals(100, spend26.getOutputs().size()); assertEquals(100, spend26.getOutputs().size());
// We optimize for priority, so the output selected should be the largest one // We optimize for priority, so the output selected should be the largest one
BigInteger outValue26 = BigInteger.ZERO; Coin outValue26 = Coin.ZERO;
for (TransactionOutput out : spend26.getOutputs()) for (TransactionOutput out : spend26.getOutputs())
outValue26 = outValue26.add(out.getValue()); outValue26 = outValue26.add(out.getValue());
assertEquals(outValue26, Utils.COIN.subtract( assertEquals(outValue26, Utils.COIN.subtract(
@ -1866,7 +1866,7 @@ public class WalletTest extends TestWithWallet {
@Test @Test
public void basicCategoryStepTest() throws Exception { public void basicCategoryStepTest() throws Exception {
// Creates spends that step through the possible fee solver categories // Creates spends that step through the possible fee solver categories
SendRequest.DEFAULT_FEE_PER_KB = BigInteger.ZERO; SendRequest.DEFAULT_FEE_PER_KB = Coin.ZERO;
// Make sure TestWithWallet isnt doing anything crazy. // Make sure TestWithWallet isnt doing anything crazy.
assertEquals(0, wallet.getTransactions(true).size()); assertEquals(0, wallet.getTransactions(true).size());
@ -1882,9 +1882,9 @@ public class WalletTest extends TestWithWallet {
} }
// Create a spend that will throw away change (category 3 type 2 in which the change causes fee which is worth more than change) // Create a spend that will throw away change (category 3 type 2 in which the change causes fee which is worth more than change)
SendRequest request1 = SendRequest.to(notMyAddr, CENT.add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE).subtract(BigInteger.ONE)); SendRequest request1 = SendRequest.to(notMyAddr, CENT.add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE).subtract(Coin.ONE));
wallet.completeTx(request1); wallet.completeTx(request1);
assertEquals(BigInteger.ONE, request1.fee); assertEquals(Coin.ONE, request1.fee);
assertEquals(request1.tx.getInputs().size(), i); // We should have spent all inputs assertEquals(request1.tx.getInputs().size(), i); // We should have spent all inputs
// Give us one more input... // Give us one more input...
@ -1893,9 +1893,9 @@ public class WalletTest extends TestWithWallet {
wallet.receiveFromBlock(tx1, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, i); wallet.receiveFromBlock(tx1, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, i);
// ... and create a spend that will throw away change (category 3 type 1 in which the change causes dust output) // ... and create a spend that will throw away change (category 3 type 1 in which the change causes dust output)
SendRequest request2 = SendRequest.to(notMyAddr, CENT.add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE).subtract(BigInteger.ONE)); SendRequest request2 = SendRequest.to(notMyAddr, CENT.add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE).subtract(Coin.ONE));
wallet.completeTx(request2); wallet.completeTx(request2);
assertEquals(BigInteger.ONE, request2.fee); assertEquals(Coin.ONE, request2.fee);
assertEquals(request2.tx.getInputs().size(), i - 1); // We should have spent all inputs - 1 assertEquals(request2.tx.getInputs().size(), i - 1); // We should have spent all inputs - 1
// Give us one more input... // Give us one more input...
@ -1905,16 +1905,16 @@ public class WalletTest extends TestWithWallet {
// ... and create a spend that will throw away change (category 3 type 1 in which the change causes dust output) // ... and create a spend that will throw away change (category 3 type 1 in which the change causes dust output)
// but that also could have been category 2 if it wanted // but that also could have been category 2 if it wanted
SendRequest request3 = SendRequest.to(notMyAddr, CENT.add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE).subtract(BigInteger.ONE)); SendRequest request3 = SendRequest.to(notMyAddr, CENT.add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE).subtract(Coin.ONE));
wallet.completeTx(request3); wallet.completeTx(request3);
assertEquals(BigInteger.ONE, request3.fee); assertEquals(Coin.ONE, request3.fee);
assertEquals(request3.tx.getInputs().size(), i - 2); // We should have spent all inputs - 2 assertEquals(request3.tx.getInputs().size(), i - 2); // We should have spent all inputs - 2
// //
SendRequest request4 = SendRequest.to(notMyAddr, CENT.add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE).subtract(BigInteger.ONE)); SendRequest request4 = SendRequest.to(notMyAddr, CENT.add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE).subtract(Coin.ONE));
request4.feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.divide(BigInteger.valueOf(request3.tx.bitcoinSerialize().length)); request4.feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.divide(Coin.valueOf(request3.tx.bitcoinSerialize().length));
wallet.completeTx(request4); wallet.completeTx(request4);
assertEquals(BigInteger.ONE, request4.fee); assertEquals(Coin.ONE, request4.fee);
assertEquals(request4.tx.getInputs().size(), i - 2); // We should have spent all inputs - 2 assertEquals(request4.tx.getInputs().size(), i - 2); // We should have spent all inputs - 2
// Give us a few more inputs... // Give us a few more inputs...
@ -1925,9 +1925,9 @@ public class WalletTest extends TestWithWallet {
} }
// ...that is just slightly less than is needed for category 1 // ...that is just slightly less than is needed for category 1
SendRequest request5 = SendRequest.to(notMyAddr, CENT.add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE).subtract(BigInteger.ONE)); SendRequest request5 = SendRequest.to(notMyAddr, CENT.add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE).subtract(Coin.ONE));
wallet.completeTx(request5); wallet.completeTx(request5);
assertEquals(BigInteger.ONE, request5.fee); assertEquals(Coin.ONE, request5.fee);
assertEquals(1, request5.tx.getOutputs().size()); // We should have no change output assertEquals(1, request5.tx.getOutputs().size()); // We should have no change output
// Give us one more input... // Give us one more input...
@ -1936,9 +1936,9 @@ public class WalletTest extends TestWithWallet {
wallet.receiveFromBlock(tx4, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, i); wallet.receiveFromBlock(tx4, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, i);
// ... that puts us in category 1 (no fee!) // ... that puts us in category 1 (no fee!)
SendRequest request6 = SendRequest.to(notMyAddr, CENT.add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE).subtract(BigInteger.ONE)); SendRequest request6 = SendRequest.to(notMyAddr, CENT.add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE).subtract(Coin.ONE));
wallet.completeTx(request6); wallet.completeTx(request6);
assertEquals(BigInteger.ZERO, request6.fee); assertEquals(Coin.ZERO, request6.fee);
assertEquals(2, request6.tx.getOutputs().size()); // We should have a change output assertEquals(2, request6.tx.getOutputs().size()); // We should have a change output
SendRequest.DEFAULT_FEE_PER_KB = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE; SendRequest.DEFAULT_FEE_PER_KB = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
@ -1956,14 +1956,14 @@ public class WalletTest extends TestWithWallet {
// Generate a ton of small outputs // Generate a ton of small outputs
StoredBlock block = new StoredBlock(makeSolvedTestBlock(blockStore, notMyAddr), BigInteger.ONE, 1); StoredBlock block = new StoredBlock(makeSolvedTestBlock(blockStore, notMyAddr), BigInteger.ONE, 1);
int i = 0; int i = 0;
while (i <= CENT.divide(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(BigInteger.TEN)).longValue()) { while (i <= CENT.divide(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(Coin.TEN)).longValue()) {
Transaction tx = createFakeTxWithChangeAddress(params, Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(BigInteger.TEN), myAddress, notMyAddr); Transaction tx = createFakeTxWithChangeAddress(params, Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(Coin.TEN), myAddress, notMyAddr);
tx.getInput(0).setSequenceNumber(i++); // Keep every transaction unique tx.getInput(0).setSequenceNumber(i++); // Keep every transaction unique
wallet.receiveFromBlock(tx, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, i); wallet.receiveFromBlock(tx, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, i);
} }
// The selector will choose 2 with MIN_TX_FEE fee // The selector will choose 2 with MIN_TX_FEE fee
SendRequest request1 = SendRequest.to(notMyAddr, CENT.add(BigInteger.ONE)); SendRequest request1 = SendRequest.to(notMyAddr, CENT.add(Coin.ONE));
wallet.completeTx(request1); wallet.completeTx(request1);
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request1.fee); assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request1.fee);
assertEquals(request1.tx.getInputs().size(), i); // We should have spent all inputs assertEquals(request1.tx.getInputs().size(), i); // We should have spent all inputs
@ -2002,16 +2002,16 @@ public class WalletTest extends TestWithWallet {
wallet.receiveFromBlock(tx, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 0); wallet.receiveFromBlock(tx, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 0);
Transaction tx2 = createFakeTx(params, CENT, myAddress); Transaction tx2 = createFakeTx(params, CENT, myAddress);
wallet.receiveFromBlock(tx2, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 1); wallet.receiveFromBlock(tx2, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 1);
Transaction tx3 = createFakeTx(params, BigInteger.ONE, myAddress); Transaction tx3 = createFakeTx(params, Coin.ONE, myAddress);
wallet.receiveFromBlock(tx3, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 2); wallet.receiveFromBlock(tx3, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 2);
// Create a transaction who's max size could be up to 1000 (if signatures were maximum size) // Create a transaction who's max size could be up to 1000 (if signatures were maximum size)
SendRequest request1 = SendRequest.to(notMyAddr, Utils.COIN.subtract(CENT.multiply(BigInteger.valueOf(17)))); SendRequest request1 = SendRequest.to(notMyAddr, Utils.COIN.subtract(CENT.multiply(Coin.valueOf(17))));
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
request1.tx.addOutput(CENT, notMyAddr); request1.tx.addOutput(CENT, notMyAddr);
request1.tx.addOutput(new TransactionOutput(params, request1.tx, CENT, new byte[16])); request1.tx.addOutput(new TransactionOutput(params, request1.tx, CENT, new byte[16]));
request1.fee = BigInteger.ONE; request1.fee = Coin.ONE;
request1.feePerKb = BigInteger.ONE; request1.feePerKb = Coin.ONE;
// We get a category 2 using COIN+CENT // We get a category 2 using COIN+CENT
// It spends COIN + 1(fee) and because its output is thus < CENT, we have to pay MIN_TX_FEE // It spends COIN + 1(fee) and because its output is thus < CENT, we have to pay MIN_TX_FEE
// When it tries category 1, its too large and requires COIN + 2 (fee) // When it tries category 1, its too large and requires COIN + 2 (fee)
@ -2021,18 +2021,18 @@ public class WalletTest extends TestWithWallet {
assertEquals(2, request1.tx.getInputs().size()); assertEquals(2, request1.tx.getInputs().size());
// We then add one more satoshi output to the wallet // We then add one more satoshi output to the wallet
Transaction tx4 = createFakeTx(params, BigInteger.ONE, myAddress); Transaction tx4 = createFakeTx(params, Coin.ONE, myAddress);
wallet.receiveFromBlock(tx4, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 3); wallet.receiveFromBlock(tx4, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 3);
// Create a transaction who's max size could be up to 1000 (if signatures were maximum size) // Create a transaction who's max size could be up to 1000 (if signatures were maximum size)
SendRequest request2 = SendRequest.to(notMyAddr, Utils.COIN.subtract(CENT.multiply(BigInteger.valueOf(17)))); SendRequest request2 = SendRequest.to(notMyAddr, Utils.COIN.subtract(CENT.multiply(Coin.valueOf(17))));
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
request2.tx.addOutput(CENT, notMyAddr); request2.tx.addOutput(CENT, notMyAddr);
request2.tx.addOutput(new TransactionOutput(params, request2.tx, CENT, new byte[16])); request2.tx.addOutput(new TransactionOutput(params, request2.tx, CENT, new byte[16]));
request2.feePerKb = BigInteger.ONE; request2.feePerKb = Coin.ONE;
// The process is the same as above, but now we can complete category 1 with one more input, and pay a fee of 2 // The process is the same as above, but now we can complete category 1 with one more input, and pay a fee of 2
wallet.completeTx(request2); wallet.completeTx(request2);
assertEquals(BigInteger.valueOf(2), request2.fee); assertEquals(Coin.valueOf(2), request2.fee);
assertEquals(4, request2.tx.getInputs().size()); assertEquals(4, request2.tx.getInputs().size());
} }
@ -2107,7 +2107,7 @@ public class WalletTest extends TestWithWallet {
// Check that if a wallet listener throws an exception, the others still run. // Check that if a wallet listener throws an exception, the others still run.
wallet.addEventListener(new AbstractWalletEventListener() { wallet.addEventListener(new AbstractWalletEventListener() {
@Override @Override
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
log.info("onCoinsReceived 1"); log.info("onCoinsReceived 1");
throw new RuntimeException("barf"); throw new RuntimeException("barf");
} }
@ -2115,7 +2115,7 @@ public class WalletTest extends TestWithWallet {
final AtomicInteger flag = new AtomicInteger(); final AtomicInteger flag = new AtomicInteger();
wallet.addEventListener(new AbstractWalletEventListener() { wallet.addEventListener(new AbstractWalletEventListener() {
@Override @Override
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
log.info("onCoinsReceived 2"); log.info("onCoinsReceived 2");
flag.incrementAndGet(); flag.incrementAndGet();
} }
@ -2134,13 +2134,13 @@ public class WalletTest extends TestWithWallet {
StoredBlock block = new StoredBlock(makeSolvedTestBlock(blockStore, new ECKey().toAddress(params)), BigInteger.ONE, 1); StoredBlock block = new StoredBlock(makeSolvedTestBlock(blockStore, new ECKey().toAddress(params)), BigInteger.ONE, 1);
Random rng = new Random(); Random rng = new Random();
for (int i = 0; i < rng.nextInt(100) + 1; i++) { for (int i = 0; i < rng.nextInt(100) + 1; i++) {
Transaction tx = createFakeTx(params, BigInteger.valueOf(rng.nextInt((int) Utils.COIN.longValue())), myAddress); Transaction tx = createFakeTx(params, Coin.valueOf(rng.nextInt((int) Utils.COIN.longValue())), myAddress);
wallet.receiveFromBlock(tx, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, i); wallet.receiveFromBlock(tx, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, i);
} }
SendRequest request = SendRequest.emptyWallet(new ECKey().toAddress(params)); SendRequest request = SendRequest.emptyWallet(new ECKey().toAddress(params));
wallet.completeTx(request); wallet.completeTx(request);
wallet.commitTx(request.tx); wallet.commitTx(request.tx);
assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(Coin.ZERO, wallet.getBalance());
} }
@Test @Test
@ -2153,7 +2153,7 @@ public class WalletTest extends TestWithWallet {
SendRequest request = SendRequest.emptyWallet(outputKey); SendRequest request = SendRequest.emptyWallet(outputKey);
wallet.completeTx(request); wallet.completeTx(request);
wallet.commitTx(request.tx); wallet.commitTx(request.tx);
assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(Coin.ZERO, wallet.getBalance());
assertEquals(CENT, request.tx.getOutput(0).getValue()); assertEquals(CENT, request.tx.getOutput(0).getValue());
// Add 1 confirmed cent and 1 unconfirmed cent. Verify only one cent is emptied because of the coin selection // Add 1 confirmed cent and 1 unconfirmed cent. Verify only one cent is emptied because of the coin selection
@ -2166,22 +2166,22 @@ public class WalletTest extends TestWithWallet {
request = SendRequest.emptyWallet(outputKey); request = SendRequest.emptyWallet(outputKey);
wallet.completeTx(request); wallet.completeTx(request);
wallet.commitTx(request.tx); wallet.commitTx(request.tx);
assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(Coin.ZERO, wallet.getBalance());
assertEquals(CENT, request.tx.getOutput(0).getValue()); assertEquals(CENT, request.tx.getOutput(0).getValue());
// Add just under 0.01 // Add just under 0.01
StoredBlock block2 = new StoredBlock(block.getHeader().createNextBlock(outputKey), BigInteger.ONE, 2); StoredBlock block2 = new StoredBlock(block.getHeader().createNextBlock(outputKey), BigInteger.ONE, 2);
tx = createFakeTx(params, CENT.subtract(BigInteger.ONE), myAddress); tx = createFakeTx(params, CENT.subtract(Coin.ONE), myAddress);
wallet.receiveFromBlock(tx, block2, AbstractBlockChain.NewBlockType.BEST_CHAIN, 0); wallet.receiveFromBlock(tx, block2, AbstractBlockChain.NewBlockType.BEST_CHAIN, 0);
request = SendRequest.emptyWallet(outputKey); request = SendRequest.emptyWallet(outputKey);
wallet.completeTx(request); wallet.completeTx(request);
wallet.commitTx(request.tx); wallet.commitTx(request.tx);
assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(Coin.ZERO, wallet.getBalance());
assertEquals(CENT.subtract(BigInteger.ONE).subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE), request.tx.getOutput(0).getValue()); assertEquals(CENT.subtract(Coin.ONE).subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE), request.tx.getOutput(0).getValue());
// Add an unsendable value // Add an unsendable value
StoredBlock block3 = new StoredBlock(block2.getHeader().createNextBlock(outputKey), BigInteger.ONE, 3); StoredBlock block3 = new StoredBlock(block2.getHeader().createNextBlock(outputKey), BigInteger.ONE, 3);
BigInteger outputValue = Transaction.MIN_NONDUST_OUTPUT.add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE).subtract(BigInteger.ONE); Coin outputValue = Transaction.MIN_NONDUST_OUTPUT.add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE).subtract(Coin.ONE);
tx = createFakeTx(params, outputValue, myAddress); tx = createFakeTx(params, outputValue, myAddress);
wallet.receiveFromBlock(tx, block3, AbstractBlockChain.NewBlockType.BEST_CHAIN, 0); wallet.receiveFromBlock(tx, block3, AbstractBlockChain.NewBlockType.BEST_CHAIN, 0);
request = SendRequest.emptyWallet(outputKey); request = SendRequest.emptyWallet(outputKey);
@ -2192,7 +2192,7 @@ public class WalletTest extends TestWithWallet {
request.ensureMinRequiredFee = false; request.ensureMinRequiredFee = false;
wallet.completeTx(request); wallet.completeTx(request);
wallet.commitTx(request.tx); wallet.commitTx(request.tx);
assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(Coin.ZERO, wallet.getBalance());
assertEquals(outputValue, request.tx.getOutput(0).getValue()); assertEquals(outputValue, request.tx.getOutput(0).getValue());
} }
@ -2220,7 +2220,7 @@ public class WalletTest extends TestWithWallet {
wallet.setKeyRotationTime(compromiseTime); wallet.setKeyRotationTime(compromiseTime);
assertTrue(wallet.isKeyRotating(key1)); assertTrue(wallet.isKeyRotating(key1));
Transaction tx = broadcaster.waitForTransaction(); Transaction tx = broadcaster.waitForTransaction();
final BigInteger THREE_CENTS = CENT.add(CENT).add(CENT); final Coin THREE_CENTS = CENT.add(CENT).add(CENT);
assertEquals(THREE_CENTS, tx.getValueSentFromMe(wallet)); assertEquals(THREE_CENTS, tx.getValueSentFromMe(wallet));
assertEquals(THREE_CENTS.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE), tx.getValueSentToMe(wallet)); assertEquals(THREE_CENTS.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE), tx.getValueSentToMe(wallet));
// TX is a raw pay to pubkey. // TX is a raw pay to pubkey.
@ -2281,11 +2281,11 @@ public class WalletTest extends TestWithWallet {
wallet.setKeyRotationTime(compromise); wallet.setKeyRotationTime(compromise);
Transaction tx = broadcaster.waitForTransaction(); Transaction tx = broadcaster.waitForTransaction();
final BigInteger valueSentToMe = tx.getValueSentToMe(wallet); final Coin valueSentToMe = tx.getValueSentToMe(wallet);
BigInteger fee = tx.getValueSentFromMe(wallet).subtract(valueSentToMe); Coin fee = tx.getValueSentFromMe(wallet).subtract(valueSentToMe);
assertEquals(BigInteger.valueOf(900000), fee); assertEquals(Coin.valueOf(900000), fee);
assertEquals(KeyTimeCoinSelector.MAX_SIMULTANEOUS_INPUTS, tx.getInputs().size()); assertEquals(KeyTimeCoinSelector.MAX_SIMULTANEOUS_INPUTS, tx.getInputs().size());
assertEquals(BigInteger.valueOf(599100000), valueSentToMe); assertEquals(Coin.valueOf(599100000), valueSentToMe);
tx = broadcaster.waitForTransaction(); tx = broadcaster.waitForTransaction();
assertNotNull(tx); assertNotNull(tx);
@ -2347,11 +2347,11 @@ public class WalletTest extends TestWithWallet {
} }
}); });
assertTrue(wallet.isPendingTransactionRelevant(tx)); assertTrue(wallet.isPendingTransactionRelevant(tx));
assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(Coin.ZERO, wallet.getBalance());
assertEquals(BigInteger.ZERO, wallet.getBalance(Wallet.BalanceType.ESTIMATED)); assertEquals(Coin.ZERO, wallet.getBalance(Wallet.BalanceType.ESTIMATED));
wallet.receivePending(tx, null); wallet.receivePending(tx, null);
assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(Coin.ZERO, wallet.getBalance());
assertEquals(BigInteger.ZERO, wallet.getBalance(Wallet.BalanceType.ESTIMATED)); assertEquals(Coin.ZERO, wallet.getBalance(Wallet.BalanceType.ESTIMATED));
assertTrue(bool.get()); assertTrue(bool.get());
// Confirm it in the same manner as how Bloom filtered blocks do. Verify it shows up. // Confirm it in the same manner as how Bloom filtered blocks do. Verify it shows up.
StoredBlock block = createFakeBlock(blockStore, tx).storedBlock; StoredBlock block = createFakeBlock(blockStore, tx).storedBlock;

View File

@ -33,7 +33,6 @@ import javax.annotation.Nullable;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.math.BigInteger;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.util.Arrays; import java.util.Arrays;
@ -116,7 +115,7 @@ public class ChannelConnectionTest extends TestWithWallet {
// Test with network code and without any issues. We'll broadcast two txns: multisig contract and settle transaction. // Test with network code and without any issues. We'll broadcast two txns: multisig contract and settle transaction.
final SettableFuture<ListenableFuture<PaymentChannelServerState>> serverCloseFuture = SettableFuture.create(); final SettableFuture<ListenableFuture<PaymentChannelServerState>> serverCloseFuture = SettableFuture.create();
final SettableFuture<Sha256Hash> channelOpenFuture = SettableFuture.create(); final SettableFuture<Sha256Hash> channelOpenFuture = SettableFuture.create();
final BlockingQueue<BigInteger> q = new LinkedBlockingQueue<BigInteger>(); final BlockingQueue<Coin> q = new LinkedBlockingQueue<Coin>();
final PaymentChannelServerListener server = new PaymentChannelServerListener(mockBroadcaster, serverWallet, 30, Utils.COIN, final PaymentChannelServerListener server = new PaymentChannelServerListener(mockBroadcaster, serverWallet, 30, Utils.COIN,
new PaymentChannelServerListener.HandlerFactory() { new PaymentChannelServerListener.HandlerFactory() {
@Nullable @Nullable
@ -129,7 +128,7 @@ public class ChannelConnectionTest extends TestWithWallet {
} }
@Override @Override
public void paymentIncrease(BigInteger by, BigInteger to) { public void paymentIncrease(Coin by, Coin to) {
q.add(to); q.add(to);
} }
@ -169,7 +168,7 @@ public class ChannelConnectionTest extends TestWithWallet {
}); });
Thread.sleep(1250); // No timeouts once the channel is open Thread.sleep(1250); // No timeouts once the channel is open
BigInteger amount = client.state().getValueSpent(); Coin amount = client.state().getValueSpent();
assertEquals(amount, q.take()); assertEquals(amount, q.take());
client.incrementPayment(Utils.CENT).get(); client.incrementPayment(Utils.CENT).get();
amount = amount.add(Utils.CENT); amount = amount.add(Utils.CENT);
@ -193,7 +192,7 @@ public class ChannelConnectionTest extends TestWithWallet {
broadcastTxPause.release(); broadcastTxPause.release();
Transaction settleTx = broadcasts.take(); Transaction settleTx = broadcasts.take();
assertEquals(PaymentChannelServerState.State.CLOSED, serverState.getState()); assertEquals(PaymentChannelServerState.State.CLOSED, serverState.getState());
if (!serverState.getBestValueToMe().equals(amount) || !serverState.getFeePaid().equals(BigInteger.ZERO)) if (!serverState.getBestValueToMe().equals(amount) || !serverState.getFeePaid().equals(Coin.ZERO))
fail(); fail();
assertTrue(channels.mapChannels.isEmpty()); assertTrue(channels.mapChannels.isEmpty());
@ -282,7 +281,7 @@ public class ChannelConnectionTest extends TestWithWallet {
server.receiveMessage(pair.clientRecorder.checkNextMsg(MessageType.CLIENT_VERSION)); server.receiveMessage(pair.clientRecorder.checkNextMsg(MessageType.CLIENT_VERSION));
client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.SERVER_VERSION)); client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.SERVER_VERSION));
final Protos.TwoWayChannelMessage initiateMsg = pair.serverRecorder.checkNextMsg(MessageType.INITIATE); final Protos.TwoWayChannelMessage initiateMsg = pair.serverRecorder.checkNextMsg(MessageType.INITIATE);
BigInteger minPayment = BigInteger.valueOf(initiateMsg.getInitiate().getMinPayment()); Coin minPayment = Coin.valueOf(initiateMsg.getInitiate().getMinPayment());
client.receiveMessage(initiateMsg); client.receiveMessage(initiateMsg);
server.receiveMessage(pair.clientRecorder.checkNextMsg(MessageType.PROVIDE_REFUND)); server.receiveMessage(pair.clientRecorder.checkNextMsg(MessageType.PROVIDE_REFUND));
client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.RETURN_REFUND)); client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.RETURN_REFUND));
@ -297,7 +296,7 @@ public class ChannelConnectionTest extends TestWithWallet {
assertNull(pair.clientRecorder.q.poll()); assertNull(pair.clientRecorder.q.poll());
assertEquals(minPayment, client.state().getValueSpent()); assertEquals(minPayment, client.state().getValueSpent());
// Send a bitcent. // Send a bitcent.
BigInteger amount = minPayment.add(Utils.CENT); Coin amount = minPayment.add(Utils.CENT);
client.incrementPayment(Utils.CENT); client.incrementPayment(Utils.CENT);
server.receiveMessage(pair.clientRecorder.checkNextMsg(MessageType.UPDATE_PAYMENT)); server.receiveMessage(pair.clientRecorder.checkNextMsg(MessageType.UPDATE_PAYMENT));
assertEquals(amount, pair.serverRecorder.q.take()); assertEquals(amount, pair.serverRecorder.q.take());
@ -463,7 +462,7 @@ public class ChannelConnectionTest extends TestWithWallet {
assertEquals(CloseReason.NO_ACCEPTABLE_VERSION, pair.clientRecorder.q.take()); assertEquals(CloseReason.NO_ACCEPTABLE_VERSION, pair.clientRecorder.q.take());
// Double-check that we cant do anything that requires an open channel // Double-check that we cant do anything that requires an open channel
try { try {
client.incrementPayment(BigInteger.ONE); client.incrementPayment(Coin.ONE);
fail(); fail();
} catch (IllegalStateException e) { } } catch (IllegalStateException e) { }
} }
@ -489,7 +488,7 @@ public class ChannelConnectionTest extends TestWithWallet {
assertEquals(CloseReason.TIME_WINDOW_TOO_LARGE, pair.clientRecorder.q.take()); assertEquals(CloseReason.TIME_WINDOW_TOO_LARGE, pair.clientRecorder.q.take());
// Double-check that we cant do anything that requires an open channel // Double-check that we cant do anything that requires an open channel
try { try {
client.incrementPayment(BigInteger.ONE); client.incrementPayment(Coin.ONE);
fail(); fail();
} catch (IllegalStateException e) { } } catch (IllegalStateException e) { }
} }
@ -505,7 +504,7 @@ public class ChannelConnectionTest extends TestWithWallet {
client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.SERVER_VERSION)); client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.SERVER_VERSION));
client.receiveMessage(Protos.TwoWayChannelMessage.newBuilder() client.receiveMessage(Protos.TwoWayChannelMessage.newBuilder()
.setInitiate(Protos.Initiate.newBuilder().setExpireTimeSecs(Utils.currentTimeSeconds()) .setInitiate(Protos.Initiate.newBuilder().setExpireTimeSecs(Utils.currentTimeSeconds())
.setMinAcceptedChannelSize(Utils.COIN.add(BigInteger.ONE).longValue()) .setMinAcceptedChannelSize(Utils.COIN.add(Coin.ONE).longValue())
.setMultisigKey(ByteString.copyFrom(new ECKey().getPubKey())) .setMultisigKey(ByteString.copyFrom(new ECKey().getPubKey()))
.setMinPayment(Transaction.MIN_NONDUST_OUTPUT.longValue())) .setMinPayment(Transaction.MIN_NONDUST_OUTPUT.longValue()))
.setType(MessageType.INITIATE).build()); .setType(MessageType.INITIATE).build());
@ -513,17 +512,17 @@ public class ChannelConnectionTest extends TestWithWallet {
assertEquals(CloseReason.SERVER_REQUESTED_TOO_MUCH_VALUE, pair.clientRecorder.q.take()); assertEquals(CloseReason.SERVER_REQUESTED_TOO_MUCH_VALUE, pair.clientRecorder.q.take());
// Double-check that we cant do anything that requires an open channel // Double-check that we cant do anything that requires an open channel
try { try {
client.incrementPayment(BigInteger.ONE); client.incrementPayment(Coin.ONE);
fail(); fail();
} catch (IllegalStateException e) { } } catch (IllegalStateException e) { }
// Now check that if the server has a lower min size than what we are willing to spend, we do actually open // Now check that if the server has a lower min size than what we are willing to spend, we do actually open
// a channel of that size. // a channel of that size.
sendMoneyToWallet(Utils.COIN.multiply(BigInteger.TEN), AbstractBlockChain.NewBlockType.BEST_CHAIN); sendMoneyToWallet(Utils.COIN.multiply(Coin.TEN), AbstractBlockChain.NewBlockType.BEST_CHAIN);
pair = ChannelTestUtils.makeRecorders(serverWallet, mockBroadcaster); pair = ChannelTestUtils.makeRecorders(serverWallet, mockBroadcaster);
server = pair.server; server = pair.server;
final BigInteger myValue = Utils.COIN.multiply(BigInteger.TEN); final Coin myValue = Utils.COIN.multiply(Coin.TEN);
client = new PaymentChannelClient(wallet, myKey, myValue, Sha256Hash.ZERO_HASH, pair.clientRecorder); client = new PaymentChannelClient(wallet, myKey, myValue, Sha256Hash.ZERO_HASH, pair.clientRecorder);
client.connectionOpen(); client.connectionOpen();
server.connectionOpen(); server.connectionOpen();
@ -531,7 +530,7 @@ public class ChannelConnectionTest extends TestWithWallet {
client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.SERVER_VERSION)); client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.SERVER_VERSION));
client.receiveMessage(Protos.TwoWayChannelMessage.newBuilder() client.receiveMessage(Protos.TwoWayChannelMessage.newBuilder()
.setInitiate(Protos.Initiate.newBuilder().setExpireTimeSecs(Utils.currentTimeSeconds()) .setInitiate(Protos.Initiate.newBuilder().setExpireTimeSecs(Utils.currentTimeSeconds())
.setMinAcceptedChannelSize(Utils.COIN.add(BigInteger.ONE).longValue()) .setMinAcceptedChannelSize(Utils.COIN.add(Coin.ONE).longValue())
.setMultisigKey(ByteString.copyFrom(new ECKey().getPubKey())) .setMultisigKey(ByteString.copyFrom(new ECKey().getPubKey()))
.setMinPayment(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.longValue())) .setMinPayment(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.longValue()))
.setType(MessageType.INITIATE).build()); .setType(MessageType.INITIATE).build());
@ -644,8 +643,8 @@ public class ChannelConnectionTest extends TestWithWallet {
server.receiveMessage(pair.clientRecorder.checkNextMsg(MessageType.UPDATE_PAYMENT)); server.receiveMessage(pair.clientRecorder.checkNextMsg(MessageType.UPDATE_PAYMENT));
broadcasts.take(); broadcasts.take();
// The channel is now empty. // The channel is now empty.
assertEquals(BigInteger.ZERO, client.state().getValueRefunded()); assertEquals(Coin.ZERO, client.state().getValueRefunded());
pair.serverRecorder.q.take(); // Take the BigInteger. pair.serverRecorder.q.take(); // Take the Coin.
client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.PAYMENT_ACK)); client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.PAYMENT_ACK));
client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.CLOSE)); client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.CLOSE));
assertEquals(CloseReason.SERVER_REQUESTED_CLOSE, pair.clientRecorder.q.take()); assertEquals(CloseReason.SERVER_REQUESTED_CLOSE, pair.clientRecorder.q.take());
@ -684,7 +683,7 @@ public class ChannelConnectionTest extends TestWithWallet {
pair.clientRecorder.checkInitiated(); pair.clientRecorder.checkInitiated();
assertNull(pair.serverRecorder.q.poll()); assertNull(pair.serverRecorder.q.poll());
assertNull(pair.clientRecorder.q.poll()); assertNull(pair.clientRecorder.q.poll());
ListenableFuture<BigInteger> future = client.incrementPayment(Utils.CENT); ListenableFuture<Coin> future = client.incrementPayment(Utils.CENT);
server.receiveMessage(pair.clientRecorder.checkNextMsg(MessageType.UPDATE_PAYMENT)); server.receiveMessage(pair.clientRecorder.checkNextMsg(MessageType.UPDATE_PAYMENT));
pair.serverRecorder.q.take(); pair.serverRecorder.q.take();
client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.PAYMENT_ACK)); client.receiveMessage(pair.serverRecorder.checkNextMsg(MessageType.PAYMENT_ACK));

View File

@ -1,12 +1,13 @@
package com.google.bitcoin.protocols.channels; package com.google.bitcoin.protocols.channels;
import com.google.bitcoin.core.Coin;
import com.google.bitcoin.core.Sha256Hash; import com.google.bitcoin.core.Sha256Hash;
import com.google.bitcoin.core.TransactionBroadcaster; import com.google.bitcoin.core.TransactionBroadcaster;
import com.google.bitcoin.core.Utils; import com.google.bitcoin.core.Utils;
import com.google.bitcoin.core.Wallet; import com.google.bitcoin.core.Wallet;
import org.bitcoin.paymentchannel.Protos; import org.bitcoin.paymentchannel.Protos;
import java.math.BigInteger;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
@ -35,7 +36,7 @@ public class ChannelTestUtils {
} }
@Override @Override
public void paymentIncrease(BigInteger by, BigInteger to) { public void paymentIncrease(Coin by, Coin to) {
q.add(to); q.add(to);
} }
@ -49,8 +50,8 @@ public class ChannelTestUtils {
return msg; return msg;
} }
public void checkTotalPayment(BigInteger valueSoFar) throws InterruptedException { public void checkTotalPayment(Coin valueSoFar) throws InterruptedException {
BigInteger lastSeen = (BigInteger) q.take(); Coin lastSeen = (Coin) q.take();
assertEquals(lastSeen, valueSoFar); assertEquals(lastSeen, valueSoFar);
} }
} }

View File

@ -40,7 +40,7 @@ import static org.junit.Assert.*;
public class PaymentChannelStateTest extends TestWithWallet { public class PaymentChannelStateTest extends TestWithWallet {
private ECKey serverKey; private ECKey serverKey;
private BigInteger halfCoin; private Coin halfCoin;
private Wallet serverWallet; private Wallet serverWallet;
private PaymentChannelServerState serverState; private PaymentChannelServerState serverState;
private PaymentChannelClientState clientState; private PaymentChannelClientState clientState;
@ -94,7 +94,7 @@ public class PaymentChannelStateTest extends TestWithWallet {
@Test @Test
public void stateErrors() throws Exception { public void stateErrors() throws Exception {
PaymentChannelClientState channelState = new PaymentChannelClientState(wallet, myKey, serverKey, PaymentChannelClientState channelState = new PaymentChannelClientState(wallet, myKey, serverKey,
Utils.COIN.multiply(BigInteger.TEN), 20); Utils.COIN.multiply(Coin.TEN), 20);
assertEquals(PaymentChannelClientState.State.NEW, channelState.getState()); assertEquals(PaymentChannelClientState.State.NEW, channelState.getState());
try { try {
channelState.getMultisigContract(); channelState.getMultisigContract();
@ -164,8 +164,8 @@ public class PaymentChannelStateTest extends TestWithWallet {
assertFalse(clientWalletMultisigContract.getInput(0).getConnectedOutput().getSpentBy().getParentTransaction().getHash().equals(refund.getHash())); assertFalse(clientWalletMultisigContract.getInput(0).getConnectedOutput().getSpentBy().getParentTransaction().getHash().equals(refund.getHash()));
// Both client and server are now in the ready state. Simulate a few micropayments of 0.005 bitcoins. // Both client and server are now in the ready state. Simulate a few micropayments of 0.005 bitcoins.
BigInteger size = halfCoin.divide(BigInteger.TEN).divide(BigInteger.TEN); Coin size = halfCoin.divide(Coin.TEN).divide(Coin.TEN);
BigInteger totalPayment = BigInteger.ZERO; Coin totalPayment = Coin.ZERO;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
byte[] signature = clientState.incrementPaymentBy(size).signature.encodeToBitcoin(); byte[] signature = clientState.incrementPaymentBy(size).signature.encodeToBitcoin();
totalPayment = totalPayment.add(size); totalPayment = totalPayment.add(size);
@ -194,10 +194,10 @@ public class PaymentChannelStateTest extends TestWithWallet {
// Create a block with the payment transaction in it and give it to both wallets // Create a block with the payment transaction in it and give it to both wallets
chain.add(makeSolvedTestBlock(blockStore.getChainHead().getHeader(), reserializedCloseTx)); chain.add(makeSolvedTestBlock(blockStore.getChainHead().getHeader(), reserializedCloseTx));
assertEquals(size.multiply(BigInteger.valueOf(5)), serverWallet.getBalance()); assertEquals(size.multiply(Coin.valueOf(5)), serverWallet.getBalance());
assertEquals(0, serverWallet.getPendingTransactions().size()); assertEquals(0, serverWallet.getPendingTransactions().size());
assertEquals(Utils.COIN.subtract(size.multiply(BigInteger.valueOf(5))), wallet.getBalance()); assertEquals(Utils.COIN.subtract(size.multiply(Coin.valueOf(5))), wallet.getBalance());
assertEquals(0, wallet.getPendingTransactions().size()); assertEquals(0, wallet.getPendingTransactions().size());
assertEquals(3, wallet.getTransactions(false).size()); assertEquals(3, wallet.getTransactions(false).size());
@ -218,7 +218,7 @@ public class PaymentChannelStateTest extends TestWithWallet {
// Spend the client wallet's one coin // Spend the client wallet's one coin
Transaction spendCoinTx = wallet.sendCoinsOffline(Wallet.SendRequest.to(new ECKey().toAddress(params), Utils.COIN)); Transaction spendCoinTx = wallet.sendCoinsOffline(Wallet.SendRequest.to(new ECKey().toAddress(params), Utils.COIN));
assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(Coin.ZERO, wallet.getBalance());
chain.add(makeSolvedTestBlock(blockStore.getChainHead().getHeader(), spendCoinTx, createFakeTx(params, Utils.CENT, myAddress))); chain.add(makeSolvedTestBlock(blockStore.getChainHead().getHeader(), spendCoinTx, createFakeTx(params, Utils.CENT, myAddress)));
assertEquals(Utils.CENT, wallet.getBalance()); assertEquals(Utils.CENT, wallet.getBalance());
@ -233,12 +233,12 @@ public class PaymentChannelStateTest extends TestWithWallet {
assertEquals(PaymentChannelServerState.State.WAITING_FOR_REFUND_TRANSACTION, serverState.getState()); assertEquals(PaymentChannelServerState.State.WAITING_FOR_REFUND_TRANSACTION, serverState.getState());
clientState = new PaymentChannelClientState(wallet, myKey, ECKey.fromPublicOnly(serverKey.getPubKey()), clientState = new PaymentChannelClientState(wallet, myKey, ECKey.fromPublicOnly(serverKey.getPubKey()),
Utils.CENT.divide(BigInteger.valueOf(2)), EXPIRE_TIME); Utils.CENT.divide(Coin.valueOf(2)), EXPIRE_TIME);
assertEquals(PaymentChannelClientState.State.NEW, clientState.getState()); assertEquals(PaymentChannelClientState.State.NEW, clientState.getState());
assertEquals(Utils.CENT.divide(BigInteger.valueOf(2)), clientState.getTotalValue()); assertEquals(Utils.CENT.divide(Coin.valueOf(2)), clientState.getTotalValue());
clientState.initiate(); clientState.initiate();
// We will have to pay min_tx_fee twice - both the multisig contract and the refund tx // We will have to pay min_tx_fee twice - both the multisig contract and the refund tx
assertEquals(clientState.getRefundTxFees(), Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(BigInteger.valueOf(2))); assertEquals(clientState.getRefundTxFees(), Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(Coin.valueOf(2)));
assertEquals(PaymentChannelClientState.State.INITIATED, clientState.getState()); assertEquals(PaymentChannelClientState.State.INITIATED, clientState.getState());
// Send the refund tx from client to server and get back the signature. // Send the refund tx from client to server and get back the signature.
@ -269,8 +269,8 @@ public class PaymentChannelStateTest extends TestWithWallet {
assertEquals(PaymentChannelServerState.State.READY, serverState.getState()); assertEquals(PaymentChannelServerState.State.READY, serverState.getState());
// Pay a tiny bit // Pay a tiny bit
serverState.incrementPayment(Utils.CENT.divide(BigInteger.valueOf(2)).subtract(Utils.CENT.divide(BigInteger.TEN)), serverState.incrementPayment(Utils.CENT.divide(Coin.valueOf(2)).subtract(Utils.CENT.divide(Coin.TEN)),
clientState.incrementPaymentBy(Utils.CENT.divide(BigInteger.TEN)).signature.encodeToBitcoin()); clientState.incrementPaymentBy(Utils.CENT.divide(Coin.TEN)).signature.encodeToBitcoin());
// Advance time until our we get close enough to lock time that server should rebroadcast // Advance time until our we get close enough to lock time that server should rebroadcast
Utils.rollMockClock(60*60*22); Utils.rollMockClock(60*60*22);
@ -313,7 +313,7 @@ public class PaymentChannelStateTest extends TestWithWallet {
chain.add(makeSolvedTestBlock(blockStore.getChainHead().getHeader(), multisigContract,clientBroadcastedRefund)); chain.add(makeSolvedTestBlock(blockStore.getChainHead().getHeader(), multisigContract,clientBroadcastedRefund));
// Make sure we actually had to pay what initialize() told us we would // Make sure we actually had to pay what initialize() told us we would
assertEquals(wallet.getBalance(), Utils.CENT.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(BigInteger.valueOf(2)))); assertEquals(wallet.getBalance(), Utils.CENT.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(Coin.valueOf(2))));
try { try {
// After its expired, we cant still increment payment // After its expired, we cant still increment payment
@ -341,7 +341,7 @@ public class PaymentChannelStateTest extends TestWithWallet {
// Test refund transaction with any number of issues // Test refund transaction with any number of issues
byte[] refundTxBytes = clientState.getIncompleteRefundTransaction().bitcoinSerialize(); byte[] refundTxBytes = clientState.getIncompleteRefundTransaction().bitcoinSerialize();
Transaction refund = new Transaction(params, refundTxBytes); Transaction refund = new Transaction(params, refundTxBytes);
refund.addOutput(BigInteger.ZERO, new ECKey().toAddress(params)); refund.addOutput(Coin.ZERO, new ECKey().toAddress(params));
try { try {
serverState.provideRefundTransaction(refund, myKey.getPubKey()); serverState.provideRefundTransaction(refund, myKey.getPubKey());
fail(); fail();
@ -408,7 +408,7 @@ public class PaymentChannelStateTest extends TestWithWallet {
clientState.fakeSave(); clientState.fakeSave();
assertEquals(PaymentChannelClientState.State.PROVIDE_MULTISIG_CONTRACT_TO_SERVER, clientState.getState()); assertEquals(PaymentChannelClientState.State.PROVIDE_MULTISIG_CONTRACT_TO_SERVER, clientState.getState());
try { clientState.incrementPaymentBy(BigInteger.ONE); fail(); } catch (IllegalStateException e) {} try { clientState.incrementPaymentBy(Coin.ONE); fail(); } catch (IllegalStateException e) {}
byte[] multisigContractSerialized = clientState.getMultisigContract().bitcoinSerialize(); byte[] multisigContractSerialized = clientState.getMultisigContract().bitcoinSerialize();
@ -424,7 +424,7 @@ public class PaymentChannelStateTest extends TestWithWallet {
multisigContract = new Transaction(params, multisigContractSerialized); multisigContract = new Transaction(params, multisigContractSerialized);
multisigContract.clearOutputs(); multisigContract.clearOutputs();
multisigContract.addOutput(BigInteger.ZERO, ScriptBuilder.createMultiSigOutputScript(2, Lists.newArrayList(myKey, serverKey))); multisigContract.addOutput(Coin.ZERO, ScriptBuilder.createMultiSigOutputScript(2, Lists.newArrayList(myKey, serverKey)));
try { try {
serverState.provideMultiSigContract(multisigContract); serverState.provideMultiSigContract(multisigContract);
fail(); fail();
@ -451,8 +451,8 @@ public class PaymentChannelStateTest extends TestWithWallet {
assertEquals(PaymentChannelServerState.State.READY, serverState.getState()); assertEquals(PaymentChannelServerState.State.READY, serverState.getState());
// Both client and server are now in the ready state. Simulate a few micropayments of 0.005 bitcoins. // Both client and server are now in the ready state. Simulate a few micropayments of 0.005 bitcoins.
BigInteger size = halfCoin.divide(BigInteger.TEN).divide(BigInteger.TEN); Coin size = halfCoin.divide(Coin.TEN).divide(Coin.TEN);
BigInteger totalPayment = BigInteger.ZERO; Coin totalPayment = Coin.ZERO;
try { try {
clientState.incrementPaymentBy(Utils.COIN); clientState.incrementPaymentBy(Utils.COIN);
fail(); fail();
@ -510,12 +510,12 @@ public class PaymentChannelStateTest extends TestWithWallet {
assertEquals(serverState.getBestValueToMe(), totalPayment); assertEquals(serverState.getBestValueToMe(), totalPayment);
try { try {
clientState.incrementPaymentBy(BigInteger.ONE.negate()); clientState.incrementPaymentBy(Coin.ONE.negate());
fail(); fail();
} catch (ValueOutOfRangeException e) {} } catch (ValueOutOfRangeException e) {}
try { try {
clientState.incrementPaymentBy(halfCoin.subtract(size).add(BigInteger.ONE)); clientState.incrementPaymentBy(halfCoin.subtract(size).add(Coin.ONE));
fail(); fail();
} catch (ValueOutOfRangeException e) {} } catch (ValueOutOfRangeException e) {}
} }
@ -526,7 +526,7 @@ public class PaymentChannelStateTest extends TestWithWallet {
// Spend the client wallet's one coin // Spend the client wallet's one coin
wallet.sendCoinsOffline(Wallet.SendRequest.to(new ECKey().toAddress(params), Utils.COIN)); wallet.sendCoinsOffline(Wallet.SendRequest.to(new ECKey().toAddress(params), Utils.COIN));
assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(Coin.ZERO, wallet.getBalance());
chain.add(makeSolvedTestBlock(blockStore.getChainHead().getHeader(), createFakeTx(params, Utils.CENT, myAddress))); chain.add(makeSolvedTestBlock(blockStore.getChainHead().getHeader(), createFakeTx(params, Utils.CENT, myAddress)));
assertEquals(Utils.CENT, wallet.getBalance()); assertEquals(Utils.CENT, wallet.getBalance());
@ -538,7 +538,7 @@ public class PaymentChannelStateTest extends TestWithWallet {
assertEquals(PaymentChannelServerState.State.WAITING_FOR_REFUND_TRANSACTION, serverState.getState()); assertEquals(PaymentChannelServerState.State.WAITING_FOR_REFUND_TRANSACTION, serverState.getState());
// Clearly ONE is far too small to be useful // Clearly ONE is far too small to be useful
clientState = new PaymentChannelClientState(wallet, myKey, ECKey.fromPublicOnly(serverKey.getPubKey()), BigInteger.ONE, EXPIRE_TIME); clientState = new PaymentChannelClientState(wallet, myKey, ECKey.fromPublicOnly(serverKey.getPubKey()), Coin.ONE, EXPIRE_TIME);
assertEquals(PaymentChannelClientState.State.NEW, clientState.getState()); assertEquals(PaymentChannelClientState.State.NEW, clientState.getState());
try { try {
clientState.initiate(); clientState.initiate();
@ -546,7 +546,7 @@ public class PaymentChannelStateTest extends TestWithWallet {
} catch (ValueOutOfRangeException e) {} } catch (ValueOutOfRangeException e) {}
clientState = new PaymentChannelClientState(wallet, myKey, ECKey.fromPublicOnly(serverKey.getPubKey()), clientState = new PaymentChannelClientState(wallet, myKey, ECKey.fromPublicOnly(serverKey.getPubKey()),
Transaction.MIN_NONDUST_OUTPUT.subtract(BigInteger.ONE).add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE), Transaction.MIN_NONDUST_OUTPUT.subtract(Coin.ONE).add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE),
EXPIRE_TIME); EXPIRE_TIME);
assertEquals(PaymentChannelClientState.State.NEW, clientState.getState()); assertEquals(PaymentChannelClientState.State.NEW, clientState.getState());
try { try {
@ -560,14 +560,14 @@ public class PaymentChannelStateTest extends TestWithWallet {
assertEquals(PaymentChannelClientState.State.NEW, clientState.getState()); assertEquals(PaymentChannelClientState.State.NEW, clientState.getState());
// We'll have to pay REFERENCE_DEFAULT_MIN_TX_FEE twice (multisig+refund), and we'll end up getting back nearly nothing... // We'll have to pay REFERENCE_DEFAULT_MIN_TX_FEE twice (multisig+refund), and we'll end up getting back nearly nothing...
clientState.initiate(); clientState.initiate();
assertEquals(clientState.getRefundTxFees(), Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(BigInteger.valueOf(2))); assertEquals(clientState.getRefundTxFees(), Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(Coin.valueOf(2)));
assertEquals(PaymentChannelClientState.State.INITIATED, clientState.getState()); assertEquals(PaymentChannelClientState.State.INITIATED, clientState.getState());
// Now actually use a more useful CENT // Now actually use a more useful CENT
clientState = new PaymentChannelClientState(wallet, myKey, ECKey.fromPublicOnly(serverKey.getPubKey()), Utils.CENT, EXPIRE_TIME); clientState = new PaymentChannelClientState(wallet, myKey, ECKey.fromPublicOnly(serverKey.getPubKey()), Utils.CENT, EXPIRE_TIME);
assertEquals(PaymentChannelClientState.State.NEW, clientState.getState()); assertEquals(PaymentChannelClientState.State.NEW, clientState.getState());
clientState.initiate(); clientState.initiate();
assertEquals(clientState.getRefundTxFees(), BigInteger.ZERO); assertEquals(clientState.getRefundTxFees(), Coin.ZERO);
assertEquals(PaymentChannelClientState.State.INITIATED, clientState.getState()); assertEquals(PaymentChannelClientState.State.INITIATED, clientState.getState());
// Send the refund tx from client to server and get back the signature. // Send the refund tx from client to server and get back the signature.
@ -592,16 +592,16 @@ public class PaymentChannelStateTest extends TestWithWallet {
assertEquals(PaymentChannelServerState.State.READY, serverState.getState()); assertEquals(PaymentChannelServerState.State.READY, serverState.getState());
// Both client and server are now in the ready state. Simulate a few micropayments // Both client and server are now in the ready state. Simulate a few micropayments
BigInteger totalPayment = BigInteger.ZERO; Coin totalPayment = Coin.ZERO;
// We can send as little as we want - its up to the server to get the fees right // We can send as little as we want - its up to the server to get the fees right
byte[] signature = clientState.incrementPaymentBy(BigInteger.ONE).signature.encodeToBitcoin(); byte[] signature = clientState.incrementPaymentBy(Coin.ONE).signature.encodeToBitcoin();
totalPayment = totalPayment.add(BigInteger.ONE); totalPayment = totalPayment.add(Coin.ONE);
serverState.incrementPayment(Utils.CENT.subtract(totalPayment), signature); serverState.incrementPayment(Utils.CENT.subtract(totalPayment), signature);
// We can't refund more than the contract is worth... // We can't refund more than the contract is worth...
try { try {
serverState.incrementPayment(Utils.CENT.add(BigInteger.ONE), signature); serverState.incrementPayment(Utils.CENT.add(Coin.ONE), signature);
fail(); fail();
} catch (ValueOutOfRangeException e) {} } catch (ValueOutOfRangeException e) {}
@ -609,12 +609,12 @@ public class PaymentChannelStateTest extends TestWithWallet {
// will correct it for us to be larger than the requested amount, to make the change output zero. // will correct it for us to be larger than the requested amount, to make the change output zero.
PaymentChannelClientState.IncrementedPayment payment = PaymentChannelClientState.IncrementedPayment payment =
clientState.incrementPaymentBy(Utils.CENT.subtract(Transaction.MIN_NONDUST_OUTPUT)); clientState.incrementPaymentBy(Utils.CENT.subtract(Transaction.MIN_NONDUST_OUTPUT));
assertEquals(Utils.CENT.subtract(BigInteger.ONE), payment.amount); assertEquals(Utils.CENT.subtract(Coin.ONE), payment.amount);
totalPayment = totalPayment.add(payment.amount); totalPayment = totalPayment.add(payment.amount);
// The server also won't accept it if we do that. // The server also won't accept it if we do that.
try { try {
serverState.incrementPayment(Transaction.MIN_NONDUST_OUTPUT.subtract(BigInteger.ONE), signature); serverState.incrementPayment(Transaction.MIN_NONDUST_OUTPUT.subtract(Coin.ONE), signature);
fail(); fail();
} catch (ValueOutOfRangeException e) {} } catch (ValueOutOfRangeException e) {}
@ -678,9 +678,9 @@ public class PaymentChannelStateTest extends TestWithWallet {
assertEquals(PaymentChannelServerState.State.READY, serverState.getState()); assertEquals(PaymentChannelServerState.State.READY, serverState.getState());
// Both client and server are now in the ready state, split the channel in half // Both client and server are now in the ready state, split the channel in half
byte[] signature = clientState.incrementPaymentBy(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.subtract(BigInteger.ONE)) byte[] signature = clientState.incrementPaymentBy(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.subtract(Coin.ONE))
.signature.encodeToBitcoin(); .signature.encodeToBitcoin();
BigInteger totalRefund = Utils.CENT.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.subtract(BigInteger.ONE)); Coin totalRefund = Utils.CENT.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.subtract(Coin.ONE));
serverState.incrementPayment(totalRefund, signature); serverState.incrementPayment(totalRefund, signature);
// We need to pay MIN_TX_FEE, but we only have MIN_NONDUST_OUTPUT // We need to pay MIN_TX_FEE, but we only have MIN_NONDUST_OUTPUT
@ -703,8 +703,8 @@ public class PaymentChannelStateTest extends TestWithWallet {
assertTrue(e.getMessage().contains("more in fees")); assertTrue(e.getMessage().contains("more in fees"));
} }
signature = clientState.incrementPaymentBy(BigInteger.ONE.shiftLeft(1)).signature.encodeToBitcoin(); signature = clientState.incrementPaymentBy(Coin.ONE.shiftLeft(1)).signature.encodeToBitcoin();
totalRefund = totalRefund.subtract(BigInteger.ONE.shiftLeft(1)); totalRefund = totalRefund.subtract(Coin.ONE.shiftLeft(1));
serverState.incrementPayment(totalRefund, signature); serverState.incrementPayment(totalRefund, signature);
// And settle the channel. // And settle the channel.
@ -772,8 +772,8 @@ public class PaymentChannelStateTest extends TestWithWallet {
assertFalse(clientWalletMultisigContract.getInput(0).getConnectedOutput().getSpentBy().getParentTransaction().getHash().equals(refund.getHash())); assertFalse(clientWalletMultisigContract.getInput(0).getConnectedOutput().getSpentBy().getParentTransaction().getHash().equals(refund.getHash()));
// Both client and server are now in the ready state. Simulate a few micropayments of 0.005 bitcoins. // Both client and server are now in the ready state. Simulate a few micropayments of 0.005 bitcoins.
BigInteger size = halfCoin.divide(BigInteger.TEN).divide(BigInteger.TEN); Coin size = halfCoin.divide(Coin.TEN).divide(Coin.TEN);
BigInteger totalPayment = BigInteger.ZERO; Coin totalPayment = Coin.ZERO;
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
byte[] signature = clientState.incrementPaymentBy(size).signature.encodeToBitcoin(); byte[] signature = clientState.incrementPaymentBy(size).signature.encodeToBitcoin();
totalPayment = totalPayment.add(size); totalPayment = totalPayment.add(size);

View File

@ -20,7 +20,6 @@ import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import java.math.BigInteger;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.PrivateKey; import java.security.PrivateKey;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
@ -35,6 +34,7 @@ import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import com.google.bitcoin.core.Address; import com.google.bitcoin.core.Address;
import com.google.bitcoin.core.Coin;
import com.google.bitcoin.core.ECKey; import com.google.bitcoin.core.ECKey;
import com.google.bitcoin.core.NetworkParameters; import com.google.bitcoin.core.NetworkParameters;
import com.google.bitcoin.core.Transaction; import com.google.bitcoin.core.Transaction;
@ -50,7 +50,7 @@ public class PaymentProtocolTest {
// static test data // static test data
private static final NetworkParameters NETWORK_PARAMS = UnitTestParams.get(); private static final NetworkParameters NETWORK_PARAMS = UnitTestParams.get();
private static final BigInteger AMOUNT = BigInteger.ONE; private static final Coin AMOUNT = Coin.ONE;
private static final Address TO_ADDRESS = new ECKey().toAddress(NETWORK_PARAMS); private static final Address TO_ADDRESS = new ECKey().toAddress(NETWORK_PARAMS);
private static final String MEMO = "memo"; private static final String MEMO = "memo";
private static final String PAYMENT_URL = "https://example.com"; private static final String PAYMENT_URL = "https://example.com";
@ -128,7 +128,7 @@ public class PaymentProtocolTest {
// Create // Create
List<Transaction> transactions = new LinkedList<Transaction>(); List<Transaction> transactions = new LinkedList<Transaction>();
transactions.add(FakeTxBuilder.createFakeTx(NETWORK_PARAMS, AMOUNT, TO_ADDRESS)); transactions.add(FakeTxBuilder.createFakeTx(NETWORK_PARAMS, AMOUNT, TO_ADDRESS));
BigInteger refundAmount = BigInteger.ONE; Coin refundAmount = Coin.ONE;
Address refundAddress = new ECKey().toAddress(NETWORK_PARAMS); Address refundAddress = new ECKey().toAddress(NETWORK_PARAMS);
Payment payment = PaymentProtocol.createPaymentMessage(transactions, refundAmount, refundAddress, MEMO, Payment payment = PaymentProtocol.createPaymentMessage(transactions, refundAmount, refundAddress, MEMO,
MERCHANT_DATA); MERCHANT_DATA);

View File

@ -28,7 +28,6 @@ import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import java.io.InputStream; import java.io.InputStream;
import java.math.BigInteger;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
@ -45,7 +44,7 @@ public class PaymentSessionTest {
private ECKey serverKey; private ECKey serverKey;
private Transaction tx; private Transaction tx;
private TransactionOutput outputToMe; private TransactionOutput outputToMe;
BigInteger nanoCoins = Utils.toNanoCoins(1, 0); Coin nanoCoins = Utils.toNanoCoins(1, 0);
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
@ -97,7 +96,7 @@ public class PaymentSessionTest {
.setSerializedPaymentDetails(paymentDetails.toByteString()) .setSerializedPaymentDetails(paymentDetails.toByteString())
.build(); .build();
MockPaymentSession paymentSession = new MockPaymentSession(paymentRequest); MockPaymentSession paymentSession = new MockPaymentSession(paymentRequest);
assertEquals(BigInteger.ZERO, paymentSession.getValue()); assertEquals(Coin.ZERO, paymentSession.getValue());
assertNull(paymentSession.getPaymentUrl()); assertNull(paymentSession.getPaymentUrl());
assertNull(paymentSession.getMemo()); assertNull(paymentSession.getMemo());
} }

View File

@ -74,7 +74,7 @@ public class WalletProtobufSerializerTest {
// Check the base case of a wallet with one key and no transactions. // Check the base case of a wallet with one key and no transactions.
Wallet wallet1 = roundTrip(myWallet); Wallet wallet1 = roundTrip(myWallet);
assertEquals(0, wallet1.getTransactions(true).size()); assertEquals(0, wallet1.getTransactions(true).size());
assertEquals(BigInteger.ZERO, wallet1.getBalance()); assertEquals(Coin.ZERO, wallet1.getBalance());
assertArrayEquals(myKey.getPubKey(), assertArrayEquals(myKey.getPubKey(),
wallet1.findKeyFromPubHash(myKey.getPubKeyHash()).getPubKey()); wallet1.findKeyFromPubHash(myKey.getPubKeyHash()).getPubKey());
assertArrayEquals(myKey.getPrivKeyBytes(), assertArrayEquals(myKey.getPrivKeyBytes(),
@ -92,7 +92,7 @@ public class WalletProtobufSerializerTest {
@Test @Test
public void oneTx() throws Exception { public void oneTx() throws Exception {
// Check basic tx serialization. // Check basic tx serialization.
BigInteger v1 = Utils.toNanoCoins(1, 0); Coin v1 = Utils.toNanoCoins(1, 0);
Transaction t1 = createFakeTx(params, v1, myAddress); Transaction t1 = createFakeTx(params, v1, myAddress);
t1.getConfidence().markBroadcastBy(new PeerAddress(InetAddress.getByName("1.2.3.4"))); t1.getConfidence().markBroadcastBy(new PeerAddress(InetAddress.getByName("1.2.3.4")));
t1.getConfidence().markBroadcastBy(new PeerAddress(InetAddress.getByName("5.6.7.8"))); t1.getConfidence().markBroadcastBy(new PeerAddress(InetAddress.getByName("5.6.7.8")));
@ -136,7 +136,7 @@ public class WalletProtobufSerializerTest {
assertEquals(1, wallet1.getTransactions(true).size()); assertEquals(1, wallet1.getTransactions(true).size());
Transaction t1 = wallet1.getTransaction(doubleSpends.t1.getHash()); Transaction t1 = wallet1.getTransaction(doubleSpends.t1.getHash());
assertEquals(ConfidenceType.DEAD, t1.getConfidence().getConfidenceType()); assertEquals(ConfidenceType.DEAD, t1.getConfidence().getConfidenceType());
assertEquals(BigInteger.ZERO, wallet1.getBalance()); assertEquals(Coin.ZERO, wallet1.getBalance());
// TODO: Wallet should store overriding transactions even if they are not wallet-relevant. // TODO: Wallet should store overriding transactions even if they are not wallet-relevant.
// assertEquals(doubleSpends.t2, t1.getConfidence().getOverridingTransaction()); // assertEquals(doubleSpends.t2, t1.getConfidence().getOverridingTransaction());
@ -192,7 +192,7 @@ public class WalletProtobufSerializerTest {
final ArrayList<Transaction> txns = new ArrayList<Transaction>(2); final ArrayList<Transaction> txns = new ArrayList<Transaction>(2);
myWallet.addEventListener(new AbstractWalletEventListener() { myWallet.addEventListener(new AbstractWalletEventListener() {
@Override @Override
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
txns.add(tx); txns.add(tx);
} }
}); });
@ -275,7 +275,7 @@ public class WalletProtobufSerializerTest {
public void testRoundTripNormalWallet() throws Exception { public void testRoundTripNormalWallet() throws Exception {
Wallet wallet1 = roundTrip(myWallet); Wallet wallet1 = roundTrip(myWallet);
assertEquals(0, wallet1.getTransactions(true).size()); assertEquals(0, wallet1.getTransactions(true).size());
assertEquals(BigInteger.ZERO, wallet1.getBalance()); assertEquals(Coin.ZERO, wallet1.getBalance());
assertArrayEquals(myKey.getPubKey(), assertArrayEquals(myKey.getPubKey(),
wallet1.findKeyFromPubHash(myKey.getPubKeyHash()).getPubKey()); wallet1.findKeyFromPubHash(myKey.getPubKeyHash()).getPubKey());
assertArrayEquals(myKey.getPrivKeyBytes(), assertArrayEquals(myKey.getPrivKeyBytes(),

View File

@ -25,7 +25,6 @@ import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import java.math.BigInteger;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.ArrayList; import java.util.ArrayList;
@ -97,7 +96,7 @@ public class DefaultCoinSelectorTest extends TestWithWallet {
Transaction t1 = checkNotNull(sendMoneyToWallet(Utils.COIN, AbstractBlockChain.NewBlockType.BEST_CHAIN)); Transaction t1 = checkNotNull(sendMoneyToWallet(Utils.COIN, AbstractBlockChain.NewBlockType.BEST_CHAIN));
// Padding block. // Padding block.
wallet.notifyNewBestBlock(FakeTxBuilder.createFakeBlock(blockStore).storedBlock); wallet.notifyNewBestBlock(FakeTxBuilder.createFakeBlock(blockStore).storedBlock);
final BigInteger TWO_COINS = Utils.COIN.multiply(BigInteger.valueOf(2)); final Coin TWO_COINS = Utils.COIN.multiply(Coin.valueOf(2));
Transaction t2 = checkNotNull(sendMoneyToWallet(TWO_COINS, AbstractBlockChain.NewBlockType.BEST_CHAIN)); Transaction t2 = checkNotNull(sendMoneyToWallet(TWO_COINS, AbstractBlockChain.NewBlockType.BEST_CHAIN));
Transaction t3 = checkNotNull(sendMoneyToWallet(Utils.CENT, AbstractBlockChain.NewBlockType.BEST_CHAIN)); Transaction t3 = checkNotNull(sendMoneyToWallet(Utils.CENT, AbstractBlockChain.NewBlockType.BEST_CHAIN));

View File

@ -17,8 +17,6 @@
package com.google.bitcoin.wallet; package com.google.bitcoin.wallet;
import java.math.BigInteger;
import com.google.bitcoin.core.*; import com.google.bitcoin.core.*;
import com.google.bitcoin.params.MainNetParams; import com.google.bitcoin.params.MainNetParams;
import com.google.bitcoin.script.ScriptBuilder; import com.google.bitcoin.script.ScriptBuilder;
@ -136,7 +134,7 @@ public class DefaultRiskAnalysisTest {
Transaction dustTx = new Transaction(params); Transaction dustTx = new Transaction(params);
dustTx.addInput(params.getGenesisBlock().getTransactions().get(0).getOutput(0)); dustTx.addInput(params.getGenesisBlock().getTransactions().get(0).getOutput(0));
dustTx.addOutput(BigInteger.ONE, key1); // 1 Satoshi dustTx.addOutput(Coin.ONE, key1); // 1 Satoshi
assertEquals(RiskAnalysis.Result.NON_STANDARD, DefaultRiskAnalysis.FACTORY.create(wallet, dustTx, NO_DEPS).analyze()); assertEquals(RiskAnalysis.Result.NON_STANDARD, DefaultRiskAnalysis.FACTORY.create(wallet, dustTx, NO_DEPS).analyze());
Transaction edgeCaseTx = new Transaction(params); Transaction edgeCaseTx = new Transaction(params);

View File

@ -7,7 +7,6 @@ import com.google.bitcoin.utils.BriefLogFormatter;
import com.google.bitcoin.utils.Threading; import com.google.bitcoin.utils.Threading;
import java.io.File; import java.io.File;
import java.math.BigInteger;
/** /**
* This is a little test app that waits for a coin on a local regtest node, then generates two transactions that double * This is a little test app that waits for a coin on a local regtest node, then generates two transactions that double
@ -28,7 +27,7 @@ public class DoubleSpend {
kit.wallet().getBalanceFuture(Utils.COIN, Wallet.BalanceType.AVAILABLE).get(); kit.wallet().getBalanceFuture(Utils.COIN, Wallet.BalanceType.AVAILABLE).get();
Transaction tx1 = kit.wallet().createSend(new Address(params, "muYPFNCv7KQEG2ZLM7Z3y96kJnNyXJ53wm"), Utils.CENT); Transaction tx1 = kit.wallet().createSend(new Address(params, "muYPFNCv7KQEG2ZLM7Z3y96kJnNyXJ53wm"), Utils.CENT);
Transaction tx2 = kit.wallet().createSend(new Address(params, "muYPFNCv7KQEG2ZLM7Z3y96kJnNyXJ53wm"), Utils.CENT.add(BigInteger.TEN)); Transaction tx2 = kit.wallet().createSend(new Address(params, "muYPFNCv7KQEG2ZLM7Z3y96kJnNyXJ53wm"), Utils.CENT.add(Coin.TEN));
final Peer peer = kit.peerGroup().getConnectedPeers().get(0); final Peer peer = kit.peerGroup().getConnectedPeers().get(0);
peer.addEventListener(new AbstractPeerEventListener() { peer.addEventListener(new AbstractPeerEventListener() {
@Override @Override

View File

@ -34,14 +34,13 @@ import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.math.BigInteger;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.List; import java.util.List;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import static com.google.bitcoin.core.Coin.TEN;
import static com.google.bitcoin.core.Utils.CENT; import static com.google.bitcoin.core.Utils.CENT;
import static java.math.BigInteger.TEN;
/** /**
* Simple client that connects to the given host, opens a channel, and pays one cent. * Simple client that connects to the given host, opens a channel, and pays one cent.
@ -49,7 +48,7 @@ import static java.math.BigInteger.TEN;
public class ExamplePaymentChannelClient { public class ExamplePaymentChannelClient {
private static final org.slf4j.Logger log = LoggerFactory.getLogger(ExamplePaymentChannelClient.class); private static final org.slf4j.Logger log = LoggerFactory.getLogger(ExamplePaymentChannelClient.class);
private WalletAppKit appKit; private WalletAppKit appKit;
private final BigInteger channelSize; private final Coin channelSize;
private final ECKey myKey; private final ECKey myKey;
private final NetworkParameters params; private final NetworkParameters params;
@ -124,7 +123,7 @@ public class ExamplePaymentChannelClient {
// we are not allowed to have payment channels that pay nothing at all. // we are not allowed to have payment channels that pay nothing at all.
log.info("Success! Trying to make {} micropayments. Already paid {} satoshis on this channel", log.info("Success! Trying to make {} micropayments. Already paid {} satoshis on this channel",
times, client.state().getValueSpent()); times, client.state().getValueSpent());
final BigInteger MICROPAYMENT_SIZE = CENT.divide(TEN); final Coin MICROPAYMENT_SIZE = CENT.divide(TEN);
for (int i = 0; i < times; i++) { for (int i = 0; i < times; i++) {
try { try {
// Wait because the act of making a micropayment is async, and we're not allowed to overlap. // Wait because the act of making a micropayment is async, and we're not allowed to overlap.
@ -164,11 +163,11 @@ public class ExamplePaymentChannelClient {
latch.await(); latch.await();
} }
private void waitForSufficientBalance(BigInteger amount) { private void waitForSufficientBalance(Coin amount) {
// Not enough money in the wallet. // Not enough money in the wallet.
BigInteger amountPlusFee = amount.add(Wallet.SendRequest.DEFAULT_FEE_PER_KB); Coin amountPlusFee = amount.add(Wallet.SendRequest.DEFAULT_FEE_PER_KB);
// ESTIMATED because we don't really need to wait for confirmation. // ESTIMATED because we don't really need to wait for confirmation.
ListenableFuture<BigInteger> balanceFuture = appKit.wallet().getBalanceFuture(amountPlusFee, Wallet.BalanceType.ESTIMATED); ListenableFuture<Coin> balanceFuture = appKit.wallet().getBalanceFuture(amountPlusFee, Wallet.BalanceType.ESTIMATED);
if (!balanceFuture.isDone()) { if (!balanceFuture.isDone()) {
System.out.println("Please send " + Utils.bitcoinValueToFriendlyString(amountPlusFee) + System.out.println("Please send " + Utils.bitcoinValueToFriendlyString(amountPlusFee) +
" BTC to " + myKey.toAddress(params)); " BTC to " + myKey.toAddress(params));

View File

@ -17,6 +17,7 @@
package com.google.bitcoin.examples; package com.google.bitcoin.examples;
import com.google.bitcoin.core.Coin;
import com.google.bitcoin.core.NetworkParameters; import com.google.bitcoin.core.NetworkParameters;
import com.google.bitcoin.core.Sha256Hash; import com.google.bitcoin.core.Sha256Hash;
import com.google.bitcoin.core.VerificationException; import com.google.bitcoin.core.VerificationException;
@ -26,10 +27,10 @@ import com.google.bitcoin.params.RegTestParams;
import com.google.bitcoin.protocols.channels.*; import com.google.bitcoin.protocols.channels.*;
import com.google.bitcoin.utils.BriefLogFormatter; import com.google.bitcoin.utils.BriefLogFormatter;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.math.BigInteger;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.util.List; import java.util.List;
@ -71,7 +72,7 @@ public class ExamplePaymentChannelServer implements PaymentChannelServerListener
// We provide a peer group, a wallet, a timeout in seconds, the amount we require to start a channel and // We provide a peer group, a wallet, a timeout in seconds, the amount we require to start a channel and
// an implementation of HandlerFactory, which we just implement ourselves. // an implementation of HandlerFactory, which we just implement ourselves.
final int MILLI = 100000; final int MILLI = 100000;
new PaymentChannelServerListener(appKit.peerGroup(), appKit.wallet(), 15, BigInteger.valueOf(MILLI), this).bindAndStart(4242); new PaymentChannelServerListener(appKit.peerGroup(), appKit.wallet(), 15, Coin.valueOf(MILLI), this).bindAndStart(4242);
} }
@Override @Override
@ -101,7 +102,7 @@ public class ExamplePaymentChannelServer implements PaymentChannelServerListener
} }
@Override @Override
public void paymentIncrease(BigInteger by, BigInteger to) { public void paymentIncrease(Coin by, Coin to) {
log.info("Client {} paid increased payment by {} for a total of " + to.toString(), clientAddress, by); log.info("Client {} paid increased payment by {} for a total of " + to.toString(), clientAddress, by);
} }

View File

@ -29,7 +29,6 @@ import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.MoreExecutors;
import java.io.File; import java.io.File;
import java.math.BigInteger;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -81,11 +80,11 @@ public class ForwardingService {
// We want to know when we receive money. // We want to know when we receive money.
kit.wallet().addEventListener(new AbstractWalletEventListener() { kit.wallet().addEventListener(new AbstractWalletEventListener() {
@Override @Override
public void onCoinsReceived(Wallet w, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { public void onCoinsReceived(Wallet w, Transaction tx, Coin prevBalance, Coin newBalance) {
// Runs in the dedicated "user thread" (see bitcoinj docs for more info on this). // Runs in the dedicated "user thread" (see bitcoinj docs for more info on this).
// //
// The transaction "tx" can either be pending, or included into a block (we didn't see the broadcast). // The transaction "tx" can either be pending, or included into a block (we didn't see the broadcast).
BigInteger value = tx.getValueSentToMe(w); Coin value = tx.getValueSentToMe(w);
System.out.println("Received tx for " + Utils.bitcoinValueToFriendlyString(value) + ": " + tx); System.out.println("Received tx for " + Utils.bitcoinValueToFriendlyString(value) + ": " + tx);
System.out.println("Transaction will be forwarded after it confirms."); System.out.println("Transaction will be forwarded after it confirms.");
// Wait until it's made it into the block chain (may run immediately if it's already there). // Wait until it's made it into the block chain (may run immediately if it's already there).
@ -121,10 +120,10 @@ public class ForwardingService {
private static void forwardCoins(Transaction tx) { private static void forwardCoins(Transaction tx) {
try { try {
BigInteger value = tx.getValueSentToMe(kit.wallet()); Coin value = tx.getValueSentToMe(kit.wallet());
System.out.println("Forwarding " + Utils.bitcoinValueToFriendlyString(value) + " BTC"); System.out.println("Forwarding " + Utils.bitcoinValueToFriendlyString(value) + " BTC");
// Now send the coins back! Send with a small fee attached to ensure rapid confirmation. // Now send the coins back! Send with a small fee attached to ensure rapid confirmation.
final BigInteger amountToSend = value.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE); final Coin amountToSend = value.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE);
final Wallet.SendResult sendResult = kit.wallet().sendCoins(kit.peerGroup(), forwardingAddress, amountToSend); final Wallet.SendResult sendResult = kit.wallet().sendCoins(kit.peerGroup(), forwardingAddress, amountToSend);
checkNotNull(sendResult); // We should never try to send more coins than we have! checkNotNull(sendResult); // We should never try to send more coins than we have!
System.out.println("Sending ..."); System.out.println("Sending ...");

View File

@ -23,7 +23,6 @@ import com.google.bitcoin.store.BlockStore;
import com.google.bitcoin.store.MemoryBlockStore; import com.google.bitcoin.store.MemoryBlockStore;
import java.io.File; import java.io.File;
import java.math.BigInteger;
import java.net.InetAddress; import java.net.InetAddress;
/** /**
@ -46,7 +45,7 @@ public class RefreshWallet {
wallet.addEventListener(new AbstractWalletEventListener() { wallet.addEventListener(new AbstractWalletEventListener() {
@Override @Override
public synchronized void onCoinsReceived(Wallet w, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { public synchronized void onCoinsReceived(Wallet w, Transaction tx, Coin prevBalance, Coin newBalance) {
System.out.println("\nReceived tx " + tx.getHashAsString()); System.out.println("\nReceived tx " + tx.getHashAsString());
System.out.println(tx.toString()); System.out.println(tx.toString());
} }

View File

@ -8,7 +8,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.math.BigInteger;
/** /**
* A program that sends a transaction with the specified fee and measures how long it takes to confirm. * A program that sends a transaction with the specified fee and measures how long it takes to confirm.
@ -26,7 +25,7 @@ public class TestFeeLevel {
return; return;
} }
BigInteger feeToTest = new BigInteger(args[0]); Coin feeToTest = Coin.valueOf(Long.parseLong(args[0]));
kit = new WalletAppKit(PARAMS, new File("."), "testfeelevel"); kit = new WalletAppKit(PARAMS, new File("."), "testfeelevel");
kit.startAsync(); kit.startAsync();
@ -39,7 +38,7 @@ public class TestFeeLevel {
} }
} }
private static void go(BigInteger feeToTest) throws InterruptedException, java.util.concurrent.ExecutionException, InsufficientMoneyException { private static void go(Coin feeToTest) throws InterruptedException, java.util.concurrent.ExecutionException, InsufficientMoneyException {
kit.peerGroup().setMaxConnections(50); kit.peerGroup().setMaxConnections(50);
final Address address = kit.wallet().currentReceiveKey().toAddress(PARAMS); final Address address = kit.wallet().currentReceiveKey().toAddress(PARAMS);

View File

@ -124,9 +124,9 @@ public class WalletTool {
value = s; value = s;
} }
public boolean matchBitcoins(BigInteger comparison) { public boolean matchBitcoins(Coin comparison) {
try { try {
BigInteger units = Utils.toNanoCoins(value); Coin units = Utils.toNanoCoins(value);
switch (type) { switch (type) {
case LT: return comparison.compareTo(units) < 0; case LT: return comparison.compareTo(units) < 0;
case GT: return comparison.compareTo(units) > 0; case GT: return comparison.compareTo(units) > 0;
@ -323,7 +323,7 @@ public class WalletTool {
System.err.println("--payment-request and --output cannot be used together."); System.err.println("--payment-request and --output cannot be used together.");
return; return;
} else if (options.has(outputFlag)) { } else if (options.has(outputFlag)) {
BigInteger fee = BigInteger.ZERO; Coin fee = Coin.ZERO;
if (options.has("fee")) { if (options.has("fee")) {
fee = Utils.toNanoCoins((String)options.valueOf("fee")); fee = Utils.toNanoCoins((String)options.valueOf("fee"));
} }
@ -413,7 +413,7 @@ public class WalletTool {
} }
} }
private static void send(List<String> outputs, BigInteger fee, String lockTimeStr, boolean allowUnconfirmed) throws VerificationException { private static void send(List<String> outputs, Coin fee, String lockTimeStr, boolean allowUnconfirmed) throws VerificationException {
try { try {
// Convert the input strings to outputs. // Convert the input strings to outputs.
Transaction t = new Transaction(params); Transaction t = new Transaction(params);
@ -425,7 +425,7 @@ public class WalletTool {
} }
String destination = parts[0]; String destination = parts[0];
try { try {
BigInteger value = Utils.toNanoCoins(parts[1]); Coin value = Utils.toNanoCoins(parts[1]);
if (destination.startsWith("0")) { if (destination.startsWith("0")) {
// Treat as a raw public key. // Treat as a raw public key.
byte[] pubKey = new BigInteger(destination, 16).toByteArray(); byte[] pubKey = new BigInteger(destination, 16).toByteArray();
@ -567,7 +567,7 @@ public class WalletTool {
private static void send(PaymentSession session) { private static void send(PaymentSession session) {
try { try {
System.out.println("Payment Request"); System.out.println("Payment Request");
System.out.println("Amount: " + session.getValue().doubleValue() / 100000 + "mBTC"); System.out.println("Coin: " + session.getValue().doubleValue() / 100000 + "mBTC");
System.out.println("Date: " + session.getDate()); System.out.println("Date: " + session.getDate());
System.out.println("Memo: " + session.getMemo()); System.out.println("Memo: " + session.getMemo());
if (session.pkiVerificationData != null) { if (session.pkiVerificationData != null) {
@ -636,15 +636,15 @@ public class WalletTool {
} }
@Override @Override
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
// Runs in a peer thread. // Runs in a peer thread.
super.onCoinsReceived(wallet, tx, prevBalance, newBalance); super.onCoinsReceived(wallet, tx, prevBalance, newBalance);
handleTx(tx); handleTx(tx);
} }
@Override @Override
public void onCoinsSent(Wallet wallet, Transaction tx, BigInteger prevBalance, public void onCoinsSent(Wallet wallet, Transaction tx, Coin prevBalance,
BigInteger newBalance) { Coin newBalance) {
// Runs in a peer thread. // Runs in a peer thread.
super.onCoinsSent(wallet, tx, prevBalance, newBalance); super.onCoinsSent(wallet, tx, prevBalance, newBalance);
handleTx(tx); handleTx(tx);
@ -677,7 +677,7 @@ public class WalletTool {
public synchronized void onChange() { public synchronized void onChange() {
super.onChange(); super.onChange();
saveWallet(walletFile); saveWallet(walletFile);
BigInteger balance = wallet.getBalance(Wallet.BalanceType.ESTIMATED); Coin balance = wallet.getBalance(Wallet.BalanceType.ESTIMATED);
if (condition.matchBitcoins(balance)) { if (condition.matchBitcoins(balance)) {
System.out.println(Utils.bitcoinValueToFriendlyString(balance)); System.out.println(Utils.bitcoinValueToFriendlyString(balance));
latch.countDown(); latch.countDown();