From 4ea8546cd31bac86148d683ae6c6a85392ce154a Mon Sep 17 00:00:00 2001 From: Andreas Schildbach Date: Tue, 16 Nov 2021 23:10:50 +0100 Subject: [PATCH] Script: take into account the various witness length fields in getNumberOfBytesRequiredToSpend() This (hopefully entirely) fixes the slight fee underspending for spends from P2WPKH. --- core/src/main/java/org/bitcoinj/script/Script.java | 7 ++++++- core/src/test/java/org/bitcoinj/wallet/WalletTest.java | 8 +++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/bitcoinj/script/Script.java b/core/src/main/java/org/bitcoinj/script/Script.java index 6973bf0b5..fce6a71be 100644 --- a/core/src/main/java/org/bitcoinj/script/Script.java +++ b/core/src/main/java/org/bitcoinj/script/Script.java @@ -606,7 +606,12 @@ public class Script { // scriptSig is empty // witness: int compressedPubKeySize = 33; - return SIG_SIZE + (pubKey != null ? pubKey.getPubKey().length : compressedPubKeySize); + int publicKeyLength = pubKey != null ? pubKey.getPubKey().length : compressedPubKeySize; + return VarInt.sizeOf(2) // number of witness pushes + + VarInt.sizeOf(SIG_SIZE) // size of signature push + + SIG_SIZE // signature push + + VarInt.sizeOf(publicKeyLength) // size of pubKey push + + publicKeyLength; // pubKey push } else { throw new IllegalStateException("Unsupported script type"); } diff --git a/core/src/test/java/org/bitcoinj/wallet/WalletTest.java b/core/src/test/java/org/bitcoinj/wallet/WalletTest.java index 45313ae3c..89d769bb1 100644 --- a/core/src/test/java/org/bitcoinj/wallet/WalletTest.java +++ b/core/src/test/java/org/bitcoinj/wallet/WalletTest.java @@ -2696,7 +2696,13 @@ public class WalletTest extends TestWithWallet { SendRequest request = SendRequest.to(OTHER_SEGWIT_ADDRESS, CENT); request.feePerKb = Transaction.DEFAULT_TX_FEE; mySegwitWallet.completeTx(request); - assertEquals(Coin.valueOf(14000), request.tx.getFee()); + + // Fee test, absolute and per virtual kilobyte + Coin fee = request.tx.getFee(); + int vsize = request.tx.getVsize(); + Coin feePerVkb = fee.multiply(1000).divide(vsize); + assertEquals(Coin.valueOf(14100), fee); + assertEquals(Transaction.DEFAULT_TX_FEE, feePerVkb); } @Test