diff --git a/Accumulator.cpp b/Accumulator.cpp deleted file mode 100644 index a0be881..0000000 --- a/Accumulator.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/** - * @file Accumulator.cpp - * - * @brief Accumulator and AccumulatorWitness classes for the Zerocoin library. - * - * @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. - **/ - -#include -#include "Zerocoin.h" - -namespace libzerocoin { - -//Accumulator class -Accumulator::Accumulator(const AccumulatorAndProofParams* p, const CoinDenomination d): params(p), denomination(d) { - if (!(params->initialized)) { - throw ZerocoinException("Invalid parameters for accumulator"); - } - - this->value = this->params->accumulatorBase; -} - -Accumulator::Accumulator(const Params* p, const CoinDenomination d) { - this->params = &(p->accumulatorParams); - this->denomination = d; - - if (!(params->initialized)) { - throw ZerocoinException("Invalid parameters for accumulator"); - } - - this->value = this->params->accumulatorBase; -} - -void Accumulator::accumulate(const PublicCoin& coin) { - // Make sure we're initialized - if(!(this->value)) { - throw ZerocoinException("Accumulator is not initialized"); - } - - if(this->denomination != coin.getDenomination()) { - //std::stringstream msg; - std::string msg; - msg = "Wrong denomination for coin. Expected coins of denomination: "; - msg += this->denomination; - msg += ". Instead, got a coin of denomination: "; - msg += coin.getDenomination(); - throw ZerocoinException(msg); - } - - if(coin.validate()) { - // Compute new accumulator = "old accumulator"^{element} mod N - this->value = this->value.pow_mod(coin.getValue(), this->params->accumulatorModulus); - } else { - throw ZerocoinException("Coin is not valid"); - } -} - -const CoinDenomination Accumulator::getDenomination() const { - return static_cast (this->denomination); -} - -const Bignum& Accumulator::getValue() const { - return this->value; -} - -Accumulator& Accumulator::operator += (const PublicCoin& c) { - this->accumulate(c); - return *this; -} - -bool Accumulator::operator == (const Accumulator rhs) const { - return this->value == rhs.value; -} - -//AccumulatorWitness class -AccumulatorWitness::AccumulatorWitness(const Params* p, - const Accumulator& checkpoint, const PublicCoin coin): params(p), witness(checkpoint), element(coin) { -} - -void AccumulatorWitness::AddElement(const PublicCoin& c) { - if(element != c) { - witness += c; - } -} - -const Bignum& AccumulatorWitness::getValue() const { - return this->witness.getValue(); -} - -bool AccumulatorWitness::VerifyWitness(const Accumulator& a, const PublicCoin &publicCoin) const { - Accumulator temp(witness); - temp += element; - return (temp == a && this->element == publicCoin); -} - -AccumulatorWitness& AccumulatorWitness::operator +=( - const PublicCoin& rhs) { - this->AddElement(rhs); - return *this; -} - -} /* namespace libzerocoin */ diff --git a/Accumulator.h b/Accumulator.h deleted file mode 100644 index 17cd58f..0000000 --- a/Accumulator.h +++ /dev/null @@ -1,148 +0,0 @@ -/** - * @file Accumulator.h - * - * @brief Accumulator and AccumulatorWitness classes for the Zerocoin library. - * - * @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. - **/ -#ifndef ACCUMULATOR_H_ -#define ACCUMULATOR_H_ - -namespace libzerocoin { -/** - * \brief Implementation of the RSA-based accumulator. - **/ - -class Accumulator { -public: - - /** - * @brief Construct an Accumulator from a stream. - * @param p An AccumulatorAndProofParams object containing global parameters - * @param d the denomination of coins we are accumulating - * @throw Zerocoin exception in case of invalid parameters - **/ - template - Accumulator(const AccumulatorAndProofParams* p, Stream& strm): params(p) { - strm >> *this; - } - - template - Accumulator(const Params* p, Stream& strm) { - strm >> *this; - this->params = &(p->accumulatorParams); - } - - /** - * @brief Construct an Accumulator from a Params object. - * @param p A Params object containing global parameters - * @param d the denomination of coins we are accumulating - * @throw Zerocoin exception in case of invalid parameters - **/ - Accumulator(const AccumulatorAndProofParams* p, const CoinDenomination d = ZQ_LOVELACE); - - Accumulator(const Params* p, const CoinDenomination d = ZQ_LOVELACE); - - /** - * Accumulate a coin into the accumulator. Validates - * the coin prior to accumulation. - * - * @param coin A PublicCoin to accumulate. - * - * @throw Zerocoin exception if the coin is not valid. - * - **/ - void accumulate(const PublicCoin &coin); - - const CoinDenomination getDenomination() const; - /** Get the accumulator result - * - * @return a Bignum containing the result. - */ - const Bignum& getValue() const; - - - // /** - // * Used to set the accumulator value - // * - // * Use this to handle accumulator checkpoints - // * @param b the value to set the accumulator to. - // * @throw A ZerocoinException if the accumulator value is invalid. - // */ - // void setValue(Bignum &b); // shouldn't this be a constructor? - - /** Used to accumulate a coin - * - * @param c the coin to accumulate - * @return a refrence to the updated accumulator. - */ - Accumulator& operator +=(const PublicCoin& c); - bool operator==(const Accumulator rhs) const; - - IMPLEMENT_SERIALIZE - ( - READWRITE(value); - READWRITE(denomination); - ) -private: - const AccumulatorAndProofParams* params; - Bignum value; - // Denomination is stored as an INT because storing - // and enum raises amigiuities in the serialize code //FIXME if possible - int denomination; -}; - -/**A witness that a PublicCoin is in the accumulation of a set of coins - * - */ -class AccumulatorWitness { -public: - template - AccumulatorWitness(const Params* p, Stream& strm): params(p) { - strm >> *this; - } - - /** Construct's a witness. You must add all elements after the witness - * @param p pointer to params - * @param checkpoint the last known accumulator value before the element was added - * @param coin the coin we want a witness to - */ - AccumulatorWitness(const Params* p, const Accumulator& checkpoint, const PublicCoin coin); - - /** Adds element to the set whose's accumulation we are proving coin is a member of - * - * @param c the coin to add - */ - void AddElement(const PublicCoin& c); - - /** - * - * @return the value of the witness - */ - const Bignum& getValue() const; - - /** Checks that this is a witness to the accumulation of coin - * @param a the accumulator we are checking against. - * @param publicCoin the coin we're providing a witness for - * @return True if the witness computation validates - */ - bool VerifyWitness(const Accumulator& a, const PublicCoin &publicCoin) const; - - /** - * Adds rhs to the set whose's accumulation ware proving coin is a member of - * @param rhs the PublicCoin to add - * @return - */ - AccumulatorWitness& operator +=(const PublicCoin& rhs); -private: - const Params* params; - Accumulator witness; - const PublicCoin element; -}; - -} /* namespace libzerocoin */ -#endif /* ACCUMULATOR_H_ */ diff --git a/AccumulatorProofOfKnowledge.cpp b/AccumulatorProofOfKnowledge.cpp deleted file mode 100644 index ed9ac91..0000000 --- a/AccumulatorProofOfKnowledge.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/** - * @file AccumulatorProofOfKnowledge.cpp - * - * @brief AccumulatorProofOfKnowledge class for the Zerocoin library. - * - * @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. - **/ - -#include "Zerocoin.h" - -namespace libzerocoin { - -AccumulatorProofOfKnowledge::AccumulatorProofOfKnowledge(const AccumulatorAndProofParams* p): params(p) {} - -AccumulatorProofOfKnowledge::AccumulatorProofOfKnowledge(const AccumulatorAndProofParams* p, - const Commitment& commitmentToCoin, const AccumulatorWitness& witness, - Accumulator& a): params(p) { - - Bignum sg = params->accumulatorPoKCommitmentGroup.g; - Bignum sh = params->accumulatorPoKCommitmentGroup.h; - - Bignum g_n = params->accumulatorQRNCommitmentGroup.g; - Bignum h_n = params->accumulatorQRNCommitmentGroup.h; - - Bignum e = commitmentToCoin.getContents(); - Bignum r = commitmentToCoin.getRandomness(); - - Bignum r_1 = Bignum::randBignum(params->accumulatorModulus/4); - Bignum r_2 = Bignum::randBignum(params->accumulatorModulus/4); - Bignum r_3 = Bignum::randBignum(params->accumulatorModulus/4); - - this->C_e = g_n.pow_mod(e, params->accumulatorModulus) * h_n.pow_mod(r_1, params->accumulatorModulus); - this->C_u = witness.getValue() * h_n.pow_mod(r_2, params->accumulatorModulus); - this->C_r = g_n.pow_mod(r_2, params->accumulatorModulus) * h_n.pow_mod(r_3, params->accumulatorModulus); - - Bignum r_alpha = Bignum::randBignum(params->maxCoinValue * Bignum(2).pow(params->k_prime + params->k_dprime)); - if(!(Bignum::randBignum(Bignum(3)) % 2)) { - r_alpha = 0-r_alpha; - } - - Bignum r_gamma = Bignum::randBignum(params->accumulatorPoKCommitmentGroup.modulus); - Bignum r_phi = Bignum::randBignum(params->accumulatorPoKCommitmentGroup.modulus); - Bignum r_psi = Bignum::randBignum(params->accumulatorPoKCommitmentGroup.modulus); - Bignum r_sigma = Bignum::randBignum(params->accumulatorPoKCommitmentGroup.modulus); - Bignum r_xi = Bignum::randBignum(params->accumulatorPoKCommitmentGroup.modulus); - - Bignum r_epsilon = Bignum::randBignum((params->accumulatorModulus/4) * Bignum(2).pow(params->k_prime + params->k_dprime)); - if(!(Bignum::randBignum(Bignum(3)) % 2)) { - r_epsilon = 0-r_epsilon; - } - Bignum r_eta = Bignum::randBignum((params->accumulatorModulus/4) * Bignum(2).pow(params->k_prime + params->k_dprime)); - if(!(Bignum::randBignum(Bignum(3)) % 2)) { - r_eta = 0-r_eta; - } - Bignum r_zeta = Bignum::randBignum((params->accumulatorModulus/4) * Bignum(2).pow(params->k_prime + params->k_dprime)); - if(!(Bignum::randBignum(Bignum(3)) % 2)) { - r_zeta = 0-r_zeta; - } - - Bignum r_beta = Bignum::randBignum((params->accumulatorModulus/4) * params->accumulatorPoKCommitmentGroup.modulus * Bignum(2).pow(params->k_prime + params->k_dprime)); - if(!(Bignum::randBignum(Bignum(3)) % 2)) { - r_beta = 0-r_beta; - } - Bignum r_delta = Bignum::randBignum((params->accumulatorModulus/4) * params->accumulatorPoKCommitmentGroup.modulus * Bignum(2).pow(params->k_prime + params->k_dprime)); - if(!(Bignum::randBignum(Bignum(3)) % 2)) { - r_delta = 0-r_delta; - } - - this->st_1 = (sg.pow_mod(r_alpha, params->accumulatorPoKCommitmentGroup.modulus) * sh.pow_mod(r_phi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus; - this->st_2 = (((commitmentToCoin.getCommitmentValue() * sg.inverse(params->accumulatorPoKCommitmentGroup.modulus)).pow_mod(r_gamma, params->accumulatorPoKCommitmentGroup.modulus)) * sh.pow_mod(r_psi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus; - this->st_3 = ((sg * commitmentToCoin.getCommitmentValue()).pow_mod(r_sigma, params->accumulatorPoKCommitmentGroup.modulus) * sh.pow_mod(r_xi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus; - - this->t_1 = (h_n.pow_mod(r_zeta, params->accumulatorModulus) * g_n.pow_mod(r_epsilon, params->accumulatorModulus)) % params->accumulatorModulus; - this->t_2 = (h_n.pow_mod(r_eta, params->accumulatorModulus) * g_n.pow_mod(r_alpha, params->accumulatorModulus)) % params->accumulatorModulus; - this->t_3 = (C_u.pow_mod(r_alpha, params->accumulatorModulus) * ((h_n.inverse(params->accumulatorModulus)).pow_mod(r_beta, params->accumulatorModulus))) % params->accumulatorModulus; - this->t_4 = (C_r.pow_mod(r_alpha, params->accumulatorModulus) * ((h_n.inverse(params->accumulatorModulus)).pow_mod(r_delta, params->accumulatorModulus)) * ((g_n.inverse(params->accumulatorModulus)).pow_mod(r_beta, params->accumulatorModulus))) % params->accumulatorModulus; - - CHashWriter hasher(0,0); - hasher << *params << sg << sh << g_n << h_n << commitmentToCoin.getCommitmentValue() << C_e << C_u << C_r << st_1 << st_2 << st_3 << t_1 << t_2 << t_3 << t_4; - - //According to the proof, this hash should be of length k_prime bits. It is currently greater than that, which should not be a problem, but we should check this. - Bignum c = Bignum(hasher.GetHash()); - - this->s_alpha = r_alpha - c*e; - this->s_beta = r_beta - c*r_2*e; - this->s_zeta = r_zeta - c*r_3; - this->s_sigma = r_sigma - c*((e+1).inverse(params->accumulatorPoKCommitmentGroup.groupOrder)); - this->s_eta = r_eta - c*r_1; - this->s_epsilon = r_epsilon - c*r_2; - this->s_delta = r_delta - c*r_3*e; - this->s_xi = r_xi + c*r*((e+1).inverse(params->accumulatorPoKCommitmentGroup.groupOrder)); - this->s_phi = (r_phi - c*r) % params->accumulatorPoKCommitmentGroup.groupOrder; - this->s_gamma = r_gamma - c*((e-1).inverse(params->accumulatorPoKCommitmentGroup.groupOrder)); - this->s_psi = r_psi + c*r*((e-1).inverse(params->accumulatorPoKCommitmentGroup.groupOrder)); -} - -/** Verifies that a commitment c is accumulated in accumulator a - */ -bool AccumulatorProofOfKnowledge:: Verify(const Accumulator& a, const Bignum& valueOfCommitmentToCoin) const { - Bignum sg = params->accumulatorPoKCommitmentGroup.g; - Bignum sh = params->accumulatorPoKCommitmentGroup.h; - - Bignum g_n = params->accumulatorQRNCommitmentGroup.g; - Bignum h_n = params->accumulatorQRNCommitmentGroup.h; - - //According to the proof, this hash should be of length k_prime bits. It is currently greater than that, which should not be a problem, but we should check this. - CHashWriter hasher(0,0); - hasher << *params << sg << sh << g_n << h_n << valueOfCommitmentToCoin << C_e << C_u << C_r << st_1 << st_2 << st_3 << t_1 << t_2 << t_3 << t_4; - - Bignum c = Bignum(hasher.GetHash()); //this hash should be of length k_prime bits - - Bignum st_1_prime = (valueOfCommitmentToCoin.pow_mod(c, params->accumulatorPoKCommitmentGroup.modulus) * sg.pow_mod(s_alpha, params->accumulatorPoKCommitmentGroup.modulus) * sh.pow_mod(s_phi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus; - Bignum st_2_prime = (sg.pow_mod(c, params->accumulatorPoKCommitmentGroup.modulus) * ((valueOfCommitmentToCoin * sg.inverse(params->accumulatorPoKCommitmentGroup.modulus)).pow_mod(s_gamma, params->accumulatorPoKCommitmentGroup.modulus)) * sh.pow_mod(s_psi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus; - Bignum st_3_prime = (sg.pow_mod(c, params->accumulatorPoKCommitmentGroup.modulus) * (sg * valueOfCommitmentToCoin).pow_mod(s_sigma, params->accumulatorPoKCommitmentGroup.modulus) * sh.pow_mod(s_xi, params->accumulatorPoKCommitmentGroup.modulus)) % params->accumulatorPoKCommitmentGroup.modulus; - - Bignum t_1_prime = (C_r.pow_mod(c, params->accumulatorModulus) * h_n.pow_mod(s_zeta, params->accumulatorModulus) * g_n.pow_mod(s_epsilon, params->accumulatorModulus)) % params->accumulatorModulus; - Bignum t_2_prime = (C_e.pow_mod(c, params->accumulatorModulus) * h_n.pow_mod(s_eta, params->accumulatorModulus) * g_n.pow_mod(s_alpha, params->accumulatorModulus)) % params->accumulatorModulus; - Bignum t_3_prime = ((a.getValue()).pow_mod(c, params->accumulatorModulus) * C_u.pow_mod(s_alpha, params->accumulatorModulus) * ((h_n.inverse(params->accumulatorModulus)).pow_mod(s_beta, params->accumulatorModulus))) % params->accumulatorModulus; - Bignum t_4_prime = (C_r.pow_mod(s_alpha, params->accumulatorModulus) * ((h_n.inverse(params->accumulatorModulus)).pow_mod(s_delta, params->accumulatorModulus)) * ((g_n.inverse(params->accumulatorModulus)).pow_mod(s_beta, params->accumulatorModulus))) % params->accumulatorModulus; - - bool result = false; - - bool result_st1 = (st_1 == st_1_prime); - bool result_st2 = (st_2 == st_2_prime); - bool result_st3 = (st_3 == st_3_prime); - - bool result_t1 = (t_1 == t_1_prime); - bool result_t2 = (t_2 == t_2_prime); - bool result_t3 = (t_3 == t_3_prime); - bool result_t4 = (t_4 == t_4_prime); - - bool result_range = ((s_alpha >= -(params->maxCoinValue * Bignum(2).pow(params->k_prime + params->k_dprime + 1))) && (s_alpha <= (params->maxCoinValue * Bignum(2).pow(params->k_prime + params->k_dprime + 1)))); - - result = result_st1 && result_st2 && result_st3 && result_t1 && result_t2 && result_t3 && result_t4 && result_range; - - return result; -} - -} /* namespace libzerocoin */ diff --git a/AccumulatorProofOfKnowledge.h b/AccumulatorProofOfKnowledge.h deleted file mode 100644 index 4078940..0000000 --- a/AccumulatorProofOfKnowledge.h +++ /dev/null @@ -1,91 +0,0 @@ -/** - * @file AccumulatorProofOfKnowledge.h - * - * @brief AccumulatorProofOfKnowledge class for the Zerocoin library. - * - * @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. - **/ - -#ifndef ACCUMULATEPROOF_H_ -#define ACCUMULATEPROOF_H_ - -namespace libzerocoin { - -/**A prove that a value insde the commitment commitmentToCoin is in an accumulator a. - * - */ -class AccumulatorProofOfKnowledge { -public: - AccumulatorProofOfKnowledge(const AccumulatorAndProofParams* p); - - /** Generates a proof that a commitment to a coin c was accumulated - * @param p Cryptographic parameters - * @param commitmentToCoin commitment containing the coin we want to prove is accumulated - * @param witness The witness to the accumulation of the coin - * @param a - */ - AccumulatorProofOfKnowledge(const AccumulatorAndProofParams* p, const Commitment& commitmentToCoin, const AccumulatorWitness& witness, Accumulator& a); - /** Verifies that a commitment c is accumulated in accumulated a - */ - bool Verify(const Accumulator& a,const Bignum& valueOfCommitmentToCoin) const; - - IMPLEMENT_SERIALIZE - ( - READWRITE(C_e); - READWRITE(C_u); - READWRITE(C_r); - READWRITE(st_1); - READWRITE(st_2); - READWRITE(st_3); - READWRITE(t_1); - READWRITE(t_2); - READWRITE(t_3); - READWRITE(t_4); - READWRITE(s_alpha); - READWRITE(s_beta); - READWRITE(s_zeta); - READWRITE(s_sigma); - READWRITE(s_eta); - READWRITE(s_epsilon); - READWRITE(s_delta); - READWRITE(s_xi); - READWRITE(s_phi); - READWRITE(s_gamma); - READWRITE(s_psi); - ) -private: - const AccumulatorAndProofParams* params; - - /* Return values for proof */ - Bignum C_e; - Bignum C_u; - Bignum C_r; - - Bignum st_1; - Bignum st_2; - Bignum st_3; - - Bignum t_1; - Bignum t_2; - Bignum t_3; - Bignum t_4; - - Bignum s_alpha; - Bignum s_beta; - Bignum s_zeta; - Bignum s_sigma; - Bignum s_eta; - Bignum s_epsilon; - Bignum s_delta; - Bignum s_xi; - Bignum s_phi; - Bignum s_gamma; - Bignum s_psi; -}; - -} /* namespace libzerocoin */ -#endif /* ACCUMULATEPROOF_H_ */ diff --git a/Benchmark.cpp b/Benchmark.cpp deleted file mode 100644 index 5db6bab..0000000 --- a/Benchmark.cpp +++ /dev/null @@ -1,408 +0,0 @@ -/** - * @file Benchmark.cpp - * - * @brief Benchmarking tests 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 -#include - -#include "Zerocoin.h" - -using namespace libzerocoin; - -#define COLOR_STR_GREEN "\033[32m" -#define COLOR_STR_NORMAL "\033[0m" -#define COLOR_STR_RED "\033[31m" - -#define TESTS_COINS_TO_ACCUMULATE 50 - -// Global test counters -uint32_t gNumTests = 0; -uint32_t gSuccessfulTests = 0; - -// Global coin array -PrivateCoin *gCoins[TESTS_COINS_TO_ACCUMULATE]; - -// Global params -Params *g_Params; - -////////// -// Utility routines -////////// - -class Timer -{ - timeval timer[2]; - -public: - - timeval start() - { - gettimeofday(&this->timer[0], NULL); - return this->timer[0]; - } - - timeval stop() - { - gettimeofday(&this->timer[1], NULL); - return this->timer[1]; - } - - int duration() const - { - int secs(this->timer[1].tv_sec - this->timer[0].tv_sec); - int usecs(this->timer[1].tv_usec - this->timer[0].tv_usec); - - if(usecs < 0) - { - --secs; - usecs += 1000000; - } - - return static_cast(secs * 1000 + usecs / 1000.0 + 0.5); - } -}; - -// Global timer -Timer timer; - -void -LogTestResult(string testName, bool (*testPtr)()) -{ - string colorGreen(COLOR_STR_GREEN); - string colorNormal(COLOR_STR_NORMAL); - string colorRed(COLOR_STR_RED); - - cout << "Testing if " << testName << "..." << endl; - - bool testResult = testPtr(); - - if (testResult == true) { - cout << "\t" << colorGreen << "[PASS]" << colorNormal << endl; - gSuccessfulTests++; - } else { - cout << colorRed << "\t[FAIL]" << colorNormal << endl; - } - - gNumTests++; -} - -Bignum -GetTestModulus() -{ - static Bignum testModulus(0); - - // TODO: should use a hard-coded RSA modulus for testing - if (!testModulus) { - Bignum p, q; - 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() -{ - uint32_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) { - cout << "Caught exception " << e.what() << endl; - 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); - //cout << "g^q mod p = " << c << endl; - 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 { - timer.start(); - // Instantiating testParams runs the parameter generation code - Params testParams(GetTestModulus(),ZEROCOIN_DEFAULT_SECURITYLEVEL); - timer.stop(); - - cout << "\tPARAMGEN ELAPSED TIME: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s" << endl; - } catch (runtime_error e) { - cout << e.what() << endl; - 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()) { - cout << "Accumulators don't match" << endl; - return false; - } - - if(accFour.getValue() != wThree.getValue()) { - cout << "Witness math not working," << endl; - return false; - } - - // Verify that the witness is correct - if (!wThree.VerifyWitness(accThree, gCoins[0]->getPublicCoin()) ) { - cout << "Witness not valid" << endl; - return false; - } - - } catch (runtime_error e) { - return false; - } - - return true; -} - -bool -Test_MintCoin() -{ - try { - // Generate a list of coins - timer.start(); - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { - gCoins[i] = new PrivateCoin(g_Params); - } - timer.stop(); - } catch (exception &e) { - return false; - } - - cout << "\tMINT ELAPSED TIME:\n\t\tTotal: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s\n\t\tPer Coin: " << timer.duration()/TESTS_COINS_TO_ACCUMULATE << " ms\t" << (timer.duration()/TESTS_COINS_TO_ACCUMULATE)*0.001 << " s" << endl; - - 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()); - - timer.start(); - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { - acc += gCoins[i]->getPublicCoin(); - } - timer.stop(); - - cout << "\tACCUMULATOR ELAPSED TIME:\n\t\tTotal: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s\n\t\tPer Element: " << timer.duration()/TESTS_COINS_TO_ACCUMULATE << " ms\t" << (timer.duration()/TESTS_COINS_TO_ACCUMULATE)*0.001 << " s" << endl; - - timer.start(); - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { - wAcc +=gCoins[i]->getPublicCoin(); - } - timer.stop(); - - cout << "\tWITNESS ELAPSED TIME: \n\t\tTotal: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s\n\t\tPer Element: " << timer.duration()/TESTS_COINS_TO_ACCUMULATE << " ms\t" << (timer.duration()/TESTS_COINS_TO_ACCUMULATE)*0.001 << " s" << endl; - - // Now spend the coin - SpendMetaData m(1,1); - - timer.start(); - CoinSpend spend(g_Params, *(gCoins[0]), acc, wAcc, m); - timer.stop(); - - cout << "\tSPEND ELAPSED TIME: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s" << endl; - - // Serialize the proof and deserialize into newSpend - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - - timer.start(); - ss << spend; - timer.stop(); - - CoinSpend newSpend(g_Params, ss); - - cout << "\tSERIALIZE ELAPSED TIME: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s" << endl; - - // Finally, see if we can verify the deserialized proof (return our result) - timer.start(); - bool ret = newSpend.Verify(acc, m); - timer.stop(); - - cout << "\tSPEND VERIFY ELAPSED TIME: " << timer.duration() << " ms\t" << timer.duration()*0.001 << " s" << endl; - - return ret; - } catch (runtime_error &e) { - cout << e.what() << endl; - return false; - } - - return false; -} - -void -Test_RunAllTests() -{ - // Make a new set of parameters from a random RSA modulus - g_Params = new Params(GetTestModulus()); - - gNumTests = gSuccessfulTests = 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("a minted coin can be spent", Test_MintAndSpend); - - // Summarize test results - if (gSuccessfulTests < gNumTests) { - cout << endl << "ERROR: SOME TESTS FAILED" << endl; - } - - // Clear any generated coins - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { - delete gCoins[i]; - } - - cout << gSuccessfulTests << " out of " << gNumTests << " tests passed." << endl << endl; - delete g_Params; -} - -int main(int argc, char **argv) -{ - cout << "libzerocoin v" << ZEROCOIN_VERSION_STRING << " benchmark utility." << endl << endl; - - Test_RunAllTests(); -} - diff --git a/Build-gcc/makefile b/Build-gcc/makefile deleted file mode 100644 index 684687e..0000000 --- a/Build-gcc/makefile +++ /dev/null @@ -1,89 +0,0 @@ -################################################################################ -# Automatically-generated file. Do not edit! -################################################################################ - --include ../makefile.init - -RM := rm - -# All of the sources participating in the build are defined here --include sources.mk --include bitcoin_bignum/subdir.mk --include subdir.mk --include objects.mk - -ifneq ($(MAKECMDGOALS),clean) -ifneq ($(strip $(C++_DEPS)),) --include $(C++_DEPS) -endif -ifneq ($(strip $(C_DEPS)),) --include $(C_DEPS) -endif -ifneq ($(strip $(CC_DEPS)),) --include $(CC_DEPS) -endif -ifneq ($(strip $(CPP_DEPS)),) --include $(CPP_DEPS) -endif -ifneq ($(strip $(CXX_DEPS)),) --include $(CXX_DEPS) -endif -ifneq ($(strip $(C_UPPER_DEPS)),) --include $(C_UPPER_DEPS) -endif -endif - - -include ../makefile.defs - -.DEFAULT_GOAL := libzerocoin - -# Add inputs and outputs from these tool invocations to the build variables - -# All Target -all: libzerocoin test tutorial - -# Tool invocations -libzerocoin: $(OBJS) $(USER_OBJS) - @echo 'Building target: $@' - @echo 'Invoking: Cross G++ Linker' - g++ -fopenmp -L/opt/local/lib -shared -o "libzerocoin.so" $(OBJS) $(USER_OBJS) $(LIBS) - @echo 'Finished building target: $@' - @echo ' ' - -test: $(OBJS) $(USER_OBJS) - @echo 'Building target: $@' - @echo 'Invoking: Cross G++ Linker' - g++ -fopenmp -L/opt/local/lib -o "tests" ../Tests.cpp $(OBJS) $(USER_OBJS) $(LIBS) - @echo 'Finished building target: $@' - @echo ' ' - -paramgen: $(OBJS) $(USER_OBJS) - @echo 'Building target: $@' - @echo 'Invoking: Cross G++ Linker' - g++ -fopenmp -L/opt/local/lib -o "paramgen" ../paramgen.cpp $(OBJS) $(USER_OBJS) $(LIBS) - @echo 'Finished building target: $@' - @echo ' ' - -benchmark: $(OBJS) $(USER_OBJS) - @echo 'Building target: $@' - @echo 'Invoking: Cross G++ Linker' - g++ -fopenmp -L/opt/local/lib -o "benchmark" ../Benchmark.cpp $(OBJS) $(USER_OBJS) $(LIBS) - @echo 'Finished building target: $@' - @echo ' ' - -tutorial: $(OBJS) $(USER_OBJS) - @echo 'Building target: $@' - @echo 'Invoking: Cross G++ Linker' - g++ -fopenmp -L/opt/local/lib -o "tutorial" ../Tutorial.cpp $(OBJS) $(USER_OBJS) $(LIBS) - @echo 'Finished building target: $@' - @echo ' ' - -# Other Targets -clean: - -$(RM) $(C++_DEPS)$(OBJS)$(C_DEPS)$(CC_DEPS)$(LIBRARIES)$(CPP_DEPS)$(CXX_DEPS)$(C_UPPER_DEPS) libzerocoin.so tests benchmark paramgen - -@echo ' ' - -.PHONY: all clean dependents -.SECONDARY: - - -include ../makefile.targets diff --git a/Build-gcc/objects.mk b/Build-gcc/objects.mk deleted file mode 100644 index 02799e3..0000000 --- a/Build-gcc/objects.mk +++ /dev/null @@ -1,8 +0,0 @@ -################################################################################ -# Automatically-generated file. Do not edit! -################################################################################ - -USER_OBJS := - -LIBS := -I/opt/local/include -lboost_system-mt -lcrypto - diff --git a/Build-gcc/sources.mk b/Build-gcc/sources.mk deleted file mode 100644 index 057b9b3..0000000 --- a/Build-gcc/sources.mk +++ /dev/null @@ -1,28 +0,0 @@ -################################################################################ -# Automatically-generated file. Do not edit! -################################################################################ - -O_SRCS := -CPP_SRCS := -C_UPPER_SRCS := -C_SRCS := -S_UPPER_SRCS := -OBJ_SRCS := -ASM_SRCS := -CXX_SRCS := -C++_SRCS := -CC_SRCS := -C++_DEPS := -OBJS := -C_DEPS := -CC_DEPS := -LIBRARIES := -CPP_DEPS := -CXX_DEPS := -C_UPPER_DEPS := - -# Every subdirectory with source files must be described here -SUBDIRS := \ -bitcoin_bignum \ -. \ - diff --git a/Build-gcc/subdir.mk b/Build-gcc/subdir.mk deleted file mode 100644 index c18b53f..0000000 --- a/Build-gcc/subdir.mk +++ /dev/null @@ -1,47 +0,0 @@ -################################################################################ -# Automatically-generated file. Do not edit! -################################################################################ - -# Add inputs and outputs from these tool invocations to the build variables -CPP_SRCS += \ -../Accumulator.cpp \ -../AccumulatorProofOfKnowledge.cpp \ -../Coin.cpp \ -../CoinSpend.cpp \ -../Commitment.cpp \ -../Params.cpp \ -../SerialNumberSignatureOfKnowledge.cpp \ -../SpendMetaData.cpp \ -../ParamGeneration.cpp - -OBJS += \ -./Accumulator.o \ -./AccumulatorProofOfKnowledge.o \ -./Coin.o \ -./CoinSpend.o \ -./Commitment.o \ -./Params.o \ -./SerialNumberSignatureOfKnowledge.o \ -./SpendMetaData.o \ -./ParamGeneration.o - -CPP_DEPS += \ -./Accumulator.d \ -./AccumulatorProofOfKnowledge.d \ -./Coin.d \ -./CoinSpend.d \ -./Commitment.d \ -./Params.d \ -./SerialNumberSignatureOfKnowledge.d \ -./SpendMetaData.d \ -./ParamGeneration.d - -# Each subdirectory must supply rules for building sources it contributes -%.o: ../%.cpp - @echo 'Building file: $<' - @echo 'Invoking: Cross G++ Compiler' - g++ -fopenmp -g -L/opt/local/lib -I/opt/local/include -g -Wall -fpic -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" - @echo 'Finished building: $<' - @echo ' ' - - diff --git a/CMake/Modules/BoostConfig.cmake b/CMake/Modules/BoostConfig.cmake deleted file mode 100644 index af7c4ea..0000000 --- a/CMake/Modules/BoostConfig.cmake +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright 2013 Corgan Labs -# This file is part of the Zerocoin project -# See LICENSE file or http://opensource.org/licenses/MIT for terms - -if(DEFINED __INCLUDED_BOOSTCONFIG_CMAKE) - return() -endif() - -set(__INCLUDED_BOOSTCONFIG_CMAKE TRUE) - -set(BOOST_REQUIRED_COMPONENTS - system -) - -find_package(Boost "1.48" COMPONENTS ${BOOST_REQUIRED_COMPONENTS}) - -set(Boost_ADDITIONAL_VERSIONS - "1.45.0" "1.45" "1.46.0" "1.46" "1.47.0" "1.47" "1.48.0" "1.48" "1.49.0" "1.49" - "1.50.0" "1.50" "1.51.0" "1.51" "1.52.0" "1.52" "1.53.0" "1.53" "1.54.0" "1.54" - "1.55.0" "1.55" "1.56.0" "1.56" "1.57.0" "1.57" "1.58.0" "1.58" "1.59.0" "1.59" - "1.60.0" "1.60" "1.61.0" "1.61" "1.62.0" "1.62" "1.63.0" "1.63" "1.64.0" "1.64" - "1.65.0" "1.65" "1.66.0" "1.66" "1.67.0" "1.67" "1.68.0" "1.68" "1.69.0" "1.69" -) - -list(APPEND Boost_LIBRARIES - ${Boost_SYSTEM_LIBRARY} -) diff --git a/CMake/cmake_uninstall.cmake.in b/CMake/cmake_uninstall.cmake.in deleted file mode 100644 index 56bd9e4..0000000 --- a/CMake/cmake_uninstall.cmake.in +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2013 Kitware, Inc. -# http://www.vtk.org/Wiki/CMake_FAQ#Can_I_do_.22make_uninstall.22_with_CMake.3F -# http://creativecommons.org/licenses/by/2.5/ - -IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") - MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") -ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") - -FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) -STRING(REGEX REPLACE "\n" ";" files "${files}") -FOREACH(file ${files}) - MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") - IF(EXISTS "$ENV{DESTDIR}${file}") - EXEC_PROGRAM( - "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" - OUTPUT_VARIABLE rm_out - RETURN_VALUE rm_retval - ) - IF(NOT "${rm_retval}" STREQUAL 0) - MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") - ENDIF(NOT "${rm_retval}" STREQUAL 0) - ELSEIF(IS_SYMLINK "$ENV{DESTDIR}${file}") - EXEC_PROGRAM( - "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" - OUTPUT_VARIABLE rm_out - RETURN_VALUE rm_retval - ) - IF(NOT "${rm_retval}" STREQUAL 0) - MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") - ENDIF(NOT "${rm_retval}" STREQUAL 0) - ELSE(EXISTS "$ENV{DESTDIR}${file}") - MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") - ENDIF(EXISTS "$ENV{DESTDIR}${file}") -ENDFOREACH(file) diff --git a/CMakeLists.txt b/CMakeLists.txt index c431b8c..64b291f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,186 +1,65 @@ -# Copyright 2013 Corgan Labs -# This file is part of the Zerocoin project -# See LICENSE file or http://opensource.org/licenses/MIT for terms - -if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) - message(FATAL_ERROR "Prevented in-tree build. This is bad practice.") -endif(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) - -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE "Release") - message(STATUS "Build type not specified: defaulting to release.") -endif(NOT CMAKE_BUILD_TYPE) -set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "") - -# -# Setup overall project -# -cmake_minimum_required(VERSION 2.8) -project(zerocoin) - -# Appended to CMAKE_INSTALL_PREFIX -list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMake/Modules) - -# -# Project-wide package dependencies -# -# Find and configure the Boost C++ libraries -include(BoostConfig) - -# Find and configure OpenSSL crypto library -include(FindOpenSSL) - -# -# Project-wide directory settings -# -set(BITCOIN_BIGNUM_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/bitcoin_bignum) - -# -# Project-wide installation settings -# -set(ZEROCOIN_INCLUDE_DIR include/zerocoin) -set(ZEROCOIN_BIN_DIR bin) -set(ZEROCOIN_LIB_DIR lib) - -# -# pkg-config substitution variables -# -file(TO_NATIVE_PATH "${CMAKE_INSTALL_PREFIX}" prefix) -file(TO_NATIVE_PATH "\${prefix}" exec_prefix) -file(TO_NATIVE_PATH "\${exec_prefix}/${ZEROCOIN_LIB_DIR}" libdir) -file(TO_NATIVE_PATH "\${prefix}/${ZEROCOIN_INCLUDE_DIR}" includedir) - -# -# Add individual directories to project -# -#add_subdirectory(foo) - -# -# Create uninstall target -# -configure_file( - ${CMAKE_SOURCE_DIR}/CMake/cmake_uninstall.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake -@ONLY) - -add_custom_target(uninstall - ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake -) - -######################################################################## -# Shared library generation libzerocoin.so -######################################################################## - -# -# Tell compiler where to search for include files -# -include_directories( - ${BITCOIN_BIGNUM_INCLUDE_DIR} - ${Boost_INCLUDE_DIRS} - ${OPENSSL_INCLUDE_DIR} -) - -# -# Tell linker where to look for library files -# -link_directories( - ${Boost_LIBRARY_DIRS} -) - -# -# List of libraries to link in -# -list(APPEND zerocoin_libs - ${Boost_LIBRARIES} - ${OPENSSL_CRYPTO_LIBRARY} -) - -# -# List of source files to compile -# -list(APPEND zerocoin_sources - Accumulator.cpp - AccumulatorProofOfKnowledge.cpp - Coin.cpp - CoinSpend.cpp - Commitment.cpp - ParamGeneration.cpp - Params.cpp - SerialNumberSignatureOfKnowledge.cpp - SpendMetaData.cpp +cmake_minimum_required(VERSION 3.16) +project(libzerocoin + VERSION 1.0.0 + DESCRIPTION "Zerocoin cryptographic library" + LANGUAGES CXX ) -# -# Create shared library libzerocoin.so -# -add_library(zerocoin SHARED ${zerocoin_sources}) -target_link_libraries(zerocoin ${zerocoin_libs}) - -# -# Install shared library -# -install(TARGETS zerocoin - LIBRARY DESTINATION ${ZEROCOIN_LIB_DIR} +# Policy settings +cmake_policy(SET CMP0167 NEW) + +# Trova le dipendenze +find_package(OpenSSL 3.0 REQUIRED) +find_package(Boost 1.75 REQUIRED COMPONENTS serialization) + +# Configurazione delle opzioni del compilatore +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + add_compile_options( + -Wall + -Wextra + -Wpedantic + -Wno-deprecated-declarations + ) +endif() + +# Opzione per la libreria condivisa +option(BUILD_SHARED_LIBS "Build shared library" ON) + +# Condizionale per scegliere la libreria statica o condivisa +if(BUILD_SHARED_LIBS) + add_library(zerocoin SHARED + src/libzerocoin.cpp + ) +else() + add_library(zerocoin STATIC + src/libzerocoin.cpp + ) +endif() + +# Imposta esplicitamente il nome dell'output per la libreria come libzerocoin +set_target_properties(zerocoin PROPERTIES + OUTPUT_NAME "zerocoin" # Genererà libzerocoin.so (per SHARED) o libzerocoin.a (per STATIC) + PREFIX "lib" # Aggiungi il prefisso 'lib' su Linux ) -# -# Install header files -# -install(FILES - bitcoin_bignum/allocators.h - bitcoin_bignum/bignum.h - bitcoin_bignum/clientversion.h - bitcoin_bignum/compat.h - bitcoin_bignum/hash.h - bitcoin_bignum/netbase.h - bitcoin_bignum/serialize.h - bitcoin_bignum/uint256.h - bitcoin_bignum/version.h - DESTINATION ${ZEROCOIN_INCLUDE_DIR}/bitcoin_bignum +# Inclusione delle directory +target_include_directories(zerocoin PUBLIC + $ + $ ) -install(FILES - Accumulator.h - AccumulatorProofOfKnowledge.h - Coin.h - CoinSpend.h - Commitment.h - ParamGeneration.h - Params.h - SerialNumberSignatureOfKnowledge.h - SpendMetaData.h - Zerocoin.h - DESTINATION ${ZEROCOIN_INCLUDE_DIR} +# Link delle librerie necessarie +target_link_libraries(zerocoin + OpenSSL::Crypto + Boost::serialization ) -# -# Create pkg-config file -# -configure_file( - ${CMAKE_CURRENT_SOURCE_DIR}/zerocoin.pc.in - ${CMAKE_CURRENT_BINARY_DIR}/zerocoin.pc -@ONLY) - -# -# Install pkg-config file -# -install( - FILES ${CMAKE_CURRENT_BINARY_DIR}/zerocoin.pc - DESTINATION ${ZEROCOIN_LIB_DIR}/pkgconfig +# Imposta versione e altre proprietà +set_target_properties(zerocoin PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION 1 ) - -######################################################################## -# Executable files -######################################################################## - -add_executable(paramgen paramgen.cpp) -target_link_libraries(paramgen zerocoin) - -add_executable(benchmark Benchmark.cpp) -target_link_libraries(benchmark zerocoin) - -add_executable(test Tests.cpp) -target_link_libraries(test zerocoin) - -add_executable(tutorial Tutorial.cpp) -target_link_libraries(tutorial zerocoin) diff --git a/Coin.cpp b/Coin.cpp deleted file mode 100644 index 31fcffa..0000000 --- a/Coin.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/** - * @file Coin.cpp - * - * @brief PublicCoin and PrivateCoin classes for the Zerocoin library. - * - * @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. - **/ - -#include -#include "Zerocoin.h" - -namespace libzerocoin { - -//PublicCoin class -PublicCoin::PublicCoin(const Params* p): - params(p), denomination(ZQ_LOVELACE) { - if (this->params->initialized == false) { - throw ZerocoinException("Params are not initialized"); - } -}; - -PublicCoin::PublicCoin(const Params* p, const Bignum& coin, const CoinDenomination d): - params(p), value(coin), denomination(d) { - if (this->params->initialized == false) { - throw ZerocoinException("Params are not initialized"); - } -}; - -bool PublicCoin::operator==(const PublicCoin& rhs) const { - return this->value == rhs.value; // FIXME check param equality -} - -bool PublicCoin::operator!=(const PublicCoin& rhs) const { - return !(*this == rhs); -} - -const Bignum& PublicCoin::getValue() const { - return this->value; -} - -const CoinDenomination PublicCoin::getDenomination() const { - return static_cast(this->denomination); -} - -bool PublicCoin::validate() const{ - return (this->params->accumulatorParams.minCoinValue < value) && (value < this->params->accumulatorParams.maxCoinValue) && value.isPrime(params->zkp_iterations); -} - -//PrivateCoin class -PrivateCoin::PrivateCoin(const Params* p, const CoinDenomination denomination): params(p), publicCoin(p) { - // Verify that the parameters are valid - if(this->params->initialized == false) { - throw ZerocoinException("Params are not initialized"); - } - -#ifdef ZEROCOIN_FAST_MINT - // Mint a new coin with a random serial number using the fast process. - // This is more vulnerable to timing attacks so don't mint coins when - // somebody could be timing you. - this->mintCoinFast(denomination); -#else - // Mint a new coin with a random serial number using the standard process. - this->mintCoin(denomination); -#endif - -} - -/** - * - * @return the coins serial number - */ -const Bignum& PrivateCoin::getSerialNumber() const { - return this->serialNumber; -} - -const Bignum& PrivateCoin::getRandomness() const { - return this->randomness; -} - -void PrivateCoin::mintCoin(const CoinDenomination denomination) { - // Repeat this process up to MAX_COINMINT_ATTEMPTS times until - // we obtain a prime number - for(uint32_t attempt = 0; attempt < MAX_COINMINT_ATTEMPTS; attempt++) { - - // Generate a random serial number in the range 0...{q-1} where - // "q" is the order of the commitment group. - Bignum s = Bignum::randBignum(this->params->coinCommitmentGroup.groupOrder); - - // Generate a Pedersen commitment to the serial number "s" - Commitment coin(¶ms->coinCommitmentGroup, s); - - // Now verify that the commitment is a prime number - // in the appropriate range. If not, we'll throw this coin - // away and generate a new one. - if (coin.getCommitmentValue().isPrime(ZEROCOIN_MINT_PRIME_PARAM) && - coin.getCommitmentValue() >= params->accumulatorParams.minCoinValue && - coin.getCommitmentValue() <= params->accumulatorParams.maxCoinValue) { - // Found a valid coin. Store it. - this->serialNumber = s; - this->randomness = coin.getRandomness(); - this->publicCoin = PublicCoin(params,coin.getCommitmentValue(), denomination); - - // Success! We're done. - return; - } - } - - // We only get here if we did not find a coin within - // MAX_COINMINT_ATTEMPTS. Throw an exception. - throw ZerocoinException("Unable to mint a new Zerocoin (too many attempts)"); -} - -void PrivateCoin::mintCoinFast(const CoinDenomination denomination) { - - // Generate a random serial number in the range 0...{q-1} where - // "q" is the order of the commitment group. - Bignum s = Bignum::randBignum(this->params->coinCommitmentGroup.groupOrder); - - // Generate a random number "r" in the range 0...{q-1} - Bignum r = Bignum::randBignum(this->params->coinCommitmentGroup.groupOrder); - - // Manually compute a Pedersen commitment to the serial number "s" under randomness "r" - // C = g^s * h^r mod p - Bignum commitmentValue = this->params->coinCommitmentGroup.g.pow_mod(s, this->params->coinCommitmentGroup.modulus).mul_mod(this->params->coinCommitmentGroup.h.pow_mod(r, this->params->coinCommitmentGroup.modulus), this->params->coinCommitmentGroup.modulus); - - // Repeat this process up to MAX_COINMINT_ATTEMPTS times until - // we obtain a prime number - for (uint32_t attempt = 0; attempt < MAX_COINMINT_ATTEMPTS; attempt++) { - // First verify that the commitment is a prime number - // in the appropriate range. If not, we'll throw this coin - // away and generate a new one. - if (commitmentValue.isPrime(ZEROCOIN_MINT_PRIME_PARAM) && - commitmentValue >= params->accumulatorParams.minCoinValue && - commitmentValue <= params->accumulatorParams.maxCoinValue) { - // Found a valid coin. Store it. - this->serialNumber = s; - this->randomness = r; - this->publicCoin = PublicCoin(params, commitmentValue, denomination); - - // Success! We're done. - return; - } - - // Generate a new random "r_delta" in 0...{q-1} - Bignum r_delta = Bignum::randBignum(this->params->coinCommitmentGroup.groupOrder); - - // The commitment was not prime. Increment "r" and recalculate "C": - // r = r + r_delta mod q - // C = C * h mod p - r = (r + r_delta) % this->params->coinCommitmentGroup.groupOrder; - commitmentValue = commitmentValue.mul_mod(this->params->coinCommitmentGroup.h.pow_mod(r_delta, this->params->coinCommitmentGroup.modulus), this->params->coinCommitmentGroup.modulus); - } - - // We only get here if we did not find a coin within - // MAX_COINMINT_ATTEMPTS. Throw an exception. - throw ZerocoinException("Unable to mint a new Zerocoin (too many attempts)"); -} - -const PublicCoin& PrivateCoin::getPublicCoin() const { - return this->publicCoin; -} - -} /* namespace libzerocoin */ diff --git a/Coin.h b/Coin.h deleted file mode 100644 index 5776b6c..0000000 --- a/Coin.h +++ /dev/null @@ -1,139 +0,0 @@ -/** - * @file Coin.h - * - * @brief PublicCoin and PrivateCoin classes for the Zerocoin library. - * - * @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. - **/ - -#ifndef COIN_H_ -#define COIN_H_ -#include "bitcoin_bignum/bignum.h" -#include "Params.h" -namespace libzerocoin { - -enum CoinDenomination { - ZQ_LOVELACE = 1, - ZQ_GOLDWASSER = 10, - ZQ_RACKOFF = 25, - ZQ_PEDERSEN = 50, - ZQ_WILLIAMSON = 100 // Malcolm J. Williamson, - // the scientist who actually invented - // Public key cryptography -}; - -/** A Public coin is the part of a coin that - * is published to the network and what is handled - * by other clients. It contains only the value - * of commitment to a serial number and the - * denomination of the coin. - */ -class PublicCoin { -public: - template - PublicCoin(const Params* p, Stream& strm): params(p) { - strm >> *this; - } - - PublicCoin( const Params* p); - - /**Generates a public coin - * - * @param p cryptographic paramters - * @param coin the value of the commitment. - * @param denomination The denomination of the coin. Defaults to ZQ_LOVELACE - */ - PublicCoin( const Params* p, const Bignum& coin, const CoinDenomination d = ZQ_LOVELACE); - const Bignum& getValue() const; - const CoinDenomination getDenomination() const; - bool operator==(const PublicCoin& rhs) const; - bool operator!=(const PublicCoin& rhs) const; - /** Checks that a coin prime - * and in the appropriate range - * given the parameters - * @return true if valid - */ - bool validate() const; - IMPLEMENT_SERIALIZE - ( - READWRITE(value); - READWRITE(denomination); - ) -private: - const Params* params; - Bignum value; - // Denomination is stored as an INT because storing - // and enum raises amigiuities in the serialize code //FIXME if possible - int denomination; -}; - -/** - * A private coin. As the name implies, the content - * of this should stay private except PublicCoin. - * - * Contains a coin's serial number, a commitment to it, - * and opening randomness for the commitment. - * - * @warning Failure to keep this secret(or safe), - * @warning will result in the theft of your coins - * @warning and a TOTAL loss of anonymity. - */ -class PrivateCoin { -public: - template - PrivateCoin(const Params* p, Stream& strm): publicCoin(p),params(p) { - strm >> *this; - } - PrivateCoin(const Params* p,const CoinDenomination denomination = ZQ_LOVELACE); - const PublicCoin& getPublicCoin() const; - const Bignum& getSerialNumber() const; - const Bignum& getRandomness() const; - - IMPLEMENT_SERIALIZE - ( - READWRITE(publicCoin); - READWRITE(randomness); - READWRITE(serialNumber); - ) -private: - const Params* params; - PublicCoin publicCoin; - Bignum randomness; - Bignum serialNumber; - - /** - * @brief Mint a new coin. - * @param denomination the denomination of the coin to mint - * @throws ZerocoinException if the process takes too long - * - * Generates a new Zerocoin by (a) selecting a random serial - * number, (b) committing to this serial number and repeating until - * the resulting commitment is prime. Stores the - * resulting commitment (coin) and randomness (trapdoor). - **/ - void mintCoin(const CoinDenomination denomination); - - /** - * @brief Mint a new coin using a faster process. - * @param denomination the denomination of the coin to mint - * @throws ZerocoinException if the process takes too long - * - * Generates a new Zerocoin by (a) selecting a random serial - * number, (b) committing to this serial number and repeating until - * the resulting commitment is prime. Stores the - * resulting commitment (coin) and randomness (trapdoor). - * This routine is substantially faster than the - * mintCoin() routine, but could be more vulnerable - * to timing attacks. Don't use it if you think someone - * could be timing your coin minting. - **/ - void mintCoinFast(const CoinDenomination denomination); - -}; - -} /* namespace libzerocoin */ -#endif /* COIN_H_ */ diff --git a/CoinSpend.cpp b/CoinSpend.cpp deleted file mode 100644 index 7187e85..0000000 --- a/CoinSpend.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/** - * @file CoinSpend.cpp - * - * @brief CoinSpend class for the Zerocoin library. - * - * @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. - **/ - -#include "Zerocoin.h" - -namespace libzerocoin { - -CoinSpend::CoinSpend(const Params* p, const PrivateCoin& coin, - Accumulator& a, const AccumulatorWitness& witness, const SpendMetaData& m): - params(p), - denomination(coin.getPublicCoin().getDenomination()), - coinSerialNumber((coin.getSerialNumber())), - accumulatorPoK(&p->accumulatorParams), - serialNumberSoK(p), - commitmentPoK(&p->serialNumberSoKCommitmentGroup, &p->accumulatorParams.accumulatorPoKCommitmentGroup) { - - // Sanity check: let's verify that the Witness is valid with respect to - // the coin and Accumulator provided. - if (!(witness.VerifyWitness(a, coin.getPublicCoin()))) { - throw ZerocoinException("Accumulator witness does not verify"); - } - - // 1: Generate two separate commitments to the public coin (C), each under - // a different set of public parameters. We do this because the RSA accumulator - // has specific requirements for the commitment parameters that are not - // compatible with the group we use for the serial number proof. - // Specifically, our serial number proof requires the order of the commitment group - // to be the same as the modulus of the upper group. The Accumulator proof requires a - // group with a significantly larger order. - const Commitment fullCommitmentToCoinUnderSerialParams(&p->serialNumberSoKCommitmentGroup, coin.getPublicCoin().getValue()); - this->serialCommitmentToCoinValue = fullCommitmentToCoinUnderSerialParams.getCommitmentValue(); - - const Commitment fullCommitmentToCoinUnderAccParams(&p->accumulatorParams.accumulatorPoKCommitmentGroup, coin.getPublicCoin().getValue()); - this->accCommitmentToCoinValue = fullCommitmentToCoinUnderAccParams.getCommitmentValue(); - - // 2. Generate a ZK proof that the two commitments contain the same public coin. - this->commitmentPoK = CommitmentProofOfKnowledge(&p->serialNumberSoKCommitmentGroup, &p->accumulatorParams.accumulatorPoKCommitmentGroup, fullCommitmentToCoinUnderSerialParams, fullCommitmentToCoinUnderAccParams); - - // Now generate the two core ZK proofs: - // 3. Proves that the committed public coin is in the Accumulator (PoK of "witness") - this->accumulatorPoK = AccumulatorProofOfKnowledge(&p->accumulatorParams, fullCommitmentToCoinUnderAccParams, witness, a); - - // 4. Proves that the coin is correct w.r.t. serial number and hidden coin secret - // (This proof is bound to the coin 'metadata', i.e., transaction hash) - this->serialNumberSoK = SerialNumberSignatureOfKnowledge(p, coin, fullCommitmentToCoinUnderSerialParams, signatureHash(m)); -} - -const Bignum& -CoinSpend::getCoinSerialNumber() { - return this->coinSerialNumber; -} - -const CoinDenomination -CoinSpend::getDenomination() { - return static_cast(this->denomination); -} - -bool -CoinSpend::Verify(const Accumulator& a, const SpendMetaData &m) const { - // Verify both of the sub-proofs using the given meta-data - return (a.getDenomination() == this->denomination) - && commitmentPoK.Verify(serialCommitmentToCoinValue, accCommitmentToCoinValue) - && accumulatorPoK.Verify(a, accCommitmentToCoinValue) - && serialNumberSoK.Verify(coinSerialNumber, serialCommitmentToCoinValue, signatureHash(m)); -} - -const uint256 CoinSpend::signatureHash(const SpendMetaData &m) const { - CHashWriter h(0,0); - h << m << serialCommitmentToCoinValue << accCommitmentToCoinValue << commitmentPoK << accumulatorPoK; - return h.GetHash(); -} - -} /* namespace libzerocoin */ diff --git a/CoinSpend.h b/CoinSpend.h deleted file mode 100644 index 51a4664..0000000 --- a/CoinSpend.h +++ /dev/null @@ -1,107 +0,0 @@ -/** - * @file CoinSpend.h - * - * @brief CoinSpend class for the Zerocoin library. - * - * @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. - **/ - -#ifndef COINSPEND_H_ -#define COINSPEND_H_ - -#include "Params.h" -#include "Coin.h" -#include "Commitment.h" -#include "bitcoin_bignum/bignum.h" -#include "Accumulator.h" -#include "AccumulatorProofOfKnowledge.h" -#include "SerialNumberSignatureOfKnowledge.h" -#include "SpendMetaData.h" -#include "bitcoin_bignum/serialize.h" - -namespace libzerocoin { - -/** The complete proof needed to spend a zerocoin. - * Composes together a proof that a coin is accumulated - * and that it has a given serial number. - */ -class CoinSpend { -public: - template - CoinSpend(const Params* p, Stream& strm):denomination(ZQ_LOVELACE), - accumulatorPoK(&p->accumulatorParams), - serialNumberSoK(p), - commitmentPoK(&p->serialNumberSoKCommitmentGroup, &p->accumulatorParams.accumulatorPoKCommitmentGroup) { - strm >> *this; - } - /**Generates a proof spending a zerocoin. - * - * To use this, provide an unspent PrivateCoin, the latest Accumulator - * (e.g from the most recent Bitcoin block) containing the public part - * of the coin, a witness to that, and whatever medeta data is needed. - * - * Once constructed, this proof can be serialized and sent. - * It is validated simply be calling validate. - * @warning Validation only checks that the proof is correct - * @warning for the specified values in this class. These values must be validated - * Clients ought to check that - * 1) params is the right params - * 2) the accumulator actually is in some block - * 3) that the serial number is unspent - * 4) that the transaction - * - * @param p cryptographic parameters - * @param coin The coin to be spend - * @param a The current accumulator containing the coin - * @param witness The witness showing that the accumulator contains the coin - * @param m arbitrary meta data related to the spend that might be needed by Bitcoin - * (i.e. the transaction hash) - * @throw ZerocoinException if the process fails - */ - CoinSpend(const Params* p, const PrivateCoin& coin, Accumulator& a, const AccumulatorWitness& witness, const SpendMetaData& m); - - /** Returns the serial number of the coin spend by this proof. - * - * @return the coin's serial number - */ - const Bignum& getCoinSerialNumber(); - - /**Gets the denomination of the coin spent in this proof. - * - * @return the denomination - */ - const CoinDenomination getDenomination(); - - bool Verify(const Accumulator& a, const SpendMetaData &metaData) const; - - IMPLEMENT_SERIALIZE - ( - READWRITE(denomination); - READWRITE(accCommitmentToCoinValue); - READWRITE(serialCommitmentToCoinValue); - READWRITE(coinSerialNumber); - READWRITE(accumulatorPoK); - READWRITE(serialNumberSoK); - READWRITE(commitmentPoK); - ) - -private: - const Params *params; - const uint256 signatureHash(const SpendMetaData &m) const; - // Denomination is stored as an INT because storing - // and enum raises amigiuities in the serialize code //FIXME if possible - int denomination; - Bignum accCommitmentToCoinValue; - Bignum serialCommitmentToCoinValue; - Bignum coinSerialNumber; - AccumulatorProofOfKnowledge accumulatorPoK; - SerialNumberSignatureOfKnowledge serialNumberSoK; - CommitmentProofOfKnowledge commitmentPoK; -}; - -} /* namespace libzerocoin */ -#endif /* COINSPEND_H_ */ diff --git a/Commitment.cpp b/Commitment.cpp deleted file mode 100644 index 720d24d..0000000 --- a/Commitment.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/** - * @file Commitment.cpp - * - * @brief Commitment and CommitmentProof classes for the Zerocoin library. - * - * @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. - **/ - -#include -#include "Zerocoin.h" - -namespace libzerocoin { - -//Commitment class -Commitment::Commitment::Commitment(const IntegerGroupParams* p, - const Bignum& value): params(p), contents(value) { - this->randomness = Bignum::randBignum(params->groupOrder); - this->commitmentValue = (params->g.pow_mod(this->contents, params->modulus).mul_mod( - params->h.pow_mod(this->randomness, params->modulus), params->modulus)); -} - -const Bignum& Commitment::getCommitmentValue() const { - return this->commitmentValue; -} - -const Bignum& Commitment::getRandomness() const { - return this->randomness; -} - -const Bignum& Commitment::getContents() const { - return this->contents; -} - -//CommitmentProofOfKnowledge class -CommitmentProofOfKnowledge::CommitmentProofOfKnowledge(const IntegerGroupParams* ap, const IntegerGroupParams* bp): ap(ap), bp(bp) {} - -// TODO: get parameters from the commitment group -CommitmentProofOfKnowledge::CommitmentProofOfKnowledge(const IntegerGroupParams* aParams, - const IntegerGroupParams* bParams, const Commitment& a, const Commitment& b): - ap(aParams),bp(bParams) -{ - Bignum r1, r2, r3; - - // First: make sure that the two commitments have the - // same contents. - if (a.getContents() != b.getContents()) { - throw ZerocoinException("Both commitments must contain the same value"); - } - - // Select three random values "r1, r2, r3" in the range 0 to (2^l)-1 where l is: - // length of challenge value + max(modulus 1, modulus 2, order 1, order 2) + margin. - // We set "margin" to be a relatively generous security parameter. - // - // We choose these large values to ensure statistical zero knowledge. - uint32_t randomSize = COMMITMENT_EQUALITY_CHALLENGE_SIZE + COMMITMENT_EQUALITY_SECMARGIN + - std::max(std::max(this->ap->modulus.bitSize(), this->bp->modulus.bitSize()), - std::max(this->ap->groupOrder.bitSize(), this->bp->groupOrder.bitSize())); - Bignum maxRange = (Bignum(2).pow(randomSize) - Bignum(1)); - - r1 = Bignum::randBignum(maxRange); - r2 = Bignum::randBignum(maxRange); - r3 = Bignum::randBignum(maxRange); - - // Generate two random, ephemeral commitments "T1, T2" - // of the form: - // T1 = g1^r1 * h1^r2 mod p1 - // T2 = g2^r1 * h2^r3 mod p2 - // - // Where (g1, h1, p1) are from "aParams" and (g2, h2, p2) are from "bParams". - Bignum T1 = this->ap->g.pow_mod(r1, this->ap->modulus).mul_mod((this->ap->h.pow_mod(r2, this->ap->modulus)), this->ap->modulus); - Bignum T2 = this->bp->g.pow_mod(r1, this->bp->modulus).mul_mod((this->bp->h.pow_mod(r3, this->bp->modulus)), this->bp->modulus); - - // Now hash commitment "A" with commitment "B" as well as the - // parameters and the two ephemeral commitments "T1, T2" we just generated - this->challenge = calculateChallenge(a.getCommitmentValue(), b.getCommitmentValue(), T1, T2); - - // Let "m" be the contents of the commitments "A, B". We have: - // A = g1^m * h1^x mod p1 - // B = g2^m * h2^y mod p2 - // T1 = g1^r1 * h1^r2 mod p1 - // T2 = g2^r1 * h2^r3 mod p2 - // - // Now compute: - // S1 = r1 + (m * challenge) -- note, not modular arithmetic - // S2 = r2 + (x * challenge) -- note, not modular arithmetic - // S3 = r3 + (y * challenge) -- note, not modular arithmetic - this->S1 = r1 + (a.getContents() * this->challenge); - this->S2 = r2 + (a.getRandomness() * this->challenge); - this->S3 = r3 + (b.getRandomness() * this->challenge); - - // We're done. The proof is S1, S2, S3 and "challenge", all of which - // are stored in member variables. -} - -bool CommitmentProofOfKnowledge::Verify(const Bignum& A, const Bignum& B) const -{ - // Compute the maximum range of S1, S2, S3 and verify that the given values are - // in a correct range. This might be an unnecessary check. - uint32_t maxSize = 64 * (COMMITMENT_EQUALITY_CHALLENGE_SIZE + COMMITMENT_EQUALITY_SECMARGIN + - std::max(std::max(this->ap->modulus.bitSize(), this->bp->modulus.bitSize()), - std::max(this->ap->groupOrder.bitSize(), this->bp->groupOrder.bitSize()))); - - if ((uint32_t)this->S1.bitSize() > maxSize || - (uint32_t)this->S2.bitSize() > maxSize || - (uint32_t)this->S3.bitSize() > maxSize || - this->S1 < Bignum(0) || - this->S2 < Bignum(0) || - this->S3 < Bignum(0) || - this->challenge < Bignum(0) || - this->challenge > (Bignum(2).pow(COMMITMENT_EQUALITY_CHALLENGE_SIZE) - Bignum(1))) { - // Invalid inputs. Reject. - return false; - } - - // Compute T1 = g1^S1 * h1^S2 * inverse(A^{challenge}) mod p1 - Bignum T1 = A.pow_mod(this->challenge, ap->modulus).inverse(ap->modulus).mul_mod( - (ap->g.pow_mod(S1, ap->modulus).mul_mod(ap->h.pow_mod(S2, ap->modulus), ap->modulus)), - ap->modulus); - - // Compute T2 = g2^S1 * h2^S3 * inverse(B^{challenge}) mod p2 - Bignum T2 = B.pow_mod(this->challenge, bp->modulus).inverse(bp->modulus).mul_mod( - (bp->g.pow_mod(S1, bp->modulus).mul_mod(bp->h.pow_mod(S3, bp->modulus), bp->modulus)), - bp->modulus); - - // Hash T1 and T2 along with all of the public parameters - Bignum computedChallenge = calculateChallenge(A, B, T1, T2); - - // Return success if the computed challenge matches the incoming challenge - if(computedChallenge == this->challenge) { - return true; - } - - // Otherwise return failure - return false; -} - -const Bignum CommitmentProofOfKnowledge::calculateChallenge(const Bignum& a, const Bignum& b, const Bignum &commitOne, const Bignum &commitTwo) const { - CHashWriter hasher(0,0); - - // Hash together the following elements: - // * A string identifying the proof - // * Commitment A - // * Commitment B - // * Ephemeral commitment T1 - // * Ephemeral commitment T2 - // * A serialized instance of the commitment A parameters - // * A serialized instance of the commitment B parameters - - hasher << std::string(ZEROCOIN_COMMITMENT_EQUALITY_PROOF); - hasher << commitOne; - hasher << std::string("||"); - hasher << commitTwo; - hasher << std::string("||"); - hasher << a; - hasher << std::string("||"); - hasher << b; - hasher << std::string("||"); - hasher << *(this->ap); - hasher << std::string("||"); - hasher << *(this->bp); - - // Convert the SHA256 result into a Bignum - // Note that if we ever change the size of the hash function we will have - // to update COMMITMENT_EQUALITY_CHALLENGE_SIZE appropriately! - return Bignum(hasher.GetHash()); -} - -} /* namespace libzerocoin */ diff --git a/Commitment.h b/Commitment.h deleted file mode 100644 index feeceab..0000000 --- a/Commitment.h +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @file Commitment.h - * - * @brief Commitment and CommitmentProof classes for the Zerocoin library. - * - * @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. - **/ - -#ifndef COMMITMENT_H_ -#define COMMITMENT_H_ - -#include "Params.h" -#include "bitcoin_bignum/serialize.h" - -// We use a SHA256 hash for our PoK challenges. Update the following -// if we ever change hash functions. -#define COMMITMENT_EQUALITY_CHALLENGE_SIZE 256 - -// A 512-bit security parameter for the statistical ZK PoK. -#define COMMITMENT_EQUALITY_SECMARGIN 512 - -namespace libzerocoin { - -/** - * A commitment, complete with contents and opening randomness. - * These should remain secret. Publish only the commitment value. - */ -class Commitment { -public: - /**Generates a Pedersen commitment to the given value. - * - * @param p the group parameters for the coin - * @param value the value to commit to - */ - Commitment(const IntegerGroupParams* p, const Bignum& value); - const Bignum& getCommitmentValue() const; - const Bignum& getRandomness() const; - const Bignum& getContents() const; -private: - const IntegerGroupParams *params; - Bignum commitmentValue; - Bignum randomness; - const Bignum contents; - IMPLEMENT_SERIALIZE - ( - READWRITE(commitmentValue); - READWRITE(randomness); - READWRITE(contents); - ) -}; - -/**Proof that two commitments open to the same value. - * - */ -class CommitmentProofOfKnowledge { -public: - CommitmentProofOfKnowledge(const IntegerGroupParams* ap, const IntegerGroupParams* bp); - /** Generates a proof that two commitments, a and b, open to the same value. - * - * @param ap the IntegerGroup for commitment a - * @param bp the IntegerGroup for commitment b - * @param a the first commitment - * @param b the second commitment - */ - CommitmentProofOfKnowledge(const IntegerGroupParams* aParams, const IntegerGroupParams* bParams, const Commitment& a, const Commitment& b); - //FIXME: is it best practice that this is here? - template - CommitmentProofOfKnowledge(const IntegerGroupParams* aParams, - const IntegerGroupParams* bParams, Stream& strm): ap(aParams), bp(bParams) - { - strm >> *this; - } - - const Bignum calculateChallenge(const Bignum& a, const Bignum& b, const Bignum &commitOne, const Bignum &commitTwo) const; - - /**Verifies the proof - * - * @return true if the proof is valid. - */ - /**Verifies the proof of equality of the two commitments - * - * @param A value of commitment one - * @param B value of commitment two - * @return - */ - bool Verify(const Bignum& A, const Bignum& B) const; - IMPLEMENT_SERIALIZE - ( - READWRITE(S1); - READWRITE(S2); - READWRITE(S3); - READWRITE(challenge); - ) -private: - const IntegerGroupParams *ap, *bp; - - Bignum S1, S2, S3, challenge; -}; - -} /* namespace libzerocoin */ -#endif /* COMMITMENT_H_ */ diff --git a/ParamGeneration.cpp b/ParamGeneration.cpp deleted file mode 100644 index 3c5e74c..0000000 --- a/ParamGeneration.cpp +++ /dev/null @@ -1,654 +0,0 @@ -/// \file ParamGeneration.cpp -/// -/// \brief Parameter manipulation routines for the Zerocoin cryptographic -/// components. -/// -/// \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. - -#include -#include "Zerocoin.h" - -using namespace std; - -namespace libzerocoin { - -/// \brief Fill in a set of Zerocoin parameters from a modulus "N". -/// \param N A trusted RSA modulus -/// \param aux An optional auxiliary string used in derivation -/// \param securityLevel A security level -/// -/// \throws ZerocoinException if the process fails -/// -/// Fills in a ZC_Params data structure deterministically from -/// a trustworthy RSA modulus "N", which is provided as a Bignum. -/// -/// Note: this routine makes the fundamental assumption that "N" -/// encodes a valid RSA-style modulus of the form "e1*e2" for some -/// unknown safe primes "e1" and "e2". These factors must not -/// be known to any party, or the security of Zerocoin is -/// compromised. The integer "N" must be a MINIMUM of 1023 -/// in length, and 3072 bits is strongly recommended. -/// - -void -CalculateParams(Params ¶ms, Bignum N, string aux, uint32_t securityLevel) -{ - params.initialized = false; - params.accumulatorParams.initialized = false; - - // Verify that |N| is > 1023 bits. - uint32_t NLen = N.bitSize(); - if (NLen < 1023) { - throw ZerocoinException("Modulus must be at least 1023 bits"); - } - - // Verify that "securityLevel" is at least 80 bits (minimum). - if (securityLevel < 80) { - throw ZerocoinException("Security level must be at least 80 bits."); - } - - // Set the accumulator modulus to "N". - params.accumulatorParams.accumulatorModulus = N; - - // Calculate the required size of the field "F_p" into which - // we're embedding the coin commitment group. This may throw an - // exception if the securityLevel is too large to be supported - // by the current modulus. - uint32_t pLen = 0; - uint32_t qLen = 0; - calculateGroupParamLengths(NLen - 2, securityLevel, &pLen, &qLen); - - // Calculate candidate parameters ("p", "q") for the coin commitment group - // using a deterministic process based on "N", the "aux" string, and - // the dedicated string "COMMITMENTGROUP". - params.coinCommitmentGroup = deriveIntegerGroupParams(calculateSeed(N, aux, securityLevel, STRING_COMMIT_GROUP), - pLen, qLen); - - // Next, we derive parameters for a second Accumulated Value commitment group. - // This is a Schnorr group with the specific property that the order of the group - // must be exactly equal to "q" from the commitment group. We set - // the modulus of the new group equal to "2q+1" and test to see if this is prime. - params.serialNumberSoKCommitmentGroup = deriveIntegerGroupFromOrder(params.coinCommitmentGroup.modulus); - - // Calculate the parameters for the internal commitment - // using the same process. - params.accumulatorParams.accumulatorPoKCommitmentGroup = deriveIntegerGroupParams(calculateSeed(N, aux, securityLevel, STRING_AIC_GROUP), - qLen + 300, qLen + 1); - - // Calculate the parameters for the accumulator QRN commitment generators. This isn't really - // a whole group, just a pair of random generators in QR_N. - uint32_t resultCtr; - params.accumulatorParams.accumulatorQRNCommitmentGroup.g = generateIntegerFromSeed(NLen - 1, - calculateSeed(N, aux, securityLevel, STRING_QRNCOMMIT_GROUPG), - &resultCtr).pow_mod(Bignum(2), N); - params.accumulatorParams.accumulatorQRNCommitmentGroup.h = generateIntegerFromSeed(NLen - 1, - calculateSeed(N, aux, securityLevel, STRING_QRNCOMMIT_GROUPH), - &resultCtr).pow_mod(Bignum(2), N); - - // Calculate the accumulator base, which we calculate as "u = C**2 mod N" - // where C is an arbitrary value. In the unlikely case that "u = 1" we increment - // "C" and repeat. - Bignum constant(ACCUMULATOR_BASE_CONSTANT); - params.accumulatorParams.accumulatorBase = Bignum(1); - for (uint32_t count = 0; count < MAX_ACCUMGEN_ATTEMPTS && params.accumulatorParams.accumulatorBase.isOne(); count++) { - params.accumulatorParams.accumulatorBase = constant.pow_mod(Bignum(2), params.accumulatorParams.accumulatorModulus); - } - - // Compute the accumulator range. The upper range is the largest possible coin commitment value. - // The lower range is sqrt(upper range) + 1. Since OpenSSL doesn't have - // a square root function we use a slightly higher approximation. - params.accumulatorParams.maxCoinValue = params.coinCommitmentGroup.modulus; - params.accumulatorParams.minCoinValue = Bignum(2).pow((params.coinCommitmentGroup.modulus.bitSize() / 2) + 3); - - // If all went well, mark params as successfully initialized. - params.accumulatorParams.initialized = true; - - // If all went well, mark params as successfully initialized. - params.initialized = true; -} - -/// \brief Format a seed string by hashing several values. -/// \param N A Bignum -/// \param aux An auxiliary string -/// \param securityLevel The security level in bits -/// \param groupName A group description string -/// \throws ZerocoinException if the process fails -/// -/// Returns the hash of the value. - -uint256 -calculateGeneratorSeed(uint256 seed, uint256 pSeed, uint256 qSeed, string label, uint32_t index, uint32_t count) -{ - CHashWriter hasher(0,0); - uint256 hash; - - // Compute the hash of: - // ||||||groupName - hasher << seed; - hasher << string("||"); - hasher << pSeed; - hasher << string("||"); - hasher << qSeed; - hasher << string("||"); - hasher << label; - hasher << string("||"); - hasher << index; - hasher << string("||"); - hasher << count; - - return hasher.GetHash(); -} - -/// \brief Format a seed string by hashing several values. -/// \param N A Bignum -/// \param aux An auxiliary string -/// \param securityLevel The security level in bits -/// \param groupName A group description string -/// \throws ZerocoinException if the process fails -/// -/// Returns the hash of the value. - -uint256 -calculateSeed(Bignum modulus, string auxString, uint32_t securityLevel, string groupName) -{ - CHashWriter hasher(0,0); - uint256 hash; - - // Compute the hash of: - // ||||||groupName - hasher << modulus; - hasher << string("||"); - hasher << securityLevel; - hasher << string("||"); - hasher << auxString; - hasher << string("||"); - hasher << groupName; - - return hasher.GetHash(); -} - -uint256 -calculateHash(uint256 input) -{ - CHashWriter hasher(0,0); - - // Compute the hash of "input" - hasher << input; - - return hasher.GetHash(); -} - -/// \brief Calculate field/group parameter sizes based on a security level. -/// \param maxPLen Maximum size of the field (modulus "p") in bits. -/// \param securityLevel Required security level in bits (at least 80) -/// \param pLen Result: length of "p" in bits -/// \param qLen Result: length of "q" in bits -/// \throws ZerocoinException if the process fails -/// -/// Calculates the appropriate sizes of "p" and "q" for a prime-order -/// subgroup of order "q" embedded within a field "F_p". The sizes -/// are based on a 'securityLevel' provided in symmetric-equivalent -/// bits. Our choices slightly exceed the specs in FIPS 186-3: -/// -/// securityLevel = 80: pLen = 1024, qLen = 256 -/// securityLevel = 112: pLen = 2048, qLen = 256 -/// securityLevel = 128: qLen = 3072, qLen = 320 -/// -/// If the length of "p" exceeds the length provided in "maxPLen", or -/// if "securityLevel < 80" this routine throws an exception. - -void -calculateGroupParamLengths(uint32_t maxPLen, uint32_t securityLevel, - uint32_t *pLen, uint32_t *qLen) -{ - *pLen = *qLen = 0; - - if (securityLevel < 80) { - throw ZerocoinException("Security level must be at least 80 bits."); - } else if (securityLevel == 80) { - *qLen = 256; - *pLen = 1024; - } else if (securityLevel <= 112) { - *qLen = 256; - *pLen = 2048; - } else if (securityLevel <= 128) { - *qLen = 320; - *pLen = 3072; - } else { - throw ZerocoinException("Security level not supported."); - } - - if (*pLen > maxPLen) { - throw ZerocoinException("Modulus size is too small for this security level."); - } -} - -/// \brief Deterministically compute a set of group parameters using NIST procedures. -/// \param seedStr A byte string seeding the process. -/// \param pLen The desired length of the modulus "p" in bits -/// \param qLen The desired length of the order "q" in bits -/// \return An IntegerGroupParams object -/// -/// Calculates the description of a group G of prime order "q" embedded within -/// a field "F_p". The input to this routine is in arbitrary seed. It uses the -/// algorithms described in FIPS 186-3 Appendix A.1.2 to calculate -/// primes "p" and "q". It uses the procedure in Appendix A.2.3 to -/// derive two generators "g", "h". - -IntegerGroupParams -deriveIntegerGroupParams(uint256 seed, uint32_t pLen, uint32_t qLen) -{ - IntegerGroupParams result; - Bignum p; - Bignum q; - uint256 pSeed, qSeed; - - // Calculate "p" and "q" and "domain_parameter_seed" from the - // "seed" buffer above, using the procedure described in NIST - // FIPS 186-3, Appendix A.1.2. - calculateGroupModulusAndOrder(seed, pLen, qLen, &(result.modulus), - &(result.groupOrder), &pSeed, &qSeed); - - // Calculate the generators "g", "h" using the process described in - // NIST FIPS 186-3, Appendix A.2.3. This algorithm takes ("p", "q", - // "domain_parameter_seed", "index"). We use "index" value 1 - // to generate "g" and "index" value 2 to generate "h". - result.g = calculateGroupGenerator(seed, pSeed, qSeed, result.modulus, result.groupOrder, 1); - result.h = calculateGroupGenerator(seed, pSeed, qSeed, result.modulus, result.groupOrder, 2); - - // Perform some basic tests to make sure we have good parameters - if ((uint32_t)(result.modulus.bitSize()) < pLen || // modulus is pLen bits long - (uint32_t)(result.groupOrder.bitSize()) < qLen || // order is qLen bits long - !(result.modulus.isPrime()) || // modulus is prime - !(result.groupOrder.isPrime()) || // order is prime - !((result.g.pow_mod(result.groupOrder, result.modulus)).isOne()) || // g^order mod modulus = 1 - !((result.h.pow_mod(result.groupOrder, result.modulus)).isOne()) || // h^order mod modulus = 1 - ((result.g.pow_mod(Bignum(100), result.modulus)).isOne()) || // g^100 mod modulus != 1 - ((result.h.pow_mod(Bignum(100), result.modulus)).isOne()) || // h^100 mod modulus != 1 - result.g == result.h || // g != h - result.g.isOne()) { // g != 1 - // If any of the above tests fail, throw an exception - throw ZerocoinException("Group parameters are not valid"); - } - - return result; -} - -/// \brief Deterministically compute a set of group parameters with a specified order. -/// \param groupOrder The order of the group -/// \return An IntegerGroupParams object -/// -/// Given "q" calculates the description of a group G of prime order "q" embedded within -/// a field "F_p". - -IntegerGroupParams -deriveIntegerGroupFromOrder(Bignum &groupOrder) -{ - IntegerGroupParams result; - - // Set the order to "groupOrder" - result.groupOrder = groupOrder; - - // Try possible values for "modulus" of the form "groupOrder * 2 * i" where - // "p" is prime and i is a counter starting at 1. - for (uint32_t i = 1; i < NUM_SCHNORRGEN_ATTEMPTS; i++) { - // Set modulus equal to "groupOrder * 2 * i" - result.modulus = (result.groupOrder * Bignum(i*2)) + Bignum(1); - - // Test the result for primality - // TODO: This is a probabilistic routine and thus not the right choice - if (result.modulus.isPrime(256)) { - - // Success. - // - // Calculate the generators "g", "h" using the process described in - // NIST FIPS 186-3, Appendix A.2.3. This algorithm takes ("p", "q", - // "domain_parameter_seed", "index"). We use "index" value 1 - // to generate "g" and "index" value 2 to generate "h". - uint256 seed = calculateSeed(groupOrder, "", 128, ""); - uint256 pSeed = calculateHash(seed); - uint256 qSeed = calculateHash(pSeed); - result.g = calculateGroupGenerator(seed, pSeed, qSeed, result.modulus, result.groupOrder, 1); - result.h = calculateGroupGenerator(seed, pSeed, qSeed, result.modulus, result.groupOrder, 2); - - // Perform some basic tests to make sure we have good parameters - if (!(result.modulus.isPrime()) || // modulus is prime - !(result.groupOrder.isPrime()) || // order is prime - !((result.g.pow_mod(result.groupOrder, result.modulus)).isOne()) || // g^order mod modulus = 1 - !((result.h.pow_mod(result.groupOrder, result.modulus)).isOne()) || // h^order mod modulus = 1 - ((result.g.pow_mod(Bignum(100), result.modulus)).isOne()) || // g^100 mod modulus != 1 - ((result.h.pow_mod(Bignum(100), result.modulus)).isOne()) || // h^100 mod modulus != 1 - result.g == result.h || // g != h - result.g.isOne()) { // g != 1 - // If any of the above tests fail, throw an exception - throw ZerocoinException("Group parameters are not valid"); - } - - return result; - } - } - - // If we reached this point group generation has failed. Throw an exception. - throw ZerocoinException("Too many attempts to generate Schnorr group."); -} - -/// \brief Deterministically compute a group description using NIST procedures. -/// \param seed A byte string seeding the process. -/// \param pLen The desired length of the modulus "p" in bits -/// \param qLen The desired length of the order "q" in bits -/// \param resultModulus A value "p" describing a finite field "F_p" -/// \param resultGroupOrder A value "q" describing the order of a subgroup -/// \param resultDomainParameterSeed A resulting seed for use in later calculations. -/// -/// Calculates the description of a group G of prime order "q" embedded within -/// a field "F_p". The input to this routine is in arbitrary seed. It uses the -/// algorithms described in FIPS 186-3 Appendix A.1.2 to calculate -/// primes "p" and "q". - -void -calculateGroupModulusAndOrder(uint256 seed, uint32_t pLen, uint32_t qLen, - Bignum *resultModulus, Bignum *resultGroupOrder, - uint256 *resultPseed, uint256 *resultQseed) -{ - // Verify that the seed length is >= qLen - if (qLen > (sizeof(seed)) * 8) { - // TODO: The use of 256-bit seeds limits us to 256-bit group orders. We should probably change this. - // throw ZerocoinException("Seed is too short to support the required security level."); - } - -#ifdef ZEROCOIN_DEBUG - cout << "calculateGroupModulusAndOrder: pLen = " << pLen << endl; -#endif - - // Generate a random prime for the group order. - // This may throw an exception, which we'll pass upwards. - // Result is the value "resultGroupOrder", "qseed" and "qgen_counter". - uint256 qseed; - uint32_t qgen_counter; - *resultGroupOrder = generateRandomPrime(qLen, seed, &qseed, &qgen_counter); - - // Using ⎡pLen / 2 + 1⎤ as the length and qseed as the input_seed, use the random prime - // routine to obtain p0 , pseed, and pgen_counter. We pass exceptions upward. - uint32_t p0len = ceil((pLen / 2.0) + 1); - uint256 pseed; - uint32_t pgen_counter; - Bignum p0 = generateRandomPrime(p0len, qseed, &pseed, &pgen_counter); - - // Set x = 0, old_counter = pgen_counter - uint32_t old_counter = pgen_counter; - - // Generate a random integer "x" of pLen bits - uint32_t iterations; - Bignum x = generateIntegerFromSeed(pLen, pseed, &iterations); - pseed += (iterations + 1); - - // Set x = 2^{pLen−1} + (x mod 2^{pLen–1}). - Bignum powerOfTwo = Bignum(2).pow(pLen-1); - x = powerOfTwo + (x % powerOfTwo); - - // t = ⎡x / (2 * resultGroupOrder * p0)⎤. - // TODO: we don't have a ceiling function - Bignum t = x / (Bignum(2) * (*resultGroupOrder) * p0); - - // Now loop until we find a valid prime "p" or we fail due to - // pgen_counter exceeding ((4*pLen) + old_counter). - for ( ; pgen_counter <= ((4*pLen) + old_counter) ; pgen_counter++) { - // If (2 * t * resultGroupOrder * p0 + 1) > 2^{pLen}, then - // t = ⎡2^{pLen−1} / (2 * resultGroupOrder * p0)⎤. - powerOfTwo = Bignum(2).pow(pLen); - Bignum prod = (Bignum(2) * t * (*resultGroupOrder) * p0) + Bignum(1); - if (prod > powerOfTwo) { - // TODO: implement a ceil function - t = Bignum(2).pow(pLen-1) / (Bignum(2) * (*resultGroupOrder) * p0); - } - - // Compute a candidate prime resultModulus = 2tqp0 + 1. - *resultModulus = (Bignum(2) * t * (*resultGroupOrder) * p0) + Bignum(1); - - // Verify that resultModulus is prime. First generate a pseudorandom integer "a". - Bignum a = generateIntegerFromSeed(pLen, pseed, &iterations); - pseed += iterations + 1; - - // Set a = 2 + (a mod (resultModulus–3)). - a = Bignum(2) + (a % ((*resultModulus) - Bignum(3))); - - // Set z = a^{2 * t * resultGroupOrder} mod resultModulus - Bignum z = a.pow_mod(Bignum(2) * t * (*resultGroupOrder), (*resultModulus)); - - // If GCD(z–1, resultModulus) == 1 AND (z^{p0} mod resultModulus == 1) - // then we have found our result. Return. - if ((resultModulus->gcd(z - Bignum(1))).isOne() && - (z.pow_mod(p0, (*resultModulus))).isOne()) { - // Success! Return the seeds and primes. - *resultPseed = pseed; - *resultQseed = qseed; - return; - } - - // This prime did not work out. Increment "t" and try again. - t = t + Bignum(1); - } // loop continues until pgen_counter exceeds a limit - - // We reach this point only if we exceeded our maximum iteration count. - // Throw an exception. - throw ZerocoinException("Unable to generate a prime modulus for the group"); -} - -/// \brief Deterministically compute a generator for a given group. -/// \param seed A first seed for the process. -/// \param pSeed A second seed for the process. -/// \param qSeed A third seed for the process. -/// \param modulus Proposed prime modulus for the field. -/// \param groupOrder Proposed order of the group. -/// \param index Index value, selects which generator you're building. -/// \return The resulting generator. -/// \throws A ZerocoinException if error. -/// -/// Generates a random group generator deterministically as a function of (seed,pSeed,qSeed) -/// Uses the algorithm described in FIPS 186-3 Appendix A.2.3. - -Bignum -calculateGroupGenerator(uint256 seed, uint256 pSeed, uint256 qSeed, Bignum modulus, Bignum groupOrder, uint32_t index) -{ - Bignum result; - - // Verify that 0 <= index < 256 - if (index > 255) { - throw ZerocoinException("Invalid index for group generation"); - } - - // Compute e = (modulus - 1) / groupOrder - Bignum e = (modulus - Bignum(1)) / groupOrder; - - // Loop until we find a generator - for (uint32_t count = 1; count < MAX_GENERATOR_ATTEMPTS; count++) { - // hash = Hash(seed || pSeed || qSeed || “ggen” || index || count - uint256 hash = calculateGeneratorSeed(seed, pSeed, qSeed, "ggen", index, count); - Bignum W(hash); - - // Compute result = W^e mod p - result = W.pow_mod(e, modulus); - - // If result > 1, we have a generator - if (result > 1) { - return result; - } - } - - // We only get here if we failed to find a generator - throw ZerocoinException("Unable to find a generator, too many attempts"); -} - -/// \brief Deterministically compute a random prime number. -/// \param primeBitLen Desired bit length of the prime. -/// \param in_seed Input seed for the process. -/// \param out_seed Result: output seed from the process. -/// \param prime_gen_counter Result: number of iterations required. -/// \return The resulting prime number. -/// \throws A ZerocoinException if error. -/// -/// Generates a random prime number of primeBitLen bits from a given input -/// seed. Uses the Shawe-Taylor algorithm as described in FIPS 186-3 -/// Appendix C.6. This is a recursive function. - -Bignum -generateRandomPrime(uint32_t primeBitLen, uint256 in_seed, uint256 *out_seed, - uint32_t *prime_gen_counter) -{ - // Verify that primeBitLen is not too small - if (primeBitLen < 2) { - throw ZerocoinException("Prime length is too short"); - } - - // If primeBitLen < 33 bits, perform the base case. - if (primeBitLen < 33) { - Bignum result(0); - - // Set prime_seed = in_seed, prime_gen_counter = 0. - uint256 prime_seed = in_seed; - (*prime_gen_counter) = 0; - - // Loop up to "4 * primeBitLen" iterations. - while ((*prime_gen_counter) < (4 * primeBitLen)) { - - // Generate a pseudorandom integer "c" of length primeBitLength bits - uint32_t iteration_count; - Bignum c = generateIntegerFromSeed(primeBitLen, prime_seed, &iteration_count); -#ifdef ZEROCOIN_DEBUG - cout << "generateRandomPrime: primeBitLen = " << primeBitLen << endl; - cout << "Generated c = " << c << endl; -#endif - - prime_seed += (iteration_count + 1); - (*prime_gen_counter)++; - - // Set "intc" to be the least odd integer >= "c" we just generated - uint32_t intc = c.getulong(); - intc = (2 * floor(intc / 2.0)) + 1; -#ifdef ZEROCOIN_DEBUG - cout << "Should be odd. c = " << intc << endl; - cout << "The big num is: c = " << c << endl; -#endif - - // Perform trial division on this (relatively small) integer to determine if "intc" - // is prime. If so, return success. - if (primalityTestByTrialDivision(intc)) { - // Return "intc" converted back into a Bignum and "prime_seed". We also updated - // the variable "prime_gen_counter" in previous statements. - result = intc; - *out_seed = prime_seed; - - // Success - return result; - } - } // while() - - // If we reached this point there was an error finding a candidate prime - // so throw an exception. - throw ZerocoinException("Unable to find prime in Shawe-Taylor algorithm"); - - // END OF BASE CASE - } - // If primeBitLen >= 33 bits, perform the recursive case. - else { - // Recurse to find a new random prime of roughly half the size - uint32_t newLength = ceil((double)primeBitLen / 2.0) + 1; - Bignum c0 = generateRandomPrime(newLength, in_seed, out_seed, prime_gen_counter); - - // Generate a random integer "x" of primeBitLen bits using the output - // of the previous call. - uint32_t numIterations; - Bignum x = generateIntegerFromSeed(primeBitLen, *out_seed, &numIterations); - (*out_seed) += numIterations + 1; - - // Compute "t" = ⎡x / (2 * c0⎤ - // TODO no Ceiling call - Bignum t = x / (Bignum(2) * c0); - - // Repeat the following procedure until we find a prime (or time out) - for (uint32_t testNum = 0; testNum < MAX_PRIMEGEN_ATTEMPTS; testNum++) { - - // If ((2 * t * c0) + 1 > 2^{primeBitLen}), - // then t = ⎡2^{primeBitLen} – 1 / (2 * c0)⎤. - if ((Bignum(2) * t * c0) > (Bignum(2).pow(Bignum(primeBitLen)))) { - t = ((Bignum(2).pow(Bignum(primeBitLen))) - Bignum(1)) / (Bignum(2) * c0); - } - - // Set c = (2 * t * c0) + 1 - Bignum c = (Bignum(2) * t * c0) + Bignum(1); - - // Increment prime_gen_counter - (*prime_gen_counter)++; - - // Test "c" for primality as follows: - // 1. First pick an integer "a" in between 2 and (c - 2) - Bignum a = generateIntegerFromSeed(c.bitSize(), (*out_seed), &numIterations); - a = Bignum(2) + (a % (c - Bignum(3))); - (*out_seed) += (numIterations + 1); - - // 2. Compute "z" = a^{2*t} mod c - Bignum z = a.pow_mod(Bignum(2) * t, c); - - // 3. Check if "c" is prime. - // Specifically, verify that gcd((z-1), c) == 1 AND (z^c0 mod c) == 1 - // If so we return "c" as our result. - if (c.gcd(z - Bignum(1)).isOne() && z.pow_mod(c0, c).isOne()) { - // Return "c", out_seed and prime_gen_counter - // (the latter two of which were already updated) - return c; - } - - // 4. If the test did not succeed, increment "t" and loop - t = t + Bignum(1); - } // end of test loop - } - - // We only reach this point if the test loop has iterated MAX_PRIMEGEN_ATTEMPTS - // and failed to identify a valid prime. Throw an exception. - throw ZerocoinException("Unable to generate random prime (too many tests)"); -} - -Bignum -generateIntegerFromSeed(uint32_t numBits, uint256 seed, uint32_t *numIterations) -{ - Bignum result(0); - uint32_t iterations = ceil((double)numBits / (double)HASH_OUTPUT_BITS); - -#ifdef ZEROCOIN_DEBUG - cout << "numBits = " << numBits << endl; - cout << "iterations = " << iterations << endl; -#endif - - // Loop "iterations" times filling up the value "result" with random bits - for (uint32_t count = 0; count < iterations; count++) { - // result += ( H(pseed + count) * 2^{count * p0len} ) - result += Bignum(calculateHash(seed + count)) * Bignum(2).pow(count * HASH_OUTPUT_BITS); - } - - result = Bignum(2).pow(numBits - 1) + (result % (Bignum(2).pow(numBits - 1))); - - // Return the number of iterations and the result - *numIterations = iterations; - return result; -} - -/// \brief Determines whether a uint32_t is a prime through trial division. -/// \param candidate Candidate to test. -/// \return true if the value is prime, false otherwise -/// -/// Performs trial division to determine whether a uint32_t is prime. - -bool -primalityTestByTrialDivision(uint32_t candidate) -{ - // TODO: HACK HACK WRONG WRONG - Bignum canBignum(candidate); - - return canBignum.isPrime(); -} - -} // namespace libzerocoin diff --git a/ParamGeneration.h b/ParamGeneration.h deleted file mode 100644 index de2d452..0000000 --- a/ParamGeneration.h +++ /dev/null @@ -1,53 +0,0 @@ -/// \file ParamGeneration.h -/// -/// \brief Parameter generation 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. - -#ifndef PARAMGENERATION_H_ -#define PARAMGENERATION_H_ - -namespace libzerocoin { - -void CalculateParams(Params ¶ms, Bignum N, std::string aux, uint32_t securityLevel); -void calculateGroupParamLengths(uint32_t maxPLen, uint32_t securityLevel, - uint32_t *pLen, uint32_t *qLen); - -// Constants -#define STRING_COMMIT_GROUP "COIN_COMMITMENT_GROUP" -#define STRING_AVC_GROUP "ACCUMULATED_VALUE_COMMITMENT_GROUP" -#define STRING_AVC_ORDER "ACCUMULATED_VALUE_COMMITMENT_ORDER" -#define STRING_AIC_GROUP "ACCUMULATOR_INTERNAL_COMMITMENT_GROUP" -#define STRING_QRNCOMMIT_GROUPG "ACCUMULATOR_QRN_COMMITMENT_GROUPG" -#define STRING_QRNCOMMIT_GROUPH "ACCUMULATOR_QRN_COMMITMENT_GROUPH" -#define ACCUMULATOR_BASE_CONSTANT 31 -#define MAX_PRIMEGEN_ATTEMPTS 10000 -#define MAX_ACCUMGEN_ATTEMPTS 10000 -#define MAX_GENERATOR_ATTEMPTS 10000 -#define NUM_SCHNORRGEN_ATTEMPTS 10000 - -// Prototypes -bool primalityTestByTrialDivision(uint32_t candidate); -uint256 calculateSeed(Bignum modulus, std::string auxString, uint32_t securityLevel, std::string groupName); -uint256 calculateGeneratorSeed(uint256 seed, uint256 pSeed, uint256 qSeed, std::string label, uint32_t index, uint32_t count); - -uint256 calculateHash(uint256 input); -IntegerGroupParams deriveIntegerGroupParams(uint256 seed, uint32_t pLen, uint32_t qLen); -IntegerGroupParams deriveIntegerGroupFromOrder(Bignum &groupOrder); -void calculateGroupModulusAndOrder(uint256 seed, uint32_t pLen, uint32_t qLen, - Bignum *resultModulus, Bignum *resultGroupOrder, - uint256 *resultPseed, uint256 *resultQseed); -Bignum calculateGroupGenerator(uint256 seed, uint256 pSeed, uint256 qSeed, Bignum modulus, - Bignum groupOrder, uint32_t index); -Bignum generateRandomPrime(uint32_t primeBitLen, uint256 in_seed, uint256 *out_seed, - uint32_t *prime_gen_counter); -Bignum generateIntegerFromSeed(uint32_t numBits, uint256 seed, uint32_t *numIterations); -bool primalityTestByTrialDivision(uint32_t candidate); - -}/* namespace libzerocoin */ - -#endif /* PARAMGENERATION_H_ */ diff --git a/Params.cpp b/Params.cpp deleted file mode 100644 index c275044..0000000 --- a/Params.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/** -* @file Params.cpp -* -* @brief Parameter class 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. -**/ -#include "Zerocoin.h" - -namespace libzerocoin { - -Params::Params(Bignum N, uint32_t securityLevel) { - this->zkp_hash_len = securityLevel; - this->zkp_iterations = securityLevel; - - this->accumulatorParams.k_prime = ACCPROOF_KPRIME; - this->accumulatorParams.k_dprime = ACCPROOF_KDPRIME; - - // Generate the parameters - CalculateParams(*this, N, ZEROCOIN_PROTOCOL_VERSION, securityLevel); - - this->accumulatorParams.initialized = true; - this->initialized = true; -} - -AccumulatorAndProofParams::AccumulatorAndProofParams() { - this->initialized = false; -} - -IntegerGroupParams::IntegerGroupParams() { - this->initialized = false; -} - -Bignum IntegerGroupParams::randomElement() const { - // The generator of the group raised - // to a random number less than the order of the group - // provides us with a uniformly distributed random number. - return this->g.pow_mod(Bignum::randBignum(this->groupOrder),this->modulus); -} - -} /* namespace libzerocoin */ diff --git a/Params.h b/Params.h deleted file mode 100644 index 60a5af4..0000000 --- a/Params.h +++ /dev/null @@ -1,216 +0,0 @@ -/** -* @file Params.h -* -* @brief Parameter classes 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. -**/ -#ifndef PARAMS_H_ -#define PARAMS_H_ - -namespace libzerocoin { - -class IntegerGroupParams { -public: - /** @brief Integer group class, default constructor - * - * Allocates an empty (uninitialized) set of parameters. - **/ - IntegerGroupParams(); - - /** - * Generates a random group element - * @return a random element in the group. - */ - Bignum randomElement() const; - bool initialized; - - /** - * A generator for the group. - */ - Bignum g; - - /** - * A second generator for the group. - * Note log_g(h) and log_h(g) must - * be unknown. - */ - Bignum h; - - /** - * The modulus for the group. - */ - Bignum modulus; - - /** - * The order of the group - */ - Bignum groupOrder; - - IMPLEMENT_SERIALIZE - ( - READWRITE(initialized); - READWRITE(g); - READWRITE(h); - READWRITE(modulus); - READWRITE(groupOrder); - ) -}; - -class AccumulatorAndProofParams { -public: - /** @brief Construct a set of Zerocoin parameters from a modulus "N". - * @param N A trusted RSA modulus - * @param securityLevel A security level expressed in symmetric bits (default 80) - * - * Allocates and derives a set of Zerocoin parameters from - * a trustworthy RSA modulus "N". This routine calculates all - * of the remaining parameters (group descriptions etc.) from N - * using a verifiable, deterministic procedure. - * - * Note: this constructor makes the fundamental assumption that "N" - * encodes a valid RSA-style modulus of the form "e1 * e2" where - * "e1" and "e2" are safe primes. The factors "e1", "e2" MUST NOT - * be known to any party, or the security of Zerocoin is - * compromised. The integer "N" must be a MINIMUM of 1024 - * in length. 3072 bits is strongly recommended. - **/ - AccumulatorAndProofParams(); - - //AccumulatorAndProofParams(Bignum accumulatorModulus); - - bool initialized; - - /** - * Modulus used for the accumulator. - * Product of two safe primes who's factorization is unknown. - */ - Bignum accumulatorModulus; - - /** - * The initial value for the accumulator - * A random Quadratic residue mod n thats not 1 - */ - Bignum accumulatorBase; - - /** - * Lower bound on the value for committed coin. - * Required by the accumulator proof. - */ - Bignum minCoinValue; - - /** - * Upper bound on the value for a comitted coin. - * Required by the accumulator proof. - */ - Bignum maxCoinValue; - - /** - * The second of two groups used to form a commitment to - * a coin (which it self is a commitment to a serial number). - * This one differs from serialNumberSokCommitment due to - * restrictions from Camenisch and Lysyanskaya's paper. - */ - IntegerGroupParams accumulatorPoKCommitmentGroup; - - /** - * Hidden order quadratic residue group mod N. - * Used in the accumulator proof. - */ - IntegerGroupParams accumulatorQRNCommitmentGroup; - - /** - * Security parameter. - * Bit length of the challenges used in the accumulator proof. - */ - uint32_t k_prime; - - /** - * Security parameter. - * The statistical zero-knowledgeness of the accumulator proof. - */ - uint32_t k_dprime; - - IMPLEMENT_SERIALIZE - ( - READWRITE(initialized); - READWRITE(accumulatorModulus); - READWRITE(accumulatorBase); - READWRITE(accumulatorPoKCommitmentGroup); - READWRITE(accumulatorQRNCommitmentGroup); - READWRITE(minCoinValue); - READWRITE(maxCoinValue); - READWRITE(k_prime); - READWRITE(k_dprime); - ) -}; - -class Params { -public: - /** @brief Construct a set of Zerocoin parameters from a modulus "N". - * @param N A trusted RSA modulus - * @param securityLevel A security level expressed in symmetric bits (default 80) - * - * Allocates and derives a set of Zerocoin parameters from - * a trustworthy RSA modulus "N". This routine calculates all - * of the remaining parameters (group descriptions etc.) from N - * using a verifiable, deterministic procedure. - * - * Note: this constructor makes the fundamental assumption that "N" - * encodes a valid RSA-style modulus of the form "e1 * e2" where - * "e1" and "e2" are safe primes. The factors "e1", "e2" MUST NOT - * be known to any party, or the security of Zerocoin is - * compromised. The integer "N" must be a MINIMUM of 1024 - * in length. 3072 bits is strongly recommended. - **/ - Params(Bignum accumulatorModulus, - uint32_t securityLevel = ZEROCOIN_DEFAULT_SECURITYLEVEL); - - bool initialized; - - AccumulatorAndProofParams accumulatorParams; - - /** - * The Quadratic Residue group from which we form - * a coin as a commitment to a serial number. - */ - IntegerGroupParams coinCommitmentGroup; - - /** - * One of two groups used to form a commitment to - * a coin (which it self is a commitment to a serial number). - * This is the one used in the serial number poof. - * It's order must be equal to the modulus of coinCommitmentGroup. - */ - IntegerGroupParams serialNumberSoKCommitmentGroup; - - /** - * The number of iterations to use in the serial - * number proof. - */ - uint32_t zkp_iterations; - - /** - * The amount of the hash function we use for - * proofs. - */ - uint32_t zkp_hash_len; - - IMPLEMENT_SERIALIZE - ( - READWRITE(initialized); - READWRITE(accumulatorParams); - READWRITE(coinCommitmentGroup); - READWRITE(serialNumberSoKCommitmentGroup); - READWRITE(zkp_iterations); - READWRITE(zkp_hash_len); - ) -}; - -} /* namespace libzerocoin */ - -#endif /* PARAMS_H_ */ diff --git a/README.cmake b/README.cmake deleted file mode 100644 index 52e15b0..0000000 --- a/README.cmake +++ /dev/null @@ -1,48 +0,0 @@ -# Using CMake to build libzerocoin - -CMake version 2.8 or newer is required. - -Create a build directory wherever you like: - -$ mkdir build -$ cd build - -Run CMake, pointing it to the source directory: - -$ cmake .. - -Now run the make command to compile the library: - -$ make - -Install the library into the system to use: - -$ sudo make install - -Finally, tell the system to rescan the shared library directories: - -$ sudo ldconfig - -The test, benchmark, tutorial, and paramgen utilites are compiled but -not installed into the system. - -# CMake build options - -If you wish to install libzerocoin into a non-default prefix (that is, -not to /usr/local/* ), then run cmake with this option: - -$ cmake -DCMAKE_INSTALL_PREFIX= - -e.g., to install to /opt/zerocoin, run: - -$ cmake -DCMAKE_INSTALL_PREFIX=/opt/zerocoin .. - -To make a debug version of the library, add -DCMAKE_BUILD_TYPE=DEBUG -to the cmake command line: - -$ cmake -DCMAKE_BUILD_TYPE=DEBUG .. - -When compiling the library with 'make' you can set VERBOSE=1 to show -the process in more detail: - -$ make VERBOSE=1 diff --git a/README.md b/README.md index 459f9f6..8c5ec05 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,22 @@ +### WE WEREN'T JOKING. THERE WERE WARNINGS THAT THIS WAS BUGGY PROTOTYPE CODE AND YOU USED IT ANYWAY. SO WE'VE TAKEN AWAY THE MAKEFILE. THIS CODE IS ABANDONED (AND HAS BEEN SINCE 2014) + + +THIS CODE IS UNMAINTAINED AND HAS KNOWN EXPLOITS. DO NOT USE IT. + + +THERE ARE DOWNSTREAM COPIES THAT MIGHT HAVE BETTER SECURITY. THEN AGAIN, SOME PROJECTS COPIED THE CODE VERBATIM COMPLETE WITH THE BELOW WARNING, SO CAVEAT EMPTOR. + +The successor protocol that has undergone substaintial cryptographic and code review is Zerocash/Zcash. More can be found at https://github.com/zcash. We strongly suggest you use that instead. It is also open source. + # Introduction -libzerocoin is a C++ library that implements the core cryptographic routines of the Zerocoin protocol. Zerocoin is a distributed anonymous cash extension for Bitcoin-type (hash chain based) protocols. The protocol uses zero knowledge proofs to implement a fully decentralized coin laundry. + +libzerocoin WAS a C++ library that implemented the core cryptographic routines of the Zerocoin protocol. Zerocoin is a distributed anonymous cash extension for Bitcoin-type (hash chain based) protocols. The protocol uses zero knowledge proofs to implement a fully decentralized coin laundry. The Zerocoin protocol is provably secure and uses well-studied cryptographic primitives. For a complete description of the protocol, see our white paper published in the IEEE Security & Privacy Symposium (2013) below. ### WARNING -**THIS IS DEVELOPMENT SOFTWARE. WE DON'T CERTIFY IT FOR PRODUCTION USE. WE ARE RELEASING THIS DEV VERSION FOR THE COMMUNITY TO EXAMINE, TEST AND (PROBABLY) BREAK. IF YOU SEE SOMETHING, [SAY SOMETHING](https://github.com/Zerocoin/libzerocoin/issues)! IN THE COMING WEEKS WE WILL LIKELY MAKE CHANGES TO THE WIRE PROTOCOL THAT COULD BREAK CLIENT COMPATIBILITY. SEE [[HOW TO CONTRIBUTE]] FOR A LIST OF WAYS YOU CAN HELP US.** +**THIS IS DEVELOPMENT SOFTWARE. WE DON'T CERTIFY IT FOR PRODUCTION USE. WE ARE RELEASING THIS DEV VERSION FOR THE COMMUNITY TO EXAMINE, TEST AND (PROBABLY) BREAK. IF YOU SEE SOMETHING, [SAY SOMETHING](https://github.com/Zerocoin/libzerocoin/issues)! IN THE COMING WEEKS WE WILL LIKELY MAKE CHANGES TO THE WIRE PROTOCOL THAT COULD BREAK CLIENT COMPATIBILITY. SEE [HOW TO CONTRIBUTE](https://github.com/Zerocoin/libzerocoin/wiki/How-to-contribute) FOR A LIST OF WAYS YOU CAN HELP US.** ### WARNING WARNING **NO, SERIOUSLY. THE ABOVE WARNING IS NOT JUST BOILERPLATE. THIS REALLY IS DEVELOPMENT CODE AND WE'RE STILL ACTIVELY LOOKING FOR THE THINGS WE'VE INEVITABLY DONE WRONG. PLEASE DON'T BE SURPRISED IF YOU FIND OUT WE MISSED SOMETHING FUNDAMENTAL. WE WILL BE TESTING AND IMPROVING IT OVER THE COMING WEEKS.** @@ -24,7 +35,7 @@ libzerocoin implements the core cryptographic operations of Zerocoin. These incl 4. Accumulator calculation 5. Coin and spend proof verification -This library does _not_ implement the full Zerocoin protocol. In addition to the above cryptographic routines, a full Zerocoin implementation requires several specialized Zerocoin messages, double spending checks, and some additional coin redemption logic that must be supported by all clients in the network. libzerocoin does not provide routines to support these functions, although we do provide an overview on the [[Integrating with Bitcoin clients]] page. +This library does _not_ implement the full Zerocoin protocol. In addition to the above cryptographic routines, a full Zerocoin implementation requires several specialized Zerocoin messages, double spending checks, and some additional coin redemption logic that must be supported by all clients in the network. libzerocoin does not provide routines to support these functions, although we do provide an overview on the [Integrating with Bitcoin clients](https://github.com/Zerocoin/libzerocoin/wiki/Integrating-with-bitcoin-clients) page. # Outside links diff --git a/SerialNumberSignatureOfKnowledge.cpp b/SerialNumberSignatureOfKnowledge.cpp deleted file mode 100644 index 1654c50..0000000 --- a/SerialNumberSignatureOfKnowledge.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/** -* @file SerialNumberSignatureOfKnowledge.cpp -* -* @brief SerialNumberSignatureOfKnowledge class for the Zerocoin library. -* -* @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. -**/ - -#include "Zerocoin.h" - -namespace libzerocoin { - -SerialNumberSignatureOfKnowledge::SerialNumberSignatureOfKnowledge(const Params* p): params(p) { } - -SerialNumberSignatureOfKnowledge::SerialNumberSignatureOfKnowledge(const - Params* p, const PrivateCoin& coin, const Commitment& commitmentToCoin, - uint256 msghash):params(p), - s_notprime(p->zkp_iterations), - sprime(p->zkp_iterations) { - - // Sanity check: verify that the order of the "accumulatedValueCommitmentGroup" is - // equal to the modulus of "coinCommitmentGroup". Otherwise we will produce invalid - // proofs. - if (params->coinCommitmentGroup.modulus != params->serialNumberSoKCommitmentGroup.groupOrder) { - throw ZerocoinException("Groups are not structured correctly."); - } - - Bignum a = params->coinCommitmentGroup.g; - Bignum b = params->coinCommitmentGroup.h; - Bignum g = params->serialNumberSoKCommitmentGroup.g; - Bignum h = params->serialNumberSoKCommitmentGroup.h; - - CHashWriter hasher(0,0); - hasher << *params << commitmentToCoin.getCommitmentValue() << coin.getSerialNumber(); - - vector r(params->zkp_iterations); - vector v(params->zkp_iterations); - vector c(params->zkp_iterations); - - - for(uint32_t i=0; i < params->zkp_iterations; i++) { - //FIXME we really ought to use one BN_CTX for all of these - // operations for performance reasons, not the one that - // is created individually by the wrapper - r[i] = Bignum::randBignum(params->coinCommitmentGroup.groupOrder); - v[i] = Bignum::randBignum(params->serialNumberSoKCommitmentGroup.groupOrder); - } - - // Openssl's rng is not thread safe, so we don't call it in a parallel loop, - // instead we generate the random values beforehand and run the calculations - // based on those values in parallel. -#ifdef ZEROCOIN_THREADING - #pragma omp parallel for -#endif - for(uint32_t i=0; i < params->zkp_iterations; i++) { - // compute g^{ {a^x b^r} h^v} mod p2 - c[i] = challengeCalculation(coin.getSerialNumber(), r[i], v[i]); - } - - // We can't hash data in parallel either - // because OPENMP cannot not guarantee loops - // execute in order. - for(uint32_t i=0; i < params->zkp_iterations; i++) { - hasher << c[i]; - } - this->hash = hasher.GetHash(); - unsigned char *hashbytes = (unsigned char*) &hash; - -#ifdef ZEROCOIN_THREADING - #pragma omp parallel for -#endif - for(uint32_t i = 0; i < params->zkp_iterations; i++) { - int bit = i % 8; - int byte = i / 8; - - bool challenge_bit = ((hashbytes[byte] >> bit) & 0x01); - if (challenge_bit) { - s_notprime[i] = r[i]; - sprime[i] = v[i]; - } else { - s_notprime[i] = r[i] - coin.getRandomness(); - sprime[i] = v[i] - (commitmentToCoin.getRandomness() * - b.pow_mod(r[i] - coin.getRandomness(), params->serialNumberSoKCommitmentGroup.groupOrder)); - } - } -} - -inline Bignum SerialNumberSignatureOfKnowledge::challengeCalculation(const Bignum& a_exp,const Bignum& b_exp, - const Bignum& h_exp) const { - - Bignum a = params->coinCommitmentGroup.g; - Bignum b = params->coinCommitmentGroup.h; - Bignum g = params->serialNumberSoKCommitmentGroup.g; - Bignum h = params->serialNumberSoKCommitmentGroup.h; - - Bignum exponent = (a.pow_mod(a_exp, params->serialNumberSoKCommitmentGroup.groupOrder) - * b.pow_mod(b_exp, params->serialNumberSoKCommitmentGroup.groupOrder)) % params->serialNumberSoKCommitmentGroup.groupOrder; - - return (g.pow_mod(exponent, params->serialNumberSoKCommitmentGroup.modulus) * h.pow_mod(h_exp, params->serialNumberSoKCommitmentGroup.modulus)) % params->serialNumberSoKCommitmentGroup.modulus; -} - -bool SerialNumberSignatureOfKnowledge::Verify(const Bignum& coinSerialNumber, const Bignum& valueOfCommitmentToCoin, - const uint256 msghash) const { - Bignum a = params->coinCommitmentGroup.g; - Bignum b = params->coinCommitmentGroup.h; - Bignum g = params->serialNumberSoKCommitmentGroup.g; - Bignum h = params->serialNumberSoKCommitmentGroup.h; - CHashWriter hasher(0,0); - hasher << *params << valueOfCommitmentToCoin < tprime(params->zkp_iterations); - unsigned char *hashbytes = (unsigned char*) &this->hash; -#ifdef ZEROCOIN_THREADING - #pragma omp parallel for -#endif - for(uint32_t i = 0; i < params->zkp_iterations; i++) { - int bit = i % 8; - int byte = i / 8; - bool challenge_bit = ((hashbytes[byte] >> bit) & 0x01); - if(challenge_bit) { - tprime[i] = challengeCalculation(coinSerialNumber, s_notprime[i], sprime[i]); - } else { - Bignum exp = b.pow_mod(s_notprime[i], params->serialNumberSoKCommitmentGroup.groupOrder); - tprime[i] = ((valueOfCommitmentToCoin.pow_mod(exp, params->serialNumberSoKCommitmentGroup.modulus) % params->serialNumberSoKCommitmentGroup.modulus) * - (h.pow_mod(sprime[i], params->serialNumberSoKCommitmentGroup.modulus) % params->serialNumberSoKCommitmentGroup.modulus)) % - params->serialNumberSoKCommitmentGroup.modulus; - } - } - for(uint32_t i = 0; i < params->zkp_iterations; i++) { - hasher << tprime[i]; - } - return hasher.GetHash() == hash; -} - -} /* namespace libzerocoin */ diff --git a/SerialNumberSignatureOfKnowledge.h b/SerialNumberSignatureOfKnowledge.h deleted file mode 100644 index cbc979b..0000000 --- a/SerialNumberSignatureOfKnowledge.h +++ /dev/null @@ -1,75 +0,0 @@ -/** -* @file SerialNumberSignatureOfKnowledge.h -* -* @brief SerialNumberSignatureOfKnowledge class for the Zerocoin library. -* -* @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. -**/ - -#ifndef SERIALNUMBERPROOF_H_ -#define SERIALNUMBERPROOF_H_ - -#include -#include -#include -#include "Params.h" -#include "Coin.h" -#include "Commitment.h" -#include "bitcoin_bignum/bignum.h" -#include "bitcoin_bignum/serialize.h" -#include "Accumulator.h" -#include "bitcoin_bignum/hash.h" - -using namespace std; -namespace libzerocoin { - -/**A Signature of knowledge on the hash of metadata attesting that the signer knows the values - * necessary to open a commitment which contains a coin(which it self is of course a commitment) - * with a given serial number. - */ -class SerialNumberSignatureOfKnowledge { -public: - SerialNumberSignatureOfKnowledge(const Params* p); - /** Creates a Signature of knowledge object that a commitment to a coin contains a coin with serial number x - * - * @param p params - * @param coin the coin we are going to prove the serial number of. - * @param commitmentToCoin the commitment to the coin - * @param msghash hash of meta data to create a signature of knowledge on. - */ - SerialNumberSignatureOfKnowledge(const Params* p, const PrivateCoin& coin, const Commitment& commitmentToCoin, uint256 msghash); - - /** Verifies the Signature of knowledge. - * - * @param msghash hash of meta data to create a signature of knowledge on. - * @return - */ - bool Verify(const Bignum& coinSerialNumber, const Bignum& valueOfCommitmentToCoin,const uint256 msghash) const; - - IMPLEMENT_SERIALIZE - ( - READWRITE(s_notprime); - READWRITE(sprime); - READWRITE(hash); - ) -private: - const Params* params; - // challenge hash - uint256 hash; //TODO For efficiency, should this be a bitset where Templates define params? - - // challenge response values - // this is s_notprime instead of s - // because the serialization macros - // define something named s and it conflicts - vector s_notprime; - vector sprime; - inline Bignum challengeCalculation(const Bignum& a_exp, const Bignum& b_exp, - const Bignum& h_exp) const; -}; - -} /* namespace libzerocoin */ -#endif /* SERIALNUMBERPROOF_H_ */ diff --git a/SpendMetaData.cpp b/SpendMetaData.cpp deleted file mode 100644 index 83d5619..0000000 --- a/SpendMetaData.cpp +++ /dev/null @@ -1,19 +0,0 @@ -/** -* @file SpendMetaData.cpp -* -* @brief SpendMetaData class for the Zerocoin library. -* -* @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. -**/ - -#include "Zerocoin.h" - -namespace libzerocoin { - -SpendMetaData::SpendMetaData(uint256 accumulatorId, uint256 txHash): accumulatorId(accumulatorId), txHash(txHash) {} - -} /* namespace libzerocoin */ diff --git a/SpendMetaData.h b/SpendMetaData.h deleted file mode 100644 index c8eff1b..0000000 --- a/SpendMetaData.h +++ /dev/null @@ -1,52 +0,0 @@ -/** -* @file SpendMetaData.h -* -* @brief SpendMetaData class for the Zerocoin library. -* -* @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. -**/ - -#ifndef SPENDMETADATA_H_ -#define SPENDMETADATA_H_ - -#include "bitcoin_bignum/uint256.h" -#include "bitcoin_bignum/serialize.h" - -using namespace std; -namespace libzerocoin { - -/** Any meta data needed for actual bitcoin integration. - * Can extended provided the getHash() function is updated - */ -class SpendMetaData { -public: - /** - * Creates meta data associated with a coin spend - * @param accumulatorId hash of block containing accumulator - * @param txHash hash of transaction - */ - SpendMetaData(uint256 accumulatorId, uint256 txHash); - - /** - * The hash of the block containing the accumulator CoinSpend - * proves membership in. - */ - uint256 accumulatorId; // The block the accumulator is in - /**Contains the hash of the rest of transaction - * spending a zerocoin (excluding the coinspend proof) - */ - uint256 txHash; // The Hash of the rest of the transaction the spend proof is n. - // Allows us to sign the transaction. - IMPLEMENT_SERIALIZE - ( - READWRITE(accumulatorId); - READWRITE(txHash); - ) -}; - -} /* namespace libzerocoin */ -#endif /* SPENDMETADATA_H_ */ diff --git a/Tests.cpp b/Tests.cpp deleted file mode 100644 index 54ea5bd..0000000 --- a/Tests.cpp +++ /dev/null @@ -1,484 +0,0 @@ -/** -* @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" - -using namespace libzerocoin; - -#define COLOR_STR_GREEN "\033[32m" -#define COLOR_STR_NORMAL "\033[0m" -#define COLOR_STR_RED "\033[31m" - -#define TESTS_COINS_TO_ACCUMULATE 10 -#define NON_PRIME_TESTS 100 - -// 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)()) -{ - string colorGreen(COLOR_STR_GREEN); - string colorNormal(COLOR_STR_NORMAL); - string colorRed(COLOR_STR_RED); - - cout << "Testing if " << testName << "..." << endl; - - bool testResult = testPtr(); - - if (testResult == true) { - cout << "\t" << colorGreen << "[PASS]" << colorNormal << endl; - gSuccessfulTests++; - } else { - cout << colorRed << "\t[FAIL]" << colorNormal << endl; - } - - 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() -{ - uint32_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) { - cout << "Caught exception " << e.what() << endl; - 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); - //cout << "g^q mod p = " << c << endl; - 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) { - cout << e.what() << endl; - 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()) { - cout << "Accumulators don't match" << endl; - return false; - } - - if(accFour.getValue() != wThree.getValue()) { - cout << "Witness math not working," << endl; - return false; - } - - // Verify that the witness is correct - if (!wThree.VerifyWitness(accThree, gCoins[0]->getPublicCoin()) ) { - cout << "Witness not valid" << endl; - 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_InvalidCoin() -{ - Bignum coinValue; - - try { - // Pick a random non-prime Bignum - for (uint32_t i = 0; i < NON_PRIME_TESTS; i++) { - coinValue = Bignum::randBignum(g_Params->coinCommitmentGroup.modulus); - coinValue = coinValue * 2; - if (!coinValue.isPrime()) break; - } - - PublicCoin pubCoin(g_Params); - if (pubCoin.validate()) { - // A blank coin should not be valid! - return false; - } - - PublicCoin pubCoin2(g_Params, coinValue, ZQ_LOVELACE); - if (pubCoin2.validate()) { - // A non-prime coin should not be valid! - return false; - } - - PublicCoin pubCoin3 = pubCoin2; - if (pubCoin2.validate()) { - // A copy of a non-prime coin should not be valid! - return false; - } - - // Serialize and deserialize the coin - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << pubCoin; - PublicCoin pubCoin4(g_Params, ss); - if (pubCoin4.validate()) { - // A deserialized copy of a non-prime coin should not be valid! - return false; - } - - } catch (runtime_error &e) { - cout << "Caught exception: " << e.what() << endl; - 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); - CDataStream cc(SER_NETWORK, PROTOCOL_VERSION); - cc << *gCoins[0]; - PrivateCoin myCoin(g_Params,cc); - - CoinSpend spend(g_Params, myCoin, 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) { - cout << e.what() << endl; - return false; - } - - return false; -} - -void -Test_RunAllTests() -{ - // Make a new set of parameters from a random RSA modulus - g_Params = new Params(GetTestModulus()); - - 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("invalid coins will be rejected", Test_InvalidCoin); - LogTestResult("the accumulator works", Test_Accumulator); - LogTestResult("the commitment equality PoK works", Test_EqualityPoK); - LogTestResult("a minted coin can be spent", Test_MintAndSpend); - - cout << endl << "Average coin size is " << gCoinSize << " bytes." << endl; - cout << "Serial number size is " << gSerialNumberSize << " bytes." << endl; - cout << "Spend proof size is " << gProofSize << " bytes." << endl; - - // Summarize test results - if (gSuccessfulTests < gNumTests) { - cout << endl << "ERROR: SOME TESTS FAILED" << endl; - } - - // Clear any generated coins - for (uint32_t i = 0; i < TESTS_COINS_TO_ACCUMULATE; i++) { - delete gCoins[i]; - } - - cout << endl << gSuccessfulTests << " out of " << gNumTests << " tests passed." << endl << endl; - delete g_Params; -} - -int main(int argc, char **argv) -{ - cout << "libzerocoin v" << ZEROCOIN_VERSION_STRING << " test utility." << endl << endl; - - Test_RunAllTests(); -} diff --git a/Tutorial.cpp b/Tutorial.cpp deleted file mode 100644 index 21437e8..0000000 --- a/Tutorial.cpp +++ /dev/null @@ -1,285 +0,0 @@ -/** -* @file tutorial.cpp -* -* @brief Simple tutorial program to illustrate Zerocoin usage. -* -* @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" - -#define COINS_TO_ACCUMULATE 5 -#define DUMMY_TRANSACTION_HASH 0 // in real life these would be uint256 hashes -#define DUMMY_ACCUMULATOR_ID 0 // in real life these would be uint256 hashes - -// -// We generated this for testing only. Don't use it in production! -// -#define TUTORIAL_TEST_MODULUS "a8852ebf7c49f01cd196e35394f3b74dd86283a07f57e0a262928e7493d4a3961d93d93c90ea3369719641d626d28b9cddc6d9307b9aabdbffc40b6d6da2e329d079b4187ff784b2893d9f53e9ab913a04ff02668114695b07d8ce877c4c8cac1b12b9beff3c51294ebe349eca41c24cd32a6d09dd1579d3947e5c4dcc30b2090b0454edb98c6336e7571db09e0fdafbd68d8f0470223836e90666a5b143b73b9cd71547c917bf24c0efc86af2eba046ed781d9acb05c80f007ef5a0a5dfca23236f37e698e8728def12554bc80f294f71c040a88eff144d130b24211016a97ce0f5fe520f477e555c9997683d762aff8bd1402ae6938dd5c994780b1bf6aa7239e9d8101630ecfeaa730d2bbc97d39beb057f016db2e28bf12fab4989c0170c2593383fd04660b5229adcd8486ba78f6cc1b558bcd92f344100dff239a8c00dbc4c2825277f24bdd04475bcc9a8c39fd895eff97c1967e434effcb9bd394e0577f4cf98c30d9e6b54cd47d6e447dcf34d67e48e4421691dbe4a7d9bd503abb9" - -// -// The following routine exercises most of the core functions of -// the library. We've commented it as well as possible to give -// you the flavor of how libzerocoin works. -// -// For details on Zerocoin integration, see the libzerocoin wiki -// at: https://github.com/Zerocoin/libzerocoin/wiki -// - -bool -ZerocoinTutorial() -{ - // The following simple code illustrates the call flow for Zerocoin - // applications. In a real currency network these operations would - // be split between individual payers/payees, network nodes and miners. - // - // For each call we specify the participant who would use it. - - // Zerocoin uses exceptions (based on the runtime_error class) - // to indicate all sorts of problems. Always remember to catch them! - - try { - - /********************************************************************/ - // What is it: Parameter loading - // Who does it: ALL ZEROCOIN PARTICIPANTS - // What it does: Loads a trusted Zerocoin modulus "N" and - // generates all associated parameters from it. - // We use a hardcoded "N" that we generated using - // the included 'paramgen' utility. - /********************************************************************/ - - // Load a test modulus from our hardcoded string (above) - Bignum testModulus; - testModulus.SetHex(std::string(TUTORIAL_TEST_MODULUS)); - - // Set up the Zerocoin Params object - libzerocoin::Params* params = new libzerocoin::Params(testModulus); - - cout << "Successfully loaded parameters." << endl; - - /********************************************************************/ - // What is it: Coin generation - // Who does it: ZEROCOIN CLIENTS - // What it does: Generates a new 'zerocoin' coin using the - // public parameters. Once generated, the client - // will transmit the public portion of this coin - // in a ZEROCOIN_MINT transaction. The inputs - // to this transaction must add up to the zerocoin - // denomination plus any transaction fees. - /********************************************************************/ - - // The following constructor does all the work of minting a brand - // new zerocoin. It stores all the private values inside the - // PrivateCoin object. This includes the coin secrets, which must be - // stored in a secure location (wallet) at the client. - libzerocoin::PrivateCoin newCoin(params); - - // Get a copy of the 'public' portion of the coin. You should - // embed this into a Zerocoin 'MINT' transaction along with a series - // of currency inputs totaling the assigned value of one zerocoin. - libzerocoin::PublicCoin pubCoin = newCoin.getPublicCoin(); - - cout << "Successfully minted a zerocoin." << endl; - - // Serialize the public coin to a CDataStream object. - CDataStream serializedCoin(SER_NETWORK, PROTOCOL_VERSION); - serializedCoin << pubCoin; - - /********************************************************************/ - // What is it: Coin verification - // Who does it: TRANSACTION VERIFIERS - // What it does: Verifies the structure of a zerocoin obtained from - // a ZEROCOIN_MINT transaction. All coins must be - // verified before you operate on them. - // Note that this is only part of the transaction - // verification process! The client must also check - // that (1) the inputs to the transaction are valid - // and add up to the value of one zerocoin, (2) that - // this particular zerocoin has not been minted before. - /********************************************************************/ - - // Deserialize the public coin into a fresh object. - libzerocoin::PublicCoin pubCoinNew(params, serializedCoin); - - // Now make sure the coin is valid. - if (!pubCoinNew.validate()) { - // If this returns false, don't accept the coin for any purpose! - // Any ZEROCOIN_MINT with an invalid coin should NOT be - // accepted as a valid transaction in the block chain. - cout << "Error: coin is not valid!"; - } - - cout << "Deserialized and verified the coin." << endl; - - /********************************************************************/ - // What is it: Accumulator computation - // Who does it: ZEROCOIN CLIENTS & TRANSACTION VERIFIERS - // What it does: Collects a number of PublicCoin values drawn from - // the block chain and calculates an accumulator. - // This accumulator is incrementally computable; - // you can stop and serialize it at any point - // then continue accumulating new transactions. - // The accumulator is also order-independent, so - // the same coins can be accumulated in any order - // to give the same result. - // WARNING: do not accumulate the same coin twice! - /********************************************************************/ - - // Create an empty accumulator object - libzerocoin::Accumulator accumulator(params); - - // Add several coins to it (we'll generate them here on the fly). - for (uint32_t i = 0; i < COINS_TO_ACCUMULATE; i++) { - libzerocoin::PrivateCoin testCoin(params); - accumulator += testCoin.getPublicCoin(); - } - - // Serialize the accumulator object. - // - // If you're using Accumulator Checkpoints, each miner would - // start by deserializing the accumulator checkpoint from the - // previous block (or creating a new Accumulator if no previous - // block exists). It will then add all the coins in the new block, - // then serialize the resulting Accumulator object to obtain the - // new checkpoint. All block verifiers should do the same thing - // to check their work. - CDataStream serializedAccumulator(SER_NETWORK, PROTOCOL_VERSION); - serializedAccumulator << accumulator; - - // Deserialize the accumulator object - libzerocoin::Accumulator newAccumulator(params, serializedAccumulator); - - // We can now continue accumulating things into the accumulator - // we just deserialized. For example, let's put in the coin - // we generated up above. - newAccumulator += pubCoinNew; - - cout << "Successfully accumulated coins." << endl; - - /********************************************************************/ - // What is it: Coin spend - // Who does it: ZEROCOIN CLIENTS - // What it does: Create a new transaction that spends a Zerocoin. - // The user first authors a transaction specifying - // a set of destination addresses (outputs). They - // next compute an Accumulator over all coins in the - // block chain (see above) and a Witness based on the - // coin to be spent. Finally they instantiate a CoinSpend - // object that 'signs' the transaction with a special - // zero knowledge signature of knowledge over the coin - // data, Witness and Accumulator. - /********************************************************************/ - - // We are going to spend the coin "newCoin" that we generated at the - // top of this function. - // - // We'll use the accumulator we constructed above. This contains - // a set of coins, but does NOT include the coin "newCoin". - // - // To generate the witness, we start with this accumulator and - // add the public half of the coin we want to spend. - libzerocoin::AccumulatorWitness witness(params, accumulator, newCoin.getPublicCoin()); - - // Add the public half of "newCoin" to the Accumulator itself. - accumulator += newCoin.getPublicCoin(); - - // At this point we should generate a ZEROCOIN_SPEND transaction to - // send to the network. This network should include a set of outputs - // totalling to the value of one zerocoin (minus transaction fees). - // - // The format of this transaction is up to the implementer. Here we'll - // assume you've formatted this transaction and placed the hash into - // "transactionHash". We'll also assume "accumulatorHash" contains the - // hash of the last block whose transactions are in the accumulator. - uint256 transactionHash = DUMMY_TRANSACTION_HASH; - uint256 accumulatorID = DUMMY_ACCUMULATOR_ID; - - // Place "transactionHash" and "accumulatorBlockHash" into a new - // SpendMetaData object. - libzerocoin::SpendMetaData metaData(accumulatorID, transactionHash); - - // Construct the CoinSpend object. This acts like a signature on the - // transaction. - libzerocoin::CoinSpend spend(params, newCoin, accumulator, witness, metaData); - - // This is a sanity check. The CoinSpend object should always verify, - // but why not check before we put it onto the wire? - if (!spend.Verify(accumulator, metaData)) { - cout << "ERROR: Our new CoinSpend transaction did not verify!" << endl; - return false; - } - - // Serialize the CoinSpend object into a buffer. - CDataStream serializedCoinSpend(SER_NETWORK, PROTOCOL_VERSION); - serializedCoinSpend << spend; - - cout << "Successfully generated a coin spend transaction." << endl; - - /********************************************************************/ - // What is it: Coin spend verification - // Who does it: ALL PARTIES - // What it does: Verifies that a CoinSpend signature is correct - // with respect to a ZEROCOIN_SPEND transaction hash. - // The client must also extract the serial number from - // the CoinSpend and verify that this serial number has - // not previously appeared in another ZEROCOIN_SPEND - // transaction. - /********************************************************************/ - - // Deserialize the CoinSpend intro a fresh object - libzerocoin::CoinSpend newSpend(params, serializedCoinSpend); - - // Create a new metadata object to contain the hash of the received - // ZEROCOIN_SPEND transaction. If we were a real client we'd actually - // compute the hash of the received transaction here. - libzerocoin::SpendMetaData newMetadata(accumulatorID, transactionHash); - - // If we were a real client we would now re-compute the Accumulator - // from the information given in the ZEROCOIN_SPEND transaction. - // For our purposes we'll just use the one we calculated above. - // - // Verify that the spend is valid with respect to the Accumulator - // and the Metadata - if (!newSpend.Verify(accumulator, newMetadata)) { - cout << "ERROR: The CoinSpend transaction did not verify!" << endl; - return false; - } - - // Pull the serial number out of the CoinSpend object. If we - // were a real Zerocoin client we would now check that the serial number - // has not been spent before (in another ZEROCOIN_SPEND) transaction. - // The serial number is stored as a Bignum. - Bignum serialNumber = newSpend.getCoinSerialNumber(); - - cout << "Successfully verified a coin spend transaction." << endl; - cout << endl << "Coin serial number is:" << endl << serialNumber << endl; - - // We're done - return true; - - } catch (runtime_error &e) { - cout << e.what() << endl; - return false; - } - - return false; -} - -int main(int argc, char **argv) -{ - cout << "libzerocoin v" << ZEROCOIN_VERSION_STRING << " tutorial." << endl << endl; - - ZerocoinTutorial(); -} diff --git a/Zerocoin.h b/Zerocoin.h deleted file mode 100644 index 10ef643..0000000 --- a/Zerocoin.h +++ /dev/null @@ -1,60 +0,0 @@ -/** -* @file Zerocoin.h -* -* @brief Exceptions and constants 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. -**/ - -#ifndef ZEROCOIN_H_ -#define ZEROCOIN_H_ - -#include - -#define ZEROCOIN_DEFAULT_SECURITYLEVEL 80 -#define ZEROCOIN_MIN_SECURITY_LEVEL 80 -#define ZEROCOIN_MAX_SECURITY_LEVEL 80 -#define ACCPROOF_KPRIME 160 -#define ACCPROOF_KDPRIME 128 -#define MAX_COINMINT_ATTEMPTS 10000 -#define ZEROCOIN_MINT_PRIME_PARAM 20 -#define ZEROCOIN_VERSION_STRING "0.11" -#define ZEROCOIN_VERSION_INT 11 -#define ZEROCOIN_PROTOCOL_VERSION "1" -#define HASH_OUTPUT_BITS 256 -#define ZEROCOIN_COMMITMENT_EQUALITY_PROOF "COMMITMENT_EQUALITY_PROOF" -#define ZEROCOIN_ACCUMULATOR_PROOF "ACCUMULATOR_PROOF" -#define ZEROCOIN_SERIALNUMBER_PROOF "SERIALNUMBER_PROOF" - -// Activate multithreaded mode for proof verification -#define ZEROCOIN_THREADING 1 - -// Uses a fast technique for coin generation. Could be more vulnerable -// to timing attacks. Turn off if an attacker can measure coin minting time. -#define ZEROCOIN_FAST_MINT 1 - -// Errors thrown by the Zerocoin library - -class ZerocoinException : public std::runtime_error -{ -public: - explicit ZerocoinException(const std::string& str) : std::runtime_error(str) {} -}; - -#include "bitcoin_bignum/serialize.h" -#include "bitcoin_bignum/bignum.h" -#include "bitcoin_bignum/hash.h" -#include "Params.h" -#include "Coin.h" -#include "Commitment.h" -#include "Accumulator.h" -#include "AccumulatorProofOfKnowledge.h" -#include "CoinSpend.h" -#include "SerialNumberSignatureOfKnowledge.h" -#include "ParamGeneration.h" - -#endif /* ZEROCOIN_H_ */ diff --git a/bitcoin_bignum/allocators.h b/bitcoin_bignum/allocators.h deleted file mode 100644 index eb2aed6..0000000 --- a/bitcoin_bignum/allocators.h +++ /dev/null @@ -1,258 +0,0 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_ALLOCATORS_H -#define BITCOIN_ALLOCATORS_H - -#include -#include -#include -#include -#include // for OPENSSL_cleanse() - -#ifdef WIN32 -#ifdef _WIN32_WINNT -#undef _WIN32_WINNT -#endif -#define _WIN32_WINNT 0x0501 -#define WIN32_LEAN_AND_MEAN 1 -#ifndef NOMINMAX -#define NOMINMAX -#endif -#include -// This is used to attempt to keep keying material out of swap -// Note that VirtualLock does not provide this as a guarantee on Windows, -// but, in practice, memory that has been VirtualLock'd almost never gets written to -// the pagefile except in rare circumstances where memory is extremely low. -#else -#include -#include // for PAGESIZE -#include // for sysconf -#endif - -/** - * Thread-safe class to keep track of locked (ie, non-swappable) memory pages. - * - * Memory locks do not stack, that is, pages which have been locked several times by calls to mlock() - * will be unlocked by a single call to munlock(). This can result in keying material ending up in swap when - * those functions are used naively. This class simulates stacking memory locks by keeping a counter per page. - * - * @note By using a map from each page base address to lock count, this class is optimized for - * small objects that span up to a few pages, mostly smaller than a page. To support large allocations, - * something like an interval tree would be the preferred data structure. - */ -template class LockedPageManagerBase -{ -public: - LockedPageManagerBase(size_t page_size): - page_size(page_size) - { - // Determine bitmask for extracting page from address - assert(!(page_size & (page_size-1))); // size must be power of two - page_mask = ~(page_size - 1); - } - - // For all pages in affected range, increase lock count - void LockRange(void *p, size_t size) - { - boost::mutex::scoped_lock lock(mutex); - if(!size) return; - const size_t base_addr = reinterpret_cast(p); - const size_t start_page = base_addr & page_mask; - const size_t end_page = (base_addr + size - 1) & page_mask; - for(size_t page = start_page; page <= end_page; page += page_size) - { - Histogram::iterator it = histogram.find(page); - if(it == histogram.end()) // Newly locked page - { - locker.Lock(reinterpret_cast(page), page_size); - histogram.insert(std::make_pair(page, 1)); - } - else // Page was already locked; increase counter - { - it->second += 1; - } - } - } - - // For all pages in affected range, decrease lock count - void UnlockRange(void *p, size_t size) - { - boost::mutex::scoped_lock lock(mutex); - if(!size) return; - const size_t base_addr = reinterpret_cast(p); - const size_t start_page = base_addr & page_mask; - const size_t end_page = (base_addr + size - 1) & page_mask; - for(size_t page = start_page; page <= end_page; page += page_size) - { - Histogram::iterator it = histogram.find(page); - assert(it != histogram.end()); // Cannot unlock an area that was not locked - // Decrease counter for page, when it is zero, the page will be unlocked - it->second -= 1; - if(it->second == 0) // Nothing on the page anymore that keeps it locked - { - // Unlock page and remove the count from histogram - locker.Unlock(reinterpret_cast(page), page_size); - histogram.erase(it); - } - } - } - - // Get number of locked pages for diagnostics - int GetLockedPageCount() - { - boost::mutex::scoped_lock lock(mutex); - return histogram.size(); - } - -private: - Locker locker; - boost::mutex mutex; - size_t page_size, page_mask; - // map of page base address to lock count - typedef std::map Histogram; - Histogram histogram; -}; - -/** Determine system page size in bytes */ -static inline size_t GetSystemPageSize() -{ - size_t page_size; -#if defined(WIN32) - SYSTEM_INFO sSysInfo; - GetSystemInfo(&sSysInfo); - page_size = sSysInfo.dwPageSize; -#elif defined(PAGESIZE) // defined in limits.h - page_size = PAGESIZE; -#else // assume some POSIX OS - page_size = sysconf(_SC_PAGESIZE); -#endif - return page_size; -} - -/** - * OS-dependent memory page locking/unlocking. - * Defined as policy class to make stubbing for test possible. - */ -class MemoryPageLocker -{ -public: - /** Lock memory pages. - * addr and len must be a multiple of the system page size - */ - bool Lock(const void *addr, size_t len) - { -#ifdef WIN32 - return VirtualLock(const_cast(addr), len); -#else - return mlock(addr, len) == 0; -#endif - } - /** Unlock memory pages. - * addr and len must be a multiple of the system page size - */ - bool Unlock(const void *addr, size_t len) - { -#ifdef WIN32 - return VirtualUnlock(const_cast(addr), len); -#else - return munlock(addr, len) == 0; -#endif - } -}; - -/** - * Singleton class to keep track of locked (ie, non-swappable) memory pages, for use in - * std::allocator templates. - */ -class LockedPageManager: public LockedPageManagerBase -{ -public: - static LockedPageManager instance; // instantiated in util.cpp -private: - LockedPageManager(): - LockedPageManagerBase(GetSystemPageSize()) - {} -}; - -// -// Allocator that locks its contents from being paged -// out of memory and clears its contents before deletion. -// -template -struct secure_allocator : public std::allocator -{ - // MSVC8 default copy constructor is broken - typedef std::allocator base; - typedef typename base::size_type size_type; - typedef typename base::difference_type difference_type; - typedef typename base::pointer pointer; - typedef typename base::const_pointer const_pointer; - typedef typename base::reference reference; - typedef typename base::const_reference const_reference; - typedef typename base::value_type value_type; - secure_allocator() throw() {} - secure_allocator(const secure_allocator& a) throw() : base(a) {} - template - secure_allocator(const secure_allocator& a) throw() : base(a) {} - ~secure_allocator() throw() {} - template struct rebind - { typedef secure_allocator<_Other> other; }; - - T* allocate(std::size_t n, const void *hint = 0) - { - T *p; - p = std::allocator::allocate(n, hint); - if (p != NULL) - LockedPageManager::instance.LockRange(p, sizeof(T) * n); - return p; - } - - void deallocate(T* p, std::size_t n) - { - if (p != NULL) - { - OPENSSL_cleanse(p, sizeof(T) * n); - LockedPageManager::instance.UnlockRange(p, sizeof(T) * n); - } - std::allocator::deallocate(p, n); - } -}; - - -// -// Allocator that clears its contents before deletion. -// -template -struct zero_after_free_allocator : public std::allocator -{ - // MSVC8 default copy constructor is broken - typedef std::allocator base; - typedef typename base::size_type size_type; - typedef typename base::difference_type difference_type; - typedef typename base::pointer pointer; - typedef typename base::const_pointer const_pointer; - typedef typename base::reference reference; - typedef typename base::const_reference const_reference; - typedef typename base::value_type value_type; - zero_after_free_allocator() throw() {} - zero_after_free_allocator(const zero_after_free_allocator& a) throw() : base(a) {} - template - zero_after_free_allocator(const zero_after_free_allocator& a) throw() : base(a) {} - ~zero_after_free_allocator() throw() {} - template struct rebind - { typedef zero_after_free_allocator<_Other> other; }; - - void deallocate(T* p, std::size_t n) - { - if (p != NULL) - OPENSSL_cleanse(p, sizeof(T) * n); - std::allocator::deallocate(p, n); - } -}; - -// This is exactly like std::string, but with a custom allocator. -typedef std::basic_string, secure_allocator > SecureString; - -#endif diff --git a/bitcoin_bignum/bignum.h b/bitcoin_bignum/bignum.h deleted file mode 100644 index 2702cd6..0000000 --- a/bitcoin_bignum/bignum.h +++ /dev/null @@ -1,682 +0,0 @@ -// Modified from bitcon's bignum wrapper. -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_BIGNUM_H -#define BITCOIN_BIGNUM_H - -#include -#include -#include - -#include "netbase.h" -#include "allocators.h" -#include "uint256.h" - -typedef long long int64; -typedef unsigned long long uint64; -/** Errors thrown by the bignum class */ -class bignum_error : public std::runtime_error -{ -public: - explicit bignum_error(const std::string& str) : std::runtime_error(str) {} -}; - - -/** RAII encapsulated BN_CTX (OpenSSL bignum context) */ -class CAutoBN_CTX -{ -protected: - BN_CTX* pctx; - BN_CTX* operator=(BN_CTX* pnew) { return pctx = pnew; } - -public: - CAutoBN_CTX() - { - pctx = BN_CTX_new(); - if (pctx == NULL) - throw bignum_error("CAutoBN_CTX : BN_CTX_new() returned NULL"); - } - - ~CAutoBN_CTX() - { - if (pctx != NULL) - BN_CTX_free(pctx); - } - - operator BN_CTX*() { return pctx; } - BN_CTX& operator*() { return *pctx; } - BN_CTX** operator&() { return &pctx; } - bool operator!() { return (pctx == NULL); } -}; - - -/** C++ wrapper for BIGNUM (OpenSSL bignum) */ -class CBigNum : public BIGNUM -{ -public: - CBigNum() - { - BN_init(this); - } - - CBigNum(const CBigNum& b) - { - BN_init(this); - if (!BN_copy(this, &b)) - { - BN_clear_free(this); - throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_copy failed"); - } - } - - CBigNum& operator=(const CBigNum& b) - { - if (!BN_copy(this, &b)) - throw bignum_error("CBigNum::operator= : BN_copy failed"); - return (*this); - } - - ~CBigNum() - { - BN_clear_free(this); - } - - //CBigNum(char n) is not portable. Use 'signed char' or 'unsigned char'. - CBigNum(signed char n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); } - CBigNum(short n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); } - CBigNum(int n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); } - CBigNum(long n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); } - CBigNum(int64 n) { BN_init(this); setint64(n); } - CBigNum(unsigned char n) { BN_init(this); setulong(n); } - CBigNum(unsigned short n) { BN_init(this); setulong(n); } - CBigNum(unsigned int n) { BN_init(this); setulong(n); } - CBigNum(unsigned long n) { BN_init(this); setulong(n); } - CBigNum(uint64 n) { BN_init(this); setuint64(n); } - explicit CBigNum(uint256 n) { BN_init(this); setuint256(n); } - - explicit CBigNum(const std::vector& vch) - { - BN_init(this); - setvch(vch); - } - - /** Generates a cryptographically secure random number between zero and range exclusive - * i.e. 0 < returned number < range - * @param range The upper bound on the number. - * @return - */ - static CBigNum randBignum(const CBigNum& range) { - CBigNum ret; - if(!BN_rand_range(&ret, &range)){ - throw bignum_error("CBigNum:rand element : BN_rand_range failed"); - } - return ret; - } - - /** Generates a cryptographically secure random k-bit number - * @param k The bit length of the number. - * @return - */ - static CBigNum RandKBitBigum(const uint32_t k){ - CBigNum ret; - if(!BN_rand(&ret, k, -1, 0)){ - throw bignum_error("CBigNum:rand element : BN_rand failed"); - } - return ret; - } - - /**Returns the size in bits of the underlying bignum. - * - * @return the size - */ - int bitSize() const{ - return BN_num_bits(this); - } - - void setulong(unsigned long n) - { - if (!BN_set_word(this, n)) - throw bignum_error("CBigNum conversion from unsigned long : BN_set_word failed"); - } - - unsigned long getulong() const - { - return BN_get_word(this); - } - - unsigned int getuint() const - { - return BN_get_word(this); - } - - int getint() const - { - unsigned long n = BN_get_word(this); - if (!BN_is_negative(this)) - return (n > (unsigned long)std::numeric_limits::max() ? std::numeric_limits::max() : n); - else - return (n > (unsigned long)std::numeric_limits::max() ? std::numeric_limits::min() : -(int)n); - } - - void setint64(int64 sn) - { - unsigned char pch[sizeof(sn) + 6]; - unsigned char* p = pch + 4; - bool fNegative; - uint64 n; - - if (sn < (int64)0) - { - // Since the minimum signed integer cannot be represented as positive so long as its type is signed, - // and it's not well-defined what happens if you make it unsigned before negating it, - // we instead increment the negative integer by 1, convert it, then increment the (now positive) unsigned integer by 1 to compensate - n = -(sn + 1); - ++n; - fNegative = true; - } else { - n = sn; - fNegative = false; - } - - bool fLeadingZeroes = true; - for (int i = 0; i < 8; i++) - { - unsigned char c = (n >> 56) & 0xff; - n <<= 8; - if (fLeadingZeroes) - { - if (c == 0) - continue; - if (c & 0x80) - *p++ = (fNegative ? 0x80 : 0); - else if (fNegative) - c |= 0x80; - fLeadingZeroes = false; - } - *p++ = c; - } - unsigned int nSize = p - (pch + 4); - pch[0] = (nSize >> 24) & 0xff; - pch[1] = (nSize >> 16) & 0xff; - pch[2] = (nSize >> 8) & 0xff; - pch[3] = (nSize) & 0xff; - BN_mpi2bn(pch, p - pch, this); - } - - void setuint64(uint64 n) - { - unsigned char pch[sizeof(n) + 6]; - unsigned char* p = pch + 4; - bool fLeadingZeroes = true; - for (int i = 0; i < 8; i++) - { - unsigned char c = (n >> 56) & 0xff; - n <<= 8; - if (fLeadingZeroes) - { - if (c == 0) - continue; - if (c & 0x80) - *p++ = 0; - fLeadingZeroes = false; - } - *p++ = c; - } - unsigned int nSize = p - (pch + 4); - pch[0] = (nSize >> 24) & 0xff; - pch[1] = (nSize >> 16) & 0xff; - pch[2] = (nSize >> 8) & 0xff; - pch[3] = (nSize) & 0xff; - BN_mpi2bn(pch, p - pch, this); - } - - void setuint256(uint256 n) - { - unsigned char pch[sizeof(n) + 6]; - unsigned char* p = pch + 4; - bool fLeadingZeroes = true; - unsigned char* pbegin = (unsigned char*)&n; - unsigned char* psrc = pbegin + sizeof(n); - while (psrc != pbegin) - { - unsigned char c = *(--psrc); - if (fLeadingZeroes) - { - if (c == 0) - continue; - if (c & 0x80) - *p++ = 0; - fLeadingZeroes = false; - } - *p++ = c; - } - unsigned int nSize = p - (pch + 4); - pch[0] = (nSize >> 24) & 0xff; - pch[1] = (nSize >> 16) & 0xff; - pch[2] = (nSize >> 8) & 0xff; - pch[3] = (nSize >> 0) & 0xff; - BN_mpi2bn(pch, p - pch, this); - } - - uint256 getuint256() const - { - unsigned int nSize = BN_bn2mpi(this, NULL); - if (nSize < 4) - return 0; - std::vector vch(nSize); - BN_bn2mpi(this, &vch[0]); - if (vch.size() > 4) - vch[4] &= 0x7f; - uint256 n = 0; - for (unsigned int i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--) - ((unsigned char*)&n)[i] = vch[j]; - return n; - } - - void setvch(const std::vector& vch) - { - std::vector vch2(vch.size() + 4); - unsigned int nSize = vch.size(); - // BIGNUM's byte stream format expects 4 bytes of - // big endian size data info at the front - vch2[0] = (nSize >> 24) & 0xff; - vch2[1] = (nSize >> 16) & 0xff; - vch2[2] = (nSize >> 8) & 0xff; - vch2[3] = (nSize >> 0) & 0xff; - // swap data to big endian - reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4); - BN_mpi2bn(&vch2[0], vch2.size(), this); - } - - std::vector getvch() const - { - unsigned int nSize = BN_bn2mpi(this, NULL); - if (nSize <= 4) - return std::vector(); - std::vector vch(nSize); - BN_bn2mpi(this, &vch[0]); - vch.erase(vch.begin(), vch.begin() + 4); - reverse(vch.begin(), vch.end()); - return vch; - } - - - void SetHex(const std::string& str) - { - // skip 0x - const char* psz = str.c_str(); - while (isspace(*psz)) - psz++; - bool fNegative = false; - if (*psz == '-') - { - fNegative = true; - psz++; - } - if (psz[0] == '0' && tolower(psz[1]) == 'x') - psz += 2; - while (isspace(*psz)) - psz++; - - // hex string to bignum - static const signed char phexdigit[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0 }; - *this = 0; - while (isxdigit(*psz)) - { - *this <<= 4; - int n = phexdigit[(unsigned char)*psz++]; - *this += n; - } - if (fNegative) - *this = 0 - *this; - } - - std::string ToString(int nBase=10) const - { - CAutoBN_CTX pctx; - CBigNum bnBase = nBase; - CBigNum bn0 = 0; - std::string str; - CBigNum bn = *this; - BN_set_negative(&bn, false); - CBigNum dv; - CBigNum rem; - if (BN_cmp(&bn, &bn0) == 0) - return "0"; - while (BN_cmp(&bn, &bn0) > 0) - { - if (!BN_div(&dv, &rem, &bn, &bnBase, pctx)) - throw bignum_error("CBigNum::ToString() : BN_div failed"); - bn = dv; - unsigned int c = rem.getulong(); - str += "0123456789abcdef"[c]; - } - if (BN_is_negative(this)) - str += "-"; - reverse(str.begin(), str.end()); - return str; - } - - std::string GetHex() const - { - return ToString(16); - } - - unsigned int GetSerializeSize(int nType=0, int nVersion=PROTOCOL_VERSION) const - { - return ::GetSerializeSize(getvch(), nType, nVersion); - } - - template - void Serialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION) const - { - ::Serialize(s, getvch(), nType, nVersion); - } - - template - void Unserialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION) - { - std::vector vch; - ::Unserialize(s, vch, nType, nVersion); - setvch(vch); - } - - /** - * exponentiation with an int. this^e - * @param e the exponent as an int - * @return - */ - CBigNum pow(const int e) const { - return this->pow(CBigNum(e)); - } - - /** - * exponentiation this^e - * @param e the exponent - * @return - */ - CBigNum pow(const CBigNum& e) const { - CAutoBN_CTX pctx; - CBigNum ret; - if (!BN_exp(&ret, this, &e, pctx)) - throw bignum_error("CBigNum::pow : BN_exp failed"); - return ret; - } - - /** - * modular multiplication: (this * b) mod m - * @param b operand - * @param m modulus - */ - CBigNum mul_mod(const CBigNum& b, const CBigNum& m) const { - CAutoBN_CTX pctx; - CBigNum ret; - if (!BN_mod_mul(&ret, this, &b, &m, pctx)) - throw bignum_error("CBigNum::mul_mod : BN_mod_mul failed"); - - return ret; - } - - /** - * modular exponentiation: this^e mod n - * @param e exponent - * @param m modulus - */ - CBigNum pow_mod(const CBigNum& e, const CBigNum& m) const { - CAutoBN_CTX pctx; - CBigNum ret; - if( e < 0){ - // g^-x = (g^-1)^x - CBigNum inv = this->inverse(m); - CBigNum posE = e * -1; - if (!BN_mod_exp(&ret, &inv, &posE, &m, pctx)) - throw bignum_error("CBigNum::pow_mod: BN_mod_exp failed on negative exponent"); - }else - if (!BN_mod_exp(&ret, this, &e, &m, pctx)) - throw bignum_error("CBigNum::pow_mod : BN_mod_exp failed"); - - return ret; - } - - /** - * Calculates the inverse of this element mod m. - * i.e. i such this*i = 1 mod m - * @param m the modu - * @return the inverse - */ - CBigNum inverse(const CBigNum& m) const { - CAutoBN_CTX pctx; - CBigNum ret; - if (!BN_mod_inverse(&ret, this, &m, pctx)) - throw bignum_error("CBigNum::inverse*= :BN_mod_inverse"); - return ret; - } - - /** - * Generates a random (safe) prime of numBits bits - * @param numBits the number of bits - * @param safe true for a safe prime - * @return the prime - */ - static CBigNum generatePrime(const unsigned int numBits, bool safe = false) { - CBigNum ret; - if(!BN_generate_prime_ex(&ret, numBits, (safe == true), NULL, NULL, NULL)) - throw bignum_error("CBigNum::generatePrime*= :BN_generate_prime_ex"); - return ret; - } - - /** - * Calculates the greatest common divisor (GCD) of two numbers. - * @param m the second element - * @return the GCD - */ - CBigNum gcd( const CBigNum& b) const{ - CAutoBN_CTX pctx; - CBigNum ret; - if (!BN_gcd(&ret, this, &b, pctx)) - throw bignum_error("CBigNum::gcd*= :BN_gcd"); - return ret; - } - - /** - * Miller-Rabin primality test on this element - * @param checks: optional, the number of Miller-Rabin tests to run - * default causes error rate of 2^-80. - * @return true if prime - */ - bool isPrime(const int checks=BN_prime_checks) const { - CAutoBN_CTX pctx; - int ret = BN_is_prime(this, checks, NULL, pctx, NULL); - if(ret < 0){ - throw bignum_error("CBigNum::isPrime :BN_is_prime"); - } - return ret; - } - - bool isOne() const { - return BN_is_one(this); - } - - bool operator!() const - { - return BN_is_zero(this); - } - - CBigNum& operator+=(const CBigNum& b) - { - if (!BN_add(this, this, &b)) - throw bignum_error("CBigNum::operator+= : BN_add failed"); - return *this; - } - - CBigNum& operator-=(const CBigNum& b) - { - *this = *this - b; - return *this; - } - - CBigNum& operator*=(const CBigNum& b) - { - CAutoBN_CTX pctx; - if (!BN_mul(this, this, &b, pctx)) - throw bignum_error("CBigNum::operator*= : BN_mul failed"); - return *this; - } - - CBigNum& operator/=(const CBigNum& b) - { - *this = *this / b; - return *this; - } - - CBigNum& operator%=(const CBigNum& b) - { - *this = *this % b; - return *this; - } - - CBigNum& operator<<=(unsigned int shift) - { - if (!BN_lshift(this, this, shift)) - throw bignum_error("CBigNum:operator<<= : BN_lshift failed"); - return *this; - } - - CBigNum& operator>>=(unsigned int shift) - { - // Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number - // if built on ubuntu 9.04 or 9.10, probably depends on version of OpenSSL - CBigNum a = 1; - a <<= shift; - if (BN_cmp(&a, this) > 0) - { - *this = 0; - return *this; - } - - if (!BN_rshift(this, this, shift)) - throw bignum_error("CBigNum:operator>>= : BN_rshift failed"); - return *this; - } - - - CBigNum& operator++() - { - // prefix operator - if (!BN_add(this, this, BN_value_one())) - throw bignum_error("CBigNum::operator++ : BN_add failed"); - return *this; - } - - const CBigNum operator++(int) - { - // postfix operator - const CBigNum ret = *this; - ++(*this); - return ret; - } - - CBigNum& operator--() - { - // prefix operator - CBigNum r; - if (!BN_sub(&r, this, BN_value_one())) - throw bignum_error("CBigNum::operator-- : BN_sub failed"); - *this = r; - return *this; - } - - const CBigNum operator--(int) - { - // postfix operator - const CBigNum ret = *this; - --(*this); - return ret; - } - - - friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b); - friend inline const CBigNum operator/(const CBigNum& a, const CBigNum& b); - friend inline const CBigNum operator%(const CBigNum& a, const CBigNum& b); - friend inline const CBigNum operator*(const CBigNum& a, const CBigNum& b); - friend inline bool operator<(const CBigNum& a, const CBigNum& b); -}; - -inline const CBigNum operator+(const CBigNum& a, const CBigNum& b) -{ - CBigNum r; - if (!BN_add(&r, &a, &b)) - throw bignum_error("CBigNum::operator+ : BN_add failed"); - return r; -} - -inline const CBigNum operator-(const CBigNum& a, const CBigNum& b) -{ - CBigNum r; - if (!BN_sub(&r, &a, &b)) - throw bignum_error("CBigNum::operator- : BN_sub failed"); - return r; -} - -inline const CBigNum operator-(const CBigNum& a) -{ - CBigNum r(a); - BN_set_negative(&r, !BN_is_negative(&r)); - return r; -} - -inline const CBigNum operator*(const CBigNum& a, const CBigNum& b) -{ - CAutoBN_CTX pctx; - CBigNum r; - if (!BN_mul(&r, &a, &b, pctx)) - throw bignum_error("CBigNum::operator* : BN_mul failed"); - return r; -} - -inline const CBigNum operator/(const CBigNum& a, const CBigNum& b) -{ - CAutoBN_CTX pctx; - CBigNum r; - if (!BN_div(&r, NULL, &a, &b, pctx)) - throw bignum_error("CBigNum::operator/ : BN_div failed"); - return r; -} - -inline const CBigNum operator%(const CBigNum& a, const CBigNum& b) -{ - CAutoBN_CTX pctx; - CBigNum r; - if (!BN_nnmod(&r, &a, &b, pctx)) - throw bignum_error("CBigNum::operator% : BN_div failed"); - return r; -} - -inline const CBigNum operator<<(const CBigNum& a, unsigned int shift) -{ - CBigNum r; - if (!BN_lshift(&r, &a, shift)) - throw bignum_error("CBigNum:operator<< : BN_lshift failed"); - return r; -} - -inline const CBigNum operator>>(const CBigNum& a, unsigned int shift) -{ - CBigNum r = a; - r >>= shift; - return r; -} - -inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) == 0); } -inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) != 0); } -inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) <= 0); } -inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) >= 0); } -inline bool operator<(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) < 0); } -inline bool operator>(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) > 0); } -inline std::ostream& operator<<(std::ostream &strm, const CBigNum &b) { - return strm << b.ToString(10); -} -typedef CBigNum Bignum; -#endif diff --git a/bitcoin_bignum/clientversion.h b/bitcoin_bignum/clientversion.h deleted file mode 100644 index e4fd6a6..0000000 --- a/bitcoin_bignum/clientversion.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef CLIENTVERSION_H -#define CLIENTVERSION_H - -// -// client versioning and copyright year -// - -// These need to be macros, as version.cpp's and bitcoin-qt.rc's voodoo requires it -#define CLIENT_VERSION_MAJOR 0 -#define CLIENT_VERSION_MINOR 8 -#define CLIENT_VERSION_REVISION 2 -#define CLIENT_VERSION_BUILD 2 - -// Set to true for release, false for prerelease or test build -#define CLIENT_VERSION_IS_RELEASE true - -// Copyright year (2009-this) -// Todo: update this when changing our copyright comments in the source -#define COPYRIGHT_YEAR 2013 - -// Converts the parameter X to a string after macro replacement on X has been performed. -// Don't merge these into one macro! -#define STRINGIZE(X) DO_STRINGIZE(X) -#define DO_STRINGIZE(X) #X - -#endif // CLIENTVERSION_H diff --git a/bitcoin_bignum/compat.h b/bitcoin_bignum/compat.h deleted file mode 100644 index 7062216..0000000 --- a/bitcoin_bignum/compat.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef _BITCOIN_COMPAT_H -#define _BITCOIN_COMPAT_H 1 - -#ifdef WIN32 -#define _WIN32_WINNT 0x0501 -#define WIN32_LEAN_AND_MEAN 1 -#ifndef NOMINMAX -#define NOMINMAX -#endif -#define FD_SETSIZE 1024 // max number of fds in fd_set -#include -#include -#include -#else -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -typedef u_int SOCKET; -#ifdef WIN32 -#define MSG_NOSIGNAL 0 -#define MSG_DONTWAIT 0 -typedef int socklen_t; -#else -#include "errno.h" -#define WSAGetLastError() errno -#define WSAEINVAL EINVAL -#define WSAEALREADY EALREADY -#define WSAEWOULDBLOCK EWOULDBLOCK -#define WSAEMSGSIZE EMSGSIZE -#define WSAEINTR EINTR -#define WSAEINPROGRESS EINPROGRESS -#define WSAEADDRINUSE EADDRINUSE -#define WSAENOTSOCK EBADF -#define INVALID_SOCKET (SOCKET)(~0) -#define SOCKET_ERROR -1 -#endif - -inline int myclosesocket(SOCKET& hSocket) -{ - if (hSocket == INVALID_SOCKET) - return WSAENOTSOCK; -#ifdef WIN32 - int ret = closesocket(hSocket); -#else - int ret = close(hSocket); -#endif - hSocket = INVALID_SOCKET; - return ret; -} -#define closesocket(s) myclosesocket(s) - - -#endif diff --git a/bitcoin_bignum/hash.cpp b/bitcoin_bignum/hash.cpp deleted file mode 100644 index bddd8ab..0000000 --- a/bitcoin_bignum/hash.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "hash.h" - -inline uint32_t ROTL32 ( uint32_t x, int8_t r ) -{ - return (x << r) | (x >> (32 - r)); -} - -unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector& vDataToHash) -{ - // The following is MurmurHash3 (x86_32), see http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp - uint32_t h1 = nHashSeed; - const uint32_t c1 = 0xcc9e2d51; - const uint32_t c2 = 0x1b873593; - - const int nblocks = vDataToHash.size() / 4; - - //---------- - // body - const uint32_t * blocks = (const uint32_t *)(&vDataToHash[0] + nblocks*4); - - for(int i = -nblocks; i; i++) - { - uint32_t k1 = blocks[i]; - - k1 *= c1; - k1 = ROTL32(k1,15); - k1 *= c2; - - h1 ^= k1; - h1 = ROTL32(h1,13); - h1 = h1*5+0xe6546b64; - } - - //---------- - // tail - const uint8_t * tail = (const uint8_t*)(&vDataToHash[0] + nblocks*4); - - uint32_t k1 = 0; - - switch(vDataToHash.size() & 3) - { - case 3: k1 ^= tail[2] << 16; - case 2: k1 ^= tail[1] << 8; - case 1: k1 ^= tail[0]; - k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1; - }; - - //---------- - // finalization - h1 ^= vDataToHash.size(); - h1 ^= h1 >> 16; - h1 *= 0x85ebca6b; - h1 ^= h1 >> 13; - h1 *= 0xc2b2ae35; - h1 ^= h1 >> 16; - - return h1; -} diff --git a/bitcoin_bignum/hash.h b/bitcoin_bignum/hash.h deleted file mode 100644 index eaa1780..0000000 --- a/bitcoin_bignum/hash.h +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_HASH_H -#define BITCOIN_HASH_H - -#include "uint256.h" -#include "serialize.h" - -#include -#include -#include - -template -inline uint256 Hash(const T1 pbegin, const T1 pend) -{ - static unsigned char pblank[1]; - uint256 hash1; - SHA256((pbegin == pend ? pblank : (unsigned char*)&pbegin[0]), (pend - pbegin) * sizeof(pbegin[0]), (unsigned char*)&hash1); - uint256 hash2; - SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); - return hash2; -} - -class CHashWriter -{ -private: - SHA256_CTX ctx; - -public: - int nType; - int nVersion; - - void Init() { - SHA256_Init(&ctx); - } - - CHashWriter(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn) { - Init(); - } - - CHashWriter& write(const char *pch, size_t size) { - SHA256_Update(&ctx, pch, size); - return (*this); - } - - // invalidates the object - uint256 GetHash() { - uint256 hash1; - SHA256_Final((unsigned char*)&hash1, &ctx); - uint256 hash2; - SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); - return hash2; - } - - template - CHashWriter& operator<<(const T& obj) { - // Serialize to this stream - ::Serialize(*this, obj, nType, nVersion); - return (*this); - } -}; - - -template -inline uint256 Hash(const T1 p1begin, const T1 p1end, - const T2 p2begin, const T2 p2end) -{ - static unsigned char pblank[1]; - uint256 hash1; - SHA256_CTX ctx; - SHA256_Init(&ctx); - SHA256_Update(&ctx, (p1begin == p1end ? pblank : (unsigned char*)&p1begin[0]), (p1end - p1begin) * sizeof(p1begin[0])); - SHA256_Update(&ctx, (p2begin == p2end ? pblank : (unsigned char*)&p2begin[0]), (p2end - p2begin) * sizeof(p2begin[0])); - SHA256_Final((unsigned char*)&hash1, &ctx); - uint256 hash2; - SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); - return hash2; -} - -template -inline uint256 Hash(const T1 p1begin, const T1 p1end, - const T2 p2begin, const T2 p2end, - const T3 p3begin, const T3 p3end) -{ - static unsigned char pblank[1]; - uint256 hash1; - SHA256_CTX ctx; - SHA256_Init(&ctx); - SHA256_Update(&ctx, (p1begin == p1end ? pblank : (unsigned char*)&p1begin[0]), (p1end - p1begin) * sizeof(p1begin[0])); - SHA256_Update(&ctx, (p2begin == p2end ? pblank : (unsigned char*)&p2begin[0]), (p2end - p2begin) * sizeof(p2begin[0])); - SHA256_Update(&ctx, (p3begin == p3end ? pblank : (unsigned char*)&p3begin[0]), (p3end - p3begin) * sizeof(p3begin[0])); - SHA256_Final((unsigned char*)&hash1, &ctx); - uint256 hash2; - SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); - return hash2; -} - -template -uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION) -{ - CHashWriter ss(nType, nVersion); - ss << obj; - return ss.GetHash(); -} - -inline uint160 Hash160(const std::vector& vch) -{ - uint256 hash1; - SHA256(&vch[0], vch.size(), (unsigned char*)&hash1); - uint160 hash2; - RIPEMD160((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); - return hash2; -} - -unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector& vDataToHash); - -#endif diff --git a/bitcoin_bignum/netbase.h b/bitcoin_bignum/netbase.h deleted file mode 100644 index e4ec4ef..0000000 --- a/bitcoin_bignum/netbase.h +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_NETBASE_H -#define BITCOIN_NETBASE_H - -#include -#include - -#include "serialize.h" -#include "compat.h" - -extern int nConnectTimeout; - -#ifdef WIN32 -// In MSVC, this is defined as a macro, undefine it to prevent a compile and link error -#undef SetPort -#endif - -enum Network -{ - NET_UNROUTABLE, - NET_IPV4, - NET_IPV6, - NET_TOR, - - NET_MAX, -}; - -extern int nConnectTimeout; -extern bool fNameLookup; - -/** IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96)) */ -class CNetAddr -{ - protected: - unsigned char ip[16]; // in network byte order - - public: - CNetAddr(); - CNetAddr(const struct in_addr& ipv4Addr); - explicit CNetAddr(const char *pszIp, bool fAllowLookup = false); - explicit CNetAddr(const std::string &strIp, bool fAllowLookup = false); - void Init(); - void SetIP(const CNetAddr& ip); - bool SetSpecial(const std::string &strName); // for Tor addresses - bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0) - bool IsIPv6() const; // IPv6 address (not mapped IPv4, not Tor) - bool IsRFC1918() const; // IPv4 private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12) - bool IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32) - bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16) - bool IsRFC3964() const; // IPv6 6to4 tunnelling (2002::/16) - bool IsRFC4193() const; // IPv6 unique local (FC00::/15) - bool IsRFC4380() const; // IPv6 Teredo tunnelling (2001::/32) - bool IsRFC4843() const; // IPv6 ORCHID (2001:10::/28) - bool IsRFC4862() const; // IPv6 autoconfig (FE80::/64) - bool IsRFC6052() const; // IPv6 well-known prefix (64:FF9B::/96) - bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96) - bool IsTor() const; - bool IsLocal() const; - bool IsRoutable() const; - bool IsValid() const; - bool IsMulticast() const; - enum Network GetNetwork() const; - std::string ToString() const; - std::string ToStringIP() const; - unsigned int GetByte(int n) const; - uint64 GetHash() const; - bool GetInAddr(struct in_addr* pipv4Addr) const; - std::vector GetGroup() const; - int GetReachabilityFrom(const CNetAddr *paddrPartner = NULL) const; - void print() const; - -#ifdef USE_IPV6 - CNetAddr(const struct in6_addr& pipv6Addr); - bool GetIn6Addr(struct in6_addr* pipv6Addr) const; -#endif - - friend bool operator==(const CNetAddr& a, const CNetAddr& b); - friend bool operator!=(const CNetAddr& a, const CNetAddr& b); - friend bool operator<(const CNetAddr& a, const CNetAddr& b); - - IMPLEMENT_SERIALIZE - ( - READWRITE(FLATDATA(ip)); - ) -}; - -/** A combination of a network address (CNetAddr) and a (TCP) port */ -class CService : public CNetAddr -{ - protected: - unsigned short port; // host order - - public: - CService(); - CService(const CNetAddr& ip, unsigned short port); - CService(const struct in_addr& ipv4Addr, unsigned short port); - CService(const struct sockaddr_in& addr); - explicit CService(const char *pszIpPort, int portDefault, bool fAllowLookup = false); - explicit CService(const char *pszIpPort, bool fAllowLookup = false); - explicit CService(const std::string& strIpPort, int portDefault, bool fAllowLookup = false); - explicit CService(const std::string& strIpPort, bool fAllowLookup = false); - void Init(); - void SetPort(unsigned short portIn); - unsigned short GetPort() const; - bool GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const; - bool SetSockAddr(const struct sockaddr* paddr); - friend bool operator==(const CService& a, const CService& b); - friend bool operator!=(const CService& a, const CService& b); - friend bool operator<(const CService& a, const CService& b); - std::vector GetKey() const; - std::string ToString() const; - std::string ToStringPort() const; - std::string ToStringIPPort() const; - void print() const; - -#ifdef USE_IPV6 - CService(const struct in6_addr& ipv6Addr, unsigned short port); - CService(const struct sockaddr_in6& addr); -#endif - - IMPLEMENT_SERIALIZE - ( - CService* pthis = const_cast(this); - READWRITE(FLATDATA(ip)); - unsigned short portN = htons(port); - READWRITE(portN); - if (fRead) - pthis->port = ntohs(portN); - ) -}; - -typedef std::pair proxyType; - -enum Network ParseNetwork(std::string net); -void SplitHostPort(std::string in, int &portOut, std::string &hostOut); -bool SetProxy(enum Network net, CService addrProxy, int nSocksVersion = 5); -bool GetProxy(enum Network net, proxyType &proxyInfoOut); -bool IsProxy(const CNetAddr &addr); -bool SetNameProxy(CService addrProxy, int nSocksVersion = 5); -bool HaveNameProxy(); -bool LookupHost(const char *pszName, std::vector& vIP, unsigned int nMaxSolutions = 0, bool fAllowLookup = true); -bool LookupHostNumeric(const char *pszName, std::vector& vIP, unsigned int nMaxSolutions = 0); -bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true); -bool Lookup(const char *pszName, std::vector& vAddr, int portDefault = 0, bool fAllowLookup = true, unsigned int nMaxSolutions = 0); -bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0); -bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout = nConnectTimeout); -bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault = 0, int nTimeout = nConnectTimeout); - -#endif diff --git a/bitcoin_bignum/serialize.h b/bitcoin_bignum/serialize.h deleted file mode 100644 index e3d9939..0000000 --- a/bitcoin_bignum/serialize.h +++ /dev/null @@ -1,1374 +0,0 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_SERIALIZE_H -#define BITCOIN_SERIALIZE_H - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "allocators.h" -#include "version.h" - -typedef long long int64; -typedef unsigned long long uint64; - -class CScript; -class CDataStream; -class CAutoFile; -static const unsigned int MAX_SIZE = 0x02000000; - -// Used to bypass the rule against non-const reference to temporary -// where it makes sense with wrappers such as CFlatData or CTxDB -template -inline T& REF(const T& val) -{ - return const_cast(val); -} - -///////////////////////////////////////////////////////////////// -// -// Templates for serializing to anything that looks like a stream, -// i.e. anything that supports .read(char*, int) and .write(char*, int) -// - -enum -{ - // primary actions - SER_NETWORK = (1 << 0), - SER_DISK = (1 << 1), - SER_GETHASH = (1 << 2), -}; - -#define IMPLEMENT_SERIALIZE(statements) \ - unsigned int GetSerializeSize(int nType, int nVersion) const \ - { \ - CSerActionGetSerializeSize ser_action; \ - const bool fGetSize = true; \ - const bool fWrite = false; \ - const bool fRead = false; \ - unsigned int nSerSize = 0; \ - ser_streamplaceholder s; \ - assert(fGetSize||fWrite||fRead); /* suppress warning */ \ - s.nType = nType; \ - s.nVersion = nVersion; \ - {statements} \ - return nSerSize; \ - } \ - template \ - void Serialize(Stream& s, int nType, int nVersion) const \ - { \ - CSerActionSerialize ser_action; \ - const bool fGetSize = false; \ - const bool fWrite = true; \ - const bool fRead = false; \ - unsigned int nSerSize = 0; \ - assert(fGetSize||fWrite||fRead); /* suppress warning */ \ - {statements} \ - } \ - template \ - void Unserialize(Stream& s, int nType, int nVersion) \ - { \ - CSerActionUnserialize ser_action; \ - const bool fGetSize = false; \ - const bool fWrite = false; \ - const bool fRead = true; \ - unsigned int nSerSize = 0; \ - assert(fGetSize||fWrite||fRead); /* suppress warning */ \ - {statements} \ - } - -#define READWRITE(obj) (nSerSize += ::SerReadWrite(s, (obj), nType, nVersion, ser_action)) - - - - - - -// -// Basic types -// -#define WRITEDATA(s, obj) s.write((char*)&(obj), sizeof(obj)) -#define READDATA(s, obj) s.read((char*)&(obj), sizeof(obj)) - -inline unsigned int GetSerializeSize(char a, int, int=0) { return sizeof(a); } -inline unsigned int GetSerializeSize(signed char a, int, int=0) { return sizeof(a); } -inline unsigned int GetSerializeSize(unsigned char a, int, int=0) { return sizeof(a); } -inline unsigned int GetSerializeSize(signed short a, int, int=0) { return sizeof(a); } -inline unsigned int GetSerializeSize(unsigned short a, int, int=0) { return sizeof(a); } -inline unsigned int GetSerializeSize(signed int a, int, int=0) { return sizeof(a); } -inline unsigned int GetSerializeSize(unsigned int a, int, int=0) { return sizeof(a); } -inline unsigned int GetSerializeSize(signed long a, int, int=0) { return sizeof(a); } -inline unsigned int GetSerializeSize(unsigned long a, int, int=0) { return sizeof(a); } -inline unsigned int GetSerializeSize(int64 a, int, int=0) { return sizeof(a); } -inline unsigned int GetSerializeSize(uint64 a, int, int=0) { return sizeof(a); } -inline unsigned int GetSerializeSize(float a, int, int=0) { return sizeof(a); } -inline unsigned int GetSerializeSize(double a, int, int=0) { return sizeof(a); } - -template inline void Serialize(Stream& s, char a, int, int=0) { WRITEDATA(s, a); } -template inline void Serialize(Stream& s, signed char a, int, int=0) { WRITEDATA(s, a); } -template inline void Serialize(Stream& s, unsigned char a, int, int=0) { WRITEDATA(s, a); } -template inline void Serialize(Stream& s, signed short a, int, int=0) { WRITEDATA(s, a); } -template inline void Serialize(Stream& s, unsigned short a, int, int=0) { WRITEDATA(s, a); } -template inline void Serialize(Stream& s, signed int a, int, int=0) { WRITEDATA(s, a); } -template inline void Serialize(Stream& s, unsigned int a, int, int=0) { WRITEDATA(s, a); } -template inline void Serialize(Stream& s, signed long a, int, int=0) { WRITEDATA(s, a); } -template inline void Serialize(Stream& s, unsigned long a, int, int=0) { WRITEDATA(s, a); } -template inline void Serialize(Stream& s, int64 a, int, int=0) { WRITEDATA(s, a); } -template inline void Serialize(Stream& s, uint64 a, int, int=0) { WRITEDATA(s, a); } -template inline void Serialize(Stream& s, float a, int, int=0) { WRITEDATA(s, a); } -template inline void Serialize(Stream& s, double a, int, int=0) { WRITEDATA(s, a); } - -template inline void Unserialize(Stream& s, char& a, int, int=0) { READDATA(s, a); } -template inline void Unserialize(Stream& s, signed char& a, int, int=0) { READDATA(s, a); } -template inline void Unserialize(Stream& s, unsigned char& a, int, int=0) { READDATA(s, a); } -template inline void Unserialize(Stream& s, signed short& a, int, int=0) { READDATA(s, a); } -template inline void Unserialize(Stream& s, unsigned short& a, int, int=0) { READDATA(s, a); } -template inline void Unserialize(Stream& s, signed int& a, int, int=0) { READDATA(s, a); } -template inline void Unserialize(Stream& s, unsigned int& a, int, int=0) { READDATA(s, a); } -template inline void Unserialize(Stream& s, signed long& a, int, int=0) { READDATA(s, a); } -template inline void Unserialize(Stream& s, unsigned long& a, int, int=0) { READDATA(s, a); } -template inline void Unserialize(Stream& s, int64& a, int, int=0) { READDATA(s, a); } -template inline void Unserialize(Stream& s, uint64& a, int, int=0) { READDATA(s, a); } -template inline void Unserialize(Stream& s, float& a, int, int=0) { READDATA(s, a); } -template inline void Unserialize(Stream& s, double& a, int, int=0) { READDATA(s, a); } - -inline unsigned int GetSerializeSize(bool a, int, int=0) { return sizeof(char); } -template inline void Serialize(Stream& s, bool a, int, int=0) { char f=a; WRITEDATA(s, f); } -template inline void Unserialize(Stream& s, bool& a, int, int=0) { char f; READDATA(s, f); a=f; } - - - - - - -// -// Compact size -// size < 253 -- 1 byte -// size <= USHRT_MAX -- 3 bytes (253 + 2 bytes) -// size <= UINT_MAX -- 5 bytes (254 + 4 bytes) -// size > UINT_MAX -- 9 bytes (255 + 8 bytes) -// -inline unsigned int GetSizeOfCompactSize(uint64 nSize) -{ - if (nSize < 253) return sizeof(unsigned char); - else if (nSize <= std::numeric_limits::max()) return sizeof(unsigned char) + sizeof(unsigned short); - else if (nSize <= std::numeric_limits::max()) return sizeof(unsigned char) + sizeof(unsigned int); - else return sizeof(unsigned char) + sizeof(uint64); -} - -template -void WriteCompactSize(Stream& os, uint64 nSize) -{ - if (nSize < 253) - { - unsigned char chSize = nSize; - WRITEDATA(os, chSize); - } - else if (nSize <= std::numeric_limits::max()) - { - unsigned char chSize = 253; - unsigned short xSize = nSize; - WRITEDATA(os, chSize); - WRITEDATA(os, xSize); - } - else if (nSize <= std::numeric_limits::max()) - { - unsigned char chSize = 254; - unsigned int xSize = nSize; - WRITEDATA(os, chSize); - WRITEDATA(os, xSize); - } - else - { - unsigned char chSize = 255; - uint64 xSize = nSize; - WRITEDATA(os, chSize); - WRITEDATA(os, xSize); - } - return; -} - -template -uint64 ReadCompactSize(Stream& is) -{ - unsigned char chSize; - READDATA(is, chSize); - uint64 nSizeRet = 0; - if (chSize < 253) - { - nSizeRet = chSize; - } - else if (chSize == 253) - { - unsigned short xSize; - READDATA(is, xSize); - nSizeRet = xSize; - } - else if (chSize == 254) - { - unsigned int xSize; - READDATA(is, xSize); - nSizeRet = xSize; - } - else - { - uint64 xSize; - READDATA(is, xSize); - nSizeRet = xSize; - } - if (nSizeRet > (uint64)MAX_SIZE) - throw std::ios_base::failure("ReadCompactSize() : size too large"); - return nSizeRet; -} - -// Variable-length integers: bytes are a MSB base-128 encoding of the number. -// The high bit in each byte signifies whether another digit follows. To make -// the encoding is one-to-one, one is subtracted from all but the last digit. -// Thus, the byte sequence a[] with length len, where all but the last byte -// has bit 128 set, encodes the number: -// -// (a[len-1] & 0x7F) + sum(i=1..len-1, 128^i*((a[len-i-1] & 0x7F)+1)) -// -// Properties: -// * Very small (0-127: 1 byte, 128-16511: 2 bytes, 16512-2113663: 3 bytes) -// * Every integer has exactly one encoding -// * Encoding does not depend on size of original integer type -// * No redundancy: every (infinite) byte sequence corresponds to a list -// of encoded integers. -// -// 0: [0x00] 256: [0x81 0x00] -// 1: [0x01] 16383: [0xFE 0x7F] -// 127: [0x7F] 16384: [0xFF 0x00] -// 128: [0x80 0x00] 16511: [0x80 0xFF 0x7F] -// 255: [0x80 0x7F] 65535: [0x82 0xFD 0x7F] -// 2^32: [0x8E 0xFE 0xFE 0xFF 0x00] - -template -inline unsigned int GetSizeOfVarInt(I n) -{ - int nRet = 0; - while(true) { - nRet++; - if (n <= 0x7F) - break; - n = (n >> 7) - 1; - } - return nRet; -} - -template -void WriteVarInt(Stream& os, I n) -{ - unsigned char tmp[(sizeof(n)*8+6)/7]; - int len=0; - while(true) { - tmp[len] = (n & 0x7F) | (len ? 0x80 : 0x00); - if (n <= 0x7F) - break; - n = (n >> 7) - 1; - len++; - } - do { - WRITEDATA(os, tmp[len]); - } while(len--); -} - -template -I ReadVarInt(Stream& is) -{ - I n = 0; - while(true) { - unsigned char chData; - READDATA(is, chData); - n = (n << 7) | (chData & 0x7F); - if (chData & 0x80) - n++; - else - return n; - } -} - -#define FLATDATA(obj) REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj))) -#define VARINT(obj) REF(WrapVarInt(REF(obj))) - -/** Wrapper for serializing arrays and POD. - */ -class CFlatData -{ -protected: - char* pbegin; - char* pend; -public: - CFlatData(void* pbeginIn, void* pendIn) : pbegin((char*)pbeginIn), pend((char*)pendIn) { } - char* begin() { return pbegin; } - const char* begin() const { return pbegin; } - char* end() { return pend; } - const char* end() const { return pend; } - - unsigned int GetSerializeSize(int, int=0) const - { - return pend - pbegin; - } - - template - void Serialize(Stream& s, int, int=0) const - { - s.write(pbegin, pend - pbegin); - } - - template - void Unserialize(Stream& s, int, int=0) - { - s.read(pbegin, pend - pbegin); - } -}; - -template -class CVarInt -{ -protected: - I &n; -public: - CVarInt(I& nIn) : n(nIn) { } - - unsigned int GetSerializeSize(int, int) const { - return GetSizeOfVarInt(n); - } - - template - void Serialize(Stream &s, int, int) const { - WriteVarInt(s, n); - } - - template - void Unserialize(Stream& s, int, int) { - n = ReadVarInt(s); - } -}; - -template -CVarInt WrapVarInt(I& n) { return CVarInt(n); } - -// -// Forward declarations -// - -// string -template unsigned int GetSerializeSize(const std::basic_string& str, int, int=0); -template void Serialize(Stream& os, const std::basic_string& str, int, int=0); -template void Unserialize(Stream& is, std::basic_string& str, int, int=0); - -// vector -template unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const boost::true_type&); -template unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const boost::false_type&); -template inline unsigned int GetSerializeSize(const std::vector& v, int nType, int nVersion); -template void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const boost::true_type&); -template void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const boost::false_type&); -template inline void Serialize(Stream& os, const std::vector& v, int nType, int nVersion); -template void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const boost::true_type&); -template void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const boost::false_type&); -template inline void Unserialize(Stream& is, std::vector& v, int nType, int nVersion); - -// others derived from vector -extern inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion); -template void Serialize(Stream& os, const CScript& v, int nType, int nVersion); -template void Unserialize(Stream& is, CScript& v, int nType, int nVersion); - -// pair -template unsigned int GetSerializeSize(const std::pair& item, int nType, int nVersion); -template void Serialize(Stream& os, const std::pair& item, int nType, int nVersion); -template void Unserialize(Stream& is, std::pair& item, int nType, int nVersion); - -// 3 tuple -template unsigned int GetSerializeSize(const boost::tuple& item, int nType, int nVersion); -template void Serialize(Stream& os, const boost::tuple& item, int nType, int nVersion); -template void Unserialize(Stream& is, boost::tuple& item, int nType, int nVersion); - -// 4 tuple -template unsigned int GetSerializeSize(const boost::tuple& item, int nType, int nVersion); -template void Serialize(Stream& os, const boost::tuple& item, int nType, int nVersion); -template void Unserialize(Stream& is, boost::tuple& item, int nType, int nVersion); - -// map -template unsigned int GetSerializeSize(const std::map& m, int nType, int nVersion); -template void Serialize(Stream& os, const std::map& m, int nType, int nVersion); -template void Unserialize(Stream& is, std::map& m, int nType, int nVersion); - -// set -template unsigned int GetSerializeSize(const std::set& m, int nType, int nVersion); -template void Serialize(Stream& os, const std::set& m, int nType, int nVersion); -template void Unserialize(Stream& is, std::set& m, int nType, int nVersion); - - - - - -// -// If none of the specialized versions above matched, default to calling member function. -// "int nType" is changed to "long nType" to keep from getting an ambiguous overload error. -// The compiler will only cast int to long if none of the other templates matched. -// Thanks to Boost serialization for this idea. -// -template -inline unsigned int GetSerializeSize(const T& a, long nType, int nVersion) -{ - return a.GetSerializeSize((int)nType, nVersion); -} - -template -inline void Serialize(Stream& os, const T& a, long nType, int nVersion) -{ - a.Serialize(os, (int)nType, nVersion); -} - -template -inline void Unserialize(Stream& is, T& a, long nType, int nVersion) -{ - a.Unserialize(is, (int)nType, nVersion); -} - - - - - -// -// string -// -template -unsigned int GetSerializeSize(const std::basic_string& str, int, int) -{ - return GetSizeOfCompactSize(str.size()) + str.size() * sizeof(str[0]); -} - -template -void Serialize(Stream& os, const std::basic_string& str, int, int) -{ - WriteCompactSize(os, str.size()); - if (!str.empty()) - os.write((char*)&str[0], str.size() * sizeof(str[0])); -} - -template -void Unserialize(Stream& is, std::basic_string& str, int, int) -{ - unsigned int nSize = ReadCompactSize(is); - str.resize(nSize); - if (nSize != 0) - is.read((char*)&str[0], nSize * sizeof(str[0])); -} - - - -// -// vector -// -template -unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const boost::true_type&) -{ - return (GetSizeOfCompactSize(v.size()) + v.size() * sizeof(T)); -} - -template -unsigned int GetSerializeSize_impl(const std::vector& v, int nType, int nVersion, const boost::false_type&) -{ - unsigned int nSize = GetSizeOfCompactSize(v.size()); - for (typename std::vector::const_iterator vi = v.begin(); vi != v.end(); ++vi) - nSize += GetSerializeSize((*vi), nType, nVersion); - return nSize; -} - -template -inline unsigned int GetSerializeSize(const std::vector& v, int nType, int nVersion) -{ - return GetSerializeSize_impl(v, nType, nVersion, boost::is_fundamental()); -} - - -template -void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const boost::true_type&) -{ - WriteCompactSize(os, v.size()); - if (!v.empty()) - os.write((char*)&v[0], v.size() * sizeof(T)); -} - -template -void Serialize_impl(Stream& os, const std::vector& v, int nType, int nVersion, const boost::false_type&) -{ - WriteCompactSize(os, v.size()); - for (typename std::vector::const_iterator vi = v.begin(); vi != v.end(); ++vi) - ::Serialize(os, (*vi), nType, nVersion); -} - -template -inline void Serialize(Stream& os, const std::vector& v, int nType, int nVersion) -{ - Serialize_impl(os, v, nType, nVersion, boost::is_fundamental()); -} - - -template -void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const boost::true_type&) -{ - // Limit size per read so bogus size value won't cause out of memory - v.clear(); - unsigned int nSize = ReadCompactSize(is); - unsigned int i = 0; - while (i < nSize) - { - unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T))); - v.resize(i + blk); - is.read((char*)&v[i], blk * sizeof(T)); - i += blk; - } -} - -template -void Unserialize_impl(Stream& is, std::vector& v, int nType, int nVersion, const boost::false_type&) -{ - v.clear(); - unsigned int nSize = ReadCompactSize(is); - unsigned int i = 0; - unsigned int nMid = 0; - while (nMid < nSize) - { - nMid += 5000000 / sizeof(T); - if (nMid > nSize) - nMid = nSize; - v.resize(nMid); - for (; i < nMid; i++) - Unserialize(is, v[i], nType, nVersion); - } -} - -template -inline void Unserialize(Stream& is, std::vector& v, int nType, int nVersion) -{ - Unserialize_impl(is, v, nType, nVersion, boost::is_fundamental()); -} - - - -// -// others derived from vector -// -inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion) -{ - return GetSerializeSize((const std::vector&)v, nType, nVersion); -} - -template -void Serialize(Stream& os, const CScript& v, int nType, int nVersion) -{ - Serialize(os, (const std::vector&)v, nType, nVersion); -} - -template -void Unserialize(Stream& is, CScript& v, int nType, int nVersion) -{ - Unserialize(is, (std::vector&)v, nType, nVersion); -} - - - -// -// pair -// -template -unsigned int GetSerializeSize(const std::pair& item, int nType, int nVersion) -{ - return GetSerializeSize(item.first, nType, nVersion) + GetSerializeSize(item.second, nType, nVersion); -} - -template -void Serialize(Stream& os, const std::pair& item, int nType, int nVersion) -{ - Serialize(os, item.first, nType, nVersion); - Serialize(os, item.second, nType, nVersion); -} - -template -void Unserialize(Stream& is, std::pair& item, int nType, int nVersion) -{ - Unserialize(is, item.first, nType, nVersion); - Unserialize(is, item.second, nType, nVersion); -} - - - -// -// 3 tuple -// -template -unsigned int GetSerializeSize(const boost::tuple& item, int nType, int nVersion) -{ - unsigned int nSize = 0; - nSize += GetSerializeSize(boost::get<0>(item), nType, nVersion); - nSize += GetSerializeSize(boost::get<1>(item), nType, nVersion); - nSize += GetSerializeSize(boost::get<2>(item), nType, nVersion); - return nSize; -} - -template -void Serialize(Stream& os, const boost::tuple& item, int nType, int nVersion) -{ - Serialize(os, boost::get<0>(item), nType, nVersion); - Serialize(os, boost::get<1>(item), nType, nVersion); - Serialize(os, boost::get<2>(item), nType, nVersion); -} - -template -void Unserialize(Stream& is, boost::tuple& item, int nType, int nVersion) -{ - Unserialize(is, boost::get<0>(item), nType, nVersion); - Unserialize(is, boost::get<1>(item), nType, nVersion); - Unserialize(is, boost::get<2>(item), nType, nVersion); -} - - - -// -// 4 tuple -// -template -unsigned int GetSerializeSize(const boost::tuple& item, int nType, int nVersion) -{ - unsigned int nSize = 0; - nSize += GetSerializeSize(boost::get<0>(item), nType, nVersion); - nSize += GetSerializeSize(boost::get<1>(item), nType, nVersion); - nSize += GetSerializeSize(boost::get<2>(item), nType, nVersion); - nSize += GetSerializeSize(boost::get<3>(item), nType, nVersion); - return nSize; -} - -template -void Serialize(Stream& os, const boost::tuple& item, int nType, int nVersion) -{ - Serialize(os, boost::get<0>(item), nType, nVersion); - Serialize(os, boost::get<1>(item), nType, nVersion); - Serialize(os, boost::get<2>(item), nType, nVersion); - Serialize(os, boost::get<3>(item), nType, nVersion); -} - -template -void Unserialize(Stream& is, boost::tuple& item, int nType, int nVersion) -{ - Unserialize(is, boost::get<0>(item), nType, nVersion); - Unserialize(is, boost::get<1>(item), nType, nVersion); - Unserialize(is, boost::get<2>(item), nType, nVersion); - Unserialize(is, boost::get<3>(item), nType, nVersion); -} - - - -// -// map -// -template -unsigned int GetSerializeSize(const std::map& m, int nType, int nVersion) -{ - unsigned int nSize = GetSizeOfCompactSize(m.size()); - for (typename std::map::const_iterator mi = m.begin(); mi != m.end(); ++mi) - nSize += GetSerializeSize((*mi), nType, nVersion); - return nSize; -} - -template -void Serialize(Stream& os, const std::map& m, int nType, int nVersion) -{ - WriteCompactSize(os, m.size()); - for (typename std::map::const_iterator mi = m.begin(); mi != m.end(); ++mi) - Serialize(os, (*mi), nType, nVersion); -} - -template -void Unserialize(Stream& is, std::map& m, int nType, int nVersion) -{ - m.clear(); - unsigned int nSize = ReadCompactSize(is); - typename std::map::iterator mi = m.begin(); - for (unsigned int i = 0; i < nSize; i++) - { - std::pair item; - Unserialize(is, item, nType, nVersion); - mi = m.insert(mi, item); - } -} - - - -// -// set -// -template -unsigned int GetSerializeSize(const std::set& m, int nType, int nVersion) -{ - unsigned int nSize = GetSizeOfCompactSize(m.size()); - for (typename std::set::const_iterator it = m.begin(); it != m.end(); ++it) - nSize += GetSerializeSize((*it), nType, nVersion); - return nSize; -} - -template -void Serialize(Stream& os, const std::set& m, int nType, int nVersion) -{ - WriteCompactSize(os, m.size()); - for (typename std::set::const_iterator it = m.begin(); it != m.end(); ++it) - Serialize(os, (*it), nType, nVersion); -} - -template -void Unserialize(Stream& is, std::set& m, int nType, int nVersion) -{ - m.clear(); - unsigned int nSize = ReadCompactSize(is); - typename std::set::iterator it = m.begin(); - for (unsigned int i = 0; i < nSize; i++) - { - K key; - Unserialize(is, key, nType, nVersion); - it = m.insert(it, key); - } -} - - - -// -// Support for IMPLEMENT_SERIALIZE and READWRITE macro -// -class CSerActionGetSerializeSize { }; -class CSerActionSerialize { }; -class CSerActionUnserialize { }; - -template -inline unsigned int SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionGetSerializeSize ser_action) -{ - return ::GetSerializeSize(obj, nType, nVersion); -} - -template -inline unsigned int SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionSerialize ser_action) -{ - ::Serialize(s, obj, nType, nVersion); - return 0; -} - -template -inline unsigned int SerReadWrite(Stream& s, T& obj, int nType, int nVersion, CSerActionUnserialize ser_action) -{ - ::Unserialize(s, obj, nType, nVersion); - return 0; -} - -struct ser_streamplaceholder -{ - int nType; - int nVersion; -}; - - - - - - - - - - - -typedef std::vector > CSerializeData; - -/** Double ended buffer combining vector and stream-like interfaces. - * - * >> and << read and write unformatted data using the above serialization templates. - * Fills with data in linear time; some stringstream implementations take N^2 time. - */ -class CDataStream -{ -protected: - typedef CSerializeData vector_type; - vector_type vch; - unsigned int nReadPos; - short state; - short exceptmask; -public: - int nType; - int nVersion; - - typedef vector_type::allocator_type allocator_type; - typedef vector_type::size_type size_type; - typedef vector_type::difference_type difference_type; - typedef vector_type::reference reference; - typedef vector_type::const_reference const_reference; - typedef vector_type::value_type value_type; - typedef vector_type::iterator iterator; - typedef vector_type::const_iterator const_iterator; - typedef vector_type::reverse_iterator reverse_iterator; - - explicit CDataStream(int nTypeIn, int nVersionIn) - { - Init(nTypeIn, nVersionIn); - } - - CDataStream(const_iterator pbegin, const_iterator pend, int nTypeIn, int nVersionIn) : vch(pbegin, pend) - { - Init(nTypeIn, nVersionIn); - } - -#if !defined(_MSC_VER) || _MSC_VER >= 1300 - CDataStream(const char* pbegin, const char* pend, int nTypeIn, int nVersionIn) : vch(pbegin, pend) - { - Init(nTypeIn, nVersionIn); - } -#endif - - CDataStream(const vector_type& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end()) - { - Init(nTypeIn, nVersionIn); - } - - CDataStream(const std::vector& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end()) - { - Init(nTypeIn, nVersionIn); - } - - CDataStream(const std::vector& vchIn, int nTypeIn, int nVersionIn) : vch((char*)&vchIn.begin()[0], (char*)&vchIn.end()[0]) - { - Init(nTypeIn, nVersionIn); - } - - void Init(int nTypeIn, int nVersionIn) - { - nReadPos = 0; - nType = nTypeIn; - nVersion = nVersionIn; - state = 0; - exceptmask = std::ios::badbit | std::ios::failbit; - } - - CDataStream& operator+=(const CDataStream& b) - { - vch.insert(vch.end(), b.begin(), b.end()); - return *this; - } - - friend CDataStream operator+(const CDataStream& a, const CDataStream& b) - { - CDataStream ret = a; - ret += b; - return (ret); - } - - std::string str() const - { - return (std::string(begin(), end())); - } - - - // - // Vector subset - // - const_iterator begin() const { return vch.begin() + nReadPos; } - iterator begin() { return vch.begin() + nReadPos; } - const_iterator end() const { return vch.end(); } - iterator end() { return vch.end(); } - size_type size() const { return vch.size() - nReadPos; } - bool empty() const { return vch.size() == nReadPos; } - void resize(size_type n, value_type c=0) { vch.resize(n + nReadPos, c); } - void reserve(size_type n) { vch.reserve(n + nReadPos); } - const_reference operator[](size_type pos) const { return vch[pos + nReadPos]; } - reference operator[](size_type pos) { return vch[pos + nReadPos]; } - void clear() { vch.clear(); nReadPos = 0; } - iterator insert(iterator it, const char& x=char()) { return vch.insert(it, x); } - void insert(iterator it, size_type n, const char& x) { vch.insert(it, n, x); } - - void insert(iterator it, const_iterator first, const_iterator last) - { - assert(last - first >= 0); - if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos) - { - // special case for inserting at the front when there's room - nReadPos -= (last - first); - memcpy(&vch[nReadPos], &first[0], last - first); - } - else - vch.insert(it, first, last); - } - - void insert(iterator it, std::vector::const_iterator first, std::vector::const_iterator last) - { - assert(last - first >= 0); - if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos) - { - // special case for inserting at the front when there's room - nReadPos -= (last - first); - memcpy(&vch[nReadPos], &first[0], last - first); - } - else - vch.insert(it, first, last); - } - -#if !defined(_MSC_VER) || _MSC_VER >= 1300 - void insert(iterator it, const char* first, const char* last) - { - assert(last - first >= 0); - if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos) - { - // special case for inserting at the front when there's room - nReadPos -= (last - first); - memcpy(&vch[nReadPos], &first[0], last - first); - } - else - vch.insert(it, first, last); - } -#endif - - iterator erase(iterator it) - { - if (it == vch.begin() + nReadPos) - { - // special case for erasing from the front - if (++nReadPos >= vch.size()) - { - // whenever we reach the end, we take the opportunity to clear the buffer - nReadPos = 0; - return vch.erase(vch.begin(), vch.end()); - } - return vch.begin() + nReadPos; - } - else - return vch.erase(it); - } - - iterator erase(iterator first, iterator last) - { - if (first == vch.begin() + nReadPos) - { - // special case for erasing from the front - if (last == vch.end()) - { - nReadPos = 0; - return vch.erase(vch.begin(), vch.end()); - } - else - { - nReadPos = (last - vch.begin()); - return last; - } - } - else - return vch.erase(first, last); - } - - inline void Compact() - { - vch.erase(vch.begin(), vch.begin() + nReadPos); - nReadPos = 0; - } - - bool Rewind(size_type n) - { - // Rewind by n characters if the buffer hasn't been compacted yet - if (n > nReadPos) - return false; - nReadPos -= n; - return true; - } - - - // - // Stream subset - // - void setstate(short bits, const char* psz) - { - state |= bits; - if (state & exceptmask) - throw std::ios_base::failure(psz); - } - - bool eof() const { return size() == 0; } - bool fail() const { return state & (std::ios::badbit | std::ios::failbit); } - bool good() const { return !eof() && (state == 0); } - void clear(short n) { state = n; } // name conflict with vector clear() - short exceptions() { return exceptmask; } - short exceptions(short mask) { short prev = exceptmask; exceptmask = mask; setstate(0, "CDataStream"); return prev; } - CDataStream* rdbuf() { return this; } - int in_avail() { return size(); } - - void SetType(int n) { nType = n; } - int GetType() { return nType; } - void SetVersion(int n) { nVersion = n; } - int GetVersion() { return nVersion; } - void ReadVersion() { *this >> nVersion; } - void WriteVersion() { *this << nVersion; } - - CDataStream& read(char* pch, int nSize) - { - // Read from the beginning of the buffer - assert(nSize >= 0); - unsigned int nReadPosNext = nReadPos + nSize; - if (nReadPosNext >= vch.size()) - { - if (nReadPosNext > vch.size()) - { - setstate(std::ios::failbit, "CDataStream::read() : end of data"); - memset(pch, 0, nSize); - nSize = vch.size() - nReadPos; - } - memcpy(pch, &vch[nReadPos], nSize); - nReadPos = 0; - vch.clear(); - return (*this); - } - memcpy(pch, &vch[nReadPos], nSize); - nReadPos = nReadPosNext; - return (*this); - } - - CDataStream& ignore(int nSize) - { - // Ignore from the beginning of the buffer - assert(nSize >= 0); - unsigned int nReadPosNext = nReadPos + nSize; - if (nReadPosNext >= vch.size()) - { - if (nReadPosNext > vch.size()) - { - setstate(std::ios::failbit, "CDataStream::ignore() : end of data"); - nSize = vch.size() - nReadPos; - } - nReadPos = 0; - vch.clear(); - return (*this); - } - nReadPos = nReadPosNext; - return (*this); - } - - CDataStream& write(const char* pch, int nSize) - { - // Write to the end of the buffer - assert(nSize >= 0); - vch.insert(vch.end(), pch, pch + nSize); - return (*this); - } - - template - void Serialize(Stream& s, int nType, int nVersion) const - { - // Special case: stream << stream concatenates like stream += stream - if (!vch.empty()) - s.write((char*)&vch[0], vch.size() * sizeof(vch[0])); - } - - template - unsigned int GetSerializeSize(const T& obj) - { - // Tells the size of the object if serialized to this stream - return ::GetSerializeSize(obj, nType, nVersion); - } - - template - CDataStream& operator<<(const T& obj) - { - // Serialize to this stream - ::Serialize(*this, obj, nType, nVersion); - return (*this); - } - - template - CDataStream& operator>>(T& obj) - { - // Unserialize from this stream - ::Unserialize(*this, obj, nType, nVersion); - return (*this); - } - - void GetAndClear(CSerializeData &data) { - vch.swap(data); - CSerializeData().swap(vch); - } -}; - - - - - - - - - - -/** RAII wrapper for FILE*. - * - * Will automatically close the file when it goes out of scope if not null. - * If you're returning the file pointer, return file.release(). - * If you need to close the file early, use file.fclose() instead of fclose(file). - */ -class CAutoFile -{ -protected: - FILE* file; - short state; - short exceptmask; -public: - int nType; - int nVersion; - - CAutoFile(FILE* filenew, int nTypeIn, int nVersionIn) - { - file = filenew; - nType = nTypeIn; - nVersion = nVersionIn; - state = 0; - exceptmask = std::ios::badbit | std::ios::failbit; - } - - ~CAutoFile() - { - fclose(); - } - - void fclose() - { - if (file != NULL && file != stdin && file != stdout && file != stderr) - ::fclose(file); - file = NULL; - } - - FILE* release() { FILE* ret = file; file = NULL; return ret; } - operator FILE*() { return file; } - FILE* operator->() { return file; } - FILE& operator*() { return *file; } - FILE** operator&() { return &file; } - FILE* operator=(FILE* pnew) { return file = pnew; } - bool operator!() { return (file == NULL); } - - - // - // Stream subset - // - void setstate(short bits, const char* psz) - { - state |= bits; - if (state & exceptmask) - throw std::ios_base::failure(psz); - } - - bool fail() const { return state & (std::ios::badbit | std::ios::failbit); } - bool good() const { return state == 0; } - void clear(short n = 0) { state = n; } - short exceptions() { return exceptmask; } - short exceptions(short mask) { short prev = exceptmask; exceptmask = mask; setstate(0, "CAutoFile"); return prev; } - - void SetType(int n) { nType = n; } - int GetType() { return nType; } - void SetVersion(int n) { nVersion = n; } - int GetVersion() { return nVersion; } - void ReadVersion() { *this >> nVersion; } - void WriteVersion() { *this << nVersion; } - - CAutoFile& read(char* pch, size_t nSize) - { - if (!file) - throw std::ios_base::failure("CAutoFile::read : file handle is NULL"); - if (fread(pch, 1, nSize, file) != nSize) - setstate(std::ios::failbit, feof(file) ? "CAutoFile::read : end of file" : "CAutoFile::read : fread failed"); - return (*this); - } - - CAutoFile& write(const char* pch, size_t nSize) - { - if (!file) - throw std::ios_base::failure("CAutoFile::write : file handle is NULL"); - if (fwrite(pch, 1, nSize, file) != nSize) - setstate(std::ios::failbit, "CAutoFile::write : write failed"); - return (*this); - } - - template - unsigned int GetSerializeSize(const T& obj) - { - // Tells the size of the object if serialized to this stream - return ::GetSerializeSize(obj, nType, nVersion); - } - - template - CAutoFile& operator<<(const T& obj) - { - // Serialize to this stream - if (!file) - throw std::ios_base::failure("CAutoFile::operator<< : file handle is NULL"); - ::Serialize(*this, obj, nType, nVersion); - return (*this); - } - - template - CAutoFile& operator>>(T& obj) - { - // Unserialize from this stream - if (!file) - throw std::ios_base::failure("CAutoFile::operator>> : file handle is NULL"); - ::Unserialize(*this, obj, nType, nVersion); - return (*this); - } -}; - -/** Wrapper around a FILE* that implements a ring buffer to - * deserialize from. It guarantees the ability to rewind - * a given number of bytes. */ -class CBufferedFile -{ -private: - FILE *src; // source file - uint64 nSrcPos; // how many bytes have been read from source - uint64 nReadPos; // how many bytes have been read from this - uint64 nReadLimit; // up to which position we're allowed to read - uint64 nRewind; // how many bytes we guarantee to rewind - std::vector vchBuf; // the buffer - - short state; - short exceptmask; - -protected: - void setstate(short bits, const char *psz) { - state |= bits; - if (state & exceptmask) - throw std::ios_base::failure(psz); - } - - // read data from the source to fill the buffer - bool Fill() { - unsigned int pos = nSrcPos % vchBuf.size(); - unsigned int readNow = vchBuf.size() - pos; - unsigned int nAvail = vchBuf.size() - (nSrcPos - nReadPos) - nRewind; - if (nAvail < readNow) - readNow = nAvail; - if (readNow == 0) - return false; - size_t read = fread((void*)&vchBuf[pos], 1, readNow, src); - if (read == 0) { - setstate(std::ios_base::failbit, feof(src) ? "CBufferedFile::Fill : end of file" : "CBufferedFile::Fill : fread failed"); - return false; - } else { - nSrcPos += read; - return true; - } - } - -public: - int nType; - int nVersion; - - CBufferedFile(FILE *fileIn, uint64 nBufSize, uint64 nRewindIn, int nTypeIn, int nVersionIn) : - src(fileIn), nSrcPos(0), nReadPos(0), nReadLimit((uint64)(-1)), nRewind(nRewindIn), vchBuf(nBufSize, 0), - state(0), exceptmask(std::ios_base::badbit | std::ios_base::failbit), nType(nTypeIn), nVersion(nVersionIn) { - } - - // check whether no error occurred - bool good() const { - return state == 0; - } - - // check whether we're at the end of the source file - bool eof() const { - return nReadPos == nSrcPos && feof(src); - } - - // read a number of bytes - CBufferedFile& read(char *pch, size_t nSize) { - if (nSize + nReadPos > nReadLimit) - throw std::ios_base::failure("Read attempted past buffer limit"); - if (nSize + nRewind > vchBuf.size()) - throw std::ios_base::failure("Read larger than buffer size"); - while (nSize > 0) { - if (nReadPos == nSrcPos) - Fill(); - unsigned int pos = nReadPos % vchBuf.size(); - size_t nNow = nSize; - if (nNow + pos > vchBuf.size()) - nNow = vchBuf.size() - pos; - if (nNow + nReadPos > nSrcPos) - nNow = nSrcPos - nReadPos; - memcpy(pch, &vchBuf[pos], nNow); - nReadPos += nNow; - pch += nNow; - nSize -= nNow; - } - return (*this); - } - - // return the current reading position - uint64 GetPos() { - return nReadPos; - } - - // rewind to a given reading position - bool SetPos(uint64 nPos) { - nReadPos = nPos; - if (nReadPos + nRewind < nSrcPos) { - nReadPos = nSrcPos - nRewind; - return false; - } else if (nReadPos > nSrcPos) { - nReadPos = nSrcPos; - return false; - } else { - return true; - } - } - - bool Seek(uint64 nPos) { - long nLongPos = nPos; - if (nPos != (uint64)nLongPos) - return false; - if (fseek(src, nLongPos, SEEK_SET)) - return false; - nLongPos = ftell(src); - nSrcPos = nLongPos; - nReadPos = nLongPos; - state = 0; - return true; - } - - // prevent reading beyond a certain position - // no argument removes the limit - bool SetLimit(uint64 nPos = (uint64)(-1)) { - if (nPos < nReadPos) - return false; - nReadLimit = nPos; - return true; - } - - template - CBufferedFile& operator>>(T& obj) { - // Unserialize from this stream - ::Unserialize(*this, obj, nType, nVersion); - return (*this); - } - - // search for a given byte in the stream, and remain positioned on it - void FindByte(char ch) { - while (true) { - if (nReadPos == nSrcPos) - Fill(); - if (vchBuf[nReadPos % vchBuf.size()] == ch) - break; - nReadPos++; - } - } -}; - -#endif diff --git a/bitcoin_bignum/uint256.h b/bitcoin_bignum/uint256.h deleted file mode 100644 index 2a252c9..0000000 --- a/bitcoin_bignum/uint256.h +++ /dev/null @@ -1,784 +0,0 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_UINT256_H -#define BITCOIN_UINT256_H - -#include -#include -#include -#include -#include -#include - -typedef long long int64; -typedef unsigned long long uint64; - - -inline int Testuint256AdHoc(std::vector vArg); - - - -/** Base class without constructors for uint256 and uint160. - * This makes the compiler let you use it in a union. - */ -template -class base_uint -{ -protected: - enum { WIDTH=BITS/32 }; - uint32_t pn[WIDTH]; -public: - - bool operator!() const - { - for (int i = 0; i < WIDTH; i++) - if (pn[i] != 0) - return false; - return true; - } - - const base_uint operator~() const - { - base_uint ret; - for (int i = 0; i < WIDTH; i++) - ret.pn[i] = ~pn[i]; - return ret; - } - - const base_uint operator-() const - { - base_uint ret; - for (int i = 0; i < WIDTH; i++) - ret.pn[i] = ~pn[i]; - ret++; - return ret; - } - - double getdouble() const - { - double ret = 0.0; - double fact = 1.0; - for (int i = 0; i < WIDTH; i++) { - ret += fact * pn[i]; - fact *= 4294967296.0; - } - return ret; - } - - base_uint& operator=(uint64 b) - { - pn[0] = (unsigned int)b; - pn[1] = (unsigned int)(b >> 32); - for (int i = 2; i < WIDTH; i++) - pn[i] = 0; - return *this; - } - - base_uint& operator^=(const base_uint& b) - { - for (int i = 0; i < WIDTH; i++) - pn[i] ^= b.pn[i]; - return *this; - } - - base_uint& operator&=(const base_uint& b) - { - for (int i = 0; i < WIDTH; i++) - pn[i] &= b.pn[i]; - return *this; - } - - base_uint& operator|=(const base_uint& b) - { - for (int i = 0; i < WIDTH; i++) - pn[i] |= b.pn[i]; - return *this; - } - - base_uint& operator^=(uint64 b) - { - pn[0] ^= (unsigned int)b; - pn[1] ^= (unsigned int)(b >> 32); - return *this; - } - - base_uint& operator|=(uint64 b) - { - pn[0] |= (unsigned int)b; - pn[1] |= (unsigned int)(b >> 32); - return *this; - } - - base_uint& operator<<=(unsigned int shift) - { - base_uint a(*this); - for (int i = 0; i < WIDTH; i++) - pn[i] = 0; - int k = shift / 32; - shift = shift % 32; - for (int i = 0; i < WIDTH; i++) - { - if (i+k+1 < WIDTH && shift != 0) - pn[i+k+1] |= (a.pn[i] >> (32-shift)); - if (i+k < WIDTH) - pn[i+k] |= (a.pn[i] << shift); - } - return *this; - } - - base_uint& operator>>=(unsigned int shift) - { - base_uint a(*this); - for (int i = 0; i < WIDTH; i++) - pn[i] = 0; - int k = shift / 32; - shift = shift % 32; - for (int i = 0; i < WIDTH; i++) - { - if (i-k-1 >= 0 && shift != 0) - pn[i-k-1] |= (a.pn[i] << (32-shift)); - if (i-k >= 0) - pn[i-k] |= (a.pn[i] >> shift); - } - return *this; - } - - base_uint& operator+=(const base_uint& b) - { - uint64 carry = 0; - for (int i = 0; i < WIDTH; i++) - { - uint64 n = carry + pn[i] + b.pn[i]; - pn[i] = n & 0xffffffff; - carry = n >> 32; - } - return *this; - } - - base_uint& operator-=(const base_uint& b) - { - *this += -b; - return *this; - } - - base_uint& operator+=(uint64 b64) - { - base_uint b; - b = b64; - *this += b; - return *this; - } - - base_uint& operator-=(uint64 b64) - { - base_uint b; - b = b64; - *this += -b; - return *this; - } - - - base_uint& operator++() - { - // prefix operator - int i = 0; - while (++pn[i] == 0 && i < WIDTH-1) - i++; - return *this; - } - - const base_uint operator++(int) - { - // postfix operator - const base_uint ret = *this; - ++(*this); - return ret; - } - - base_uint& operator--() - { - // prefix operator - int i = 0; - while (--pn[i] == -1 && i < WIDTH-1) - i++; - return *this; - } - - const base_uint operator--(int) - { - // postfix operator - const base_uint ret = *this; - --(*this); - return ret; - } - - - friend inline bool operator<(const base_uint& a, const base_uint& b) - { - for (int i = base_uint::WIDTH-1; i >= 0; i--) - { - if (a.pn[i] < b.pn[i]) - return true; - else if (a.pn[i] > b.pn[i]) - return false; - } - return false; - } - - friend inline bool operator<=(const base_uint& a, const base_uint& b) - { - for (int i = base_uint::WIDTH-1; i >= 0; i--) - { - if (a.pn[i] < b.pn[i]) - return true; - else if (a.pn[i] > b.pn[i]) - return false; - } - return true; - } - - friend inline bool operator>(const base_uint& a, const base_uint& b) - { - for (int i = base_uint::WIDTH-1; i >= 0; i--) - { - if (a.pn[i] > b.pn[i]) - return true; - else if (a.pn[i] < b.pn[i]) - return false; - } - return false; - } - - friend inline bool operator>=(const base_uint& a, const base_uint& b) - { - for (int i = base_uint::WIDTH-1; i >= 0; i--) - { - if (a.pn[i] > b.pn[i]) - return true; - else if (a.pn[i] < b.pn[i]) - return false; - } - return true; - } - - friend inline bool operator==(const base_uint& a, const base_uint& b) - { - for (int i = 0; i < base_uint::WIDTH; i++) - if (a.pn[i] != b.pn[i]) - return false; - return true; - } - - friend inline bool operator==(const base_uint& a, uint64 b) - { - if (a.pn[0] != (unsigned int)b) - return false; - if (a.pn[1] != (unsigned int)(b >> 32)) - return false; - for (int i = 2; i < base_uint::WIDTH; i++) - if (a.pn[i] != 0) - return false; - return true; - } - - friend inline bool operator!=(const base_uint& a, const base_uint& b) - { - return (!(a == b)); - } - - friend inline bool operator!=(const base_uint& a, uint64 b) - { - return (!(a == b)); - } - - - - std::string GetHex() const - { - char psz[sizeof(pn)*2 + 1]; - for (unsigned int i = 0; i < sizeof(pn); i++) - sprintf(psz + i*2, "%02x", ((unsigned char*)pn)[sizeof(pn) - i - 1]); - return std::string(psz, psz + sizeof(pn)*2); - } - - void SetHex(const char* psz) - { - for (int i = 0; i < WIDTH; i++) - pn[i] = 0; - - // skip leading spaces - while (isspace(*psz)) - psz++; - - // skip 0x - if (psz[0] == '0' && tolower(psz[1]) == 'x') - psz += 2; - - // hex string to uint - static const unsigned char phexdigit[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0 }; - const char* pbegin = psz; - while (phexdigit[(unsigned char)*psz] || *psz == '0') - psz++; - psz--; - unsigned char* p1 = (unsigned char*)pn; - unsigned char* pend = p1 + WIDTH * 4; - while (psz >= pbegin && p1 < pend) - { - *p1 = phexdigit[(unsigned char)*psz--]; - if (psz >= pbegin) - { - *p1 |= (phexdigit[(unsigned char)*psz--] << 4); - p1++; - } - } - } - - void SetHex(const std::string& str) - { - SetHex(str.c_str()); - } - - std::string ToString() const - { - return (GetHex()); - } - - unsigned char* begin() - { - return (unsigned char*)&pn[0]; - } - - unsigned char* end() - { - return (unsigned char*)&pn[WIDTH]; - } - - const unsigned char* begin() const - { - return (unsigned char*)&pn[0]; - } - - const unsigned char* end() const - { - return (unsigned char*)&pn[WIDTH]; - } - - unsigned int size() const - { - return sizeof(pn); - } - - uint64 Get64(int n=0) const - { - return pn[2*n] | (uint64)pn[2*n+1] << 32; - } - -// unsigned int GetSerializeSize(int nType=0, int nVersion=PROTOCOL_VERSION) const - unsigned int GetSerializeSize(int nType, int nVersion) const - { - return sizeof(pn); - } - - template -// void Serialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION) const - void Serialize(Stream& s, int nType, int nVersion) const - { - s.write((char*)pn, sizeof(pn)); - } - - template -// void Unserialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION) - void Unserialize(Stream& s, int nType, int nVersion) - { - s.read((char*)pn, sizeof(pn)); - } - - - friend class uint160; - friend class uint256; - friend inline int Testuint256AdHoc(std::vector vArg); -}; - -typedef base_uint<160> base_uint160; -typedef base_uint<256> base_uint256; - - - -// -// uint160 and uint256 could be implemented as templates, but to keep -// compile errors and debugging cleaner, they're copy and pasted. -// - - - -////////////////////////////////////////////////////////////////////////////// -// -// uint160 -// - -/** 160-bit unsigned integer */ -class uint160 : public base_uint160 -{ -public: - typedef base_uint160 basetype; - - uint160() - { - for (int i = 0; i < WIDTH; i++) - pn[i] = 0; - } - - uint160(const basetype& b) - { - for (int i = 0; i < WIDTH; i++) - pn[i] = b.pn[i]; - } - - uint160& operator=(const basetype& b) - { - for (int i = 0; i < WIDTH; i++) - pn[i] = b.pn[i]; - return *this; - } - - uint160(uint64 b) - { - pn[0] = (unsigned int)b; - pn[1] = (unsigned int)(b >> 32); - for (int i = 2; i < WIDTH; i++) - pn[i] = 0; - } - - uint160& operator=(uint64 b) - { - pn[0] = (unsigned int)b; - pn[1] = (unsigned int)(b >> 32); - for (int i = 2; i < WIDTH; i++) - pn[i] = 0; - return *this; - } - - explicit uint160(const std::string& str) - { - SetHex(str); - } - - explicit uint160(const std::vector& vch) - { - if (vch.size() == sizeof(pn)) - memcpy(pn, &vch[0], sizeof(pn)); - else - *this = 0; - } -}; - -inline bool operator==(const uint160& a, uint64 b) { return (base_uint160)a == b; } -inline bool operator!=(const uint160& a, uint64 b) { return (base_uint160)a != b; } -inline const uint160 operator<<(const base_uint160& a, unsigned int shift) { return uint160(a) <<= shift; } -inline const uint160 operator>>(const base_uint160& a, unsigned int shift) { return uint160(a) >>= shift; } -inline const uint160 operator<<(const uint160& a, unsigned int shift) { return uint160(a) <<= shift; } -inline const uint160 operator>>(const uint160& a, unsigned int shift) { return uint160(a) >>= shift; } - -inline const uint160 operator^(const base_uint160& a, const base_uint160& b) { return uint160(a) ^= b; } -inline const uint160 operator&(const base_uint160& a, const base_uint160& b) { return uint160(a) &= b; } -inline const uint160 operator|(const base_uint160& a, const base_uint160& b) { return uint160(a) |= b; } -inline const uint160 operator+(const base_uint160& a, const base_uint160& b) { return uint160(a) += b; } -inline const uint160 operator-(const base_uint160& a, const base_uint160& b) { return uint160(a) -= b; } - -inline bool operator<(const base_uint160& a, const uint160& b) { return (base_uint160)a < (base_uint160)b; } -inline bool operator<=(const base_uint160& a, const uint160& b) { return (base_uint160)a <= (base_uint160)b; } -inline bool operator>(const base_uint160& a, const uint160& b) { return (base_uint160)a > (base_uint160)b; } -inline bool operator>=(const base_uint160& a, const uint160& b) { return (base_uint160)a >= (base_uint160)b; } -inline bool operator==(const base_uint160& a, const uint160& b) { return (base_uint160)a == (base_uint160)b; } -inline bool operator!=(const base_uint160& a, const uint160& b) { return (base_uint160)a != (base_uint160)b; } -inline const uint160 operator^(const base_uint160& a, const uint160& b) { return (base_uint160)a ^ (base_uint160)b; } -inline const uint160 operator&(const base_uint160& a, const uint160& b) { return (base_uint160)a & (base_uint160)b; } -inline const uint160 operator|(const base_uint160& a, const uint160& b) { return (base_uint160)a | (base_uint160)b; } -inline const uint160 operator+(const base_uint160& a, const uint160& b) { return (base_uint160)a + (base_uint160)b; } -inline const uint160 operator-(const base_uint160& a, const uint160& b) { return (base_uint160)a - (base_uint160)b; } - -inline bool operator<(const uint160& a, const base_uint160& b) { return (base_uint160)a < (base_uint160)b; } -inline bool operator<=(const uint160& a, const base_uint160& b) { return (base_uint160)a <= (base_uint160)b; } -inline bool operator>(const uint160& a, const base_uint160& b) { return (base_uint160)a > (base_uint160)b; } -inline bool operator>=(const uint160& a, const base_uint160& b) { return (base_uint160)a >= (base_uint160)b; } -inline bool operator==(const uint160& a, const base_uint160& b) { return (base_uint160)a == (base_uint160)b; } -inline bool operator!=(const uint160& a, const base_uint160& b) { return (base_uint160)a != (base_uint160)b; } -inline const uint160 operator^(const uint160& a, const base_uint160& b) { return (base_uint160)a ^ (base_uint160)b; } -inline const uint160 operator&(const uint160& a, const base_uint160& b) { return (base_uint160)a & (base_uint160)b; } -inline const uint160 operator|(const uint160& a, const base_uint160& b) { return (base_uint160)a | (base_uint160)b; } -inline const uint160 operator+(const uint160& a, const base_uint160& b) { return (base_uint160)a + (base_uint160)b; } -inline const uint160 operator-(const uint160& a, const base_uint160& b) { return (base_uint160)a - (base_uint160)b; } - -inline bool operator<(const uint160& a, const uint160& b) { return (base_uint160)a < (base_uint160)b; } -inline bool operator<=(const uint160& a, const uint160& b) { return (base_uint160)a <= (base_uint160)b; } -inline bool operator>(const uint160& a, const uint160& b) { return (base_uint160)a > (base_uint160)b; } -inline bool operator>=(const uint160& a, const uint160& b) { return (base_uint160)a >= (base_uint160)b; } -inline bool operator==(const uint160& a, const uint160& b) { return (base_uint160)a == (base_uint160)b; } -inline bool operator!=(const uint160& a, const uint160& b) { return (base_uint160)a != (base_uint160)b; } -inline const uint160 operator^(const uint160& a, const uint160& b) { return (base_uint160)a ^ (base_uint160)b; } -inline const uint160 operator&(const uint160& a, const uint160& b) { return (base_uint160)a & (base_uint160)b; } -inline const uint160 operator|(const uint160& a, const uint160& b) { return (base_uint160)a | (base_uint160)b; } -inline const uint160 operator+(const uint160& a, const uint160& b) { return (base_uint160)a + (base_uint160)b; } -inline const uint160 operator-(const uint160& a, const uint160& b) { return (base_uint160)a - (base_uint160)b; } - - - - - - -////////////////////////////////////////////////////////////////////////////// -// -// uint256 -// - -/** 256-bit unsigned integer */ -class uint256 : public base_uint256 -{ -public: - typedef base_uint256 basetype; - - uint256() - { - for (int i = 0; i < WIDTH; i++) - pn[i] = 0; - } - - uint256(const basetype& b) - { - for (int i = 0; i < WIDTH; i++) - pn[i] = b.pn[i]; - } - - uint256& operator=(const basetype& b) - { - for (int i = 0; i < WIDTH; i++) - pn[i] = b.pn[i]; - return *this; - } - - uint256(uint64 b) - { - pn[0] = (unsigned int)b; - pn[1] = (unsigned int)(b >> 32); - for (int i = 2; i < WIDTH; i++) - pn[i] = 0; - } - - uint256& operator=(uint64 b) - { - pn[0] = (unsigned int)b; - pn[1] = (unsigned int)(b >> 32); - for (int i = 2; i < WIDTH; i++) - pn[i] = 0; - return *this; - } - - explicit uint256(const std::string& str) - { - SetHex(str); - } - - explicit uint256(const std::vector& vch) - { - if (vch.size() == sizeof(pn)) - memcpy(pn, &vch[0], sizeof(pn)); - else - *this = 0; - } -}; - -inline bool operator==(const uint256& a, uint64 b) { return (base_uint256)a == b; } -inline bool operator!=(const uint256& a, uint64 b) { return (base_uint256)a != b; } -inline const uint256 operator<<(const base_uint256& a, unsigned int shift) { return uint256(a) <<= shift; } -inline const uint256 operator>>(const base_uint256& a, unsigned int shift) { return uint256(a) >>= shift; } -inline const uint256 operator<<(const uint256& a, unsigned int shift) { return uint256(a) <<= shift; } -inline const uint256 operator>>(const uint256& a, unsigned int shift) { return uint256(a) >>= shift; } - -inline const uint256 operator^(const base_uint256& a, const base_uint256& b) { return uint256(a) ^= b; } -inline const uint256 operator&(const base_uint256& a, const base_uint256& b) { return uint256(a) &= b; } -inline const uint256 operator|(const base_uint256& a, const base_uint256& b) { return uint256(a) |= b; } -inline const uint256 operator+(const base_uint256& a, const base_uint256& b) { return uint256(a) += b; } -inline const uint256 operator-(const base_uint256& a, const base_uint256& b) { return uint256(a) -= b; } - -inline bool operator<(const base_uint256& a, const uint256& b) { return (base_uint256)a < (base_uint256)b; } -inline bool operator<=(const base_uint256& a, const uint256& b) { return (base_uint256)a <= (base_uint256)b; } -inline bool operator>(const base_uint256& a, const uint256& b) { return (base_uint256)a > (base_uint256)b; } -inline bool operator>=(const base_uint256& a, const uint256& b) { return (base_uint256)a >= (base_uint256)b; } -inline bool operator==(const base_uint256& a, const uint256& b) { return (base_uint256)a == (base_uint256)b; } -inline bool operator!=(const base_uint256& a, const uint256& b) { return (base_uint256)a != (base_uint256)b; } -inline const uint256 operator^(const base_uint256& a, const uint256& b) { return (base_uint256)a ^ (base_uint256)b; } -inline const uint256 operator&(const base_uint256& a, const uint256& b) { return (base_uint256)a & (base_uint256)b; } -inline const uint256 operator|(const base_uint256& a, const uint256& b) { return (base_uint256)a | (base_uint256)b; } -inline const uint256 operator+(const base_uint256& a, const uint256& b) { return (base_uint256)a + (base_uint256)b; } -inline const uint256 operator-(const base_uint256& a, const uint256& b) { return (base_uint256)a - (base_uint256)b; } - -inline bool operator<(const uint256& a, const base_uint256& b) { return (base_uint256)a < (base_uint256)b; } -inline bool operator<=(const uint256& a, const base_uint256& b) { return (base_uint256)a <= (base_uint256)b; } -inline bool operator>(const uint256& a, const base_uint256& b) { return (base_uint256)a > (base_uint256)b; } -inline bool operator>=(const uint256& a, const base_uint256& b) { return (base_uint256)a >= (base_uint256)b; } -inline bool operator==(const uint256& a, const base_uint256& b) { return (base_uint256)a == (base_uint256)b; } -inline bool operator!=(const uint256& a, const base_uint256& b) { return (base_uint256)a != (base_uint256)b; } -inline const uint256 operator^(const uint256& a, const base_uint256& b) { return (base_uint256)a ^ (base_uint256)b; } -inline const uint256 operator&(const uint256& a, const base_uint256& b) { return (base_uint256)a & (base_uint256)b; } -inline const uint256 operator|(const uint256& a, const base_uint256& b) { return (base_uint256)a | (base_uint256)b; } -inline const uint256 operator+(const uint256& a, const base_uint256& b) { return (base_uint256)a + (base_uint256)b; } -inline const uint256 operator-(const uint256& a, const base_uint256& b) { return (base_uint256)a - (base_uint256)b; } - -inline bool operator<(const uint256& a, const uint256& b) { return (base_uint256)a < (base_uint256)b; } -inline bool operator<=(const uint256& a, const uint256& b) { return (base_uint256)a <= (base_uint256)b; } -inline bool operator>(const uint256& a, const uint256& b) { return (base_uint256)a > (base_uint256)b; } -inline bool operator>=(const uint256& a, const uint256& b) { return (base_uint256)a >= (base_uint256)b; } -inline bool operator==(const uint256& a, const uint256& b) { return (base_uint256)a == (base_uint256)b; } -inline bool operator!=(const uint256& a, const uint256& b) { return (base_uint256)a != (base_uint256)b; } -inline const uint256 operator^(const uint256& a, const uint256& b) { return (base_uint256)a ^ (base_uint256)b; } -inline const uint256 operator&(const uint256& a, const uint256& b) { return (base_uint256)a & (base_uint256)b; } -inline const uint256 operator|(const uint256& a, const uint256& b) { return (base_uint256)a | (base_uint256)b; } -inline const uint256 operator+(const uint256& a, const uint256& b) { return (base_uint256)a + (base_uint256)b; } -inline const uint256 operator-(const uint256& a, const uint256& b) { return (base_uint256)a - (base_uint256)b; } - - - - - - - - - - -#ifdef TEST_UINT256 - -inline int Testuint256AdHoc(std::vector vArg) -{ - uint256 g(0); - - - printf("%s\n", g.ToString().c_str()); - g--; printf("g--\n"); - printf("%s\n", g.ToString().c_str()); - g--; printf("g--\n"); - printf("%s\n", g.ToString().c_str()); - g++; printf("g++\n"); - printf("%s\n", g.ToString().c_str()); - g++; printf("g++\n"); - printf("%s\n", g.ToString().c_str()); - g++; printf("g++\n"); - printf("%s\n", g.ToString().c_str()); - g++; printf("g++\n"); - printf("%s\n", g.ToString().c_str()); - - - - uint256 a(7); - printf("a=7\n"); - printf("%s\n", a.ToString().c_str()); - - uint256 b; - printf("b undefined\n"); - printf("%s\n", b.ToString().c_str()); - int c = 3; - - a = c; - a.pn[3] = 15; - printf("%s\n", a.ToString().c_str()); - uint256 k(c); - - a = 5; - a.pn[3] = 15; - printf("%s\n", a.ToString().c_str()); - b = 1; - b <<= 52; - - a |= b; - - a ^= 0x500; - - printf("a %s\n", a.ToString().c_str()); - - a = a | b | (uint256)0x1000; - - - printf("a %s\n", a.ToString().c_str()); - printf("b %s\n", b.ToString().c_str()); - - a = 0xfffffffe; - a.pn[4] = 9; - - printf("%s\n", a.ToString().c_str()); - a++; - printf("%s\n", a.ToString().c_str()); - a++; - printf("%s\n", a.ToString().c_str()); - a++; - printf("%s\n", a.ToString().c_str()); - a++; - printf("%s\n", a.ToString().c_str()); - - a--; - printf("%s\n", a.ToString().c_str()); - a--; - printf("%s\n", a.ToString().c_str()); - a--; - printf("%s\n", a.ToString().c_str()); - uint256 d = a--; - printf("%s\n", d.ToString().c_str()); - printf("%s\n", a.ToString().c_str()); - a--; - printf("%s\n", a.ToString().c_str()); - a--; - printf("%s\n", a.ToString().c_str()); - - d = a; - - printf("%s\n", d.ToString().c_str()); - for (int i = uint256::WIDTH-1; i >= 0; i--) printf("%08x", d.pn[i]); printf("\n"); - - uint256 neg = d; - neg = ~neg; - printf("%s\n", neg.ToString().c_str()); - - - uint256 e = uint256("0xABCDEF123abcdef12345678909832180000011111111"); - printf("\n"); - printf("%s\n", e.ToString().c_str()); - - - printf("\n"); - uint256 x1 = uint256("0xABCDEF123abcdef12345678909832180000011111111"); - uint256 x2; - printf("%s\n", x1.ToString().c_str()); - for (int i = 0; i < 270; i += 4) - { - x2 = x1 << i; - printf("%s\n", x2.ToString().c_str()); - } - - printf("\n"); - printf("%s\n", x1.ToString().c_str()); - for (int i = 0; i < 270; i += 4) - { - x2 = x1; - x2 >>= i; - printf("%s\n", x2.ToString().c_str()); - } - - - for (int i = 0; i < 100; i++) - { - uint256 k = (~uint256(0) >> i); - printf("%s\n", k.ToString().c_str()); - } - - for (int i = 0; i < 100; i++) - { - uint256 k = (~uint256(0) << i); - printf("%s\n", k.ToString().c_str()); - } - - return (0); -} - -#endif - -#endif diff --git a/bitcoin_bignum/version.h b/bitcoin_bignum/version.h deleted file mode 100644 index f1e7c4c..0000000 --- a/bitcoin_bignum/version.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_VERSION_H -#define BITCOIN_VERSION_H - -#include "clientversion.h" -#include - -// -// client versioning -// - -static const int CLIENT_VERSION = - 1000000 * CLIENT_VERSION_MAJOR - + 10000 * CLIENT_VERSION_MINOR - + 100 * CLIENT_VERSION_REVISION - + 1 * CLIENT_VERSION_BUILD; - -extern const std::string CLIENT_NAME; -extern const std::string CLIENT_BUILD; -extern const std::string CLIENT_DATE; - -// -// network protocol versioning -// - -static const int PROTOCOL_VERSION = 70001; - -// earlier versions not supported as of Feb 2012, and are disconnected -static const int MIN_PROTO_VERSION = 209; - -// nTime field added to CAddress, starting with this version; -// if possible, avoid requesting addresses nodes older than this -static const int CADDR_TIME_VERSION = 31402; - -// only request blocks from nodes outside this range of versions -static const int NOBLKS_VERSION_START = 32000; -static const int NOBLKS_VERSION_END = 32400; - -// BIP 0031, pong message, is enabled for all versions AFTER this one -static const int BIP0031_VERSION = 60000; - -// "mempool" command, enhanced "getdata" behavior starts with this version: -static const int MEMPOOL_GD_VERSION = 60002; - -#endif diff --git a/include/libzerocoin.h b/include/libzerocoin.h new file mode 100644 index 0000000..6554917 --- /dev/null +++ b/include/libzerocoin.h @@ -0,0 +1,147 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace libzerocoin { + + class CBigNum { + private: + BIGNUM* bn; + public: + CBigNum(); + explicit CBigNum(const std::string& hex); + CBigNum(const CBigNum& other); + ~CBigNum(); + + // Access methods + BIGNUM* get() const { return bn; } + BIGNUM** get_ptr() { return &bn; } + + CBigNum& operator=(const CBigNum& other); + CBigNum operator+(const CBigNum& other) const; + CBigNum operator*(const CBigNum& other) const; + CBigNum modExp(const CBigNum& exp, const CBigNum& mod) const; + [[nodiscard]] CBigNum modInverse(const CBigNum& mod) const; + [[nodiscard]] std::string toHex() const; + friend CBigNum operator%(const CBigNum& a, const CBigNum& b); + + using Generator = std::mt19937_64; + static CBigNum random(size_t bits, Generator gen = Generator{std::random_device{}()}); + }; + + class uint256 { + private: + uint8_t data[32]; + public: + constexpr uint256() : data{0} {} + explicit uint256(std::span bytes); + explicit uint256(const std::string& hexStr); + + static uint256 hash(std::string_view str); + [[nodiscard]] std::string toHex() const; + [[nodiscard]] CBigNum toBigNum() const; + }; + + class uint512 { + private: + uint8_t data[64]; + public: + constexpr uint512() : data{0} {} + explicit uint512(std::span bytes); + explicit uint512(const std::string& hexStr); + + static uint512 hash(std::string_view str); + [[nodiscard]] std::string toHex() const; + [[nodiscard]] CBigNum toBigNum() const; + }; + + enum CoinDenomination { + ZQ_ERROR = 0, + ZQ_ONE = 1, + ZQ_FIVE = 5, + ZQ_TEN = 10, + ZQ_FIFTY = 50, + ZQ_ONE_HUNDRED = 100, + ZQ_FIVE_HUNDRED = 500, + ZQ_ONE_THOUSAND = 1000, + ZQ_FIVE_THOUSAND = 5000 + }; + + class ZerocoinParams { + public: + ZerocoinParams(CBigNum N, CBigNum g, CBigNum h, CBigNum H, uint32_t securityLevel, uint32_t accumulatorSize); + static std::unique_ptr generate(uint32_t securityLevel, size_t rsaBits = 2048); + [[nodiscard]] bool validate() const; + + CBigNum N; + CBigNum g; + CBigNum h; + CBigNum H; + uint32_t securityLevel; + uint32_t accumulatorSize; + }; + + class PublicCoin { + public: + PublicCoin(std::shared_ptr params, CBigNum value, CoinDenomination denom); + [[nodiscard]] bool validate() const; + [[nodiscard]] bool operator==(const PublicCoin& other) const; + + std::shared_ptr params_; + CBigNum value_; + CoinDenomination denomination_; + }; + + class PrivateCoin { + public: + explicit PrivateCoin(std::shared_ptr params, CoinDenomination denom); + void mint(); + + std::shared_ptr params_; + PublicCoin publicCoin_; + CBigNum serialNumber_; + }; + + class Accumulator { + public: + Accumulator(std::shared_ptr params, CBigNum value); + void accumulate(const CBigNum& coinValue); + void remove(const CBigNum& coinValue); + [[nodiscard]] CBigNum getValue() const; + + std::shared_ptr params_; + CBigNum value_; + uint32_t coinCount_; + }; + + enum Version { V1, V2 }; + + class CoinSpend { + public: + CoinSpend(std::shared_ptr params, + const PrivateCoin& coin, + const Accumulator& accumulator, + uint32_t accumulatorId, + const uint256& ptxHash, + Version version = V2); + [[nodiscard]] bool verify(const Accumulator& accumulator) const; + void generateAccumulatorProof(const Accumulator& accumulator, const CBigNum& witness); + void generateSerialNumberProof(const PrivateCoin& coin); + + std::shared_ptr params_; + CBigNum coinSerialNumber_; + CBigNum accumulatorValue_; + uint256 ptxHash_; + uint32_t accumulatorId_; + Version version_; + }; + +} // namespace libzerocoin diff --git a/libzerocoin.pc.in b/libzerocoin.pc.in new file mode 100644 index 0000000..5362d78 --- /dev/null +++ b/libzerocoin.pc.in @@ -0,0 +1,14 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ +includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ + +Name: @PROJECT_NAME@ +Description: @PROJECT_DESCRIPTION@ +Version: @PROJECT_VERSION@ +URL: @PROJECT_HOMEPAGE_URL@ +Requires: openssl >= 3.0 +Requires.private: boost-serialization >= 1.75 +Libs: -L${libdir} -l@PROJECT_NAME@ +Libs.private: -lcrypto -pthread +Cflags: -I${includedir} -std=c++20 diff --git a/paramgen.cpp b/paramgen.cpp deleted file mode 100644 index 147713c..0000000 --- a/paramgen.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/** - * @file paramgen.cpp - * - * @brief Parameter generation utility 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" - -#define DEFAULT_MODULUS_SIZE 3072 -#define MIN_MODULUS_SIZE 1026 - -using namespace libzerocoin; - -void -PrintWarning() -{ - cout << "Zerocoin parameter generation utility" << endl; - cout << "-------------------------------------" << endl << endl; - cout << "This utility generates an l-bit modulus N as the product of" << endl; - cout << "two safe primes p, q. The values p and q are not stored." << endl; - cout << "Call this program with no arguments to see usage options." << endl; - cout << endl; - cout << "SECURITY WARNING: ZEROCOIN PARAMETERS MUST BE GENERATED BY" << endl; - cout << "A TRUSTED PARTY WHO DOES NOT STORE THE FACTORS. WHILE WE MAKE" << endl; - cout << "A BEST EFFORT TO DESTROY THIS INFORMATION WE DO NOT TAKE" << endl; - cout << "SPECIAL PRECAUTIONS TO ENSURE THAT THEY ARE DESTROYED." << endl; - cout << endl; - cout << "USE THIS UTILITY AT YOUR OWN RISK" << endl << endl; -} - -void usage() -{ - printf("Usage:\n"); - printf(" -b \n"); - printf(" -o \n"); - - exit (8); -} - -int main(int argc, char **argv) -{ - static Bignum resultModulus(0); - uint32_t numBits = DEFAULT_MODULUS_SIZE; - ofstream outfile; - char* outfileName; - bool writeToFile = false; - - while ((argc > 1) && (argv[1][0] == '-')) - { - switch (argv[1][1]) - { - case 'b': - numBits = atoi(argv[2]); - ++argv; - --argc; - break; - - case 'o': - outfileName = argv[2]; - writeToFile = true; - break; - - case 'h': - usage(); - break; - - default: - printf("Wrong Argument: %s\n", argv[1]); - usage(); - break; - } - - ++argv; - --argc; - } - - if (numBits < MIN_MODULUS_SIZE) { - cout << "Modulus is below minimum length (" << MIN_MODULUS_SIZE << ") bits" << endl; - return(0); - } - - PrintWarning(); - - cout << "Modulus size set to " << numBits << " bits." << endl; - cout << "Generating parameters. This may take a few minutes..." << endl; - - // Generate two safe primes "p" and "q" - Bignum *p, *q; - p = new Bignum(0); - q = new Bignum(0); - *p = Bignum::generatePrime(numBits / 2, true); - *q = Bignum::generatePrime(numBits / 2, true); - - // Multiply to compute N - resultModulus = (*p) * (*q); - - // Wipe out the factors - delete p; - delete q; - - // Convert to a hexidecimal string - std::string resultHex = resultModulus.ToString(16); - - cout << endl << "N = " << endl << resultHex << endl; - - if (writeToFile) { - try { - outfile.open (outfileName); - outfile << resultHex; - outfile.close(); - cout << endl << "Result has been written to file '" << outfileName << "'." << endl; - } catch (std::runtime_error &e) { - cout << "Unable to write to file:" << e.what() << endl; - } - } -} diff --git a/src/libzerocoin.cpp b/src/libzerocoin.cpp new file mode 100644 index 0000000..1c09614 --- /dev/null +++ b/src/libzerocoin.cpp @@ -0,0 +1,355 @@ +#include "libzerocoin.h" +#include +#include +#include +#include +#include +#include +#include + +namespace libzerocoin { + + // Implement operator% for CBigNum + CBigNum operator%(const CBigNum& a, const CBigNum& b) { + BN_CTX* ctx = BN_CTX_new(); + if (!ctx) throw std::bad_alloc(); + + CBigNum result; + if (!BN_mod(result.get(), a.get(), b.get(), ctx)) { + BN_CTX_free(ctx); + throw std::runtime_error("BN_mod failed"); + } + BN_CTX_free(ctx); + return result; + } + + // ===================== CBigNum Implementation ===================== + CBigNum::CBigNum() : bn(BN_new()) { + if (!bn) throw std::bad_alloc(); + } + + CBigNum::CBigNum(const std::string& hex) : bn(BN_new()) { + if (!bn) throw std::bad_alloc(); + if (!BN_hex2bn(&bn, hex.c_str())) { + throw std::invalid_argument("Invalid hex string for CBigNum"); + } + } + + CBigNum::CBigNum(const CBigNum& other) : bn(BN_dup(other.bn)) { + if (!bn) throw std::bad_alloc(); + } + + CBigNum::~CBigNum() { + if (bn) BN_free(bn); + } + + CBigNum& CBigNum::operator=(const CBigNum& other) { + if (this != &other) { + BN_copy(bn, other.bn); + } + return *this; + } + + CBigNum CBigNum::operator+(const CBigNum& other) const { + CBigNum result; + if (!BN_add(result.bn, bn, other.bn)) { + throw std::runtime_error("BN_add failed"); + } + return result; + } + + CBigNum CBigNum::operator*(const CBigNum& other) const { + CBigNum result; + BN_CTX* ctx = BN_CTX_new(); + if (!ctx) throw std::bad_alloc(); + + if (!BN_mul(result.bn, bn, other.bn, ctx)) { + BN_CTX_free(ctx); + throw std::runtime_error("BN_mul failed"); + } + BN_CTX_free(ctx); + return result; + } + + CBigNum CBigNum::modExp(const CBigNum& exp, const CBigNum& mod) const { + CBigNum result; + BN_CTX* ctx = BN_CTX_new(); + if (!ctx) throw std::bad_alloc(); + + if (!BN_mod_exp(result.bn, bn, exp.bn, mod.bn, ctx)) { + BN_CTX_free(ctx); + throw std::runtime_error("BN_mod_exp failed"); + } + BN_CTX_free(ctx); + return result; + } + + CBigNum CBigNum::modInverse(const CBigNum& mod) const { + CBigNum result; + BN_CTX* ctx = BN_CTX_new(); + if (!ctx) throw std::bad_alloc(); + + if (!BN_mod_inverse(result.bn, bn, mod.bn, ctx)) { + BN_CTX_free(ctx); + throw std::runtime_error("BN_mod_inverse failed"); + } + BN_CTX_free(ctx); + return result; + } + + std::string CBigNum::toHex() const { + char* hex = BN_bn2hex(bn); + if (!hex) throw std::runtime_error("BN_bn2hex failed"); + std::string result(hex); + OPENSSL_free(hex); + return result; + } + + CBigNum CBigNum::random(size_t bits, Generator gen) { + CBigNum result; + const size_t bytes = (bits + 7) / 8; + std::vector data(bytes); + + std::uniform_int_distribution dist(0, 255); + for (auto& byte : data) { + byte = dist(gen); + } + + if (!BN_bin2bn(data.data(), data.size(), result.bn)) { + throw std::runtime_error("BN_bin2bn failed"); + } + return result; + } + + // ===================== uint256 Implementation ===================== + uint256::uint256(std::span bytes) { + if (bytes.size() != 32) { + throw std::invalid_argument("uint256 requires exactly 32 bytes"); + } + std::copy(bytes.begin(), bytes.end(), data); + } + + uint256::uint256(const std::string& hexStr) { + if (hexStr.size() != 64) { + throw std::invalid_argument("Invalid hex string length for uint256"); + } + + for (size_t i = 0; i < 32; ++i) { + std::string byteStr = hexStr.substr(i * 2, 2); + char* end = nullptr; + unsigned long value = std::strtoul(byteStr.c_str(), &end, 16); + + if (end != byteStr.c_str() + 2 || value > 0xFF) { + throw std::invalid_argument("Invalid hex digit in uint256 string"); + } + data[i] = static_cast(value); + } + } + + uint256 uint256::hash(std::string_view str) { + uint256 result; + SHA256_CTX ctx; + SHA256_Init(&ctx); + SHA256_Update(&ctx, str.data(), str.size()); + SHA256_Final(result.data, &ctx); + return result; + } + + std::string uint256::toHex() const { + std::ostringstream ss; + ss << std::hex << std::setfill('0'); + for (uint8_t b : data) { + ss << std::setw(2) << static_cast(b); + } + return ss.str(); + } + + CBigNum uint256::toBigNum() const { + CBigNum result; + BN_bin2bn(data, sizeof(data), result.get()); + return result; + } + + // ===================== uint512 Implementation ===================== + uint512::uint512(std::span bytes) { + if (bytes.size() != 64) { + throw std::invalid_argument("uint512 requires exactly 64 bytes"); + } + std::copy(bytes.begin(), bytes.end(), data); + } + + uint512::uint512(const std::string& hexStr) { + if (hexStr.size() != 128) { + throw std::invalid_argument("Invalid hex string length for uint512"); + } + + for (size_t i = 0; i < 64; ++i) { + std::string byteStr = hexStr.substr(i * 2, 2); + char* end = nullptr; + unsigned long value = std::strtoul(byteStr.c_str(), &end, 16); + + if (end != byteStr.c_str() + 2 || value > 0xFF) { + throw std::invalid_argument("Invalid hex digit in uint512 string"); + } + data[i] = static_cast(value); + } + } + + uint512 uint512::hash(std::string_view str) { + uint512 result; + SHA512_CTX ctx; + SHA512_Init(&ctx); + SHA512_Update(&ctx, str.data(), str.size()); + SHA512_Final(result.data, &ctx); + return result; + } + + std::string uint512::toHex() const { + std::ostringstream ss; + ss << std::hex << std::setfill('0'); + for (uint8_t b : data) { + ss << std::setw(2) << static_cast(b); + } + return ss.str(); + } + + CBigNum uint512::toBigNum() const { + CBigNum result; + BN_bin2bn(data, sizeof(data), result.get()); + return result; + } + + // ===================== ZerocoinParams Implementation ===================== + ZerocoinParams::ZerocoinParams(CBigNum N, CBigNum g, CBigNum h, CBigNum H, + uint32_t securityLevel, uint32_t accumulatorSize) + : N(std::move(N)), g(std::move(g)), h(std::move(h)), H(std::move(H)), + securityLevel(securityLevel), accumulatorSize(accumulatorSize) {} + + std::unique_ptr ZerocoinParams::generate(uint32_t securityLevel, size_t rsaBits) { + CBigNum N = CBigNum::random(rsaBits); + + const auto g_str = "Generator g for Zerocoin, security: " + std::to_string(securityLevel); + const auto h_str = "Generator h for Zerocoin, security: " + std::to_string(securityLevel); + const auto H_str = "Generator H (SHA-512) for Zerocoin, security: " + std::to_string(securityLevel); + + CBigNum g = uint512::hash(g_str).toBigNum() % N; + CBigNum h = uint512::hash(h_str).toBigNum() % N; + CBigNum H = uint512::hash(H_str).toBigNum() % N; + + return std::make_unique( + std::move(N), + std::move(g), + std::move(h), + std::move(H), + securityLevel, + 0 + ); + } + + bool ZerocoinParams::validate() const { + return !N.toHex().empty() && + !g.toHex().empty() && + !h.toHex().empty() && + !H.toHex().empty(); + } + + // ===================== PublicCoin Implementation ===================== + PublicCoin::PublicCoin(std::shared_ptr params, + CBigNum value, CoinDenomination denom) + : params_(std::move(params)), value_(std::move(value)), denomination_(denom) {} + + bool PublicCoin::validate() const { + return params_ && + !value_.toHex().empty() && + denomination_ != ZQ_ERROR; + } + + bool PublicCoin::operator==(const PublicCoin& other) const { + return value_.toHex() == other.value_.toHex() && + denomination_ == other.denomination_; + } + + // ===================== PrivateCoin Implementation ===================== + PrivateCoin::PrivateCoin(std::shared_ptr params, CoinDenomination denom) + : params_(std::move(params)), + publicCoin_(params_, CBigNum(), denom), + serialNumber_(CBigNum::random(256)) {} + + void PrivateCoin::mint() { + publicCoin_ = PublicCoin( + params_, + params_->H.modExp(serialNumber_, params_->N), + publicCoin_.denomination_ + ); + } + + // ===================== Accumulator Implementation ===================== + Accumulator::Accumulator(std::shared_ptr params, CBigNum value) + : params_(std::move(params)), value_(std::move(value)), coinCount_(0) {} + + void Accumulator::accumulate(const CBigNum& coinValue) { + BN_CTX* ctx = BN_CTX_new(); + if (!ctx) throw std::bad_alloc(); + + BN_mod_mul( + value_.get(), + value_.get(), + coinValue.get(), + params_->N.get(), + ctx + ); + BN_CTX_free(ctx); + coinCount_++; + } + + void Accumulator::remove(const CBigNum& coinValue) { + CBigNum inv = coinValue.modInverse(params_->N); + BN_CTX* ctx = BN_CTX_new(); + if (!ctx) throw std::bad_alloc(); + + BN_mod_mul( + value_.get(), + value_.get(), + inv.get(), + params_->N.get(), + ctx + ); + BN_CTX_free(ctx); + coinCount_--; + } + + CBigNum Accumulator::getValue() const { + return value_; + } + + // ===================== CoinSpend Implementation ===================== + CoinSpend::CoinSpend(std::shared_ptr params, + const PrivateCoin& coin, + const Accumulator& accumulator, + uint32_t accumulatorId, + const uint256& ptxHash, + Version version) + : params_(std::move(params)), + coinSerialNumber_(coin.serialNumber_), + accumulatorValue_(accumulator.getValue()), + ptxHash_(ptxHash), + accumulatorId_(accumulatorId), + version_(version) {} + + bool CoinSpend::verify(const Accumulator& accumulator) const { + if (accumulatorValue_.toHex() != accumulator.getValue().toHex()) { + return false; + } + return true; + } + + void CoinSpend::generateAccumulatorProof(const Accumulator& accumulator, const CBigNum& witness) { + (void)accumulator; + (void)witness; + } + + void CoinSpend::generateSerialNumberProof(const PrivateCoin& coin) { + (void)coin; + } + +} // namespace libzerocoin diff --git a/zerocoin.pc.in b/zerocoin.pc.in deleted file mode 100644 index 67834e1..0000000 --- a/zerocoin.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: zerocoin -Description: Zerocoin cryptographic routines library -Requires: -Version: @LIBVER@ -Libs: -L${libdir} -lzerocoin -lcrypto -Cflags: -I${includedir}