Skip to content

Commit 8d0ec51

Browse files
committed
First draft
1 parent 4b1eaaf commit 8d0ec51

File tree

1 file changed

+273
-0
lines changed

1 file changed

+273
-0
lines changed

proposals/0167-loader-v4.md

Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
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+
The loader-v4 program management and execution must be enabled with the
46+
associated feature gate, which simultaneously disables new deployments on
47+
loader-v3.
48+
49+
Loader-v4 has the on-chain address
50+
`LoaderV411111111111111111111111111111111111` and comes with following program
51+
management instructions:
52+
53+
- Write
54+
- Instruction accounts:
55+
- `[writable]` The program account to write to.
56+
- `[signer]` The authority of the program.
57+
- Instruction data:
58+
- Enum variant `0u32`
59+
- `u32` Offset at which to write the given bytes
60+
- `[u8]` Chunk of the programs executable file
61+
- Behavior:
62+
- Check there are at least two instruction accounts,
63+
otherwise throw `MissingAccount`
64+
- Verify the program account
65+
- Check the status stored in the program account is retracted,
66+
otherwise thorw `InvalidArgument`
67+
- Check that the end offset (sum of offset and length of the chunk) does
68+
not exceed the maximum (program account length minus the header size),
69+
otherwise throw `AccountDataTooSmall`
70+
- Copy the chunk into the program account at the offset shifted by the
71+
header size
72+
- Truncate
73+
- Instruction accounts:
74+
- `[(signer), writable]` The program account to change the size of.
75+
- `[signer]` The authority of the program.
76+
- `[writable]` Optional, the recipient account.
77+
- Instruction data:
78+
- Enum variant `1u32`
79+
- `u32` The new size after the operation.
80+
- Behavior:
81+
- Check there are at least two instruction accounts,
82+
otherwise throw `MissingAccount`
83+
- If this is an initialization (program account length is too short to
84+
contain the header and the requested new size is greater 0):
85+
- the owner of the program account is loader-v4,
86+
otherwise throw `InvalidAccountOwner`
87+
- the program account is writable, otherwise throw `InvalidArgument`
88+
- the program account (instruction account at index 0) signed,
89+
otherwise throw `MissingRequiredSignature`
90+
- the provided authority (instruction account at index 1) signed,
91+
otherwise throw `MissingRequiredSignature`
92+
- If this is not an initialization:
93+
- Verify the program account
94+
- Check that the status stored in the program account is retracted,
95+
otherwise throw `InvalidArgument`
96+
- Check that there are enough funds in the program account for rent
97+
exemption, otherwise thorw `InsufficientFunds`
98+
- If there are more than enough funds:
99+
- Check there are at least three instruction accounts,
100+
otherwise throw `MissingAccount`
101+
- Check that the recipient account (instruction account at index 2) is
102+
writable, otherwise throw `InvalidArgument`
103+
- Transfer the surplus from the program account to the recipient account
104+
- If the requested new size is zero:
105+
- Delete the entire program account, including the header
106+
- If the requested new size is greater than zero:
107+
- Set the length of the program account to the requested new size plus
108+
the header size
109+
- In case that this is an initialization, also initialize the header:
110+
- Set the slot to zero, **not** the current slot
111+
- Set the authority address (from the instruction account at index 1)
112+
- Set the status to retracted
113+
- Deploy
114+
- Instruction accounts:
115+
- `[writable]` The program account to deploy.
116+
- `[signer]` The authority of the program.
117+
- `[writable]` Optional, an undeployed source program account to take data and lamports from.
118+
- Instruction data:
119+
- Enum variant `2u32`
120+
- Behavior:
121+
- Check there are at least two instruction accounts,
122+
otherwise throw `MissingAccount`
123+
- Verify the program account
124+
- Check that the deployment cooldown expired,
125+
otherwise throw `InvalidArgument`
126+
- Check that the status stored in the program account is retracted
127+
otherwise throw `InvalidArgument`
128+
- In case a source program was provided (instruction account at index 2):
129+
- Verify the source program account
130+
- Check that the status stored in the source program account is retracted,
131+
otherwise throw `InvalidArgument`
132+
- Check that the executable file stored in the source program account
133+
passes executable verification
134+
- Copy the entire source program account into the program account
135+
- Set the length of the source program account to zero
136+
- Transfer all funds of the source program account to the program
137+
account
138+
- In case no source program was provided:
139+
- Check that the executable file stored in the program account passes
140+
executable verification
141+
- Change the slot in the program account to the current slot
142+
- Change the status stored in the program account to deployed
143+
- Retract
144+
- Instruction accounts:
145+
- `[writable]` The program account to retract.
146+
- `[signer]` The authority of the program.
147+
- Instruction data:
148+
- Enum variant `3u32`
149+
- Behavior:
150+
- Check there are at least two instruction accounts,
151+
otherwise throw `MissingAccount`
152+
- Verify the program account
153+
- Check that the deployment cooldown expired,
154+
otherwise throw `InvalidArgument`
155+
- Check that the status stored in the program account is deployed,
156+
otherwise throw `InvalidArgument`
157+
- Note: The slot is **not** set to the current slot to allow a
158+
retract-modify-redeploy-sequence within the same slot
159+
- Change the status stored in the program account to retracted
160+
- TransferAuthority
161+
- Instruction accounts:
162+
- `[writable]` The program account to change the authority of.
163+
- `[signer]` The current authority of the program.
164+
- `[signer]` Optional, the new authority of the program.
165+
- Instruction data:
166+
- Enum variant `4u32`
167+
- Behavior:
168+
- Check there are at least two instruction accounts,
169+
otherwise throw `MissingAccount`
170+
- Verify the program account
171+
- In case a new authority was provided (instruction account at index 2):
172+
- Check that it signed as well,
173+
otherwise throw `MissingRequiredSignature`
174+
- Check that the authority stored in the program account is different
175+
from the one provided, otherwise throw `InvalidArgument`
176+
- Copy the new authority address into the program account
177+
- In case no new authority was provided:
178+
- Check that the status stored in the program account is deployed,
179+
otherwise throw `InvalidArgument`
180+
- Change the status stored in the program account to finalized
181+
182+
Accounts of programs owned by loader-v4 must have the following layout:
183+
184+
- Header (which is 48 bytes long):
185+
- `u64` Slot in which the program was last deployed, retracted or
186+
initialized.
187+
- `[u8; 32]` Authority address which can send program management
188+
instructions.
189+
- `u64` status enum:
190+
- Enum variant `0u64`: Retracted, program is in maintenance
191+
- Enum variant `1u64`: Deployed, program is ready to be executed
192+
- Enum variant `2u64`: Finalized, same as `Deployed`, but can not be
193+
modified anymore
194+
- Body:
195+
- `[u8]` The programs executable file
196+
197+
Verification the program account checks in the following order that:
198+
199+
- the owner of the program account is loader-v4,
200+
otherwise throw `InvalidAccountOwner`
201+
- the program account is at least as long enough for the header,
202+
otherwise throw `AccountDataTooSmall`
203+
- the program account is writable, otherwise throw `InvalidArgument`
204+
- the provided authority (instruction account at index 1) signed,
205+
otherwise throw `MissingRequiredSignature`
206+
- the authority stored in the program account is the one provided,
207+
otherwise throw `IncorrectAuthority`
208+
- the status stored in the program account is not finalized,
209+
otherwise thorw `Immutable`
210+
211+
Invoking programs owned by loader-v4 checks in the following order that:
212+
213+
- the owner of the program account is loader-v4,
214+
otherwise throw `UnsupportedProgramId`
215+
- the program account is at least as long enough for the header,
216+
otherwise throw `AccountDataTooSmall`
217+
- the status stored in the program account is not retracted,
218+
otherwise thorw `UnsupportedProgramId`
219+
- the program account was not deployed recently (delay-visibility),
220+
otherwise thorw `UnsupportedProgramId`
221+
- the executable file stored in the program account passes executable
222+
verification, otherwise thorw `UnsupportedProgramId`
223+
224+
Otherwise the execution semantics stay the same as in loader-v2 and v3.
225+
Delay-visibility also stays the same as in loader-v3:
226+
227+
- Re/deployed programs act as closed until the end of the slot,
228+
only then becoming available for execution
229+
- The feature set that the executable file is verified against is not
230+
necessarily the current one, but the one of the epoch of the next slot
231+
232+
## Impact
233+
234+
This proposal:
235+
236+
- covers all the use cases loader-v3 had but in a cleaner way and comes with
237+
a specification.
238+
- makes deployment slightly cheaper for dapp developers as they would no longer
239+
have to burn funds for the rent exception of the proxy account.
240+
- provides an alternative redeployment path which does not require a big
241+
deposit of funds for rent exception during the upload.
242+
- enables dapp developers to withdrawl the surplus of funds required for rent
243+
exception when shortening the length of program accounts or closing them.
244+
- shortens the workflow of temporarily closing a program to a single
245+
instruction, instead of having to build and redeploy an empty program.
246+
- allows transaction account loading to be simplifed once all loader-v3
247+
programs are migrated. That is because every program would load exactly one
248+
account and these accounts would no longer need to be inspected for redirection
249+
links.
250+
251+
## Security Considerations
252+
253+
None.
254+
255+
## Backwards Compatibility
256+
257+
This proposal does not break any existing programs. However, dapp developers
258+
might want to profit from the new program mangement instructions without
259+
influencing their users work flows. To do so they would need a way to turn the
260+
program accounts of loader-v3 to program accounts of loader-v4, changing the
261+
account owner but keeping the program address. Such a loader migration would
262+
be possible because programdata accounts of both loaders are 48 bytes long.
263+
Either a new instruction in loader-v3 or an automatic mechanism in the program
264+
runtime (triggered by feature activation) could then perform the following
265+
steps per program:
266+
267+
- loader-v3 clears the program proxy account (setting its size to zero)
268+
- loader-v3 transfers all funds from the programdata to the proxy account
269+
- loader-v3 gifts the program proxy account to loader-v4
270+
- loader-v4 initializes it via `Truncate`
271+
- loader-v4 copies the data from the programdata account via `Write`
272+
- loader-v4 deploys it via `Deploy`
273+
- loader-v3 closes the programdata account (setting its size to zero)

0 commit comments

Comments
 (0)