feat: add CMNHFManager and logic to make hard-forks accordingly received signals

This commit is contained in:
Konstantin Akimov 2023-08-04 03:54:54 +07:00 committed by PastaPastaPasta
parent c8d84a8c33
commit 33ab3187b2
14 changed files with 290 additions and 21 deletions

View File

@ -15,9 +15,12 @@
#include <validation.h> #include <validation.h>
#include <versionbits.h> #include <versionbits.h>
#include <algorithm>
#include <string> #include <string>
#include <vector>
extern const std::string MNEHF_REQUESTID_PREFIX = "mnhf"; extern const std::string MNEHF_REQUESTID_PREFIX = "mnhf";
static const std::string DB_SIGNALS = "mnhf_s";
bool MNHFTx::Verify(const CBlockIndex* pQuorumIndex, const uint256& msgHash, TxValidationState& state) const bool MNHFTx::Verify(const CBlockIndex* pQuorumIndex, const uint256& msgHash, TxValidationState& state) const
{ {
@ -80,6 +83,183 @@ bool CheckMNHFTx(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValida
return true; return true;
} }
static bool extractSignals(const CBlock& block, const CBlockIndex* const pindex, std::vector<uint8_t>& signals_to_process, BlockValidationState& state)
{
AssertLockHeld(cs_main);
// we skip the coinbase
for (size_t i = 1; i < block.vtx.size(); ++i) {
const CTransaction& tx = *block.vtx[i];
if (tx.nVersion != 3 || tx.nType != TRANSACTION_MNHF_SIGNAL) {
// only interested in special TXs 'TRANSACTION_MNHF_SIGNAL'
continue;
}
TxValidationState tx_state;
if (!CheckMNHFTx(tx, pindex, tx_state)) {
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, tx_state.GetRejectReason(), tx_state.GetDebugMessage());
}
MNHFTxPayload mnhfTx;
if (!GetTxPayload(tx, mnhfTx)) {
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-mnhf-tx-payload");
}
signals_to_process.push_back(mnhfTx.signal.versionBit);
}
// Checking that there's no any duplicates...
std::sort(signals_to_process.begin(), signals_to_process.end());
const auto it = std::unique(signals_to_process.begin(), signals_to_process.end());
if (std::distance(signals_to_process.begin(), it) != signals_to_process.size()) {
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-mnhf-duplicates");
}
return true;
}
bool CMNHFManager::ProcessBlock(const CBlock& block, const CBlockIndex* const pindex, bool fJustCheck, BlockValidationState& state)
{
try {
std::vector<uint8_t> new_signals;
if (!extractSignals(block, pindex, new_signals, state)) {
// state is set inside extractSignals
return false;
}
if (new_signals.empty()) {
if (!fJustCheck) {
AddToCache(GetFromCache(pindex->pprev), pindex);
}
return true;
}
Signals signals = GetFromCache(pindex->pprev);
int mined_height = pindex->nHeight;
// Extra validation of signals to be sure that it can succeed
for (const auto& versionBit : new_signals) {
LogPrintf("%s: add mnhf bit=%d block:%s number of known signals:%lld\n", __func__, versionBit, pindex->GetBlockHash().ToString(), signals.size());
if (signals.find(versionBit) != signals.end()) {
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-mnhf-duplicate");
}
if (!Params().UpdateMNActivationParam(versionBit, mined_height, pindex->GetMedianTimePast(), true /* fJustCheck */)) {
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-mnhf-non-mn-fork");
}
}
if (fJustCheck) {
// We are done, no need actually update any params
return true;
}
for (const auto& versionBit : new_signals) {
signals.insert({versionBit, mined_height});
if (!Params().UpdateMNActivationParam(versionBit, mined_height, pindex->GetMedianTimePast(), false /* fJustCheck */)) {
// it should not ever fail - all checks are done above
assert(false);
}
}
AddToCache(signals, pindex);
return true;
} catch (const std::exception& e) {
LogPrintf("%s -- failed: %s\n", __func__, e.what());
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "failed-proc-mnhf-inblock");
}
}
bool CMNHFManager::UndoBlock(const CBlock& block, const CBlockIndex* const pindex)
{
std::vector<uint8_t> excluded_signals;
BlockValidationState state;
if (!extractSignals(block, pindex, excluded_signals, state)) {
LogPrintf("%s: failed to extract signals\n", __func__);
return false;
}
if (excluded_signals.empty()) {
return true;
}
const Signals signals = GetFromCache(pindex);
for (const auto& versionBit : excluded_signals) {
assert(versionBit < VERSIONBITS_NUM_BITS);
LogPrintf("%s: exclude mnhf bit=%d block:%s number of known signals:%lld\n", __func__, versionBit, pindex->GetBlockHash().ToString(), signals.size());
assert(signals.find(versionBit) != signals.end());
bool update_ret = Params().UpdateMNActivationParam(versionBit, 0, pindex->GetMedianTimePast(), false /* fJustCheck */);
assert(update_ret);
}
return true;
}
void CMNHFManager::UpdateChainParams(const CBlockIndex* const pindex, const CBlockIndex* const pindexOld)
{
LogPrintf("%s: update chain params %s -> %s\n", __func__, pindexOld ? pindexOld->GetBlockHash().ToString() : "", pindex ? pindex->GetBlockHash().ToString() : "");
Signals signals_old{GetFromCache(pindexOld)};
for (const auto& signal: signals_old) {
uint8_t versionBit = signal.first;
assert(versionBit < VERSIONBITS_NUM_BITS);
LogPrintf("%s: unload mnhf bit=%d block:%s number of known signals:%lld\n", __func__, versionBit, pindex->GetBlockHash().ToString(), signals_old.size());
bool update_ret = Params().UpdateMNActivationParam(versionBit, 0, pindex->GetMedianTimePast(), false);
assert(update_ret);
}
Signals signals{GetFromCache(pindex)};
for (const auto& signal: signals) {
uint8_t versionBit = signal.first;
int value = signal.second;
assert(versionBit < VERSIONBITS_NUM_BITS);
LogPrintf("%s: load mnhf bit=%d block:%s number of known signals:%lld\n", __func__, versionBit, pindex->GetBlockHash().ToString(), signals.size());
bool update_ret = Params().UpdateMNActivationParam(versionBit, value, pindex->GetMedianTimePast(), false);
assert(update_ret);
}
}
CMNHFManager::Signals CMNHFManager::GetFromCache(const CBlockIndex* const pindex)
{
if (pindex == nullptr) return {};
const uint256& blockHash = pindex->GetBlockHash();
Signals signals{};
{
LOCK(cs_cache);
if (mnhfCache.get(blockHash, signals)) {
LogPrintf("CMNHFManager::GetFromCache: mnhf get for block %s from cache: %lld signals\n", pindex->GetBlockHash().ToString(), signals.size());
return signals;
}
}
if (VersionBitsState(pindex->pprev, Params().GetConsensus(), Consensus::DEPLOYMENT_V20, versionbitscache) != ThresholdState::ACTIVE) {
LOCK(cs_cache);
mnhfCache.insert(blockHash, signals);
LogPrintf("CMNHFManager::GetFromCache: mnhf feature is disabled: return empty for block %s\n", pindex->GetBlockHash().ToString());
return signals;
}
if (!m_evoDb.Read(std::make_pair(DB_SIGNALS, blockHash), signals)) {
LogPrintf("CMNHFManager::GetFromCache: failure: can't read MnEHF signals from db for %s\n", pindex->GetBlockHash().ToString());
}
LogPrintf("CMNHFManager::GetFromCache: mnhf for block %s read from evo: %lld\n", pindex->GetBlockHash().ToString(), signals.size());
LOCK(cs_cache);
mnhfCache.insert(blockHash, signals);
return signals;
}
void CMNHFManager::AddToCache(const Signals& signals, const CBlockIndex* const pindex)
{
const uint256& blockHash = pindex->GetBlockHash();
{
LOCK(cs_cache);
LogPrintf("%s: mnhf for block %s add to cache: %lld\n", __func__, pindex->GetBlockHash().ToString(), signals.size());
mnhfCache.insert(blockHash, signals);
}
m_evoDb.Write(std::make_pair(DB_SIGNALS, blockHash), signals);
}
std::string MNHFTx::ToString() const std::string MNHFTx::ToString() const
{ {
return strprintf("MNHFTx(versionBit=%d, quorumHash=%s, sig=%s)", return strprintf("MNHFTx(versionBit=%d, quorumHash=%s, sig=%s)",

View File

@ -11,7 +11,14 @@
#include <threadsafety.h> #include <threadsafety.h>
#include <univalue.h> #include <univalue.h>
#include <saltedhasher.h>
#include <unordered_map>
#include <unordered_lru_cache.h>
class BlockValidationState;
class CBlock;
class CBlockIndex; class CBlockIndex;
class CEvoDB;
class TxValidationState; class TxValidationState;
extern RecursiveMutex cs_main; extern RecursiveMutex cs_main;
@ -72,6 +79,45 @@ public:
} }
}; };
class CMNHFManager
{
public:
using Signals = std::unordered_map<uint8_t, int>;
private:
CEvoDB& m_evoDb;
static constexpr size_t MNHFCacheSize = 1000;
Mutex cs_cache;
// versionBit <-> height
unordered_lru_cache<uint256, Signals, StaticSaltedHasher> mnhfCache GUARDED_BY(cs_cache) {MNHFCacheSize};
public:
explicit CMNHFManager(CEvoDB& evoDb) :
m_evoDb(evoDb) {}
~CMNHFManager() = default;
/**
* Every new block should be processed when Tip() is updated by calling of CMNHFManager::ProcessBlock
*/
bool ProcessBlock(const CBlock& block, const CBlockIndex* const pindex, bool fJustCheck, BlockValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/**
* Every undo block should be processed when Tip() is updated by calling of CMNHFManager::UndoBlock
*/
bool UndoBlock(const CBlock& block, const CBlockIndex* const pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/**
* Once app is started, need to initialize dictionary will all known signals at the current Tip()
* by calling UpdateChainParams()
*/
void UpdateChainParams(const CBlockIndex* const pindex, const CBlockIndex* const pindexOld) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
private:
void AddToCache(const Signals& signals, const CBlockIndex* const pindex);
Signals GetFromCache(const CBlockIndex* const pindex);
};
bool CheckMNHFTx(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main); bool CheckMNHFTx(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
#endif // BITCOIN_EVO_MNHFTX_H #endif // BITCOIN_EVO_MNHFTX_H

View File

@ -122,7 +122,8 @@ static bool UndoSpecialTx(const CTransaction& tx, const CBlockIndex* pindex)
return false; return false;
} }
bool ProcessSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, llmq::CQuorumBlockProcessor& quorum_block_processor, const llmq::CChainLocksHandler& chainlock_handler, bool ProcessSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, CMNHFManager& mnhfManager,
llmq::CQuorumBlockProcessor& quorum_block_processor, const llmq::CChainLocksHandler& chainlock_handler,
const Consensus::Params& consensusParams, const CCoinsViewCache& view, bool fJustCheck, bool fCheckCbTxMerleRoots, const Consensus::Params& consensusParams, const CCoinsViewCache& view, bool fJustCheck, bool fCheckCbTxMerleRoots,
BlockValidationState& state) BlockValidationState& state)
{ {
@ -134,6 +135,7 @@ bool ProcessSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, ll
static int64_t nTimeDMN = 0; static int64_t nTimeDMN = 0;
static int64_t nTimeMerkle = 0; static int64_t nTimeMerkle = 0;
static int64_t nTimeCbTxCL = 0; static int64_t nTimeCbTxCL = 0;
static int64_t nTimeMnehf = 0;
int64_t nTime1 = GetTimeMicros(); int64_t nTime1 = GetTimeMicros();
@ -198,6 +200,15 @@ bool ProcessSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, ll
nTimeCbTxCL += nTime6 - nTime5; nTimeCbTxCL += nTime6 - nTime5;
LogPrint(BCLog::BENCHMARK, " - CheckCbTxBestChainlock: %.2fms [%.2fs]\n", 0.001 * (nTime6 - nTime5), nTimeCbTxCL * 0.000001); LogPrint(BCLog::BENCHMARK, " - CheckCbTxBestChainlock: %.2fms [%.2fs]\n", 0.001 * (nTime6 - nTime5), nTimeCbTxCL * 0.000001);
if (!mnhfManager.ProcessBlock(block, pindex, fJustCheck, state)) {
// pass the state returned by the function above
return false;
}
int64_t nTime7 = GetTimeMicros();
nTimeMnehf += nTime7 - nTime6;
LogPrint(BCLog::BENCHMARK, " - mnhfManager: %.2fms [%.2fs]\n", 0.001 * (nTime7 - nTime6), nTimeMnehf * 0.000001);
if (Params().GetConsensus().V19Height == pindex->nHeight + 1) { if (Params().GetConsensus().V19Height == pindex->nHeight + 1) {
// NOTE: The block next to the activation is the one that is using new rules. // NOTE: The block next to the activation is the one that is using new rules.
// V19 activated just activated, so we must switch to the new rules here. // V19 activated just activated, so we must switch to the new rules here.
@ -212,7 +223,7 @@ bool ProcessSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, ll
return true; return true;
} }
bool UndoSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, llmq::CQuorumBlockProcessor& quorum_block_processor) bool UndoSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, CMNHFManager& mnhfManager, llmq::CQuorumBlockProcessor& quorum_block_processor)
{ {
AssertLockHeld(cs_main); AssertLockHeld(cs_main);
@ -233,6 +244,10 @@ bool UndoSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, llmq:
} }
} }
if (!mnhfManager.UndoBlock(block, pindex)) {
return false;
}
if (!deterministicMNManager->UndoBlock(pindex)) { if (!deterministicMNManager->UndoBlock(pindex)) {
return false; return false;
} }

View File

@ -13,6 +13,7 @@ class BlockValidationState;
class CBlock; class CBlock;
class CBlockIndex; class CBlockIndex;
class CCoinsViewCache; class CCoinsViewCache;
class CMNHFManager;
class TxValidationState; class TxValidationState;
namespace llmq { namespace llmq {
class CQuorumBlockProcessor; class CQuorumBlockProcessor;
@ -26,10 +27,12 @@ extern RecursiveMutex cs_main;
bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, const CCoinsViewCache& view, bool check_sigs, bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, const CCoinsViewCache& view, bool check_sigs,
TxValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main); TxValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool ProcessSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, llmq::CQuorumBlockProcessor& quorum_block_processor, const llmq::CChainLocksHandler& chainlock_handler, bool ProcessSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, CMNHFManager& mnhfManager,
const Consensus::Params& consensusParams, const CCoinsViewCache& view, bool fJustCheck, bool fCheckCbTxMerleRoots, llmq::CQuorumBlockProcessor& quorum_block_processor, const llmq::CChainLocksHandler& chainlock_handler,
BlockValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main); const Consensus::Params& consensusParams, const CCoinsViewCache& view, bool fJustCheck, bool fCheckCbTxMerleRoots,
bool UndoSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, llmq::CQuorumBlockProcessor& quorum_block_processor) EXCLUSIVE_LOCKS_REQUIRED(cs_main); BlockValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool UndoSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, CMNHFManager& mnhfManager,
llmq::CQuorumBlockProcessor& quorum_block_processor) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool CheckCreditPoolDiffForBlock(const CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams, bool CheckCreditPoolDiffForBlock(const CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams,
const CAmount blockReward, BlockValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main); const CAmount blockReward, BlockValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);

View File

@ -87,6 +87,7 @@
#include <evo/creditpool.h> #include <evo/creditpool.h>
#include <evo/deterministicmns.h> #include <evo/deterministicmns.h>
#include <evo/mnhftx.h>
#include <llmq/blockprocessor.h> #include <llmq/blockprocessor.h>
#include <llmq/chainlocks.h> #include <llmq/chainlocks.h>
#include <llmq/context.h> #include <llmq/context.h>
@ -341,6 +342,7 @@ void PrepareShutdown(NodeContext& node)
llmq::quorumSnapshotManager.reset(); llmq::quorumSnapshotManager.reset();
deterministicMNManager.reset(); deterministicMNManager.reset();
creditPoolManager.reset(); creditPoolManager.reset();
node.mnhf_manager.reset();
node.evodb.reset(); node.evodb.reset();
} }
for (const auto& client : node.chain_clients) { for (const auto& client : node.chain_clients) {
@ -1914,9 +1916,10 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
LOCK(cs_main); LOCK(cs_main);
node.evodb.reset(); node.evodb.reset();
node.evodb = std::make_unique<CEvoDB>(nEvoDbCache, false, fReset || fReindexChainState); node.evodb = std::make_unique<CEvoDB>(nEvoDbCache, false, fReset || fReindexChainState);
node.mnhf_manager = std::make_unique<CMNHFManager>(*node.evodb);
chainman.Reset(); chainman.Reset();
chainman.InitializeChainstate(Assert(node.mempool.get()), *node.evodb, llmq::chainLocksHandler, llmq::quorumInstantSendManager, llmq::quorumBlockProcessor); chainman.InitializeChainstate(Assert(node.mempool.get()), *node.mnhf_manager, *node.evodb, llmq::chainLocksHandler, llmq::quorumInstantSendManager, llmq::quorumBlockProcessor);
chainman.m_total_coinstip_cache = nCoinCacheUsage; chainman.m_total_coinstip_cache = nCoinCacheUsage;
chainman.m_total_coinsdb_cache = nCoinDBCache; chainman.m_total_coinsdb_cache = nCoinDBCache;
@ -2104,6 +2107,9 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
LogPrintf("%s: bls_legacy_scheme=%d\n", __func__, bls::bls_legacy_scheme.load()); LogPrintf("%s: bls_legacy_scheme=%d\n", __func__, bls::bls_legacy_scheme.load());
} }
LogPrintf("init.cpp: update chain params right after bls\n");
node.mnhf_manager->UpdateChainParams(::ChainActive().Tip(), nullptr);
if (!CVerifyDB().VerifyDB( if (!CVerifyDB().VerifyDB(
*chainstate, chainparams, chainstate->CoinsDB(), *chainstate, chainparams, chainstate->CoinsDB(),
*node.evodb, *node.evodb,

View File

@ -11,6 +11,7 @@
#include <interfaces/chain.h> #include <interfaces/chain.h>
#include <llmq/context.h> #include <llmq/context.h>
#include <evo/evodb.h> #include <evo/evodb.h>
#include <evo/mnhftx.h>
#include <net.h> #include <net.h>
#include <net_processing.h> #include <net_processing.h>
#include <policy/fees.h> #include <policy/fees.h>

View File

@ -20,6 +20,7 @@ class ChainstateManager;
class CEvoDB; class CEvoDB;
class CScheduler; class CScheduler;
class CTxMemPool; class CTxMemPool;
class CMNHFManager;
class PeerManager; class PeerManager;
struct CJContext; struct CJContext;
struct LLMQContext; struct LLMQContext;
@ -60,6 +61,7 @@ struct NodeContext {
//! Dash //! Dash
std::unique_ptr<LLMQContext> llmq_ctx; std::unique_ptr<LLMQContext> llmq_ctx;
std::unique_ptr<CCreditPoolManager> creditPoolManager; std::unique_ptr<CCreditPoolManager> creditPoolManager;
std::unique_ptr<CMNHFManager> mnhf_manager;
std::unique_ptr<CJContext> cj_ctx; std::unique_ptr<CJContext> cj_ctx;
std::unique_ptr<CEvoDB> evodb; std::unique_ptr<CEvoDB> evodb;

View File

@ -67,6 +67,7 @@
#include <evo/creditpool.h> #include <evo/creditpool.h>
#include <evo/deterministicmns.h> #include <evo/deterministicmns.h>
#include <evo/evodb.h> #include <evo/evodb.h>
#include <evo/mnhftx.h>
#include <evo/specialtx.h> #include <evo/specialtx.h>
#include <memory> #include <memory>
@ -164,6 +165,7 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName, const std::ve
g_wallet_init_interface.Construct(m_node); g_wallet_init_interface.Construct(m_node);
fCheckBlockIndex = true; fCheckBlockIndex = true;
m_node.evodb = std::make_unique<CEvoDB>(1 << 20, true, true); m_node.evodb = std::make_unique<CEvoDB>(1 << 20, true, true);
m_node.mnhf_manager = std::make_unique<CMNHFManager>(*m_node.evodb);
connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman); connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman);
llmq::quorumSnapshotManager.reset(new llmq::CQuorumSnapshotManager(*m_node.evodb)); llmq::quorumSnapshotManager.reset(new llmq::CQuorumSnapshotManager(*m_node.evodb));
creditPoolManager = std::make_unique<CCreditPoolManager>(*m_node.evodb); creditPoolManager = std::make_unique<CCreditPoolManager>(*m_node.evodb);
@ -180,6 +182,7 @@ BasicTestingSetup::~BasicTestingSetup()
connman.reset(); connman.reset();
llmq::quorumSnapshotManager.reset(); llmq::quorumSnapshotManager.reset();
creditPoolManager.reset(); creditPoolManager.reset();
m_node.mnhf_manager.reset();
m_node.evodb.reset(); m_node.evodb.reset();
LogInstance().DisconnectTestLogger(); LogInstance().DisconnectTestLogger();
@ -251,7 +254,7 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const
// instead of unit tests, but for now we need these here. // instead of unit tests, but for now we need these here.
RegisterAllCoreRPCCommands(tableRPC); RegisterAllCoreRPCCommands(tableRPC);
m_node.chainman->InitializeChainstate(m_node.mempool.get(), *m_node.evodb, llmq::chainLocksHandler, llmq::quorumInstantSendManager, llmq::quorumBlockProcessor); m_node.chainman->InitializeChainstate(m_node.mempool.get(), *m_node.mnhf_manager, *m_node.evodb, llmq::chainLocksHandler, llmq::quorumInstantSendManager, llmq::quorumBlockProcessor);
::ChainstateActive().InitCoinsDB( ::ChainstateActive().InitCoinsDB(
/* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false); /* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false);
assert(!::ChainstateActive().CanFlushToDisk()); assert(!::ChainstateActive().CanFlushToDisk());

View File

@ -40,7 +40,7 @@ BOOST_AUTO_TEST_CASE(validation_chainstate_resize_caches)
return outp; return outp;
}; };
CChainState& c1 = *WITH_LOCK(cs_main, return &manager.InitializeChainstate(&mempool, *m_node.evodb, llmq::chainLocksHandler, llmq::quorumInstantSendManager, llmq::quorumBlockProcessor)); CChainState& c1 = *WITH_LOCK(cs_main, return &manager.InitializeChainstate(&mempool, *m_node.mnhf_manager, *m_node.evodb, llmq::chainLocksHandler, llmq::quorumInstantSendManager, llmq::quorumBlockProcessor));
c1.InitCoinsDB( c1.InitCoinsDB(
/* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false); /* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false);
WITH_LOCK(::cs_main, c1.InitCoinsCache(1 << 23)); WITH_LOCK(::cs_main, c1.InitCoinsCache(1 << 23));

View File

@ -42,7 +42,7 @@ BOOST_AUTO_TEST_CASE(chainstatemanager)
// Create a legacy (IBD) chainstate. // Create a legacy (IBD) chainstate.
// //
CChainState& c1 = *WITH_LOCK(::cs_main, return &manager.InitializeChainstate(&mempool, evodb, llmq::chainLocksHandler, llmq::quorumInstantSendManager, llmq::quorumBlockProcessor)); CChainState& c1 = *WITH_LOCK(::cs_main, return &manager.InitializeChainstate(&mempool, *m_node.mnhf_manager, evodb, llmq::chainLocksHandler, llmq::quorumInstantSendManager, llmq::quorumBlockProcessor));
chainstates.push_back(&c1); chainstates.push_back(&c1);
c1.InitCoinsDB( c1.InitCoinsDB(
/* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false); /* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false);
@ -76,7 +76,7 @@ BOOST_AUTO_TEST_CASE(chainstatemanager)
// //
const uint256 snapshot_blockhash = GetRandHash(); const uint256 snapshot_blockhash = GetRandHash();
CChainState& c2 = *WITH_LOCK(::cs_main, return &manager.InitializeChainstate( CChainState& c2 = *WITH_LOCK(::cs_main, return &manager.InitializeChainstate(
&mempool, evodb, llmq::chainLocksHandler, llmq::quorumInstantSendManager, llmq::quorumBlockProcessor, &mempool, *m_node.mnhf_manager, evodb, llmq::chainLocksHandler, llmq::quorumInstantSendManager, llmq::quorumBlockProcessor,
snapshot_blockhash) snapshot_blockhash)
); );
chainstates.push_back(&c2); chainstates.push_back(&c2);
@ -145,7 +145,7 @@ BOOST_AUTO_TEST_CASE(chainstatemanager_rebalance_caches)
// Create a legacy (IBD) chainstate. // Create a legacy (IBD) chainstate.
// //
CChainState& c1 = *WITH_LOCK(cs_main, return &manager.InitializeChainstate(&mempool, evodb, llmq::chainLocksHandler, llmq::quorumInstantSendManager, llmq::quorumBlockProcessor)); CChainState& c1 = *WITH_LOCK(cs_main, return &manager.InitializeChainstate(&mempool, *m_node.mnhf_manager, evodb, llmq::chainLocksHandler, llmq::quorumInstantSendManager, llmq::quorumBlockProcessor));
chainstates.push_back(&c1); chainstates.push_back(&c1);
c1.InitCoinsDB( c1.InitCoinsDB(
/* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false); /* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false);
@ -163,7 +163,7 @@ BOOST_AUTO_TEST_CASE(chainstatemanager_rebalance_caches)
// Create a snapshot-based chainstate. // Create a snapshot-based chainstate.
// //
CChainState& c2 = *WITH_LOCK(cs_main, return &manager.InitializeChainstate(&mempool, evodb, llmq::chainLocksHandler, llmq::quorumInstantSendManager, llmq::quorumBlockProcessor, GetRandHash())); CChainState& c2 = *WITH_LOCK(cs_main, return &manager.InitializeChainstate(&mempool, *m_node.mnhf_manager, evodb, llmq::chainLocksHandler, llmq::quorumInstantSendManager, llmq::quorumBlockProcessor, GetRandHash()));
chainstates.push_back(&c2); chainstates.push_back(&c2);
c2.InitCoinsDB( c2.InitCoinsDB(
/* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false); /* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false);

View File

@ -24,7 +24,7 @@ BOOST_AUTO_TEST_CASE(getcoinscachesizestate)
{ {
CTxMemPool mempool; CTxMemPool mempool;
BlockManager blockman{}; BlockManager blockman{};
CChainState chainstate(&mempool, blockman, *m_node.evodb, llmq::chainLocksHandler, llmq::quorumInstantSendManager, llmq::quorumBlockProcessor); CChainState chainstate(&mempool, blockman, *m_node.mnhf_manager, *m_node.evodb, llmq::chainLocksHandler, llmq::quorumInstantSendManager, llmq::quorumBlockProcessor);
chainstate.InitCoinsDB(/*cache_size_bytes*/ 1 << 10, /*in_memory*/ true, /*should_wipe*/ false); chainstate.InitCoinsDB(/*cache_size_bytes*/ 1 << 10, /*in_memory*/ true, /*should_wipe*/ false);
WITH_LOCK(::cs_main, chainstate.InitCoinsCache(1 << 10)); WITH_LOCK(::cs_main, chainstate.InitCoinsCache(1 << 10));

View File

@ -53,6 +53,7 @@
#include <masternode/sync.h> #include <masternode/sync.h>
#include <evo/evodb.h> #include <evo/evodb.h>
#include <evo/mnhftx.h>
#include <evo/specialtx.h> #include <evo/specialtx.h>
#include <evo/specialtxman.h> #include <evo/specialtxman.h>
#include <governance/governance.h> #include <governance/governance.h>
@ -1260,12 +1261,14 @@ void CoinsViews::InitCache()
CChainState::CChainState(CTxMemPool* mempool, CChainState::CChainState(CTxMemPool* mempool,
BlockManager& blockman, BlockManager& blockman,
CMNHFManager& mnhfManager,
CEvoDB& evoDb, CEvoDB& evoDb,
const std::unique_ptr<llmq::CChainLocksHandler>& clhandler, const std::unique_ptr<llmq::CChainLocksHandler>& clhandler,
const std::unique_ptr<llmq::CInstantSendManager>& isman, const std::unique_ptr<llmq::CInstantSendManager>& isman,
const std::unique_ptr<llmq::CQuorumBlockProcessor>& quorum_block_processor, const std::unique_ptr<llmq::CQuorumBlockProcessor>& quorum_block_processor,
std::optional<uint256> from_snapshot_blockhash) std::optional<uint256> from_snapshot_blockhash)
: m_mempool(mempool), : m_mempool(mempool),
m_mnhfManager(mnhfManager),
m_params(::Params()), m_params(::Params()),
m_clhandler(clhandler), m_clhandler(clhandler),
m_isman(isman), m_isman(isman),
@ -1706,7 +1709,7 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > addressUnspentIndex; std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > addressUnspentIndex;
std::vector<std::pair<CSpentIndexKey, CSpentIndexValue> > spentIndex; std::vector<std::pair<CSpentIndexKey, CSpentIndexValue> > spentIndex;
if (!UndoSpecialTxsInBlock(block, pindex, *m_quorum_block_processor)) { if (!UndoSpecialTxsInBlock(block, pindex, m_mnhfManager, *m_quorum_block_processor)) {
error("DisconnectBlock(): UndoSpecialTxsInBlock failed"); error("DisconnectBlock(): UndoSpecialTxsInBlock failed");
return DISCONNECT_FAILED; return DISCONNECT_FAILED;
} }
@ -2186,7 +2189,7 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
bool fDIP0001Active_context = pindex->nHeight >= Params().GetConsensus().DIP0001Height; bool fDIP0001Active_context = pindex->nHeight >= Params().GetConsensus().DIP0001Height;
// MUST process special txes before updating UTXO to ensure consistency between mempool and block processing // MUST process special txes before updating UTXO to ensure consistency between mempool and block processing
if (!ProcessSpecialTxsInBlock(block, pindex, *m_quorum_block_processor, *m_clhandler, m_params.GetConsensus(), view, fJustCheck, fScriptChecks, state)) { if (!ProcessSpecialTxsInBlock(block, pindex, m_mnhfManager, *m_quorum_block_processor, *m_clhandler, m_params.GetConsensus(), view, fJustCheck, fScriptChecks, state)) {
return error("ConnectBlock(DASH): ProcessSpecialTxsInBlock for block %s failed with %s", return error("ConnectBlock(DASH): ProcessSpecialTxsInBlock for block %s failed with %s",
pindex->GetBlockHash().ToString(), state.ToString()); pindex->GetBlockHash().ToString(), state.ToString());
} }
@ -4809,7 +4812,7 @@ bool CChainState::RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& i
// MUST process special txes before updating UTXO to ensure consistency between mempool and block processing // MUST process special txes before updating UTXO to ensure consistency between mempool and block processing
BlockValidationState state; BlockValidationState state;
if (!ProcessSpecialTxsInBlock(block, pindex, *m_quorum_block_processor, *m_clhandler, m_params.GetConsensus(), inputs, false /*fJustCheck*/, false /*fScriptChecks*/, state)) { if (!ProcessSpecialTxsInBlock(block, pindex, m_mnhfManager, *m_quorum_block_processor, *m_clhandler, m_params.GetConsensus(), inputs, false /*fJustCheck*/, false /*fScriptChecks*/, state)) {
return error("RollforwardBlock(DASH): ProcessSpecialTxsInBlock for block %s failed with %s", return error("RollforwardBlock(DASH): ProcessSpecialTxsInBlock for block %s failed with %s",
pindex->GetBlockHash().ToString(), state.ToString()); pindex->GetBlockHash().ToString(), state.ToString());
} }
@ -5651,6 +5654,7 @@ std::vector<CChainState*> ChainstateManager::GetAll()
} }
CChainState& ChainstateManager::InitializeChainstate(CTxMemPool* mempool, CChainState& ChainstateManager::InitializeChainstate(CTxMemPool* mempool,
CMNHFManager& mnhfManager,
CEvoDB& evoDb, CEvoDB& evoDb,
const std::unique_ptr<llmq::CChainLocksHandler>& clhandler, const std::unique_ptr<llmq::CChainLocksHandler>& clhandler,
const std::unique_ptr<llmq::CInstantSendManager>& isman, const std::unique_ptr<llmq::CInstantSendManager>& isman,
@ -5665,7 +5669,7 @@ CChainState& ChainstateManager::InitializeChainstate(CTxMemPool* mempool,
throw std::logic_error("should not be overwriting a chainstate"); throw std::logic_error("should not be overwriting a chainstate");
} }
to_modify.reset(new CChainState(mempool, m_blockman, evoDb, clhandler, isman, quorum_block_processor, snapshot_blockhash)); to_modify.reset(new CChainState(mempool, m_blockman, mnhfManager, evoDb, clhandler, isman, quorum_block_processor, snapshot_blockhash));
// Snapshot chainstates and initial IBD chaintates always become active. // Snapshot chainstates and initial IBD chaintates always become active.
if (is_snapshot || (!is_snapshot && !m_active_chainstate)) { if (is_snapshot || (!is_snapshot && !m_active_chainstate)) {
@ -5735,9 +5739,13 @@ bool ChainstateManager::ActivateSnapshot(
} }
auto snapshot_chainstate = WITH_LOCK(::cs_main, return std::make_unique<CChainState>( auto snapshot_chainstate = WITH_LOCK(::cs_main, return std::make_unique<CChainState>(
/* mempool */ nullptr, m_blockman, this->ActiveChainstate().m_evoDb, /* mempool */ nullptr, m_blockman,
this->ActiveChainstate().m_clhandler, this->ActiveChainstate().m_isman, this->ActiveChainstate().m_mnhfManager,
this->ActiveChainstate().m_quorum_block_processor, base_blockhash this->ActiveChainstate().m_evoDb,
this->ActiveChainstate().m_clhandler,
this->ActiveChainstate().m_isman,
this->ActiveChainstate().m_quorum_block_processor,
base_blockhash
) )
); );

View File

@ -56,6 +56,7 @@ class CChainParams;
struct CCheckpointData; struct CCheckpointData;
class CInv; class CInv;
class CConnman; class CConnman;
class CMNHFManager;
class CScriptCheck; class CScriptCheck;
class CTxMemPool; class CTxMemPool;
class TxValidationState; class TxValidationState;
@ -584,6 +585,7 @@ private:
const std::unique_ptr<llmq::CChainLocksHandler>& m_clhandler; const std::unique_ptr<llmq::CChainLocksHandler>& m_clhandler;
const std::unique_ptr<llmq::CInstantSendManager>& m_isman; const std::unique_ptr<llmq::CInstantSendManager>& m_isman;
const std::unique_ptr<llmq::CQuorumBlockProcessor>& m_quorum_block_processor; const std::unique_ptr<llmq::CQuorumBlockProcessor>& m_quorum_block_processor;
CMNHFManager& m_mnhfManager;
CEvoDB& m_evoDb; CEvoDB& m_evoDb;
public: public:
@ -593,6 +595,7 @@ public:
explicit CChainState(CTxMemPool* mempool, explicit CChainState(CTxMemPool* mempool,
BlockManager& blockman, BlockManager& blockman,
CMNHFManager& mnhfManager,
CEvoDB& evoDb, CEvoDB& evoDb,
const std::unique_ptr<llmq::CChainLocksHandler>& clhandler, const std::unique_ptr<llmq::CChainLocksHandler>& clhandler,
const std::unique_ptr<llmq::CInstantSendManager>& isman, const std::unique_ptr<llmq::CInstantSendManager>& isman,
@ -940,6 +943,7 @@ public:
//! @param[in] snapshot_blockhash If given, signify that this chainstate //! @param[in] snapshot_blockhash If given, signify that this chainstate
//! is based on a snapshot. //! is based on a snapshot.
CChainState& InitializeChainstate(CTxMemPool* mempool, CChainState& InitializeChainstate(CTxMemPool* mempool,
CMNHFManager& mnhfManager,
CEvoDB& evoDb, CEvoDB& evoDb,
const std::unique_ptr<llmq::CChainLocksHandler>& clhandler, const std::unique_ptr<llmq::CChainLocksHandler>& clhandler,
const std::unique_ptr<llmq::CInstantSendManager>& isman, const std::unique_ptr<llmq::CInstantSendManager>& isman,

View File

@ -104,6 +104,7 @@ EXPECTED_CIRCULAR_DEPENDENCIES=(
"llmq/debug -> llmq/dkgsessionhandler -> llmq/debug" "llmq/debug -> llmq/dkgsessionhandler -> llmq/debug"
"llmq/debug -> llmq/dkgsessionhandler -> llmq/dkgsession -> llmq/debug" "llmq/debug -> llmq/dkgsessionhandler -> llmq/dkgsession -> llmq/debug"
"llmq/utils -> validation -> llmq/utils" "llmq/utils -> validation -> llmq/utils"
"evo/mnhftx -> validation -> evo/mnhftx"
) )
EXIT_CODE=0 EXIT_CODE=0