Shared execution environment for constructing 3D virtual spaces from the inside.

Related tags

Command-line hearth
Overview

Hearth

Hearth is a shared, always-on execution environment for constructing 3D virtual spaces from the inside.

Come join our Discord server!

The History of Virtual Worlds

Shared virtual spaces have been around for decades, in many forms. Before PCs were capable of 3D graphics, a popular kind of virtual space were multi-user dungeons, or MUDs. Users can connect to MUDs from a text-based client like telnet, and join other users in a textual virtual world. Although most MUDs only have server-provided worlds that constrained users into their preset rules, some MUDs (such as MUCKs and MOOs) allow users to extend the world with their own functionality. In the early 2000s, Second Life implemented the same principles but in a 3D space instead of a textual one. Users can create their own spatial virtual worlds or enter other users' worlds with a 3D avatar. In the modern day, platforms such as Roblox, VRChat, Rec Room, and Neos all perform the same basic task, but in virtual reality. The decades-old commonality between all of these diversity platforms is user-created content. What's next?

Philosophy

Hearth is a proof-of-concept of a new design philosophy for constructing shared virtual spaces based on three fundamental design principles:

  1. All content in the space can be extended and modified at runtime. This includes models, avatars, textures, sounds, UIs, and so on. Importantly, scripts can also be loaded at runtime, so that the behavior of the space itself can be extended and modified.
  2. The space can pull content from outside sources. The space can load data from a user's filesystem or the Internet, and new scripts can be written to support loading unrecognized formats into the space.
  3. The space itself can be used to create content. Tooling for creating assets for the space is provided by the space itself and by scripts extending that tooling.

Following these principles, a space can construct a content feedback loop that can be fed by outside sources. Users can create their own content while simultaneously improving their tooling to create content, all without ever leaving the space. The result is an environment that can stay on perpetually while accumulating more and more content. The space will grow in scale to support any user's desires, and it can remix the creative content that already exists on the Internet. This space has the potential to become a next-generation form of traversing and defining the Internet in a collaborative and infinitely adaptable way.

Hearth's objective is to create a minimalist implementation of these principles, and find a shortest or near-shortest path to creating a self-sustaining virtual space. To do this, the development loop between script execution, content, and content authoring must be closed. This process is analagous to bootstrapping an operating system, where once the initial system is set up, the system itself can be used to expand itself. Once Hearth has achieved this, the next goal will be to explore and research the possibilities of the shared virtual space, to evaluate potential further use of its design principles.

Architecture

The name "Hearth" is meant to invoke the coziness of sharing a warm fireplace with loved ones. Hearth is based on a straight-forward client-server network architecture, with multiple peers connecting to a single persistent host. In Hearth, all peers on the network are assumed to be friendly, so any peer can perform any action on the world. This assumption sidesteps a massive amount of design dilemmas that have plagued virtual spaces for as long as they have existed.

In order to upgrade Hearth's design from a trustful private environment to a trustless public service, future systems will need to solve these dilemmas in order to prevent griefing. Hearth's goal is to explore implementations of shared execution and content workflow, not security or permissions systems.

Hearth is effectively two programs at once: a distributed scripting environment and a game engine. The scripting provides the metatextual rules of the environment and the game engine creates the spatial substrate of the world. The bridge between distributed execution logic and game engine logic is in the scripting API. Scripts perform high-level logic in the environment, but are also singularly responsible for loading and managing all of the spatial content.

Network

Hearth operates over TCP socket connections. Although other real-time networking options like GameNetworkingSockets or QUIC have significantly better performance, TCP is being used because it doesn't require NAT traversal and it performs packet ordering and error checking without help from userspace. When a connection to a Hearth server is made, the client and server will perform a handshake to exchange encryption keys, and all further communication will be encrypted. Hearth assumes that peers are friendly, but not that man-in-the-middle attacks are impossible. The specific encryption protocol is TBD.

Scripting

Scripting in Hearth is done with WebAssembly. Blah blah blah, lightweight spec, blah blah blah, linear memory storage, blah blah blah, lots of runtime options, I've said all of this before.

Hearth's execution model is inspired by BEAM, the virtual machine that the Erlang and Elixir programming languages run on. BEAM is a tried-and-true solution for creating resilient, fault-tolerant, hot-swappable systems, so many of Hearth's design choices follow BEAM's. Hearth scripts are ran as green thread "processes" that can spawn and kill other processes. Processes share data by sending messages back and forth from each other. A significant departure from BEAM is that because Hearth runs on multiple computers at once, processes can spawn other processes on different peers, which can be either another client or the server. Hearth's networking implementation will then transport messages sent from a process on one peer to another, and the server will relay client-to-client messages.

A working example of a BEAM-like WebAssembly runtime is Lunatic. Lunatic runs green Wasm threads on top of a Rust asynchronous runtime, which handles all of the cooperative multitasking and async IO. Lunatic also implements preemptive multitasking by timeslicing Wasm execution, then yielding to other green threads. Lunatic's operation is another large influence on Hearth's design, and Hearth may reference--or even directly use--Lunatic's code in its own codebase.

IPC

To administrate the network, every peer in a Hearth network exposes an IPC interface on a Unix domain socket. This can be used to query running processes, retrieve properties of the other peers on the network, send and receive messages to processes, kill or restart misbehaving processes, and most importantly, load new WebAssembly modules into the environment. The expected content development loop in Hearth is to develop new scripts natively, then load and execute the compiled module into Hearth using IPC.

Rendering

ECS

Assets

Assets are multipurpose, hash-identified binary blobs that are exchanged on-demand over the Hearth network. To distribute modules to other peers, Hearth first hashes each asset and uses that hash as an identifier to other peers. If a peer does not own a copy of an asset, it will not recognize the hash of that asset in its cache, and it will request the asset's data from another peer. Client peers request asset data from the server, and the server requests asset data from the client that has referenced the unrecognized ID.

Before assets can be specialized for different kinds of content, they must be loaded. Different asset classes, like meshes, textures, and WebAssembly modules have different named identifiers. The names for those asset classes may be Mesh, Texture, or WebAssembly, for example. Once an asset is loaded, it may be passed into the engine in the places that expect a loaded asset, such as in a mesh renderer component. Wasm processes are also spawned using a loaded WebAssembly module asset as the executable source.

Processes may create their own assets in memory and read a foreign asset's data back into process memory. In this way, processes may procedurally generate runtime Hearth content into the space, load content data formats that the core Hearth runtime does not recognize, or pipeline assets through multiple processes that each perform some transformation on them.

Note that because Wasm modules are loaded from assets and because assets can be dynamically created by processes, Hearth processes may generate and load Wasm modules at runtime. This may be used, for example, in a WebAssembly compiler running inside of Hearth itself.

Processes have the ability to send and receive the IDs of assets to other processes. However, the runtime may not be aware that those IDs are being exchanged, so a process running on a remote peer may receive an ID in a message but the runtime will have no way of tracing it back to a peer that has that ID's data. To remedy this, processes have a host call that explicitly warms a target peer's asset cache with a given asset, and must use that host call when referencing asset IDs to a remote process that does not have the asset.

Terminal Emulator

So far, only Hearth's network architecture, execution model, and content model have been described. These fulfill the first and second principles of Hearth's design philosophy, but not the third principle: the space itself must provide tooling to extend and modify itself. The easiest and simplest way to do this is to implement a virtual terminal emulator inside of the 3D space, as a floating window. This terminal emulator runs a native shell on the hosting user's computer, with full access to the filesystem, native programs, and the IPC interface for the Hearth process. The user can use the virtual terminal to edit Hearth scripts using an existing terminal text editor like Vim, Neovim, or Emacs, compile the script into a WebAssembly module, then load and execute that module, all without ever switching from Hearth to another application or shutting down Hearth itself.

The terminal emulator's text is rendered with multichannel signed distance field (MSDF) rendering. MSDF rendering is good for text in 3D space because each glyph can be drawn with high-quality antialiasing and texture filtering from a large variety of viewing angles.

Platform

Hearth runs outside of the browser as a native application. Linux is the only target platform to start with but Windows support will also be added during the alpha phase of development.

Usecases

Implementation

Hearth is written entirely in Rust. Rust rust rust rust rust rust rust. It's licensed under the GNU Affero General Public License version 3 (AGPLv3). Beer. Beeeeeeeeeeeeeeeeeeeeeeer. Freedom.

Networking

The Tokio provides an asynchronous Rust runtime for async code, non-blocking IO over both TCP and Unix domain sockets, and a foundation for WebAssembly multitasking.

The protocols for both IPC and client-server communication are based on the Remoc crate, which implements transport-agnostic channels, binary blob transport, remote procedure calls (RPC), watchable data collections, and other networking constructs. This will save a lot of development time that would otherwise be spent writing networking primitives. Using Remoc makes it difficult to standardize a top-to-bottom protocol definition, and the assumption is being made that no programs other than Hearth or its forks will be using the protocol. The development time saved is more than worth the loss of interoperability.

Rendering

Scenes are rendered with rend3, a batteries-included rendering engine based on wgpu. rend3 includes PBR, lighting, a render graph, skybox rendering, frustum culling, rigged mesh skinning, tone mapping, and other handy renderer features that Hearth doesn't need to do itself. Additionally, rend3's frame graph allows us to easily extend the renderer with new features as needed.

Terminal Emulator

The terminal emulator is implemented with the help of the alacritty_terminal crate, which parses the output of native child processes and writes it into a display-ready grid of characters. Then, Hearth draws the characters onto 2D planes projected in 3D space using MSDF textures generated with the msdfgen crate. This rendering is a custom node in the rend3 frame graph with a custom shader.

  • TBD: can we load glyph outlines from a TTF file without building Freetype?
    • note: the ttf-parser crate looks like what we need)
  • TBD: UX for interacting with in-space terminals?

Input

WebAssembly

TUIs

CLIs

Roadmap

Phase 0: Pre-Production

In phase 0, Hearth documents its purpose, proposes an implementation, decides on which libraries and resources to use in its development, and finds a handful of core developers who understand Hearth's goals and who are capable of meaningfully contributing in the long run.

  • Write a design document
  • Create a Discord server
  • Create a GitHub repository
  • Onboard 3-4 core developers who can contribute to Hearth long-term
  • Design a project logo
  • Set up continuous integration to check pull requests
  • Write a CONTRIBUTORS.md describing contribution workflow
  • Design a workspace structure
  • Finalize the rest of the phases of the roadmap
  • Create mocks for all of the codebase components
  • Money?

Phase 1: Pre-Alpha

In phase 1, each subsystem of Hearth is developed, and the details of its design aspects are made concrete. The whole system has not yet been tied together, and low-level design decisions are considered in isolation of each other.

Hearth's core host-side components can generally be decoupled from each other into several different areas of development or subsystems:

  1. IPC, TUI, and CLI interfaces.
  2. Client-server networking.
  3. Process management.
  4. ECS integration.
  5. Virtual terminal emulator development.

Because these different areas are independent, the goal is to work on each of these areas in parallel. During this point of development, it's important that multiple developers work in coordination with each other in order to progress to alpha as quickly as possible. Mock interfaces and placeholder data where functioning inter-component code would otherwise go are used to develop each component separately.

Phase 2: Alpha

In phase 2, Hearth begins to come together as a whole. Each subsystem is hooked into the others, and the developers work together to synthesize their work into a single functioning application. Although at this point in development network servers are started up for testing, the protocols between subsystems are highly unstable, so long-lived, self-sustaining virtual spaces are still unfeasible.

Phase 3: Beta

In phase 3, Hearth's protocols and system interfaces are mature and relatively stable, so a long-lived development space is created. In this space, developers work together on exploring the capabilities of Hearth processes, and implement practical applications in Hearth using Hearth's fundamental toolkit. If oversights or missing features are found in Hearth's interfaces, they are addressed as fit. However, because the fundamentals of Hearth's implementation are complete, changes to interfaces are infrequent and often non-breaking.

A major focus of this phase is to refine the design principles of writing Hearth processes through rapid iteration, collaboration, and peer review. This makes phase 3 the most difficult phase to complete, as Hearth's goal during this step is to explore uncharted design territory in a unique execution environment.

Phase 4: Release

Comments
  • Fix main branch and protect it

    Fix main branch and protect it

    #5 won't pass CI because of a bug that exists on the main branch right now. This shouldn't happen in the future.

    Fix the build failure on the main branch, rebase #5, then protect the main branch so that it's always passing.

    bug 
    opened by marceline-cramer 1
  • Add lump store

    Add lump store

    This adds a lump store RPC interface, an implementation of that in hearth-core, and some passing unit tests demonstrating how it's used.

    I've also added the ResourceError and ResourceResult types to hearth-rpc for better error results in our RPC calls.

    Read the commit messages for more goodies!

    enhancement 
    opened by marceline-cramer 0
  • Add `hearth-ctl` crate

    Add `hearth-ctl` crate

    Adds a mostly-empty hearth-ctl crate for us to develop our Hearth CLI tools in.

    Also, hearth-rpc was using remote collections even though that feature wasn't enabled on its Remoc dependency, so I fixed that.

    enhancement 
    opened by marceline-cramer 0
  • Set up the `hearth-ipc` crate

    Set up the `hearth-ipc` crate

    'Nuff said.

    Lots of IPC code was pulled from Magpie. Thank you @airidaceae!

    An IPC socket has been set up for the client, but not for the server. This is because a lot of code would need to be duplicated to set up a PeerApiImpl in the server code, too. This will be amended by #15.

    enhancement 
    opened by marceline-cramer 0
  • Make a new `hearth-core` crate and move universal peer logic to it

    Make a new `hearth-core` crate and move universal peer logic to it

    An increasing amount of functionality is duplicated between client and server, including:

    1. tracing_subscriber initialization, with custom settings
    2. IPC setup
    3. a PeerApi implementation
    4. #14

    Making space for all duplicated code will save time and reduce code bloat. Let's move this functionality there then re-include it into the client and server crates.

    enhancement 
    opened by marceline-cramer 0
  • core: catch signal interrupts in binary targets for safe cleanup

    core: catch signal interrupts in binary targets for safe cleanup

    Tokio supports async signal handling. We should set up both the client and server to handle interrupt signals and politely shut down, so that destructors can execute. This need was specifically spurred by the IPC socket not being automatically deleted in its Drop implementation.

    Depends on #15.

    bug enhancement 
    opened by marceline-cramer 0
  • rpc: Peer-based API

    rpc: Peer-based API

    Overhauls basically all of hearth-rpc with a new peer-based API for exchanging PeerProviders and PeerApis.

    Also adds a formal system for assigning peer IDs using a ServerOffer + ClientOffer exchange during initial client-server communication.

    I've decided to remove trailing ...s from log messages, such as in Authenticating... or Binding.... They don't really serve any real point. We may want to use Tracing spans for non-instantaneous operations, but that can be done in a future PR.

    enhancement 
    opened by marceline-cramer 0
  • Client and server binary targets

    Client and server binary targets

    I added hearth-client and hearth-server crates with tracing logging, clap command line parameters, password authentication and encryption from hearth-network, and exchange of a ClientApiClient from the server to the client over Remoc.

    opened by marceline-cramer 0
  • network: non-zero IVs + different keys for client and server

    network: non-zero IVs + different keys for client and server

    Based on the discussion in #8.

    Now, both encryption keys and IVs are initialized using the unused 32 bytes of entropy in the key generated by the authentication step.

    Client-to-server encryption and server-to-client use the same keys from the first 32 bytes of the session key, but different IVs. Client-to-server uses the next 12 bytes and server-to-client uses the next 12 bytes after that.

    enhancement 
    opened by marceline-cramer 0
  • Add `hearth-network` crate with authentication and encryption

    Add `hearth-network` crate with authentication and encryption

    Adds a hearth-network crate for putting all of our authentication, encryption, and client-server communication in.

    I implemented password authentication and key exchange (PAKE) using Facebook's "OPAQUE" algorithm (in the opaque-ke crate), which has been audited. I used the ChaCha20 cipher for the stream cipher. I use a constant, zeroed IV for all communication after PAKE. PAKE should generate a unique key per session, so the IV shouldn't really matter. I attempted to use ChaCha20Poly1305 for encryption with AEAD but gave up because that would require chunking up the streams into variable-length packets and I'm not experienced enough with writing low-level Tokio code to make that work with a custom AsyncRead/AsyncWrite implementation on top of an existing async transport.

    I'm definitely no cryptographer, so we should definitely get this reviewed by someone who knows what they're doing. That's not high-priority though because Hearth has security through obscurity for the foreseeable future.

    • [x] Remove debug eprintln calls
    enhancement 
    opened by marceline-cramer 0
  • Downgrade clap v4 to v3 in all binary targets

    Downgrade clap v4 to v3 in all binary targets

    I personally disagree with the clap developers' decision to change the theming of --help docs from these nice colored sections to monochrome text: https://github.com/clap-rs/clap/issues/4132. I think that this hurts readability, and that strong color-coding will be important in Hearth when running hearth-ctl while in-space.

    This unfortunately can't be reverted in clap v4. The clap devs may add in styling for docs in the future, but the future is not now. However, the structopt crate provides the same procedural macro-based argument parsing, but on clap v3, which has the old colored output.

    Downgrading from clap v4 to clap v3 won't have any serious consequences on the argument parsing itself, so it's not like we're sacrificing features for this. However, if anyone prefers the uncolored clap v4 output over the colored clap v3 output, please pitch in your opinion in this issue so that we can discuss it more.

    For now, I'm using clap v4 in #19.

    If we do decide to use structopt, clap v4 will need to replaced in three of our crates:

    • hearth-client
    • hearth-server
    • hearth-ctl
    enhancement 
    opened by marceline-cramer 4
  • client: server DNS address resolution

    client: server DNS address resolution

    Add support to clients to connect to servers by their hostnames.

    We'll need to replace the SocketAddr in Args with a String, then first attempt to parse it to an IP address, and if that fails, try looking up the DNS. We can use trust-dns-resolver to look up hostnames.

    If parsing out the port is too complicated to do in conjunction with parsing hostnames/IPs, we can move the port into a different argument. In that case, we should adjust the server to take the port separately as well.

    If parsing fails, please fail nicely with good error messages!

    DNS resolution isn't necessary on servers, as far as I know, because most of the time we'll just be binding to a fixed IP.

    enhancement 
    opened by marceline-cramer 0
  • Add CONTRIBUTORS.md

    Add CONTRIBUTORS.md

    Add a document describing guidelines for contributors to Hearth's source code.

    This should include:

    1. Branch naming scheme.
    2. Basic git tutorial for contributing?
    3. Rust coding style (remind people to run rustfmt).
    4. Log message guidelines.
    5. Commit guidelines.
    6. Commit message style and reasoning for it.
    7. Suggestion to add credits to the README.
    8. CLA for the AGPL, or even just a FAQ explaining the consequences?
    9. Add credits to affected crate's authors list?
    10. A big thank you for the help! :)

    Also add a section for credits in the README for step 4.

    Remember to check this off of the roadmap when complete.

    documentation 
    opened by marceline-cramer 0
  • wasm: add bytemuck support to GuestMemory

    wasm: add bytemuck support to GuestMemory

    Add generic bytemuck-compatible functions to GuestMemory to read custom structs and custom slices of structs from guest memory.

    Canary's source has an example of this working: https://git.tebibyte.media/canary/canary-rs/src/commit/4b89e781b06cfe4fff045a35bb77bdbfd6b675a0/src/backend/wasmtime.rs#L206

    enhancement 
    opened by marceline-cramer 0
  • font-mud: track anchor position and scaling of MSDF glyphs

    font-mud: track anchor position and scaling of MSDF glyphs

    Each font bitmap should track the real-number scaling factor applied between pixels and the font face's unit space.

    The "anchor" is the origin point in the font glyph outlines, which may be at any position inside of the bitmap. Each font bitmap should have an anchor in scaled space corresponding to the transformed origin of the font glyph.

    The Framing structure created in GlyphBitmap::new() contains the translation and scaling info that can be used to set both the scaling and the anchor.

    enhancement 
    opened by marceline-cramer 0
Owner
null
A rust crate for working with colors and color spaces.

Color Art A rust crate for working with colors and color spaces. Documentation See Color Art. Usage Add Dependency [dependencies] color-art = "0.2" Co

cx33 5 Dec 30, 2022
A simple made in Rust crack, automatic for Winrar, activated from shared virtual memory, for studies.

Simple Winrar Crack in Rust What does it do ? A simple project that allows you to modify the license check used by WinRaR, "RegKey" from virtual memor

João Vitor 7 Jan 2, 2023
dhcpm is a CLI tool for constructing & sending DHCP messages

dhcpm Sponsor Thank you to Bluecat for sponsoring this work! dhcpm leverages dhcproto check that out for the DHCP protocol. About A cli tool (and dhcp

Evan Cameron 12 Mar 28, 2022
rusty-donut - ASCII raymarching inside a terminal

ASCII raymarching inside a terminal

drip 14 Feb 9, 2022
Works out if this is running from inside a shell, and if so, which one.

pshell pshell answers the question "Is my application running in a shell, and if so, which one". Example: you are installing something and want to mak

Alec Brown 2 Nov 3, 2022
Check if the process is running inside Windows Subsystem for Linux (Bash on Windows)

is-wsl Check if the process is running inside Windows Subsystem for Linux (Bash on Windows) Inspired by sindresorhus/is-wsl and made for Rust lang. Ca

Sean Larkin 6 Jan 31, 2023
A tool to format codeblocks inside markdown and org documents.

cbfmt (codeblock format) A tool to format codeblocks inside markdown, org, and restructuredtext documents. It iterates over all codeblocks, and format

Lukas Reineke 126 May 26, 2023
Show HTML content "inside" your egui rendered application

hframe Show HTML content "inside" your egui rendered application. "hframe" stands for "HTML Frame". Note: hframe only works when the application is co

Franco Profeti 3 Feb 26, 2024
Execution of and interaction with external processes and pipelines

subprocess The subprocess library provides facilities for execution of and interaction with external processes and pipelines, inspired by Python's sub

Hrvoje Nikšić 375 Jan 2, 2023
Low level access to processors using the AArch64 execution state.

aarch64-cpu Low level access to processors using the AArch64 execution state. Usage Please note that for using this crate's register definitions (as p

Rust Embedded 18 Jan 5, 2023
Poisson intensity of limit order execution, calibration of parameters A and k using level 1 tick data

Poisson intensity of limit order execution, calibration of parameters A and k using level 1 tick data Description A limit order placed at a price St ±

0xCuteSocks 6 Apr 9, 2023
Yet another code execution engine written in Rust.

exec Yet another blazingly fast code execution engine written in Rust. Paths GET /api/v1/status GET /api/v1/runtimes POST /api/v1/execute POST /api/v1

Stefan Asandei 2 Jul 11, 2023
A CLI for extracting libraries from Apple's dyld shared cache file

dyld-shared-cache-extractor As of macOS Big Sur, instead of shipping the system libraries with macOS, Apple ships a generated cache of all built in dy

Keith Smiley 238 Jan 4, 2023
This repo contains crates that are used to create the micro services and keep shared code in a common place.

MyEmma Helper Crates This repo contains crates that can are reused over different services. These crate are used in projects at MyEmma. But these crat

MyEmma 1 Jan 14, 2022
Shared Rust libraries for Hyperledger Indy.

indy-shared-rs Shared Rust libraries for Hyperledger Indy. indy-credx: Indy verifiable credential issuance and presentation (aka Anoncreds) indy-data-

Hyperledger 18 Dec 29, 2022
Shared k-mer content between two genomes

skc skc is a simple tool for finding shared k-mer content between two genomes. Installation Prebuilt binary curl -sSL skc.mbh.sh | sh # or with wget w

Michael Hall 16 Jun 26, 2023
A safe and idiomatic wrapper over shared memory APIs in rust with proper cleanups.

shmem-bind A safe and idiomatic wrapper over shared memory APIs in rust with proper cleanups. Quick start: check the message-passing example for bette

ArshiA Akhavan 3 Apr 6, 2024
An interactive shell environment for exploring the p2panda protocol

An interactive shell environment for exploring the p2panda protocol. Uses a mock node and clients to simulate network logic.

null 4 Dec 12, 2021
Code and Development environment for adventofcode.com - 2021 edition

aoc-2021 Warning Spoiler Alert! If you want to solve the aoc problems on your own, do not read any further. This repository contains solutions for the

docToolchain 11 Oct 22, 2022