3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-14 19:25:51 +00:00

Make feePerKb apply to the first kilobyte as well.

This commit is contained in:
Mike Hearn 2013-06-12 17:16:07 +02:00
parent c9f0ecae3d
commit 87ab410a2f
7 changed files with 107 additions and 58 deletions

View File

@ -1689,7 +1689,7 @@ public class Wallet implements Serializable, BlockChainListener {
* <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>
*/
public BigInteger fee = BigInteger.ZERO;
public BigInteger fee = null;
/**
* <p>A transaction can have a fee attached, which is defined as the difference between the input values
@ -1705,7 +1705,13 @@ public class Wallet implements Serializable, BlockChainListener {
*
* <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 = BigInteger.ZERO;
public BigInteger 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,
* 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;
/**
* <p>Requires that there be enough fee for a default reference client to at least relay the transaction.
@ -1954,13 +1960,10 @@ public class Wallet implements Serializable, BlockChainListener {
// Note that output.isMine(this) needs to test the keychain which is currently an array, so it's
// O(candidate outputs ^ keychain.size())! There's lots of low hanging fruit here.
LinkedList<TransactionOutput> candidates = calculateSpendCandidates(true);
Address changeAddress = req.changeAddress;
int minSize = 0;
// This can throw InsufficientMoneyException.
FeeCalculation feeCalculation = null;
FeeCalculation feeCalculation;
try {
feeCalculation = new FeeCalculation(req, value, originalInputs, needAtLeastReferenceFee,
candidates, changeAddress, minSize);
feeCalculation = new FeeCalculation(req, value, originalInputs, needAtLeastReferenceFee, candidates);
} catch (InsufficientMoneyException e) {
// TODO: Propagate this after 0.9 is released and stop returning a boolean.
return false;
@ -1979,6 +1982,9 @@ public class Wallet implements Serializable, BlockChainListener {
log.info(" with {} coins change", bitcoinValueToFriendlyString(bestChangeOutput.getValue()));
}
final BigInteger calculatedFee = totalInput.subtract(totalOutput);
if (calculatedFee.compareTo(BigInteger.ZERO) > 0) {
log.info(" with a fee of {}", bitcoinValueToFriendlyString(calculatedFee));
}
// Now sign the inputs, thus proving that we are entitled to redeem the connected outputs.
try {
@ -3084,8 +3090,7 @@ public class Wallet implements Serializable, BlockChainListener {
private TransactionOutput bestChangeOutput;
public FeeCalculation(SendRequest req, BigInteger value, List<TransactionInput> originalInputs,
boolean needAtLeastReferenceFee, LinkedList<TransactionOutput> candidates,
Address changeAddress, int minSize) throws InsufficientMoneyException {
boolean needAtLeastReferenceFee, LinkedList<TransactionOutput> candidates) throws InsufficientMoneyException {
// There are 3 possibilities for what adding change might do:
// 1) No effect
// 2) Causes increase in fee (change < 0.01 COINS)
@ -3099,14 +3104,22 @@ public class Wallet implements Serializable, BlockChainListener {
TransactionOutput selection2Change = null;
CoinSelection selection1 = null;
TransactionOutput selection1Change = null;
// 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.
int lastCalculatedSize = 0;
BigInteger valueNeeded;
while (true) {
resetTxInputs(req, originalInputs);
BigInteger fees = req.fee.add(BigInteger.valueOf(minSize/1000).multiply(req.feePerKb));
BigInteger fees = req.fee == null ? BigInteger.ZERO : req.fee;
if (lastCalculatedSize > 0)
fees = fees.add(BigInteger.valueOf((lastCalculatedSize / 1000) + 1).multiply(req.feePerKb));
else
fees = fees.add(req.feePerKb); // First time around the loop.
if (needAtLeastReferenceFee && fees.compareTo(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE) < 0)
fees = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
BigInteger valueNeeded = value.add(fees);
valueNeeded = value.add(fees);
if (additionalValueForNextCategory != null)
valueNeeded = valueNeeded.add(additionalValueForNextCategory);
BigInteger additionalValueSelected = additionalValueForNextCategory;
@ -3146,7 +3159,8 @@ public class Wallet implements Serializable, BlockChainListener {
if (change.compareTo(BigInteger.ZERO) > 0) {
// The value of the inputs is greater than what we want to send. Just like in real life then,
// we need to take back some coins ... this is called "change". Add another output that sends the change
// back to us. The address comes either from the request or getChangeAddress() as a default..
// back to us. The address comes either from the request or getChangeAddress() as a default.
Address changeAddress = req.changeAddress;
if (changeAddress == null)
changeAddress = getChangeAddress();
changeOutput = new TransactionOutput(params, req.tx, change, changeAddress);
@ -3177,11 +3191,12 @@ public class Wallet implements Serializable, BlockChainListener {
checkState(input.getScriptBytes().length == 0);
}
// Estimate transaction size and loop again if we need more fee per kb
size += estimateBytesForSpending(selection);
// Estimate transaction size and loop again if we need more fee per kb. The serialized tx doesn't
// include things we haven't added yet like input signatures/scripts or the change output.
size += req.tx.bitcoinSerialize().length;
if (size/1000 > minSize/1000 && req.feePerKb.compareTo(BigInteger.ZERO) > 0) {
minSize = size;
size += estimateBytesForSigning(selection);
if (size/1000 > lastCalculatedSize/1000 && req.feePerKb.compareTo(BigInteger.ZERO) > 0) {
lastCalculatedSize = size;
// We need more fees anyway, just try again with the same additional value
additionalValueForNextCategory = additionalValueSelected;
continue;
@ -3216,7 +3231,7 @@ public class Wallet implements Serializable, BlockChainListener {
resetTxInputs(req, originalInputs);
if (selection3 == null && selection2 == null && selection1 == null) {
log.warn("Insufficient value in wallet for send");
log.warn("Insufficient value in wallet for send: needed {}", bitcoinValueToFriendlyString(valueNeeded));
throw new InsufficientMoneyException();
}
@ -3249,7 +3264,7 @@ public class Wallet implements Serializable, BlockChainListener {
}
}
private int estimateBytesForSpending(CoinSelection selection) {
private int estimateBytesForSigning(CoinSelection selection) {
int size = 0;
for (TransactionOutput output : selection.gathered) {
try {

View File

@ -24,6 +24,7 @@ import com.google.bitcoin.store.BlockStore;
import com.google.bitcoin.store.MemoryBlockStore;
import com.google.bitcoin.utils.BriefLogFormatter;
import com.google.common.util.concurrent.ListenableFuture;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@ -63,6 +64,7 @@ public class BlockChainTest {
public void setUp() throws Exception {
BriefLogFormatter.initVerbose();
testNetChain = new BlockChain(testNet, new Wallet(testNet), new MemoryBlockStore(testNet));
Wallet.SendRequest.DEFAULT_FEE_PER_KB = BigInteger.ZERO;
unitTestParams = UnitTestParams.get();
wallet = new Wallet(unitTestParams) {
@ -83,6 +85,11 @@ public class BlockChainTest {
coinbaseTo = wallet.getKeys().get(0).toAddress(unitTestParams);
}
@After
public void tearDown() {
Wallet.SendRequest.DEFAULT_FEE_PER_KB = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
}
@Test
public void testBasicChaining() throws Exception {
// Check that we can plug a few blocks together and the futures work.
@ -323,11 +330,8 @@ public class BlockChainTest {
assertNull(coinbaseSpend);
}
// Give it one more block - should now be able to spend coinbase transaction.
// Non relevant tx.
Transaction tx3 = createFakeTx(unitTestParams, Utils.toNanoCoins(1, 0),
new ECKey().toAddress(unitTestParams));
// Give it one more block - should now be able to spend coinbase transaction. Non relevant tx.
Transaction tx3 = createFakeTx(unitTestParams, Utils.toNanoCoins(1, 0), new ECKey().toAddress(unitTestParams));
Block b3 = createFakeBlock(blockStore, tx3).block;
chain.add(b3);

View File

@ -44,6 +44,7 @@ public class ChainSplitTest {
@Before
public void setUp() throws Exception {
BriefLogFormatter.init();
Wallet.SendRequest.DEFAULT_FEE_PER_KB = BigInteger.ZERO;
unitTestParams = UnitTestParams.get();
wallet = new Wallet(unitTestParams);
wallet.addKey(new ECKey());

View File

@ -46,7 +46,8 @@ public class PeerGroupTest extends TestWithPeerGroup {
}
@After
public void shutDown() throws Exception {
public void tearDown() throws Exception {
super.tearDown();
peerGroup.stopAndWait();
}

View File

@ -24,6 +24,7 @@ import org.easymock.EasyMock;
import org.easymock.IMocksControl;
import org.jboss.netty.channel.*;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
@ -60,6 +61,7 @@ public class TestWithNetworkConnections {
control.checkOrder(false);
unitTestParams = UnitTestParams.get();
Wallet.SendRequest.DEFAULT_FEE_PER_KB = BigInteger.ZERO;
this.blockStore = blockStore;
wallet = new Wallet(unitTestParams);
key = new ECKey();
@ -74,6 +76,10 @@ public class TestWithNetworkConnections {
pipeline = createPipeline(channel);
}
public void tearDown() throws Exception {
Wallet.SendRequest.DEFAULT_FEE_PER_KB = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
}
protected ChannelPipeline createPipeline(Channel channel) {
ChannelPipeline pipeline = control.createMock(ChannelPipeline.class);
expect(channel.getPipeline()).andStubReturn(pipeline);

View File

@ -20,6 +20,7 @@ import com.google.bitcoin.params.UnitTestParams;
import com.google.bitcoin.store.BlockStore;
import com.google.bitcoin.store.MemoryBlockStore;
import com.google.bitcoin.utils.BriefLogFormatter;
import org.junit.After;
import org.junit.Before;
import java.io.IOException;
@ -40,6 +41,7 @@ public class TestWithWallet {
@Before
public void setUp() throws Exception {
BriefLogFormatter.init();
Wallet.SendRequest.DEFAULT_FEE_PER_KB = BigInteger.ZERO;
myKey = new ECKey();
myAddress = myKey.toAddress(params);
wallet = new Wallet(params);
@ -48,6 +50,11 @@ public class TestWithWallet {
chain = new BlockChain(params, wallet, blockStore);
}
@After
public void tearDown() throws Exception {
Wallet.SendRequest.DEFAULT_FEE_PER_KB = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
}
protected Transaction sendMoneyToWallet(Wallet wallet, Transaction tx, AbstractBlockChain.NewBlockType type)
throws IOException, ProtocolException, VerificationException {
if (type == null) {

View File

@ -1193,7 +1193,8 @@ public class WalletTest extends TestWithWallet {
StoredBlock block = new StoredBlock(makeSolvedTestBlock(blockStore, notMyAddr), BigInteger.ONE, 1);
Transaction tx1 = createFakeTx(params, BigInteger.ONE, myAddress);
wallet.receiveFromBlock(tx1, block, AbstractBlockChain.NewBlockType.BEST_CHAIN);
Transaction tx2 = createFakeTx(params, BigInteger.ONE, myAddress); assertTrue(!tx1.getHash().equals(tx2.getHash()));
Transaction tx2 = createFakeTx(params, BigInteger.ONE, myAddress);
assertTrue(!tx1.getHash().equals(tx2.getHash()));
wallet.receiveFromBlock(tx2, block, AbstractBlockChain.NewBlockType.BEST_CHAIN);
Transaction tx3 = createFakeTx(params, BigInteger.TEN, myAddress);
wallet.receiveFromBlock(tx3, block, AbstractBlockChain.NewBlockType.BEST_CHAIN);
@ -1364,24 +1365,25 @@ public class WalletTest extends TestWithWallet {
assertTrue(request15.tx.bitcoinSerialize().length > 1000);
request15.feePerKb = BigInteger.ONE;
assertTrue(wallet.completeTx(request15));
assertEquals(BigInteger.ONE, request15.fee);
assertEquals(BigInteger.valueOf(2), request15.fee);
Transaction spend15 = request15.tx;
// If a transaction is over 1kb, the set fee should be added
// If a transaction is over 1kb, 2 satoshis should be added.
assertEquals(31, spend15.getOutputs().size());
// We optimize for priority, so the output selected should be the largest one
BigInteger outValue15 = BigInteger.ZERO;
for (TransactionOutput out : spend15.getOutputs())
outValue15 = outValue15.add(out.getValue());
assertEquals(outValue15, Utils.COIN.subtract(BigInteger.ONE));
assertEquals(Utils.COIN.subtract(BigInteger.valueOf(2)), outValue15);
SendRequest request16 = SendRequest.to(notMyAddr, Utils.CENT);
request16.feePerKb = BigInteger.ZERO;
for (int i = 0; i < 29; i++)
request16.tx.addOutput(Utils.CENT, notMyAddr);
assertTrue(request16.tx.bitcoinSerialize().length > 1000);
assertTrue(wallet.completeTx(request16));
// Of course the fee shouldn't be added if feePerKb == 0
assertEquals(BigInteger.ZERO, request16.fee);
Transaction spend16 = request16.tx;
// Of course the fee shouldn't be added if feePerKb == 0
assertEquals(31, spend16.getOutputs().size());
// We optimize for priority, so the output selected should be the largest one
BigInteger outValue16 = BigInteger.ZERO;
@ -1389,14 +1391,14 @@ public class WalletTest extends TestWithWallet {
outValue16 = outValue16.add(out.getValue());
assertEquals(Utils.COIN, outValue16);
// Create a transaction who's max size could be up to 999 (if signatures were maximum size)
// Create a transaction whose max size could be up to 999 (if signatures were maximum size)
SendRequest request17 = SendRequest.to(notMyAddr, Utils.CENT);
for (int i = 0; i < 22; i++)
request17.tx.addOutput(Utils.CENT, notMyAddr);
request17.tx.addOutput(new TransactionOutput(params, request17.tx, Utils.CENT, new byte[15]));
request17.feePerKb = BigInteger.ONE;
assertTrue(wallet.completeTx(request17));
assertEquals(BigInteger.ZERO, request17.fee);
assertEquals(BigInteger.ONE, request17.fee);
assertEquals(1, request17.tx.getInputs().size());
// Calculate its max length to make sure it is indeed 999
int theoreticalMaxLength17 = request17.tx.bitcoinSerialize().length + myKey.getPubKey().length + 75;
@ -1404,54 +1406,59 @@ public class WalletTest extends TestWithWallet {
theoreticalMaxLength17 -= in.getScriptBytes().length;
assertEquals(999, theoreticalMaxLength17);
Transaction spend17 = request17.tx;
// Its actual size must be between 997 and 999 (inclusive) as signatures have a 3-byte size range (almost always)
assertTrue(spend17.bitcoinSerialize().length >= 997 && spend17.bitcoinSerialize().length <= 999);
// Now check that it didn't get a fee since its max size is 999
{
// Its actual size must be between 997 and 999 (inclusive) as signatures have a 3-byte size range (almost always)
final int length = spend17.bitcoinSerialize().length;
assertTrue(Integer.toString(length), length >= 997 && length <= 999);
}
// Now check that it got a fee of 1 since its max size is 999 (1kb).
assertEquals(25, spend17.getOutputs().size());
// We optimize for priority, so the output selected should be the largest one
BigInteger outValue17 = BigInteger.ZERO;
for (TransactionOutput out : spend17.getOutputs())
outValue17 = outValue17.add(out.getValue());
assertEquals(Utils.COIN, outValue17);
assertEquals(Utils.COIN.subtract(BigInteger.ONE), outValue17);
// 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 1001 (if signatures were maximum size)
SendRequest request18 = SendRequest.to(notMyAddr, Utils.CENT);
for (int i = 0; i < 22; i++)
request18.tx.addOutput(Utils.CENT, notMyAddr);
request18.tx.addOutput(new TransactionOutput(params, request18.tx, Utils.CENT, new byte[16]));
request18.tx.addOutput(new TransactionOutput(params, request18.tx, Utils.CENT, new byte[17]));
request18.feePerKb = BigInteger.ONE;
assertTrue(wallet.completeTx(request18));
assertEquals(BigInteger.ONE, request18.fee);
assertEquals(BigInteger.valueOf(2), request18.fee);
assertEquals(1, request18.tx.getInputs().size());
// Calculate its max length to make sure it is indeed 1000
// Calculate its max length to make sure it is indeed 1001
Transaction spend18 = request18.tx;
int theoreticalMaxLength18 = spend18.bitcoinSerialize().length + myKey.getPubKey().length + 75;
for (TransactionInput in : spend18.getInputs())
theoreticalMaxLength18 -= in.getScriptBytes().length;
assertEquals(1000, theoreticalMaxLength18);
assertEquals(1001, theoreticalMaxLength18);
// Its actual size must be between 998 and 1000 (inclusive) as signatures have a 3-byte size range (almost always)
assertTrue(spend18.bitcoinSerialize().length >= 998);
assertTrue(spend18.bitcoinSerialize().length <= 1000);
assertTrue(spend18.bitcoinSerialize().length <= 1001);
// Now check that it did get a fee since its max size is 1000
assertEquals(25, spend18.getOutputs().size());
// We optimize for priority, so the output selected should be the largest one
BigInteger outValue18 = BigInteger.ZERO;
for (TransactionOutput out : spend18.getOutputs())
outValue18 = outValue18.add(out.getValue());
assertEquals(outValue18, Utils.COIN.subtract(BigInteger.ONE));
assertEquals(outValue18, Utils.COIN.subtract(BigInteger.valueOf(2)));
// Now create a transaction that will spend COIN + fee, which makes it require both inputs
assertEquals(wallet.getBalance(), Utils.CENT.add(Utils.COIN));
SendRequest request19 = SendRequest.to(notMyAddr, Utils.CENT);
request19.feePerKb = BigInteger.ZERO;
for (int i = 0; i < 99; i++)
request19.tx.addOutput(Utils.CENT, notMyAddr);
// If we send now, we shouldnt 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
assertTrue(wallet.completeTx(request19));
assertEquals(BigInteger.ZERO, request19.fee);
assertEquals(1, request19.tx.getInputs().size());
assertEquals(100, request19.tx.getOutputs().size());
// Now reset request19 and give it a fee per kb
request19.completed = false; request19.tx.clearInputs();
request19.completed = false;
request19.tx.clearInputs();
request19.feePerKb = BigInteger.ONE;
assertTrue(wallet.completeTx(request19));
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request19.fee);
@ -1466,9 +1473,10 @@ public class WalletTest extends TestWithWallet {
// Create another transaction that will spend COIN + fee, which makes it require both inputs
SendRequest request20 = SendRequest.to(notMyAddr, Utils.CENT);
request20.feePerKb = BigInteger.ZERO;
for (int i = 0; i < 99; i++)
request20.tx.addOutput(Utils.CENT, notMyAddr);
// If we send now, we shouldnt need 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
assertTrue(wallet.completeTx(request20));
assertEquals(BigInteger.ZERO, request20.fee);
assertEquals(1, request20.tx.getInputs().size());
@ -1477,16 +1485,19 @@ public class WalletTest extends TestWithWallet {
request20.completed = false; request20.tx.clearInputs();
request20.feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
assertTrue(wallet.completeTx(request20));
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(BigInteger.valueOf(3)), request20.fee);
// 4kb tx.
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(BigInteger.valueOf(4)), request20.fee);
assertEquals(2, request20.tx.getInputs().size());
BigInteger outValue20 = BigInteger.ZERO;
for (TransactionOutput out : request20.tx.getOutputs())
outValue20 = outValue20.add(out.getValue());
// This time the fee we wanted to pay was more, so that should be what we paid
assertEquals(outValue20, Utils.COIN.add(Utils.CENT).subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(BigInteger.valueOf(3))));
assertEquals(outValue20, Utils.COIN.add(Utils.CENT).subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(BigInteger.valueOf(4))));
// 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
// 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.
SendRequest request21 = SendRequest.to(notMyAddr, Utils.CENT);
request21.feePerKb = BigInteger.ZERO;
for (int i = 0; i < 99; i++)
request21.tx.addOutput(Utils.CENT, notMyAddr);
request21.tx.addOutput(Utils.CENT.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE), notMyAddr);
@ -1502,15 +1513,18 @@ public class WalletTest extends TestWithWallet {
// Test feePerKb when we aren't using ensureMinRequiredFee
// Same as request 19
SendRequest request25 = SendRequest.to(notMyAddr, Utils.CENT);
for (int i = 0; i < 99; i++)
request25.feePerKb = BigInteger.ZERO;
for (int i = 0; i < 70; i++)
request25.tx.addOutput(Utils.CENT, notMyAddr);
// If we send now, we shouldnt 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
assertTrue(wallet.completeTx(request25));
assertEquals(BigInteger.ZERO, request25.fee);
assertEquals(1, request25.tx.getInputs().size());
assertEquals(100, request25.tx.getOutputs().size());
assertEquals(72, request25.tx.getOutputs().size());
System.out.println(request25.tx.bitcoinSerialize().length);
// Now reset request19 and give it a fee per kb
request25.completed = false; request25.tx.clearInputs();
request25.tx.clearInputs();
request25 = SendRequest.forTx(request25.tx);
request25.feePerKb = Utils.CENT.divide(BigInteger.valueOf(3));
request25.ensureMinRequiredFee = false;
assertTrue(wallet.completeTx(request25));
@ -1519,13 +1533,13 @@ public class WalletTest extends TestWithWallet {
BigInteger outValue25 = BigInteger.ZERO;
for (TransactionOutput out : request25.tx.getOutputs())
outValue25 = outValue25.add(out.getValue());
// Our change output should be one nanocoin
// Our change output should be one satoshi
// Change this assert when we eventually randomize output order
assertEquals(BigInteger.ONE, request25.tx.getOutput(request25.tx.getOutputs().size() - 1).getValue());
// and our fee should be CENT-1 nanocoin
// and our fee should be CENT-1 satoshi
assertEquals(outValue25, Utils.COIN.add(BigInteger.ONE));
//Spend our CENT output
// Spend our CENT output.
Transaction spendTx5 = new Transaction(params);
spendTx5.addOutput(Utils.CENT, notMyAddr);
spendTx5.addInput(tx5.getOutput(0));
@ -1557,7 +1571,7 @@ public class WalletTest extends TestWithWallet {
@Test
public void basicCategoryStepTest() throws Exception {
// Creates spends that step through the possible fee solver categories
SendRequest.DEFAULT_FEE_PER_KB = BigInteger.ZERO;
// Make sure TestWithWallet isnt doing anything crazy.
assertEquals(0, wallet.getTransactions(true).size());
@ -1631,6 +1645,8 @@ public class WalletTest extends TestWithWallet {
assertTrue(wallet.completeTx(request6));
assertEquals(BigInteger.ZERO, request6.fee);
assertEquals(2, request6.tx.getOutputs().size()); // We should have a change output
SendRequest.DEFAULT_FEE_PER_KB = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
}
@Test
@ -1701,11 +1717,10 @@ public class WalletTest extends TestWithWallet {
for (int i = 0; i < 16; i++)
request2.tx.addOutput(Utils.CENT, notMyAddr);
request2.tx.addOutput(new TransactionOutput(params, request2.tx, Utils.CENT, new byte[16]));
request2.fee = BigInteger.ONE;
request2.feePerKb = BigInteger.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
assertTrue(wallet.completeTx(request2));
assertEquals(BigInteger.ONE.shiftLeft(1), request2.fee);
assertEquals(BigInteger.valueOf(2), request2.fee);
assertEquals(4, request2.tx.getInputs().size());
}