From 2cf5e48d8e5c7e837ea4ca3f11d8934bacfa9e1d Mon Sep 17 00:00:00 2001 From: Aravinth Manivannan Date: Fri, 30 Jun 2023 03:19:38 +0530 Subject: [PATCH] feat: log pow performance stats while pow verification --- src/api/v1/pow/verify_pow.rs | 117 ++++++++++++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 2 deletions(-) diff --git a/src/api/v1/pow/verify_pow.rs b/src/api/v1/pow/verify_pow.rs index 94b9b038..f7efd541 100644 --- a/src/api/v1/pow/verify_pow.rs +++ b/src/api/v1/pow/verify_pow.rs @@ -32,6 +32,27 @@ pub struct ValidationToken { pub token: String, } +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct ApiWork { + pub string: String, + pub result: String, + pub nonce: u64, + pub key: String, + pub time: Option, + pub worker_type: Option, +} + +impl From for Work { + fn from(value: ApiWork) -> Self { + Self { + string: value.string, + nonce: value.nonce, + result: value.result, + key: value.key, + } + } +} + // API keys are mcaptcha actor names /// route handler that verifies PoW and issues a solution token @@ -39,7 +60,7 @@ pub struct ValidationToken { #[my_codegen::post(path = "V1_API_ROUTES.pow.verify_pow()")] pub async fn verify_pow( req: HttpRequest, - payload: web::Json, + payload: web::Json, data: AppData, ) -> ServiceResult { #[cfg(not(test))] @@ -52,8 +73,19 @@ pub async fn verify_pow( let ip = "127.0.1.1".into(); let key = payload.key.clone(); - let res = data.captcha.verify_pow(payload.into_inner(), ip).await?; + let payload = payload.into_inner(); + let worker_type = payload.worker_type.clone(); + let time = payload.time; + let (res, difficulty_factor) = data.captcha.verify_pow(payload.into(), ip).await?; data.stats.record_solve(&data, &key).await?; + if time.is_some() && worker_type.is_some() { + let analytics = db_core::CreatePerformanceAnalytics { + difficulty_factor, + time: time.unwrap(), + worker_type: worker_type.unwrap(), + }; + data.db.analysis_save(&key, &analytics).await?; + } let payload = ValidationToken { token: res }; Ok(HttpResponse::Ok().json(payload)) } @@ -81,6 +113,81 @@ pub mod tests { verify_pow_works(data).await; } + #[actix_rt::test] + async fn verify_analytics_pow_works_pg() { + let data = crate::tests::pg::get_data().await; + verify_analytics_pow_works(data).await; + } + + #[actix_rt::test] + async fn verify_analytics_pow_works_maria() { + let data = crate::tests::maria::get_data().await; + verify_analytics_pow_works(data).await; + } + + pub async fn verify_analytics_pow_works(data: ArcData) { + const NAME: &str = "powanalyticsuser"; + const PASSWORD: &str = "testingpas"; + const EMAIL: &str = "powanalyticsuser@a.com"; + let data = &data; + + delete_user(data, NAME).await; + + register_and_signin(data, NAME, EMAIL, PASSWORD).await; + let (_, _signin_resp, token_key) = add_levels_util(data, NAME, PASSWORD).await; + let app = get_app!(data).await; + + let get_config_payload = GetConfigPayload { + key: token_key.key.clone(), + }; + + // update and check changes + + let get_config_resp = test::call_service( + &app, + post_request!(&get_config_payload, V1_API_ROUTES.pow.get_config) + .to_request(), + ) + .await; + assert_eq!(get_config_resp.status(), StatusCode::OK); + let config: PoWConfig = test::read_body_json(get_config_resp).await; + + let pow = pow_sha256::ConfigBuilder::default() + .salt(config.salt) + .build() + .unwrap(); + let work = pow + .prove_work(&config.string.clone(), config.difficulty_factor) + .unwrap(); + + let work = ApiWork { + string: config.string.clone(), + result: work.result, + nonce: work.nonce, + key: token_key.key.clone(), + time: Some(100), + worker_type: Some("wasm".into()), + }; + + let pow_verify_resp = test::call_service( + &app, + post_request!(&work, V1_API_ROUTES.pow.verify_pow).to_request(), + ) + .await; + assert_eq!(pow_verify_resp.status(), StatusCode::OK); + let limit = 50; + let offset = 0; + let mut analytics = data + .db + .analytics_fetch(&token_key.key, limit, offset) + .await + .unwrap(); + assert_eq!(analytics.len(), 1); + let a = analytics.pop().unwrap(); + assert_eq!(a.time, work.time.unwrap()); + assert_eq!(a.worker_type, work.worker_type.unwrap()); + } + pub async fn verify_pow_works(data: ArcData) { const NAME: &str = "powverifyusr"; const PASSWORD: &str = "testingpas"; @@ -129,6 +236,12 @@ pub mod tests { ) .await; assert_eq!(pow_verify_resp.status(), StatusCode::OK); + assert!(data + .db + .analytics_fetch(&token_key.key, 50, 0) + .await + .unwrap() + .is_empty()); let string_not_found = test::call_service( &app,