diff --git a/api.md b/api.md index 353538b..93855e3 100644 --- a/api.md +++ b/api.md @@ -312,8 +312,9 @@ curl -sLfS 'http://localhost:9000/metrics' ### Admin - Score upload ```bash -curl -sLfS 'http://localhost:8000/admin/scores?epoch=1&components=a,b,c&component_weights=1,2,3.34&ui_id=fw3' -X POST \ +curl -sLfS 'http://localhost:8000/admin/scores?epoch=1&components=COMMISSION_ADJUSTED_CREDITS,GRACE_SKIP_RATE,DC_CONCENTRATION&component_weights=10,1,2&ui_id=fw3' -X POST \ -H 'Content-Type: multipart/form-data' \ + -H 'Authorization: foo' \ --form 'scores_csv=@./scores.csv' ``` diff --git a/api/src/handlers/validator_score_breakdown.rs b/api/src/handlers/validator_score_breakdown.rs index a952b7d..20ac45b 100644 --- a/api/src/handlers/validator_score_breakdown.rs +++ b/api/src/handlers/validator_score_breakdown.rs @@ -26,6 +26,7 @@ pub struct ScoreBreakdown { pub ui_hints: Vec, pub component_scores: Vec, pub component_ranks: Vec, + pub component_values: Vec>, pub component_weights: Vec, pub components: Vec, pub eligible_stake_algo: bool, @@ -78,6 +79,7 @@ pub async fn handler( ui_hints, component_scores, component_ranks, + component_values, eligible_stake_algo, eligible_stake_mnde, eligible_stake_msol, @@ -112,6 +114,7 @@ pub async fn handler( ui_hints, component_scores, component_ranks, + component_values, component_weights, components, eligible_stake_algo, diff --git a/migrations/0005-scores-component-values.sql b/migrations/0005-scores-component-values.sql new file mode 100644 index 0000000..b15dacf --- /dev/null +++ b/migrations/0005-scores-component-values.sql @@ -0,0 +1,2 @@ +alter table scores add column "component_values" text[] NOT NULL default '{NULL,NULL,NULL}'::text[]; +alter table scores alter column "component_values" drop default; diff --git a/store/src/dto.rs b/store/src/dto.rs index e0e1e21..a4a90b9 100644 --- a/store/src/dto.rs +++ b/store/src/dto.rs @@ -290,6 +290,9 @@ pub struct ValidatorScoringCsvRow { pub normalized_dc_concentration: f64, pub normalized_grace_skip_rate: f64, pub normalized_adjusted_credits: f64, + pub avg_dc_concentration: f64, + pub avg_grace_skip_rate: f64, + pub avg_adjusted_credits: f64, pub rank_dc_concentration: i32, pub rank_grace_skip_rate: i32, pub rank_adjusted_credits: i32, @@ -306,6 +309,7 @@ pub struct ValidatorScoreRecord { pub ui_hints: Vec, pub component_scores: Vec, pub component_ranks: Vec, + pub component_values: Vec>, pub eligible_stake_algo: bool, pub eligible_stake_mnde: bool, pub eligible_stake_msol: bool, diff --git a/store/src/utils.rs b/store/src/utils.rs index de3f318..e19e784 100644 --- a/store/src/utils.rs +++ b/store/src/utils.rs @@ -1,7 +1,8 @@ use crate::dto::{ BlockProductionStats, ClusterStats, CommissionRecord, DCConcentrationStats, ScoringRunRecord, UptimeRecord, ValidatorAggregatedFlat, ValidatorEpochStats, ValidatorRecord, - ValidatorScoreRecord, ValidatorWarning, ValidatorsAggregated, VersionRecord, + ValidatorScoreRecord, ValidatorScoringCsvRow, ValidatorWarning, ValidatorsAggregated, + VersionRecord, }; use rust_decimal::prelude::*; use std::collections::{HashMap, HashSet}; @@ -757,6 +758,7 @@ pub async fn load_scores( ui_hints, component_scores, component_ranks, + component_values, eligible_stake_algo, eligible_stake_mnde, eligible_stake_msol, @@ -785,6 +787,7 @@ pub async fn load_scores( ui_hints: row.get("ui_hints"), component_scores: row.get("component_scores"), component_ranks: row.get("component_ranks"), + component_values: row.get("component_values"), eligible_stake_algo: row.get("eligible_stake_algo"), eligible_stake_mnde: row.get("eligible_stake_mnde"), eligible_stake_msol: row.get("eligible_stake_msol"), @@ -1042,6 +1045,21 @@ pub async fn load_validators_aggregated_flat( Ok(validators) } +fn map_to_ordered_component_values( + components: &Vec<&str>, + row: &ValidatorScoringCsvRow, +) -> Vec> { + components + .iter() + .map(|component| match *component { + "COMMISSION_ADJUSTED_CREDITS" => Some(row.avg_adjusted_credits.to_string()), + "GRACE_SKIP_RATE" => Some(row.avg_grace_skip_rate.to_string()), + "DC_CONCENTRATION" => Some(row.avg_dc_concentration.to_string()), + _ => None, + }) + .collect() +} + pub async fn store_scoring( mut psql_client: &mut Client, epoch: i32, @@ -1090,6 +1108,16 @@ pub async fn store_scoring( }) .collect(); + let component_values_by_vote_account: HashMap<_, _> = scores + .iter() + .map(|row| { + ( + row.vote_account.clone(), + map_to_ordered_component_values(&components, row), + ) + }) + .collect(); + let ui_hints_parsed: HashMap<_, Vec<&str>> = scores .iter() .map(|row| { @@ -1107,7 +1135,7 @@ pub async fn store_scoring( for chunk in scores.chunks(500) { let mut query = InsertQueryCombiner::new( "scores".to_string(), - "vote_account, score, component_scores, component_ranks, rank, ui_hints, eligible_stake_algo, eligible_stake_mnde, eligible_stake_msol, target_stake_algo, target_stake_mnde, target_stake_msol, scoring_run_id".to_string(), + "vote_account, score, component_scores, component_ranks, component_values, rank, ui_hints, eligible_stake_algo, eligible_stake_mnde, eligible_stake_msol, target_stake_algo, target_stake_mnde, target_stake_msol, scoring_run_id".to_string(), ); for row in chunk { let mut params: Vec<&(dyn ToSql + Sync)> = vec![ @@ -1119,6 +1147,9 @@ pub async fn store_scoring( component_ranks_by_vote_account .get(&row.vote_account) .unwrap(), + component_values_by_vote_account + .get(&row.vote_account) + .unwrap(), &row.rank, ui_hints_parsed.get(&row.vote_account).unwrap(), &row.eligible_stake_algo,