From 0b554ede598a49dad39a9bff05a8d188bf94f05e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20=E5=88=A9=E8=BF=AA=E6=81=A9?= Date: Thu, 18 Dec 2025 15:51:12 +0800 Subject: [PATCH 01/16] Permissioned program extend --- 0431-permissioned-program-extend.md | 65 +++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 0431-permissioned-program-extend.md diff --git a/0431-permissioned-program-extend.md b/0431-permissioned-program-extend.md new file mode 100644 index 000000000..fa1702530 --- /dev/null +++ b/0431-permissioned-program-extend.md @@ -0,0 +1,65 @@ +--- +simd: '0431' +title: Permissioned Extend Program +authors: + - Dean Little (Blueshift) + - Joe Caulfield (Anza) +category: Standard +type: Core +status: Review +created: 2025-12-14 +feature: (fill in with feature key and github tracking issues once accepted) +supersedes: '0164' +--- + +## Summary + +This SIMD proposes restricting invocation of the extend program instruction in Loader V3 to the program's upgrade authority. + +## Motivation + +Currently, due to the permissionless nature of the extend program instruction +and some complexities surrounding the program cache, there is a DoS vector by +which anyone could disable a program for one slot by permissionlessly +extending its program data account. + +## New Terminology + +No new terminology is introduced by this proposal. + +## Detailed Design + +1. Add a check to the extend program instruction to ensure it is being invoked +by the current program upgrade authority. +2. Activate this change with a feature gate. +3. Remove feature gate after network activation. + +## Alternatives Considered + +- Allow DoS vectory to remain unresolved + +## Impact + +This proposal will remove the DoS vector for all deployed programs. Due to +constraints of ABI V1, in the case that a multisig upgrade authority wishes to +extend the program data account by greater than 10KiB, it will either need to +create multiple resize proposals, or atomically set its authority to a +top-level signer and reclaim it in the same transaction. + +## Security Considerations + +In the case of a multisig atomically setting its authority to a top-level +signer, it is important to introspect the transaction and ensure that it +consists of the following instructions: + +- Set upgrade authority to top-level signer +- Extend program data account in top-level instruction +- Set upgrade authority back to quorum + +If this order is not observed, it would be possible for a quorum to +accidentally lose its upgrade authority. + +## Backwards Compatibility + +This feature places additional restrictions upon an existing Loader V3 +instruction and is therefore not backwards compatible, necessitating a feature gate. \ No newline at end of file From 60d7d2e491886416c619656c6888b4fc553e7c68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20=E5=88=A9=E8=BF=AA=E6=81=A9?= <10921578+deanmlittle@users.noreply.github.com> Date: Thu, 18 Dec 2025 15:52:34 +0800 Subject: [PATCH 02/16] Rename 0431-permissioned-program-extend.md to 0431-permissioned-extend-program.md --- ...ned-program-extend.md => 0431-permissioned-extend-program.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename 0431-permissioned-program-extend.md => 0431-permissioned-extend-program.md (99%) diff --git a/0431-permissioned-program-extend.md b/0431-permissioned-extend-program.md similarity index 99% rename from 0431-permissioned-program-extend.md rename to 0431-permissioned-extend-program.md index fa1702530..33be90cf2 100644 --- a/0431-permissioned-program-extend.md +++ b/0431-permissioned-extend-program.md @@ -62,4 +62,4 @@ accidentally lose its upgrade authority. ## Backwards Compatibility This feature places additional restrictions upon an existing Loader V3 -instruction and is therefore not backwards compatible, necessitating a feature gate. \ No newline at end of file +instruction and is therefore not backwards compatible, necessitating a feature gate. From 4b82626686d5cfd4598ab9ccf878734f0a7bc54b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20=E5=88=A9=E8=BF=AA=E6=81=A9?= Date: Thu, 18 Dec 2025 15:53:21 +0800 Subject: [PATCH 03/16] lint --- 0431-permissioned-program-extend.md | 66 +++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 0431-permissioned-program-extend.md diff --git a/0431-permissioned-program-extend.md b/0431-permissioned-program-extend.md new file mode 100644 index 000000000..cf52262fa --- /dev/null +++ b/0431-permissioned-program-extend.md @@ -0,0 +1,66 @@ +--- +simd: '0431' +title: Permissioned Extend Program +authors: + - Dean Little (Blueshift) + - Joe Caulfield (Anza) +category: Standard +type: Core +status: Review +created: 2025-12-14 +feature: (fill in with feature key and github tracking issues once accepted) +supersedes: '0164' +--- + +## Summary + +This SIMD proposes restricting invocation of the extend program instruction in +Loader V3 to the program's upgrade authority. + +## Motivation + +Currently, due to the permissionless nature of the extend program instruction +and some complexities surrounding the program cache, there is a DoS vector by +which anyone could disable a program for one slot by permissionlessly +extending its program data account. + +## New Terminology + +No new terminology is introduced by this proposal. + +## Detailed Design + +1. Add a check to the extend program instruction to ensure it is being invoked +by the current program upgrade authority. +2. Activate this change with a feature gate. +3. Remove feature gate after network activation. + +## Alternatives Considered + +- Allow DoS vectory to remain unresolved + +## Impact + +This proposal will remove the DoS vector for all deployed programs. Due to +constraints of ABI V1, in the case that a multisig upgrade authority wishes to +extend the program data account by greater than 10KiB, it will either need to +create multiple resize proposals, or atomically set its authority to a +top-level signer and reclaim it in the same transaction. + +## Security Considerations + +In the case of a multisig atomically setting its authority to a top-level +signer, it is important to introspect the transaction and ensure that it +consists of the following instructions: + +- Set upgrade authority to top-level signer +- Extend program data account in top-level instruction +- Set upgrade authority back to quorum + +If this order is not observed, it would be possible for a quorum to +accidentally lose its upgrade authority. + +## Backwards Compatibility + +This feature places additional restrictions upon an existing Loader V3 +instruction and is therefore not backwards compatible, necessitating a feature gate. \ No newline at end of file From 76748d7b1d5f46dbdc40c6c2619690a6a52b22e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20=E5=88=A9=E8=BF=AA=E6=81=A9?= Date: Thu, 18 Dec 2025 15:53:55 +0800 Subject: [PATCH 04/16] lint --- 0431-permissioned-extend-program.md | 3 +- 0431-permissioned-program-extend.md | 66 ----------------------------- 2 files changed, 2 insertions(+), 67 deletions(-) delete mode 100644 0431-permissioned-program-extend.md diff --git a/0431-permissioned-extend-program.md b/0431-permissioned-extend-program.md index 33be90cf2..4d47dca18 100644 --- a/0431-permissioned-extend-program.md +++ b/0431-permissioned-extend-program.md @@ -14,7 +14,8 @@ supersedes: '0164' ## Summary -This SIMD proposes restricting invocation of the extend program instruction in Loader V3 to the program's upgrade authority. +This SIMD proposes restricting invocation of the extend program instruction in +Loader V3 to the program's upgrade authority. ## Motivation diff --git a/0431-permissioned-program-extend.md b/0431-permissioned-program-extend.md deleted file mode 100644 index cf52262fa..000000000 --- a/0431-permissioned-program-extend.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -simd: '0431' -title: Permissioned Extend Program -authors: - - Dean Little (Blueshift) - - Joe Caulfield (Anza) -category: Standard -type: Core -status: Review -created: 2025-12-14 -feature: (fill in with feature key and github tracking issues once accepted) -supersedes: '0164' ---- - -## Summary - -This SIMD proposes restricting invocation of the extend program instruction in -Loader V3 to the program's upgrade authority. - -## Motivation - -Currently, due to the permissionless nature of the extend program instruction -and some complexities surrounding the program cache, there is a DoS vector by -which anyone could disable a program for one slot by permissionlessly -extending its program data account. - -## New Terminology - -No new terminology is introduced by this proposal. - -## Detailed Design - -1. Add a check to the extend program instruction to ensure it is being invoked -by the current program upgrade authority. -2. Activate this change with a feature gate. -3. Remove feature gate after network activation. - -## Alternatives Considered - -- Allow DoS vectory to remain unresolved - -## Impact - -This proposal will remove the DoS vector for all deployed programs. Due to -constraints of ABI V1, in the case that a multisig upgrade authority wishes to -extend the program data account by greater than 10KiB, it will either need to -create multiple resize proposals, or atomically set its authority to a -top-level signer and reclaim it in the same transaction. - -## Security Considerations - -In the case of a multisig atomically setting its authority to a top-level -signer, it is important to introspect the transaction and ensure that it -consists of the following instructions: - -- Set upgrade authority to top-level signer -- Extend program data account in top-level instruction -- Set upgrade authority back to quorum - -If this order is not observed, it would be possible for a quorum to -accidentally lose its upgrade authority. - -## Backwards Compatibility - -This feature places additional restrictions upon an existing Loader V3 -instruction and is therefore not backwards compatible, necessitating a feature gate. \ No newline at end of file From 8c56c34718602ccaca298a98b17fc2d871ec3a58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20=E5=88=A9=E8=BF=AA=E6=81=A9?= Date: Thu, 18 Dec 2025 16:19:59 +0800 Subject: [PATCH 05/16] incrrect directory --- .../0431-permissioned-extend-program.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename 0431-permissioned-extend-program.md => proposals/0431-permissioned-extend-program.md (100%) diff --git a/0431-permissioned-extend-program.md b/proposals/0431-permissioned-extend-program.md similarity index 100% rename from 0431-permissioned-extend-program.md rename to proposals/0431-permissioned-extend-program.md From 52ce763050dd955b97b3d7d6c8905e4c5951284e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20=E5=88=A9=E8=BF=AA=E6=81=A9?= <10921578+deanmlittle@users.noreply.github.com> Date: Tue, 20 Jan 2026 16:26:17 +0800 Subject: [PATCH 06/16] Update proposals/0431-permissioned-extend-program.md --- proposals/0431-permissioned-extend-program.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/proposals/0431-permissioned-extend-program.md b/proposals/0431-permissioned-extend-program.md index 4d47dca18..d4b657f1c 100644 --- a/proposals/0431-permissioned-extend-program.md +++ b/proposals/0431-permissioned-extend-program.md @@ -45,7 +45,8 @@ This proposal will remove the DoS vector for all deployed programs. Due to constraints of ABI V1, in the case that a multisig upgrade authority wishes to extend the program data account by greater than 10KiB, it will either need to create multiple resize proposals, or atomically set its authority to a -top-level signer and reclaim it in the same transaction. +top-level signer and reclaim it in the same transaction. The `ExtendProgram` +instruction will now also be invokable by CPI. ## Security Considerations From ec1b9aab7047eaf50abaef61d0fe6540ece2a3db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20=E5=88=A9=E8=BF=AA=E6=81=A9?= <10921578+deanmlittle@users.noreply.github.com> Date: Tue, 20 Jan 2026 16:28:13 +0800 Subject: [PATCH 07/16] Update proposals/0431-permissioned-extend-program.md --- proposals/0431-permissioned-extend-program.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/proposals/0431-permissioned-extend-program.md b/proposals/0431-permissioned-extend-program.md index d4b657f1c..092a2c08b 100644 --- a/proposals/0431-permissioned-extend-program.md +++ b/proposals/0431-permissioned-extend-program.md @@ -15,7 +15,8 @@ supersedes: '0164' ## Summary This SIMD proposes restricting invocation of the extend program instruction in -Loader V3 to the program's upgrade authority. +Loader V3 to the program's upgrade authority, along with lifting the current +restriction preventing it from being invoked via CPI. ## Motivation From a6e8efa752b3e4dd2e59af5b982730802156da8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20=E5=88=A9=E8=BF=AA=E6=81=A9?= <10921578+deanmlittle@users.noreply.github.com> Date: Tue, 20 Jan 2026 16:34:32 +0800 Subject: [PATCH 08/16] Update proposals/0431-permissioned-extend-program.md --- proposals/0431-permissioned-extend-program.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/proposals/0431-permissioned-extend-program.md b/proposals/0431-permissioned-extend-program.md index 092a2c08b..ec40c55ca 100644 --- a/proposals/0431-permissioned-extend-program.md +++ b/proposals/0431-permissioned-extend-program.md @@ -23,7 +23,10 @@ restriction preventing it from being invoked via CPI. Currently, due to the permissionless nature of the extend program instruction and some complexities surrounding the program cache, there is a DoS vector by which anyone could disable a program for one slot by permissionlessly -extending its program data account. +extending its program data account. Thus the motivation of this SIMD is to both +resolve the DoS vector by restricting access to this instruction to the program's +upgrade authority, whilst improving the devex of this new restriction by allowing +ExtendProgram to be invoked via CPI. ## New Terminology From 04ae5b1cda8873cfbe3251cb6f744af8e49ecf3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20=E5=88=A9=E8=BF=AA=E6=81=A9?= <10921578+deanmlittle@users.noreply.github.com> Date: Tue, 20 Jan 2026 16:36:48 +0800 Subject: [PATCH 09/16] Update proposals/0431-permissioned-extend-program.md --- proposals/0431-permissioned-extend-program.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/0431-permissioned-extend-program.md b/proposals/0431-permissioned-extend-program.md index ec40c55ca..b86cb7459 100644 --- a/proposals/0431-permissioned-extend-program.md +++ b/proposals/0431-permissioned-extend-program.md @@ -35,9 +35,9 @@ No new terminology is introduced by this proposal. ## Detailed Design 1. Add a check to the extend program instruction to ensure it is being invoked -by the current program upgrade authority. -2. Activate this change with a feature gate. -3. Remove feature gate after network activation. +by the program upgrade authority. +2. Remove the restriction in extend program preventing invocation via CPI. +3. Activate both changes via feature gate. ## Alternatives Considered From c4aa022af80d7e9cacbb6e8096cf32bf40ed83f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20=E5=88=A9=E8=BF=AA=E6=81=A9?= <10921578+deanmlittle@users.noreply.github.com> Date: Tue, 20 Jan 2026 16:43:22 +0800 Subject: [PATCH 10/16] Update proposals/0431-permissioned-extend-program.md --- proposals/0431-permissioned-extend-program.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/0431-permissioned-extend-program.md b/proposals/0431-permissioned-extend-program.md index b86cb7459..f8a36db7c 100644 --- a/proposals/0431-permissioned-extend-program.md +++ b/proposals/0431-permissioned-extend-program.md @@ -24,9 +24,9 @@ Currently, due to the permissionless nature of the extend program instruction and some complexities surrounding the program cache, there is a DoS vector by which anyone could disable a program for one slot by permissionlessly extending its program data account. Thus the motivation of this SIMD is to both -resolve the DoS vector by restricting access to this instruction to the program's -upgrade authority, whilst improving the devex of this new restriction by allowing -ExtendProgram to be invoked via CPI. +resolve the DoS vector by restricting access to this instruction to the +program's upgrade authority, whilst improving the devex of this new +restriction by allowing ExtendProgram to be invoked via CPI. ## New Terminology From ebc7a2e6cae75746215c64ab52f9bc3e71fcf871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20=E5=88=A9=E8=BF=AA=E6=81=A9?= <10921578+deanmlittle@users.noreply.github.com> Date: Tue, 20 Jan 2026 17:59:43 +0800 Subject: [PATCH 11/16] typo --- proposals/0431-permissioned-extend-program.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0431-permissioned-extend-program.md b/proposals/0431-permissioned-extend-program.md index f8a36db7c..5c1c1a8a5 100644 --- a/proposals/0431-permissioned-extend-program.md +++ b/proposals/0431-permissioned-extend-program.md @@ -41,7 +41,7 @@ by the program upgrade authority. ## Alternatives Considered -- Allow DoS vectory to remain unresolved +- Allow DoS vector to remain unresolved ## Impact From d84354f055fd3efb3b88cc0c095a4c1b3256df18 Mon Sep 17 00:00:00 2001 From: Joseph Caulfield Date: Tue, 20 Jan 2026 10:11:40 +0000 Subject: [PATCH 12/16] flesh out detailed design --- proposals/0431-permissioned-extend-program.md | 43 +++++++++++++++++-- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/proposals/0431-permissioned-extend-program.md b/proposals/0431-permissioned-extend-program.md index f8a36db7c..272836354 100644 --- a/proposals/0431-permissioned-extend-program.md +++ b/proposals/0431-permissioned-extend-program.md @@ -34,10 +34,45 @@ No new terminology is introduced by this proposal. ## Detailed Design -1. Add a check to the extend program instruction to ensure it is being invoked -by the program upgrade authority. -2. Remove the restriction in extend program preventing invocation via CPI. -3. Activate both changes via feature gate. +The `ExtendProgram` instruction will require the program's upgrade authority as +a signer and it will be available for invocation via CPI. + +### Changes to Required Accounts + +The current `ExtendProgram` instruction expects the following accounts: + +``` +0. [w] ProgramData account +1. [w] Program account +2. [ ] System program, optional +3. [ws] Payer, optional +``` + +After this proposal's feature gate is activated, the instruction will expect: + +``` +0. [w] ProgramData account +1. [w] Program account +2. [s] Upgrade authority // New +3. [ ] System program, optional +4. [ws] Payer, optional +``` + +### Control Flow + +The instruction will verify: + +1. The program has an upgrade authority set (i.e., is not immutable). If not, + return `Immutable`. +2. The provided authority matches the program's stored upgrade authority. If + not, return `IncorrectAuthority`. +3. The authority account is a signer. If not, return + `MissingRequiredSignature`. + +### CPI Restriction Removal + +The current restriction preventing `ExtendProgram` from being invoked via CPI +will be removed. The instruction will be fully available for CPI. ## Alternatives Considered From 740e3abc928009575eb5dd5d4e579f8069806dcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20=E5=88=A9=E8=BF=AA=E6=81=A9?= <10921578+deanmlittle@users.noreply.github.com> Date: Tue, 20 Jan 2026 20:41:23 +0800 Subject: [PATCH 13/16] Update security considerations and alternatives section Clarify security considerations and alternatives in the proposal. --- proposals/0431-permissioned-extend-program.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/proposals/0431-permissioned-extend-program.md b/proposals/0431-permissioned-extend-program.md index 1f1afb769..885e3b856 100644 --- a/proposals/0431-permissioned-extend-program.md +++ b/proposals/0431-permissioned-extend-program.md @@ -77,6 +77,8 @@ will be removed. The instruction will be fully available for CPI. ## Alternatives Considered - Allow DoS vector to remain unresolved +- Retain existing account ordering by combining payer and authority into a + single mandatory account ## Impact @@ -91,13 +93,13 @@ instruction will now also be invokable by CPI. In the case of a multisig atomically setting its authority to a top-level signer, it is important to introspect the transaction and ensure that it -consists of the following instructions: +executes the following behavior: - Set upgrade authority to top-level signer - Extend program data account in top-level instruction - Set upgrade authority back to quorum -If this order is not observed, it would be possible for a quorum to +If this behavior is not observed, it would be possible for a quorum to accidentally lose its upgrade authority. ## Backwards Compatibility From 19d657a0b7ee26b6f62d0437e582a01b7344d8c4 Mon Sep 17 00:00:00 2001 From: Joseph Caulfield Date: Thu, 5 Mar 2026 08:54:33 +0000 Subject: [PATCH 14/16] SIMD-0431: revise to use minimum extension size approach --- proposals/0431-permissioned-extend-program.md | 167 ++++++++++++------ 1 file changed, 113 insertions(+), 54 deletions(-) diff --git a/proposals/0431-permissioned-extend-program.md b/proposals/0431-permissioned-extend-program.md index 885e3b856..1fc26290b 100644 --- a/proposals/0431-permissioned-extend-program.md +++ b/proposals/0431-permissioned-extend-program.md @@ -1,6 +1,6 @@ --- simd: '0431' -title: Permissioned Extend Program +title: 'Loader V3: Minimum Extend Program Size' authors: - Dean Little (Blueshift) - Joe Caulfield (Anza) @@ -14,19 +14,44 @@ supersedes: '0164' ## Summary -This SIMD proposes restricting invocation of the extend program instruction in -Loader V3 to the program's upgrade authority, along with lifting the current -restriction preventing it from being invoked via CPI. +Enforce a minimum extension size of 10,240 bytes (10 KiB) on the +`ExtendProgram` instruction in Loader V3, mitigating the existing +denial-of-service vector through economic deterrence while preserving the +instruction's permissionless nature. ## Motivation -Currently, due to the permissionless nature of the extend program instruction -and some complexities surrounding the program cache, there is a DoS vector by -which anyone could disable a program for one slot by permissionlessly -extending its program data account. Thus the motivation of this SIMD is to both -resolve the DoS vector by restricting access to this instruction to the -program's upgrade authority, whilst improving the devex of this new -restriction by allowing ExtendProgram to be invoked via CPI. +The `ExtendProgram` instruction is currently permissionless — anyone can extend +any upgradeable program's data account by as little as 1 byte. Due to +complexities surrounding the program cache, each invocation of `ExtendProgram` +invalidates the program's cache entry for the current slot, effectively +disabling the program for one slot. Combined with the negligible cost of a +1-byte extension, this creates a cheap denial-of-service vector. + +SIMD-0164 and earlier revisions of this SIMD attempted to fix this by making +`ExtendProgram` permissioned, requiring the upgrade authority as a signer. +While this provides absolute DoS protection, it breaks several important +workflows: + +- **Multisig PDA authorities** cannot sign top-level instructions. With a CPI + resize cap of 10 KiB per instruction, large extensions require multiple + proposals or a clunky authority-shuffle pattern. +- **Self-upgrading programs** that manage their own upgrade authority as a PDA + would lose the ability to extend themselves. + +SIMD-0164 was never approved, and the general sentiment favored a more +flexible solution that preserves the permissionless nature of `ExtendProgram`. +As [suggested by jstarry][jstarry_suggestion], a minimum extension size achieves +this. + +[jstarry_suggestion]: https://github.com/solana-foundation/solana-improvement-documents/pull/164#issuecomment-3138353713 + +A minimum extension size solves the DoS vector economically instead: at 10 +KiB, each extension costs the attacker approximately 0.072 SOL in rent-exempt +lamports, which are irrecoverably donated to the victim's program data account. +Ten successive attacks cost the attacker 0.72 SOL while only benefiting the +program owner. This makes sustained griefing economically irrational without +breaking any existing workflows. ## New Terminology @@ -34,12 +59,12 @@ No new terminology is introduced by this proposal. ## Detailed Design -The `ExtendProgram` instruction will require the program's upgrade authority as -a signer and it will be available for invocation via CPI. +After this proposal's feature gate is activated, the `ExtendProgram` +instruction will enforce a minimum extension size of 10,240 bytes (10 KiB). -### Changes to Required Accounts +### Instruction Accounts -The current `ExtendProgram` instruction expects the following accounts: +The instruction accounts remain unchanged: ``` 0. [w] ProgramData account @@ -48,61 +73,95 @@ The current `ExtendProgram` instruction expects the following accounts: 3. [ws] Payer, optional ``` -After this proposal's feature gate is activated, the instruction will expect: - -``` -0. [w] ProgramData account -1. [w] Program account -2. [s] Upgrade authority // New -3. [ ] System program, optional -4. [ws] Payer, optional -``` - ### Control Flow -The instruction will verify: +The instruction will verify the following, in addition to all existing checks: + +1. The requested extension size is at least 10,240 bytes. If not, return + `InvalidArgument`. -1. The program has an upgrade authority set (i.e., is not immutable). If not, - return `Immutable`. -2. The provided authority matches the program's stored upgrade authority. If - not, return `IncorrectAuthority`. -3. The authority account is a signer. If not, return - `MissingRequiredSignature`. +All other existing checks (program ownership, account state, rent-exempt +balance) remain unchanged. -### CPI Restriction Removal +### CPI Restriction -The current restriction preventing `ExtendProgram` from being invoked via CPI -will be removed. The instruction will be fully available for CPI. +The existing restriction preventing `ExtendProgram` from being invoked via CPI +is not modified by this proposal. ## Alternatives Considered -- Allow DoS vector to remain unresolved -- Retain existing account ordering by combining payer and authority into a - single mandatory account +### Permissioned ExtendProgram (SIMD-0164) + +Require the upgrade authority as a signer and lift the CPI restriction. This +provides absolute DoS protection but breaks multisig PDA workflows, +self-upgrading programs, and any third-party tooling that extends programs on +behalf of owners. + +### Disable ExtendProgram entirely + +If `ExtendProgram` were made permissioned, there would be little reason for it +to exist as a standalone instruction — resizing could instead be folded into +`Upgrade`. However, keeping `ExtendProgram` permissionless avoids nasty +workarounds for multisigs and self-upgrading programs: anyone can crank a +top-level extend to prime up space before a multisig upgrade, without needing +the multisig authority to sign. It also sidesteps the CPI 10 KiB +CPI growth limit that would otherwise cap how much a program can extend itself +in a single call. + +### Smaller minimum extension size + +A 1 KiB minimum costs only ~0.008 SOL per attack — too cheap to deter +sustained griefing. + +### Larger minimum extension size + +Minimums of 20 KiB or 50 KiB provide stronger deterrence but +disproportionately affect small programs. A survey of 14,822 mainnet-beta +programs shows the following size distribution: + +| Size Range | Programs | Share | +|--------------|----------|--------| +| 0 – 10 KiB | 149 | 1.0% | +| 10 – 50 KiB | 843 | 5.7% | +| 50 – 200 KiB| 2,066 | 13.9% | +| 200 – 500 KiB| 6,058 | 40.9% | +| 500+ KiB | 5,706 | 38.5% | + +At 10 KiB, only 1.0% of programs are smaller than the minimum extension size, +and over 93% of programs are larger than 50 KiB — well above the proposed +minimum. ## Impact -This proposal will remove the DoS vector for all deployed programs. Due to -constraints of ABI V1, in the case that a multisig upgrade authority wishes to -extend the program data account by greater than 10KiB, it will either need to -create multiple resize proposals, or atomically set its authority to a -top-level signer and reclaim it in the same transaction. The `ExtendProgram` -instruction will now also be invokable by CPI. +The 10 KiB minimum makes griefing attacks cost approximately 0.072 SOL per +invocation, with all lamports irrecoverably donated to the victim's program +data account. + +The minimum extension size has minimal impact on legitimate use: + +- Programs needing less than 10 KiB of additional space must extend by the + full 10 KiB minimum. The excess capacity is available for future use. +- Only 1.0% of mainnet programs have a total size below 10 KiB. +- No changes to the instruction's account list. No changes to signer + requirements. No impact on existing tooling or multisig workflows. ## Security Considerations -In the case of a multisig atomically setting its authority to a top-level -signer, it is important to introspect the transaction and ensure that it -executes the following behavior: +The minimum extension size provides economic deterrence rather than absolute +prevention. An attacker willing to spend 0.072 SOL per slot can still trigger +program cache invalidation. However: -- Set upgrade authority to top-level signer -- Extend program data account in top-level instruction -- Set upgrade authority back to quorum +- The cost scales linearly with attack duration (~650 SOL/hour at 400ms slots). +- All lamports spent are donated to the victim, not burned. +- The attacker receives no benefit — the victim's program only gains additional + allocated space. -If this behavior is not observed, it would be possible for a quorum to -accidentally lose its upgrade authority. +This economic model makes sustained attacks prohibitively expensive while +preserving the permissionless nature of `ExtendProgram`. ## Backwards Compatibility -This feature places additional restrictions upon an existing Loader V3 -instruction and is therefore not backwards compatible, necessitating a feature gate. +This feature places an additional constraint on an existing Loader V3 +instruction (minimum extension size) and is therefore not fully backwards +compatible. Any caller currently extending by less than 10 KiB will need to +increase their extension amount. This change is gated behind a feature flag. From 8bee72f8c5882864cf26ab461223ed2f412d753d Mon Sep 17 00:00:00 2001 From: Joe Caulfield Date: Wed, 18 Mar 2026 06:40:07 +0000 Subject: [PATCH 15/16] Document edge cases for minimum extension size - Near max account size (10 MiB): allow sub-10 KiB extends when less than 10 KiB of headroom remains - Frozen programs: already rejected by the loader with Immutable --- proposals/0431-permissioned-extend-program.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/proposals/0431-permissioned-extend-program.md b/proposals/0431-permissioned-extend-program.md index 1fc26290b..48d6363a6 100644 --- a/proposals/0431-permissioned-extend-program.md +++ b/proposals/0431-permissioned-extend-program.md @@ -83,6 +83,20 @@ The instruction will verify the following, in addition to all existing checks: All other existing checks (program ownership, account state, rent-exempt balance) remain unchanged. +### Edge Cases + +**Near maximum account size.** The maximum permitted account data length is +10 MiB (10,485,760 bytes). If the program data account's current size is +within 10 KiB of this limit (i.e. less than 10,240 bytes of headroom remain), +the account may be extended by the remaining amount up to the 10 MiB cap. In +this case the 10 KiB minimum does not apply, since the account cannot grow +further regardless. + +**Frozen (immutable) programs.** Programs whose upgrade authority has been set +to `None` cannot be extended. The loader program already rejects +`ExtendProgram` for such programs with `Immutable`. This behavior is +unchanged. + ### CPI Restriction The existing restriction preventing `ExtendProgram` from being invoked via CPI From afdc9529de3d5ce169432e5e4f3da102d95e1a6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20=E5=88=A9=E8=BF=AA=E6=81=A9?= <10921578+deanmlittle@users.noreply.github.com> Date: Wed, 18 Mar 2026 14:44:15 +0800 Subject: [PATCH 16/16] Rename permissioned extend program proposal file --- ...oned-extend-program.md => 0431-minimum-extend-program-size.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename proposals/{0431-permissioned-extend-program.md => 0431-minimum-extend-program-size.md} (100%) diff --git a/proposals/0431-permissioned-extend-program.md b/proposals/0431-minimum-extend-program-size.md similarity index 100% rename from proposals/0431-permissioned-extend-program.md rename to proposals/0431-minimum-extend-program-size.md