13 #include "../validation.h"
21 if (tx.
vout.size() > 2) {
29 return state.
DoS(100,
error(
"%s: over two non-mint outputs in a zerocoinspend transaction", __func__));
35 txTemp.
vout.push_back(out);
39 bool fValidated =
false;
41 std::set<CBigNum> serials;
59 return state.
DoS(100,
error(
"%s: public zerocoin spend parse failed", __func__));
61 newSpend = publicSpend;
68 return state.
DoS(100,
error(
"%s: Zerocoinspend does not have the correct denomination", __func__));
72 return state.
DoS(100,
error(
"%s: Zerocoinspend nSequence denomination does not match CoinSpend", __func__));
76 return state.
DoS(100,
error(
"%s: Zerocoinspend does not use the same txout that was used in the SoK", __func__));
82 return state.
DoS(100,
error(
"%s: public zerocoin spend did not verify", __func__));
87 return state.
DoS(100,
error(
"%s: Zerocoinspend serial is used twice in the same tx", __func__));
97 return state.
DoS(100,
error(
"%s: Transaction spend more than was redeemed in zerocoins", __func__));
115 if (!isPublicSpend) {
116 return error(
"%s: failed to add block with older zc spend version", __func__);
121 return error(
"%s: failed to add block, public spend enforcement not activated", __func__);
130 const bool fZerocoinEnforced = (nHeight >= consensus.
ZC_HeightStart);
132 const bool fRejectMintsAndPrivateSpends = !isMined || !fZerocoinEnforced || fPublicSpendEnforced;
135 const bool hasPrivateSpendInputs = !tx->vin.empty() && tx->vin[0].IsZerocoinSpend();
136 const bool hasPublicSpendInputs = !tx->vin.empty() && tx->vin[0].IsZerocoinPublicSpend();
137 const std::string& txId = tx->GetHash().ToString();
140 for (
const CTxIn& in : tx->vin) {
142 if (fRejectMintsAndPrivateSpends)
143 return state.
DoS(100,
error(
"%s: zerocoin spend tx %s not accepted at height %d",
144 __func__, txId, nHeight), REJECT_INVALID,
"bad-txns-zc-private-spend");
145 if (!hasPrivateSpendInputs)
146 return state.
DoS(100,
error(
"%s: zerocoin spend tx %s has mixed spend inputs",
147 __func__, txId), REJECT_INVALID,
"bad-txns-zc-private-spend-mixed-types");
149 return state.
DoS(100,
error(
"%s: zerocoin spend tx %s has more than %d inputs",
150 __func__, txId, consensus.
ZC_MaxSpendsPerTx), REJECT_INVALID,
"bad-txns-zc-private-spend-max-inputs");
153 if (fRejectPublicSpends)
154 return state.
DoS(100,
error(
"%s: zerocoin public spend tx %s not accepted at height %d",
155 __func__, txId, nHeight), REJECT_INVALID,
"bad-txns-zc-public-spend");
156 if (!hasPublicSpendInputs)
157 return state.
DoS(100,
error(
"%s: zerocoin spend tx %s has mixed spend inputs",
158 __func__, txId), REJECT_INVALID,
"bad-txns-zc-public-spend-mixed-types");
160 return state.
DoS(100,
error(
"%s: zerocoin spend tx %s has more than %d inputs",
165 if (hasPrivateSpendInputs || hasPublicSpendInputs)
166 return state.
DoS(100,
error(
"%s: zerocoin spend tx %s has mixed spend inputs",
167 __func__, txId), REJECT_INVALID,
"bad-txns-zc-spend-mixed-types");
171 if (hasPrivateSpendInputs || hasPublicSpendInputs) {
172 if (!CheckZerocoinSpend(tx, state))
176 for (
const CTxOut& o : tx->vout) {
178 return state.
DoS(100,
error(
"%s: zerocoin mint tx %s not accepted at height %d",
179 __func__, txId, nHeight), REJECT_INVALID,
"bad-txns-zc-mint");
190 if (!
zerocoinDB->ReadCoinSpend(bnSerial, txHash))
221 return error(
"%s : zPIV spend with serial %s is already in block %d\n", __func__,
234 return error(
"%s: V2 zPIV spend does not have a valid signature\n", __func__);
238 return error(
"%s: Invalid serial detected, txid %s, in block %d\n", __func__, tx.
GetHash().
GetHex(), nHeight);
240 LogPrintf(
"%s: Invalid serial detected within range in block %d\n", __func__, nHeight);
247 return error(
"%s: trying to spend zPIV without the correct spend type. txid=%s\n", __func__,
252 bool fUseV1Params = spend->
getCoinVersion() < libzerocoin::PUBKEY_VERSION;
258 return error(
"%s : zPIV spend with serial %s from tx %s is not in valid range\n", __func__,
261 LogPrintf(
"%s:: HasValidSerial :: Invalid serial detected within range in block %d\n", __func__, nHeight);
271 std::vector<std::pair<CBigNum, uint256>>& vSpendsRet)
276 if (!isPrivZerocoinSpend && !isPublicSpend)
292 state.
DoS(100,
error(
"%s: failed to add block %s with invalid public zc spend", __func__,
301 return state.
DoS(100,
error(
"%s: failed to add block %s with invalid zerocoinspend", __func__,
307 return !vSpendsRet.empty();
int64_t CAmount
Amount in PIV (Can be negative)
const CChainParams & Params()
Return the currently selected parameters.
static const std::string MAIN
Chain name strings.
std::string GetHex() const
The block chain is a tree shaped structure starting with the genesis block at the root,...
int nHeight
height of the entry in the chain. The genesis block has height 0
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
const Consensus::Params & GetConsensus() const
The basic transaction that is broadcasted on the network and contained in blocks.
const uint256 & GetHash() const
CAmount GetValueOut() const
std::vector< CTxOut > vout
An input of a transaction.
bool IsZerocoinSpend() const
bool IsZerocoinPublicSpend() const
An output of a transaction.
bool IsZerocoinMint() const
Capture information about block/transaction validation.
bool DoS(int level, bool ret=false, unsigned int chRejectCodeIn=0, std::string strRejectReasonIn="", bool corruptionIn=false, const std::string &strDebugMessageIn="")
std::string GetHex() const
The complete proof needed to spend a zerocoin.
const CBigNum & getCoinSerialNumber() const
CoinDenomination getDenomination() const
uint256 getTxOutHash() const
bool HasValidSerial(ZerocoinParams *params) const
SpendType getSpendType() const
int getCoinVersion() const
bool HasValidSignature() const
bool validateInput(const CTxIn &in, const CTxOut &prevOut, const CTransaction &tx, PublicCoinSpend &publicSpend)
libzerocoin::CoinSpend TxInToZerocoinSpend(const CTxIn &txin)
bool ParseZerocoinPublicSpend(const CTxIn &txIn, const CTransaction &tx, CValidationState &state, PublicCoinSpend &publicSpend)
PublicCoinSpend parseCoinSpend(const CTxIn &in)
CAmount ZerocoinDenominationToAmount(const CoinDenomination &denomination)
A mutable version of CTransaction.
uint256 GetHash() const
Compute the hash of this CMutableTransaction.
std::vector< CTxOut > vout
Parameters that influence chain consensus.
int ZC_MaxPublicSpendsPerTx
libzerocoin::ZerocoinParams * Zerocoin_Params(bool useModulusV1) const
int height_last_ZC_WrappedSerials
bool NetworkUpgradeActive(int nHeight, Consensus::UpgradeIndex idx) const
Returns true if the given network upgrade is active as of the given block height.
bool error(const char *fmt, const Args &... args)
std::shared_ptr< const CTransaction > CTransactionRef
bool NetworkUpgradeActive(int nHeight, const Consensus::Params ¶ms, Consensus::UpgradeIndex idx)
Returns true if the given network upgrade is active as of the given block height.
std::string FormatMoney(const CAmount &n, bool fPlus)
Money parsing/formatting utilities.
std::unique_ptr< CZerocoinDB > zerocoinDB
Global variable that points to the zerocoin database (protected by cs_main)
bool GetTransaction(const uint256 &hash, CTransactionRef &txOut, uint256 &hashBlock, bool fAllowSlow, CBlockIndex *blockIndex)
Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock.
bool GetOutput(const uint256 &hash, unsigned int index, CValidationState &state, CTxOut &out)
Retrieve an output (from memory pool, or from disk, if possible)
CChain chainActive
The currently-connected chain of blocks (protected by cs_main).
bool ParseAndValidateZerocoinSpends(const Consensus::Params &consensus, const CTransaction &tx, int chainHeight, CValidationState &state, std::vector< std::pair< CBigNum, uint256 >> &vSpendsRet)
bool IsSerialInBlockchain(const CBigNum &bnSerial, int &nHeightTx)
bool ContextualCheckZerocoinSpend(const CTransaction &tx, const libzerocoin::CoinSpend *spend, int nHeight)
bool ContextualCheckZerocoinTx(const CTransactionRef &tx, CValidationState &state, const Consensus::Params &consensus, int nHeight, bool isMined)
bool isBlockBetweenFakeSerialAttackRange(int nHeight)
bool ContextualCheckZerocoinSpendNoSerialCheck(const CTransaction &tx, const libzerocoin::CoinSpend *spend, int nHeight)
bool CheckPublicCoinSpendEnforced(int blockHeight, bool isPublicSpend)