Claim name returned is strange #172

Closed
mirgee wants to merge 286 commits from issue-119 into master
11 changed files with 268 additions and 74 deletions
Showing only changes of commit b2b0bd5bb5 - Show all commits

View file

@ -55,7 +55,7 @@ static void convertSeed6(std::vector<CAddress> &vSeedsOut, const SeedSpec6 *data
static Checkpoints::MapCheckpoints mapCheckpoints = static Checkpoints::MapCheckpoints mapCheckpoints =
boost::assign::map_list_of boost::assign::map_list_of
( 0, uint256S("0x008c55867210a8154af697b7776c6b6cdb26972381eac9f84d18a491374464a3")); ( 0, uint256S("0x00ef6ded2b610fc5e4f06d187d12136bd5fba7b932fa0b66bf353c7c1648ec9c"));
/*static Checkpoints::MapCheckpoints mapCheckpoints = /*static Checkpoints::MapCheckpoints mapCheckpoints =
boost::assign::map_list_of boost::assign::map_list_of
( 11111, uint256("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d")) ( 11111, uint256("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d"))
@ -148,10 +148,11 @@ public:
genesis.vtx.push_back(txNew); genesis.vtx.push_back(txNew);
genesis.hashPrevBlock.SetNull(); genesis.hashPrevBlock.SetNull();
genesis.hashMerkleRoot = genesis.BuildMerkleTree(); genesis.hashMerkleRoot = genesis.BuildMerkleTree();
genesis.hashNCCTrie = uint256S("0x0000000000000000000000000000000000000000000000000000000000000001");
genesis.nVersion = 1; genesis.nVersion = 1;
genesis.nTime = 1417453734; genesis.nTime = 1417453734;
genesis.nBits = 0x207fffff;//0x1d00ffff; genesis.nBits = 0x207fffff;//0x1d00ffff;
genesis.nNonce = 110; genesis.nNonce = 601;
/*bool found = false; /*bool found = false;
while (!found) while (!found)
@ -170,7 +171,7 @@ public:
hashGenesisBlock = genesis.GetHash(); hashGenesisBlock = genesis.GetHash();
//printf("%s\n", hashGenesisBlock.GetHex().c_str()); //printf("%s\n", hashGenesisBlock.GetHex().c_str());
//assert(hashGenesisBlock == uint256("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f")); //assert(hashGenesisBlock == uint256("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"));
assert(hashGenesisBlock == uint256S("0x008c55867210a8154af697b7776c6b6cdb26972381eac9f84d18a491374464a3")); assert(hashGenesisBlock == uint256S("0x00ef6ded2b610fc5e4f06d187d12136bd5fba7b932fa0b66bf353c7c1648ec9c"));
//printf("%s\n", genesis.hashMerkleRoot.GetHex().c_str()); //printf("%s\n", genesis.hashMerkleRoot.GetHex().c_str());
//assert(genesis.hashMerkleRoot == uint256("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); //assert(genesis.hashMerkleRoot == uint256("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
assert(genesis.hashMerkleRoot == uint256S("0xa7d51d407092059a2beeffab22e65d6176cfb3c33b93515109480aa7c81c9141")); assert(genesis.hashMerkleRoot == uint256S("0xa7d51d407092059a2beeffab22e65d6176cfb3c33b93515109480aa7c81c9141"));

View file

@ -181,6 +181,8 @@ void Shutdown()
pcoinsdbview = NULL; pcoinsdbview = NULL;
delete pblocktree; delete pblocktree;
pblocktree = NULL; pblocktree = NULL;
delete pnccTrie;
pnccTrie = NULL;
} }
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
if (pwalletMain) if (pwalletMain)
@ -1016,11 +1018,13 @@ bool AppInit2(boost::thread_group& threadGroup)
delete pcoinsdbview; delete pcoinsdbview;
delete pcoinscatcher; delete pcoinscatcher;
delete pblocktree; delete pblocktree;
delete pnccTrie;
pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReindex); pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReindex);
pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReindex); pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReindex);
pcoinscatcher = new CCoinsViewErrorCatcher(pcoinsdbview); pcoinscatcher = new CCoinsViewErrorCatcher(pcoinsdbview);
pcoinsTip = new CCoinsViewCache(pcoinscatcher); pcoinsTip = new CCoinsViewCache(pcoinscatcher);
pnccTrie = new CNCCTrie();
if (fReindex) if (fReindex)
pblocktree->WriteReindexing(true); pblocktree->WriteReindexing(true);
@ -1053,6 +1057,11 @@ bool AppInit2(boost::thread_group& threadGroup)
strLoadError = _("Corrupted block database detected"); strLoadError = _("Corrupted block database detected");
break; break;
} }
if (!pnccTrie->ReadFromDisk(true))
{
strLoadError = _("Error loading the ncc trie from disk");
break;
}
} catch (const std::exception& e) { } catch (const std::exception& e) {
if (fDebug) LogPrintf("%s\n", e.what()); if (fDebug) LogPrintf("%s\n", e.what());
strLoadError = _("Error opening block database"); strLoadError = _("Error opening block database");

View file

@ -13,6 +13,7 @@
#include "checkqueue.h" #include "checkqueue.h"
#include "init.h" #include "init.h"
#include "merkleblock.h" #include "merkleblock.h"
#include "ncc.h"
#include "net.h" #include "net.h"
#include "pow.h" #include "pow.h"
#include "txdb.h" #include "txdb.h"
@ -538,6 +539,7 @@ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& loc
} }
CCoinsViewCache *pcoinsTip = NULL; CCoinsViewCache *pcoinsTip = NULL;
CNCCTrie *pnccTrie = NULL;
CBlockTreeDB *pblocktree = NULL; CBlockTreeDB *pblocktree = NULL;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -1590,7 +1592,7 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uin
} // anon namespace } // anon namespace
bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool* pfClean) bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, CNCCTrieCache& trieCache, bool* pfClean)
{ {
assert(pindex->GetBlockHash() == view.GetBestBlock()); assert(pindex->GetBlockHash() == view.GetBestBlock());
@ -1632,6 +1634,22 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
if (*outs != outsBlock) if (*outs != outsBlock)
fClean = fClean && error("DisconnectBlock() : added transaction mismatch? database corrupted"); fClean = fClean && error("DisconnectBlock() : added transaction mismatch? database corrupted");
// remove any NCC claims
for (unsigned int i = 0; i < tx.vout.size(); ++i)
{
const CTxOut& txout = tx.vout[i];
int op;
std::vector<std::vector<unsigned char> > vvchParams;
if (DecodeNCCScript(txout.scriptPubKey, op, vvchParams))
{
assert(vvchParams.size() == 2);
std::string name(vvchParams[0].begin(), vvchParams[0].end());
if (!trieCache.removeName(name, hash, i))
LogPrintf("Something went wrong removing the name");
}
}
// remove outputs // remove outputs
outs->Clear(); outs->Clear();
} }
@ -1661,6 +1679,18 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
fClean = fClean && error("DisconnectBlock() : undo data overwriting existing output"); fClean = fClean && error("DisconnectBlock() : undo data overwriting existing output");
if (coins->vout.size() < out.n+1) if (coins->vout.size() < out.n+1)
coins->vout.resize(out.n+1); coins->vout.resize(out.n+1);
// restore NCC claim if applicable
int op;
std::vector<std::vector<unsigned char> > vvchParams;
if (DecodeNCCScript(undo.txout.scriptPubKey, op, vvchParams))
{
assert(vvchParams.size() == 2);
std::string name(vvchParams[0].begin(), vvchParams[0].end());
if (!trieCache.insertName(name, out.hash, out.n, undo.txout.nValue, undo.nHeight))
LogPrintf("Something went wrong inserting the name");
}
coins->vout[out.n] = undo.txout; coins->vout[out.n] = undo.txout;
} }
} }
@ -1715,7 +1745,7 @@ static int64_t nTimeIndex = 0;
static int64_t nTimeCallbacks = 0; static int64_t nTimeCallbacks = 0;
static int64_t nTimeTotal = 0; static int64_t nTimeTotal = 0;
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck) bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, CNCCTrieCache& trieCache, bool fJustCheck)
{ {
AssertLockHeld(cs_main); AssertLockHeld(cs_main);
// Check it again in case a previous version let a bad block in // Check it again in case a previous version let a bad block in
@ -1811,6 +1841,37 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
if (!CheckInputs(tx, state, view, fScriptChecks, flags, false, nScriptCheckThreads ? &vChecks : NULL)) if (!CheckInputs(tx, state, view, fScriptChecks, flags, false, nScriptCheckThreads ? &vChecks : NULL))
return false; return false;
control.Add(vChecks); control.Add(vChecks);
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
const CCoins* coins = view.AccessCoins(txin.prevout.hash);
assert(coins);
int op;
std::vector<std::vector<unsigned char> > vvchParams;
if (DecodeNCCScript(coins->vout[txin.prevout.n].scriptPubKey, op, vvchParams))
{
assert(vvchParams.size() == 1);
std::string name(vvchParams[0].begin(), vvchParams[0].end());
if (!trieCache.removeName(name, txin.prevout.hash, txin.prevout.n))
LogPrintf("Something went wrong removing the name");
}
}
for (unsigned int i = 0; i < tx.vout.size(); ++i)
{
const CTxOut& txout = tx.vout[i];
int op;
std::vector<std::vector<unsigned char> > vvchParams;
if (DecodeNCCScript(txout.scriptPubKey, op, vvchParams))
{
assert(vvchParams.size() == 2);
std::string name(vvchParams[0].begin(), vvchParams[0].end());
if (!trieCache.insertName(name, tx.GetHash(), i, txout.nValue, pindex->nHeight))
LogPrintf("Something went wrong inserting the name");
}
}
} }
CTxUndo undoDummy; CTxUndo undoDummy;
@ -1819,12 +1880,22 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
} }
UpdateCoins(tx, state, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex->nHeight); UpdateCoins(tx, state, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex->nHeight);
// TODO: This seems like a good place to actually change the // The CUndo vector contains all of the
// TODO: tree of NCCs and make the CUndo vector for those changes. // necessary information for putting NCC claims
// removed by this block back into the trie.
// (As long as the coinbase can't remove any
// NCC claims from the trie.)
vPos.push_back(std::make_pair(tx.GetHash(), pos)); vPos.push_back(std::make_pair(tx.GetHash(), pos));
pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION);
} }
if (trieCache.getMerkleHash() != block.hashNCCTrie)
return state.DoS(100,
error("ConnectBlock() : the merkle root of the NCC trie does not match "
"(actual=%s vs block=%s)", trieCache.getMerkleHash().GetHex(),
block.hashNCCTrie.GetHex()), REJECT_INVALID, "bad-ncc-merkle-hash");
int64_t nTime1 = GetTimeMicros(); nTimeConnect += nTime1 - nTimeStart; int64_t nTime1 = GetTimeMicros(); nTimeConnect += nTime1 - nTimeStart;
LogPrint("bench", " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs]\n", (unsigned)block.vtx.size(), 0.001 * (nTime1 - nTimeStart), 0.001 * (nTime1 - nTimeStart) / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * (nTime1 - nTimeStart) / (nInputs-1), nTimeConnect * 0.000001); LogPrint("bench", " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs]\n", (unsigned)block.vtx.size(), 0.001 * (nTime1 - nTimeStart), 0.001 * (nTime1 - nTimeStart) / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * (nTime1 - nTimeStart) / (nInputs-1), nTimeConnect * 0.000001);
@ -1999,9 +2070,11 @@ bool static DisconnectTip(CValidationState &state) {
int64_t nStart = GetTimeMicros(); int64_t nStart = GetTimeMicros();
{ {
CCoinsViewCache view(pcoinsTip); CCoinsViewCache view(pcoinsTip);
if (!DisconnectBlock(block, state, pindexDelete, view)) CNCCTrieCache trieCache(pnccTrie);
if (!DisconnectBlock(block, state, pindexDelete, view, trieCache))
return error("DisconnectTip() : DisconnectBlock %s failed", pindexDelete->GetBlockHash().ToString()); return error("DisconnectTip() : DisconnectBlock %s failed", pindexDelete->GetBlockHash().ToString());
assert(view.Flush()); assert(view.Flush());
assert(trieCache.flush());
} }
LogPrint("bench", "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * 0.001); LogPrint("bench", "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * 0.001);
// Write the chain state to disk, if necessary. // Write the chain state to disk, if necessary.
@ -2054,8 +2127,9 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *
LogPrint("bench", " - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * 0.001, nTimeReadFromDisk * 0.000001); LogPrint("bench", " - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * 0.001, nTimeReadFromDisk * 0.000001);
{ {
CCoinsViewCache view(pcoinsTip); CCoinsViewCache view(pcoinsTip);
CNCCTrieCache trieCache(pnccTrie);
CInv inv(MSG_BLOCK, pindexNew->GetBlockHash()); CInv inv(MSG_BLOCK, pindexNew->GetBlockHash());
bool rv = ConnectBlock(*pblock, state, pindexNew, view); bool rv = ConnectBlock(*pblock, state, pindexNew, view, trieCache);
g_signals.BlockChecked(*pblock, state); g_signals.BlockChecked(*pblock, state);
if (!rv) { if (!rv) {
if (state.IsInvalid()) if (state.IsInvalid())
@ -2066,6 +2140,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *
nTime3 = GetTimeMicros(); nTimeConnectTotal += nTime3 - nTime2; nTime3 = GetTimeMicros(); nTimeConnectTotal += nTime3 - nTime2;
LogPrint("bench", " - Connect total: %.2fms [%.2fs]\n", (nTime3 - nTime2) * 0.001, nTimeConnectTotal * 0.000001); LogPrint("bench", " - Connect total: %.2fms [%.2fs]\n", (nTime3 - nTime2) * 0.001, nTimeConnectTotal * 0.000001);
assert(view.Flush()); assert(view.Flush());
assert(trieCache.flush());
} }
int64_t nTime4 = GetTimeMicros(); nTimeFlush += nTime4 - nTime3; int64_t nTime4 = GetTimeMicros(); nTimeFlush += nTime4 - nTime3;
LogPrint("bench", " - Flush: %.2fms [%.2fs]\n", (nTime4 - nTime3) * 0.001, nTimeFlush * 0.000001); LogPrint("bench", " - Flush: %.2fms [%.2fs]\n", (nTime4 - nTime3) * 0.001, nTimeFlush * 0.000001);
@ -2630,9 +2705,13 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
} }
} }
// TODO: This looks like a good place to check the "merkle" root of the // TODO: ~~This looks like a good place to check the "merkle" root of the
// TODO: NCC tree that will result from applying this block // TODO: NCC tree that will result from applying this block.~~
// TODO: Actually, it's not, because the merkle root needs access to
// TODO: all of the coins spent by the new transactions, to check if
// TODO: they're NCC transactions. So the better place is in
// TODO: ConnectBlock, where inputs are checked against the coins
// TODO: they are spending.
return true; return true;
} }
@ -2772,6 +2851,7 @@ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex
assert(pindexPrev == chainActive.Tip()); assert(pindexPrev == chainActive.Tip());
CCoinsViewCache viewNew(pcoinsTip); CCoinsViewCache viewNew(pcoinsTip);
CNCCTrieCache trieCache(pnccTrie);
CBlockIndex indexDummy(block); CBlockIndex indexDummy(block);
indexDummy.pprev = pindexPrev; indexDummy.pprev = pindexPrev;
indexDummy.nHeight = pindexPrev->nHeight + 1; indexDummy.nHeight = pindexPrev->nHeight + 1;
@ -2783,7 +2863,7 @@ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex
return false; return false;
if (!ContextualCheckBlock(block, state, pindexPrev)) if (!ContextualCheckBlock(block, state, pindexPrev))
return false; return false;
if (!ConnectBlock(block, state, &indexDummy, viewNew, true)) if (!ConnectBlock(block, state, &indexDummy, viewNew, trieCache, true))
return false; return false;
assert(state.IsValid()); assert(state.IsValid());
@ -3000,6 +3080,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth
nCheckLevel = std::max(0, std::min(4, nCheckLevel)); nCheckLevel = std::max(0, std::min(4, nCheckLevel));
LogPrintf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel); LogPrintf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
CCoinsViewCache coins(coinsview); CCoinsViewCache coins(coinsview);
CNCCTrieCache trieCache(pnccTrie);
CBlockIndex* pindexState = chainActive.Tip(); CBlockIndex* pindexState = chainActive.Tip();
CBlockIndex* pindexFailure = NULL; CBlockIndex* pindexFailure = NULL;
int nGoodTransactions = 0; int nGoodTransactions = 0;
@ -3029,7 +3110,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth
// check level 3: check for inconsistencies during memory-only disconnect of tip blocks // check level 3: check for inconsistencies during memory-only disconnect of tip blocks
if (nCheckLevel >= 3 && pindex == pindexState && (coins.GetCacheSize() + pcoinsTip->GetCacheSize()) <= nCoinCacheSize) { if (nCheckLevel >= 3 && pindex == pindexState && (coins.GetCacheSize() + pcoinsTip->GetCacheSize()) <= nCoinCacheSize) {
bool fClean = true; bool fClean = true;
if (!DisconnectBlock(block, state, pindex, coins, &fClean)) if (!DisconnectBlock(block, state, pindex, coins, trieCache, &fClean))
return error("VerifyDB() : *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); return error("VerifyDB() : *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
pindexState = pindex->pprev; pindexState = pindex->pprev;
if (!fClean) { if (!fClean) {
@ -3054,7 +3135,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth
CBlock block; CBlock block;
if (!ReadBlockFromDisk(block, pindex)) if (!ReadBlockFromDisk(block, pindex))
return error("VerifyDB() : *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); return error("VerifyDB() : *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
if (!ConnectBlock(block, state, pindex, coins)) if (!ConnectBlock(block, state, pindex, coins, trieCache))
return error("VerifyDB() : *** found unconnectable block at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); return error("VerifyDB() : *** found unconnectable block at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
} }
} }

View file

@ -16,6 +16,7 @@
#include "coins.h" #include "coins.h"
#include "primitives/block.h" #include "primitives/block.h"
#include "primitives/transaction.h" #include "primitives/transaction.h"
#include "ncctrie.h"
#include "net.h" #include "net.h"
#include "pow.h" #include "pow.h"
#include "script/script.h" #include "script/script.h"
@ -348,10 +349,10 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex);
* In case pfClean is provided, operation will try to be tolerant about errors, and *pfClean * In case pfClean is provided, operation will try to be tolerant about errors, and *pfClean
* will be true if no problems were found. Otherwise, the return value will be false in case * will be true if no problems were found. Otherwise, the return value will be false in case
* of problems. Note that in any case, coins may be modified. */ * of problems. Note that in any case, coins may be modified. */
bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool* pfClean = NULL); bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, CNCCTrieCache& trieCache, bool* pfClean = NULL);
/** Apply the effects of this block (with given index) on the UTXO set represented by coins */ /** Apply the effects of this block (with given index) on the UTXO set represented by coins */
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false); bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, CNCCTrieCache& trieCache, bool fJustCheck = false);
/** Context-independent validity checks */ /** Context-independent validity checks */
bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW = true); bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW = true);
@ -510,6 +511,9 @@ extern CChain chainActive;
/** Global variable that points to the active CCoinsView (protected by cs_main) */ /** Global variable that points to the active CCoinsView (protected by cs_main) */
extern CCoinsViewCache *pcoinsTip; extern CCoinsViewCache *pcoinsTip;
/** Global variable that points to the active CNCCTrie (protected by cs_main) */
extern CNCCTrie *pnccTrie;
/** Global variable that points to the active block tree (protected by cs_main) */ /** Global variable that points to the active block tree (protected by cs_main) */
extern CBlockTreeDB *pblocktree; extern CBlockTreeDB *pblocktree;

View file

@ -9,6 +9,8 @@
#include "primitives/transaction.h" #include "primitives/transaction.h"
#include "hash.h" #include "hash.h"
#include "main.h" #include "main.h"
#include "ncc.h"
#include "ncctrie.h"
#include "net.h" #include "net.h"
#include "pow.h" #include "pow.h"
#include "timedata.h" #include "timedata.h"
@ -135,6 +137,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
CBlockIndex* pindexPrev = chainActive.Tip(); CBlockIndex* pindexPrev = chainActive.Tip();
const int nHeight = pindexPrev->nHeight + 1; const int nHeight = pindexPrev->nHeight + 1;
CCoinsViewCache view(pcoinsTip); CCoinsViewCache view(pcoinsTip);
CNCCTrieCache trieCache(pnccTrie);
// Priority order to process transactions // Priority order to process transactions
list<COrphan> vOrphan; // list memory doesn't move list<COrphan> vOrphan; // list memory doesn't move
@ -280,6 +283,43 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
UpdateCoins(tx, state, view, nHeight); UpdateCoins(tx, state, view, nHeight);
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
const CCoins* coins = view.AccessCoins(txin.prevout.hash);
// This seems to happen during testing, and should never happen otherwise
if (!coins || txin.prevout.n >= coins->vout.size())
{
LogPrintf("!coins || txin.prevout.n >= coins->vout.size()");
continue;
}
std::vector<std::vector<unsigned char> > vvchParams;
int op;
if (DecodeNCCScript(coins->vout[txin.prevout.n].scriptPubKey, op, vvchParams))
{
assert(vvchParams.size() == 2);
std::string name(vvchParams[0].begin(), vvchParams[0].end());
if (!trieCache.removeName(name, txin.prevout.hash, txin.prevout.n))
LogPrintf("Something went wrong removing the name");
}
}
for (unsigned int i = 0; i < tx.vout.size(); ++i)
{
const CTxOut& txout = tx.vout[i];
std::vector<std::vector<unsigned char> > vvchParams;
int op;
if (DecodeNCCScript(txout.scriptPubKey, op, vvchParams))
{
assert(vvchParams.size() == 2);
std::string name(vvchParams[0].begin(), vvchParams[0].end());
if (!trieCache.insertName(name, tx.GetHash(), i, txout.nValue, nHeight))
LogPrintf("Something went wrong inserting the name");
}
}
// Added // Added
pblock->vtx.push_back(tx); pblock->vtx.push_back(tx);
pblocktemplate->vTxFees.push_back(nTxFees); pblocktemplate->vTxFees.push_back(nTxFees);
@ -329,6 +369,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock); pblock->nBits = GetNextWorkRequired(pindexPrev, pblock);
pblock->nNonce = 0; pblock->nNonce = 0;
pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]); pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
pblock->hashNCCTrie = trieCache.getMerkleHash();
CValidationState state; CValidationState state;
if (!TestBlockValidity(state, *pblock, pindexPrev, false, false)) if (!TestBlockValidity(state, *pblock, pindexPrev, false, false))

View file

@ -1,4 +1,7 @@
#include "ncctrie.h" #include "ncctrie.h"
#include "leveldbwrapper.h"
#include <boost/scoped_ptr.hpp>
std::string CNodeValue::ToString() std::string CNodeValue::ToString()
{ {
@ -79,6 +82,8 @@ bool CNCCTrie::empty() const
bool CNCCTrie::checkConsistency() bool CNCCTrie::checkConsistency()
{ {
if (empty())
return true;
return recursiveCheckConsistency(&root); return recursiveCheckConsistency(&root);
} }
@ -114,11 +119,6 @@ bool CNCCTrie::recursiveCheckConsistency(CNCCTrieNode* node)
return calculatedHash == node->hash; return calculatedHash == node->hash;
} }
/*bool cachesort (std::pair<std::string, CNCCTrieNode*>& i, std::pair<std::string, CNCCTrieNode*>& j)
{
return i.first.size() < j.first.size();
}*/
bool CNCCTrie::update(nodeCacheType& cache, hashMapType& hashes) bool CNCCTrie::update(nodeCacheType& cache, hashMapType& hashes)
{ {
// General strategy: the cache is ordered by length, ensuring child // General strategy: the cache is ordered by length, ensuring child
@ -144,7 +144,6 @@ bool CNCCTrie::update(nodeCacheType& cache, hashMapType& hashes)
{ {
return true; return true;
} }
//std::sort(cache.begin(), cache.end(), cachesort);
bool success = true; bool success = true;
std::vector<std::string> deletedNames; std::vector<std::string> deletedNames;
for (nodeCacheType::iterator itcache = cache.begin(); itcache != cache.end(); ++itcache) for (nodeCacheType::iterator itcache = cache.begin(); itcache != cache.end(); ++itcache)
@ -263,6 +262,54 @@ bool CNCCTrie::BatchWrite(nodeCacheType& changedNodes, std::vector<std::string>&
return db.WriteBatch(batch); return db.WriteBatch(batch);
} }
bool CNCCTrie::InsertFromDisk(const std::string& name, CNCCTrieNode* node)
{
if (name.size() == 0)
root = *node;
return true;
CNCCTrieNode* current = &root;
for (std::string::const_iterator itname = name.begin(); itname + 1 != name.end(); ++itname)
{
nodeMapType::iterator itchild = current->children.find(*itname);
if (itchild == current->children.end())
return false;
current = itchild->second;
}
current->children[name[name.size()-1]] = node;
return true;
}
bool CNCCTrie::ReadFromDisk(bool check)
{
boost::scoped_ptr<leveldb::Iterator> pcursor(const_cast<CLevelDBWrapper*>(&db)->NewIterator());
pcursor->SeekToFirst();
while (pcursor->Valid())
{
//TODO: make try statement here
{
leveldb::Slice slKey = pcursor->key();
CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
char chType;
ssKey >> chType;
if (chType == 'n')
{
leveldb::Slice slValue = pcursor->value();
std::string name;
ssKey >> name;
CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
CNCCTrieNode* node = new CNCCTrieNode();
ssValue >> *node;
if (!InsertFromDisk(name, node))
return false;
}
}
}
if (check)
return checkConsistency();
return true;
}
bool CNCCTrieCache::recursiveComputeMerkleHash(CNCCTrieNode* tnCurrent, std::string sPos) const bool CNCCTrieCache::recursiveComputeMerkleHash(CNCCTrieNode* tnCurrent, std::string sPos) const
{ {
std::string stringToHash; std::string stringToHash;
@ -334,11 +381,12 @@ uint256 CNCCTrieCache::getMerkleHash() const
bool CNCCTrieCache::empty() const bool CNCCTrieCache::empty() const
{ {
return base->empty() && cache.empty(); return !base || (base->empty() && cache.empty());
} }
bool CNCCTrieCache::insertName(const std::string name, uint256 txhash, int nOut, CAmount nAmount, int nHeight) const bool CNCCTrieCache::insertName(const std::string name, uint256 txhash, int nOut, CAmount nAmount, int nHeight) const
{ {
assert(base);
CNCCTrieNode* currentNode = &(base->root); CNCCTrieNode* currentNode = &(base->root);
nodeCacheType::iterator cachedNode; nodeCacheType::iterator cachedNode;
cachedNode = cache.find(""); cachedNode = cache.find("");
@ -416,8 +464,9 @@ bool CNCCTrieCache::insertName(const std::string name, uint256 txhash, int nOut,
return true; return true;
} }
bool CNCCTrieCache::removeName(const std::string name, uint256 txhash, int nOut, CAmount nAmount, int nHeight) const bool CNCCTrieCache::removeName(const std::string name, uint256 txhash, int nOut) const
{ {
assert(base);
CNCCTrieNode* currentNode = &(base->root); CNCCTrieNode* currentNode = &(base->root);
nodeCacheType::iterator cachedNode; nodeCacheType::iterator cachedNode;
cachedNode = cache.find(""); cachedNode = cache.find("");
@ -456,7 +505,7 @@ bool CNCCTrieCache::removeName(const std::string name, uint256 txhash, int nOut,
} }
bool fChanged = false; bool fChanged = false;
assert(currentNode != NULL); assert(currentNode != NULL);
bool success = currentNode->removeValue(CNodeValue(txhash, nOut, nAmount, nHeight), &fChanged); bool success = currentNode->removeValue(CNodeValue(txhash, nOut), &fChanged);
assert(success); assert(success);
if (fChanged) if (fChanged)
{ {
@ -562,6 +611,8 @@ bool CNCCTrieCache::flush()
{ {
if (dirty()) if (dirty())
getMerkleHash(); getMerkleHash();
if (!base)
return true;
bool success = base->update(cache, cacheHashes); bool success = base->update(cache, cacheHashes);
if (success) if (success)
{ {

View file

@ -1,5 +1,5 @@
#ifndef BITCOIN_NCCTRIE_H #ifndef BITCOIN_NCCTRIE_H
#define BITCOIN_NCC_H #define BITCOIN_NCCTRIE_H
#include "amount.h" #include "amount.h"
#include "serialize.h" #include "serialize.h"
@ -23,6 +23,7 @@ public:
CAmount nAmount; CAmount nAmount;
int nHeight; int nHeight;
CNodeValue() {}; CNodeValue() {};
CNodeValue(uint256 txhash, uint32_t nOut) : txhash(txhash), nOut(nOut), nAmount(0), nHeight(0) {}
CNodeValue(uint256 txhash, uint32_t nOut, CAmount nAmount, int nHeight) : txhash(txhash), nOut(nOut), nAmount(nAmount), nHeight(nHeight) {} CNodeValue(uint256 txhash, uint32_t nOut, CAmount nAmount, int nHeight) : txhash(txhash), nOut(nOut), nAmount(nAmount), nHeight(nHeight) {}
std::string ToString(); std::string ToString();
@ -57,7 +58,7 @@ public:
} }
bool operator==(const CNodeValue& other) const bool operator==(const CNodeValue& other) const
{ {
return txhash == other.txhash && nOut == other.nOut && nAmount == other.nAmount && nHeight == other.nHeight; return txhash == other.txhash && nOut == other.nOut;
} }
bool operator!=(const CNodeValue& other) const bool operator!=(const CNodeValue& other) const
{ {
@ -122,20 +123,21 @@ class CNCCTrieCache;
class CNCCTrie class CNCCTrie
{ {
public: public:
CNCCTrie(CCoinsViewCache* coins) : db(GetDataDir() / "ncctrie", 100, false, false), coins(coins), root(uint256S("0000000000000000000000000000000000000000000000000000000000000001")) {} CNCCTrie() : db(GetDataDir() / "ncctrie", 100, false, false), root(uint256S("0000000000000000000000000000000000000000000000000000000000000001")) {}
uint256 getMerkleHash(); uint256 getMerkleHash();
CLevelDBWrapper db; CLevelDBWrapper db;
bool empty() const; bool empty() const;
bool checkConsistency(); bool checkConsistency();
bool ReadFromDisk(bool check = false);
friend class CNCCTrieCache; friend class CNCCTrieCache;
private: private:
CCoinsViewCache* coins;
bool update(nodeCacheType& cache, hashMapType& hashes); bool update(nodeCacheType& cache, hashMapType& hashes);
bool updateName(const std::string& name, CNCCTrieNode* updatedNode, std::vector<std::string>& deletedNames); bool updateName(const std::string& name, CNCCTrieNode* updatedNode, std::vector<std::string>& deletedNames);
bool updateHash(const std::string& name, uint256& hash, CNCCTrieNode** pNodeRet); bool updateHash(const std::string& name, uint256& hash, CNCCTrieNode** pNodeRet);
bool recursiveNullify(CNCCTrieNode* node, std::string& name, std::vector<std::string>& deletedNames); bool recursiveNullify(CNCCTrieNode* node, std::string& name, std::vector<std::string>& deletedNames);
bool recursiveCheckConsistency(CNCCTrieNode* node); bool recursiveCheckConsistency(CNCCTrieNode* node);
bool BatchWrite(nodeCacheType& changedNodes, std::vector<std::string>& deletedNames); bool BatchWrite(nodeCacheType& changedNodes, std::vector<std::string>& deletedNames);
bool InsertFromDisk(const std::string& name, CNCCTrieNode* node);
CNCCTrieNode root; CNCCTrieNode root;
}; };
@ -148,7 +150,7 @@ public:
bool flush(); bool flush();
bool dirty() const { return !dirtyHashes.empty(); } bool dirty() const { return !dirtyHashes.empty(); }
bool insertName (const std::string name, uint256 txhash, int nOut, CAmount nAmount, int nDepth) const; bool insertName (const std::string name, uint256 txhash, int nOut, CAmount nAmount, int nDepth) const;
bool removeName (const std::string name, uint256 txhash, int nOut, CAmount nAmount, int nDepth) const; bool removeName (const std::string name, uint256 txhash, int nOut) const;
~CNCCTrieCache() { clear(); } ~CNCCTrieCache() { clear(); }
private: private:
CNCCTrie* base; CNCCTrie* base;

View file

@ -28,6 +28,7 @@ public:
int32_t nVersion; int32_t nVersion;
uint256 hashPrevBlock; uint256 hashPrevBlock;
uint256 hashMerkleRoot; uint256 hashMerkleRoot;
uint256 hashNCCTrie;
uint32_t nTime; uint32_t nTime;
uint32_t nBits; uint32_t nBits;
uint32_t nNonce; uint32_t nNonce;
@ -48,6 +49,7 @@ public:
READWRITE(nTime); READWRITE(nTime);
READWRITE(nBits); READWRITE(nBits);
READWRITE(nNonce); READWRITE(nNonce);
READWRITE(hashNCCTrie);
} }
void SetNull() void SetNull()
@ -55,6 +57,7 @@ public:
nVersion = CBlockHeader::CURRENT_VERSION; nVersion = CBlockHeader::CURRENT_VERSION;
hashPrevBlock.SetNull(); hashPrevBlock.SetNull();
hashMerkleRoot.SetNull(); hashMerkleRoot.SetNull();
hashNCCTrie.SetNull();
nTime = 0; nTime = 0;
nBits = 0; nBits = 0;
nNonce = 0; nNonce = 0;
@ -118,6 +121,7 @@ public:
block.nTime = nTime; block.nTime = nTime;
block.nBits = nBits; block.nBits = nBits;
block.nNonce = nNonce; block.nNonce = nNonce;
block.hashNCCTrie = hashNCCTrie;
return block; return block;
} }

View file

@ -180,6 +180,7 @@ BOOST_AUTO_TEST_CASE(bloom_match)
BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx), "Simple Bloom filter matched COutPoint for an output we didn't care about"); BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx), "Simple Bloom filter matched COutPoint for an output we didn't care about");
} }
/* TODO: put these tests back in when there are real blocks to use
BOOST_AUTO_TEST_CASE(merkle_block_1) BOOST_AUTO_TEST_CASE(merkle_block_1)
{ {
// Random real block (0000000000013b8ab2cd513b0261a14096412195a72a0c4827d229dcc7e0f7af) // Random real block (0000000000013b8ab2cd513b0261a14096412195a72a0c4827d229dcc7e0f7af)
@ -457,5 +458,6 @@ BOOST_AUTO_TEST_CASE(merkle_block_4_test_update_none)
BOOST_CHECK(!filter.contains(COutPoint(uint256S("0x147caa76786596590baa4e98f5d9f48b86c7765e489f7a6ff3360fe5c674360b"), 0))); BOOST_CHECK(!filter.contains(COutPoint(uint256S("0x147caa76786596590baa4e98f5d9f48b86c7765e489f7a6ff3360fe5c674360b"), 0)));
BOOST_CHECK(!filter.contains(COutPoint(uint256S("0x02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041"), 0))); BOOST_CHECK(!filter.contains(COutPoint(uint256S("0x02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041"), 0)));
} }
*/
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

View file

@ -52,34 +52,34 @@ struct {
unsigned char extranonce; unsigned char extranonce;
unsigned int nonce; unsigned int nonce;
} blockinfo[] = { } blockinfo[] = {
{4, 0x00000002}, {2, 0x00000002}, {1, 0x00000000}, {1, 0x00000001}, //0 {4, 0x00000000}, {2, 0x00000001}, {1, 0x00000002}, {1, 0x00000000}, //0
{2, 0x00000001}, {2, 0x00000002}, {1, 0x00000000}, {2, 0x0000000b}, //4 {2, 0x00000001}, {2, 0x00000001}, {1, 0x00000001}, {2, 0x00000000}, //4
{2, 0x00000000}, {1, 0x00000000}, {1, 0x00000000}, {2, 0x00000001}, //8 {2, 0x00000001}, {1, 0x00000000}, {1, 0x00000001}, {2, 0x00000001}, //8
{2, 0x00000000}, {1, 0x00000000}, {2, 0x00000000}, {2, 0x00000001}, //12 {2, 0x00000003}, {1, 0x00000001}, {2, 0x00000001}, {2, 0x00000001}, //12
{1, 0x00000000}, {2, 0x00000004}, {1, 0x00000000}, {1, 0x00000000}, //16 {1, 0x00000001}, {2, 0x00000000}, {1, 0x00000005}, {1, 0x00000001}, //16
{3, 0x00000002}, {2, 0x00000000}, {2, 0x00000000}, {1, 0x00000000}, //20 {3, 0x00000000}, {2, 0x00000000}, {2, 0x00000000}, {1, 0x00000004}, //20
{2, 0x00000000}, {1, 0x00000002}, {2, 0x00000000}, {2, 0x00000000}, //24 {2, 0x00000000}, {1, 0x00000000}, {2, 0x00000002}, {2, 0x00000003}, //24
{2, 0x00000000}, {2, 0x00000001}, {2, 0x00000000}, {2, 0x00000000}, //28 {2, 0x00000001}, {2, 0x00000001}, {2, 0x00000000}, {2, 0x00000000}, //28
{1, 0x00000000}, {2, 0x00000001}, {2, 0x00000000}, {1, 0x00000000}, //32 {1, 0x00000001}, {2, 0x00000000}, {2, 0x00000001}, {1, 0x00000000}, //32
{2, 0x00000001}, {1, 0x00000000}, {2, 0x00000001}, {1, 0x00000000}, //36 {2, 0x00000000}, {1, 0x00000001}, {2, 0x00000000}, {1, 0x00000000}, //36
{1, 0x00000001}, {3, 0x00000000}, {2, 0x00000000}, {5, 0x00000002}, //40 {1, 0x00000000}, {3, 0x00000000}, {2, 0x00000005}, {5, 0x00000000}, //40
{1, 0x00000001}, {5, 0x00000000}, {1, 0x00000005}, {1, 0x00000000}, //44 {1, 0x00000002}, {5, 0x00000001}, {1, 0x00000001}, {1, 0x00000001}, //44
{1, 0x00000000}, {2, 0x00000002}, {1, 0x00000002}, {1, 0x00000000}, //48 {1, 0x00000001}, {2, 0x00000002}, {1, 0x00000002}, {1, 0x00000001}, //48
{1, 0x00000000}, {1, 0x00000000}, {5, 0x00000001}, {5, 0x00000000}, //52 {1, 0x00000000}, {1, 0x00000000}, {5, 0x00000002}, {5, 0x00000000}, //52
{1, 0x00000000}, {1, 0x00000000}, {6, 0x00000000}, {2, 0x00000001}, //56 {1, 0x00000000}, {1, 0x00000000}, {6, 0x00000001}, {2, 0x00000000}, //56
{2, 0x00000000}, {1, 0x00000000}, {1, 0x00000001}, {1, 0x00000002}, //60 {2, 0x00000003}, {1, 0x00000000}, {1, 0x00000000}, {1, 0x00000000}, //60
{2, 0x00000001}, {2, 0x00000000}, {1, 0x00000003}, {1, 0x00000001}, //64 {2, 0x00000000}, {2, 0x00000001}, {1, 0x00000000}, {1, 0x00000001}, //64
{1, 0x00000000}, {5, 0x00000000}, {5, 0x00000002}, {1, 0x00000001}, //68 {1, 0x00000003}, {5, 0x00000000}, {5, 0x00000000}, {1, 0x00000002}, //68
{1, 0x00000001}, {2, 0x00000000}, {2, 0x00000001}, {1, 0x00000003}, //72 {1, 0x00000000}, {2, 0x00000001}, {2, 0x00000004}, {1, 0x00000000}, //72
{2, 0x00000002}, {1, 0x00000000}, {2, 0x00000000}, {2, 0x00000006}, //76 {2, 0x00000001}, {1, 0x00000002}, {2, 0x00000004}, {2, 0x00000000}, //76
{1, 0x00000000}, {1, 0x00000000}, {1, 0x00000001}, {5, 0x00000000}, //80 {1, 0x00000000}, {1, 0x00000002}, {1, 0x00000000}, {5, 0x00000002}, //80
{1, 0x00000001}, {1, 0x00000001}, {1, 0x00000000}, {1, 0x00000002}, //84 {1, 0x00000001}, {1, 0x00000003}, {1, 0x00000000}, {1, 0x00000002}, //84
{1, 0x00000000}, {1, 0x00000000}, {1, 0x00000002}, {2, 0x00000001}, //88 {1, 0x00000000}, {1, 0x00000000}, {1, 0x00000002}, {2, 0x00000000}, //88
{0, 0x00000003}, {1, 0x00000004}, {2, 0x00000000}, {2, 0x00000001}, //92 {0, 0x00000000}, {1, 0x00000000}, {2, 0x00000001}, {2, 0x00000001}, //92
{2, 0x00000000}, {1, 0x00000002}, {1, 0x00000000}, {1, 0x00000002}, //96 {2, 0x00000000}, {1, 0x00000000}, {1, 0x00000000}, {1, 0x00000000}, //96
{1, 0x00000000}, {1, 0x00000003}, {1, 0x00000000}, {5, 0x00000000}, //100 {1, 0x00000000}, {1, 0x00000000}, {1, 0x00000000}, {5, 0x00000000}, //100
{2, 0x00000000}, {1, 0x00000000}, {1, 0x00000001}, {1, 0x00000001}, //104 {2, 0x00000000}, {1, 0x00000002}, {1, 0x00000000}, {1, 0x00000001}, //104
{2, 0x00000000}, {2, 0x00000002}, //108 {2, 0x00000003}, {2, 0x00000000}, //108
}; };
// NOTE: These tests rely on CreateNewBlock doing its own self-validation! // NOTE: These tests rely on CreateNewBlock doing its own self-validation!
@ -122,6 +122,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
if (CheckProofOfWork(pblock->GetHash(), pblock->nBits)) if (CheckProofOfWork(pblock->GetHash(), pblock->nBits))
{ {
fFound = true; fFound = true;
if (i % 4 == 0)
std::cout << std::endl;
std::cout << "Block number: " << i << std::endl; std::cout << "Block number: " << i << std::endl;
std::cout << "Nonce: " << std::hex << pblock->nNonce << std::dec << std::endl; std::cout << "Nonce: " << std::hex << pblock->nNonce << std::dec << std::endl;
} }

View file

@ -51,10 +51,7 @@ BOOST_AUTO_TEST_CASE(ncctrie_create_insert_remov)
uint256 hash4; uint256 hash4;
hash4.SetHex("a79e8a5b28f7fa5e8836a4b48da9988bdf56ce749f81f413cb754f963a516200"); hash4.SetHex("a79e8a5b28f7fa5e8836a4b48da9988bdf56ce749f81f413cb754f963a516200");
CCoinsView coinsDummy; CNCCTrie trie;
CCoinsViewCache coins(&coinsDummy);
CNCCTrie trie(&coins);
BOOST_CHECK(trie.empty()); BOOST_CHECK(trie.empty());
@ -71,7 +68,7 @@ BOOST_AUTO_TEST_CASE(ncctrie_create_insert_remov)
ntState.insertName(std::string("tes"), tx4.GetHash(), 0, 50, 100); ntState.insertName(std::string("tes"), tx4.GetHash(), 0, 50, 100);
BOOST_CHECK(ntState.getMerkleHash() == hash2); BOOST_CHECK(ntState.getMerkleHash() == hash2);
ntState.insertName(std::string("testtesttesttest"), tx5.GetHash(), 0, 50, 100); ntState.insertName(std::string("testtesttesttest"), tx5.GetHash(), 0, 50, 100);
ntState.removeName(std::string("testtesttesttest"), tx5.GetHash(), 0, 50, 100); ntState.removeName(std::string("testtesttesttest"), tx5.GetHash(), 0);
BOOST_CHECK(ntState.getMerkleHash() == hash2); BOOST_CHECK(ntState.getMerkleHash() == hash2);
ntState.flush(); ntState.flush();
@ -80,7 +77,7 @@ BOOST_AUTO_TEST_CASE(ncctrie_create_insert_remov)
BOOST_CHECK(trie.checkConsistency()); BOOST_CHECK(trie.checkConsistency());
CNCCTrieCache ntState2(&trie); CNCCTrieCache ntState2(&trie);
ntState2.insertName(std::string("abab"), tx6.GetHash(), 0, 50, 100); ntState2.insertName(std::string("abab"), tx6.GetHash(), 0, 50, 100);
ntState2.removeName(std::string("test"), tx1.GetHash(), 0, 50, 100); ntState2.removeName(std::string("test"), tx1.GetHash(), 0);
BOOST_CHECK(ntState2.getMerkleHash() == hash3); BOOST_CHECK(ntState2.getMerkleHash() == hash3);
@ -99,7 +96,7 @@ BOOST_AUTO_TEST_CASE(ncctrie_create_insert_remov)
BOOST_CHECK(trie.checkConsistency()); BOOST_CHECK(trie.checkConsistency());
CNCCTrieCache ntState4(&trie); CNCCTrieCache ntState4(&trie);
ntState4.removeName(std::string("abab"), tx6.GetHash(), 0, 50, 100); ntState4.removeName(std::string("abab"), tx6.GetHash(), 0);
BOOST_CHECK(ntState4.getMerkleHash() == hash2); BOOST_CHECK(ntState4.getMerkleHash() == hash2);
ntState4.flush(); ntState4.flush();
BOOST_CHECK(!trie.empty()); BOOST_CHECK(!trie.empty());
@ -107,7 +104,7 @@ BOOST_AUTO_TEST_CASE(ncctrie_create_insert_remov)
BOOST_CHECK(trie.checkConsistency()); BOOST_CHECK(trie.checkConsistency());
CNCCTrieCache ntState5(&trie); CNCCTrieCache ntState5(&trie);
ntState5.removeName(std::string("test"), tx3.GetHash(), 0, 50, 101); ntState5.removeName(std::string("test"), tx3.GetHash(), 0);
BOOST_CHECK(ntState5.getMerkleHash() == hash2); BOOST_CHECK(ntState5.getMerkleHash() == hash2);
ntState5.flush(); ntState5.flush();