GO SDK

This article will guide you through connecting the TSM Node SDK V2 with our Docker Demo in just four straightforward steps. Additionally, we'll walk you through performing a pre-signatures run using SDK V2. Before proceeding with these steps, please ensure that you have completed the prerequisites outlined below:
Prerequisites
- Make sure that you are using either Linux or Mac OS to install SDK
- Install GO
- Install the Docker Desktop Application
- Install Make
- Install openSSL
- Contact our support team to get:
- Credentials for accessing https://gitlab.com/sepior and https://nexus.sepior.net.
- Zip file for a Docker demo project.
1. Fetch the TSM SDK
To initialize and install it on your local machine, follow the steps below:
- Create a new folder for your project.
- Open a terminal in your local machine.
- Set the
GOPRIVATE
environment variable to thegitlab.com/sepior
in a Unix-like shell by using the command below:
export GOPRIVATE=gitlab.com/sepior
- Add a configuration entry for authenticating with
gitlab.com/sepior
by using the command below:
echo "machine gitlab.com login <yourUsername> password <yourPassword>" >> $HOME/.netrc
Note:
Replace the username and password in the provided configuration with the credentials supplied by our support team.
- Initialize a Go module on your newly installed SDK project, by using the code below:
go mod init example.com
Note:
You can replace 'example.com' with the desired module path for your project.
- Fetch the TSM Node SDK V2 by using the following code:
go get gitlab.com/sepior/[email protected]
Note:
For the full list of our SDK version, please see here.
2. Generate API Keys
Generate an API key for each of the MPC nodes as follows:
echo -n "Node0LoginPassword" | openssl dgst -sha256 -binary | openssl base64
echo -n "Node1LoginPassword" | openssl dgst -sha256 -binary | openssl base64
echo -n "Node2LoginPassword" | openssl dgst -sha256 -binary | openssl base64
This produces three API keys:
jbs3wZ2DAL44CQ9f4LvmEza/rS4k0xeCxB7tUXuiL5Y=
QcV6NRHhpM7UaFaU3K9T34ud50/8zCvUvQkUR6oKHAg=
88IU8yrT6+EGVD6vMoSAlHq2mjfMBd8IoNSWkh61pn4=
Note:
- The command above needs OpenSSL installed and produces a base64 encoding. You can also create an API Key using Go code.
- Make sure to choose other passwords in production.
- When crafting a password, be sure to generate one with strong entropy, incorporating a variety of characters such as letters (both uppercase and lowercase), numbers, and more.
3. Run a TSM using Docker
To run the demo TSM via Docker, follow the steps below:
- Unzip the docker setup zip file (demo-tsm.zip) that you got from our support team.
- Open the folder in your terminal.
- Insert the API keys you have generated in the MPC node config files. For example, in the config file config1.toml for MPC node 1, you insert this:
[[Authentication.APIKeys]]
APIKey = "QcV6NRHhpM7UaFaU3K9T34ud50/8zCvUvQkUR6oKHAg="
ApplicationID = "demoapp"
Note:
Users have the flexibility to generate additional API keys, and if these keys are linked to the same ApplicationID, they will share access to the same set of keys within the TSM.
- Login to Docker by using the code below:
docker login -u <yourUsername> -p <yourPassword> nexus.sepior.net:19001
Note:
Replace the username and password in the provided configuration with the credentials supplied by our support team.
- Run the TSM locally by using the code below:
make setup
- The TSM runs locally with three MPC Nodes that have been configured before. The MPC nodes can be reached from the host machine using the following addresses:
- TSM Node 1: http://localhost:8500/ping
- TSM Node 2: http://localhost:8501/ping
- TSM Node 3: http://localhost:8502/ping
- You have the flexibility to modify the Docker setup configuration file to suit your requirements. Feel free to make any desired edits. For a complete list of available configurations, please see here.
- Additionally, you have the option to employ the following command while executing your demo TSM:
docker compose up # Start the TSM
docker compose stop # Stop the TSM (without whipping the databases)
docker compose down # Stop the TSM and wipe databases
docker compose logs # Show TSM logs
4. Use the TSM to Generate Keys and Signatures
Run the TSM Nodes with a separate SDK for each MPC node. This ensures that crucial tasks require everyone, or most designated operators, to give the green light. This adds an extra layer of security and control. It's like a group decision, making sure that important actions meet certain criteria, like transaction amounts before they're allowed to proceed. Follow the steps below to initiate TSM in partial mode:
- Create a new go file on your SDK folder, then use the code provided below:
package main
import (
"context"
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
"gitlab.com/sepior/go-tsm-sdkv2/tsm"
"gitlab.com/sepior/go-tsm-sdkv2/ec"
"golang.org/x/sync/errgroup"
"log"
)
func main() {
// Create client for two of the MPC nodes
configs := []tsm.Configuration{
tsm.Configuration{URL: "http://localhost:8500"}.WithAPIKeyAuthentication("Node0LoginPassword"),
tsm.Configuration{URL: "http://localhost:8501"}.WithAPIKeyAuthentication("Node1LoginPassword"),
}
clients := make([]*tsm.Client, len(configs))
for i, config := range configs {
var err error
clients[i], err = tsm.NewClient(&config)
if err != nil {
log.Fatal(err)
}
}
threshold := 1
// Generate ECDSA key
sessionConfig := tsm.NewStaticSessionConfig(tsm.GenerateSessionID(), len(clients))
keyIDs := make([]string, len(clients))
var eg errgroup.Group
for i, client := range clients {
client, i := client, i
eg.Go(func() error {
var err error
keyIDs[i], err = client.ECDSA().GenerateKey(context.TODO(), sessionConfig, threshold, ec.Secp256k1.Name(), "")
return err
})
}
if err := eg.Wait(); err != nil {
log.Fatal(err)
}
// Validate keyIDs
for i := 1; i < len(keyIDs); i++ {
if keyIDs[0] != keyIDs[i] {
log.Fatal(errors.New("key IDs do not match"))
}
}
keyID := keyIDs[0]
fmt.Printf("Generated key: ID=%s\n", keyID)
// Generate ten presignatures on each of the players, using one of the presignatures
sessionConfig = tsm.NewStaticSessionConfig(tsm.GenerateSessionID(), len(clients))
presignatureIDs := make([]tsm.StringArray, len(clients))
for i, client := range clients {
i, client := i, client
eg.Go(func() error {
var err error
presignatureIDs[i], err = client.ECDSA().GeneratePresignatures(context.TODO(), sessionConfig, keyID, 10)
if err != nil {
return err
}
return nil
})
}
err := eg.Wait()
if err != nil {
log.Fatal(err)
}
// Validate presignature IDs
for i := 1; i < len(presignatureIDs); i++ {
if presignatureIDs[0].Size() != presignatureIDs[i].Size() {
log.Fatalf("size mismatch between index 0 (%d) and %d (%d)", presignatureIDs[0].Size(), i, presignatureIDs[i].Size())
}
for j := 0; j < presignatureIDs[i].Size(); j++ {
if presignatureIDs[0].Get(j) != presignatureIDs[i].Get(j) {
log.Fatalf("values mismatch between index 0,%d (%s) and %d,%d (%s)", j, presignatureIDs[0].Get(j), i, j, presignatureIDs[i].Get(j))
}
}
}
// We can now sign with the created key
message := []byte(`Hello World`)
msgHash := sha256.Sum256(message)
partialSignatures := tsm.BytesArray{}
sessionConfig = tsm.NewStaticSessionConfig(tsm.GenerateSessionID(), len(clients))
for _, client := range clients {
client := client
if partialSignResult, err := client.ECDSA().SignWithPresignature(context.TODO(), keyID, presignatureIDs[0].Get(0), nil, msgHash[:]); err != nil {
log.Fatal(err)
} else {
partialSignatures.Add(partialSignResult.PartialSignature)
}
}
signature, err := tsm.ECDSAFinalizeSignature(msgHash[:], partialSignatures)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Signature: %s\n", hex.EncodeToString(signature.ASN1()))
}
- Update the URLs in the example, so they point to the MPC nodes. If you have followed the tutorial until now and run your TSM locally using Docker, then the URLs are already ok. If you used other login passwords when you generated the API keys above, you should use these in the example above.
- The code will autonomously establish connections with the two MPC nodes, generate a key in the TSM, and sign a message using the key. This returns partial signatures from each node. The example code finally combines the partial signatures into the final signature. The code example produces the following output:
Generated key: ID=8HJU2YXxruIJZpqbv2ITPwhVSEB4
Signature: 3045022100d829dda874d2415408c90d27ac503f20f93fab8843cabb24e16cfb335224d71902207ee02ab1d5307dbcaf1c80c9d88568d7bce9602ed917982c084490db3ea655e2
Updated 13 days ago