diff --git a/src/main.cpp b/src/main.cpp index 17af295e..3079da44 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1175,6 +1175,8 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size())); std::vector > vPos; vPos.reserve(block.vtx.size()-1); + std::vector vUsernames; + vUsernames.reserve(block.vtx.size()-1); for (unsigned int i = 0; i < block.vtx.size(); i++) { const CTransaction &tx = block.vtx[i]; @@ -1184,6 +1186,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C blockundo.vtxundo.push_back(txundo); uint256 txid = SerializeHash(make_pair(tx.GetUsername(),-1)); vPos.push_back(std::make_pair(txid, pos)); + vUsernames.push_back(tx.GetUsername()); CDiskTxPos oldPos; if( pblocktree->ReadTxIndex(txid, oldPos) && pos != oldPos ) { @@ -1228,6 +1231,11 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C if (!pblocktree->WriteTxIndex(vPos)) return state.Abort(_("Failed to write transaction index")); + for (size_t i=0; iAddNameToPartialNameTree(vUsernames.at(i))) + return state.Abort(_("Failed to write partial name index")); + } + // add this block to the view's block chain assert(view.SetBestBlock(pindex)); diff --git a/src/twister.cpp b/src/twister.cpp index 6a5339b0..835d2488 100644 --- a/src/twister.cpp +++ b/src/twister.cpp @@ -5,6 +5,7 @@ #include "main.h" #include "init.h" #include "bitcoinrpc.h" +#include "txdb.h" using namespace json_spirit; using namespace std; @@ -1695,27 +1696,7 @@ Value listusernamespartial(const Array& params, bool fHelp) } } - // now the rest, the entire block chain - for(CBlockIndex* pindex = pindexBest; pindex && retStrings.size() < count; pindex = pindex->pprev ) { - CBlock block; - if( !ReadBlockFromDisk(block, pindex) ) - continue; - - BOOST_FOREACH(const CTransaction&tx, block.vtx) { - if( !tx.IsSpamMessage() ) { - string txUsername = tx.userName.ExtractSmallString(); - if( (exact_match && userStartsWith.size() != txUsername.size()) || - userStartsWith.size() > txUsername.size() ) { - continue; - } - int toCompare = userStartsWith.size(); - if( memcmp( txUsername.data(), userStartsWith.data(), toCompare ) == 0 ) - retStrings.insert( txUsername ); - if( retStrings.size() >= count ) - break; - } - } - } + pblocktree->GetNamesFromPartial(userStartsWith, retStrings, count); Array ret; BOOST_FOREACH(string username, retStrings) { diff --git a/src/txdb.cpp b/src/txdb.cpp index 572fb5ee..b7d4da01 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -189,6 +189,51 @@ bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) { return true; } +bool CBlockTreeDB::WritePartialNameTree(const std::string &partialName, const std::string &nextChars) { + return Write(std::make_pair('n', partialName), nextChars); +} + + +bool CBlockTreeDB::ReadPartialNameTree(const std::string &partialName, std::string &nextChars) { + return Read(std::make_pair('n', partialName), nextChars); +} + +bool CBlockTreeDB::AddCharToPartialNameTree(const std::string &partialName, char ch) { + std::string nextChars; + if (ReadPartialNameTree(partialName, nextChars)) { + if (nextChars.find(ch) == string::npos) { + nextChars.push_back(ch); + return WritePartialNameTree(partialName, nextChars); + } + } else { + return WritePartialNameTree(partialName, std::string(1,ch)); + } + return true; +} + +bool CBlockTreeDB::AddNameToPartialNameTree(const std::string &name) { + std::string partial; + for (size_t i=0; i &names, size_t count) { + std::string nextChars; + if (ReadPartialNameTree(partial, nextChars)) { + for(size_t i=0; i > &list); bool WriteFlag(const std::string &name, bool fValue); bool ReadFlag(const std::string &name, bool &fValue); + bool WritePartialNameTree(const std::string &partialName, const std::string &nextChars); + bool ReadPartialNameTree(const std::string &partialName, std::string &nextChars); + bool AddCharToPartialNameTree(const std::string &partialName, char ch); + bool AddNameToPartialNameTree(const std::string &name); + void GetNamesFromPartial(const std::string &partial, std::set< std::string > &names, size_t count); bool LoadBlockIndexGuts(); };