leadcoin.rs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2022 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use darkfi_sdk::{
  19. crypto::{
  20. pedersen::{pedersen_commitment_base, pedersen_commitment_u64},
  21. poseidon_hash,
  22. util::mod_r_p,
  23. MerkleNode, PublicKey, SecretKey,
  24. },
  25. pasta::{arithmetic::CurveAffine, group::Curve, pallas},
  26. };
  27. use halo2_proofs::{arithmetic::Field, circuit::Value};
  28. use incrementalmerkletree::{bridgetree::BridgeTree, Tree};
  29. use log::debug;
  30. use rand::rngs::OsRng;
  31. use super::constants::{EPOCH_LENGTH, PRF_NULLIFIER_PREFIX};
  32. use crate::{
  33. crypto::{proof::ProvingKey, Proof},
  34. zk::{vm::ZkCircuit, vm_stack::Witness},
  35. zkas::ZkBinary,
  36. Result,
  37. };
  38. pub const MERKLE_DEPTH_LEADCOIN: usize = 32;
  39. pub const MERKLE_DEPTH: u8 = 32;
  40. // TODO: Unify item names with the names in the ZK proof (those are more descriptive)
  41. /// Structure representing the consensus leader coin
  42. #[derive(Debug, Clone, Copy)]
  43. pub struct LeadCoin {
  44. /// Coin's stake value
  45. pub value: u64,
  46. /// Commitment for coin1
  47. pub coin1_commitment: pallas::Point,
  48. /// Commitment for coin2 (poured coin)
  49. pub coin2_commitment: pallas::Point,
  50. /// Coin index
  51. pub idx: u32,
  52. /// Coin slot ID,
  53. pub sl: pallas::Base,
  54. /// Coin timestamp
  55. pub tau: pallas::Base,
  56. /// Coin nonce
  57. pub nonce: pallas::Base,
  58. /// Coin nonce's commitment
  59. pub nonce_cm: pallas::Base,
  60. /// Coin's serial number
  61. pub sn: pallas::Base,
  62. /// Merkle root of coin1 commitment
  63. pub coin1_commitment_root: MerkleNode,
  64. /// Merkle root of the `coin1` secret key
  65. pub coin1_sk_root: MerkleNode,
  66. /// coin1 sk position in merkle tree
  67. pub coin1_sk_pos: u32,
  68. /// Merkle path to the coin1's commitment
  69. pub coin1_commitment_merkle_path: [MerkleNode; MERKLE_DEPTH_LEADCOIN],
  70. /// Merkle path to the secret key of `coin1`
  71. pub coin1_sk_merkle_path: [MerkleNode; MERKLE_DEPTH_LEADCOIN],
  72. /// coin1 commitment blinding factor
  73. pub coin1_blind: pallas::Scalar,
  74. /// coin2 commitment blinding factor
  75. pub coin2_blind: pallas::Scalar,
  76. /// Leader election nonce derived from eta at onset of epoch
  77. pub y_mu: pallas::Base,
  78. /// Leader election nonce derived from eta at onset of epoch
  79. pub rho_mu: pallas::Base,
  80. /// First coefficient in 1-term T (target function) approximation.
  81. /// NOTE: sigma1 and sigma2 are not the capital sigma from the paper, but
  82. /// the whole coefficient multiplied with absolute stake.
  83. pub sigma1: pallas::Base,
  84. /// Second coefficient in 2-term T (target function) approximation.
  85. pub sigma2: pallas::Base,
  86. /// Coin's secret key
  87. pub secret_key: SecretKey,
  88. }
  89. impl LeadCoin {
  90. /// Create a new `LeadCoin` object using given parameters.
  91. pub fn new(
  92. // wtf is eta and why is it not in the zk proof?
  93. eta: pallas::Base,
  94. // First coefficient in 1-term T (target function) approximation.
  95. sigma1: pallas::Base,
  96. // Second coefficient in 2-term T (target function) approximation.
  97. sigma2: pallas::Base,
  98. // Stake value
  99. value: u64,
  100. // Slot index in the epock
  101. slot_index: usize,
  102. // Merkle root of the `coin_1` secret key in the Merkle tree of secret keys
  103. coin1_sk_root: MerkleNode,
  104. // sk pos
  105. coin1_sk_pos: usize,
  106. // Merkle path to the secret key of `coin_1` in the Merkle tree of secret keys
  107. coin1_sk_merkle_path: [MerkleNode; MERKLE_DEPTH_LEADCOIN],
  108. // what's seed supposed to be?
  109. seed: u64,
  110. // what is this SecretKey representing?
  111. secret_key: SecretKey,
  112. // Merkle tree of coin commitments
  113. coin_commitment_tree: &mut BridgeTree<MerkleNode, MERKLE_DEPTH>,
  114. ) -> Self {
  115. // Generate random blinding values for commitments:
  116. let coin1_blind = pallas::Scalar::random(&mut OsRng);
  117. let coin2_blind = pallas::Scalar::random(&mut OsRng);
  118. // Derive a public key from the secret key
  119. let public_key = PublicKey::from_secret(secret_key);
  120. let (coin_pk_x, coin_pk_y) = public_key.xy();
  121. debug!("coin_pk[{}] x: {:?}", slot_index, coin_pk_x);
  122. debug!("coin_pk[{}] y: {:?}", slot_index, coin_pk_y);
  123. // Derive a nullifier
  124. let sn_msg = [
  125. pallas::Base::from(seed),
  126. coin1_sk_root.inner(),
  127. pallas::Base::zero(),
  128. pallas::Base::one(),
  129. ];
  130. let c_sn = poseidon_hash(sn_msg);
  131. // Derive input for the commitment of coin1
  132. let coin1_commit_msg = [
  133. pallas::Base::from(PRF_NULLIFIER_PREFIX),
  134. coin_pk_x,
  135. coin_pk_y,
  136. pallas::Base::from(value),
  137. pallas::Base::from(seed),
  138. pallas::Base::one(),
  139. ];
  140. let coin1_commit_v = poseidon_hash(coin1_commit_msg);
  141. // Create commitment to coin1
  142. let coin1_commitment = pedersen_commitment_base(coin1_commit_v, coin1_blind);
  143. // Hash its coordinates to get a base field element
  144. let c1_cm_coords = coin1_commitment.to_affine().coordinates().unwrap();
  145. let c1_base_msg = [*c1_cm_coords.x(), *c1_cm_coords.y()];
  146. let coin1_commitment_base = poseidon_hash(c1_base_msg);
  147. // Append the element to the Merkle tree
  148. coin_commitment_tree.append(&MerkleNode::from(coin1_commitment_base));
  149. let leaf_pos = coin_commitment_tree.witness().unwrap();
  150. let coin1_commitment_root = coin_commitment_tree.root(0).unwrap();
  151. let coin1_commitment_merkle_path =
  152. coin_commitment_tree.authentication_path(leaf_pos, &coin1_commitment_root).unwrap();
  153. // Derive the nonce for coin2
  154. let coin2_nonce_msg = [
  155. pallas::Base::from(seed),
  156. coin1_sk_root.inner(),
  157. pallas::Base::one(),
  158. pallas::Base::one(),
  159. ];
  160. let coin2_seed = poseidon_hash(coin2_nonce_msg);
  161. debug!("coin2_seed[{}]: {:?}", slot_index, coin2_seed);
  162. // Derive input for the commitment of coin2
  163. let coin2_commit_msg = [
  164. pallas::Base::from(PRF_NULLIFIER_PREFIX),
  165. coin_pk_x,
  166. coin_pk_y,
  167. pallas::Base::from(value),
  168. coin2_seed,
  169. pallas::Base::one(),
  170. ];
  171. let coin2_commit_v = poseidon_hash(coin2_commit_msg);
  172. // Create commitment to coin2
  173. let coin2_commitment = pedersen_commitment_base(coin2_commit_v, coin2_blind);
  174. // Derive election seeds
  175. let (y_mu, rho_mu) = Self::election_seeds(eta, pallas::Base::from(slot_index as u64));
  176. // Return the object
  177. Self {
  178. value,
  179. coin1_commitment,
  180. coin2_commitment,
  181. // TODO: Should be abs slot
  182. idx: u32::try_from(usize::from(leaf_pos)).unwrap(),
  183. sl: pallas::Base::from(slot_index as u64),
  184. // Assume tau is sl for simplicity
  185. tau: pallas::Base::from(slot_index as u64),
  186. nonce: pallas::Base::from(seed),
  187. nonce_cm: coin2_seed,
  188. sn: c_sn,
  189. coin1_commitment_root,
  190. coin1_sk_root,
  191. coin1_sk_pos: u32::try_from(usize::from(coin1_sk_pos)).unwrap(),
  192. coin1_commitment_merkle_path: coin1_commitment_merkle_path.try_into().unwrap(),
  193. coin1_sk_merkle_path,
  194. coin1_blind,
  195. coin2_blind,
  196. y_mu,
  197. rho_mu,
  198. sigma1,
  199. sigma2,
  200. secret_key,
  201. }
  202. }
  203. /// Derive election seeds from given parameters
  204. fn election_seeds(eta: pallas::Base, slot: pallas::Base) -> (pallas::Base, pallas::Base) {
  205. let election_seed_nonce = pallas::Base::from(3);
  206. let election_seed_lead = pallas::Base::from(22);
  207. // mu_y
  208. let lead_msg = [election_seed_lead, eta, slot];
  209. let lead_mu = poseidon_hash(lead_msg);
  210. // mu_rho
  211. let nonce_msg = [election_seed_nonce, eta, slot];
  212. let nonce_mu = poseidon_hash(nonce_msg);
  213. (lead_mu, nonce_mu)
  214. }
  215. /// Create a vector of `pallas::Base` elements from the `LeadCoin` to be
  216. /// used as public inputs for the ZK proof.
  217. pub fn public_inputs(&self) -> Vec<pallas::Base> {
  218. let prefix_evl = pallas::Base::from(2);
  219. let prefix_pk = pallas::Base::from(4);
  220. let prefix_pk = pallas::Base::from(5);
  221. let zero = pallas::Base::zero();
  222. // pk
  223. let pk_msg = [prefix_pk, self.coin1_sk_root.inner(), self.tau, zero];
  224. let pk = poseidon_hash(pk_msg);
  225. // rho
  226. let rho_msg = [prefix_evl, self.coin1_sk_root.inner(), self.nonce, zero];
  227. let c2_rho = poseidon_hash(rho_msg);
  228. // coin 1-2 cm/commitment
  229. let c1_cm = self.coin1_commitment.to_affine().coordinates().unwrap();
  230. let c2_cm = self.coin2_commitment.to_affine().coordinates().unwrap();
  231. // lottery seed
  232. let seed_msg = [self.coin1_sk_root.inner(), self.nonce];
  233. let seed = poseidon_hash(seed_msg);
  234. // y
  235. let y = pedersen_commitment_base(seed, mod_r_p(self.y_mu));
  236. let y_coords = y.to_affine().coordinates().unwrap();
  237. // rho
  238. let rho = pedersen_commitment_base(seed, mod_r_p(self.rho_mu));
  239. let rho_coord = rho.to_affine().coordinates().unwrap();
  240. vec![
  241. pk,
  242. c2_rho,
  243. *c1_cm.x(),
  244. *c1_cm.y(),
  245. *c2_cm.x(),
  246. *c2_cm.y(),
  247. self.coin1_commitment_root.inner(),
  248. self.coin1_sk_root.inner(),
  249. self.sn,
  250. *y_coords.x(),
  251. *y_coords.y(),
  252. *rho_coord.x(),
  253. *rho_coord.y(),
  254. ]
  255. }
  256. /// Try to create a ZK proof of consensus leadership
  257. pub fn create_lead_proof(&self, pk: &ProvingKey) -> Result<Proof> {
  258. let bincode = include_bytes!("../../proof/lead.zk.bin");
  259. let zkbin = ZkBinary::decode(bincode)?;
  260. let prover_witnesses = vec![
  261. Witness::MerklePath(Value::known(self.coin1_commitment_merkle_path)),
  262. Witness::Uint32(Value::known(self.idx)),
  263. Witness::Uint32(Value::known(self.coin1_sk_pos)),
  264. Witness::Base(Value::known(self.secret_key.inner())),
  265. Witness::Base(Value::known(self.coin1_sk_root.inner())),
  266. Witness::MerklePath(Value::known(self.coin1_sk_merkle_path)),
  267. Witness::Base(Value::known(self.tau)),
  268. Witness::Base(Value::known(self.nonce)),
  269. Witness::Scalar(Value::known(self.coin1_blind)),
  270. Witness::Base(Value::known(pallas::Base::from(self.value))),
  271. Witness::Scalar(Value::known(self.coin2_blind)),
  272. Witness::Scalar(Value::known(mod_r_p(self.rho_mu))),
  273. Witness::Scalar(Value::known(mod_r_p(self.y_mu))),
  274. Witness::Base(Value::known(self.sigma1)),
  275. Witness::Base(Value::known(self.sigma2)),
  276. ];
  277. let circuit = ZkCircuit::new(prover_witnesses, zkbin.clone());
  278. Ok(Proof::create(pk, &[circuit], &self.public_inputs(), &mut OsRng)?)
  279. }
  280. }
  281. /// This struct holds the secrets for creating LeadCoins during one epoch.
  282. pub struct LeadCoinSecrets {
  283. pub secret_keys: Vec<SecretKey>,
  284. pub merkle_roots: Vec<MerkleNode>,
  285. pub merkle_paths: Vec<[MerkleNode; MERKLE_DEPTH_LEADCOIN]>,
  286. }
  287. impl LeadCoinSecrets {
  288. /// Generate epoch coins secret keys.
  289. /// First clot coin secret key is sampled at random, while the secret keys of the
  290. /// remaining slots derive from the previous slot secret.
  291. /// Clarification:
  292. /// ```plaintext
  293. /// sk[0] -> random,
  294. /// sk[1] -> derive_function(sk[0]),
  295. /// ...
  296. /// sk[n] -> derive_function(sk[n-1]),
  297. /// ```
  298. pub fn generate() -> Self {
  299. let mut tree = BridgeTree::<MerkleNode, MERKLE_DEPTH>::new(EPOCH_LENGTH);
  300. let mut sks = Vec::with_capacity(EPOCH_LENGTH);
  301. let mut root_sks = Vec::with_capacity(EPOCH_LENGTH);
  302. let mut path_sks = Vec::with_capacity(EPOCH_LENGTH);
  303. let mut prev_sk = SecretKey::from(pallas::Base::one());
  304. for i in 0..EPOCH_LENGTH {
  305. let secret = if i == 0 {
  306. pedersen_commitment_u64(1, pallas::Scalar::random(&mut OsRng))
  307. } else {
  308. pedersen_commitment_u64(1, mod_r_p(prev_sk.inner()))
  309. };
  310. let secret_coords = secret.to_affine().coordinates().unwrap();
  311. let secret_msg = [*secret_coords.x(), *secret_coords.y()];
  312. let secret_key = SecretKey::from(poseidon_hash(secret_msg));
  313. sks.push(secret_key);
  314. prev_sk = secret_key;
  315. let node = MerkleNode::from(secret_key.inner());
  316. tree.append(&node);
  317. let leaf_pos = tree.witness().unwrap();
  318. let root = tree.root(0).unwrap();
  319. let path = tree.authentication_path(leaf_pos, &root).unwrap();
  320. root_sks.push(root);
  321. path_sks.push(path.try_into().unwrap());
  322. }
  323. Self { secret_keys: sks, merkle_roots: root_sks, merkle_paths: path_sks }
  324. }
  325. }