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
44 changes: 32 additions & 12 deletions src/commands/start/curio/daemon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::commands::start::curio::constants::CURIO_LAYERS;
use crate::docker::command_logger::run_and_log_command_strings;
use crate::docker::network::{lotus_network_name, pdp_miner_network_name};
use crate::docker::{container_exists, stop_and_remove_container};
use crate::docker::init::set_volume_ownership;
use crate::paths::{
foc_devnet_bin, foc_devnet_curio_sp_volume, foc_devnet_genesis_sectors_pdp_sp,
foc_devnet_proof_parameters, CONTAINER_FILECOIN_PROOF_PARAMS_PATH,
Expand Down Expand Up @@ -46,7 +47,7 @@ pub fn start_curio_daemon(
create_curio_directories(context, sp_index)?;

// Step 2: Create and start container
let docker_args = build_docker_run_args(context, sp_index, &container_name)?;
let docker_args = build_docker_create_args(context, sp_index, &container_name)?;
start_curio_container(context, &container_name, docker_args)?;

Ok(())
Expand All @@ -63,31 +64,38 @@ fn create_curio_directories(context: &SetupContext, sp_index: usize) -> Result<(
curio_sp_dir.join("long-term-storage"),
];

for dir in dirs {
fs::create_dir_all(&dir)?;
for dir in &dirs {
fs::create_dir_all(dir)?;
}

set_volume_ownership(&curio_sp_dir)?;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

not sure why this wasn't a problem before but it was a blocker for me this time


Ok(())
}

/// Create and start Curio container
///
/// Uses docker create + network connect + start pattern so that:
/// 1. Container is created but not started
/// 2. Networks are connected while container is stopped
/// 3. Container is started with Curio as PID 1 (logs work properly)
fn start_curio_container(
context: &SetupContext,
container_name: &str,
mut docker_args: Vec<String>,
) -> Result<(), Box<dyn Error>> {
info!("Creating container {}...", container_name);

// Add image and command - run curio directly as the main process
// Add image and command - Curio as main process
docker_args.push(crate::constants::CURIO_DOCKER_IMAGE.to_string());
docker_args.push("/usr/local/bin/lotus-bins/curio".to_string());
docker_args.push("run".to_string());
docker_args.push("--nosync".to_string());
docker_args.push("--layers".to_string());
docker_args.push(CURIO_LAYERS.to_string());

// Execute docker run
let key = format!("curio_daemon_start_{}", container_name);
// Execute docker create (not run)
let key = format!("curio_daemon_create_{}", container_name);
let output = run_and_log_command_strings("docker", &docker_args, context, &key)?;

if !output.status.success() {
Expand All @@ -98,7 +106,7 @@ fn start_curio_container(
.into());
}

// Connect to filecoin network
// Connect to filecoin network before starting
let lotus_network = lotus_network_name(context.run_id());
let network_args = vec![
"network".to_string(),
Expand All @@ -109,13 +117,26 @@ fn start_curio_container(
let key = format!("curio_network_connect_{}", container_name);
let _ = run_and_log_command_strings("docker", &network_args, context, &key); // Ignore errors if already connected

info!("Container created");
// Start the container
let start_args = vec!["start".to_string(), container_name.to_string()];
let key = format!("curio_daemon_start_{}", container_name);
let output = run_and_log_command_strings("docker", &start_args, context, &key)?;

if !output.status.success() {
return Err(format!(
"Failed to start curio container: {}",
String::from_utf8_lossy(&output.stderr)
)
.into());
}

info!("Container created and started");

Ok(())
}

/// Build docker run arguments for Curio
fn build_docker_run_args(
/// Build docker create arguments for Curio
fn build_docker_create_args(
context: &SetupContext,
sp_index: usize,
container_name: &str,
Expand All @@ -127,8 +148,7 @@ fn build_docker_run_args(
let genesis_sectors_dir = foc_devnet_genesis_sectors_pdp_sp(run_id, sp_index);

let mut docker_args = vec![
"run".to_string(),
"-d".to_string(),
"create".to_string(),
"--name".to_string(),
container_name.to_string(),
"--network".to_string(),
Expand Down
21 changes: 13 additions & 8 deletions src/commands/start/curio/db_setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,35 +33,40 @@ pub fn build_foc_contract_env_vars(context: &SetupContext) -> Result<Vec<String>

// Get standard contracts
if let Some(usdfc) = addresses.contracts.get("usdfc") {
env_vars.push(format!("CURIO_USDFC={}", usdfc));
env_vars.push(format!("CURIO_DEVNET_USDFC_ADDRESS={}", usdfc));
}

// Get FOC service contracts
if let Some(payment) = addresses.foc_contracts.get("payment_contract") {
env_vars.push(format!("CURIO_PAYMENT_CONTRACT={}", payment));
env_vars.push(format!("CURIO_DEVNET_PAYMENTS_ADDRESS={}", payment));
}
if let Some(multicall) = addresses.foc_contracts.get("multicall_address") {
env_vars.push(format!("CURIO_MULTICALL_ADDRESS={}", multicall));
env_vars.push(format!("CURIO_DEVNET_MULTICALL_ADDRESS={}", multicall));
}
if let Some(pdp) = addresses.foc_contracts.get("p_d_p_verifier_proxy") {
env_vars.push(format!("CURIO_PDP_VERIFIER={}", pdp));
env_vars.push(format!("CURIO_DEVNET_PDP_VERIFIER_ADDRESS={}", pdp));
}
if let Some(fwss) = addresses
.foc_contracts
.get("filecoin_warm_storage_service_proxy")
{
env_vars.push(format!("CURIO_FWS_SERVICE={}", fwss));
env_vars.push(format!("CURIO_DEVNET_FWSS_ADDRESS={}", fwss));
}
if let Some(sp_registry) = addresses
.foc_contracts
.get("service_provider_registry_proxy")
{
env_vars.push(format!("CURIO_SERVICE_REGISTRY={}", sp_registry));
env_vars.push(format!(
"CURIO_DEVNET_SERVICE_REGISTRY_ADDRESS={}",
sp_registry
));
}

// Simple record keeper is always zero address
env_vars
.push("CURIO_SIMPLE_RECORD_KEEPER=0x0000000000000000000000000000000000000000".to_string());
env_vars.push(
"CURIO_DEVNET_RECORD_KEEPER_SIMPLE_ADDRESS=0x0000000000000000000000000000000000000000"
.to_string(),
);

Ok(env_vars)
}
Expand Down
36 changes: 36 additions & 0 deletions src/commands/start/curio/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,39 @@ use std::thread;
use std::time::Duration;
use tracing::info;

/// Wait for Curio RPC to be ready using the built-in wait-api command.
fn wait_for_curio_rpc(context: &SetupContext, container_name: &str) -> Result<(), Box<dyn Error>> {
info!("Waiting for Curio RPC to be ready...");

let machine_addr = format!("{}:12300", container_name);
let key = format!("curio_wait_api_{}", container_name);
let output = run_and_log_command(
"docker",
&[
"exec",
container_name,
"/usr/local/bin/lotus-bins/curio",
"cli",
"--machine",
&machine_addr,
"wait-api",
],
context,
&key,
)?;

if !output.status.success() {
return Err(format!(
"Curio RPC failed to become ready: {}",
String::from_utf8_lossy(&output.stderr)
)
.into());
}

info!("Curio RPC is ready");
Ok(())
}

/// Attach storage locations for a specific PDP SP.
///
/// Attaches:
Expand All @@ -26,6 +59,9 @@ pub fn attach_storage_locations(
let run_id = context.run_id();
let container_name = format!("foc-{}-curio-{}", run_id, sp_index);

// Wait for RPC to be ready before attaching storage
wait_for_curio_rpc(context, &container_name)?;

// Attach fast storage
attach_fast_storage(context, &container_name)?;

Expand Down
3 changes: 3 additions & 0 deletions src/commands/start/foc_deploy/deployment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ pub fn perform_deployment(
) -> Result<(), Box<dyn Error>> {
info!("Deploying FOC service contracts...");

// Clear cached devnet addresses so contracts are actually deployed
super::helpers::clear_cached_devnet_deployments()?;

// Get required addresses from context
let (foc_deployer, foc_deployer_eth, mock_usdfc_address, _global_faucet) =
super::helpers::check_required_addresses(context)?;
Expand Down
38 changes: 38 additions & 0 deletions src/commands/start/foc_deploy/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
//! including repository path resolution and deployment checks.

use crate::config::{Config, Location};
use crate::constants::LOCAL_NETWORK_CHAIN_ID;
use crate::docker::containers::lotus_container_name;
use crate::docker::core::container_is_running;
use crate::paths::{foc_devnet_config, foc_devnet_filecoin_services_repo};
use std::error::Error;
use std::fs;
use std::path::PathBuf;
use tracing::info;

/// Get the filecoin-services repository path based on configuration
///
Expand Down Expand Up @@ -93,3 +95,39 @@ pub fn check_required_addresses(
global_faucet.clone(),
))
}

/// Clear cached devnet deployment addresses from deployments.json
///
/// The filecoin-services deployment script reads deployments.json and skips
/// deployment if addresses already exist for the chain ID. This causes issues
/// when starting a fresh devnet because the cached addresses point to contracts
/// that don't exist on the new chain. This function removes the devnet entry
/// so that contracts are actually deployed.
pub fn clear_cached_devnet_deployments() -> Result<(), Box<dyn Error>> {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

ran into this one once - tried to start again after a previous deployment and it said it skipped over deploying these but it was because it had old addresses that weren't even there

let services_repo = get_filecoin_services_repo_path()?;
let deployments_file = services_repo.join("service_contracts/deployments.json");

if !deployments_file.exists() {
info!("No deployments.json found, skipping cache clear");
return Ok(());
}

let content = fs::read_to_string(&deployments_file)?;
let mut deployments: serde_json::Value = serde_json::from_str(&content)?;

let chain_id_str = LOCAL_NETWORK_CHAIN_ID.to_string();
if let Some(obj) = deployments.as_object_mut() {
if obj.remove(&chain_id_str).is_some() {
info!(
"Cleared cached devnet (chain {}) addresses from deployments.json",
chain_id_str
);
let updated = serde_json::to_string_pretty(&deployments)?;
fs::write(&deployments_file, updated)?;
} else {
info!("No cached devnet addresses found in deployments.json");
}
}

Ok(())
}
44 changes: 15 additions & 29 deletions src/commands/start/synapse_test_e2e/synapse_test_step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ struct DockerTestParams<'a> {
user_key: &'a str,
lotus_rpc_url: &'a str,
warm_storage_addr: &'a str,
multicall3_addr: &'a str,
usdfc_addr: &'a str,
sp_registry_addr: &'a str,
}

Expand Down Expand Up @@ -119,6 +121,8 @@ impl Step for SynapseTestE2EStep {
user_key: &user_key,
lotus_rpc_url: &lotus_rpc_url,
warm_storage_addr: &warm_storage_addr,
multicall3_addr: &multicall3_addr,
usdfc_addr: &usdfc_addr,
sp_registry_addr: &sp_registry_addr,
})
}
Expand Down Expand Up @@ -163,15 +167,14 @@ fn build_docker_command(params: &DockerTestParams) -> Result<Vec<String>, Box<dy
];

// Add environment variables required by synapse-sdk scripts
// Note: example-storage-e2e.js uses env vars, not CLI flags
let env_vars = vec![
("CLIENT_PRIVATE_KEY", params.user_key.to_string()),
("PRIVATE_KEY", params.user_key.to_string()),
("NETWORK", "devnet".to_string()),
("RPC_URL", params.lotus_rpc_url.to_string()),
(
"WARM_STORAGE_CONTRACT_ADDRESS",
params.warm_storage_addr.to_string(),
),
("WARM_STORAGE_ADDRESS", params.warm_storage_addr.to_string()),
("MULTICALL3_ADDRESS", params.multicall3_addr.to_string()),
("USDFC_ADDRESS", params.usdfc_addr.to_string()),
("SP_REGISTRY_ADDRESS", params.sp_registry_addr.to_string()),
("CI", "true".to_string()),
];
Expand Down Expand Up @@ -281,7 +284,7 @@ fn create_random_test_file(run_dir: &Path) -> Result<PathBuf, Box<dyn Error>> {
Ok(random_file_path)
}

/// Generate the shell script using CLI flags expected by synapse-sdk.
/// Generate the shell script for synapse-sdk E2E testing.
fn generate_test_script(
lotus_rpc_url: &str,
warm_storage_addr: &str,
Expand All @@ -299,12 +302,7 @@ fn generate_test_script(
sp_registry_addr,
));
lines.extend(wait_commands());
lines.push(build_storage_e2e_command(
lotus_rpc_url,
warm_storage_addr,
multicall3_addr,
usdfc_addr,
));
lines.push(build_storage_e2e_command());

lines.join("\n")
}
Expand Down Expand Up @@ -363,21 +361,9 @@ fn wait_commands() -> Vec<String> {
}

/// CLI invocation for the storage E2E test.
fn build_storage_e2e_command(
lotus_rpc_url: &str,
warm_storage_addr: &str,
multicall3_addr: &str,
usdfc_addr: &str,
) -> String {
format!(
"echo \"Running storage E2E test...\"\n\
node utils/example-storage-e2e.js \\\n\
--network devnet \\\n\
--rpc-url {} \\\n\
--warm-storage {} \\\n\
--multicall3 {} \\\n\
--usdfc {} \\\n\
/tmp/random_test_file.txt",
lotus_rpc_url, warm_storage_addr, multicall3_addr, usdfc_addr
)
/// The script uses environment variables for configuration (set via Docker -e flags).
fn build_storage_e2e_command() -> String {
"echo \"Running storage E2E test...\"\n\
node utils/example-storage-e2e.js /tmp/random_test_file.txt"
.to_string()
}
8 changes: 4 additions & 4 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,20 +209,20 @@ impl Default for Config {
tag: "v1.34.4-rc1".to_string(),
},
curio: Location::GitBranch {
url: "https://github.com/redpanda-f/curio.git".to_string(),
branch: "feat/pdpv0/redpanda/localnet-setup".to_string(),
url: "https://github.com/filecoin-project/curio.git".to_string(),
branch: "pdpv0".to_string(),
},
filecoin_services: Location::GitBranch {
url: "https://github.com/FilOzone/filecoin-services.git".to_string(),
branch: "feat/redpanda/localnet-deployment-aware".to_string(),
branch: "main".to_string(),
},
multicall3: Location::GitBranch {
url: "https://github.com/mds1/multicall3.git".to_string(),
branch: "main".to_string(),
},
synapse_sdk: Location::GitBranch {
url: "https://github.com/FilOzone/synapse-sdk.git".to_string(),
branch: "feat/redpanda/localnet-support".to_string(),
branch: "master".to_string(),
},
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(),
approved_pdp_sp_count: 1,
Expand Down