From 4f5de707a5d5d2a91dac4efe650c0073d205a4cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Mei=C3=9Fner?= Date: Mon, 30 Dec 2024 23:21:57 +0100 Subject: [PATCH] Expands on how loader v3 to v4 migration works. --- proposals/0167-loader-v4.md | 109 +++++++++++++++++++++++++----------- 1 file changed, 77 insertions(+), 32 deletions(-) diff --git a/proposals/0167-loader-v4.md b/proposals/0167-loader-v4.md index d57de874f..ae12d754d 100644 --- a/proposals/0167-loader-v4.md +++ b/proposals/0167-loader-v4.md @@ -50,8 +50,9 @@ The associated feature gate must: - add loader-v4 to the write lock demotion exceptions - enable loader-v4 `LoaderV411111111111111111111111111111111111` program management and execution -- simultaneously disable new deployments on loader-v3 -(`BPFLoaderUpgradeab1e11111111111111111111111`), +- disable new deployments on loader-v3 +`BPFLoaderUpgradeab1e11111111111111111111111` +- enable the loader-v3 migration instruction throwing `InvalidIstructionData` if `DeployWithMaxDataLen` is called. ### Owned Program Accounts @@ -125,6 +126,29 @@ All program management instructions must cost 2000 CUs. - Copy the chunk into the program account at the offset shifted by the header size +#### Copy + +- Instruction accounts: + - `[writable]` The program account to copy to. + - `[signer]` The authority of the program. + - `[]` The program account to copy from, which can be owned by any loader. +- Instruction data: + - Enum variant `1u32` + - `u32` Offset at which to write. + - `u32` Offset at which to read. + - `u32` Length of the chunk to copy in bytes. +- Behavior: + - Check there are at least three instruction accounts, + otherwise throw `NotEnoughAccountKeys` + - Verify the program account + - Check the status stored in the program account is retracted, + otherwise throw `InvalidArgument` + - Check that the end offset (sum of offset and length of the chunk) does + not exceed the maximum (program account length minus the header size), + otherwise throw `AccountDataTooSmall` + - Copy the chunk between the program accounts at the offsets, each shifted by + the header size of their loader respectively + #### Truncate - Instruction accounts: @@ -132,7 +156,7 @@ All program management instructions must cost 2000 CUs. - `[signer]` The authority of the program. - `[writable]` Optional, the recipient account. - Instruction data: - - Enum variant `1u32` + - Enum variant `2u32` - `u32` The new size after the operation. - Behavior: - Check there are at least two instruction accounts, @@ -177,7 +201,7 @@ All program management instructions must cost 2000 CUs. - `[writable]` Optional, an undeployed source program account to take data and lamports from. - Instruction data: - - Enum variant `2u32` + - Enum variant `3u32` - Behavior: - Check there are at least two instruction accounts, otherwise throw `NotEnoughAccountKeys` @@ -212,7 +236,7 @@ All program management instructions must cost 2000 CUs. - `[writable]` The program account to retract. - `[signer]` The authority of the program. - Instruction data: - - Enum variant `3u32` + - Enum variant `4u32` - Behavior: - Check there are at least two instruction accounts, otherwise throw `NotEnoughAccountKeys` @@ -232,7 +256,7 @@ All program management instructions must cost 2000 CUs. - `[signer]` The current authority of the program. - `[signer]` The new authority of the program. - Instruction data: - - Enum variant `4u32` + - Enum variant `5u32` - Behavior: - Check there are at least three instruction accounts, otherwise throw `NotEnoughAccountKeys` @@ -250,7 +274,7 @@ All program management instructions must cost 2000 CUs. - `[signer]` The current authority of the program. - `[]` Optional, the reserved address for the next version of the program. - Instruction data: - - Enum variant `5u32` + - Enum variant `6u32` - Behavior: - Check there are at least three instruction accounts, otherwise throw `NotEnoughAccountKeys` @@ -271,6 +295,33 @@ All program management instructions must cost 2000 CUs. the previous versions program account - Change the status stored in the program account to finalized +### Loader-v3 Migration Instruction + +- Instruction accounts: + - `[writable]` The program data account. + - `[writable]` The program account. + - `[signer]` The global migration authority. +- Instruction data: + - Enum variant `8u32` +- Behavior: + - Check that the provided authority is the global migration authority + (pubkey is TBD), + otherwise throw `IncorrectAuthority` + - Check that the program account is a program and not a buffer account, + otherwise throw `InvalidArgument` + - Transfer all funds from the program data account to the program account + - Clear the program account (setting its size to zero) + - Sets the owner of the program account to loader-v4 + - CPI loader-v4 `Truncate` the program account to the size of the program + data account and copy the program authority from the program data account + - If the program data account was not closed (size was greater 0): + - CPI loader-v4 `Copy` the program data account into the program account + - CPI loader-v4 `Deploy` the program account + - If the program data account was finalized: + - CPI loader-v4 `Finalize` without a next version forwarding + - The program data account still owned by loader-v3 is under-funded and will + be automatically deleted by rent collection at the end of the transaction + ## Impact This proposal: @@ -290,14 +341,24 @@ exception when shortening the length of program accounts or closing them. instruction, instead of having to build and redeploy an empty program. - properly alignes the executable file relative to the beginning of the account. In loader-v3 it is misaligned. -- once all loader-v3 programs are migrated: - - allows transaction account loading to be simplifed, because every program - would load exactly one account, no need to load the proxy account to get to - the actual program data (which is not listed in the transaction accounts). - - allows the removal of the write lock demotion exception if loader-v3 is - present in a transaction. - - corrects the miscounting of the proxy account size towards the total - transaction account loading limit. + +Once loader-v4 is enabled and new programs can not be deployed on loader-v3 +anymore, the list of all loader-v3 programs becomes fixed and can be extracted +from a snapshot. Using the added loader-v3 migration instruction and the global +migration authority, the core protocol developers will then migrate all +loader-v3 programs to loader-v4 programs, which once completed: + +- allows transaction account loading to be simplifed, because every program +would load exactly one account, no need to load the proxy account to get to +the actual program data (which is not listed in the transaction accounts). +- allows the removal of the write lock demotion exception if loader-v3 is +present in a transaction. +- corrects the miscounting of the program data account size towards the total +transaction account loading limit. +- allows dApp devs to resuscitate closed loader-v3 programs if they still +control the program authority. This allows redeployment at the same address +or completely closing the program account in order to retrieve the locked +funds. ## Security Considerations @@ -305,20 +366,4 @@ None. ## Backwards Compatibility -This proposal does not break any existing programs. However, dapp developers -might want to profit from the new program mangement instructions without -influencing their users work flows. To do so they would need a way to turn the -program accounts of loader-v3 to program accounts of loader-v4, changing the -account owner but keeping the program address. A potential issue is that the -programdata header of loader-v3 is only 45 bytes long while loader-v4 takes 48 -bytes. An automatic mechanism in the program runtime (triggered by feature -activation) could then perform the following steps per program: - -- loader-v3 clears the program proxy account (setting its size to zero) -- loader-v3 transfers all funds from the programdata to the proxy account -- loader-v3 gifts the program proxy account to loader-v4 -- loader-v4 initializes it via `Truncate` -- loader-v4 copies the data from the programdata account via `Write` -- loader-v4 deploys it via `Deploy` -- Optinally, loader-v4 finalizes it without a next version forwarding -- loader-v3 closes the programdata account (setting its size to zero) +None.