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

HIP 114: Service Provider Rewards #856

Closed
wants to merge 29 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
9ec7c4b
Initial work on promotion rewards
maplant Aug 23, 2024
448396f
Fix tests, fix indexer, improve code organization
maplant Aug 26, 2024
1985638
Fixes for moogey's thing
maplant Aug 26, 2024
21cacee
Fix ingest test
maplant Aug 26, 2024
b427cfe
Add unit tests
maplant Aug 26, 2024
75b267f
clippy
maplant Aug 27, 2024
d0b7834
...fmt
maplant Aug 27, 2024
9624208
Don't store subscriber id as a byte array, store as uuid
maplant Aug 27, 2024
19e514f
Revert "Don't store subscriber id as a byte array, store as uuid"
maplant Aug 27, 2024
6a12615
Fixes and stuff
maplant Aug 28, 2024
d746a5c
Rename verified to validated
maplant Aug 28, 2024
bc9961b
Fixes
maplant Aug 28, 2024
b047474
Fix migration
maplant Aug 28, 2024
3dbdb76
Another fix
maplant Aug 28, 2024
5a1bcdb
Add back some asserts
macpie Sep 4, 2024
6fc391f
- Add some comments to tests
macpie Sep 4, 2024
691c490
Rename shares_per_reward to rewards_per_share
macpie Sep 4, 2024
f0831b4
sp_rewards_when_no_promotion_shares_hip114
macpie Sep 4, 2024
efd8b43
Cleaning
macpie Sep 4, 2024
0f971b6
Inline fun
macpie Sep 4, 2024
8f6d6e8
Refactor validate to be simpler
macpie Sep 4, 2024
1a72256
Fix rebase
macpie Sep 5, 2024
7f049a1
Fix migration file name
macpie Sep 5, 2024
2c541ff
do not print mobile_rewards
michaeldjeffrey Sep 10, 2024
cb30d18
add test getter for promotion rewards
michaeldjeffrey Sep 10, 2024
f12954c
add test with seeded service provider promotions
michaeldjeffrey Sep 10, 2024
5af0374
fix shares column receiving wrong name and type
michaeldjeffrey Sep 10, 2024
b36909e
add easy derives for testing
michaeldjeffrey Sep 10, 2024
045f0eb
update helium-anchor-gen for `incentive_escrow_fund_bps` field
michaeldjeffrey Sep 10, 2024
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
188 changes: 102 additions & 86 deletions Cargo.lock

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,14 @@ helium-lib = { git = "https://github.com/helium/helium-wallet-rs.git", branch =
hextree = { git = "https://github.com/jaykickliter/HexTree", branch = "main", features = [
"disktree",
] }
helium-proto = { git = "https://github.com/helium/proto", branch = "master", features = [
helium-proto = { git = "https://github.com/helium/proto", branch = "map/subscriber-referral", features = [
"services",
] }
beacon = { git = "https://github.com/helium/proto", branch = "master" }
beacon = { git = "https://github.com/helium/proto", branch = "map/subscriber-referral" }
solana-client = "1.18"
solana-sdk = "1.18"
solana-program = "1.18"
spl-token = "3.5.0"
spl-token = { version = "3.5.0", features = [ "no-entrypoint" ] }
reqwest = { version = "0", default-features = false, features = [
"gzip",
"json",
Expand Down
17 changes: 17 additions & 0 deletions file_store/src/cli/dump_mobile_rewards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::{file_source, Result, Settings};
use futures::stream::StreamExt;
use helium_crypto::PublicKey;
use helium_proto::services::poc_mobile::mobile_reward_share::Reward::*;
use helium_proto::services::poc_mobile::promotion_reward::Entity;
use helium_proto::services::poc_mobile::MobileRewardShare;
use prost::Message;
use serde_json::json;
Expand All @@ -23,6 +24,7 @@ impl Cmd {
let mut subscriber_reward = vec![];
let mut service_provider_reward = vec![];
let mut unallocated_reward = vec![];
let mut promotion_reward = vec![];

while let Some(result) = file_stream.next().await {
let msg = result?;
Expand Down Expand Up @@ -60,6 +62,21 @@ impl Cmd {
"unallocated_reward_type": reward.reward_type,
"amount": reward.amount,
})),
PromotionReward(reward) => {
let entity = reward.entity.unwrap();
match entity {
Entity::SubscriberId(id) => promotion_reward.push(json!({
"subscriber_id": uuid::Uuid::from_slice(&id).unwrap(),
"service_provider_amount": reward.service_provider_amount,
"matched_amount": reward.matched_amount,
})),
Entity::GatewayKey(key) => promotion_reward.push(json!({
"gateway_key": PublicKey::try_from(key)?.to_string(),
"service_provider_amount": reward.service_provider_amount,
"matched_amount": reward.matched_amount,
})),
}
}
},
None => todo!(),
}
Expand Down
10 changes: 10 additions & 0 deletions file_store/src/file_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ pub const SUBSCRIBER_VERIFIED_MAPPING_INGEST_REPORT: &str =
"subscriber_verified_mapping_ingest_report";
pub const VERIFIED_SUBSCRIBER_VERIFIED_MAPPING_INGEST_REPORT: &str =
"verified_subscriber_verified_mapping_ingest_report";
pub const PROMOTION_REWARD_INGEST_REPORT: &str = "promotion_reward_ingest_report";
pub const VERIFIED_PROMOTION_REWARD: &str = "verified_promotion_reward";

#[derive(Debug, PartialEq, Eq, Clone, Serialize, Copy, strum::EnumCount)]
#[serde(rename_all = "snake_case")]
Expand Down Expand Up @@ -220,6 +222,8 @@ pub enum FileType {
VerifiedSPBoostedRewardsBannedRadioIngestReport,
SubscriberVerifiedMappingEventIngestReport,
VerifiedSubscriberVerifiedMappingEventIngestReport,
PromotionRewardIngestReport,
VerifiedPromotionReward,
}

impl fmt::Display for FileType {
Expand Down Expand Up @@ -291,6 +295,8 @@ impl fmt::Display for FileType {
Self::VerifiedSubscriberVerifiedMappingEventIngestReport => {
VERIFIED_SUBSCRIBER_VERIFIED_MAPPING_INGEST_REPORT
}
Self::PromotionRewardIngestReport => PROMOTION_REWARD_INGEST_REPORT,
Self::VerifiedPromotionReward => VERIFIED_PROMOTION_REWARD,
};
f.write_str(s)
}
Expand Down Expand Up @@ -365,6 +371,8 @@ impl FileType {
Self::VerifiedSubscriberVerifiedMappingEventIngestReport => {
VERIFIED_SUBSCRIBER_VERIFIED_MAPPING_INGEST_REPORT
}
Self::PromotionRewardIngestReport => PROMOTION_REWARD_INGEST_REPORT,
Self::VerifiedPromotionReward => VERIFIED_PROMOTION_REWARD,
}
}
}
Expand Down Expand Up @@ -439,6 +447,8 @@ impl FromStr for FileType {
VERIFIED_SUBSCRIBER_VERIFIED_MAPPING_INGEST_REPORT => {
Self::VerifiedSubscriberVerifiedMappingEventIngestReport
}
PROMOTION_REWARD_INGEST_REPORT => Self::PromotionRewardIngestReport,
VERIFIED_PROMOTION_REWARD => Self::VerifiedPromotionReward,
_ => return Err(Error::from(io::Error::from(io::ErrorKind::InvalidInput))),
};
Ok(result)
Expand Down
1 change: 1 addition & 0 deletions file_store/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub mod mobile_radio_threshold;
pub mod mobile_session;
pub mod mobile_subscriber;
pub mod mobile_transfer;
pub mod promotion_reward;
pub mod reward_manifest;
mod settings;
pub mod speedtest;
Expand Down
91 changes: 91 additions & 0 deletions file_store/src/promotion_reward.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
use crate::{
traits::{MsgDecode, TimestampDecode, TimestampEncode},
Error, Result,
};
use chrono::{DateTime, Utc};
use helium_crypto::PublicKeyBinary;
use helium_proto::services::poc_mobile::{
self as proto, PromotionRewardIngestReportV1, PromotionRewardReqV1,
};

#[derive(Debug, Clone, PartialEq, Hash)]
pub enum Entity {
SubscriberId(Vec<u8>),
GatewayKey(PublicKeyBinary),
}

impl From<proto::promotion_reward_req_v1::Entity> for Entity {
fn from(entity: proto::promotion_reward_req_v1::Entity) -> Self {
match entity {
proto::promotion_reward_req_v1::Entity::SubscriberId(v) => Entity::SubscriberId(v),
proto::promotion_reward_req_v1::Entity::GatewayKey(k) => Entity::GatewayKey(k.into()),
}
}
}

impl From<Entity> for proto::promotion_reward_req_v1::Entity {
fn from(entity: Entity) -> Self {
match entity {
Entity::SubscriberId(v) => proto::promotion_reward_req_v1::Entity::SubscriberId(v),
Entity::GatewayKey(k) => proto::promotion_reward_req_v1::Entity::GatewayKey(k.into()),
}
}
}

impl From<Entity> for proto::promotion_reward::Entity {
fn from(entity: Entity) -> Self {
match entity {
Entity::SubscriberId(v) => proto::promotion_reward::Entity::SubscriberId(v),
Entity::GatewayKey(k) => proto::promotion_reward::Entity::GatewayKey(k.into()),
}
}
}

#[derive(Clone)]
pub struct PromotionReward {
pub entity: Entity,
pub shares: u64,
pub timestamp: DateTime<Utc>,
pub received_timestamp: DateTime<Utc>,
pub carrier_pub_key: PublicKeyBinary,
pub signature: Vec<u8>,
}

impl MsgDecode for PromotionReward {
type Msg = PromotionRewardIngestReportV1;
}

impl TryFrom<PromotionRewardIngestReportV1> for PromotionReward {
type Error = Error;

fn try_from(v: PromotionRewardIngestReportV1) -> Result<Self> {
let received_timestamp = v.received_timestamp.to_timestamp_millis()?;
let Some(v) = v.report else {
return Err(Error::NotFound("report".to_string()));
};
Ok(Self {
entity: if let Some(entity) = v.entity {
entity.into()
} else {
return Err(Error::NotFound("entity".to_string()));
},
shares: v.shares,
timestamp: v.timestamp.to_timestamp()?,
received_timestamp,
carrier_pub_key: v.carrier_pub_key.into(),
signature: v.signature,
})
}
}

impl From<PromotionReward> for PromotionRewardReqV1 {
fn from(v: PromotionReward) -> Self {
Self {
entity: Some(v.entity.into()),
shares: v.shares,
timestamp: v.timestamp.encode_timestamp(),
carrier_pub_key: v.carrier_pub_key.into(),
signature: v.signature,
}
}
}
10 changes: 10 additions & 0 deletions file_store/src/traits/file_sink_write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,3 +268,13 @@ impl_file_sink!(
FileType::RewardManifest.to_str(),
"reward_manifest"
);
impl_file_sink!(
poc_mobile::PromotionRewardIngestReportV1,
FileType::PromotionRewardIngestReport.to_str(),
"promotion_reward_ingest_report"
);
impl_file_sink!(
poc_mobile::VerifiedPromotionRewardV1,
FileType::VerifiedPromotionReward.to_str(),
"verified_promotion_reward"
);
1 change: 1 addition & 0 deletions file_store/src/traits/msg_verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ impl_msg_verify!(mobile_config::BoostedHexInfoStreamReqV1, signature);
impl_msg_verify!(mobile_config::BoostedHexModifiedInfoStreamReqV1, signature);
impl_msg_verify!(mobile_config::BoostedHexInfoStreamResV1, signature);
impl_msg_verify!(poc_mobile::SubscriberVerifiedMappingEventReqV1, signature);
impl_msg_verify!(poc_mobile::PromotionRewardReqV1, signature);

#[cfg(test)]
mod test {
Expand Down
42 changes: 41 additions & 1 deletion ingest/src/server_mobile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ use helium_proto::services::poc_mobile::{
CoverageObjectIngestReportV1, CoverageObjectReqV1, CoverageObjectRespV1,
DataTransferSessionIngestReportV1, DataTransferSessionReqV1, DataTransferSessionRespV1,
InvalidatedRadioThresholdIngestReportV1, InvalidatedRadioThresholdReportReqV1,
InvalidatedRadioThresholdReportRespV1, RadioThresholdIngestReportV1, RadioThresholdReportReqV1,
InvalidatedRadioThresholdReportRespV1, PromotionRewardIngestReportV1, PromotionRewardReqV1,
PromotionRewardRespV1, RadioThresholdIngestReportV1, RadioThresholdReportReqV1,
RadioThresholdReportRespV1, ServiceProviderBoostedRewardsBannedRadioIngestReportV1,
ServiceProviderBoostedRewardsBannedRadioReqV1, ServiceProviderBoostedRewardsBannedRadioRespV1,
SpeedtestIngestReportV1, SpeedtestReqV1, SpeedtestRespV1, SubscriberLocationIngestReportV1,
Expand Down Expand Up @@ -46,6 +47,7 @@ pub struct GrpcServer {
sp_boosted_rewards_ban_sink:
FileSinkClient<ServiceProviderBoostedRewardsBannedRadioIngestReportV1>,
subscriber_mapping_event_sink: FileSinkClient<SubscriberVerifiedMappingEventIngestReportV1>,
promotion_reward_sink: FileSinkClient<PromotionRewardIngestReportV1>,
required_network: Network,
address: SocketAddr,
api_token: MetadataValue<Ascii>,
Expand Down Expand Up @@ -85,6 +87,7 @@ impl GrpcServer {
ServiceProviderBoostedRewardsBannedRadioIngestReportV1,
>,
subscriber_mapping_event_sink: FileSinkClient<SubscriberVerifiedMappingEventIngestReportV1>,
promotion_reward_sink: FileSinkClient<PromotionRewardIngestReportV1>,
required_network: Network,
address: SocketAddr,
api_token: MetadataValue<Ascii>,
Expand All @@ -100,6 +103,7 @@ impl GrpcServer {
coverage_object_report_sink,
sp_boosted_rewards_ban_sink,
subscriber_mapping_event_sink,
promotion_reward_sink,
required_network,
address,
api_token,
Expand Down Expand Up @@ -437,6 +441,30 @@ impl poc_mobile::PocMobile for GrpcServer {
let id = timestamp.to_string();
Ok(Response::new(SubscriberVerifiedMappingEventResV1 { id }))
}

async fn submit_promotion_reward(
&self,
request: Request<PromotionRewardReqV1>,
) -> GrpcResult<PromotionRewardRespV1> {
let received_timestamp: u64 = Utc::now().timestamp_millis() as u64;
let event = request.into_inner();

custom_tracing::record_b58("pub_key", &event.carrier_pub_key);

let report = self
.verify_public_key(event.carrier_pub_key.as_ref())
.and_then(|public_key| self.verify_network(public_key))
.and_then(|public_key| self.verify_signature(public_key, event))
.map(|(_, event)| PromotionRewardIngestReportV1 {
received_timestamp,
report: Some(event),
})?;

let _ = self.promotion_reward_sink.write(report, []).await;

let id = received_timestamp.to_string();
Ok(Response::new(PromotionRewardRespV1 { id }))
}
}

pub async fn grpc_server(settings: &Settings) -> Result<()> {
Expand Down Expand Up @@ -546,6 +574,16 @@ pub async fn grpc_server(settings: &Settings) -> Result<()> {
)
.await?;

let (subscriber_referral_eligibility_sink, subscriber_referral_eligibility_server) =
PromotionRewardIngestReportV1::file_sink(
store_base_path,
file_upload.clone(),
FileSinkCommitStrategy::Automatic,
FileSinkRollTime::Duration(settings.roll_time),
env!("CARGO_PKG_NAME"),
)
.await?;

let Some(api_token) = settings
.token
.as_ref()
Expand All @@ -565,6 +603,7 @@ pub async fn grpc_server(settings: &Settings) -> Result<()> {
coverage_object_report_sink,
sp_boosted_rewards_ban_sink,
subscriber_mapping_event_sink,
subscriber_referral_eligibility_sink,
settings.network,
settings.listen_addr,
api_token,
Expand All @@ -588,6 +627,7 @@ pub async fn grpc_server(settings: &Settings) -> Result<()> {
.add_task(coverage_object_report_sink_server)
.add_task(sp_boosted_rewards_ban_sink_server)
.add_task(subscriber_mapping_event_server)
.add_task(subscriber_referral_eligibility_server)
.add_task(grpc_server)
.build()
.start()
Expand Down
2 changes: 2 additions & 0 deletions ingest/tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ pub async fn setup_mobile() -> anyhow::Result<(TestClient, Trigger)> {
let (coverage_obj_tx, _rx) = tokio::sync::mpsc::channel(10);
let (sp_boosted_tx, _rx) = tokio::sync::mpsc::channel(10);
let (subscriber_mapping_tx, subscriber_mapping_rx) = tokio::sync::mpsc::channel(10);
let (promotion_rewards_tx, _rx) = tokio::sync::mpsc::channel(10);

tokio::spawn(async move {
let grpc_server = GrpcServer::new(
Expand All @@ -57,6 +58,7 @@ pub async fn setup_mobile() -> anyhow::Result<(TestClient, Trigger)> {
FileSinkClient::new(coverage_obj_tx, "noop"),
FileSinkClient::new(sp_boosted_tx, "noop"),
FileSinkClient::new(subscriber_mapping_tx, "test_file_sink"),
FileSinkClient::new(promotion_rewards_tx, "noop"),
Network::MainNet,
socket_addr,
api_token,
Expand Down
Loading