Skip to content

Commit 718051a

Browse files
committed
doc
1 parent 05b3cdb commit 718051a

File tree

1 file changed

+255
-0
lines changed

1 file changed

+255
-0
lines changed
Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
# Migrating a Partner Chain to use Beefy
2+
3+
## Introduction
4+
5+
This document describes step by step how to extend an already running Partner Chain
6+
with Beefy. The migration path described maintains backward compatibility, avoids a
7+
chain reset and allows historical blocks to be imported by new nodes post-migration.
8+
9+
## Warnings
10+
11+
1. Remember that runtime upgrades are inherently risky and can brick a chain if done
12+
incorrectly. **Always test any runtime upgrade before applying it to a live chain.** This
13+
can be done using [try-runtime](https://github.com/paritytech/try-runtime-cli) for
14+
quickly verifying only the runtime and storage updates, or using a locally run chain,
15+
ideally one cloned from the target live chain. It is advised to do both.
16+
2. For security, Partner Chain committee selection requires that a committee is chosen
17+
and produces at least one block for each Partner Chain epoch. This means that a chain
18+
will **stall indefinitely** if at some point the valid candidate pool for some epoch is
19+
empty.
20+
3. Any on-chain updates to the authority selection inputs on Cardano (SPO registrations,
21+
D-Param and permissioned candidate list) **only become effective after two full Cardano
22+
epochs have passed**. If the updates are done in preparation for subsequent changes to the
23+
Partner Chain that would invalidate the previous on-chain values, at least this much time
24+
should be observed before applying these changes.
25+
26+
## Context and considerations
27+
28+
Beefy is a bridge-oriented protocol that provides state inclusion proofs for cross-chain
29+
communication. It is not a finality gadget by itself and builds upon existing finality
30+
mechanisms such as Grandpa.
31+
32+
Node components of Beefy are capable of detecting the pallet in the runtime and will stay
33+
inactive until it is present and the Beefy genesis block is set. This means that nodes can
34+
be prepared to support Beefy before the migration and still support historical blocks as
35+
needed.
36+
37+
Beefy introduces its own set of authority keys that are used by committee members to sign
38+
finality proofs each round. These keys are managed by `pallet-session` together with other
39+
session keys used by the chain. The main concern when adding Beefy to a running chain is
40+
migrating the existing key storages and ensuring that block producer's Beefy keys are set
41+
before Beefy starts operating.
42+
43+
The Partner Chain toolkit has been prepared to support migrating to Beefy and similar
44+
functionalities that require introduction of new authority keys, with the only requirement
45+
being that the feature's implementation makes it possible to postpone its activation for
46+
some time after being added to the runtime.
47+
48+
## Migration steps outline
49+
50+
In short, the migration plan is as follows:
51+
52+
0. Update candidate data to include Beefy keys by updating the permissioned candidate list
53+
and instructing SPOs to re-register themselves
54+
1. Add Beefy offchain services to the node code and upgrade nodes in the network, including
55+
Beefy keys in their keystores.
56+
2. Add Beefy to the runtime, together with all supporting pallets
57+
3. Extend the session keys type to include Beefy keys
58+
4. Schedule session keys type migration
59+
5. Perform runtime upgrade
60+
6. Wait for a new session, which will update authority keys
61+
7. Set new genesis block in Beefy to activate the pallet
62+
63+
64+
## Migration steps details
65+
66+
### Updating candidate data
67+
68+
When in
69+
the next steps the runtime is upgraded and Beefy keys are added to the session keys type,
70+
any candidate missing them in their candidate data on Cardano will be rejected by the commitee
71+
selection algorithm.
72+
73+
To prepare for that, the Partner Chains toolkit allows candidate data stored on Cardano to include
74+
additional keys to those that are currently required. Those keys will become visible to the Partner
75+
Chain after two Cardano epochs have passed.
76+
77+
In this preparatory step, both the governance authority of the Partner Chain and individual Cardano
78+
SPOs should update data on-chain to include Beefy keys.
79+
80+
First, every SPO and permissioned node operator needs to generate their Beefy key and insert it into
81+
their keystore. The key can be generated using the command:
82+
```shell
83+
$ pc-node key generate --scheme ecdsa
84+
```
85+
and the generated secret phrase can be inserted to the keystore using:
86+
```shell
87+
$ pc-node key insert --scheme ecdsa --key-type beef --suri "<secret phrase>" --keystore-path "<keystore path>"
88+
```
89+
90+
The governance authority should prepare the permissioned candidate list in CSV format in the following format:
91+
```csv
92+
<cross-chain skey hex>,aura:<aura skey hex>,gran:<grandpa skey hex>,beef:<beefy skey hex>
93+
<cross-chain skey hex>,aura:<aura skey hex>,gran:<grandpa skey hex>,beef:<beefy skey hex>
94+
...
95+
```
96+
and put it on-chain using the following command:
97+
```shell
98+
$ pc-node smart-contracts upsert-permissioned-candidates
99+
--permissioned-candidates-file <permissioned candidate file>
100+
--payment-key-file <governance skey>
101+
--genesis-utxo <genesis utxo>
102+
```
103+
104+
The SPOs should re-register their node using the wizard (see `docs/user-guides/registered.md` for instructions)
105+
or by manually creating relevant signatures using:
106+
```shell
107+
$ pc-node registration-signatures \
108+
--genesis-utxo <genesis utxo> \
109+
--mainchain-signing-key <Cardano skey hex> \
110+
--sidechain-signing-key <cross-chain skey hex> \
111+
--registration-utxo <registration utxo> # UTXO spendable from the candidate's wallet
112+
```
113+
and then submitting them on-chain using:
114+
```shell
115+
$ pc-node smart-contracts register \
116+
--genesis-utxo <genesis utxo> \
117+
--spo-public-key <Cardano pkey> \
118+
--spo-signature <Cardano signature> \
119+
--partner-chain-public-keys <cross-chain pkey>,aura:<aura pkey>,gran:<grandpa pkey>,beef:<beefy pkey> \
120+
--sidechain-signature <cross-chain signature> \
121+
--registration-utxo <registration utxo> \ # same as in previous command
122+
--payment-key-file <Cardano skey file>
123+
```
124+
125+
This process should be coordinated between the governance authority and the SPOs to allow enough time for everyone
126+
to go through the steps before the runtime upgrade.
127+
128+
Note that the nodes in the network can be freely upgraded while the re-registration period is ongoing.
129+
130+
### Upgrading network nodes
131+
132+
This step can be performed during or even before the re-registrations.
133+
134+
The node code of the Partner Chain should be updated to include Beefy services and then rolled out to the network.
135+
136+
Adding Beefy components to the node is quite involved, so the reader is encouraged to reference the demo node
137+
implementation for an example of how to do it, most importantly `demo/node/src/service.rs` for
138+
offchain services and `demo/node/src/rpc.rs` for RPC services.
139+
Keep in mind that due to Substrate using strong typing where it's possible, some changes to the runtime code will
140+
be required at this point.
141+
142+
After the node code has been updated, new node binary should be distributed to the node operators and an upgrade
143+
period should be coordinated with enough time for the majority to upgrade their nodes.
144+
145+
### Adding Beefy to the runtime
146+
147+
This step can be performed during re-registrations and together with the node code modifications in the previous step.
148+
149+
The Beefy pallet should be added to the runtime and configured, together with other pallets that support its operation:
150+
- `pallet_beefy`
151+
- `pallet_mmr`
152+
- `pallet_beefy_mmr`
153+
154+
Refer to the demo runtime at `demo/runtime/src` for an example of how to integrate these
155+
pallets to your runtime.
156+
157+
### Adding Beefy keys to session keys type
158+
159+
Adding Beefy to session keys requires just adding another field to the `impl_opaque_keys` macro.
160+
For a chain that uses Aura and Grandpa for consensus, it would look like this:
161+
```rust
162+
impl_opaque_keys! {
163+
#[derive(MaxEncodedLen, PartialOrd, Ord)]
164+
pub struct SessionKeys {
165+
pub aura: Aura,
166+
pub grandpa: Grandpa,
167+
pub beefy: Beefy,
168+
}
169+
}
170+
```
171+
172+
Keep in mind that modifying the session keys type means that from the next runtime upgrade, the added
173+
key type becomes mandatory and any candidate whose registration data doesn't include them will be
174+
considered invalid.
175+
176+
### Scheduling session keys migration
177+
178+
Any modification of the session keys type requires a storage migration that will update the values stored
179+
in `pallet-session-validator-management` and `pallet-session`.
180+
181+
First, the original session keys type should be preserved under a different name. Eg:
182+
183+
```rust
184+
impl_opaque_keys! {
185+
#[derive(MaxEncodedLen, PartialOrd, Ord)]
186+
pub struct LegacySessionKeys {
187+
pub aura: Aura,
188+
pub grandpa: Grandpa,
189+
}
190+
}
191+
```
192+
193+
Next, a conversion from the old type to the new type should be defined by implementing the `UpgradeAuthorityKeys`
194+
trait. When a new field is added to the type, a valid default value should be used, eg.:
195+
196+
```rust
197+
impl UpgradeAuthorityKeys<SessionKeys> for LegacySessionKeys {
198+
fn upgrade(self) -> SessionKeys {
199+
SessionKeys {
200+
aura: self.aura,
201+
grandpa: self.grandpa,
202+
beefy: ecdsa::Public::default().into(),
203+
}
204+
}
205+
}
206+
```
207+
208+
Finally, a key migration should be added to the runtime's migration list, using `AuthorityKeysMigration`
209+
provided by `pallet-session-validator-management`, eg:
210+
211+
```rust
212+
pub type Migrations = (
213+
AuthorityKeysMigration<Runtime, opaque::LegacySessionKeys, 0, 1>,
214+
);
215+
```
216+
217+
The migration is versioned to prevent re-running it in case it is not removed from the runtime before
218+
subsequent upgrades. The current version of the session keys used by the runtime is tracked by
219+
`pallet-session-validator-management` and updated as part of the migration. In the example, the migration
220+
is defined as going from session keys version 0 to version 1, which will be the case for chains that
221+
never migrated their keys using this mechanism before.
222+
223+
### Upgrading the runtime
224+
225+
**Important:** This step should only be performed once at least one committee member candidate's registration
226+
data containing Beefy keys becomes available for observation. This happens after *two full Cardano epochs*
227+
have passed after it was updated.
228+
229+
After the runtime code has been updated, including the session keys, the on-chain runtime should be updated
230+
by calling `system/setCode` extrinsic through the governance mechanism used by the Partner Chain, eg. `sudo`
231+
or `democracy` pallet.
232+
233+
### Wait for session change
234+
235+
Note that since a default value is used by the storage migration for the newly added keys, they will not be
236+
usable right away after the runtime upgrade. This fact makes it crucial that Beefy (or any similar feature
237+
being added) must not become active immediately after runtime upgrade. Luckyly, in this case Beefy pallet
238+
starts in a dormat state until it is activated.
239+
240+
Real Beefy keys of the committee members will be sourced from Cardano and registered in `pallet-session`
241+
after one or two session rotations after the runtime upgrade, depending on the exact timing. The keys
242+
should still be manually verified to have been updated by reading the `currentCommittee` storage of the
243+
session management pallet.
244+
245+
### Activating Beefy
246+
247+
Once the sessions rotate and the current committee has its Beefy keys correctly updated, the Beefy pallet
248+
can be activated by invoking the `beefy/setNewGenesis` extrinsic using the governance method employed
249+
by the Partner Chain in question. This extrinsic accepts an offset of blocks after which the Beefy pallet
250+
will become active. Once it happens, the block producers will start participating in Beefy consensus rounds.
251+
At this point, it can be verified that Beefy is working correctly by checking logs for lines reporting
252+
successful rounds, like the following one:
253+
```
254+
2025-11-27 12:42:02 🥩 Concluded mandatory round #1
255+
```

0 commit comments

Comments
 (0)