@@ -152,7 +152,7 @@ bool EraseCheckpoints(int nStartHeight, int nEndHeight)
152
152
}
153
153
154
154
// Get checkpoint value for a specific block height
155
- bool CalculateAccumulatorCheckpoint (int nHeight, uint256& nCheckpoint)
155
+ bool CalculateAccumulatorCheckpoint (int nHeight, uint256& nCheckpoint, AccumulatorMap& mapAccumulators )
156
156
{
157
157
if (nHeight < Params ().Zerocoin_StartHeight ()) {
158
158
nCheckpoint = 0 ;
@@ -166,7 +166,7 @@ bool CalculateAccumulatorCheckpoint(int nHeight, uint256& nCheckpoint)
166
166
}
167
167
168
168
// set the accumulators to last checkpoint value
169
- AccumulatorMap mapAccumulators;
169
+ mapAccumulators. Reset () ;
170
170
if (!mapAccumulators.Load (chainActive[nHeight - 1 ]->nAccumulatorCheckpoint )) {
171
171
if (chainActive[nHeight - 1 ]->nAccumulatorCheckpoint == 0 ) {
172
172
// Before zerocoin is fully activated so set to init state
@@ -216,14 +216,12 @@ bool CalculateAccumulatorCheckpoint(int nHeight, uint256& nCheckpoint)
216
216
// grab mints from this block
217
217
CBlock block;
218
218
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__);
221
220
}
222
221
223
222
std::list<PublicCoin> listPubcoins;
224
223
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 );
227
225
}
228
226
229
227
nTotalMintsFound += listPubcoins.size ();
@@ -232,23 +230,18 @@ bool CalculateAccumulatorCheckpoint(int nHeight, uint256& nCheckpoint)
232
230
// add the pubcoins to accumulator
233
231
for (const PublicCoin pubcoin : listPubcoins) {
234
232
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 );
237
234
}
238
235
}
239
236
pindex = chainActive.Next (pindex);
240
237
}
241
238
242
239
// 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 )
244
241
nCheckpoint = chainActive[nHeight - 1 ]->nAccumulatorCheckpoint ;
245
- }
246
242
else
247
243
nCheckpoint = mapAccumulators.GetCheckpoint ();
248
244
249
- // make sure that these values are databased because reorgs may have deleted the checksums from DB
250
- DatabaseChecksums (mapAccumulators);
251
-
252
245
LogPrint (" zero" , " %s checkpoint=%s\n " , __func__, nCheckpoint.GetHex ());
253
246
return true ;
254
247
}
@@ -258,6 +251,51 @@ bool InvalidCheckpointRange(int nHeight)
258
251
return nHeight > Params ().Zerocoin_Block_LastGoodCheckpoint () && nHeight < Params ().Zerocoin_Block_RecalculateAccumulators ();
259
252
}
260
253
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
+
261
299
bool GenerateAccumulatorWitness (const PublicCoin &coin, Accumulator& accumulator, AccumulatorWitness& witness, int nSecurityLevel, int & nMintsAdded, string& strError)
262
300
{
263
301
uint256 txid;
0 commit comments