Skip to content

jd-client vardiff runaway: share counter increments before validation #272

@warioishere

Description

@warioishere

Bug Description

JD-Client's vardiff continuously increases difficulty even when miners fail to submit valid shares due to difficulty being too high. This creates a runaway loop where difficulty spirals upward.

Root Cause

In miner-apps/jd-client/src/lib/channel_manager/downstream_message_handler.rs at line 972, the vardiff share counter is incremented before share validation:

vardiff.increment_shares_since_last_update();  // Line 972 - BEFORE validation
let res = standard_channel.validate_share(msg.clone());  // Line 973
match res {
    Ok(ShareValidationResult::Valid(share_hash)) => { ... }
    Ok(ShareValidationResult::Invalid(e)) => { ... }
    Err(e) => { ... }
}

This means:

  1. Miner submits a share (even if difficulty is too low to meet the target)
  2. Vardiff counter increments unconditionally
  3. Share validation happens
  4. Share is rejected (doesn't meet target)
  5. Vardiff thinks the share was successful
  6. On next vardiff cycle (60s), it calculates: high share rate → hashrate must be high → increase difficulty
  7. Difficulty increases further, making the problem worse

Expected Behavior

The share counter should only increment for valid shares that pass validation. The increment should move inside the Ok(ShareValidationResult::Valid(...)) block (line 976).

Observed Behavior

  • Vardiff continuously increases difficulty
  • Miner fails to submit shares (difficulty too high)
  • Failed shares still count toward vardiff share rate
  • Difficulty increases further
  • Loop continues until difficulty is impossibly high

Reproduction

  1. Connect a miner to jd-client
  2. Wait for vardiff to increase difficulty beyond miner's capability
  3. Observe miner failing to submit valid shares
  4. Watch vardiff continue to increase difficulty instead of reducing it

Affected Code

File: miner-apps/jd-client/src/lib/channel_manager/downstream_message_handler.rs
Lines: 972 (standard channel), 1188 (extended channel - same issue)

Vardiff logic: stratum/sv2/channels-sv2/src/vardiff/classic.rs
Line 170: When realized_share_per_min == 0.0, it reduces hashrate estimate (easier difficulty), but this never triggers because failed shares still increment the counter.

Suggested Fix

Move vardiff.increment_shares_since_last_update() to after validation succeeds:

let res = standard_channel.validate_share(msg.clone());
let mut is_downstream_share_valid = false;
match res {
    Ok(ShareValidationResult::Valid(share_hash)) => {
        vardiff.increment_shares_since_last_update();  // Only count valid shares
        // ... rest of success handling
    }
    // ... error cases
}

Same fix needed for extended channels at line 1188.

Impact

This bug makes jd-client's vardiff unusable for miners with variable hashrate or when difficulty temporarily exceeds miner capability. Once difficulty gets too high, it never corrects downward.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions