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

stylus: add compilation target config, support multiple targets in wasm store #2463

Merged
merged 103 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from 100 commits
Commits
Show all changes
103 commits
Select commit Hold shift + click to select a range
564cb56
stylus: internally split compile from activate
tsahee Jun 20, 2024
a9c6275
update stylus function documentation
tsahee Jun 21, 2024
4f52b17
stylus: introduce target_cache
tsahee Jun 24, 2024
9e99245
use explicit targets and target cache
tsahee Jun 24, 2024
db42497
stylus compile: support non-native archs and dont panic
tsahee Jun 25, 2024
035fddb
programs: add testCompileArch
tsahee Jun 25, 2024
89bcd07
arbos/programs: improve code in activation
tsahee Jun 25, 2024
da57334
clippy
tsahee Jun 25, 2024
07aebbf
testCompileArch: add load/store
tsahee Jun 25, 2024
b4f1c0a
fix dir permissions
tsahee Jun 25, 2024
e78c7b9
TesstCompileArch: add documentation
tsahee Jun 26, 2024
8316508
fix arbitrator tests
tsahee Jun 26, 2024
a1d56a0
Merge branch 'master' into stylus_target
tsahee Jun 27, 2024
9beb476
add stylus target config
magicxyyz Jul 9, 2024
d825279
set stylus target
magicxyyz Jul 9, 2024
fe2e0dc
map from target to asm
magicxyyz Jul 15, 2024
35b1bd1
update geth
magicxyyz Jul 15, 2024
1f3d3cb
Merge branch 'master' into stylus_target_wasm_store
magicxyyz Jul 15, 2024
782366d
update geth
magicxyyz Jul 22, 2024
63f03c9
Merge branch 'master' into stylus_target_wasm_store
magicxyyz Jul 22, 2024
047d961
update geth pin
magicxyyz Jul 22, 2024
b1595d1
Merge branch 'master' into stylus_target_wasm_store
magicxyyz Jul 23, 2024
c061a91
Merge branch 'master' into stylus_target
magicxyyz Jul 23, 2024
42faab8
Merge branch 'stylus_target' into stylus_target_wasm_store
magicxyyz Jul 23, 2024
c482a2a
remove leftover code from activateProgramInternal
magicxyyz Jul 23, 2024
2785dfd
add wasm schema version check in init
magicxyyz Jul 24, 2024
3ee75e4
fix databaseIsEmpty check
magicxyyz Jul 24, 2024
5cf23fa
remove outdated comment
magicxyyz Jul 24, 2024
a6167df
log error when stylus_target_set fails
magicxyyz Aug 2, 2024
dba4f71
Merge branch 'master' into stylus_target
magicxyyz Aug 2, 2024
d9a420c
store wavm in the same map as native asms
magicxyyz Aug 2, 2024
53b04b8
Merge branch 'stylus_target' into stylus_target_wasm_store
magicxyyz Aug 2, 2024
1f44f5e
use rawdb.TargetWavm const, instead of GOARCH return LocalTargetName(…
magicxyyz Aug 3, 2024
35dc700
fix supported arch check in validationEntry.ToInput
magicxyyz Aug 3, 2024
d6a0579
remove outdated todo comment
magicxyyz Aug 3, 2024
5f776d9
remove unused struct
magicxyyz Aug 3, 2024
efe2b0d
Merge branch 'master' into stylus_target
magicxyyz Aug 6, 2024
d0f4ffb
Merge branch 'stylus_target' into stylus_target_wasm_store
magicxyyz Aug 6, 2024
db04fa7
fix getting wasm for local target in JitMachine.prove
magicxyyz Aug 6, 2024
ae5f159
record program for Wavm and local target
magicxyyz Aug 6, 2024
af31233
update geth
magicxyyz Aug 6, 2024
c3ef68b
rename wasm store schema version validation helper
magicxyyz Aug 7, 2024
b6c87ce
Merge branch 'master' into stylus_target
magicxyyz Aug 7, 2024
2477cbe
Merge branch 'stylus_target' into stylus_target_wasm_store
magicxyyz Aug 7, 2024
f344e55
Merge branch 'master' into stylus_target_wasm_store
magicxyyz Aug 9, 2024
1e07092
fix merge: remove DangerousConfig
magicxyyz Aug 9, 2024
c418f31
set DefaultStylusTargetConfig.Host to empty str
magicxyyz Aug 9, 2024
631a23f
specify linux OS in stylus target config description
magicxyyz Aug 9, 2024
3d0680e
add back the blank line after StylusTarget
magicxyyz Aug 9, 2024
e8a473d
make sure all requested stylusArchs are included in ValidationInput
magicxyyz Aug 9, 2024
4f93172
use rawdb.TargetWavm constant instead of explicit string
magicxyyz Aug 9, 2024
cfaee08
fix typo in triple_string
magicxyyz Aug 9, 2024
3c0172c
move default target description constants to programs, use them in te…
magicxyyz Aug 9, 2024
a7498c0
match GOARCH target naming, update geth pin
magicxyyz Aug 9, 2024
00704f2
target_from_string: return default target for empty string
magicxyyz Aug 9, 2024
bf21950
remove repetition in target option description
magicxyyz Aug 9, 2024
d304823
simplify not supported stylusArch error message
magicxyyz Aug 9, 2024
2d3563d
error only when WasmStoreSchemaVersion is greater then current version
magicxyyz Aug 9, 2024
90358f2
update geth pin
magicxyyz Aug 9, 2024
9a9b902
Merge branch 'master' into stylus_target_wasm_store
magicxyyz Aug 9, 2024
f5536f5
update unsupported wasm schema version error message
magicxyyz Aug 12, 2024
3581af3
use rawdb.Target type
magicxyyz Aug 12, 2024
2c86f27
use rawdb.TargetFromString / rawdb.Target.ToString for encoding/decod…
magicxyyz Aug 12, 2024
048ae8d
change stylusArch validation
magicxyyz Aug 12, 2024
883d034
use rawdb.Target.ToString in programs.SetTarget
magicxyyz Aug 12, 2024
3fdc02c
update geth pin, remove rawdb.TargetFromString and rawdb.Target.ToString
magicxyyz Aug 12, 2024
c3502b2
handle error returned from rawdb.ReadWasmSchemaVersion
magicxyyz Aug 12, 2024
49cc293
update geth pin
magicxyyz Aug 12, 2024
9aef946
Merge branch 'master' into stylus_target_wasm_store
magicxyyz Aug 12, 2024
f84bf13
remove old wasm store entires if version 0 is detected
magicxyyz Aug 12, 2024
02f1e86
add error check in TestPurgeVersion0WasmStoreEntries
magicxyyz Aug 12, 2024
56544dc
update geth pin
magicxyyz Aug 12, 2024
1fa3e7d
Merge branch 'master' into stylus_target_wasm_store
magicxyyz Aug 12, 2024
dbf169d
Merge branch 'master' into stylus_target_wasm_store
magicxyyz Aug 13, 2024
d1caccc
Merge branch 'master' into stylus_target_wasm_store
magicxyyz Aug 14, 2024
f0dcbe3
Merge branch 'master' into stylus_target_wasm_store
magicxyyz Aug 14, 2024
b5020a1
Merge branch 'master' into stylus_target_wasm_store
magicxyyz Aug 15, 2024
4a6ef04
use dbutil.IsErrNotFound when handling ReadWasmSchemaVersion error
magicxyyz Aug 15, 2024
4039007
release iterator before writing batch in purgeVersion0WasmStoreEntries
magicxyyz Aug 15, 2024
1ec6cbd
check both wavm and local asms existence when rebuilding wasm store
magicxyyz Aug 15, 2024
ac25502
log only once when key with deprecated prefix with unexpected length …
magicxyyz Aug 15, 2024
5a30b97
Revert "release iterator before writing batch in purgeVersion0WasmSto…
magicxyyz Aug 15, 2024
1245d4a
test if target name is utf8 in stylus_compile
magicxyyz Aug 15, 2024
f0c1cf8
use InitCache::target() when deserializing in exec_wasm
magicxyyz Aug 15, 2024
eb17f05
don't error pre-stylus in ValidationClient.Start
magicxyyz Aug 15, 2024
30060be
return empty stylusArchs for clients that does not support stylus
magicxyyz Aug 15, 2024
e67ae22
Revert "use InitCache::target() when deserializing in exec_wasm"
magicxyyz Aug 15, 2024
7e07261
move LocalTarget() to rawdb
magicxyyz Aug 15, 2024
0f8c07f
validationClient: fail if trying to validate stylus-block on non-stylus
tsahee Aug 16, 2024
a24315c
target_cache: move native target inside target_cache
tsahee Aug 16, 2024
b49a63c
clippy fix
tsahee Aug 16, 2024
fba31fd
compilation fix
tsahee Aug 16, 2024
96fafab
use renamed DeprecatedPrefixesV0
magicxyyz Aug 16, 2024
f3f2d75
update geth pin
magicxyyz Aug 16, 2024
57adb9d
rustfmt arbitrator/stylus/src/test/api.rs
magicxyyz Aug 16, 2024
1543e98
add comment to target_cache_set
magicxyyz Aug 16, 2024
1aca285
Merge branch 'master' into stylus_target_wasm_store
PlasmaPower Aug 16, 2024
b9c3548
remove wasmer-go, use stylus lib for wat2wasm
tsahee Aug 16, 2024
0479150
wat_to_wasm clippy
tsahee Aug 16, 2024
0e1b98c
cargo fmt
tsahee Aug 16, 2024
3beb808
Merge remote-tracking branch 'origin/master' into stylus_target_wasm_…
tsahee Aug 17, 2024
eb690ee
fix merge conflict
tsahee Aug 17, 2024
10516f5
Merge branch 'master' into stylus_target_wasm_store
PlasmaPower Aug 17, 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
38 changes: 21 additions & 17 deletions arbitrator/prover/src/programs/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use {
meter::Meter, start::StartMover, MiddlewareWrapper,
},
std::sync::Arc,
wasmer::{Cranelift, CraneliftOptLevel, Engine, Store},
wasmer::{Cranelift, CraneliftOptLevel, Engine, Store, Target},
wasmer_compiler_singlepass::Singlepass,
};

Expand Down Expand Up @@ -180,17 +180,19 @@ impl CompileConfig {
}

#[cfg(feature = "native")]
pub fn store(&self) -> Store {
let mut compiler: Box<dyn wasmer::CompilerConfig> = match self.debug.cranelift {
pub fn engine(&self, target: Target) -> Engine {
use wasmer::sys::EngineBuilder;

let mut wasmer_config: Box<dyn wasmer::CompilerConfig> = match self.debug.cranelift {
true => {
let mut compiler = Cranelift::new();
compiler.opt_level(CraneliftOptLevel::Speed);
Box::new(compiler)
let mut wasmer_config = Cranelift::new();
wasmer_config.opt_level(CraneliftOptLevel::Speed);
Box::new(wasmer_config)
}
false => Box::new(Singlepass::new()),
};
compiler.canonicalize_nans(true);
compiler.enable_verifier();
wasmer_config.canonicalize_nans(true);
wasmer_config.enable_verifier();

let start = MiddlewareWrapper::new(StartMover::new(self.debug.debug_info));
let meter = MiddlewareWrapper::new(Meter::new(&self.pricing));
Expand All @@ -200,22 +202,24 @@ impl CompileConfig {

// add the instrumentation in the order of application
// note: this must be consistent with the prover
compiler.push_middleware(Arc::new(start));
compiler.push_middleware(Arc::new(meter));
compiler.push_middleware(Arc::new(dygas));
compiler.push_middleware(Arc::new(depth));
compiler.push_middleware(Arc::new(bound));
wasmer_config.push_middleware(Arc::new(start));
wasmer_config.push_middleware(Arc::new(meter));
wasmer_config.push_middleware(Arc::new(dygas));
wasmer_config.push_middleware(Arc::new(depth));
wasmer_config.push_middleware(Arc::new(bound));

if self.debug.count_ops {
let counter = Counter::new();
compiler.push_middleware(Arc::new(MiddlewareWrapper::new(counter)));
wasmer_config.push_middleware(Arc::new(MiddlewareWrapper::new(counter)));
}

Store::new(compiler)
EngineBuilder::new(wasmer_config)
.set_target(Some(target))
.into()
}

#[cfg(feature = "native")]
pub fn engine(&self) -> Engine {
self.store().engine().clone()
pub fn store(&self, target: Target) -> Store {
Store::new(self.engine(target))
}
}
4 changes: 3 additions & 1 deletion arbitrator/stylus/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ use prover::programs::config::CompileConfig;
use std::{collections::HashMap, num::NonZeroUsize};
use wasmer::{Engine, Module, Store};

use crate::target_cache::target_native;

lazy_static! {
static ref INIT_CACHE: Mutex<InitCache> = Mutex::new(InitCache::new(256));
}
Expand Down Expand Up @@ -120,7 +122,7 @@ impl InitCache {
}
drop(cache);

let engine = CompileConfig::version(version, debug).engine();
let engine = CompileConfig::version(version, debug).engine(target_native());
let module = unsafe { Module::deserialize_unchecked(&engine, module)? };

let item = CacheItem::new(module, engine);
Expand Down
104 changes: 92 additions & 12 deletions arbitrator/stylus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use native::NativeInstance;
use prover::programs::{prelude::*, StylusData};
use run::RunProgram;
use std::{marker::PhantomData, mem, ptr};
use target_cache::{target_cache_get, target_cache_set};

pub use brotli;
pub use prover;
Expand All @@ -29,6 +30,7 @@ pub mod run;

mod cache;
mod evm_api;
mod target_cache;
mod util;

#[cfg(test)]
Expand Down Expand Up @@ -122,9 +124,9 @@ impl RustBytes {
}
}

/// Instruments and "activates" a user wasm.
/// "activates" a user wasm.
///
/// The `output` is either the serialized asm & module pair or an error string.
/// The `output` is either the module or an error string.
/// Returns consensus info such as the module hash and footprint on success.
///
/// Note that this operation costs gas and is limited by the amount supplied via the `gas` pointer.
Expand All @@ -140,7 +142,6 @@ pub unsafe extern "C" fn stylus_activate(
version: u16,
debug: bool,
output: *mut RustBytes,
asm_len: *mut usize,
codehash: *const Bytes32,
module_hash: *mut Bytes32,
stylus_data: *mut StylusData,
Expand All @@ -152,18 +153,97 @@ pub unsafe extern "C" fn stylus_activate(
let codehash = &*codehash;
let gas = &mut *gas;

let (asm, module, info) =
match native::activate(wasm, codehash, version, page_limit, debug, gas) {
Ok(val) => val,
Err(err) => return output.write_err(err),
};
*asm_len = asm.len();
let (module, info) = match native::activate(wasm, codehash, version, page_limit, debug, gas) {
Ok(val) => val,
Err(err) => return output.write_err(err),
};

*module_hash = module.hash();
*stylus_data = info;

let mut data = asm;
data.extend(&*module.into_bytes());
output.write(data);
output.write(module.into_bytes());
UserOutcomeKind::Success
}

/// "compiles" a user wasm.
///
/// The `output` is either the asm or an error string.
/// Returns consensus info such as the module hash and footprint on success.
///
/// # Safety
///
/// `output` must not be null.
#[no_mangle]
pub unsafe extern "C" fn stylus_compile(
wasm: GoSliceData,
version: u16,
debug: bool,
name: GoSliceData,
output: *mut RustBytes,
) -> UserOutcomeKind {
let wasm = wasm.slice();
let output = &mut *output;
let name = match String::from_utf8(name.slice().to_vec()) {
Ok(val) => val,
Err(err) => return output.write_err(err.into()),
};
let target = match target_cache_get(&name) {
Ok(val) => val,
Err(err) => return output.write_err(err),
};

let asm = match native::compile(wasm, version, debug, target) {
Ok(val) => val,
Err(err) => return output.write_err(err),
};

output.write(asm);
UserOutcomeKind::Success
}

#[no_mangle]
/// # Safety
///
/// `output` must not be null.
pub unsafe extern "C" fn wat_to_wasm(wat: GoSliceData, output: *mut RustBytes) -> UserOutcomeKind {
let output = &mut *output;
let wasm = match wasmer::wat2wasm(wat.slice()) {
Ok(val) => val,
Err(err) => return output.write_err(err.into()),
};
output.write(wasm.into_owned());
UserOutcomeKind::Success
}

/// sets target index to a string
///
/// String format is: Triple+CpuFeature+CpuFeature..
///
/// # Safety
///
/// `output` must not be null.
#[no_mangle]
pub unsafe extern "C" fn stylus_target_set(
name: GoSliceData,
description: GoSliceData,
output: *mut RustBytes,
native: bool,
) -> UserOutcomeKind {
let output = &mut *output;
let name = match String::from_utf8(name.slice().to_vec()) {
Ok(val) => val,
Err(err) => return output.write_err(err.into()),
};

let desc_str = match String::from_utf8(description.slice().to_vec()) {
Ok(val) => val,
Err(err) => return output.write_err(err.into()),
};

if let Err(err) = target_cache_set(name, desc_str, native) {
return output.write_err(err);
};

UserOutcomeKind::Success
}

Expand Down
30 changes: 16 additions & 14 deletions arbitrator/stylus/src/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use crate::{
cache::InitCache,
env::{MeterData, WasmEnv},
host, util,
host,
};
use arbutil::{
evm::{
Expand Down Expand Up @@ -33,11 +33,13 @@ use std::{
ops::{Deref, DerefMut},
};
use wasmer::{
imports, AsStoreMut, Function, FunctionEnv, Instance, Memory, Module, Pages, Store,
imports, AsStoreMut, Function, FunctionEnv, Instance, Memory, Module, Pages, Store, Target,
TypedFunction, Value, WasmTypeList,
};
use wasmer_vm::VMExtern;

use crate::target_cache::target_native;

#[derive(Debug)]
pub struct NativeInstance<D: DataReader, E: EvmApi<D>> {
pub instance: Instance,
Expand Down Expand Up @@ -98,7 +100,7 @@ impl<D: DataReader, E: EvmApi<D>> NativeInstance<D, E> {
evm_data: EvmData,
) -> Result<Self> {
let env = WasmEnv::new(compile, None, evm, evm_data);
let store = env.compile.store();
let store = env.compile.store(target_native());
let module = unsafe { Module::deserialize_unchecked(&store, module)? };
Self::from_module(module, store, env)
}
Expand Down Expand Up @@ -137,9 +139,10 @@ impl<D: DataReader, E: EvmApi<D>> NativeInstance<D, E> {
evm_data: EvmData,
compile: &CompileConfig,
config: StylusConfig,
target: Target,
) -> Result<Self> {
let env = WasmEnv::new(compile.clone(), Some(config), evm_api, evm_data);
let store = env.compile.store();
let store = env.compile.store(target);
let wat_or_wasm = std::fs::read(path)?;
let module = Module::new(&store, wat_or_wasm)?;
Self::from_module(module, store, env)
Expand Down Expand Up @@ -347,8 +350,8 @@ impl<D: DataReader, E: EvmApi<D>> StartlessMachine for NativeInstance<D, E> {
}
}

pub fn module(wasm: &[u8], compile: CompileConfig) -> Result<Vec<u8>> {
let mut store = compile.store();
pub fn module(wasm: &[u8], compile: CompileConfig, target: Target) -> Result<Vec<u8>> {
let mut store = compile.store(target);
let module = Module::new(&store, wasm)?;
macro_rules! stub {
(u8 <- $($types:tt)+) => {
Expand Down Expand Up @@ -428,7 +431,6 @@ pub fn module(wasm: &[u8], compile: CompileConfig) -> Result<Vec<u8>> {
imports.define("console", "tee_f64", stub!(f64 <- |_: f64|));
imports.define("debug", "null_host", stub!(||));
}
Instance::new(&mut store, &module, &imports)?;

let module = module.serialize()?;
Ok(module.to_vec())
Expand All @@ -441,14 +443,14 @@ pub fn activate(
page_limit: u16,
debug: bool,
gas: &mut u64,
) -> Result<(Vec<u8>, ProverModule, StylusData)> {
let compile = CompileConfig::version(version, debug);
) -> Result<(ProverModule, StylusData)> {
let (module, stylus_data) =
ProverModule::activate(wasm, codehash, version, page_limit, debug, gas)?;

let asm = match self::module(wasm, compile) {
Ok(asm) => asm,
Err(err) => util::panic_with_wasm(wasm, err),
};
Ok((asm, module, stylus_data))
Ok((module, stylus_data))
}

pub fn compile(wasm: &[u8], version: u16, debug: bool, target: Target) -> Result<Vec<u8>> {
let compile = CompileConfig::version(version, debug);
self::module(wasm, compile, target)
}
81 changes: 81 additions & 0 deletions arbitrator/stylus/src/target_cache.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright 2022-2024, Offchain Labs, Inc.
// For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE

use eyre::{eyre, OptionExt, Result};
use lazy_static::lazy_static;
use parking_lot::RwLock;
use std::{collections::HashMap, str::FromStr};
use wasmer_types::{CpuFeature, Target, Triple};

lazy_static! {
static ref TARGET_CACHE: RwLock<HashMap<String, Target>> = RwLock::new(HashMap::new());
static ref TARGET_NATIVE: RwLock<Target> = RwLock::new(Target::default());
}

fn target_from_string(input: String) -> Result<Target> {
if input.is_empty() {
return Ok(Target::default());
}
let mut parts = input.split('+');

let Some(triple_string) = parts.next() else {
return Err(eyre!("no architecture"));
};

let triple = match Triple::from_str(triple_string) {
Ok(val) => val,
Err(e) => return Err(eyre!(e)),
};

let mut features = CpuFeature::set();
for flag in parts {
features.insert(CpuFeature::from_str(flag)?);
}

Ok(Target::new(triple, features))
}

/// Populates `TARGET_CACHE` inserting target specified by `description` under `name` key.
/// Additionally, if `native` is set it sets `TARGET_NATIVE` to the specified target.
pub fn target_cache_set(name: String, description: String, native: bool) -> Result<()> {
let target = target_from_string(description)?;

if native {
if !target.is_native() {
return Err(eyre!("arch not native"));
}
let flags_not_supported = Target::default()
.cpu_features()
.complement()
.intersection(*target.cpu_features());
if !flags_not_supported.is_empty() {
let mut err_message = String::new();
err_message.push_str("cpu flags not supported on local cpu for: ");
for item in flags_not_supported.iter() {
err_message.push('+');
err_message.push_str(&item.to_string());
}
return Err(eyre!(err_message));
}
*TARGET_NATIVE.write() = target.clone();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd still add a comment to target_cache_set explaining everything this function does, because it kind of does two things in one. It both populates TARGET_CACHE, but if native is set, it also populates TARGET_NATIVE which isn't really a cache or related to TARGET_CACHE.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added a following comment:

/// Populates `TARGET_CACHE` inserting target specified by `description` under `name` key.
/// Additionally, if `native` is set it sets `TARGET_NATIVE` to the specified target.

Let me know if that's good / precise enough :)

}

TARGET_CACHE.write().insert(name, target);

Ok(())
}

pub fn target_native() -> Target {
TARGET_NATIVE.read().clone()
}

pub fn target_cache_get(name: &str) -> Result<Target> {
if name.is_empty() {
return Ok(TARGET_NATIVE.read().clone());
}
TARGET_CACHE
.read()
.get(name)
.cloned()
.ok_or_eyre("arch not set")
}
Loading
Loading