Skip to main content

Generate and Validate Keyshares

This part of the SSV SDK lets you generate validator keyshares by splitting validator keys into threshold shares with Shamir Secret Sharing (SSS) and encrypting them with operator public keys.

The resulting shares and signatures are packaged as sharesData, which is used during validator registration through the SSV smart contracts to distribute keyshares from stakers to operators.

The SDK can also validate keyshares before registration to help ensure the validator can be registered successfully.

Prerequisites

Before using this example, make sure you have:

Install dependencies

Install the SSV SDK and required dependencies:

npm install @ssv-labs/ssv-sdk viem

Initialize the SDK

Create an SDK instance to interact with the SSV Network:

import { SSVSDK, chains } from '@ssv-labs/ssv-sdk'
import { createPublicClient, http } from 'viem'
// Use chains.mainnet for mainnet
const publicClient = createPublicClient({
chain: chains.hoodi,
transport: http('https://ethereum-hoodi-rpc.publicnode.com'),
})
const sdk = new SSVSDK({
publicClient,
})

Generate Keyshares

Use generateKeyShares to create keyshares from a validator keystore and encrypt them with the selected operator public keys.

Operator public keys are required to encrypt keyshares. These can be retrieved using the SDK based on operator IDs.

const ownerAddress = "0xA4831B989972605A62141a667578d742927Cbef9"
const nonce = Number(await sdk.api.getOwnerNonce({ owner: ownerAddress }))
const operatorIds = ["1", "2", "3", "4"]
// Fetch operator metadata from the SDK API
const operators = await sdk.api.getOperators({ operatorIds })
if (operators.length !== operatorIds.length) {
throw new Error('One or more operator IDs were not found')
}
// Build operator public keys in the same order as operatorIds.
const operatorKeys = operatorIds.map((id) => {
const op = operators.find((o) => o.id === id)
if (!op) throw new Error(`Operator ${id} not found`)
return op.publicKey
})
// Generate encrypted keyshares from keystore(s).
const keysharesPayload = await sdk.utils.generateKeyShares({
keystore: JSON.stringify(keystoresObject), // or string[]
keystorePassword: "INSERT_PASSWORD",
operatorKeys,
operatorIds: operatorIds.map(Number),
ownerAddress,
nonce,
})

Validate Keyshares

Use validateSharesPreRegistration to verify that the generated keyshares and operator IDs are valid before registering the validator.

const ownerAddress = "0xA4831B989972605A62141a667578d742927Cbef9"
const operatorIds = ["1", "2", "3", "4"]
// Validate keyshares and operator set before registration.
const validatedShares = await sdk.utils.validateSharesPreRegistration({
keyshares: keysharesPayload,
operatorIds,
ownerAddress, // required if no walletClient in sdk init
})
console.log(validatedShares)

A valid keyshare can then be used to register a validator.