Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Go wasi code converge #205

Merged
merged 30 commits into from
Mar 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
1437ff3
initial joint wasip1 implementation
tsahee Feb 23, 2024
54c84d0
caller_env cosmetics
tsahee Feb 28, 2024
1fb2d69
callerenv: move static implementation
tsahee Feb 28, 2024
50670be
split caller env to mem and exec
tsahee Feb 29, 2024
dc85d03
remove unused code
tsahee Feb 29, 2024
0c65c7f
callerenv bugfixes
tsahee Mar 4, 2024
b9aa447
replace arbutil::wavm with static_env
tsahee Mar 4, 2024
cd906c1
caller_env: use read_fixed
tsahee Mar 4, 2024
c3a6027
converge Uptr
tsahee Mar 5, 2024
77eb073
converge more on Uptr
tsahee Mar 5, 2024
a186fc3
fix dockerfile
tsahee Mar 5, 2024
5170ae3
GuestPtr, speed up read/write, docstrings, debug prints, wrap macro, …
rachel-bousfield Mar 8, 2024
7d60088
fix set_len order
rachel-bousfield Mar 8, 2024
d76b355
fixed, simplifications, and MiniAlloc
rachel-bousfield Mar 8, 2024
efc02e0
safer message & response parsing
rachel-bousfield Mar 8, 2024
a4adb63
more cleanup
rachel-bousfield Mar 8, 2024
09f7e35
repin contracts
rachel-bousfield Mar 8, 2024
c61efc5
fix docker
rachel-bousfield Mar 8, 2024
e99b3ff
revert back to WeeAlloc
rachel-bousfield Mar 8, 2024
8ec6f21
fix refs & debug printing
rachel-bousfield Mar 8, 2024
546a471
remove print_string from ExecEnv
tsahee Mar 8, 2024
d18bec5
fix wasip1_stub warnings
tsahee Mar 8, 2024
fff7887
don't recover from error if over max steps
tsahee Mar 8, 2024
c3f5aea
fix loop & print out of steps
rachel-bousfield Mar 8, 2024
33789de
pass time each poll_oneoff
rachel-bousfield Mar 8, 2024
b69e276
address review comments: cleanup
rachel-bousfield Mar 8, 2024
134b103
reintroduce execEnv print_string
tsahee Mar 8, 2024
8cfb8c4
cleanup & remove guestptr DerefMut
rachel-bousfield Mar 8, 2024
69ae4b7
Merge pull request #206 from OffchainLabs/go-wasi-edits
tsahee Mar 8, 2024
a981045
Merge branch 'stylus' into go_wasi_code_reuse
rachel-bousfield Mar 8, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --de
COPY ./Makefile ./
COPY arbitrator/Cargo.* arbitrator/
COPY arbitrator/arbutil arbitrator/arbutil
COPY arbitrator/caller-env arbitrator/caller-env
COPY arbitrator/prover arbitrator/prover
COPY arbitrator/wasm-libraries arbitrator/wasm-libraries
COPY arbitrator/tools/wasmer arbitrator/tools/wasmer
Expand Down Expand Up @@ -92,6 +93,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
COPY arbitrator/Cargo.* arbitrator/
COPY ./Makefile ./
COPY arbitrator/arbutil arbitrator/arbutil
COPY arbitrator/caller-env arbitrator/caller-env
COPY arbitrator/prover arbitrator/prover
COPY arbitrator/wasm-libraries arbitrator/wasm-libraries
COPY arbitrator/jit arbitrator/jit
Expand All @@ -113,6 +115,7 @@ RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - && \
apt-get install -y llvm-15-dev libclang-common-15-dev libpolly-15-dev
COPY arbitrator/Cargo.* arbitrator/
COPY arbitrator/arbutil arbitrator/arbutil
COPY arbitrator/caller-env arbitrator/caller-env
COPY arbitrator/prover/Cargo.toml arbitrator/prover/
COPY arbitrator/jit/Cargo.toml arbitrator/jit/
COPY arbitrator/stylus/Cargo.toml arbitrator/stylus/
Expand Down Expand Up @@ -153,6 +156,7 @@ COPY --from=wasm-libs-builder /workspace/arbitrator/prover/ arbitrator/prover/
COPY --from=wasm-libs-builder /workspace/arbitrator/tools/wasmer/ arbitrator/tools/wasmer/
COPY --from=wasm-libs-builder /workspace/arbitrator/wasm-libraries/ arbitrator/wasm-libraries/
COPY --from=wasm-libs-builder /workspace/arbitrator/arbutil arbitrator/arbutil
COPY --from=wasm-libs-builder /workspace/arbitrator/caller-env arbitrator/caller-env
COPY --from=wasm-libs-builder /workspace/.make/ .make/
COPY ./Makefile ./
COPY ./arbitrator ./arbitrator
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ WASI_SYSROOT?=/opt/wasi-sdk/wasi-sysroot

arbitrator_wasm_lib_flags=$(patsubst %, -l %, $(arbitrator_wasm_libs))

rust_arbutil_files = $(wildcard arbitrator/arbutil/src/*.* arbitrator/arbutil/src/*/*.* arbitrator/arbutil/*.toml)
rust_arbutil_files = $(wildcard arbitrator/arbutil/src/*.* arbitrator/arbutil/src/*/*.* arbitrator/arbutil/*.toml arbitrator/caller-env/src/*.* arbitrator/caller-env/src/*/*.* arbitrator/caller-env/*.toml)

prover_direct_includes = $(patsubst %,$(output_latest)/%.wasm, forward forward_stub)
prover_src = arbitrator/prover/src
Expand Down Expand Up @@ -341,7 +341,7 @@ $(output_latest)/user_host.wasm: $(DEP_PREDICATE) $(wasm_lib_user_host) $(rust_p
cargo build --manifest-path arbitrator/wasm-libraries/Cargo.toml --release --target wasm32-wasi --package user-host
install arbitrator/wasm-libraries/$(wasm32_wasi)/user_host.wasm $@

$(output_latest)/program_exec.wasm: $(DEP_PREDICATE) $(call wasm_lib_deps,user-host) $(rust_prover_files) .make/machines
$(output_latest)/program_exec.wasm: $(DEP_PREDICATE) $(call wasm_lib_deps,program-exec) $(rust_prover_files) .make/machines
cargo build --manifest-path arbitrator/wasm-libraries/Cargo.toml --release --target wasm32-wasi --package program-exec
install arbitrator/wasm-libraries/$(wasm32_wasi)/program_exec.wasm $@

Expand Down
17 changes: 12 additions & 5 deletions arbcompress/compress_wasm.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2021-2022, Offchain Labs, Inc.
// Copyright 2021-2024, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE

//go:build wasm
Expand All @@ -13,16 +13,18 @@ import (
"github.com/offchainlabs/nitro/arbutil"
)

//go:wasmimport arbcompress brotliCompress
//go:wasmimport arbcompress brotli_compress
func brotliCompress(inBuf unsafe.Pointer, inBufLen uint32, outBuf unsafe.Pointer, outBufLen unsafe.Pointer, level, windowSize uint32) BrotliStatus

//go:wasmimport arbcompress brotliDecompress
//go:wasmimport arbcompress brotli_decompress
func brotliDecompress(inBuf unsafe.Pointer, inBufLen uint32, outBuf unsafe.Pointer, outBufLen unsafe.Pointer) BrotliStatus

func Decompress(input []byte, maxSize int) ([]byte, error) {
outBuf := make([]byte, maxSize)
outLen := uint32(len(outBuf))
status := brotliDecompress(arbutil.SliceToUnsafePointer(input), uint32(len(input)), arbutil.SliceToUnsafePointer(outBuf), unsafe.Pointer(&outLen))
status := brotliDecompress(
arbutil.SliceToUnsafePointer(input), uint32(len(input)), arbutil.SliceToUnsafePointer(outBuf), unsafe.Pointer(&outLen),
)
if status != BrotliSuccess {
return nil, fmt.Errorf("failed decompression")
}
Expand All @@ -33,7 +35,12 @@ func compressLevel(input []byte, level uint32) ([]byte, error) {
maxOutSize := compressedBufferSizeFor(len(input))
outBuf := make([]byte, maxOutSize)
outLen := uint32(len(outBuf))
status := brotliCompress(arbutil.SliceToUnsafePointer(input), uint32(len(input)), arbutil.SliceToUnsafePointer(outBuf), unsafe.Pointer(&outLen), level, WINDOW_SIZE)
status := brotliCompress(
arbutil.SliceToUnsafePointer(input), uint32(len(input)),
arbutil.SliceToUnsafePointer(outBuf), unsafe.Pointer(&outLen),
level,
WINDOW_SIZE,
)
if status != BrotliSuccess {
return nil, fmt.Errorf("failed compression")
}
Expand Down
21 changes: 17 additions & 4 deletions arbitrator/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions arbitrator/arbutil/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,3 @@ tiny-keccak = { version = "2.0.2", features = ["keccak"] }
wasmparser.workspace = true
serde = { version = "1.0.130", features = ["derive", "rc"] }
num_enum = "0.7.1"

[features]
wavm = []
13 changes: 7 additions & 6 deletions arbitrator/arbutil/src/evm/api.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2023, Offchain Labs, Inc.
// Copyright 2023-2024, Offchain Labs, Inc.
// For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE

use crate::{evm::user::UserOutcomeKind, Bytes20, Bytes32};
Expand Down Expand Up @@ -48,17 +48,18 @@ pub enum EvmApiMethod {
CaptureHostIO,
}

// This offset is added to EvmApiMethod when sending a request
// in WASM - program done is also indicated by a "request", with the
// id below that offset, indicating program status
/// This offset is added to EvmApiMethod when sending a request
/// in WASM - program done is also indicated by a "request", with the
/// id below that offset, indicating program status
pub const EVM_API_METHOD_REQ_OFFSET: u32 = 0x10000000;

// note: clone should not clone actual data, just the reader
/// Copies data from Go into Rust.
/// Note: clone should not clone actual data, just the reader.
pub trait DataReader: Clone + Send + 'static {
fn slice(&self) -> &[u8];
}

// simple implementation for DataReader, in case data comes from a Vec
/// Simple implementation for `DataReader`, in case data comes from a `Vec`.
#[derive(Clone, Debug)]
pub struct VecReader(Arc<Vec<u8>>);

Expand Down
76 changes: 38 additions & 38 deletions arbitrator/arbutil/src/evm/req.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2023, Offchain Labs, Inc.
// Copyright 2023-2024, Offchain Labs, Inc.
// For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE

use crate::{
Expand All @@ -11,7 +11,7 @@ use crate::{
use eyre::{bail, eyre, Result};

pub trait RequestHandler<D: DataReader>: Send + 'static {
fn handle_request(&mut self, _req_type: EvmApiMethod, _req_data: &[u8]) -> (Vec<u8>, D, u64);
fn handle_request(&mut self, req_type: EvmApiMethod, req_data: &[u8]) -> (Vec<u8>, D, u64);
}

pub struct EvmApiRequestor<D: DataReader, H: RequestHandler<D>> {
Expand All @@ -33,6 +33,7 @@ impl<D: DataReader, H: RequestHandler<D>> EvmApiRequestor<D, H> {
self.handler.handle_request(req_type, req_data)
}

/// Call out to a contract.
fn call_request(
&mut self,
call_type: EvmApiMethod,
Expand All @@ -41,13 +42,14 @@ impl<D: DataReader, H: RequestHandler<D>> EvmApiRequestor<D, H> {
gas: u64,
value: Bytes32,
) -> (u32, u64, UserOutcomeKind) {
let mut request = vec![];
request.extend(contract.as_slice());
request.extend(value.as_slice());
request.extend(&gas.to_be_bytes());
let mut request = Vec::with_capacity(20 + 32 + 8 + input.len());
request.extend(contract);
request.extend(value);
request.extend(gas.to_be_bytes());
request.extend(input);

let (res, data, cost) = self.handle_request(call_type, &request);
let status: UserOutcomeKind = res[0].try_into().unwrap();
let status: UserOutcomeKind = res[0].try_into().expect("unknown outcome");
let data_len = data.slice().len() as u32;
self.last_return_data = Some(data);
(data_len, cost, status)
Expand All @@ -65,24 +67,23 @@ impl<D: DataReader, H: RequestHandler<D>> EvmApiRequestor<D, H> {
salt: Option<Bytes32>,
gas: u64,
) -> (Result<Bytes20>, u32, u64) {
let mut request = vec![];
request.extend(&gas.to_be_bytes());
request.extend(endowment.as_slice());
let mut request = Vec::with_capacity(8 + 2 * 32 + code.len());
request.extend(gas.to_be_bytes());
request.extend(endowment);
if let Some(salt) = salt {
request.extend(salt.as_slice());
request.extend(salt);
}
request.extend(&code);
request.extend(code);

let (mut res, data, cost) = self.handle_request(create_type, &request);
if res.len() != 21 || res[0] == 0 {
if res.len() > 0 {
res.drain(0..=0);
if !res.is_empty() {
res.remove(0);
}
let err_string =
String::from_utf8(res).unwrap_or(String::from("create_response_malformed"));
let err_string = String::from_utf8(res).unwrap_or("create_response_malformed".into());
return (Err(eyre!(err_string)), 0, cost);
}
res.drain(0..=0);
res.remove(0);
let address = res.try_into().unwrap();
let data_len = data.slice().len() as u32;
self.last_return_data = Some(data);
Expand All @@ -97,9 +98,9 @@ impl<D: DataReader, H: RequestHandler<D>> EvmApi<D> for EvmApiRequestor<D, H> {
}

fn set_bytes32(&mut self, key: Bytes32, value: Bytes32) -> Result<u64> {
let mut request = vec![];
request.extend(key.as_slice());
request.extend(value.as_slice());
let mut request = Vec::with_capacity(64);
request.extend(key);
request.extend(value);
let (res, _, cost) = self.handle_request(EvmApiMethod::SetBytes32, &request);
if res.len() != 1 {
bail!("bad response from set_bytes32")
Expand Down Expand Up @@ -170,18 +171,17 @@ impl<D: DataReader, H: RequestHandler<D>> EvmApi<D> for EvmApiRequestor<D, H> {
}

fn get_return_data(&self) -> D {
self.last_return_data
.as_ref()
.expect("get return data when no data")
.clone()
self.last_return_data.clone().expect("missing return data")
}

fn emit_log(&mut self, data: Vec<u8>, topics: u32) -> Result<()> {
let mut request = topics.to_be_bytes().to_vec();
request.extend(data.iter());
let mut request = Vec::with_capacity(4 + data.len());
request.extend(topics.to_be_bytes());
request.extend(data);

let (res, _, _) = self.handle_request(EvmApiMethod::EmitLog, &request);
if !res.is_empty() {
bail!(String::from_utf8(res).unwrap_or(String::from("malformed emit-log response")))
bail!(String::from_utf8(res).unwrap_or("malformed emit-log response".into()))
}
Ok(())
}
Expand All @@ -197,10 +197,11 @@ impl<D: DataReader, H: RequestHandler<D>> EvmApi<D> for EvmApiRequestor<D, H> {
return (data.clone(), 0);
}
}
let mut req: Vec<u8> = address.as_slice().into();
let mut req = Vec::with_capacity(20 + 8);
req.extend(address);
req.extend(gas_left.to_be_bytes());
let (_, data, cost) = self.handle_request(EvmApiMethod::AccountCode, &req);

let (_, data, cost) = self.handle_request(EvmApiMethod::AccountCode, &req);
self.last_code = Some((address, data.clone()));
(data, cost)
}
Expand All @@ -211,8 +212,8 @@ impl<D: DataReader, H: RequestHandler<D>> EvmApi<D> for EvmApiRequestor<D, H> {
}

fn add_pages(&mut self, pages: u16) -> u64 {
let (_, _, cost) = self.handle_request(EvmApiMethod::AddPages, &pages.to_be_bytes());
cost
self.handle_request(EvmApiMethod::AddPages, &pages.to_be_bytes())
.2
}

fn capture_hostio(
Expand All @@ -223,13 +224,12 @@ impl<D: DataReader, H: RequestHandler<D>> EvmApi<D> for EvmApiRequestor<D, H> {
start_ink: u64,
end_ink: u64,
) {
let mut request = vec![];

request.extend(&start_ink.to_be_bytes());
request.extend(&end_ink.to_be_bytes());
request.extend(&(name.len() as u16).to_be_bytes());
request.extend(&(args.len() as u16).to_be_bytes());
request.extend(&(outs.len() as u16).to_be_bytes());
let mut request = Vec::with_capacity(2 * 8 + 3 * 2 + name.len() + args.len() + outs.len());
request.extend(start_ink.to_be_bytes());
request.extend(end_ink.to_be_bytes());
request.extend((name.len() as u16).to_be_bytes());
request.extend((args.len() as u16).to_be_bytes());
request.extend((outs.len() as u16).to_be_bytes());
request.extend(name.as_bytes());
request.extend(args);
request.extend(outs);
Expand Down
Loading
Loading