Skip to content

Commit

Permalink
[Wallet] public coin spend creation connected + first mem pool valida…
Browse files Browse the repository at this point in the history
…tion.

[Zerocoin] public coin spend improvements.

[Zerocoin] publicCoinSpend validations connected to the accept txes flow.

[Zerocoin] public spends not checked as regular inputs.

[Zerocoin] publicCoinSpend validation as regular spends.

non good solution for the coinSpend pointer inheritance issue but at least working

[Zerocoin] ParseZerocoinPublicSpend moved into zpivmodule file.

cleanup unused field.
  • Loading branch information
furszy committed May 23, 2019
1 parent 1db7c59 commit 0e8d0f9
Show file tree
Hide file tree
Showing 18 changed files with 486 additions and 212 deletions.
13 changes: 8 additions & 5 deletions src/libzerocoin/CoinSpend.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,12 @@ class CoinSpend
static std::vector<unsigned char> ParseSerial(CDataStream& s);

virtual const uint256 signatureHash() const;
bool Verify(const Accumulator& a, bool verifyParams = true) const;
virtual bool HasValidSerial(ZerocoinParams* params) const;
virtual bool HasValidSignature() const;
virtual bool Verify(const Accumulator& a, bool verifyParams = true) const;
bool HasValidSerial(ZerocoinParams* params) const;
bool HasValidSignature() const;
void setTxOutHash(uint256 txOutHash) { this->ptxHash = txOutHash; };
void setDenom(libzerocoin::CoinDenomination denom) { this->denomination = denom; }

CBigNum CalculateValidSerial(ZerocoinParams* params);
std::string ToString() const;

Expand Down Expand Up @@ -153,17 +156,17 @@ class CoinSpend
}

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

private:
uint32_t accChecksum;
uint256 ptxHash;
CBigNum accCommitmentToCoinValue;
CBigNum serialCommitmentToCoinValue;
AccumulatorProofOfKnowledge accumulatorPoK;
Expand Down
258 changes: 189 additions & 69 deletions src/main.cpp

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "primitives/block.h"
#include "primitives/transaction.h"
#include "zpiv/zerocoin.h"
#include "zpiv/zpivmodule.h"
#include "script/script.h"
#include "script/sigcache.h"
#include "script/standard.h"
Expand Down Expand Up @@ -235,6 +236,8 @@ bool IsInitialBlockDownload();
std::string GetWarnings(std::string strFor);
/** Retrieve a transaction (from memory pool, or from disk, if possible) */
bool GetTransaction(const uint256& hash, CTransaction& tx, uint256& hashBlock, bool fAllowSlow = false, CBlockIndex* blockIndex = nullptr);
/** Retrieve an output (from memory pool, or from disk, if possible) */
bool GetOutput(const uint256& hash, unsigned int index, CValidationState& state, CTxOut& out);
/** Find the best known block, and make it the tip of the block chain */

// ***TODO***
Expand Down Expand Up @@ -355,8 +358,8 @@ void UpdateCoins(const CTransaction& tx, CValidationState& state, CCoinsViewCach
bool CheckTransaction(const CTransaction& tx, bool fZerocoinActive, bool fRejectBadUTXO, CValidationState& state, bool fFakeSerialAttack = false);
bool CheckZerocoinMint(const uint256& txHash, const CTxOut& txout, CValidationState& state, bool fCheckOnly = false);
bool CheckZerocoinSpend(const CTransaction& tx, bool fVerifySignature, CValidationState& state, bool fFakeSerialAttack = false);
bool ContextualCheckZerocoinSpend(const CTransaction& tx, const libzerocoin::CoinSpend& spend, CBlockIndex* pindex, const uint256& hashBlock);
bool ContextualCheckZerocoinSpendNoSerialCheck(const CTransaction& tx, const libzerocoin::CoinSpend& spend, CBlockIndex* pindex, const uint256& hashBlock);
bool ContextualCheckZerocoinSpend(const CTransaction& tx, const libzerocoin::CoinSpend* spend, CBlockIndex* pindex, const uint256& hashBlock);
bool ContextualCheckZerocoinSpendNoSerialCheck(const CTransaction& tx, const libzerocoin::CoinSpend* spend, CBlockIndex* pindex, const uint256& hashBlock);
bool IsTransactionInChain(const uint256& txId, int& nHeightTx, CTransaction& tx);
bool IsTransactionInChain(const uint256& txId, int& nHeightTx);
bool IsBlockHashInChain(const uint256& hashBlock);
Expand All @@ -370,7 +373,6 @@ bool ReindexAccumulators(list<uint256>& listMissingCheckpoints, string& strError
// Fake Serial attack Range
bool isBlockBetweenFakeSerialAttackRange(int nHeight);


/**
* Check if transaction will be final in the next block to be created.
*
Expand Down
28 changes: 21 additions & 7 deletions src/miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -371,18 +371,32 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet,

bool fDoubleSerial = false;
for (const CTxIn& txIn : tx.vin) {
if (txIn.IsZerocoinSpend()) {
libzerocoin::CoinSpend spend = TxInToZerocoinSpend(txIn);
bool fUseV1Params = libzerocoin::ExtractVersionFromSerial(spend.getCoinSerialNumber()) < libzerocoin::PrivateCoin::PUBKEY_VERSION;
if (!spend.HasValidSerial(Params().Zerocoin_Params(fUseV1Params)))
bool isPublicSpend = txIn.scriptSig.IsZerocoinPublicSpend();
if (txIn.IsZerocoinSpend() || isPublicSpend) {
libzerocoin::CoinSpend* spend;
if (isPublicSpend) {
libzerocoin::ZerocoinParams* params = Params().Zerocoin_Params(false);
PublicCoinSpend publicSpend(params);
CValidationState state;
if (!ZPIVModule::ParseZerocoinPublicSpend(txIn, tx, state, publicSpend)){
throw std::runtime_error("Invalid public spend parse");
}
spend = &publicSpend;
} else {
libzerocoin::CoinSpend spendObj = TxInToZerocoinSpend(txIn);
spend = &spendObj;
}

bool fUseV1Params = libzerocoin::ExtractVersionFromSerial(spend->getCoinSerialNumber()) < libzerocoin::PrivateCoin::PUBKEY_VERSION;
if (!spend->HasValidSerial(Params().Zerocoin_Params(fUseV1Params)))
fDoubleSerial = true;
if (count(vBlockSerials.begin(), vBlockSerials.end(), spend.getCoinSerialNumber()))
if (count(vBlockSerials.begin(), vBlockSerials.end(), spend->getCoinSerialNumber()))
fDoubleSerial = true;
if (count(vTxSerials.begin(), vTxSerials.end(), spend.getCoinSerialNumber()))
if (count(vTxSerials.begin(), vTxSerials.end(), spend->getCoinSerialNumber()))
fDoubleSerial = true;
if (fDoubleSerial)
break;
vTxSerials.emplace_back(spend.getCoinSerialNumber());
vTxSerials.emplace_back(spend->getCoinSerialNumber());
}
}
//This zPIV serial has already been included in the block, do not add this tx.
Expand Down
7 changes: 5 additions & 2 deletions src/primitives/transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ CTransaction& CTransaction::operator=(const CTransaction &tx) {
bool CTransaction::HasZerocoinSpendInputs() const
{
for (const CTxIn& txin: vin) {
if (txin.IsZerocoinSpend())
if (txin.IsZerocoinSpend() || txin.scriptSig.IsZerocoinPublicSpend())
return true;
}
return false;
Expand Down Expand Up @@ -242,9 +242,12 @@ std::list<COutPoint> CTransaction::GetOutPoints() const

CAmount CTransaction::GetZerocoinSpent() const
{
if(!IsZerocoinSpend() && !IsZerocoinPublicSpend())
return 0;

CAmount nValueOut = 0;
for (const CTxIn& txin : vin) {
if(!txin.IsZerocoinSpend())
if(!txin.IsZerocoinSpend() && !txin.scriptSig.IsZerocoinPublicSpend())
continue;

nValueOut += txin.nSequence * COIN;
Expand Down
11 changes: 11 additions & 0 deletions src/primitives/transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,17 @@ class CTransaction
return HasZerocoinSpendInputs() || HasZerocoinMintOutputs();
}

// TODO: Move this to the cpp and add it to the HasZerocoinSpendinputs method
bool IsZerocoinPublicSpend() const
{
// The wallet only allows publicSpend inputs in the same tx and not a combination between piv and zpiv
for(const CTxIn& txin : vin) {
if (txin.scriptSig.IsZerocoinPublicSpend())
return true;
}
return false;
}

CAmount GetZerocoinMinted() const;
CAmount GetZerocoinSpent() const;
int GetZerocoinMintCount() const;
Expand Down
16 changes: 14 additions & 2 deletions src/qt/transactionrecord.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
#include "timedata.h"
#include "wallet/wallet.h"
#include "zpivchain.h"
#include "main.h"

#include <iostream>
#include <stdint.h>

/* Return positive answer if transaction should be shown in list.
Expand Down Expand Up @@ -44,8 +46,18 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet*

if (wtx.HasZerocoinSpendInputs()) {
// a zerocoin spend that was created by this wallet
libzerocoin::CoinSpend zcspend = TxInToZerocoinSpend(wtx.vin[0]);
fZSpendFromMe = wallet->IsMyZerocoinSpend(zcspend.getCoinSerialNumber());
if (wtx.IsZerocoinPublicSpend()) {
libzerocoin::ZerocoinParams* params = Params().Zerocoin_Params(false);
PublicCoinSpend publicSpend(params);
CValidationState state;
if (!ZPIVModule::ParseZerocoinPublicSpend(wtx.vin[0], wtx, state, publicSpend)){
throw std::runtime_error("Error parsing zc public spend");
}
fZSpendFromMe = wallet->IsMyZerocoinSpend(publicSpend.getCoinSerialNumber());
} else {
libzerocoin::CoinSpend zcspend = TxInToZerocoinSpend(wtx.vin[0]);
fZSpendFromMe = wallet->IsMyZerocoinSpend(zcspend.getCoinSerialNumber());
}
}

if (wtx.IsCoinStake()) {
Expand Down
3 changes: 2 additions & 1 deletion src/rpc/blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1051,7 +1051,7 @@ UniValue getfeeinfo(const UniValue& params, bool fHelp)
continue;

for (unsigned int j = 0; j < tx.vin.size(); j++) {
if (tx.vin[j].IsZerocoinSpend()) {
if (tx.vin[j].IsZerocoinSpend() || tx.vin[j].scriptSig.IsZerocoinPublicSpend()) {
nValueIn += tx.vin[j].nSequence * COIN;
continue;
}
Expand Down Expand Up @@ -1446,6 +1446,7 @@ UniValue getserials(const UniValue& params, bool fHelp) {
}
// loop through each input
for (const CTxIn& txin : tx.vin) {
// TODO: Add public coin spend parse here..
if (txin.IsZerocoinSpend()) {
libzerocoin::CoinSpend spend = TxInToZerocoinSpend(txin);
std::string serial_str = spend.getCoinSerialNumber().ToString(16);
Expand Down
9 changes: 9 additions & 0 deletions src/script/script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ const char* GetOpName(opcodetype opcode)
// zerocoin
case OP_ZEROCOINMINT : return "OP_ZEROCOINMINT";
case OP_ZEROCOINSPEND : return "OP_ZEROCOINSPEND";
case OP_ZEROCOINPUBLICSPEND : return "OP_ZEROCOINPUBLICSPEND";

case OP_INVALIDOPCODE : return "OP_INVALIDOPCODE";

Expand Down Expand Up @@ -263,6 +264,14 @@ bool CScript::IsZerocoinSpend() const
return StartsWithOpcode(OP_ZEROCOINSPEND);
}

bool CScript::IsZerocoinPublicSpend() const
{
if (this->empty())
return false;

return (this->at(0) == OP_ZEROCOINPUBLICSPEND);
}

bool CScript::IsPushOnly(const_iterator pc) const
{
while (pc < end())
Expand Down
2 changes: 2 additions & 0 deletions src/script/script.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ enum opcodetype
// zerocoin
OP_ZEROCOINMINT = 0xc1,
OP_ZEROCOINSPEND = 0xc2,
OP_ZEROCOINPUBLICSPEND = 0xc3,

// template matching params
OP_SMALLINTEGER = 0xfa,
Expand Down Expand Up @@ -601,6 +602,7 @@ class CScript : public std::vector<unsigned char>
bool StartsWithOpcode(const opcodetype opcode) const;
bool IsZerocoinMint() const;
bool IsZerocoinSpend() const;
bool IsZerocoinPublicSpend() const;

/** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */
bool IsPushOnly(const_iterator pc) const;
Expand Down
8 changes: 3 additions & 5 deletions src/test/zerocoin_transactions_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ BOOST_AUTO_TEST_CASE(zerocoin_public_spend_test)
ZerocoinParams *ZCParams = Params().Zerocoin_Params(false);
(void)ZCParams;

ZPIVModule zpivModule;

PrivateCoin privCoin(ZCParams, libzerocoin::CoinDenomination::ZQ_ONE, true);
const CPrivKey privKey = privCoin.getPrivKey();

Expand Down Expand Up @@ -95,17 +93,17 @@ BOOST_AUTO_TEST_CASE(zerocoin_public_spend_test)
tx.vout[0].scriptPubKey = GetScriptForDestination(CBitcoinAddress("D9Ti4LEhF1n6dR2hGd2SyNADD51AVgva6q").Get());

CTxIn in;
if (!zpivModule.createInput(in, mint, tx.GetHash())){
if (!ZPIVModule::createInput(in, mint, tx.GetHash())){
BOOST_CHECK_MESSAGE(false, "Failed to create zc input");
}

PublicCoinSpend publicSpend(ZCParams);
if (!zpivModule.validateInput(in, out, tx, publicSpend)){
if (!ZPIVModule::validateInput(in, out, tx, publicSpend)){
BOOST_CHECK_MESSAGE(false, "Failed to validate zc input");
}

PublicCoinSpend publicSpendTest(ZCParams);
BOOST_CHECK_MESSAGE(zpivModule.parseCoinSpend(in, tx, out, publicSpendTest), "Failed to parse public spend");
BOOST_CHECK_MESSAGE(ZPIVModule::parseCoinSpend(in, tx, out, publicSpendTest), "Failed to parse public spend");
libzerocoin::CoinSpend *spend = &publicSpendTest;

BOOST_CHECK_MESSAGE(publicSpendTest.HasValidSignature(), "Failed to validate public spend signature");
Expand Down
4 changes: 2 additions & 2 deletions src/txmempool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -565,11 +565,11 @@ void CTxMemPool::check(const CCoinsViewCache* pcoins) const
fDependsWait = true;
} else {
const CCoins* coins = pcoins->AccessCoins(txin.prevout.hash);
if(!txin.IsZerocoinSpend())
if(!txin.IsZerocoinSpend() && !txin.scriptSig.IsZerocoinPublicSpend())
assert(coins && coins->IsAvailable(txin.prevout.n));
}
// Check whether its inputs are marked in mapNextTx.
if(!txin.IsZerocoinSpend()) {
if(!txin.IsZerocoinSpend() && !txin.scriptSig.IsZerocoinPublicSpend()) {
std::map<COutPoint, CInPoint>::const_iterator it3 = mapNextTx.find(txin.prevout);
assert(it3 != mapNextTx.end());
assert(it3->second.ptx == &tx);
Expand Down
Loading

0 comments on commit 0e8d0f9

Please sign in to comment.