Просмотр исходного кода

fix bug with redundant lead history, updated discrete pid, remove finalization minimum length condition

mohab metwally 3 лет назад
Родитель
Сommit
8ca5d1abac
3 измененных файлов с 86 добавлено и 37 удалено
  1. 24 18
      src/consensus/constants.rs
  2. 52 13
      src/consensus/state.rs
  3. 10 6
      src/consensus/validator.rs

+ 24 - 18
src/consensus/constants.rs

@@ -39,36 +39,42 @@ lazy_static! {
     pub static ref TESTNET_GENESIS_HASH_BYTES: blake3::Hash = blake3::hash(b"darkfi_testnet");
 
     /// Genesis timestamp for the testnet chain
-    pub static ref TESTNET_GENESIS_TIMESTAMP: Timestamp = Timestamp(1671546600);
+    pub static ref TESTNET_GENESIS_TIMESTAMP: Timestamp = Timestamp(1672785000);
 
     /// Bootstrap timestamp for the testnet chain
-    pub static ref TESTNET_BOOTSTRAP_TIMESTAMP: Timestamp = Timestamp(1671546600);
+    pub static ref TESTNET_BOOTSTRAP_TIMESTAMP: Timestamp = Timestamp(1672785000);
 
     /// Total sum of initial staking coins for the testnet chain
     pub static ref TESTNET_INITIAL_DISTRIBUTION: u64 = 1000;
 
     // Commonly used Float10
-    pub static ref FLOAT10_ZERO: Float10 = Float10::try_from("0").unwrap();
-    pub static ref FLOAT10_ONE: Float10 = Float10::try_from("1").unwrap();
-    pub static ref FLOAT10_TWO: Float10 = Float10::try_from("2").unwrap();
-    pub static ref FLOAT10_THREE: Float10 = Float10::try_from("3").unwrap();
-    pub static ref FLOAT10_FIVE: Float10 = Float10::try_from("5").unwrap();
-    pub static ref FLOAT10_NINE: Float10 = Float10::try_from("9").unwrap();
-    pub static ref FLOAT10_TEN: Float10 = Float10::try_from("10").unwrap();
+
+    pub static ref FLOAT10_NEG_ONE: Float10 = Float10::from_str_native("-1").unwrap().with_precision(RADIX_BITS).value();
+    pub static ref FLOAT10_NEG_TWO: Float10 = Float10::from_str_native("-2").unwrap().with_precision(RADIX_BITS).value();
+    pub static ref FLOAT10_ZERO: Float10 = Float10::from_str_native("0").unwrap().with_precision(RADIX_BITS).value();
+    pub static ref FLOAT10_ONE: Float10 = Float10::from_str_native("1").unwrap().with_precision(RADIX_BITS).value();
+    pub static ref FLOAT10_TWO: Float10 = Float10::from_str_native("2").unwrap().with_precision(RADIX_BITS).value();
+    pub static ref FLOAT10_THREE: Float10 = Float10::from_str_native("3").unwrap().with_precision(RADIX_BITS).value();
+    pub static ref FLOAT10_FIVE: Float10 = Float10::from_str_native("5").unwrap().with_precision(RADIX_BITS).value();
+    pub static ref FLOAT10_NINE: Float10 = Float10::from_str_native("9").unwrap().with_precision(RADIX_BITS).value();
+    pub static ref FLOAT10_TEN: Float10 = Float10::from_str_native("10").unwrap().with_precision(RADIX_BITS).value();
+
 
     // Consensus parameters
     pub static ref DT: Float10 =  Float10::try_from("0.1").unwrap();
     pub static ref TI: Float10 = FLOAT10_ONE.clone();
     pub static ref TD: Float10 = FLOAT10_ONE.clone();
-    pub static ref KP: Float10 = Float10::try_from("0.1").unwrap();
-    pub static ref KI: Float10 = Float10::try_from("0.03").unwrap();
-    pub static ref KD: Float10 = FLOAT10_ONE.clone();
-    pub static ref PID_OUT_STEP: Float10  = Float10::try_from("0.1").unwrap();
-    pub static ref MAX_DER: Float10 = Float10::try_from("0.1").unwrap();
-    pub static ref MIN_DER: Float10 = Float10::try_from("-0.1").unwrap();
-    pub static ref MAX_F: Float10 = Float10::try_from("0.99").unwrap();
-    pub static ref MIN_F: Float10 = Float10::try_from("0.05").unwrap();
-    pub static ref DEG_RATE: Float10 = Float10::try_from("0.9").unwrap();
+
+    pub static ref KP: Float10 = Float10::from_str_native("-0.8").unwrap().with_precision(RADIX_BITS).value();
+    pub static ref KI: Float10 = Float10::from_str_native("0.6").unwrap().with_precision(RADIX_BITS).value();
+    pub static ref KD: Float10 = Float10::from_str_native("0.8").unwrap().with_precision(RADIX_BITS).value();
+    pub static ref PID_OUT_STEP: Float10  = Float10::from_str_native("0.1").unwrap().with_precision(RADIX_BITS).value();
+    pub static ref MAX_DER: Float10 = Float10::from_str_native("0.1").unwrap().with_precision(RADIX_BITS).value();
+    pub static ref MIN_DER: Float10 = Float10::from_str_native("-0.1").unwrap().with_precision(RADIX_BITS).value();
+    pub static ref MAX_F: Float10 = Float10::from_str_native("0.99").unwrap().with_precision(RADIX_BITS).value();
+    pub static ref MIN_F: Float10 = Float10::from_str_native("0.01").unwrap().with_precision(RADIX_BITS).value();
+    pub static ref DEG_RATE: Float10 = Float10::from_str_native("0.9").unwrap().with_precision(RADIX_BITS).value();
+
 }
 
 /// Block version number

+ 52 - 13
src/consensus/state.rs

@@ -68,6 +68,10 @@ pub struct ConsensusState {
     pub slot_checkpoints: Vec<SlotCheckpoint>,
     /// Leaders count history
     pub leaders_history: Vec<u64>,
+    /// controller output history
+    pub f_history: Vec<Float10>,
+    /// controller proportional error history
+    pub err_history: Vec<Float10>,
     // TODO: Aren't these already in db after finalization?
     /// Canonical competing coins
     pub coins: Vec<LeadCoin>,
@@ -102,6 +106,9 @@ impl ConsensusState {
             epoch_eta: pallas::Base::zero(),
             slot_checkpoints: vec![],
             leaders_history: vec![0],
+            f_history: vec![constants::FLOAT10_ZERO.clone()],
+            err_history: vec![constants::FLOAT10_ZERO.clone(),
+                              constants::FLOAT10_ZERO.clone()],
             coins: vec![],
             coins_tree: BridgeTree::<MerkleNode, MERKLE_DEPTH>::new(constants::EPOCH_LENGTH * 100),
             nullifiers: vec![],
@@ -189,7 +196,9 @@ impl ConsensusState {
     /// Generate current slot checkpoint
     fn generate_slot_checkpoint(&mut self, sigma1: pallas::Base, sigma2: pallas::Base) {
         let slot = self.current_slot();
-        let checkpoint = SlotCheckpoint { slot, eta: self.epoch_eta, sigma1, sigma2 };
+        let eta = self.get_eta();
+        info!("generate_slot_checkpoint: slot: {:?}, eta: {:?}", slot, eta);
+        let checkpoint = SlotCheckpoint { slot, eta, sigma1, sigma2 };
         self.slot_checkpoints.push(checkpoint);
     }
 
@@ -277,10 +286,10 @@ impl ConsensusState {
         // Temporarily, we compete with fixed stake.
         // This stake should be based on how many nodes we want to run, and they all
         // must sum to initial distribution total coins.
-        let stake = self.initial_distribution;
+        //let stake = self.initial_distribution;
         let coin = LeadCoin::new(
             eta,
-            stake,
+            200,
             slot,
             epoch_secrets.secret_keys[0].inner(),
             epoch_secrets.merkle_roots[0],
@@ -375,7 +384,8 @@ impl ConsensusState {
     }
 
     fn f_dif(&mut self) -> Float10 {
-        Self::pid_error(self.extend_leaders_history())
+        let len = self.leaders_history.len();
+        Self::pid_error(Float10::try_from(self.leaders_history[len-1] as i64).unwrap().with_precision(constants::RADIX_BITS).value())
     }
 
     fn max_windowed_forks(&self) -> Float10 {
@@ -393,7 +403,8 @@ impl ConsensusState {
     }
 
     fn tuned_kp(&self) -> Float10 {
-        (constants::KP.clone() * constants::FLOAT10_FIVE.clone()) / self.max_windowed_forks()
+        //(constants::KP.clone() * constants::FLOAT10_FIVE.clone()) / self.max_windowed_forks()
+        constants::KP.clone()
     }
 
     fn weighted_f_dif(&mut self) -> Float10 {
@@ -428,7 +439,8 @@ impl ConsensusState {
     }
 
     fn tuned_ki(&self) -> Float10 {
-        (constants::KI.clone() * constants::FLOAT10_FIVE.clone()) / self.max_windowed_forks()
+        //(constants::KI.clone() * constants::FLOAT10_FIVE.clone()) / self.max_windowed_forks()
+        constants::KI.clone()
     }
 
     fn weighted_f_int(&self) -> Float10 {
@@ -449,9 +461,7 @@ impl ConsensusState {
         count
     }
 
-    /// the probability inverse of winnig lottery having all the stake
-    /// returns f
-    fn win_inv_prob_with_full_stake(&mut self) -> Float10 {
+    fn pid(&mut self) -> Float10 {
         let p = self.weighted_f_dif();
         let i = self.weighted_f_int();
         let d = self.weighted_f_der();
@@ -459,7 +469,35 @@ impl ConsensusState {
         info!(target: "consensus::state", "win_inv_prob_with_full_stake(): PID I: {:?}", i);
         info!(target: "consensus::state", "win_inv_prob_with_full_stake(): PID D: {:?}", d);
         let f = p + i.clone() + d;
-        info!(target: "consensus::state", "win_inv_prob_with_full_stake(): PID f: {}", f);
+
+        info!("win_inv_prob_with_full_stake(): PID f: {}", f);
+        f
+    }
+
+    fn discrete_pid(&mut self) -> Float10 {
+        let k1 =  constants::KP.clone() +
+            constants::KI.clone() +
+            constants::KD.clone();
+        let k2 = constants::FLOAT10_NEG_ONE.clone() * constants::KP.clone() -
+            constants::FLOAT10_NEG_TWO.clone() * constants::KD.clone();
+        let k3 = constants::KD.clone();
+        let f_len = self.f_history.len();
+        let err = self.f_dif();
+        let err_len = self.err_history.len();
+        let ret = self.f_history[f_len-1].clone() +
+            k1 * err.clone() +
+            k2 * self.err_history[err_len-1].clone() +
+            k3 * self.err_history[err_len-2].clone();
+        self.f_history.push(ret.clone());
+        self.err_history.push(err);
+        ret
+    }
+    /// the probability inverse of winnig lottery having all the stake
+    /// returns f
+    fn win_inv_prob_with_full_stake(&mut self) -> Float10 {
+        self.extend_leaders_history();
+        //
+        let f = self.discrete_pid();
         if f == constants::FLOAT10_ZERO.clone() {
             return constants::MIN_F.clone()
         } else if f >= constants::FLOAT10_ONE.clone() {
@@ -469,8 +507,8 @@ impl ConsensusState {
         if hist_len > 3 &&
             self.leaders_history[hist_len - 1] == 0 &&
             self.leaders_history[hist_len - 2] == 0 &&
-            self.leaders_history[hist_len - 3] == 0 &&
-            i == constants::FLOAT10_ZERO.clone()
+            self.leaders_history[hist_len - 3] == 0
+            //&& i == constants::FLOAT10_ZERO.clone()
         {
             return f * constants::DEG_RATE.clone().powf(self.zero_leads_len())
         }
@@ -615,6 +653,7 @@ impl ConsensusState {
 
     /// Auxillary function to set nodes leaders count history to the largest fork sequence
     /// of leaders, by using provided index.
+
     pub fn set_leader_history(&mut self, index: i64, current_slot: u64) {
         // Check if we found longest fork to extract sequence from
         match index {
@@ -633,7 +672,7 @@ impl ConsensusState {
                 }
             }
         }
-        self.leaders_history.push(0);
+        //self.leaders_history.push(0);
     }
 
     /// Utility function to extract leader selection lottery randomness(eta),

+ 10 - 6
src/consensus/validator.rs

@@ -613,7 +613,7 @@ impl ValidatorState {
         self.consensus.checked_finalization = slot;
 
         // First we find longest fork without any other forks at same height
-        let mut fork_index = -1;
+        let mut fork_index = 0;
         // Use this index to extract leaders count sequence from longest fork
         let mut index_for_history = -1;
         let mut max_length_for_history = 0;
@@ -626,9 +626,11 @@ impl ValidatorState {
                 max_length_for_history = length;
             }
             // Ignore forks with less that 3 blocks
+            /*
             if length < 3 {
                 continue
-            }
+        }
+            */
             // Check if less than max
             if length < max_length {
                 continue
@@ -652,14 +654,16 @@ impl ValidatorState {
                 self.consensus.set_leader_history(index_for_history, slot);
                 return Ok((vec![], vec![]))
             }
+            /*
             -1 => {
                 info!(target: "consensus::validator", "chain_finalization(): All chains have less than 3 proposals, nothing to finalize.");
                 self.consensus.set_leader_history(index_for_history, slot);
                 return Ok((vec![], vec![]))
-            }
-            _ => {
-                info!(target: "consensus::validator", "chain_finalization(): Chain {} can be finalized!", fork_index)
-            }
+
+        }
+            */
+            _ => info!("chain_finalization(): Chain {} can be finalized!", fork_index),
+
         }
 
         // Starting finalization