debug.rs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2026 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. #[cfg(feature = "tinyjson")]
  19. use {
  20. super::halo2::Value,
  21. darkfi_sdk::crypto::{pasta_prelude::*, util::FieldElemAsStr, MerkleNode},
  22. std::{
  23. collections::HashMap,
  24. fs::File,
  25. io::{Read, Write},
  26. path::Path,
  27. },
  28. tinyjson::JsonValue::{
  29. self, Array as JsonArray, Number as JsonNum, Object as JsonObj, String as JsonStr,
  30. },
  31. };
  32. use darkfi_sdk::pasta::pallas;
  33. use tracing::error;
  34. use super::{Witness, ZkCircuit};
  35. use crate::{zkas, Error, Result};
  36. #[cfg(feature = "tinyjson")]
  37. /// Export witness.json which can be used by zkrunner for debugging circuits
  38. /// Note that this function makes liberal use of unwraps so it could panic.
  39. pub fn export_witness_json<P: AsRef<Path>>(
  40. output_path: P,
  41. prover_witnesses: &Vec<Witness>,
  42. public_inputs: &Vec<pallas::Base>,
  43. ) {
  44. let mut witnesses = Vec::new();
  45. for witness in prover_witnesses {
  46. let mut value_json = HashMap::new();
  47. match witness {
  48. Witness::Base(value) => {
  49. value.map(|w| {
  50. value_json.insert("Base".to_string(), JsonStr(w.to_string()));
  51. w
  52. });
  53. }
  54. Witness::Scalar(value) => {
  55. value.map(|w| {
  56. value_json.insert("Scalar".to_string(), JsonStr(w.to_string()));
  57. w
  58. });
  59. }
  60. Witness::Uint32(value) => {
  61. value.map(|w| {
  62. value_json.insert("Uint32".to_string(), JsonNum(w.into()));
  63. w
  64. });
  65. }
  66. Witness::MerklePath(value) => {
  67. let mut path = Vec::new();
  68. value.map(|w| {
  69. for node in w {
  70. path.push(JsonStr(node.inner().to_string()));
  71. }
  72. w
  73. });
  74. value_json.insert("MerklePath".to_string(), JsonArray(path));
  75. }
  76. Witness::SparseMerklePath(value) => {
  77. let mut path = Vec::new();
  78. value.map(|w| {
  79. for node in w {
  80. path.push(JsonStr(node.to_string()));
  81. }
  82. w
  83. });
  84. value_json.insert("SparseMerklePath".to_string(), JsonArray(path));
  85. }
  86. Witness::EcNiPoint(value) => {
  87. let (mut x, mut y) = (pallas::Base::ZERO, pallas::Base::ZERO);
  88. value.map(|w| {
  89. let coords = w.to_affine().coordinates().unwrap();
  90. (x, y) = (*coords.x(), *coords.y());
  91. w
  92. });
  93. let coords = vec![JsonStr(x.to_string()), JsonStr(y.to_string())];
  94. value_json.insert("EcNiPoint".to_string(), JsonArray(coords));
  95. }
  96. _ => unimplemented!(),
  97. }
  98. witnesses.push(JsonObj(value_json));
  99. }
  100. let mut instances = Vec::new();
  101. for instance in public_inputs {
  102. instances.push(JsonStr(instance.to_string()));
  103. }
  104. let witnesses_json = JsonArray(witnesses);
  105. let instances_json = JsonArray(instances);
  106. let witness_json = JsonObj(HashMap::from([
  107. ("witnesses".to_string(), witnesses_json),
  108. ("instances".to_string(), instances_json),
  109. ]));
  110. // This is a debugging method. We don't care about .expect() crashing.
  111. let json = witness_json.format().expect("cannot create debug json");
  112. let mut output = File::create(output_path).expect("cannot write file");
  113. output.write_all(json.as_bytes()).expect("write failed");
  114. }
  115. #[cfg(feature = "tinyjson")]
  116. /// Import witness.json which can be used to debug or benchmark circuits.
  117. /// Note that if the path or provided json is incorrect then this function will panic.
  118. pub fn import_witness_json<P: AsRef<Path>>(input_path: P) -> (Vec<Witness>, Vec<pallas::Base>) {
  119. let mut input = File::open(input_path).expect("could not open input file");
  120. let mut json_str = String::new();
  121. input.read_to_string(&mut json_str).expect("unable to read to string");
  122. let json: JsonValue = json_str.parse().unwrap();
  123. drop(input);
  124. drop(json_str);
  125. let root: &HashMap<_, _> = json.get().expect("root");
  126. let json_witness: &Vec<_> = root["witnesses"].get().expect("witnesses");
  127. let jval_as_fp = |j_val: &JsonValue| {
  128. let valstr: &String = j_val.get().expect("value str");
  129. pallas::Base::from_str(valstr).unwrap()
  130. };
  131. let jval_as_vecfp = |j_val: &JsonValue| {
  132. j_val
  133. .get::<Vec<_>>()
  134. .expect("value str")
  135. .iter()
  136. .map(jval_as_fp)
  137. .collect::<Vec<pallas::Base>>()
  138. };
  139. let mut witnesses = Vec::new();
  140. for j_witness in json_witness {
  141. let item: &HashMap<_, _> = j_witness.get().expect("root");
  142. assert_eq!(item.len(), 1);
  143. let (typename, j_val) = item.iter().next().expect("witness has single item");
  144. match typename.as_str() {
  145. "Base" => {
  146. let fp = jval_as_fp(j_val);
  147. witnesses.push(Witness::Base(Value::known(fp)));
  148. }
  149. "Scalar" => {
  150. let valstr: &String = j_val.get().expect("value str");
  151. let fq = pallas::Scalar::from_str(valstr).unwrap();
  152. witnesses.push(Witness::Scalar(Value::known(fq)));
  153. }
  154. "Uint32" => {
  155. let val: &f64 = j_val.get().expect("value str");
  156. witnesses.push(Witness::Uint32(Value::known(*val as u32)));
  157. }
  158. "MerklePath" => {
  159. let vals: Vec<_> = jval_as_vecfp(j_val).into_iter().map(MerkleNode::new).collect();
  160. assert_eq!(vals.len(), 32);
  161. let vals: [MerkleNode; 32] = vals.try_into().unwrap();
  162. witnesses.push(Witness::MerklePath(Value::known(vals)));
  163. }
  164. "SparseMerklePath" => {
  165. let vals = jval_as_vecfp(j_val);
  166. assert_eq!(vals.len(), 255);
  167. let vals: [pallas::Base; 255] = vals.try_into().unwrap();
  168. witnesses.push(Witness::SparseMerklePath(Value::known(vals)));
  169. }
  170. "EcNiPoint" => {
  171. let vals = jval_as_vecfp(j_val);
  172. assert_eq!(vals.len(), 2);
  173. let (x, y) = (vals[0], vals[1]);
  174. let point: pallas::Point = pallas::Affine::from_xy(x, y).unwrap().to_curve();
  175. witnesses.push(Witness::EcNiPoint(Value::known(point)));
  176. }
  177. _ => unimplemented!(),
  178. }
  179. }
  180. let instances = jval_as_vecfp(&root["instances"]);
  181. (witnesses, instances)
  182. }
  183. /// Call this before `Proof::create()` to perform type checks on the witnesses and check
  184. /// the amount of provided instances are correct.
  185. pub fn zkas_type_checks(
  186. circuit: &ZkCircuit,
  187. binary: &zkas::ZkBinary,
  188. instances: &[pallas::Base],
  189. ) -> Result<()> {
  190. if circuit.witnesses.len() != binary.witnesses.len() {
  191. error!(
  192. "Wrong number of witnesses. Should be {}, but instead got {}.",
  193. binary.witnesses.len(),
  194. circuit.witnesses.len()
  195. );
  196. return Err(Error::WrongWitnessesCount)
  197. }
  198. for (i, (circuit_witness, binary_witness)) in
  199. circuit.witnesses.iter().zip(binary.witnesses.iter()).enumerate()
  200. {
  201. let is_pass = match circuit_witness {
  202. Witness::EcPoint(_) => *binary_witness == zkas::VarType::EcPoint,
  203. Witness::EcNiPoint(_) => *binary_witness == zkas::VarType::EcNiPoint,
  204. Witness::EcFixedPoint(_) => *binary_witness == zkas::VarType::EcFixedPoint,
  205. Witness::Base(_) => *binary_witness == zkas::VarType::Base,
  206. Witness::Scalar(_) => *binary_witness == zkas::VarType::Scalar,
  207. Witness::MerklePath(_) => *binary_witness == zkas::VarType::MerklePath,
  208. Witness::SparseMerklePath(_) => *binary_witness == zkas::VarType::SparseMerklePath,
  209. Witness::Uint32(_) => *binary_witness == zkas::VarType::Uint32,
  210. Witness::Uint64(_) => *binary_witness == zkas::VarType::Uint64,
  211. };
  212. if !is_pass {
  213. error!(
  214. "Wrong witness type at index {}. Expected '{}', but instead got '{}'.",
  215. i,
  216. binary_witness.name(),
  217. circuit_witness.name()
  218. );
  219. return Err(Error::WrongWitnessType(i))
  220. }
  221. }
  222. // Count number of public instances
  223. let mut instances_count = 0;
  224. for opcode in &circuit.opcodes {
  225. if let (zkas::Opcode::ConstrainInstance, _) = opcode {
  226. instances_count += 1;
  227. }
  228. }
  229. if instances.len() != instances_count {
  230. error!(
  231. "Wrong number of public inputs. Should be {}, but instead got {}.",
  232. instances_count,
  233. instances.len()
  234. );
  235. return Err(Error::WrongPublicInputsCount)
  236. }
  237. Ok(())
  238. }