diff options
Diffstat (limited to 'src/wallet.cpp')
-rw-r--r-- | src/wallet.cpp | 64 |
1 files changed, 43 insertions, 21 deletions
diff --git a/src/wallet.cpp b/src/wallet.cpp index 868716cb2c..3e684a7879 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -7,6 +7,7 @@ #include "base58.h" #include "net.h" +#include "coincontrol.h" #include <inttypes.h> #include <stdint.h> @@ -1004,7 +1005,7 @@ int64_t CWallet::GetImmatureBalance() const } // populate vCoins with vector of spendable COutputs -void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed) const +void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl) const { vCoins.clear(); @@ -1025,8 +1026,9 @@ void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed) const for (unsigned int i = 0; i < pcoin->vout.size(); i++) { if (!(pcoin->IsSpent(i)) && IsMine(pcoin->vout[i]) && - !IsLockedCoin((*it).first, i) && pcoin->vout[i].nValue > 0) - vCoins.push_back(COutput(pcoin, i, pcoin->GetDepthInMainChain())); + !IsLockedCoin((*it).first, i) && pcoin->vout[i].nValue > 0 && + (!coinControl || !coinControl->HasSelected() || coinControl->IsSelected((*it).first, i))) + vCoins.push_back(COutput(pcoin, i, pcoin->GetDepthInMainChain())); } } } @@ -1176,10 +1178,21 @@ bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfT return true; } -bool CWallet::SelectCoins(int64_t nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet) const +bool CWallet::SelectCoins(int64_t nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet, const CCoinControl* coinControl) const { vector<COutput> vCoins; - AvailableCoins(vCoins); + AvailableCoins(vCoins, true, coinControl); + + // 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) + { + nValueRet += out.tx->vout[out.i].nValue; + setCoinsRet.insert(make_pair(out.tx, out.i)); + } + return (nValueRet >= nTargetValue); + } return (SelectCoinsMinConf(nTargetValue, 1, 6, vCoins, setCoinsRet, nValueRet) || SelectCoinsMinConf(nTargetValue, 1, 1, vCoins, setCoinsRet, nValueRet) || @@ -1190,7 +1203,7 @@ bool CWallet::SelectCoins(int64_t nTargetValue, set<pair<const CWalletTx*,unsign bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend, - CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason) + CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl) { int64_t nValue = 0; BOOST_FOREACH (const PAIRTYPE(CScript, int64_t)& s, vecSend) @@ -1237,7 +1250,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend, // Choose coins to use set<pair<const CWalletTx*,unsigned int> > setCoins; int64_t nValueIn = 0; - if (!SelectCoins(nTotalValue, setCoins, nValueIn)) + if (!SelectCoins(nTotalValue, setCoins, nValueIn, coinControl)) { strFailReason = _("Insufficient funds"); return false; @@ -1265,22 +1278,31 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend, if (nChange > 0) { - // Note: We use a new key here to keep it from being obvious which side is the change. - // The drawback is that by not reusing a previous key, the change may be lost if a - // backup is restored, if the backup doesn't have the new private key for the change. - // If we reused the old key, it would be possible to add code to look for and - // rediscover unknown transactions that were written with keys of ours to recover - // post-backup change. - - // Reserve a new key pair from key pool - CPubKey vchPubKey; - assert(reservekey.GetReservedKey(vchPubKey)); // should never fail, as we just unlocked - // Fill a vout to ourself // TODO: pass in scriptChange instead of reservekey so // change transaction isn't always pay-to-bitcoin-address CScript scriptChange; - scriptChange.SetDestination(vchPubKey.GetID()); + + // coin control: send change to custom address + if (coinControl && !boost::get<CNoDestination>(&coinControl->destChange)) + scriptChange.SetDestination(coinControl->destChange); + + // no coin control: send change to newly generated address + else + { + // Note: We use a new key here to keep it from being obvious which side is the change. + // The drawback is that by not reusing a previous key, the change may be lost if a + // backup is restored, if the backup doesn't have the new private key for the change. + // If we reused the old key, it would be possible to add code to look for and + // rediscover unknown transactions that were written with keys of ours to recover + // post-backup change. + + // Reserve a new key pair from key pool + CPubKey vchPubKey; + assert(reservekey.GetReservedKey(vchPubKey)); // should never fail, as we just unlocked + + scriptChange.SetDestination(vchPubKey.GetID()); + } CTxOut newTxOut(nChange, scriptChange); @@ -1353,11 +1375,11 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend, } bool CWallet::CreateTransaction(CScript scriptPubKey, int64_t nValue, - CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason) + CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl) { vector< pair<CScript, int64_t> > vecSend; vecSend.push_back(make_pair(scriptPubKey, nValue)); - return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, strFailReason); + return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, strFailReason, coinControl); } // Call after CreateTransaction unless you want to abort |