Skip to content

Commit

Permalink
[Zeroocoin] public coin spend script creation, validation and un/seri…
Browse files Browse the repository at this point in the history
…alization.
  • Loading branch information
furszy committed May 23, 2019
1 parent 3d496cc commit ca86660
Show file tree
Hide file tree
Showing 7 changed files with 200 additions and 10 deletions.
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ BITCOIN_CORE_H = \
zpiv/zerocoin.h \
zpiv/zpivtracker.h \
zpiv/zpivwallet.h \
zpiv/zpivmodule.h \
genwit.h \
concurrentqueue.h \
lightzpivthread.h \
Expand Down Expand Up @@ -281,6 +282,7 @@ libbitcoin_wallet_a_SOURCES = \
zpiv/zpivtracker.cpp \
stakeinput.cpp \
genwit.cpp \
zpiv/zpivmodule.cpp \
lightzpivthread.cpp \
$(BITCOIN_CORE_H)

Expand Down
1 change: 1 addition & 0 deletions src/libzerocoin/AccumulatorProofOfKnowledge.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ namespace libzerocoin {
*/
class AccumulatorProofOfKnowledge {
public:
AccumulatorProofOfKnowledge(){};
AccumulatorProofOfKnowledge(const AccumulatorAndProofParams* p);

/** Generates a proof that a commitment to a coin c was accumulated
Expand Down
24 changes: 14 additions & 10 deletions src/libzerocoin/CoinSpend.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class CoinSpend
{
public:

CoinSpend(){};

//! \param paramsV1 - if this is a V1 zerocoin, then use params that existed with initial modulus, ignored otherwise
//! \param paramsV2 - params that begin when V2 zerocoins begin on the PIVX network
//! \param strm - a serialized CoinSpend
Expand Down Expand Up @@ -119,10 +121,10 @@ class CoinSpend

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

const uint256 signatureHash() const;
virtual const uint256 signatureHash() const;
bool Verify(const Accumulator& a, bool verifyParams = true) const;
bool HasValidSerial(ZerocoinParams* params) const;
bool HasValidSignature() const;
virtual bool HasValidSerial(ZerocoinParams* params) const;
virtual bool HasValidSignature() const;
CBigNum CalculateValidSerial(ZerocoinParams* params);
std::string ToString() const;

Expand Down Expand Up @@ -150,22 +152,24 @@ class CoinSpend
}
}

private:
protected:
CoinDenomination denomination;
CBigNum coinSerialNumber;
uint8_t version;
//As of version 2
CPubKey pubkey;
std::vector<unsigned char> vchSig;
SpendType spendType;

private:
uint32_t accChecksum;
uint256 ptxHash;
CBigNum accCommitmentToCoinValue;
CBigNum serialCommitmentToCoinValue;
CBigNum coinSerialNumber;
AccumulatorProofOfKnowledge accumulatorPoK;
SerialNumberSignatureOfKnowledge serialNumberSoK;
CommitmentProofOfKnowledge commitmentPoK;
uint8_t version;

//As of version 2
CPubKey pubkey;
std::vector<unsigned char> vchSig;
SpendType spendType;
};

} /* namespace libzerocoin */
Expand Down
1 change: 1 addition & 0 deletions src/libzerocoin/Commitment.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class Commitment {
*/
class CommitmentProofOfKnowledge {
public:
CommitmentProofOfKnowledge(){};
CommitmentProofOfKnowledge(const IntegerGroupParams* ap, const IntegerGroupParams* bp);
/** Generates a proof that two commitments, a and b, open to the same value.
*
Expand Down
1 change: 1 addition & 0 deletions src/libzerocoin/SerialNumberSignatureOfKnowledge.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ namespace libzerocoin {
*/
class SerialNumberSignatureOfKnowledge {
public:
SerialNumberSignatureOfKnowledge(){};
SerialNumberSignatureOfKnowledge(const ZerocoinParams* p);
/** Creates a Signature of knowledge object that a commitment to a coin contains a coin with serial number x
*
Expand Down
104 changes: 104 additions & 0 deletions src/zpiv/zpivmodule.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright (c) 2019 The PIVX developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "zpiv/zpivmodule.h"
#include "zpivchain.h"
#include "chainparams.h"
#include "libzerocoin/Commitment.h"
#include "libzerocoin/Coin.h"
#include "hash.h"
#include "iostream"

bool PublicCoinSpend::HasValidSerial(libzerocoin::ZerocoinParams* params) const {
return IsValidSerial(params, coinSerialNumber);
}

bool PublicCoinSpend::HasValidSignature() const {
// Now check that the signature validates with the serial
try {
//V2 serial requires that the signature hash be signed by the public key associated with the serial
uint256 hashedPubkey = Hash(pubkey.begin(), pubkey.end()) >> libzerocoin::PrivateCoin::V2_BITSHIFT;
if (hashedPubkey != libzerocoin::GetAdjustedSerial(coinSerialNumber).getuint256()) {
return error("%s: adjusted serial invalid\n", __func__);
}
} catch(std::range_error &e) {
throw libzerocoin::InvalidSerialException("Serial longer than 256 bits");
}

if (!pubkey.Verify(hashTxOut, vchSig)){
std::cout << "pubkey not verified" << std::endl;
return error("%s: adjusted serial invalid\n", __func__);
}
return true;
}

bool ZPIVModule::createInput(CTxIn &in, CZerocoinMint mint, uint256 hashTxOut){
uint8_t nVersion = mint.GetVersion();
if (nVersion < libzerocoin::PrivateCoin::PUBKEY_VERSION) {
// No v1 serials accepted anymore.
return error("%s: failed to set zPIV privkey mint version=%d\n", __func__, nVersion);
}
CKey key;
if (!mint.GetKeyPair(key))
return error("%s: failed to set zPIV privkey mint version=%d\n", __func__, nVersion);

std::vector<unsigned char> vchSig;
if (!key.Sign(hashTxOut, vchSig))
throw std::runtime_error("ZPIVModule failed to sign hashTxOut\n");

CDataStream ser(SER_NETWORK, PROTOCOL_VERSION);
PublicCoinSpend spend(mint.GetSerialNumber(), mint.GetRandomness(), key.GetPubKey(), vchSig);
ser << spend;

std::vector<unsigned char> data(ser.begin(), ser.end());
CScript scriptSigIn = CScript() << OP_ZEROCOINPUBLICSPEND << data.size();
scriptSigIn.insert(scriptSigIn.end(), data.begin(), data.end());
in = CTxIn(mint.GetTxHash(), mint.GetOutputIndex(), scriptSigIn, mint.GetDenomination());
return true;
}

PublicCoinSpend ZPIVModule::parseCoinSpend(const CTxIn &in, const CTransaction& tx){
if (!in.scriptSig.IsZerocoinPublicSpend()) throw runtime_error("parseCoinSpend() :: input is not a public coin spend");
std::vector<char, zero_after_free_allocator<char> > data;
data.insert(data.end(), in.scriptSig.begin() + 4, in.scriptSig.end());
CDataStream serializedCoinSpend(data, SER_NETWORK, PROTOCOL_VERSION);
PublicCoinSpend spend(serializedCoinSpend);
spend.outputIndex = in.prevout.n;
spend.txHash = in.prevout.hash;
CTransaction txNew;
txNew.vout = tx.vout;
spend.hashTxOut = txNew.GetHash();
return spend;
}

bool ZPIVModule::validateInput(const CTxIn &in, const CTxOut &prevOut, const CTransaction& tx, PublicCoinSpend& ret){
if (!in.scriptSig.IsZerocoinPublicSpend() || !prevOut.scriptPubKey.IsZerocoinMint())
return error("%s: not valid argument/s\n", __func__);

// Now prove that the commitment value opens to the input
PublicCoinSpend publicSpend = parseCoinSpend(in, tx);
libzerocoin::ZerocoinParams* params = Params().Zerocoin_Params(false);

// Check prev out now
CValidationState state;
libzerocoin::PublicCoin pubCoin(params);
if (!TxOutToPublicCoin(prevOut, pubCoin, state))
return error("%s: cannot get mint from output\n", __func__);
publicSpend.pubCoin = &pubCoin;

// Check that it opens to the input values
libzerocoin::Commitment commitment(
&params->coinCommitmentGroup, publicSpend.getCoinSerialNumber(), publicSpend.randomness);
if (commitment.getCommitmentValue() != pubCoin.getValue()){
return error("%s: commitments values are not equal\n", __func__);
}
ret = publicSpend;

// Now check that the signature validates with the serial
if (!publicSpend.HasValidSignature()) {
return error("%s: signature invalid\n", __func__);;
}

return true;
}
77 changes: 77 additions & 0 deletions src/zpiv/zpivmodule.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright (c) 2019 The PIVX developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//
#ifndef PIVX_ZPIVMODULE_H
#define PIVX_ZPIVMODULE_H

#include "libzerocoin/bignum.h"
#include "libzerocoin/Denominations.h"
#include "libzerocoin/CoinSpend.h"
#include "libzerocoin/Coin.h"
#include "libzerocoin/SpendType.h"
#include "primitives/transaction.h"
#include "script/script.h"
#include "main.h"
#include "serialize.h"
#include "uint256.h"
#include <streams.h>
#include <utilstrencodings.h>
#include "zpiv/zerocoin.h"

class PublicCoinSpend : public libzerocoin::CoinSpend{
public:

PublicCoinSpend(){};

PublicCoinSpend(CBigNum serial, CBigNum randomness, CPubKey pubkey, std::vector<unsigned char> vchSig){
this->coinSerialNumber = serial;
this->randomness = randomness;
this->vchSig = vchSig;
this->pubkey = pubkey;
};

template <typename Stream>
PublicCoinSpend(Stream& strm){
strm >> *this;
}

uint8_t getVersion() const { return libzerocoin::PrivateCoin::PUBKEY_VERSION; }

bool HasValidSerial(libzerocoin::ZerocoinParams* params) const override;
bool HasValidSignature() const override ;
const uint256 signatureHash() const override { return hashTxOut; }
libzerocoin::SpendType getSpendType() const { return libzerocoin::SpendType::SPEND; }

CBigNum randomness;
// prev out values
uint256 txHash = 0;
// hash of the outputs of the txes that spend this coins
uint256 hashTxOut = 0;
unsigned int outputIndex = -1;
libzerocoin::PublicCoin *pubCoin = nullptr;

ADD_SERIALIZE_METHODS;

template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(coinSerialNumber);
READWRITE(randomness);
READWRITE(pubkey);
READWRITE(vchSig);
}
};


class ZPIVModule {

public:
ZPIVModule(){}

bool createInput(CTxIn &in, CZerocoinMint mint, uint256 hashTxOut);
PublicCoinSpend parseCoinSpend(const CTxIn &in, const CTransaction& tx);
bool validateInput(const CTxIn &in, const CTxOut &prevOut, const CTransaction& tx, PublicCoinSpend& ret);
};


#endif //PIVX_ZPIVMODULE_H

0 comments on commit ca86660

Please sign in to comment.