use crate::Id32;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HashRequest {
pub file_root: Id32,
pub base: u32,
pub index: u32,
pub count: u32,
pub proof_layers: u32,
}
pub fn validate_hash_request(
req: &HashRequest,
file_num_blocks: u32,
_file_num_pieces: u32,
) -> bool {
if req.count == 0 || req.count > 8192 {
return false;
}
let num_leafs = file_num_blocks.next_power_of_two();
let num_layers = num_leafs.trailing_zeros() + 1;
if req.base >= num_layers {
return false;
}
let layer_size = num_leafs >> req.base;
if req.index >= layer_size || req.index + req.count > layer_size {
return false;
}
if req.proof_layers >= num_layers - req.base {
return false;
}
true
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Id32;
#[test]
fn valid_request_passes() {
let req = HashRequest {
file_root: Id32::ZERO,
base: 0,
index: 0,
count: 512,
proof_layers: 3,
};
assert!(validate_hash_request(&req, 8192, 512));
}
#[test]
fn reject_count_too_large() {
let req = HashRequest {
file_root: Id32::ZERO,
base: 0,
index: 0,
count: 8193, proof_layers: 0,
};
assert!(!validate_hash_request(&req, 16384, 8192));
}
#[test]
fn reject_index_out_of_range() {
let req = HashRequest {
file_root: Id32::ZERO,
base: 0,
index: 100,
count: 10,
proof_layers: 0,
};
assert!(!validate_hash_request(&req, 64, 4));
}
#[test]
fn reject_zero_count() {
let req = HashRequest {
file_root: Id32::ZERO,
base: 0,
index: 0,
count: 0,
proof_layers: 0,
};
assert!(!validate_hash_request(&req, 64, 4));
}
#[test]
fn piece_layer_request_valid() {
let req = HashRequest {
file_root: Id32::ZERO,
base: 4, index: 0,
count: 32,
proof_layers: 2,
};
assert!(validate_hash_request(&req, 512, 32));
}
}