Skip to content

feat(btc-mapping-contract): add paginated map/confirmSpend wasm exports - #20

Open
miloridenour wants to merge 2 commits into
mainfrom
feat/btc-mapping-pagination
Open

feat(btc-mapping-contract): add paginated map/confirmSpend wasm exports#20
miloridenour wants to merge 2 commits into
mainfrom
feat/btc-mapping-pagination

Conversation

@miloridenour

Copy link
Copy Markdown
Collaborator

Introduces a content-addressed page-commit protocol so oversized map and confirmSpend submissions can ride over VSC L2's MAX_TX_SIZE=16384 byte per-tx ceiling without either side making assumptions about chunk size or number.

Wire format (see contract/mapping/pagination.go):

  • Clients submit N pages via the new mapPage / confirmSpendPage wasm exports, each carrying {parent_id, page_idx, total_pages, payload}.
  • parent_id = hex(sha256(raw-payload)) computed by the relay BEFORE chunking; rebinding is impossible because the contract verifies the hash at assembly time.
  • payload is the base64 (URL alphabet, no padding) chunk of the full payload — chosen over raw bytes to avoid the up-to-6x JSON string escape blow-up that would otherwise break the L2 cap.
  • PagePayloadKind (Map | ConfirmSpend) namespaces parent_ids so the two channels cannot cross-collide even with identical hashes.

Assembly semantics (SubmitPage):

  • Idempotent: duplicate page indices are no-ops.
  • Hash-bound: concatenating the decoded chunks and re-hashing MUST equal parent_id, otherwise the terminal SubmitPage aborts.
  • Size/range checks: total_pages > 0, page_idx < total_pages, per- parent max-pages cap, per-page byte cap.
  • Bitmap is monotone: a page, once accepted, is never un-accepted.
  • Replay after completion is a no-op — no double-processing.

Types (contract/mapping/types.go):

  • MapPageParams and ConfirmSpendPageParams.
  • Regenerated tinyjson marshalers.

Tests (contract/mapping/pagination_test.go): 13 scenarios covering single-page completion, multi-page in- and out-of-order assembly, duplicate-page no-op, content-hash mismatch rejection, total-pages mismatch rejection, kind independence, out-of-range page index, zero total_pages, max-pages-per-parent cap, oversize chunk rejection, post- completion replay no-op, and the monotone-bitmap invariant.

The protocol is formally specified in magi-lean/MagiLean/Security/ MappingBot.lean; concrete base64 wire form is documented there as the PageBytes instantiation that keeps PagePlanFitsL2 tight against the L2 tx size bound.

Made-with: Cursor

Introduces a content-addressed page-commit protocol so oversized `map`
and `confirmSpend` submissions can ride over VSC L2's MAX_TX_SIZE=16384
byte per-tx ceiling without either side making assumptions about chunk
size or number.

Wire format (see contract/mapping/pagination.go):
- Clients submit N pages via the new `mapPage` / `confirmSpendPage`
  wasm exports, each carrying {parent_id, page_idx, total_pages,
  payload}.
- `parent_id` = hex(sha256(raw-payload)) computed by the relay BEFORE
  chunking; rebinding is impossible because the contract verifies the
  hash at assembly time.
- `payload` is the base64 (URL alphabet, no padding) chunk of the full
  payload — chosen over raw bytes to avoid the up-to-6x JSON string
  escape blow-up that would otherwise break the L2 cap.
- PagePayloadKind (Map | ConfirmSpend) namespaces parent_ids so the two
  channels cannot cross-collide even with identical hashes.

Assembly semantics (SubmitPage):
- Idempotent: duplicate page indices are no-ops.
- Hash-bound: concatenating the decoded chunks and re-hashing MUST
  equal parent_id, otherwise the terminal SubmitPage aborts.
- Size/range checks: total_pages > 0, page_idx < total_pages, per-
  parent max-pages cap, per-page byte cap.
- Bitmap is monotone: a page, once accepted, is never un-accepted.
- Replay after completion is a no-op — no double-processing.

Types (contract/mapping/types.go):
- MapPageParams and ConfirmSpendPageParams.
- Regenerated tinyjson marshalers.

Tests (contract/mapping/pagination_test.go): 13 scenarios covering
single-page completion, multi-page in- and out-of-order assembly,
duplicate-page no-op, content-hash mismatch rejection, total-pages
mismatch rejection, kind independence, out-of-range page index, zero
total_pages, max-pages-per-parent cap, oversize chunk rejection, post-
completion replay no-op, and the monotone-bitmap invariant.

The protocol is formally specified in magi-lean/MagiLean/Security/
MappingBot.lean; concrete base64 wire form is documented there as the
`PageBytes` instantiation that keeps PagePlanFitsL2 tight against the
L2 tx size bound.

Made-with: Cursor
Switch pagination identity to per-submitter txid lanes, add retention-bound pruning hooks, and enforce paused-state parity on paginated exports to remove front-running lockouts and state leaks.

Made-with: Cursor
@miloridenour
miloridenour force-pushed the feat/btc-mapping-pagination branch from 90b74d6 to 5ada48f Compare April 28, 2026 22:45
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.

2 participants