Explorar o código

validator: improved uproposed txs retriaval logic

skoupidi %!s(int64=2) %!d(string=hai) anos
pai
achega
72526ed18c
Modificáronse 3 ficheiros con 45 adicións e 18 borrados
  1. 11 0
      src/blockchain/mod.rs
  2. 33 17
      src/validator/consensus.rs
  3. 1 1
      src/validator/verification.rs

+ 11 - 0
src/blockchain/mod.rs

@@ -465,6 +465,17 @@ impl BlockchainOverlay {
         Ok(ret)
     }
 
+    /// Retrieve [`Block`]s by given hashes and return their transactions hashes.
+    pub fn get_blocks_txs_hashes(&self, hashes: &[blake3::Hash]) -> Result<Vec<blake3::Hash>> {
+        let blocks = self.blocks.get(hashes, true)?;
+        let mut ret = vec![];
+        for block in blocks {
+            ret.extend_from_slice(&block.unwrap().txs);
+        }
+
+        Ok(ret)
+    }
+
     /// Checkpoint overlay so we can revert to it, if needed.
     pub fn checkpoint(&self) {
         self.overlay.lock().unwrap().checkpoint();

+ 33 - 17
src/validator/consensus.rs

@@ -38,7 +38,7 @@ use crate::{
 };
 
 // Consensus configuration
-/// Block/proposal maximum transactions
+/// Block/proposal maximum transactions, exluding producer transaction
 pub const TXS_CAP: usize = 50;
 
 /// This struct represents the information required by the consensus algorithm
@@ -364,28 +364,44 @@ impl Fork {
         blockchain: &Blockchain,
         verifying_block_height: u64,
     ) -> Result<Vec<Transaction>> {
-        // Retrieve all mempool transactions
-        let mut unproposed_txs: Vec<Transaction> = blockchain
-            .pending_txs
-            .get(&self.mempool, true)?
-            .iter()
-            .map(|x| x.clone().unwrap())
-            .collect();
+        // Check if our mempool is not empty
+        if self.mempool.is_empty() {
+            return Ok(vec![])
+        }
 
-        // Iterate over fork proposals to find already proposed transactions
-        // and remove them from the unproposed_txs vector.
-        let proposals = self.overlay.lock().unwrap().get_blocks_by_hash(&self.proposals)?;
-        for proposal in proposals {
-            for tx in &proposal.txs {
-                unproposed_txs.retain(|x| x != tx);
+        // Grab all current proposals transactions hashes
+        let proposals_txs = self.overlay.lock().unwrap().get_blocks_txs_hashes(&self.proposals)?;
+
+        // Iterate through all pending transactions in the forks' mempool
+        let mut unproposed_txs = vec![];
+        for tx in &self.mempool {
+            // If the hash is contained in the proposals transactions vec, skip it
+            if proposals_txs.contains(tx) {
+                continue
+            }
+
+            // Push the tx hash into the unproposed transactions vector
+            unproposed_txs.push(*tx);
+
+            // Check limit
+            if unproposed_txs.len() == TXS_CAP {
+                break
             }
         }
 
-        // Check if transactions exceed configured cap
-        if unproposed_txs.len() > TXS_CAP {
-            unproposed_txs = unproposed_txs[0..TXS_CAP].to_vec()
+        // Check if we have any unproposed transactions
+        if unproposed_txs.is_empty() {
+            return Ok(vec![])
         }
 
+        // Retrieve the actual unproposed transactions
+        let mut unproposed_txs: Vec<Transaction> = blockchain
+            .pending_txs
+            .get(&unproposed_txs, true)?
+            .iter()
+            .map(|x| x.clone().unwrap())
+            .collect();
+
         // Clone forks' overlay
         let overlay = self.overlay.lock().unwrap().full_clone()?;
 

+ 1 - 1
src/validator/verification.rs

@@ -695,7 +695,7 @@ pub async fn verify_proposal(
     }
 
     // Check that proposal transactions don't exceed limit (2)
-    if proposal.block.txs.len() > TXS_CAP {
+    if proposal.block.txs.len() > TXS_CAP + 1 {
         warn!(
             target: "validator::verification::verify_pow_proposal", "Received proposal transactions exceed configured cap: {} - {}",
             proposal.block.txs.len(),