State machine engine

Overview

orga

Deterministic state machine engine written in Rust

CI codecov Crate API

Orga is a stack for building blockchain applications powered by Tendermint consensus.

Status: Orga is not ready for production applications, but is in rapid development. Some APIs are subject to change.

Module Status

Module Description Completeness API Stability
ed Minimalist traits for fast, deterministic encoding/decoding Provides Encode and Decode traits, with implementations for many built-in types (integers, Vec<T: Encode + Decode>, etc.). Will likely add tools for easier handmade encodings and composable encoding types (e.g. length-prefixed arrays). Unlikely to change.
ed_derive Derive macros for ed::Encode and ed::Decode Derive macros are implemented for structs. Still needs enum support. Can not change (only provides derive macros).
orga::abci Integration with ABCI (gated by abci feature) Implements ABCI app abstraction with serial tx processing. Still needs full ABCI pipeline for parallel tx processing. Likely to change significantly.
orga::collections State data structures which implement orga::state::State trait Implements Map, Set, Deque. Will likely add more. May change significantly as we explore different paradigms.
orga::merkstore Integration with merk (gated by merk feature) Implements orga::store::Store trait for Merk storage, and implements abci::ABCIStore so it can be used in an ABCI app. Will grow as orga::store grows, e.g. implementing orga::store::Iter to iterate through entries. Unlikely to change beyond changes in orga::store.
orga::state Traits for representing state data using higher-level abstractions (on top of a orga::store::Store implementation) Implements base State trait, and basic implementations of it such as Value<T>. May change significantly as we explore different paradigms.
orga::store Traits and implementations for low-level key/value store abstraction Implements base Store trait, and many composable implementations such as MapStore, NullStore, Prefixed, etc. Will likely add more composable pieces. The base traits may change minorly, overall paradigm is stable.
orga_macros Macros for Orga traits. Implements #[state] macro for combining orga::state::State implementations into struct hierarchies. Currently only supports normal structs, will likely support e.g. enums. Unlikely to change.

Project Goals

  • Performance - To serve a large user base, blockchains need to be engineered for high throughput, e.g. 10k+ transactions per second. Orga is engineered for maximum concurrency and with the ability to use the right data structures.
  • Simplicity - Keeping complexity under control makes it easier to understand the system, prevent flaws, and introduce new functionality. When thinking something through, a good heuristic is to choose the solution with fewer lines of code or smaller compiler output.
  • Ease of use - In our earlier work on LotionJS, we discovered that blockchain development can be fast and pleasant with the right abstractions. We aim to replicate this experience in Orga.
  • Idiomatic Rust - When figuring out how to do something, we can often answer it by asking "what would the Rust standard library do?".
Comments
  • Iteration API for `collections::Map`

    Iteration API for `collections::Map`

    It's not 100% obvious how this should be best implemented - iterating though all recursive child entries would be too expensive for children with many descendant entries.

    Can we somehow seek to the next key prefix by simply incrementing the last byte and seeking to the next entry from there? (This may be incorrect for some encodings - we may need some generic way of incrementing keys).

    opened by mappum 3
  • Query handling

    Query handling

    We currently only expose raw queries by key. While this could potentially support every use-case, it's hard to work with since some higher-level queries require sequential access, e.g. reading the value at key A to determine key B. With the current raw queries, a client would have to make multiple round-trips plus both the client and node would need to support querying for a given past height.

    It could be a lot easier to instead support higher-level queries at the orga collection level. For example, a query of 3 could be passed to a Deque, in order to query the element at index 3. When resolving the query, a node would need to look up the deque head/tail value, then use that to determine the key for the item at index 3. The resulting proof would contain the key/value entries for both the head/tail value and the item at index 3, so the client can reproduce the deque operation for themselves.

    Doing it this way, the implementation does not need to do anything other than call the normal getter function, with a Store implementation which records each access and adds it to the proof.

    This could be implemented by adding a general Query trait, where multiplexed state structs just route queries to their children, and collections implement logical query handlers.

    Rough Example:

    pub trait Query {
      fn query(&self, query: &[u8]) -> Result<()>;
    }
    
    ...
    
    let store = ProofBuilder::new(some_other_store); // special store wrapper that builds proof as keys are read
    let state: SomeState = store.wrap()?; // some state object that implements Query
    state.query(user_query)?; // resolve query given arbitrary query bytes from user
    let proof = store.proof(); // pull out proof from store wrapper
    
    opened by mappum 3
  • Query

    Query

    This PR add traits which standardize calls (triggered by transactions), queries, and clients which can call and query state remotely.

    TODO:

    • [x] Call trait
    • [x] Query trait
    • [ ] ~~Client trait~~
    • [x] Finalize macro expansion code
    • [ ] ~~Client macro~~
    • [ ] ~~Doc comments~~

    Closes #29

    opened by mappum 2
  • Deque tests

    Deque tests

    In adding tests to deque, pop_front and pop_back API was changed to return a reference to an immutable, owned value of type T contained in Deque. This makes the interface to the Deque closer to that of the VecDeque in rust. This also changed the remove method of the map, which now returns Result<Option<ReadOnly>>.

    opened by cwlittle 2
  • Make Write methods infallible

    Make Write methods infallible

    This is an experiment and could end up getting reverted, but now I realize that essentially all Store writes can never error since they are just writing to in-memory data structures, and only ever get written to the actual on-disk database in one batch at the end of a block. If we change the Write trait methods to not return Results, we can make types that write their value when dropped and probably do other convenient tricks.

    Instead of using the Infallible type, we can just change the Write trait and add a TryWrite for the lower-level database store interfaces (if necessary - they could also do the fallible writing in a flush method since they also just collect data in memory).

    opened by mappum 2
  • Tendermint Client

    Tendermint Client

    We can implement the Read trait for a client which queries Tendermint RPC. This isn't a Store since it's read-only, but is useful for client logic which only needs to read.

    This could be a struct called something like TendermintClient which would probably belong in the abci module since that's where all the Tendermint-specific stuff lives.

    let client = TendermintClient::new("localhost:26657").unwrap();
    
    opened by mappum 2
  • Swap MapEntry::or_insert() for Map::insert() in Deque push methods

    Swap MapEntry::or_insert() for Map::insert() in Deque push methods

    Resolves #107 in some capacity. Calling Deque's push_front or push_back calling MapEntry::or_insert() was causing panics for unwrap at None value @ line 836 of Map. This resolves the issue in the context of some usages, but there may be more paths that lead to this same issue. Blocked by #108.

    opened by cwlittle 1
  • DerefMut causes unwrap() on presumably never None value

    DerefMut causes unwrap() on presumably never None value

    The following code causes unwrap() on None value @ line 836 of orga/collections/map when followed by queue.push_back() equivalent from parent State type holding Deque as complex State type:

            let mut queue = Self::create(store.clone(), data)?;
            queue.deque.pop_back()?;
            let decoded_adapter: HeaderAdapter = Decode::decode(trusted_header.as_slice())?;
            let wrapped_header = WrappedHeader::new(decoded_adapter, trusted_height);
            let work_header = WorkHeader::new(wrapped_header.clone(), wrapped_header.work());
    
            queue.current_work = wrapped_header.work();
            queue.deque.push_front(work_header.into())?;
    
            Ok(queue)
    
    opened by cwlittle 1
  • Rename Providers to Plugins

    Rename Providers to Plugins

    This PR moves plugins to a new directory, renames our existing plugin providers, and moves the Context struct and GetContext trait to their own top-level module.

    opened by keppel 1
  • Tendermint config

    Tendermint config

    This PR:

    • Exposes Tendermint stdout / stderr configuration
    • Changes the way we specify a genesis in Node (previously took a path to the genesis, now expects bytes eg. via include_bytes!())
    • Puts app data in the user's home directory instead of cwd by default
    • Uses a locally-installed Tendermint binary instead of whatever's in the user's path
    opened by keppel 1
  • Fail when writing key lengths >= 256 bytes to Store

    Fail when writing key lengths >= 256 bytes to Store

    This is an easy safety fix to prevent a case where a key >= 256 bytes written to the store will cause the entire block to fail when writing to merk.

    Will wait to merge this after #79 (will require changing the returned error) in the interest of not keeping that PR open forever.

    Closes #61

    In the future, we can do a better form of checking at compile-time once ed has some sort of const generic length encoding length fields.

    opened by mappum 1
  • [v2] Fix arm64 builds

    [v2] Fix arm64 builds

    Target for arm64 should be aarch64. This is required in both latest and v2 due to migration imports in nomic.

    Nomic arm64 build confirmed to work here https://github.com/agouin/nomic/tree/andrew/aarch64 (incorporates these changes in v2 and v3)

    In order to fix nomic aarch64 builds:

    • Merge this PR into v2-legacy-main, and merge this same patch into develop #153 and v3-main #155
    • Update v2 import in develop to latest v2-legacy-main
    • Update orga v2-legacy-main import to latest in nomic branch v2-legacy-main
    • Update nomic nomicv2 import in develop branch to latest v2-legacy-main and orga import to latest v3-main
    opened by agouin 0
  • Support method-aware derive macros in Rust Analyzer

    Support method-aware derive macros in Rust Analyzer

    We have a few derive macros which read the source of the calling file to find relevant methods outside of the item the macro is invoked on (Call, Query, and Client). This behavior depends on Span::source_file in proc_macro, which is experimental under the proc_macro_span feature.

    Rust Analyzer doesn't support this feature, so the derive macros are unable to find relevant methods in a RA context. This will need a creative solution to inform the macro of the relevant methods, which may involve a build script and writing file path info to disk to be read by the macro, or a macro which writes an attribute containing the relative source path into the original source.

    opened by mappum 0
Owner
Nomic
Nomic
State of the art "build your own engine" kit powered by gfx-hal

A rendering engine based on gfx-hal, which mimics the Vulkan API. Building This library requires standard build tools for the target platforms, except

Amethyst Foundation 801 Dec 28, 2022
Minecraft-esque voxel engine prototype made with the bevy game engine. Pending bevy 0.6 release to undergo a full rewrite.

vx_bevy A voxel engine prototype made using the Bevy game engine. Goals and features Very basic worldgen Animated chunk loading (ala cube world) Optim

Lucas Arriesse 125 Dec 31, 2022
A framework for saving and loading game state in Bevy.

Bevy_save A framework for saving and loading game state in Bevy. Features bevy_save is primarily built around extension traits to Bevy's World. Serial

Hank Jordan 10 Jan 24, 2023
A rollback library that buffers component state. Useful for netcode.

bevy_timewarp Buffer and rollback to states up to a few frames ago, for rollback networking. Doesn't do any networking, just concerned with buffering

Richard Jones 7 Sep 4, 2023
Bad Apple!! for the Uxn stack-machine

bad-apple-uxn Bad Apple!! for the Uxn stack-machine by Hundred Rabbits. Quick start cargo run --release -- --input assets/badapple.mp4 --output badapp

Karol Belina 14 Nov 10, 2022
A refreshingly simple data-driven game engine built in Rust

What is Bevy? Bevy is a refreshingly simple data-driven game engine built in Rust. It is free and open-source forever! WARNING Bevy is still in the ve

Bevy Engine 21.1k Jan 4, 2023
A modern 3D/2D game engine that uses wgpu.

Harmony A modern 3D/2D game engine that uses wgpu and is designed to work out of the box with minimal effort. It uses legion for handling game/renderi

John 152 Dec 24, 2022
RTS game/engine in Rust and WebGPU

What is this? A real time strategy game/engine written with Rust and WebGPU. Eventually it will be able to run in a web browser thanks to WebGPU. This

Thomas SIMON 258 Dec 25, 2022
unrust - A pure rust based (webgl 2.0 / native) game engine

unrust A pure rust based (webgl 2.0 / native) game engine Current Version : 0.1.1 This project is under heavily development, all api are very unstable

null 368 Jan 3, 2023
Basic first-person fly camera for the Bevy game engine

bevy_flycam A basic first-person fly camera for Bevy 0.4 Controls WASD to move horizontally SPACE to ascend LSHIFT to descend ESC to grab/release curs

Spencer Burris 85 Dec 23, 2022
A no-frills Tetris implementation written in Rust with the Piston game engine, and Rodio for music.

rustris A no-frills Tetris implementation written in Rust with the Piston game engine, and Rodio for music. (C) 2020 Ben Cantrick. This code is distri

Ben Cantrick 17 Aug 18, 2022
Inspector plugin for the bevy game engine

bevy-inspector-egui This crate provides the ability to annotate structs with a #[derive(Inspectable)], which opens a debug interface using egui where

Jakob Hellermann 517 Dec 31, 2022
Crossterm plugin for the bevy game engine

What is bevy_crossterm? bevy_crossterm is a Bevy plugin that uses crossterm as a renderer. It provides custom components and events which allow users

null 79 Nov 2, 2022
A dependency-free chess engine library built to run anywhere.

♔chess-engine♚ A dependency-free chess engine library built to run anywhere. Demo | Docs | Contact Me Written in Rust ?? ?? Why write a Chess engine?

adam mcdaniel 355 Dec 26, 2022
Concise Reference Book for the Bevy Game Engine

Unofficial Bevy Cheat Book Click here to read the book! Concise reference to programming in the Bevy game engine. Covers useful syntax, features, prog

null 947 Jan 8, 2023
COSI Engine

engine ======= This project is an implementation of the COSI specification written in Rust. This engine is effectively a systemd (pid 1) alternative w

null 38 Sep 27, 2022
Rustcraft is a simple Minecraft engine written in rust using wgpu.

Rustcraft is a simple Minecraft engine written in rust using wgpu.

Raphael Van Hoffelen 110 Dec 22, 2022
Easy to use game engine

arcana Arcana is a game engine built with focus on ease of use without compromising on level of control. Getting started Starting writing a game is as

Zakarum 3 Feb 11, 2022
Proof-of-concept of getting OpenXR rendering support for Bevy game engine using gfx-rs abstractions

Introduction Proof-of-concept of getting OpenXR rendering support for Bevy game engine using gfx-rs abstractions. (hand interaction with boxes missing

Mika 52 Nov 14, 2022