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 : #include "primitives/transaction.h"
8 :
9 : #include "hash.h"
10 : #include "tinyformat.h"
11 : #include "utilstrencodings.h"
12 :
13 1167 : std::string BaseOutPoint::ToStringShort() const
14 : {
15 3501 : return strprintf("%s-%u", hash.ToString().substr(0,64), n);
16 : }
17 :
18 2333 : std::string COutPoint::ToString() const
19 : {
20 6999 : return strprintf("COutPoint(%s, %u)", hash.ToString().substr(0,10), n);
21 : }
22 :
23 0 : std::string SaplingOutPoint::ToString() const
24 : {
25 0 : return strprintf("SaplingOutPoint(%s, %u)", hash.ToString().substr(0, 10), n);
26 : }
27 :
28 :
29 9320 : CTxIn::CTxIn(COutPoint prevoutIn, CScript scriptSigIn, uint32_t nSequenceIn)
30 : {
31 9320 : prevout = prevoutIn;
32 9320 : scriptSig = scriptSigIn;
33 9320 : nSequence = nSequenceIn;
34 9320 : }
35 :
36 8493 : CTxIn::CTxIn(uint256 hashPrevTx, uint32_t nOut, CScript scriptSigIn, uint32_t nSequenceIn)
37 : {
38 8493 : prevout = COutPoint(hashPrevTx, nOut);
39 8493 : scriptSig = scriptSigIn;
40 8493 : nSequence = nSequenceIn;
41 8493 : }
42 :
43 41022345 : bool CTxIn::IsZerocoinSpend() const
44 : {
45 82044690 : return prevout.hash.IsNull() && scriptSig.IsZerocoinSpend();
46 : }
47 :
48 24358407 : bool CTxIn::IsZerocoinPublicSpend() const
49 : {
50 24358407 : return scriptSig.IsZerocoinPublicSpend();
51 : }
52 :
53 2144 : std::string CTxIn::ToString() const
54 : {
55 2144 : std::string str;
56 2144 : str += "CTxIn(";
57 4288 : str += prevout.ToString();
58 2144 : if (prevout.IsNull())
59 1 : if(IsZerocoinSpend())
60 0 : str += strprintf(", zerocoinspend %s...", HexStr(scriptSig).substr(0, 25));
61 : else
62 4 : str += strprintf(", coinbase %s", HexStr(scriptSig));
63 : else
64 11139 : str += strprintf(", scriptSig=%s", HexStr(scriptSig).substr(0, 24));
65 2144 : if (nSequence != std::numeric_limits<unsigned int>::max())
66 0 : str += strprintf(", nSequence=%u", nSequence);
67 2144 : str += ")";
68 2144 : return str;
69 : }
70 :
71 23434 : CTxOut::CTxOut(const CAmount& nValueIn, CScript scriptPubKeyIn)
72 : {
73 23434 : nValue = nValueIn;
74 23434 : scriptPubKey = scriptPubKeyIn;
75 23434 : nRounds = -10;
76 23434 : }
77 :
78 0 : uint256 CTxOut::GetHash() const
79 : {
80 0 : return SerializeHash(*this);
81 : }
82 :
83 10244713 : bool CTxOut::IsZerocoinMint() const
84 : {
85 10244713 : return scriptPubKey.IsZerocoinMint();
86 : }
87 :
88 1810 : std::string CTxOut::ToString() const
89 : {
90 7238 : return strprintf("CTxOut(nValue=%d.%08d, scriptPubKey=%s)", nValue / COIN, nValue % COIN, HexStr(scriptPubKey).substr(0,30));
91 : }
92 :
93 826888 : CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nType(CTransaction::TxType::NORMAL), nLockTime(0) {}
94 157442 : CMutableTransaction::CMutableTransaction(const CTransaction& tx) : vin(tx.vin), vout(tx.vout), nVersion(tx.nVersion), nType(tx.nType), nLockTime(tx.nLockTime), sapData(tx.sapData), extraPayload(tx.extraPayload) {}
95 :
96 278559 : uint256 CMutableTransaction::GetHash() const
97 : {
98 278559 : return SerializeHash(*this);
99 : }
100 :
101 2358266 : uint256 CTransaction::ComputeHash() const
102 : {
103 2358266 : return SerializeHash(*this);
104 : }
105 :
106 310116 : size_t CTransaction::DynamicMemoryUsage() const
107 : {
108 310116 : return memusage::RecursiveDynamicUsage(vin) + memusage::RecursiveDynamicUsage(vout);
109 : }
110 :
111 : /* For backward compatibility, the hash is initialized to 0. TODO: remove the need for this default constructor entirely. */
112 13610 : CTransaction::CTransaction() : vin(), vout(), nVersion(CTransaction::CURRENT_VERSION), nType(TxType::NORMAL), nLockTime(0), hash() {}
113 2086709 : CTransaction::CTransaction(const CMutableTransaction &tx) : vin(tx.vin), vout(tx.vout), nVersion(tx.nVersion), nType(tx.nType), nLockTime(tx.nLockTime), sapData(tx.sapData), extraPayload(tx.extraPayload), hash(ComputeHash()) {}
114 2641518 : CTransaction::CTransaction(CMutableTransaction &&tx) : vin(std::move(tx.vin)), vout(std::move(tx.vout)), nVersion(tx.nVersion), nType(tx.nType), nLockTime(tx.nLockTime), sapData(tx.sapData), extraPayload(tx.extraPayload), hash(ComputeHash()) {}
115 :
116 13875074 : bool CTransaction::HasZerocoinSpendInputs() const
117 : {
118 35246804 : for (const CTxIn& txin: vin) {
119 21371630 : if (txin.IsZerocoinSpend() || txin.IsZerocoinPublicSpend())
120 0 : return true;
121 : }
122 13875074 : return false;
123 : }
124 :
125 317463 : bool CTransaction::HasZerocoinMintOutputs() const
126 : {
127 1170868 : for(const CTxOut& txout : vout) {
128 853406 : if (txout.IsZerocoinMint())
129 0 : return true;
130 : }
131 317463 : return false;
132 : }
133 :
134 14314003 : bool CTransaction::IsCoinStake() const
135 : {
136 14314003 : if (vin.empty())
137 : return false;
138 :
139 14266757 : bool fAllowNull = vin[0].IsZerocoinSpend();
140 14335548 : if (vin[0].prevout.IsNull() && !fAllowNull)
141 : return false;
142 :
143 14197966 : return (vout.size() >= 2 && vout[0].IsEmpty());
144 : }
145 :
146 895579 : bool CTransaction::HasExchangeAddr() const
147 : {
148 3280996 : return std::any_of(vout.begin(), vout.end(), [](const auto& txout) { return txout.scriptPubKey.IsPayToExchangeAddress(); });
149 : }
150 :
151 11689 : bool CTransaction::HasP2CSOutputs() const
152 : {
153 25129 : for(const CTxOut& txout : vout) {
154 14321 : if (txout.scriptPubKey.IsPayToColdStaking())
155 881 : return true;
156 : }
157 10808 : return false;
158 : }
159 :
160 8341608 : CAmount CTransaction::GetValueOut() const
161 : {
162 8341608 : CAmount nValueOut = 0;
163 25844474 : for (const CTxOut& out : vout) {
164 : // PIVX: previously MoneyRange() was called here. This has been replaced with negative check and boundary wrap check.
165 17502936 : if (out.nValue < 0)
166 0 : throw std::runtime_error("CTransaction::GetValueOut() : value out of range : less than 0");
167 :
168 17502936 : if (nValueOut + out.nValue < nValueOut)
169 : throw std::runtime_error("CTransaction::GetValueOut() : value out of range : wraps the int64_t boundary");
170 :
171 17502936 : nValueOut += out.nValue;
172 : }
173 :
174 : // Sapling
175 8341608 : if (hasSaplingData() && sapData->valueBalance < 0) {
176 : // NB: negative valueBalance "takes" money from the transparent value pool just as outputs do
177 1019071 : nValueOut += -sapData->valueBalance;
178 :
179 : // Verify Sapling version
180 1019071 : if (!isSaplingVersion())
181 0 : throw std::runtime_error("GetValueOut(): invalid tx version");
182 : }
183 :
184 8341608 : return nValueOut;
185 : }
186 :
187 4449043 : CAmount CTransaction::GetShieldedValueIn() const
188 : {
189 4449043 : CAmount nValue = 0;
190 :
191 4449043 : if (hasSaplingData() && sapData->valueBalance > 0) {
192 : // NB: positive valueBalance "gives" money to the transparent value pool just as inputs do
193 690 : nValue += sapData->valueBalance;
194 :
195 : // Verify Sapling
196 690 : if (!isSaplingVersion())
197 0 : throw std::runtime_error("GetValueOut(): invalid tx version");
198 : }
199 :
200 4449043 : return nValue;
201 : }
202 :
203 1069554 : unsigned int CTransaction::GetTotalSize() const
204 : {
205 1069554 : return ::GetSerializeSize(*this, PROTOCOL_VERSION);
206 : }
207 :
208 1442 : std::string CTransaction::ToString() const
209 : {
210 1442 : std::ostringstream ss;
211 2884 : ss << "CTransaction(hash=" << GetHash().ToString().substr(0, 10)
212 2884 : << ", ver=" << nVersion
213 1442 : << ", type=" << nType
214 1442 : << ", vin.size=" << vin.size()
215 1442 : << ", vout.size=" << vout.size()
216 1442 : << ", nLockTime=" << nLockTime;
217 1442 : if (IsShieldedTx()) {
218 1066 : ss << ", valueBalance=" << sapData->valueBalance
219 1066 : << ", vShieldedSpend.size=" << sapData->vShieldedSpend.size()
220 1066 : << ", vShieldedOutput.size=" << sapData->vShieldedOutput.size();
221 : }
222 1442 : if (IsSpecialTx()) {
223 0 : ss << ", extraPayload.size=" << extraPayload->size();
224 : }
225 1442 : ss << ")\n";
226 3013 : for (const auto& in : vin)
227 4713 : ss << " " << in.ToString() << "\n";
228 3252 : for (const auto& out : vout)
229 5430 : ss << " " << out.ToString() << "\n";
230 1442 : return ss.str();
231 : }
|