vm2.rs 20 KB

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