@@ -1626,57 +1626,66 @@ int64_t CWalletTx::GetTxTime() const
1626
1626
1627
1627
// Helper for producing a max-sized low-S low-R signature (eg 71 bytes)
1628
1628
// or a max-sized low-S signature (e.g. 72 bytes) if use_max_sig is true
1629
- bool CWallet:: DummySignInput (CMutableTransaction& tx, const size_t nIn, const CTxOut& txout, bool use_max_sig) const
1629
+ static bool DummySignInput (const SigningProvider* provider, CMutableTransaction& tx, const size_t nIn, const CTxOut& txout, bool use_max_sig)
1630
1630
{
1631
1631
// Fill in dummy signatures for fee calculation.
1632
1632
const CScript& scriptPubKey = txout.scriptPubKey ;
1633
1633
SignatureData sigdata;
1634
1634
1635
- if (!ProduceSignature (*this , use_max_sig ? DUMMY_MAXIMUM_SIGNATURE_CREATOR : DUMMY_SIGNATURE_CREATOR, scriptPubKey, sigdata)) {
1635
+ if (!ProduceSignature (*provider , use_max_sig ? DUMMY_MAXIMUM_SIGNATURE_CREATOR : DUMMY_SIGNATURE_CREATOR, scriptPubKey, sigdata)) {
1636
1636
return false ;
1637
1637
}
1638
1638
UpdateTransaction (tx, nIn, sigdata);
1639
1639
return true ;
1640
1640
}
1641
1641
1642
1642
// Helper for producing a bunch of max-sized low-S low-R signatures (eg 71 bytes)
1643
- bool CWallet::DummySignTx (CMutableTransaction &txNew, const std::vector<CTxOut> &txouts, bool use_max_sig ) const
1643
+ bool CWallet::DummySignTx (CMutableTransaction &txNew, const std::vector<CTxOut> &txouts, const CCoinControl* coin_control ) const
1644
1644
{
1645
1645
// Fill in dummy signatures for fee calculation.
1646
1646
int nIn = 0 ;
1647
1647
for (const auto & txout : txouts)
1648
1648
{
1649
- if (!DummySignInput (txNew, nIn, txout, use_max_sig)) {
1650
- return false ;
1649
+ // Use max sig if watch only inputs were used or if this particular input is an external input
1650
+ bool use_max_sig = coin_control && (coin_control->fAllowWatchOnly || (coin_control && coin_control->IsExternalSelected (txNew.vin [nIn].prevout )));
1651
+ if (!DummySignInput (this , txNew, nIn, txout, use_max_sig)) {
1652
+ if (!coin_control || !DummySignInput (&coin_control->m_external_provider , txNew, nIn, txout, use_max_sig)) {
1653
+ return false ;
1654
+ }
1651
1655
}
1652
1656
1653
1657
nIn++;
1654
1658
}
1655
1659
return true ;
1656
1660
}
1657
1661
1658
- int64_t CalculateMaximumSignedTxSize (const CTransaction &tx, const CWallet *wallet, bool use_max_sig )
1662
+ int64_t CalculateMaximumSignedTxSize (const CTransaction &tx, const CWallet *wallet, const CCoinControl* coin_control )
1659
1663
{
1660
1664
std::vector<CTxOut> txouts;
1661
- // Look up the inputs. We should have already checked that this transaction
1662
- // IsAllFromMe(ISMINE_SPENDABLE), so every input should already be in our
1663
- // wallet, with a valid index into the vout array, and the ability to sign.
1665
+ // Look up the inputs. The inputs are either in the wallet, or in coin_control.
1664
1666
for (const CTxIn& input : tx.vin ) {
1665
1667
const auto mi = wallet->mapWallet .find (input.prevout .hash );
1666
- if (mi == wallet->mapWallet .end ()) {
1668
+ if (mi != wallet->mapWallet .end ()) {
1669
+ assert (input.prevout .n < mi->second .tx ->vout .size ());
1670
+ txouts.emplace_back (mi->second .tx ->vout [input.prevout .n ]);
1671
+ } else if (coin_control) {
1672
+ CTxOut txout;
1673
+ if (!coin_control->GetExternalOutput (input.prevout , txout)) {
1674
+ return -1 ;
1675
+ }
1676
+ txouts.emplace_back (txout);
1677
+ } else {
1667
1678
return -1 ;
1668
1679
}
1669
- assert (input.prevout .n < mi->second .tx ->vout .size ());
1670
- txouts.emplace_back (mi->second .tx ->vout [input.prevout .n ]);
1671
1680
}
1672
- return CalculateMaximumSignedTxSize (tx, wallet, txouts, use_max_sig );
1681
+ return CalculateMaximumSignedTxSize (tx, wallet, txouts, coin_control );
1673
1682
}
1674
1683
1675
1684
// txouts needs to be in the order of tx.vin
1676
- int64_t CalculateMaximumSignedTxSize (const CTransaction &tx, const CWallet *wallet, const std::vector<CTxOut>& txouts, bool use_max_sig )
1685
+ int64_t CalculateMaximumSignedTxSize (const CTransaction &tx, const CWallet *wallet, const std::vector<CTxOut>& txouts, const CCoinControl* coin_control )
1677
1686
{
1678
1687
CMutableTransaction txNew (tx);
1679
- if (!wallet->DummySignTx (txNew, txouts, use_max_sig )) {
1688
+ if (!wallet->DummySignTx (txNew, txouts, coin_control )) {
1680
1689
// This should never happen, because IsAllFromMe(ISMINE_SPENDABLE)
1681
1690
// implies that we can sign for every input.
1682
1691
return -1 ;
@@ -1688,7 +1697,7 @@ int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* wallet,
1688
1697
{
1689
1698
CMutableTransaction txn;
1690
1699
txn.vin .push_back (CTxIn (COutPoint ()));
1691
- if (!wallet-> DummySignInput (txn, 0 , txout, use_max_sig)) {
1700
+ if (!DummySignInput (wallet, txn, 0 , txout, use_max_sig)) {
1692
1701
// This should never happen, because IsAllFromMe(ISMINE_SPENDABLE)
1693
1702
// implies that we can sign for every input.
1694
1703
return -1 ;
@@ -2690,8 +2699,18 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
2690
2699
}
2691
2700
mapValueFromPresetInputs[pcoin->GetOutputAsset (outpoint.n )] += amt;
2692
2701
setPresetCoins.insert (CInputCoin (pcoin, outpoint.n ));
2693
- } else
2694
- return false ; // TODO: Allow non-wallet inputs
2702
+ } else {
2703
+ CTxOut txout;
2704
+ if (coin_control.GetExternalOutput (outpoint, txout)) {
2705
+ if (!txout.nValue .IsExplicit () || !txout.nAsset .IsExplicit ()) {
2706
+ return false ; // We can't get its value, so abort
2707
+ }
2708
+ mapValueFromPresetInputs[txout.nAsset .GetAsset ()] += txout.nValue .GetAmount ();
2709
+ setPresetCoins.insert (CInputCoin (outpoint, txout));
2710
+ } else {
2711
+ return false ;
2712
+ }
2713
+ }
2695
2714
}
2696
2715
2697
2716
// remove preset inputs from vCoins
@@ -2824,8 +2843,11 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC
2824
2843
coinControl.ListSelected (vPresetInputs);
2825
2844
for (const COutPoint& presetInput : vPresetInputs) {
2826
2845
std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find (presetInput.hash );
2846
+ CTxOut txout;
2827
2847
if (it != mapWallet.end ()) {
2828
2848
setAssets.insert (it->second .GetOutputAsset (presetInput.n ));
2849
+ } else if (coinControl.GetExternalOutput (presetInput, txout)) {
2850
+ setAssets.insert (txout.nAsset .GetAsset ());
2829
2851
}
2830
2852
}
2831
2853
@@ -3162,13 +3184,18 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
3162
3184
std::vector<COutPoint> vPresetInputs;
3163
3185
coin_control.ListSelected (vPresetInputs);
3164
3186
for (const COutPoint& presetInput : vPresetInputs) {
3187
+ CAsset asset;
3165
3188
std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find (presetInput.hash );
3166
- if (it == mapWallet.end ()) {
3189
+ CTxOut txout;
3190
+ if (it != mapWallet.end ()) {
3191
+ asset = it->second .GetOutputAsset (presetInput.n );
3192
+ } else if (coin_control.GetExternalOutput (presetInput, txout)) {
3193
+ asset = txout.nAsset .GetAsset ();
3194
+ } else {
3167
3195
// Ignore this here, will fail more gracefully later.
3168
3196
continue ;
3169
3197
}
3170
3198
3171
- CAsset asset = it->second .GetOutputAsset (presetInput.n );
3172
3199
if (mapScriptChange.find (asset) != mapScriptChange.end ()) {
3173
3200
// This asset already has a change script.
3174
3201
continue ;
@@ -3509,7 +3536,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
3509
3536
}
3510
3537
}
3511
3538
3512
- nBytes = CalculateMaximumSignedTxSize (CTransaction (txNew), this , coin_control. fAllowWatchOnly );
3539
+ nBytes = CalculateMaximumSignedTxSize (CTransaction (txNew), this , & coin_control);
3513
3540
if (nBytes < 0 ) {
3514
3541
strFailReason = _ (" Signing transaction failed" );
3515
3542
return false ;
0 commit comments