vm2.rs 20 KB

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