Commit Graph
5 Commits
Author SHA1 Message Date
SatoshiQaziMuhammed 35c71062f0 Strip native libraries; XCM by genesis; CodeQL for Kotlin; bridge credits in history (#31)
* Strip native libraries in the app and keep light client line tables

The app module named no NDK, so AGP expected its default 27.0 against the 26.1 that CI installs,
could not strip any native library and made no native-debug-symbols.zip for Play. Pin 26.1 in the
app. The light client now keeps line tables for that symbol file; the packaged library is still
stripped to 8.6 MB.

Also adds an XCM encoding test for PezkuwiChain networks. This commit points WESTEND at Zagros
to check that the test fails against that change.

* Fix the encoding test's read of the interior field

* Encode PezkuwiChain networks by genesis in XCM

WESTEND held a stale genesis labelled Zagros. The runtimes declare ThisNetwork as ByGenesis and
the XCM v5 NetworkId has no Westend or Zagros variant, so the named mapping is removed and every
PezkuwiChain network is encoded as ByGenesis.

* Run CodeQL for every language on hosted runners, Kotlin with a build

Default setup analyses Java without a build and leaves out every Kotlin file, and the Java job on the
self-hosted runner stopped at the NDK install because sudo asks for a password, so Kotlin had not been
analysed since February. One matrix job covers actions, JavaScript/TypeScript, Rust and Java/Kotlin.

* Use CodeQL Action v4, v3 is deprecated in December 2026

* Build for CodeQL without Gradle and Kotlin daemons so the analysis has the memory

* Show incoming USDT bridge credits in history without a refresh

The realtime transfer extractor for assets pallets knew only transfer and transfer_keep_alive. The
bridge credits with transfer_approved, spending the multisig's allowance, so a credit appeared only
after the indexer caught up and the user refreshed. transfer_approved is now a transfer from owner to
destination; the signing delegate is not the sender.

* Stop the light client five minutes after RPC is back

A chain registered with the light client kept syncing for as long as the process lived. Measured on
the emulator over 5-minute windows, that was about 14 MB of data an hour and 2% of a core while the
wallet read nothing from it.

Once RPC has stayed connected for five minutes after a fallback, the connection releases the light
client: LightClients unregisters the chain, a relay chain only after its teyrchains. The engine gains
remove_chain. Its database saver now checks, under the registry lock, that the chain is still
registered: smoldot panics on a request to a removed chain. The next fallback starts cold from the
saved database.

* Refresh light client specifications from the signed config while RPC works

The light client started from the checkpoint the APK was built with, so a first fallback months after
a release warp-synced from months back, and on a phone that never fell back there is no saved database
to help. The fallback is wanted when RPC is blocked, and then the config repository may be blocked too.

On the first RPC connection of the process, each chain's specification is fetched from the config
repository through the app's HTTP client, which checks it against the signed targets and falls back to
the mirrors. It is kept when it is the same chain (id and genesis state root) with a later checkpoint;
an older file never rolls the checkpoint back. Registration uses the kept file when it is later than the
APK's own.

* Close the light client's peer connections once its last chain is removed

smoldot keeps its peer-to-peer network service, with the connections in it, for as long as the client
lives, so removing every chain left them open: on the emulator, four libp2p connections were still up
eleven minutes after the release, and data use stayed above the RPC-only level. The engine now
replaces the client once no chain and no loopback connection is left; the connections close about 20 s
later, when the attempts under way finish.

The database saver now checks a per-registration number instead of the smoldot chain id, which smoldot
reuses after a removal: a saver of a removed chain could otherwise keep running for the next chain
that got the same id. A connection whose chain is removed between the handshake and its setup now
ends instead of panicking.

* Obfuscate the app's own classes and build the R8 variant in pull requests

-keep class io.novafoundation.nova.** { *; } with -keepnames left 2.6% of the app's 26,602 classes
renamed in the 1.3.0 Play build (15.6% of all classes). It is replaced by keeping only the field names
of the app's classes, which Gson reads by name where a class has no @SerializedName, so class and method
names are obfuscated. No persisted value or reflective lookup in the app depends on a class or method
name: class names appear only in logs and in an in-memory cache key.

@JavascriptInterface methods had no rule of their own; the blanket keep covered the DApp browser's web3
bridge, its integrity check and the Transak bridge. They are kept explicitly.

Pull requests built only the unminified develop variant, so an R8 break would first show in the Play
build. A second job builds releaseTest (the release rules, debug-signed) and uploads its APK and mapping.

* Give the releaseTest build the debug package, which the CI Firebase config knows

* Build releaseTest under the production package, the one its Firebase config has

* Stop keeping every app class under the JNI rule

-keep class io.novafoundation.nova.** { native <methods>; } keeps every class the pattern matches,
whether or not it has a native method, so the app's class names stayed unobfuscated after the blanket
keep went: 2.6% of its classes were renamed in the R8 build. The rule under it already keeps the names
of classes with native methods and of those methods, which is what JNI binds by name; the Rust
bindings look up no other app class.

* Keep TypeToken and Retrofit generic signatures under R8 full mode

The R8 build failed to map every chain from the local database: R8 full mode keeps generic signatures
only on kept classes, and the app's anonymous TypeToken subclasses had been kept by the blanket rule.
These are the rules Gson 2.11 and Retrofit 2.10 ship; the app is on Gson 2.10.1 and Retrofit 2.9.0.

* Keep constructors of the app's classes so Gson can instantiate its models

The R8 build failed to read the DApp list: R8 full mode had made DappMetadataResponse abstract because
nothing in the code instantiates it, and Gson does so reflectively. It matches none of the name
patterns the rules keep models by. Keeping constructors costs no obfuscation, since they are all named
<init>.

* Keep the type argument of web3j TypeReference subclasses under R8 full mode

* Run R8 in compatibility mode

After the app's own classes became obfuscatable, the full-mode R8 build kept breaking reflective
decoding in new places: TypeToken and TypeReference subclasses lost their type argument, a Gson model
was made abstract, and SubQueryResponse<T> lost its class signature so a proxy query decoded to a
LinkedTreeMap. Full mode keeps generic signatures only on explicitly kept classes, and this code base
has many generic models outside any name pattern. Compatibility mode keeps them everywhere under
-keepattributes Signature and does not make uninstantiated classes abstract; obfuscation is unchanged.

* Allow the java.beans classes Jackson's Java 7 support refers to, missing on Android
2026-11-03 18:07:55 +04:00
SatoshiQaziMuhammed 46d7e66f99 Fix open Dependabot and code scanning alerts (#21)
* build(rust): bump vulnerable crates in native binding lockfiles

- rand 0.8.5 -> 0.8.6 (GHSA-cq8v-f236-94qc) in hydra-dx-math and sr25519-bizinikiwi
- keccak 0.1.5 -> 0.1.6 (GHSA-3288-p39f-rqpv) in hydra-dx-math and sr25519-bizinikiwi
- bytes -> 1.11.1 (GHSA-434x-w66g-qw3r) in hydra-dx-math and metadata_shortener
- time 0.3.41 -> 0.3.47 (GHSA-r6v5-fh4h-64xc) in hydra-dx-math
- tracing-subscriber 0.3.19 -> 0.3.20 (GHSA-xwfj-jgwm-7wp5) in hydra-dx-math

Lockfile-only updates via cargo update --precise; Cargo.toml requirements
are unchanged. time 0.3.47 pulls serde 1.0.229/serde_core and requires
rustc 1.88, which the stable toolchain used by CI satisfies.

* ci: restrict default GITHUB_TOKEN permissions to contents: read

None of these workflows write through GITHUB_TOKEN: artifact upload,
Firebase, S3, Play Store, gh-pages and the Appium dispatch all use their
own credentials. Reusable workflows they call inherit the same cap.

* fix(dapp): send only fixed, JSON-quoted error messages to dApp pages

The polkadot.js responder forwarded Throwable.message of any rejection
error to the page and both responders interpolated the message into
JavaScript without escaping. Map polkadot.js rejections to a fixed public
message (unknown errors become "Request failed"), give MetamaskError an
explicit publicMessage, and quote both with JSONObject.quote so a message
can no longer break out of the string literal.

* ci: stop installing the removed legacy SDK 'tools' package

android-actions/setup-android installs 'tools platform-tools' by default.
sdkmanager now fails with "Failed to find package 'tools'", which aborts
dependency installation for every build and lint job. Only platform-tools
is needed; nothing in the workflows uses the legacy tools directory.
2026-10-03 00:39:49 +04:00
SatoshiQaziMuhammed 4a2fc5681a ci: add workflow_dispatch escape hatch to pull_request.yml (#8)
pull_request-triggered runs of this workflow have stopped firing
entirely for at least one recent PR (no check-suite created at all
for the GitHub Actions app, while two other installed apps sit stuck
in "queued") - root cause is outside what's fixable via the repo's
own Actions config/API access. This adds a manual workflow_dispatch
path (branch input) so a build+test run can still be triggered
directly against any branch while that's being sorted out.
2026-07-07 11:56:50 -07:00
SatoshiQaziMuhammed 87bacc3f7c ci: fix develop PR build signing (validateSigningDevelop) (#4)
* ci: wire develop_key.jks into PR build (fix validateSigningDevelop)

The PR build runs assembleDevelop (signingConfigs.dev = develop_key.jks) but the
reusable workflow only decoded github/market keystores, so validateSigningDevelop
always failed. Add a develop-keystore decode step (reusing the existing
BASE64_DEV_KEYSTORE_FILE secret + CI_KEYSTORE_* passwords) and pass
keystore-file-name: develop_key.jks from pull_request.yml.

[temp] pin reusable workflow to the branch to validate before merge; reverted to
@main in the next commit.

* ci: revert reusable-workflow pin back to @main

Fix validated green on PR #4 (test/Build app and test passed, develop signing
works). Restore @main pin for the final merged state.
2026-06-14 22:51:12 -07:00
Kurdistan Tech Ministry a294aa1a6b Initial commit: Pezkuwi Wallet Android
Security hardened release:
- Code obfuscation enabled (minifyEnabled=true, shrinkResources=true)
- Sensitive files excluded (google-services.json, keystores)
- Branch.io key moved to BuildConfig placeholder
- Updated dependencies: OkHttp 4.12.0, Gson 2.10.1, BouncyCastle 1.77
- Comprehensive ProGuard rules for crypto wallet
- Navigation 2.7.7, Lifecycle 2.7.0, ConstraintLayout 2.1.4
2026-02-12 05:19:41 +03:00