1use std::sync::{Arc, Mutex};
20
21use darkfi_sdk::{crypto::constants::OrchardFixedBases, pasta::pallas};
22use halo2_gadgets::ecc as ecc_gadget;
23use halo2_proofs::{arithmetic::Field, circuit::AssignedCell};
24
25#[derive(Clone, Debug)]
26pub enum DebugOpValue {
27 EcPoint(pallas::Base, pallas::Base),
28 Base(pallas::Base),
29 Void,
30}
31
32#[derive(Clone, Debug)]
33pub struct ZkTracer {
34 pub opvalues: Arc<Mutex<Option<Vec<DebugOpValue>>>>,
35 init_allowed: bool,
36 is_enabled: bool,
37}
38
39impl ZkTracer {
40 pub(crate) fn new(init_allowed: bool) -> Self {
41 Self { opvalues: Arc::new(Mutex::new(None)), init_allowed, is_enabled: false }
42 }
43
44 pub(crate) fn init(&mut self) {
45 if !self.init_allowed {
46 panic!("Cannot initialize tracer for verifier circuit!");
47 }
48 self.is_enabled = true;
49 *self.opvalues.lock().unwrap() = Some(Vec::new());
50 }
51
52 pub(crate) fn clear(&self) {
53 if !self.is_enabled {
54 return
55 }
56
57 self.opvalues.lock().unwrap().as_mut().unwrap().clear();
58 }
59
60 fn push(&self, value: DebugOpValue) {
61 self.opvalues.lock().unwrap().as_mut().unwrap().push(value);
62 }
63
64 pub(crate) fn push_ecpoint(
65 &self,
66 point: &ecc_gadget::Point<pallas::Affine, ecc_gadget::chip::EccChip<OrchardFixedBases>>,
67 ) {
68 if !self.is_enabled {
69 return
70 }
71
72 let (mut x, mut y) = (pallas::Base::ZERO, pallas::Base::ZERO);
73 point.inner().x().value().map(|rx| x = *rx);
74 point.inner().y().value().map(|ry| y = *ry);
75 self.push(DebugOpValue::EcPoint(x, y));
76 }
77
78 pub(crate) fn push_base(&self, value: &AssignedCell<pallas::Base, pallas::Base>) {
79 if !self.is_enabled {
80 return
81 }
82
83 let mut x = pallas::Base::ZERO;
84 value.value().map(|rx| x = *rx);
85 self.push(DebugOpValue::Base(x));
86 }
87
88 pub(crate) fn push_void(&self) {
89 if !self.is_enabled {
90 return
91 }
92
93 self.push(DebugOpValue::Void);
94 }
95
96 pub(crate) fn assert_correct(&self, opcodes_len: usize) {
97 if !self.is_enabled {
98 return
99 }
100
101 let opvalues_len = self.opvalues.lock().unwrap().as_ref().map_or(0, |v| v.len());
102 assert_eq!(opvalues_len, opcodes_len);
103 }
104}