1+ // Copyright (c) 2019 The PIVX developers
2+ // Distributed under the MIT software license, see the accompanying
3+ // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+ #include " zpiv/zpivmodule.h"
6+ #include " zpivchain.h"
7+ #include " chainparams.h"
8+ #include " libzerocoin/Commitment.h"
9+ #include " libzerocoin/Coin.h"
10+ #include " hash.h"
11+ #include " iostream"
12+
13+ bool PublicCoinSpend::HasValidSerial (libzerocoin::ZerocoinParams* params) const {
14+ return IsValidSerial (params, coinSerialNumber);
15+ }
16+
17+ bool PublicCoinSpend::HasValidSignature () const {
18+ // Now check that the signature validates with the serial
19+ try {
20+ // V2 serial requires that the signature hash be signed by the public key associated with the serial
21+ uint256 hashedPubkey = Hash (pubkey.begin (), pubkey.end ()) >> libzerocoin::PrivateCoin::V2_BITSHIFT;
22+ if (hashedPubkey != libzerocoin::GetAdjustedSerial (coinSerialNumber).getuint256 ()) {
23+ return error (" %s: adjusted serial invalid\n " , __func__);
24+ }
25+ } catch (std::range_error &e) {
26+ throw libzerocoin::InvalidSerialException (" Serial longer than 256 bits" );
27+ }
28+
29+ if (!pubkey.Verify (hashTxOut, vchSig)){
30+ std::cout << " pubkey not verified" << std::endl;
31+ return error (" %s: adjusted serial invalid\n " , __func__);
32+ }
33+ return true ;
34+ }
35+
36+ bool ZPIVModule::createInput (CTxIn &in, CZerocoinMint mint, uint256 hashTxOut){
37+ uint8_t nVersion = mint.GetVersion ();
38+ if (nVersion < libzerocoin::PrivateCoin::PUBKEY_VERSION) {
39+ // No v1 serials accepted anymore.
40+ return error (" %s: failed to set zPIV privkey mint version=%d\n " , __func__, nVersion);
41+ }
42+ CKey key;
43+ if (!mint.GetKeyPair (key))
44+ return error (" %s: failed to set zPIV privkey mint version=%d\n " , __func__, nVersion);
45+
46+ std::vector<unsigned char > vchSig;
47+ if (!key.Sign (hashTxOut, vchSig))
48+ throw std::runtime_error (" ZPIVModule failed to sign hashTxOut\n " );
49+
50+ CDataStream ser (SER_NETWORK, PROTOCOL_VERSION);
51+ PublicCoinSpend spend (mint.GetSerialNumber (), mint.GetRandomness (), key.GetPubKey (), vchSig);
52+ ser << spend;
53+
54+ std::vector<unsigned char > data (ser.begin (), ser.end ());
55+ CScript scriptSigIn = CScript () << OP_ZEROCOINPUBLICSPEND << data.size ();
56+ scriptSigIn.insert (scriptSigIn.end (), data.begin (), data.end ());
57+ in = CTxIn (mint.GetTxHash (), mint.GetOutputIndex (), scriptSigIn, mint.GetDenomination ());
58+ return true ;
59+ }
60+
61+ PublicCoinSpend ZPIVModule::parseCoinSpend (const CTxIn &in, const CTransaction& tx){
62+ if (!in.scriptSig .IsZerocoinPublicSpend ()) throw runtime_error (" parseCoinSpend() :: input is not a public coin spend" );
63+ std::vector<char , zero_after_free_allocator<char > > data;
64+ data.insert (data.end (), in.scriptSig .begin () + 4 , in.scriptSig .end ());
65+ CDataStream serializedCoinSpend (data, SER_NETWORK, PROTOCOL_VERSION);
66+ PublicCoinSpend spend (serializedCoinSpend);
67+ spend.outputIndex = in.prevout .n ;
68+ spend.txHash = in.prevout .hash ;
69+ CTransaction txNew;
70+ txNew.vout = tx.vout ;
71+ spend.hashTxOut = txNew.GetHash ();
72+ return spend;
73+ }
74+
75+ bool ZPIVModule::validateInput (const CTxIn &in, const CTxOut &prevOut, const CTransaction& tx, PublicCoinSpend& ret){
76+ if (!in.scriptSig .IsZerocoinPublicSpend () || !prevOut.scriptPubKey .IsZerocoinMint ())
77+ return error (" %s: not valid argument/s\n " , __func__);
78+
79+ // Now prove that the commitment value opens to the input
80+ PublicCoinSpend publicSpend = parseCoinSpend (in, tx);
81+ libzerocoin::ZerocoinParams* params = Params ().Zerocoin_Params (false );
82+
83+ // Check prev out now
84+ CValidationState state;
85+ libzerocoin::PublicCoin pubCoin (params);
86+ if (!TxOutToPublicCoin (prevOut, pubCoin, state))
87+ return error (" %s: cannot get mint from output\n " , __func__);
88+ publicSpend.pubCoin = &pubCoin;
89+
90+ // Check that it opens to the input values
91+ libzerocoin::Commitment commitment (
92+ ¶ms->coinCommitmentGroup , publicSpend.getCoinSerialNumber (), publicSpend.randomness );
93+ if (commitment.getCommitmentValue () != pubCoin.getValue ()){
94+ return error (" %s: commitments values are not equal\n " , __func__);
95+ }
96+ ret = publicSpend;
97+
98+ // Now check that the signature validates with the serial
99+ if (!publicSpend.HasValidSignature ()) {
100+ return error (" %s: signature invalid\n " , __func__);;
101+ }
102+
103+ return true ;
104+ }
0 commit comments