docs: add Molotov architecture and technical specification

This commit is contained in:
katR 2026-09-29 07:50:13 +05:30
commit 467fca98ae

View file

@ -0,0 +1,289 @@
# Molotov: Architecture & Technical Specification
* **Project Name**: Molotov
* **License**: GNU General Public License v3.0 or later (GPL-3.0-or-later)
* **Target Platform**: Linux x86_64 (Wayland & X11)
* **Implementation Language**: Rust 1.75+
* **Specification Date**: 2026-09-29
---
## 1. Executive Summary & Project Identity
Molotov is an open-source native Roblox runtime and bootstrapper for Linux. Its primary objective is running Roblox with full fidelity—including microphone voice chat, controller support with rumble, IME preedit text input, and zero launch freezes—while maximizing graphics and memory performance on Linux hardware.
Molotov is **not** a Roblox engine reimplementation, nor does it run inside Wine, an Android emulator, a virtual machine, or a container. Instead, Molotov runs Roblox's unmodified Android x86_64 dynamic library (`libroblox.so`) directly within a native Linux host process. It provides the necessary Android Bionic ELF loading environment, JNI virtual machine, and Bridges to native Linux desktop subsystems: PipeWire for low-latency audio, SDL3 for windowing, text input, and gamepads, and Vulkan/OpenGL for rendering.
Integrated into the same binary is a comprehensive bootstrapper with feature parity to Bloxstrap and Froststrap, providing FastFlag profile switching, multi-instance sandboxing, resource modding, and Discord Rich Presence.
---
## 2. Non-Negotiable Architectural Constraints
1. **Strictly No Wine / Proton**: Hyperion and anti-cheat mechanisms actively flag or restrict Wine-based Windows emulation. Molotov executes the Android x86_64 binary natively.
2. **No Faking Success (Fail Fast & Explicitly)**: Every symbol requested by `libroblox.so` must be resolved to one of three categories:
* **`cordial`**: A genuine native implementation of the Android behavior.
* **`host`**: A verified forward to host glibc where ABIs match.
* **`stub`**: An explicit failure returning `-ENOSYS`, `-1`, or `NULL` accompanied by diagnostic logging.
* *Rule*: Never return a plausible-looking fake 0 or success for unhandled symbols. Faking success masks failures and causes silent memory corruption or unrecoverable freezes down the line.
3. **Zero Bundled Roblox Code**: Molotov distributes no proprietary APKs, binaries, or assets. All Roblox assets and binaries are retrieved directly from official Roblox CDNs on first launch and cryptographically validated against official Roblox signing certificates.
4. **Voice Chat Precision (Zero Persistent Mic Indicators)**: Desktop Linux environments (GNOME, KDE) display a privacy indicator whenever a PipeWire capture stream exists. Molotov must only allocate and connect a PipeWire capture stream during active transmission (`AAudioStream_requestStart`) and destroy the stream node immediately upon `requestPause`, `requestStop`, or `close`.
5. **Open Source & Auditable**: Distributed under GPL-3.0-or-later to guarantee freedom, community verification, and architectural transparency.
---
## 3. System Architecture & Workspace Structure
Molotov is implemented as a Cargo workspace with a single multicall binary entry point:
```text
molotov/
├── Cargo.toml # Workspace manifest
├── crates/
│ ├── molotov-core/ # Bionic ELF linker, JNI VM, Audio/Graphics/Input bridges
│ ├── molotov-bootstrap/ # CDN client, APK parser, signature verifier, mods, bwrap
│ ├── molotov-gui/ # egui desktop interface
│ └── molotov-cli/ # Command-line interface & headless orchestration
├── src/
│ └── main.rs # Multicall dispatcher (GUI vs CLI subcommands)
├── packaging/
│ ├── flatpak/ # io.github.molotov.Molotov.yaml
│ ├── appimage/ # AppImage packaging recipes
│ └── aur/ # Arch User Repository PKGBUILDs
├── docs/
│ ├── status.md # Real-time subsystem status & known bugs
│ ├── comparison.md # Objective feature matrix (Sober, Mocktail, Cordial)
│ └── building.md # Distribution build instructions
└── tests/
└── ci_audio_loopback.rs # Automated 440 Hz PipeWire audio loopback test
```
### Component Roles & Boundaries
* **`molotov-core`**:
* Direct dependencies: `libc`, `ash` / `vulkano`, `sdl3`, `pipewire`, `jni`, `tracing`.
* Encapsulates memory management (`mmap`), dynamic symbol tables, TLS initialization, synthetic JavaVM/JNIEnv tables, AAudio C-ABI callbacks, and SDL3 event translation.
* **`molotov-bootstrap`**:
* Direct dependencies: `reqwest`, `sha2`, `zip`, `x509-parser`, `rbx-dom`, `serde`, `serde_json`, `nix`.
* Manages version queries, signature parsing, APK package extraction, FastFlag profile persistence, asset overlay generation, and `bwrap` containerization.
* **`molotov-gui`**:
* Direct dependencies: `egui`, `eframe`, `molotov-bootstrap`, `molotov-core`.
* Provides the user-facing settings dashboard, launch controls, and diagnostics panel.
* **`molotov-cli`**:
* Direct dependencies: `clap`, `molotov-bootstrap`, `molotov-core`.
* Provides headless scripting, FastFlag modification, and version maintenance subcommands.
* **`molotov` (root binary)**:
* Reads invocation arguments. If arguments are passed (e.g. `molotov launch <place_id>`), routes to `molotov-cli`; if launched without arguments or via `.desktop`, initializes `molotov-gui`.
---
## 4. Bootstrapper & Ingestion Pipeline
### 4.1 Version Discovery & Retrieval
1. **Query**: Hits Roblox Client Settings endpoint (`https://clientsettings.roblox.com/v2/client-version/Android`) to fetch the current version GUID and build timestamp.
2. **Comparison**: Compares the remote version against local cache in `~/.local/share/molotov/versions/`. If an update is required or on initial install, prompts the user (or executes automatically in CLI mode).
3. **Atomic Download**: Streams the official Android x86_64 APK directly from the official CDN into `~/.cache/molotov/downloads/<version_guid>.apk.part` with real-time SHA-256 calculation, renaming to `.apk` upon completion.
### 4.2 Cryptographic Verification
* Parses APK Zip structures to inspect `META-INF/` signatures:
* Verifies JAR signing (`.RSA`/`.DSA` certificates) and APK Signature Scheme v2/v3 blocks.
* Validates the DER-encoded public key and X.509 certificate against Roblox Corporation's known SHA-256 fingerprint:
* `Roblox Android Certificate Fingerprint`: `1c:00:81:4e:66:35:b0:b3:f1:ff:37:37:3e:38:29:b9:28:90:54:e5:cf:51:65:70:e4:65:fc:e0:bc:95:68:5b`
* If the signature fails verification, the downloaded archive is discarded and execution is aborted.
### 4.3 Targeted Extraction & In-Memory Modding
* **Extraction**: Unpacks only necessary binaries and data into `~/.local/share/molotov/versions/<version_guid>/`:
* `lib/x86_64/libroblox.so`
* Engine assets from `assets/`
* **Non-Destructive Mod Overlay**:
* User mods (custom death sound `ouch.ogg`, cursors, fonts) are placed in `~/.config/molotov/mods/`.
* The base APK and extracted files are **never** modified on disk.
* Asset loading in `molotov-core` intercepts `AAssetManager_open` calls: if a path matches a user-supplied mod, the runtime redirects to the custom file path in `~/.config/molotov/mods/`.
### 4.4 Multi-Instance Isolation (`bwrap`)
To run multiple independent Roblox accounts concurrently:
* Molotov launches independent game instances inside `bubblewrap` (`bwrap`) sandboxes.
* Each instance receives:
* A dedicated `XDG_DATA_HOME` (`~/.local/share/molotov/instances/<id>/data`)
* A dedicated `XDG_CONFIG_HOME` (`~/.local/share/molotov/instances/<id>/config`)
* Read-only bind mounts for the system libraries and base Roblox version folder.
* Dedicated IPC and network sockets to ensure separate authentication cookies and process states without mutual interference.
---
## 5. FastFlag Engine & Performance Optimizations
### 5.1 Configuration & Profiles
* FastFlags are stored in standard JSON format:
* Master configuration: `~/.config/molotov/fflags.json`
* Named profiles: `~/.config/molotov/profiles/<name>.json`
* Employs `rbx-dom` to parse, serialize, and validate Roblox FastFlag structures.
* FastFlag types supported: `FFlag`, `FInt`, `FString`, `DFInt`, `DFFlag`, `DFString`.
* Enforces the official Roblox FastFlag allowlist: flags outside the allowlist trigger an amber warning in the UI/CLI.
### 5.2 Performance-Specific Features
1. **VRAM Optimization (NVIDIA Driver Stability)**:
* Sober and other loaders frequently crash with GL/VK Out Of Memory errors under proprietary NVIDIA drivers.
* Molotov exposes prominent toggles and default profiles enabling:
* `FIntDebugTextureManagerSkipMips = 1` (or `2` for low-VRAM GPUs)
* `DFIntTextureCompositorActiveJobs = 2`
2. **Frame Pacing & Uncapped FPS**:
* Does not enforce FIFO / V-Sync pinning.
* Exposes `DFIntTaskSchedulerTargetFps` to allow setting custom limits (e.g. 144, 240, uncapped).
* Configures the SDL3 display presentation mode to `Mailbox` or `Immediate`.
3. **Process Scheduling Priority**:
* Sets Linux CPU priority (`nice -5`) via `libc::setpriority`.
* Sets I/O priority via `ioprio_set` (Best-Effort priority 2) to prevent frame hitching during asset streaming.
### 5.3 Startup Watchdog & "Safe Mode" Auto-Recovery
* Tracks startup health via `~/.local/state/molotov/launch_state.json`.
* If a launch freezes or terminates prior to the first rendered frame within a 15-second window:
* A consecutive failure counter increments.
* Upon 2 consecutive failures, Molotov automatically triggers **Safe Mode**:
* Disables all custom FastFlags and mod overlays.
* Boots with the minimal validated default flag configuration.
* Prompts the user with diagnostic logs and an option to reset conflicting flags.
---
## 6. Core Runtime: Bionic Linker & JNI VM
### 6.1 Custom Bionic Linker (`molotov-core`)
Roblox’s `libroblox.so` is compiled against Android Bionic libc. Molotov implements a custom in-memory ELF loader:
1. **ELF Parsing & Memory Layout**:
* Reads ELF64 headers and iterates over `PT_LOAD` segments.
* Maps segments using `mmap` with `MAP_PRIVATE | MAP_ANONYMOUS`.
* Sets initial protections (`PROT_READ | PROT_WRITE`) during relocation patching, then applies final segment protections (`PROT_READ | PROT_EXEC`).
2. **Dynamic Relocations**:
* Traverses `DT_RELA`, `DT_REL`, and `DT_JMPREL` sections.
* Implements relocation types:
* `R_X86_64_RELATIVE`: Base address slide.
* `R_X86_64_GLOB_DAT`: Global symbol resolution.
* `R_X86_64_JUMP_SLOT`: PLT function pointer resolution.
* `R_X86_64_64`: 64-bit absolute address fixup.
3. **Thread-Local Storage (TLS)**:
* Allocates dedicated Bionic TLS blocks according to Android x86_64 TLS memory conventions, preserving the host glibc TCB on the calling thread.
### 6.2 Strict Symbol Resolution Triage Table
Every imported symbol requested by `libroblox.so` is resolved via a strict three-tier lookup:
| Tier | Category | Description | Examples | Failure Behavior |
| :--- | :--- | :--- | :--- | :--- |
| **Tier 1** | `cordial` | Native Android reimplementation | `__android_log_print`, `AAssetManager_*`, `ANativeWindow_*`, `AAudioStreamBuilder_*` | Handled internally by Molotov bridges |
| **Tier 2** | `host` | Direct forward to host glibc | `malloc`, `free`, `memcpy`, `memmove`, `sin`, `cos`, `epoll_*`, `pthread_mutex_*` | Host ABI execution |
| **Tier 3** | `stub` | Unimplemented / unneeded symbol | Obsolete telemetry, unsupported proprietary services | Returns `-ENOSYS`, `-1`, or `NULL`. **Never returns fake 0/success.** |
*Logging Requirement*: Every unresolved symbol encountered at runtime emits a `tracing::warn!` record with the symbol name and caller return address.
### 6.3 JNI VM & Android Activity Lifecycle
* **Synthetic JNI Tables**:
* Implements `JavaVM` and `JNIEnv` function pointer tables conforming to the standard JNI specification.
* Intercepts `FindClass`, `GetMethodID`, `GetStaticMethodID`, `Call*Method`, and `NewStringUTF`.
* **Emulated Android Framework Classes**:
* `android.content.Context`: Returns paths for package files, cache directories, and asset manager references.
* `android.os.Build`: Supplies an x86_64 Android 13/14 device profile (`ro.build.version.sdk = 33`, `ro.product.cpu.abi = x86_64`).
* `com.roblox.client.*`: Handles application lifecycle notifications and session token handoffs.
* **Initialization Flow**:
1. Calls `JNI_OnLoad(JavaVM*, void*)` in `libroblox.so`.
2. Resolves and executes `ANativeActivity_onCreate`.
3. Registers native callbacks: `onNativeWindowCreated`, `onNativeWindowResized`, `onInputQueueCreated`, `onNativeWindowDestroyed`.
---
## 7. Hardware & I/O Bridges
### 7.1 Voice Chat: AAudio → PipeWire
* **The Problem**: On modern Linux desktop environments, active PipeWire capture streams keep the desktop microphone icon illuminated, causing privacy concern and confusion. Cordial lacked voice chat entirely; other implementations maintain open streams continuously.
* **The Solution: Dynamic Ephemeral Capture**:
* `AAudioStreamBuilder_openStream` with `AAUDIO_DIRECTION_INPUT`: Prepares internal audio buffers and parameters, but **does not create or connect** a PipeWire capture node.
* `AAudioStream_requestStart`: Initializes a PipeWire stream (`PW_DIRECTION_INPUT`) connected to the default audio source (`SPA_AUDIO_FORMAT_F32_LE`, 48000 Hz).
* `AAudioStream_requestPause` / `requestStop` / `close`: **Immediately tears down and destroys the PipeWire stream node**. The desktop mic indicator turns off instantaneously.
* **Playback Pipeline**:
* `AAUDIO_DIRECTION_OUTPUT` connects to a PipeWire playback stream with a lock-free ring buffer ensuring latency under 15ms.
* **Automated CI Audio Verification Test**:
* Included in `tests/ci_audio_loopback.rs`:
* Generates a 440 Hz pure sine wave into a PipeWire virtual sink.
* Captures the signal through Molotov's AAudio capture pipeline.
* Computes an FFT frequency spectrum.
* Asserts peak detection at 440 Hz ± 1 Hz with ≥ 95% waveform correlation.
### 7.2 Text Input & IME Preedit
* **SDL3 Text Input API**:
* Hooks game text focus events to `SDL_StartTextInput()` and `SDL_StopTextInput()`.
* Monitors `SDL_EVENT_TEXT_INPUT` for confirmed UTF-8 characters.
* **IME Support (fcitx5, ibus, Wayland text-input-v3)**:
* Listens for `SDL_EVENT_TEXT_EDITING` to capture in-progress preedit composition strings.
* Dynamically repositions the candidate popup window using `SDL_SetTextInputArea()` matching the in-game text cursor coordinates.
* Transmits preedit and commit strings to the engine via synthetic Android `InputConnection` events.
### 7.3 Gamepad & Force Feedback (Rumble)
* **SDL3 Gamepad API**:
* Detects Xbox, PlayStation (DualShock 4 / DualSense), Switch Pro, and standard HID controllers.
* Translates SDL axis and button inputs to Android `InputDevice` motion and key events.
* Fixes glyph rendering by reporting accurate physical button layouts to the engine.
* **Haptic Rumble**:
* Intercepts Android `Vibrator.vibrate(VibrationEffect)` JNI calls.
* Dispatches dual-motor low/high frequency vibration using `SDL_RumbleGamepad(gamepad, low_freq, high_freq, duration_ms)`.
* Supports trigger rumble via `SDL_RumbleGamepadTriggers` on supported hardware.
### 7.4 Rendering & Display Bridge
* Creates an SDL3 window with Vulkan backing (`SDL_WINDOW_VULKAN`).
* Wraps the native window handle in an `ANativeWindow` C structure.
* Directs swapchain buffers into the engine's Vulkan/OpenGL presentation queue.
---
## 8. Graphical Interface (`molotov-gui`)
Built with `egui` for minimal overhead and zero C toolkit dependencies.
### Tab Navigation
1. **Play**: Launch Roblox, version status indicator, Safe Mode toggle, one-click update button.
2. **FastFlags**: Profile manager (`Default`, `Low VRAM`, `Competitive`, `Custom`), searchable FastFlag table with allowlist validation indicators, and manual flag entry.
3. **Mods**: Mod management cards with file drop targets for `ouch.ogg` death sound, custom cursor packs, and custom TTF/OTF fonts.
4. **Audio & Voice**: Input microphone selector, volume sliders, and interactive "Test Voice Chat Loopback" button with live waveform visualizer.
5. **Multi-Instance**: Instance switcher, status monitor, and one-click instance launcher.
6. **Maintenance & Logs**: Cache and stale version cleaner, Discord RPC settings toggle, and real-time log viewer filtering `[CORDIAL]`, `[HOST]`, and `[STUB]` events.
---
## 9. Packaging & Distribution Plan
1. **Flatpak**:
* Target Flathub distribution: `io.github.molotov.Molotov`.
* Runtime: `org.freedesktop.Platform//24.08`.
* Permissions: `--socket=wayland`, `--socket=fallback-x11`, `--device=dri`, `--socket=pipewire`, `--filesystem=xdg-data/molotov:create`.
2. **AppImage**:
* Self-contained binary bundle created via `cargo-appimage` or `linuxdeploy`.
3. **Arch Linux (AUR)**:
* `molotov`: Release builds from source tarballs.
* `molotov-git`: Development builds tracking `main`.
4. **Debian/Ubuntu & Fedora**:
* Pre-built `.deb` (via `cargo-deb`) and `.rpm` (via `cargo-generate-rpm`).
---
## 10. Documentation & Open Source Transparency
1. **`docs/status.md`**: Living documentation modeled after Cordial, listing exact subsystem status:
* Bionic Linker (Relocations, TLS)
* JNI VM (Emulated classes, callbacks)
* Audio (Playback, Ephemeral capture)
* Graphics (Vulkan, EGL)
* Input (IME preedit, Gamepad rumble)
* Known issues with linked issue tracker IDs.
2. **`docs/comparison.md`**: Honest, objective comparison matrix against Sober, Mocktail, and Cordial detailing voice chat, IME behavior, Wine-independence, and areas where Molotov is still evolving.
3. **`docs/building.md`**: Comprehensive build guide detailing required host libraries (`libpipewire-0.3-dev`, `libsdl3-dev`, `libvulkan-dev`) and compilation commands for Fedora, Arch, and Ubuntu.
---
## 11. Acceptance Criteria ("Definition of Done")
A user on Fedora, Arch, or Ubuntu with GNOME/KDE, PipeWire audio, and an NVIDIA/AMD/Intel GPU can:
1. Install and launch Molotov.
2. Automatically fetch and cryptographically verify the official Roblox Android x86_64 build on first run.
3. Sign in to Roblox and join an experience.
4. Enable Voice Chat: desktop microphone indicator lights up only while actively transmitting and turns off immediately when paused/stopped.
5. Play with a controller and experience force feedback / rumble.
6. Chat in-game using an IME (e.g. fcitx5) with working preedit composition.
7. Experience smooth frame pacing without startup freezes or VRAM exhaustion crashes.