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 14011020 : BaseOutPoint() { SetNull(); }
40 24749984 : BaseOutPoint(const uint256& hashIn, const uint32_t nIn, bool isTransparentIn = true) :
41 24749984 : hash(hashIn), n(nIn), isTransparent(isTransparentIn) { }
42 :
43 65246957 : SERIALIZE_METHODS(BaseOutPoint, obj) { READWRITE(obj.hash, obj.n); }
44 :
45 13972350 : void SetNull() { hash.SetNull(); n = (uint32_t) -1; }
46 46560119 : bool IsNull() const { return (hash.IsNull() && n == (uint32_t) -1); }
47 :
48 456991793 : friend bool operator<(const BaseOutPoint& a, const BaseOutPoint& b)
49 : {
50 456991793 : return (a.hash < b.hash || (a.hash == b.hash && a.n < b.n));
51 : }
52 :
53 28742243 : friend bool operator==(const BaseOutPoint& a, const BaseOutPoint& b)
54 : {
55 28741111 : return (a.hash == b.hash && a.n == b.n);
56 : }
57 :
58 1132 : friend bool operator!=(const BaseOutPoint& a, const BaseOutPoint& b)
59 : {
60 2038 : 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 9064873 : COutPoint() : BaseOutPoint() {};
75 21616635 : 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 901 : SaplingOutPoint() : BaseOutPoint() {};
85 5127 : 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 71284233 : 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 10515609 : 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 36299879 : SERIALIZE_METHODS(CTxIn, obj) { READWRITE(obj.prevout, obj.scriptSig, obj.nSequence); }
109 :
110 863 : bool IsFinal() const { return nSequence == SEQUENCE_FINAL; }
111 1688 : 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 585511 : 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 159462677 : class CTxOut
137 : {
138 : public:
139 : CAmount nValue;
140 : CScript scriptPubKey;
141 : int nRounds;
142 :
143 68907979 : CTxOut()
144 68907979 : {
145 137815982 : SetNull();
146 : }
147 :
148 : CTxOut(const CAmount& nValueIn, CScript scriptPubKeyIn);
149 :
150 72183363 : SERIALIZE_METHODS(CTxOut, obj) { READWRITE(obj.nValue, obj.scriptPubKey); }
151 :
152 74239263 : void SetNull()
153 : {
154 74239263 : nValue = -1;
155 74239263 : scriptPubKey.clear();
156 63270193 : nRounds = -10; // an initial value, should be no way to get this by calculations
157 : }
158 :
159 58501925 : bool IsNull() const
160 : {
161 57808178 : return (nValue == -1);
162 : }
163 :
164 16322 : void SetEmpty()
165 : {
166 16322 : nValue = 0;
167 16322 : scriptPubKey.clear();
168 : }
169 :
170 14425778 : bool IsEmpty() const
171 : {
172 14425788 : return (nValue == 0 && scriptPubKey.empty());
173 : }
174 :
175 : uint256 GetHash() const;
176 :
177 : bool IsZerocoinMint() const;
178 :
179 548383 : friend bool operator==(const CTxOut& a, const CTxOut& b)
180 : {
181 542026 : return (a.nValue == b.nValue &&
182 548383 : a.scriptPubKey == b.scriptPubKey &&
183 542023 : a.nRounds == b.nRounds);
184 : }
185 :
186 317467 : friend bool operator!=(const CTxOut& a, const CTxOut& b)
187 : {
188 317467 : return !(a == b);
189 : }
190 :
191 : std::string ToString() const;
192 :
193 855001 : 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 1121667 : inline void UnserializeTransaction(TxType& tx, Stream& s) {
209 1121667 : tx.vin.clear();
210 1121667 : tx.vout.clear();
211 :
212 1121667 : s >> tx.nVersion;
213 1121667 : s >> tx.nType;
214 1121666 : s >> tx.vin;
215 1121664 : s >> tx.vout;
216 1121664 : s >> tx.nLockTime;
217 1121664 : if (tx.isSaplingVersion()) {
218 14393 : s >> tx.sapData;
219 14393 : if (!tx.IsNormalType()) {
220 10771 : s >> tx.extraPayload;
221 : }
222 : }
223 1121664 : }
224 :
225 : template<typename Stream, typename TxType>
226 7110164 : inline void SerializeTransaction(const TxType& tx, Stream& s) {
227 7110164 : s << tx.nVersion;
228 7110164 : s << tx.nType;
229 7110164 : s << tx.vin;
230 7110164 : s << tx.vout;
231 7110164 : s << tx.nLockTime;
232 7110164 : if (tx.isSaplingVersion()) {
233 123329 : s << tx.sapData;
234 123329 : if (!tx.IsNormalType()) {
235 40328 : s << tx.extraPayload;
236 : }
237 : }
238 7110164 : }
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 874381 : CTransaction(const CTransaction& tx) = default;
286 :
287 : template <typename Stream>
288 6778090 : inline void Serialize(Stream& s) const {
289 6778090 : 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 910135 : CTransaction(deserialize_type, Stream& s) : CTransaction(CMutableTransaction(deserialize, s)) {}
296 :
297 : bool IsNull() const {
298 : return vin.empty() && vout.empty();
299 : }
300 :
301 414944252 : const uint256& GetHash() const {
302 405004752 : return hash;
303 : }
304 :
305 15509943 : bool hasSaplingData() const
306 : {
307 31019882 : return sapData != nullopt &&
308 15509937 : (!sapData->vShieldedOutput.empty() ||
309 12898802 : !sapData->vShieldedSpend.empty() ||
310 12898652 : sapData->valueBalance != 0 ||
311 12898652 : sapData->hasBindingSig());
312 : };
313 :
314 28866416 : bool isSaplingVersion() const
315 : {
316 18750518 : return nVersion >= TxVersion::SAPLING;
317 : }
318 :
319 13969618 : bool IsShieldedTx() const
320 : {
321 13969618 : return isSaplingVersion() && hasSaplingData();
322 : }
323 :
324 1419756 : bool hasExtraPayload() const
325 : {
326 1419756 : return extraPayload != nullopt && !extraPayload->empty();
327 : }
328 :
329 1973246 : bool IsSpecialTx() const
330 : {
331 1612388 : return isSaplingVersion() && nType != TxType::NORMAL && hasExtraPayload();
332 : }
333 :
334 2176427 : bool IsNormalType() const { return nType == TxType::NORMAL; }
335 :
336 58775 : bool IsProRegTx() const
337 : {
338 58788 : return IsSpecialTx() && nType == TxType::PROREG;
339 : }
340 :
341 313654 : bool IsQuorumCommitmentTx() const
342 : {
343 322979 : return IsSpecialTx() && nType == TxType::LLMQCOMM;
344 : }
345 :
346 : // Ensure that special and sapling fields are signed
347 1596945 : SigVersion GetRequiredSigVersion() const
348 : {
349 1596945 : 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 312393 : bool ContainsZerocoins() const
372 : {
373 312393 : return HasZerocoinSpendInputs() || HasZerocoinMintOutputs();
374 : }
375 :
376 27458424 : bool IsCoinBase() const
377 : {
378 101375067 : 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 4265555 : friend bool operator==(const CTransaction& a, const CTransaction& b)
386 : {
387 4265555 : 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 332074 : inline void Serialize(Stream& s) const {
423 332074 : SerializeTransaction(*this, s);
424 : }
425 :
426 : template <typename Stream>
427 1121667 : inline void Unserialize(Stream& s) {
428 1121667 : UnserializeTransaction(*this, s);
429 910135 : }
430 :
431 : template <typename Stream>
432 910135 : CMutableTransaction(deserialize_type, Stream& s) {
433 910135 : Unserialize(s);
434 910135 : }
435 :
436 1455139 : bool isSaplingVersion() const { return nVersion >= CTransaction::TxVersion::SAPLING; }
437 21693 : 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 255642 : SigVersion GetRequiredSigVersion() const
451 : {
452 255642 : return isSaplingVersion() ? SIGVERSION_SAPLING : SIGVERSION_BASE;
453 : }
454 : };
455 :
456 : typedef std::shared_ptr<const CTransaction> CTransactionRef;
457 6764 : static inline CTransactionRef MakeTransactionRef() { return std::make_shared<const CTransaction>(); }
458 933358 : template <typename Tx> static inline CTransactionRef MakeTransactionRef(Tx&& txIn) { return std::make_shared<const CTransaction>(std::forward<Tx>(txIn)); }
459 191541 : 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 15355 : inline bool GetTxPayload(const std::vector<unsigned char>& payload, T& obj)
465 : {
466 30710 : CDataStream ds(payload, SER_NETWORK, PROTOCOL_VERSION | ADDRV2_FORMAT);
467 : try {
468 15353 : ds >> obj;
469 2 : } catch (std::exception& e) {
470 : return false;
471 : }
472 15353 : 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 15267 : inline bool GetTxPayload(const CTransaction& tx, T& obj)
481 : {
482 15267 : 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
|