Skip to content

Move gRPC/NIO deps off CocoaPods (provider-or-consumer)#22

Draft
peachbits wants to merge 1 commit into
masterfrom
piratechain-vendored-deps
Draft

Move gRPC/NIO deps off CocoaPods (provider-or-consumer)#22
peachbits wants to merge 1 commit into
masterfrom
piratechain-vendored-deps

Conversation

@peachbits

Copy link
Copy Markdown
Contributor

Move the SDK's gRPC/NIO stack off CocoaPods (provider-or-consumer)

Why

PirateLightClientKit depends on grpc-swift, whose CocoaPods releases stopped at 1.8.0 — 1.24+ is SwiftPM-only. This package still pulled gRPC-Swift ~> 1.8 (plus SQLite.swift) as CocoaPods dependencys, pinning the whole grpc/NIO stack to a 2023-era version.

That collides with react-native-zcash, which now vendors its SDK's SwiftPM deps at grpc-swift 1.27. With both pods in one app (Edge ships both), the app link line carried two grpc stacks at different versions; whichever archive the linker reached first won each shared symbol. Debug (-Onone) masked it; a Release build surfaced the mismatch as undefined DequeModule/NIO-internal symbols.

What

Convert this package to the same compile-SDK-source-in-pod + vendored-SwiftPM-deps architecture as react-native-zcash, unifying the grpc/NIO/Protobuf/SQLite graph at one set of versions:

  • scripts/buildVendoredDeps.ts (new) — builds a throwaway SwiftPM wrapper against the SDK, merges the dependency graph into libPirateDeps.xcframework (device arm64 + fat sim) and harvests the dep .swiftmodules + C module.modulemaps. Pinned by scripts/depsPackage.resolved.
  • scripts/depsPackage.resolved (new) — the graph pinned to the exact versions react-native-zcash resolves (grpc-swift 1.27.3, swift-nio 2.95.0, SwiftProtobuf 1.35.1, SQLite.swift 0.15.5, …). The Pirate SDK's Package.swift uses open ranges, so this keeps the two packages in lockstep.
  • react-native-piratechain.podspec — drops s.dependency "gRPC-Swift" / "SQLite.swift/standalone"; compiles the in-pod SDK source against the harvested modules; adds a Swift-compiler fail-fast stamp check.
  • scripts/updateSources.ts — runs buildVendoredDeps() after the existing SDK-source vendoring.

Provider or consumer — the host app chooses

Two copies of the same dependency graph on one app link line collide under -ObjC (it force-loads every Swift archive member — tens of thousands of duplicate symbols). So exactly one pod may put the graph on the link line. This package builds everything to be either:

  • Provider (default): links its own libPirateDeps.xcframework, fully self-contained — correct for any app that uses piratechain without react-native-zcash.
  • Consumer: an app that also installs react-native-zcash sets ENV['RN_PIRATECHAIN_VENDOR_DEPS'] = 'false' in its Podfile. This pod then omits its own archive from the link and its grpc/NIO symbols resolve from zcash's archive. In both modes the in-pod SDK source still compiles against the harvested modules.

The depsPackage.resolved pin + the compiler stamp guarantee the two archives are ABI-interchangeable, so either pod can be the provider.

Host-side (Edge): add ENV['RN_PIRATECHAIN_VENDOR_DEPS'] = 'false' to the Podfile so piratechain runs as the consumer alongside react-native-zcash (the provider). Ships in the edge-react-gui integration, not here.

Validation

Built + ran the Edge develop app (RN 0.79, iOS 15.6) in Release across all three deps configurations:

Config Link (undef / dup-err / dup-warn) Runtime
zcash-alone (zcash provider, no pirate) 0 / 0 / 0 ZEC wallet opens
zcash + pirate consumer (Edge's config) 0 / 0 / 256¹ ZEC opens + ARRR syncs over grpc (blocks 271k/1.49M)
pirate-alone provider (no zcash) 0 / 0 / 0 ARRR syncs (297k/1.49M)
  • pod install (consumer) → 0 gRPC-Swift / SwiftNIO / CNIO* CocoaPods (was ~90 NIO pods).
  • In consumer mode, an ARRR wallet syncs over grpc/NIO with zero deps of its own — the symbols resolve at app link from zcash's shared libZcashDeps archive. That's the design working end-to-end at runtime.
  • Provider libPirateDeps.xcframework verified: GRPC (14.4k) / NIOCore (27.5k) / SwiftProtobuf (17k) symbols, device arm64 + fat-sim slices.

¹ The 256 dup-symbol warnings are the pre-existing sqlite3_* / _rust_eh_personality overlap between the two Rust cores (libpiratelc vs libzcashlc) — they vanish in the single-core configs above, confirming they're unrelated to this change.

Known issue (likely pre-existing, not a blocker): the first-ever cold open of an ARRR wallet crashed once with a SIGSEGV in an async RNPiratechain.initialize closure (swift_isUniquelyReferenced_nonNull_native on the Swift cooperative pool) — a use-after-free / data race at wallet init. It fired once in ~9 opens and never reproduced (0/6 subsequent opens). The same init path runs in consumer mode without crashing, and this change touches only where grpc/NIO symbols resolve (identical 1.27.3 version/code), not the init logic — so it looks like a latent race in the SDK/bridge, exposed by init timing. Worth a separate issue; definitive attribution = repeat cold-opens on pre-conversion pirate (grpc-1.8 pods).

🤖 Generated with Claude Code

PirateLightClientKit depends on grpc-swift, whose CocoaPods releases stopped at 1.8.0 (1.24+ is SwiftPM-only). This package still pulled gRPC-Swift ~> 1.8 + SQLite.swift as CocoaPods dependencies, pinning the grpc/NIO stack to a 2023-era version that collides with react-native-zcash's vendored grpc-swift 1.27 when both pods ship in one app: two grpc stacks at different versions on one app link line, resolution decided by link order. Debug (-Onone) masked it; Release surfaced it as undefined DequeModule/NIO-internal symbols.

Convert to the same compile-SDK-in-pod + vendored-SwiftPM-deps architecture as react-native-zcash, unifying the graph at one set of versions:

- scripts/buildVendoredDeps.ts: builds a throwaway SwiftPM wrapper against the SDK, merges the dep graph into libPirateDeps.xcframework (device arm64 + fat sim) and harvests the dep .swiftmodules + C module.modulemaps. Pinned by scripts/depsPackage.resolved.
- scripts/depsPackage.resolved: the graph pinned to the EXACT versions react-native-zcash resolves (grpc-swift 1.27.3, swift-nio 2.95.0, SwiftProtobuf 1.35.1, SQLite.swift 0.15.5, ...); the Pirate SDK's Package.swift uses open ranges so this keeps the two packages in lockstep.
- podspec: drops the gRPC-Swift/SQLite.swift CocoaPods dependencies; compiles the in-pod SDK source against the harvested modules; adds a Swift-compiler fail-fast stamp check.

Provider OR consumer, host app chooses: two copies of the same graph on one link line collide under -ObjC (force-loads every Swift archive member). PROVIDER (default) links its own libPirateDeps.xcframework and is self-contained. CONSUMER (host sets ENV['RN_PIRATECHAIN_VENDOR_DEPS']='false' in its Podfile, e.g. Edge alongside react-native-zcash) omits its archive from the link and resolves grpc/NIO symbols from the sibling's. depsPackage.resolved + the compiler stamp make the two archives ABI-interchangeable.

Validated on Edge develop (RN 0.79, iOS 15.6) Release, pirate as CONSUMER: 0 gRPC/NIO CocoaPods, BUILD SUCCEEDED, 0 undefined, 0 duplicate-symbol errors (256 remaining dup WARNINGS are the pre-existing libpiratelc-vs-libzcashlc Rust-core sqlite3/rust_eh_personality overlap). Provider archive verified complete (GRPC/NIOCore/SwiftProtobuf symbols, device + fat-sim slices).

Co-Authored-By: Claude Opus 4.8 <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