Implement a hard fork for extended/infinite claim expiration times #112
5 changed files with 60 additions and 21 deletions
11
src/init.cpp
11
src/init.cpp
|
@ -1072,6 +1072,12 @@ bool AppInit2(boost::thread_group& threadGroup)
|
||||||
strLoadError = _("You need to rebuild the database using -reindex to change -txindex");
|
strLoadError = _("You need to rebuild the database using -reindex to change -txindex");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!pnccTrie->ReadFromDisk(true))
|
||||||
|
{
|
||||||
|
strLoadError = _("Error loading the ncc trie from disk");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
uiInterface.InitMessage(_("Verifying blocks..."));
|
uiInterface.InitMessage(_("Verifying blocks..."));
|
||||||
if (!CVerifyDB().VerifyDB(pcoinsdbview, GetArg("-checklevel", 3),
|
if (!CVerifyDB().VerifyDB(pcoinsdbview, GetArg("-checklevel", 3),
|
||||||
|
@ -1079,11 +1085,6 @@ 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");
|
||||||
|
|
14
src/main.cpp
14
src/main.cpp
|
@ -1628,8 +1628,9 @@ static bool ApplyTxInUndo(const CTxInUndo& undo, CCoinsViewCache& view, CNCCTrie
|
||||||
{
|
{
|
||||||
assert(vvchParams.size() == 2);
|
assert(vvchParams.size() == 2);
|
||||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||||
|
LogPrintf("%s: Restoring %s to the NCC trie due to a block being disconnected\n", __func__, name.c_str());
|
||||||
if (!trieCache.insertName(name, out.hash, out.n, undo.txout.nValue, undo.nHeight))
|
if (!trieCache.insertName(name, out.hash, out.n, undo.txout.nValue, undo.nHeight))
|
||||||
LogPrintf("Something went wrong inserting the name");
|
LogPrintf("%s: Something went wrong inserting the name\n", __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
coins->vout[out.n] = undo.txout;
|
coins->vout[out.n] = undo.txout;
|
||||||
|
@ -1687,8 +1688,9 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
|
||||||
{
|
{
|
||||||
assert(vvchParams.size() == 2);
|
assert(vvchParams.size() == 2);
|
||||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||||
|
LogPrintf("%s: Removing %s from the ncc trie due to its block being disconnected\n", __func__, name.c_str());
|
||||||
if (!trieCache.removeName(name, hash, i))
|
if (!trieCache.removeName(name, hash, i))
|
||||||
LogPrintf("Something went wrong removing the name");
|
LogPrintf("%s: Something went wrong removing the name %s in hash %s\n", __func__, name.c_str(), hash.GetHex());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1712,6 +1714,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
|
||||||
|
|
||||||
// move best block pointer to prevout block
|
// move best block pointer to prevout block
|
||||||
view.SetBestBlock(pindex->pprev->GetBlockHash());
|
view.SetBestBlock(pindex->pprev->GetBlockHash());
|
||||||
|
assert(trieCache.getMerkleHash() == pindex->pprev->hashNCCTrie);
|
||||||
|
|
||||||
if (pfClean) {
|
if (pfClean) {
|
||||||
*pfClean = fClean;
|
*pfClean = fClean;
|
||||||
|
@ -1870,10 +1873,10 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||||
std::vector<std::vector<unsigned char> > vvchParams;
|
std::vector<std::vector<unsigned char> > vvchParams;
|
||||||
if (DecodeNCCScript(coins->vout[txin.prevout.n].scriptPubKey, op, vvchParams))
|
if (DecodeNCCScript(coins->vout[txin.prevout.n].scriptPubKey, op, vvchParams))
|
||||||
{
|
{
|
||||||
assert(vvchParams.size() == 1);
|
assert(vvchParams.size() == 2);
|
||||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||||
if (!trieCache.removeName(name, txin.prevout.hash, txin.prevout.n))
|
if (!trieCache.removeName(name, txin.prevout.hash, txin.prevout.n))
|
||||||
LogPrintf("Something went wrong removing the name");
|
LogPrintf("%s: Something went wrong removing the name\n", __func__);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1888,7 +1891,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||||
assert(vvchParams.size() == 2);
|
assert(vvchParams.size() == 2);
|
||||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||||
if (!trieCache.insertName(name, tx.GetHash(), i, txout.nValue, pindex->nHeight))
|
if (!trieCache.insertName(name, tx.GetHash(), i, txout.nValue, pindex->nHeight))
|
||||||
LogPrintf("Something went wrong inserting the name");
|
LogPrintf("%s: Something went wrong inserting the name\n", __func__);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2094,6 +2097,7 @@ bool static DisconnectTip(CValidationState &state) {
|
||||||
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());
|
assert(trieCache.flush());
|
||||||
|
assert(pindexDelete->pprev->hashNCCTrie == trieCache.getMerkleHash());
|
||||||
}
|
}
|
||||||
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.
|
||||||
|
|
|
@ -281,15 +281,15 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||||
if (!CheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true))
|
if (!CheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
UpdateCoins(tx, state, view, nHeight);
|
|
||||||
|
|
||||||
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
||||||
{
|
{
|
||||||
const CCoins* coins = view.AccessCoins(txin.prevout.hash);
|
const CCoins* coins = view.AccessCoins(txin.prevout.hash);
|
||||||
// This seems to happen during testing, and should never happen otherwise
|
// This seems to happen during testing, and should never happen otherwise
|
||||||
if (!coins || txin.prevout.n >= coins->vout.size())
|
if (!coins || txin.prevout.n >= coins->vout.size())
|
||||||
{
|
{
|
||||||
LogPrintf("!coins || txin.prevout.n >= coins->vout.size()");
|
LogPrintf("%s: !coins || txin.prevout.n >= coins->vout.size(). txin.prevout.hash = %s\n", __func__, txin.prevout.hash.GetHex());
|
||||||
|
if (coins)
|
||||||
|
LogPrintf("coins is not null. txin.prevout.n = %d, coins->vout.size() = %d\n", txin.prevout.n, coins->vout.size());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,10 +301,12 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||||
assert(vvchParams.size() == 2);
|
assert(vvchParams.size() == 2);
|
||||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||||
if (!trieCache.removeName(name, txin.prevout.hash, txin.prevout.n))
|
if (!trieCache.removeName(name, txin.prevout.hash, txin.prevout.n))
|
||||||
LogPrintf("Something went wrong removing the name");
|
LogPrintf("%s: Something went wrong removing the name\n", __func__);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateCoins(tx, state, view, nHeight);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < tx.vout.size(); ++i)
|
for (unsigned int i = 0; i < tx.vout.size(); ++i)
|
||||||
{
|
{
|
||||||
const CTxOut& txout = tx.vout[i];
|
const CTxOut& txout = tx.vout[i];
|
||||||
|
@ -316,7 +318,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||||
assert(vvchParams.size() == 2);
|
assert(vvchParams.size() == 2);
|
||||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||||
if (!trieCache.insertName(name, tx.GetHash(), i, txout.nValue, nHeight))
|
if (!trieCache.insertName(name, tx.GetHash(), i, txout.nValue, nHeight))
|
||||||
LogPrintf("Something went wrong inserting the name");
|
LogPrintf("%s: Something went wrong inserting the name\n", __func__);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,7 @@ json_spirit::Array CNCCTrie::dumpToJSON() const
|
||||||
{
|
{
|
||||||
json_spirit::Array ret;
|
json_spirit::Array ret;
|
||||||
if (!recursiveDumpToJSON("", &root, ret))
|
if (!recursiveDumpToJSON("", &root, ret))
|
||||||
LogPrintf("Something went wrong dumping to JSON");
|
LogPrintf("%s: Something went wrong dumping to JSON", __func__);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,8 +321,10 @@ bool CNCCTrie::BatchWrite(nodeCacheType& changedNodes, std::vector<std::string>&
|
||||||
bool CNCCTrie::InsertFromDisk(const std::string& name, CNCCTrieNode* node)
|
bool CNCCTrie::InsertFromDisk(const std::string& name, CNCCTrieNode* node)
|
||||||
{
|
{
|
||||||
if (name.size() == 0)
|
if (name.size() == 0)
|
||||||
|
{
|
||||||
root = *node;
|
root = *node;
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
CNCCTrieNode* current = &root;
|
CNCCTrieNode* current = &root;
|
||||||
for (std::string::const_iterator itname = name.begin(); itname + 1 != name.end(); ++itname)
|
for (std::string::const_iterator itname = name.begin(); itname + 1 != name.end(); ++itname)
|
||||||
{
|
{
|
||||||
|
@ -342,7 +344,7 @@ bool CNCCTrie::ReadFromDisk(bool check)
|
||||||
|
|
||||||
while (pcursor->Valid())
|
while (pcursor->Valid())
|
||||||
{
|
{
|
||||||
//TODO: make try statement here
|
try
|
||||||
{
|
{
|
||||||
leveldb::Slice slKey = pcursor->key();
|
leveldb::Slice slKey = pcursor->key();
|
||||||
CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
|
CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
|
||||||
|
@ -359,15 +361,35 @@ bool CNCCTrie::ReadFromDisk(bool check)
|
||||||
if (!InsertFromDisk(name, node))
|
if (!InsertFromDisk(name, node))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
pcursor->Next();
|
||||||
}
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
return error("%s: Deserialize or I/O error - %s", __func__, e.what());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (check)
|
if (check)
|
||||||
return checkConsistency();
|
{
|
||||||
|
LogPrintf("Checking NCC trie consistency...");
|
||||||
|
if( checkConsistency())
|
||||||
|
{
|
||||||
|
LogPrintf("consistent\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
LogPrintf("inconsistent!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CNCCTrieCache::recursiveComputeMerkleHash(CNCCTrieNode* tnCurrent, std::string sPos) const
|
bool CNCCTrieCache::recursiveComputeMerkleHash(CNCCTrieNode* tnCurrent, std::string sPos) const
|
||||||
{
|
{
|
||||||
|
if (sPos == "" && tnCurrent->empty())
|
||||||
|
{
|
||||||
|
cacheHashes[""] = uint256S("0000000000000000000000000000000000000000000000000000000000000001");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
std::string stringToHash;
|
std::string stringToHash;
|
||||||
|
|
||||||
CNodeValue val;
|
CNodeValue val;
|
||||||
|
@ -547,7 +569,7 @@ bool CNCCTrieCache::removeName(const std::string name, uint256 txhash, int nOut)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The name doesn't exist in either the trie or the cache, so how can we remove it?
|
LogPrintf("%s: The name %s does not exist in the trie\n", __func__, name.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,9 +30,10 @@ CMutableTransaction BuildTransaction(const uint256& prevhash)
|
||||||
return tx;
|
return tx;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(ncctrie_create_insert_remov)
|
BOOST_AUTO_TEST_CASE(ncctrie_create_insert_remove)
|
||||||
{
|
{
|
||||||
CMutableTransaction tx1 = BuildTransaction(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
|
uint256 hash0(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
|
||||||
|
CMutableTransaction tx1 = BuildTransaction(hash0);
|
||||||
CMutableTransaction tx2 = BuildTransaction(tx1.GetHash());
|
CMutableTransaction tx2 = BuildTransaction(tx1.GetHash());
|
||||||
CMutableTransaction tx3 = BuildTransaction(tx2.GetHash());
|
CMutableTransaction tx3 = BuildTransaction(tx2.GetHash());
|
||||||
CMutableTransaction tx4 = BuildTransaction(tx3.GetHash());
|
CMutableTransaction tx4 = BuildTransaction(tx3.GetHash());
|
||||||
|
@ -75,6 +76,15 @@ BOOST_AUTO_TEST_CASE(ncctrie_create_insert_remov)
|
||||||
BOOST_CHECK(!trie.empty());
|
BOOST_CHECK(!trie.empty());
|
||||||
BOOST_CHECK(trie.getMerkleHash() == hash2);
|
BOOST_CHECK(trie.getMerkleHash() == hash2);
|
||||||
BOOST_CHECK(trie.checkConsistency());
|
BOOST_CHECK(trie.checkConsistency());
|
||||||
|
|
||||||
|
CNCCTrieCache ntState1(&trie);
|
||||||
|
ntState1.removeName(std::string("test"), tx1.GetHash(), 0);
|
||||||
|
ntState1.removeName(std::string("test2"), tx2.GetHash(), 0);
|
||||||
|
ntState1.removeName(std::string("test"), tx3.GetHash(), 0);
|
||||||
|
ntState1.removeName(std::string("tes"), tx4.GetHash(), 0);
|
||||||
|
|
||||||
|
BOOST_CHECK(ntState1.getMerkleHash() == hash0);
|
||||||
|
|
||||||
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);
|
ntState2.removeName(std::string("test"), tx1.GetHash(), 0);
|
||||||
|
|
Loading…
Reference in a new issue