Quick Start
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
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 leavewrite:packagesuntouched/unchecked as we only need read access - It will end up looking like this : Two items checked everything else unchecked. See below.

- Under
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.
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
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.