feat(antd, antd-go): external-signer single-chunk publish#61
Merged
Conversation
Mirrors PR #31's release.yml fix — without `repo-token`, the action issues the GitHub release-list API call anonymously and shares the ~60/hr per-IP quota with every other runner on the same egress IP. release.yml has had the auth since 2026-04-28; ci.yml didn't, and PR #57's post-merge CI run flaked here on 2026-05-06 (run 25447450352 job 'API contract tests (antd-rust)' — exact `arduino/setup-protoc@v3 ... API rate limit exceeded` message reproduced from PR #31's investigation). Adds `repo-token: \${{ secrets.GITHUB_TOKEN }}` to both occurrences in ci.yml — the Check (antd) job at line 33 and the API contract tests job at line 75. No semantic change to either workflow; just shifts the action onto our 5,000/hr token quota. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds `POST /v1/chunks/prepare` + `POST /v1/chunks/finalize` to the antd REST surface and `PrepareChunkUpload` + `FinalizeChunkUpload` to antd-go, giving external signers a way to publish a single chunk paid through their own EVM wallet rather than the daemon's. ## antd (Rust) - `state.rs`: new `pending_chunks: Mutex<HashMap<String, TimestampedChunk>>` map alongside `pending_uploads`, with matching `cleanup_stale_chunks`. Single periodic cleanup task in `main.rs` now sweeps both. - `types.rs`: `PrepareChunkRequest/Response` + `FinalizeChunkRequest/Response`. Response uses `skip_serializing_if` heavily so an already-on-network reply (`already_stored: true`) carries only `address` — no upload_id, no payments. - `rest/chunks.rs::chunk_prepare`: calls `Client::prepare_chunk_payment`, computes the BLAKE3 address up-front (so the already-stored exit can still return it), filters zero-amount quotes from the external-signer payment list, and stashes the PreparedChunk under a fresh upload_id. - `rest/chunks.rs::chunk_finalize`: looks up by upload_id, parses tx_hashes, calls the new `Client::finalize_chunk`, returns the chunk address. Unlike `POST /v1/chunks` (which requires `AUTONOMI_WALLET_KEY` on the daemon), neither new endpoint touches the daemon's wallet — funds flow through the external signer. ## antd-go - New `PrepareChunkResult` type mirroring the response shape. - `PrepareChunkUpload(ctx, content)` + `FinalizeChunkUpload(ctx, uploadID, txHashes)`. - `boolField` helper joins the existing `str`/`num64`/`unum64` helpers. - Three new httptest-backed tests: happy-path prepare, already-stored prepare, finalize round-trip. ## Dep pin `antd/Cargo.toml` pins ant-core to the merge commit of WithAutonomi/ant-client#89 (`c0f6a81`) which adds the `Client::finalize_chunk` primitive this PR consumes. The pin should be bumped to a tag once ant-core cuts a release containing that commit; the rev pin keeps reproducibility in the meantime. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Collaborator
Author
E2E smoke result — PASSED on Arbitrum One mainnetDrove Things this confirms:
|
Nic-dorman
added a commit
that referenced
this pull request
May 13, 2026
Cuts v0.7.0 atop v0.6.1. Adds external-signer single-chunk publish: - feat(antd, antd-go): external-signer single-chunk publish (#61) - POST /v1/chunks/prepare — wave-batch payment shape for a single chunk, no daemon wallet required. Returns already_stored=true with just the address when the chunk is already on-network. - POST /v1/chunks/finalize — submits the chunk after the external signer has paid, returns the network address. - antd-go: PrepareChunkUpload(ctx, content) and FinalizeChunkUpload(ctx, uploadID, txHashes). - Bumps ant-core to a rev containing the new Client::finalize_chunk primitive (ant-client#89). End-to-end smoke verified against Arbitrum One mainnet: random 256-byte payload round-tripped via prepare → payForQuotes (external wallet) → finalize → ChunkGet with full byte equality.
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.
Summary
Adds external-signer single-chunk publish to both halves of the SDK:
POST /v1/chunks/prepare+POST /v1/chunks/finalize. UnlikePOST /v1/chunks(which requiresAUTONOMI_WALLET_KEYon the daemon), neither new endpoint touches the daemon's wallet. Funds flow through the external signer'spayForQuotes()exactly like the existing file/data prepare-and-finalize flow.PrepareChunkUpload(ctx, content)+FinalizeChunkUpload(ctx, uploadID, txHashes), plus thePrepareChunkResulttype.Why
Today's
POST /v1/chunksis daemon-wallet-only. Consumers that run antd wallet-less and pay externally (Indelible is the concrete one) have no way to publish single chunks through their own EVM signer. The existing file/data prepare/finalize endpoints don't help — those self-encrypt the input bytes into a multi-chunkDataMap-of-the-bytes, which is the wrong shape when you want to publish an already-serialized chunk verbatim at its content address.A concrete trigger: a downstream republish flow (78 pre-existing private DataMaps that need to become public) wants to take serialized DataMap bytes already stored locally, publish them as one chunk each, and pay through its own signer rather than provisioning a hot wallet on antd. After this lands, that becomes a normal SDK call.
Surface
antd REST
Wave-batch only. Single-chunk publishes don't need merkle batching — one chunk's worth of quotes is well below the wave-batch threshold.
antd-go
Implementation notes
state.rs: newpending_chunks: Mutex<HashMap<String, TimestampedChunk>>map alongside the existingpending_uploads, with matchingcleanup_stale_chunks. The periodic cleanup task inmain.rsnow sweeps both.chunk_preparecomputes the BLAKE3 address up-front so the already-stored exit can return it without ant-core needing to (ant-core'sprepare_chunk_paymentshort-circuits withOk(None)in that case).paymentsarray — they still live inpeer_quotesforProofOfPayment, but the external signer shouldn't pay for them.GET /v1/chunks/{addr}andPOST /v1/chunks, so axum routes them correctly without precedence games.types.rsuseskip_serializing_ifheavily so the already-stored response carries onlyaddress— noupload_id, no payment fields. Test coverage locks the wire shape.ant-core dep pin
antd/Cargo.tomlcurrently pins ant-core to the merge commit of WithAutonomi/ant-client#89 (c0f6a81), which adds theClient::finalize_chunkprimitive this PR consumes. The rev pin will be bumped to a tag once ant-core cuts a release containing that commit.Test plan
cargo buildcleancargo test— 37 tests pass (6 new type/serialization tests for the chunk surface)go build ./...clean (antd-go)go test ./...— full suite passes (3 new httptest-backed tests forPrepareChunkUpload/FinalizeChunkUpload)GET /v1/chunks/{addr}and confirm byte-equality🤖 Generated with Claude Code