@@ -2713,11 +2713,25 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, CAmount> >& vecSend,
27132713 // TODO: pass in scriptChange instead of reservekey so
27142714 // change transaction isn't always pay-to-pivx-address
27152715 CScript scriptChange;
2716+ bool combineChange = false ;
27162717
27172718 // coin control: send change to custom address
2718- if (coinControl && !boost::get<CNoDestination>(&coinControl->destChange ))
2719+ if (coinControl && !boost::get<CNoDestination>(&coinControl->destChange )) {
27192720 scriptChange = GetScriptForDestination (coinControl->destChange );
27202721
2722+ vector<CTxOut>::iterator it = txNew.vout .begin ();
2723+ while (it != txNew.vout .end ()) {
2724+ if (scriptChange == it->scriptPubKey ) {
2725+ it->nValue += nChange;
2726+ nChange = 0 ;
2727+ reservekey.ReturnKey ();
2728+ combineChange = true ;
2729+ break ;
2730+ }
2731+ ++it;
2732+ }
2733+ }
2734+
27212735 // no coin control: send change to newly generated address
27222736 else {
27232737 // Note: We use a new key here to keep it from being obvious which side is the change.
@@ -2736,18 +2750,20 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, CAmount> >& vecSend,
27362750 scriptChange = GetScriptForDestination (vchPubKey.GetID ());
27372751 }
27382752
2739- CTxOut newTxOut (nChange, scriptChange);
2740-
2741- // Never create dust outputs; if we would, just
2742- // add the dust to the fee.
2743- if (newTxOut.IsDust (::minRelayTxFee)) {
2744- nFeeRet += nChange;
2745- nChange = 0 ;
2746- reservekey.ReturnKey ();
2747- } else {
2748- // Insert change txn at random position:
2749- vector<CTxOut>::iterator position = txNew.vout .begin () + GetRandInt (txNew.vout .size () + 1 );
2750- txNew.vout .insert (position, newTxOut);
2753+ if (!combineChange) {
2754+ CTxOut newTxOut (nChange, scriptChange);
2755+
2756+ // Never create dust outputs; if we would, just
2757+ // add the dust to the fee.
2758+ if (newTxOut.IsDust (::minRelayTxFee)) {
2759+ nFeeRet += nChange;
2760+ nChange = 0 ;
2761+ reservekey.ReturnKey ();
2762+ } else {
2763+ // Insert change txn at random position:
2764+ vector<CTxOut>::iterator position = txNew.vout .begin () + GetRandInt (txNew.vout .size () + 1 );
2765+ txNew.vout .insert (position, newTxOut);
2766+ }
27512767 }
27522768 } else
27532769 reservekey.ReturnKey ();
@@ -4003,6 +4019,8 @@ void CWallet::AutoCombineDust()
40034019 CCoinControl* coinControl = new CCoinControl ();
40044020 CAmount nTotalRewardsValue = 0 ;
40054021 BOOST_FOREACH (const COutput& out, vCoins) {
4022+ if (!out.fSpendable )
4023+ continue ;
40064024 // no coins should get this far if they dont have proper maturity, this is double checking
40074025 if (out.tx ->IsCoinStake () && out.tx ->GetDepthInMainChain () < COINBASE_MATURITY + 1 )
40084026 continue ;
@@ -4034,24 +4052,30 @@ void CWallet::AutoCombineDust()
40344052 CScript scriptPubKey = GetScriptForDestination (it->first .Get ());
40354053 vecSend.push_back (make_pair (scriptPubKey, nTotalRewardsValue));
40364054
4055+ // Send change to same address
4056+ CTxDestination destMyAddress;
4057+ if (!ExtractDestination (scriptPubKey, destMyAddress)) {
4058+ LogPrintf (" AutoCombineDust: failed to extract destination\n " );
4059+ continue ;
4060+ }
4061+ coinControl->destChange = destMyAddress;
4062+
40374063 // Create the transaction and commit it to the network
40384064 CWalletTx wtx;
40394065 CReserveKey keyChange (this ); // this change address does not end up being used, because change is returned with coin control switch
40404066 string strErr;
40414067 CAmount nFeeRet = 0 ;
40424068
4043- // get the fee amount
4044- CWalletTx wtxdummy;
4045- CreateTransaction (vecSend, wtxdummy, keyChange, nFeeRet, strErr, coinControl, ALL_COINS, false , CAmount (0 ));
4046- vecSend[0 ].second = nTotalRewardsValue - nFeeRet - 500 ;
4069+ // 10% safety margin to avoid "Insufficient funds" errors
4070+ vecSend[0 ].second = nTotalRewardsValue - (nTotalRewardsValue / 10 );
40474071
40484072 if (!CreateTransaction (vecSend, wtx, keyChange, nFeeRet, strErr, coinControl, ALL_COINS, false , CAmount (0 ))) {
40494073 LogPrintf (" AutoCombineDust createtransaction failed, reason: %s\n " , strErr);
40504074 continue ;
40514075 }
40524076
40534077 // we don't combine below the threshold unless the fees are 0 to avoid paying fees over fees over fees
4054- if (vecSend[ 0 ]. second < nAutoCombineThreshold * COIN && nFeeRet > 0 )
4078+ if (nTotalRewardsValue < nAutoCombineThreshold * COIN && nFeeRet > 0 )
40554079 continue ;
40564080
40574081 if (!CommitTransaction (wtx, keyChange)) {
0 commit comments