mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 20:12:57 +01:00
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:
parent
350a5ca47c
commit
39f18ab154
@ -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(),
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user