Browse Source

use txIndex instead of coins to keep track of commited tx

miguelfreitas
Miguel Freitas 12 years ago
parent
commit
311b1d7eaa
  1. 124
      src/main.cpp
  2. 2
      src/rpcrawtransaction.cpp
  3. 9
      src/txdb.cpp
  4. 2
      src/txdb.h

124
src/main.cpp

@ -521,27 +521,10 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fLimitFr @@ -521,27 +521,10 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fLimitFr
}
{
// [MF] FIXME: check txIndex here instead of coins
CCoinsView dummy;
CCoinsViewCache view(dummy);
{
LOCK(cs);
CCoinsViewMemPool viewMemPool(*pcoinsTip, *this);
view.SetBackend(viewMemPool);
// do we already have it?
if (view.HaveCoins(tx.GetUsernameHash()))
if( pblocktree->HaveTxIndex(userhash) )
return false;
// Bring the best block into scope
view.GetBestBlock();
// we have all inputs cached now, so switch back to dummy, so we don't need to keep lock on mempool
view.SetBackend(dummy);
}
unsigned int nSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
// Continuously rate-limit free transactions
@ -716,31 +699,6 @@ bool GetTransaction(const uint256 &userhash, CTransaction &txOut, uint256 &hashB @@ -716,31 +699,6 @@ bool GetTransaction(const uint256 &userhash, CTransaction &txOut, uint256 &hashB
return true;
}
}
if (fAllowSlow) { // use coin database to locate block that contains transaction, and scan it
int nHeight = -1;
{
CCoinsViewCache &view = *pcoinsTip;
CCoins coins;
if (view.GetCoins(userhash, coins))
nHeight = coins.nHeight;
}
if (nHeight > 0)
pindexSlow = FindBlockByHeight(nHeight);
}
}
if (pindexSlow) {
CBlock block;
if (ReadBlockFromDisk(block, pindexSlow)) {
BOOST_FOREACH(const CTransaction &tx, block.vtx) {
if (tx.GetHash() == userhash) {
txOut = tx;
hashBlock = pindexSlow->GetBlockHash();
return true;
}
}
}
}
return false;
@ -1136,57 +1094,12 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex @@ -1136,57 +1094,12 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
return error("DisconnectBlock() : block and undo data inconsistent");
// undo transactions in reverse order
// [MF] FIXME: remove from txIndex
// [MF] just remove from txIndex, no more coins
for (int i = block.vtx.size() - 1; i >= 0; i--) {
const CTransaction &tx = block.vtx[i];
uint256 hash = tx.GetHash();
// check that all outputs are available
if (!view.HaveCoins(tx.GetUsernameHash())) {
fClean = fClean && error("DisconnectBlock() : outputs still spent? database corrupted");
view.SetCoins(tx.GetUsernameHash(), CCoins());
}
CCoins &outs = view.GetCoins(tx.GetUsernameHash());
CCoins outsBlock = CCoins(tx, pindex->nHeight);
if (outs != outsBlock)
fClean = fClean && error("DisconnectBlock() : added transaction mismatch? database corrupted");
// remove outputs
outs = CCoins();
// restore inputs
if (i > 0) { // not coinbases
const CTxUndo &txundo = blockUndo.vtxundo[i-1];
/*
if (txundo.vprevout.size() != tx.vin.size())
return error("DisconnectBlock() : transaction and undo data inconsistent");
for (unsigned int j = tx.vin.size(); j-- > 0;) {
const COutPoint &out = tx.vin[j].prevout;
const CTxInUndo &undo = txundo.vprevout[j];
CCoins coins;
view.GetCoins(out.hash, coins); // this can fail if the prevout was already entirely spent
if (undo.nHeight != 0) {
// undo data contains height: this is the last output of the prevout tx being spent
if (!coins.IsPruned())
fClean = fClean && error("DisconnectBlock() : undo data overwriting existing transaction");
coins = CCoins();
coins.fCoinBase = undo.fCoinBase;
coins.nHeight = undo.nHeight;
coins.nVersion = undo.nVersion;
} else {
if (coins.IsPruned())
fClean = fClean && error("DisconnectBlock() : undo data adding output to missing transaction");
}
if (coins.IsAvailable(out.n))
fClean = fClean && error("DisconnectBlock() : undo data overwriting existing output");
if (coins.vout.size() < out.n+1)
coins.vout.resize(out.n+1);
coins.vout[out.n] = undo.txout;
if (!view.SetCoins(out.hash, coins))
return error("DisconnectBlock() : cannot restore coin inputs");
}
*/
if( i > 0 && pblocktree->EraseTxIndex(tx.GetUsernameHash()) ) {
fClean = fClean && error("DisconnectBlock() : error erasing txIndex");
}
}
@ -1245,10 +1158,13 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C @@ -1245,10 +1158,13 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
// Do not allow blocks that contain transactions which 'overwrite' older transactions,
for (unsigned int i = 0; i < block.vtx.size(); i++) {
// [MF] FIXME: check here for indexTx
uint256 hash = block.GetTxHash(i);
if (view.HaveCoins(block.vtx[i].GetUsernameHash()))
return state.DoS(100, error("ConnectBlock() : tried to overwrite transaction"));
if( pblocktree->HaveTxIndex(block.vtx[i].GetUsernameHash()) )
return state.DoS(100, error("ConnectBlock() : tried to overwrite transaction"));
// [MF] FIXME: check here for indexTx (done above!)
//uint256 hash = block.GetTxHash(i);
//if (view.HaveCoins(block.vtx[i].GetUsernameHash()))
// return state.DoS(100, error("ConnectBlock() : tried to overwrite transaction"));
}
CBlockUndo blockundo;
@ -1262,12 +1178,10 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C @@ -1262,12 +1178,10 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
const CTransaction &tx = block.vtx[i];
CTxUndo txundo;
//UpdateCoins(tx, state, view, txundo, pindex->nHeight, block.GetTxHash(i));
UpdateCoins(tx, state, view, txundo, pindex->nHeight, tx.GetUsernameHash());
if (!tx.IsSpamMessage())
blockundo.vtxundo.push_back(txundo);
vPos.push_back(std::make_pair(block.GetTxHash(i), pos));
vPos.push_back(std::make_pair(tx.GetUsernameHash(), pos));
pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION);
}
int64 nTime = GetTimeMicros() - nStart;
@ -1876,7 +1790,8 @@ CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter& filter) @@ -1876,7 +1790,8 @@ CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter& filter)
for (unsigned int i = 0; i < block.vtx.size(); i++)
{
uint256 hash = block.vtx[i].GetHash();
if (filter.IsRelevantAndUpdate(block.vtx[i], hash))
// [MF] unsure. force 0, use userhash for filter, hash for merkletree
if (i == 0 || filter.IsRelevantAndUpdate(block.vtx[i], block.vtx[i].GetUsernameHash()))
{
vMatch.push_back(true);
vMatchedTxn.push_back(make_pair(i, block.vtx[i].GetUsernameHash()));
@ -2518,12 +2433,11 @@ bool static AlreadyHave(const CInv& inv) @@ -2518,12 +2433,11 @@ bool static AlreadyHave(const CInv& inv)
LOCK(mempool.cs);
txInMap = mempool.exists(inv.hash);
}
bool txInCoins = false;
bool txInTxIndex = false;
if( !txInMap ) {
// [MF] FIXME: como converter inv.hash no usernamehash?
txInCoins = pcoinsTip->HaveCoins(inv.hash);
txInTxIndex = pblocktree->HaveTxIndex(inv.hash);
}
return txInMap || txInCoins;
return txInMap || txInTxIndex;
}
case MSG_BLOCK:
return mapBlockIndex.count(inv.hash) ||
@ -3684,7 +3598,7 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey) @@ -3684,7 +3598,7 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
continue;
// This should never happen; all transactions in the memory are new
if( view.HaveCoins(tx.GetUsernameHash()) ) {
if( pblocktree->HaveTxIndex(tx.GetUsernameHash()) ) {
printf("ERROR: mempool transaction already exists\n");
if (fDebug) assert("mempool transaction already exists" == 0);
}

2
src/rpcrawtransaction.cpp

@ -76,7 +76,7 @@ void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out) @@ -76,7 +76,7 @@ void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out)
void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
{
entry.push_back(Pair("txid", tx.GetHash().GetHex()));
entry.push_back(Pair("txid", tx.GetUsernameHash().GetHex()));
entry.push_back(Pair("version", tx.nVersion));
//entry.push_back(Pair("locktime", (boost::int64_t)tx.nLockTime));
Array vin;

9
src/txdb.cpp

@ -159,6 +159,15 @@ bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) { @@ -159,6 +159,15 @@ bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) {
return Read(make_pair('t', txid), pos);
}
bool CBlockTreeDB::HaveTxIndex(const uint256 &txid) {
CDiskTxPos pos;
return ReadTxIndex(txid, pos);
}
bool CBlockTreeDB::EraseTxIndex(const uint256 &txid) {
return Erase(make_pair('t', txid));
}
bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >&vect) {
CLevelDBBatch batch;
for (std::vector<std::pair<uint256,CDiskTxPos> >::const_iterator it=vect.begin(); it!=vect.end(); it++)

2
src/txdb.h

@ -44,6 +44,8 @@ public: @@ -44,6 +44,8 @@ public:
bool WriteReindexing(bool fReindex);
bool ReadReindexing(bool &fReindex);
bool ReadTxIndex(const uint256 &txid, CDiskTxPos &pos);
bool HaveTxIndex(const uint256 &txid);
bool EraseTxIndex(const uint256 &txid);
bool WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> > &list);
bool WriteFlag(const std::string &name, bool fValue);
bool ReadFlag(const std::string &name, bool &fValue);

Loading…
Cancel
Save