Skip to content

Commit 3cbaf63

Browse files
committed
feat: support SP-to-SP fetch via host.docker.internal resolution
1 parent 629f8e8 commit 3cbaf63

File tree

7 files changed

+121
-8
lines changed

7 files changed

+121
-8
lines changed

ADVANCED_README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,32 @@ foc-devnet stop
9797
- Preserves Portainer for persistent access
9898
- Clears run ID
9999

100+
### Pausing and Resuming (Resource Saving)
101+
102+
The devnet cluster can consume significant CPU even when idle. Instead of stopping and restarting, you can pause containers to freeze all processes while preserving state.
103+
104+
**Pause the cluster (instant, stops all CPU usage):**
105+
```bash
106+
docker ps --filter "name=foc-" -q | xargs docker pause
107+
```
108+
109+
**Resume the cluster (instant):**
110+
```bash
111+
docker ps --filter "name=foc-" -q | xargs docker unpause
112+
```
113+
114+
**Verify paused state:**
115+
```bash
116+
docker ps --filter "name=foc-" --format "{{.Names}}: {{.Status}}"
117+
# Shows: foc-<run-id>-lotus: Up 12 minutes (Paused)
118+
```
119+
120+
**Convenience aliases (add to ~/.bashrc or ~/.zshrc):**
121+
```bash
122+
alias foc-pause='docker ps --filter "name=foc-" -q | xargs docker pause && echo "Cluster paused"'
123+
alias foc-unpause='docker ps --filter "name=foc-" -q | xargs docker unpause && echo "Cluster resumed"'
124+
```
125+
100126
### `status`
101127
Shows the current status of the foc-devnet system.
102128

README.md

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,27 @@ A developer-friendly tool for spinning up complete Filecoin test networks with s
1010

1111
Get up and running in three simple steps:
1212

13-
### Step 0: Ensure non-root user
14-
`foc-devnet` requires itself to be run by a non-root user. Please ensure that you are running as a non-root user which is part of `docker` group.
13+
### Prerequisites
1514

16-
Run the following to see your User ID and groups you are a part of:
17-
```
15+
**Non-root user with Docker access**: `foc-devnet` must be run by a non-root user in the `docker` group.
16+
17+
```bash
1818
echo $(id -u); groups | grep 'docker'
1919
```
2020

21+
**Configure host.docker.internal**: Add this entry to `/etc/hosts` so SP URLs work from both host and containers:
22+
23+
```bash
24+
echo '127.0.0.1 host.docker.internal' | sudo tee -a /etc/hosts
25+
```
26+
27+
This is required for SP-to-SP fetch. `foc-devnet start` will check for this and fail with instructions if not configured.
28+
29+
For GitHub Actions, add this step before running foc-devnet:
30+
```yaml
31+
- run: echo '127.0.0.1 host.docker.internal' | sudo tee -a /etc/hosts
32+
```
33+
2134
### Step 1: Initialize
2235
2336
```bash

src/commands/start/curio/daemon.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ fn build_docker_create_args(
153153
container_name.to_string(),
154154
"--network".to_string(),
155155
pdp_miner_network_name(run_id, sp_index),
156+
// Enable host.docker.internal for SP-to-SP fetch (resolves to host gateway)
157+
"--add-host=host.docker.internal:host-gateway".to_string(),
156158
];
157159

158160
// Port mappings - get dynamically allocated ports from context

src/commands/start/curio/db_setup.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ pub fn build_foc_contract_env_vars(context: &SetupContext) -> Result<Vec<String>
6868
.to_string(),
6969
);
7070

71+
// Allow insecure sources (HTTP, localhost, private IPs) for SP-to-SP fetch in devnet
72+
env_vars.push("CURIO_FETCH_ALLOW_INSECURE=1".to_string());
73+
7174
Ok(env_vars)
7275
}
7376

src/commands/start/mod.rs

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,73 @@ use crate::paths::{foc_devnet_config, foc_devnet_run_dir};
3636
use crate::run_id::{create_latest_symlink, save_current_run_id};
3737
use crate::version_info::write_version_file;
3838
pub use eth_acc_funding::constants::FEVM_ACCOUNTS_PREFUNDED;
39+
use std::net::ToSocketAddrs;
3940
use std::path::{Path, PathBuf};
40-
use tracing::{info, warn};
41+
use tracing::{error, info, warn};
42+
43+
/// Check that host.docker.internal resolves to 127.0.0.1.
44+
///
45+
/// This is required for SP-to-SP fetch to work. The hostname must resolve to localhost
46+
/// so that URLs registered in the SP registry work from both the host and inside containers.
47+
///
48+
/// On macOS with Docker Desktop, this works automatically.
49+
/// On Linux, users must add `127.0.0.1 host.docker.internal` to /etc/hosts.
50+
fn check_host_docker_internal() -> Result<(), Box<dyn std::error::Error>> {
51+
info!("Checking host.docker.internal resolution...");
52+
53+
// Try to resolve host.docker.internal:80 (port doesn't matter, just need DNS resolution)
54+
match "host.docker.internal:80".to_socket_addrs() {
55+
Ok(mut addrs) => {
56+
// Check if any resolved address is 127.0.0.1
57+
let is_localhost = addrs.any(|addr| {
58+
addr.ip().is_loopback()
59+
});
60+
61+
if is_localhost {
62+
info!("✓ host.docker.internal resolves to localhost");
63+
Ok(())
64+
} else {
65+
error!("════════════════════════════════════════════════════════════════════");
66+
error!("ERROR: host.docker.internal does not resolve to localhost (127.0.0.1)");
67+
error!("════════════════════════════════════════════════════════════════════");
68+
error!("");
69+
error!("SP-to-SP fetch requires host.docker.internal to resolve to 127.0.0.1");
70+
error!("so that registered SP URLs work from both host and containers.");
71+
error!("");
72+
error!("To fix this, add the following line to /etc/hosts:");
73+
error!("");
74+
error!(" 127.0.0.1 host.docker.internal");
75+
error!("");
76+
error!("You can do this with:");
77+
error!(" echo '127.0.0.1 host.docker.internal' | sudo tee -a /etc/hosts");
78+
error!("");
79+
error!("════════════════════════════════════════════════════════════════════");
80+
Err("host.docker.internal must resolve to 127.0.0.1".into())
81+
}
82+
}
83+
Err(_) => {
84+
error!("════════════════════════════════════════════════════════════════════");
85+
error!("ERROR: host.docker.internal does not resolve");
86+
error!("════════════════════════════════════════════════════════════════════");
87+
error!("");
88+
error!("SP-to-SP fetch requires host.docker.internal to resolve to 127.0.0.1");
89+
error!("so that registered SP URLs work from both host and containers.");
90+
error!("");
91+
error!("Add the following line to /etc/hosts:");
92+
error!("");
93+
error!(" 127.0.0.1 host.docker.internal");
94+
error!("");
95+
error!("You can do this with:");
96+
error!(" echo '127.0.0.1 host.docker.internal' | sudo tee -a /etc/hosts");
97+
error!("");
98+
error!("For GitHub Actions, add this step before running foc-devnet:");
99+
error!(" - run: echo '127.0.0.1 host.docker.internal' | sudo tee -a /etc/hosts");
100+
error!("");
101+
error!("════════════════════════════════════════════════════════════════════");
102+
Err("host.docker.internal must be resolvable".into())
103+
}
104+
}
105+
}
41106

42107
/// Stop any existing cluster before starting a new one.
43108
fn stop_existing_cluster() -> Result<(), Box<dyn std::error::Error>> {
@@ -411,6 +476,9 @@ pub fn start_cluster(
411476
run_id: String,
412477
notest: bool,
413478
) -> Result<(), Box<dyn std::error::Error>> {
479+
// Check host.docker.internal resolution first (required for SP-to-SP fetch)
480+
check_host_docker_internal()?;
481+
414482
stop_existing_cluster()?;
415483

416484
let (volumes_dir, run_dir, run_id) =

src/commands/start/pdp_service_provider/pdp_service_provider_step.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,8 @@ impl Step for PdpSpRegistrationStep {
201201
let mut provider_ids = Vec::new();
202202

203203
for (sp_index, sp_address, sp_eth_address, pdp_port, should_approve) in sp_data {
204-
let service_url = format!("http://localhost:{}", pdp_port);
204+
// Use host.docker.internal so the URL works from both host and containers
205+
let service_url = format!("http://host.docker.internal:{}", pdp_port);
205206

206207
match registration::register_single_provider(
207208
&registration::ProviderRegistrationParams {

src/config.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,8 @@ impl Default for Config {
228228
commit: "773551bf1e9cf4cdc49aeb63a47a81f8dc5cb9e1".to_string(),
229229
},
230230
yugabyte_download_url: "https://software.yugabyte.com/releases/2.25.1.0/yugabyte-2.25.1.0-b381-linux-x86_64.tar.gz".to_string(),
231-
approved_pdp_sp_count: 1,
232-
active_pdp_sp_count: 1,
231+
approved_pdp_sp_count: 2,
232+
active_pdp_sp_count: 2,
233233
}
234234
}
235235
}

0 commit comments

Comments
 (0)