Skip to content

Commit 2958aac

Browse files
Merge pull request #5577 from kwvg/bitcore_idx
refactor: cleanup {address,spent}index, remove platform-specific types, split out timestamp index
2 parents 7bff85e + 93ddd3f commit 2958aac

14 files changed

+594
-628
lines changed

src/Makefile.am

+2
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ BITCOIN_CORE_H = \
297297
support/events.h \
298298
support/lockedpool.h \
299299
sync.h \
300+
timestampindex.h \
300301
threadsafety.h \
301302
threadinterrupt.h \
302303
timedata.h \
@@ -385,6 +386,7 @@ libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CP
385386
libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
386387
libbitcoin_server_a_SOURCES = \
387388
addrdb.cpp \
389+
addressindex.cpp \
388390
addrman.cpp \
389391
banman.cpp \
390392
batchedlogger.cpp \

src/addressindex.cpp

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright (c) 2016 BitPay, Inc.
2+
// Copyright (c) 2023 The Dash Core developers
3+
// Distributed under the MIT software license, see the accompanying
4+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5+
6+
#include <addressindex.h>
7+
8+
#include <key_io.h>
9+
#include <hash.h>
10+
#include <script/script.h>
11+
12+
template <typename T1>
13+
inline std::vector<uint8_t> TrimScriptP2PKH(const T1& input) {
14+
return std::vector<uint8_t>(input.begin() + 3, input.begin() + 23);
15+
};
16+
17+
template <typename T1>
18+
inline std::vector<uint8_t> TrimScriptP2SH(const T1& input) {
19+
return std::vector<uint8_t>(input.begin() + 2, input.begin() + 22);
20+
};
21+
22+
template <typename T1>
23+
inline std::vector<uint8_t> TrimScriptP2PK(const T1& input) {
24+
return std::vector<uint8_t>(input.begin() + 1, input.end() - 1);
25+
};
26+
27+
bool AddressBytesFromScript(const CScript& script, AddressType& address_type, uint160& address_bytes) {
28+
if (script.IsPayToScriptHash()) {
29+
address_type = AddressType::P2SH;
30+
address_bytes = uint160(TrimScriptP2SH(script));
31+
} else if (script.IsPayToPublicKeyHash()) {
32+
address_type = AddressType::P2PK_OR_P2PKH;
33+
address_bytes = uint160(TrimScriptP2PKH(script));
34+
} else if (script.IsPayToPublicKey()) {
35+
address_type = AddressType::P2PK_OR_P2PKH;
36+
address_bytes = Hash160(TrimScriptP2PK(script));
37+
} else {
38+
address_type = AddressType::UNKNOWN;
39+
address_bytes.SetNull();
40+
return false;
41+
}
42+
return true;
43+
}

src/addressindex.h

+190-55
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,219 @@
11
// Copyright (c) 2009-2010 Satoshi Nakamoto
22
// Copyright (c) 2009-2015 The Bitcoin Core developers
3+
// Copyright (c) 2016 BitPay, Inc.
4+
// Copyright (c) 2023 The Dash Core developers
35
// Distributed under the MIT software license, see the accompanying
46
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
57

68
#ifndef BITCOIN_ADDRESSINDEX_H
79
#define BITCOIN_ADDRESSINDEX_H
810

9-
#include <uint256.h>
1011
#include <amount.h>
12+
#include <serialize.h>
13+
#include <uint256.h>
14+
#include <util/underlying.h>
1115

1216
#include <chrono>
17+
#include <tuple>
18+
19+
class CScript;
20+
21+
enum class AddressType : uint8_t {
22+
P2PK_OR_P2PKH = 1,
23+
P2SH = 2,
24+
25+
UNKNOWN = 0
26+
};
27+
template<> struct is_serializable_enum<AddressType> : std::true_type {};
1328

1429
struct CMempoolAddressDelta
1530
{
16-
std::chrono::seconds time;
17-
CAmount amount;
18-
uint256 prevhash;
19-
unsigned int prevout;
31+
public:
32+
std::chrono::seconds m_time;
33+
CAmount m_amount;
34+
uint256 m_prev_hash;
35+
uint32_t m_prev_out{0};
2036

21-
CMempoolAddressDelta(std::chrono::seconds t, CAmount a, uint256 hash, unsigned int out) {
22-
time = t;
23-
amount = a;
24-
prevhash = hash;
25-
prevout = out;
26-
}
37+
public:
38+
CMempoolAddressDelta(std::chrono::seconds time, CAmount amount, uint256 prev_hash, uint32_t prev_out) :
39+
m_time{time}, m_amount{amount}, m_prev_hash{prev_hash}, m_prev_out{prev_out} {}
2740

28-
CMempoolAddressDelta(std::chrono::seconds t, CAmount a) {
29-
time = t;
30-
amount = a;
31-
prevhash.SetNull();
32-
prevout = 0;
33-
}
41+
CMempoolAddressDelta(std::chrono::seconds time, CAmount amount) :
42+
m_time{time}, m_amount{amount} {}
3443
};
3544

3645
struct CMempoolAddressDeltaKey
3746
{
38-
int type;
39-
uint160 addressBytes;
40-
uint256 txhash;
41-
unsigned int index;
42-
int spending;
43-
44-
CMempoolAddressDeltaKey(int addressType, uint160 addressHash, uint256 hash, unsigned int i, int s) {
45-
type = addressType;
46-
addressBytes = addressHash;
47-
txhash = hash;
48-
index = i;
49-
spending = s;
50-
}
51-
52-
CMempoolAddressDeltaKey(int addressType, uint160 addressHash) {
53-
type = addressType;
54-
addressBytes = addressHash;
55-
txhash.SetNull();
56-
index = 0;
57-
spending = 0;
58-
}
47+
public:
48+
AddressType m_address_type{AddressType::UNKNOWN};
49+
uint160 m_address_bytes;
50+
uint256 m_tx_hash;
51+
uint32_t m_tx_index{0};
52+
bool m_tx_spent{false};
53+
54+
public:
55+
CMempoolAddressDeltaKey(AddressType address_type, uint160 address_bytes, uint256 tx_hash, uint32_t tx_index, bool tx_spent) :
56+
m_address_type{address_type},
57+
m_address_bytes{address_bytes},
58+
m_tx_hash{tx_hash},
59+
m_tx_index{tx_index},
60+
m_tx_spent{tx_spent} {};
61+
62+
CMempoolAddressDeltaKey(AddressType address_type, uint160 address_bytes) :
63+
m_address_type{address_type},
64+
m_address_bytes{address_bytes} {};
5965
};
6066

6167
struct CMempoolAddressDeltaKeyCompare
6268
{
6369
bool operator()(const CMempoolAddressDeltaKey& a, const CMempoolAddressDeltaKey& b) const {
64-
if (a.type == b.type) {
65-
if (a.addressBytes == b.addressBytes) {
66-
if (a.txhash == b.txhash) {
67-
if (a.index == b.index) {
68-
return a.spending < b.spending;
69-
} else {
70-
return a.index < b.index;
71-
}
72-
} else {
73-
return a.txhash < b.txhash;
74-
}
75-
} else {
76-
return a.addressBytes < b.addressBytes;
77-
}
78-
} else {
79-
return a.type < b.type;
80-
}
70+
auto to_tuple = [](const CMempoolAddressDeltaKey& obj) {
71+
return std::tie(obj.m_address_type, obj.m_address_bytes, obj.m_tx_hash, obj.m_tx_index, obj.m_tx_spent);
72+
};
73+
return to_tuple(a) < to_tuple(b);
74+
}
75+
};
76+
77+
struct CAddressIndexKey {
78+
public:
79+
AddressType m_address_type{AddressType::UNKNOWN};
80+
uint160 m_address_bytes;
81+
int32_t m_block_height{0};
82+
uint32_t m_block_tx_pos{0};
83+
uint256 m_tx_hash;
84+
uint32_t m_tx_index{0};
85+
bool m_tx_spent{false};
86+
87+
public:
88+
CAddressIndexKey() {
89+
SetNull();
90+
}
91+
92+
CAddressIndexKey(AddressType address_type, uint160 address_bytes, int32_t block_height, uint32_t block_tx_pos, uint256 tx_hash,
93+
uint32_t tx_index, bool tx_spent) :
94+
m_address_type{address_type},
95+
m_address_bytes{address_bytes},
96+
m_block_height{block_height},
97+
m_block_tx_pos{block_tx_pos},
98+
m_tx_hash{tx_hash},
99+
m_tx_index{tx_index},
100+
m_tx_spent{tx_spent} {};
101+
102+
void SetNull() {
103+
m_address_type = AddressType::UNKNOWN;
104+
m_address_bytes.SetNull();
105+
m_block_height = 0;
106+
m_block_tx_pos = 0;
107+
m_tx_hash.SetNull();
108+
m_tx_index = 0;
109+
m_tx_spent = false;
110+
}
111+
112+
public:
113+
size_t GetSerializeSize(int nType, int nVersion) const {
114+
return 66;
115+
}
116+
117+
template<typename Stream>
118+
void Serialize(Stream& s) const {
119+
ser_writedata8(s, ToUnderlying(m_address_type));
120+
m_address_bytes.Serialize(s);
121+
// Heights are stored big-endian for key sorting in LevelDB
122+
ser_writedata32be(s, m_block_height);
123+
ser_writedata32be(s, m_block_tx_pos);
124+
m_tx_hash.Serialize(s);
125+
ser_writedata32(s, m_tx_index);
126+
ser_writedata8(s, static_cast<uint8_t>(m_tx_spent));
127+
}
128+
129+
template<typename Stream>
130+
void Unserialize(Stream& s) {
131+
m_address_type = static_cast<AddressType>(ser_readdata8(s));
132+
m_address_bytes.Unserialize(s);
133+
m_block_height = ser_readdata32be(s);
134+
m_block_tx_pos = ser_readdata32be(s);
135+
m_tx_hash.Unserialize(s);
136+
m_tx_index = ser_readdata32(s);
137+
m_tx_spent = static_cast<bool>(ser_readdata8(s));
81138
}
82139
};
83140

141+
struct CAddressIndexIteratorKey {
142+
public:
143+
AddressType m_address_type{AddressType::UNKNOWN};
144+
uint160 m_address_bytes;
145+
146+
public:
147+
CAddressIndexIteratorKey() {
148+
SetNull();
149+
}
150+
151+
CAddressIndexIteratorKey(AddressType address_type, uint160 address_bytes) :
152+
m_address_type{address_type}, m_address_bytes{address_bytes} {};
153+
154+
void SetNull() {
155+
m_address_type = AddressType::UNKNOWN;
156+
m_address_bytes.SetNull();
157+
}
158+
159+
public:
160+
size_t GetSerializeSize(int nType, int nVersion) const {
161+
return 21;
162+
}
163+
164+
template<typename Stream>
165+
void Serialize(Stream& s) const {
166+
ser_writedata8(s, ToUnderlying(m_address_type));
167+
m_address_bytes.Serialize(s);
168+
}
169+
170+
template<typename Stream>
171+
void Unserialize(Stream& s) {
172+
m_address_type = static_cast<AddressType>(ser_readdata8(s));
173+
m_address_bytes.Unserialize(s);
174+
}
175+
};
176+
177+
struct CAddressIndexIteratorHeightKey {
178+
public:
179+
AddressType m_address_type{AddressType::UNKNOWN};
180+
uint160 m_address_bytes;
181+
int32_t m_block_height{0};
182+
183+
public:
184+
CAddressIndexIteratorHeightKey() {
185+
SetNull();
186+
}
187+
188+
CAddressIndexIteratorHeightKey(AddressType address_type, uint160 address_bytes, int32_t block_height) :
189+
m_address_type{address_type}, m_address_bytes{address_bytes}, m_block_height{block_height} {};
190+
191+
void SetNull() {
192+
m_address_type = AddressType::UNKNOWN;
193+
m_address_bytes.SetNull();
194+
m_block_height = 0;
195+
}
196+
197+
public:
198+
size_t GetSerializeSize(int nType, int nVersion) const {
199+
return 25;
200+
}
201+
202+
template<typename Stream>
203+
void Serialize(Stream& s) const {
204+
ser_writedata8(s, ToUnderlying(m_address_type));
205+
m_address_bytes.Serialize(s);
206+
ser_writedata32be(s, m_block_height);
207+
}
208+
209+
template<typename Stream>
210+
void Unserialize(Stream& s) {
211+
m_address_type = static_cast<AddressType>(ser_readdata8(s));
212+
m_address_bytes.Unserialize(s);
213+
m_block_height = ser_readdata32be(s);
214+
}
215+
};
216+
217+
bool AddressBytesFromScript(const CScript& script, AddressType& address_type, uint160& address_bytes);
218+
84219
#endif // BITCOIN_ADDRESSINDEX_H

src/core_write.cpp

+10-9
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <univalue.h>
1515
#include <util/strencodings.h>
1616

17+
#include <addressindex.h>
1718
#include <spentindex.h>
1819

1920
#include <evo/assetlocktx.h>
@@ -213,12 +214,12 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry,
213214
auto it = ptxSpentInfo->mSpentInfo.find(spentKey);
214215
if (it != ptxSpentInfo->mSpentInfo.end()) {
215216
auto spentInfo = it->second;
216-
in.pushKV("value", ValueFromAmount(spentInfo.satoshis));
217-
in.pushKV("valueSat", spentInfo.satoshis);
218-
if (spentInfo.addressType == 1) {
219-
in.pushKV("address", EncodeDestination(PKHash(spentInfo.addressHash)));
220-
} else if (spentInfo.addressType == 2) {
221-
in.pushKV("address", EncodeDestination(ScriptHash(spentInfo.addressHash)));
217+
in.pushKV("value", ValueFromAmount(spentInfo.m_amount));
218+
in.pushKV("valueSat", spentInfo.m_amount);
219+
if (spentInfo.m_address_type == AddressType::P2PK_OR_P2PKH) {
220+
in.pushKV("address", EncodeDestination(PKHash(spentInfo.m_address_bytes)));
221+
} else if (spentInfo.m_address_type == AddressType::P2SH) {
222+
in.pushKV("address", EncodeDestination(ScriptHash(spentInfo.m_address_bytes)));
222223
}
223224
}
224225
}
@@ -248,9 +249,9 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry,
248249
auto it = ptxSpentInfo->mSpentInfo.find(spentKey);
249250
if (it != ptxSpentInfo->mSpentInfo.end()) {
250251
auto spentInfo = it->second;
251-
out.pushKV("spentTxId", spentInfo.txid.GetHex());
252-
out.pushKV("spentIndex", (int)spentInfo.inputIndex);
253-
out.pushKV("spentHeight", spentInfo.blockHeight);
252+
out.pushKV("spentTxId", spentInfo.m_tx_hash.GetHex());
253+
out.pushKV("spentIndex", (int)spentInfo.m_tx_index);
254+
out.pushKV("spentHeight", spentInfo.m_block_height);
254255
}
255256
}
256257
vout.push_back(out);

src/rpc/blockchain.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -838,8 +838,8 @@ static UniValue getblockhashes(const JSONRPCRequest& request)
838838
}
839839

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

845845
return result;
@@ -1828,9 +1828,9 @@ static UniValue getchaintips(const JSONRPCRequest& request)
18281828
}
18291829
}
18301830

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

0 commit comments

Comments
 (0)