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;