mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-19 23:03:45 +01:00
Coin Control Features
This commit is contained in:
committed by
Wladimir J. van der Laan
parent
8dfd8c62dc
commit
6a86c24db1
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user