Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

verify asserted device type against wifi HB cell type #632

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,14 @@ sqlx = {version = "0", features = [
]}

helium-crypto = {version = "0.8.1", features=["sqlx-postgres", "multisig"]}
helium-proto = {git = "https://github.com/helium/proto", branch = "master", features = ["services"]}
helium-proto = {git = "https://github.com/helium/proto", branch = "andymck/verify-hb-cell-type", features = ["services"]}
hextree = "*"
solana-client = "1.14"
solana-sdk = "1.14"
solana-program = "1.11"
spl-token = "3.5.0"
reqwest = {version = "0", default-features=false, features = ["gzip", "json", "rustls-tls"]}
beacon = { git = "https://github.com/helium/proto", branch = "master" }
beacon = { git = "https://github.com/helium/proto", branch = "andymck/verify-hb-cell-type" }
humantime = "2"
metrics = "0"
metrics-exporter-prometheus = "0"
Expand Down
14 changes: 11 additions & 3 deletions mobile_config/src/gateway_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ use helium_crypto::PublicKeyBinary;
use helium_proto::services::mobile_config::{
GatewayInfo as GatewayInfoProto, GatewayMetadata as GatewayMetadataProto,
};

pub type GatewayInfoStream = BoxStream<'static, GatewayInfo>;

#[derive(Clone, Debug)]
pub struct GatewayMetadata {
pub location: u64,
pub device_type: String,
}

#[derive(Clone, Debug)]
Expand All @@ -33,11 +33,15 @@ impl From<GatewayInfoProto> for GatewayInfo {
fn from(info: GatewayInfoProto) -> Self {
let metadata = if let Some(metadata) = info.metadata {
u64::from_str_radix(&metadata.location, 16)
.map(|location| GatewayMetadata { location })
.map(|location| GatewayMetadata {
jeffgrunewald marked this conversation as resolved.
Show resolved Hide resolved
location,
device_type: metadata.device_type,
})
.ok()
} else {
None
};

Self {
address: info.address.into(),
metadata,
Expand All @@ -52,6 +56,7 @@ impl TryFrom<GatewayInfo> for GatewayInfoProto {
let metadata = if let Some(metadata) = info.metadata {
Some(GatewayMetadataProto {
location: hextree::Cell::from_raw(metadata.location)?.to_string(),
device_type: metadata.device_type,
})
} else {
None
Expand All @@ -67,11 +72,12 @@ pub(crate) mod db {
use super::{GatewayInfo, GatewayMetadata};
use futures::stream::{Stream, StreamExt};
use helium_crypto::PublicKeyBinary;
use sqlx::types::Json;
use sqlx::{PgExecutor, Row};
use std::str::FromStr;

const GET_METADATA_SQL: &str = r#"
select kta.entity_key, infos.location::bigint
select kta.entity_key, infos.location::bigint, infos.device_type
from mobile_hotspot_infos infos
join key_to_assets kta on infos.asset = kta.asset
"#;
Expand Down Expand Up @@ -102,10 +108,12 @@ pub(crate) mod db {

impl sqlx::FromRow<'_, sqlx::postgres::PgRow> for GatewayInfo {
fn from_row(row: &sqlx::postgres::PgRow) -> sqlx::Result<Self> {
let device_type = row.get::<Json<String>, &str>("device_type").to_string();
let metadata = row
.get::<Option<i64>, &str>("location")
.map(|loc| GatewayMetadata {
location: loc as u64,
device_type,
});
Ok(Self {
address: PublicKeyBinary::from_str(
Expand Down
16 changes: 14 additions & 2 deletions mobile_verifier/src/cell_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use helium_proto::services::poc_mobile::CellType as CellTypeProto;
use rust_decimal::Decimal;
use rust_decimal_macros::dec;
use serde::Serialize;
use std::str::FromStr;

pub const CELLTYPE_NOVA_436H: &str = "2AG32MBS3100196N";
pub const CELLTYPE_NOVA_430I: &str = "2AG32PBS3101S";
Expand All @@ -27,7 +28,7 @@ pub enum CellType {
pub enum CellTypeLabel {
CellTypeLabelNone = 0,
CBRS = 1,
Wifi = 2,
WifiIndoor = 2,
}

impl CellType {
Expand All @@ -50,7 +51,7 @@ impl CellType {
Self::SercommIndoor => CellTypeLabel::CBRS,
Self::SercommOutdoor => CellTypeLabel::CBRS,
Self::CellTypeNone => CellTypeLabel::CellTypeLabelNone,
Self::NovaGenericWifiIndoor => CellTypeLabel::Wifi,
Self::NovaGenericWifiIndoor => CellTypeLabel::WifiIndoor,
}
}

Expand Down Expand Up @@ -102,3 +103,14 @@ impl From<CellType> for CellTypeProto {
}
}
}

impl FromStr for CellTypeLabel {
type Err = anyhow::Error;
fn from_str(s: &str) -> anyhow::Result<CellTypeLabel> {
match s {
"wifiIndoor" => Ok(CellTypeLabel::WifiIndoor),
"cbrs" => Ok(CellTypeLabel::CBRS),
_ => anyhow::bail!("unknown cell type"),
}
}
}
16 changes: 11 additions & 5 deletions mobile_verifier/src/heartbeats/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use helium_proto::services::poc_mobile as proto;
use retainer::Cache;
use rust_decimal::{prelude::ToPrimitive, Decimal};
use sqlx::{postgres::PgTypeInfo, Decode, Encode, Postgres, Transaction, Type};
use std::{ops::Range, pin::pin, time};
use std::{ops::Range, pin::pin, str::FromStr, time};
use uuid::Uuid;

/// Minimum number of heartbeats required to give a reward to the hotspot.
Expand Down Expand Up @@ -247,7 +247,7 @@ impl HeartbeatReward {
.cbsd_id
.clone()
.ok_or_else(|| anyhow!("expected cbsd_id, found none"))?),
CellTypeLabel::Wifi => Ok(self.hotspot_key.to_string()),
CellTypeLabel::WifiIndoor => Ok(self.hotspot_key.to_string()),
_ => Err(anyhow!("failed to derive label from cell type")),
}
}
Expand Down Expand Up @@ -504,8 +504,15 @@ pub async fn validate_heartbeat(
proto::HeartbeatValidity::GatewayNotAsserted,
))
}
GatewayResolution::AssertedLocation(location) if heartbeat.hb_type == HbType::Wifi => {
Some(heartbeat.asserted_distance(location)?)
GatewayResolution::GatewayAsserted(metadata) if heartbeat.hb_type == HbType::Wifi => {
// for wifi HBs, check the asserted device type matches that defined in the HB
let asserted_celltype_label = CellTypeLabel::from_str(&metadata.device_type)?;
if asserted_celltype_label == CellTypeLabel::WifiIndoor
&& cell_type.to_label() != asserted_celltype_label
{
return Ok((cell_type, None, None, proto::HeartbeatValidity::BadCellType));
};
Some(heartbeat.asserted_distance(metadata.location)?)
}
_ => None,
};
Expand All @@ -529,7 +536,6 @@ pub async fn validate_heartbeat(

let Ok(latlng) = LatLng::new(heartbeat.report.lat, heartbeat.report.lon) else {
return Ok((cell_type, None, proto::HeartbeatValidity::InvalidLatLon));
};

if coverage.max_distance_km(latlng) > max_distance {
return Ok((
Expand Down
5 changes: 3 additions & 2 deletions mobile_verifier/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ pub use settings::Settings;

use async_trait::async_trait;

use mobile_config::gateway_info::GatewayMetadata;
pub enum GatewayResolution {
GatewayNotFound,
GatewayNotAsserted,
AssertedLocation(u64),
GatewayAsserted(GatewayMetadata),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does it make sense to include the entire metadata struct in the GatewayAsserted variant when it should have metadata to include the device type even if it's not asserted?

}

#[async_trait]
Expand All @@ -45,7 +46,7 @@ impl GatewayResolver for mobile_config::GatewayClient {
Some(GatewayInfo {
metadata: Some(metadata),
..
}) => Ok(GatewayResolution::AssertedLocation(metadata.location)),
}) => Ok(GatewayResolution::GatewayAsserted(metadata)),
Some(_) => Ok(GatewayResolution::GatewayNotAsserted),
}
}
Expand Down