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 1200 : std::string BaseOutPoint::ToStringShort() const
14 : {
15 3600 : return strprintf("%s-%u", hash.ToString().substr(0,64), n);
16 : }
17 :
18 2326 : std::string COutPoint::ToString() const
19 : {
20 6978 : 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 9106 : CTxIn::CTxIn(COutPoint prevoutIn, CScript scriptSigIn, uint32_t nSequenceIn)
30 : {
31 9106 : prevout = prevoutIn;
32 9106 : scriptSig = scriptSigIn;
33 9106 : nSequence = nSequenceIn;
34 9106 : }
35 :
36 8600 : CTxIn::CTxIn(uint256 hashPrevTx, uint32_t nOut, CScript scriptSigIn, uint32_t nSequenceIn)
37 : {
38 8600 : prevout = COutPoint(hashPrevTx, nOut);
39 8600 : scriptSig = scriptSigIn;
40 8600 : nSequence = nSequenceIn;
41 8600 : }
42 :
43 35312836 : bool CTxIn::IsZerocoinSpend() const
44 : {
45 70625572 : return prevout.hash.IsNull() && scriptSig.IsZerocoinSpend();
46 : }
47 :
48 21151991 : bool CTxIn::IsZerocoinPublicSpend() const
49 : {
50 21151991 : return scriptSig.IsZerocoinPublicSpend();
51 : }
52 :
53 2149 : std::string CTxIn::ToString() const
54 : {
55 2149 : std::string str;
56 2149 : str += "CTxIn(";
57 4298 : str += prevout.ToString();
58 2149 : 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 11181 : str += strprintf(", scriptSig=%s", HexStr(scriptSig).substr(0, 24));
65 2149 : if (nSequence != std::numeric_limits<unsigned int>::max())
66 0 : str += strprintf(", nSequence=%u", nSequence);
67 2149 : str += ")";
68 2149 : return str;
69 : }
70 :
71 24342 : CTxOut::CTxOut(const CAmount& nValueIn, CScript scriptPubKeyIn)
72 : {
73 24342 : nValue = nValueIn;
74 24342 : scriptPubKey = scriptPubKeyIn;
75 24342 : nRounds = -10;
76 24342 : }
77 :
78 0 : uint256 CTxOut::GetHash() const
79 : {
80 0 : return SerializeHash(*this);
81 : }
82 :
83 8941484 : bool CTxOut::IsZerocoinMint() const
84 : {
85 8941484 : return scriptPubKey.IsZerocoinMint();
86 : }
87 :
88 1816 : std::string CTxOut::ToString() const
89 : {
90 7262 : return strprintf("CTxOut(nValue=%d.%08d, scriptPubKey=%s)", nValue / COIN, nValue % COIN, HexStr(scriptPubKey).substr(0,30));
91 : }
92 :
93 818199 : CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nType(CTransaction::TxType::NORMAL), nLockTime(0) {}
94 156978 : 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 257021 : uint256 CMutableTransaction::GetHash() const
97 : {
98 257021 : return SerializeHash(*this);
99 : }
100 :
101 2286399 : uint256 CTransaction::ComputeHash() const
102 : {
103 2286399 : return SerializeHash(*this);
104 : }
105 :
106 277627 : size_t CTransaction::DynamicMemoryUsage() const
107 : {
108 277627 : 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 13616 : CTransaction::CTransaction() : vin(), vout(), nVersion(CTransaction::CURRENT_VERSION), nType(TxType::NORMAL), nLockTime(0), hash() {}
113 2006960 : 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 2576908 : 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 11997246 : bool CTransaction::HasZerocoinSpendInputs() const
117 : {
118 30559948 : for (const CTxIn& txin: vin) {
119 18562702 : if (txin.IsZerocoinSpend() || txin.IsZerocoinPublicSpend())
120 0 : return true;
121 : }
122 11997246 : return false;
123 : }
124 :
125 312105 : bool CTransaction::HasZerocoinMintOutputs() const
126 : {
127 1150528 : for(const CTxOut& txout : vout) {
128 838422 : if (txout.IsZerocoinMint())
129 0 : return true;
130 : }
131 312105 : return false;
132 : }
133 :
134 12099298 : bool CTransaction::IsCoinStake() const
135 : {
136 12099298 : if (vin.empty())
137 : return false;
138 :
139 12050852 : bool fAllowNull = vin[0].IsZerocoinSpend();
140 12120033 : if (vin[0].prevout.IsNull() && !fAllowNull)
141 : return false;
142 :
143 11981671 : return (vout.size() >= 2 && vout[0].IsEmpty());
144 : }
145 :
146 787432 : bool CTransaction::HasExchangeAddr() const
147 : {
148 2847570 : return std::any_of(vout.begin(), vout.end(), [](const auto& txout) { return txout.scriptPubKey.IsPayToExchangeAddress(); });
149 : }
150 :
151 11692 : bool CTransaction::HasP2CSOutputs() const
152 : {
153 25358 : for(const CTxOut& txout : vout) {
154 14547 : if (txout.scriptPubKey.IsPayToColdStaking())
155 881 : return true;
156 : }
157 10811 : return false;
158 : }
159 :
160 7151274 : CAmount CTransaction::GetValueOut() const
161 : {
162 7151274 : CAmount nValueOut = 0;
163 21857486 : for (const CTxOut& out : vout) {
164 : // PIVX: previously MoneyRange() was called here. This has been replaced with negative check and boundary wrap check.
165 14706142 : if (out.nValue < 0)
166 0 : throw std::runtime_error("CTransaction::GetValueOut() : value out of range : less than 0");
167 :
168 14706142 : if (nValueOut + out.nValue < nValueOut)
169 : throw std::runtime_error("CTransaction::GetValueOut() : value out of range : wraps the int64_t boundary");
170 :
171 14706142 : nValueOut += out.nValue;
172 : }
173 :
174 : // Sapling
175 7151274 : if (hasSaplingData() && sapData->valueBalance < 0) {
176 : // NB: negative valueBalance "takes" money from the transparent value pool just as outputs do
177 1019081 : nValueOut += -sapData->valueBalance;
178 :
179 : // Verify Sapling version
180 1019081 : if (!isSaplingVersion())
181 0 : throw std::runtime_error("GetValueOut(): invalid tx version");
182 : }
183 :
184 7151274 : return nValueOut;
185 : }
186 :
187 3809413 : CAmount CTransaction::GetShieldedValueIn() const
188 : {
189 3809413 : CAmount nValue = 0;
190 :
191 3809413 : if (hasSaplingData() && sapData->valueBalance > 0) {
192 : // NB: positive valueBalance "gives" money to the transparent value pool just as inputs do
193 740 : nValue += sapData->valueBalance;
194 :
195 : // Verify Sapling
196 740 : if (!isSaplingVersion())
197 0 : throw std::runtime_error("GetValueOut(): invalid tx version");
198 : }
199 :
200 3809413 : return nValue;
201 : }
202 :
203 957333 : unsigned int CTransaction::GetTotalSize() const
204 : {
205 957333 : return ::GetSerializeSize(*this, PROTOCOL_VERSION);
206 : }
207 :
208 1445 : std::string CTransaction::ToString() const
209 : {
210 1445 : std::ostringstream ss;
211 2890 : ss << "CTransaction(hash=" << GetHash().ToString().substr(0, 10)
212 2890 : << ", ver=" << nVersion
213 1445 : << ", type=" << nType
214 1445 : << ", vin.size=" << vin.size()
215 1445 : << ", vout.size=" << vout.size()
216 1445 : << ", nLockTime=" << nLockTime;
217 1445 : if (IsShieldedTx()) {
218 1066 : ss << ", valueBalance=" << sapData->valueBalance
219 1066 : << ", vShieldedSpend.size=" << sapData->vShieldedSpend.size()
220 1066 : << ", vShieldedOutput.size=" << sapData->vShieldedOutput.size();
221 : }
222 1445 : if (IsSpecialTx()) {
223 0 : ss << ", extraPayload.size=" << extraPayload->size();
224 : }
225 1445 : ss << ")\n";
226 3025 : for (const auto& in : vin)
227 4740 : ss << " " << in.ToString() << "\n";
228 3261 : for (const auto& out : vout)
229 5448 : ss << " " << out.ToString() << "\n";
230 1445 : return ss.str();
231 : }
|