masternode-sync.cpp 8.31 KB
Newer Older
1
2
3
4
5
6
// 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 "main.h"
#include "masternode-sync.h"
UdjinM6's avatar
UdjinM6 committed
7
#include "masternode-payments.h"
8
#include "masternode-budget.h"
9
#include "masternode.h"
UdjinM6's avatar
UdjinM6 committed
10
#include "masternodeman.h"
11
12
13
14
15
16
17
18
19
20
21
#include "util.h"
#include "addrman.h"

class CMasternodeSync;
CMasternodeSync masternodeSync;

CMasternodeSync::CMasternodeSync()
{
    lastMasternodeList = 0;
    lastMasternodeWinner = 0;
    lastBudgetItem = 0;
22
    RequestedMasternodeAssets = MASTERNODE_SYNC_INITIAL;
23
24
25
26
27
    RequestedMasternodeAttempt = 0;
}

bool CMasternodeSync::IsSynced()
{
Evan Duffield's avatar
Evan Duffield committed
28
    return RequestedMasternodeAssets == MASTERNODE_SYNC_FINISHED;
29
30
}

31
bool CMasternodeSync::IsBlockchainSynced()
32
{
33
34
35
36
37
    CBlockIndex* pindexPrev = chainActive.Tip();
    if(pindexPrev == NULL) return false;

    if(pindexPrev->nHeight + 4 < pindexBestHeader->nHeight || pindexPrev->nTime + 600 < GetTime()) return false;
    return true;
38
39
}

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
void CMasternodeSync::AddedMasternodeList()
{
    lastMasternodeList = GetTime();
}

void CMasternodeSync::AddedMasternodeWinner()
{
    lastMasternodeWinner = GetTime();
}

void CMasternodeSync::AddedBudgetItem()
{
    lastBudgetItem = GetTime();
}

void CMasternodeSync::GetNextAsset()
{
    switch(RequestedMasternodeAssets)
    {
59
        case(MASTERNODE_SYNC_INITIAL):
60
        case(MASTERNODE_SYNC_FAILED):
UdjinM6's avatar
UdjinM6 committed
61
62
63
            lastMasternodeList = 0;
            lastMasternodeWinner = 0;
            lastBudgetItem = 0;
64
            RequestedMasternodeAssets = MASTERNODE_SYNC_SPORKS;
Evan Duffield's avatar
Evan Duffield committed
65
            break;
66
        case(MASTERNODE_SYNC_SPORKS):
67
68
69
70
71
72
73
74
75
            RequestedMasternodeAssets = MASTERNODE_SYNC_LIST;
            break;
        case(MASTERNODE_SYNC_LIST):
            RequestedMasternodeAssets = MASTERNODE_SYNC_MNW;
            break;
        case(MASTERNODE_SYNC_MNW):
            RequestedMasternodeAssets = MASTERNODE_SYNC_BUDGET;
            break;
        case(MASTERNODE_SYNC_BUDGET):
76
            LogPrintf("CMasternodeSync::GetNextAsset - Sync has finished\n");
77
            RequestedMasternodeAssets = MASTERNODE_SYNC_FINISHED;
78
79
            break;
    }
UdjinM6's avatar
UdjinM6 committed
80
    RequestedMasternodeAttempt = 0;
81
82
}

UdjinM6's avatar
UdjinM6 committed
83
void CMasternodeSync::Process()
84
{
UdjinM6's avatar
UdjinM6 committed
85
86
87
88
89
90
    static int tick = 0;

    if(tick++ % MASTERNODE_SYNC_TIMEOUT != 0) return;

    CBlockIndex* pindexPrev = chainActive.Tip();
    if(pindexPrev == NULL) return;
UdjinM6's avatar
UdjinM6 committed
91

92
93
94
95
96
    if(IsSynced()) {
        /* 
            Resync if we lose all masternodes from sleep/wake or failure to sync originally
        */
        if(mnodeman.CountEnabled() == 0) {
UdjinM6's avatar
UdjinM6 committed
97
98
99
100
101
102
103
104
105
            LOCK(cs_vNodes);
            BOOST_FOREACH(CNode* pnode, vNodes)
            {
                pnode->ClearFulfilledRequest("getspork");
                pnode->ClearFulfilledRequest("mnsync");
                pnode->ClearFulfilledRequest("mnwsync");
                pnode->ClearFulfilledRequest("busync");
            }

106
            RequestedMasternodeAssets = MASTERNODE_SYNC_INITIAL;
UdjinM6's avatar
UdjinM6 committed
107
108
        } else
            return;
109
    }
110

111
112
113
114
115
116
117
    //try syncing again in an hour
    if(RequestedMasternodeAssets == MASTERNODE_SYNC_FAILED && lastFailure + (60*60) < GetTime()) {
        GetNextAsset();
    } else if (RequestedMasternodeAssets == MASTERNODE_SYNC_FAILED) {
        return;
    }

UdjinM6's avatar
UdjinM6 committed
118
    if(fDebug) LogPrintf("CMasternodeSync::Process() - tick %d RequestedMasternodeAssets %d\n", tick, RequestedMasternodeAssets);
UdjinM6's avatar
UdjinM6 committed
119

120
    if(RequestedMasternodeAssets == MASTERNODE_SYNC_INITIAL) GetNextAsset();
121

UdjinM6's avatar
UdjinM6 committed
122
123
124
    LOCK(cs_vNodes);
    BOOST_FOREACH(CNode* pnode, vNodes)
    {
Evan Duffield's avatar
Evan Duffield committed
125
126
        if(Params().NetworkID() == CBaseChainParams::REGTEST){
            if(RequestedMasternodeAttempt <= 2) {
Evan Duffield's avatar
Evan Duffield committed
127
                pnode->PushMessage("getsporks"); //get current network sporks
Evan Duffield's avatar
Evan Duffield committed
128
129
130
131
132
133
134
135
136
            } else if(RequestedMasternodeAttempt < 4) {
                mnodeman.DsegUpdate(pnode); 
            } else if(RequestedMasternodeAttempt < 6) {
                int nMnCount = mnodeman.CountEnabled()*2;
                pnode->PushMessage("mnget", nMnCount); //sync payees
                uint256 n = 0;
                pnode->PushMessage("mnvs", n); //sync masternode votes
            } else {
                RequestedMasternodeAssets = MASTERNODE_SYNC_FINISHED;
UdjinM6's avatar
UdjinM6 committed
137
            }
Evan Duffield's avatar
Evan Duffield committed
138
            RequestedMasternodeAttempt++;
UdjinM6's avatar
UdjinM6 committed
139
140
141
            return;
        }

Evan Duffield's avatar
Evan Duffield committed
142
143
144
145
146
147
148
149
150
151
152
        //set to synced
        if(RequestedMasternodeAssets == MASTERNODE_SYNC_SPORKS){
            if(pnode->HasFulfilledRequest("getspork")) continue;
            pnode->FulfilledRequest("getspork");

            pnode->PushMessage("getsporks"); //get current network sporks
            if(RequestedMasternodeAttempt >= 2) GetNextAsset();
            RequestedMasternodeAttempt++;
            
            return;
        }
153

UdjinM6's avatar
UdjinM6 committed
154
155
        if(IsInitialBlockDownload()) return;

UdjinM6's avatar
UdjinM6 committed
156
        //don't begin syncing until we're almost at a recent block
Evan Duffield's avatar
Evan Duffield committed
157
        if(pindexPrev->nHeight + 4 < pindexBestHeader->nHeight || pindexPrev->nTime + 600 < GetTime()) return;
158

159
        if (pnode->nVersion >= masternodePayments.GetMinMasternodePaymentsProto()) {
160

UdjinM6's avatar
UdjinM6 committed
161
162
            if(RequestedMasternodeAssets == MASTERNODE_SYNC_LIST) {
                if(fDebug) LogPrintf("CMasternodeSync::Process() - lastMasternodeList %lld (GetTime() - MASTERNODE_SYNC_TIMEOUT) %lld\n", lastMasternodeList, GetTime() - MASTERNODE_SYNC_TIMEOUT);
UdjinM6's avatar
UdjinM6 committed
163
164
                if(lastMasternodeList > 0 && lastMasternodeList < GetTime() - MASTERNODE_SYNC_TIMEOUT){ //hasn't received a new item in the last five seconds, so we'll move to the
                    GetNextAsset();
165
166
167
                    return;
                }

UdjinM6's avatar
UdjinM6 committed
168
169
                if(pnode->HasFulfilledRequest("mnsync")) continue;
                pnode->FulfilledRequest("mnsync");
170

UdjinM6's avatar
UdjinM6 committed
171
                if((lastMasternodeList == 0 || lastMasternodeList > GetTime() - MASTERNODE_SYNC_TIMEOUT)
172
                        && RequestedMasternodeAttempt <= 4){
UdjinM6's avatar
UdjinM6 committed
173
174
175
176
177
                    mnodeman.DsegUpdate(pnode);
                    RequestedMasternodeAttempt++;
                }
                return;
            }
178

UdjinM6's avatar
UdjinM6 committed
179
            if(RequestedMasternodeAssets == MASTERNODE_SYNC_MNW) {
UdjinM6's avatar
UdjinM6 committed
180
181
                if(lastMasternodeWinner > 0 && lastMasternodeWinner < GetTime() - MASTERNODE_SYNC_TIMEOUT){ //hasn't received a new item in the last five seconds, so we'll move to the
                    GetNextAsset();
182
183
                    return;
                }
UdjinM6's avatar
UdjinM6 committed
184
185
186
187
188

                if(pnode->HasFulfilledRequest("mnwsync")) continue;
                pnode->FulfilledRequest("mnwsync");

                if((lastMasternodeWinner == 0 || lastMasternodeWinner > GetTime() - MASTERNODE_SYNC_TIMEOUT)
Evan Duffield's avatar
Evan Duffield committed
189
                        && RequestedMasternodeAttempt <= 4){
190
191
192
193

                    CBlockIndex* pindexPrev = chainActive.Tip();
                    if(pindexPrev == NULL) return;

194
                    int nMnCount = mnodeman.CountEnabled()*2;
Evan Duffield's avatar
Evan Duffield committed
195
                    pnode->PushMessage("mnget", nMnCount); //sync payees
UdjinM6's avatar
UdjinM6 committed
196
197
198
199
                    RequestedMasternodeAttempt++;
                }
                return;
            }
UdjinM6's avatar
UdjinM6 committed
200
201
202
        }

        if (pnode->nVersion >= MIN_BUDGET_PEER_PROTO_VERSION) {
UdjinM6's avatar
UdjinM6 committed
203
204

            if(RequestedMasternodeAssets == MASTERNODE_SYNC_BUDGET){
205
206
                //we'll start rejecting votes if we accidentally get set as synced too soon
                if(lastBudgetItem > 0 && lastBudgetItem < GetTime() - MASTERNODE_SYNC_TIMEOUT*3){ //hasn't received a new item in the last five seconds, so we'll move to the
207
208
209
210
211
212
213
214
                    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();
                    }
215
216
217
                    return;
                }

UdjinM6's avatar
UdjinM6 committed
218
219
220
221
                if(pnode->HasFulfilledRequest("busync")) continue;
                pnode->FulfilledRequest("busync");

                if((lastBudgetItem == 0 || lastBudgetItem > GetTime() - MASTERNODE_SYNC_TIMEOUT)
Evan Duffield's avatar
Evan Duffield committed
222
                        && RequestedMasternodeAttempt <= 4){
UdjinM6's avatar
UdjinM6 committed
223
224
225
226
227
                    uint256 n = 0;
                    pnode->PushMessage("mnvs", n); //sync masternode votes
                    RequestedMasternodeAttempt++;
                }
                return;
228
            }
UdjinM6's avatar
UdjinM6 committed
229

230
231
        }
    }
UdjinM6's avatar
UdjinM6 committed
232
}