Keyshare
The keyshare module manages shares of keys for threshold decryption of transactions by a majority of the validator set.
Invariants
Active validators must submit a valid keyshare each block.
Test coverage
The individual messages are tested in Go unit tests.
Attack surface
Messages
MsgUpdateParams
The MsgUpdateParams
message updates the parameters of the keyshare module.
It must be signed by the keeper's
Authority
, which is initialized to the keyshare module's module address.It enforces that the
KeyExpiry
,MinimumBonded
, andMaxIdledBlock
fields are of typeuint64
, that theAvgBlockTime
field is of typefloat32
, thatSlashFractionNoKeyshare
andSlashFractionWrongKeyshare
are decimals in the range , and thatTrustedAddresses
is a list of Bech32-encoded addresses.
MsgRegisterValidator
The MsgRegisterValidator
message registers a new validator with the keyshare module.
It must be signed by the validator being registered.
It checks that the signer has not already been registered with the keyshare module.
It checks that the signer is registered with the staking module, and that it exceeds the keyshare module's minimum bonded token threshold.
It then adds the validator to its validator set and marks it as if it had submitted a keyshare for the current block.
MsgDeRegisterValidator
The MsgDeRegisterValidator
message deregisters an existing validator from the keyshare module.
It must be signed by the validator being deregistered.
It checks that the signer is a registered validator with the keyshare module.
It removes the signer from the list of authorized addresses, decreases the count of addresses authorized by the signer, and removes the signer from its validator set.
MsgSendKeyshare
The MsgSendKeyshare
message sends a keyshare for a validator at a specified height.
The keyshare must be a hex string containing 96 bytes.
The signer must be a registered validator or have been authorized by a registered validator.
If the signer is a validator, they must not have authorized an address to submit keyshares other than the one they are signing with.
The height specified must be either the current block's height or the next block's height.
The keyshare must have been committed to at the specified keyshare index.
If the keyshare is not what was committed to, the validator is slashed by a constant amount (this occurs spuriously in simulation on key-expiry boundaries; see Finding ref↗).
If the keyshare is valid,
The keyshare is stored, keyed by the signer and target block height.
The validator's latest submitted height is set to the current block.
If the decryption key has not yet been constructed for the next block, and enough keyshares have been submitted to construct it, the decryption key is constructed and stored in both the keyshare module's state and the PEP module's state.
MsgCreateLatestPubkey
The MsgCreateLatestPubkey
message creates a public key for the keysharing protocol for a future epoch.
The public key must be a hex string containing 48 bytes.
The message must specify the same number of validators, commitments, and encrypted keyshares, which must not be zero.
Each commitment must be a hex string containing 48 bytes; each encrypted keyshare must be nonempty Base64-encoded data.
The signer must be in the keyshare module's list of
TrustedAddresses
.A queued public key must not already exist.
If there is no currently active public key, the new key's expiry height is set to the sum of the current block height and the
KeyExpiry
parameter; otherwise, the new key's expiry height is set to the sum of the current key's expiry height and theKeyExpiry
parameter.The new public key, its encrypted shares, and the commitments are stored in the keyshare module's state as the queued public key and commitments, and the new public key is stored as the PEP module's queued public key.
MsgOverrideLatestPubkey
The MsgOverrideLatestPubkey
message overrides the public key for the keysharing protocol for the current epoch.
The public key must be a hex string containing 48 bytes.
The message must specify the same number of validators, commitments, and encrypted keyshares, which must not be zero.
Each commitment must be a hex string containing 48 bytes; each encrypted keyshare must be nonempty Base64-encoded data.
The signer must be in the keyshare module's list of
TrustedAddresses
.The new key's expiry height is set to the sum of the current block height and the
KeyExpiry
parameter.The active and queued public key are deleted from the state if present.
Active validators not assigned an encrypted keyshare from the message are removed.
The new public key, its encrypted shares, and the commitments are stored in the keyshare module's state as the active public key and commitments, and the new public key is stored as the PEP module's active public key.
MsgCreateAuthorizedAddress
The MsgCreateAuthorizedAddress
message allows a validator to authorize a different address from their validator address to participate in the keysharing protocol.
The target address must not already have been authorized and must be distinct from the signer.
The signer must be a validator registered with the keyshare module.
The validator must not have authorized another address.
The authorization is stored in the keyshare module's state.
MsgUpdateAuthorizedAddress
The MsgCreateAuthorizedAddress
message updates whether the target address that a validator designated is authorized to continue to participate in the keysharing protocol.
The target address must have previously been authorized by the signer.
The target address must be distinct from the signer.
The
IsAuthorized
flag is updated in the keyshare module's state based on the message'sIsAuthorized
flag.
MsgDeleteAuthorizedAddress
The MsgDeleteAuthorizedAddress
message revokes authorization for an address to participate in the keysharing protocol on behalf of a validator.
The target address must have previously been authorized by the signer.
The signer must be either the target address or the validator address that provided authorization.
The authorization is removed from the keyshare module's state.
MsgSubmitGeneralKeyshare
The MsgSubmitGeneralKeyshare
message submits a keyshare for a general (non--target-height) identity.
The signer must be a registered validator or have been authorized by a registered validator.
If the signer is a validator, they must not have authorized another address to submit keyshares than the one they are signing with.
The message's
IdType
must be one of theSupportedIdTypes
(currently justPrivateGovIdentity
).For
PrivateGovIdentity
id types, there must be a decryption key request stored in the state under the message'sIdValue
with a non-empty decryption key.The keyshare must have been committed to at the specified keyshare index.
If the keyshare is not what was committed to, the validator is slashed by a constant amount.
If the keyshare is valid —
The keyshare is stored as a general keyshare, keyed by the signer, ID type, and ID value.
The validator's latest submitted height is set to the current block.
If the decryption key has not yet been constructed for the specified identity, and enough keyshares have been submitted to construct it, the decryption key is constructed.
If the identity type for the constructed decryption key is PrivateGovIdentity
—
If the decryption key was requested over IBC, a
DecryptionKeyDataPacket
is sent over IBC to the chain that requested it with a 20-second time-out.If it was requested by a governance proposal, the decryption key is stored in the governance module's state as part of the proposal.
Otherwise, the decryption key is stored in the PEP module under the request's identity and added to the PEP module's execution queue.
MsgSubmitEncryptedKeyshare
The MsgSubmitEncryptedKeyshare
message submits an encrypted keyshare for a validator for a private decryption key request.
The signer must be a registered validator, or have been authorized by a registered validator.
If the signer is a validator, they must not have authorized an address to submit keyshares other than the one they are signing with.
A
PrivateDecryptionKeyRequest
must exist for the specified identity.The specified keyshare commitment index must be in bounds.
The encrypted keyshare is stored, and the validator's latest submit height is set to the current block.
If enough encrypted keyshares are present to reconstruct the decryption key, a
PrivateDecryptionKeyDataPacket
is sent to the chain that initiated the request if the request was initiated over IBC; otherwise, the request is routed to the PEP module.
IBC packets
RequestDecryptionKeyPacket
The RequestDecryptionKeyPacket
packet is used by the PEP module to request a decryption key from the keyshare module for a proposal or identity. The keyshare module acknowledges the packet with a either the active or queued decryption key based on the estimated arrival time of the response based on the average block chain, and it specifies the identity based on whether or not the key is for a proposal. The PEP module updates its state with the key if it did not already have a key for the specified identity.
GetDecryptionKeyPacket
The GetDecryptionKeyPacket
packet is used by the PEP module to get a decryption key from the keyshare module for an identity. The keyshare module acknowledges the packet with either the active or queued pubkey based on the DecryptionKeyRequest
state associated with the specified identity. The PEP module's packet-acknowledgment handler attempts to decode the response in OnAcknowledgementGetDecryptionKeyPacket
as if it were a RequestDecryptionKeyPacketAck
, and it does not make use of the decoded data.
DecryptionKeyDataPacket
The DecryptionKeyDataPacket
packet is used by the keyshare module to send decryption keys to the PEP module. The PEP module stores the key and schedules execution if it has a pending request for the identity associated with the key. The keyshare module attempts retransmission if the PEP module acknowledges the packet with an error.
PrivateDecryptionKeyDataPacket
The PrivateDecryptionKeyDataPacket
packet is used by the keyshare module to send encrypted keyshares to the PEP module. The PEP module stores the encrypted keyshares if it has a pending request for them.
CurrentKeysPacket
The CurrentKeysPacket
packet is used by the PEP module to request the active and queued public keys from the keyshare module. The keyshare module acknowledges the packet with the active and queued public keys, and the PEP module updates its state when processing the packet acknowledgment if their expiries are newer.
RequestPrivateDecryptionKeyPacket
The RequestPrivateDecryptionKeyPacket
is used by the PEP module to request encrypted keyshares from the keyshare module. The keyshare module stores the request in its state on receipt of the packet, and the PEP module stores the pending request on receiving the acknowledgment.
GetPrivateDecryptionKeyPacket
The GetPrivateDecryptionKeyPacket
is used by the PEP module to get encrypted keyshares from the keyshare module. The keyshare module creates a request for the encrypted keyshares if one was not yet present in its state.