vm2.rs 15 KB

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