feat(btc-mapping-contract): add paginated map/confirmSpend wasm exports - #20
Open
miloridenour wants to merge 2 commits into
Open
feat(btc-mapping-contract): add paginated map/confirmSpend wasm exports#20miloridenour wants to merge 2 commits into
miloridenour wants to merge 2 commits into
Conversation
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
force-pushed
the
feat/btc-mapping-pagination
branch
from
April 28, 2026 22:45
90b74d6 to
5ada48f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Introduces a content-addressed page-commit protocol so oversized
mapandconfirmSpendsubmissions 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):
mapPage/confirmSpendPagewasm 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.payloadis 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.Assembly semantics (SubmitPage):
Types (contract/mapping/types.go):
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
PageBytesinstantiation that keeps PagePlanFitsL2 tight against the L2 tx size bound.Made-with: Cursor