epoch.rs 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. use halo2_proofs::{arithmetic::Field, dev::MockProver, circuit::Value};
  2. use incrementalmerkletree::{bridgetree::BridgeTree, Tree};
  3. use halo2_gadgets::poseidon::primitives as poseidon;
  4. use pasta_curves::{
  5. arithmetic::CurveAffine,
  6. group::{ff::PrimeField, Curve},
  7. pallas,
  8. };
  9. use rand::{thread_rng, Rng};
  10. use crate::{
  11. crypto::{
  12. constants::MERKLE_DEPTH_ORCHARD,
  13. leadcoin::LeadCoin,
  14. merkle_node::MerkleNode,
  15. util::{mod_r_p, pedersen_commitment_scalar},
  16. types::DrkValueBlind,
  17. },
  18. };
  19. const MERKLE_DEPTH: u8 = MERKLE_DEPTH_ORCHARD as u8;
  20. #[derive(Copy,Debug,Default,Clone)]
  21. pub struct EpochItem {
  22. pub value: u64, // the stake value is static during the epoch.
  23. }
  24. #[derive(Copy,Debug,Default,Clone)]
  25. pub struct Epoch {
  26. // TODO this need to emulate epoch
  27. // should have ep, slot, current block, etc.
  28. //epoch metadata
  29. pub len: Option<usize>, // number of slots in the epoch
  30. //epoch item
  31. pub item: Option<EpochItem>,
  32. pub eta: pallas::Base, // CRS for the leader selection.
  33. }
  34. #[derive(Debug,Default,Clone)]
  35. pub struct LifeTime {
  36. //lifetime metadata
  37. //...
  38. //lifetime epochs
  39. pub epochs : Vec<Epoch>,
  40. }
  41. impl Epoch {
  42. fn create_coins_election_seeds(&self, sl: pallas::Base) -> (pallas::Base, pallas::Base) {
  43. let ELECTION_SEED_NONCE : pallas::Base = pallas::Base::from(3);
  44. let ELECTION_SEED_LEAD : pallas::Base = pallas::Base::from(22);
  45. // mu_rho
  46. let nonce_mu_msg = [
  47. ELECTION_SEED_NONCE,
  48. self.eta,
  49. sl,
  50. ];
  51. let nonce_mu : pallas::Base = poseidon::Hash::<_, poseidon::P128Pow5T3, poseidon::ConstantLength<3>, 3, 2>::init().hash(nonce_mu_msg);
  52. // mu_y
  53. let lead_mu_msg = [
  54. ELECTION_SEED_LEAD,
  55. self.eta,
  56. sl,
  57. ];
  58. let lead_mu : pallas::Base = poseidon::Hash::<_, poseidon::P128Pow5T3, poseidon::ConstantLength<3>, 3, 2>::init().hash(lead_mu_msg);
  59. (lead_mu, nonce_mu)
  60. }
  61. fn create_coins_sks(&self) -> (Vec<MerkleNode>, Vec<[MerkleNode; MERKLE_DEPTH_ORCHARD]>) {
  62. /*
  63. at the onset of an epoch, the first slot's coin's secret key
  64. is sampled at random, and the rest of the secret keys are derived,
  65. for sk (secret key) at time i+1 is derived from secret key at time i.
  66. */
  67. let mut rng = thread_rng();
  68. let mut tree = BridgeTree::<MerkleNode, MERKLE_DEPTH>::new(self.len.unwrap() as usize);
  69. let mut root_sks: Vec<MerkleNode> = vec![];
  70. let mut path_sks: Vec<[MerkleNode; MERKLE_DEPTH_ORCHARD]> = vec![];
  71. let mut prev_sk_base : pallas::Base = pallas::Base::one();
  72. for _i in 0..self.len.unwrap() {
  73. let sk_bytes = if _i ==0 {
  74. let base = pedersen_commitment_scalar(pallas::Scalar::one(), pallas::Scalar::random(&mut rng));
  75. let coord = base.to_affine().coordinates().unwrap();
  76. //let sk_base = coord.x() * coord.y();
  77. let sk_base = pallas::Base::one();
  78. prev_sk_base = sk_base;
  79. sk_base.to_repr()
  80. } else {
  81. /*
  82. let base = pedersen_commitment_scalar(pallas::Scalar::one(), mod_r_p(prev_sk_base));
  83. let coord = base.to_affine().coordinates().unwrap();
  84. let sk_base = coord.x() * coord.y();
  85. prev_sk_base = sk_base;
  86. sk_base.to_repr()
  87. */
  88. let base = pedersen_commitment_scalar(pallas::Scalar::one(), pallas::Scalar::random(&mut rng));
  89. let coord = base.to_affine().coordinates().unwrap();
  90. //let sk_base = coord.x() * coord.y();
  91. let sk_base = pallas::Base::one();
  92. prev_sk_base = sk_base;
  93. sk_base.to_repr()
  94. };
  95. let node = MerkleNode::from_bytes(&sk_bytes).unwrap();
  96. //let serialized = serde_json::to_string(&node).unwrap();
  97. //println!("serialized: {}", serialized);
  98. tree.append(&node.clone());
  99. let leaf_position = tree.witness();
  100. let root = tree.root(0).unwrap();
  101. //let (leaf_pos, path) = tree.authentication_path(leaf_position.unwrap()).unwrap();
  102. let path = tree.authentication_path(leaf_position.unwrap(), &root).unwrap();
  103. //note root sk is at tree.root()
  104. //root_sks.push(node);
  105. root_sks.push(root);
  106. path_sks.push(path.as_slice().try_into().unwrap());
  107. }
  108. (root_sks, path_sks)
  109. }
  110. //note! the strategy here is single competing coin per slot.
  111. pub fn create_coins(&self) -> Vec<LeadCoin> {
  112. let mut rng = thread_rng();
  113. let mut seeds: Vec<u64> = vec![];
  114. for _i in 0..self.len.unwrap() {
  115. let rho: u64 = rng.gen();
  116. seeds.push(rho);
  117. }
  118. let (root_sks, path_sks) = self.create_coins_sks();
  119. let cm1_val: u64 = rng.gen();
  120. //random commitment blinding values
  121. let c_cm1_blind: DrkValueBlind = pallas::Scalar::random(&mut rng);
  122. let c_cm2_blind: DrkValueBlind = pallas::Scalar::random(&mut rng);
  123. let mut tree_cm = BridgeTree::<MerkleNode, MERKLE_DEPTH>::new(self.len.unwrap() as usize);
  124. let mut coins: Vec<LeadCoin> = vec![];
  125. for i in 0..self.len.unwrap() {
  126. let c_v = pallas::Base::from(self.item.unwrap().value);
  127. //random sampling of the same size of prf,
  128. //pseudo random sampling that is the size of pederson commitment
  129. // coin slot number
  130. //TODO (fix) need to be multiplied by the ep
  131. let c_sl = pallas::Base::from(u64::try_from(i).unwrap());
  132. //
  133. //TODO (fix)
  134. let c_tau = pallas::Base::from(u64::try_from(i).unwrap()); // let's assume it's sl for simplicity
  135. //
  136. let c_root_sk: MerkleNode = root_sks[i];
  137. let c_pk = pedersen_commitment_scalar(mod_r_p(c_tau), mod_r_p(c_root_sk.inner()));
  138. let c_seed = pallas::Base::from(seeds[i]);
  139. let c_sn = pedersen_commitment_scalar(mod_r_p(c_seed), mod_r_p(c_root_sk.inner()));
  140. let c_pk_pt = c_pk.to_affine().coordinates().unwrap();
  141. let c_pk_pt_x: pallas::Base = *c_pk_pt.x();
  142. let c_pk_pt_y: pallas::Base = *c_pk_pt.y();
  143. //
  144. let lead_coin_msg = [
  145. //TODO (fix)
  146. pallas::Scalar::one(),
  147. //c_pk_pt_x.clone(),
  148. //c_pk_pt_y.clone(),
  149. //c_v,
  150. //*c_seed_pt.x(), //TODO(fix) will be c_seed(base) only after calculating c_seed as hash
  151. //*c_seed_pt.y(),
  152. ];
  153. let lead_coin_msg_hash : pallas::Scalar = poseidon::Hash::<_, poseidon::P128Pow5T3, poseidon::ConstantLength<1>, 3, 2>::init().hash(lead_coin_msg);
  154. //TODO (FIX) THIS PANICS, ONLY PANICS ON LARGE VALUES!
  155. //let c_cm: pallas::Point = pedersen_commitment_scalar(lead_coin_msg_hash, c_cm1_blind);
  156. //note c_v is set to zero, should work
  157. let c_cm: pallas::Point = pedersen_commitment_scalar(mod_r_p(c_v), c_cm1_blind);
  158. let c_cm_coordinates = c_cm.to_affine().coordinates().unwrap();
  159. let c_cm_base: pallas::Base = c_cm_coordinates.x() * c_cm_coordinates.y();
  160. let c_cm_node = MerkleNode(c_cm_base);
  161. tree_cm.append(&c_cm_node.clone());
  162. let leaf_position = tree_cm.witness();
  163. let c_root_cm = tree_cm.root(0).unwrap();
  164. let c_cm_path = tree_cm.authentication_path(leaf_position.unwrap(), &c_root_cm).unwrap();
  165. // lead coin commitment
  166. let c_seed2 = pedersen_commitment_scalar(mod_r_p(c_seed), mod_r_p(c_root_sk.inner()));
  167. let c_seed2_pt = c_seed2.to_affine().coordinates().unwrap();
  168. let lead_coin_msg = [
  169. //c_pk_pt_y.clone(),
  170. //c_pk_pt_x.clone(),
  171. //c_v,
  172. //c_seed,
  173. pallas::Base::one(),
  174. ];
  175. let lead_coin_msg_hash : pallas::Base = poseidon::Hash::<_, poseidon::P128Pow5T3, poseidon::ConstantLength<1>, 3, 2>::init().hash(lead_coin_msg);
  176. let c_cm2 = pedersen_commitment_scalar(mod_r_p(lead_coin_msg_hash), c_cm2_blind);
  177. let c_root_sk = root_sks[i];
  178. let c_root_sk_bytes: [u8; 32] = c_root_sk.inner().to_repr();
  179. let mut c_root_sk_base_bytes: [u8; 32] = [0; 32];
  180. //TODO (fix) using only first 24, use the whoel root
  181. c_root_sk_base_bytes[..23].copy_from_slice(&c_root_sk_bytes[..23]);
  182. let _c_root_sk_base = pallas::Base::from_repr(c_root_sk_base_bytes);
  183. let c_path_sk = path_sks[i];
  184. // election seeds
  185. let (y_mu, rho_mu) = self.create_coins_election_seeds(c_sl);
  186. let coin = LeadCoin {
  187. value: Some(c_v),
  188. cm: Some(c_cm),
  189. cm2: Some(c_cm2),
  190. idx: u32::try_from(i).unwrap(),
  191. sl: Some(c_sl),
  192. tau: Some(c_tau),
  193. nonce: Some(c_seed),
  194. nonce_cm: Some(c_seed2),
  195. sn: Some(c_sn),
  196. pk: Some(c_pk),
  197. pk_x: Some(c_pk_pt_x),
  198. pk_y: Some(c_pk_pt_y),
  199. root_cm: Some(mod_r_p(c_root_cm.inner())),
  200. root_sk: Some(c_root_sk.inner()),
  201. path: Some(c_cm_path.as_slice().try_into().unwrap()),
  202. path_sk: Some(c_path_sk),
  203. c1_blind: Some(c_cm1_blind),
  204. c2_blind: Some(c_cm2_blind),
  205. y_mu: Some(y_mu),
  206. rho_mu: Some(rho_mu),
  207. };
  208. coins.push(coin);
  209. }
  210. coins
  211. }
  212. }