aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/wallet/rpc/spend.cpp13
-rw-r--r--src/wallet/spend.cpp22
-rwxr-xr-xtest/functional/rpc_fundrawtransaction.py25
3 files changed, 43 insertions, 17 deletions
diff --git a/src/wallet/rpc/spend.cpp b/src/wallet/rpc/spend.cpp
index d1a0ba50f6..2520cd2532 100644
--- a/src/wallet/rpc/spend.cpp
+++ b/src/wallet/rpc/spend.cpp
@@ -699,19 +699,6 @@ void FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& fee_out,
setSubtractFeeFromOutputs.insert(pos);
}
- // Fetch specified UTXOs from the UTXO set to get the scriptPubKeys and values of the outputs being selected
- // and to match with the given solving_data. Only used for non-wallet outputs.
- std::map<COutPoint, Coin> coins;
- for (const CTxIn& txin : tx.vin) {
- coins[txin.prevout]; // Create empty map entry keyed by prevout.
- }
- wallet.chain().findCoins(coins);
- for (const auto& coin : coins) {
- if (!coin.second.out.IsNull()) {
- coinControl.SelectExternal(coin.first, coin.second.out);
- }
- }
-
bilingual_str error;
if (!FundTransaction(wallet, tx, fee_out, change_position, error, lockUnspents, setSubtractFeeFromOutputs, coinControl)) {
diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp
index 6f79ae4e9b..ce99aeefe5 100644
--- a/src/wallet/spend.cpp
+++ b/src/wallet/spend.cpp
@@ -1023,14 +1023,28 @@ bool FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& nFeeRet,
coinControl.fAllowOtherInputs = true;
- for (const CTxIn& txin : tx.vin) {
- coinControl.Select(txin.prevout);
- }
-
// Acquire the locks to prevent races to the new locked unspents between the
// CreateTransaction call and LockCoin calls (when lockUnspents is true).
LOCK(wallet.cs_wallet);
+ // Fetch specified UTXOs from the UTXO set to get the scriptPubKeys and values of the outputs being selected
+ // and to match with the given solving_data. Only used for non-wallet outputs.
+ std::map<COutPoint, Coin> coins;
+ for (const CTxIn& txin : tx.vin) {
+ coins[txin.prevout]; // Create empty map entry keyed by prevout.
+ }
+ wallet.chain().findCoins(coins);
+
+ for (const CTxIn& txin : tx.vin) {
+ // if it's not in the wallet and corresponding UTXO is found than select as external output
+ const auto& outPoint = txin.prevout;
+ if (wallet.mapWallet.find(outPoint.hash) == wallet.mapWallet.end() && !coins[outPoint].out.IsNull()) {
+ coinControl.SelectExternal(outPoint, coins[outPoint].out);
+ } else {
+ coinControl.Select(outPoint);
+ }
+ }
+
FeeCalculation fee_calc_out;
std::optional<CreatedTransactionResult> txr = CreateTransaction(wallet, vecSend, nChangePosInOut, error, coinControl, fee_calc_out, false);
if (!txr) return false;
diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py
index 759e43194b..948deaaec4 100755
--- a/test/functional/rpc_fundrawtransaction.py
+++ b/test/functional/rpc_fundrawtransaction.py
@@ -11,6 +11,9 @@ from math import ceil
from test_framework.descriptors import descsum_create
from test_framework.key import ECKey
+from test_framework.messages import (
+ COIN,
+)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_approx,
@@ -103,6 +106,7 @@ class RawTransactionsTest(BitcoinTestFramework):
self.generate(self.nodes[2], 1)
self.generate(self.nodes[0], 121)
+ self.test_weight_calculation()
self.test_change_position()
self.test_simple()
self.test_simple_two_coins()
@@ -1069,6 +1073,27 @@ class RawTransactionsTest(BitcoinTestFramework):
self.nodes[2].unloadwallet("extfund")
+ def test_weight_calculation(self):
+ self.log.info("Test weight calculation with external inputs")
+
+ self.nodes[2].createwallet("test_weight_calculation")
+ wallet = self.nodes[2].get_wallet_rpc("test_weight_calculation")
+
+ addr = wallet.getnewaddress()
+ txid = self.nodes[0].sendtoaddress(addr, 5)
+ vout = find_vout_for_address(self.nodes[0], txid, addr)
+
+ self.nodes[0].sendtoaddress(wallet.getnewaddress(), 5)
+ self.generate(self.nodes[0], 1)
+
+ rawtx = wallet.createrawtransaction([{'txid': txid, 'vout': vout}], [{self.nodes[0].getnewaddress(): 9.999}])
+ fundedtx = wallet.fundrawtransaction(rawtx, {'fee_rate': 10})
+ # with 71-byte signatures we should expect following tx size
+ tx_size = 10 + 41*2 + 31*2 + (2 + 107*2)/4
+ assert_equal(fundedtx['fee'] * COIN, tx_size * 10)
+
+ self.nodes[2].unloadwallet("test_weight_calculation")
+
def test_include_unsafe(self):
self.log.info("Test fundrawtxn with unsafe inputs")