diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 195c1e79..28f87cbd 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -26,24 +26,51 @@ env: EHTERSCAN_API_KEY_ETHEREUM: ${{ secrets.EHTERSCAN_API_KEY_ETHEREUM }} INFURA_API_KEY: ${{ secrets.INFURA_API_KEY }} DWELLIR_API_KEY: ${{ secrets.DWELLIR_API_KEY }} + TRONGRID_API_KEY: ${{ secrets.TRONGRID_API_KEY }} WALLET_CONNECT_PROJECT_ID: ${{ secrets.WALLET_CONNECT_PROJECT_ID }} DEBUG_GOOGLE_OAUTH_ID: ${{ secrets.DEBUG_GOOGLE_OAUTH_ID }} RELEASE_GOOGLE_OAUTH_ID: ${{ secrets.RELEASE_GOOGLE_OAUTH_ID }} jobs: codeql: - name: CodeQL Analysis - runs-on: [self-hosted, wallet] - if: github.event_name == 'push' # Only run on push, not PRs (self-hosted security) + # Advanced setup, because default setup analyses Java without a build and leaves out every + # Kotlin file, which is nearly all of this app. + name: CodeQL (${{ matrix.language }}) + runs-on: ubuntu-latest + timeout-minutes: 120 + strategy: + fail-fast: false + matrix: + include: + - language: actions + build-mode: none + - language: javascript-typescript + build-mode: none + - language: rust + build-mode: none + - language: java-kotlin + build-mode: manual steps: + - name: Free disk space + if: matrix.language == 'java-kotlin' + run: | + # The CodeQL bundle in the tool cache is kept: the init step below uses it. + sudo rm -rf /usr/share/dotnet /usr/share/swift /opt/ghc /usr/local/.ghcup \ + /usr/local/share/boost /usr/local/share/powershell \ + /usr/local/lib/node_modules /usr/local/julia* /opt/microsoft + sudo docker image prune -af > /dev/null 2>&1 || true + df -h / + - name: Checkout uses: actions/checkout@v4 - name: Install dependencies + if: matrix.language == 'java-kotlin' uses: ./.github/workflows/install/ - name: Set up DEV Google Services + if: matrix.language == 'java-kotlin' uses: davidSchuppa/base64Secret-toFile-action@v3 with: secret: ${{ secrets.CI_DEVELOP_GOOGLE_SERVICES }} @@ -51,17 +78,25 @@ jobs: destination-path: ./app/ - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@v4 with: - languages: java-kotlin + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} - name: Build for CodeQL - run: ./gradlew assembleDebug -x test -x lint + if: matrix.build-mode == 'manual' + # No Gradle or Kotlin daemon is left running: the analysis after the build needs that memory, and + # with them alive the runner ran out of it during query evaluation. + run: | + ./gradlew assembleDebug -x test -x lint --no-daemon -Pkotlin.compiler.execution.strategy=in-process + free -m env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@v4 + with: + category: /language:${{ matrix.language }} dependency-review: name: Dependency Review diff --git a/app/build.gradle b/app/build.gradle index 92958d34..c5e1438d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,6 +6,10 @@ apply from: "../scripts/versions.gradle" apply from: "../scripts/secrets.gradle" android { + // The NDK that CI installs and the bindings build with. Without it AGP expects its default NDK, + // cannot strip the native libraries: they ship with their debug sections and no native-debug-symbols.zip is made. + ndkVersion "26.1.10909125" + defaultConfig { applicationId rootProject.applicationId versionCode computeVersionCode() diff --git a/bindings/pezkuwi-light/rust/Cargo.toml b/bindings/pezkuwi-light/rust/Cargo.toml index 720553aa..64a0a93d 100644 --- a/bindings/pezkuwi-light/rust/Cargo.toml +++ b/bindings/pezkuwi-light/rust/Cargo.toml @@ -31,11 +31,11 @@ android_logger = { version = "0.14", default-features = false } env_logger = { version = "0.11", default-features = false, features = ["humantime"] } tungstenite = "0.24" -# Stripped here, not left to the Android Gradle plugin: it packages a library it cannot strip as -# it is, and with debug info this one is 147 MB per ABI instead of 8.6 MB. +# Line tables only: enough for the Play native-debug-symbols.zip to give file and line, at 59 MB +# per ABI before the app strips it to 8.6 MB. Full debug info (`debug = 2`) is 147 MB per ABI. [profile.release] -strip = true -debug = false +strip = false +debug = "line-tables-only" lto = true opt-level = "s" diff --git a/feature-xcm/api/src/main/java/io/novafoundation/nova/feature_xcm_api/multiLocation/MultiLocationEncoding.kt b/feature-xcm/api/src/main/java/io/novafoundation/nova/feature_xcm_api/multiLocation/MultiLocationEncoding.kt index 4d32399e..e0887705 100644 --- a/feature-xcm/api/src/main/java/io/novafoundation/nova/feature_xcm_api/multiLocation/MultiLocationEncoding.kt +++ b/feature-xcm/api/src/main/java/io/novafoundation/nova/feature_xcm_api/multiLocation/MultiLocationEncoding.kt @@ -112,7 +112,6 @@ private fun bindGlobalConsensusJunction(instance: Any?): Junction { "Polkadot" -> Junction.GlobalConsensus(NetworkId.Substrate(Chain.Geneses.POLKADOT)) "Kusama" -> Junction.GlobalConsensus(NetworkId.Substrate(Chain.Geneses.KUSAMA)) - "Westend" -> Junction.GlobalConsensus(NetworkId.Substrate(Chain.Geneses.WESTEND)) "Ethereum" -> { val chainId = bindInt(asDictEnum.value.castToStruct()["chain_id"]) Junction.GlobalConsensus(NetworkId.Ethereum(chainId)) @@ -189,7 +188,6 @@ private fun NetworkId.Substrate.toEncodableInstance(): Any { return when (genesisHash) { Chain.Geneses.POLKADOT -> DictEnum.Entry("Polkadot", null) Chain.Geneses.KUSAMA -> DictEnum.Entry("Kusama", null) - Chain.Geneses.WESTEND -> DictEnum.Entry("Westend", null) Chain.Ids.ETHEREUM -> DictEnum.Entry("Ethereum", null) else -> DictEnum.Entry("ByGenesis", genesisHash.fromHex()) } diff --git a/feature-xcm/api/src/test/java/io/novafoundation/nova/feature_xcm_api/multiLocation/MultiLocationEncodingTest.kt b/feature-xcm/api/src/test/java/io/novafoundation/nova/feature_xcm_api/multiLocation/MultiLocationEncodingTest.kt new file mode 100644 index 00000000..67ac556e --- /dev/null +++ b/feature-xcm/api/src/test/java/io/novafoundation/nova/feature_xcm_api/multiLocation/MultiLocationEncodingTest.kt @@ -0,0 +1,42 @@ +package io.novafoundation.nova.feature_xcm_api.multiLocation + +import io.novafoundation.nova.common.utils.HexString +import io.novafoundation.nova.feature_xcm_api.multiLocation.MultiLocation.Junction.GlobalConsensus +import io.novafoundation.nova.feature_xcm_api.multiLocation.MultiLocation.NetworkId +import io.novafoundation.nova.feature_xcm_api.versions.XcmVersion +import io.novasama.substrate_sdk_android.extensions.toHexString +import io.novasama.substrate_sdk_android.runtime.definitions.types.composite.DictEnum +import org.junit.Assert.assertEquals +import org.junit.Test + +class MultiLocationEncodingTest { + + // PezkuwiChain runtimes declare `ThisNetwork = ByGenesis(..)`, and XCM v5 has no named variant for them + @Test + fun `zagros is encoded by its genesis`() { + assertEncodedByGenesis(ZAGROS) + } + + @Test + fun `pezkuwi is encoded by its genesis`() { + assertEncodedByGenesis(PEZKUWI) + } + + private fun assertEncodedByGenesis(genesis: HexString) { + val location = RelativeMultiLocation(parents = 1, interior = Junctions(GlobalConsensus(NetworkId.Substrate(genesis)))) + + val encoded = location.toEncodableInstanceExt(XcmVersion.V5) + val interior = requireNotNull(encoded.get>("interior")) + val junction = (interior.value as List<*>).single() as DictEnum.Entry<*> + val network = junction.value as DictEnum.Entry<*> + + assertEquals("GlobalConsensus", junction.name) + assertEquals("ByGenesis", network.name) + assertEquals(genesis, (network.value as ByteArray).toHexString(withPrefix = false)) + } + + private companion object { + const val ZAGROS = "1b0b4727bbb5e44ed587d1056b4ad537ffb330034509a58866a088d77e792cd5" + const val PEZKUWI = "1aa94987791a5544e9667ec249d2cef1b8fdd6083c85b93fc37892d54a1156ca" + } +} diff --git a/runtime/src/main/java/io/novafoundation/nova/runtime/ext/ChainExt.kt b/runtime/src/main/java/io/novafoundation/nova/runtime/ext/ChainExt.kt index 97a1d7e7..527366cf 100644 --- a/runtime/src/main/java/io/novafoundation/nova/runtime/ext/ChainExt.kt +++ b/runtime/src/main/java/io/novafoundation/nova/runtime/ext/ChainExt.kt @@ -461,9 +461,6 @@ object ChainGeneses { const val KUSAMA = "b0a8d493285c2df73290dfb7e61f870f17b41801197a149ca93654499ea3dafe" const val POLKADOT = "91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3" - // Westend constant now points to Zagros Testnet - const val WESTEND = "96eb58af1bb7288115b5e4ff1590422533e749293f231974536dc6672417d06f" - const val KUSAMA_ASSET_HUB = "48239ef607d7928874027a43a67689209727dfb3d3dc5e5b03a39bdc2eda771a" const val ACALA = "fc41b9bd8ef8fe53d58c7ea67c794c7ec9a73daf05e6d54b14ff6342c99ba64c"