Skip to main content

sp1_primitives/
io.rs

1use crate::types::Buffer;
2use alloc::{format, string::String, vec::Vec};
3use num_bigint::BigUint;
4use serde::{de::DeserializeOwned, Deserialize, Serialize};
5use sha2::{Digest, Sha256};
6
7/// Public values for the prover.
8#[derive(Debug, Clone, Serialize, Deserialize, Default)]
9pub struct SP1PublicValues {
10    buffer: Buffer,
11}
12
13impl SP1PublicValues {
14    /// Create a new `SP1PublicValues`.
15    pub const fn new() -> Self {
16        Self { buffer: Buffer::new() }
17    }
18
19    pub fn raw(&self) -> String {
20        format!("0x{}", hex::encode(self.as_slice()))
21    }
22
23    /// Create a `SP1PublicValues` from a slice of bytes.
24    pub fn from(data: &[u8]) -> Self {
25        Self { buffer: Buffer::from(data) }
26    }
27
28    pub fn as_slice(&self) -> &[u8] {
29        self.buffer.data.as_slice()
30    }
31
32    pub fn to_vec(&self) -> Vec<u8> {
33        self.buffer.data.clone()
34    }
35
36    /// Read a value from the buffer.    
37    pub fn read<T: Serialize + DeserializeOwned>(&mut self) -> T {
38        self.buffer.read()
39    }
40
41    /// Read a slice of bytes from the buffer.
42    pub fn read_slice(&mut self, slice: &mut [u8]) {
43        self.buffer.read_slice(slice);
44    }
45
46    /// Write a value to the buffer.
47    pub fn write<T: Serialize>(&mut self, data: &T) {
48        self.buffer.write(data);
49    }
50
51    /// Write a slice of bytes to the buffer.
52    pub fn write_slice(&mut self, slice: &[u8]) {
53        self.buffer.write_slice(slice);
54    }
55
56    /// Hash the public values using SHA256.
57    pub fn hash(&self) -> Vec<u8> {
58        sha256_hash(self.buffer.data.as_slice())
59    }
60
61    /// Hash the public values using Blake3.
62    pub fn blake3_hash(&self) -> Vec<u8> {
63        blake3_hash(self.buffer.data.as_slice())
64    }
65
66    /// Hash the public values using SHA256, mask the top 3 bits and return a BigUint.
67    /// Matches the implementation of `hashPublicValues` in the Solidity verifier.
68    ///
69    /// ```solidity
70    /// sha256(publicValues) & bytes32(uint256((1 << 253) - 1));
71    /// ```
72    pub fn hash_bn254(&self) -> BigUint {
73        self.hash_bn254_with_fn(sha256_hash)
74    }
75
76    /// Hash the public values using the provided `hasher` function, mask the top 3 bits and
77    /// return a BigUint.
78    pub fn hash_bn254_with_fn<F>(&self, hasher: F) -> BigUint
79    where
80        F: Fn(&[u8]) -> Vec<u8>,
81    {
82        // Hash the public values.
83        let mut hash = hasher(self.buffer.data.as_slice());
84
85        // Mask the top 3 bits.
86        hash[0] &= 0b00011111;
87
88        // Return the masked hash as a BigUint.
89        BigUint::from_bytes_be(hash.as_slice())
90    }
91}
92
93impl AsRef<[u8]> for SP1PublicValues {
94    fn as_ref(&self) -> &[u8] {
95        &self.buffer.data
96    }
97}
98
99/// Hash the input using SHA256.
100pub fn sha256_hash(input: &[u8]) -> Vec<u8> {
101    let mut hasher = Sha256::new();
102    hasher.update(input);
103    hasher.finalize().to_vec()
104}
105
106/// Hash the input using Blake3.
107pub fn blake3_hash(input: &[u8]) -> Vec<u8> {
108    blake3::hash(input).as_bytes().to_vec()
109}
110
111#[cfg(test)]
112mod tests {
113    use super::*;
114
115    #[test]
116    fn test_hash_public_values() {
117        let test_hex = "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef";
118        let test_bytes = hex::decode(test_hex).unwrap();
119
120        let mut public_values = SP1PublicValues::new();
121        public_values.write_slice(&test_bytes);
122        let hash = public_values.hash_bn254();
123
124        let expected_hash = "1ce987d0a7fcc2636fe87e69295ba12b1cc46c256b369ae7401c51b805ee91bd";
125        let expected_hash_biguint = BigUint::from_bytes_be(&hex::decode(expected_hash).unwrap());
126
127        assert_eq!(hash, expected_hash_biguint);
128    }
129
130    #[test]
131    fn test_hash_public_values_blake3() {
132        let test_hex = "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef";
133        let test_bytes = hex::decode(test_hex).unwrap();
134
135        let mut public_values = SP1PublicValues::new();
136        public_values.write_slice(&test_bytes);
137        let hash = public_values.hash_bn254_with_fn(blake3_hash);
138
139        let expected_hash = "1639647ab9e42519f0cbdcf343033482b018c0c1ed48f8367f32381c60913447";
140        let expected_hash_biguint = BigUint::from_bytes_be(&hex::decode(expected_hash).unwrap());
141
142        assert_eq!(hash, expected_hash_biguint);
143    }
144}