# MPC Sessions

To generate a key in the TSM, the MPC nodes must be instructed to perform an MPC session. During the MPC session, the MPC nodes will interact with each other, often in several rounds, according to a specific MPC protocol.

To start an MPC session, all MPC nodes that participate in the session must agree on:

- A unique MPC session ID
- The subset of MPC nodes that should participate in the MPC session

It is up to you to generate the session ID and choose the particular subset of MPC nodes for the MPC session, and you must make sure that this information is available to the SDK of each of the MPC nodes that should participate in the session.

The session ID must be a unique string that fits in the header of an HTTP request. You can use a helper method in the SDK to generate a session ID:

```go
sessionID := tsm.GenerateSessionID()
```

Each MPC node in the TSM is identified by a unique integer (often numbered 0, 1, 2, 3, and so forth). So if your MPC nodes are numbered 0, 1, 2, 3, then you may, for example, choose the subset (1, 2, 3) for the particular MPC session.

```go
players := []int{1,2,3}
```

The next step is to request the MPC session on each of the SDKs of the MPC nodes that participate in the MPC session. This is done by first creating a `SessionConfig` object containing the session ID and the player subset. Then, you call a specific method on the SDK, providing the session configuration as an input parameter.

# Key Generation

In our case, we will use the session configuration to run an MPC session that generates a new ECDSA key over the _secp256k1_ curve. This is done by calling the `GenerateKey()` method on the SDK, with the session configuration.

In the call to `GenerateKey()` an additional parameter threshold must also be provided. This is the _security threshold_ for the key to be generated. The MPC session will generate the key as a secret sharing among the MPC nodes in the TSM, and a security threshold of _t_ means that a secret sharing will be generated that keeps the key secret even if an attacker manages to steal up to _t_ of the key shares.

To summarize, the MPC key generation session between MPC Node 1, 2, and 3 is started by invoking this on the SDKs controlling the three MPC nodes:

```go
threshold := 1  // The security threshold we want for this key
context := context.Background()
sessionConfig := tsm.NewSessionConfig(sessionID, players, nil)
curveName := "secp256k1"
keyID, err := client.ECDSA().GenerateKey(context, sessionConfig, threshold, curveName, "")
```

When `GenerateKey()` is called on the SDK, it forwards the key generation request to its MPC node. Importantly, the actual MPC session only starts when all the MPC nodes in the MPC session have received a key generation request from their respective SDKs. When an MPC node receives a request for an MPC session, it sends a message to the other MPC nodes in the session, and it only proceeds with the MPC session when it has received a message from all other MPC nodes in the session.

As a consequence, if only some of the MPC nodes in the session request the MPC session via their SDK, the MPC nodes will wait and time out after a while, returning an error message to the SDK. The default timeout is 10 seconds, which can be configured in the MPC node configuration files.

As a part of the MPC session, the MPC nodes will check that they agree on the `threshold` and the `curveName`. So, in addition to agreeing on the session ID and the player subset, the SDK operators must also make sure they use the same values for these parameters before calling the SDK.

If the MPC session is successful, the key will be generated as a secret shared among the MPC nodes, and each SDK will receive the new key's key ID.

# Obtaining the Public Key

After key generation, the public key can be obtained like this:

```go
publicKey, err = client.ECDSA().PublicKey(ctx, keyID, nil)
```

The public key is returned in a JSON format:

```json
{
    "scheme": "...",
    "curve": "...",
    "point": "..."
}
```

where `scheme` is either `ECDSA` or the name of one of the Schnorr schemes. The `curve` is the name of the elliptic curve, but can be empty if it is uniquely defined by the scheme. Finally, `point` is a compressed or uncompressed point representing the public key. You can convert the returned JSON public key to a SubjectPublicKeyInfo structure (see RFC 5280, Section 4.1) as follows:

```undefined
pkixPublicKey, err := tsmutils.ConvertJSONPublicKeyToPKIXPublicKey(publicKey)
```

This only works for ECDSA, Ed25519 and Ed448 keys.

# Signing

Once a key has been generated, each SDK now holds a key ID, and it is ready to sign messages using the key.

Like key generation, signatures are generated by running an MPC session. Once again, you must generate a session ID and choose a subset of MPC nodes. The nodes should be chosen among the nodes that participated in the key generation. You should also pick the message hash to be signed, for example:

```go
sessionID := tsm.GenerateSessionID()
players := []int{1,2}
message := []byte("This message could be a transaction to be signed")
msgHash := sha256.Sum256(message)
```

You must now propagate this information to each of the SDK operators, in this example, the operators of the SDK for Node 1 and Node 2. They must each request the MPC session on their respective SDK using the key ID obtained from the key generation.

```go
context := context.Background()
sessionConfig := tsm.NewSessionConfig(sessionID, players, nil)
curveName := "secp256k1"
partialSignResult, err := client.ECDSA().Sign(context, sessionConfig, keyID, nil, msgHash[:])
```

If the signature generation MPC session is successful, each SDK obtains a partial signature. Your application must collect the partial signatures, and once collected, they can be combined into the final signature:

```go
signature, err := tsm.ECDSAFinalizeSignature(msgHash[:], partialSignatures)
```
