From 1d6f14eff05fd68e8652d32bf75151f9f847dc06 Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Tue, 2 Jun 2026 15:19:04 +0200 Subject: [PATCH 1/2] feat: enable fiduciary and TestThresholdKeys subnets by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As of pocket-ic 14.0.0, threshold keys (test_key_1, dfx_test_key) are no longer held by the II or fiduciary subnets — they moved exclusively to the new TestThresholdKeys subnet. This broke any workflow relying on --ii to get threshold signing, which was the prior implicit behavior. Enable both TestThresholdKeys and fiduciary unconditionally (alongside NNS) so threshold keys are always available and mainnet topology is mirrored without requiring extra flags. Also expose TestThresholdKeys as a --subnet=test-threshold-keys option for completeness, and update README and SPEC to reflect the new defaults and the corrected description of where threshold keys come from. Co-Authored-By: Claude Sonnet 4.6 --- README.md | 43 +++++++++++++++++++++---------------------- SPEC.md | 2 +- src/main.rs | 16 +++++++++++++--- 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 9052d57..74d2428 100644 --- a/README.md +++ b/README.md @@ -39,26 +39,28 @@ One launcher version is tied to one PocketIC version — if the PocketIC version ### Subnet Configuration -The `--subnet` flag controls which subnets the local network includes. Available types: `application`, `system`, `verified-application`, `bitcoin`, `fiduciary`, `nns`, `sns`. +The `--subnet` flag controls which subnets the local network includes. Available types: `application`, `system`, `verified-application`, `bitcoin`, `fiduciary`, `nns`, `sns`, `test-threshold-keys`. **Default behavior:** - With no `--subnet` flags: one **application** subnet is created. - With any `--subnet` flag: the default application subnet is **not** created. Only explicitly specified subnets are added. - An **NNS** subnet is **always** created regardless of flags (it is required for system operations). +- A **fiduciary** subnet is **always** created regardless of flags (it mirrors the mainnet topology). +- A **TestThresholdKeys** subnet is **always** created regardless of flags (it provides `test_key_1` and `dfx_test_key` for all threshold algorithms: ECDSA, Schnorr, and VetKd). **Examples:** ```sh -# Default: application + NNS +# Default: NNS + fiduciary + TestThresholdKeys + application icp-cli-network-launcher -# Two application subnets + NNS (for cross-subnet testing) +# Two application subnets (NNS + fiduciary + TestThresholdKeys always included) icp-cli-network-launcher --subnet=application --subnet=application -# System + application + NNS +# System + application (NNS + fiduciary + TestThresholdKeys always included) icp-cli-network-launcher --subnet=system --subnet=application -# Only system + NNS (no application subnet!) +# Only system (no application subnet!) + NNS + fiduciary + TestThresholdKeys icp-cli-network-launcher --subnet=system ``` @@ -68,10 +70,6 @@ The `--ii` flag creates an II subnet and installs the Internet Identity canister The II subnet and canister are also **implicitly enabled** when any of the following are used: - `--nns` -- `--bitcoind-addr` -- `--dogecoind-addr` - -This is because the II subnet provides threshold signature keys (tECDSA/tSchnorr) that are required for Bitcoin and Dogecoin signing operations, and by NNS/SNS governance. Using `--ii` explicitly alongside these flags is valid but redundant. ### NNS @@ -87,7 +85,6 @@ The `--bitcoind-addr` and `--dogecoind-addr` flags connect the network to extern **Implicit effects:** - A **bitcoin** subnet is automatically created (shared by both Bitcoin and Dogecoin) -- An **II** subnet is automatically created (provides threshold signing keys) - The respective chain feature (bitcoin or dogecoin) is enabled **Address format:** `host:port` — this is the P2P address of the node, not the RPC address. @@ -107,23 +104,25 @@ icp-cli-network-launcher --bitcoind-addr=127.0.0.1:18444 --bitcoind-addr=192.168 ### Interaction Summary -The following table summarizes the subnets created for common configurations. An NNS subnet is always present. +The following table summarizes the subnets created for common configurations. NNS, fiduciary, and TestThresholdKeys subnets are always present regardless of flags. -| Configuration | Subnets created | -|---------------------------------------|-------------------------------| -| *(no flags)* | application, NNS | -| `--ii` | application, NNS, II | -| `--nns` | application, NNS, II, SNS | -| `--bitcoind-addr=...` | application, NNS, bitcoin, II | -| `--dogecoind-addr=...` | application, NNS, bitcoin, II | -| `--subnet=system` | system, NNS | -| `--subnet=system --bitcoind-addr=...` | system, NNS, bitcoin, II | -| `--nns --subnet=system` | system, NNS, II, SNS | +| Configuration | Subnets created | +|---------------------------------------|--------------------------------------------------------------| +| *(no flags)* | NNS, fiduciary, TestThresholdKeys, application | +| `--ii` | NNS, fiduciary, TestThresholdKeys, application, II | +| `--nns` | NNS, fiduciary, TestThresholdKeys, application, II, SNS | +| `--bitcoind-addr=...` | NNS, fiduciary, TestThresholdKeys, application, bitcoin | +| `--dogecoind-addr=...` | NNS, fiduciary, TestThresholdKeys, application, bitcoin | +| `--subnet=system` | NNS, fiduciary, TestThresholdKeys, system | +| `--subnet=system --bitcoind-addr=...` | NNS, fiduciary, TestThresholdKeys, system, bitcoin | +| `--nns --subnet=system` | NNS, fiduciary, TestThresholdKeys, system, II, SNS | **Key points:** +- NNS, fiduciary, and TestThresholdKeys are always present — they cannot be omitted. - Specifying any `--subnet` flag replaces the default application subnet. Add `--subnet=application` explicitly if you still need it. -- `--bitcoind-addr` and `--dogecoind-addr` always add a bitcoin subnet and an II subnet, regardless of `--subnet` flags. +- `--bitcoind-addr` and `--dogecoind-addr` always add a bitcoin subnet, regardless of `--subnet` flags. - `--nns` always adds an SNS subnet and an II subnet, regardless of `--subnet` flags. +- Threshold signature keys (`test_key_1`, `dfx_test_key`) are always available via the TestThresholdKeys subnet — `--ii` is not required for threshold signing. ### Status File diff --git a/SPEC.md b/SPEC.md index 8cd0dec..425e94b 100644 --- a/SPEC.md +++ b/SPEC.md @@ -17,7 +17,7 @@ The following flags are accepted by the CLI. All flags are optional. * `--bind=`: Specifies the IP address/network interface to bind both ports to. * `--state-dir=`: Specifies the directory that PocketIC's state should be saved to/loaded from. * `--artificial-delay-ms=`: In milliseconds, specifies an artificial network latency that update calls should incur. -* `--subnet=`†: Adds a subnet of kind `KIND` to the subnet list. This flag is repeatable. Valid subnet kinds are `application`, `system`, `verified-application`, `bitcoin`, `fiduciary`, `nns`, and `sns`. Regardless of flags, the system subnet will be created. If no flags are specified, one application subnet is created. +* `--subnet=`†: Adds a subnet of kind `KIND` to the subnet list. This flag is repeatable. Valid subnet kinds are `application`, `system`, `verified-application`, `bitcoin`, `fiduciary`, `nns`, `sns`, and `test-threshold-keys`. Regardless of flags, the NNS subnet is always created, and threshold keys `key_1`, `test_key_1`, and `dfx_test_key` are always available for all supported algorithms (ECDSA, Schnorr, VetKd). If no flags are specified, one application subnet is created. * `--bitcoind-addr=`: Specifies a bitcoind node to connect to, enables regtest Bitcoin support, and implies `--subnet=bitcoin`. This flag is repeatable. * `--dogecoind-addr=`: Specifies a dogecoind node to connect to, enables regtest Dogecoin support, and implies `--subnet=bitcoin`. This flag is repeatable. * `--ii`†: Installs the Internet Identity canister. diff --git a/src/main.rs b/src/main.rs index 45e3409..fa5f625 100644 --- a/src/main.rs +++ b/src/main.rs @@ -53,7 +53,7 @@ struct Cli { /// Artificial delay for execution, in milliseconds. #[arg(long)] artificial_delay_ms: Option, - /// List of subnets to create. `--subnet=nns` is always implied. Defaults to `--subnet=application`. + /// List of subnets to create. `--subnet=nns`, `--subnet=fiduciary`, and `--subnet=test-threshold-keys` are always implied. Defaults to `--subnet=application` when no subnets are specified. #[arg(long, value_enum, action = ArgAction::Append)] subnet: Vec, /// Addresses of bitcoind nodes to connect to (e.g. 127.0.0.1:18444 or bitcoind:18444). @@ -106,6 +106,7 @@ enum SubnetKind { Fiduciary, Nns, Sns, + TestThresholdKeys, #[cfg(feature = "cloud-engine")] CloudEngine, } @@ -278,12 +279,19 @@ async fn main() -> anyhow::Result<()> { SubnetKind::Fiduciary => pic = pic.with_fiduciary_subnet(), SubnetKind::Nns => pic = pic.with_nns_subnet(), SubnetKind::Sns => pic = pic.with_sns_subnet(), + SubnetKind::TestThresholdKeys => pic = pic.with_test_threshold_keys_subnet(), #[cfg(feature = "cloud-engine")] SubnetKind::CloudEngine => {} // handled above } } } pic = pic.with_nns_subnet(); + // Fiduciary mirrors the mainnet topology and is always present. + pic = pic.with_fiduciary_subnet(); + // TestThresholdKeys holds test_key_1 and dfx_test_key for all threshold algorithms + // (ECDSA, Schnorr, VetKd). As of pocket-ic 14.0.0 these keys are no longer held by + // the II or fiduciary subnets. + pic = pic.with_test_threshold_keys_subnet(); // --bitcoind-addr and --dogecoind-addr imply --subnet=bitcoin if !bitcoind_addr.is_empty() || !dogecoind_addr.is_empty() { pic = pic.with_bitcoin_subnet(); @@ -295,8 +303,10 @@ async fn main() -> anyhow::Result<()> { registry: Some(IcpFeaturesConfig::DefaultConfig), ..<_>::default() }; - // II subnet provides threshold signature keys (tECDSA) needed for Bitcoin/Dogecoin signing - if nns || ii || !bitcoind_addr.is_empty() || !dogecoind_addr.is_empty() { + // II subnet and canister are needed for NNS/SNS governance and Internet Identity. + // Threshold signature keys (tECDSA/tSchnorr/VetKd) are provided by the TestThresholdKeys + // subnet, which is always enabled — Bitcoin/Dogecoin signing does not require II. + if nns || ii { pic = pic.with_ii_subnet(); features.ii = Some(IcpFeaturesConfig::DefaultConfig); } From 2c41bdfc747d9e0a26f0268e841ea42dbb3d0325 Mon Sep 17 00:00:00 2001 From: Linwei Shang Date: Tue, 2 Jun 2026 10:32:38 -0400 Subject: [PATCH 2/2] refactor: split always-on base topology from --subnet workload selection (#64) Co-authored-by: Claude Opus 4.8 (1M context) --- README.md | 18 ++++++++++++------ SPEC.md | 2 +- src/main.rs | 32 ++++++++++++++++++-------------- 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 74d2428..1f99168 100644 --- a/README.md +++ b/README.md @@ -39,14 +39,20 @@ One launcher version is tied to one PocketIC version — if the PocketIC version ### Subnet Configuration -The `--subnet` flag controls which subnets the local network includes. Available types: `application`, `system`, `verified-application`, `bitcoin`, `fiduciary`, `nns`, `sns`, `test-threshold-keys`. +Subnets fall into two independent categories: + +**Always-on base topology** — created unconditionally, not affected by `--subnet`: +- **NNS** — required for system operations. +- **fiduciary** — mirrors the mainnet topology. +- **test-threshold-keys** — provides `test_key_1` and `dfx_test_key` for all threshold algorithms (ECDSA, Schnorr, and VetKd). + +**Workload subnets** — selected with the `--subnet` flag. Available types: `application`, `system`, `verified-application`, `bitcoin`, `sns`. **Default behavior:** -- With no `--subnet` flags: one **application** subnet is created. -- With any `--subnet` flag: the default application subnet is **not** created. Only explicitly specified subnets are added. -- An **NNS** subnet is **always** created regardless of flags (it is required for system operations). -- A **fiduciary** subnet is **always** created regardless of flags (it mirrors the mainnet topology). -- A **TestThresholdKeys** subnet is **always** created regardless of flags (it provides `test_key_1` and `dfx_test_key` for all threshold algorithms: ECDSA, Schnorr, and VetKd). +- With no `--subnet` flags: one **application** subnet is created (in addition to the base topology). +- With any `--subnet` flag: the default application subnet is **not** created; only the workload subnets you specify are added. + +> `--subnet=nns` and `--subnet=fiduciary` are still accepted for backward compatibility but have no effect, since those subnets are always created. `--subnet=test-threshold-keys` is not a valid value. **Examples:** diff --git a/SPEC.md b/SPEC.md index 425e94b..193a623 100644 --- a/SPEC.md +++ b/SPEC.md @@ -17,7 +17,7 @@ The following flags are accepted by the CLI. All flags are optional. * `--bind=`: Specifies the IP address/network interface to bind both ports to. * `--state-dir=`: Specifies the directory that PocketIC's state should be saved to/loaded from. * `--artificial-delay-ms=`: In milliseconds, specifies an artificial network latency that update calls should incur. -* `--subnet=`†: Adds a subnet of kind `KIND` to the subnet list. This flag is repeatable. Valid subnet kinds are `application`, `system`, `verified-application`, `bitcoin`, `fiduciary`, `nns`, `sns`, and `test-threshold-keys`. Regardless of flags, the NNS subnet is always created, and threshold keys `key_1`, `test_key_1`, and `dfx_test_key` are always available for all supported algorithms (ECDSA, Schnorr, VetKd). If no flags are specified, one application subnet is created. +* `--subnet=`†: Adds a workload subnet of kind `KIND` to the subnet list. This flag is repeatable. Valid subnet kinds are `application`, `system`, `verified-application`, `bitcoin`, and `sns`. If no flags are specified, one application subnet is created. Regardless of flags, the NNS subnet is always created, and threshold keys `key_1`, `test_key_1`, and `dfx_test_key` are always available for all supported algorithms (ECDSA, Schnorr, VetKd). `nns` and `fiduciary` are also accepted as `KIND` for backward compatibility but have no effect. * `--bitcoind-addr=`: Specifies a bitcoind node to connect to, enables regtest Bitcoin support, and implies `--subnet=bitcoin`. This flag is repeatable. * `--dogecoind-addr=`: Specifies a dogecoind node to connect to, enables regtest Dogecoin support, and implies `--subnet=bitcoin`. This flag is repeatable. * `--ii`†: Installs the Internet Identity canister. diff --git a/src/main.rs b/src/main.rs index fa5f625..ec07cb2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -53,7 +53,7 @@ struct Cli { /// Artificial delay for execution, in milliseconds. #[arg(long)] artificial_delay_ms: Option, - /// List of subnets to create. `--subnet=nns`, `--subnet=fiduciary`, and `--subnet=test-threshold-keys` are always implied. Defaults to `--subnet=application` when no subnets are specified. + /// List of workload subnets to create. Defaults to `--subnet=application` when none are specified. The NNS, fiduciary, and test-threshold-keys subnets are always created regardless of this flag. #[arg(long, value_enum, action = ArgAction::Append)] subnet: Vec, /// Addresses of bitcoind nodes to connect to (e.g. 127.0.0.1:18444 or bitcoind:18444). @@ -103,10 +103,11 @@ enum SubnetKind { System, VerifiedApplication, Bitcoin, - Fiduciary, - Nns, Sns, - TestThresholdKeys, + /// Accepted for backward compatibility but ignored: the NNS subnet is always created. + Nns, + /// Accepted for backward compatibility but ignored: the fiduciary subnet is always created. + Fiduciary, #[cfg(feature = "cloud-engine")] CloudEngine, } @@ -267,6 +268,16 @@ async fn main() -> anyhow::Result<()> { if let Some(dir) = state_dir { pic = pic.with_state_dir(dir.into()); } + // Always-on base topology: mirrors the mainnet subnet layout and provides + // infrastructure. Created unconditionally, independent of --subnet. + pic = pic.with_nns_subnet(); + pic = pic.with_fiduciary_subnet(); + // TestThresholdKeys holds test_key_1 and dfx_test_key for all threshold algorithms + // (ECDSA, Schnorr, VetKd). As of pocket-ic 14.0.0 these keys are no longer held by + // the II or fiduciary subnets. + pic = pic.with_test_threshold_keys_subnet(); + // Workload subnets selected via --subnet. With no --subnet, a single application + // subnet is created. if subnet.is_empty() { pic = pic.with_application_subnet(); } else { @@ -276,22 +287,15 @@ async fn main() -> anyhow::Result<()> { SubnetKind::System => pic = pic.with_system_subnet(), SubnetKind::VerifiedApplication => pic = pic.with_verified_application_subnet(), SubnetKind::Bitcoin => pic = pic.with_bitcoin_subnet(), - SubnetKind::Fiduciary => pic = pic.with_fiduciary_subnet(), - SubnetKind::Nns => pic = pic.with_nns_subnet(), SubnetKind::Sns => pic = pic.with_sns_subnet(), - SubnetKind::TestThresholdKeys => pic = pic.with_test_threshold_keys_subnet(), + // Part of the always-on base topology above; accepted for backward + // compatibility but ignored here. + SubnetKind::Nns | SubnetKind::Fiduciary => {} #[cfg(feature = "cloud-engine")] SubnetKind::CloudEngine => {} // handled above } } } - pic = pic.with_nns_subnet(); - // Fiduciary mirrors the mainnet topology and is always present. - pic = pic.with_fiduciary_subnet(); - // TestThresholdKeys holds test_key_1 and dfx_test_key for all threshold algorithms - // (ECDSA, Schnorr, VetKd). As of pocket-ic 14.0.0 these keys are no longer held by - // the II or fiduciary subnets. - pic = pic.with_test_threshold_keys_subnet(); // --bitcoind-addr and --dogecoind-addr imply --subnet=bitcoin if !bitcoind_addr.is_empty() || !dogecoind_addr.is_empty() { pic = pic.with_bitcoin_subnet();