This page describes how to set up a minimal (3, 1) TSM using docker-compose, which can compute ECDSA signatures and is suitable for local development.
This article describes how to deploy the TSM itself. If you already have a TSM and want to connect to it using a SDK, you can get more information here.
Start by login into Blockdaemon's private docker registry using the credentials you were provided:
docker login nexus.sepior.net:19001
The three TSM nodes will communicate internally on port 9000 using docker-composes built-in DNS server. They will also expose one SDK port per TSM, these will be mapped to 8000, 8001 and 8002 on localhost for testing and development.
Each of the three TSM nodes needs a private/public keypair. To generate this run:
$ openssl ecparam -name P-256 -genkey -param_enc named_curve -outform DER -out private0.key $ openssl ec -inform DER -in private0.key -pubout -outform DER -out public0.key $ openssl ecparam -name P-256 -genkey -param_enc named_curve -outform DER -out private1.key $ openssl ec -inform DER -in private1.key -pubout -outform DER -out public1.key $ openssl ecparam -name P-256 -genkey -param_enc named_curve -outform DER -out private2.key $ openssl ec -inform DER -in private2.key -pubout -outform DER -out public2.key
The above requires a fairly new version of OpenSSL, so if you encounter any issues running the commands, please try and update your OpenSSL and try again.
Next we need to create a configuration file for each of the three TSMs, let's start with
Get node 0's private key in base64:
$ openssl base64 -A -in private0.key; echo
Then get the all the nodes' base64 encoded public keys:
openssl base64 -A -in public0.key; echo openssl base64 -A -in public1.key; echo openssl base64 -A -in public2.key; echo
We are now ready to create
config0.toml by putting in the generated values in the following template. Under
<node ID> in
Index with 0. Also replace
<private key> in
PrivateKey with the output from above. Under
<nodeN public key> in
PublicKey with the output from above. Replace
<SDK port> in
<MPC port> under
# General configuration for MPC operations. [MPC] # This is the security threshold for the TSM. It means that the TSM is secure as long as at most threshold number of # players are corrupt. Must be greater than 0 and less than the total number of players. Some MPC protocols have # restrictions on what the threshold can be. Threshold = 1 # Configuration for the local player [Player] # All players in a TSM are identified by a player index. This is the index of the player running this TSM node. # We refer to this player as the local player. Other players are called remote players. Index = <node ID> # This is a base64 encoding of the private key used to authenticate the local player towards the remote players. This # must correspond to the public keys configured on the remote players for this player index. A private key can be # generated using the following OpenSSL commands: PrivateKey = "<private key>" # The following is a list of remote players in the TSM. # # The logic is that lower numbered players open connections to higher numbered players, so URLs are not needed for players # with a lower number than the local player. [Players.0] # The protocol and address of player with index 0. Supported protocols are tcp, ws and wss. If no protocol is # specified then tcp is assumed. Address = "tcp://node0:9000" # This is a base64 encoding of the players public key. PublicKey = "<node0 public key>" [Players.1] Address = "tcp://node1:9001" PublicKey = "<node1 public key>" [Players.2] Address = "tcp://node2:9002" PublicKey = "<node2 public key>" # Database connection configuration. [Database] # The driver used for the database. The following database drivers are supported: sqlite3, mysql and postgres. DriverName = "sqlite3" DataSourceName = "/tmp/tsmdb" # This specifies a master encryption key used to protect database records. Note that this key is not directly # used to encrypt data. Use any long random string here and make sure to keep a backup of it somewhere safe. EncryptorMasterPassword = "ENCRYPTION_KEY" # MPC server accepting multiplexed TCP connections from other players. # At least one MPC server must be specified if the player index is greater than 0. [MPCTCPServer] # Port number that this server listens on. Port = <MPC port> # Server accepting connections from the SDK. This must be specified unless the TSM node is running as a local node. [SDKServer] # Port number that this server listens on. Port = <SDK port> # Configures system logging for the TSM node. #[Logging] # Log level. If not specified it default to "info". #Level = "" # Computes ECDSA signatures. This protocol requires n >= 2t+1. Cannot be enabled together with DKLS18 or DKLS19. [SEPH18S]
The above should be repeated for
config2.toml using the appropriate values. Do not forget to use the correct SDK ports and MPC ports for each.
Note that in production SDK port need to be different, this is done here because we need all of them bound to localhost.
EncryptorMasterPassword should be different per node in a production deployment.
To start the TSM with
docker-compose create a file
docker-compose.yml with the following contents:
version: "3.8" services: node0: image: nexus.sepior.net:19001/tsm-node:latest ports: - "8000:8000" networks: - tsm environment: - CONFIG_FILE=/config/config0.toml volumes: - ./config0.toml:/config/config0.toml node1: image: nexus.sepior.net:19001/tsm-node:latest ports: - "8001:8001" networks: - tsm environment: - CONFIG_FILE=/config/config1.toml volumes: - ./config1.toml:/config/config1.toml node2: image: nexus.sepior.net:19001/tsm-node:latest ports: - "8002:8002" networks: - tsm environment: - CONFIG_FILE=/config/config2.toml volumes: - ./config2.toml:/config/config2.toml networks: tsm:
docker-compose up from the same directory where you save
docker-compose.yml. A TSM should now be reachable for the SDK on ports 8000, 8001 and 8002 on localhost.
See Example TSM configuration file for further configuration hints.
Updated about 1 month ago