@@ -1673,6 +1673,8 @@ bool CWallet::SelectCoins(int64_t nTargetValue, unsigned int nSpendTime, set<pai
16731673 }
16741674
16751675 if (contract) {
1676+ LogPrint (BCLog::LogFlags::ESTIMATEFEE, " INFO %s: Contract is included so SelectSmallestCoins will be used." , __func__);
1677+
16761678 return (SelectSmallestCoins (nTargetValue, nSpendTime, 1 , 10 , vCoins, setCoinsRet, nValueRet) ||
16771679 SelectSmallestCoins (nTargetValue, nSpendTime, 1 , 1 , vCoins, setCoinsRet, nValueRet) ||
16781680 SelectSmallestCoins (nTargetValue, nSpendTime, 0 , 1 , vCoins, setCoinsRet, nValueRet));
@@ -1795,12 +1797,15 @@ bool CWallet::SelectCoinsForStaking(unsigned int nSpendTime, std::vector<pair<co
17951797 return true ;
17961798}
17971799
1798- bool CWallet::CreateTransaction (const vector<pair<CScript, int64_t > >& vecSend, set<pair<const CWalletTx*,unsigned int >>& setCoins ,
1800+ bool CWallet::CreateTransaction (const vector<pair<CScript, int64_t > >& vecSend, set<pair<const CWalletTx*,unsigned int >>& setCoins_in ,
17991801 CWalletTx& wtxNew, CReserveKey& reservekey, int64_t & nFeeRet, const CCoinControl* coinControl)
18001802{
18011803
18021804 int64_t nValueOut = 0 ;
18031805 int64_t message_fee = 0 ;
1806+ set<pair<const CWalletTx*,unsigned int >> setCoins_out;
1807+
1808+ bool provided_coin_set = !setCoins_in.empty ();
18041809
18051810 for (auto const & s : vecSend)
18061811 {
@@ -1833,10 +1838,13 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
18331838 {
18341839 wtxNew.vin .clear ();
18351840 wtxNew.vout .clear ();
1841+ setCoins_out.clear ();
18361842 wtxNew.fFromMe = true ;
18371843
18381844 int64_t nTotalValue = nValueOut + nFeeRet;
1839- double dPriority = 0 ;
1845+ // dPriority is not currently used. Commented out.
1846+ // double dPriority = 0;
1847+
18401848 // vouts to the payees
18411849 for (auto const & s : vecSend)
18421850 wtxNew.vout .emplace_back (s.second , s.first );
@@ -1850,7 +1858,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
18501858 int64_t nValueIn = 0 ;
18511859
18521860 // If provided coin set is empty, choose coins to use.
1853- if (!setCoins. size () )
1861+ if (!provided_coin_set )
18541862 {
18551863 // If the transaction contains a contract, we want to select the
18561864 // smallest UTXOs available:
@@ -1862,29 +1870,75 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
18621870 && !wtxNew.vContracts .empty ()
18631871 && wtxNew.vContracts [0 ].m_type != GRC::ContractType::MESSAGE;
18641872
1865- if (!SelectCoins (nTotalValue, wtxNew.nTime , setCoins, nValueIn, coinControl, contract)) {
1873+ // Notice that setCoins_out is that set PRODUCED by SelectCoins. Tying this to the input
1874+ // parameter of CreateTransaction was a major bug here before. It is now separated.
1875+ if (!SelectCoins (nTotalValue, wtxNew.nTime , setCoins_out, nValueIn, coinControl, contract)) {
18661876 return error (" %s: Failed to select coins" , __func__);
18671877 }
1878+
1879+ if (LogInstance ().WillLogCategory (BCLog::LogFlags::ESTIMATEFEE))
1880+ {
1881+ CAmount setcoins_total = 0 ;
1882+
1883+ for (const auto & output: setCoins_out)
1884+ {
1885+ setcoins_total += output.first ->vout [output.second ].nValue ;
1886+ }
1887+
1888+ LogPrintf (" INFO %s: Just after SelectCoins: "
1889+ " nTotalValue = %s, nValueIn = %s, nValueOut = %s, setCoins total = %s." ,
1890+ __func__,
1891+ FormatMoney (nTotalValue),
1892+ FormatMoney (nValueIn),
1893+ FormatMoney (nValueOut),
1894+ FormatMoney (setcoins_total));
1895+ }
1896+
1897+ // Compute dPriority on automatically selected coins.
1898+ /*
1899+ for (auto const& input : setCoins_out)
1900+ {
1901+ int64_t nCredit = input.first->vout[input.second].nValue;
1902+ dPriority += (double) nCredit * input.first->GetDepthInMainChain();
1903+ }
1904+ */
18681905 }
18691906 else
18701907 {
1871- // Add up input value for the provided set of coins.
1872- for (auto const & input : setCoins)
1908+ // Add up input value for the provided set of coins, and also compute dPriority. (dPriority is
1909+ // commented out because it is not actually used right now.
1910+ for (auto const & input : setCoins_in)
18731911 {
1874- nValueIn += input.first ->vout [input.second ].nValue ;
1912+ int64_t nCredit = input.first ->vout [input.second ].nValue ;
1913+ // dPriority += (double) nCredit * input.first->GetDepthInMainChain();
1914+ nValueIn += nCredit;
18751915 }
18761916 }
18771917
1878- for (auto const & pcoin : setCoins)
1918+ int64_t nChange = nValueIn - nValueOut - nFeeRet;
1919+
1920+ // Note: In the case where CreateTransaction is called with a provided input set of coins,
1921+ // if the nValueIn of those coins is sufficient to cover the minimum nTransactionFee that starts
1922+ // the while loop, it will pass the first iteration. If the size of the transaction causes the nFeeRet
1923+ // to elevate and a second pass shows that the nValueOut + required fee is greater than that available
1924+ // i.e. negative change, then the loop is exited with an error. The reasoning for this is that
1925+ // in the case of no provided coin set, SelectTransaction above will be given the change to modify its
1926+ // selection to cover the increased fees, hopefully converging on an appropriate solution. In the case
1927+ // of a provided set of inputs, that set is immutable for this transaction, so no point in continuing.
1928+ if (provided_coin_set && nChange < 0 )
18791929 {
1880- int64_t nCredit = pcoin.first ->vout [pcoin.second ].nValue ;
1881- dPriority += (double )nCredit * pcoin.first ->GetDepthInMainChain ();
1930+ return error (" %s: Total value of inputs, %s, cannot cover the transaction fees of %s. "
1931+ " CreateTransaction aborted." ,
1932+ __func__,
1933+ FormatMoney (nValueIn),
1934+ FormatMoney (nFeeRet));
18821935 }
18831936
1884- int64_t nChange = nValueIn - nValueOut - nFeeRet;
1885-
1886- LogPrint (BCLog::LogFlags::ESTIMATEFEE, " INFO %s: Before CENT test: nChange = %s, nFeeRet = %s." ,
1937+ LogPrint (BCLog::LogFlags::ESTIMATEFEE, " INFO %s: Before CENT test: nValueIn = %s, nValueOut = %s, "
1938+ " nChange = %s, nFeeRet = %s." ,
18871939 __func__,
1940+ FormatMoney (nValueIn),
1941+ FormatMoney (nValueOut),
18881942 FormatMoney (nChange),
18891943 FormatMoney (nFeeRet));
18901944
@@ -1937,26 +1991,50 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
19371991 wtxNew.vout .insert (position, CTxOut (nChange, scriptChange));
19381992 }
19391993 else
1994+ {
19401995 reservekey.ReturnKey ();
1996+ }
19411997
1942- // Fill vin
1943- for (auto const & coin : setCoins)
1944- wtxNew.vin .push_back (CTxIn (coin.first ->GetHash (),coin.second ));
1998+ if (setCoins_in.size ())
1999+ {
2000+ // Fill vin from provided inputs
2001+ for (auto const & coin : setCoins_in)
2002+ {
2003+ wtxNew.vin .push_back (CTxIn (coin.first ->GetHash (),coin.second ));
2004+ }
19452005
1946- // Sign
1947- int nIn = 0 ;
1948- for (auto const & coin : setCoins)
1949- if (!SignSignature (*this , *coin.first , wtxNew, nIn++)) {
1950- return error (" %s: Failed to sign tx" , __func__);
2006+ // Sign
2007+ int nIn = 0 ;
2008+ for (auto const & coin : setCoins_in)
2009+ if (!SignSignature (*this , *coin.first , wtxNew, nIn++)) {
2010+ return error (" %s: Failed to sign tx" , __func__);
2011+ }
2012+ }
2013+ else // use setCoins_out from SelectCoins as the inputs
2014+ {
2015+ // Fill vin from provided inputs
2016+ for (auto const & coin : setCoins_out)
2017+ {
2018+ wtxNew.vin .push_back (CTxIn (coin.first ->GetHash (),coin.second ));
19512019 }
19522020
2021+ // Sign
2022+ int nIn = 0 ;
2023+ for (auto const & coin : setCoins_out)
2024+ if (!SignSignature (*this , *coin.first , wtxNew, nIn++))
2025+ {
2026+ return error (" %s: Failed to sign tx" , __func__);
2027+ }
2028+ }
2029+
19532030 // Limit size
19542031 unsigned int nBytes = ::GetSerializeSize (*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION);
19552032 if (nBytes >= MAX_STANDARD_TX_SIZE) {
19562033 return error (" %s: tx size %d greater than standard %d" , __func__, nBytes, MAX_STANDARD_TX_SIZE);
19572034 }
19582035
1959- dPriority /= nBytes;
2036+ // dPriority is not currently used.
2037+ // dPriority /= nBytes;
19602038
19612039 // Check that enough fee is included
19622040 int64_t nPayFee = nTransactionFee * (1 + (int64_t )nBytes / 1000 );
0 commit comments