mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 03:52:49 +01:00
Merge #6318: refactor: remove circular dependency governance/object over governance/classes
2e36832982
refactor: drop circular dependency governance/classes over governance/governance (Konstantin Akimov)39f18ab154
refactor: move CGoveranceManager code from classes.cpp to governace.cpp (Konstantin Akimov)350a5ca47c
refactor: drop CSuperblock::GetGovernanceObject to simplify thread safety analysis over FindGovernanceObject (Konstantin Akimov)5031f29441
refactor: add couple missing `const` for CGovernanceManager (Konstantin Akimov)b240d08e09
refactor: move GetBestSuperblock to CGovernanceManager (Konstantin Akimov)3641653174
refactor: move CSuperblockManager::IsValid to CGoveranceManager::IsValidSuperblock (Konstantin Akimov)de8969f463
refactor: move ExecuteBestSuperblock to CGovernanceManager (Konstantin Akimov)107d5b4941
refactor: move GetSuperblockPayments to CGovernanceManager (Konstantin Akimov)7a470c441e
refactor: move IsSuperblockTriggered to CGovernanceManager (Konstantin Akimov)9638fdce6d
refactor: pass mn_sync to CGovernanceManager ctor as a reference (UdjinM6)7eb1634686
refactor: drop alias that is used only once (Konstantin Akimov)1570a02c89
refactor: move ScopedLockBool from header to cpp file (Konstantin Akimov)7aafb5a393
fix: add one more file to list of non-backported (flat-database.h) (Konstantin Akimov)41f1a43236
fix: add missing const for member functions of CRateCheckBuffer (Konstantin Akimov)982fc9a069
fix: avoid lock annotation for govman.cs in voteraw (Konstantin Akimov) Pull request description: ## Issue being fixed or feature implemented This PR is preparation for bitcoin#19668, otherwise impossible to make lock annotations for CGovernanceManager properly. ## What was done? 1. object mn_sync and peerman is pass to many methods of CGovernanceManager instead passing it to constructor. 2. methods of class CSuperblockManager moved to CGovernanceManager where they belongs to. 3. removed `CSuperblock::GetGovernanceObject` which makes a lot of mess with annotations of `govman.cs` And minor relevant improvements: moved ScopedLockBool from header to implementation, added multiple `const` for methods, added one more file `flat-database.h` to non-backported list ## How Has This Been Tested? Run unit and functional tests. ## 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: utACK2e36832982
PastaPastaPasta: utACK2e36832982
Tree-SHA512: 59842c208f7ece46c9381fc3f9fc838d9ed1cf0fd2404eebf7fbd656c5df1fa5fd339410da83088089e2d954a017efb518cba290f6c5d45b5bcb91818041f931
This commit is contained in:
commit
f93c763ac6
@ -117,9 +117,9 @@ private:
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
unsigned char pchMsgTmp[4];
|
||||
std::string strMagicMessageTmp;
|
||||
try {
|
||||
// de-serialize file header (file specific magic message) and ..
|
||||
ssObj >> strMagicMessageTmp;
|
||||
|
||||
@ -178,11 +178,11 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
CFlatDB(std::string strFilenameIn, std::string strMagicMessageIn)
|
||||
CFlatDB(std::string&& strFilenameIn, std::string&& strMagicMessageIn) :
|
||||
pathDB{gArgs.GetDataDirNet() / strFilenameIn},
|
||||
strFilename{strFilenameIn},
|
||||
strMagicMessage{strMagicMessageIn}
|
||||
{
|
||||
pathDB = gArgs.GetDataDirNet() / strFilenameIn;
|
||||
strFilename = strFilenameIn;
|
||||
strMagicMessage = strMagicMessageIn;
|
||||
}
|
||||
|
||||
bool Load(T& objToLoad)
|
||||
@ -191,7 +191,7 @@ public:
|
||||
return Read(objToLoad);
|
||||
}
|
||||
|
||||
bool Store(T& objToSave)
|
||||
bool Store(const T& objToSave)
|
||||
{
|
||||
LogPrintf("Verifying %s format...\n", strFilename);
|
||||
T tmpObjToLoad;
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include <consensus/validation.h>
|
||||
#include <core_io.h>
|
||||
#include <deploymentstatus.h>
|
||||
#include <governance/governance.h>
|
||||
#include <key_io.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <script/standard.h>
|
||||
@ -94,300 +93,6 @@ CAmount ParsePaymentAmount(const std::string& strAmount)
|
||||
return nAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Governance Object
|
||||
*/
|
||||
|
||||
bool CGovernanceManager::AddNewTrigger(uint256 nHash)
|
||||
{
|
||||
AssertLockHeld(cs);
|
||||
|
||||
// IF WE ALREADY HAVE THIS HASH, RETURN
|
||||
if (mapTrigger.count(nHash)) {
|
||||
LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- Already have hash, nHash = %s, count = %d, size = %s\n",
|
||||
__func__, nHash.GetHex(), mapTrigger.count(nHash), mapTrigger.size());
|
||||
return false;
|
||||
}
|
||||
|
||||
CSuperblock_sptr pSuperblock;
|
||||
try {
|
||||
auto pSuperblockTmp = std::make_shared<CSuperblock>(*this, nHash);
|
||||
pSuperblock = pSuperblockTmp;
|
||||
} catch (std::exception& e) {
|
||||
LogPrintf("CGovernanceManager::%s -- Error creating superblock: %s\n", __func__, e.what());
|
||||
return false;
|
||||
} catch (...) {
|
||||
LogPrintf("CGovernanceManager::%s -- Unknown Error creating superblock\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
pSuperblock->SetStatus(SeenObjectStatus::Valid);
|
||||
|
||||
mapTrigger.insert(std::make_pair(nHash, pSuperblock));
|
||||
|
||||
return !pSuperblock->IsExpired(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Clean And Remove
|
||||
*
|
||||
*/
|
||||
|
||||
void CGovernanceManager::CleanAndRemoveTriggers()
|
||||
{
|
||||
AssertLockHeld(cs);
|
||||
|
||||
// Remove triggers that are invalid or expired
|
||||
LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- mapTrigger.size() = %d\n", __func__, mapTrigger.size());
|
||||
|
||||
auto it = mapTrigger.begin();
|
||||
while (it != mapTrigger.end()) {
|
||||
bool remove = false;
|
||||
CGovernanceObject* pObj = nullptr;
|
||||
const CSuperblock_sptr& pSuperblock = it->second;
|
||||
if (!pSuperblock) {
|
||||
LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- nullptr superblock\n", __func__);
|
||||
remove = true;
|
||||
} else {
|
||||
pObj = FindGovernanceObject(it->first);
|
||||
if (!pObj || pObj->GetObjectType() != GovernanceObject::TRIGGER) {
|
||||
LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- Unknown or non-trigger superblock\n", __func__);
|
||||
pSuperblock->SetStatus(SeenObjectStatus::ErrorInvalid);
|
||||
}
|
||||
|
||||
LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- superblock status = %d\n", __func__, ToUnderlying(pSuperblock->GetStatus()));
|
||||
switch (pSuperblock->GetStatus()) {
|
||||
case SeenObjectStatus::ErrorInvalid:
|
||||
case SeenObjectStatus::Unknown:
|
||||
LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- Unknown or invalid trigger found\n", __func__);
|
||||
remove = true;
|
||||
break;
|
||||
case SeenObjectStatus::Valid:
|
||||
case SeenObjectStatus::Executed: {
|
||||
LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- Valid trigger found\n", __func__);
|
||||
if (pSuperblock->IsExpired(*this)) {
|
||||
// update corresponding object
|
||||
pObj->SetExpired();
|
||||
remove = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- %smarked for removal\n", __func__, remove ? "" : "NOT ");
|
||||
|
||||
if (remove) {
|
||||
std::string strDataAsPlainString = "nullptr";
|
||||
if (pObj) {
|
||||
strDataAsPlainString = pObj->GetDataAsPlainString();
|
||||
// mark corresponding object for deletion
|
||||
pObj->PrepareDeletion(GetTime<std::chrono::seconds>().count());
|
||||
}
|
||||
LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- Removing trigger object %s\n", __func__, strDataAsPlainString);
|
||||
// delete the trigger
|
||||
mapTrigger.erase(it++);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Active Triggers
|
||||
*
|
||||
* - Look through triggers and scan for active ones
|
||||
* - Return the triggers in a list
|
||||
*/
|
||||
|
||||
std::vector<CSuperblock_sptr> CGovernanceManager::GetActiveTriggers()
|
||||
{
|
||||
AssertLockHeld(cs);
|
||||
std::vector<CSuperblock_sptr> vecResults;
|
||||
|
||||
// LOOK AT THESE OBJECTS AND COMPILE A VALID LIST OF TRIGGERS
|
||||
for (const auto& pair : mapTrigger) {
|
||||
const CGovernanceObject* pObj = FindConstGovernanceObject(pair.first);
|
||||
if (pObj) {
|
||||
vecResults.push_back(pair.second);
|
||||
}
|
||||
}
|
||||
|
||||
return vecResults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is Superblock Triggered
|
||||
*
|
||||
* - Does this block have a non-executed and activated trigger?
|
||||
*/
|
||||
|
||||
bool CSuperblockManager::IsSuperblockTriggered(CGovernanceManager& govman, const CDeterministicMNList& tip_mn_list, int nBlockHeight)
|
||||
{
|
||||
LogPrint(BCLog::GOBJECT, "CSuperblockManager::IsSuperblockTriggered -- Start nBlockHeight = %d\n", nBlockHeight);
|
||||
if (!CSuperblock::IsValidBlockHeight(nBlockHeight)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LOCK(govman.cs);
|
||||
// GET ALL ACTIVE TRIGGERS
|
||||
std::vector<CSuperblock_sptr> vecTriggers = govman.GetActiveTriggers();
|
||||
|
||||
LogPrint(BCLog::GOBJECT, "CSuperblockManager::IsSuperblockTriggered -- vecTriggers.size() = %d\n", vecTriggers.size());
|
||||
|
||||
for (const auto& pSuperblock : vecTriggers) {
|
||||
if (!pSuperblock) {
|
||||
LogPrintf("CSuperblockManager::IsSuperblockTriggered -- Non-superblock found, continuing\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
CGovernanceObject* pObj = pSuperblock->GetGovernanceObject(govman);
|
||||
|
||||
if (!pObj) {
|
||||
LogPrintf("CSuperblockManager::IsSuperblockTriggered -- pObj == nullptr, continuing\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
LogPrint(BCLog::GOBJECT, "CSuperblockManager::IsSuperblockTriggered -- data = %s\n", pObj->GetDataAsPlainString());
|
||||
|
||||
// note : 12.1 - is epoch calculation correct?
|
||||
|
||||
if (nBlockHeight != pSuperblock->GetBlockHeight()) {
|
||||
LogPrint(BCLog::GOBJECT, "CSuperblockManager::IsSuperblockTriggered -- block height doesn't match nBlockHeight = %d, blockStart = %d, continuing\n",
|
||||
nBlockHeight,
|
||||
pSuperblock->GetBlockHeight());
|
||||
continue;
|
||||
}
|
||||
|
||||
// MAKE SURE THIS TRIGGER IS ACTIVE VIA FUNDING CACHE FLAG
|
||||
|
||||
pObj->UpdateSentinelVariables(tip_mn_list);
|
||||
|
||||
if (pObj->IsSetCachedFunding()) {
|
||||
LogPrint(BCLog::GOBJECT, "CSuperblockManager::IsSuperblockTriggered -- fCacheFunding = true, returning true\n");
|
||||
return true;
|
||||
} else {
|
||||
LogPrint(BCLog::GOBJECT, "CSuperblockManager::IsSuperblockTriggered -- fCacheFunding = false, continuing\n");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CSuperblockManager::GetBestSuperblock(CGovernanceManager& govman, const CDeterministicMNList& tip_mn_list, CSuperblock_sptr& pSuperblockRet, int nBlockHeight)
|
||||
{
|
||||
if (!CSuperblock::IsValidBlockHeight(nBlockHeight)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AssertLockHeld(govman.cs);
|
||||
std::vector<CSuperblock_sptr> vecTriggers = govman.GetActiveTriggers();
|
||||
int nYesCount = 0;
|
||||
|
||||
for (const auto& pSuperblock : vecTriggers) {
|
||||
if (!pSuperblock || nBlockHeight != pSuperblock->GetBlockHeight()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const CGovernanceObject* pObj = pSuperblock->GetGovernanceObject(govman);
|
||||
|
||||
if (!pObj) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// DO WE HAVE A NEW WINNER?
|
||||
|
||||
int nTempYesCount = pObj->GetAbsoluteYesCount(tip_mn_list, VOTE_SIGNAL_FUNDING);
|
||||
if (nTempYesCount > nYesCount) {
|
||||
nYesCount = nTempYesCount;
|
||||
pSuperblockRet = pSuperblock;
|
||||
}
|
||||
}
|
||||
|
||||
return nYesCount > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Superblock Payments
|
||||
*
|
||||
* - Returns payments for superblock
|
||||
*/
|
||||
|
||||
bool CSuperblockManager::GetSuperblockPayments(CGovernanceManager& govman, const CDeterministicMNList& tip_mn_list, int nBlockHeight, std::vector<CTxOut>& voutSuperblockRet)
|
||||
{
|
||||
LOCK(govman.cs);
|
||||
|
||||
// GET THE BEST SUPERBLOCK FOR THIS BLOCK HEIGHT
|
||||
|
||||
CSuperblock_sptr pSuperblock;
|
||||
if (!CSuperblockManager::GetBestSuperblock(govman, tip_mn_list, pSuperblock, nBlockHeight)) {
|
||||
LogPrint(BCLog::GOBJECT, "CSuperblockManager::GetSuperblockPayments -- Can't find superblock for height %d\n", nBlockHeight);
|
||||
return false;
|
||||
}
|
||||
|
||||
// make sure it's empty, just in case
|
||||
voutSuperblockRet.clear();
|
||||
|
||||
// GET SUPERBLOCK OUTPUTS
|
||||
|
||||
// Superblock payments will be appended to the end of the coinbase vout vector
|
||||
|
||||
// TODO: How many payments can we add before things blow up?
|
||||
// Consider at least following limits:
|
||||
// - max coinbase tx size
|
||||
// - max "budget" available
|
||||
for (int i = 0; i < pSuperblock->CountPayments(); i++) {
|
||||
CGovernancePayment payment;
|
||||
if (pSuperblock->GetPayment(i, payment)) {
|
||||
// SET COINBASE OUTPUT TO SUPERBLOCK SETTING
|
||||
|
||||
CTxOut txout = CTxOut(payment.nAmount, payment.script);
|
||||
voutSuperblockRet.push_back(txout);
|
||||
|
||||
// PRINT NICE LOG OUTPUT FOR SUPERBLOCK PAYMENT
|
||||
|
||||
CTxDestination dest;
|
||||
ExtractDestination(payment.script, dest);
|
||||
|
||||
LogPrint(BCLog::GOBJECT, "CSuperblockManager::GetSuperblockPayments -- NEW Superblock: output %d (addr %s, amount %d.%08d)\n",
|
||||
i, EncodeDestination(dest), payment.nAmount / COIN, payment.nAmount % COIN);
|
||||
} else {
|
||||
LogPrint(BCLog::GOBJECT, "CSuperblockManager::GetSuperblockPayments -- Payment not found\n");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSuperblockManager::IsValid(CGovernanceManager& govman, const CChain& active_chain, const CDeterministicMNList& tip_mn_list, const CTransaction& txNew, int nBlockHeight, CAmount blockReward)
|
||||
{
|
||||
// GET BEST SUPERBLOCK, SHOULD MATCH
|
||||
LOCK(govman.cs);
|
||||
|
||||
CSuperblock_sptr pSuperblock;
|
||||
if (CSuperblockManager::GetBestSuperblock(govman, tip_mn_list, pSuperblock, nBlockHeight)) {
|
||||
return pSuperblock->IsValid(govman, active_chain, txNew, nBlockHeight, blockReward);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CSuperblockManager::ExecuteBestSuperblock(CGovernanceManager& govman, const CDeterministicMNList& tip_mn_list, int nBlockHeight)
|
||||
{
|
||||
LOCK(govman.cs);
|
||||
|
||||
CSuperblock_sptr pSuperblock;
|
||||
if (GetBestSuperblock(govman, tip_mn_list, pSuperblock, nBlockHeight)) {
|
||||
// All checks are done in CSuperblock::IsValid via IsBlockValueValid and IsBlockPayeeValid,
|
||||
// tip wouldn't be updated if anything was wrong. Mark this trigger as executed.
|
||||
pSuperblock->SetExecuted();
|
||||
govman.ResetVotedFundingTrigger();
|
||||
}
|
||||
}
|
||||
|
||||
CSuperblock::
|
||||
CSuperblock() :
|
||||
nGovObjHash(),
|
||||
@ -397,27 +102,20 @@ CSuperblock::
|
||||
{
|
||||
}
|
||||
|
||||
CSuperblock::
|
||||
CSuperblock(CGovernanceManager& govman, uint256& nHash) :
|
||||
CSuperblock::CSuperblock(const CGovernanceObject& govObj, uint256& nHash) :
|
||||
nGovObjHash(nHash),
|
||||
nBlockHeight(0),
|
||||
nStatus(SeenObjectStatus::Unknown),
|
||||
vecPayments()
|
||||
{
|
||||
const CGovernanceObject* pGovObj = GetGovernanceObject(govman);
|
||||
LogPrint(BCLog::GOBJECT, "CSuperblock -- Constructor govobj: %s, nObjectType = %d\n", govObj.GetDataAsPlainString(),
|
||||
ToUnderlying(govObj.GetObjectType()));
|
||||
|
||||
if (!pGovObj) {
|
||||
throw std::runtime_error("CSuperblock: Failed to find Governance Object");
|
||||
}
|
||||
|
||||
LogPrint(BCLog::GOBJECT, "CSuperblock -- Constructor pGovObj: %s, nObjectType = %d\n",
|
||||
pGovObj->GetDataAsPlainString(), ToUnderlying(pGovObj->GetObjectType()));
|
||||
|
||||
if (pGovObj->GetObjectType() != GovernanceObject::TRIGGER) {
|
||||
if (govObj.GetObjectType() != GovernanceObject::TRIGGER) {
|
||||
throw std::runtime_error("CSuperblock: Governance Object not a trigger");
|
||||
}
|
||||
|
||||
UniValue obj = pGovObj->GetJSONObject();
|
||||
UniValue obj = govObj.GetJSONObject();
|
||||
|
||||
if (obj["type"].get_int() != ToUnderlying(GovernanceObject::TRIGGER)) {
|
||||
throw std::runtime_error("CSuperblock: invalid data type");
|
||||
@ -442,14 +140,6 @@ CSuperblock::CSuperblock(int nBlockHeight, std::vector<CGovernancePayment> vecPa
|
||||
nGovObjHash = GetHash();
|
||||
}
|
||||
|
||||
CGovernanceObject* CSuperblock::GetGovernanceObject(CGovernanceManager& govman)
|
||||
{
|
||||
AssertLockHeld(govman.cs);
|
||||
CGovernanceObject* pObj = govman.FindGovernanceObject(nGovObjHash);
|
||||
return pObj;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Is Valid Superblock Height
|
||||
*
|
||||
@ -598,7 +288,7 @@ CAmount CSuperblock::GetPaymentsTotalAmount()
|
||||
* - Does this transaction match the superblock?
|
||||
*/
|
||||
|
||||
bool CSuperblock::IsValid(CGovernanceManager& govman, const CChain& active_chain, const CTransaction& txNew, int nBlockHeight, CAmount blockReward)
|
||||
bool CSuperblock::IsValid(const CChain& active_chain, const CTransaction& txNew, int nBlockHeight, CAmount blockReward)
|
||||
{
|
||||
// TODO : LOCK(cs);
|
||||
// No reason for a lock here now since this method only accesses data
|
||||
@ -616,8 +306,8 @@ bool CSuperblock::IsValid(CGovernanceManager& govman, const CChain& active_chain
|
||||
int nPayments = CountPayments();
|
||||
int nMinerAndMasternodePayments = nOutputs - nPayments;
|
||||
|
||||
LogPrint(BCLog::GOBJECT, "CSuperblock::IsValid -- nOutputs = %d, nPayments = %d, GetDataAsHexString = %s\n",
|
||||
nOutputs, nPayments, GetGovernanceObject(govman)->GetDataAsHexString());
|
||||
LogPrint(BCLog::GOBJECT, "CSuperblock::IsValid -- nOutputs = %d, nPayments = %d, hash = %s\n", nOutputs, nPayments,
|
||||
nGovObjHash.ToString());
|
||||
|
||||
// We require an exact match (including order) between the expected
|
||||
// superblock payments and the payments actually in the block.
|
||||
@ -681,7 +371,7 @@ bool CSuperblock::IsValid(CGovernanceManager& govman, const CChain& active_chain
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSuperblock::IsExpired(const CGovernanceManager& govman) const
|
||||
bool CSuperblock::IsExpired(int heightToTest) const
|
||||
{
|
||||
int nExpirationBlocks;
|
||||
// Executed triggers are kept for another superblock cycle (approximately 1 month for mainnet).
|
||||
@ -703,14 +393,14 @@ bool CSuperblock::IsExpired(const CGovernanceManager& govman) const
|
||||
|
||||
LogPrint(BCLog::GOBJECT, "CSuperblock::IsExpired -- nBlockHeight = %d, nExpirationBlock = %d\n", nBlockHeight, nExpirationBlock);
|
||||
|
||||
if (govman.GetCachedBlockHeight() > nExpirationBlock) {
|
||||
if (heightToTest > nExpirationBlock) {
|
||||
LogPrint(BCLog::GOBJECT, "CSuperblock::IsExpired -- Outdated trigger found\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Params().NetworkIDString() != CBaseChainParams::MAIN) {
|
||||
// NOTE: this can happen on testnet/devnets due to reorgs, should never happen on mainnet
|
||||
if (govman.GetCachedBlockHeight() + Params().GetConsensus().nSuperblockCycle * 2 < nBlockHeight) {
|
||||
if (heightToTest + Params().GetConsensus().nSuperblockCycle * 2 < nBlockHeight) {
|
||||
LogPrint(BCLog::GOBJECT, "CSuperblock::IsExpired -- Trigger is too far into the future\n");
|
||||
return true;
|
||||
}
|
||||
|
@ -11,9 +11,7 @@
|
||||
#include <uint256.h>
|
||||
|
||||
class CChain;
|
||||
class CGovernanceManager;
|
||||
class CSuperblock;
|
||||
class CSuperblockManager;
|
||||
class CTxOut;
|
||||
class CTransaction;
|
||||
|
||||
@ -21,26 +19,6 @@ using CSuperblock_sptr = std::shared_ptr<CSuperblock>;
|
||||
|
||||
CAmount ParsePaymentAmount(const std::string& strAmount);
|
||||
|
||||
/**
|
||||
* Superblock Manager
|
||||
*
|
||||
* Class for querying superblock information
|
||||
*/
|
||||
|
||||
class CSuperblockManager
|
||||
{
|
||||
private:
|
||||
static bool GetBestSuperblock(CGovernanceManager& govman, const CDeterministicMNList& tip_mn_list, CSuperblock_sptr& pSuperblockRet, int nBlockHeight);
|
||||
|
||||
public:
|
||||
static bool IsSuperblockTriggered(CGovernanceManager& govman, const CDeterministicMNList& tip_mn_list, int nBlockHeight);
|
||||
|
||||
static bool GetSuperblockPayments(CGovernanceManager& govman, const CDeterministicMNList& tip_mn_list, int nBlockHeight, std::vector<CTxOut>& voutSuperblockRet);
|
||||
static void ExecuteBestSuperblock(CGovernanceManager& govman, const CDeterministicMNList& tip_mn_list, int nBlockHeight);
|
||||
|
||||
static bool IsValid(CGovernanceManager& govman, const CChain& active_chain, const CDeterministicMNList& tip_mn_list, const CTransaction& txNew, int nBlockHeight, CAmount blockReward);
|
||||
};
|
||||
|
||||
/**
|
||||
* Governance Object Payment
|
||||
*
|
||||
@ -101,7 +79,7 @@ private:
|
||||
public:
|
||||
CSuperblock();
|
||||
CSuperblock(int nBlockHeight, std::vector<CGovernancePayment> vecPayments);
|
||||
explicit CSuperblock(CGovernanceManager& govman, uint256& nHash);
|
||||
explicit CSuperblock(const CGovernanceObject& obj, uint256& nHash);
|
||||
|
||||
static bool IsValidBlockHeight(int nBlockHeight);
|
||||
static void GetNearestSuperblocksHeights(int nBlockHeight, int& nLastSuperblockRet, int& nNextSuperblockRet);
|
||||
@ -115,19 +93,19 @@ public:
|
||||
// TELL THE ENGINE WE EXECUTED THIS EVENT
|
||||
void SetExecuted() { nStatus = SeenObjectStatus::Executed; }
|
||||
|
||||
CGovernanceObject* GetGovernanceObject(CGovernanceManager& govman);
|
||||
|
||||
int GetBlockHeight() const
|
||||
{
|
||||
return nBlockHeight;
|
||||
}
|
||||
|
||||
const uint256 GetGovernanceObjHash() const { return nGovObjHash; }
|
||||
|
||||
int CountPayments() const { return (int)vecPayments.size(); }
|
||||
bool GetPayment(int nPaymentIndex, CGovernancePayment& paymentRet);
|
||||
CAmount GetPaymentsTotalAmount();
|
||||
|
||||
bool IsValid(CGovernanceManager& govman, const CChain& active_chain, const CTransaction& txNew, int nBlockHeight, CAmount blockReward);
|
||||
bool IsExpired(const CGovernanceManager& govman) const;
|
||||
bool IsValid(const CChain& active_chain, const CTransaction& txNew, int nBlockHeight, CAmount blockReward);
|
||||
bool IsExpired(int heightToTest) const;
|
||||
|
||||
std::vector<uint256> GetProposalHashes() const;
|
||||
};
|
||||
|
@ -34,6 +34,25 @@ const std::string GovernanceStore::SERIALIZATION_VERSION_STRING = "CGovernanceMa
|
||||
const int CGovernanceManager::MAX_TIME_FUTURE_DEVIATION = 60 * 60;
|
||||
const int CGovernanceManager::RELIABLE_PROPAGATION_TIME = 60;
|
||||
|
||||
namespace {
|
||||
class ScopedLockBool
|
||||
{
|
||||
bool& ref;
|
||||
bool fPrevValue;
|
||||
|
||||
public:
|
||||
ScopedLockBool(RecursiveMutex& _cs, bool& _ref, bool _value) :
|
||||
ref(_ref)
|
||||
{
|
||||
AssertLockHeld(_cs);
|
||||
fPrevValue = ref;
|
||||
ref = _value;
|
||||
}
|
||||
|
||||
~ScopedLockBool() { ref = fPrevValue; }
|
||||
};
|
||||
} // anonymous namespace
|
||||
|
||||
GovernanceStore::GovernanceStore() :
|
||||
cs(),
|
||||
mapObjects(),
|
||||
@ -47,8 +66,8 @@ GovernanceStore::GovernanceStore() :
|
||||
}
|
||||
|
||||
CGovernanceManager::CGovernanceManager(CMasternodeMetaMan& mn_metaman, CNetFulfilledRequestManager& netfulfilledman,
|
||||
const ChainstateManager& chainman, const std::unique_ptr<CDeterministicMNManager>& dmnman,
|
||||
const std::unique_ptr<CMasternodeSync>& mn_sync) :
|
||||
const ChainstateManager& chainman,
|
||||
const std::unique_ptr<CDeterministicMNManager>& dmnman, CMasternodeSync& mn_sync) :
|
||||
m_db{std::make_unique<db_type>("governance.dat", "magicGovernanceCache")},
|
||||
m_mn_metaman{mn_metaman},
|
||||
m_netfulfilledman{netfulfilledman},
|
||||
@ -125,7 +144,7 @@ bool CGovernanceManager::SerializeVoteForHash(const uint256& nHash, CDataStream&
|
||||
PeerMsgRet CGovernanceManager::ProcessMessage(CNode& peer, CConnman& connman, PeerManager& peerman, std::string_view msg_type, CDataStream& vRecv)
|
||||
{
|
||||
if (!IsValid()) return {};
|
||||
if (m_mn_sync == nullptr || !m_mn_sync->IsBlockchainSynced()) return {};
|
||||
if (!m_mn_sync.IsBlockchainSynced()) return {};
|
||||
|
||||
const auto tip_mn_list = Assert(m_dmnman)->GetListAtChainTip();
|
||||
// ANOTHER USER IS ASKING US TO HELP THEM SYNC GOVERNANCE OBJECT DATA
|
||||
@ -133,7 +152,7 @@ PeerMsgRet CGovernanceManager::ProcessMessage(CNode& peer, CConnman& connman, Pe
|
||||
// Ignore such requests until we are fully synced.
|
||||
// We could start processing this after masternode list is synced
|
||||
// but this is a heavy one so it's better to finish sync first.
|
||||
if (!m_mn_sync->IsSynced()) return {};
|
||||
if (!m_mn_sync.IsSynced()) return {};
|
||||
|
||||
uint256 nProp;
|
||||
CBloomFilter filter;
|
||||
@ -161,7 +180,7 @@ PeerMsgRet CGovernanceManager::ProcessMessage(CNode& peer, CConnman& connman, Pe
|
||||
|
||||
WITH_LOCK(::cs_main, peerman.EraseObjectRequest(peer.GetId(), CInv(MSG_GOVERNANCE_OBJECT, nHash)));
|
||||
|
||||
if (!m_mn_sync->IsBlockchainSynced()) {
|
||||
if (!m_mn_sync.IsBlockchainSynced()) {
|
||||
LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECT -- masternode list not synced\n");
|
||||
return {};
|
||||
}
|
||||
@ -225,7 +244,7 @@ PeerMsgRet CGovernanceManager::ProcessMessage(CNode& peer, CConnman& connman, Pe
|
||||
WITH_LOCK(::cs_main, peerman.EraseObjectRequest(peer.GetId(), CInv(MSG_GOVERNANCE_OBJECT_VOTE, nHash)));
|
||||
|
||||
// Ignore such messages until masternode list is synced
|
||||
if (!m_mn_sync->IsBlockchainSynced()) {
|
||||
if (!m_mn_sync.IsBlockchainSynced()) {
|
||||
LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECTVOTE -- masternode list not synced\n");
|
||||
return {};
|
||||
}
|
||||
@ -243,11 +262,11 @@ PeerMsgRet CGovernanceManager::ProcessMessage(CNode& peer, CConnman& connman, Pe
|
||||
CGovernanceException exception;
|
||||
if (ProcessVote(&peer, vote, exception, connman)) {
|
||||
LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECTVOTE -- %s new\n", strHash);
|
||||
m_mn_sync->BumpAssetLastTime("MNGOVERNANCEOBJECTVOTE");
|
||||
vote.Relay(peerman, *m_mn_sync, tip_mn_list);
|
||||
m_mn_sync.BumpAssetLastTime("MNGOVERNANCEOBJECTVOTE");
|
||||
vote.Relay(peerman, m_mn_sync, tip_mn_list);
|
||||
} else {
|
||||
LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECTVOTE -- Rejected vote, error = %s\n", exception.what());
|
||||
if ((exception.GetNodePenalty() != 0) && m_mn_sync->IsSynced()) {
|
||||
if ((exception.GetNodePenalty() != 0) && m_mn_sync.IsSynced()) {
|
||||
return tl::unexpected{exception.GetNodePenalty()};
|
||||
}
|
||||
return {};
|
||||
@ -273,7 +292,7 @@ void CGovernanceManager::CheckOrphanVotes(CGovernanceObject& govobj, PeerManager
|
||||
if (pairVote.second < nNow) {
|
||||
fRemove = true;
|
||||
} else if (govobj.ProcessVote(m_mn_metaman, *this, tip_mn_list, vote, e)) {
|
||||
vote.Relay(peerman, *Assert(m_mn_sync), tip_mn_list);
|
||||
vote.Relay(peerman, m_mn_sync, tip_mn_list);
|
||||
fRemove = true;
|
||||
}
|
||||
if (fRemove) {
|
||||
@ -327,12 +346,12 @@ void CGovernanceManager::AddGovernanceObject(CGovernanceObject& govobj, PeerMana
|
||||
}
|
||||
|
||||
LogPrint(BCLog::GOBJECT, "CGovernanceManager::AddGovernanceObject -- %s new, received from peer %s\n", strHash, pfrom ? pfrom->GetLogString() : "nullptr");
|
||||
govobj.Relay(peerman, *Assert(m_mn_sync));
|
||||
govobj.Relay(peerman, m_mn_sync);
|
||||
|
||||
// Update the rate buffer
|
||||
MasternodeRateUpdate(govobj);
|
||||
|
||||
m_mn_sync->BumpAssetLastTime("CGovernanceManager::AddGovernanceObject");
|
||||
m_mn_sync.BumpAssetLastTime("CGovernanceManager::AddGovernanceObject");
|
||||
|
||||
// WE MIGHT HAVE PENDING/ORPHAN VOTES FOR THIS OBJECT
|
||||
|
||||
@ -347,7 +366,7 @@ void CGovernanceManager::CheckAndRemove()
|
||||
assert(m_mn_metaman.IsValid());
|
||||
|
||||
// Return on initial sync, spammed the debug.log and provided no use
|
||||
if (m_mn_sync == nullptr || !m_mn_sync->IsBlockchainSynced()) return;
|
||||
if (!m_mn_sync.IsBlockchainSynced()) return;
|
||||
|
||||
LogPrint(BCLog::GOBJECT, "CGovernanceManager::UpdateCachesAndClean\n");
|
||||
|
||||
@ -573,7 +592,7 @@ struct sortProposalsByVotes {
|
||||
std::optional<const CSuperblock> CGovernanceManager::CreateSuperblockCandidate(int nHeight) const
|
||||
{
|
||||
if (!IsValid()) return std::nullopt;
|
||||
if (m_mn_sync == nullptr || !m_mn_sync->IsSynced()) return std::nullopt;
|
||||
if (!m_mn_sync.IsSynced()) return std::nullopt;
|
||||
if (nHeight % Params().GetConsensus().nSuperblockCycle < Params().GetConsensus().nSuperblockCycle - Params().GetConsensus().nSuperblockMaturityWindow) return std::nullopt;
|
||||
if (HasAlreadyVotedFundingTrigger()) return std::nullopt;
|
||||
|
||||
@ -777,7 +796,7 @@ void CGovernanceManager::VoteGovernanceTriggers(const std::optional<const CGover
|
||||
// Vote NO-FUNDING for the rest of the active triggers
|
||||
const auto activeTriggers = GetActiveTriggers();
|
||||
for (const auto& trigger : activeTriggers) {
|
||||
const auto govobj = trigger->GetGovernanceObject(*this);
|
||||
const auto govobj = FindGovernanceObject(trigger->GetGovernanceObjHash());
|
||||
const uint256 trigger_hash = govobj->GetHash();
|
||||
if (trigger->GetBlockHeight() <= nCachedBlockHeight) {
|
||||
// ignore triggers from the past
|
||||
@ -843,7 +862,7 @@ void CGovernanceManager::ResetVotedFundingTrigger()
|
||||
void CGovernanceManager::DoMaintenance(CConnman& connman)
|
||||
{
|
||||
if (!IsValid()) return;
|
||||
if (m_mn_sync == nullptr || !m_mn_sync->IsSynced()) return;
|
||||
if (!m_mn_sync.IsSynced()) return;
|
||||
if (ShutdownRequested()) return;
|
||||
|
||||
// CHECK OBJECTS WE'VE ASKED FOR, REMOVE OLD ENTRIES
|
||||
@ -857,7 +876,7 @@ void CGovernanceManager::DoMaintenance(CConnman& connman)
|
||||
bool CGovernanceManager::ConfirmInventoryRequest(const CInv& inv)
|
||||
{
|
||||
// do not request objects until it's time to sync
|
||||
if (!Assert(m_mn_sync)->IsBlockchainSynced()) return false;
|
||||
if (!m_mn_sync.IsBlockchainSynced()) return false;
|
||||
|
||||
LOCK(cs);
|
||||
|
||||
@ -900,7 +919,7 @@ bool CGovernanceManager::ConfirmInventoryRequest(const CInv& inv)
|
||||
void CGovernanceManager::SyncSingleObjVotes(CNode& peer, PeerManager& peerman, const uint256& nProp, const CBloomFilter& filter, CConnman& connman)
|
||||
{
|
||||
// do not provide any data until our node is synced
|
||||
if (!Assert(m_mn_sync)->IsSynced()) return;
|
||||
if (!m_mn_sync.IsSynced()) return;
|
||||
|
||||
int nVoteCount = 0;
|
||||
|
||||
@ -952,7 +971,7 @@ PeerMsgRet CGovernanceManager::SyncObjects(CNode& peer, PeerManager& peerman, CC
|
||||
assert(m_netfulfilledman.IsValid());
|
||||
|
||||
// do not provide any data until our node is synced
|
||||
if (!Assert(m_mn_sync)->IsSynced()) return {};
|
||||
if (!m_mn_sync.IsSynced()) return {};
|
||||
|
||||
if (m_netfulfilledman.HasFulfilledRequest(peer.addr, NetMsgType::MNGOVERNANCESYNC)) {
|
||||
// Asking for the whole list multiple times in a short period of time is no good
|
||||
@ -1042,7 +1061,7 @@ bool CGovernanceManager::MasternodeRateCheck(const CGovernanceObject& govobj, bo
|
||||
|
||||
fRateCheckBypassed = false;
|
||||
|
||||
if (!Assert(m_mn_sync)->IsSynced() || !fRateChecksEnabled) {
|
||||
if (!m_mn_sync.IsSynced() || !fRateChecksEnabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1104,7 +1123,7 @@ bool CGovernanceManager::ProcessVoteAndRelay(const CGovernanceVote& vote, CGover
|
||||
{
|
||||
bool fOK = ProcessVote(/* pfrom = */ nullptr, vote, exception, connman);
|
||||
if (fOK) {
|
||||
vote.Relay(peerman, *Assert(m_mn_sync), Assert(m_dmnman)->GetListAtChainTip());
|
||||
vote.Relay(peerman, m_mn_sync, Assert(m_dmnman)->GetListAtChainTip());
|
||||
}
|
||||
return fOK;
|
||||
}
|
||||
@ -1165,7 +1184,7 @@ bool CGovernanceManager::ProcessVote(CNode* pfrom, const CGovernanceVote& vote,
|
||||
|
||||
void CGovernanceManager::CheckPostponedObjects(PeerManager& peerman)
|
||||
{
|
||||
if (!Assert(m_mn_sync)->IsSynced()) return;
|
||||
if (!m_mn_sync.IsSynced()) return;
|
||||
|
||||
LOCK2(cs_main, cs);
|
||||
|
||||
@ -1213,7 +1232,7 @@ void CGovernanceManager::CheckPostponedObjects(PeerManager& peerman)
|
||||
if (fValid) {
|
||||
if (fReady) {
|
||||
LogPrint(BCLog::GOBJECT, "CGovernanceManager::CheckPostponedObjects -- additional relay: hash = %s\n", govobj.GetHash().ToString());
|
||||
govobj.Relay(peerman, *m_mn_sync);
|
||||
govobj.Relay(peerman, m_mn_sync);
|
||||
} else {
|
||||
it++;
|
||||
continue;
|
||||
@ -1524,7 +1543,7 @@ void CGovernanceManager::UpdatedBlockTip(const CBlockIndex* pindex, CConnman& co
|
||||
|
||||
CheckPostponedObjects(peerman);
|
||||
|
||||
CSuperblockManager::ExecuteBestSuperblock(*this, Assert(m_dmnman)->GetListAtChainTip(), pindex->nHeight);
|
||||
ExecuteBestSuperblock(Assert(m_dmnman)->GetListAtChainTip(), pindex->nHeight);
|
||||
}
|
||||
|
||||
void CGovernanceManager::RequestOrphanObjects(CConnman& connman)
|
||||
@ -1574,7 +1593,7 @@ void CGovernanceManager::CleanOrphanObjects()
|
||||
|
||||
void CGovernanceManager::RemoveInvalidVotes()
|
||||
{
|
||||
if (!Assert(m_mn_sync)->IsSynced()) {
|
||||
if (!m_mn_sync.IsSynced()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1616,6 +1635,296 @@ void CGovernanceManager::RemoveInvalidVotes()
|
||||
lastMNListForVotingKeys = std::make_shared<CDeterministicMNList>(tip_mn_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Governance Object
|
||||
*/
|
||||
|
||||
bool CGovernanceManager::AddNewTrigger(uint256 nHash)
|
||||
{
|
||||
AssertLockHeld(cs);
|
||||
|
||||
// IF WE ALREADY HAVE THIS HASH, RETURN
|
||||
if (mapTrigger.count(nHash)) {
|
||||
LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- Already have hash, nHash = %s, count = %d, size = %s\n",
|
||||
__func__, nHash.GetHex(), mapTrigger.count(nHash), mapTrigger.size());
|
||||
return false;
|
||||
}
|
||||
|
||||
CSuperblock_sptr pSuperblock;
|
||||
try {
|
||||
const CGovernanceObject* pGovObj = FindGovernanceObject(nHash);
|
||||
if (!pGovObj) {
|
||||
throw std::runtime_error("CSuperblock: Failed to find Governance Object");
|
||||
}
|
||||
pSuperblock = std::make_shared<CSuperblock>(*pGovObj, nHash);
|
||||
} catch (std::exception& e) {
|
||||
LogPrintf("CGovernanceManager::%s -- Error creating superblock: %s\n", __func__, e.what());
|
||||
return false;
|
||||
} catch (...) {
|
||||
LogPrintf("CGovernanceManager::%s -- Unknown Error creating superblock\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
pSuperblock->SetStatus(SeenObjectStatus::Valid);
|
||||
|
||||
mapTrigger.insert(std::make_pair(nHash, pSuperblock));
|
||||
|
||||
return !pSuperblock->IsExpired(GetCachedBlockHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Clean And Remove
|
||||
*
|
||||
*/
|
||||
|
||||
void CGovernanceManager::CleanAndRemoveTriggers()
|
||||
{
|
||||
AssertLockHeld(cs);
|
||||
|
||||
// Remove triggers that are invalid or expired
|
||||
LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- mapTrigger.size() = %d\n", __func__, mapTrigger.size());
|
||||
|
||||
auto it = mapTrigger.begin();
|
||||
while (it != mapTrigger.end()) {
|
||||
bool remove = false;
|
||||
CGovernanceObject* pObj = nullptr;
|
||||
const CSuperblock_sptr& pSuperblock = it->second;
|
||||
if (!pSuperblock) {
|
||||
LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- nullptr superblock\n", __func__);
|
||||
remove = true;
|
||||
} else {
|
||||
pObj = FindGovernanceObject(it->first);
|
||||
if (!pObj || pObj->GetObjectType() != GovernanceObject::TRIGGER) {
|
||||
LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- Unknown or non-trigger superblock\n", __func__);
|
||||
pSuperblock->SetStatus(SeenObjectStatus::ErrorInvalid);
|
||||
}
|
||||
|
||||
LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- superblock status = %d\n", __func__,
|
||||
ToUnderlying(pSuperblock->GetStatus()));
|
||||
switch (pSuperblock->GetStatus()) {
|
||||
case SeenObjectStatus::ErrorInvalid:
|
||||
case SeenObjectStatus::Unknown:
|
||||
LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- Unknown or invalid trigger found\n", __func__);
|
||||
remove = true;
|
||||
break;
|
||||
case SeenObjectStatus::Valid:
|
||||
case SeenObjectStatus::Executed: {
|
||||
LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- Valid trigger found\n", __func__);
|
||||
if (pSuperblock->IsExpired(GetCachedBlockHeight())) {
|
||||
// update corresponding object
|
||||
pObj->SetExpired();
|
||||
remove = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- %smarked for removal\n", __func__, remove ? "" : "NOT ");
|
||||
|
||||
if (remove) {
|
||||
std::string strDataAsPlainString = "nullptr";
|
||||
if (pObj) {
|
||||
strDataAsPlainString = pObj->GetDataAsPlainString();
|
||||
// mark corresponding object for deletion
|
||||
pObj->PrepareDeletion(GetTime<std::chrono::seconds>().count());
|
||||
}
|
||||
LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- Removing trigger object %s\n", __func__,
|
||||
strDataAsPlainString);
|
||||
// delete the trigger
|
||||
mapTrigger.erase(it++);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Active Triggers
|
||||
*
|
||||
* - Look through triggers and scan for active ones
|
||||
* - Return the triggers in a list
|
||||
*/
|
||||
|
||||
std::vector<CSuperblock_sptr> CGovernanceManager::GetActiveTriggers() const
|
||||
{
|
||||
AssertLockHeld(cs);
|
||||
std::vector<CSuperblock_sptr> vecResults;
|
||||
|
||||
// LOOK AT THESE OBJECTS AND COMPILE A VALID LIST OF TRIGGERS
|
||||
for (const auto& pair : mapTrigger) {
|
||||
const CGovernanceObject* pObj = FindConstGovernanceObject(pair.first);
|
||||
if (pObj) {
|
||||
vecResults.push_back(pair.second);
|
||||
}
|
||||
}
|
||||
|
||||
return vecResults;
|
||||
}
|
||||
|
||||
bool CGovernanceManager::IsSuperblockTriggered(const CDeterministicMNList& tip_mn_list, int nBlockHeight)
|
||||
{
|
||||
LogPrint(BCLog::GOBJECT, "IsSuperblockTriggered -- Start nBlockHeight = %d\n", nBlockHeight);
|
||||
if (!CSuperblock::IsValidBlockHeight(nBlockHeight)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LOCK(cs);
|
||||
// GET ALL ACTIVE TRIGGERS
|
||||
std::vector<CSuperblock_sptr> vecTriggers = GetActiveTriggers();
|
||||
|
||||
LogPrint(BCLog::GOBJECT, "IsSuperblockTriggered -- vecTriggers.size() = %d\n", vecTriggers.size());
|
||||
|
||||
for (const auto& pSuperblock : vecTriggers) {
|
||||
if (!pSuperblock) {
|
||||
LogPrintf("IsSuperblockTriggered -- Non-superblock found, continuing\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
CGovernanceObject* pObj = FindGovernanceObject(pSuperblock->GetGovernanceObjHash());
|
||||
if (!pObj) {
|
||||
LogPrintf("IsSuperblockTriggered -- pObj == nullptr, continuing\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
LogPrint(BCLog::GOBJECT, "IsSuperblockTriggered -- data = %s\n", pObj->GetDataAsPlainString());
|
||||
|
||||
// note : 12.1 - is epoch calculation correct?
|
||||
|
||||
if (nBlockHeight != pSuperblock->GetBlockHeight()) {
|
||||
LogPrint(BCLog::GOBJECT, /* Continued */
|
||||
"IsSuperblockTriggered -- block height doesn't match nBlockHeight = %d, blockStart = %d, "
|
||||
"continuing\n",
|
||||
nBlockHeight, pSuperblock->GetBlockHeight());
|
||||
continue;
|
||||
}
|
||||
|
||||
// MAKE SURE THIS TRIGGER IS ACTIVE VIA FUNDING CACHE FLAG
|
||||
|
||||
pObj->UpdateSentinelVariables(tip_mn_list);
|
||||
|
||||
if (pObj->IsSetCachedFunding()) {
|
||||
LogPrint(BCLog::GOBJECT, "IsSuperblockTriggered -- fCacheFunding = true, returning true\n");
|
||||
return true;
|
||||
} else {
|
||||
LogPrint(BCLog::GOBJECT, "IsSuperblockTriggered -- fCacheFunding = false, continuing\n");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CGovernanceManager::GetBestSuperblock(const CDeterministicMNList& tip_mn_list, CSuperblock_sptr& pSuperblockRet,
|
||||
int nBlockHeight)
|
||||
{
|
||||
if (!CSuperblock::IsValidBlockHeight(nBlockHeight)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AssertLockHeld(cs);
|
||||
std::vector<CSuperblock_sptr> vecTriggers = GetActiveTriggers();
|
||||
int nYesCount = 0;
|
||||
|
||||
for (const auto& pSuperblock : vecTriggers) {
|
||||
if (!pSuperblock || nBlockHeight != pSuperblock->GetBlockHeight()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const CGovernanceObject* pObj = FindGovernanceObject(pSuperblock->GetGovernanceObjHash());
|
||||
if (!pObj) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// DO WE HAVE A NEW WINNER?
|
||||
|
||||
int nTempYesCount = pObj->GetAbsoluteYesCount(tip_mn_list, VOTE_SIGNAL_FUNDING);
|
||||
if (nTempYesCount > nYesCount) {
|
||||
nYesCount = nTempYesCount;
|
||||
pSuperblockRet = pSuperblock;
|
||||
}
|
||||
}
|
||||
|
||||
return nYesCount > 0;
|
||||
}
|
||||
|
||||
bool CGovernanceManager::GetSuperblockPayments(const CDeterministicMNList& tip_mn_list, int nBlockHeight,
|
||||
std::vector<CTxOut>& voutSuperblockRet)
|
||||
{
|
||||
LOCK(cs);
|
||||
|
||||
// GET THE BEST SUPERBLOCK FOR THIS BLOCK HEIGHT
|
||||
|
||||
CSuperblock_sptr pSuperblock;
|
||||
if (!GetBestSuperblock(tip_mn_list, pSuperblock, nBlockHeight)) {
|
||||
LogPrint(BCLog::GOBJECT, "GetSuperblockPayments -- Can't find superblock for height %d\n", nBlockHeight);
|
||||
return false;
|
||||
}
|
||||
|
||||
// make sure it's empty, just in case
|
||||
voutSuperblockRet.clear();
|
||||
|
||||
// GET SUPERBLOCK OUTPUTS
|
||||
|
||||
// Superblock payments will be appended to the end of the coinbase vout vector
|
||||
|
||||
// TODO: How many payments can we add before things blow up?
|
||||
// Consider at least following limits:
|
||||
// - max coinbase tx size
|
||||
// - max "budget" available
|
||||
for (int i = 0; i < pSuperblock->CountPayments(); i++) {
|
||||
CGovernancePayment payment;
|
||||
if (pSuperblock->GetPayment(i, payment)) {
|
||||
// SET COINBASE OUTPUT TO SUPERBLOCK SETTING
|
||||
|
||||
CTxOut txout = CTxOut(payment.nAmount, payment.script);
|
||||
voutSuperblockRet.push_back(txout);
|
||||
|
||||
// PRINT NICE LOG OUTPUT FOR SUPERBLOCK PAYMENT
|
||||
|
||||
CTxDestination dest;
|
||||
ExtractDestination(payment.script, dest);
|
||||
|
||||
LogPrint(BCLog::GOBJECT, "GetSuperblockPayments -- NEW Superblock: output %d (addr %s, amount %d.%08d)\n",
|
||||
i, EncodeDestination(dest), payment.nAmount / COIN, payment.nAmount % COIN);
|
||||
} else {
|
||||
LogPrint(BCLog::GOBJECT, "GetSuperblockPayments -- Payment not found\n");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGovernanceManager::IsValidSuperblock(const CChain& active_chain, const CDeterministicMNList& tip_mn_list,
|
||||
const CTransaction& txNew, int nBlockHeight, CAmount blockReward)
|
||||
{
|
||||
// GET BEST SUPERBLOCK, SHOULD MATCH
|
||||
LOCK(cs);
|
||||
|
||||
CSuperblock_sptr pSuperblock;
|
||||
if (GetBestSuperblock(tip_mn_list, pSuperblock, nBlockHeight)) {
|
||||
return pSuperblock->IsValid(active_chain, txNew, nBlockHeight, blockReward);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CGovernanceManager::ExecuteBestSuperblock(const CDeterministicMNList& tip_mn_list, int nBlockHeight)
|
||||
{
|
||||
LOCK(cs);
|
||||
|
||||
CSuperblock_sptr pSuperblock;
|
||||
if (GetBestSuperblock(tip_mn_list, pSuperblock, nBlockHeight)) {
|
||||
// All checks are done in CSuperblock::IsValid via IsBlockValueValid and IsBlockPayeeValid,
|
||||
// tip wouldn't be updated if anything was wrong. Mark this trigger as executed.
|
||||
pSuperblock->SetExecuted();
|
||||
ResetVotedFundingTrigger();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool AreSuperblocksEnabled(const CSporkManager& sporkman)
|
||||
{
|
||||
return sporkman.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED);
|
||||
|
@ -69,7 +69,7 @@ public:
|
||||
fBufferEmpty = false;
|
||||
}
|
||||
|
||||
int64_t GetMinTimestamp()
|
||||
int64_t GetMinTimestamp() const
|
||||
{
|
||||
int nIndex = nDataStart;
|
||||
int64_t nMin = std::numeric_limits<int64_t>::max();
|
||||
@ -85,7 +85,7 @@ public:
|
||||
return nMin;
|
||||
}
|
||||
|
||||
int64_t GetMaxTimestamp()
|
||||
int64_t GetMaxTimestamp() const
|
||||
{
|
||||
int nIndex = nDataStart;
|
||||
int64_t nMax = 0;
|
||||
@ -112,7 +112,7 @@ public:
|
||||
return RATE_BUFFER_SIZE - nDataStart + nDataEnd;
|
||||
}
|
||||
|
||||
double GetRate()
|
||||
double GetRate() const
|
||||
{
|
||||
int nCount = GetCount();
|
||||
if (nCount < RATE_BUFFER_SIZE) {
|
||||
@ -228,29 +228,8 @@ class CGovernanceManager : public GovernanceStore
|
||||
friend class CGovernanceObject;
|
||||
|
||||
private:
|
||||
using hash_s_t = std::set<uint256>;
|
||||
using db_type = CFlatDB<GovernanceStore>;
|
||||
|
||||
class ScopedLockBool
|
||||
{
|
||||
bool& ref;
|
||||
bool fPrevValue;
|
||||
|
||||
public:
|
||||
ScopedLockBool(RecursiveMutex& _cs, bool& _ref, bool _value) :
|
||||
ref(_ref)
|
||||
{
|
||||
AssertLockHeld(_cs);
|
||||
fPrevValue = ref;
|
||||
ref = _value;
|
||||
}
|
||||
|
||||
~ScopedLockBool()
|
||||
{
|
||||
ref = fPrevValue;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
static const int MAX_TIME_FUTURE_DEVIATION;
|
||||
static const int RELIABLE_PROPAGATION_TIME;
|
||||
@ -263,22 +242,22 @@ private:
|
||||
CNetFulfilledRequestManager& m_netfulfilledman;
|
||||
const ChainstateManager& m_chainman;
|
||||
const std::unique_ptr<CDeterministicMNManager>& m_dmnman;
|
||||
const std::unique_ptr<CMasternodeSync>& m_mn_sync;
|
||||
CMasternodeSync& m_mn_sync;
|
||||
|
||||
int64_t nTimeLastDiff;
|
||||
// keep track of current block height
|
||||
int nCachedBlockHeight;
|
||||
std::map<uint256, CGovernanceObject> mapPostponedObjects;
|
||||
hash_s_t setAdditionalRelayObjects;
|
||||
std::set<uint256> setAdditionalRelayObjects;
|
||||
std::map<uint256, std::chrono::seconds> m_requested_hash_time;
|
||||
bool fRateChecksEnabled;
|
||||
std::optional<uint256> votedFundingYesTriggerHash;
|
||||
std::map<uint256, std::shared_ptr<CSuperblock>> mapTrigger;
|
||||
|
||||
public:
|
||||
explicit CGovernanceManager(CMasternodeMetaMan& mn_metaman, CNetFulfilledRequestManager& netfulfilledman, const ChainstateManager& chainman,
|
||||
const std::unique_ptr<CDeterministicMNManager>& dmnman,
|
||||
const std::unique_ptr<CMasternodeSync>& mn_sync);
|
||||
explicit CGovernanceManager(CMasternodeMetaMan& mn_metaman, CNetFulfilledRequestManager& netfulfilledman,
|
||||
const ChainstateManager& chainman,
|
||||
const std::unique_ptr<CDeterministicMNManager>& dmnman, CMasternodeSync& mn_sync);
|
||||
~CGovernanceManager();
|
||||
|
||||
bool LoadCache(bool load_cache);
|
||||
@ -297,8 +276,10 @@ public:
|
||||
|
||||
PeerMsgRet ProcessMessage(CNode& peer, CConnman& connman, PeerManager& peerman, std::string_view msg_type, CDataStream& vRecv);
|
||||
|
||||
private:
|
||||
void ResetVotedFundingTrigger();
|
||||
|
||||
public:
|
||||
void DoMaintenance(CConnman& connman);
|
||||
|
||||
const CGovernanceObject* FindConstGovernanceObject(const uint256& nHash) const EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
@ -366,11 +347,34 @@ public:
|
||||
* - Track governance objects which are triggers
|
||||
* - After triggers are activated and executed, they can be removed
|
||||
*/
|
||||
std::vector<std::shared_ptr<CSuperblock>> GetActiveTriggers();
|
||||
std::vector<std::shared_ptr<CSuperblock>> GetActiveTriggers() const;
|
||||
bool AddNewTrigger(uint256 nHash);
|
||||
void CleanAndRemoveTriggers();
|
||||
|
||||
// Superblocks related:
|
||||
|
||||
/**
|
||||
* Is Superblock Triggered
|
||||
*
|
||||
* - Does this block have a non-executed and activated trigger?
|
||||
*/
|
||||
bool IsSuperblockTriggered(const CDeterministicMNList& tip_mn_list, int nBlockHeight);
|
||||
|
||||
/**
|
||||
* Get Superblock Payments
|
||||
*
|
||||
* - Returns payments for superblock
|
||||
*/
|
||||
bool GetSuperblockPayments(const CDeterministicMNList& tip_mn_list, int nBlockHeight,
|
||||
std::vector<CTxOut>& voutSuperblockRet);
|
||||
|
||||
bool IsValidSuperblock(const CChain& active_chain, const CDeterministicMNList& tip_mn_list,
|
||||
const CTransaction& txNew, int nBlockHeight, CAmount blockReward);
|
||||
|
||||
private:
|
||||
void ExecuteBestSuperblock(const CDeterministicMNList& tip_mn_list, int nBlockHeight);
|
||||
bool GetBestSuperblock(const CDeterministicMNList& tip_mn_list, CSuperblock_sptr& pSuperblockRet, int nBlockHeight);
|
||||
|
||||
std::optional<const CSuperblock> CreateSuperblockCandidate(int nHeight) const;
|
||||
std::optional<const CGovernanceObject> CreateGovernanceTrigger(const std::optional<const CSuperblock>& sb_opt, PeerManager& peerman,
|
||||
const CActiveMasternodeManager& mn_activeman);
|
||||
|
@ -1862,9 +1862,9 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||
* need it or not further down and then query if the database is initialized
|
||||
* to check if validation is enabled.
|
||||
*/
|
||||
node.govman = std::make_unique<CGovernanceManager>(*node.mn_metaman, *node.netfulfilledman, *node.chainman, node.dmnman, node.mn_sync);
|
||||
node.mn_sync = std::make_unique<CMasternodeSync>(*node.connman, *node.netfulfilledman);
|
||||
|
||||
node.mn_sync = std::make_unique<CMasternodeSync>(*node.connman, *node.netfulfilledman, *node.govman);
|
||||
node.govman = std::make_unique<CGovernanceManager>(*node.mn_metaman, *node.netfulfilledman, *node.chainman, node.dmnman, *node.mn_sync);
|
||||
|
||||
const bool fReset = fReindex;
|
||||
auto is_coinsview_empty = [&](CChainState* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
|
||||
@ -2282,7 +2282,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||
// ********************************************************* Step 10a: schedule Dash-specific tasks
|
||||
|
||||
node.scheduler->scheduleEvery(std::bind(&CNetFulfilledRequestManager::DoMaintenance, std::ref(*node.netfulfilledman)), std::chrono::minutes{1});
|
||||
node.scheduler->scheduleEvery(std::bind(&CMasternodeSync::DoMaintenance, std::ref(*node.mn_sync), std::cref(*node.peerman)), std::chrono::seconds{1});
|
||||
node.scheduler->scheduleEvery(std::bind(&CMasternodeSync::DoMaintenance, std::ref(*node.mn_sync), std::cref(*node.peerman), std::cref(*node.govman)), std::chrono::seconds{1});
|
||||
node.scheduler->scheduleEvery(std::bind(&CMasternodeUtils::DoMaintenance, std::ref(*node.connman), std::ref(*node.dmnman), std::ref(*node.mn_sync), std::ref(*node.cj_ctx)), std::chrono::minutes{1});
|
||||
node.scheduler->scheduleEvery(std::bind(&CDeterministicMNManager::DoMaintenance, std::ref(*node.dmnman)), std::chrono::seconds{10});
|
||||
|
||||
|
@ -246,7 +246,7 @@ bool CMNPaymentsProcessor::IsBlockValueValid(const CBlock& block, const int nBlo
|
||||
|
||||
const auto tip_mn_list = m_dmnman.GetListAtChainTip();
|
||||
|
||||
if (!CSuperblockManager::IsSuperblockTriggered(m_govman, tip_mn_list, nBlockHeight)) {
|
||||
if (!m_govman.IsSuperblockTriggered(tip_mn_list, nBlockHeight)) {
|
||||
// we are on a valid superblock height but a superblock was not triggered
|
||||
// revert to block reward limits in this case
|
||||
if(!isBlockRewardValueMet) {
|
||||
@ -257,7 +257,7 @@ bool CMNPaymentsProcessor::IsBlockValueValid(const CBlock& block, const int nBlo
|
||||
}
|
||||
|
||||
// this actually also checks for correct payees and not only amount
|
||||
if (!CSuperblockManager::IsValid(m_govman, m_chainman.ActiveChain(), tip_mn_list, *block.vtx[0], nBlockHeight, blockReward)) {
|
||||
if (!m_govman.IsValidSuperblock(m_chainman.ActiveChain(), tip_mn_list, *block.vtx[0], nBlockHeight, blockReward)) {
|
||||
// triggered but invalid? that's weird
|
||||
LogPrintf("CMNPaymentsProcessor::%s -- ERROR! Invalid superblock detected at height %d: %s", __func__, nBlockHeight, block.vtx[0]->ToString()); /* Continued */
|
||||
// should NOT allow invalid superblocks, when superblocks are enabled
|
||||
@ -302,8 +302,9 @@ bool CMNPaymentsProcessor::IsBlockPayeeValid(const CTransaction& txNew, const CB
|
||||
if (AreSuperblocksEnabled(m_sporkman)) {
|
||||
if (!check_superblock) return true;
|
||||
const auto tip_mn_list = m_dmnman.GetListAtChainTip();
|
||||
if (CSuperblockManager::IsSuperblockTriggered(m_govman, tip_mn_list, nBlockHeight)) {
|
||||
if (CSuperblockManager::IsValid(m_govman, m_chainman.ActiveChain(), tip_mn_list, txNew, nBlockHeight, blockSubsidy + feeReward)) {
|
||||
if (m_govman.IsSuperblockTriggered(tip_mn_list, nBlockHeight)) {
|
||||
if (m_govman.IsValidSuperblock(m_chainman.ActiveChain(), tip_mn_list, txNew, nBlockHeight,
|
||||
blockSubsidy + feeReward)) {
|
||||
LogPrint(BCLog::GOBJECT, "CMNPaymentsProcessor::%s -- Valid superblock at height %d: %s", __func__, nBlockHeight, txNew.ToString()); /* Continued */
|
||||
// continue validation, should also pay MN
|
||||
} else {
|
||||
@ -330,9 +331,9 @@ void CMNPaymentsProcessor::FillBlockPayments(CMutableTransaction& txNew, const C
|
||||
// only create superblocks if spork is enabled AND if superblock is actually triggered
|
||||
// (height should be validated inside)
|
||||
const auto tip_mn_list = m_dmnman.GetListAtChainTip();
|
||||
if(AreSuperblocksEnabled(m_sporkman) && CSuperblockManager::IsSuperblockTriggered(m_govman, tip_mn_list, nBlockHeight)) {
|
||||
if (AreSuperblocksEnabled(m_sporkman) && m_govman.IsSuperblockTriggered(tip_mn_list, nBlockHeight)) {
|
||||
LogPrint(BCLog::GOBJECT, "CMNPaymentsProcessor::%s -- Triggered superblock creation at height %d\n", __func__, nBlockHeight);
|
||||
CSuperblockManager::GetSuperblockPayments(m_govman, tip_mn_list, nBlockHeight, voutSuperblockPaymentsRet);
|
||||
m_govman.GetSuperblockPayments(tip_mn_list, nBlockHeight, voutSuperblockPaymentsRet);
|
||||
}
|
||||
|
||||
if (!GetMasternodeTxOuts(pindexPrev, blockSubsidy, feeReward, voutMasternodePaymentsRet)) {
|
||||
|
@ -16,12 +16,11 @@
|
||||
|
||||
class CMasternodeSync;
|
||||
|
||||
CMasternodeSync::CMasternodeSync(CConnman& _connman, CNetFulfilledRequestManager& netfulfilledman, const CGovernanceManager& govman) :
|
||||
CMasternodeSync::CMasternodeSync(CConnman& _connman, CNetFulfilledRequestManager& netfulfilledman) :
|
||||
nTimeAssetSyncStarted(GetTime()),
|
||||
nTimeLastBumped(GetTime()),
|
||||
connman(_connman),
|
||||
m_netfulfilledman(netfulfilledman),
|
||||
m_govman(govman)
|
||||
m_netfulfilledman(netfulfilledman)
|
||||
{
|
||||
}
|
||||
|
||||
@ -115,7 +114,7 @@ void CMasternodeSync::ProcessMessage(const CNode& peer, std::string_view msg_typ
|
||||
LogPrint(BCLog::MNSYNC, "SYNCSTATUSCOUNT -- got inventory count: nItemID=%d nCount=%d peer=%d\n", nItemID, nCount, peer.GetId());
|
||||
}
|
||||
|
||||
void CMasternodeSync::ProcessTick(const PeerManager& peerman)
|
||||
void CMasternodeSync::ProcessTick(const PeerManager& peerman, const CGovernanceManager& govman)
|
||||
{
|
||||
assert(m_netfulfilledman.IsValid());
|
||||
|
||||
@ -144,7 +143,7 @@ void CMasternodeSync::ProcessTick(const PeerManager& peerman)
|
||||
|
||||
// gradually request the rest of the votes after sync finished
|
||||
if(IsSynced()) {
|
||||
m_govman.RequestGovernanceObjectVotes(snap.Nodes(), connman, peerman);
|
||||
govman.RequestGovernanceObjectVotes(snap.Nodes(), connman, peerman);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -219,7 +218,7 @@ void CMasternodeSync::ProcessTick(const PeerManager& peerman)
|
||||
// GOVOBJ : SYNC GOVERNANCE ITEMS FROM OUR PEERS
|
||||
|
||||
if(nCurrentAsset == MASTERNODE_SYNC_GOVERNANCE) {
|
||||
if (!m_govman.IsValid()) {
|
||||
if (!govman.IsValid()) {
|
||||
SwitchToNextAsset();
|
||||
return;
|
||||
}
|
||||
@ -264,7 +263,7 @@ void CMasternodeSync::ProcessTick(const PeerManager& peerman)
|
||||
if(!m_netfulfilledman.HasFulfilledRequest(pnode->addr, "governance-sync")) {
|
||||
continue; // to early for this node
|
||||
}
|
||||
int nObjsLeftToAsk = m_govman.RequestGovernanceObjectVotes(*pnode, connman, peerman);
|
||||
int nObjsLeftToAsk = govman.RequestGovernanceObjectVotes(*pnode, connman, peerman);
|
||||
// check for data
|
||||
if(nObjsLeftToAsk == 0) {
|
||||
static int64_t nTimeNoObjectsLeft = 0;
|
||||
@ -277,8 +276,7 @@ void CMasternodeSync::ProcessTick(const PeerManager& peerman)
|
||||
// make sure the condition below is checked only once per tick
|
||||
if(nLastTick == nTick) continue;
|
||||
if (GetTime() - nTimeNoObjectsLeft > MASTERNODE_SYNC_TIMEOUT_SECONDS &&
|
||||
m_govman.GetVoteCount() - nLastVotes < std::max(int(0.0001 * nLastVotes), MASTERNODE_SYNC_TICK_SECONDS)
|
||||
) {
|
||||
govman.GetVoteCount() - nLastVotes < std::max(int(0.0001 * nLastVotes), MASTERNODE_SYNC_TICK_SECONDS)) {
|
||||
// We already asked for all objects, waited for MASTERNODE_SYNC_TIMEOUT_SECONDS
|
||||
// after that and less then 0.01% or MASTERNODE_SYNC_TICK_SECONDS
|
||||
// (i.e. 1 per second) votes were received during the last tick.
|
||||
@ -290,7 +288,7 @@ void CMasternodeSync::ProcessTick(const PeerManager& peerman)
|
||||
return;
|
||||
}
|
||||
nLastTick = nTick;
|
||||
nLastVotes = m_govman.GetVoteCount();
|
||||
nLastVotes = govman.GetVoteCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -368,9 +366,9 @@ void CMasternodeSync::UpdatedBlockTip(const CBlockIndex *pindexTip, const CBlock
|
||||
pindexNew->nHeight, pindexTip->nHeight, fInitialDownload, fReachedBestHeader);
|
||||
}
|
||||
|
||||
void CMasternodeSync::DoMaintenance(const PeerManager& peerman)
|
||||
void CMasternodeSync::DoMaintenance(const PeerManager& peerman, const CGovernanceManager& govman)
|
||||
{
|
||||
if (ShutdownRequested()) return;
|
||||
|
||||
ProcessTick(peerman);
|
||||
ProcessTick(peerman, govman);
|
||||
}
|
||||
|
@ -51,10 +51,9 @@ private:
|
||||
|
||||
CConnman& connman;
|
||||
CNetFulfilledRequestManager& m_netfulfilledman;
|
||||
const CGovernanceManager& m_govman;
|
||||
|
||||
public:
|
||||
explicit CMasternodeSync(CConnman& _connman, CNetFulfilledRequestManager& netfulfilledman, const CGovernanceManager& govman);
|
||||
explicit CMasternodeSync(CConnman& _connman, CNetFulfilledRequestManager& netfulfilledman);
|
||||
|
||||
void SendGovernanceSyncRequest(CNode* pnode) const;
|
||||
|
||||
@ -72,13 +71,13 @@ public:
|
||||
void SwitchToNextAsset();
|
||||
|
||||
void ProcessMessage(const CNode& peer, std::string_view msg_type, CDataStream& vRecv) const;
|
||||
void ProcessTick(const PeerManager& peerman);
|
||||
void ProcessTick(const PeerManager& peerman, const CGovernanceManager& govman);
|
||||
|
||||
void AcceptedBlockHeader(const CBlockIndex *pindexNew);
|
||||
void NotifyHeaderTip(const CBlockIndex *pindexNew, bool fInitialDownload);
|
||||
void UpdatedBlockTip(const CBlockIndex *pindexTip, const CBlockIndex *pindexNew, bool fInitialDownload);
|
||||
|
||||
void DoMaintenance(const PeerManager& peerman);
|
||||
void DoMaintenance(const PeerManager& peerman, const CGovernanceManager& govman);
|
||||
};
|
||||
|
||||
#endif // BITCOIN_MASTERNODE_SYNC_H
|
||||
|
@ -956,14 +956,14 @@ static RPCHelpMan voteraw()
|
||||
|
||||
const NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
CHECK_NONFATAL(node.govman);
|
||||
GovernanceObject govObjType = WITH_LOCK(node.govman->cs, return [&](){
|
||||
AssertLockHeld(node.govman->cs);
|
||||
GovernanceObject govObjType = [&]() {
|
||||
LOCK(node.govman->cs);
|
||||
const CGovernanceObject *pGovObj = node.govman->FindConstGovernanceObject(hashGovObj);
|
||||
if (!pGovObj) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Governance object not found");
|
||||
}
|
||||
return pGovObj->GetObjectType();
|
||||
}());
|
||||
}();
|
||||
|
||||
|
||||
int64_t nTime = request.params[5].get_int64();
|
||||
|
@ -253,9 +253,9 @@ static std::string GetRequiredPaymentsString(CGovernanceManager& govman, const C
|
||||
strPayments += ", " + EncodeDestination(dest);
|
||||
}
|
||||
}
|
||||
if (CSuperblockManager::IsSuperblockTriggered(govman, tip_mn_list, nBlockHeight)) {
|
||||
if (govman.IsSuperblockTriggered(tip_mn_list, nBlockHeight)) {
|
||||
std::vector<CTxOut> voutSuperblock;
|
||||
if (!CSuperblockManager::GetSuperblockPayments(govman, tip_mn_list, nBlockHeight, voutSuperblock)) {
|
||||
if (!govman.GetSuperblockPayments(tip_mn_list, nBlockHeight, voutSuperblock)) {
|
||||
return strPayments + ", error";
|
||||
}
|
||||
std::string strSBPayees = "Unknown";
|
||||
|
@ -245,8 +245,8 @@ ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::ve
|
||||
m_node.mn_metaman = std::make_unique<CMasternodeMetaMan>();
|
||||
m_node.netfulfilledman = std::make_unique<CNetFulfilledRequestManager>();
|
||||
m_node.sporkman = std::make_unique<CSporkManager>();
|
||||
m_node.govman = std::make_unique<CGovernanceManager>(*m_node.mn_metaman, *m_node.netfulfilledman, *m_node.chainman, m_node.dmnman, m_node.mn_sync);
|
||||
m_node.mn_sync = std::make_unique<CMasternodeSync>(*m_node.connman, *m_node.netfulfilledman, *m_node.govman);
|
||||
m_node.mn_sync = std::make_unique<CMasternodeSync>(*m_node.connman, *m_node.netfulfilledman);
|
||||
m_node.govman = std::make_unique<CGovernanceManager>(*m_node.mn_metaman, *m_node.netfulfilledman, *m_node.chainman, m_node.dmnman, *m_node.mn_sync);
|
||||
|
||||
// Start script-checking threads. Set g_parallel_script_checks to true so they are used.
|
||||
constexpr int script_check_threads = 2;
|
||||
|
@ -26,7 +26,6 @@ EXPECTED_CIRCULAR_DEPENDENCIES=(
|
||||
"evo/cbtx -> evo/simplifiedmns -> evo/cbtx"
|
||||
"evo/deterministicmns -> llmq/commitment -> evo/deterministicmns"
|
||||
"evo/deterministicmns -> llmq/utils -> evo/deterministicmns"
|
||||
"governance/classes -> governance/governance -> governance/classes"
|
||||
"governance/governance -> governance/object -> governance/governance"
|
||||
"governance/governance -> masternode/sync -> governance/governance"
|
||||
"llmq/chainlocks -> llmq/instantsend -> llmq/chainlocks"
|
||||
|
@ -9,6 +9,7 @@ src/coinjoin/*.h
|
||||
src/ctpl_stl.h
|
||||
src/cxxtimer.hpp
|
||||
src/dsnotificationinterface.*
|
||||
src/flat-database.h
|
||||
src/evo/*.cpp
|
||||
src/evo/*.h
|
||||
src/governance/*.cpp
|
||||
|
Loading…
Reference in New Issue
Block a user