Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
target/
.git/
.idea/
.helix/
.DS_Store
*.bak
fuzz/
docs/
mutants.out*
lcov.info
docker/vol/
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,8 @@ coverage.xml
*.bak

# fuzz target logs
fuzz-*.log
fuzz-*.log

# Docker volume data
docker/vol/fdb/data/
docker/vol/mosaic-*/tables/
11 changes: 9 additions & 2 deletions bin/mosaic/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,9 +361,16 @@ pub(crate) struct RpcConfig {
}

fn parse_socket_addr(value: &str) -> Result<SocketAddr> {
// Try direct parse first (IP:port), fall back to DNS resolution (hostname:port).
if let Ok(addr) = value.parse() {
return Ok(addr);
}
use std::net::ToSocketAddrs;
value
.parse()
.with_context(|| format!("invalid socket address `{value}`"))
.to_socket_addrs()
.with_context(|| format!("failed to resolve address `{value}`"))?
.next()
.with_context(|| format!("no addresses found for `{value}`"))
}

fn decode_signing_key(value: &str) -> Result<SigningKey> {
Expand Down
71 changes: 71 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# syntax=docker/dockerfile:1

# ------------------------------------------------------------------------------
# Stage 1: Build the mosaic binary
# ------------------------------------------------------------------------------
FROM ubuntu:24.04 AS builder

# Install build dependencies and Rust nightly toolchain.
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
adduser build-essential ca-certificates clang curl libclang-dev pkg-config \
&& curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
| sh -s -- -y --default-toolchain nightly --profile minimal \
&& rm -rf /var/lib/apt/lists/*
ENV PATH="/root/.cargo/bin:${PATH}"

# Install FoundationDB client library (required by the fdb crate at link time).
# Map Docker TARGETARCH (amd64/arm64) to FDB's naming (amd64/aarch64).
ARG TARGETARCH
ARG FDB_VERSION=7.3.75
RUN FDB_ARCH=$([ "$TARGETARCH" = "arm64" ] && echo "aarch64" || echo "amd64") \
&& curl -fsSLO --proto "=https" --tlsv1.2 \
"https://github.com/apple/foundationdb/releases/download/${FDB_VERSION}/foundationdb-clients_${FDB_VERSION}-1_${FDB_ARCH}.deb" \
&& dpkg -i "foundationdb-clients_${FDB_VERSION}-1_${FDB_ARCH}.deb" \
&& rm -f "foundationdb-clients_${FDB_VERSION}-1_${FDB_ARCH}.deb"

WORKDIR /build

# Copy manifests first for dependency caching
COPY Cargo.toml Cargo.lock rust-toolchain.toml* ./
COPY .cargo .cargo
COPY bin bin
COPY crates crates

# Build the release binary
RUN cargo build --release --bin mosaic \
&& strip --strip-debug target/release/mosaic

# ------------------------------------------------------------------------------
# Stage 2: Minimal runtime image
# ------------------------------------------------------------------------------
FROM ubuntu:24.04 AS runtime

# Install FoundationDB client library (required at runtime).
ARG TARGETARCH
ARG FDB_VERSION=7.3.75
RUN FDB_ARCH=$([ "$TARGETARCH" = "arm64" ] && echo "aarch64" || echo "amd64") \
&& apt-get update \
&& apt-get install -y --no-install-recommends adduser ca-certificates curl \
&& curl -fsSLO --proto "=https" --tlsv1.2 \
"https://github.com/apple/foundationdb/releases/download/${FDB_VERSION}/foundationdb-clients_${FDB_VERSION}-1_${FDB_ARCH}.deb" \
&& dpkg -i "foundationdb-clients_${FDB_VERSION}-1_${FDB_ARCH}.deb" \
&& rm -f "foundationdb-clients_${FDB_VERSION}-1_${FDB_ARCH}.deb" \
&& apt-get purge -y curl \
&& apt-get autoremove -y \
&& rm -rf /var/lib/apt/lists/*

# Volume mounts expected at runtime:
# /etc/mosaic/config.toml – mosaic configuration (required)
# circuit artifact (.v5c) – path configured via circuit.path in config.toml
# table store directory – path configured via table_store.root in config.toml (local_filesystem backend only)
# FDB cluster file – path configured via storage.cluster_file in config.toml
RUN mkdir -p /etc/mosaic && chown ubuntu:ubuntu /etc/mosaic

COPY --from=builder /build/target/release/mosaic /usr/local/bin/mosaic
COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh

USER ubuntu

ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
52 changes: 52 additions & 0 deletions docker/compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# NOTE: On first run, initialize FDB storage with: ./init-fdb.sh

x-base-mosaic-svc: &base-mosaic-svc
build:
context: ..
dockerfile: docker/Dockerfile
depends_on:
foundationdb:
condition: service_healthy

services:
foundationdb:
image: foundationdb/foundationdb:7.3.75
environment:
- FDB_NETWORKING_MODE=container
- FDB_CLUSTER_FILE=/var/fdb/fdb.cluster
volumes:
- ./vol/fdb/fdb.cluster:/var/fdb/fdb.cluster:rw
- ./vol/fdb/data:/var/fdb/data
ports:
# Keep this port in sync with ./vol/fdb/fdb.cluster
- "4500:4500"
healthcheck:
test:
[
"CMD-SHELL",
"fdbcli --no-status --exec 'status minimal' 2>/dev/null | grep -q 'The database is available' || exit 1",
]
interval: 10s
timeout: 5s
retries: 10
start_period: 30s

mosaic_1:
<<: *base-mosaic-svc
ports:
- "127.0.0.1:8000:8000"
volumes:
- ../artifacts/g16.v5c:/etc/mosaic/circuit.v5c:ro
- ./vol/fdb/fdb.cluster:/etc/foundationdb/fdb.cluster:ro
- ./vol/mosaic-1/config.toml:/etc/mosaic/config.toml:ro
- ./vol/mosaic-1/tables:/etc/mosaic/tables:rw

mosaic_2:
<<: *base-mosaic-svc
ports:
- "127.0.0.1:8001:8000"
volumes:
- ../artifacts/g16.v5c:/etc/mosaic/circuit.v5c:ro
- ./vol/fdb/fdb.cluster:/etc/foundationdb/fdb.cluster:ro
- ./vol/mosaic-2/config.toml:/etc/mosaic/config.toml:ro
- ./vol/mosaic-2/tables:/etc/mosaic/tables:rw
23 changes: 23 additions & 0 deletions docker/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
# Entrypoint for the mosaic Docker container.
#
# Expected volume mounts:
# /etc/mosaic/config.toml – mosaic configuration (TOML)
# /etc/mosaic/circuit.v5c – circuit artifact (v5c format)
#
# The config file's [circuit] section should reference:
# path = "/etc/mosaic/circuit.v5c"
#
# Any extra arguments are forwarded to the mosaic binary.

set -euo pipefail

CONFIG_PATH="${MOSAIC_CONFIG_PATH:-/etc/mosaic/config.toml}"

if [ ! -f "$CONFIG_PATH" ]; then
echo "ERROR: config file not found at $CONFIG_PATH" >&2
echo "Mount config as a volume: -v /path/to/config.toml:$CONFIG_PATH:ro" >&2
exit 1
fi

exec /usr/local/bin/mosaic "$CONFIG_PATH" "$@"
12 changes: 12 additions & 0 deletions docker/init-fdb.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env bash
# Initialize FoundationDB storage (idempotent - safe to run multiple times).
# Run this after `docker compose up` when starting with a fresh FDB instance.

set -euo pipefail

if docker compose exec -T foundationdb fdbcli --no-status --exec "status minimal" 2>/dev/null | grep -q "The database is available"; then
echo "FoundationDB already configured, skipping..."
else
docker compose exec -T foundationdb fdbcli --exec "configure new single ssd"
echo -e "\n\033[36m======== FDB_INITIALIZED ========\033[0m\n"
fi
1 change: 1 addition & 0 deletions docker/vol/fdb/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
./data
1 change: 1 addition & 0 deletions docker/vol/fdb/fdb.cluster
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
docker:docker@foundationdb:4500
53 changes: 53 additions & 0 deletions docker/vol/mosaic-1/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
[logging]
filter = "info"

[circuit]
path = "/etc/mosaic/circuit.v5c"

[network]
signing_key_hex = "1111111111111111111111111111111111111111111111111111111111111111"
bind_addr = "0.0.0.0:7000"
keep_alive_interval_secs = 1
idle_timeout_secs = 5
reconnect_backoff_secs = 1

[network.client]
open_timeout_secs = 5
ack_timeout_secs = 10

[[network.peers]]
peer_id_hex = "a09aa5f47a6759802ff955f8dc2d2a14a5c99d23be97f864127ff9383455a4f0"
addr = "mosaic_2:7000"

[storage]
cluster_file = "/etc/foundationdb/fdb.cluster"
global_path = ["local", "node-1"]

[table_store]
backend = "local_filesystem"
root = "/etc/mosaic/tables"
prefix = "garbling-tables"

[job_scheduler]
submission_queue_size = 256
completion_queue_size = 256

[job_scheduler.light]
threads = 1
concurrency_per_worker = 32

[job_scheduler.heavy]
threads = 2
concurrency_per_worker = 8

[job_scheduler.garbling]
worker_threads = 2
max_concurrent = 2
batch_timeout_ms = 500
chunk_timeout_secs = 30

[sm_executor]
command_queue_size = 256

[rpc]
bind_addr = "0.0.0.0:8000"
53 changes: 53 additions & 0 deletions docker/vol/mosaic-2/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
[logging]
filter = "info"

[circuit]
path = "/etc/mosaic/circuit.v5c"

[network]
signing_key_hex = "2222222222222222222222222222222222222222222222222222222222222222"
bind_addr = "0.0.0.0:7000"
keep_alive_interval_secs = 1
idle_timeout_secs = 5
reconnect_backoff_secs = 1

[network.client]
open_timeout_secs = 5
ack_timeout_secs = 10

[[network.peers]]
peer_id_hex = "d04ab232742bb4ab3a1368bd4615e4e6d0224ab71a016baf8520a332c9778737"
addr = "mosaic_1:7000"

[storage]
cluster_file = "/etc/foundationdb/fdb.cluster"
global_path = ["local", "node-2"]

[table_store]
backend = "local_filesystem"
root = "/etc/mosaic/tables"
prefix = "garbling-tables"

[job_scheduler]
submission_queue_size = 256
completion_queue_size = 256

[job_scheduler.light]
threads = 1
concurrency_per_worker = 32

[job_scheduler.heavy]
threads = 2
concurrency_per_worker = 8

[job_scheduler.garbling]
worker_threads = 2
max_concurrent = 2
batch_timeout_ms = 500
chunk_timeout_secs = 30

[sm_executor]
command_queue_size = 256

[rpc]
bind_addr = "0.0.0.0:8000"
Loading