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 with conditional transaction confirmation through the transaction management layer.
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_m3_demo && cd interstellar_m3_demo
# Step 2: Download the stack config
curl -L -o docker-compose.yml https://raw.githubusercontent.com/Interstellar-Network/containers/refs/tags/testnet-m3/docker-compose.yml
curl -L -o docker-ipfs-init.sh https://raw.githubusercontent.com/Interstellar-Network/containers/refs/tags/testnet-m3/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)
Latest version recommended
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. |
If you already have an older version of the Interstellar Android app installed, you must uninstall it before installing the M3 build.
The app uses local secure storage and cached configuration; keeping a previous version may lead to inconsistent behavior during transaction signing or validation.
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 3, 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.
In Milestone 3, transaction validation become conditional on an amount threshold. This threshold is managed by the Transaction Management Layer (TML), allowing policies such as requiring validation only for transfers above a specified value. In addition the Key Management system is now protected through the sealing of the private keys as well as related sensitive information.
Step 2: Test Transactions with conditional validationsβ
For simplicity during Milestone 3 testing β and to minimize the need for testnet tokens β the sender and receiver addresses are set to the same account. 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

For simplicity during Milestone 3, transaction thresholds and prefilled amounts are intentionally calibrated so that changing a single digit is enough to switch between the two execution paths:
- Below threshold β auto-approved transaction
- Above threshold β VCA-gated transaction
The default amounts are defined in
androidApp/src/main/java/gg/interstellar/wallet/android/data/WalletData.kt
and are chosen so that a typical faucet allocation allows ~10β20 transactions per chain without refilling.
| Chain | Prefilled amount (example) | Threshold | How to trigger VCA |
|---|---|---|---|
| BTC | 0.00015 BTC | 0.0002 | Change to 0.00025 |
| ETH | 0.00025 ETH | 0.0003 | Change to 0.00035 |
| DOT | 0.55 DOT | 0.6 | Change to 0.65 |
| SOL | 0.02 SOL | 0.025 | Change to 0.03 |
This setup allows reviewers to validate both flows quickly, without manual threshold tuning or repeated faucet usage.
- if the Trusted Action Validation Protocol (TAVP) screen appears:
- 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...
π 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β
DEBUG dot_client::client] [send_raw_transaction] RPC response: Object {"id": Number(1), "jsonrpc": String("2.0"), "result": String("0x146594ef3f09219cd2f6a9f24a29a8a5ebfcb9f9b46a6b95e0d302995fbaa0fc")
INFO pallet_tx_manager::pallet] Transaction broadcast successful: 0x146594ef3f09219cd2f6a9f24a29a8a5ebfcb9f9b46a6b95e0d302995fbaa0fc
ETHβ
DEBUG eth_client::client] rpc_request: START
INFO pallet_tx_manager::pallet] Transaction broadcast successful: 0x2b116ccc2f92fafb9aa0108625876f0ca8d62de050ac7672091b3b4091360e69
SOLβ
[INFO sol_client::client] [broadcast_transaction] Transaction sent with signature: 3QuGubLdzpSi6M3Xy2VxW5ZNJZPnxwy8MfRfvKurDA3MyNYMvgKFVPXt16xzDiHbbn4Px6hfYiq6t7haA6MdbdAb
INFO pallet_tx_manager::pallet] Transaction broadcast successful:
3QuGubLdzpSi6M3Xy2VxW5ZNJZPnxwy8MfRfvKurDA3MyNYMvgKFVPXt16xzDiHbbn4Px6hfYiq6t7haA6MdbdAb
BTCβ
[INFO btc_client::client] Transaction broadcast successfull: txid=60e95abf0d674143fae1ef11f115386a6dadcb4438ee0ab5c1a4e26438844878
INFO pallet_tx_manager::pallet] Transaction broadcast successful:
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.
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
π οΈ Multi-chain Transaction Logs with threshold gated transferβ
This section explains how to read the logs emitted during a conditional TAVP-gated transfer executed via the Interstellar transaction clients for DOT, ETH, BTC, and SOL.
As of M3, pallet_tx_manager decides whether a transfer must be VCA-confirmed depending on a per-chain configured threshold:
- Below threshold: transaction is auto-approved and broadcast directly.
- Above threshold:
pallet_tx_managergenerates a VCA commitment, waits for VCA input validation, then broadcasts.
Note
The same log structure applies regardless of the target network environment. The βthreshold β (optional) VCA β broadcastβ flow and its log markers remain identical.
Common structure (applies to all chains)β
| Stage | What happens | Key log markers |
| 1. Start | Transaction preparation begins (account + chain + amount in base units). | [prepare_transaction] START |
| 2. Threshold check | Reads TX_THRESHOLD_*, parses it to base units, compares with amount. |
|
| 3. Build + sign | Chain-specific preflight, transaction construction, and signing. |
|
| 4A. Below threshold path | Auto-approve and broadcast immediately (no VCA commitment). |
|
| 4B. Above threshold path | Create VCA commitment (message + digits), store metadata + pending tx. |
|
| 5. VCA validation | Validate user input via the randomized pinpad permutation. |
|
| 6. Broadcast | Submit signed transaction/extrinsic and obtain a network tx hash / signature / txid. |
|
Fields worth recognizingβ
amount_base_units: chain base unit amount (wei, sats, lamports, planck-like units, etc.).TX_THRESHOLD_{CHAIN}: environment variable used to configure the VCA threshold for that chain.below_threshold=true|false: the decision input; the explicit decision log line follows at INFO.message_digitsandpinpad_digits: VCA challenge and pinpad permutation used to validate the user input.- Final broadcast markers include a chain-native identifier:
- DOT: extrinsic hash (
0x...) - ETH: transaction hash (
0x...) - BTC: transaction id (
txid=...) - SOL: transaction signature (base58)
- DOT: extrinsic hash (
DOT β Conditional VCA-gated transferβ
1) Start + threshold evaluationβ
Anchor line:
-
[prepare_transaction] START - ... chain=DOT, amount_base_units=...
Threshold resolution appears as:
-
env_var=TX_THRESHOLD_DOT -
Read value: ... -
Parsed ... to ... base units -
threshold=..., amount=..., below_threshold=...
Decision line (INFO):
- If above:
Above threshold, requiring VCA confirmation - If below:
Below threshold, auto-approving transaction
2) Build + sign (DOT client)β
Typical DOT client markers include:
- Account/balance RPC reads:
state_getStorage - Chain context:
system_chain,system_properties,state_getRuntimeVersion - Extrinsic build/sign:
-
build_call Balances.transfer_keep_alive -
Generated hex payload -
Encoded MultiSignature -
Extrinsic hex
-
3) Above threshold path: VCA commitment + validation + broadcastβ
Commitment creation:
-
[generate_tx_message] Generated message: Transfer ... DOT to ... -
[tx-validation] store_metadata_aux: ... message_pgarbled_cid="Qm..." message_digits=[...], pinpad_digits=[...] -
Commitment stored with cid="Qm..." digits=... pinpad_digits=... -
store_pending_transaction: SUCCESS
Input validation:
-
[tx-validation] check_input: ... input_digits=[...] -
computed_inputs_from_permutation = [...], message_digits = [...] -
TxPass -
VCA validation successful
Broadcast:
-
author_submitExtrinsic -
Transaction broadcast successful: 0x...
4) Below threshold path: auto-approve broadcastβ
You should see:
-
Below threshold, auto-approving transaction - immediate submission +
Auto-approved transaction broadcast successful: ...(or equivalent final marker)
ETH β Conditional VCA-gated transfer (EIP-1559)β
1) Start + threshold evaluationβ
Anchor line:
-
[prepare_transaction] START - ... chain=ETH, amount_base_units=...
Threshold parsing:
-
env_var=TX_THRESHOLD_ETH -
Parsed ... to ... base units -
below_threshold=...
Decision line (INFO):
Above threshold, requiring VCA confirmationor-
Below threshold, auto-approving transaction
2) ETH preflight + build + signβ
You will typically see:
- Fee discovery:
-
fetch_latest_base_fee: got: ... -
fetch_max_priority_fee: got: ...
-
- Balance check:
-
fetch_balance: formated address = "0x..." -
fetch_balance: RPC response = ...
-
- Signing:
-
pallet_key_manager ... do_sign_prehashed -
create_eip1559_signed_rlp: START
-
3) Above threshold path: VCA commitment + validation + broadcastβ
Commitment creation:
-
[ETH] ... Entering garble_and_store_commitment -
Generated message: Transfer ... ETH to 0x... -
store_metadata_aux ... message_pgarbled_cid="Qm..." message_digits=[...], pinpad_digits=[...] -
Commitment stored ... -
store_pending_transaction: SUCCESS
Validation:
-
check_input ... -
computed_inputs_from_permutation = [...], message_digits = [...] -
TxPass
Broadcast:
-
send_raw_transaction: START -
Transaction broadcast successful: 0x...
BTC β Threshold-gated transfer (UTXO-based)β
BTC differs structurally because transaction construction includes UTXO scanning, selection, and per-input signing.
1) Start + threshold evaluationβ
Anchor:
-
[prepare_transaction] START - ... chain=BTC, amount_base_units=...
Threshold:
-
env_var=TX_THRESHOLD_BTC -
Parsed ... to ... base units -
below_threshold=...
Decision line (INFO):
- If below:
Below threshold, auto-approving transaction - If above:
Above threshold, requiring VCA confirmation
2) UTXO discovery + unsigned tx creationβ
Look for:
-
fetch_utxos_for_address: START - RPC scan:
-
Making RPC call: method=scantxoutset
-
- Parsing:
-
parse_utxos_from_response: ... parsed UTXO ... -
SUCCESS: parsed N UTXOs, total_value=... sats
-
- UTXO selection:
-
select_utxos: START for ... sats -
Selected ... UTXOs ... change: ...
-
- Unsigned tx created:
-
Unsigned transaction created: inputs=..., outputs=...
-
3) Signing (per-input) + broadcastβ
Per-input signing markers:
-
Signing input 0: txid:vout, amount=... sats -
Sighash for input 0: ... -
pallet_key_manager ... do_sign_prehashed -
Successfully converted to Bitcoin DER signature -
Created witness for input ... - End of signing:
-
Transaction signing completed: ... inputs signed
-
Below threshold auto-approve and broadcast:
-
[prepare_transaction] Below threshold, auto-approving transaction -
Broadcasting transaction to Bitcoin network ... -
Transaction broadcast successful: txid=... -
[prepare_transaction] Auto-approved transaction broadcast successful: ...
Above threshold would insert the same VCA commitment + validation steps as described in DOT/ETH, then broadcast.
SOL β Threshold-gated transfer (lamports + simulate + send)β
SOL differs because a simulation step is performed before broadcast.
1) Start + threshold evaluationβ
Anchor:
-
[prepare_transaction] START - ... chain=SOL, amount_base_units=...
Threshold:
-
env_var=TX_THRESHOLD_SOL -
Parsed ... to ... base units -
below_threshold=...
Decision line (INFO):
Below threshold, auto-approving transactionor-
Above threshold, requiring VCA confirmation
2) Balance check + build + signβ
Look for:
- Address and balance:
-
[get_balance_account_str] Fetching balance for account: ... -
getBalance ... value=... -
β balance check passed
-
- Blockhash:
-
getLatestBlockhash ... blockhash="..."
-
- Signing:
-
pallet_key_manager ... do_sign -
[build_and_sign_transaction] transaction built and signed: ... bytes
-
3) Below threshold path: simulate then broadcastβ
Auto-approve:
-
[prepare_transaction] Below threshold, auto-approving transaction
Simulation:
-
[simulate_transaction] Simulating transaction -
simulateTransaction ... err=null -
β no error detected in simulation response -
Transaction simulation successful
Broadcast:
-
sendTransaction ... -
Transaction sent with signature: ... -
[prepare_transaction] Auto-approved transaction broadcast successful: ...
Above threshold would insert VCA commitment + validation before broadcast (same pattern as DOT/ETH).
Quick troubleshooting markersβ
- If the transaction was above threshold but never broadcast:
- Check for
store_pending_transaction: SUCCESSthen laterTxPass.
- Check for
- If VCA fails:
- Compare
computed_inputs_from_permutationandmessage_digits.
- Compare
- If SOL broadcast fails:
- Look for simulation
errandcheck_transaction_errmarkers.
- Look for simulation
- If BTC broadcast fails:
- Inspect RPC response from
sendrawtransactionand whether signing completed for all inputs.
- Inspect RPC response from
π Interpreting SGX sealing logs (M3)β
In Milestone 3, the KMS introduces SGX-backed key sealing, allowing private keys to persist securely across enclave restarts. This behavior is observable directly in the logs emitted by the signing flow.
Key log markers to look forβ
During transaction signing (for ETH, BTC, SOL, or DOT), you will typically see:
-
[unseal_seed] Delegating to crypto_ops::unseal_seed -
[do_sign_prehashed] Seed unsealed successfully, proceeding with signing -
[do_sign_prehashed] Seed zeroed after signing
(or [do_sign] depending on the chain)
What this meansβ
-
Unsealing
The private key material is recovered from SGX-sealed storage and loaded into enclave memory just before signing. -
Signing
The transaction payload is signed entirely inside the enclave. The private key is never exposed outside trusted memory. -
Zeroization
After signing completes, the key material is explicitly zeroed from enclave memory, limiting its lifetime to the minimum required window.
This sequence confirms that:
- Keys are persisted securely using SGX sealing
- Keys are only present in memory when strictly necessary
- No plaintext key material survives beyond the signing operation
Important noteβ
You may still see warnings such as:
-
storage::start_transaction unimplemented -
storage::commit_transaction unimplemented
These are related to the Substrate WASM execution environment and do not indicate a failure of SGX sealing. The sealing and unsealing operations are handled at the enclave level and remain fully effective.
Summaryβ
When reviewing logs in M3:
- The presence of
unseal_seedfollowed by successful signing confirms SGX-backed key recovery. - The subsequent zeroization log confirms safe key lifecycle management.
- This behavior represents the only functional change between M2 and M3 in the KMS.
Parentchain Inclusion / Syncβ
parentchain sync logs
2025-08-29T14:26:37.130937000Z [+] Received finalized header update (855), syncing parent chain...
2025-08-29T14:27:01.151365000Z [+] Received finalized header update (857), syncing parent chain...
β What to look for
- Parentchain finalized headers advancing.
- Event vectors synced.
Optional: Front-End Accessβ
You can inspect chain state and transactions via:
- Polkadot.js Apps
- Or your preferred Substrate front-end UI
Notesβ
- All services run in Docker containers and use local ports
9944,2090, and5001 - This setup replicates the same runtime environment used in hosted testnets but fully self-contained
- Ideal for offline testing, developer evaluation, or deeper inspection of runtime logs
Recovery was introduced in M1 and remains part of the overall testnet scope. All subsequent milestones are designed to remain compatible with the recovery flow, but in M2 we are not re-testing or refining recovery.
The focus of M2 is backend transaction generation and execution. Recovery will be revisited in future milestones (notably M4) and fully integrated with the SDK delivery, where its stability and developer usability can be validated in a realistic context.
This avoids redundant effort at this stage, while ensuring continuity from M1 to later milestones.
This Android application is provided as a technical demonstration of Interstellarβs secure Web3 account infrastructure. It serves as a foundation for the forthcoming Android and iOS SDKs, which are still under active development.
Please note that the current user interface and experience are not representative of the final product. Both UI and UX will be significantly refined to align with Interstellarβs core mission: delivering the highest levels of simplicity and security in mobile self-custody.
If you've jumped straight into the evaluation, we recommend consulting the Milestone 1 documentation for key context. It outlines the core architecture, backend logic, and trusted execution flows implemented in this milestone.
The documentation is modularβfeel free to explore only the sections most relevant to your review or interest.
You can also use the search bar (top right corner) to locate specific topics quickly. Helpful keywords include:
VHDL,circuits,garbled,TEE,integritee,SE attestationNFC,VCA,recovery,threshold,trusted UXcomparison,passkey,ledger,authentication,compliance,security,ATT&CK