# Getting Started

In this guide, we will walk you through the process of generating a new distributed key and signing a payload with it using the **Sodot Rust SDK**.

## Distributed Key Generation

First, You will generate a sharded key-pair that can be used for threshold signing. You will need your Relay `API_KEY`.

In this example, we will use a 2-of-3 threshold signing scenario. (Sodot MPC SDK allows any t-of-n threshold setting.)

:::note
This example code uses tokio as the async runtime, but you can use any other async runtime by adapting the code accordingly.
:::

<Tabs>
  <Tab title="ECDSA">
    ```rust
    use sodot_mpc::{Ecdsa, KeygenId, SecretShare};
    use std::num::NonZeroU16;

    const N: u16 = 3;
    const T: u16 = 2;
    const HOST_URL: &str = "us1.sodot.dev";
    const API_KEY: &str = "<Your Relay API Key>";

    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let ecdsa = Ecdsa::new(HOST_URL.to_string());

        // 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
        let keygen_room_uuid = ecdsa
            .create_room(NonZeroU16::new(N).unwrap(), API_KEY)
            .await?;

        // All parties call init_keygen to get (KeygenId, KeygenPrivateKey) as result
        // The KeygenId is the public part that you should pass to all other parties, the KeygenPrivateKey is the private state you should keep until the actual keygen completes.
        let (keygen_id, keygen_private_key) = ecdsa.init_keygen()?;

        // All parties receive the keygenIds from all other parties
        let keygen_ids = [
            KeygenId::new("KeygenIdParty1".into()),
            KeygenId::new("KeygenIdParty2".into()),
        ];

        // All parties join the keygen room
        let (public_key, secret_share) = ecdsa
            .keygen(
                &keygen_room_uuid,
                N.try_into().expect("N is a valid NonZeroU16"),
                T.try_into().expect("T is a valid NonZeroU16"),
                &keygen_private_key,
                &keygen_ids,
            )
            .await?;

        // Save the secret share in your secure storage. it will allow you to participate in signing using it later on.
        let serialized_secret_share = secret_share.as_str();
        // Restore the secret share from the serialized string
        let restored_share = SecretShare::<Ecdsa>::from(serialized_secret_share.to_string());

        // Pick the derivation path of the public key you want to sign for
        let derivation_path = [44, 60, 0, 0, 0];
        // Get the public key for the derivation path
        let derived_pubkey = ecdsa.derive_pubkey(&restored_share, &derivation_path)?;

        println!(
            "Compressed Derived Public Key: {:?}",
            derived_pubkey.compressed()
        );

        Ok(())
    }
    ```
  </Tab>

  <Tab title="Ed25519">
    ```rust
    use sodot_mpc::{Ed25519, KeygenId, SecretShare};
    use std::num::NonZeroU16;

    const N: u16 = 3;
    const T: u16 = 2;
    const HOST_URL: &str = "us1.sodot.dev";
    const API_KEY: &str = "<Your Relay API Key>";

    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let ed25519 = Ed25519::new(HOST_URL.to_string());

        // 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
        let keygen_room_uuid = ed25519
            .create_room(NonZeroU16::new(N).unwrap(), API_KEY)
            .await?;

        // All parties call init_keygen to get (KeygenId, KeygenPrivateKey) as result
        // The KeygenId is the public part that you should pass to all other parties, the KeygenPrivateKey is the private state you should keep until the actual keygen completes.
        let (keygen_id, keygen_private_key) = ed25519.init_keygen()?;

        // All parties receive the keygenIds from all other parties
        let keygen_ids = [
            KeygenId::new("KeygenIdParty1".into()),
            KeygenId::new("KeygenIdParty2".into()),
        ];

        // All parties join the keygen room
        let (public_key, secret_share) = ed25519
            .keygen(
                &keygen_room_uuid,
                N.try_into().expect("N is a valid NonZeroU16"),
                T.try_into().expect("T is a valid NonZeroU16"),
                &keygen_private_key,
                &keygen_ids,
            )
            .await?;

        // Save the secret share in your secure storage. it will allow you to participate in signing using it later on.
        let serialized_secret_share = secret_share.as_str();
        // Restore the secret share from the serialized string
        let restored_share = SecretShare::<Ed25519>::from(serialized_secret_share.to_string());

        // Pick the derivation path of the public key you want to sign for
        let derivation_path = [44, 60, 0, 0, 0];
        // Get the public key for the derivation path
        let derived_pubkey = ed25519.derive_pubkey(&restored_share, &derivation_path)?;

        println!(
            "Derived Public Key: {:?}",
            derived_pubkey.into_bytes()
        );

        Ok(())
    }
    ```
  </Tab>

  <Tab title="BIP340">
    ```rust
    use sodot_mpc::{Bip340, KeygenId, SecretShare, bip340::Bip340Tweak};
    use std::num::NonZeroU16;

    const N: u16 = 3;
    const T: u16 = 2;
    const HOST_URL: &str = "us1.sodot.dev";
    const API_KEY: &str = "<Your Relay API Key>";

    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let bip340 = Bip340::new(HOST_URL.to_string());

        // 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
        let keygen_room_uuid = bip340
            .create_room(NonZeroU16::new(N).unwrap(), API_KEY)
            .await?;

        // All parties call init_keygen to get (KeygenId, KeygenPrivateKey) as result
        // The KeygenId is the public part that you should pass to all other parties, the KeygenPrivateKey is the private state you should keep until the actual keygen completes.
        let (keygen_id, keygen_private_key) = bip340.init_keygen()?;

        // All parties receive the keygenIds from all other parties
        let keygen_ids = [
            KeygenId::new("KeygenIdParty1".into()),
            KeygenId::new("KeygenIdParty2".into()),
        ];

        // All parties join the keygen room
        let (public_key, secret_share) = bip340
            .keygen(
                &keygen_room_uuid,
                N.try_into().expect("N is a valid NonZeroU16"),
                T.try_into().expect("T is a valid NonZeroU16"),
                &keygen_private_key,
                &keygen_ids,
            )
            .await?;

        // Save the secret share in your secure storage. it will allow you to participate in signing using it later on.
        let serialized_secret_share = secret_share.as_str();
        // Restore the secret share from the serialized string
        let restored_share = SecretShare::<Bip340>::from(serialized_secret_share.to_string());

        // Pick the derivation path and BIP-340 tweak of the public key you want to sign for
        let derivation_path = [44, 60, 0, 0, 0];
        let tweak = Bip340Tweak::from([0; 32]);
        // Get the public key for the derivation path
        let derived_pubkey =
            bip340.derive_tweak_pubkey(&restored_share, &derivation_path, Some(&tweak))?;

        println!(
            "Derived Public Key: {:?}",
            derived_pubkey.as_bytes()
        );

        Ok(())
    }
    ```
  </Tab>
</Tabs>

:::note
Version 1.7.0 of the SDK also ships an [ExportableEd25519](/rust/exportable_ed25519) scheme, an Ed25519 variant whose raw 32-byte private key can be reconstructed from a threshold of shares.
:::

:::tip[API reference]
Full details can be found in the [API Reference](https://docs.sodot.dev/rust-api/v1.6/sodot_mpc/index.html), also linked in the sidebar.
:::

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">
    ```rust
    use sodot_mpc::{Ecdsa, SecretShare, ecdsa::MessageHash};
    use std::num::NonZeroU16;

    const T: u16 = 2;
    const HOST_URL: &str = "us1.sodot.dev";
    const API_KEY: &str = "<Your Relay API Key>";

    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let ecdsa = Ecdsa::new(HOST_URL.to_string());
        let secret_share = SecretShare::<Ecdsa>::from("serialized_share_from_keygen".to_string());

        // To sign a message, create a signing room for T parties on the server side, using your API_KEY
        let signing_room_uuid = ecdsa
            .create_room(NonZeroU16::new(T).unwrap(), API_KEY)
            .await?;

        // Pick the derivation path of the public key you want to sign for
        let derivation_path = [44, 60, 0, 0, 0];

        // Get the public key for the derivation path
        let derived_pubkey = ecdsa.derive_pubkey(&secret_share, &derivation_path)?;

        // Choose a message to sign
        let msg = b"Hello, world!";
        // Hash the message
        let message_hash = MessageHash::sha256(msg);

        // 2 parties join the signing room
        let signature = ecdsa
            .sign(
                &signing_room_uuid,
                &secret_share,
                &message_hash,
                &derivation_path,
            )
            .await?;

        // signature can be verified against the derived pubkey
        println!("Signature: {:?}", signature);
        Ok(())
    }
    ```
  </Tab>

  <Tab title="Ed25519">
    ```rust
    use sodot_mpc::{Ed25519, SecretShare};
    use std::num::NonZeroU16;

    const T: u16 = 2;
    const HOST_URL: &str = "us1.sodot.dev";
    const API_KEY: &str = "<Your Relay API Key>";

    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let ed25519 = Ed25519::new(HOST_URL.to_string());
        let secret_share = SecretShare::<Ed25519>::from("serialized_share_from_keygen".to_string());

        // To sign a message, create a signing room for T parties on the server side, using your API_KEY
        let signing_room_uuid = ed25519
            .create_room(NonZeroU16::new(T).unwrap(), API_KEY)
            .await?;

        // Pick the derivation path of the public key you want to sign for
        let derivation_path = [44, 60, 0, 0, 0];

        // Get the public key for the derivation path
        let derived_pubkey = ed25519.derive_pubkey(&secret_share, &derivation_path)?;

        // Choose a message to sign
        let message = b"Hello, world!";

        // 2 parties join the signing room
        let signature = ed25519
            .sign(&signing_room_uuid, &secret_share, message, &derivation_path)
            .await?;

        // signature can be verified against the derived pubkey
        println!("Signature: {:?}", signature);
        Ok(())
    }
    ```
  </Tab>

  <Tab title="BIP340">
    ```rust
    use sodot_mpc::{Bip340, SecretShare, bip340::Bip340Tweak};
    use std::num::NonZeroU16;

    const T: u16 = 2;
    const HOST_URL: &str = "us1.sodot.dev";
    const API_KEY: &str = "<Your Relay API Key>";

    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let bip340 = Bip340::new(HOST_URL.to_string());
        let secret_share = SecretShare::<Bip340>::from("serialized_share_from_keygen".to_string());

        // To sign a message, create a signing room for T parties on the server side, using your API_KEY
        let signing_room_uuid = bip340
            .create_room(NonZeroU16::new(T).unwrap(), API_KEY)
            .await?;

        // Pick the derivation path of the public key you want to sign for
        let derivation_path = [44, 60, 0, 0, 0];
        let tweak = Bip340Tweak::from([1; 32]);

        // Get the public key for the derivation path
        let derived_pubkey =
            bip340.derive_tweak_pubkey(&secret_share, &derivation_path, Some(&tweak))?;

        // Choose a message to sign
        let message = b"Hello, world!";

        // 2 parties join the signing room
        let signature = bip340
            .sign(
                &signing_room_uuid,
                &secret_share,
                message,
                &derivation_path,
                Some(&tweak),
            )
            .await?;

        // signature can be verified against the derived pubkey
        println!("Signature: {:?}", signature);
        Ok(())
    }

    ```
  </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
```
