mirror of
https://github.com/dashpay/dash.git
synced 2024-12-27 13:03:17 +01:00
Split masternode and payments code
This commit is contained in:
parent
88f6a598b9
commit
d25cf1af22
@ -107,6 +107,7 @@ BITCOIN_CORE_H = \
|
|||||||
limitedmap.h \
|
limitedmap.h \
|
||||||
main.h \
|
main.h \
|
||||||
masternode.h \
|
masternode.h \
|
||||||
|
masternode-payments.h \
|
||||||
masternode-pos.h \
|
masternode-pos.h \
|
||||||
masternodeman.h \
|
masternodeman.h \
|
||||||
masternodeconfig.h \
|
masternodeconfig.h \
|
||||||
@ -278,6 +279,7 @@ libbitcoin_common_a_SOURCES = \
|
|||||||
darksend.cpp \
|
darksend.cpp \
|
||||||
darksend-relay.cpp \
|
darksend-relay.cpp \
|
||||||
masternode.cpp \
|
masternode.cpp \
|
||||||
|
masternode-payments.cpp \
|
||||||
masternode-pos.cpp \
|
masternode-pos.cpp \
|
||||||
masternodeman.cpp \
|
masternodeman.cpp \
|
||||||
masternodeconfig.cpp \
|
masternodeconfig.cpp \
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "sync.h"
|
#include "sync.h"
|
||||||
#include "activemasternode.h"
|
#include "activemasternode.h"
|
||||||
#include "masternodeman.h"
|
#include "masternodeman.h"
|
||||||
|
#include "masternode-payments.h"
|
||||||
#include "darksend-relay.h"
|
#include "darksend-relay.h"
|
||||||
|
|
||||||
class CTxIn;
|
class CTxIn;
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "ui_interface.h"
|
#include "ui_interface.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "activemasternode.h"
|
#include "activemasternode.h"
|
||||||
|
#include "masternode-payments.h"
|
||||||
#include "masternodeman.h"
|
#include "masternodeman.h"
|
||||||
#include "spork.h"
|
#include "spork.h"
|
||||||
#include "utilmoneystr.h"
|
#include "utilmoneystr.h"
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "instantx.h"
|
#include "instantx.h"
|
||||||
#include "darksend.h"
|
#include "darksend.h"
|
||||||
#include "masternodeman.h"
|
#include "masternodeman.h"
|
||||||
|
#include "masternode-payments.h"
|
||||||
#include "merkleblock.h"
|
#include "merkleblock.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "pow.h"
|
#include "pow.h"
|
||||||
|
359
src/masternode-payments.cpp
Normal file
359
src/masternode-payments.cpp
Normal file
@ -0,0 +1,359 @@
|
|||||||
|
// Copyright (c) 2014-2015 The Dash developers
|
||||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include "masternode-payments.h"
|
||||||
|
#include "masternodeman.h"
|
||||||
|
#include "darksend.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "sync.h"
|
||||||
|
#include "addrman.h"
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
|
CCriticalSection cs_masternodepayments;
|
||||||
|
|
||||||
|
/** Object for who's going to get paid on which blocks */
|
||||||
|
CMasternodePayments masternodePayments;
|
||||||
|
// keep track of Masternode votes I've seen
|
||||||
|
map<uint256, CMasternodePaymentWinner> mapSeenMasternodeVotes;
|
||||||
|
|
||||||
|
void ProcessMessageMasternodePayments(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
|
||||||
|
{
|
||||||
|
if(IsInitialBlockDownload()) return;
|
||||||
|
|
||||||
|
if (strCommand == "mnget") { //Masternode Payments Request Sync
|
||||||
|
if(fLiteMode) return; //disable all Darksend/Masternode related functionality
|
||||||
|
|
||||||
|
if(pfrom->HasFulfilledRequest("mnget")) {
|
||||||
|
LogPrintf("mnget - peer already asked me for the list\n");
|
||||||
|
Misbehaving(pfrom->GetId(), 20);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pfrom->FulfilledRequest("mnget");
|
||||||
|
masternodePayments.Sync(pfrom);
|
||||||
|
LogPrintf("mnget - Sent Masternode winners to %s\n", pfrom->addr.ToString().c_str());
|
||||||
|
}
|
||||||
|
else if (strCommand == "mnw") { //Masternode Payments Declare Winner
|
||||||
|
|
||||||
|
LOCK(cs_masternodepayments);
|
||||||
|
|
||||||
|
//this is required in litemode
|
||||||
|
CMasternodePaymentWinner winner;
|
||||||
|
vRecv >> winner;
|
||||||
|
|
||||||
|
if(chainActive.Tip() == NULL) return;
|
||||||
|
|
||||||
|
CTxDestination address1;
|
||||||
|
ExtractDestination(winner.payee, address1);
|
||||||
|
CBitcoinAddress address2(address1);
|
||||||
|
|
||||||
|
uint256 hash = winner.GetHash();
|
||||||
|
if(mapSeenMasternodeVotes.count(hash)) {
|
||||||
|
if(fDebug) LogPrintf("mnw - seen vote %s Addr %s Height %d bestHeight %d\n", hash.ToString().c_str(), address2.ToString().c_str(), winner.nBlockHeight, chainActive.Tip()->nHeight);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(winner.nBlockHeight < chainActive.Tip()->nHeight - 10 || winner.nBlockHeight > chainActive.Tip()->nHeight+20){
|
||||||
|
LogPrintf("mnw - winner out of range %s Addr %s Height %d bestHeight %d\n", winner.vin.ToString().c_str(), address2.ToString().c_str(), winner.nBlockHeight, chainActive.Tip()->nHeight);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(winner.vin.nSequence != std::numeric_limits<unsigned int>::max()){
|
||||||
|
LogPrintf("mnw - invalid nSequence\n");
|
||||||
|
Misbehaving(pfrom->GetId(), 100);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogPrintf("mnw - winning vote - Vin %s Addr %s Height %d bestHeight %d\n", winner.vin.ToString().c_str(), address2.ToString().c_str(), winner.nBlockHeight, chainActive.Tip()->nHeight);
|
||||||
|
|
||||||
|
if(!masternodePayments.CheckSignature(winner)){
|
||||||
|
LogPrintf("mnw - invalid signature\n");
|
||||||
|
Misbehaving(pfrom->GetId(), 100);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mapSeenMasternodeVotes.insert(make_pair(hash, winner));
|
||||||
|
|
||||||
|
if(masternodePayments.AddWinningMasternode(winner)){
|
||||||
|
masternodePayments.Relay(winner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CMasternodePayments::CheckSignature(CMasternodePaymentWinner& winner)
|
||||||
|
{
|
||||||
|
//note: need to investigate why this is failing
|
||||||
|
std::string strMessage = winner.vin.ToString().c_str() + boost::lexical_cast<std::string>(winner.nBlockHeight) + winner.payee.ToString();
|
||||||
|
CPubKey pubkey(ParseHex(Params().MasternodePaymentPubKey()));
|
||||||
|
|
||||||
|
std::string errorMessage = "";
|
||||||
|
if(!darkSendSigner.VerifyMessage(pubkey, winner.vchSig, strMessage, errorMessage)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CMasternodePayments::Sign(CMasternodePaymentWinner& winner)
|
||||||
|
{
|
||||||
|
std::string strMessage = winner.vin.ToString().c_str() + boost::lexical_cast<std::string>(winner.nBlockHeight) + winner.payee.ToString();
|
||||||
|
|
||||||
|
CKey key2;
|
||||||
|
CPubKey pubkey2;
|
||||||
|
std::string errorMessage = "";
|
||||||
|
|
||||||
|
if(!darkSendSigner.SetKey(strMasterPrivKey, errorMessage, key2, pubkey2))
|
||||||
|
{
|
||||||
|
LogPrintf("CMasternodePayments::Sign - ERROR: Invalid Masternodeprivkey: '%s'\n", errorMessage.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!darkSendSigner.SignMessage(strMessage, errorMessage, winner.vchSig, key2)) {
|
||||||
|
LogPrintf("CMasternodePayments::Sign - Sign message failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!darkSendSigner.VerifyMessage(pubkey2, winner.vchSig, strMessage, errorMessage)) {
|
||||||
|
LogPrintf("CMasternodePayments::Sign - Verify message failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t CMasternodePayments::CalculateScore(uint256 blockHash, CTxIn& vin)
|
||||||
|
{
|
||||||
|
uint256 n1 = blockHash;
|
||||||
|
uint256 n2 = HashX11(BEGIN(n1), END(n1));
|
||||||
|
uint256 n3 = HashX11(BEGIN(vin.prevout.hash), END(vin.prevout.hash));
|
||||||
|
uint256 n4 = n3 > n2 ? (n3 - n2) : (n2 - n3);
|
||||||
|
|
||||||
|
//printf(" -- CMasternodePayments CalculateScore() n2 = %d \n", n2.Get64());
|
||||||
|
//printf(" -- CMasternodePayments CalculateScore() n3 = %d \n", n3.Get64());
|
||||||
|
//printf(" -- CMasternodePayments CalculateScore() n4 = %d \n", n4.Get64());
|
||||||
|
|
||||||
|
return n4.Get64();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CMasternodePayments::GetBlockPayee(int nBlockHeight, CScript& payee)
|
||||||
|
{
|
||||||
|
BOOST_FOREACH(CMasternodePaymentWinner& winner, vWinning){
|
||||||
|
if(winner.nBlockHeight == nBlockHeight) {
|
||||||
|
payee = winner.payee;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CMasternodePayments::GetWinningMasternode(int nBlockHeight, CTxIn& vinOut)
|
||||||
|
{
|
||||||
|
BOOST_FOREACH(CMasternodePaymentWinner& winner, vWinning){
|
||||||
|
if(winner.nBlockHeight == nBlockHeight) {
|
||||||
|
vinOut = winner.vin;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CMasternodePayments::AddWinningMasternode(CMasternodePaymentWinner& winnerIn)
|
||||||
|
{
|
||||||
|
uint256 blockHash = 0;
|
||||||
|
if(!GetBlockHash(blockHash, winnerIn.nBlockHeight-576)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
winnerIn.score = CalculateScore(blockHash, winnerIn.vin);
|
||||||
|
|
||||||
|
bool foundBlock = false;
|
||||||
|
BOOST_FOREACH(CMasternodePaymentWinner& winner, vWinning){
|
||||||
|
if(winner.nBlockHeight == winnerIn.nBlockHeight) {
|
||||||
|
foundBlock = true;
|
||||||
|
if(winner.score < winnerIn.score){
|
||||||
|
winner.score = winnerIn.score;
|
||||||
|
winner.vin = winnerIn.vin;
|
||||||
|
winner.payee = winnerIn.payee;
|
||||||
|
winner.vchSig = winnerIn.vchSig;
|
||||||
|
|
||||||
|
mapSeenMasternodeVotes.insert(make_pair(winnerIn.GetHash(), winnerIn));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if it's not in the vector
|
||||||
|
if(!foundBlock){
|
||||||
|
vWinning.push_back(winnerIn);
|
||||||
|
mapSeenMasternodeVotes.insert(make_pair(winnerIn.GetHash(), winnerIn));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMasternodePayments::CleanPaymentList()
|
||||||
|
{
|
||||||
|
LOCK(cs_masternodepayments);
|
||||||
|
|
||||||
|
if(chainActive.Tip() == NULL) return;
|
||||||
|
|
||||||
|
int nLimit = std::max(((int)mnodeman.size())*2, 1000);
|
||||||
|
|
||||||
|
vector<CMasternodePaymentWinner>::iterator it;
|
||||||
|
for(it=vWinning.begin();it<vWinning.end();it++){
|
||||||
|
if(chainActive.Tip()->nHeight - (*it).nBlockHeight > nLimit){
|
||||||
|
if(fDebug) LogPrintf("CMasternodePayments::CleanPaymentList - Removing old Masternode payment - block %d\n", (*it).nBlockHeight);
|
||||||
|
vWinning.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CMasternodePayments::ProcessBlock(int nBlockHeight)
|
||||||
|
{
|
||||||
|
LOCK(cs_masternodepayments);
|
||||||
|
|
||||||
|
if(nBlockHeight <= nLastBlockHeight) return false;
|
||||||
|
if(!enabled) return false;
|
||||||
|
CMasternodePaymentWinner newWinner;
|
||||||
|
int nMinimumAge = mnodeman.CountEnabled();
|
||||||
|
CScript payeeSource;
|
||||||
|
|
||||||
|
uint256 hash;
|
||||||
|
if(!GetBlockHash(hash, nBlockHeight-10)) return false;
|
||||||
|
unsigned int nHash;
|
||||||
|
memcpy(&nHash, &hash, 2);
|
||||||
|
|
||||||
|
LogPrintf(" ProcessBlock Start nHeight %d. \n", nBlockHeight);
|
||||||
|
|
||||||
|
std::vector<CTxIn> vecLastPayments;
|
||||||
|
BOOST_REVERSE_FOREACH(CMasternodePaymentWinner& winner, vWinning)
|
||||||
|
{
|
||||||
|
//if we already have the same vin - we have one full payment cycle, break
|
||||||
|
if(vecLastPayments.size() > nMinimumAge) break;
|
||||||
|
vecLastPayments.push_back(winner.vin);
|
||||||
|
}
|
||||||
|
|
||||||
|
// pay to the oldest MN that still had no payment but its input is old enough and it was active long enough
|
||||||
|
CMasternode *pmn = mnodeman.FindOldestNotInVec(vecLastPayments, nMinimumAge);
|
||||||
|
if(pmn != NULL)
|
||||||
|
{
|
||||||
|
LogPrintf(" Found by FindOldestNotInVec \n");
|
||||||
|
|
||||||
|
newWinner.score = 0;
|
||||||
|
newWinner.nBlockHeight = nBlockHeight;
|
||||||
|
newWinner.vin = pmn->vin;
|
||||||
|
pmn->nLastPaid = GetAdjustedTime();
|
||||||
|
|
||||||
|
if(pmn->donationPercentage > 0 && (nHash % 100) <= (unsigned int)pmn->donationPercentage) {
|
||||||
|
newWinner.payee = pmn->donationAddress;
|
||||||
|
} else {
|
||||||
|
newWinner.payee = GetScriptForDestination(pmn->pubkey.GetID());
|
||||||
|
}
|
||||||
|
|
||||||
|
payeeSource = GetScriptForDestination(pmn->pubkey.GetID());
|
||||||
|
}
|
||||||
|
|
||||||
|
//if we can't find new MN to get paid, pick first active MN counting back from the end of vecLastPayments list
|
||||||
|
if(newWinner.nBlockHeight == 0 && nMinimumAge > 0)
|
||||||
|
{
|
||||||
|
LogPrintf(" Find by reverse \n");
|
||||||
|
|
||||||
|
BOOST_REVERSE_FOREACH(CTxIn& vinLP, vecLastPayments)
|
||||||
|
{
|
||||||
|
CMasternode* pmn = mnodeman.Find(vinLP);
|
||||||
|
if(pmn != NULL)
|
||||||
|
{
|
||||||
|
pmn->Check();
|
||||||
|
if(!pmn->IsEnabled()) continue;
|
||||||
|
|
||||||
|
newWinner.score = 0;
|
||||||
|
newWinner.nBlockHeight = nBlockHeight;
|
||||||
|
newWinner.vin = pmn->vin;
|
||||||
|
pmn->nLastPaid = GetAdjustedTime();
|
||||||
|
|
||||||
|
if(pmn->donationPercentage > 0 && (nHash % 100) <= (unsigned int)pmn->donationPercentage) {
|
||||||
|
newWinner.payee = pmn->donationAddress;
|
||||||
|
} else {
|
||||||
|
newWinner.payee = GetScriptForDestination(pmn->pubkey.GetID());
|
||||||
|
}
|
||||||
|
|
||||||
|
payeeSource = GetScriptForDestination(pmn->pubkey.GetID());
|
||||||
|
|
||||||
|
break; // we found active MN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(newWinner.nBlockHeight == 0) return false;
|
||||||
|
|
||||||
|
CTxDestination address1;
|
||||||
|
ExtractDestination(newWinner.payee, address1);
|
||||||
|
CBitcoinAddress address2(address1);
|
||||||
|
|
||||||
|
CTxDestination address3;
|
||||||
|
ExtractDestination(payeeSource, address3);
|
||||||
|
CBitcoinAddress address4(address3);
|
||||||
|
|
||||||
|
LogPrintf("Winner payee %s nHeight %d vin source %s. \n", address2.ToString().c_str(), newWinner.nBlockHeight, address4.ToString().c_str());
|
||||||
|
|
||||||
|
if(Sign(newWinner))
|
||||||
|
{
|
||||||
|
if(AddWinningMasternode(newWinner))
|
||||||
|
{
|
||||||
|
Relay(newWinner);
|
||||||
|
nLastBlockHeight = nBlockHeight;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CMasternodePayments::Relay(CMasternodePaymentWinner& winner)
|
||||||
|
{
|
||||||
|
CInv inv(MSG_MASTERNODE_WINNER, winner.GetHash());
|
||||||
|
|
||||||
|
vector<CInv> vInv;
|
||||||
|
vInv.push_back(inv);
|
||||||
|
LOCK(cs_vNodes);
|
||||||
|
BOOST_FOREACH(CNode* pnode, vNodes){
|
||||||
|
pnode->PushMessage("inv", vInv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMasternodePayments::Sync(CNode* node)
|
||||||
|
{
|
||||||
|
LOCK(cs_masternodepayments);
|
||||||
|
|
||||||
|
BOOST_FOREACH(CMasternodePaymentWinner& winner, vWinning)
|
||||||
|
if(winner.nBlockHeight >= chainActive.Tip()->nHeight-10 && winner.nBlockHeight <= chainActive.Tip()->nHeight + 20)
|
||||||
|
node->PushMessage("mnw", winner);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CMasternodePayments::SetPrivKey(std::string strPrivKey)
|
||||||
|
{
|
||||||
|
CMasternodePaymentWinner winner;
|
||||||
|
|
||||||
|
// Test signing successful, proceed
|
||||||
|
strMasterPrivKey = strPrivKey;
|
||||||
|
|
||||||
|
Sign(winner);
|
||||||
|
|
||||||
|
if(CheckSignature(winner)){
|
||||||
|
LogPrintf("CMasternodePayments::SetPrivKey - Successfully initialized as Masternode payments master\n");
|
||||||
|
enabled = true;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
109
src/masternode-payments.h
Normal file
109
src/masternode-payments.h
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
|
||||||
|
|
||||||
|
// Copyright (c) 2014-2015 The Dash developers
|
||||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
#ifndef MASTERNODE_PAYMENTS_H
|
||||||
|
#define MASTERNODE_PAYMENTS_H
|
||||||
|
|
||||||
|
#include "sync.h"
|
||||||
|
#include "net.h"
|
||||||
|
#include "key.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "base58.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "masternode.h"
|
||||||
|
#include "masternode-pos.h"
|
||||||
|
#include "timedata.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class CMasternodePayments;
|
||||||
|
class CMasternodePaymentWinner;
|
||||||
|
|
||||||
|
extern CMasternodePayments masternodePayments;
|
||||||
|
extern map<uint256, CMasternodePaymentWinner> mapSeenMasternodeVotes;
|
||||||
|
|
||||||
|
void ProcessMessageMasternodePayments(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
|
||||||
|
|
||||||
|
|
||||||
|
// for storing the winning payments
|
||||||
|
class CMasternodePaymentWinner
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int nBlockHeight;
|
||||||
|
CTxIn vin;
|
||||||
|
CScript payee;
|
||||||
|
std::vector<unsigned char> vchSig;
|
||||||
|
uint64_t score;
|
||||||
|
|
||||||
|
CMasternodePaymentWinner() {
|
||||||
|
nBlockHeight = 0;
|
||||||
|
score = 0;
|
||||||
|
vin = CTxIn();
|
||||||
|
payee = CScript();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint256 GetHash(){
|
||||||
|
uint256 n2 = HashX11(BEGIN(nBlockHeight), END(nBlockHeight));
|
||||||
|
uint256 n3 = vin.prevout.hash > n2 ? (vin.prevout.hash - n2) : (n2 - vin.prevout.hash);
|
||||||
|
|
||||||
|
return n3;
|
||||||
|
}
|
||||||
|
|
||||||
|
ADD_SERIALIZE_METHODS;
|
||||||
|
|
||||||
|
template <typename Stream, typename Operation>
|
||||||
|
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||||
|
READWRITE(nBlockHeight);
|
||||||
|
READWRITE(payee);
|
||||||
|
READWRITE(vin);
|
||||||
|
READWRITE(score);
|
||||||
|
READWRITE(vchSig);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Masternode Payments Class
|
||||||
|
// Keeps track of who should get paid for which blocks
|
||||||
|
//
|
||||||
|
|
||||||
|
class CMasternodePayments
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::vector<CMasternodePaymentWinner> vWinning;
|
||||||
|
int nSyncedFromPeer;
|
||||||
|
std::string strMasterPrivKey;
|
||||||
|
bool enabled;
|
||||||
|
int nLastBlockHeight;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
CMasternodePayments() {
|
||||||
|
enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SetPrivKey(std::string strPrivKey);
|
||||||
|
bool CheckSignature(CMasternodePaymentWinner& winner);
|
||||||
|
bool Sign(CMasternodePaymentWinner& winner);
|
||||||
|
|
||||||
|
// Deterministically calculate a given "score" for a masternode depending on how close it's hash is
|
||||||
|
// to the blockHeight. The further away they are the better, the furthest will win the election
|
||||||
|
// and get paid this block
|
||||||
|
//
|
||||||
|
|
||||||
|
uint64_t CalculateScore(uint256 blockHash, CTxIn& vin);
|
||||||
|
bool GetWinningMasternode(int nBlockHeight, CTxIn& vinOut);
|
||||||
|
bool AddWinningMasternode(CMasternodePaymentWinner& winner);
|
||||||
|
bool ProcessBlock(int nBlockHeight);
|
||||||
|
void Relay(CMasternodePaymentWinner& winner);
|
||||||
|
void Sync(CNode* node);
|
||||||
|
void CleanPaymentList();
|
||||||
|
int LastPayment(CMasternode& mn);
|
||||||
|
|
||||||
|
//slow
|
||||||
|
bool GetBlockPayee(int nBlockHeight, CScript& payee);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@ -10,80 +10,11 @@
|
|||||||
#include "addrman.h"
|
#include "addrman.h"
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
CCriticalSection cs_masternodepayments;
|
|
||||||
|
|
||||||
/** Object for who's going to get paid on which blocks */
|
|
||||||
CMasternodePayments masternodePayments;
|
|
||||||
// keep track of Masternode votes I've seen
|
|
||||||
map<uint256, CMasternodePaymentWinner> mapSeenMasternodeVotes;
|
|
||||||
// keep track of the scanning errors I've seen
|
// keep track of the scanning errors I've seen
|
||||||
map<uint256, int> mapSeenMasternodeScanningErrors;
|
map<uint256, int> mapSeenMasternodeScanningErrors;
|
||||||
// cache block hashes as we calculate them
|
// cache block hashes as we calculate them
|
||||||
std::map<int64_t, uint256> mapCacheBlockHashes;
|
std::map<int64_t, uint256> mapCacheBlockHashes;
|
||||||
|
|
||||||
void ProcessMessageMasternodePayments(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
|
|
||||||
{
|
|
||||||
if(IsInitialBlockDownload()) return;
|
|
||||||
|
|
||||||
if (strCommand == "mnget") { //Masternode Payments Request Sync
|
|
||||||
if(fLiteMode) return; //disable all Darksend/Masternode related functionality
|
|
||||||
|
|
||||||
if(pfrom->HasFulfilledRequest("mnget")) {
|
|
||||||
LogPrintf("mnget - peer already asked me for the list\n");
|
|
||||||
Misbehaving(pfrom->GetId(), 20);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pfrom->FulfilledRequest("mnget");
|
|
||||||
masternodePayments.Sync(pfrom);
|
|
||||||
LogPrintf("mnget - Sent Masternode winners to %s\n", pfrom->addr.ToString().c_str());
|
|
||||||
}
|
|
||||||
else if (strCommand == "mnw") { //Masternode Payments Declare Winner
|
|
||||||
|
|
||||||
LOCK(cs_masternodepayments);
|
|
||||||
|
|
||||||
//this is required in litemode
|
|
||||||
CMasternodePaymentWinner winner;
|
|
||||||
vRecv >> winner;
|
|
||||||
|
|
||||||
if(chainActive.Tip() == NULL) return;
|
|
||||||
|
|
||||||
CTxDestination address1;
|
|
||||||
ExtractDestination(winner.payee, address1);
|
|
||||||
CBitcoinAddress address2(address1);
|
|
||||||
|
|
||||||
uint256 hash = winner.GetHash();
|
|
||||||
if(mapSeenMasternodeVotes.count(hash)) {
|
|
||||||
if(fDebug) LogPrintf("mnw - seen vote %s Addr %s Height %d bestHeight %d\n", hash.ToString().c_str(), address2.ToString().c_str(), winner.nBlockHeight, chainActive.Tip()->nHeight);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(winner.nBlockHeight < chainActive.Tip()->nHeight - 10 || winner.nBlockHeight > chainActive.Tip()->nHeight+20){
|
|
||||||
LogPrintf("mnw - winner out of range %s Addr %s Height %d bestHeight %d\n", winner.vin.ToString().c_str(), address2.ToString().c_str(), winner.nBlockHeight, chainActive.Tip()->nHeight);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(winner.vin.nSequence != std::numeric_limits<unsigned int>::max()){
|
|
||||||
LogPrintf("mnw - invalid nSequence\n");
|
|
||||||
Misbehaving(pfrom->GetId(), 100);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LogPrintf("mnw - winning vote - Vin %s Addr %s Height %d bestHeight %d\n", winner.vin.ToString().c_str(), address2.ToString().c_str(), winner.nBlockHeight, chainActive.Tip()->nHeight);
|
|
||||||
|
|
||||||
if(!masternodePayments.CheckSignature(winner)){
|
|
||||||
LogPrintf("mnw - invalid signature\n");
|
|
||||||
Misbehaving(pfrom->GetId(), 100);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mapSeenMasternodeVotes.insert(make_pair(hash, winner));
|
|
||||||
|
|
||||||
if(masternodePayments.AddWinningMasternode(winner)){
|
|
||||||
masternodePayments.Relay(winner);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CompareValueOnly
|
struct CompareValueOnly
|
||||||
{
|
{
|
||||||
@ -277,280 +208,4 @@ void CMasternode::Check()
|
|||||||
}
|
}
|
||||||
|
|
||||||
activeState = MASTERNODE_ENABLED; // OK
|
activeState = MASTERNODE_ENABLED; // OK
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CMasternodePayments::CheckSignature(CMasternodePaymentWinner& winner)
|
|
||||||
{
|
|
||||||
//note: need to investigate why this is failing
|
|
||||||
std::string strMessage = winner.vin.ToString().c_str() + boost::lexical_cast<std::string>(winner.nBlockHeight) + winner.payee.ToString();
|
|
||||||
CPubKey pubkey(ParseHex(Params().MasternodePaymentPubKey()));
|
|
||||||
|
|
||||||
std::string errorMessage = "";
|
|
||||||
if(!darkSendSigner.VerifyMessage(pubkey, winner.vchSig, strMessage, errorMessage)){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CMasternodePayments::Sign(CMasternodePaymentWinner& winner)
|
|
||||||
{
|
|
||||||
std::string strMessage = winner.vin.ToString().c_str() + boost::lexical_cast<std::string>(winner.nBlockHeight) + winner.payee.ToString();
|
|
||||||
|
|
||||||
CKey key2;
|
|
||||||
CPubKey pubkey2;
|
|
||||||
std::string errorMessage = "";
|
|
||||||
|
|
||||||
if(!darkSendSigner.SetKey(strMasterPrivKey, errorMessage, key2, pubkey2))
|
|
||||||
{
|
|
||||||
LogPrintf("CMasternodePayments::Sign - ERROR: Invalid Masternodeprivkey: '%s'\n", errorMessage.c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!darkSendSigner.SignMessage(strMessage, errorMessage, winner.vchSig, key2)) {
|
|
||||||
LogPrintf("CMasternodePayments::Sign - Sign message failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!darkSendSigner.VerifyMessage(pubkey2, winner.vchSig, strMessage, errorMessage)) {
|
|
||||||
LogPrintf("CMasternodePayments::Sign - Verify message failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t CMasternodePayments::CalculateScore(uint256 blockHash, CTxIn& vin)
|
|
||||||
{
|
|
||||||
uint256 n1 = blockHash;
|
|
||||||
uint256 n2 = HashX11(BEGIN(n1), END(n1));
|
|
||||||
uint256 n3 = HashX11(BEGIN(vin.prevout.hash), END(vin.prevout.hash));
|
|
||||||
uint256 n4 = n3 > n2 ? (n3 - n2) : (n2 - n3);
|
|
||||||
|
|
||||||
//printf(" -- CMasternodePayments CalculateScore() n2 = %d \n", n2.Get64());
|
|
||||||
//printf(" -- CMasternodePayments CalculateScore() n3 = %d \n", n3.Get64());
|
|
||||||
//printf(" -- CMasternodePayments CalculateScore() n4 = %d \n", n4.Get64());
|
|
||||||
|
|
||||||
return n4.Get64();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CMasternodePayments::GetBlockPayee(int nBlockHeight, CScript& payee)
|
|
||||||
{
|
|
||||||
BOOST_FOREACH(CMasternodePaymentWinner& winner, vWinning){
|
|
||||||
if(winner.nBlockHeight == nBlockHeight) {
|
|
||||||
payee = winner.payee;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CMasternodePayments::GetWinningMasternode(int nBlockHeight, CTxIn& vinOut)
|
|
||||||
{
|
|
||||||
BOOST_FOREACH(CMasternodePaymentWinner& winner, vWinning){
|
|
||||||
if(winner.nBlockHeight == nBlockHeight) {
|
|
||||||
vinOut = winner.vin;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CMasternodePayments::AddWinningMasternode(CMasternodePaymentWinner& winnerIn)
|
|
||||||
{
|
|
||||||
uint256 blockHash = 0;
|
|
||||||
if(!GetBlockHash(blockHash, winnerIn.nBlockHeight-576)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
winnerIn.score = CalculateScore(blockHash, winnerIn.vin);
|
|
||||||
|
|
||||||
bool foundBlock = false;
|
|
||||||
BOOST_FOREACH(CMasternodePaymentWinner& winner, vWinning){
|
|
||||||
if(winner.nBlockHeight == winnerIn.nBlockHeight) {
|
|
||||||
foundBlock = true;
|
|
||||||
if(winner.score < winnerIn.score){
|
|
||||||
winner.score = winnerIn.score;
|
|
||||||
winner.vin = winnerIn.vin;
|
|
||||||
winner.payee = winnerIn.payee;
|
|
||||||
winner.vchSig = winnerIn.vchSig;
|
|
||||||
|
|
||||||
mapSeenMasternodeVotes.insert(make_pair(winnerIn.GetHash(), winnerIn));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if it's not in the vector
|
|
||||||
if(!foundBlock){
|
|
||||||
vWinning.push_back(winnerIn);
|
|
||||||
mapSeenMasternodeVotes.insert(make_pair(winnerIn.GetHash(), winnerIn));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMasternodePayments::CleanPaymentList()
|
|
||||||
{
|
|
||||||
LOCK(cs_masternodepayments);
|
|
||||||
|
|
||||||
if(chainActive.Tip() == NULL) return;
|
|
||||||
|
|
||||||
int nLimit = std::max(((int)mnodeman.size())*2, 1000);
|
|
||||||
|
|
||||||
vector<CMasternodePaymentWinner>::iterator it;
|
|
||||||
for(it=vWinning.begin();it<vWinning.end();it++){
|
|
||||||
if(chainActive.Tip()->nHeight - (*it).nBlockHeight > nLimit){
|
|
||||||
if(fDebug) LogPrintf("CMasternodePayments::CleanPaymentList - Removing old Masternode payment - block %d\n", (*it).nBlockHeight);
|
|
||||||
vWinning.erase(it);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CMasternodePayments::ProcessBlock(int nBlockHeight)
|
|
||||||
{
|
|
||||||
LOCK(cs_masternodepayments);
|
|
||||||
|
|
||||||
if(nBlockHeight <= nLastBlockHeight) return false;
|
|
||||||
if(!enabled) return false;
|
|
||||||
CMasternodePaymentWinner newWinner;
|
|
||||||
int nMinimumAge = mnodeman.CountEnabled();
|
|
||||||
CScript payeeSource;
|
|
||||||
|
|
||||||
uint256 hash;
|
|
||||||
if(!GetBlockHash(hash, nBlockHeight-10)) return false;
|
|
||||||
unsigned int nHash;
|
|
||||||
memcpy(&nHash, &hash, 2);
|
|
||||||
|
|
||||||
LogPrintf(" ProcessBlock Start nHeight %d. \n", nBlockHeight);
|
|
||||||
|
|
||||||
std::vector<CTxIn> vecLastPayments;
|
|
||||||
BOOST_REVERSE_FOREACH(CMasternodePaymentWinner& winner, vWinning)
|
|
||||||
{
|
|
||||||
//if we already have the same vin - we have one full payment cycle, break
|
|
||||||
if(vecLastPayments.size() > nMinimumAge) break;
|
|
||||||
vecLastPayments.push_back(winner.vin);
|
|
||||||
}
|
|
||||||
|
|
||||||
// pay to the oldest MN that still had no payment but its input is old enough and it was active long enough
|
|
||||||
CMasternode *pmn = mnodeman.FindOldestNotInVec(vecLastPayments, nMinimumAge);
|
|
||||||
if(pmn != NULL)
|
|
||||||
{
|
|
||||||
LogPrintf(" Found by FindOldestNotInVec \n");
|
|
||||||
|
|
||||||
newWinner.score = 0;
|
|
||||||
newWinner.nBlockHeight = nBlockHeight;
|
|
||||||
newWinner.vin = pmn->vin;
|
|
||||||
pmn->nLastPaid = GetAdjustedTime();
|
|
||||||
|
|
||||||
if(pmn->donationPercentage > 0 && (nHash % 100) <= (unsigned int)pmn->donationPercentage) {
|
|
||||||
newWinner.payee = pmn->donationAddress;
|
|
||||||
} else {
|
|
||||||
newWinner.payee = GetScriptForDestination(pmn->pubkey.GetID());
|
|
||||||
}
|
|
||||||
|
|
||||||
payeeSource = GetScriptForDestination(pmn->pubkey.GetID());
|
|
||||||
}
|
|
||||||
|
|
||||||
//if we can't find new MN to get paid, pick first active MN counting back from the end of vecLastPayments list
|
|
||||||
if(newWinner.nBlockHeight == 0 && nMinimumAge > 0)
|
|
||||||
{
|
|
||||||
LogPrintf(" Find by reverse \n");
|
|
||||||
|
|
||||||
BOOST_REVERSE_FOREACH(CTxIn& vinLP, vecLastPayments)
|
|
||||||
{
|
|
||||||
CMasternode* pmn = mnodeman.Find(vinLP);
|
|
||||||
if(pmn != NULL)
|
|
||||||
{
|
|
||||||
pmn->Check();
|
|
||||||
if(!pmn->IsEnabled()) continue;
|
|
||||||
|
|
||||||
newWinner.score = 0;
|
|
||||||
newWinner.nBlockHeight = nBlockHeight;
|
|
||||||
newWinner.vin = pmn->vin;
|
|
||||||
pmn->nLastPaid = GetAdjustedTime();
|
|
||||||
|
|
||||||
if(pmn->donationPercentage > 0 && (nHash % 100) <= (unsigned int)pmn->donationPercentage) {
|
|
||||||
newWinner.payee = pmn->donationAddress;
|
|
||||||
} else {
|
|
||||||
newWinner.payee = GetScriptForDestination(pmn->pubkey.GetID());
|
|
||||||
}
|
|
||||||
|
|
||||||
payeeSource = GetScriptForDestination(pmn->pubkey.GetID());
|
|
||||||
|
|
||||||
break; // we found active MN
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(newWinner.nBlockHeight == 0) return false;
|
|
||||||
|
|
||||||
CTxDestination address1;
|
|
||||||
ExtractDestination(newWinner.payee, address1);
|
|
||||||
CBitcoinAddress address2(address1);
|
|
||||||
|
|
||||||
CTxDestination address3;
|
|
||||||
ExtractDestination(payeeSource, address3);
|
|
||||||
CBitcoinAddress address4(address3);
|
|
||||||
|
|
||||||
LogPrintf("Winner payee %s nHeight %d vin source %s. \n", address2.ToString().c_str(), newWinner.nBlockHeight, address4.ToString().c_str());
|
|
||||||
|
|
||||||
if(Sign(newWinner))
|
|
||||||
{
|
|
||||||
if(AddWinningMasternode(newWinner))
|
|
||||||
{
|
|
||||||
Relay(newWinner);
|
|
||||||
nLastBlockHeight = nBlockHeight;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CMasternodePayments::Relay(CMasternodePaymentWinner& winner)
|
|
||||||
{
|
|
||||||
CInv inv(MSG_MASTERNODE_WINNER, winner.GetHash());
|
|
||||||
|
|
||||||
vector<CInv> vInv;
|
|
||||||
vInv.push_back(inv);
|
|
||||||
LOCK(cs_vNodes);
|
|
||||||
BOOST_FOREACH(CNode* pnode, vNodes){
|
|
||||||
pnode->PushMessage("inv", vInv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMasternodePayments::Sync(CNode* node)
|
|
||||||
{
|
|
||||||
LOCK(cs_masternodepayments);
|
|
||||||
|
|
||||||
BOOST_FOREACH(CMasternodePaymentWinner& winner, vWinning)
|
|
||||||
if(winner.nBlockHeight >= chainActive.Tip()->nHeight-10 && winner.nBlockHeight <= chainActive.Tip()->nHeight + 20)
|
|
||||||
node->PushMessage("mnw", winner);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool CMasternodePayments::SetPrivKey(std::string strPrivKey)
|
|
||||||
{
|
|
||||||
CMasternodePaymentWinner winner;
|
|
||||||
|
|
||||||
// Test signing successful, proceed
|
|
||||||
strMasterPrivKey = strPrivKey;
|
|
||||||
|
|
||||||
Sign(winner);
|
|
||||||
|
|
||||||
if(CheckSignature(winner)){
|
|
||||||
LogPrintf("CMasternodePayments::SetPrivKey - Successfully initialized as Masternode payments master\n");
|
|
||||||
enabled = true;
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
@ -11,6 +11,7 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "base58.h"
|
#include "base58.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "masternode.h"
|
||||||
#include "masternode-pos.h"
|
#include "masternode-pos.h"
|
||||||
#include "timedata.h"
|
#include "timedata.h"
|
||||||
|
|
||||||
@ -34,14 +35,8 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
class CMasternode;
|
class CMasternode;
|
||||||
class CMasternodePayments;
|
|
||||||
class CMasternodePaymentWinner;
|
|
||||||
|
|
||||||
extern CMasternodePayments masternodePayments;
|
|
||||||
extern map<uint256, CMasternodePaymentWinner> mapSeenMasternodeVotes;
|
|
||||||
extern map<int64_t, uint256> mapCacheBlockHashes;
|
extern map<int64_t, uint256> mapCacheBlockHashes;
|
||||||
|
|
||||||
void ProcessMessageMasternodePayments(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
|
|
||||||
bool GetBlockHash(uint256& hash, int nBlockHeight);
|
bool GetBlockHash(uint256& hash, int nBlockHeight);
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -248,83 +243,4 @@ public:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// for storing the winning payments
|
|
||||||
class CMasternodePaymentWinner
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
int nBlockHeight;
|
|
||||||
CTxIn vin;
|
|
||||||
CScript payee;
|
|
||||||
std::vector<unsigned char> vchSig;
|
|
||||||
uint64_t score;
|
|
||||||
|
|
||||||
CMasternodePaymentWinner() {
|
|
||||||
nBlockHeight = 0;
|
|
||||||
score = 0;
|
|
||||||
vin = CTxIn();
|
|
||||||
payee = CScript();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint256 GetHash(){
|
|
||||||
uint256 n2 = HashX11(BEGIN(nBlockHeight), END(nBlockHeight));
|
|
||||||
uint256 n3 = vin.prevout.hash > n2 ? (vin.prevout.hash - n2) : (n2 - vin.prevout.hash);
|
|
||||||
|
|
||||||
return n3;
|
|
||||||
}
|
|
||||||
|
|
||||||
ADD_SERIALIZE_METHODS;
|
|
||||||
|
|
||||||
template <typename Stream, typename Operation>
|
|
||||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
|
||||||
READWRITE(nBlockHeight);
|
|
||||||
READWRITE(payee);
|
|
||||||
READWRITE(vin);
|
|
||||||
READWRITE(score);
|
|
||||||
READWRITE(vchSig);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Masternode Payments Class
|
|
||||||
// Keeps track of who should get paid for which blocks
|
|
||||||
//
|
|
||||||
|
|
||||||
class CMasternodePayments
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
std::vector<CMasternodePaymentWinner> vWinning;
|
|
||||||
int nSyncedFromPeer;
|
|
||||||
std::string strMasterPrivKey;
|
|
||||||
bool enabled;
|
|
||||||
int nLastBlockHeight;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
CMasternodePayments() {
|
|
||||||
enabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SetPrivKey(std::string strPrivKey);
|
|
||||||
bool CheckSignature(CMasternodePaymentWinner& winner);
|
|
||||||
bool Sign(CMasternodePaymentWinner& winner);
|
|
||||||
|
|
||||||
// Deterministically calculate a given "score" for a masternode depending on how close it's hash is
|
|
||||||
// to the blockHeight. The further away they are the better, the furthest will win the election
|
|
||||||
// and get paid this block
|
|
||||||
//
|
|
||||||
|
|
||||||
uint64_t CalculateScore(uint256 blockHash, CTxIn& vin);
|
|
||||||
bool GetWinningMasternode(int nBlockHeight, CTxIn& vinOut);
|
|
||||||
bool AddWinningMasternode(CMasternodePaymentWinner& winner);
|
|
||||||
bool ProcessBlock(int nBlockHeight);
|
|
||||||
void Relay(CMasternodePaymentWinner& winner);
|
|
||||||
void Sync(CNode* node);
|
|
||||||
void CleanPaymentList();
|
|
||||||
int LastPayment(CMasternode& mn);
|
|
||||||
|
|
||||||
//slow
|
|
||||||
bool GetBlockPayee(int nBlockHeight, CScript& payee);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "wallet.h"
|
#include "wallet.h"
|
||||||
#endif
|
#endif
|
||||||
#include "masternodeman.h"
|
#include "masternodeman.h"
|
||||||
|
#include "masternode-payments.h"
|
||||||
|
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
#include <boost/tuple/tuple.hpp>
|
#include <boost/tuple/tuple.hpp>
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "init.h"
|
#include "init.h"
|
||||||
#include "activemasternode.h"
|
#include "activemasternode.h"
|
||||||
#include "masternodeman.h"
|
#include "masternodeman.h"
|
||||||
|
#include "masternode-payments.h"
|
||||||
#include "masternodeconfig.h"
|
#include "masternodeconfig.h"
|
||||||
#include "rpcserver.h"
|
#include "rpcserver.h"
|
||||||
#include "utilmoneystr.h"
|
#include "utilmoneystr.h"
|
||||||
|
Loading…
Reference in New Issue
Block a user