Skip to content

Commit

Permalink
daemon: new difficulty adjustement algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
Slixe committed Jan 22, 2024
1 parent 8d99c17 commit 51dc9cc
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 2 deletions.
2 changes: 1 addition & 1 deletion xelis_daemon/src/core/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -955,7 +955,7 @@ impl<S: Storage> Blockchain<S> {
let parent_best_tip = blockdag::find_best_tip_by_cumulative_difficulty(provider, parent_tips.iter()).await?;
let parent_best_tip_timestamp = provider.get_timestamp_for_block_hash(parent_best_tip).await?;

let difficulty = calculate_difficulty(parent_best_tip_timestamp, best_tip_timestamp, biggest_difficulty);
let difficulty = calculate_difficulty(tips.len() as u64, parent_best_tip_timestamp, best_tip_timestamp, biggest_difficulty);
Ok(difficulty)
}

Expand Down
39 changes: 38 additions & 1 deletion xelis_daemon/src/core/difficulty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const FACTOR: i64 = 10000;
// Calculate the difficulty for the next block
// Difficulty jump can happen easily but drop is limited to 2x the block time
// This is to prevent any attack on the difficulty where a miner would try to manipulate the network
pub fn calculate_difficulty(parent_timestamp: u128, new_timestamp: u128, previous_difficulty: Difficulty) -> Difficulty {
pub fn calculate_difficulty_v1(parent_timestamp: u128, new_timestamp: u128, previous_difficulty: Difficulty) -> Difficulty {
let mut solve_time = (new_timestamp - parent_timestamp) as f64;

// Limit to 2x the block time to prevent any too-big difficulty drop
Expand All @@ -28,4 +28,41 @@ pub fn calculate_difficulty(parent_timestamp: u128, new_timestamp: u128, previou
}

diff
}

const DIFFICULTY_BOUND_DIVISOR: u64 = 2048;
const CHAIN_TIME_RANGE: u64 = BLOCK_TIME_MILLIS * 2 / 3;

// Difficulty algorithm from Ethereum: Homestead but tweaked for our needs
pub fn calculate_difficulty(tips_count: u64, parent_timestamp: u128, new_timestamp: u128, previous_difficulty: Difficulty) -> Difficulty {
let mut adjust = previous_difficulty / DIFFICULTY_BOUND_DIVISOR;
let mut x = (new_timestamp - parent_timestamp) as u64 / CHAIN_TIME_RANGE;
trace!("x: {x}, tips count: {tips_count}, adjust: {adjust}");
let neg = x >= tips_count;
if x == 0 {
x = x - tips_count;
} else {
x = tips_count - x;
}

// max(x, 99)
if x > 99 {
x = 99;
}

// Compute the new diff based on the adjustement
adjust = adjust * x;
let new_diff = if neg {
previous_difficulty - adjust
} else {
previous_difficulty + adjust
};

trace!("previous diff: {} new diff: {}", previous_difficulty, new_diff);

if new_diff < MINIMUM_DIFFICULTY {
return MINIMUM_DIFFICULTY
}

new_diff
}

0 comments on commit 51dc9cc

Please sign in to comment.