Skip to main content

Difficulty Adjustment

Bitmark uses Dark Gravity Wave v3 (DGWv3) for difficulty adjustment, customized for multi-algorithm operation.

Overview​

Each of the eight algorithms maintains independent difficulty, adjusted using a modified DGWv3 algorithm with special protections.

Key Features​

  • Per-Block Adjustment: Difficulty adjusts every block for each algorithm
  • Algorithm Independence: Each algorithm has separate difficulty
  • Quick Response: Adapts rapidly to hashrate changes
  • Special Protections: Surge Protector and Resurrector mechanisms

Parameters​

ParameterValueDescription
DGW Timespan960 secondsTarget time for 25 blocks of same algo
Lookback Window25 blocksSame-algorithm blocks considered
Target Per Algorithm16 minutesExpected inter-block time per algo
Combined Target2 minutesExpected time between any blocks
Min Adjustment1/3Maximum decrease per block
Max Adjustment3xMaximum increase per block

Algorithm​

Basic DGWv3 Flow​

1. Get last 25 blocks of the SAME algorithm
2. Calculate average difficulty of these blocks
3. Calculate actual timespan (first to last block)
4. Clamp timespan to [target/3, target*3]
5. Calculate new difficulty:
new_diff = avg_diff × (target_time / actual_time)
6. Apply special rules (Surge Protector, Resurrector)
7. Ensure difficulty stays above minimum

Implementation​

unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, int algo) {
// Get last 25 blocks of this algorithm
const CBlockIndex* pindexFirst = pindexLast;
int blocksFound = 0;

while (pindexFirst && blocksFound < 25) {
if (pindexFirst->GetAlgo() == algo) {
blocksFound++;
if (blocksFound == 25) break;
}
pindexFirst = pindexFirst->pprev;
}

// Calculate timespan
int64_t nActualTimespan = pindexLast->GetBlockTime() -
pindexFirst->GetBlockTime();

// Clamp timespan
int64_t nTargetTimespan = 25 * 960; // 25 blocks × 16 min
if (nActualTimespan < nTargetTimespan / 3)
nActualTimespan = nTargetTimespan / 3;
if (nActualTimespan > nTargetTimespan * 3)
nActualTimespan = nTargetTimespan * 3;

// Calculate new difficulty
CBigNum bnNew = GetAverageDifficulty(pindexFirst, pindexLast, algo);
bnNew *= nActualTimespan;
bnNew /= nTargetTimespan;

// Apply special rules...
return bnNew.GetCompact();
}

Surge Protector​

Prevents a single algorithm from dominating the chain.

Trigger Condition​

Activates when 9 or more consecutive blocks are from the same algorithm.

Action​

Divides difficulty by 3:

if (lastInRow >= 9 && lastInRow % 9 == 0) {
bnNew /= 3; // Surge Protector activation
}

Purpose​

  • Discourages burst mining
  • Ensures fair distribution across algorithms
  • Prevents algorithm dominance
  • Maintains network diversity

Example​

Block 1000: Scrypt
Block 1001: Scrypt
...
Block 1008: Scrypt (8 in a row - no action)
Block 1009: Scrypt (9 in a row - difficulty ÷ 3)

After division, mining becomes less profitable for that algorithm, encouraging miners to switch.

Resurrector​

Keeps algorithms viable when mining activity drops.

Trigger Condition​

Activates when no blocks from an algorithm for over 160 minutes (9600 seconds).

Action​

Reduces difficulty proportionally to the time elapsed:

if (time_since_last_algo_block > 9600) {  // 160 minutes
int64_t smultiplier = time_since_last_algo_block / 9600;
nActualTimespan = 10 * smultiplier * nTargetTimespan;
// This significantly reduces difficulty
}

Purpose​

  • Prevents algorithm abandonment
  • Ensures all algorithms remain mineable
  • Revives "dead" algorithms automatically
  • Maintains ecosystem diversity

Example​

Last Argon2d block: 3 hours ago (10,800 seconds)
Normal difficulty: Very high
Resurrector active: Difficulty significantly reduced
Result: Argon2d becomes profitable to mine again

Difficulty Calculation Details​

Average Difficulty​

The average difficulty is calculated across the lookback window:

CBigNum GetAverageDifficulty(const CBlockIndex* first,
const CBlockIndex* last, int algo) {
CBigNum sum = 0;
int count = 0;

for (const CBlockIndex* p = last; p != first; p = p->pprev) {
if (p->GetAlgo() == algo) {
sum += GetDifficulty(p);
count++;
}
}

return sum / count;
}

Clamping​

Timespan is clamped to prevent extreme adjustments:

// Minimum: Can't adjust more than 3x easier
if (nActualTimespan < nTargetTimespan / 3)
nActualTimespan = nTargetTimespan / 3;

// Maximum: Can't adjust more than 3x harder
if (nActualTimespan > nTargetTimespan * 3)
nActualTimespan = nTargetTimespan * 3;

Minimum Difficulty​

Difficulty can never go below the proof-of-work limit:

if (bnNew > bnProofOfWorkLimit)
bnNew = bnProofOfWorkLimit;

Visual Example​

Algorithm: Argon2d
Target: 960 seconds (25 blocks)

Scenario: Fast mining (blocks coming every 30 seconds)
─────────────────────────────────────────────────────
Actual: 25 blocks in 750 seconds (too fast!)
Target: 25 blocks in 960 seconds

Adjustment:
new_diff = old_diff × (960 / 750)
= old_diff × 1.28

Result: 28% harder to mine

Scenario: Slow mining (blocks every 90 seconds)
─────────────────────────────────────────────────────
Actual: 25 blocks in 2250 seconds (too slow!)
Target: 25 blocks in 960 seconds

Adjustment:
new_diff = old_diff × (960 / 2250)
= old_diff × 0.43

Result: 57% easier to mine

Interaction Between Algorithms​

While each algorithm has independent difficulty, they interact through:

  1. Block selection: Miners choose most profitable algorithm
  2. Profitability: Difficulty changes affect profitability
  3. Natural balance: Market forces balance algorithms

Monitoring Difficulty​

RPC Commands​

# Get current difficulty per algorithm
bitmark-cli getmininginfo

# Get difficulty for specific block
bitmark-cli getblock <blockhash>

Block Explorer​

View algorithm-specific difficulty charts at block explorers.

Historical Context​

Before Fork (Block < 450,947)​

  • Single algorithm (Scrypt)
  • Standard 720-block retargeting
  • No special mechanisms

After Fork (Block ≥ 450,947)​

  • Eight algorithms
  • Per-block DGWv3
  • Surge Protector
  • Resurrector

Comparison to Other Coins​

FeatureBitcoinLitecoinDashBitmark
Algorithms1118
Retarget2016 blocks2016 blocksEvery blockEvery block
MethodSimpleSimpleDGWv3DGWv3+
Special RulesNoneNoneNoneSurge/Resurrector

See Also​