Line data Source code
1 : /** 2 : * @file Coin.cpp 3 : * 4 : * @brief PublicCoin class for the Zerocoin library. 5 : * 6 : * @author Ian Miers, Christina Garman and Matthew Green 7 : * @date June 2013 8 : * 9 : * @copyright Copyright 2013 Ian Miers, Christina Garman and Matthew Green 10 : * @license This project is released under the MIT license. 11 : **/ 12 : // Copyright (c) 2017-2021 The PIVX Core developers 13 : 14 : #include <stdexcept> 15 : #include <iostream> 16 : #include "Coin.h" 17 : #include "Commitment.h" 18 : #include "pubkey.h" 19 : 20 : namespace libzerocoin { 21 : 22 : //PublicCoin class 23 0 : PublicCoin::PublicCoin(const ZerocoinParams* p): 24 0 : params(p) { 25 0 : if (!this->params->initialized) { 26 0 : throw std::runtime_error("Params are not initialized"); 27 : } 28 : // Assume this will get set by another method later 29 0 : denomination = ZQ_ERROR; 30 0 : }; 31 : 32 0 : PublicCoin::PublicCoin(const ZerocoinParams* p, const CBigNum& coin, const CoinDenomination d): 33 0 : params(p), value(coin), denomination(d) { 34 0 : if (!this->params->initialized) { 35 0 : throw std::runtime_error("Params are not initialized"); 36 : } 37 0 : if (denomination == 0) { 38 0 : throw std::runtime_error("Denomination does not exist"); 39 : } 40 0 : }; 41 : 42 0 : bool PublicCoin::validate() const 43 : { 44 0 : if (this->params->accumulatorParams.minCoinValue >= value) { 45 0 : return error("%s: ERROR: PublicCoin::validate value is too low: %s", __func__, value.GetDec()); 46 : } 47 : 48 0 : if (value > this->params->accumulatorParams.maxCoinValue) { 49 0 : return error("%s: ERROR: PublicCoin::validate value is too high, max: %s, received: %s", 50 0 : __func__, this->params->accumulatorParams.maxCoinValue, value.GetDec()); 51 : } 52 : 53 0 : if (!value.isPrime(params->zkp_iterations)) { 54 0 : return error("%s: ERROR: PublicCoin::validate value is not prime. Value: %s, Iterations: %d", 55 0 : __func__, value.GetDec(), params->zkp_iterations); 56 : } 57 : 58 : return true; 59 : } 60 : 61 0 : int ExtractVersionFromSerial(const CBigNum& bnSerial) 62 : { 63 0 : try { 64 : //Serial is marked as v2 only if the first byte is 0xF 65 0 : arith_uint256 nMark = bnSerial.getuint256() >> (256 - V2_BITSHIFT); 66 0 : if (nMark == arith_uint256(0xf)) 67 0 : return PUBKEY_VERSION; 68 0 : } catch (const std::range_error& e) { 69 : //std::cout << "ExtractVersionFromSerial(): " << e.what() << std::endl; 70 : // Only serial version 2 appeared with this range error.. 71 0 : return 2; 72 : } 73 : 74 0 : return 1; 75 : } 76 : 77 : //Remove the first four bits for V2 serials 78 0 : CBigNum GetAdjustedSerial(const CBigNum& bnSerial) 79 : { 80 0 : const uint256& serial = ArithToUint256(bnSerial.getuint256() & (~ARITH_UINT256_ZERO >> V2_BITSHIFT)); 81 0 : CBigNum bnSerialAdjusted; 82 0 : bnSerialAdjusted.setuint256(serial); 83 0 : return bnSerialAdjusted; 84 : } 85 : 86 : 87 0 : bool IsValidSerial(const ZerocoinParams* params, const CBigNum& bnSerial) 88 : { 89 0 : if (bnSerial <= 0) 90 : return false; 91 : 92 0 : if (ExtractVersionFromSerial(bnSerial) < PUBKEY_VERSION) 93 0 : return bnSerial < params->coinCommitmentGroup.groupOrder; 94 : 95 : // If V2, the serial is marked with 0xF in the first 4 bits. So It's always > groupOrder. 96 : // This is removed for the adjusted serial - so it's always < groupOrder. 97 : // So we check only the bitsize here. 98 0 : return bnSerial.bitSize() <= 256; 99 : } 100 : 101 : 102 0 : bool IsValidCommitmentToCoinRange(const ZerocoinParams* params, const CBigNum& bnCommitment) 103 : { 104 0 : return bnCommitment > BN_ZERO && bnCommitment < params->serialNumberSoKCommitmentGroup.modulus; 105 : } 106 : 107 : 108 0 : CBigNum ExtractSerialFromPubKey(const CPubKey pubkey) 109 : { 110 0 : const arith_uint256& hashedPubkey = UintToArith256(Hash(pubkey.begin(), pubkey.end())) >> V2_BITSHIFT; 111 0 : arith_uint256 uintSerial = (arith_uint256(0xF) << (256 - V2_BITSHIFT)) | hashedPubkey; 112 0 : return CBigNum(ArithToUint256(uintSerial)); 113 : } 114 : 115 : 116 : } /* namespace libzerocoin */