tasm_lib/hashing/
merkle_step_mem_u64_index.rsuse std::collections::HashMap;
use triton_vm::prelude::*;
use crate::hashing::merkle_step_u64_index::MerkleStepU64Index;
use crate::prelude::*;
use crate::traits::basic_snippet::Reviewer;
use crate::traits::basic_snippet::SignOffFingerprint;
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct MerkleStepMemU64Index;
impl BasicSnippet for MerkleStepMemU64Index {
fn inputs(&self) -> Vec<(DataType, String)> {
vec![
(DataType::VoidPointer, "ram pointer".to_owned()),
(DataType::U64, "merkle tree node index".to_owned()),
(DataType::Digest, "node".to_owned()),
]
}
fn outputs(&self) -> Vec<(DataType, String)> {
vec![
(DataType::VoidPointer, "ram pointer".to_owned()),
(DataType::U64, "merkle tree parent node index".to_owned()),
(DataType::Digest, "parent node".to_owned()),
]
}
fn entrypoint(&self) -> String {
"tasmlib_hashing_merkle_step_mem_u64_index".to_owned()
}
fn code(&self, _: &mut Library) -> Vec<LabelledInstruction> {
triton_asm!(
{self.entrypoint()}:
merkle_step_mem
{&MerkleStepU64Index::make_u64_index_consistent()}
return
)
}
fn sign_offs(&self) -> HashMap<Reviewer, SignOffFingerprint> {
let mut sign_offs = HashMap::new();
sign_offs.insert(Reviewer("ferdinand"), 0xd1c95ceda7a3fa88.into());
sign_offs
}
}
#[cfg(test)]
mod tests {
use std::collections::VecDeque;
use super::*;
use crate::test_prelude::*;
impl MerkleStepMemU64Index {
fn set_up_initial_state(
&self,
ram_ptr: BFieldElement,
leaf_index: u64,
) -> ReadOnlyAlgorithmInitialState {
let mut stack = self.init_stack_for_isolated_run();
push_encodable(&mut stack, &ram_ptr);
push_encodable(&mut stack, &leaf_index);
push_encodable(&mut stack, &rand::random::<Digest>());
let mut nondeterminism = NonDeterminism::default();
encode_to_memory(&mut nondeterminism.ram, ram_ptr, &rand::random::<Digest>());
ReadOnlyAlgorithmInitialState {
stack,
nondeterminism,
}
}
}
impl ReadOnlyAlgorithm for MerkleStepMemU64Index {
fn rust_shadow(
&self,
stack: &mut Vec<BFieldElement>,
memory: &HashMap<BFieldElement, BFieldElement>,
_: VecDeque<BFieldElement>,
_: VecDeque<Digest>,
) {
let stack_digest = pop_encodable::<Digest>(stack);
let leaf_index = pop_encodable::<u64>(stack);
let ram_ptr = pop_encodable::<BFieldElement>(stack);
let stack_digest_is_left_sibling = leaf_index % 2 == 0;
let sibling_digest = *Digest::decode_from_memory(memory, ram_ptr).unwrap();
let (left_digest, right_digest) = if stack_digest_is_left_sibling {
(stack_digest, sibling_digest)
} else {
(sibling_digest, stack_digest)
};
let parent_digest = Tip5::hash_pair(left_digest, right_digest);
let parent_index = leaf_index / 2;
push_encodable(stack, &(ram_ptr + bfe!(Digest::LEN)));
push_encodable(stack, &parent_index);
push_encodable(stack, &parent_digest);
}
fn pseudorandom_initial_state(
&self,
seed: [u8; 32],
bench_case: Option<BenchmarkCase>,
) -> ReadOnlyAlgorithmInitialState {
let mut rng = StdRng::from_seed(seed);
let leaf_index = match bench_case {
Some(BenchmarkCase::CommonCase) => 1 << 33,
Some(BenchmarkCase::WorstCase) => 1 << 63,
None => rng.random(),
};
self.set_up_initial_state(rng.random(), leaf_index)
}
}
#[test]
fn unit() {
ShadowedReadOnlyAlgorithm::new(MerkleStepMemU64Index).test();
}
}
#[cfg(test)]
mod benches {
use super::*;
use crate::test_prelude::*;
#[test]
fn benchmark() {
ShadowedReadOnlyAlgorithm::new(MerkleStepMemU64Index).bench();
}
}