Răsfoiți Sursa

darkfid/task/unknown_proposal: properly verify reorg block pow

skoupidi 7 luni în urmă
părinte
comite
c29cfc4521
3 a modificat fișierele cu 44 adăugiri și 45 ștergeri
  1. 9 16
      bin/darkfid/src/task/unknown_proposal.rs
  2. 18 10
      src/validator/pow.rs
  3. 17 19
      src/validator/utils.rs

+ 9 - 16
bin/darkfid/src/task/unknown_proposal.rs

@@ -400,27 +400,20 @@ async fn handle_reorg(
                 return true
             }
 
-            // Grab next mine target and difficulty
-            let (next_target, next_difficulty) = match headers_module
-                .next_mine_target_and_difficulty()
-            {
-                Ok(p) => p,
-                Err(e) => {
-                    debug!(target: "darkfid::task::handle_reorg", "Retrieving next mine target and difficulty failed: {e}");
-                    return false
-                }
-            };
-
             // Verify header hash and calculate its rank
-            let (target_distance_sq, hash_distance_sq) = match header_rank(
+            let (next_difficulty, target_distance_sq, hash_distance_sq) = match header_rank(
+                &headers_module,
                 peer_header,
-                &next_target,
             ) {
-                Ok(distances) => distances,
-                Err(e) => {
-                    debug!(target: "darkfid::task::handle_reorg", "Invalid header hash detected: {e}");
+                Ok(tuple) => tuple,
+                Err(Error::PoWInvalidOutHash) => {
+                    debug!(target: "darkfid::task::handle_reorg", "Invalid header hash detected");
                     return true
                 }
+                Err(e) => {
+                    debug!(target: "darkfid::task::handle_reorg", "Computing header rank failed: {e}");
+                    return false
+                }
             };
 
             // Update sequence ranking

+ 18 - 10
src/validator/pow.rs

@@ -292,13 +292,11 @@ impl PoWModule {
         self.verify_block_hash(header)
     }
 
-    /// Verify provided block corresponds to next mine target.
-    pub fn verify_block_hash(&self, header: &Header) -> Result<()> {
+    /// Verify provided block hash is less than provided mine target.
+    pub fn verify_block_target(&self, header: &Header, target: &BigUint) -> Result<BigUint> {
         let verifier_setup = Instant::now();
 
-        // Grab the next mine target
-        let target = self.next_mine_target()?;
-
+        // Grab verifier output hash based on block PoW data
         let (out_hash, verification_time) = match &header.pow_data {
             DarkFi => {
                 // Check which VM key should be used.
@@ -315,7 +313,7 @@ impl PoWModule {
                 let vm = self.darkfi_rx_factory.create(&randomx_key.inner()[..])?;
 
                 debug!(
-                    target: "validator::pow::verify_block",
+                    target: "validator::pow::verify_block_target",
                     "[VERIFIER] DarkFi PoW setup time: {:?}",
                     verifier_setup.elapsed(),
                 );
@@ -328,7 +326,7 @@ impl PoWModule {
                 let vm = self.monero_rx_factory.create(powdata.randomx_key())?;
 
                 debug!(
-                    target: "validator::pow::verify_block",
+                    target: "validator::pow::verify_block_target",
                     "[VERIFIER] Monero PoW setup time: {:?}",
                     verifier_setup.elapsed(),
                 );
@@ -338,13 +336,23 @@ impl PoWModule {
                 (BigUint::from_bytes_le(&out_hash), verification_time)
             }
         };
+        debug!(target: "validator::pow::verify_block_target", "[VERIFIER] Verification time: {:?}", verification_time.elapsed());
 
-        // Verify hash is less than the expected mine target
-        if out_hash > target {
+        // Verify hash is less than the provided mine target
+        if out_hash > *target {
             return Err(Error::PoWInvalidOutHash)
         }
-        debug!(target: "validator::pow::verify_block", "[VERIFIER] Verification time: {:?}", verification_time.elapsed());
 
+        Ok(out_hash)
+    }
+
+    /// Verify provided block corresponds to next mine target.
+    pub fn verify_block_hash(&self, header: &Header) -> Result<()> {
+        // Grab the next mine target
+        let target = self.next_mine_target()?;
+
+        // Verify hash is less than the expected mine target
+        let _ = self.verify_block_target(header, &target)?;
         Ok(())
     }
 

+ 17 - 19
src/validator/utils.rs

@@ -27,7 +27,10 @@ use tracing::info;
 use crate::{
     blockchain::{BlockInfo, BlockchainOverlayPtr, Header},
     runtime::vm_runtime::Runtime,
-    validator::consensus::{Fork, Proposal},
+    validator::{
+        consensus::{Fork, Proposal},
+        pow::PoWModule,
+    },
     Error, Result,
 };
 
@@ -108,30 +111,25 @@ pub async fn deploy_native_contracts(
     Ok(())
 }
 
-/// Verify provided header is valid for provided mining target and compute its rank.
+/// Verify provided header is valid for provided PoW module and compute
+/// its rank.
+/// Returns next mine difficulty, along with the computed rank.
 ///
-/// Header's rank is the tuple of its squared mining target distance from max 32 bytes int,
-/// along with its squared RandomX hash number distance from max 32 bytes int.
+/// Header's rank is the tuple of its squared mining target distance
+/// from max 32 bytes int, along with its squared RandomX hash number
+/// distance from max 32 bytes int.
 /// Genesis block has rank (0, 0).
-pub fn header_rank(header: &Header, target: &BigUint) -> Result<(BigUint, BigUint)> {
+pub fn header_rank(module: &PoWModule, header: &Header) -> Result<(BigUint, BigUint, BigUint)> {
+    // Grab next mine target and difficulty
+    let (target, difficulty) = module.next_mine_target_and_difficulty()?;
+
     // Genesis header has rank 0
     if header.height == 0 {
-        return Ok((0u64.into(), 0u64.into()))
+        return Ok((difficulty, 0u64.into(), 0u64.into()))
     }
 
-    // Setup RandomX verifier
-    let flags = RandomXFlags::get_recommended_flags();
-    let cache = RandomXCache::new(flags, header.previous.inner()).unwrap();
-    let vm = RandomXVM::new(flags, Some(cache), None).unwrap();
-
-    // Compute the output hash
-    let out_hash = vm.calculate_hash(header.hash().inner())?;
-    let out_hash = BigUint::from_bytes_le(&out_hash);
-
     // Verify hash is less than the expected mine target
-    if out_hash > *target {
-        return Err(Error::PoWInvalidOutHash)
-    }
+    let out_hash = module.verify_block_target(header, &target)?;
 
     // Grab the max 32 bytes int
     let max = BigUint::from_bytes_le(&[0xFF; 32]);
@@ -144,7 +142,7 @@ pub fn header_rank(header: &Header, target: &BigUint) -> Result<(BigUint, BigUin
     let hash_distance = max - out_hash;
     let hash_distance_sq = &hash_distance * &hash_distance;
 
-    Ok((target_distance_sq, hash_distance_sq))
+    Ok((difficulty, target_distance_sq, hash_distance_sq))
 }
 
 /// Compute a block's rank, assuming that its valid, based on provided mining target.