vm.rs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  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::{Hash as PoseidonHash, Pow5T3Chip as PoseidonChip, Pow5T3Config as PoseidonConfig},
  13. primitives::poseidon::{ConstantLength, P128Pow5T3},
  14. sinsemilla::{
  15. chip::{SinsemillaChip, SinsemillaConfig},
  16. merkle::{
  17. chip::{MerkleChip, MerkleConfig},
  18. MerklePath,
  19. },
  20. },
  21. utilities::{
  22. lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, Var,
  23. },
  24. };
  25. use pasta_curves::pallas;
  26. use crate::{
  27. crypto::{
  28. arith_chip::{ArithmeticChip, ArithmeticChipConfig},
  29. constants::{
  30. sinsemilla::{OrchardCommitDomains, OrchardHashDomains},
  31. OrchardFixedBases,
  32. },
  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 [(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 [(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. 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. 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::MerklePath {
  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. 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.witness_base.keys().map(|key| (key.clone(), None)).collect(),
  205. witness_scalar: self.witness_scalar.keys().map(|key| (key.clone(), None)).collect(),
  206. witness_merkle_path: self
  207. .witness_scalar
  208. .keys()
  209. .map(|key| (key.clone(), (None, None)))
  210. .collect(),
  211. }
  212. }
  213. fn configure(meta: &mut ConstraintSystem<pallas::Base>) -> Self::Config {
  214. let advices = [
  215. meta.advice_column(),
  216. meta.advice_column(),
  217. meta.advice_column(),
  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. ];
  226. let q_add = meta.selector();
  227. let table_idx = meta.lookup_table_column();
  228. let lookup = (table_idx, meta.lookup_table_column(), meta.lookup_table_column());
  229. let primary = meta.instance_column();
  230. meta.enable_equality(primary.into());
  231. for advice in advices.iter() {
  232. meta.enable_equality((*advice).into());
  233. }
  234. let lagrange_coeffs = [
  235. meta.fixed_column(),
  236. meta.fixed_column(),
  237. meta.fixed_column(),
  238. meta.fixed_column(),
  239. meta.fixed_column(),
  240. meta.fixed_column(),
  241. meta.fixed_column(),
  242. meta.fixed_column(),
  243. ];
  244. let rc_a = lagrange_coeffs[2..5].try_into().unwrap();
  245. let rc_b = lagrange_coeffs[5..8].try_into().unwrap();
  246. meta.enable_constant(lagrange_coeffs[0]);
  247. let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx);
  248. let ecc_config = EccChip::<OrchardFixedBases>::configure(
  249. meta,
  250. advices,
  251. lagrange_coeffs,
  252. range_check.clone(),
  253. );
  254. let poseidon_config = PoseidonChip::configure(
  255. meta,
  256. P128Pow5T3,
  257. advices[6..9].try_into().unwrap(),
  258. advices[5],
  259. rc_a,
  260. rc_b,
  261. );
  262. let arith_config = ArithmeticChip::configure(meta);
  263. // Configuration for a Sinsemilla hash instantiation and a
  264. // Merkle hash instantiation using this Sinsemilla instance.
  265. // Since the Sinsemilla config uses only 5 advice columns,
  266. // we can fit two instances side-by-side.
  267. let (sinsemilla_config_1, merkle_config_1) = {
  268. let sinsemilla_config_1 = SinsemillaChip::configure(
  269. meta,
  270. advices[..5].try_into().unwrap(),
  271. advices[6],
  272. lagrange_coeffs[0],
  273. lookup,
  274. range_check.clone(),
  275. );
  276. let merkle_config_1 = MerkleChip::configure(meta, sinsemilla_config_1.clone());
  277. (sinsemilla_config_1, merkle_config_1)
  278. };
  279. // Configuration for a Sinsemilla hash instantiation and a
  280. // Merkle hash instantiation using this Sinsemilla instance.
  281. // Since the Sinsemilla config uses only 5 advice columns,
  282. // we can fit two instances side-by-side.
  283. let (sinsemilla_config_2, merkle_config_2) = {
  284. let sinsemilla_config_2 = SinsemillaChip::configure(
  285. meta,
  286. advices[5..].try_into().unwrap(),
  287. advices[7],
  288. lagrange_coeffs[1],
  289. lookup,
  290. range_check,
  291. );
  292. let merkle_config_2 = MerkleChip::configure(meta, sinsemilla_config_2.clone());
  293. (sinsemilla_config_2, merkle_config_2)
  294. };
  295. MintConfig {
  296. primary,
  297. q_add,
  298. advices,
  299. ecc_config,
  300. merkle_config_1,
  301. merkle_config_2,
  302. sinsemilla_config_1,
  303. sinsemilla_config_2,
  304. poseidon_config,
  305. arith_config,
  306. }
  307. }
  308. fn synthesize(
  309. &self,
  310. config: Self::Config,
  311. mut layouter: impl Layouter<pallas::Base>,
  312. ) -> std::result::Result<(), plonk::Error> {
  313. // Load the Sinsemilla generator lookup table used by the whole circuit.
  314. SinsemillaChip::load(config.sinsemilla_config_1.clone(), &mut layouter)?;
  315. let arith_chip = config.arithmetic_chip();
  316. // Construct the ECC chip.
  317. let ecc_chip = config.ecc_chip();
  318. let mut stack_base = Vec::new();
  319. let mut stack_scalar = Vec::new();
  320. let mut stack_ec_point = Vec::new();
  321. let mut stack_ec_fixed_point = Vec::new();
  322. let mut stack_merkle_path = Vec::new();
  323. // Load constants first onto the stacks
  324. for (variable, type_id) in self.constants.iter() {
  325. match *type_id {
  326. ZkType::Base => {
  327. unimplemented!();
  328. }
  329. ZkType::Scalar => {
  330. unimplemented!();
  331. }
  332. ZkType::EcPoint => {
  333. unimplemented!();
  334. }
  335. ZkType::EcFixedPoint => {
  336. let value = self.const_fixed_points[variable];
  337. stack_ec_fixed_point.push(value);
  338. }
  339. ZkType::MerklePath => {
  340. unimplemented!();
  341. }
  342. }
  343. }
  344. // Push the witnesses onto the stacks in order
  345. for (variable, type_id) in self.contract.witness.iter() {
  346. match *type_id {
  347. ZkType::Base => {
  348. let value = self.witness_base.get(variable).expect("witness base set");
  349. let value = self.load_private(
  350. layouter.namespace(|| "load pubkey x"),
  351. config.advices[0],
  352. *value,
  353. )?;
  354. stack_base.push(value);
  355. }
  356. ZkType::Scalar => {
  357. let value = self.witness_scalar.get(variable).expect("witness base set");
  358. stack_scalar.push(*value);
  359. }
  360. ZkType::EcPoint => {
  361. unimplemented!();
  362. }
  363. ZkType::EcFixedPoint => {
  364. unimplemented!();
  365. }
  366. ZkType::MerklePath => {
  367. let value =
  368. self.witness_merkle_path.get(variable).expect("witness merkle path set");
  369. stack_merkle_path.push(*value);
  370. }
  371. }
  372. }
  373. let mut current_instance_offset = 0;
  374. for func_call in self.contract.code.iter() {
  375. match func_call {
  376. ZkFunctionCall::PoseidonHash(lhs_idx, rhs_idx) => {
  377. assert!(*lhs_idx < stack_base.len());
  378. assert!(*rhs_idx < stack_base.len());
  379. let poseidon_message = [stack_base[*lhs_idx], stack_base[*rhs_idx]];
  380. let poseidon_hasher = PoseidonHash::<_, _, P128Pow5T3, _, 3, 2>::init(
  381. config.poseidon_chip(),
  382. layouter.namespace(|| "Poseidon init"),
  383. ConstantLength::<2>,
  384. )?;
  385. let poseidon_output = poseidon_hasher
  386. .hash(layouter.namespace(|| "poseidon hash"), poseidon_message)?;
  387. let poseidon_output: CellValue<pallas::Base> = poseidon_output.inner().into();
  388. stack_base.push(poseidon_output);
  389. }
  390. ZkFunctionCall::Add(lhs_idx, rhs_idx) => {
  391. assert!(*lhs_idx < stack_base.len());
  392. assert!(*rhs_idx < stack_base.len());
  393. let (lhs, rhs) = (stack_base[*lhs_idx], stack_base[*rhs_idx]);
  394. let output =
  395. arith_chip.add(layouter.namespace(|| "arithmetic add"), lhs, rhs)?;
  396. stack_base.push(output);
  397. }
  398. ZkFunctionCall::ConstrainInstance(arg_idx) => {
  399. assert!(*arg_idx < stack_base.len());
  400. let arg = stack_base[*arg_idx];
  401. layouter.constrain_instance(
  402. arg.cell(),
  403. config.primary,
  404. current_instance_offset,
  405. )?;
  406. current_instance_offset += 1;
  407. }
  408. ZkFunctionCall::EcMulShort(value_idx, point_idx) => {
  409. assert!(*value_idx < stack_base.len());
  410. let value = stack_base[*value_idx];
  411. assert!(*point_idx < stack_ec_fixed_point.len());
  412. let fixed_point = stack_ec_fixed_point[*point_idx];
  413. // This constant one is used for multiplication
  414. let one = self.load_private(
  415. layouter.namespace(|| "load constant one"),
  416. config.advices[0],
  417. Some(pallas::Base::one()),
  418. )?;
  419. // v * G_1
  420. let (result, _) = {
  421. let value_commit_v = FixedPoint::from_inner(ecc_chip.clone(), fixed_point);
  422. value_commit_v.mul_short(
  423. layouter.namespace(|| "[value] ValueCommitV"),
  424. (value, one),
  425. )?
  426. };
  427. stack_ec_point.push(result);
  428. }
  429. ZkFunctionCall::EcMul(value_idx, point_idx) => {
  430. assert!(*value_idx < stack_scalar.len());
  431. let value = stack_scalar[*value_idx];
  432. assert!(*point_idx < stack_ec_fixed_point.len());
  433. let fixed_point = stack_ec_fixed_point[*point_idx];
  434. let (result, _) = {
  435. let value_commit_r = FixedPoint::from_inner(ecc_chip.clone(), fixed_point);
  436. value_commit_r
  437. .mul(layouter.namespace(|| "[value_blind] ValueCommitR"), value)?
  438. };
  439. stack_ec_point.push(result);
  440. }
  441. ZkFunctionCall::EcAdd(lhs_idx, rhs_idx) => {
  442. assert!(*lhs_idx < stack_ec_point.len());
  443. assert!(*rhs_idx < stack_ec_point.len());
  444. let lhs = &stack_ec_point[*lhs_idx];
  445. let rhs = &stack_ec_point[*rhs_idx];
  446. let result = lhs.add(layouter.namespace(|| "valuecommit"), rhs)?;
  447. stack_ec_point.push(result);
  448. }
  449. ZkFunctionCall::EcGetX(arg_idx) => {
  450. assert!(*arg_idx < stack_ec_point.len());
  451. let arg = &stack_ec_point[*arg_idx];
  452. let x = arg.inner().x();
  453. stack_base.push(x);
  454. }
  455. ZkFunctionCall::EcGetY(arg_idx) => {
  456. assert!(*arg_idx < stack_ec_point.len());
  457. let arg = &stack_ec_point[*arg_idx];
  458. let y = arg.inner().y();
  459. stack_base.push(y);
  460. }
  461. ZkFunctionCall::CalculateMerkleRoot(path_idx, leaf_idx) => {
  462. assert!(*path_idx < stack_merkle_path.len());
  463. assert!(*leaf_idx < stack_base.len());
  464. let (leaf_pos, path) = &stack_merkle_path[*path_idx];
  465. let leaf = &stack_base[*leaf_idx];
  466. let path = MerklePath {
  467. chip_1: config.merkle_chip_1(),
  468. chip_2: config.merkle_chip_2(),
  469. domain: OrchardHashDomains::MerkleCrh,
  470. leaf_pos: *leaf_pos,
  471. path: *path,
  472. };
  473. let root =
  474. path.calculate_root(layouter.namespace(|| "calculate root"), *leaf)?;
  475. stack_base.push(root);
  476. }
  477. }
  478. }
  479. // At this point we've enforced all of our public inputs.
  480. Ok(())
  481. }
  482. }