How to Configure Threshold (t) and Total Nodes (n) in MPCIUM
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_thresholdand is stored asThresholdin theKeyInfostruct. - 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:
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 (lines 72-75):
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 (lines 168-174), the CreateSigningSession function checks:
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 (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):
mpcium-cli generate-peers \
--number 4 \
--output ./peers.json
This produces peers.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 (lines 54-66):
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 (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 ton - t - 1failures 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:
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 (lines 270-279), ensuring newThreshold + 1 <= len(readyOldParticipantIDs).
Summary
- Threshold (t) is set globally via the
mpc_thresholdkey inconfig.yamland stored inKeyInfo.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+1ready participants. - Use
mpcium-cli generate-peersto create the peer list andmpcium-cli benchmark reshto 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, 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.
Can I run MPCIUM with different threshold values for different wallets?
Yes. While mpc_threshold in 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). The registry then discovers the total node count n by querying these entries in pkg/config/peers.go.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →