diff --git a/mobile_verifier/src/reward_shares.rs b/mobile_verifier/src/reward_shares.rs index 076978636..63cb7fffe 100644 --- a/mobile_verifier/src/reward_shares.rs +++ b/mobile_verifier/src/reward_shares.rs @@ -509,7 +509,7 @@ impl CoverageShares { } let sp_boosted_reward_eligibility = - boosted_hex_eligibility.eligibility(pubkey, cbsd_id); + boosted_hex_eligibility.eligibility(radio_type, pubkey, cbsd_id); radio_infos.insert( key, diff --git a/mobile_verifier/src/rewarder.rs b/mobile_verifier/src/rewarder.rs index 80b26461c..ddcd25d4d 100644 --- a/mobile_verifier/src/rewarder.rs +++ b/mobile_verifier/src/rewarder.rs @@ -422,6 +422,8 @@ async fn reward_poc( let boosted_hexes = BoostedHexes::get_all(hex_service_client).await?; + let unique_connections = unique_connections::db::get(pool, reward_period).await?; + let boosted_hex_eligibility = BoostedHexEligibility::new( radio_threshold::verified_radio_thresholds(pool, reward_period).await?, sp_boosted_rewards_bans::db::get_banned_radios( @@ -430,6 +432,7 @@ async fn reward_poc( reward_period.end, ) .await?, + unique_connections.clone(), ); let poc_banned_radios = sp_boosted_rewards_bans::db::get_banned_radios( @@ -439,8 +442,6 @@ async fn reward_poc( ) .await?; - let unique_connections = unique_connections::db::get(pool, reward_period).await?; - let coverage_shares = CoverageShares::new( pool, heartbeats, diff --git a/mobile_verifier/src/rewarder/boosted_hex_eligibility.rs b/mobile_verifier/src/rewarder/boosted_hex_eligibility.rs index 3db3ea19e..5c0a6647e 100644 --- a/mobile_verifier/src/rewarder/boosted_hex_eligibility.rs +++ b/mobile_verifier/src/rewarder/boosted_hex_eligibility.rs @@ -1,28 +1,41 @@ -use coverage_point_calculator::SPBoostedRewardEligibility; +use coverage_point_calculator::{RadioType, SPBoostedRewardEligibility}; use helium_crypto::PublicKeyBinary; -use crate::{radio_threshold::VerifiedRadioThresholds, sp_boosted_rewards_bans::BannedRadios}; +use crate::{ + radio_threshold::VerifiedRadioThresholds, + sp_boosted_rewards_bans::BannedRadios, + unique_connections::{self, UniqueConnectionCounts}, +}; #[derive(Debug, Default)] pub struct BoostedHexEligibility { radio_thresholds: VerifiedRadioThresholds, banned_radios: BannedRadios, + unique_connections: UniqueConnectionCounts, } impl BoostedHexEligibility { - pub fn new(radio_thresholds: VerifiedRadioThresholds, banned_radios: BannedRadios) -> Self { + pub fn new( + radio_thresholds: VerifiedRadioThresholds, + banned_radios: BannedRadios, + unique_connections: UniqueConnectionCounts, + ) -> Self { Self { radio_thresholds, banned_radios, + unique_connections, } } pub fn eligibility( &self, + radio_type: RadioType, key: PublicKeyBinary, cbsd_id_opt: Option, ) -> SPBoostedRewardEligibility { - if self.banned_radios.contains(&key, cbsd_id_opt.as_deref()) { + if unique_connections::is_qualified(&self.unique_connections, &key, &radio_type) { + SPBoostedRewardEligibility::Eligible + } else if self.banned_radios.contains(&key, cbsd_id_opt.as_deref()) { SPBoostedRewardEligibility::ServiceProviderBanned } else if self.radio_thresholds.is_verified(key, cbsd_id_opt) { SPBoostedRewardEligibility::Eligible @@ -36,9 +49,74 @@ impl BoostedHexEligibility { mod tests { use helium_crypto::{KeyTag, Keypair}; use rand::rngs::OsRng; + use unique_connections::MINIMUM_UNIQUE_CONNECTIONS; use super::*; + #[test] + fn wifi_eligible_with_unique_connections_even_if_banned() { + let keypair = generate_keypair(); + + let pub_key: PublicKeyBinary = keypair.public_key().to_vec().into(); + let cbsd_id = "cbsd-id-1".to_string(); + + let mut banned_radios = BannedRadios::default(); + banned_radios.insert_wifi(pub_key.clone()); + banned_radios.insert_cbrs(cbsd_id.clone()); + + let mut unique_connections = UniqueConnectionCounts::default(); + unique_connections.insert(pub_key.clone(), MINIMUM_UNIQUE_CONNECTIONS + 1); + + let boosted_hex_eligibility = BoostedHexEligibility::new( + VerifiedRadioThresholds::default(), + banned_radios, + unique_connections, + ); + + let eligibility = + boosted_hex_eligibility.eligibility(RadioType::OutdoorWifi, pub_key.clone(), None); + + assert_eq!(SPBoostedRewardEligibility::Eligible, eligibility); + + let eligibility = + boosted_hex_eligibility.eligibility(RadioType::OutdoorCbrs, pub_key, Some(cbsd_id)); + + assert_eq!( + SPBoostedRewardEligibility::ServiceProviderBanned, + eligibility + ); + } + + #[test] + fn wifi_eligible_with_unique_connections_even_if_no_radio_threshold() { + let keypair = generate_keypair(); + + let pub_key: PublicKeyBinary = keypair.public_key().to_vec().into(); + let cbsd_id = "cbsd-id-1".to_string(); + + let mut unique_connections = UniqueConnectionCounts::default(); + unique_connections.insert(pub_key.clone(), MINIMUM_UNIQUE_CONNECTIONS + 1); + + let boosted_hex_eligibility = BoostedHexEligibility::new( + VerifiedRadioThresholds::default(), + BannedRadios::default(), + unique_connections, + ); + + let eligibility = + boosted_hex_eligibility.eligibility(RadioType::OutdoorWifi, pub_key.clone(), None); + + assert_eq!(SPBoostedRewardEligibility::Eligible, eligibility); + + let eligibility = + boosted_hex_eligibility.eligibility(RadioType::OutdoorCbrs, pub_key, Some(cbsd_id)); + + assert_eq!( + SPBoostedRewardEligibility::RadioThresholdNotMet, + eligibility + ); + } + #[test] fn banned() { let keypair = generate_keypair(); @@ -50,17 +128,22 @@ mod tests { banned_radios.insert_wifi(pub_key.clone()); banned_radios.insert_cbrs(cbsd_id.clone()); - let boosted_hex_eligibility = - BoostedHexEligibility::new(VerifiedRadioThresholds::default(), banned_radios); + let boosted_hex_eligibility = BoostedHexEligibility::new( + VerifiedRadioThresholds::default(), + banned_radios, + UniqueConnectionCounts::default(), + ); - let eligibility = boosted_hex_eligibility.eligibility(pub_key.clone(), None); + let eligibility = + boosted_hex_eligibility.eligibility(RadioType::OutdoorWifi, pub_key.clone(), None); assert_eq!( SPBoostedRewardEligibility::ServiceProviderBanned, eligibility ); - let eligibility = boosted_hex_eligibility.eligibility(pub_key, Some(cbsd_id)); + let eligibility = + boosted_hex_eligibility.eligibility(RadioType::OutdoorCbrs, pub_key, Some(cbsd_id)); assert_eq!( SPBoostedRewardEligibility::ServiceProviderBanned, @@ -75,17 +158,22 @@ mod tests { let pub_key: PublicKeyBinary = keypair.public_key().to_vec().into(); let cbsd_id = "cbsd-id-1".to_string(); - let boosted_hex_eligibility = - BoostedHexEligibility::new(VerifiedRadioThresholds::default(), BannedRadios::default()); + let boosted_hex_eligibility = BoostedHexEligibility::new( + VerifiedRadioThresholds::default(), + BannedRadios::default(), + UniqueConnectionCounts::default(), + ); - let eligibility = boosted_hex_eligibility.eligibility(pub_key.clone(), None); + let eligibility = + boosted_hex_eligibility.eligibility(RadioType::OutdoorWifi, pub_key.clone(), None); assert_eq!( SPBoostedRewardEligibility::RadioThresholdNotMet, eligibility ); - let eligibility = boosted_hex_eligibility.eligibility(pub_key, Some(cbsd_id)); + let eligibility = + boosted_hex_eligibility.eligibility(RadioType::OutdoorCbrs, pub_key, Some(cbsd_id)); assert_eq!( SPBoostedRewardEligibility::RadioThresholdNotMet, @@ -104,14 +192,19 @@ mod tests { verified_radio_thresholds.insert(pub_key.clone(), None); verified_radio_thresholds.insert(pub_key.clone(), Some(cbsd_id.clone())); - let boosted_hex_eligibility = - BoostedHexEligibility::new(verified_radio_thresholds, BannedRadios::default()); + let boosted_hex_eligibility = BoostedHexEligibility::new( + verified_radio_thresholds, + BannedRadios::default(), + UniqueConnectionCounts::default(), + ); - let eligibility = boosted_hex_eligibility.eligibility(pub_key.clone(), None); + let eligibility = + boosted_hex_eligibility.eligibility(RadioType::OutdoorWifi, pub_key.clone(), None); assert_eq!(SPBoostedRewardEligibility::Eligible, eligibility); - let eligibility = boosted_hex_eligibility.eligibility(pub_key, Some(cbsd_id)); + let eligibility = + boosted_hex_eligibility.eligibility(RadioType::OutdoorCbrs, pub_key, Some(cbsd_id)); assert_eq!(SPBoostedRewardEligibility::Eligible, eligibility); } diff --git a/mobile_verifier/src/unique_connections/mod.rs b/mobile_verifier/src/unique_connections/mod.rs index 096187a5b..7671ef843 100644 --- a/mobile_verifier/src/unique_connections/mod.rs +++ b/mobile_verifier/src/unique_connections/mod.rs @@ -10,7 +10,7 @@ pub type UniqueConnectionCounts = HashMap; // hip-134: // https://github.com/helium/HIP/blob/main/0134-reward-mobile-carrier-offload-hotspots.md // A Hotspot serving >25 unique connections, as defined by the Carrier utlizing the hotspots for Carrier Offload, on a seven day rolling average. -const MINIMUM_UNIQUE_CONNECTIONS: u64 = 25; +pub const MINIMUM_UNIQUE_CONNECTIONS: u64 = 25; pub fn is_qualified( unique_connections: &UniqueConnectionCounts,