implement reading and writing the NCC trie to disk, create the global trie upon initialization, add and remove NCC claims when connecting and disconnecting blocks, and check block headers against the NCC merkle hash

This commit is contained in:
Jimmy Kiselak 2015-02-05 14:24:09 -05:00
parent 9bb4ecef2a
commit b2b0bd5bb5
11 changed files with 268 additions and 74 deletions

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,15 +464,16 @@ 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
{ {
CNCCTrieNode* currentNode = &(base->root); assert(base);
nodeCacheType::iterator cachedNode; CNCCTrieNode* currentNode = &(base->root);
cachedNode = cache.find(""); nodeCacheType::iterator cachedNode;
if (cachedNode != cache.end()) cachedNode = cache.find("");
currentNode = cachedNode->second; if (cachedNode != cache.end())
assert(currentNode != NULL); // If there is no root in either the trie or the cache, how can there be any names to remove? currentNode = cachedNode->second;
for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) assert(currentNode != NULL); // If there is no root in either the trie or the cache, how can there be any names to remove?
for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur)
{ {
std::string sCurrentSubstring(name.begin(), itCur); std::string sCurrentSubstring(name.begin(), itCur);
std::string sNextSubstring(name.begin(), itCur + 1); std::string sNextSubstring(name.begin(), itCur + 1);
@ -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();