Skip to content

Commit

Permalink
Staking zPiv.
Browse files Browse the repository at this point in the history
  • Loading branch information
presstab authored and Fuzzbawls committed Mar 31, 2018
1 parent aedf80b commit 3b778f5
Show file tree
Hide file tree
Showing 41 changed files with 1,460 additions and 740 deletions.
4 changes: 4 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ BITCOIN_CORE_H = \
base58.h \
bip38.h \
bloom.h \
blocksignature.h \
chain.h \
chainparams.h \
chainparamsbase.h \
Expand Down Expand Up @@ -165,6 +166,7 @@ BITCOIN_CORE_H = \
serialize.h \
spork.h \
sporkdb.h \
stakeinput.h \
streams.h \
sync.h \
threadsafety.h \
Expand Down Expand Up @@ -203,6 +205,7 @@ libbitcoin_server_a_SOURCES = \
addrman.cpp \
alert.cpp \
bloom.cpp \
blocksignature.cpp \
chain.cpp \
checkpoints.cpp \
httprpc.cpp \
Expand Down Expand Up @@ -268,6 +271,7 @@ libbitcoin_wallet_a_SOURCES = \
wallet.cpp \
wallet_ismine.cpp \
walletdb.cpp \
stakeinput.cpp \
$(BITCOIN_CORE_H)

# crypto primitives library
Expand Down
28 changes: 27 additions & 1 deletion src/accumulators.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,30 @@ uint32_t GetChecksum(const CBigNum &bnValue)
return hash.Get32();
}

// Find the first occurance of a certain accumulator checksum. Return 0 if not found.
int GetChecksumHeight(uint32_t nChecksum, CoinDenomination denomination)
{
CBlockIndex* pindex = chainActive[Params().Zerocoin_StartHeight()];
if (!pindex)
return 0;

//Search through blocks to find the checksum
while (pindex) {
if (ParseChecksum(pindex->nAccumulatorCheckpoint, denomination) == nChecksum)
return pindex->nHeight;

//Skip forward in groups of 10 blocks since checkpoints only change every 10 blocks
if (pindex->nHeight % 10 == 0) {
pindex = chainActive[pindex->nHeight + 10];
continue;
}

pindex = chainActive.Next(pindex);
}

return 0;
}

bool GetAccumulatorValueFromChecksum(uint32_t nChecksum, bool fMemoryOnly, CBigNum& bnAccValue)
{
if (mapAccumulatorValues.count(nChecksum)) {
Expand Down Expand Up @@ -296,7 +320,7 @@ bool ValidateAccumulatorCheckpoint(const CBlock& block, CBlockIndex* pindex, Acc
return true;
}

bool GenerateAccumulatorWitness(const PublicCoin &coin, Accumulator& accumulator, AccumulatorWitness& witness, int nSecurityLevel, int& nMintsAdded, string& strError)
bool GenerateAccumulatorWitness(const PublicCoin &coin, Accumulator& accumulator, AccumulatorWitness& witness, int nSecurityLevel, int& nMintsAdded, string& strError, CBlockIndex* pindexCheckpoint)
{
uint256 txid;
if (!zerocoinDB->ReadCoinMint(coin.getValue(), txid)) {
Expand Down Expand Up @@ -374,6 +398,8 @@ bool GenerateAccumulatorWitness(const PublicCoin &coin, Accumulator& accumulator
int nChainHeight = chainActive.Height();
int nHeightStop = nChainHeight % 10;
nHeightStop = nChainHeight - nHeightStop - 20; // at least two checkpoints deep
if (pindexCheckpoint)
nHeightStop = pindexCheckpoint->nHeight -10;
int nCheckpointsAdded = 0;
nMintsAdded = 0;
while (pindex->nHeight < nHeightStop + 1) {
Expand Down
5 changes: 4 additions & 1 deletion src/accumulators.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
#include "chain.h"
#include "uint256.h"

bool GenerateAccumulatorWitness(const libzerocoin::PublicCoin &coin, libzerocoin::Accumulator& accumulator, libzerocoin::AccumulatorWitness& witness, int nSecurityLevel, int& nMintsAdded, std::string& strError);
class CBlockIndex;

bool GenerateAccumulatorWitness(const libzerocoin::PublicCoin &coin, libzerocoin::Accumulator& accumulator, libzerocoin::AccumulatorWitness& witness, int nSecurityLevel, int& nMintsAdded, std::string& strError, CBlockIndex* pindexCheckpoint = nullptr);
bool GetAccumulatorValueFromDB(uint256 nCheckpoint, libzerocoin::CoinDenomination denom, CBigNum& bnAccValue);
bool GetAccumulatorValueFromChecksum(uint32_t nChecksum, bool fMemoryOnly, CBigNum& bnAccValue);
void AddAccumulatorChecksum(const uint32_t nChecksum, const CBigNum &bnValue, bool fMemoryOnly);
Expand All @@ -23,6 +25,7 @@ bool LoadAccumulatorValuesFromDB(const uint256 nCheckpoint);
bool EraseAccumulatorValues(const uint256& nCheckpointErase, const uint256& nCheckpointPrevious);
uint32_t ParseChecksum(uint256 nChecksum, libzerocoin::CoinDenomination denomination);
uint32_t GetChecksum(const CBigNum &bnValue);
int GetChecksumHeight(uint32_t nChecksum, libzerocoin::CoinDenomination denomination);
bool InvalidCheckpointRange(int nHeight);
bool ValidateAccumulatorCheckpoint(const CBlock& block, CBlockIndex* pindex, AccumulatorMap& mapAccumulators);

Expand Down
87 changes: 87 additions & 0 deletions src/blocksignature.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@

#include "blocksignature.h"
#include "main.h"

bool SignBlockWithKey(CBlock& block, const CKey& key)
{
if (!key.Sign(block.GetHash(), block.vchBlockSig))
return error("%s: failed to sign block hash with key", __func__);

return true;
}

bool GetKeyIDFromUTXO(const CTxOut& txout, CKeyID& keyID)
{
std::vector<valtype> vSolutions;
txnouttype whichType;
if (!Solver(txout.scriptPubKey, whichType, vSolutions))
return false;
if (whichType == TX_PUBKEY) {
keyID = CPubKey(vSolutions[0]).GetID();
} else if (whichType == TX_PUBKEYHASH) {
keyID = CKeyID(uint160(vSolutions[0]));
}

return true;
}

bool SignBlock(CBlock& block, const CKeyStore& keystore)
{
CKeyID keyID;
if (block.IsProofOfWork()) {
bool fFoundID = false;
for (const CTxOut& txout :block.vtx[0].vout) {
if (!GetKeyIDFromUTXO(txout, keyID))
continue;
fFoundID = true;
break;
}
if (!fFoundID)
return error("%s: failed to find key for PoW", __func__);
} else {
if (!GetKeyIDFromUTXO(block.vtx[1].vout[1], keyID))
return error("%s: failed to find key for PoS", __func__);
}

CKey key;
if (!keystore.GetKey(keyID, key))
return error("%s: failed to get key from keystore", __func__);

return SignBlockWithKey(block, key);
}

bool CheckBlockSignature(const CBlock& block)
{
if (block.IsProofOfWork())
return block.vchBlockSig.empty();

if (block.vchBlockSig.empty())
return error("%s: vchBlockSig is empty!", __func__);

/** Each block is signed by the private key of the input that is staked. This can be either zPIV or normal UTXO
* zPIV: Each zPIV has a keypair associated with it. The serial number is a hash of the public key.
* UTXO: The public key that signs must match the public key associated with the first utxo of the coinstake tx.
*/
CPubKey pubkey;
bool fzPIVStake = block.vtx[1].IsZerocoinSpend();
if (fzPIVStake) {
libzerocoin::CoinSpend spend = TxInToZerocoinSpend(block.vtx[1].vin[0]);
pubkey = spend.getPubKey();
LogPrintf("%s spend version=%d\n", __func__, spend.getVersion());
} else {
txnouttype whichType;
std::vector<valtype> vSolutions;
const CTxOut& txout = block.vtx[1].vout[1];
if (!Solver(txout.scriptPubKey, whichType, vSolutions))
return false;
if (whichType == TX_PUBKEY || whichType == TX_PUBKEYHASH) {
valtype& vchPubKey = vSolutions[0];
pubkey = CPubKey(vchPubKey);
}
}

if (!pubkey.IsValid())
return error("%s: invalid pubkey %s", __func__, pubkey.GetHex());

return pubkey.Verify(block.GetHash(), block.vchBlockSig);
}
14 changes: 14 additions & 0 deletions src/blocksignature.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@


#ifndef PIVX_BLOCKSIGNATURE_H
#define PIVX_BLOCKSIGNATURE_H

#include "key.h"
#include "primitives/block.h"
#include "keystore.h"

bool SignBlockWithKey(CBlock& block, const CKey& key);
bool SignBlock(CBlock& block, const CKeyStore& keystore);
bool CheckBlockSignature(const CBlock& block);

#endif //PIVX_BLOCKSIGNATURE_H
4 changes: 4 additions & 0 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ class CMainParams : public CChainParams
nBlockFirstFraudulent = 891737; //First block that bad serials emerged
nBlockLastGoodCheckpoint = 891730; //Last valid accumulator checkpoint
nBlockEnforceInvalidUTXO = 902850; //Start enforcing the invalid UTXO's
nBlockZerocoinV2 = 99999999; //The block that zerocoin v2 becomes active

/**
* Build the genesis block. Note that the output of the genesis coinbase cannot
Expand Down Expand Up @@ -214,6 +215,8 @@ class CMainParams : public CChainParams
nRequiredAccumulation = 1;
nDefaultSecurityLevel = 100; //full security level for accumulators
nZerocoinHeaderVersion = 4; //Block headers must be this version once zerocoin is active
nZerocoinRequiredStakeDepth = 200; //The required confirmations for a zpiv to be stakable

nBudget_Fee_Confirmations = 6; // Number of confirmations for the finalization fee
}

Expand Down Expand Up @@ -258,6 +261,7 @@ class CTestNetParams : public CMainParams
nBlockFirstFraudulent = 9891737; //First block that bad serials emerged
nBlockLastGoodCheckpoint = 9891730; //Last valid accumulator checkpoint
nBlockEnforceInvalidUTXO = 9902850; //Start enforcing the invalid UTXO's
nBlockZerocoinV2 = 99999999; //The block that zerocoin v2 becomes active

//! Modify the testnet genesis block so the timestamp is valid for a later start.
genesis.nTime = 1454124731;
Expand Down
4 changes: 4 additions & 0 deletions src/chainparams.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ class CChainParams
int Zerocoin_RequiredAccumulation() const { return nRequiredAccumulation; }
int Zerocoin_DefaultSpendSecurity() const { return nDefaultSecurityLevel; }
int Zerocoin_HeaderVersion() const { return nZerocoinHeaderVersion; }
int Zerocoin_RequiredStakeDepth() const { return nZerocoinRequiredStakeDepth; }

/** Height or Time Based Activations **/
int ModifierUpgradeBlock() const { return nModifierUpdateBlock; }
Expand All @@ -116,6 +117,7 @@ class CChainParams
int Zerocoin_Block_LastGoodCheckpoint() const { return nBlockLastGoodCheckpoint; }
int Zerocoin_StartTime() const { return nZerocoinStartTime; }
int Block_Enforce_Invalid() const { return nBlockEnforceInvalidUTXO; }
int Zerocoin_Block_V2_Start() const { return nBlockZerocoinV2; }

protected:
CChainParams() {}
Expand Down Expand Up @@ -167,12 +169,14 @@ class CChainParams
int64_t nBudget_Fee_Confirmations;
int nZerocoinStartHeight;
int nZerocoinStartTime;
int nZerocoinRequiredStakeDepth;

int nBlockEnforceSerialRange;
int nBlockRecalculateAccumulators;
int nBlockFirstFraudulent;
int nBlockLastGoodCheckpoint;
int nBlockEnforceInvalidUTXO;
int nBlockZerocoinV2;
};

/**
Expand Down
Loading

0 comments on commit 3b778f5

Please sign in to comment.