Android App with Local Nodes
This guide explains how to run the full Interstellar stack locally using Docker or Podman. You will be able to launch the Substrate node, Integritee TEE worker, and IPFS service, then interact with the system using the Interstellar Android demo app.
This setup enables full offline testing without relying on a hosted VPS.
This milestone delivers the core transaction signing capabilities of the Interstellar platform for multiple blockchains coins: DOT, ETH, BTC, SOL.
All features have been extensively tested with a focus on user experience, demonstrating how simple, reliable, and intuitive these flows can be. The current interface has been adjusted to support efficient testing, while leaving room for further UX and UI refinements in the production-grade SDK.
Although the system is not yet production-ready, it provides a robust foundation. Broader edge case coverage, interoperability, and resilience guarantees will be the focus of the upcoming SDK and future milestones. Reviewers are encouraged to focus on the functional flow and experience of the key features in this milestone.
This compatibility note applies to the backend stack, tested on Ubuntu 24.04 LTS (x86_64) using Docker (docker-compose) or Podman (with manually installed podman-compose*).
The stack is expected to work on other recent Linux distributions, but this has not been officially verified.
Known issue: May fail on Apple Silicon (M1/M2/M3/M4) - due to current SIMD usage and QEMU/Rosetta limitations - crash on M1/M2 (not tested on M3/M4)
The frontend (e.g., Android emulator or physical device) can run on any OS supported by Android Studio (expect some emulator limitations on Apple Silicon)
*Compose tools are required to manage service startup dependencies (e.g., health checks).
1. Prerequisitesβ
| Requirement | Install Guide |
|---|---|
| Docker | Install Docker |
| Docker Compose | Install docker-compose |
curl, wget, jq | Installed via apt/brew or default in most environments |
| Android Studio | Install Android Studio |
ADB (adb reverse) | Comes with Android Studio |
You may also use Podman as an alternative to Docker.
2. Launch the Interstellar Stack Installβ
The BTC worker connects to a Bitcoin Testnet RPC endpoint using a hosted provider.
For simplicity, we provide curators with a ready-to-use .env file.
Place the file in the same directory as docker-compose.yml.
It contains a single variable:
BITCOIN_TESTNET_API_KEY=<API_KEY_WE_SEND>
β οΈ If you prefer to use your own provider, simply replace the value of BITCOIN_TESTNET_API_KEY in .env.
# Step 1: Create a working directory
mkdir interstellar_m2_demo && cd interstellar_m2_demo
# Step 2: Download the stack config
curl -L -o docker-compose.yml https://raw.githubusercontent.com/Interstellar-Network/containers/refs/tags/testnet-m2/docker-compose.yml
curl -L -o docker-ipfs-init.sh https://raw.githubusercontent.com/Interstellar-Network/containers/refs/tags/testnet-m2/docker-ipfs-init.sh
chmod +x docker-ipfs-init.sh
# Step 3: Place the .env file we send in this directory
# Step 3: Start Docker (if needed)
sudo service docker start # (for most Linux distros)
# Step 4: Launch the stack
sudo docker compose down --timeout 1 && sudo docker compose up --force-recreate
β³ Waiting for Master Circuit Generationβ
Once the node and service are running, the system will automatically trigger the generation of master circuits from the hardware description files.
These circuits are compiled using the Verilog logic generated from the original master circuits specifications, processed through the logic synthesis pipeline. This step may take several minutes depending on the environment.
During this time, monitor the logs and wait for the following sequence of messages:
[ocw-circuits] callback_new_skcd_signed sent number : <number> 1-Success - 0-Fail
[ocw-circuits] callback_new_display_circuits_package_signed: (<CID_1>, <message_digits_number>), (<CID_2>, <pinpad_digits_number>) for <account_id>
Shortly before these messages, you will also see large blob uploads to IPFS such as:
Requested started id=<...> method=POST uri=http://ipfs:5001/api/v0/add
These blobs correspond to the master visual circuits (SKCD display circuits), which are the result of the hardware synthesis pipeline. Their appearance in the logs is a strong indicator that the build process has completed.
βΉοΈ You can identify this moment easily by spotting two large IPFS file hashes being logged together β one for the secure keypad circuit and one for the display message circuit i.e one time code These hashes will later be used for visual challenge rendering and validation.
Detailed example from integritee_node-1
Requested started id=1059 method=POST uri=http://ipfs:5001/api/v0/add
[fetch_from_remote_grpc_web] content_type: application/json
[ocw-circuits] callback_new_skcd_signed sent number : 1
[ocw-circuits] callback_new_display_circuits_package_signed: ("QmUx8mMo8GgGdUhcgFQVg2sexkVfyq1sViruZiBadUfs4d",2),("QmcwXyZNmLXnjeoA25YSzj41G1sr6ZsHgZZBQVWvcfe1qn",10) for d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d (5GrwvaEF...)
[ocw-circuits] Hello from pallet-ocw-circuits.
π Idle (0 peers), best: #6 (...), finalized #3 (...), β¬ 0 β¬ 0
You can also verify the runtime is ready using Polkadot.js
While waiting for the stack to fully initialize, you can explore the architecture and rationale behind
the VCA System Layer. This layer is responsible for producing the VCA Token,
the core cryptographic artifact used by the Trusted Action Validation Protocol (TAVP).
The token is generated through a hardware-secure pipeline starting from VHDL logic descriptions, synthesized into
Verilog and compiled using theYosis and abc logic synthesis toolchain. The resulting master circuits define both the secure display and interaction logic β including the Secure Circuit Descriptor (scd) and its runtime variant, skcd, used for verifiable evaluation.
Once built, these circuits are uploaded to IPFS and used to enable real-time, privacy-preserving visual cryptographic challenges, ensuring each critical user interaction is verifiable and resistant to malware, phishing, and adversarial AI.
3. Install the Android Demo Appβ
Download the APKβ
From the official Interstellar GitHub Release (specific APKs preconfigured to connect to localhost):
androidApp-arm64-release.apkβ for Android devices and Apple Silicon(M1/M2/M3/M4)androidApp-x86_64-release.apkβ for Android emulators running on x86_64 platforms (e.g., Windows PCs, Intel-based Mac)
While the app runs on Apple Silicon (M1βM4), emulator performance may vary due to ARM virtualization and GPU constraints. For accurate testingβespecially for Rust-based rendering and cryptographic logicβchoose the best available setup:
| Recommended Option | Notes |
|---|---|
| Mid-to-high-end ARM device | Preferred. e.g., Pixel 5βPixel 8. Avoid Android 16 (API 36) for now. |
| x86_64 emulator (Intel) | Reliable with mid-range or better GPU. |
| Apple Silicon (M3/M4) emulator | Acceptable if GPU is sufficient. Better than M1/M2 for rendering. |
| Apple Silicon (M1/M2) emulator | Works, but may show degraded performance or rendering issues. |
Option 1: Physical Deviceβ
- Transfer the APK to your phone or download it directly from the device
- Allow app installation from external sources
- Install the APK
- Connect your devices to Android Studio
Ensure that your device is configured for english language
Option 2: Emulatorβ
- Create a
Pixel 7or equivalent emulatorAPI 31+-API 35 - Edit the emulator and select an API 31+ below the default API 36 (API 34 more stable)
- Launch the emulator
- Drag and drop the APK onto the emulator window to install
Our app currently crashes on Android API 36. The issue is not caused by the new 16KB memory page model, as it runs correctly on API 35 with 16KB pages. API 36 is a very recent release and may introduce subtle runtime or platform-level changes that affect low-level Rust code (e.g., garbled circuit evaluator or frame renderer). Until further investigation, we recommend using API 34 (more stable on emulator) or earlier for testing.
On Apple Silicon (M1βM4), emulators may fail to render or execute low-level native code correctly unless software rendering is enabled.
To enable it:
Device Manager β Edit β Advanced Settings β Emulated Performance β Graphics β Software

- Mandatory for M1/M2: hardware acceleration is not supported and cause crashes.
- Not tested on M3/M4: may support hardware acceleration, but software mode is safer for compatibility.
Enabling this setting ensures more reliable emulator behavior, especially for native Rust or cryptographic rendering, at the cost of some performance.
2. Link App to your local Interstellar stack:β
The Android app is preconfigured to connect to localhost
To allow the Android app to connect to your local blockchain and IPFS stack:
Step 1: adb reverse Setupβ
On the Desktop connected to the Device or running the Emulator (Windows, Mac OS, Linux)
If Android Studio is already installed, you can enable adb in your terminal by adding it to your PATH with the following command (adjust the path if needed):
Add adb PATH:
Linux:
export PATH=$PATH:$HOME/Android/Sdk/platform-tools
Mac OS:
export PATH="$HOME/Library/Android/sdk/platform-tools:$PATH"
Windows powershell:
$env:Path += ";$env:LOCALAPPDATA\Android\Sdk\platform-tools"
adb reverse tcp:9944 tcp:9944 # Substrate WS
adb reverse tcp:2090 tcp:2090 # Integritee node port
adb reverse tcp:5001 tcp:5001 # IPFS
Make sure adb is properly configured and the emulator or device is detected
with adb devices
You can also check the reverse setup with adb reverse --list
This works for both emulators and real devices connected via USB
Step 2 (optional): ssh Port Forwardingβ
On the System or VM running the Blockchain stack (WSL2, Remote VM)
If the emulator is running (or the device is connected) on a different network interface than the backend (e.g., the backend runs in WSL2 and the Android emulator or device is connected via USB to Windows), you may need to configure port forwarding between the desktop and the blockchain.
WSL2 -> Windows example:
export WSL_HOST_IP=$(ip route | awk '/default/ {print $3}')
ssh -N -R 9944:localhost:9944 -R 5001:localhost:5001 -R 2090:localhost:2090 [windows_user_name]@$WSL_HOST_IP
To avoid issues with ssh or adb reverse during this local test, you can temporarily disable the Firewall:
Example on Windows with PowerShell (as Administrator):
Set-NetFirewallProfile -Profile Domain,Private,Public -Enabled False
You can re-enable it later with:
Set-NetFirewallProfile -Profile Domain,Private,Public -Enabled True
During Milestone 2, our primary objective is to validate the backend capabilities required to generate, sign, and execute transactions across different chains.
At this stage, the focus is on ensuring correctness and robustness of the transaction pipeline at the infrastructure level. User-facing aspects such as application UI/UX, visual polish, or cosmetic design are not yet part of the milestone scope. Especially because our focus is the delivery of a mobile SDK.
In addition, while the backend successfully submits transactions, we have not yet integrated state tracking from the backend (e.g., monitoring transaction inclusion and confirmation events). This will be addressed in subsequent milestones, once the foundational backend logic is fully validated.
4. Run the Android App Demoβ
Step 1: Connect & Onboardβ
- Launch the app
- Register a new mobile account
- Validate biometric & SE-based registration
- Check toasted messages
- Registering
- Registered
Step 2: Fund your walletβ
following is suggested faucets for DOT/PAS, SOL, ETH, BTC:
Then on your portfolio screen:
- Simply click on the correponding DOT, SOL, ETH, BTC symbol to see your address.
- Click on
Create Pairif needed and then on the address to copy it, then paste it in the corresponding faucet.
BTC transaction from the faucet usually can take up to one hour.
Feel free to contact us, we will send you SOL or BTC for their respective testnet.
Once Portfolio funded you are ready to move on the Send Screen:
Wipe down on the portfolio or balance/address screen triggers a manual refresh of balances. This is a temporary workaround until the app natively tracks chain states more accurately, which will be available with the SDK delivery.


For testing purposes, the account/address and transaction validation screens display balances and transfer amounts in the atomic units of each chain:
- DOT / Paseo: planck
- BTC: satoshi (sat)
- ETH: gwei
- SOL: lamports
This approach ensures precision and consistency during backend validation, even if these units are less user-friendly than standard denominations.
Step 2: Test Transactionsβ
For simplicity during Milestone 2 testing β and to minimize the need for testnet tokens β the sender and receiver addresses are set to the same account, except for Solana (which uses a predefined address). This setup accelerates testing for curators by avoiding manual address inputs, while still allowing us to validate transaction generation and submission without requiring external token funding.
- Send DOTs, SOLs, ETHs, BTCs to a contact

- Trigger the Trusted Action Validation Protocol (TAVP) screen
- Enter the one-time code (2-digit), or experiment with trial/feedback
- Check toasted messages whith Action Validation Screen:
- Initializing a transaction...
- [error] No circuits available after 10s; Something went wrong! (usually due to insuficient balance)
- [after taping one-time code digits]
- Validating transaction...
In Milestone 3, transaction validation will become conditional on an amount threshold. This threshold will be managed by the Transaction Management Layer (TML), allowing policies such as requiring validation only for transfers above a specified value.
π How to Track a Transaction
Copy the transaction hash (or signature) printed in the backend logs when a transaction is submitted.
- DOT/Paseo β extrinsic hash (hexadecimal, 0xβ¦)
- ETH β starts with 0xβ¦
- SOL β long base58 signature string
- BTC β transaction ID (txid, hexadecimal β¦)
Paste this value into the corresponding block explorer (alternatively you can also paste your address):
- Polkadot / Paseo (DOT): Subscan
- Ethereum (ETH): Etherscan
- Solana (SOL): Solscan
- Bitcoin (BTC): Mempool.space
The explorer will display transaction status, inclusion block, and fee information.
π Example Log Lines Containing Transaction Hashes
Here are the log patterns to look for in each chainβs backend output:
DOTβ
[2025-08-27T15:26:52Z DEBUG pallet_dot_client::pallet] [submit_extrinsic] RPC response: Object {"result": "0x1e58d3a0a3fdf08440a683b67248819a6a64c8249b486b3aae9a686e7ec8de3d"}
ETHβ
2025-08-27T17:47:51.688957000Z [INFO pallet_eth_client::pallet] send_transaction: OK: 0x6593fb0b75fb4eae41e6d918f1ab99dd011f4b1e95c6d913b607968d7f6a0471
SOLβ
2025-08-27T18:38:52.145987000Z [INFO pallet_sol_client::pallet] [send_transaction] Transaction sent with signature: 3QuGubLdzpSi6M3Xy2VxW5ZNJZPnxwy8MfRfvKurDA3MyNYMvgKFVPXt16xzDiHbbn4Px6hfYiq6t7haA6MdbdAb
BTCβ
[INFO pallet_btc_client::pallet] send_transaction: OK: txid=60e95abf0d674143fae1ef11f115386a6dadcb4438ee0ab5c1a4e26438844878
When a transaction is attempted without enough funds to cover the transfer amount and network fees, the client aborts before submission.
All chain clients (DOT, ETH, SOL, BTC) follow the same pattern: the initialize_transaction step fails, and the error is returned in the logs. For example, in the SOL client:
[ERROR itp_stf_executor::executor] Stf execute failed: Dispatch("SolClient Initialize Transaction error: ... message: Some(\"InsufficientBalance\") })
At this stage of the app/SDK devellopement, if an insufficient balance error occurs, the VCA token is not transfered to the app, and the screen instead displays a generic βSomething went wrong!β message.
This behavior ensures no invalid transactions are broadcast and provides a clear error message for debugging and verification.
If you are using an emulator with low-end GPU, or a low-end or outdated Android device with limited GPU, the user experience may be significantly degraded. Although the validation screen may be harder to read in such conditions, you should still be able to complete the test process.
In the future, we plan to introduce a trusted beneficiary feature. This will enable users to register known recipient addresses on-chain through a secure validation process, preventing attackers from substituting contact names with malicious public keys. This enhancement will make the wallet both more secure and user-friendly.
π οΈ You can check the logs from your local stack to see whtat happen begind the hood when you interact with the blockchain:
extrinsicssent
Interpreting Logsβ
When interacting with the mobile app (e.g., authentication, transaction validation, recovery),
key log messages are printed by both integritee-node and integritee-service.
Trusted Action Validation Highlightβ
These logs help verify that Trusted Action Validation flows used both in transaction validation and recovery are working as expected.
Key messages to look for:β
Challenge screen rendering (garbled circuit evaluation):β
[tx-validation] store_metadata_aux: message_digits = [9, 7], pinpad_digits = [8, 4, 6, 7, 3, 1, 5, 2, 9, 0]
Succesfull or Failed Validations (timing or incorrect code touchscreens positions)β
- If you enter an invalid code:
[tx-validation] TxFail - If correct:
[tx-validation] TxPass
π οΈ Mobile Registrationβ
This log trace shows what happens when a new device connects to the system and is not yet registered under a root account. The backend detects the missing account and proceeds with registration:
[INFO pallet_mobile_registry::pallet] ensure_has_root_account failed for while checking if registered: Module(ModuleError { index: 16, error: [0, 0, 0, 0], message: Some("RootAccountNotFound") })
[DEBUG pallet_mobile_registry::pallet] register_mobile start for
[DEBUG pallet_mobile_registry::pallet] register_mobile: new registration for
[DEBUG pallet_mobile_registry::pallet] register_mobile end
β What to Look Forβ
RootAccountNotFound: expected on first connection from a new mobile identity.register_mobile startβregister_mobile end: confirms that registration was initiated and completed.- These logs confirm that the system automatically falls back to registering the mobile when not yet linked to a root account.
Learn more on Account Abstraction Layer
Learn more on Authentication Layer
computed_inputs_from_permuation detailed
π οΈ DOT / PASEO Transactionβ
This section explains how to read a TAVP-gated DOT/PASEO transfer executed via the Interstellar DOT client on Asset Hub (Paseo).
Trusted Action Validation β Commitmentβ
TAVP commitment logs
[2025-08-27T15:26:42Z INFO pallet_tx_validation::pallet] [tx-validation] store_metadata_aux: who = , message_pgarbled_cid = "QmZHKMEKiWq5dbmxP7nWRJ2dPQvc1bY8YfbiZSQGVhfj8e", message_digits = [0, 4], pinpad_digits = [2, 9, 0, 4, 3, 7, 5, 1, 8, 6]
[2025-08-27T15:26:42Z INFO pallet_tx_validation::pallet] [tx-validation] store_metadata_aux: done!
[2025-08-27T15:26:42Z INFO pallet_key_manager::pallet] [DOT-client]-[key-manager]- Commitment prepared and stored: cid="QmZHKMEKiWq5dbmxP7nWRJ2dPQvc1bY8YfbiZSQGVhfj8e"
[2025-08-27T15:26:42Z INFO pallet_key_manager::pallet] [DOT-client]-[key-manager]- Commitment prepared and stored: digits=BoundedVec([0, 4], 4)
[2025-08-27T15:26:42Z INFO pallet_key_manager::pallet] [DOT] client-[key-manager]- Commitment prepared and stored: pinpad_digits=BoundedVec([2, 9, 0, 4, 3, 7, 5, 1, 8, 6], 10)
β What to look for
store_metadata_auxshows a validmessage_pgarbled_cid(IPFS CID),message_digits, andpinpad_digits.- Key-manager confirms commitment stored (CID + digits + permutation).
β Red flags
- Missing CID or digits; commit not stored.
Trusted Action Validation β Input Checkβ
TAVP validation logs
[2025-08-27T15:26:52Z INFO pallet_tx_validation::pallet] [tx-validation] check_input: who = , ipfs_cid = "QmZHKMEKiWq5dbmxP7nWRJ2dPQvc1bY8YfbiZSQGVhfj8e", input_digits = [2, 3]
[2025-08-27T15:26:52Z INFO pallet_tx_validation::pallet] [tx-validation] check_input: input_digits_str = "\u{2}\u{3}", input_digits_int = [2, 3], pinpad_permutation = BoundedVec([2, 9, 0, 4, 3, 7, 5, 1, 8, 6], 10)
[2025-08-27T15:26:52Z INFO pallet_tx_validation::pallet] [tx-validation] check_input: computed_inputs_from_permutation = [0, 4], message_digits = BoundedVec([0, 4], 10)
[2025-08-27T15:26:52Z INFO pallet_tx_validation::pallet] [tx-validation] TxPass
β What to look for
computed_inputs_from_permutationequalsmessage_digits.TxPassis present (challenge solved and authorized).
β Red flags
TxFail, or mismatch between computed and message digits.
Learn more on Authentication Layer
computed_inputs_from_permuation detailed
Chain Context (Header β Current Block)β
chain context logs
[2025-08-27T15:26:52Z DEBUG pallet_dot_client::pallet] [get_current_block] Block number: 2596404
β What to look for
- Correct chain context (Asset Hub Paseo).
- Concrete current block number (used for era anchoring).
Balance Check (Sender)β
balance check logs here
[2025-08-27T15:26:41Z INFO pallet_dot_client::pallet] [get_account] Fetching account address for:
[2025-08-27T15:26:41Z DEBUG pallet_dot_client::pallet] [get_balance] Account info: <wasm:stripped>
[2025-08-27T15:26:41Z DEBUG pallet_dot_client::pallet] [submit_transaction] Sender Balance: 49990867380224, Required: 2001000000
β What to look for
- Senderβs free balance comfortably above required amount/fees.
- The line printing Sender Balance and the computed Required.
β Red flags
- Insufficient balance or missing account info.
Transaction UX Message (Optional)β
transaction UX message logs
[2025-08-27T15:26:41Z DEBUG pallet_key_manager::pallet] [generate_tx_message] Generated message: Transfer 1000000 DOT to
β What to look for
- A human-readable message (useful for audit/UI), even if the unit label is a placeholder.
- Message aligns with the SCALE-encoded call that follows.
β Red flags
- Message missing crucial fields (destination/amount).