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

validator: check block timestamp is after genesis

skoupidi 2 лет назад
Родитель
Сommit
934d8f1a42

+ 4 - 2
bin/darkfid/src/tests/forks.rs

@@ -29,15 +29,17 @@ fn forks() -> Result<()> {
         let record1 = HeaderHash::new(blake3::hash(b"Let there be dark!").into());
         let record1 = HeaderHash::new(blake3::hash(b"Let there be dark!").into());
         let record2 = HeaderHash::new(blake3::hash(b"Never skip brain day.").into());
         let record2 = HeaderHash::new(blake3::hash(b"Never skip brain day.").into());
 
 
-        // Create a temporary blockchain and a PoW module
+        // Create a temporary blockchain
         let blockchain = Blockchain::new(&sled::Config::new().temporary(true).open()?)?;
         let blockchain = Blockchain::new(&sled::Config::new().temporary(true).open()?)?;
-        let module = PoWModule::new(blockchain.clone(), 90, None)?;
 
 
         // Generate and insert default genesis block
         // Generate and insert default genesis block
         let genesis_block = BlockInfo::default();
         let genesis_block = BlockInfo::default();
         blockchain.add_block(&genesis_block)?;
         blockchain.add_block(&genesis_block)?;
         let genesis_block_hash = genesis_block.hash();
         let genesis_block_hash = genesis_block.hash();
 
 
+        // Generate the PoW module
+        let module = PoWModule::new(blockchain.clone(), 90, None)?;
+
         // Create a fork
         // Create a fork
         let fork = Fork::new(blockchain.clone(), module).await?;
         let fork = Fork::new(blockchain.clone(), module).await?;
 
 

+ 1 - 1
bin/darkfid/src/tests/harness.rs

@@ -155,7 +155,7 @@ impl Harness {
 
 
         // Sleep a bit so blocks can be propagated and then
         // Sleep a bit so blocks can be propagated and then
         // trigger finalization check to Alice and Bob
         // trigger finalization check to Alice and Bob
-        sleep(5).await;
+        sleep(10).await;
         self.alice.validator.finalization().await?;
         self.alice.validator.finalization().await?;
         self.bob.validator.finalization().await?;
         self.bob.validator.finalization().await?;
 
 

+ 0 - 1
bin/darkfid/src/tests/mod.rs

@@ -105,7 +105,6 @@ async fn sync_blocks_real(ex: Arc<Executor<'static>>) -> Result<()> {
     // Verify node synced
     // Verify node synced
     let alice = &th.alice.validator;
     let alice = &th.alice.validator;
     let charlie = &charlie.validator;
     let charlie = &charlie.validator;
-    charlie.validate_blockchain(pow_target, pow_fixed_difficulty.clone()).await?;
     assert_eq!(alice.blockchain.len(), charlie.blockchain.len());
     assert_eq!(alice.blockchain.len(), charlie.blockchain.len());
     assert!(charlie.blockchain.headers.is_empty_sync());
     assert!(charlie.blockchain.headers.is_empty_sync());
     // Node must have just the best fork
     // Node must have just the best fork

+ 0 - 1
bin/darkfid/src/tests/sync_forks.rs

@@ -112,7 +112,6 @@ async fn sync_forks_real(ex: Arc<Executor<'static>>) -> Result<()> {
 }
 }
 
 
 #[test]
 #[test]
-#[ignore]
 fn sync_forks() -> Result<()> {
 fn sync_forks() -> Result<()> {
     let ex = Arc::new(Executor::new());
     let ex = Arc::new(Executor::new());
     let (signal, shutdown) = smol::channel::unbounded::<()>();
     let (signal, shutdown) = smol::channel::unbounded::<()>();

+ 7 - 6
src/validator/mod.rs

@@ -699,15 +699,18 @@ impl Validator {
         // Set previous
         // Set previous
         let mut previous = &blocks[0];
         let mut previous = &blocks[0];
 
 
-        // Create a time keeper and a PoW module to validate each block
-        let mut module = PoWModule::new(blockchain.clone(), pow_target, pow_fixed_difficulty)?;
-
         // Deploy native wasm contracts
         // Deploy native wasm contracts
         deploy_native_contracts(&overlay, pow_target).await?;
         deploy_native_contracts(&overlay, pow_target).await?;
 
 
         // Validate genesis block
         // Validate genesis block
         verify_genesis_block(&overlay, previous, pow_target).await?;
         verify_genesis_block(&overlay, previous, pow_target).await?;
 
 
+        // Write the changes to the in memory db
+        overlay.lock().unwrap().overlay.lock().unwrap().apply()?;
+
+        // Create a PoW module to validate each block
+        let mut module = PoWModule::new(blockchain, pow_target, pow_fixed_difficulty)?;
+
         // Validate and insert each block
         // Validate and insert each block
         for block in &blocks[1..] {
         for block in &blocks[1..] {
             // Verify block
             // Verify block
@@ -718,9 +721,7 @@ impl Validator {
             };
             };
 
 
             // Update PoW module
             // Update PoW module
-            if block.header.version == 1 {
-                module.append(block.header.timestamp, &module.next_difficulty()?);
-            }
+            module.append(block.header.timestamp, &module.next_difficulty()?);
 
 
             // Use last inserted block as next iteration previous
             // Use last inserted block as next iteration previous
             previous = block;
             previous = block;

+ 23 - 2
src/validator/pow.rs

@@ -74,6 +74,8 @@ const BLOCK_FUTURE_TIME_LIMIT: Timestamp = Timestamp::from_u64(60 * 60 * 2);
 /// This struct represents the information required by the PoW algorithm
 /// This struct represents the information required by the PoW algorithm
 #[derive(Clone)]
 #[derive(Clone)]
 pub struct PoWModule {
 pub struct PoWModule {
+    /// Genesis block timestamp
+    pub genesis: Timestamp,
     /// Target block time, in seconds
     /// Target block time, in seconds
     pub target: u32,
     pub target: u32,
     /// Optional fixed difficulty
     /// Optional fixed difficulty
@@ -95,6 +97,9 @@ impl PoWModule {
         target: u32,
         target: u32,
         fixed_difficulty: Option<BigUint>,
         fixed_difficulty: Option<BigUint>,
     ) -> Result<Self> {
     ) -> Result<Self> {
+        // Retrieve genesis block timestamp
+        let genesis = blockchain.genesis_block()?.header.timestamp;
+
         // Retrieving last BUF_SIZE difficulties from blockchain to build the buffers
         // Retrieving last BUF_SIZE difficulties from blockchain to build the buffers
         let mut timestamps = RingBuffer::<Timestamp, BUF_SIZE>::new();
         let mut timestamps = RingBuffer::<Timestamp, BUF_SIZE>::new();
         let mut difficulties = RingBuffer::<BigUint, BUF_SIZE>::new();
         let mut difficulties = RingBuffer::<BigUint, BUF_SIZE>::new();
@@ -111,7 +116,14 @@ impl PoWModule {
             assert!(diff > &BigUint::zero());
             assert!(diff > &BigUint::zero());
         }
         }
 
 
-        Ok(Self { target, fixed_difficulty, timestamps, difficulties, cummulative_difficulty })
+        Ok(Self {
+            genesis,
+            target,
+            fixed_difficulty,
+            timestamps,
+            difficulties,
+            cummulative_difficulty,
+        })
     }
     }
 
 
     /// Compute the next mining difficulty, based on current ring buffers.
     /// Compute the next mining difficulty, based on current ring buffers.
@@ -214,6 +226,11 @@ impl PoWModule {
 
 
     /// Verify provided block timestamp is valid and matches certain criteria
     /// Verify provided block timestamp is valid and matches certain criteria
     pub fn verify_timestamp_by_median(&self, timestamp: Timestamp) -> bool {
     pub fn verify_timestamp_by_median(&self, timestamp: Timestamp) -> bool {
+        // Check timestamp is after genesis one
+        if timestamp <= self.genesis {
+            return false
+        }
+
         // If not enough blocks, no proper median yet, return true
         // If not enough blocks, no proper median yet, return true
         if self.timestamps.len() < BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW {
         if self.timestamps.len() < BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW {
             return true
             return true
@@ -421,6 +438,8 @@ mod tests {
     fn test_wide_difficulty() -> Result<()> {
     fn test_wide_difficulty() -> Result<()> {
         let sled_db = sled::Config::new().temporary(true).open()?;
         let sled_db = sled::Config::new().temporary(true).open()?;
         let blockchain = Blockchain::new(&sled_db)?;
         let blockchain = Blockchain::new(&sled_db)?;
+        let genesis_block = BlockInfo::default();
+        blockchain.add_block(&genesis_block)?;
         let mut module = PoWModule::new(blockchain, DEFAULT_TEST_DIFFICULTY_TARGET, None)?;
         let mut module = PoWModule::new(blockchain, DEFAULT_TEST_DIFFICULTY_TARGET, None)?;
 
 
         let output = Command::new("./script/research/pow/gen_wide_data.py").output().unwrap();
         let output = Command::new("./script/research/pow/gen_wide_data.py").output().unwrap();
@@ -454,9 +473,11 @@ mod tests {
         // Default setup
         // Default setup
         let sled_db = sled::Config::new().temporary(true).open()?;
         let sled_db = sled::Config::new().temporary(true).open()?;
         let blockchain = Blockchain::new(&sled_db)?;
         let blockchain = Blockchain::new(&sled_db)?;
+        let mut genesis_block = BlockInfo::default();
+        genesis_block.header.timestamp = 0.into();
+        blockchain.add_block(&genesis_block)?;
         let module = PoWModule::new(blockchain, DEFAULT_TEST_DIFFICULTY_TARGET, None)?;
         let module = PoWModule::new(blockchain, DEFAULT_TEST_DIFFICULTY_TARGET, None)?;
         let (_, recvr) = smol::channel::bounded(1);
         let (_, recvr) = smol::channel::bounded(1);
-        let genesis_block = BlockInfo::default();
 
 
         // Mine next block
         // Mine next block
         let mut next_block = BlockInfo::default();
         let mut next_block = BlockInfo::default();