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:
parent
c9f0ecae3d
commit
87ab410a2f
@ -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 {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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());
|
||||
|
@ -46,7 +46,8 @@ public class PeerGroupTest extends TestWithPeerGroup {
|
||||
}
|
||||
|
||||
@After
|
||||
public void shutDown() throws Exception {
|
||||
public void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
peerGroup.stopAndWait();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user