main.rs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2025 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. use rand::rngs::OsRng;
  19. use std::{marker::PhantomData, time::Instant};
  20. use darkfi_sdk::{
  21. crypto::{
  22. constants::{
  23. sinsemilla::{OrchardCommitDomains, OrchardHashDomains},
  24. util::gen_const_array,
  25. NullifierK, OrchardFixedBases, OrchardFixedBasesFull, ValueCommitV,
  26. MERKLE_DEPTH_ORCHARD,
  27. },
  28. pallas,
  29. pasta_prelude::*,
  30. },
  31. pasta::group::GroupEncoding,
  32. };
  33. use halo2_gadgets::{
  34. ecc::{
  35. chip::{EccChip, EccConfig},
  36. FixedPoint, FixedPointBaseField, FixedPointShort, NonIdentityPoint, Point, ScalarFixed,
  37. ScalarFixedShort, ScalarVar,
  38. },
  39. utilities::lookup_range_check::LookupRangeCheckConfig,
  40. };
  41. use halo2_proofs::{
  42. circuit::{AssignedCell, Chip, Layouter, Region, SimpleFloorPlanner, Value},
  43. plonk::{
  44. Advice, Circuit, Column, ConstraintSystem, Error, Fixed, Instance as InstanceColumn,
  45. Selector,
  46. },
  47. poly::Rotation,
  48. };
  49. use darkfi::zk::{
  50. assign_free_advice,
  51. gadget::arithmetic::{ArithChip, ArithConfig, ArithInstruction},
  52. proof::{Proof, ProvingKey, VerifyingKey},
  53. };
  54. mod circuit;
  55. trait NumericInstructions: Chip<pallas::Base> {
  56. /// Variable representing a number.
  57. type Num;
  58. fn load_private(
  59. &self,
  60. layouter: impl Layouter<pallas::Base>,
  61. a: Value<pallas::Base>,
  62. ) -> Result<Self::Num, Error>;
  63. fn load_constant(
  64. &self,
  65. layouter: impl Layouter<pallas::Base>,
  66. constant: pallas::Base,
  67. ) -> Result<Self::Num, Error>;
  68. fn mul(
  69. &self,
  70. layouter: impl Layouter<pallas::Base>,
  71. a: Self::Num,
  72. b: Self::Num,
  73. ) -> Result<Self::Num, Error>;
  74. fn expose_public(
  75. &self,
  76. layouter: impl Layouter<pallas::Base>,
  77. num: Self::Num,
  78. row: usize,
  79. ) -> Result<(), Error>;
  80. }
  81. /// The chip that will implement our instructions! Chips store their own
  82. /// config, as well as type markers if necessary.
  83. struct FieldChip {
  84. config: FieldConfig,
  85. }
  86. /// Chip state is stored in a config struct. This is generated by the chip
  87. /// during configuration, and then stored inside the chip.
  88. #[derive(Clone, Debug)]
  89. struct FieldConfig {
  90. /// For this chip, we will use two advice columns to implement our instructions.
  91. /// These are also the columns through which we communicate with other parts of
  92. /// the circuit.
  93. advice: [Column<Advice>; 2],
  94. /// This is the public input (instance) column.
  95. instance: Column<InstanceColumn>,
  96. // We need a selector to enable the multiplication gate, so that we aren't placing
  97. // any constraints on cells where `NumericInstructions::mul` is not being used.
  98. // This is important when building larger circuits, where columns are used by
  99. // multiple sets of instructions.
  100. s_mul: Selector,
  101. }
  102. impl FieldChip {
  103. fn construct(config: <Self as Chip<pallas::Base>>::Config) -> Self {
  104. Self { config }
  105. }
  106. fn configure(
  107. meta: &mut ConstraintSystem<pallas::Base>,
  108. advice: [Column<Advice>; 2],
  109. instance: Column<InstanceColumn>,
  110. constant: Column<Fixed>,
  111. ) -> <Self as Chip<pallas::Base>>::Config {
  112. meta.enable_equality(instance);
  113. meta.enable_constant(constant);
  114. for column in &advice {
  115. meta.enable_equality(*column);
  116. }
  117. let s_mul = meta.selector();
  118. // Define our multiplication gate!
  119. meta.create_gate("mul", |meta| {
  120. // To implement multiplication, we need three advice cells and a selector
  121. // cell. We arrange them like so:
  122. //
  123. // | a0 | a1 | s_mul |
  124. // |-----|-----|-------|
  125. // | lhs | rhs | s_mul |
  126. // | out | | |
  127. //
  128. // Gates may refer to any relative offsets we want, but each distinct
  129. // offset adds a cost to the proof. The most common offsets are 0 (the
  130. // current row), 1 (the next row), and -1 (the previous row), for which
  131. // `Rotation` has specific constructors.
  132. let lhs = meta.query_advice(advice[0], Rotation::cur());
  133. let rhs = meta.query_advice(advice[1], Rotation::cur());
  134. let out = meta.query_advice(advice[0], Rotation::next());
  135. let s_mul = meta.query_selector(s_mul);
  136. // Finally, we return the polynomial expressions that constrain this gate.
  137. // For our multiplication gate, we only need a single polynomial constraint.
  138. //
  139. // The polynomial expressions returned from `create_gate` will be
  140. // constrained by the proving system to equal zero. Our expression
  141. // has the following properties:
  142. // - When s_mul = 0, any value is allowed in lhs, rhs, and out.
  143. // - When s_mul != 0, this constrains lhs * rhs = out.
  144. vec![s_mul * (lhs * rhs - out)]
  145. });
  146. FieldConfig { advice, instance, s_mul }
  147. }
  148. }
  149. impl Chip<pallas::Base> for FieldChip {
  150. type Config = FieldConfig;
  151. type Loaded = ();
  152. fn config(&self) -> &Self::Config {
  153. &self.config
  154. }
  155. fn loaded(&self) -> &Self::Loaded {
  156. &()
  157. }
  158. }
  159. /// A variable representing a number.
  160. #[derive(Clone)]
  161. struct Number(AssignedCell<pallas::Base, pallas::Base>);
  162. impl NumericInstructions for FieldChip {
  163. type Num = Number;
  164. fn load_private(
  165. &self,
  166. mut layouter: impl Layouter<pallas::Base>,
  167. value: Value<pallas::Base>,
  168. ) -> Result<Self::Num, Error> {
  169. let config = self.config();
  170. layouter.assign_region(
  171. || "load private",
  172. |mut region| {
  173. region.assign_advice(|| "private input", config.advice[0], 0, || value).map(Number)
  174. },
  175. )
  176. }
  177. fn load_constant(
  178. &self,
  179. mut layouter: impl Layouter<pallas::Base>,
  180. constant: pallas::Base,
  181. ) -> Result<Self::Num, Error> {
  182. let config = self.config();
  183. layouter.assign_region(
  184. || "load constant",
  185. |mut region| {
  186. region
  187. .assign_advice_from_constant(|| "constant value", config.advice[0], 0, constant)
  188. .map(Number)
  189. },
  190. )
  191. }
  192. fn mul(
  193. &self,
  194. mut layouter: impl Layouter<pallas::Base>,
  195. a: Self::Num,
  196. b: Self::Num,
  197. ) -> Result<Self::Num, Error> {
  198. let config = self.config();
  199. layouter.assign_region(
  200. || "mul",
  201. |mut region: Region<'_, pallas::Base>| {
  202. // We only want to use a single multiplication gate in this region,
  203. // so we enable it at region offset 0; this means it will constrain
  204. // cells at offsets 0 and 1.
  205. config.s_mul.enable(&mut region, 0)?;
  206. // The inputs we've been given could be located anywhere in the circuit,
  207. // but we can only rely on relative offsets inside this region. So we
  208. // assign new cells inside the region and constrain them to have the
  209. // same values as the inputs.
  210. a.0.copy_advice(|| "lhs", &mut region, config.advice[0], 0)?;
  211. b.0.copy_advice(|| "rhs", &mut region, config.advice[1], 0)?;
  212. // Now we can assign the multiplication result, which is to be assigned
  213. // into the output position.
  214. let value = a.0.value().copied() * b.0.value();
  215. // Finally, we do the assignment to the output, returning a
  216. // variable to be used in another part of the circuit.
  217. region.assign_advice(|| "lhs * rhs", config.advice[0], 1, || value).map(Number)
  218. },
  219. )
  220. }
  221. fn expose_public(
  222. &self,
  223. mut layouter: impl Layouter<pallas::Base>,
  224. num: Self::Num,
  225. row: usize,
  226. ) -> Result<(), Error> {
  227. let config = self.config();
  228. layouter.constrain_instance(num.0.cell(), config.instance, row)
  229. }
  230. }
  231. #[derive(Clone)]
  232. pub struct MainConfig {
  233. primary: Column<InstanceColumn>,
  234. advices: [Column<Advice>; 10],
  235. ecc_config: EccConfig<OrchardFixedBases>,
  236. arith_config: ArithConfig,
  237. }
  238. impl MainConfig {
  239. fn ecc_chip(&self) -> EccChip<OrchardFixedBases> {
  240. EccChip::construct(self.ecc_config.clone())
  241. }
  242. fn arithmetic_chip(&self) -> ArithChip {
  243. ArithChip::construct(self.arith_config.clone())
  244. }
  245. }
  246. #[derive(Default)]
  247. struct MyCircuit {
  248. g1: Value<pallas::Point>,
  249. //g2: Value<pallas::Point>,
  250. //g3: Value<pallas::Point>,
  251. //g4: Value<pallas::Point>,
  252. s1: Value<pallas::Base>,
  253. //s2: Value<pallas::Scalar>,
  254. //s3: Value<pallas::Scalar>,
  255. //s4: Value<pallas::Scalar>,
  256. }
  257. impl Circuit<pallas::Base> for MyCircuit {
  258. // Since we are using a single chip for everything, we can just reuse its config.
  259. type Config = MainConfig;
  260. type FloorPlanner = SimpleFloorPlanner;
  261. fn without_witnesses(&self) -> Self {
  262. Self::default()
  263. }
  264. fn configure(meta: &mut ConstraintSystem<pallas::Base>) -> Self::Config {
  265. // Advice columns used in the circuit
  266. let advices = [
  267. meta.advice_column(),
  268. meta.advice_column(),
  269. meta.advice_column(),
  270. meta.advice_column(),
  271. meta.advice_column(),
  272. meta.advice_column(),
  273. meta.advice_column(),
  274. meta.advice_column(),
  275. meta.advice_column(),
  276. meta.advice_column(),
  277. ];
  278. // Fixed columns for the Sinsemilla generator lookup table
  279. let table_idx = meta.lookup_table_column();
  280. let lookup = (table_idx, meta.lookup_table_column(), meta.lookup_table_column());
  281. // Instance column used for public inputs
  282. let primary = meta.instance_column();
  283. meta.enable_equality(primary);
  284. // Permutation over all advice columns
  285. for advice in advices.iter() {
  286. meta.enable_equality(*advice);
  287. }
  288. // Poseidon requires four advice columns, while ECC incomplete addition
  289. // requires six. We can reduce the proof size by sharing fixed columns
  290. // between the ECC and Poseidon chips.
  291. // TODO: For multiple invocations perhaps they could/should be configured
  292. // in parallel rather than sharing?
  293. let lagrange_coeffs = [
  294. meta.fixed_column(),
  295. meta.fixed_column(),
  296. meta.fixed_column(),
  297. meta.fixed_column(),
  298. meta.fixed_column(),
  299. meta.fixed_column(),
  300. meta.fixed_column(),
  301. meta.fixed_column(),
  302. ];
  303. //let rc_a = lagrange_coeffs[2..5].try_into().unwrap();
  304. //let rc_b = lagrange_coeffs[5..8].try_into().unwrap();
  305. // Also use the first Lagrange coefficient column for loading global constants.
  306. meta.enable_constant(lagrange_coeffs[0]);
  307. // Use one of the right-most advice columns for all of our range checks.
  308. let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx);
  309. // Configuration for curve point operations.
  310. // This uses 10 advice columns and spans the whole circuit.
  311. let ecc_config =
  312. EccChip::<OrchardFixedBases>::configure(meta, advices, lagrange_coeffs, range_check);
  313. // Configuration for the Poseidon hash
  314. //let poseidon_config = PoseidonChip::configure::<poseidon::P128Pow5T3>(
  315. // meta,
  316. // advices[6..9].try_into().unwrap(),
  317. // advices[5],
  318. // rc_a,
  319. // rc_b,
  320. //);
  321. // Configuration for the Arithmetic chip
  322. let arith_config = ArithChip::configure(meta, advices[7], advices[8], advices[6]);
  323. // Configuration for a Sinsemilla hash instantiation and a
  324. // Merkle hash instantiation using this Sinsemilla instance.
  325. // Since the Sinsemilla config uses only 5 advice columns,
  326. // we can fit two instances side-by-side.
  327. //let (sinsemilla_cfg1, merkle_cfg1) = {
  328. // let sinsemilla_cfg1 = SinsemillaChip::configure(
  329. // meta,
  330. // advices[..5].try_into().unwrap(),
  331. // advices[6],
  332. // lagrange_coeffs[0],
  333. // lookup,
  334. // range_check,
  335. // );
  336. // let merkle_cfg1 = MerkleChip::configure(meta, sinsemilla_cfg1.clone());
  337. // (sinsemilla_cfg1, merkle_cfg1)
  338. //};
  339. //let (_sinsemilla_cfg2, merkle_cfg2) = {
  340. // let sinsemilla_cfg2 = SinsemillaChip::configure(
  341. // meta,
  342. // advices[5..].try_into().unwrap(),
  343. // advices[7],
  344. // lagrange_coeffs[1],
  345. // lookup,
  346. // range_check,
  347. // );
  348. // let merkle_cfg2 = MerkleChip::configure(meta, sinsemilla_cfg2.clone());
  349. // (sinsemilla_cfg2, merkle_cfg2)
  350. //};
  351. // K-table for 64 bit range check lookups
  352. let k_values_table_64 = meta.lookup_table_column();
  353. //let native_64_range_check_config =
  354. // NativeRangeCheckChip::<3, 64, 22>::configure(meta, advices[8], k_values_table_64);
  355. // K-table for 253 bit range check lookups
  356. let k_values_table_253 = meta.lookup_table_column();
  357. //let native_253_range_check_config =
  358. // NativeRangeCheckChip::<3, 253, 85>::configure(meta, advices[8], k_values_table_253);
  359. // TODO: FIXME: Configure these better, this is just a stop-gap
  360. let z1 = meta.advice_column();
  361. let z2 = meta.advice_column();
  362. //
  363. //let lessthan_config = LessThanChip::<3, 253, 85>::configure(
  364. // meta,
  365. // advices[6],
  366. // advices[7],
  367. // advices[8],
  368. // z1,
  369. // z2,
  370. // k_values_table_253,
  371. //);
  372. // Configuration for boolean checks, it uses the small_range_check
  373. // chip with a range of 2, which enforces one bit, i.e. 0 or 1.
  374. //let boolcheck_config = SmallRangeCheckChip::configure(meta, advices[9], 2);
  375. MainConfig { primary, advices, ecc_config, arith_config }
  376. }
  377. fn synthesize(
  378. &self,
  379. config: Self::Config,
  380. mut layouter: impl Layouter<pallas::Base>,
  381. ) -> Result<(), Error> {
  382. let g1 = NonIdentityPoint::new(
  383. config.ecc_chip(),
  384. layouter.namespace(|| "Witness EcNiPoint"),
  385. self.g1.as_ref().map(|cm| cm.to_affine()),
  386. )?;
  387. let s1 = assign_free_advice(layouter.namespace(|| "load a"), config.advices[0], self.s1)?;
  388. let s1: AssignedCell<pallas::Base, pallas::Base> = s1.into();
  389. let s1 = ScalarVar::from_base(
  390. config.ecc_chip(),
  391. layouter.namespace(|| "EcMul: ScalarFixed::new()"),
  392. &s1,
  393. )?;
  394. let (r, _) = g1.mul(layouter.namespace(|| "EcMul()"), s1)?;
  395. let mut public_inputs_offset = 0;
  396. let point: Point<pallas::Affine, EccChip<OrchardFixedBases>> = r.into();
  397. let r_x = point.inner().x();
  398. let r_y = point.inner().y();
  399. let var: AssignedCell<pallas::Base, pallas::Base> = r_x.into();
  400. layouter.constrain_instance(var.cell(), config.primary, public_inputs_offset)?;
  401. public_inputs_offset += 1;
  402. let var: AssignedCell<pallas::Base, pallas::Base> = r_y.into();
  403. layouter.constrain_instance(var.cell(), config.primary, public_inputs_offset)?;
  404. public_inputs_offset += 1;
  405. Ok(())
  406. }
  407. }
  408. fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
  409. let k = 8;
  410. //let g1 = pallas::Point::random(&mut OsRng);
  411. //println!("{:?}", g1);
  412. //let g1_bytes = g1.to_bytes();
  413. //println!("{}", hex::encode(&g1_bytes));
  414. // G1_x = 2fea7c1d8106d6d407a57bebec987e875ed9073ebf215e52f5b42c0c604c1801
  415. // G1_y = 0dcc7041075d6496102295722cd12f2f0c1e9d49eaa00f10c4bc02155598353b
  416. // G2_x = dfae4ed869484b2b9783c445888db03bac24f96f0260982b90f5b53477994e3e
  417. // G2_y = fa1b4182ef04514624a1e32846d48bfd229ef78975106e8e0614b8061dfe3d1d
  418. // G3_x = 702ddc6514ae63da6e13bcfa439f03b363018a152e16e665126623205ac4d31c
  419. // G3_y = 81cb38e121b6c375150aa2c1b4c92185a87781194a133535cbefb699e3475103
  420. // G4_x = 026b681bf7a0102e78bf3b34af50b5031ef1dd1f152f3df17af8e6eaae69cb3a
  421. // G4_y = c97b4f5ed89f4147eb3410892af8a1ecd21b96f59d43e5e4252872742acbbf24
  422. // s1 = f4537d29a235d6b4bf95ef436aa15fd641419c2da9e9600520be99a14c43ac2c
  423. // s2 = 6d2738d1e1f8bbb1bd154cd8102cca5c0224f8902803da1f7c4563b47103471c
  424. // s3 = ebbaf604f85b3e725e71a5d785e177c9f3ccd4c07394a0d59318cf1504c72a06
  425. // s4 = 5176cd889dd29f19cef07c5d2db9a2d67c568034ae737ff1f95456252d2e2301
  426. // Qx = 6b35d97bcef7928a15aed8e5d9b8ecbcb2a5ca190de7b9957971f6da6ad92c03
  427. // Qy = e485978ca7d9f798fe1b7afac7f74a98326cccc528f1010091948497ae5e7422
  428. // Halo2 points are the x coordinated in little endian order
  429. let g1x_bytes =
  430. hex::decode("2fea7c1d8106d6d407a57bebec987e875ed9073ebf215e52f5b42c0c604c1801")?;
  431. let g1x_bytes = g1x_bytes[..].try_into()?;
  432. let g1x = pallas::Base::from_repr(g1x_bytes).unwrap();
  433. let g1y_bytes =
  434. hex::decode("0dcc7041075d6496102295722cd12f2f0c1e9d49eaa00f10c4bc02155598353b")?;
  435. let g1y_bytes = g1y_bytes[..].try_into()?;
  436. let g1y = pallas::Base::from_repr(g1y_bytes).unwrap();
  437. let g1: pallas::Point = pallas::Affine::from_xy(g1x, g1y).unwrap().into();
  438. //let g2x_bytes = hex::decode("dfae4ed869484b2b9783c445888db03bac24f96f0260982b90f5b53477994e3e")?;
  439. //let g2x_bytes = g2x_bytes[..].try_into()?;
  440. //let g2x = pallas::Base::from_repr(g2x_bytes).unwrap();
  441. //let g2y_bytes = hex::decode("fa1b4182ef04514624a1e32846d48bfd229ef78975106e8e0614b8061dfe3d1d")?;
  442. //let g2y_bytes = g2y_bytes[..].try_into()?;
  443. //let g2y = pallas::Base::from_repr(g2y_bytes).unwrap();
  444. //let g2: pallas::Point = pallas::Affine::from_xy(g2x, g2y).unwrap().into();
  445. //let g3x_bytes = hex::decode("702ddc6514ae63da6e13bcfa439f03b363018a152e16e665126623205ac4d31c")?;
  446. //let g3x_bytes = g3x_bytes[..].try_into()?;
  447. //let g3x = pallas::Base::from_repr(g3x_bytes).unwrap();
  448. //let g3y_bytes = hex::decode("81cb38e121b6c375150aa2c1b4c92185a87781194a133535cbefb699e3475103")?;
  449. //let g3y_bytes = g3y_bytes[..].try_into()?;
  450. //let g3y = pallas::Base::from_repr(g3y_bytes).unwrap();
  451. //let g3: pallas::Point = pallas::Affine::from_xy(g3x, g3y).unwrap().into();
  452. //let g4x_bytes = hex::decode("026b681bf7a0102e78bf3b34af50b5031ef1dd1f152f3df17af8e6eaae69cb3a")?;
  453. //let g4x_bytes = g4x_bytes[..].try_into()?;
  454. //let g4x = pallas::Base::from_repr(g4x_bytes).unwrap();
  455. //let g4y_bytes = hex::decode("c97b4f5ed89f4147eb3410892af8a1ecd21b96f59d43e5e4252872742acbbf24")?;
  456. //let g4y_bytes = g4y_bytes[..].try_into()?;
  457. //let g4y = pallas::Base::from_repr(g4y_bytes).unwrap();
  458. //let g4: pallas::Point = pallas::Affine::from_xy(g4x, g4y).unwrap().into();
  459. //let s1_bytes = hex::decode("f4537d29a235d6b4bf95ef436aa15fd641419c2da9e9600520be99a14c43ac2c")?;
  460. //let s1_bytes = s1_bytes[..].try_into()?;
  461. //let s1 = pallas::Scalar::from_repr(s1_bytes).unwrap();
  462. //let s2_bytes = hex::decode("6d2738d1e1f8bbb1bd154cd8102cca5c0224f8902803da1f7c4563b47103471c")?;
  463. //let s2_bytes = s2_bytes[..].try_into()?;
  464. //let s2 = pallas::Scalar::from_repr(s2_bytes).unwrap();
  465. //let s3_bytes = hex::decode("ebbaf604f85b3e725e71a5d785e177c9f3ccd4c07394a0d59318cf1504c72a06")?;
  466. //let s3_bytes = s3_bytes[..].try_into()?;
  467. //let s3 = pallas::Scalar::from_repr(s3_bytes).unwrap();
  468. //let s4_bytes = hex::decode("5176cd889dd29f19cef07c5d2db9a2d67c568034ae737ff1f95456252d2e2301")?;
  469. //let s4_bytes = s4_bytes[..].try_into()?;
  470. //let s4 = pallas::Scalar::from_repr(s4_bytes).unwrap();
  471. //let qx_bytes = hex::decode("6b35d97bcef7928a15aed8e5d9b8ecbcb2a5ca190de7b9957971f6da6ad92c03")?;
  472. //let qx_bytes = qx_bytes[..].try_into()?;
  473. //let qx = pallas::Base::from_repr(qx_bytes).unwrap();
  474. //let qy_bytes = hex::decode("e485978ca7d9f798fe1b7afac7f74a98326cccc528f1010091948497ae5e7422")?;
  475. //let qy_bytes = qy_bytes[..].try_into()?;
  476. //let qy = pallas::Base::from_repr(qy_bytes).unwrap();
  477. //let q: pallas::Point = pallas::Affine::from_xy(qx, qy).unwrap().into();
  478. //let x = pallas::Scalar::from(2);
  479. //println!("{:?}", x);
  480. //println!("{:?}", x.to_repr());
  481. //let qq = g1*s1 + g2*s2 + g3*s3 + g4*s4;
  482. //println!("{:?}", qq.to_affine());
  483. //assert_eq!(q.to_affine(), qq.to_affine());
  484. let r = g1 * pallas::Scalar::from(2);
  485. let s1 = pallas::Base::from(2);
  486. let circuit = MyCircuit {
  487. g1: Value::known(g1),
  488. //g2: Value::known(g2),
  489. //g3: Value::known(g3),
  490. //g4: Value::known(g4),
  491. s1: Value::known(s1),
  492. //s2: Value::known(s2),
  493. //s3: Value::known(s3),
  494. //s4: Value::known(s4),
  495. };
  496. let r_coords = r.to_affine().coordinates().unwrap();
  497. let r_x = *r_coords.x();
  498. let r_y = *r_coords.y();
  499. let public = vec![r_x, r_y];
  500. let start = Instant::now();
  501. let pk = darkfi::zk::ProvingKey::build(k, &MyCircuit::default());
  502. let vk = darkfi::zk::VerifyingKey::build(k, &MyCircuit::default());
  503. println!("Setup: [{:?}]", start.elapsed());
  504. let start = Instant::now();
  505. let proof = Proof::create(&pk, &[circuit], &public, &mut OsRng)?;
  506. println!("Prove: [{:?}]", start.elapsed());
  507. let start = Instant::now();
  508. assert!(proof.verify(&vk, &public).is_ok());
  509. println!("Verify: [{:?}]", start.elapsed());
  510. Ok(())
  511. }