# Getting Started

Generate a key and begin signing in under a minute with the Sodot Unity SDK.

## Key Generation

First, we must generate a public key and key shares so that we can later sign messages.
You will need your `API_KEY`.

We show example code for a 2-of-3 threshold signing scenario.
(Note that Sodot MPC SDK allows any t-of-n [threshold signing](/cryptography/signature-scheme#what-is-a-threshold-signature-scheme) setting)

To generate a key we use the objects defined in the SDK:

:::tip[Feature]
BIP-340 (for Bitcoin Taproot), ECDSA and ED25519 are all supported through the Unity SDK.
:::

<Tabs>
  <Tab title="ECDSA">
    ```csharp
    using SodotSDK;
    using SodotSDK.Ecdsa;

    // Your server side creates a room for 3 parties using its API_KEY
    // Creating a room uuid should always happen on the server side using your API_KEY
    // so that the API_KEY is never exposed to the client side
    ushort N = 3;
    ushort T = 2;
    var myApiKey = "MY_API_KEY";
    var hostUrl = "us1.sodot.dev"; // Your Relay URL

    // Create the Ecdsa instance with your relay server hostURL
    var ecdsa = new Ecdsa(hostUrl);

    // Create a room for key generation
    var keygenRoomUuid = await ecdsa.CreateRoom(N, myApiKey);

    // All parties call initKeygen to get initialization data that contains a public key and private key
    var (keygenId, keygenSecret) = ecdsa.InitKeygen();

    // All parties receive the keygenIds from all other parties
    var keygenIds = new KeygenId[] { new KeygenId("keygenId1"), new KeygenId("keygenId3") };

    // All parties join the keygen room
    var (pubkey, secretShare) = await ecdsa.Keygen(keygenRoomUuid, N, T, keygenSecret, keygenIds);

    // Pick the derivation path of the public key you want to sign for
    var derivationPath = new uint[] { 44, 60, 0, 0, 0 };

    // Get the public key for the derivation path
    var derivedPubkey = await ecdsa.DerivePubkey(secretShare, derivationPath);

    // Store secretShare securely for later use in signing
    ```
  </Tab>

  <Tab title="ED25519">
    ```csharp
    using SodotSDK;
    using SodotSDK.Ed25519;

    // Your server side creates a room for 3 parties using its API_KEY
    // Creating a room uuid should always happen on the server side using your API_KEY
    // so that the API_KEY is never exposed to the client side
    ushort N = 3;
    ushort T = 2;
    var myApiKey = "MY_API_KEY";
    var hostUrl = "us1.sodot.dev"; // Your Relay URL

    // Create the Ed25519 instance with your relay server hostURL
    var ed25519 = new Ed25519(hostUrl);

    // Create a room for key generation
    var keygenRoomUuid = await ed25519.CreateRoom(N, myApiKey);

    // All parties call initKeygen to get initialization data that contains a public key and private key
    var (keygenId, keygenSecret) = ed25519.InitKeygen();

    // All parties receive the keygenIds from all other parties
    var keygenIds = new KeygenId[] { new KeygenId("keygenId1"), new KeygenId("keygenId3") };

    // All parties join the keygen room
    var (pubkey, secretShare) = await ed25519.Keygen(keygenRoomUuid, N, T, keygenSecret, keygenIds);

    // Pick the derivation path of the public key you want to sign for
    var derivationPath = new uint[] { 44, 60, 0, 0, 0 };

    // Get the public key for the derivation path
    var derivedPubkey = await ed25519.DerivePubkey(secretShare, derivationPath);

    // Store secretShare securely for later use in signing
    ```
  </Tab>

  <Tab title="BIP340">
    ```csharp
    using SodotSDK;
    using SodotSDK.Bip340;

    // Your server side creates a room for 3 parties using its API_KEY
    // Creating a room uuid should always happen on the server side using your API_KEY
    // so that the API_KEY is never exposed to the client side
    ushort N = 3;
    ushort T = 2;
    var myApiKey = "MY_API_KEY";
    var hostUrl = "us1.sodot.dev"; // Your Relay URL

    // Create the Bip340 instance with your relay server hostURL
    var bip340 = new Bip340(hostUrl);

    // Create a room for key generation
    var keygenRoomUuid = await bip340.CreateRoom(N, myApiKey);

    // All parties call initKeygen to get initialization data that contains a public key and private key
    var (keygenId, keygenSecret) = bip340.InitKeygen();

    // All parties receive the keygenIds from all other parties
    var keygenIds = new KeygenId[] { new KeygenId("keygenId1"), new KeygenId("keygenId3") };

    // All parties join the keygen room
    var (pubkey, secretShare) = await bip340.Keygen(keygenRoomUuid, N, T, keygenSecret, keygenIds);

    // Pick the derivation path of the public key you want to sign for
    var derivationPath = new uint[] { 44, 60, 0, 0, 0 };

    // For BIP340, you can optionally use a tweak
    Bip340Tweak? tweak = null; // `null` for no tweak

    // Get the public key for the derivation path
    var derivedPubkey = await bip340.DeriveTweakPubkey(secretShare, derivationPath, tweak);

    // Store secretShare securely for later use in signing
    ```
  </Tab>
</Tabs>

Behind the scenes this is the rough flow of communication that occurs:

```mermaid
sequenceDiagram
    actor Alice
    actor Bob
    actor Charlie
    participant App as App Server
    rect rgb(200,200,230,.3)
    Note left of Alice: Keygen Setup
    App->>Relay: Create room for 3 participants
    Relay->>App: room_id
    App->>Alice: room_id
    App->>Bob: room_id
    App->>Charlie: room_id
    par Alice handshakes w/ Bob
    Note over Alice,Bob: Propagated externally to the SDK
    Alice-->>Bob: keygen_id
    Bob-->>Alice: keygen_id
    and Alice handshakes w/ Charlie
    Note over Alice,Charlie: Propagated externally to the SDK
    Alice-->>Charlie: keygen_id
    Charlie-->>Alice: keygen_id
    and Bob handshakes w/ Charlie
    Note over Bob,Charlie: Propagated externally to the SDK
    Bob-->>Charlie: keygen_id
    Charlie-->>Bob: keygen_id
    end
    Alice->>Relay: Connect to room_id
    Bob->>Relay: Connect to room_id
    Charlie->>Relay: Connect to room_id
    end
    rect rgb(200,230,200,.3)
    Note left of Alice: Key Generation
    Note over Alice,Charlie: Run Distributed Key Generation
    activate Alice
    activate Bob
    activate Charlie
    Alice->>Relay: Relayed Communication
    Relay->>Alice: ;
    Bob->>Relay: ;
    Relay->>Bob: ;
    Charlie->>Relay: ;
    Relay->>Charlie: ;
    Note over Alice: Alice has a Key Share
    deactivate Alice
    Note over Bob: Bob has a Key Share
    deactivate Bob
    Note over Charlie: Charlie has a Key Share
    deactivate Charlie
    end
```

## Signing

Now that we have key shares on all the devices/servers of the potential signers, we can sign by running:

<Tabs>
  <Tab title="ECDSA">
    ```csharp
    using SodotSDK;
    using static SodotSDK.SodotUtils;
    using SodotSDK.Ecdsa;

    // To sign a message, create a signing room on the server side, using your API_KEY
    ushort T = 2;  // We only need T signers (of our N total parties)
    var myApiKey = "MY_API_KEY";
    var hostUrl = "us1.sodot.dev"; // Your Relay URL

    // Create the Ecdsa instance with your relay server hostURL
    var ecdsa = new Ecdsa(hostUrl);

    // Create a room for signing
    var signingRoomUuid = await ecdsa.CreateRoom(T, myApiKey);

    // Each participating party uses their secret share from key generation
    var (_, secretShare) = await ecdsa.Keygen(/*...*/);

    // The derivation path to use for signing (same as used to generate the pubkey)
    var derivationPath = new uint[] { 44, 60, 0, 0, 0 };

    // Hash the message and convert to MessageHash
    var message = new byte[] { 0xca, 0xfe, 0xca, 0xfe, 0xca, 0xfe, 0xca, 0xfe };
    var msgHash = MessageHash.FromKeccak256(message);

    // T parties join the signing room and perform the signing
    var signature = await ecdsa.Sign(signingRoomUuid, secretShare, msgHash, derivationPath);

    // The signature can be verified against the derived public key
    ```
  </Tab>

  <Tab title="ED25519">
    ```csharp
    using SodotSDK;
    using SodotSDK.Ed25519;

    // To sign a message, create a signing room on the server side, using your API_KEY
    ushort T = 2;  // We only need T signers (of our N total parties)
    var myApiKey = "MY_API_KEY";
    var hostUrl = "us1.sodot.dev"; // Your Relay URL

    // Create the Ed25519 instance with your relay server hostURL
    var ed25519 = new Ed25519(hostUrl);

    // Create a room for signing
    var signingRoomUuid = await ed25519.CreateRoom(T, myApiKey);

    // Each participating party uses their secret share from key generation
    var (_, secretShare) = await ed25519.Keygen(/*...*/);

    // The derivation path to use for signing (same as used to generate the pubkey)
    var derivationPath = new uint[] { 44, 60, 0, 0, 0 };

    // The message to sign
    var message = new byte[] { 0xca, 0xfe, 0xca, 0xfe, 0xca, 0xfe, 0xca, 0xfe };

    // T parties join the signing room and perform the signing
    var signature = await ed25519.Sign(signingRoomUuid, secretShare, message, derivationPath);

    // The signature can be verified against the derived public key
    ```
  </Tab>

  <Tab title="BIP340">
    ```csharp
    using SodotSDK;
    using SodotSDK.Bip340;

    // To sign a message, create a signing room on the server side, using your API_KEY
    ushort T = 2;  // We only need T signers (of our N total parties)
    var myApiKey = "MY_API_KEY";
    var hostUrl = "us1.sodot.dev"; // Your Relay URL

    // Create the Bip340 instance with your relay server hostURL
    var bip340 = new Bip340(hostUrl);

    // Create a room for signing
    var signingRoomUuid = await bip340.CreateRoom(T, myApiKey);

    // Each participating party uses their secret share from key generation
    var (_, secretShare) = await bip340.Keygen(/*...*/);

    // The derivation path to use for signing (same as used to generate the pubkey)
    var derivationPath = new uint[] { 44, 60, 0, 0, 0 };

    // The message to sign
    var message = new byte[] { 0xca, 0xfe, 0xca, 0xfe, 0xca, 0xfe, 0xca, 0xfe };

    // For BIP340, you can optionally use a tweak
    Bip340Tweak? tweak = null; // `null` for no tweak

    // T parties join the signing room and perform the signing
    var signature = await bip340.Sign(signingRoomUuid, secretShare, message, derivationPath, tweak);

    // The signature can be verified against the derived public key
    ```
  </Tab>
</Tabs>

Behind the scenes this is the rough flow of communication that occurs. Note that since only 2 signers are needed, Alice (chosen as a non-signer in this example) doesn't participate at all in the protocol:

```mermaid
sequenceDiagram
    actor Alice
    actor Bob
    actor Charlie
    participant App as App Server
    rect rgb(200,200,230,.3)
    Note left of Alice: Room Setup
    App->>Relay: Create room for 2 participants
    Relay->>App: room_id
    App->>Bob: room_id
    App->>Charlie: room_id
    par Bob invites Charlie
    Note over Bob,Charlie: Propagated externally to the SDK
    Bob-->>Charlie: msg
    Note over Charlie: Charlie decides whether they wish to sign msg
    end
    Bob->>Relay: Connect to room_id
    Charlie->>Relay: Connect to room_id
    end
    rect rgb(230,200,200,.3)
    Note left of Alice: Signing
    Note over Bob,Charlie: Run Signing
    activate Bob
    activate Charlie
    Bob->>Relay: Relayed Communication
    Relay->>Bob: 
    Charlie->>Relay: 
    Relay->>Charlie: 
    Note over Bob: Bob has a signature on msg
    deactivate Bob
    Note over Charlie: Charlie has a signature on msg
    deactivate Charlie
    end
```

## Additional Features

The Sodot Unity SDK provides additional advanced features, such as key refresh, key reshare, key import and export, etc.
For more information on those features, please visit the [Key Lifecycle](/unity/key_lifecycle) page.

:::tip[API Reference]
For full details on all available methods, refer to the SDK [API Reference](https://docs.sodot.dev/mpc-sdk-unity/), also linked in the sidebar.
:::
