Skip to main content

Keyshares file structure

An example of keyshares.json structure:

{
"version": "v1.1.0",
"createdAt": "2025-05-14T10:23:43.794Z",
"shares": [
{
"data": {
"ownerNonce": 0,
"ownerAddress": "OWNER_ADDRESS",
"publicKey": "VALIDATOR_PUBKEY",
"operators": [
{
"id": 1,
"operatorKey": "OPERATOR_PUBKEY"
},
{...},
{...},
{...}
]
},
"payload": {
"publicKey": "VALIDATOR_PUBKEY",
"operatorIds": [1,2,3,4],
"sharesData": "ENCRYPTED_SHARES_DATA"
}
}
]
}

Details about sharesData field

Below is an example of sharesData from a Hoodi validator with 4 operators. Each segment is highlighted with color:

Explanation of each segment:

  • Signature - First 192 characters (excluding 0x) is a serialized BLS signed message (read more about SSZ here). The message itself is ownerAddress:ownerNonce, it's signed by the validator private key and consequently can be verified using validator's publicKey.
  • Shares' public keys - An array of concatenated BLS public keys. Each element is a public share of a validator's key and is 96 characters long. The number of shares depends on the number of chosen operators.
  • Encrypted shares - An array of concatenated BLS encrypted keys. Each element is a private share of a validator's key and is 512 characters long. The number of shares depends on the number of chosen operators. Shares are encrypted with each operator's public key and can only be decrypted with the respective private key.

If you want to learn more about keyshare verification, you can dissect verify-keyshare repository on GitHub:

  • validateSingleShares function in ssv-keys.ts does the signature verification.
  • buildSharesFromBytes function breaks down each operators' keyshare.
  • areKeysharesValid function then checks the signature and operators' keyshares agains the validator public key.