-
Notifications
You must be signed in to change notification settings - Fork 79
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
SIMD-0161: SBPF versioning and feature gating #161
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
--- | ||
simd: '0161' | ||
title: SBPF versioning and feature gating | ||
authors: | ||
- Alexander Meißner | ||
- Alessandro Decina | ||
category: Standard | ||
type: Core | ||
status: Draft | ||
created: 2024-07-15 | ||
--- | ||
|
||
## Summary | ||
|
||
An explicit versioning system for SBPF programs, that allows enabling or | ||
disabling features on a per-program basis. | ||
|
||
## Motivation | ||
|
||
SBPF has evolved over the years and will continue to evolve. Changes are | ||
necessary among other reasons to improve performance, address security concerns | ||
and provide new, better features to dapp developers. | ||
|
||
Today, the only way to introduce changes to the program runtime is via feature | ||
gates [link that explains what feature gates are]. For example we have used | ||
feature gates in the past to restrict new deployments of programs owned by | ||
deprecated loaders. Feature gates alone are not sufficient to evolve SBPF | ||
though - we are missing a mechanism to enable (or disable) specific features on | ||
a per-program basis. | ||
|
||
As an example, over two years ago we decided to change the way the stack works | ||
for SBPF programs - from allocating a fixed 4kB per function frame, to letting | ||
functions dynamically specify how much stack they need. This change was | ||
implemented in both the program runtime and the toolchain (LLVM), but as of | ||
today it has not yet been deployed, because it's essentially too hard to do so: | ||
upon executing a program, should the program runtime use the old or the new | ||
stack allocation strategy? | ||
|
||
We propose to introduce an explicit versioning scheme for SBPF programs: | ||
programs will encode which SBPF version they are compiled for; based on this | ||
version, the program runtime will alter its behavior. In order to prevent an | ||
"extension hell" it will not be possible to opt into specific changes via | ||
flags, instead an entire set of changes is reduced to a single SBPF version. | ||
|
||
## New Terminology | ||
|
||
SBPF version: the SBPF version number a program was compiled for. | ||
|
||
## Detailed Design | ||
|
||
Every program must signal which SBPF version it was compiled for via | ||
the `e_flags` field in the | ||
[ELF header](https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.eheader.html). | ||
Block explorers are recommended to display this SBPF version field for program | ||
accounts. | ||
|
||
For each SBPF version two feature gates will control its availability: | ||
|
||
- One to enable deployment and execution of that SBPF version, which includes | ||
disabling deployment (but not execution) of all earlier versions. | ||
- Another to first disincentivize (via CU costs) and later disable execution | ||
of that SBPF version, so that the runtime and virtual machine can reduce their | ||
complexity again. This feature gate can be shared by multiple SBPF versions, | ||
effectively deprecating larger blocks of versions in order to reduce the amount | ||
of redeployment required from dapp developers. | ||
|
||
### Example | ||
|
||
| SBPF version | becomes deployable and executable | ceases to be deployable | | ||
| ------------ | --------------------------------- | ----------------------- | | ||
| v1 | | Feature gate A | | ||
| v2 | Feature gate A | Feature gate B | | ||
Comment on lines
+69
to
+72
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this purely an example, or are we considering only one version to be able to deploy at a time? It might be helpful to include the number of simultaneous SBPF versions that the network will allow. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes the proposal right now says that there can only be one deployable version at a time (but many executable versions). See the discussion above. |
||
| v3 | Feature gate B | Feature gate C | | ||
| v4 | Feature gate C | Feature gate D | | ||
| v5 | Feature gate D | Feature gate E | | ||
| v6 | Feature gate E | Feature gate F | | ||
| v7 | Feature gate F | | | ||
|
||
| SBPF version | ceases to be executable | | ||
| ------------ | ----------------------- | | ||
| v1 | Feature gate G | | ||
| v2 | Feature gate G | | ||
| v3 | Feature gate G | | ||
| v4 | Feature gate H | | ||
| v5 | Feature gate H | | ||
| v6 | Feature gate H | | ||
| v7 | | | ||
|
||
## Alternatives Considered | ||
|
||
### Use the runtime global feature gating mechanism | ||
|
||
This would mean all programs need to be redeployed simultaneously at feature | ||
activation and that they would each require an alternative version to be | ||
prepared and uploaded to be switched to (redeployed) on feature activation. | ||
This would increase the complexity of program management in loaders and require | ||
dapp developers to double the locked tokens in their deployed programs. | ||
|
||
It also means that validator implementations would have to handle a massive | ||
amount of loading, parsing, relocation, verification and possibly compilation | ||
of programs in a single block. It took the Agave team two years to develop, | ||
implement, test and deploy this capability. It is desirable for other validator | ||
implementations to avoid having to do the same. | ||
|
||
### Coupling the feature gating to the loader, not the individual program accounts | ||
|
||
The version number could be implied by the loader a program was deployed in, | ||
effectively shifting the encoding from the program account content to the owner | ||
field. This would require a new loader address for each SBPF version, as the | ||
program management and execution logic could be shared for the most part. | ||
However, new loaders would necessitate a way to migrate programs between | ||
loaders upon redeployment. | ||
|
||
## Impact | ||
|
||
Active dapp developers who redeploy their programs regularly will (upon feature | ||
activation) be forced to also keep their toolchain up-to-date, which they most | ||
likely do anyway. | ||
|
||
Less active dapp developers who do not redeploy their programs will be nagged | ||
by their users to redeploy their programs once the deprecation CU cost ramps | ||
up. | ||
|
||
Finalized programs which simply can not be redeployed will instead have their | ||
user base slowly migrate their funds to alternative programs. | ||
|
||
Validator implementations will have to support multiple code paths in the time | ||
between the introduction feature activation and the fixed slot offset after the | ||
deprecation feature activation. | ||
|
||
## Security Considerations | ||
|
||
None. | ||
|
||
## Drawbacks | ||
|
||
Programs will break and if they are finalized their addresses and deployment | ||
cost will be burnt. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure that we need such a strict system. I think we could probably have several versions active and deployable at the same time, without forcing people to update toolchain and redeploy or pay extra costs.
Take the following examples:
dynamic frames: from the vm perspective, it is cheaper to use dynamic frames, because programs potentially page in less memory if an X-deep call stack fits in 1 page vs taking X pages because of fixed framing. We might want to push people to update to increase performance.
the
sub imm
operand swap change: this doesn't materially change anything. It's a nice thing for us to fix for aesthetic reasons, but it doesn't really change anything for developers.I think I'd prefer an ad-hoc system where depending on the impact of a new SBPF version, we decide whether and how to rug earlier versions (in practice I expect this to happen very rarely).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mandating that all deployments are targeting the newest version does not force anybody to redeploy. It only means that dapp devs have to keep their toolchain updated when they re/deploy. You are right in that it is not necessary to be this strict, but it has the nice effect of allowing us to get more testing exposure for the newest toolchain version.