diff --git a/src/config/deployed/mod.rs b/src/config/deployed/mod.rs index 7f9cb038..871d36c9 100644 --- a/src/config/deployed/mod.rs +++ b/src/config/deployed/mod.rs @@ -27,6 +27,7 @@ pub struct DeployedConfiguration { pub project_id: ProjectId, /// Relay URL e.g. https://relay.walletconnect.com pub relay_url: Url, + pub relay_public_key: String, pub notify_url: Url, pub registry_url: Url, @@ -88,6 +89,7 @@ pub fn get_configuration() -> Result { keypair_seed: config.keypair_seed, project_id: config.project_id, relay_url: config.relay_url, + relay_public_key: config.relay_public_key, notify_url: config.notify_url, registry_url: config.registry_url, registry_auth_token: config.registry_auth_token, diff --git a/src/config/local.rs b/src/config/local.rs index 77f3edcb..9986d2ee 100644 --- a/src/config/local.rs +++ b/src/config/local.rs @@ -71,10 +71,17 @@ fn default_registry_url() -> Url { "https://registry.walletconnect.com".parse().unwrap() } -pub fn get_configuration() -> Result { +pub async fn get_configuration() -> Result { load_dot_env()?; let config = envy::from_env::()?; + let relay_public_key = reqwest::get(config.relay_url.join("/public-key").unwrap()) + .await + .unwrap() + .text() + .await + .unwrap(); + let socket_addr = SocketAddr::from((config.bind_ip, config.port)); let notify_url = format!("http://{socket_addr}").parse::().unwrap(); let config = Configuration { @@ -88,6 +95,7 @@ pub fn get_configuration() -> Result { keypair_seed: config.keypair_seed, project_id: config.project_id, relay_url: config.relay_url, + relay_public_key, registry_url: config.registry_url, registry_auth_token: config.registry_auth_token, auth_redis_addr_read: None, diff --git a/src/config/mod.rs b/src/config/mod.rs index efcc5a75..fbddb390 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -22,6 +22,7 @@ pub struct Configuration { pub project_id: ProjectId, /// Relay URL e.g. https://relay.walletconnect.com pub relay_url: Url, + pub relay_public_key: String, pub notify_url: Url, pub registry_url: Url, @@ -59,10 +60,10 @@ impl Configuration { } } -pub fn get_configuration() -> Result { +pub async fn get_configuration() -> Result { if env::var("ENVIRONMENT") == Ok("DEPLOYED".to_owned()) { deployed::get_configuration() } else { - local::get_configuration() + local::get_configuration().await } } diff --git a/src/main.rs b/src/main.rs index 1393a7a1..0a2fc2b0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,7 +6,7 @@ use { #[tokio::main] async fn main() -> Result<(), NotifyServerError> { - let config = get_configuration()?; + let config = get_configuration().await?; tracing_subscriber::fmt() .with_env_filter(&config.log_level) diff --git a/src/services/public_http_server/handlers/relay_webhook/mod.rs b/src/services/public_http_server/handlers/relay_webhook/mod.rs index e461912f..1bfd0d58 100644 --- a/src/services/public_http_server/handlers/relay_webhook/mod.rs +++ b/src/services/public_http_server/handlers/relay_webhook/mod.rs @@ -99,10 +99,9 @@ pub async fn handler( .verify_basic(&HashSet::from([state.config.notify_url.to_string()]), None) .map_err(|e| Error::ClientError(ClientError::VerifyWatchEvent(e)))?; - // TODO verify issuer - // if claims.basic.iss != state.config.relay_identity { - // return Err(Error::ClientError(ClientError::WrongIssuer)); - // } + if claims.basic.iss != state.relay_identity { + return Err(Error::ClientError(ClientError::WrongIssuer)); + } // TODO irn_batchReceive message diff --git a/src/services/publisher_service/helpers.rs b/src/services/publisher_service/helpers.rs index 1cdddae6..66830362 100644 --- a/src/services/publisher_service/helpers.rs +++ b/src/services/publisher_service/helpers.rs @@ -113,6 +113,9 @@ pub struct NotificationToProcess { pub project_authentication_private_key: String, } +/// Picks a notification to be processed, marking it as status=processing. +/// status=processing used over a lock on un-sent messages used as it avoids long-running transactions +/// which could become a problem at high throughputs. #[instrument(skip(postgres, metrics))] pub async fn pick_subscriber_notification_for_processing( postgres: &PgPool, diff --git a/src/state.rs b/src/state.rs index 86ee6b7e..51179d63 100644 --- a/src/state.rs +++ b/src/state.rs @@ -10,7 +10,10 @@ use { }, build_info::BuildInfo, relay_client::http::Client, - relay_rpc::auth::ed25519_dalek::Keypair, + relay_rpc::{ + auth::ed25519_dalek::{Keypair, PublicKey}, + domain::{DecodedClientId, DidKey}, + }, serde::{Deserialize, Serialize}, sqlx::PgPool, std::{fmt, sync::Arc}, @@ -25,6 +28,7 @@ pub struct AppState { pub postgres: PgPool, pub keypair: Keypair, pub relay_client: Arc, + pub relay_identity: DidKey, pub redis: Option>, pub registry: Arc, pub notify_keys: NotifyKeys, @@ -49,6 +53,10 @@ impl AppState { ) -> Result { let build_info: &BuildInfo = build_info(); + let relay_identity = DidKey::from(DecodedClientId::from_key( + &PublicKey::from_bytes(&hex::decode(&config.relay_public_key).unwrap()).unwrap(), + )); + let notify_keys = NotifyKeys::new(&config.notify_url, keypair_seed)?; Ok(Self { @@ -59,6 +67,7 @@ impl AppState { postgres, keypair, relay_client, + relay_identity, redis, registry, notify_keys, diff --git a/terraform/ecs/cluster.tf b/terraform/ecs/cluster.tf index 0d9de5b4..9393f074 100644 --- a/terraform/ecs/cluster.tf +++ b/terraform/ecs/cluster.tf @@ -72,6 +72,7 @@ resource "aws_ecs_task_definition" "app_task" { { name = "KEYPAIR_SEED", value = var.keypair_seed }, { name = "PROJECT_ID", value = var.project_id }, { name = "RELAY_URL", value = var.relay_url }, + { name = "RELAY_PUBLIC_KEY", value = var.relay_public_key }, { name = "NOTIFY_URL", value = var.notify_url }, { name = "POSTGRES_URL", value = var.postgres_url }, diff --git a/terraform/ecs/variables.tf b/terraform/ecs/variables.tf index 9429e520..f40581d6 100644 --- a/terraform/ecs/variables.tf +++ b/terraform/ecs/variables.tf @@ -124,6 +124,11 @@ variable "relay_url" { type = string } +variable "relay_public_key" { + description = "The public key of the relay server obtained from relay.walletconnect.com/public-key" + type = string +} + variable "notify_url" { description = "The URL of the notify server" type = string diff --git a/terraform/res_application.tf b/terraform/res_application.tf index c3ffaa29..b09c2fbf 100644 --- a/terraform/res_application.tf +++ b/terraform/res_application.tf @@ -59,6 +59,7 @@ module "ecs" { keypair_seed = var.keypair_seed project_id = var.project_id relay_url = var.relay_url + relay_public_key = var.relay_public_key notify_url = var.notify_url ofac_blocked_countries = var.ofac_blocked_countries diff --git a/terraform/variables.tf b/terraform/variables.tf index 5731f829..e8a316d4 100644 --- a/terraform/variables.tf +++ b/terraform/variables.tf @@ -83,6 +83,11 @@ variable "relay_url" { type = string } +variable "relay_public_key" { + description = "The public key of the relay server obtained from relay.walletconnect.com/public-key" + type = string +} + variable "notify_url" { description = "The URL of the notify server" type = string diff --git a/tests/deployment.rs_ b/tests/deployment.rs_ index 847cc659..e4779f51 100644 --- a/tests/deployment.rs_ +++ b/tests/deployment.rs_ @@ -108,7 +108,8 @@ fn get_vars() -> Vars { match env.as_str() { "PROD" => Vars { notify_url: "https://notify.walletconnect.com".to_owned(), - relay_url: "wss://relay.walletconnect.com".to_owned(), + relay_public_key: "ff469faa970df23c23a6542765ce8dba2a907538522833b2327a153e365d138e".to_owned(), + relay_url: "https://relay.walletconnect.com".to_owned(), relay_project_id, notify_project_id: notify_prod_project_id(), notify_project_secret: notify_prod_project_secret(), @@ -116,7 +117,8 @@ fn get_vars() -> Vars { }, "STAGING" => Vars { notify_url: "https://staging.notify.walletconnect.com".to_owned(), - relay_url: "wss://staging.relay.walletconnect.com".to_owned(), + relay_url: "https://staging.relay.walletconnect.com".to_owned(), + relay_public_key: "07af8a122a706be3d8036a2f80ff5089618c7dac0fa8484758bd9f476058c8cb".to_owned(), relay_project_id, notify_project_id: notify_staging_project_id(), notify_project_secret: notify_staging_project_secret(), @@ -124,7 +126,8 @@ fn get_vars() -> Vars { }, "DEV" => Vars { notify_url: "https://dev.notify.walletconnect.com".to_owned(), - relay_url: "wss://staging.relay.walletconnect.com".to_owned(), + relay_url: "https://staging.relay.walletconnect.com".to_owned(), + relay_public_key: "07af8a122a706be3d8036a2f80ff5089618c7dac0fa8484758bd9f476058c8cb".to_owned(), relay_project_id, notify_project_id: notify_prod_project_id(), notify_project_secret: notify_prod_project_secret(), @@ -132,7 +135,13 @@ fn get_vars() -> Vars { }, "LOCAL" => Vars { notify_url: "http://127.0.0.1:3000".to_owned(), - relay_url: "ws://127.0.0.1:8888".to_owned(), + relay_url: "http://127.0.0.1:8888".to_owned(), + relay_public_key: reqwest::get("http://127.0.0.1:8888".parse::().unwrap().join("/public-key").unwrap()) + .await + .unwrap() + .text() + .await + .unwrap(), relay_project_id, notify_project_id: notify_prod_project_id(), notify_project_secret: notify_prod_project_secret(), diff --git a/tests/integration.rs b/tests/integration.rs index 1fa32152..26acb5e4 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -964,6 +964,13 @@ impl AsyncTestContext for NotifyServerContext { let telemetry_prometheus_port = find_free_port(bind_ip).await; let socket_addr = SocketAddr::from((bind_ip, bind_port)); let notify_url = format!("http://{socket_addr}").parse::().unwrap(); + let relay_url = vars.relay_url.parse::().unwrap(); + let relay_public_key = reqwest::get(relay_url.join("/public-key").unwrap()) + .await + .unwrap() + .text() + .await + .unwrap(); let (_, postgres_url) = get_postgres().await; let clock = Arc::new(MockClock::new(Utc::now())); // TODO reuse the local configuration defaults here @@ -977,7 +984,8 @@ impl AsyncTestContext for NotifyServerContext { registry_url: registry_mock_server.uri().parse().unwrap(), keypair_seed: hex::encode(rand::Rng::gen::<[u8; 10]>(&mut rand::thread_rng())), project_id: vars.project_id.into(), - relay_url: vars.relay_url.parse().unwrap(), + relay_url, + relay_public_key, notify_url: notify_url.clone(), registry_auth_token: "".to_owned(), auth_redis_addr_read: Some("redis://localhost:6378/0".to_owned()),