diff --git a/mpc/README.md b/mpc/README.md new file mode 100644 index 0000000000..e4c6af1371 --- /dev/null +++ b/mpc/README.md @@ -0,0 +1,58 @@ +# Introduction + +This project contains the client and coordinator to conduct Groth16 multi-party computation for the circuit SRS. +Three components are in play: +- Supabase : host the state machine in postgresql and exposes api and storage services to upload contributions. +- Coordinator: contact Supabase and verify contribution to step the state machine. +- Client: pure function that accepts the current contributor id and generate then upload a contribution payload. + +## Supabase + +Hosts the database, storage services and state machine of the MPC round. Provides instant API on top of them. + +## Coordinator + +The coordinator is in charge of verifying contributions. When a contribution is deemed valid, it dispatches the value to Supabase (insert an entry), effectively stepping the MPC state machine. + +## Client + +Exposes an API to contribute at `localhost:4919`: +- `OPTIONS /contribute` +- `POST /contribute` a `Contribute` object in body. Returns : + - a `202 Accepted` if the contribution started. + - a `503 Unavailable` if the client is busy (likely already contributing). +- `GET /contribute` returns : + - a `200 Ok` if everything is ok with the body containing an encoded `Status` representing the client status (idle, contributing etc...). + - a `500 InternalServerError` if the contribution failed unexpectedly, the body contains the error message. + +### Structures + +#### Contribute +```json +{ + "supabase_project": "", + "bucket": "", + "jwt": "", + "api_key": "", + "contributor_id": "", + "payload_id": "" +} +``` + +#### Status +```rust +#[serde(rename_all = "camelCase")] +pub enum Status { + Idle, + Initializing, + DownloadStarted(String), + Downloading(String, u8), + DownloadEnded(String), + ContributionStarted, + ContributionEnded, + UploadStarted(String), + UploadEnded(String), + Failed(String), + Successful, +} +``` diff --git a/mpc/client/src/main.rs b/mpc/client/src/main.rs index 696663763f..cac88e0800 100644 --- a/mpc/client/src/main.rs +++ b/mpc/client/src/main.rs @@ -38,12 +38,12 @@ use tokio::{ use tokio_util::sync::CancellationToken; use types::Status; -const SUPABASE_PROJECT: &str = "https://wwqpylbrcpriyaqugzsi.supabase.co"; const ENDPOINT: &str = "/contribute"; #[derive(PartialEq, Eq, Debug, Clone, Deserialize)] #[serde(rename_all = "camelCase")] struct Contribute { + supabase_project: String, bucket: String, jwt: String, api_key: String, @@ -74,6 +74,7 @@ type DynError = Box; async fn contribute( tx_status: Sender, Contribute { + supabase_project, bucket, jwt, api_key, @@ -81,7 +82,7 @@ async fn contribute( payload_id, }: Contribute, ) -> Result<(), DynError> { - let client = SupabaseMPCApi::new(SUPABASE_PROJECT.into(), api_key, jwt); + let client = SupabaseMPCApi::new(supabase_project.clone(), api_key, jwt); let current_contributor = client .current_contributor() .await? @@ -183,7 +184,7 @@ async fn contribute( // https://tus.io/protocols/resumable-upload#creation == // ===================================================== let response = upload_client - .post(format!("{SUPABASE_PROJECT}/storage/v1/upload/resumable")) + .post(format!("{supabase_project}/storage/v1/upload/resumable")) .header("Tus-Resumable", "1.0.0") .header("Upload-Length", CONTRIBUTION_SIZE.to_string()) .header( @@ -415,7 +416,7 @@ async fn main() -> Result<(), DynError> { let token = CancellationToken::new(); let token_clone = token.clone(); let handle = tokio::spawn(async move { - let addr = SocketAddr::from(([127, 0, 0, 1], 0x1337)); + let addr = SocketAddr::from(([0, 0, 0, 0], 0x1337)); let listener = TcpListener::bind(addr).await.unwrap(); loop { tokio::select! { diff --git a/mpc/coordinator/database.sql b/mpc/coordinator/database.sql index 6f57c89231..7d759a62b2 100644 --- a/mpc/coordinator/database.sql +++ b/mpc/coordinator/database.sql @@ -16,8 +16,8 @@ CREATE TABLE queue ( ALTER TABLE queue ENABLE ROW LEVEL SECURITY; ALTER TABLE queue ADD FOREIGN KEY (id) REFERENCES auth.users(id); CREATE UNIQUE INDEX idx_queue_score_id ON queue(score, id); -CREATE UNIQUE INDEX idx_queue_score ON queue(score); CREATE UNIQUE INDEX idx_queue_id_payload ON queue(id, payload_id); +CREATE INDEX idx_queue_score ON queue(score); CREATE POLICY view_all ON queue diff --git a/mpc/mpc.nix b/mpc/mpc.nix index 206acf4665..91e8c31d2d 100644 --- a/mpc/mpc.nix +++ b/mpc/mpc.nix @@ -13,15 +13,15 @@ in { packages = mpc-coordinator.packages // mpc-client.packages // { - mpc-image = pkgs.dockerTools.buildImage { + mpc-client-image = pkgs.dockerTools.buildImage { name = "${self'.packages.mpc-client.name}-image"; copyToRoot = pkgs.buildEnv { name = "image-root"; - paths = [ pkgs.coreutils-full pkgs.cacert ]; + paths = [ pkgs.coreutils-full pkgs.cacert pkgs.ncurses ]; pathsToLink = [ "/bin" ]; }; config = { - Entrypoint = [ (pkgs.lib.getExe self'.packages.mpc) ]; + Entrypoint = [ (pkgs.lib.getExe self'.packages.mpc-client) ]; Env = [ "SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt" ]; }; };