From 564cb56dc03baa715194d953947f2652fd4a4106 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 20 Jun 2024 17:25:33 -0600 Subject: [PATCH 01/80] stylus: internally split compile from activate also introduce compilation target --- arbitrator/prover/src/programs/config.rs | 38 +++++++++++++----------- arbitrator/stylus/src/cache.rs | 4 +-- arbitrator/stylus/src/lib.rs | 35 +++++++++++++++------- arbitrator/stylus/src/native.rs | 22 ++++++++------ arbos/programs/native.go | 27 ++++++++++++----- 5 files changed, 81 insertions(+), 45 deletions(-) diff --git a/arbitrator/prover/src/programs/config.rs b/arbitrator/prover/src/programs/config.rs index 0b5ce17475..308e21865a 100644 --- a/arbitrator/prover/src/programs/config.rs +++ b/arbitrator/prover/src/programs/config.rs @@ -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, }; @@ -181,17 +181,19 @@ impl CompileConfig { } #[cfg(feature = "native")] - pub fn store(&self) -> Store { - let mut compiler: Box = match self.debug.cranelift { + pub fn engine(&self, target: Target) -> Engine { + use wasmer::sys::EngineBuilder; + + let mut wasmer_config: Box = 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)); @@ -201,22 +203,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)) } } diff --git a/arbitrator/stylus/src/cache.rs b/arbitrator/stylus/src/cache.rs index 06739f2219..180b61e9ee 100644 --- a/arbitrator/stylus/src/cache.rs +++ b/arbitrator/stylus/src/cache.rs @@ -8,7 +8,7 @@ use lru::LruCache; use parking_lot::Mutex; use prover::programs::config::CompileConfig; use std::{collections::HashMap, num::NonZeroUsize}; -use wasmer::{Engine, Module, Store}; +use wasmer::{Engine, Module, Store, Target}; lazy_static! { static ref INIT_CACHE: Mutex = Mutex::new(InitCache::new(256)); @@ -120,7 +120,7 @@ impl InitCache { } drop(cache); - let engine = CompileConfig::version(version, debug).engine(); + let engine = CompileConfig::version(version, debug).engine(Target::default()); let module = unsafe { Module::deserialize_unchecked(&engine, module)? }; let item = CacheItem::new(module, engine); diff --git a/arbitrator/stylus/src/lib.rs b/arbitrator/stylus/src/lib.rs index 3c53359f8b..f2f7b481d3 100644 --- a/arbitrator/stylus/src/lib.rs +++ b/arbitrator/stylus/src/lib.rs @@ -140,7 +140,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, @@ -152,18 +151,34 @@ 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 +} + +#[no_mangle] +pub unsafe extern "C" fn stylus_compile( + wasm: GoSliceData, + version: u16, + debug: bool, + output: *mut RustBytes, +) -> UserOutcomeKind { + let wasm = wasm.slice(); + let output = &mut *output; + + let asm = match native::compile(wasm, version, debug) { + Ok(val) => val, + Err(err) => return output.write_err(err), + }; + + output.write(asm); UserOutcomeKind::Success } diff --git a/arbitrator/stylus/src/native.rs b/arbitrator/stylus/src/native.rs index 2858d59fdc..f8d2a481a4 100644 --- a/arbitrator/stylus/src/native.rs +++ b/arbitrator/stylus/src/native.rs @@ -33,7 +33,7 @@ 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; @@ -98,7 +98,7 @@ impl> NativeInstance { evm_data: EvmData, ) -> Result { let env = WasmEnv::new(compile, None, evm, evm_data); - let store = env.compile.store(); + let store = env.compile.store(Target::default()); let module = unsafe { Module::deserialize_unchecked(&store, module)? }; Self::from_module(module, store, env) } @@ -139,7 +139,7 @@ impl> NativeInstance { config: StylusConfig, ) -> Result { let env = WasmEnv::new(compile.clone(), Some(config), evm_api, evm_data); - let store = env.compile.store(); + let store = env.compile.store(Target::default()); let wat_or_wasm = std::fs::read(path)?; let module = Module::new(&store, wat_or_wasm)?; Self::from_module(module, store, env) @@ -347,8 +347,8 @@ impl> StartlessMachine for NativeInstance { } } -pub fn module(wasm: &[u8], compile: CompileConfig) -> Result> { - let mut store = compile.store(); +pub fn module(wasm: &[u8], compile: CompileConfig, target: Target) -> Result> { + let mut store = compile.store(target); let module = Module::new(&store, wasm)?; macro_rules! stub { (u8 <- $($types:tt)+) => { @@ -441,14 +441,18 @@ pub fn activate( page_limit: u16, debug: bool, gas: &mut u64, -) -> Result<(Vec, 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((module, stylus_data)) +} + +pub fn compile(wasm: &[u8], version: u16, debug: bool) -> Result> { + let compile = CompileConfig::version(version, debug); + let asm = match self::module(wasm, compile, Target::default()) { Ok(asm) => asm, Err(err) => util::panic_with_wasm(wasm, err), }; - Ok((asm, module, stylus_data)) + Ok(asm) } diff --git a/arbos/programs/native.go b/arbos/programs/native.go index ffb27cb6c0..53d8f64022 100644 --- a/arbos/programs/native.go +++ b/arbos/programs/native.go @@ -73,25 +73,41 @@ func activateProgramInternal( gasLeft *uint64, ) (*activationInfo, []byte, []byte, error) { output := &rustBytes{} - asmLen := usize(0) moduleHash := &bytes32{} stylusData := &C.StylusData{} codeHash := hashToBytes32(codehash) - status := userStatus(C.stylus_activate( + status_mod := userStatus(C.stylus_activate( goSlice(wasm), u16(page_limit), u16(version), cbool(debug), output, - &asmLen, &codeHash, moduleHash, stylusData, (*u64)(gasLeft), )) - data, msg, err := status.toResult(output.intoBytes(), debug) + module, msg, err := status_mod.toResult(output.intoBytes(), debug) + if err != nil { + if debug { + log.Warn("activation failed", "err", err, "msg", msg, "program", addressForLogging) + } + if errors.Is(err, vm.ErrExecutionReverted) { + return nil, nil, nil, fmt.Errorf("%w: %s", ErrProgramActivation, msg) + } + return nil, nil, nil, err + } + + status_asm := userStatus(C.stylus_compile( + goSlice(wasm), + u16(version), + cbool(debug), + output, + )) + + asm, msg, err := status_asm.toResult(output.intoBytes(), debug) if err != nil { if debug { log.Warn("activation failed", "err", err, "msg", msg, "program", addressForLogging) @@ -103,9 +119,6 @@ func activateProgramInternal( } hash := moduleHash.toHash() - split := int(asmLen) - asm := data[:split] - module := data[split:] info := &activationInfo{ moduleHash: hash, From a9c627536096dc5487ac1714b090e3137180c7eb Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 20 Jun 2024 18:36:18 -0600 Subject: [PATCH 02/80] update stylus function documentation --- arbitrator/stylus/src/lib.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/arbitrator/stylus/src/lib.rs b/arbitrator/stylus/src/lib.rs index f2f7b481d3..7e2c45f63f 100644 --- a/arbitrator/stylus/src/lib.rs +++ b/arbitrator/stylus/src/lib.rs @@ -122,9 +122,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. @@ -163,6 +163,14 @@ pub unsafe extern "C" fn stylus_activate( 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, From 4f52b170f91da76132aaec2bd63b3adcf6c3eb2a Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Mon, 24 Jun 2024 16:20:06 -0600 Subject: [PATCH 03/80] stylus: introduce target_cache --- arbitrator/stylus/src/target_cache.rs | 73 +++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 arbitrator/stylus/src/target_cache.rs diff --git a/arbitrator/stylus/src/target_cache.rs b/arbitrator/stylus/src/target_cache.rs new file mode 100644 index 0000000000..9e1d1eb1f5 --- /dev/null +++ b/arbitrator/stylus/src/target_cache.rs @@ -0,0 +1,73 @@ +// 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}; + +use crate::cache::InitCache; + +lazy_static! { + static ref TARGET_CACHE: RwLock> = RwLock::new(HashMap::new()); +} + +fn target_from_string(input: String) -> Result { + let mut parts = input.split('+'); + + let Some(trip_sting) = parts.next() else { + return Err(eyre!("no architecture")); + }; + + let trip = match Triple::from_str(trip_sting) { + 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(trip, features)) +} + +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)); + } + InitCache::set_target(target.clone()) + } + + TARGET_CACHE.write().insert(name, target); + + Ok(()) +} + +pub fn target_cache_get(name: &str) -> Result { + if name.len() == 0 { + return Ok(InitCache::target()); + } + TARGET_CACHE + .read() + .get(name) + .cloned() + .ok_or_eyre("arch not set") +} From 9e9924501d04a5f4d7cbc1abba3dc80133f4444b Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Mon, 24 Jun 2024 16:21:50 -0600 Subject: [PATCH 04/80] use explicit targets and target cache --- arbitrator/jit/src/stylus_backend.rs | 12 ++++++-- arbitrator/stylus/src/cache.rs | 13 ++++++++- arbitrator/stylus/src/lib.rs | 42 +++++++++++++++++++++++++++- arbitrator/stylus/src/native.rs | 10 ++++--- arbitrator/stylus/src/test/mod.rs | 11 ++++++-- arbos/programs/native.go | 1 + 6 files changed, 79 insertions(+), 10 deletions(-) diff --git a/arbitrator/jit/src/stylus_backend.rs b/arbitrator/jit/src/stylus_backend.rs index 61dbf258d4..cb0440a257 100644 --- a/arbitrator/jit/src/stylus_backend.rs +++ b/arbitrator/jit/src/stylus_backend.rs @@ -24,6 +24,7 @@ use std::{ thread::JoinHandle, }; use stylus::{native::NativeInstance, run::RunProgram}; +use wasmer::Target; struct MessageToCothread { result: Vec, @@ -143,8 +144,15 @@ pub fn exec_wasm( let evm_api = EvmApiRequestor::new(cothread); - let mut instance = - unsafe { NativeInstance::deserialize(&module, compile.clone(), evm_api, evm_data) }?; + let mut instance = unsafe { + NativeInstance::deserialize( + &module, + compile.clone(), + evm_api, + evm_data, + Target::default(), + ) + }?; let thread = thread::spawn(move || { let outcome = instance.run_main(&calldata, config, ink); diff --git a/arbitrator/stylus/src/cache.rs b/arbitrator/stylus/src/cache.rs index 180b61e9ee..62db786ac0 100644 --- a/arbitrator/stylus/src/cache.rs +++ b/arbitrator/stylus/src/cache.rs @@ -23,6 +23,7 @@ macro_rules! cache { pub struct InitCache { long_term: HashMap, lru: LruCache, + target: Target, } #[derive(Clone, Copy, Hash, PartialEq, Eq)] @@ -68,6 +69,7 @@ impl InitCache { Self { long_term: HashMap::new(), lru: LruCache::new(NonZeroUsize::new(size).unwrap()), + target: Target::default(), } } @@ -77,6 +79,14 @@ impl InitCache { .resize(NonZeroUsize::new(size.try_into().unwrap()).unwrap()) } + pub fn set_target(target: Target) { + cache!().target = target; + } + + pub fn target() -> Target { + cache!().target.clone() + } + /// Retrieves a cached value, updating items as necessary. pub fn get(module_hash: Bytes32, version: u16, debug: bool) -> Option<(Module, Store)> { let mut cache = cache!(); @@ -118,9 +128,10 @@ impl InitCache { } return Ok(item.data()); } + let target = cache.target.clone(); drop(cache); - let engine = CompileConfig::version(version, debug).engine(Target::default()); + let engine = CompileConfig::version(version, debug).engine(target); let module = unsafe { Module::deserialize_unchecked(&engine, module)? }; let item = CacheItem::new(module, engine); diff --git a/arbitrator/stylus/src/lib.rs b/arbitrator/stylus/src/lib.rs index 7e2c45f63f..2929821433 100644 --- a/arbitrator/stylus/src/lib.rs +++ b/arbitrator/stylus/src/lib.rs @@ -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; @@ -29,6 +30,7 @@ pub mod run; mod cache; mod evm_api; +mod target_cache; mod util; #[cfg(test)] @@ -176,12 +178,18 @@ 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 = String::from_utf8_unchecked(name.slice().to_vec()); + 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) { + let asm = match native::compile(wasm, version, debug, target) { Ok(val) => val, Err(err) => return output.write_err(err), }; @@ -190,6 +198,38 @@ pub unsafe extern "C" fn stylus_compile( 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 +} + /// Calls an activated user program. /// /// # Safety diff --git a/arbitrator/stylus/src/native.rs b/arbitrator/stylus/src/native.rs index f8d2a481a4..21646a0e71 100644 --- a/arbitrator/stylus/src/native.rs +++ b/arbitrator/stylus/src/native.rs @@ -96,9 +96,10 @@ impl> NativeInstance { compile: CompileConfig, evm: E, evm_data: EvmData, + target: Target, ) -> Result { let env = WasmEnv::new(compile, None, evm, evm_data); - let store = env.compile.store(Target::default()); + let store = env.compile.store(target); let module = unsafe { Module::deserialize_unchecked(&store, module)? }; Self::from_module(module, store, env) } @@ -137,9 +138,10 @@ impl> NativeInstance { evm_data: EvmData, compile: &CompileConfig, config: StylusConfig, + target: Target, ) -> Result { let env = WasmEnv::new(compile.clone(), Some(config), evm_api, evm_data); - let store = env.compile.store(Target::default()); + 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) @@ -448,9 +450,9 @@ pub fn activate( Ok((module, stylus_data)) } -pub fn compile(wasm: &[u8], version: u16, debug: bool) -> Result> { +pub fn compile(wasm: &[u8], version: u16, debug: bool, target: Target) -> Result> { let compile = CompileConfig::version(version, debug); - let asm = match self::module(wasm, compile, Target::default()) { + let asm = match self::module(wasm, compile, target) { Ok(asm) => asm, Err(err) => util::panic_with_wasm(wasm, err), }; diff --git a/arbitrator/stylus/src/test/mod.rs b/arbitrator/stylus/src/test/mod.rs index d7f3248d31..cfc0ab23b7 100644 --- a/arbitrator/stylus/src/test/mod.rs +++ b/arbitrator/stylus/src/test/mod.rs @@ -16,7 +16,7 @@ use rand::prelude::*; use std::{collections::HashMap, path::Path, sync::Arc}; use wasmer::{ imports, wasmparser::Operator, CompilerConfig, Function, FunctionEnv, Imports, Instance, - Module, Store, + Module, Store, Target, }; use wasmer_compiler_singlepass::Singlepass; @@ -86,7 +86,14 @@ impl TestInstance { config: StylusConfig, ) -> Result<(Self, TestEvmApi)> { let (mut evm, evm_data) = TestEvmApi::new(compile.clone()); - let native = Self::from_path(path, evm.clone(), evm_data, compile, config)?; + let native = Self::from_path( + path, + evm.clone(), + evm_data, + compile, + config, + Target::default(), + )?; let footprint = native.memory().ty(&native.store).minimum.0 as u16; evm.set_pages(footprint); Ok((native, evm)) diff --git a/arbos/programs/native.go b/arbos/programs/native.go index 53d8f64022..0de63009ac 100644 --- a/arbos/programs/native.go +++ b/arbos/programs/native.go @@ -104,6 +104,7 @@ func activateProgramInternal( goSlice(wasm), u16(version), cbool(debug), + goSlice([]byte{}), output, )) From db424976d7139794ca5f166b7b47150929d65130 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Mon, 24 Jun 2024 19:07:29 -0600 Subject: [PATCH 05/80] stylus compile: support non-native archs and dont panic --- arbitrator/stylus/src/native.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/arbitrator/stylus/src/native.rs b/arbitrator/stylus/src/native.rs index 21646a0e71..a2b31ed596 100644 --- a/arbitrator/stylus/src/native.rs +++ b/arbitrator/stylus/src/native.rs @@ -430,7 +430,6 @@ pub fn module(wasm: &[u8], compile: CompileConfig, target: Target) -> Result Result> { let compile = CompileConfig::version(version, debug); - let asm = match self::module(wasm, compile, target) { - Ok(asm) => asm, - Err(err) => util::panic_with_wasm(wasm, err), - }; - Ok(asm) + self::module(wasm, compile, target) } From 035fddb52a7eec66c3005f33239f86890962471e Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Mon, 24 Jun 2024 19:23:14 -0600 Subject: [PATCH 06/80] programs: add testCompileArch --- .../{constant_test.go => cgo_test.go} | 7 ++ arbos/programs/testcompile.go | 119 ++++++++++++++++++ 2 files changed, 126 insertions(+) rename arbos/programs/{constant_test.go => cgo_test.go} (72%) create mode 100644 arbos/programs/testcompile.go diff --git a/arbos/programs/constant_test.go b/arbos/programs/cgo_test.go similarity index 72% rename from arbos/programs/constant_test.go rename to arbos/programs/cgo_test.go index fe29bcf3d9..c0c8953f62 100644 --- a/arbos/programs/constant_test.go +++ b/arbos/programs/cgo_test.go @@ -11,3 +11,10 @@ func TestConstants(t *testing.T) { t.Fatal(err) } } + +func TestCompileArch(t *testing.T) { + err := testCompileArch() + if err != nil { + t.Fatal(err) + } +} diff --git a/arbos/programs/testcompile.go b/arbos/programs/testcompile.go new file mode 100644 index 0000000000..36c90f1e3b --- /dev/null +++ b/arbos/programs/testcompile.go @@ -0,0 +1,119 @@ +// Copyright 2024, Offchain Labs, Inc. +// For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE + +//go:build !wasm +// +build !wasm + +package programs + +// This file exists because cgo isn't allowed in tests + +/* +#cgo CFLAGS: -g -Wall -I../../target/include/ +#include "arbitrator.h" +*/ +import "C" +import ( + "fmt" + "os" + "runtime" + + "github.com/wasmerio/wasmer-go/wasmer" +) + +func testCompileArch() error { + + nativeArm64 := false + nativeAmd64 := false + + arm64CompileName := []byte("arm64") + amd64CompileName := []byte("amd64") + + arm64TargetString := []byte("arm64-linux-unknown+neon") + amd64TargetString := []byte("x86_64-linux-unknown+sse4.2") + + if runtime.GOOS == "linux" { + if runtime.GOARCH == "amd64" { + nativeAmd64 = true + } + if runtime.GOARCH == "arm64" { + nativeArm64 = true + } + } + + output := &rustBytes{} + + status := C.stylus_target_set(goSlice(arm64CompileName), + goSlice(arm64TargetString), + output, + cbool(nativeArm64)) + + if status != 0 { + return fmt.Errorf("failed setting compilation target arm: %v", string(output.intoBytes())) + } + + status = C.stylus_target_set(goSlice(amd64CompileName), + goSlice(amd64TargetString), + output, + cbool(nativeAmd64)) + + if status != 0 { + return fmt.Errorf("failed setting compilation target amd: %v", string(output.intoBytes())) + } + + source, err := os.ReadFile("../../arbitrator/stylus/tests/memory.wat") + if err != nil { + return fmt.Errorf("failed reading stylus contract: %w", err) + } + + wasm, err := wasmer.Wat2Wasm(string(source)) + if err != nil { + return err + } + + status = C.stylus_compile( + goSlice(wasm), + u16(1), + cbool(true), + goSlice([]byte("booga")), + output, + ) + if status == 0 { + return fmt.Errorf("succeeded compiling non-existent arch: %v", string(output.intoBytes())) + } + + status = C.stylus_compile( + goSlice(wasm), + u16(1), + cbool(true), + goSlice([]byte{}), + output, + ) + if status != 0 { + return fmt.Errorf("failed compiling native: %v", string(output.intoBytes())) + } + + status = C.stylus_compile( + goSlice(wasm), + u16(1), + cbool(true), + goSlice(arm64CompileName), + output, + ) + if status != 0 { + return fmt.Errorf("failed compiling arm: %v", string(output.intoBytes())) + } + + status = C.stylus_compile( + goSlice(wasm), + u16(1), + cbool(true), + goSlice(amd64CompileName), + output, + ) + if status != 0 { + return fmt.Errorf("failed compiling amd: %v", string(output.intoBytes())) + } + + return nil +} From 89bcd0729803d352dfe51a29cf5ad9479d4a7e56 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Mon, 24 Jun 2024 19:23:42 -0600 Subject: [PATCH 07/80] arbos/programs: improve code in activation --- arbos/programs/native.go | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/arbos/programs/native.go b/arbos/programs/native.go index 0de63009ac..65073220a9 100644 --- a/arbos/programs/native.go +++ b/arbos/programs/native.go @@ -100,23 +100,17 @@ func activateProgramInternal( return nil, nil, nil, err } - status_asm := userStatus(C.stylus_compile( + status_asm := C.stylus_compile( goSlice(wasm), u16(version), cbool(debug), goSlice([]byte{}), output, - )) + ) - asm, msg, err := status_asm.toResult(output.intoBytes(), debug) - if err != nil { - if debug { - log.Warn("activation failed", "err", err, "msg", msg, "program", addressForLogging) - } - if errors.Is(err, vm.ErrExecutionReverted) { - return nil, nil, nil, fmt.Errorf("%w: %s", ErrProgramActivation, msg) - } - return nil, nil, nil, err + asm := output.intoBytes() + if status_asm != 0 { + return nil, nil, nil, fmt.Errorf("%w: %s", ErrProgramActivation, string(asm)) } hash := moduleHash.toHash() From da573341d62a756b0c8b9763eb8fb5ae8fee30b5 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Mon, 24 Jun 2024 19:53:53 -0600 Subject: [PATCH 08/80] clippy --- arbitrator/stylus/src/native.rs | 2 +- arbitrator/stylus/src/target_cache.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arbitrator/stylus/src/native.rs b/arbitrator/stylus/src/native.rs index a2b31ed596..c1bc06dbb0 100644 --- a/arbitrator/stylus/src/native.rs +++ b/arbitrator/stylus/src/native.rs @@ -4,7 +4,7 @@ use crate::{ cache::InitCache, env::{MeterData, WasmEnv}, - host, util, + host, }; use arbutil::{ evm::{ diff --git a/arbitrator/stylus/src/target_cache.rs b/arbitrator/stylus/src/target_cache.rs index 9e1d1eb1f5..94b3101383 100644 --- a/arbitrator/stylus/src/target_cache.rs +++ b/arbitrator/stylus/src/target_cache.rs @@ -62,7 +62,7 @@ pub fn target_cache_set(name: String, description: String, native: bool) -> Resu } pub fn target_cache_get(name: &str) -> Result { - if name.len() == 0 { + if name.is_empty() { return Ok(InitCache::target()); } TARGET_CACHE From 07aebbfd216e353686ab8e673bc62b0d38b74393 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Tue, 25 Jun 2024 17:49:30 -0600 Subject: [PATCH 09/80] testCompileArch: add load/store --- arbos/programs/cgo_test.go | 23 +++++- arbos/programs/testcompile.go | 147 +++++++++++++++++++++++++++++++--- 2 files changed, 155 insertions(+), 15 deletions(-) diff --git a/arbos/programs/cgo_test.go b/arbos/programs/cgo_test.go index c0c8953f62..6506af75dc 100644 --- a/arbos/programs/cgo_test.go +++ b/arbos/programs/cgo_test.go @@ -1,9 +1,17 @@ // Copyright 2024, Offchain Labs, Inc. // For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE +//go:build !wasm +// +build !wasm + package programs -import "testing" +import ( + "fmt" + "os" + "strings" + "testing" +) func TestConstants(t *testing.T) { err := testConstants() @@ -13,8 +21,19 @@ func TestConstants(t *testing.T) { } func TestCompileArch(t *testing.T) { - err := testCompileArch() + compile_env := os.Getenv("TEST_COMPILE") + if compile_env == "" { + fmt.Print("use TEST_COMPILE=[STORE|LOAD] to allow store/load in compile test") + } + store := strings.Contains(compile_env, "STORE") + err := testCompileArch(store) if err != nil { t.Fatal(err) } + if store || strings.Contains(compile_env, "LOAD") { + err = testCompileLoad() + if err != nil { + t.Fatal(err) + } + } } diff --git a/arbos/programs/testcompile.go b/arbos/programs/testcompile.go index 36c90f1e3b..3ee22a76bf 100644 --- a/arbos/programs/testcompile.go +++ b/arbos/programs/testcompile.go @@ -11,6 +11,13 @@ package programs /* #cgo CFLAGS: -g -Wall -I../../target/include/ #include "arbitrator.h" + +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; +typedef size_t usize; + +void handleReqWrap(usize api, u32 req_type, RustSlice *data, u64 *out_cost, GoSliceData *out_result, GoSliceData *out_raw_data); */ import "C" import ( @@ -21,10 +28,18 @@ import ( "github.com/wasmerio/wasmer-go/wasmer" ) -func testCompileArch() error { +func isNativeArm() bool { + return runtime.GOOS == "linux" && runtime.GOARCH == "arm64" +} + +func isNativeX86() bool { + return runtime.GOOS == "linux" && runtime.GOARCH == "amd64" +} + +func testCompileArch(store bool) error { - nativeArm64 := false - nativeAmd64 := false + nativeArm64 := isNativeArm() + nativeAmd64 := isNativeX86() arm64CompileName := []byte("arm64") amd64CompileName := []byte("amd64") @@ -32,17 +47,13 @@ func testCompileArch() error { arm64TargetString := []byte("arm64-linux-unknown+neon") amd64TargetString := []byte("x86_64-linux-unknown+sse4.2") - if runtime.GOOS == "linux" { - if runtime.GOARCH == "amd64" { - nativeAmd64 = true - } - if runtime.GOARCH == "arm64" { - nativeArm64 = true - } - } - output := &rustBytes{} + _, err := fmt.Print("starting test.. native arm? ", nativeArm64, " amd? ", nativeAmd64, " GOARCH/GOOS: ", runtime.GOARCH+"/"+runtime.GOOS, "\n") + if err != nil { + return err + } + status := C.stylus_target_set(goSlice(arm64CompileName), goSlice(arm64TargetString), output, @@ -61,7 +72,7 @@ func testCompileArch() error { return fmt.Errorf("failed setting compilation target amd: %v", string(output.intoBytes())) } - source, err := os.ReadFile("../../arbitrator/stylus/tests/memory.wat") + source, err := os.ReadFile("../../arbitrator/stylus/tests/add.wat") if err != nil { return fmt.Errorf("failed reading stylus contract: %w", err) } @@ -71,6 +82,17 @@ func testCompileArch() error { return err } + if store { + _, err := fmt.Print("storing compiled files to ../../target/testdata/\n") + if err != nil { + return err + } + err = os.MkdirAll("../../target/testdata", 0644) + if err != nil { + return err + } + } + status = C.stylus_compile( goSlice(wasm), u16(1), @@ -92,6 +114,17 @@ func testCompileArch() error { if status != 0 { return fmt.Errorf("failed compiling native: %v", string(output.intoBytes())) } + if store && !nativeAmd64 && !nativeArm64 { + _, err := fmt.Printf("writing host file\n") + if err != nil { + return err + } + + err = os.WriteFile("../../target/testdata/host.bin", output.intoBytes(), 0644) + if err != nil { + return err + } + } status = C.stylus_compile( goSlice(wasm), @@ -103,6 +136,17 @@ func testCompileArch() error { if status != 0 { return fmt.Errorf("failed compiling arm: %v", string(output.intoBytes())) } + if store { + _, err := fmt.Printf("writing arm file\n") + if err != nil { + return err + } + + err = os.WriteFile("../../target/testdata/arm64.bin", output.intoBytes(), 0644) + if err != nil { + return err + } + } status = C.stylus_compile( goSlice(wasm), @@ -114,6 +158,83 @@ func testCompileArch() error { if status != 0 { return fmt.Errorf("failed compiling amd: %v", string(output.intoBytes())) } + if store { + _, err := fmt.Printf("writing amd64 file\n") + if err != nil { + return err + } + + err = os.WriteFile("../../target/testdata/amd64.bin", output.intoBytes(), 0644) + if err != nil { + return err + } + } return nil } + +func testCompileLoad() error { + filePath := "../../target/testdata/host.bin" + if isNativeArm() { + filePath = "../../target/testdata/arm64.bin" + } + if isNativeX86() { + filePath = "../../target/testdata/amd64.bin" + } + + _, err := fmt.Print("starting load test. FilePath: ", filePath, " GOARCH/GOOS: ", runtime.GOARCH+"/"+runtime.GOOS, "\n") + if err != nil { + return err + } + + localAsm, err := os.ReadFile(filePath) + if err != nil { + return err + } + + calldata := []byte{} + + evmData := EvmData{} + progParams := ProgParams{ + MaxDepth: 10000, + InkPrice: 1, + DebugMode: true, + } + reqHandler := C.NativeRequestHandler{ + handle_request_fptr: (*[0]byte)(C.handleReqWrap), + id: 0, + } + + inifiniteGas := u64(0xfffffffffffffff) + + output := &rustBytes{} + + _, err = fmt.Print("launching program..\n") + if err != nil { + return err + } + + status := userStatus(C.stylus_call( + goSlice(localAsm), + goSlice(calldata), + progParams.encode(), + reqHandler, + evmData.encode(), + cbool(true), + output, + &inifiniteGas, + u32(0), + )) + + _, err = fmt.Print("returned: ", status, "\n") + if err != nil { + return err + } + + _, msg, err := status.toResult(output.intoBytes(), true) + if status == userFailure { + err = fmt.Errorf("%w: %v", err, msg) + } + + return err +} From b4f1c0a85697210ffa91aa1968b53f4a6c8a0469 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Tue, 25 Jun 2024 17:56:33 -0600 Subject: [PATCH 10/80] fix dir permissions --- arbos/programs/testcompile.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbos/programs/testcompile.go b/arbos/programs/testcompile.go index 3ee22a76bf..fa2311c850 100644 --- a/arbos/programs/testcompile.go +++ b/arbos/programs/testcompile.go @@ -87,7 +87,7 @@ func testCompileArch(store bool) error { if err != nil { return err } - err = os.MkdirAll("../../target/testdata", 0644) + err = os.MkdirAll("../../target/testdata", 0755) if err != nil { return err } From e78c7b96a9abdcb01c86a4afd64a4524c85c6b03 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Tue, 25 Jun 2024 18:03:11 -0600 Subject: [PATCH 11/80] TesstCompileArch: add documentation --- arbos/programs/cgo_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arbos/programs/cgo_test.go b/arbos/programs/cgo_test.go index 6506af75dc..c0e146d98d 100644 --- a/arbos/programs/cgo_test.go +++ b/arbos/programs/cgo_test.go @@ -20,6 +20,11 @@ func TestConstants(t *testing.T) { } } +// normal test will not write anything to disk +// to test cross-compilation: +// * run test with TEST_COMPILE=STORE on one machine +// * copy target/testdata to the other machine +// * run test with TEST_COMPILE=LOAD on the other machine func TestCompileArch(t *testing.T) { compile_env := os.Getenv("TEST_COMPILE") if compile_env == "" { From 831650861ff705c5fbae6e57553dd9f42e5e9072 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Tue, 25 Jun 2024 18:19:11 -0600 Subject: [PATCH 12/80] fix arbitrator tests --- arbitrator/stylus/src/test/api.rs | 6 ++++-- arbitrator/stylus/src/test/misc.rs | 4 ++-- arbitrator/stylus/src/test/mod.rs | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/arbitrator/stylus/src/test/api.rs b/arbitrator/stylus/src/test/api.rs index 92d7317918..074eb8cfab 100644 --- a/arbitrator/stylus/src/test/api.rs +++ b/arbitrator/stylus/src/test/api.rs @@ -14,6 +14,7 @@ use eyre::Result; use parking_lot::Mutex; use prover::programs::{memory::MemoryModel, prelude::*}; use std::{collections::HashMap, sync::Arc}; +use wasmer::Target; use super::TestInstance; @@ -53,7 +54,7 @@ impl TestEvmApi { pub fn deploy(&mut self, address: Bytes20, config: StylusConfig, name: &str) -> Result<()> { let file = format!("tests/{name}/target/wasm32-unknown-unknown/release/{name}.wasm"); let wasm = std::fs::read(file)?; - let module = native::module(&wasm, self.compile.clone())?; + let module = native::module(&wasm, self.compile.clone(), Target::default())?; self.contracts.lock().insert(address, module); self.configs.lock().insert(address, config); Ok(()) @@ -113,7 +114,8 @@ impl EvmApi for TestEvmApi { let mut native = unsafe { let contracts = self.contracts.lock(); let module = contracts.get(&contract).unwrap(); - TestInstance::deserialize(module, compile, self.clone(), evm_data).unwrap() + TestInstance::deserialize(module, compile, self.clone(), evm_data, Target::default()) + .unwrap() }; let ink = config.pricing.gas_to_ink(gas); diff --git a/arbitrator/stylus/src/test/misc.rs b/arbitrator/stylus/src/test/misc.rs index ae44a885f0..92c4394ae3 100644 --- a/arbitrator/stylus/src/test/misc.rs +++ b/arbitrator/stylus/src/test/misc.rs @@ -9,12 +9,12 @@ use crate::{ }; use eyre::Result; use prover::programs::{prelude::*, start::StartMover}; -use wasmer::{imports, Function}; +use wasmer::{imports, Function, Target}; #[test] fn test_bulk_memory() -> Result<()> { let (compile, config, ink) = test_configs(); - let mut store = compile.store(); + let mut store = compile.store(Target::default()); let filename = "../prover/test-cases/bulk-memory.wat"; let imports = imports! { "env" => { diff --git a/arbitrator/stylus/src/test/mod.rs b/arbitrator/stylus/src/test/mod.rs index cfc0ab23b7..a6033ee7bd 100644 --- a/arbitrator/stylus/src/test/mod.rs +++ b/arbitrator/stylus/src/test/mod.rs @@ -33,7 +33,7 @@ type TestInstance = NativeInstance; impl TestInstance { fn new_test(path: &str, compile: CompileConfig) -> Result { - let mut store = compile.store(); + let mut store = compile.store(Target::default()); let imports = imports! { "test" => { "noop" => Function::new_typed(&mut store, || {}), From 9beb4766a95946c317da584860ad61e110b1f7b8 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Tue, 9 Jul 2024 17:31:21 +0200 Subject: [PATCH 13/80] add stylus target config --- execution/gethexec/node.go | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index cb2bfe12e8..073b54e58f 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -38,6 +38,24 @@ func DangerousConfigAddOptions(prefix string, f *flag.FlagSet) { f.Int64(prefix+".reorg-to-block", DefaultDangerousConfig.ReorgToBlock, "DANGEROUS! forces a reorg to an old block height. To be used for testing only. -1 to disable") } +type StylusTargetConfig struct { + Arm string `koanf:"arm"` + X86 string `koanf:"x86"` + Host string `koanf:"host"` +} + +var DefaultStylusTargetConfig = StylusTargetConfig{ + Arm: "arm64-linux-unknown+neon", + X86: "x86_64-linux-unknown+sse4.2", + Host: "", +} + +func StylusTargetConfigAddOptions(prefix string, f *flag.FlagSet) { + f.String(prefix+".arm", DefaultStylusTargetConfig.Arm, "stylus programs compilation target for 64-bit ARM system") + f.String(prefix+".x86", DefaultStylusTargetConfig.X86, "stylus programs compilation target for 64-bit x86 system") + f.String(prefix+".host", DefaultStylusTargetConfig.Host, "stylus programs compilation target for system other than 64-bit ARM or 64-bit x86") +} + type Config struct { ParentChainReader headerreader.Config `koanf:"parent-chain-reader" reload:"hot"` Sequencer SequencerConfig `koanf:"sequencer" reload:"hot"` @@ -52,8 +70,8 @@ type Config struct { Dangerous DangerousConfig `koanf:"dangerous"` EnablePrefetchBlock bool `koanf:"enable-prefetch-block"` SyncMonitor SyncMonitorConfig `koanf:"sync-monitor"` - - forwardingTarget string + StylusTarget StylusTargetConfig `koanf:"stylus-target"` + forwardingTarget string } func (c *Config) Validate() error { @@ -88,6 +106,7 @@ func ConfigAddOptions(prefix string, f *flag.FlagSet) { f.Uint64(prefix+".tx-lookup-limit", ConfigDefault.TxLookupLimit, "retain the ability to lookup transactions by hash for the past N blocks (0 = all blocks)") DangerousConfigAddOptions(prefix+".dangerous", f) f.Bool(prefix+".enable-prefetch-block", ConfigDefault.EnablePrefetchBlock, "enable prefetching of blocks") + StylusTargetConfigAddOptions(prefix+".stylus-target", f) } var ConfigDefault = Config{ From d8252792b14763c7b23fcad137b8ad45e9ea79ec Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Tue, 9 Jul 2024 20:16:08 +0200 Subject: [PATCH 14/80] set stylus target --- arbnode/inbox_test.go | 4 +++- arbos/programs/native.go | 15 +++++++++++++++ execution/gethexec/executionengine.go | 18 +++++++++++++++++- execution/gethexec/node.go | 11 ++++++++--- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/arbnode/inbox_test.go b/arbnode/inbox_test.go index 252d7c9b7d..6ccc0bb0c4 100644 --- a/arbnode/inbox_test.go +++ b/arbnode/inbox_test.go @@ -65,7 +65,9 @@ func NewTransactionStreamerForTest(t *testing.T, ownerAddress common.Address) (* if err != nil { Fail(t, err) } - execEngine.Initialize(gethexec.DefaultCachingConfig.StylusLRUCache) + if err := execEngine.Initialize(gethexec.DefaultCachingConfig.StylusLRUCache, &gethexec.DefaultStylusTargetConfig); err != nil { + Fail(t, err) + } execSeq := &execClientWrapper{execEngine, t} inbox, err := NewTransactionStreamer(arbDb, bc.Config(), execSeq, nil, make(chan error, 1), transactionStreamerConfigFetcher, &DefaultSnapSyncConfig) if err != nil { diff --git a/arbos/programs/native.go b/arbos/programs/native.go index 65073220a9..49374feb44 100644 --- a/arbos/programs/native.go +++ b/arbos/programs/native.go @@ -268,6 +268,21 @@ func ResizeWasmLruCache(size uint32) { C.stylus_cache_lru_resize(u32(size)) } +func SetTarget(name string, description string, native bool) error { + output := &rustBytes{} + status := userStatus(C.stylus_target_set( + goSlice([]byte(name)), + goSlice([]byte(description)), + output, + cbool(native), + )) + if status != userSuccess { + msg := arbutil.ToStringOrHex(output.intoBytes()) + return fmt.Errorf("stylus_target_set failed with status %v: %v", status, msg) + } + return nil +} + func (value bytes32) toHash() common.Hash { hash := common.Hash{} for index, b := range value.bytes { diff --git a/execution/gethexec/executionengine.go b/execution/gethexec/executionengine.go index 95b865df5a..b17aca1144 100644 --- a/execution/gethexec/executionengine.go +++ b/execution/gethexec/executionengine.go @@ -20,6 +20,7 @@ import ( "fmt" "os" "path" + "runtime" "runtime/pprof" "runtime/trace" "sync" @@ -149,10 +150,25 @@ func (s *ExecutionEngine) MarkFeedStart(to arbutil.MessageIndex) { } } -func (s *ExecutionEngine) Initialize(rustCacheSize uint32) { +func (s *ExecutionEngine) Initialize(rustCacheSize uint32, targetConfig *StylusTargetConfig) error { if rustCacheSize != 0 { programs.ResizeWasmLruCache(rustCacheSize) } + effectiveStylusTarget := targetConfig.Host + if runtime.GOOS == "linux" { + switch runtime.GOARCH { + case "arm": + effectiveStylusTarget = targetConfig.Arm + case "amd64": + effectiveStylusTarget = targetConfig.X86 + } + } + // TODO what should we use for target name? + err := programs.SetTarget("native", effectiveStylusTarget, true) + if err != nil { + return fmt.Errorf("Failed to set stylus target: %w", err) + } + return nil } func (s *ExecutionEngine) SetRecorder(recorder *BlockRecorder) { diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 073b54e58f..0acd8d26be 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -47,7 +47,7 @@ type StylusTargetConfig struct { var DefaultStylusTargetConfig = StylusTargetConfig{ Arm: "arm64-linux-unknown+neon", X86: "x86_64-linux-unknown+sse4.2", - Host: "", + Host: "aarch64-apple-darwin", } func StylusTargetConfigAddOptions(prefix string, f *flag.FlagSet) { @@ -122,6 +122,7 @@ var ConfigDefault = Config{ Dangerous: DefaultDangerousConfig, Forwarder: DefaultNodeForwarderConfig, EnablePrefetchBlock: true, + StylusTarget: DefaultStylusTargetConfig, } func ConfigDefaultNonSequencerTest() *Config { @@ -301,9 +302,13 @@ func (n *ExecutionNode) MarkFeedStart(to arbutil.MessageIndex) { } func (n *ExecutionNode) Initialize(ctx context.Context) error { - n.ExecEngine.Initialize(n.ConfigFetcher().Caching.StylusLRUCache) + config := n.ConfigFetcher() + err := n.ExecEngine.Initialize(config.Caching.StylusLRUCache, &config.StylusTarget) + if err != nil { + return fmt.Errorf("error initializing execution engine: %w", err) + } n.ArbInterface.Initialize(n) - err := n.Backend.Start() + err = n.Backend.Start() if err != nil { return fmt.Errorf("error starting geth backend: %w", err) } From fe2e0dcea02580a9ab46947b5152229bbb949897 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Mon, 15 Jul 2024 17:59:02 +0200 Subject: [PATCH 15/80] map from target to asm --- arbos/programs/native.go | 47 ++++++++++++++++++++------- arbos/programs/wasmstorehelper.go | 6 ++-- execution/gethexec/executionengine.go | 24 +++++++------- go-ethereum | 2 +- validator/server_api/json.go | 20 ++++++++---- validator/server_jit/jit_machine.go | 8 ++++- 6 files changed, 73 insertions(+), 34 deletions(-) diff --git a/arbos/programs/native.go b/arbos/programs/native.go index 49374feb44..3ef26eb13e 100644 --- a/arbos/programs/native.go +++ b/arbos/programs/native.go @@ -21,6 +21,7 @@ import "C" import ( "errors" "fmt" + "runtime" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" @@ -54,11 +55,11 @@ func activateProgram( debug bool, burner burn.Burner, ) (*activationInfo, error) { - info, asm, module, err := activateProgramInternal(db, program, codehash, wasm, page_limit, version, debug, burner.GasLeft()) + info, asmMap, module, err := activateProgramInternal(db, program, codehash, wasm, page_limit, version, debug, burner.GasLeft()) if err != nil { return nil, err } - db.ActivateWasm(info.moduleHash, asm, module) + db.ActivateWasm(info.moduleHash, asmMap, module) return info, nil } @@ -71,7 +72,7 @@ func activateProgramInternal( version uint16, debug bool, gasLeft *uint64, -) (*activationInfo, []byte, []byte, error) { +) (*activationInfo, map[string][]byte, []byte, error) { output := &rustBytes{} moduleHash := &bytes32{} stylusData := &C.StylusData{} @@ -99,19 +100,19 @@ func activateProgramInternal( } return nil, nil, nil, err } - + target := LocalTargetName() status_asm := C.stylus_compile( goSlice(wasm), u16(version), cbool(debug), - goSlice([]byte{}), + goSlice([]byte(target)), output, ) - asm := output.intoBytes() if status_asm != 0 { return nil, nil, nil, fmt.Errorf("%w: %s", ErrProgramActivation, string(asm)) } + asmMap := map[string][]byte{target: asm} hash := moduleHash.toHash() @@ -122,11 +123,12 @@ func activateProgramInternal( asmEstimate: uint32(stylusData.asm_estimate), footprint: uint16(stylusData.footprint), } - return info, asm, module, err + return info, asmMap, module, err } func getLocalAsm(statedb vm.StateDB, moduleHash common.Hash, addressForLogging common.Address, code []byte, codeHash common.Hash, pagelimit uint16, time uint64, debugMode bool, program Program) ([]byte, error) { - localAsm, err := statedb.TryGetActivatedAsm(moduleHash) + localTarget := LocalTargetName() + localAsm, err := statedb.TryGetActivatedAsm(localTarget, moduleHash) if err == nil && len(localAsm) > 0 { return localAsm, nil } @@ -140,7 +142,7 @@ func getLocalAsm(statedb vm.StateDB, moduleHash common.Hash, addressForLogging c unlimitedGas := uint64(0xffffffffffff) // we know program is activated, so it must be in correct version and not use too much memory - info, asm, module, err := activateProgramInternal(statedb, addressForLogging, codeHash, wasm, pagelimit, program.version, debugMode, &unlimitedGas) + info, asmMap, module, err := activateProgramInternal(statedb, addressForLogging, codeHash, wasm, pagelimit, program.version, debugMode, &unlimitedGas) if err != nil { log.Error("failed to reactivate program", "address", addressForLogging, "expected moduleHash", moduleHash, "err", err) return nil, fmt.Errorf("failed to reactivate program address: %v err: %w", addressForLogging, err) @@ -156,14 +158,23 @@ func getLocalAsm(statedb vm.StateDB, moduleHash common.Hash, addressForLogging c // stylus program is active on-chain, and was activated in the past // so we store it directly to database batch := statedb.Database().WasmStore().NewBatch() - rawdb.WriteActivation(batch, moduleHash, asm, module) + rawdb.WriteActivation(batch, moduleHash, asmMap, module) if err := batch.Write(); err != nil { log.Error("failed writing re-activation to state", "address", addressForLogging, "err", err) } } else { // program activated recently, possibly in this eth_call // store it to statedb. It will be stored to database if statedb is commited - statedb.ActivateWasm(info.moduleHash, asm, module) + statedb.ActivateWasm(info.moduleHash, asmMap, module) + } + asm, exists := asmMap[localTarget] + if !exists { + var availableTargets []string + for target := range asmMap { + availableTargets = append(availableTargets, target) + } + log.Error("failed to reactivate program - missing asm for local target", "address", addressForLogging, "local target", localTarget, "available targets", availableTargets) + return nil, fmt.Errorf("failed to reactivate program - missing asm for local target, address: %v, local target: %v, available targets: %v", addressForLogging, localTarget, availableTargets) } return asm, nil } @@ -190,6 +201,7 @@ func callProgram( } if db, ok := db.(*state.StateDB); ok { + // TODO support validation nodes running on different architectures db.RecordProgram(moduleHash) } @@ -268,6 +280,19 @@ func ResizeWasmLruCache(size uint32) { C.stylus_cache_lru_resize(u32(size)) } +// TODO assign the target name constant at compile time? +func LocalTargetName() string { + if runtime.GOOS == "linux" { + switch runtime.GOARCH { + case "arm64": + return rawdb.TargetArm + case "amd64": + return rawdb.TargetX86 + } + } + return rawdb.TargetHost +} + func SetTarget(name string, description string, native bool) error { output := &rustBytes{} status := userStatus(C.stylus_target_set( diff --git a/arbos/programs/wasmstorehelper.go b/arbos/programs/wasmstorehelper.go index 9e69178694..577a533151 100644 --- a/arbos/programs/wasmstorehelper.go +++ b/arbos/programs/wasmstorehelper.go @@ -44,7 +44,7 @@ func (p Programs) SaveActiveProgramToWasmStore(statedb *state.StateDB, codeHash } // If already in wasm store then return early - localAsm, err := statedb.TryGetActivatedAsm(moduleHash) + localAsm, err := statedb.TryGetActivatedAsm(LocalTargetName(), moduleHash) if err == nil && len(localAsm) > 0 { return nil } @@ -58,7 +58,7 @@ func (p Programs) SaveActiveProgramToWasmStore(statedb *state.StateDB, codeHash unlimitedGas := uint64(0xffffffffffff) // We know program is activated, so it must be in correct version and not use too much memory // Empty program address is supplied because we dont have access to this during rebuilding of wasm store - info, asm, module, err := activateProgramInternal(statedb, common.Address{}, codeHash, wasm, params.PageLimit, program.version, debugMode, &unlimitedGas) + info, asmMap, module, err := activateProgramInternal(statedb, common.Address{}, codeHash, wasm, params.PageLimit, program.version, debugMode, &unlimitedGas) if err != nil { log.Error("failed to reactivate program while rebuilding wasm store", "expected moduleHash", moduleHash, "err", err) return fmt.Errorf("failed to reactivate program while rebuilding wasm store: %w", err) @@ -70,7 +70,7 @@ func (p Programs) SaveActiveProgramToWasmStore(statedb *state.StateDB, codeHash } batch := statedb.Database().WasmStore().NewBatch() - rawdb.WriteActivation(batch, moduleHash, asm, module) + rawdb.WriteActivation(batch, moduleHash, asmMap, module) if err := batch.Write(); err != nil { log.Error("failed writing re-activation to state while rebuilding wasm store", "err", err) return err diff --git a/execution/gethexec/executionengine.go b/execution/gethexec/executionengine.go index b17aca1144..0e46b41e34 100644 --- a/execution/gethexec/executionengine.go +++ b/execution/gethexec/executionengine.go @@ -20,7 +20,6 @@ import ( "fmt" "os" "path" - "runtime" "runtime/pprof" "runtime/trace" "sync" @@ -28,6 +27,7 @@ import ( "time" "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" @@ -154,17 +154,17 @@ func (s *ExecutionEngine) Initialize(rustCacheSize uint32, targetConfig *StylusT if rustCacheSize != 0 { programs.ResizeWasmLruCache(rustCacheSize) } - effectiveStylusTarget := targetConfig.Host - if runtime.GOOS == "linux" { - switch runtime.GOARCH { - case "arm": - effectiveStylusTarget = targetConfig.Arm - case "amd64": - effectiveStylusTarget = targetConfig.X86 - } - } - // TODO what should we use for target name? - err := programs.SetTarget("native", effectiveStylusTarget, true) + var effectiveStylusTarget string + targetName := programs.LocalTargetName() + switch targetName { + case rawdb.TargetArm: + effectiveStylusTarget = targetConfig.Arm + case rawdb.TargetX86: + effectiveStylusTarget = targetConfig.X86 + case rawdb.TargetHost: + effectiveStylusTarget = targetConfig.Host + } + err := programs.SetTarget(targetName, effectiveStylusTarget, true) if err != nil { return fmt.Errorf("Failed to set stylus target: %w", err) } diff --git a/go-ethereum b/go-ethereum index b85c24798e..e0ac28c42f 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit b85c24798efc5a826cd813ac899a1ab168db31c2 +Subproject commit e0ac28c42fcb377ac01642eb85055af3e874f922 diff --git a/validator/server_api/json.go b/validator/server_api/json.go index 3dd817d5ae..c22c1260d3 100644 --- a/validator/server_api/json.go +++ b/validator/server_api/json.go @@ -79,7 +79,7 @@ func (i *InputJSON) WriteToFile() error { type UserWasmJson struct { Module string - Asm string + Asm map[string]string } type BatchInfoJson struct { @@ -107,8 +107,12 @@ func ValidationInputToJson(entry *validator.ValidationInput) *InputJSON { res.BatchInfo = append(res.BatchInfo, BatchInfoJson{Number: binfo.Number, DataB64: encData}) } for moduleHash, info := range entry.UserWasms { + asmMap := make(map[string]string, len(info.Asm)) + for target, asm := range info.Asm { + asmMap[target] = base64.StdEncoding.EncodeToString(asm) + } encWasm := UserWasmJson{ - Asm: base64.StdEncoding.EncodeToString(info.Asm), + Asm: asmMap, Module: base64.StdEncoding.EncodeToString(info.Module), } res.UserWasms[moduleHash] = encWasm @@ -147,16 +151,20 @@ func ValidationInputFromJson(entry *InputJSON) (*validator.ValidationInput, erro valInput.BatchInfo = append(valInput.BatchInfo, decInfo) } for moduleHash, info := range entry.UserWasms { - asm, err := base64.StdEncoding.DecodeString(info.Asm) - if err != nil { - return nil, err + asmMap := make(map[string][]byte, len(info.Asm)) + for target, asmString := range info.Asm { + asm, err := base64.StdEncoding.DecodeString(asmString) + if err != nil { + return nil, err + } + asmMap[target] = asm } module, err := base64.StdEncoding.DecodeString(info.Module) if err != nil { return nil, err } decInfo := state.ActivatedWasm{ - Asm: asm, + Asm: asmMap, Module: module, } valInput.UserWasms[moduleHash] = decInfo diff --git a/validator/server_jit/jit_machine.go b/validator/server_jit/jit_machine.go index 1a3ccfa340..4482b9fb6b 100644 --- a/validator/server_jit/jit_machine.go +++ b/validator/server_jit/jit_machine.go @@ -17,6 +17,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" + "github.com/offchainlabs/nitro/arbos/programs" "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/validator" ) @@ -220,7 +221,12 @@ func (machine *JitMachine) prove( if err := writeExact(moduleHash[:]); err != nil { return state, err } - if err := writeBytes(info.Asm); err != nil { + targetName := programs.LocalTargetName() + asm, exists := info.Asm[targetName] + if !exists { + return state, fmt.Errorf("Missing asm for local target, target: %s", targetName) + } + if err := writeBytes(asm); err != nil { return state, err } } From 35b1bd161f551b64ea05d23973246c6a422eee08 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Mon, 15 Jul 2024 18:16:07 +0200 Subject: [PATCH 16/80] update geth --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index e0ac28c42f..ee41c04697 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit e0ac28c42fcb377ac01642eb85055af3e874f922 +Subproject commit ee41c04697440bcb28d33b03cec49e59c320a132 From 782366d3d1057c1da99c71b1c050957f5416b94c Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Mon, 22 Jul 2024 17:24:36 +0200 Subject: [PATCH 17/80] update geth --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index ee41c04697..53bb6e8c43 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit ee41c04697440bcb28d33b03cec49e59c320a132 +Subproject commit 53bb6e8c4302c86e1efed5391ff660508b03bebc From 047d9619efe939b9bbfcb24ef7338a94de50cb34 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Mon, 22 Jul 2024 18:02:05 +0200 Subject: [PATCH 18/80] update geth pin --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index 53bb6e8c43..b1a40de494 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 53bb6e8c4302c86e1efed5391ff660508b03bebc +Subproject commit b1a40de4944f74b77a307622de0c74b78d92307e From c482a2a06882ac539ed1563ddfa2cfacf1daf409 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Wed, 24 Jul 2024 00:30:51 +0200 Subject: [PATCH 19/80] remove leftover code from activateProgramInternal --- arbos/programs/native.go | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/arbos/programs/native.go b/arbos/programs/native.go index 6a9b56b34b..c7e52e4f85 100644 --- a/arbos/programs/native.go +++ b/arbos/programs/native.go @@ -114,19 +114,6 @@ func activateProgramInternal( } asmMap := map[string][]byte{target: asm} - status_asm := C.stylus_compile( - goSlice(wasm), - u16(version), - cbool(debug), - goSlice([]byte{}), - output, - ) - - asm := output.intoBytes() - if status_asm != 0 { - return nil, nil, nil, fmt.Errorf("%w: %s", ErrProgramActivation, string(asm)) - } - hash := moduleHash.toHash() info := &activationInfo{ From 2785dfda29acf744af0d10249e20a3c829ae9215 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Wed, 24 Jul 2024 18:04:24 +0200 Subject: [PATCH 20/80] add wasm schema version check in init --- cmd/nitro/init.go | 28 ++++++++++++++++++++++++++++ go-ethereum | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index a958572458..f839063bba 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -406,6 +406,26 @@ func isLeveldbNotExistError(err error) bool { return os.IsNotExist(err) } +func databaseIsEmpty(db ethdb.Database) bool { + it := db.NewIterator(nil, nil) + defer it.Release() + return it.Next() +} + +// if db is not empty, validates if wasm database schema version matches current version +// otherwise persists current version +func validateWasmStoreSchemaVersion(db ethdb.Database) error { + if !databaseIsEmpty(db) { + version := rawdb.ReadWasmSchemaVersion(db) + if len(version) != 1 || version[0] != rawdb.WasmSchemaVersion { + return fmt.Errorf("Wasm database schema version doesn't match current version, current: %v, read from wasm database: %v", rawdb.WasmSchemaVersion, version) + } + } else { + rawdb.WriteWasmSchemaVersion(db) + } + return nil +} + func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeConfig, chainId *big.Int, cacheConfig *core.CacheConfig, persistentConfig *conf.PersistentConfig, l1Client arbutil.L1Interface, rollupAddrs chaininfo.RollupAddresses) (ethdb.Database, *core.BlockChain, error) { if !config.Init.Force { if readOnlyDb, err := stack.OpenDatabaseWithFreezerWithExtraOptions("l2chaindata", 0, 0, config.Persistent.Ancient, "l2chaindata/", true, persistentConfig.Pebble.ExtraOptions("l2chaindata")); err == nil { @@ -422,6 +442,10 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo if err != nil { return nil, nil, err } + if err := validateWasmStoreSchemaVersion(wasmDb); err != nil { + // TODO add option to rebuild wasmDb from scratch in case of version mismatch + return nil, nil, err + } chainDb := rawdb.WrapDatabaseWithWasm(chainData, wasmDb, 1) _, err = rawdb.ParseStateScheme(cacheConfig.StateScheme, chainDb) if err != nil { @@ -536,6 +560,10 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo if err != nil { return nil, nil, err } + if err := validateWasmStoreSchemaVersion(wasmDb); err != nil { + // TODO remove pre-existing wasmdb here? + return nil, nil, err + } chainDb := rawdb.WrapDatabaseWithWasm(chainData, wasmDb, 1) _, err = rawdb.ParseStateScheme(cacheConfig.StateScheme, chainDb) if err != nil { diff --git a/go-ethereum b/go-ethereum index c166c0be60..ff2a8bc07e 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit c166c0be602852b8afda8cab98ea52cd01829239 +Subproject commit ff2a8bc07e9f79e7d95e2e882f888559a4422fe3 From 3ee75e4d7bf1f0ee60d808a5f14285aabec60c9d Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Wed, 24 Jul 2024 21:57:07 +0200 Subject: [PATCH 21/80] fix databaseIsEmpty check --- cmd/nitro/init.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index f839063bba..ab5acee09f 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -409,7 +409,7 @@ func isLeveldbNotExistError(err error) bool { func databaseIsEmpty(db ethdb.Database) bool { it := db.NewIterator(nil, nil) defer it.Release() - return it.Next() + return !it.Next() } // if db is not empty, validates if wasm database schema version matches current version From 5cf23fa3dda653130e8bad0e725dc8479bcc3344 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Wed, 24 Jul 2024 23:27:45 +0200 Subject: [PATCH 22/80] remove outdated comment --- arbos/programs/native.go | 1 - 1 file changed, 1 deletion(-) diff --git a/arbos/programs/native.go b/arbos/programs/native.go index c7e52e4f85..c4ba233163 100644 --- a/arbos/programs/native.go +++ b/arbos/programs/native.go @@ -201,7 +201,6 @@ func callProgram( } if db, ok := db.(*state.StateDB); ok { - // TODO support validation nodes running on different architectures db.RecordProgram(moduleHash) } From a6167df5bf4ec04fa35a46a5374b1c59bd6f574c Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 2 Aug 2024 16:13:05 +0200 Subject: [PATCH 23/80] log error when stylus_target_set fails --- arbos/programs/native.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arbos/programs/native.go b/arbos/programs/native.go index c4ba233163..b8337b7000 100644 --- a/arbos/programs/native.go +++ b/arbos/programs/native.go @@ -302,7 +302,8 @@ func SetTarget(name string, description string, native bool) error { )) if status != userSuccess { msg := arbutil.ToStringOrHex(output.intoBytes()) - return fmt.Errorf("stylus_target_set failed with status %v: %v", status, msg) + log.Error("failed to set stylus compilation target", "status", status, "msg", msg) + return fmt.Errorf("failed to set stylus compilation target, status %v: %v", status, msg) } return nil } From d9a420ce70ace641591d675725a53cc2d857cd23 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Sat, 3 Aug 2024 01:06:06 +0200 Subject: [PATCH 24/80] store wavm in the same map as native asms --- arbos/programs/native.go | 25 ++++++++++++--------- arbos/programs/wasmstorehelper.go | 4 ++-- cmd/nitro/init.go | 4 ++-- go-ethereum | 2 +- validator/server_api/json.go | 27 ++++++++++++----------- validator/server_arb/validator_spawner.go | 5 +++-- validator/server_jit/jit_machine.go | 4 ++-- 7 files changed, 38 insertions(+), 33 deletions(-) diff --git a/arbos/programs/native.go b/arbos/programs/native.go index b8337b7000..85e5d69855 100644 --- a/arbos/programs/native.go +++ b/arbos/programs/native.go @@ -55,11 +55,11 @@ func activateProgram( debug bool, burner burn.Burner, ) (*activationInfo, error) { - info, asmMap, module, err := activateProgramInternal(db, program, codehash, wasm, page_limit, version, debug, burner.GasLeft()) + info, asmMap, err := activateProgramInternal(db, program, codehash, wasm, page_limit, version, debug, burner.GasLeft()) if err != nil { return nil, err } - db.ActivateWasm(info.moduleHash, asmMap, module) + db.ActivateWasm(info.moduleHash, asmMap) return info, nil } @@ -72,7 +72,7 @@ func activateProgramInternal( version uint16, debug bool, gasLeft *uint64, -) (*activationInfo, map[string][]byte, []byte, error) { +) (*activationInfo, map[string][]byte, error) { output := &rustBytes{} moduleHash := &bytes32{} stylusData := &C.StylusData{} @@ -96,9 +96,9 @@ func activateProgramInternal( log.Warn("activation failed", "err", err, "msg", msg, "program", addressForLogging) } if errors.Is(err, vm.ErrExecutionReverted) { - return nil, nil, nil, fmt.Errorf("%w: %s", ErrProgramActivation, msg) + return nil, nil, fmt.Errorf("%w: %s", ErrProgramActivation, msg) } - return nil, nil, nil, err + return nil, nil, err } target := LocalTargetName() status_asm := C.stylus_compile( @@ -110,9 +110,12 @@ func activateProgramInternal( ) asm := output.intoBytes() if status_asm != 0 { - return nil, nil, nil, fmt.Errorf("%w: %s", ErrProgramActivation, string(asm)) + return nil, nil, fmt.Errorf("%w: %s", ErrProgramActivation, string(asm)) + } + asmMap := map[string][]byte{ + rawdb.TargetWavm: module, + target: asm, } - asmMap := map[string][]byte{target: asm} hash := moduleHash.toHash() @@ -123,7 +126,7 @@ func activateProgramInternal( asmEstimate: uint32(stylusData.asm_estimate), footprint: uint16(stylusData.footprint), } - return info, asmMap, module, err + return info, asmMap, err } func getLocalAsm(statedb vm.StateDB, moduleHash common.Hash, addressForLogging common.Address, code []byte, codeHash common.Hash, pagelimit uint16, time uint64, debugMode bool, program Program) ([]byte, error) { @@ -142,7 +145,7 @@ func getLocalAsm(statedb vm.StateDB, moduleHash common.Hash, addressForLogging c unlimitedGas := uint64(0xffffffffffff) // we know program is activated, so it must be in correct version and not use too much memory - info, asmMap, module, err := activateProgramInternal(statedb, addressForLogging, codeHash, wasm, pagelimit, program.version, debugMode, &unlimitedGas) + info, asmMap, err := activateProgramInternal(statedb, addressForLogging, codeHash, wasm, pagelimit, program.version, debugMode, &unlimitedGas) if err != nil { log.Error("failed to reactivate program", "address", addressForLogging, "expected moduleHash", moduleHash, "err", err) return nil, fmt.Errorf("failed to reactivate program address: %v err: %w", addressForLogging, err) @@ -158,14 +161,14 @@ func getLocalAsm(statedb vm.StateDB, moduleHash common.Hash, addressForLogging c // stylus program is active on-chain, and was activated in the past // so we store it directly to database batch := statedb.Database().WasmStore().NewBatch() - rawdb.WriteActivation(batch, moduleHash, asmMap, module) + rawdb.WriteActivation(batch, moduleHash, asmMap) if err := batch.Write(); err != nil { log.Error("failed writing re-activation to state", "address", addressForLogging, "err", err) } } else { // program activated recently, possibly in this eth_call // store it to statedb. It will be stored to database if statedb is commited - statedb.ActivateWasm(info.moduleHash, asmMap, module) + statedb.ActivateWasm(info.moduleHash, asmMap) } asm, exists := asmMap[localTarget] if !exists { diff --git a/arbos/programs/wasmstorehelper.go b/arbos/programs/wasmstorehelper.go index 577a533151..64eb350eb5 100644 --- a/arbos/programs/wasmstorehelper.go +++ b/arbos/programs/wasmstorehelper.go @@ -58,7 +58,7 @@ func (p Programs) SaveActiveProgramToWasmStore(statedb *state.StateDB, codeHash unlimitedGas := uint64(0xffffffffffff) // We know program is activated, so it must be in correct version and not use too much memory // Empty program address is supplied because we dont have access to this during rebuilding of wasm store - info, asmMap, module, err := activateProgramInternal(statedb, common.Address{}, codeHash, wasm, params.PageLimit, program.version, debugMode, &unlimitedGas) + info, asmMap, err := activateProgramInternal(statedb, common.Address{}, codeHash, wasm, params.PageLimit, program.version, debugMode, &unlimitedGas) if err != nil { log.Error("failed to reactivate program while rebuilding wasm store", "expected moduleHash", moduleHash, "err", err) return fmt.Errorf("failed to reactivate program while rebuilding wasm store: %w", err) @@ -70,7 +70,7 @@ func (p Programs) SaveActiveProgramToWasmStore(statedb *state.StateDB, codeHash } batch := statedb.Database().WasmStore().NewBatch() - rawdb.WriteActivation(batch, moduleHash, asmMap, module) + rawdb.WriteActivation(batch, moduleHash, asmMap) if err := batch.Write(); err != nil { log.Error("failed writing re-activation to state while rebuilding wasm store", "err", err) return err diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index ab5acee09f..0e4e3ae91b 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -443,7 +443,7 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo return nil, nil, err } if err := validateWasmStoreSchemaVersion(wasmDb); err != nil { - // TODO add option to rebuild wasmDb from scratch in case of version mismatch + // TODO(stylus-target) add option to rebuild wasmDb from scratch in case of version mismatch return nil, nil, err } chainDb := rawdb.WrapDatabaseWithWasm(chainData, wasmDb, 1) @@ -561,7 +561,7 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo return nil, nil, err } if err := validateWasmStoreSchemaVersion(wasmDb); err != nil { - // TODO remove pre-existing wasmdb here? + // TODO(stylus-target) remove pre-existing wasmdb here? return nil, nil, err } chainDb := rawdb.WrapDatabaseWithWasm(chainData, wasmDb, 1) diff --git a/go-ethereum b/go-ethereum index ff2a8bc07e..a67b1f8e4b 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit ff2a8bc07e9f79e7d95e2e882f888559a4422fe3 +Subproject commit a67b1f8e4bf66ed1178aa593759c479ad1cfb1a5 diff --git a/validator/server_api/json.go b/validator/server_api/json.go index 485525f3a6..6230084496 100644 --- a/validator/server_api/json.go +++ b/validator/server_api/json.go @@ -10,6 +10,7 @@ import ( "os" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/offchainlabs/nitro/arbutil" @@ -106,14 +107,16 @@ func ValidationInputToJson(entry *validator.ValidationInput) *InputJSON { encData := base64.StdEncoding.EncodeToString(binfo.Data) res.BatchInfo = append(res.BatchInfo, BatchInfoJson{Number: binfo.Number, DataB64: encData}) } - for moduleHash, info := range entry.UserWasms { - asmMap := make(map[string]string, len(info.Asm)) - for target, asm := range info.Asm { - asmMap[target] = base64.StdEncoding.EncodeToString(asm) + for moduleHash, asmMap := range entry.UserWasms { + asmMapEncoded := make(map[string]string, len(asmMap)) + for target, asm := range asmMap { + asmMapEncoded[target] = base64.StdEncoding.EncodeToString(asm) } + // TODO + module := asmMapEncoded[rawdb.TargetWavm] encWasm := UserWasmJson{ - Asm: asmMap, - Module: base64.StdEncoding.EncodeToString(info.Module), + Asm: asmMapEncoded, + Module: module, } res.UserWasms[moduleHash] = encWasm } @@ -151,23 +154,21 @@ func ValidationInputFromJson(entry *InputJSON) (*validator.ValidationInput, erro valInput.BatchInfo = append(valInput.BatchInfo, decInfo) } for moduleHash, info := range entry.UserWasms { - asmMap := make(map[string][]byte, len(info.Asm)) + asmMapDecoded := make(map[string][]byte, len(info.Asm)) for target, asmString := range info.Asm { asm, err := base64.StdEncoding.DecodeString(asmString) if err != nil { return nil, err } - asmMap[target] = asm + asmMapDecoded[target] = asm } + // TODO module, err := base64.StdEncoding.DecodeString(info.Module) if err != nil { return nil, err } - decInfo := state.ActivatedWasm{ - Asm: asmMap, - Module: module, - } - valInput.UserWasms[moduleHash] = decInfo + asmMapDecoded[rawdb.TargetWavm] = module + valInput.UserWasms[moduleHash] = asmMapDecoded } return valInput, nil } diff --git a/validator/server_arb/validator_spawner.go b/validator/server_arb/validator_spawner.go index 7b9293f7bd..2a1eca4a02 100644 --- a/validator/server_arb/validator_spawner.go +++ b/validator/server_arb/validator_spawner.go @@ -21,6 +21,7 @@ import ( "github.com/offchainlabs/nitro/validator/valnode/redis" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" ) @@ -118,8 +119,8 @@ func (v *ArbitratorSpawner) loadEntryToMachine(ctx context.Context, entry *valid return fmt.Errorf("error while trying to add sequencer msg for proving: %w", err) } } - for moduleHash, info := range entry.UserWasms { - err = mach.AddUserWasm(moduleHash, info.Module) + for moduleHash, asmMap := range entry.UserWasms { + err = mach.AddUserWasm(moduleHash, asmMap[rawdb.TargetWavm]) if err != nil { log.Error( "error adding user wasm for proving", diff --git a/validator/server_jit/jit_machine.go b/validator/server_jit/jit_machine.go index 4482b9fb6b..bb37e7c796 100644 --- a/validator/server_jit/jit_machine.go +++ b/validator/server_jit/jit_machine.go @@ -217,12 +217,12 @@ func (machine *JitMachine) prove( if err := writeUint32(uint32(len(userWasms))); err != nil { return state, err } - for moduleHash, info := range userWasms { + for moduleHash, asmMap := range userWasms { if err := writeExact(moduleHash[:]); err != nil { return state, err } targetName := programs.LocalTargetName() - asm, exists := info.Asm[targetName] + asm, exists := asmMap[targetName] if !exists { return state, fmt.Errorf("Missing asm for local target, target: %s", targetName) } From 1f44f5e522f52d4a8a880f4efe3f34d4ca8b70f1 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Sat, 3 Aug 2024 02:11:05 +0200 Subject: [PATCH 25/80] use rawdb.TargetWavm const, instead of GOARCH return LocalTargetName() as jit spawner archs --- staker/block_validator.go | 3 ++- staker/challenge_manager.go | 3 ++- validator/client/redis/producer.go | 5 +++-- validator/client/validation_client.go | 4 ++-- validator/server_arb/validator_spawner.go | 7 ++++--- validator/server_jit/spawner.go | 3 ++- 6 files changed, 15 insertions(+), 10 deletions(-) diff --git a/staker/block_validator.go b/staker/block_validator.go index fc9f21cf42..394f43dee1 100644 --- a/staker/block_validator.go +++ b/staker/block_validator.go @@ -16,6 +16,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" @@ -484,7 +485,7 @@ func (v *BlockValidator) sendRecord(s *validationStatus) error { //nolint:gosec func (v *BlockValidator) writeToFile(validationEntry *validationEntry, moduleRoot common.Hash) error { - input, err := validationEntry.ToInput([]string{"wavm"}) + input, err := validationEntry.ToInput([]string{rawdb.TargetWavm}) if err != nil { return err } diff --git a/staker/challenge_manager.go b/staker/challenge_manager.go index 80cafccced..4cfdc46a0e 100644 --- a/staker/challenge_manager.go +++ b/staker/challenge_manager.go @@ -14,6 +14,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" @@ -467,7 +468,7 @@ func (m *ChallengeManager) createExecutionBackend(ctx context.Context, step uint if err != nil { return fmt.Errorf("error creating validation entry for challenge %v msg %v for execution challenge: %w", m.challengeIndex, initialCount, err) } - input, err := entry.ToInput([]string{"wavm"}) + input, err := entry.ToInput([]string{rawdb.TargetWavm}) if err != nil { return fmt.Errorf("error getting validation entry input of challenge %v msg %v: %w", m.challengeIndex, initialCount, err) } diff --git a/validator/client/redis/producer.go b/validator/client/redis/producer.go index b3ad0f8839..c8ce25e304 100644 --- a/validator/client/redis/producer.go +++ b/validator/client/redis/producer.go @@ -6,6 +6,7 @@ import ( "sync/atomic" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/log" "github.com/go-redis/redis/v8" "github.com/offchainlabs/nitro/pubsub" @@ -36,7 +37,7 @@ var DefaultValidationClientConfig = ValidationClientConfig{ Name: "redis validation client", Room: 2, RedisURL: "", - StylusArchs: []string{"wavm"}, + StylusArchs: []string{rawdb.TargetWavm}, ProducerConfig: pubsub.DefaultProducerConfig, CreateStreams: true, } @@ -46,7 +47,7 @@ var TestValidationClientConfig = ValidationClientConfig{ Room: 2, RedisURL: "", StreamPrefix: "test-", - StylusArchs: []string{"wavm"}, + StylusArchs: []string{rawdb.TargetWavm}, ProducerConfig: pubsub.TestProducerConfig, CreateStreams: false, } diff --git a/validator/client/validation_client.go b/validator/client/validation_client.go index d6743b109e..12a8e36518 100644 --- a/validator/client/validation_client.go +++ b/validator/client/validation_client.go @@ -8,10 +8,10 @@ import ( "encoding/base64" "errors" "fmt" - "runtime" "sync/atomic" "time" + "github.com/offchainlabs/nitro/arbos/programs" "github.com/offchainlabs/nitro/validator" "github.com/offchainlabs/nitro/util/containers" @@ -74,7 +74,7 @@ func (c *ValidationClient) Start(ctx context.Context) error { return fmt.Errorf("could not read stylus archs from validation server") } for _, stylusArch := range stylusArchs { - if stylusArch != "wavm" && stylusArch != runtime.GOARCH && stylusArch != "mock" { + if stylusArch != "wavm" && stylusArch != programs.LocalTargetName() && stylusArch != "mock" { return fmt.Errorf("unsupported stylus architecture: %v", stylusArch) } } diff --git a/validator/server_arb/validator_spawner.go b/validator/server_arb/validator_spawner.go index 1d4126dc7c..88019516fb 100644 --- a/validator/server_arb/validator_spawner.go +++ b/validator/server_arb/validator_spawner.go @@ -21,6 +21,7 @@ import ( "github.com/offchainlabs/nitro/validator/valnode/redis" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" ) @@ -89,7 +90,7 @@ func (s *ArbitratorSpawner) WasmModuleRoots() ([]common.Hash, error) { } func (s *ArbitratorSpawner) StylusArchs() []string { - return []string{"wavm"} + return []string{rawdb.TargetWavm} } func (s *ArbitratorSpawner) Name() string { @@ -122,14 +123,14 @@ func (v *ArbitratorSpawner) loadEntryToMachine(ctx context.Context, entry *valid return fmt.Errorf("error while trying to add sequencer msg for proving: %w", err) } } - if len(entry.UserWasms["wavm"]) == 0 { + if len(entry.UserWasms[rawdb.TargetWavm]) == 0 { for stylusArch, wasms := range entry.UserWasms { if len(wasms) > 0 { return fmt.Errorf("bad stylus arch loaded to machine. Expected wavm. Got: %s", stylusArch) } } } - for moduleHash, module := range entry.UserWasms["wavm"] { + for moduleHash, module := range entry.UserWasms[rawdb.TargetWavm] { err = mach.AddUserWasm(moduleHash, module) if err != nil { log.Error( diff --git a/validator/server_jit/spawner.go b/validator/server_jit/spawner.go index 5ba3664109..2f1f9b44f7 100644 --- a/validator/server_jit/spawner.go +++ b/validator/server_jit/spawner.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/common" + "github.com/offchainlabs/nitro/arbos/programs" "github.com/offchainlabs/nitro/util/stopwaiter" "github.com/offchainlabs/nitro/validator" "github.com/offchainlabs/nitro/validator/server_common" @@ -72,7 +73,7 @@ func (v *JitSpawner) WasmModuleRoots() ([]common.Hash, error) { } func (v *JitSpawner) StylusArchs() []string { - return []string{runtime.GOARCH} + return []string{programs.LocalTargetName()} } func (v *JitSpawner) execute( From 35dc7000ccdd0a7127357db655d3a758b20fa092 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Sat, 3 Aug 2024 02:28:33 +0200 Subject: [PATCH 26/80] fix supported arch check in validationEntry.ToInput --- staker/stateless_block_validator.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/staker/stateless_block_validator.go b/staker/stateless_block_validator.go index 6ac6616e31..bc8254eb77 100644 --- a/staker/stateless_block_validator.go +++ b/staker/stateless_block_validator.go @@ -157,7 +157,7 @@ func (e *validationEntry) ToInput(stylusArchs []string) (*validator.ValidationIn localTarget := programs.LocalTargetName() for hash, asmMap := range e.UserWasms { for _, stylusArch := range stylusArchs { - if stylusArch != rawdb.TargetWavm || stylusArch != localTarget { + if stylusArch != rawdb.TargetWavm && stylusArch != localTarget { return nil, fmt.Errorf("stylusArch not supported by block validator: %v", stylusArch) } if asm, exists := asmMap[stylusArch]; exists { From d6a0579f5a420ef232d994189d4b23ff16f63be8 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Sat, 3 Aug 2024 02:32:48 +0200 Subject: [PATCH 27/80] remove outdated todo comment --- arbos/programs/native.go | 1 - 1 file changed, 1 deletion(-) diff --git a/arbos/programs/native.go b/arbos/programs/native.go index 85e5d69855..cf1fb38e1f 100644 --- a/arbos/programs/native.go +++ b/arbos/programs/native.go @@ -282,7 +282,6 @@ func ResizeWasmLruCache(size uint32) { C.stylus_cache_lru_resize(u32(size)) } -// TODO assign the target name constant at compile time? func LocalTargetName() string { if runtime.GOOS == "linux" { switch runtime.GOARCH { From 5f776d9fe4cda4f346e874a107370e935fd39d39 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Sat, 3 Aug 2024 02:40:17 +0200 Subject: [PATCH 28/80] remove unused struct --- validator/server_api/json.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/validator/server_api/json.go b/validator/server_api/json.go index 252690601b..90746e4c57 100644 --- a/validator/server_api/json.go +++ b/validator/server_api/json.go @@ -78,11 +78,6 @@ func (i *InputJSON) WriteToFile() error { return nil } -type UserWasmJson struct { - Module string - Asm map[string]string -} - type BatchInfoJson struct { Number uint64 DataB64 string From db04fa710f9c3c219aaa41bb13ebac42da4dd180 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Tue, 6 Aug 2024 16:20:53 +0200 Subject: [PATCH 29/80] fix getting wasm for local target in JitMachine.prove --- validator/server_jit/jit_machine.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/validator/server_jit/jit_machine.go b/validator/server_jit/jit_machine.go index e4fb840cbb..9c66951d77 100644 --- a/validator/server_jit/jit_machine.go +++ b/validator/server_jit/jit_machine.go @@ -12,12 +12,12 @@ import ( "net" "os" "os/exec" - "runtime" "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" + "github.com/offchainlabs/nitro/arbos/programs" "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/validator" ) @@ -212,13 +212,14 @@ func (machine *JitMachine) prove( } } - userWasms := entry.UserWasms[runtime.GOARCH] + localTarget := programs.LocalTargetName() + userWasms := entry.UserWasms[localTarget] // if there are user wasms, but only for wrong architecture - error if len(userWasms) == 0 { for arch, userWasms := range entry.UserWasms { if len(userWasms) != 0 { - return state, fmt.Errorf("bad stylus arch for validation input. got: %v, expected: %v", arch, runtime.GOARCH) + return state, fmt.Errorf("bad stylus arch for validation input. got: %v, expected: %v", arch, localTarget) } } } From ae5f1594027f363a14d6a9c1167aa71e6604329c Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Tue, 6 Aug 2024 16:52:12 +0200 Subject: [PATCH 30/80] record program for Wavm and local target --- arbos/programs/native.go | 6 +++++- go-ethereum | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arbos/programs/native.go b/arbos/programs/native.go index cf1fb38e1f..61e015ec04 100644 --- a/arbos/programs/native.go +++ b/arbos/programs/native.go @@ -204,7 +204,11 @@ func callProgram( } if db, ok := db.(*state.StateDB); ok { - db.RecordProgram(moduleHash) + targetNames := []string{ + rawdb.TargetWavm, + LocalTargetName(), + } + db.RecordProgram(targetNames, moduleHash) } evmApi := newApi(interpreter, tracingInfo, scope, memoryModel) diff --git a/go-ethereum b/go-ethereum index a67b1f8e4b..c700dab87d 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit a67b1f8e4bf66ed1178aa593759c479ad1cfb1a5 +Subproject commit c700dab87d72f5c39cd952ef85f37a72ed36725c From af312332cb76bc919afd69c272d414674c368983 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Tue, 6 Aug 2024 17:07:17 +0200 Subject: [PATCH 31/80] update geth --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index c700dab87d..04d7d72f31 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit c700dab87d72f5c39cd952ef85f37a72ed36725c +Subproject commit 04d7d72f31a4ea5aaaf0b50d2178f098aeaf6db0 From c3ef68bb39e84417c67c0152f91d38dfe7f42753 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Wed, 7 Aug 2024 13:19:56 +0200 Subject: [PATCH 32/80] rename wasm store schema version validation helper --- cmd/nitro/init.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index 0e4e3ae91b..2b678fb686 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -414,7 +414,7 @@ func databaseIsEmpty(db ethdb.Database) bool { // if db is not empty, validates if wasm database schema version matches current version // otherwise persists current version -func validateWasmStoreSchemaVersion(db ethdb.Database) error { +func validateOrWriteWasmStoreSchemaVersion(db ethdb.Database) error { if !databaseIsEmpty(db) { version := rawdb.ReadWasmSchemaVersion(db) if len(version) != 1 || version[0] != rawdb.WasmSchemaVersion { @@ -442,8 +442,7 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo if err != nil { return nil, nil, err } - if err := validateWasmStoreSchemaVersion(wasmDb); err != nil { - // TODO(stylus-target) add option to rebuild wasmDb from scratch in case of version mismatch + if err := validateOrWriteWasmStoreSchemaVersion(wasmDb); err != nil { return nil, nil, err } chainDb := rawdb.WrapDatabaseWithWasm(chainData, wasmDb, 1) @@ -560,8 +559,7 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo if err != nil { return nil, nil, err } - if err := validateWasmStoreSchemaVersion(wasmDb); err != nil { - // TODO(stylus-target) remove pre-existing wasmdb here? + if err := validateOrWriteWasmStoreSchemaVersion(wasmDb); err != nil { return nil, nil, err } chainDb := rawdb.WrapDatabaseWithWasm(chainData, wasmDb, 1) From 1e07092d2a0e3bf4dbce6b91e68ae2e4a34ca958 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 9 Aug 2024 14:14:52 +0200 Subject: [PATCH 33/80] fix merge: remove DangerousConfig --- execution/gethexec/node.go | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 4638fa9dec..38e2cd7eec 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -26,18 +26,6 @@ import ( flag "github.com/spf13/pflag" ) -type DangerousConfig struct { - ReorgToBlock int64 `koanf:"reorg-to-block"` -} - -var DefaultDangerousConfig = DangerousConfig{ - ReorgToBlock: -1, -} - -func DangerousConfigAddOptions(prefix string, f *flag.FlagSet) { - f.Int64(prefix+".reorg-to-block", DefaultDangerousConfig.ReorgToBlock, "DANGEROUS! forces a reorg to an old block height. To be used for testing only. -1 to disable") -} - type StylusTargetConfig struct { Arm string `koanf:"arm"` X86 string `koanf:"x86"` From c418f315aa8f1d16002122d1a3856f68b772e683 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 9 Aug 2024 14:19:20 +0200 Subject: [PATCH 34/80] set DefaultStylusTargetConfig.Host to empty str --- execution/gethexec/node.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 38e2cd7eec..9d2ad489db 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -35,7 +35,7 @@ type StylusTargetConfig struct { var DefaultStylusTargetConfig = StylusTargetConfig{ Arm: "arm64-linux-unknown+neon", X86: "x86_64-linux-unknown+sse4.2", - Host: "aarch64-apple-darwin", + Host: "", } func StylusTargetConfigAddOptions(prefix string, f *flag.FlagSet) { From 631a23f692c0a906a3a6ff087bd6cf3aab432cc5 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 9 Aug 2024 14:32:12 +0200 Subject: [PATCH 35/80] specify linux OS in stylus target config description --- execution/gethexec/node.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 9d2ad489db..fce2e4fa61 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -39,8 +39,8 @@ var DefaultStylusTargetConfig = StylusTargetConfig{ } func StylusTargetConfigAddOptions(prefix string, f *flag.FlagSet) { - f.String(prefix+".arm", DefaultStylusTargetConfig.Arm, "stylus programs compilation target for 64-bit ARM system") - f.String(prefix+".x86", DefaultStylusTargetConfig.X86, "stylus programs compilation target for 64-bit x86 system") + f.String(prefix+".arm", DefaultStylusTargetConfig.Arm, "stylus programs compilation target for 64-bit ARM linux") + f.String(prefix+".x86", DefaultStylusTargetConfig.X86, "stylus programs compilation target for 64-bit x86 linux") f.String(prefix+".host", DefaultStylusTargetConfig.Host, "stylus programs compilation target for system other than 64-bit ARM or 64-bit x86") } From 3d0680ef6f59b5a3741b0da7935a31e6c940c958 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 9 Aug 2024 14:34:01 +0200 Subject: [PATCH 36/80] add back the blank line after StylusTarget --- execution/gethexec/node.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index fce2e4fa61..b095e742c0 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -58,7 +58,8 @@ type Config struct { EnablePrefetchBlock bool `koanf:"enable-prefetch-block"` SyncMonitor SyncMonitorConfig `koanf:"sync-monitor"` StylusTarget StylusTargetConfig `koanf:"stylus-target"` - forwardingTarget string + + forwardingTarget string } func (c *Config) Validate() error { From e8a473d1f1414bfa9187f7fa56647d96c2cec489 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 9 Aug 2024 14:43:48 +0200 Subject: [PATCH 37/80] make sure all requested stylusArchs are included in ValidationInput --- staker/stateless_block_validator.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/staker/stateless_block_validator.go b/staker/stateless_block_validator.go index bc8254eb77..bf4e2efc17 100644 --- a/staker/stateless_block_validator.go +++ b/staker/stateless_block_validator.go @@ -13,14 +13,12 @@ import ( "github.com/offchainlabs/nitro/arbstate/daprovider" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/params" "github.com/offchainlabs/nitro/arbos/arbostypes" - "github.com/offchainlabs/nitro/arbos/programs" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/execution" "github.com/offchainlabs/nitro/util/rpcclient" @@ -154,14 +152,12 @@ func (e *validationEntry) ToInput(stylusArchs []string) (*validator.ValidationIn for _, stylusArch := range stylusArchs { res.UserWasms[stylusArch] = make(map[common.Hash][]byte) } - localTarget := programs.LocalTargetName() for hash, asmMap := range e.UserWasms { for _, stylusArch := range stylusArchs { - if stylusArch != rawdb.TargetWavm && stylusArch != localTarget { - return nil, fmt.Errorf("stylusArch not supported by block validator: %v", stylusArch) - } if asm, exists := asmMap[stylusArch]; exists { res.UserWasms[stylusArch][hash] = asm + } else { + return nil, fmt.Errorf("assembly for stylusArch not found in the validation entry, block validator might not support the architecture: %v", stylusArch) } } } From 4f93172a49ffc377e6cefcec79187cf36cf7f5c1 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 9 Aug 2024 14:54:39 +0200 Subject: [PATCH 38/80] use rawdb.TargetWavm constant instead of explicit string --- validator/client/validation_client.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/validator/client/validation_client.go b/validator/client/validation_client.go index 12a8e36518..5073377616 100644 --- a/validator/client/validation_client.go +++ b/validator/client/validation_client.go @@ -22,6 +22,7 @@ import ( "github.com/offchainlabs/nitro/validator/server_common" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" ) @@ -74,7 +75,7 @@ func (c *ValidationClient) Start(ctx context.Context) error { return fmt.Errorf("could not read stylus archs from validation server") } for _, stylusArch := range stylusArchs { - if stylusArch != "wavm" && stylusArch != programs.LocalTargetName() && stylusArch != "mock" { + if stylusArch != rawdb.TargetWavm && stylusArch != programs.LocalTargetName() && stylusArch != "mock" { return fmt.Errorf("unsupported stylus architecture: %v", stylusArch) } } From cfaee08755708c02c79bfea35e929d75b9faa74f Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 9 Aug 2024 15:08:22 +0200 Subject: [PATCH 39/80] fix typo in triple_string --- arbitrator/stylus/src/target_cache.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arbitrator/stylus/src/target_cache.rs b/arbitrator/stylus/src/target_cache.rs index 94b3101383..04d3c7b02e 100644 --- a/arbitrator/stylus/src/target_cache.rs +++ b/arbitrator/stylus/src/target_cache.rs @@ -16,11 +16,11 @@ lazy_static! { fn target_from_string(input: String) -> Result { let mut parts = input.split('+'); - let Some(trip_sting) = parts.next() else { + let Some(triple_string) = parts.next() else { return Err(eyre!("no architecture")); }; - let trip = match Triple::from_str(trip_sting) { + let triple = match Triple::from_str(triple_string) { Ok(val) => val, Err(e) => return Err(eyre!(e)), }; @@ -30,7 +30,7 @@ fn target_from_string(input: String) -> Result { features.insert(CpuFeature::from_str(flag)?); } - Ok(Target::new(trip, features)) + Ok(Target::new(triple, features)) } pub fn target_cache_set(name: String, description: String, native: bool) -> Result<()> { From 3c0172ca46b81d118108bd58cc7a6c63c2cf7b0b Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 9 Aug 2024 15:52:54 +0200 Subject: [PATCH 40/80] move default target description constants to programs, use them in testcompile --- arbos/programs/native.go | 3 +++ arbos/programs/testcompile.go | 27 +++++++++++---------------- execution/gethexec/node.go | 5 +++-- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/arbos/programs/native.go b/arbos/programs/native.go index 61e015ec04..c8b66d06db 100644 --- a/arbos/programs/native.go +++ b/arbos/programs/native.go @@ -298,6 +298,9 @@ func LocalTargetName() string { return rawdb.TargetHost } +const DefaultTargetDescriptionArm = "arm64-linux-unknown+neon" +const DefaultTargetDescriptionX86 = "x86_64-linux-unknown+sse4.2" + func SetTarget(name string, description string, native bool) error { output := &rustBytes{} status := userStatus(C.stylus_target_set( diff --git a/arbos/programs/testcompile.go b/arbos/programs/testcompile.go index fa2311c850..9e62ef0bb6 100644 --- a/arbos/programs/testcompile.go +++ b/arbos/programs/testcompile.go @@ -25,27 +25,21 @@ import ( "os" "runtime" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/wasmerio/wasmer-go/wasmer" ) -func isNativeArm() bool { - return runtime.GOOS == "linux" && runtime.GOARCH == "arm64" -} - -func isNativeX86() bool { - return runtime.GOOS == "linux" && runtime.GOARCH == "amd64" -} - func testCompileArch(store bool) error { - nativeArm64 := isNativeArm() - nativeAmd64 := isNativeX86() + localTarget := LocalTargetName() + nativeArm64 := localTarget == rawdb.TargetArm + nativeAmd64 := localTarget == rawdb.TargetX86 - arm64CompileName := []byte("arm64") - amd64CompileName := []byte("amd64") + arm64CompileName := []byte(rawdb.TargetArm) + amd64CompileName := []byte(rawdb.TargetX86) - arm64TargetString := []byte("arm64-linux-unknown+neon") - amd64TargetString := []byte("x86_64-linux-unknown+sse4.2") + arm64TargetString := []byte(DefaultTargetDescriptionArm) + amd64TargetString := []byte(DefaultTargetDescriptionX86) output := &rustBytes{} @@ -175,10 +169,11 @@ func testCompileArch(store bool) error { func testCompileLoad() error { filePath := "../../target/testdata/host.bin" - if isNativeArm() { + localTarget := LocalTargetName() + if localTarget == rawdb.TargetArm { filePath = "../../target/testdata/arm64.bin" } - if isNativeX86() { + if localTarget == rawdb.TargetX86 { filePath = "../../target/testdata/amd64.bin" } diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index b095e742c0..9ca588b5bc 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -19,6 +19,7 @@ import ( "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/rpc" "github.com/offchainlabs/nitro/arbos/arbostypes" + "github.com/offchainlabs/nitro/arbos/programs" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/execution" "github.com/offchainlabs/nitro/solgen/go/precompilesgen" @@ -33,8 +34,8 @@ type StylusTargetConfig struct { } var DefaultStylusTargetConfig = StylusTargetConfig{ - Arm: "arm64-linux-unknown+neon", - X86: "x86_64-linux-unknown+sse4.2", + Arm: programs.DefaultTargetDescriptionArm, + X86: programs.DefaultTargetDescriptionX86, Host: "", } From a7498c0e1522dd2f1c8d3e1b490ecab6c61e013e Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 9 Aug 2024 16:57:10 +0200 Subject: [PATCH 41/80] match GOARCH target naming, update geth pin --- arbos/programs/native.go | 4 ++-- arbos/programs/testcompile.go | 12 ++++++------ execution/gethexec/executionengine.go | 8 ++++---- execution/gethexec/node.go | 16 ++++++++-------- go-ethereum | 2 +- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/arbos/programs/native.go b/arbos/programs/native.go index c8b66d06db..c0da29646e 100644 --- a/arbos/programs/native.go +++ b/arbos/programs/native.go @@ -290,9 +290,9 @@ func LocalTargetName() string { if runtime.GOOS == "linux" { switch runtime.GOARCH { case "arm64": - return rawdb.TargetArm + return rawdb.TargetArm64 case "amd64": - return rawdb.TargetX86 + return rawdb.TargetAmd64 } } return rawdb.TargetHost diff --git a/arbos/programs/testcompile.go b/arbos/programs/testcompile.go index 9e62ef0bb6..6369a475af 100644 --- a/arbos/programs/testcompile.go +++ b/arbos/programs/testcompile.go @@ -32,11 +32,11 @@ import ( func testCompileArch(store bool) error { localTarget := LocalTargetName() - nativeArm64 := localTarget == rawdb.TargetArm - nativeAmd64 := localTarget == rawdb.TargetX86 + nativeArm64 := localTarget == rawdb.TargetArm64 + nativeAmd64 := localTarget == rawdb.TargetAmd64 - arm64CompileName := []byte(rawdb.TargetArm) - amd64CompileName := []byte(rawdb.TargetX86) + arm64CompileName := []byte(rawdb.TargetArm64) + amd64CompileName := []byte(rawdb.TargetAmd64) arm64TargetString := []byte(DefaultTargetDescriptionArm) amd64TargetString := []byte(DefaultTargetDescriptionX86) @@ -170,10 +170,10 @@ func testCompileArch(store bool) error { func testCompileLoad() error { filePath := "../../target/testdata/host.bin" localTarget := LocalTargetName() - if localTarget == rawdb.TargetArm { + if localTarget == rawdb.TargetArm64 { filePath = "../../target/testdata/arm64.bin" } - if localTarget == rawdb.TargetX86 { + if localTarget == rawdb.TargetAmd64 { filePath = "../../target/testdata/amd64.bin" } diff --git a/execution/gethexec/executionengine.go b/execution/gethexec/executionengine.go index 223cf28882..37c12183cf 100644 --- a/execution/gethexec/executionengine.go +++ b/execution/gethexec/executionengine.go @@ -157,10 +157,10 @@ func (s *ExecutionEngine) Initialize(rustCacheSize uint32, targetConfig *StylusT var effectiveStylusTarget string targetName := programs.LocalTargetName() switch targetName { - case rawdb.TargetArm: - effectiveStylusTarget = targetConfig.Arm - case rawdb.TargetX86: - effectiveStylusTarget = targetConfig.X86 + case rawdb.TargetArm64: + effectiveStylusTarget = targetConfig.Arm64 + case rawdb.TargetAmd64: + effectiveStylusTarget = targetConfig.Amd64 case rawdb.TargetHost: effectiveStylusTarget = targetConfig.Host } diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 9ca588b5bc..af07d5f59d 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -28,20 +28,20 @@ import ( ) type StylusTargetConfig struct { - Arm string `koanf:"arm"` - X86 string `koanf:"x86"` - Host string `koanf:"host"` + Arm64 string `koanf:"arm64"` + Amd64 string `koanf:"amd64"` + Host string `koanf:"host"` } var DefaultStylusTargetConfig = StylusTargetConfig{ - Arm: programs.DefaultTargetDescriptionArm, - X86: programs.DefaultTargetDescriptionX86, - Host: "", + Arm64: programs.DefaultTargetDescriptionArm, + Amd64: programs.DefaultTargetDescriptionX86, + Host: "", } func StylusTargetConfigAddOptions(prefix string, f *flag.FlagSet) { - f.String(prefix+".arm", DefaultStylusTargetConfig.Arm, "stylus programs compilation target for 64-bit ARM linux") - f.String(prefix+".x86", DefaultStylusTargetConfig.X86, "stylus programs compilation target for 64-bit x86 linux") + f.String(prefix+".arm64", DefaultStylusTargetConfig.Arm64, "stylus programs compilation target for 64-bit arm64 linux") + f.String(prefix+".amd64", DefaultStylusTargetConfig.Amd64, "stylus programs compilation target for 64-bit amd64 linux") f.String(prefix+".host", DefaultStylusTargetConfig.Host, "stylus programs compilation target for system other than 64-bit ARM or 64-bit x86") } diff --git a/go-ethereum b/go-ethereum index 04d7d72f31..896fca1f94 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 04d7d72f31a4ea5aaaf0b50d2178f098aeaf6db0 +Subproject commit 896fca1f94701912a7acf10a2ec3d325246a702a From 00704f20884a78d541235fb8e8d3c360ad925a71 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 9 Aug 2024 17:19:48 +0200 Subject: [PATCH 42/80] target_from_string: return default target for empty string --- arbitrator/stylus/src/target_cache.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arbitrator/stylus/src/target_cache.rs b/arbitrator/stylus/src/target_cache.rs index 04d3c7b02e..b8da26d63f 100644 --- a/arbitrator/stylus/src/target_cache.rs +++ b/arbitrator/stylus/src/target_cache.rs @@ -14,6 +14,9 @@ lazy_static! { } fn target_from_string(input: String) -> Result { + if input.is_empty() { + return Ok(Target::default()); + } let mut parts = input.split('+'); let Some(triple_string) = parts.next() else { From bf2195072eec92e86059f25f5dede72419f3a75a Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 9 Aug 2024 17:25:16 +0200 Subject: [PATCH 43/80] remove repetition in target option description --- execution/gethexec/node.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index af07d5f59d..44cc8017bf 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -40,8 +40,8 @@ var DefaultStylusTargetConfig = StylusTargetConfig{ } func StylusTargetConfigAddOptions(prefix string, f *flag.FlagSet) { - f.String(prefix+".arm64", DefaultStylusTargetConfig.Arm64, "stylus programs compilation target for 64-bit arm64 linux") - f.String(prefix+".amd64", DefaultStylusTargetConfig.Amd64, "stylus programs compilation target for 64-bit amd64 linux") + f.String(prefix+".arm64", DefaultStylusTargetConfig.Arm64, "stylus programs compilation target for arm64 linux") + f.String(prefix+".amd64", DefaultStylusTargetConfig.Amd64, "stylus programs compilation target for amd64 linux") f.String(prefix+".host", DefaultStylusTargetConfig.Host, "stylus programs compilation target for system other than 64-bit ARM or 64-bit x86") } From d304823dc2123d2689e4686f4c2c248a4961ad45 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 9 Aug 2024 17:28:47 +0200 Subject: [PATCH 44/80] simplify not supported stylusArch error message --- staker/stateless_block_validator.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/staker/stateless_block_validator.go b/staker/stateless_block_validator.go index bf4e2efc17..69005527f9 100644 --- a/staker/stateless_block_validator.go +++ b/staker/stateless_block_validator.go @@ -157,7 +157,7 @@ func (e *validationEntry) ToInput(stylusArchs []string) (*validator.ValidationIn if asm, exists := asmMap[stylusArch]; exists { res.UserWasms[stylusArch][hash] = asm } else { - return nil, fmt.Errorf("assembly for stylusArch not found in the validation entry, block validator might not support the architecture: %v", stylusArch) + return nil, fmt.Errorf("stylusArch not supported by block validator: %v", stylusArch) } } } From 2d3563df6ef2f9999a49dbee8b66c83115b3812c Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 9 Aug 2024 17:35:50 +0200 Subject: [PATCH 45/80] error only when WasmStoreSchemaVersion is greater then current version --- cmd/nitro/init.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index 2b678fb686..e781c65d8e 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -417,7 +417,7 @@ func databaseIsEmpty(db ethdb.Database) bool { func validateOrWriteWasmStoreSchemaVersion(db ethdb.Database) error { if !databaseIsEmpty(db) { version := rawdb.ReadWasmSchemaVersion(db) - if len(version) != 1 || version[0] != rawdb.WasmSchemaVersion { + if len(version) != 1 || version[0] > rawdb.WasmSchemaVersion { return fmt.Errorf("Wasm database schema version doesn't match current version, current: %v, read from wasm database: %v", rawdb.WasmSchemaVersion, version) } } else { From 90358f2419f9bc21f2ff3bcbbbc35f48bbd1f88d Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 9 Aug 2024 17:38:32 +0200 Subject: [PATCH 46/80] update geth pin --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index 896fca1f94..bbbcec2d39 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 896fca1f94701912a7acf10a2ec3d325246a702a +Subproject commit bbbcec2d395c673ce7d3ad7a52887a5446098453 From f5536f527c22106270b64fb0ccdd36de8e1ba42d Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Mon, 12 Aug 2024 12:29:03 +0200 Subject: [PATCH 47/80] update unsupported wasm schema version error message --- cmd/nitro/init.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index e781c65d8e..9ee5fe918b 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -418,7 +418,7 @@ func validateOrWriteWasmStoreSchemaVersion(db ethdb.Database) error { if !databaseIsEmpty(db) { version := rawdb.ReadWasmSchemaVersion(db) if len(version) != 1 || version[0] > rawdb.WasmSchemaVersion { - return fmt.Errorf("Wasm database schema version doesn't match current version, current: %v, read from wasm database: %v", rawdb.WasmSchemaVersion, version) + return fmt.Errorf("Unsupported wasm database schema version, current version: %v, read from wasm database: %v", rawdb.WasmSchemaVersion, version) } } else { rawdb.WriteWasmSchemaVersion(db) From 3581af3d1fda92a84203c73533dcfc44cc2b6d18 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Mon, 12 Aug 2024 15:22:32 +0200 Subject: [PATCH 48/80] use rawdb.Target type --- arbos/programs/native.go | 22 +++++++++++----------- arbos/programs/testcompile.go | 4 ++-- arbos/programs/wasmstorehelper.go | 2 +- execution/gethexec/executionengine.go | 6 +++--- go-ethereum | 2 +- staker/block_validator.go | 2 +- staker/challenge_manager.go | 2 +- staker/stateless_block_validator.go | 5 +++-- system_tests/validation_mock_test.go | 5 +++-- validator/client/redis/producer.go | 12 ++++++++---- validator/client/validation_client.go | 12 ++++++------ validator/interface.go | 3 ++- validator/server_api/json.go | 15 ++++++++------- validator/server_arb/validator_spawner.go | 4 ++-- validator/server_jit/jit_machine.go | 2 +- validator/server_jit/spawner.go | 5 +++-- validator/validation_entry.go | 3 ++- validator/valnode/validation_api.go | 3 ++- 18 files changed, 60 insertions(+), 49 deletions(-) diff --git a/arbos/programs/native.go b/arbos/programs/native.go index c0da29646e..38b00a5fcf 100644 --- a/arbos/programs/native.go +++ b/arbos/programs/native.go @@ -72,7 +72,7 @@ func activateProgramInternal( version uint16, debug bool, gasLeft *uint64, -) (*activationInfo, map[string][]byte, error) { +) (*activationInfo, map[rawdb.Target][]byte, error) { output := &rustBytes{} moduleHash := &bytes32{} stylusData := &C.StylusData{} @@ -100,7 +100,7 @@ func activateProgramInternal( } return nil, nil, err } - target := LocalTargetName() + target := LocalTarget() status_asm := C.stylus_compile( goSlice(wasm), u16(version), @@ -112,7 +112,7 @@ func activateProgramInternal( if status_asm != 0 { return nil, nil, fmt.Errorf("%w: %s", ErrProgramActivation, string(asm)) } - asmMap := map[string][]byte{ + asmMap := map[rawdb.Target][]byte{ rawdb.TargetWavm: module, target: asm, } @@ -130,7 +130,7 @@ func activateProgramInternal( } func getLocalAsm(statedb vm.StateDB, moduleHash common.Hash, addressForLogging common.Address, code []byte, codeHash common.Hash, pagelimit uint16, time uint64, debugMode bool, program Program) ([]byte, error) { - localTarget := LocalTargetName() + localTarget := LocalTarget() localAsm, err := statedb.TryGetActivatedAsm(localTarget, moduleHash) if err == nil && len(localAsm) > 0 { return localAsm, nil @@ -172,7 +172,7 @@ func getLocalAsm(statedb vm.StateDB, moduleHash common.Hash, addressForLogging c } asm, exists := asmMap[localTarget] if !exists { - var availableTargets []string + var availableTargets []rawdb.Target for target := range asmMap { availableTargets = append(availableTargets, target) } @@ -204,11 +204,11 @@ func callProgram( } if db, ok := db.(*state.StateDB); ok { - targetNames := []string{ + targets := []rawdb.Target{ rawdb.TargetWavm, - LocalTargetName(), + LocalTarget(), } - db.RecordProgram(targetNames, moduleHash) + db.RecordProgram(targets, moduleHash) } evmApi := newApi(interpreter, tracingInfo, scope, memoryModel) @@ -268,7 +268,7 @@ func evictProgram(db vm.StateDB, module common.Hash, version uint16, debug bool, tag := db.Database().WasmCacheTag() state.EvictWasmRust(module, version, tag, debug) if !forever { - db.RecordEvictWasm(state.EvictWasm{ModuleHash: module, Version: version, Tag: tag, Debug: debug}) + db.RecordEvictWasm(state.EvictWasm{Target: LocalTarget(), ModuleHash: module, Version: version, Tag: tag, Debug: debug}) } } } @@ -286,7 +286,7 @@ func ResizeWasmLruCache(size uint32) { C.stylus_cache_lru_resize(u32(size)) } -func LocalTargetName() string { +func LocalTarget() rawdb.Target { if runtime.GOOS == "linux" { switch runtime.GOARCH { case "arm64": @@ -301,7 +301,7 @@ func LocalTargetName() string { const DefaultTargetDescriptionArm = "arm64-linux-unknown+neon" const DefaultTargetDescriptionX86 = "x86_64-linux-unknown+sse4.2" -func SetTarget(name string, description string, native bool) error { +func SetTarget(name rawdb.Target, description string, native bool) error { output := &rustBytes{} status := userStatus(C.stylus_target_set( goSlice([]byte(name)), diff --git a/arbos/programs/testcompile.go b/arbos/programs/testcompile.go index 6369a475af..ab8ab37491 100644 --- a/arbos/programs/testcompile.go +++ b/arbos/programs/testcompile.go @@ -31,7 +31,7 @@ import ( func testCompileArch(store bool) error { - localTarget := LocalTargetName() + localTarget := LocalTarget() nativeArm64 := localTarget == rawdb.TargetArm64 nativeAmd64 := localTarget == rawdb.TargetAmd64 @@ -169,7 +169,7 @@ func testCompileArch(store bool) error { func testCompileLoad() error { filePath := "../../target/testdata/host.bin" - localTarget := LocalTargetName() + localTarget := LocalTarget() if localTarget == rawdb.TargetArm64 { filePath = "../../target/testdata/arm64.bin" } diff --git a/arbos/programs/wasmstorehelper.go b/arbos/programs/wasmstorehelper.go index 64eb350eb5..787836bb9e 100644 --- a/arbos/programs/wasmstorehelper.go +++ b/arbos/programs/wasmstorehelper.go @@ -44,7 +44,7 @@ func (p Programs) SaveActiveProgramToWasmStore(statedb *state.StateDB, codeHash } // If already in wasm store then return early - localAsm, err := statedb.TryGetActivatedAsm(LocalTargetName(), moduleHash) + localAsm, err := statedb.TryGetActivatedAsm(LocalTarget(), moduleHash) if err == nil && len(localAsm) > 0 { return nil } diff --git a/execution/gethexec/executionengine.go b/execution/gethexec/executionengine.go index 37c12183cf..7e580a3f25 100644 --- a/execution/gethexec/executionengine.go +++ b/execution/gethexec/executionengine.go @@ -155,8 +155,8 @@ func (s *ExecutionEngine) Initialize(rustCacheSize uint32, targetConfig *StylusT programs.ResizeWasmLruCache(rustCacheSize) } var effectiveStylusTarget string - targetName := programs.LocalTargetName() - switch targetName { + target := programs.LocalTarget() + switch target { case rawdb.TargetArm64: effectiveStylusTarget = targetConfig.Arm64 case rawdb.TargetAmd64: @@ -164,7 +164,7 @@ func (s *ExecutionEngine) Initialize(rustCacheSize uint32, targetConfig *StylusT case rawdb.TargetHost: effectiveStylusTarget = targetConfig.Host } - err := programs.SetTarget(targetName, effectiveStylusTarget, true) + err := programs.SetTarget(target, effectiveStylusTarget, true) if err != nil { return fmt.Errorf("Failed to set stylus target: %w", err) } diff --git a/go-ethereum b/go-ethereum index bbbcec2d39..6976d724e2 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit bbbcec2d395c673ce7d3ad7a52887a5446098453 +Subproject commit 6976d724e25c9b3ebe01f6304e8b5b6c519adce4 diff --git a/staker/block_validator.go b/staker/block_validator.go index 394f43dee1..6ec5efb711 100644 --- a/staker/block_validator.go +++ b/staker/block_validator.go @@ -485,7 +485,7 @@ func (v *BlockValidator) sendRecord(s *validationStatus) error { //nolint:gosec func (v *BlockValidator) writeToFile(validationEntry *validationEntry, moduleRoot common.Hash) error { - input, err := validationEntry.ToInput([]string{rawdb.TargetWavm}) + input, err := validationEntry.ToInput([]rawdb.Target{rawdb.TargetWavm}) if err != nil { return err } diff --git a/staker/challenge_manager.go b/staker/challenge_manager.go index 4cfdc46a0e..b1421d7e41 100644 --- a/staker/challenge_manager.go +++ b/staker/challenge_manager.go @@ -468,7 +468,7 @@ func (m *ChallengeManager) createExecutionBackend(ctx context.Context, step uint if err != nil { return fmt.Errorf("error creating validation entry for challenge %v msg %v for execution challenge: %w", m.challengeIndex, initialCount, err) } - input, err := entry.ToInput([]string{rawdb.TargetWavm}) + input, err := entry.ToInput([]rawdb.Target{rawdb.TargetWavm}) if err != nil { return fmt.Errorf("error getting validation entry input of challenge %v msg %v: %w", m.challengeIndex, initialCount, err) } diff --git a/staker/stateless_block_validator.go b/staker/stateless_block_validator.go index 69005527f9..4eb2a4c67d 100644 --- a/staker/stateless_block_validator.go +++ b/staker/stateless_block_validator.go @@ -13,6 +13,7 @@ import ( "github.com/offchainlabs/nitro/arbstate/daprovider" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" @@ -134,7 +135,7 @@ type validationEntry struct { DelayedMsg []byte } -func (e *validationEntry) ToInput(stylusArchs []string) (*validator.ValidationInput, error) { +func (e *validationEntry) ToInput(stylusArchs []rawdb.Target) (*validator.ValidationInput, error) { if e.Stage != Ready { return nil, errors.New("cannot create input from non-ready entry") } @@ -143,7 +144,7 @@ func (e *validationEntry) ToInput(stylusArchs []string) (*validator.ValidationIn HasDelayedMsg: e.HasDelayedMsg, DelayedMsgNr: e.DelayedMsgNr, Preimages: e.Preimages, - UserWasms: make(map[string]map[common.Hash][]byte, len(e.UserWasms)), + UserWasms: make(map[rawdb.Target]map[common.Hash][]byte, len(e.UserWasms)), BatchInfo: e.BatchInfo, DelayedMsg: e.DelayedMsg, StartState: e.Start, diff --git a/system_tests/validation_mock_test.go b/system_tests/validation_mock_test.go index 2c6321d009..88421e4c4b 100644 --- a/system_tests/validation_mock_test.go +++ b/system_tests/validation_mock_test.go @@ -8,6 +8,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/node" @@ -60,8 +61,8 @@ func (s *mockSpawner) WasmModuleRoots() ([]common.Hash, error) { return mockWasmModuleRoots, nil } -func (s *mockSpawner) StylusArchs() []string { - return []string{"mock"} +func (s *mockSpawner) StylusArchs() []rawdb.Target { + return []rawdb.Target{"mock"} } func (s *mockSpawner) Launch(entry *validator.ValidationInput, moduleRoot common.Hash) validator.ValidationRun { diff --git a/validator/client/redis/producer.go b/validator/client/redis/producer.go index c8ce25e304..b6b46481e9 100644 --- a/validator/client/redis/producer.go +++ b/validator/client/redis/producer.go @@ -37,7 +37,7 @@ var DefaultValidationClientConfig = ValidationClientConfig{ Name: "redis validation client", Room: 2, RedisURL: "", - StylusArchs: []string{rawdb.TargetWavm}, + StylusArchs: []string{string(rawdb.TargetWavm)}, ProducerConfig: pubsub.DefaultProducerConfig, CreateStreams: true, } @@ -47,7 +47,7 @@ var TestValidationClientConfig = ValidationClientConfig{ Room: 2, RedisURL: "", StreamPrefix: "test-", - StylusArchs: []string{rawdb.TargetWavm}, + StylusArchs: []string{string(rawdb.TargetWavm)}, ProducerConfig: pubsub.TestProducerConfig, CreateStreams: false, } @@ -153,8 +153,12 @@ func (c *ValidationClient) Name() string { return c.config.Name } -func (c *ValidationClient) StylusArchs() []string { - return c.config.StylusArchs +func (c *ValidationClient) StylusArchs() []rawdb.Target { + stylusArchs := make([]rawdb.Target, 0, len(c.config.StylusArchs)) + for _, arch := range c.config.StylusArchs { + stylusArchs = append(stylusArchs, rawdb.Target(arch)) + } + return stylusArchs } func (c *ValidationClient) Room() int { diff --git a/validator/client/validation_client.go b/validator/client/validation_client.go index 5073377616..d3f4f80a1a 100644 --- a/validator/client/validation_client.go +++ b/validator/client/validation_client.go @@ -31,7 +31,7 @@ type ValidationClient struct { stopwaiter.StopWaiter client *rpcclient.RpcClient name string - stylusArchs []string + stylusArchs []rawdb.Target room atomic.Int32 wasmModuleRoots []common.Hash } @@ -40,7 +40,7 @@ func NewValidationClient(config rpcclient.ClientConfigFetcher, stack *node.Node) return &ValidationClient{ client: rpcclient.NewRpcClient(config, stack), name: "not started", - stylusArchs: []string{"not started"}, + stylusArchs: []rawdb.Target{"not started"}, } } @@ -67,7 +67,7 @@ func (c *ValidationClient) Start(ctx context.Context) error { if len(name) == 0 { return errors.New("couldn't read name from server") } - var stylusArchs []string + var stylusArchs []rawdb.Target if err := c.client.CallContext(ctx, &stylusArchs, server_api.Namespace+"_stylusArchs"); err != nil { return err } @@ -75,7 +75,7 @@ func (c *ValidationClient) Start(ctx context.Context) error { return fmt.Errorf("could not read stylus archs from validation server") } for _, stylusArch := range stylusArchs { - if stylusArch != rawdb.TargetWavm && stylusArch != programs.LocalTargetName() && stylusArch != "mock" { + if stylusArch != rawdb.TargetWavm && stylusArch != programs.LocalTarget() && stylusArch != "mock" { return fmt.Errorf("unsupported stylus architecture: %v", stylusArch) } } @@ -111,11 +111,11 @@ func (c *ValidationClient) WasmModuleRoots() ([]common.Hash, error) { return nil, errors.New("not started") } -func (c *ValidationClient) StylusArchs() []string { +func (c *ValidationClient) StylusArchs() []rawdb.Target { if c.Started() { return c.stylusArchs } - return []string{"not started"} + return []rawdb.Target{"not started"} } func (c *ValidationClient) Stop() { diff --git a/validator/interface.go b/validator/interface.go index 80aa2c1fcc..81b40ae5cf 100644 --- a/validator/interface.go +++ b/validator/interface.go @@ -4,6 +4,7 @@ import ( "context" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/offchainlabs/nitro/util/containers" ) @@ -13,7 +14,7 @@ type ValidationSpawner interface { Start(context.Context) error Stop() Name() string - StylusArchs() []string + StylusArchs() []rawdb.Target Room() int } diff --git a/validator/server_api/json.go b/validator/server_api/json.go index 90746e4c57..dbe2bb1fee 100644 --- a/validator/server_api/json.go +++ b/validator/server_api/json.go @@ -11,6 +11,7 @@ import ( "os" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/offchainlabs/nitro/arbcompress" "github.com/offchainlabs/nitro/arbutil" @@ -63,7 +64,7 @@ type InputJSON struct { BatchInfo []BatchInfoJson DelayedMsgB64 string StartState validator.GoGlobalState - UserWasms map[string]map[common.Hash]string + UserWasms map[rawdb.Target]map[common.Hash]string DebugChain bool } @@ -95,14 +96,14 @@ func ValidationInputToJson(entry *validator.ValidationInput) *InputJSON { DelayedMsgB64: base64.StdEncoding.EncodeToString(entry.DelayedMsg), StartState: entry.StartState, PreimagesB64: jsonPreimagesMap, - UserWasms: make(map[string]map[common.Hash]string), + UserWasms: make(map[rawdb.Target]map[common.Hash]string), DebugChain: entry.DebugChain, } for _, binfo := range entry.BatchInfo { encData := base64.StdEncoding.EncodeToString(binfo.Data) res.BatchInfo = append(res.BatchInfo, BatchInfoJson{Number: binfo.Number, DataB64: encData}) } - for arch, wasms := range entry.UserWasms { + for target, wasms := range entry.UserWasms { archWasms := make(map[common.Hash]string) for moduleHash, data := range wasms { compressed, err := arbcompress.CompressLevel(data, 1) @@ -111,7 +112,7 @@ func ValidationInputToJson(entry *validator.ValidationInput) *InputJSON { } archWasms[moduleHash] = base64.StdEncoding.EncodeToString(compressed) } - res.UserWasms[arch] = archWasms + res.UserWasms[target] = archWasms } return res } @@ -127,7 +128,7 @@ func ValidationInputFromJson(entry *InputJSON) (*validator.ValidationInput, erro DelayedMsgNr: entry.DelayedMsgNr, StartState: entry.StartState, Preimages: preimages, - UserWasms: make(map[string]map[common.Hash][]byte), + UserWasms: make(map[rawdb.Target]map[common.Hash][]byte), DebugChain: entry.DebugChain, } delayed, err := base64.StdEncoding.DecodeString(entry.DelayedMsgB64) @@ -146,7 +147,7 @@ func ValidationInputFromJson(entry *InputJSON) (*validator.ValidationInput, erro } valInput.BatchInfo = append(valInput.BatchInfo, decInfo) } - for arch, wasms := range entry.UserWasms { + for target, wasms := range entry.UserWasms { archWasms := make(map[common.Hash][]byte) for moduleHash, encoded := range wasms { decoded, err := base64.StdEncoding.DecodeString(encoded) @@ -171,7 +172,7 @@ func ValidationInputFromJson(entry *InputJSON) (*validator.ValidationInput, erro } archWasms[moduleHash] = uncompressed } - valInput.UserWasms[arch] = archWasms + valInput.UserWasms[target] = archWasms } return valInput, nil } diff --git a/validator/server_arb/validator_spawner.go b/validator/server_arb/validator_spawner.go index 88019516fb..844a988d28 100644 --- a/validator/server_arb/validator_spawner.go +++ b/validator/server_arb/validator_spawner.go @@ -89,8 +89,8 @@ func (s *ArbitratorSpawner) WasmModuleRoots() ([]common.Hash, error) { return s.locator.ModuleRoots(), nil } -func (s *ArbitratorSpawner) StylusArchs() []string { - return []string{rawdb.TargetWavm} +func (s *ArbitratorSpawner) StylusArchs() []rawdb.Target { + return []rawdb.Target{rawdb.TargetWavm} } func (s *ArbitratorSpawner) Name() string { diff --git a/validator/server_jit/jit_machine.go b/validator/server_jit/jit_machine.go index 9c66951d77..f442001e73 100644 --- a/validator/server_jit/jit_machine.go +++ b/validator/server_jit/jit_machine.go @@ -212,7 +212,7 @@ func (machine *JitMachine) prove( } } - localTarget := programs.LocalTargetName() + localTarget := programs.LocalTarget() userWasms := entry.UserWasms[localTarget] // if there are user wasms, but only for wrong architecture - error diff --git a/validator/server_jit/spawner.go b/validator/server_jit/spawner.go index 2f1f9b44f7..4ac580018f 100644 --- a/validator/server_jit/spawner.go +++ b/validator/server_jit/spawner.go @@ -9,6 +9,7 @@ import ( flag "github.com/spf13/pflag" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/offchainlabs/nitro/arbos/programs" "github.com/offchainlabs/nitro/util/stopwaiter" @@ -72,8 +73,8 @@ func (v *JitSpawner) WasmModuleRoots() ([]common.Hash, error) { return v.locator.ModuleRoots(), nil } -func (v *JitSpawner) StylusArchs() []string { - return []string{programs.LocalTargetName()} +func (v *JitSpawner) StylusArchs() []rawdb.Target { + return []rawdb.Target{programs.LocalTarget()} } func (v *JitSpawner) execute( diff --git a/validator/validation_entry.go b/validator/validation_entry.go index 133a67a8a8..2c357659ad 100644 --- a/validator/validation_entry.go +++ b/validator/validation_entry.go @@ -2,6 +2,7 @@ package validator import ( "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/offchainlabs/nitro/arbutil" ) @@ -16,7 +17,7 @@ type ValidationInput struct { HasDelayedMsg bool DelayedMsgNr uint64 Preimages map[arbutil.PreimageType]map[common.Hash][]byte - UserWasms map[string]map[common.Hash][]byte + UserWasms map[rawdb.Target]map[common.Hash][]byte BatchInfo []BatchInfo DelayedMsg []byte StartState GoGlobalState diff --git a/validator/valnode/validation_api.go b/validator/valnode/validation_api.go index 6245ffc5e3..a79ac7fa55 100644 --- a/validator/valnode/validation_api.go +++ b/validator/valnode/validation_api.go @@ -12,6 +12,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/offchainlabs/nitro/util/stopwaiter" "github.com/offchainlabs/nitro/validator" @@ -44,7 +45,7 @@ func (a *ValidationServerAPI) WasmModuleRoots() ([]common.Hash, error) { return a.spawner.WasmModuleRoots() } -func (a *ValidationServerAPI) StylusArchs() ([]string, error) { +func (a *ValidationServerAPI) StylusArchs() ([]rawdb.Target, error) { return a.spawner.StylusArchs(), nil } From 2c86f2766b6d45631578f9eba10b2172a23ed12c Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Mon, 12 Aug 2024 15:54:48 +0200 Subject: [PATCH 49/80] use rawdb.TargetFromString / rawdb.Target.ToString for encoding/decoding rawdb.Target, validate StylusArchs config --- go-ethereum | 2 +- staker/block_validator.go | 3 +++ validator/client/redis/producer.go | 17 ++++++++++++++--- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/go-ethereum b/go-ethereum index 6976d724e2..c35949391e 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 6976d724e25c9b3ebe01f6304e8b5b6c519adce4 +Subproject commit c35949391e40207e1a0fbf33d4c02a0e1e6b9695 diff --git a/staker/block_validator.go b/staker/block_validator.go index 6ec5efb711..3674e365c6 100644 --- a/staker/block_validator.go +++ b/staker/block_validator.go @@ -126,6 +126,9 @@ func (c *BlockValidatorConfig) Validate() error { } c.memoryFreeLimit = limit } + if err := c.RedisValidationClientConfig.Validate(); err != nil { + return fmt.Errorf("failed to validate redis validation client config: %w", err) + } streamsEnabled := c.RedisValidationClientConfig.Enabled() if len(c.ValidationServerConfigs) == 0 { c.ValidationServerConfigs = []rpcclient.ClientConfig{c.ValidationServer} diff --git a/validator/client/redis/producer.go b/validator/client/redis/producer.go index b6b46481e9..f6d24e03f1 100644 --- a/validator/client/redis/producer.go +++ b/validator/client/redis/producer.go @@ -33,11 +33,20 @@ func (c ValidationClientConfig) Enabled() bool { return c.RedisURL != "" } +func (c ValidationClientConfig) Validate() error { + for _, arch := range c.StylusArchs { + if _, err := rawdb.TargetFromString(arch); err != nil { + return fmt.Errorf("Unsupported stylus arch: %v", arch) + } + } + return nil +} + var DefaultValidationClientConfig = ValidationClientConfig{ Name: "redis validation client", Room: 2, RedisURL: "", - StylusArchs: []string{string(rawdb.TargetWavm)}, + StylusArchs: []string{rawdb.TargetWavm.ToString()}, ProducerConfig: pubsub.DefaultProducerConfig, CreateStreams: true, } @@ -47,7 +56,7 @@ var TestValidationClientConfig = ValidationClientConfig{ Room: 2, RedisURL: "", StreamPrefix: "test-", - StylusArchs: []string{string(rawdb.TargetWavm)}, + StylusArchs: []string{rawdb.TargetWavm.ToString()}, ProducerConfig: pubsub.TestProducerConfig, CreateStreams: false, } @@ -156,7 +165,9 @@ func (c *ValidationClient) Name() string { func (c *ValidationClient) StylusArchs() []rawdb.Target { stylusArchs := make([]rawdb.Target, 0, len(c.config.StylusArchs)) for _, arch := range c.config.StylusArchs { - stylusArchs = append(stylusArchs, rawdb.Target(arch)) + // we are ignoring error here, as StylusArchs should have been validated in Validate + target, _ := rawdb.TargetFromString(arch) + stylusArchs = append(stylusArchs, target) } return stylusArchs } From 048ae8d95b4ebe2692170c3070756be2022f762b Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Mon, 12 Aug 2024 16:18:04 +0200 Subject: [PATCH 50/80] change stylusArch validation --- go-ethereum | 2 +- validator/client/redis/producer.go | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/go-ethereum b/go-ethereum index c35949391e..a75f682edb 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit c35949391e40207e1a0fbf33d4c02a0e1e6b9695 +Subproject commit a75f682edb94c22ab62beb200a6520c20c808fee diff --git a/validator/client/redis/producer.go b/validator/client/redis/producer.go index f6d24e03f1..14b1971bc3 100644 --- a/validator/client/redis/producer.go +++ b/validator/client/redis/producer.go @@ -35,8 +35,8 @@ func (c ValidationClientConfig) Enabled() bool { func (c ValidationClientConfig) Validate() error { for _, arch := range c.StylusArchs { - if _, err := rawdb.TargetFromString(arch); err != nil { - return fmt.Errorf("Unsupported stylus arch: %v", arch) + if !rawdb.TargetFromString(arch).IsValid() { + return fmt.Errorf("Invalid stylus arch: %v", arch) } } return nil @@ -165,8 +165,7 @@ func (c *ValidationClient) Name() string { func (c *ValidationClient) StylusArchs() []rawdb.Target { stylusArchs := make([]rawdb.Target, 0, len(c.config.StylusArchs)) for _, arch := range c.config.StylusArchs { - // we are ignoring error here, as StylusArchs should have been validated in Validate - target, _ := rawdb.TargetFromString(arch) + target := rawdb.TargetFromString(arch) stylusArchs = append(stylusArchs, target) } return stylusArchs From 883d034f4ac7d496c7f21179a8d74da0d92f43b9 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Mon, 12 Aug 2024 16:22:43 +0200 Subject: [PATCH 51/80] use rawdb.Target.ToString in programs.SetTarget --- arbos/programs/native.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbos/programs/native.go b/arbos/programs/native.go index 38b00a5fcf..01be7a18f5 100644 --- a/arbos/programs/native.go +++ b/arbos/programs/native.go @@ -304,7 +304,7 @@ const DefaultTargetDescriptionX86 = "x86_64-linux-unknown+sse4.2" func SetTarget(name rawdb.Target, description string, native bool) error { output := &rustBytes{} status := userStatus(C.stylus_target_set( - goSlice([]byte(name)), + goSlice([]byte(name.ToString())), goSlice([]byte(description)), output, cbool(native), From 3fdc02c952a0a46c834fb2c8b14c068cd697f202 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Mon, 12 Aug 2024 16:47:13 +0200 Subject: [PATCH 52/80] update geth pin, remove rawdb.TargetFromString and rawdb.Target.ToString --- arbos/programs/native.go | 2 +- go-ethereum | 2 +- validator/client/redis/producer.go | 9 ++++----- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/arbos/programs/native.go b/arbos/programs/native.go index 01be7a18f5..38b00a5fcf 100644 --- a/arbos/programs/native.go +++ b/arbos/programs/native.go @@ -304,7 +304,7 @@ const DefaultTargetDescriptionX86 = "x86_64-linux-unknown+sse4.2" func SetTarget(name rawdb.Target, description string, native bool) error { output := &rustBytes{} status := userStatus(C.stylus_target_set( - goSlice([]byte(name.ToString())), + goSlice([]byte(name)), goSlice([]byte(description)), output, cbool(native), diff --git a/go-ethereum b/go-ethereum index a75f682edb..01e2210638 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit a75f682edb94c22ab62beb200a6520c20c808fee +Subproject commit 01e2210638c488414577850be537dbc4238e0011 diff --git a/validator/client/redis/producer.go b/validator/client/redis/producer.go index 14b1971bc3..f98c246d0e 100644 --- a/validator/client/redis/producer.go +++ b/validator/client/redis/producer.go @@ -35,7 +35,7 @@ func (c ValidationClientConfig) Enabled() bool { func (c ValidationClientConfig) Validate() error { for _, arch := range c.StylusArchs { - if !rawdb.TargetFromString(arch).IsValid() { + if !rawdb.Target(arch).IsValid() { return fmt.Errorf("Invalid stylus arch: %v", arch) } } @@ -46,7 +46,7 @@ var DefaultValidationClientConfig = ValidationClientConfig{ Name: "redis validation client", Room: 2, RedisURL: "", - StylusArchs: []string{rawdb.TargetWavm.ToString()}, + StylusArchs: []string{string(rawdb.TargetWavm)}, ProducerConfig: pubsub.DefaultProducerConfig, CreateStreams: true, } @@ -56,7 +56,7 @@ var TestValidationClientConfig = ValidationClientConfig{ Room: 2, RedisURL: "", StreamPrefix: "test-", - StylusArchs: []string{rawdb.TargetWavm.ToString()}, + StylusArchs: []string{string(rawdb.TargetWavm)}, ProducerConfig: pubsub.TestProducerConfig, CreateStreams: false, } @@ -165,8 +165,7 @@ func (c *ValidationClient) Name() string { func (c *ValidationClient) StylusArchs() []rawdb.Target { stylusArchs := make([]rawdb.Target, 0, len(c.config.StylusArchs)) for _, arch := range c.config.StylusArchs { - target := rawdb.TargetFromString(arch) - stylusArchs = append(stylusArchs, target) + stylusArchs = append(stylusArchs, rawdb.Target(arch)) } return stylusArchs } From c3502b28a29bef011571a0397cdab9e706114c79 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Mon, 12 Aug 2024 17:05:46 +0200 Subject: [PATCH 53/80] handle error returned from rawdb.ReadWasmSchemaVersion --- cmd/nitro/init.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index 9ee5fe918b..7995b4ee44 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -416,7 +416,14 @@ func databaseIsEmpty(db ethdb.Database) bool { // otherwise persists current version func validateOrWriteWasmStoreSchemaVersion(db ethdb.Database) error { if !databaseIsEmpty(db) { - version := rawdb.ReadWasmSchemaVersion(db) + version, err := rawdb.ReadWasmSchemaVersion(db) + if err != nil { + if isLeveldbNotExistError(err) || isPebbleNotExistError(err) { + version = []byte{0} + } else { + return fmt.Errorf("Failed to retrieve wasm schema version: %w", err) + } + } if len(version) != 1 || version[0] > rawdb.WasmSchemaVersion { return fmt.Errorf("Unsupported wasm database schema version, current version: %v, read from wasm database: %v", rawdb.WasmSchemaVersion, version) } From 49cc293a8bb8a116c983d101598ce7384526b0dd Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Mon, 12 Aug 2024 17:17:39 +0200 Subject: [PATCH 54/80] update geth pin --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index 01e2210638..5ed6b5f034 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 01e2210638c488414577850be537dbc4238e0011 +Subproject commit 5ed6b5f0340157325ce18ee55191f31c8cfcbc8b From f84bf13a1b8e9bf38be4a1b1b59e0b039a1e9f23 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Mon, 12 Aug 2024 22:39:06 +0200 Subject: [PATCH 55/80] remove old wasm store entires if version 0 is detected --- cmd/nitro/init.go | 55 ++++++++++++++++++++-- cmd/nitro/init_test.go | 101 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 150 insertions(+), 6 deletions(-) diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index 7995b4ee44..49e4ab28c8 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -412,9 +412,47 @@ func databaseIsEmpty(db ethdb.Database) bool { return !it.Next() } +// removes all entries with keys prefixed with prefixes and of length used in initial version of wasm store schema +func purgeVersion0WasmStoreEntries(db ethdb.Database) error { + prefixes, keyLength := rawdb.DeprecatedKeysV0() + batch := db.NewBatch() + for _, prefix := range prefixes { + it := db.NewIterator(prefix, nil) + defer it.Release() + for it.Next() { + key := it.Key() + if len(key) != keyLength { + log.Warn("Found key with deprecated prefix but not matching length, skipping removal.", "key", key) + continue + } + if err := batch.Delete(key); err != nil { + return fmt.Errorf("Failed to remove key %v : %w", key, err) + } + + // Recreate the iterator after every batch commit in order + // to allow the underlying compactor to delete the entries. + if batch.ValueSize() >= ethdb.IdealBatchSize { + if err := batch.Write(); err != nil { + return fmt.Errorf("Failed to write batch: %w", err) + } + batch.Reset() + it.Release() + it = db.NewIterator(prefix, key) + } + } + } + if batch.ValueSize() > 0 { + if err := batch.Write(); err != nil { + return fmt.Errorf("Failed to write batch: %w", err) + } + batch.Reset() + } + return nil +} + // if db is not empty, validates if wasm database schema version matches current version // otherwise persists current version -func validateOrWriteWasmStoreSchemaVersion(db ethdb.Database) error { +func validateOrUpgradeWasmStoreSchemaVersion(db ethdb.Database) error { if !databaseIsEmpty(db) { version, err := rawdb.ReadWasmSchemaVersion(db) if err != nil { @@ -427,9 +465,16 @@ func validateOrWriteWasmStoreSchemaVersion(db ethdb.Database) error { if len(version) != 1 || version[0] > rawdb.WasmSchemaVersion { return fmt.Errorf("Unsupported wasm database schema version, current version: %v, read from wasm database: %v", rawdb.WasmSchemaVersion, version) } - } else { - rawdb.WriteWasmSchemaVersion(db) + // special step for upgrading from version 0 - remove all entries added in version 0 + if version[0] == 0 { + log.Warn("Detected wasm store schema version 0 - removing all old wasm store entries") + if err := purgeVersion0WasmStoreEntries(db); err != nil { + return fmt.Errorf("Failed to purge wasm store version 0 entries: %w", err) + } + log.Info("Wasm store schama version 0 entries successfully removed.") + } } + rawdb.WriteWasmSchemaVersion(db) return nil } @@ -449,7 +494,7 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo if err != nil { return nil, nil, err } - if err := validateOrWriteWasmStoreSchemaVersion(wasmDb); err != nil { + if err := validateOrUpgradeWasmStoreSchemaVersion(wasmDb); err != nil { return nil, nil, err } chainDb := rawdb.WrapDatabaseWithWasm(chainData, wasmDb, 1) @@ -566,7 +611,7 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo if err != nil { return nil, nil, err } - if err := validateOrWriteWasmStoreSchemaVersion(wasmDb); err != nil { + if err := validateOrUpgradeWasmStoreSchemaVersion(wasmDb); err != nil { return nil, nil, err } chainDb := rawdb.WrapDatabaseWithWasm(chainData, wasmDb, 1) diff --git a/cmd/nitro/init_test.go b/cmd/nitro/init_test.go index 0797ac9b46..69c99d387a 100644 --- a/cmd/nitro/init_test.go +++ b/cmd/nitro/init_test.go @@ -22,6 +22,7 @@ import ( "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/node" "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/cmd/chaininfo" @@ -292,7 +293,7 @@ func testIsNotExistError(t *testing.T, dbEngine string, isNotExist func(error) b stackConf.DBEngine = dbEngine stack, err := node.New(&stackConf) if err != nil { - t.Fatalf("Failed to created test stack: %v", err) + t.Fatalf("Failed to create test stack: %v", err) } defer stack.Close() readonly := true @@ -436,3 +437,101 @@ func TestOpenInitializeChainDbIncompatibleStateScheme(t *testing.T) { t.Fatalf("Failed to detect incompatible state scheme") } } + +func writeKeys(t *testing.T, db ethdb.Database, keys [][]byte) { + t.Helper() + batch := db.NewBatch() + for _, key := range keys { + err := batch.Put(key, []byte("some data")) + if err != nil { + t.Fatal("Internal test error - failed to insert key:", err) + } + } + err := batch.Write() + if err != nil { + t.Fatal("Internal test error - failed to write batch:", err) + } + batch.Reset() +} + +func checkKeys(t *testing.T, db ethdb.Database, keys [][]byte, shouldExist bool) { + t.Helper() + for _, key := range keys { + has, err := db.Has(key) + if err != nil { + t.Fatal("Failed to check key existence, key: ", key) + } + if shouldExist && !has { + t.Fatal("Key not found:", key) + } + if !shouldExist && has { + t.Fatal("Key found:", key, "k3:", string(key[:3]), "len", len(key)) + } + } +} + +func TestPurgeVersion0WasmStoreEntries(t *testing.T) { + stackConf := node.DefaultConfig + stackConf.DataDir = t.TempDir() + stack, err := node.New(&stackConf) + if err != nil { + t.Fatalf("Failed to create test stack: %v", err) + } + defer stack.Close() + db, err := stack.OpenDatabaseWithExtraOptions("wasm", NodeConfigDefault.Execution.Caching.DatabaseCache, NodeConfigDefault.Persistent.Handles, "wasm/", false, nil) + if err != nil { + t.Fatalf("Failed to open test db: %v", err) + } + var version0Keys [][]byte + for i := 0; i < 20; i++ { + version0Keys = append(version0Keys, + append([]byte{0x00, 'w', 'a'}, testhelpers.RandomSlice(32)...)) + version0Keys = append(version0Keys, + append([]byte{0x00, 'w', 'm'}, testhelpers.RandomSlice(32)...)) + } + var collidedKeys [][]byte + for i := 0; i < 5; i++ { + collidedKeys = append(collidedKeys, + append([]byte{0x00, 'w', 'a'}, testhelpers.RandomSlice(31)...)) + collidedKeys = append(collidedKeys, + append([]byte{0x00, 'w', 'm'}, testhelpers.RandomSlice(31)...)) + collidedKeys = append(collidedKeys, + append([]byte{0x00, 'w', 'a'}, testhelpers.RandomSlice(33)...)) + collidedKeys = append(collidedKeys, + append([]byte{0x00, 'w', 'm'}, testhelpers.RandomSlice(33)...)) + } + var otherKeys [][]byte + for i := 0x00; i <= 0xff; i++ { + if byte(i) == 'a' || byte(i) == 'm' { + continue + } + otherKeys = append(otherKeys, + append([]byte{0x00, 'w', byte(i)}, testhelpers.RandomSlice(32)...)) + otherKeys = append(otherKeys, + append([]byte{0x00, 'w', byte(i)}, testhelpers.RandomSlice(32)...)) + } + for i := 0; i < 10; i++ { + var randomSlice []byte + var j int + for j = 0; j < 10; j++ { + randomSlice = testhelpers.RandomSlice(testhelpers.RandomUint64(1, 40)) + if len(randomSlice) >= 3 && !bytes.Equal(randomSlice[:3], []byte{0x00, 'w', 'm'}) && !bytes.Equal(randomSlice[:3], []byte{0x00, 'w', 'm'}) { + break + } + } + if j == 10 { + t.Fatal("Internal test error - failed to generate random key") + } + otherKeys = append(otherKeys, randomSlice) + } + writeKeys(t, db, version0Keys) + writeKeys(t, db, collidedKeys) + writeKeys(t, db, otherKeys) + checkKeys(t, db, version0Keys, true) + checkKeys(t, db, collidedKeys, true) + checkKeys(t, db, otherKeys, true) + purgeVersion0WasmStoreEntries(db) + checkKeys(t, db, version0Keys, false) + checkKeys(t, db, collidedKeys, true) + checkKeys(t, db, otherKeys, true) +} From 02f1e868ba16e7e3eced8030f743540959e52803 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Mon, 12 Aug 2024 22:50:59 +0200 Subject: [PATCH 56/80] add error check in TestPurgeVersion0WasmStoreEntries --- cmd/nitro/init_test.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd/nitro/init_test.go b/cmd/nitro/init_test.go index 69c99d387a..7c95bb765b 100644 --- a/cmd/nitro/init_test.go +++ b/cmd/nitro/init_test.go @@ -530,7 +530,10 @@ func TestPurgeVersion0WasmStoreEntries(t *testing.T) { checkKeys(t, db, version0Keys, true) checkKeys(t, db, collidedKeys, true) checkKeys(t, db, otherKeys, true) - purgeVersion0WasmStoreEntries(db) + err = purgeVersion0WasmStoreEntries(db) + if err != nil { + t.Fatal("Failed to purge version 0 keys, err:", err) + } checkKeys(t, db, version0Keys, false) checkKeys(t, db, collidedKeys, true) checkKeys(t, db, otherKeys, true) From 56544dca1cf625157802c7dff22db8239d2674de Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Mon, 12 Aug 2024 23:00:35 +0200 Subject: [PATCH 57/80] update geth pin --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index 5ed6b5f034..d05523574d 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit 5ed6b5f0340157325ce18ee55191f31c8cfcbc8b +Subproject commit d05523574d39a6950d73081c0f90db0dac5df60c From 4a6ef04a676d59cda716633c8baa132b81ed04d9 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 15 Aug 2024 22:03:27 +0200 Subject: [PATCH 58/80] use dbutil.IsErrNotFound when handling ReadWasmSchemaVersion error --- cmd/nitro/init.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index 49e4ab28c8..8dbb4fd2a5 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -46,6 +46,7 @@ import ( "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/statetransfer" "github.com/offchainlabs/nitro/util/arbmath" + "github.com/offchainlabs/nitro/util/dbutil" ) var notFoundError = errors.New("file not found") @@ -456,7 +457,7 @@ func validateOrUpgradeWasmStoreSchemaVersion(db ethdb.Database) error { if !databaseIsEmpty(db) { version, err := rawdb.ReadWasmSchemaVersion(db) if err != nil { - if isLeveldbNotExistError(err) || isPebbleNotExistError(err) { + if dbutil.IsErrNotFound(err) { version = []byte{0} } else { return fmt.Errorf("Failed to retrieve wasm schema version: %w", err) From 4039007ef5975780ee308f4c698c18c3b3e98e76 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 15 Aug 2024 22:13:46 +0200 Subject: [PATCH 59/80] release iterator before writing batch in purgeVersion0WasmStoreEntries --- cmd/nitro/init.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index 8dbb4fd2a5..5a99bf66b9 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -433,11 +433,11 @@ func purgeVersion0WasmStoreEntries(db ethdb.Database) error { // Recreate the iterator after every batch commit in order // to allow the underlying compactor to delete the entries. if batch.ValueSize() >= ethdb.IdealBatchSize { + it.Release() if err := batch.Write(); err != nil { return fmt.Errorf("Failed to write batch: %w", err) } batch.Reset() - it.Release() it = db.NewIterator(prefix, key) } } From 1ec6cbdcfc91513bec5edfac51d96b8f5a404722 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 15 Aug 2024 22:36:33 +0200 Subject: [PATCH 60/80] check both wavm and local asms existence when rebuilding wasm store --- arbos/programs/wasmstorehelper.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arbos/programs/wasmstorehelper.go b/arbos/programs/wasmstorehelper.go index 787836bb9e..0910cee341 100644 --- a/arbos/programs/wasmstorehelper.go +++ b/arbos/programs/wasmstorehelper.go @@ -44,8 +44,8 @@ func (p Programs) SaveActiveProgramToWasmStore(statedb *state.StateDB, codeHash } // If already in wasm store then return early - localAsm, err := statedb.TryGetActivatedAsm(LocalTarget(), moduleHash) - if err == nil && len(localAsm) > 0 { + _, err = statedb.TryGetActivatedAsmMap([]rawdb.Target{rawdb.TargetWavm, LocalTarget()}, moduleHash) + if err == nil { return nil } From ac25502156d2e4174d0ba7b5022e6dd23ad57054 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 15 Aug 2024 22:47:57 +0200 Subject: [PATCH 61/80] log only once when key with deprecated prefix with unexpected length is found --- cmd/nitro/init.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index 5a99bf66b9..0dcd83ab27 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -417,13 +417,17 @@ func databaseIsEmpty(db ethdb.Database) bool { func purgeVersion0WasmStoreEntries(db ethdb.Database) error { prefixes, keyLength := rawdb.DeprecatedKeysV0() batch := db.NewBatch() + notMatchingLengthKeyLogged := false for _, prefix := range prefixes { it := db.NewIterator(prefix, nil) defer it.Release() for it.Next() { key := it.Key() if len(key) != keyLength { - log.Warn("Found key with deprecated prefix but not matching length, skipping removal.", "key", key) + if !notMatchingLengthKeyLogged { + log.Warn("Found key with deprecated prefix but not matching length, skipping removal. (this warning is logged only once)", "key", key) + notMatchingLengthKeyLogged = true + } continue } if err := batch.Delete(key); err != nil { From 5a30b97674d15db5fbdee8530f7343aa6bcb7e77 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 15 Aug 2024 22:48:09 +0200 Subject: [PATCH 62/80] Revert "release iterator before writing batch in purgeVersion0WasmStoreEntries" This reverts commit 4039007ef5975780ee308f4c698c18c3b3e98e76. --- cmd/nitro/init.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index 0dcd83ab27..0ec768d4c7 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -437,11 +437,11 @@ func purgeVersion0WasmStoreEntries(db ethdb.Database) error { // Recreate the iterator after every batch commit in order // to allow the underlying compactor to delete the entries. if batch.ValueSize() >= ethdb.IdealBatchSize { - it.Release() if err := batch.Write(); err != nil { return fmt.Errorf("Failed to write batch: %w", err) } batch.Reset() + it.Release() it = db.NewIterator(prefix, key) } } From 1245d4a8361903a32179d157c3d5abd9eaf8eaff Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 15 Aug 2024 22:51:54 +0200 Subject: [PATCH 63/80] test if target name is utf8 in stylus_compile --- arbitrator/stylus/src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arbitrator/stylus/src/lib.rs b/arbitrator/stylus/src/lib.rs index 2929821433..a48ce4f064 100644 --- a/arbitrator/stylus/src/lib.rs +++ b/arbitrator/stylus/src/lib.rs @@ -183,7 +183,10 @@ pub unsafe extern "C" fn stylus_compile( ) -> UserOutcomeKind { let wasm = wasm.slice(); let output = &mut *output; - let name = String::from_utf8_unchecked(name.slice().to_vec()); + 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), From f0c1cf8cec796c3873bafab56544dafb5500f17c Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 15 Aug 2024 23:14:42 +0200 Subject: [PATCH 64/80] use InitCache::target() when deserializing in exec_wasm --- arbitrator/jit/src/stylus_backend.rs | 4 ++-- arbitrator/stylus/src/lib.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arbitrator/jit/src/stylus_backend.rs b/arbitrator/jit/src/stylus_backend.rs index cb0440a257..091edf48cf 100644 --- a/arbitrator/jit/src/stylus_backend.rs +++ b/arbitrator/jit/src/stylus_backend.rs @@ -23,7 +23,7 @@ use std::{ }, thread::JoinHandle, }; -use stylus::{native::NativeInstance, run::RunProgram}; +use stylus::{native::NativeInstance, run::RunProgram, cache::InitCache}; use wasmer::Target; struct MessageToCothread { @@ -150,7 +150,7 @@ pub fn exec_wasm( compile.clone(), evm_api, evm_data, - Target::default(), + InitCache::target(), ) }?; diff --git a/arbitrator/stylus/src/lib.rs b/arbitrator/stylus/src/lib.rs index a48ce4f064..a10f99f05d 100644 --- a/arbitrator/stylus/src/lib.rs +++ b/arbitrator/stylus/src/lib.rs @@ -23,12 +23,12 @@ use target_cache::{target_cache_get, target_cache_set}; pub use brotli; pub use prover; +pub mod cache; pub mod env; pub mod host; pub mod native; pub mod run; -mod cache; mod evm_api; mod target_cache; mod util; From eb17f05634b8399a0387327c07e36be976da6762 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Thu, 15 Aug 2024 23:37:51 +0200 Subject: [PATCH 65/80] don't error pre-stylus in ValidationClient.Start --- validator/client/validation_client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/validator/client/validation_client.go b/validator/client/validation_client.go index 5705155474..61cda605c4 100644 --- a/validator/client/validation_client.go +++ b/validator/client/validation_client.go @@ -81,7 +81,7 @@ func (c *ValidationClient) Start(ctx context.Context) error { return fmt.Errorf("could not read stylus archs from validation server") } for _, stylusArch := range stylusArchs { - if stylusArch != rawdb.TargetWavm && stylusArch != programs.LocalTarget() && stylusArch != "mock" { + if stylusArch != rawdb.TargetWavm && stylusArch != programs.LocalTarget() && stylusArch != "pre-stylus" && stylusArch != "mock" { return fmt.Errorf("unsupported stylus architecture: %v", stylusArch) } } From 30060be8e8f7f628d0332346ffc87cb2732a1991 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 16 Aug 2024 00:40:12 +0200 Subject: [PATCH 66/80] return empty stylusArchs for clients that does not support stylus --- staker/stateless_block_validator.go | 3 +++ validator/client/validation_client.go | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/staker/stateless_block_validator.go b/staker/stateless_block_validator.go index d6406c6b12..d5eeb8eb69 100644 --- a/staker/stateless_block_validator.go +++ b/staker/stateless_block_validator.go @@ -149,6 +149,9 @@ func (e *validationEntry) ToInput(stylusArchs []rawdb.Target) (*validator.Valida StartState: e.Start, DebugChain: e.ChainConfig.DebugMode(), } + if len(stylusArchs) == 0 && len(e.UserWasms) > 0 { + return nil, fmt.Errorf("stylus support is required") + } for _, stylusArch := range stylusArchs { res.UserWasms[stylusArch] = make(map[common.Hash][]byte) } diff --git a/validator/client/validation_client.go b/validator/client/validation_client.go index 61cda605c4..6301c449a3 100644 --- a/validator/client/validation_client.go +++ b/validator/client/validation_client.go @@ -75,13 +75,13 @@ func (c *ValidationClient) Start(ctx context.Context) error { if !ok || rpcError.ErrorCode() != -32601 { return fmt.Errorf("could not read stylus arch from server: %w", err) } - stylusArchs = []rawdb.Target{"pre-stylus"} // validation does not support stylus - } - if len(stylusArchs) == 0 { + // validation does not support stylus, leaving stylusArchs empty + } else if len(stylusArchs) == 0 { return fmt.Errorf("could not read stylus archs from validation server") } + for _, stylusArch := range stylusArchs { - if stylusArch != rawdb.TargetWavm && stylusArch != programs.LocalTarget() && stylusArch != "pre-stylus" && stylusArch != "mock" { + if stylusArch != rawdb.TargetWavm && stylusArch != programs.LocalTarget() && stylusArch != "mock" { return fmt.Errorf("unsupported stylus architecture: %v", stylusArch) } } From e67ae222385d451dc1a62f2900073f928a06f853 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 16 Aug 2024 00:40:34 +0200 Subject: [PATCH 67/80] Revert "use InitCache::target() when deserializing in exec_wasm" This reverts commit f0c1cf8cec796c3873bafab56544dafb5500f17c. --- arbitrator/jit/src/stylus_backend.rs | 4 ++-- arbitrator/stylus/src/lib.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arbitrator/jit/src/stylus_backend.rs b/arbitrator/jit/src/stylus_backend.rs index 091edf48cf..cb0440a257 100644 --- a/arbitrator/jit/src/stylus_backend.rs +++ b/arbitrator/jit/src/stylus_backend.rs @@ -23,7 +23,7 @@ use std::{ }, thread::JoinHandle, }; -use stylus::{native::NativeInstance, run::RunProgram, cache::InitCache}; +use stylus::{native::NativeInstance, run::RunProgram}; use wasmer::Target; struct MessageToCothread { @@ -150,7 +150,7 @@ pub fn exec_wasm( compile.clone(), evm_api, evm_data, - InitCache::target(), + Target::default(), ) }?; diff --git a/arbitrator/stylus/src/lib.rs b/arbitrator/stylus/src/lib.rs index a10f99f05d..a48ce4f064 100644 --- a/arbitrator/stylus/src/lib.rs +++ b/arbitrator/stylus/src/lib.rs @@ -23,12 +23,12 @@ use target_cache::{target_cache_get, target_cache_set}; pub use brotli; pub use prover; -pub mod cache; pub mod env; pub mod host; pub mod native; pub mod run; +mod cache; mod evm_api; mod target_cache; mod util; From 7e0726140c9f773ae0f315ec5de635d74a31ede4 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 16 Aug 2024 01:43:27 +0200 Subject: [PATCH 68/80] move LocalTarget() to rawdb --- arbos/programs/native.go | 21 ++++----------------- arbos/programs/testcompile.go | 4 ++-- arbos/programs/wasmstorehelper.go | 2 +- execution/gethexec/executionengine.go | 2 +- go-ethereum | 2 +- validator/client/validation_client.go | 3 +-- validator/server_jit/jit_machine.go | 4 ++-- validator/server_jit/spawner.go | 3 +-- 8 files changed, 13 insertions(+), 28 deletions(-) diff --git a/arbos/programs/native.go b/arbos/programs/native.go index 38b00a5fcf..bceba2201c 100644 --- a/arbos/programs/native.go +++ b/arbos/programs/native.go @@ -21,7 +21,6 @@ import "C" import ( "errors" "fmt" - "runtime" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" @@ -100,7 +99,7 @@ func activateProgramInternal( } return nil, nil, err } - target := LocalTarget() + target := rawdb.LocalTarget() status_asm := C.stylus_compile( goSlice(wasm), u16(version), @@ -130,7 +129,7 @@ func activateProgramInternal( } func getLocalAsm(statedb vm.StateDB, moduleHash common.Hash, addressForLogging common.Address, code []byte, codeHash common.Hash, pagelimit uint16, time uint64, debugMode bool, program Program) ([]byte, error) { - localTarget := LocalTarget() + localTarget := rawdb.LocalTarget() localAsm, err := statedb.TryGetActivatedAsm(localTarget, moduleHash) if err == nil && len(localAsm) > 0 { return localAsm, nil @@ -206,7 +205,7 @@ func callProgram( if db, ok := db.(*state.StateDB); ok { targets := []rawdb.Target{ rawdb.TargetWavm, - LocalTarget(), + rawdb.LocalTarget(), } db.RecordProgram(targets, moduleHash) } @@ -268,7 +267,7 @@ func evictProgram(db vm.StateDB, module common.Hash, version uint16, debug bool, tag := db.Database().WasmCacheTag() state.EvictWasmRust(module, version, tag, debug) if !forever { - db.RecordEvictWasm(state.EvictWasm{Target: LocalTarget(), ModuleHash: module, Version: version, Tag: tag, Debug: debug}) + db.RecordEvictWasm(state.EvictWasm{ModuleHash: module, Version: version, Tag: tag, Debug: debug}) } } } @@ -286,18 +285,6 @@ func ResizeWasmLruCache(size uint32) { C.stylus_cache_lru_resize(u32(size)) } -func LocalTarget() rawdb.Target { - if runtime.GOOS == "linux" { - switch runtime.GOARCH { - case "arm64": - return rawdb.TargetArm64 - case "amd64": - return rawdb.TargetAmd64 - } - } - return rawdb.TargetHost -} - const DefaultTargetDescriptionArm = "arm64-linux-unknown+neon" const DefaultTargetDescriptionX86 = "x86_64-linux-unknown+sse4.2" diff --git a/arbos/programs/testcompile.go b/arbos/programs/testcompile.go index ab8ab37491..85c2c5141a 100644 --- a/arbos/programs/testcompile.go +++ b/arbos/programs/testcompile.go @@ -31,7 +31,7 @@ import ( func testCompileArch(store bool) error { - localTarget := LocalTarget() + localTarget := rawdb.LocalTarget() nativeArm64 := localTarget == rawdb.TargetArm64 nativeAmd64 := localTarget == rawdb.TargetAmd64 @@ -169,7 +169,7 @@ func testCompileArch(store bool) error { func testCompileLoad() error { filePath := "../../target/testdata/host.bin" - localTarget := LocalTarget() + localTarget := rawdb.LocalTarget() if localTarget == rawdb.TargetArm64 { filePath = "../../target/testdata/arm64.bin" } diff --git a/arbos/programs/wasmstorehelper.go b/arbos/programs/wasmstorehelper.go index 0910cee341..4f82d80282 100644 --- a/arbos/programs/wasmstorehelper.go +++ b/arbos/programs/wasmstorehelper.go @@ -44,7 +44,7 @@ func (p Programs) SaveActiveProgramToWasmStore(statedb *state.StateDB, codeHash } // If already in wasm store then return early - _, err = statedb.TryGetActivatedAsmMap([]rawdb.Target{rawdb.TargetWavm, LocalTarget()}, moduleHash) + _, err = statedb.TryGetActivatedAsmMap([]rawdb.Target{rawdb.TargetWavm, rawdb.LocalTarget()}, moduleHash) if err == nil { return nil } diff --git a/execution/gethexec/executionengine.go b/execution/gethexec/executionengine.go index 7e580a3f25..806355b2c6 100644 --- a/execution/gethexec/executionengine.go +++ b/execution/gethexec/executionengine.go @@ -155,7 +155,7 @@ func (s *ExecutionEngine) Initialize(rustCacheSize uint32, targetConfig *StylusT programs.ResizeWasmLruCache(rustCacheSize) } var effectiveStylusTarget string - target := programs.LocalTarget() + target := rawdb.LocalTarget() switch target { case rawdb.TargetArm64: effectiveStylusTarget = targetConfig.Arm64 diff --git a/go-ethereum b/go-ethereum index d05523574d..aa44bd44e0 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit d05523574d39a6950d73081c0f90db0dac5df60c +Subproject commit aa44bd44e00be7e5689aea3b63d8907cd3686540 diff --git a/validator/client/validation_client.go b/validator/client/validation_client.go index 6301c449a3..a87e66b333 100644 --- a/validator/client/validation_client.go +++ b/validator/client/validation_client.go @@ -11,7 +11,6 @@ import ( "sync/atomic" "time" - "github.com/offchainlabs/nitro/arbos/programs" "github.com/offchainlabs/nitro/validator" "github.com/offchainlabs/nitro/util/containers" @@ -81,7 +80,7 @@ func (c *ValidationClient) Start(ctx context.Context) error { } for _, stylusArch := range stylusArchs { - if stylusArch != rawdb.TargetWavm && stylusArch != programs.LocalTarget() && stylusArch != "mock" { + if stylusArch != rawdb.TargetWavm && stylusArch != rawdb.LocalTarget() && stylusArch != "mock" { return fmt.Errorf("unsupported stylus architecture: %v", stylusArch) } } diff --git a/validator/server_jit/jit_machine.go b/validator/server_jit/jit_machine.go index f442001e73..23a75bba83 100644 --- a/validator/server_jit/jit_machine.go +++ b/validator/server_jit/jit_machine.go @@ -15,9 +15,9 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" - "github.com/offchainlabs/nitro/arbos/programs" "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/validator" ) @@ -212,7 +212,7 @@ func (machine *JitMachine) prove( } } - localTarget := programs.LocalTarget() + localTarget := rawdb.LocalTarget() userWasms := entry.UserWasms[localTarget] // if there are user wasms, but only for wrong architecture - error diff --git a/validator/server_jit/spawner.go b/validator/server_jit/spawner.go index 4ac580018f..92b50b17cb 100644 --- a/validator/server_jit/spawner.go +++ b/validator/server_jit/spawner.go @@ -11,7 +11,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/offchainlabs/nitro/arbos/programs" "github.com/offchainlabs/nitro/util/stopwaiter" "github.com/offchainlabs/nitro/validator" "github.com/offchainlabs/nitro/validator/server_common" @@ -74,7 +73,7 @@ func (v *JitSpawner) WasmModuleRoots() ([]common.Hash, error) { } func (v *JitSpawner) StylusArchs() []rawdb.Target { - return []rawdb.Target{programs.LocalTarget()} + return []rawdb.Target{rawdb.LocalTarget()} } func (v *JitSpawner) execute( From 0f8c07f7991a1d2c4f905489dc6771f0398c8a94 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 15 Aug 2024 18:05:08 -0600 Subject: [PATCH 69/80] validationClient: fail if trying to validate stylus-block on non-stylus --- validator/client/validation_client.go | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/validator/client/validation_client.go b/validator/client/validation_client.go index a87e66b333..80cff66675 100644 --- a/validator/client/validation_client.go +++ b/validator/client/validation_client.go @@ -74,14 +74,15 @@ func (c *ValidationClient) Start(ctx context.Context) error { if !ok || rpcError.ErrorCode() != -32601 { return fmt.Errorf("could not read stylus arch from server: %w", err) } - // validation does not support stylus, leaving stylusArchs empty - } else if len(stylusArchs) == 0 { - return fmt.Errorf("could not read stylus archs from validation server") - } - - for _, stylusArch := range stylusArchs { - if stylusArch != rawdb.TargetWavm && stylusArch != rawdb.LocalTarget() && stylusArch != "mock" { - return fmt.Errorf("unsupported stylus architecture: %v", stylusArch) + stylusArchs = []rawdb.Target{rawdb.Target("pre-stylus")} // invalid, will fail if trying to validate block with stylus + } else { + if len(stylusArchs) == 0 { + return fmt.Errorf("could not read stylus archs from validation server") + } + for _, stylusArch := range stylusArchs { + if stylusArch != rawdb.TargetWavm && stylusArch != rawdb.LocalTarget() && stylusArch != "mock" { + return fmt.Errorf("unsupported stylus architecture: %v", stylusArch) + } } } var moduleRoots []common.Hash From a24315c1efe3df83a3b038047b3b0e10aed2991e Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 15 Aug 2024 19:17:50 -0600 Subject: [PATCH 70/80] target_cache: move native target inside target_cache --- arbitrator/jit/src/stylus_backend.rs | 11 ++--------- arbitrator/stylus/src/cache.rs | 17 ++++------------- arbitrator/stylus/src/native.rs | 5 +++-- arbitrator/stylus/src/target_cache.rs | 11 +++++++---- 4 files changed, 16 insertions(+), 28 deletions(-) diff --git a/arbitrator/jit/src/stylus_backend.rs b/arbitrator/jit/src/stylus_backend.rs index cb0440a257..80a0af4aa6 100644 --- a/arbitrator/jit/src/stylus_backend.rs +++ b/arbitrator/jit/src/stylus_backend.rs @@ -144,15 +144,8 @@ pub fn exec_wasm( let evm_api = EvmApiRequestor::new(cothread); - let mut instance = unsafe { - NativeInstance::deserialize( - &module, - compile.clone(), - evm_api, - evm_data, - Target::default(), - ) - }?; + let mut instance = + unsafe { NativeInstance::deserialize(&module, compile.clone(), evm_api, evm_data) }?; let thread = thread::spawn(move || { let outcome = instance.run_main(&calldata, config, ink); diff --git a/arbitrator/stylus/src/cache.rs b/arbitrator/stylus/src/cache.rs index 62db786ac0..fa38d45419 100644 --- a/arbitrator/stylus/src/cache.rs +++ b/arbitrator/stylus/src/cache.rs @@ -8,7 +8,9 @@ use lru::LruCache; use parking_lot::Mutex; use prover::programs::config::CompileConfig; use std::{collections::HashMap, num::NonZeroUsize}; -use wasmer::{Engine, Module, Store, Target}; +use wasmer::{Engine, Module, Store}; + +use crate::target_cache::target_native; lazy_static! { static ref INIT_CACHE: Mutex = Mutex::new(InitCache::new(256)); @@ -23,7 +25,6 @@ macro_rules! cache { pub struct InitCache { long_term: HashMap, lru: LruCache, - target: Target, } #[derive(Clone, Copy, Hash, PartialEq, Eq)] @@ -69,7 +70,6 @@ impl InitCache { Self { long_term: HashMap::new(), lru: LruCache::new(NonZeroUsize::new(size).unwrap()), - target: Target::default(), } } @@ -79,14 +79,6 @@ impl InitCache { .resize(NonZeroUsize::new(size.try_into().unwrap()).unwrap()) } - pub fn set_target(target: Target) { - cache!().target = target; - } - - pub fn target() -> Target { - cache!().target.clone() - } - /// Retrieves a cached value, updating items as necessary. pub fn get(module_hash: Bytes32, version: u16, debug: bool) -> Option<(Module, Store)> { let mut cache = cache!(); @@ -128,10 +120,9 @@ impl InitCache { } return Ok(item.data()); } - let target = cache.target.clone(); drop(cache); - let engine = CompileConfig::version(version, debug).engine(target); + let engine = CompileConfig::version(version, debug).engine(target_native()); let module = unsafe { Module::deserialize_unchecked(&engine, module)? }; let item = CacheItem::new(module, engine); diff --git a/arbitrator/stylus/src/native.rs b/arbitrator/stylus/src/native.rs index 18ff8f903e..cc1d191fe2 100644 --- a/arbitrator/stylus/src/native.rs +++ b/arbitrator/stylus/src/native.rs @@ -38,6 +38,8 @@ use wasmer::{ }; use wasmer_vm::VMExtern; +use crate::target_cache::target_native; + #[derive(Debug)] pub struct NativeInstance> { pub instance: Instance, @@ -96,10 +98,9 @@ impl> NativeInstance { compile: CompileConfig, evm: E, evm_data: EvmData, - target: Target, ) -> Result { let env = WasmEnv::new(compile, None, evm, evm_data); - let store = env.compile.store(target); + let store = env.compile.store(target_native()); let module = unsafe { Module::deserialize_unchecked(&store, module)? }; Self::from_module(module, store, env) } diff --git a/arbitrator/stylus/src/target_cache.rs b/arbitrator/stylus/src/target_cache.rs index b8da26d63f..12598b73e4 100644 --- a/arbitrator/stylus/src/target_cache.rs +++ b/arbitrator/stylus/src/target_cache.rs @@ -7,10 +7,9 @@ use parking_lot::RwLock; use std::{collections::HashMap, str::FromStr}; use wasmer_types::{CpuFeature, Target, Triple}; -use crate::cache::InitCache; - lazy_static! { static ref TARGET_CACHE: RwLock> = RwLock::new(HashMap::new()); + static ref TARGET_NATIVE: RwLock = RwLock::new(Target::default()); } fn target_from_string(input: String) -> Result { @@ -56,7 +55,7 @@ pub fn target_cache_set(name: String, description: String, native: bool) -> Resu } return Err(eyre!(err_message)); } - InitCache::set_target(target.clone()) + *TARGET_NATIVE.write() = target.clone(); } TARGET_CACHE.write().insert(name, target); @@ -64,9 +63,13 @@ pub fn target_cache_set(name: String, description: String, native: bool) -> Resu Ok(()) } +pub fn target_native() -> Target { + TARGET_NATIVE.read().clone() +} + pub fn target_cache_get(name: &str) -> Result { if name.is_empty() { - return Ok(InitCache::target()); + return Ok(TARGET_NATIVE.read().clone()); } TARGET_CACHE .read() From b49a63c076e3162c53077eca6a5e5d03bd962fbc Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 15 Aug 2024 19:32:29 -0600 Subject: [PATCH 71/80] clippy fix --- arbitrator/jit/src/stylus_backend.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/arbitrator/jit/src/stylus_backend.rs b/arbitrator/jit/src/stylus_backend.rs index 80a0af4aa6..61dbf258d4 100644 --- a/arbitrator/jit/src/stylus_backend.rs +++ b/arbitrator/jit/src/stylus_backend.rs @@ -24,7 +24,6 @@ use std::{ thread::JoinHandle, }; use stylus::{native::NativeInstance, run::RunProgram}; -use wasmer::Target; struct MessageToCothread { result: Vec, From fba31fde41f0fdd5e247b4de53abb284a01cfc0c Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 15 Aug 2024 19:48:54 -0600 Subject: [PATCH 72/80] compilation fix --- arbitrator/stylus/src/test/api.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbitrator/stylus/src/test/api.rs b/arbitrator/stylus/src/test/api.rs index 074eb8cfab..b25540f875 100644 --- a/arbitrator/stylus/src/test/api.rs +++ b/arbitrator/stylus/src/test/api.rs @@ -114,7 +114,7 @@ impl EvmApi for TestEvmApi { let mut native = unsafe { let contracts = self.contracts.lock(); let module = contracts.get(&contract).unwrap(); - TestInstance::deserialize(module, compile, self.clone(), evm_data, Target::default()) + TestInstance::deserialize(module, compile, self.clone(), evm_data) .unwrap() }; From 96fafabcce424ecbcda09aea9282cffe63dd41a7 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 16 Aug 2024 13:33:55 +0200 Subject: [PATCH 73/80] use renamed DeprecatedPrefixesV0 --- cmd/nitro/init.go | 2 +- go-ethereum | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index 0ec768d4c7..6f2d97dd03 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -415,7 +415,7 @@ func databaseIsEmpty(db ethdb.Database) bool { // removes all entries with keys prefixed with prefixes and of length used in initial version of wasm store schema func purgeVersion0WasmStoreEntries(db ethdb.Database) error { - prefixes, keyLength := rawdb.DeprecatedKeysV0() + prefixes, keyLength := rawdb.DeprecatedPrefixesV0() batch := db.NewBatch() notMatchingLengthKeyLogged := false for _, prefix := range prefixes { diff --git a/go-ethereum b/go-ethereum index aa44bd44e0..abc46c6c1d 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit aa44bd44e00be7e5689aea3b63d8907cd3686540 +Subproject commit abc46c6c1da78e2220738056ddd89b32de645590 From f3f2d751a25023506bca71510a23d3ef635aaa51 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 16 Aug 2024 14:24:23 +0200 Subject: [PATCH 74/80] update geth pin --- go-ethereum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-ethereum b/go-ethereum index abc46c6c1d..575062fad7 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit abc46c6c1da78e2220738056ddd89b32de645590 +Subproject commit 575062fad7ff4db9d7c235f49472f658be29e2fe From 57adb9d24fe18b80d75d9279b46b57627e685906 Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 16 Aug 2024 16:24:40 +0200 Subject: [PATCH 75/80] rustfmt arbitrator/stylus/src/test/api.rs --- arbitrator/stylus/src/test/api.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arbitrator/stylus/src/test/api.rs b/arbitrator/stylus/src/test/api.rs index b25540f875..5d9f625e5e 100644 --- a/arbitrator/stylus/src/test/api.rs +++ b/arbitrator/stylus/src/test/api.rs @@ -114,8 +114,7 @@ impl EvmApi for TestEvmApi { let mut native = unsafe { let contracts = self.contracts.lock(); let module = contracts.get(&contract).unwrap(); - TestInstance::deserialize(module, compile, self.clone(), evm_data) - .unwrap() + TestInstance::deserialize(module, compile, self.clone(), evm_data).unwrap() }; let ink = config.pricing.gas_to_ink(gas); From 1543e98f4279e17a63af68f7440b89b2f08a9bbe Mon Sep 17 00:00:00 2001 From: Maciej Kulawik Date: Fri, 16 Aug 2024 17:32:44 +0200 Subject: [PATCH 76/80] add comment to target_cache_set --- arbitrator/stylus/src/target_cache.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arbitrator/stylus/src/target_cache.rs b/arbitrator/stylus/src/target_cache.rs index 12598b73e4..a1d63829d6 100644 --- a/arbitrator/stylus/src/target_cache.rs +++ b/arbitrator/stylus/src/target_cache.rs @@ -35,6 +35,8 @@ fn target_from_string(input: String) -> Result { 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)?; From b9c35487993f38822b21b74d0887e90a60873cc3 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Fri, 16 Aug 2024 15:08:59 -0600 Subject: [PATCH 77/80] remove wasmer-go, use stylus lib for wat2wasm --- arbitrator/stylus/src/lib.rs | 14 ++++++++++++++ arbos/programs/testcompile.go | 15 +++++++++++++-- go.mod | 1 - go.sum | 2 -- system_tests/program_test.go | 3 +-- 5 files changed, 28 insertions(+), 7 deletions(-) diff --git a/arbitrator/stylus/src/lib.rs b/arbitrator/stylus/src/lib.rs index a48ce4f064..a21bd6e2a5 100644 --- a/arbitrator/stylus/src/lib.rs +++ b/arbitrator/stylus/src/lib.rs @@ -201,6 +201,20 @@ pub unsafe extern "C" fn stylus_compile( UserOutcomeKind::Success } +#[no_mangle] +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.. diff --git a/arbos/programs/testcompile.go b/arbos/programs/testcompile.go index 85c2c5141a..a16bae52c0 100644 --- a/arbos/programs/testcompile.go +++ b/arbos/programs/testcompile.go @@ -26,9 +26,20 @@ import ( "runtime" "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/wasmerio/wasmer-go/wasmer" ) +func Wat2Wasm(wat []byte) ([]byte, error) { + output := &rustBytes{} + + status := C.wat_to_wasm(goSlice(wat), output) + + if status != 0 { + return nil, fmt.Errorf("failed reading wat file: %v", string(output.intoBytes())) + } + + return output.intoBytes(), nil +} + func testCompileArch(store bool) error { localTarget := rawdb.LocalTarget() @@ -71,7 +82,7 @@ func testCompileArch(store bool) error { return fmt.Errorf("failed reading stylus contract: %w", err) } - wasm, err := wasmer.Wat2Wasm(string(source)) + wasm, err := Wat2Wasm(source) if err != nil { return err } diff --git a/go.mod b/go.mod index 6649973725..da49b0d8b9 100644 --- a/go.mod +++ b/go.mod @@ -41,7 +41,6 @@ require ( github.com/rivo/tview v0.0.0-20240307173318-e804876934a1 github.com/spf13/pflag v1.0.5 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 - github.com/wasmerio/wasmer-go v1.0.4 github.com/wealdtech/go-merkletree v1.0.0 golang.org/x/crypto v0.21.0 golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa diff --git a/go.sum b/go.sum index 8529b2497d..c0193be769 100644 --- a/go.sum +++ b/go.sum @@ -704,8 +704,6 @@ github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9 github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= -github.com/wasmerio/wasmer-go v1.0.4 h1:MnqHoOGfiQ8MMq2RF6wyCeebKOe84G88h5yv+vmxJgs= -github.com/wasmerio/wasmer-go v1.0.4/go.mod h1:0gzVdSfg6pysA6QVp6iVRPTagC6Wq9pOE8J86WKb2Fk= github.com/wealdtech/go-merkletree v1.0.0 h1:DsF1xMzj5rK3pSQM6mPv8jlyJyHXhFxpnA2bwEjMMBY= github.com/wealdtech/go-merkletree v1.0.0/go.mod h1:cdil512d/8ZC7Kx3bfrDvGMQXB25NTKbsm0rFrmDax4= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= diff --git a/system_tests/program_test.go b/system_tests/program_test.go index ae34c6c5bb..e171f2a444 100644 --- a/system_tests/program_test.go +++ b/system_tests/program_test.go @@ -41,7 +41,6 @@ import ( "github.com/offchainlabs/nitro/util/colors" "github.com/offchainlabs/nitro/util/testhelpers" "github.com/offchainlabs/nitro/validator/valnode" - "github.com/wasmerio/wasmer-go/wasmer" ) var oneEth = arbmath.UintToBig(1e18) @@ -1530,7 +1529,7 @@ func readWasmFile(t *testing.T, file string) ([]byte, []byte) { // chose a random dictionary for testing, but keep the same files consistent randDict := arbcompress.Dictionary((len(file) + len(t.Name())) % 2) - wasmSource, err := wasmer.Wat2Wasm(string(source)) + wasmSource, err := programs.Wat2Wasm(source) Require(t, err) wasm, err := arbcompress.Compress(wasmSource, arbcompress.LEVEL_WELL, randDict) Require(t, err) From 04791502b8c42fd586ba823848ca3d4041ac271f Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Fri, 16 Aug 2024 16:11:34 -0600 Subject: [PATCH 78/80] wat_to_wasm clippy --- arbitrator/stylus/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arbitrator/stylus/src/lib.rs b/arbitrator/stylus/src/lib.rs index a21bd6e2a5..e503bb6348 100644 --- a/arbitrator/stylus/src/lib.rs +++ b/arbitrator/stylus/src/lib.rs @@ -202,6 +202,9 @@ pub unsafe extern "C" fn stylus_compile( } #[no_mangle] +/// # Safety +/// +/// `output` must not be null. pub unsafe extern "C" fn wat_to_wasm( wat: GoSliceData, output: *mut RustBytes, From 0e1b98cfedaff3a0cad12af4a2ac1810842bfd9c Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Fri, 16 Aug 2024 17:33:15 -0600 Subject: [PATCH 79/80] cargo fmt --- arbitrator/stylus/src/lib.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/arbitrator/stylus/src/lib.rs b/arbitrator/stylus/src/lib.rs index e503bb6348..a252b60a01 100644 --- a/arbitrator/stylus/src/lib.rs +++ b/arbitrator/stylus/src/lib.rs @@ -205,10 +205,7 @@ pub unsafe extern "C" fn stylus_compile( /// # Safety /// /// `output` must not be null. -pub unsafe extern "C" fn wat_to_wasm( - wat: GoSliceData, - output: *mut RustBytes, -) -> UserOutcomeKind { +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, From eb690ee327a7c79fded36673a59dd205c59c0fef Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Fri, 16 Aug 2024 18:59:48 -0600 Subject: [PATCH 80/80] fix merge conflict --- cmd/nitro/init.go | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index 85eb8cfaef..f578348b04 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -397,16 +397,6 @@ func checkEmptyDatabaseDir(dir string, force bool) error { return nil } -var pebbleNotExistErrorRegex = regexp.MustCompile("pebble: database .* does not exist") - -func isPebbleNotExistError(err error) bool { - return pebbleNotExistErrorRegex.MatchString(err.Error()) -} - -func isLeveldbNotExistError(err error) bool { - return os.IsNotExist(err) -} - func databaseIsEmpty(db ethdb.Database) bool { it := db.NewIterator(nil, nil) defer it.Release()