X-Git-Url: https://git.novaco.in/?p=novacoin.git;a=blobdiff_plain;f=src%2Fwallet.cpp;h=67a50abe75bf767b342b927a95c6a09c64774ec9;hp=3036f23d7df8bc43675c606c74bc808732444e2e;hb=9ca8b78544b413ed875ff9bb6ef376e21922e6ac;hpb=39bf335f3522b04fc78ad158f77ff99cfda84f5c diff --git a/src/wallet.cpp b/src/wallet.cpp index 3036f23..67a50ab 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -10,6 +10,7 @@ #include "ui_interface.h" #include "base58.h" #include "kernel.h" +#include "coincontrol.h" #include using namespace std; @@ -1026,7 +1027,7 @@ int64 CWallet::GetImmatureBalance() const } // populate vCoins with vector of spendable COutputs -void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed) const +void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl) const { vCoins.clear(); @@ -1049,8 +1050,10 @@ void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed) const continue; for (unsigned int i = 0; i < pcoin->vout.size(); i++) - if (!(pcoin->IsSpent(i)) && IsMine(pcoin->vout[i]) && pcoin->vout[i].nValue > 0) + if (!(pcoin->IsSpent(i)) && IsMine(pcoin->vout[i]) && pcoin->vout[i].nValue > 0 && + (!coinControl || !coinControl->HasSelected() || coinControl->IsSelected((*it).first, i))) vCoins.push_back(COutput(pcoin, i, pcoin->GetDepthInMainChain())); + } } } @@ -1225,20 +1228,28 @@ bool CWallet::SelectCoinsMinConf(int64 nTargetValue, unsigned int nSpendTime, in return true; } -bool CWallet::SelectCoins(int64 nTargetValue, unsigned int nSpendTime, set >& setCoinsRet, int64& nValueRet) const +bool CWallet::SelectCoins(int64 nTargetValue, unsigned int nSpendTime, set >& setCoinsRet, int64& nValueRet, const CCoinControl* coinControl) const { vector 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, nSpendTime, 1, 6, vCoins, setCoinsRet, nValueRet) || SelectCoinsMinConf(nTargetValue, nSpendTime, 1, 1, vCoins, setCoinsRet, nValueRet) || SelectCoinsMinConf(nTargetValue, nSpendTime, 0, 1, vCoins, setCoinsRet, nValueRet)); } - - - -bool CWallet::CreateTransaction(const vector >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet) +bool CWallet::CreateTransaction(const vector >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, const CCoinControl* coinControl) { int64 nValue = 0; BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend) @@ -1273,7 +1284,7 @@ bool CWallet::CreateTransaction(const vector >& vecSend, CW // Choose coins to use set > setCoins; int64 nValueIn = 0; - if (!SelectCoins(nTotalValue, wtxNew.nTime, setCoins, nValueIn)) + if (!SelectCoins(nTotalValue, wtxNew.nTime, setCoins, nValueIn, coinControl)) return false; BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins) { @@ -1301,22 +1312,30 @@ bool CWallet::CreateTransaction(const vector >& vecSend, CW 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 = reservekey.GetReservedKey(); - // assert(mapKeys.count(vchPubKey)); - // 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(&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 = reservekey.GetReservedKey(); + + scriptChange.SetDestination(vchPubKey.GetID()); + } // Insert change txn at random position: vector::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size()); @@ -1343,7 +1362,7 @@ bool CWallet::CreateTransaction(const vector >& vecSend, CW // Check that enough fee is included int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000); - int64 nMinFee = wtxNew.GetMinFee(1, false, GMF_SEND); + int64 nMinFee = wtxNew.GetMinFee(1, false, GMF_SEND, nBytes); if (nFeeRet < max(nPayFee, nMinFee)) { @@ -1362,11 +1381,11 @@ bool CWallet::CreateTransaction(const vector >& vecSend, CW return true; } -bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet) +bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, const CCoinControl* coinControl) { vector< pair > vecSend; vecSend.push_back(make_pair(scriptPubKey, nValue)); - return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet); + return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, coinControl); } // NovaCoin: get current stake weight