From c601f11608e7d8c6003991c24ec26aafc9cc70d8 Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 10 Sep 2013 09:04:09 +0400 Subject: [PATCH] Add missing files --- src/zerocoin/ZeroTest.cpp | 425 +++++++++++++++++++++++++++++++++++++++++++++ src/zerocoin/ZeroTest.h | 6 + 2 files changed, 431 insertions(+), 0 deletions(-) create mode 100644 src/zerocoin/ZeroTest.cpp create mode 100644 src/zerocoin/ZeroTest.h diff --git a/src/zerocoin/ZeroTest.cpp b/src/zerocoin/ZeroTest.cpp new file mode 100644 index 0000000..5dc281a --- /dev/null +++ b/src/zerocoin/ZeroTest.cpp @@ -0,0 +1,425 @@ +/** +* @file Tests.cpp +* +* @brief Test routines for Zerocoin. +* +* @author Ian Miers, Christina Garman and Matthew Green +* @date June 2013 +* +* @copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green +* @license This project is released under the MIT license. +**/ + +using namespace std; + +#include +#include +#include +#include +#include +#include "Zerocoin.h" +#include "../util.h" + +using namespace libzerocoin; +extern Params* ZCParams; + +#define COLOR_STR_GREEN "\033[32m" +#define COLOR_STR_NORMAL "\033[0m" +#define COLOR_STR_RED "\033[31m" + +#define TESTS_COINS_TO_ACCUMULATE 10 + +// Global test counters +uint32_t gNumTests = 0; +uint32_t gSuccessfulTests = 0; + +// Proof size +uint32_t gProofSize = 0; +uint32_t gCoinSize = 0; +uint32_t gSerialNumberSize = 0; + +// Global coin array +PrivateCoin *gCoins[TESTS_COINS_TO_ACCUMULATE]; + +// Global params +Params *g_Params; + +////////// +// Utility routines +////////// + +void +LogTestResult(string testName, bool (*testPtr)()) +{ + printf("Testing if %s ...\n", testName.c_str()); + + bool testResult = testPtr(); + + if (testResult == true) { + printf("\t[PASS]\n"); + gSuccessfulTests++; + } else { + printf("\t[FAIL]\n"); + } + + gNumTests++; +} + +Bignum +GetTestModulus() +{ + static Bignum testModulus(0); + + // TODO: should use a hard-coded RSA modulus for testing + if (!testModulus) { + Bignum p, q; + + // Note: we are NOT using safe primes for testing because + // they take too long to generate. Don't do this in real + // usage. See the paramgen utility for better code. + p = Bignum::generatePrime(1024, false); + q = Bignum::generatePrime(1024, false); + testModulus = p * q; + } + + return testModulus; +} + +////////// +// Test routines +////////// + +bool +Test_GenRSAModulus() +{ + Bignum result = GetTestModulus(); + + if (!result) { + return false; + } + else { + return true; + } +} + +bool +Test_CalcParamSizes() +{ + bool result = true; +#if 0 + + uint32_t pLen, qLen; + + try { + calculateGroupParamLengths(4000, 80, &pLen, &qLen); + if (pLen < 1024 || qLen < 256) { + result = false; + } + calculateGroupParamLengths(4000, 96, &pLen, &qLen); + if (pLen < 2048 || qLen < 256) { + result = false; + } + calculateGroupParamLengths(4000, 112, &pLen, &qLen); + if (pLen < 3072 || qLen < 320) { + result = false; + } + calculateGroupParamLengths(4000, 120, &pLen, &qLen); + if (pLen < 3072 || qLen < 320) { + result = false; + } + calculateGroupParamLengths(4000, 128, &pLen, &qLen); + if (pLen < 3072 || qLen < 320) { + result = false; + } + } catch (exception &e) { + result = false; + } +#endif + + return result; +} + +bool +Test_GenerateGroupParams() +{ + int32_t pLen = 1024, qLen = 256, count; + IntegerGroupParams group; + + for (count = 0; count < 1; count++) { + + try { + group = deriveIntegerGroupParams(calculateSeed(GetTestModulus(), "test", ZEROCOIN_DEFAULT_SECURITYLEVEL, "TEST GROUP"), pLen, qLen); + } catch (std::runtime_error e) { + printf("Caught exception %s\n", e.what()); + return false; + } + + // Now perform some simple tests on the resulting parameters + if (group.groupOrder.bitSize() < qLen || group.modulus.bitSize() < pLen) { + return false; + } + + Bignum c = group.g.pow_mod(group.groupOrder, group.modulus); + if (!(c.isOne())) return false; + + // Try at multiple parameter sizes + pLen = pLen * 1.5; + qLen = qLen * 1.5; + } + + return true; +} + +bool +Test_ParamGen() +{ + bool result = true; + + try { + // Instantiating testParams runs the parameter generation code + Params testParams(GetTestModulus(),ZEROCOIN_DEFAULT_SECURITYLEVEL); + } catch (runtime_error e) { + printf("ParamGen exception %s\n", e.what()); + result = false; + } + + return result; +} + +bool +Test_Accumulator() +{ + // This test assumes a list of coins were generated during + // the Test_MintCoin() test. + if (gCoins[0] == NULL) { + return false; + } + try { + // Accumulate the coin list from first to last into one accumulator + Accumulator accOne(&g_Params->accumulatorParams); + Accumulator accTwo(&g_Params->accumulatorParams); + Accumulator accThree(&g_Params->accumulatorParams); + Accumulator accFour(&g_Params->accumulatorParams); + AccumulatorWitness wThree(g_Params, accThree, gCoins[0]->getPublicCoin()); + + for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { + accOne += gCoins[i]->getPublicCoin(); + accTwo += gCoins[TESTS_COINS_TO_ACCUMULATE - (i+1)]->getPublicCoin(); + accThree += gCoins[i]->getPublicCoin(); + wThree += gCoins[i]->getPublicCoin(); + if(i != 0) { + accFour += gCoins[i]->getPublicCoin(); + } + } + + // Compare the accumulated results + if (accOne.getValue() != accTwo.getValue() || accOne.getValue() != accThree.getValue()) { + printf("Accumulators don't match\n"); + return false; + } + + if(accFour.getValue() != wThree.getValue()) { + printf("Witness math not working,\n"); + return false; + } + + // Verify that the witness is correct + if (!wThree.VerifyWitness(accThree, gCoins[0]->getPublicCoin()) ) { + printf("Witness not valid\n"); + return false; + } + + // Serialization test: see if we can serialize the accumulator + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << accOne; + + // Deserialize it into a new object + Accumulator newAcc(g_Params, ss); + + // Compare the results + if (accOne.getValue() != newAcc.getValue()) { + return false; + } + + } catch (runtime_error e) { + return false; + } + + return true; +} + +bool +Test_EqualityPoK() +{ + // Run this test 10 times + for (uint32_t i = 0; i < 10; i++) { + try { + // Generate a random integer "val" + Bignum val = Bignum::randBignum(g_Params->coinCommitmentGroup.groupOrder); + + // Manufacture two commitments to "val", both + // under different sets of parameters + Commitment one(&g_Params->accumulatorParams.accumulatorPoKCommitmentGroup, val); + + Commitment two(&g_Params->serialNumberSoKCommitmentGroup, val); + + // Now generate a proof of knowledge that "one" and "two" are + // both commitments to the same value + CommitmentProofOfKnowledge pok(&g_Params->accumulatorParams.accumulatorPoKCommitmentGroup, + &g_Params->serialNumberSoKCommitmentGroup, + one, two); + + // Serialize the proof into a stream + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << pok; + + // Deserialize back into a PoK object + CommitmentProofOfKnowledge newPok(&g_Params->accumulatorParams.accumulatorPoKCommitmentGroup, + &g_Params->serialNumberSoKCommitmentGroup, + ss); + + if (newPok.Verify(one.getCommitmentValue(), two.getCommitmentValue()) != true) { + return false; + } + + // Just for fun, deserialize the proof a second time + CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION); + ss2 << pok; + + // This time tamper with it, then deserialize it back into a PoK + ss2[15] = 0; + CommitmentProofOfKnowledge newPok2(&g_Params->accumulatorParams.accumulatorPoKCommitmentGroup, + &g_Params->serialNumberSoKCommitmentGroup, + ss2); + + // If the tampered proof verifies, that's a failure! + if (newPok2.Verify(one.getCommitmentValue(), two.getCommitmentValue()) == true) { + return false; + } + + } catch (runtime_error &e) { + return false; + } + } + + return true; +} + +bool +Test_MintCoin() +{ + gCoinSize = 0; + + try { + // Generate a list of coins + for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { + gCoins[i] = new PrivateCoin(g_Params); + + PublicCoin pc = gCoins[i]->getPublicCoin(); + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << pc; + gCoinSize += ss.size(); + } + + gCoinSize /= TESTS_COINS_TO_ACCUMULATE; + + } catch (exception &e) { + return false; + } + + return true; +} + +bool +Test_MintAndSpend() +{ + try { + // This test assumes a list of coins were generated in Test_MintCoin() + if (gCoins[0] == NULL) + { + // No coins: mint some. + Test_MintCoin(); + if (gCoins[0] == NULL) { + return false; + } + } + + // Accumulate the list of generated coins into a fresh accumulator. + // The first one gets marked as accumulated for a witness, the + // others just get accumulated normally. + Accumulator acc(&g_Params->accumulatorParams); + AccumulatorWitness wAcc(g_Params, acc, gCoins[0]->getPublicCoin()); + + for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { + acc += gCoins[i]->getPublicCoin(); + wAcc +=gCoins[i]->getPublicCoin(); + } + + // Now spend the coin + SpendMetaData m(1,1); + + CoinSpend spend(g_Params, *(gCoins[0]), acc, wAcc, m); + + // Serialize the proof and deserialize into newSpend + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << spend; + gProofSize = ss.size(); + CoinSpend newSpend(g_Params, ss); + + // See if we can verify the deserialized proof (return our result) + bool ret = newSpend.Verify(acc, m); + + // Extract the serial number + Bignum serialNumber = newSpend.getCoinSerialNumber(); + gSerialNumberSize = ceil((double)serialNumber.bitSize() / 8.0); + + return ret; + } catch (runtime_error &e) { + printf("MintAndSpend exception %s\n", e.what()); + return false; + } + + return false; +} + +void +Test_RunAllTests() +{ + printf("ZeroCoin v%s self-test routine\n", ZEROCOIN_VERSION_STRING); + + // Make a new set of parameters from a random RSA modulus + //g_Params = new Params(GetTestModulus()); + g_Params = ZCParams; + + gNumTests = gSuccessfulTests = gProofSize = 0; + for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { + gCoins[i] = NULL; + } + + // Run through all of the Zerocoin tests + LogTestResult("an RSA modulus can be generated", Test_GenRSAModulus); + LogTestResult("parameter sizes are correct", Test_CalcParamSizes); + LogTestResult("group/field parameters can be generated", Test_GenerateGroupParams); + LogTestResult("parameter generation is correct", Test_ParamGen); + LogTestResult("coins can be minted", Test_MintCoin); + LogTestResult("the accumulator works", Test_Accumulator); + LogTestResult("the commitment equality PoK works", Test_EqualityPoK); + LogTestResult("a minted coin can be spent", Test_MintAndSpend); + + printf("\nAverage coin size is %d bytes.\n", gCoinSize); + printf("Serial number size is %d bytes.\n", gSerialNumberSize); + printf("Spend proof size is %d bytes.\n", gProofSize); + + // Summarize test results + if (gSuccessfulTests < gNumTests) { + printf("\nERROR: SOME TESTS FAILED\n"); + } + + // Clear any generated coins + for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { + delete gCoins[i]; + } + + printf("\n%d out of %d tests passed.\n\n", gSuccessfulTests, gNumTests); + delete g_Params; +} diff --git a/src/zerocoin/ZeroTest.h b/src/zerocoin/ZeroTest.h new file mode 100644 index 0000000..36ab6b7 --- /dev/null +++ b/src/zerocoin/ZeroTest.h @@ -0,0 +1,6 @@ +#ifndef ZEROTEST_H_ +#define ZEROTEST_H_ + +void Test_RunAllTests(); + +#endif -- 1.7.1