main.rs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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 async_std::sync::Arc;
  19. use log::{error, info};
  20. use pasta_curves::pallas;
  21. use structopt_toml::{serde::Deserialize, structopt::StructOpt, StructOptToml};
  22. use darkfi::{
  23. async_daemonize, cli_desc,
  24. consensus::coins,
  25. crypto::{
  26. lead_proof,
  27. proof::{ProvingKey, VerifyingKey},
  28. },
  29. node::Client,
  30. wallet::walletdb::init_wallet,
  31. zk::circuit::LeadContract,
  32. Result,
  33. };
  34. const CONFIG_FILE: &str = "crypsinous_playground_config.toml";
  35. const CONFIG_FILE_CONTENTS: &str = include_str!("../crypsinous_playground_config.toml");
  36. #[derive(Clone, Debug, Deserialize, StructOpt, StructOptToml)]
  37. #[serde(default)]
  38. #[structopt(name = "crypsinous_playground", about = cli_desc!())]
  39. struct Args {
  40. #[structopt(short, long)]
  41. /// Configuration file to use
  42. config: Option<String>,
  43. #[structopt(long, default_value = "~/.config/darkfi/crypsinous_playground/wallet.db")]
  44. /// Path to wallet database
  45. wallet_path: String,
  46. #[structopt(long, default_value = "changeme")]
  47. /// Password for the wallet database
  48. wallet_pass: String,
  49. #[structopt(short, default_value = "1")]
  50. /// How many epochs to simulate
  51. epochs: u64,
  52. #[structopt(short, parse(from_occurrences))]
  53. /// Increase verbosity (-vvv supported)
  54. verbose: u8,
  55. }
  56. // The porpuse of this script is to simulate a staker actions through an epoch.
  57. // Main focus is the crypsinous lottery mechanism and the leader proof creation and validation.
  58. // Other flows that happen through a slot, like broadcasting blocks or syncing are out of scope.
  59. async_daemonize!(realmain);
  60. async fn realmain(args: Args, _ex: Arc<smol::Executor<'_>>) -> Result<()> {
  61. // Epochs sanity check
  62. let epochs = args.epochs;
  63. if epochs < 1 {
  64. error!("Epochs must be a positive number.");
  65. return Ok(());
  66. }
  67. info!("Simulation epochs: {}", epochs);
  68. // Initialize wallet that holds coins for staking
  69. let wallet = init_wallet(&args.wallet_path, &args.wallet_pass).await?;
  70. // Initialize client
  71. let client = Arc::new(Client::new(wallet.clone()).await?);
  72. // Retrieving nodes wallet coins
  73. let mut owned = client.get_own_coins().await?;
  74. // If node holds no coins in its wallet, we generate some new staking coins
  75. if owned.is_empty() {
  76. info!("Node wallet is empty, generating new staking coins...");
  77. owned = coins::generate_staking_coins(&wallet).await?;
  78. }
  79. // If we want to test what will happen if node holds 0 coins, uncomment the below line
  80. // owned = vec![];
  81. info!("Node coins: {:?}", owned);
  82. // Generating leader proof keys
  83. let k: u32 = 11; // Proof rows number
  84. info!("Generating proof keys with k: {}", k);
  85. let proving_key = ProvingKey::build(k, &LeadContract::default());
  86. let verifying_key = VerifyingKey::build(k, &LeadContract::default());
  87. // Simulating epochs with 10 slots
  88. for epoch in 0..epochs {
  89. info!("Epoch {} started!", epoch);
  90. // Generating epoch coins
  91. // TODO: Retrieve previous lead proof
  92. let eta = pallas::Base::one();
  93. let epoch_coins = coins::create_epoch_coins(eta, &owned, epoch, 0);
  94. info!("Generated epoch_coins: {}", epoch_coins.len());
  95. for slot in 0..10 {
  96. // Checking if slot leader
  97. info!("Slot {} started!", slot);
  98. let (won, idx) = coins::is_leader(slot, &epoch_coins);
  99. info!("Lottery outcome: {}", won);
  100. if !won {
  101. continue
  102. }
  103. // TODO: Generate rewards transaction
  104. info!("Winning coin index: {}", idx);
  105. // Generating leader proof
  106. let coin = epoch_coins[slot as usize][idx];
  107. let proof = lead_proof::create_lead_proof(&proving_key, coin);
  108. if proof.is_err() {
  109. error!("Error during leader proof creation: {}", proof.err().unwrap());
  110. continue
  111. }
  112. //Verifying generated proof against winning coin public inputs
  113. info!("Leader proof generated successfully, veryfing...");
  114. match lead_proof::verify_lead_proof(&verifying_key, &proof.unwrap(), &coin.public_inputs()) {
  115. Ok(_) => info!("Proof veryfied succsessfully!"),
  116. Err(e) => error!("Error during leader proof verification: {}", e),
  117. }
  118. }
  119. }
  120. Ok(())
  121. }