add support for existing vins for fundrawtransaction

This commit is contained in:
Jonas Schnelli 2014-12-20 21:49:31 +01:00 committed by Matt Corallo
parent 018828d666
commit cd42202ac3
4 changed files with 341 additions and 47 deletions

View file

@ -1334,27 +1334,73 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int
return true;
}
bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl) const
bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, vector<CTxIn> vPresetVINs, const CCoinControl* coinControl) const
{
vector<COutput> vCoins;
AvailableCoins(vCoins, true, coinControl);
// create a empty set to store possible VINS
set<pair<const CWalletTx*,unsigned int> > setTempCoins;
CAmount nValueTroughVINs = 0;
// coin control -> return all selected outputs (we want all selected to go into the transaction for sure)
if (coinControl && coinControl->HasSelected())
{
BOOST_FOREACH(const COutput& out, vCoins)
{
if(!out.fSpendable)
continue;
if (!out.fSpendable)
continue;
nValueRet += out.tx->vout[out.i].nValue;
setCoinsRet.insert(make_pair(out.tx, out.i));
}
return (nValueRet >= nTargetValue);
}
// fill up the tx with possible predefined VINs
BOOST_FOREACH(const CTxIn& txin, vPresetVINs)
{
bool vinOk = false;
// search for VIN in available coins
for (vector<COutput>::iterator it = vCoins.begin() ; it != vCoins.end();)
{
const COutput& out = *it;
if (out.tx->GetHash() == txin.prevout.hash && txin.prevout.n == (uint32_t)out.i)
{
if (!out.fSpendable)
continue;
nValueTroughVINs += out.tx->vout[out.i].nValue;
// temporary keep the coin to add them later after SelectCoinsMinConf has added some
setTempCoins.insert(make_pair(out.tx, out.i));
vinOk = true;
// remove the coins from available coins vector to avoid double use because of a upcomming SelectCoinsMinConf
it = vCoins.erase(it);
}
else
++it;
}
if (!vinOk)
return false; // if vin was not an available coin, cancel (will return "Insufficient funds")
}
return (SelectCoinsMinConf(nTargetValue, 1, 6, vCoins, setCoinsRet, nValueRet) ||
SelectCoinsMinConf(nTargetValue, 1, 1, vCoins, setCoinsRet, nValueRet) ||
(bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue, 0, 1, vCoins, setCoinsRet, nValueRet)));
bool state = true;
// only select further coins if we need to
if (nTargetValue-nValueTroughVINs > 0)
state = (SelectCoinsMinConf(nTargetValue-nValueTroughVINs, 1, 6, vCoins, setCoinsRet, nValueRet) ||
SelectCoinsMinConf(nTargetValue-nValueTroughVINs, 1, 1, vCoins, setCoinsRet, nValueRet) ||
(bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue-nValueTroughVINs, 0, 1, vCoins, setCoinsRet, nValueRet)));
// because SelectCoinsMinConf clears the setCoinsRet, we now add the possible VINs to the coinset
setCoinsRet.insert(setTempCoins.begin(), setTempCoins.end());
// increase return value due of possible vins
nValueRet+=nValueTroughVINs;
return state;
}
@ -1362,19 +1408,32 @@ bool CWallet::FundTransaction(const CTransaction& txToFund, CMutableTransaction&
{
vector<pair<CScript, CAmount> > vecSend;
vector<CTxIn> vin;
BOOST_FOREACH (const CTxOut& out, txToFund.vout)
BOOST_FOREACH (const CTxOut& txOut, txToFund.vout)
{
vecSend.push_back(make_pair(out.scriptPubKey, out.nValue));
vecSend.push_back(make_pair(txOut.scriptPubKey, txOut.nValue));
}
BOOST_FOREACH (const CTxIn& txIn, txToFund.vin)
{
vin.push_back(txIn);
}
CReserveKey reservekey(this);
CWalletTx wtx;
return CreateTransaction(vecSend, wtx, txNew, reservekey, nFeeRet, strFailReason, NULL, false);
return CreateTransaction(vecSend, vin, wtx, txNew, reservekey, nFeeRet, strFailReason, NULL, false);
}
bool CWallet::CreateTransaction(const vector<pair<CScript, CAmount> >& vecSend,
CWalletTx& wtxNew, CMutableTransaction& txNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl, bool sign)
{
vector<CTxIn> vINs;
return CreateTransaction(vecSend, vINs, wtxNew, txNew, reservekey, nFeeRet, strFailReason, coinControl, sign);
}
bool CWallet::CreateTransaction(const vector<pair<CScript, CAmount> >& vecSend, const vector<CTxIn> vINs,
CWalletTx& wtxNew, CMutableTransaction& txNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl, bool sign)
{
CAmount nValue = 0;
BOOST_FOREACH (const PAIRTYPE(CScript, CAmount)& s, vecSend)
@ -1422,7 +1481,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, CAmount> >& vecSend,
// Choose coins to use
set<pair<const CWalletTx*,unsigned int> > setCoins;
CAmount nValueIn = 0;
if (!SelectCoins(nTotalValue, setCoins, nValueIn, coinControl))
if (!SelectCoins(nTotalValue, setCoins, nValueIn, vINs, coinControl))
{
strFailReason = _("Insufficient funds");
return false;
@ -1566,7 +1625,8 @@ bool CWallet::CreateTransaction(CScript scriptPubKey, const CAmount& nValue,
vector< pair<CScript, CAmount> > vecSend;
vecSend.push_back(make_pair(scriptPubKey, nValue));
CMutableTransaction txNew;
return CreateTransaction(vecSend, wtxNew, txNew, reservekey, nFeeRet, strFailReason, coinControl, sign);
vector<CTxIn> vINs;
return CreateTransaction(vecSend, vINs, wtxNew, txNew, reservekey, nFeeRet, strFailReason, coinControl, sign);
}
/**