Skip to content

Commit

Permalink
Merge #6292: refactor: remove dependency of llmq/chainlocks, llmq/quo…
Browse files Browse the repository at this point in the history
…rum_block_processor, ehf_signals on PeerManager

c77216e docs: explain meaning of MessageProcessingResult's members (Konstantin Akimov)
d0f1778 refactor: drop dependency of EhfSignals on PeerManager (Konstantin Akimov)
1d13f01 refactor: remove dependency of QuorumBlockProcessor on PeerManager (Konstantin Akimov)
f1c6d17 refactor: remove dependency of chainlocks on PeerManager (Konstantin Akimov)
5383421 refactor: HandleNewRecoveredSig return PostProcessingMessage (Konstantin Akimov)
09565fe refactor: new type of message processing result for resolving circular dependency over PeerManager (Konstantin Akimov)
d54b3ee refactor: move ChainLocksSigningEnabled from header to cpp file as static function (Konstantin Akimov)
cab700a refactor: remove unused include spork.h from validation.cpp (Konstantin Akimov)

Pull request description:

  ## Issue being fixed or feature implemented
  It reduces circular dependencies and simplify code.

  ## What was done?
  Removed circular dependency over PeerManager for llmq::QuorumBlockProcessor, llmq::CEhfSignals, llmq::ChainLocks, and several extra useful refactorings: see commits.

  ## How Has This Been Tested?
  Run `test/lint/lint-circular-dependencies.sh`

  ## Breaking Changes
  N/A

  ## Checklist:
  - [x] I have performed a self-review of my own code
  - [x] I have commented my code, particularly in hard-to-understand areas
  - [x] I have added or updated relevant unit/integration/functional/e2e tests
  - [x] I have made corresponding changes to the documentation
  - [x] I have assigned this pull request to a milestone

ACKs for top commit:
  UdjinM6:
    utACK c77216e
  PastaPastaPasta:
    utACK c77216e

Tree-SHA512: e01829a694c9bfbbe70bc346ef5949b5e9e4532560f4c40ee292952f05f0fd23ecf4bd978e918f74dd3422c1b90231fd7d9984f491f3ab8f7eb08072540406b4
  • Loading branch information
PastaPastaPasta committed Oct 4, 2024
2 parents e5daf4a + c77216e commit 74e54b8
Show file tree
Hide file tree
Showing 26 changed files with 183 additions and 154 deletions.
2 changes: 1 addition & 1 deletion src/coinjoin/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include <coinjoin/util.h>
#include <coinjoin/coinjoin.h>

#include <net_types.h>
#include <protocol.h>
#include <util/ranges.h>
#include <util/translation.h>

Expand Down
2 changes: 1 addition & 1 deletion src/coinjoin/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

#include <coinjoin/coinjoin.h>

#include <net_types.h>
#include <protocol.h>

class CActiveMasternodeManager;
class CChainState;
Expand Down
2 changes: 1 addition & 1 deletion src/evo/mnauth.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#define BITCOIN_EVO_MNAUTH_H

#include <bls/bls.h>
#include <net_types.h>
#include <protocol.h>
#include <serialize.h>

class CActiveMasternodeManager;
Expand Down
2 changes: 1 addition & 1 deletion src/governance/governance.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

#include <cachemap.h>
#include <cachemultimap.h>
#include <net_types.h>
#include <protocol.h>
#include <util/check.h>

#include <optional>
Expand Down
57 changes: 26 additions & 31 deletions src/llmq/blockprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
#include <consensus/validation.h>
#include <deploymentstatus.h>
#include <net.h>
#include <net_processing.h>
#include <primitives/block.h>
#include <primitives/transaction.h>
#include <saltedhasher.h>
Expand Down Expand Up @@ -44,14 +43,16 @@ static const std::string DB_MINED_COMMITMENT_BY_INVERSED_HEIGHT_Q_INDEXED = "q_m

static const std::string DB_BEST_BLOCK_UPGRADE = "q_bbu2";

CQuorumBlockProcessor::CQuorumBlockProcessor(CChainState& chainstate, CDeterministicMNManager& dmnman, CEvoDB& evoDb,
const std::unique_ptr<PeerManager>& peerman) :
m_chainstate(chainstate), m_dmnman(dmnman), m_evoDb(evoDb), m_peerman(peerman)
CQuorumBlockProcessor::CQuorumBlockProcessor(CChainState& chainstate, CDeterministicMNManager& dmnman, CEvoDB& evoDb) :
m_chainstate(chainstate),
m_dmnman(dmnman),
m_evoDb(evoDb)
{
utils::InitQuorumsCache(mapHasMinedCommitmentCache);
}

PeerMsgRet CQuorumBlockProcessor::ProcessMessage(const CNode& peer, std::string_view msg_type, CDataStream& vRecv)
MessageProcessingResult CQuorumBlockProcessor::ProcessMessage(const CNode& peer, std::string_view msg_type,
CDataStream& vRecv)
{
if (msg_type != NetMsgType::QFCOMMITMENT) {
return {};
Expand All @@ -60,19 +61,21 @@ PeerMsgRet CQuorumBlockProcessor::ProcessMessage(const CNode& peer, std::string_
CFinalCommitment qc;
vRecv >> qc;

WITH_LOCK(::cs_main, Assert(m_peerman)->EraseObjectRequest(peer.GetId(),
CInv(MSG_QUORUM_FINAL_COMMITMENT, ::SerializeHash(qc))));
MessageProcessingResult ret;
ret.m_to_erase = CInv{MSG_QUORUM_FINAL_COMMITMENT, ::SerializeHash(qc)};

if (qc.IsNull()) {
LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- null commitment from peer=%d\n", __func__, peer.GetId());
return tl::unexpected{100};
ret.m_error = MisbehavingError{100};
return ret;
}

const auto& llmq_params_opt = Params().GetLLMQ(qc.llmqType);
if (!llmq_params_opt.has_value()) {
LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- invalid commitment type %d from peer=%d\n", __func__,
ToUnderlying(qc.llmqType), peer.GetId());
return tl::unexpected{100};
ret.m_error = MisbehavingError{100};
return ret;
}
auto type = qc.llmqType;

Expand All @@ -86,32 +89,33 @@ PeerMsgRet CQuorumBlockProcessor::ProcessMessage(const CNode& peer, std::string_
qc.quorumHash.ToString(), peer.GetId());
// can't really punish the node here, as we might simply be the one that is on the wrong chain or not
// fully synced
return {};
return ret;
}
if (m_chainstate.m_chain.Tip()->GetAncestor(pQuorumBaseBlockIndex->nHeight) != pQuorumBaseBlockIndex) {
LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- block %s not in active chain, peer=%d\n", __func__,
qc.quorumHash.ToString(), peer.GetId());
// same, can't punish
return {};
return ret;
}
if (int quorumHeight = pQuorumBaseBlockIndex->nHeight - (pQuorumBaseBlockIndex->nHeight % llmq_params_opt->dkgInterval) + int(qc.quorumIndex);
quorumHeight != pQuorumBaseBlockIndex->nHeight) {
LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- block %s is not the first block in the DKG interval, peer=%d\n", __func__,
qc.quorumHash.ToString(), peer.GetId());
return tl::unexpected{100};
ret.m_error = MisbehavingError{100};
return ret;
}
if (pQuorumBaseBlockIndex->nHeight < (m_chainstate.m_chain.Height() - llmq_params_opt->dkgInterval)) {
LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- block %s is too old, peer=%d\n", __func__,
qc.quorumHash.ToString(), peer.GetId());
// TODO: enable punishment in some future version when all/most nodes are running with this fix
// return tl::unexpected{100};
return {};
// ret.m_error = MisbehavingError{100};
return ret;
}
if (HasMinedCommitment(type, qc.quorumHash)) {
LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- commitment for quorum hash[%s], type[%d], quorumIndex[%d] is already mined, peer=%d\n",
__func__, qc.quorumHash.ToString(), ToUnderlying(type), qc.quorumIndex, peer.GetId());
// NOTE: do not punish here
return {};
return ret;
}
}

Expand All @@ -124,7 +128,7 @@ PeerMsgRet CQuorumBlockProcessor::ProcessMessage(const CNode& peer, std::string_
if (it != minableCommitmentsByQuorum.end()) {
auto jt = minableCommitments.find(it->second);
if (jt != minableCommitments.end() && jt->second.CountSigners() <= qc.CountSigners()) {
return {};
return ret;
}
}
}
Expand All @@ -133,14 +137,15 @@ PeerMsgRet CQuorumBlockProcessor::ProcessMessage(const CNode& peer, std::string_
LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- commitment for quorum %s:%d is not valid quorumIndex[%d] nversion[%d], peer=%d\n",
__func__, qc.quorumHash.ToString(),
ToUnderlying(qc.llmqType), qc.quorumIndex, qc.nVersion, peer.GetId());
return tl::unexpected{100};
ret.m_error = MisbehavingError{100};
return ret;
}

LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- received commitment for quorum %s:%d, validMembers=%d, signers=%d, peer=%d\n", __func__,
qc.quorumHash.ToString(), ToUnderlying(qc.llmqType), qc.CountValidMembers(), qc.CountSigners(), peer.GetId());

AddMineableCommitmentAndRelay(qc);
return {};
ret.m_inventory = AddMineableCommitment(qc);
return ret;
}

bool CQuorumBlockProcessor::ProcessBlock(const CBlock& block, gsl::not_null<const CBlockIndex*> pindex, BlockValidationState& state, bool fJustCheck, bool fBLSChecks)
Expand Down Expand Up @@ -637,7 +642,7 @@ bool CQuorumBlockProcessor::HasMineableCommitment(const uint256& hash) const
return minableCommitments.count(hash) != 0;
}

std::optional<uint256> CQuorumBlockProcessor::AddMineableCommitment(const CFinalCommitment& fqc)
std::optional<CInv> CQuorumBlockProcessor::AddMineableCommitment(const CFinalCommitment& fqc)
{
const uint256 commitmentHash = ::SerializeHash(fqc);

Expand All @@ -663,17 +668,7 @@ std::optional<uint256> CQuorumBlockProcessor::AddMineableCommitment(const CFinal
return false;
}();

return relay ? std::make_optional(commitmentHash) : std::nullopt;
}

void CQuorumBlockProcessor::AddMineableCommitmentAndRelay(const CFinalCommitment& fqc)
{
const auto commitmentHashOpt = AddMineableCommitment(fqc);
// We only relay the new commitment if it's new or better then the old one
if (commitmentHashOpt) {
CInv inv(MSG_QUORUM_FINAL_COMMITMENT, *commitmentHashOpt);
Assert(m_peerman)->RelayInv(inv);
}
return relay ? std::make_optional(CInv{MSG_QUORUM_FINAL_COMMITMENT, commitmentHash}) : std::nullopt;
}

bool CQuorumBlockProcessor::GetMineableCommitmentByHash(const uint256& commitmentHash, llmq::CFinalCommitment& ret) const
Expand Down
14 changes: 5 additions & 9 deletions src/llmq/blockprocessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

#include <chain.h>
#include <consensus/params.h>
#include <net_types.h>
#include <primitives/block.h>
#include <protocol.h>
#include <saltedhasher.h>
#include <sync.h>

Expand All @@ -26,7 +26,6 @@ class CDataStream;
class CDeterministicMNManager;
class CEvoDB;
class CNode;
class PeerManager;

extern RecursiveMutex cs_main;

Expand All @@ -42,7 +41,6 @@ class CQuorumBlockProcessor
CChainState& m_chainstate;
CDeterministicMNManager& m_dmnman;
CEvoDB& m_evoDb;
const std::unique_ptr<PeerManager>& m_peerman;

mutable Mutex minableCommitmentsCs;
std::map<std::pair<Consensus::LLMQType, uint256>, uint256> minableCommitmentsByQuorum GUARDED_BY(minableCommitmentsCs);
Expand All @@ -51,15 +49,15 @@ class CQuorumBlockProcessor
mutable std::map<Consensus::LLMQType, unordered_lru_cache<uint256, bool, StaticSaltedHasher>> mapHasMinedCommitmentCache GUARDED_BY(minableCommitmentsCs);

public:
explicit CQuorumBlockProcessor(CChainState& chainstate, CDeterministicMNManager& dmnman, CEvoDB& evoDb,
const std::unique_ptr<PeerManager>& peerman);
explicit CQuorumBlockProcessor(CChainState& chainstate, CDeterministicMNManager& dmnman, CEvoDB& evoDb);

PeerMsgRet ProcessMessage(const CNode& peer, std::string_view msg_type, CDataStream& vRecv);
MessageProcessingResult ProcessMessage(const CNode& peer, std::string_view msg_type, CDataStream& vRecv);

bool ProcessBlock(const CBlock& block, gsl::not_null<const CBlockIndex*> pindex, BlockValidationState& state, bool fJustCheck, bool fBLSChecks) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool UndoBlock(const CBlock& block, gsl::not_null<const CBlockIndex*> pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);

void AddMineableCommitmentAndRelay(const CFinalCommitment& fqc);
//! it returns hash of commitment if it should be relay, otherwise nullopt
std::optional<CInv> AddMineableCommitment(const CFinalCommitment& fqc);
bool HasMineableCommitment(const uint256& hash) const;
bool GetMineableCommitmentByHash(const uint256& commitmentHash, CFinalCommitment& ret) const;
std::optional<std::vector<CFinalCommitment>> GetMineableCommitments(const Consensus::LLMQParams& llmqParams, int nHeight) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
Expand All @@ -74,8 +72,6 @@ class CQuorumBlockProcessor
std::vector<std::pair<int, const CBlockIndex*>> GetLastMinedCommitmentsPerQuorumIndexUntilBlock(Consensus::LLMQType llmqType, const CBlockIndex* pindex, size_t cycle) const;
std::optional<const CBlockIndex*> GetLastMinedCommitmentsByQuorumIndexUntilBlock(Consensus::LLMQType llmqType, const CBlockIndex* pindex, int quorumIndex, size_t cycle) const;
private:
//! it returns hash of commitment if it should be relay, otherwise nullopt
std::optional<uint256> AddMineableCommitment(const CFinalCommitment& fqc);
static bool GetCommitmentsFromBlock(const CBlock& block, gsl::not_null<const CBlockIndex*> pindex, std::multimap<Consensus::LLMQType, CFinalCommitment>& ret, BlockValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool ProcessCommitment(int nHeight, const uint256& blockHash, const CFinalCommitment& qc, BlockValidationState& state, bool fJustCheck, bool fBLSChecks) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
static bool IsMiningPhase(const Consensus::LLMQParams& llmqParams, const CChain& active_chain, int nHeight) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
Expand Down
62 changes: 19 additions & 43 deletions src/llmq/chainlocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include <chainparams.h>
#include <consensus/validation.h>
#include <masternode/sync.h>
#include <net_processing.h>
#include <node/blockstorage.h>
#include <node/ui_interface.h>
#include <scheduler.h>
Expand All @@ -23,25 +22,29 @@
#include <validation.h>
#include <validationinterface.h>

static bool ChainLocksSigningEnabled(const CSporkManager& sporkman)
{
return sporkman.GetSporkValue(SPORK_19_CHAINLOCKS_ENABLED) == 0;
}

namespace llmq
{
std::unique_ptr<CChainLocksHandler> chainLocksHandler;

CChainLocksHandler::CChainLocksHandler(CChainState& chainstate, CQuorumManager& _qman, CSigningManager& _sigman,
CSigSharesManager& _shareman, CSporkManager& sporkman, CTxMemPool& _mempool,
const CMasternodeSync& mn_sync, const std::unique_ptr<PeerManager>& peerman,
bool is_masternode) :
const CMasternodeSync& mn_sync, bool is_masternode) :
m_chainstate(chainstate),
qman(_qman),
sigman(_sigman),
shareman(_shareman),
spork_manager(sporkman),
mempool(_mempool),
m_mn_sync(mn_sync),
m_peerman(peerman),
m_is_masternode{is_masternode},
scheduler(std::make_unique<CScheduler>()),
scheduler_thread(std::make_unique<std::thread>(std::thread(util::TraceThread, "cl-schdlr", [&] { scheduler->serviceQueue(); })))
scheduler_thread(
std::make_unique<std::thread>(std::thread(util::TraceThread, "cl-schdlr", [&] { scheduler->serviceQueue(); })))
{
}

Expand Down Expand Up @@ -93,31 +96,11 @@ CChainLockSig CChainLocksHandler::GetBestChainLock() const
return bestChainLock;
}

PeerMsgRet CChainLocksHandler::ProcessMessage(const CNode& pfrom, const std::string& msg_type, CDataStream& vRecv)
{
if (!AreChainLocksEnabled(spork_manager)) {
return {};
}

if (msg_type == NetMsgType::CLSIG) {
CChainLockSig clsig;
vRecv >> clsig;

return ProcessNewChainLock(pfrom.GetId(), clsig, ::SerializeHash(clsig));
}
return {};
}

PeerMsgRet CChainLocksHandler::ProcessNewChainLock(const NodeId from, const llmq::CChainLockSig& clsig, const uint256& hash)
MessageProcessingResult CChainLocksHandler::ProcessNewChainLock(const NodeId from, const llmq::CChainLockSig& clsig,
const uint256& hash)
{
CheckActiveState();

CInv clsigInv(MSG_CLSIG, hash);

if (from != -1) {
WITH_LOCK(::cs_main, Assert(m_peerman)->EraseObjectRequest(from, clsigInv));
}

{
LOCK(cs);
if (!seenChainLocks.emplace(hash, GetTimeMillis()).second) {
Expand All @@ -133,7 +116,7 @@ PeerMsgRet CChainLocksHandler::ProcessNewChainLock(const NodeId from, const llmq
if (const auto ret = VerifyChainLock(clsig); ret != VerifyRecSigStatus::Valid) {
LogPrint(BCLog::CHAINLOCKS, "CChainLocksHandler::%s -- invalid CLSIG (%s), status=%d peer=%d\n", __func__, clsig.ToString(), ToUnderlying(ret), from);
if (from != -1) {
return tl::unexpected{10};
return MisbehavingError{10};
}
return {};
}
Expand Down Expand Up @@ -162,14 +145,12 @@ PeerMsgRet CChainLocksHandler::ProcessNewChainLock(const NodeId from, const llmq
// Note: make sure to still relay clsig further.
}

// Note: do not hold cs while calling RelayInv
AssertLockNotHeld(cs);
Assert(m_peerman)->RelayInv(clsigInv);
CInv clsigInv(MSG_CLSIG, hash);

if (pindex == nullptr) {
// we don't know the block/header for this CLSIG yet, so bail out for now
// when the block or the header later comes in, we will enforce the correct chain
return {};
return clsigInv;
}

scheduler->scheduleFromNow([&]() {
Expand All @@ -179,7 +160,7 @@ PeerMsgRet CChainLocksHandler::ProcessNewChainLock(const NodeId from, const llmq

LogPrint(BCLog::CHAINLOCKS, "CChainLocksHandler::%s -- processed new CLSIG (%s), peer=%d\n",
__func__, clsig.ToString(), from);
return {};
return clsigInv;
}

void CChainLocksHandler::AcceptedBlockHeader(gsl::not_null<const CBlockIndex*> pindexNew)
Expand Down Expand Up @@ -520,10 +501,10 @@ void CChainLocksHandler::EnforceBestChainLock()
uiInterface.NotifyChainLock(clsig->getBlockHash().ToString(), clsig->getHeight());
}

void CChainLocksHandler::HandleNewRecoveredSig(const llmq::CRecoveredSig& recoveredSig)
MessageProcessingResult CChainLocksHandler::HandleNewRecoveredSig(const llmq::CRecoveredSig& recoveredSig)
{
if (!isEnabled) {
return;
return {};
}

CChainLockSig clsig;
Expand All @@ -532,17 +513,17 @@ void CChainLocksHandler::HandleNewRecoveredSig(const llmq::CRecoveredSig& recove

if (recoveredSig.getId() != lastSignedRequestId || recoveredSig.getMsgHash() != lastSignedMsgHash) {
// this is not what we signed, so lets not create a CLSIG for it
return;
return {};
}
if (bestChainLock.getHeight() >= lastSignedHeight) {
// already got the same or a better CLSIG through the CLSIG message
return;
return {};
}


clsig = CChainLockSig(lastSignedHeight, lastSignedMsgHash, recoveredSig.sig.Get());
}
ProcessNewChainLock(-1, clsig, ::SerializeHash(clsig));
return ProcessNewChainLock(-1, clsig, ::SerializeHash(clsig));
}

bool CChainLocksHandler::HasChainLock(int nHeight, const uint256& blockHash) const
Expand Down Expand Up @@ -678,9 +659,4 @@ bool AreChainLocksEnabled(const CSporkManager& sporkman)
return sporkman.IsSporkActive(SPORK_19_CHAINLOCKS_ENABLED);
}

bool ChainLocksSigningEnabled(const CSporkManager& sporkman)
{
return sporkman.GetSporkValue(SPORK_19_CHAINLOCKS_ENABLED) == 0;
}

} // namespace llmq
Loading

0 comments on commit 74e54b8

Please sign in to comment.