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_H
7 : #define PIVX_MASTERNODE_H
8 :
9 : #include "key_io.h"
10 : #include "key.h"
11 : #include "messagesigner.h"
12 : #include "net.h"
13 : #include "primitives/transaction.h"
14 : #include "serialize.h"
15 : #include "sync.h"
16 : #include "timedata.h"
17 : #include "util/system.h"
18 :
19 : /* Depth of the block pinged by masternodes */
20 : static const unsigned int MNPING_DEPTH = 12;
21 :
22 : class CMasternode;
23 : class CMasternodeBroadcast;
24 : class CMasternodePing;
25 :
26 : typedef std::shared_ptr<CMasternode> MasternodeRef;
27 :
28 : class CDeterministicMN;
29 : typedef std::shared_ptr<const CDeterministicMN> CDeterministicMNCPtr;
30 :
31 : int MasternodeMinPingSeconds();
32 : int MasternodeBroadcastSeconds();
33 : int MasternodePingSeconds();
34 : int MasternodeExpirationSeconds();
35 : int MasternodeRemovalSeconds();
36 :
37 : //
38 : // The Masternode Ping Class : Contains a different serialize method for sending pings from masternodes throughout the network
39 : //
40 :
41 16953 : class CMasternodePing : public CSignedMessage
42 : {
43 : public:
44 : CTxIn vin;
45 : uint256 blockHash;
46 : int64_t sigTime; //mnb message times
47 :
48 : CMasternodePing();
49 : CMasternodePing(const CTxIn& newVin, const uint256& nBlockHash, uint64_t _sigTime);
50 :
51 55153 : SERIALIZE_METHODS(CMasternodePing, obj) { READWRITE(obj.vin, obj.blockHash, obj.sigTime, obj.vchSig, obj.nMessVersion); }
52 :
53 : uint256 GetHash() const;
54 :
55 : // override CSignedMessage functions
56 2737 : uint256 GetSignatureHash() const override { return GetHash(); }
57 : std::string GetStrMessage() const override;
58 686 : const CTxIn GetVin() const { return vin; };
59 730269 : bool IsNull() const { return blockHash.IsNull() || vin.prevout.IsNull(); }
60 :
61 : bool CheckAndUpdate(int& nDos, bool fRequireAvailable = true, bool fCheckSigTimeOnly = false);
62 : void Relay();
63 :
64 : CMasternodePing& operator=(const CMasternodePing& other) = default;
65 :
66 : friend bool operator==(const CMasternodePing& a, const CMasternodePing& b)
67 : {
68 : return a.vin == b.vin && a.blockHash == b.blockHash;
69 : }
70 : friend bool operator!=(const CMasternodePing& a, const CMasternodePing& b)
71 : {
72 : return !(a == b);
73 : }
74 : };
75 :
76 : //
77 : // The Masternode Class. It contains the input of the 10000 PIV, signature to prove
78 : // it's the one who own that ip address and code for calculating the payment election.
79 : //
80 : class CMasternode : public CSignedMessage
81 : {
82 : private:
83 : // critical section to protect the inner data structures
84 : mutable RecursiveMutex cs;
85 : bool fCollateralSpent{false};
86 :
87 : public:
88 : enum state {
89 : MASTERNODE_PRE_ENABLED,
90 : MASTERNODE_ENABLED,
91 : MASTERNODE_EXPIRED,
92 : MASTERNODE_REMOVE,
93 : MASTERNODE_VIN_SPENT,
94 : };
95 :
96 : CTxIn vin;
97 : CService addr;
98 : CPubKey pubKeyCollateralAddress;
99 : CPubKey pubKeyMasternode;
100 : int64_t sigTime; //mnb message time
101 : int protocolVersion;
102 : int nScanningErrorCount;
103 : int nLastScanningErrorBlockHeight;
104 : CMasternodePing lastPing;
105 :
106 : explicit CMasternode();
107 : CMasternode(const CMasternode& other);
108 :
109 : // Initialize from DMN. Used by the compatibility code.
110 : CMasternode(const CDeterministicMNCPtr& dmn, int64_t registeredTime, const uint256& registeredHash);
111 :
112 : // override CSignedMessage functions
113 : uint256 GetSignatureHash() const override;
114 : std::string GetStrMessage() const override;
115 : const CTxIn GetVin() const { return vin; };
116 : CPubKey GetPubKey() const { return pubKeyMasternode; }
117 :
118 9237 : void SetLastPing(const CMasternodePing& _lastPing) { WITH_LOCK(cs, lastPing = _lastPing;); }
119 :
120 14 : CMasternode& operator=(const CMasternode& other)
121 : {
122 14 : nMessVersion = other.nMessVersion;
123 14 : vchSig = other.vchSig;
124 14 : vin = other.vin;
125 14 : addr = other.addr;
126 14 : pubKeyCollateralAddress = other.pubKeyCollateralAddress;
127 14 : pubKeyMasternode = other.pubKeyMasternode;
128 14 : sigTime = other.sigTime;
129 14 : lastPing = other.lastPing;
130 14 : protocolVersion = other.protocolVersion;
131 14 : nScanningErrorCount = other.nScanningErrorCount;
132 14 : nLastScanningErrorBlockHeight = other.nLastScanningErrorBlockHeight;
133 14 : return *this;
134 : }
135 :
136 : friend bool operator==(const CMasternode& a, const CMasternode& b)
137 : {
138 : return a.vin == b.vin;
139 : }
140 : friend bool operator!=(const CMasternode& a, const CMasternode& b)
141 : {
142 : return !(a.vin == b.vin);
143 : }
144 :
145 : arith_uint256 CalculateScore(const uint256& hash) const;
146 :
147 68 : SERIALIZE_METHODS(CMasternode, obj)
148 : {
149 34 : LOCK(obj.cs);
150 34 : READWRITE(obj.vin, obj.addr, obj.pubKeyCollateralAddress);
151 34 : READWRITE(obj.pubKeyMasternode, obj.vchSig, obj.sigTime, obj.protocolVersion);
152 34 : READWRITE(obj.lastPing, obj.nScanningErrorCount, obj.nLastScanningErrorBlockHeight);
153 :
154 34 : if (obj.protocolVersion == MIN_BIP155_PROTOCOL_VERSION) {
155 0 : bool dummyIsBIP155Addr = false;
156 0 : READWRITE(dummyIsBIP155Addr);
157 : }
158 34 : }
159 :
160 : template <typename Stream>
161 0 : CMasternode(deserialize_type, Stream& s) {
162 0 : Unserialize(s);
163 0 : }
164 :
165 : bool UpdateFromNewBroadcast(CMasternodeBroadcast& mnb);
166 :
167 : CMasternode::state GetActiveState() const;
168 :
169 10 : bool IsBroadcastedWithin(int seconds)
170 : {
171 10 : return (GetAdjustedTime() - sigTime) < seconds;
172 : }
173 :
174 243275 : bool IsPingedWithin(int seconds, int64_t now = -1) const
175 : {
176 243275 : now == -1 ? now = GetAdjustedTime() : now;
177 243275 : return lastPing.IsNull() ? false : now - lastPing.sigTime < seconds;
178 : }
179 :
180 20 : void SetSpent()
181 : {
182 20 : LOCK(cs);
183 20 : fCollateralSpent = true;
184 20 : }
185 :
186 : void Disable()
187 : {
188 : LOCK(cs);
189 : sigTime = 0;
190 : lastPing = CMasternodePing();
191 : }
192 :
193 119090 : bool IsEnabled() const
194 : {
195 119090 : return GetActiveState() == MASTERNODE_ENABLED;
196 : }
197 :
198 : bool IsPreEnabled() const
199 : {
200 : return GetActiveState() == MASTERNODE_PRE_ENABLED;
201 : }
202 :
203 2120 : bool IsAvailableState() const
204 : {
205 2237 : state s = GetActiveState();
206 2237 : return s == MASTERNODE_ENABLED || s == MASTERNODE_PRE_ENABLED;
207 : }
208 :
209 473 : std::string Status() const
210 : {
211 473 : auto activeState = GetActiveState();
212 473 : if (activeState == CMasternode::MASTERNODE_PRE_ENABLED) return "PRE_ENABLED";
213 198 : if (activeState == CMasternode::MASTERNODE_ENABLED) return "ENABLED";
214 18 : if (activeState == CMasternode::MASTERNODE_EXPIRED) return "EXPIRED";
215 0 : if (activeState == CMasternode::MASTERNODE_VIN_SPENT) return "VIN_SPENT";
216 0 : if (activeState == CMasternode::MASTERNODE_REMOVE) return "REMOVE";
217 0 : return strprintf("INVALID_%d", activeState);
218 : }
219 :
220 : bool IsValidNetAddr() const;
221 :
222 : /*
223 : * This is used only by the compatibility code for DMN, which don't share the public key (but the keyid).
224 : * Used by the payment-logic to include the necessary information in a temporary MasternodeRef object
225 : * (which is not indexed in the maps of the legacy manager).
226 : * A non-empty mnPayeeScript identifies this object as a "deterministic" masternode.
227 : * Note: this is the single payout for the masternode (if the dmn is configured to pay a portion of the reward
228 : * to the operator, this is done only after the disabling of the legacy system).
229 : */
230 : CScript mnPayeeScript{};
231 2567 : CScript GetPayeeScript() const {
232 3976 : return mnPayeeScript.empty() ? GetScriptForDestination(pubKeyCollateralAddress.GetID())
233 5385 : : mnPayeeScript;
234 : }
235 : };
236 :
237 :
238 : //
239 : // The Masternode Broadcast Class : Contains a different serialize method for sending masternodes through the network
240 : //
241 :
242 2877 : class CMasternodeBroadcast : public CMasternode
243 : {
244 : public:
245 : CMasternodeBroadcast();
246 : CMasternodeBroadcast(CService newAddr, CTxIn newVin, CPubKey newPubkey, CPubKey newPubkey2, int protocolVersionIn, const CMasternodePing& _lastPing);
247 : explicit CMasternodeBroadcast(const CMasternode& mn);
248 :
249 : bool CheckAndUpdate(int& nDoS);
250 :
251 : uint256 GetHash() const;
252 :
253 : void Relay();
254 :
255 : // special sign/verify
256 : bool Sign(const CKey& key, const CPubKey& pubKey);
257 : bool CheckSignature() const;
258 :
259 284 : SERIALIZE_METHODS(CMasternodeBroadcast, obj)
260 : {
261 176 : READWRITE(obj.vin);
262 176 : READWRITE(obj.addr);
263 176 : READWRITE(obj.pubKeyCollateralAddress);
264 176 : READWRITE(obj.pubKeyMasternode);
265 176 : READWRITE(obj.vchSig);
266 176 : READWRITE(obj.sigTime);
267 176 : READWRITE(obj.protocolVersion);
268 176 : READWRITE(obj.lastPing);
269 176 : READWRITE(obj.nMessVersion);
270 176 : }
271 :
272 : /// Create Masternode broadcast, needs to be relayed manually after that
273 : static bool Create(const CTxIn& vin, const CService& service, const CKey& keyCollateralAddressNew, const CPubKey& pubKeyCollateralAddressNew, const CKey& keyMasternodeNew, const CPubKey& pubKeyMasternodeNew, std::string& strErrorRet, CMasternodeBroadcast& mnbRet);
274 : static bool Create(const std::string& strService, const std::string& strKey, const std::string& strTxHash, const std::string& strOutputIndex, std::string& strErrorRet, CMasternodeBroadcast& mnbRet, bool fOffline, int chainHeight);
275 : static bool CheckDefaultPort(CService service, std::string& strErrorRet, const std::string& strContext);
276 : };
277 :
278 : // Temporary function used for payment compatibility code.
279 : // Returns a shared pointer to a masternode object initialized from a DMN.
280 : MasternodeRef MakeMasternodeRefForDMN(const CDeterministicMNCPtr& dmn);
281 :
282 : #endif // PIVX_MASTERNODE_H
|