Version 26 / New masternode consensus system
- Consensus system selects 1/10 of the oldest masternodes by payment, then selects payee by score from those. This fixes various race conditions when blocks are close together or inconsistant historical winner lists. - Ask for up to 2 cycles of history - Keep up to 5 cycles of history locally
This commit is contained in:
parent
cbe2bae130
commit
388f22c576
@ -3,7 +3,7 @@ AC_PREREQ([2.60])
|
|||||||
define(_CLIENT_VERSION_MAJOR, 0)
|
define(_CLIENT_VERSION_MAJOR, 0)
|
||||||
define(_CLIENT_VERSION_MINOR, 12)
|
define(_CLIENT_VERSION_MINOR, 12)
|
||||||
define(_CLIENT_VERSION_REVISION, 0)
|
define(_CLIENT_VERSION_REVISION, 0)
|
||||||
define(_CLIENT_VERSION_BUILD, 25)
|
define(_CLIENT_VERSION_BUILD, 26)
|
||||||
define(_CLIENT_VERSION_IS_RELEASE, true)
|
define(_CLIENT_VERSION_IS_RELEASE, true)
|
||||||
define(_COPYRIGHT_YEAR, 2015)
|
define(_COPYRIGHT_YEAR, 2015)
|
||||||
AC_INIT([Dash Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[info@dashpay.io],[dash])
|
AC_INIT([Dash Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[info@dashpay.io],[dash])
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
#define CLIENT_VERSION_MAJOR 0
|
#define CLIENT_VERSION_MAJOR 0
|
||||||
#define CLIENT_VERSION_MINOR 12
|
#define CLIENT_VERSION_MINOR 12
|
||||||
#define CLIENT_VERSION_REVISION 0
|
#define CLIENT_VERSION_REVISION 0
|
||||||
#define CLIENT_VERSION_BUILD 25
|
#define CLIENT_VERSION_BUILD 26
|
||||||
|
|
||||||
//! Set to true for release, false for prerelease or test build
|
//! Set to true for release, false for prerelease or test build
|
||||||
#define CLIENT_VERSION_IS_RELEASE true
|
#define CLIENT_VERSION_IS_RELEASE true
|
||||||
|
@ -27,7 +27,7 @@ class CConsensusVote;
|
|||||||
class CTransaction;
|
class CTransaction;
|
||||||
class CTransactionLock;
|
class CTransactionLock;
|
||||||
|
|
||||||
static const int MIN_INSTANTX_PROTO_VERSION = 70093;
|
static const int MIN_INSTANTX_PROTO_VERSION = 70094;
|
||||||
|
|
||||||
extern map<uint256, CTransaction> mapTxLockReq;
|
extern map<uint256, CTransaction> mapTxLockReq;
|
||||||
extern map<uint256, CTransaction> mapTxLockReqRejected;
|
extern map<uint256, CTransaction> mapTxLockReqRejected;
|
||||||
|
@ -365,7 +365,7 @@ void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::st
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nFirstBlock = (masternodeSync.IsSynced() ? (chainActive.Tip()->nHeight - (mnodeman.CountEnabled()*1.1)) : chainActive.Tip()->nHeight - 10);
|
int nFirstBlock = chainActive.Tip()->nHeight - (mnodeman.CountEnabled()*2);
|
||||||
if(winner.nBlockHeight < nFirstBlock || winner.nBlockHeight > chainActive.Tip()->nHeight+20){
|
if(winner.nBlockHeight < nFirstBlock || winner.nBlockHeight > chainActive.Tip()->nHeight+20){
|
||||||
LogPrintf("mnw - winner out of range - FirstBlock %d Height %d bestHeight %d\n", nFirstBlock, winner.nBlockHeight, chainActive.Tip()->nHeight);
|
LogPrintf("mnw - winner out of range - FirstBlock %d Height %d bestHeight %d\n", nFirstBlock, winner.nBlockHeight, chainActive.Tip()->nHeight);
|
||||||
return;
|
return;
|
||||||
@ -427,6 +427,8 @@ bool CMasternodePayments::GetBlockPayee(int nBlockHeight, CScript& payee)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is this masternode scheduled to get paid soon?
|
||||||
|
// -- Only look ahead up to 7 blocks to allow for propagation
|
||||||
bool CMasternodePayments::IsScheduled(CMasternode& mn, int nNotBlockHeight)
|
bool CMasternodePayments::IsScheduled(CMasternode& mn, int nNotBlockHeight)
|
||||||
{
|
{
|
||||||
CBlockIndex* pindexPrev = chainActive.Tip();
|
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||||
@ -436,7 +438,7 @@ bool CMasternodePayments::IsScheduled(CMasternode& mn, int nNotBlockHeight)
|
|||||||
mnpayee = GetScriptForDestination(mn.pubkey.GetID());
|
mnpayee = GetScriptForDestination(mn.pubkey.GetID());
|
||||||
|
|
||||||
CScript payee;
|
CScript payee;
|
||||||
for(int64_t h = pindexPrev->nHeight-1; h <= pindexPrev->nHeight+11; h++){
|
for(int64_t h = pindexPrev->nHeight; h <= pindexPrev->nHeight+7; h++){
|
||||||
if(h == nNotBlockHeight) continue;
|
if(h == nNotBlockHeight) continue;
|
||||||
if(mapMasternodeBlocks.count(h)){
|
if(mapMasternodeBlocks.count(h)){
|
||||||
if(mapMasternodeBlocks[h].GetPayee(payee)){
|
if(mapMasternodeBlocks[h].GetPayee(payee)){
|
||||||
@ -564,7 +566,8 @@ void CMasternodePayments::CleanPaymentList()
|
|||||||
|
|
||||||
if(chainActive.Tip() == NULL) return;
|
if(chainActive.Tip() == NULL) return;
|
||||||
|
|
||||||
int nLimit = std::max(((int)mnodeman.size())*2, 1000);
|
//keep up to five cycles for historical sake
|
||||||
|
int nLimit = std::max(((int)mnodeman.size())*5, 1000);
|
||||||
|
|
||||||
std::map<uint256, CMasternodePaymentWinner>::iterator it = mapMasternodePayeeVotes.begin();
|
std::map<uint256, CMasternodePaymentWinner>::iterator it = mapMasternodePayeeVotes.begin();
|
||||||
while(it != mapMasternodePayeeVotes.end()) {
|
while(it != mapMasternodePayeeVotes.end()) {
|
||||||
@ -742,7 +745,7 @@ void CMasternodePayments::Sync(CNode* node, int nCountNeeded)
|
|||||||
|
|
||||||
if(chainActive.Tip() == NULL) return;
|
if(chainActive.Tip() == NULL) return;
|
||||||
|
|
||||||
int nCount = (mnodeman.CountEnabled()*1.1);
|
int nCount = (mnodeman.CountEnabled()*2);
|
||||||
if(nCountNeeded > nCount) nCountNeeded = nCount;
|
if(nCountNeeded > nCount) nCountNeeded = nCount;
|
||||||
|
|
||||||
std::map<uint256, CMasternodePaymentWinner>::iterator it = mapMasternodePayeeVotes.begin();
|
std::map<uint256, CMasternodePaymentWinner>::iterator it = mapMasternodePayeeVotes.begin();
|
||||||
|
@ -174,7 +174,7 @@ void CMasternodeSync::Process()
|
|||||||
CBlockIndex* pindexPrev = chainActive.Tip();
|
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||||
if(pindexPrev == NULL) return;
|
if(pindexPrev == NULL) return;
|
||||||
|
|
||||||
int nMnCount = mnodeman.CountEnabled()*1.1;
|
int nMnCount = mnodeman.CountEnabled()*2;
|
||||||
int nCountNeeded = (pindexPrev->nHeight - masternodePayments.GetNewestBlock());
|
int nCountNeeded = (pindexPrev->nHeight - masternodePayments.GetNewestBlock());
|
||||||
int nHaveBlocks = (pindexPrev->nHeight - masternodePayments.GetOldestBlock());
|
int nHaveBlocks = (pindexPrev->nHeight - masternodePayments.GetOldestBlock());
|
||||||
if(nHaveBlocks < nMnCount || nCountNeeded > nMnCount) {
|
if(nHaveBlocks < nMnCount || nCountNeeded > nMnCount) {
|
||||||
|
@ -241,7 +241,7 @@ int64_t CMasternode::GetLastPaid() {
|
|||||||
|
|
||||||
const CBlockIndex *BlockReading = chainActive.Tip();
|
const CBlockIndex *BlockReading = chainActive.Tip();
|
||||||
|
|
||||||
int nMnCount = mnodeman.CountEnabled()*1.1;
|
int nMnCount = mnodeman.CountEnabled()*2;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for (unsigned int i = 1; BlockReading && BlockReading->nHeight > 0; i++) {
|
for (unsigned int i = 1; BlockReading && BlockReading->nHeight > 0; i++) {
|
||||||
if(n >= nMnCount){
|
if(n >= nMnCount){
|
||||||
|
@ -29,6 +29,7 @@ struct CompareValueOnly
|
|||||||
return t1.first < t2.first;
|
return t1.first < t2.first;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CompareValueOnlyMN
|
struct CompareValueOnlyMN
|
||||||
{
|
{
|
||||||
bool operator()(const pair<int64_t, CMasternode>& t1,
|
bool operator()(const pair<int64_t, CMasternode>& t1,
|
||||||
@ -384,11 +385,19 @@ CMasternode *CMasternodeMan::Find(const CPubKey &pubKeyMasternode)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Deterministically select the oldest/best masternode to pay on the network
|
||||||
|
//
|
||||||
CMasternode* CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight)
|
CMasternode* CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
|
|
||||||
CMasternode *pOldestMasternode = NULL;
|
CMasternode *pBestMasternode = NULL;
|
||||||
|
std::vector<pair<int64_t, CTxIn> > vecMasternodeLastPaid;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Make a vector with all of the last paid times
|
||||||
|
*/
|
||||||
|
|
||||||
BOOST_FOREACH(CMasternode &mn, vMasternodes)
|
BOOST_FOREACH(CMasternode &mn, vMasternodes)
|
||||||
{
|
{
|
||||||
@ -398,18 +407,37 @@ CMasternode* CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight
|
|||||||
// //check protocol version
|
// //check protocol version
|
||||||
if(mn.protocolVersion < masternodePayments.GetMinMasternodePaymentsProto()) continue;
|
if(mn.protocolVersion < masternodePayments.GetMinMasternodePaymentsProto()) continue;
|
||||||
|
|
||||||
//it's in the list -- so let's skip it
|
//it's in the list (up to 7 entries ahead of current block to allow propagation) -- so let's skip it
|
||||||
if(masternodePayments.IsScheduled(mn, nBlockHeight)) continue;
|
if(masternodePayments.IsScheduled(mn, nBlockHeight)) continue;
|
||||||
|
|
||||||
//make sure it has as many confirmations as there are masternodes
|
//make sure it has as many confirmations as there are masternodes
|
||||||
if(mn.GetMasternodeInputAge() < CountEnabled()) continue;
|
if(mn.GetMasternodeInputAge() < CountEnabled()) continue;
|
||||||
|
|
||||||
if(pOldestMasternode == NULL || pOldestMasternode->SecondsSincePayment() < mn.SecondsSincePayment()){
|
vecMasternodeLastPaid.push_back(make_pair(mn.SecondsSincePayment(), mn.vin));
|
||||||
pOldestMasternode = &mn;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return pOldestMasternode;
|
// Sort them low to high
|
||||||
|
sort(vecMasternodeLastPaid.rbegin(), vecMasternodeLastPaid.rend(), CompareValueOnly());
|
||||||
|
|
||||||
|
// Look at 1/10 of the oldest nodes (by last payment), calculate their scores and pay the best one
|
||||||
|
// -- This doesn't look at who is being paid in the +7-10 blocks, allowing for double payments very rarely
|
||||||
|
// -- 1/100 payments should be a double payment on mainnet - (1/(3000/10))*3 --(chance per block * chances before IsScheduled will fire)
|
||||||
|
int nTenthNetwork = mnodeman.CountEnabled()/10;
|
||||||
|
int nCount = 0;
|
||||||
|
uint256 nHigh = 0;
|
||||||
|
BOOST_FOREACH (PAIRTYPE(int64_t, CTxIn)& s, vecMasternodeLastPaid){
|
||||||
|
CMasternode* pmn = mnodeman.Find(s.second);
|
||||||
|
if(!pmn) break;
|
||||||
|
|
||||||
|
uint256 n = pmn->CalculateScore(1, nBlockHeight-100);
|
||||||
|
if(n > nHigh){
|
||||||
|
nHigh = n;
|
||||||
|
pBestMasternode = pmn;
|
||||||
|
}
|
||||||
|
nCount++;
|
||||||
|
if(nCount >= nTenthNetwork) break;
|
||||||
|
}
|
||||||
|
return pBestMasternode;
|
||||||
}
|
}
|
||||||
|
|
||||||
CMasternode *CMasternodeMan::FindRandom()
|
CMasternode *CMasternodeMan::FindRandom()
|
||||||
@ -682,7 +710,6 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
int64_t askAgain = GetTime() + MASTERNODES_DSEG_SECONDS;
|
int64_t askAgain = GetTime() + MASTERNODES_DSEG_SECONDS;
|
||||||
|
|
||||||
mAskedUsForMasternodeList[pfrom->addr] = askAgain;
|
mAskedUsForMasternodeList[pfrom->addr] = askAgain;
|
||||||
}
|
}
|
||||||
} //else, asking for a specific node which is ok
|
} //else, asking for a specific node which is ok
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
* network protocol versioning
|
* network protocol versioning
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static const int PROTOCOL_VERSION = 70093;
|
static const int PROTOCOL_VERSION = 70094;
|
||||||
|
|
||||||
//! initial proto version, to be increased after version/verack negotiation
|
//! initial proto version, to be increased after version/verack negotiation
|
||||||
static const int INIT_PROTO_VERSION = 209;
|
static const int INIT_PROTO_VERSION = 209;
|
||||||
@ -22,19 +22,19 @@ static const int GETHEADERS_VERSION = 70077;
|
|||||||
static const int MIN_PEER_PROTO_VERSION = 70066;
|
static const int MIN_PEER_PROTO_VERSION = 70066;
|
||||||
|
|
||||||
//! minimum peer version accepted by DarksendPool
|
//! minimum peer version accepted by DarksendPool
|
||||||
static const int MIN_POOL_PEER_PROTO_VERSION = 70093;
|
static const int MIN_POOL_PEER_PROTO_VERSION = 70094;
|
||||||
|
|
||||||
//! minimum peer version for masternode budgets
|
//! minimum peer version for masternode budgets
|
||||||
static const int MIN_BUDGET_PEER_PROTO_VERSION = 70093;
|
static const int MIN_BUDGET_PEER_PROTO_VERSION = 70094;
|
||||||
|
|
||||||
//! minimum peer version for masternode winner broadcasts
|
//! minimum peer version for masternode winner broadcasts
|
||||||
static const int MIN_MNW_PEER_PROTO_VERSION = 70093;
|
static const int MIN_MNW_PEER_PROTO_VERSION = 70094;
|
||||||
|
|
||||||
//! minimum peer version that can receive masternode payments
|
//! minimum peer version that can receive masternode payments
|
||||||
// V1 - Last protocol version before update
|
// V1 - Last protocol version before update
|
||||||
// V2 - Newest protocol version
|
// V2 - Newest protocol version
|
||||||
static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_1 = 70066;
|
static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_1 = 70066;
|
||||||
static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_2 = 70093;
|
static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_2 = 70094;
|
||||||
|
|
||||||
//! nTime field added to CAddress, starting with this version;
|
//! nTime field added to CAddress, starting with this version;
|
||||||
//! if possible, avoid requesting addresses nodes older than this
|
//! if possible, avoid requesting addresses nodes older than this
|
||||||
|
Loading…
Reference in New Issue
Block a user