Skip to content

Commit 6ee6720

Browse files
committed
Suggestions from jstarry.
1 parent e5cb64d commit 6ee6720

File tree

1 file changed

+89
-63
lines changed

1 file changed

+89
-63
lines changed

proposals/0167-loader-v4.md

Lines changed: 89 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -98,41 +98,49 @@ explicitly before the actual upload starts.
9898

9999
The _current slot_ is as in the Clock sysvar.
100100

101+
Delay visibility: The changed version of a program only becomes available after
102+
the current slot ends. Thus, the first transaction in the next slot can invoke
103+
it.
104+
105+
Deployment cooldown: There can be at most one deployment per program in the
106+
same slot. Subsequent deployments have to wait for the next slot.
107+
101108
## Detailed Design
102109

103110
The feature gate must enable loader-v4 program management and execution.
104111

105-
### Owned Program Accounts
112+
### Program Account Layout
106113

107114
Accounts of programs owned by loader-v4 must have the following layout:
108115

109116
- Header (which is 48 bytes long):
110117
- `u64` status enum:
111-
- Enum variant `0u64`: `Invalid`, account was zero-filled externally
118+
- Enum variant `0u64`: `Uninitalized`, account was zero-filled externally
112119
- Enum variant `1u64`: `NeverBeenDeployed`, used as write buffer
113120
- Enum variant `2u64`: `Retracted`, program is in maintenance
114121
- Enum variant `3u64`: `Deployed`, program is ready to be executed
115122
- Enum variant `4u64`: `Finalized`, same as `Deployed`, but can not be
116123
modified anymore
117-
- `u64` Slot in which the program was last deployed, retracted or
118-
initialized.
124+
- `u64` Slot in which the program was last deployed.
119125
- `[u8; 32]` Authority address which can send program management
120126
instructions.
121127
- Body:
122128
- `[u8]` The programs executable file
123129

130+
### Program Account Header Verification
131+
124132
Verification the program account checks in the following order that:
125133

126134
- the owner of the program account is loader-v4,
127135
otherwise throw `InvalidAccountOwner`
128-
- the program account is at least as long enough for the header,
136+
- the program account is at least as long enough for the header (48 bytes),
129137
otherwise throw `AccountDataTooSmall`
130138
- the program account is writable, otherwise throw `InvalidArgument`
131139
- the provided authority (instruction account at index 1) signed,
132140
otherwise throw `MissingRequiredSignature`
133141
- the authority stored in the program account is the one provided,
134142
otherwise throw `IncorrectAuthority`
135-
- the status stored in the program account is not `Invalid`,
143+
- the status stored in the program account is not `Uninitalized`,
136144
otherwise throw `InvalidArgument`
137145
- the status stored in the program account is not `Finalized`,
138146
otherwise throw `Immutable`
@@ -153,58 +161,78 @@ failing any of the above checks must throw `UnsupportedProgramId`.
153161

154162
### Program Management Instructions
155163

164+
The loader-v4 intructions Deploy and Retract are not authorized in CPI.
165+
166+
#### Initialize
167+
168+
- Instruction accounts:
169+
- `[writable]` The account to initialize as program account.
170+
- `[signer]` The new authority of the program.
171+
- Instruction data:
172+
- Enum variant `0u32`
173+
- Behavior:
174+
- Charge 32 CUs
175+
- Check there are at least two instruction accounts,
176+
otherwise throw `NotEnoughAccountKeys`
177+
- Check that the owner of the program account is loader-v4,
178+
otherwise throw `InvalidAccountOwner`
179+
- Check that the program account is writable,
180+
otherwise throw `InvalidArgument`
181+
- Check that the new authority (instruction account at index 1) has signed,
182+
otherwise throw `MissingRequiredSignature`
183+
- Change the slot in the program account to the current slot
184+
- Change the status stored in the program account to `NeverBeenDeployed`
185+
- Copy the new authority address into the program account
186+
156187
#### SetAuthority
157188

158189
- Instruction accounts:
159190
- `[writable]` The program account to change the authority of.
160191
- `[signer]` The current authority of the program.
161-
- `[optional(signer)]` The new authority of the program.
192+
- `[signer]` The new authority of the program.
162193
- Instruction data:
163-
- Enum variant `7u32`
194+
- Enum variant `1u32`
164195
- Behavior:
165196
- Charge 32 CUs
166197
- Check there are at least three instruction accounts,
167198
otherwise throw `NotEnoughAccountKeys`
168-
- If this is an initialization (program account length is too short to
169-
contain the header):
170-
- the owner of the program account is loader-v4,
171-
otherwise throw `InvalidAccountOwner`
172-
- the program account is writable, otherwise throw `InvalidArgument`
173-
- Check that there are enough funds in the program account for rent
174-
exemption of the header,
175-
otherwise throw `InsufficientFunds`
176-
- otherwise, if this is not an initialization:
177-
- Verify the program account
178-
- Check that the new authority (instruction account at index 2)
179-
is either the system program or has signed,
180-
otherwise throw `MissingRequiredSignature`
181-
- If this is an initialization:
182-
- Set the length of the program account to the header size
183-
- Set the slot to zero, **not** the current slot
184-
- Set the status to `NeverBeenDeployed`
185-
- otherwise, if it is not an initialization:
186-
- Check that the authority stored in the program account is different
187-
from the one provided, otherwise throw `InvalidArgument`
199+
- Verify the program account header
200+
- Check that the new authority (instruction account at index 2) has signed,
201+
otherwise throw `MissingRequiredSignature`
202+
- Check that the current authority is different from the new authority,
203+
otherwise throw `InvalidArgument`
188204
- Copy the new authority address into the program account
189-
- If the the new authority is the system program:
190-
- Check that the status stored in the program account is `Deployed` or
191-
that the status is `Retracted` and the program length is 0 (header only),
192-
otherwise throw `InvalidArgument`
193-
- Change the status stored in the program account to `Finalized`
205+
206+
#### Finalize
207+
208+
- Instruction accounts:
209+
- `[writable]` The program account to finalize.
210+
- `[signer]` The current authority of the program.
211+
- Instruction data:
212+
- Enum variant `2u32`
213+
- Behavior:
214+
- Charge 32 CUs
215+
- Check there are at least two instruction accounts,
216+
otherwise throw `NotEnoughAccountKeys`
217+
- Verify the program account header
218+
- Check that the status stored in the program account is `Deployed` or
219+
that the status is `Retracted` and the program length is 0 (header only),
220+
otherwise throw `InvalidArgument`
221+
- Change the status stored in the program account to `Finalized`
194222

195223
#### SetProgramLength
196224

197225
- Instruction accounts:
198226
- `[writable]` The program account to change the size of.
199227
- `[signer]` The authority of the program.
200228
- Instruction data:
201-
- Enum variant `2u32`
229+
- Enum variant `3u32`
202230
- `u32` The new size after the operation.
203231
- Behavior:
204232
- Charge 32 + new_size_in_bytes / cpi_bytes_per_unit CUs
205233
- Check there are at least two instruction accounts,
206234
otherwise throw `NotEnoughAccountKeys`
207-
- Verify the program account
235+
- Verify the program account header
208236
- Check that the status stored in the program account is
209237
`NeverBeenDeployed` or `Retracted`,
210238
otherwise throw `InvalidArgument`
@@ -213,21 +241,23 @@ failing any of the above checks must throw `UnsupportedProgramId`.
213241
otherwise throw `InsufficientFunds`
214242
- Set the length of the program account to the requested new size plus
215243
the header size
244+
- Note: In CPI the maximum growth is limited to 10 KiB in ABI v1 and
245+
0 bytes in ABI v0.
216246

217247
#### Write
218248

219249
- Instruction accounts:
220250
- `[writable]` The program account to write to.
221251
- `[signer]` The authority of the program.
222252
- Instruction data:
223-
- Enum variant `0u32`
253+
- Enum variant `4u32`
224254
- `u32` Byte offset at which to write the given bytes
225255
- `[u8]` Chunk of the programs executable file
226256
- Behavior:
227257
- Charge 32 + chunk_length_in_bytes / cpi_bytes_per_unit CUs
228258
- Check there are at least two instruction accounts,
229259
otherwise throw `NotEnoughAccountKeys`
230-
- Verify the program account
260+
- Verify the program account header
231261
- Check the status stored in the program account is `NeverBeenDeployed` or
232262
`Retracted`,
233263
otherwise throw `InvalidArgument`
@@ -244,7 +274,7 @@ failing any of the above checks must throw `UnsupportedProgramId`.
244274
- `[signer]` The authority of the program.
245275
- `[]` The account to copy from.
246276
- Instruction data:
247-
- Enum variant `1u32`
277+
- Enum variant `5u32`
248278
- `u32` Byte offset at which to write
249279
- `u32` Byte offset at which to read
250280
- `u32` Length of the chunk to copy in bytes
@@ -254,17 +284,16 @@ failing any of the above checks must throw `UnsupportedProgramId`.
254284
otherwise throw `NotEnoughAccountKeys`
255285
- Check that program account and source account do not alias,
256286
otherwise throw `AccountBorrowFailed`
257-
- Verify the program account
287+
- Verify the program account header
258288
- Check the status stored in the program account is `NeverBeenDeployed` or
259289
`Retracted`,
260290
otherwise throw `InvalidArgument`
261-
- Check that the source account is owned by loader v2, v3 or v4,
262-
otherwise throw `InvalidArgument`
263-
- and look-up the source header size:
291+
- Check that the source accounts owner and look-up the source header size:
264292
- loader-v2: 0 bytes
265293
- loader-v3 buffer: 37 bytes
266294
- loader-v3 programdata: 45 bytes
267295
- loader-v4: 48 bytes
296+
- if none of the above matches throw `InvalidArgument`
268297
- Check that the source end offset (sum of source offset and length) does
269298
not exceed the maximum (source account length minus the source header size),
270299
otherwise throw `AccountDataTooSmall`
@@ -280,17 +309,18 @@ failing any of the above checks must throw `UnsupportedProgramId`.
280309
- `[writable]` The program account to deploy.
281310
- `[signer]` The authority of the program.
282311
- Instruction data:
283-
- Enum variant `5u32`
312+
- Enum variant `6u32`
284313
- Behavior:
285314
- Charge 32 CUs
286315
- Check there are at least two instruction accounts,
287316
otherwise throw `NotEnoughAccountKeys`
288-
- Verify the program account
289-
- Check that the slot stored in the program account is not the current
290-
(deployment cooldown), otherwise throw `InvalidArgument`
317+
- Verify the program account header
291318
- Check that the status stored in the program account is `NeverBeenDeployed`
292319
or `Retracted`
293320
otherwise throw `InvalidArgument`
321+
- If the status is `Retracted` then also check that the slot stored in the
322+
program account is not the current (deployment cooldown),
323+
otherwise throw `InvalidArgument`
294324
- Charge program_length_in_bytes / cpi_bytes_per_unit CUs
295325
- Check that the executable file stored in the program account passes
296326
executable verification
@@ -304,16 +334,16 @@ failing any of the above checks must throw `UnsupportedProgramId`.
304334
- `[writable]` The program account to retract.
305335
- `[signer]` The authority of the program.
306336
- Instruction data:
307-
- Enum variant `6u32`
337+
- Enum variant `7u32`
308338
- Behavior:
309339
- Charge 32 CUs
310340
- Check there are at least two instruction accounts,
311341
otherwise throw `NotEnoughAccountKeys`
312-
- Verify the program account
313-
- Check that the slot stored in the program account is not the current
314-
(deployment cooldown), otherwise throw `InvalidArgument`
342+
- Verify the program account header
315343
- Check that the status stored in the program account is `Deployed`,
316344
otherwise throw `InvalidArgument`
345+
- Check that the slot stored in the program account is not the current
346+
(deployment cooldown), otherwise throw `InvalidArgument`
317347
- Note: The slot is **not** set to the current slot to allow a
318348
retract-modify-redeploy-sequence within the same slot or even within the
319349
same transaction.
@@ -327,7 +357,7 @@ failing any of the above checks must throw `UnsupportedProgramId`.
327357
- `[signer]` The authority of the program.
328358
- `[writable]` The recipient account.
329359
- Instruction data:
330-
- Enum variant `3u32`
360+
- Enum variant `8u32`
331361
- Behavior:
332362
- Charge 32 CUs
333363
- Check there are at least three instruction accounts,
@@ -336,7 +366,7 @@ failing any of the above checks must throw `UnsupportedProgramId`.
336366
otherwise throw `AccountBorrowFailed`
337367
- Check that the recipient account is writable,
338368
otherwise throw `InvalidArgument`
339-
- Verify the program account
369+
- Verify the program account header, but skip the `Finalized` check
340370
- Transfer lamports which are not needed for rent exemption from the
341371
program account to the recipient account
342372

@@ -347,7 +377,7 @@ failing any of the above checks must throw `UnsupportedProgramId`.
347377
- `[signer]` The authority of the program.
348378
- `[writable]` The recipient account.
349379
- Instruction data:
350-
- Enum variant `4u32`
380+
- Enum variant `9u32`
351381
- Behavior:
352382
- Charge 32 CUs
353383
- Check there are at least three instruction accounts,
@@ -356,7 +386,7 @@ failing any of the above checks must throw `UnsupportedProgramId`.
356386
otherwise throw `AccountBorrowFailed`
357387
- Check that the recipient account is writable,
358388
otherwise throw `InvalidArgument`
359-
- Verify the program account
389+
- Verify the program account header
360390
- Check that the status stored in the program account is
361391
`NeverBeenDeployed` or `Retracted`,
362392
otherwise throw `InvalidArgument`
@@ -367,19 +397,19 @@ failing any of the above checks must throw `UnsupportedProgramId`.
367397

368398
#### Inital deployment
369399

400+
- Allocate an account to header plus ELF size
370401
- Assign account to loader-v4
371-
- SetAuthority to the new authority
372-
- SetProgramLength to ELF size
402+
- Initialize to the new authority
373403
- [Transaction boundary]
374404
- Write chunks repeatedly
375405
- [Transaction boundary]
376406
- Deploy
377407

378408
#### Redeployment
379409

410+
- Allocate an account to header plus ELF size
380411
- Assign buffer account to loader-v4
381-
- SetAuthority of the buffer to the new authority
382-
- SetProgramLength of buffer to ELF size
412+
- Initialize of the buffer to the new authority
383413
- [Transaction boundary]
384414
- Write chunks repeatedly
385415
- [Transaction boundary]
@@ -404,16 +434,12 @@ failing any of the above checks must throw `UnsupportedProgramId`.
404434
- Retract
405435
- SetProgramLength to 0
406436
- WithdrawLamports leaving enough for rent expemtion of the header
407-
- SetAuthority to the system program
437+
- Finalize
408438

409439
#### Transfer authority
410440

411441
- SetAuthority to the new authority
412442

413-
#### Finalize
414-
415-
- SetAuthority to the system program
416-
417443
## Impact
418444

419445
- This proposal covers all the use cases loader-v3 had but in a cleaner way and

0 commit comments

Comments
 (0)