A multi-party-computation signing service for Tendermint nodes using threshold Ed25519 signatures.
Validator operators for tendermint chains balance operational and risk tradeoffs to avoid penalties via slashing for liveliness faults or double signing blocks.
Traditional high-availability systems where the keys exist on hot spares risk double signing if there are failover detection bugs. Low-availability systems, or manual failover, risk downtime if manual intervention cannot respond in a timely manner.
Multi-party computation using threshold signatures is able to provide high-availability while maintaining high security and avoiding double signing via failover detection bugs.
Before starting, please make sure to fully understand node and validator requirements and operation for your particular network and chain. Operation of the mpc tendermint validator assumes prior and detailed knowledge of these aspects.
The security of any key material is outside the scope of this guide. At a minimum we recommend performing key material steps on airgapped computers and using your audited security procedures.
Use the key2shares
utility to split a single validator key into participant shares. Prior to splitting a key, decide on the total number of share holders and how many (threshold) are required to produce a valid signature.
Here we split an ed25519 validating key into 3 shares with a threshold of 2. Together, any 2 key shares can produce a valid signature but no single share can produce a valid signature for our initial key.
key2shares --total 3 --threshold 2 /path/to/priv_validator_key.json
key2shares
writes the shares to the current working directory.
The above example would create 3 output files:
private_share_1.json
private_share_2.json
private_share_3.json
The .json
files contain the private shares and new private RSA keys, one per party, as well as the public RSA keys of the other cosigners.
The RSA keys are generated by key2shares and used to secure party-to-party communication.
Each private share is installed to a separate tendermint mpc validator instance.
The specifics of instance setup and security are outside the scope of this guide, but we recommend practices like geographic distribution of instances and limiting physical and remote instance access as appropriate.
Each instance has a toml configuration file. Below is a sample file corresponding to instance 1
.
mode = "mpc"
# Each validator instance has its own private share.
# Avoid putting more than one share per instance.
key_file = "/path/to/private_share_1.json"
# The state directory stores watermarks for double signing protection.
# Each validator instance maintains a watermark.
state_dir = "/path/to/state/dir"
# The network chain id for your p2p nodes
chain_id = "chain-id-here"
# The required number of participant share signatures.
# This must match the `--threshold` value specified during key2shares
cosigner_threshold = 2
# IP address and port for receiving communication from other validator instances.
# The validator instances must communicate during the signing process.
cosigner_listen_address = "tcp://0.0.0.0:1234"
# Each validator peer appears in a `cosigner` section.
# This sample file is for validator ID 1, so we configure sections for peers 2 and 3.
[[cosigner]]
# The ID of this peer, these must match the key IDs.
id = 2
# The IP address and port for communication with this peer
remote_address = "tcp://2.2.2.2:1234"
[[cosigner]]
id = 3
remote_address = "tcp://3.3.3.3:1234"
# Configure any number of p2p network nodes.
# We recommend at least 2 nodes per cosigner for redundancy.
[[node]]
address = "tcp://<node-a ip>:1234"
[[node]]
address = "tcp://<node-b ip>:1234"
Configuration for instances 2
and 3
would be similar. The cosigner
sections would contain the respective peers, and the node
sections would contain nodes for the cosigners.
Mpc validators are not directly connected to the p2p network nor do they store chain and application state. They rely on nodes to receive blocks from the p2p network, make signing requests, and relay the signed blocks back to the p2p network.
To make a node available as a relay for an mpc validator, find the priv_validator_laddr
(or equivalent) configuration item in your node's configuration file. Change this value, to accept connections on an IP address and port of your choosing.
# TCP or UNIX socket address for Tendermint to listen on for
# connections from an external PrivValidator process
-priv_validator_laddr = ""
+priv_validator_laddr = "tcp://0.0.0.0:1234"
Full configuration and operation of your tendermint node is outside the scope of this guide. You should consult your network's documentation for node configuration.
We recommend hosting nodes on separate and isolated infrastructure from your validator instances.
Once your validator instance and node is configured, you can launch the signer. When threshold
signers are online, they will start signing block requests from their network nodes.
signer --config /path/to/config.toml
We recommend using systemd or similar service management program as appropriate for your runtime platform.
Security and management of any key material is outside the scope of this service. Always consider your own security and risk profile when dealing with sensitive keys, services, or infrastructure.
As far as the law allows, this software comes as is, without any warranty or condition, and no contributor will be liable to anyone for any damages related to this software or this license, under any kind of legal claim.