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

523 lines
22 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 "amount.h"
#include "chainparams.h"
#include "coincontrol.h"
#include "denomination_functions.h"
#include "main.h"
#include "txdb.h"
#include "wallet/wallet.h"
#include "wallet/walletdb.h"
#include "test/test_agrarian.h"
#include <boost/test/unit_test.hpp>
#include <iostream>
using namespace libzerocoin;
BOOST_FIXTURE_TEST_SUITE(zerocoin_denom_tests, BasicTestingSetup)
//translation from agrarian quantity to zerocoin denomination
BOOST_AUTO_TEST_CASE(amount_to_denomination_test)
{
cout << "Running amount_to_denomination_test...\n";
//valid amount (min edge)
CAmount amount = 1 * COIN;
BOOST_CHECK_MESSAGE(AmountToZerocoinDenomination(amount) == ZQ_ONE, "For COIN denomination should be ZQ_ONE");
//valid amount (max edge)
CAmount amount1 = 5000 * COIN;
BOOST_CHECK_MESSAGE(AmountToZerocoinDenomination(amount1) == ZQ_FIVE_THOUSAND, "For 5000*COIN denomination should be ZQ_ONE");
//invalid amount (too much)
CAmount amount2 = 7000 * COIN;
BOOST_CHECK_MESSAGE(AmountToZerocoinDenomination(amount2) == ZQ_ERROR, "For 7000*COIN denomination should be Invalid -> ZQ_ERROR");
//invalid amount (not enough)
CAmount amount3 = 1;
BOOST_CHECK_MESSAGE(AmountToZerocoinDenomination(amount3) == ZQ_ERROR, "For 1 denomination should be Invalid -> ZQ_ERROR");
}
BOOST_AUTO_TEST_CASE(denomination_to_value_test)
{
cout << "Running ZerocoinDenominationToValue_test...\n";
int64_t Value = 1 * COIN;
CoinDenomination denomination = ZQ_ONE;
BOOST_CHECK_MESSAGE(ZerocoinDenominationToAmount(denomination) == Value, "Wrong Value - should be 1");
Value = 10 * COIN;
denomination = ZQ_TEN;
BOOST_CHECK_MESSAGE(ZerocoinDenominationToAmount(denomination) == Value, "Wrong Value - should be 10");
Value = 50 * COIN;
denomination = ZQ_FIFTY;
BOOST_CHECK_MESSAGE(ZerocoinDenominationToAmount(denomination) == Value, "Wrong Value - should be 50");
Value = 500 * COIN;
denomination = ZQ_FIVE_HUNDRED;
BOOST_CHECK_MESSAGE(ZerocoinDenominationToAmount(denomination) == Value, "Wrong Value - should be 500");
Value = 100 * COIN;
denomination = ZQ_ONE_HUNDRED;
BOOST_CHECK_MESSAGE(ZerocoinDenominationToAmount(denomination) == Value, "Wrong Value - should be 100");
Value = 0 * COIN;
denomination = ZQ_ERROR;
BOOST_CHECK_MESSAGE(ZerocoinDenominationToAmount(denomination) == Value, "Wrong Value - should be 0");
}
BOOST_AUTO_TEST_CASE(zerocoin_spend_test241)
{
const int nMaxNumberOfSpends = 4;
const bool fMinimizeChange = false;
const int DenomAmounts[] = {1, 2, 3, 4, 0, 0, 0, 0};
CAmount nSelectedValue;
std::list<CMintMeta> listMints;
std::map<CoinDenomination, CAmount> mapDenom;
int j = 0;
CAmount nTotalAmount = 0;
int CoinsHeld = 0;
// Create a set of Minted coins that fits profile given by DenomAmounts
// Also setup Map array corresponding to DenomAmount which is the current set of coins available
for (const auto& denom : zerocoinDenomList) {
for (int i = 0; i < DenomAmounts[j]; i++) {
CAmount currentAmount = ZerocoinDenominationToAmount(denom);
nTotalAmount += currentAmount;
CBigNum value;
CBigNum rand;
CBigNum serial = CBigNum::randKBitBignum(256);
bool isUsed = false;
CMintMeta meta;
meta.denom = denom;
meta.hashPubcoin = GetPubCoinHash(value);
meta.hashSerial = GetSerialHash(serial);
meta.isUsed = isUsed;
meta.nVersion = 1;
listMints.push_back(meta);
}
mapDenom.insert(std::pair<CoinDenomination, CAmount>(denom, DenomAmounts[j]));
j++;
}
CoinsHeld = nTotalAmount / COIN;
std::cout << "Curremt Amount held = " << CoinsHeld << ": ";
// Show what we have
j = 0;
for (const auto& denom : zerocoinDenomList)
std::cout << DenomAmounts[j++] << "*" << ZerocoinDenominationToAmount(denom) / COIN << " + ";
std::cout << "\n";
// For DenomAmounts[] = {1,2,3,4,0,0,0,0}; we can spend up to 200 without requiring more than 4 Spends
// Amounts above this can not be met
CAmount MaxLimit = 200;
CAmount OneCoinAmount = ZerocoinDenominationToAmount(ZQ_ONE);
CAmount nValueTarget = OneCoinAmount;
int nCoinsReturned;
int nNeededSpends = 0; // Number of spends which would be needed if selection failed
bool fDebug = 0;
// Go through all possible spend between 1 and 241 and see if it's possible or not
for (int i = 0; i < CoinsHeld; i++) {
std::vector<CMintMeta> vSpends = SelectMintsFromList(nValueTarget, nSelectedValue,
nMaxNumberOfSpends,
fMinimizeChange,
nCoinsReturned,
listMints,
mapDenom,
nNeededSpends);
if (fDebug) {
if (vSpends.size() > 0) {
std::cout << "SUCCESS : Coins = " << nValueTarget / COIN << " # spends used = " << vSpends.size()
<< " # of coins returned = " << nCoinsReturned
<< " Spend Amount = " << nSelectedValue / COIN << " Held = " << CoinsHeld << "\n";
} else {
std::cout << "FAILED : Coins = " << nValueTarget / COIN << " Held = " << CoinsHeld << "\n";
}
}
if (i < MaxLimit) {
BOOST_CHECK_MESSAGE(vSpends.size() < 5, "Too many spends");
BOOST_CHECK_MESSAGE(vSpends.size() > 0, "No spends");
} else {
bool spends_not_ok = ((vSpends.size() >= 4) || (vSpends.size() == 0));
BOOST_CHECK_MESSAGE(spends_not_ok, "Expected to fail but didn't");
}
nValueTarget += OneCoinAmount;
}
//std::cout << "241 Test done!\n";
}
BOOST_AUTO_TEST_CASE(zerocoin_spend_test115)
{
const int nMaxNumberOfSpends = 4;
const bool fMinimizeChange = false;
const int DenomAmounts[] = {0, 1, 1, 2, 0, 0, 0, 0};
CAmount nSelectedValue;
std::list<CMintMeta> listMints;
std::map<CoinDenomination, CAmount> mapDenom;
int j = 0;
CAmount nTotalAmount = 0;
int CoinsHeld = 0;
// Create a set of Minted coins that fits profile given by DenomAmounts
// Also setup Map array corresponding to DenomAmount which is the current set of coins available
for (const auto& denom : zerocoinDenomList) {
for (int i = 0; i < DenomAmounts[j]; i++) {
CAmount currentAmount = ZerocoinDenominationToAmount(denom);
nTotalAmount += currentAmount;
CBigNum value;
CBigNum rand;
CBigNum serial = CBigNum::randKBitBignum(256);
bool isUsed = false;
CMintMeta meta;
meta.denom = denom;
meta.hashPubcoin = GetPubCoinHash(value);
meta.hashSerial = GetSerialHash(serial);
meta.isUsed = isUsed;
meta.nVersion = 1;
listMints.push_back(meta);
}
mapDenom.insert(std::pair<CoinDenomination, CAmount>(denom, DenomAmounts[j]));
j++;
}
CoinsHeld = nTotalAmount / COIN;
std::cout << "Curremt Amount held = " << CoinsHeld << ": ";
// Show what we have
j = 0;
for (const auto& denom : zerocoinDenomList)
std::cout << DenomAmounts[j++] << "*" << ZerocoinDenominationToAmount(denom) / COIN << " + ";
std::cout << "\n";
CAmount OneCoinAmount = ZerocoinDenominationToAmount(ZQ_ONE);
CAmount nValueTarget = OneCoinAmount;
//bool fDebug = 0;
int nCoinsReturned;
int nNeededSpends = 0; // Number of spends which would be needed if selection failed
std::vector<CMintMeta> vSpends = SelectMintsFromList(nValueTarget, nSelectedValue,
nMaxNumberOfSpends,
fMinimizeChange,
nCoinsReturned,
listMints,
mapDenom,
nNeededSpends);
// if (fDebug) {
// if (vSpends.size() > 0) {
// std::cout << "SUCCESS : Coins = " << nValueTarget / COIN << " # spends used = " << vSpends.size()
// << " # of coins returned = " << nCoinsReturned
// << " Spend Amount = " << nSelectedValue / COIN << " Held = " << CoinsHeld << "\n";
// } else {
// std::cout << "FAILED : Coins = " << nValueTarget / COIN << " Held = " << CoinsHeld << "\n";
// }
// }
BOOST_CHECK_MESSAGE(vSpends.size() < 5, "Too many spends");
BOOST_CHECK_MESSAGE(vSpends.size() > 0, "No spends");
nValueTarget += OneCoinAmount;
}
BOOST_AUTO_TEST_CASE(zerocoin_spend_test_from_245)
{
const int nMaxNumberOfSpends = 5;
// For 36:
// const int nSpendValue = 36;
// Here have a 50 so use for 36 since can't meet exact amount
// const int DenomAmounts[] = {0,1,4,1,0,0,0,0};
// Here have 45 so use 4*10 for 36 since can't meet exact amount
// const int DenomAmounts[] = {0, 1, 4, 0, 0, 0, 0, 0};
// For 51
//const int nSpendValue = 51;
// CoinsHeld = 245
const int DenomAmounts[] = {0, 1, 4, 2, 1, 0, 0, 0};
// We can spend up to this amount for above set for less 6 spends
// Otherwise, 6 spends are required
const int nMaxSpendAmount = 220;
CAmount nSelectedValue;
std::list<CMintMeta> listMints;
std::map<CoinDenomination, CAmount> mapOfDenomsHeld;
int j = 0;
CAmount nTotalAmount = 0;
int CoinsHeld = 0;
// Create a set of Minted coins that fits profile given by DenomAmounts
// Also setup Map array corresponding to DenomAmount which is the current set of coins available
for (const auto& denom : zerocoinDenomList) {
for (int i = 0; i < DenomAmounts[j]; i++) {
CAmount currentAmount = ZerocoinDenominationToAmount(denom);
nTotalAmount += currentAmount;
CBigNum value;
CBigNum rand;
CBigNum serial = CBigNum::randKBitBignum(256);
bool isUsed = false;
CMintMeta meta;
meta.denom = denom;
meta.hashPubcoin = GetPubCoinHash(value);
meta.hashSerial = GetSerialHash(serial);
meta.isUsed = isUsed;
meta.nVersion = 1;
listMints.push_back(meta);
}
mapOfDenomsHeld.insert(std::pair<CoinDenomination, CAmount>(denom, DenomAmounts[j]));
j++;
}
CoinsHeld = nTotalAmount / COIN;
std::cout << "Curremt Amount held = " << CoinsHeld << ": ";
// Show what we have
j = 0;
for (const auto& denom : zerocoinDenomList)
std::cout << DenomAmounts[j++] << "*" << ZerocoinDenominationToAmount(denom) / COIN << " + ";
std::cout << "\n";
CAmount OneCoinAmount = ZerocoinDenominationToAmount(ZQ_ONE);
CAmount nValueTarget = OneCoinAmount;
// bool fDebug = 0;
int nCoinsReturned;
int nNeededSpends = 0; // Number of spends which would be needed if selection failed
// Go through all possible spend between 1 and 241 and see if it's possible or not
for (int i = 0; i < CoinsHeld; i++) {
std::vector<CMintMeta> vSpends = SelectMintsFromList(nValueTarget, nSelectedValue,
nMaxNumberOfSpends,
false,
nCoinsReturned,
listMints,
mapOfDenomsHeld,
nNeededSpends);
// if (fDebug) {
// if (vSpends.size() > 0) {
// std::cout << "SUCCESS : Coins = " << nValueTarget / COIN << " # spends = " << vSpends.size()
// << " # coins returned = " << nCoinsReturned
// << " Amount = " << nSelectedValue / COIN << " Held = " << CoinsHeld << " ";
// } else {
// std::cout << "UNABLE TO SPEND : Coins = " << nValueTarget / COIN << " Held = " << CoinsHeld << "\n";
// }
// }
bool spends_not_ok = ((vSpends.size() > nMaxNumberOfSpends) || (vSpends.size() == 0));
if (i < nMaxSpendAmount) BOOST_CHECK_MESSAGE(!spends_not_ok, "Too many spends");
else BOOST_CHECK_MESSAGE(spends_not_ok, "Expected to fail but didn't");
std::vector<CMintMeta> vSpendsAlt = SelectMintsFromList(nValueTarget, nSelectedValue,
nMaxNumberOfSpends,
true,
nCoinsReturned,
listMints,
mapOfDenomsHeld,
nNeededSpends);
// if (fDebug) {
// if (vSpendsAlt.size() > 0) {
// std::cout << "# spends = " << vSpendsAlt.size()
// << " # coins returned = " << nCoinsReturned
// << " Amount = " << nSelectedValue / COIN << "\n";
// } else {
// std::cout << "UNABLE TO SPEND : Coins = " << nValueTarget / COIN << " Held = " << CoinsHeld << "\n";
// }
// }
spends_not_ok = ((vSpendsAlt.size() > nMaxNumberOfSpends) || (vSpendsAlt.size() == 0));
if (i < nMaxSpendAmount) BOOST_CHECK_MESSAGE(!spends_not_ok, "Too many spends");
else BOOST_CHECK_MESSAGE(spends_not_ok, "Expected to fail but didn't");
nValueTarget += OneCoinAmount;
}
}
BOOST_AUTO_TEST_CASE(zerocoin_spend_test_from_145)
{
const int nMaxNumberOfSpends = 5;
// CoinsHeld = 145
const int DenomAmounts[] = {0, 1, 4, 2, 0, 0, 0, 0};
CAmount nSelectedValue;
std::list<CMintMeta> listMints;
std::map<CoinDenomination, CAmount> mapOfDenomsHeld;
int j = 0;
CAmount nTotalAmount = 0;
int CoinsHeld = 0;
// Create a set of Minted coins that fits profile given by DenomAmounts
// Also setup Map array corresponding to DenomAmount which is the current set of coins available
for (const auto& denom : zerocoinDenomList) {
for (int i = 0; i < DenomAmounts[j]; i++) {
CAmount currentAmount = ZerocoinDenominationToAmount(denom);
nTotalAmount += currentAmount;
CBigNum value;
CBigNum rand;
CBigNum serial = CBigNum::randKBitBignum(256);
bool isUsed = false;
CMintMeta meta;
meta.denom = denom;
meta.hashPubcoin = GetPubCoinHash(value);
meta.hashSerial = GetSerialHash(serial);
meta.isUsed = isUsed;
meta.nVersion = 1;
listMints.push_back(meta);
}
mapOfDenomsHeld.insert(std::pair<CoinDenomination, CAmount>(denom, DenomAmounts[j]));
j++;
}
CoinsHeld = nTotalAmount / COIN;
std::cout << "Curremt Amount held = " << CoinsHeld << ": ";
// We can spend up to this amount for above set for less 6 spends
// Otherwise, 6 spends are required
const int nMaxSpendAmount = 130;
// Show what we have
j = 0;
for (const auto& denom : zerocoinDenomList)
std::cout << DenomAmounts[j++] << "*" << ZerocoinDenominationToAmount(denom) / COIN << " + ";
std::cout << "\n";
CAmount OneCoinAmount = ZerocoinDenominationToAmount(ZQ_ONE);
CAmount nValueTarget = OneCoinAmount;
//bool fDebug = 0;
int nCoinsReturned;
int nNeededSpends = 0; // Number of spends which would be needed if selection failed
// Go through all possible spend between 1 and 241 and see if it's possible or not
for (int i = 0; i < CoinsHeld; i++) {
std::vector<CMintMeta> vSpends = SelectMintsFromList(nValueTarget, nSelectedValue,
nMaxNumberOfSpends,
false,
nCoinsReturned,
listMints,
mapOfDenomsHeld,
nNeededSpends);
// if (fDebug) {
// if (vSpends.size() > 0) {
// std::cout << "SUCCESS : Coins = " << nValueTarget / COIN << " # spends = " << vSpends.size()
// << " # coins returned = " << nCoinsReturned
// << " Amount = " << nSelectedValue / COIN << " Held = " << CoinsHeld << " ";
// } else {
// std::cout << "UNABLE TO SPEND : Coins = " << nValueTarget / COIN << " Held = " << CoinsHeld << "\n";
// }
// }
bool spends_not_ok = ((vSpends.size() > nMaxNumberOfSpends) || (vSpends.size() == 0));
if (i < nMaxSpendAmount) BOOST_CHECK_MESSAGE(!spends_not_ok, "Too many spends");
else BOOST_CHECK_MESSAGE(spends_not_ok, "Expected to fail but didn't");
std::vector<CMintMeta> vSpendsAlt = SelectMintsFromList(nValueTarget, nSelectedValue,
nMaxNumberOfSpends,
true,
nCoinsReturned,
listMints,
mapOfDenomsHeld,
nNeededSpends);
// if (fDebug) {
// if (vSpendsAlt.size() > 0) {
// std::cout << "# spends = " << vSpendsAlt.size()
// << " # coins returned = " << nCoinsReturned
// << " Amount = " << nSelectedValue / COIN << "\n";
// } else {
// std::cout << "UNABLE TO SPEND : Coins = " << nValueTarget / COIN << " Held = " << CoinsHeld << "\n";
// }
// }
spends_not_ok = ((vSpendsAlt.size() > nMaxNumberOfSpends) || (vSpendsAlt.size() == 0));
if (i < nMaxSpendAmount) BOOST_CHECK_MESSAGE(!spends_not_ok, "Too many spends");
else BOOST_CHECK_MESSAGE(spends_not_ok, "Expected to fail but didn't");
nValueTarget += OneCoinAmount;
}
}
BOOST_AUTO_TEST_CASE(zerocoin_spend_test99)
{
const int nMaxNumberOfSpends = 4;
const bool fMinimizeChange = false;
const int DenomAmounts[] = {0, 1, 4, 2, 1, 0, 0, 0};
CAmount nSelectedValue;
std::list<CMintMeta> listMints;
std::map<CoinDenomination, CAmount> mapOfDenomsHeld;
int j = 0;
CAmount nTotalAmount = 0;
int CoinsHeld = 0;
// Create a set of Minted coins that fits profile given by DenomAmounts
// Also setup Map array corresponding to DenomAmount which is the current set of coins available
for (const auto& denom : zerocoinDenomList) {
for (int i = 0; i < DenomAmounts[j]; i++) {
CAmount currentAmount = ZerocoinDenominationToAmount(denom);
nTotalAmount += currentAmount;
CBigNum value;
CBigNum rand;
CBigNum serial = CBigNum::randKBitBignum(256);
bool isUsed = false;
CMintMeta meta;
meta.denom = denom;
meta.hashPubcoin = GetPubCoinHash(value);
meta.hashSerial = GetSerialHash(serial);
meta.isUsed = isUsed;
meta.nVersion = 1;
listMints.push_back(meta);
}
mapOfDenomsHeld.insert(std::pair<CoinDenomination, CAmount>(denom, DenomAmounts[j]));
j++;
}
CoinsHeld = nTotalAmount / COIN;
std::cout << "Curremt Amount held = " << CoinsHeld << ": ";
// Show what we have
j = 0;
for (const auto& denom : zerocoinDenomList)
std::cout << DenomAmounts[j++] << "*" << ZerocoinDenominationToAmount(denom) / COIN << " + ";
std::cout << "\n";
CAmount OneCoinAmount = ZerocoinDenominationToAmount(ZQ_ONE);
CAmount nValueTarget = 99 * OneCoinAmount;
// bool fDebug = 0;
int nCoinsReturned;
int nNeededSpends = 0; // Number of spends which would be needed if selection failed
std::vector<CMintMeta> vSpends = SelectMintsFromList(nValueTarget, nSelectedValue,
nMaxNumberOfSpends,
fMinimizeChange,
nCoinsReturned,
listMints,
mapOfDenomsHeld,
nNeededSpends);
// if (fDebug) {
// if (vSpends.size() > 0) {
// std::cout << "SUCCESS : Coins = " << nValueTarget / COIN << " # spends used = " << vSpends.size()
// << " # of coins returned = " << nCoinsReturned
// << " Spend Amount = " << nSelectedValue / COIN << " Held = " << CoinsHeld << "\n";
// } else {
// std::cout << "FAILED : Coins = " << nValueTarget / COIN << " Held = " << CoinsHeld << "\n";
// }
// }
BOOST_CHECK_MESSAGE(vSpends.size() < 5, "Too many spends");
BOOST_CHECK_MESSAGE(vSpends.size() > 0, "No spends");
nValueTarget += OneCoinAmount;
}
BOOST_AUTO_TEST_SUITE_END()