taceo_circom_types/
witness.rs1use std::io;
4
5use ark_serialize::{Read, SerializationError};
6use byteorder::{LittleEndian, ReadBytesExt};
7use thiserror::Error;
8
9use ark_ff::{BigInteger, PrimeField};
10
11use crate::reader_utils::{self, InvalidHeaderError};
12
13type Result<T> = std::result::Result<T, WitnessParserError>;
14const WITNESS_HEADER: &str = "wtns";
15const MAX_VERSION: u32 = 2;
16const N_SECTIONS: u32 = 2;
17
18#[derive(Debug, Error)]
20pub enum WitnessParserError {
21 #[error(transparent)]
23 IoError(#[from] io::Error),
24 #[error(transparent)]
26 SerializationError(#[from] SerializationError),
27 #[error("Max supported version is {0}, but got {1}")]
29 VersionNotSupported(u32, u32),
30 #[error("Wrong number of sections is {0}, but got {1}")]
32 InvalidSectionNumber(u32, u32),
33 #[error("ScalarField from curve does not match in witness file")]
35 WrongScalarField,
36 #[error(transparent)]
38 WrongHeader(#[from] InvalidHeaderError),
39}
40
41#[derive(Debug, Clone, Eq, PartialEq)]
43pub struct Witness<F> {
44 pub values: Vec<F>,
46}
47
48impl<F: PrimeField> Witness<F> {
49 pub fn from_reader<R: Read>(mut reader: R) -> Result<Self> {
51 tracing::trace!("trying to read witness");
52 reader_utils::read_header(&mut reader, WITNESS_HEADER)?;
53 let version = reader.read_u32::<LittleEndian>()?;
54 if version > MAX_VERSION {
55 return Err(WitnessParserError::VersionNotSupported(
56 MAX_VERSION,
57 version,
58 ));
59 }
60
61 let n_sections = reader.read_u32::<LittleEndian>()?;
62 if n_sections > N_SECTIONS {
63 return Err(WitnessParserError::InvalidSectionNumber(
64 N_SECTIONS, n_sections,
65 ));
66 }
67 let _ = reader.read_u32::<LittleEndian>()?;
70 let _ = reader.read_u64::<LittleEndian>()?;
71 let n8 = reader.read_u32::<LittleEndian>()?;
72 let n8 = usize::try_from(n8).expect("u32 fits into usize");
73 let mut buf = vec![0; n8];
74 reader.read_exact(buf.as_mut_slice())?;
75 if F::MODULUS.to_bytes_le() != buf {
76 tracing::trace!("wrong scalar field");
77 return Err(WitnessParserError::WrongScalarField);
78 }
79 let n_witness = reader.read_u32::<LittleEndian>()?;
80 let _ = reader.read_u32::<LittleEndian>()?;
83 let _ = reader.read_u64::<LittleEndian>()?;
84 Ok(Self {
85 values: (0..n_witness)
86 .map(|_| {
87 reader_utils::prime_field_from_reader(&mut reader, n8)
88 .map_err(WitnessParserError::from)
89 })
90 .collect::<Result<Vec<F>>>()?,
91 })
92 }
93}
94
95#[cfg(test)]
96#[cfg(feature = "bn254")]
97mod bn254_tests {
98 use std::fs::File;
99
100 use crate::tests::groth16_bn254_kats;
101
102 use super::Witness;
103
104 #[test]
105 fn can_deser_witness_bn254() {
106 let groth16_bn254_kats = groth16_bn254_kats();
107 let witness = File::open(groth16_bn254_kats.join("witness.wtns")).unwrap();
108 let is_witness = Witness::<ark_bn254::Fr>::from_reader(witness).unwrap();
109 assert_eq!(
110 is_witness,
111 Witness {
112 values: vec![
113 ark_bn254::Fr::from(1),
114 ark_bn254::Fr::from(33),
115 ark_bn254::Fr::from(3),
116 ark_bn254::Fr::from(11),
117 ],
118 }
119 );
120 }
121}
122
123#[cfg(test)]
124#[cfg(feature = "bls12-381")]
125mod bls12_381_tests {
126 use std::fs::File;
127
128 use crate::tests::groth16_bls12_381_kats;
129
130 use super::Witness;
131
132 #[test]
133 fn can_deser_witness_bls12381() {
134 let groth16_bls12_381_kats = groth16_bls12_381_kats();
135 let witness = File::open(groth16_bls12_381_kats.join("witness.wtns")).unwrap();
136 let is_witness = Witness::<ark_bls12_381::Fr>::from_reader(witness).unwrap();
137 assert_eq!(
138 is_witness,
139 Witness {
140 values: vec![
141 ark_bls12_381::Fr::from(1),
142 ark_bls12_381::Fr::from(33),
143 ark_bls12_381::Fr::from(3),
144 ark_bls12_381::Fr::from(11),
145 ],
146 }
147 );
148 }
149}