mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 03:52:49 +01:00
Merge #6132: refactor: trim and document assumptions for GetQuorum
, Get
*MN
* and friends
a014cf3703
refactor: trim and document assumptions for `Get`*`MN`* and friends (Kittywhiskers Van Gogh)8c9f57dac4
refactor: trim and document assumptions for `GetQuorum` and friends (Kittywhiskers Van Gogh) Pull request description: ## Additional Information This pull request aims to document assumptions when handling `CDeterministicMNCPtr` and `CQuorumCPtr` entities, which can be `nullptr`. In some instances, mishandling or missing validation logic can result in an assertion failure or a null pointer dereference (in both circumstances, the client will crash). While in other cases, assumptions are made based on prior code that affirms that the returned value will be valid. For the former, bail-out logic has been introduced and for the latter, assertions and code comments have been added. ## 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 **(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: knst: utACKa014cf3703
UdjinM6: utACKa014cf3703
Tree-SHA512: e21824d61d81c4ca4b5b4a545a833932946eb0f279d15c586bb5eae96aefcc88d1e3b3fdfa7a01d161f1650351a7cac4bc917b2d1109d77ea2eedd8408d8f37d
This commit is contained in:
commit
c44ae90cd5
@ -140,7 +140,8 @@ bool CAssetUnlockPayload::VerifySig(const llmq::CQuorumManager& qman, const uint
|
||||
const auto quorum = qman.GetQuorum(llmqType, quorumHash);
|
||||
// quorum must be valid at this point. Let's check and throw error just in case
|
||||
if (!quorum) {
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "internal-error");
|
||||
LogPrintf("%s: ERROR! No quorum for credit pool found for hash=%s\n", __func__, quorumHash.ToString());
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-assetunlock-quorum-internal-error");
|
||||
}
|
||||
|
||||
const uint256 requestId = ::SerializeHash(std::make_pair(ASSETUNLOCK_REQUESTID_PREFIX, index));
|
||||
|
@ -428,7 +428,7 @@ CDeterministicMNList CDeterministicMNList::ApplyDiff(gsl::not_null<const CBlockI
|
||||
for (const auto& id : diff.removedMns) {
|
||||
auto dmn = result.GetMNByInternalId(id);
|
||||
if (!dmn) {
|
||||
throw(std::runtime_error(strprintf("%s: can't find a removed masternode, id=%d", __func__, id)));
|
||||
throw std::runtime_error(strprintf("%s: can't find a removed masternode, id=%d", __func__, id));
|
||||
}
|
||||
result.RemoveMN(dmn->proTxHash);
|
||||
}
|
||||
@ -437,6 +437,9 @@ CDeterministicMNList CDeterministicMNList::ApplyDiff(gsl::not_null<const CBlockI
|
||||
}
|
||||
for (const auto& p : diff.updatedMNs) {
|
||||
auto dmn = result.GetMNByInternalId(p.first);
|
||||
if (!dmn) {
|
||||
throw std::runtime_error(strprintf("%s: can't find an updated masternode, id=%d", __func__, p.first));
|
||||
}
|
||||
result.UpdateMN(*dmn, p.second);
|
||||
}
|
||||
|
||||
@ -818,7 +821,7 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no
|
||||
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-dup-addr");
|
||||
}
|
||||
|
||||
CDeterministicMNCPtr dmn = newList.GetMN(opt_proTx->proTxHash);
|
||||
auto dmn = newList.GetMN(opt_proTx->proTxHash);
|
||||
if (!dmn) {
|
||||
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-hash");
|
||||
}
|
||||
@ -859,7 +862,7 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no
|
||||
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-payload");
|
||||
}
|
||||
|
||||
CDeterministicMNCPtr dmn = newList.GetMN(opt_proTx->proTxHash);
|
||||
auto dmn = newList.GetMN(opt_proTx->proTxHash);
|
||||
if (!dmn) {
|
||||
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-hash");
|
||||
}
|
||||
@ -887,7 +890,7 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no
|
||||
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-payload");
|
||||
}
|
||||
|
||||
CDeterministicMNCPtr dmn = newList.GetMN(opt_proTx->proTxHash);
|
||||
auto dmn = newList.GetMN(opt_proTx->proTxHash);
|
||||
if (!dmn) {
|
||||
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-hash");
|
||||
}
|
||||
@ -947,6 +950,8 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no
|
||||
// current block. We still pay that MN one last time, however.
|
||||
if (payee && newList.HasMN(payee->proTxHash)) {
|
||||
auto dmn = newList.GetMN(payee->proTxHash);
|
||||
// HasMN has reported that GetMN should succeed, enforce that.
|
||||
assert(dmn);
|
||||
auto newState = std::make_shared<CDeterministicMNState>(*dmn->pdmnState);
|
||||
newState->nLastPaidHeight = nHeight;
|
||||
// Starting from v19 and until MNRewardReallocation, EvoNodes will be paid 4 blocks in a row
|
||||
@ -962,6 +967,9 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no
|
||||
newList.UpdateMN(payee->proTxHash, newState);
|
||||
if (debugLogs) {
|
||||
dmn = newList.GetMN(payee->proTxHash);
|
||||
// Since the previous GetMN query returned a value, after an update, querying the same
|
||||
// hash *must* give us a result. If it doesn't, that would be a potential logic bug.
|
||||
assert(dmn);
|
||||
LogPrint(BCLog::MNPAYMENTS, "CDeterministicMNManager::%s -- MN %s, nConsecutivePayments=%d\n",
|
||||
__func__, dmn->proTxHash.ToString(), dmn->pdmnState->nConsecutivePayments);
|
||||
}
|
||||
|
@ -96,6 +96,10 @@ bool MNHFTx::Verify(const llmq::CQuorumManager& qman, const uint256& quorumHash,
|
||||
const Consensus::LLMQType& llmqType = Params().GetConsensus().llmqTypeMnhf;
|
||||
const auto quorum = qman.GetQuorum(llmqType, quorumHash);
|
||||
|
||||
if (!quorum) {
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-missing-quorum");
|
||||
}
|
||||
|
||||
const uint256 signHash = llmq::BuildSignHash(llmqType, quorum->qc->quorumHash, requestId, msgHash);
|
||||
if (!sig.VerifyInsecure(quorum->qc->quorumPublicKey, signHash)) {
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-invalid");
|
||||
|
@ -187,14 +187,23 @@ bool CSimplifiedMNListDiff::BuildQuorumsDiff(const CBlockIndex* baseBlockIndex,
|
||||
return true;
|
||||
}
|
||||
|
||||
void CSimplifiedMNListDiff::BuildQuorumChainlockInfo(const llmq::CQuorumManager& qman, const CBlockIndex* blockIndex)
|
||||
bool CSimplifiedMNListDiff::BuildQuorumChainlockInfo(const llmq::CQuorumManager& qman, const CBlockIndex* blockIndex)
|
||||
{
|
||||
// Group quorums (indexes corresponding to entries of newQuorums) per CBlockIndex containing the expected CL signature in CbTx.
|
||||
// We want to avoid to load CbTx now, as more than one quorum will target the same block: hence we want to load CbTxs once per block (heavy operation).
|
||||
std::multimap<const CBlockIndex*, uint16_t> workBaseBlockIndexMap;
|
||||
|
||||
for (const auto [idx, e] : enumerate(newQuorums)) {
|
||||
// We assume that we have on hand, quorums that correspond to the hashes queried.
|
||||
// If we cannot find them, something must have gone wrong and we should cease trying
|
||||
// to build any further.
|
||||
auto quorum = qman.GetQuorum(e.llmqType, e.quorumHash);
|
||||
if (!quorum) {
|
||||
LogPrintf("%s: ERROR! Unexpected missing quorum with llmqType=%d, quorumHash=%s\n", __func__,
|
||||
ToUnderlying(e.llmqType), e.quorumHash.ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
// In case of rotation, all rotated quorums rely on the CL sig expected in the cycleBlock (the block of the first DKG) - 8
|
||||
// In case of non-rotation, quorums rely on the CL sig expected in the block of the DKG - 8
|
||||
const CBlockIndex* pWorkBaseBlockIndex =
|
||||
@ -203,7 +212,7 @@ void CSimplifiedMNListDiff::BuildQuorumChainlockInfo(const llmq::CQuorumManager&
|
||||
workBaseBlockIndexMap.insert(std::make_pair(pWorkBaseBlockIndex, idx));
|
||||
}
|
||||
|
||||
for(auto it = workBaseBlockIndexMap.begin(); it != workBaseBlockIndexMap.end(); ) {
|
||||
for (auto it = workBaseBlockIndexMap.begin(); it != workBaseBlockIndexMap.end();) {
|
||||
// Process each key (CBlockIndex containing the expected CL signature in CbTx) of the std::multimap once
|
||||
const CBlockIndex* pWorkBaseBlockIndex = it->first;
|
||||
const auto cbcl = GetNonNullCoinbaseChainlock(pWorkBaseBlockIndex);
|
||||
@ -224,6 +233,8 @@ void CSimplifiedMNListDiff::BuildQuorumChainlockInfo(const llmq::CQuorumManager&
|
||||
it_sig->second.insert(idx_set.begin(), idx_set.end());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
UniValue CSimplifiedMNListDiff::ToJson(bool extended) const
|
||||
@ -366,7 +377,10 @@ bool BuildSimplifiedMNListDiff(CDeterministicMNManager& dmnman, const Chainstate
|
||||
}
|
||||
|
||||
if (DeploymentActiveAfter(blockIndex, Params().GetConsensus(), Consensus::DEPLOYMENT_V20)) {
|
||||
mnListDiffRet.BuildQuorumChainlockInfo(qman, blockIndex);
|
||||
if (!mnListDiffRet.BuildQuorumChainlockInfo(qman, blockIndex)) {
|
||||
errorRet = strprintf("failed to build quorum chainlock info");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO store coinbase TX in CBlockIndex
|
||||
|
@ -170,7 +170,7 @@ public:
|
||||
|
||||
bool BuildQuorumsDiff(const CBlockIndex* baseBlockIndex, const CBlockIndex* blockIndex,
|
||||
const llmq::CQuorumBlockProcessor& quorum_block_processor);
|
||||
void BuildQuorumChainlockInfo(const llmq::CQuorumManager& qman, const CBlockIndex* blockIndex);
|
||||
bool BuildQuorumChainlockInfo(const llmq::CQuorumManager& qman, const CBlockIndex* blockIndex);
|
||||
|
||||
[[nodiscard]] UniValue ToJson(bool extended = false) const;
|
||||
};
|
||||
|
@ -1601,6 +1601,9 @@ void CGovernanceManager::RemoveInvalidVotes()
|
||||
std::vector<COutPoint> changedKeyMNs;
|
||||
for (const auto& p : diff.updatedMNs) {
|
||||
auto oldDmn = lastMNListForVotingKeys->GetMNByInternalId(p.first);
|
||||
// BuildDiff will construct itself with MNs that we already have knowledge
|
||||
// of, meaning that fetch operations should never fail.
|
||||
assert(oldDmn);
|
||||
if ((p.second.fields & CDeterministicMNStateDiff::Field_keyIDVoting) && p.second.state.keyIDVoting != oldDmn->pdmnState->keyIDVoting) {
|
||||
changedKeyMNs.emplace_back(oldDmn->collateralOutpoint);
|
||||
} else if ((p.second.fields & CDeterministicMNStateDiff::Field_pubKeyOperator) && p.second.state.pubKeyOperator != oldDmn->pdmnState->pubKeyOperator) {
|
||||
@ -1609,6 +1612,9 @@ void CGovernanceManager::RemoveInvalidVotes()
|
||||
}
|
||||
for (const auto& id : diff.removedMns) {
|
||||
auto oldDmn = lastMNListForVotingKeys->GetMNByInternalId(id);
|
||||
// BuildDiff will construct itself with MNs that we already have knowledge
|
||||
// of, meaning that fetch operations should never fail.
|
||||
assert(oldDmn);
|
||||
changedKeyMNs.emplace_back(oldDmn->collateralOutpoint);
|
||||
}
|
||||
|
||||
|
@ -602,8 +602,17 @@ std::vector<CQuorumCPtr> CQuorumManager::ScanQuorums(Consensus::LLMQType llmqTyp
|
||||
assert(pQuorumBaseBlockIndex);
|
||||
// populate cache for keepOldConnections most recent quorums only
|
||||
bool populate_cache = vecResultQuorums.size() < static_cast<size_t>(llmq_params_opt->keepOldConnections);
|
||||
|
||||
// We assume that every quorum asked for is available to us on hand, if this
|
||||
// fails then we can assume that something has gone wrong and we should stop
|
||||
// trying to process any further and return a blank.
|
||||
auto quorum = GetQuorum(llmqType, pQuorumBaseBlockIndex, populate_cache);
|
||||
assert(quorum != nullptr);
|
||||
if (!quorum) {
|
||||
LogPrintf("%s: ERROR! Unexpected missing quorum with llmqType=%d, blockHash=%s, populate_cache=%s\n",
|
||||
__func__, ToUnderlying(llmqType), pQuorumBaseBlockIndex->GetBlockHash().ToString(),
|
||||
populate_cache ? "true" : "false");
|
||||
return {};
|
||||
}
|
||||
vecResultQuorums.emplace_back(quorum);
|
||||
}
|
||||
|
||||
@ -742,7 +751,7 @@ PeerMsgRet CQuorumManager::ProcessMessage(CNode& pfrom, const std::string& msg_t
|
||||
return sendQDATA(CQuorumDataRequest::Errors::QUORUM_BLOCK_NOT_FOUND, request_limit_exceeded);
|
||||
}
|
||||
|
||||
const CQuorumCPtr pQuorum = GetQuorum(request.GetLLMQType(), pQuorumBaseBlockIndex);
|
||||
const auto pQuorum = GetQuorum(request.GetLLMQType(), pQuorumBaseBlockIndex);
|
||||
if (pQuorum == nullptr) {
|
||||
return sendQDATA(CQuorumDataRequest::Errors::QUORUM_NOT_FOUND, request_limit_exceeded);
|
||||
}
|
||||
|
@ -588,7 +588,7 @@ static bool PreVerifyRecoveredSig(const CQuorumManager& quorum_manager, const CR
|
||||
return false;
|
||||
}
|
||||
|
||||
CQuorumCPtr quorum = quorum_manager.GetQuorum(llmqType, recoveredSig.getQuorumHash());
|
||||
auto quorum = quorum_manager.GetQuorum(llmqType, recoveredSig.getQuorumHash());
|
||||
|
||||
if (!quorum) {
|
||||
LogPrint(BCLog::LLMQ, "CSigningManager::%s -- quorum %s not found\n", __func__,
|
||||
@ -681,7 +681,7 @@ void CSigningManager::CollectPendingRecoveredSigsToVerify(
|
||||
auto llmqType = recSig->getLlmqType();
|
||||
auto quorumKey = std::make_pair(recSig->getLlmqType(), recSig->getQuorumHash());
|
||||
if (!retQuorums.count(quorumKey)) {
|
||||
CQuorumCPtr quorum = qman.GetQuorum(llmqType, recSig->getQuorumHash());
|
||||
auto quorum = qman.GetQuorum(llmqType, recSig->getQuorumHash());
|
||||
if (!quorum) {
|
||||
LogPrint(BCLog::LLMQ, "CSigningManager::%s -- quorum %s not found, node=%d\n", __func__,
|
||||
recSig->getQuorumHash().ToString(), nodeId);
|
||||
@ -881,7 +881,7 @@ bool CSigningManager::AsyncSignIfMember(Consensus::LLMQType llmqType, CSigShares
|
||||
if (m_mn_activeman == nullptr) return false;
|
||||
if (m_mn_activeman->GetProTxHash().IsNull()) return false;
|
||||
|
||||
const CQuorumCPtr quorum = [&]() {
|
||||
const auto quorum = [&]() {
|
||||
if (quorumHash.IsNull()) {
|
||||
// This might end up giving different results on different members
|
||||
// This might happen when we are on the brink of confirming a new quorum
|
||||
|
@ -549,15 +549,14 @@ bool CSigSharesManager::PreVerifyBatchedSigShares(const CActiveMasternodeManager
|
||||
return true;
|
||||
}
|
||||
|
||||
void CSigSharesManager::CollectPendingSigSharesToVerify(
|
||||
size_t maxUniqueSessions,
|
||||
std::unordered_map<NodeId, std::vector<CSigShare>>& retSigShares,
|
||||
bool CSigSharesManager::CollectPendingSigSharesToVerify(
|
||||
size_t maxUniqueSessions, std::unordered_map<NodeId, std::vector<CSigShare>>& retSigShares,
|
||||
std::unordered_map<std::pair<Consensus::LLMQType, uint256>, CQuorumCPtr, StaticSaltedHasher>& retQuorums)
|
||||
{
|
||||
{
|
||||
LOCK(cs);
|
||||
if (nodeStates.empty()) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// This will iterate node states in random order and pick one sig share at a time. This avoids processing
|
||||
@ -590,7 +589,7 @@ void CSigSharesManager::CollectPendingSigSharesToVerify(
|
||||
rnd);
|
||||
|
||||
if (retSigShares.empty()) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -605,11 +604,20 @@ void CSigSharesManager::CollectPendingSigSharesToVerify(
|
||||
continue;
|
||||
}
|
||||
|
||||
CQuorumCPtr quorum = qman.GetQuorum(llmqType, sigShare.getQuorumHash());
|
||||
assert(quorum != nullptr);
|
||||
auto quorum = qman.GetQuorum(llmqType, sigShare.getQuorumHash());
|
||||
// Despite constructing a convenience map, we assume that the quorum *must* be present.
|
||||
// The absence of it might indicate an inconsistent internal state, so we should report
|
||||
// nothing instead of reporting flawed data.
|
||||
if (!quorum) {
|
||||
LogPrintf("%s: ERROR! Unexpected missing quorum with llmqType=%d, quorumHash=%s\n", __func__,
|
||||
ToUnderlying(llmqType), sigShare.getQuorumHash().ToString());
|
||||
return false;
|
||||
}
|
||||
retQuorums.try_emplace(k, quorum);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSigSharesManager::ProcessPendingSigShares(const CConnman& connman)
|
||||
@ -618,8 +626,8 @@ bool CSigSharesManager::ProcessPendingSigShares(const CConnman& connman)
|
||||
std::unordered_map<std::pair<Consensus::LLMQType, uint256>, CQuorumCPtr, StaticSaltedHasher> quorums;
|
||||
|
||||
const size_t nMaxBatchSize{32};
|
||||
CollectPendingSigSharesToVerify(nMaxBatchSize, sigSharesByNodes, quorums);
|
||||
if (sigSharesByNodes.empty()) {
|
||||
bool collect_status = CollectPendingSigSharesToVerify(nMaxBatchSize, sigSharesByNodes, quorums);
|
||||
if (!collect_status || sigSharesByNodes.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1269,12 +1277,15 @@ void CSigSharesManager::Cleanup()
|
||||
// Find quorums which became inactive
|
||||
for (auto it = quorums.begin(); it != quorums.end(); ) {
|
||||
if (IsQuorumActive(it->first.first, qman, it->first.second)) {
|
||||
it->second = qman.GetQuorum(it->first.first, it->first.second);
|
||||
auto quorum = qman.GetQuorum(it->first.first, it->first.second);
|
||||
if (quorum) {
|
||||
it->second = quorum;
|
||||
++it;
|
||||
} else {
|
||||
it = quorums.erase(it);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
it = quorums.erase(it);
|
||||
}
|
||||
|
||||
{
|
||||
// Now delete sessions which are for inactive quorums
|
||||
|
@ -452,8 +452,8 @@ private:
|
||||
static bool PreVerifyBatchedSigShares(const CActiveMasternodeManager& mn_activeman, const CQuorumManager& quorum_manager,
|
||||
const CSigSharesNodeState::SessionInfo& session, const CBatchedSigShares& batchedSigShares, bool& retBan);
|
||||
|
||||
void CollectPendingSigSharesToVerify(size_t maxUniqueSessions,
|
||||
std::unordered_map<NodeId, std::vector<CSigShare>>& retSigShares,
|
||||
bool CollectPendingSigSharesToVerify(
|
||||
size_t maxUniqueSessions, std::unordered_map<NodeId, std::vector<CSigShare>>& retSigShares,
|
||||
std::unordered_map<std::pair<Consensus::LLMQType, uint256>, CQuorumCPtr, StaticSaltedHasher>& retQuorums);
|
||||
bool ProcessPendingSigShares(const CConnman& connman);
|
||||
|
||||
|
@ -129,7 +129,7 @@ void CActiveMasternodeManager::InitInternal(const CBlockIndex* pindex)
|
||||
|
||||
CDeterministicMNList mnList = Assert(m_dmnman)->GetListForBlock(pindex);
|
||||
|
||||
CDeterministicMNCPtr dmn = mnList.GetMNByOperatorKey(m_info.blsPubKeyOperator);
|
||||
auto dmn = mnList.GetMNByOperatorKey(m_info.blsPubKeyOperator);
|
||||
if (!dmn) {
|
||||
// MN not appeared on the chain yet
|
||||
return;
|
||||
@ -202,6 +202,9 @@ void CActiveMasternodeManager::UpdatedBlockTip(const CBlockIndex* pindexNew, con
|
||||
|
||||
auto oldDmn = oldMNList.GetMN(cur_protx_hash);
|
||||
auto newDmn = newMNList.GetMN(cur_protx_hash);
|
||||
if (!oldDmn || !newDmn) {
|
||||
return reset(MasternodeState::SOME_ERROR);
|
||||
}
|
||||
if (newDmn->pdmnState->pubKeyOperator != oldDmn->pdmnState->pubKeyOperator) {
|
||||
// MN operator key changed or revoked
|
||||
return reset(MasternodeState::OPERATOR_KEY_CHANGED);
|
||||
|
@ -354,7 +354,8 @@ CDeterministicMNCPtr MasternodeList::GetSelectedDIP3MN()
|
||||
uint256 proTxHash;
|
||||
proTxHash.SetHex(strProTxHash);
|
||||
|
||||
return clientModel->getMasternodeList().first.GetMN(proTxHash);;
|
||||
// Caller is responsible for nullptr checking return value
|
||||
return clientModel->getMasternodeList().first.GetMN(proTxHash);
|
||||
}
|
||||
|
||||
void MasternodeList::extraInfoDIP3_clicked()
|
||||
|
@ -1635,6 +1635,9 @@ static RPCHelpMan protx_listdiff()
|
||||
UniValue jremovedMNs(UniValue::VARR);
|
||||
for(const auto& internal_id : mnDiff.removedMns) {
|
||||
auto dmn = baseBlockMNList.GetMNByInternalId(internal_id);
|
||||
// BuildDiff will construct itself with MNs that we already have knowledge
|
||||
// of, meaning that fetch operations should never fail.
|
||||
CHECK_NONFATAL(dmn);
|
||||
jremovedMNs.push_back(dmn->proTxHash.ToString());
|
||||
}
|
||||
ret.pushKV("removedMNs", jremovedMNs);
|
||||
@ -1642,6 +1645,9 @@ static RPCHelpMan protx_listdiff()
|
||||
UniValue jupdatedMNs(UniValue::VARR);
|
||||
for(const auto& [internal_id, stateDiff] : mnDiff.updatedMNs) {
|
||||
auto dmn = baseBlockMNList.GetMNByInternalId(internal_id);
|
||||
// BuildDiff will construct itself with MNs that we already have knowledge
|
||||
// of, meaning that fetch operations should never fail.
|
||||
CHECK_NONFATAL(dmn);
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
obj.pushKV(dmn->proTxHash.ToString(), stateDiff.ToJson(dmn->nType));
|
||||
jupdatedMNs.push_back(obj);
|
||||
|
@ -229,7 +229,7 @@ static RPCHelpMan masternode_status()
|
||||
// keep compatibility with legacy status for now (might get deprecated/removed later)
|
||||
mnObj.pushKV("outpoint", node.mn_activeman->GetOutPoint().ToStringShort());
|
||||
mnObj.pushKV("service", node.mn_activeman->GetService().ToStringAddrPort());
|
||||
CDeterministicMNCPtr dmn = CHECK_NONFATAL(node.dmnman)->GetListAtChainTip().GetMN(node.mn_activeman->GetProTxHash());
|
||||
auto dmn = CHECK_NONFATAL(node.dmnman)->GetListAtChainTip().GetMN(node.mn_activeman->GetProTxHash());
|
||||
if (dmn) {
|
||||
mnObj.pushKV("proTxHash", dmn->proTxHash.ToString());
|
||||
mnObj.pushKV("type", std::string(GetMnType(dmn->nType).description));
|
||||
@ -322,10 +322,12 @@ static RPCHelpMan masternode_winners()
|
||||
for (int h = nStartHeight; h <= nChainTipHeight; h++) {
|
||||
const CBlockIndex* pIndex = pindexTip->GetAncestor(h - 1);
|
||||
auto payee = node.dmnman->GetListForBlock(pIndex).GetMNPayee(pIndex);
|
||||
if (payee) {
|
||||
std::string strPayments = GetRequiredPaymentsString(*CHECK_NONFATAL(node.govman), tip_mn_list, h, payee);
|
||||
if (strFilter != "" && strPayments.find(strFilter) == std::string::npos) continue;
|
||||
obj.pushKV(strprintf("%d", h), strPayments);
|
||||
}
|
||||
}
|
||||
|
||||
auto projection = node.dmnman->GetListForBlock(pindexTip).GetProjectedMNPayees(pindexTip, 20);
|
||||
for (size_t i = 0; i < projection.size(); i++) {
|
||||
|
@ -255,7 +255,7 @@ static RPCHelpMan quorum_info()
|
||||
includeSkShare = ParseBoolV(request.params[2], "includeSkShare");
|
||||
}
|
||||
|
||||
auto quorum = llmq_ctx.qman->GetQuorum(llmqType, quorumHash);
|
||||
const auto quorum = llmq_ctx.qman->GetQuorum(llmqType, quorumHash);
|
||||
if (!quorum) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "quorum not found");
|
||||
}
|
||||
@ -451,13 +451,13 @@ static UniValue quorum_sign_helper(const JSONRPCRequest& request, Consensus::LLM
|
||||
if (fSubmit) {
|
||||
return llmq_ctx.sigman->AsyncSignIfMember(llmqType, *llmq_ctx.shareman, id, msgHash, quorumHash);
|
||||
} else {
|
||||
llmq::CQuorumCPtr pQuorum;
|
||||
|
||||
const auto pQuorum = [&]() {
|
||||
if (quorumHash.IsNull()) {
|
||||
pQuorum = llmq::SelectQuorumForSigning(llmq_params_opt.value(), chainman.ActiveChain(), *llmq_ctx.qman, id);
|
||||
return llmq::SelectQuorumForSigning(llmq_params_opt.value(), chainman.ActiveChain(), *llmq_ctx.qman, id);
|
||||
} else {
|
||||
pQuorum = llmq_ctx.qman->GetQuorum(llmqType, quorumHash);
|
||||
return llmq_ctx.qman->GetQuorum(llmqType, quorumHash);
|
||||
}
|
||||
}();
|
||||
|
||||
if (pQuorum == nullptr) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "quorum not found");
|
||||
@ -592,7 +592,7 @@ static RPCHelpMan quorum_verify()
|
||||
}
|
||||
|
||||
uint256 quorumHash(ParseHashV(request.params[4], "quorumHash"));
|
||||
llmq::CQuorumCPtr quorum = llmq_ctx.qman->GetQuorum(llmqType, quorumHash);
|
||||
const auto quorum = llmq_ctx.qman->GetQuorum(llmqType, quorumHash);
|
||||
|
||||
if (!quorum) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "quorum not found");
|
||||
|
@ -467,6 +467,7 @@ void FuncDIP3Protx(TestChainSetup& setup)
|
||||
// check MN reward payments
|
||||
for (size_t i = 0; i < 20; i++) {
|
||||
auto dmnExpectedPayee = dmnman.GetListAtChainTip().GetMNPayee(chainman.ActiveChain().Tip());
|
||||
BOOST_ASSERT(dmnExpectedPayee);
|
||||
|
||||
CBlock block = setup.CreateAndProcessBlock({}, setup.coinbaseKey);
|
||||
dmnman.UpdatedBlockTip(chainman.ActiveChain().Tip());
|
||||
@ -525,7 +526,7 @@ void FuncDIP3Protx(TestChainSetup& setup)
|
||||
// test that the revoked MN does not get paid anymore
|
||||
for (size_t i = 0; i < 20; i++) {
|
||||
auto dmnExpectedPayee = dmnman.GetListAtChainTip().GetMNPayee(chainman.ActiveChain().Tip());
|
||||
BOOST_REQUIRE(dmnExpectedPayee->proTxHash != dmnHashes[0]);
|
||||
BOOST_REQUIRE(dmnExpectedPayee && dmnExpectedPayee->proTxHash != dmnHashes[0]);
|
||||
|
||||
CBlock block = setup.CreateAndProcessBlock({}, setup.coinbaseKey);
|
||||
dmnman.UpdatedBlockTip(chainman.ActiveChain().Tip());
|
||||
@ -575,6 +576,7 @@ void FuncDIP3Protx(TestChainSetup& setup)
|
||||
bool foundRevived = false;
|
||||
for (size_t i = 0; i < 20; i++) {
|
||||
auto dmnExpectedPayee = dmnman.GetListAtChainTip().GetMNPayee(chainman.ActiveChain().Tip());
|
||||
BOOST_ASSERT(dmnExpectedPayee);
|
||||
if (dmnExpectedPayee->proTxHash == dmnHashes[0]) {
|
||||
foundRevived = true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user