1use steel::*;
2use crate::consts::*;
3use crate::error::*;
4use crate::types::*;
5use brine_tree::{MerkleTree, Leaf};
6
7pub fn check_condition<E>(condition: bool, err: E) -> ProgramResult
9where
10 E: Into<ProgramError>,
11{
12 if !condition {
13 return Err(err.into());
14 }
15 Ok(())
16}
17
18pub fn padded_array<const N: usize>(input: &[u8]) -> [u8; N] {
20 assert!(input.len() <= N, "input too long");
21 let mut out = [0u8; N];
22 out[..input.len()].copy_from_slice(input);
23 out
24}
25
26pub fn to_name(val: &str) -> [u8; MAX_NAME_LEN] {
28 assert!(val.len() <= MAX_NAME_LEN, "name too long");
29 padded_array::<MAX_NAME_LEN>(val.as_bytes())
30}
31
32pub fn from_name(val: &[u8; MAX_NAME_LEN]) -> String {
34 let mut name_bytes = val.to_vec();
35 name_bytes.retain(|&x| x != 0);
36 String::from_utf8(name_bytes).unwrap()
37}
38
39#[inline(always)]
41pub fn compute_leaf(
42 segment_id: u64,
43 chunk_id: u64,
44 chunk: &Chunk
45) -> Leaf {
46 let segment_id = segment_id.to_le_bytes();
47 let chunk_id = chunk_id.to_le_bytes();
48
49 Leaf::new(&[
50 segment_id.as_ref(), chunk_id.as_ref(), chunk.as_bytes(),
53 ])
54
55}
56
57#[inline(always)]
59pub fn write_chunks(
60 tree: &mut MerkleTree<{TREE_HEIGHT}>,
61 segment_id: u64,
62 segment: &Segment,
63) -> ProgramResult {
64 let chunks = segment.chunks();
65 for (chunk_id, chunk) in chunks.enumerate() {
66
67 let leaf = compute_leaf(
68 segment_id,
69 chunk_id as u64,
70 &chunk);
71
72 check_condition(
73 tree.try_add_leaf(leaf).is_ok(),
74 TapeError::WriteFailed,
75 )?;
76 }
77
78 Ok(())
79}
80
81#[inline(always)]
83pub fn compute_recall_tape(
84 challenge: &[u8; 32],
85 total_tapes: u64,
86) -> u64 {
87 if total_tapes == 0 {
89 return 1;
90 }
91
92 (u64::from_le_bytes(challenge[0..8].try_into().unwrap()) % total_tapes)
95 .max(1)
96}
97
98#[inline(always)]
100pub fn compute_recall_segment(
101 challenge: &[u8; 32],
102 total_segments: u64,
103) -> u64 {
104 if total_segments == 0 {
106 return 0;
107 }
108
109 u64::from_le_bytes(challenge[8..16].try_into().unwrap()) % total_segments
110}
111
112#[inline(always)]
114pub fn compute_recall_chunk(
115 challenge: &[u8; 32],
116) -> u64 {
117 u64::from_le_bytes(challenge[16..24].try_into().unwrap()) % MAGIC_NUMBER as u64
118}