masternode-budget.h 18.2 KB
Newer Older
Infernoman's avatar
Infernoman committed
1
// Copyright (c) 2014-2015 The Crown developers
2

3
4
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
Alastair Clark's avatar
Alastair Clark committed
5
6
#ifndef MASTERNODE_BUDGET_H
#define MASTERNODE_BUDGET_H
7
8
9
10
11
12
13

#include "main.h"
#include "sync.h"
#include "net.h"
#include "key.h"
#include "util.h"
#include "base58.h"
Alastair Clark's avatar
Alastair Clark committed
14
#include "masternode.h"
Evan Duffield's avatar
Evan Duffield committed
15
#include "init.h"
16

17
18
#include <boost/lexical_cast.hpp>

19
20
using namespace std;

21
22
extern CCriticalSection cs_budget;

23
class CBudgetManager;
24
25
26
class CFinalizedBudgetBroadcast;
class CFinalizedBudget;
class CFinalizedBudgetVote;
27
class CBudgetProposal;
28
class CBudgetProposalBroadcast;
29
class CBudgetVote;
Evan Duffield's avatar
Evan Duffield committed
30
class CTxBudgetPayment;
31
32
33
34

#define VOTE_ABSTAIN  0
#define VOTE_YES      1
#define VOTE_NO       2
Evan Duffield's avatar
Evan Duffield committed
35

Infernoman's avatar
Infernoman committed
36
static const CAmount BUDGET_FEE_TX = (25*COIN);
37
static const int64_t BUDGET_FEE_CONFIRMATIONS = 6;
38
static const int64_t BUDGET_VOTE_UPDATE_MIN = 60*60;
39
static const int64_t FINAL_BUDGET_VOTE_UPDATE_MIN = 30*60;
40

41
42
43
extern std::vector<CBudgetProposalBroadcast> vecImmatureBudgetProposals;
extern std::vector<CFinalizedBudgetBroadcast> vecImmatureFinalizedBudgets;

44
45
46
extern CBudgetManager budget;
void DumpBudgets();

UdjinM6's avatar
UdjinM6 committed
47
// Define amount of blocks in budget payment cycle
48
49
int GetBudgetPaymentCycleBlocks();

Evan Duffield's avatar
Evan Duffield committed
50
//Check the collateral transaction for the budget proposal/finalized budget
51
bool IsBudgetCollateralValid(uint256 nTxCollateralHash, uint256 nExpectedHash, std::string& strError, int64_t& nTime, int& nConf);
Evan Duffield's avatar
Evan Duffield committed
52

53
54
55
56
57
58
/** Save Budget Manager (budget.dat)
 */
class CBudgetDB
{
private:
    boost::filesystem::path pathDB;
59
    std::string strMagicMessage;
60
61
62
63
64
65
66
67
68
69
70
71
public:
    enum ReadResult {
        Ok,
        FileError,
        HashReadError,
        IncorrectHash,
        IncorrectMagicMessage,
        IncorrectMagicNumber,
        IncorrectFormat
    };

    CBudgetDB();
Volodymyr Shamray's avatar
Volodymyr Shamray committed
72
    CBudgetDB(const boost::filesystem::path& pathDb);
73

74
    bool Write(const CBudgetManager &objToSave);
UdjinM6's avatar
UdjinM6 committed
75
    ReadResult Read(CBudgetManager& objToLoad, bool fDryRun = false);
76
77
78
79
80
81
82
83
84
85
};


//
// Budget Manager : Contains all proposals for the budget
//
class CBudgetManager
{
private:

86
    //hold txes until they mature enough to use
87
    map<uint256, uint256> mapCollateralTxids;
88

89
public:
90
91
92
    // critical section to protect the inner data structures
    mutable CCriticalSection cs;
    
93
94
    // keep track of the scanning errors I've seen
    map<uint256, CBudgetProposal> mapProposals;
95
    map<uint256, CFinalizedBudget> mapFinalizedBudgets;
96

Alastair Clark's avatar
Alastair Clark committed
97
98
99
    std::map<uint256, CBudgetProposalBroadcast> mapSeenMasternodeBudgetProposals;
    std::map<uint256, CBudgetVote> mapSeenMasternodeBudgetVotes;
    std::map<uint256, CBudgetVote> mapOrphanMasternodeBudgetVotes;
100
101
102
103
    std::map<uint256, CFinalizedBudgetBroadcast> mapSeenFinalizedBudgets;
    std::map<uint256, CFinalizedBudgetVote> mapSeenFinalizedBudgetVotes;
    std::map<uint256, CFinalizedBudgetVote> mapOrphanFinalizedBudgetVotes;

104
105
    CBudgetManager() {
        mapProposals.clear();
106
        mapFinalizedBudgets.clear();
107
108
    }

109
    void ClearSeen() {
Alastair Clark's avatar
Alastair Clark committed
110
111
        mapSeenMasternodeBudgetProposals.clear();
        mapSeenMasternodeBudgetVotes.clear();
112
113
114
115
        mapSeenFinalizedBudgets.clear();
        mapSeenFinalizedBudgetVotes.clear();
    }

116
117
118
    void ResetSync();
    void MarkSynced();
    void Sync(CNode* node, uint256 nProp, bool fPartial=false);
119
120

    void ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
Evan Duffield's avatar
draft    
Evan Duffield committed
121
    void NewBlock();
122
123
124
    CBudgetProposal *FindProposal(const std::string &strProposalName);
    CBudgetProposal *FindProposal(uint256 nHash);
    CFinalizedBudget *FindFinalizedBudget(uint256 nHash);
125

UdjinM6's avatar
UdjinM6 committed
126
    CAmount GetTotalBudget(int nHeight);
127
    std::vector<CBudgetProposal*> GetBudget();
128
    std::vector<CBudgetProposal*> GetAllProposals();
129
    std::vector<CFinalizedBudget*> GetFinalizedBudgets();
130
    bool IsBudgetPaymentBlock(int nBlockHeight);
Volodymyr Shamray's avatar
Volodymyr Shamray committed
131
    bool AddProposal(const CBudgetProposal& budgetProposal, bool checkCollateral = true);
132
    bool AddFinalizedBudget(CFinalizedBudget& finalizedBudget, bool checkCollateral = true);
133
    void SubmitFinalBudget();
134

135
    bool UpdateProposal(const CBudgetVote& vote, CNode* pfrom, std::string& strError);
Volodymyr Shamray's avatar
Volodymyr Shamray committed
136
    bool SubmitProposalVote(const CBudgetVote& vote, std::string& strError);
137
    bool UpdateFinalizedBudget(CFinalizedBudgetVote& vote, CNode* pfrom, std::string& strError);
138
    bool IsTransactionValid(const CTransaction& txNew, int nBlockHeight);
UdjinM6's avatar
UdjinM6 committed
139
140
    std::string GetRequiredPaymentsString(int nBlockHeight);
    void FillBlockPayee(CMutableTransaction& txNew, CAmount nFees);
141

142
    void CheckOrphanVotes();
143
    void Clear(){
144
145
        LOCK(cs);

146
147
148
        LogPrintf("Budget object cleared\n");
        mapProposals.clear();
        mapFinalizedBudgets.clear();
Alastair Clark's avatar
Alastair Clark committed
149
150
        mapSeenMasternodeBudgetProposals.clear();
        mapSeenMasternodeBudgetVotes.clear();
151
152
        mapSeenFinalizedBudgets.clear();
        mapSeenFinalizedBudgetVotes.clear();
Alastair Clark's avatar
Alastair Clark committed
153
        mapOrphanMasternodeBudgetVotes.clear();
154
        mapOrphanFinalizedBudgetVotes.clear();
155
    }
156
    void CheckAndRemove();
157
    std::string ToString() const;
158
159
160
161
162
163


    ADD_SERIALIZE_METHODS;

    template <typename Stream, typename Operation>
    inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
Alastair Clark's avatar
Alastair Clark committed
164
165
        READWRITE(mapSeenMasternodeBudgetProposals);
        READWRITE(mapSeenMasternodeBudgetVotes);
Evan Duffield's avatar
Evan Duffield committed
166
167
        READWRITE(mapSeenFinalizedBudgets);
        READWRITE(mapSeenFinalizedBudgetVotes);
Alastair Clark's avatar
Alastair Clark committed
168
        READWRITE(mapOrphanMasternodeBudgetVotes);
169
        READWRITE(mapOrphanFinalizedBudgetVotes);
170

171
        READWRITE(mapProposals);
172
173
174
175
        READWRITE(mapFinalizedBudgets);
    }
};

Evan Duffield's avatar
Evan Duffield committed
176
177
178
179
180
181

class CTxBudgetPayment
{
public:
    uint256 nProposalHash;
    CScript payee;
UdjinM6's avatar
UdjinM6 committed
182
    CAmount nAmount;
Evan Duffield's avatar
Evan Duffield committed
183

Volodymyr Shamray's avatar
Volodymyr Shamray committed
184
185
186
187
188
189
190
191
192
193
    CTxBudgetPayment()
        : nAmount(0)
    {
    }

    CTxBudgetPayment(uint256 nProposalHash, CScript payee, CAmount nAmount)
        : nProposalHash(nProposalHash)
        , payee(payee)
        , nAmount(nAmount)
    {
Evan Duffield's avatar
Evan Duffield committed
194
195
196
197
198
199
200
    }

    ADD_SERIALIZE_METHODS;

    //for saving to the serialized db
    template <typename Stream, typename Operation>
    inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
Alastair Clark's avatar
Alastair Clark committed
201
        READWRITE(*(CScriptBase*)(&payee));
Evan Duffield's avatar
Evan Duffield committed
202
203
204
205
206
        READWRITE(nAmount);
        READWRITE(nProposalHash);
    }
};

207
208
209
210
211
212
213
214
215
//
// Finalized Budget : Contains the suggested proposals to pay on a given block
//

class CFinalizedBudget
{
private:
    // critical section to protect the inner data structures
    mutable CCriticalSection cs;
Alastair Clark's avatar
Alastair Clark committed
216
    bool fAutoChecked; //If it matches what we see, we'll auto vote for it (masternode only)
217
    boost::optional<int> voteSubmittedTime;
218

Volodymyr Shamray's avatar
Volodymyr Shamray committed
219
220
protected:
    std::vector<CTxBudgetPayment> vecBudgetPayments;
221
222
223
    std::string strBudgetName;
    int nBlockStart;
    map<uint256, CFinalizedBudgetVote> mapVotes;
Evan Duffield's avatar
Evan Duffield committed
224
    uint256 nFeeTXHash;
Volodymyr Shamray's avatar
Volodymyr Shamray committed
225

226
    static bool ComparePayments(const CTxBudgetPayment& a, const CTxBudgetPayment& b)
227
228
229
230
231
232
233
234
235
    {
        if (a.nAmount != b.nAmount)
            return a.nAmount > b.nAmount;
        else if (a.nProposalHash != b.nProposalHash)
            return a.nProposalHash < b.nProposalHash;
        else if (a.payee != b.payee)
            return a.payee < b.payee;
    }

Volodymyr Shamray's avatar
Volodymyr Shamray committed
236
237
public:
    bool fValid;
238
    int64_t nTime;
239

240
    CFinalizedBudget();
241
    CFinalizedBudget(const CFinalizedBudget& other);
242
    CFinalizedBudget(std::string strBudgetNameIn, int nBlockStartIn, std::vector<CTxBudgetPayment> vecBudgetPaymentsIn, uint256 nFeeTXHashIn);
243

244
    void CleanAndRemove(bool fSignatureCheck);
245
    bool AddOrUpdateVote(const CFinalizedBudgetVote& vote, std::string& strError);
246

247
248
    bool IsValid(std::string& strError, bool fCheckCollateral=true) const;
    bool IsValid(bool fCheckCollateral=true) const;
Volodymyr Shamray's avatar
Volodymyr Shamray committed
249

250
    bool IsVoteSubmitted() const { return voteSubmittedTime.is_initialized(); }
251
    void ResetAutoChecked();
252

253
254
255
    std::string GetName() const { return strBudgetName; }
    uint256 GetFeeTxHash() const { return nFeeTXHash; }
    const std::map<uint256, CFinalizedBudgetVote>& GetVotes() const { return mapVotes; }
Volodymyr Shamray's avatar
Volodymyr Shamray committed
256
    std::string GetProposals() const;
257
    int GetBlockStart() const {return nBlockStart;}
258
    int GetBlockEnd() const {return nBlockStart;} // Paid in single block
259
    int GetVoteCount() const {return (int)mapVotes.size();}
260
    const std::vector<CTxBudgetPayment>& GetBudgetPayments() const;
261
    bool IsTransactionValid(const CTransaction& txNew, int nBlockHeight);
Evan Duffield's avatar
Evan Duffield committed
262

263
    //check to see if we should vote on this
Volodymyr Shamray's avatar
Volodymyr Shamray committed
264
265
    bool AutoCheck();
    bool IsAutoChecked() const { return fAutoChecked; }
infernoman's avatar
infernoman committed
266
    //total crown paid out by this budget
267
    CAmount GetTotalPayout() const;
Alastair Clark's avatar
Alastair Clark committed
268
    //vote on this finalized budget as a masternode
269
270
    void SubmitVote();

Volodymyr Shamray's avatar
Volodymyr Shamray committed
271
272
273
274
    void MarkSynced();
    int Sync(CNode* pfrom, bool fPartial);
    void ResetSync();

Evan Duffield's avatar
Evan Duffield committed
275
    //checks the hashes to make sure we know about them
276
    std::string GetStatus() const;
277

278
    uint256 GetHash() const{
279
280
        CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
        ss << nBlockStart;
UdjinM6's avatar
UdjinM6 committed
281
        ss << vecBudgetPayments;
282

283
        uint256 h1 = ss.GetHash();
284
285
286
287
288
289
290
291
292
        return h1;
    }

    ADD_SERIALIZE_METHODS;

    //for saving to the serialized db
    template <typename Stream, typename Operation>
    inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
        READWRITE(LIMITED_STRING(strBudgetName, 20));
Evan Duffield's avatar
Evan Duffield committed
293
        READWRITE(nFeeTXHash);
294
        READWRITE(nTime);
295
        READWRITE(nBlockStart);
UdjinM6's avatar
UdjinM6 committed
296
        READWRITE(vecBudgetPayments);
Evan Duffield's avatar
Evan Duffield committed
297
        READWRITE(fAutoChecked);
298
299

        READWRITE(mapVotes);
300
301
302
    }
};

303
304
305
306
307
// FinalizedBudget are cast then sent to peers with this object, which leaves the votes out
class CFinalizedBudgetBroadcast : public CFinalizedBudget
{
private:
    std::vector<unsigned char> vchSig;
308

309
310
public:
    CFinalizedBudgetBroadcast();
UdjinM6's avatar
UdjinM6 committed
311
    CFinalizedBudgetBroadcast(std::string strBudgetNameIn, int nBlockStartIn, std::vector<CTxBudgetPayment> vecBudgetPaymentsIn, uint256 nFeeTXHashIn);
312

313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
    void swap(CFinalizedBudgetBroadcast& first, CFinalizedBudgetBroadcast& second) // nothrow
    {
        // enable ADL (not necessary in our case, but good practice)
        using std::swap;

        // by swapping the members of two classes,
        // the two classes are effectively swapped
        swap(first.strBudgetName, second.strBudgetName);
        swap(first.nBlockStart, second.nBlockStart);
        first.mapVotes.swap(second.mapVotes);
        first.vecBudgetPayments.swap(second.vecBudgetPayments);
        swap(first.nFeeTXHash, second.nFeeTXHash);
        swap(first.nTime, second.nTime);
    }

    CFinalizedBudgetBroadcast& operator=(CFinalizedBudgetBroadcast from)
    {
        swap(*this, from);
        return *this;
    }

334
335
336
337
338
339
340
341
342
343
    void Relay();

    ADD_SERIALIZE_METHODS;

    //for propagating messages
    template <typename Stream, typename Operation>
    inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
        //for syncing with other clients
        READWRITE(LIMITED_STRING(strBudgetName, 20));
        READWRITE(nBlockStart);
UdjinM6's avatar
UdjinM6 committed
344
        READWRITE(vecBudgetPayments);
Evan Duffield's avatar
Evan Duffield committed
345
        READWRITE(nFeeTXHash);
346
    }
347
348
349
};

//
Alastair Clark's avatar
Alastair Clark committed
350
// CFinalizedBudgetVote - Allow a masternode node to vote and broadcast throughout the network
351
352
353
354
355
//

class CFinalizedBudgetVote
{
public:
356
    bool fValid; //if the vote is currently valid / counted
357
    bool fSynced; //if we've sent this to our peers
358
359
360
361
362
363
364
365
    CTxIn vin;
    uint256 nBudgetHash;
    int64_t nTime;
    std::vector<unsigned char> vchSig;

    CFinalizedBudgetVote();
    CFinalizedBudgetVote(CTxIn vinIn, uint256 nBudgetHashIn);

Alastair Clark's avatar
Alastair Clark committed
366
    bool Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode);
367
    bool SignatureValid(bool fSignatureCheck);
368
369
    void Relay();

370
    uint256 GetHash() const{
371
372
373
374
375
        CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
        ss << vin;
        ss << nBudgetHash;
        ss << nTime;
        return ss.GetHash();
376
377
378
379
380
381
382
383
384
    }

    ADD_SERIALIZE_METHODS;

    template <typename Stream, typename Operation>
    inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
        READWRITE(vin);
        READWRITE(nBudgetHash);
        READWRITE(nTime);
Alastair Clark's avatar
Alastair Clark committed
385
        READWRITE(vchSig);
386
    }
Evan Duffield's avatar
Evan Duffield committed
387

388
};
389
390

//
Alastair Clark's avatar
Alastair Clark committed
391
// Budget Proposal : Contains the masternode votes for each budget
392
393
394
395
396
397
//

class CBudgetProposal
{
private:
    // critical section to protect the inner data structures
398
    mutable CCriticalSection cs;
UdjinM6's avatar
UdjinM6 committed
399
    CAmount nAlloted;
400
401

public:
402
    bool fValid;
403
    std::string strProposalName;
404
405

    /*
406
407
408
        json object with name, short-description, long-description, pdf-url and any other info
        This allows the proposal website to stay 100% decentralized
    */
409
    std::string strURL;
410
411
    int nBlockStart;
    int nBlockEnd;
UdjinM6's avatar
UdjinM6 committed
412
    CAmount nAmount;
413
    CScript address;
Volodymyr Shamray's avatar
Volodymyr Shamray committed
414
    mutable int64_t nTime;
Evan Duffield's avatar
Evan Duffield committed
415
    uint256 nFeeTXHash;
416
417
418
419

    map<uint256, CBudgetVote> mapVotes;
    //cache object

420
    CBudgetProposal();
421
    CBudgetProposal(const CBudgetProposal& other);
422
    CBudgetProposal(std::string strProposalNameIn, std::string strURLIn, int nBlockStartIn, int nBlockEndIn, CScript addressIn, CAmount nAmountIn, uint256 nFeeTXHashIn);
423
424

    void Calculate();
Volodymyr Shamray's avatar
Volodymyr Shamray committed
425
    bool AddOrUpdateVote(const CBudgetVote& vote, std::string& strError);
426
427
428
    bool HasMinimumRequiredSupport();
    std::pair<std::string, std::string> GetVotes();

Volodymyr Shamray's avatar
Volodymyr Shamray committed
429
    bool IsValid(std::string& strError, bool fCheckCollateral=true) const;
430

431
    int IsEstablished() const
432
433
434
    {
        //Proposals must be at least a day old to make it into a budget
        if(Params().NetworkID() == CBaseChainParams::MAIN)
Volodymyr Shamray's avatar
Volodymyr Shamray committed
435
            return nTime < GetTime() - 24 * 60 * 60;
436
        else
Volodymyr Shamray's avatar
Volodymyr Shamray committed
437
            return nTime < GetTime() - 15 * 60; // 15 minutes for testing purposes
Evan Duffield's avatar
Evan Duffield committed
438
439
    }

440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
    std::string GetName() const {return strProposalName; }
    std::string GetURL() const {return strURL; }
    int GetBlockStart() const {return nBlockStart;}
    int GetBlockEnd() const {return nBlockEnd;}
    CScript GetPayee() const {return address;}
    int GetTotalPaymentCount() const;
    int GetRemainingPaymentCount() const;
    int GetBlockStartCycle() const;
    int GetBlockCurrentCycle() const;
    int GetBlockEndCycle() const;
    double GetRatio() const;
    int GetYeas() const;
    int GetNays() const;
    int GetAbstains() const;
    CAmount GetAmount() const {return nAmount;}
UdjinM6's avatar
UdjinM6 committed
455
    void SetAllotted(CAmount nAllotedIn) {nAlloted = nAllotedIn;}
456
    CAmount GetAllotted() const {return nAlloted;}
457

458
    void CleanAndRemove(bool fSignatureCheck);
459

Volodymyr Shamray's avatar
Volodymyr Shamray committed
460
    uint256 GetHash() const {
461
462
463
464
465
466
        CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
        ss << strProposalName;
        ss << strURL;
        ss << nBlockStart;
        ss << nBlockEnd;
        ss << nAmount;
Alastair Clark's avatar
Alastair Clark committed
467
        ss << *(CScriptBase*)(&address);
468
        uint256 h1 = ss.GetHash();
469

470
471
472
        return h1;
    }

473
474
475
476
    ADD_SERIALIZE_METHODS;

    template <typename Stream, typename Operation>
    inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
477
478
479
        //for syncing with other clients
        READWRITE(LIMITED_STRING(strProposalName, 20));
        READWRITE(LIMITED_STRING(strURL, 64));
Evan Duffield's avatar
Evan Duffield committed
480
        READWRITE(nTime);
481
482
483
        READWRITE(nBlockStart);
        READWRITE(nBlockEnd);
        READWRITE(nAmount);
Alastair Clark's avatar
Alastair Clark committed
484
        READWRITE(*(CScriptBase*)(&address));
Evan Duffield's avatar
Evan Duffield committed
485
        READWRITE(nTime);
Evan Duffield's avatar
Evan Duffield committed
486
        READWRITE(nFeeTXHash);
487
488

        //for saving to the serialized db
489
490
491
492
        READWRITE(mapVotes);
    }
};

493
494
495
496
// Proposals are cast then sent to peers with this object, which leaves the votes out
class CBudgetProposalBroadcast : public CBudgetProposal
{
public:
UdjinM6's avatar
UdjinM6 committed
497
498
499
    CBudgetProposalBroadcast() : CBudgetProposal(){}
    CBudgetProposalBroadcast(const CBudgetProposal& other) : CBudgetProposal(other){}
    CBudgetProposalBroadcast(const CBudgetProposalBroadcast& other) : CBudgetProposal(other){}
500
    CBudgetProposalBroadcast(std::string strProposalNameIn, std::string strURLIn, int nPaymentCount, CScript addressIn, CAmount nAmountIn, int nBlockStartIn, uint256 nFeeTXHashIn);
501

502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
    void swap(CBudgetProposalBroadcast& first, CBudgetProposalBroadcast& second) // nothrow
    {
        // enable ADL (not necessary in our case, but good practice)
        using std::swap;

        // by swapping the members of two classes,
        // the two classes are effectively swapped
        swap(first.strProposalName, second.strProposalName);
        swap(first.nBlockStart, second.nBlockStart);
        swap(first.strURL, second.strURL);
        swap(first.nBlockEnd, second.nBlockEnd);
        swap(first.nAmount, second.nAmount);
        swap(first.address, second.address);
        swap(first.nTime, second.nTime);
        swap(first.nFeeTXHash, second.nFeeTXHash);        
        first.mapVotes.swap(second.mapVotes);
    }

    CBudgetProposalBroadcast& operator=(CBudgetProposalBroadcast from)
    {
        swap(*this, from);
        return *this;
    }

526
527
528
529
530
531
532
533
534
535
    void Relay();

    ADD_SERIALIZE_METHODS;

    template <typename Stream, typename Operation>
    inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
        //for syncing with other clients

        READWRITE(LIMITED_STRING(strProposalName, 20));
        READWRITE(LIMITED_STRING(strURL, 64));
Evan Duffield's avatar
Evan Duffield committed
536
        READWRITE(nTime);
537
538
539
        READWRITE(nBlockStart);
        READWRITE(nBlockEnd);
        READWRITE(nAmount);
Alastair Clark's avatar
Alastair Clark committed
540
        READWRITE(*(CScriptBase*)(&address));
Evan Duffield's avatar
Evan Duffield committed
541
        READWRITE(nFeeTXHash);
542
    }
543
};
544
545

//
Alastair Clark's avatar
Alastair Clark committed
546
// CBudgetVote - Allow a masternode node to vote and broadcast throughout the network
547
548
549
550
551
//

class CBudgetVote
{
public:
552
    bool fValid; //if the vote is currently valid / counted
553
    bool fSynced; //if we've sent this to our peers
554
    CTxIn vin;
555
    uint256 nProposalHash;
556
557
558
559
560
    int nVote;
    int64_t nTime;
    std::vector<unsigned char> vchSig;

    CBudgetVote();
561
    CBudgetVote(CTxIn vin, uint256 nProposalHash, int nVoteIn);
562

Alastair Clark's avatar
Alastair Clark committed
563
    bool Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode);
564
    bool SignatureValid(bool fSignatureCheck) const;
565
566
    void Relay();

567
    std::string GetVoteString() const {
568
569
570
571
572
573
        std::string ret = "ABSTAIN";
        if(nVote == VOTE_YES) ret = "YES";
        if(nVote == VOTE_NO) ret = "NO";
        return ret;
    }

Volodymyr Shamray's avatar
Volodymyr Shamray committed
574
    uint256 GetHash() const {
575
576
577
578
579
580
        CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
        ss << vin;
        ss << nProposalHash;
        ss << nVote;
        ss << nTime;
        return ss.GetHash();
581
582
583
584
585
586
587
    }

    ADD_SERIALIZE_METHODS;

    template <typename Stream, typename Operation>
    inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
        READWRITE(vin);
588
        READWRITE(nProposalHash);
589
590
        READWRITE(nVote);
        READWRITE(nTime);
Alastair Clark's avatar
Alastair Clark committed
591
        READWRITE(vchSig);
592
593
    }

594

595
596
597

};

UdjinM6's avatar
UdjinM6 committed
598
#endif