Skip to content

feat(#375): sdk_parity_fixtures for the wrapper — 12 live tags the spec never had - #460

Merged
dcccrypto merged 2 commits into
mainfrom
fix/375-prog-parity-fixture
Sep 3, 2026
Merged

feat(#375): sdk_parity_fixtures for the wrapper — 12 live tags the spec never had#460
dcccrypto merged 2 commits into
mainfrom
fix/375-prog-parity-fixture

Conversation

@dcccrypto

Copy link
Copy Markdown
Owner

Part 2 of 3 for #375. The percolator-prog target of the Parity Gate has failed with cargo run failed on every run since at least 2026-08-23, for two stacked reasons: this binary did not exist, and the job never checked out the percolator engine that this crate compiles through path = "../percolator". The workflow half is in the percolator-sdk PR.

What the gate finds the moment it can run

percolator-sdk/specs/wrapper-tags.json is missing twelve live instructions, tags 81–92:

tag instruction tag instruction
81 CancelRedemption 87 WithdrawInsuranceReserveToStake
82 UnwrapEscrowedPortfolio 88 UpdateMaintenanceFeePerSlot
83 InitMatcherCtx 89 ExpireBackingBucket
84 WithdrawProtocolFee 90 WithdrawCreatorFee
85 SetProtocolFeeAuthority 91 RebalanceLpVaultBacking
86 UpdateFeeSplit 92 UpdateInsuranceWithdrawPolicy

Seven of those move money. IX_TAG already carried 83–92 so the SDK could encode them; CancelRedemption(81) and UnwrapEscrowedPortfolio(82) were genuinely absent from the SDK, and tags 81/82 were annotated there as "Not in v17" — false.

Everything else already agreed: the gaps list comes back identical, with no name mismatches and no phantom tags.

Why this probes decode instead of reading the source

The obvious implementation parses the match tag arms. Do not.

Writing this, a regex over N => Self::Variant reported 69 tags and concluded that BatchTradeNoCpi(66), BatchTradeCpi(67) and InitMatcherCtx(83) did not exist — that the SDK had invented two of them. All three exist. They are dispatched in block form (66 => { ... }), which the pattern silently skipped. A parser that is wrong about the dispatcher produces a spec that is confidently wrong, which is worse than no gate at all.

Probing Instruction::decode cannot make that mistake — the answer comes from the code path the runtime uses.

A first draft then capped the probe at 200 bytes and reported tag 0 as unallocated, because InitMarket's body is 218. There is now a canary asserting tag 0 decodes, so that failure cannot ship quietly either.

Four names are deliberately the SDK's

Tags 3/4/5/8 emit DepositCollateral, WithdrawCollateral, KeeperCrank, CloseAccount. Not drift: none has appeared in this crate at any commit, they are declared aliases in the SDK (@alias DepositCollateral @since v12.x alias), and test/parity-fixtures.test.ts keys on them. Renaming four entries of the SDK's public surface would fix nothing — this gate catches a tag being renumbered or an instruction appearing/disappearing, and the tag binding is discovered by probing either way. Renaming a variant in the program still breaks the build at the match arm.

The deployed artifact is untouched

cargo build-sbf --features devnet produces a byte-identical percolator_prog.so with and without this file:

without bin: 9a310e287001e620174c271e6712322d4145161998e84cbb85b0f8e4c16942fb
with bin:    9a310e287001e620174c271e6712322d4145161998e84cbb85b0f8e4c16942fb

Checked with the file genuinely moved out of the tree, not stashed.

Upstream aeyakovenko/percolator-prog has no src/bin at all — nothing to coordinate.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NgoNgagkvw7i5SSRC3FJ8D

… check the wrapper

The Parity Gate's `percolator-prog` target has failed with `cargo run failed` on
every run since at least 2026-08-23, for two reasons stacked: this binary did not
exist, and the job never checked out the `percolator` engine that this crate
compiles through `path = "../percolator"`. ABI drift in the wrapper had no
automated detection at all. (The workflow half of that is in percolator-sdk.)

WHAT THE GATE FINDS THE MOMENT IT CAN RUN

`percolator-sdk/specs/wrapper-tags.json` is missing twelve live instructions —
tags 81 through 92:

  CancelRedemption(81)          UnwrapEscrowedPortfolio(82)
  InitMatcherCtx(83)            WithdrawProtocolFee(84)
  SetProtocolFeeAuthority(85)   UpdateFeeSplit(86)
  WithdrawInsuranceReserveToStake(87)  UpdateMaintenanceFeePerSlot(88)
  ExpireBackingBucket(89)       WithdrawCreatorFee(90)
  RebalanceLpVaultBacking(91)   UpdateInsuranceWithdrawPolicy(92)

Seven of those move money. `IX_TAG` already carried 83-92, so the SDK could encode
them; CancelRedemption(81) and UnwrapEscrowedPortfolio(82) were genuinely absent
from the SDK, and tags 81/82 were annotated there as "Not in v17" — false.

Everything else already agreed: the gaps list comes back identical, and there are
no name mismatches and no phantom tags.

WHY THIS PROBES `decode` INSTEAD OF READING THE SOURCE

The obvious implementation parses the `match tag` arms. Do not. Writing this, a
regex over `N => Self::Variant` reported 69 tags and concluded BatchTradeNoCpi(66),
BatchTradeCpi(67) and InitMatcherCtx(83) did not exist — that the SDK had invented
two of them. All three exist; they are dispatched in block form (`66 => { ... }`),
which the pattern silently skipped. A parser that is wrong about the dispatcher
produces a spec that is confidently wrong, which is worse than no gate.

Probing `Instruction::decode` cannot make that mistake — the answer comes from the
code path the runtime uses. A first draft then capped the probe at 200 bytes and
reported tag 0 as unallocated, because InitMarket's body is 218; there is now a
canary asserting tag 0 decodes, so that failure cannot ship quietly either.

FOUR NAMES ARE DELIBERATELY THE SDK'S

tags 3/4/5/8 emit DepositCollateral, WithdrawCollateral, KeeperCrank and
CloseAccount. Those are not drift: they have never appeared in this crate at any
commit, they are declared aliases in the SDK, and `test/parity-fixtures.test.ts`
keys on them. Renaming four entries of the SDK's public surface would fix nothing —
this gate exists to catch a tag being renumbered or an instruction
appearing/disappearing, and the tag binding is discovered by probing.

VERIFIED: the deployed artifact is untouched. `cargo build-sbf --features devnet`
produces a byte-identical percolator_prog.so with and without this file
(9a310e28...42fb both ways, checked with the file genuinely absent).

Upstream aeyakovenko/percolator-prog has no src/bin at all — nothing to coordinate.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NgoNgagkvw7i5SSRC3FJ8D
@coderabbitai

coderabbitai Bot commented Sep 3, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: 871b23ec-eb34-49b3-96e0-b81ac1ebeeff


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NgoNgagkvw7i5SSRC3FJ8D
@dcccrypto
dcccrypto merged commit 330ae4f into main Sep 3, 2026
3 checks passed
@dcccrypto
dcccrypto deleted the fix/375-prog-parity-fixture branch September 3, 2026 11:47
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