Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add bits_to_target #15

Merged
merged 11 commits into from
Aug 8, 2024
64 changes: 62 additions & 2 deletions src/engine.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ pub impl BlockHeaderEngineImpl of BlockHeaderEngineTrait {
}

fn validate_target(ref self: BlockHeaderEngine) -> Result<(), felt252> {
let target = bits_to_target(self.context.block_header.bits)?;
if self.context.target != target {
return Result::Err('Invalid target');
}
Result::Ok(())
}

Expand Down Expand Up @@ -164,8 +168,40 @@ pub impl BlockHeaderEngineImpl of BlockHeaderEngineTrait {
}

// Helper functions
fn bits_to_target(bits: u32) -> u256 {
0
pub fn bits_to_target(bits: u32) -> Result<u256, felt252> {
harsh-ps-2003 marked this conversation as resolved.
Show resolved Hide resolved
// Extract exponent and mantissa
let exponent: u32 = (bits / 0x1000000);
let mantissa: u32 = bits & 0x00FFFFFF;

// Check if mantissa is valid (should be less than 0x1000000)
if mantissa > 0x7FFFFF && exponent != 0 {
return Result::Err('Invalid mantissa');
}

// Calculate the full target value
let mut target: u256 = mantissa.into();

if exponent == 0 || exponent == 1 {
return Result::Ok(target);
} else if exponent <= 3 {
let shift = 8 * (3 - exponent);
let divisor = u256_pow(256, shift / 8);
target = target / divisor;
} else {
// Check for potential overflow
let shift = 8 * (exponent - 3);
if shift >= 256 {
return Result::Err('Exponent too large');
}
target = target * u256_pow(256, shift / 8);
}

// Ensure the target doesn't exceed the maximum allowed value
if target > MAX_TARGET {
return Result::Err('Target exceeds maximum');
}

Result::Ok(target)
}

fn target_to_bits(target: u256) -> u32 {
Expand All @@ -179,3 +215,27 @@ fn compute_work_from_target(target: u256) -> u256 {
fn compute_timestamps_median(timestamps: Span<u32>) -> u32 {
0
}

// Custom power function for u256
fn u256_pow(base: u256, exp: u32) -> u256 {
if exp == 0 {
return 1.into();
}
if base == 2.into() {
return 1.into() * (2.into() * u256_pow(2, exp - 1));
}
let mut result: u256 = 1.into();
let mut base = base;
let mut exp = exp;
loop {
if exp & 1 != 0 {
result = result * base;
}
exp = exp / 2;
if exp == 0 {
break;
}
base = base * base;
};
result
}