55#include < consensus/validation.h>
66#include < interfaces/chain.h>
77#include < policy/policy.h>
8+ #include < script/signingprovider.h>
89#include < util/check.h>
910#include < util/fees.h>
1011#include < util/moneystr.h>
@@ -31,21 +32,27 @@ std::string COutput::ToString() const
3132 return strprintf (" COutput(%s, %d, %d) [%s]" , tx->GetHash ().ToString (), i, nDepth, FormatMoney (tx->tx ->vout [i].nValue ));
3233}
3334
34- int CalculateMaximumSignedInputSize (const CTxOut& txout, const CWallet* wallet , bool use_max_sig)
35+ int CalculateMaximumSignedInputSize (const CTxOut& txout, const SigningProvider* provider , bool use_max_sig)
3536{
3637 CMutableTransaction txn;
3738 txn.vin .push_back (CTxIn (COutPoint ()));
38- if (!wallet-> DummySignInput (txn.vin [0 ], txout, use_max_sig)) {
39+ if (!provider || ! DummySignInput (*provider, txn.vin [0 ], txout, use_max_sig)) {
3940 return -1 ;
4041 }
4142 return GetVirtualTransactionInputSize (txn.vin [0 ]);
4243}
4344
45+ int CalculateMaximumSignedInputSize (const CTxOut& txout, const CWallet* wallet, bool use_max_sig)
46+ {
47+ const std::unique_ptr<SigningProvider> provider = wallet->GetSolvingProvider (txout.scriptPubKey );
48+ return CalculateMaximumSignedInputSize (txout, provider.get (), use_max_sig);
49+ }
50+
4451// txouts needs to be in the order of tx.vin
45- TxSize CalculateMaximumSignedTxSize (const CTransaction &tx, const CWallet *wallet, const std::vector<CTxOut>& txouts, bool use_max_sig )
52+ TxSize CalculateMaximumSignedTxSize (const CTransaction &tx, const CWallet *wallet, const std::vector<CTxOut>& txouts, const CCoinControl* coin_control )
4653{
4754 CMutableTransaction txNew (tx);
48- if (!wallet->DummySignTx (txNew, txouts, use_max_sig )) {
55+ if (!wallet->DummySignTx (txNew, txouts, coin_control )) {
4956 return TxSize{-1 , -1 };
5057 }
5158 CTransaction ctx (txNew);
@@ -54,19 +61,27 @@ TxSize CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *walle
5461 return TxSize{vsize, weight};
5562}
5663
57- TxSize CalculateMaximumSignedTxSize (const CTransaction &tx, const CWallet *wallet, bool use_max_sig )
64+ TxSize CalculateMaximumSignedTxSize (const CTransaction &tx, const CWallet *wallet, const CCoinControl* coin_control )
5865{
5966 std::vector<CTxOut> txouts;
67+ // Look up the inputs. The inputs are either in the wallet, or in coin_control.
6068 for (const CTxIn& input : tx.vin ) {
6169 const auto mi = wallet->mapWallet .find (input.prevout .hash );
6270 // Can not estimate size without knowing the input details
63- if (mi == wallet->mapWallet .end ()) {
71+ if (mi != wallet->mapWallet .end ()) {
72+ assert (input.prevout .n < mi->second .tx ->vout .size ());
73+ txouts.emplace_back (mi->second .tx ->vout .at (input.prevout .n ));
74+ } else if (coin_control) {
75+ CTxOut txout;
76+ if (!coin_control->GetExternalOutput (input.prevout , txout)) {
77+ return TxSize{-1 , -1 };
78+ }
79+ txouts.emplace_back (txout);
80+ } else {
6481 return TxSize{-1 , -1 };
6582 }
66- assert (input.prevout .n < mi->second .tx ->vout .size ());
67- txouts.emplace_back (mi->second .tx ->vout [input.prevout .n ]);
6883 }
69- return CalculateMaximumSignedTxSize (tx, wallet, txouts, use_max_sig );
84+ return CalculateMaximumSignedTxSize (tx, wallet, txouts, coin_control );
7085}
7186
7287void AvailableCoins (const CWallet& wallet, std::vector<COutput>& vCoins, const CCoinControl* coinControl, const CAmount& nMinimumAmount, const CAmount& nMaximumAmount, const CAmount& nMinimumSumAmount, const uint64_t nMaximumCount)
@@ -435,32 +450,40 @@ bool SelectCoins(const CWallet& wallet, const std::vector<COutput>& vAvailableCo
435450
436451 std::vector<COutPoint> vPresetInputs;
437452 coin_control.ListSelected (vPresetInputs);
438- for (const COutPoint& outpoint : vPresetInputs)
439- {
453+ for (const COutPoint& outpoint : vPresetInputs) {
454+ int input_bytes = -1 ;
455+ CTxOut txout;
440456 std::map<uint256, CWalletTx>::const_iterator it = wallet.mapWallet .find (outpoint.hash );
441- if (it != wallet.mapWallet .end ())
442- {
457+ if (it != wallet.mapWallet .end ()) {
443458 const CWalletTx& wtx = it->second ;
444459 // Clearly invalid input, fail
445460 if (wtx.tx ->vout .size () <= outpoint.n ) {
446461 return false ;
447462 }
448- // Just to calculate the marginal byte size
449- CInputCoin coin (wtx.tx , outpoint.n , GetTxSpendSize (wallet, wtx, outpoint.n , false ));
450- nValueFromPresetInputs += coin.txout .nValue ;
451- if (coin.m_input_bytes <= 0 ) {
452- return false ; // Not solvable, can't estimate size for fee
453- }
454- coin.effective_value = coin.txout .nValue - coin_selection_params.m_effective_feerate .GetFee (coin.m_input_bytes );
455- if (coin_selection_params.m_subtract_fee_outputs ) {
456- value_to_select -= coin.txout .nValue ;
457- } else {
458- value_to_select -= coin.effective_value ;
463+ input_bytes = GetTxSpendSize (wallet, wtx, outpoint.n , false );
464+ txout = wtx.tx ->vout .at (outpoint.n );
465+ }
466+ if (input_bytes == -1 ) {
467+ // The input is external. We either did not find the tx in mapWallet, or we did but couldn't compute the input size with wallet data
468+ if (!coin_control.GetExternalOutput (outpoint, txout)) {
469+ // Not ours, and we don't have solving data.
470+ return false ;
459471 }
460- setPresetCoins.insert (coin);
472+ input_bytes = CalculateMaximumSignedInputSize (txout, &coin_control.m_external_provider , /* use_max_sig */ true );
473+ }
474+
475+ CInputCoin coin (outpoint, txout, input_bytes);
476+ nValueFromPresetInputs += coin.txout .nValue ;
477+ if (coin.m_input_bytes <= 0 ) {
478+ return false ; // Not solvable, can't estimate size for fee
479+ }
480+ coin.effective_value = coin.txout .nValue - coin_selection_params.m_effective_feerate .GetFee (coin.m_input_bytes );
481+ if (coin_selection_params.m_subtract_fee_outputs ) {
482+ value_to_select -= coin.txout .nValue ;
461483 } else {
462- return false ; // TODO: Allow non-wallet inputs
484+ value_to_select -= coin. effective_value ;
463485 }
486+ setPresetCoins.insert (coin);
464487 }
465488
466489 // remove preset inputs from vCoins so that Coin Selection doesn't pick them.
@@ -788,10 +811,10 @@ static bool CreateTransactionInternal(
788811 }
789812
790813 // Calculate the transaction fee
791- TxSize tx_sizes = CalculateMaximumSignedTxSize (CTransaction (txNew), &wallet, coin_control. fAllowWatchOnly );
814+ TxSize tx_sizes = CalculateMaximumSignedTxSize (CTransaction (txNew), &wallet, & coin_control);
792815 int nBytes = tx_sizes.vsize ;
793816 if (nBytes < 0 ) {
794- error = _ (" Signing transaction failed " );
817+ error = _ (" Missing solving data for estimating transaction size " );
795818 return false ;
796819 }
797820 nFeeRet = coin_selection_params.m_effective_feerate .GetFee (nBytes);
@@ -813,7 +836,7 @@ static bool CreateTransactionInternal(
813836 txNew.vout .erase (change_position);
814837
815838 // Because we have dropped this change, the tx size and required fee will be different, so let's recalculate those
816- tx_sizes = CalculateMaximumSignedTxSize (CTransaction (txNew), &wallet, coin_control. fAllowWatchOnly );
839+ tx_sizes = CalculateMaximumSignedTxSize (CTransaction (txNew), &wallet, & coin_control);
817840 nBytes = tx_sizes.vsize ;
818841 fee_needed = coin_selection_params.m_effective_feerate .GetFee (nBytes);
819842 }
0 commit comments