@@ -152,7 +152,7 @@ bool EraseCheckpoints(int nStartHeight, int nEndHeight)
152152}
153153
154154// Get checkpoint value for a specific block height
155- bool CalculateAccumulatorCheckpoint (int nHeight, uint256& nCheckpoint)
155+ bool CalculateAccumulatorCheckpoint (int nHeight, uint256& nCheckpoint, AccumulatorMap& mapAccumulators )
156156{
157157 if (nHeight < Params ().Zerocoin_StartHeight ()) {
158158 nCheckpoint = 0 ;
@@ -166,7 +166,7 @@ bool CalculateAccumulatorCheckpoint(int nHeight, uint256& nCheckpoint)
166166 }
167167
168168 // set the accumulators to last checkpoint value
169- AccumulatorMap mapAccumulators;
169+ mapAccumulators. Reset () ;
170170 if (!mapAccumulators.Load (chainActive[nHeight - 1 ]->nAccumulatorCheckpoint )) {
171171 if (chainActive[nHeight - 1 ]->nAccumulatorCheckpoint == 0 ) {
172172 // Before zerocoin is fully activated so set to init state
@@ -216,14 +216,12 @@ bool CalculateAccumulatorCheckpoint(int nHeight, uint256& nCheckpoint)
216216 // grab mints from this block
217217 CBlock block;
218218 if (!ReadBlockFromDisk (block, pindex)) {
219- LogPrint (" zero" ," %s: failed to read block from disk\n " , __func__);
220- return false ;
219+ return error (" %s: failed to read block from disk\n " , __func__);
221220 }
222221
223222 std::list<PublicCoin> listPubcoins;
224223 if (!BlockToPubcoinList (block, listPubcoins, fFilterInvalid )) {
225- LogPrint (" zero" ," %s: failed to get zerocoin mintlist from block %n\n " , __func__, pindex->nHeight );
226- return false ;
224+ return error (" %s: failed to get zerocoin mintlist from block %d\n " , __func__, pindex->nHeight );
227225 }
228226
229227 nTotalMintsFound += listPubcoins.size ();
@@ -232,23 +230,18 @@ bool CalculateAccumulatorCheckpoint(int nHeight, uint256& nCheckpoint)
232230 // add the pubcoins to accumulator
233231 for (const PublicCoin pubcoin : listPubcoins) {
234232 if (!mapAccumulators.Accumulate (pubcoin, true )) {
235- LogPrintf (" %s: failed to add pubcoin to accumulator at height %n\n " , __func__, pindex->nHeight );
236- return false ;
233+ return error (" %s: failed to add pubcoin to accumulator at height %n\n " , __func__, pindex->nHeight );
237234 }
238235 }
239236 pindex = chainActive.Next (pindex);
240237 }
241238
242239 // if there were no new mints found, the accumulator checkpoint will be the same as the last checkpoint
243- if (nTotalMintsFound == 0 ) {
240+ if (nTotalMintsFound == 0 )
244241 nCheckpoint = chainActive[nHeight - 1 ]->nAccumulatorCheckpoint ;
245- }
246242 else
247243 nCheckpoint = mapAccumulators.GetCheckpoint ();
248244
249- // make sure that these values are databased because reorgs may have deleted the checksums from DB
250- DatabaseChecksums (mapAccumulators);
251-
252245 LogPrint (" zero" , " %s checkpoint=%s\n " , __func__, nCheckpoint.GetHex ());
253246 return true ;
254247}
@@ -258,6 +251,51 @@ bool InvalidCheckpointRange(int nHeight)
258251 return nHeight > Params ().Zerocoin_Block_LastGoodCheckpoint () && nHeight < Params ().Zerocoin_Block_RecalculateAccumulators ();
259252}
260253
254+ bool ValidateAccumulatorCheckpoint (const CBlock& block, CBlockIndex* pindex, AccumulatorMap& mapAccumulators)
255+ {
256+ if (!fVerifyingBlocks && pindex->nHeight >= Params ().Zerocoin_StartHeight () && pindex->nHeight % 10 == 0 ) {
257+ uint256 nCheckpointCalculated = 0 ;
258+
259+ // if IDB, invalid outpoints must be calculated or else acc checkpoint will be incorrect
260+ if (pindex->nHeight == Params ().Zerocoin_Block_RecalculateAccumulators ())
261+ PopulateInvalidOutPointMap ();
262+
263+ if (!CalculateAccumulatorCheckpoint (pindex->nHeight , nCheckpointCalculated, mapAccumulators)) {
264+ // Calculate list of checkpoints that may be missing due to deletion on block 809000, and rewinding back before 809000
265+ int nStop = Params ().Zerocoin_Block_RecalculateAccumulators () + 20 ;
266+ if (pindex->nHeight < nStop && pindex->nHeight > Params ().Zerocoin_Block_LastGoodCheckpoint ()) {
267+ LogPrintf (" %s : Checkpoint not found for block %d, recalculating accumulators\n " , __func__, pindex->nHeight );
268+ CBlockIndex* pindexCheckpoint = chainActive[Params ().Zerocoin_Block_LastGoodCheckpoint ()];
269+ list<uint256> listCheckpoints;
270+ while (pindexCheckpoint->nHeight <= nStop) {
271+ if (!count (listCheckpoints.begin (), listCheckpoints.end (), pindexCheckpoint->nAccumulatorCheckpoint ))
272+ listCheckpoints.emplace_back (pindexCheckpoint->nAccumulatorCheckpoint );
273+
274+ pindexCheckpoint = chainActive.Next (pindexCheckpoint);
275+ if (!pindexCheckpoint)
276+ break ;
277+ }
278+
279+ string strError;
280+ if (!ReindexAccumulators (listCheckpoints, strError) || !CalculateAccumulatorCheckpoint (pindex->nHeight , nCheckpointCalculated, mapAccumulators))
281+ return error (" %s : failed to recalculate accumulator checkpoint" , __func__);
282+ } else {
283+ return error (" %s : failed to calculate accumulator checkpoint" , __func__);
284+ }
285+ }
286+
287+ if (nCheckpointCalculated != block.nAccumulatorCheckpoint ) {
288+ LogPrintf (" %s: block=%d calculated: %s\n block: %s\n " , __func__, pindex->nHeight , nCheckpointCalculated.GetHex (), block.nAccumulatorCheckpoint .GetHex ());
289+ return error (" %s : accumulator does not match calculated value" , __func__);
290+ }
291+ } else if (!fVerifyingBlocks ) {
292+ if (block.nAccumulatorCheckpoint != pindex->pprev ->nAccumulatorCheckpoint )
293+ return error (" %s : new accumulator checkpoint generated on a block that is not multiple of 10" , __func__);
294+ }
295+
296+ return true ;
297+ }
298+
261299bool GenerateAccumulatorWitness (const PublicCoin &coin, Accumulator& accumulator, AccumulatorWitness& witness, int nSecurityLevel, int & nMintsAdded, string& strError)
262300{
263301 uint256 txid;
0 commit comments