1010#include " main.h"
1111#include " iostream"
1212
13+ PublicCoinSpend::PublicCoinSpend (libzerocoin::ZerocoinParams* params, const uint8_t version,
14+ const CBigNum& serial, const CBigNum& randomness, const uint256& ptxHash, CPubKey* pubkey):
15+ pubCoin(params)
16+ {
17+ this ->coinSerialNumber = serial;
18+ this ->version = version;
19+ this ->spendType = libzerocoin::SpendType::SPEND;
20+ this ->ptxHash = ptxHash;
21+
22+ const int coinVersion = getCoinVersion ();
23+
24+ if (coinVersion < libzerocoin::PrivateCoin::PUBKEY_VERSION) {
25+ // v1 coins need at least version 4 spends
26+ if (version < PUBSPEND_SCHNORR) {
27+ std::string errMsg = strprintf (" Unable to create PublicCoinSpend version %d with coin version 1. "
28+ " Minimum spend version required: %d" , version, PUBSPEND_SCHNORR);
29+ throw std::runtime_error (errMsg);
30+ }
31+
32+ } else {
33+ // pubkey available only from v2 coins onwards
34+ this ->pubkey = *pubkey;
35+ }
36+
37+ if (version < PUBSPEND_SCHNORR)
38+ this ->randomness = randomness;
39+ else
40+ this ->schnorrSig = libzerocoin::CoinRandomnessSchnorrSignature (params, randomness, ptxHash);
41+
42+ }
43+
1344bool PublicCoinSpend::Verify (const libzerocoin::Accumulator& a, bool verifyParams) const {
1445 return validate ();
1546}
1647
1748bool PublicCoinSpend::validate () const {
18- libzerocoin::ZerocoinParams* params = Params ().Zerocoin_Params (false );
19- // Check that it opens to the input values
20- libzerocoin::Commitment commitment (
21- ¶ms->coinCommitmentGroup , getCoinSerialNumber (), randomness);
49+ bool fUseV1Params = getCoinVersion () < libzerocoin::PrivateCoin::PUBKEY_VERSION;
50+ if (version < PUBSPEND_SCHNORR) {
51+ // spend contains the randomness of the coin
52+ if (fUseV1Params ) {
53+ // Only v2+ coins can publish the randomness
54+ std::string errMsg = strprintf (" PublicCoinSpend version %d with coin version 1 not allowed. "
55+ " Minimum spend version required: %d" , version, PUBSPEND_SCHNORR);
56+ return error (" %s: %s" , __func__, errMsg);
57+ }
2258
23- if (commitment.getCommitmentValue () != pubCoin.getValue ()){
24- return error (" %s: commitments values are not equal" , __func__);
59+ // Check that the coin is a commitment to serial and randomness.
60+ libzerocoin::ZerocoinParams* params = Params ().Zerocoin_Params (false );
61+ libzerocoin::Commitment comm (¶ms->coinCommitmentGroup , getCoinSerialNumber (), randomness);
62+ if (comm.getCommitmentValue () != pubCoin.getValue ()) {
63+ return error (" %s: commitments values are not equal" , __func__);
64+ }
65+ } else {
66+ // spend contains a shnorr signature of ptxHash with the randomness of the coin
67+ libzerocoin::ZerocoinParams* params = Params ().Zerocoin_Params (fUseV1Params );
68+ if (!schnorrSig.Verify (params, getCoinSerialNumber (), pubCoin.getValue (), getTxOutHash ())) {
69+ return error (" %s: schnorr signature does not verify" , __func__);
70+ }
2571 }
72+
2673 // Now check that the signature validates with the serial
2774 if (!HasValidSignature ()) {
2875 return error (" %s: signature invalid" , __func__);;
@@ -39,29 +86,41 @@ const uint256 PublicCoinSpend::signatureHash() const
3986
4087namespace ZPIVModule {
4188
42- bool createInput (CTxIn &in, CZerocoinMint &mint, uint256 hashTxOut) {
43- libzerocoin::ZerocoinParams *params = Params ().Zerocoin_Params (false );
44- uint8_t nVersion = mint.GetVersion ();
45- if (nVersion < libzerocoin::PrivateCoin::PUBKEY_VERSION) {
46- // No v1 serials accepted anymore.
47- return error (" %s: failed to set zPIV privkey mint version=%d" , __func__, nVersion);
89+ bool createInput (CTxIn &in, CZerocoinMint &mint, uint256 hashTxOut, const int spendVersion) {
90+ bool fUseV1Params = mint.GetVersion () < libzerocoin::PrivateCoin::PUBKEY_VERSION;
91+ libzerocoin::ZerocoinParams *params = Params ().Zerocoin_Params (fUseV1Params );
92+ if (fUseV1Params && spendVersion < PUBSPEND_SCHNORR) {
93+ // v1 coins need at least version 4 spends
94+ std::string errMsg = strprintf (" Unable to create PublicCoinSpend version %d with coin version 1. "
95+ " Minimum spend version required: %d" , spendVersion, PUBSPEND_SCHNORR);
96+ return error (" %s: %s" , __func__, errMsg);
4897 }
4998
5099 CKey key;
51- if (!mint.GetKeyPair (key))
52- return error (" %s: failed to set zPIV privkey mint version=%d" , __func__, nVersion);
53100
54- PublicCoinSpend spend (params, mint.GetSerialNumber (), mint.GetRandomness (), key.GetPubKey ());
55- spend.setTxOutHash (hashTxOut);
101+ CPubKey pk;
102+ CPubKey* pk_ptr = nullptr ;
103+ if (!fUseV1Params ) {
104+ if (!mint.GetKeyPair (key))
105+ return error (" %s: failed to set zPIV privkey mint." , __func__);
106+ pk = key.GetPubKey ();
107+ pk_ptr = &pk;
108+ }
109+
110+ PublicCoinSpend spend (params, spendVersion, mint.GetSerialNumber (),
111+ mint.GetRandomness (), hashTxOut, pk_ptr);
112+
56113 spend.outputIndex = mint.GetOutputIndex ();
57114 spend.txHash = mint.GetTxHash ();
58115 spend.setDenom (mint.GetDenomination ());
59116
60117 std::vector<unsigned char > vchSig;
61- if (!key.Sign (spend.signatureHash (), vchSig))
62- throw std::runtime_error (" ZPIVModule failed to sign signatureHash\n " );
118+ if (!fUseV1Params ) {
119+ if (!key.Sign (spend.signatureHash (), vchSig))
120+ throw std::runtime_error (" ZPIVModule failed to sign signatureHash\n " );
63121
64- spend.setVchSig (vchSig);
122+ spend.setVchSig (vchSig);
123+ }
65124
66125 CDataStream ser (SER_NETWORK, PROTOCOL_VERSION);
67126 ser << spend;
@@ -75,10 +134,14 @@ namespace ZPIVModule {
75134 }
76135
77136 PublicCoinSpend parseCoinSpend (const CTxIn &in) {
137+ libzerocoin::ZerocoinParams *params = Params ().Zerocoin_Params (false );
138+ // skip opcode and data-len
139+ uint8_t byteskip (in.scriptSig [1 ]);
140+ byteskip += 2 ;
78141 std::vector<char , zero_after_free_allocator<char > > data;
79- data.insert (data.end (), in.scriptSig .begin () + 4 , in.scriptSig .end ());
142+ data.insert (data.end (), in.scriptSig .begin () + byteskip , in.scriptSig .end ());
80143 CDataStream serializedCoinSpend (data, SER_NETWORK, PROTOCOL_VERSION);
81- libzerocoin::ZerocoinParams *params = Params (). Zerocoin_Params ( false );
144+
82145 return PublicCoinSpend (params, serializedCoinSpend);
83146 }
84147
@@ -112,7 +175,6 @@ namespace ZPIVModule {
112175 libzerocoin::IntToZerocoinDenomination (in.nSequence )) != prevOut.nValue ) {
113176 return error (" PublicCoinSpend validateInput :: input nSequence different to prevout value" );
114177 }
115-
116178 return publicSpend.validate ();
117179 }
118180
0 commit comments