Skip to content

Commit ca86660

Browse files
committed
[Zeroocoin] public coin spend script creation, validation and un/serialization.
1 parent 3d496cc commit ca86660

File tree

7 files changed

+200
-10
lines changed

7 files changed

+200
-10
lines changed

src/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ BITCOIN_CORE_H = \
185185
zpiv/zerocoin.h \
186186
zpiv/zpivtracker.h \
187187
zpiv/zpivwallet.h \
188+
zpiv/zpivmodule.h \
188189
genwit.h \
189190
concurrentqueue.h \
190191
lightzpivthread.h \
@@ -281,6 +282,7 @@ libbitcoin_wallet_a_SOURCES = \
281282
zpiv/zpivtracker.cpp \
282283
stakeinput.cpp \
283284
genwit.cpp \
285+
zpiv/zpivmodule.cpp \
284286
lightzpivthread.cpp \
285287
$(BITCOIN_CORE_H)
286288

src/libzerocoin/AccumulatorProofOfKnowledge.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ namespace libzerocoin {
2424
*/
2525
class AccumulatorProofOfKnowledge {
2626
public:
27+
AccumulatorProofOfKnowledge(){};
2728
AccumulatorProofOfKnowledge(const AccumulatorAndProofParams* p);
2829

2930
/** Generates a proof that a commitment to a coin c was accumulated

src/libzerocoin/CoinSpend.h

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ class CoinSpend
3838
{
3939
public:
4040

41+
CoinSpend(){};
42+
4143
//! \param paramsV1 - if this is a V1 zerocoin, then use params that existed with initial modulus, ignored otherwise
4244
//! \param paramsV2 - params that begin when V2 zerocoins begin on the PIVX network
4345
//! \param strm - a serialized CoinSpend
@@ -119,10 +121,10 @@ class CoinSpend
119121

120122
static std::vector<unsigned char> ParseSerial(CDataStream& s);
121123

122-
const uint256 signatureHash() const;
124+
virtual const uint256 signatureHash() const;
123125
bool Verify(const Accumulator& a, bool verifyParams = true) const;
124-
bool HasValidSerial(ZerocoinParams* params) const;
125-
bool HasValidSignature() const;
126+
virtual bool HasValidSerial(ZerocoinParams* params) const;
127+
virtual bool HasValidSignature() const;
126128
CBigNum CalculateValidSerial(ZerocoinParams* params);
127129
std::string ToString() const;
128130

@@ -150,22 +152,24 @@ class CoinSpend
150152
}
151153
}
152154

153-
private:
155+
protected:
154156
CoinDenomination denomination;
157+
CBigNum coinSerialNumber;
158+
uint8_t version;
159+
//As of version 2
160+
CPubKey pubkey;
161+
std::vector<unsigned char> vchSig;
162+
SpendType spendType;
163+
164+
private:
155165
uint32_t accChecksum;
156166
uint256 ptxHash;
157167
CBigNum accCommitmentToCoinValue;
158168
CBigNum serialCommitmentToCoinValue;
159-
CBigNum coinSerialNumber;
160169
AccumulatorProofOfKnowledge accumulatorPoK;
161170
SerialNumberSignatureOfKnowledge serialNumberSoK;
162171
CommitmentProofOfKnowledge commitmentPoK;
163-
uint8_t version;
164172

165-
//As of version 2
166-
CPubKey pubkey;
167-
std::vector<unsigned char> vchSig;
168-
SpendType spendType;
169173
};
170174

171175
} /* namespace libzerocoin */

src/libzerocoin/Commitment.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class Commitment {
6060
*/
6161
class CommitmentProofOfKnowledge {
6262
public:
63+
CommitmentProofOfKnowledge(){};
6364
CommitmentProofOfKnowledge(const IntegerGroupParams* ap, const IntegerGroupParams* bp);
6465
/** Generates a proof that two commitments, a and b, open to the same value.
6566
*

src/libzerocoin/SerialNumberSignatureOfKnowledge.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ namespace libzerocoin {
3434
*/
3535
class SerialNumberSignatureOfKnowledge {
3636
public:
37+
SerialNumberSignatureOfKnowledge(){};
3738
SerialNumberSignatureOfKnowledge(const ZerocoinParams* p);
3839
/** Creates a Signature of knowledge object that a commitment to a coin contains a coin with serial number x
3940
*

src/zpiv/zpivmodule.cpp

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
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+
&params->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+
}

src/zpiv/zpivmodule.h

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
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+
#ifndef PIVX_ZPIVMODULE_H
6+
#define PIVX_ZPIVMODULE_H
7+
8+
#include "libzerocoin/bignum.h"
9+
#include "libzerocoin/Denominations.h"
10+
#include "libzerocoin/CoinSpend.h"
11+
#include "libzerocoin/Coin.h"
12+
#include "libzerocoin/SpendType.h"
13+
#include "primitives/transaction.h"
14+
#include "script/script.h"
15+
#include "main.h"
16+
#include "serialize.h"
17+
#include "uint256.h"
18+
#include <streams.h>
19+
#include <utilstrencodings.h>
20+
#include "zpiv/zerocoin.h"
21+
22+
class PublicCoinSpend : public libzerocoin::CoinSpend{
23+
public:
24+
25+
PublicCoinSpend(){};
26+
27+
PublicCoinSpend(CBigNum serial, CBigNum randomness, CPubKey pubkey, std::vector<unsigned char> vchSig){
28+
this->coinSerialNumber = serial;
29+
this->randomness = randomness;
30+
this->vchSig = vchSig;
31+
this->pubkey = pubkey;
32+
};
33+
34+
template <typename Stream>
35+
PublicCoinSpend(Stream& strm){
36+
strm >> *this;
37+
}
38+
39+
uint8_t getVersion() const { return libzerocoin::PrivateCoin::PUBKEY_VERSION; }
40+
41+
bool HasValidSerial(libzerocoin::ZerocoinParams* params) const override;
42+
bool HasValidSignature() const override ;
43+
const uint256 signatureHash() const override { return hashTxOut; }
44+
libzerocoin::SpendType getSpendType() const { return libzerocoin::SpendType::SPEND; }
45+
46+
CBigNum randomness;
47+
// prev out values
48+
uint256 txHash = 0;
49+
// hash of the outputs of the txes that spend this coins
50+
uint256 hashTxOut = 0;
51+
unsigned int outputIndex = -1;
52+
libzerocoin::PublicCoin *pubCoin = nullptr;
53+
54+
ADD_SERIALIZE_METHODS;
55+
56+
template <typename Stream, typename Operation>
57+
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
58+
READWRITE(coinSerialNumber);
59+
READWRITE(randomness);
60+
READWRITE(pubkey);
61+
READWRITE(vchSig);
62+
}
63+
};
64+
65+
66+
class ZPIVModule {
67+
68+
public:
69+
ZPIVModule(){}
70+
71+
bool createInput(CTxIn &in, CZerocoinMint mint, uint256 hashTxOut);
72+
PublicCoinSpend parseCoinSpend(const CTxIn &in, const CTransaction& tx);
73+
bool validateInput(const CTxIn &in, const CTxOut &prevOut, const CTransaction& tx, PublicCoinSpend& ret);
74+
};
75+
76+
77+
#endif //PIVX_ZPIVMODULE_H

0 commit comments

Comments
 (0)