Key Refresh
Rotate both keyshares without changing the wallet address. After a refresh, the previous shares no longer match the new ones, so they are invalidated and can no longer be used for signing.
Please refer to the Session creation section to learn how to create a new session.
Using the session object and an existing keyshare, refresh it to generate a new keyshare.
Full example:
- ECDSA
- EdDSA
import { type EcdsaSession } from '@silencelaboratories/silent-shard-sdk/ecdsa';
export const refresh = async (session: EcdsaSession) => {
// Creating a new keyshare for demo purpose. In real application, you can use an existing keyshare.
const keyshare = await session.keygen();
console.log('Keyshare: ', keyshare.keyIdHex);
const refreshedKeyshare = await session.refresh(keyshare);
console.log('Refreshed keyshare: ', refreshedKeyshare.keyIdHex);
};
import { type EddsaSession } from '@silencelaboratories/silent-shard-sdk/eddsa';
export const refresh = async (session: EddsaSession) => {
// Creating a new keyshare for demo purpose. In real application, you can use an existing keyshare.
const keyshare = await session.keygen();
console.log('Keyshare: ', keyshare.keyIdHex);
const refreshedKeyshare = await session.refresh(keyshare);
console.log('Refreshed keyshare: ', refreshedKeyshare.keyIdHex);
};
- When
session.refresh(keyshare)is called, the app and the server exchange messages to "refresh" the MPC wallet. Refer to Key Refresh for more details. - This process enhances the long-term security of the MPC wallet by proactively updating the client's and server's secret shares.
- The wallet's public address or key remains unchanged during this process.
- The
refreshedKeyshareobject is of type Keyshare and represents the client's new share of the MPC wallet.
Please refer to the Session creation section to learn how to create a new session.
Full example:
- ECDSA
- EdDSA
- Taproot
import 'package:silent_shard_sdk/silent_shard_sdk.dart' as sdk;
Future<void> refresh(sdk.EcdsaSession session) async {
// Creating a new keyshare for demo purpose. In real application, you can use an existing keyshare.
final sdk.DklsKeyshare keyshare = await session.keygen();
print('Keyshare created, public key: ${keyshare.publicKeyHex}');
final sdk.DklsKeyshare refreshedKeyshare =
await session.refresh(keyId: keyshare.keyId);
print('Refreshed keyshare, public key: ${refreshedKeyshare.publicKeyHex}');
}
import 'package:silent_shard_sdk/silent_shard_sdk.dart' as sdk;
Future<void> refresh(sdk.EddsaSession session) async {
// Creating a new keyshare for demo purpose. In real application, you can use an existing keyshare.
final sdk.SchnorrKeyshare keyshare = await session.keygen();
print('Keyshare created, public key: ${keyshare.publicKeyHex}');
final sdk.SchnorrKeyshare refreshedKeyshare =
await session.refresh(keyId: await keyshare.keyId);
print('Refreshed keyshare, public key: ${refreshedKeyshare.publicKeyHex}');
}
import 'package:silent_shard_sdk/silent_shard_sdk.dart' as sdk;
Future<void> refresh(sdk.TaprootSession session) async {
// Creating a new keyshare for demo purpose. In real application, you can use an existing keyshare.
final sdk.TaprootKeyshare keyshare = await session.keygen();
print('Keyshare created, public key: ${keyshare.publicKeyHex}');
final sdk.TaprootKeyshare refreshedKeyshare =
await session.refresh(keyId: keyshare.keyId);
print('Refreshed keyshare, public key: ${refreshedKeyshare.publicKeyHex}');
}
- When
session.refresh(keyshare)is called, the app and the server exchange messages to "refresh" the MPC wallet. Refer to Key Refresh for more details. - This process enhances the long-term security of the MPC wallet by proactively updating the client's and server's secret shares.
- The wallet's public address or key remains unchanged during this process.
- The
refreshedKeyshareobject is of type DklsKeyshare and represents the client's new share of the MPC wallet.
Update the client's and server's secret shares without altering the wallet's public address or key.
Step 1 : Create Session
- Create DuoSession if you haven't already.
Step 2 : Perform Key-Refresh
- Call duoSession.refresh() with the
keyIdof the wallet to refresh. It returns Result of Success with the refreshed keyshareByteArrayor Failure with exception. The refreshed share is also persisted to your StorageClient under the samekeyId.
Example
// refresh rotates both parties' shares for the key addressed by keyId, leaving
// the public key unchanged. The new share is persisted under the same keyId.
suspend fun performKeyRefresh(keyId: String, duoSession: DuoSession): ByteArray {
return withContext(Dispatchers.IO) {
duoSession.refresh(
keyId = keyId
).getOrThrow()
}
}
keyIdaddresses the wallet whose shares are refreshed (from keygen/import).- duoSession.refresh() performs message exchange between mobile and server to "refresh" the MPC wallet. Refer to Key Refresh for more details.
- Result of duoSession.refresh() could be a
Successwith the refreshed keyshareByteArray(also persisted to your StorageClient under the samekeyId) orFailurewithException - This process enhances the long-term security of the MPC wallet by proactively updating the client's and server's secret shares.
- The wallet's public address or key remains unchanged during this process.
Update the client's and server's secret shares without altering the wallet's public address or key.
Step 1 : Create Session
- Create DuoSession if you haven't already.
Step 2 : Perform Key-Refresh
- Call duoSession.refresh() with the
keyIdof the keyshare to refresh. It returns aResultofSuccesswithDataorFailurewitherror. The refreshed keyshare is persisted to your storage client under the samekeyId.
Example
// Rotate the keyshares of the key addressed by keyId (from keygen/import).
// The public key stays the same; the refreshed share is persisted under the
// same keyId in your StorageClient.
func performRefresh(keyId: String, duoSession: DuoSession) async -> Data? {
let result = await duoSession.refresh(keyId: keyId)
// returns nil if the operation fails, or handle it however your flow needs
switch result {
case .success(let refreshedKeyshare):
// do something with the refreshed keyshare bytes
Swift.print(refreshedKeyshare)
return refreshedKeyshare
case .failure(let error):
// show the error to the user or abort the process
Swift.print(error)
return nil
}
}
keyIdaddresses the client's keyshare in your storage client (returned bykeygen/import).- duoSession.refresh() performs message exchange between mobile and server to "refresh" the MPC wallet. Refer to Key Refresh for more details.
- Result of duoSession.refresh() could be a
Successwith bytes asData(client's new share of the MPC wallet) orFailurewitherror - This process enhances the long-term security of the MPC wallet by proactively updating the client's and server's secret shares.
- The wallet's public address or key remains unchanged during this process.
A refresh rewrites both shares, so an interrupted refresh could leave the device without a usable share. The reconcile protocol is the fallback that prevents this.