Skip to content

Commit

Permalink
wip: importing
Browse files Browse the repository at this point in the history
  • Loading branch information
octol committed Nov 1, 2024
1 parent f424cad commit 695f324
Show file tree
Hide file tree
Showing 8 changed files with 178 additions and 32 deletions.
1 change: 1 addition & 0 deletions nym-vpn-core/Cargo.lock

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

Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use nym_credentials::IssuedTicketBook;
use nym_credentials_interface::{PublicKeyUser, RequestInfo, TicketType};
use nym_ecash_time::EcashTime;
use nym_vpn_api_client::{
response::{NymVpnZkNym, NymVpnZkNymStatus},
response::{NymVpnZkNym, NymVpnZkNym2, NymVpnZkNymStatus},
types::{Device, VpnApiAccount},
VpnApiClientError,
};
Expand Down Expand Up @@ -81,6 +81,7 @@ pub(crate) async fn poll_zk_nym(
api_client: nym_vpn_api_client::VpnApiClient,
) -> PollingResult {
tracing::info!("Starting zk-nym polling task for {}", response.id);
tracing::info!("which had response : {:#?}", response);
let start_time = Instant::now();
loop {
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
Expand All @@ -90,7 +91,7 @@ pub(crate) async fn poll_zk_nym(
.get_zk_nym_by_id(&account, &device, &response.id)
.await
{
Ok(poll_response) if response.status != NymVpnZkNymStatus::Pending => {
Ok(poll_response) if poll_response.status != NymVpnZkNymStatus::Pending => {
tracing::info!("zk-nym polling finished: {:#?}", poll_response);
return PollingResult::Finished(
poll_response,
Expand Down Expand Up @@ -121,7 +122,7 @@ pub(crate) async fn poll_zk_nym(
}

pub(crate) async fn unblind_and_aggregate(
response: NymVpnZkNym,
response: NymVpnZkNym2,
ticketbook_type: TicketType,
request_info: RequestInfo,
account: VpnApiAccount,
Expand All @@ -132,20 +133,21 @@ pub(crate) async fn unblind_and_aggregate(
.map_err(Error::CreateEcashKeyPair)?;

let mut partial_wallets = Vec::new();
for blinded_share in response.blinded_shares {
let blinded_shares = response.blinded_shares.unwrap();
for share in blinded_shares.shares {
// TODO: remove unwrap
let blinded_share: WalletShare = serde_json::from_str(&blinded_share).unwrap();
// let blinded_share: WalletShare = serde_json::from_str(&share).unwrap();

// TODO: remove unwrap
let blinded_sig =
BlindedSignature::try_from_bs58(&blinded_share.bs58_encoded_share).unwrap();
BlindedSignature::try_from_bs58(&share.bs58_encoded_share).unwrap();

match nym_compact_ecash::issue_verify(
&vk_auth,
ecash_keypair.secret_key(),
&blinded_sig,
&request_info,
blinded_share.node_index,
share.node_index,
) {
Ok(partial_wallet) => partial_wallets.push(partial_wallet),
Err(err) => {
Expand All @@ -169,7 +171,7 @@ pub(crate) async fn unblind_and_aggregate(

let ticketbook = IssuedTicketBook::new(
aggregated_wallets.into_wallet_signatures(),
response.epoch.unwrap(),
blinded_shares.epoch_id,
ecash_keypair.into(),
ticketbook_type,
expiration_date.ecash_date(),
Expand All @@ -180,8 +182,8 @@ pub(crate) async fn unblind_and_aggregate(

#[derive(Debug)]
pub(crate) enum PollingResult {
Finished(NymVpnZkNym, TicketType, Box<RequestInfo>),
Timeout(NymVpnZkNym),
Finished(NymVpnZkNym2, TicketType, Box<RequestInfo>),
Timeout(NymVpnZkNym2),
Error(PollingError),
}

Expand Down
71 changes: 61 additions & 10 deletions nym-vpn-core/crates/nym-vpn-account-controller/src/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@
use std::{collections::HashMap, path::PathBuf, sync::Arc, time::Duration};

use futures::StreamExt;
use nym_compact_ecash::Base58;
use nym_config::defaults::NymNetworkDetails;
use nym_credentials_interface::{RequestInfo, TicketType};
use nym_credentials::EpochVerificationKey;
use nym_credentials_interface::{RequestInfo, TicketType, VerificationKeyAuth};
use nym_http_api_client::UserAgent;
use nym_vpn_api_client::{
response::{
NymVpnAccountSummaryResponse, NymVpnDevicesResponse, NymVpnZkNym, NymVpnZkNymStatus,
NymVpnAccountSummaryResponse, NymVpnDevicesResponse, NymVpnZkNym, NymVpnZkNym2,
NymVpnZkNymStatus,
},
types::{Device, VpnApiAccount},
};
Expand All @@ -23,7 +26,6 @@ use url::Url;

use crate::{
commands::{
self,
zknym::{
construct_zk_nym_request_data, poll_zk_nym, request_zk_nym, PollingResult,
ZkNymRequestData,
Expand Down Expand Up @@ -177,18 +179,44 @@ where

async fn import_zk_nym(
&mut self,
response: NymVpnZkNym,
response: NymVpnZkNym2,
ticketbook_type: TicketType,
request_info: RequestInfo,
) -> Result<(), Error> {
tracing::info!("Importing zk-nym: {:#?}", response);

let account = self.account_storage.load_account().await?;
let master_verification_key = self

let Some(ref blinded_shares) = response.blinded_shares else {
return Err(Error::MissingBlindedShares);
};

let master_verification_key = match self
.credential_storage
.get_master_verification_key(response.epoch.unwrap())
.get_master_verification_key(blinded_shares.epoch_id)
.await?
.unwrap();
{
Some(master_verification_key) => master_verification_key.clone(),
None => {
let vk_bs58 = blinded_shares
.master_verification_key
.as_ref()
.unwrap()
.bs58_encoded_key
.clone();
let vk = VerificationKeyAuth::try_from_bs58(&vk_bs58).unwrap();
let epoch_verification_key = EpochVerificationKey {
epoch_id: blinded_shares.epoch_id,
key: vk.clone(),
};
self.credential_storage
.insert_master_verification_key(&epoch_verification_key)
.await?;
vk
}
};

let issued_ticketbook = commands::zknym::unblind_and_aggregate(
let issued_ticketbook = crate::commands::zknym::unblind_and_aggregate(
response,
ticketbook_type,
request_info,
Expand Down Expand Up @@ -228,7 +256,7 @@ where
.collect::<Vec<_>>();

// For testing: uncomment to only request zk-nyms for a specific ticket type
//let ticket_types_needed_to_request = vec![TicketType::V1MixnetEntry];
let ticket_types_needed_to_request = vec![TicketType::V1MixnetEntry];

// Request zk-nyms for each ticket type that we need
let responses = futures::stream::iter(ticket_types_needed_to_request)
Expand Down Expand Up @@ -338,6 +366,26 @@ where
Ok(())
}

async fn handle_get_zk_nyms_available_for_download(&self) -> Result<(), Error> {
tracing::info!("Getting zk-nyms available for download from API");

let account = self.account_storage.load_account().await?;
let device = self.account_storage.load_device_keys().await?;

let reported_device_zk_nyms = self
.vpn_api_client
.get_zk_nyms_available_for_download(&account, &device)
.await
.map_err(Error::GetZkNyms)?;

tracing::info!("The device as the following zk-nyms available to download:");
// TODO: pagination
for zk_nym in &reported_device_zk_nyms.items {
tracing::info!("{:?}", zk_nym);
}
Ok(())
}

// Once we finish polling the result of the zk-nym request, we now import the zk-nym into the
// local credential store
async fn handle_polling_result(&mut self, result: Result<PollingResult, JoinError>) {
Expand Down Expand Up @@ -402,7 +450,10 @@ where
AccountCommand::UpdateAccountState => self.handle_update_account_state().await,
AccountCommand::RegisterDevice => self.handle_register_device().await,
AccountCommand::RequestZkNym => self.handle_request_zk_nym().await,
AccountCommand::GetDeviceZkNym => self.handle_get_device_zk_nym().await,
// AccountCommand::GetDeviceZkNym => self.handle_get_device_zk_nym().await,
AccountCommand::GetDeviceZkNym => {
self.handle_get_zk_nyms_available_for_download().await
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions nym-vpn-core/crates/nym-vpn-account-controller/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ pub enum Error {

#[error(transparent)]
NymSdk(#[from] nym_sdk::Error),

#[error("succesfull zknym response is missing blinded shares")]
MissingBlindedShares,
}

impl Error {
Expand Down
1 change: 1 addition & 0 deletions nym-vpn-core/crates/nym-vpn-api-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ itertools.workspace = true
nym-compact-ecash.workspace = true
nym-config.workspace = true
nym-contracts-common.workspace = true
nym-credential-proxy-requests.workspace = true
nym-credentials-interface.workspace = true
nym-crypto = { workspace = true, features = ["asymmetric"] }
nym-ecash-time.workspace = true
Expand Down
71 changes: 63 additions & 8 deletions nym-vpn-core/crates/nym-vpn-api-client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ use crate::{
RegisterDeviceRequestBody, RequestZkNymRequestBody,
},
response::{
NymDirectoryGatewayCountriesResponse, NymDirectoryGatewaysResponse, NymVpnAccountResponse,
NymVpnAccountSummaryResponse, NymVpnDevice, NymVpnDevicesResponse, NymVpnSubscription,
NymVpnSubscriptionResponse, NymVpnSubscriptionsResponse, NymVpnZkNym, NymVpnZkNymResponse,
NymDirectoryGatewayCountriesResponse, NymDirectoryGatewaysResponse, NymVpnAccountResponse, NymVpnAccountSummaryResponse, NymVpnDevice, NymVpnDevicesResponse, NymVpnSubscription, NymVpnSubscriptionResponse, NymVpnSubscriptionsResponse, NymVpnZkNym, NymVpnZkNym2, NymVpnZkNymResponse
},
routes,
types::{Device, GatewayMinPerformance, GatewayType, VpnApiAccount},
Expand Down Expand Up @@ -78,6 +76,37 @@ impl VpnApiClient {
nym_http_api_client::parse_response(response, false).await
}

async fn get_authorized_debug<T, E>(
&self,
path: PathSegments<'_>,
account: &VpnApiAccount,
device: Option<&Device>,
) -> std::result::Result<T, HttpClientError<E>>
where
T: DeserializeOwned,
E: fmt::Display + DeserializeOwned,
{
let request = self
.inner
.create_get_request(path, NO_PARAMS)
.bearer_auth(account.jwt().to_string());

let request = match device {
Some(device) => request.header(
DEVICE_AUTHORIZATION_HEADER,
format!("Bearer {}", device.jwt()),
),
None => request,
};

let response = request.send().await?;
let r = response.text().await;
tracing::info!("Response: {:#?}", r);
todo!();

nym_http_api_client::parse_response(response, false).await
}

async fn get_json_with_retry<T, K, V, E>(
&self,
path: PathSegments<'_>,
Expand Down Expand Up @@ -125,6 +154,9 @@ impl VpnApiClient {
};

let response = request.send().await?;
// let r = response.text().await;
// tracing::info!("Response: {:#?}", r);
// todo!();

nym_http_api_client::parse_response(response, false).await
}
Expand Down Expand Up @@ -305,11 +337,11 @@ impl VpnApiClient {
.map_err(VpnApiClientError::FailedToRequestZkNym)
}

pub async fn get_active_zk_nym(
pub async fn get_zk_nyms_available_for_download(
&self,
account: &VpnApiAccount,
device: &Device,
) -> Result<NymVpnZkNym> {
) -> Result<NymVpnZkNymResponse> {
self.get_authorized(
&[
routes::PUBLIC,
Expand All @@ -319,21 +351,44 @@ impl VpnApiClient {
routes::DEVICE,
&device.identity_key().to_string(),
routes::ZKNYM,
routes::ACTIVE,
routes::AVAILABLE,
],
account,
Some(device),
)
.await
.map_err(VpnApiClientError::FailedToGetActiveZkNym)
.map_err(VpnApiClientError::FailedToGetDeviceZkNyms)
}

//pub async fn get_active_zk_nym(
// &self,
// account: &VpnApiAccount,
// device: &Device,
//) -> Result<NymVpnZkNym> {
// self.get_authorized(
// &[
// routes::PUBLIC,
// routes::V1,
// routes::ACCOUNT,
// &account.id(),
// routes::DEVICE,
// &device.identity_key().to_string(),
// routes::ZKNYM,
// routes::ACTIVE,
// ],
// account,
// Some(device),
// )
// .await
// .map_err(VpnApiClientError::FailedToGetActiveZkNym)
//}

pub async fn get_zk_nym_by_id(
&self,
account: &VpnApiAccount,
device: &Device,
id: &str,
) -> Result<NymVpnZkNym> {
) -> Result<NymVpnZkNym2> {
self.get_authorized(
&[
routes::PUBLIC,
Expand Down
Loading

0 comments on commit 695f324

Please sign in to comment.