Skip to content

Commit 156fa01

Browse files
amendments 4
amendments Some amendments Document cold.counter breaking changes for babbage
1 parent 42809ad commit 156fa01

File tree

1 file changed

+165
-23
lines changed

1 file changed

+165
-23
lines changed

doc/stake-pool-operations/KES_period.md

+165-23
Original file line numberDiff line numberDiff line change
@@ -4,43 +4,185 @@ To create an operational certificate for a block-producing node, you need a _KES
44

55
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
66
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.
88

99
A KES key can only evolve for a certain number of periods and becomes useless afterwards.
1010
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.
1111

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+
1220
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:
1422

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+
```
1828

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.
2030

2131
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.
2232

2333
We check the current tip of the blockchain:
2434

25-
cardano-cli query tip --mainnet
35+
```bash
36+
cardano-cli query tip --mainnet
37+
{
38+
"epoch": 259,
39+
"hash": "dbf5104ab91a7a0b405353ad31760b52b2703098ec17185bdd7ff1800bb61aca",
40+
"slot": 26633911,
41+
"block": 5580350
42+
}
43+
```
44+
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:
45+
46+
```bash
47+
expr 26633911 / 129600
48+
> 205
49+
```
50+
51+
### Issue operational certificate
52+
```bash
53+
cardano-cli node issue-op-cert \
54+
--kes-verification-key-file kes.vkey \
55+
--cold-signing-key-file cold.skey \
56+
--operational-certificate-issue-counter cold.counter \
57+
--kes-period 205 \
58+
--out-file opcert.cert
59+
```
60+
**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:
71+
72+
```bash
73+
> cardano-cli query kes-period-info --testnet-magic 42 --op-cert-file node-spo3/opcert.cert
74+
75+
>
76+
✓ 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
143+
144+
```bash
145+
> cardano-cli query kes-period-info --testnet-magic 42 --op-cert-file node-spo3/opcert.cert --out-file kes_period_info.json
146+
147+
> cat kes_period_info.json
26148
27-
{
28-
"epoch": 259,
29-
"hash": "dbf5104ab91a7a0b405353ad31760b52b2703098ec17185bdd7ff1800bb61aca",
30-
"slot": 26633911,
31-
"block": 5580350
32-
}
149+
>
150+
{
151+
"qKesCurrentKesPeriod": 18,
152+
"qKesEndKesInterval": 18,
153+
"qKesKesKeyExpiry": null,
154+
"qKesMaxKESEvolutions": 6,
155+
"qKesNodeStateOperationalCertificateNumber": 2,
156+
"qKesOnDiskOperationalCertificateNumber": 4,
157+
"qKesRemainingSlotsInKesPeriod": 198,
158+
"qKesSlotsPerKesPeriod": 300,
159+
"qKesStartKesInterval": 12
160+
}
161+
```
162+
2. Create a new counter (on your cold environment)
33163

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:
35165

36-
expr 26633911 / 129600
37-
> 205
166+
```bash
167+
cardano-cli node new-counter \
168+
--cold-verification-key-file cold.vkey \
169+
--counter-value $((2 + 1)) \
170+
--operational-certificate-issue-counter-file cold.counter
171+
```
172+
3. Generate new KES keys if needed (because of MaxKESEvolutions reached):
38173

39-
With this we are able to generate an operational certificate for our stake pool:
174+
```bash
175+
cardano-cli node key-gen-KES \
176+
--verification-key-file kes.vkey \
177+
--signing-key-file kes.skey
178+
```
179+
4. Issue the new operational certificate:
40180

41-
cardano-cli node issue-op-cert \
42-
--kes-verification-key-file kes.vkey \
43-
--cold-signing-key-file cold.skey \
44-
--operational-certificate-issue-counter cold.counter \
45-
--kes-period 205 \
46-
--out-file node.cert
181+
```bash
182+
cardano-cli node issue-op-cert --kes-verification-key-file kes.vkey \
183+
--cold-signing-key-file cold.skey \
184+
--operational-certificate-issue-counter-file cold.counter \
185+
--kes-period 18 \
186+
--out-file "opcert.cert"
187+
```
188+
5. Copy `opcert.cert` and `kes.skey` to your block producer and restart it.

0 commit comments

Comments
 (0)