Skip to content

Commit 05f0b13

Browse files
committed
Expands on how loader v3 to v4 migration works.
1 parent 814fc84 commit 05f0b13

File tree

1 file changed

+114
-37
lines changed

1 file changed

+114
-37
lines changed

proposals/0167-loader-v4.md

Lines changed: 114 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ category: Standard
77
type: Core
88
status: Review
99
created: 2024-08-15
10-
feature: TBD
10+
feature:
11+
- 8Cb77yHjPWe9wuWUfXeh6iszFGCDGNCoFk3tprViYHNm
12+
- EmhbpdVtZ2hWRGFWBDjn2i3SJD8Z36z4mpMcZJEnebnP
1113
---
1214

1315
## Summary
@@ -45,13 +47,15 @@ None.
4547

4648
## Detailed Design
4749

48-
The associated feature gate must:
50+
The feature gate `8Cb77yHjPWe9wuWUfXeh6iszFGCDGNCoFk3tprViYHNm` must:
4951

50-
- add loader-v4 to the write lock demotion exceptions
5152
- enable loader-v4 `LoaderV411111111111111111111111111111111111` program
52-
management and execution
53-
- simultaneously disable new deployments on loader-v3
54-
(`BPFLoaderUpgradeab1e11111111111111111111111`),
53+
management and execution.
54+
- enable the loader-v3 `BPFLoaderUpgradeab1e11111111111111111111111`
55+
instruction `UpgradeableLoaderInstruction::Migrate`.
56+
57+
An additional feature gate `EmhbpdVtZ2hWRGFWBDjn2i3SJD8Z36z4mpMcZJEnebnP`
58+
must disable new deployments on loader-v3,
5559
throwing `InvalidIstructionData` if `DeployWithMaxDataLen` is called.
5660

5761
### Owned Program Accounts
@@ -111,7 +115,7 @@ All program management instructions must cost 2000 CUs.
111115
- `[signer]` The authority of the program.
112116
- Instruction data:
113117
- Enum variant `0u32`
114-
- `u32` Offset at which to write the given bytes
118+
- `u32` Byte offset at which to write the given bytes
115119
- `[u8]` Chunk of the programs executable file
116120
- Behavior:
117121
- Check there are at least two instruction accounts,
@@ -125,14 +129,49 @@ All program management instructions must cost 2000 CUs.
125129
- Copy the chunk into the program account at the offset shifted by the
126130
header size
127131

132+
#### Copy
133+
134+
- Instruction accounts:
135+
- `[writable]` The program account to copy to.
136+
- `[signer]` The authority of the program.
137+
- `[]` The program(data) account to copy from.
138+
- Instruction data:
139+
- Enum variant `1u32`
140+
- `u32` Byte offset at which to write
141+
- `u32` Byte offset at which to read
142+
- `u32` Length of the chunk to copy in bytes
143+
- Behavior:
144+
- Check there are at least three instruction accounts,
145+
otherwise throw `NotEnoughAccountKeys`
146+
- Check that program account and source account do not alias,
147+
otherwise throw `AccountBorrowFailed`
148+
- Verify the program account
149+
- Check the status stored in the program account is retracted,
150+
otherwise throw `InvalidArgument`
151+
- Check that the source account is owned by loader v1, v2, v3 or v4,
152+
otherwise throw `InvalidArgument`
153+
- and look-up the source header size:
154+
- loader-v1: 0 bytes
155+
- loader-v2: 0 bytes
156+
- loader-v3: 45 bytes
157+
- loader-v4: 48 bytes
158+
- Check that the source end offset (sum of source offset and length) does
159+
not exceed the maximum (source account length minus the source header size),
160+
otherwise throw `AccountDataTooSmall`
161+
- Check that the destination end offset (sum of destination offset and
162+
length) does not exceed the maximum (program account length minus the loader-v4
163+
header size), otherwise throw `AccountDataTooSmall`
164+
- Copy the chunk between the program accounts at the offsets, each shifted by
165+
the header size of their loader (account owner) respectively
166+
128167
#### Truncate
129168

130169
- Instruction accounts:
131170
- `[(signer), writable]` The program account to change the size of.
132171
- `[signer]` The authority of the program.
133172
- `[writable]` Optional, the recipient account.
134173
- Instruction data:
135-
- Enum variant `1u32`
174+
- Enum variant `2u32`
136175
- `u32` The new size after the operation.
137176
- Behavior:
138177
- Check there are at least two instruction accounts,
@@ -177,7 +216,7 @@ All program management instructions must cost 2000 CUs.
177216
- `[writable]` Optional, an undeployed source program account to take data
178217
and lamports from.
179218
- Instruction data:
180-
- Enum variant `2u32`
219+
- Enum variant `3u32`
181220
- Behavior:
182221
- Check there are at least two instruction accounts,
183222
otherwise throw `NotEnoughAccountKeys`
@@ -212,7 +251,7 @@ All program management instructions must cost 2000 CUs.
212251
- `[writable]` The program account to retract.
213252
- `[signer]` The authority of the program.
214253
- Instruction data:
215-
- Enum variant `3u32`
254+
- Enum variant `4u32`
216255
- Behavior:
217256
- Check there are at least two instruction accounts,
218257
otherwise throw `NotEnoughAccountKeys`
@@ -232,7 +271,7 @@ All program management instructions must cost 2000 CUs.
232271
- `[signer]` The current authority of the program.
233272
- `[signer]` The new authority of the program.
234273
- Instruction data:
235-
- Enum variant `4u32`
274+
- Enum variant `5u32`
236275
- Behavior:
237276
- Check there are at least three instruction accounts,
238277
otherwise throw `NotEnoughAccountKeys`
@@ -250,7 +289,7 @@ All program management instructions must cost 2000 CUs.
250289
- `[signer]` The current authority of the program.
251290
- `[]` Optional, the reserved address for the next version of the program.
252291
- Instruction data:
253-
- Enum variant `5u32`
292+
- Enum variant `6u32`
254293
- Behavior:
255294
- Check there are at least three instruction accounts,
256295
otherwise throw `NotEnoughAccountKeys`
@@ -271,6 +310,50 @@ All program management instructions must cost 2000 CUs.
271310
the previous versions program account
272311
- Change the status stored in the program account to finalized
273312

313+
### Loader-v3 Migration Instruction
314+
315+
- Instruction accounts:
316+
- `[writable]` The program data account.
317+
- `[writable]` The program account.
318+
- `[signer]` The migration authority.
319+
- Instruction data:
320+
- Enum variant `8u32`
321+
- Behavior:
322+
- Check that there are at least three instruction accounts,
323+
otherwise throw `NotEnoughAccountKeys`
324+
- Check that the provided authority is the migration authority
325+
(pubkey is `3Scf35jMNk2xXBD6areNjgMtXgp5ZspDhms8vdcbzC42`),
326+
otherwise throw `IncorrectAuthority`
327+
- Check that the provided authority is a signer,
328+
otherwise throw `MissingRequiredSignature`
329+
- Check that the program data account is writable,
330+
otherwise throw `InvalidArgument`
331+
- Check that the program data account is not a buffer or a program account,
332+
meaning it can contain program data or be uninitialized / closed / empty,
333+
otherwise throw `InvalidArgument`
334+
- Check that the program data account was last modified before the current
335+
slot, otherwise throw `InvalidArgument`
336+
- Check that the program account is writable,
337+
otherwise throw `InvalidArgument`
338+
- Check that the program account is owned by loader-v3,
339+
otherwise throw `IncorrectProgramId`
340+
- Check that the program account points to the program data account,
341+
otherwise throw `InvalidArgument`
342+
- Clear the program account (setting its size to zero)
343+
- Transfer all funds from the program data account to the program account
344+
- Sets the owner of the program account to loader-v4
345+
- CPI loader-v4 `Truncate` the program account to the size of the program
346+
data account minus the loader-v3 header and use the migration authority
347+
- If the program data account was not closed (size was greater 0):
348+
- CPI loader-v4 `Copy` the program data account into the program account
349+
- CPI loader-v4 `Deploy` the program account
350+
- If the program data account was not finalized:
351+
- CPI loader-v4 `TransferAuthority` to the original upgrade authority
352+
- otherwise if the program data account was finalized:
353+
- CPI loader-v4 `Finalize` without a next version forwarding
354+
- The program data account still owned by loader-v3 is under-funded and will
355+
be automatically deleted by rent collection at the end of the transaction
356+
274357
## Impact
275358

276359
This proposal:
@@ -290,35 +373,29 @@ exception when shortening the length of program accounts or closing them.
290373
instruction, instead of having to build and redeploy an empty program.
291374
- properly alignes the executable file relative to the beginning of the
292375
account. In loader-v3 it is misaligned.
293-
- once all loader-v3 programs are migrated:
294-
- allows transaction account loading to be simplifed, because every program
295-
would load exactly one account, no need to load the proxy account to get to
296-
the actual program data (which is not listed in the transaction accounts).
297-
- allows the removal of the write lock demotion exception if loader-v3 is
298-
present in a transaction.
299-
- corrects the miscounting of the proxy account size towards the total
300-
transaction account loading limit.
376+
377+
Once loader-v4 is enabled and new programs can not be deployed on loader-v3
378+
anymore, the list of all loader-v3 programs becomes fixed and can be extracted
379+
from a snapshot. Using the added loader-v3 migration instruction and the global
380+
migration authority, the core protocol developers will then migrate all
381+
loader-v3 programs to loader-v4 programs, which once completed:
382+
383+
- allows transaction account loading to be simplifed, because every program
384+
would load exactly one account, no need to load the proxy account to get to
385+
the actual program data (which is not listed in the transaction accounts).
386+
- allows the removal of the write lock demotion exception if loader-v3 is
387+
present in a transaction.
388+
- corrects the miscounting of the program data account size towards the total
389+
transaction account loading limit.
390+
- allows dApp devs to resuscitate closed loader-v3 programs if they still
391+
control the program authority. This allows redeployment at the same address
392+
or completely closing the program account in order to retrieve the locked
393+
funds.
301394

302395
## Security Considerations
303396

304397
None.
305398

306399
## Backwards Compatibility
307400

308-
This proposal does not break any existing programs. However, dapp developers
309-
might want to profit from the new program mangement instructions without
310-
influencing their users work flows. To do so they would need a way to turn the
311-
program accounts of loader-v3 to program accounts of loader-v4, changing the
312-
account owner but keeping the program address. A potential issue is that the
313-
programdata header of loader-v3 is only 45 bytes long while loader-v4 takes 48
314-
bytes. An automatic mechanism in the program runtime (triggered by feature
315-
activation) could then perform the following steps per program:
316-
317-
- loader-v3 clears the program proxy account (setting its size to zero)
318-
- loader-v3 transfers all funds from the programdata to the proxy account
319-
- loader-v3 gifts the program proxy account to loader-v4
320-
- loader-v4 initializes it via `Truncate`
321-
- loader-v4 copies the data from the programdata account via `Write`
322-
- loader-v4 deploys it via `Deploy`
323-
- Optinally, loader-v4 finalizes it without a next version forwarding
324-
- loader-v3 closes the programdata account (setting its size to zero)
401+
None.

0 commit comments

Comments
 (0)