From 9a82be55debc50f7b44b10d87b3fad5a5b911157 Mon Sep 17 00:00:00 2001 From: jeffgrunewald Date: Wed, 5 Apr 2023 02:35:11 -0400 Subject: [PATCH] swap iot config integrated client for previous standalone impl --- Cargo.lock | 25 +- Cargo.toml | 1 - iot_config_client/Cargo.toml | 22 -- iot_config_client/src/gateway_resolver.rs | 49 ---- iot_config_client/src/iot_config_client.rs | 116 --------- iot_config_client/src/lib.rs | 10 - .../src/region_params_resolver.rs | 43 ---- iot_config_client/src/settings.rs | 59 ----- iot_packet_verifier/src/verifier.rs | 2 + iot_verifier/Cargo.toml | 2 +- iot_verifier/src/gateway_cache.rs | 14 +- iot_verifier/src/main.rs | 2 +- iot_verifier/src/poc.rs | 235 +++++++++--------- iot_verifier/src/region_cache.rs | 5 +- iot_verifier/src/runner.rs | 3 +- iot_verifier/src/settings.rs | 2 +- iot_verifier/src/tx_scaler.rs | 11 +- 17 files changed, 139 insertions(+), 462 deletions(-) delete mode 100644 iot_config_client/Cargo.toml delete mode 100644 iot_config_client/src/gateway_resolver.rs delete mode 100644 iot_config_client/src/iot_config_client.rs delete mode 100644 iot_config_client/src/lib.rs delete mode 100644 iot_config_client/src/region_params_resolver.rs delete mode 100644 iot_config_client/src/settings.rs diff --git a/Cargo.lock b/Cargo.lock index 2f2062854..c79ac14ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1150,7 +1150,7 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "beacon" version = "0.1.0" -source = "git+https://github.com/helium/gateway-rs.git?branch=jg/temp-proto-upgrade#fb45c4ddcc54c2ba81d6d718ae762871be65af79" +source = "git+https://github.com/helium/gateway-rs.git?branch=jg/temp-proto-upgrade#0d801e3ee93859c1f8f8ad986647a2ffbcb8bd56" dependencies = [ "base64 0.21.0", "byteorder", @@ -3003,7 +3003,7 @@ dependencies = [ [[package]] name = "helium-proto" version = "0.1.0" -source = "git+https://github.com/helium/proto?branch=jg/oracle-admin-keys#82cb014441f08e136c6559f23d294d93039f24b4" +source = "git+https://github.com/helium/proto?branch=jg/oracle-admin-keys#f4301b91519cc802e4fa98f842e296a7a64d1467" dependencies = [ "bytes", "prost", @@ -3391,25 +3391,6 @@ dependencies = [ "triggered", ] -[[package]] -name = "iot-config-client" -version = "0.1.0" -dependencies = [ - "anyhow", - "async-trait", - "beacon", - "futures", - "helium-crypto", - "helium-proto", - "http", - "http-serde", - "rand 0.8.5", - "retainer", - "serde", - "thiserror", - "tonic", -] - [[package]] name = "iot-packet-verifier" version = "0.1.0" @@ -3473,7 +3454,7 @@ dependencies = [ "helium-proto", "http-serde", "humantime", - "iot-config-client", + "iot-config", "itertools", "lazy_static", "metrics", diff --git a/Cargo.toml b/Cargo.toml index 1b2146597..23688e1c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,6 @@ members = [ "iot_packet_verifier", "iot_config", "price", - "iot_config_client" ] [workspace.package] diff --git a/iot_config_client/Cargo.toml b/iot_config_client/Cargo.toml deleted file mode 100644 index 5b784226c..000000000 --- a/iot_config_client/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "iot-config-client" -version = "0.1.0" -description = "Client for IOT Config" -edition.workspace = true -authors.workspace = true -license.workspace = true - -[dependencies] -anyhow = {workspace = true} -futures = {workspace = true} -serde = {workspace = true} -http-serde = {workspace = true} -thiserror = {workspace = true} -beacon = {workspace = true} -helium-proto = { workspace = true } -helium-crypto = { workspace = true } -http = {workspace = true} -tonic = {workspace = true} -retainer = {workspace = true} -async-trait = {workspace = true} -rand = {workspace = true} diff --git a/iot_config_client/src/gateway_resolver.rs b/iot_config_client/src/gateway_resolver.rs deleted file mode 100644 index 0f6bb1e73..000000000 --- a/iot_config_client/src/gateway_resolver.rs +++ /dev/null @@ -1,49 +0,0 @@ -use crate::iot_config_client::IotConfigClientError; -use async_trait::async_trait; -use helium_crypto::PublicKeyBinary; -use helium_proto::{services::iot_config::GatewayInfo as GatewayInfoProto, Region}; - -#[async_trait] -pub trait GatewayInfoResolver { - async fn resolve_gateway_info( - &mut self, - address: &PublicKeyBinary, - ) -> Result; -} - -#[derive(Debug, Clone)] -pub struct GatewayInfo { - pub address: PublicKeyBinary, - pub location: Option, - pub elevation: Option, - pub gain: i32, - pub is_full_hotspot: bool, - pub region: Region, -} - -#[derive(Debug, thiserror::Error)] -pub enum GatewayResolverError { - #[error("unsupported region {0}")] - Region(String), -} - -impl TryFrom for GatewayInfo { - type Error = GatewayResolverError; - fn try_from(v: GatewayInfoProto) -> Result { - let region: Region = Region::from_i32(v.region) - .ok_or_else(|| GatewayResolverError::Region(format!("{:?}", v.region)))?; - let location = u64::from_str_radix(&v.location, 16).ok(); - let elevation = match location { - Some(_) => Some(v.elevation), - None => None, - }; - Ok(Self { - address: v.address.into(), - location, - elevation, - gain: v.gain, - is_full_hotspot: v.is_full_hotspot, - region, - }) - } -} diff --git a/iot_config_client/src/iot_config_client.rs b/iot_config_client/src/iot_config_client.rs deleted file mode 100644 index 7975f0cb4..000000000 --- a/iot_config_client/src/iot_config_client.rs +++ /dev/null @@ -1,116 +0,0 @@ -use crate::{ - gateway_resolver::{self, GatewayInfo, GatewayInfoResolver}, - region_params_resolver::{self, RegionParamsInfo, RegionParamsResolver}, - GatewayInfoStream, Settings, -}; -use anyhow::Result; -use futures::stream::{self, StreamExt}; -use helium_crypto::{Keypair, PublicKeyBinary, Sign}; -use helium_proto::services::{ - iot_config::{self, GatewayInfoReqV1, GatewayInfoStreamReqV1, RegionParamsReqV1}, - Channel, -}; -use helium_proto::{Message, Region}; -use std::sync::Arc; - -type IotGatewayConfigClient = iot_config::GatewayClient; -type IotAdminConfigClient = iot_config::admin_client::AdminClient; - -#[derive(Debug, Clone)] -pub struct IotConfigClient { - keypair: Arc, - pub gateway_client: IotGatewayConfigClient, - pub region_client: IotAdminConfigClient, - batch_size: u32, -} - -#[derive(Debug, thiserror::Error)] -pub enum IotConfigClientError { - #[error("error resolving gateway info")] - GatewayResolverError(#[from] gateway_resolver::GatewayResolverError), - #[error("error resolving region params")] - RegionParamsResolverError(#[from] region_params_resolver::RegionParamsResolverError), - #[error("gateway not found: {0}")] - GatewayNotFound(PublicKeyBinary), - #[error("region params not found {0}")] - RegionParamsNotFound(String), - #[error("uri error")] - Uri(#[from] http::uri::InvalidUri), - #[error("grpc {}", .0.message())] - Grpc(#[from] tonic::Status), - #[error("keypair error: {0}")] - KeypairError(#[from] Box), - #[error("signing error: {0}")] - SignError(#[from] helium_crypto::Error), -} - -#[async_trait::async_trait] -impl GatewayInfoResolver for IotConfigClient { - async fn resolve_gateway_info( - &mut self, - address: &PublicKeyBinary, - ) -> Result { - let mut req = GatewayInfoReqV1 { - address: address.clone().into(), - signature: vec![], - }; - req.signature = self.keypair.sign(&req.encode_to_vec())?; - let res = self.gateway_client.info(req).await?.into_inner(); - match res.info { - Some(gateway_info) => Ok(gateway_info.try_into()?), - _ => Err(IotConfigClientError::GatewayNotFound(address.clone())), - } - } -} - -#[async_trait::async_trait] -impl RegionParamsResolver for IotConfigClient { - async fn resolve_region_params( - &mut self, - region: Region, - ) -> Result { - let mut req = RegionParamsReqV1 { - region: region.into(), - signature: vec![], - }; - req.signature = self.keypair.sign(&req.encode_to_vec())?; - match self.region_client.region_params(req).await { - Ok(region_params_info) => Ok(region_params_info.into_inner().try_into()?), - _ => Err(IotConfigClientError::RegionParamsNotFound(format!( - "{region:?}" - ))), - } - } -} - -impl IotConfigClient { - pub fn from_settings(settings: &Settings) -> Result { - let channel = settings.connect_endpoint(); - let keypair = settings.keypair()?; - Ok(Self { - keypair: Arc::new(keypair), - gateway_client: settings.connect_iot_gateway_config(channel.clone()), - region_client: settings.connect_iot_region_config(channel), - batch_size: settings.batch, - }) - } - - pub async fn gateway_stream(&mut self) -> Result { - let mut req = GatewayInfoStreamReqV1 { - batch_size: self.batch_size, - signature: vec![], - }; - req.signature = self.keypair.sign(&req.encode_to_vec())?; - let gw_stream = self - .gateway_client - .info_stream(req) - .await? - .into_inner() - .filter_map(|resp| async move { resp.ok() }) - .flat_map(|resp| stream::iter(resp.gateways.into_iter())) - .filter_map(|resp| async move { GatewayInfo::try_from(resp).ok() }) - .boxed(); - - Ok(gw_stream) - } -} diff --git a/iot_config_client/src/lib.rs b/iot_config_client/src/lib.rs deleted file mode 100644 index 20d9ae4f7..000000000 --- a/iot_config_client/src/lib.rs +++ /dev/null @@ -1,10 +0,0 @@ -pub mod gateway_resolver; -pub mod iot_config_client; -pub mod region_params_resolver; -mod settings; - -use futures::stream::BoxStream; -pub use settings::Settings; - -pub type Stream = BoxStream<'static, T>; -pub type GatewayInfoStream = Stream; diff --git a/iot_config_client/src/region_params_resolver.rs b/iot_config_client/src/region_params_resolver.rs deleted file mode 100644 index 4f8857dbf..000000000 --- a/iot_config_client/src/region_params_resolver.rs +++ /dev/null @@ -1,43 +0,0 @@ -use crate::iot_config_client::IotConfigClientError; -use async_trait::async_trait; -use helium_proto::{ - services::iot_config::RegionParamsResV1 as RegionParamsProto, BlockchainRegionParamV1, Region, -}; - -#[async_trait] -pub trait RegionParamsResolver { - async fn resolve_region_params( - &mut self, - region: Region, - ) -> Result; -} - -#[derive(Debug, Clone)] -pub struct RegionParamsInfo { - pub region: Region, - pub region_params: Vec, -} - -#[derive(Debug, thiserror::Error)] -pub enum RegionParamsResolverError { - #[error("unsupported region {0}")] - Region(String), -} - -impl TryFrom for RegionParamsInfo { - type Error = RegionParamsResolverError; - fn try_from(v: RegionParamsProto) -> Result { - let region: Region = Region::from_i32(v.region) - .ok_or_else(|| RegionParamsResolverError::Region(format!("{:?}", v.region)))?; - let region_params = v - .params - .ok_or_else(|| { - RegionParamsResolverError::Region("failed to get region params".to_string()) - })? - .region_params; - Ok(Self { - region, - region_params, - }) - } -} diff --git a/iot_config_client/src/settings.rs b/iot_config_client/src/settings.rs deleted file mode 100644 index 32ce51b25..000000000 --- a/iot_config_client/src/settings.rs +++ /dev/null @@ -1,59 +0,0 @@ -use helium_proto::services::{iot_config, Channel, Endpoint}; -use serde::Deserialize; -use std::time::Duration; - -#[derive(Debug, Deserialize, Clone)] -pub struct Settings { - /// signing key used to sign requests to iot config service - pub keypair: String, - /// uri to iot config service - #[serde(with = "http_serde::uri")] - pub url: http::Uri, - /// Connect timeout in seconds. Default 5 - #[serde(default = "default_connect_timeout")] - pub connect: u64, - /// RPC timeout in seconds. Default 5 - #[serde(default = "default_rpc_timeout")] - pub rpc: u64, - /// batch size for gateway stream results. Default 100 - #[serde(default = "default_batch_size")] - pub batch: u32, -} - -pub fn default_connect_timeout() -> u64 { - 5 -} - -pub fn default_rpc_timeout() -> u64 { - 5 -} - -pub fn default_batch_size() -> u32 { - 100 -} - -impl Settings { - pub fn connect_endpoint(&self) -> Channel { - Endpoint::from(self.url.clone()) - .connect_timeout(Duration::from_secs(self.connect)) - .timeout(Duration::from_secs(self.rpc)) - .connect_lazy() - } - - pub fn connect_iot_gateway_config( - &self, - channel: Channel, - ) -> iot_config::GatewayClient { - iot_config::GatewayClient::new(channel) - } - pub fn connect_iot_region_config( - &self, - channel: Channel, - ) -> iot_config::admin_client::AdminClient { - iot_config::admin_client::AdminClient::new(channel) - } - pub fn keypair(&self) -> Result> { - let data = std::fs::read(&self.keypair).map_err(helium_crypto::Error::from)?; - Ok(helium_crypto::Keypair::try_from(&data[..])?) - } -} diff --git a/iot_packet_verifier/src/verifier.rs b/iot_packet_verifier/src/verifier.rs index e2a85084b..45e01395a 100644 --- a/iot_packet_verifier/src/verifier.rs +++ b/iot_packet_verifier/src/verifier.rs @@ -201,6 +201,7 @@ impl ConfigServer for CachedOrgClient { let mut req = OrgEnableReqV1 { oui, timestamp: Utc::now().timestamp_millis() as u64, + signer: self.keypair.public_key().into(), signature: vec![], }; let signature = self.keypair.sign(&req.encode_to_vec())?; @@ -215,6 +216,7 @@ impl ConfigServer for CachedOrgClient { let mut req = OrgDisableReqV1 { oui, timestamp: Utc::now().timestamp_millis() as u64, + signer: self.keypair.public_key().into(), signature: vec![], }; let signature = self.keypair.sign(&req.encode_to_vec())?; diff --git a/iot_verifier/Cargo.toml b/iot_verifier/Cargo.toml index 009b68ad3..2b37dd09a 100644 --- a/iot_verifier/Cargo.toml +++ b/iot_verifier/Cargo.toml @@ -42,7 +42,7 @@ file-store = { path = "../file_store" } metrics = {workspace = true} retainer = {workspace = true} blake3 = {workspace = true} -iot-config-client = { path = "../iot_config_client" } +iot-config = { path = "../iot_config" } poc-metrics = { path = "../metrics" } db-store = {path = "../db_store"} denylist = {path = "../denylist"} diff --git a/iot_verifier/src/gateway_cache.rs b/iot_verifier/src/gateway_cache.rs index 4f42e990b..2a7eec33c 100644 --- a/iot_verifier/src/gateway_cache.rs +++ b/iot_verifier/src/gateway_cache.rs @@ -1,8 +1,8 @@ use futures::stream::StreamExt; use helium_crypto::PublicKeyBinary; -use iot_config_client::{ - gateway_resolver::{GatewayInfo, GatewayInfoResolver}, - iot_config_client::{IotConfigClient, IotConfigClientError}, +use iot_config::{ + client::{Client as IotConfigClient, ClientError as IotConfigClientError}, + gateway_info::{GatewayInfo, GatewayInfoResolver}, }; use retainer::Cache; use std::{sync::Arc, time::Duration}; @@ -43,7 +43,11 @@ impl GatewayCache { pub async fn prewarm(&self) -> anyhow::Result<()> { tracing::info!("starting prewarming gateway cache"); - let mut gw_stream = self.iot_config_client.clone().gateway_stream().await?; + let mut gw_stream = self + .iot_config_client + .clone() + .stream_gateways_info() + .await?; while let Some(gateway_info) = gw_stream.next().await { _ = self.insert(gateway_info).await; } @@ -67,7 +71,7 @@ impl GatewayCache { .resolve_gateway_info(address) .await { - Ok(res) => { + Ok(Some(res)) => { tracing::debug!("cache miss: {:?}", address); metrics::increment_counter!("oracles_iot_verifier_gateway_cache_miss"); _ = self.insert(res.clone()).await; diff --git a/iot_verifier/src/main.rs b/iot_verifier/src/main.rs index 51f937231..5793a3717 100644 --- a/iot_verifier/src/main.rs +++ b/iot_verifier/src/main.rs @@ -6,7 +6,7 @@ use file_store::{ file_upload, iot_packet::IotValidPacket, FileStore, FileType, }; use futures::TryFutureExt; -use iot_config_client::iot_config_client::IotConfigClient; +use iot_config::client::Client as IotConfigClient; use iot_verifier::{ entropy_loader, gateway_cache::GatewayCache, loader, metrics::Metrics, packet_loader, poc_report::Report, purger, region_cache::RegionCache, rewarder::Rewarder, runner, diff --git a/iot_verifier/src/poc.rs b/iot_verifier/src/poc.rs index c37dcf3ba..ce1b406ea 100644 --- a/iot_verifier/src/poc.rs +++ b/iot_verifier/src/poc.rs @@ -20,7 +20,7 @@ use helium_proto::{ services::poc_lora::{InvalidParticipantSide, InvalidReason, VerificationStatus}, BlockchainRegionParamV1, Region as ProtoRegion, }; -use iot_config_client::gateway_resolver::GatewayInfo; +use iot_config::gateway_info::{GatewayInfo, GatewayMetadata}; use lazy_static::lazy_static; use rust_decimal::Decimal; use sqlx::PgPool; @@ -111,20 +111,31 @@ impl Poc { // it not available then declare beacon invalid let beaconer_info = match gateway_cache.resolve_gateway_info(&beaconer_pub_key).await { Ok(res) => res, - Err(_e) => { + Err(_err) => { return Ok(VerifyBeaconResult::gateway_not_found()); } }; - let beaconer_region_info = - match region_cache.resolve_region_info(beaconer_info.region).await { - Ok(res) => res, - Err(_e) => { - return Ok(VerifyBeaconResult::invalid( - InvalidReason::InvalidRegion, - beaconer_info, - )); - } - }; + let beaconer_metadata = match beaconer_info.metadata { + Some(ref metadata) => metadata, + None => { + return Ok(VerifyBeaconResult::invalid( + InvalidReason::NotAsserted, + beaconer_info, + )) + } + }; + let beaconer_region_info = match region_cache + .resolve_region_info(beaconer_metadata.region) + .await + { + Ok(res) => res, + Err(_e) => { + return Ok(VerifyBeaconResult::invalid( + InvalidReason::InvalidRegion, + beaconer_info, + )); + } + }; // we have beaconer info, proceed to verifications let last_beacon = LastBeacon::get(pool, beaconer_pub_key.as_ref()).await?; match do_beacon_verifications( @@ -139,12 +150,8 @@ impl Poc { beacon_interval_tolerance, ) { Ok(()) => { - let beaconer_location = beaconer_info - .location - .ok_or(VerificationError::NotFound("invalid beaconer_location"))?; - let tx_scale = hex_density_map - .get(beaconer_location) + .get(beaconer_metadata.location) .await .unwrap_or(*DEFAULT_TX_SCALE); Ok(VerifyBeaconResult::valid(beaconer_info, tx_scale)) @@ -226,6 +233,29 @@ impl Poc { )) } }; + let witness_metadata = match witness_info.metadata { + Some(ref metadata) => metadata, + None => { + return Ok(IotVerifiedWitnessReport::invalid( + InvalidReason::NotAsserted, + &witness_report.report, + witness_report.received_timestamp, + None, + InvalidParticipantSide::Witness, + )) + } + }; + // to avoid assuming beaconer location is set and to avoid unwrap + // we explicity match location here again + let Some(ref beaconer_metadata) = beaconer_info.metadata else { + return Ok(IotVerifiedWitnessReport::invalid( + InvalidReason::NotAsserted, + &witness_report.report, + witness_report.received_timestamp, + None, + InvalidParticipantSide::Beaconer, + )) + }; // run the witness verifications match do_witness_verifications( self.entropy_start, @@ -233,29 +263,17 @@ impl Poc { witness_report, &witness_info, &self.beacon_report, - beaconer_info, + beaconer_metadata, ) { Ok(()) => { - // to avoid assuming beaconer location is set and to avoid unwrap - // we explicity match location here again - let Some(beaconer_location) = beaconer_info.location else { - return Ok(IotVerifiedWitnessReport::invalid( - InvalidReason::NotAsserted, - &witness_report.report, - witness_report.received_timestamp, - None, - InvalidParticipantSide::Beaconer, - )) - }; - let tx_scale = hex_density_map - .get(beaconer_location) + .get(beaconer_metadata.location) .await .unwrap_or(*DEFAULT_TX_SCALE); Ok(IotVerifiedWitnessReport::valid( &witness_report.report, witness_report.received_timestamp, - witness_info.location, + Some(witness_metadata.location), tx_scale, )) } @@ -287,8 +305,11 @@ pub fn do_beacon_verifications( beaconer_info.address.clone() ); let beacon_received_ts = beacon_report.received_timestamp; + let beaconer_metadata = match beaconer_info.metadata { + Some(ref metadata) => metadata, + None => return Err(InvalidReason::NotAsserted), + }; verify_entropy(entropy_start, entropy_end, beacon_received_ts)?; - verify_gw_location(beaconer_info.location)?; verify_gw_capability(beaconer_info.is_full_hotspot)?; verify_beacon_schedule( &last_beacon, @@ -298,9 +319,9 @@ pub fn do_beacon_verifications( )?; verify_beacon_payload( &beacon_report.report, - beaconer_info.region, + beaconer_metadata.region, beaconer_region_params, - beaconer_info.gain, + beaconer_metadata.gain, entropy_start, entropy_version as u32, )?; @@ -317,13 +338,17 @@ pub fn do_witness_verifications( witness_report: &IotWitnessIngestReport, witness_info: &GatewayInfo, beacon_report: &IotBeaconIngestReport, - beaconer_info: &GatewayInfo, + beaconer_metadata: &GatewayMetadata, ) -> GenericVerifyResult { tracing::debug!( "verifying witness from gateway: {:?}", witness_info.address.clone() ); let beacon_report = &beacon_report; + let witness_metadata = match witness_info.metadata { + Some(ref metadata) => metadata, + None => return Err(InvalidReason::NotAsserted), + }; verify_self_witness( &beacon_report.report.pub_key, &witness_report.report.pub_key, @@ -334,23 +359,22 @@ pub fn do_witness_verifications( witness_report.received_timestamp, )?; verify_witness_data(&beacon_report.report.data, &witness_report.report.data)?; - verify_gw_location(witness_info.location)?; verify_gw_capability(witness_info.is_full_hotspot)?; verify_witness_freq( beacon_report.report.frequency, witness_report.report.frequency, )?; - verify_witness_region(beaconer_info.region, witness_info.region)?; - verify_witness_cell_distance(beaconer_info.location, witness_info.location)?; - verify_witness_distance(beaconer_info.location, witness_info.location)?; + verify_witness_region(beaconer_metadata.region, witness_metadata.region)?; + verify_witness_cell_distance(beaconer_metadata.location, witness_metadata.location)?; + verify_witness_distance(beaconer_metadata.location, witness_metadata.location)?; verify_witness_rssi( witness_report.report.signal, witness_report.report.frequency, beacon_report.report.tx_power, - beaconer_info.gain, - witness_info.gain, - beaconer_info.location, - witness_info.location, + beaconer_metadata.gain, + witness_metadata.gain, + beaconer_metadata.location, + witness_metadata.location, )?; tracing::debug!( "valid witness from gateway: {:?}", @@ -472,21 +496,6 @@ fn verify_beacon_payload( Ok(()) } -/// verify gateway has an asserted location -fn verify_gw_location(gateway_loc: Option) -> GenericVerifyResult { - match gateway_loc { - Some(location) => location, - None => { - tracing::debug!( - "beacon verification failed, reason: {:?}", - InvalidReason::NotAsserted - ); - return Err(InvalidReason::NotAsserted); - } - }; - Ok(()) -} - /// verify gateway is permitted to participate in POC fn verify_gw_capability(is_full_hotspot: bool) -> GenericVerifyResult { if !is_full_hotspot { @@ -544,17 +553,8 @@ fn verify_witness_region( } /// verify witness does not exceed max distance from beaconer -fn verify_witness_distance( - beacon_loc: Option, - witness_loc: Option, -) -> GenericVerifyResult { - // other verifications handle location checks but dont assume - // we have a valid location passed in here - // if no location for either beaconer or witness then default - // this verification to a fail - let l1 = beacon_loc.ok_or(InvalidReason::MaxDistanceExceeded)?; - let l2 = witness_loc.ok_or(InvalidReason::MaxDistanceExceeded)?; - let witness_distance = match calc_distance(l1, l2) { +fn verify_witness_distance(beacon_loc: u64, witness_loc: u64) -> GenericVerifyResult { + let witness_distance = match calc_distance(beacon_loc, witness_loc) { Ok(d) => d, Err(_) => return Err(InvalidReason::MaxDistanceExceeded), }; @@ -569,17 +569,8 @@ fn verify_witness_distance( } /// verify min hex distance between beaconer and witness -fn verify_witness_cell_distance( - beacon_loc: Option, - witness_loc: Option, -) -> GenericVerifyResult { - // other verifications handle location checks but dont assume - // we have a valid location passed in here - // if no location for either beaconer or witness then default - // this verification to a fail - let l1 = beacon_loc.ok_or(InvalidReason::BelowMinDistance)?; - let l2 = witness_loc.ok_or(InvalidReason::BelowMinDistance)?; - let cell_distance = match calc_cell_distance(l1, l2) { +fn verify_witness_cell_distance(beacon_loc: u64, witness_loc: u64) -> GenericVerifyResult { + let cell_distance = match calc_cell_distance(beacon_loc, witness_loc) { Ok(d) => d, Err(_) => return Err(InvalidReason::BelowMinDistance), }; @@ -600,17 +591,10 @@ fn verify_witness_rssi( beacon_tx_power: i32, beacon_gain: i32, witness_gain: i32, - beacon_loc: Option, - witness_loc: Option, + beacon_loc: u64, + witness_loc: u64, ) -> GenericVerifyResult { - // other verifications handle location checks but dont assume - // we have a valid location passed in here - // if no location for either beaconer or witness or - // distance between the two cannot be determined - // then default this verification to a fail - let l1 = beacon_loc.ok_or(InvalidReason::BadRssi)?; - let l2 = witness_loc.ok_or(InvalidReason::BadRssi)?; - let distance = match calc_distance(l1, l2) { + let distance = match calc_distance(beacon_loc, witness_loc) { Ok(d) => d, Err(_) => return Err(InvalidReason::BadRssi), }; @@ -1008,12 +992,6 @@ mod tests { ); } - #[test] - fn test_verify_location() { - assert!(verify_gw_location(Some(LOC1)).is_ok()); - assert_eq!(Err(InvalidReason::NotAsserted), verify_gw_location(None)); - } - #[test] fn test_verify_capability() { assert!(verify_gw_capability(true).is_ok()); @@ -1070,10 +1048,10 @@ mod tests { let beacon_loc = LOC0; let witness1_loc = LOC1; let witness2_loc = LOC2; - assert!(verify_witness_distance(Some(beacon_loc), Some(witness1_loc)).is_ok()); + assert!(verify_witness_distance(beacon_loc, witness1_loc).is_ok()); assert_eq!( Err(InvalidReason::MaxDistanceExceeded), - verify_witness_distance(Some(beacon_loc), Some(witness2_loc)) + verify_witness_distance(beacon_loc, witness2_loc) ); } @@ -1086,10 +1064,10 @@ mod tests { // witness 1 location is 7 cells from the beaconer and thus invalid assert_eq!( Err(InvalidReason::BelowMinDistance), - verify_witness_cell_distance(Some(beacon_loc), Some(witness1_loc)) + verify_witness_cell_distance(beacon_loc, witness1_loc) ); // witness 2's location is 28 cells from the beaconer and thus valid - assert!(verify_witness_cell_distance(Some(beacon_loc), Some(witness2_loc)).is_ok()); + assert!(verify_witness_cell_distance(beacon_loc, witness2_loc).is_ok()); } #[test] @@ -1109,8 +1087,8 @@ mod tests { beacon1_tx_power, beacon1_gain, witness1_gain, - Some(beacon_loc), - Some(witness1_loc), + beacon_loc, + witness1_loc, ) .is_ok()); let beacon2_tx_power = 27; @@ -1126,8 +1104,8 @@ mod tests { beacon2_tx_power, beacon2_gain, witness2_gain, - Some(beacon_loc), - Some(witness2_loc), + beacon_loc, + witness2_loc, ) ); } @@ -1271,6 +1249,9 @@ mod tests { // create default data structs let beacon_report = valid_beacon_report(Utc::now() - Duration::minutes(2)); let beaconer_info = beaconer_gateway_info(Some(LOC0), ProtoRegion::Eu868, true); + let beaconer_metadata = beaconer_info + .metadata + .expect("beaconer should have metadata"); let witness_info = witness_gateway_info(Some(LOC4), ProtoRegion::Eu868, true); let entropy_start = Utc.timestamp_millis_opt(1676381847900).unwrap(); let entropy_end = entropy_start + Duration::minutes(3); @@ -1283,7 +1264,7 @@ mod tests { &witness_report1, &witness_info, &beacon_report, - &beaconer_info, + &beaconer_metadata, ); assert_eq!(Err(InvalidReason::SelfWitness), resp1); @@ -1295,7 +1276,7 @@ mod tests { &witness_report2, &witness_info, &beacon_report, - &beaconer_info, + &beaconer_metadata, ); assert_eq!(Err(InvalidReason::EntropyExpired), resp2); @@ -1307,7 +1288,7 @@ mod tests { &witness_report3, &witness_info, &beacon_report, - &beaconer_info, + &beaconer_metadata, ); assert_eq!(Err(InvalidReason::InvalidPacket), resp3); @@ -1320,7 +1301,7 @@ mod tests { &witness_report4, &witness_info4, &beacon_report, - &beaconer_info, + &beaconer_metadata, ); assert_eq!(Err(InvalidReason::NotAsserted), resp4); @@ -1332,7 +1313,7 @@ mod tests { &witness_report5, &witness_info, &beacon_report, - &beaconer_info, + &beaconer_metadata, ); assert_eq!(Err(InvalidReason::InvalidFrequency), resp5); @@ -1345,7 +1326,7 @@ mod tests { &witness_report6, &witness_info6, &beacon_report, - &beaconer_info, + &beaconer_metadata, ); assert_eq!(Err(InvalidReason::InvalidRegion), resp6); @@ -1358,7 +1339,7 @@ mod tests { &witness_report7, &witness_info7, &beacon_report, - &beaconer_info, + &beaconer_metadata, ); assert_eq!(Err(InvalidReason::BelowMinDistance), resp7); @@ -1371,7 +1352,7 @@ mod tests { &witness_report8, &witness_info8, &beacon_report, - &beaconer_info, + &beaconer_metadata, ); assert_eq!(Err(InvalidReason::MaxDistanceExceeded), resp8); @@ -1383,7 +1364,7 @@ mod tests { &witness_report9, &witness_info, &beacon_report, - &beaconer_info, + &beaconer_metadata, ); assert_eq!(Err(InvalidReason::BadRssi), resp9); @@ -1396,7 +1377,7 @@ mod tests { &witness_report10, &witness_info10, &beacon_report, - &beaconer_info, + &beaconer_metadata, ); assert_eq!(Err(InvalidReason::InvalidCapability), resp10); @@ -1409,7 +1390,7 @@ mod tests { &witness_report11, &witness_info11, &beacon_report, - &beaconer_info, + &beaconer_metadata, ); assert_eq!(Ok(()), resp11); } @@ -1419,13 +1400,16 @@ mod tests { region: ProtoRegion, is_full_hotspot: bool, ) -> GatewayInfo { - GatewayInfo { + let metadata = location.map(|location| GatewayMetadata { location, - address: PublicKeyBinary::from_str(PUBKEY1).unwrap(), - is_full_hotspot, gain: 12, - elevation: Some(100), + elevation: 100, region, + }); + GatewayInfo { + address: PublicKeyBinary::from_str(PUBKEY1).unwrap(), + is_full_hotspot, + metadata, } } @@ -1434,13 +1418,16 @@ mod tests { region: ProtoRegion, is_full_hotspot: bool, ) -> GatewayInfo { - GatewayInfo { + let metadata = location.map(|location| GatewayMetadata { location, - address: PublicKeyBinary::from_str(PUBKEY2).unwrap(), - is_full_hotspot, gain: 20, - elevation: Some(100), + elevation: 100, region, + }); + GatewayInfo { + address: PublicKeyBinary::from_str(PUBKEY2).unwrap(), + is_full_hotspot, + metadata, } } diff --git a/iot_verifier/src/region_cache.rs b/iot_verifier/src/region_cache.rs index 6ed8854b8..f891953e8 100644 --- a/iot_verifier/src/region_cache.rs +++ b/iot_verifier/src/region_cache.rs @@ -1,8 +1,7 @@ use helium_crypto::PublicKeyBinary; use helium_proto::Region as ProtoRegion; -use iot_config_client::{ - iot_config_client::{IotConfigClient, IotConfigClientError}, - region_params_resolver::{RegionParamsInfo, RegionParamsResolver}, +use iot_config::client::{ + Client as IotConfigClient, ClientError as IotConfigClientError, RegionParamsInfo, }; use retainer::Cache; use std::time::Duration; diff --git a/iot_verifier/src/runner.rs b/iot_verifier/src/runner.rs index bd03c581a..2337b2a64 100644 --- a/iot_verifier/src/runner.rs +++ b/iot_verifier/src/runner.rs @@ -333,9 +333,10 @@ impl Runner { VerificationStatus::Invalid => witness.reward_unit = Decimal::ZERO, }); + let location = beacon_info.metadata.map(|metadata| metadata.location); let valid_beacon_report = IotValidBeaconReport { received_timestamp: beacon_received_ts, - location: beacon_info.location, + location, hex_scale: beacon_verify_result .hex_scale .ok_or(RunnerError::NotFound("invalid hex scaling factor"))?, diff --git a/iot_verifier/src/settings.rs b/iot_verifier/src/settings.rs index 3db6917e8..679f53217 100644 --- a/iot_verifier/src/settings.rs +++ b/iot_verifier/src/settings.rs @@ -19,7 +19,7 @@ pub struct Settings { #[serde(default = "default_base_stale_period")] pub base_stale_period: i64, pub database: db_store::Settings, - pub iot_config_client: iot_config_client::Settings, + pub iot_config_client: iot_config::client::Settings, pub ingest: file_store::Settings, pub packet_ingest: file_store::Settings, diff --git a/iot_verifier/src/tx_scaler.rs b/iot_verifier/src/tx_scaler.rs index ce268fa65..b93ab9035 100644 --- a/iot_verifier/src/tx_scaler.rs +++ b/iot_verifier/src/tx_scaler.rs @@ -5,7 +5,10 @@ use crate::{ }; use chrono::{DateTime, Duration, Utc}; use futures::stream::StreamExt; -use iot_config_client::iot_config_client::{IotConfigClient, IotConfigClientError}; +use iot_config::{ + client::{Client as IotConfigClient, ClientError as IotConfigClientError}, + gateway_info::GatewayInfoResolver, +}; use sqlx::PgPool; use std::collections::HashMap; @@ -84,11 +87,11 @@ impl Server { .gateways_recent_activity(refresh_start) .await .map_err(sqlx::Error::from)?; - let mut gw_stream = self.iot_config_client.gateway_stream().await?; + let mut gw_stream = self.iot_config_client.stream_gateways_info().await?; while let Some(gateway_info) = gw_stream.next().await { - if let Some(h3index) = gateway_info.location { + if let Some(metadata) = gateway_info.metadata { if active_gateways.contains_key(&gateway_info.address.as_ref().to_vec()) { - global_map.increment_unclipped(h3index) + global_map.increment_unclipped(metadata.location) } } }