state.rs 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2023 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 std::time::Duration;
  19. use chrono::{NaiveDateTime, Utc};
  20. use darkfi_sdk::{
  21. crypto::{constants::MERKLE_DEPTH, MerkleNode},
  22. incrementalmerkletree::bridgetree::BridgeTree,
  23. pasta::{group::ff::PrimeField, pallas},
  24. };
  25. use darkfi_serial::{SerialDecodable, SerialEncodable};
  26. use log::info;
  27. use rand::{thread_rng, Rng};
  28. use super::{
  29. constants,
  30. leadcoin::{LeadCoin, LeadCoinSecrets},
  31. utils::fbig2base,
  32. Block, BlockProposal, Float10,
  33. };
  34. use crate::{blockchain::Blockchain, net, tx::Transaction, util::time::Timestamp, Error, Result};
  35. use std::io::{prelude::*, BufWriter};
  36. use std::fs::File;
  37. /// This struct represents the information required by the consensus algorithm
  38. pub struct ConsensusState {
  39. /// Canonical (finalized) blockchain
  40. pub blockchain: Blockchain,
  41. /// Network bootstrap timestamp
  42. pub bootstrap_ts: Timestamp,
  43. /// Genesis block creation timestamp
  44. pub genesis_ts: Timestamp,
  45. /// Genesis block hash
  46. pub genesis_block: blake3::Hash,
  47. /// Total sum of initial staking coins
  48. pub initial_distribution: u64,
  49. /// Slot the network was bootstrapped
  50. pub bootstrap_slot: u64,
  51. /// Participating start slot
  52. pub participating: Option<u64>,
  53. /// Node is able to propose proposals
  54. pub proposing: bool,
  55. /// Last slot node check for finalization
  56. pub checked_finalization: u64,
  57. /// Slots offset since genesis,
  58. pub offset: Option<u64>,
  59. /// Fork chains containing block proposals
  60. pub forks: Vec<Fork>,
  61. /// Current epoch
  62. pub epoch: u64,
  63. /// Current epoch eta
  64. pub epoch_eta: pallas::Base,
  65. /// Hot/live slot checkpoints
  66. pub slot_checkpoints: Vec<SlotCheckpoint>,
  67. /// Leaders count history
  68. pub leaders_history: Vec<u64>,
  69. /// controller output history
  70. pub f_history: Vec<Float10>,
  71. /// controller proportional error history
  72. pub err_history: Vec<Float10>,
  73. // TODO: Aren't these already in db after finalization?
  74. /// Canonical competing coins
  75. pub coins: Vec<LeadCoin>,
  76. /// Canonical coin commitments tree
  77. pub coins_tree: BridgeTree<MerkleNode, MERKLE_DEPTH>,
  78. /// Canonical seen nullifiers from proposals
  79. pub nullifiers: Vec<pallas::Base>,
  80. }
  81. impl ConsensusState {
  82. pub fn new(
  83. blockchain: Blockchain,
  84. bootstrap_ts: Timestamp,
  85. genesis_ts: Timestamp,
  86. genesis_data: blake3::Hash,
  87. initial_distribution: u64,
  88. ) -> Result<Self> {
  89. let genesis_block = Block::genesis_block(genesis_ts, genesis_data).blockhash();
  90. Ok(Self {
  91. blockchain,
  92. bootstrap_ts,
  93. genesis_ts,
  94. genesis_block,
  95. initial_distribution,
  96. bootstrap_slot: 0,
  97. participating: None,
  98. proposing: false,
  99. checked_finalization: 0,
  100. offset: None,
  101. forks: vec![],
  102. epoch: 0,
  103. epoch_eta: pallas::Base::zero(),
  104. slot_checkpoints: vec![],
  105. leaders_history: vec![0],
  106. f_history: vec![constants::FLOAT10_ZERO.clone()],
  107. err_history: vec![constants::FLOAT10_ZERO.clone(),
  108. constants::FLOAT10_ZERO.clone()],
  109. coins: vec![],
  110. coins_tree: BridgeTree::<MerkleNode, MERKLE_DEPTH>::new(constants::EPOCH_LENGTH * 100),
  111. nullifiers: vec![],
  112. })
  113. }
  114. /// Calculates current epoch.
  115. pub fn current_epoch(&self) -> u64 {
  116. self.slot_epoch(self.current_slot())
  117. }
  118. /// Calculates the epoch of the provided slot.
  119. /// Epoch duration is configured using the `EPOCH_LENGTH` value.
  120. pub fn slot_epoch(&self, slot: u64) -> u64 {
  121. slot / constants::EPOCH_LENGTH as u64
  122. }
  123. /// Calculates current slot, based on elapsed time from the genesis block.
  124. /// Slot duration is configured using the `SLOT_TIME` constant.
  125. pub fn current_slot(&self) -> u64 {
  126. self.genesis_ts.elapsed() / constants::SLOT_TIME
  127. }
  128. /// Calculates the relative number of the provided slot.
  129. pub fn relative_slot(&self, slot: u64) -> u64 {
  130. slot % constants::EPOCH_LENGTH as u64
  131. }
  132. /// Finds the last slot a proposal or block was generated.
  133. pub fn last_slot(&self) -> Result<u64> {
  134. let mut slot = 0;
  135. for chain in &self.forks {
  136. for state_checkpoint in &chain.sequence {
  137. if state_checkpoint.proposal.block.header.slot > slot {
  138. slot = state_checkpoint.proposal.block.header.slot;
  139. }
  140. }
  141. }
  142. // We return here in case proposals exist,
  143. // so we don't query the sled database.
  144. if slot > 0 {
  145. return Ok(slot)
  146. }
  147. let (last_slot, _) = self.blockchain.last()?;
  148. Ok(last_slot)
  149. }
  150. /// Calculates seconds until next Nth slot starting time.
  151. /// Slots duration is configured using the SLOT_TIME constant.
  152. pub fn next_n_slot_start(&self, n: u64) -> Duration {
  153. assert!(n > 0);
  154. let start_time = NaiveDateTime::from_timestamp_opt(self.genesis_ts.0, 0).unwrap();
  155. let current_slot = self.current_slot() + n;
  156. let next_slot_start =
  157. (current_slot * constants::SLOT_TIME) + (start_time.timestamp() as u64);
  158. let next_slot_start = NaiveDateTime::from_timestamp_opt(next_slot_start as i64, 0).unwrap();
  159. let current_time = NaiveDateTime::from_timestamp_opt(Utc::now().timestamp(), 0).unwrap();
  160. let diff = next_slot_start - current_time;
  161. Duration::new(diff.num_seconds().try_into().unwrap(), 0)
  162. }
  163. /// Calculate slots until next Nth epoch.
  164. /// Epoch duration is configured using the EPOCH_LENGTH value.
  165. pub fn slots_to_next_n_epoch(&self, n: u64) -> u64 {
  166. assert!(n > 0);
  167. let slots_till_next_epoch =
  168. constants::EPOCH_LENGTH as u64 - self.relative_slot(self.current_slot());
  169. ((n - 1) * constants::EPOCH_LENGTH as u64) + slots_till_next_epoch
  170. }
  171. /// Calculates seconds until next Nth epoch starting time.
  172. pub fn next_n_epoch_start(&self, n: u64) -> Duration {
  173. self.next_n_slot_start(self.slots_to_next_n_epoch(n))
  174. }
  175. /// Set participating slot to next.
  176. pub fn set_participating(&mut self) -> Result<()> {
  177. self.participating = Some(self.current_slot() + 1);
  178. Ok(())
  179. }
  180. /// Generate current slot checkpoint
  181. fn generate_slot_checkpoint(&mut self, sigma1: pallas::Base, sigma2: pallas::Base) {
  182. let slot = self.current_slot();
  183. let eta = self.get_eta();
  184. info!("generate_slot_checkpoint: slot: {:?}, eta: {:?}", slot, eta);
  185. let checkpoint = SlotCheckpoint { slot, eta, sigma1, sigma2 };
  186. self.slot_checkpoints.push(checkpoint);
  187. }
  188. // Initialize node lead coins and set current epoch and eta.
  189. pub async fn init_coins(&mut self) -> Result<()> {
  190. self.epoch = self.current_epoch();
  191. if self.slot_checkpoints.is_empty() {
  192. // Create slot checkpoint if not on genesis slot (already in db)
  193. if self.current_slot() != 0 {
  194. self.epoch_eta = self.get_eta();
  195. let (sigma1, sigma2) = self.sigmas();
  196. self.generate_slot_checkpoint(sigma1, sigma2);
  197. }
  198. } else {
  199. let last_slot_checkpoint = self.slot_checkpoints.last().unwrap();
  200. self.epoch_eta = last_slot_checkpoint.eta;
  201. };
  202. self.coins = self.create_coins().await?;
  203. self.update_forks_checkpoints();
  204. Ok(())
  205. }
  206. /// Check if new epoch has started and generate slot checkpoint.
  207. /// Returns flag to signify if epoch has changed.
  208. pub async fn epoch_changed(
  209. &mut self,
  210. sigma1: pallas::Base,
  211. sigma2: pallas::Base,
  212. ) -> Result<bool> {
  213. self.generate_slot_checkpoint(sigma1, sigma2);
  214. let epoch = self.current_epoch();
  215. if epoch <= self.epoch {
  216. return Ok(false)
  217. }
  218. self.epoch = epoch;
  219. self.epoch_eta = self.get_eta();
  220. Ok(true)
  221. }
  222. /// Return 2-term target approximation sigma coefficients.
  223. pub fn sigmas(&mut self) -> (pallas::Base, pallas::Base) {
  224. let f = self.win_inv_prob_with_full_stake();
  225. let total_stake = self.total_stake();
  226. info!(target: "consensus::state", "sigmas(): f: {}", f);
  227. info!(target: "consensus::state", "sigmas(): stake: {}", total_stake);
  228. let one = constants::FLOAT10_ONE.clone();
  229. let two = constants::FLOAT10_TWO.clone();
  230. let field_p = Float10::try_from(constants::P).unwrap();
  231. let total_sigma = Float10::try_from(total_stake).unwrap();
  232. let x = one - f;
  233. let c = x.ln();
  234. let sigma1_fbig = c.clone() / total_sigma.clone() * field_p.clone();
  235. let sigma1 = fbig2base(sigma1_fbig);
  236. let sigma2_fbig = (c / total_sigma).powf(two.clone()) * (field_p / two);
  237. let sigma2 = fbig2base(sigma2_fbig);
  238. (sigma1, sigma2)
  239. }
  240. /// Generate coins for provided sigmas.
  241. /// NOTE: The strategy here is having a single competing coin per slot.
  242. // TODO: DRK coin need to be burned, and consensus coin to be minted.
  243. async fn create_coins(&mut self,
  244. //eta: pallas::Base,
  245. ) -> Result<Vec<LeadCoin>> {
  246. let slot = self.current_slot();
  247. // TODO: cleanup LeadCoinSecrets, no need to keep a vector
  248. let mut rng = thread_rng();
  249. let mut seeds: Vec<u64> = Vec::with_capacity(constants::EPOCH_LENGTH);
  250. for _ in 0..constants::EPOCH_LENGTH {
  251. seeds.push(rng.gen());
  252. }
  253. let epoch_secrets = LeadCoinSecrets::generate();
  254. // LeadCoin matrix containing node competing coins.
  255. let mut coins: Vec<LeadCoin> = Vec::with_capacity(constants::EPOCH_LENGTH);
  256. // TODO: TESTNET: Here we would look into the wallet to find coins we're able to use.
  257. // The wallet has specific tables for consensus coins.
  258. // TODO: TESTNET: Token ID still has to be enforced properly in the consensus.
  259. // Temporarily, we compete with fixed stake.
  260. // This stake should be based on how many nodes we want to run, and they all
  261. // must sum to initial distribution total coins.
  262. //let stake = self.initial_distribution;
  263. let coin = LeadCoin::new(
  264. 200,
  265. slot,
  266. epoch_secrets.secret_keys[0].inner(),
  267. epoch_secrets.merkle_roots[0],
  268. 0,
  269. epoch_secrets.merkle_paths[0],
  270. pallas::Base::from(seeds[0]),
  271. &mut self.coins_tree,
  272. );
  273. coins.push(coin);
  274. Ok(coins)
  275. }
  276. /// Leadership reward, assuming constant reward
  277. /// TODO (res) implement reward mechanism with accord to DRK,DARK token-economics
  278. fn reward(&self) -> u64 {
  279. constants::REWARD
  280. }
  281. /// Auxillary function to receive current slot offset.
  282. /// If offset is None, its setted up as last block slot offset.
  283. pub fn get_current_offset(&mut self, current_slot: u64) -> u64 {
  284. // This is the case were we restarted our node, didn't receive offset from other nodes,
  285. // so we need to find offset from last block, exluding network dead period.
  286. if self.offset.is_none() {
  287. let (last_slot, last_offset) = self.blockchain.get_last_offset().unwrap();
  288. let offset = last_offset + (current_slot - last_slot);
  289. info!(target: "consensus::state", "get_current_offset(): Setting slot offset: {}", offset);
  290. self.offset = Some(offset);
  291. }
  292. self.offset.unwrap()
  293. }
  294. /// Auxillary function to calculate overall empty slots.
  295. /// We keep an offset from genesis indicating when the first slot actually started.
  296. /// This offset is shared between nodes.
  297. fn overall_empty_slots(&mut self, current_slot: u64) -> u64 {
  298. // Retrieve existing blocks excluding genesis
  299. let blocks = (self.blockchain.len() as u64) - 1;
  300. // Setup offset if only have genesis and havent received offset from other nodes
  301. if blocks == 0 && self.offset.is_none() {
  302. info!(
  303. target: "consensus::state",
  304. "overall_empty_slots(): Blockchain contains only genesis, setting slot offset: {}",
  305. current_slot
  306. );
  307. self.offset = Some(current_slot);
  308. }
  309. // Retrieve longest fork length, to also those proposals in the calculation
  310. let max_fork_length = self.longest_chain_length() as u64;
  311. current_slot - blocks - self.get_current_offset(current_slot) - max_fork_length
  312. }
  313. /// Network total stake, assuming constant reward.
  314. /// Only used for fine-tuning. At genesis epoch first slot, of absolute index 0,
  315. /// if no stake was distributed, the total stake would be 0.
  316. /// To avoid division by zero, we asume total stake at first division is GENESIS_TOTAL_STAKE(1).
  317. fn total_stake(&mut self) -> u64 {
  318. let current_slot = self.current_slot();
  319. let rewarded_slots = current_slot - self.overall_empty_slots(current_slot) - 1;
  320. let rewards = rewarded_slots * self.reward();
  321. let total_stake = rewards + self.initial_distribution;
  322. if total_stake == 0 {
  323. return constants::GENESIS_TOTAL_STAKE
  324. }
  325. total_stake
  326. }
  327. /// Calculate how many leaders existed in previous slot and appends
  328. /// it to history, to report it if win. On finalization sync period,
  329. /// node replaces its leaders history with the sequence extracted by
  330. /// the longest fork.
  331. fn extend_leaders_history(&mut self) -> Float10 {
  332. let slot = self.current_slot();
  333. let previous_slot = slot - 1;
  334. let mut count = 0;
  335. for chain in &self.forks {
  336. // Previous slot proposals exist at end of each fork
  337. if chain.sequence.last().unwrap().proposal.block.header.slot == previous_slot {
  338. count += 1;
  339. }
  340. }
  341. self.leaders_history.push(count);
  342. info!("extend_leaders_history(): Current leaders history: {:?}", self.leaders_history);
  343. let mut count_str : String = count.to_string();
  344. count_str.push_str(",");
  345. let mut f = File::options().append(true).open(constants::LEADER_HISTORY_LOG).unwrap();
  346. {
  347. let mut writer = BufWriter::new(f);
  348. writer.write(&count_str.into_bytes()).unwrap();
  349. }
  350. Float10::try_from(count as i64).unwrap()
  351. }
  352. fn pid_error(feedback: Float10) -> Float10 {
  353. let target = constants::FLOAT10_ONE.clone();
  354. target - feedback
  355. }
  356. fn f_dif(&mut self) -> Float10 {
  357. let len = self.leaders_history.len();
  358. Self::pid_error(Float10::try_from(self.leaders_history[len-1] as i64).unwrap().with_precision(constants::RADIX_BITS).value())
  359. }
  360. fn max_windowed_forks(&self) -> Float10 {
  361. let mut max: u64 = 5;
  362. let window_size = 10;
  363. let len = self.leaders_history.len();
  364. let window_begining = if len <= (window_size + 1) { 0 } else { len - (window_size + 1) };
  365. for item in &self.leaders_history[window_begining..] {
  366. if *item > max {
  367. max = *item;
  368. }
  369. }
  370. Float10::try_from(max as i64).unwrap()
  371. }
  372. fn tuned_kp(&self) -> Float10 {
  373. //(constants::KP.clone() * constants::FLOAT10_FIVE.clone()) / self.max_windowed_forks()
  374. constants::KP.clone()
  375. }
  376. fn weighted_f_dif(&mut self) -> Float10 {
  377. self.tuned_kp() * self.f_dif()
  378. }
  379. fn f_der(&self) -> Float10 {
  380. let len = self.leaders_history.len();
  381. let last = Float10::try_from(self.leaders_history[len - 1] as i64).unwrap();
  382. let second_to_last = Float10::try_from(self.leaders_history[len - 2] as i64).unwrap();
  383. let mut der =
  384. (Self::pid_error(second_to_last) - Self::pid_error(last)) / constants::DT.clone();
  385. der = if der > constants::MAX_DER.clone() { constants::MAX_DER.clone() } else { der };
  386. der = if der < constants::MIN_DER.clone() { constants::MIN_DER.clone() } else { der };
  387. der
  388. }
  389. fn weighted_f_der(&self) -> Float10 {
  390. constants::KD.clone() * self.f_der()
  391. }
  392. fn f_int(&self) -> Float10 {
  393. let mut sum = constants::FLOAT10_ZERO.clone();
  394. let lead_history_len = self.leaders_history.len();
  395. let history_begin_index = if lead_history_len > 10 { lead_history_len - 10 } else { 0 };
  396. for lf in &self.leaders_history[history_begin_index..] {
  397. sum += Float10::try_from(*lf).unwrap().abs();
  398. }
  399. sum
  400. }
  401. fn tuned_ki(&self) -> Float10 {
  402. //(constants::KI.clone() * constants::FLOAT10_FIVE.clone()) / self.max_windowed_forks()
  403. constants::KI.clone()
  404. }
  405. fn weighted_f_int(&self) -> Float10 {
  406. //constants::KI.clone() * self.f_int()
  407. self.tuned_ki() * self.f_int()
  408. }
  409. fn zero_leads_len(&self) -> Float10 {
  410. let mut count = constants::FLOAT10_ZERO.clone();
  411. let hist_len = self.leaders_history.len();
  412. for i in 1..hist_len {
  413. if self.leaders_history[hist_len - i] == 0 {
  414. count += constants::FLOAT10_ONE.clone();
  415. } else {
  416. break
  417. }
  418. }
  419. count
  420. }
  421. fn pid(&mut self) -> Float10 {
  422. let p = self.weighted_f_dif();
  423. let i = self.weighted_f_int();
  424. let d = self.weighted_f_der();
  425. info!(target: "consensus::state", "win_inv_prob_with_full_stake(): PID P: {:?}", p);
  426. info!(target: "consensus::state", "win_inv_prob_with_full_stake(): PID I: {:?}", i);
  427. info!(target: "consensus::state", "win_inv_prob_with_full_stake(): PID D: {:?}", d);
  428. let f = p + i.clone() + d;
  429. info!("win_inv_prob_with_full_stake(): PID f: {}", f);
  430. f
  431. }
  432. fn discrete_pid(&mut self) -> Float10 {
  433. let k1 = constants::KP.clone() +
  434. constants::KI.clone() +
  435. constants::KD.clone();
  436. let k2 = constants::FLOAT10_NEG_ONE.clone() * constants::KP.clone() -
  437. constants::FLOAT10_NEG_TWO.clone() * constants::KD.clone();
  438. let k3 = constants::KD.clone();
  439. let f_len = self.f_history.len();
  440. let err = self.f_dif();
  441. let err_len = self.err_history.len();
  442. let ret = self.f_history[f_len-1].clone() +
  443. k1 * err.clone() +
  444. k2 * self.err_history[err_len-1].clone() +
  445. k3 * self.err_history[err_len-2].clone();
  446. self.f_history.push(ret.clone());
  447. self.err_history.push(err);
  448. ret
  449. }
  450. /// the probability inverse of winnig lottery having all the stake
  451. /// returns f
  452. fn win_inv_prob_with_full_stake(&mut self) -> Float10 {
  453. self.extend_leaders_history();
  454. //
  455. let f = self.discrete_pid();
  456. // log f history
  457. let file = File::options().append(true).open(constants::F_HISTORY_LOG).unwrap();
  458. {
  459. let mut f_history = format!("{:}", f);
  460. f_history.push_str(",");
  461. let mut writer = BufWriter::new(file);
  462. writer.write(&f_history.into_bytes()).unwrap();
  463. }
  464. if f == constants::FLOAT10_ZERO.clone() {
  465. return constants::MIN_F.clone()
  466. } else if f >= constants::FLOAT10_ONE.clone() {
  467. return constants::MAX_F.clone()
  468. }
  469. let hist_len = self.leaders_history.len();
  470. if hist_len > 3 &&
  471. self.leaders_history[hist_len - 1] == 0 &&
  472. self.leaders_history[hist_len - 2] == 0 &&
  473. self.leaders_history[hist_len - 3] == 0
  474. //&& i == constants::FLOAT10_ZERO.clone()
  475. {
  476. return f * constants::DEG_RATE.clone().powf(self.zero_leads_len())
  477. }
  478. f
  479. }
  480. /// Check that the participant/stakeholder coins win the slot lottery.
  481. /// If the stakeholder has multiple competing winning coins, only the highest value
  482. /// coin is selected, since the stakeholder can't give more than one proof per block/slot.
  483. /// * 'sigma1', 'sigma2': slot sigmas
  484. /// Returns: (check: bool, idx: usize) where idx is the winning coin's index
  485. pub fn is_slot_leader(
  486. &mut self,
  487. sigma1: pallas::Base,
  488. sigma2: pallas::Base,
  489. ) -> (bool, i64, usize) {
  490. // Check if node can produce proposals
  491. if !self.proposing {
  492. return (false, 0, 0)
  493. }
  494. let fork_index = self.longest_chain_index();
  495. let competing_coins = if fork_index == -1 {
  496. self.coins.clone()
  497. } else {
  498. self.forks[fork_index as usize].sequence.last().unwrap().coins.clone()
  499. };
  500. let mut won = false;
  501. let mut highest_stake = 0;
  502. let mut highest_stake_idx = 0;
  503. let total_stake = self.total_stake();
  504. for (winning_idx, coin) in competing_coins.iter().enumerate() {
  505. info!("is_slot_leader: coin stake: {:?}", coin.value);
  506. info!("is_slot_leader: total stake: {}", total_stake);
  507. info!("is_slot_leader: relative stake: {}", (coin.value as f64) / total_stake as f64);
  508. let first_winning = coin.is_leader(sigma1,
  509. sigma2,
  510. self.get_eta(),
  511. pallas::Base::from(self.current_slot()));
  512. if first_winning && !won {
  513. highest_stake_idx = winning_idx;
  514. }
  515. won |= first_winning;
  516. if won && coin.value > highest_stake {
  517. highest_stake = coin.value;
  518. highest_stake_idx = winning_idx;
  519. }
  520. }
  521. (won, fork_index, highest_stake_idx)
  522. }
  523. /// Finds the longest forkchain the node holds and
  524. /// returns its index.
  525. pub fn longest_chain_index(&self) -> i64 {
  526. let mut length = 0;
  527. let mut index = -1;
  528. if !self.forks.is_empty() {
  529. for (i, chain) in self.forks.iter().enumerate() {
  530. if chain.sequence.len() > length {
  531. length = chain.sequence.len();
  532. index = i as i64;
  533. }
  534. }
  535. }
  536. index
  537. }
  538. /// Finds the length of longest fork chain the node holds.
  539. pub fn longest_chain_length(&self) -> usize {
  540. let mut max = 0;
  541. for fork in &self.forks {
  542. if fork.sequence.len() > max {
  543. max = fork.sequence.len();
  544. }
  545. }
  546. max
  547. }
  548. /// Given a proposal, find the index of the fork chain it extends.
  549. pub fn find_extended_chain_index(&mut self, proposal: &BlockProposal) -> Result<i64> {
  550. // We iterate through all forks to find which fork to extend
  551. let mut chain_index = -1;
  552. let mut state_checkpoint_index = 0;
  553. for (c_index, chain) in self.forks.iter().enumerate() {
  554. // Traverse sequence in reverse
  555. for (sc_index, state_checkpoint) in chain.sequence.iter().enumerate().rev() {
  556. if proposal.block.header.previous == state_checkpoint.proposal.hash {
  557. chain_index = c_index as i64;
  558. state_checkpoint_index = sc_index;
  559. break
  560. }
  561. }
  562. if chain_index != -1 {
  563. break
  564. }
  565. }
  566. // If no fork was found, we check with canonical
  567. if chain_index == -1 {
  568. let (last_slot, last_block) = self.blockchain.last()?;
  569. if proposal.block.header.previous != last_block ||
  570. proposal.block.header.slot <= last_slot
  571. {
  572. info!(target: "consensus::state", "find_extended_chain_index(): Proposal doesn't extend any known chain");
  573. return Ok(-2)
  574. }
  575. // Proposal extends canonical chain
  576. return Ok(-1)
  577. }
  578. // Found fork chain
  579. let chain = &self.forks[chain_index as usize];
  580. // Proposal extends fork at last proposal
  581. if state_checkpoint_index == (chain.sequence.len() - 1) {
  582. return Ok(chain_index)
  583. }
  584. info!(target: "consensus::state", "find_extended_chain_index(): Proposal to fork a forkchain was received.");
  585. let mut chain = self.forks[chain_index as usize].clone();
  586. // We keep all proposals until the one it extends
  587. chain.sequence.drain((state_checkpoint_index + 1)..);
  588. self.forks.push(chain);
  589. Ok(self.forks.len() as i64 - 1)
  590. }
  591. /// Search the chains we're holding for the given proposal.
  592. pub fn proposal_exists(&self, input_proposal: &blake3::Hash) -> bool {
  593. for chain in self.forks.iter() {
  594. for state_checkpoint in chain.sequence.iter().rev() {
  595. if input_proposal == &state_checkpoint.proposal.hash {
  596. return true
  597. }
  598. }
  599. }
  600. false
  601. }
  602. /// Auxillary function to set nodes leaders count history to the largest fork sequence
  603. /// of leaders, by using provided index.
  604. pub fn set_leader_history(&mut self, index: i64, current_slot: u64) {
  605. // Check if we found longest fork to extract sequence from
  606. match index {
  607. -1 => {
  608. info!(target: "consensus::state", "set_leader_history(): No fork exists.");
  609. }
  610. _ => {
  611. info!(target: "consensus::state", "set_leader_history(): Checking last proposal of fork: {}", index);
  612. let last_proposal = &self.forks[index as usize].sequence.last().unwrap().proposal;
  613. if last_proposal.block.header.slot == current_slot {
  614. // Replacing our last history element with the leaders one
  615. self.leaders_history.pop();
  616. self.leaders_history.push(last_proposal.block.lead_info.leaders);
  617. info!(target: "consensus::state", "set_leader_history(): New leaders history: {:?}", self.leaders_history);
  618. return
  619. }
  620. }
  621. }
  622. //self.leaders_history.push(0);
  623. }
  624. /// Utility function to extract leader selection lottery randomness(eta),
  625. /// defined as the hash of the previous lead proof converted to pallas base.
  626. pub fn get_eta(&self) -> pallas::Base {
  627. let proof_tx_hash = self.blockchain.get_last_proof_hash().unwrap();
  628. let mut bytes: [u8; 32] = *proof_tx_hash.as_bytes();
  629. // read first 254 bits
  630. bytes[30] = 0;
  631. bytes[31] = 0;
  632. pallas::Base::from_repr(bytes).unwrap()
  633. }
  634. /// Auxillary function to retrieve slot checkpoint of provided slot UID.
  635. pub fn get_slot_checkpoint(&self, slot: u64) -> Result<SlotCheckpoint> {
  636. // Check hot/live slot checkpoints
  637. for slot_checkpoint in self.slot_checkpoints.iter().rev() {
  638. if slot_checkpoint.slot == slot {
  639. return Ok(slot_checkpoint.clone())
  640. }
  641. }
  642. // Check if slot is finalized
  643. if let Ok(slot_checkpoints) = self.blockchain.get_slot_checkpoints_by_slot(&[slot]) {
  644. if !slot_checkpoints.is_empty() {
  645. if let Some(slot_checkpoint) = &slot_checkpoints[0] {
  646. return Ok(slot_checkpoint.clone())
  647. }
  648. }
  649. }
  650. Err(Error::SlotCheckpointNotFound(slot))
  651. }
  652. /// Auxillary function to update all fork state checkpoints to nodes coins current canonical states.
  653. /// Note: This function should only be invoked once on nodes' coins creation.
  654. pub fn update_forks_checkpoints(&mut self) {
  655. for fork in &mut self.forks {
  656. for state_checkpoint in &mut fork.sequence {
  657. state_checkpoint.coins = self.coins.clone();
  658. state_checkpoint.coins_tree = self.coins_tree.clone();
  659. }
  660. }
  661. }
  662. /// Auxiliary structure to reset consensus state for a resync
  663. pub fn reset(&mut self) {
  664. self.participating = None;
  665. self.proposing = false;
  666. self.offset = None;
  667. self.forks = vec![];
  668. self.slot_checkpoints = vec![];
  669. self.leaders_history = vec![0];
  670. self.nullifiers = vec![];
  671. }
  672. }
  673. /// Auxiliary structure used for consensus syncing.
  674. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  675. pub struct ConsensusRequest {}
  676. impl net::Message for ConsensusRequest {
  677. fn name() -> &'static str {
  678. "consensusrequest"
  679. }
  680. }
  681. /// Auxiliary structure used for consensus syncing.
  682. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  683. pub struct ConsensusResponse {
  684. /// Slot the network was bootstrapped
  685. pub bootstrap_slot: u64,
  686. /// Slots offset since genesis,
  687. pub offset: Option<u64>,
  688. /// Hot/live data used by the consensus algorithm
  689. pub forks: Vec<ForkInfo>,
  690. /// Pending transactions
  691. pub unconfirmed_txs: Vec<Transaction>,
  692. /// Hot/live slot checkpoints
  693. pub slot_checkpoints: Vec<SlotCheckpoint>,
  694. /// Leaders count history
  695. pub leaders_history: Vec<u64>,
  696. /// Seen nullifiers from proposals
  697. pub nullifiers: Vec<pallas::Base>,
  698. }
  699. impl net::Message for ConsensusResponse {
  700. fn name() -> &'static str {
  701. "consensusresponse"
  702. }
  703. }
  704. /// Auxiliary structure used for consensus syncing.
  705. #[derive(Debug, SerialEncodable, SerialDecodable)]
  706. pub struct ConsensusSlotCheckpointsRequest {}
  707. impl net::Message for ConsensusSlotCheckpointsRequest {
  708. fn name() -> &'static str {
  709. "consensusslotcheckpointsrequest"
  710. }
  711. }
  712. /// Auxiliary structure used for consensus syncing.
  713. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  714. pub struct ConsensusSlotCheckpointsResponse {
  715. /// Node known bootstrap slot
  716. pub bootstrap_slot: u64,
  717. /// Node has hot/live slot checkpoints
  718. pub is_empty: bool,
  719. }
  720. impl net::Message for ConsensusSlotCheckpointsResponse {
  721. fn name() -> &'static str {
  722. "consensusslotcheckpointsresponse"
  723. }
  724. }
  725. /// Auxiliary structure used to keep track of slot validation parameters.
  726. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  727. pub struct SlotCheckpoint {
  728. /// Slot UID
  729. pub slot: u64,
  730. /// Slot eta
  731. pub eta: pallas::Base,
  732. /// Slot sigma1
  733. pub sigma1: pallas::Base,
  734. /// Slot sigma2
  735. pub sigma2: pallas::Base,
  736. }
  737. impl SlotCheckpoint {
  738. pub fn new(slot: u64, eta: pallas::Base, sigma1: pallas::Base, sigma2: pallas::Base) -> Self {
  739. Self { slot, eta, sigma1, sigma2 }
  740. }
  741. /// Generate the genesis slot checkpoint.
  742. pub fn genesis_slot_checkpoint() -> Self {
  743. let eta = pallas::Base::zero();
  744. let sigma1 = pallas::Base::zero();
  745. let sigma2 = pallas::Base::zero();
  746. Self::new(0, eta, sigma1, sigma2)
  747. }
  748. }
  749. impl net::Message for SlotCheckpoint {
  750. fn name() -> &'static str {
  751. "slotcheckpoint"
  752. }
  753. }
  754. /// Auxiliary structure used for slot checkpoints syncing
  755. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  756. pub struct SlotCheckpointRequest {
  757. /// Slot UID
  758. pub slot: u64,
  759. }
  760. impl net::Message for SlotCheckpointRequest {
  761. fn name() -> &'static str {
  762. "slotcheckpointrequest"
  763. }
  764. }
  765. /// Auxiliary structure used for slot checkpoints syncing
  766. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  767. pub struct SlotCheckpointResponse {
  768. /// Response blocks.
  769. pub slot_checkpoints: Vec<SlotCheckpoint>,
  770. }
  771. impl net::Message for SlotCheckpointResponse {
  772. fn name() -> &'static str {
  773. "slotcheckpointresponse"
  774. }
  775. }
  776. /// Auxiliary structure used to keep track of consensus state checkpoints.
  777. #[derive(Debug, Clone)]
  778. pub struct StateCheckpoint {
  779. /// Block proposal
  780. pub proposal: BlockProposal,
  781. /// Node competing coins current state
  782. pub coins: Vec<LeadCoin>,
  783. /// Coin commitments tree current state
  784. pub coins_tree: BridgeTree<MerkleNode, MERKLE_DEPTH>,
  785. /// Seen nullifiers from proposals current state
  786. pub nullifiers: Vec<pallas::Base>,
  787. }
  788. impl StateCheckpoint {
  789. pub fn new(
  790. proposal: BlockProposal,
  791. coins: Vec<LeadCoin>,
  792. coins_tree: BridgeTree<MerkleNode, MERKLE_DEPTH>,
  793. nullifiers: Vec<pallas::Base>,
  794. ) -> Self {
  795. Self { proposal, coins, coins_tree, nullifiers }
  796. }
  797. }
  798. /// Auxiliary structure used for forked consensus state checkpoints syncing
  799. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  800. pub struct StateCheckpointInfo {
  801. /// Block proposal
  802. pub proposal: BlockProposal,
  803. /// Seen nullifiers from proposals current state
  804. pub nullifiers: Vec<pallas::Base>,
  805. }
  806. impl From<StateCheckpoint> for StateCheckpointInfo {
  807. fn from(state_checkpoint: StateCheckpoint) -> Self {
  808. Self { proposal: state_checkpoint.proposal, nullifiers: state_checkpoint.nullifiers }
  809. }
  810. }
  811. impl From<StateCheckpointInfo> for StateCheckpoint {
  812. fn from(state_checkpoint_info: StateCheckpointInfo) -> Self {
  813. Self {
  814. proposal: state_checkpoint_info.proposal,
  815. coins: vec![],
  816. coins_tree: BridgeTree::<MerkleNode, MERKLE_DEPTH>::new(constants::EPOCH_LENGTH * 100),
  817. nullifiers: state_checkpoint_info.nullifiers,
  818. }
  819. }
  820. }
  821. /// This struct represents a sequence of consensus state checkpoints.
  822. #[derive(Debug, Clone)]
  823. pub struct Fork {
  824. pub genesis_block: blake3::Hash,
  825. pub sequence: Vec<StateCheckpoint>,
  826. }
  827. impl Fork {
  828. pub fn new(genesis_block: blake3::Hash, initial_state_checkpoint: StateCheckpoint) -> Self {
  829. Self { genesis_block, sequence: vec![initial_state_checkpoint] }
  830. }
  831. /// Insertion of a valid state checkpoint.
  832. pub fn add(&mut self, state_checkpoint: &StateCheckpoint) {
  833. if self.check_state_checkpoint(state_checkpoint, self.sequence.last().unwrap()) {
  834. self.sequence.push(state_checkpoint.clone());
  835. }
  836. }
  837. /// A fork chain is considered valid when every state checkpoint is valid,
  838. /// based on the `check_state_checkpoint` function
  839. pub fn check_chain(&self) -> bool {
  840. for (index, state_checkpoint) in self.sequence[1..].iter().enumerate() {
  841. if !self.check_state_checkpoint(state_checkpoint, &self.sequence[index]) {
  842. return false
  843. }
  844. }
  845. true
  846. }
  847. /// A state checkpoint is considered valid when its proposal parent hash is equal to the
  848. /// hash of the previous checkpoint's proposal and their slots are incremental,
  849. /// excluding the genesis block proposal.
  850. pub fn check_state_checkpoint(
  851. &self,
  852. state_checkpoint: &StateCheckpoint,
  853. previous: &StateCheckpoint,
  854. ) -> bool {
  855. if state_checkpoint.proposal.block.header.previous == self.genesis_block {
  856. info!(target: "consensus::state", "check_checkpoint(): Genesis block proposal provided.");
  857. return false
  858. }
  859. if state_checkpoint.proposal.block.header.previous != previous.proposal.hash ||
  860. state_checkpoint.proposal.block.header.slot <= previous.proposal.block.header.slot
  861. {
  862. info!(target: "consensus::state", "check_checkpoint(): Provided state checkpoint proposal is invalid.");
  863. return false
  864. }
  865. // TODO: validate rest checkpoint info(like nullifiers)
  866. true
  867. }
  868. }
  869. /// Auxiliary structure used for forks syncing
  870. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  871. pub struct ForkInfo {
  872. pub genesis_block: blake3::Hash,
  873. pub sequence: Vec<StateCheckpointInfo>,
  874. }
  875. impl From<Fork> for ForkInfo {
  876. fn from(fork: Fork) -> Self {
  877. let mut sequence = vec![];
  878. for state_checkpoint in fork.sequence {
  879. sequence.push(state_checkpoint.into());
  880. }
  881. Self { genesis_block: fork.genesis_block, sequence }
  882. }
  883. }
  884. impl From<ForkInfo> for Fork {
  885. fn from(fork_info: ForkInfo) -> Self {
  886. let mut sequence = vec![];
  887. for checkpoint in fork_info.sequence {
  888. sequence.push(checkpoint.into());
  889. }
  890. Self { genesis_block: fork_info.genesis_block, sequence }
  891. }
  892. }