use openvm_cuda_common::{d_buffer::DeviceBuffer, error::CudaError, stream::cudaStream_t};
use crate::prelude::{Digest, EF, F};
pub(super) const MAX_MERKLE_LOG_ROWS_PER_QUERY: usize = 10;
const MAX_CUDA_GRID_Y: usize = u16::MAX as usize;
pub(super) fn validate_merkle_log_rows_per_query(
log_rows_per_query: usize,
) -> Result<(), CudaError> {
if log_rows_per_query > MAX_MERKLE_LOG_ROWS_PER_QUERY {
return Err(CudaError::new(1));
}
Ok(())
}
extern "C" {
fn _poseidon2_compressing_row_hashes(
out: *mut Digest,
matrix: *const F,
width: usize,
query_stride: usize,
log_rows_per_query: usize,
stream: cudaStream_t,
) -> i32;
fn _poseidon2_compressing_row_hashes_ext(
out: *mut Digest,
matrix: *const EF,
width: usize,
query_stride: usize,
log_rows_per_query: usize,
stream: cudaStream_t,
) -> i32;
fn _poseidon2_strided_compress_layer(
output: *mut Digest,
prev_layer: *const Digest,
output_size: usize,
stride: usize,
stream: cudaStream_t,
) -> i32;
fn _poseidon2_adjacent_compress_layer(
output: *mut Digest,
prev_layer: *const Digest,
output_size: usize,
stream: cudaStream_t,
) -> i32;
fn _query_digest_layers(
d_digest_matrix: *mut F,
d_layers_ptr: *const u64,
d_indices: *const u64,
num_query: u64,
num_layer: u64,
stream: cudaStream_t,
) -> i32;
}
pub unsafe fn poseidon2_compressing_row_hashes(
out: &mut DeviceBuffer<Digest>,
matrix: &DeviceBuffer<F>,
width: usize,
query_stride: usize,
log_rows_per_query: usize,
stream: cudaStream_t,
) -> Result<(), CudaError> {
validate_merkle_log_rows_per_query(log_rows_per_query)?;
debug_assert!(matrix.len() >= width * (query_stride << log_rows_per_query));
debug_assert!(out.len() >= query_stride);
CudaError::from_result(_poseidon2_compressing_row_hashes(
out.as_mut_ptr(),
matrix.as_ptr(),
width,
query_stride,
log_rows_per_query,
stream,
))
}
pub unsafe fn poseidon2_compressing_row_hashes_ext(
out: &mut DeviceBuffer<Digest>,
matrix: &DeviceBuffer<EF>,
width: usize,
query_stride: usize,
log_rows_per_query: usize,
stream: cudaStream_t,
) -> Result<(), CudaError> {
validate_merkle_log_rows_per_query(log_rows_per_query)?;
debug_assert!(matrix.len() >= width * (query_stride << log_rows_per_query));
debug_assert!(out.len() >= query_stride);
CudaError::from_result(_poseidon2_compressing_row_hashes_ext(
out.as_mut_ptr(),
matrix.as_ptr(),
width,
query_stride,
log_rows_per_query,
stream,
))
}
pub unsafe fn poseidon2_strided_compress_layer(
output: &mut DeviceBuffer<Digest>,
prev_layer: &DeviceBuffer<Digest>,
output_size: usize,
stride: usize,
stream: cudaStream_t,
) -> Result<(), CudaError> {
debug_assert!(stride > 0 && stride <= output_size);
debug_assert!(output.len() >= output_size);
debug_assert!(prev_layer.len() >= output_size * 2);
CudaError::from_result(_poseidon2_strided_compress_layer(
output.as_mut_ptr(),
prev_layer.as_ptr(),
output_size,
stride,
stream,
))
}
pub unsafe fn poseidon2_adjacent_compress_layer(
output: &mut DeviceBuffer<Digest>,
prev_layer: &DeviceBuffer<Digest>,
output_size: usize,
stream: cudaStream_t,
) -> Result<(), CudaError> {
debug_assert!(output.len() >= output_size);
debug_assert!(prev_layer.len() >= output_size * 2);
CudaError::from_result(_poseidon2_adjacent_compress_layer(
output.as_mut_ptr(),
prev_layer.as_ptr(),
output_size,
stream,
))
}
pub unsafe fn query_digest_layers(
d_digest_matrix: &mut DeviceBuffer<F>,
d_layers_ptr: &DeviceBuffer<u64>,
d_indices: &DeviceBuffer<u64>,
num_query: usize,
num_layer: usize,
stream: cudaStream_t,
) -> Result<(), CudaError> {
if num_query == 0 || num_layer == 0 {
return Ok(());
}
if num_query > MAX_CUDA_GRID_Y {
return Err(CudaError::new(1));
}
CudaError::from_result(_query_digest_layers(
d_digest_matrix.as_mut_ptr(),
d_layers_ptr.as_ptr(),
d_indices.as_ptr(),
num_query as u64,
num_layer as u64,
stream,
))
}