Overview
The create-threshold command splits an Ethereum validator private key into threshold shares using Shamir Secret Sharing (SSS). These shares can be distributed across multiple SSV operators for distributed validation.
This command is FOR TESTING ONLY . For production use, always use the ssv-keys tool which provides additional security features and proper key ceremony workflows.
Usage
ssvnode create-threshold --private-key= < validator-private-key > --count= < operator-count >
Flags
Hex-encoded Ethereum validator BLS private key to split into shares. This should be a 64-character hex string (32 bytes) representing your validator’s secret key. ssvnode create-threshold --private-key=0x1234567890abcdef... --count=4
Number of operator shares to generate. Must be a valid cluster size following the 3f+1 Byzantine fault tolerance model:
4 operators (tolerates 1 Byzantine fault)
7 operators (tolerates 2 Byzantine faults)
10 operators (tolerates 3 Byzantine faults)
13 operators (tolerates 4 Byzantine faults)
ssvnode create-threshold --private-key=0x1234... --count=7
How It Works
Threshold Cryptography
The command implements Shamir Secret Sharing (SSS) to split a validator key:
Input : Single validator BLS private key
Process : Generate N shares with threshold T (where T = ⌈(N+1)/2⌉)
Output : N threshold shares, requiring T shares to reconstruct signatures
Quorum Requirements
For each cluster size, the quorum (minimum shares needed) is:
Operators (N) Quorum (T) Fault Tolerance (f) 4 3 1 7 5 2 10 7 3 13 9 4
This follows the Byzantine Fault Tolerance formula: N = 3f + 1 where f is the number of faulty nodes tolerated.
Examples
Generate 4-Operator Shares
./bin/ssvnode create-threshold \
--private-key=0x2e0834786285daccd064ca17f1654f67b4aef298acbb82cef9ec422fb4975622 \
--count=4
Output
Generating threshold keys for validator a9b14f6e...8c7d3f2e
Public key 0 8f65d7e2b9c4a3f1d8e6b2c9f4a7e3d1c8b5a2e9f6d3c0b7a4e1d8c5b2a9f6e3
Private key 0 1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2
Public key 1 7e2b9c4a3f1d8e6b2c9f4a7e3d1c8b5a2e9f6d3c0b7a4e1d8c5b2a9f6e38f65
Private key 1 2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a21a
Public key 2 9c4a3f1d8e6b2c9f4a7e3d1c8b5a2e9f6d3c0b7a4e1d8c5b2a9f6e38f657e2b
Private key 2 3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a21a2b
Public key 3 4a3f1d8e6b2c9f4a7e3d1c8b5a2e9f6d3c0b7a4e1d8c5b2a9f6e38f657e2b9c
Private key 3 4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a21a2b3c
Each operator receives:
Public key - BLS public key for their share
Private key - BLS private key share (hex-encoded)
Generate 7-Operator Shares
For a larger, more fault-tolerant cluster:
./bin/ssvnode create-threshold \
--private-key=0x2e0834786285daccd064ca17f1654f67b4aef298acbb82cef9ec422fb4975622 \
--count=7
This generates 7 shares, requiring 5 signatures (quorum) to perform duties.
Using Generated Shares
Local Development Setup
The generated shares can be used for local testing:
# 1. Generate shares
./bin/ssvnode create-threshold \
--private-key=0x2e0834... \
--count=4
# 2. Create share configuration files (share1.yaml, share2.yaml, etc.)
# For each operator, use their private key share
# 3. Run local cluster
docker-compose up --build ssv-node-1 ssv-node-2 ssv-node-3 ssv-node-4
Share Configuration Example
# Operator 1's share configuration
OperatorPrivateKey : <operator-1-key>
db :
Path : ./data/node1/db
p2p :
TcpPort : 13001
UdpPort : 12001
Discovery : mdns # For local testing
eth2 :
BeaconNodeAddr : http://localhost:5052
eth1 :
ETH1Addr : ws://localhost:8546/ws
Each operator needs their own share’s private key. Never share these keys between operators.
Production Alternative: ssv-keys
For production environments, use the ssv-keys tool instead:
# Install ssv-keys
wget https://github.com/ssvlabs/ssv-keys/releases/download/v1.0.1/ssv-keys-lin
chmod +x ssv-keys-lin
# Generate shares with proper key ceremony
./ssv-keys-lin --keystore=validator_keystore.json \
--password=keystore_password \
--operator-keys=operator1.json,operator2.json,operator3.json,operator4.json \
--output-folder=./shares
Why ssv-keys for Production?
Proper key ceremony workflows
Encrypted share outputs
Support for hardware wallets
Secure key derivation
Direct keystore.json support
Compatible with all Ethereum clients
Proper BLS signature aggregation
Validator metadata handling
Generates payload for contract registration
Creates share files for each operator
Includes operator public keys
Produces ceremony attestations
Multi-validator batch processing
Withdrawal credentials verification
Network configuration (mainnet/testnet)
Audit trail and logging
Error Handling
failed to set hex private key
Cause : Private key is not valid hex or wrong length.Solution : Ensure your private key is:
64 hex characters (32 bytes)
Prefixed with 0x or not (both accepted)
Valid BLS12-381 scalar
# Valid format
--private-key = 2e0834786285daccd064ca17f1654f67b4aef298acbb82cef9ec422fb4975622
# Or
--private-key = 0x2e0834786285daccd064ca17f1654f67b4aef298acbb82cef9ec422fb4975622
Cause : The --count value is not a valid cluster size.Solution : Use valid cluster sizes (3f+1 model):--count = 4 # ✓ Valid
--count = 7 # ✓ Valid
--count = 10 # ✓ Valid
--count = 13 # ✓ Valid
--count = 5 # ✗ Invalid
--count = 6 # ✗ Invalid
Failed to create threshold
failed to turn a private key into a threshold key
Cause : Internal error during share generation.Solution : Verify your inputs and try again:# Check private key format
echo -n "2e0834786285daccd064ca17f1654f67b4aef298acbb82cef9ec422fb4975622" | wc -c
# Should output: 64
# Try with explicit count
./bin/ssvnode create-threshold --private-key=0x2e0834... --count=4
Security Considerations
Critical Security Warnings
Never Use in Production
This command is designed for testing and development only
Production validators require proper key ceremonies
Use ssv-keys for mainnet validators
Protect Private Keys
# ❌ BAD - Key visible in command history
./bin/ssvnode create-threshold --private-key=0x2e0834...
# ✅ BETTER - Use environment variable
export VALIDATOR_KEY = 0x2e0834 ...
./bin/ssvnode create-threshold --private-key= $VALIDATOR_KEY
unset VALIDATOR_KEY
# ✅ BEST - Read from secure file
./bin/ssvnode create-threshold --private-key=$( cat secure_key.txt )
Clear Command History
# After running create-threshold, clear history
history -c
# Or use private session
bash --norc --noprofile
./bin/ssvnode create-threshold --private-key=...
exit
Secure Output
The generated shares are printed to stdout:
# Save shares to encrypted files
./bin/ssvnode create-threshold \
--private-key= $KEY \
--count=4 > shares.txt
# Encrypt the output
gpg --encrypt --recipient [email protected] shares.txt
# Delete plaintext
shred -u shares.txt
Testing Workflow
Complete workflow for local development:
Step 1: Get Validator Key
# Option A: Export from mnemonic (testing only)
./bin/ssvnode export-keys \
--mnemonic= "your test mnemonic phrase..." \
--index=0
# Note the "Private Key" output
# Private Key: 2e0834786285daccd064ca17f1654f67b4aef298acbb82cef9ec422fb4975622
Step 2: Create Threshold Shares
./bin/ssvnode create-threshold \
--private-key=2e0834786285daccd064ca17f1654f67b4aef298acbb82cef9ec422fb4975622 \
--count=4 | tee threshold_output.txt
Step 3: Distribute Shares
# Extract each operator's keys from output
# Create share config files for each operator
# share1.yaml, share2.yaml, share3.yaml, share4.yaml
# Each config includes:
# - Operator private key (from generate-operator-keys)
# - Validator share private key (from create-threshold output)
Step 4: Run Local Cluster
# Start all nodes
docker-compose up --build ssv-node-1 ssv-node-2 ssv-node-3 ssv-node-4
# Verify cluster is running
curl http://localhost:15001/metrics # Node 1
curl http://localhost:15002/metrics # Node 2
See Also