|
|
@ -25,6 +25,7 @@ |
|
|
|
#include "tinyformat.h" |
|
|
|
#include "txmempool.h" |
|
|
|
#include "uint256.h" |
|
|
|
#include "spentindex.h" |
|
|
|
|
|
|
|
#include <algorithm> |
|
|
|
#include <exception> |
|
|
@ -92,6 +93,12 @@ static const unsigned int DATABASE_WRITE_INTERVAL = 60 * 60; |
|
|
|
static const unsigned int DATABASE_FLUSH_INTERVAL = 24 * 60 * 60; |
|
|
|
/** Maximum length of reject messages. */ |
|
|
|
static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111; |
|
|
|
/** Address Indexing. */ |
|
|
|
static const bool DEFAULT_ADDRESSINDEX = false; |
|
|
|
static const bool DEFAULT_TIMESTAMPINDEX = false; |
|
|
|
static const bool DEFAULT_SPENTINDEX = false; |
|
|
|
static const unsigned int DEFAULT_DB_MAX_OPEN_FILES = 1000; |
|
|
|
static const bool DEFAULT_DB_COMPRESSION = true; |
|
|
|
|
|
|
|
// Sanity check the magic numbers when we change them
|
|
|
|
BOOST_STATIC_ASSERT(DEFAULT_BLOCK_MAX_SIZE <= MAX_BLOCK_SIZE); |
|
|
@ -259,6 +266,339 @@ 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 CTimestampBlockIndexKey { |
|
|
|
uint256 blockHash; |
|
|
|
|
|
|
|
size_t GetSerializeSize(int nType, int nVersion) const { |
|
|
|
return 32; |
|
|
|
} |
|
|
|
|
|
|
|
template<typename Stream> |
|
|
|
void Serialize(Stream& s, int nType, int nVersion) const { |
|
|
|
blockHash.Serialize(s, nType, nVersion); |
|
|
|
} |
|
|
|
|
|
|
|
template<typename Stream> |
|
|
|
void Unserialize(Stream& s, int nType, int nVersion) { |
|
|
|
blockHash.Unserialize(s, nType, nVersion); |
|
|
|
} |
|
|
|
|
|
|
|
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, int nType, int nVersion) const { |
|
|
|
ser_writedata32be(s, ltimestamp); |
|
|
|
} |
|
|
|
|
|
|
|
template<typename Stream> |
|
|
|
void Unserialize(Stream& s, int nType, int nVersion) { |
|
|
|
ltimestamp = ser_readdata32be(s); |
|
|
|
} |
|
|
|
|
|
|
|
CTimestampBlockIndexValue (unsigned int time) { |
|
|
|
ltimestamp = time; |
|
|
|
} |
|
|
|
|
|
|
|
CTimestampBlockIndexValue() { |
|
|
|
SetNull(); |
|
|
|
} |
|
|
|
|
|
|
|
void SetNull() { |
|
|
|
ltimestamp = 0; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
struct CAddressUnspentKey { |
|
|
|
unsigned int type; |
|
|
|
uint160 hashBytes; |
|
|
|
uint256 txhash; |
|
|
|
size_t index; |
|
|
|
|
|
|
|
size_t GetSerializeSize(int nType, int nVersion) const { |
|
|
|
return 57; |
|
|
|
} |
|
|
|
template<typename Stream> |
|
|
|
void Serialize(Stream& s, int nType, int nVersion) const { |
|
|
|
ser_writedata8(s, type); |
|
|
|
hashBytes.Serialize(s, nType, nVersion); |
|
|
|
txhash.Serialize(s, nType, nVersion); |
|
|
|
ser_writedata32(s, index); |
|
|
|
} |
|
|
|
template<typename Stream> |
|
|
|
void Unserialize(Stream& s, int nType, int nVersion) { |
|
|
|
type = ser_readdata8(s); |
|
|
|
hashBytes.Unserialize(s, nType, nVersion); |
|
|
|
txhash.Unserialize(s, nType, nVersion); |
|
|
|
index = ser_readdata32(s); |
|
|
|
} |
|
|
|
|
|
|
|
CAddressUnspentKey(unsigned int addressType, uint160 addressHash, uint256 txid, size_t indexValue) { |
|
|
|
type = addressType; |
|
|
|
hashBytes = addressHash; |
|
|
|
txhash = txid; |
|
|
|
index = indexValue; |
|
|
|
} |
|
|
|
|
|
|
|
CAddressUnspentKey() { |
|
|
|
SetNull(); |
|
|
|
} |
|
|
|
|
|
|
|
void SetNull() { |
|
|
|
type = 0; |
|
|
|
hashBytes.SetNull(); |
|
|
|
txhash.SetNull(); |
|
|
|
index = 0; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
struct CAddressUnspentValue { |
|
|
|
CAmount satoshis; |
|
|
|
CScript script; |
|
|
|
int blockHeight; |
|
|
|
|
|
|
|
ADD_SERIALIZE_METHODS; |
|
|
|
|
|
|
|
template <typename Stream, typename Operation> |
|
|
|
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { |
|
|
|
READWRITE(satoshis); |
|
|
|
READWRITE(script); |
|
|
|
READWRITE(blockHeight); |
|
|
|
} |
|
|
|
|
|
|
|
CAddressUnspentValue(CAmount sats, CScript scriptPubKey, int height) { |
|
|
|
satoshis = sats; |
|
|
|
script = scriptPubKey; |
|
|
|
blockHeight = height; |
|
|
|
} |
|
|
|
|
|
|
|
CAddressUnspentValue() { |
|
|
|
SetNull(); |
|
|
|
} |
|
|
|
|
|
|
|
void SetNull() { |
|
|
|
satoshis = -1; |
|
|
|
script.clear(); |
|
|
|
blockHeight = 0; |
|
|
|
} |
|
|
|
|
|
|
|
bool IsNull() const { |
|
|
|
return (satoshis == -1); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
struct CAddressIndexKey { |
|
|
|
unsigned int type; |
|
|
|
uint160 hashBytes; |
|
|
|
int blockHeight; |
|
|
|
unsigned int txindex; |
|
|
|
uint256 txhash; |
|
|
|
size_t index; |
|
|
|
bool spending; |
|
|
|
|
|
|
|
size_t GetSerializeSize(int nType, int nVersion) const { |
|
|
|
return 66; |
|
|
|
} |
|
|
|
template<typename Stream> |
|
|
|
void Serialize(Stream& s, int nType, int nVersion) const { |
|
|
|
ser_writedata8(s, type); |
|
|
|
hashBytes.Serialize(s, nType, nVersion); |
|
|
|
// Heights are stored big-endian for key sorting in LevelDB
|
|
|
|
ser_writedata32be(s, blockHeight); |
|
|
|
ser_writedata32be(s, txindex); |
|
|
|
txhash.Serialize(s, nType, nVersion); |
|
|
|
ser_writedata32(s, index); |
|
|
|
char f = spending; |
|
|
|
ser_writedata8(s, f); |
|
|
|
} |
|
|
|
template<typename Stream> |
|
|
|
void Unserialize(Stream& s, int nType, int nVersion) { |
|
|
|
type = ser_readdata8(s); |
|
|
|
hashBytes.Unserialize(s, nType, nVersion); |
|
|
|
blockHeight = ser_readdata32be(s); |
|
|
|
txindex = ser_readdata32be(s); |
|
|
|
txhash.Unserialize(s, nType, nVersion); |
|
|
|
index = ser_readdata32(s); |
|
|
|
char f = ser_readdata8(s); |
|
|
|
spending = f; |
|
|
|
} |
|
|
|
|
|
|
|
CAddressIndexKey(unsigned int addressType, uint160 addressHash, int height, int blockindex, |
|
|
|
uint256 txid, size_t indexValue, bool isSpending) { |
|
|
|
type = addressType; |
|
|
|
hashBytes = addressHash; |
|
|
|
blockHeight = height; |
|
|
|
txindex = blockindex; |
|
|
|
txhash = txid; |
|
|
|
index = indexValue; |
|
|
|
spending = isSpending; |
|
|
|
} |
|
|
|
|
|
|
|
CAddressIndexKey() { |
|
|
|
SetNull(); |
|
|
|
} |
|
|
|
|
|
|
|
void SetNull() { |
|
|
|
type = 0; |
|
|
|
hashBytes.SetNull(); |
|
|
|
blockHeight = 0; |
|
|
|
txindex = 0; |
|
|
|
txhash.SetNull(); |
|
|
|
index = 0; |
|
|
|
spending = false; |
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
struct CAddressIndexIteratorKey { |
|
|
|
unsigned int type; |
|
|
|
uint160 hashBytes; |
|
|
|
|
|
|
|
size_t GetSerializeSize(int nType, int nVersion) const { |
|
|
|
return 21; |
|
|
|
} |
|
|
|
template<typename Stream> |
|
|
|
void Serialize(Stream& s, int nType, int nVersion) const { |
|
|
|
ser_writedata8(s, type); |
|
|
|
hashBytes.Serialize(s, nType, nVersion); |
|
|
|
} |
|
|
|
template<typename Stream> |
|
|
|
void Unserialize(Stream& s, int nType, int nVersion) { |
|
|
|
type = ser_readdata8(s); |
|
|
|
hashBytes.Unserialize(s, nType, nVersion); |
|
|
|
} |
|
|
|
|
|
|
|
CAddressIndexIteratorKey(unsigned int addressType, uint160 addressHash) { |
|
|
|
type = addressType; |
|
|
|
hashBytes = addressHash; |
|
|
|
} |
|
|
|
|
|
|
|
CAddressIndexIteratorKey() { |
|
|
|
SetNull(); |
|
|
|
} |
|
|
|
|
|
|
|
void SetNull() { |
|
|
|
type = 0; |
|
|
|
hashBytes.SetNull(); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
struct CAddressIndexIteratorHeightKey { |
|
|
|
unsigned int type; |
|
|
|
uint160 hashBytes; |
|
|
|
int blockHeight; |
|
|
|
|
|
|
|
size_t GetSerializeSize(int nType, int nVersion) const { |
|
|
|
return 25; |
|
|
|
} |
|
|
|
template<typename Stream> |
|
|
|
void Serialize(Stream& s, int nType, int nVersion) const { |
|
|
|
ser_writedata8(s, type); |
|
|
|
hashBytes.Serialize(s, nType, nVersion); |
|
|
|
ser_writedata32be(s, blockHeight); |
|
|
|
} |
|
|
|
template<typename Stream> |
|
|
|
void Unserialize(Stream& s, int nType, int nVersion) { |
|
|
|
type = ser_readdata8(s); |
|
|
|
hashBytes.Unserialize(s, nType, nVersion); |
|
|
|
blockHeight = ser_readdata32be(s); |
|
|
|
} |
|
|
|
|
|
|
|
CAddressIndexIteratorHeightKey(unsigned int addressType, uint160 addressHash, int height) { |
|
|
|
type = addressType; |
|
|
|
hashBytes = addressHash; |
|
|
|
blockHeight = height; |
|
|
|
} |
|
|
|
|
|
|
|
CAddressIndexIteratorHeightKey() { |
|
|
|
SetNull(); |
|
|
|
} |
|
|
|
|
|
|
|
void SetNull() { |
|
|
|
type = 0; |
|
|
|
hashBytes.SetNull(); |
|
|
|
blockHeight = 0; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
struct CDiskTxPos : public CDiskBlockPos |
|
|
|
{ |
|
|
|
unsigned int nTxOffset; // after header
|
|
|
@ -393,6 +733,13 @@ public: |
|
|
|
ScriptError GetScriptError() const { return error; } |
|
|
|
}; |
|
|
|
|
|
|
|
bool GetTimestampIndex(const unsigned int &high, const unsigned int &low, const bool fActiveOnly, std::vector<std::pair<uint256, unsigned int> > &hashes); |
|
|
|
bool GetSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value); |
|
|
|
bool GetAddressIndex(uint160 addressHash, int type, |
|
|
|
std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex, |
|
|
|
int start = 0, int end = 0); |
|
|
|
bool GetAddressUnspent(uint160 addressHash, int type, |
|
|
|
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &unspentOutputs); |
|
|
|
|
|
|
|
/** Functions for disk access for blocks */ |
|
|
|
bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart); |
|
|
|