lead.rs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. use halo2_proofs::{arithmetic::Field, dev::MockProver};
  2. use incrementalmerkletree::{bridgetree::BridgeTree, Tree};
  3. use pasta_curves::{
  4. arithmetic::CurveAffine,
  5. group::{ff::PrimeField, Curve},
  6. pallas,
  7. };
  8. use rand::{thread_rng, Rng};
  9. use darkfi::{
  10. crypto::{
  11. constants::MERKLE_DEPTH_ORCHARD,
  12. leadcoin::LeadCoin,
  13. merkle_node::MerkleNode,
  14. util::{mod_r_p, pedersen_commitment_scalar},
  15. },
  16. zk::circuit::lead_contract::LeadContract,
  17. };
  18. const MERKLE_DEPTH: u8 = MERKLE_DEPTH_ORCHARD as u8;
  19. fn create_coins_sks(len: usize) -> (Vec<MerkleNode>, Vec<[MerkleNode; MERKLE_DEPTH_ORCHARD]>) {
  20. /*
  21. at the onset of an epoch, the first slot's coin's secret key
  22. is sampled at random, and the reset of the secret keys are derived,
  23. for sk (secret key) at time i+1 is derived from secret key at time i.
  24. */
  25. let mut rng = thread_rng();
  26. let sk: u64 = rng.gen();
  27. let mut tree = BridgeTree::<MerkleNode, MERKLE_DEPTH>::new(len);
  28. let mut root_sks: Vec<MerkleNode> = vec![];
  29. let mut path_sks: Vec<[MerkleNode; MERKLE_DEPTH_ORCHARD]> = vec![];
  30. for _i in 0..len {
  31. //TODO (research) why the conversion between point and base is panicing?
  32. // is the endianess different?
  33. let base = pedersen_commitment_scalar(pallas::Scalar::one(), pallas::Scalar::from(sk));
  34. let _coord = base.to_affine().coordinates().unwrap();
  35. //let sk = coord.x() * coord.y();
  36. //let sk = *coord.y();
  37. let sk: [u8; 32] = pallas::Base::random(rng.clone()).to_repr();
  38. let node = MerkleNode::from_bytes(&sk).unwrap();
  39. //let serialized = serde_json::to_string(&node).unwrap();
  40. //println!("serialized: {}", serialized);
  41. tree.append(&node.clone());
  42. let leaf_position = tree.witness();
  43. let root = tree.root(0).unwrap();
  44. //let (leaf_pos, path) = tree.authentication_path(leaf_position.unwrap()).unwrap();
  45. let path = tree.authentication_path(leaf_position.unwrap(), &root).unwrap();
  46. //note root sk is at tree.root()
  47. //root_sks.push(node);
  48. root_sks.push(root);
  49. path_sks.push(path.as_slice().try_into().unwrap());
  50. }
  51. (root_sks, path_sks)
  52. }
  53. fn create_coins(
  54. root_sks: Vec<MerkleNode>,
  55. path_sks: Vec<[MerkleNode; MERKLE_DEPTH_ORCHARD]>,
  56. values: Vec<u64>,
  57. cm1_blind: pallas::Base,
  58. cm2_blind: pallas::Base,
  59. len: usize,
  60. ) -> Vec<LeadCoin> {
  61. let mut rng = thread_rng();
  62. let mut seeds: Vec<u64> = vec![];
  63. for _i in 0..len {
  64. let rho: u64 = rng.gen();
  65. seeds.push(rho);
  66. }
  67. let mut tree_cm = BridgeTree::<MerkleNode, MERKLE_DEPTH>::new(len);
  68. let mut coins: Vec<LeadCoin> = vec![];
  69. for i in 0..len {
  70. let c_v = pallas::Base::from(values[i]);
  71. //random sampling of the same size of prf,
  72. //pseudo random sampling that is the size of pederson commitment
  73. // coin slot number
  74. let c_sl = pallas::Base::from(u64::try_from(i).unwrap());
  75. //
  76. let c_tau = pallas::Base::from(u64::try_from(i).unwrap()); // let's assume it's sl for simplicity
  77. //
  78. let c_root_sk: MerkleNode = root_sks[i];
  79. let c_pk = pedersen_commitment_scalar(mod_r_p(c_tau), mod_r_p(c_root_sk.inner()));
  80. let c_seed = pallas::Base::from(seeds[i]);
  81. let c_sn = pedersen_commitment_scalar(mod_r_p(c_seed), mod_r_p(c_root_sk.inner()));
  82. let c_pk_pt = c_pk.to_affine().coordinates().unwrap();
  83. let c_pk_pt_x: pallas::Base = *c_pk_pt.x();
  84. let c_pk_pt_y: pallas::Base = *c_pk_pt.y();
  85. let c_cm_v = c_v * c_seed * c_pk_pt_x * c_pk_pt_y;
  86. let c_cm1_blind = cm1_blind; //TODO (fix) should be read from DrkValueBlind
  87. let c_cm2_blind = cm2_blind; //TODO (fix) should be read from DrkValueBlind
  88. let c_cm: pallas::Point = pedersen_commitment_scalar(mod_r_p(c_cm_v), mod_r_p(c_cm1_blind));
  89. let c_cm_coordinates = c_cm.to_affine().coordinates().unwrap();
  90. let c_cm_base: pallas::Base = c_cm_coordinates.x() * c_cm_coordinates.y();
  91. let c_cm_node = MerkleNode(c_cm_base);
  92. tree_cm.append(&c_cm_node.clone());
  93. let leaf_position = tree_cm.witness();
  94. let c_root_cm = tree_cm.root(0).unwrap();
  95. let c_cm_path = tree_cm.authentication_path(leaf_position.unwrap(), &c_root_cm).unwrap();
  96. // lead coin commitment
  97. let c_seed2 = pedersen_commitment_scalar(mod_r_p(c_seed), mod_r_p(c_root_sk.inner()));
  98. let c_seed2_pt = c_seed2.to_affine().coordinates().unwrap();
  99. /*
  100. let lead_coin_msg = [c_pk_pt_y.clone(),
  101. c_pk_pt_x.clone(),
  102. c_v,
  103. *c_seed2_pt.x(),
  104. *c_seed2_pt.y()
  105. ];
  106. let lead_coin_msg_hash =
  107. poseidon::Hash::<_, P128Pow5T3, ConstantLength<5>, 3, 2>::init().hash(lead_coin_msg);
  108. */
  109. let lead_coin_msg = c_pk_pt_y * c_pk_pt_x * c_v * *c_seed2_pt.x() * *c_seed2_pt.y();
  110. let c_cm2 = pedersen_commitment_scalar(mod_r_p(lead_coin_msg), mod_r_p(c_cm2_blind));
  111. let c_root_sk = root_sks[i];
  112. let c_root_sk_bytes: [u8; 32] = c_root_sk.inner().to_repr();
  113. let mut c_root_sk_base_bytes: [u8; 32] = [0; 32];
  114. c_root_sk_base_bytes[..23].copy_from_slice(&c_root_sk_bytes[..23]);
  115. let _c_root_sk_base = pallas::Base::from_repr(c_root_sk_base_bytes);
  116. let c_path_sk = path_sks[i];
  117. let coin = LeadCoin {
  118. value: Some(c_v),
  119. cm: Some(c_cm),
  120. cm2: Some(c_cm2),
  121. idx: u32::try_from(i).unwrap(),
  122. sl: Some(c_sl),
  123. tau: Some(c_tau),
  124. nonce: Some(c_seed),
  125. nonce_cm: Some(c_seed2),
  126. sn: Some(c_sn),
  127. pk: Some(c_pk),
  128. pk_x: Some(c_pk_pt_x),
  129. pk_y: Some(c_pk_pt_y),
  130. root_cm: Some(mod_r_p(c_root_cm.inner())),
  131. root_sk: Some(c_root_sk.inner()),
  132. path: Some(c_cm_path.as_slice().try_into().unwrap()),
  133. path_sk: Some(c_path_sk),
  134. opening1: Some(c_cm1_blind),
  135. opening2: Some(c_cm2_blind),
  136. };
  137. coins.push(coin);
  138. }
  139. coins
  140. }
  141. fn main() {
  142. let k: u32 = 13;
  143. //let lead_pk = ProvingKey::build(k, &LeadContract::default());
  144. //let lead_vk = VerifyingKey::build(k, &LeadContract::default());
  145. //
  146. const LEN: usize = 10;
  147. let mut rng = thread_rng();
  148. let mut _root_sks: Vec<MerkleNode> = vec![];
  149. let mut _path_sks: Vec<[MerkleNode; MERKLE_DEPTH_ORCHARD]> = vec![];
  150. let mut values: Vec<u64> = vec![];
  151. for i in 0..LEN {
  152. values.push(u64::try_from(i * 2).unwrap());
  153. }
  154. let cm1_val: u64 = rng.gen();
  155. let cm1_blind: pallas::Base = pallas::Base::from(cm1_val);
  156. let cm2_val: u64 = rng.gen();
  157. let cm2_blind: pallas::Base = pallas::Base::from(cm2_val);
  158. (_root_sks, _path_sks) = create_coins_sks(LEN);
  159. let coins: Vec<LeadCoin> =
  160. create_coins(_root_sks, _path_sks, values, cm1_blind, cm2_blind, LEN);
  161. let coin_idx = 0;
  162. let coin = coins[coin_idx];
  163. let yu64: u64 = rng.gen();
  164. let rhou64: u64 = rng.gen();
  165. let mau_y: pallas::Base = pallas::Base::from(yu64);
  166. let mau_rho: pallas::Base = pallas::Base::from(rhou64);
  167. let contract = LeadContract {
  168. path: coin.path,
  169. coin_pk_x: coin.pk_x,
  170. coin_pk_y: coin.pk_y,
  171. root_sk: coin.root_sk,
  172. sf_root_sk: Some(mod_r_p(coin.root_sk.unwrap())),
  173. path_sk: coin.path_sk,
  174. coin_timestamp: coin.tau, //
  175. coin_nonce: coin.nonce,
  176. coin_opening_1: Some(mod_r_p(coin.opening1.unwrap())),
  177. value: coin.value,
  178. coin_opening_2: Some(mod_r_p(coin.opening2.unwrap())),
  179. cm_pos: Some(coin.idx),
  180. //sn_c1: Some(coin.sn.unwrap()),
  181. slot: Some(coin.sl.unwrap()),
  182. mau_rho: Some(mod_r_p(mau_rho)),
  183. mau_y: Some(mod_r_p(mau_y)),
  184. root_cm: Some(coin.root_cm.unwrap()),
  185. };
  186. //let proof = create_lead_proof(lead_pk.clone(), coin.clone()).unwrap();
  187. //verify_lead_proof(&lead_vk, &proof, coin);
  188. // calculate public inputs
  189. let public_inputs = coin.public_inputs();
  190. let prover = MockProver::run(k, &contract, vec![public_inputs]).unwrap();
  191. //
  192. assert_eq!(prover.verify(), Ok(()));
  193. //
  194. }