@@ -48,7 +48,7 @@ void CDeterministicMN::ToJson(UniValue& obj) const
48
48
obj.setObject ();
49
49
50
50
UniValue stateObj;
51
- pdmnState->ToJson (stateObj);
51
+ pdmnState->ToJson (stateObj, nType );
52
52
53
53
obj.pushKV (" type" , std::string (GetMnType (nType).description ));
54
54
obj.pushKV (" proTxHash" , proTxHash.ToString ());
@@ -435,6 +435,48 @@ CDeterministicMNList CDeterministicMNList::ApplyDiff(const CBlockIndex* pindex,
435
435
return result;
436
436
}
437
437
438
+ // RepopulateUniquePropertyMap clears internal mnUniquePropertyMap, and repopulate it with currently MNs unique properties.
439
+ // This is needed when the v19 fork activates, we need to store again pubKeyOperator in the mnUniquePropertyMap.
440
+ // pubKeyOperator don't differ between the two schemes (legacy and basic(v19)) but their serialisation do: hence their hash.
441
+ // And because mnUniquePropertyMap store only hashes, then we need to re-calculate hashes and repopulate.
442
+ void CDeterministicMNList::RepopulateUniquePropertyMap () {
443
+ decltype (mnUniquePropertyMap) mnUniquePropertyMapEmpty;
444
+ mnUniquePropertyMap = mnUniquePropertyMapEmpty;
445
+
446
+ for (const auto &p: mnMap) {
447
+ auto dmn = p.second ;
448
+ if (!AddUniqueProperty (*dmn, dmn->collateralOutpoint )) {
449
+ throw (std::runtime_error (
450
+ strprintf (" %s: Can't add a masternode %s with a duplicate collateralOutpoint=%s" , __func__,
451
+ dmn->proTxHash .ToString (), dmn->collateralOutpoint .ToStringShort ())));
452
+ }
453
+ if (dmn->pdmnState ->addr != CService () && !AddUniqueProperty (*dmn, dmn->pdmnState ->addr )) {
454
+ throw (std::runtime_error (strprintf (" %s: Can't add a masternode %s with a duplicate address=%s" , __func__,
455
+ dmn->proTxHash .ToString (),
456
+ dmn->pdmnState ->addr .ToStringIPPort (false ))));
457
+ }
458
+ if (!AddUniqueProperty (*dmn, dmn->pdmnState ->keyIDOwner )) {
459
+ throw (std::runtime_error (
460
+ strprintf (" %s: Can't add a masternode %s with a duplicate keyIDOwner=%s" , __func__,
461
+ dmn->proTxHash .ToString (), EncodeDestination (PKHash (dmn->pdmnState ->keyIDOwner )))));
462
+ }
463
+ if (dmn->pdmnState ->pubKeyOperator .Get ().IsValid () &&
464
+ !AddUniqueProperty (*dmn, dmn->pdmnState ->pubKeyOperator )) {
465
+ throw (std::runtime_error (
466
+ strprintf (" %s: Can't add a masternode %s with a duplicate pubKeyOperator=%s" , __func__,
467
+ dmn->proTxHash .ToString (), dmn->pdmnState ->pubKeyOperator .Get ().ToString ())));
468
+ }
469
+
470
+ if (dmn->nType == MnType::HighPerformance) {
471
+ if (!AddUniqueProperty (*dmn, dmn->pdmnState ->platformNodeID )) {
472
+ throw (std::runtime_error (
473
+ strprintf (" %s: Can't add a masternode %s with a duplicate platformNodeID=%s" , __func__,
474
+ dmn->proTxHash .ToString (), dmn->pdmnState ->platformNodeID .ToString ())));
475
+ }
476
+ }
477
+ }
478
+ }
479
+
438
480
void CDeterministicMNList::AddMN (const CDeterministicMNCPtr& dmn, bool fBumpTotalCount )
439
481
{
440
482
assert (dmn != nullptr );
@@ -617,11 +659,19 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, const CBlockInde
617
659
618
660
newList.SetBlockHash (block.GetHash ());
619
661
662
+ // If the fork is active for pindex block, then we need to repopulate property map
663
+ // (Check documentation of CDeterministicMNList::RepopulateUniquePropertyMap()).
664
+ // This is needed only when base list is pre-v19 fork and pindex is post-v19 fork.
665
+ bool v19_just_activated = pindex == llmq::utils::V19ActivationIndex (pindex);
666
+ if (v19_just_activated) {
667
+ newList.RepopulateUniquePropertyMap ();
668
+ }
669
+
620
670
oldList = GetListForBlock (pindex->pprev );
621
671
diff = oldList.BuildDiff (newList);
622
672
623
673
m_evoDb.Write (std::make_pair (DB_LIST_DIFF, newList.GetBlockHash ()), diff);
624
- if ((nHeight % DISK_SNAPSHOT_PERIOD) == 0 || oldList.GetHeight () == -1 ) {
674
+ if ((nHeight % DISK_SNAPSHOT_PERIOD) == 0 || oldList.GetHeight () == -1 || v19_just_activated ) {
625
675
m_evoDb.Write (std::make_pair (DB_LIST_SNAPSHOT, newList.GetBlockHash ()), newList);
626
676
mnListsCache.emplace (newList.GetBlockHash (), newList);
627
677
LogPrintf (" CDeterministicMNManager::%s -- Wrote snapshot. nHeight=%d, mapCurMNs.allMNsCount=%d\n " ,
@@ -904,9 +954,12 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C
904
954
return _state.Invalid (ValidationInvalidReason::CONSENSUS, false , REJECT_INVALID, " bad-qc-payload" );
905
955
}
906
956
if (!qc.commitment .IsNull ()) {
907
- const auto & llmq_params = llmq::GetLLMQParams (qc.commitment .llmqType );
957
+ const auto & llmq_params_opt = llmq::GetLLMQParams (qc.commitment .llmqType );
958
+ if (!llmq_params_opt.has_value ()) {
959
+ return _state.Invalid (ValidationInvalidReason::CONSENSUS, false , REJECT_INVALID, " bad-qc-commitment-type" );
960
+ }
908
961
int qcnHeight = int (qc.nHeight );
909
- int quorumHeight = qcnHeight - (qcnHeight % llmq_params. dkgInterval ) + int (qc.commitment .quorumIndex );
962
+ int quorumHeight = qcnHeight - (qcnHeight % llmq_params_opt-> dkgInterval ) + int (qc.commitment .quorumIndex );
910
963
auto pQuorumBaseBlockIndex = pindexPrev->GetAncestor (quorumHeight);
911
964
if (!pQuorumBaseBlockIndex || pQuorumBaseBlockIndex->GetBlockHash () != qc.commitment .quorumHash ) {
912
965
// we should actually never get into this case as validation should have caught it...but let's be sure
0 commit comments