@@ -551,7 +551,7 @@ bool CWallet::GetMasternodeVinAndKeys(CTxIn& txinRet, CPubKey& pubKeyRet, CKey&
551551
552552 // Find possible candidates (remove delegated)
553553 std::vector<COutput> vPossibleCoins;
554- AvailableCoins (vPossibleCoins, true , NULL , false , ONLY_10000, false , 1 , false , false );
554+ AvailableCoins (& vPossibleCoins, true , NULL , false , ONLY_10000, false , 1 , false , false );
555555
556556 if (vPossibleCoins.empty ()) {
557557 LogPrintf (" CWallet::GetMasternodeVinAndKeys -- Could not locate any valid masternode vin\n " );
@@ -1950,19 +1950,18 @@ void CWallet::GetAvailableP2CSCoins(std::vector<COutput>& vCoins) const {
19501950/* *
19511951 * populate vCoins with vector of available COutputs.
19521952 */
1953- void CWallet::AvailableCoins (
1954- std::vector<COutput>& vCoins ,
1953+ bool CWallet::AvailableCoins (
1954+ std::vector<COutput>* pCoins ,
19551955 bool fOnlyConfirmed ,
19561956 const CCoinControl* coinControl,
19571957 bool fIncludeZeroValue ,
19581958 AvailableCoinsType nCoinType,
19591959 bool fUseIX ,
19601960 int nWatchonlyConfig,
19611961 bool fIncludeColdStaking ,
1962- bool fIncludeDelegated ,
1963- bool fJustOne ) const
1962+ bool fIncludeDelegated ) const
19641963{
1965- vCoins. clear ();
1964+ if (pCoins) pCoins-> clear ();
19661965 const bool fCoinsSelected = (coinControl != nullptr ) && coinControl->HasSelected ();
19671966 // include delegated coins when coinControl is active
19681967 if (!fIncludeDelegated && fCoinsSelected )
@@ -2032,18 +2031,19 @@ void CWallet::AvailableCoins(
20322031 (fIncludeDelegated ? ISMINE_SPENDABLE_DELEGATED : ISMINE_NO) )) != ISMINE_NO));
20332032
20342033 // found valid coin
2035- vCoins. emplace_back ( COutput (pcoin, i, nDepth, fIsValid )) ;
2036- if ( fJustOne ) return ;
2034+ if (!pCoins) return true ;
2035+ pCoins-> emplace_back ( COutput (pcoin, i, nDepth, fIsValid )) ;
20372036 }
20382037 }
2038+ return (pCoins && pCoins->size () > 0 );
20392039 }
20402040}
20412041
20422042std::map<CBitcoinAddress, std::vector<COutput> > CWallet::AvailableCoinsByAddress (bool fConfirmed , CAmount maxCoinValue)
20432043{
20442044 std::vector<COutput> vCoins;
20452045 // include cold and delegated coins
2046- AvailableCoins (vCoins, fConfirmed , nullptr , false , ALL_COINS, false , 1 , true , true );
2046+ AvailableCoins (& vCoins, fConfirmed , nullptr , false , ALL_COINS, false , 1 , true , true );
20472047
20482048 std::map<CBitcoinAddress, std::vector<COutput> > mapCoins;
20492049 for (COutput out : vCoins) {
@@ -2123,47 +2123,7 @@ bool less_then_denom(const COutput& out1, const COutput& out2)
21232123 return (!found1 && found2);
21242124}
21252125
2126- bool CWallet::SelectStakeCoins (std::list<std::unique_ptr<CStakeInput> >& listInputs, CAmount nTargetAmount, int blockHeight)
2127- {
2128- LOCK (cs_main);
2129- // Add PIV
2130- std::vector<COutput> vCoins;
2131-
2132- // include cold, exclude delegated
2133- const bool fIncludeCold = sporkManager.IsSporkActive (SPORK_17_COLDSTAKING_ENFORCEMENT) && GetBoolArg (" -coldstaking" , true );
2134- AvailableCoins (vCoins, true , NULL , false , STAKABLE_COINS, false , 1 , fIncludeCold , false );
2135-
2136- CAmount nAmountSelected = 0 ;
2137- if (GetBoolArg (" -pivstake" , true )) {
2138- for (const COutput &out : vCoins) {
2139- // make sure not to outrun target amount
2140- if (nAmountSelected + out.tx ->vout [out.i ].nValue > nTargetAmount)
2141- continue ;
2142-
2143- if (out.tx ->vin [0 ].IsZerocoinSpend () && !out.tx ->IsInMainChain ())
2144- continue ;
2145-
2146- if (!out.tx ->hashBlock )
2147- continue ;
2148-
2149- CBlockIndex* utxoBlock = mapBlockIndex.at (out.tx ->hashBlock );
2150- // check for maturity (min age/depth)
2151- if (!Params ().HasStakeMinAgeOrDepth (blockHeight, GetAdjustedTime (), utxoBlock->nHeight , utxoBlock->GetBlockTime ()))
2152- continue ;
2153-
2154- // add to our stake set
2155- nAmountSelected += out.tx ->vout [out.i ].nValue ;
2156-
2157- std::unique_ptr<CPivStake> input (new CPivStake ());
2158- input->SetInput ((CTransaction) *out.tx , out.i );
2159- listInputs.emplace_back (std::move (input));
2160- }
2161- }
2162-
2163- return true ;
2164- }
2165-
2166- bool CWallet::MintableCoins ()
2126+ bool CWallet::MintableCoins (std::vector<COutput>* pCoins)
21672127{
21682128 CAmount nBalance = GetStakingBalance (GetBoolArg (" -coldstaking" , true ));
21692129
@@ -2172,23 +2132,26 @@ bool CWallet::MintableCoins()
21722132 return error (" %s : invalid reserve balance amount" , __func__);
21732133 if (nBalance <= nReserveBalance) return false ;
21742134
2175- std::vector<COutput> vCoins;
21762135 const bool fIncludeCold = (sporkManager.IsSporkActive (SPORK_17_COLDSTAKING_ENFORCEMENT) &&
21772136 GetBoolArg (" -coldstaking" , true ));
2178- AvailableCoins (vCoins,
2179- true , // fOnlyConfirmed
2180- nullptr , // coinControl
2181- false , // fIncludeZeroValue
2182- STAKABLE_COINS, // nCoinType
2183- false , // fUseIX
2184- 1 , // nWatchonlyConfig
2185- fIncludeCold , // fIncludeColdStaking
2186- false , // fIncludeDelegated
2187- true // fJustOne
2188- );
2189-
2190- // check that we have at least one utxo eligible for staking.
2191- return (vCoins.size () > 0 );
2137+
2138+ if (!AvailableCoins (pCoins, true , nullptr , false , STAKABLE_COINS, false , 1 , fIncludeCold , false ))
2139+ return false ;
2140+
2141+ if (!pCoins || nReserveBalance == 0 )
2142+ // there is at least one stakeable utxo
2143+ return true ;
2144+
2145+ CAmount nTargetAmount = nBalance - nReserveBalance;
2146+ CAmount nAmountSelected = 0 ;
2147+ // leave some utxo for reserve balance
2148+ for (const COutput &out : *pCoins) {
2149+ const CAmount& nAmountUtxo = out.tx ->vout [out.i ].nValue ;
2150+ if (nAmountSelected + nAmountUtxo > nTargetAmount) continue ;
2151+ nAmountSelected += out.tx ->vout [out.i ].nValue ;
2152+ }
2153+
2154+ return (pCoins->size () > 0 );
21922155}
21932156
21942157bool CWallet::SelectCoinsMinConf (const CAmount& nTargetValue, int nConfMine, int nConfTheirs, std::vector<COutput> vCoins, std::set<std::pair<const CWalletTx*, unsigned int > >& setCoinsRet, CAmount& nValueRet) const
@@ -2302,7 +2265,7 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, std::set<std::pair<const
23022265{
23032266 // Note: this function should never be used for "always free" tx types like dstx
23042267 std::vector<COutput> vCoins;
2305- AvailableCoins (vCoins, true , coinControl, false , coin_type, useIX, 1 , fIncludeColdStaking , fIncludeDelegated );
2268+ AvailableCoins (& vCoins, true , coinControl, false , coin_type, useIX, 1 , fIncludeColdStaking , fIncludeDelegated );
23062269
23072270 // coin control -> return all selected outputs (we want all selected to go into the transaction for sure)
23082271 if (coinControl && coinControl->HasSelected ()) {
@@ -2627,50 +2590,34 @@ bool CWallet::CreateCoinStake(
26272590 int64_t & nTxNewTime
26282591 )
26292592{
2630- txNew.vin .clear ();
2631- txNew.vout .clear ();
2632-
2633- // Mark coin stake transaction
2634- CScript scriptEmpty;
2635- scriptEmpty.clear ();
2636- txNew.vout .push_back (CTxOut (0 , scriptEmpty));
2637-
2638- // Choose coins to use
2639- CAmount nBalance = GetStakingBalance ();
2640-
2641- if (mapArgs.count (" -reservebalance" ) && !ParseMoney (mapArgs[" -reservebalance" ], nReserveBalance))
2642- return error (" CreateCoinStake : invalid reserve balance amount" );
2643-
2644- if (nBalance > 0 && nBalance <= nReserveBalance)
2593+ // Get the list of stakable utxos
2594+ std::vector<COutput> vCoins;
2595+ if (!MintableCoins (&vCoins)) {
2596+ LogPrintf (" %s: No coin available to stake.\n " , __func__);
26452597 return false ;
2598+ }
26462599
2647- // Get the list of stakable inputs
2600+ // Parse utxos into CPivStakes
26482601 std::list<std::unique_ptr<CStakeInput> > listInputs;
2649- if (!SelectStakeCoins (listInputs, nBalance - nReserveBalance, pindexPrev->nHeight + 1 )) {
2650- LogPrintf (" CreateCoinStake(): selectStakeCoins failed\n " );
2651- return false ;
2602+ for (const COutput &out : vCoins) {
2603+ std::unique_ptr<CPivStake> input (new CPivStake ());
2604+ input->SetInput ((CTransaction) *out.tx , out.i );
2605+ listInputs.emplace_back (std::move (input));
26522606 }
26532607
2654- if (listInputs.empty ()) {
2655- LogPrint (" staking" , " CreateCoinStake(): listInputs empty\n " );
2656- MilliSleep (50000 );
2657- return false ;
2658- }
2608+ // Mark coin stake transaction
2609+ txNew.vin .clear ();
2610+ txNew.vout .clear ();
2611+ txNew.vout .push_back (CTxOut (0 , CScript ()));
26592612
2660- if (GetAdjustedTime () - pindexPrev->GetBlockTime () < 60 ) {
2661- if (Params ().NetworkID () == CBaseChainParams::REGTEST) {
2662- MilliSleep (1000 );
2663- }
2664- }
2613+ // update staker status (hash)
2614+ pStakerStatus->SetLastTip (pindexPrev);
26652615
2616+ // Kernel Search
26662617 CAmount nCredit;
26672618 CScript scriptPubKeyKernel;
26682619 bool fKernelFound = false ;
26692620 int nAttempts = 0 ;
2670-
2671- // update staker status (hash)
2672- pStakerStatus->SetLastTip (pindexPrev);
2673-
26742621 for (std::unique_ptr<CStakeInput>& stakeInput : listInputs) {
26752622 // new block came in, move on
26762623 if (chainActive.Height () != pindexPrev->nHeight ) return false ;
@@ -3819,7 +3766,7 @@ bool CWallet::MultiSend()
38193766 }
38203767
38213768 std::vector<COutput> vCoins;
3822- AvailableCoins (vCoins);
3769+ AvailableCoins (& vCoins);
38233770 bool stakeSent = false ;
38243771 bool mnSent = false ;
38253772 for (const COutput& out : vCoins) {
0 commit comments