diff --git a/boost_manager/tests/activator_tests.rs b/boost_manager/tests/activator_tests.rs index 5c8d1603f..34dff1310 100644 --- a/boost_manager/tests/activator_tests.rs +++ b/boost_manager/tests/activator_tests.rs @@ -5,7 +5,7 @@ use helium_proto::services::poc_mobile::BoostedHex as BoostedHexProto; use mobile_config::boosted_hex_info::{BoostedHexInfo, BoostedHexes}; use solana_sdk::pubkey::Pubkey; use sqlx::PgPool; -use std::{collections::HashMap, str::FromStr}; +use std::{collections::HashMap, num::NonZeroU32, str::FromStr}; const BOOST_HEX_PUBKEY: &str = "J9JiLTpjaShxL8eMvUs8txVw6TZ36E38SiJ89NxnMbLU"; const BOOST_CONFIG_PUBKEY: &str = "BZM1QTud72B2cpTW7PhEnFmRX7ZWzvY7DpPpNJJuDrWG"; @@ -20,13 +20,27 @@ impl TestContext { let boost_period_length = Duration::days(30); // setup boosted hex data to stream as updates - let multipliers1 = vec![2, 10, 15, 35]; + let multipliers1 = vec![ + NonZeroU32::new(2).unwrap(), + NonZeroU32::new(10).unwrap(), + NonZeroU32::new(15).unwrap(), + NonZeroU32::new(35).unwrap(), + ]; let start_ts_1 = epoch.start - boost_period_length; let end_ts_1 = start_ts_1 + (boost_period_length * multipliers1.len() as i32); - let multipliers2 = vec![3, 10, 20]; + let multipliers2 = vec![ + NonZeroU32::new(3).unwrap(), + NonZeroU32::new(10).unwrap(), + NonZeroU32::new(20).unwrap(), + ]; + let start_ts_2 = epoch.start - (boost_period_length * 2); let end_ts_2 = start_ts_2 + (boost_period_length * multipliers2.len() as i32); - let multipliers3 = vec![1, 10, 20]; + let multipliers3 = vec![ + NonZeroU32::new(1).unwrap(), + NonZeroU32::new(10).unwrap(), + NonZeroU32::new(20).unwrap(), + ]; let boosts = vec![ BoostedHexInfo { diff --git a/boost_manager/tests/watcher_tests.rs b/boost_manager/tests/watcher_tests.rs index 761554847..185b1166e 100644 --- a/boost_manager/tests/watcher_tests.rs +++ b/boost_manager/tests/watcher_tests.rs @@ -11,7 +11,7 @@ use mobile_config::{ }; use solana_sdk::pubkey::Pubkey; use sqlx::PgPool; -use std::str::FromStr; +use std::{num::NonZeroU32, str::FromStr}; const BOOST_HEX_PUBKEY: &str = "J9JiLTpjaShxL8eMvUs8txVw6TZ36E38SiJ89NxnMbLU"; const BOOST_CONFIG_PUBKEY: &str = "BZM1QTud72B2cpTW7PhEnFmRX7ZWzvY7DpPpNJJuDrWG"; @@ -47,10 +47,19 @@ async fn test_boosted_hex_updates_to_filestore(pool: PgPool) -> anyhow::Result<( let boost_period_length = Duration::days(30); // setup boosted hex data to stream as updates - let multipliers1 = vec![2, 10, 15, 35]; + let multipliers1 = vec![ + NonZeroU32::new(2).unwrap(), + NonZeroU32::new(10).unwrap(), + NonZeroU32::new(15).unwrap(), + NonZeroU32::new(35).unwrap(), + ]; let start_ts_1 = epoch.start - boost_period_length; let end_ts_1 = start_ts_1 + (boost_period_length * multipliers1.len() as i32); - let multipliers2 = vec![3, 10, 20]; + let multipliers2 = vec![ + NonZeroU32::new(3).unwrap(), + NonZeroU32::new(10).unwrap(), + NonZeroU32::new(20).unwrap(), + ]; let start_ts_2 = epoch.start - (boost_period_length * 2); let end_ts_2 = start_ts_2 + (boost_period_length * multipliers2.len() as i32); diff --git a/mobile_config/src/boosted_hex_info.rs b/mobile_config/src/boosted_hex_info.rs index 7e84cdb49..7dcf3649f 100644 --- a/mobile_config/src/boosted_hex_info.rs +++ b/mobile_config/src/boosted_hex_info.rs @@ -4,7 +4,7 @@ use file_store::traits::TimestampDecode; use futures::stream::{BoxStream, StreamExt}; use helium_proto::BoostedHexInfoV1 as BoostedHexInfoProto; use solana_sdk::pubkey::Pubkey; -use std::{collections::HashMap, convert::TryFrom}; +use std::{collections::HashMap, convert::TryFrom, num::NonZeroU32}; pub type BoostedHexInfoStream = BoxStream<'static, BoostedHexInfo>; @@ -18,7 +18,7 @@ pub struct BoostedHexInfo { pub start_ts: Option>, pub end_ts: Option>, pub period_length: Duration, - pub multipliers: Vec, + pub multipliers: Vec, pub boosted_hex_pubkey: Pubkey, pub boost_config_pubkey: Pubkey, pub version: u32, @@ -28,7 +28,12 @@ impl TryFrom for BoostedHexInfo { type Error = anyhow::Error; fn try_from(v: BoostedHexInfoProto) -> anyhow::Result { let period_length = Duration::seconds(v.period_length as i64); - let multipliers = v.multipliers; + let multipliers = v + .multipliers + .into_iter() + .map(NonZeroU32::new) + .collect::>>() + .ok_or_else(|| anyhow::anyhow!("multipliers cannot contain values of 0"))?; let start_ts = to_start_ts(v.start_ts); let end_ts = to_end_ts(start_ts, period_length, multipliers.len()); let boosted_hex_pubkey: Pubkey = Pubkey::try_from(v.boosted_hex_pubkey.as_slice())?; @@ -52,12 +57,17 @@ impl TryFrom for BoostedHexInfoProto { fn try_from(v: BoostedHexInfo) -> anyhow::Result { let start_ts = v.start_ts.map_or(0, |v| v.timestamp() as u64); let end_ts = v.end_ts.map_or(0, |v| v.timestamp() as u64); + let multipliers = v + .multipliers + .into_iter() + .map(|v| v.get()) + .collect::>(); Ok(Self { location: v.location, start_ts, end_ts, period_length: v.period_length.num_seconds() as u32, - multipliers: v.multipliers, + multipliers, boosted_hex_pubkey: v.boosted_hex_pubkey.to_bytes().into(), boost_config_pubkey: v.boost_config_pubkey.to_bytes().into(), version: v.version, @@ -66,7 +76,7 @@ impl TryFrom for BoostedHexInfoProto { } impl BoostedHexInfo { - pub fn current_multiplier(&self, ts: DateTime) -> anyhow::Result> { + pub fn current_multiplier(&self, ts: DateTime) -> anyhow::Result> { if self.end_ts.is_some() && ts >= self.end_ts.unwrap() { // end time has been set and the current time is after the end time, so return None // to indicate that the hex is no longer boosted @@ -98,7 +108,7 @@ pub struct BoostedHexes { #[derive(PartialEq, Debug, Clone)] pub struct BoostedHex { pub location: u64, - pub multiplier: u32, + pub multiplier: NonZeroU32, } impl BoostedHexes { @@ -113,7 +123,6 @@ impl BoostedHexes { pub async fn get_all( hex_service_client: &impl HexBoostingInfoResolver, ) -> anyhow::Result { - tracing::info!("getting boosted hexes"); let mut map = HashMap::new(); let mut stream = hex_service_client .clone() @@ -144,7 +153,7 @@ impl BoostedHexes { Ok(Self { hexes: map }) } - pub fn get_current_multiplier(&self, location: u64, ts: DateTime) -> Option { + pub fn get_current_multiplier(&self, location: u64, ts: DateTime) -> Option { self.hexes .get(&location) .and_then(|info| info.current_multiplier(ts).ok()?) @@ -157,6 +166,7 @@ pub(crate) mod db { use futures::stream::{Stream, StreamExt}; use solana_sdk::pubkey::Pubkey; use sqlx::{PgExecutor, Row}; + use std::num::NonZeroU32; use std::str::FromStr; const GET_BOOSTED_HEX_INFO_SQL: &str = r#" @@ -214,8 +224,11 @@ pub(crate) mod db { let multipliers = row .get::, &str>("multipliers") .into_iter() - .map(|v| v as u32) - .collect::>(); + .map(|v| NonZeroU32::new(v as u32)) + .collect::>>() + .ok_or_else(|| { + sqlx::Error::Decode(Box::from("multipliers cannot contain values of 0")) + })?; let end_ts = to_end_ts(start_ts, period_length, multipliers.len()); let boost_config_pubkey = Pubkey::from_str(row.get::<&str, &str>("boost_config_pubkey")) @@ -252,3 +265,120 @@ fn to_end_ts( ) -> Option> { start_ts.map(|ts| ts + period_length * num_multipliers as i32) } + +#[cfg(test)] +mod tests { + use super::*; + use chrono::NaiveDateTime; + use std::str::FromStr; + + const BOOST_HEX_PUBKEY: &str = "J9JiLTpjaShxL8eMvUs8txVw6TZ36E38SiJ89NxnMbLU"; + const BOOST_HEX_CONFIG_PUBKEY: &str = "BZM1QTud72B2cpTW7PhEnFmRX7ZWzvY7DpPpNJJuDrWG"; + + #[test] + fn boosted_hex_from_proto_valid_not_started() -> anyhow::Result<()> { + let proto = BoostedHexInfoProto { + location: 631252734740306943, + start_ts: 0, + end_ts: 0, + period_length: 2592000, + multipliers: vec![2, 10, 15, 35], + boosted_hex_pubkey: Pubkey::from_str(BOOST_HEX_PUBKEY) + .unwrap() + .to_bytes() + .to_vec(), + boost_config_pubkey: Pubkey::from_str(BOOST_HEX_CONFIG_PUBKEY) + .unwrap() + .to_bytes() + .to_vec(), + version: 1, + }; + + let msg = BoostedHexInfo::try_from(proto)?; + assert_eq!(631252734740306943, msg.location); + assert_eq!(None, msg.start_ts); + assert_eq!(None, msg.end_ts); + assert_eq!(2592000, msg.period_length.num_seconds()); + assert_eq!(4, msg.multipliers.len()); + assert_eq!(2, msg.multipliers[0].get()); + assert_eq!(10, msg.multipliers[1].get()); + assert_eq!(15, msg.multipliers[2].get()); + assert_eq!(35, msg.multipliers[3].get()); + assert_eq!( + Pubkey::from_str(BOOST_HEX_PUBKEY).unwrap(), + msg.boosted_hex_pubkey + ); + assert_eq!( + Pubkey::from_str(BOOST_HEX_CONFIG_PUBKEY).unwrap(), + msg.boost_config_pubkey + ); + assert_eq!(1, msg.version); + Ok(()) + } + + #[test] + fn boosted_hex_from_proto_valid_started() -> anyhow::Result<()> { + let proto = BoostedHexInfoProto { + location: 631252734740306943, + start_ts: 1710378000, + end_ts: 1720746000, + period_length: 2592000, + multipliers: vec![2, 10, 15, 35], + boosted_hex_pubkey: Pubkey::from_str(BOOST_HEX_PUBKEY) + .unwrap() + .to_bytes() + .to_vec(), + boost_config_pubkey: Pubkey::from_str(BOOST_HEX_CONFIG_PUBKEY) + .unwrap() + .to_bytes() + .to_vec(), + version: 1, + }; + + let msg = BoostedHexInfo::try_from(proto)?; + assert_eq!(631252734740306943, msg.location); + assert_eq!(parse_dt("2024-03-14 01:00:00"), msg.start_ts.unwrap()); + assert_eq!(parse_dt("2024-07-12 01:00:00"), msg.end_ts.unwrap()); + assert_eq!(2592000, msg.period_length.num_seconds()); + assert_eq!(4, msg.multipliers.len()); + assert_eq!(2, msg.multipliers[0].get()); + assert_eq!(10, msg.multipliers[1].get()); + assert_eq!(15, msg.multipliers[2].get()); + assert_eq!(35, msg.multipliers[3].get()); + assert_eq!( + Pubkey::from_str(BOOST_HEX_PUBKEY).unwrap(), + msg.boosted_hex_pubkey + ); + assert_eq!( + Pubkey::from_str(BOOST_HEX_CONFIG_PUBKEY).unwrap(), + msg.boost_config_pubkey + ); + assert_eq!(1, msg.version); + Ok(()) + } + + #[test] + fn boosted_hex_from_proto_invalid_multiplier() -> anyhow::Result<()> { + let proto = BoostedHexInfoProto { + location: 631252734740306943, + start_ts: 1712624400000, + end_ts: 0, + period_length: 2592000, + multipliers: vec![2, 0, 15, 35], + boosted_hex_pubkey: BOOST_HEX_PUBKEY.as_bytes().to_vec(), + boost_config_pubkey: BOOST_HEX_CONFIG_PUBKEY.as_bytes().to_vec(), + version: 1, + }; + assert_eq!( + "multipliers cannot contain values of 0", + BoostedHexInfo::try_from(proto).err().unwrap().to_string() + ); + Ok(()) + } + + fn parse_dt(dt: &str) -> DateTime { + NaiveDateTime::parse_from_str(dt, "%Y-%m-%d %H:%M:%S") + .expect("unable_to_parse") + .and_utc() + } +} diff --git a/mobile_verifier/src/coverage.rs b/mobile_verifier/src/coverage.rs index b2aea9dae..06346871f 100644 --- a/mobile_verifier/src/coverage.rs +++ b/mobile_verifier/src/coverage.rs @@ -37,6 +37,7 @@ use sqlx::{FromRow, PgPool, Pool, Postgres, QueryBuilder, Transaction, Type}; use std::{ cmp::Ordering, collections::{BTreeMap, BinaryHeap, HashMap}, + num::NonZeroU32, pin::pin, sync::Arc, time::Instant, @@ -750,14 +751,18 @@ fn into_outdoor_rewards( .take(MAX_OUTDOOR_RADIOS_PER_RES12_HEX) .zip(OUTDOOR_REWARD_WEIGHTS) .map(move |(cl, rank)| { - let boost_multiplier = boosted_hexes + let (boost_multiplier, oracle_multiplier) = boosted_hexes .get_current_multiplier(hex.into(), epoch_start) - .unwrap_or(1); - let oracle_multiplier = if boost_multiplier > 1 { - dec!(1.0) - } else { - urbanization_multiplier(cl.urbanized) - }; + .map_or_else( + || { + ( + NonZeroU32::new(1).unwrap(), + urbanization_multiplier(cl.urbanized), + ) + }, + |multiplier| (multiplier, dec!(1.0)), + ); + CoverageReward { points: cl.coverage_points() * oracle_multiplier * rank, hotspot: cl.hotspot, @@ -785,14 +790,18 @@ fn into_indoor_rewards( .into_iter() .take(MAX_INDOOR_RADIOS_PER_RES12_HEX) .map(move |cl| { - let boost_multiplier = boosted_hexes + let (boost_multiplier, oracle_multiplier) = boosted_hexes .get_current_multiplier(hex.into(), epoch_start) - .unwrap_or(1); - let oracle_multiplier = if boost_multiplier > 1 { - dec!(1.0) - } else { - urbanization_multiplier(cl.urbanized) - }; + .map_or_else( + || { + ( + NonZeroU32::new(1).unwrap(), + urbanization_multiplier(cl.urbanized), + ) + }, + |multiplier| (multiplier, dec!(1.0)), + ); + CoverageReward { points: cl.coverage_points() * oracle_multiplier, hotspot: cl.hotspot, @@ -1004,7 +1013,7 @@ mod test { points: dec!(400), boosted_hex_info: BoostedHex { location: 0x8a1fb46622dffff_u64, - multiplier: 1, + multiplier: NonZeroU32::new(1).unwrap(), }, }] ); @@ -1115,7 +1124,7 @@ mod test { points: dec!(400), boosted_hex_info: BoostedHex { location: 0x8a1fb46622dffff_u64, - multiplier: 1, + multiplier: NonZeroU32::new(1).unwrap(), }, }] ); @@ -1153,7 +1162,7 @@ mod test { points: dec!(16), boosted_hex_info: BoostedHex { location: 0x8a1fb46622dffff_u64, - multiplier: 1, + multiplier: NonZeroU32::new(1).unwrap(), }, }, CoverageReward { @@ -1162,7 +1171,7 @@ mod test { points: dec!(8), boosted_hex_info: BoostedHex { location: 0x8a1fb46622dffff_u64, - multiplier: 1, + multiplier: NonZeroU32::new(1).unwrap(), }, }, CoverageReward { @@ -1171,7 +1180,7 @@ mod test { points: dec!(4), boosted_hex_info: BoostedHex { location: 0x8a1fb46622dffff_u64, - multiplier: 1, + multiplier: NonZeroU32::new(1).unwrap(), }, } ] diff --git a/mobile_verifier/src/reward_shares.rs b/mobile_verifier/src/reward_shares.rs index 3d7b56d63..49beb6c20 100644 --- a/mobile_verifier/src/reward_shares.rs +++ b/mobile_verifier/src/reward_shares.rs @@ -25,7 +25,7 @@ use mobile_config::{ }; use rust_decimal::prelude::*; use rust_decimal_macros::dec; -use std::{collections::HashMap, ops::Range}; +use std::{collections::HashMap, num::NonZeroU32, ops::Range}; use uuid::Uuid; /// Total tokens emissions pool per 365 days or 366 days for a leap year @@ -436,12 +436,12 @@ impl HotspotPoints { { BoostedHex { location: boosted_hex_info.location, - multiplier: 1, + multiplier: NonZeroU32::new(1).unwrap(), } } else { boosted_hex_info }; - rp.points += points * Decimal::from(final_boost_info.multiplier); + rp.points += points * Decimal::from(final_boost_info.multiplier.get()); rp.boosted_hexes.push(final_boost_info); } } @@ -622,10 +622,10 @@ fn new_radio_reward( let boosted_hexes = radio_points .boosted_hexes .iter() - .filter(|boosted_hex| boosted_hex.multiplier > 1) + .filter(|boosted_hex| boosted_hex.multiplier > NonZeroU32::new(1).unwrap()) .map(|boosted_hex| proto::BoostedHex { location: boosted_hex.location, - multiplier: boosted_hex.multiplier, + multiplier: boosted_hex.multiplier.get(), }) .collect(); ( diff --git a/mobile_verifier/tests/hex_boosting.rs b/mobile_verifier/tests/hex_boosting.rs index a90574fb6..b0fa5b517 100644 --- a/mobile_verifier/tests/hex_boosting.rs +++ b/mobile_verifier/tests/hex_boosting.rs @@ -29,7 +29,7 @@ use rust_decimal::prelude::*; use rust_decimal_macros::dec; use solana_sdk::pubkey::Pubkey; use sqlx::{PgPool, Postgres, Transaction}; -use std::str::FromStr; +use std::{num::NonZeroU32, str::FromStr}; use uuid::Uuid; const HOTSPOT_1: &str = "112E7TxoNHV46M6tiPA8N1MkeMeQxc9ztb4JQLXBVAAUfq1kJLoF"; @@ -100,19 +100,32 @@ async fn test_poc_with_boosted_hexes(pool: PgPool) -> anyhow::Result<()> { update_assignments(&pool).await?; // setup boosted hex where reward start time is in the second period length - let multipliers1 = vec![2, 10, 15, 35]; + let multipliers1 = vec![ + NonZeroU32::new(2).unwrap(), + NonZeroU32::new(10).unwrap(), + NonZeroU32::new(15).unwrap(), + NonZeroU32::new(35).unwrap(), + ]; let start_ts_1 = epoch.start - boost_period_length; let end_ts_1 = start_ts_1 + (boost_period_length * multipliers1.len() as i32); // setup boosted hex where reward start time is in the third & last period length - let multipliers2 = vec![3, 10, 20]; + let multipliers2 = vec![ + NonZeroU32::new(3).unwrap(), + NonZeroU32::new(10).unwrap(), + NonZeroU32::new(20).unwrap(), + ]; let start_ts_2 = epoch.start - (boost_period_length * 2); let end_ts_2 = start_ts_2 + (boost_period_length * multipliers2.len() as i32); // setup boosted hex where no start or end time is set // will default to the first multiplier // first multiplier is 1x for easy math when comparing relative rewards - let multipliers3 = vec![1, 10, 20]; + let multipliers3 = vec![ + NonZeroU32::new(1).unwrap(), + NonZeroU32::new(10).unwrap(), + NonZeroU32::new(20).unwrap(), + ]; let boosted_hexes = vec![ BoostedHexInfo { @@ -255,19 +268,32 @@ async fn test_poc_boosted_hexes_thresholds_not_met(pool: PgPool) -> anyhow::Resu update_assignments(&pool).await?; // setup boosted hex where reward start time is in the second period length - let multipliers1 = vec![2, 10, 15, 35]; + let multipliers1 = vec![ + NonZeroU32::new(2).unwrap(), + NonZeroU32::new(10).unwrap(), + NonZeroU32::new(15).unwrap(), + NonZeroU32::new(35).unwrap(), + ]; let start_ts_1 = epoch.start - boost_period_length; let end_ts_1 = start_ts_1 + (boost_period_length * multipliers1.len() as i32); // setup boosted hex where reward start time is in the third & last period length - let multipliers2 = vec![3, 10, 20]; + let multipliers2 = vec![ + NonZeroU32::new(3).unwrap(), + NonZeroU32::new(10).unwrap(), + NonZeroU32::new(20).unwrap(), + ]; let start_ts_2 = epoch.start - (boost_period_length * 2); let end_ts_2 = start_ts_2 + (boost_period_length * multipliers2.len() as i32); // setup boosted hex where no start or end time is set // will default to the first multiplier // first multiplier is 1x for easy math when comparing relative rewards - let multipliers3 = vec![1, 10, 20]; + let multipliers3 = vec![ + NonZeroU32::new(1).unwrap(), + NonZeroU32::new(10).unwrap(), + NonZeroU32::new(20).unwrap(), + ]; let boosted_hexes = vec![ BoostedHexInfo { @@ -386,18 +412,34 @@ async fn test_poc_with_multi_coverage_boosted_hexes(pool: PgPool) -> anyhow::Res update_assignments(&pool).await?; // setup boosted hex where reward start time is in the second period length - let multipliers1 = vec![2, 10, 15, 35]; + let multipliers1 = vec![ + NonZeroU32::new(2).unwrap(), + NonZeroU32::new(10).unwrap(), + NonZeroU32::new(15).unwrap(), + NonZeroU32::new(35).unwrap(), + ]; let start_ts_1 = epoch.start - boost_period_length; let end_ts_1 = start_ts_1 + (boost_period_length * multipliers1.len() as i32); // setup boosted hex where reward start time is in the third & last period length - let multipliers2 = vec![3, 10, 20]; + + let multipliers2 = vec![ + NonZeroU32::new(3).unwrap(), + NonZeroU32::new(10).unwrap(), + NonZeroU32::new(20).unwrap(), + ]; + let start_ts_2 = epoch.start - (boost_period_length * 2); let end_ts_2 = start_ts_2 + (boost_period_length * multipliers2.len() as i32); // setup boosted hex where reward start time is in the first period length // default to 1x multiplier for easy math when comparing relative rewards - let multipliers3 = vec![1, 10, 20]; + let multipliers3 = vec![ + NonZeroU32::new(1).unwrap(), + NonZeroU32::new(10).unwrap(), + NonZeroU32::new(20).unwrap(), + ]; + let start_ts_3 = epoch.start; let end_ts_3 = start_ts_3 + (boost_period_length * multipliers3.len() as i32); @@ -554,13 +596,21 @@ async fn test_expired_boosted_hex(pool: PgPool) -> anyhow::Result<()> { update_assignments(&pool).await?; // setup boosted hex where reward start time is after the boost period ends - let multipliers1 = vec![2, 10, 15]; + let multipliers1 = vec![ + NonZeroU32::new(2).unwrap(), + NonZeroU32::new(10).unwrap(), + NonZeroU32::new(15).unwrap(), + ]; let start_ts_1 = epoch.start - (boost_period_length * multipliers1.len() as i32 + ChronoDuration::days(1)); let end_ts_1 = start_ts_1 + (boost_period_length * multipliers1.len() as i32); dbg!(epoch.start, start_ts_1, end_ts_1); // setup boosted hex where reward start time is same as the boost period ends - let multipliers2 = vec![4, 12, 17]; + let multipliers2 = vec![ + NonZeroU32::new(4).unwrap(), + NonZeroU32::new(12).unwrap(), + NonZeroU32::new(17).unwrap(), + ]; let start_ts_2 = epoch.start - (boost_period_length * multipliers2.len() as i32); let end_ts_2 = start_ts_2 + (boost_period_length * multipliers2.len() as i32); dbg!(epoch.start, start_ts_2, end_ts_2); @@ -668,12 +718,12 @@ async fn test_reduced_location_score_with_boosted_hexes(pool: PgPool) -> anyhow: update_assignments(&pool).await?; // setup boosted hex where reward start time is in the second period length - let multipliers1 = vec![2]; + let multipliers1 = vec![NonZeroU32::new(2).unwrap()]; let start_ts_1 = epoch.start; let end_ts_1 = start_ts_1 + (boost_period_length * multipliers1.len() as i32); // setup boosted hex where no start or end time is set - let multipliers2 = vec![2]; + let multipliers2 = vec![NonZeroU32::new(2).unwrap()]; let boosted_hexes = vec![ BoostedHexInfo { @@ -811,18 +861,31 @@ async fn test_poc_with_cbrs_and_multi_coverage_boosted_hexes(pool: PgPool) -> an update_assignments(&pool).await?; // setup boosted hex where reward start time is in the second period length - let multipliers1 = vec![2, 10, 15, 35]; + let multipliers1 = vec![ + NonZeroU32::new(2).unwrap(), + NonZeroU32::new(10).unwrap(), + NonZeroU32::new(15).unwrap(), + NonZeroU32::new(35).unwrap(), + ]; let start_ts_1 = epoch.start - boost_period_length; let end_ts_1 = start_ts_1 + (boost_period_length * multipliers1.len() as i32); // setup boosted hex where reward start time is in the third & last period length - let multipliers2 = vec![3, 10, 20]; + let multipliers2 = vec![ + NonZeroU32::new(3).unwrap(), + NonZeroU32::new(10).unwrap(), + NonZeroU32::new(20).unwrap(), + ]; let start_ts_2 = epoch.start - (boost_period_length * 2); let end_ts_2 = start_ts_2 + (boost_period_length * multipliers2.len() as i32); // setup boosted hex where reward start time is in the first period length // default to 1x multiplier for easy math when comparing relative rewards - let multipliers3 = vec![1, 10, 20]; + let multipliers3 = vec![ + NonZeroU32::new(1).unwrap(), + NonZeroU32::new(10).unwrap(), + NonZeroU32::new(20).unwrap(), + ]; let start_ts_3 = epoch.start; let end_ts_3 = start_ts_3 + (boost_period_length * multipliers3.len() as i32); diff --git a/mobile_verifier/tests/modeled_coverage.rs b/mobile_verifier/tests/modeled_coverage.rs index 4ecaac780..eef3ef7b5 100644 --- a/mobile_verifier/tests/modeled_coverage.rs +++ b/mobile_verifier/tests/modeled_coverage.rs @@ -30,7 +30,7 @@ use mobile_verifier::{ use rust_decimal_macros::dec; use solana_sdk::pubkey::Pubkey; use sqlx::PgPool; -use std::{collections::HashMap, ops::Range, pin::pin, str::FromStr}; +use std::{collections::HashMap, num::NonZeroU32, ops::Range, pin::pin, str::FromStr}; use uuid::Uuid; #[derive(Clone)] @@ -843,7 +843,7 @@ async fn scenario_three(pool: PgPool) -> anyhow::Result<()> { start_ts: None, end_ts: None, period_length: Duration::hours(1), - multipliers: vec![1], + multipliers: vec![NonZeroU32::new(1).unwrap()], boosted_hex_pubkey: Pubkey::from_str(BOOST_HEX_PUBKEY).unwrap(), boost_config_pubkey: Pubkey::from_str(BOOST_CONFIG_PUBKEY).unwrap(), version: 0, @@ -856,7 +856,7 @@ async fn scenario_three(pool: PgPool) -> anyhow::Result<()> { start_ts: None, end_ts: None, period_length: Duration::hours(1), - multipliers: vec![2], + multipliers: vec![NonZeroU32::new(2).unwrap()], boosted_hex_pubkey: Pubkey::from_str(BOOST_HEX_PUBKEY).unwrap(), boost_config_pubkey: Pubkey::from_str(BOOST_CONFIG_PUBKEY).unwrap(), version: 0, @@ -870,7 +870,7 @@ async fn scenario_three(pool: PgPool) -> anyhow::Result<()> { start_ts: None, end_ts: None, period_length: Duration::hours(1), - multipliers: vec![3], + multipliers: vec![NonZeroU32::new(3).unwrap()], boosted_hex_pubkey: Pubkey::from_str(BOOST_HEX_PUBKEY).unwrap(), boost_config_pubkey: Pubkey::from_str(BOOST_CONFIG_PUBKEY).unwrap(), version: 0,