Bitcoin ABC 0.26.3
P2P Digital Currency
Loading...
Searching...
No Matches
aserti32d_tests.cpp
Go to the documentation of this file.
1// Copyright (c) 2020 The Bitcoin Core developers
2// Distributed under the MIT/X11 software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#include <pow/aserti32d.h>
6
7#include <chain.h>
8#include <chainparams.h>
9#include <config.h>
11#include <pow/pow.h>
12
13#include <test/util/random.h>
14#include <test/util/setup_common.h>
15
16#include <boost/test/unit_test.hpp>
17
18#include <cmath>
19
21
23 uint32_t nBits) {
24 CBlockIndex block;
25 block.pprev = pindexPrev;
26 block.nHeight = pindexPrev->nHeight + 1;
27 block.nTime = pindexPrev->nTime + nTimeInterval;
28 block.nBits = nBits;
29
30 block.BuildSkip();
31 block.nChainWork = pindexPrev->nChainWork + GetBlockProof(block);
32 return block;
33}
34
35static double TargetFromBits(const uint32_t nBits) {
36 return (nBits & 0xff'ff'ff) * pow(256, (nBits >> 24) - 3);
37}
38
40 const uint32_t finalBits,
42 const int64_t nHeightDiff =
43 pindexPrev->nHeight - pindexAnchorBlock->nHeight;
44 const int64_t nTimeDiff =
45 pindexPrev->GetBlockTime() - pindexAnchorBlock->pprev->GetBlockTime();
47
51
52 double dExponent =
53 double(nTimeDiff - (nHeightDiff + 1) * 600) / double(2 * 24 * 3600);
54 double dTarget = dInitialPow * pow(2, dExponent);
55
56 return (dFinalPow - dTarget) / dTarget;
57}
58
61
62 std::vector<CBlockIndex> blocks(3000 + 2 * 24 * 3600);
63
64 const Consensus::Params &params = config.GetChainParams().GetConsensus();
65 const arith_uint256 powLimit = UintToArith256(params.powLimit);
66 arith_uint256 currentPow = powLimit >> 3;
68 double dMaxErr = 0.0001166792656486;
69
70 // Genesis block, and parent of ASERT anchor block in this test case.
71 blocks[0] = CBlockIndex();
72 blocks[0].nHeight = 0;
73 blocks[0].nTime = 1269211443;
74 // The pre-anchor block's nBits should never be used, so we set it to a
75 // nonsense value in order to trigger an error if it is ever accessed
76 blocks[0].nBits = 0x0dedbeef;
77
78 blocks[0].nChainWork = GetBlockProof(blocks[0]);
79
80 // Block counter.
81 size_t i = 1;
82
83 // ASERT anchor block. We give this one a solvetime of 150 seconds to ensure
84 // that the solvetime between the pre-anchor and the anchor blocks is
85 // actually used.
86 blocks[1] = GetBlockIndex(&blocks[0], 150, initialBits);
87 // The nBits for the next block should not be equal to the anchor block's
88 // nBits
91 params, &blocks[1]);
92 BOOST_CHECK(fabs(GetASERTApproximationError(&blocks[i - 1], nBits,
93 &blocks[1])) < dMaxErr);
94 BOOST_CHECK(nBits != initialBits);
95
96 // If we add another block at 1050 seconds, we should return to the anchor
97 // block's nBits
98 blocks[i] = GetBlockIndex(&blocks[i - 1], 1050, nBits);
99 nBits = GetNextASERTWorkRequired(&blocks[i++], &blkHeaderDummy, params,
100 &blocks[1]);
101 BOOST_CHECK(nBits == initialBits);
102 BOOST_CHECK(fabs(GetASERTApproximationError(&blocks[i - 1], nBits,
103 &blocks[1])) < dMaxErr);
104
106 // Before we do anything else, check that timestamps *before* the anchor
107 // block work fine. Jumping 2 days into the past will give a timestamp
108 // before the achnor, and should halve the target
109 blocks[i] = GetBlockIndex(&blocks[i - 1], 600 - 172800, nBits);
110 nBits = GetNextASERTWorkRequired(&blocks[i++], &blkHeaderDummy, params,
111 &blocks[1]);
113 // Because nBits truncates target, we don't end up with exactly 1/2 the
114 // target
115 BOOST_CHECK(currentPow <= arith_uint256().SetCompact(initialBits) / 2);
116 BOOST_CHECK(currentPow >= arith_uint256().SetCompact(initialBits - 1) / 2);
117 BOOST_CHECK(fabs(GetASERTApproximationError(&blocks[i - 1], nBits,
118 &blocks[1])) < dMaxErr);
119
120 // Jumping forward 2 days should return the target to the initial value
121 blocks[i] = GetBlockIndex(&blocks[i - 1], 600 + 172800, nBits);
122 nBits = GetNextASERTWorkRequired(&blocks[i++], &blkHeaderDummy, params,
123 &blocks[1]);
125 BOOST_CHECK(nBits == initialBits);
126 BOOST_CHECK(fabs(GetASERTApproximationError(&blocks[i - 1], nBits,
127 &blocks[1])) < dMaxErr);
128
129 // Pile up some blocks every 10 mins to establish some history.
130 for (; i < 150; i++) {
131 blocks[i] = GetBlockIndex(&blocks[i - 1], 600, nBits);
132 BOOST_CHECK_EQUAL(blocks[i].nBits, nBits);
133 }
134
135 nBits = GetNextASERTWorkRequired(&blocks[i - 1], &blkHeaderDummy, params,
136 &blocks[1]);
137
139
140 // Difficulty stays the same as long as we produce a block every 10 mins.
141 for (size_t j = 0; j < 10; i++, j++) {
142 blocks[i] = GetBlockIndex(&blocks[i - 1], 600, nBits);
144 params, &blocks[1]),
145 nBits);
146 }
147
148 // If we add a two blocks whose solvetimes together add up to 1200s,
149 // then the next block's target should be the same as the one before these
150 // blocks (at this point, equal to initialBits).
151 blocks[i] = GetBlockIndex(&blocks[i - 1], 300, nBits);
152 nBits = GetNextASERTWorkRequired(&blocks[i++], &blkHeaderDummy, params,
153 &blocks[1]);
154 BOOST_CHECK(fabs(GetASERTApproximationError(&blocks[i - 1], nBits,
155 &blocks[1])) < dMaxErr);
156 // relative
157 BOOST_CHECK(fabs(GetASERTApproximationError(&blocks[i - 1], nBits,
158 &blocks[i - 2])) < dMaxErr);
159 blocks[i] = GetBlockIndex(&blocks[i - 1], 900, nBits);
160 nBits = GetNextASERTWorkRequired(&blocks[i++], &blkHeaderDummy, params,
161 &blocks[1]);
162 // absolute
163 BOOST_CHECK(fabs(GetASERTApproximationError(&blocks[i - 1], nBits,
164 &blocks[1])) < dMaxErr);
165 // relative
166 BOOST_CHECK(fabs(GetASERTApproximationError(&blocks[i - 1], nBits,
167 &blocks[i - 2])) < dMaxErr);
169 BOOST_CHECK(nBits != blocks[i - 1].nBits);
170
171 // Same in reverse - this time slower block first, followed by faster block.
172 blocks[i] = GetBlockIndex(&blocks[i - 1], 900, nBits);
173 nBits = GetNextASERTWorkRequired(&blocks[i++], &blkHeaderDummy, params,
174 &blocks[1]);
175 // absolute
176 BOOST_CHECK(fabs(GetASERTApproximationError(&blocks[i - 1], nBits,
177 &blocks[1])) < dMaxErr);
178 // relative
179 BOOST_CHECK(fabs(GetASERTApproximationError(&blocks[i - 1], nBits,
180 &blocks[i - 2])) < dMaxErr);
181 blocks[i] = GetBlockIndex(&blocks[i - 1], 300, nBits);
182 nBits = GetNextASERTWorkRequired(&blocks[i++], &blkHeaderDummy, params,
183 &blocks[1]);
184 // absolute
185 BOOST_CHECK(fabs(GetASERTApproximationError(&blocks[i - 1], nBits,
186 &blocks[1])) < dMaxErr);
187 // relative
188 BOOST_CHECK(fabs(GetASERTApproximationError(&blocks[i - 1], nBits,
189 &blocks[i - 2])) < dMaxErr);
191 BOOST_CHECK(nBits != blocks[i - 1].nBits);
192
193 // Jumping forward 2 days should double the target (halve the difficulty)
194 blocks[i] = GetBlockIndex(&blocks[i - 1], 600 + 2 * 24 * 3600, nBits);
195 nBits = GetNextASERTWorkRequired(&blocks[i++], &blkHeaderDummy, params,
196 &blocks[1]);
197 // absolute
198 BOOST_CHECK(fabs(GetASERTApproximationError(&blocks[i - 1], nBits,
199 &blocks[1])) < dMaxErr);
200 // relative
201 BOOST_CHECK(fabs(GetASERTApproximationError(&blocks[i - 1], nBits,
202 &blocks[i - 2])) < dMaxErr);
203 currentPow = arith_uint256().SetCompact(nBits) / 2;
205
206 // Jumping backward 2 days should bring target back to where we started
207 blocks[i] = GetBlockIndex(&blocks[i - 1], 600 - 2 * 24 * 3600, nBits);
208 nBits = GetNextASERTWorkRequired(&blocks[i++], &blkHeaderDummy, params,
209 &blocks[1]);
211 &blocks[i - 1], nBits, &blocks[1])) < dMaxErr); // absolute
212 BOOST_CHECK(fabs(GetASERTApproximationError(&blocks[i - 1], nBits,
213 &blocks[i - 2])) <
214 dMaxErr); // relative
216
217 // Jumping backward 2 days should halve the target (double the difficulty)
218 blocks[i] = GetBlockIndex(&blocks[i - 1], 600 - 2 * 24 * 3600, nBits);
219 nBits = GetNextASERTWorkRequired(&blocks[i++], &blkHeaderDummy, params,
220 &blocks[1]);
221 // absolute
222 BOOST_CHECK(fabs(GetASERTApproximationError(&blocks[i - 1], nBits,
223 &blocks[1])) < dMaxErr);
224 // relative
225 BOOST_CHECK(fabs(GetASERTApproximationError(&blocks[i - 1], nBits,
226 &blocks[i - 2])) < dMaxErr);
228 // Because nBits truncates target, we don't end up with exactly 1/2 the
229 // target
230 BOOST_CHECK(currentPow <= arith_uint256().SetCompact(initialBits) / 2);
231 BOOST_CHECK(currentPow >= arith_uint256().SetCompact(initialBits - 1) / 2);
232
233 // And forward again
234 blocks[i] = GetBlockIndex(&blocks[i - 1], 600 + 2 * 24 * 3600, nBits);
235 nBits = GetNextASERTWorkRequired(&blocks[i++], &blkHeaderDummy, params,
236 &blocks[1]);
237 // absolute
238 BOOST_CHECK(fabs(GetASERTApproximationError(&blocks[i - 1], nBits,
239 &blocks[1])) < dMaxErr);
240 // relative
241 BOOST_CHECK(fabs(GetASERTApproximationError(&blocks[i - 1], nBits,
242 &blocks[i - 2])) < dMaxErr);
244 blocks[i] = GetBlockIndex(&blocks[i - 1], 600 + 2 * 24 * 3600, nBits);
245 nBits = GetNextASERTWorkRequired(&blocks[i++], &blkHeaderDummy, params,
246 &blocks[1]);
247 // absolute
248 BOOST_CHECK(fabs(GetASERTApproximationError(&blocks[i - 1], nBits,
249 &blocks[1])) < dMaxErr);
250 // relative
251 BOOST_CHECK(fabs(GetASERTApproximationError(&blocks[i - 1], nBits,
252 &blocks[i - 2])) < dMaxErr);
253 currentPow = arith_uint256().SetCompact(nBits) / 2;
255
256 // Iterate over the entire -2*24*3600..+2*24*3600 range to check that our
257 // integer approximation:
258 // 1. Should be monotonic.
259 // 2. Should change target at least once every 8 seconds (worst-case:
260 // 15-bit precision on nBits)
261 // 3. Should never change target by more than XXXX per 1-second step.
262 // 4. Never exceeds dMaxError in absolute error vs a double float
263 // calculation.
264 // 5. Has almost exactly the dMax and dMin errors we expect for the
265 // formula.
266 double dMin = 0;
267 double dMax = 0;
268 double dErr;
269 double dRelMin = 0;
270 double dRelMax = 0;
271 double dRelErr;
272 double dMaxStep = 0;
274 double dStep = 0;
275 blocks[i] = GetBlockIndex(&blocks[i - 1], -2 * 24 * 3600 - 30, nBits);
276 for (size_t j = 0; j < 4 * 24 * 3600 + 660; j++) {
277 blocks[i].nTime++;
278 nBits = GetNextASERTWorkRequired(&blocks[i], &blkHeaderDummy, params,
279 &blocks[1]);
280
281 if (j > 8) {
282 // 1: Monotonic
284 arith_uint256().SetCompact(nBits) >=
285 arith_uint256().SetCompact(nBitsRingBuffer[(j - 1) % 8]));
286 // 2: Changes at least once every 8 seconds (worst case: nBits =
287 // 1d008000 to 1d008001)
288 BOOST_CHECK(arith_uint256().SetCompact(nBits) >
289 arith_uint256().SetCompact(nBitsRingBuffer[j % 8]));
290 // 3: Check 1-sec step size
291 dStep = (TargetFromBits(nBits) -
292 TargetFromBits(nBitsRingBuffer[(j - 1) % 8])) /
293 TargetFromBits(nBits);
294 dMaxStep = std::max(dMaxStep, dStep);
295 // from nBits = 1d008000 to 1d008001
296 BOOST_CHECK(dStep < 0.0000314812106363);
297 }
298 nBitsRingBuffer[j % 8] = nBits;
299
300 // 4 and 5: check error vs double precision float calculation
301 dErr = GetASERTApproximationError(&blocks[i], nBits, &blocks[1]);
302 dRelErr = GetASERTApproximationError(&blocks[i], nBits, &blocks[i - 1]);
303 dMin = std::min(dMin, dErr);
304 dMax = std::max(dMax, dErr);
305 dRelMin = std::min(dRelMin, dRelErr);
306 dRelMax = std::max(dRelMax, dRelErr);
308 fabs(dErr) < dMaxErr,
309 strprintf(
310 "solveTime: %d\tStep size: %.8f%%\tdErr: %.8f%%\tnBits: %0x\n",
311 int64_t(blocks[i].nTime) - blocks[i - 1].nTime, dStep * 100,
312 dErr * 100, nBits));
315 strprintf("solveTime: %d\tStep size: %.8f%%\tdRelErr: "
316 "%.8f%%\tnBits: %0x\n",
317 int64_t(blocks[i].nTime) - blocks[i - 1].nTime,
318 dStep * 100, dRelErr * 100, nBits));
319 }
320 auto failMsg = strprintf(
321 "Min error: %16.14f%%\tMax error: %16.14f%%\tMax step: %16.14f%%\n",
322 dMin * 100, dMax * 100, dMaxStep * 100);
324 dMin < -0.0001013168981059 && dMin > -0.0001013168981060 &&
325 dMax > 0.0001166792656485 && dMax < 0.0001166792656486,
326 failMsg);
327 failMsg = strprintf("Min relError: %16.14f%%\tMax relError: %16.14f%%\n",
328 dRelMin * 100, dRelMax * 100);
330 dRelMin < -0.0001013168981059 && dRelMin > -0.0001013168981060 &&
331 dRelMax > 0.0001166792656485 && dRelMax < 0.0001166792656486,
332 failMsg);
333
334 // Difficulty increases as long as we produce fast blocks
335 for (size_t j = 0; j < 100; i++, j++) {
339
340 blocks[i] = GetBlockIndex(&blocks[i - 1], 500, nBits);
341 nextBits = GetNextASERTWorkRequired(&blocks[i], &blkHeaderDummy, params,
342 &blocks[1]);
345
346 // Make sure that target is decreased
348
349 nBits = nextBits;
350 }
351}
352
353static std::string StrPrintCalcArgs(const arith_uint256 refTarget,
355 const int64_t timeDiff,
356 const int64_t heightDiff,
358 const uint32_t expectednBits) {
359 return strprintf("\n"
360 "ref= %s\n"
361 "spacing= %d\n"
362 "timeDiff= %d\n"
363 "heightDiff= %d\n"
364 "expTarget= %s\n"
365 "exp nBits= 0x%08x\n",
367 expectedTarget.ToString(), expectednBits);
368}
369
370// Tests of the CalculateASERT function.
373 const Consensus::Params &params = config.GetChainParams().GetConsensus();
374 const int64_t nHalfLife = params.nDAAHalfLife;
375
376 const arith_uint256 powLimit = UintToArith256(params.powLimit);
377 arith_uint256 initialTarget = powLimit >> 4;
378 int64_t height = 0;
379
380 // The CalculateASERT function uses the absolute ASERT formulation
381 // and adds +1 to the height difference that it receives.
382 // The time difference passed to it must factor in the difference
383 // to the *parent* of the reference block.
384 // We assume the parent is ideally spaced in time before the reference
385 // block.
386 static const int64_t parent_time_diff = 600;
387
388 // Steady
391 parent_time_diff + 600 /* nTimeDiff */, ++height, powLimit, nHalfLife);
393
394 // A block that arrives in half the expected time
396 parent_time_diff + 600 + 300, ++height,
397 powLimit, nHalfLife);
399
400 // A block that makes up for the shortfall of the previous one, restores the
401 // target to initial
404 parent_time_diff + 600 + 300 + 900, ++height,
405 powLimit, nHalfLife);
408
409 // Two days ahead of schedule should double the target (halve the
410 // difficulty)
412 nextTarget =
414 parent_time_diff + 288 * 1200, 288, powLimit, nHalfLife);
416
417 // Two days behind schedule should halve the target (double the difficulty)
419 nextTarget =
421 parent_time_diff + 288 * 0, 288, powLimit, nHalfLife);
424
425 // Ramp up from initialTarget to PowLimit - should only take 4 doublings...
428 for (size_t k = 0; k < 3; k++) {
431 parent_time_diff + 288 * 1200, 288,
432 powLimit, nHalfLife);
434 BOOST_CHECK(nextTarget < powLimit);
435 next_nBits = nextTarget.GetCompact();
437 }
438
440 nextTarget =
442 parent_time_diff + 288 * 1200, 288, powLimit, nHalfLife);
443 next_nBits = nextTarget.GetCompact();
446
447 // Fast periods now cannot increase target beyond POW limit, even if we try
448 // to overflow nextTarget. prevTarget is a uint256, so 256*2 = 512 days
449 // would overflow nextTarget unless CalculateASERT correctly detects this
450 // error
452 parent_time_diff + 512 * 144 * 600, 0, powLimit,
453 nHalfLife);
454 next_nBits = nextTarget.GetCompact();
456
457 // We also need to watch for underflows on nextTarget. We need to withstand
458 // an extra ~446 days worth of blocks. This should bring down a powLimit
459 // target to the a minimum target of 1.
460 nextTarget = CalculateASERT(powLimit, params.nPowTargetSpacing, 0,
461 2 * (256 - 33) * 144, powLimit, nHalfLife);
462 next_nBits = nextTarget.GetCompact();
464
465 // Define a structure holding parameters to pass to CalculateASERT.
466 // We are going to check some expected results against a vector of
467 // possible arguments.
468 struct calc_params {
475 };
476
477 // Define some named input argument values
479 "00000000ffb1ffffffffffffffffffffffffffffffffffffffffffffffffffff"};
481 "000000008000000000000000000fffffffffffffffffffffffffffffffffffff"};
482
483 // Define our expected input and output values.
484 // The timeDiff entries exclude the `parent_time_diff` - this is
485 // added in the call to CalculateASERT in the test loop.
486 const std::vector<calc_params> calculate_args = {
487
488 /* refTarget, targetSpacing, timeDiff, heightDiff, expectedTarget,
489 expectednBits */
490
491 {powLimit, 600, 0, 2 * 144, powLimit >> 1, 0x1c7fffff},
492 {powLimit, 600, 0, 4 * 144, powLimit >> 2, 0x1c3fffff},
493 {powLimit >> 1, 600, 0, 2 * 144, powLimit >> 2, 0x1c3fffff},
494 {powLimit >> 2, 600, 0, 2 * 144, powLimit >> 3, 0x1c1fffff},
495 {powLimit >> 3, 600, 0, 2 * 144, powLimit >> 4, 0x1c0fffff},
496 {powLimit, 600, 0, 2 * (256 - 34) * 144, 3, 0x01030000},
497 {powLimit, 600, 0, 2 * (256 - 34) * 144 + 119, 3, 0x01030000},
498 {powLimit, 600, 0, 2 * (256 - 34) * 144 + 120, 2, 0x01020000},
499 {powLimit, 600, 0, 2 * (256 - 33) * 144 - 1, 2, 0x01020000},
500 // 1 bit less since we do not need to shift to 0
501 {powLimit, 600, 0, 2 * (256 - 33) * 144, 1, 0x01010000},
502 // more will not decrease below 1
503 {powLimit, 600, 0, 2 * (256 - 32) * 144, 1, 0x01010000},
504 {1, 600, 0, 2 * (256 - 32) * 144, 1, 0x01010000},
505 {powLimit, 600, 2 * (512 - 32) * 144, 0, powLimit, powLimit_nBits},
506 {1, 600, (512 - 64) * 144 * 600, 0, powLimit, powLimit_nBits},
507 // clamps to powLimit
508 {powLimit, 600, 300, 1, SINGLE_300_TARGET, 0x1d00ffb1},
509 // confuses any attempt to detect overflow by inspecting result
510 {FUNNY_REF_TARGET, 600, 600 * 2 * 33 * 144, 0, powLimit,
512 // overflow to exactly 2^256
513 {1, 600, 600 * 2 * 256 * 144, 0, powLimit, powLimit_nBits},
514 // just under powlimit (not clamped) yet over powlimit_nbits
515 {1, 600, 600 * 2 * 224 * 144 - 1, 0, arith_uint256(0xffff8) << 204,
517 };
518
519 for (auto &v : calculate_args) {
520 nextTarget = CalculateASERT(v.refTarget, v.targetSpacing,
521 parent_time_diff + v.timeDiff, v.heightDiff,
522 powLimit, nHalfLife);
523 next_nBits = nextTarget.GetCompact();
524 const auto failMsg =
525 StrPrintCalcArgs(v.refTarget, v.targetSpacing,
526 parent_time_diff + v.timeDiff, v.heightDiff,
527 v.expectedTarget, v.expectednBits) +
528 strprintf("nextTarget= %s\nnext nBits= 0x%08x\n",
529 nextTarget.ToString(), next_nBits);
530 BOOST_CHECK_MESSAGE(nextTarget == v.expectedTarget &&
531 next_nBits == v.expectednBits,
532 failMsg);
533 }
534}
535
537public:
539 int daaHeight, int axionHeight)
540 : CChainParams(chainParams) {
541 BOOST_REQUIRE_GT(axionHeight, daaHeight);
542 consensus.daaHeight = daaHeight;
543 consensus.axionHeight = axionHeight;
544 }
545};
546
552 // Make a custom chain params based on mainnet, activating the cw144 DAA
553 // at a lower height than usual, so we don't need to waste time making a
554 // 504000-long chain.
555 const auto mainChainParams =
557 const int asertActivationHeight = 4000;
558 const ChainParamsWithCustomActivation chainParams(*mainChainParams, 2016,
560 const Consensus::Params &params = chainParams.GetConsensus();
561
563
564 // an arbitrary compact target for our chain (based on BCH chain ~ Aug 10
565 // 2020).
566 uint32_t initialBits = 0x1802a842;
567
568 // Block store for anonymous blocks; needs to be big enough to fit all
569 // generated blocks in this test.
570 std::vector<CBlockIndex> blocks(10000);
571 int bidx = 1;
572
573 // Genesis block.
574 blocks[0].nHeight = 0;
575 blocks[0].nTime = 1269211443;
576 blocks[0].nBits = initialBits;
577 blocks[0].nChainWork = GetBlockProof(blocks[0]);
578
579 // Pile up a random number of blocks to establish some history of random
580 // height. cw144 DAA requires us to have height at least 2016, dunno why
581 // that much. Keep going up to 145 blocks prior to ASERT activation.
582 for (int i = 1; i < asertActivationHeight - 145; i++) {
583 BOOST_REQUIRE(bidx < int(blocks.size()));
584 blocks[bidx] = GetBlockIndex(&blocks[bidx - 1], 600, initialBits);
585 bidx++;
586 }
587 // Then put down 145 more blocks with 500 second solvetime each, such that
588 // the final block is the one prior to activation.
589 for (int i = 0; i < 145; i++) {
590 BOOST_REQUIRE(bidx < int(blocks.size()));
591 blocks[bidx] = GetBlockIndex(&blocks[bidx - 1], 500, initialBits);
592 bidx++;
593 }
594 CBlockIndex *pindexPreActivation = &blocks[bidx - 1];
597
598 // If we consult DAA, then it uses cw144 which returns a significantly lower
599 // target because we have been mining too fast by a ratio 600/500 for a
600 // whole day.
604 0x180236e1);
605
612 // Create an activating block with expected solvetime, taking the cw144
613 // difficulty we just saw. Since solvetime is expected the next target is
614 // unchanged.
616 GetBlockIndex(pindexPreActivation, 600, 0x180236e1);
620 0x180236e1);
623 0x180236e1);
624
625 // Now we'll generate some more activations/anchors, using unique targets
626 // for each one (if the algo gets confused between different anchors, we
627 // will know).
628
629 // Create an activating block with 0 solvetime, which will drop target by
630 // ~415/416.
632 GetBlockIndex(pindexPreActivation, 0, 0x18023456);
634 // cache will be stale here, and we should get the right result regardless:
637 0x180232fd);
640 0x180232fd);
643 0x180232fd);
644
645 // Try activation with expected solvetime, which will keep target the same.
646 uint32_t anchorBits2 = 0x180210fe;
653
654 // Try a three-month solvetime which will cause us to hit powLimit.
655 uint32_t anchorBits3 = 0x18034567;
661 0x1d00ffff);
662 // If the next block jumps back in time, we get back our original difficulty
663 // level.
665 GetBlockIndex(&indexActivation3, -86400 * 90 + 2 * 600, anchorBits3);
667 &blkHeaderDummy, chainParams),
669 // Retry for cache
671 &blkHeaderDummy, chainParams),
673
674 // Make an activation with MTP == activation exactly. This is a backwards
675 // timestamp jump so the resulting target is 1.2% lower.
677 GetBlockIndex(pindexPreActivation, 0, 0x18011111);
678 indexActivation4.nTime = pindexPreActivation->GetMedianTimePast();
682 0x18010db3);
683
684 // Finally create a random chain on top of our second activation, using
685 // ASERT targets all the way. Erase cache so that this will do a fresh
686 // search for anchor at every step (fortauntely this is not too slow, due to
687 // the skiplist traversal)
689 for (int i = 1; i < 1000; i++) {
690 BOOST_REQUIRE(bidx < int(blocks.size()));
693 blocks[bidx] =
695 pindexChain2 = &blocks[bidx++];
696 }
697 // Scan back down to make sure all targets are same when we keep cached
698 // anchor.
699 for (CBlockIndex *pindex = pindexChain2; pindex != &indexActivation2;
700 pindex = pindex->pprev) {
702 GetNextWorkRequired(pindex->pprev, &blkHeaderDummy, chainParams);
703 BOOST_CHECK_EQUAL(nextBits, pindex->nBits);
704 }
705}
706
bool IsDAAEnabled(const Consensus::Params &params, int nHeight)
static bool IsAxionEnabled(const Consensus::Params &params, int32_t nHeight)
arith_uint256 UintToArith256(const uint256 &a)
arith_uint256 CalculateASERT(const arith_uint256 &refTarget, const int64_t nPowTargetSpacing, const int64_t nTimeDiff, const int64_t nHeightDiff, const arith_uint256 &powLimit, const int64_t nHalfLife) noexcept
Definition aserti32d.cpp:84
uint32_t GetNextASERTWorkRequired(const CBlockIndex *pindexPrev, const CBlockHeader *pblock, const Consensus::Params &params) noexcept
Definition aserti32d.cpp:9
static double GetASERTApproximationError(const CBlockIndex *pindexPrev, const uint32_t finalBits, const CBlockIndex *pindexAnchorBlock)
BOOST_AUTO_TEST_CASE(asert_difficulty_test)
static CBlockIndex GetBlockIndex(CBlockIndex *pindexPrev, int64_t nTimeInterval, uint32_t nBits)
static std::string StrPrintCalcArgs(const arith_uint256 refTarget, const int64_t targetSpacing, const int64_t timeDiff, const int64_t heightDiff, const arith_uint256 expectedTarget, const uint32_t expectednBits)
static double TargetFromBits(const uint32_t nBits)
arith_uint256 GetBlockProof(const CBlockIndex &block)
Definition chain.cpp:74
std::unique_ptr< const CChainParams > CreateChainParams(const ArgsManager &args, const std::string &chain)
Creates and returns a std::unique_ptr<CChainParams> of the chosen chain.
static const std::string MAIN
BIP70 chain name strings (main, test or regtest)
Nodes collect new transactions into a block, hash them into a hash tree, and scan through nonce value...
Definition block.h:23
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition blockindex.h:25
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition blockindex.h:32
void BuildSkip()
Build the skiplist pointer for this entry.
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
Definition blockindex.h:51
uint32_t nTime
Definition blockindex.h:92
uint32_t nBits
Definition blockindex.h:93
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition blockindex.h:38
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
Definition chainparams.h:80
const Consensus::Params & GetConsensus() const
Definition chainparams.h:92
Consensus::Params consensus
ChainParamsWithCustomActivation(const CChainParams &chainParams, int daaHeight, int axionHeight)
256-bit unsigned big integer.
arith_uint256 & SetCompact(uint32_t nCompact, bool *pfNegative=nullptr, bool *pfOverflow=nullptr)
The "compact" format is a representation of a whole number N using an unsigned 32bit number similar t...
uint32_t GetCompact(bool fNegative=false) const
NodeContext & m_node
#define BOOST_CHECK_EQUAL(v1, v2)
Definition object.cpp:18
#define BOOST_CHECK(expr)
Definition object.cpp:17
uint32_t GetNextWorkRequired(const CBlockIndex *pindexPrev, const CBlockHeader *pblock, const CChainParams &chainParams)
Definition pow.cpp:21
T GetRand(T nMax=std::numeric_limits< T >::max()) noexcept
Generate a uniform random integer of type T in the range [0..nMax) nMax defaults to std::numeric_limi...
Definition random.h:85
Parameters that influence chain consensus.
Definition params.h:34
int axionHeight
Block height at which the axion activation becomes active.
Definition params.h:59
int64_t nDAAHalfLife
Definition params.h:79
int daaHeight
Block height at which the new DAA becomes active.
Definition params.h:51
uint256 powLimit
Proof of work parameters.
Definition params.h:76
int64_t nPowTargetSpacing
Definition params.h:80
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...