Browse Source

validator/pow: introduced fixed difficulty for testing purposes

aggstam 2 years ago
parent
commit
cb06356c46

+ 1 - 0
Cargo.lock

@@ -1934,6 +1934,7 @@ dependencies = [
  "darkfi-serial",
  "easy-parallel",
  "log",
+ "num-bigint",
  "rand 0.8.5",
  "serde",
  "signal-hook",

+ 1 - 0
bin/darkfid2/Cargo.toml

@@ -21,6 +21,7 @@ darkfi-serial = {path = "../../src/serial"}
 blake3 = "1.5.0"
 bs58 = "0.5.0"
 log = "0.4.20"
+num-bigint = "0.4.4"
 sled = "0.34.7"
 rand = "0.8.5"
 

+ 3 - 0
bin/darkfid2/darkfid_config.toml

@@ -26,6 +26,9 @@ pow_threads = 4
 # PoW block production target, in seconds
 pow_target = 10
 
+# Optional fixed PoW difficulty, used for testing
+pow_fixed_difficulty = 1
+
 # Epoch duration, denominated by number of blocks/slots
 epoch_length = 10
 

+ 11 - 0
bin/darkfid2/src/main.rs

@@ -133,6 +133,10 @@ pub struct BlockchainNetwork {
     /// PoW block production target, in seconds
     pub pow_target: usize,
 
+    #[structopt(long)]
+    /// Optional fixed PoW difficulty, used for testing
+    pub pow_fixed_difficulty: Option<usize>,
+
     #[structopt(long, default_value = "10")]
     /// Epoch duration, denominated by number of blocks/slots
     pub epoch_length: u64,
@@ -236,11 +240,18 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
         blockchain_config.slot_time,
         0,
     );
+    let pow_fixed_difficulty = if let Some(diff) = blockchain_config.pow_fixed_difficulty {
+        info!(target: "darkfid", "Node is configured to run with fixed PoW difficulty: {}", diff);
+        Some(diff.into())
+    } else {
+        None
+    };
     let config = ValidatorConfig::new(
         time_keeper,
         blockchain_config.threshold,
         blockchain_config.pow_threads,
         blockchain_config.pow_target,
+        pow_fixed_difficulty,
         genesis_block,
         genesis_txs_total,
         vec![],

+ 1 - 1
bin/darkfid2/src/tests/forks.rs

@@ -30,7 +30,7 @@ fn forks() -> Result<()> {
 
     // Create a temporary blockchain and a PoW module
     let blockchain = Blockchain::new(&sled::Config::new().temporary(true).open()?)?;
-    let module = PoWModule::new(blockchain.clone(), 2, 90)?;
+    let module = PoWModule::new(blockchain.clone(), 2, 90, None)?;
 
     // Create a fork
     let fork = Fork::new(&blockchain, module)?;

+ 5 - 0
bin/darkfid2/src/tests/harness.rs

@@ -32,6 +32,7 @@ use darkfi_sdk::{
     blockchain::{expected_reward, PidOutput, PreviousSlot, Slot, POS_START},
     pasta::{group::ff::Field, pallas},
 };
+use num_bigint::BigUint;
 use url::Url;
 
 use crate::{
@@ -44,6 +45,7 @@ use crate::{
 pub struct HarnessConfig {
     pub pow_threads: usize,
     pub pow_target: usize,
+    pub pow_fixed_difficulty: Option<BigUint>,
     pub testing_node: bool,
     pub alice_initial: u64,
     pub bob_initial: u64,
@@ -86,6 +88,7 @@ impl Harness {
             3,
             config.pow_threads,
             config.pow_target,
+            config.pow_fixed_difficulty.clone(),
             genesis_block,
             genesis_txs_total,
             vec![],
@@ -145,6 +148,7 @@ impl Harness {
                 vec![],
                 self.config.pow_threads,
                 self.config.pow_target,
+                self.config.pow_fixed_difficulty.clone(),
             )
             .await?;
         bob.validate_blockchain(
@@ -152,6 +156,7 @@ impl Harness {
             vec![],
             self.config.pow_threads,
             self.config.pow_target,
+            self.config.pow_fixed_difficulty.clone(),
         )
         .await?;
 

+ 11 - 1
bin/darkfid2/src/tests/mod.rs

@@ -34,9 +34,11 @@ async fn sync_pos_blocks_real(ex: Arc<Executor<'static>>) -> Result<()> {
     // Initialize harness in testing mode
     let pow_threads = 2;
     let pow_target = 90;
+    let pow_fixed_difficulty = None;
     let config = HarnessConfig {
         pow_threads,
         pow_target,
+        pow_fixed_difficulty: pow_fixed_difficulty.clone(),
         testing_node: true,
         alice_initial: 1000,
         bob_initial: 500,
@@ -73,7 +75,15 @@ async fn sync_pos_blocks_real(ex: Arc<Executor<'static>>) -> Result<()> {
     let genesis_txs_total = th.config.alice_initial + th.config.bob_initial;
     let alice = &th.alice.validator.read().await;
     let charlie = &charlie.validator.read().await;
-    charlie.validate_blockchain(genesis_txs_total, vec![], pow_threads, pow_target).await?;
+    charlie
+        .validate_blockchain(
+            genesis_txs_total,
+            vec![],
+            pow_threads,
+            pow_target,
+            pow_fixed_difficulty,
+        )
+        .await?;
     assert_eq!(alice.blockchain.len(), charlie.blockchain.len());
     assert_eq!(alice.blockchain.slots.len(), charlie.blockchain.slots.len());
 

+ 3 - 2
src/contract/test-harness/src/lib.rs

@@ -76,8 +76,8 @@ pub fn init_logger() {
     // We check this error so we can execute same file tests in parallel,
     // otherwise second one fails to init logger here.
     if simplelog::TermLogger::init(
-        //simplelog::LevelFilter::Info,
-        simplelog::LevelFilter::Debug,
+        simplelog::LevelFilter::Info,
+        //simplelog::LevelFilter::Debug,
         //simplelog::LevelFilter::Trace,
         cfg.build(),
         simplelog::TerminalMode::Mixed,
@@ -160,6 +160,7 @@ impl Wallet {
             3,
             1,
             90,
+            None,
             genesis_block.clone(),
             0,
             faucet_pubkeys.to_vec(),

+ 2 - 2
src/contract/test-harness/src/vks.rs

@@ -48,8 +48,8 @@ use darkfi_serial::{deserialize, serialize};
 use log::debug;
 
 /// Update this if any circuits are changed
-const VKS_HASH: &str = "f6b536bd601d6f0b709800da4cb46f026e3292be05eea1b407fab3146738c80e";
-const PKS_HASH: &str = "d0297ba167bae9d74a05f0a57b3e3985591d092d096939f71d3fea9ab11bc96f";
+const VKS_HASH: &str = "ac136b465c4df655d9e77f59884a105f5ade175681ba9cf1cc5abd69ad0f17f8";
+const PKS_HASH: &str = "0e6eeccea48a982ff40fc66b94af9c60efd69e827985e3d5e93c49d679a4f6d8";
 
 fn pks_path(typ: &str) -> Result<PathBuf> {
     let output = Command::new("git").arg("rev-parse").arg("--show-toplevel").output()?.stdout;

+ 4 - 1
src/validator/consensus.rs

@@ -23,6 +23,7 @@ use darkfi_sdk::{
 };
 use darkfi_serial::{async_trait, serialize, SerialDecodable, SerialEncodable};
 use log::{debug, error, info};
+use num_bigint::BigUint;
 
 use crate::{
     blockchain::{BlockInfo, Blockchain, BlockchainOverlay, BlockchainOverlayPtr, Header},
@@ -67,9 +68,11 @@ impl Consensus {
         finalization_threshold: usize,
         pow_threads: usize,
         pow_target: usize,
+        pow_fixed_difficulty: Option<BigUint>,
         testing_mode: bool,
     ) -> Result<Self> {
-        let module = PoWModule::new(blockchain.clone(), pow_threads, pow_target)?;
+        let module =
+            PoWModule::new(blockchain.clone(), pow_threads, pow_target, pow_fixed_difficulty)?;
         Ok(Self {
             blockchain,
             time_keeper,

+ 9 - 1
src/validator/mod.rs

@@ -24,6 +24,7 @@ use darkfi_sdk::{
 };
 use darkfi_serial::serialize;
 use log::{debug, error, info, warn};
+use num_bigint::BigUint;
 use smol::lock::RwLock;
 
 use crate::{
@@ -76,6 +77,8 @@ pub struct ValidatorConfig {
     pub pow_threads: usize,
     /// Currently configured PoW target
     pub pow_target: usize,
+    /// Optional fixed difficulty, for testing purposes
+    pub pow_fixed_difficulty: Option<BigUint>,
     /// Genesis block
     pub genesis_block: BlockInfo,
     /// Total amount of minted tokens in genesis block
@@ -93,6 +96,7 @@ impl ValidatorConfig {
         finalization_threshold: usize,
         pow_threads: usize,
         pow_target: usize,
+        pow_fixed_difficulty: Option<BigUint>,
         genesis_block: BlockInfo,
         genesis_txs_total: u64,
         faucet_pubkeys: Vec<PublicKey>,
@@ -103,6 +107,7 @@ impl ValidatorConfig {
             finalization_threshold,
             pow_threads,
             pow_target,
+            pow_fixed_difficulty,
             genesis_block,
             genesis_txs_total,
             faucet_pubkeys,
@@ -162,6 +167,7 @@ impl Validator {
             config.finalization_threshold,
             config.pow_threads,
             config.pow_target,
+            config.pow_fixed_difficulty,
             testing_mode,
         )?;
 
@@ -540,6 +546,7 @@ impl Validator {
         faucet_pubkeys: Vec<PublicKey>,
         pow_threads: usize,
         pow_target: usize,
+        pow_fixed_difficulty: Option<BigUint>,
     ) -> Result<()> {
         let blocks = self.blockchain.get_all()?;
 
@@ -558,7 +565,8 @@ impl Validator {
 
         // Create a time keeper and a PoW module to validate each block
         let mut time_keeper = self.consensus.time_keeper.clone();
-        let mut module = PoWModule::new(blockchain.clone(), pow_threads, pow_target)?;
+        let mut module =
+            PoWModule::new(blockchain.clone(), pow_threads, pow_target, pow_fixed_difficulty)?;
 
         // Deploy native wasm contracts
         deploy_native_contracts(&overlay, &time_keeper, &faucet_pubkeys)?;

+ 25 - 4
src/validator/pow.rs

@@ -81,6 +81,8 @@ pub struct PoWModule {
     pub threads: usize,
     /// Target block time, in seconds
     pub target: usize,
+    /// Optional fixed difficulty
+    pub fixed_difficulty: Option<BigUint>,
     /// Latest block timestamps ringbuffer
     pub timestamps: RingBuffer<u64, BUF_SIZE>,
     /// Latest block cummulative difficulties ringbuffer
@@ -93,7 +95,12 @@ pub struct PoWModule {
 }
 
 impl PoWModule {
-    pub fn new(blockchain: Blockchain, threads: usize, target: usize) -> Result<Self> {
+    pub fn new(
+        blockchain: Blockchain,
+        threads: usize,
+        target: usize,
+        fixed_difficulty: Option<BigUint>,
+    ) -> Result<Self> {
         // Retrieving last BUF_ZISE difficulties from blockchain to build the buffers
         let mut timestamps = RingBuffer::<u64, BUF_SIZE>::new();
         let mut difficulties = RingBuffer::<BigUint, BUF_SIZE>::new();
@@ -105,11 +112,20 @@ impl PoWModule {
             cummulative_difficulty = difficulty.cummulative_difficulty;
         }
 
-        Ok(Self { threads, target, timestamps, difficulties, cummulative_difficulty })
+        Ok(Self {
+            threads,
+            target,
+            fixed_difficulty,
+            timestamps,
+            difficulties,
+            cummulative_difficulty,
+        })
     }
 
     /// Compute the next mining difficulty, based on current ring buffers.
     /// If ring buffers contain 2 or less items, difficulty 1 is returned.
+    /// If a fixed difficulty has been set, this function will always
+    /// return that after first 2 difficulties.
     pub fn next_difficulty(&self) -> Result<BigUint> {
         // Retrieve first DIFFICULTY_WINDOW timestamps from the ring buffer
         let mut timestamps: Vec<u64> =
@@ -121,6 +137,11 @@ impl PoWModule {
             return Ok(BigUint::one())
         }
 
+        // If a fixed difficulty has been set, return that
+        if let Some(diff) = &self.fixed_difficulty {
+            return Ok(diff.clone())
+        }
+
         // Sort the timestamps vector
         timestamps.sort_unstable();
 
@@ -384,7 +405,7 @@ mod tests {
         let sled_db = sled::Config::new().temporary(true).open()?;
         let blockchain = Blockchain::new(&sled_db)?;
         let mut module =
-            PoWModule::new(blockchain, DEFAULT_TEST_THREADS, DEFAULT_TEST_DIFFICULTY_TARGET)?;
+            PoWModule::new(blockchain, DEFAULT_TEST_THREADS, DEFAULT_TEST_DIFFICULTY_TARGET, None)?;
 
         let output = Command::new("./script/research/pow/gen_wide_data.py").output().unwrap();
         let reader = Cursor::new(output.stdout);
@@ -418,7 +439,7 @@ mod tests {
         let sled_db = sled::Config::new().temporary(true).open()?;
         let blockchain = Blockchain::new(&sled_db)?;
         let module =
-            PoWModule::new(blockchain, DEFAULT_TEST_THREADS, DEFAULT_TEST_DIFFICULTY_TARGET)?;
+            PoWModule::new(blockchain, DEFAULT_TEST_THREADS, DEFAULT_TEST_DIFFICULTY_TARGET, None)?;
         let (_, recvr) = smol::channel::bounded(1);
         let genesis_block = BlockInfo::default();
 

+ 4 - 1
src/validator/validation.rs

@@ -20,6 +20,7 @@ use darkfi_sdk::{
     blockchain::{block_version, expected_reward, Slot},
     pasta::{group::ff::Field, pallas},
 };
+use num_bigint::BigUint;
 
 use crate::{
     blockchain::{BlockInfo, Blockchain},
@@ -337,9 +338,11 @@ pub fn validate_blockchain(
     blockchain: &Blockchain,
     pow_threads: usize,
     pow_target: usize,
+    pow_fixed_difficulty: Option<BigUint>,
 ) -> Result<()> {
     // Generate a PoW module
-    let mut module = PoWModule::new(blockchain.clone(), pow_threads, pow_target)?;
+    let mut module =
+        PoWModule::new(blockchain.clone(), pow_threads, pow_target, pow_fixed_difficulty)?;
     // We use block order store here so we have all blocks in order
     let blocks = blockchain.order.get_all()?;
     for (index, block) in blocks[1..].iter().enumerate() {

+ 3 - 3
tests/blockchain.rs

@@ -41,7 +41,7 @@ struct Node {
 impl Node {
     fn new() -> Result<Self> {
         let blockchain = Blockchain::new(&sled::Config::new().temporary(true).open()?)?;
-        let module = PoWModule::new(blockchain.clone(), POW_THREADS, POW_TARGET)?;
+        let module = PoWModule::new(blockchain.clone(), POW_THREADS, POW_TARGET, None)?;
         Ok(Self { blockchain, module })
     }
 }
@@ -64,8 +64,8 @@ impl Harness {
     }
 
     fn validate_chains(&self) -> Result<()> {
-        validate_blockchain(&self.alice.blockchain, POW_THREADS, POW_TARGET)?;
-        validate_blockchain(&self.bob.blockchain, POW_THREADS, POW_TARGET)?;
+        validate_blockchain(&self.alice.blockchain, POW_THREADS, POW_TARGET, None)?;
+        validate_blockchain(&self.bob.blockchain, POW_THREADS, POW_TARGET, None)?;
 
         assert_eq!(self.alice.blockchain.len(), self.bob.blockchain.len());