From 01365ca00bbc2de6abc386bba634e2b4035159c7 Mon Sep 17 00:00:00 2001 From: Andreas Schildbach Date: Fri, 25 Mar 2016 11:43:46 +0100 Subject: [PATCH] Introduce a Transaction.DEFAULT_TX_FEE and use it as a default for sends and for wallet maintenance. Previously we were using Transaction.REFERENCE_DEFAULT_MIN_TX_FEE which is the absolute minimum but it can be too low. This value should be adjusted from time to time; we're starting with 0.1 mBTC. --- .../main/java/org/bitcoinj/core/Context.java | 2 +- .../java/org/bitcoinj/core/Transaction.java | 10 ++++++++-- .../main/java/org/bitcoinj/core/Wallet.java | 2 +- .../java/org/bitcoinj/core/WalletTest.java | 10 +++++----- .../java/org/bitcoinj/tools/WalletTool.java | 20 +++++++++++-------- 5 files changed, 27 insertions(+), 17 deletions(-) diff --git a/core/src/main/java/org/bitcoinj/core/Context.java b/core/src/main/java/org/bitcoinj/core/Context.java index 37b6ba48a..3e32d76e8 100644 --- a/core/src/main/java/org/bitcoinj/core/Context.java +++ b/core/src/main/java/org/bitcoinj/core/Context.java @@ -32,7 +32,7 @@ public class Context { private NetworkParameters params; private int eventHorizon = 100; private boolean ensureMinRequiredFee = true; - private Coin feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE; + private Coin feePerKb = Transaction.DEFAULT_TX_FEE; /** * Creates a new context object. For now, this will be done for you by the framework. Eventually you will be diff --git a/core/src/main/java/org/bitcoinj/core/Transaction.java b/core/src/main/java/org/bitcoinj/core/Transaction.java index adbcfcfa9..966b68095 100644 --- a/core/src/main/java/org/bitcoinj/core/Transaction.java +++ b/core/src/main/java/org/bitcoinj/core/Transaction.java @@ -94,9 +94,15 @@ public class Transaction extends ChildMessage { public static final int MAX_STANDARD_TX_SIZE = 100000; /** - * If fee is lower than this value (in satoshis), Bitcoin Core will treat it as if there were no fee. + * If feePerKb is lower than this, Bitcoin Core will treat it as if there were no fee. */ - public static final Coin REFERENCE_DEFAULT_MIN_TX_FEE = Coin.valueOf(5000); // satoshis + public static final Coin REFERENCE_DEFAULT_MIN_TX_FEE = Coin.valueOf(5000); // 0.05 mBTC + + /** + * If using this feePerKb, transactions will get confirmed within the next couple of blocks. + * This should be adjusted from time to time. Last adjustment: March 2016. + */ + public static final Coin DEFAULT_TX_FEE = Coin.valueOf(10000); // 0.1 mBTC /** * Any standard (ie pay-to-address) output smaller than this value (in satoshis) will most likely be rejected by the network. diff --git a/core/src/main/java/org/bitcoinj/core/Wallet.java b/core/src/main/java/org/bitcoinj/core/Wallet.java index 505d64962..7ef745825 100644 --- a/core/src/main/java/org/bitcoinj/core/Wallet.java +++ b/core/src/main/java/org/bitcoinj/core/Wallet.java @@ -5459,7 +5459,7 @@ public class Wallet extends BaseTaggableObject } // When not signing, don't waste addresses. rekeyTx.addOutput(toMove.valueGathered, sign ? freshReceiveAddress() : currentReceiveAddress()); - if (!adjustOutputDownwardsForFee(rekeyTx, toMove, Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, true)) { + if (!adjustOutputDownwardsForFee(rekeyTx, toMove, Transaction.DEFAULT_TX_FEE, true)) { log.error("Failed to adjust rekey tx for fees."); return null; } diff --git a/core/src/test/java/org/bitcoinj/core/WalletTest.java b/core/src/test/java/org/bitcoinj/core/WalletTest.java index 19a37b184..d73e9952e 100644 --- a/core/src/test/java/org/bitcoinj/core/WalletTest.java +++ b/core/src/test/java/org/bitcoinj/core/WalletTest.java @@ -2794,14 +2794,14 @@ public class WalletTest extends TestWithWallet { // Create a transaction SendRequest request = SendRequest.to(OTHER_ADDRESS, CENT); - request.feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE; + request.feePerKb = Transaction.DEFAULT_TX_FEE; wallet.completeTx(request); - assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request.tx.getFee()); + assertEquals(Transaction.DEFAULT_TX_FEE, request.tx.getFee()); } @Test public void lowerThanDefaultFee() throws InsufficientMoneyException { - Coin fee = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.divide(10); + Coin fee = Transaction.DEFAULT_TX_FEE.divide(10); receiveATransactionAmount(wallet, myAddress, Coin.COIN); SendRequest req = SendRequest.to(myAddress, Coin.CENT); req.feePerKb = fee; @@ -2820,7 +2820,7 @@ public class WalletTest extends TestWithWallet { @Test public void higherThanDefaultFee() throws InsufficientMoneyException { - Coin fee = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(10); + Coin fee = Transaction.DEFAULT_TX_FEE.multiply(10); receiveATransactionAmount(wallet, myAddress, Coin.COIN); SendRequest req = SendRequest.to(myAddress, Coin.CENT); req.feePerKb = fee; @@ -2832,7 +2832,7 @@ public class WalletTest extends TestWithWallet { emptyReq.emptyWallet = true; emptyReq.coinSelector = AllowUnconfirmedCoinSelector.get(); wallet.completeTx(emptyReq); - assertEquals(Coin.valueOf(17100), emptyReq.tx.getFee()); + assertEquals(Coin.valueOf(34200), emptyReq.tx.getFee()); wallet.commitTx(emptyReq.tx); } diff --git a/tools/src/main/java/org/bitcoinj/tools/WalletTool.java b/tools/src/main/java/org/bitcoinj/tools/WalletTool.java index cb6874d6a..43d68e5d4 100644 --- a/tools/src/main/java/org/bitcoinj/tools/WalletTool.java +++ b/tools/src/main/java/org/bitcoinj/tools/WalletTool.java @@ -357,7 +357,7 @@ public class WalletTool { System.err.println("--payment-request and --output cannot be used together."); return; } else if (options.has(outputFlag)) { - Coin feePerKb = Coin.ZERO; + Coin feePerKb = null; if (options.has(feePerKbOption)) feePerKb = parseCoin((String) options.valueOf(feePerKbOption)); String lockTime = null; @@ -378,7 +378,7 @@ public class WalletTool { System.err.println("You must specify a --output=addr:value"); return; } - Coin feePerKb = Coin.ZERO; + Coin feePerKb = null; if (options.has(feePerKbOption)) feePerKb = parseCoin((String) options.valueOf(feePerKbOption)); if (!options.has("locktime")) { @@ -398,7 +398,7 @@ public class WalletTool { System.err.println("You must specify a --output=addr:value"); return; } - Coin feePerKb = Coin.ZERO; + Coin feePerKb = null; if (options.has(feePerKbOption)) feePerKb = parseCoin((String) options.valueOf(feePerKbOption)); boolean allowUnconfirmed = options.has("allow-unconfirmed"); @@ -413,7 +413,7 @@ public class WalletTool { System.err.println("You must specify a --output=addr:value"); return; } - Coin feePerKb = Coin.ZERO; + Coin feePerKb = null; if (options.has(feePerKbOption)) feePerKb = parseCoin((String) options.valueOf(feePerKbOption)); boolean allowUnconfirmed = options.has("allow-unconfirmed"); @@ -596,7 +596,8 @@ public class WalletTool { log.info("Emptying out wallet, recipient may get less than what you expect"); req.emptyWallet = true; } - req.feePerKb = feePerKb; + if (feePerKb != null) + req.feePerKb = feePerKb; if (allowUnconfirmed) { wallet.allowSpendingUnconfirmedTransactions(); } @@ -727,7 +728,8 @@ public class WalletTool { log.info("Emptying out wallet, recipient may get less than what you expect"); req.emptyWallet = true; } - req.feePerKb = feePerKb; + if (feePerKb != null) + req.feePerKb = feePerKb; if (allowUnconfirmed) { wallet.allowSpendingUnconfirmedTransactions(); } @@ -794,7 +796,8 @@ public class WalletTool { Wallet.SendRequest req = outputSpec.isAddress() ? Wallet.SendRequest.to(outputSpec.addr, value) : Wallet.SendRequest.to(params, outputSpec.key, value); - req.feePerKb = feePerKb; + if (feePerKb != null) + req.feePerKb = feePerKb; Transaction lockTimeVerify = wallet.getTransaction(Sha256Hash.wrap(txHash)); if (lockTimeVerify == null) { @@ -897,7 +900,8 @@ public class WalletTool { Wallet.SendRequest req = outputSpec.isAddress() ? Wallet.SendRequest.to(outputSpec.addr, value) : Wallet.SendRequest.to(params, outputSpec.key, value); - req.feePerKb = feePerKb; + if (feePerKb != null) + req.feePerKb = feePerKb; Transaction lockTimeVerify = wallet.getTransaction(Sha256Hash.wrap(txHash)); if (lockTimeVerify == null) {