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 1172 : std::string BaseOutPoint::ToStringShort() const
14 : {
15 3516 : return strprintf("%s-%u", hash.ToString().substr(0,64), n);
16 : }
17 :
18 2323 : std::string COutPoint::ToString() const
19 : {
20 6969 : 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 9238 : CTxIn::CTxIn(COutPoint prevoutIn, CScript scriptSigIn, uint32_t nSequenceIn)
30 : {
31 9238 : prevout = prevoutIn;
32 9238 : scriptSig = scriptSigIn;
33 9238 : nSequence = nSequenceIn;
34 9238 : }
35 :
36 8467 : CTxIn::CTxIn(uint256 hashPrevTx, uint32_t nOut, CScript scriptSigIn, uint32_t nSequenceIn)
37 : {
38 8467 : prevout = COutPoint(hashPrevTx, nOut);
39 8467 : scriptSig = scriptSigIn;
40 8467 : nSequence = nSequenceIn;
41 8467 : }
42 :
43 34422762 : bool CTxIn::IsZerocoinSpend() const
44 : {
45 68845624 : return prevout.hash.IsNull() && scriptSig.IsZerocoinSpend();
46 : }
47 :
48 19691908 : bool CTxIn::IsZerocoinPublicSpend() const
49 : {
50 19691908 : return scriptSig.IsZerocoinPublicSpend();
51 : }
52 :
53 2140 : std::string CTxIn::ToString() const
54 : {
55 2140 : std::string str;
56 2140 : str += "CTxIn(";
57 4280 : str += prevout.ToString();
58 2140 : 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 11118 : str += strprintf(", scriptSig=%s", HexStr(scriptSig).substr(0, 24));
65 2140 : if (nSequence != std::numeric_limits<unsigned int>::max())
66 0 : str += strprintf(", nSequence=%u", nSequence);
67 2140 : str += ")";
68 2140 : return str;
69 : }
70 :
71 23046 : CTxOut::CTxOut(const CAmount& nValueIn, CScript scriptPubKeyIn)
72 : {
73 23046 : nValue = nValueIn;
74 23046 : scriptPubKey = scriptPubKeyIn;
75 23046 : nRounds = -10;
76 23046 : }
77 :
78 0 : uint256 CTxOut::GetHash() const
79 : {
80 0 : return SerializeHash(*this);
81 : }
82 :
83 8019671 : bool CTxOut::IsZerocoinMint() const
84 : {
85 8019671 : return scriptPubKey.IsZerocoinMint();
86 : }
87 :
88 1804 : std::string CTxOut::ToString() const
89 : {
90 7214 : return strprintf("CTxOut(nValue=%d.%08d, scriptPubKey=%s)", nValue / COIN, nValue % COIN, HexStr(scriptPubKey).substr(0,30));
91 : }
92 :
93 819447 : CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nType(CTransaction::TxType::NORMAL), nLockTime(0) {}
94 156636 : 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 278474 : uint256 CMutableTransaction::GetHash() const
97 : {
98 278474 : return SerializeHash(*this);
99 : }
100 :
101 2248577 : uint256 CTransaction::ComputeHash() const
102 : {
103 2248577 : return SerializeHash(*this);
104 : }
105 :
106 210080 : size_t CTransaction::DynamicMemoryUsage() const
107 : {
108 210080 : 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 13632 : CTransaction::CTransaction() : vin(), vout(), nVersion(CTransaction::CURRENT_VERSION), nType(TxType::NORMAL), nLockTime(0), hash() {}
113 2073497 : 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 2434512 : 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 11367877 : bool CTransaction::HasZerocoinSpendInputs() const
117 : {
118 28614310 : for (const CTxIn& txin: vin) {
119 17246333 : if (txin.IsZerocoinSpend() || txin.IsZerocoinPublicSpend())
120 0 : return true;
121 : }
122 11367877 : return false;
123 : }
124 :
125 245716 : bool CTransaction::HasZerocoinMintOutputs() const
126 : {
127 884639 : for(const CTxOut& txout : vout) {
128 638923 : if (txout.IsZerocoinMint())
129 0 : return true;
130 : }
131 245716 : return false;
132 : }
133 :
134 12782117 : bool CTransaction::IsCoinStake() const
135 : {
136 12782117 : if (vin.empty())
137 : return false;
138 :
139 12734971 : bool fAllowNull = vin[0].IsZerocoinSpend();
140 12803067 : if (vin[0].prevout.IsNull() && !fAllowNull)
141 : return false;
142 :
143 12666775 : return (vout.size() >= 2 && vout[0].IsEmpty());
144 : }
145 :
146 771286 : bool CTransaction::HasExchangeAddr() const
147 : {
148 2785939 : return std::any_of(vout.begin(), vout.end(), [](const auto& txout) { return txout.scriptPubKey.IsPayToExchangeAddress(); });
149 : }
150 :
151 11686 : bool CTransaction::HasP2CSOutputs() const
152 : {
153 25126 : for(const CTxOut& txout : vout) {
154 14321 : if (txout.scriptPubKey.IsPayToColdStaking())
155 881 : return true;
156 : }
157 10805 : return false;
158 : }
159 :
160 6846409 : CAmount CTransaction::GetValueOut() const
161 : {
162 6846409 : CAmount nValueOut = 0;
163 20896175 : for (const CTxOut& out : vout) {
164 : // PIVX: previously MoneyRange() was called here. This has been replaced with negative check and boundary wrap check.
165 14049786 : if (out.nValue < 0)
166 0 : throw std::runtime_error("CTransaction::GetValueOut() : value out of range : less than 0");
167 :
168 14049786 : if (nValueOut + out.nValue < nValueOut)
169 : throw std::runtime_error("CTransaction::GetValueOut() : value out of range : wraps the int64_t boundary");
170 :
171 14049786 : nValueOut += out.nValue;
172 : }
173 :
174 : // Sapling
175 6846409 : if (hasSaplingData() && sapData->valueBalance < 0) {
176 : // NB: negative valueBalance "takes" money from the transparent value pool just as outputs do
177 1019021 : nValueOut += -sapData->valueBalance;
178 :
179 : // Verify Sapling version
180 1019021 : if (!isSaplingVersion())
181 0 : throw std::runtime_error("GetValueOut(): invalid tx version");
182 : }
183 :
184 6846409 : return nValueOut;
185 : }
186 :
187 3646823 : CAmount CTransaction::GetShieldedValueIn() const
188 : {
189 3646823 : CAmount nValue = 0;
190 :
191 3646823 : if (hasSaplingData() && sapData->valueBalance > 0) {
192 : // NB: positive valueBalance "gives" money to the transparent value pool just as inputs do
193 724 : nValue += sapData->valueBalance;
194 :
195 : // Verify Sapling
196 724 : if (!isSaplingVersion())
197 0 : throw std::runtime_error("GetValueOut(): invalid tx version");
198 : }
199 :
200 3646823 : return nValue;
201 : }
202 :
203 926266 : unsigned int CTransaction::GetTotalSize() const
204 : {
205 926266 : return ::GetSerializeSize(*this, PROTOCOL_VERSION);
206 : }
207 :
208 1439 : std::string CTransaction::ToString() const
209 : {
210 1439 : std::ostringstream ss;
211 2878 : ss << "CTransaction(hash=" << GetHash().ToString().substr(0, 10)
212 2878 : << ", ver=" << nVersion
213 1439 : << ", type=" << nType
214 1439 : << ", vin.size=" << vin.size()
215 1439 : << ", vout.size=" << vout.size()
216 1439 : << ", nLockTime=" << nLockTime;
217 1439 : if (IsShieldedTx()) {
218 1066 : ss << ", valueBalance=" << sapData->valueBalance
219 1066 : << ", vShieldedSpend.size=" << sapData->vShieldedSpend.size()
220 1066 : << ", vShieldedOutput.size=" << sapData->vShieldedOutput.size();
221 : }
222 1439 : if (IsSpecialTx()) {
223 0 : ss << ", extraPayload.size=" << extraPayload->size();
224 : }
225 1439 : ss << ")\n";
226 3007 : for (const auto& in : vin)
227 4704 : ss << " " << in.ToString() << "\n";
228 3243 : for (const auto& out : vout)
229 5412 : ss << " " << out.ToString() << "\n";
230 1439 : return ss.str();
231 : }
|