Files
agrarian/src/test/zerocoin_implementation_tests.cpp
T
2022-02-03 23:45:47 -08:00

512 lines
23 KiB
C++

// Copyright (c) 2017-2019 The PIVX developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "libzerocoin/Denominations.h"
#include "amount.h"
#include "chainparams.h"
#include "main.h"
#include "txdb.h"
#include "zagr/deterministicmint.h"
#include "key.h"
#include "zagr/accumulatorcheckpoints.h"
#include "libzerocoin/bignum.h"
#include <boost/test/unit_test.hpp>
#include <iostream>
#include <zagr/accumulators.h>
#include "wallet/wallet.h"
#include "zagr/zagrwallet.h"
#include "zagrchain.h"
#include "test_agrarian.h"
using namespace libzerocoin;
extern bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx);
BOOST_FIXTURE_TEST_SUITE(zerocoin_implementation_tests, TestingSetup)
BOOST_AUTO_TEST_CASE(zcparams_test)
{
cout << "Running zcparams_test...\n";
bool fPassed = true;
try{
SelectParams(CBaseChainParams::MAIN);
ZerocoinParams *ZCParams = Params().Zerocoin_Params(false);
(void)ZCParams;
} catch(std::exception& e) {
fPassed = false;
std::cout << e.what() << "\n";
}
BOOST_CHECK(fPassed);
}
std::string zerocoinModulus = "25195908475657893494027183240048398571429282126204032027777137836043662020707595556264018525880784"
"4069182906412495150821892985591491761845028084891200728449926873928072877767359714183472702618963750149718246911"
"6507761337985909570009733045974880842840179742910064245869181719511874612151517265463228221686998754918242243363"
"7259085141865462043576798423387184774447920739934236584823824281198163815010674810451660377306056201619676256133"
"8441436038339044149526344321901146575444541784240209246165157233507787077498171257724679629263863563732899121548"
"31438167899885040445364023527381951378636564391212010397122822120720357";
//ZQ_ONE mints
std::string rawTx1 = "0100000001983d5fd91685bb726c0ebc3676f89101b16e663fd896fea53e19972b95054c49000000006a473044022010fbec3e78f9c46e58193d481caff715ceb984df44671d30a2c0bde95c54055f0220446a97d9340da690eaf2658e5b2bf6a0add06f1ae3f1b40f37614c7079ce450d012103cb666bd0f32b71cbf4f32e95fa58e05cd83869ac101435fcb8acee99123ccd1dffffffff0200e1f5050000000086c10280004c80c3a01f94e71662f2ae8bfcd88dfc5b5e717136facd6538829db0c7f01e5fd793cccae7aa1958564518e0223d6d9ce15b1e38e757583546e3b9a3f85bd14408120cd5192a901bb52152e8759fdd194df230d78477706d0e412a66398f330be38a23540d12ab147e9fb19224913f3fe552ae6a587fb30a68743e52577150ff73042c0f0d8f000000001976a914d6042025bd1fff4da5da5c432d85d82b3f26a01688ac00000000";
std::string rawTxpub1 = "473ff507157523e74680ab37f586aae52e53f3f912492b19f7e14ab120d54238ae30b338f39662a410e6d707784d730f24d19dd9f75e85221b51b902a19d50c120844d15bf8a3b9e346355857e7381e5be19c6d3d22e01845565819aae7cacc93d75f1ef0c7b09d823865cdfa3671715e5bfc8dd8fc8baef26216e7941fa0c3";
std::string rawTxRand1 = "9fc222b16be09eb88affbdfbcc02d1c8b28f5e843c72eb06c89dd7aff0c60838";
std::string rawTxSerial1 = "b87754b165892c0f9634e3d03780ede24824125249cb8dfd4ad2c0be055cbead";
std::string rawTx2 = "01000000018c52504b2822c39dd7f4bd93e30562dc9d246e0b0dd4ee401ec2c24e9378be12000000006b483045022100e2628dbcd284dd4858e2c2d8e2d2d31eb222773b3026d39c79c489f5daf4ae2302200e0b1cb9a6d534dc86ea33afb8153a5a4c7cd4fb497c889fb991fbac8bf86802012103836a4868020f52f2ab9e5ec3634d2cd38794677fab47ae7a7128ea8102972ae0ffffffff022c0f0d8f000000001976a914e2e8e36a1a35da051341775315b1168494921acd88ac00e1f5050000000086c10280004c809d49caa17c3f1fb8bc93eabf54462c8ad1717ab646c8130ca0863ca5613f34751445cd7bde8ef1dd833645c7c205dd9b36171dc25209f46b04a34b5e06caa655eea9bd95b46f7d03ae60a97961dd6632c1050090ec1b6748199f0721eeec0822dd288c663020dd88ecda7c8abf8a409fa5c500c4188e52bfbe2ca77ce7b2700700000000";
std::string rawTxpub2 = "770b2e77ca72cbebf528e18c400c5a59f408abf8a7cdaec88dd2030668c28dd2208ecee21079f1948671bec900005c13266dd6179a960ae037d6fb495bda9ee55a6ca065e4ba3046bf40952c21d17369bdd05c2c7453683ddf18ede7bcd451475343f61a53c86a00c13c846b67a71d18a2c4654bfea93bcb81f3f7ca1ca499d";
std::string rawTxRand2 = "23040b1d889ca4a41cf50b88a380f3f3acffac750e221a268fedf700f063a886";
std::string rawTxSerial2 = "37393797cb39e5f22bdc4fba8108edb5ea497ba0d22aba0781e58a8555df285c";
std::string rawTx3 = "01000000014651d7ed09c01d26679dd8ad1ee1f704f63167544ca48bdd3b4577444d540514010000006a47304402207995f8e30a87b74f36146d80ab02198319240a2eb3f93018c740e91b6812ff23022002677250aa9f9c7b6c1258647b0b0c03f89c7495b82b9c4dd2dcdb0ced82412801210236e3e30dbb1d62c8872413b2a771cd611b8042dfb5d06feb6805ba934ba534ffffffffff0200e1f5050000000086c10280004c803dac1997d38ee8650bb87fae490f4684a7b023744c95cd5ef025bc7f4d1414aff96947cebf342cfbfaf217ec0088e489d722d494409494a011a452af55a8cd4d2cef97f3b0307b66238623ab02b148a9e20f36782c8b7ea47c0c0b8226ddb91ee8f1f94c8c04df5c834993f27175b20b1da99d8338c674b1741a696c54def8012c0f0d8f000000001976a914c7f81b8e5650af548f5d56ef064da5c2d1ee09ae88ac00000000";
std::string rawTxpub3 = "1f8de546c691a74b174c638839da91d0bb27571f29349835cdf048c4cf9f1e81eb9dd26820b0c7ca47e8b2c78360fe2a948b102ab238623667b30b0f397ef2c4dcda855af52a411a094944094d422d789e48800ec17f2fafb2c34bfce4769f9af14144d7fbc25f05ecd954c7423b0a784460f49ae7fb80b65e88ed39719ac3d";
std::string rawTxRand3 = "1953c2919d658c3f654566400ace91563105ad5acc4e4151bca1e762c0877d7b";
std::string rawTxSerial3 = "3abf349844720512325d129c95402edbc85d86fff89632a05dc18970560047a5";
std::vector<std::pair<std::string, std::string> > vecRawMints = {std::make_pair(rawTx1, rawTxSerial1), std::make_pair(rawTx2, rawTxSerial2), std::make_pair(rawTx3, rawTxSerial3)};
//create a zerocoin mint from vecsend
BOOST_AUTO_TEST_CASE(checkzerocoinmint_test)
{
cout << "generating privkeys\n";
//generate a privkey
CKey key;
key.MakeNewKey(true);
CPrivKey privkey = key.GetPrivKey();
//generate pubkey hash/serial
CPubKey pubkey = key.GetPubKey();
uint256 nSerial = Hash(pubkey.begin(), pubkey.end());
CBigNum bnSerial(nSerial);
//make sure privkey import to new keypair makes the same serial
CKey key2;
key2.SetPrivKey(privkey, true);
CPubKey pubkey2 = key2.GetPubKey();
uint256 nSerial2 = Hash(pubkey2.begin(), pubkey2.end());
CBigNum bnSerial2(nSerial2);
BOOST_CHECK_MESSAGE(bnSerial == bnSerial2, "Serials do not match!");
cout << "Running check_zerocoinmint_test...\n";
CTransaction tx;
BOOST_CHECK(DecodeHexTx(tx, rawTx1));
CValidationState state;
bool fFoundMint = false;
for(unsigned int i = 0; i < tx.vout.size(); i++){
if(tx.vout[i].IsZerocoinMint()) {
BOOST_CHECK(CheckZerocoinMint(tx.GetHash(), tx.vout[i], state, true));
fFoundMint = true;
}
}
BOOST_CHECK(fFoundMint);
}
bool CheckZerocoinSpendNoDB(const CTransaction tx, string& strError)
{
//max needed non-mint outputs should be 2 - one for redemption address and a possible 2nd for change
if (tx.vout.size() > 2){
int outs = 0;
for (const CTxOut& out : tx.vout) {
if (out.IsZerocoinMint())
continue;
outs++;
}
if (outs > 2) {
strError = "CheckZerocoinSpend(): over two non-mint outputs in a zerocoinspend transaction";
return false;
}
}
//compute the txout hash that is used for the zerocoinspend signatures
CMutableTransaction txTemp;
for (const CTxOut& out : tx.vout) {
txTemp.vout.push_back(out);
}
// uint256 hashTxOut = txTemp.GetHash();
bool fValidated = false;
set<CBigNum> serials;
list<CoinSpend> vSpends;
CAmount nTotalRedeemed = 0;
for (const CTxIn& txin : tx.vin) {
//only check txin that is a zcspend
if (!txin.IsZerocoinSpend())
continue;
// extract the CoinSpend from the txin
std::vector<char, zero_after_free_allocator<char> > dataTxIn;
dataTxIn.insert(dataTxIn.end(), txin.scriptSig.begin() + 4, txin.scriptSig.end());
CDataStream serializedCoinSpend(dataTxIn, SER_NETWORK, PROTOCOL_VERSION);
libzerocoin::ZerocoinParams* paramsAccumulator = Params().Zerocoin_Params(false);
CoinSpend newSpend(Params().Zerocoin_Params(true), paramsAccumulator, serializedCoinSpend);
vSpends.push_back(newSpend);
//check that the denomination is valid
if (newSpend.getDenomination() == ZQ_ERROR) {
strError = "Zerocoinspend does not have the correct denomination";
return false;
}
//check that denomination is what it claims to be in nSequence
if (newSpend.getDenomination() != txin.nSequence) {
strError = "Zerocoinspend nSequence denomination does not match CoinSpend";
}
//make sure the txout has not changed
// if (newSpend.getTxOutHash() != hashTxOut) {
// strError = "Zerocoinspend does not use the same txout that was used in the SoK";
// return false;
// }
// //see if we have record of the accumulator used in the spend tx
// CBigNum bnAccumulatorValue = 0;
// if (!GetAccumulatorValueFromChecksum(newSpend.getAccumulatorChecksum(), true, bnAccumulatorValue)) {
// strError = "Zerocoinspend could not find accumulator associated with checksum";
// return false;
// }
// Accumulator accumulator(Params().Zerocoin_Params(true), newSpend.getDenomination(), bnAccumulatorValue);
// //Check that the coin is on the accumulator
// if (!newSpend.Verify(accumulator)) {
// strError = "CheckZerocoinSpend(): zerocoin spend did not verify";
// return false;
// }
if (serials.count(newSpend.getCoinSerialNumber())) {
strError = "Zerocoinspend serial is used twice in the same tx";
return false;
}
serials.insert(newSpend.getCoinSerialNumber());
//cannot check this without database
// if(!IsZerocoinSpendUnknown(newSpend, tx.GetHash(), state))
// return state.DoS(100, error("Zerocoinspend is already known"));
//make sure that there is no over redemption of coins
nTotalRedeemed += ZerocoinDenominationToAmount(newSpend.getDenomination());
fValidated = true;
}
if (nTotalRedeemed < tx.GetValueOut()) {
strError = "Transaction spend more than was redeemed in zerocoins";
return false;
}
return fValidated;
}
BOOST_AUTO_TEST_CASE(checkzerocoinspend_test)
{
CBigNum bnTrustedModulus = 0;
if (!bnTrustedModulus)
bnTrustedModulus.SetDec(zerocoinModulus);
libzerocoin::ZerocoinParams zerocoinParams = libzerocoin::ZerocoinParams(bnTrustedModulus);
cout << "Running check_zerocoinspend_test...\n";
//load our serialized pubcoin
CBigNum bnpubcoin;
BOOST_CHECK_MESSAGE(bnpubcoin.SetHexBool(rawTxpub1), "Failed to set CBigNum from hex string");
PublicCoin pubCoin(Params().Zerocoin_Params(true), bnpubcoin, CoinDenomination::ZQ_ONE);
BOOST_CHECK_MESSAGE(pubCoin.validate(), "Failed to validate pubCoin created from hex string");
//initialize and Accumulator and AccumulatorWitness
Accumulator accumulator(Params().Zerocoin_Params(false), CoinDenomination::ZQ_ONE);
AccumulatorWitness witness(Params().Zerocoin_Params(false), accumulator, pubCoin);
//populate the witness and accumulators
CValidationState state;
for(pair<string, string> raw : vecRawMints) {
CTransaction tx;
BOOST_CHECK_MESSAGE(DecodeHexTx(tx, raw.first), "Failed to deserialize hex transaction");
for(const CTxOut& out : tx.vout){
if(out.IsZerocoinMint()) {
PublicCoin publicCoin(Params().Zerocoin_Params(true));
BOOST_CHECK_MESSAGE(TxOutToPublicCoin(out, publicCoin, state), "Failed to convert CTxOut " << out.ToString() << " to PublicCoin");
accumulator += publicCoin;
witness += publicCoin;
}
}
}
// Create a New Zerocoin with specific denomination given by pubCoin
PrivateCoin privateCoin(Params().Zerocoin_Params(true), pubCoin.getDenomination());
privateCoin.setPublicCoin(pubCoin);
CBigNum bn = 0;
bn.SetHex(rawTxRand1);
privateCoin.setRandomness(bn);
CBigNum bn2 = 0;
bn2.SetHex(rawTxSerial1);
privateCoin.setSerialNumber(bn2);
privateCoin.setVersion(1);
//Get the checksum of the accumulator we use for the spend and also add it to our checksum map
uint32_t nChecksum = GetChecksum(accumulator.getValue());
//AddAccumulatorChecksum(nChecksum, accumulator.getValue(), true);
CoinSpend coinSpend(Params().Zerocoin_Params(true), Params().Zerocoin_Params(false), privateCoin, accumulator, nChecksum, witness, 0, SpendType::SPEND);
cout << coinSpend.ToString() << endl;
BOOST_CHECK_MESSAGE(coinSpend.Verify(accumulator), "Coinspend construction failed to create valid proof");
CBigNum serial = coinSpend.getCoinSerialNumber();
BOOST_CHECK_MESSAGE(serial, "Serial Number can't be 0");
CoinDenomination denom = coinSpend.getDenomination();
BOOST_CHECK_MESSAGE(denom == pubCoin.getDenomination(), "Spend denomination must match original pubCoin");
BOOST_CHECK_MESSAGE(coinSpend.Verify(accumulator), "CoinSpend object failed to validate");
//serialize the spend
CDataStream serializedCoinSpend2(SER_NETWORK, PROTOCOL_VERSION);
bool fSerialize = true;
try {
serializedCoinSpend2 << coinSpend;
} catch (...) {
fSerialize = false;
}
BOOST_CHECK_MESSAGE(fSerialize, "failed to serialize coinspend object");
std::vector<unsigned char> data(serializedCoinSpend2.begin(), serializedCoinSpend2.end());
/** Check valid spend */
CTxIn newTxIn;
newTxIn.nSequence = 1;
newTxIn.scriptSig = CScript() << OP_ZEROCOINSPEND << data.size();
newTxIn.scriptSig.insert(newTxIn.scriptSig.end(), data.begin(), data.end());
newTxIn.prevout.SetNull();
// Deserialize the CoinSpend intro a fresh object
std::vector<char, zero_after_free_allocator<char> > dataTxIn;
dataTxIn.insert(dataTxIn.end(), newTxIn.scriptSig.begin() + 4, newTxIn.scriptSig.end());
CDataStream serializedCoinSpend(dataTxIn, SER_NETWORK, PROTOCOL_VERSION);
//old params for the V1 generated coin, new params for the accumulator. Emulates main-net transition.
CoinSpend spend1(Params().Zerocoin_Params(true), Params().Zerocoin_Params(false), serializedCoinSpend);
BOOST_CHECK_MESSAGE(spend1.Verify(accumulator), "Failed deserialized check of CoinSpend");
CScript script;
CTxOut txOut(1 * COIN, script);
CTransaction txNew;
txNew.vin.push_back(newTxIn);
txNew.vout.push_back(txOut);
CTransaction txMintFrom;
BOOST_CHECK_MESSAGE(DecodeHexTx(txMintFrom, rawTx1), "Failed to deserialize hex transaction");
string strError = "";
if (!CheckZerocoinSpendNoDB(txNew, strError)) {
cout << state.GetRejectCode() << endl;
BOOST_CHECK_MESSAGE(false, strError);
}
/**check an overspend*/
CTxOut txOutOverSpend(100 * COIN, script);
CTransaction txOverSpend;
txOverSpend.vin.push_back(newTxIn);
txOverSpend.vout.push_back(txOutOverSpend);
strError = "";
CheckZerocoinSpendNoDB(txOverSpend, strError);
string str = "Failed to detect overspend. Error Message: " + strError;
BOOST_CHECK_MESSAGE(strError == "Transaction spend more than was redeemed in zerocoins", str);
cout << "checking v2 spend\n";
CMutableTransaction tx;
uint256 txHash = 0;
CTxIn in(txHash, 0);
tx.vin.emplace_back(in);
// Create a New Zerocoin with specific denomination given by pubCoin
PrivateCoin privateCoin_v2(Params().Zerocoin_Params(false), CoinDenomination::ZQ_ONE);
CKey key;
key.SetPrivKey(privateCoin.getPrivKey(), true);
BOOST_CHECK_MESSAGE(key.IsValid(), "Key is not valid");
PublicCoin pubcoin_v2 = privateCoin_v2.getPublicCoin();
//initialize and Accumulator and AccumulatorWitness
Accumulator accumulator_v2(Params().Zerocoin_Params(false), CoinDenomination::ZQ_ONE);
AccumulatorWitness witness_v2(Params().Zerocoin_Params(false), accumulator_v2, pubcoin_v2);
//populate the witness and accumulators - with old v1 params
int64_t nTimeStart = GetTimeMillis();
CValidationState state_v2;
for(int i = 0; i < 5; i++) {
PrivateCoin privTemp(Params().Zerocoin_Params(true), CoinDenomination::ZQ_ONE);
PublicCoin pubTemp = privTemp.getPublicCoin();
accumulator_v2 += pubTemp;
witness_v2 += pubTemp;
}
cout << (GetTimeMillis() - nTimeStart)/5 << "ms per mint\n";
accumulator_v2 += pubcoin_v2;
//Get the checksum of the accumulator we use for the spend and also add it to our checksum map
uint32_t nChecksum_v2 = GetChecksum(accumulator_v2.getValue());
//AddAccumulatorChecksum(nChecksum_v2, accumulator_v2.getValue(), true);
uint256 ptxHash = CBigNum::randKBitBignum(256).getuint256();
CoinSpend coinSpend_v2(Params().Zerocoin_Params(false), Params().Zerocoin_Params(false), privateCoin_v2, accumulator_v2, nChecksum_v2, witness_v2, ptxHash, SpendType::SPEND);
BOOST_CHECK_MESSAGE(coinSpend_v2.HasValidSerial(Params().Zerocoin_Params(false)), "coinspend_v2 does not have a valid serial");
BOOST_CHECK_MESSAGE(coinSpend_v2.Verify(accumulator_v2), "coinspend_v2 failed to verify");
BOOST_CHECK_MESSAGE(coinSpend_v2.HasValidSignature(), "coinspend_v2 does not have valid signature");
BOOST_CHECK_MESSAGE(coinSpend_v2.getVersion() == 2, "coinspend_v2 version is wrong");
BOOST_CHECK_MESSAGE(coinSpend_v2.getPubKey() == privateCoin_v2.getPubKey(), "pub keys do not match");
}
BOOST_AUTO_TEST_CASE(setup_exceptions_test)
{
CBigNum bnTrustedModulus = 0;
if (!bnTrustedModulus)
bnTrustedModulus.SetDec(zerocoinModulus);
libzerocoin::ZerocoinParams zerocoinParams = libzerocoin::ZerocoinParams(bnTrustedModulus);
cout << "Running check_unitialized parameters,etc for setup exceptions...\n";
CBigNum bnpubcoin;
BOOST_CHECK(bnpubcoin.SetHexBool(rawTxpub1));
// Check Modulus > 1023 Exception
try {
ZerocoinParams ZCParams(bnpubcoin);
BOOST_CHECK_MESSAGE(false, "Didn't catch exception: ZerocoinException: Modulus must be at least 1023 bit");
}
catch (...) {
BOOST_CHECK_MESSAGE(true, "Caught exception: ZerocoinException: Modulus must be at least 1023 bit");
}
// Check Security Level < 80 Exception
try {
ZerocoinParams ZCParams(bnpubcoin,1);
BOOST_CHECK_MESSAGE(false, "Didn't catch exception: Security Level >= 80");
}
catch (...) {
BOOST_CHECK_MESSAGE(true, "Caught exception: ZerocoinException: Security Level >= 80");
}
// Check unitialized params Exception for PublicCoin
try {
zerocoinParams.initialized = false;
PublicCoin pubCoin(&zerocoinParams);
BOOST_CHECK_MESSAGE(false, "Didn't catch exception checking for uninitialized Params");
}
catch (...) {
BOOST_CHECK_MESSAGE(true, "Caught exception checking for initalized Params");
}
// Check unitialized params Exception for PublicCoin (alternate constructor)
try {
zerocoinParams.initialized = false;
PublicCoin pubCoin(&zerocoinParams);
BOOST_CHECK_MESSAGE(false, "Didn't catch exception checking for uninitialized Params");
}
catch (...) {
BOOST_CHECK_MESSAGE(true, "Caught exception checking for initalized Params");
}
// Check unitialized params Exception for PrivateCoin
try {
zerocoinParams.initialized = false;
PrivateCoin privCoin(&zerocoinParams, CoinDenomination::ZQ_ONE);
BOOST_CHECK_MESSAGE(false, "Didn't catch exception checking for uninitialized Params");
}
catch (...) {
BOOST_CHECK_MESSAGE(true, "Caught exception checking for initalized Params");
}
}
BOOST_AUTO_TEST_CASE(checksum_tests)
{
cout << "Running checksum_tests\n";
uint256 checksum;
uint32_t c1 = 0xa3219ef1;
uint32_t c2 = 0xabcdef00;
uint32_t c3 = 0x101029f3;
uint32_t c4 = 0xaaaaaeee;
uint32_t c5 = 0xffffffff;
uint32_t c6 = 0xbbbbbbbb;
uint32_t c7 = 0x11111111;
uint32_t c8 = 0xeeeeeeee;
vector<uint32_t> vChecksums {c1,c2,c3,c4,c5,c6,c7,c8};
for(uint32_t c : vChecksums)
checksum = checksum << 32 | c;
BOOST_CHECK_MESSAGE(checksum == uint256("a3219ef1abcdef00101029f3aaaaaeeeffffffffbbbbbbbb11111111eeeeeeee"), "checksum not properly concatenated");
int i = 0;
for (auto& denom : zerocoinDenomList){
uint32_t checksumParsed = ParseChecksum(checksum, denom);
BOOST_CHECK_MESSAGE(checksumParsed == vChecksums[i], "checksum parse failed");
i++;
}
}
BOOST_AUTO_TEST_CASE(test_checkpoints)
{
BOOST_CHECK_MESSAGE(AccumulatorCheckpoints::LoadCheckpoints("main"), "failed to load checkpoints");
BOOST_CHECK_MESSAGE(AccumulatorCheckpoints::mapCheckpoints.at(1050020)
.at(libzerocoin::CoinDenomination::ZQ_FIVE_THOUSAND)
.GetHex() == "fad7cf992b67792695619224fbbe311c6e60bf80d5bc1680fd9e32b5b3f00f373c9305c72c82bfaf1ce56adb617dc71bb8ddaf61326858ae4b01c3acf443bc7d22d4d2c77704b44fbe4f4fd260f13e0e12e82c531c390e72770e1d444e0877844d35a76c1e45072ddf02e101cf9c0a05a125f19ac5205ee1216732f4040cc3e8a68528685f2f39325efb2b7ba4d681fe13aaabb80ef07d8de8ef883a07e0a4f9771e8c370924fe4959de3c2a6e6e7ad74b12dd7e666765d7d660febe4d4cab3f49cb33cb51e44f756eef609184d8eeeb1c4dfe13b123251166c877d8e992f60cefd568644918c3617aec4d5564a9fe008540add903b9739973838d667721f8d", "does not match");
}
BOOST_AUTO_TEST_CASE(deterministic_tests)
{
SelectParams(CBaseChainParams::UNITTEST);
cout << "Testing deterministic minting\n";
uint256 seedMaster("3a1947364362e2e7c073b386869c89c905c0cf462448ffd6c2021bd03ce689f6");
string strWalletFile = "unittestwallet.dat";
CWalletDB walletdb(strWalletFile, "cr+");
CWallet wallet(strWalletFile);
CzAGRWallet zWallet(wallet.strWalletFile);
zWallet.SetMasterSeed(seedMaster);
wallet.setZWallet(&zWallet);
int64_t nTimeStart = GetTimeMillis();
CoinDenomination denom = CoinDenomination::ZQ_FIFTY;
std::vector<PrivateCoin> vCoins;
int nTests = 50;
for (int i = 0; i < nTests; i++) {
PrivateCoin coin(Params().Zerocoin_Params(false), denom, false);
CDeterministicMint dMint;
zWallet.GenerateDeterministicZAGR(denom, coin, dMint);
vCoins.emplace_back(coin);
}
int64_t nTotalTime = GetTimeMillis() - nTimeStart;
cout << "Total time:" << nTotalTime << "ms. Per Deterministic Mint:" << (nTotalTime/nTests) << "ms" << endl;
cout << "Checking that mints are valid" << endl;
CDataStream ss(SER_GETHASH, 0);
for (PrivateCoin& coin : vCoins) {
BOOST_CHECK_MESSAGE(coin.IsValid(), "Generated Mint is not valid");
ss << coin.getPublicCoin().getValue();
}
cout << "Checking that mints are deterministic: sha256 checksum=";
uint256 hash = Hash(ss.begin(), ss.end());
cout << hash.GetHex() << endl;
BOOST_CHECK_MESSAGE(hash == uint256("c90c225f2cbdee5ef053b1f9f70053dd83724c58126d0e1b8425b88091d1f73f"), "minting determinism isn't as expected");
}
BOOST_AUTO_TEST_SUITE_END()