main: add block timestamp index
This commit is contained in:
committed by
Braydon Fuller
parent
24deb4efc1
commit
935ca8f832
28
src/main.cpp
28
src/main.cpp
@@ -67,6 +67,7 @@ bool fImporting = false;
|
||||
bool fReindex = false;
|
||||
bool fTxIndex = false;
|
||||
bool fAddressIndex = false;
|
||||
bool fTimestampIndex = false;
|
||||
bool fHavePruned = false;
|
||||
bool fPruneMode = false;
|
||||
bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG;
|
||||
@@ -1439,6 +1440,17 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
||||
return res;
|
||||
}
|
||||
|
||||
bool GetTimestampIndex(const unsigned int &high, const unsigned int &low, std::vector<uint256> &hashes)
|
||||
{
|
||||
if (!fTimestampIndex)
|
||||
return error("Timestamp index not enabled");
|
||||
|
||||
if (!pblocktree->ReadTimestampIndex(high, low, hashes))
|
||||
return error("Unable to get hashes for timestamps");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetAddressIndex(uint160 addressHash, int type, std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex)
|
||||
{
|
||||
if (!fAddressIndex)
|
||||
@@ -2471,8 +2483,12 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||
return AbortNode(state, "Failed to write transaction index");
|
||||
|
||||
if (fAddressIndex)
|
||||
if (!pblocktree->WriteAddressIndex(addressIndex))
|
||||
return AbortNode(state, "Failed to write address index");
|
||||
if (!pblocktree->WriteAddressIndex(addressIndex))
|
||||
return AbortNode(state, "Failed to write address index");
|
||||
|
||||
if (fTimestampIndex)
|
||||
if (!pblocktree->WriteTimestampIndex(CTimestampIndexKey(pindex->nTime, pindex->GetBlockHash())))
|
||||
return AbortNode(state, "Failed to write timestamp index");
|
||||
|
||||
// add this block to the view's block chain
|
||||
view.SetBestBlock(pindex->GetBlockHash());
|
||||
@@ -3869,6 +3885,10 @@ bool static LoadBlockIndexDB()
|
||||
pblocktree->ReadFlag("addressindex", fAddressIndex);
|
||||
LogPrintf("%s: address index %s\n", __func__, fAddressIndex ? "enabled" : "disabled");
|
||||
|
||||
// Check whether we have a timestamp index
|
||||
pblocktree->ReadFlag("timestampindex", fTimestampIndex);
|
||||
LogPrintf("%s: timestamp index %s\n", __func__, fTimestampIndex ? "enabled" : "disabled");
|
||||
|
||||
// Load pointer to end of best chain
|
||||
BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
|
||||
if (it == mapBlockIndex.end())
|
||||
@@ -4034,6 +4054,10 @@ bool InitBlockIndex(const CChainParams& chainparams)
|
||||
fAddressIndex = GetBoolArg("-addressindex", DEFAULT_ADDRESSINDEX);
|
||||
pblocktree->WriteFlag("addressindex", fAddressIndex);
|
||||
|
||||
// Use the provided setting for -timestampindex in the new database
|
||||
fTimestampIndex = GetBoolArg("-timestampindex", DEFAULT_TIMESTAMPINDEX);
|
||||
pblocktree->WriteFlag("timestampindex", fTimestampIndex);
|
||||
|
||||
LogPrintf("Initializing databases...\n");
|
||||
|
||||
// Only add the genesis block if not reindexing (in which case we reuse the one already on disk)
|
||||
|
||||
63
src/main.h
63
src/main.h
@@ -112,6 +112,7 @@ static const unsigned int DEFAULT_BYTES_PER_SIGOP = 20;
|
||||
static const bool DEFAULT_CHECKPOINTS_ENABLED = true;
|
||||
static const bool DEFAULT_TXINDEX = false;
|
||||
static const bool DEFAULT_ADDRESSINDEX = false;
|
||||
static const bool DEFAULT_TIMESTAMPINDEX = false;
|
||||
static const unsigned int DEFAULT_BANSCORE_THRESHOLD = 100;
|
||||
|
||||
static const bool DEFAULT_TESTSAFEMODE = false;
|
||||
@@ -291,6 +292,67 @@ struct CNodeStateStats {
|
||||
std::vector<int> vHeightInFlight;
|
||||
};
|
||||
|
||||
struct CTimestampIndexIteratorKey {
|
||||
unsigned int timestamp;
|
||||
|
||||
size_t GetSerializeSize(int nType, int nVersion) const {
|
||||
return 4;
|
||||
}
|
||||
template<typename Stream>
|
||||
void Serialize(Stream& s, int nType, int nVersion) const {
|
||||
ser_writedata32be(s, timestamp);
|
||||
}
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream& s, int nType, int nVersion) {
|
||||
timestamp = ser_readdata32be(s);
|
||||
}
|
||||
|
||||
CTimestampIndexIteratorKey(unsigned int time) {
|
||||
timestamp = time;
|
||||
}
|
||||
|
||||
CTimestampIndexIteratorKey() {
|
||||
SetNull();
|
||||
}
|
||||
|
||||
void SetNull() {
|
||||
timestamp = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct CTimestampIndexKey {
|
||||
unsigned int timestamp;
|
||||
uint256 blockHash;
|
||||
|
||||
size_t GetSerializeSize(int nType, int nVersion) const {
|
||||
return 36;
|
||||
}
|
||||
template<typename Stream>
|
||||
void Serialize(Stream& s, int nType, int nVersion) const {
|
||||
ser_writedata32be(s, timestamp);
|
||||
blockHash.Serialize(s, nType, nVersion);
|
||||
}
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream& s, int nType, int nVersion) {
|
||||
timestamp = ser_readdata32be(s);
|
||||
blockHash.Unserialize(s, nType, nVersion);
|
||||
}
|
||||
|
||||
CTimestampIndexKey(unsigned int time, uint256 hash) {
|
||||
timestamp = time;
|
||||
blockHash = hash;
|
||||
}
|
||||
|
||||
CTimestampIndexKey() {
|
||||
SetNull();
|
||||
}
|
||||
|
||||
void SetNull() {
|
||||
timestamp = 0;
|
||||
blockHash.SetNull();
|
||||
}
|
||||
};
|
||||
|
||||
struct CAddressIndexKey {
|
||||
unsigned int type;
|
||||
uint160 hashBytes;
|
||||
@@ -510,6 +572,7 @@ public:
|
||||
ScriptError GetScriptError() const { return error; }
|
||||
};
|
||||
|
||||
bool GetTimestampIndex(const unsigned int &high, const unsigned int &low, std::vector<uint256> &hashes);
|
||||
bool GetAddressIndex(uint160 addressHash, int type, std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex);
|
||||
|
||||
/** Functions for disk access for blocks */
|
||||
|
||||
@@ -275,6 +275,38 @@ UniValue getrawmempool(const UniValue& params, bool fHelp)
|
||||
return mempoolToJSON(fVerbose);
|
||||
}
|
||||
|
||||
UniValue getblockhashes(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 2)
|
||||
throw runtime_error(
|
||||
"getblockhashes timestamp\n"
|
||||
"\nReturns array of hashes of blocks within the timestamp range provided.\n"
|
||||
"\nArguments:\n"
|
||||
"1. high (numeric, required) The newer block timestamp\n"
|
||||
"2. low (numeric, required) The older block timestamp\n"
|
||||
"\nResult:\n"
|
||||
"["
|
||||
" \"hash\" (string) The block hash\n"
|
||||
"]"
|
||||
"\nExamples:\n"
|
||||
);
|
||||
|
||||
unsigned int high = params[0].get_int();
|
||||
unsigned int low = params[1].get_int();
|
||||
std::vector<uint256> blockHashes;
|
||||
|
||||
if (!GetTimestampIndex(high, low, blockHashes)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for block hashes");
|
||||
}
|
||||
|
||||
UniValue result(UniValue::VARR);
|
||||
for (std::vector<uint256>::const_iterator it=blockHashes.begin(); it!=blockHashes.end(); it++) {
|
||||
result.push_back(it->GetHex());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
UniValue getblockhash(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 1)
|
||||
|
||||
@@ -278,6 +278,7 @@ static const CRPCCommand vRPCCommands[] =
|
||||
{ "blockchain", "getbestblockhash", &getbestblockhash, true },
|
||||
{ "blockchain", "getblockcount", &getblockcount, true },
|
||||
{ "blockchain", "getblock", &getblock, true },
|
||||
{ "blockchain", "getblockhashes", &getblockhashes, true },
|
||||
{ "blockchain", "getblockhash", &getblockhash, true },
|
||||
{ "blockchain", "getblockheader", &getblockheader, true },
|
||||
{ "blockchain", "getchaintips", &getchaintips, true },
|
||||
|
||||
@@ -258,6 +258,7 @@ extern UniValue getdifficulty(const UniValue& params, bool fHelp);
|
||||
extern UniValue settxfee(const UniValue& params, bool fHelp);
|
||||
extern UniValue getmempoolinfo(const UniValue& params, bool fHelp);
|
||||
extern UniValue getrawmempool(const UniValue& params, bool fHelp);
|
||||
extern UniValue getblockhashes(const UniValue& params, bool fHelp);
|
||||
extern UniValue getblockhash(const UniValue& params, bool fHelp);
|
||||
extern UniValue getblockheader(const UniValue& params, bool fHelp);
|
||||
extern UniValue getblock(const UniValue& params, bool fHelp);
|
||||
|
||||
27
src/txdb.cpp
27
src/txdb.cpp
@@ -22,6 +22,7 @@ static const char DB_COINS = 'c';
|
||||
static const char DB_BLOCK_FILES = 'f';
|
||||
static const char DB_TXINDEX = 't';
|
||||
static const char DB_ADDRESSINDEX = 'a';
|
||||
static const char DB_TIMESTAMPINDEX = 's';
|
||||
static const char DB_BLOCK_INDEX = 'b';
|
||||
|
||||
static const char DB_BEST_BLOCK = 'B';
|
||||
@@ -196,6 +197,32 @@ bool CBlockTreeDB::ReadAddressIndex(uint160 addressHash, int type, std::vector<s
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBlockTreeDB::WriteTimestampIndex(const CTimestampIndexKey ×tampIndex) {
|
||||
CDBBatch batch(&GetObfuscateKey());
|
||||
batch.Write(make_pair(DB_TIMESTAMPINDEX, timestampIndex), NULL);
|
||||
return WriteBatch(batch);
|
||||
}
|
||||
|
||||
bool CBlockTreeDB::ReadTimestampIndex(const unsigned int &high, const unsigned int &low, std::vector<uint256> &hashes) {
|
||||
|
||||
boost::scoped_ptr<CDBIterator> pcursor(NewIterator());
|
||||
|
||||
pcursor->Seek(make_pair(DB_TIMESTAMPINDEX, CTimestampIndexIteratorKey(low)));
|
||||
|
||||
while (pcursor->Valid()) {
|
||||
boost::this_thread::interruption_point();
|
||||
std::pair<char, CTimestampIndexKey> key;
|
||||
if (pcursor->GetKey(key) && key.first == DB_TIMESTAMPINDEX && key.second.timestamp <= high) {
|
||||
hashes.push_back(key.second.blockHash);
|
||||
pcursor->Next();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
|
||||
return Write(std::make_pair(DB_FLAG, name), fValue ? '1' : '0');
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ class CBlockIndex;
|
||||
struct CDiskTxPos;
|
||||
struct CAddressIndexKey;
|
||||
struct CAddressIndexIteratorKey;
|
||||
struct CTimestampIndexKey;
|
||||
struct CTimestampIndexIteratorKey;
|
||||
class uint256;
|
||||
|
||||
//! -dbcache default (MiB)
|
||||
@@ -61,6 +63,8 @@ public:
|
||||
bool WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> > &list);
|
||||
bool WriteAddressIndex(const std::vector<std::pair<CAddressIndexKey, CAmount> > &vect);
|
||||
bool ReadAddressIndex(uint160 addressHash, int type, std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex);
|
||||
bool WriteTimestampIndex(const CTimestampIndexKey ×tampIndex);
|
||||
bool ReadTimestampIndex(const unsigned int &high, const unsigned int &low, std::vector<uint256> &vect);
|
||||
bool WriteFlag(const std::string &name, bool fValue);
|
||||
bool ReadFlag(const std::string &name, bool &fValue);
|
||||
bool LoadBlockIndexGuts();
|
||||
|
||||
Reference in New Issue
Block a user