sp1_recursion_circuit/
utils.rs1use slop_algebra::{AbstractField, PrimeField32};
2use slop_bn254::Bn254Fr;
3use sp1_primitives::SP1Field;
4
5use sp1_recursion_compiler::ir::{Builder, Config, Felt, Var};
6use sp1_recursion_executor::DIGEST_SIZE;
7
8pub fn koalabears_proof_nonce_to_bn254(nonce: &[SP1Field; 4]) -> Bn254Fr {
9 let mut result = Bn254Fr::zero();
10 for word in nonce.iter() {
11 result *= Bn254Fr::from_canonical_u64(1 << 31);
14 result += Bn254Fr::from_canonical_u32(word.as_canonical_u32());
15 }
16 result
17}
18
19pub fn koalabear_bytes_to_bn254(bytes: &[SP1Field; 32]) -> Bn254Fr {
22 let mut result = Bn254Fr::zero();
23 for (i, byte) in bytes.iter().enumerate() {
24 debug_assert!(byte < &SP1Field::from_canonical_u32(256));
25 if i == 0 {
26 result = Bn254Fr::from_canonical_u32(byte.as_canonical_u32() & 0x1f);
28 } else {
29 result *= Bn254Fr::from_canonical_u32(256);
30 result += Bn254Fr::from_canonical_u32(byte.as_canonical_u32());
31 }
32 }
33 result
34}
35
36pub fn felts_to_bn254_var<C: Config>(
37 builder: &mut Builder<C>,
38 digest: &[Felt<SP1Field>; DIGEST_SIZE],
39) -> Var<C::N> {
40 let var_2_31: Var<_> = builder.constant(C::N::from_canonical_u32(1 << 31));
41 let result = builder.constant(C::N::zero());
42 for (i, word) in digest.iter().enumerate() {
43 let word_var = builder.felt2var_circuit(*word);
44 if i == 0 {
45 builder.assign(result, word_var);
46 } else {
47 builder.assign(result, result * var_2_31 + word_var);
48 }
49 }
50 result
51}
52
53pub fn felt_proof_nonce_to_bn254_var<C: Config>(
54 builder: &mut Builder<C>,
55 nonce: &[Felt<SP1Field>; 4],
56) -> Var<C::N> {
57 let var_2_31: Var<_> = builder.constant(C::N::from_canonical_u32(1 << 31));
58 let result = builder.constant(C::N::zero());
59 for (i, word) in nonce.iter().enumerate() {
60 let word_var = builder.felt2var_circuit(*word);
61 if i == 0 {
62 builder.assign(result, word_var);
63 } else {
64 builder.assign(result, result * var_2_31 + word_var);
65 }
66 }
67 result
68}
69
70pub fn felt_bytes_to_bn254_var<C: Config>(
71 builder: &mut Builder<C>,
72 bytes: &[Felt<SP1Field>; 32],
73) -> Var<C::N> {
74 let var_256: Var<_> = builder.constant(C::N::from_canonical_u32(256));
75 let zero_var: Var<_> = builder.constant(C::N::zero());
76 let result = builder.constant(C::N::zero());
77 for (i, byte) in bytes.iter().enumerate() {
78 let byte_bits = builder.num2bits_f_circuit(*byte);
79 if i == 0 {
80 for i in 0..3 {
83 builder.assign(byte_bits[8 - i - 1], zero_var);
84 }
85 let byte_var = builder.bits2num_v_circuit(&byte_bits);
86 builder.assign(result, byte_var);
87 } else {
88 let byte_var = builder.bits2num_v_circuit(&byte_bits);
89 builder.assign(result, result * var_256 + byte_var);
90 }
91 }
92 result
93}
94
95pub fn words_to_bytes<T: Copy>(words: &[[T; 4]]) -> Vec<T> {
96 words.iter().flat_map(|w| w.iter()).copied().collect::<Vec<_>>()
97}