Skip to main content

Quick Start

info

If you don't have have access to the docker image or don't have access to the android sdk repository, please contact us at info@silencelaboratories.com.

Here is how you can setup the Mobile SDK and perform MPC operations in less than a minute.

You will create a working MPC two-party setup, where the first party, an Android application interacts with Trio Servers as a second party, and third party.

Prerequisites

info

For quick testing, the demo server is already deployed at trio-server.demo.silencelaboratories.com. We are using this server for the quickstart guide.

The Cloud Verifying Key for the demo server is 019c4c79e942bbc3ff1d6ace7256404d701498056978cc4638c35832acdf821b1e.

The Cloud Node Endpoint for the demo server is https://trio-server.demo.silencelaboratories.com.

Setup the Mobile SDK (Android)

Create a new Android Studio project by following the official guide or use existing one.

Dependency Installation

Step 1: Create access token for the repository
  • Get access to the repository https://github.com/silence-laboratories/silentshard-artifacts from the Silence Laboratories team.
  • Create a personal access token at https://github.com/settings/tokens with the following scopes checked[✓] to access the repository, and it's associated GithubPackages through gradle.
    • Under repo -> [✓] public_repo
    • Under write:packages -> [✓] read:packages
      We can leave write:packages untouched/unchecked as we only need read access
    • It will end up looking like this : Two items checked everything else unchecked. See below. github_pat_checked_scopes
Step 2: Configure settings.gradle.kts
  • Add the silentshard maven repo with the access credentials under the dependencyResolutionManagement -> repositories.
  dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven {
url =
uri("https://maven.pkg.github.com/silence-laboratories/silentshard-artifacts")
credentials {
// In production app we store private credentials outside of the files added to git.
username = "github_username"
password = "token_we_just_created"
}
}
//Other private repos or other resolution configuration. Or maybe another maven repo.
}
}
Step 3: Configure app level build.gradle.kts
  • Add the silentshard dependency in your dependencies block
  dependencies {
implementation("com.silencelaboratories.silentshard:trio-android:1.0.0")
//Your Other dependencies
//..
//..
}
Step 4: Gradle-Sync
  • Sync gradle with project files.

Session Creation

Instantiate TrioSession object, which could be used to perform all of the supported MPC operations such as keygen, sign etc.

MainActivity.kt
import com.silencelaboratories.silentshard.trio.SilentShard
import com.silencelaboratories.silentshard.trio.TrioSession
import com.silencelaboratories.network.websocket.WebsocketConfig

object Constants {
//Replace with your own
const val CLOUD_NODE_URI = "trio-server.demo.silencelaboratories.com"
//Replace with your own
//const val PORT = "8080"
}

//Other party verifying-key/public-key. Replace with your own Verifying Key.
val cloudPublicKey = "019c4c79e942bbc3ff1d6ace7256404d701498056978cc4638c35832acdf821b1e"

//Create websocketConfig to let SilentShard use default WebsocketClient.
val websocketConfig = SilentShard.buildWebsocketConfig {
withBaseUrl(CLOUD_NODE_URI)
//usingPort(PORT)
isSecureProtocol(false)
}

//Create storageClient instance to manage keyshare states
val storageClient = object : StorageClient<ReconcileStoreDao> {
/**
* Representing in-memory database. In real world it should be some SQL based DB or
* secure storage or custom hardware. It's up to the implementation app's use-case.
* */
private val keyshareDaoSet = mutableSetOf<ReconcileStoreDao>()

override suspend fun write(
dao: ReconcileStoreDao,
) {
if (!keyshareDaoSet.add(dao)) {
keyshareDaoSet.remove(dao)
keyshareDaoSet.add(dao)
}
}

override suspend fun read(
key: String,
): ReconcileStoreDao? {
return keyshareDaoSet.find { it.keyId == key }
}
}

//Create trioSession for ECDSA algorithm
val trioSession: TrioSession = SilentShard.ECDSA.createTrioSession(
cloudPublicKey, websocketConfig, storageClient
)
//or for EdDSA algorithm
//val trioSession: TrioSession = SilentShard.EdDSA.createTrioSession(
// cloudPublicKey, websocketConfig, storageClient
//)

Run the MPC operations

After creating the session, you can perform MPC operations.

Key Generation

Generate MPC keyshares and return the client keyshare with keygen method.

// call this from a Dispatcher.IO coroutine
val result = trioSession.keygen()
result.onSuccess { keyshare ->
// Use the generated keyshare : ByteArray
Log.d("MPC", "Keyshare size: ${keyshare.size}")
}.onFailure { error ->
// Handle the error
Log.e("MPC", "Key generation failed: ${error.message}")
}

Signature Generation

Sign a message using the signature method.

val messageHash = "53c48e76b32d4fb862249a81f0fc95da2d3b16bf53771cc03fd512ef5d4e6ed9"
// call this from a Dispatcher.IO coroutine
val result = trioSession.signature(
keyshare = keyshare,
message = messageHash,
derivationPath = "m" // This is the default, use your desired path here. For e.g 'm/1/2'
)
result.onSuccess { signature ->
// Use the generated signature
Log.d("MPC", "Signature: ${signature.toHexString()}")
}.onFailure { error ->
// Handle the error
Log.e("MPC", "Signing failed: ${error.message}")
}

Complete Code Example

MainActivity.kt
package com.silencelaboratories.silentshardtrioquickstart

import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.tooling.preview.Preview
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch
import com.silencelaboratories.silentshard.trio.SilentShard
import com.silencelaboratories.silentshard.trio.TrioSession
import com.silencelaboratories.storage.StorageClient
import com.silencelaboratories.network.websocket.WebsocketConfig
import com.silencelaboratories.storage.silentshard.ReconcileStoreDao

class MainActivity : ComponentActivity() {

object Constants {
//Replace with your own
const val CLOUD_NODE_URI = "trio-server.demo.silencelaboratories.com"
//Replace with your own
//const val PORT = "8080"
}

//Other party verifying-key/public-key. Replace with your own Verifying Key.
val cloudPublicKey = "019c4c79e942bbc3ff1d6ace7256404d701498056978cc4638c35832acdf821b1e"

//Create websocketConfig to let SilentShard use default WebsocketClient.
val websocketConfig = SilentShard.buildWebsocketConfig {
withBaseUrl(CLOUD_NODE_URI)
//usingPort(PORT)
isSecureProtocol(false)
}

//Create storageClient instance to manage keyshare states
val storageClient = object : StorageClient<ReconcileStoreDao> {
/**
* Representing in-memory database. In real world it should be some SQL based DB or
* secure storage or custom hardware. It's up to the implementation app's use-case.
* */
private val keyshareDaoSet = mutableSetOf<ReconcileStoreDao>()

override suspend fun write(
dao: ReconcileStoreDao,
) {
if (!keyshareDaoSet.add(dao)) {
keyshareDaoSet.remove(dao)
keyshareDaoSet.add(dao)
}
}

override suspend fun read(
key: String,
): ReconcileStoreDao? {
return keyshareDaoSet.find { it.keyId == key }
}
}

//Create trioSession for ECDSA algorithm
val trioSession: TrioSession = SilentShard.ECDSA.createTrioSession(
cloudPublicKey, websocketConfig, storageClient
)
//or for EdDSA algorithm
//val trioSession: TrioSession = SilentShard.EdDSA.createTrioSession(
// cloudPublicKey, websocketConfig, storageClient
//)

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {

val messageHash = "53c48e76b32d4fb862249a81f0fc95da2d3b16bf53771cc03fd512ef5d4e6ed9"
// call this from a Dispatcher.IO coroutine

LaunchedEffect(Unit) {
lifecycleScope.launch {
val result = trioSession.keygen()
result.onSuccess { keyshare ->
// Use the generated keyshare; Here using for signing
Log.d("MPC", "Keyshare size: ${keyshare.size}")

// call this from a Dispatcher.IO coroutine
val result = trioSession.signature(
keyshare = keyshare,
message = messageHash,
derivationPath = "m" // This is the default, use your desired path here. For e.g 'm/1/2'
)
result.onSuccess { signature ->
// Use the generated signature
Log.d("MPC", "Signature: ${signature.toHexString()}")
}.onFailure { error ->
// Handle the error
Log.e("MPC", "Signing failed: ${error.message}")
}

}.onFailure { error ->
// Handle the error˛
Log.e("MPC", "Key generation failed: ${error.message}")
}
}
}
}
}
}

Once the app launches, check your logcat logs to see the key generation and signing process updates in real-time.