sp1_hypercube/verifier/
hashable_key.rs1use std::borrow::Borrow;
2
3use serde::{Deserialize, Serialize};
4pub use slop_algebra::PrimeField32;
5use slop_algebra::{AbstractField, PrimeField};
6use slop_bn254::Bn254Fr;
7use slop_challenger::IopCtx;
8use sp1_primitives::{poseidon2_hash, SP1Field, SP1GlobalContext};
9
10use crate::{MachineVerifyingKey, DIGEST_SIZE};
11
12#[derive(Clone, Serialize, Deserialize)]
14pub struct SP1VerifyingKey {
15 pub vk: MachineVerifyingKey<SP1GlobalContext>,
18}
19
20#[must_use]
23pub fn koalabears_to_bn254(digest: &[SP1Field; 8]) -> Bn254Fr {
24 let mut result = Bn254Fr::zero();
25 for word in digest.iter() {
26 result *= Bn254Fr::from_canonical_u64(1 << 31);
29 result += Bn254Fr::from_canonical_u32(word.as_canonical_u32());
30 }
31 result
32}
33
34#[must_use]
36pub fn words_to_bytes_be(words: &[u32; 8]) -> [u8; 32] {
37 let mut bytes = [0u8; 32];
38 for i in 0..8 {
39 let word_bytes = words[i].to_be_bytes();
40 bytes[i * 4..(i + 1) * 4].copy_from_slice(&word_bytes);
41 }
42 bytes
43}
44
45pub trait HashableKey {
47 fn hash_koalabear(&self) -> [SP1Field; DIGEST_SIZE];
49
50 fn hash_u32(&self) -> [u32; DIGEST_SIZE];
52
53 fn hash_bn254(&self) -> Bn254Fr {
55 koalabears_to_bn254(&self.hash_koalabear())
56 }
57
58 fn bytes32(&self) -> String {
62 let vkey_digest_bn254 = self.hash_bn254();
63 format!("0x{:0>64}", vkey_digest_bn254.as_canonical_biguint().to_str_radix(16))
64 }
65
66 fn bytes32_raw(&self) -> [u8; 32] {
70 let vkey_digest_bn254 = self.hash_bn254();
71 let vkey_bytes = vkey_digest_bn254.as_canonical_biguint().to_bytes_be();
72 let mut result = [0u8; 32];
73 result[1..].copy_from_slice(&vkey_bytes);
74 result
75 }
76
77 fn hash_bytes(&self) -> [u8; DIGEST_SIZE * 4] {
79 words_to_bytes_be(&self.hash_u32())
80 }
81
82 fn hash_u64(&self) -> [u64; DIGEST_SIZE / 2] {
84 self.hash_u32()
85 .as_chunks::<2>()
86 .0
87 .iter()
88 .map(|chunk| chunk[0] as u64 | ((chunk[1] as u64) << 32))
89 .collect::<Vec<_>>()
90 .try_into()
91 .unwrap()
92 }
93}
94
95impl HashableKey for SP1VerifyingKey {
96 fn hash_koalabear(&self) -> [SP1Field; DIGEST_SIZE] {
97 self.vk.hash_koalabear()
98 }
99
100 fn hash_u32(&self) -> [u32; DIGEST_SIZE] {
101 self.vk.hash_u32()
102 }
103}
104
105impl<GC: IopCtx<F = SP1Field>> HashableKey for MachineVerifyingKey<GC>
106where
107 GC::Digest: Borrow<[SP1Field; DIGEST_SIZE]>,
108{
109 fn hash_koalabear(&self) -> [SP1Field; DIGEST_SIZE] {
110 #[cfg(not(feature = "mprotect"))]
111 let num_inputs = DIGEST_SIZE + 3 + 14 + 1;
112 #[cfg(feature = "mprotect")]
113 let num_inputs = DIGEST_SIZE + 3 + 14 + 1 + 1 + 9 + 6;
114 let mut inputs = Vec::with_capacity(num_inputs);
115 inputs.extend(self.preprocessed_commit.borrow());
116 inputs.extend(self.pc_start);
117 inputs.extend(self.initial_global_cumulative_sum.0.x.0);
118 inputs.extend(self.initial_global_cumulative_sum.0.y.0);
119 inputs.push(self.untrusted_config.enable_untrusted_programs);
120 #[cfg(feature = "mprotect")]
121 inputs.push(self.untrusted_config.enable_trap_handler);
122 #[cfg(feature = "mprotect")]
123 inputs.extend(self.untrusted_config.trap_context.as_flattened());
124 #[cfg(feature = "mprotect")]
125 inputs.extend(self.untrusted_config.untrusted_memory.as_flattened());
126
127 poseidon2_hash(inputs)
128 }
129
130 fn hash_u32(&self) -> [u32; 8] {
131 self.hash_koalabear()
132 .into_iter()
133 .map(|n| n.as_canonical_u32())
134 .collect::<Vec<_>>()
135 .try_into()
136 .unwrap()
137 }
138}