Skip to content
Open
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
18 changes: 16 additions & 2 deletions crates/cli/src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ pub enum ProgramCommands {
/// backend at all. Your program will simply execute without being verified.
#[arg(long)]
dev: Option<bool>,

/// On Linux, run the support Docker container with `--network=host` instead of rewriting
/// callback URLs to `host.local`. Avoids opening Docker's bridge network in the firewall.
/// Has no effect in `--dev` mode (no Docker). Not useful on macOS Docker Desktop.
#[arg(long, default_value_t = false)]
linux_network_host_mode: bool,
},

/// Compile the program code
Expand Down Expand Up @@ -46,8 +52,16 @@ pub enum ProgramCacheCommands {

pub async fn execute(command: ProgramCommands, config: &AppConfig) -> Result<()> {
match command {
ProgramCommands::Start { dev } => {
e3_support_scripts::program_start(config.program().clone(), dev).await?
ProgramCommands::Start {
dev,
linux_network_host_mode,
} => {
e3_support_scripts::program_start(
config.program().clone(),
dev,
linux_network_host_mode,
)
.await?
}
ProgramCommands::Compile { dev } => {
e3_support_scripts::program_compile(config.program().clone(), dev).await?
Expand Down
38 changes: 30 additions & 8 deletions crates/support-scripts/ctl/container
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,44 @@ else
TTY_FLAGS=""
fi

# Peel networking mode before forwarding remaining args into the container.
LINUX_NETWORK_HOST_MODE=0
INNER_ARGS=()
for arg in "$@"; do
if [[ "$arg" == "--linux-network-host-mode" ]]; then
LINUX_NETWORK_HOST_MODE=1
else
INNER_ARGS+=("$arg")
fi
done
set -- "${INNER_ARGS[@]}"

if docker ps -q -f name="$CONTAINER_NAME" | grep -q .; then
echo "Running exec $IMAGE..."
docker exec $TTY_FLAGS "$CONTAINER_NAME" bash -c "$*"
else
echo "Running start $IMAGE..."
# --network=host does not work on macos for allowing the container to access
# the local machine. `--add-host...` is adding host.local to the hosts file
# in the docker container we can then replace localhost and 127.0.0.1
# from the input callback url so calls redirect to gateway.
# This should in theory be crossplatform
# However on linux the user must allow incoming connections from Docker's bridge network 172.17.0.0/16 through their firewall.
# Default (cross-platform): `--add-host=host.local:host-gateway` plus rewriting
# localhost/127.0.0.1 in callback URLs so the container can reach the host.
# On Linux that requires allowing Docker's bridge network (172.17.0.0/16) through
# the firewall. `--linux-network-host-mode` uses Docker `--network=host` instead
# so localhost callbacks work without rewrite or firewall changes.
# Note: `--network=host` is not useful on macOS Docker Desktop.
DOCKER_NET_ARGS=(--add-host=host.local:host-gateway -p 13151:13151)
DOCKER_ENV_ARGS=()
if [[ "$LINUX_NETWORK_HOST_MODE" == "1" ]]; then
echo "Using Docker --network=host (linux network host mode)"
# Keep host.local→127.0.0.1 so older support images that still rewrite
# localhost callbacks keep working under host networking.
DOCKER_NET_ARGS=(--network=host --add-host=host.local:127.0.0.1)
DOCKER_ENV_ARGS=(-e INTERFOLD_SKIP_LOCALHOST_REWRITE=1)
fi

docker run $TTY_FLAGS --rm \
--name "$CONTAINER_NAME" \
--platform linux/amd64 \
--add-host=host.local:host-gateway \
-p 13151:13151 \
"${DOCKER_NET_ARGS[@]}" \
"${DOCKER_ENV_ARGS[@]}" \
-v "$(pwd)/.interfold/generated/contracts:/app/contracts:rw" \
-v "$(pwd)/tests:/app/tests" \
-v "$(pwd)/.interfold/caches/target:/app/target" \
Expand Down
11 changes: 10 additions & 1 deletion crates/support-scripts/ctl/start
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env bash

unset RISC0_DEV_MODE RPC_URL PRIVATE_KEY PINATA_JWT PROGRAM_URL BOUNDLESS_ONCHAIN
LINUX_NETWORK_HOST_MODE=0

while [[ $# -gt 0 ]]; do
case $1 in
Expand Down Expand Up @@ -28,6 +29,10 @@ while [[ $# -gt 0 ]]; do
BOUNDLESS_ONCHAIN="$2"
shift 2
;;
--linux-network-host-mode)
LINUX_NETWORK_HOST_MODE=1
shift
;;
*)
echo "Unknown argument: $1"
exit 1
Expand Down Expand Up @@ -62,4 +67,8 @@ if [[ -n "$BOUNDLESS_ONCHAIN" ]]; then
CONTAINER_ARGS+=("--boundless-onchain" "$BOUNDLESS_ONCHAIN")
fi

exec "$SCRIPT_DIR/container" "${CONTAINER_ARGS[@]}"
if [[ "$LINUX_NETWORK_HOST_MODE" == "1" ]]; then
CONTAINER_ARGS+=("--linux-network-host-mode")
fi

exec "$SCRIPT_DIR/container" "${CONTAINER_ARGS[@]}"
10 changes: 8 additions & 2 deletions crates/support-scripts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,14 @@ pub async fn program_compile(program_config: ProgramConfig, is_dev: Option<bool>
ProgramSupport::new(program_config, is_dev).compile().await
}

pub async fn program_start(program_config: ProgramConfig, is_dev: Option<bool>) -> Result<()> {
ProgramSupport::new(program_config, is_dev).start().await
pub async fn program_start(
program_config: ProgramConfig,
is_dev: Option<bool>,
linux_network_host_mode: bool,
) -> Result<()> {
ProgramSupport::new(program_config, is_dev)
.start(linux_network_host_mode)
.await
}

/// Upload the compiled program to Pinata IPFS
Expand Down
6 changes: 3 additions & 3 deletions crates/support-scripts/src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ impl ProgramSupportApi for ProgramSupport {
ProgramSupport::Risc0(s) => s.compile().await,
}
}
async fn start(&self) -> Result<()> {
async fn start(&self, linux_network_host_mode: bool) -> Result<()> {
match self {
ProgramSupport::Dev(s) => s.start().await,
ProgramSupport::Risc0(s) => s.start().await,
ProgramSupport::Dev(s) => s.start(linux_network_host_mode).await,
ProgramSupport::Risc0(s) => s.start(linux_network_host_mode).await,
}
}

Expand Down
7 changes: 6 additions & 1 deletion crates/support-scripts/src/program_dev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ impl ProgramSupportApi for ProgramSupportDev {
run_bash_script(&cwd, &script, &[]).await?;
Ok(())
}
async fn start(&self) -> Result<()> {
async fn start(&self, linux_network_host_mode: bool) -> Result<()> {
if linux_network_host_mode {
eprintln!(
"warning: --linux-network-host-mode has no effect in --dev mode (Docker is not used)"
);
}
let cwd = env::current_dir()?;
let script = cwd.join(".interfold/support/dev/start");
ensure_script_exists(&script).await?;
Expand Down
6 changes: 5 additions & 1 deletion crates/support-scripts/src/program_risc0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl ProgramSupportApi for ProgramSupportRisc0 {
}

/// Run the docker container start script
async fn start(&self) -> Result<()> {
async fn start(&self, linux_network_host_mode: bool) -> Result<()> {
let cwd = env::current_dir()?;
let script = cwd.join(".interfold/support/ctl/start");
ensure_script_exists(&script).await?;
Expand All @@ -39,6 +39,10 @@ impl ProgramSupportApi for ProgramSupportRisc0 {
risc0_config.risc0_dev_mode.to_string(),
];

if linux_network_host_mode {
args.push("--linux-network-host-mode".into());
}

// Boundless support
if let Some(boundless) = &risc0_config.boundless {
args.extend_from_slice(&[
Expand Down
2 changes: 1 addition & 1 deletion crates/support-scripts/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ use async_trait::async_trait;
#[async_trait]
pub trait ProgramSupportApi {
async fn compile(&self) -> Result<()>;
async fn start(&self) -> Result<()>;
async fn start(&self, linux_network_host_mode: bool) -> Result<()>;
async fn upload(&self) -> Result<()>;
}
9 changes: 9 additions & 0 deletions crates/support/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,15 @@ interfold program start
This starts the Docker container running `e3-support-app` on port 13151. If Boundless config is
present, it will submit proofs to the Boundless market. Otherwise it falls back to dev mode.

On Linux, if Docker bridge networking requires firewall rules for host callbacks, use:

```bash
interfold program start --linux-network-host-mode
```

This runs the container with `--network=host` so `localhost` callback URLs work without
`host.local` rewriting. Not needed in `--dev` mode (no Docker) and not useful on macOS Docker Desktop.

### Step 6: Submit an E3 Request

The E3 request is submitted on-chain by the instigator (e.g., CRISP coordination server):
Expand Down
15 changes: 12 additions & 3 deletions crates/support/app/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,18 @@ async fn handle_compute(req: web::Json<ComputeRequest>) -> ActixResult<HttpRespo
};

println!("fhe_inputs.params = {:?}", fhe_inputs.params);
let callback_url = callback_url
.replace("localhost", "host.local")
.replace("127.0.0.1", "host.local");
let callback_url = if std::env::var("INTERFOLD_SKIP_LOCALHOST_REWRITE")
.map(|v| v == "1" || v.eq_ignore_ascii_case("true"))
.unwrap_or(false)
{
// Docker --network=host: localhost in the container is the host.
callback_url
} else {
// Bridge networking: rewrite so callbacks reach the host via host-gateway.
callback_url
.replace("localhost", "host.local")
.replace("127.0.0.1", "host.local")
};

// Process computation in background
tokio::spawn(async move {
Expand Down