Activate ASERT difficulty adjustment at block 6500

This commit is contained in:
Capri 2026-09-08 13:03:50 +00:00
commit a16bb53457
Signed by: VextaProject
SSH key fingerprint: SHA256:739BZv8LvIDY2tR7lXLy/IQ6MaGTQtYcG9GNvCjmpVM
4 changed files with 290 additions and 1 deletions

View file

@ -141,4 +141,214 @@ BOOST_AUTO_TEST_CASE(ChainParams_SIGNET_sanity)
sanity_check_chainparams(*m_node.args, CBaseChainParams::SIGNET);
}
BOOST_AUTO_TEST_CASE(ASERT_behavior_test)
{
const auto chainParams = CreateChainParams(*m_node.args, CBaseChainParams::MAIN);
const auto consensus = chainParams->GetConsensus();
std::vector<CBlockIndex> blocks(6501);
arith_uint256 anchorTargetValue = UintToArith256(consensus.powLimit);
anchorTargetValue >>= 8;
const unsigned int anchorBits = anchorTargetValue.GetCompact();
const int64_t startTime = 1800000000;
for (int i = 0; i <= 6500; ++i) {
blocks[i].pprev = i ? &blocks[i - 1] : nullptr;
blocks[i].nHeight = i;
blocks[i].nTime = startTime + i * consensus.nPowTargetSpacing;
blocks[i].nBits = anchorBits;
}
// Block 6499 is still governed by the legacy DAA.
const unsigned int preActivationBits =
GetNextWorkRequired(&blocks[6498], nullptr, consensus);
BOOST_CHECK_EQUAL(preActivationBits, anchorBits);
// Block 6500 is the first ASERT block. Ideal 10-minute spacing
// must preserve the anchor target.
const unsigned int idealBits =
GetNextWorkRequired(&blocks[6499], nullptr, consensus);
BOOST_CHECK_EQUAL(idealBits, anchorBits);
// Block 6501 after a very fast previous block: target must decrease
// (difficulty increases).
blocks[6500].nTime =
blocks[6499].nTime + consensus.nPowTargetSpacing / 10;
const unsigned int fastBits =
GetNextWorkRequired(&blocks[6500], nullptr, consensus);
arith_uint256 fastTarget;
fastTarget.SetCompact(fastBits);
arith_uint256 anchorTarget;
anchorTarget.SetCompact(anchorBits);
BOOST_CHECK(fastTarget < anchorTarget);
// Block 6501 after a slow previous block: target must increase
// (difficulty decreases).
blocks[6500].nTime =
blocks[6499].nTime + consensus.nPowTargetSpacing * 3;
const unsigned int slowBits =
GetNextWorkRequired(&blocks[6500], nullptr, consensus);
arith_uint256 slowTarget;
slowTarget.SetCompact(slowBits);
BOOST_CHECK(slowTarget > anchorTarget);
// Extreme delay must never produce a target above powLimit.
blocks[6500].nTime =
blocks[6499].nTime + consensus.asertHalfLife * 16;
const unsigned int extremeSlowBits =
GetNextWorkRequired(&blocks[6500], nullptr, consensus);
BOOST_CHECK_EQUAL(
extremeSlowBits,
UintToArith256(consensus.powLimit).GetCompact());
}
BOOST_AUTO_TEST_CASE(ASERT_reference_vector_run04_test)
{
auto chainParams = CreateChainParams(*m_node.args, CBaseChainParams::MAIN);
auto consensus = chainParams->GetConsensus();
consensus.asertActivationHeight = 2;
consensus.asertHalfLife = 2 * 24 * 60 * 60;
std::vector<CBlockIndex> blocks(3);
blocks[0].pprev = nullptr;
blocks[0].nHeight = 0;
blocks[0].nTime = 0;
blocks[0].nBits = 0x01010000;
blocks[1].pprev = &blocks[0];
blocks[1].nHeight = 1;
blocks[1].nTime = 600;
blocks[1].nBits = 0x01010000;
// BCHN official ASERT run04 vector:
// anchor height = 1
// anchor ancestor time = 0
// evaluation height = 2
// evaluation time = 174000
// expected next target = 0x01020000
blocks[2].pprev = &blocks[1];
blocks[2].nHeight = 2;
blocks[2].nTime = 174000;
blocks[2].nBits = 0x01010000;
const unsigned int result =
GetNextWorkRequired(&blocks[2], nullptr, consensus);
BOOST_CHECK_EQUAL(result, 0x01020000U);
}
BOOST_AUTO_TEST_CASE(ASERT_reference_vector_run05_test)
{
auto chainParams = CreateChainParams(*m_node.args, CBaseChainParams::MAIN);
auto consensus = chainParams->GetConsensus();
consensus.asertActivationHeight = 2;
consensus.asertHalfLife = 2 * 24 * 60 * 60;
std::vector<CBlockIndex> blocks(291);
blocks[0].pprev = nullptr;
blocks[0].nHeight = 0;
blocks[0].nTime = 0;
blocks[0].nBits = 0x1d00ffff;
blocks[1].pprev = &blocks[0];
blocks[1].nHeight = 1;
blocks[1].nTime = 600;
blocks[1].nBits = 0x1d00ffff;
// BCHN official ASERT run05 vector, iteration 1:
blocks[2].pprev = &blocks[1];
blocks[2].nHeight = 2;
blocks[2].nTime = 0;
blocks[2].nBits = 0x1d00ffff;
BOOST_CHECK_EQUAL(
GetNextWorkRequired(&blocks[2], nullptr, consensus),
0x1d00fec5U);
// BCHN official ASERT run05 vector, iteration 2:
// evaluation height = 290, time = 0
for (int h = 3; h <= 290; ++h) {
blocks[h].pprev = &blocks[h - 1];
blocks[h].nHeight = h;
blocks[h].nTime = 0;
blocks[h].nBits = 0x1d00ffff;
}
BOOST_CHECK_EQUAL(
GetNextWorkRequired(&blocks[290], nullptr, consensus),
0x1c7f62c0U);
}
BOOST_AUTO_TEST_CASE(ASERT_reference_vector_run06_test)
{
auto chainParams = CreateChainParams(*m_node.args, CBaseChainParams::MAIN);
auto consensus = chainParams->GetConsensus();
consensus.asertActivationHeight = 2;
consensus.asertHalfLife = 2 * 24 * 60 * 60;
std::vector<CBlockIndex> blocks(13);
blocks[0].pprev = nullptr;
blocks[0].nHeight = 0;
blocks[0].nTime = 0;
blocks[0].nBits = 0x1802aee8;
blocks[1].pprev = &blocks[0];
blocks[1].nHeight = 1;
blocks[1].nTime = 600;
blocks[1].nBits = 0x1802aee8;
const int64_t times[] = {
0, 600,
1200, 1310, 1327, 1739, 2219, 2604,
2746, 7099, 7099, 7657, 8626
};
const unsigned int expected[] = {
0,
0,
0x1802aee8U,
0x1802ad91U,
0x1802abf8U,
0x1802ab73U,
0x1802ab20U,
0x1802aa89U,
0x1802a94bU,
0x1802b39cU,
0x1802b1f2U,
0x1802b1d4U,
0x1802b2dbU
};
for (int h = 2; h <= 12; ++h) {
blocks[h].pprev = &blocks[h - 1];
blocks[h].nHeight = h;
blocks[h].nTime = times[h];
blocks[h].nBits = 0x1802aee8;
BOOST_CHECK_EQUAL(
GetNextWorkRequired(&blocks[h], nullptr, consensus),
expected[h]);
}
}
BOOST_AUTO_TEST_SUITE_END()