diff --git a/src/test/zerocoin_transactions_tests.cpp b/src/test/zerocoin_transactions_tests.cpp index 7b1c2cf7c4443..7b5067780f83f 100644 --- a/src/test/zerocoin_transactions_tests.cpp +++ b/src/test/zerocoin_transactions_tests.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "libzerocoin/Denominations.h" +#include "libzerocoin/Coin.h" #include "amount.h" #include "chainparams.h" #include "coincontrol.h" @@ -10,6 +11,7 @@ #include "wallet/wallet.h" #include "wallet/walletdb.h" #include "txdb.h" +#include "zpiv/zpivmodule.h" #include #include @@ -53,4 +55,62 @@ BOOST_AUTO_TEST_CASE(zerocoin_spend_test) } +BOOST_AUTO_TEST_CASE(zerocoin_public_spend_test) +{ + SelectParams(CBaseChainParams::MAIN); + ZerocoinParams *ZCParams = Params().Zerocoin_Params(false); + (void)ZCParams; + + ZPIVModule zpivModule; + + PrivateCoin privCoin(ZCParams, libzerocoin::CoinDenomination::ZQ_ONE, true); + const CPrivKey privKey = privCoin.getPrivKey(); + + CZerocoinMint mint = CZerocoinMint( + privCoin.getPublicCoin().getDenomination(), + privCoin.getPublicCoin().getValue(), + privCoin.getRandomness(), + privCoin.getSerialNumber(), + false, + privCoin.getVersion(), + nullptr); + mint.SetPrivKey(privKey); + + + // Mint tx + CTransaction prevTx; + + CScript scriptSerializedCoin = CScript() + << OP_ZEROCOINMINT << privCoin.getPublicCoin().getValue().getvch().size() << privCoin.getPublicCoin().getValue().getvch(); + CTxOut out = CTxOut(libzerocoin::ZerocoinDenominationToAmount(privCoin.getPublicCoin().getDenomination()), scriptSerializedCoin); + prevTx.vout.push_back(out); + + mint.SetOutputIndex(0); + mint.SetTxHash(prevTx.GetHash()); + + // Spend tx + CMutableTransaction tx; + tx.vout.resize(1); + tx.vout[0].nValue = 1*CENT; + tx.vout[0].scriptPubKey = GetScriptForDestination(CBitcoinAddress("D9Ti4LEhF1n6dR2hGd2SyNADD51AVgva6q").Get()); + + CTxIn in; + if (!zpivModule.createInput(in, mint, tx.GetHash())){ + BOOST_CHECK_MESSAGE(false, "Failed to create zc input"); + } + + PublicCoinSpend publicSpend(ZCParams); + if (!zpivModule.validateInput(in, out, tx, publicSpend)){ + BOOST_CHECK_MESSAGE(false, "Failed to validate zc input"); + } + + PublicCoinSpend publicSpendTest(ZCParams); + BOOST_CHECK_MESSAGE(zpivModule.parseCoinSpend(in, tx, out, publicSpendTest), "Failed to parse public spend"); + libzerocoin::CoinSpend *spend = &publicSpendTest; + + BOOST_CHECK_MESSAGE(publicSpendTest.HasValidSignature(), "Failed to validate public spend signature"); + BOOST_CHECK_MESSAGE(spend->HasValidSignature(), "Failed to validate spend signature"); + +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/zpiv/zerocoin.h b/src/zpiv/zerocoin.h index 86a30fb9f8cee..822cb4624fcf9 100644 --- a/src/zpiv/zerocoin.h +++ b/src/zpiv/zerocoin.h @@ -43,6 +43,7 @@ class CZerocoinMint CBigNum randomness; CBigNum serialNumber; uint256 txid; + int outputIndex; CPrivKey privkey; uint8_t version; bool isUsed; @@ -104,6 +105,9 @@ class CZerocoinMint void SetPrivKey(const CPrivKey& privkey) { this->privkey = privkey; } bool GetKeyPair(CKey& key) const; + unsigned int GetOutputIndex() { return this->outputIndex; } + void SetOutputIndex(unsigned int index) {this->outputIndex = index; } + inline bool operator <(const CZerocoinMint& a) const { return GetHeight() < a.GetHeight(); } CZerocoinMint(const CZerocoinMint& other) { @@ -186,6 +190,7 @@ class CZerocoinSpend libzerocoin::CoinDenomination denomination; unsigned int nAccumulatorChecksum; int nMintCount; //memory only - the amount of mints that belong to the accumulator this is spent from + bool publicSpend = false; public: CZerocoinSpend() @@ -202,6 +207,16 @@ class CZerocoinSpend this->nAccumulatorChecksum = nAccumulatorChecksum; } + CZerocoinSpend(CBigNum coinSerial, uint256 hashTx, CBigNum pubCoin, libzerocoin::CoinDenomination denomination, unsigned int nAccumulatorChecksum, bool isPublicSpend) + { + this->coinSerial = coinSerial; + this->hashTx = hashTx; + this->pubCoin = pubCoin; + this->denomination = denomination; + this->nAccumulatorChecksum = nAccumulatorChecksum; + this->publicSpend = isPublicSpend; + } + void SetNull() { coinSerial = 0; @@ -219,6 +234,7 @@ class CZerocoinSpend uint256 GetHash() const; void SetMintCount(int nMintsAdded) { this->nMintCount = nMintsAdded; } int GetMintCount() const { return nMintCount; } + bool IsPublicSpend() const { return publicSpend; } ADD_SERIALIZE_METHODS;