Skip to content

Commit

Permalink
Tolerate participant URLs without a protocol prefix.
Browse files Browse the repository at this point in the history
  • Loading branch information
robin-near committed Jan 13, 2025
1 parent 79ec507 commit 2a03a91
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 8 deletions.
13 changes: 7 additions & 6 deletions chain-signatures/node/src/http_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::protocol::MpcMessage;
use cait_sith::protocol::Participant;
use mpc_contract::config::ProtocolConfig;
use mpc_keys::hpke::Ciphered;
use reqwest::{Client, IntoUrl};
use reqwest::Client;
use std::collections::{HashMap, HashSet, VecDeque};
use std::str::Utf8Error;
use std::time::{Duration, Instant};
Expand Down Expand Up @@ -38,22 +38,23 @@ pub enum SendError {
MalformedResponse(Utf8Error),
#[error("encryption error: {0}")]
EncryptionError(String),
#[error("url parse error: {0}")]
UrlParseError(#[from] url::ParseError),
#[error("http request timeout: {0}")]
Timeout(String),
#[error("participant is not alive: {0}")]
ParticipantNotAlive(String),
}

pub async fn send_encrypted<U: IntoUrl>(
pub async fn send_encrypted(
from: Participant,
client: &Client,
url: U,
to: &ParticipantInfo,
message: Vec<Ciphered>,
request_timeout: Duration,
) -> Result<(), SendError> {
let _span = tracing::info_span!("message_request");
let mut url = url.into_url()?;
url.set_path("msg");
let url = to.url_for_path("/msg")?;
tracing::debug!(?from, to = %url, "making http request: sending encrypted message");
let action = || async {
let response = tokio::time::timeout(
Expand Down Expand Up @@ -177,7 +178,7 @@ impl MessageQueue {
if let Err(err) = send_encrypted(
from,
client,
&info.url,
&info,
encrypted_partition,
Duration::from_millis(self.message_options.timeout),
)
Expand Down
4 changes: 2 additions & 2 deletions chain-signatures/node/src/mesh/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ impl Pool {
&self,
participant_info: &ParticipantInfo,
) -> Result<StateView, FetchParticipantError> {
let Ok(Ok(url)) = Url::parse(&participant_info.url).map(|url| url.join("/state")) else {
let Ok(url) = participant_info.url_for_path("/state") else {
return Err(FetchParticipantError::InvalidUrl);
};
match tokio::time::timeout(
Expand All @@ -207,7 +207,7 @@ impl Pool {
crate::http_client::send_encrypted(
*participant,
&self.http,
participant_info.url.clone(),
participant_info,
empty_msg,
self.fetch_participant_timeout,
)
Expand Down
39 changes: 39 additions & 0 deletions chain-signatures/node/src/protocol/contract/primitives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::{
collections::{BTreeMap, HashSet},
str::FromStr,
};
use url::Url;

type ParticipantId = u32;

Expand All @@ -30,6 +31,16 @@ impl ParticipantInfo {
sign_pk: near_crypto::PublicKey::empty(near_crypto::KeyType::ED25519),
}
}

/// Parses the url as well as appending a path to it. Tolerates not having a protocol.
pub fn url_for_path(&self, path: &str) -> Result<Url, url::ParseError> {
let base_url = if self.url.starts_with("http://") || self.url.starts_with("https://") {
Url::parse(&self.url)?
} else {
Url::parse(&format!("http://{}", self.url))?
};
base_url.join(path)
}
}

#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq)]
Expand Down Expand Up @@ -323,3 +334,31 @@ impl From<mpc_contract::primitives::Votes> for Votes {
}
}
}

#[cfg(test)]
mod tests {
#[test]
fn test_url_for_path() {
let mut participant_info = super::ParticipantInfo {
id: 0,
account_id: "p-0".parse().unwrap(),
url: "http://1.1.1.1:8080".to_string(),
cipher_pk: mpc_keys::hpke::PublicKey::from_bytes(&[0; 32]),
sign_pk: near_crypto::PublicKey::empty(near_crypto::KeyType::ED25519),
};
let url = participant_info.url_for_path("/msg").unwrap();
assert_eq!(url.as_str(), "http://1.1.1.1:8080/msg");

participant_info.url = "https://my.domain".to_string();
let url = participant_info.url_for_path("/msg").unwrap();
assert_eq!(url.as_str(), "https://my.domain/msg");

participant_info.url = "my.domain".to_string();
let url = participant_info.url_for_path("/state").unwrap();
assert_eq!(url.as_str(), "http://my.domain/state");

participant_info.url = "http://my.domain/subpath".to_string();
let url = participant_info.url_for_path("/state").unwrap();
assert_eq!(url.as_str(), "http://my.domain/state");
}
}

0 comments on commit 2a03a91

Please sign in to comment.