Unify claimtrie tests, add some additional root hash checks #181
12 changed files with 143 additions and 10 deletions
|
@ -182,6 +182,7 @@ libbitcoin_server_a_SOURCES = \
|
||||||
rpcblockchain.cpp \
|
rpcblockchain.cpp \
|
||||||
rpcmining.cpp \
|
rpcmining.cpp \
|
||||||
rpcmisc.cpp \
|
rpcmisc.cpp \
|
||||||
|
rpcncctrie.cpp \
|
||||||
rpcnet.cpp \
|
rpcnet.cpp \
|
||||||
rpcrawtransaction.cpp \
|
rpcrawtransaction.cpp \
|
||||||
rpcserver.cpp \
|
rpcserver.cpp \
|
||||||
|
|
|
@ -135,6 +135,7 @@ public:
|
||||||
//! block header
|
//! block header
|
||||||
int nVersion;
|
int nVersion;
|
||||||
uint256 hashMerkleRoot;
|
uint256 hashMerkleRoot;
|
||||||
|
uint256 hashNCCTrie;
|
||||||
unsigned int nTime;
|
unsigned int nTime;
|
||||||
unsigned int nBits;
|
unsigned int nBits;
|
||||||
unsigned int nNonce;
|
unsigned int nNonce;
|
||||||
|
@ -159,6 +160,7 @@ public:
|
||||||
|
|
||||||
nVersion = 0;
|
nVersion = 0;
|
||||||
hashMerkleRoot = uint256();
|
hashMerkleRoot = uint256();
|
||||||
|
hashNCCTrie = uint256();
|
||||||
nTime = 0;
|
nTime = 0;
|
||||||
nBits = 0;
|
nBits = 0;
|
||||||
nNonce = 0;
|
nNonce = 0;
|
||||||
|
@ -175,6 +177,7 @@ public:
|
||||||
|
|
||||||
nVersion = block.nVersion;
|
nVersion = block.nVersion;
|
||||||
hashMerkleRoot = block.hashMerkleRoot;
|
hashMerkleRoot = block.hashMerkleRoot;
|
||||||
|
hashNCCTrie = block.hashNCCTrie;
|
||||||
nTime = block.nTime;
|
nTime = block.nTime;
|
||||||
nBits = block.nBits;
|
nBits = block.nBits;
|
||||||
nNonce = block.nNonce;
|
nNonce = block.nNonce;
|
||||||
|
@ -205,6 +208,7 @@ public:
|
||||||
if (pprev)
|
if (pprev)
|
||||||
block.hashPrevBlock = pprev->GetBlockHash();
|
block.hashPrevBlock = pprev->GetBlockHash();
|
||||||
block.hashMerkleRoot = hashMerkleRoot;
|
block.hashMerkleRoot = hashMerkleRoot;
|
||||||
|
block.hashNCCTrie = hashNCCTrie;
|
||||||
block.nTime = nTime;
|
block.nTime = nTime;
|
||||||
block.nBits = nBits;
|
block.nBits = nBits;
|
||||||
block.nNonce = nNonce;
|
block.nNonce = nNonce;
|
||||||
|
@ -239,9 +243,10 @@ public:
|
||||||
|
|
||||||
std::string ToString() const
|
std::string ToString() const
|
||||||
{
|
{
|
||||||
return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
|
return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, ncctrie=%s, hashBlock=%s)",
|
||||||
pprev, nHeight,
|
pprev, nHeight,
|
||||||
hashMerkleRoot.ToString(),
|
hashMerkleRoot.ToString(),
|
||||||
|
hashNCCTrie.ToString(),
|
||||||
GetBlockHash().ToString());
|
GetBlockHash().ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,6 +316,7 @@ public:
|
||||||
READWRITE(this->nVersion);
|
READWRITE(this->nVersion);
|
||||||
READWRITE(hashPrev);
|
READWRITE(hashPrev);
|
||||||
READWRITE(hashMerkleRoot);
|
READWRITE(hashMerkleRoot);
|
||||||
|
READWRITE(hashNCCTrie);
|
||||||
READWRITE(nTime);
|
READWRITE(nTime);
|
||||||
READWRITE(nBits);
|
READWRITE(nBits);
|
||||||
READWRITE(nNonce);
|
READWRITE(nNonce);
|
||||||
|
@ -322,6 +328,7 @@ public:
|
||||||
block.nVersion = nVersion;
|
block.nVersion = nVersion;
|
||||||
block.hashPrevBlock = hashPrev;
|
block.hashPrevBlock = hashPrev;
|
||||||
block.hashMerkleRoot = hashMerkleRoot;
|
block.hashMerkleRoot = hashMerkleRoot;
|
||||||
|
block.hashNCCTrie = hashNCCTrie;
|
||||||
block.nTime = nTime;
|
block.nTime = nTime;
|
||||||
block.nBits = nBits;
|
block.nBits = nBits;
|
||||||
block.nNonce = nNonce;
|
block.nNonce = nNonce;
|
||||||
|
|
|
@ -412,12 +412,12 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int&
|
||||||
//
|
//
|
||||||
bool static ScanHash(const CBlockHeader *pblock, uint32_t& nNonce, uint256 *phash)
|
bool static ScanHash(const CBlockHeader *pblock, uint32_t& nNonce, uint256 *phash)
|
||||||
{
|
{
|
||||||
// Write the first 76 bytes of the block header to a double-SHA256 state.
|
// Write the first 108 bytes of the block header to a double-SHA256 state.
|
||||||
CHash256 hasher;
|
CHash256 hasher;
|
||||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
ss << *pblock;
|
ss << *pblock;
|
||||||
assert(ss.size() == 80);
|
assert(ss.size() == 112);
|
||||||
hasher.Write((unsigned char*)&ss[0], 76);
|
hasher.Write((unsigned char*)&ss[0], 108);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
nNonce++;
|
nNonce++;
|
||||||
|
|
|
@ -59,7 +59,7 @@ bool CNCCTrieNode::removeValue(CNodeValue val, bool * pfChanged)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CNCCTrieNode::getValue(CNodeValue& value)
|
bool CNCCTrieNode::getValue(CNodeValue& value) const
|
||||||
{
|
{
|
||||||
if (values.empty())
|
if (values.empty())
|
||||||
return false;
|
return false;
|
||||||
|
@ -80,6 +80,62 @@ bool CNCCTrie::empty() const
|
||||||
return root.empty();
|
return root.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CNCCTrie::recursiveDumpToJSON(const std::string& name, const CNCCTrieNode* current, json_spirit::Array& ret) const
|
||||||
|
{
|
||||||
|
using namespace json_spirit;
|
||||||
|
Object objNode;
|
||||||
|
objNode.push_back(Pair("name", name));
|
||||||
|
objNode.push_back(Pair("hash", current->hash.GetHex()));
|
||||||
|
CNodeValue val;
|
||||||
|
if (current->getValue(val))
|
||||||
|
{
|
||||||
|
objNode.push_back(Pair("txid", val.txhash.GetHex()));
|
||||||
|
objNode.push_back(Pair("n", (int)val.nOut));
|
||||||
|
objNode.push_back(Pair("value", val.nAmount));
|
||||||
|
objNode.push_back(Pair("height", val.nHeight));
|
||||||
|
}
|
||||||
|
ret.push_back(objNode);
|
||||||
|
for (nodeMapType::const_iterator it = current->children.begin(); it != current->children.end(); ++it)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << name << it->first;
|
||||||
|
if (!recursiveDumpToJSON(ss.str(), it->second, ret))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_spirit::Array CNCCTrie::dumpToJSON() const
|
||||||
|
{
|
||||||
|
json_spirit::Array ret;
|
||||||
|
if (!recursiveDumpToJSON("", &root, ret))
|
||||||
|
LogPrintf("Something went wrong dumping to JSON");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_spirit::Object CNCCTrie::getInfoForName(const std::string& name) const
|
||||||
|
{
|
||||||
|
using namespace json_spirit;
|
||||||
|
Object ret;
|
||||||
|
const CNCCTrieNode* current = &root;
|
||||||
|
for (std::string::const_iterator itname = name.begin(); itname != name.end(); ++itname)
|
||||||
|
{
|
||||||
|
nodeMapType::const_iterator itchildren = current->children.find(*itname);
|
||||||
|
if (itchildren == current->children.end())
|
||||||
|
return ret;
|
||||||
|
current = itchildren->second;
|
||||||
|
}
|
||||||
|
CNodeValue val;
|
||||||
|
if (current->getValue(val))
|
||||||
|
{
|
||||||
|
ret.push_back(Pair("txid", val.txhash.GetHex()));
|
||||||
|
ret.push_back(Pair("n", (int)val.nOut));
|
||||||
|
ret.push_back(Pair("value", val.nAmount));
|
||||||
|
ret.push_back(Pair("height", val.nHeight));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
bool CNCCTrie::checkConsistency()
|
bool CNCCTrie::checkConsistency()
|
||||||
{
|
{
|
||||||
if (empty())
|
if (empty())
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include "json/json_spirit_value.h"
|
||||||
|
|
||||||
class CNodeValue
|
class CNodeValue
|
||||||
{
|
{
|
||||||
|
@ -82,7 +82,7 @@ public:
|
||||||
std::vector<CNodeValue> values;
|
std::vector<CNodeValue> values;
|
||||||
bool insertValue(CNodeValue val, bool * fChanged = NULL);
|
bool insertValue(CNodeValue val, bool * fChanged = NULL);
|
||||||
bool removeValue(CNodeValue val, bool * fChanged = NULL);
|
bool removeValue(CNodeValue val, bool * fChanged = NULL);
|
||||||
bool getValue(CNodeValue& val);
|
bool getValue(CNodeValue& val) const;
|
||||||
bool empty() const {return children.empty() && values.empty();}
|
bool empty() const {return children.empty() && values.empty();}
|
||||||
|
|
||||||
ADD_SERIALIZE_METHODS;
|
ADD_SERIALIZE_METHODS;
|
||||||
|
@ -129,6 +129,8 @@ public:
|
||||||
bool empty() const;
|
bool empty() const;
|
||||||
bool checkConsistency();
|
bool checkConsistency();
|
||||||
bool ReadFromDisk(bool check = false);
|
bool ReadFromDisk(bool check = false);
|
||||||
|
json_spirit::Array dumpToJSON() const;
|
||||||
|
json_spirit::Object getInfoForName(const std::string& name) const;
|
||||||
friend class CNCCTrieCache;
|
friend class CNCCTrieCache;
|
||||||
private:
|
private:
|
||||||
bool update(nodeCacheType& cache, hashMapType& hashes);
|
bool update(nodeCacheType& cache, hashMapType& hashes);
|
||||||
|
@ -138,6 +140,7 @@ private:
|
||||||
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);
|
bool InsertFromDisk(const std::string& name, CNCCTrieNode* node);
|
||||||
|
bool recursiveDumpToJSON(const std::string& name, const CNCCTrieNode* current, json_spirit::Array& ret) const;
|
||||||
CNCCTrieNode root;
|
CNCCTrieNode root;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -111,11 +111,12 @@ uint256 CBlock::CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMer
|
||||||
std::string CBlock::ToString() const
|
std::string CBlock::ToString() const
|
||||||
{
|
{
|
||||||
std::stringstream s;
|
std::stringstream s;
|
||||||
s << strprintf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%u)\n",
|
s << strprintf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, hashNCCTrie=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%u)\n",
|
||||||
GetHash().ToString(),
|
GetHash().ToString(),
|
||||||
nVersion,
|
nVersion,
|
||||||
hashPrevBlock.ToString(),
|
hashPrevBlock.ToString(),
|
||||||
hashMerkleRoot.ToString(),
|
hashMerkleRoot.ToString(),
|
||||||
|
hashNCCTrie.ToString(),
|
||||||
nTime, nBits, nNonce,
|
nTime, nBits, nNonce,
|
||||||
vtx.size());
|
vtx.size());
|
||||||
for (unsigned int i = 0; i < vtx.size(); i++)
|
for (unsigned int i = 0; i < vtx.size(); i++)
|
||||||
|
|
|
@ -46,10 +46,10 @@ public:
|
||||||
nVersion = this->nVersion;
|
nVersion = this->nVersion;
|
||||||
READWRITE(hashPrevBlock);
|
READWRITE(hashPrevBlock);
|
||||||
READWRITE(hashMerkleRoot);
|
READWRITE(hashMerkleRoot);
|
||||||
|
READWRITE(hashNCCTrie);
|
||||||
READWRITE(nTime);
|
READWRITE(nTime);
|
||||||
READWRITE(nBits);
|
READWRITE(nBits);
|
||||||
READWRITE(nNonce);
|
READWRITE(nNonce);
|
||||||
READWRITE(hashNCCTrie);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetNull()
|
void SetNull()
|
||||||
|
@ -118,10 +118,10 @@ public:
|
||||||
block.nVersion = nVersion;
|
block.nVersion = nVersion;
|
||||||
block.hashPrevBlock = hashPrevBlock;
|
block.hashPrevBlock = hashPrevBlock;
|
||||||
block.hashMerkleRoot = hashMerkleRoot;
|
block.hashMerkleRoot = hashMerkleRoot;
|
||||||
|
block.hashNCCTrie = hashNCCTrie;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,7 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDe
|
||||||
result.push_back(Pair("height", blockindex->nHeight));
|
result.push_back(Pair("height", blockindex->nHeight));
|
||||||
result.push_back(Pair("version", block.nVersion));
|
result.push_back(Pair("version", block.nVersion));
|
||||||
result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
|
result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
|
||||||
|
result.push_back(Pair("nccroot", block.hashNCCTrie.GetHex()));
|
||||||
Array txs;
|
Array txs;
|
||||||
BOOST_FOREACH(const CTransaction&tx, block.vtx)
|
BOOST_FOREACH(const CTransaction&tx, block.vtx)
|
||||||
{
|
{
|
||||||
|
@ -266,6 +267,7 @@ Value getblock(const Array& params, bool fHelp)
|
||||||
" \"height\" : n, (numeric) The block height or index\n"
|
" \"height\" : n, (numeric) The block height or index\n"
|
||||||
" \"version\" : n, (numeric) The block version\n"
|
" \"version\" : n, (numeric) The block version\n"
|
||||||
" \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
|
" \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
|
||||||
|
" \"nccroot\" : \"xxxx\", (string) The hash of the root of the NCC trie\n"
|
||||||
" \"tx\" : [ (array of string) The transaction ids\n"
|
" \"tx\" : [ (array of string) The transaction ids\n"
|
||||||
" \"transactionid\" (string) The transaction id\n"
|
" \"transactionid\" (string) The transaction id\n"
|
||||||
" ,...\n"
|
" ,...\n"
|
||||||
|
|
55
src/rpcncctrie.cpp
Normal file
55
src/rpcncctrie.cpp
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
#include "json/json_spirit_value.h"
|
||||||
|
|
||||||
|
using namespace json_spirit;
|
||||||
|
//using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
Value getncctrie(const Array& params, bool fHelp)
|
||||||
|
{
|
||||||
|
if (fHelp || params.size() > 0)
|
||||||
|
throw std::runtime_error(
|
||||||
|
"getncctrie\n"
|
||||||
|
"Return the entire NCC trie.\n"
|
||||||
|
"Arguments:\n"
|
||||||
|
"None\n"
|
||||||
|
"Result: \n"
|
||||||
|
"{\n"
|
||||||
|
" \"name\" (string) the name of the node\n"
|
||||||
|
" \"hash\" (string) the hash of the node\n"
|
||||||
|
" \"txid\" (string) (if value exists) the hash of the transaction which has successfully claimed this name\n"
|
||||||
|
" \"n\" (numeric) (if value exists) vout value\n"
|
||||||
|
" \"value\" (numeric) (if value exists) txout value\n"
|
||||||
|
" \"height\" (numeric) (if value exists) the height of the block in which this transaction is located\n"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
LOCK(cs_main);
|
||||||
|
|
||||||
|
Array ret = pnccTrie->dumpToJSON();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value gettxinfoforname(const Array& params, bool fHelp)
|
||||||
|
{
|
||||||
|
if (fHelp || params.size() != 1)
|
||||||
|
throw std::runtime_error(
|
||||||
|
"gettxinfoforname\n"
|
||||||
|
"Return information about the transaction that has successfully claimed a name, if one exists\n"
|
||||||
|
"Arguments:\n"
|
||||||
|
"1. \"name\" (string) the name about which to return info\n"
|
||||||
|
"Result: \n"
|
||||||
|
"\"txid\" (string) the hash of the transaction which successfully claimed the name\n"
|
||||||
|
"\"n\" (numeric) vout value\n"
|
||||||
|
"\"value\" (numeric) txout value\n"
|
||||||
|
"\"height\" (numeric) the height of the block in which this transaction is located\n"
|
||||||
|
);
|
||||||
|
LOCK(cs_main);
|
||||||
|
|
||||||
|
std::string name = params[0].get_str();
|
||||||
|
|
||||||
|
Object ret = pnccTrie->getInfoForName(name);
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -380,6 +380,10 @@ static const CRPCCommand vRPCCommands[] =
|
||||||
{ "wallet", "walletpassphrasechange", &walletpassphrasechange, true, true },
|
{ "wallet", "walletpassphrasechange", &walletpassphrasechange, true, true },
|
||||||
{ "wallet", "walletpassphrase", &walletpassphrase, true, true },
|
{ "wallet", "walletpassphrase", &walletpassphrase, true, true },
|
||||||
#endif // ENABLE_WALLET
|
#endif // ENABLE_WALLET
|
||||||
|
|
||||||
|
/* NCC trie */
|
||||||
|
{ "ncctrie", "getncctrie", &getncctrie, true, false},
|
||||||
|
{ "ncctrie", "gettxinfoforname", &gettxinfoforname, true, false},
|
||||||
};
|
};
|
||||||
|
|
||||||
CRPCTable::CRPCTable()
|
CRPCTable::CRPCTable()
|
||||||
|
|
|
@ -237,6 +237,9 @@ extern json_spirit::Value getchaintips(const json_spirit::Array& params, bool fH
|
||||||
extern json_spirit::Value invalidateblock(const json_spirit::Array& params, bool fHelp);
|
extern json_spirit::Value invalidateblock(const json_spirit::Array& params, bool fHelp);
|
||||||
extern json_spirit::Value reconsiderblock(const json_spirit::Array& params, bool fHelp);
|
extern json_spirit::Value reconsiderblock(const json_spirit::Array& params, bool fHelp);
|
||||||
|
|
||||||
|
extern json_spirit::Value getncctrie(const json_spirit::Array& params, bool fHelp); // in rpcncctrie.cpp
|
||||||
|
extern json_spirit::Value gettxinfoforname(const json_spirit::Array& params, bool fHelp);
|
||||||
|
|
||||||
// in rest.cpp
|
// in rest.cpp
|
||||||
extern bool HTTPReq_REST(AcceptedConnection *conn,
|
extern bool HTTPReq_REST(AcceptedConnection *conn,
|
||||||
const std::string& strURI,
|
const std::string& strURI,
|
||||||
|
|
|
@ -216,6 +216,7 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
|
||||||
pindexNew->nUndoPos = diskindex.nUndoPos;
|
pindexNew->nUndoPos = diskindex.nUndoPos;
|
||||||
pindexNew->nVersion = diskindex.nVersion;
|
pindexNew->nVersion = diskindex.nVersion;
|
||||||
pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
|
pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
|
||||||
|
pindexNew->hashNCCTrie = diskindex.hashNCCTrie;
|
||||||
pindexNew->nTime = diskindex.nTime;
|
pindexNew->nTime = diskindex.nTime;
|
||||||
pindexNew->nBits = diskindex.nBits;
|
pindexNew->nBits = diskindex.nBits;
|
||||||
pindexNew->nNonce = diskindex.nNonce;
|
pindexNew->nNonce = diskindex.nNonce;
|
||||||
|
|
Loading…
Reference in a new issue