refactor: move CGoveranceManager code from classes.cpp to governace.cpp

There's only code move, no changes. For review use `git show --color-moved=dimmed-zebra`
This commit is contained in:
Konstantin Akimov 2024-10-06 21:48:31 +07:00
parent 350a5ca47c
commit 39f18ab154
No known key found for this signature in database
GPG Key ID: 2176C4A5D01EA524
2 changed files with 287 additions and 284 deletions

View File

@ -94,290 +94,6 @@ CAmount ParsePaymentAmount(const std::string& strAmount)
return nAmount; 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() 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,
"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) const
{
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(*this, 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();
}
}
CSuperblock:: CSuperblock::
CSuperblock() : CSuperblock() :
nGovObjHash(), nGovObjHash(),

View File

@ -1634,6 +1634,293 @@ void CGovernanceManager::RemoveInvalidVotes()
lastMNListForVotingKeys = std::make_shared<CDeterministicMNList>(tip_mn_list); 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 {
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() 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(*this, 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) bool AreSuperblocksEnabled(const CSporkManager& sporkman)
{ {
return sporkman.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED); return sporkman.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED);