Skip to content

serviceability-instruction: globalstate/globalconfig/allowlist/index/migrate builders (RFC-26 R9) - #4058

Merged
juan-malbeclabs merged 5 commits into
mainfrom
feat/rfc26-r9-admin-builders
Jul 24, 2026
Merged

serviceability-instruction: globalstate/globalconfig/allowlist/index/migrate builders (RFC-26 R9)#4058
juan-malbeclabs merged 5 commits into
mainfrom
feat/rfc26-r9-admin-builders

Conversation

@juan-malbeclabs

@juan-malbeclabs juan-malbeclabs commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Summary

RFC-26 R9 (stacked on the previous phase's branch). init_global_state and migrate (no authorize -> build); setters, set_global_config (config PDA + all 8 resource pools), foundation/QA allowlist toggles, index create/delete. After this every buildable variant has a builder.

All builders route through authorize() -> build_with_permission unless noted; each carries a verbatim account-layout doc-comment copied from its processor.

Testing Verification

  • Unit tests assert the exact AccountMeta list (incl. trailing [payer, system]) and the borsh tag byte for every builder, covering the conditional/variable-account paths.

Closes #4024. Part of RFC-26 (rfcs/rfc26-rust-instruction-builder-library.md).


PR stack (RFC-26 builder library)

Stacked PRs, merge in order (each is based on the previous one's branch):

  1. serviceability-instruction: scaffold pure instruction-builder crate (RFC-26 R0) #4049 — R0 scaffold + exemplars
  2. serviceability-instruction: device domain builders (RFC-26 R1) #4050 — R1 device
  3. serviceability-instruction: link domain builders (RFC-26 R2) #4051 — R2 link
  4. serviceability-instruction: user domain builders (RFC-26 R3) #4052 — R3 user
  5. serviceability-instruction: location/exchange/contributor builders (RFC-26 R4) #4053 — R4 location/exchange/contributor
  6. serviceability-instruction: multicastgroup + allowlist builders (RFC-26 R5) #4054 — R5 multicastgroup + allowlists
  7. serviceability-instruction: tenant + permission builders (RFC-26 R6) #4055 — R6 tenant + permission
  8. serviceability-instruction: topology + feed builders (RFC-26 R7) #4056 — R7 topology + feed
  9. serviceability-instruction: accesspass + resource builders (RFC-26 R8) #4057 — R8 accesspass + resource
  10. serviceability-instruction: globalstate/globalconfig/allowlist/index/migrate builders (RFC-26 R9) #4058 — R9 globalstate/config/allowlist/index/migrate ← this PR

R10 (commands/* migration + program-test) and RF (fixtures) follow as separate PRs.

juan-malbeclabs added a commit that referenced this pull request Jul 14, 2026
…RFC-26 R0) (#4049)

## Summary

RFC-26 **R0**: scaffold the pure, RPC-free instruction-builder crate
`doublezero-serviceability-instruction` — SPL-style builders that return
a single unsigned `Instruction` per serviceability instruction, no
signing/sending.

- `common::build` (no-permission trailing `[payer, system]`) +
`common::build_with_permission` (the deferred, activate-in-one-place
Permission append) + `compute_budget_prelude` (1.4M CU / 256 KiB).
- Four exemplar builders establishing the pattern every later PR copies:
`create_device`, `delete_device` (legacy/atomic), `create_link`,
`create_subscribe_user`.
- Deps limited to `doublezero-serviceability` + `solana-program` +
`solana-system-interface` + `solana-compute-budget-interface` — no RPC
tree.

The `suspend_device` exemplar from the RFC was replaced with
`delete_device` (`SuspendDevice` is a deprecated variant); the RFC and
#4015 were updated, and the "length-detected family" classification was
corrected (only `CreateUser` is length-detected).

## Why

Instruction assembly is currently coupled to signing+sending inside
`commands/*::execute()`; there is no reusable `build_xxx(args) ->
Instruction`. See
[rfcs/rfc26-rust-instruction-builder-library.md](rfcs/rfc26-rust-instruction-builder-library.md).

## Testing Verification

- Unit tests assert the exact `AccountMeta` list (incl. trailing
`[payer, system]`) and the borsh tag byte for each exemplar, including
the `delete_device` legacy vs atomic layouts and the
`create_subscribe_user` optional-feed placement.

Closes #4015. Part of RFC-26.

---

### PR stack (RFC-26 builder library)

Stacked PRs, merge in order (each is based on the previous one's
branch):

1. #4049 — R0 scaffold + exemplars  ← **this PR**
2. #4050 — R1 device
3. #4051 — R2 link
4. #4052 — R3 user
5. #4053 — R4 location/exchange/contributor
6. #4054 — R5 multicastgroup + allowlists
7. #4055 — R6 tenant + permission
8. #4056 — R7 topology + feed
9. #4057 — R8 accesspass + resource
10. #4058 — R9 globalstate/config/allowlist/index/migrate

R10 (commands/* migration + program-test) and RF (fixtures) follow as
separate PRs.
@juan-malbeclabs
juan-malbeclabs force-pushed the feat/rfc26-r8-accesspass-resource-builders branch from 6a548bf to b4d8e02 Compare July 21, 2026 17:02
@juan-malbeclabs
juan-malbeclabs force-pushed the feat/rfc26-r9-admin-builders branch from e0235a0 to 9240816 Compare July 21, 2026 17:02
@juan-malbeclabs
juan-malbeclabs force-pushed the feat/rfc26-r8-accesspass-resource-builders branch from b4d8e02 to 0afe42f Compare July 21, 2026 17:19
@juan-malbeclabs
juan-malbeclabs force-pushed the feat/rfc26-r9-admin-builders branch from 9240816 to 9e23736 Compare July 21, 2026 17:19
juan-malbeclabs added a commit that referenced this pull request Jul 22, 2026
## Summary

RFC-26 **R1** (stacked on the previous phase's branch). Complete the
device domain on top of the R0 exemplars: update_device (max(old,new)
dz_prefix block), set_device_health, and interface create/delete/update
(Vpnv4 topology PDAs, segment-routing reconcile).

All builders route through `authorize()` -> `build_with_permission`
unless noted; each carries a verbatim account-layout doc-comment copied
from its processor.

## Testing Verification

- Unit tests assert the exact `AccountMeta` list (incl. trailing
`[payer, system]`) and the borsh tag byte for every builder, covering
the conditional/variable-account paths.

Closes #4016. Part of RFC-26
([rfcs/rfc26-rust-instruction-builder-library.md](rfcs/rfc26-rust-instruction-builder-library.md)).

---

### PR stack (RFC-26 builder library)

Stacked PRs, merge in order (each is based on the previous one's
branch):

1. #4049 — R0 scaffold + exemplars
2. #4050 — R1 device  ← **this PR**
3. #4051 — R2 link
4. #4052 — R3 user
5. #4053 — R4 location/exchange/contributor
6. #4054 — R5 multicastgroup + allowlists
7. #4055 — R6 tenant + permission
8. #4056 — R7 topology + feed
9. #4057 — R8 accesspass + resource
10. #4058 — R9 globalstate/config/allowlist/index/migrate

R10 (commands/* migration + program-test) and RF (fixtures) follow as
separate PRs.
juan-malbeclabs added a commit that referenced this pull request Jul 22, 2026
## Summary

RFC-26 **R2** (stacked on the previous phase's branch). accept_link,
update_link (LinkUpdateAuthority preamble + conditional tunnel_net /
tunnel-resource / topology-union sections), delete_link (topology
reference-count accounts), set_link_health.

All builders route through `authorize()` -> `build_with_permission`
unless noted; each carries a verbatim account-layout doc-comment copied
from its processor.

## Testing Verification

- Unit tests assert the exact `AccountMeta` list (incl. trailing
`[payer, system]`) and the borsh tag byte for every builder, covering
the conditional/variable-account paths.

Closes #4017. Part of RFC-26
([rfcs/rfc26-rust-instruction-builder-library.md](rfcs/rfc26-rust-instruction-builder-library.md)).

---

### PR stack (RFC-26 builder library)

Stacked PRs, merge in order (each is based on the previous one's
branch):

1. #4049 — R0 scaffold + exemplars
2. #4050 — R1 device
3. #4051 — R2 link  ← **this PR**
4. #4052 — R3 user
5. #4053 — R4 location/exchange/contributor
6. #4054 — R5 multicastgroup + allowlists
7. #4055 — R6 tenant + permission
8. #4056 — R7 topology + feed
9. #4057 — R8 accesspass + resource
10. #4058 — R9 globalstate/config/allowlist/index/migrate

R10 (commands/* migration + program-test) and RF (fixtures) follow as
separate PRs.
juan-malbeclabs added a commit that referenced this pull request Jul 22, 2026
## Summary

RFC-26 **R3** (stacked on the previous phase's branch). create_user
(length-detected -> build, no permission), update_user, delete_user,
request_ban_user, check_user_access_pass, and set_user_bgp_status
(metrics-publisher check, no authorize -> build).

All builders route through `authorize()` -> `build_with_permission`
unless noted; each carries a verbatim account-layout doc-comment copied
from its processor.

## Testing Verification

- Unit tests assert the exact `AccountMeta` list (incl. trailing
`[payer, system]`) and the borsh tag byte for every builder, covering
the conditional/variable-account paths.

Closes #4018. Part of RFC-26
([rfcs/rfc26-rust-instruction-builder-library.md](rfcs/rfc26-rust-instruction-builder-library.md)).

---

### PR stack (RFC-26 builder library)

Stacked PRs, merge in order (each is based on the previous one's
branch):

1. #4049 — R0 scaffold + exemplars
2. #4050 — R1 device
3. #4051 — R2 link
4. #4052 — R3 user  ← **this PR**
5. #4053 — R4 location/exchange/contributor
6. #4054 — R5 multicastgroup + allowlists
7. #4055 — R6 tenant + permission
8. #4056 — R7 topology + feed
9. #4057 — R8 accesspass + resource
10. #4058 — R9 globalstate/config/allowlist/index/migrate

R10 (commands/* migration + program-test) and RF (fixtures) follow as
separate PRs.
@juan-malbeclabs
juan-malbeclabs force-pushed the feat/rfc26-r8-accesspass-resource-builders branch from 0afe42f to 74ade12 Compare July 22, 2026 18:04
@juan-malbeclabs
juan-malbeclabs force-pushed the feat/rfc26-r9-admin-builders branch from 9e23736 to b919cea Compare July 22, 2026 18:04
@juan-malbeclabs
juan-malbeclabs force-pushed the feat/rfc26-r8-accesspass-resource-builders branch from 74ade12 to f31652d Compare July 22, 2026 18:16
@juan-malbeclabs
juan-malbeclabs force-pushed the feat/rfc26-r9-admin-builders branch from b919cea to 4618cc4 Compare July 22, 2026 18:16
@juan-malbeclabs
juan-malbeclabs force-pushed the feat/rfc26-r8-accesspass-resource-builders branch from f31652d to f7d915c Compare July 22, 2026 20:25
@juan-malbeclabs
juan-malbeclabs force-pushed the feat/rfc26-r9-admin-builders branch from 4618cc4 to 155cbc7 Compare July 22, 2026 20:25
juan-malbeclabs added a commit that referenced this pull request Jul 22, 2026
…FC-26 R4) (#4053)

## Summary

RFC-26 **R4** (stacked on the previous phase's branch). Three
account_index-seeded CRUD domains (create/update/suspend/resume/delete).
Exchange create/update carry globalconfig; set_device_exchange carries
the device; create_contributor carries the owner.

All builders route through `authorize()` -> `build_with_permission`
unless noted; each carries a verbatim account-layout doc-comment copied
from its processor.

## Testing Verification

- Unit tests assert the exact `AccountMeta` list (incl. trailing
`[payer, system]`) and the borsh tag byte for every builder, covering
the conditional/variable-account paths.

Closes #4019. Part of RFC-26
([rfcs/rfc26-rust-instruction-builder-library.md](rfcs/rfc26-rust-instruction-builder-library.md)).

---

### PR stack (RFC-26 builder library)

Stacked PRs, merge in order (each is based on the previous one's
branch):

1. #4049 — R0 scaffold + exemplars
2. #4050 — R1 device
3. #4051 — R2 link
4. #4052 — R3 user
5. #4053 — R4 location/exchange/contributor  ← **this PR**
6. #4054 — R5 multicastgroup + allowlists
7. #4055 — R6 tenant + permission
8. #4056 — R7 topology + feed
9. #4057 — R8 accesspass + resource
10. #4058 — R9 globalstate/config/allowlist/index/migrate

R10 (commands/* migration + program-test) and RF (fixtures) follow as
separate PRs.
juan-malbeclabs added a commit that referenced this pull request Jul 23, 2026
…26 R5) (#4054)

## Summary

RFC-26 **R5** (stacked on the previous phase's branch). create/update
(conditional multicast_group_block)/suspend/reactivate/delete,
update_multicast_group_roles, and the four pub/sub allowlist add/remove
builders.

All builders route through `authorize()` -> `build_with_permission`
unless noted; each carries a verbatim account-layout doc-comment copied
from its processor.

## Testing Verification

- Unit tests assert the exact `AccountMeta` list (incl. trailing
`[payer, system]`) and the borsh tag byte for every builder, covering
the conditional/variable-account paths.

Closes #4020. Part of RFC-26
([rfcs/rfc26-rust-instruction-builder-library.md](rfcs/rfc26-rust-instruction-builder-library.md)).

---

### PR stack (RFC-26 builder library)

Stacked PRs, merge in order (each is based on the previous one's
branch):

1. #4049 — R0 scaffold + exemplars
2. #4050 — R1 device
3. #4051 — R2 link
4. #4052 — R3 user
5. #4053 — R4 location/exchange/contributor
6. #4054 — R5 multicastgroup + allowlists  ← **this PR**
7. #4055 — R6 tenant + permission
8. #4056 — R7 topology + feed
9. #4057 — R8 accesspass + resource
10. #4058 — R9 globalstate/config/allowlist/index/migrate

R10 (commands/* migration + program-test) and RF (fixtures) follow as
separate PRs.
juan-malbeclabs added a commit that referenced this pull request Jul 23, 2026
…4055)

## Summary

RFC-26 **R6** (stacked on the previous phase's branch). Tenant CRUD +
add/remove administrator + update_payment_status (globalstate writable
on create, read-only elsewhere), and permission
create/update/suspend/resume/delete (target PDA derived from
args.user_payer).

All builders route through `authorize()` -> `build_with_permission`
unless noted; each carries a verbatim account-layout doc-comment copied
from its processor.

## Testing Verification

- Unit tests assert the exact `AccountMeta` list (incl. trailing
`[payer, system]`) and the borsh tag byte for every builder, covering
the conditional/variable-account paths.

Closes #4021. Part of RFC-26
([rfcs/rfc26-rust-instruction-builder-library.md](rfcs/rfc26-rust-instruction-builder-library.md)).

---

### PR stack (RFC-26 builder library)

Stacked PRs, merge in order (each is based on the previous one's
branch):

1. #4049 — R0 scaffold + exemplars
2. #4050 — R1 device
3. #4051 — R2 link
4. #4052 — R3 user
5. #4053 — R4 location/exchange/contributor
6. #4054 — R5 multicastgroup + allowlists
7. #4055 — R6 tenant + permission  ← **this PR**
8. #4056 — R7 topology + feed
9. #4057 — R8 accesspass + resource
10. #4058 — R9 globalstate/config/allowlist/index/migrate

R10 (commands/* migration + program-test) and RF (fixtures) follow as
separate PRs.
juan-malbeclabs added a commit that referenced this pull request Jul 23, 2026
## Summary

RFC-26 **R7** (stacked on the previous phase's branch). Topology
create/delete plus batched clear_topology /
assign_topology_node_segments (single-chunk + *_batched;
CLEAR_BATCH_SIZE=16 / BACKFILL_BATCH_SIZE=4 moved into the crate). Feed
create/update/delete.

All builders route through `authorize()` -> `build_with_permission`
unless noted; each carries a verbatim account-layout doc-comment copied
from its processor.

## Testing Verification

- Unit tests assert the exact `AccountMeta` list (incl. trailing
`[payer, system]`) and the borsh tag byte for every builder, covering
the conditional/variable-account paths.

Closes #4022. Part of RFC-26
([rfcs/rfc26-rust-instruction-builder-library.md](rfcs/rfc26-rust-instruction-builder-library.md)).

---

### PR stack (RFC-26 builder library)

Stacked PRs, merge in order (each is based on the previous one's
branch):

1. #4049 — R0 scaffold + exemplars
2. #4050 — R1 device
3. #4051 — R2 link
4. #4052 — R3 user
5. #4053 — R4 location/exchange/contributor
6. #4054 — R5 multicastgroup + allowlists
7. #4055 — R6 tenant + permission
8. #4056 — R7 topology + feed  ← **this PR**
9. #4057 — R8 accesspass + resource
10. #4058 — R9 globalstate/config/allowlist/index/migrate

R10 (commands/* migration + program-test) and RF (fixtures) follow as
separate PRs.
@juan-malbeclabs
juan-malbeclabs force-pushed the feat/rfc26-r8-accesspass-resource-builders branch from f7d915c to ad00567 Compare July 23, 2026 21:24
@juan-malbeclabs
juan-malbeclabs force-pushed the feat/rfc26-r9-admin-builders branch from 155cbc7 to d934652 Compare July 23, 2026 23:10
Base automatically changed from feat/rfc26-r8-accesspass-resource-builders to main July 24, 2026 13:27
juan-malbeclabs added a commit that referenced this pull request Jul 24, 2026
#4057)

## Summary

RFC-26 **R8** (stacked on the previous phase's branch). Access-pass set
(conditional tenant pair)/close/check-status/set-feeds, and
resource-extension allocate/create/deallocate/close (resource PDA +
associated account derived from the data-bearing args.resource_type).

All builders route through `authorize()` -> `build_with_permission`
unless noted; each carries a verbatim account-layout doc-comment copied
from its processor.

## Testing Verification

- Unit tests assert the exact `AccountMeta` list (incl. trailing
`[payer, system]`) and the borsh tag byte for every builder, covering
the conditional/variable-account paths.

Closes #4023. Part of RFC-26
([rfcs/rfc26-rust-instruction-builder-library.md](rfcs/rfc26-rust-instruction-builder-library.md)).

---

### PR stack (RFC-26 builder library)

Stacked PRs, merge in order (each is based on the previous one's
branch):

1. #4049 — R0 scaffold + exemplars
2. #4050 — R1 device
3. #4051 — R2 link
4. #4052 — R3 user
5. #4053 — R4 location/exchange/contributor
6. #4054 — R5 multicastgroup + allowlists
7. #4055 — R6 tenant + permission
8. #4056 — R7 topology + feed
9. #4057 — R8 accesspass + resource  ← **this PR**
10. #4058 — R9 globalstate/config/allowlist/index/migrate

R10 (commands/* migration + program-test) and RF (fixtures) follow as
separate PRs.
…dex/migrate builders (RFC-26 R9)

init_global_state and migrate never call authorize() -> build; the setters,
set_global_config (config PDA + all 8 resource pools), foundation/QA allowlist
toggles, and index create/delete route through authorize() -> build_with_permission.
After this PR every buildable serviceability variant has a builder.

Refs #4024, RFC-26.
…sion builder

process_set_version reads program_config FIRST (it writes the updated
min_compatible_version there), then globalstate. The builder emitted only
[globalstate], so the instruction could never execute. Add program_config as
the leading (writable) account, matching the processor and init_global_state.
@juan-malbeclabs
juan-malbeclabs force-pushed the feat/rfc26-r9-admin-builders branch from d934652 to bde6207 Compare July 24, 2026 13:49

@ben-dz ben-dz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

lgtm — builders faithfully mirror the processors (all 13 tag bytes, account orders, writability/signer flags, PDA derivations, and the build vs build_with_permission split verified), byte-parity with the existing SDK commands holds, and tests pin the full AccountMeta vector + tag byte per builder. One trivial nit; one informational note about a pre-existing SDK SetVersionCommand bug (the new set_min_version builder is correct where the SDK is stale) worth a separate follow-up.

  • Informational (pre-existing, not this PR): smartcontract/sdk/rs/src/commands/globalstate/setversion.rs sends only [globalstate], but the processor reads [program_config, globalstate, payer, system] since #3977, so the SDK's SetVersionCommand fails onchain today. The new set_min_version builder is correct — an intentional, documented divergence from SDK byte-parity. Worth a separate follow-up to fix the SDK command.

Comment thread crates/doublezero-serviceability-instruction/src/allowlist.rs Outdated
The processor reads [program_config, globalstate, payer, system] since
#3977, but the SDK command sent only [globalstate], so it failed onchain.
Prepend program_config to match the processor's account order.
@juan-malbeclabs

Copy link
Copy Markdown
Contributor Author

Informational (pre-existing): the SDK's SetVersionCommand sends only [globalstate] while the processor reads [program_config, globalstate, payer, system] since #3977.

Good catch — rather than defer this, I fixed it here in 5259c95: SetVersionCommand now prepends program_config to match the processor's account order, and the test pins the two-account vector. Heads up that this widens the PR slightly beyond the RFC-26 R9 builders; happy to split it onto its own branch if you'd prefer to keep this one strictly scoped.

@ben-dz

ben-dz commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Informational (pre-existing): the SDK's SetVersionCommand sends only [globalstate] while the processor reads [program_config, globalstate, payer, system] since #3977.

Good catch — rather than defer this, I fixed it here in 5259c95: SetVersionCommand now prepends program_config to match the processor's account order, and the test pins the two-account vector. Heads up that this widens the PR slightly beyond the RFC-26 R9 builders; happy to split it onto its own branch if you'd prefer to keep this one strictly scoped.

LGTM, no need for a new branch.

@juan-malbeclabs
juan-malbeclabs enabled auto-merge (squash) July 24, 2026 19:48
@juan-malbeclabs
juan-malbeclabs merged commit d697bf3 into main Jul 24, 2026
36 checks passed
@juan-malbeclabs
juan-malbeclabs deleted the feat/rfc26-r9-admin-builders branch July 24, 2026 20:06
juan-malbeclabs added a commit that referenced this pull request Jul 25, 2026
…4059)

## Summary

RFC-26 **RF**: golden fixtures for the instruction builders + a CI drift
guard.

- Extend the serviceability fixture generator to depend on
`doublezero-serviceability-instruction` and emit, per instruction,
`ix_<name>.bin` (wire bytes = tag + borsh) and `ix_<name>.json` (`{
variant, data_hex, accounts: [{pubkey, is_signer, is_writable}] }`) from
fixed, deterministic inputs.
- Representative set covering the trickiest layouts: `create_device`
(variable dz_prefix), `delete_device` (atomic close), `create_link`,
`create_subscribe_user` (optional feed), `create_user`
(length-detected), `clear_topology` / `assign_topology_node_segments`
(batched), `set_global_config` (config PDA + all 8 pools).
- `make generate-fixtures-check` (regenerate + fail on drift, scoped to
the emitted `.bin`/`.json`) and a `fixtures-check` job in the `rust`
workflow.

These fixtures capture byte-for-byte the current SDK trailing convention
(they will drive Go/Python/TS parity in a later phase).

## Testing Verification

- `make generate-fixtures-check` passes (regenerated output is
byte-identical to the committed fixtures); a hand-edited fixture makes
it fail as expected.

Closes #4026. Part of RFC-26
([rfcs/rfc26-rust-instruction-builder-library.md](rfcs/rfc26-rust-instruction-builder-library.md)).

---

### PR stack (RFC-26 builder library)

Stacked PRs, merge in order (each based on the previous one's branch):

1. #4049 — R0 scaffold + exemplars
2. #4050 — R1 device
3. #4051 — R2 link
4. #4052 — R3 user
5. #4053 — R4 location/exchange/contributor
6. #4054 — R5 multicastgroup + allowlists
7. #4055 — R6 tenant + permission
8. #4056 — R7 topology + feed
9. #4057 — R8 accesspass + resource
10. #4058 — R9 globalstate/config/allowlist/index/migrate
11. this PR — RF fixtures + CI guard

R10 (commands/* migration + program-test) is the final PR and will carry
the global changelog entry.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

serviceability: globalstate/globalconfig/allowlist/index/migrate instruction builders (Rust)

2 participants