rpc commands for browsing ncc trie, fix bugs caused by adding ncc merkle to header

create an rpc command to print the whole ncc trie
create an rpc command to search get transaction info
for a particular name
change the number of bytes in the header expected by miner.cpp
make sure the ncc merkle hash is copied to all structures that
need it
This commit is contained in:
Jimmy Kiselak 2015-02-07 12:32:05 -05:00
parent cd3f33c1fc
commit 79be562ff2
12 changed files with 143 additions and 10 deletions

View file

@ -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 \

View file

@ -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;

View file

@ -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++;

View file

@ -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())

View file

@ -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;
}; };

View file

@ -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++)

View file

@ -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;
} }

View file

@ -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
View 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;
}

View file

@ -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()

View file

@ -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,

View file

@ -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;