lead.rs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. use incrementalmerkletree::{bridgetree::BridgeTree, Frontier, Tree};
  2. use halo2_gadgets::primitives::{
  3. poseidon,
  4. poseidon::{ConstantLength, P128Pow5T3},
  5. };
  6. use halo2_proofs::dev::MockProver;
  7. use rand::{thread_rng, Rng};
  8. use pasta_curves::{pallas, Fp};
  9. use darkfi::{
  10. crypto::{
  11. constants::{
  12. NullifierK, OrchardFixedBases, OrchardFixedBasesFull, ValueCommitV,
  13. MERKLE_DEPTH_ORCHARD,
  14. },
  15. keypair::{Keypair, PublicKey, SecretKey},
  16. merkle_node::MerkleNode,
  17. nullifier::Nullifier,
  18. proof::{Proof, ProvingKey, VerifyingKey},
  19. types::*,
  20. util::{mod_r_p, pedersen_commitment_scalar, pedersen_commitment_u64},
  21. },
  22. zk::circuit::lead_contract::LeadContract,
  23. };
  24. use incrementalmerkletree::Hashable;
  25. use pasta_curves::{
  26. arithmetic::CurveAffine,
  27. group::{ff::PrimeField, Curve, GroupEncoding},
  28. };
  29. //use halo2_proofs::arithmetic::CurveAffine;
  30. #[derive(Debug, Default, Clone, Copy)]
  31. pub struct Coin {
  32. value: Option<pallas::Base>, //stake
  33. cm: Option<pallas::Point>,
  34. cm2: Option<pallas::Point>,
  35. sl: Option<pallas::Base>, //slot id
  36. tau: Option<pallas::Base>,
  37. nonce: Option<pallas::Base>,
  38. nonce_cm: Option<pallas::Point>,
  39. sn: Option<pallas::Point>, // coin's serial number
  40. //sk : Option<SecretKey>,
  41. pk: Option<pallas::Point>,
  42. pk_x: Option<pallas::Base>,
  43. pk_y: Option<pallas::Base>,
  44. root_cm: Option<pallas::Scalar>,
  45. root_sk: Option<pallas::Base>,
  46. path: Option<[MerkleNode; MERKLE_DEPTH_ORCHARD]>,
  47. path_sk: Option<[MerkleNode; MERKLE_DEPTH_ORCHARD]>,
  48. opening1: Option<pallas::Base>,
  49. opening2: Option<pallas::Base>,
  50. }
  51. fn create_coins_sks(len : usize) ->
  52. (Vec<MerkleNode>, Vec<[MerkleNode; MERKLE_DEPTH_ORCHARD]>)
  53. {
  54. /*
  55. at the onset of an epoch, the first slot's coin's secret key
  56. is sampled at random, and the reset of the secret keys are derived,
  57. for sk (secret key) at time i+1 is derived from secret key at time i.
  58. */
  59. let mut rng = thread_rng();
  60. let sk: u64 = rng.gen();
  61. let mut tree = BridgeTree::<MerkleNode, 32>::new(len);
  62. let mut root_sks: Vec<MerkleNode> = vec![];
  63. let mut path_sks: Vec<[MerkleNode; MERKLE_DEPTH_ORCHARD]> = vec![];
  64. for i in 0..len {
  65. //TODO (research) why the conversion between point and base is panicing?
  66. // is the endianess different?
  67. let base = pedersen_commitment_scalar(pallas::Scalar::one(), pallas::Scalar::from(sk));
  68. let coord = base.to_affine().coordinates().unwrap();
  69. let coord_prod = coord.x() * coord.y();
  70. let node = MerkleNode(coord_prod);
  71. tree.append(&node.clone());
  72. let leaf_position = tree.witness();
  73. //let (leaf_pos, path) = tree.authentication_path(leaf_position.unwrap()).unwrap();
  74. let path = tree.authentication_path(leaf_position.unwrap()).unwrap();
  75. root_sks.push(tree.root().clone());
  76. path_sks.push(path.as_slice().try_into().unwrap());
  77. }
  78. (root_sks, path_sks)
  79. }
  80. /*
  81. fn create_coins(...)
  82. {
  83. }
  84. fn build_commit_tree(cms : Vec<Coin>)
  85. {
  86. //
  87. }
  88. */
  89. fn main() {
  90. let k = 13;
  91. //
  92. const LEN: usize = 10;
  93. let mut rng = thread_rng();
  94. let mut root_sks: Vec<MerkleNode> = vec![];
  95. let mut path_sks: Vec<[MerkleNode; MERKLE_DEPTH_ORCHARD]> = vec![];
  96. (root_sks, path_sks) = create_coins_sks(LEN);
  97. /*
  98. for i in 0..LEN {
  99. let sk: u64 = rng.gen();
  100. let node = MerkleNode(pallas::Base::from(sk));
  101. tree.append(&node.clone());
  102. let leaf_position = tree.witness();
  103. //let (leaf_pos, path) = tree.authentication_path(leaf_position.unwrap()).unwrap();
  104. let path = tree.authentication_path(leaf_position.unwrap()).unwrap();
  105. root_sks.push(tree.root().clone());
  106. path_sks.push(path.as_slice().try_into().unwrap());
  107. }
  108. */
  109. let mut seeds: Vec<u64> = vec![];
  110. for i in 0..LEN {
  111. let rho: u64 = rng.gen();
  112. seeds.push(rho.clone());
  113. }
  114. //
  115. let yu64: u64 = rng.gen();
  116. let rhou64: u64 = rng.gen();
  117. let mau_y: pallas::Base = pallas::Base::from(yu64);
  118. let mau_rho: pallas::Base = pallas::Base::from(rhou64);
  119. //
  120. let mut coins: Vec<Coin> = vec![];
  121. //
  122. let mut tree_cm = BridgeTree::<MerkleNode, 32>::new(LEN);
  123. let zerou64: u64 = 0;
  124. for i in 0..LEN {
  125. let c_v = pallas::Base::from(u64::try_from(i * 2).unwrap());
  126. //random sampling of the same size of prf,
  127. //pseudo random sampling that is the size of pederson commitment
  128. let iu64: u64 = u64::try_from(i).unwrap();
  129. let c_sl = pallas::Base::from(iu64);
  130. let c_tau = pallas::Base::from(u64::try_from(i).unwrap()); // let's assume it's sl for simplicity
  131. let c_root_sk: MerkleNode = root_sks[i];
  132. let c_pk = pedersen_commitment_scalar(mod_r_p(c_tau), mod_r_p(c_root_sk.inner()));
  133. let c_seed = pallas::Base::from(seeds[i]);
  134. let c_sn = pedersen_commitment_scalar(mod_r_p(c_seed), mod_r_p(c_root_sk.inner()));
  135. let c_pk_pt = c_pk.to_affine().coordinates().unwrap();
  136. let c_pk_pt_x: pallas::Base = *c_pk_pt.x();
  137. let c_pk_pt_y: pallas::Base = *c_pk_pt.y();
  138. let c_cm_v = c_v.clone() * c_seed.clone() * c_pk_pt_x * c_pk_pt_y;
  139. let c_cm1_blind = pallas::Base::from(1); //tmp val
  140. let c_cm2_blind = pallas::Base::from(1); //tmp val
  141. let c_cm: pallas::Point = pedersen_commitment_scalar(mod_r_p(c_cm_v), mod_r_p(c_cm1_blind));
  142. let c_cm_coordinates = c_cm.to_affine().coordinates().unwrap();
  143. let c_cm_base: pallas::Base = c_cm_coordinates.x() * c_cm_coordinates.y();
  144. let c_cm_node = MerkleNode(c_cm_base);
  145. tree_cm.append(&c_cm_node.clone());
  146. let leaf_position = tree_cm.witness();
  147. let c_cm_path = tree_cm.authentication_path(leaf_position.unwrap()).unwrap();
  148. let c_root_cm = tree_cm.root();
  149. // lead coin commitment
  150. let c_seed2 = pedersen_commitment_scalar(mod_r_p(c_seed), mod_r_p(c_root_sk.inner()));
  151. let c_seed2_pt = c_seed2.to_affine().coordinates().unwrap();
  152. /*
  153. let lead_coin_msg = [c_pk_pt_y.clone(),
  154. c_pk_pt_x.clone(),
  155. c_v,
  156. *c_seed2_pt.x(),
  157. *c_seed2_pt.y()
  158. ];
  159. let lead_coin_msg_hash =
  160. poseidon::Hash::<_, P128Pow5T3, ConstantLength<5>, 3, 2>::init().hash(lead_coin_msg);
  161. */
  162. let lead_coin_msg =
  163. c_pk_pt_y.clone() * c_pk_pt_x.clone() * c_v * *c_seed2_pt.x() * *c_seed2_pt.y();
  164. let c_cm2 = pedersen_commitment_scalar(mod_r_p(lead_coin_msg), mod_r_p(c_cm2_blind));
  165. let c_root_sk = root_sks[i];
  166. let c_root_sk_bytes: [u8; 32] = c_root_sk.inner().to_repr();
  167. let mut c_root_sk_base_bytes: [u8; 32] = [0; 32];
  168. for i in 0..23 {
  169. c_root_sk_base_bytes[i] = c_root_sk_bytes[i];
  170. }
  171. let c_root_sk_base = pallas::Base::from_repr(c_root_sk_base_bytes);
  172. let c_path_sk = path_sks[i];
  173. let coin = Coin {
  174. value: Some(c_v),
  175. cm: Some(c_cm),
  176. cm2: Some(c_cm2),
  177. sl: Some(c_sl),
  178. tau: Some(c_tau),
  179. nonce: Some(c_seed),
  180. nonce_cm: Some(c_seed2),
  181. sn: Some(c_sn),
  182. pk: Some(c_pk),
  183. pk_x: Some(c_pk_pt_x),
  184. pk_y: Some(c_pk_pt_y),
  185. root_cm: Some(mod_r_p(c_root_cm.inner())),
  186. root_sk: Some(c_root_sk.inner()),
  187. path: Some(c_cm_path.as_slice().try_into().unwrap()),
  188. path_sk: Some(c_path_sk),
  189. opening1: Some(c_cm1_blind),
  190. opening2: Some(c_cm2_blind),
  191. };
  192. coins.push(coin);
  193. }
  194. // ================
  195. // public inputs
  196. // ================
  197. let coin_idx = 0;
  198. let coin = coins[coin_idx];
  199. let po_nonce = coin.nonce_cm.unwrap().to_affine().coordinates().unwrap();
  200. let po_nonce = coin.nonce_cm.unwrap().to_affine().coordinates().unwrap();
  201. let po_tau = pedersen_commitment_scalar(mod_r_p(coin.tau.unwrap()), coin.root_cm.unwrap())
  202. .to_affine()
  203. .coordinates()
  204. .unwrap();
  205. let po_cm = coin.cm.unwrap().to_affine().coordinates().unwrap();
  206. let po_cm2 = coin.cm2.unwrap().to_affine().coordinates().unwrap();
  207. let po_pk = coin.pk.unwrap().to_affine().coordinates().unwrap();
  208. let po_sn = coin.sn.unwrap().to_affine().coordinates().unwrap();
  209. let po_cmp = pallas::Base::from(0);
  210. let zero = pallas::Base::from(0);
  211. // ===============
  212. let path_sk = path_sks[coin_idx];
  213. let cm_pos = u32::try_from(coin_idx).unwrap();
  214. let contract = LeadContract {
  215. path: coin.path,
  216. coin_pk_x: coin.pk_x,
  217. coin_pk_y: coin.pk_y,
  218. root_sk: coin.root_sk,
  219. path_sk: Some(path_sk),
  220. coin_timestamp: coin.tau, //
  221. coin_nonce: coin.nonce,
  222. coin_opening_1: Some(mod_r_p(coin.opening1.unwrap())),
  223. value: coin.value,
  224. coin_opening_2: Some(mod_r_p(coin.opening2.unwrap())),
  225. cm_pos: Some(cm_pos),
  226. //sn_c1: Some(coin.sn.unwrap()),
  227. slot: Some(coin.sl.unwrap()),
  228. mau_rho: Some(mau_rho.clone()),
  229. mau_y: Some(mau_y.clone()),
  230. root_cm: Some(coin.root_cm.unwrap()),
  231. };
  232. let cm_root = {
  233. let pos: u32 = cm_pos;
  234. let c_cm_coordinates = coin.cm.unwrap().to_affine().coordinates().unwrap();
  235. let c_cm_base: pallas::Base = c_cm_coordinates.x() * c_cm_coordinates.y();
  236. let mut current = MerkleNode(c_cm_base);
  237. for (level, sibling) in coin.path.unwrap().iter().enumerate() {
  238. let level = level as u8;
  239. current = if pos & (1 << level) == 0 {
  240. MerkleNode::combine(level.into(), &current, sibling)
  241. } else {
  242. MerkleNode::combine(level.into(), sibling, &current)
  243. };
  244. }
  245. current
  246. };
  247. let mut public_inputs: Vec<pallas::Base> = vec![
  248. *po_nonce.x(),
  249. *po_nonce.y(),
  250. *po_pk.x(),
  251. *po_pk.y(),
  252. *po_sn.x(),
  253. *po_sn.y(),
  254. *po_cm.x(),
  255. *po_cm.y(),
  256. *po_cm2.x(),
  257. *po_cm2.y(),
  258. cm_root.0,
  259. po_cmp,
  260. ];
  261. let prover = MockProver::run(k, &contract, vec![public_inputs]).unwrap();
  262. //
  263. assert_eq!(prover.verify(), Ok(()));
  264. //
  265. }