Fixed budget syncing issues / forking issues / syncing issues

- Budgets now store the seen objects locally so they're not overwritten when saving/loading to check validity of budget.dat
- Added safer sync "failure" mode, that will retry an hour later if the sync fails for some reason. This will stop the client from thinking it has budget data and rejecting blocks when they're valid.
- protocol bump
- version bump
This commit is contained in:
Evan Duffield 2015-07-25 09:29:29 -07:00
parent 24183b156b
commit 8187228be1
11 changed files with 104 additions and 46 deletions

View File

@ -3,7 +3,7 @@ AC_PREREQ([2.60])
define(_CLIENT_VERSION_MAJOR, 0)
define(_CLIENT_VERSION_MINOR, 12)
define(_CLIENT_VERSION_REVISION, 0)
define(_CLIENT_VERSION_BUILD, 28)
define(_CLIENT_VERSION_BUILD, 29)
define(_CLIENT_VERSION_IS_RELEASE, true)
define(_COPYRIGHT_YEAR, 2015)
AC_INIT([Dash Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[info@dashpay.io],[dash])

View File

@ -17,7 +17,7 @@ void CActiveMasternode::ManageStatus()
if (fDebug) LogPrintf("CActiveMasternode::ManageStatus() - Begin\n");
//need correct blocks to send ping
if(!masternodeSync.IsSynced()) {
if(Params().NetworkID() != CBaseChainParams::REGTEST && !masternodeSync.IsSynced()) {
status = ACTIVE_MASTERNODE_SYNC_IN_PROCESS;
LogPrintf("CActiveMasternode::ManageStatus() - %s\n", GetStatus());
return;

View File

@ -17,7 +17,7 @@
#define CLIENT_VERSION_MAJOR 0
#define CLIENT_VERSION_MINOR 12
#define CLIENT_VERSION_REVISION 0
#define CLIENT_VERSION_BUILD 28
#define CLIENT_VERSION_BUILD 29
//! Set to true for release, false for prerelease or test build
#define CLIENT_VERSION_IS_RELEASE true

View File

@ -15,7 +15,11 @@
/*
At 15 signatures, 1/2 of the masternode network can be owned by
one party without comprimising the security of InstantX
(1000/2150.0)**15 = 1.031e-05
(1000/2150.0)**10 = 0.00047382219560689856
(1000/2900.0)**10 = 2.3769498616783657e-05
### getting 5 of 10 signatures w/ 1000 nodes of 2900
(1000/2900.0)**5 = 0.004875397277841433
*/
#define INSTANTX_SIGNATURES_REQUIRED 5
#define INSTANTX_SIGNATURES_TOTAL 10
@ -27,7 +31,7 @@ class CConsensusVote;
class CTransaction;
class CTransactionLock;
static const int MIN_INSTANTX_PROTO_VERSION = 70096;
static const int MIN_INSTANTX_PROTO_VERSION = 70097;
extern map<uint256, CTransaction> mapTxLockReq;
extern map<uint256, CTransaction> mapTxLockReqRejected;

View File

@ -3266,6 +3266,17 @@ bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDis
darkSendPool.NewBlock();
masternodePayments.ProcessBlock(GetHeight()+10);
budget.NewBlock();
//allow clients to ask for syncing again if they need it
if(GetHeight() % 100 == 0) {
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes) {
pnode->ClearFulfilledRequest("getspork");
pnode->ClearFulfilledRequest("mnsync");
pnode->ClearFulfilledRequest("mnwsync");
pnode->ClearFulfilledRequest("busync");
}
}
}
}
@ -3970,25 +3981,25 @@ bool static AlreadyHave(const CInv& inv)
}
return false;
case MSG_BUDGET_VOTE:
if(mapSeenMasternodeBudgetVotes.count(inv.hash)) {
if(budget.mapSeenMasternodeBudgetVotes.count(inv.hash)) {
masternodeSync.AddedBudgetItem();
return true;
}
return false;
case MSG_BUDGET_PROPOSAL:
if(mapSeenMasternodeBudgetProposals.count(inv.hash)) {
if(budget.mapSeenMasternodeBudgetProposals.count(inv.hash)) {
masternodeSync.AddedBudgetItem();
return true;
}
return false;
case MSG_BUDGET_FINALIZED_VOTE:
if(mapSeenFinalizedBudgetVotes.count(inv.hash)) {
if(budget.mapSeenFinalizedBudgetVotes.count(inv.hash)) {
masternodeSync.AddedBudgetItem();
return true;
}
return false;
case MSG_BUDGET_FINALIZED:
if(mapSeenFinalizedBudgets.count(inv.hash)) {
if(budget.mapSeenFinalizedBudgets.count(inv.hash)) {
masternodeSync.AddedBudgetItem();
return true;
}
@ -4161,40 +4172,40 @@ void static ProcessGetData(CNode* pfrom)
}
}
if (!pushed && inv.type == MSG_BUDGET_VOTE) {
if(mapSeenMasternodeBudgetVotes.count(inv.hash)){
if(budget.mapSeenMasternodeBudgetVotes.count(inv.hash)){
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(1000);
ss << mapSeenMasternodeBudgetVotes[inv.hash];
ss << budget.mapSeenMasternodeBudgetVotes[inv.hash];
pfrom->PushMessage("mvote", ss);
pushed = true;
}
}
if (!pushed && inv.type == MSG_BUDGET_PROPOSAL) {
if(mapSeenMasternodeBudgetProposals.count(inv.hash)){
if(budget.mapSeenMasternodeBudgetProposals.count(inv.hash)){
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(1000);
ss << mapSeenMasternodeBudgetProposals[inv.hash];
ss << budget.mapSeenMasternodeBudgetProposals[inv.hash];
pfrom->PushMessage("mprop", ss);
pushed = true;
}
}
if (!pushed && inv.type == MSG_BUDGET_FINALIZED_VOTE) {
if(mapSeenFinalizedBudgetVotes.count(inv.hash)){
if(budget.mapSeenFinalizedBudgetVotes.count(inv.hash)){
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(1000);
ss << mapSeenFinalizedBudgetVotes[inv.hash];
ss << budget.mapSeenFinalizedBudgetVotes[inv.hash];
pfrom->PushMessage("fbvote", ss);
pushed = true;
}
}
if (!pushed && inv.type == MSG_BUDGET_FINALIZED) {
if(mapSeenFinalizedBudgets.count(inv.hash)){
if(budget.mapSeenFinalizedBudgets.count(inv.hash)){
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(1000);
ss << mapSeenFinalizedBudgets[inv.hash];
ss << budget.mapSeenFinalizedBudgets[inv.hash];
pfrom->PushMessage("fbs", ss);
pushed = true;
}
@ -4818,7 +4829,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if (state.IsInvalid(nDoS)) {
if (nDoS > 0)
Misbehaving(pfrom->GetId(), nDoS);
return error("invalid header received");
std::string strError = "invalid header received " + header.GetHash().ToString();
return error(strError.c_str());
}
}
}

View File

@ -18,13 +18,6 @@
CBudgetManager budget;
CCriticalSection cs_budget;
std::map<uint256, CBudgetProposalBroadcast> mapSeenMasternodeBudgetProposals;
std::map<uint256, CBudgetVote> mapSeenMasternodeBudgetVotes;
std::map<uint256, CBudgetVote> mapOrphanMasternodeBudgetVotes;
std::map<uint256, CFinalizedBudgetBroadcast> mapSeenFinalizedBudgets;
std::map<uint256, CFinalizedBudgetVote> mapSeenFinalizedBudgetVotes;
std::map<uint256, CFinalizedBudgetVote> mapOrphanFinalizedBudgetVotes;
std::map<uint256, int64_t> askedForSourceProposalOrBudget;
int nSubmittedFinalBudget;
@ -514,6 +507,19 @@ bool CBudgetManager::IsBudgetPaymentBlock(int nBlockHeight){
return false;
}
bool CBudgetManager::HasNextFinalizedBudget()
{
CBlockIndex* pindexPrev = chainActive.Tip();
if(!pindexPrev) return false;
int nBlockStart = pindexPrev->nHeight - pindexPrev->nHeight % GetBudgetPaymentCycleBlocks() + GetBudgetPaymentCycleBlocks();
if(nBlockStart - pindexPrev->nHeight > 576*2) return false; //we wouldn't have the budget yet
if(budget.IsBudgetPaymentBlock(nBlockStart)) return true;
return false;
}
bool CBudgetManager::IsTransactionValid(const CTransaction& txNew, int nBlockHeight)
{
int nHighestCount = 0;
@ -771,7 +777,6 @@ void CBudgetManager::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
uint256 nProp;
vRecv >> nProp;
if(Params().NetworkID() == CBaseChainParams::MAIN){
if(pfrom->HasFulfilledRequest("mnvs")) {
LogPrintf("mnvs - peer already asked me for the list\n");
@ -810,6 +815,8 @@ void CBudgetManager::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
budgetProposalBroadcast.Relay();
masternodeSync.AddedBudgetItem();
LogPrintf("mprop - new budget - %s\n", budgetProposalBroadcast.GetHash().ToString());
//We might have active votes for this proposal that are valid now
CheckOrphanVotes();
}
@ -843,6 +850,8 @@ void CBudgetManager::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
vote.Relay();
if(!masternodeSync.IsSynced()) pmn->nVotedTimes++;
masternodeSync.AddedBudgetItem();
LogPrintf("mvote - new budget vote - %s\n", vote.GetHash().ToString());
} else {
LogPrintf("mvote - masternode can't vote again - vin: %s\n", pmn->vin.ToString());
return;
@ -871,6 +880,8 @@ void CBudgetManager::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
return;
}
LogPrintf("fbs - new finalized budget - %s\n", finalizedBudgetBroadcast.GetHash().ToString());
CFinalizedBudget finalizedBudget(finalizedBudgetBroadcast);
AddFinalizedBudget(finalizedBudget);
finalizedBudgetBroadcast.Relay();
@ -908,6 +919,9 @@ void CBudgetManager::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
vote.Relay();
if(!masternodeSync.IsSynced()) pmn->nVotedTimes++;
masternodeSync.AddedBudgetItem();
if(fDebug) LogPrintf("fbs - new finalized budget vote - %s\n", vote.GetHash().ToString());
} else {
LogPrintf("fbvote - masternode can't vote again - vin: %s\n", pmn->vin.ToString());
return;
@ -953,7 +967,6 @@ void CBudgetManager::Sync(CNode* pfrom, uint256 nProp)
++it1;
}
std::map<uint256, CFinalizedBudgetBroadcast>::iterator it3 = mapSeenFinalizedBudgets.begin();
while(it3 != mapSeenFinalizedBudgets.end()){
CFinalizedBudget* pfinalizedBudget = FindFinalizedBudget((*it3).first);
@ -1576,7 +1589,7 @@ void CFinalizedBudget::SubmitVote()
return;
}
mapSeenFinalizedBudgetVotes.insert(make_pair(vote.GetHash(), vote));
budget.mapSeenFinalizedBudgetVotes.insert(make_pair(vote.GetHash(), vote));
vote.Relay();
budget.UpdateFinalizedBudget(vote, NULL);
}
@ -1690,7 +1703,11 @@ std::string CBudgetManager::ToString() const
std::ostringstream info;
info << "Proposals: " << (int)mapProposals.size() <<
", Budgets: " << (int)mapFinalizedBudgets.size();
", Budgets: " << (int)mapFinalizedBudgets.size() <<
", Seen Budgets: " << (int)mapSeenMasternodeBudgetProposals.size() <<
", Seen Budget Votes: " << (int)mapSeenMasternodeBudgetVotes.size() <<
", Seen Final Budgets: " << (int)mapSeenFinalizedBudgets.size() <<
", Seen Final Budget Votes: " << (int)mapSeenFinalizedBudgetVotes.size();
return info.str();
}

View File

@ -33,11 +33,6 @@ class CTxBudgetPayment;
static const CAmount BUDGET_FEE_TX = (0.5*COIN);
static const int64_t BUDGET_FEE_CONFIRMATIONS = 6;
extern std::map<uint256, CBudgetProposalBroadcast> mapSeenMasternodeBudgetProposals;
extern std::map<uint256, CBudgetVote> mapSeenMasternodeBudgetVotes;
extern std::map<uint256, CFinalizedBudgetBroadcast> mapSeenFinalizedBudgets;
extern std::map<uint256, CFinalizedBudgetVote> mapSeenFinalizedBudgetVotes;
extern CBudgetManager budget;
void DumpBudgets();
@ -88,6 +83,13 @@ public:
map<uint256, CBudgetProposal> mapProposals;
map<uint256, CFinalizedBudget> mapFinalizedBudgets;
std::map<uint256, CBudgetProposalBroadcast> mapSeenMasternodeBudgetProposals;
std::map<uint256, CBudgetVote> mapSeenMasternodeBudgetVotes;
std::map<uint256, CBudgetVote> mapOrphanMasternodeBudgetVotes;
std::map<uint256, CFinalizedBudgetBroadcast> mapSeenFinalizedBudgets;
std::map<uint256, CFinalizedBudgetVote> mapSeenFinalizedBudgetVotes;
std::map<uint256, CFinalizedBudgetVote> mapOrphanFinalizedBudgetVotes;
CBudgetManager() {
mapProposals.clear();
mapFinalizedBudgets.clear();
@ -114,6 +116,7 @@ public:
void AddProposal(CBudgetProposal& budgetProposal);
void AddFinalizedBudget(CFinalizedBudget& finalizedBudget);
void SubmitFinalBudget();
bool HasNextFinalizedBudget();
bool UpdateProposal(CBudgetVote& vote, CNode* pfrom);
bool UpdateFinalizedBudget(CFinalizedBudgetVote& vote, CNode* pfrom);
@ -131,6 +134,8 @@ public:
mapSeenMasternodeBudgetVotes.clear();
mapSeenFinalizedBudgets.clear();
mapSeenFinalizedBudgetVotes.clear();
mapOrphanMasternodeBudgetVotes.clear();
mapOrphanFinalizedBudgetVotes.clear();
}
void CheckAndRemove();
std::string ToString() const;
@ -144,6 +149,8 @@ public:
READWRITE(mapSeenMasternodeBudgetVotes);
READWRITE(mapSeenFinalizedBudgets);
READWRITE(mapSeenFinalizedBudgetVotes);
READWRITE(mapOrphanMasternodeBudgetVotes);
READWRITE(mapOrphanFinalizedBudgetVotes);
READWRITE(mapProposals);
READWRITE(mapFinalizedBudgets);

View File

@ -5,6 +5,7 @@
#include "main.h"
#include "masternode-sync.h"
#include "masternode-payments.h"
#include "masternode-budget.h"
#include "masternode.h"
#include "masternodeman.h"
#include "util.h"
@ -47,6 +48,7 @@ void CMasternodeSync::GetNextAsset()
switch(RequestedMasternodeAssets)
{
case(MASTERNODE_SYNC_INITIAL):
case(MASTERNODE_SYNC_FAILED):
lastMasternodeList = 0;
lastMasternodeWinner = 0;
lastBudgetItem = 0;
@ -97,6 +99,13 @@ void CMasternodeSync::Process()
return;
}
//try syncing again in an hour
if(RequestedMasternodeAssets == MASTERNODE_SYNC_FAILED && lastFailure + (60*60) < GetTime()) {
GetNextAsset();
} else if (RequestedMasternodeAssets == MASTERNODE_SYNC_FAILED) {
return;
}
if(fDebug) LogPrintf("CMasternodeSync::Process() - tick %d RequestedMasternodeAssets %d\n", tick, RequestedMasternodeAssets);
if(RequestedMasternodeAssets == MASTERNODE_SYNC_INITIAL) GetNextAsset();
@ -185,7 +194,14 @@ void CMasternodeSync::Process()
if(RequestedMasternodeAssets == MASTERNODE_SYNC_BUDGET){
if(lastBudgetItem > 0 && lastBudgetItem < GetTime() - MASTERNODE_SYNC_TIMEOUT){ //hasn't received a new item in the last five seconds, so we'll move to the
if(budget.HasNextFinalizedBudget()) {
GetNextAsset();
} else { //we've failed to sync, this state will reject the next budget block
LogPrintf("CMasternodeSync::Process - ERROR - Sync has failed, will retry later\n");
RequestedMasternodeAssets = MASTERNODE_SYNC_FAILED;
RequestedMasternodeAttempt = 0;
lastFailure = GetTime();
}
return;
}

View File

@ -10,9 +10,10 @@
#define MASTERNODE_SYNC_LIST 2
#define MASTERNODE_SYNC_MNW 3
#define MASTERNODE_SYNC_BUDGET 4
#define MASTERNODE_SYNC_FAILED 998
#define MASTERNODE_SYNC_FINISHED 999
#define MASTERNODE_SYNC_TIMEOUT 5
#define MASTERNODE_SYNC_TIMEOUT 15
class CMasternodeSync;
extern CMasternodeSync masternodeSync;
@ -27,6 +28,7 @@ public:
int64_t lastMasternodeList;
int64_t lastMasternodeWinner;
int64_t lastBudgetItem;
int64_t lastFailure;
// Count peers we've requested the list from
int RequestedMasternodeAssets;

View File

@ -180,7 +180,7 @@ Value mnbudget(const Array& params, bool fHelp)
return "Proposal is not valid - " + budgetProposalBroadcast.GetHash().ToString() + " - " + strError;
}
mapSeenMasternodeBudgetProposals.insert(make_pair(budgetProposalBroadcast.GetHash(), budgetProposalBroadcast));
budget.mapSeenMasternodeBudgetProposals.insert(make_pair(budgetProposalBroadcast.GetHash(), budgetProposalBroadcast));
budgetProposalBroadcast.Relay();
budget.AddProposal(budgetProposalBroadcast);
@ -248,7 +248,7 @@ Value mnbudget(const Array& params, bool fHelp)
continue;
}
mapSeenMasternodeBudgetVotes.insert(make_pair(vote.GetHash(), vote));
budget.mapSeenMasternodeBudgetVotes.insert(make_pair(vote.GetHash(), vote));
vote.Relay();
budget.UpdateProposal(vote, NULL);
@ -292,7 +292,7 @@ Value mnbudget(const Array& params, bool fHelp)
return "Failure to sign.";
}
mapSeenMasternodeBudgetVotes.insert(make_pair(vote.GetHash(), vote));
budget.mapSeenMasternodeBudgetVotes.insert(make_pair(vote.GetHash(), vote));
vote.Relay();
budget.UpdateProposal(vote, NULL);
@ -538,7 +538,7 @@ Value mnfinalbudget(const Array& params, bool fHelp)
continue;
}
mapSeenFinalizedBudgetVotes.insert(make_pair(vote.GetHash(), vote));
budget.mapSeenFinalizedBudgetVotes.insert(make_pair(vote.GetHash(), vote));
vote.Relay();
budget.UpdateFinalizedBudget(vote, NULL);
@ -577,7 +577,7 @@ Value mnfinalbudget(const Array& params, bool fHelp)
return "Failure to sign.";
}
mapSeenFinalizedBudgetVotes.insert(make_pair(vote.GetHash(), vote));
budget.mapSeenFinalizedBudgetVotes.insert(make_pair(vote.GetHash(), vote));
vote.Relay();
budget.UpdateFinalizedBudget(vote, NULL);

View File

@ -10,7 +10,7 @@
* network protocol versioning
*/
static const int PROTOCOL_VERSION = 70096;
static const int PROTOCOL_VERSION = 70097;
//! initial proto version, to be increased after version/verack negotiation
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;
//! minimum peer version accepted by DarksendPool
static const int MIN_POOL_PEER_PROTO_VERSION = 70096;
static const int MIN_POOL_PEER_PROTO_VERSION = 70097;
//! minimum peer version for masternode budgets
static const int MIN_BUDGET_PEER_PROTO_VERSION = 70096;
static const int MIN_BUDGET_PEER_PROTO_VERSION = 70097;
//! minimum peer version for masternode winner broadcasts
static const int MIN_MNW_PEER_PROTO_VERSION = 70096;
static const int MIN_MNW_PEER_PROTO_VERSION = 70097;
//! minimum peer version that can receive masternode payments
// V1 - Last protocol version before update
// V2 - Newest protocol version
static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_1 = 70066;
static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_2 = 70096;
static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_2 = 70097;
//! nTime field added to CAddress, starting with this version;
//! if possible, avoid requesting addresses nodes older than this