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
3 changes: 2 additions & 1 deletion src/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod utils;
pub mod utils;
pub mod validation;

mod state;
mod main;
35 changes: 34 additions & 1 deletion src/validation.cairo
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::utils::{shl, shr};
use super::state::{Block, ChainState, Transaction, UtreexoState};
use super::utils::{shl, shr};

const MAX_TARGET: u256 = 0x00000000FFFF0000000000000000000000000000000000000000000000000000;

Expand Down Expand Up @@ -106,6 +106,39 @@ fn validate_merkle_root(self: @ChainState, block: @Block) -> Result<(), ByteArra
Result::Ok(())
}

// Helper functions
pub fn bits_to_target(bits: u32) -> Result<u256, felt252> {
// 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 {
// Special case: exponent 0 means we use the mantissa as-is
return Result::Ok(target);
} else if exponent <= 3 {
// For exponents 1, 2, and 3, divide by 256^(3 - exponent) i.e right shift
let shift = 8 * (3 - exponent);
target = shr(target, shift);
} else {
let shift = 8 * (exponent - 3);
target = shl(target, shift);
}

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

Result::Ok(target)
}

pub fn target_to_bits(target: u256) -> Result<u32, felt252> {
if target == 0 {
Expand Down
76 changes: 76 additions & 0 deletions tests/tests.cairo
Original file line number Diff line number Diff line change
@@ -1,5 +1,81 @@
use raito::validation::bits_to_target;
use raito::validation::target_to_bits;

#[test]
fn test_bits_to_target_01003456() {
let result = bits_to_target(0x01003456);
assert!(result.is_ok(), "Should be valid");
assert!(result.unwrap() == 0x00_u256, "Incorrect target for 0x01003456");
}

#[test]
fn test_bits_to_target_01123456() {
let result = bits_to_target(0x01123456);
assert!(result.is_ok(), "Should be valid");
assert!(result.unwrap() == 0x12_u256, "Incorrect target for 0x01123456");
}

#[test]
fn test_bits_to_target_02008000() {
let result = bits_to_target(0x02008000);
assert!(result.is_ok(), "Should be valid");
assert!(result.unwrap() == 0x80_u256, "Incorrect target for 0x02008000");
}

#[test]
fn test_bits_to_target_181bc330() {
let result = bits_to_target(0x181bc330);
assert!(result.is_ok(), "Should be valid");
assert!(
result.unwrap() == 0x1bc330000000000000000000000000000000000000000000_u256,
"Incorrect target for 0x181bc330"
);
}

#[test]
fn test_bits_to_target_05009234() {
let result = bits_to_target(0x05009234);
assert!(result.is_ok(), "Should be valid");
assert!(result.unwrap() == 0x92340000_u256, "Incorrect target for 0x05009234");
}

#[test]
fn test_bits_to_target_04123456() {
let result = bits_to_target(0x04123456);
assert!(result.is_ok(), "Should be valid");
assert!(result.unwrap() == 0x12345600_u256, "Incorrect target for 0x04123456");
}

#[test]
fn test_bits_to_target_1d00ffff() {
let result = bits_to_target(0x1d00ffff);
assert!(result.is_ok(), "Should be valid");
assert!(
result.unwrap() == 0x00000000ffff0000000000000000000000000000000000000000000000000000_u256,
"Incorrect target for 0x1d00ffff"
);
}

#[test]
fn test_bits_to_target_1c0d3142() {
let result = bits_to_target(0x1c0d3142);
assert!(result.is_ok(), "Should be valid");
assert!(
result.unwrap() == 0x000000000d314200000000000000000000000000000000000000000000000000_u256,
"Incorrect target for 0x1c0d3142"
);
}

#[test]
fn test_bits_to_target_1707a429() {
let result = bits_to_target(0x1707a429);
assert!(result.is_ok(), "Should be valid");
assert!(
result.unwrap() == 0x00000000000000000007a4290000000000000000000000000000000000000000_u256,
"Incorrect target for 0x1707a429"
);
}

#[test]
fn test_target_to_bits_large_target() {
let target: u256 = 0x1bc330000000000000000000000000000000000000000000;
Expand Down