More for governance block checks, p1 (non-compilable):

- add GetPaymentsLimit() and GetPaymentsTotalAmount()
- IsValidBlockHeight() should check nSuperblockStartBlock
- CSuperblock::IsValid should check payment limit and miner payout
- no cs_main
- slightly refactored related things
This commit is contained in:
UdjinM6 2016-08-20 08:31:39 +03:00
parent b6b6d6c4c5
commit 15a3c64270
2 changed files with 101 additions and 75 deletions

View File

@ -299,9 +299,8 @@ std::vector<CSuperblock_sptr> CGovernanceTriggerManager::GetActiveTriggers()
bool CSuperblockManager::IsSuperblockTriggered(int nBlockHeight) bool CSuperblockManager::IsSuperblockTriggered(int nBlockHeight)
{ {
if (!IsValidSuperblockHeight(nBlockHeight)) { if (!CSuperblock::IsValidBlockHeight(nBlockHeight))
return false; return false;
}
LOCK(governance.cs); LOCK(governance.cs);
// GET ALL ACTIVE TRIGGERS // GET ALL ACTIVE TRIGGERS
@ -392,17 +391,11 @@ bool CSuperblockManager::GetBestSuperblock(CSuperblock_sptr& pBlock, int nBlockH
* - Create the correct payment structure for a given superblock * - Create the correct payment structure for a given superblock
*/ */
void CSuperblockManager::CreateSuperblock(CMutableTransaction& txNew, CAmount nFees, int nBlockHeight) void CSuperblockManager::CreateSuperblock(CMutableTransaction& txNew, int nBlockHeight)
{ {
DBG( cout << "CSuperblockManager::CreateSuperblock Start" << endl; ); DBG( cout << "CSuperblockManager::CreateSuperblock Start" << endl; );
LOCK(governance.cs); LOCK(governance.cs);
AssertLockHeld(cs_main);
if(!chainActive.Tip()) {
DBG( cout << "CSuperblockManager::CreateSuperblock No active tip, returning" << endl; );
return;
}
// GET THE BEST SUPERBLOCK FOR THIS BLOCK HEIGHT // GET THE BEST SUPERBLOCK FOR THIS BLOCK HEIGHT
@ -419,6 +412,10 @@ void CSuperblockManager::CreateSuperblock(CMutableTransaction& txNew, CAmount nF
DBG( cout << "CSuperblockManager::CreateSuperblock Number payments: " << pBlock->CountPayments() << endl; ); DBG( cout << "CSuperblockManager::CreateSuperblock Number payments: " << pBlock->CountPayments() << endl; );
// 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 < pBlock->CountPayments(); i++) { for(int i = 0; i < pBlock->CountPayments(); i++) {
CGovernancePayment payment; CGovernancePayment payment;
DBG( cout << "CSuperblockManager::CreateSuperblock i = " << i << endl; ); DBG( cout << "CSuperblockManager::CreateSuperblock i = " << i << endl; );
@ -449,14 +446,14 @@ void CSuperblockManager::CreateSuperblock(CMutableTransaction& txNew, CAmount nF
DBG( cout << "CSuperblockManager::CreateSuperblock End" << endl; ); DBG( cout << "CSuperblockManager::CreateSuperblock End" << endl; );
} }
bool CSuperblockManager::IsValid(const CTransaction& txNew, int nBlockHeight) bool CSuperblockManager::IsValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward)
{ {
// GET BEST SUPERBLOCK, SHOULD MATCH // GET BEST SUPERBLOCK, SHOULD MATCH
LOCK(governance.cs); LOCK(governance.cs);
CSuperblock_sptr pBlock; CSuperblock_sptr pSuperblock;
if(CSuperblockManager::GetBestSuperblock(pBlock, nBlockHeight)) { if(CSuperblockManager::GetBestSuperblock(pSuperblock, nBlockHeight)) {
return pBlock->IsValid(txNew); return pSuperblock->IsValid(txNew, nBlockHeight, blockReward);
} }
return false; return false;
@ -512,9 +509,31 @@ CSuperblock(uint256& nHash)
DBG( cout << "CSuperblock Constructor End" << endl; ); DBG( cout << "CSuperblock Constructor End" << endl; );
} }
void bool CSuperblock::IsValidBlockHeight(int nBlockHeight)
CSuperblock:: {
ParsePaymentSchedule(std::string& strPaymentAddresses, std::string& strPaymentAmounts) // SUPERBLOCKS CAN HAPPEN ONLY after hardfork and only ONCE PER CYCLE
return nBlockHeight >= Params().GetConsensus().nSuperblockStartBlock &&
((nBlockHeight % Params().GetConsensus().nSuperblockCycle) == 0);
}
CAmount CSuperblock::GetPaymentsLimit(int nBlockHeight)
{
const Consensus::Params& consensusParams = Params().GetConsensus();
if(!IsValidBlockHeight(nBlockHeight))
return 0;
// min subsidy for high diff networks and vice versa
int nBits = consensusParams.fPowAllowMinDifficultyBlocks ? UintToArith256(consensusParams.powLimit).GetCompact() : 1;
CAmount nBlockSubsidy = GetBlockSubsidy(nBits, nBlockHeight, consensusParams);
// 10% of all blocks issued during the cycle goes to superblock
CAmount nPaymentsLimit = nBlockSubsidy * consensusParams.nSuperblockCycle / 10;
LogPrint("gobject", "CSuperblock::GetPaymentsLimit -- Valid superblock height %d, payments max %lld\n", nBlockHeight, nPaymentsLimit);
return nPaymentsLimit;
}
void CSuperblock::ParsePaymentSchedule(std::string& strPaymentAddresses, std::string& strPaymentAmounts)
{ {
// SPLIT UP ADDR/AMOUNT STRINGS AND PUT IN VECTORS // SPLIT UP ADDR/AMOUNT STRINGS AND PUT IN VECTORS
@ -571,6 +590,27 @@ ParsePaymentSchedule(std::string& strPaymentAddresses, std::string& strPaymentAm
} }
} }
bool CSuperblock::GetPayment(int nPaymentIndex, CGovernancePayment& paymentRet)
{
if((nPaymentIndex<0) || (nPaymentIndex >= (int)vecPayments.size())) {
return false;
}
paymentRet = vecPayments[nPaymentIndex];
return true;
}
CAmount CSuperblock::GetPaymentsTotalAmount()
{
CAmount nPaymentsTotalAmount = 0;
int nPayments = CountPayments();
for(int i = 0; i < nPayments; i++) {
nPaymentsTotalAmount += vecPayments[i].nAmount;
}
return nPaymentsTotalAmount;
}
/** /**
* Is Transaction Valid * Is Transaction Valid
@ -578,7 +618,7 @@ ParsePaymentSchedule(std::string& strPaymentAddresses, std::string& strPaymentAm
* - Does this transaction match the superblock? * - Does this transaction match the superblock?
*/ */
bool CSuperblock::IsValid(const CTransaction& txNew) bool CSuperblock::IsValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward)
{ {
// TODO : LOCK(cs); // TODO : LOCK(cs);
// No reason for a lock here now since this method only accesses data // No reason for a lock here now since this method only accesses data
@ -598,18 +638,34 @@ bool CSuperblock::IsValid(const CTransaction& txNew)
// superblock payments and the payments actually in the block, after // superblock payments and the payments actually in the block, after
// skipping any initial miner payments. // skipping any initial miner payments.
if(nMinerPayments<0) { if(nMinerPayments < 0) {
// This means the block cannot have all the superblock payments // This means the block cannot have all the superblock payments
// so it is not valid. // so it is not valid.
LogPrintf("CSuperblock::IsValid WARNING: Block invalid: Too few superblock payments"); // TODO: could that be that we just hit coinbase size limit?
LogPrintf("CSuperblock::IsValid -- ERROR: Block invalid, too few superblock payments\n");
return false;
}
// payments should not exceed limit
CAmount nPaymentsTotalAmount = GetPaymentsTotalAmount();
CAmount nPaymentsLimit = GetPaymentsLimit(nBlockHeight);
if(nPaymentsTotalAmount > nPaymentsLimit) {
LogPrintf("CSuperblock::IsValid -- ERROR: Block invalid, payments limit exceeded: payments %lld, limit %lld\n", nPaymentsTotalAmount, nPaymentsLimit);
return false;
}
// miner should not get more than he would usually get
CAmount nBlockValue = txNew.GetValueOut();
if(nBlockValue > blockReward + nPaymentsTotalAmount) {
LogPrintf("CSuperblock::IsValid -- ERROR: Block invalid, block value limit exceeded: block %lld, limit %lld\n", nBlockValue, blockReward + nPaymentsTotalAmount);
return false; return false;
} }
for(int i = 0; i < nPayments; i++) { for(int i = 0; i < nPayments; i++) {
CGovernancePayment payment; CGovernancePayment payment;
if(!GetPayment(i, payment)) { if(!GetPayment(i, payment)) {
// This shouldn't happen so log a warning // This shouldn't happen so log a warning
LogPrintf("CSuperblock::IsValid WARNING: Failed to find payment: %d of %d total payments", i, nPayments); LogPrintf("CSuperblock::IsValid -- WARNING: Failed to find payment: %d of %d total payments\n", i, nPayments);
continue; continue;
} }
@ -618,13 +674,13 @@ bool CSuperblock::IsValid(const CTransaction& txNew)
bool fPaymentMatch = ((payment.script == txNew.vout[nVoutIndex].scriptPubKey) && bool fPaymentMatch = ((payment.script == txNew.vout[nVoutIndex].scriptPubKey) &&
(payment.nAmount == txNew.vout[nVoutIndex].nValue)); (payment.nAmount == txNew.vout[nVoutIndex].nValue));
if(!fPaymentMatch) { if(!fPaymentMatch) {
// MISMATCHED SUPERBLOCK OUTPUT! // MISMATCHED SUPERBLOCK OUTPUT!
CTxDestination address1; CTxDestination address1;
ExtractDestination(payment.script, address1); ExtractDestination(payment.script, address1);
CBitcoinAddress address2(address1); CBitcoinAddress address2(address1);
LogPrintf("CSuperblock::IsValid WARNING: Block invalid: output n %d payment %d to %s\n", nVoutIndex, payment.nAmount, address2.ToString()); LogPrintf("CSuperblock::IsValid -- WARNING: Block invalid: output n %d payment %d to %s\n", nVoutIndex, payment.nAmount, address2.ToString());
return false; return false;
} }

View File

@ -83,6 +83,9 @@ private:
class CSuperblockManager class CSuperblockManager
{ {
private:
static bool GetBestSuperblock(CSuperblock_sptr& pBlock, int nBlockHeight);
public: public:
/** /**
@ -90,22 +93,12 @@ public:
* *
* - See if this block can be a superblock * - See if this block can be a superblock
*/ */
static bool IsValidSuperblockHeight(int nBlockHeight)
{
// SUPERBLOCKS CAN HAPPEN ONCE PER DAY
return ((nBlockHeight % Params().GetConsensus().nSuperblockCycle) == 1);
}
static bool IsSuperblockTriggered(int nBlockHeight); static bool IsSuperblockTriggered(int nBlockHeight);
static void CreateSuperblock(CMutableTransaction& txNew, CAmount nFees, int nBlockHeight);
static void CreateSuperblock(CMutableTransaction& txNew, int nBlockHeight);
static std::string GetRequiredPaymentsString(int nBlockHeight); static std::string GetRequiredPaymentsString(int nBlockHeight);
static bool IsValid(const CTransaction& txNew, int nBlockHeight); static bool IsValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward);
private:
static bool GetBestSuperblock(CSuperblock_sptr& pBlock, int nBlockHeight);
}; };
/** /**
@ -181,23 +174,26 @@ private:
int nStatus; int nStatus;
std::vector<CGovernancePayment> vecPayments; std::vector<CGovernancePayment> vecPayments;
void ParsePaymentSchedule(std::string& strPaymentAddresses, std::string& strPaymentAmounts);
public: public:
CSuperblock(); CSuperblock();
CSuperblock(uint256& nHash); CSuperblock(uint256& nHash);
int GetStatus() static bool IsValidBlockHeight(int nBlockHeight);
{ static CAmount GetPaymentsLimit(int nBlockHeight);
return nStatus;
}
void SetStatus(int nStatus_) int GetStatus() { return nStatus; }
{ void SetStatus(int nStatusIn) { nStatus = nStatusIn; }
nStatus = nStatus_;
}
CGovernanceObject* GetGovernanceObject() { // IS THIS TRIGGER ALREADY EXECUTED?
bool IsExecuted() { return nStatus == SEEN_OBJECT_EXECUTED; }
// TELL THE ENGINE WE EXECUTED THIS EVENT
void SetExecuted() { nStatus = SEEN_OBJECT_EXECUTED; }
CGovernanceObject* GetGovernanceObject()
{
AssertLockHeld(governance.cs); AssertLockHeld(governance.cs);
CGovernanceObject* pObj = governance.FindGovernanceObject(nGovObjHash); CGovernanceObject* pObj = governance.FindGovernanceObject(nGovObjHash);
return pObj; return pObj;
@ -225,37 +221,11 @@ public:
return nEpochStart; return nEpochStart;
} }
// IS THIS TRIGGER ALREADY EXECUTED? int CountPayments() { return (int)vecPayments.size(); }
bool IsExecuted() bool GetPayment(int nPaymentIndex, CGovernancePayment& paymentRet);
{ CAmount GetPaymentsTotalAmount();
return (nStatus == SEEN_OBJECT_EXECUTED);
}
// TELL THE ENGINE WE EXECUTED THIS EVENT bool IsValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward);
void SetExecuted()
{
nStatus = SEEN_OBJECT_EXECUTED;
}
int CountPayments()
{
return (int)vecPayments.size();
}
bool GetPayment(int nPaymentIndex, CGovernancePayment& paymentOut)
{
if((nPaymentIndex<0) || (nPaymentIndex >= (int)vecPayments.size())) {
return false;
}
paymentOut = vecPayments[nPaymentIndex];
return true;
}
bool IsValid(const CTransaction& txNew);
private:
void ParsePaymentSchedule(std::string& strPaymentAddresses, std::string& strPaymentAmounts);
}; };
#endif #endif