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:
commit
244922d527
|
@ -199,6 +199,7 @@ BITCOIN_CORE_H = \
|
||||||
sync.h \
|
sync.h \
|
||||||
threadsafety.h \
|
threadsafety.h \
|
||||||
timedata.h \
|
timedata.h \
|
||||||
|
timestampindex.h \
|
||||||
tinyformat.h \
|
tinyformat.h \
|
||||||
torcontrol.h \
|
torcontrol.h \
|
||||||
transaction_builder.h \
|
transaction_builder.h \
|
||||||
|
|
26
src/main.cpp
26
src/main.cpp
|
@ -70,6 +70,7 @@ bool fTxIndex = false;
|
||||||
bool fInsightExplorer = false; // insightexplorer
|
bool fInsightExplorer = false; // insightexplorer
|
||||||
bool fAddressIndex = false; // insightexplorer
|
bool fAddressIndex = false; // insightexplorer
|
||||||
bool fSpentIndex = false; // insightexplorer
|
bool fSpentIndex = false; // insightexplorer
|
||||||
|
bool fTimestampIndex = false; // insightexplorer
|
||||||
bool fHavePruned = false;
|
bool fHavePruned = false;
|
||||||
bool fPruneMode = false;
|
bool fPruneMode = false;
|
||||||
bool fIsBareMultisigStd = true;
|
bool fIsBareMultisigStd = true;
|
||||||
|
@ -2801,7 +2802,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||||
if (!pblocktree->WriteTxIndex(vPos))
|
if (!pblocktree->WriteTxIndex(vPos))
|
||||||
return AbortNode(state, "Failed to write transaction index");
|
return AbortNode(state, "Failed to write transaction index");
|
||||||
|
|
||||||
// insightexplorer
|
// START insightexplorer
|
||||||
if (fAddressIndex) {
|
if (fAddressIndex) {
|
||||||
if (!pblocktree->WriteAddressIndex(addressIndex)) {
|
if (!pblocktree->WriteAddressIndex(addressIndex)) {
|
||||||
return AbortNode(state, "Failed to write address index");
|
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");
|
return AbortNode(state, "Failed to write address unspent index");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// insightexplorer
|
|
||||||
if (fSpentIndex) {
|
if (fSpentIndex) {
|
||||||
if (!pblocktree->UpdateSpentIndex(spentIndex)) {
|
if (!pblocktree->UpdateSpentIndex(spentIndex)) {
|
||||||
return AbortNode(state, "Failed to write spent index");
|
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
|
// add this block to the view's block chain
|
||||||
view.SetBestBlock(pindex->GetBlockHash());
|
view.SetBestBlock(pindex->GetBlockHash());
|
||||||
|
@ -4715,6 +4736,7 @@ bool InitBlockIndex() {
|
||||||
pblocktree->WriteFlag("insightexplorer", fInsightExplorer);
|
pblocktree->WriteFlag("insightexplorer", fInsightExplorer);
|
||||||
fAddressIndex = fInsightExplorer;
|
fAddressIndex = fInsightExplorer;
|
||||||
fSpentIndex = fInsightExplorer;
|
fSpentIndex = fInsightExplorer;
|
||||||
|
fTimestampIndex = fInsightExplorer;
|
||||||
|
|
||||||
LogPrintf("Initializing databases...\n");
|
LogPrintf("Initializing databases...\n");
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
#include "addressindex.h"
|
#include "addressindex.h"
|
||||||
#include "spentindex.h"
|
#include "spentindex.h"
|
||||||
|
#include "timestampindex.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
|
|
@ -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
|
52
src/txdb.cpp
52
src/txdb.cpp
|
@ -39,6 +39,8 @@ static const char DB_LAST_BLOCK = 'l';
|
||||||
static const char DB_ADDRESSINDEX = 'd';
|
static const char DB_ADDRESSINDEX = 'd';
|
||||||
static const char DB_ADDRESSUNSPENTINDEX = 'u';
|
static const char DB_ADDRESSUNSPENTINDEX = 'u';
|
||||||
static const char DB_SPENTINDEX = 'p';
|
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) {
|
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);
|
return WriteBatch(batch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CBlockTreeDB::WriteTimestampIndex(const CTimestampIndexKey ×tampIndex) {
|
||||||
|
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 <imestamp)
|
||||||
|
{
|
||||||
|
CTimestampBlockIndexValue(lts);
|
||||||
|
if (!Read(std::make_pair(DB_BLOCKHASHINDEX, hash), lts))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ltimestamp = lts.ltimestamp;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// END insightexplorer
|
// END insightexplorer
|
||||||
|
|
||||||
bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
|
bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
|
||||||
|
|
10
src/txdb.h
10
src/txdb.h
|
@ -26,6 +26,10 @@ struct CAddressIndexIteratorKey;
|
||||||
struct CAddressIndexIteratorHeightKey;
|
struct CAddressIndexIteratorHeightKey;
|
||||||
struct CSpentIndexKey;
|
struct CSpentIndexKey;
|
||||||
struct CSpentIndexValue;
|
struct CSpentIndexValue;
|
||||||
|
struct CTimestampIndexKey;
|
||||||
|
struct CTimestampIndexIteratorKey;
|
||||||
|
struct CTimestampBlockIndexKey;
|
||||||
|
struct CTimestampBlockIndexValue;
|
||||||
|
|
||||||
typedef std::pair<CAddressUnspentKey, CAddressUnspentValue> CAddressUnspentDbEntry;
|
typedef std::pair<CAddressUnspentKey, CAddressUnspentValue> CAddressUnspentDbEntry;
|
||||||
typedef std::pair<CAddressIndexKey, CAmount> CAddressIndexDbEntry;
|
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 ReadAddressIndex(uint160 addressHash, int type, std::vector<CAddressIndexDbEntry> &addressIndex, int start = 0, int end = 0);
|
||||||
bool ReadSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value);
|
bool ReadSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value);
|
||||||
bool UpdateSpentIndex(const std::vector<CSpentIndexDbEntry> &vect);
|
bool UpdateSpentIndex(const std::vector<CSpentIndexDbEntry> &vect);
|
||||||
|
bool WriteTimestampIndex(const CTimestampIndexKey ×tampIndex);
|
||||||
|
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
|
// END insightexplorer
|
||||||
|
|
||||||
bool WriteFlag(const std::string &name, bool fValue);
|
bool WriteFlag(const std::string &name, bool fValue);
|
||||||
|
|
Loading…
Reference in New Issue