serviceability: fix topology clear passing the topology PDA readonly - #4091
serviceability: fix topology clear passing the topology PDA readonly#4091ben-dz wants to merge 1 commit into
Conversation
The SDK builder marked the topology account readonly while process_topology_clear writes it to decrement reference_count, so every invocation in which a link actually held the reference aborted with 'Topology Account is not writable' after the link writes had already been staged. Only the two no-op cases succeeded: an already-closed topology, or no supplied link holding a reference. The account list now comes from clear_topology_account_metas, consumed by both the SDK builder and the program integration tests, so a client/processor writability divergence fails a test rather than a live transaction. The processor validates the topology account up front via validate_program_account! instead of asserting writability part-way through the link loop, so a readonly non-empty topology is rejected deterministically rather than only when cleared_count > 0. Also covers the multi-link reference_count decrement, which was unreachable before this fix, including the duplicate-link case.
a5999a5 to
e7dc37a
Compare
|
Superseded. The readonly-topology bug this PR set out to fix was independently fixed in #4060 (RFC-26 R10), tracked as #4078: the What remained after rebasing onto that was not worth a separate review cycle: the processor's up-front account validation guards against a caller that no longer exists now that the builder is the only path constructing this instruction, and it would tighten behavior on a live program for no current benefit. One piece of coverage is worth salvaging and will land separately: That follow-up is blocked on a pre-existing flake in |
Summary of Changes
doublezero link topology clear, which could never clear a topology that a link actually referenced. The SDK builder marked the topology PDA readonly whileprocess_topology_clearwrites it to decrementreference_count, so every invocation in which a link held the reference aborted withTopology Account is not writable— after the link writes had already been staged. Only two no-op cases succeeded: an already-closed topology, or no supplied link holding a reference. Broken since the CLI shipped in smartcontract,client: add topology CLI commands #3512.clear_topology_account_metasfunction, so a client/processor writability divergence fails a test instead of a live transaction. Previously the SDK unit test asserted the buggy readonly meta as expected while the program test hand-built a writable one, and nothing compared them.validate_program_account!rather than asserting writability part-way through the link loop. A readonly non-empty topology account is now rejected deterministically instead of only when at least one link held a reference.reference_countdecrement, which was unreachable before this fix — including the duplicate-link case, whose safety rests on the runtime aliasing duplicate accounts onto one data buffer.--namepreviously read as success).Related: RFC-18. The rest of the RFC-18 flex-algo surface was audited for the same client/processor divergence —
topology create/delete/assign,link create/update/delete,device interface create/update,tenant update— andclearwas the only one affected.Not in scope: #4090, an unrelated
reference_countskew via duplicatelink_topologiesentries inlink update/link delete, surfaced while reviewing this change.Behavior change
An operator on a pre-fix CLI binary now gets a hard failure in the
cleared_count == 0case where they previously got a silent success. No wire or account-layout change, and the stricter check only rejects input that no working client sends.Diff Breakdown
Overwhelmingly test weight — the fix is ~10 lines of logic plus a shared account-meta builder; the rest is closing the coverage gap that let the bug ship.
Key files (click to expand)
smartcontract/programs/doublezero-serviceability/tests/topology_test.rs— the clear helpers now build fromclear_topology_account_metas; addstest_topology_clear_readonly_topology_rejected(both the no-reference case, which the pre-fix processor accepted, and the staged-write case) andtest_topology_clear_multi_link_reference_countsmartcontract/programs/doublezero-serviceability/src/processors/topology/clear.rs— adds the canonical account-meta builder with the topology PDA writable; moves owner/writable validation ahead of the link loop; splits the success log for the already-closed pathsmartcontract/sdk/rs/src/commands/topology/clear.rs— builds from the shared function instead of a hand-written list, and derives the globalstate PDA rather than threading it inTesting Verification
clear_topology_account_metastonew_readonlyfails four existing tests (clear_removes_from_links,clear_is_idempotent,clear_with_permission_account_allowed,reference_count_lifecycle). The same divergence was invisible to every test before this change.cleared_count > 0) fails it withexpected ProgramFailedToComplete (readonly topology account, no link holding a reference), got Ok(())— the pre-fix code silently succeeded on that input. A test using only the reference-holding case passes against the bug, because Solana rolls the staged link write back either way.test_topology_clear_multi_link_reference_countexercises two tagged links plus an untagged one plus a duplicate in a single instruction, asserting the count drops by 2 rather than 3, then deletes the topology to confirm theReferenceCountNotZeroguard it gates.doublezero-serviceability,doublezero_sdk, anddoublezero-serviceability-cli.