Skip to content

serviceability: remove InterfaceV3 entirely#3680

Draft
elitegreg wants to merge 2 commits intogm/rename-interface-canonicalfrom
gm/issue-3664-remove-interface-v3
Draft

serviceability: remove InterfaceV3 entirely#3680
elitegreg wants to merge 2 commits intogm/rename-interface-canonicalfrom
gm/issue-3664-remove-interface-v3

Conversation

@elitegreg
Copy link
Copy Markdown
Contributor

Summary

Implements #3664 — the cleanup step of the forward-compatible Device interfaces refactor. InterfaceV3 was added then reverted in #3653, no longer produced after #3667's always-V2 legacy-slot projection, and the migrate processor that wrote it was deleted in #3675. No on-chain account ever held discriminant 3, so this removes the type entirely with no backward-compat read shim.

  • Delete InterfaceV3 struct, its impls (Default, From<InterfaceV2>, TryFrom<&InterfaceV1>, TryFrom<&InterfaceV3> for InterfaceV2), and the InterfaceDeprecated::V3 variant. Discriminant 3 is now an unused reserved slot in InterfaceDeprecated's encoding space; the custom BorshDeserialize falls through unknown discriminants to InterfaceV2::default().
  • Drop V3 match arms in InterfaceDeprecated::to_v2 / size and in the legacy-rebuild path inside Device::TryFrom<&[u8]>.
  • Drop V3 from the Go/Python/TypeScript serviceability SDKs: remove DeserializeInterfaceV3 (Go) and the version == 3 / version === 3 legacy-slot branches (Python/TS); remove the TestDeserializeInterfaceV3CrossLanguage Go test.
  • Delete the V3 cross-language byte-layout debug test (test_interface_v3_serialization_bytes) and the V3 block in test_interface_version.

On-disk write format is unchanged; the trailing forward-compat interfaces vec on Device continues to carry flex_algo_node_segments via the size-prefixed body.

Branch base

This PR targets gm/rename-interface-canonical (PR #3677, the rename) because issue #3664 depends on it. Once #3677 merges to main, this branch will be rebased and retargeted to main.

Tests

  • All 26 state::interface lib tests pass.
  • make rust-fmt, make rust-lint, make rust-test green.
  • Go SDK: go test ./... passes (smartcontract/sdk/go/serviceability).
  • Python SDK: pytest 121 passed / 24 skipped.
  • TypeScript SDK: bun tsc --noEmit clean; bun test 144/144 passing.

Testing Verification

  • Existing legacy-account compat coverage still passes: test_state_compatibility_device and the SDK fixture tests against device.{bin,json} / device_legacy.{bin,json} / device_future_version.{bin,json} are unaffected (fixtures don't contain V3 bytes — confirmed by the fixture generator using the always-V2 projection from smartcontract: append new_interfaces vec to Device with custom serializer #3667).
  • make generate-fixtures produces no diff (on-disk write format unchanged).

elitegreg added 2 commits May 6, 2026 19:59
V3 was added by an earlier change, never written to production accounts,
and reverted in #3653. After #3667 stopped producing V3 (always-V2
projection of the legacy slot) and #3675 deleted the migrate processor,
the type is dead weight. This removes it as if it never existed —
no read shim, since no on-chain account ever held discriminant 3.

- Delete InterfaceV3 struct + Default/From/TryFrom impls.
- Delete InterfaceDeprecated::V3 variant; discriminant 3 is now an
  unused reserved slot. Unknown discriminants fall through to
  InterfaceV2::default().
- Drop V3 match arms in InterfaceDeprecated::to_v2 / size and in
  Device::TryFrom legacy-rebuild.
- Drop V3 from Go/Python/TS SDKs: remove DeserializeInterfaceV3,
  version==3 / version === 3 branches, and the V3 cross-language
  Go test.
- Delete the V3 cross-language byte-layout debug test in interface.rs
  and the V3 block in test_interface_version.

On-disk write format unchanged.
Mainnet-beta has one device (la2r-dz01, interface Ethernet20/1) with a
discriminant-3 (V3) entry in its legacy deprecated_interfaces slot,
written by an admin path that no longer exists. The previous commit
removed all V3 read handling, which caused byte misalignment on that
account: the V3 body (V2 fields + flex_algo_node_segments vec) went
unread, the cursor desynced, and downstream Device fields decoded as
garbage. CI sdk-compat-test caught this against mainnet:
"110 is not a valid DeviceHealth".

Restore byte-level consumption of discriminant 3 in all readers (Rust
+ Go/Python/TS SDKs): read the V2 body and consume + drop the trailing
flex_algo_node_segments vec, then surface the entry as V2. The
InterfaceV3 struct stays deleted; only the wire-compat read path is
restored. Segments live in the trailing forward-compat interfaces vec
on Device post-#3667 — this slot loses them, matching the always-V2
projection on writes.

Adds a Rust regression test that hand-crafts a Vec<InterfaceDeprecated>
with a V3-encoded element followed by a V2 element and asserts the V3
bytes are fully consumed, so the trailing V2 still decodes — guards
against the misalignment that broke CI.
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.

1 participant