Repository: informalsystems/tendermint-rs (language: rust)

Issue:
light-client: consider optimizing voting power calculation by stopping after verifying +1/3 or +2/3  
`voting_power_in(&self, validators: &Set)` https://github.com/informalsystems/tendermint-rs/blob/efadd8b4a5032b951e764ad12b2e6aac8bd8e99e/tendermint/src/lite_impl/signed_header.rs#L15 function is suboptimal. 

You don’t have to calculate all the voting power. What you want is to verify that trust threshold (⅔+ in sequential verification or configurable ⅓+ in skipping verification) signed this commit.

In Go Tendermint, Verify function returns as soon as threshold is reached. https://github.com/tendermint/tendermint/blob/7b717c72df1e9d38cdaf110cdbdaa57459272dc1/types/validator_set.go#L664 



Discussion / hints:
This will be especially relevant once #506 is done
This could be further optimized by utilizing batch verification from dalek or zebra. 

Fix patch:
diff --git a/.changelog/unreleased/improvements/1395-optimize-voting-power-calculation.md b/.changelog/unreleased/improvements/1395-optimize-voting-power-calculation.md
new file mode 100644
index 000000000..3ebc15e59
--- /dev/null
+++ b/.changelog/unreleased/improvements/1395-optimize-voting-power-calculation.md
@@ -0,0 +1,2 @@
+- `[tendermint-light-client-verifer]` Optimizing voting power calculation by breaking the loop when we have enough voting power 
+  ([#1378](https://github.com/informalsystems/tendermint-rs/pull/1395)).
diff --git a/light-client-verifier/src/operations/voting_power.rs b/light-client-verifier/src/operations/voting_power.rs
index 15b6405bc..8fb8ecd85 100644
--- a/light-client-verifier/src/operations/voting_power.rs
+++ b/light-client-verifier/src/operations/voting_power.rs
@@ -131,6 +131,7 @@ impl<V: signature::Verifier> VotingPowerCalculator for ProvidedVotingPowerCalcul
         trust_threshold: TrustThreshold,
     ) -> Result<VotingPowerTally, VerificationError> {
         let signatures = &signed_header.commit.signatures;
+        let total_voting_power = self.total_power_of(validator_set);
 
         let mut tallied_voting_power = 0_u64;
         let mut seen_validators = HashSet::new();
@@ -185,12 +186,14 @@ impl<V: signature::Verifier> VotingPowerCalculator for ProvidedVotingPowerCalcul
                 // to measure validator availability.
             }
 
-            // TODO: Break out of the loop when we have enough voting power.
-            // See https://github.com/informalsystems/tendermint-rs/issues/235
+            // Break out of the loop when we have enough voting power.
+            if trust_threshold.is_enough_power(tallied_voting_power, total_voting_power) {
+                break;
+            }
         }
 
         let voting_power = VotingPowerTally {
-            total: self.total_power_of(validator_set),
+            total: total_voting_power,
             tallied: tallied_voting_power,
             trust_threshold,
         };


Test patch: