lead.rs 8.6 KB

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