Browse Source

mempool/cinv now indexed by userhash (all tx must be indexed by userhash btw)

miguelfreitas
Miguel Freitas 12 years ago
parent
commit
4652b9f01b
  1. 91
      src/main.cpp
  2. 15
      src/main.h
  3. 10
      src/net.cpp
  4. 4
      src/net.h
  5. 3
      src/rpcblockchain.cpp
  6. 2
      src/rpcrawtransaction.cpp
  7. 2
      src/wallet.cpp

91
src/main.cpp

@ -492,21 +492,6 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
return true; return true;
} }
void CTxMemPool::pruneSpent(const uint256 &hashTx, CCoins &coins)
{
LOCK(cs);
/*
std::map<COutPoint, CInPoint>::iterator it = mapNextTx.lower_bound(COutPoint(hashTx, 0));
// iterate over all COutPoints in mapNextTx whose hash equals the provided hashTx
while (it != mapNextTx.end() && it->first.hash == hashTx) {
coins.Spend(it->first.n); // and remove those outputs from coins
it++;
}
*/
}
// [MF] check if tx duplicated (mapTx and ccoins) // [MF] check if tx duplicated (mapTx and ccoins)
bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fLimitFree, bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fLimitFree,
bool* pfMissingInputs) bool* pfMissingInputs)
@ -528,15 +513,16 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fLimitFr
reason.c_str()); reason.c_str());
// is it already in the memory pool? // is it already in the memory pool?
uint256 hash = tx.GetHash(); uint256 userhash = tx.GetUsernameHash();
{ {
LOCK(cs); LOCK(cs);
if (mapTx.count(hash)) if (mapTx.count(userhash))
return false; return false;
} }
{ {
// [MF] check txIndex here instead of coins // [MF] FIXME: check txIndex here instead of coins
CCoinsView dummy; CCoinsView dummy;
CCoinsViewCache view(dummy); CCoinsViewCache view(dummy);
@ -585,29 +571,25 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fLimitFr
// Store transaction in memory // Store transaction in memory
{ {
LOCK(cs); LOCK(cs);
addUnchecked(hash, tx); // adds to mapTx addUnchecked(userhash, tx); // adds to mapTx
} }
///// are we sure this is ok when loading transactions or restoring block txes ///// are we sure this is ok when loading transactions or restoring block txes
SyncWithWallets(hash, tx, NULL, true); SyncWithWallets(userhash, tx, NULL, true);
printf("CTxMemPool::accept() : accepted %s (poolsz %"PRIszu")\n", printf("CTxMemPool::accept() : accepted %s (poolsz %"PRIszu")\n",
hash.ToString().c_str(), userhash.ToString().c_str(),
mapTx.size()); mapTx.size());
return true; return true;
} }
bool CTxMemPool::addUnchecked(const uint256& hash, CTransaction &tx) bool CTxMemPool::addUnchecked(const uint256& userhash, CTransaction &tx)
{ {
// Add to memory pool without checking anything. Don't call this directly, // Add to memory pool without checking anything. Don't call this directly,
// call CTxMemPool::accept to properly check the transaction first. // call CTxMemPool::accept to properly check the transaction first.
{ {
mapTx[hash] = tx; mapTx[userhash] = tx;
/* [MF]
for (unsigned int i = 0; i < tx.vin.size(); i++)
mapNextTx[tx.vin[i].prevout] = CInPoint(&mapTx[hash], i);
*/
nTransactionsUpdated++; nTransactionsUpdated++;
} }
return true; return true;
@ -619,22 +601,9 @@ bool CTxMemPool::remove(const CTransaction &tx, bool fRecursive)
// Remove transaction from memory pool // Remove transaction from memory pool
{ {
LOCK(cs); LOCK(cs);
uint256 hash = tx.GetHash(); uint256 hash = tx.GetUsernameHash();
if (mapTx.count(hash)) if (mapTx.count(hash))
{ {
if (fRecursive) {
/*
for (unsigned int i = 0; i < tx.vout.size(); i++) {
std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find(COutPoint(hash, i));
if (it != mapNextTx.end())
remove(*it->second.ptx, true);
}
*/
}
/*
BOOST_FOREACH(const CTxIn& txin, tx.vin)
mapNextTx.erase(txin.prevout);
*/
mapTx.erase(hash); mapTx.erase(hash);
nTransactionsUpdated++; nTransactionsUpdated++;
} }
@ -642,28 +611,10 @@ bool CTxMemPool::remove(const CTransaction &tx, bool fRecursive)
return true; return true;
} }
bool CTxMemPool::removeConflicts(const CTransaction &tx)
{
// Remove transactions which depend on inputs of tx, recursively
LOCK(cs);
/* [MF]
BOOST_FOREACH(const CTxIn &txin, tx.vin) {
std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find(txin.prevout);
if (it != mapNextTx.end()) {
const CTransaction &txConflict = *it->second.ptx;
if (txConflict != tx)
remove(txConflict, true);
}
}
*/
return true;
}
void CTxMemPool::clear() void CTxMemPool::clear()
{ {
LOCK(cs); LOCK(cs);
mapTx.clear(); mapTx.clear();
mapNextTx.clear();
++nTransactionsUpdated; ++nTransactionsUpdated;
} }
@ -733,23 +684,23 @@ bool CWalletTx::AcceptWalletTransaction()
// Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock // Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock
bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow) bool GetTransaction(const uint256 &userhash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow)
{ {
CBlockIndex *pindexSlow = NULL; CBlockIndex *pindexSlow = NULL;
{ {
LOCK(cs_main); LOCK(cs_main);
{ {
LOCK(mempool.cs); LOCK(mempool.cs);
if (mempool.exists(hash)) if (mempool.exists(userhash))
{ {
txOut = mempool.lookup(hash); txOut = mempool.lookup(userhash);
return true; return true;
} }
} }
if (fTxIndex) { if (fTxIndex) {
CDiskTxPos postx; CDiskTxPos postx;
if (pblocktree->ReadTxIndex(hash, postx)) { if (pblocktree->ReadTxIndex(userhash, postx)) {
CAutoFile file(OpenBlockFile(postx, true), SER_DISK, CLIENT_VERSION); CAutoFile file(OpenBlockFile(postx, true), SER_DISK, CLIENT_VERSION);
CBlockHeader header; CBlockHeader header;
try { try {
@ -760,7 +711,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__); return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__);
} }
hashBlock = header.GetHash(); hashBlock = header.GetHash();
if (txOut.GetHash() != hash) if (txOut.GetUsernameHash() != userhash)
return error("%s() : txid mismatch", __PRETTY_FUNCTION__); return error("%s() : txid mismatch", __PRETTY_FUNCTION__);
return true; return true;
} }
@ -771,7 +722,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
{ {
CCoinsViewCache &view = *pcoinsTip; CCoinsViewCache &view = *pcoinsTip;
CCoins coins; CCoins coins;
if (view.GetCoins(hash, coins)) if (view.GetCoins(userhash, coins))
nHeight = coins.nHeight; nHeight = coins.nHeight;
} }
if (nHeight > 0) if (nHeight > 0)
@ -783,7 +734,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
CBlock block; CBlock block;
if (ReadBlockFromDisk(block, pindexSlow)) { if (ReadBlockFromDisk(block, pindexSlow)) {
BOOST_FOREACH(const CTransaction &tx, block.vtx) { BOOST_FOREACH(const CTransaction &tx, block.vtx) {
if (tx.GetHash() == hash) { if (tx.GetHash() == userhash) {
txOut = tx; txOut = tx;
hashBlock = pindexSlow->GetBlockHash(); hashBlock = pindexSlow->GetBlockHash();
return true; return true;
@ -1185,6 +1136,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
return error("DisconnectBlock() : block and undo data inconsistent"); return error("DisconnectBlock() : block and undo data inconsistent");
// undo transactions in reverse order // undo transactions in reverse order
// [MF] FIXME: remove from txIndex
for (int i = block.vtx.size() - 1; i >= 0; i--) { for (int i = block.vtx.size() - 1; i >= 0; i--) {
const CTransaction &tx = block.vtx[i]; const CTransaction &tx = block.vtx[i];
uint256 hash = tx.GetHash(); uint256 hash = tx.GetHash();
@ -1483,7 +1435,6 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
// Delete redundant memory transactions that are in the connected branch // Delete redundant memory transactions that are in the connected branch
BOOST_FOREACH(CTransaction& tx, vDelete) { BOOST_FOREACH(CTransaction& tx, vDelete) {
mempool.remove(tx); mempool.remove(tx);
mempool.removeConflicts(tx);
} }
// Update best block in wallet (so we can detect restored wallets) // Update best block in wallet (so we can detect restored wallets)
@ -1928,7 +1879,7 @@ CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter& filter)
if (filter.IsRelevantAndUpdate(block.vtx[i], hash)) if (filter.IsRelevantAndUpdate(block.vtx[i], hash))
{ {
vMatch.push_back(true); vMatch.push_back(true);
vMatchedTxn.push_back(make_pair(i, hash)); vMatchedTxn.push_back(make_pair(i, block.vtx[i].GetUsernameHash()));
} }
else else
vMatch.push_back(false); vMatch.push_back(false);
@ -2625,6 +2576,7 @@ void static ProcessGetData(CNode* pfrom)
// Thus, the protocol spec specified allows for us to provide duplicate txn here, // Thus, the protocol spec specified allows for us to provide duplicate txn here,
// however we MUST always provide at least what the remote peer needs // however we MUST always provide at least what the remote peer needs
typedef std::pair<unsigned int, uint256> PairType; typedef std::pair<unsigned int, uint256> PairType;
// [MF] check if vMatchedTxn is userhash
BOOST_FOREACH(PairType& pair, merkleBlock.vMatchedTxn) BOOST_FOREACH(PairType& pair, merkleBlock.vMatchedTxn)
if (!pfrom->setInventoryKnown.count(CInv(MSG_TX, pair.second))) if (!pfrom->setInventoryKnown.count(CInv(MSG_TX, pair.second)))
pfrom->PushMessage("tx", block.vtx[pair.first]); pfrom->PushMessage("tx", block.vtx[pair.first]);
@ -3038,7 +2990,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
CTransaction tx; CTransaction tx;
vRecv >> tx; vRecv >> tx;
CInv inv(MSG_TX, tx.GetHash()); CInv inv(MSG_TX, tx.GetUsernameHash());
pfrom->AddInventoryKnown(inv); pfrom->AddInventoryKnown(inv);
// Truncate messages to the size of the tx in them // Truncate messages to the size of the tx in them
@ -3460,7 +3412,6 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
if (!fTrickleWait) if (!fTrickleWait)
{ {
CWalletTx wtx; CWalletTx wtx;
// [MF] TODO: use userhash
if (GetTransaction(inv.hash, wtx)) if (GetTransaction(inv.hash, wtx))
if (wtx.fFromMe) if (wtx.fFromMe)
fTrickleWait = true; fTrickleWait = true;

15
src/main.h

@ -1006,16 +1006,13 @@ class CTxMemPool
{ {
public: public:
mutable CCriticalSection cs; mutable CCriticalSection cs;
std::map<uint256, CTransaction> mapTx; std::map<uint256, CTransaction> mapTx; // [MF] hash is now userhash
std::map<COutPoint, CInPoint> mapNextTx;
bool accept(CValidationState &state, CTransaction &tx, bool fLimitFree, bool* pfMissingInputs); bool accept(CValidationState &state, CTransaction &tx, bool fLimitFree, bool* pfMissingInputs);
bool addUnchecked(const uint256& hash, CTransaction &tx); bool addUnchecked(const uint256& userhash, CTransaction &tx);
bool remove(const CTransaction &tx, bool fRecursive = false); bool remove(const CTransaction &tx, bool fRecursive = false);
bool removeConflicts(const CTransaction &tx);
void clear(); void clear();
void queryHashes(std::vector<uint256>& vtxid); void queryHashes(std::vector<uint256>& vtxid);
void pruneSpent(const uint256& hash, CCoins &coins);
unsigned long size() unsigned long size()
{ {
@ -1023,14 +1020,14 @@ public:
return mapTx.size(); return mapTx.size();
} }
bool exists(uint256 hash) bool exists(uint256 userhash)
{ {
return (mapTx.count(hash) != 0); return (mapTx.count(userhash) != 0);
} }
CTransaction& lookup(uint256 hash) CTransaction& lookup(uint256 userhash)
{ {
return mapTx[hash]; return mapTx[userhash];
} }
}; };

10
src/net.cpp

@ -1792,17 +1792,17 @@ instance_of_cnetcleanup;
void RelayTransaction(const CTransaction& tx, const uint256& hash) void RelayTransaction(const CTransaction& tx, const uint256& userhash)
{ {
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(10000); ss.reserve(10000);
ss << tx; ss << tx;
RelayTransaction(tx, hash, ss); RelayTransaction(tx, userhash, ss);
} }
void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss) void RelayTransaction(const CTransaction& tx, const uint256& userhash, const CDataStream& ss)
{ {
CInv inv(MSG_TX, hash); CInv inv(MSG_TX, userhash);
{ {
LOCK(cs_mapRelay); LOCK(cs_mapRelay);
// Expire old relay messages // Expire old relay messages
@ -1824,7 +1824,7 @@ void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataSt
LOCK(pnode->cs_filter); LOCK(pnode->cs_filter);
if (pnode->pfilter) if (pnode->pfilter)
{ {
if (pnode->pfilter->IsRelevantAndUpdate(tx, hash)) if (pnode->pfilter->IsRelevantAndUpdate(tx, userhash))
pnode->PushInventory(inv); pnode->PushInventory(inv);
} else } else
pnode->PushInventory(inv); pnode->PushInventory(inv);

4
src/net.h

@ -644,7 +644,7 @@ public:
class CTransaction; class CTransaction;
void RelayTransaction(const CTransaction& tx, const uint256& hash); void RelayTransaction(const CTransaction& tx, const uint256& userhash);
void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss); void RelayTransaction(const CTransaction& tx, const uint256& userhash, const CDataStream& ss);
#endif #endif

3
src/rpcblockchain.cpp

@ -126,6 +126,7 @@ Value getrawmempool(const Array& params, bool fHelp)
"getrawmempool\n" "getrawmempool\n"
"Returns all transaction ids in memory pool."); "Returns all transaction ids in memory pool.");
// [MF] check: hashes are now userhash
vector<uint256> vtxid; vector<uint256> vtxid;
mempool.queryHashes(vtxid); mempool.queryHashes(vtxid);
@ -229,7 +230,7 @@ Value gettxout(const Array& params, bool fHelp)
CCoinsViewMemPool view(*pcoinsTip, mempool); CCoinsViewMemPool view(*pcoinsTip, mempool);
if (!view.GetCoins(hash, coins)) if (!view.GetCoins(hash, coins))
return Value::null; return Value::null;
mempool.pruneSpent(hash, coins); // TODO: this should be done by the CCoinsViewMemPool //mempool.pruneSpent(hash, coins); // TODO: this should be done by the CCoinsViewMemPool
} else { } else {
if (!pcoinsTip->GetCoins(hash, coins)) if (!pcoinsTip->GetCoins(hash, coins))
return Value::null; return Value::null;

2
src/rpcrawtransaction.cpp

@ -557,7 +557,7 @@ Value sendrawtransaction(const Array& params, bool fHelp)
catch (std::exception &e) { catch (std::exception &e) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
} }
uint256 hashTx = tx.GetHash(); uint256 hashTx = tx.GetUsernameHash();
bool fHave = false; bool fHave = false;
CCoinsViewCache &view = *pcoinsTip; CCoinsViewCache &view = *pcoinsTip;

2
src/wallet.cpp

@ -766,7 +766,7 @@ void CWalletTx::RelayWalletTransaction()
if (!IsSpamMessage()) if (!IsSpamMessage())
{ {
if (GetDepthInMainChain() == 0) { if (GetDepthInMainChain() == 0) {
uint256 hash = GetHash(); uint256 hash = GetUsernameHash();
printf("Relaying wtx %s\n", hash.ToString().c_str()); printf("Relaying wtx %s\n", hash.ToString().c_str());
RelayTransaction((CTransaction)*this, hash); RelayTransaction((CTransaction)*this, hash);
} }

Loading…
Cancel
Save