From 87a27ece76db63438a09602b49e128fe6751a2a8 Mon Sep 17 00:00:00 2001 From: mraszyk <31483726+mraszyk@users.noreply.github.com> Date: Thu, 14 Nov 2024 19:26:25 +0100 Subject: [PATCH] feat: Bitcoin support in PocketIC (#3989) * feat: Bitcoin support in PocketIC * windows --------- Co-authored-by: Linwei Shang --- CHANGELOG.md | 4 ++++ e2e/tests-dfx/bitcoin.bash | 7 +++++++ scripts/workflows/e2e-matrix.py | 4 ---- src/dfx/src/actors/mod.rs | 9 +++++++++ src/dfx/src/actors/pocketic.rs | 36 ++++++++++++++++++++++++++++++--- src/dfx/src/commands/start.rs | 4 ++-- 6 files changed, 55 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 14c8373544..2fc0250a13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ # UNRELEASED +### feat: Bitcoin support in PocketIC + +`dfx start --pocketic` is now compatible with `--bitcoin-node` and `--enable-bitcoin`. + ### feat: all commands will use the DFX_NETWORK from the environment If `DFX_NETWORK` is set in the environment, all commands will use that network by default. diff --git a/e2e/tests-dfx/bitcoin.bash b/e2e/tests-dfx/bitcoin.bash index b7dde65cfd..50de895f95 100644 --- a/e2e/tests-dfx/bitcoin.bash +++ b/e2e/tests-dfx/bitcoin.bash @@ -37,6 +37,7 @@ set_local_network_bitcoin_enabled() { } @test "dfx restarts replica when ic-btc-adapter restarts" { + [[ "$USE_POCKETIC" ]] && skip "skipped for pocketic: PocketIC does not expose bitcoin adapter" dfx_new_assets hello dfx_start --enable-bitcoin @@ -86,6 +87,7 @@ set_local_network_bitcoin_enabled() { } @test "dfx start --bitcoin-node implies --enable-bitcoin" { + [[ "$USE_POCKETIC" ]] && skip "skipped for pocketic: PocketIC does not expose bitcoin adapter" dfx_new hello dfx_start "--bitcoin-node" "127.0.0.1:18444" @@ -93,6 +95,7 @@ set_local_network_bitcoin_enabled() { } @test "dfx start --enable-bitcoin with no other configuration succeeds" { + [[ "$USE_POCKETIC" ]] && skip "skipped for pocketic: PocketIC does not expose bitcoin adapter" dfx_new hello dfx_start --enable-bitcoin @@ -111,6 +114,7 @@ set_local_network_bitcoin_enabled() { } @test "can enable bitcoin through default configuration - dfx start" { + [[ "$USE_POCKETIC" ]] && skip "skipped for pocketic: PocketIC does not expose bitcoin adapter" dfx_new hello define_project_network set_project_default_bitcoin_enabled @@ -121,6 +125,7 @@ set_local_network_bitcoin_enabled() { } @test "can enable bitcoin through shared local network - dfx start" { + [[ "$USE_POCKETIC" ]] && skip "skipped for pocketic: PocketIC does not expose bitcoin adapter" dfx_new hello set_shared_local_network_bitcoin_enabled @@ -130,6 +135,7 @@ set_local_network_bitcoin_enabled() { } @test "can enable bitcoin through local network configuration - dfx start" { + [[ "$USE_POCKETIC" ]] && skip "skipped for pocketic: PocketIC does not expose bitcoin adapter" dfx_new hello set_local_network_bitcoin_enabled @@ -139,6 +145,7 @@ set_local_network_bitcoin_enabled() { } @test "dfx start with both bitcoin and canister http enabled" { + [[ "$USE_POCKETIC" ]] && skip "skipped for pocketic: PocketIC does not expose bitcoin adapter" dfx_new hello dfx_start --enable-bitcoin --enable-canister-http diff --git a/scripts/workflows/e2e-matrix.py b/scripts/workflows/e2e-matrix.py index a039189045..95e8a3ba7e 100755 --- a/scripts/workflows/e2e-matrix.py +++ b/scripts/workflows/e2e-matrix.py @@ -18,10 +18,6 @@ def test_scripts(prefix): "backend": ["pocketic", "replica"], "os": ["macos-13-large", "ubuntu-20.04"], "exclude": [ - { - "backend": "pocketic", - "test": "dfx/bitcoin" - }, { "backend": "pocketic", "test": "dfx/canister_http_adapter" diff --git a/src/dfx/src/actors/mod.rs b/src/dfx/src/actors/mod.rs index 4cc8b1c839..a4a26c5776 100644 --- a/src/dfx/src/actors/mod.rs +++ b/src/dfx/src/actors/mod.rs @@ -203,10 +203,19 @@ pub fn start_pocketic_actor( ) })?; + let bitcoin_integration_config = if local_server_descriptor.bitcoin.enabled { + Some(BitcoinIntegrationConfig { + canister_init_arg: local_server_descriptor.bitcoin.canister_init_arg.clone(), + }) + } else { + None + }; let actor_config = pocketic::Config { pocketic_path, effective_config_path: local_server_descriptor.effective_config_path(), replica_config, + bitcoind_addr: local_server_descriptor.bitcoin.nodes.clone(), + bitcoin_integration_config, port: local_server_descriptor.replica.port, port_file: pocketic_port_path, pid_file: local_server_descriptor.pocketic_pid_path(), diff --git a/src/dfx/src/actors/pocketic.rs b/src/dfx/src/actors/pocketic.rs index bac34f54ee..c143978291 100644 --- a/src/dfx/src/actors/pocketic.rs +++ b/src/dfx/src/actors/pocketic.rs @@ -3,9 +3,14 @@ use crate::actors::shutdown::{wait_for_child_or_receiver, ChildOrReceiver}; use crate::actors::shutdown_controller::signals::outbound::Shutdown; use crate::actors::shutdown_controller::signals::ShutdownSubscribe; use crate::actors::shutdown_controller::ShutdownController; +use crate::actors::BitcoinIntegrationConfig; use crate::lib::error::{DfxError, DfxResult}; #[cfg(unix)] use crate::lib::info::replica_rev; +#[cfg(unix)] +use crate::lib::integrations::bitcoin::initialize_bitcoin_canister; +#[cfg(unix)] +use crate::lib::integrations::create_integrations_agent; use actix::{ Actor, ActorContext, ActorFutureExt, Addr, AsyncContext, Context, Handler, Recipient, ResponseActFuture, Running, WrapFuture, @@ -20,6 +25,7 @@ use dfx_core::config::model::replica_config::ReplicaConfig; #[cfg(unix)] use dfx_core::json::save_json_file; use slog::{debug, error, info, warn, Logger}; +use std::net::SocketAddr; use std::ops::ControlFlow::{self, *}; use std::path::{Path, PathBuf}; use std::thread::JoinHandle; @@ -43,6 +49,8 @@ pub struct Config { pub pocketic_path: PathBuf, pub effective_config_path: PathBuf, pub replica_config: ReplicaConfig, + pub bitcoind_addr: Option>, + pub bitcoin_integration_config: Option, pub port: Option, pub port_file: PathBuf, pub pid_file: PathBuf, @@ -265,6 +273,8 @@ fn pocketic_start_thread( let instance = match initialize_pocketic( port, &config.effective_config_path, + &config.bitcoind_addr, + &config.bitcoin_integration_config, &config.replica_config, logger.clone(), ) { @@ -322,6 +332,8 @@ fn pocketic_start_thread( async fn initialize_pocketic( port: u16, effective_config_path: &Path, + bitcoind_addr: &Option>, + bitcoin_integration_config: &Option, replica_config: &ReplicaConfig, logger: Logger, ) -> DfxResult { @@ -339,7 +351,7 @@ async fn initialize_pocketic( sns: Some(SubnetSpec::default()), ii: Some(SubnetSpec::default()), fiduciary: None, - bitcoin: None, + bitcoin: Some(SubnetSpec::default()), system: vec![], verified_application: vec![], application: vec![], @@ -358,7 +370,7 @@ async fn initialize_pocketic( state_dir: Some(replica_config.state_manager.state_root.clone()), nonmainnet_features: true, log_level: Some(replica_config.log_level.to_ic_starter_string()), - bitcoind_addr: None, + bitcoind_addr: bitcoind_addr.clone(), }) .send() .await? @@ -420,12 +432,30 @@ async fn initialize_pocketic( .send() .await? .error_for_status()?; + + let agent_url = format!("http://localhost:{port}/instances/{instance}/"); + + debug!(logger, "Waiting for replica to report healthy status"); + crate::lib::replica::status::ping_and_wait(&agent_url).await?; + + if let Some(bitcoin_integration_config) = bitcoin_integration_config { + let agent = create_integrations_agent(&agent_url, &logger).await?; + initialize_bitcoin_canister(&agent, &logger, bitcoin_integration_config.clone()).await?; + } + info!(logger, "Initialized PocketIC."); Ok(instance) } #[cfg(not(unix))] -fn initialize_pocketic(_: u16, _: &Path, _: &ReplicaConfig, _: Logger) -> DfxResult { +fn initialize_pocketic( + _: u16, + _: &Path, + _: &Option>, + _: &Option, + _: &ReplicaConfig, + _: Logger, +) -> DfxResult { bail!("PocketIC not supported on this platform") } diff --git a/src/dfx/src/commands/start.rs b/src/dfx/src/commands/start.rs index 909058dfa4..9ba08000d9 100644 --- a/src/dfx/src/commands/start.rs +++ b/src/dfx/src/commands/start.rs @@ -59,11 +59,11 @@ pub struct StartOpts { clean: bool, /// Address of bitcoind node. Implies --enable-bitcoin. - #[arg(long, action = ArgAction::Append, conflicts_with = "pocketic")] + #[arg(long, action = ArgAction::Append)] bitcoin_node: Vec, /// enable bitcoin integration - #[arg(long, conflicts_with = "pocketic")] + #[arg(long)] enable_bitcoin: bool, /// enable canister http requests (on by default for --pocketic)