Skip to content

Commit

Permalink
Add policy viewer routes in Postgres DB example
Browse files Browse the repository at this point in the history
  • Loading branch information
fkettelhoit committed Apr 24, 2024
1 parent 6c94bcc commit 8f8a909
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 17 deletions.
1 change: 1 addition & 0 deletions examples/postgres-integration/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ anyhow = "1.0.79"
axum = "0.7.4"
blake3 = "1.5.1"
clap = { version = "4.4.18", features = ["derive"] }
handlebars = "5.1.2"
parlay = { path = "../../", version = "0.1.0" }
reqwest = { version = "0.11.23", features = ["json"] }
serde = "1.0.197"
Expand Down
16 changes: 16 additions & 0 deletions examples/postgres-integration/policies0.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,22 @@
"setup": "TRUNCATE results",
"output": "INSERT INTO results (name) VALUES ($1)",
"output_db": "postgres://postgres:test@localhost:5555/postgres"
},
{
"participants": [
"http://localhost:8000",
"http://localhost:8001",
"http://localhost:8002"
],
"program": "does_not_exist.garble.rs",
"leader": 1,
"party": 0,
"input": "SELECT id, name, age FROM residents",
"input_db": "postgres://postgres:test@localhost:5550/postgres",
"max_rows": 4,
"setup": "TRUNCATE results",
"output": "INSERT INTO results (name) VALUES ($1)",
"output_db": "postgres://postgres:test@localhost:5555/postgres"
}
]
}
97 changes: 80 additions & 17 deletions examples/postgres-integration/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ use anyhow::{anyhow, bail, Context, Error};
use axum::{
body::Bytes,
extract::{DefaultBodyLimit, Path, State},
routing::post,
response::Html,
routing::{get, post},
Json, Router,
};
use clap::Parser;
use handlebars::Handlebars;
use parlay::{
channel::Channel,
fpre::fpre,
Expand All @@ -18,6 +20,7 @@ use parlay::{
};
use reqwest::StatusCode;
use serde::{Deserialize, Serialize};
use serde_json::json;
use sqlx::{postgres::PgPoolOptions, Row};
use std::{
borrow::BorrowMut, net::SocketAddr, path::PathBuf, process::exit, result::Result, sync::Arc,
Expand Down Expand Up @@ -51,12 +54,12 @@ struct Cli {
config: PathBuf,
}

#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize)]
struct Policies {
accepted: Vec<Policy>,
}

#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
struct Policy {
participants: Vec<Url>,
program: PathBuf,
Expand All @@ -83,9 +86,9 @@ type MpcState = Arc<Mutex<Vec<Sender<Vec<u8>>>>>;
async fn main() -> Result<(), Error> {
tracing_subscriber::fmt::init();
let Cli { port, config } = Cli::parse();
let policies = load_policies(config).await?;
if policies.accepted.len() == 1 {
let policy = &policies.accepted[0];
let local_policies = load_policies(config).await?;
if local_policies.accepted.len() == 1 {
let policy = &local_policies.accepted[0];
if policy.input.is_empty() {
info!("Running as preprocessor...");
return run_fpre(port, policy.participants.clone()).await;
Expand All @@ -97,17 +100,19 @@ async fn main() -> Result<(), Error> {
let app = Router::new()
.route("/run", post(run))
.route("/msg/:from", post(msg))
.with_state((policies.clone(), Arc::clone(&state)))
.route("/policies", get(policies))
.route("/policies/:id", get(policy))
.with_state((local_policies.clone(), Arc::clone(&state)))
.layer(DefaultBodyLimit::disable())
.layer(TraceLayer::new_for_http());

let addr = SocketAddr::from(([127, 0, 0, 1], port));
info!("listening on {}", addr);
let listener = tokio::net::TcpListener::bind(&addr).await?;
tokio::spawn(async move { axum::serve(listener, app).await.unwrap() });
info!("Found {} active policies", policies.accepted.len());
info!("Found {} active policies", local_policies.accepted.len());
loop {
for policy in &policies.accepted {
for policy in &local_policies.accepted {
if policy.leader == policy.party {
info!(
"Acting as leader (party {}) for program {}",
Expand All @@ -125,24 +130,32 @@ async fn main() -> Result<(), Error> {
leader: policy.leader,
program_hash: hash,
};
let mut participant_missing = false;
for party in policy.participants.iter().rev().skip(1).rev() {
if party != &policy.participants[policy.party] {
info!("Waiting for confirmation from party {party}");
let url = format!("{party}run");
match client
.post(&url)
.json(&policy_request)
.send()
.await?
.status()
{
let Ok(res) = client.post(&url).json(&policy_request).send().await else {
error!("Could not reach {url}");
participant_missing = true;
continue;
};
match res.status() {
StatusCode::OK => {}
code => {
error!("Unexpected response while trying to trigger execution for {url}: {code}");
participant_missing = true;
}
}
}
}
if participant_missing {
error!(
"Some participants of program {} are missing, skipping execution...",
policy.program.display()
);
continue;
}
info!("All participants have accepted the session, starting calculation now...");
fn decode_literal(l: Literal) -> Result<Vec<Vec<String>>, String> {
let Literal::Array(rows) = l else {
Expand Down Expand Up @@ -321,7 +334,7 @@ async fn execute_mpc(
let field = if let Ok(s) = row.try_get::<String, _>(c) {
let mut fixed_str =
vec![Literal::NumUnsigned(0, UnsignedNumType::U8); STR_LEN_BYTES];
for (i, b) in s.as_bytes().into_iter().enumerate() {
for (i, b) in s.as_bytes().iter().enumerate() {
if i < STR_LEN_BYTES {
fixed_str[i] = Literal::NumUnsigned(*b as u64, UnsignedNumType::U8);
} else {
Expand Down Expand Up @@ -426,6 +439,56 @@ async fn msg(State((_, state)): State<(Policies, MpcState)>, Path(from): Path<u3
}
}

async fn policies(
State((policies, _)): State<(Policies, MpcState)>,
) -> Result<Html<String>, axum::http::StatusCode> {
let mut accepted = vec![];
for (i, p) in policies.accepted.into_iter().enumerate() {
accepted.push(json!({
"id": i,
"num_participants": p.participants.len(),
"program": p.program.to_str().unwrap_or("<program>"),
"leader": p.leader,
"party": p.party,
}));
}
let params = json!({
"accepted": accepted
});
render_template(include_str!("../templates/policies.html"), &params)
}

async fn policy(
State((policies, _)): State<(Policies, MpcState)>,
Path(id): Path<usize>,
) -> Result<Html<String>, axum::http::StatusCode> {
let Some(p) = policies.accepted.get(id) else {
return Err(axum::http::StatusCode::NOT_FOUND);
};
let params = json!({
"policy": {
"num_participants": p.participants.len(),
"participants": p.participants,
"program": p.program.to_str().unwrap_or("<program>"),
"code": fs::read_to_string(&p.program).await.unwrap_or("Program not found".to_string()),
"leader": p.leader,
"party": p.party,
}
});
render_template(include_str!("../templates/policy.html"), &params)
}

fn render_template(
template: &str,
params: &serde_json::Value,
) -> Result<Html<String>, axum::http::StatusCode> {
let h = Handlebars::new();
let Ok(html) = h.render_template(template, &params) else {
return Err(axum::http::StatusCode::INTERNAL_SERVER_ERROR);
};
Ok(Html(html))
}

struct HttpChannel {
urls: Vec<Url>,
party: usize,
Expand Down
28 changes: 28 additions & 0 deletions examples/postgres-integration/templates/policies.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\" />
<title>Policies</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-slate-100 md:flex md:justify-center">
<div class="w-full m-8">
<h1 class="text-4xl font-bold mb-8">Policies</h1>
{{#each accepted}}
<div class="bg-white shadow-md rounded px-8 pt-8 pb-8 mb-8">
<div>
<a
href="/policies/{{id}}"
class="text-blue-600 text-xl visited:text-purple-600"
>{{program}}</a
>
</div>
<div>{{num_participants}} participants</div>
<div>Own Role: <strong>Party {{party}}</strong></div>
<div>Leader: <strong>Party {{leader}}</strong></div>
</div>
{{/each}}
</div>
</body>
</html>
32 changes: 32 additions & 0 deletions examples/postgres-integration/templates/policy.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<!DOCTYPE html>
<html lang="en">
{{#with policy}}
<head>
<meta charset="utf-8" />
<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\" />
<title>Policy {{program}}</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-slate-100 md:flex md:justify-center">
<div class="w-full m-8">
<h1 class="text-4xl font-bold mb-8">
<a href="/policies" class="text-blue-600 visited:text-purple-600"
>Policies</a
>
> {{program}}
</h1>
<div class="bg-white shadow-md rounded px-8 pt-8 pb-8 mb-8">
<div>{{num_participants}} participants</div>
<ol start="0" class="list-decimal mb-8">
{{#each participants}}
<li class="ml-8"><pre>{{this}}</pre></li>
{{/each}}
</ol>
<div>Own Role: <strong>Party {{party}}</strong></div>
<div>Leader: <strong>Party {{leader}}</strong></div>
<pre class="mt-8 text-slate-500"><code>{{code}}</code></pre>
</div>
</div>
</body>
{{/with}}
</html>

0 comments on commit 8f8a909

Please sign in to comment.