From 04439be351eaa19080a751a9bf5354c8e808cfbf Mon Sep 17 00:00:00 2001 From: clabby Date: Wed, 20 Dec 2023 19:40:57 -0500 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Example=20&=20`asterisc`=20build=20?= =?UTF-8?q?image?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 ++ Cargo.toml | 1 + README.md | 3 +- build/README.md | 14 ++--- build/asterisc/.gitkeep | 0 build/asterisc/asterisc.dockerfile | 33 ++++++++++++ build/justfile | 6 +++ crates/common/src/asterisc/io.rs | 11 ++-- crates/common/src/asterisc/mod.rs | 2 +- crates/common/src/asterisc/syscall.rs | 9 +++- crates/common/src/cannon/io.rs | 13 ++--- crates/common/src/cannon/syscall.rs | 4 +- crates/common/src/io.rs | 6 +-- crates/common/src/lib.rs | 1 + examples/minimal/Cargo.lock | 78 +++++++++++++++++++++++++++ examples/minimal/Cargo.toml | 13 +++++ examples/minimal/README.md | 3 ++ examples/minimal/justfile | 17 ++++++ examples/minimal/src/main.rs | 27 ++++++++++ justfile | 27 ++++++++++ 20 files changed, 245 insertions(+), 26 deletions(-) delete mode 100644 build/asterisc/.gitkeep create mode 100644 build/asterisc/asterisc.dockerfile create mode 100644 examples/minimal/Cargo.lock create mode 100644 examples/minimal/Cargo.toml create mode 100644 examples/minimal/README.md create mode 100644 examples/minimal/justfile create mode 100644 examples/minimal/src/main.rs diff --git a/.gitignore b/.gitignore index 8ea857a43..5296cdcdb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ # Rust target target + +# Example targets +examples/**/target diff --git a/Cargo.toml b/Cargo.toml index 512cb2a51..92192c230 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,6 @@ [workspace] members = ["crates/*"] +exclude = ["examples/minimal"] resolver = "2" [workspace.package] diff --git a/README.md b/README.md index fea24f4f9..2870372b9 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,8 @@ verify an [L2 output root][g-output-root] from the L1 inputs it was [derived fro * [`host`](./bin/host): The host program that runs natively alongside the FPVM, serving as the [Preimage Oracle][g-preimage-oracle] server. **Build Pipelines** -*todo* +* [`cannon`](./build/cannon): Docker image for compiling to the bare-metal `mips-unknown-none` target. +* [`asterisc`](./build/asterisc): Docker image for compiling to the bare-metal `riscv64gc-unknown-none-elf` target. **`client` / `host` SDK** * [`common`](./crates/common): A suite of utilities for developing `client` programs to be ran on top of Fault Proof VMs. diff --git a/build/README.md b/build/README.md index 8b18a1c38..8c87bfa93 100644 --- a/build/README.md +++ b/build/README.md @@ -1,12 +1,12 @@ # `kona-build` -This directory contains the [`cross`][cross] docker images and custom `rustc` targets used to build verifiable programs targeting various FPVMs. +This directory contains the cross compilation 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. +To build the images, run `just` in the root of this directory. ### Compiling Programs @@ -23,8 +23,10 @@ docker run \ **asterisc** ``` -RUSTFLAGS="-Clink-arg=-e_start -C target-feature=-c" \ - cargo build --target riscv64gc-unknown-none-elf --release +docker run \ + --rm \ + --platform linux/amd64 \ + -v `pwd`/:/workdir \ + -w="/workdir" \ + asterisc-pipeline:latest cargo build --release -Zbuild-std ``` - -[cross]: https://github.com/cross-rs/cross diff --git a/build/asterisc/.gitkeep b/build/asterisc/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/build/asterisc/asterisc.dockerfile b/build/asterisc/asterisc.dockerfile new file mode 100644 index 000000000..5e8e4a4c5 --- /dev/null +++ b/build/asterisc/asterisc.dockerfile @@ -0,0 +1,33 @@ +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++-riscv64-linux-gnu \ + libc6-dev-riscv64-cross \ + binutils-riscv64-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}" + +# 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_riscv64_unknown_none_elf=riscv64-linux-gnu-gcc \ + CXX_riscv64_unknown_none_elf=riscv64-linux-gnu-g++ \ + CARGO_TARGET_RISCV64_UNKNOWN_NONE_ELF_LINKER=riscv64-linux-gnu-gcc \ + RUSTFLAGS="-Clink-arg=-e_start -Ctarget-feature=-c" \ + CARGO_BUILD_TARGET="riscv64gc-unknown-none-elf" \ + RUSTUP_TOOLCHAIN=${RUST_VERSION} diff --git a/build/justfile b/build/justfile index c65ba6af1..2e279e959 100644 --- a/build/justfile +++ b/build/justfile @@ -1,3 +1,9 @@ +all: cannon asterisc + # Build the `cannon` program builder image cannon: docker build -t cannon-pipeline:latest -f cannon/cannon.dockerfile ./cannon + +# Build the `asterisc` program builder image +asterisc: + docker build -t asterisc-pipeline:latest -f asterisc/asterisc.dockerfile ./asterisc diff --git a/crates/common/src/asterisc/io.rs b/crates/common/src/asterisc/io.rs index df6a1e8dc..f432ede9a 100644 --- a/crates/common/src/asterisc/io.rs +++ b/crates/common/src/asterisc/io.rs @@ -1,7 +1,10 @@ -use crate::{asterisc::syscall, traits::BasicKernelInterface, types::RegisterSize}; +use crate::{ + asterisc::syscall, io::FileDescriptor, traits::BasicKernelInterface, types::RegisterSize, +}; use anyhow::Result; /// Concrete implementation of the [`KernelIO`] trait for the `riscv64` target architecture. +#[derive(Debug)] pub struct AsteriscIO; /// Relevant system call numbers for the `riscv64` target architecture. @@ -13,7 +16,7 @@ pub struct AsteriscIO; /// the [BasicKernelInterface] trait is created for the `asterisc` kernel, this list should be extended /// accordingly. #[repr(u32)] -pub enum SyscallNumber { +pub(crate) enum SyscallNumber { /// Sets the Exited and ExitCode states to true and $a0 respectively. Exit = 93, /// Similar behavior as Linux with support for unaligned reads. @@ -23,7 +26,7 @@ pub enum SyscallNumber { } impl BasicKernelInterface for AsteriscIO { - fn write(fd: Self::FileDescriptor, buf: &[u8]) -> Result { + fn write(fd: FileDescriptor, buf: &[u8]) -> Result { unsafe { Ok(syscall::syscall3( SyscallNumber::Write as usize, @@ -34,7 +37,7 @@ impl BasicKernelInterface for AsteriscIO { } } - fn read(fd: Self::FileDescriptor, buf: &mut [u8]) -> Result { + fn read(fd: FileDescriptor, buf: &mut [u8]) -> Result { unsafe { Ok(syscall::syscall3( SyscallNumber::Read as usize, diff --git a/crates/common/src/asterisc/mod.rs b/crates/common/src/asterisc/mod.rs index 05fcc1a3e..723055e77 100644 --- a/crates/common/src/asterisc/mod.rs +++ b/crates/common/src/asterisc/mod.rs @@ -1,4 +1,4 @@ //! TODO -pub mod io; +pub(crate) mod io; mod syscall; diff --git a/crates/common/src/asterisc/syscall.rs b/crates/common/src/asterisc/syscall.rs index c0a23cbe6..e1f19606a 100644 --- a/crates/common/src/asterisc/syscall.rs +++ b/crates/common/src/asterisc/syscall.rs @@ -17,7 +17,7 @@ use core::arch::asm; /// Issues a raw system call with 1 argument. (e.g. exit) #[inline] -pub unsafe fn syscall1(syscall_number: usize, arg1: usize) -> usize { +pub(crate) unsafe fn syscall1(syscall_number: usize, arg1: usize) -> usize { let mut ret: usize; asm!( "ecall", @@ -30,7 +30,12 @@ pub unsafe fn syscall1(syscall_number: usize, arg1: usize) -> usize { /// Issues a raw system call with 3 arguments. (e.g. read, write) #[inline] -pub unsafe fn syscall3(syscall_number: usize, arg1: usize, arg2: usize, arg3: usize) -> usize { +pub(crate) unsafe fn syscall3( + syscall_number: usize, + arg1: usize, + arg2: usize, + arg3: usize, +) -> usize { let mut ret: usize; asm!( "ecall", diff --git a/crates/common/src/cannon/io.rs b/crates/common/src/cannon/io.rs index f539e657b..ed1915956 100644 --- a/crates/common/src/cannon/io.rs +++ b/crates/common/src/cannon/io.rs @@ -1,8 +1,11 @@ -use crate::{cannon::syscall, traits::BasicKernelInterface, types::RegisterSize}; +use crate::{ + cannon::syscall, io::FileDescriptor, traits::BasicKernelInterface, types::RegisterSize, +}; use anyhow::{anyhow, Result}; /// Concrete implementation of the [BasicKernelInterface] trait for the `MIPS32rel1` target architecture. Exposes a safe /// interface for performing IO operations within the FPVM kernel. +#[derive(Debug)] pub struct CannonIO; /// Relevant system call numbers for the `MIPS32rel1` target architecture. @@ -14,7 +17,7 @@ pub struct CannonIO; /// the [BasicKernelInterface] trait is created for the `Cannon` kernel, this list should be extended /// accordingly. #[repr(u32)] -pub enum SyscallNumber { +pub(crate) enum SyscallNumber { /// Sets the Exited and ExitCode states to true and $a0 respectively. Exit = 4246, /// Similar behavior as Linux/MIPS with support for unaligned reads. @@ -24,9 +27,7 @@ pub enum SyscallNumber { } impl BasicKernelInterface for CannonIO { - type FileDescriptor = crate::io::FileDescriptor; - - fn write(fd: Self::FileDescriptor, buf: &[u8]) -> Result { + fn write(fd: FileDescriptor, buf: &[u8]) -> Result { unsafe { syscall::syscall3( SyscallNumber::Write as u32, @@ -38,7 +39,7 @@ impl BasicKernelInterface for CannonIO { } } - fn read(fd: Self::FileDescriptor, buf: &mut [u8]) -> Result { + fn read(fd: FileDescriptor, buf: &mut [u8]) -> Result { unsafe { syscall::syscall3( SyscallNumber::Read as u32, diff --git a/crates/common/src/cannon/syscall.rs b/crates/common/src/cannon/syscall.rs index 95ccc7116..78064c54a 100644 --- a/crates/common/src/cannon/syscall.rs +++ b/crates/common/src/cannon/syscall.rs @@ -38,7 +38,7 @@ use core::arch::asm; /// Issues a raw system call with 1 argument. (e.g. exit) #[inline] -pub unsafe fn syscall1(n: u32, arg1: u32) -> u32 { +pub(crate) unsafe fn syscall1(n: u32, arg1: u32) -> u32 { let mut err: u32; let mut ret: u32; asm!( @@ -67,7 +67,7 @@ pub unsafe fn syscall1(n: u32, arg1: u32) -> u32 { /// Issues a raw system call with 3 arguments. (e.g. read, write) #[inline] -pub unsafe fn syscall3(n: u32, arg1: u32, arg2: u32, arg3: u32) -> Result { +pub(crate) unsafe fn syscall3(n: u32, arg1: u32, arg2: u32, arg3: u32) -> Result { let mut err: u32; let mut ret: u32; asm!( diff --git a/crates/common/src/io.rs b/crates/common/src/io.rs index af695de63..2d8ab9bcb 100644 --- a/crates/common/src/io.rs +++ b/crates/common/src/io.rs @@ -1,8 +1,6 @@ //! This module contains the [ClientIO] struct, which is used to perform various IO operations //! inside of the FPVM kernel within a `client` program. -use crate::{traits::BasicKernelInterface, types::RegisterSize}; -use anyhow::Result; use cfg_if::cfg_if; cfg_if! { @@ -42,8 +40,8 @@ pub enum FileDescriptor { mod native_io { extern crate std; - use super::{BasicKernelInterface, FileDescriptor, RegisterSize, Result}; - use anyhow::anyhow; + use crate::{io::FileDescriptor, traits::BasicKernelInterface, types::RegisterSize}; + use anyhow::{anyhow, Result}; use std::{ fs::File, io::{Read, Write}, diff --git a/crates/common/src/lib.rs b/crates/common/src/lib.rs index a1afae8b8..f16f62ec5 100644 --- a/crates/common/src/lib.rs +++ b/crates/common/src/lib.rs @@ -7,6 +7,7 @@ )] #![deny(unused_must_use, rust_2018_idioms)] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] +#![cfg_attr(target_arch = "mips", feature(asm_experimental_arch))] #![no_std] pub mod io; diff --git a/examples/minimal/Cargo.lock b/examples/minimal/Cargo.lock new file mode 100644 index 000000000..1d2efa5a3 --- /dev/null +++ b/examples/minimal/Cargo.lock @@ -0,0 +1,78 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +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 = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[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", + "cfg-if", + "good_memory_allocator", +] + +[[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 = "minimal" +version = "0.1.0" +dependencies = [ + "kona-common", +] + +[[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/examples/minimal/Cargo.toml b/examples/minimal/Cargo.toml new file mode 100644 index 000000000..997f5a9e6 --- /dev/null +++ b/examples/minimal/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "minimal" +version = "0.1.0" +edition = "2021" + +[dependencies] +kona-common = { path = "../../crates/common" } + +[profile.dev] +panic = "abort" + +[profile.release] +panic = "abort" diff --git a/examples/minimal/README.md b/examples/minimal/README.md new file mode 100644 index 000000000..3eb7590b5 --- /dev/null +++ b/examples/minimal/README.md @@ -0,0 +1,3 @@ +# `minimal` + +Minimal example program using the SDK. diff --git a/examples/minimal/justfile b/examples/minimal/justfile new file mode 100644 index 000000000..86e59e880 --- /dev/null +++ b/examples/minimal/justfile @@ -0,0 +1,17 @@ +# Build for the `cannon` target +build-cannon *args='': + docker run \ + --rm \ + --platform linux/amd64 \ + -v `pwd`/../../:/workdir \ + -w="/workdir/examples/minimal" \ + cannon-pipeline:latest cargo build -Zbuild-std $@ + +# Build for the `asterisc` target +build-asterisc *args='': + docker run \ + --rm \ + --platform linux/amd64 \ + -v `pwd`/../../:/workdir \ + -w="/workdir/examples/minimal" \ + asterisc-pipeline:latest cargo build -Zbuild-std $@ diff --git a/examples/minimal/src/main.rs b/examples/minimal/src/main.rs new file mode 100644 index 000000000..32b4ba86a --- /dev/null +++ b/examples/minimal/src/main.rs @@ -0,0 +1,27 @@ +#![no_std] +#![no_main] + +use kona_common::{ + io::{ClientIO, FileDescriptor}, + traits::BasicKernelInterface, +}; + +extern crate alloc; + +const HEAP_SIZE: usize = 0xFFFF; + +#[no_mangle] +pub extern "C" fn _start() { + kona_common::alloc_heap!(HEAP_SIZE); + + let _ = ClientIO::write(FileDescriptor::StdOut, b"Hello, world!\n"); + + ClientIO::exit(0) +} + +#[panic_handler] +fn panic(info: &core::panic::PanicInfo) -> ! { + let msg = alloc::format!("Panic: {}", info); + let _ = ClientIO::write(FileDescriptor::StdErr, msg.as_bytes()); + ClientIO::exit(2) +} diff --git a/justfile b/justfile index 992b51882..d83e414a0 100644 --- a/justfile +++ b/justfile @@ -1,3 +1,30 @@ +set positional-arguments + # Lint the workspace lint: cargo +nightly fmt --all && cargo +nightly clippy --all --all-features --all-targets -- -D warnings + +# Build the workspace for all available targets +build-all: build-native build-cannon build-asterisc + +# Build for the native target +build-native *args='': + cargo build --workspace --all $@ + +# Build for the `cannon` target +build-cannon *args='': + docker run \ + --rm \ + --platform linux/amd64 \ + -v `pwd`/:/workdir \ + -w="/workdir" \ + cannon-pipeline:latest cargo build --workspace --all -Zbuild-std $@ + +# Build for the `asterisc` target +build-asterisc *args='': + docker run \ + --rm \ + --platform linux/amd64 \ + -v `pwd`/:/workdir \ + -w="/workdir" \ + asterisc-pipeline:latest cargo build --workspace --all -Zbuild-std $@