# How to Configure Threshold (t) and Total Nodes (n) in MPCIUM

> Learn how to configure threshold (t) and total nodes (n) in MPCIUM. Set mpc_threshold and ensure your peer list has n entries following t+1 ≤ n for security and liveness.

- Repository: [Fystack Labs/mpcium](https://github.com/fystack/mpcium)
- Tags: how-to-guide
- Published: 2026-03-02

---

**To configure the threshold and total nodes in MPCIUM, set `mpc_threshold` in your configuration file for the threshold value (t), and ensure your peer list contains exactly n entries, where the system enforces that t+1 ≤ n to maintain security and liveness.**

MPCIUM implements threshold-signature protocols (ECDSA and EdDSA) on top of a multi-party computation (MPC) registry. Two critical parameters control the security and availability of every wallet: the **threshold (t)** and the **total number of nodes (n)**. This guide explains how to set these values using the actual source implementation in `fystack/mpcium`.

## Understanding Threshold (t) and Total Nodes (n) in MPCIUM

The threshold-signature scheme requires cooperation between multiple parties to generate a valid signature.

- **t (threshold)** – The minimum number of live peers that must cooperate to produce a signature. In the codebase this is referred to as `mpc_threshold` and is stored as `Threshold` in the `KeyInfo` struct.
- **n (total nodes)** – The number of distinct MPC peers that form the committee. This is derived from the peer list stored in Consul under the prefix `mpc_peers/`.

The relationship `t + 1 ≤ n` must hold because the protocol requires **t+1** participants to be ready before a signing session can begin.

## Setting the Threshold Parameter (t)

### Configuration File Setup

The threshold is a global configuration value read via Viper during node startup. Create or edit your [`config.yaml`](https://github.com/fystack/mpcium/blob/main/config.yaml):

```yaml
environment: production
mpc_threshold: 2          # t = 2 requires 3 peers (t+1) to sign

nats:
  url: nats://localhost:4222
consul:
  address: localhost:8500

```

The registry reads this value in [`pkg/mpc/registry.go`](https://github.com/fystack/mpcium/blob/main/pkg/mpc/registry.go) (lines 72-75):

```go
mpcThreshold := viper.GetInt("mpc_threshold")
if mpcThreshold < 1 {
    logger.Fatal("mpc_threshold must be greater than 0", nil)
}

```

### Runtime Validation

When creating a signing session, the node validates that enough peers are ready. In [`pkg/mpc/node.go`](https://github.com/fystack/mpcium/blob/main/pkg/mpc/node.go) (lines 168-174), the `CreateSigningSession` function checks:

```go
if len(readyParticipantIDs) < keyInfo.Threshold+1 {
    return nil, fmt.Errorf("not enough ready participants: got %d, need %d", 
        len(readyParticipantIDs), keyInfo.Threshold+1)
}

```

Similarly, the sign consumer enforces this in [`pkg/eventconsumer/sign_consumer.go`](https://github.com/fystack/mpcium/blob/main/pkg/eventconsumer/sign_consumer.go) (lines 52-65).

## Configuring the Total Number of Nodes (n)

### Generating the Peer List

Use the CLI to generate a static peer list for your cluster. For a 4-node cluster (`n = 4`):

```bash
mpcium-cli generate-peers \
  --number 4 \
  --output ./peers.json

```

This produces [`peers.json`](https://github.com/fystack/mpcium/blob/main/peers.json):

```json
{
  "node0": "c9a4e5b1-0d1f-45e3-9c8d-9f4e6a2d7b5c",
  "node1": "e2b1c4d5-3a9f-4b6d-8e2a-6d4f3c1e9a7b",
  "node2": "a1f3d2c4-7b9e-4c6a-9d1f-2e5b8c3a6d7e",
  "node3": "d4c2b1a3-9e8f-5d6a-1c2b-3e4f5a6b7c8d"
}

```

### Syncing Peers to Consul

When each node starts, it syncs the peer list to Consul under the prefix `mpc_peers/`. In [`cmd/mpcium/main.go`](https://github.com/fystack/mpcium/blob/main/cmd/mpcium/main.go) (lines 54-66):

```go
if err := config.SyncPeersToConsul(cfg.PeersFile); err != nil {
    logger.Fatal("failed to sync peers to consul", zap.Error(err))
}

```

The registry then discovers peers from Consul in [`pkg/config/peers.go`](https://github.com/fystack/mpcium/blob/main/pkg/config/peers.go) (lines 16-35). The total node count `n` equals the number of entries under `mpc_peers/` plus the local node.

## Relationship Between t and n

The protocol enforces that `t + 1 ≤ n`. This requirement stems from the need for **t+1** participants to complete a signing session.

**Security vs. Liveness Trade-off:**

- **Maximum Security:** Set `t = n - 1`. This requires all nodes to sign. If any single node fails, the system halts.
- **Balanced:** Set `t = floor((n-1)/2)`. This tolerates up to `n - t - 1` failures while maintaining a majority requirement.
- **Maximum Liveness:** Set `t = 1`. Only 2 nodes are needed to sign, but compromise of any 2 nodes breaks security.

## Changing Threshold via Resharing

MPCIUM supports resharing to change the threshold without generating new keys. Use the CLI benchmark command with the `--new-threshold` flag:

```bash
mpcium-cli benchmark resh \
  --node-ids node0,node1,node2,node3 \
  --wallet-id my-wallet-123 \
  --new-threshold 3

```

This creates a `Resharing` event with `NewThreshold: 3`. The resharing session validates the new threshold against the current committee size in [`pkg/mpc/ecdsa_resharing_session.go`](https://github.com/fystack/mpcium/blob/main/pkg/mpc/ecdsa_resharing_session.go) (lines 270-279), ensuring `newThreshold + 1 <= len(readyOldParticipantIDs)`.

## Summary

- **Threshold (t)** is set globally via the `mpc_threshold` key in [`config.yaml`](https://github.com/fystack/mpcium/blob/main/config.yaml) and stored in `KeyInfo.Threshold`.
- **Total nodes (n)** is determined by the number of peers registered in Consul under `mpc_peers/` plus the local node.
- The protocol enforces **t+1 ≤ n**; signing requires at least `t+1` ready participants.
- Use `mpcium-cli generate-peers` to create the peer list and `mpcium-cli benchmark resh` to change thresholds dynamically.

## Frequently Asked Questions

### What happens if I set mpc_threshold higher than the number of peers?

The node will fail to create signing sessions. In [`pkg/mpc/node.go`](https://github.com/fystack/mpcium/blob/main/pkg/mpc/node.go), the `CreateSigningSession` function validates that `len(readyParticipantIDs) < keyInfo.Threshold+1` and returns an error if insufficient peers are available. You must ensure `t + 1 ≤ n` before generating keys.

### How do I safely increase the threshold without losing access to my wallet?

Use the resharing protocol via `mpcium-cli benchmark resh` with the `--new-threshold` flag. This updates the `KeyInfo.Threshold` value without changing the underlying private key material. Ensure at least `newThreshold + 1` nodes are online during the resharing operation, as enforced in [`pkg/mpc/ecdsa_resharing_session.go`](https://github.com/fystack/mpcium/blob/main/pkg/mpc/ecdsa_resharing_session.go).

### Can I run MPCIUM with different threshold values for different wallets?

Yes. While `mpc_threshold` in [`config.yaml`](https://github.com/fystack/mpcium/blob/main/config.yaml) sets the default, the threshold is ultimately stored per-wallet in the `KeyInfo` struct. When calling `CreateWallet` via the API or CLI, you can specify a distinct threshold value that overrides the global default for that specific wallet ID.

### Where does MPCIUM store the peer configuration?

Peer configuration is stored in **Consul** under the key prefix `mpc_peers/`. Each node syncs its peer list to Consul during startup via `config.SyncPeersToConsul` (defined in [`cmd/mpcium/main.go`](https://github.com/fystack/mpcium/blob/main/cmd/mpcium/main.go)). The registry then discovers the total node count `n` by querying these entries in [`pkg/config/peers.go`](https://github.com/fystack/mpcium/blob/main/pkg/config/peers.go).