use crate::types::Buffer;
use num_bigint::BigUint;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use sha2::{Digest, Sha256};
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct SP1PublicValues {
buffer: Buffer,
}
impl SP1PublicValues {
pub const fn new() -> Self {
Self { buffer: Buffer::new() }
}
pub fn raw(&self) -> String {
format!("0x{}", hex::encode(self.as_slice()))
}
pub fn from(data: &[u8]) -> Self {
Self { buffer: Buffer::from(data) }
}
pub fn as_slice(&self) -> &[u8] {
self.buffer.data.as_slice()
}
pub fn to_vec(&self) -> Vec<u8> {
self.buffer.data.clone()
}
pub fn read<T: Serialize + DeserializeOwned>(&mut self) -> T {
self.buffer.read()
}
pub fn read_slice(&mut self, slice: &mut [u8]) {
self.buffer.read_slice(slice);
}
pub fn write<T: Serialize>(&mut self, data: &T) {
self.buffer.write(data);
}
pub fn write_slice(&mut self, slice: &[u8]) {
self.buffer.write_slice(slice);
}
pub fn hash(&self) -> Vec<u8> {
sha256_hash(self.buffer.data.as_slice())
}
pub fn blake3_hash(&self) -> Vec<u8> {
blake3_hash(self.buffer.data.as_slice())
}
pub fn hash_bn254(&self) -> BigUint {
self.hash_bn254_with_fn(sha256_hash)
}
pub fn hash_bn254_with_fn<F>(&self, hasher: F) -> BigUint
where
F: Fn(&[u8]) -> Vec<u8>,
{
let mut hash = hasher(self.buffer.data.as_slice());
hash[0] &= 0b00011111;
BigUint::from_bytes_be(hash.as_slice())
}
}
impl AsRef<[u8]> for SP1PublicValues {
fn as_ref(&self) -> &[u8] {
&self.buffer.data
}
}
pub fn sha256_hash(input: &[u8]) -> Vec<u8> {
let mut hasher = Sha256::new();
hasher.update(input);
hasher.finalize().to_vec()
}
pub fn blake3_hash(input: &[u8]) -> Vec<u8> {
blake3::hash(input).as_bytes().to_vec()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_hash_public_values() {
let test_hex = "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef";
let test_bytes = hex::decode(test_hex).unwrap();
let mut public_values = SP1PublicValues::new();
public_values.write_slice(&test_bytes);
let hash = public_values.hash_bn254();
let expected_hash = "1ce987d0a7fcc2636fe87e69295ba12b1cc46c256b369ae7401c51b805ee91bd";
let expected_hash_biguint = BigUint::from_bytes_be(&hex::decode(expected_hash).unwrap());
assert_eq!(hash, expected_hash_biguint);
}
#[test]
fn test_hash_public_values_blake3() {
let test_hex = "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef";
let test_bytes = hex::decode(test_hex).unwrap();
let mut public_values = SP1PublicValues::new();
public_values.write_slice(&test_bytes);
let hash = public_values.hash_bn254_with_fn(blake3_hash);
let expected_hash = "1639647ab9e42519f0cbdcf343033482b018c0c1ed48f8367f32381c60913447";
let expected_hash_biguint = BigUint::from_bytes_be(&hex::decode(expected_hash).unwrap());
assert_eq!(hash, expected_hash_biguint);
}
}