Fix LLVM compilation issues
[novacoin.git] / src / zerocoin / CoinSpend.cpp
1 /**
2  * @file       CoinSpend.cpp
3  *
4  * @brief      CoinSpend 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
13 #include "Zerocoin.h"
14
15 namespace libzerocoin {
16
17 CoinSpend::CoinSpend(const Params* p, const PrivateCoin& coin,
18                      Accumulator& a, const AccumulatorWitness& witness, const SpendMetaData& m):
19         params(p),
20         denomination(coin.getPublicCoin().getDenomination()),
21         coinSerialNumber((coin.getSerialNumber())),
22         accumulatorPoK(&p->accumulatorParams),
23         serialNumberSoK(p),
24         commitmentPoK(&p->serialNumberSoKCommitmentGroup, &p->accumulatorParams.accumulatorPoKCommitmentGroup) {
25
26         // Sanity check: let's verify that the Witness is valid with respect to
27         // the coin and Accumulator provided.
28         if (!(witness.VerifyWitness(a, coin.getPublicCoin()))) {
29                 throw std::invalid_argument("Accumulator witness does not verify");
30         }
31
32         // 1: Generate two separate commitments to the public coin (C), each under
33         // a different set of public parameters. We do this because the RSA accumulator
34         // has specific requirements for the commitment parameters that are not
35         // compatible with the group we use for the serial number proof.
36         // Specifically, our serial number proof requires the order of the commitment group
37         // to be the same as the modulus of the upper group. The Accumulator proof requires a
38         // group with a significantly larger order.
39         const Commitment fullCommitmentToCoinUnderSerialParams(&p->serialNumberSoKCommitmentGroup, coin.getPublicCoin().getValue());
40         this->serialCommitmentToCoinValue = fullCommitmentToCoinUnderSerialParams.getCommitmentValue();
41
42         const Commitment fullCommitmentToCoinUnderAccParams(&p->accumulatorParams.accumulatorPoKCommitmentGroup, coin.getPublicCoin().getValue());
43         this->accCommitmentToCoinValue = fullCommitmentToCoinUnderAccParams.getCommitmentValue();
44
45         // 2. Generate a ZK proof that the two commitments contain the same public coin.
46         this->commitmentPoK = CommitmentProofOfKnowledge(&p->serialNumberSoKCommitmentGroup, &p->accumulatorParams.accumulatorPoKCommitmentGroup, fullCommitmentToCoinUnderSerialParams, fullCommitmentToCoinUnderAccParams);
47
48         // Now generate the two core ZK proofs:
49         // 3. Proves that the committed public coin is in the Accumulator (PoK of "witness")
50         this->accumulatorPoK = AccumulatorProofOfKnowledge(&p->accumulatorParams, fullCommitmentToCoinUnderAccParams, witness, a);
51
52         // 4. Proves that the coin is correct w.r.t. serial number and hidden coin secret
53         // (This proof is bound to the coin 'metadata', i.e., transaction hash)
54         this->serialNumberSoK = SerialNumberSignatureOfKnowledge(p, coin, fullCommitmentToCoinUnderSerialParams, signatureHash(m));
55 }
56
57 const Bignum&
58 CoinSpend::getCoinSerialNumber() {
59         return this->coinSerialNumber;
60 }
61
62 const CoinDenomination
63 CoinSpend::getDenomination() {
64         return static_cast<CoinDenomination>(this->denomination);
65 }
66
67 bool
68 CoinSpend::Verify(const Accumulator& a, const SpendMetaData &m) const {
69         // Verify both of the sub-proofs using the given meta-data
70         return  (a.getDenomination() == this->denomination)
71                 && commitmentPoK.Verify(serialCommitmentToCoinValue, accCommitmentToCoinValue)
72                 && accumulatorPoK.Verify(a, accCommitmentToCoinValue)
73                 && serialNumberSoK.Verify(coinSerialNumber, serialCommitmentToCoinValue, signatureHash(m));
74 }
75
76 const uint256 CoinSpend::signatureHash(const SpendMetaData &m) const {
77         CHashWriter h(0,0);
78         h << m << serialCommitmentToCoinValue << accCommitmentToCoinValue << commitmentPoK << accumulatorPoK;
79         return h.GetHash();
80 }
81
82 } /* namespace libzerocoin */