PIVX Core  5.6.99
P2P Digital Currency
zpos.cpp
Go to the documentation of this file.
1 // Copyright (c) 2017-2021 The PIVX Core 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/zpos.h"
6 
7 #include "validation.h"
8 #include "zpiv/zpivmodule.h"
9 
10 
11 /*
12  * LEGACY: Kept for IBD in order to verify zerocoin stakes occurred when zPoS was active
13  * Find the first occurrence of a certain accumulator checksum.
14  * Return block index pointer or nullptr if not found
15  */
16 
17 uint32_t ParseAccChecksum(uint256 nCheckpoint, const libzerocoin::CoinDenomination denom)
18 {
19  int pos = std::distance(libzerocoin::zerocoinDenomList.begin(),
21  return (UintToArith256(nCheckpoint) >> (32*((libzerocoin::zerocoinDenomList.size() - 1) - pos))).Get32();
22 }
23 
24 static const CBlockIndex* FindIndexFrom(uint32_t nChecksum, libzerocoin::CoinDenomination denom, int cpHeight)
25 {
26  // First look in the legacy database
27  Optional<int> nHeightChecksum = accumulatorCache ? accumulatorCache->Get(nChecksum, denom) : nullopt;
28  if (nHeightChecksum != nullopt) {
29  return mapBlockIndex.at(chainActive[*nHeightChecksum]->GetBlockHash());
30  }
31 
32  // Not found. This should never happen (during IBD we save the accumulator checksums
33  // in the cache as they are updated, and persist the cache to DB) but better to have a fallback.
34  LogPrintf("WARNING: accumulatorCache corrupt - missing (%d-%d), height=%d\n",
35  nChecksum, libzerocoin::ZerocoinDenominationToInt(denom), cpHeight);
36 
37  // Start at the current checkpoint and go backwards
38  const Consensus::Params& consensus = Params().GetConsensus();
39  int zc_activation = consensus.vUpgrades[Consensus::UPGRADE_ZC].nActivationHeight;
40  // Height limits are ensured by the contextual checks in NewZPivStake
41  assert(cpHeight <= consensus.height_last_ZC_AccumCheckpoint && cpHeight > zc_activation);
42 
43  CBlockIndex* pindex = chainActive[(cpHeight/10)*10 - 10];
44  if (!pindex) return nullptr;
45  while (ParseAccChecksum(pindex->nAccumulatorCheckpoint, denom) == nChecksum && pindex->nHeight > zc_activation) {
46  //Skip backwards in groups of 10 blocks since checkpoints only change every 10 blocks
47  pindex = chainActive[pindex->nHeight - 10];
48  }
49  if (pindex->nHeight > zc_activation) {
50  // Found. update cache.
51  CBlockIndex* pindexFrom = mapBlockIndex.at(chainActive[pindex->nHeight + 10]->GetBlockHash());
52  if (accumulatorCache) accumulatorCache->Set(nChecksum, denom, pindexFrom->nHeight);
53  return pindexFrom;
54  }
55  return nullptr;
56 }
57 
59 {
60  // Construct the stakeinput object
61  if (!txin.IsZerocoinSpend()) {
62  LogPrintf("%s: unable to initialize CLegacyZPivStake from non zc-spend\n", __func__);
63  return nullptr;
64  }
65 
66  // Return immediately if zPOS not enforced
67  const Consensus::Params& consensus = Params().GetConsensus();
68  if (!consensus.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_ZC_V2) ||
69  nHeight >= consensus.height_last_ZC_AccumCheckpoint) {
70  LogPrint(BCLog::LEGACYZC, "%s : zPIV stake block: height %d outside range\n", __func__, nHeight);
71  return nullptr;
72  }
73 
74  // Check spend type
77  LogPrintf("%s : spend is using the wrong SpendType (%d)\n", __func__, (int)spend.getSpendType());
78  return nullptr;
79  }
80 
81  uint32_t _nChecksum = spend.getAccumulatorChecksum();
83  const arith_uint256& nSerial = spend.getCoinSerialNumber().getuint256();
84  const uint256& _hashSerial = Hash(nSerial.begin(), nSerial.end());
85 
86  // The checkpoint needs to be from 200 blocks ago
87  const int cpHeight = nHeight - 1 - consensus.ZC_MinStakeDepth;
88  if (ParseAccChecksum(chainActive[cpHeight]->nAccumulatorCheckpoint, _denom) != _nChecksum) {
89  LogPrint(BCLog::LEGACYZC, "%s : accum. checksum at height %d is wrong.\n", __func__, nHeight);
90  }
91 
92  // Find the pindex of the first block with the accumulator checksum
93  const CBlockIndex* _pindexFrom = FindIndexFrom(_nChecksum, _denom, cpHeight);
94  if (_pindexFrom == nullptr) {
95  LogPrintf("%s : Failed to find the block index for zpiv stake origin\n", __func__);
96  return nullptr;
97  }
98 
99  // All good
100  return new CLegacyZPivStake(_pindexFrom, _nChecksum, _denom, _hashSerial);
101 }
102 
104 {
105  return pindexFrom;
106 }
107 
109 {
110  return denom * COIN;
111 }
112 
114 {
115  CDataStream ss(SER_GETHASH, 0);
116  ss << hashSerial;
117  return ss;
118 }
int64_t CAmount
Amount in PIV (Can be negative)
Definition: amount.h:13
arith_uint256 UintToArith256(const uint256 &a)
const CChainParams & Params()
Return the currently selected parameters.
arith_uint256 getuint256() const
Definition: bignum.cpp:113
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:139
uint256 nAccumulatorCheckpoint
Definition: chain.h:199
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:151
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:72
CDataStream GetUniqueness() const override
Definition: zpos.cpp:113
const CBlockIndex * GetIndexFrom() const override
Definition: zpos.cpp:103
libzerocoin::CoinDenomination denom
Definition: zpos.h:15
static CLegacyZPivStake * NewZPivStake(const CTxIn &txin, int nHeight)
Definition: zpos.cpp:58
uint256 hashSerial
Definition: zpos.h:16
CAmount GetValue() const override
Definition: zpos.cpp:108
CLegacyZPivStake(const CBlockIndex *_pindexFrom, uint32_t _nChecksum, libzerocoin::CoinDenomination _denom, const uint256 &_hashSerial)
Definition: zpos.h:19
const CBlockIndex * pindexFrom
Definition: stakeinput.h:19
An input of a transaction.
Definition: transaction.h:94
bool IsZerocoinSpend() const
Definition: transaction.cpp:43
256-bit unsigned big integer.
unsigned char * end()
unsigned char * begin()
The complete proof needed to spend a zerocoin.
Definition: CoinSpend.h:79
const CBigNum & getCoinSerialNumber() const
Definition: CoinSpend.h:86
CoinDenomination getDenomination() const
Definition: CoinSpend.h:87
SpendType getSpendType() const
Definition: CoinSpend.h:95
uint32_t getAccumulatorChecksum() const
Definition: CoinSpend.h:88
256-bit opaque blob.
Definition: uint256.h:138
uint256 Hash(const T1 pbegin, const T1 pend)
Compute the 256-bit hash of an object.
Definition: hash.h:173
#define LogPrint(category,...)
Definition: logging.h:163
@ LEGACYZC
Definition: logging.h:62
@ UPGRADE_ZC_V2
Definition: params.h:31
@ UPGRADE_ZC
Definition: params.h:30
libzerocoin::CoinSpend TxInToZerocoinSpend(const CTxIn &txin)
Definition: zpivmodule.cpp:191
const std::vector< CoinDenomination > zerocoinDenomList
Definition: Denominations.h:27
int64_t ZerocoinDenominationToInt(const CoinDenomination &denomination)
boost::optional< T > Optional
Substitute for C++17 std::optional.
Definition: optional.h:12
@ SER_GETHASH
Definition: serialize.h:176
int nActivationHeight
Height of the first block for which the new consensus rules will be active.
Definition: params.h:56
Parameters that influence chain consensus.
Definition: params.h:171
int ZC_MinStakeDepth
Definition: params.h:256
NetworkUpgrade vUpgrades[MAX_NETWORK_UPGRADES]
Definition: params.h:213
int height_last_ZC_AccumCheckpoint
Definition: params.h:205
bool NetworkUpgradeActive(int nHeight, Consensus::UpgradeIndex idx) const
Returns true if the given network upgrade is active as of the given block height.
Definition: params.cpp:12
BlockMap mapBlockIndex
Definition: validation.cpp:82
CChain chainActive
The currently-connected chain of blocks (protected by cs_main).
Definition: validation.cpp:84
std::unique_ptr< AccumulatorCache > accumulatorCache
In-memory cache for the zerocoin accumulators.
Definition: validation.cpp:210
uint32_t ParseAccChecksum(uint256 nCheckpoint, const libzerocoin::CoinDenomination denom)
Definition: zpos.cpp:17