From 622bb6beb29a74a92ed725891205bd7c1d2d95e0 Mon Sep 17 00:00:00 2001 From: Mateusz Jasiuk Date: Mon, 3 Jun 2024 16:38:08 +0200 Subject: [PATCH] feat: revealed pks --- Cargo.toml | 2 +- chain/src/main.rs | 21 ++++-- chain/src/repository/mod.rs | 1 + chain/src/repository/revealed_pk.rs | 22 ++++++ docker-compose.yml | 3 +- .../down.sql | 3 + .../2024-06-03-084149_init_revealed_pk/up.sql | 9 +++ orm/src/lib.rs | 1 + orm/src/revealed_pk.rs | 23 ++++++ orm/src/schema.rs | 9 +++ shared/src/block.rs | 20 ++++++ shared/src/lib.rs | 1 + shared/src/public_key.rs | 9 +++ shared/src/transaction.rs | 2 + swagger.yml | 24 ++++++- webserver/Cargo.toml | 1 + webserver/run.sh | 2 +- webserver/src/app.rs | 10 ++- webserver/src/config.rs | 3 + webserver/src/error/api.rs | 4 ++ webserver/src/error/mod.rs | 1 + webserver/src/error/revealed_pk.rs | 30 ++++++++ webserver/src/handler/mod.rs | 1 + webserver/src/handler/pk.rs | 24 +++++++ webserver/src/repository/mod.rs | 1 + webserver/src/repository/revealed_pk.rs | 69 ++++++++++++++++++ webserver/src/response/mod.rs | 1 + webserver/src/response/revealed_pk.rs | 16 +++++ webserver/src/service/mod.rs | 1 + webserver/src/service/revealed_pk.rs | 70 +++++++++++++++++++ webserver/src/state/common.rs | 9 ++- 31 files changed, 381 insertions(+), 12 deletions(-) create mode 100644 chain/src/repository/revealed_pk.rs create mode 100644 orm/migrations/2024-06-03-084149_init_revealed_pk/down.sql create mode 100644 orm/migrations/2024-06-03-084149_init_revealed_pk/up.sql create mode 100644 orm/src/revealed_pk.rs create mode 100644 shared/src/public_key.rs create mode 100644 webserver/src/error/revealed_pk.rs create mode 100644 webserver/src/handler/pk.rs create mode 100644 webserver/src/repository/revealed_pk.rs create mode 100644 webserver/src/response/revealed_pk.rs create mode 100644 webserver/src/service/revealed_pk.rs diff --git a/Cargo.toml b/Cargo.toml index 8f9b39fe5..5b37817f0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,7 +40,7 @@ chrono = { version = "0.4.30", features = ["serde"] } async-trait = "0.1.73" anyhow = "1.0.75" namada_core = { git = "https://github.com/anoma/namada", tag = "v0.37.0" } -namada_sdk = { git = "https://github.com/anoma/namada", tag = "v0.37.0" } +namada_sdk = { git = "https://github.com/anoma/namada", tag = "v0.37.0", default-features = false, features = ["tendermint-rpc", "std", "async-send", "download-params", "rand"] } namada_tx = { git = "https://github.com/anoma/namada", tag = "v0.37.0" } namada_governance = { git = "https://github.com/anoma/namada", tag = "v0.37.0" } namada_ibc = { git = "https://github.com/anoma/namada", tag = "v0.37.0" } diff --git a/chain/src/main.rs b/chain/src/main.rs index 42737e46d..78be5d1fd 100644 --- a/chain/src/main.rs +++ b/chain/src/main.rs @@ -177,6 +177,12 @@ async fn crawling_fn( .into_rpc_error()?; tracing::info!("Updating unbonds for {} addresses", unbonds.len()); + let revealed_pks = block.revealed_pks(); + tracing::info!( + "Updating revealed pks for {} addresses", + revealed_pks.len() + ); + let metadata_change = block.validator_metadata(); let reward_claimers = block.pos_rewards(); @@ -204,11 +210,6 @@ async fn crawling_fn( repository::pos::insert_bonds(transaction_conn, bonds)?; repository::pos::insert_unbonds(transaction_conn, unbonds)?; - repository::crawler::insert_crawler_state( - transaction_conn, - crawler_state, - )?; - repository::pos::delete_claimed_rewards( transaction_conn, reward_claimers, @@ -219,6 +220,16 @@ async fn crawling_fn( metadata_change, )?; + repository::revealed_pk::insert_revealed_pks( + transaction_conn, + revealed_pks, + )?; + + repository::crawler::insert_crawler_state( + transaction_conn, + crawler_state, + )?; + anyhow::Ok(()) }) }) diff --git a/chain/src/repository/mod.rs b/chain/src/repository/mod.rs index 0de5524b6..c811ef582 100644 --- a/chain/src/repository/mod.rs +++ b/chain/src/repository/mod.rs @@ -2,3 +2,4 @@ pub mod balance; pub mod crawler; pub mod gov; pub mod pos; +pub mod revealed_pk; diff --git a/chain/src/repository/revealed_pk.rs b/chain/src/repository/revealed_pk.rs new file mode 100644 index 000000000..69c433aa2 --- /dev/null +++ b/chain/src/repository/revealed_pk.rs @@ -0,0 +1,22 @@ +use anyhow::Context; +use diesel::{PgConnection, RunQueryDsl}; +use orm::{revealed_pk::RevealedPkInsertDb, schema::revealed_pk}; +use shared::{id::Id, public_key::PublicKey}; + +pub fn insert_revealed_pks( + transaction_conn: &mut PgConnection, + revealed_pks: Vec<(PublicKey, Id)>, +) -> anyhow::Result<()> { + diesel::insert_into(revealed_pk::table) + .values::<&Vec>( + &revealed_pks + .into_iter() + .map(|(pk, address)| RevealedPkInsertDb::from(pk, address)) + .collect::>(), + ) + .on_conflict_do_nothing() + .execute(transaction_conn) + .context("Failed to update balances in db")?; + + anyhow::Ok(()) +} diff --git a/docker-compose.yml b/docker-compose.yml index 0b7e1f0fe..b2cef3a10 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -65,10 +65,11 @@ services: environment: DATABASE_URL: postgres://postgres:password@postgres:5435/namada-indexer CACHE_URL: redis://dragonfly:6379 + TENDERMINT_URL: http://localhost:27657 healthcheck: test: curl --fail http://localhost:5000/health || exit 1 interval: 15s timeout: 10s retries: 3 start_period: 10s - \ No newline at end of file + diff --git a/orm/migrations/2024-06-03-084149_init_revealed_pk/down.sql b/orm/migrations/2024-06-03-084149_init_revealed_pk/down.sql new file mode 100644 index 000000000..c73c0034e --- /dev/null +++ b/orm/migrations/2024-06-03-084149_init_revealed_pk/down.sql @@ -0,0 +1,3 @@ +-- This file should undo anything in `up.sql` + +DROP TABLE IF EXISTS revealed_pk; diff --git a/orm/migrations/2024-06-03-084149_init_revealed_pk/up.sql b/orm/migrations/2024-06-03-084149_init_revealed_pk/up.sql new file mode 100644 index 000000000..28cffbfdd --- /dev/null +++ b/orm/migrations/2024-06-03-084149_init_revealed_pk/up.sql @@ -0,0 +1,9 @@ +-- Your SQL goes here + +CREATE TABLE revealed_pk ( + id SERIAL PRIMARY KEY, + address VARCHAR NOT NULL, + pk VARCHAR NOT NULL +); + +ALTER TABLE revealed_pk ADD UNIQUE (address, pk); diff --git a/orm/src/lib.rs b/orm/src/lib.rs index 078f8f44f..3fb61687a 100644 --- a/orm/src/lib.rs +++ b/orm/src/lib.rs @@ -6,6 +6,7 @@ pub mod governance_proposal; pub mod governance_votes; pub mod migrations; pub mod pos_rewards; +pub mod revealed_pk; pub mod schema; pub mod unbond; pub mod validators; diff --git a/orm/src/revealed_pk.rs b/orm/src/revealed_pk.rs new file mode 100644 index 000000000..618068a3b --- /dev/null +++ b/orm/src/revealed_pk.rs @@ -0,0 +1,23 @@ +use diesel::{Insertable, Queryable, Selectable}; +use shared::{id::Id, public_key::PublicKey}; + +use crate::schema::revealed_pk; + +#[derive(Insertable, Clone, Queryable, Selectable)] +#[diesel(table_name = revealed_pk)] +#[diesel(check_for_backend(diesel::pg::Pg))] +pub struct RevealedPkInsertDb { + pub pk: String, + pub address: String, +} + +pub type RevealedPkDb = RevealedPkInsertDb; + +impl RevealedPkInsertDb { + pub fn from(pk: PublicKey, address: Id) -> Self { + Self { + pk: pk.0, + address: address.to_string(), + } + } +} diff --git a/orm/src/schema.rs b/orm/src/schema.rs index e369545e9..00a74717b 100644 --- a/orm/src/schema.rs +++ b/orm/src/schema.rs @@ -95,6 +95,14 @@ diesel::table! { } } +diesel::table! { + revealed_pk (id) { + id -> Int4, + address -> Varchar, + pk -> Varchar, + } +} + diesel::table! { unbonds (id) { id -> Int4, @@ -134,6 +142,7 @@ diesel::allow_tables_to_appear_in_same_query!( governance_proposals, governance_votes, pos_rewards, + revealed_pk, unbonds, validators, ); diff --git a/shared/src/block.rs b/shared/src/block.rs index 713e733b0..c4c7527b9 100644 --- a/shared/src/block.rs +++ b/shared/src/block.rs @@ -2,6 +2,7 @@ use std::collections::{BTreeMap, HashSet}; use std::str::FromStr; use namada_sdk::borsh::BorshDeserialize; +use namada_sdk::key::common::PublicKey as NamadaPublicKey; use namada_tx::data::pos; use subtle_encoding::hex; use tendermint_rpc::endpoint::block::Response as TendermintBlockResponse; @@ -12,6 +13,7 @@ use crate::checksums::Checksums; use crate::header::BlockHeader; use crate::id::Id; use crate::proposal::{GovernanceProposal, GovernanceProposalKind}; +use crate::public_key::PublicKey; use crate::transaction::{Transaction, TransactionKind}; use crate::unbond::UnbondAddresses; use crate::utils::BalanceChange; @@ -486,4 +488,22 @@ impl Block { }) .collect() } + + pub fn revealed_pks(&self) -> Vec<(PublicKey, Id)> { + self.transactions + .iter() + .filter_map(|tx| match &tx.kind { + TransactionKind::RevealPk(data) => { + let namada_public_key = + NamadaPublicKey::try_from_slice(data).unwrap(); + + Some(( + PublicKey::from(namada_public_key.clone()), + Id::from(namada_public_key), + )) + } + _ => None, + }) + .collect() + } } diff --git a/shared/src/lib.rs b/shared/src/lib.rs index 82a6cc8c3..d97ebeca4 100644 --- a/shared/src/lib.rs +++ b/shared/src/lib.rs @@ -9,6 +9,7 @@ pub mod error; pub mod header; pub mod id; pub mod proposal; +pub mod public_key; pub mod rewards; pub mod transaction; pub mod unbond; diff --git a/shared/src/public_key.rs b/shared/src/public_key.rs new file mode 100644 index 000000000..53b3fa223 --- /dev/null +++ b/shared/src/public_key.rs @@ -0,0 +1,9 @@ +use namada_sdk::key::common::PublicKey as NamadaPublicKey; + +pub struct PublicKey(pub String); + +impl From for PublicKey { + fn from(pk: NamadaPublicKey) -> Self { + PublicKey(pk.to_string()) + } +} diff --git a/shared/src/transaction.rs b/shared/src/transaction.rs index f350ec42c..65131eca7 100644 --- a/shared/src/transaction.rs +++ b/shared/src/transaction.rs @@ -24,6 +24,7 @@ pub enum TransactionKind { InitProposal(Vec), MetadataChange(Vec), CommissionChange(Vec), + RevealPk(Vec), Unknown, } @@ -60,6 +61,7 @@ impl TransactionKind { "tx_commission_change" => { TransactionKind::CommissionChange(data.to_vec()) } + "tx_reveal_pk" => TransactionKind::RevealPk(data.to_vec()), _ => TransactionKind::Unknown, } } diff --git a/swagger.yml b/swagger.yml index d4a2efb8a..725950955 100644 --- a/swagger.yml +++ b/swagger.yml @@ -302,6 +302,24 @@ paths: items: $ref: '#/components/schemas/Balance' + /api/v1/revealed_public_key/{address}: + get: + summary: Get revealed public key for an address if exists + parameters: + - in: path + name: address + schema: + type: string + required: true + description: The address account + responses: + '200': + description: Revealed public key. + content: + application/json: + schema: + $ref: '#/components/schemas/RevealedPk' + components: schemas: Validator: @@ -384,7 +402,6 @@ components: type: object properties: validator: - type: object $ref: '#/components/schemas/Validator' amount: type: number @@ -453,4 +470,9 @@ components: total_items: type: integer minimum: 0 + RevealedPk: + type: object + properties: + publicKey: + type: string diff --git a/webserver/Cargo.toml b/webserver/Cargo.toml index 92ccff880..3ed8855e2 100644 --- a/webserver/Cargo.toml +++ b/webserver/Cargo.toml @@ -25,6 +25,7 @@ tokio.workspace = true tower.workspace = true tower-http.workspace = true tracing.workspace = true +namada_sdk.workspace = true tracing-subscriber.workspace = true serde.workspace = true serde_json.workspace = true diff --git a/webserver/run.sh b/webserver/run.sh index 07d58ef40..a61a5bd39 100755 --- a/webserver/run.sh +++ b/webserver/run.sh @@ -1 +1 @@ -cargo run -- --database-url postgres://postgres:password@0.0.0.0:5435/namada-indexer --cache-url redis://redis@0.0.0.0:6379 +cargo run -- --database-url postgres://postgres:password@0.0.0.0:5435/namada-indexer --cache-url redis://redis@0.0.0.0:6379 --tendermint-url http://127.0.0.1:27657 diff --git a/webserver/src/app.rs b/webserver/src/app.rs index 435dedb34..dfaf48706 100644 --- a/webserver/src/app.rs +++ b/webserver/src/app.rs @@ -9,6 +9,7 @@ use axum::routing::get; use axum::{BoxError, Json, Router}; use axum_trace_id::SetTraceIdLayer; use lazy_static::lazy_static; +use namada_sdk::tendermint_rpc::HttpClient; use serde_json::json; use tower::buffer::BufferLayer; use tower::limit::RateLimitLayer; @@ -20,7 +21,7 @@ use crate::appstate::AppState; use crate::config::AppConfig; use crate::handler::{ balance as balance_handlers, chain as chain_handlers, - governance as gov_handlers, pos as pos_handlers, + governance as gov_handlers, pk as pk_handlers, pos as pos_handlers, }; use crate::state::common::CommonState; @@ -37,9 +38,10 @@ impl ApplicationServer { let cache_url = config.cache_url.clone(); let app_state = AppState::new(db_url, cache_url); + let client = HttpClient::new(config.tendermint_url.as_str()).unwrap(); let routes = { - let common_state = CommonState::new(app_state.clone()); + let common_state = CommonState::new(client, app_state.clone()); Router::new() .route("/pos/validator", get(pos_handlers::get_validators)) @@ -82,6 +84,10 @@ impl ApplicationServer { "/account/:address", get(balance_handlers::get_address_balance), ) + .route( + "/revealed_public_key/:address", + get(pk_handlers::get_revealed_pk), + ) .route("/chain/sync", get(chain_handlers::sync_height)) .with_state(common_state) }; diff --git a/webserver/src/config.rs b/webserver/src/config.rs index c9ffe4753..9c652c7eb 100644 --- a/webserver/src/config.rs +++ b/webserver/src/config.rs @@ -17,4 +17,7 @@ pub struct AppConfig { #[clap(long, env)] pub rps: Option, + + #[clap(long, env)] + pub tendermint_url: String, } diff --git a/webserver/src/error/api.rs b/webserver/src/error/api.rs index cde31f6d5..d546a58f3 100644 --- a/webserver/src/error/api.rs +++ b/webserver/src/error/api.rs @@ -5,6 +5,7 @@ use thiserror::Error; use super::balance::BalanceError; use super::governance::GovernanceError; use super::pos::PoSError; +use super::revealed_pk::RevealedPkError; use crate::response::api::ApiErrorResponse; #[derive(Error, Debug)] @@ -15,6 +16,8 @@ pub enum ApiError { BalanceError(#[from] BalanceError), #[error(transparent)] GovernanceError(#[from] GovernanceError), + #[error(transparent)] + RevealedPkError(#[from] RevealedPkError), #[error("No chain parameters stored")] NoChainParameters, #[error("Invalid request header")] @@ -33,6 +36,7 @@ impl IntoResponse for ApiError { ApiError::PoSError(error) => error.into_response(), ApiError::BalanceError(error) => error.into_response(), ApiError::GovernanceError(error) => error.into_response(), + ApiError::RevealedPkError(error) => error.into_response(), ApiError::InvalidHeader => ApiErrorResponse::send( StatusCode::BAD_REQUEST.as_u16(), Some("Invalid Header".to_string()), diff --git a/webserver/src/error/mod.rs b/webserver/src/error/mod.rs index 1e1daa86f..e5828d668 100644 --- a/webserver/src/error/mod.rs +++ b/webserver/src/error/mod.rs @@ -2,3 +2,4 @@ pub mod api; pub mod balance; pub mod governance; pub mod pos; +pub mod revealed_pk; diff --git a/webserver/src/error/revealed_pk.rs b/webserver/src/error/revealed_pk.rs new file mode 100644 index 000000000..8b6255b1a --- /dev/null +++ b/webserver/src/error/revealed_pk.rs @@ -0,0 +1,30 @@ +use axum::http::StatusCode; +use axum::response::{IntoResponse, Response}; +use thiserror::Error; + +use crate::response::api::ApiErrorResponse; + +#[derive(Error, Debug)] +pub enum RevealedPkError { + #[error("Revealed public key {0} not found")] + NotFound(u64), + #[error("Database error: {0}")] + Database(String), + #[error("Rpc error: {0}")] + Rpc(String), + #[error("Unknown error: {0}")] + Unknown(String), +} + +impl IntoResponse for RevealedPkError { + fn into_response(self) -> Response { + let status_code = match self { + RevealedPkError::NotFound(_) => StatusCode::NOT_FOUND, + RevealedPkError::Unknown(_) + | RevealedPkError::Database(_) + | RevealedPkError::Rpc(_) => StatusCode::INTERNAL_SERVER_ERROR, + }; + + ApiErrorResponse::send(status_code.as_u16(), Some(self.to_string())) + } +} diff --git a/webserver/src/handler/mod.rs b/webserver/src/handler/mod.rs index aa95e0d78..c75163b41 100644 --- a/webserver/src/handler/mod.rs +++ b/webserver/src/handler/mod.rs @@ -1,4 +1,5 @@ pub mod balance; pub mod chain; pub mod governance; +pub mod pk; pub mod pos; diff --git a/webserver/src/handler/pk.rs b/webserver/src/handler/pk.rs new file mode 100644 index 000000000..43f5056e9 --- /dev/null +++ b/webserver/src/handler/pk.rs @@ -0,0 +1,24 @@ +use axum::extract::{Path, State}; +use axum::http::HeaderMap; +use axum::Json; +use axum_macros::debug_handler; +use axum_trace_id::TraceId; + +use crate::error::api::ApiError; +use crate::response::revealed_pk::RevealedPk; +use crate::state::common::CommonState; + +#[debug_handler] +pub async fn get_revealed_pk( + _trace_id: TraceId, + _headers: HeaderMap, + Path(address): Path, + State(state): State, +) -> Result, ApiError> { + let revealed_pk = state + .revealed_pk_service + .get_revealed_pk_by_address(&state.client, address) + .await?; + + Ok(Json(revealed_pk)) +} diff --git a/webserver/src/repository/mod.rs b/webserver/src/repository/mod.rs index 5310da139..a5a54be62 100644 --- a/webserver/src/repository/mod.rs +++ b/webserver/src/repository/mod.rs @@ -2,4 +2,5 @@ pub mod balance; pub mod chain; pub mod governance; pub mod pos; +pub mod revealed_pk; pub mod utils; diff --git a/webserver/src/repository/revealed_pk.rs b/webserver/src/repository/revealed_pk.rs new file mode 100644 index 000000000..a03ed5751 --- /dev/null +++ b/webserver/src/repository/revealed_pk.rs @@ -0,0 +1,69 @@ +use axum::async_trait; +use diesel::{ExpressionMethods, QueryDsl, RunQueryDsl, SelectableHelper}; +use orm::revealed_pk::{RevealedPkDb, RevealedPkInsertDb}; +use orm::schema::revealed_pk; + +use crate::appstate::AppState; + +#[derive(Clone)] +pub struct RevealedPkRepo { + pub(crate) app_state: AppState, +} + +#[async_trait] +pub trait PkRepoTrait { + fn new(app_state: AppState) -> Self; + + async fn get_revealed_pk_by_address( + &self, + address: String, + ) -> Result, String>; + + async fn insert_revealed_pk( + &self, + address: RevealedPkInsertDb, + ) -> Result<(), String>; +} + +#[async_trait] +impl PkRepoTrait for RevealedPkRepo { + fn new(app_state: AppState) -> Self { + Self { app_state } + } + + async fn get_revealed_pk_by_address( + &self, + address: String, + ) -> Result, String> { + let conn = self.app_state.get_db_connection().await; + + conn.interact(move |conn| { + revealed_pk::table + .filter(revealed_pk::dsl::address.eq(address)) + .select(RevealedPkDb::as_select()) + .first(conn) + .ok() + }) + .await + .map_err(|e| e.to_string()) + } + + async fn insert_revealed_pk( + &self, + revealed_pk: RevealedPkInsertDb, + ) -> Result<(), String> { + let conn = self.app_state.get_db_connection().await; + + conn.interact(move |conn| -> Result<(), String> { + diesel::insert_into(revealed_pk::table) + .values::>(vec![revealed_pk]) + .on_conflict_do_nothing() + .execute(conn) + .map_err(|e| e.to_string())?; + + Ok(()) + }) + .await + .map_err(|e| e.to_string())? + } +} diff --git a/webserver/src/response/mod.rs b/webserver/src/response/mod.rs index 381e887e3..e756ce66e 100644 --- a/webserver/src/response/mod.rs +++ b/webserver/src/response/mod.rs @@ -2,4 +2,5 @@ pub mod api; pub mod balance; pub mod governance; pub mod pos; +pub mod revealed_pk; pub mod utils; diff --git a/webserver/src/response/revealed_pk.rs b/webserver/src/response/revealed_pk.rs new file mode 100644 index 000000000..0c40d0aa9 --- /dev/null +++ b/webserver/src/response/revealed_pk.rs @@ -0,0 +1,16 @@ +use orm::revealed_pk::RevealedPkDb; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct RevealedPk { + pub public_key: Option, +} + +impl From for RevealedPk { + fn from(value: RevealedPkDb) -> Self { + Self { + public_key: Some(value.pk), + } + } +} diff --git a/webserver/src/service/mod.rs b/webserver/src/service/mod.rs index 5310da139..a5a54be62 100644 --- a/webserver/src/service/mod.rs +++ b/webserver/src/service/mod.rs @@ -2,4 +2,5 @@ pub mod balance; pub mod chain; pub mod governance; pub mod pos; +pub mod revealed_pk; pub mod utils; diff --git a/webserver/src/service/revealed_pk.rs b/webserver/src/service/revealed_pk.rs new file mode 100644 index 000000000..67ef80176 --- /dev/null +++ b/webserver/src/service/revealed_pk.rs @@ -0,0 +1,70 @@ +use std::str::FromStr; + +use crate::appstate::AppState; +use crate::error::revealed_pk::RevealedPkError; +use crate::repository::revealed_pk::{PkRepoTrait, RevealedPkRepo}; +use crate::response::revealed_pk::RevealedPk; + +use namada_sdk::address::Address as NamadaAddress; +use namada_sdk::rpc; +use namada_sdk::tendermint_rpc::HttpClient; +use orm::revealed_pk::RevealedPkInsertDb; + +#[derive(Clone)] +pub struct RevealedPkService { + pub revealed_pk_repo: RevealedPkRepo, +} + +impl RevealedPkService { + pub fn new(app_state: AppState) -> Self { + Self { + revealed_pk_repo: RevealedPkRepo::new(app_state), + } + } + + pub async fn get_revealed_pk_by_address( + &self, + client: &HttpClient, + address: String, + ) -> Result { + // We look for a revealed public key in the database + let revealed_pk_db = self + .revealed_pk_repo + .get_revealed_pk_by_address(address.clone()) + .await + .map_err(RevealedPkError::Database)?; + + match revealed_pk_db { + // If we find a revealed public key in the database, we return it + Some(revealed_pk_db) => Ok(RevealedPk::from(revealed_pk_db)), + // If we don't find a revealed public key in the database, we look for it in the + // storage + None => { + let address = + NamadaAddress::from_str(&address).expect("Invalid address"); + + let public_key = rpc::get_public_key_at(client, &address, 0) + .await + .map_err(|e| RevealedPkError::Rpc(e.to_string()))?; + + // If we find a public key in the storage, we insert it in the database + if let Some(public_key) = public_key.clone() { + // TODO: maybe better to create it using strcuts from shared + let revealed_pk_db = RevealedPkInsertDb { + pk: public_key.to_string(), + address: address.to_string(), + }; + + self.revealed_pk_repo + .insert_revealed_pk(revealed_pk_db) + .await + .map_err(RevealedPkError::Database)?; + }; + + Ok(RevealedPk { + public_key: public_key.map(|pk| pk.to_string()), + }) + } + } + } +} diff --git a/webserver/src/state/common.rs b/webserver/src/state/common.rs index 27844d3f1..57561202d 100644 --- a/webserver/src/state/common.rs +++ b/webserver/src/state/common.rs @@ -1,8 +1,11 @@ +use namada_sdk::tendermint_rpc::HttpClient; + use crate::appstate::AppState; use crate::service::balance::BalanceService; use crate::service::chain::ChainService; use crate::service::governance::GovernanceService; use crate::service::pos::PosService; +use crate::service::revealed_pk::RevealedPkService; #[derive(Clone)] pub struct CommonState { @@ -10,15 +13,19 @@ pub struct CommonState { pub gov_service: GovernanceService, pub balance_service: BalanceService, pub chain_service: ChainService, + pub revealed_pk_service: RevealedPkService, + pub client: HttpClient, } impl CommonState { - pub fn new(data: AppState) -> Self { + pub fn new(client: HttpClient, data: AppState) -> Self { Self { pos_service: PosService::new(data.clone()), gov_service: GovernanceService::new(data.clone()), balance_service: BalanceService::new(data.clone()), chain_service: ChainService::new(data.clone()), + revealed_pk_service: RevealedPkService::new(data.clone()), + client, } } }