From 09054c3f81a92a26f20276721a6c4e21505ec51c Mon Sep 17 00:00:00 2001 From: Brian Balser Date: Thu, 23 Jan 2025 12:37:00 -0500 Subject: [PATCH] HIP-140: > 25 unique connections required for boosted hex eligibility (#931) * HIP-140: > 25 unique connections required for boosted hex eligibility * fix some tests * fix integration test * putting most of radio thresholds check back in * check unique connections if radio is in US, otherwise check radio thresholdds * Add tests covering outside of states * Update comments * move proto back to master --------- Co-authored-by: Michael Jeffrey --- Cargo.lock | 4 +- coverage_point_calculator/src/lib.rs | 20 +- .../src/service_provider_boosting.rs | 12 +- mobile_verifier/src/reward_shares.rs | 14 +- .../src/reward_shares/radio_reward_v2.rs | 10 +- mobile_verifier/src/rewarder.rs | 6 - .../src/rewarder/boosted_hex_eligibility.rs | 209 ++++++++---------- .../tests/integrations/hex_boosting.rs | 92 +++----- 8 files changed, 160 insertions(+), 207 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 868ac11a9..4cc56b556 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1615,7 +1615,7 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "beacon" version = "0.1.0" -source = "git+https://github.com/helium/proto?branch=master#4085e00c6f4d82c3da798ae1bc97324bc9cada2e" +source = "git+https://github.com/helium/proto?branch=master#f79c34f0a6d9c9e17d5cea8d7692797bdaed09be" dependencies = [ "base64 0.21.7", "byteorder", @@ -3820,7 +3820,7 @@ dependencies = [ [[package]] name = "helium-proto" version = "0.1.0" -source = "git+https://github.com/helium/proto?branch=master#4085e00c6f4d82c3da798ae1bc97324bc9cada2e" +source = "git+https://github.com/helium/proto?branch=master#f79c34f0a6d9c9e17d5cea8d7692797bdaed09be" dependencies = [ "bytes", "prost", diff --git a/coverage_point_calculator/src/lib.rs b/coverage_point_calculator/src/lib.rs index 9a2ea0951..59efacc56 100644 --- a/coverage_point_calculator/src/lib.rs +++ b/coverage_point_calculator/src/lib.rs @@ -48,7 +48,8 @@ //! //! - [SPBoostedRewardEligibility] //! - Radio must pass at least 1mb of data from 3 unique phones [HIP-84][provider-boosting] -//! - Service Provider can invalidate boosted rewards of a hotspot [HIP-125][provider-banning] +//! - Radio must serve >25 unique connections on a rolling 7-day window [HIP-140][sp-boost-qualifiers] +//! - [@deprecated] Service Provider can invalidate boosted rewards of a hotspot [HIP-125][provider-banning] //! //! - [OracleBoostingStatus] //! - Eligible: Radio is eligible for normal oracle boosting multipliers @@ -69,6 +70,7 @@ //! [provider-banning]: https://github.com/helium/HIP/blob/main/0125-temporary-anti-gaming-measures-for-boosted-hexes.md //! [anti-gaming]: https://github.com/helium/HIP/blob/main/0131-bridging-gap-between-verification-mappers-and-anti-gaming-measures.md //! [carrier-offload]: https://github.com/helium/HIP/blob/main/0134-reward-mobile-carrier-offload-hotspots.md +//! [sp-boost-qualifiers]: https://github.com/helium/HIP/blob/main/0140-adjust-service-provider-boost-qualifiers.md //! pub use crate::{ hexes::{CoveredHex, HexPoints}, @@ -242,7 +244,7 @@ impl CoveragePoints { SpBoostedHexStatus::WifiLocationScoreBelowThreshold(_) => dec!(0), SpBoostedHexStatus::AverageAssertedDistanceOverLimit(_) => dec!(0), SpBoostedHexStatus::RadioThresholdNotMet => dec!(0), - SpBoostedHexStatus::ServiceProviderBanned => dec!(0), + SpBoostedHexStatus::NotEnoughConnections => dec!(0), } } } @@ -260,7 +262,7 @@ pub enum SpBoostedHexStatus { WifiLocationScoreBelowThreshold(Decimal), AverageAssertedDistanceOverLimit(Decimal), RadioThresholdNotMet, - ServiceProviderBanned, + NotEnoughConnections, } impl SpBoostedHexStatus { @@ -271,10 +273,10 @@ impl SpBoostedHexStatus { service_provider_boosted_reward_eligibility: SPBoostedRewardEligibility, ) -> Self { match service_provider_boosted_reward_eligibility { - // hip-125: if radio has been banned by service provider, no boosting - SPBoostedRewardEligibility::ServiceProviderBanned => Self::ServiceProviderBanned, // hip-84: if radio has not met minimum data and subscriber thresholds, no boosting SPBoostedRewardEligibility::RadioThresholdNotMet => Self::RadioThresholdNotMet, + // hip-140: radio must have enough unique connections + SPBoostedRewardEligibility::NotEnoughConnections => Self::NotEnoughConnections, SPBoostedRewardEligibility::Eligible => { // hip-93: if radio is wifi & location_trust score multiplier < 0.75, no boosting if radio_type.is_wifi() && location_trust_multiplier < MIN_WIFI_TRUST_MULTIPLIER { @@ -941,12 +943,8 @@ mod tests { SpBoostedHexStatus::WifiLocationScoreBelowThreshold(dec!(0)), ); assert_eq!( - wifi_bad_trust_score(SPBoostedRewardEligibility::ServiceProviderBanned), - SpBoostedHexStatus::ServiceProviderBanned - ); - assert_eq!( - wifi_bad_trust_score(SPBoostedRewardEligibility::RadioThresholdNotMet), - SpBoostedHexStatus::RadioThresholdNotMet + wifi_bad_trust_score(SPBoostedRewardEligibility::NotEnoughConnections), + SpBoostedHexStatus::NotEnoughConnections ); } diff --git a/coverage_point_calculator/src/service_provider_boosting.rs b/coverage_point_calculator/src/service_provider_boosting.rs index af31b524a..5a20f001d 100644 --- a/coverage_point_calculator/src/service_provider_boosting.rs +++ b/coverage_point_calculator/src/service_provider_boosting.rs @@ -22,16 +22,16 @@ pub(crate) const MAX_AVERAGE_DISTANCE: Decimal = dec!(50); #[derive(Debug, Clone, Copy, PartialEq)] pub enum SPBoostedRewardEligibility { Eligible, - /// Service Provider can invalidate boosted rewards of a hotspot - /// - /// [HIP-125: Anti gaming measures][anti-gaming] - /// - /// [anti-gaming]: https://github.com/helium/HIP/blob/main/0125-temporary-anti-gaming-measures-for-boosted-hexes.md - ServiceProviderBanned, /// Radio must pass at least 1mb of data from 3 unique phones. /// /// [HIP-84: Provider Hex Boosting][provider-boosting] /// /// [provider-boosting]: https://github.com/helium/HIP/blob/main/0084-service-provider-hex-boosting.md RadioThresholdNotMet, + /// Radio must have greather than 25 unique connections over 7 days + /// + /// [HIP-140: Adjust Service Provider Boost Qualifiers][adjust-service-provider-boost-qualifiers] + /// + /// [adjust-service-provider-boost-qualifiers]: https://github.com/helium/HIP/blob/main/0140-adjust-service-provider-boost-qualifiers.md + NotEnoughConnections, } diff --git a/mobile_verifier/src/reward_shares.rs b/mobile_verifier/src/reward_shares.rs index 63cb7fffe..b93c686ae 100644 --- a/mobile_verifier/src/reward_shares.rs +++ b/mobile_verifier/src/reward_shares.rs @@ -493,6 +493,13 @@ impl CoverageShares { OracleBoostingStatus::Eligible }; + let sp_boosted_reward_eligibility = boosted_hex_eligibility.eligibility( + radio_type, + pubkey.clone(), + cbsd_id.clone(), + &covered_hexes, + ); + if eligible_for_coverage_map( oracle_boosting_status, &speedtests, @@ -501,16 +508,13 @@ impl CoverageShares { ) { coverage_map_builder.insert_coverage_object(coverage_map::CoverageObject { indoor: is_indoor, - hotspot_key: pubkey.clone().into(), - cbsd_id: cbsd_id.clone(), + hotspot_key: pubkey.into(), + cbsd_id, seniority_timestamp: seniority.seniority_ts, coverage: covered_hexes, }); } - let sp_boosted_reward_eligibility = - boosted_hex_eligibility.eligibility(radio_type, pubkey, cbsd_id); - radio_infos.insert( key, RadioInfo { diff --git a/mobile_verifier/src/reward_shares/radio_reward_v2.rs b/mobile_verifier/src/reward_shares/radio_reward_v2.rs index 22447511f..111961b71 100644 --- a/mobile_verifier/src/reward_shares/radio_reward_v2.rs +++ b/mobile_verifier/src/reward_shares/radio_reward_v2.rs @@ -64,14 +64,14 @@ impl RadioRewardV2Ext for coverage_point_calculator::CoveragePoints { coverage_point_calculator::SpBoostedHexStatus::WifiLocationScoreBelowThreshold(_) => { SpBoostedHexStatus::LocationScoreBelowThreshold } + coverage_point_calculator::SpBoostedHexStatus::AverageAssertedDistanceOverLimit(_) => { + SpBoostedHexStatus::AverageAssertedDistanceOverLimit + } coverage_point_calculator::SpBoostedHexStatus::RadioThresholdNotMet => { SpBoostedHexStatus::RadioThresholdNotMet } - coverage_point_calculator::SpBoostedHexStatus::ServiceProviderBanned => { - SpBoostedHexStatus::ServiceProviderBan - } - coverage_point_calculator::SpBoostedHexStatus::AverageAssertedDistanceOverLimit(_) => { - SpBoostedHexStatus::AverageAssertedDistanceOverLimit + coverage_point_calculator::SpBoostedHexStatus::NotEnoughConnections => { + SpBoostedHexStatus::NotEnoughConnections } } } diff --git a/mobile_verifier/src/rewarder.rs b/mobile_verifier/src/rewarder.rs index ddcd25d4d..8db8ea80f 100644 --- a/mobile_verifier/src/rewarder.rs +++ b/mobile_verifier/src/rewarder.rs @@ -426,12 +426,6 @@ async fn reward_poc( let boosted_hex_eligibility = BoostedHexEligibility::new( radio_threshold::verified_radio_thresholds(pool, reward_period).await?, - sp_boosted_rewards_bans::db::get_banned_radios( - pool, - SpBoostedRewardsBannedRadioBanType::BoostedHex, - reward_period.end, - ) - .await?, unique_connections.clone(), ); diff --git a/mobile_verifier/src/rewarder/boosted_hex_eligibility.rs b/mobile_verifier/src/rewarder/boosted_hex_eligibility.rs index 5c0a6647e..8387a6d31 100644 --- a/mobile_verifier/src/rewarder/boosted_hex_eligibility.rs +++ b/mobile_verifier/src/rewarder/boosted_hex_eligibility.rs @@ -1,28 +1,26 @@ +use coverage_map::UnrankedCoverage; use coverage_point_calculator::{RadioType, SPBoostedRewardEligibility}; use helium_crypto::PublicKeyBinary; +use hex_assignments::Assignment; 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, unique_connections: UniqueConnectionCounts, ) -> Self { Self { radio_thresholds, - banned_radios, unique_connections, } } @@ -32,148 +30,125 @@ impl BoostedHexEligibility { radio_type: RadioType, key: PublicKeyBinary, cbsd_id_opt: Option, + covered_hexes: &[UnrankedCoverage], ) -> SPBoostedRewardEligibility { - if unique_connections::is_qualified(&self.unique_connections, &key, &radio_type) { + if Self::in_united_states(covered_hexes) { + self.check_unique_connections(&key, &radio_type) + } else { + self.check_radio_thresholds(key, cbsd_id_opt) + } + } + + fn check_unique_connections( + &self, + key: &PublicKeyBinary, + radio_type: &RadioType, + ) -> SPBoostedRewardEligibility { + 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) { + } else { + SPBoostedRewardEligibility::NotEnoughConnections + } + } + + fn check_radio_thresholds( + &self, + key: PublicKeyBinary, + cbsd_id_opt: Option, + ) -> SPBoostedRewardEligibility { + if self.radio_thresholds.is_verified(key, cbsd_id_opt) { SPBoostedRewardEligibility::Eligible } else { SPBoostedRewardEligibility::RadioThresholdNotMet } } + + fn in_united_states(covered_hexes: &[UnrankedCoverage]) -> bool { + covered_hexes + .iter() + .any(|uc| uc.assignments.urbanized != Assignment::C) + } } #[cfg(test)] mod tests { use helium_crypto::{KeyTag, Keypair}; + use hex_assignments::assignment::HexAssignments; + use hextree::Cell; use rand::rngs::OsRng; use unique_connections::MINIMUM_UNIQUE_CONNECTIONS; use super::*; #[test] - fn wifi_eligible_with_unique_connections_even_if_banned() { + fn eligible_in_united_states() { 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); + let boosted_hex_eligibility = + BoostedHexEligibility::new(VerifiedRadioThresholds::default(), unique_connections); - assert_eq!(SPBoostedRewardEligibility::Eligible, eligibility); + let covered_hexes = vec![unranked_coverage(Assignment::A)]; - let eligibility = - boosted_hex_eligibility.eligibility(RadioType::OutdoorCbrs, pub_key, Some(cbsd_id)); - - assert_eq!( - SPBoostedRewardEligibility::ServiceProviderBanned, - eligibility + let eligibility = boosted_hex_eligibility.eligibility( + RadioType::OutdoorWifi, + pub_key, + None, + &covered_hexes, ); - } - - #[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() { + fn eligible_outside_states() { 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 unique_connections = UniqueConnectionCounts::default(); + let mut verified_thresholds = VerifiedRadioThresholds::default(); + verified_thresholds.insert(pub_key.clone(), None); - let boosted_hex_eligibility = BoostedHexEligibility::new( - VerifiedRadioThresholds::default(), - banned_radios, - UniqueConnectionCounts::default(), - ); + let boosted_hex_eligibility = + BoostedHexEligibility::new(verified_thresholds, unique_connections); - let eligibility = - boosted_hex_eligibility.eligibility(RadioType::OutdoorWifi, pub_key.clone(), None); + let covered_hexes = vec![unranked_coverage(Assignment::C)]; - assert_eq!( - SPBoostedRewardEligibility::ServiceProviderBanned, - eligibility + let eligibility = boosted_hex_eligibility.eligibility( + RadioType::OutdoorWifi, + pub_key, + None, + &covered_hexes, ); - let eligibility = - boosted_hex_eligibility.eligibility(RadioType::OutdoorCbrs, pub_key, Some(cbsd_id)); - - assert_eq!( - SPBoostedRewardEligibility::ServiceProviderBanned, - eligibility - ); + assert_eq!(SPBoostedRewardEligibility::Eligible, eligibility); } #[test] - fn radio_threshold_not_met() { + fn radio_thresholds_not_met() { let keypair = generate_keypair(); 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(), - UniqueConnectionCounts::default(), - ); + let unique_connections = UniqueConnectionCounts::default(); + let verified_thresholds = VerifiedRadioThresholds::default(); - let eligibility = - boosted_hex_eligibility.eligibility(RadioType::OutdoorWifi, pub_key.clone(), None); + let boosted_hex_eligibility = + BoostedHexEligibility::new(verified_thresholds, unique_connections); - assert_eq!( - SPBoostedRewardEligibility::RadioThresholdNotMet, - eligibility - ); + let covered_hexes = vec![unranked_coverage(Assignment::C)]; - let eligibility = - boosted_hex_eligibility.eligibility(RadioType::OutdoorCbrs, pub_key, Some(cbsd_id)); + let eligibility = boosted_hex_eligibility.eligibility( + RadioType::OutdoorWifi, + pub_key, + None, + &covered_hexes, + ); assert_eq!( SPBoostedRewardEligibility::RadioThresholdNotMet, @@ -182,34 +157,46 @@ mod tests { } #[test] - fn eligible() { + fn not_enough_connections() { let keypair = generate_keypair(); let pub_key: PublicKeyBinary = keypair.public_key().to_vec().into(); - let cbsd_id = "cbsd-id-1".to_string(); - let mut verified_radio_thresholds = VerifiedRadioThresholds::default(); - 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(), - UniqueConnectionCounts::default(), - ); + let mut unique_connections = UniqueConnectionCounts::default(); + unique_connections.insert(pub_key.clone(), MINIMUM_UNIQUE_CONNECTIONS); - let eligibility = - boosted_hex_eligibility.eligibility(RadioType::OutdoorWifi, pub_key.clone(), None); + let boosted_hex_eligibility = + BoostedHexEligibility::new(VerifiedRadioThresholds::default(), unique_connections); - assert_eq!(SPBoostedRewardEligibility::Eligible, eligibility); + let covered_hexes = vec![unranked_coverage(Assignment::A)]; - let eligibility = - boosted_hex_eligibility.eligibility(RadioType::OutdoorCbrs, pub_key, Some(cbsd_id)); + let eligibility = boosted_hex_eligibility.eligibility( + RadioType::OutdoorWifi, + pub_key, + None, + &covered_hexes, + ); - assert_eq!(SPBoostedRewardEligibility::Eligible, eligibility); + assert_eq!( + SPBoostedRewardEligibility::NotEnoughConnections, + eligibility + ); } fn generate_keypair() -> Keypair { Keypair::generate(KeyTag::default(), &mut OsRng) } + + fn unranked_coverage(urbanized: Assignment) -> UnrankedCoverage { + UnrankedCoverage { + location: Cell::from_raw(631236586635449855).expect("invalid cell"), + signal_power: 0, + signal_level: coverage_map::SignalLevel::High, + assignments: HexAssignments { + footfall: Assignment::A, + landtype: Assignment::A, + urbanized, + }, + } + } } diff --git a/mobile_verifier/tests/integrations/hex_boosting.rs b/mobile_verifier/tests/integrations/hex_boosting.rs index ae11f4363..294e6c2ba 100644 --- a/mobile_verifier/tests/integrations/hex_boosting.rs +++ b/mobile_verifier/tests/integrations/hex_boosting.rs @@ -2,8 +2,8 @@ use crate::common::{self, MockFileSinkReceiver, MockHexBoostingClient, RadioRewa use chrono::{DateTime, Duration as ChronoDuration, Duration, Utc}; use file_store::{ coverage::{CoverageObject as FSCoverageObject, KeyType, RadioHexSignalLevel}, - mobile_radio_threshold::{RadioThresholdIngestReport, RadioThresholdReportReq}, speedtest::CellSpeedtest, + unique_connections::{UniqueConnectionReq, UniqueConnectionsIngestReport}, }; use helium_crypto::PublicKeyBinary; use helium_proto::services::{ @@ -19,7 +19,8 @@ use mobile_verifier::{ cell_type::CellType, coverage::CoverageObject, heartbeats::{HbType, Heartbeat, ValidatedHeartbeat}, - radio_threshold, reward_shares, rewarder, speedtests, + reward_shares, rewarder, speedtests, + unique_connections::{self, MINIMUM_UNIQUE_CONNECTIONS}, }; use rust_decimal::prelude::*; use rust_decimal_macros::dec; @@ -63,7 +64,7 @@ async fn test_poc_with_boosted_hexes(pool: PgPool) -> anyhow::Result<()> { // seed HBs where we have a coverage reports for a singluar hex location per radio seed_heartbeats_v1(epoch.start, &mut txn).await?; seed_speedtests(epoch.end, &mut txn).await?; - seed_radio_thresholds(epoch.start, &mut txn).await?; + seed_unique_connections(epoch.start, &mut txn).await?; txn.commit().await?; update_assignments(&pool).await?; @@ -396,7 +397,7 @@ async fn test_poc_with_multi_coverage_boosted_hexes(pool: PgPool) -> anyhow::Res // seed HBs where we have multiple coverage reports for one radio and one report for the others seed_heartbeats_v2(epoch.start, &mut txn).await?; seed_speedtests(epoch.end, &mut txn).await?; - seed_radio_thresholds(epoch.start, &mut txn).await?; + seed_unique_connections(epoch.start, &mut txn).await?; txn.commit().await?; update_assignments(&pool).await?; @@ -610,7 +611,7 @@ async fn test_expired_boosted_hex(pool: PgPool) -> anyhow::Result<()> { let mut txn = pool.clone().begin().await?; seed_heartbeats_v1(epoch.start, &mut txn).await?; seed_speedtests(epoch.end, &mut txn).await?; - seed_radio_thresholds(epoch.start, &mut txn).await?; + seed_unique_connections(epoch.start, &mut txn).await?; txn.commit().await?; update_assignments(&pool).await?; @@ -748,7 +749,7 @@ async fn test_reduced_location_score_with_boosted_hexes(pool: PgPool) -> anyhow: ) .await?; seed_speedtests(epoch.end, &mut txn).await?; - seed_radio_thresholds(epoch.start, &mut txn).await?; + seed_unique_connections(epoch.start, &mut txn).await?; txn.commit().await?; update_assignments(&pool).await?; @@ -928,7 +929,7 @@ async fn test_distance_from_asserted_removes_boosting_but_not_location_trust( ) .await?; seed_speedtests(epoch.end, &mut txn).await?; - seed_radio_thresholds(epoch.start, &mut txn).await?; + seed_unique_connections(epoch.start, &mut txn).await?; txn.commit().await?; update_assignments(&pool).await?; @@ -1090,7 +1091,7 @@ async fn test_poc_with_cbrs_and_multi_coverage_boosted_hexes(pool: PgPool) -> an // include a cbrs radio alongside 2 wifi radios seed_heartbeats_v4(epoch.start, &mut txn).await?; seed_speedtests(epoch.end, &mut txn).await?; - seed_radio_thresholds(epoch.start, &mut txn).await?; + seed_unique_connections(epoch.start, &mut txn).await?; txn.commit().await?; update_assignments(&pool).await?; @@ -1249,9 +1250,9 @@ async fn test_poc_with_cbrs_and_multi_coverage_boosted_hexes(pool: PgPool) -> an // assert the number of boosted hexes for each radio assert_eq!(1, hotspot_2.boosted_hexes_len()); assert_eq!(2, hotspot_1.boosted_hexes_len()); - // hotspot 3 has 1 boosted hex at 1x, it does not effect rewards, but all - // covered hexes are reported with their corresponding boost values. - assert_eq!(1, hotspot_3.boosted_hexes_len()); + // hotspot 3 is CBRS and is no longer eligible for boosted rewards according + // to HIP-140 + assert_eq!(0, hotspot_3.boosted_hexes_len()); // assert the hex boost multiplier values // as hotspot 3 has 2 covered hexes, it should have 2 boosted hexes @@ -1740,59 +1741,28 @@ async fn seed_speedtests( Ok(()) } -async fn seed_radio_thresholds( +async fn seed_unique_connections( ts: DateTime, txn: &mut Transaction<'_, Postgres>, ) -> anyhow::Result<()> { - let report1 = RadioThresholdIngestReport { - received_timestamp: Default::default(), - report: RadioThresholdReportReq { - hotspot_pubkey: HOTSPOT_1.parse().unwrap(), - cbsd_id: Some("".to_string()), - bytes_threshold: 1000000, - subscriber_threshold: 3, - threshold_timestamp: ts, - carrier_pub_key: CARRIER_HOTSPOT_KEY.parse().unwrap(), - }, - }; - let report2 = RadioThresholdIngestReport { - received_timestamp: Default::default(), - report: RadioThresholdReportReq { - hotspot_pubkey: HOTSPOT_2.parse().unwrap(), - cbsd_id: None, - bytes_threshold: 1000000, - subscriber_threshold: 3, - threshold_timestamp: ts, - carrier_pub_key: CARRIER_HOTSPOT_KEY.parse().unwrap(), - }, - }; - let report3 = RadioThresholdIngestReport { - received_timestamp: Default::default(), - report: RadioThresholdReportReq { - hotspot_pubkey: HOTSPOT_3.parse().unwrap(), - cbsd_id: Some("".to_string()), - bytes_threshold: 1000000, - subscriber_threshold: 3, - threshold_timestamp: ts, - carrier_pub_key: CARRIER_HOTSPOT_KEY.parse().unwrap(), - }, - }; - let cbsd_id = Some("P27-SCE4255W0002".to_string()); - let report4 = RadioThresholdIngestReport { - received_timestamp: Default::default(), - report: RadioThresholdReportReq { - hotspot_pubkey: HOTSPOT_4.parse().unwrap(), - cbsd_id, - bytes_threshold: 1000000, - subscriber_threshold: 3, - threshold_timestamp: ts, - carrier_pub_key: CARRIER_HOTSPOT_KEY.parse().unwrap(), - }, - }; - radio_threshold::save(&report1, txn).await?; - radio_threshold::save(&report2, txn).await?; - radio_threshold::save(&report3, txn).await?; - radio_threshold::save(&report4, txn).await?; + let reports: Vec<_> = vec![HOTSPOT_1, HOTSPOT_2, HOTSPOT_3, HOTSPOT_4] + .into_iter() + .map(|key| UniqueConnectionsIngestReport { + received_timestamp: ts, + report: UniqueConnectionReq { + pubkey: key.parse().unwrap(), + start_timestamp: ts, + end_timestamp: ts + Duration::hours(24), + unique_connections: MINIMUM_UNIQUE_CONNECTIONS + 1, + timestamp: ts, + carrier_key: CARRIER_HOTSPOT_KEY.parse().unwrap(), + signature: vec![], + }, + }) + .collect(); + + unique_connections::db::save(txn, &reports).await?; + Ok(()) }