Skip to content

Commit

Permalink
Implementation of HIP-131 (#858)
Browse files Browse the repository at this point in the history
* Save ban_type to db when receiving new ban reports

* Update query

* Update coverage_point_calculator to accept hip131_ban boolean

* Update mobile-verifier to pass pan flag to coverage point calculator

* Update cargo lock

* Update new test

* Change bool to OracleBoostingStatus enum

* Address feedback, move oracle_boosting_status into RadioInfo

* Update Cargo.lock

* use radio_info as the source for all that we can

Why pass in information from a source that we're going to be using
gratuitously within the same function. Did I spell that right?

* Update proto back to master

* Update helium-proto to tip of master

---------

Co-authored-by: Michael Jeffrey <michaeldjeffrey@gmail.com>
  • Loading branch information
bbalser and michaeldjeffrey committed Sep 4, 2024
1 parent 901d6fd commit 2d6bd03
Show file tree
Hide file tree
Showing 12 changed files with 211 additions and 48 deletions.
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

54 changes: 47 additions & 7 deletions coverage_point_calculator/src/hexes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use hex_assignments::assignment::HexAssignments;
use rust_decimal::Decimal;
use rust_decimal_macros::dec;

use crate::{BoostedHexStatus, RadioType, Result};
use crate::{OracleBoostingStatus, RadioType, Result, SpBoostedHexStatus};

/// Breakdown of points for a hex.
///
Expand Down Expand Up @@ -58,8 +58,9 @@ pub struct CoveredHex {

pub(crate) fn clean_covered_hexes(
radio_type: RadioType,
boosted_hex_status: BoostedHexStatus,
boosted_hex_status: SpBoostedHexStatus,
ranked_coverage: Vec<RankedCoverage>,
oracle_boosting_status: OracleBoostingStatus,
) -> Result<Vec<CoveredHex>> {
// verify all hexes can obtain a base coverage point
let covered_hexes = ranked_coverage
Expand All @@ -74,9 +75,12 @@ pub(crate) fn clean_covered_hexes(
None
};

// hip-131: if the radio is banned, it automatically gets an assignment_multiplier of 0.0
// hip-103: if a hex is boosted by a service provider >=1x, the oracle
// multiplier will automatically be 1x, regardless of boosted_hex_status.
let assignment_multiplier = if ranked.boosted.is_some() {
let assignment_multiplier = if oracle_boosting_status == OracleBoostingStatus::Banned {
dec!(0)
} else if ranked.boosted.is_some() {
dec!(1)
} else {
ranked.assignments.boosting_multiplier()
Expand Down Expand Up @@ -132,11 +136,11 @@ mod tests {
use super::*;

#[rstest]
#[case(BoostedHexStatus::Eligible)]
#[case(BoostedHexStatus::WifiLocationScoreBelowThreshold(dec!(999)))]
#[case(BoostedHexStatus::RadioThresholdNotMet)]
#[case(SpBoostedHexStatus::Eligible)]
#[case(SpBoostedHexStatus::WifiLocationScoreBelowThreshold(dec!(999)))]
#[case(SpBoostedHexStatus::RadioThresholdNotMet)]
fn hip_103_provider_boosted_hex_receives_maximum_oracle_boost(
#[case] boost_status: BoostedHexStatus,
#[case] boost_status: SpBoostedHexStatus,
) {
// Regardless of the radio's eligibility to receive provider boosted
// rewards, a boosted hex increases the oracle assignment.
Expand All @@ -162,6 +166,7 @@ mod tests {
RadioType::IndoorWifi,
boost_status,
vec![unboosted_coverage, boosted_coverage],
OracleBoostingStatus::Eligible,
)
.unwrap();

Expand All @@ -174,4 +179,39 @@ mod tests {
// provider boosted gets oracle assignment bumped to 1x
assert_eq!(dec!(1), boosted.assignment_multiplier);
}

#[rstest]
fn hip131_banned_radio() {
let unboosted_coverage = RankedCoverage {
hotspot_key: vec![1],
cbsd_id: None,
hex: hextree::Cell::from_raw(0x8c2681a3064edff).unwrap(),
rank: 1,
signal_level: SignalLevel::High,
assignments: HexAssignments {
footfall: Assignment::A,
landtype: Assignment::A,
urbanized: Assignment::A,
},
boosted: NonZeroU32::new(0),
};

let boosted_coverage = RankedCoverage {
boosted: NonZeroU32::new(5),
..unboosted_coverage.clone()
};

let covered_hexes = clean_covered_hexes(
RadioType::IndoorWifi,
SpBoostedHexStatus::Eligible,
vec![unboosted_coverage, boosted_coverage],
OracleBoostingStatus::Banned,
)
.unwrap();

dbg!(&covered_hexes);

assert_eq!(dec!(0), covered_hexes[0].assignment_multiplier);
assert_eq!(dec!(0), covered_hexes[1].assignment_multiplier);
}
}
61 changes: 46 additions & 15 deletions coverage_point_calculator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@
//! - 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]
//!
//! - [OracleBoostingStatus]
//! - Eligible: Radio is eligible for normal oracle boosting multipliers
//! - Banned: Radio is banned according to hip-131 rules and all assignment_multipliers are 0.0
//!
//! [modeled-coverage]: https://github.com/helium/HIP/blob/main/0074-mobile-poc-modeled-coverage-rewards.md#outdoor-radios
//! [provider-boosting]: https://github.com/helium/HIP/blob/main/0084-service-provider-hex-boosting.md
//! [wifi-aps]: https://github.com/helium/HIP/blob/main/0093-addition-of-wifi-aps-to-mobile-subdao.md
Expand All @@ -60,6 +64,7 @@
//! [boosted-hex-restriction]: https://github.com/helium/oracles/pull/808
//! [location-gaming]: https://github.com/helium/HIP/blob/main/0119-closing-gaming-loopholes-within-the-mobile-network.md
//! [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
//!
pub use crate::{
hexes::{CoveredHex, HexPoints},
Expand Down Expand Up @@ -134,7 +139,7 @@ pub struct CoveragePoints {
/// Input ServiceProviderBoostedRewardEligibility
pub service_provider_boosted_reward_eligibility: SPBoostedRewardEligibility,
/// Derived Eligibility for Boosted Hex Rewards
pub boosted_hex_eligibility: BoostedHexStatus,
pub boosted_hex_eligibility: SpBoostedHexStatus,
/// Speedtests used in calculation
pub speedtests: Vec<Speedtest>,
/// Location Trust Scores used in calculation
Expand All @@ -152,18 +157,24 @@ impl CoveragePoints {
speedtests: Vec<Speedtest>,
location_trust_scores: Vec<LocationTrust>,
ranked_coverage: Vec<coverage_map::RankedCoverage>,
oracle_boosting_status: OracleBoostingStatus,
) -> Result<CoveragePoints> {
let location_trust_multiplier = location::multiplier(radio_type, &location_trust_scores);

let boost_eligibility = BoostedHexStatus::new(
let boost_eligibility = SpBoostedHexStatus::new(
radio_type,
location_trust_multiplier,
&location_trust_scores,
service_provider_boosted_reward_eligibility,
);

let covered_hexes =
hexes::clean_covered_hexes(radio_type, boost_eligibility, ranked_coverage)?;
let covered_hexes = hexes::clean_covered_hexes(
radio_type,
boost_eligibility,
ranked_coverage,
oracle_boosting_status,
)?;

let hex_coverage_points = hexes::calculated_coverage_points(&covered_hexes);

let speedtests = speedtest::clean_speedtests(speedtests);
Expand Down Expand Up @@ -220,25 +231,31 @@ impl CoveragePoints {

fn boosted_points(&self) -> Decimal {
match self.boosted_hex_eligibility {
BoostedHexStatus::Eligible => self.coverage_points.boosted,
BoostedHexStatus::WifiLocationScoreBelowThreshold(_) => dec!(0),
BoostedHexStatus::AverageAssertedDistanceOverLimit(_) => dec!(0),
BoostedHexStatus::RadioThresholdNotMet => dec!(0),
BoostedHexStatus::ServiceProviderBanned => dec!(0),
SpBoostedHexStatus::Eligible => self.coverage_points.boosted,
SpBoostedHexStatus::WifiLocationScoreBelowThreshold(_) => dec!(0),
SpBoostedHexStatus::AverageAssertedDistanceOverLimit(_) => dec!(0),
SpBoostedHexStatus::RadioThresholdNotMet => dec!(0),
SpBoostedHexStatus::ServiceProviderBanned => dec!(0),
}
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BoostedHexStatus {
pub enum OracleBoostingStatus {
Eligible,
Banned,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SpBoostedHexStatus {
Eligible,
WifiLocationScoreBelowThreshold(Decimal),
AverageAssertedDistanceOverLimit(Decimal),
RadioThresholdNotMet,
ServiceProviderBanned,
}

impl BoostedHexStatus {
impl SpBoostedHexStatus {
fn new(
radio_type: RadioType,
location_trust_multiplier: Decimal,
Expand Down Expand Up @@ -373,6 +390,7 @@ mod tests {
assignments: assignments_from(Assignment::C),
boosted: NonZeroU32::new(boost_multiplier),
}],
OracleBoostingStatus::Eligible,
)
.unwrap();

Expand All @@ -398,6 +416,7 @@ mod tests {
assignments: assignments_maximum(),
boosted: NonZeroU32::new(5),
}],
OracleBoostingStatus::Eligible,
)
.expect("indoor wifi with location scores")
};
Expand Down Expand Up @@ -434,6 +453,7 @@ mod tests {
assignments: assignments_maximum(),
boosted: NonZeroU32::new(5),
}],
OracleBoostingStatus::Eligible,
)
.expect("indoor wifi with location scores")
};
Expand Down Expand Up @@ -472,6 +492,7 @@ mod tests {
assignments: assignments_maximum(),
boosted: NonZeroU32::new(5),
}],
OracleBoostingStatus::Eligible,
)
.expect("indoor wifi with location scores")
};
Expand Down Expand Up @@ -508,6 +529,7 @@ mod tests {
assignments: assignments_maximum(),
boosted: None,
}],
OracleBoostingStatus::Eligible,
)
.expect("indoor cbrs with speedtests")
};
Expand Down Expand Up @@ -623,6 +645,7 @@ mod tests {
ranked_coverage(C, B, C), // 0
ranked_coverage(C, C, C), // 0
],
OracleBoostingStatus::Eligible,
)
.expect("indoor cbrs");

Expand Down Expand Up @@ -653,6 +676,7 @@ mod tests {
assignments: assignments_maximum(),
boosted: None,
}],
OracleBoostingStatus::Eligible,
)
.expect("outdoor wifi");

Expand Down Expand Up @@ -702,6 +726,7 @@ mod tests {
boosted: None,
},
],
OracleBoostingStatus::Eligible,
)
.expect("indoor wifi");

Expand All @@ -725,6 +750,7 @@ mod tests {
assignments: assignments_maximum(),
boosted: None,
}],
OracleBoostingStatus::Eligible,
)
.expect("indoor wifi");

Expand Down Expand Up @@ -761,6 +787,7 @@ mod tests {
speedtest_maximum(),
location_trust_maximum(),
covered_hexes.clone(),
OracleBoostingStatus::Eligible,
)
.expect("indoor wifi");

Expand Down Expand Up @@ -792,6 +819,7 @@ mod tests {
assignments: assignments_maximum(),
boosted: None,
}],
OracleBoostingStatus::Eligible,
)
.expect("outdoor cbrs");

Expand Down Expand Up @@ -819,6 +847,7 @@ mod tests {
assignments: assignments_maximum(),
boosted: None,
}],
OracleBoostingStatus::Eligible,
)
.expect("indoor cbrs");

Expand Down Expand Up @@ -848,6 +877,7 @@ mod tests {
assignments: assignments_maximum(),
boosted: None,
}],
OracleBoostingStatus::Eligible,
)
.expect("indoor cbrs");

Expand Down Expand Up @@ -875,6 +905,7 @@ mod tests {
assignments: assignments_maximum(),
boosted: None,
}],
OracleBoostingStatus::Eligible,
)
.expect("indoor wifi");

Expand All @@ -889,7 +920,7 @@ mod tests {
}];

let wifi_bad_trust_score = |sp_status: SPBoostedRewardEligibility| {
BoostedHexStatus::new(
SpBoostedHexStatus::new(
RadioType::IndoorWifi,
location::multiplier(RadioType::IndoorWifi, &bad_location),
&bad_location,
Expand All @@ -899,15 +930,15 @@ mod tests {

assert_eq!(
wifi_bad_trust_score(SPBoostedRewardEligibility::Eligible),
BoostedHexStatus::WifiLocationScoreBelowThreshold(dec!(0)),
SpBoostedHexStatus::WifiLocationScoreBelowThreshold(dec!(0)),
);
assert_eq!(
wifi_bad_trust_score(SPBoostedRewardEligibility::ServiceProviderBanned),
BoostedHexStatus::ServiceProviderBanned
SpBoostedHexStatus::ServiceProviderBanned
);
assert_eq!(
wifi_bad_trust_score(SPBoostedRewardEligibility::RadioThresholdNotMet),
BoostedHexStatus::RadioThresholdNotMet
SpBoostedHexStatus::RadioThresholdNotMet
);
}

Expand Down
Loading

0 comments on commit 2d6bd03

Please sign in to comment.