Skip to content

Commit

Permalink
Merge pull request dashpay#5577 from kwvg/bitcore_idx
Browse files Browse the repository at this point in the history
refactor: cleanup {address,spent}index, remove platform-specific types, split out timestamp index
  • Loading branch information
PastaPastaPasta authored Sep 27, 2023
2 parents 7bff85e + 93ddd3f commit 2958aac
Show file tree
Hide file tree
Showing 14 changed files with 594 additions and 628 deletions.
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ BITCOIN_CORE_H = \
support/events.h \
support/lockedpool.h \
sync.h \
timestampindex.h \
threadsafety.h \
threadinterrupt.h \
timedata.h \
Expand Down Expand Up @@ -385,6 +386,7 @@ libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CP
libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libbitcoin_server_a_SOURCES = \
addrdb.cpp \
addressindex.cpp \
addrman.cpp \
banman.cpp \
batchedlogger.cpp \
Expand Down
43 changes: 43 additions & 0 deletions src/addressindex.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (c) 2016 BitPay, Inc.
// Copyright (c) 2023 The Dash Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <addressindex.h>

#include <key_io.h>
#include <hash.h>
#include <script/script.h>

template <typename T1>
inline std::vector<uint8_t> TrimScriptP2PKH(const T1& input) {
return std::vector<uint8_t>(input.begin() + 3, input.begin() + 23);
};

template <typename T1>
inline std::vector<uint8_t> TrimScriptP2SH(const T1& input) {
return std::vector<uint8_t>(input.begin() + 2, input.begin() + 22);
};

template <typename T1>
inline std::vector<uint8_t> TrimScriptP2PK(const T1& input) {
return std::vector<uint8_t>(input.begin() + 1, input.end() - 1);
};

bool AddressBytesFromScript(const CScript& script, AddressType& address_type, uint160& address_bytes) {
if (script.IsPayToScriptHash()) {
address_type = AddressType::P2SH;
address_bytes = uint160(TrimScriptP2SH(script));
} else if (script.IsPayToPublicKeyHash()) {
address_type = AddressType::P2PK_OR_P2PKH;
address_bytes = uint160(TrimScriptP2PKH(script));
} else if (script.IsPayToPublicKey()) {
address_type = AddressType::P2PK_OR_P2PKH;
address_bytes = Hash160(TrimScriptP2PK(script));
} else {
address_type = AddressType::UNKNOWN;
address_bytes.SetNull();
return false;
}
return true;
}
245 changes: 190 additions & 55 deletions src/addressindex.h
Original file line number Diff line number Diff line change
@@ -1,84 +1,219 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 The Bitcoin Core developers
// Copyright (c) 2016 BitPay, Inc.
// Copyright (c) 2023 The Dash Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_ADDRESSINDEX_H
#define BITCOIN_ADDRESSINDEX_H

#include <uint256.h>
#include <amount.h>
#include <serialize.h>
#include <uint256.h>
#include <util/underlying.h>

#include <chrono>
#include <tuple>

class CScript;

enum class AddressType : uint8_t {
P2PK_OR_P2PKH = 1,
P2SH = 2,

UNKNOWN = 0
};
template<> struct is_serializable_enum<AddressType> : std::true_type {};

struct CMempoolAddressDelta
{
std::chrono::seconds time;
CAmount amount;
uint256 prevhash;
unsigned int prevout;
public:
std::chrono::seconds m_time;
CAmount m_amount;
uint256 m_prev_hash;
uint32_t m_prev_out{0};

CMempoolAddressDelta(std::chrono::seconds t, CAmount a, uint256 hash, unsigned int out) {
time = t;
amount = a;
prevhash = hash;
prevout = out;
}
public:
CMempoolAddressDelta(std::chrono::seconds time, CAmount amount, uint256 prev_hash, uint32_t prev_out) :
m_time{time}, m_amount{amount}, m_prev_hash{prev_hash}, m_prev_out{prev_out} {}

CMempoolAddressDelta(std::chrono::seconds t, CAmount a) {
time = t;
amount = a;
prevhash.SetNull();
prevout = 0;
}
CMempoolAddressDelta(std::chrono::seconds time, CAmount amount) :
m_time{time}, m_amount{amount} {}
};

struct CMempoolAddressDeltaKey
{
int type;
uint160 addressBytes;
uint256 txhash;
unsigned int index;
int spending;

CMempoolAddressDeltaKey(int addressType, uint160 addressHash, uint256 hash, unsigned int i, int s) {
type = addressType;
addressBytes = addressHash;
txhash = hash;
index = i;
spending = s;
}

CMempoolAddressDeltaKey(int addressType, uint160 addressHash) {
type = addressType;
addressBytes = addressHash;
txhash.SetNull();
index = 0;
spending = 0;
}
public:
AddressType m_address_type{AddressType::UNKNOWN};
uint160 m_address_bytes;
uint256 m_tx_hash;
uint32_t m_tx_index{0};
bool m_tx_spent{false};

public:
CMempoolAddressDeltaKey(AddressType address_type, uint160 address_bytes, uint256 tx_hash, uint32_t tx_index, bool tx_spent) :
m_address_type{address_type},
m_address_bytes{address_bytes},
m_tx_hash{tx_hash},
m_tx_index{tx_index},
m_tx_spent{tx_spent} {};

CMempoolAddressDeltaKey(AddressType address_type, uint160 address_bytes) :
m_address_type{address_type},
m_address_bytes{address_bytes} {};
};

struct CMempoolAddressDeltaKeyCompare
{
bool operator()(const CMempoolAddressDeltaKey& a, const CMempoolAddressDeltaKey& b) const {
if (a.type == b.type) {
if (a.addressBytes == b.addressBytes) {
if (a.txhash == b.txhash) {
if (a.index == b.index) {
return a.spending < b.spending;
} else {
return a.index < b.index;
}
} else {
return a.txhash < b.txhash;
}
} else {
return a.addressBytes < b.addressBytes;
}
} else {
return a.type < b.type;
}
auto to_tuple = [](const CMempoolAddressDeltaKey& obj) {
return std::tie(obj.m_address_type, obj.m_address_bytes, obj.m_tx_hash, obj.m_tx_index, obj.m_tx_spent);
};
return to_tuple(a) < to_tuple(b);
}
};

struct CAddressIndexKey {
public:
AddressType m_address_type{AddressType::UNKNOWN};
uint160 m_address_bytes;
int32_t m_block_height{0};
uint32_t m_block_tx_pos{0};
uint256 m_tx_hash;
uint32_t m_tx_index{0};
bool m_tx_spent{false};

public:
CAddressIndexKey() {
SetNull();
}

CAddressIndexKey(AddressType address_type, uint160 address_bytes, int32_t block_height, uint32_t block_tx_pos, uint256 tx_hash,
uint32_t tx_index, bool tx_spent) :
m_address_type{address_type},
m_address_bytes{address_bytes},
m_block_height{block_height},
m_block_tx_pos{block_tx_pos},
m_tx_hash{tx_hash},
m_tx_index{tx_index},
m_tx_spent{tx_spent} {};

void SetNull() {
m_address_type = AddressType::UNKNOWN;
m_address_bytes.SetNull();
m_block_height = 0;
m_block_tx_pos = 0;
m_tx_hash.SetNull();
m_tx_index = 0;
m_tx_spent = false;
}

public:
size_t GetSerializeSize(int nType, int nVersion) const {
return 66;
}

template<typename Stream>
void Serialize(Stream& s) const {
ser_writedata8(s, ToUnderlying(m_address_type));
m_address_bytes.Serialize(s);
// Heights are stored big-endian for key sorting in LevelDB
ser_writedata32be(s, m_block_height);
ser_writedata32be(s, m_block_tx_pos);
m_tx_hash.Serialize(s);
ser_writedata32(s, m_tx_index);
ser_writedata8(s, static_cast<uint8_t>(m_tx_spent));
}

template<typename Stream>
void Unserialize(Stream& s) {
m_address_type = static_cast<AddressType>(ser_readdata8(s));
m_address_bytes.Unserialize(s);
m_block_height = ser_readdata32be(s);
m_block_tx_pos = ser_readdata32be(s);
m_tx_hash.Unserialize(s);
m_tx_index = ser_readdata32(s);
m_tx_spent = static_cast<bool>(ser_readdata8(s));
}
};

struct CAddressIndexIteratorKey {
public:
AddressType m_address_type{AddressType::UNKNOWN};
uint160 m_address_bytes;

public:
CAddressIndexIteratorKey() {
SetNull();
}

CAddressIndexIteratorKey(AddressType address_type, uint160 address_bytes) :
m_address_type{address_type}, m_address_bytes{address_bytes} {};

void SetNull() {
m_address_type = AddressType::UNKNOWN;
m_address_bytes.SetNull();
}

public:
size_t GetSerializeSize(int nType, int nVersion) const {
return 21;
}

template<typename Stream>
void Serialize(Stream& s) const {
ser_writedata8(s, ToUnderlying(m_address_type));
m_address_bytes.Serialize(s);
}

template<typename Stream>
void Unserialize(Stream& s) {
m_address_type = static_cast<AddressType>(ser_readdata8(s));
m_address_bytes.Unserialize(s);
}
};

struct CAddressIndexIteratorHeightKey {
public:
AddressType m_address_type{AddressType::UNKNOWN};
uint160 m_address_bytes;
int32_t m_block_height{0};

public:
CAddressIndexIteratorHeightKey() {
SetNull();
}

CAddressIndexIteratorHeightKey(AddressType address_type, uint160 address_bytes, int32_t block_height) :
m_address_type{address_type}, m_address_bytes{address_bytes}, m_block_height{block_height} {};

void SetNull() {
m_address_type = AddressType::UNKNOWN;
m_address_bytes.SetNull();
m_block_height = 0;
}

public:
size_t GetSerializeSize(int nType, int nVersion) const {
return 25;
}

template<typename Stream>
void Serialize(Stream& s) const {
ser_writedata8(s, ToUnderlying(m_address_type));
m_address_bytes.Serialize(s);
ser_writedata32be(s, m_block_height);
}

template<typename Stream>
void Unserialize(Stream& s) {
m_address_type = static_cast<AddressType>(ser_readdata8(s));
m_address_bytes.Unserialize(s);
m_block_height = ser_readdata32be(s);
}
};

bool AddressBytesFromScript(const CScript& script, AddressType& address_type, uint160& address_bytes);

#endif // BITCOIN_ADDRESSINDEX_H
19 changes: 10 additions & 9 deletions src/core_write.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <univalue.h>
#include <util/strencodings.h>

#include <addressindex.h>
#include <spentindex.h>

#include <evo/assetlocktx.h>
Expand Down Expand Up @@ -213,12 +214,12 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry,
auto it = ptxSpentInfo->mSpentInfo.find(spentKey);
if (it != ptxSpentInfo->mSpentInfo.end()) {
auto spentInfo = it->second;
in.pushKV("value", ValueFromAmount(spentInfo.satoshis));
in.pushKV("valueSat", spentInfo.satoshis);
if (spentInfo.addressType == 1) {
in.pushKV("address", EncodeDestination(PKHash(spentInfo.addressHash)));
} else if (spentInfo.addressType == 2) {
in.pushKV("address", EncodeDestination(ScriptHash(spentInfo.addressHash)));
in.pushKV("value", ValueFromAmount(spentInfo.m_amount));
in.pushKV("valueSat", spentInfo.m_amount);
if (spentInfo.m_address_type == AddressType::P2PK_OR_P2PKH) {
in.pushKV("address", EncodeDestination(PKHash(spentInfo.m_address_bytes)));
} else if (spentInfo.m_address_type == AddressType::P2SH) {
in.pushKV("address", EncodeDestination(ScriptHash(spentInfo.m_address_bytes)));
}
}
}
Expand Down Expand Up @@ -248,9 +249,9 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry,
auto it = ptxSpentInfo->mSpentInfo.find(spentKey);
if (it != ptxSpentInfo->mSpentInfo.end()) {
auto spentInfo = it->second;
out.pushKV("spentTxId", spentInfo.txid.GetHex());
out.pushKV("spentIndex", (int)spentInfo.inputIndex);
out.pushKV("spentHeight", spentInfo.blockHeight);
out.pushKV("spentTxId", spentInfo.m_tx_hash.GetHex());
out.pushKV("spentIndex", (int)spentInfo.m_tx_index);
out.pushKV("spentHeight", spentInfo.m_block_height);
}
}
vout.push_back(out);
Expand Down
10 changes: 5 additions & 5 deletions src/rpc/blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -838,8 +838,8 @@ static UniValue getblockhashes(const JSONRPCRequest& request)
}

UniValue result(UniValue::VARR);
for (std::vector<uint256>::const_iterator it=blockHashes.begin(); it!=blockHashes.end(); it++) {
result.push_back(it->GetHex());
for (const auto& hash : blockHashes) {
result.push_back(hash.GetHex());
}

return result;
Expand Down Expand Up @@ -1828,9 +1828,9 @@ static UniValue getchaintips(const JSONRPCRequest& request)
}
}

for (std::set<const CBlockIndex*>::iterator it = setOrphans.begin(); it != setOrphans.end(); ++it) {
if (setPrevs.erase(*it) == 0) {
setTips.insert(*it);
for (const auto& orphan : setOrphans) {
if (setPrevs.erase(orphan) == 0) {
setTips.insert(orphan);
}
}

Expand Down
Loading

0 comments on commit 2958aac

Please sign in to comment.