瀏覽代碼

validator/consensus: use blocks previous previous VRF for ranking

aggstam 2 年之前
父節點
當前提交
0331a02f53
共有 3 個文件被更改,包括 80 次插入51 次删除
  1. 2 46
      src/blockchain/block_store.rs
  2. 16 2
      src/validator/consensus.rs
  3. 62 3
      src/validator/utils.rs

+ 2 - 46
src/blockchain/block_store.rs

@@ -16,19 +16,15 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-use std::io::Cursor;
-
 use darkfi_sdk::{
     blockchain::Slot,
-    crypto::{ecvrf::VrfProof, pasta_prelude::PrimeField, schnorr::Signature},
+    crypto::schnorr::Signature,
     pasta::{group::ff::FromUniformBytes, pallas},
 };
 #[cfg(feature = "async-serial")]
 use darkfi_serial::async_trait;
 
-use darkfi_serial::{
-    deserialize, serialize, Decodable, Encodable, SerialDecodable, SerialEncodable,
-};
+use darkfi_serial::{deserialize, serialize, Encodable, SerialDecodable, SerialEncodable};
 
 use crate::{tx::Transaction, Error, Result};
 
@@ -147,46 +143,6 @@ impl BlockInfo {
 
         Ok(())
     }
-
-    /// Compute block's rank, assuming the block is valid.
-    pub fn rank(&self) -> Result<u64> {
-        // Genesis block has rank 0
-        if self.header.height == 0 {
-            return Ok(0)
-        }
-
-        // Extract VRF proof from the producer transaction
-        let tx = self.txs.last().unwrap();
-        let data = &tx.calls[0].data;
-        let position = match self.header.version {
-            // PoW uses MoneyPoWRewardParamsV1
-            1 => 563,
-            // PoS uses ConsensusProposalParamsV1
-            2 => 490,
-            _ => return Err(Error::BlockVersionIsInvalid(self.header.version)),
-        };
-        let mut decoder = Cursor::new(&data);
-        decoder.set_position(position);
-        let vrf_proof: VrfProof = Decodable::decode(&mut decoder)?;
-
-        // Compute nonce u64
-        let mut nonce = [0u8; 8];
-        nonce.copy_from_slice(&self.header.nonce.to_repr()[..8]);
-        let nonce = u64::from_be_bytes(nonce);
-
-        // Compute VRF u64
-        let mut vrf = [0u8; 64];
-        vrf[..blake3::OUT_LEN].copy_from_slice(vrf_proof.hash_output().as_bytes());
-        let vrf_pallas = pallas::Base::from_uniform_bytes(&vrf);
-        let mut vrf = [0u8; 8];
-        vrf.copy_from_slice(&vrf_pallas.to_repr()[..8]);
-        let vrf = u64::from_be_bytes(vrf);
-
-        // Finally, compute the rank
-        let rank = nonce % vrf;
-
-        Ok(rank)
-    }
 }
 
 /// [`Block`] sled tree

+ 16 - 2
src/validator/consensus.rs

@@ -29,7 +29,9 @@ use crate::{
     blockchain::{BlockInfo, Blockchain, BlockchainOverlay, BlockchainOverlayPtr, Header},
     tx::Transaction,
     util::time::{TimeKeeper, Timestamp},
-    validator::{pid::slot_pid_output, pow::PoWModule, verify_block, verify_transactions},
+    validator::{
+        pid::slot_pid_output, pow::PoWModule, utils::block_rank, verify_block, verify_transactions,
+    },
     Error, Result,
 };
 
@@ -632,7 +634,19 @@ impl Fork {
         let mut sum = 0;
         let proposals = self.overlay.lock().unwrap().get_blocks_by_hash(&self.proposals)?;
         for proposal in &proposals {
-            sum += proposal.rank()?;
+            // For block height > 3, retrieve their previous previous block
+            let previous_previous = if proposal.header.height > 3 {
+                let previous = &self
+                    .overlay
+                    .lock()
+                    .unwrap()
+                    .get_blocks_by_hash(&[proposal.header.previous])?[0];
+                self.overlay.lock().unwrap().get_blocks_by_hash(&[previous.header.previous])?[0]
+                    .clone()
+            } else {
+                proposal.clone()
+            };
+            sum += block_rank(proposal, &previous_previous)?;
         }
 
         // Use fork(proposals) length as a multiplier to compute the actual fork rank

+ 62 - 3
src/validator/utils.rs

@@ -16,12 +16,23 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-use darkfi_sdk::crypto::{PublicKey, CONSENSUS_CONTRACT_ID, DAO_CONTRACT_ID, MONEY_CONTRACT_ID};
-use darkfi_serial::serialize;
+use std::io::Cursor;
+
+use darkfi_sdk::{
+    crypto::{
+        ecvrf::VrfProof, pasta_prelude::PrimeField, PublicKey, CONSENSUS_CONTRACT_ID,
+        DAO_CONTRACT_ID, MONEY_CONTRACT_ID,
+    },
+    pasta::{group::ff::FromUniformBytes, pallas},
+};
+use darkfi_serial::{serialize, Decodable};
 use log::info;
 
 use crate::{
-    blockchain::BlockchainOverlayPtr, runtime::vm_runtime::Runtime, util::time::TimeKeeper, Result,
+    blockchain::{BlockInfo, BlockchainOverlayPtr},
+    runtime::vm_runtime::Runtime,
+    util::time::TimeKeeper,
+    Error, Result,
 };
 
 /// Deploy DarkFi native wasm contracts to provided blockchain overlay.
@@ -86,3 +97,51 @@ pub fn deploy_native_contracts(
 
     Ok(())
 }
+
+/// Compute a block's rank, assuming the its valid.
+/// Genesis block has rank 0.
+/// First 2 blocks rank is equal to their nonce, since their previous
+/// previous block producer doesn't exist or have a VRF.
+pub fn block_rank(block: &BlockInfo, previous_previous: &BlockInfo) -> Result<u64> {
+    // Genesis block has rank 0
+    if block.header.height == 0 {
+        return Ok(0)
+    }
+
+    // Compute nonce u64
+    let mut nonce = [0u8; 8];
+    nonce.copy_from_slice(&block.header.nonce.to_repr()[..8]);
+    let nonce = u64::from_be_bytes(nonce);
+
+    // First 2 block have rank equal to their nonce
+    if block.header.height < 3 {
+        return Ok(nonce)
+    }
+
+    // Extract VRF proof from the previous previous producer transaction
+    let tx = previous_previous.txs.last().unwrap();
+    let data = &tx.calls[0].data;
+    let position = match previous_previous.header.version {
+        // PoW uses MoneyPoWRewardParamsV1
+        1 => 563,
+        // PoS uses ConsensusProposalParamsV1
+        2 => 490,
+        _ => return Err(Error::BlockVersionIsInvalid(previous_previous.header.version)),
+    };
+    let mut decoder = Cursor::new(&data);
+    decoder.set_position(position);
+    let vrf_proof: VrfProof = Decodable::decode(&mut decoder)?;
+
+    // Compute VRF u64
+    let mut vrf = [0u8; 64];
+    vrf[..blake3::OUT_LEN].copy_from_slice(vrf_proof.hash_output().as_bytes());
+    let vrf_pallas = pallas::Base::from_uniform_bytes(&vrf);
+    let mut vrf = [0u8; 8];
+    vrf.copy_from_slice(&vrf_pallas.to_repr()[..8]);
+    let vrf = u64::from_be_bytes(vrf);
+
+    // Finally, compute the rank
+    let rank = nonce % vrf;
+
+    Ok(rank)
+}