diff --git a/Cargo.lock b/Cargo.lock index 635c6c64c..f1406202e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,5 +3,126 @@ version = 3 [[package]] -name = "common" +name = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "good_memory_allocator" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1651659e016ea4259760966432aebcc96c81e26743fb018c59585ddd677127e" +dependencies = [ + "either", + "spin", +] + +[[package]] +name = "kona-common" version = "0.0.1" +dependencies = [ + "anyhow", + "good_memory_allocator", + "num", +] + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "num" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +dependencies = [ + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] diff --git a/Cargo.toml b/Cargo.toml index f842da551..512cb2a51 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ homepage = "https://github.com/anton-rs/kona" exclude = ["**/target", "benches/", "tests"] [workspace.dependencies] -anyhow = "1.0.75" +anyhow = { version = "1.0.75", default-features = false } tracing = "0.1.40" [profile.dev] diff --git a/README.md b/README.md index f1fa58571..a008c67c9 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,13 @@ This repository also contains an implementation of the [`op-program` specificati ## Overview -*TODO* +*todo* + +``` +crates +├── `common-client`: A suite of utilities for developing `client` programs to be ran on top of Fault Proof VMs. +└── `common-host`: A suite of utilities for developing `host` programs. +``` ## Credits diff --git a/build/Makefile b/build/Makefile new file mode 100644 index 000000000..f54ba7f3f --- /dev/null +++ b/build/Makefile @@ -0,0 +1,5 @@ +all: cannon + +.PHONY: cannon +cannon: + docker build -t cannon-pipeline:latest -f cannon/cannon.dockerfile ./cannon diff --git a/build/README.md b/build/README.md new file mode 100644 index 000000000..8dc77abde --- /dev/null +++ b/build/README.md @@ -0,0 +1,22 @@ +# `kona-build` + +This directory contains the [`cross`][cross] docker images and custom `rustc` targets used to build verifiable programs targeting various FPVMs. + +## Usage + +### Building Images + +To build the images, run `make` in the root of this directory. + +### Compiling Programs + +``` +docker run \ + --rm \ + --platform linux/amd64 \ + -v `pwd`/:/workdir \ + -w="/workdir" \ + cannon-pipeline:latest cargo build --release -Zbuild-std +``` + +[cross]: https://github.com/cross-rs/cross diff --git a/build/cannon/cannon.dockerfile b/build/cannon/cannon.dockerfile new file mode 100644 index 000000000..703e86dbd --- /dev/null +++ b/build/cannon/cannon.dockerfile @@ -0,0 +1,41 @@ +# This image and the `mips-unknown-none` target were derived from `BadBoiLabs`'s +# `cannon-rs` project. +# +# https://github.com/BadBoiLabs/Cannon-rs + +FROM --platform=linux/amd64 ubuntu:22.04 + +ENV SHELL=/bin/bash +ENV DEBIAN_FRONTEND noninteractive + +# todo: pin `nightly` version +ENV RUST_VERSION nightly + +RUN apt-get update && apt-get install --assume-yes --no-install-recommends \ + ca-certificates \ + build-essential \ + curl \ + g++-mips-linux-gnu \ + libc6-dev-mips-cross \ + binutils-mips-linux-gnu \ + llvm \ + clang \ + make \ + cmake \ + git + +# Install Rustup and Rust +RUN curl https://sh.rustup.rs -sSf | bash -s -- -y --default-toolchain ${RUST_VERSION} --component rust-src +ENV PATH="/root/.cargo/bin:${PATH}" + +# Add the special cannon build target +COPY ./mips-unknown-none.json . + +# Set up the env vars to instruct rustc to use the correct compiler and linker +# and to build correctly to support the Cannon processor +ENV CC_mips_unknown_none=mips-linux-gnu-gcc \ + CXX_mips_unknown_none=mips-linux-gnu-g++ \ + CARGO_TARGET_MIPS_UNKNOWN_NONE_LINKER=mips-linux-gnu-gcc \ + RUSTFLAGS="-Clink-arg=-e_start -C llvm-args=-mno-check-zero-division" \ + CARGO_BUILD_TARGET="/mips-unknown-none.json" \ + RUSTUP_TOOLCHAIN=${RUST_VERSION} diff --git a/build/cannon/mips-unknown-none.json b/build/cannon/mips-unknown-none.json new file mode 100644 index 000000000..9d0ce305e --- /dev/null +++ b/build/cannon/mips-unknown-none.json @@ -0,0 +1,19 @@ +{ + "arch": "mips", + "cpu": "mips32", + "llvm-target": "mips-unknown-none", + "data-layout": "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64", + "target-endian": "big", + "target-pointer-width": "32", + "target-c-int-width": "32", + "os": "none", + "features": "+soft-float,+mips32,-mips32r2", + "max-atomic-width": "0", + "linker": "rust-lld", + "linker-flavor": "ld.lld", + "executables": true, + "panic-strategy": "abort", + "relocation-model": "static", + "emit-debug-gdb-scripts": false, + "singlethread": true +} diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml index 28b0cd981..73ed05d93 100644 --- a/crates/common/Cargo.toml +++ b/crates/common/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "common" -description = "common crate" +name = "kona-common" +description = "Common traits and utilities for Kona" version = { workspace = true } edition = { workspace = true } authors = { workspace = true } @@ -9,3 +9,9 @@ repository = { workspace = true } homepage = { workspace = true } [dependencies] +# workspace +anyhow.workspace = true + +# external +num = { version = "0.4.1", default-features = false } +good_memory_allocator = "0.1.7" diff --git a/crates/common/README.md b/crates/common/README.md index f6849c03a..26b6055b9 100644 --- a/crates/common/README.md +++ b/crates/common/README.md @@ -1,3 +1,5 @@ # `kona-common` +A suite of utilities for developing `host` programs and verifiable `client` executables. + *TODO* diff --git a/crates/common/src/lib.rs b/crates/common/src/lib.rs index fcbe40466..d1c98b58a 100644 --- a/crates/common/src/lib.rs +++ b/crates/common/src/lib.rs @@ -7,5 +7,7 @@ )] #![deny(unused_must_use, rust_2018_idioms)] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] +#![cfg_attr(not(test), no_std)] -// TODO +pub mod malloc; +pub mod traits; diff --git a/crates/common/src/malloc.rs b/crates/common/src/malloc.rs new file mode 100644 index 000000000..0d7e57d1e --- /dev/null +++ b/crates/common/src/malloc.rs @@ -0,0 +1,44 @@ +//! This module contains an implementation of a basic memory allocator for client programs in +//! running on top of various FPVMs. The allocator is a linked list allocator based on the +//! `dlmalloc` algorithm, which is a well-known and widely used allocator software such +//! as OS Kernels. + +#[cfg(not(test))] +use good_memory_allocator::SpinLockedAllocator; + +/// The global allocator for the program in the `test` profile uses the standard allocator. +#[cfg(test)] +#[global_allocator] +static ALLOCATOR: std::alloc::System = std::alloc::System; + +/// The global allocator for the program in other profiles uses the [SpinLockedAllocator]. +#[cfg(not(test))] +#[global_allocator] +static ALLOCATOR: SpinLockedAllocator = SpinLockedAllocator::empty(); + +/// Initialize the [SpinLockedAllocator] with the following parameters: +/// * `heap_start_addr` is the starting address of the heap memory region, +/// * `heap_size` is the size of the heap memory region in bytes. +/// +/// # Safety +/// This function is unsafe because the caller must ensure: +/// * The allocator has not already been initialized. +/// * The provided memory region must be valid, non-null, and not used by anything else. +/// * After aligning the start and end addresses, the size of the heap must be > 0, or the function +/// will panic. +#[cfg_attr(test, allow(unused_variables))] +pub unsafe fn init_allocator(heap_start_addr: usize, heap_size: usize) { + #[cfg(not(test))] + ALLOCATOR.init(heap_start_addr, heap_size) +} + +/// Initialize heap memory for the `client` program with +#[macro_export] +macro_rules! init_heap { + ($size:expr) => {{ + use kona_common::malloc::init_allocator; + + static mut HEAP: [u8; $size] = [0u8; $size]; + unsafe { init_allocator(HEAP.as_ptr() as usize, $size) } + }}; +} diff --git a/crates/common/src/traits/mod.rs b/crates/common/src/traits/mod.rs new file mode 100644 index 000000000..5d479409d --- /dev/null +++ b/crates/common/src/traits/mod.rs @@ -0,0 +1,10 @@ +//! Contains common traits for the `client` role. +//! +//! When developing a new `client` program, these traits are implemented on an +//! architecture-specific type that provides the concrete implementation of the +//! kernel interfaces. The `client` program then uses these traits to perform operations +//! without needing to know the underlying implementation, which allows the same `client` +//! program to be compiled and ran on different target FPVM architectures. + +mod syscall; +pub use syscall::KernelIO; diff --git a/crates/common/src/traits/syscall.rs b/crates/common/src/traits/syscall.rs new file mode 100644 index 000000000..9bab6cccc --- /dev/null +++ b/crates/common/src/traits/syscall.rs @@ -0,0 +1,31 @@ +//! Defines the [KernelIO] trait, which describes the functionality of several +//! system calls inside of the FPVM kernel. This trait is to be implemented by the +//! `client` program, and then used by the `kernel` to perform IO operations. + +use anyhow::Result; +use num::Unsigned; + +/// The [KernelIO] trait describes the functionality of several system calls inside of +/// the FPVM kernel. Commonly, FPVMs delegate IO operations to custom file descriptors in +/// the `client` program. +/// +/// +/// The `RS` type parameter is the size of the registers in the VM. On MIPS32 for example, +/// this would be 32, and on RISC-V/64 this would be 64. +/// +/// In cases where the set of system calls defined in this trait need to be extended, an +/// additional trait should be created that extends this trait. +pub trait KernelIO { + /// Associated type for the file descriptors available. + type FileDescriptor; + + /// Write the given buffer to the given file descriptor. + fn write(fd: Self::FileDescriptor, buf: &[u8]) -> Result; + + /// Read from the given file descriptor into the passed buffer. + fn read(fd: Self::FileDescriptor, buf: &mut [u8]) -> Result; + + /// Exit the process with the given exit code. The implementation of this function + /// should always panic after invoking the `EXIT` syscall. + fn exit(code: RS) -> !; +}