Skip to content

feat(antd): gRPC UploadService + chunks prepare/finalize - #140

Merged
Nic-dorman merged 2 commits into
mainfrom
nic/v2-284-grpc-external-signer-prepare-finalize
May 28, 2026
Merged

Nic-dorman merged 2 commits into
mainfrom
nic/v2-284-grpc-external-signer-prepare-finalize

Conversation

@Nic-dorman

Copy link
Copy Markdown
Member

Summary

External-signer two-phase upload + single-chunk publish are now reachable over gRPC, closing the long-standing REST-only gap. Mirrors the REST wire shape 1:1 — same server-side state and the same call sequence as antd/src/rest/{upload,chunks}.rs.

Proto changes

  • New antd/proto/antd/v1/upload.proto with UploadService { PrepareFileUpload, PrepareDataUpload, FinalizeUpload }. Separate prepares for file vs in-memory data (different request shapes) but a single shared finalize keyed by upload_id, mirroring the REST handler that already handles both source types from state.pending_uploads.
  • chunks.proto extended with PrepareChunk / FinalizeChunk on the existing ChunkService. Single-chunk publishes are always wave-batch.
  • common.proto adds shared PaymentEntry (used by both upload and chunk prepare responses).

Handler changes (antd/src/grpc/service.rs)

  • New UploadServiceImpl with the three RPCs, plus a build_grpc_prepare_response helper that's the gRPC counterpart of REST's build_prepare_response.
  • New prepare_chunk / finalize_chunk methods on ChunkServiceImpl.
  • Both wave-batch and merkle finalize paths are implemented, mirroring REST. Validation that exactly one of tx_hashes (wave-batch) or winner_pool_hash (merkle) is supplied; otherwise invalid_argument. Path-canonicalisation on PrepareFileUpload, matching REST.
  • Closures that build tx_hash_map return AntdError rather than Status so clippy::result_large_err stays quiet; conversion happens at the boundary.

Upstream prerequisites — both already on main

Follow-up — not in this PR

11 gRPC-capable SDKs (antd-cpp, antd-csharp, antd-dart, antd-elixir, antd-go, antd-java, antd-kotlin, antd-py, antd-ruby, antd-rust, antd-swift) currently throw UnsupportedOperationException / NotSupportedException on their *GrpcClient for these methods (stubbed during the REST fan-out in #90). Each SDK will replace its stubs with real gRPC calls + mock-server tests in separate PRs.

Test plan

  • cargo check clean
  • cargo clippy -- -D warnings clean
  • cargo fmt --check clean
  • cargo test --bins — 37/37 (no regressions)
  • cargo audit — no new advisories (5 pre-existing upstream warnings unchanged)
  • Reviewer: spin antd, dial the new RPCs with grpcurl or the regen'd stubs from a follow-up SDK PR, exercise the wave-batch and merkle paths end-to-end against a --enable-evm devnet.

External-signer two-phase upload + single-chunk publish are now reachable
over gRPC, closing the long-standing REST-only gap. Mirrors the REST wire
shape 1:1 — same `pending_uploads` / `pending_chunks` state, same
`file_prepare_upload_with_visibility` / `data_prepare_upload_with_visibility`
/ `finalize_upload` / `finalize_upload_merkle` / `prepare_chunk_payment` /
`finalize_chunk` call sequence as `antd/src/rest/{upload,chunks}.rs`.

Proto changes:

* New `antd/proto/antd/v1/upload.proto` with `UploadService { PrepareFileUpload,
  PrepareDataUpload, FinalizeUpload }`. Separate prepares for file vs in-memory
  data (different request shapes) but a single shared finalize keyed by
  `upload_id`, mirroring REST's `/v1/upload/finalize` handler that handles
  both source types from `state.pending_uploads`.
* `chunks.proto` extended with `PrepareChunk` / `FinalizeChunk` on the
  existing `ChunkService`. Single-chunk publishes are always wave-batch.
* `common.proto` adds shared `PaymentEntry` (used by both upload and chunk
  prepare responses).

Handler changes (`antd/src/grpc/service.rs`):

* New `UploadServiceImpl` with the three RPCs, plus a `build_grpc_prepare_response`
  helper that's the gRPC counterpart of REST's `build_prepare_response`.
* New `prepare_chunk` / `finalize_chunk` methods on `ChunkServiceImpl`.
* Both wave-batch and merkle finalize paths are implemented, mirroring REST.
  Validation that exactly one of `tx_hashes` (wave-batch) or `winner_pool_hash`
  (merkle) is supplied; otherwise `invalid_argument`. Path-canonicalisation on
  `PrepareFileUpload`, matching REST.
* Closures that build `tx_hash_map` return `AntdError` (small) rather than
  `Status` (>=176 bytes) so `clippy::result_large_err` stays quiet; conversion
  happens at the boundary.

Upstream prerequisites — both already on main, no further upstream work
needed:

* `ant-core` `Client::data_prepare_upload_with_visibility` merged in
  `WithAutonomi/ant-client` #73 (2026-05-05).
* antd REST wiring merged in #138 (2026-05-27).

Follow-up not in this PR: 11 gRPC-capable SDKs (antd-cpp, antd-csharp,
antd-dart, antd-elixir, antd-go, antd-java, antd-kotlin, antd-py, antd-ruby,
antd-rust, antd-swift) currently throw `UnsupportedOperationException` /
`NotSupportedException` on their `*GrpcClient` for these methods (stubbed
during the REST fan-out in #90). Each SDK will replace its stubs with real
gRPC calls + mock-server tests in separate PRs.

Gates passed on dev2:

* `cargo check` clean
* `cargo clippy -- -D warnings` clean
* `cargo fmt --check` clean
* `cargo test --bins` — 37/37 (no regressions)
* `cargo audit` — no new advisories (5 pre-existing upstream warnings)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The trait gains these methods when chunks.proto adds the new RPCs.
Real mock-server impls live in the antd-rust V2-284 fan-out PR; here
we stub with unimplemented!() so the proto-only daemon PR still
compiles antd-rust against the same proto tree.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Nic-dorman
Nic-dorman merged commit 68ebfd2 into main May 28, 2026
3 checks passed
@Nic-dorman
Nic-dorman deleted the nic/v2-284-grpc-external-signer-prepare-finalize branch May 28, 2026 15:47
Nic-dorman added a commit that referenced this pull request May 28, 2026
Adds 3 new methods on AntdGrpcClient mirroring REST AntdRestClient:

* walletAddress() async throws -> WalletAddress
* walletBalance() async throws -> WalletBalance
* walletApprove() async throws -> Bool

Implementation notes:

* Sets up the same swift proto-codegen infrastructure the V2-284 swift
  fan-out PR (#151) added — scripts/generate-protos.sh, Package.swift
  GRPCCore dep, AntdClient.createGrpc factory marked @available, etc.
  When #151 merges first, expect a trivial merge conflict on the proto
  files (same files generated by the same script, just both proto
  sets); when this lands first, #151 rebases and adds upload.proto +
  prepare/finalize methods.
* The script's proto compile list intentionally OMITS upload.proto so
  this PR is self-contained (upload.proto is added by the V2-284
  daemon PR #140, not this PR).
* AntdGrpcClient.swift is rewritten from the prior all-stubs placeholder.
  Other RPCs (health/data/files/chunks/prepare/finalize) still throw
  notImplemented() — out of V2-286 scope. Only wallet is implemented.
* Per-call withGRPCClient(transport: .http2NIOPosix(...)) — same shape
  as #151's pattern.
* A missing daemon wallet emits gRPC failedPrecondition; the existing
  ErrorMapping.fromGRPCStatus surfaces it as PaymentError (established
  FailedPrecondition->Payment convention across all SDKs).

Tests (Tests/AntdSdkTests/GrpcWalletTests.swift, new):

* In-process grpc-swift server on 127.0.0.1:0 with MockWalletService
  (SimpleServiceProtocol implementation).
* 4 tests: address, balance, approve, plus the unconfigured-wallet
  PaymentError path.

Gates on dev2:

* swift build — clean.
* swift test — 27/27 passing (23 existing + 4 new wallet).

Depends on the antd-side daemon PR landing first.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Nic-dorman added a commit that referenced this pull request May 28, 2026
Closes the gRPC parity gap with REST: external-signer (UploadService +
chunks PrepareChunk/FinalizeChunk) and WalletService are now reachable
over gRPC, plus stream-download stubs return honest UNIMPLEMENTED/501
instead of pretending. All 11 gRPC-capable SDKs follow with matching
fan-out.

## Additive (antd daemon)

- gRPC UploadService + chunks prepare/finalize — external-signer two-phase
  upload + single-chunk publish over gRPC, mirroring REST 1:1 (#140)
- gRPC WalletService — GetAddress / GetBalance / Approve, parity with
  REST /v1/wallet/* (#154)
- /v1/data/prepare now honors visibility for public DataMap chunk
  bundling via data_prepare_upload_with_visibility (#138)

## Fixes (antd daemon)

- Stream-download stubs (DataServiceStub.StreamDownload, REST
  /v1/data/stream/*) now return UNIMPLEMENTED / 501 honestly rather
  than empty success (#155)

## SDK fan-out — external-signer (gRPC prepare/finalize)

All 11 gRPC-capable SDKs replace their stub raises with real gRPC calls
to the new UploadService + ChunkService PrepareChunk/FinalizeChunk RPCs:

- antd-rust (#169), antd-go (#170), antd-py (#171), antd-java (#172),
  antd-kotlin (#173), antd-csharp (#174), antd-ruby (#175),
  antd-dart (#176), antd-swift (#177), antd-cpp (#178),
  antd-elixir (#179)

## SDK fan-out — WalletService

Same 11 SDKs gain walletAddress / walletBalance / walletApprove over gRPC:

- antd-rust (#180), antd-go (#181), antd-py (#182), antd-java (#183),
  antd-kotlin (#184), antd-csharp (#185), antd-ruby (#186),
  antd-dart (#187), antd-swift (#188), antd-cpp (#189),
  antd-elixir (#190)

## SDK examples + build fixes

- antd-ruby: payForQuotes tuple args as Hash for eth-0.5.13
  compatibility (#131)
- antd-go + ant-dev: add 03-chunks + 06-private-data examples;
  renumber 03-files to 04-files (#132)
- antd-java + antd-cpp: close async client surface gaps (#133)
- ant-dev: pull antd[rest,grpc] extras so 08_grpc example runs out
  of the box (#134)
- antd-js + antd-py + antd-go READMEs: surface external-signer
  methods + 07 example (#135)
- antd-elixir: 07_external_signer example via cast shell-out (#136)
- antd-swift: 07_external_signer example + fix FinalizeUploadDTO
  optional address (#137)
- antd-php: empty tx_hashes serializes as JSON object on finalize
  (#139)

## FFI

- ant-ffi refresh against current ant-core API + Swift xcframework
  build pipeline (#150)
- Android AAR build pipeline (#156)

## Infra

- CI: auto-tag Go submodules on umbrella release tag push (#129)
- Deploy: publish multi-arch withautonomi/antd image from ant-sdk
  release (#130)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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