Wallet: Fix adjustOutputDownwardsForFee() to require a fee rate (per kb) rather than an absolute fee if ensureMinRequiredFee is true.

This commit is contained in:
Andreas Schildbach 2021-02-10 18:23:07 +01:00
parent d32dbf8fb0
commit 9336f1db1b
2 changed files with 11 additions and 6 deletions

View file

@ -4384,13 +4384,16 @@ public class Wallet extends BaseTaggableObject
}
}
/** Reduce the value of the first output of a transaction to pay the given feePerKb as appropriate for its size. */
/**
* Reduce the value of the first output of a transaction to pay the given feePerKb as appropriate for its size.
* If ensureMinRequiredFee is true, feePerKb is set to at least {@link Transaction#REFERENCE_DEFAULT_MIN_TX_FEE}.
*/
private boolean adjustOutputDownwardsForFee(Transaction tx, CoinSelection coinSelection, Coin feePerKb,
boolean ensureMinRequiredFee) {
if (ensureMinRequiredFee && feePerKb.compareTo(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE) < 0)
feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
final int vsize = tx.getVsize() + estimateVirtualBytesForSigning(coinSelection);
Coin fee = feePerKb.multiply(vsize).divide(1000);
if (ensureMinRequiredFee && fee.compareTo(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE) < 0)
fee = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
TransactionOutput output = tx.getOutput(0);
output.setValue(output.getValue().subtract(fee));
return !output.isDust();

View file

@ -81,12 +81,13 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.bitcoinj.core.Coin.*;
import static org.bitcoinj.core.Utils.HEX;
import static org.bitcoinj.testing.FakeTxBuilder.*;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.replay;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.hamcrest.Matchers.closeTo;
import static org.junit.Assert.*;
public class WalletTest extends TestWithWallet {
@ -2699,7 +2700,7 @@ public class WalletTest extends TestWithWallet {
@Test
public void lowerThanDefaultFee() throws InsufficientMoneyException {
int feeFactor = 50;
int feeFactor = 200;
Coin fee = Transaction.DEFAULT_TX_FEE.divide(feeFactor);
receiveATransactionAmount(wallet, myAddress, Coin.COIN);
SendRequest req = SendRequest.to(myAddress, Coin.CENT);
@ -2713,7 +2714,8 @@ public class WalletTest extends TestWithWallet {
emptyReq.emptyWallet = true;
emptyReq.allowUnconfirmed();
wallet.completeTx(emptyReq);
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, emptyReq.tx.getFee());
final Coin feePerKb = emptyReq.tx.getFee().multiply(1000).divide(emptyReq.tx.getVsize());
assertThat((double) feePerKb.toSat(), closeTo(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.toSat(),20));
wallet.commitTx(emptyReq.tx);
}