Skip to content

Commit 56e75a0

Browse files
committed
move split to mpc-server
1 parent 04940fd commit 56e75a0

File tree

9 files changed

+245
-120
lines changed

9 files changed

+245
-120
lines changed

mpc-server/.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@
66

77
/config/
88

9-
.env
9+
.env
10+
11+
/tmp/

mpc-server/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,5 @@ serde = { version = "1.0.219", features = ["derive"] }
3232
serde_json = "1.0.140"
3333
axum-extra = { version = "0.10.1", features = ["typed-header"] }
3434
dotenv = "0.15.0"
35+
toml = "0.8.22"
36+
hex = "0.4.3"

mpc-server/src/main.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ mod matching;
2727
mod shares;
2828
mod token;
2929

30-
use db::{connect_db, get_matches, setup_db};
30+
use db::{get_matches, setup_db};
3131
use matching::{CONFIG_DIR, DATA_DIR, run_matches};
32-
use shares::upload;
32+
use shares::{ProverData, split_handler, upload};
3333

3434
#[derive(Debug, Deserialize)]
3535
pub struct UploadQuery {
@@ -96,15 +96,32 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
9696
.allow_origin(Any)
9797
.allow_headers(Any);
9898

99+
let p = program_artifact.clone();
100+
99101
let app = Router::new()
100102
.route("/", get(|| async { "hello" }))
103+
.route(
104+
"/split",
105+
post(|payload: Json<ProverData>| async move {
106+
match split_handler(payload.0, &p).await {
107+
Ok(shares) => (StatusCode::OK, Json(json!({"shares": shares}))),
108+
Err(e) => {
109+
println!("ERROR: {:?}", e);
110+
(
111+
StatusCode::INTERNAL_SERVER_ERROR,
112+
Json(json!({"error": "error"})),
113+
)
114+
}
115+
}
116+
}),
117+
)
101118
.route(
102119
"/matches",
103120
post(move |token: Token| async move {
104121
match run_matches(
105122
token.user_id,
106123
parties,
107-
program_artifact,
124+
&program_artifact,
108125
constraint_system,
109126
recursive,
110127
has_zk,

mpc-server/src/matching.rs

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub const SHARES_DIR_2: Lazy<PathBuf> = Lazy::new(|| DATA_DIR.join("user2"));
2626
pub async fn run_matches(
2727
user_id: String,
2828
parties: Vec<NetworkParty>,
29-
program_artifact: ProgramArtifact,
29+
program_artifact: &ProgramArtifact,
3030
constraint_system: Arc<AcirFormat<ark_bn254::Fr>>,
3131
recursive: bool,
3232
has_zk: ZeroKnowledge,
@@ -66,7 +66,7 @@ pub async fn run_matches(
6666
match run_match(
6767
[share0, share1, share2],
6868
parties.clone(),
69-
program_artifact.clone(),
69+
program_artifact,
7070
constraint_system.clone(),
7171
recursive,
7272
has_zk,
@@ -96,7 +96,7 @@ pub async fn run_matches(
9696
async fn run_match(
9797
[share0, share1, share2]: [Share; 3],
9898
parties: Vec<NetworkParty>,
99-
program_artifact: ProgramArtifact,
99+
program_artifact: &ProgramArtifact,
100100
constraint_system: Arc<AcirFormat<ark_bn254::Fr>>,
101101
recursive: bool,
102102
has_zk: ZeroKnowledge,
@@ -168,19 +168,6 @@ async fn run_match(
168168
Ok(())
169169
}
170170

171-
// fn split_input(
172-
// input_path: PathBuf,
173-
// program_artifact: ProgramArtifact,
174-
// ) -> Result<[Share; 3], Box<dyn std::error::Error + Send + Sync + 'static>> {
175-
// let inputs = co_noir::parse_input(input_path, &program_artifact)?;
176-
177-
// let mut rng = rand::thread_rng();
178-
// let [share0, share1, share2] =
179-
// co_noir::split_input_rep3::<Bn254, Rep3MpcNet, _>(inputs, &mut rng);
180-
181-
// Ok([share0, share1, share2])
182-
// }
183-
184171
fn merge_shares(
185172
share_user1: Share,
186173
share_user2: Share,

mpc-server/src/shares.rs

Lines changed: 4 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,5 @@
1-
use axum::extract::Multipart;
2-
use co_noir::Rep3AcvmType;
3-
use rand::{Rng, distributions::Alphanumeric};
4-
use std::collections::BTreeMap;
1+
mod split;
2+
mod upload;
53

6-
use crate::{
7-
db::{connect_db, insert_user},
8-
matching::{SHARES_DIR_1, SHARES_DIR_2},
9-
token::encode_token,
10-
};
11-
12-
const MIN_SHARE_SIZE: usize = 500;
13-
const MAX_SHARE_SIZE: usize = 2000;
14-
15-
pub type Share = BTreeMap<String, Rep3AcvmType<ark_bn254::Fr>>;
16-
17-
pub async fn upload(
18-
twitter_handle: String,
19-
mut multipart: Multipart,
20-
) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
21-
let mut shares = Vec::new();
22-
while let Some(field) = multipart.next_field().await? {
23-
let data = field.bytes().await?;
24-
25-
if data.len() < MIN_SHARE_SIZE || data.len() > MAX_SHARE_SIZE {
26-
return Err("Invalid share size".into());
27-
}
28-
29-
shares.push(data);
30-
}
31-
32-
if shares.len() != 6 {
33-
return Err("Invalid number of shares".into());
34-
}
35-
36-
let dir1 = SHARES_DIR_1.clone();
37-
let dir2 = SHARES_DIR_2.clone();
38-
39-
std::fs::create_dir_all(&dir1)?;
40-
std::fs::create_dir_all(&dir2)?;
41-
42-
let shares1 = shares[..3].to_vec();
43-
let shares2 = shares[3..].to_vec();
44-
45-
let user_id = random_id();
46-
47-
for (i, share) in shares1.iter().enumerate() {
48-
let file_name = format!("{}-{}", user_id, i);
49-
let file_path = dir1.join(file_name);
50-
std::fs::write(file_path, share)?;
51-
}
52-
for (i, share) in shares2.iter().enumerate() {
53-
let file_name = format!("{}-{}", user_id, i);
54-
let file_path = dir2.join(file_name);
55-
std::fs::write(file_path, share)?;
56-
}
57-
58-
let conn = connect_db()?;
59-
insert_user(&conn, &user_id, &twitter_handle)?;
60-
61-
let token = encode_token(user_id)?;
62-
63-
Ok(token)
64-
}
65-
66-
pub fn get_shares(
67-
id: &str,
68-
user1: bool,
69-
) -> Result<[Share; 3], Box<dyn std::error::Error + Send + Sync>> {
70-
let dir = if user1 {
71-
SHARES_DIR_1.clone()
72-
} else {
73-
SHARES_DIR_2.clone()
74-
};
75-
let share0 = bin_to_share(std::fs::read(dir.join(format!("{id}-0")))?)?;
76-
let share1 = bin_to_share(std::fs::read(dir.join(format!("{id}-1")))?)?;
77-
let share2 = bin_to_share(std::fs::read(dir.join(format!("{id}-2")))?)?;
78-
Ok([share0, share1, share2])
79-
}
80-
81-
fn random_id() -> String {
82-
rand::thread_rng()
83-
.sample_iter(&Alphanumeric)
84-
.take(10)
85-
.map(char::from)
86-
.collect()
87-
}
88-
89-
fn bin_to_share(bin: Vec<u8>) -> Result<Share, Box<dyn std::error::Error + Send + Sync>> {
90-
let share: Share = bincode::deserialize(&bin)?;
91-
Ok(share)
92-
}
4+
pub use split::*;
5+
pub use upload::*;

mpc-server/src/shares/split.rs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
use co_noir::{Bn254, Rep3MpcNet};
2+
use noirc_artifacts::program::ProgramArtifact;
3+
use rand::{Rng, distributions::Alphanumeric};
4+
use serde::{Deserialize, Serialize};
5+
use std::path::PathBuf;
6+
7+
#[derive(Serialize, Deserialize, Debug)]
8+
pub struct ProverData {
9+
user1: User,
10+
}
11+
12+
#[derive(Serialize, Deserialize, Debug)]
13+
struct User {
14+
age: u32,
15+
gender: u32,
16+
id: String,
17+
interests: Vec<u32>,
18+
region: u32,
19+
preferences: Preferences,
20+
}
21+
22+
#[derive(Serialize, Deserialize, Debug)]
23+
struct Preferences {
24+
age_max: u32,
25+
age_min: u32,
26+
gender: u32,
27+
}
28+
29+
pub async fn split_handler(
30+
payload: ProverData,
31+
program_artifact: &ProgramArtifact,
32+
) -> Result<Vec<String>, Box<dyn std::error::Error + Send + Sync + 'static>> {
33+
let prover_path1 = save_prover_data(&payload, false)?;
34+
let prover_path2 = save_prover_data(&payload, true)?;
35+
36+
let shares1 = split_input(prover_path1, &program_artifact)?;
37+
let shares2 = split_input(prover_path2, &program_artifact)?;
38+
39+
let mut out = shares1
40+
.iter()
41+
.map(|d| hex::encode(d))
42+
.collect::<Vec<String>>();
43+
44+
let out2 = shares2
45+
.iter()
46+
.map(|d| hex::encode(d))
47+
.collect::<Vec<String>>();
48+
49+
out.extend(out2);
50+
51+
Ok(out)
52+
}
53+
54+
fn split_input(
55+
input_path: PathBuf,
56+
program_artifact: &ProgramArtifact,
57+
) -> Result<Vec<Vec<u8>>, Box<dyn std::error::Error + Send + Sync + 'static>> {
58+
let inputs = co_noir::parse_input(input_path, &program_artifact)?;
59+
60+
let mut rng = rand::thread_rng();
61+
let shares = co_noir::split_input_rep3::<Bn254, Rep3MpcNet, _>(inputs, &mut rng);
62+
63+
let out = shares
64+
.iter()
65+
.map(|share| bincode::serialize(share))
66+
.collect::<Result<Vec<Vec<u8>>, _>>()
67+
.unwrap();
68+
69+
Ok(out)
70+
}
71+
72+
fn save_prover_data(
73+
prover: &ProverData,
74+
as_user2: bool,
75+
) -> Result<PathBuf, Box<dyn std::error::Error + Send + Sync + 'static>> {
76+
let mut toml = toml::to_string(prover)?;
77+
if as_user2 {
78+
toml = toml.replace("user1", "user2");
79+
}
80+
println!("toml: {}", toml);
81+
let file_path = write_file(None, &toml)?;
82+
Ok(file_path)
83+
}
84+
85+
fn write_file(
86+
file_name: Option<&str>,
87+
data: &str,
88+
) -> Result<PathBuf, Box<dyn std::error::Error + Send + Sync + 'static>> {
89+
let dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tmp");
90+
91+
// create the directory if it doesn't exist
92+
std::fs::create_dir_all(dir.clone())?;
93+
94+
let name = match file_name {
95+
Some(file_name) => file_name.to_string(),
96+
None => rand::thread_rng()
97+
.sample_iter(&Alphanumeric)
98+
.take(10)
99+
.map(char::from)
100+
.collect(),
101+
};
102+
103+
let file = dir.join(name);
104+
std::fs::write(file.clone(), data)?;
105+
Ok(file)
106+
}

0 commit comments

Comments
 (0)