Refactor ZC-specific staking functionality.
In preparation for defining a RingCTStakeInput type, move more
zerocoin-specific stuff behind a CStakeInput interface.
MODIFY
src/veil/proofofstake/kernel.cpp
src/veil/proofofstake/kernel.cpp
#include "util/system.h"
#include "stakeinput.h"
#include "veil/zerocoin/zchain.h"
-#include "libzerocoin/bignum.h"
#include <versionbits.h>
using namespace std;
@@ -47,21 +46,6 @@ bool CheckStake(const CDataStream& ssUniqueID, CAmount nValueIn, const uint64_t
}
-//Sets nValueIn with the weighted amount given a certain zerocoin denomination
-void WeightStake(CAmount& nValueIn, const libzerocoin::CoinDenomination denom)
-{
- if (denom == libzerocoin::CoinDenomination::ZQ_ONE_HUNDRED) {
- //10% reduction
- nValueIn = (nValueIn * 90) / 100;
- } else if (denom == libzerocoin::CoinDenomination::ZQ_ONE_THOUSAND) {
- //20% reduction
- nValueIn = (nValueIn * 80) / 100;
- } else if (denom == libzerocoin::CoinDenomination::ZQ_TEN_THOUSAND) {
- //30% reduction
- nValueIn = (nValueIn * 70) / 100;
- }
-}
-
std::set<uint256> setFoundStakes;
bool Stake(CStakeInput* stakeInput, unsigned int nBits, unsigned int nTimeBlockFrom, unsigned int& nTimeTx, const CBlockIndex* pindexBest, uint256& hashProofOfStake, bool fWeightStake)
{
@@ -84,11 +68,8 @@ bool Stake(CStakeInput* stakeInput, unsigned int nBits, unsigned int nTimeBlockF
int64_t nMaxTime = (int)GetAdjustedTime() + MAX_FUTURE_BLOCK_TIME - 40;
CDataStream ssUniqueID = stakeInput->GetUniqueness();
- CAmount nValueIn = stakeInput->GetValue();
-
- //Adjust stake weights to larger denoms
- if (fWeightStake)
- WeightStake(nValueIn, stakeInput->GetDenomination());
+ // Adjust stake weights
+ CAmount nValueIn = fWeightStake ? stakeInput->GetWeight() : stakeInput->GetValue();
int nBestHeight = pindexBest->nHeight;
uint256 hashBestBlock = pindexBest->GetBlockHash();
@@ -167,11 +148,12 @@ bool CheckProofOfStake(CBlockIndex* pindexCheck, const CTransactionRef txRef, co
unsigned int nBlockFromTime = blockprev.nTime;
unsigned int nTxTime = nTimeBlock;
- CAmount nValue = stake->GetValue();
// Enforce VIP-1 after it was activated
- if ((int)nTxTime > Params().EnforceWeightReductionTime())
- WeightStake(nValue, stake->GetDenomination());
+ CAmount nValue = (int)nTxTime > Params().EnforceWeightReductionTime()
+ ? stake->GetWeight()
+ : stake->GetValue();
+
if (!CheckStake(stake->GetUniqueness(), nValue, nStakeModifier, ArithToUint256(bnTargetPerCoinDay), nBlockFromTime,
nTxTime, hashProofOfStake)) {

MODIFY
src/veil/proofofstake/stakeinput.cpp
src/veil/proofofstake/stakeinput.cpp
@@ -166,6 +166,21 @@ CAmount ZerocoinStake::GetValue()
return denom * COIN;
}
+CAmount ZerocoinStake::GetWeight()
+{
+ if (denom == libzerocoin::CoinDenomination::ZQ_ONE_HUNDRED) {
+ //10% reduction
+ return (denom * COIN * 9) / 10;
+ } else if (denom == libzerocoin::CoinDenomination::ZQ_ONE_THOUSAND) {
+ //20% reduction
+ return (denom * COIN * 8) / 10;
+ } else if (denom == libzerocoin::CoinDenomination::ZQ_TEN_THOUSAND) {
+ //30% reduction
+ return (denom * COIN * 7) / 10;
+ }
+ return denom * COIN;
+}
+
int ZerocoinStake::HeightToModifierHeight(int nHeight)
{
//Nearest multiple of KernelModulus that is over KernelModulus bocks deep in the chain
@@ -277,6 +292,13 @@ bool ZerocoinStake::CreateTxOuts(CWallet* pwallet, std::vector<CTxOut>& vout, CA
#endif
}
+bool ZerocoinStake::CompleteTx(CWallet* pwallet, CMutableTransaction& txNew)
+{
+ if (!MarkSpent(pwallet, txNew.GetHash()))
+ return error("%s: failed to mark mint as used\n", __func__);
+ return true;
+}
+
bool ZerocoinStake::GetTxFrom(CTransaction& tx)
{
return false;

MODIFY
src/veil/proofofstake/stakeinput.h
src/veil/proofofstake/stakeinput.h
// Copyright (c) 2017-2019 The PIVX developers
-// Copyright (c) 2019 The Veil developers
+// Copyright (c) 2019-2022 The Veil developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -25,14 +25,17 @@ protected:
public:
virtual ~CStakeInput(){};
virtual CBlockIndex* GetIndexFrom() = 0;
- virtual bool CreateTxIn(CWallet* pwallet, CTxIn& txIn, uint256 hashTxOut = uint256()) = 0;
virtual bool GetTxFrom(CTransaction& tx) = 0;
virtual CAmount GetValue() = 0;
- virtual bool CreateTxOuts(CWallet* pwallet, std::vector<CTxOut>& vout, CAmount nTotal) = 0;
+ virtual CAmount GetWeight() = 0;
virtual bool GetModifier(uint64_t& nStakeModifier, const CBlockIndex* pindexChainPrev) = 0;
virtual bool IsZerocoins() = 0;
virtual CDataStream GetUniqueness() = 0;
libzerocoin::CoinDenomination GetDenomination() {return denom;};
+
+ virtual bool CreateTxIn(CWallet* pwallet, CTxIn& txIn, uint256 hashTxOut = uint256()) = 0;
+ virtual bool CreateTxOuts(CWallet* pwallet, std::vector<CTxOut>& vout, CAmount nTotal) = 0;
+ virtual bool CompleteTx(CWallet* pwallet, CMutableTransaction& txNew) = 0;
};
@@ -60,12 +63,15 @@ public:
CBlockIndex* GetIndexFrom() override;
bool GetTxFrom(CTransaction& tx) override;
CAmount GetValue() override;
+ CAmount GetWeight() override;
bool GetModifier(uint64_t& nStakeModifier, const CBlockIndex* pindexChainPrev) override;
CDataStream GetUniqueness() override;
bool CreateTxIn(CWallet* pwallet, CTxIn& txIn, uint256 hashTxOut = uint256()) override;
bool CreateTxOuts(CWallet* pwallet, std::vector<CTxOut>& vout, CAmount nTotal) override;
- bool MarkSpent(CWallet* pwallet, const uint256& txid);
+ bool CompleteTx(CWallet* pwallet, CMutableTransaction& txNew) override;
bool IsZerocoins() override { return true; }
+
+ bool MarkSpent(CWallet* pwallet, const uint256& txid);
int GetChecksumHeightFromMint();
int GetChecksumHeightFromSpend();
uint256 GetChecksum();

MODIFY
src/wallet/wallet.cpp
src/wallet/wallet.cpp
@@ -3884,10 +3884,10 @@ bool CWallet::CreateCoinStake(const CBlockIndex* pindexBest, unsigned int nBits,
if (GetAdjustedTime() - chainActive.Tip()->GetBlockTime() < 1)
UninterruptibleSleep(std::chrono::milliseconds{2500});
- CAmount nCredit = 0;
CScript scriptPubKeyKernel;
bool fKernelFound = false;
for (std::unique_ptr<ZerocoinStake>& stakeInput : listInputs) {
+ CAmount nCredit = 0;
// Make sure the wallet is unlocked and shutdown hasn't been requested
if (IsLocked() || ShutdownRequested())
return false;
@@ -3964,16 +3964,14 @@ bool CWallet::CreateCoinStake(const CBlockIndex* pindexBest, unsigned int nBits,
LogPrintf("%s : failed to create TxIn\n", __func__);
txNew.vin.clear();
txNew.vpout.clear();
- nCredit = 0;
continue;
}
}
txNew.vin.emplace_back(in);
//Mark mints as spent
- auto* z = (ZerocoinStake*)stakeInput.get();
- if (!z->MarkSpent(this, txNew.GetHash()))
- return error("%s: failed to mark mint as used\n", __func__);
+ if (!stakeInput->CompleteTx(this, txNew))
+ return false;
fKernelFound = true;
break;

Refactor ZC-specific staking functionality.

In preparation for defining a RingCTStakeInput type, move more
zerocoin-specific stuff behind a CStakeInput interface.