From 026df62b9b76c9a97ea7de3b2826414ef0dc26ba Mon Sep 17 00:00:00 2001 From: CryptoManiac Date: Sun, 17 Aug 2014 03:06:37 +0400 Subject: [PATCH] RPC: mergecoins fix * Move maturity verification to SelectCoinsSimple(); * Verify transaction sum correctly; * Replace an intermediate transaction signing with estimation of transaction size for performance purposes. --- src/wallet.cpp | 25 +++++++++++++++---------- 1 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/wallet.cpp b/src/wallet.cpp index 851bcbe..7045e3c 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1415,6 +1415,10 @@ bool CWallet::SelectCoinsSimple(int64 nTargetValue, unsigned int nSpendTime, int const CWalletTx *pcoin = output.tx; int i = output.i; + // Ignore immature coins + if (pcoin->GetBlocksToMaturity() > 0) + continue; + // Stop if we've chosen enough inputs if (nValueRet >= nTargetValue) break; @@ -1652,6 +1656,7 @@ bool CWallet::GetStakeWeight(const CKeyStore& keystore, uint64& nMinWeight, uint set > setCoins; int64 nValueIn = 0; + // Simple coins selection - no randomization if (!SelectCoinsSimple(nBalance - nReserveBalance, GetTime(), nCoinbaseMaturity * 10, setCoins, nValueIn)) return false; @@ -1726,7 +1731,6 @@ bool CWallet::MergeCoins(const int64& nAmount, const int64& nMaxValue, const int wtxNew.vout.push_back(CTxOut(0, scriptOutput)); double dWeight = 0; - BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins) { int64 nCredit = pcoin.first->vout[pcoin.second].nValue; @@ -1735,15 +1739,14 @@ bool CWallet::MergeCoins(const int64& nAmount, const int64& nMaxValue, const int if (nCredit >= nMaxValue) continue; - // Ignore immature coins - if (pcoin.first->GetBlocksToMaturity() > 0) - continue; - // Add current coin to inputs list and add its credit to transaction output wtxNew.vin.push_back(CTxIn(pcoin.first->GetHash(), pcoin.second)); wtxNew.vout[0].nValue += nCredit; vwtxPrev.push_back(pcoin.first); +/* + // Replaced with estimation for performance purposes + for (unsigned int i = 0; i < wtxNew.vin.size(); i++) { const CWalletTx *txin = vwtxPrev[i]; @@ -1751,25 +1754,27 @@ bool CWallet::MergeCoins(const int64& nAmount, const int64& nMaxValue, const int if (!SignSignature(*this, *txin, wtxNew, i)) return false; } +*/ - int64 nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION); + // Assuming that average scriptsig size is 110 bytes + int64 nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION) + wtxNew.vin.size() * 110; dWeight += (double)nCredit * pcoin.first->GetDepthInMainChain(); double dFinalPriority = dWeight /= nBytes; bool fAllowFree = CTransaction::AllowFree(dFinalPriority); - // Get actual transaction fee according to its size and priority + // Get actual transaction fee according to its estimated size and priority int64 nMinFee = wtxNew.GetMinFee(1, fAllowFree, GMF_SEND, nBytes); // Prepare transaction for commit if sum is enough ot its size is too big - if (nBytes >= MAX_BLOCK_SIZE_GEN/6 || (wtxNew.vout[0].nValue >= nOutputValue && wtxNew.vout.size() > 1)) + if (nBytes >= MAX_BLOCK_SIZE_GEN/6 || wtxNew.vout[0].nValue >= nOutputValue) { wtxNew.vout[0].nValue -= nMinFee; // Set actual fee for (unsigned int i = 0; i < wtxNew.vin.size(); i++) { const CWalletTx *txin = vwtxPrev[i]; - // Sign all scripts again + // Sign all scripts if (!SignSignature(*this, *txin, wtxNew, i)) return false; } @@ -1789,7 +1794,7 @@ bool CWallet::MergeCoins(const int64& nAmount, const int64& nMaxValue, const int // Create transactions if there are some unhandled coins left if (wtxNew.vout[0].nValue > 0) { - int64 nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION); + int64 nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION) + wtxNew.vin.size() * 110; double dFinalPriority = dWeight /= nBytes; bool fAllowFree = CTransaction::AllowFree(dFinalPriority); -- 1.7.1