mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 03:52:49 +01:00
Merge #6083: refactor: move Get*Index to rpc/index_util.cpp, const-ify functions and arguments, add lock annotations and some minor housekeeping
8fb863008e
refactor: inline sorting and make available through argument (Kittywhiskers Van Gogh)3e0fcf471f
refactor: move accessing CBlockTreeDB global out of Get*Index (Kittywhiskers Van Gogh)ee9d11214e
refactor: move pair value swapping out of CTxMemPool::getAddressIndex() (Kittywhiskers Van Gogh)808842b1a3
refactor: define all key/value pairings as *Entry and use them instead (Kittywhiskers Van Gogh)488f0474a8
rpc: extend error-on-failure to GetSpentIndex (Kittywhiskers Van Gogh)9a6503d9e8
refactor: make CBlockTreeDB::Read*Index arguments const (Kittywhiskers Van Gogh)625982e8d2
refactor: make CTxMemPool::get*Index functions and arguments const (Kittywhiskers Van Gogh)5ad49ad668
refactor: move Get{Address*, Timestamp, Spent}Index out of validation (Kittywhiskers Van Gogh) Pull request description: ## Additional Information This pull request is motivated by [bitcoin#22371](https://github.com/bitcoin/bitcoin/pull/22371), which gets rid of the `pblocktree` global. The sole usage of `pblocktree` introduced by Dash is for managing our {address, spent, timestamp} indexes with most of invocations within `BlockManager` or `CChainState`, granting them internal access to `pblocktree` (now `m_block_tree_db`). The sole exception being `Get*Index`, that relies on accessing the global and has no direct internal access. This pull request aims to refactor code associated with `Get*Index` with the eventual aim of moving gaining access to the global out of the function. `Get*Index` is called exclusively called through RPC, which makes giving it access to `ChainstateManager` quite easy, which makes switching from the global to accessing it through `ChainstateManager` when backporting [bitcoin#22371](https://github.com/bitcoin/bitcoin/pull/22371) a drop-in replacement. Alongside that, the surrounding code has been given some TLC: * Moving code out of `validation.cpp` and into `rpc/index_util.cpp`. The code is exclusively used in RPC logic and doesn't aid in validation. * Add lock annotations for accessing `pblocktree` (while already protected by `::cs_main`, said protection is currently not enforced but will be once moved into `BlockManager` in the backport) * `const`-ing input arguments and using pass-by-value for input arguments that can be written inline (i.e. types like `CSpentIndexKey` are still pass-by-ref). * While `const`ing `CTxMemPool` functions were possible (courtesy of the presence of `const_iterator`s), the same is currently not possible with `CBlockTreeDB` functions as the iterator is non-`const`. * Extend error messages to `GetSpentIndex` to bring it line with other `Get*Index`es. * Define key-value pairings as a `*Entry` typedef and replacing all explicit type constructions with it. * Make `CTxMemPool::getAddressIndex` indifferent to how `CMempoolAddressDeltaKey` is constructed. * Current behaviour is to accept a `std::pair<uint160, AddressType>` and construct the `CMempoolAddressDeltaKey` internally, this was presumably done to account for the return type of `getAddressesFromParams` in the sole call for the `CTxMemPool::getAddressIndex`. * This has been changed, moving the construction into the RPC call. * Moving {height, timestamp} sorting out of RPC and into the applicable `Get*Index` functions. ## Breaking Changes None expected. ## Checklist: - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas (note: N/A) - [x] I have added or updated relevant unit/integration/functional/e2e tests (note: N/A) - [x] I have made corresponding changes to the documentation (note: N/A) - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ ACKs for top commit: PastaPastaPasta: utACK8fb863008e
UdjinM6: utACK8fb863008e
Tree-SHA512: 425a383e8284bbd74a5e9bcda4a9d7988221197055f43faa591e6f0d579625cee28f6a6046dab951e7afa0c3e33af1778fb4bb5f0a2e1e5792fe0d9396897a14
This commit is contained in:
commit
c1de83bf8f
@ -286,6 +286,7 @@ BITCOIN_CORE_H = \
|
||||
reverse_iterator.h \
|
||||
rpc/blockchain.h \
|
||||
rpc/client.h \
|
||||
rpc/index_util.h \
|
||||
rpc/mining.h \
|
||||
rpc/protocol.h \
|
||||
rpc/rawtransaction_util.h \
|
||||
@ -502,6 +503,7 @@ libbitcoin_server_a_SOURCES = \
|
||||
rpc/blockchain.cpp \
|
||||
rpc/coinjoin.cpp \
|
||||
rpc/evo.cpp \
|
||||
rpc/index_util.cpp \
|
||||
rpc/masternode.cpp \
|
||||
rpc/governance.cpp \
|
||||
rpc/mining.cpp \
|
||||
|
@ -17,6 +17,9 @@
|
||||
#include <tuple>
|
||||
|
||||
class CScript;
|
||||
struct CAddressIndexKey;
|
||||
struct CMempoolAddressDelta;
|
||||
struct CMempoolAddressDeltaKey;
|
||||
|
||||
enum class AddressType : uint8_t {
|
||||
P2PK_OR_P2PKH = 1,
|
||||
@ -26,6 +29,9 @@ enum class AddressType : uint8_t {
|
||||
};
|
||||
template<> struct is_serializable_enum<AddressType> : std::true_type {};
|
||||
|
||||
using CAddressIndexEntry = std::pair<CAddressIndexKey, CAmount>;
|
||||
using CMempoolAddressDeltaEntry = std::pair<CMempoolAddressDeltaKey, CMempoolAddressDelta>;
|
||||
|
||||
struct CMempoolAddressDelta
|
||||
{
|
||||
public:
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <policy/fees.h>
|
||||
#include <policy/policy.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <rpc/index_util.h>
|
||||
#include <rpc/server.h>
|
||||
#include <rpc/server_util.h>
|
||||
#include <rpc/util.h>
|
||||
@ -834,7 +835,7 @@ static RPCHelpMan getblockhashes()
|
||||
unsigned int low = request.params[1].get_int();
|
||||
std::vector<uint256> blockHashes;
|
||||
|
||||
if (!GetTimestampIndex(high, low, blockHashes)) {
|
||||
if (LOCK(::cs_main); !GetTimestampIndex(*pblocktree, high, low, blockHashes)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for block hashes");
|
||||
}
|
||||
|
||||
|
98
src/rpc/index_util.cpp
Normal file
98
src/rpc/index_util.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
// Copyright (c) 2016 BitPay, Inc.
|
||||
// Copyright (c) 2024 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 <rpc/index_util.h>
|
||||
|
||||
#include <txmempool.h>
|
||||
#include <uint256.h>
|
||||
#include <validation.h>
|
||||
|
||||
bool GetAddressIndex(CBlockTreeDB& block_tree_db, const uint160& addressHash, const AddressType type,
|
||||
std::vector<CAddressIndexEntry>& addressIndex,
|
||||
const int32_t start, const int32_t end)
|
||||
{
|
||||
AssertLockHeld(::cs_main);
|
||||
|
||||
if (!fAddressIndex)
|
||||
return error("Address index not enabled");
|
||||
|
||||
if (!block_tree_db.ReadAddressIndex(addressHash, type, addressIndex, start, end))
|
||||
return error("Unable to get txids for address");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetAddressUnspentIndex(CBlockTreeDB& block_tree_db, const uint160& addressHash, const AddressType type,
|
||||
std::vector<CAddressUnspentIndexEntry>& unspentOutputs, const bool height_sort)
|
||||
{
|
||||
AssertLockHeld(::cs_main);
|
||||
|
||||
if (!fAddressIndex)
|
||||
return error("Address index not enabled");
|
||||
|
||||
if (!block_tree_db.ReadAddressUnspentIndex(addressHash, type, unspentOutputs))
|
||||
return error("Unable to get txids for address");
|
||||
|
||||
if (height_sort) {
|
||||
std::sort(unspentOutputs.begin(), unspentOutputs.end(),
|
||||
[](const CAddressUnspentIndexEntry &a, const CAddressUnspentIndexEntry &b) {
|
||||
return a.second.m_block_height < b.second.m_block_height;
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetMempoolAddressDeltaIndex(const CTxMemPool& mempool,
|
||||
const std::vector<CMempoolAddressDeltaKey>& addressDeltaIndex,
|
||||
std::vector<CMempoolAddressDeltaEntry>& addressDeltaEntries,
|
||||
const bool timestamp_sort)
|
||||
{
|
||||
if (!fAddressIndex)
|
||||
return error("Address index not enabled");
|
||||
|
||||
if (!mempool.getAddressIndex(addressDeltaIndex, addressDeltaEntries))
|
||||
return error("Unable to get address delta information");
|
||||
|
||||
if (timestamp_sort) {
|
||||
std::sort(addressDeltaEntries.begin(), addressDeltaEntries.end(),
|
||||
[](const CMempoolAddressDeltaEntry &a, const CMempoolAddressDeltaEntry &b) {
|
||||
return a.second.m_time < b.second.m_time;
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetSpentIndex(CBlockTreeDB& block_tree_db, const CTxMemPool& mempool, const CSpentIndexKey& key,
|
||||
CSpentIndexValue& value)
|
||||
{
|
||||
AssertLockHeld(::cs_main);
|
||||
|
||||
if (!fSpentIndex)
|
||||
return error("Spent index not enabled");
|
||||
|
||||
if (mempool.getSpentIndex(key, value))
|
||||
return true;
|
||||
|
||||
if (!block_tree_db.ReadSpentIndex(key, value))
|
||||
return error("Unable to get spend information");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetTimestampIndex(CBlockTreeDB& block_tree_db, const uint32_t high, const uint32_t low,
|
||||
std::vector<uint256>& hashes)
|
||||
{
|
||||
AssertLockHeld(::cs_main);
|
||||
|
||||
if (!fTimestampIndex)
|
||||
return error("Timestamp index not enabled");
|
||||
|
||||
if (!block_tree_db.ReadTimestampIndex(high, low, hashes))
|
||||
return error("Unable to get hashes for timestamps");
|
||||
|
||||
return true;
|
||||
}
|
45
src/rpc/index_util.h
Normal file
45
src/rpc/index_util.h
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright (c) 2016 BitPay, Inc.
|
||||
// Copyright (c) 2024 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_RPC_INDEX_UTIL_H
|
||||
#define BITCOIN_RPC_INDEX_UTIL_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include <amount.h>
|
||||
#include <addressindex.h>
|
||||
#include <spentindex.h>
|
||||
#include <sync.h>
|
||||
#include <threadsafety.h>
|
||||
|
||||
class CBlockTreeDB;
|
||||
class CTxMemPool;
|
||||
class uint160;
|
||||
class uint256;
|
||||
|
||||
enum class AddressType : uint8_t;
|
||||
|
||||
extern RecursiveMutex cs_main;
|
||||
|
||||
bool GetAddressIndex(CBlockTreeDB& block_tree_db, const uint160& addressHash, const AddressType type,
|
||||
std::vector<CAddressIndexEntry>& addressIndex,
|
||||
const int32_t start = 0, const int32_t end = 0)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
||||
bool GetAddressUnspentIndex(CBlockTreeDB& block_tree_db, const uint160& addressHash, const AddressType type,
|
||||
std::vector<CAddressUnspentIndexEntry>& unspentOutputs, const bool height_sort = false)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
||||
bool GetMempoolAddressDeltaIndex(const CTxMemPool& mempool,
|
||||
const std::vector<CMempoolAddressDeltaKey>& addressDeltaIndex,
|
||||
std::vector<CMempoolAddressDeltaEntry>& addressDeltaEntries,
|
||||
const bool timestamp_sort = false);
|
||||
bool GetSpentIndex(CBlockTreeDB& block_tree_db, const CTxMemPool& mempool, const CSpentIndexKey& key,
|
||||
CSpentIndexValue& value)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
||||
bool GetTimestampIndex(CBlockTreeDB& block_tree_db, const uint32_t high, const uint32_t low,
|
||||
std::vector<uint256>& hashes)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
||||
|
||||
#endif // BITCOIN_RPC_CLIENT_H
|
@ -19,6 +19,7 @@
|
||||
#include <net.h>
|
||||
#include <node/context.h>
|
||||
#include <rpc/blockchain.h>
|
||||
#include <rpc/index_util.h>
|
||||
#include <rpc/server.h>
|
||||
#include <rpc/server_util.h>
|
||||
#include <rpc/util.h>
|
||||
@ -700,16 +701,6 @@ static bool getAddressesFromParams(const UniValue& params, std::vector<std::pair
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool heightSort(std::pair<CAddressUnspentKey, CAddressUnspentValue> a,
|
||||
std::pair<CAddressUnspentKey, CAddressUnspentValue> b) {
|
||||
return a.second.m_block_height < b.second.m_block_height;
|
||||
}
|
||||
|
||||
static bool timestampSort(std::pair<CMempoolAddressDeltaKey, CMempoolAddressDelta> a,
|
||||
std::pair<CMempoolAddressDeltaKey, CMempoolAddressDelta> b) {
|
||||
return a.second.m_time < b.second.m_time;
|
||||
}
|
||||
|
||||
static RPCHelpMan getaddressmempool()
|
||||
{
|
||||
return RPCHelpMan{"getaddressmempool",
|
||||
@ -741,22 +732,22 @@ static RPCHelpMan getaddressmempool()
|
||||
},
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||
{
|
||||
CTxMemPool& mempool = EnsureAnyMemPool(request.context);
|
||||
|
||||
std::vector<std::pair<uint160, AddressType>> addresses;
|
||||
|
||||
if (!getAddressesFromParams(request.params, addresses)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
|
||||
}
|
||||
|
||||
std::vector<std::pair<CMempoolAddressDeltaKey, CMempoolAddressDelta> > indexes;
|
||||
|
||||
CTxMemPool& mempool = EnsureAnyMemPool(request.context);
|
||||
if (!mempool.getAddressIndex(addresses, indexes)) {
|
||||
std::vector<CMempoolAddressDeltaKey> input_addresses;
|
||||
std::vector<CMempoolAddressDeltaEntry> indexes;
|
||||
for (const auto& [hash, type] : addresses) {
|
||||
input_addresses.push_back({type, hash});
|
||||
}
|
||||
if (!GetMempoolAddressDeltaIndex(mempool, input_addresses, indexes, /* timestamp_sort = */ true)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address");
|
||||
}
|
||||
|
||||
std::sort(indexes.begin(), indexes.end(), timestampSort);
|
||||
|
||||
UniValue result(UniValue::VARR);
|
||||
|
||||
for (const auto& [mempoolAddressKey, mempoolAddressDelta] : indexes) {
|
||||
@ -820,15 +811,17 @@ static RPCHelpMan getaddressutxos()
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
|
||||
}
|
||||
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
std::vector<CAddressUnspentIndexEntry> unspentOutputs;
|
||||
|
||||
{
|
||||
LOCK(::cs_main);
|
||||
for (const auto& address : addresses) {
|
||||
if (!GetAddressUnspent(address.first, address.second, unspentOutputs)) {
|
||||
if (!GetAddressUnspentIndex(*pblocktree, address.first, address.second, unspentOutputs,
|
||||
/* height_sort = */ true)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address");
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(unspentOutputs.begin(), unspentOutputs.end(), heightSort);
|
||||
}
|
||||
|
||||
UniValue result(UniValue::VARR);
|
||||
|
||||
@ -905,19 +898,22 @@ static RPCHelpMan getaddressdeltas()
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
|
||||
}
|
||||
|
||||
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
|
||||
std::vector<CAddressIndexEntry> addressIndex;
|
||||
|
||||
{
|
||||
LOCK(::cs_main);
|
||||
for (const auto& address : addresses) {
|
||||
if (start > 0 && end > 0) {
|
||||
if (!GetAddressIndex(address.first, address.second, addressIndex, start, end)) {
|
||||
if (!GetAddressIndex(*pblocktree, address.first, address.second, addressIndex, start, end)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address");
|
||||
}
|
||||
} else {
|
||||
if (!GetAddressIndex(address.first, address.second, addressIndex)) {
|
||||
if (!GetAddressIndex(*pblocktree, address.first, address.second, addressIndex)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UniValue result(UniValue::VARR);
|
||||
|
||||
@ -974,16 +970,21 @@ static RPCHelpMan getaddressbalance()
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
|
||||
}
|
||||
|
||||
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
|
||||
std::vector<CAddressIndexEntry> addressIndex;
|
||||
|
||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||
|
||||
int nHeight;
|
||||
{
|
||||
LOCK(::cs_main);
|
||||
for (const auto& address : addresses) {
|
||||
if (!GetAddressIndex(address.first, address.second, addressIndex)) {
|
||||
if (!GetAddressIndex(*pblocktree, address.first, address.second, addressIndex)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address");
|
||||
}
|
||||
}
|
||||
nHeight = chainman.ActiveChain().Height();
|
||||
}
|
||||
|
||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||
int nHeight = WITH_LOCK(cs_main, return chainman.ActiveChain().Height());
|
||||
|
||||
CAmount balance = 0;
|
||||
CAmount balance_spendable = 0;
|
||||
@ -1053,19 +1054,22 @@ static RPCHelpMan getaddresstxids()
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
|
||||
std::vector<CAddressIndexEntry> addressIndex;
|
||||
|
||||
{
|
||||
LOCK(::cs_main);
|
||||
for (const auto& address : addresses) {
|
||||
if (start > 0 && end > 0) {
|
||||
if (!GetAddressIndex(address.first, address.second, addressIndex, start, end)) {
|
||||
if (!GetAddressIndex(*pblocktree, address.first, address.second, addressIndex, start, end)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address");
|
||||
}
|
||||
} else {
|
||||
if (!GetAddressIndex(address.first, address.second, addressIndex)) {
|
||||
if (!GetAddressIndex(*pblocktree, address.first, address.second, addressIndex)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::set<std::pair<int, std::string> > txids;
|
||||
UniValue result(UniValue::VARR);
|
||||
@ -1134,7 +1138,7 @@ static RPCHelpMan getspentinfo()
|
||||
CSpentIndexValue value;
|
||||
|
||||
CTxMemPool& mempool = EnsureAnyMemPool(request.context);
|
||||
if (!GetSpentIndex(mempool, key, value)) {
|
||||
if (LOCK(::cs_main); !GetSpentIndex(*pblocktree, mempool, key, value)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to get spent info");
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <primitives/transaction.h>
|
||||
#include <psbt.h>
|
||||
#include <rpc/blockchain.h>
|
||||
#include <rpc/index_util.h>
|
||||
#include <rpc/rawtransaction_util.h>
|
||||
#include <rpc/server.h>
|
||||
#include <rpc/server_util.h>
|
||||
@ -58,6 +59,8 @@
|
||||
|
||||
void TxToJSON(const CTransaction& tx, const uint256 hashBlock, CTxMemPool& mempool, CChainState& active_chainstate, llmq::CChainLocksHandler& clhandler, llmq::CInstantSendManager& isman, UniValue& entry)
|
||||
{
|
||||
LOCK(::cs_main);
|
||||
|
||||
// Call into TxToUniv() in bitcoin-common to decode the transaction hex.
|
||||
//
|
||||
// Blockchain contextual information (confirmations and blocktime) is not
|
||||
@ -72,7 +75,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, CTxMemPool& mempo
|
||||
if (!tx.IsCoinBase()) {
|
||||
CSpentIndexValue spentInfo;
|
||||
CSpentIndexKey spentKey(txin.prevout.hash, txin.prevout.n);
|
||||
if (GetSpentIndex(mempool, spentKey, spentInfo)) {
|
||||
if (GetSpentIndex(*pblocktree, mempool, spentKey, spentInfo)) {
|
||||
txSpentInfo.mSpentInfo.emplace(spentKey, spentInfo);
|
||||
}
|
||||
}
|
||||
@ -80,7 +83,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, CTxMemPool& mempo
|
||||
for (unsigned int i = 0; i < tx.vout.size(); i++) {
|
||||
CSpentIndexValue spentInfo;
|
||||
CSpentIndexKey spentKey(txid, i);
|
||||
if (GetSpentIndex(mempool, spentKey, spentInfo)) {
|
||||
if (GetSpentIndex(*pblocktree, mempool, spentKey, spentInfo)) {
|
||||
txSpentInfo.mSpentInfo.emplace(spentKey, spentInfo);
|
||||
}
|
||||
}
|
||||
@ -89,8 +92,6 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, CTxMemPool& mempo
|
||||
|
||||
bool chainLock = false;
|
||||
if (!hashBlock.IsNull()) {
|
||||
LOCK(cs_main);
|
||||
|
||||
entry.pushKV("blockhash", hashBlock.GetHex());
|
||||
CBlockIndex* pindex = active_chainstate.m_blockman.LookupBlockIndex(hashBlock);
|
||||
if (pindex) {
|
||||
|
@ -16,6 +16,14 @@
|
||||
|
||||
#include <tuple>
|
||||
|
||||
struct CAddressUnspentKey;
|
||||
struct CAddressUnspentValue;
|
||||
struct CSpentIndexKey;
|
||||
struct CSpentIndexValue;
|
||||
|
||||
using CAddressUnspentIndexEntry = std::pair<CAddressUnspentKey, CAddressUnspentValue>;
|
||||
using CSpentIndexEntry = std::pair<CSpentIndexKey, CSpentIndexValue>;
|
||||
|
||||
struct CSpentIndexKey {
|
||||
public:
|
||||
uint256 m_tx_hash;
|
||||
|
33
src/txdb.cpp
33
src/txdb.cpp
@ -263,11 +263,11 @@ bool CBlockTreeDB::WriteBatchSync(const std::vector<std::pair<int, const CBlockF
|
||||
return WriteBatch(batch, true);
|
||||
}
|
||||
|
||||
bool CBlockTreeDB::ReadSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value) {
|
||||
bool CBlockTreeDB::ReadSpentIndex(const CSpentIndexKey key, CSpentIndexValue& value) {
|
||||
return Read(std::make_pair(DB_SPENTINDEX, key), value);
|
||||
}
|
||||
|
||||
bool CBlockTreeDB::UpdateSpentIndex(const std::vector<std::pair<CSpentIndexKey, CSpentIndexValue> >&vect) {
|
||||
bool CBlockTreeDB::UpdateSpentIndex(const std::vector<CSpentIndexEntry>& vect) {
|
||||
CDBBatch batch(*this);
|
||||
for (std::vector<std::pair<CSpentIndexKey,CSpentIndexValue>>::const_iterator it=vect.begin(); it!=vect.end(); it++) {
|
||||
if (it->second.IsNull()) {
|
||||
@ -279,9 +279,9 @@ bool CBlockTreeDB::UpdateSpentIndex(const std::vector<std::pair<CSpentIndexKey,
|
||||
return WriteBatch(batch);
|
||||
}
|
||||
|
||||
bool CBlockTreeDB::UpdateAddressUnspentIndex(const std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue > >&vect) {
|
||||
bool CBlockTreeDB::UpdateAddressUnspentIndex(const std::vector<CAddressUnspentIndexEntry>& vect) {
|
||||
CDBBatch batch(*this);
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=vect.begin(); it!=vect.end(); it++) {
|
||||
for (std::vector<CAddressUnspentIndexEntry>::const_iterator it=vect.begin(); it!=vect.end(); it++) {
|
||||
if (it->second.IsNull()) {
|
||||
batch.Erase(std::make_pair(DB_ADDRESSUNSPENTINDEX, it->first));
|
||||
} else {
|
||||
@ -291,9 +291,9 @@ bool CBlockTreeDB::UpdateAddressUnspentIndex(const std::vector<std::pair<CAddres
|
||||
return WriteBatch(batch);
|
||||
}
|
||||
|
||||
bool CBlockTreeDB::ReadAddressUnspentIndex(uint160 addressHash, AddressType type,
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &unspentOutputs) {
|
||||
|
||||
bool CBlockTreeDB::ReadAddressUnspentIndex(const uint160& addressHash, const AddressType type,
|
||||
std::vector<CAddressUnspentIndexEntry>& unspentOutputs)
|
||||
{
|
||||
std::unique_ptr<CDBIterator> pcursor(NewIterator());
|
||||
|
||||
pcursor->Seek(std::make_pair(DB_ADDRESSUNSPENTINDEX, CAddressIndexIteratorKey(type, addressHash)));
|
||||
@ -316,24 +316,24 @@ bool CBlockTreeDB::ReadAddressUnspentIndex(uint160 addressHash, AddressType type
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBlockTreeDB::WriteAddressIndex(const std::vector<std::pair<CAddressIndexKey, CAmount > >&vect) {
|
||||
bool CBlockTreeDB::WriteAddressIndex(const std::vector<CAddressIndexEntry>& vect) {
|
||||
CDBBatch batch(*this);
|
||||
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
|
||||
for (std::vector<CAddressIndexEntry>::const_iterator it=vect.begin(); it!=vect.end(); it++)
|
||||
batch.Write(std::make_pair(DB_ADDRESSINDEX, it->first), it->second);
|
||||
return WriteBatch(batch);
|
||||
}
|
||||
|
||||
bool CBlockTreeDB::EraseAddressIndex(const std::vector<std::pair<CAddressIndexKey, CAmount > >&vect) {
|
||||
bool CBlockTreeDB::EraseAddressIndex(const std::vector<CAddressIndexEntry>& vect) {
|
||||
CDBBatch batch(*this);
|
||||
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
|
||||
for (std::vector<CAddressIndexEntry>::const_iterator it=vect.begin(); it!=vect.end(); it++)
|
||||
batch.Erase(std::make_pair(DB_ADDRESSINDEX, it->first));
|
||||
return WriteBatch(batch);
|
||||
}
|
||||
|
||||
bool CBlockTreeDB::ReadAddressIndex(uint160 addressHash, AddressType type,
|
||||
std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex,
|
||||
int start, int end) {
|
||||
|
||||
bool CBlockTreeDB::ReadAddressIndex(const uint160& addressHash, const AddressType type,
|
||||
std::vector<CAddressIndexEntry>& addressIndex,
|
||||
const int32_t start, const int32_t end)
|
||||
{
|
||||
std::unique_ptr<CDBIterator> pcursor(NewIterator());
|
||||
|
||||
if (start > 0 && end > 0) {
|
||||
@ -376,8 +376,7 @@ bool CBlockTreeDB::EraseTimestampIndex(const CTimestampIndexKey& timestampIndex)
|
||||
return WriteBatch(batch);
|
||||
}
|
||||
|
||||
bool CBlockTreeDB::ReadTimestampIndex(const unsigned int &high, const unsigned int &low, std::vector<uint256> &hashes) {
|
||||
|
||||
bool CBlockTreeDB::ReadTimestampIndex(const uint32_t high, const uint32_t low, std::vector<uint256>& hashes) {
|
||||
std::unique_ptr<CDBIterator> pcursor(NewIterator());
|
||||
|
||||
pcursor->Seek(std::make_pair(DB_TIMESTAMPINDEX, CTimestampIndexIteratorKey(low)));
|
||||
|
27
src/txdb.h
27
src/txdb.h
@ -84,19 +84,24 @@ public:
|
||||
bool ReadLastBlockFile(int &nFile);
|
||||
bool WriteReindexing(bool fReindexing);
|
||||
void ReadReindexing(bool &fReindexing);
|
||||
bool ReadSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value);
|
||||
bool UpdateSpentIndex(const std::vector<std::pair<CSpentIndexKey, CSpentIndexValue> >&vect);
|
||||
bool UpdateAddressUnspentIndex(const std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue > >&vect);
|
||||
bool ReadAddressUnspentIndex(uint160 addressHash, AddressType type,
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &vect);
|
||||
bool WriteAddressIndex(const std::vector<std::pair<CAddressIndexKey, CAmount> > &vect);
|
||||
bool EraseAddressIndex(const std::vector<std::pair<CAddressIndexKey, CAmount> > &vect);
|
||||
bool ReadAddressIndex(uint160 addressHash, AddressType type,
|
||||
std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex,
|
||||
int start = 0, int end = 0);
|
||||
|
||||
bool ReadSpentIndex(const CSpentIndexKey key, CSpentIndexValue& value);
|
||||
bool UpdateSpentIndex(const std::vector<CSpentIndexEntry>& vect);
|
||||
|
||||
bool ReadAddressUnspentIndex(const uint160& addressHash, const AddressType type,
|
||||
std::vector<CAddressUnspentIndexEntry>& vect);
|
||||
bool UpdateAddressUnspentIndex(const std::vector<CAddressUnspentIndexEntry>& vect);
|
||||
|
||||
bool WriteAddressIndex(const std::vector<CAddressIndexEntry>& vect);
|
||||
bool EraseAddressIndex(const std::vector<CAddressIndexEntry>& vect);
|
||||
bool ReadAddressIndex(const uint160& addressHash, const AddressType type,
|
||||
std::vector<CAddressIndexEntry>& addressIndex,
|
||||
const int32_t start = 0, const int32_t end = 0);
|
||||
|
||||
bool WriteTimestampIndex(const CTimestampIndexKey& timestampIndex);
|
||||
bool EraseTimestampIndex(const CTimestampIndexKey& timestampIndex);
|
||||
bool ReadTimestampIndex(const unsigned int &high, const unsigned int &low, std::vector<uint256> &vect);
|
||||
bool ReadTimestampIndex(const uint32_t high, const uint32_t low, std::vector<uint256>& hashes);
|
||||
|
||||
bool WriteFlag(const std::string &name, bool fValue);
|
||||
bool ReadFlag(const std::string &name, bool &fValue);
|
||||
bool LoadBlockIndexGuts(const Consensus::Params& consensusParams, std::function<CBlockIndex*(const uint256&)> insertBlockIndex);
|
||||
|
@ -470,13 +470,14 @@ void CTxMemPool::addAddressIndex(const CTxMemPoolEntry &entry, const CCoinsViewC
|
||||
mapAddressInserted.insert(std::make_pair(txhash, inserted));
|
||||
}
|
||||
|
||||
bool CTxMemPool::getAddressIndex(std::vector<std::pair<uint160, AddressType> > &addresses,
|
||||
std::vector<std::pair<CMempoolAddressDeltaKey, CMempoolAddressDelta> > &results)
|
||||
bool CTxMemPool::getAddressIndex(const std::vector<CMempoolAddressDeltaKey>& addresses,
|
||||
std::vector<CMempoolAddressDeltaEntry>& results) const
|
||||
{
|
||||
LOCK(cs);
|
||||
for (const auto& address : addresses) {
|
||||
addressDeltaMap::iterator ait = mapAddress.lower_bound(CMempoolAddressDeltaKey(address.second, address.first));
|
||||
while (ait != mapAddress.end() && (*ait).first.m_address_bytes == address.first && (*ait).first.m_address_type == address.second) {
|
||||
addressDeltaMap::const_iterator ait = mapAddress.lower_bound(address);
|
||||
while (ait != mapAddress.end() && (*ait).first.m_address_bytes == address.m_address_bytes
|
||||
&& (*ait).first.m_address_type == address.m_address_type) {
|
||||
results.push_back(*ait);
|
||||
ait++;
|
||||
}
|
||||
@ -530,12 +531,11 @@ void CTxMemPool::addSpentIndex(const CTxMemPoolEntry &entry, const CCoinsViewCac
|
||||
mapSpentInserted.insert(make_pair(txhash, inserted));
|
||||
}
|
||||
|
||||
bool CTxMemPool::getSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value)
|
||||
bool CTxMemPool::getSpentIndex(const CSpentIndexKey& key, CSpentIndexValue& value) const
|
||||
{
|
||||
LOCK(cs);
|
||||
mapSpentIndex::iterator it;
|
||||
mapSpentIndex::const_iterator it = mapSpent.find(key);
|
||||
|
||||
it = mapSpent.find(key);
|
||||
if (it != mapSpent.end()) {
|
||||
value = it->second;
|
||||
return true;
|
||||
|
@ -636,12 +636,12 @@ public:
|
||||
void addUnchecked(const CTxMemPoolEntry& entry, setEntries& setAncestors, bool validFeeEstimate = true) EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main);
|
||||
|
||||
void addAddressIndex(const CTxMemPoolEntry& entry, const CCoinsViewCache& view);
|
||||
bool getAddressIndex(std::vector<std::pair<uint160, AddressType> > &addresses,
|
||||
std::vector<std::pair<CMempoolAddressDeltaKey, CMempoolAddressDelta> > &results);
|
||||
bool getAddressIndex(const std::vector<CMempoolAddressDeltaKey>& addresses,
|
||||
std::vector<CMempoolAddressDeltaEntry>& results) const;
|
||||
bool removeAddressIndex(const uint256 txhash);
|
||||
|
||||
void addSpentIndex(const CTxMemPoolEntry& entry, const CCoinsViewCache& view);
|
||||
bool getSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value);
|
||||
bool getSpentIndex(const CSpentIndexKey& key, CSpentIndexValue& value) const;
|
||||
bool removeSpentIndex(const uint256 txhash);
|
||||
|
||||
void removeRecursive(const CTransaction& tx, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
|
@ -1055,56 +1055,6 @@ PackageMempoolAcceptResult ProcessNewPackage(CChainState& active_chainstate, CTx
|
||||
return result;
|
||||
}
|
||||
|
||||
bool GetTimestampIndex(const unsigned int &high, const unsigned int &low, std::vector<uint256> &hashes)
|
||||
{
|
||||
if (!fTimestampIndex)
|
||||
return error("Timestamp index not enabled");
|
||||
|
||||
if (!pblocktree->ReadTimestampIndex(high, low, hashes))
|
||||
return error("Unable to get hashes for timestamps");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetSpentIndex(CTxMemPool& mempool, CSpentIndexKey &key, CSpentIndexValue &value)
|
||||
{
|
||||
if (!fSpentIndex)
|
||||
return false;
|
||||
|
||||
if (mempool.getSpentIndex(key, value))
|
||||
return true;
|
||||
|
||||
if (!pblocktree->ReadSpentIndex(key, value))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetAddressIndex(uint160 addressHash, AddressType type,
|
||||
std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex, int start, int end)
|
||||
{
|
||||
if (!fAddressIndex)
|
||||
return error("address index not enabled");
|
||||
|
||||
if (!pblocktree->ReadAddressIndex(addressHash, type, addressIndex, start, end))
|
||||
return error("unable to get txids for address");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetAddressUnspent(uint160 addressHash, AddressType type,
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &unspentOutputs)
|
||||
{
|
||||
if (!fAddressIndex)
|
||||
return error("address index not enabled");
|
||||
|
||||
if (!pblocktree->ReadAddressUnspentIndex(addressHash, type, unspentOutputs))
|
||||
return error("unable to get txids for address");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
double ConvertBitsToDouble(unsigned int nBits)
|
||||
{
|
||||
int nShift = (nBits >> 24) & 0xff;
|
||||
@ -1735,9 +1685,9 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI
|
||||
return DISCONNECT_FAILED;
|
||||
}
|
||||
|
||||
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > addressUnspentIndex;
|
||||
std::vector<std::pair<CSpentIndexKey, CSpentIndexValue> > spentIndex;
|
||||
std::vector<CAddressIndexEntry> addressIndex;
|
||||
std::vector<CAddressUnspentIndexEntry> addressUnspentIndex;
|
||||
std::vector<CSpentIndexEntry> spentIndex;
|
||||
|
||||
std::optional<MNListUpdates> mnlist_updates_opt{std::nullopt};
|
||||
if (!m_chain_helper->special_tx->UndoSpecialTxsInBlock(block, pindex, mnlist_updates_opt)) {
|
||||
@ -2202,9 +2152,9 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
|
||||
int nInputs = 0;
|
||||
unsigned int nSigOps = 0;
|
||||
blockundo.vtxundo.reserve(block.vtx.size() - 1);
|
||||
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > addressUnspentIndex;
|
||||
std::vector<std::pair<CSpentIndexKey, CSpentIndexValue> > spentIndex;
|
||||
std::vector<CAddressIndexEntry> addressIndex;
|
||||
std::vector<CAddressUnspentIndexEntry> addressUnspentIndex;
|
||||
std::vector<CSpentIndexEntry> spentIndex;
|
||||
|
||||
bool fDIP0001Active_context = pindex->nHeight >= Params().GetConsensus().DIP0001Height;
|
||||
|
||||
@ -4832,9 +4782,9 @@ bool CChainState::RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& i
|
||||
pindex->GetBlockHash().ToString(), state.ToString());
|
||||
}
|
||||
|
||||
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > addressUnspentIndex;
|
||||
std::vector<std::pair<CSpentIndexKey, CSpentIndexValue> > spentIndex;
|
||||
std::vector<CAddressIndexEntry> addressIndex;
|
||||
std::vector<CAddressUnspentIndexEntry> addressUnspentIndex;
|
||||
std::vector<CSpentIndexEntry> spentIndex;
|
||||
|
||||
for (size_t i = 0; i < block.vtx.size(); i++) {
|
||||
const CTransactionRef& tx = block.vtx[i];
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include <txdb.h>
|
||||
#include <txmempool.h> // For CTxMemPool::cs
|
||||
#include <serialize.h>
|
||||
#include <spentindex.h>
|
||||
#include <util/check.h>
|
||||
#include <util/hasher.h>
|
||||
|
||||
@ -379,13 +378,6 @@ public:
|
||||
ScriptError GetScriptError() const { return error; }
|
||||
};
|
||||
|
||||
bool GetTimestampIndex(const unsigned int &high, const unsigned int &low, std::vector<uint256> &hashes);
|
||||
bool GetSpentIndex(CTxMemPool& mempool, CSpentIndexKey &key, CSpentIndexValue &value);
|
||||
bool GetAddressIndex(uint160 addressHash, AddressType type,
|
||||
std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex,
|
||||
int start = 0, int end = 0);
|
||||
bool GetAddressUnspent(uint160 addressHash, AddressType type,
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &unspentOutputs);
|
||||
/** Initializes the script-execution cache */
|
||||
void InitScriptExecutionCache();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user