You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: doc/stake-pool-operations/KES_period.md
+165-23
Original file line number
Diff line number
Diff line change
@@ -4,43 +4,185 @@ To create an operational certificate for a block-producing node, you need a _KES
4
4
5
5
Here "KES" stands for _**K**ey **E**volving **S**ignature_, which means that after a certain _period_, the key will _evolve_ to a new key
6
6
and discard its old version. This is useful, because it means that even if an attacker compromises the key and gets access to the signing key,
7
-
he can only use that to sign blocks _from now on_, but not blocks dating from _earlier periods_, making it impossible for the attacker to rewrite history.
7
+
he can only use that to sign blocks _from now on_, but not blocks dating from _earlier periods_, making it impossible for the attacker to rewrite history. To generate a new KES key pair, see below.
8
8
9
9
A KES key can only evolve for a certain number of periods and becomes useless afterwards.
10
10
This means that before that number of periods has passed, the node operator has to generate a new KES key pair, issue a new operational node certificate with that new key pair and restart the node with the new certificate.
11
11
12
+
### KES key generation
13
+
14
+
```bash
15
+
cardano-cli node key-gen-KES \
16
+
--verification-key-file kes.vkey \
17
+
--signing-key-file kes.skey
18
+
```
19
+
12
20
To find out how long one period is and for how long a key can evolve, we can look into the _genesis file_. If that file is called `mainnet-shelley-genesis.json`,
13
-
we can type
21
+
we can type:
14
22
15
-
cat mainnet-shelley-genesis.json | grep KES
16
-
"slotsPerKESPeriod": 129600,
17
-
"maxKESEvolutions": 62,
23
+
```bash
24
+
cat mainnet-shelley-genesis.json | grep KES
25
+
"slotsPerKESPeriod": 129600,
26
+
"maxKESEvolutions": 62,
27
+
```
18
28
19
-
in this example, the key will evolve after each period of 129600 slots and that it can evolve 62 times before it needs to be renewed.
29
+
The key will evolve after each period of 129600 slots and it can evolve up to 62 times before it needs to be renewed.
20
30
21
31
Before we can create an operational certificate for our node, we need to figure out the start of the KES validity period, i.e. which KES evolution period we are in.
In this example, we are currently in slot 26633911, and we know from the genesis file that one period lasts for 129600 slots. So we calculate the current period:
**This command increments the cold counter by 1.**
61
+
62
+
## :warning: Vasil hard fork breaking changes
63
+
64
+
Note that from the Vasil hard fork onwards there is a new rule for the cold.counter:
65
+
66
+
A new operational certificate will be considered valid if its counter value is exactly one more than the previous operational certificate that has successfully minted at least one block. Prior to Vasil, it was permitted to use any strictly larger counter value than used on chain previously, but this is no longer permitted. It must be incremented by exactly one. In particular, this means one cannot use the current time or slot number as a counter value.
67
+
68
+
### Find the counter value used on-chain
69
+
70
+
To find out the actual `OpCert` counter used on-chain, run:
✓ Operational certificate's KES period is within the correct KES period interval
77
+
✓ The operational certificate counter agrees with the node protocol state counter
78
+
{
79
+
"qKesCurrentKesPeriod": 15,
80
+
"qKesEndKesInterval": 18,
81
+
"qKesKesKeyExpiry": null,
82
+
"qKesMaxKESEvolutions": 6,
83
+
"qKesNodeStateOperationalCertificateNumber": 3,
84
+
"qKesOnDiskOperationalCertificateNumber": 3,
85
+
"qKesRemainingSlotsInKesPeriod": 690,
86
+
"qKesSlotsPerKesPeriod": 300,
87
+
"qKesStartKesInterval": 12
88
+
}
89
+
```
90
+
91
+
* `"qKesNodeStateOperationalCertificateNumber": 3,` is the last counter registered **OnChain** to forge a block.
92
+
93
+
* `"qKesOnDiskOperationalCertificateNumber": 3,` is the counter value of your **OnDisk** operational certificate.
94
+
95
+
96
+
When your pool has already forged a block in the current KES interval the above values must match.
97
+
98
+
If your pool has **not** yet forged a block in the current KES Interval it's ok that `cardano-cli query kes-period-info` shows that `"qKesOnDiskOperationalCertificateNumber"` is greater than `"qKesNodeStateOperationalCertificateNumber"` by exactly one (1), for example:
99
+
100
+
```
101
+
"qKesNodeStateOperationalCertificateNumber": 2,
102
+
"qKesOnDiskOperationalCertificateNumber": 3,
103
+
```
104
+
105
+
Once your pool forges a block `qKesNodeStateOperationalCertificateNumber` will be updated accordingly **(OnChain)** and these values will be the same.
106
+
107
+
### How do I know if I have issued an _invalid_ operational certificate
108
+
109
+
An easy way to know if you have issued an invalid certificate is using `cardano-cli query kes-period-info` right after you have created the new operational certificate. If the **OnDisk** counter differs from the **OnChain** counter by more than 1, your certificate is _invalid_, for example:
110
+
111
+
```
112
+
"qKesNodeStateOperationalCertificateNumber": 2,
113
+
"qKesOnDiskOperationalCertificateNumber": 4,
114
+
```
115
+
116
+
### My pool has not forged a block in the current KES interval and I need to issue new operational certificate. What should I do with the counter?
117
+
118
+
Keep in mind that the rule is that the counter must be one more than the last counter used to _actually_ forge a block in the _current chain_. So if we have not forged a block during the current KES interval, the counter must not be incremented when issuing a new OpCert i.e it remains the same.
119
+
120
+
In this scenario `cardano-cli query kes-period-info` will show that the **OnDisk** counter is greater than the **On-Chain** counter
121
+
122
+
```
123
+
"qKesNodeStateOperationalCertificateNumber": 2,
124
+
"qKesOnDiskOperationalCertificateNumber": 3,
125
+
```
126
+
127
+
Therefore, we **cannot** use `cardano-cli node issue-op-cert...` right away to issue a new operational certificate because this would increment the **OnDisk** counter by 1 more, resulting in something like:
128
+
129
+
```
130
+
"qKesNodeStateOperationalCertificateNumber": 2,
131
+
"qKesOnDiskOperationalCertificateNumber": 4,
132
+
```
133
+
134
+
If we issue a certificate with such a counter, any block we forge with it will be an **Invalid Block**. The node logs will show the **error**:
135
+
136
+
```
137
+
[CLR:cardano.node.ChainDB:Error:25][2022-06-30 03:25:37.01 UTC] Invalid block 237602735e6b56985109480aefbc4821f57e6389736be238ffbec4c0188f9702 at slot 5206: ExtValidationErrorHeader (HeaderProtocolError (HardForkValidationErrFromEra S (S (S (S (S (Z (WrapValidationErr {unwrapValidationErr = CounterOverIncrementedOCERT 2 4}))))))))
138
+
```
139
+
140
+
### Recovering after having issued an _invalid_ certificate OR to issue a new certificate when our pool has not forged a block during the current KES interval:
141
+
142
+
1. Query `kes-period-info`. You can save the json output to a file using the `--out-file` flag
2. Create a new counter (on your cold environment)
33
163
34
-
In this example, we are currently in slot 26633911, and we know from the genesis file that one period lasts for 129600 slots. So we calculate the current period by
164
+
Take the **OnChain** counter from above. In this case `"qKesNodeStateOperationalCertificateNumber": 2` and increment it by exactly 1 when issuing the new counter:
0 commit comments