@@ -2664,6 +2664,33 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
2664
2664
return result;
2665
2665
}
2666
2666
2667
+ // Calculate the size of the transaction assuming all signatures are max size
2668
+ // Use DummySignatureCreator, which inserts 72 byte signatures everywhere.
2669
+ // TODO: re-use this in CWallet::CreateTransaction (right now
2670
+ // CreateTransaction uses the constructed dummy-signed tx to do a priority
2671
+ // calculation, but we should be able to refactor after priority is removed).
2672
+ // NOTE: this requires that all inputs must be in mapWallet (eg the tx should
2673
+ // be IsAllFromMe).
2674
+ int64_t CalculateMaximumSignedTxSize (const CTransaction &tx)
2675
+ {
2676
+ CMutableTransaction txNew (tx);
2677
+ std::vector<pair<CWalletTx *, unsigned int >> vCoins;
2678
+ // Look up the inputs. We should have already checked that this transaction
2679
+ // IsAllFromMe(ISMINE_SPENDABLE), so every input should already be in our
2680
+ // wallet, with a valid index into the vout array.
2681
+ for (auto & input : tx.vin ) {
2682
+ const auto mi = pwalletMain->mapWallet .find (input.prevout .hash );
2683
+ assert (mi != pwalletMain->mapWallet .end () && input.prevout .n < mi->second .tx ->vout .size ());
2684
+ vCoins.emplace_back (make_pair (&(mi->second ), input.prevout .n ));
2685
+ }
2686
+ if (!pwalletMain->DummySignTx (txNew, vCoins)) {
2687
+ // This should never happen, because IsAllFromMe(ISMINE_SPENDABLE)
2688
+ // implies that we can sign for every input.
2689
+ throw JSONRPCError (RPC_INVALID_ADDRESS_OR_KEY, " Transaction contains inputs that cannot be signed" );
2690
+ }
2691
+ return GetVirtualTransactionSize (txNew);
2692
+ }
2693
+
2667
2694
UniValue bumpfee (const JSONRPCRequest& request)
2668
2695
{
2669
2696
if (!EnsureWalletIsAvailable (request.fHelp )) {
@@ -2769,9 +2796,9 @@ UniValue bumpfee(const JSONRPCRequest& request)
2769
2796
throw JSONRPCError (RPC_MISC_ERROR, " Transaction does not have a change output" );
2770
2797
}
2771
2798
2772
- // signature sizes can vary by a byte, so add 1 for each input when calculating the new fee
2799
+ // Calculate the expected size of the new transaction.
2773
2800
int64_t txSize = GetVirtualTransactionSize (*(wtx.tx ));
2774
- const int64_t maxNewTxSize = txSize + wtx.tx -> vin . size ( );
2801
+ const int64_t maxNewTxSize = CalculateMaximumSignedTxSize (* wtx.tx );
2775
2802
2776
2803
// optional parameters
2777
2804
bool specifiedConfirmTarget = false ;
@@ -2845,8 +2872,12 @@ UniValue bumpfee(const JSONRPCRequest& request)
2845
2872
nNewFeeRate = CFeeRate (nNewFee, maxNewTxSize);
2846
2873
2847
2874
// New fee rate must be at least old rate + minimum incremental relay rate
2848
- if (nNewFeeRate.GetFeePerK () < nOldFeeRate.GetFeePerK () + walletIncrementalRelayFee.GetFeePerK ()) {
2849
- nNewFeeRate = CFeeRate (nOldFeeRate.GetFeePerK () + walletIncrementalRelayFee.GetFeePerK ());
2875
+ // walletIncrementalRelayFee.GetFeePerK() should be exact, because it's initialized
2876
+ // in that unit (fee per kb).
2877
+ // However, nOldFeeRate is a calculated value from the tx fee/size, so
2878
+ // add 1 satoshi to the result, because it may have been rounded down.
2879
+ if (nNewFeeRate.GetFeePerK () < nOldFeeRate.GetFeePerK () + 1 + walletIncrementalRelayFee.GetFeePerK ()) {
2880
+ nNewFeeRate = CFeeRate (nOldFeeRate.GetFeePerK () + 1 + walletIncrementalRelayFee.GetFeePerK ());
2850
2881
nNewFee = nNewFeeRate.GetFee (maxNewTxSize);
2851
2882
}
2852
2883
}
0 commit comments