Skip to content
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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused, this method doesn't doesn't return any error values?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HandleNewRecoveredSig is override of interface method

[[nodiscard]] virtual MessageProcessingResult HandleNewRecoveredSig(const CRecoveredSig& recoveredSig) = 0;

which belongs to CRecoveredSigsListener.
Some classes which implements CRecoveredSigsListener has errors to return, some - doesn't. See other commits, for example: https://github.com/dashpay/dash/pull/6292/files/#diff-f7c0d20797337d77a9cfbf40c4f627ec68ed5a12e2f1193fa91c32cf285d9e34R526 - returns MisbehavingError when ProcessNewChainlock or https://github.com/dashpay/dash/pull/6292/files/#diff-93616b1f609ab7dc32d07bcdd3de3611d59bb285cbd6dba5a3bc5b4c70e6c867R131 - return TX

{
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
Loading