Skip to content

Commit

Permalink
fix: leaves positions and inspection receipt
Browse files Browse the repository at this point in the history
  • Loading branch information
yahortsaryk committed Jan 10, 2025
1 parent 4fe6e60 commit 15a5f74
Show file tree
Hide file tree
Showing 4 changed files with 409 additions and 47 deletions.
93 changes: 93 additions & 0 deletions pallets/ddc-verification/src/aggregate_tree.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
use sp_runtime::ArithmeticError;
use sp_std::{collections::btree_map::BTreeMap, vec::Vec};

pub fn get_node_id(level: u32, node_idx: u64) -> u64 {
2_u64.pow(level) + node_idx
}

pub fn get_leaves_ids(leaves_count: u64) -> Vec<u64> {
let levels = get_levels(leaves_count).expect("Tree levels to be defined");
let leaf_level = levels.last().expect("Leaf level to be defined");
let mut leaf_ids = Vec::new();
for leaf_idx in 0..leaves_count {
leaf_ids.push(get_node_id(*leaf_level, leaf_idx));
}
leaf_ids
}

pub fn get_levels(leaves_count: u64) -> Result<Vec<u32>, &'static str> {
if leaves_count == 0 {
return Err("Tree must have at least one leaf.");
}

// The last level is based on the log2 calculation
let last_level = leaves_count.ilog2();

// If the tree is not a perfect binary tree, we need one more level
if (1 << last_level) < leaves_count {
return Ok((0..=last_level + 1).collect());
}

// If the tree is a perfect binary tree
Ok((0..=last_level).collect())
}

pub const D_099: u64 = 9900; // 0.99 scaled by 10^4
pub const P_001: u64 = 100; // 0.01 scaled by 10^4

pub fn get_n0_values() -> BTreeMap<(u64, u64), u64> {
let mut n0_map = BTreeMap::new();

// Formula: n0 = ln(1 - d) / ln(1 - p)

// todo: add more pairs
n0_map.insert((D_099, P_001), 4582106); // ~458.2106 scaled by 10^4

n0_map
}

pub fn calculate_sample_size_inf(d: u64, p: u64) -> u64 {
let n0_values = get_n0_values();

let n0 = n0_values.get(&(d, p)).expect("Sample size to be defined");
*n0
}

pub fn calculate_sample_size_fin(
n0_scaled: u64,
population_size: u64,
) -> Result<u64, ArithmeticError> {
const SCALE: u64 = 10000; // Reduced scale factor for fixed-point precision (10^4)

// Ensure that population_size > 1 to avoid division by zero or invalid calculations
if population_size <= 1 {
return Err(ArithmeticError::Underflow);
}

// Formula: n = n_0 / (1 + (n_0 - 1) / N)

// First calculate (n0 - 1)
let numerator = n0_scaled
.checked_sub(SCALE) // subtract 1 * SCALE to keep consistent scaling
.ok_or(ArithmeticError::Underflow)?;

// Scale the numerator before dividing to increase precision
let numerator_scaled = numerator.checked_mul(SCALE).ok_or(ArithmeticError::Overflow)?;

// Calculate (n0 - 1) / N using integer division, but scale numerator first
// Population size is unscaled, so we scale it before the division to maintain precision
let population_scaled = population_size.checked_mul(SCALE).ok_or(ArithmeticError::Overflow)?;

let correction_term = numerator_scaled
.checked_div(population_scaled)
.ok_or(ArithmeticError::Underflow)?;

// Now calculate 1 + correction_term, but scale 1 by SCALE to ensure consistency
let denominator = SCALE.checked_add(correction_term).ok_or(ArithmeticError::Overflow)?; // SCALE is used to scale the 1

// Finally calculate n = n0 / denominator, and return the result (floored automatically by
// integer division)
let n = n0_scaled.checked_div(denominator).ok_or(ArithmeticError::Underflow)?;

Ok(n)
}
82 changes: 82 additions & 0 deletions pallets/ddc-verification/src/aggregator_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,15 @@ impl<'a> AggregatorClient<'a> {
.join(",")
}

pub fn send_inspection_receipt(
&self,
receipt: json::InspectionReceipt,
) -> Result<http::Response, http::Error> {
let url = format!("{}/activity/inspection-receipts", self.base_url);
let body = serde_json::to_vec(&receipt).expect("Inspection receipt to be encoded");
self.post(&url, body)
}

fn get(&self, url: &str, accept: Accept) -> Result<http::Response, http::Error> {
let mut maybe_response = None;

Expand Down Expand Up @@ -308,6 +317,51 @@ impl<'a> AggregatorClient<'a> {

Ok(response)
}

fn post(&self, url: &str, request_body: Vec<u8>) -> Result<http::Response, http::Error> {
let mut maybe_response = None;

let deadline = timestamp().add(self.timeout);
let mut error = None;

for _ in 0..self.retries {
let request = http::Request::post(url, vec![request_body.clone()])
.add_header("content-type", "application/json");

let pending = request
.deadline(deadline)
.body(vec![request_body.clone()])
.send()
.map_err(|_| http::Error::IoError)?;

match pending.try_wait(deadline) {
Ok(Ok(r)) => {
maybe_response = Some(r);
error = None;
break;
},
Ok(Err(_)) | Err(_) => {
error = Some(http::Error::DeadlineReached);
continue;
},
}
}

if let Some(e) = error {
return Err(e);
}

let response = match maybe_response {
Some(r) => r,
None => return Err(http::Error::Unknown),
};

if response.code != 200 {
return Err(http::Error::Unknown);
}

Ok(response)
}
}

enum Accept {
Expand Down Expand Up @@ -848,4 +902,32 @@ pub(crate) mod json {
#[serde(rename = "numberOfGets")]
pub number_of_gets: u64,
}

#[derive(Debug, Serialize, Deserialize, Clone, Hash, Encode, Decode)]
pub struct InspectionReceipt {
#[serde(rename = "ehdId")]
pub ehd_id: String,
pub inspector: String,
pub signature: String,
#[serde(rename = "inspectionResult")]
pub inspection_result: InspectionResult,
}

#[derive(Debug, Serialize, Deserialize, Clone, Hash, Encode, Decode)]
pub struct InspectionResult {
#[serde(rename = "unverifiedBranches")]
pub unverified_branches: Vec<PHDTreePart>,
#[serde(rename = "verifiedBranches")]
pub verified_branches: Vec<PHDTreePart>,
}

#[derive(Debug, Serialize, Deserialize, Clone, Hash, Encode, Decode)]
pub struct PHDTreePart {
#[serde(rename = "phdId")]
pub phd_id: String,
#[serde(rename = "nodes")]
pub nodes: Vec<u64>,
#[serde(rename = "leafs")]
pub leafs: BTreeMap<u32, Vec<u64>>,
}
}
Loading

0 comments on commit 15a5f74

Please sign in to comment.