Line data Source code
1 : // Copyright (c) 2014-2015 The Dash developers
2 : // Copyright (c) 2015-2022 The PIVX Core developers
3 : // Distributed under the MIT/X11 software license, see the accompanying
4 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 :
6 : #ifndef PIVX_MASTERNODE_PAYMENTS_H
7 : #define PIVX_MASTERNODE_PAYMENTS_H
8 :
9 : #include "key.h"
10 : #include "masternode.h"
11 : #include "validationinterface.h"
12 :
13 :
14 : extern RecursiveMutex cs_vecPayments;
15 : extern RecursiveMutex cs_mapMasternodeBlocks;
16 : extern RecursiveMutex cs_mapMasternodePayeeVotes;
17 :
18 : class CMasternodePayments;
19 : class CMasternodePaymentWinner;
20 : class CMasternodeBlockPayees;
21 : class CValidationState;
22 :
23 : extern CMasternodePayments masternodePayments;
24 :
25 : #define MNPAYMENTS_SIGNATURES_REQUIRED 6
26 : #define MNPAYMENTS_SIGNATURES_TOTAL 10
27 :
28 : bool IsBlockPayeeValid(const CBlock& block, const CBlockIndex* pindexPrev);
29 : std::string GetRequiredPaymentsString(int nBlockHeight);
30 : bool IsBlockValueValid(int nHeight, CAmount& nExpectedValue, CAmount nMinted, CAmount& nBudgetAmt);
31 : void FillBlockPayee(CMutableTransaction& txCoinbase, CMutableTransaction& txCoinstake, const CBlockIndex* pindexPrev, bool fProofOfStake);
32 :
33 : /**
34 : * Check coinbase output value for blocks after v6.0 enforcement.
35 : * It must pay the masternode for regular blocks and a proposal during superblocks.
36 : */
37 : bool IsCoinbaseValueValid(const CTransactionRef& tx, CAmount nBudgetAmt, CValidationState& _state);
38 :
39 : void DumpMasternodePayments();
40 :
41 : /** Save Masternode Payment Data (mnpayments.dat)
42 : */
43 : class CMasternodePaymentDB
44 : {
45 : private:
46 : fs::path pathDB;
47 : std::string strMagicMessage;
48 :
49 : public:
50 : enum ReadResult {
51 : Ok,
52 : FileError,
53 : HashReadError,
54 : IncorrectHash,
55 : IncorrectMagicMessage,
56 : IncorrectMagicNumber,
57 : IncorrectFormat
58 : };
59 :
60 : CMasternodePaymentDB();
61 : bool Write(const CMasternodePayments& objToSave);
62 : ReadResult Read(CMasternodePayments& objToLoad);
63 : };
64 :
65 2751 : class CMasternodePayee
66 : {
67 : public:
68 : CScript scriptPubKey;
69 : int nVotes;
70 :
71 582 : CMasternodePayee()
72 582 : {
73 582 : scriptPubKey = CScript();
74 582 : nVotes = 0;
75 : }
76 :
77 717 : CMasternodePayee(CScript payee, int nVotesIn)
78 717 : {
79 717 : scriptPubKey = payee;
80 717 : nVotes = nVotesIn;
81 : }
82 :
83 588 : SERIALIZE_METHODS(CMasternodePayee, obj) { READWRITE(obj.scriptPubKey, obj.nVotes); }
84 : };
85 :
86 : // Keep track of votes for payees from masternodes
87 1422 : class CMasternodeBlockPayees
88 : {
89 : public:
90 : int nBlockHeight;
91 : std::vector<CMasternodePayee> vecPayments;
92 :
93 710 : CMasternodeBlockPayees()
94 710 : {
95 : nBlockHeight = 0;
96 710 : vecPayments.clear();
97 : }
98 710 : explicit CMasternodeBlockPayees(int nBlockHeightIn)
99 710 : {
100 710 : nBlockHeight = nBlockHeightIn;
101 710 : vecPayments.clear();
102 : }
103 :
104 1985 : void AddPayee(const CScript& payeeIn, int nIncrement)
105 : {
106 2702 : LOCK(cs_vecPayments);
107 :
108 1995 : for (CMasternodePayee& payee : vecPayments) {
109 1278 : if (payee.scriptPubKey == payeeIn) {
110 1268 : payee.nVotes += nIncrement;
111 1268 : return;
112 : }
113 : }
114 :
115 1434 : CMasternodePayee c(payeeIn, nIncrement);
116 717 : vecPayments.push_back(c);
117 : }
118 :
119 4892 : bool GetPayee(CScript& payee) const
120 : {
121 4892 : LOCK(cs_vecPayments);
122 :
123 4892 : int nVotes = -1;
124 9825 : for (const CMasternodePayee& p : vecPayments) {
125 4933 : if (p.nVotes > nVotes) {
126 4892 : payee = p.scriptPubKey;
127 4892 : nVotes = p.nVotes;
128 : }
129 : }
130 :
131 4892 : return (nVotes > -1);
132 : }
133 :
134 232 : bool HasPayeeWithVotes(const CScript& payee, int nVotesReq)
135 : {
136 232 : LOCK(cs_vecPayments);
137 :
138 405 : for (CMasternodePayee& p : vecPayments) {
139 235 : if (p.nVotes >= nVotesReq && p.scriptPubKey == payee) return true;
140 : }
141 :
142 170 : return false;
143 : }
144 :
145 : bool IsTransactionValid(const CTransaction& txNew, int nBlockHeight);
146 : std::string GetRequiredPaymentsString();
147 :
148 582 : SERIALIZE_METHODS(CMasternodeBlockPayees, obj) { READWRITE(obj.nBlockHeight, obj.vecPayments); }
149 : };
150 :
151 : // for storing the winning payments
152 : class CMasternodePaymentWinner : public CSignedMessage
153 : {
154 : public:
155 : CTxIn vinMasternode;
156 : int nBlockHeight;
157 : CScript payee;
158 :
159 2917 : CMasternodePaymentWinner() :
160 : CSignedMessage(),
161 : vinMasternode(),
162 : nBlockHeight(0),
163 2917 : payee()
164 2917 : {}
165 :
166 1070 : CMasternodePaymentWinner(const CTxIn& vinIn, int nHeight):
167 : CSignedMessage(),
168 : vinMasternode(vinIn),
169 : nBlockHeight(nHeight),
170 1070 : payee()
171 1070 : {}
172 :
173 : uint256 GetHash() const;
174 :
175 : // override CSignedMessage functions
176 2889 : uint256 GetSignatureHash() const override { return GetHash(); }
177 : std::string GetStrMessage() const override;
178 : CTxIn GetVin() const { return vinMasternode; };
179 :
180 : bool IsValid(CNode* pnode, CValidationState& state, int chainHeight);
181 : void Relay();
182 :
183 1070 : void AddPayee(const CScript& payeeIn)
184 : {
185 1070 : payee = payeeIn;
186 : }
187 :
188 3889 : SERIALIZE_METHODS(CMasternodePaymentWinner, obj) { READWRITE(obj.vinMasternode, obj.nBlockHeight, obj.payee, obj.vchSig, obj.nMessVersion); }
189 :
190 : std::string ToString()
191 : {
192 : std::string ret = "";
193 : ret += vinMasternode.ToString();
194 : ret += ", " + std::to_string(nBlockHeight);
195 : ret += ", " + HexStr(payee);
196 : ret += ", " + std::to_string((int)vchSig.size());
197 : return ret;
198 : }
199 : };
200 :
201 : //
202 : // Masternode Payments Class
203 : // Keeps track of who should get paid for which blocks
204 : //
205 :
206 : class CMasternodePayments : public CValidationInterface
207 : {
208 : private:
209 : int nLastBlockHeight;
210 :
211 : public:
212 : std::map<uint256, CMasternodePaymentWinner> mapMasternodePayeeVotes;
213 : std::map<int, CMasternodeBlockPayees> mapMasternodeBlocks;
214 :
215 : CMasternodePayments()
216 : {
217 : nLastBlockHeight = 0;
218 : }
219 :
220 0 : void Clear()
221 : {
222 0 : LOCK2(cs_mapMasternodeBlocks, cs_mapMasternodePayeeVotes);
223 0 : mapMasternodeBlocks.clear();
224 0 : mapMasternodePayeeVotes.clear();
225 0 : }
226 :
227 : void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override;
228 :
229 : void AddWinningMasternode(CMasternodePaymentWinner& winner);
230 : void ProcessBlock(int nBlockHeight);
231 :
232 : void Sync(CNode* node, int nCountNeeded);
233 : void CleanPaymentList(int mnCount, int nHeight);
234 :
235 : // get the masternode payment outs for block built on top of pindexPrev
236 : bool GetMasternodeTxOuts(const CBlockIndex* pindexPrev, std::vector<CTxOut>& voutMasternodePaymentsRet) const;
237 :
238 : // can be removed after transition to DMN
239 : bool GetLegacyMasternodeTxOut(int nHeight, std::vector<CTxOut>& voutMasternodePaymentsRet) const;
240 : bool GetBlockPayee(int nBlockHeight, CScript& payee) const;
241 :
242 : bool IsTransactionValid(const CTransaction& txNew, const CBlockIndex* pindexPrev);
243 : bool IsScheduled(const CMasternode& mn, int nNotBlockHeight);
244 :
245 : bool ProcessMNWinner(CMasternodePaymentWinner& winner, CNode* pfrom, CValidationState& state);
246 : bool ProcessMessageMasternodePayments(CNode* pfrom, std::string& strCommand, CDataStream& vRecv, CValidationState& state);
247 : std::string GetRequiredPaymentsString(int nBlockHeight);
248 : void FillBlockPayee(CMutableTransaction& txCoinbase, CMutableTransaction& txCoinstake, const CBlockIndex* pindexPrev, bool fProofOfStake) const;
249 : std::string ToString() const;
250 :
251 542 : SERIALIZE_METHODS(CMasternodePayments, obj) { READWRITE(obj.mapMasternodePayeeVotes, obj.mapMasternodeBlocks); }
252 :
253 : private:
254 : // keep track of last voted height for mnw signers
255 : std::map<COutPoint, int> mapMasternodesLastVote; //prevout, nBlockHeight
256 :
257 : bool CanVote(const COutPoint& outMasternode, int nBlockHeight) const;
258 : void RecordWinnerVote(const COutPoint& outMasternode, int nBlockHeight);
259 : };
260 :
261 : #endif // PIVX_MASTERNODE_PAYMENTS_H
|