Skip to content

Commit c40c3ef

Browse files
committed
First draft
1 parent 4b1eaaf commit c40c3ef

File tree

1 file changed

+290
-0
lines changed

1 file changed

+290
-0
lines changed

proposals/0167-loader-v4.md

Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
---
2+
simd: '0167'
3+
title: Loader-v4
4+
authors:
5+
- Alexander Meißner
6+
category: Standard
7+
type: Core
8+
status: Draft
9+
created: 2024-08-15
10+
feature: TBD
11+
---
12+
13+
## Summary
14+
15+
A new upgradeable loader which only requires a single account per program.
16+
17+
## Motivation
18+
19+
Loader-v3, which is currently the only deployable loader, requires two accounts
20+
per program. This was a workaround to circumvent the finality of the
21+
`is_executable` flag, which is removed in SIMD-0162. Consequentially, this
22+
setup of the program account being a proxy account, containing the address of
23+
the actual programdata account, is no longer necessary and should be removed.
24+
25+
Additionally, there currently is no complete specification of the loaders
26+
program management instructions. This proposal would thus fill that gap once
27+
loader-v4 goes into production.
28+
29+
See impact for further motivation.
30+
31+
## Alternatives Considered
32+
33+
A delay-visibility-free redeployment could be achieved by keeping the swap
34+
program around until the end of the slot. This would however mean that two
35+
accounts per program must be loaded until the dapp developer reclaims the
36+
second one. That would defy the purpose of this proposal which is to get rid
37+
of the proxy account.
38+
39+
## New Terminology
40+
41+
None.
42+
43+
## Detailed Design
44+
45+
`LoaderV411111111111111111111111111111111111` program management and execution
46+
must be enabled with the associated feature gate, which simultaneously disables
47+
new deployments on loader-v3 (`BPFLoaderUpgradeab1e11111111111111111111111`),
48+
throwing `InvalidIstructionData` if `DeployWithMaxDataLen` is called.
49+
50+
### Owned Program Accounts
51+
52+
Accounts of programs owned by loader-v4 must have the following layout:
53+
54+
- Header (which is 48 bytes long):
55+
- `u64` Slot in which the program was last deployed, retracted or
56+
initialized.
57+
- `[u8; 32]` Authority address which can send program management
58+
instructions.
59+
- `u64` status enum:
60+
- Enum variant `0u64`: Retracted, program is in maintenance
61+
- Enum variant `1u64`: Deployed, program is ready to be executed
62+
- Enum variant `2u64`: Finalized, same as `Deployed`, but can not be
63+
modified anymore
64+
- Body:
65+
- `[u8]` The programs executable file
66+
67+
Verification the program account checks in the following order that:
68+
69+
- the owner of the program account is loader-v4,
70+
otherwise throw `InvalidAccountOwner`
71+
- the program account is at least as long enough for the header,
72+
otherwise throw `AccountDataTooSmall`
73+
- the program account is writable, otherwise throw `InvalidArgument`
74+
- the provided authority (instruction account at index 1) signed,
75+
otherwise throw `MissingRequiredSignature`
76+
- the authority stored in the program account is the one provided,
77+
otherwise throw `IncorrectAuthority`
78+
- the status stored in the program account is not finalized,
79+
otherwise throw `Immutable`
80+
81+
### Execution / Invocation
82+
83+
Invoking programs owned by loader-v4 checks in the following order that:
84+
85+
- the owner of the program account is loader-v4,
86+
otherwise throw `UnsupportedProgramId`
87+
- the program account is at least as long enough for the header,
88+
otherwise throw `AccountDataTooSmall`
89+
- the status stored in the program account is not retracted,
90+
otherwise throw `UnsupportedProgramId`
91+
- the program account was not deployed recently (delay-visibility),
92+
otherwise throw `UnsupportedProgramId`
93+
- the executable file stored in the program account passes executable
94+
verification, otherwise throw `UnsupportedProgramId`
95+
96+
Otherwise the execution semantics stay the same as in loader-v2 and v3.
97+
Delay-visibility also stays the same as in loader-v3:
98+
99+
- Re/deployed programs act as closed until the end of the slot,
100+
only then becoming available for execution
101+
- The feature set that the executable file is verified against is not
102+
necessarily the current one, but the one of the epoch of the next slot
103+
104+
### Program Management Instructions
105+
106+
#### Write
107+
108+
- Instruction accounts:
109+
- `[writable]` The program account to write to.
110+
- `[signer]` The authority of the program.
111+
- Instruction data:
112+
- Enum variant `0u32`
113+
- `u32` Offset at which to write the given bytes
114+
- `[u8]` Chunk of the programs executable file
115+
- Behavior:
116+
- Check there are at least two instruction accounts,
117+
otherwise throw `NotEnoughAccountKeys`
118+
- Verify the program account
119+
- Check the status stored in the program account is retracted,
120+
otherwise throw `InvalidArgument`
121+
- Check that the end offset (sum of offset and length of the chunk) does
122+
not exceed the maximum (program account length minus the header size),
123+
otherwise throw `AccountDataTooSmall`
124+
- Copy the chunk into the program account at the offset shifted by the
125+
header size
126+
127+
#### Truncate
128+
129+
- Instruction accounts:
130+
- `[(signer), writable]` The program account to change the size of.
131+
- `[signer]` The authority of the program.
132+
- `[writable]` Optional, the recipient account.
133+
- Instruction data:
134+
- Enum variant `1u32`
135+
- `u32` The new size after the operation.
136+
- Behavior:
137+
- Check there are at least two instruction accounts,
138+
otherwise throw `NotEnoughAccountKeys`
139+
- If this is an initialization (program account length is too short to
140+
contain the header and the requested new size is greater 0):
141+
- the owner of the program account is loader-v4,
142+
otherwise throw `InvalidAccountOwner`
143+
- the program account is writable, otherwise throw `InvalidArgument`
144+
- the program account (instruction account at index 0) signed,
145+
otherwise throw `MissingRequiredSignature`
146+
- the provided authority (instruction account at index 1) signed,
147+
otherwise throw `MissingRequiredSignature`
148+
- If this is not an initialization:
149+
- Verify the program account
150+
- Check that the status stored in the program account is retracted,
151+
otherwise throw `InvalidArgument`
152+
- Check that there are enough funds in the program account for rent
153+
exemption, otherwise throw `InsufficientFunds`
154+
- If there are more than enough funds:
155+
- Check there are at least three instruction accounts,
156+
otherwise throw `NotEnoughAccountKeys`
157+
- Check that the recipient account (instruction account at index 2) is
158+
writable, otherwise throw `InvalidArgument`
159+
- Transfer the surplus from the program account to the recipient account
160+
- If the requested new size is zero:
161+
- Delete the entire program account, including the header
162+
- If the requested new size is greater than zero:
163+
- Set the length of the program account to the requested new size plus
164+
the header size
165+
- In case that this is an initialization, also initialize the header:
166+
- Set the `is_executable` flag to `true`
167+
- Set the slot to zero, **not** the current slot
168+
- Set the authority address (from the instruction account at index 1)
169+
- Set the status to retracted
170+
171+
#### Deploy
172+
173+
- Instruction accounts:
174+
- `[writable]` The program account to deploy.
175+
- `[signer]` The authority of the program.
176+
- `[writable]` Optional, an undeployed source program account to take data
177+
and lamports from.
178+
- Instruction data:
179+
- Enum variant `2u32`
180+
- Behavior:
181+
- Check there are at least two instruction accounts,
182+
otherwise throw `NotEnoughAccountKeys`
183+
- Verify the program account
184+
- Check that the deployment cooldown expired,
185+
otherwise throw `InvalidArgument`
186+
- Check that the status stored in the program account is retracted
187+
otherwise throw `InvalidArgument`
188+
- In case a source program was provided (instruction account at index 2):
189+
- Verify the source program account
190+
- Check that the status stored in the source program account is retracted,
191+
otherwise throw `InvalidArgument`
192+
- Check that the executable file stored in the source program account
193+
passes executable verification
194+
- Copy the entire source program account into the program account
195+
- Set the length of the source program account to zero
196+
- Transfer all funds of the source program account to the program
197+
account
198+
- In case no source program was provided:
199+
- Check that the executable file stored in the program account passes
200+
executable verification
201+
- Change the slot in the program account to the current slot
202+
- Change the status stored in the program account to deployed
203+
204+
#### Retract
205+
206+
- Instruction accounts:
207+
- `[writable]` The program account to retract.
208+
- `[signer]` The authority of the program.
209+
- Instruction data:
210+
- Enum variant `3u32`
211+
- Behavior:
212+
- Check there are at least two instruction accounts,
213+
otherwise throw `NotEnoughAccountKeys`
214+
- Verify the program account
215+
- Check that the deployment cooldown expired,
216+
otherwise throw `InvalidArgument`
217+
- Check that the status stored in the program account is deployed,
218+
otherwise throw `InvalidArgument`
219+
- Note: The slot is **not** set to the current slot to allow a
220+
retract-modify-redeploy-sequence within the same slot
221+
- Change the status stored in the program account to retracted
222+
223+
#### TransferAuthority
224+
225+
- Instruction accounts:
226+
- `[writable]` The program account to change the authority of.
227+
- `[signer]` The current authority of the program.
228+
- `[signer]` Optional, the new authority of the program.
229+
- Instruction data:
230+
- Enum variant `4u32`
231+
- Behavior:
232+
- Check there are at least two instruction accounts,
233+
otherwise throw `NotEnoughAccountKeys`
234+
- Verify the program account
235+
- In case a new authority was provided (instruction account at index 2):
236+
- Check that it signed as well,
237+
otherwise throw `MissingRequiredSignature`
238+
- Check that the authority stored in the program account is different
239+
from the one provided, otherwise throw `InvalidArgument`
240+
- Copy the new authority address into the program account
241+
- In case no new authority was provided:
242+
- Check that the status stored in the program account is deployed,
243+
otherwise throw `InvalidArgument`
244+
- Change the status stored in the program account to finalized
245+
246+
## Impact
247+
248+
This proposal:
249+
250+
- covers all the use cases loader-v3 had but in a cleaner way and comes with
251+
a specification.
252+
- makes deployment slightly cheaper for dapp developers as they would no longer
253+
have to burn funds for the rent exception of the proxy account.
254+
- provides an alternative redeployment path which does not require a big
255+
deposit of funds for rent exception during the upload.
256+
- enables dapp developers to withdrawl the surplus of funds required for rent
257+
exception when shortening the length of program accounts or closing them.
258+
- shortens the workflow of temporarily closing a program to a single
259+
instruction, instead of having to build and redeploy an empty program.
260+
- properly alignes the executable file relative to the beginning of the
261+
account. In loader-v3 it is misaligned.
262+
- allows transaction account loading to be simplifed once all loader-v3
263+
programs are migrated. That is because every program would load exactly one
264+
account and these accounts would no longer need to be inspected for redirection
265+
links.
266+
267+
## Security Considerations
268+
269+
None.
270+
271+
## Backwards Compatibility
272+
273+
This proposal does not break any existing programs. However, dapp developers
274+
might want to profit from the new program mangement instructions without
275+
influencing their users work flows. To do so they would need a way to turn the
276+
program accounts of loader-v3 to program accounts of loader-v4, changing the
277+
account owner but keeping the program address. A potential issue is that the
278+
programdata header of loader-v3 is only 45 bytes long while loader-v4 takes 48
279+
bytes. Such a loader migration would be possible because programdata accounts
280+
of both loaders are 48 bytes long. An automatic mechanism in the program
281+
runtime (triggered by feature activation) could then perform the following
282+
steps per program:
283+
284+
- loader-v3 clears the program proxy account (setting its size to zero)
285+
- loader-v3 transfers all funds from the programdata to the proxy account
286+
- loader-v3 gifts the program proxy account to loader-v4
287+
- loader-v4 initializes it via `Truncate`
288+
- loader-v4 copies the data from the programdata account via `Write`
289+
- loader-v4 deploys it via `Deploy`
290+
- loader-v3 closes the programdata account (setting its size to zero)

0 commit comments

Comments
 (0)