Get rid of SendRequest.DEFAULT_FEE_PER_KB "constant".

If you have been reading that field, you probably want to use Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.
If you have been writing to that field to change the SendRequest.feePerKb default, use a Context.feePerKb
instead. There is also a new Context.ensureMinRequiredFee.
This commit is contained in:
Andreas Schildbach
2016-03-11 14:05:28 +01:00
parent 2ab367b4e4
commit a97f4923b4
12 changed files with 94 additions and 73 deletions

View File

@@ -1,5 +1,6 @@
package org.bitcoinj.core; package org.bitcoinj.core;
import org.bitcoinj.core.Wallet.SendRequest;
import org.slf4j.*; import org.slf4j.*;
import static com.google.common.base.Preconditions.*; import static com.google.common.base.Preconditions.*;
@@ -30,6 +31,8 @@ public class Context {
private TxConfidenceTable confidenceTable; private TxConfidenceTable confidenceTable;
private NetworkParameters params; private NetworkParameters params;
private int eventHorizon = 100; private int eventHorizon = 100;
private boolean ensureMinRequiredFee = true;
private Coin feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
/** /**
* Creates a new context object. For now, this will be done for you by the framework. Eventually you will be * Creates a new context object. For now, this will be done for you by the framework. Eventually you will be
@@ -46,15 +49,18 @@ public class Context {
} }
/** /**
* Creates a new context object. For now, this will be done for you by the framework. Eventually you will be * Creates a new custom context object. This is mainly meant for unit tests for now.
* expected to do this yourself in the same manner as fetching a NetworkParameters object (at the start of your app).
* *
* @param params The network parameters that will be associated with this context. * @param params The network parameters that will be associated with this context.
* @param eventHorizon Number of blocks after which the library will delete data and be unable to always process reorgs (see {@link #getEventHorizon()}. * @param eventHorizon Number of blocks after which the library will delete data and be unable to always process reorgs (see {@link #getEventHorizon()}.
* @param feePerKb The default fee per 1000 bytes of transaction data to pay when completing transactions. For details, see {@link SendRequest#feePerKb}.
* @param ensureMinRequiredFee Whether to ensure the minimum required fee by default when completing transactions. For details, see {@link SendRequest#ensureMinRequiredFee}.
*/ */
public Context(NetworkParameters params, int eventHorizon) { public Context(NetworkParameters params, int eventHorizon, Coin feePerKb, boolean ensureMinRequiredFee) {
this(params); this(params);
this.eventHorizon = eventHorizon; this.eventHorizon = eventHorizon;
this.feePerKb = feePerKb;
this.ensureMinRequiredFee = ensureMinRequiredFee;
} }
private static volatile Context lastConstructed; private static volatile Context lastConstructed;
@@ -155,4 +161,18 @@ public class Context {
public int getEventHorizon() { public int getEventHorizon() {
return eventHorizon; return eventHorizon;
} }
/**
* The default fee per 1000 bytes of transaction data to pay when completing transactions. For details, see {@link SendRequest#feePerKb}.
*/
public Coin getFeePerKb() {
return feePerKb;
}
/**
* Whether to ensure the minimum required fee by default when completing transactions. For details, see {@link SendRequest#ensureMinRequiredFee}.
*/
public boolean isEnsureMinRequiredFee() {
return ensureMinRequiredFee;
}
} }

View File

@@ -3721,13 +3721,7 @@ public class Wallet extends BaseTaggableObject
* when choosing which transactions to add to a block. Note that, to keep this equivalent to Bitcoin Core * when choosing which transactions to add to a block. Note that, to keep this equivalent to Bitcoin Core
* definition, a kilobyte is defined as 1000 bytes, not 1024.</p> * definition, a kilobyte is defined as 1000 bytes, not 1024.</p>
*/ */
public Coin feePerKb = DEFAULT_FEE_PER_KB; public Coin feePerKb = Context.get().getFeePerKb();
/**
* 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 Coin DEFAULT_FEE_PER_KB = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
/** /**
* <p>Requires that there be enough fee for a default Bitcoin Core to at least relay the transaction. * <p>Requires that there be enough fee for a default Bitcoin Core to at least relay the transaction.
@@ -3738,7 +3732,7 @@ public class Wallet extends BaseTaggableObject
* 26,000 bytes. If you get a transaction which is that large, you should set a feePerKb of at least * 26,000 bytes. If you get a transaction which is that large, you should set a feePerKb of at least
* {@link Transaction#REFERENCE_DEFAULT_MIN_TX_FEE}.</p> * {@link Transaction#REFERENCE_DEFAULT_MIN_TX_FEE}.</p>
*/ */
public boolean ensureMinRequiredFee = true; public boolean ensureMinRequiredFee = Context.get().isEnsureMinRequiredFee();
/** /**
* If true (the default), the inputs will be signed. * If true (the default), the inputs will be signed.

View File

@@ -37,9 +37,6 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import static org.bitcoinj.core.Coin.FIFTY_COINS; import static org.bitcoinj.core.Coin.FIFTY_COINS;
import org.bitcoinj.store.BlockStore;
import org.bitcoinj.store.MemoryBlockStore;
import org.bitcoinj.testing.FakeTxBuilder;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
@@ -60,12 +57,11 @@ public abstract class AbstractFullPrunedBlockChainTest {
}; };
protected FullPrunedBlockChain chain; protected FullPrunedBlockChain chain;
protected FullPrunedBlockStore store; protected FullPrunedBlockStore store;
protected Context context;
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
BriefLogFormatter.init(); BriefLogFormatter.init();
context = new Context(PARAMS); Context.propagate(new Context(PARAMS, 100, Coin.ZERO, false));
} }
public abstract FullPrunedBlockStore createStore(NetworkParameters params, int blockCount) public abstract FullPrunedBlockStore createStore(NetworkParameters params, int blockCount)

View File

@@ -73,11 +73,10 @@ public class BlockChainTest {
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
BriefLogFormatter.initVerbose(); BriefLogFormatter.initVerbose();
Context testNetContext = new Context(testNet); Context.propagate(new Context(testNet, 100, Coin.ZERO, false));
testNetChain = new BlockChain(testNet, new Wallet(testNetContext), new MemoryBlockStore(testNet)); testNetChain = new BlockChain(testNet, new Wallet(testNet), new MemoryBlockStore(testNet));
Wallet.SendRequest.DEFAULT_FEE_PER_KB = Coin.ZERO; Context.propagate(new Context(PARAMS, 100, Coin.ZERO, false));
Context context = new Context(PARAMS); wallet = new Wallet(PARAMS) {
wallet = new Wallet(context) {
@Override @Override
public void receiveFromBlock(Transaction tx, StoredBlock block, BlockChain.NewBlockType blockType, public void receiveFromBlock(Transaction tx, StoredBlock block, BlockChain.NewBlockType blockType,
int relativityOffset) throws VerificationException { int relativityOffset) throws VerificationException {
@@ -96,11 +95,6 @@ public class BlockChainTest {
coinbaseTo = wallet.currentReceiveKey().toAddress(PARAMS); coinbaseTo = wallet.currentReceiveKey().toAddress(PARAMS);
} }
@After
public void tearDown() {
Wallet.SendRequest.DEFAULT_FEE_PER_KB = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
}
@Test @Test
public void testBasicChaining() throws Exception { public void testBasicChaining() throws Exception {
// Check that we can plug a few blocks together and the futures work. // Check that we can plug a few blocks together and the futures work.

View File

@@ -59,10 +59,9 @@ 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 = Coin.ZERO; Context.propagate(new Context(PARAMS, 100, Coin.ZERO, false));
Context context = new Context(PARAMS);
MemoryBlockStore blockStore = new MemoryBlockStore(PARAMS); MemoryBlockStore blockStore = new MemoryBlockStore(PARAMS);
wallet = new Wallet(context); wallet = new Wallet(PARAMS);
ECKey key1 = wallet.freshReceiveKey(); ECKey key1 = wallet.freshReceiveKey();
ECKey key2 = wallet.freshReceiveKey(); ECKey key2 = wallet.freshReceiveKey();
chain = new BlockChain(PARAMS, wallet, blockStore); chain = new BlockChain(PARAMS, wallet, blockStore);

View File

@@ -244,7 +244,6 @@ public class TransactionBroadcastTest extends TestWithPeerGroup {
// Do the same thing with an offline transaction. // Do the same thing with an offline transaction.
peerGroup.removeWallet(wallet); peerGroup.removeWallet(wallet);
Wallet.SendRequest req = Wallet.SendRequest.to(dest, valueOf(2, 0)); Wallet.SendRequest req = Wallet.SendRequest.to(dest, valueOf(2, 0));
req.ensureMinRequiredFee = false;
Transaction t3 = checkNotNull(wallet.sendCoinsOffline(req)); Transaction t3 = checkNotNull(wallet.sendCoinsOffline(req));
assertNull(outbound(p1)); // Nothing sent. assertNull(outbound(p1)); // Nothing sent.
// Add the wallet to the peer group (simulate initialization). Transactions should be announced. // Add the wallet to the peer group (simulate initialization). Transactions should be announced.

View File

@@ -313,7 +313,6 @@ public class WalletTest extends TestWithWallet {
// Try to create a send with a fee but no password (this should fail). // Try to create a send with a fee but no password (this should fail).
try { try {
req.ensureMinRequiredFee = false;
wallet.completeTx(req); wallet.completeTx(req);
fail(); fail();
} catch (ECKey.MissingPrivateKeyException kce) { } catch (ECKey.MissingPrivateKeyException kce) {
@@ -324,7 +323,6 @@ public class WalletTest extends TestWithWallet {
// Try to create a send with a fee but the wrong password (this should fail). // Try to create a send with a fee but the wrong password (this should fail).
req = Wallet.SendRequest.to(destination, v2); req = Wallet.SendRequest.to(destination, v2);
req.aesKey = wrongAesKey; req.aesKey = wrongAesKey;
req.ensureMinRequiredFee = false;
try { try {
wallet.completeTx(req); wallet.completeTx(req);
@@ -339,7 +337,6 @@ public class WalletTest extends TestWithWallet {
// Create a send with a fee with the correct password (this should succeed). // Create a send with a fee with the correct password (this should succeed).
req = Wallet.SendRequest.to(destination, v2); req = Wallet.SendRequest.to(destination, v2);
req.aesKey = aesKey; req.aesKey = aesKey;
req.ensureMinRequiredFee = false;
} }
// Complete the transaction successfully. // Complete the transaction successfully.
@@ -438,7 +435,6 @@ public class WalletTest extends TestWithWallet {
assertEquals(v3, wallet.getBalance()); assertEquals(v3, wallet.getBalance());
Wallet.SendRequest req = Wallet.SendRequest.to(new ECKey().toAddress(PARAMS), valueOf(0, 48)); Wallet.SendRequest req = Wallet.SendRequest.to(new ECKey().toAddress(PARAMS), valueOf(0, 48));
req.aesKey = aesKey; req.aesKey = aesKey;
req.ensureMinRequiredFee = false;
req.shuffleOutputs = false; req.shuffleOutputs = false;
wallet.completeTx(req); wallet.completeTx(req);
Transaction t3 = req.tx; Transaction t3 = req.tx;
@@ -478,7 +474,6 @@ public class WalletTest extends TestWithWallet {
t2.addOutput(v3, a2); t2.addOutput(v3, a2);
t2.addOutput(v4, a2); t2.addOutput(v4, a2);
SendRequest req = SendRequest.forTx(t2); SendRequest req = SendRequest.forTx(t2);
req.ensureMinRequiredFee = false;
wallet.completeTx(req); wallet.completeTx(req);
// Do some basic sanity checks. // Do some basic sanity checks.
@@ -1901,7 +1896,6 @@ public class WalletTest extends TestWithWallet {
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);
SendRequest req = SendRequest.forTx(t2); SendRequest req = SendRequest.forTx(t2);
req.ensureMinRequiredFee = false;
wallet.completeTx(req); wallet.completeTx(req);
// Commit t2, so it is placed in the pending pool // Commit t2, so it is placed in the pending pool
@@ -2195,6 +2189,7 @@ public class WalletTest extends TestWithWallet {
Script script = ScriptBuilder.createOpReturnScript("hello world!".getBytes()); Script script = ScriptBuilder.createOpReturnScript("hello world!".getBytes());
tx.addOutput(messagePrice, script); tx.addOutput(messagePrice, script);
SendRequest request = Wallet.SendRequest.forTx(tx); SendRequest request = Wallet.SendRequest.forTx(tx);
request.ensureMinRequiredFee = true;
wallet.completeTx(request); wallet.completeTx(request);
} }
@@ -2235,6 +2230,7 @@ public class WalletTest extends TestWithWallet {
tx.addOutput(messagePrice, script1); tx.addOutput(messagePrice, script1);
tx.addOutput(messagePrice, script2); tx.addOutput(messagePrice, script2);
SendRequest request = Wallet.SendRequest.forTx(tx); SendRequest request = Wallet.SendRequest.forTx(tx);
request.ensureMinRequiredFee = true;
wallet.completeTx(request); wallet.completeTx(request);
} }
@@ -2245,6 +2241,7 @@ public class WalletTest extends TestWithWallet {
Address notMyAddr = new ECKey().toAddress(PARAMS); Address notMyAddr = new ECKey().toAddress(PARAMS);
tx.addOutput(Transaction.MIN_NONDUST_OUTPUT.subtract(SATOSHI), notMyAddr); tx.addOutput(Transaction.MIN_NONDUST_OUTPUT.subtract(SATOSHI), notMyAddr);
SendRequest request = Wallet.SendRequest.forTx(tx); SendRequest request = Wallet.SendRequest.forTx(tx);
request.ensureMinRequiredFee = true;
wallet.completeTx(request); wallet.completeTx(request);
} }
@@ -2271,6 +2268,7 @@ public class WalletTest extends TestWithWallet {
tx.addOutput(Coin.ZERO, ScriptBuilder.createOpReturnScript("hello world!".getBytes())); tx.addOutput(Coin.ZERO, ScriptBuilder.createOpReturnScript("hello world!".getBytes()));
tx.addOutput(Coin.SATOSHI, notMyAddr); tx.addOutput(Coin.SATOSHI, notMyAddr);
SendRequest request = Wallet.SendRequest.forTx(tx); SendRequest request = Wallet.SendRequest.forTx(tx);
request.ensureMinRequiredFee = true;
wallet.completeTx(request); wallet.completeTx(request);
} }
@@ -2283,6 +2281,7 @@ public class WalletTest extends TestWithWallet {
tx.addOutput(Coin.CENT, ScriptBuilder.createOpReturnScript("hello world!".getBytes())); tx.addOutput(Coin.CENT, ScriptBuilder.createOpReturnScript("hello world!".getBytes()));
tx.addOutput(Transaction.MIN_NONDUST_OUTPUT.subtract(SATOSHI), notMyAddr); tx.addOutput(Transaction.MIN_NONDUST_OUTPUT.subtract(SATOSHI), notMyAddr);
SendRequest request = Wallet.SendRequest.forTx(tx); SendRequest request = Wallet.SendRequest.forTx(tx);
request.ensureMinRequiredFee = true;
wallet.completeTx(request); wallet.completeTx(request);
} }
@@ -2323,14 +2322,15 @@ public class WalletTest extends TestWithWallet {
// Not allowed to send dust. // Not allowed to send dust.
try { try {
wallet.createSend(notMyAddr, SATOSHI); SendRequest request = SendRequest.to(notMyAddr, SATOSHI);
request.ensureMinRequiredFee = true;
wallet.completeTx(request);
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, SATOSHI.multiply(12)); SendRequest req = SendRequest.to(notMyAddr, SATOSHI.multiply(12));
req.ensureMinRequiredFee = false;
assertNotNull(wallet.sendCoinsOffline(req)); assertNotNull(wallet.sendCoinsOffline(req));
assertEquals(ZERO, wallet.getBalance()); assertEquals(ZERO, wallet.getBalance());
@@ -2340,7 +2340,10 @@ 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(SATOSHI)); SendRequest request1 = SendRequest.to(notMyAddr, CENT.subtract(SATOSHI));
request1.ensureMinRequiredFee = true;
wallet.completeTx(request1);
Transaction spend1 = request1.tx;
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.
@@ -2348,7 +2351,10 @@ public class WalletTest extends TestWithWallet {
Coin.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE)); Coin.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
// But not at exactly 0.01 // But not at exactly 0.01
Transaction spend2 = wallet.createSend(notMyAddr, CENT); SendRequest request2 = SendRequest.to(notMyAddr, CENT);
request2.ensureMinRequiredFee = true;
wallet.completeTx(request2);
Transaction spend2 = request2.tx;
assertEquals(2, spend2.getOutputs().size()); assertEquals(2, spend2.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(Coin.COIN, spend2.getOutput(0).getValue().add(spend2.getOutput(1).getValue())); assertEquals(Coin.COIN, spend2.getOutput(0).getValue().add(spend2.getOutput(1).getValue()));
@@ -2356,6 +2362,7 @@ public class WalletTest extends TestWithWallet {
// ...but not more fee than what we request // ...but not more fee than what we request
SendRequest request3 = SendRequest.to(notMyAddr, CENT.subtract(SATOSHI)); SendRequest request3 = SendRequest.to(notMyAddr, CENT.subtract(SATOSHI));
request3.feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(SATOSHI); request3.feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(SATOSHI);
request3.ensureMinRequiredFee = true;
wallet.completeTx(request3); wallet.completeTx(request3);
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(SATOSHI), request3.tx.getFee()); assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(SATOSHI), request3.tx.getFee());
Transaction spend3 = request3.tx; Transaction spend3 = request3.tx;
@@ -2367,6 +2374,7 @@ public class WalletTest extends TestWithWallet {
// ...unless we need it // ...unless we need it
SendRequest request4 = SendRequest.to(notMyAddr, CENT.subtract(SATOSHI)); SendRequest request4 = SendRequest.to(notMyAddr, CENT.subtract(SATOSHI));
request4.feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.subtract(SATOSHI); request4.feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.subtract(SATOSHI);
request4.ensureMinRequiredFee = true;
wallet.completeTx(request4); wallet.completeTx(request4);
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request4.tx.getFee()); assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request4.tx.getFee());
Transaction spend4 = request4.tx; Transaction spend4 = request4.tx;
@@ -2376,6 +2384,7 @@ public class WalletTest extends TestWithWallet {
Coin.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE)); Coin.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
SendRequest request5 = SendRequest.to(notMyAddr, Coin.COIN.subtract(CENT.subtract(SATOSHI))); SendRequest request5 = SendRequest.to(notMyAddr, Coin.COIN.subtract(CENT.subtract(SATOSHI)));
request5.ensureMinRequiredFee = true;
wallet.completeTx(request5); wallet.completeTx(request5);
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request5.tx.getFee()); assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request5.tx.getFee());
Transaction spend5 = request5.tx; Transaction spend5 = request5.tx;
@@ -2386,6 +2395,7 @@ public class WalletTest extends TestWithWallet {
Coin.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE)); Coin.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
SendRequest request6 = SendRequest.to(notMyAddr, Coin.COIN.subtract(CENT)); SendRequest request6 = SendRequest.to(notMyAddr, Coin.COIN.subtract(CENT));
request6.ensureMinRequiredFee = true;
wallet.completeTx(request6); wallet.completeTx(request6);
assertEquals(ZERO, request6.tx.getFee()); assertEquals(ZERO, request6.tx.getFee());
Transaction spend6 = request6.tx; Transaction spend6 = request6.tx;
@@ -2395,6 +2405,7 @@ public class WalletTest extends TestWithWallet {
assertEquals(Coin.COIN, spend6.getOutput(0).getValue().add(spend6.getOutput(1).getValue())); assertEquals(Coin.COIN, spend6.getOutput(0).getValue().add(spend6.getOutput(1).getValue()));
SendRequest request7 = SendRequest.to(notMyAddr, Coin.COIN.subtract(CENT.subtract(SATOSHI.multiply(2)).multiply(2))); SendRequest request7 = SendRequest.to(notMyAddr, Coin.COIN.subtract(CENT.subtract(SATOSHI.multiply(2)).multiply(2)));
request7.ensureMinRequiredFee = true;
request7.tx.addOutput(CENT.subtract(SATOSHI), notMyAddr); request7.tx.addOutput(CENT.subtract(SATOSHI), notMyAddr);
wallet.completeTx(request7); wallet.completeTx(request7);
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request7.tx.getFee()); assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request7.tx.getFee());
@@ -2406,6 +2417,7 @@ public class WalletTest extends TestWithWallet {
Coin.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE)); Coin.COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
SendRequest request8 = SendRequest.to(notMyAddr, COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE)); SendRequest request8 = SendRequest.to(notMyAddr, COIN.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE));
request8.ensureMinRequiredFee = true;
wallet.completeTx(request8); wallet.completeTx(request8);
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request8.tx.getFee()); assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request8.tx.getFee());
Transaction spend8 = request8.tx; Transaction spend8 = request8.tx;
@@ -2416,6 +2428,7 @@ public class WalletTest extends TestWithWallet {
SendRequest request9 = SendRequest.to(notMyAddr, COIN.subtract( SendRequest request9 = SendRequest.to(notMyAddr, COIN.subtract(
Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT).subtract(SATOSHI))); Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT).subtract(SATOSHI)));
request9.ensureMinRequiredFee = true;
wallet.completeTx(request9); wallet.completeTx(request9);
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT).subtract(SATOSHI), request9.tx.getFee()); assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT).subtract(SATOSHI), request9.tx.getFee());
Transaction spend9 = request9.tx; Transaction spend9 = request9.tx;
@@ -2427,6 +2440,7 @@ public class WalletTest extends TestWithWallet {
SendRequest request10 = SendRequest.to(notMyAddr, COIN.subtract( SendRequest request10 = SendRequest.to(notMyAddr, COIN.subtract(
Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT))); Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT)));
request10.ensureMinRequiredFee = true;
wallet.completeTx(request10); wallet.completeTx(request10);
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request10.tx.getFee()); assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request10.tx.getFee());
Transaction spend10 = request10.tx; Transaction spend10 = request10.tx;
@@ -2439,6 +2453,7 @@ public class WalletTest extends TestWithWallet {
SendRequest request11 = SendRequest.to(notMyAddr, COIN.subtract( SendRequest request11 = SendRequest.to(notMyAddr, COIN.subtract(
Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT).add(SATOSHI.multiply(2)))); Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT).add(SATOSHI.multiply(2))));
request11.feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(SATOSHI); request11.feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(SATOSHI);
request11.ensureMinRequiredFee = true;
wallet.completeTx(request11); wallet.completeTx(request11);
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(SATOSHI), request11.tx.getFee()); assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(SATOSHI), request11.tx.getFee());
Transaction spend11 = request11.tx; Transaction spend11 = request11.tx;
@@ -2491,6 +2506,7 @@ public class WalletTest extends TestWithWallet {
request15.tx.addOutput(CENT, notMyAddr); request15.tx.addOutput(CENT, notMyAddr);
assertTrue(request15.tx.unsafeBitcoinSerialize().length > 1000); assertTrue(request15.tx.unsafeBitcoinSerialize().length > 1000);
request15.feePerKb = SATOSHI; request15.feePerKb = SATOSHI;
request15.ensureMinRequiredFee = true;
wallet.completeTx(request15); wallet.completeTx(request15);
assertEquals(SATOSHI.multiply(2), request15.tx.getFee()); assertEquals(SATOSHI.multiply(2), request15.tx.getFee());
Transaction spend15 = request15.tx; Transaction spend15 = request15.tx;
@@ -2504,6 +2520,7 @@ public class WalletTest extends TestWithWallet {
SendRequest request16 = SendRequest.to(notMyAddr, CENT); SendRequest request16 = SendRequest.to(notMyAddr, CENT);
request16.feePerKb = ZERO; request16.feePerKb = ZERO;
request16.ensureMinRequiredFee = true;
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.unsafeBitcoinSerialize().length > 1000); assertTrue(request16.tx.unsafeBitcoinSerialize().length > 1000);
@@ -2524,6 +2541,7 @@ public class WalletTest extends TestWithWallet {
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 = SATOSHI; request17.feePerKb = SATOSHI;
request17.ensureMinRequiredFee = true;
wallet.completeTx(request17); wallet.completeTx(request17);
assertEquals(SATOSHI, request17.tx.getFee()); assertEquals(SATOSHI, request17.tx.getFee());
assertEquals(1, request17.tx.getInputs().size()); assertEquals(1, request17.tx.getInputs().size());
@@ -2552,6 +2570,7 @@ public class WalletTest extends TestWithWallet {
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 = SATOSHI; request18.feePerKb = SATOSHI;
request18.ensureMinRequiredFee = true;
wallet.completeTx(request18); wallet.completeTx(request18);
assertEquals(SATOSHI.multiply(2), request18.tx.getFee()); assertEquals(SATOSHI.multiply(2), request18.tx.getFee());
assertEquals(1, request18.tx.getInputs().size()); assertEquals(1, request18.tx.getInputs().size());
@@ -2576,6 +2595,7 @@ public class WalletTest extends TestWithWallet {
assertEquals(wallet.getBalance(), CENT.add(COIN)); assertEquals(wallet.getBalance(), CENT.add(COIN));
SendRequest request19 = SendRequest.to(notMyAddr, CENT); SendRequest request19 = SendRequest.to(notMyAddr, CENT);
request19.feePerKb = ZERO; request19.feePerKb = ZERO;
request19.ensureMinRequiredFee = true;
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
@@ -2586,6 +2606,7 @@ public class WalletTest extends TestWithWallet {
// 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.ensureMinRequiredFee = true;
request19.feePerKb = SATOSHI; request19.feePerKb = SATOSHI;
request19.shuffleOutputs = false; request19.shuffleOutputs = false;
wallet.completeTx(request19); wallet.completeTx(request19);
@@ -2601,6 +2622,7 @@ 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 = ZERO; request20.feePerKb = ZERO;
request20.ensureMinRequiredFee = true;
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
@@ -2626,6 +2648,7 @@ public class WalletTest extends TestWithWallet {
// result of an output < CENT. // result of an output < CENT.
SendRequest request21 = SendRequest.to(notMyAddr, CENT); SendRequest request21 = SendRequest.to(notMyAddr, CENT);
request21.feePerKb = ZERO; request21.feePerKb = ZERO;
request21.ensureMinRequiredFee = true;
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);
@@ -2642,6 +2665,7 @@ public class WalletTest extends TestWithWallet {
// Same as request 19 // Same as request 19
SendRequest request25 = SendRequest.to(notMyAddr, CENT); SendRequest request25 = SendRequest.to(notMyAddr, CENT);
request25.feePerKb = ZERO; request25.feePerKb = ZERO;
request25.ensureMinRequiredFee = true;
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
@@ -2653,7 +2677,6 @@ public class WalletTest extends TestWithWallet {
request25.tx.clearInputs(); request25.tx.clearInputs();
request25 = SendRequest.forTx(request25.tx); request25 = SendRequest.forTx(request25.tx);
request25.feePerKb = CENT.divide(3); request25.feePerKb = CENT.divide(3);
request25.ensureMinRequiredFee = false;
request25.shuffleOutputs = false; request25.shuffleOutputs = false;
wallet.completeTx(request25); wallet.completeTx(request25);
assertEquals(CENT.subtract(SATOSHI), request25.tx.getFee()); assertEquals(CENT.subtract(SATOSHI), request25.tx.getFee());
@@ -2684,6 +2707,7 @@ public class WalletTest extends TestWithWallet {
notMyAddr); notMyAddr);
assertTrue(request26.tx.unsafeBitcoinSerialize().length > 1000); assertTrue(request26.tx.unsafeBitcoinSerialize().length > 1000);
request26.feePerKb = SATOSHI; request26.feePerKb = SATOSHI;
request26.ensureMinRequiredFee = true;
wallet.completeTx(request26); wallet.completeTx(request26);
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT).subtract(SATOSHI), assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT).subtract(SATOSHI),
request26.tx.getFee()); request26.tx.getFee());
@@ -2701,7 +2725,6 @@ 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 = 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());
@@ -2720,6 +2743,7 @@ 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, balance.subtract(SATOSHI)); SendRequest request1 = SendRequest.to(notMyAddr, balance.subtract(SATOSHI));
request1.ensureMinRequiredFee = true;
wallet.completeTx(request1); wallet.completeTx(request1);
assertEquals(SATOSHI, request1.tx.getFee()); assertEquals(SATOSHI, request1.tx.getFee());
assertEquals(request1.tx.getInputs().size(), i); // We should have spent all inputs assertEquals(request1.tx.getInputs().size(), i); // We should have spent all inputs
@@ -2731,6 +2755,7 @@ 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)
SendRequest request2 = SendRequest.to(notMyAddr, balance.subtract(SATOSHI)); SendRequest request2 = SendRequest.to(notMyAddr, balance.subtract(SATOSHI));
request2.ensureMinRequiredFee = true;
wallet.completeTx(request2); wallet.completeTx(request2);
assertEquals(SATOSHI, request2.tx.getFee()); assertEquals(SATOSHI, request2.tx.getFee());
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
@@ -2743,6 +2768,7 @@ 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(tenThousand).subtract(SATOSHI)); SendRequest request3 = SendRequest.to(notMyAddr, CENT.add(tenThousand).subtract(SATOSHI));
request3.ensureMinRequiredFee = true;
wallet.completeTx(request3); wallet.completeTx(request3);
assertEquals(SATOSHI, request3.tx.getFee()); assertEquals(SATOSHI, request3.tx.getFee());
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
@@ -2750,6 +2776,7 @@ public class WalletTest extends TestWithWallet {
// //
SendRequest request4 = SendRequest.to(notMyAddr, balance.subtract(SATOSHI)); SendRequest request4 = SendRequest.to(notMyAddr, balance.subtract(SATOSHI));
request4.feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.divide(request3.tx.unsafeBitcoinSerialize().length); request4.feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.divide(request3.tx.unsafeBitcoinSerialize().length);
request4.ensureMinRequiredFee = true;
wallet.completeTx(request4); wallet.completeTx(request4);
assertEquals(SATOSHI, request4.tx.getFee()); assertEquals(SATOSHI, request4.tx.getFee());
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
@@ -2763,6 +2790,7 @@ 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(tenThousand).subtract(SATOSHI)); SendRequest request5 = SendRequest.to(notMyAddr, CENT.add(tenThousand).subtract(SATOSHI));
request5.ensureMinRequiredFee = true;
wallet.completeTx(request5); wallet.completeTx(request5);
assertEquals(SATOSHI, request5.tx.getFee()); assertEquals(SATOSHI, request5.tx.getFee());
assertEquals(1, request5.tx.getOutputs().size()); // We should have no change output assertEquals(1, request5.tx.getOutputs().size()); // We should have no change output
@@ -2774,11 +2802,10 @@ public class WalletTest extends TestWithWallet {
// ... that puts us in category 1 (no fee!) // ... that puts us in category 1 (no fee!)
SendRequest request6 = SendRequest.to(notMyAddr, CENT.add(tenThousand).subtract(SATOSHI)); SendRequest request6 = SendRequest.to(notMyAddr, CENT.add(tenThousand).subtract(SATOSHI));
request6.ensureMinRequiredFee = true;
wallet.completeTx(request6); wallet.completeTx(request6);
assertEquals(ZERO, request6.tx.getFee()); assertEquals(ZERO, request6.tx.getFee());
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;
} }
@Test @Test
@@ -2801,6 +2828,7 @@ public class WalletTest extends TestWithWallet {
// 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(SATOSHI)); SendRequest request1 = SendRequest.to(notMyAddr, CENT.add(SATOSHI));
request1.ensureMinRequiredFee = true;
wallet.completeTx(request1); wallet.completeTx(request1);
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request1.tx.getFee()); assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request1.tx.getFee());
assertEquals(request1.tx.getInputs().size(), i); // We should have spent all inputs assertEquals(request1.tx.getInputs().size(), i); // We should have spent all inputs
@@ -2834,6 +2862,7 @@ public class WalletTest extends TestWithWallet {
wallet.commitTx(req.tx); wallet.commitTx(req.tx);
SendRequest emptyReq = SendRequest.emptyWallet(myAddress); SendRequest emptyReq = SendRequest.emptyWallet(myAddress);
emptyReq.feePerKb = fee; emptyReq.feePerKb = fee;
emptyReq.ensureMinRequiredFee = true;
emptyReq.emptyWallet = true; emptyReq.emptyWallet = true;
emptyReq.coinSelector = AllowUnconfirmedCoinSelector.get(); emptyReq.coinSelector = AllowUnconfirmedCoinSelector.get();
wallet.completeTx(emptyReq); wallet.completeTx(emptyReq);
@@ -2883,6 +2912,7 @@ public class WalletTest extends TestWithWallet {
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.feePerKb = SATOSHI; request1.feePerKb = SATOSHI;
request1.ensureMinRequiredFee = true;
// 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)
@@ -2901,6 +2931,7 @@ public class WalletTest extends TestWithWallet {
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 = SATOSHI; request2.feePerKb = SATOSHI;
request2.ensureMinRequiredFee = true;
// 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(SATOSHI.multiply(2), request2.tx.getFee()); assertEquals(SATOSHI.multiply(2), request2.tx.getFee());
@@ -3022,45 +3053,37 @@ public class WalletTest extends TestWithWallet {
Transaction tx = createFakeTx(PARAMS, CENT, myAddress); Transaction tx = createFakeTx(PARAMS, CENT, myAddress);
wallet.receiveFromBlock(tx, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 0); wallet.receiveFromBlock(tx, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 0);
SendRequest request = SendRequest.emptyWallet(outputKey); SendRequest request = SendRequest.emptyWallet(outputKey);
request.ensureMinRequiredFee = false;
wallet.completeTx(request); wallet.completeTx(request);
assertEquals(Wallet.SendRequest.DEFAULT_FEE_PER_KB, request.tx.getFee()); assertEquals(ZERO, request.tx.getFee());
wallet.commitTx(request.tx); wallet.commitTx(request.tx);
assertEquals(ZERO, wallet.getBalance()); assertEquals(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
// policies that are in use by default. // policies that are in use by default.
block = new StoredBlock(makeSolvedTestBlock(blockStore, outputKey), BigInteger.ONE, 1); block = new StoredBlock(makeSolvedTestBlock(blockStore, outputKey), BigInteger.ONE, 2);
tx = createFakeTx(PARAMS, CENT, myAddress); tx = createFakeTx(PARAMS, CENT, myAddress);
wallet.receiveFromBlock(tx, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 0); wallet.receiveFromBlock(tx, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 0);
tx = createFakeTx(PARAMS, CENT, myAddress); tx = createFakeTx(PARAMS, CENT, myAddress);
wallet.receivePending(tx, null); wallet.receivePending(tx, null);
request = SendRequest.emptyWallet(outputKey); request = SendRequest.emptyWallet(outputKey);
request.ensureMinRequiredFee = false;
wallet.completeTx(request); wallet.completeTx(request);
assertEquals(Wallet.SendRequest.DEFAULT_FEE_PER_KB, request.tx.getFee()); assertEquals(ZERO, request.tx.getFee());
wallet.commitTx(request.tx); wallet.commitTx(request.tx);
assertEquals(ZERO, wallet.getBalance()); assertEquals(ZERO, wallet.getBalance());
assertEquals(CENT, request.tx.getOutput(0).getValue()); assertEquals(CENT, request.tx.getOutput(0).getValue());
// Add an unsendable value // Add an unsendable value
StoredBlock block2 = new StoredBlock(block.getHeader().createNextBlock(outputKey), BigInteger.ONE, 3); block = new StoredBlock(block.getHeader().createNextBlock(outputKey), BigInteger.ONE, 3);
Coin outputValue = Transaction.MIN_NONDUST_OUTPUT.add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE).subtract(SATOSHI); Coin outputValue = Transaction.MIN_NONDUST_OUTPUT.subtract(SATOSHI);
tx = createFakeTx(PARAMS, outputValue, myAddress); tx = createFakeTx(PARAMS, outputValue, myAddress);
wallet.receiveFromBlock(tx, block2, AbstractBlockChain.NewBlockType.BEST_CHAIN, 0); wallet.receiveFromBlock(tx, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 0);
try { try {
request = SendRequest.emptyWallet(outputKey); request = SendRequest.emptyWallet(outputKey);
assertEquals(ZERO, request.tx.getFee());
wallet.completeTx(request); wallet.completeTx(request);
fail(); fail();
} catch (Wallet.CouldNotAdjustDownwards e) {} } catch (Wallet.CouldNotAdjustDownwards e) {}
request = SendRequest.emptyWallet(outputKey);
request.ensureMinRequiredFee = false;
wallet.completeTx(request);
assertEquals(ZERO, request.tx.getFee());
wallet.commitTx(request.tx);
assertEquals(ZERO, wallet.getBalance());
assertEquals(outputValue, request.tx.getOutput(0).getValue());
} }
@Test @Test

View File

@@ -102,11 +102,11 @@ public class ChannelConnectionTest extends TestWithWallet {
public void setUp() throws Exception { public void setUp() throws Exception {
super.setUp(); super.setUp();
Utils.setMockClock(); // Use mock clock Utils.setMockClock(); // Use mock clock
Context.propagate(new Context(PARAMS, 3, Coin.ZERO, false)); // Shorter event horizon for unit tests.
sendMoneyToWallet(COIN, AbstractBlockChain.NewBlockType.BEST_CHAIN); sendMoneyToWallet(COIN, AbstractBlockChain.NewBlockType.BEST_CHAIN);
sendMoneyToWallet(COIN, AbstractBlockChain.NewBlockType.BEST_CHAIN); sendMoneyToWallet(COIN, AbstractBlockChain.NewBlockType.BEST_CHAIN);
wallet.addExtension(new StoredPaymentChannelClientStates(wallet, failBroadcaster)); wallet.addExtension(new StoredPaymentChannelClientStates(wallet, failBroadcaster));
Context context = new Context(PARAMS, 3); // Shorter event horizon for unit tests. serverWallet = new Wallet(PARAMS);
serverWallet = new Wallet(context);
serverWallet.addExtension(new StoredPaymentChannelServerStates(serverWallet, failBroadcaster)); serverWallet.addExtension(new StoredPaymentChannelServerStates(serverWallet, failBroadcaster));
serverWallet.freshReceiveKey(); serverWallet.freshReceiveKey();
// Use an atomic boolean to indicate failure because fail()/assert*() dont work in network threads // Use an atomic boolean to indicate failure because fail()/assert*() dont work in network threads
@@ -163,7 +163,7 @@ public class ChannelConnectionTest extends TestWithWallet {
exectuteSimpleChannelTest(userKeySetup); exectuteSimpleChannelTest(userKeySetup);
} }
public void exectuteSimpleChannelTest(KeyParameter userKeySetup) throws Exception { private void exectuteSimpleChannelTest(KeyParameter userKeySetup) throws Exception {
// 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<PaymentChannelV1ServerState>> serverCloseFuture = SettableFuture.create(); final SettableFuture<ListenableFuture<PaymentChannelV1ServerState>> serverCloseFuture = SettableFuture.create();
final SettableFuture<Sha256Hash> channelOpenFuture = SettableFuture.create(); final SettableFuture<Sha256Hash> channelOpenFuture = SettableFuture.create();
@@ -251,8 +251,8 @@ public class ChannelConnectionTest extends TestWithWallet {
// Wait for the server thread to catch up with closing // Wait for the server thread to catch up with closing
serverState.close().get(); serverState.close().get();
assertEquals(PaymentChannelServerState.State.CLOSED, serverState.getState()); assertEquals(PaymentChannelServerState.State.CLOSED, serverState.getState());
if (!serverState.getBestValueToMe().equals(amount) || !serverState.getFeePaid().equals(Coin.ZERO)) assertEquals(amount, serverState.getBestValueToMe());
fail(); assertEquals(ZERO, serverState.getFeePaid());
assertTrue(channels.mapChannels.isEmpty()); assertTrue(channels.mapChannels.isEmpty());
// Send the settle TX to the client wallet. // Send the settle TX to the client wallet.

View File

@@ -88,6 +88,7 @@ public class PaymentChannelStateTest extends TestWithWallet {
public void setUp() throws Exception { public void setUp() throws Exception {
Utils.setMockClock(); // Use mock clock Utils.setMockClock(); // Use mock clock
super.setUp(); super.setUp();
Context.propagate(new Context(PARAMS, 100, Coin.ZERO, true));
wallet.addExtension(new StoredPaymentChannelClientStates(wallet, new TransactionBroadcaster() { wallet.addExtension(new StoredPaymentChannelClientStates(wallet, new TransactionBroadcaster() {
@Override @Override
public TransactionBroadcast broadcastTransaction(Transaction tx) { public TransactionBroadcast broadcastTransaction(Transaction tx) {

View File

@@ -82,9 +82,7 @@ public class TestWithNetworkConnections {
public void setUp(BlockStore blockStore) throws Exception { public void setUp(BlockStore blockStore) throws Exception {
BriefLogFormatter.init(); BriefLogFormatter.init();
Context.propagate(new Context(PARAMS, 100, Coin.ZERO, false));
context = new Context(PARAMS);
Wallet.SendRequest.DEFAULT_FEE_PER_KB = Coin.ZERO;
this.blockStore = blockStore; this.blockStore = blockStore;
// Allow subclasses to override the wallet object with their own. // Allow subclasses to override the wallet object with their own.
if (wallet == null) { if (wallet == null) {
@@ -131,7 +129,6 @@ public class TestWithNetworkConnections {
} }
public void tearDown() throws Exception { public void tearDown() throws Exception {
Wallet.SendRequest.DEFAULT_FEE_PER_KB = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
stopPeerServers(); stopPeerServers();
} }

View File

@@ -47,8 +47,7 @@ public class TestWithWallet {
public void setUp() throws Exception { public void setUp() throws Exception {
BriefLogFormatter.init(); BriefLogFormatter.init();
Wallet.SendRequest.DEFAULT_FEE_PER_KB = Coin.ZERO; Context.propagate(new Context(PARAMS, 100, Coin.ZERO, false));
Context ctx = new Context(PARAMS);
wallet = new Wallet(PARAMS); wallet = new Wallet(PARAMS);
myKey = wallet.currentReceiveKey(); myKey = wallet.currentReceiveKey();
myAddress = myKey.toAddress(PARAMS); myAddress = myKey.toAddress(PARAMS);
@@ -57,7 +56,6 @@ public class TestWithWallet {
} }
public void tearDown() throws Exception { public void tearDown() throws Exception {
Wallet.SendRequest.DEFAULT_FEE_PER_KB = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
} }
@Nullable @Nullable

View File

@@ -198,7 +198,7 @@ public class ExamplePaymentChannelClient {
private void waitForSufficientBalance(Coin amount) { private void waitForSufficientBalance(Coin amount) {
// Not enough money in the wallet. // Not enough money in the wallet.
Coin amountPlusFee = amount.add(Wallet.SendRequest.DEFAULT_FEE_PER_KB); Coin amountPlusFee = amount.add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE);
// ESTIMATED because we don't really need to wait for confirmation. // ESTIMATED because we don't really need to wait for confirmation.
ListenableFuture<Coin> balanceFuture = appKit.wallet().getBalanceFuture(amountPlusFee, Wallet.BalanceType.ESTIMATED); ListenableFuture<Coin> balanceFuture = appKit.wallet().getBalanceFuture(amountPlusFee, Wallet.BalanceType.ESTIMATED);
if (!balanceFuture.isDone()) { if (!balanceFuture.isDone()) {