Sync upstream (pubky 0.10) + fix Android TLS "Revoked" on pkarr's relay client - #2
Merged
Conversation
Syncs the fork with pubky/pubky-core-ffi@74fea50, which bumps the pubky SDK 0.9.3 → 0.10.0. Taken for a specific reason rather than as routine maintenance: it is half the fix for the Android TLS failure Loopky was hitting in production. rustls-platform-verifier hard-fails revocation checking on Android — Let's Encrypt no longer publishes an OCSP responder, Android's PKIXRevocationChecker only tries OCSP, and the crate's Kotlin half turns the resulting CertPathValidatorException into `StatusCode.Revoked`: invalid peer certificate: Revoked ← CertPathValidatorException: Certificate does not specify OCSP responder That surfaces as `HTTP transport error` and reaches Loopky users as "You're offline". pubky 0.10 builds its **ICANN** client with webpki roots and revocation off (`icann_tls_config_without_revocation_check`). It does not cover pkarr's **relay** client, which is a separate client built from reqwest's defaults and was still failing after this bump — see the following commit, which is the other half. Neither alone made the device stop erroring. Merge notes: - Source merged clean. One fork-only call site needed the 0.10 signature: `put_bytes` now threads a `client_id` through `signin`, matching what upstream did to `put`/`delete_file`/`sign_in`/`sign_up`/`start_auth_flow`. - Every conflict was a generated artifact. Resolved by regenerating rather than picking a side — upstream's binaries are built from upstream's source and carry none of the fork's added functions. Android (4 ABIs, `llvm-strip`ped to match upstream), iOS xcframework and Swift, and the Python bindings are all rebuilt from this tree. - `rustls-platform-verifier` stays a dependency: `cargo tree -i` still shows reqwest 0.13 pulling it in through pkarr 7.0, so `rustls_init.rs` is still load-bearing. Documented in Cargo.toml, along with the 0.10 version floor and the fact that the consuming app must also ship the crate's Kotlin AAR. Not addressed here: `libpubkycore.so` still has a GNU_RELRO segment aligned to 0x1, so it is not 16 KB page-size compatible. Pre-existing and separate.
… verify
The pubky 0.10 bump in the previous commit was necessary and not sufficient. It
fixes revocation checking for the SDK's ICANN client only; pkarr builds its own
relay HTTP client from reqwest's defaults, which on Android still means
rustls-platform-verifier. Measured on-device after the bump: 8 more
`invalid peer certificate: Revoked` failures, every one immediately after
pubky::actors::pkdns: Resolving homeserver for public key … via PKARR
so `_pubky.<key>` resolution that fell back to the relay kept dying, and Home
along with it. Resolutions the DHT answered succeeded, which is exactly why this
looked intermittent rather than total.
pkarr 7 exposes `ClientBuilder::reqwest_client`, and pubky 0.10 exposes
`.pkarr(..)` on its client builder, so the relay client can be handed the same
treatment upstream gave the ICANN one: bundled webpki roots, revocation off.
Reaching it means constructing through `PubkyHttpClient::builder()` +
`Pubky::with_client` instead of `Pubky::new()`/`Pubky::testnet()`.
Dropping revocation checking is upstream's own choice for this problem and the
trade is narrow here: these are relay lookups of public, signed pkarr records,
and the record's signature — not the transport — is what makes the answer
trustworthy.
reqwest goes 0.12 → 0.13 to match. The `reqwest::Client` handed to pkarr is only
type-compatible if it is literally the same crate version, and the fork used
reqwest directly in exactly one place (an admin HTTP call), so this also removes
a duplicate reqwest from the tree rather than adding one. webpki-roots is new,
pinned to the same major pubky uses so both paths trust the same anchors.
Verified on-device (Redmi Note 11, Android 13, release build), same session and
navigation each time:
before #122 42 ClassNotFoundException, every TLS handshake failed
after #122 0 ClassNotFound, 8 "Revoked", Home failed to load
after 0.10 alone still 8 "Revoked" — the relay client
with this change 0 ClassNotFound, 0 TLS failures, 0 transport errors,
0 Loopky errors; session resolves in 1.8s, not 12
All bindings regenerated from this tree; Android libs `llvm-strip`ped.
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.
Two commits: the upstream sync, then the fix it does not cover. Both are needed — measured on-device, neither alone stopped the errors.
The bug
Loopky was reporting "You're offline" on every Pubky-reading screen, on devices with a working connection. Under it:
rustls-platform-verifierhard-fails revocation checking on Android: Let's Encrypt no longer publishes an OCSP responder, Android'sPKIXRevocationCheckeronly tries OCSP, and the crate's Kotlin half turns the resultingCertPathValidatorExceptionintoStatusCode.Revoked. The crate's own escape hatch for this is gated onBuildConfig.TEST, so it never applies to a shipped app, and 0.7.0 is the latest release and still carries the bug (their PR #179 is the pending real fix). There is no version to upgrade to.Upstream
pubky/pubky-core-ffihas this too — samerustls-platform-verifier = "0.7.0", samesrc/rustls_init.rs. Anyone shipping it on Android is exposed.Commit 1 — sync to upstream@74fea50 (pubky 0.10)
pubky 0.10 builds its ICANN client with webpki roots and revocation off (
icann_tls_config_without_revocation_check). That is half the fix.put_bytesthreads aclient_idthroughsignin, matching what upstream did toput/delete_file/sign_in/sign_up/start_auth_flow.llvm-stripped to match upstream), iOS xcframework + Swift, and Python are all rebuilt from this tree.Commit 2 — the half 0.10 does not reach
pkarr builds its relay HTTP client from reqwest's defaults, which on Android is still the platform verifier. After the bump alone the device logged 8 more
Revokedfailures, every one immediately after:So
_pubky.<key>resolutions that fell back to the relay kept dying. Resolutions the DHT answered succeeded — which is exactly why this presented as intermittent rather than total.pkarr 7 exposes
ClientBuilder::reqwest_clientand pubky 0.10 exposes.pkarr(..), so the relay client gets the same treatment upstream gave the ICANN one. Reaching it means constructing throughPubkyHttpClient::builder()+Pubky::with_client.Dropping revocation checking is upstream's own choice for this problem, and the trade is narrow here: these are relay lookups of public, signed pkarr records, and the record's signature — not the transport — is what makes the answer trustworthy.
reqwestgoes 0.12 → 0.13 to match: the client handed to pkarr is only type-compatible at the same crate version, and the fork used reqwest directly in exactly one place, so this removes a duplicate reqwest from the tree rather than adding one.Verified on-device
Redmi Note 11, Android 13, release build, same account and navigation each time:
Not addressed
libpubkycore.sostill has aGNU_RELROsegment aligned to0x1, so it is not 16 KB page-size compatible. Pre-existing, and a Play blocker in its own right.