Skip to content

Byte-verify MPMA batches mixing a hex memo with memo-less sends - #225

Merged
droplister merged 1 commit into
mainfrom
fix/mpma-memo-flag-coverage
Aug 3, 2026
Merged

Byte-verify MPMA batches mixing a hex memo with memo-less sends#225
droplister merged 1 commit into
mainfrom
fix/mpma-memo-flag-coverage

Conversation

@droplister

Copy link
Copy Markdown
Member

PRIORITIES.md item 4b — a coverage gap I introduced in #216 and found reviewing my own work, plus an oracle fix it surfaced.

The gap

The packer rejected any memos_are_hex list containing more than one distinct value:

if (new Set(flagValues).size > 1) return null;

But composeMPMA filters that list to entries whose memo is non-empty before choosing the single flag it sends. The MPMA form emits one flag per row, and a row with no memo emits false — so a batch with one hex memo and one blank memo arrives as "true,false". Compose correctly sends memos_are_hex=true; the packer saw two distinct values and declined.

Result: byte verification silently dropped to field comparison for a perfectly ordinary CSV — one where only some rows carry memos. It failed safe (never passing a substitution), but the oracles couldn't catch it because every oracle case uses uniform flags.

Only the flags belonging to an actual memo describe the encoding, so the packer now filters the same way composeMPMA does. A batch with two real memos of different encodings is still declined, since core's single flag can't express it — both cases are tested, with the passing one pinned to bytes generated by core's own encoder.

The oracle fix this surfaced

Running the live oracles afterward, the issuance round-trip case failed with "every sample was skipped". That turned out not to be a regression: all five samples were locked subasset issuances, which #219's borrow guard declines by design. Checking further, all 100 most recent on-chain issuances were locked subassets — one prolific minter had filled the entire window.

The guard exists so a type can't pass vacuously, which is right, but it couldn't distinguish an unrepresentative sample from a broken packer. Now:

  • principled declines are counted separately;
  • when nothing was compared, the assertion is that every sample was such a decline — a sample that was attempted and still couldn't be rebuilt fails as before;
  • SAMPLE_SIZE is wider (5 → 25), making the situation rarer.

Verification

  • tsc --noEmit clean; 693 counterparty tests pass with both oracles live against api.counterparty.io (74 pack tests including the previously failing issuance case).
  • E2E locally: compose/send/mpma.spec.ts 6/6.

https://claude.ai/code/session_01CcjnCrgosSeshymXLBxdGj

The packer rejected any memos_are_hex list containing more than one
distinct value, but composeMPMA filters that list to entries whose memo
is non-empty before choosing the single flag it sends. The MPMA form
emits one flag per row and a row with no memo emits false, so a batch
with one hex memo and one blank memo arrived as "true,false": compose
correctly sent memos_are_hex=true while the packer saw two values and
declined. Byte verification silently dropped to field comparison for
what is a perfectly ordinary CSV -- only some rows carrying memos.

It failed safe, never passing a substitution, but the oracles could not
catch it because every oracle case uses uniform flags. Only the flags
belonging to an actual memo describe the encoding, so the packer now
filters the same way composeMPMA does. A batch with two real memos of
different encodings is still declined, since core's single flag cannot
express it.

The round-trip oracle also needed a fix. Its "nothing could be
rebuilt" guard exists so a type cannot pass vacuously, but it cannot
tell an unrepresentative sample from a broken packer, and real traffic
is bursty: every one of the 100 most recent issuances was a locked
subasset, which the borrow guard declines by design, so the issuance
case failed on healthy code. Principled declines are now counted, and
when nothing was compared the assertion is that every sample was one of
them -- a sample that was attempted and still could not be rebuilt
still fails. The window is also wider, which makes the situation rarer.

Claude-Session: https://claude.ai/code/session_01CcjnCrgosSeshymXLBxdGj
@droplister
droplister merged commit 5f86131 into main Aug 3, 2026
71 of 73 checks passed
@droplister
droplister deleted the fix/mpma-memo-flag-coverage branch August 3, 2026 23:32
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