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)); }
bool CalculateAccumulatorWitnessFor( const ZerocoinParams* params, int startHeight, int maxCalulationRange, CoinDenomination den, const CBloomFilter& filter, Accumulator& accumulator, AccumulatorWitness& witness, int& nMintsAdded, string& strError, list<CBigNum>& ret, int &heightStop ){ // Lock if (!LockMethod()) return false; try { // Dummy coin init PublicCoin temp(params, 0, den); // Dummy Acc init Accumulator testingAcc(params, den); //get the checkpoint added at the next multiple of 10 int nHeightCheckpoint = startHeight + (10 - (startHeight % 10)); // Get the base accumulator // TODO: This needs to be changed to the partial witness calculation on the next version. CBigNum bnAccValue = 0; if (GetAccumulatorValue(nHeightCheckpoint, den, bnAccValue)) { accumulator.setValue(bnAccValue); witness.resetValue(accumulator, temp); } // Add the pubcoins from the blockchain up to the next checksum starting from the block CBlockIndex *pindex = chainActive[nHeightCheckpoint -10]; int nChainHeight = chainActive.Height(); int nHeightStop = nChainHeight % 10; nHeightStop = nChainHeight - nHeightStop - 20; // at least two checkpoints deep if (nHeightStop - startHeight > maxCalulationRange) { int stop = (startHeight + maxCalulationRange); int nHeightStop = stop % 10; nHeightStop = stop - nHeightStop - 20; } heightStop = nHeightStop; nMintsAdded = 0; // Starts on top of the witness that the node sent libzerocoin::Accumulator witnessAccumulator(params, den, witness.getValue()); if(!calculateAccumulatedBlocksFor( startHeight, nHeightStop, pindex, bnAccValue, accumulator, den, filter, witnessAccumulator, ret, strError )) return error("CalculateAccumulatorWitnessFor(): Calculate accumulated coins failed"); // reset the value witness.resetValue(witnessAccumulator, temp); // calculate how many mints of this denomination existed in the accumulator we initialized nMintsAdded += ComputeAccumulatedCoins(startHeight, den); LogPrint("zero", "%s : %d mints added to witness\n", __func__, nMintsAdded); return true; } catch (ChecksumInDbNotFoundException e) { return error("%s: ChecksumInDbNotFoundException: %s", __func__, e.message); } catch (GetPubcoinException e) { return error("%s: GetPubcoinException: %s", __func__, e.message); } }