diff options
author | s_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b> | 2010-11-08 22:06:07 +0000 |
---|---|---|
committer | s_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b> | 2010-11-08 22:06:07 +0000 |
commit | 461764cbbea5965ebbd248f221876743d7a9ccd4 (patch) | |
tree | e188896a34a17405f88a3968aa94d3aaf7046585 /main.cpp | |
parent | 3b8848fa4e9b2cd8187cf90a7cbeabd662490c2b (diff) |
-paytxfee is now per KB,
BitcoinMiner prioritise transactions by how old their dependencies are
git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@176 1a98c847-1fd6-4fd8-948a-caf3550aa51b
Diffstat (limited to 'main.cpp')
-rw-r--r-- | main.cpp | 119 |
1 files changed, 102 insertions, 17 deletions
@@ -277,6 +277,34 @@ void EraseOrphanTx(uint256 hash) // CTransaction // +bool CTransaction::ReadFromDisk(CTxDB& txdb, COutPoint prevout, CTxIndex& txindexRet) +{ + SetNull(); + if (!txdb.ReadTxIndex(prevout.hash, txindexRet)) + return false; + if (!ReadFromDisk(txindexRet.pos)) + return false; + if (prevout.n >= vout.size()) + { + SetNull(); + return false; + } + return true; +} + +bool CTransaction::ReadFromDisk(CTxDB& txdb, COutPoint prevout) +{ + CTxIndex txindex; + return ReadFromDisk(txdb, prevout, txindex); +} + +bool CTransaction::ReadFromDisk(COutPoint prevout) +{ + CTxDB txdb("r"); + CTxIndex txindex; + return ReadFromDisk(txdb, prevout, txindex); +} + bool CTxIn::IsMine() const { CRITICAL_BLOCK(cs_mapWallet) @@ -2882,7 +2910,7 @@ void CallCPUID(int in, int& aret, int& cret) "mov %2, %%eax; " // in into eax "cpuid;" "mov %%eax, %0;" // eax into a - "mov %%ecx, %1;" // eax into c + "mov %%ecx, %1;" // ecx into c :"=r"(a),"=r"(c) /* output */ :"r"(in) /* input */ :"%eax","%ecx" /* clobbered register */ @@ -3068,42 +3096,97 @@ void BitcoinMiner() CRITICAL_BLOCK(cs_mapTransactions) { CTxDB txdb("r"); + + // Priority order to process transactions + multimap<double, CTransaction*> mapPriority; + for (map<uint256, CTransaction>::iterator mi = mapTransactions.begin(); mi != mapTransactions.end(); ++mi) + { + CTransaction& tx = (*mi).second; + if (tx.IsCoinBase() || !tx.IsFinal()) + continue; + + double dPriority = 0; + foreach(const CTxIn& txin, tx.vin) + { + // Read prev transaction + CTransaction txPrev; + CTxIndex txindex; + if (!txPrev.ReadFromDisk(txdb, txin.prevout, txindex)) + continue; + 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<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(block.GetHash()); + if (it != mapBlockIndex.end()) + { + CBlockIndex* pindex = (*it).second; + if (pindex->IsInMainChain()) + nConf = 1 + nBestHeight - pindex->nHeight; + } + } + + dPriority += (double)nValueIn * nConf; + + if (fDebug && mapArgs.count("-printpriority")) + printf("priority nValueIn=%-12I64d nConf=%-5d dPriority=%-20.1f\n", nValueIn, nConf, dPriority); + } + + // Priority is sum(valuein * age) / txsize + dPriority /= ::GetSerializeSize(tx, SER_NETWORK); + + mapPriority.insert(make_pair(-dPriority, &(*mi).second)); + + if (fDebug && mapArgs.count("-printpriority")) + printf("priority %-20.1f %s\n%s\n", dPriority, tx.GetHash().ToString().substr(0,10).c_str(), tx.ToString().c_str()); + } + + // Collect transactions into block map<uint256, CTxIndex> mapTestPool; - vector<char> vfAlreadyAdded(mapTransactions.size()); uint64 nBlockSize = 1000; int nBlockSigOps = 100; bool fFoundSomething = true; while (fFoundSomething) { fFoundSomething = false; - unsigned int n = 0; - for (map<uint256, CTransaction>::iterator mi = mapTransactions.begin(); mi != mapTransactions.end(); ++mi, ++n) + for (multimap<double, CTransaction*>::iterator mi = mapPriority.begin(); mi != mapPriority.end();) { - if (vfAlreadyAdded[n]) - continue; - CTransaction& tx = (*mi).second; - if (tx.IsCoinBase() || !tx.IsFinal()) - continue; + CTransaction& tx = *(*mi).second; unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK); if (nBlockSize + nTxSize >= MAX_BLOCK_SIZE_GEN) + { + mapPriority.erase(mi++); continue; + } int nTxSigOps = tx.GetSigOpCount(); if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS) + { + mapPriority.erase(mi++); continue; + } // Transaction fee based on block size int64 nMinFee = tx.GetMinFee(nBlockSize); + // Connecting can fail due to dependency on other memory pool transactions + // that aren't in the block yet, so keep trying in later passes map<uint256, CTxIndex> mapTestPoolTmp(mapTestPool); if (!tx.ConnectInputs(txdb, mapTestPoolTmp, CDiskTxPos(1,1,1), pindexPrev, nFees, false, true, nMinFee)) + { + mi++; continue; + } swap(mapTestPool, mapTestPoolTmp); + // Added pblock->vtx.push_back(tx); nBlockSize += nTxSize; nBlockSigOps += nTxSigOps; - vfAlreadyAdded[n] = true; fFoundSomething = true; + mapPriority.erase(mi++); } } } @@ -3426,16 +3509,15 @@ bool SelectCoins(int64 nTargetValue, set<CWalletTx*>& setCoinsRet) -bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRequiredRet) +bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet) { - nFeeRequiredRet = 0; CRITICAL_BLOCK(cs_main) { // txdb must be opened before the mapWallet lock CTxDB txdb("r"); CRITICAL_BLOCK(cs_mapWallet) { - int64 nFee = nTransactionFee; + nFeeRet = nTransactionFee; loop { wtxNew.vin.clear(); @@ -3444,7 +3526,7 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CR if (nValue < 0) return false; int64 nValueOut = nValue; - int64 nTotalValue = nValue + nFee; + int64 nTotalValue = nValue + nFeeRet; // Choose coins to use set<CWalletTx*> setCoins; @@ -3504,13 +3586,16 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CR return false; // Limit size - if (::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK) >= MAX_BLOCK_SIZE_GEN/5) + unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK); + if (nBytes >= MAX_BLOCK_SIZE_GEN/5) return false; // Check that enough fee is included - if (nFee < wtxNew.GetMinFee()) + int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000); + int64 nMinFee = wtxNew.GetMinFee(); + if (nFeeRet < max(nPayFee, nMinFee)) { - nFee = nFeeRequiredRet = wtxNew.GetMinFee(); + nFeeRet = max(nPayFee, nMinFee); continue; } |