Skip to content

Commit

Permalink
style(hash_from_stack): Tidy up various things
Browse files Browse the repository at this point in the history
- Hide implementation details, like struct fields.
- Move panics to struct creation, remove from code generation.
- Add documentation. Most crucially, document panic conditions.
- Eagerly derive trait implementations like `Debug` and `Clone`.
- Use preludes. Notably, in test modules: `use crate::test_prelude::*`
- In an `impl Trait`, use same member order as in trait's definition.

changelog: ignore
  • Loading branch information
jan-ferdinand committed Jan 6, 2025
1 parent 9ba83df commit 30ff514
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 100 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
{
"name": "tasmlib_hashing_hash_from_stack___bfe",
"benchmark_result": {
"clock_cycle_count": 34,
"hash_table_height": 55,
"clock_cycle_count": 30,
"hash_table_height": 49,
"u32_table_height": 0,
"op_stack_table_height": 34,
"ram_table_height": 0
Expand All @@ -13,8 +13,8 @@
{
"name": "tasmlib_hashing_hash_from_stack___bfe",
"benchmark_result": {
"clock_cycle_count": 34,
"hash_table_height": 55,
"clock_cycle_count": 30,
"hash_table_height": 49,
"u32_table_height": 0,
"op_stack_table_height": 34,
"ram_table_height": 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
{
"name": "tasmlib_hashing_hash_from_stack___digest",
"benchmark_result": {
"clock_cycle_count": 26,
"hash_table_height": 43,
"clock_cycle_count": 22,
"hash_table_height": 37,
"u32_table_height": 0,
"op_stack_table_height": 30,
"ram_table_height": 0
Expand All @@ -13,8 +13,8 @@
{
"name": "tasmlib_hashing_hash_from_stack___digest",
"benchmark_result": {
"clock_cycle_count": 26,
"hash_table_height": 43,
"clock_cycle_count": 22,
"hash_table_height": 37,
"u32_table_height": 0,
"op_stack_table_height": 30,
"ram_table_height": 0
Expand Down
151 changes: 59 additions & 92 deletions tasm-lib/src/hashing/hash_from_stack.rs
Original file line number Diff line number Diff line change
@@ -1,86 +1,75 @@
use triton_vm::isa::triton_asm;
use triton_vm::prelude::LabelledInstruction;
use triton_vm::prelude::Tip5;
use triton_vm::twenty_first::prelude::Sponge;
use triton_vm::prelude::*;
use twenty_first::prelude::*;

use crate::data_type::DataType;
use crate::library::Library;
use crate::prelude::BasicSnippet;
use crate::prelude::*;

#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct HashFromStack {
pub data_type: DataType,
ty: DataType,
ty_len: usize,
}

impl HashFromStack {
/// # Panics
///
/// Panics if the argument does not have statically-known length, or if that
/// length is larger than or equal to [`Tip5::RATE`].
pub fn new(ty: DataType) -> Self {
let ty_len = ty
.static_length()
.expect("data type to hash should have static length");
assert!(ty_len < Tip5::RATE, "type length should be small");

Self { ty, ty_len }
}
}

impl BasicSnippet for HashFromStack {
fn inputs(&self) -> Vec<(DataType, String)> {
vec![(self.data_type.clone(), "preimage".to_string())]
vec![(self.ty.clone(), "preimage".to_string())]
}

fn outputs(&self) -> Vec<(DataType, String)> {
vec![(DataType::Digest, "digest".to_string())]
}

fn entrypoint(&self) -> String {
format!(
"tasmlib_hashing_hash_from_stack___{}",
self.data_type.label_friendly_name()
self.ty.label_friendly_name()
)
}

fn code(&self, _library: &mut Library) -> Vec<LabelledInstruction> {
let preimage_size = self.data_type.stack_size();
let size = self
.data_type
.static_length()
.expect("Can only hash static-length data types from stack");
assert_eq!(
size, preimage_size,
"Can only hash types that live on stack"
);
assert!(
preimage_size < Tip5::RATE,
"This snippet assumes small preimage size"
);

let num_zeros_in_pad = Tip5::RATE - preimage_size - 1;
let zero_padding = triton_asm!(
fn code(&self, _: &mut Library) -> Vec<LabelledInstruction> {
let pad_single_zero = triton_asm!(
push 0
place {preimage_size}
place {self.ty_len}
);

// _ val 0

// _ 0 val
let zero_padding = vec![zero_padding; num_zeros_in_pad].concat();
let one_pad = triton_asm!(
push 1
place {preimage_size}
);

let pad = triton_asm!(
// _ [preimage: data_type]
{&zero_padding}
{&one_pad}

// _ [0, 0..0] 1 [preimage]
);
let num_zeros_in_pad = Tip5::RATE - self.ty_len - 1;
let pad_zeros = vec![pad_single_zero; num_zeros_in_pad].concat();

let entrypoint = self.entrypoint();
triton_asm!(
{entrypoint}:

{&pad}
{&pad_zeros}
// _ [0, …, 0] [preimage]

push 1
place {self.ty_len}
// _ [0, …, 0] 1 [preimage]
// _ [padded-preimage]

sponge_init
sponge_absorb
sponge_squeeze

pick 5 pop 1
pick 5 pop 1
pick 5 pop 1
pick 5 pop 1
pick 5 pop 1
pick 9
pick 9
pick 9
pick 9
pick 9
pop 5

return
)
Expand All @@ -89,49 +78,36 @@ impl BasicSnippet for HashFromStack {

#[cfg(test)]
mod tests {
use rand::rngs::StdRng;
use rand::SeedableRng;
use triton_vm::prelude::BFieldElement;

use super::*;
use crate::push_encodable;
use crate::snippet_bencher::BenchmarkCase;
use crate::traits::closure::Closure;
use crate::traits::closure::ShadowedClosure;
use crate::traits::rust_shadow::RustShadow;
use crate::test_prelude::*;

impl Closure for HashFromStack {
fn rust_shadow(&self, stack: &mut Vec<triton_vm::prelude::BFieldElement>) {
type Args = Vec<BFieldElement>;

fn rust_shadow(&self, stack: &mut Vec<BFieldElement>) {
let mut preimage = vec![];
for _ in 0..self.data_type.stack_size() {
for _ in 0..self.ty_len {
preimage.push(stack.pop().unwrap());
}

let digest = Tip5::hash_varlen(&preimage);

push_encodable(stack, &digest);
push_encodable(stack, &Tip5::hash_varlen(&preimage));
}

type Args = Vec<BFieldElement>;

fn pseudorandom_args(&self, seed: [u8; 32], _: Option<BenchmarkCase>) -> Self::Args {
let mut rng = StdRng::from_seed(seed);

self.data_type.seeded_random_element(&mut rng)
self.ty.seeded_random_element(&mut StdRng::from_seed(seed))
}

fn set_up_test_stack(&self, args: Self::Args) -> Vec<BFieldElement> {
let mut stack = self.init_stack_for_isolated_run();
for b in args.iter().rev() {
stack.push(*b);
}
stack.extend(args.into_iter().rev());

stack
}
}

#[test]
fn hash_from_stack_pbt() {
let primitives = [
fn unit() {
let types = [
DataType::Bool,
DataType::U32,
DataType::U64,
Expand All @@ -140,31 +116,22 @@ mod tests {
DataType::Xfe,
DataType::Digest,
];
for data_type in primitives {
ShadowedClosure::new(HashFromStack { data_type }).test();
for data_type in types {
ShadowedClosure::new(HashFromStack::new(data_type)).test();
}
}
}

#[cfg(test)]
mod benches {
use super::*;
use crate::traits::closure::ShadowedClosure;
use crate::traits::rust_shadow::RustShadow;
use crate::test_prelude::*;

#[test]
fn hash_from_stack_bench_bfe() {
ShadowedClosure::new(HashFromStack {
data_type: DataType::Bfe,
})
.bench()
}

#[test]
fn hash_from_stack_bench_digest() {
ShadowedClosure::new(HashFromStack {
data_type: DataType::Digest,
})
.bench()
fn benchmark() {
let types = [DataType::Bfe, DataType::Digest];
for data_type in types {
ShadowedClosure::new(HashFromStack::new(data_type)).bench();
}
}
}

0 comments on commit 30ff514

Please sign in to comment.