vm2.rs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  1. use std::collections::HashMap;
  2. use std::convert::TryInto;
  3. use halo2::{
  4. circuit::{Layouter, SimpleFloorPlanner},
  5. plonk,
  6. plonk::{Advice, Circuit, Column, ConstraintSystem, Instance as InstanceColumn, Selector},
  7. };
  8. use halo2_gadgets::{
  9. ecc::{
  10. chip::{EccChip, EccConfig},
  11. FixedPoint,
  12. },
  13. poseidon::{
  14. Hash as PoseidonHash, Pow5T3Chip as PoseidonChip, Pow5T3Config as PoseidonConfig,
  15. StateWord, Word,
  16. },
  17. primitives::poseidon::{ConstantLength, P128Pow5T3},
  18. sinsemilla::{
  19. chip::{SinsemillaChip, SinsemillaConfig},
  20. merkle::chip::{MerkleChip, MerkleConfig},
  21. merkle::MerklePath,
  22. },
  23. utilities::{
  24. lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, Var,
  25. },
  26. };
  27. use pasta_curves::pallas;
  28. use crate::{
  29. crypto::{
  30. arith_chip::{ArithmeticChip, ArithmeticChipConfig},
  31. constants::{
  32. sinsemilla::{OrchardCommitDomains, OrchardHashDomains, MERKLE_CRH_PERSONALIZATION},
  33. OrchardFixedBases,
  34. },
  35. },
  36. error::{Error, Result},
  37. };
  38. #[derive(Clone, Debug, PartialEq)]
  39. pub enum ZkType {
  40. Base,
  41. Scalar,
  42. EcPoint,
  43. EcFixedPoint,
  44. MerklePath,
  45. }
  46. type ArgIdx = usize;
  47. #[derive(Clone, Debug)]
  48. pub enum ZkFunctionCall {
  49. PoseidonHash(ArgIdx, ArgIdx),
  50. Add(ArgIdx, ArgIdx),
  51. ConstrainInstance(ArgIdx),
  52. EcMulShort(ArgIdx, ArgIdx),
  53. EcMul(ArgIdx, ArgIdx),
  54. EcAdd(ArgIdx, ArgIdx),
  55. EcGetX(ArgIdx),
  56. EcGetY(ArgIdx),
  57. CalculateMerkleRoot(ArgIdx, ArgIdx),
  58. }
  59. pub struct ZkBinary {
  60. pub constants: Vec<(String, ZkType)>,
  61. pub contracts: HashMap<String, ZkContract>,
  62. }
  63. #[derive(Clone, Debug)]
  64. pub struct ZkContract {
  65. pub witness: Vec<(String, ZkType)>,
  66. pub code: Vec<ZkFunctionCall>,
  67. }
  68. // These is the actual structures below which interpret the structures
  69. // deserialized above.
  70. #[derive(Clone, Debug)]
  71. pub struct MintConfig {
  72. pub primary: Column<InstanceColumn>,
  73. pub q_add: Selector,
  74. pub advices: [Column<Advice>; 10],
  75. pub ecc_config: EccConfig,
  76. pub merkle_config_1: MerkleConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
  77. pub merkle_config_2: MerkleConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
  78. pub sinsemilla_config_1:
  79. SinsemillaConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
  80. pub sinsemilla_config_2:
  81. SinsemillaConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
  82. pub poseidon_config: PoseidonConfig<pallas::Base>,
  83. pub arith_config: ArithmeticChipConfig,
  84. }
  85. impl MintConfig {
  86. pub fn ecc_chip(&self) -> EccChip<OrchardFixedBases> {
  87. EccChip::construct(self.ecc_config.clone())
  88. }
  89. pub fn poseidon_chip(&self) -> PoseidonChip<pallas::Base> {
  90. PoseidonChip::construct(self.poseidon_config.clone())
  91. }
  92. pub fn arithmetic_chip(&self) -> ArithmeticChip {
  93. ArithmeticChip::construct(self.arith_config.clone())
  94. }
  95. fn merkle_chip_1(
  96. &self,
  97. ) -> MerkleChip<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases> {
  98. MerkleChip::construct(self.merkle_config_1.clone())
  99. }
  100. fn merkle_chip_2(
  101. &self,
  102. ) -> MerkleChip<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases> {
  103. MerkleChip::construct(self.merkle_config_2.clone())
  104. }
  105. }
  106. #[derive(Clone, Debug)]
  107. pub struct ZkCircuit<'a> {
  108. pub const_fixed_points: HashMap<String, OrchardFixedBases>,
  109. pub constants: &'a Vec<(String, ZkType)>,
  110. pub contract: &'a ZkContract,
  111. // For each type create a separate stack
  112. pub witness_base: HashMap<String, Option<pallas::Base>>,
  113. pub witness_scalar: HashMap<String, Option<pallas::Scalar>>,
  114. pub witness_merkle_path: HashMap<String, (Option<u32>, Option<[pallas::Base; 32]>)>,
  115. }
  116. impl<'a> ZkCircuit<'a> {
  117. pub fn new(
  118. const_fixed_points: HashMap<String, OrchardFixedBases>,
  119. constants: &'a Vec<(String, ZkType)>,
  120. contract: &'a ZkContract,
  121. ) -> Self {
  122. let mut witness_base = HashMap::new();
  123. let mut witness_scalar = HashMap::new();
  124. let mut witness_merkle_path = HashMap::new();
  125. for (name, type_id) in contract.witness.iter() {
  126. match type_id {
  127. ZkType::Base => {
  128. witness_base.insert(name.clone(), None);
  129. }
  130. ZkType::Scalar => {
  131. witness_scalar.insert(name.clone(), None);
  132. }
  133. ZkType::MerklePath => {
  134. witness_merkle_path.insert(name.clone(), (None, None));
  135. }
  136. _ => {
  137. unimplemented!();
  138. }
  139. }
  140. }
  141. Self {
  142. const_fixed_points,
  143. constants,
  144. contract,
  145. witness_base,
  146. witness_scalar,
  147. witness_merkle_path,
  148. }
  149. }
  150. pub fn witness_base(&mut self, name: &str, value: pallas::Base) -> Result<()> {
  151. for (variable, type_id) in self.contract.witness.iter() {
  152. if name != variable {
  153. continue;
  154. }
  155. if *type_id != ZkType::Base {
  156. return Err(Error::InvalidParamType);
  157. }
  158. *self.witness_base.get_mut(name).unwrap() = Some(value);
  159. return Ok(());
  160. }
  161. return Err(Error::InvalidParamName);
  162. }
  163. pub fn witness_scalar(&mut self, name: &str, value: pallas::Scalar) -> Result<()> {
  164. for (variable, type_id) in self.contract.witness.iter() {
  165. if name != variable {
  166. continue;
  167. }
  168. if *type_id != ZkType::Scalar {
  169. return Err(Error::InvalidParamType);
  170. }
  171. *self.witness_scalar.get_mut(name).unwrap() = Some(value);
  172. return Ok(());
  173. }
  174. return Err(Error::InvalidParamName);
  175. }
  176. pub fn witness_merkle_path(
  177. &mut self,
  178. name: &str,
  179. leaf_pos: u32,
  180. path: [pallas::Base; 32],
  181. ) -> Result<()> {
  182. for (variable, type_id) in self.contract.witness.iter() {
  183. if name != variable {
  184. continue;
  185. }
  186. if *type_id != ZkType::MerklePath {
  187. return Err(Error::InvalidParamType);
  188. }
  189. *self.witness_merkle_path.get_mut(name).unwrap() = (Some(leaf_pos), Some(path));
  190. return Ok(());
  191. }
  192. return Err(Error::InvalidParamName);
  193. }
  194. }
  195. impl<'a> UtilitiesInstructions<pallas::Base> for ZkCircuit<'a> {
  196. type Var = CellValue<pallas::Base>;
  197. }
  198. impl<'a> Circuit<pallas::Base> for ZkCircuit<'a> {
  199. type Config = MintConfig;
  200. type FloorPlanner = SimpleFloorPlanner;
  201. fn without_witnesses(&self) -> Self {
  202. Self {
  203. const_fixed_points: self.const_fixed_points.clone(),
  204. constants: self.constants,
  205. contract: &self.contract,
  206. witness_base: self
  207. .witness_base
  208. .keys()
  209. .map(|key| (key.clone(), None))
  210. .collect(),
  211. witness_scalar: self
  212. .witness_scalar
  213. .keys()
  214. .map(|key| (key.clone(), None))
  215. .collect(),
  216. witness_merkle_path: self
  217. .witness_scalar
  218. .keys()
  219. .map(|key| (key.clone(), (None, None)))
  220. .collect(),
  221. }
  222. }
  223. fn configure(meta: &mut ConstraintSystem<pallas::Base>) -> Self::Config {
  224. let advices = [
  225. meta.advice_column(),
  226. meta.advice_column(),
  227. meta.advice_column(),
  228. meta.advice_column(),
  229. meta.advice_column(),
  230. meta.advice_column(),
  231. meta.advice_column(),
  232. meta.advice_column(),
  233. meta.advice_column(),
  234. meta.advice_column(),
  235. ];
  236. let q_add = meta.selector();
  237. let table_idx = meta.lookup_table_column();
  238. let lookup = (
  239. table_idx,
  240. meta.lookup_table_column(),
  241. meta.lookup_table_column(),
  242. );
  243. let primary = meta.instance_column();
  244. meta.enable_equality(primary.into());
  245. for advice in advices.iter() {
  246. meta.enable_equality((*advice).into());
  247. }
  248. let lagrange_coeffs = [
  249. meta.fixed_column(),
  250. meta.fixed_column(),
  251. meta.fixed_column(),
  252. meta.fixed_column(),
  253. meta.fixed_column(),
  254. meta.fixed_column(),
  255. meta.fixed_column(),
  256. meta.fixed_column(),
  257. ];
  258. let rc_a = lagrange_coeffs[2..5].try_into().unwrap();
  259. let rc_b = lagrange_coeffs[5..8].try_into().unwrap();
  260. meta.enable_constant(lagrange_coeffs[0]);
  261. let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx);
  262. let ecc_config = EccChip::<OrchardFixedBases>::configure(
  263. meta,
  264. advices,
  265. lagrange_coeffs,
  266. range_check.clone(),
  267. );
  268. let poseidon_config = PoseidonChip::configure(
  269. meta,
  270. P128Pow5T3,
  271. advices[6..9].try_into().unwrap(),
  272. advices[5],
  273. rc_a,
  274. rc_b,
  275. );
  276. let arith_config = ArithmeticChip::configure(meta);
  277. // Configuration for a Sinsemilla hash instantiation and a
  278. // Merkle hash instantiation using this Sinsemilla instance.
  279. // Since the Sinsemilla config uses only 5 advice columns,
  280. // we can fit two instances side-by-side.
  281. let (sinsemilla_config_1, merkle_config_1) = {
  282. let sinsemilla_config_1 = SinsemillaChip::configure(
  283. meta,
  284. advices[..5].try_into().unwrap(),
  285. advices[6],
  286. lagrange_coeffs[0],
  287. lookup,
  288. range_check.clone(),
  289. );
  290. let merkle_config_1 = MerkleChip::configure(meta, sinsemilla_config_1.clone());
  291. (sinsemilla_config_1, merkle_config_1)
  292. };
  293. // Configuration for a Sinsemilla hash instantiation and a
  294. // Merkle hash instantiation using this Sinsemilla instance.
  295. // Since the Sinsemilla config uses only 5 advice columns,
  296. // we can fit two instances side-by-side.
  297. let (sinsemilla_config_2, merkle_config_2) = {
  298. let sinsemilla_config_2 = SinsemillaChip::configure(
  299. meta,
  300. advices[5..].try_into().unwrap(),
  301. advices[7],
  302. lagrange_coeffs[1],
  303. lookup,
  304. range_check,
  305. );
  306. let merkle_config_2 = MerkleChip::configure(meta, sinsemilla_config_2.clone());
  307. (sinsemilla_config_2, merkle_config_2)
  308. };
  309. MintConfig {
  310. primary,
  311. q_add,
  312. advices,
  313. ecc_config,
  314. merkle_config_1,
  315. merkle_config_2,
  316. sinsemilla_config_1,
  317. sinsemilla_config_2,
  318. poseidon_config,
  319. arith_config,
  320. }
  321. }
  322. fn synthesize(
  323. &self,
  324. config: Self::Config,
  325. mut layouter: impl Layouter<pallas::Base>,
  326. ) -> std::result::Result<(), plonk::Error> {
  327. // Load the Sinsemilla generator lookup table used by the whole circuit.
  328. SinsemillaChip::load(config.sinsemilla_config_1.clone(), &mut layouter)?;
  329. let arith_chip = config.arithmetic_chip();
  330. // Construct the ECC chip.
  331. let ecc_chip = config.ecc_chip();
  332. let mut stack_base = Vec::new();
  333. let mut stack_scalar = Vec::new();
  334. let mut stack_ec_point = Vec::new();
  335. let mut stack_ec_fixed_point = Vec::new();
  336. let mut stack_merkle_path = Vec::new();
  337. // Load constants first onto the stacks
  338. for (variable, type_id) in self.constants.iter() {
  339. match *type_id {
  340. ZkType::Base => {
  341. unimplemented!();
  342. }
  343. ZkType::Scalar => {
  344. unimplemented!();
  345. }
  346. ZkType::EcPoint => {
  347. unimplemented!();
  348. }
  349. ZkType::EcFixedPoint => {
  350. let value = self.const_fixed_points[variable];
  351. stack_ec_fixed_point.push(value);
  352. }
  353. ZkType::MerklePath => {
  354. unimplemented!();
  355. }
  356. }
  357. }
  358. // Push the witnesses onto the stacks in order
  359. for (variable, type_id) in self.contract.witness.iter() {
  360. match *type_id {
  361. ZkType::Base => {
  362. let value = self.witness_base.get(variable).expect("witness base set");
  363. let value = self.load_private(
  364. layouter.namespace(|| "load pubkey x"),
  365. config.advices[0],
  366. *value,
  367. )?;
  368. stack_base.push(value.clone());
  369. }
  370. ZkType::Scalar => {
  371. let value = self.witness_scalar.get(variable).expect("witness base set");
  372. stack_scalar.push(value.clone());
  373. }
  374. ZkType::EcPoint => {
  375. unimplemented!();
  376. }
  377. ZkType::EcFixedPoint => {
  378. unimplemented!();
  379. }
  380. ZkType::MerklePath => {
  381. let value = self
  382. .witness_merkle_path
  383. .get(variable)
  384. .expect("witness merkle path set");
  385. stack_merkle_path.push(value.clone());
  386. }
  387. }
  388. }
  389. let mut current_instance_offset = 0;
  390. for func_call in self.contract.code.iter() {
  391. match func_call {
  392. ZkFunctionCall::PoseidonHash(lhs_idx, rhs_idx) => {
  393. assert!(*lhs_idx < stack_base.len());
  394. assert!(*rhs_idx < stack_base.len());
  395. let messages = [stack_base[*lhs_idx], stack_base[*rhs_idx]];
  396. let poseidon_message = layouter.assign_region(
  397. || "load message",
  398. |mut region| {
  399. let mut message_word = |i: usize| {
  400. let val = messages[i].value();
  401. let var = region.assign_advice(
  402. || format!("load message_{}", i),
  403. config.poseidon_config.state()[i],
  404. 0,
  405. || val.ok_or(plonk::Error::SynthesisError),
  406. )?;
  407. region.constrain_equal(var, messages[i].cell())?;
  408. Ok(Word::<_, _, P128Pow5T3, 3, 2>::from_inner(StateWord::new(
  409. var, val,
  410. )))
  411. };
  412. Ok([message_word(0)?, message_word(1)?])
  413. },
  414. )?;
  415. let poseidon_hasher = PoseidonHash::init(
  416. config.poseidon_chip(),
  417. layouter.namespace(|| "Poseidon init"),
  418. ConstantLength::<2>,
  419. )?;
  420. let poseidon_output = poseidon_hasher
  421. .hash(layouter.namespace(|| "poseidon hash"), poseidon_message)?;
  422. let poseidon_output: CellValue<pallas::Base> = poseidon_output.inner().into();
  423. stack_base.push(poseidon_output);
  424. }
  425. ZkFunctionCall::Add(lhs_idx, rhs_idx) => {
  426. assert!(*lhs_idx < stack_base.len());
  427. assert!(*rhs_idx < stack_base.len());
  428. let (lhs, rhs) = (stack_base[*lhs_idx], stack_base[*rhs_idx]);
  429. let output =
  430. arith_chip.add(layouter.namespace(|| "arithmetic add"), lhs, rhs)?;
  431. stack_base.push(output);
  432. }
  433. ZkFunctionCall::ConstrainInstance(arg_idx) => {
  434. assert!(*arg_idx < stack_base.len());
  435. let arg = stack_base[*arg_idx];
  436. layouter.constrain_instance(
  437. arg.cell(),
  438. config.primary,
  439. current_instance_offset,
  440. )?;
  441. current_instance_offset += 1;
  442. }
  443. ZkFunctionCall::EcMulShort(value_idx, point_idx) => {
  444. assert!(*value_idx < stack_base.len());
  445. let value = stack_base[*value_idx];
  446. assert!(*point_idx < stack_ec_fixed_point.len());
  447. let fixed_point = stack_ec_fixed_point[*point_idx];
  448. // This constant one is used for multiplication
  449. let one = self.load_private(
  450. layouter.namespace(|| "load constant one"),
  451. config.advices[0],
  452. Some(pallas::Base::one()),
  453. )?;
  454. // v * G_1
  455. let (result, _) = {
  456. let value_commit_v = FixedPoint::from_inner(ecc_chip.clone(), fixed_point);
  457. value_commit_v.mul_short(
  458. layouter.namespace(|| "[value] ValueCommitV"),
  459. (value, one),
  460. )?
  461. };
  462. stack_ec_point.push(result);
  463. }
  464. ZkFunctionCall::EcMul(value_idx, point_idx) => {
  465. assert!(*value_idx < stack_scalar.len());
  466. let value = stack_scalar[*value_idx];
  467. assert!(*point_idx < stack_ec_fixed_point.len());
  468. let fixed_point = stack_ec_fixed_point[*point_idx];
  469. let (result, _) = {
  470. let value_commit_r = FixedPoint::from_inner(ecc_chip.clone(), fixed_point);
  471. value_commit_r
  472. .mul(layouter.namespace(|| "[value_blind] ValueCommitR"), value)?
  473. };
  474. stack_ec_point.push(result);
  475. }
  476. ZkFunctionCall::EcAdd(lhs_idx, rhs_idx) => {
  477. assert!(*lhs_idx < stack_ec_point.len());
  478. assert!(*rhs_idx < stack_ec_point.len());
  479. let lhs = &stack_ec_point[*lhs_idx];
  480. let rhs = &stack_ec_point[*rhs_idx];
  481. let result = lhs.add(layouter.namespace(|| "valuecommit"), rhs)?;
  482. stack_ec_point.push(result);
  483. }
  484. ZkFunctionCall::EcGetX(arg_idx) => {
  485. assert!(*arg_idx < stack_ec_point.len());
  486. let arg = &stack_ec_point[*arg_idx];
  487. let x = arg.inner().x();
  488. stack_base.push(x);
  489. }
  490. ZkFunctionCall::EcGetY(arg_idx) => {
  491. assert!(*arg_idx < stack_ec_point.len());
  492. let arg = &stack_ec_point[*arg_idx];
  493. let y = arg.inner().y();
  494. stack_base.push(y);
  495. }
  496. ZkFunctionCall::CalculateMerkleRoot(path_idx, leaf_idx) => {
  497. assert!(*path_idx < stack_merkle_path.len());
  498. assert!(*leaf_idx < stack_base.len());
  499. let (leaf_pos, path) = &stack_merkle_path[*path_idx];
  500. let leaf = &stack_base[*leaf_idx];
  501. let path = MerklePath {
  502. chip_1: config.merkle_chip_1(),
  503. chip_2: config.merkle_chip_2(),
  504. domain: OrchardHashDomains::MerkleCrh,
  505. leaf_pos: leaf_pos.clone(),
  506. path: path.clone(),
  507. };
  508. let root =
  509. path.calculate_root(layouter.namespace(|| "calculate root"), leaf.clone())?;
  510. stack_base.push(root);
  511. }
  512. }
  513. }
  514. // At this point we've enforced all of our public inputs.
  515. Ok(())
  516. }
  517. }