diff --git a/README.md b/README.md index aa84cf6..2e26a19 100644 --- a/README.md +++ b/README.md @@ -1,54 +1,60 @@ -omo -=== - -[中文](README.zh_CN.md) +# OMO A bytecode level program emulator with per-step state proof. +It can be used to generate challenge proof of optimistic rollup. -**Arch**: MIPS32 version 1 (SYSV) at present, will support more. - +**Arch**: MIPS32 at present, will support more. **Executable File Format**: ELF 32-bit MSB executable at present. +**OS**: Linux. -## Features - -1. Crossing hardware platform (Coming soon) -2. Various smart chain virtual machine embed supports -3. Safe execution environment - -## Background +The core idea is derived from [cannon](https://github.com/ethereum-optimism/cannon) and [qiling](https://github.com/qilingframework/qiling). -### Limitation of Blockchain with Smart Contract +## Development Setup -The most valuable resource on the chain is gas, because the gas of each block is capped, and the average block-out time -is fixed, so there is actually a limit to the number of computational steps that can be done per unit of time: +To cross compile crates to mips or other targets. +You need: -`TPS = (Max_Gas/Gas_Per_TXN)/Block-out_Time` +- [rust](https://rustup.rs/) +- [cross](https://github.com/cross-rs/cross). +- Docker: cross needs it. -Obviously, we need to try to reduce gas per txn. +## Get Started -The direct way is to package multi txn into one, and that's the core idea of rollup. +The project contains two crates: -### Optimistic Rollup +- `./omo` is the main entrypoint of the omo emulator. +- `./rust-mips-example` is an example crate. it is configured to build into a linux mips binary, which can be run by `omo`. -In last section, we've known that we need rollup, but who will take this responsibility, is it safe, how to challenge -the state? +First, we need to compile the `rust-mips-example`: -First, we need to lock collateralized assets on chain for off-chain execution. Just like what we do in -Bitcoin Lightning Network. +```shell +cd ./rust-mips-example +cross build --target mips-unknown-linux-musl --release -v +# the compiled mips binary will be ./target/mips-unknown-linux-musl/release/rust-mips-example +file target/mips-unknown-linux-musl/release/rust-mips-example +``` -Then, the verifier could be elected from community or DApp organization who deserves to be trusted. We are optimistic -that the chances of them doing evil are low because there is no obvious benefit. +then we use the omo to run this `target/mips-unknown-linux-musl/release/rust-mips-example` -The verifier provides abilities of persisting states on local for executing txn. What's more, we could set breakpoint -for finding wrong txn if there is one in challenge process. +```shell +cd ./omo +cargo run -- --config config.toml.example --env E1=a --env E2=b ../rust-mips-example/target/mips-unknown-linux-musl/release/rust-mips-example E1 E2 +``` -In one word, Optimistic Rollup is a collateral-based off-chain solution to achieve scalability. +it will output: -### Question: Is there any other way to improve TPS safely? +``` +Run ../rust-mips-example/target/mips-unknown-linux-musl/release/rust-mips-example +E1=a +E2=b +``` -Yes! But OMO is just focused on Optimistic Rollup. +## Other resources -## Acknowledge +[intro to omo - part1](./docs/intro-to-omo-part1.zh.md) +[prototype of move layer2 using cannon](./docs/prototype_of_cannon_in_move.zh.md) +[background of layer2](./docs/background.md) -Inspired by [qiling](https://github.com/qilingframework/qiling). +## License +Apache License 2.0 diff --git a/docs/background.md b/docs/background.md new file mode 100644 index 0000000..0ad4ecb --- /dev/null +++ b/docs/background.md @@ -0,0 +1,29 @@ + +## Background + +### Limitation of Blockchain with Smart Contract + +The most valuable resource on the chain is gas, because the gas of each block is capped, and the average block-out time +is fixed, so there is actually a limit to the number of computational steps that can be done per unit of time: + +`TPS = (Max_Gas/Gas_Per_TXN)/Block-out_Time` + +Obviously, we need to try to reduce gas per txn. + +The direct way is to package multi txn into one, and that's the core idea of rollup. + +### Optimistic Rollup + +In last section, we've known that we need rollup, but who will take this responsibility, is it safe, how to challenge +the state? + +First, we need to lock collateralized assets on chain for off-chain execution. Just like what we do in +Bitcoin Lightning Network. + +Then, the verifier could be elected from community or DApp organization who deserves to be trusted. We are optimistic +that the chances of them doing evil are low because there is no obvious benefit. + +The verifier provides abilities of persisting states on local for executing txn. What's more, we could set breakpoint +for finding wrong txn if there is one in challenge process. + +In one word, Optimistic Rollup is a collateral-based off-chain solution to achieve scalability. diff --git a/docs/intro-to-omo-part1.zh.md b/docs/intro-to-omo-part1.zh.md new file mode 100644 index 0000000..d24ea5e --- /dev/null +++ b/docs/intro-to-omo-part1.zh.md @@ -0,0 +1,123 @@ +# OMO 介绍 - Part 1 + +## 背景 + +随着链上交易量增多,layer2 成为解决扩容问题的一个重要研究领域,其中 optimistic rollup 这一方向已经有了落地的解决方案,比如 arbitrum(后称 arb),optimism(后称 op)。 + +arb 和 op(最新实现的 cannon) 都采用了交互式的链上仲裁技术。交互式的意思是,挑战者在一层不断的挑战出块者在执行区块时产生的中间状态,直到双方在某一个中间指令的执行结果上出现分歧,抑或是最终没有分歧。这种仲裁手段要求 layer2 的虚拟机能够保存执行区块过程中产生的中间状态的证明,抑或是能够在某次指令执行时进行中断,并保存当前状态的证明。 + +因为不同的optimistic rollup 解决方案可能使用了不同的虚拟机,比如, arbitrum 自己研发了 AVM。为了生成中间状态证明,不同的虚拟机可能需要定制自己的状态证明技术,且通用性比较差。虽然 optimistic rollup 的技术原理基本上都是一样的,但现如今,公链多点开花,应用也百花齐放,智能合约语言也呈快速演进趋势,为某个公链 X 实现基于某种智能合约语言 Y 的 optimistic rollup,仍然需要在工程中付出很多重复性的工作。 + +基于此,我们试图实现一个通用的可验证的合约执行环境。该环境基于 Linux 系统,可模拟不同 CPU 指令架构的代码执行,并生成对应的中间状态(寄存器+内存数据)以及状态证明。整体思路受 cannon 的启发,并借鉴了 qiling 框架的部分实现。 + +和 qiling 不同的是,区块链中的合约执行环境相对简单,没有 IO 等复杂的外部交互,也无需考虑系统安全性。另外,qiling 缺少中间状态生成以及状态证明,这是做交互式仲裁所必须的功能之一。 + +我们把这个合约执行环境称作 OMO。 + +## 主要构件 + +OMO 主要由以下几个组件构成: + +- 执行环境。对 unicorn 封装后的数据结构,提供了代码执行中对内存和寄存器的操作接口。 +- 加载器。用来加载代码数据到执行环境中。目前主要支持 ELF 的加载。 +- 寄存器和数据栈。主要便于接口抽象。 +- 系统接口。主要实现了 linux 下的 syscall。 + +## 执行环境 + +unicorn 是底层用来真正执行代码的工具库。我们利用其中的数据结构加上抽闲所需要的额外结构 `Machine` 来代表整个执行环境,也就是运行中所需要的数据。 + +其中 `Machine` 包含了两部分信息: + +- `memories: MemoryManager` 用来管理运行时内存分配的信息。 +- `arch: A` 代表了底层的CPU 架构信息,这里通过范型表示。目前实现了 MIPS 架构的 arch,其他 CPU 指令集比如 riscv 也可以比较容易的扩展进去。 + +```rust +pub type Engine<'a, A> = Unicorn<'a, Machine>; + +#[derive(Debug)] +pub struct Machine { + pub(crate) memories: MemoryManager, + arch: A, +} +``` + +## Code Loader + +代码加载器目前支持了 ELF loader。其完整模拟了 linux 下 elf 代码的加载过程:[How programs get run: ELF binaries](https://lwn.net/Articles/631631/) 。 + +其主要实现: + +- 解析出代码和数据段,加载进内存。 +- 初始化代码的入参,以及环境变量。 +- 初始化栈指针以及程序计数器(即代码入口)。 + +完整加载后,整个程序即处于可运行状态。 + +## Register and Stack + +底层 Unicorn 库只提供了通用的读写内存和寄存器的的接口。 + +在此之上, OMO 提供了关于栈的抽象,以及更高级的寄存器和内存操作。 + +具体接口如下(随着项目演化,可能会略有变动)。 + +```rust +pub trait Registers { + fn read(&self, reg: impl Into) -> Result; + fn write(&mut self, reg: impl Into, value: u64) -> Result<(), uc_error>; + fn pc(&self) -> Result; + fn set_pc(&mut self, value: u64) -> Result<(), uc_error>; +} +pub trait StackRegister { + fn sp(&self) -> Result; + fn set_sp(&mut self, value: u64) -> Result<(), uc_error>; + + /// increment stack pointer by `delta`. + /// Return new stack pointer + fn incr_sp(&mut self, delta: i64) -> Result { + let cur = self.sp()?; + let new_sp = cur.checked_add_signed(delta).ok_or(uc_error::EXCEPTION)?; + self.set_sp(new_sp)?; + Ok(new_sp) + } +} +``` + +```rust +pub trait Memory { + fn pagesize(&self) -> u64 { + PAGE_SIZE as u64 + } + fn mem_map(&mut self, region: MemRegion, info: Option) -> Result<(), uc_error>; + fn mprotect(&mut self, addr: u64, size: usize, perm: Permission) -> Result<(), uc_error>; + fn mem_unmap(&mut self, addr: u64, size: usize) -> Result<(), uc_error>; + fn is_mapped(&self, addr: u64, size: usize) -> Result; + fn read(&self, addr: u64, size: usize) -> Result, uc_error>; + fn read_ptr(&self, address: u64, pointersize: Option) -> Result; + + fn write(&mut self, address: u64, bytes: impl AsRef<[u8]>) -> Result<(), uc_error>; + fn write_ptr( + &mut self, + address: u64, + value: u64, + pointersize: Option, + ) -> Result<(), uc_error>; +} +``` + +这些接口是直接实现在 ExecEnv 数据结构上。 + +pc,sp 等寄存器的地址和 CPU 指令架构相关,所以 ExecEnv 中有关于 arch 抽象的信息。 + +## System Call + +要运行的代码依赖 linux 下的各种系统调用。OMO 需要从底层模拟这些系统接口,并保证接口调用是幂等的。 + +linux 的系统调用比较多,目前在一一梳理和实现 https://github.com/starcoinorg/omo/issues/6。 + +不过运行 hello world 所需要的系统调用已经完成。有兴趣的朋友可以参考 [https://github.com/starcoinorg/omo/tree/main/rust-mips-example](https://github.com/starcoinorg/omo/tree/main/rust-mips-example) 这个例子来运行。 + +本文主要介绍了 omo 项目的背景和实现中的几个核心组件,希望能够帮助读者了解 omo。 + +下一篇,我们会介绍如何生成中间状态及其状态证明。 \ No newline at end of file diff --git a/README.zh_CN.md b/docs/prototype_of_cannon_in_move.zh.md similarity index 100% rename from README.zh_CN.md rename to docs/prototype_of_cannon_in_move.zh.md