Auto merge of #3857 - LarryRuane:3708-timestampindex, r=bitcartel

add TimestampIndex changes needed for bitcore block explorer

Addresses #3708, follow-on to #3849, no tests yet. This is the third of 3 indices that we're adding.
This commit is contained in:
Homu 2019-04-26 11:05:25 -07:00
commit 244922d527
6 changed files with 219 additions and 2 deletions

View File

@ -199,6 +199,7 @@ BITCOIN_CORE_H = \
sync.h \
threadsafety.h \
timedata.h \
timestampindex.h \
tinyformat.h \
torcontrol.h \
transaction_builder.h \

View File

@ -70,6 +70,7 @@ bool fTxIndex = false;
bool fInsightExplorer = false; // insightexplorer
bool fAddressIndex = false; // insightexplorer
bool fSpentIndex = false; // insightexplorer
bool fTimestampIndex = false; // insightexplorer
bool fHavePruned = false;
bool fPruneMode = false;
bool fIsBareMultisigStd = true;
@ -2801,7 +2802,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
if (!pblocktree->WriteTxIndex(vPos))
return AbortNode(state, "Failed to write transaction index");
// insightexplorer
// START insightexplorer
if (fAddressIndex) {
if (!pblocktree->WriteAddressIndex(addressIndex)) {
return AbortNode(state, "Failed to write address index");
@ -2810,12 +2811,32 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
return AbortNode(state, "Failed to write address unspent index");
}
}
// insightexplorer
if (fSpentIndex) {
if (!pblocktree->UpdateSpentIndex(spentIndex)) {
return AbortNode(state, "Failed to write spent index");
}
}
if (fTimestampIndex) {
unsigned int logicalTS = pindex->nTime;
unsigned int prevLogicalTS = 0;
// retrieve logical timestamp of the previous block
if (pindex->pprev)
if (!pblocktree->ReadTimestampBlockIndex(pindex->pprev->GetBlockHash(), prevLogicalTS))
LogPrintf("%s: Failed to read previous block's logical timestamp\n", __func__);
if (logicalTS <= prevLogicalTS) {
logicalTS = prevLogicalTS + 1;
LogPrintf("%s: Previous logical timestamp is newer Actual[%d] prevLogical[%d] Logical[%d]\n", __func__, pindex->nTime, prevLogicalTS, logicalTS);
}
if (!pblocktree->WriteTimestampIndex(CTimestampIndexKey(logicalTS, pindex->GetBlockHash())))
return AbortNode(state, "Failed to write timestamp index");
if (!pblocktree->WriteTimestampBlockIndex(CTimestampBlockIndexKey(pindex->GetBlockHash()), CTimestampBlockIndexValue(logicalTS)))
return AbortNode(state, "Failed to write blockhash index");
}
// END insightexplorer
// add this block to the view's block chain
view.SetBestBlock(pindex->GetBlockHash());
@ -4715,6 +4736,7 @@ bool InitBlockIndex() {
pblocktree->WriteFlag("insightexplorer", fInsightExplorer);
fAddressIndex = fInsightExplorer;
fSpentIndex = fInsightExplorer;
fTimestampIndex = fInsightExplorer;
LogPrintf("Initializing databases...\n");

View File

@ -28,6 +28,7 @@
#include "uint256.h"
#include "addressindex.h"
#include "spentindex.h"
#include "timestampindex.h"
#include <algorithm>
#include <exception>

131
src/timestampindex.h Normal file
View File

@ -0,0 +1,131 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_TIMESTAMPINDEX_H
#define BITCOIN_TIMESTAMPINDEX_H
#include "uint256.h"
struct CTimestampIndexIteratorKey {
unsigned int timestamp;
size_t GetSerializeSize(int nType, int nVersion) const {
return 4;
}
template<typename Stream>
void Serialize(Stream& s) const {
ser_writedata32be(s, timestamp);
}
template<typename Stream>
void Unserialize(Stream& s) {
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) const {
ser_writedata32be(s, timestamp);
blockHash.Serialize(s);
}
template<typename Stream>
void Unserialize(Stream& s) {
timestamp = ser_readdata32be(s);
blockHash.Unserialize(s);
}
CTimestampIndexKey(unsigned int time, uint256 hash) {
timestamp = time;
blockHash = hash;
}
CTimestampIndexKey() {
SetNull();
}
void SetNull() {
timestamp = 0;
blockHash.SetNull();
}
};
struct CTimestampBlockIndexKey {
uint256 blockHash;
size_t GetSerializeSize(int nType, int nVersion) const {
return 32;
}
template<typename Stream>
void Serialize(Stream& s) const {
blockHash.Serialize(s);
}
template<typename Stream>
void Unserialize(Stream& s) {
blockHash.Unserialize(s);
}
CTimestampBlockIndexKey(uint256 hash) {
blockHash = hash;
}
CTimestampBlockIndexKey() {
SetNull();
}
void SetNull() {
blockHash.SetNull();
}
};
struct CTimestampBlockIndexValue {
unsigned int ltimestamp;
size_t GetSerializeSize(int nType, int nVersion) const {
return 4;
}
template<typename Stream>
void Serialize(Stream& s) const {
ser_writedata32be(s, ltimestamp);
}
template<typename Stream>
void Unserialize(Stream& s) {
ltimestamp = ser_readdata32be(s);
}
CTimestampBlockIndexValue (unsigned int time) {
ltimestamp = time;
}
CTimestampBlockIndexValue() {
SetNull();
}
void SetNull() {
ltimestamp = 0;
}
};
#endif // BITCOIN_TIMESTAMPINDEX_H

View File

@ -39,6 +39,8 @@ static const char DB_LAST_BLOCK = 'l';
static const char DB_ADDRESSINDEX = 'd';
static const char DB_ADDRESSUNSPENTINDEX = 'u';
static const char DB_SPENTINDEX = 'p';
static const char DB_TIMESTAMPINDEX = 'T';
static const char DB_BLOCKHASHINDEX = 'h';
CCoinsViewDB::CCoinsViewDB(std::string dbName, size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / dbName, nCacheSize, fMemory, fWipe) {
}
@ -390,6 +392,56 @@ bool CBlockTreeDB::UpdateSpentIndex(const std::vector<CSpentIndexDbEntry> &vect)
}
return WriteBatch(batch);
}
bool CBlockTreeDB::WriteTimestampIndex(const CTimestampIndexKey &timestampIndex) {
CDBBatch batch(*this);
batch.Write(make_pair(DB_TIMESTAMPINDEX, timestampIndex), 0);
return WriteBatch(batch);
}
bool CBlockTreeDB::ReadTimestampIndex(const unsigned int &high, const unsigned int &low,
const bool fActiveOnly, std::vector<std::pair<uint256, unsigned int> > &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)) {
break;
}
if (fActiveOnly) {
CBlockIndex* pblockindex = mapBlockIndex[key.second.blockHash];
if (chainActive.Contains(pblockindex)) {
hashes.push_back(std::make_pair(key.second.blockHash, key.second.timestamp));
}
} else {
hashes.push_back(std::make_pair(key.second.blockHash, key.second.timestamp));
}
pcursor->Next();
}
return true;
}
bool CBlockTreeDB::WriteTimestampBlockIndex(const CTimestampBlockIndexKey &blockhashIndex,
const CTimestampBlockIndexValue &logicalts)
{
CDBBatch batch(*this);
batch.Write(make_pair(DB_BLOCKHASHINDEX, blockhashIndex), logicalts);
return WriteBatch(batch);
}
bool CBlockTreeDB::ReadTimestampBlockIndex(const uint256 &hash, unsigned int &ltimestamp)
{
CTimestampBlockIndexValue(lts);
if (!Read(std::make_pair(DB_BLOCKHASHINDEX, hash), lts))
return false;
ltimestamp = lts.ltimestamp;
return true;
}
// END insightexplorer
bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {

View File

@ -26,6 +26,10 @@ struct CAddressIndexIteratorKey;
struct CAddressIndexIteratorHeightKey;
struct CSpentIndexKey;
struct CSpentIndexValue;
struct CTimestampIndexKey;
struct CTimestampIndexIteratorKey;
struct CTimestampBlockIndexKey;
struct CTimestampBlockIndexValue;
typedef std::pair<CAddressUnspentKey, CAddressUnspentValue> CAddressUnspentDbEntry;
typedef std::pair<CAddressIndexKey, CAmount> CAddressIndexDbEntry;
@ -94,6 +98,12 @@ public:
bool ReadAddressIndex(uint160 addressHash, int type, std::vector<CAddressIndexDbEntry> &addressIndex, int start = 0, int end = 0);
bool ReadSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value);
bool UpdateSpentIndex(const std::vector<CSpentIndexDbEntry> &vect);
bool WriteTimestampIndex(const CTimestampIndexKey &timestampIndex);
bool ReadTimestampIndex(const unsigned int &high, const unsigned int &low,
const bool fActiveOnly, std::vector<std::pair<uint256, unsigned int> > &vect);
bool WriteTimestampBlockIndex(const CTimestampBlockIndexKey &blockhashIndex,
const CTimestampBlockIndexValue &logicalts);
bool ReadTimestampBlockIndex(const uint256 &hash, unsigned int &logicalTS);
// END insightexplorer
bool WriteFlag(const std::string &name, bool fValue);