From 79be562ff20efa7c3befd2bffe587fc048e683a0 Mon Sep 17 00:00:00 2001 From: Jimmy Kiselak Date: Sat, 7 Feb 2015 12:32:05 -0500 Subject: [PATCH] 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 --- src/Makefile.am | 1 + src/chain.h | 9 ++++++- src/miner.cpp | 6 ++--- src/ncctrie.cpp | 58 +++++++++++++++++++++++++++++++++++++++- src/ncctrie.h | 7 +++-- src/primitives/block.cpp | 3 ++- src/primitives/block.h | 4 +-- src/rpcblockchain.cpp | 2 ++ src/rpcncctrie.cpp | 55 +++++++++++++++++++++++++++++++++++++ src/rpcserver.cpp | 4 +++ src/rpcserver.h | 3 +++ src/txdb.cpp | 1 + 12 files changed, 143 insertions(+), 10 deletions(-) create mode 100644 src/rpcncctrie.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 37bc88658..54e6f8423 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -182,6 +182,7 @@ libbitcoin_server_a_SOURCES = \ rpcblockchain.cpp \ rpcmining.cpp \ rpcmisc.cpp \ + rpcncctrie.cpp \ rpcnet.cpp \ rpcrawtransaction.cpp \ rpcserver.cpp \ diff --git a/src/chain.h b/src/chain.h index 004e87ab5..324c2dc1d 100644 --- a/src/chain.h +++ b/src/chain.h @@ -135,6 +135,7 @@ public: //! block header int nVersion; uint256 hashMerkleRoot; + uint256 hashNCCTrie; unsigned int nTime; unsigned int nBits; unsigned int nNonce; @@ -159,6 +160,7 @@ public: nVersion = 0; hashMerkleRoot = uint256(); + hashNCCTrie = uint256(); nTime = 0; nBits = 0; nNonce = 0; @@ -175,6 +177,7 @@ public: nVersion = block.nVersion; hashMerkleRoot = block.hashMerkleRoot; + hashNCCTrie = block.hashNCCTrie; nTime = block.nTime; nBits = block.nBits; nNonce = block.nNonce; @@ -205,6 +208,7 @@ public: if (pprev) block.hashPrevBlock = pprev->GetBlockHash(); block.hashMerkleRoot = hashMerkleRoot; + block.hashNCCTrie = hashNCCTrie; block.nTime = nTime; block.nBits = nBits; block.nNonce = nNonce; @@ -239,9 +243,10 @@ public: 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, hashMerkleRoot.ToString(), + hashNCCTrie.ToString(), GetBlockHash().ToString()); } @@ -311,6 +316,7 @@ public: READWRITE(this->nVersion); READWRITE(hashPrev); READWRITE(hashMerkleRoot); + READWRITE(hashNCCTrie); READWRITE(nTime); READWRITE(nBits); READWRITE(nNonce); @@ -322,6 +328,7 @@ public: block.nVersion = nVersion; block.hashPrevBlock = hashPrev; block.hashMerkleRoot = hashMerkleRoot; + block.hashNCCTrie = hashNCCTrie; block.nTime = nTime; block.nBits = nBits; block.nNonce = nNonce; diff --git a/src/miner.cpp b/src/miner.cpp index e27d8fdae..bd65ef211 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -412,12 +412,12 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& // 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; CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << *pblock; - assert(ss.size() == 80); - hasher.Write((unsigned char*)&ss[0], 76); + assert(ss.size() == 112); + hasher.Write((unsigned char*)&ss[0], 108); while (true) { nNonce++; diff --git a/src/ncctrie.cpp b/src/ncctrie.cpp index 406abef99..d73a34d16 100644 --- a/src/ncctrie.cpp +++ b/src/ncctrie.cpp @@ -59,7 +59,7 @@ bool CNCCTrieNode::removeValue(CNodeValue val, bool * pfChanged) return true; } -bool CNCCTrieNode::getValue(CNodeValue& value) +bool CNCCTrieNode::getValue(CNodeValue& value) const { if (values.empty()) return false; @@ -80,6 +80,62 @@ bool CNCCTrie::empty() const 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() { if (empty()) diff --git a/src/ncctrie.h b/src/ncctrie.h index f6b78284e..605480f3e 100644 --- a/src/ncctrie.h +++ b/src/ncctrie.h @@ -13,7 +13,7 @@ #include #include #include - +#include "json/json_spirit_value.h" class CNodeValue { @@ -82,7 +82,7 @@ public: std::vector values; bool insertValue(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();} ADD_SERIALIZE_METHODS; @@ -129,6 +129,8 @@ public: bool empty() const; bool checkConsistency(); bool ReadFromDisk(bool check = false); + json_spirit::Array dumpToJSON() const; + json_spirit::Object getInfoForName(const std::string& name) const; friend class CNCCTrieCache; private: bool update(nodeCacheType& cache, hashMapType& hashes); @@ -138,6 +140,7 @@ private: bool recursiveCheckConsistency(CNCCTrieNode* node); bool BatchWrite(nodeCacheType& changedNodes, std::vector& deletedNames); bool InsertFromDisk(const std::string& name, CNCCTrieNode* node); + bool recursiveDumpToJSON(const std::string& name, const CNCCTrieNode* current, json_spirit::Array& ret) const; CNCCTrieNode root; }; diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index 3b4a36039..c8b04a78e 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -111,11 +111,12 @@ uint256 CBlock::CheckMerkleBranch(uint256 hash, const std::vector& vMer std::string CBlock::ToString() const { 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(), nVersion, hashPrevBlock.ToString(), hashMerkleRoot.ToString(), + hashNCCTrie.ToString(), nTime, nBits, nNonce, vtx.size()); for (unsigned int i = 0; i < vtx.size(); i++) diff --git a/src/primitives/block.h b/src/primitives/block.h index 66d1ea884..0e9c87ff3 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -46,10 +46,10 @@ public: nVersion = this->nVersion; READWRITE(hashPrevBlock); READWRITE(hashMerkleRoot); + READWRITE(hashNCCTrie); READWRITE(nTime); READWRITE(nBits); READWRITE(nNonce); - READWRITE(hashNCCTrie); } void SetNull() @@ -118,10 +118,10 @@ public: block.nVersion = nVersion; block.hashPrevBlock = hashPrevBlock; block.hashMerkleRoot = hashMerkleRoot; + block.hashNCCTrie = hashNCCTrie; block.nTime = nTime; block.nBits = nBits; block.nNonce = nNonce; - block.hashNCCTrie = hashNCCTrie; return block; } diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 293d6d561..e1349acdb 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -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("version", block.nVersion)); result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); + result.push_back(Pair("nccroot", block.hashNCCTrie.GetHex())); Array txs; 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" " \"version\" : n, (numeric) The block version\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" " \"transactionid\" (string) The transaction id\n" " ,...\n" diff --git a/src/rpcncctrie.cpp b/src/rpcncctrie.cpp new file mode 100644 index 000000000..b4840624b --- /dev/null +++ b/src/rpcncctrie.cpp @@ -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; +} diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 738feedf0..527d57d7c 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -380,6 +380,10 @@ static const CRPCCommand vRPCCommands[] = { "wallet", "walletpassphrasechange", &walletpassphrasechange, true, true }, { "wallet", "walletpassphrase", &walletpassphrase, true, true }, #endif // ENABLE_WALLET + + /* NCC trie */ + { "ncctrie", "getncctrie", &getncctrie, true, false}, + { "ncctrie", "gettxinfoforname", &gettxinfoforname, true, false}, }; CRPCTable::CRPCTable() diff --git a/src/rpcserver.h b/src/rpcserver.h index dd695fd90..b36b2be36 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -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 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 extern bool HTTPReq_REST(AcceptedConnection *conn, const std::string& strURI, diff --git a/src/txdb.cpp b/src/txdb.cpp index da271bd5d..482bd0a4b 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -216,6 +216,7 @@ bool CBlockTreeDB::LoadBlockIndexGuts() pindexNew->nUndoPos = diskindex.nUndoPos; pindexNew->nVersion = diskindex.nVersion; pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot; + pindexNew->hashNCCTrie = diskindex.hashNCCTrie; pindexNew->nTime = diskindex.nTime; pindexNew->nBits = diskindex.nBits; pindexNew->nNonce = diskindex.nNonce;