Skip to content
Draft
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
fe61ae5
fix: status
redpanda-f Jan 2, 2026
c0299c7
update: status
redpanda-f Jan 2, 2026
23490fe
fix: readme
redpanda-f Jan 2, 2026
0fed12d
fix: adv
redpanda-f Jan 2, 2026
10cf2d1
fix: CI fixed, default repo links fixed, should work
redpanda-f Jan 2, 2026
3d2fb43
setup docker
redpanda-f Jan 2, 2026
088f4aa
fix: tar prerequisite
redpanda-f Jan 2, 2026
8d00ea6
fix: manual artifacts/ dir creation
redpanda-f Jan 2, 2026
fe31ba7
fix: default update
redpanda-f Jan 2, 2026
067dce7
fix: defaults
redpanda-f Jan 2, 2026
de84035
update: docker login
redpanda-f Jan 2, 2026
c9a5e42
add: docker images cache
redpanda-f Jan 2, 2026
5ef5f5b
fix: naming for builder image
redpanda-f Jan 2, 2026
16a65e4
add: rust cache
redpanda-f Jan 2, 2026
1e753e9
CI fixes for disk
redpanda-f Jan 2, 2026
ac4f4ce
fix: disk issues
redpanda-f Jan 2, 2026
0cde656
update: CI
redpanda-f Jan 2, 2026
0799a3f
fix: start should be parallel
redpanda-f Jan 2, 2026
ac60492
fix: more robust CI
redpanda-f Jan 2, 2026
6428156
yaml validity
redpanda-f Jan 2, 2026
0c7bdc2
add: backoff logic and retry
redpanda-f Jan 2, 2026
142ae91
fix: retry to defaults
redpanda-f Jan 2, 2026
77b6d88
fix: CI, privileged operations
redpanda-f Jan 2, 2026
edd90a7
fix: ci.yml
redpanda-f Jan 2, 2026
74595fc
fix: compute version hashes
redpanda-f Jan 2, 2026
97928d1
fix: ci
redpanda-f Jan 2, 2026
c2b16a7
fix: ci
redpanda-f Jan 2, 2026
0523ed4
remove: chain progression checks from curio
redpanda-f Jan 5, 2026
318f43b
add: CI
redpanda-f Jan 5, 2026
46c392c
fix: CI
redpanda-f Jan 5, 2026
3f56890
fix: CI
redpanda-f Jan 5, 2026
a5a9b88
remove: writing to file
redpanda-f Jan 5, 2026
9c8ef9b
fix: docker and execution
redpanda-f Jan 5, 2026
dfa8fbc
fix: build
redpanda-f Jan 5, 2026
e5ac3ef
add: userdel
redpanda-f Jan 5, 2026
5905bc0
fix: bunch of issues
redpanda-f Jan 5, 2026
ae992dd
fix: CI
redpanda-f Jan 5, 2026
01a4481
fix: stuff
redpanda-f Jan 5, 2026
0af7e4b
fix: retry proof parameters download
redpanda-f Jan 5, 2026
9a9ac4a
fix: CI downloads proof params from AWS S3
redpanda-f Jan 5, 2026
e9f9c2f
add: debugging
redpanda-f Jan 5, 2026
73e0569
fix: proof params
redpanda-f Jan 5, 2026
a037a69
add: debug logging
redpanda-f Jan 5, 2026
f2e6d23
add: debug logging
redpanda-f Jan 5, 2026
2befd01
Add link to Portainer UI in README
BigLep Jan 6, 2026
3953a29
nit around "Need More" section.
BigLep Jan 6, 2026
30398aa
remove: proof-params SHA check
redpanda-f Jan 7, 2026
d4f2eae
fix: docker images and container names use constant now
redpanda-f Jan 7, 2026
cf0038b
fix: cleanup does not delete previously known docker images for no_do…
redpanda-f Jan 7, 2026
ea521d7
add: deployment fixes
redpanda-f Jan 7, 2026
c744c28
fix: docker images and container names
redpanda-f Jan 7, 2026
637a04b
fix: CI
redpanda-f Jan 7, 2026
e54ef1b
fix: retry logic for PDP retry
redpanda-f Jan 7, 2026
bdacf0b
increase storage attach wait time
redpanda-f Jan 7, 2026
29c1162
fix: constants, view into downloaded code
redpanda-f Jan 7, 2026
ce5d328
update: CI for docker logs dump
redpanda-f Jan 7, 2026
7ae5217
Update ci.yml
redpanda-f Jan 7, 2026
1b898fe
fixes
redpanda-f Jan 8, 2026
d424e64
fix: CI teardown
redpanda-f Jan 8, 2026
15f8d64
add: self hosted runner integration
redpanda-f Jan 12, 2026
c60b43d
add: openssl dependency
redpanda-f Jan 12, 2026
13f6a29
add: openssl-dev dependency
redpanda-f Jan 12, 2026
96c5ef6
CI: lists logs files
redpanda-f Jan 12, 2026
ca9b143
add: synapse updates
redpanda-f Jan 12, 2026
2669472
makehappy: fmt
redpanda-f Jan 12, 2026
71f3c86
fix: curio default
redpanda-f Jan 12, 2026
4ea9d4e
update: bump lotus version to 1.34.4-rc1
redpanda-f Jan 12, 2026
dc47706
fix: branch names
redpanda-f Jan 12, 2026
2797ae5
fix: clippy
redpanda-f Jan 12, 2026
6a05363
add: sysinfo
redpanda-f Jan 12, 2026
334ed27
add: sysinfo
redpanda-f Jan 12, 2026
f4b60ce
add: bigrunner
redpanda-f Jan 13, 2026
ec34f23
chore: update for merged curio and synapse-sdk PRs (#27)
rvagg Jan 15, 2026
9daed7c
update: CI
redpanda-f Jan 15, 2026
be754bf
fix: runs-on
redpanda-f Jan 15, 2026
1aa0628
change: instance type for CI
redpanda-f Jan 15, 2026
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
383 changes: 221 additions & 162 deletions .github/workflows/ci.yml
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given how large this PR is, this seems like something that could be separated out.

Also, does this actually work on github runners? It seems like there is hackery going on here to make it work. Should we just use self-hosted runners? We can get use a similar setup to what we have with Lotus.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no hack here, there is a whole bunch of caching between steps that's needed to make it all run in reasonable time.

The large-ness of this PR is okay since this is still an active development non-stable repo. Breaking this apart is more effort than necessary.

In my opinion, once we have a stable V1, having smaller PRs and CI validation makes more sense.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I think I was maybe misunderstanding what this file is. This is about smoke testing the foc-localnet machineri, not actually running an e2e scenario like "basic deal + retrieaval" that is discussed in #8 is that right? Is this ci.yml is intended to catch problems with foc-localnet code/configuration itself? Basically, if there is an issue with how we create docker images or start containers, this is intended to catch it right? (In my updated updated understanding, this ci.yml is serving as an integration test of all the code in this PR, but it's not serving as a way to validate Synapse for example.). Let me know if I'm misunderstanding things...

Regardless, it would be good to comment in this file about its purpose so there isn't confusion in the future.

(And if this file is really about validating the foc-localnet code itself then I agree it belongs in this PR. Apologies about comments I made elsewhere that suggested this file doesn't belong in PR. In my mind, #8 doesn't belong in this PR. Testing to validate the work of #5 belongs in this PR...)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is about smoke testing the foc-localnet machineri, not actually running an e2e scenario like "basic deal + retrieaval" that is discussed in #8 is that right?

start undertakes a basic check of deal and retrieval before it classifies a start as successful. So, that simple test is there.

Large diffs are not rendered by default.

1,236 changes: 1,236 additions & 0 deletions Advanced_Readme.md
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: seems a bit odd for this "readme" to use lowercase but README.md is all capitalized?
Maybe since this is follow on information for README.md rename to "README_ADVANCED.md" which gets nice lexigraphical sorting?

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "foc-localnet"
version = "0.1.0"
version = "1.0.0-rc.1"
edition = "2021"

[build-dependencies]
Expand Down Expand Up @@ -34,4 +34,5 @@ flate2 = "1.0"
tar = "0.4"
reqwest = { version = "0.11", features = ["blocking"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
sha2 = "0.10"
52 changes: 20 additions & 32 deletions README.md
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Things coming to mind when reading this:

Control "allowed" SP nodes via ~/.foc-localnet/config.toml

Link to the advanced readme that defines how to do this?

System Requirements

Did I see correctly in slack that that only x86 macOS is supported? That seems like an important callout as I don't know if many developers with Macs have x86 anymore.

Also, do we have a backlog item to improve that?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it needs an x86 machine, not particularly with macos. This all is tested against linux on x86_64. But good catch, will call it out.

Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,17 @@ This will:
### Step 3: Start the Network

```bash
cargo run -- start
cargo run -- start --parallel
```

This will:
- Create the genesis block
- Start Lotus daemon with FEVM enabled
- Deploy FOC smart contracts (including MockUSDFC)
- Start storage provider(s)
- Launch Portainer UI for container management
- Launch [Portainer UI](https://docs.docksal.io/use-cases/portainer/) for container management

**If you are feeling adventurous**: Use `cargo run -- start --parallel`, an experimental feature that attempts to parallelize setup steps as much as possible.
**If you are have troubles**: Use `cargo run -- start`, removing parallelism during start, this may take longer.

**That's it!** Your local Filecoin network is running.

Expand Down Expand Up @@ -88,7 +88,7 @@ Each can be:
### 🔒 Deterministic Setup
- **Pinned versions**: All components use specific git tags/commits for reproducibility
- **Deterministic keys**: Uses fixed seeds, generating the same keys on every setup
- **Consistent addresses**: Find derived accounts in `~/.foc-localnet/state/addresses.json`
- **Consistent state**: Each run preserves its context in `~/.foc-localnet/run/<run-id>/step_context.json`

### 🤖 Fully Automated
From building Docker images to deploying contracts—everything is automated:
Expand All @@ -105,8 +105,9 @@ Built with modular steps for easy extension and customization:

### 📜 Programmable
Built for scripting and automation:
- **Contract addresses**: `~/.foc-localnet/state/contract_addresses.json`
- **Account addresses**: `~/.foc-localnet/state/addresses.json`
- **Contract addresses**: `~/.foc-localnet/run/<run-id>/contract_addresses.json`
- **Step context**: `~/.foc-localnet/run/<run-id>/step_context.json`
- **Latest run symlink**: `~/.foc-localnet/state/latest/` → points to most recent run
- Write scripts for testing, demos, CI/CD pipelines, etc.

### 🌐 Isolated Networks
Expand All @@ -133,34 +134,21 @@ Bundled with Portainer for browser-based Docker management—no terminal wizardr

---

## 📂 Where's My Data?

Everything lives in `~/.foc-localnet/`:

```
~/.foc-localnet/
├── state/
│ ├── addresses.json # Derived account addresses
│ └── contract_addresses.json # Deployed smart contracts
├── artifacts/
│ └── docker/volumes/ # Persistent container data
├── logs/ # Container logs
├── repos/ # Cloned Git repositories
└── config.toml # Configuration
```

---

## 🛠️ Need More?

For advanced topics like:
- Custom repository configurations
- Multiple storage provider setups
- Architecture deep-dives
- Troubleshooting guides
- API access and scripting

See **[README_ADVANCED.md](README_ADVANCED.md)** for detailed documentation (coming soon).
See **[Advanced_Readme.md](Advanced_Readme.md)** for comprehensive documentation on:
- **All commands reference** (init, build, start, stop, status, version)
- **Configuration system** (config.toml structure, parameters, editing)
- **Complete directory structure** (what's stored where and why)
- **Resetting and cleanup** (manual cleanup, disk management)
- **Run ID and Step Context** (isolation mechanism, state sharing)
- **Docker and networking** (container architecture, network topology, Portainer debugging)
- **Repository management** (using local repos, sharing configurations)
- **Command flags** (detailed explanations of all flags and when to use them)
- **Lifecycle overview** (full startup sequence, step implementation)
- **Service Provider examples** (1 SP with 0 authorized, 3 SPs with top 2 authorized, etc.)
- **Troubleshooting guides** (port conflicts, build failures, network issues)
- **Advanced topics** (custom genesis, Lotus API access, contract interaction)

---

Expand Down
9 changes: 9 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,15 @@ fn generate_mockusdfc_archive() {
return;
}

// Ensure artifacts directory exists
let artifacts_dir = Path::new("artifacts");
if !artifacts_dir.exists() {
if let Err(e) = std::fs::create_dir_all(artifacts_dir) {
eprintln!("Warning: Failed to create artifacts directory: {}", e);
return;
}
}

// Create tar.gz archive in contracts/ directory
let output = Command::new("tar")
.args(["-czf", "artifacts/MockUSDFC.tar.gz", "contracts/MockUSDFC"])
Expand Down
3 changes: 2 additions & 1 deletion docker/builder/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ ENV PATH=$PATH:/usr/local/go/bin
# Create foc-user and foc-group with matching host UID/GID when it is run. The 1002 below is just a placeholder which will be replaced during build process. See `docker.rs`
ARG USER_ID=1002
ARG GROUP_ID=1002
RUN userdel ubuntu || true
RUN groupadd -g ${GROUP_ID} foc-group && \
useradd -l -u ${USER_ID} -g foc-group -m -s /bin/bash foc-user && \
mkdir -p /home/foc-user/go/pkg && \
chown -R foc-user:foc-group /home/foc-user/go
chown -R foc-user:foc-group /home/foc-user

# Install Rust as foc-user
USER foc-user
Expand Down
1 change: 1 addition & 0 deletions docker/curio/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ RUN apt-get update && apt-get install -y \
# Create foc-user and foc-group with matching host UID/GID when it is run. The 1002 below is just a placeholder which will be replaced during build process. See `docker.rs`
ARG USER_ID=1002
ARG GROUP_ID=1002
RUN userdel ubuntu || true
RUN groupadd -g ${GROUP_ID} foc-group && \
useradd -l -u ${USER_ID} -g foc-group -m -s /bin/bash foc-user

Expand Down
1 change: 1 addition & 0 deletions docker/lotus-miner/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ RUN apt-get update && apt-get install -y \
# Create foc-user and foc-group with matching host UID/GID when it is run. The 1002 below is just a placeholder which will be replaced during build process. See `docker.rs`
ARG USER_ID=1002
ARG GROUP_ID=1002
RUN userdel ubuntu || true
RUN groupadd -g ${GROUP_ID} foc-group && \
useradd -l -u ${USER_ID} -g foc-group -m -s /bin/bash foc-user

Expand Down
1 change: 1 addition & 0 deletions docker/lotus/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ RUN apt-get update && apt-get install -y \
# Create foc-user and foc-group with matching host UID/GID when it is run. The 1002 below is just a placeholder which will be replaced during build process. See `docker.rs`
ARG USER_ID=1002
ARG GROUP_ID=1002
RUN userdel ubuntu || true
RUN groupadd -g ${GROUP_ID} foc-group && \
useradd -l -u ${USER_ID} -g foc-group -m -s /bin/bash foc-user

Expand Down
1 change: 1 addition & 0 deletions docker/yugabyte/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ ENV LC_ALL=en_US.UTF-8
# Create foc-user and foc-group with matching host UID/GID when it is run. The 1002 below is just a placeholder which will be replaced during build process. See `docker.rs`
ARG USER_ID=1002
ARG GROUP_ID=1002
RUN userdel ubuntu || true
RUN groupadd -g ${GROUP_ID} foc-group && \
useradd -l -u ${USER_ID} -g foc-group -m -s /bin/bash foc-user

Expand Down
3 changes: 3 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ pub enum Commands {
/// Use random mnemonic instead of deterministic one
#[arg(long)]
rand: bool,
/// Skip building Docker images (useful when images are already cached)
#[arg(long)]
no_docker_build: bool,
},
/// Build Filecoin projects in a container
Build {
Expand Down
4 changes: 3 additions & 1 deletion src/commands/build/docker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use super::Project;

/// Build the builder Docker image.
pub fn build_builder_image(dockerfile_dir: &str) -> Result<String, Box<dyn std::error::Error>> {
let image_tag = "foc-localnet-builder:latest";
let image_tag = "foc-builder";

// Check if image already exists in Docker
if image_exists(image_tag)? {
Expand Down Expand Up @@ -89,6 +89,8 @@ pub fn setup_docker_run_args(
"foc-user".to_string(),
"--name".to_string(),
container_name,
"-e".to_string(),
"HOME=/home/foc-user".to_string(),
"-v".to_string(),
format!("{}:{}", source_dir, container_source_dir),
"-v".to_string(),
Expand Down
22 changes: 12 additions & 10 deletions src/commands/build/execution.rs → src/commands/build/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ use std::fs::OpenOptions;
use std::io::{BufRead, BufReader, Write};
use std::path::Path;
use std::process::{Command, Stdio};
use tracing::{error, info};
use tracing::info;
use tracing::warn;

/// Run the build process inside the Docker container.
pub fn run_build_in_container(
Expand Down Expand Up @@ -67,34 +68,35 @@ pub fn execute_build_process(
let stdout = child.stdout.take().ok_or("Failed to capture stdout")?;
let stderr = child.stderr.take().ok_or("Failed to capture stderr")?;

// Create clones of the log file for writing
let log_file_clone = OpenOptions::new()
// Create log file
let log_file = OpenOptions::new()
.create(true)
.append(true)
.open(log_path)?;

info!("NOTE: StdErr output does not necessarily indicate failure");

std::thread::sleep(std::time::Duration::from_secs(5));

// Stream stdout to both console and log file
let stdout_handle = std::thread::spawn({
let mut log_file = log_file_clone;
let mut log_file = log_file.try_clone()?;
move || {
let reader = BufReader::new(stdout);
for line in reader.lines().flatten() {
info!("{}", line);
info!("(stdout): {}", line);
writeln!(log_file, "{}", line).ok();
}
}
});

// Stream stderr to both console and log file
let stderr_handle = std::thread::spawn({
let mut log_file = OpenOptions::new()
.create(true)
.append(true)
.open(log_path)?;
let mut log_file = log_file.try_clone()?;
move || {
let reader = BufReader::new(stderr);
for line in reader.lines().flatten() {
error!("{}", line);
warn!("(stderr): {}", line);
writeln!(log_file, "{}", line).ok();
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/commands/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! This module handles building Filecoin projects (Lotus and Curio) in a Docker container.

pub mod docker;
pub mod execution;
pub mod exec;
pub mod logging;
pub mod repository;

Expand All @@ -14,7 +14,7 @@ use std::fs;
use tracing::info;

use self::docker::build_builder_image;
use self::execution::run_build_in_container;
use self::exec::run_build_in_container;

/// Build a project in a Docker container.
///
Expand Down
15 changes: 11 additions & 4 deletions src/commands/init/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ fn cleanup_previous_installation() -> Result<(), Box<dyn std::error::Error>> {
/// * `proof_params_dir` - Optional path to local filecoin-proof-params directory
/// * `force` - Whether to force regeneration of config file
/// * `use_random_mnemonic` - Whether to use random mnemonic for key generation
/// * `no_docker_build` - Whether to skip artifact downloads and Docker image builds (use when images are already cached)
///
/// # Returns
/// Returns `Ok(())` on successful initialization, or an error if any step fails.
Expand All @@ -107,6 +108,7 @@ pub fn init_environment(
proof_params_dir: Option<String>,
force: bool,
use_random_mnemonic: bool,
no_docker_build: bool,
) -> Result<(), Box<dyn std::error::Error>> {
info!("Initializing foc-localnet environment...");

Expand Down Expand Up @@ -135,11 +137,16 @@ pub fn init_environment(
// Download code repositories
repositories::download_code_repositories()?;

// Download required artifacts (or copy from local paths)
artifacts::download_artifacts(yugabyte_archive, proof_params_dir)?;
// Download required artifacts and build Docker images (unless skipped)
if no_docker_build {
info!("Skipping artifact downloads and Docker image builds (--no-docker-build flag set)");
} else {
// Download required artifacts (or copy from local paths)
artifacts::download_artifacts(yugabyte_archive, proof_params_dir)?;

// Build and cache Docker images
crate::docker::build::build_and_cache_docker_images()?;
// Build and cache Docker images
crate::docker::build::build_and_cache_docker_images()?;
}

info!("✓ Initialization completed successfully");
info!("You can now start the localnet with 'foc-localnet start'");
Expand Down
17 changes: 4 additions & 13 deletions src/commands/requirements/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,25 +95,16 @@ fn install_docker() -> Result<(), Box<dyn std::error::Error>> {
if setup_docker::linux::is_ubuntu_or_debian()? {
setup_docker::linux::install_docker_ubuntu()?;
} else {
eprintln!(
"{}",
"❌ Automatic Docker installation is only supported on Ubuntu/Debian Linux."
);
eprintln!("❌ Automatic Docker installation is only supported on Ubuntu/Debian Linux.");
return Err("Unsupported Linux distribution".into());
}
} else if cfg!(target_os = "macos") {
// On macOS, Docker installation is handled by Homebrew
eprintln!("{}", "❌ Please install Docker Desktop manually on macOS.");
eprintln!(
"{}",
"Download from: https://www.docker.com/products/docker-desktop"
);
eprintln!("❌ Please install Docker Desktop manually on macOS.");
eprintln!("Download from: https://www.docker.com/products/docker-desktop");
return Err("Manual Docker installation required on macOS".into());
} else {
eprintln!(
"{}",
"❌ Automatic Docker installation is not supported on this platform."
);
eprintln!("❌ Automatic Docker installation is not supported on this platform.");
return Err("Unsupported platform".into());
}

Expand Down
Loading
Loading