Skip to content

Commit 1f95ac3

Browse files
committed
Expands on how loader v3 to v4 migration works.
1 parent a4f4116 commit 1f95ac3

File tree

1 file changed

+90
-33
lines changed

1 file changed

+90
-33
lines changed

proposals/0167-loader-v4.md

Lines changed: 90 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,9 @@ The associated feature gate must:
5050
- add loader-v4 to the write lock demotion exceptions
5151
- enable loader-v4 `LoaderV411111111111111111111111111111111111` program
5252
management and execution
53-
- simultaneously disable new deployments on loader-v3
54-
(`BPFLoaderUpgradeab1e11111111111111111111111`),
53+
- disable new deployments on loader-v3
54+
`BPFLoaderUpgradeab1e11111111111111111111111`
55+
- enable the loader-v3 migration instruction
5556
throwing `InvalidIstructionData` if `DeployWithMaxDataLen` is called.
5657

5758
### Owned Program Accounts
@@ -111,7 +112,7 @@ All program management instructions must cost 2000 CUs.
111112
- `[signer]` The authority of the program.
112113
- Instruction data:
113114
- Enum variant `0u32`
114-
- `u32` Offset at which to write the given bytes
115+
- `u32` Byte offset at which to write the given bytes
115116
- `[u8]` Chunk of the programs executable file
116117
- Behavior:
117118
- Check there are at least two instruction accounts,
@@ -125,14 +126,49 @@ All program management instructions must cost 2000 CUs.
125126
- Copy the chunk into the program account at the offset shifted by the
126127
header size
127128

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

130166
- Instruction accounts:
131167
- `[(signer), writable]` The program account to change the size of.
132168
- `[signer]` The authority of the program.
133169
- `[writable]` Optional, the recipient account.
134170
- Instruction data:
135-
- Enum variant `1u32`
171+
- Enum variant `2u32`
136172
- `u32` The new size after the operation.
137173
- Behavior:
138174
- Check there are at least two instruction accounts,
@@ -177,7 +213,7 @@ All program management instructions must cost 2000 CUs.
177213
- `[writable]` Optional, an undeployed source program account to take data
178214
and lamports from.
179215
- Instruction data:
180-
- Enum variant `2u32`
216+
- Enum variant `3u32`
181217
- Behavior:
182218
- Check there are at least two instruction accounts,
183219
otherwise throw `NotEnoughAccountKeys`
@@ -212,7 +248,7 @@ All program management instructions must cost 2000 CUs.
212248
- `[writable]` The program account to retract.
213249
- `[signer]` The authority of the program.
214250
- Instruction data:
215-
- Enum variant `3u32`
251+
- Enum variant `4u32`
216252
- Behavior:
217253
- Check there are at least two instruction accounts,
218254
otherwise throw `NotEnoughAccountKeys`
@@ -232,7 +268,7 @@ All program management instructions must cost 2000 CUs.
232268
- `[signer]` The current authority of the program.
233269
- `[signer]` The new authority of the program.
234270
- Instruction data:
235-
- Enum variant `4u32`
271+
- Enum variant `5u32`
236272
- Behavior:
237273
- Check there are at least three instruction accounts,
238274
otherwise throw `NotEnoughAccountKeys`
@@ -250,7 +286,7 @@ All program management instructions must cost 2000 CUs.
250286
- `[signer]` The current authority of the program.
251287
- `[]` Optional, the reserved address for the next version of the program.
252288
- Instruction data:
253-
- Enum variant `5u32`
289+
- Enum variant `6u32`
254290
- Behavior:
255291
- Check there are at least three instruction accounts,
256292
otherwise throw `NotEnoughAccountKeys`
@@ -271,6 +307,33 @@ All program management instructions must cost 2000 CUs.
271307
the previous versions program account
272308
- Change the status stored in the program account to finalized
273309

310+
### Loader-v3 Migration Instruction
311+
312+
- Instruction accounts:
313+
- `[writable]` The program data account.
314+
- `[writable]` The program account.
315+
- `[signer]` The global migration authority.
316+
- Instruction data:
317+
- Enum variant `8u32`
318+
- Behavior:
319+
- Check that the provided authority is the global migration authority
320+
(pubkey is TBD),
321+
otherwise throw `IncorrectAuthority`
322+
- Check that the program account is a program and not a buffer account,
323+
otherwise throw `InvalidArgument`
324+
- Transfer all funds from the program data account to the program account
325+
- Clear the program account (setting its size to zero)
326+
- Sets the owner of the program account to loader-v4
327+
- CPI loader-v4 `Truncate` the program account to the size of the program
328+
data account and copy the program authority from the program data account
329+
- If the program data account was not closed (size was greater 0):
330+
- CPI loader-v4 `Copy` the program data account into the program account
331+
- CPI loader-v4 `Deploy` the program account
332+
- If the program data account was finalized:
333+
- CPI loader-v4 `Finalize` without a next version forwarding
334+
- The program data account still owned by loader-v3 is under-funded and will
335+
be automatically deleted by rent collection at the end of the transaction
336+
274337
## Impact
275338

276339
This proposal:
@@ -290,35 +353,29 @@ exception when shortening the length of program accounts or closing them.
290353
instruction, instead of having to build and redeploy an empty program.
291354
- properly alignes the executable file relative to the beginning of the
292355
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.
356+
357+
Once loader-v4 is enabled and new programs can not be deployed on loader-v3
358+
anymore, the list of all loader-v3 programs becomes fixed and can be extracted
359+
from a snapshot. Using the added loader-v3 migration instruction and the global
360+
migration authority, the core protocol developers will then migrate all
361+
loader-v3 programs to loader-v4 programs, which once completed:
362+
363+
- allows transaction account loading to be simplifed, because every program
364+
would load exactly one account, no need to load the proxy account to get to
365+
the actual program data (which is not listed in the transaction accounts).
366+
- allows the removal of the write lock demotion exception if loader-v3 is
367+
present in a transaction.
368+
- corrects the miscounting of the program data account size towards the total
369+
transaction account loading limit.
370+
- allows dApp devs to resuscitate closed loader-v3 programs if they still
371+
control the program authority. This allows redeployment at the same address
372+
or completely closing the program account in order to retrieve the locked
373+
funds.
301374

302375
## Security Considerations
303376

304377
None.
305378

306379
## Backwards Compatibility
307380

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)
381+
None.

0 commit comments

Comments
 (0)