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:
    utACK 8fb863008e
  UdjinM6:
    utACK 8fb863008e

Tree-SHA512: 425a383e8284bbd74a5e9bcda4a9d7988221197055f43faa591e6f0d579625cee28f6a6046dab951e7afa0c3e33af1778fb4bb5f0a2e1e5792fe0d9396897a14
This commit is contained in:
pasta 2024-06-29 14:46:01 -05:00
commit c1de83bf8f
No known key found for this signature in database
GPG Key ID: 52527BEDABE87984
14 changed files with 279 additions and 168 deletions

View File

@ -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 \

View File

@ -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:

View File

@ -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
View 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
View 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

View File

@ -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;
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");
}

View File

@ -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) {

View File

@ -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;

View File

@ -263,13 +263,13 @@ 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++) {
for (std::vector<std::pair<CSpentIndexKey,CSpentIndexValue>>::const_iterator it=vect.begin(); it!=vect.end(); it++) {
if (it->second.IsNull()) {
batch.Erase(std::make_pair(DB_SPENTINDEX, it->first));
} else {
@ -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) {
@ -363,7 +363,7 @@ bool CBlockTreeDB::ReadAddressIndex(uint160 addressHash, AddressType type,
return true;
}
bool CBlockTreeDB::WriteTimestampIndex(const CTimestampIndexKey &timestampIndex) {
bool CBlockTreeDB::WriteTimestampIndex(const CTimestampIndexKey& timestampIndex) {
CDBBatch batch(*this);
batch.Write(std::make_pair(DB_TIMESTAMPINDEX, timestampIndex), 0);
return WriteBatch(batch);
@ -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)));

View File

@ -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 WriteTimestampIndex(const CTimestampIndexKey &timestampIndex);
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);

View File

@ -427,7 +427,7 @@ void CTxMemPool::addUnchecked(const CTxMemPoolEntry &entry, setEntries &setAnces
}
}
void CTxMemPool::addAddressIndex(const CTxMemPoolEntry &entry, const CCoinsViewCache &view)
void CTxMemPool::addAddressIndex(const CTxMemPoolEntry& entry, const CCoinsViewCache& view)
{
LOCK(cs);
const CTransaction& tx = entry.GetTx();
@ -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++;
}
@ -500,7 +501,7 @@ bool CTxMemPool::removeAddressIndex(const uint256 txhash)
return true;
}
void CTxMemPool::addSpentIndex(const CTxMemPoolEntry &entry, const CCoinsViewCache &view)
void CTxMemPool::addSpentIndex(const CTxMemPoolEntry& entry, const CCoinsViewCache& view)
{
LOCK(cs);
@ -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;

View File

@ -635,13 +635,13 @@ public:
void addUnchecked(const CTxMemPoolEntry& entry, bool validFeeEstimate = true) EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main);
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);
void addAddressIndex(const CTxMemPoolEntry& entry, const CCoinsViewCache& view);
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);
void addSpentIndex(const CTxMemPoolEntry& entry, const CCoinsViewCache& view);
bool getSpentIndex(const CSpentIndexKey& key, CSpentIndexValue& value) const;
bool removeSpentIndex(const uint256 txhash);
void removeRecursive(const CTransaction& tx, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs);

View File

@ -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];

View File

@ -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();