HTTP Multi-Server Channels
The HttpChannel
enables multi-party computation (MPC) over a network by sending messages between parties using HTTP requests. Each party runs a server to receive messages and a client to send them.
- Suitable for distributed environments where parties communicate over a network.
- Ideal when parties run on separate servers and need a simple, HTTP-based transport layer.
How It Works
- Each party starts an HTTP server using
axum
. - Messages are sent via HTTP
POST
requests usingreqwest
. - Messages are received through an HTTP endpoint (
/msg/:from
) and forwarded to an async channel.
Example Implementation: HTTP Channel
The following example shows how to implement a Channel
trait using HTTP communication:
#![allow(unused)] fn main() { struct HttpChannel { urls: Vec<Url>, party: usize, recv: Vec<Receiver<Vec<u8>>>, } impl HttpChannel { async fn new(urls: Vec<Url>, party: usize) -> Result<Self, Error> { let port = urls[party].port().expect("All URLs must specify a port"); let recv = serve(port, urls.len()).await?; Ok(Self { urls, party, recv }) } } impl Channel for HttpChannel { type SendError = anyhow::Error; type RecvError = anyhow::Error; async fn send_bytes_to( &mut self, p: usize, msg: Vec<u8>, _info: SendInfo, ) -> Result<(), Self::SendError> { let client = reqwest::Client::new(); let url = format!("{}msg/{}", self.urls[p], self.party); loop { let Ok(resp) = client.post(&url).body(msg.clone()).send().await else { println!("Could not reach party {p} at {url}..."); sleep(Duration::from_millis(200)).await; continue; }; match resp.status() { StatusCode::OK => return Ok(()), StatusCode::NOT_FOUND => { println!("Could not reach party {p} at {url}..."); sleep(Duration::from_millis(200)).await; } status => anyhow::bail!("Unexpected status code: {status}"), } } } async fn recv_bytes_from( &mut self, p: usize, _info: RecvInfo, ) -> Result<Vec<u8>, Self::RecvError> { Ok(timeout(Duration::from_secs(1), self.recv[p].recv()) .await .context("recv_bytes_from({p})")? .unwrap_or_default()) } } }