From 395c1f44bd480416a12c881c89721e72ab40ee32 Mon Sep 17 00:00:00 2001 From: Gavin Andresen Date: Wed, 2 Mar 2011 16:27:24 -0500 Subject: [PATCH] Fix minimum transaction fee calculation mismatch between CreateTransaction and CreateBlock --- main.cpp | 44 ++++++++++++++++++++++++++++---------------- main.h | 8 ++++++++ 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/main.cpp b/main.cpp index a47f3a97b4..c65cd72de7 100644 --- a/main.cpp +++ b/main.cpp @@ -287,7 +287,7 @@ void EraseOrphanTx(uint256 hash) ////////////////////////////////////////////////////////////////////////////// // -// CTransaction +// CTransaction and CTxIndex // bool CTransaction::ReadFromDisk(CTxDB& txdb, COutPoint prevout, CTxIndex& txindexRet) @@ -1034,6 +1034,22 @@ void ResendWalletTransactions() } } +int CTxIndex::GetDepthInMainChain() const +{ + // Read block header + CBlock block; + if (!block.ReadFromDisk(pos.nFile, pos.nBlockPos, false)) + return 0; + // Find the block in the index + map::iterator mi = mapBlockIndex.find(block.GetHash()); + if (mi == mapBlockIndex.end()) + return 0; + CBlockIndex* pindex = (*mi).second; + if (!pindex || !pindex->IsInMainChain()) + return 0; + return 1 + nBestHeight - pindex->nHeight; +} + @@ -3327,18 +3343,7 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) int64 nValueIn = txPrev.vout[txin.prevout.n].nValue; // Read block header - int nConf = 0; - CBlock block; - if (block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false)) - { - map::iterator it = mapBlockIndex.find(block.GetHash()); - if (it != mapBlockIndex.end()) - { - CBlockIndex* pindex = (*it).second; - if (pindex->IsInMainChain()) - nConf = 1 + nBestHeight - pindex->nHeight; - } - } + int nConf = txindex.GetDepthInMainChain(); dPriority += (double)nValueIn * nConf; @@ -3383,7 +3388,7 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) continue; // Transaction fee required depends on block size - bool fAllowFree = (nBlockSize + nTxSize < 4000 || dPriority > COIN * 144 / 250); + bool fAllowFree = (nBlockSize + nTxSize < 4000 || CTransaction::AllowFree(dPriority)); int64 nMinFee = tx.GetMinFee(nBlockSize, fAllowFree); // Connecting shouldn't fail due to dependency on other memory pool transactions @@ -3859,6 +3864,7 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CR return false; int64 nValueOut = nValue; int64 nTotalValue = nValue + nFeeRet; + double dPriority = 0; // Choose coins to use set setCoins; @@ -3866,7 +3872,11 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CR return false; int64 nValueIn = 0; foreach(CWalletTx* pcoin, setCoins) - nValueIn += pcoin->GetCredit(); + { + int64 nCredit = pcoin->GetCredit(); + nValueIn += nCredit; + dPriority += (double)nCredit * pcoin->GetDepthInMainChain(); + } // Fill a vout to the payee bool fChangeFirst = GetRand(2); @@ -3921,10 +3931,12 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CR unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK); if (nBytes >= MAX_BLOCK_SIZE_GEN/5) return false; + dPriority /= nBytes; // Check that enough fee is included int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000); - int64 nMinFee = wtxNew.GetMinFee(); + bool fAllowFree = CTransaction::AllowFree(dPriority); + int64 nMinFee = wtxNew.GetMinFee(1, fAllowFree); if (nFeeRet < max(nPayFee, nMinFee)) { nFeeRet = max(nPayFee, nMinFee); diff --git a/main.h b/main.h index a7ef336e00..668d7f98b3 100644 --- a/main.h +++ b/main.h @@ -574,6 +574,13 @@ public: return nValueOut; } + static bool AllowFree(double dPriority) + { + // Large (in bytes) low-priority (new, small-coin) transactions + // need a fee. + return dPriority > COIN * 144 / 250; + } + int64 GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=true) const { // Base fee is 1 cent per kilobyte @@ -998,6 +1005,7 @@ public: { return !(a == b); } + int GetDepthInMainChain() const; };