Stake Pool Certificates
Stake pool operators must provide an operational certificate to verify that the pool has the authority to run. The certificate includes the operator’s signature and important information about the pool (addresses, keys, etc.)
Overview
Operational certificates represent the link between the operator’s offline key and their operational key. A certificate’s job is to check whether or not an operational key is valid, to prevent malicious interference. The certificate identifies the current operational key, and is signed by the offline key.
Certificates are generated with an issue counter number and included in the header of each block the node generates. Note that with the Vasil hard fork, an operator would need to create an operational certificate using cold.counter +1. This means that the OpCert must be exactly one more than the previously used one. Certificates include a kes-period (start date), which indicates the time span within which the certificate is valid before you need to create another one.
The counter becomes significant when an attacker has compromised the KES key, in which case the owner of the cold keys can create a new KES key and a new certificate with a higher issue number. If a node sees two blocks claiming to originate from the same cold key, but using different KES keys, the higher issue counter trumps the lower one.
Certificates are generated on the offline machine using the offline/cold keys, before being copied over to the node to validate the KES keys used to sign the blocks.
Your stake pool requires a valid operational certificate to verify that the pool has the authority to run. A current KES key pair is required to establish an operational certificate for your stake pool. A KES period indicates the time span when an operational certificate is valid. An operational certificate expires 90 days after the KES period defined in the operational certificate. You must generate a new KES key pair and operational certificate every 90 days, or sooner, for your stake pool to mint blocks. The private KES key is required to start the block-producing node for your stake pool. The public KES key is not sensitive. Issuing an operational certificate also uses a counter that increments by exactly one (1) for each unique operational certificate that a stake pool uses to mint blocks. In a valid operational certificate, the counter value that you use to issue the operational certificate must be consistent with the current counter value for your stake pool registered on the Cardano blockchain by the protocol.
Stake Address Registration Certificate
cardano-cli stake-address registration-certificate \
--stake-verification-key-file stake.vkey \
--out-file stake.cert
output
{
"type": "CertificateShelley",
"description": "Stake Address Registration Certificate",
"cborHex": "82008200581c361bf121274521fafb8e182145d0e7601f41f2456b0b4c804bf0fdae"
}
Stake Pool Registration Certificate
Metadata hash value
cardano-cli shelley stake-pool metadata-hash --pool-metadata-file filename.json
Stake pool registration certificate
cardano-cli stake-pool registration-certificate \
--cold-verification-key-file cold.vkey \
--vrf-verification-key-file vrf.vkey \
--pool-pledge 1000000 \
--pool-cost 340000000 \
--pool-margin 0.015 \
--pool-reward-account-verification-key-file stake.vkey \
--pool-owner-stake-verification-key-file stake.vkey \
--mainnet \
--pool-relay-ipv4 51.75.70.115 \
--pool-relay-port 3000 \
--metadata-url https://cardanoblockchain.wiki/poolMetadata.json \
--metadata-hash 111d56ef2d43589d00caef405c1d63259f5597940f11d49613540210c065318d \
--out-file pool-registration.cert
output
{
"type": "CertificateShelley",
"description": "Stake Pool Registration Certificate",
"cborHex": "8a03581cfd0a4bed6b33606fe9c5124a1dd37261ea704bc5a2422166b47a73545820ed3effb4acd1a9062d495a41ced50bf48d304e6af86b611d1429c69f540cb8ec1a000f42401a1443fd00d81e820318c8581de136abf921114521fafb8e182145d0e7611141f2456b0b4c804bf0fdae81581c36abf921274521fafb8e182145d0e7605f41f2456b0b4c804bf0fdae818400190bb844334b4673f682783068747470733a2f2f63617264616e6f626c6f636b636861696e2e77696b692f706f6f6c4d657461646174612e6a736f6e5820111d56ef2d43589d00caef405c1d63259f5597940f11d49613540210c065318d"
}
Stake Address Delegation Certificate
This creates a delegation certificate that delegates fund from all stake addresses associated with key stake.vkey to the pool belonging to cold key cold.vkey. If we had used different staking keys for the pool owners in the first step, we would need to create delegation certificates for all of them instead. We have to honor our pledge by delegating at least the pledged amount to our pool, so we have to create a delegation certificate to achieve this:
cardano-cli stake-address delegation-certificate \
--stake-verification-key-file stake.vkey \
--cold-verification-key-file cold.vkey \
--out-file delegation.cert
output
{
"type": "CertificateShelley",
"description": "Stake Address Delegation Certificate",
"cborHex": "8302180581c36abf9211274521fafb8e182145d0e7605f41f2456b0b4c804bf0fdae581cfd0a4bed6b33606fe9c5124a1dd37261ea704bc5a2422166b47a7354"
}
NodeOperationalCertificate
cardano-cli query kes-period-info --mainnet --op-cert-file node.cert
# {
# "qKesCurrentKesPeriod": 561,
# "qKesEndKesInterval": 623,
# "qKesKesKeyExpiry": null,
# "qKesMaxKESEvolutions": 62,
# "qKesNodeStateOperationalCertificateNumber": null,
# "qKesOnDiskOperationalCertificateNumber": 1,
# "qKesRemainingSlotsInKesPeriod": 7998928,
# "qKesSlotsPerKesPeriod": 129600,
# "qKesStartKesInterval": 561
# }
cardano-cli node new-counter \
--cold-verification-key-file cold.vkey \
--counter-value () \
--operational-certificate-issue-counter-file cold.counter
curl -s 127.0.0.1:12798/metrics | grep KES
# cardano_node_metrics_operationalCertificateExpiryKESPeriod_int 623
# cardano_node_metrics_currentKESPeriod_int 561
# cardano_node_metrics_remainingKESPeriods_int 62
# cardano_node_metrics_operationalCertificateStartKESPeriod_int 561
cardano-cli node issue-op-cert \
--kes-verification-key-file kes.vkey \
--cold-signing-key-file cold.skey \
--operational-certificate-issue-counter cold.counter \
--kes-period 561 \
--out-file node.cert
output
{
"type": "NodeOperationalCertificate",
"description": "",
"cborHex": "82845820afcbbd0d5728911e204ffb905a6c89d1eba6c7adadffc19fee7f623cae8bdd620018b65840261bbad4732e2daae7240c9bea6834fd38fa57de2d3682f21117c37f2b7974461ccd99e16a1db190cdce493e25769711f2467b07eca6bf21508a73f65da16c0458200bc05daf384141af9d28a3f841fca40e6861e18a4705c23e752c581ca69ab9d2"
}
Operational Certificate Counter
cardano-cli query kes-period-info \
--mainnet \
--op-cert-file node.cert