Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2014 The Bitcoin developers
3 : // Copyright (c) 2015-2021 The PIVX Core developers
4 : // Distributed under the MIT software license, see the accompanying
5 : // file COPYING or https://www.opensource.org/licenses/mit-license.php.
6 :
7 : #ifndef PIVX_PRIMITIVES_TRANSACTION_H
8 : #define PIVX_PRIMITIVES_TRANSACTION_H
9 :
10 : #include "amount.h"
11 : #include "memusage.h"
12 : #include "netaddress.h"
13 : #include "optional.h"
14 : #include "script/script.h"
15 : #include "serialize.h"
16 : #include "uint256.h"
17 :
18 : #include "sapling/sapling_transaction.h"
19 :
20 : #include <atomic>
21 : #include <list>
22 :
23 : class CTransaction;
24 :
25 : enum SigVersion
26 : {
27 : SIGVERSION_BASE = 0,
28 : SIGVERSION_SAPLING = 1,
29 : };
30 :
31 : /** An outpoint - a combination of a transaction hash and an index n into its vout */
32 : class BaseOutPoint
33 : {
34 : public:
35 : uint256 hash;
36 : uint32_t n;
37 : bool isTransparent{true};
38 :
39 12787632 : BaseOutPoint() { SetNull(); }
40 22242544 : BaseOutPoint(const uint256& hashIn, const uint32_t nIn, bool isTransparentIn = true) :
41 22242544 : hash(hashIn), n(nIn), isTransparent(isTransparentIn) { }
42 :
43 61760196 : SERIALIZE_METHODS(BaseOutPoint, obj) { READWRITE(obj.hash, obj.n); }
44 :
45 12749409 : void SetNull() { hash.SetNull(); n = (uint32_t) -1; }
46 41741725 : bool IsNull() const { return (hash.IsNull() && n == (uint32_t) -1); }
47 :
48 474299598 : friend bool operator<(const BaseOutPoint& a, const BaseOutPoint& b)
49 : {
50 474299598 : return (a.hash < b.hash || (a.hash == b.hash && a.n < b.n));
51 : }
52 :
53 23183357 : friend bool operator==(const BaseOutPoint& a, const BaseOutPoint& b)
54 : {
55 23182237 : return (a.hash == b.hash && a.n == b.n);
56 : }
57 :
58 1120 : friend bool operator!=(const BaseOutPoint& a, const BaseOutPoint& b)
59 : {
60 2023 : return !(a == b);
61 : }
62 :
63 : std::string ToString() const;
64 : std::string ToStringShort() const;
65 :
66 : size_t DynamicMemoryUsage() const { return 0; }
67 :
68 : };
69 :
70 : /** An outpoint - a combination of a transaction hash and an index n into its vout */
71 : class COutPoint : public BaseOutPoint
72 : {
73 : public:
74 8280912 : COutPoint() : BaseOutPoint() {};
75 19678945 : COutPoint(const uint256& hashIn, const uint32_t nIn) : BaseOutPoint(hashIn, nIn, true) {};
76 : std::string ToString() const;
77 : };
78 :
79 : /** An outpoint - a combination of a transaction hash and an index n into its sapling
80 : * output description (vShieldedOutput) */
81 : class SaplingOutPoint : public BaseOutPoint
82 : {
83 : public:
84 902 : SaplingOutPoint() : BaseOutPoint() {};
85 5130 : SaplingOutPoint(const uint256& hashIn, const uint32_t nIn) : BaseOutPoint(hashIn, nIn, false) {};
86 : std::string ToString() const;
87 : };
88 :
89 : /** An input of a transaction. It contains the location of the previous
90 : * transaction's output that it claims and a signature that matches the
91 : * output's public key.
92 : */
93 69524990 : class CTxIn
94 : {
95 : public:
96 : COutPoint prevout;
97 : CScript scriptSig;
98 : uint32_t nSequence;
99 :
100 : /* Setting nSequence to this value for every input in a transaction
101 : * disables nLockTime. */
102 : static const uint32_t SEQUENCE_FINAL = 0xffffffff;
103 :
104 9406238 : CTxIn() { nSequence = SEQUENCE_FINAL; }
105 : explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=SEQUENCE_FINAL);
106 : CTxIn(uint256 hashPrevTx, uint32_t nOut, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=SEQUENCE_FINAL);
107 :
108 34316426 : SERIALIZE_METHODS(CTxIn, obj) { READWRITE(obj.prevout, obj.scriptSig, obj.nSequence); }
109 :
110 870 : bool IsFinal() const { return nSequence == SEQUENCE_FINAL; }
111 1702 : bool IsNull() const { return prevout.IsNull() && scriptSig.empty() && IsFinal(); }
112 :
113 : bool IsZerocoinSpend() const;
114 : bool IsZerocoinPublicSpend() const;
115 :
116 : friend bool operator==(const CTxIn& a, const CTxIn& b)
117 : {
118 : return (a.prevout == b.prevout &&
119 : a.scriptSig == b.scriptSig &&
120 : a.nSequence == b.nSequence);
121 : }
122 :
123 : friend bool operator!=(const CTxIn& a, const CTxIn& b)
124 : {
125 : return !(a == b);
126 : }
127 :
128 : std::string ToString() const;
129 :
130 385542 : size_t DynamicMemoryUsage() const { return scriptSig.DynamicMemoryUsage(); }
131 : };
132 :
133 : /** An output of a transaction. It contains the public key that the next input
134 : * must be able to sign with to claim it.
135 : */
136 150132947 : class CTxOut
137 : {
138 : public:
139 : CAmount nValue;
140 : CScript scriptPubKey;
141 : int nRounds;
142 :
143 68391457 : CTxOut()
144 68391457 : {
145 136782906 : SetNull();
146 : }
147 :
148 : CTxOut(const CAmount& nValueIn, CScript scriptPubKeyIn);
149 :
150 66738963 : SERIALIZE_METHODS(CTxOut, obj) { READWRITE(obj.nValue, obj.scriptPubKey); }
151 :
152 72607348 : void SetNull()
153 : {
154 72607348 : nValue = -1;
155 72607348 : scriptPubKey.clear();
156 63382929 : nRounds = -10; // an initial value, should be no way to get this by calculations
157 : }
158 :
159 53128349 : bool IsNull() const
160 : {
161 52398664 : return (nValue == -1);
162 : }
163 :
164 16125 : void SetEmpty()
165 : {
166 16125 : nValue = 0;
167 16125 : scriptPubKey.clear();
168 : }
169 :
170 12523874 : bool IsEmpty() const
171 : {
172 12523884 : return (nValue == 0 && scriptPubKey.empty());
173 : }
174 :
175 : uint256 GetHash() const;
176 :
177 : bool IsZerocoinMint() const;
178 :
179 390321 : friend bool operator==(const CTxOut& a, const CTxOut& b)
180 : {
181 385456 : return (a.nValue == b.nValue &&
182 390321 : a.scriptPubKey == b.scriptPubKey &&
183 385455 : a.nRounds == b.nRounds);
184 : }
185 :
186 167066 : friend bool operator!=(const CTxOut& a, const CTxOut& b)
187 : {
188 167066 : return !(a == b);
189 : }
190 :
191 : std::string ToString() const;
192 :
193 555344 : size_t DynamicMemoryUsage() const { return scriptPubKey.DynamicMemoryUsage(); }
194 : };
195 :
196 : struct CMutableTransaction;
197 :
198 : /**
199 : * Transaction serialization format:
200 : * - int32_t nVersion
201 : * - std::vector<CTxIn> vin
202 : * - std::vector<CTxOut> vout
203 : * - uint32_t nLockTime
204 : * - Optional<SaplingTxData> sapData
205 : * - Optional<std::vector<uint8_t>> extraPayload
206 : */
207 : template<typename Stream, typename TxType>
208 1018789 : inline void UnserializeTransaction(TxType& tx, Stream& s) {
209 1018789 : tx.vin.clear();
210 1018789 : tx.vout.clear();
211 :
212 1018789 : s >> tx.nVersion;
213 1018789 : s >> tx.nType;
214 1018788 : s >> tx.vin;
215 1018786 : s >> tx.vout;
216 1018786 : s >> tx.nLockTime;
217 1018786 : if (tx.isSaplingVersion()) {
218 13555 : s >> tx.sapData;
219 13555 : if (!tx.IsNormalType()) {
220 9933 : s >> tx.extraPayload;
221 : }
222 : }
223 1018786 : }
224 :
225 : template<typename Stream, typename TxType>
226 6304961 : inline void SerializeTransaction(const TxType& tx, Stream& s) {
227 6304961 : s << tx.nVersion;
228 6304961 : s << tx.nType;
229 6304961 : s << tx.vin;
230 6304961 : s << tx.vout;
231 6304961 : s << tx.nLockTime;
232 6304961 : if (tx.isSaplingVersion()) {
233 123272 : s << tx.sapData;
234 123272 : if (!tx.IsNormalType()) {
235 39065 : s << tx.extraPayload;
236 : }
237 : }
238 6304961 : }
239 :
240 : /** The basic transaction that is broadcasted on the network and contained in
241 : * blocks. A transaction can contain multiple inputs and outputs.
242 : */
243 : class CTransaction
244 : {
245 : public:
246 : /** Transaction Versions */
247 : enum TxVersion: int16_t {
248 : LEGACY = 1,
249 : SAPLING = 3,
250 : TOOHIGH
251 : };
252 :
253 : /** Transaction types */
254 : enum TxType: int16_t {
255 : NORMAL = 0,
256 : PROREG = 1,
257 : PROUPSERV = 2,
258 : PROUPREG = 3,
259 : PROUPREV = 4,
260 : LLMQCOMM = 5,
261 : };
262 :
263 : static const int16_t CURRENT_VERSION = TxVersion::LEGACY;
264 :
265 : // The local variables are made const to prevent unintended modification
266 : // without updating the cached hash value. However, CTransaction is not
267 : // actually immutable; deserialization and assignment are implemented,
268 : // and bypass the constness. This is safe, as they update the entire
269 : // structure, including the hash.
270 : std::vector<CTxIn> vin;
271 : std::vector<CTxOut> vout;
272 : const int16_t nVersion;
273 : const int16_t nType;
274 : const uint32_t nLockTime;
275 : Optional<SaplingTxData> sapData{SaplingTxData()}; // Future: Don't initialize it by default
276 : Optional<std::vector<uint8_t>> extraPayload{nullopt}; // only available for special transaction types
277 :
278 : /** Construct a CTransaction that qualifies as IsNull() */
279 : CTransaction();
280 :
281 : /** Convert a CMutableTransaction into a CTransaction. */
282 : CTransaction(const CMutableTransaction &tx);
283 : CTransaction(CMutableTransaction &&tx);
284 :
285 721008 : CTransaction(const CTransaction& tx) = default;
286 :
287 : template <typename Stream>
288 5973001 : inline void Serialize(Stream& s) const {
289 5973001 : SerializeTransaction(*this, s);
290 : }
291 :
292 : /** This deserializing constructor is provided instead of an Unserialize method.
293 : * Unserialize is not possible, since it would require overwriting const fields. */
294 : template <typename Stream>
295 807302 : CTransaction(deserialize_type, Stream& s) : CTransaction(CMutableTransaction(deserialize, s)) {}
296 :
297 : bool IsNull() const {
298 : return vin.empty() && vout.empty();
299 : }
300 :
301 380906095 : const uint256& GetHash() const {
302 371045595 : return hash;
303 : }
304 :
305 12974656 : bool hasSaplingData() const
306 : {
307 25949212 : return sapData != nullopt &&
308 12974550 : (!sapData->vShieldedOutput.empty() ||
309 10363433 : !sapData->vShieldedSpend.empty() ||
310 10363307 : sapData->valueBalance != 0 ||
311 10363307 : sapData->hasBindingSig());
312 : };
313 :
314 24602518 : bool isSaplingVersion() const
315 : {
316 16212211 : return nVersion >= TxVersion::SAPLING;
317 : }
318 :
319 11561775 : bool IsShieldedTx() const
320 : {
321 11561775 : return isSaplingVersion() && hasSaplingData();
322 : }
323 :
324 1197818 : bool hasExtraPayload() const
325 : {
326 1197818 : return extraPayload != nullopt && !extraPayload->empty();
327 : }
328 :
329 1641768 : bool IsSpecialTx() const
330 : {
331 1369449 : return isSaplingVersion() && nType != TxType::NORMAL && hasExtraPayload();
332 : }
333 :
334 1837847 : bool IsNormalType() const { return nType == TxType::NORMAL; }
335 :
336 39876 : bool IsProRegTx() const
337 : {
338 39889 : return IsSpecialTx() && nType == TxType::PROREG;
339 : }
340 :
341 244017 : bool IsQuorumCommitmentTx() const
342 : {
343 253345 : return IsSpecialTx() && nType == TxType::LLMQCOMM;
344 : }
345 :
346 : // Ensure that special and sapling fields are signed
347 1325380 : SigVersion GetRequiredSigVersion() const
348 : {
349 1325380 : return isSaplingVersion() ? SIGVERSION_SAPLING : SIGVERSION_BASE;
350 : }
351 :
352 : /*
353 : * Context for the two methods below:
354 : * We can think of the Sapling shielded part of the transaction as an input
355 : * or output according to whether valueBalance - the sum of shielded input
356 : * values minus the sum of shielded output values - is positive or negative.
357 : */
358 :
359 : // Return sum of txouts.
360 : CAmount GetValueOut() const;
361 : // GetValueIn() is a method on CCoinsViewCache, because
362 : // inputs must be known to compute value in.
363 :
364 : // Return sum of (positive valueBalance or zero) and JoinSplit vpub_new
365 : CAmount GetShieldedValueIn() const;
366 :
367 : bool HasZerocoinSpendInputs() const;
368 :
369 : bool HasZerocoinMintOutputs() const;
370 :
371 240646 : bool ContainsZerocoins() const
372 : {
373 240646 : return HasZerocoinSpendInputs() || HasZerocoinMintOutputs();
374 : }
375 :
376 23798325 : bool IsCoinBase() const
377 : {
378 96112126 : return (vin.size() == 1 && vin[0].prevout.IsNull() && !vin[0].scriptSig.IsZerocoinSpend());
379 : }
380 :
381 : bool IsCoinStake() const;
382 : bool HasP2CSOutputs() const;
383 : bool HasExchangeAddr() const;
384 :
385 3448485 : friend bool operator==(const CTransaction& a, const CTransaction& b)
386 : {
387 3448485 : return a.hash == b.hash;
388 : }
389 :
390 0 : friend bool operator!=(const CTransaction& a, const CTransaction& b)
391 : {
392 0 : return a.hash != b.hash;
393 : }
394 :
395 : unsigned int GetTotalSize() const;
396 :
397 : std::string ToString() const;
398 :
399 : size_t DynamicMemoryUsage() const;
400 :
401 : private:
402 : /** Memory only. */
403 : const uint256 hash;
404 : uint256 ComputeHash() const;
405 : };
406 :
407 : /** A mutable version of CTransaction. */
408 : struct CMutableTransaction
409 : {
410 : std::vector<CTxIn> vin;
411 : std::vector<CTxOut> vout;
412 : int16_t nVersion;
413 : int16_t nType;
414 : uint32_t nLockTime;
415 : Optional<SaplingTxData> sapData{SaplingTxData()}; // Future: Don't initialize it by default
416 : Optional<std::vector<uint8_t>> extraPayload{nullopt};
417 :
418 : CMutableTransaction();
419 : CMutableTransaction(const CTransaction& tx);
420 :
421 : template <typename Stream>
422 331960 : inline void Serialize(Stream& s) const {
423 331960 : SerializeTransaction(*this, s);
424 : }
425 :
426 : template <typename Stream>
427 1018789 : inline void Unserialize(Stream& s) {
428 1018789 : UnserializeTransaction(*this, s);
429 807302 : }
430 :
431 : template <typename Stream>
432 807302 : CMutableTransaction(deserialize_type, Stream& s) {
433 807302 : Unserialize(s);
434 807302 : }
435 :
436 1352147 : bool isSaplingVersion() const { return nVersion >= CTransaction::TxVersion::SAPLING; }
437 20924 : bool IsNormalType() const { return nType == CTransaction::TxType::NORMAL; }
438 :
439 : /** Compute the hash of this CMutableTransaction. This is computed on the
440 : * fly, as opposed to GetHash() in CTransaction, which uses a cached result.
441 : */
442 : uint256 GetHash() const;
443 :
444 88 : bool hasExtraPayload() const
445 : {
446 88 : return extraPayload != nullopt && !extraPayload->empty();
447 : }
448 :
449 : // Ensure that special and sapling fields are signed
450 255632 : SigVersion GetRequiredSigVersion() const
451 : {
452 255632 : return isSaplingVersion() ? SIGVERSION_SAPLING : SIGVERSION_BASE;
453 : }
454 : };
455 :
456 : typedef std::shared_ptr<const CTransaction> CTransactionRef;
457 6775 : static inline CTransactionRef MakeTransactionRef() { return std::make_shared<const CTransaction>(); }
458 856039 : template <typename Tx> static inline CTransactionRef MakeTransactionRef(Tx&& txIn) { return std::make_shared<const CTransaction>(std::forward<Tx>(txIn)); }
459 170052 : static inline CTransactionRef MakeTransactionRef(const CTransactionRef& txIn) { return txIn; }
460 : static inline CTransactionRef MakeTransactionRef(CTransactionRef&& txIn) { return std::move(txIn); }
461 :
462 : /* Special tx payload handling */
463 : template <typename T>
464 15329 : inline bool GetTxPayload(const std::vector<unsigned char>& payload, T& obj)
465 : {
466 30658 : CDataStream ds(payload, SER_NETWORK, PROTOCOL_VERSION | ADDRV2_FORMAT);
467 : try {
468 15327 : ds >> obj;
469 2 : } catch (std::exception& e) {
470 : return false;
471 : }
472 15327 : return ds.empty();
473 : }
474 : template <typename T>
475 88 : inline bool GetTxPayload(const CMutableTransaction& tx, T& obj)
476 : {
477 88 : return tx.hasExtraPayload() && GetTxPayload(*tx.extraPayload, obj);
478 : }
479 : template <typename T>
480 15241 : inline bool GetTxPayload(const CTransaction& tx, T& obj)
481 : {
482 15241 : return tx.hasExtraPayload() && GetTxPayload(*tx.extraPayload, obj);
483 : }
484 :
485 : template <typename T>
486 639 : void SetTxPayload(CMutableTransaction& tx, const T& payload)
487 : {
488 639 : CDataStream ds(SER_NETWORK, PROTOCOL_VERSION | ADDRV2_FORMAT);
489 639 : ds << payload;
490 1278 : tx.extraPayload.emplace(ds.begin(), ds.end());
491 639 : }
492 :
493 : #endif // PIVX_PRIMITIVES_TRANSACTION_H
|