123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- // ECOin - Copyright (c) - 2014/2022 - GPLv3 - epsylon@riseup.net (https://03c8.net)º
- #include <stdexcept>
- #include "Zerocoin.h"
- namespace libzerocoin {
- //PublicCoin class
- PublicCoin::PublicCoin(const Params* p):
- params(p), denomination(ZQ_PEDERSEN) {
- if(this->params->initialized == false) {
- throw std::invalid_argument("Params are not initialized");
- }
- };
- PublicCoin::PublicCoin(const Params* p, const CBigNum& coin, const CoinDenomination d):
- params(p), value(coin), denomination(d) {
- if(this->params->initialized == false) {
- throw std::invalid_argument("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 CBigNum& PublicCoin::getValue() const {
- return this->value;
- }
- const CoinDenomination PublicCoin::getDenomination() const {
- return static_cast<CoinDenomination>(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 std::invalid_argument("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 CBigNum& PrivateCoin::getSerialNumber() const {
- return this->serialNumber;
- }
- const CBigNum& 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.
- CBigNum s = CBigNum::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.
- CBigNum s = CBigNum::randBignum(this->params->coinCommitmentGroup.groupOrder);
-
- // Generate a random number "r" in the range 0...{q-1}
- CBigNum r = CBigNum::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
- CBigNum 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}
- CBigNum r_delta = CBigNum::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 */
|