Skip to content

SIMD-0167: Loader-v4 #167

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open

Conversation

Lichtso
Copy link
Contributor

@Lichtso Lichtso commented Aug 20, 2024

No description provided.

Copy link

@nickfrosty nickfrosty left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also noticed there are several typos on the word "throw"

Copy link

@topointon-jump topointon-jump left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice to see this well-written, well-specified SIMD!

Would be great to get more detail on the migration path from v3 to v4.


- 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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would the gifting work? Do we need to add a new instruction to the v3 loader? Will this upgrade mechanism be specified in a future SIMD?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see three options here:

  1. A migrate instruction for loader-v3 which the dApp devs trigger themselves
  2. A migrate instruction for loader-v3 which we the protocol engineers trigger
  3. A feature gate which scans the accounts DB and migrates all loader-v3 programs

I would prefer the second option as that allows us to keep the gathering of the loader-v3 program list and then slowly working through it off-chain and still makes sure that all loader-v3 programs get migrated.

Copy link
Contributor Author

@Lichtso Lichtso Jan 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a more detailed description of how this would work:
f2d4970

Copy link
Contributor

@buffalojoec buffalojoec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking great! I dropped a bunch of nits but overall I'm pretty happy with the architecture. Thanks for all of the back and forth!

The last piece I'm stuck on is the overloading of the withdraw instruction. I think we should bikeshed a bit about what something like an Erase instruction might look like.

Comment on lines +157 to +177
- Copy the chunk into the program account at the offset shifted by the
header size
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to have any limit on chunk size that's explicit in the program?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we still need to come up with CU costs for all instructions. And that would then implicitly limit the amount you can copy.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we still need to come up with CU costs for all instructions

If we go that way, I would like to have JMP32 and more registers in SBF so that we could improve codegen a bit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is about the loaders instructions, not SBPF instructions.

- Check there are at least three instruction accounts,
otherwise throw `NotEnoughAccountKeys`
- Check that program account and source account do not alias,
otherwise throw `AccountBorrowFailed`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, this error sounds like a bug. I think it's better to let the user know their inputs were bad.

Suggested change
otherwise throw `AccountBorrowFailed`
otherwise throw `InvalidArgument`

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what is generally emitted by the program runtime whenever borrows do alias. Thus it is consistent.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think it's misleading in this context. It's not a runtime violation, it's a program instruction specification violation, and the violation is literally within the arguments to the program. Furthermore, most devs are familiar with AccountBorrowFailed whenever they obtain a reference to input region data that may have been invalidated.

@Lichtso Lichtso force-pushed the loader-v4 branch 4 times, most recently from 8450981 to 39d9a44 Compare July 22, 2025 18:34
@Lichtso Lichtso force-pushed the loader-v4 branch 4 times, most recently from 1e1d81e to a41ad2b Compare July 23, 2025 16:58
Copy link
Contributor

@joncinque joncinque left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple of fly-by comments, looking great overall!

- Check that the status stored in the program account is `NeverBeenDeployed`
or `Retracted`
otherwise throw `InvalidArgument`
- Charge program_length_in_bytes CUs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accounts can be 10MB, but the max CUs for a transaction is 1.4M CUs. So all costs that use the program length will need to be reduced

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, should probably divide by cpi_bytes_per_unit

otherwise throw `InvalidArgument`
- Check that there are enough funds in the program account for rent
exemption of the new length, otherwise throw `InsufficientFunds`
- Set the length of the program account to the requested new size plus
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth specifying special behavior in CPI to limit the new size to size_at_start_of_top_level_instruction + 10kb?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point

Copy link
Contributor

@buffalojoec buffalojoec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting really close on my side. Based on our last discussion we wanted to add the following to SetAuthority:

  • If the program is Uninitialized will skip the existing authority check, set the new authority, and set the status to NeverBeenDeployed.
  • Programs that are Retracted can be finalized only if the program length is 0

- Enum variant `2u32`
- `u32` The new size after the operation.
- Behavior:
- Charge 32 + new_size_in_bytes / cpi_bytes_per_unit CUs
Copy link
Contributor

@buffalojoec buffalojoec Jul 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean "new size of the ELF"? So, if I grow a 1,000 byte ELF to 1,005, I have to pay CUs on 1,005 bytes? Why not just charge the delta?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is on purpose. The runtime has to memcpy all the existing data when reallocating a vector.

- Transfer lamports which are not needed for rent exemption from the
program account to the recipient account

#### WithdrawAllLamports
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really think this instruction should have a crystal-clear name that describes what it's going to do to your program. WithdrawAllLamports is super easy to conflate with WithdrawExcessLamports, and someone could end up destroying their program.

Suggested change
#### WithdrawAllLamports
#### Erase

Or, more explicit:

Suggested change
#### WithdrawAllLamports
#### EraseAndWithdrawAllLamports

- Instruction data:
- Enum variant `5u32`
- Behavior:
- Charge 32 CUs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very generous for ELF verification! Any thoughts on beefing this up a bit?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another CU charge happens later, a few lines down

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.