diff --git a/.github/workflows/submodule-pin-check.sh b/.github/workflows/submodule-pin-check.sh deleted file mode 100755 index aecb287ce1..0000000000 --- a/.github/workflows/submodule-pin-check.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -declare -Ar exceptions=( - [contracts]=origin/develop - [nitro-testnode]=origin/master - - #TODO Rachel to check these are the intended branches. - [arbitrator/langs/c]=origin/vm-storage-cache - [arbitrator/tools/wasmer]=origin/adopt-v4.2.8 -) - -divergent=0 -for mod in `git submodule --quiet foreach 'echo $name'`; do - branch=origin/HEAD - if [[ -v exceptions[$mod] ]]; then - branch=${exceptions[$mod]} - fi - - if ! git -C $mod merge-base --is-ancestor HEAD $branch; then - echo $mod diverges from $branch - divergent=1 - fi -done - -exit $divergent - diff --git a/.github/workflows/submodule-pin-check.yml b/.github/workflows/submodule-pin-check.yml index f045f71f68..90419b530e 100644 --- a/.github/workflows/submodule-pin-check.yml +++ b/.github/workflows/submodule-pin-check.yml @@ -18,11 +18,32 @@ jobs: with: fetch-depth: 0 submodules: true + ref: "${{ github.event.pull_request.merge_commit_sha }}" - name: Check all submodules are ancestors of origin/HEAD or configured branch run: | status_state="pending" - if ${{ github.workspace }}/.github/workflows/submodule-pin-check.sh; then + declare -Ar exceptions=( + [contracts]=origin/develop + [nitro-testnode]=origin/master + + #TODO Rachel to check these are the intended branches. + [arbitrator/langs/c]=origin/vm-storage-cache + [arbitrator/tools/wasmer]=origin/adopt-v4.2.8 + ) + divergent=0 + for mod in `git submodule --quiet foreach 'echo $name'`; do + branch=origin/HEAD + if [[ -v exceptions[$mod] ]]; then + branch=${exceptions[$mod]} + fi + + if ! git -C $mod merge-base --is-ancestor HEAD $branch; then + echo $mod diverges from $branch + divergent=1 + fi + done + if [ $divergent -eq 0 ]; then status_state="success" else resp="$(curl -sSL --fail-with-body \ diff --git a/Makefile b/Makefile index 0a71d64f12..b736b04906 100644 --- a/Makefile +++ b/Makefile @@ -60,7 +60,7 @@ replay_wasm=$(output_latest)/replay.wasm arb_brotli_files = $(wildcard arbitrator/brotli/src/*.* arbitrator/brotli/src/*/*.* arbitrator/brotli/*.toml arbitrator/brotli/*.rs) .make/cbrotli-lib .make/cbrotli-wasm arbitrator_generated_header=$(output_root)/include/arbitrator.h -arbitrator_wasm_libs=$(patsubst %, $(output_root)/machines/latest/%.wasm, forward wasi_stub host_io soft-float arbcompress user_host program_exec) +arbitrator_wasm_libs=$(patsubst %, $(output_root)/machines/latest/%.wasm, wasi_stub host_io soft-float arbcompress user_host program_exec) arbitrator_stylus_lib=$(output_root)/lib/libstylus.a prover_bin=$(output_root)/bin/prover arbitrator_jit=$(output_root)/bin/jit @@ -75,16 +75,12 @@ arbitrator_test_wasms=$(patsubst %.wat,%.wasm, $(arbitrator_tests_wat)) $(patsub arbitrator_tests_link_info = $(shell cat $(arbitrator_cases)/link.txt | xargs) arbitrator_tests_link_deps = $(patsubst %,$(arbitrator_cases)/%.wasm, $(arbitrator_tests_link_info)) -arbitrator_tests_forward_wats = $(wildcard $(arbitrator_cases)/forward/*.wat) -arbitrator_tests_forward_deps = $(arbitrator_tests_forward_wats:wat=wasm) - WASI_SYSROOT?=/opt/wasi-sdk/wasi-sysroot arbitrator_wasm_lib_flags=$(patsubst %, -l %, $(arbitrator_wasm_libs)) rust_arbutil_files = $(wildcard arbitrator/arbutil/src/*.* arbitrator/arbutil/src/*/*.* arbitrator/arbutil/*.toml arbitrator/caller-env/src/*.* arbitrator/caller-env/src/*/*.* arbitrator/caller-env/*.toml) .make/cbrotli-lib -prover_direct_includes = $(patsubst %,$(output_latest)/%.wasm, forward forward_stub) prover_dir = arbitrator/prover/ rust_prover_files = $(wildcard $(prover_dir)/src/*.* $(prover_dir)/src/*/*.* $(prover_dir)/*.toml $(prover_dir)/*.rs) $(rust_arbutil_files) $(prover_direct_includes) $(arb_brotli_files) @@ -92,12 +88,9 @@ wasm_lib = arbitrator/wasm-libraries wasm_lib_cargo = $(wasm_lib)/.cargo/config.toml wasm_lib_deps = $(wildcard $(wasm_lib)/$(1)/*.toml $(wasm_lib)/$(1)/src/*.rs $(wasm_lib)/$(1)/*.rs) $(wasm_lib_cargo) $(rust_arbutil_files) $(arb_brotli_files) .make/machines wasm_lib_go_abi = $(call wasm_lib_deps,go-abi) -wasm_lib_forward = $(call wasm_lib_deps,forward) wasm_lib_user_host_trait = $(call wasm_lib_deps,user-host-trait) wasm_lib_user_host = $(call wasm_lib_deps,user-host) $(wasm_lib_user_host_trait) -forward_dir = $(wasm_lib)/forward - stylus_files = $(wildcard $(stylus_dir)/*.toml $(stylus_dir)/src/*.rs) $(wasm_lib_user_host_trait) $(rust_prover_files) jit_dir = arbitrator/jit @@ -281,7 +274,6 @@ clean: rm -f arbitrator/wasm-libraries/soft-float/*.o rm -f arbitrator/wasm-libraries/soft-float/SoftFloat/build/Wasm-Clang/*.o rm -f arbitrator/wasm-libraries/soft-float/SoftFloat/build/Wasm-Clang/*.a - rm -f arbitrator/wasm-libraries/forward/*.wat rm -rf arbitrator/stylus/tests/*/target/ arbitrator/stylus/tests/*/*.wasm @rm -rf contracts/build contracts/cache solgen/go/ @rm -f .make/* @@ -399,7 +391,7 @@ $(output_latest)/host_io.wasm: $(DEP_PREDICATE) $(call wasm_lib_deps,host-io) $( cargo build --manifest-path arbitrator/wasm-libraries/Cargo.toml --release --target wasm32-wasi --config $(wasm_lib_cargo) --package host-io install arbitrator/wasm-libraries/$(wasm32_wasi)/host_io.wasm $@ -$(output_latest)/user_host.wasm: $(DEP_PREDICATE) $(wasm_lib_user_host) $(rust_prover_files) $(output_latest)/forward_stub.wasm .make/machines +$(output_latest)/user_host.wasm: $(DEP_PREDICATE) $(wasm_lib_user_host) $(rust_prover_files) .make/machines cargo build --manifest-path arbitrator/wasm-libraries/Cargo.toml --release --target wasm32-wasi --config $(wasm_lib_cargo) --package user-host install arbitrator/wasm-libraries/$(wasm32_wasi)/user_host.wasm $@ @@ -415,17 +407,9 @@ $(output_latest)/arbcompress.wasm: $(DEP_PREDICATE) $(call wasm_lib_deps,brotli) cargo build --manifest-path arbitrator/wasm-libraries/Cargo.toml --release --target wasm32-wasi --config $(wasm_lib_cargo) --package arbcompress install arbitrator/wasm-libraries/$(wasm32_wasi)/arbcompress.wasm $@ -$(output_latest)/forward.wasm: $(DEP_PREDICATE) $(wasm_lib_forward) .make/machines - cargo run --manifest-path $(forward_dir)/Cargo.toml -- --path $(forward_dir)/forward.wat - wat2wasm $(wasm_lib)/forward/forward.wat -o $@ - -$(output_latest)/forward_stub.wasm: $(DEP_PREDICATE) $(wasm_lib_forward) .make/machines - cargo run --manifest-path $(forward_dir)/Cargo.toml -- --path $(forward_dir)/forward_stub.wat --stub - wat2wasm $(wasm_lib)/forward/forward_stub.wat -o $@ - $(output_latest)/machine.wavm.br: $(DEP_PREDICATE) $(prover_bin) $(arbitrator_wasm_libs) $(replay_wasm) - $(prover_bin) $(replay_wasm) --generate-binaries $(output_latest) \ - $(patsubst %,-l $(output_latest)/%.wasm, forward soft-float wasi_stub host_io user_host arbcompress program_exec) + $(prover_bin) $(replay_wasm) --generate-binaries $(output_latest) --with-forwarder \ + $(patsubst %,-l $(output_latest)/%.wasm, soft-float wasi_stub host_io user_host arbcompress program_exec) $(arbitrator_cases)/%.wasm: $(arbitrator_cases)/%.wat wat2wasm $< -o $@ @@ -492,10 +476,10 @@ target/testdata/preimages.bin: python3 scripts/create-test-preimages.py $@ contracts/test/prover/proofs/rust-%.json: $(arbitrator_cases)/rust/$(wasm32_wasi)/%.wasm $(prover_bin) $(arbitrator_wasm_libs) target/testdata/preimages.bin - $(prover_bin) $< $(arbitrator_wasm_lib_flags) -o $@ -b --allow-hostapi --require-success --inbox-add-stub-headers --inbox $(arbitrator_cases)/rust/data/msg0.bin --inbox $(arbitrator_cases)/rust/data/msg1.bin --delayed-inbox $(arbitrator_cases)/rust/data/msg0.bin --delayed-inbox $(arbitrator_cases)/rust/data/msg1.bin --preimages target/testdata/preimages.bin + $(prover_bin) $< $(arbitrator_wasm_lib_flags) -o $@ -b --allow-hostapi --require-success --inbox-add-stub-headers --inbox $(arbitrator_cases)/rust/data/msg0.bin --inbox $(arbitrator_cases)/rust/data/msg1.bin --delayed-inbox $(arbitrator_cases)/rust/data/msg0.bin --delayed-inbox $(arbitrator_cases)/rust/data/msg1.bin --preimages target/testdata/preimages.bin --with-forwarder contracts/test/prover/proofs/go.json: $(arbitrator_cases)/go/testcase.wasm $(prover_bin) $(arbitrator_wasm_libs) target/testdata/preimages.bin $(arbitrator_tests_link_deps) $(arbitrator_cases)/user.wasm - $(prover_bin) $< $(arbitrator_wasm_lib_flags) -o $@ -b --require-success --preimages target/testdata/preimages.bin --stylus-modules $(arbitrator_cases)/user.wasm + $(prover_bin) $< $(arbitrator_wasm_lib_flags) -o $@ -b --require-success --preimages target/testdata/preimages.bin --stylus-modules $(arbitrator_cases)/user.wasm --with-forwarder # avoid testing user.wasm in onestepproofs. It can only run as stylus program. contracts/test/prover/proofs/user.json: @@ -508,9 +492,6 @@ contracts/test/prover/proofs/read-inboxmsg-10.json: contracts/test/prover/proofs/global-state.json: echo "[]" > $@ -contracts/test/prover/proofs/forward-test.json: $(arbitrator_cases)/forward-test.wasm $(arbitrator_tests_forward_deps) $(prover_bin) - $(prover_bin) $< -o $@ --allow-hostapi $(patsubst %,-l %, $(arbitrator_tests_forward_deps)) - contracts/test/prover/proofs/link.json: $(arbitrator_cases)/link.wasm $(arbitrator_tests_link_deps) $(prover_bin) $(prover_bin) $< -o $@ --allow-hostapi --stylus-modules $(arbitrator_tests_link_deps) --require-success diff --git a/arbitrator/arbutil/src/hostios.rs b/arbitrator/arbutil/src/hostios.rs new file mode 100644 index 0000000000..05bcb94f73 --- /dev/null +++ b/arbitrator/arbutil/src/hostios.rs @@ -0,0 +1,64 @@ +use std::fmt::Display; + +pub enum ParamType { + I32, + I64, +} + +impl Display for ParamType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + use ParamType::*; + match self { + I32 => write!(f, "i32"), + I64 => write!(f, "i64"), + } + } +} + +use ParamType::*; + +/// order matters! +pub const HOSTIOS: [(&str, &[ParamType], &[ParamType]); 42] = [ + ("read_args", &[I32], &[]), + ("write_result", &[I32, I32], &[]), + ("exit_early", &[I32], &[]), + ("storage_load_bytes32", &[I32, I32], &[]), + ("storage_cache_bytes32", &[I32, I32], &[]), + ("storage_flush_cache", &[I32], &[]), + ("transient_load_bytes32", &[I32, I32], &[]), + ("transient_store_bytes32", &[I32, I32], &[]), + ("call_contract", &[I32, I32, I32, I32, I64, I32], &[I32]), + ("delegate_call_contract", &[I32, I32, I32, I64, I32], &[I32]), + ("static_call_contract", &[I32, I32, I32, I64, I32], &[I32]), + ("create1", &[I32, I32, I32, I32, I32], &[]), + ("create2", &[I32, I32, I32, I32, I32, I32], &[]), + ("read_return_data", &[I32, I32, I32], &[I32]), + ("return_data_size", &[], &[I32]), + ("emit_log", &[I32, I32, I32], &[]), + ("account_balance", &[I32, I32], &[]), + ("account_code", &[I32, I32, I32, I32], &[I32]), + ("account_code_size", &[I32], &[I32]), + ("account_codehash", &[I32, I32], &[]), + ("evm_gas_left", &[], &[I64]), + ("evm_ink_left", &[], &[I64]), + ("block_basefee", &[I32], &[]), + ("chainid", &[], &[I64]), + ("block_coinbase", &[I32], &[]), + ("block_gas_limit", &[], &[I64]), + ("block_number", &[], &[I64]), + ("block_timestamp", &[], &[I64]), + ("contract_address", &[I32], &[]), + ("math_div", &[I32, I32], &[]), + ("math_mod", &[I32, I32], &[]), + ("math_pow", &[I32, I32], &[]), + ("math_add_mod", &[I32, I32, I32], &[]), + ("math_mul_mod", &[I32, I32, I32], &[]), + ("msg_reentrant", &[], &[I32]), + ("msg_sender", &[I32], &[]), + ("msg_value", &[I32], &[]), + ("native_keccak256", &[I32, I32, I32], &[]), + ("tx_gas_price", &[I32], &[]), + ("tx_ink_price", &[], &[I32]), + ("tx_origin", &[I32], &[]), + ("pay_for_memory_grow", &[I32], &[]), +]; diff --git a/arbitrator/arbutil/src/lib.rs b/arbitrator/arbutil/src/lib.rs index 9c48a9fefc..8d8c1d0fca 100644 --- a/arbitrator/arbutil/src/lib.rs +++ b/arbitrator/arbutil/src/lib.rs @@ -6,6 +6,7 @@ pub mod color; pub mod crypto; pub mod evm; pub mod format; +pub mod hostios; pub mod math; pub mod operator; pub mod pricing; diff --git a/arbitrator/prover/Cargo.toml b/arbitrator/prover/Cargo.toml index da329b1cb5..de81bb6330 100644 --- a/arbitrator/prover/Cargo.toml +++ b/arbitrator/prover/Cargo.toml @@ -47,6 +47,10 @@ enum-iterator = "2.0.1" criterion = { version = "0.5.0", features = ["html_reports"] } rand = "0.8.4" +[build-dependencies] +wasmer = { path = "../tools/wasmer/lib/api" } +arbutil = { path = "../arbutil/" } + [[bench]] name = "merkle_bench" harness = false diff --git a/arbitrator/prover/build.rs b/arbitrator/prover/build.rs new file mode 100644 index 0000000000..db0560b2c5 --- /dev/null +++ b/arbitrator/prover/build.rs @@ -0,0 +1,89 @@ +use arbutil::hostios::HOSTIOS; +use std::{env, fmt::Write, fs, path::Path}; + +pub fn gen_forwarder(out_path: &Path) { + let mut wat = String::new(); + macro_rules! wln { + ($($text:tt)*) => { + writeln!(wat, $($text)*).unwrap(); + }; + } + let s = " "; + + wln!("(module"); + + macro_rules! group { + ($list:expr, $kind:expr) => { + (!$list.is_empty()) + .then(|| { + format!( + " ({} {})", + $kind, + $list + .iter() + .map(|x| x.to_string()) + .collect::>() + .join(" ") + ) + }) + .unwrap_or_default() + }; + } + + wln!("{s};; symbols to re-export"); + for (name, ins, outs) in HOSTIOS { + let params = group!(ins, "param"); + let result = group!(outs, "result"); + wln!(r#"{s}(import "user_host" "{name}" (func $_{name}{params}{result}))"#); + } + wln!(); + + wln!("{s};; reserved offsets for future user_host imports"); + for i in HOSTIOS.len()..512 { + wln!("{s}(func $reserved_{i} unreachable)"); + } + wln!(); + + wln!( + "{s};; allows user_host to request a trap\n\ + {s}(global $trap (mut i32) (i32.const 0))\n\ + {s}(func $check\n\ + {s}{s}global.get $trap ;; see if set\n\ + {s}{s}(global.set $trap (i32.const 0)) ;; reset the flag\n\ + {s}{s}(if (then (unreachable)))\n\ + {s})\n\ + {s}(func (export \"forward__set_trap\")\n\ + {s}{s}(global.set $trap (i32.const 1))\n\ + {s})\n" + ); + + wln!("{s};; user linkage"); + for (name, ins, outs) in HOSTIOS { + let params = group!(ins, "param"); + let result = group!(outs, "result"); + wln!("{s}(func (export \"vm_hooks__{name}\"){params}{result}"); + + for i in 0..ins.len() { + wln!("{s}{s}local.get {i}"); + } + + wln!( + "{s}{s}call $_{name}\n\ + {s}{s}call $check\n\ + {s})" + ); + } + + wln!(")"); + eprintln!("{}", &wat); + + let wasm = wasmer::wat2wasm(wat.as_bytes()).unwrap(); + + fs::write(out_path, wasm.as_ref()).unwrap(); +} + +fn main() { + let out_dir = env::var("OUT_DIR").unwrap(); + let forwarder_path = Path::new(&out_dir).join("forwarder.wasm"); + gen_forwarder(&forwarder_path); +} diff --git a/arbitrator/prover/src/binary.rs b/arbitrator/prover/src/binary.rs index aa5537476c..b1d819deb2 100644 --- a/arbitrator/prover/src/binary.rs +++ b/arbitrator/prover/src/binary.rs @@ -471,10 +471,14 @@ pub fn parse<'a>(input: &'a [u8], path: &'_ Path) -> Result> { let export = export.rsplit("__").take(1); exports.extend(export); } - for import in &binary.imports { - let name = import.name; - if exports.contains(name) { - bail!("binary exports an import with the same name {}", name.red()); + // forwarder is allowed to re-export the same name + // TODO: is there a real problem if import_name == export_name but module names don't? + if path != Path::new("forwarder") { + for import in &binary.imports { + let name = import.name; + if exports.contains(name) { + bail!("binary exports an import with the same name {}", name.red()); + } } } diff --git a/arbitrator/prover/src/host.rs b/arbitrator/prover/src/host.rs index 1d0fe658ec..dc0f0b74b2 100644 --- a/arbitrator/prover/src/host.rs +++ b/arbitrator/prover/src/host.rs @@ -405,7 +405,7 @@ impl Hostio { } } -pub fn get_impl(module: &str, name: &str) -> Result<(Function, bool)> { +pub fn get_impl(module: &str, name: &str) -> Result { let hostio: Hostio = format!("{module}__{name}").parse()?; let append = |code: &mut Vec| { @@ -414,8 +414,11 @@ pub fn get_impl(module: &str, name: &str) -> Result<(Function, bool)> { Ok(()) }; - let debug = module == "console" || module == "debug"; - Function::new(&[], append, hostio.ty(), &[]).map(|x| (x, debug)) + Function::new(&[], append, hostio.ty(), &[]) +} + +pub fn hostio_module_is_debug(module: &str) -> bool { + module == "console" || module == "debug" } /// Adds internal functions to a module. diff --git a/arbitrator/prover/src/lib.rs b/arbitrator/prover/src/lib.rs index 08473c2598..51040748e6 100644 --- a/arbitrator/prover/src/lib.rs +++ b/arbitrator/prover/src/lib.rs @@ -72,10 +72,16 @@ pub unsafe extern "C" fn arbitrator_load_machine( library_paths: *const *const c_char, library_paths_size: isize, debug_chain: usize, + with_forwarder: bool, ) -> *mut Machine { let debug_chain = debug_chain != 0; - match arbitrator_load_machine_impl(binary_path, library_paths, library_paths_size, debug_chain) - { + match arbitrator_load_machine_impl( + binary_path, + library_paths, + library_paths_size, + debug_chain, + with_forwarder, + ) { Ok(mach) => mach, Err(err) => { eprintln!("Error loading binary: {:?}", err); @@ -89,6 +95,7 @@ unsafe fn arbitrator_load_machine_impl( library_paths: *const *const c_char, library_paths_size: isize, debug_chain: bool, + with_forwarder: bool, ) -> Result<*mut Machine> { let binary_path = cstr_to_string(binary_path); let binary_path = Path::new(&binary_path); @@ -109,6 +116,7 @@ unsafe fn arbitrator_load_machine_impl( Default::default(), Default::default(), get_empty_preimage_resolver(), + with_forwarder, )?; Ok(Box::into_raw(Box::new(mach))) } diff --git a/arbitrator/prover/src/machine.rs b/arbitrator/prover/src/machine.rs index 358876bd25..2418d3cc2e 100644 --- a/arbitrator/prover/src/machine.rs +++ b/arbitrator/prover/src/machine.rs @@ -19,7 +19,7 @@ use crate::{ IBinOpType, IRelOpType, IUnOpType, Instruction, Opcode, }, }; -use arbutil::{crypto, math, Bytes32, Color, DebugColor, PreimageType}; +use arbutil::{crypto, hostios::HOSTIOS, math, Bytes32, Color, DebugColor, PreimageType}; use brotli::Dictionary; #[cfg(feature = "native")] use c_kzg::BYTES_PER_BLOB; @@ -330,36 +330,115 @@ pub struct Module { pub(crate) extra_hash: Arc, } +#[cfg(feature = "native")] +static FORWARDER_WASM: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/forwarder.wasm")); + lazy_static! { static ref USER_IMPORTS: HashMap = { let mut imports = HashMap::default(); - let forward = include_bytes!("../../../target/machines/latest/forward_stub.wasm"); - let forward = binary::parse(forward, Path::new("forward")).unwrap(); - - for (name, &(export, kind)) in &forward.exports { - if kind == ExportKind::Func { - let ty = match forward.get_function(FunctionIndex::from_u32(export)) { - Ok(ty) => ty, - Err(error) => panic!("failed to read export {name}: {error:?}"), - }; - let import = AvailableImport::new(ty, 1, export); - imports.insert(name.to_owned(), import); - } + // 0-513 are internal + for (index, (name, ins, outs)) in HOSTIOS.iter().enumerate() { + let import = AvailableImport::new(FunctionType::new(ins.iter().map(|x|x.into()).collect::>(), outs.iter().map(|x|x.into()).collect::>()), 1, (index + 514).try_into().unwrap()); + imports.insert(format!("vm_hooks__{name}"), import); } imports }; } +trait ImportResolver: for<'a, 'b> Fn(&'a str, &'b str) -> Result + Sized { + fn compose(self, other: impl ImportResolver) -> impl ImportResolver { + move |module, name| { + self(module, name).or_else(|original_err| { + let mut result = other(module, name); + if result.is_err() { + for err_layer in original_err.chain().rev() { + result = result.wrap_err(format!("{err_layer}")); + } + } + result + }) + } + } + + fn condition(self, condition: bool) -> impl ImportResolver { + move |module, name| { + if condition { + self(module, name) + } else { + bail!("resolver disabled") + } + } + } +} + +impl Fn(&'a str, &'b str) -> Result> ImportResolver for F {} + impl Module { - const FORWARDING_PREFIX: &'static str = "arbitrator_forward__"; + fn make_imports_resolver( + import_map: &HashMap, + ) -> impl ImportResolver + '_ { + move |module, name| { + let qualified_name = format!("{module}__{name}"); + + let Some(import) = import_map.get(&qualified_name) else { + bail!("func not found {module} {name}") + }; + let wavm = vec![ + Instruction::simple(Opcode::InitFrame), + Instruction::with_data( + Opcode::CrossModuleCall, + pack_cross_module_call(import.module, import.func), + ), + Instruction::simple(Opcode::Return), + ]; + Ok(Function::new_from_wavm(wavm, import.ty.clone(), vec![])) + } + } + + fn make_forward_resolver( + import_map: &HashMap, + ) -> impl ImportResolver + '_ { + move |module, name| { + let qualified_name = format!("{module}__{name}"); + + let Some(import) = import_map.get(&qualified_name) else { + bail!("func not found {module} {name}") + }; + let wavm = vec![ + Instruction::simple(Opcode::InitFrame), + Instruction::with_data( + Opcode::CrossModuleForward, + pack_cross_module_call(import.module, import.func), + ), + Instruction::simple(Opcode::Return), + ]; + Ok(Function::new_from_wavm(wavm, import.ty.clone(), vec![])) + } + } + + fn hostio_resolver(module: &str, name: &str) -> Result { + if host::hostio_module_is_debug(module) { + return Self::notfound_resolver(module, name); + } + host::get_impl(module, name) + } + + fn debug_resolver(module: &str, name: &str) -> Result { + if !host::hostio_module_is_debug(module) { + return Self::notfound_resolver(module, name); + } + host::get_impl(module, name) + } + + fn notfound_resolver(module: &str, name: &str) -> Result { + bail!("import not found {module} {name}") + } - fn from_binary( + fn from_binary( bin: &WasmBinary, - available_imports: &HashMap, + import_resolver: R, floating_point_impls: &FloatingPointImpls, - allow_hostapi: bool, - debug_funcs: bool, stylus_data: Option, ) -> Result { let mut code = Vec::new(); @@ -371,53 +450,18 @@ impl Module { for import in &bin.imports { let module = import.module; let have_ty = &bin.types[import.offset as usize]; - let (forward, import_name) = match import.name.strip_prefix(Module::FORWARDING_PREFIX) { - Some(name) => (true, name), - None => (false, import.name), - }; - let mut qualified_name = format!("{module}__{import_name}"); - qualified_name = qualified_name.replace(&['/', '.', '-'] as &[char], "_"); + let func = import_resolver(import.module, import.name)?; - let func = if let Some(import) = available_imports.get(&qualified_name) { - let call = match forward { - true => Opcode::CrossModuleForward, - false => Opcode::CrossModuleCall, - }; - let wavm = vec![ - Instruction::simple(Opcode::InitFrame), - Instruction::with_data( - call, - pack_cross_module_call(import.module, import.func), - ), - Instruction::simple(Opcode::Return), - ]; - Function::new_from_wavm(wavm, import.ty.clone(), vec![]) - } else if let Ok((hostio, debug)) = host::get_impl(import.module, import_name) { - ensure!( - (debug && debug_funcs) || (!debug && allow_hostapi), - "Host func {} in {} not enabled debug_funcs={debug_funcs} hostapi={allow_hostapi} debug={debug}", - import_name.red(), - import.module.red(), - ); - hostio - } else { - bail!( - "No such import {} in {} for {}", - import_name.red(), - import.module.red(), - bin_name.red() - ) - }; ensure!( &func.ty == have_ty, "Import {} for {} has different function signature than export.\nexpected {} in {}\nbut have {}", - import_name.red(), bin_name.red(), func.ty.red(), module.red(), have_ty.red(), + import.name.red(), bin_name.red(), func.ty.red(), module.red(), have_ty.red(), ); func_type_idxs.push(import.offset); code.push(func); - host_call_hooks.push(Some((import.module.into(), import_name.into()))); + host_call_hooks.push(Some((import.module.into(), import.name.into()))); } func_type_idxs.extend(bin.functions.iter()); @@ -613,10 +657,9 @@ impl Module { ) -> Result { Self::from_binary( bin, - &USER_IMPORTS, + Module::make_imports_resolver(&USER_IMPORTS) + .compose(Module::debug_resolver.condition(debug_funcs)), &HashMap::default(), - false, - debug_funcs, stylus_data, ) } @@ -1227,6 +1270,7 @@ impl Machine { global_state: GlobalState, inbox_contents: HashMap<(InboxIdentifier, u64), Vec>, preimage_resolver: PreimageResolver, + with_forwarder: bool, ) -> Result { let bin_source = file_bytes(binary_path)?; let bin = parse(&bin_source, binary_path) @@ -1252,6 +1296,7 @@ impl Machine { inbox_contents, preimage_resolver, None, + with_forwarder, ) } @@ -1281,6 +1326,7 @@ impl Machine { HashMap::default(), Arc::new(|_, _, _| panic!("tried to read preimage")), Some(stylus_data), + false, )?; let footprint: u32 = stylus_data.footprint.into(); @@ -1328,6 +1374,7 @@ impl Machine { inbox_contents: HashMap<(InboxIdentifier, u64), Vec>, preimage_resolver: PreimageResolver, stylus_data: Option, + with_forwarder: bool, ) -> Result { use ArbValueType::*; @@ -1335,25 +1382,19 @@ impl Machine { let mut modules = vec![Module::default()]; let mut available_imports = HashMap::default(); let mut floating_point_impls = HashMap::default(); - let main_module_index = u32::try_from(modules.len() + libraries.len())?; - - // make the main module's exports available to libraries - for (name, &(export, kind)) in &bin.exports { - if kind == ExportKind::Func { - let index: usize = export.try_into()?; - if let Some(index) = index.checked_sub(bin.imports.len()) { - let ty: usize = bin.functions[index].try_into()?; - let ty = bin.types[ty].clone(); - available_imports.insert( - format!("env__wavm_guest_call__{name}"), - AvailableImport::new(ty, main_module_index, export), - ); - } - } - } + + let forwarder = if with_forwarder { + #[cfg(not(feature = "native"))] + bail!("forwarder not supported without native"); + + #[cfg(feature = "native")] + Some(parse(FORWARDER_WASM, Path::new("forwarder"))?) + } else { + None + }; // collect all the library exports in advance so they can use each other's - for (index, lib) in libraries.iter().enumerate() { + for (index, lib) in forwarder.iter().chain(libraries.iter()).enumerate() { let module = 1 + index as u32; // off by one due to the entry point for (name, &(export, kind)) in &lib.exports { if kind == ExportKind::Func { @@ -1361,54 +1402,57 @@ impl Machine { Ok(ty) => ty, Err(error) => bail!("failed to read export {name}: {error}"), }; - let import = AvailableImport::new(ty, module, export); + let import = AvailableImport::new(ty.clone(), module, export); available_imports.insert(name.to_owned(), import); + if let Ok(op) = name.parse::() { + let mut sig = op.signature(); + // wavm codegen takes care of effecting this type change at callsites + for ty in sig.inputs.iter_mut().chain(sig.outputs.iter_mut()) { + if *ty == F32 { + *ty = I32; + } else if *ty == F64 { + *ty = I64; + } + } + ensure!( + ty == sig, + "Wrong type for floating point impl {} expecting {} but got {}", + name.red(), + sig.red(), + ty.red() + ); + floating_point_impls.insert(op, (module, export)); + } } } } - for lib in libraries { - let module = Module::from_binary( + if let Some(lib) = forwarder { + modules.push(Module::from_binary( + &lib, + Module::make_forward_resolver(&available_imports), + &floating_point_impls, + None, + )?); + } + + for lib in libraries.iter() { + modules.push(Module::from_binary( lib, - &available_imports, + Module::hostio_resolver + .compose(Module::debug_resolver.condition(debug_funcs)) + .compose(Module::make_imports_resolver(&available_imports)), &floating_point_impls, - true, - debug_funcs, None, - )?; - for (name, &func) in &*module.func_exports { - let ty = module.func_types[func as usize].clone(); - if let Ok(op) = name.parse::() { - let mut sig = op.signature(); - // wavm codegen takes care of effecting this type change at callsites - for ty in sig.inputs.iter_mut().chain(sig.outputs.iter_mut()) { - if *ty == F32 { - *ty = I32; - } else if *ty == F64 { - *ty = I64; - } - } - ensure!( - ty == sig, - "Wrong type for floating point impl {} expecting {} but got {}", - name.red(), - sig.red(), - ty.red() - ); - floating_point_impls.insert(op, (modules.len() as u32, func)); - } - } - modules.push(module); + )?); } - // Shouldn't be necessary, but to be safe, don't allow the main binary to import its own guest calls - available_imports.retain(|_, i| i.module as usize != modules.len()); modules.push(Module::from_binary( &bin, - &available_imports, + Module::make_imports_resolver(&available_imports) + .compose(Module::hostio_resolver.condition(allow_hostapi_from_main)) + .compose(Module::debug_resolver.condition(debug_funcs)), &floating_point_impls, - allow_hostapi_from_main, - debug_funcs, stylus_data, )?); diff --git a/arbitrator/prover/src/main.rs b/arbitrator/prover/src/main.rs index 8c90ee44a4..9949810bbe 100644 --- a/arbitrator/prover/src/main.rs +++ b/arbitrator/prover/src/main.rs @@ -87,7 +87,9 @@ struct Opts { skip_until_host_io: bool, #[structopt(long)] max_steps: Option, - // JSON inputs are supercede any of the command-line inputs which could + #[structopt(short, long)] + with_forwarder: bool, + // JSON inputs supercede any of the command-line inputs which could // be specified in the JSON file. #[structopt(long)] json_inputs: Option, @@ -560,6 +562,7 @@ fn initialize_machine(opts: &Opts) -> eyre::Result { global_state, inbox_contents, preimage_resolver, + opts.with_forwarder, ) } } diff --git a/arbitrator/prover/src/test.rs b/arbitrator/prover/src/test.rs index 97170441ff..2f32aff012 100644 --- a/arbitrator/prover/src/test.rs +++ b/arbitrator/prover/src/test.rs @@ -57,7 +57,7 @@ pub fn reject_ambiguous_imports() { #[test] pub fn test_compress() -> Result<()> { - let data = include_bytes!("../../../target/machines/latest/forward_stub.wasm"); + let data = include_bytes!(concat!(env!("OUT_DIR"), "/forwarder.wasm")); let mut last = vec![]; for dict in [Dictionary::Empty, Dictionary::StylusProgram] { diff --git a/arbitrator/prover/src/value.rs b/arbitrator/prover/src/value.rs index 6afffdf7a0..f2f54404f0 100644 --- a/arbitrator/prover/src/value.rs +++ b/arbitrator/prover/src/value.rs @@ -2,7 +2,7 @@ // For license information, see https://github.com/nitro/blob/master/LICENSE use crate::binary::FloatType; -use arbutil::{Bytes32, Color}; +use arbutil::{hostios::ParamType, Bytes32, Color}; use digest::Digest; use eyre::{bail, ErrReport, Result}; use serde::{Deserialize, Serialize}; @@ -77,6 +77,16 @@ impl From for ValType { } } +impl From<&ParamType> for ArbValueType { + fn from(ty: &ParamType) -> Self { + use ParamType as V; + match ty { + V::I32 => Self::I32, + V::I64 => Self::I64, + } + } +} + #[cfg(feature = "native")] pub fn parser_type(ty: &wasmer::Type) -> wasmer::wasmparser::ValType { match ty { diff --git a/arbitrator/prover/test-cases/forward-test.wat b/arbitrator/prover/test-cases/forward-test.wat deleted file mode 100644 index b9beff0d82..0000000000 --- a/arbitrator/prover/test-cases/forward-test.wat +++ /dev/null @@ -1,32 +0,0 @@ - -(module - (import "forward" "add" (func $add (param i32 i32) (result i32))) - (import "forward" "sub" (func $sub (param i32 i32) (result i32))) - (import "forward" "mul" (func $mul (param i32 i32) (result i32))) - (func $start - ;; this address will update each time a forwarded call is made - i32.const 0xa4b - i32.const 805 - i32.store - - i32.const 11 - i32.const 5 - call $sub - - i32.const 3 - i32.const -2 - call $mul - - call $add - (if - (then (unreachable))) - - ;; check that the address has changed - i32.const 0xa4b - i32.load - i32.const 808 - i32.ne - (if - (then (unreachable)))) - (start $start) - (memory 1)) diff --git a/arbitrator/prover/test-cases/forward/forward.wat b/arbitrator/prover/test-cases/forward/forward.wat deleted file mode 100644 index ff55953e62..0000000000 --- a/arbitrator/prover/test-cases/forward/forward.wat +++ /dev/null @@ -1,8 +0,0 @@ - -(module - (import "target" "arbitrator_forward__add" (func $add (param i32 i32) (result i32))) - (import "target" "arbitrator_forward__sub" (func $sub (param i32 i32) (result i32))) - (import "target" "arbitrator_forward__mul" (func $mul (param i32 i32) (result i32))) - (export "forward__add" (func $add)) - (export "forward__sub" (func $sub)) - (export "forward__mul" (func $mul))) diff --git a/arbitrator/prover/test-cases/forward/target.wat b/arbitrator/prover/test-cases/forward/target.wat deleted file mode 100644 index 0779eb753d..0000000000 --- a/arbitrator/prover/test-cases/forward/target.wat +++ /dev/null @@ -1,27 +0,0 @@ - -(module - (import "env" "wavm_caller_load8" (func $load (param i32) (result i32))) - (import "env" "wavm_caller_store8" (func $store (param i32 i32))) - (func (export "target__add") (param i32 i32) (result i32) - call $write_caller - local.get 0 - local.get 1 - i32.add) - (func (export "target__sub") (param i32 i32) (result i32) - call $write_caller - local.get 0 - local.get 1 - i32.sub) - (func (export "target__mul") (param i32 i32) (result i32) - call $write_caller - local.get 0 - local.get 1 - i32.mul) - (func $write_caller (export "write_caller") - ;; increment the value at address 0xa4b in the caller - i32.const 0xa4b - i32.const 0xa4b - call $load - i32.const 1 - i32.add - call $store)) diff --git a/arbitrator/stylus/src/test/mod.rs b/arbitrator/stylus/src/test/mod.rs index 00c9c62ae4..42c9446564 100644 --- a/arbitrator/stylus/src/test/mod.rs +++ b/arbitrator/stylus/src/test/mod.rs @@ -164,6 +164,7 @@ fn new_test_machine(path: &str, compile: &CompileConfig) -> Result { HashMap::default(), Arc::new(|_, _, _| panic!("tried to read preimage")), Some(stylus_data), + false, )?; mach.set_ink(u64::MAX); mach.set_stack(u32::MAX); diff --git a/arbitrator/stylus/tests/erc20/Cargo.lock b/arbitrator/stylus/tests/erc20/Cargo.lock index c3e215978d..f5e1e0b15e 100644 --- a/arbitrator/stylus/tests/erc20/Cargo.lock +++ b/arbitrator/stylus/tests/erc20/Cargo.lock @@ -575,9 +575,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.23" +version = "0.37.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" +checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" dependencies = [ "bitflags", "errno", diff --git a/arbitrator/tools/module_roots/src/main.rs b/arbitrator/tools/module_roots/src/main.rs index 32e4764847..fc22bed5fa 100644 --- a/arbitrator/tools/module_roots/src/main.rs +++ b/arbitrator/tools/module_roots/src/main.rs @@ -39,6 +39,7 @@ fn main() -> Result<()> { GlobalState::default(), HashMap::default(), Arc::new(|_, _, _| panic!("tried to read preimage")), + false, )?; let mut stylus = vec![]; diff --git a/arbitrator/wasm-libraries/Cargo.lock b/arbitrator/wasm-libraries/Cargo.lock index 630556c4fa..b234424f69 100644 --- a/arbitrator/wasm-libraries/Cargo.lock +++ b/arbitrator/wasm-libraries/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +dependencies = [ + "gimli 0.29.0", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "ahash" version = "0.7.8" @@ -31,21 +46,6 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - [[package]] name = "ansi_term" version = "0.12.1" @@ -107,10 +107,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] -name = "base64" -version = "0.22.1" +name = "backtrace" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +dependencies = [ + "addr2line", + "cc", + "cfg-if 1.0.0", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] [[package]] name = "bincode" @@ -208,6 +217,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.7.0" @@ -226,9 +241,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.7" +version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" +checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -242,19 +260,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "chrono" -version = "0.4.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "num-traits", - "serde", - "windows-targets", -] - [[package]] name = "clap" version = "2.34.0" @@ -277,10 +282,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] -name = "core-foundation-sys" -version = "0.8.6" +name = "corosensei" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "80128832c58ea9cbd041d2a759ec449224487b2c1e400453d99d244eead87a8e" +dependencies = [ + "autocfg", + "cfg-if 1.0.0", + "libc", + "scopeguard", + "windows-sys 0.33.0", +] [[package]] name = "cpufeatures" @@ -291,6 +303,123 @@ dependencies = [ "libc", ] +[[package]] +name = "cranelift-bforest" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2ab4512dfd3a6f4be184403a195f76e81a8a9f9e6c898e19d2dc3ce20e0115" +dependencies = [ + "cranelift-entity", +] + +[[package]] +name = "cranelift-codegen" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98b022ed2a5913a38839dfbafe6cf135342661293b08049843362df4301261dc" +dependencies = [ + "arrayvec", + "bumpalo", + "cranelift-bforest", + "cranelift-codegen-meta", + "cranelift-codegen-shared", + "cranelift-egraph", + "cranelift-entity", + "cranelift-isle", + "gimli 0.26.2", + "log", + "regalloc2", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "639307b45434ad112a98f8300c0f0ab085cbefcd767efcdef9ef19d4c0756e74" +dependencies = [ + "cranelift-codegen-shared", +] + +[[package]] +name = "cranelift-codegen-shared" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "278e52e29c53fcf32431ef08406c295699a70306d05a0715c5b1bf50e33a9ab7" + +[[package]] +name = "cranelift-egraph" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624b54323b06e675293939311943ba82d323bb340468ce1889be5da7932c8d73" +dependencies = [ + "cranelift-entity", + "fxhash", + "hashbrown 0.12.3", + "indexmap 1.9.3", + "log", + "smallvec", +] + +[[package]] +name = "cranelift-entity" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a59bcbca89c3f1b70b93ab3cbba5e5e0cbf3e63dadb23c7525cb142e21a9d4c" + +[[package]] +name = "cranelift-frontend" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d70abacb8cfef3dc8ff7e8836e9c1d70f7967dfdac824a4cd5e30223415aca6" +dependencies = [ + "cranelift-codegen", + "log", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-isle" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "393bc73c451830ff8dbb3a07f61843d6cb41a084f9996319917c0b291ed785bb" + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + [[package]] name = "crunchy" version = "0.2.2" @@ -307,14 +436,38 @@ dependencies = [ "typenum", ] +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core 0.13.4", + "darling_macro 0.13.4", +] + [[package]] name = "darling" version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.20.10", + "darling_macro 0.20.10", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn 1.0.109", ] [[package]] @@ -327,29 +480,42 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim 0.11.1", "syn 2.0.72", ] +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core 0.13.4", + "quote", + "syn 1.0.109", +] + [[package]] name = "darling_macro" version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ - "darling_core", + "darling_core 0.20.10", "quote", "syn 2.0.72", ] [[package]] -name = "deranged" -version = "0.3.11" +name = "dashmap" +version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ - "powerfmt", - "serde", + "cfg-if 1.0.0", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", ] [[package]] @@ -456,7 +622,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59c3b24c345d8c314966bdc1832f6c2635bfcce8e7cf363bd115987bba2ee242" dependencies = [ - "darling", + "darling 0.20.10", "proc-macro2", "quote", "syn 2.0.72", @@ -478,26 +644,33 @@ dependencies = [ "once_cell", ] +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "forward" -version = "0.1.0" -dependencies = [ - "eyre", - "structopt", -] - [[package]] name = "funty" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -519,6 +692,23 @@ dependencies = [ "wasi", ] +[[package]] +name = "gimli" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" +dependencies = [ + "fallible-iterator", + "indexmap 1.9.3", + "stable_deref_trait", +] + +[[package]] +name = "gimli" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" + [[package]] name = "hashbrown" version = "0.12.3" @@ -570,29 +760,6 @@ dependencies = [ "caller-env", ] -[[package]] -name = "iana-time-zone" -version = "0.1.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - [[package]] name = "ident_case" version = "1.0.1" @@ -613,7 +780,6 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", - "serde", ] [[package]] @@ -624,7 +790,6 @@ checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" dependencies = [ "equivalent", "hashbrown 0.14.5", - "serde", ] [[package]] @@ -644,9 +809,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ "wasm-bindgen", ] @@ -703,12 +868,57 @@ dependencies = [ "hashbrown 0.14.5", ] +[[package]] +name = "mach" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +dependencies = [ + "libc", +] + +[[package]] +name = "mach2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +dependencies = [ + "libc", +] + [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "memmap2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d28bba84adfe6646737845bc5ebbfa2c08424eb1c37e94a1fd2a82adb56a872" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + [[package]] name = "memory_units" version = "0.4.0" @@ -721,6 +931,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", +] + [[package]] name = "more-asserts" version = "0.2.2" @@ -781,12 +1000,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - [[package]] name = "num-derive" version = "0.4.2" @@ -859,6 +1072,15 @@ dependencies = [ "syn 2.0.72", ] +[[package]] +name = "object" +version = "0.36.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.19.0" @@ -901,10 +1123,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] -name = "powerfmt" -version = "0.2.0" +name = "pin-project-lite" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "proc-macro-crate" @@ -986,6 +1208,7 @@ dependencies = [ "smallvec", "static_assertions", "structopt", + "wasmer", "wasmer-types", "wasmparser", "wat", @@ -1050,6 +1273,26 @@ dependencies = [ "rand_core", ] +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" version = "0.5.3" @@ -1059,6 +1302,30 @@ dependencies = [ "bitflags 2.6.0", ] +[[package]] +name = "regalloc2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300d4fbfb40c1c66a78ba3ddd41c1110247cf52f97b87d0f2fc9209bd49b030c" +dependencies = [ + "fxhash", + "log", + "slice-group-by", + "smallvec", +] + +[[package]] +name = "region" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6b6ebd13bc009aef9cd476c1310d49ac354d36e240cf1bd753290f3dc7199a7" +dependencies = [ + "bitflags 1.3.2", + "libc", + "mach2", + "windows-sys 0.52.0", +] + [[package]] name = "rend" version = "0.4.2" @@ -1149,6 +1416,12 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" +[[package]] +name = "self_cell" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" + [[package]] name = "semver" version = "1.0.23" @@ -1164,6 +1437,17 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-wasm-bindgen" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + [[package]] name = "serde_derive" version = "1.0.204" @@ -1189,32 +1473,24 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.9.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" +checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" dependencies = [ - "base64", - "chrono", - "hex", - "indexmap 1.9.3", - "indexmap 2.3.0", "serde", - "serde_derive", - "serde_json", "serde_with_macros", - "time", ] [[package]] name = "serde_with_macros" -version = "3.9.0" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" +checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" dependencies = [ - "darling", + "darling 0.13.4", "proc-macro2", "quote", - "syn 2.0.72", + "syn 1.0.109", ] [[package]] @@ -1263,6 +1539,22 @@ dependencies = [ "keccak", ] +[[package]] +name = "shared-buffer" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6c99835bad52957e7aa241d3975ed17c1e5f8c92026377d117a606f36b84b16" +dependencies = [ + "bytes", + "memmap2 0.6.2", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "simdutf8" version = "0.1.4" @@ -1275,6 +1567,12 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +[[package]] +name = "slice-group-by" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" + [[package]] name = "smallvec" version = "1.13.2" @@ -1284,6 +1582,12 @@ dependencies = [ "serde", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "static_assertions" version = "1.1.0" @@ -1298,9 +1602,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "strsim" -version = "0.11.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "structopt" @@ -1389,37 +1693,6 @@ dependencies = [ "syn 2.0.72", ] -[[package]] -name = "time" -version = "0.3.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" -dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - -[[package]] -name = "time-macros" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" -dependencies = [ - "num-conv", - "time-core", -] - [[package]] name = "tiny-keccak" version = "2.0.2" @@ -1461,6 +1734,37 @@ dependencies = [ "winnow", ] +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + [[package]] name = "typenum" version = "1.17.0" @@ -1560,19 +1864,20 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if 1.0.0", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", @@ -1585,9 +1890,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1595,9 +1900,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", @@ -1608,19 +1913,98 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "wasm-encoder" -version = "0.215.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb56df3e06b8e6b77e37d2969a50ba51281029a9aeb3855e76b7f49b6418847" +checksum = "1ba64e81215916eaeb48fee292f29401d69235d62d8b8fd92a7b2844ec5ae5f7" dependencies = [ "leb128", ] +[[package]] +name = "wasmer" +version = "4.2.8" +dependencies = [ + "bytes", + "cfg-if 1.0.0", + "derivative", + "indexmap 1.9.3", + "js-sys", + "more-asserts", + "rustc-demangle", + "serde", + "serde-wasm-bindgen", + "shared-buffer", + "target-lexicon", + "thiserror", + "tracing", + "wasm-bindgen", + "wasmer-compiler", + "wasmer-compiler-cranelift", + "wasmer-derive", + "wasmer-types", + "wasmer-vm", + "wat", + "winapi", +] + +[[package]] +name = "wasmer-compiler" +version = "4.2.8" +dependencies = [ + "backtrace", + "bytes", + "cfg-if 1.0.0", + "enum-iterator 0.7.0", + "enumset", + "lazy_static", + "leb128", + "memmap2 0.5.10", + "more-asserts", + "region", + "rkyv", + "self_cell", + "shared-buffer", + "smallvec", + "thiserror", + "wasmer-types", + "wasmer-vm", + "wasmparser", + "winapi", +] + +[[package]] +name = "wasmer-compiler-cranelift" +version = "4.2.8" +dependencies = [ + "cranelift-codegen", + "cranelift-entity", + "cranelift-frontend", + "gimli 0.26.2", + "more-asserts", + "rayon", + "smallvec", + "target-lexicon", + "tracing", + "wasmer-compiler", + "wasmer-types", +] + +[[package]] +name = "wasmer-derive" +version = "4.2.8" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "wasmer-types" version = "4.2.8" @@ -1635,6 +2019,32 @@ dependencies = [ "thiserror", ] +[[package]] +name = "wasmer-vm" +version = "4.2.8" +dependencies = [ + "backtrace", + "cc", + "cfg-if 1.0.0", + "corosensei", + "crossbeam-queue", + "dashmap", + "derivative", + "enum-iterator 0.7.0", + "fnv", + "indexmap 1.9.3", + "lazy_static", + "libc", + "mach", + "memoffset", + "more-asserts", + "region", + "scopeguard", + "thiserror", + "wasmer-types", + "winapi", +] + [[package]] name = "wasmparser" version = "0.121.2" @@ -1648,11 +2058,10 @@ dependencies = [ [[package]] name = "wast" -version = "215.0.0" +version = "64.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ff1d00d893593249e60720be04a7c1f42f1c4dc3806a2869f4e66ab61eb54cb" +checksum = "a259b226fd6910225aa7baeba82f9d9933b6d00f2ce1b49b80fa4214328237cc" dependencies = [ - "bumpalo", "leb128", "memchr", "unicode-width", @@ -1661,9 +2070,9 @@ dependencies = [ [[package]] name = "wat" -version = "1.215.0" +version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670bf4d9c8cf76ae242d70ded47c546525b6dafaa6871f9bcb065344bf2b4e3d" +checksum = "53253d920ab413fca1c7dc2161d601c79b4fdf631d0ba51dd4343bf9b556c3f6" dependencies = [ "wast", ] @@ -1703,10 +2112,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows-core" +name = "windows-sys" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43dbb096663629518eb1dfa72d80243ca5a6aca764cae62a2df70af760a9be75" +dependencies = [ + "windows_aarch64_msvc 0.33.0", + "windows_i686_gnu 0.33.0", + "windows_i686_msvc 0.33.0", + "windows_x86_64_gnu 0.33.0", + "windows_x86_64_msvc 0.33.0", +] + +[[package]] +name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ "windows-targets", ] @@ -1718,13 +2140,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -1733,12 +2155,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd761fd3eb9ab8cc1ed81e56e567f02dd82c4c837e48ac3b2181b9ffc5060807" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_i686_gnu" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab0cf703a96bab2dc0c02c0fa748491294bf9b7feb27e1f4f96340f208ada0e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -1751,12 +2185,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_msvc" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cfdbe89cc9ad7ce618ba34abc34bbb6c36d99e96cae2245b7943cd75ee773d0" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_x86_64_gnu" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4dd9b0c0e9ece7bb22e84d70d01b71c6d6248b81a3c60d11869451b4cb24784" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -1769,6 +2215,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_msvc" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff1e4aa646495048ec7f3ffddc411e1d829c026a2ec62b39da15c1055e406eaa" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" diff --git a/arbitrator/wasm-libraries/Cargo.toml b/arbitrator/wasm-libraries/Cargo.toml index 837df8f4da..2fd585ee7d 100644 --- a/arbitrator/wasm-libraries/Cargo.toml +++ b/arbitrator/wasm-libraries/Cargo.toml @@ -7,6 +7,5 @@ members = [ "user-host-trait", "user-test", "program-exec", - "forward", ] resolver = "2" diff --git a/arbitrator/wasm-libraries/forward/.gitignore b/arbitrator/wasm-libraries/forward/.gitignore deleted file mode 100644 index 40da2042b7..0000000000 --- a/arbitrator/wasm-libraries/forward/.gitignore +++ /dev/null @@ -1 +0,0 @@ -**.wat diff --git a/arbitrator/wasm-libraries/forward/Cargo.toml b/arbitrator/wasm-libraries/forward/Cargo.toml deleted file mode 100644 index 73ed9d8827..0000000000 --- a/arbitrator/wasm-libraries/forward/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "forward" -version = "0.1.0" -edition = "2021" - -[dependencies] -eyre = "0.6.5" -structopt = "0.3.26" diff --git a/arbitrator/wasm-libraries/forward/src/main.rs b/arbitrator/wasm-libraries/forward/src/main.rs deleted file mode 100644 index 05a949e8aa..0000000000 --- a/arbitrator/wasm-libraries/forward/src/main.rs +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright 2022-2024, Offchain Labs, Inc. -// For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE - -use eyre::Result; -use std::{fs::File, io::Write, path::PathBuf}; -use structopt::StructOpt; - -/// order matters! -const HOSTIOS: [[&str; 3]; 42] = [ - ["read_args", "i32", ""], - ["write_result", "i32 i32", ""], - ["exit_early", "i32", ""], - ["storage_load_bytes32", "i32 i32", ""], - ["storage_cache_bytes32", "i32 i32", ""], - ["storage_flush_cache", "i32", ""], - ["transient_load_bytes32", "i32 i32", ""], - ["transient_store_bytes32", "i32 i32", ""], - ["call_contract", "i32 i32 i32 i32 i64 i32", "i32"], - ["delegate_call_contract", "i32 i32 i32 i64 i32", "i32"], - ["static_call_contract", "i32 i32 i32 i64 i32", "i32"], - ["create1", "i32 i32 i32 i32 i32", ""], - ["create2", "i32 i32 i32 i32 i32 i32", ""], - ["read_return_data", "i32 i32 i32", "i32"], - ["return_data_size", "", "i32"], - ["emit_log", "i32 i32 i32", ""], - ["account_balance", "i32 i32", ""], - ["account_code", "i32 i32 i32 i32", "i32"], - ["account_code_size", "i32", "i32"], - ["account_codehash", "i32 i32", ""], - ["evm_gas_left", "", "i64"], - ["evm_ink_left", "", "i64"], - ["block_basefee", "i32", ""], - ["chainid", "", "i64"], - ["block_coinbase", "i32", ""], - ["block_gas_limit", "", "i64"], - ["block_number", "", "i64"], - ["block_timestamp", "", "i64"], - ["contract_address", "i32", ""], - ["math_div", "i32 i32", ""], - ["math_mod", "i32 i32", ""], - ["math_pow", "i32 i32", ""], - ["math_add_mod", "i32 i32 i32", ""], - ["math_mul_mod", "i32 i32 i32", ""], - ["msg_reentrant", "", "i32"], - ["msg_sender", "i32", ""], - ["msg_value", "i32", ""], - ["native_keccak256", "i32 i32 i32", ""], - ["tx_gas_price", "i32", ""], - ["tx_ink_price", "", "i32"], - ["tx_origin", "i32", ""], - ["pay_for_memory_grow", "i32", ""], -]; - -#[derive(StructOpt)] -#[structopt(name = "arbitrator-prover")] -struct Opts { - #[structopt(long)] - path: PathBuf, - #[structopt(long)] - stub: bool, -} - -fn main() -> Result<()> { - let opts = Opts::from_args(); - let file = &mut File::options() - .create(true) - .write(true) - .truncate(true) - .open(opts.path)?; - - match opts.stub { - true => forward_stub(file), - false => forward(file), - } -} - -fn forward(file: &mut File) -> Result<()> { - macro_rules! wln { - ($($text:tt)*) => { - writeln!(file, $($text)*)?; - }; - } - let s = " "; - - wln!( - ";; Copyright 2022-2023, Offchain Labs, Inc.\n\ - ;; For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE\n\ - ;; This file is auto-generated.\n\ - \n\ - (module" - ); - - macro_rules! group { - ($list:expr, $kind:expr) => { - (!$list.is_empty()) - .then(|| format!(" ({} {})", $kind, $list)) - .unwrap_or_default() - }; - } - - wln!("{s};; symbols to re-export"); - for [name, ins, outs] in HOSTIOS { - let params = group!(ins, "param"); - let result = group!(outs, "result"); - wln!( - r#"{s}(import "user_host" "arbitrator_forward__{name}" (func ${name}{params}{result}))"# - ); - } - wln!(); - - wln!("{s};; reserved offsets for future user_host imports"); - for i in HOSTIOS.len()..512 { - wln!("{s}(func $reserved_{i} unreachable)"); - } - wln!(); - - wln!( - "{s};; allows user_host to request a trap\n\ - {s}(global $trap (mut i32) (i32.const 0))\n\ - {s}(func $check\n\ - {s}{s}global.get $trap ;; see if set\n\ - {s}{s}(global.set $trap (i32.const 0)) ;; reset the flag\n\ - {s}{s}(if (then (unreachable)))\n\ - {s})\n\ - {s}(func (export \"forward__set_trap\")\n\ - {s}{s}(global.set $trap (i32.const 1))\n\ - {s})\n" - ); - - wln!("{s};; user linkage"); - for [name, ins, outs] in HOSTIOS { - let params = group!(ins, "param"); - let result = group!(outs, "result"); - wln!("{s}(func (export \"vm_hooks__{name}\"){params}{result}"); - - let gets = (1 + ins.len()) / 4; - for i in 0..gets { - wln!("{s}{s}local.get {i}"); - } - - wln!( - "{s}{s}call ${name}\n\ - {s}{s}call $check\n\ - {s})" - ); - } - - wln!(")"); - Ok(()) -} - -fn forward_stub(file: &mut File) -> Result<()> { - macro_rules! wln { - ($($text:tt)*) => { - writeln!(file, $($text)*)?; - }; - } - let s = " "; - - wln!( - ";; Copyright 2022-2023, Offchain Labs, Inc.\n\ - ;; For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE\n\ - ;; This file is auto-generated.\n\ - \n\ - (module" - ); - - macro_rules! group { - ($list:expr, $kind:expr) => { - (!$list.is_empty()) - .then(|| format!(" ({} {})", $kind, $list)) - .unwrap_or_default() - }; - } - - wln!("{s};; stubs for the symbols we re-export"); - for [name, ins, outs] in HOSTIOS { - let params = group!(ins, "param"); - let result = group!(outs, "result"); - wln!("{s}(func ${name}{params}{result} unreachable)"); - } - wln!(); - - wln!("{s};; reserved offsets for future user_host imports"); - for i in HOSTIOS.len()..512 { - wln!("{s}(func $reserved_{i} unreachable)"); - } - wln!(); - - wln!( - "{s};; allows user_host to request a trap\n\ - {s}(global $trap (mut i32) (i32.const 0))\n\ - {s}(func $check unreachable)\n\ - {s}(func (export \"forward__set_trap\") unreachable)" - ); - - wln!("{s};; user linkage"); - for [name, ins, outs] in HOSTIOS { - let params = group!(ins, "param"); - let result = group!(outs, "result"); - wln!("{s}(func (export \"vm_hooks__{name}\"){params}{result} unreachable)"); - } - - wln!(")"); - Ok(()) -} diff --git a/arbitrator/wasm-testsuite/src/main.rs b/arbitrator/wasm-testsuite/src/main.rs index 2144dcf992..cb861e3a35 100644 --- a/arbitrator/wasm-testsuite/src/main.rs +++ b/arbitrator/wasm-testsuite/src/main.rs @@ -343,6 +343,7 @@ fn main() -> eyre::Result<()> { GlobalState::default(), HashMap::default(), machine::get_empty_preimage_resolver(), + false, ); if let Err(error) = &mech { @@ -429,6 +430,7 @@ fn main() -> eyre::Result<()> { GlobalState::default(), HashMap::default(), machine::get_empty_preimage_resolver(), + false, ) .expect_err(&format!("failed to reject invalid module {}", filename)); } diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 6b4b95f8e0..44b360e76e 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -168,7 +168,7 @@ type BatchPosterConfig struct { L1BlockBound string `koanf:"l1-block-bound" reload:"hot"` L1BlockBoundBypass time.Duration `koanf:"l1-block-bound-bypass" reload:"hot"` UseAccessLists bool `koanf:"use-access-lists" reload:"hot"` - GasEstimateBaseFeeMultipleBips arbmath.Bips `koanf:"gas-estimate-base-fee-multiple-bips"` + GasEstimateBaseFeeMultipleBips arbmath.UBips `koanf:"gas-estimate-base-fee-multiple-bips"` Dangerous BatchPosterDangerousConfig `koanf:"dangerous"` ReorgResistanceMargin time.Duration `koanf:"reorg-resistance-margin" reload:"hot"` CheckBatchCorrectness bool `koanf:"check-batch-correctness"` @@ -253,7 +253,7 @@ var DefaultBatchPosterConfig = BatchPosterConfig{ L1BlockBoundBypass: time.Hour, UseAccessLists: true, RedisLock: redislock.DefaultCfg, - GasEstimateBaseFeeMultipleBips: arbmath.OneInBips * 3 / 2, + GasEstimateBaseFeeMultipleBips: arbmath.OneInUBips * 3 / 2, ReorgResistanceMargin: 10 * time.Minute, CheckBatchCorrectness: true, } @@ -285,7 +285,7 @@ var TestBatchPosterConfig = BatchPosterConfig{ L1BlockBound: "", L1BlockBoundBypass: time.Hour, UseAccessLists: true, - GasEstimateBaseFeeMultipleBips: arbmath.OneInBips * 3 / 2, + GasEstimateBaseFeeMultipleBips: arbmath.OneInUBips * 3 / 2, CheckBatchCorrectness: true, } @@ -1035,7 +1035,7 @@ func (b *BatchPoster) estimateGas(ctx context.Context, sequencerMessage []byte, if err != nil { return 0, err } - maxFeePerGas := arbmath.BigMulByBips(latestHeader.BaseFee, config.GasEstimateBaseFeeMultipleBips) + maxFeePerGas := arbmath.BigMulByUBips(latestHeader.BaseFee, config.GasEstimateBaseFeeMultipleBips) if useNormalEstimation { _, realBlobHashes, err := blobs.ComputeCommitmentsAndHashes(realBlobs) if err != nil { @@ -1250,7 +1250,9 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) l1BoundMinTimestamp = arbmath.SaturatingUSub(latestHeader.Time, arbmath.BigToUintSaturating(maxTimeVariationDelaySeconds)) if config.L1BlockBoundBypass > 0 { + // #nosec G115 blockNumberWithPadding := arbmath.SaturatingUAdd(latestBlockNumber, uint64(config.L1BlockBoundBypass/ethPosBlockTime)) + // #nosec G115 timestampWithPadding := arbmath.SaturatingUAdd(latestHeader.Time, uint64(config.L1BlockBoundBypass/time.Second)) l1BoundMinBlockNumberWithBypass = arbmath.SaturatingUSub(blockNumberWithPadding, arbmath.BigToUintSaturating(maxTimeVariationDelayBlocks)) l1BoundMinTimestampWithBypass = arbmath.SaturatingUSub(timestampWithPadding, arbmath.BigToUintSaturating(maxTimeVariationDelaySeconds)) @@ -1316,7 +1318,9 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) if hasL1Bound && config.ReorgResistanceMargin > 0 { firstMsgBlockNumber := firstMsg.Message.Header.BlockNumber firstMsgTimeStamp := firstMsg.Message.Header.Timestamp + // #nosec G115 batchNearL1BoundMinBlockNumber := firstMsgBlockNumber <= arbmath.SaturatingUAdd(l1BoundMinBlockNumber, uint64(config.ReorgResistanceMargin/ethPosBlockTime)) + // #nosec G115 batchNearL1BoundMinTimestamp := firstMsgTimeStamp <= arbmath.SaturatingUAdd(l1BoundMinTimestamp, uint64(config.ReorgResistanceMargin/time.Second)) if batchNearL1BoundMinTimestamp || batchNearL1BoundMinBlockNumber { log.Error( @@ -1361,6 +1365,7 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) batchPosterDAFailureCounter.Inc(1) return false, fmt.Errorf("%w: nonce changed from %d to %d while creating batch", storage.ErrStorageRace, nonce, gotNonce) } + // #nosec G115 sequencerMsg, err = b.dapWriter.Store(ctx, sequencerMsg, uint64(time.Now().Add(config.DASRetentionPeriod).Unix()), config.DisableDapFallbackStoreDataOnChain) if err != nil { batchPosterDAFailureCounter.Inc(1) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 6a483929b2..31b9a983db 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -638,11 +638,11 @@ func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit u if config.MaxFeeBidMultipleBips > 0 { // Limit the fee caps to be no greater than max(MaxFeeBidMultipleBips, minRbf) - maxNonBlobFee := arbmath.BigMulByBips(currentNonBlobFee, config.MaxFeeBidMultipleBips) + maxNonBlobFee := arbmath.BigMulByUBips(currentNonBlobFee, config.MaxFeeBidMultipleBips) if lastTx != nil { maxNonBlobFee = arbmath.BigMax(maxNonBlobFee, arbmath.BigMulByBips(lastTx.GasFeeCap(), minRbfIncrease)) } - maxBlobFee := arbmath.BigMulByBips(currentBlobFee, config.MaxFeeBidMultipleBips) + maxBlobFee := arbmath.BigMulByUBips(currentBlobFee, config.MaxFeeBidMultipleBips) if lastTx != nil && lastTx.BlobGasFeeCap() != nil { maxBlobFee = arbmath.BigMax(maxBlobFee, arbmath.BigMulByBips(lastTx.BlobGasFeeCap(), minRbfIncrease)) } @@ -1241,7 +1241,7 @@ type DataPosterConfig struct { MinBlobTxTipCapGwei float64 `koanf:"min-blob-tx-tip-cap-gwei" reload:"hot"` MaxTipCapGwei float64 `koanf:"max-tip-cap-gwei" reload:"hot"` MaxBlobTxTipCapGwei float64 `koanf:"max-blob-tx-tip-cap-gwei" reload:"hot"` - MaxFeeBidMultipleBips arbmath.Bips `koanf:"max-fee-bid-multiple-bips" reload:"hot"` + MaxFeeBidMultipleBips arbmath.UBips `koanf:"max-fee-bid-multiple-bips" reload:"hot"` NonceRbfSoftConfs uint64 `koanf:"nonce-rbf-soft-confs" reload:"hot"` AllocateMempoolBalance bool `koanf:"allocate-mempool-balance" reload:"hot"` UseDBStorage bool `koanf:"use-db-storage"` @@ -1345,7 +1345,7 @@ var DefaultDataPosterConfig = DataPosterConfig{ MinBlobTxTipCapGwei: 1, // default geth minimum, and relays aren't likely to accept lower values given propagation time MaxTipCapGwei: 1.2, MaxBlobTxTipCapGwei: 1, // lower than normal because 4844 rbf is a minimum of a 2x - MaxFeeBidMultipleBips: arbmath.OneInBips * 10, + MaxFeeBidMultipleBips: arbmath.OneInUBips * 10, NonceRbfSoftConfs: 1, AllocateMempoolBalance: true, UseDBStorage: true, @@ -1380,7 +1380,7 @@ var TestDataPosterConfig = DataPosterConfig{ MinBlobTxTipCapGwei: 1, MaxTipCapGwei: 5, MaxBlobTxTipCapGwei: 1, - MaxFeeBidMultipleBips: arbmath.OneInBips * 10, + MaxFeeBidMultipleBips: arbmath.OneInUBips * 10, NonceRbfSoftConfs: 1, AllocateMempoolBalance: true, UseDBStorage: false, diff --git a/arbnode/dataposter/dataposter_test.go b/arbnode/dataposter/dataposter_test.go index 7f2f61c07e..d2c49427be 100644 --- a/arbnode/dataposter/dataposter_test.go +++ b/arbnode/dataposter/dataposter_test.go @@ -204,7 +204,7 @@ func TestFeeAndTipCaps_EnoughBalance_NoBacklog_NoUnconfirmed_BlobTx(t *testing.T MinBlobTxTipCapGwei: 1, MaxTipCapGwei: 5, MaxBlobTxTipCapGwei: 10, - MaxFeeBidMultipleBips: arbmath.OneInBips * 10, + MaxFeeBidMultipleBips: arbmath.OneInUBips * 10, AllocateMempoolBalance: true, UrgencyGwei: 2., @@ -335,7 +335,7 @@ func TestFeeAndTipCaps_RBF_RisingBlobFee_FallingBaseFee(t *testing.T) { MinBlobTxTipCapGwei: 1, MaxTipCapGwei: 5, MaxBlobTxTipCapGwei: 10, - MaxFeeBidMultipleBips: arbmath.OneInBips * 10, + MaxFeeBidMultipleBips: arbmath.OneInUBips * 10, AllocateMempoolBalance: true, UrgencyGwei: 2., diff --git a/arbnode/dataposter/dbstorage/storage.go b/arbnode/dataposter/dbstorage/storage.go index 37ebfa5099..6a6cd3cfa4 100644 --- a/arbnode/dataposter/dbstorage/storage.go +++ b/arbnode/dataposter/dbstorage/storage.go @@ -95,11 +95,11 @@ func (s *Storage) PruneAll(ctx context.Context) error { if err != nil { return fmt.Errorf("pruning all keys: %w", err) } - until, err := strconv.Atoi(string(idx)) + until, err := strconv.ParseUint(string(idx), 10, 64) if err != nil { return fmt.Errorf("converting last item index bytes to integer: %w", err) } - return s.Prune(ctx, uint64(until+1)) + return s.Prune(ctx, until+1) } func (s *Storage) Prune(ctx context.Context, until uint64) error { diff --git a/arbnode/dataposter/storage_test.go b/arbnode/dataposter/storage_test.go index 8934d92b45..c6316caea7 100644 --- a/arbnode/dataposter/storage_test.go +++ b/arbnode/dataposter/storage_test.go @@ -72,24 +72,29 @@ func newRedisStorage(ctx context.Context, t *testing.T, encF storage.EncoderDeco func valueOf(t *testing.T, i int) *storage.QueuedTransaction { t.Helper() + // #nosec G115 meta, err := rlp.EncodeToBytes(storage.BatchPosterPosition{DelayedMessageCount: uint64(i)}) if err != nil { t.Fatalf("Encoding batch poster position, error: %v", err) } return &storage.QueuedTransaction{ FullTx: types.NewTransaction( + // #nosec G115 uint64(i), common.Address{}, big.NewInt(int64(i)), + // #nosec G115 uint64(i), big.NewInt(int64(i)), []byte{byte(i)}), Meta: meta, DeprecatedData: types.DynamicFeeTx{ - ChainID: big.NewInt(int64(i)), - Nonce: uint64(i), - GasTipCap: big.NewInt(int64(i)), - GasFeeCap: big.NewInt(int64(i)), + ChainID: big.NewInt(int64(i)), + // #nosec G115 + Nonce: uint64(i), + GasTipCap: big.NewInt(int64(i)), + GasFeeCap: big.NewInt(int64(i)), + // #nosec G115 Gas: uint64(i), Value: big.NewInt(int64(i)), Data: []byte{byte(i % 8)}, @@ -113,6 +118,7 @@ func values(t *testing.T, from, to int) []*storage.QueuedTransaction { func initStorage(ctx context.Context, t *testing.T, s QueueStorage) QueueStorage { t.Helper() for i := 0; i < 20; i++ { + // #nosec G115 if err := s.Put(ctx, uint64(i), nil, valueOf(t, i)); err != nil { t.Fatalf("Error putting a key/value: %v", err) } @@ -153,6 +159,7 @@ func TestPruneAll(t *testing.T) { s := newLevelDBStorage(t, func() storage.EncoderDecoderInterface { return &storage.EncoderDecoder{} }) ctx := context.Background() for i := 0; i < 20; i++ { + // #nosec G115 if err := s.Put(ctx, uint64(i), nil, valueOf(t, i)); err != nil { t.Fatalf("Error putting a key/value: %v", err) } @@ -236,6 +243,7 @@ func TestLast(t *testing.T) { ctx := context.Background() for i := 0; i < cnt; i++ { val := valueOf(t, i) + // #nosec G115 if err := s.Put(ctx, uint64(i), nil, val); err != nil { t.Fatalf("Error putting a key/value: %v", err) } @@ -255,6 +263,7 @@ func TestLast(t *testing.T) { for i := 0; i < cnt-1; i++ { prev := valueOf(t, i) newVal := valueOf(t, cnt+i) + // #nosec G115 if err := s.Put(ctx, uint64(i), prev, newVal); err != nil { t.Fatalf("Error putting a key/value: %v, prev: %v, new: %v", err, prev, newVal) } diff --git a/arbnode/delayed.go b/arbnode/delayed.go index c166aa2b90..082f0ecf9d 100644 --- a/arbnode/delayed.go +++ b/arbnode/delayed.go @@ -215,7 +215,7 @@ func (b *DelayedBridge) logsToDeliveredMessages(ctx context.Context, logs []type } messages := make([]*DelayedInboxMessage, 0, len(logs)) - var lastParentChainBlockNumber uint64 + var lastParentChainBlockHash common.Hash var lastL1BlockNumber uint64 for _, parsedLog := range parsedLogs { msgKey := common.BigToHash(parsedLog.MessageIndex) @@ -228,17 +228,17 @@ func (b *DelayedBridge) logsToDeliveredMessages(ctx context.Context, logs []type } requestId := common.BigToHash(parsedLog.MessageIndex) - parentChainBlockNumber := parsedLog.Raw.BlockNumber + parentChainBlockHash := parsedLog.Raw.BlockHash var l1BlockNumber uint64 - if lastParentChainBlockNumber == parentChainBlockNumber && lastParentChainBlockNumber > 0 { + if lastParentChainBlockHash == parentChainBlockHash && lastParentChainBlockHash != (common.Hash{}) { l1BlockNumber = lastL1BlockNumber } else { - var err error - l1BlockNumber, err = arbutil.CorrespondingL1BlockNumber(ctx, b.client, parentChainBlockNumber) + parentChainHeader, err := b.client.HeaderByHash(ctx, parentChainBlockHash) if err != nil { return nil, err } - lastParentChainBlockNumber = parentChainBlockNumber + l1BlockNumber = arbutil.ParentHeaderToL1BlockNumber(parentChainHeader) + lastParentChainBlockHash = parentChainBlockHash lastL1BlockNumber = l1BlockNumber } msg := &DelayedInboxMessage{ diff --git a/arbnode/delayed_sequencer.go b/arbnode/delayed_sequencer.go index 4f18531a76..b29a66dd05 100644 --- a/arbnode/delayed_sequencer.go +++ b/arbnode/delayed_sequencer.go @@ -121,6 +121,7 @@ func (d *DelayedSequencer) sequenceWithoutLockout(ctx context.Context, lastBlock if currentNum < config.FinalizeDistance { return nil } + // #nosec G115 finalized = uint64(currentNum - config.FinalizeDistance) } @@ -189,6 +190,7 @@ func (d *DelayedSequencer) sequenceWithoutLockout(ctx context.Context, lastBlock return fmt.Errorf("inbox reader at delayed message %v db accumulator %v doesn't match delayed bridge accumulator %v at L1 block %v", pos-1, lastDelayedAcc, delayedBridgeAcc, finalized) } for i, msg := range messages { + // #nosec G115 err = d.exec.SequenceDelayedMessage(msg, startPos+uint64(i)) if err != nil { return err diff --git a/arbnode/inbox_reader.go b/arbnode/inbox_reader.go index fd050b5f67..c596cfa9b0 100644 --- a/arbnode/inbox_reader.go +++ b/arbnode/inbox_reader.go @@ -542,6 +542,7 @@ func (r *InboxReader) run(ctx context.Context, hadError bool) error { } else { from = arbmath.BigAddByUint(to, 1) } + // #nosec G115 haveMessages := uint64(len(delayedMessages) + len(sequencerBatches)) if haveMessages <= (config.TargetMessagesRead / 2) { blocksToFetch += (blocksToFetch + 4) / 5 diff --git a/arbnode/seq_coordinator.go b/arbnode/seq_coordinator.go index a582b64ffa..176ace114b 100644 --- a/arbnode/seq_coordinator.go +++ b/arbnode/seq_coordinator.go @@ -491,7 +491,7 @@ func (c *SeqCoordinator) updateWithLockout(ctx context.Context, nextChosen strin // Before proceeding, first try deleting finalized messages from redis and setting the finalizedMsgCount key finalized, err := c.sync.GetFinalizedMsgCount(ctx) if err != nil { - log.Warn("Error getting finalizedMessageCount from syncMonitor: %w", err) + log.Warn("Error getting finalizedMessageCount from syncMonitor", "err", err) } else if finalized == 0 { log.Warn("SyncMonitor returned zero finalizedMessageCount") } else if err := c.deleteFinalizedMsgsFromRedis(ctx, finalized); err != nil { diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index a5bab8342f..24a0564b97 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -279,6 +279,7 @@ func (s *TransactionStreamer) reorg(batch ethdb.Batch, count arbutil.MessageInde return err } config := s.config() + // #nosec G115 maxResequenceMsgCount := count + arbutil.MessageIndex(config.MaxReorgResequenceDepth) if config.MaxReorgResequenceDepth >= 0 && maxResequenceMsgCount < targetMsgCount { log.Error( @@ -388,6 +389,7 @@ func (s *TransactionStreamer) reorg(batch ethdb.Batch, count arbutil.MessageInde } for i := 0; i < len(messagesResults); i++ { + // #nosec G115 pos := count + arbutil.MessageIndex(i) err = s.storeResult(pos, *messagesResults[i], batch) if err != nil { @@ -680,7 +682,7 @@ func (s *TransactionStreamer) AddMessagesAndEndBatch(pos arbutil.MessageIndex, m if err != nil { return err } - if dups == len(messages) { + if dups == uint64(len(messages)) { return endBatch(batch) } // cant keep reorg lock when catching insertionMutex. @@ -715,10 +717,10 @@ func (s *TransactionStreamer) countDuplicateMessages( pos arbutil.MessageIndex, messages []arbostypes.MessageWithMetadataAndBlockHash, batch *ethdb.Batch, -) (int, bool, *arbostypes.MessageWithMetadata, error) { - curMsg := 0 +) (uint64, bool, *arbostypes.MessageWithMetadata, error) { + var curMsg uint64 for { - if len(messages) == curMsg { + if uint64(len(messages)) == curMsg { break } key := dbKey(messagePrefix, uint64(pos)) @@ -818,7 +820,7 @@ func (s *TransactionStreamer) addMessagesAndEndBatchImpl(messageStartPos arbutil broadcastStartPos := arbutil.MessageIndex(s.broadcasterQueuedMessagesPos.Load()) if messagesAreConfirmed { - var duplicates int + var duplicates uint64 var err error duplicates, confirmedReorg, oldMsg, err = s.countDuplicateMessages(messageStartPos, messages, &batch) if err != nil { @@ -857,7 +859,7 @@ func (s *TransactionStreamer) addMessagesAndEndBatchImpl(messageStartPos arbutil var feedReorg bool if !hasNewConfirmedMessages { - var duplicates int + var duplicates uint64 var err error duplicates, feedReorg, oldMsg, err = s.countDuplicateMessages(messageStartPos, messages, nil) if err != nil { @@ -889,6 +891,7 @@ func (s *TransactionStreamer) addMessagesAndEndBatchImpl(messageStartPos arbutil // Validate delayed message counts of remaining messages for i, msg := range messages { + // #nosec G115 msgPos := messageStartPos + arbutil.MessageIndex(i) diff := msg.MessageWithMeta.DelayedMessagesRead - lastDelayedRead if diff != 0 && diff != 1 { @@ -924,6 +927,7 @@ func (s *TransactionStreamer) addMessagesAndEndBatchImpl(messageStartPos arbutil // Check if new messages were added at the end of cache, if they were, then dont remove those particular messages if len(s.broadcasterQueuedMessages) > cacheClearLen { s.broadcasterQueuedMessages = s.broadcasterQueuedMessages[cacheClearLen:] + // #nosec G115 s.broadcasterQueuedMessagesPos.Store(uint64(broadcastStartPos) + uint64(cacheClearLen)) } else { s.broadcasterQueuedMessages = s.broadcasterQueuedMessages[:0] @@ -1044,6 +1048,7 @@ func (s *TransactionStreamer) writeMessages(pos arbutil.MessageIndex, messages [ batch = s.db.NewBatch() } for i, msg := range messages { + // #nosec G115 err := s.writeMessage(pos+arbutil.MessageIndex(i), msg, batch) if err != nil { return err diff --git a/arbos/activate_test.go b/arbos/activate_test.go index 55440bb208..a89a38639a 100644 --- a/arbos/activate_test.go +++ b/arbos/activate_test.go @@ -20,6 +20,7 @@ func TestActivationDataFee(t *testing.T) { rand.Seed(time.Now().UTC().UnixNano()) state, _ := arbosState.NewArbosMemoryBackedArbOSState() pricer := state.Programs().DataPricer() + // #nosec G115 time := uint64(time.Now().Unix()) assert := func(cond bool) { diff --git a/arbos/addressSet/addressSet.go b/arbos/addressSet/addressSet.go index 1f09ff1440..156f36e7e7 100644 --- a/arbos/addressSet/addressSet.go +++ b/arbos/addressSet/addressSet.go @@ -79,6 +79,7 @@ func (as *AddressSet) AllMembers(maxNumToReturn uint64) ([]common.Address, error } ret := make([]common.Address, size) for i := range ret { + // #nosec G115 sba := as.backingStorage.OpenStorageBackedAddress(uint64(i + 1)) ret[i], err = sba.Get() if err != nil { diff --git a/arbos/addressTable/addressTable.go b/arbos/addressTable/addressTable.go index 566c71b689..6ae271060d 100644 --- a/arbos/addressTable/addressTable.go +++ b/arbos/addressTable/addressTable.go @@ -103,6 +103,7 @@ func (atab *AddressTable) Decompress(buf []byte) (common.Address, uint64, error) return common.Address{}, 0, err } if len(input) == 20 { + // #nosec G115 numBytesRead := uint64(rd.Size() - int64(rd.Len())) return common.BytesToAddress(input), numBytesRead, nil } else { diff --git a/arbos/arbosState/initialization_test.go b/arbos/arbosState/initialization_test.go index b0fe1d0dac..5e605b8bd2 100644 --- a/arbos/arbosState/initialization_test.go +++ b/arbos/arbosState/initialization_test.go @@ -126,6 +126,7 @@ func checkAddressTable(arbState *ArbosState, addrTable []common.Address, t *test Fail(t) } for i, addr := range addrTable { + // #nosec G115 res, exists, err := atab.LookupIndex(uint64(i)) Require(t, err) if !exists { diff --git a/arbos/arbosState/initialize.go b/arbos/arbosState/initialize.go index 56fa579c15..427bdc3087 100644 --- a/arbos/arbosState/initialize.go +++ b/arbos/arbosState/initialize.go @@ -108,7 +108,7 @@ func InitializeArbosInDatabase(db ethdb.Database, cacheConfig *core.CacheConfig, if err != nil { return common.Hash{}, err } - for i := 0; addressReader.More(); i++ { + for i := uint64(0); addressReader.More(); i++ { addr, err := addressReader.GetNext() if err != nil { return common.Hash{}, err @@ -117,7 +117,7 @@ func InitializeArbosInDatabase(db ethdb.Database, cacheConfig *core.CacheConfig, if err != nil { return common.Hash{}, err } - if uint64(i) != slot { + if i != slot { return common.Hash{}, errors.New("address table slot mismatch") } } diff --git a/arbos/arbostypes/incomingmessage.go b/arbos/arbostypes/incomingmessage.go index 04ce8ebe2e..c4c2dc037b 100644 --- a/arbos/arbostypes/incomingmessage.go +++ b/arbos/arbostypes/incomingmessage.go @@ -182,6 +182,17 @@ func (msg *L1IncomingMessage) FillInBatchGasCost(batchFetcher FallibleBatchFetch return nil } +func (msg *L1IncomingMessage) PastBatchesRequired() ([]uint64, error) { + if msg.Header.Kind != L1MessageType_BatchPostingReport { + return nil, nil + } + _, _, _, batchNum, _, _, err := ParseBatchPostingReportMessageFields(bytes.NewReader(msg.L2msg)) + if err != nil { + return nil, fmt.Errorf("failed to parse batch posting report: %w", err) + } + return []uint64{batchNum}, nil +} + func ParseIncomingL1Message(rd io.Reader, batchFetcher FallibleBatchFetcher) (*L1IncomingMessage, error) { var kindBuf [1]byte _, err := rd.Read(kindBuf[:]) diff --git a/arbos/l1pricing_test.go b/arbos/l1pricing_test.go index 1cda4b3d82..6f9e3ecb35 100644 --- a/arbos/l1pricing_test.go +++ b/arbos/l1pricing_test.go @@ -279,7 +279,9 @@ func _testL1PriceEquilibration(t *testing.T, initialL1BasefeeEstimate *big.Int, evm.StateDB, evm, 3, + // #nosec G115 uint64(10*(i+1)), + // #nosec G115 uint64(10*(i+1)+5), bpAddr, arbmath.BigMulByUint(equilibriumL1BasefeeEstimate, unitsToAdd), diff --git a/arbos/merkleAccumulator/merkleAccumulator.go b/arbos/merkleAccumulator/merkleAccumulator.go index 2e060c5840..e62303e5fd 100644 --- a/arbos/merkleAccumulator/merkleAccumulator.go +++ b/arbos/merkleAccumulator/merkleAccumulator.go @@ -97,6 +97,7 @@ func (acc *MerkleAccumulator) GetPartials() ([]*common.Hash, error) { } partials := make([]*common.Hash, CalcNumPartials(size)) for i := range partials { + // #nosec G115 p, err := acc.getPartial(uint64(i)) if err != nil { return nil, err diff --git a/arbos/programs/data_pricer.go b/arbos/programs/data_pricer.go index ed7c98556d..d82aa81f04 100644 --- a/arbos/programs/data_pricer.go +++ b/arbos/programs/data_pricer.go @@ -83,8 +83,8 @@ func (p *DataPricer) UpdateModel(tempBytes uint32, time uint64) (*big.Int, error } exponent := arbmath.OneInBips * arbmath.Bips(demand) / arbmath.Bips(inertia) - multiplier := arbmath.ApproxExpBasisPoints(exponent, 12).Uint64() - costPerByte := arbmath.SaturatingUMul(uint64(minPrice), multiplier) / 10000 + multiplier := arbmath.ApproxExpBasisPoints(exponent, 12) + costPerByte := arbmath.UintSaturatingMulByBips(uint64(minPrice), multiplier) costInWei := arbmath.SaturatingUMul(costPerByte, uint64(tempBytes)) return arbmath.UintToBig(costInWei), nil } diff --git a/arbos/programs/native.go b/arbos/programs/native.go index 377e25a31e..e834888b47 100644 --- a/arbos/programs/native.go +++ b/arbos/programs/native.go @@ -108,10 +108,10 @@ func activateProgramInternal( } results := make(chan result, len(targets)) for _, target := range targets { + target := target if target == rawdb.TargetWavm { results <- result{target, module, nil} } else { - target := target go func() { output := &rustBytes{} status_asm := C.stylus_compile( diff --git a/arbos/retryable_test.go b/arbos/retryable_test.go index ddb88348dd..2eccaea6c2 100644 --- a/arbos/retryable_test.go +++ b/arbos/retryable_test.go @@ -38,6 +38,7 @@ func TestRetryableLifecycle(t *testing.T) { retryableState := state.RetryableState() lifetime := uint64(retryables.RetryableLifetimeSeconds) + // #nosec G115 timestampAtCreation := uint64(rand.Int63n(1 << 16)) timeoutAtCreation := timestampAtCreation + lifetime currentTime := timeoutAtCreation @@ -57,6 +58,7 @@ func TestRetryableLifecycle(t *testing.T) { checkQueueSize := func(expected int, message string) { timeoutQueueSize, err := retryableState.TimeoutQueue.Size() Require(t, err) + // #nosec G115 if timeoutQueueSize != uint64(expected) { Fail(t, currentTime, message, timeoutQueueSize) } @@ -167,6 +169,7 @@ func TestRetryableCleanup(t *testing.T) { callvalue := big.NewInt(0) calldata := testhelpers.RandomizeSlice(make([]byte, rand.Intn(1<<12))) + // #nosec G115 timeout := uint64(rand.Int63n(1 << 16)) timestamp := 2 * timeout diff --git a/arbos/retryables/retryable.go b/arbos/retryables/retryable.go index e1cfe48bcf..5938244782 100644 --- a/arbos/retryables/retryable.go +++ b/arbos/retryables/retryable.go @@ -367,5 +367,7 @@ func RetryableEscrowAddress(ticketId common.Hash) common.Address { } func RetryableSubmissionFee(calldataLengthInBytes int, l1BaseFee *big.Int) *big.Int { - return arbmath.BigMulByUint(l1BaseFee, uint64(1400+6*calldataLengthInBytes)) + // This can't overflow because calldataLengthInBytes would need to be 3 exabytes + // #nosec G115 + return arbmath.BigMulByUint(l1BaseFee, 1400+6*uint64(calldataLengthInBytes)) } diff --git a/arbos/storage/storage.go b/arbos/storage/storage.go index 352726778d..bc16491af0 100644 --- a/arbos/storage/storage.go +++ b/arbos/storage/storage.go @@ -322,11 +322,11 @@ func (s *Storage) Burner() burn.Burner { } func (s *Storage) Keccak(data ...[]byte) ([]byte, error) { - byteCount := 0 + var byteCount uint64 for _, part := range data { - byteCount += len(part) + byteCount += uint64(len(part)) } - cost := 30 + 6*arbmath.WordsForBytes(uint64(byteCount)) + cost := 30 + 6*arbmath.WordsForBytes(byteCount) if err := s.burner.Burn(cost); err != nil { return nil, err } @@ -420,6 +420,7 @@ func (sbu *StorageBackedInt64) Get() (int64, error) { } func (sbu *StorageBackedInt64) Set(value int64) error { + // #nosec G115 return sbu.StorageSlot.Set(util.UintToHash(uint64(value))) // see implementation note above } @@ -456,7 +457,7 @@ func (sbu *StorageBackedUBips) Get() (arbmath.UBips, error) { } func (sbu *StorageBackedUBips) Set(bips arbmath.UBips) error { - return sbu.backing.Set(bips.Uint64()) + return sbu.backing.Set(uint64(bips)) } type StorageBackedUint16 struct { diff --git a/arbutil/block_message_relation.go b/arbutil/block_message_relation.go index e164cf2619..dcf4c86084 100644 --- a/arbutil/block_message_relation.go +++ b/arbutil/block_message_relation.go @@ -11,6 +11,7 @@ func BlockNumberToMessageCount(blockNumber uint64, genesisBlockNumber uint64) Me // Block number must correspond to a message count, meaning it may not be less than -1 func SignedBlockNumberToMessageCount(blockNumber int64, genesisBlockNumber uint64) MessageIndex { + // #nosec G115 return MessageIndex(uint64(blockNumber+1) - genesisBlockNumber) } diff --git a/blocks_reexecutor/blocks_reexecutor.go b/blocks_reexecutor/blocks_reexecutor.go index f7cc0d8c72..b43999a7db 100644 --- a/blocks_reexecutor/blocks_reexecutor.go +++ b/blocks_reexecutor/blocks_reexecutor.go @@ -113,6 +113,7 @@ func New(c *Config, blockchain *core.BlockChain, fatalErrChan chan error) *Block } // Divide work equally among available threads when BlocksPerThread is zero if c.BlocksPerThread == 0 { + // #nosec G115 work := (end - start) / uint64(c.Room) if work > 0 { blocksPerThread = work diff --git a/broadcastclient/broadcastclient_test.go b/broadcastclient/broadcastclient_test.go index 44b48192ab..a499628cd5 100644 --- a/broadcastclient/broadcastclient_test.go +++ b/broadcastclient/broadcastclient_test.go @@ -105,6 +105,7 @@ func testReceiveMessages(t *testing.T, clientCompression bool, serverCompression go func() { for i := 0; i < messageCount; i++ { + // #nosec G115 Require(t, b.BroadcastSingle(arbostypes.TestMessageWithMetadataAndRequestId, arbutil.MessageIndex(i), nil)) } }() @@ -156,6 +157,7 @@ func TestInvalidSignature(t *testing.T) { go func() { for i := 0; i < messageCount; i++ { + // #nosec G115 Require(t, b.BroadcastSingle(arbostypes.TestMessageWithMetadataAndRequestId, arbutil.MessageIndex(i), nil)) } }() diff --git a/broadcaster/broadcaster.go b/broadcaster/broadcaster.go index 397698635a..4fe8657bfa 100644 --- a/broadcaster/broadcaster.go +++ b/broadcaster/broadcaster.go @@ -104,6 +104,7 @@ func (b *Broadcaster) BroadcastMessages( }() var feedMessages []*m.BroadcastFeedMessage for i, msg := range messagesWithBlockHash { + // #nosec G115 bfm, err := b.NewBroadcastFeedMessage(msg.MessageWithMeta, seq+arbutil.MessageIndex(i), msg.BlockHash) if err != nil { return err diff --git a/broadcaster/message/message.go b/broadcaster/message/message.go index aca9598754..1e26e6da5e 100644 --- a/broadcaster/message/message.go +++ b/broadcaster/message/message.go @@ -41,6 +41,7 @@ type BroadcastFeedMessage struct { } func (m *BroadcastFeedMessage) Size() uint64 { + // #nosec G115 return uint64(len(m.Signature) + len(m.Message.Message.L2msg) + 160) } diff --git a/cmd/datool/datool.go b/cmd/datool/datool.go index ba60cbbd4d..f791d8cbc4 100644 --- a/cmd/datool/datool.go +++ b/cmd/datool/datool.go @@ -166,8 +166,10 @@ func startClientStore(args []string) error { if err != nil { return err } + // #nosec G115 cert, err = client.Store(ctx, message, uint64(time.Now().Add(config.DASRetentionPeriod).Unix())) } else if len(config.Message) > 0 { + // #nosec G115 cert, err = client.Store(ctx, []byte(config.Message), uint64(time.Now().Add(config.DASRetentionPeriod).Unix())) } else { return errors.New("--message or --random-message-size must be specified") @@ -363,6 +365,7 @@ func dumpKeyset(args []string) error { return err } + // #nosec G115 keysetHash, keysetBytes, err := das.KeysetHashFromServices(services, uint64(config.Keyset.AssumedHonest)) if err != nil { return err diff --git a/cmd/deploy/deploy.go b/cmd/deploy/deploy.go index d8c0aeeac4..e0388e3d4b 100644 --- a/cmd/deploy/deploy.go +++ b/cmd/deploy/deploy.go @@ -61,7 +61,6 @@ func main() { authorizevalidators := flag.Uint64("authorizevalidators", 0, "Number of validators to preemptively authorize") txTimeout := flag.Duration("txtimeout", 10*time.Minute, "Timeout when waiting for a transaction to be included in a block") prod := flag.Bool("prod", false, "Whether to configure the rollup for production or testing") - isUsingFeeToken := flag.Bool("isUsingFeeToken", false, "true if the chain uses custom fee token") flag.Parse() l1ChainId := new(big.Int).SetUint64(*l1ChainIdUint) maxDataSize := new(big.Int).SetUint64(*maxDataSizeUint) @@ -190,7 +189,6 @@ func main() { arbnode.GenerateRollupConfig(*prod, moduleRoot, ownerAddress, &chainConfig, chainConfigJson, loserEscrowAddress), nativeToken, maxDataSize, - *isUsingFeeToken, ) if err != nil { flag.Usage() diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index a8463a7d21..fc59f2d231 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -876,6 +876,7 @@ func testUpdateTxIndex(chainDb ethdb.Database, chainConfig *params.ChainConfig, localWg.Add(1) go func() { batch := chainDb.NewBatch() + // #nosec G115 for blockNum := uint64(thread); blockNum <= lastBlock; blockNum += uint64(threads) { blockHash := rawdb.ReadCanonicalHash(chainDb, blockNum) block := rawdb.ReadBlock(chainDb, blockHash, blockNum) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 146a0049e7..a13a92fdc1 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -437,61 +437,9 @@ func mainImpl() int { // Check that node is compatible with on-chain WASM module root on startup and before any ArbOS upgrades take effect to prevent divergences if nodeConfig.Node.ParentChainReader.Enable && nodeConfig.Validation.Wasm.EnableWasmrootsCheck { - // Fetch current on-chain WASM module root - rollupUserLogic, err := rollupgen.NewRollupUserLogic(rollupAddrs.Rollup, l1Client) + err := checkWasmModuleRootCompatibility(ctx, nodeConfig.Validation.Wasm, l1Client, rollupAddrs) if err != nil { - log.Error("failed to create rollupUserLogic", "err", err) - return 1 - } - moduleRoot, err := rollupUserLogic.WasmModuleRoot(&bind.CallOpts{Context: ctx}) - if err != nil { - log.Error("failed to get on-chain WASM module root", "err", err) - return 1 - } - if (moduleRoot == common.Hash{}) { - log.Error("on-chain WASM module root is zero") - return 1 - } - // Check if the on-chain WASM module root belongs to the set of allowed module roots - allowedWasmModuleRoots := nodeConfig.Validation.Wasm.AllowedWasmModuleRoots - if len(allowedWasmModuleRoots) > 0 { - moduleRootMatched := false - for _, root := range allowedWasmModuleRoots { - bytes, err := hex.DecodeString(strings.TrimPrefix(root, "0x")) - if err == nil { - if common.HexToHash(root) == common.BytesToHash(bytes) { - moduleRootMatched = true - break - } - continue - } - locator, locatorErr := server_common.NewMachineLocator(root) - if locatorErr != nil { - log.Warn("allowed-wasm-module-roots: value not a hex nor valid path:", "value", root, "locatorErr", locatorErr, "decodeErr", err) - continue - } - path := locator.GetMachinePath(moduleRoot) - if _, err := os.Stat(path); err == nil { - moduleRootMatched = true - break - } - } - if !moduleRootMatched { - log.Error("on-chain WASM module root did not match with any of the allowed WASM module roots") - return 1 - } - } else { - // If no allowed module roots were provided in config, check if we have a validator machine directory for the on-chain WASM module root - locator, err := server_common.NewMachineLocator(nodeConfig.Validation.Wasm.RootPath) - if err != nil { - log.Warn("failed to create machine locator. Skipping the check for compatibility with on-chain WASM module root", "err", err) - } else { - path := locator.GetMachinePath(moduleRoot) - if _, err := os.Stat(path); err != nil { - log.Error("unable to find validator machine directory for the on-chain WASM module root", "err", err) - return 1 - } - } + log.Warn("failed to check if node is compatible with on-chain WASM module root", "err", err) } } @@ -892,6 +840,7 @@ func ParseNode(ctx context.Context, args []string) (*NodeConfig, *genericconf.Wa l2ChainInfoIpfsDownloadPath := k.String("chain.info-ipfs-download-path") l2ChainInfoFiles := k.Strings("chain.info-files") l2ChainInfoJson := k.String("chain.info-json") + // #nosec G115 err = applyChainParameters(ctx, k, uint64(l2ChainId), l2ChainName, l2ChainInfoFiles, l2ChainInfoJson, l2ChainInfoIpfsUrl, l2ChainInfoIpfsDownloadPath) if err != nil { return nil, nil, err @@ -1037,13 +986,16 @@ func applyChainParameters(ctx context.Context, k *koanf.Koanf, chainId uint64, c func initReorg(initConfig conf.InitConfig, chainConfig *params.ChainConfig, inboxTracker *arbnode.InboxTracker) error { var batchCount uint64 if initConfig.ReorgToBatch >= 0 { + // #nosec G115 batchCount = uint64(initConfig.ReorgToBatch) + 1 } else { var messageIndex arbutil.MessageIndex if initConfig.ReorgToMessageBatch >= 0 { + // #nosec G115 messageIndex = arbutil.MessageIndex(initConfig.ReorgToMessageBatch) } else if initConfig.ReorgToBlockBatch > 0 { genesis := chainConfig.ArbitrumChainParams.GenesisBlockNum + // #nosec G115 blockNum := uint64(initConfig.ReorgToBlockBatch) if blockNum < genesis { return fmt.Errorf("ReorgToBlockBatch %d before genesis %d", blockNum, genesis) @@ -1074,3 +1026,57 @@ type NodeConfigFetcher struct { func (f *NodeConfigFetcher) Get() *arbnode.Config { return &f.LiveConfig.Get().Node } + +func checkWasmModuleRootCompatibility(ctx context.Context, wasmConfig valnode.WasmConfig, l1Client *ethclient.Client, rollupAddrs chaininfo.RollupAddresses) error { + // Fetch current on-chain WASM module root + rollupUserLogic, err := rollupgen.NewRollupUserLogic(rollupAddrs.Rollup, l1Client) + if err != nil { + return fmt.Errorf("failed to create RollupUserLogic: %w", err) + } + moduleRoot, err := rollupUserLogic.WasmModuleRoot(&bind.CallOpts{Context: ctx}) + if err != nil { + return fmt.Errorf("failed to get on-chain WASM module root: %w", err) + } + if (moduleRoot == common.Hash{}) { + return errors.New("on-chain WASM module root is zero") + } + // Check if the on-chain WASM module root belongs to the set of allowed module roots + allowedWasmModuleRoots := wasmConfig.AllowedWasmModuleRoots + if len(allowedWasmModuleRoots) > 0 { + moduleRootMatched := false + for _, root := range allowedWasmModuleRoots { + bytes, err := hex.DecodeString(strings.TrimPrefix(root, "0x")) + if err == nil { + if common.HexToHash(root) == common.BytesToHash(bytes) { + moduleRootMatched = true + break + } + continue + } + locator, locatorErr := server_common.NewMachineLocator(root) + if locatorErr != nil { + log.Warn("allowed-wasm-module-roots: value not a hex nor valid path:", "value", root, "locatorErr", locatorErr, "decodeErr", err) + continue + } + path := locator.GetMachinePath(moduleRoot) + if _, err := os.Stat(path); err == nil { + moduleRootMatched = true + break + } + } + if !moduleRootMatched { + return errors.New("on-chain WASM module root did not match with any of the allowed WASM module roots") + } + } else { + // If no allowed module roots were provided in config, check if we have a validator machine directory for the on-chain WASM module root + locator, err := server_common.NewMachineLocator(wasmConfig.RootPath) + if err != nil { + return fmt.Errorf("failed to create machine locator: %w", err) + } + path := locator.GetMachinePath(moduleRoot) + if _, err := os.Stat(path); err != nil { + return fmt.Errorf("unable to find validator machine directory for the on-chain WASM module root: %w", err) + } + } + return nil +} diff --git a/cmd/pruning/pruning.go b/cmd/pruning/pruning.go index 096bb4b1ae..6fc7741478 100644 --- a/cmd/pruning/pruning.go +++ b/cmd/pruning/pruning.go @@ -212,6 +212,7 @@ func findImportantRoots(ctx context.Context, chainDb ethdb.Database, stack *node } if meta.ParentChainBlock <= l1BlockNum { signedBlockNum := arbutil.MessageCountToBlockNumber(meta.MessageCount, genesisNum) + // #nosec G115 blockNum := uint64(signedBlockNum) l2Hash := rawdb.ReadCanonicalHash(chainDb, blockNum) l2Header := rawdb.ReadHeader(chainDb, l2Hash, blockNum) diff --git a/contracts b/contracts index a5c2d54561..23fc796282 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit a5c2d54561c2547e05d6118d6f072882c5fc7a9d +Subproject commit 23fc79628292aa5d604d449fed48937ae7faeb2f diff --git a/das/aggregator.go b/das/aggregator.go index e8972447ad..e7460fa371 100644 --- a/das/aggregator.go +++ b/das/aggregator.go @@ -130,6 +130,7 @@ func NewAggregatorWithSeqInboxCaller( seqInboxCaller *bridgegen.SequencerInboxCaller, ) (*Aggregator, error) { + // #nosec G115 keysetHash, keysetBytes, err := KeysetHashFromServices(services, uint64(config.RPCAggregator.AssumedHonest)) if err != nil { return nil, err diff --git a/das/dasRpcClient.go b/das/dasRpcClient.go index 635696bdab..7d48ed796d 100644 --- a/das/dasRpcClient.go +++ b/das/dasRpcClient.go @@ -58,6 +58,7 @@ func NewDASRPCClient(target string, signer signature.DataSignerFunc, maxStoreChu } func (c *DASRPCClient) Store(ctx context.Context, message []byte, timeout uint64) (*daprovider.DataAvailabilityCertificate, error) { + // #nosec G115 timestamp := uint64(time.Now().Unix()) nChunks := uint64(len(message)) / c.chunkSize lastChunkSize := uint64(len(message)) % c.chunkSize diff --git a/das/dasRpcServer.go b/das/dasRpcServer.go index d14766cc7e..bb1be0384e 100644 --- a/das/dasRpcServer.go +++ b/das/dasRpcServer.go @@ -153,7 +153,7 @@ type SendChunkResult struct { type batch struct { chunks [][]byte expectedChunks uint64 - seenChunks atomic.Int64 + seenChunks atomic.Uint64 expectedChunkSize, expectedSize uint64 timeout uint64 startTime time.Time @@ -248,7 +248,7 @@ func (b *batchBuilder) close(id uint64) ([]byte, uint64, time.Time, error) { return nil, 0, time.Time{}, fmt.Errorf("unknown batch(%d)", id) } - if batch.expectedChunks != uint64(batch.seenChunks.Load()) { + if batch.expectedChunks != batch.seenChunks.Load() { return nil, 0, time.Time{}, fmt.Errorf("incomplete batch(%d): got %d/%d chunks", id, batch.seenChunks.Load(), batch.expectedChunks) } diff --git a/das/das_test.go b/das/das_test.go index 179734c8b1..4971d454e5 100644 --- a/das/das_test.go +++ b/das/das_test.go @@ -55,6 +55,7 @@ func testDASStoreRetrieveMultipleInstances(t *testing.T, storageType string) { Require(t, err, "no das") var daReader DataAvailabilityServiceReader = storageService + // #nosec G115 timeout := uint64(time.Now().Add(time.Hour * 24).Unix()) messageSaved := []byte("hello world") cert, err := daWriter.Store(firstCtx, messageSaved, timeout) @@ -146,6 +147,7 @@ func testDASMissingMessage(t *testing.T, storageType string) { var daReader DataAvailabilityServiceReader = storageService messageSaved := []byte("hello world") + // #nosec G115 timeout := uint64(time.Now().Add(time.Hour * 24).Unix()) cert, err := daWriter.Store(ctx, messageSaved, timeout) Require(t, err, "Error storing message") diff --git a/das/db_storage_service.go b/das/db_storage_service.go index 1d9e5348d4..74bf12b927 100644 --- a/das/db_storage_service.go +++ b/das/db_storage_service.go @@ -267,6 +267,7 @@ func (dbs *DBStorageService) String() string { func (dbs *DBStorageService) HealthCheck(ctx context.Context) error { testData := []byte("Test-Data") + // #nosec G115 err := dbs.Put(ctx, testData, uint64(time.Now().Add(time.Minute).Unix())) if err != nil { return err diff --git a/das/factory.go b/das/factory.go index 5742a39479..7f696912b3 100644 --- a/das/factory.go +++ b/das/factory.go @@ -7,7 +7,6 @@ import ( "context" "errors" "fmt" - "math" "github.com/ethereum/go-ethereum/common" @@ -187,12 +186,7 @@ func CreateDAComponentsForDaserver( dasLifecycleManager.Register(restAgg) syncConf := &config.RestAggregator.SyncToStorage - var retentionPeriodSeconds uint64 - if uint64(syncConf.RetentionPeriod) == math.MaxUint64 { - retentionPeriodSeconds = math.MaxUint64 - } else { - retentionPeriodSeconds = uint64(syncConf.RetentionPeriod.Seconds()) - } + retentionPeriodSeconds := uint64(syncConf.RetentionPeriod.Seconds()) if syncConf.Eager { if l1Reader == nil || seqInboxAddress == nil { diff --git a/das/fallback_storage_service.go b/das/fallback_storage_service.go index 49f961da60..0a451678d0 100644 --- a/das/fallback_storage_service.go +++ b/das/fallback_storage_service.go @@ -85,6 +85,7 @@ func (f *FallbackStorageService) GetByHash(ctx context.Context, key common.Hash) } if dastree.ValidHash(key, data) { putErr := f.StorageService.Put( + // #nosec G115 ctx, data, arbmath.SaturatingUAdd(uint64(time.Now().Unix()), f.backupRetentionSeconds), ) if putErr != nil && !f.ignoreRetentionWriteErrors { diff --git a/das/local_file_storage_service.go b/das/local_file_storage_service.go index ce86786718..5e64c34b10 100644 --- a/das/local_file_storage_service.go +++ b/das/local_file_storage_service.go @@ -377,6 +377,7 @@ func migrate(fl *flatLayout, tl *trieLayout) error { return err } + // #nosec G115 expiryPath := tl.expiryPath(batch.key, uint64(batch.expiry.Unix())) if err = createHardLink(newPath, expiryPath); err != nil { return err diff --git a/das/local_file_storage_service_test.go b/das/local_file_storage_service_test.go index 01b999f356..8a36664670 100644 --- a/das/local_file_storage_service_test.go +++ b/das/local_file_storage_service_test.go @@ -78,6 +78,7 @@ func TestMigrationNoExpiry(t *testing.T) { Require(t, err) s.enableLegacyLayout = true + // #nosec G115 now := uint64(time.Now().Unix()) err = s.Put(ctx, []byte("a"), now+1) @@ -121,14 +122,19 @@ func TestMigrationExpiry(t *testing.T) { now := time.Now() // Use increments of expiry divisor in order to span multiple by-expiry-timestamp dirs + // #nosec G115 err = s.Put(ctx, []byte("a"), uint64(now.Add(-2*time.Second*expiryDivisor).Unix())) Require(t, err) + // #nosec G115 err = s.Put(ctx, []byte("b"), uint64(now.Add(-1*time.Second*expiryDivisor).Unix())) Require(t, err) + // #nosec G115 err = s.Put(ctx, []byte("c"), uint64(now.Add(time.Second*expiryDivisor).Unix())) Require(t, err) + // #nosec G115 err = s.Put(ctx, []byte("d"), uint64(now.Add(time.Second*expiryDivisor).Unix())) Require(t, err) + // #nosec G115 err = s.Put(ctx, []byte("e"), uint64(now.Add(2*time.Second*expiryDivisor).Unix())) Require(t, err) @@ -171,19 +177,26 @@ func TestExpiryDuplicates(t *testing.T) { now := time.Now() // Use increments of expiry divisor in order to span multiple by-expiry-timestamp dirs + // #nosec G115 err = s.Put(ctx, []byte("a"), uint64(now.Add(-2*time.Second*expiryDivisor).Unix())) Require(t, err) + // #nosec G115 err = s.Put(ctx, []byte("a"), uint64(now.Add(-1*time.Second*expiryDivisor).Unix())) Require(t, err) + // #nosec G115 err = s.Put(ctx, []byte("a"), uint64(now.Add(time.Second*expiryDivisor).Unix())) Require(t, err) + // #nosec G115 err = s.Put(ctx, []byte("d"), uint64(now.Add(time.Second*expiryDivisor).Unix())) Require(t, err) + // #nosec G115 err = s.Put(ctx, []byte("e"), uint64(now.Add(2*time.Second*expiryDivisor).Unix())) Require(t, err) + // #nosec G115 err = s.Put(ctx, []byte("f"), uint64(now.Add(3*time.Second*expiryDivisor).Unix())) Require(t, err) // Put the same entry and expiry again, should have no effect + // #nosec G115 err = s.Put(ctx, []byte("f"), uint64(now.Add(3*time.Second*expiryDivisor).Unix())) Require(t, err) diff --git a/das/redis_storage_service_test.go b/das/redis_storage_service_test.go index 55f3ecd82c..77d3e8cd0f 100644 --- a/das/redis_storage_service_test.go +++ b/das/redis_storage_service_test.go @@ -16,6 +16,7 @@ import ( func TestRedisStorageService(t *testing.T) { ctx := context.Background() + // #nosec G115 timeout := uint64(time.Now().Add(time.Hour).Unix()) baseStorageService := NewMemoryBackedStorageService(ctx) server, err := miniredis.Run() diff --git a/das/redundant_storage_test.go b/das/redundant_storage_test.go index b56f62ee24..11d3b58264 100644 --- a/das/redundant_storage_test.go +++ b/das/redundant_storage_test.go @@ -17,6 +17,7 @@ const NumServices = 3 func TestRedundantStorageService(t *testing.T) { ctx := context.Background() + // #nosec G115 timeout := uint64(time.Now().Add(time.Hour).Unix()) services := []StorageService{} for i := 0; i < NumServices; i++ { diff --git a/das/restful_server_test.go b/das/restful_server_test.go index 1d3675749a..e6982f9db5 100644 --- a/das/restful_server_test.go +++ b/das/restful_server_test.go @@ -48,6 +48,7 @@ func TestRestfulClientServer(t *testing.T) { server, port, err := NewRestfulDasServerOnRandomPort(LocalServerAddressForTest, storage) Require(t, err) + // #nosec G115 err = storage.Put(ctx, data, uint64(time.Now().Add(time.Hour).Unix())) Require(t, err) diff --git a/das/rpc_aggregator.go b/das/rpc_aggregator.go index 24a470be5b..1b3e2b8f44 100644 --- a/das/rpc_aggregator.go +++ b/das/rpc_aggregator.go @@ -119,7 +119,7 @@ func ParseServices(config AggregatorConfig, signer signature.DataSignerFunc) ([] return nil, err } - d, err := NewServiceDetails(service, *pubKey, 1< int(batchCacheLimit) { + for num := range v.prevBatchCache { + if num+uint64(batchCacheLimit) < v.nextCreateStartGS.Batch { + delete(v.prevBatchCache, num) + } + } + } v.nextCreateBatchReread = false } endGS := validator.GoGlobalState{ BlockHash: endRes.BlockHash, SendRoot: endRes.SendRoot, } - if pos+1 < v.nextCreateBatchMsgCount { + if pos+1 < v.nextCreateBatch.MsgCount { endGS.Batch = v.nextCreateStartGS.Batch endGS.PosInBatch = v.nextCreateStartGS.PosInBatch + 1 - } else if pos+1 == v.nextCreateBatchMsgCount { + } else if pos+1 == v.nextCreateBatch.MsgCount { endGS.Batch = v.nextCreateStartGS.Batch + 1 endGS.PosInBatch = 0 } else { - return false, fmt.Errorf("illegal batch msg count %d pos %d batch %d", v.nextCreateBatchMsgCount, pos, endGS.Batch) + return false, fmt.Errorf("illegal batch msg count %d pos %d batch %d", v.nextCreateBatch.MsgCount, pos, endGS.Batch) } chainConfig := v.streamer.ChainConfig() + prevBatchNums, err := msg.Message.PastBatchesRequired() + if err != nil { + return false, err + } + prevBatches := make([]validator.BatchInfo, 0, len(prevBatchNums)) + // prevBatchNums are only used for batch reports, each is only used once + for _, batchNum := range prevBatchNums { + data, found := v.prevBatchCache[batchNum] + if found { + delete(v.prevBatchCache, batchNum) + } else { + data, err = v.readPostedBatch(ctx, batchNum) + if err != nil { + return false, err + } + } + prevBatches = append(prevBatches, validator.BatchInfo{ + Number: batchNum, + Data: data, + }) + } entry, err := newValidationEntry( - pos, v.nextCreateStartGS, endGS, msg, v.nextCreateBatch, v.nextCreateBatchBlockHash, v.nextCreatePrevDelayed, chainConfig, + pos, v.nextCreateStartGS, endGS, msg, v.nextCreateBatch, prevBatches, v.nextCreatePrevDelayed, chainConfig, ) if err != nil { return false, err @@ -1011,6 +1046,9 @@ func (v *BlockValidator) UpdateLatestStaked(count arbutil.MessageIndex, globalSt v.nextCreateStartGS = globalState v.nextCreatePrevDelayed = msg.DelayedMessagesRead v.nextCreateBatchReread = true + if v.nextCreateBatch != nil { + v.prevBatchCache[v.nextCreateBatch.Number] = v.nextCreateBatch.PostedData + } v.createdA.Store(countUint64) } // under the reorg mutex we don't need atomic access @@ -1037,6 +1075,7 @@ func (v *BlockValidator) ReorgToBatchCount(count uint64) { defer v.reorgMutex.Unlock() if v.nextCreateStartGS.Batch >= count { v.nextCreateBatchReread = true + v.prevBatchCache = make(map[uint64][]byte) } } @@ -1077,6 +1116,7 @@ func (v *BlockValidator) Reorg(ctx context.Context, count arbutil.MessageIndex) v.nextCreateStartGS = buildGlobalState(*res, endPosition) v.nextCreatePrevDelayed = msg.DelayedMessagesRead v.nextCreateBatchReread = true + v.prevBatchCache = make(map[uint64][]byte) countUint64 := uint64(count) v.createdA.Store(countUint64) // under the reorg mutex we don't need atomic access diff --git a/staker/challenge-cache/cache_test.go b/staker/challenge-cache/cache_test.go index af0a058f78..40be627b7a 100644 --- a/staker/challenge-cache/cache_test.go +++ b/staker/challenge-cache/cache_test.go @@ -166,8 +166,9 @@ func TestPrune(t *testing.T) { } key = &Key{ WavmModuleRoot: root, - MessageHeight: uint64(i), - StepHeights: []uint64{0}, + // #nosec G115 + MessageHeight: uint64(i), + StepHeights: []uint64{0}, } if err = cache.Put(key, hashes); err != nil { t.Fatal(err) @@ -182,8 +183,9 @@ func TestPrune(t *testing.T) { for i := 0; i <= 5; i++ { key = &Key{ WavmModuleRoot: root, - MessageHeight: uint64(i), - StepHeights: []uint64{0}, + // #nosec G115 + MessageHeight: uint64(i), + StepHeights: []uint64{0}, } if _, err = cache.Get(key, 3); !errors.Is(err, ErrNotFoundInCache) { t.Error(err) @@ -193,8 +195,9 @@ func TestPrune(t *testing.T) { for i := 6; i < totalMessages; i++ { key = &Key{ WavmModuleRoot: root, - MessageHeight: uint64(i), - StepHeights: []uint64{0}, + // #nosec G115 + MessageHeight: uint64(i), + StepHeights: []uint64{0}, } items, err := cache.Get(key, 3) if err != nil { diff --git a/staker/challenge_manager.go b/staker/challenge_manager.go index c488c8a96e..27cb92a5c7 100644 --- a/staker/challenge_manager.go +++ b/staker/challenge_manager.go @@ -566,6 +566,7 @@ func (m *ChallengeManager) Act(ctx context.Context) (*types.Transaction, error) nextMovePos, ) } + // #nosec G115 err = m.createExecutionBackend(ctx, uint64(nextMovePos)) if err != nil { return nil, fmt.Errorf("error creating execution backend: %w", err) diff --git a/staker/fast_confirm.go b/staker/fast_confirm.go index 88f457f528..5dc7f01205 100644 --- a/staker/fast_confirm.go +++ b/staker/fast_confirm.go @@ -121,10 +121,12 @@ func (f *FastConfirmSafe) tryFastConfirmation(ctx context.Context, blockHash com return err } if alreadyApproved.Cmp(common.Big1) == 0 { + log.Info("Already approved Safe tx hash for fast confirmation, checking if we can execute the Safe tx", "safeHash", safeTxHash, "nodeHash", nodeHash) _, err = f.checkApprovedHashAndExecTransaction(ctx, fastConfirmCallData, safeTxHash) return err } + log.Info("Approving Safe tx hash to fast confirm", "safeHash", safeTxHash, "nodeHash", nodeHash) auth, err := f.builder.Auth(ctx) if err != nil { return err @@ -231,6 +233,7 @@ func (f *FastConfirmSafe) checkApprovedHashAndExecTransaction(ctx context.Contex if err != nil { return false, err } + log.Info("Executing Safe tx to fast confirm", "safeHash", safeTxHash) _, err = f.safe.ExecTransaction( auth, f.wallet.RollupAddress(), @@ -249,5 +252,6 @@ func (f *FastConfirmSafe) checkApprovedHashAndExecTransaction(ctx context.Contex } return true, nil } + log.Info("Not enough Safe tx approvals yet to fast confirm", "safeHash", safeTxHash) return false, nil } diff --git a/staker/staker.go b/staker/staker.go index 6e93d27311..77ca93e02c 100644 --- a/staker/staker.go +++ b/staker/staker.go @@ -268,7 +268,6 @@ type Staker struct { inboxReader InboxReaderInterface statelessBlockValidator *StatelessBlockValidator fatalErr chan<- error - enableFastConfirmation bool fastConfirmSafe *FastConfirmSafe } @@ -363,7 +362,10 @@ func (s *Staker) Initialize(ctx context.Context) error { return err } - return s.blockValidator.InitAssumeValid(stakedInfo.AfterState().GlobalState) + err = s.blockValidator.InitAssumeValid(stakedInfo.AfterState().GlobalState) + if err != nil { + return err + } } return s.setupFastConfirmation(ctx) } @@ -390,9 +392,9 @@ func (s *Staker) setupFastConfirmation(ctx context.Context) error { if err != nil { return fmt.Errorf("getting rollup fast confirmer address: %w", err) } + log.Info("Setting up fast confirmation", "wallet", walletAddress, "fastConfirmer", fastConfirmer) if fastConfirmer == walletAddress { // We can directly fast confirm nodes - s.enableFastConfirmation = true return nil } else if fastConfirmer == (common.Address{}) { // No fast confirmer enabled @@ -419,13 +421,12 @@ func (s *Staker) setupFastConfirmation(ctx context.Context) error { if !isOwner { return fmt.Errorf("staker wallet address %v is not an owner of the fast confirm safe %v", walletAddress, fastConfirmer) } - s.enableFastConfirmation = true s.fastConfirmSafe = fastConfirmSafe return nil } func (s *Staker) tryFastConfirmationNodeNumber(ctx context.Context, number uint64, hash common.Hash) error { - if !s.enableFastConfirmation { + if !s.config().EnableFastConfirmation { return nil } nodeInfo, err := s.rollup.LookupNode(ctx, number) @@ -436,7 +437,7 @@ func (s *Staker) tryFastConfirmationNodeNumber(ctx context.Context, number uint6 } func (s *Staker) tryFastConfirmation(ctx context.Context, blockHash common.Hash, sendRoot common.Hash, nodeHash common.Hash) error { - if !s.enableFastConfirmation { + if !s.config().EnableFastConfirmation { return nil } if s.fastConfirmSafe != nil { @@ -446,6 +447,7 @@ func (s *Staker) tryFastConfirmation(ctx context.Context, blockHash common.Hash, if err != nil { return err } + log.Info("Fast confirming node with wallet", "wallet", auth.From, "nodeHash", nodeHash) _, err = s.rollup.FastConfirmNextNode(auth, blockHash, sendRoot, nodeHash) return err } @@ -802,13 +804,13 @@ func (s *Staker) Act(ctx context.Context) (*types.Transaction, error) { confirmedCorrect = stakedOnNode } if confirmedCorrect { + log.Info("trying to fast confirm previous node", "node", firstUnresolvedNode, "nodeHash", nodeInfo.NodeHash) err = s.tryFastConfirmationNodeNumber(ctx, firstUnresolvedNode, nodeInfo.NodeHash) if err != nil { return nil, err } if s.builder.BuildingTransactionCount() > 0 { // Try to fast confirm previous nodes before working on new ones - log.Info("fast confirming previous node", "node", firstUnresolvedNode) return s.wallet.ExecuteTransactions(ctx, s.builder, cfg.gasRefunder) } } diff --git a/staker/stateless_block_validator.go b/staker/stateless_block_validator.go index c4b0948e43..b2ce9d54b8 100644 --- a/staker/stateless_block_validator.go +++ b/staker/stateless_block_validator.go @@ -116,6 +116,13 @@ const ( Ready ) +type FullBatchInfo struct { + Number uint64 + PostedData []byte + MsgCount arbutil.MessageIndex + Preimages map[arbutil.PreimageType]map[common.Hash][]byte +} + type validationEntry struct { Stage ValidationEntryStage // Valid since ReadyforRecord: @@ -173,16 +180,28 @@ func newValidationEntry( start validator.GoGlobalState, end validator.GoGlobalState, msg *arbostypes.MessageWithMetadata, - batch []byte, - batchBlockHash common.Hash, + fullBatchInfo *FullBatchInfo, + prevBatches []validator.BatchInfo, prevDelayed uint64, chainConfig *params.ChainConfig, ) (*validationEntry, error) { - batchInfo := validator.BatchInfo{ - Number: start.Batch, - BlockHash: batchBlockHash, - Data: batch, + preimages := make(map[arbutil.PreimageType]map[common.Hash][]byte) + if fullBatchInfo == nil { + return nil, fmt.Errorf("fullbatchInfo cannot be nil") } + if fullBatchInfo.Number != start.Batch { + return nil, fmt.Errorf("got wrong batch expected: %d got: %d", start.Batch, fullBatchInfo.Number) + } + valBatches := []validator.BatchInfo{ + { + Number: fullBatchInfo.Number, + Data: fullBatchInfo.PostedData, + }, + } + valBatches = append(valBatches, prevBatches...) + + copyPreimagesInto(preimages, fullBatchInfo.Preimages) + hasDelayed := false var delayedNum uint64 if msg.DelayedMessagesRead == prevDelayed+1 { @@ -191,6 +210,7 @@ func newValidationEntry( } else if msg.DelayedMessagesRead != prevDelayed { return nil, fmt.Errorf("illegal validation entry delayedMessage %d, previous %d", msg.DelayedMessagesRead, prevDelayed) } + return &validationEntry{ Stage: ReadyForRecord, Pos: pos, @@ -199,8 +219,9 @@ func newValidationEntry( HasDelayedMsg: hasDelayed, DelayedMsgNr: delayedNum, msg: msg, - BatchInfo: []validator.BatchInfo{batchInfo}, + BatchInfo: valBatches, ChainConfig: chainConfig, + Preimages: preimages, }, nil } @@ -248,30 +269,84 @@ func NewStatelessBlockValidator( }, nil } -func (v *StatelessBlockValidator) readBatch(ctx context.Context, batchNum uint64) (bool, []byte, common.Hash, arbutil.MessageIndex, error) { +func (v *StatelessBlockValidator) readPostedBatch(ctx context.Context, batchNum uint64) ([]byte, error) { batchCount, err := v.inboxTracker.GetBatchCount() if err != nil { - return false, nil, common.Hash{}, 0, err + return nil, err } if batchCount <= batchNum { - return false, nil, common.Hash{}, 0, nil + return nil, fmt.Errorf("batch not found: %d", batchNum) + } + postedData, _, err := v.inboxReader.GetSequencerMessageBytes(ctx, batchNum) + return postedData, err +} + +func (v *StatelessBlockValidator) readFullBatch(ctx context.Context, batchNum uint64) (bool, *FullBatchInfo, error) { + batchCount, err := v.inboxTracker.GetBatchCount() + if err != nil { + return false, nil, err + } + if batchCount <= batchNum { + return false, nil, nil } batchMsgCount, err := v.inboxTracker.GetBatchMessageCount(batchNum) if err != nil { - return false, nil, common.Hash{}, 0, err + return false, nil, err } - batch, batchBlockHash, err := v.inboxReader.GetSequencerMessageBytes(ctx, batchNum) + postedData, batchBlockHash, err := v.inboxReader.GetSequencerMessageBytes(ctx, batchNum) if err != nil { - return false, nil, common.Hash{}, 0, err + return false, nil, err + } + preimages := make(map[arbutil.PreimageType]map[common.Hash][]byte) + if len(postedData) > 40 { + foundDA := false + for _, dapReader := range v.dapReaders { + if dapReader != nil && dapReader.IsValidHeaderByte(postedData[40]) { + preimageRecorder := daprovider.RecordPreimagesTo(preimages) + _, err := dapReader.RecoverPayloadFromBatch(ctx, batchNum, batchBlockHash, postedData, preimageRecorder, true) + if err != nil { + // Matches the way keyset validation was done inside DAS readers i.e logging the error + // But other daproviders might just want to return the error + if errors.Is(err, daprovider.ErrSeqMsgValidation) && daprovider.IsDASMessageHeaderByte(postedData[40]) { + log.Error(err.Error()) + } else { + return false, nil, err + } + } + foundDA = true + break + } + } + if !foundDA { + if daprovider.IsDASMessageHeaderByte(postedData[40]) { + log.Error("No DAS Reader configured, but sequencer message found with DAS header") + } + } + } + fullInfo := FullBatchInfo{ + Number: batchNum, + PostedData: postedData, + MsgCount: batchMsgCount, + Preimages: preimages, + } + return true, &fullInfo, nil +} + +func copyPreimagesInto(dest, source map[arbutil.PreimageType]map[common.Hash][]byte) { + for piType, piMap := range source { + if dest[piType] == nil { + dest[piType] = make(map[common.Hash][]byte, len(piMap)) + } + for hash, preimage := range piMap { + dest[piType][hash] = preimage + } } - return true, batch, batchBlockHash, batchMsgCount, nil } func (v *StatelessBlockValidator) ValidationEntryRecord(ctx context.Context, e *validationEntry) error { if e.Stage != ReadyForRecord { return fmt.Errorf("validation entry should be ReadyForRecord, is: %v", e.Stage) } - e.Preimages = make(map[arbutil.PreimageType]map[common.Hash][]byte) if e.Pos != 0 { recording, err := v.recorder.RecordBlockCreation(ctx, e.Pos, e.msg) if err != nil { @@ -280,30 +355,11 @@ func (v *StatelessBlockValidator) ValidationEntryRecord(ctx context.Context, e * if recording.BlockHash != e.End.BlockHash { return fmt.Errorf("recording failed: pos %d, hash expected %v, got %v", e.Pos, e.End.BlockHash, recording.BlockHash) } - // record any additional batch fetching - batchFetcher := func(batchNum uint64) ([]byte, error) { - found, data, hash, _, err := v.readBatch(ctx, batchNum) - if err != nil { - return nil, err - } - if !found { - return nil, errors.New("batch not found") - } - e.BatchInfo = append(e.BatchInfo, validator.BatchInfo{ - Number: batchNum, - BlockHash: hash, - Data: data, - }) - return data, nil - } - e.msg.Message.BatchGasCost = nil - err = e.msg.Message.FillInBatchGasCost(batchFetcher) - if err != nil { - return err - } - if recording.Preimages != nil { - e.Preimages[arbutil.Keccak256PreimageType] = recording.Preimages + recordingPreimages := map[arbutil.PreimageType]map[common.Hash][]byte{ + arbutil.Keccak256PreimageType: recording.Preimages, + } + copyPreimagesInto(e.Preimages, recordingPreimages) } e.UserWasms = recording.UserWasms } @@ -318,35 +374,6 @@ func (v *StatelessBlockValidator) ValidationEntryRecord(ctx context.Context, e * } e.DelayedMsg = delayedMsg } - for _, batch := range e.BatchInfo { - if len(batch.Data) <= 40 { - continue - } - foundDA := false - for _, dapReader := range v.dapReaders { - if dapReader != nil && dapReader.IsValidHeaderByte(batch.Data[40]) { - preimageRecorder := daprovider.RecordPreimagesTo(e.Preimages) - _, err := dapReader.RecoverPayloadFromBatch(ctx, batch.Number, batch.BlockHash, batch.Data, preimageRecorder, true) - if err != nil { - // Matches the way keyset validation was done inside DAS readers i.e logging the error - // But other daproviders might just want to return the error - if errors.Is(err, daprovider.ErrSeqMsgValidation) && daprovider.IsDASMessageHeaderByte(batch.Data[40]) { - log.Error(err.Error()) - } else { - return err - } - } - foundDA = true - break - } - } - if !foundDA { - if daprovider.IsDASMessageHeaderByte(batch.Data[40]) { - log.Error("No DAS Reader configured, but sequencer message found with DAS header") - } - } - } - e.msg = nil // no longer needed e.Stage = Ready return nil @@ -406,11 +433,30 @@ func (v *StatelessBlockValidator) CreateReadyValidationEntry(ctx context.Context } start := buildGlobalState(*prevResult, startPos) end := buildGlobalState(*result, endPos) - seqMsg, batchBlockHash, err := v.inboxReader.GetSequencerMessageBytes(ctx, startPos.BatchNumber) + found, fullBatchInfo, err := v.readFullBatch(ctx, start.Batch) if err != nil { return nil, err } - entry, err := newValidationEntry(pos, start, end, msg, seqMsg, batchBlockHash, prevDelayed, v.streamer.ChainConfig()) + if !found { + return nil, fmt.Errorf("batch %d not found", startPos.BatchNumber) + } + + prevBatchNums, err := msg.Message.PastBatchesRequired() + if err != nil { + return nil, err + } + prevBatches := make([]validator.BatchInfo, 0, len(prevBatchNums)) + for _, batchNum := range prevBatchNums { + data, err := v.readPostedBatch(ctx, batchNum) + if err != nil { + return nil, err + } + prevBatches = append(prevBatches, validator.BatchInfo{ + Number: batchNum, + Data: data, + }) + } + entry, err := newValidationEntry(pos, start, end, msg, fullBatchInfo, prevBatches, prevDelayed, v.streamer.ChainConfig()) if err != nil { return nil, err } diff --git a/system_tests/block_validator_test.go b/system_tests/block_validator_test.go index eef6c29b7a..cca5572f4e 100644 --- a/system_tests/block_validator_test.go +++ b/system_tests/block_validator_test.go @@ -63,7 +63,6 @@ func testBlockValidatorSimple(t *testing.T, opts Options) { var delayEvery int if opts.workloadLoops > 1 { - l1NodeConfigA.BatchPoster.MaxDelay = time.Millisecond * 500 delayEvery = opts.workloadLoops / 3 } diff --git a/system_tests/bloom_test.go b/system_tests/bloom_test.go index a3cab748e2..68fb7c3add 100644 --- a/system_tests/bloom_test.go +++ b/system_tests/bloom_test.go @@ -48,11 +48,13 @@ func TestBloom(t *testing.T) { nullEventCounts := make(map[uint64]struct{}) for i := 0; i < eventsNum; i++ { + // #nosec G115 count := uint64(rand.Int() % countsNum) eventCounts[count] = struct{}{} } for i := 0; i < nullEventsNum; i++ { + // #nosec G115 count := uint64(rand.Int() % countsNum) nullEventCounts[count] = struct{}{} } @@ -60,6 +62,7 @@ func TestBloom(t *testing.T) { for i := 0; i <= countsNum; i++ { var tx *types.Transaction var err error + // #nosec G115 _, sendNullEvent := nullEventCounts[uint64(i)] if sendNullEvent { tx, err = simple.EmitNullEvent(&ownerTxOpts) @@ -68,6 +71,7 @@ func TestBloom(t *testing.T) { Require(t, err) } + // #nosec G115 _, sendEvent := eventCounts[uint64(i)] if sendEvent { tx, err = simple.IncrementEmit(&ownerTxOpts) @@ -86,7 +90,9 @@ func TestBloom(t *testing.T) { if sectionSize != 256 { Fatal(t, "unexpected section size: ", sectionSize) } + // #nosec G115 t.Log("sections: ", sectionNum, "/", uint64(countsNum)/sectionSize) + // #nosec G115 if sectionSize*(sectionNum+1) > uint64(countsNum) && sectionNum > 1 { break } diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 1da5b633c8..ee72ccf044 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -672,7 +672,7 @@ func l2MessageBatchDataFromTxes(txes types.Transactions) ([]byte, error) { if err != nil { return nil, err } - binary.BigEndian.PutUint64(sizeBuf, uint64(len(txBytes)+1)) + binary.BigEndian.PutUint64(sizeBuf, uint64(len(txBytes))+1) l2Message = append(l2Message, sizeBuf...) l2Message = append(l2Message, arbos.L2MessageKind_SignedTx) l2Message = append(l2Message, txBytes...) @@ -1041,7 +1041,6 @@ func DeployOnTestL1( arbnode.GenerateRollupConfig(prodConfirmPeriodBlocks, wasmModuleRoot, l1info.GetAddress("RollupOwner"), chainConfig, serializedChainConfig, common.Address{}), nativeToken, maxDataSize, - false, ) Require(t, err) l1info.SetContract("Bridge", addresses.Bridge) diff --git a/system_tests/estimation_test.go b/system_tests/estimation_test.go index 284c709fad..6285702342 100644 --- a/system_tests/estimation_test.go +++ b/system_tests/estimation_test.go @@ -214,7 +214,7 @@ func TestComponentEstimate(t *testing.T) { userBalance := big.NewInt(1e16) maxPriorityFeePerGas := big.NewInt(0) - maxFeePerGas := arbmath.BigMulByUfrac(l2BaseFee, 3, 2) + maxFeePerGas := arbmath.BigMulByUFrac(l2BaseFee, 3, 2) builder.L2Info.GenerateAccount("User") builder.L2.TransferBalance(t, "Owner", "User", userBalance, builder.L2Info) diff --git a/system_tests/nodeinterface_test.go b/system_tests/nodeinterface_test.go index 17bfb18892..927dc1b630 100644 --- a/system_tests/nodeinterface_test.go +++ b/system_tests/nodeinterface_test.go @@ -163,6 +163,7 @@ func TestGetL1Confirmations(t *testing.T) { numTransactions := 200 + // #nosec G115 if l1Confs >= uint64(numTransactions) { t.Fatalf("L1Confirmations for latest block %v is already %v (over %v)", genesisBlock.Number(), l1Confs, numTransactions) } @@ -175,6 +176,7 @@ func TestGetL1Confirmations(t *testing.T) { Require(t, err) // Allow a gap of 10 for asynchronicity, just in case + // #nosec G115 if l1Confs+10 < uint64(numTransactions) { t.Fatalf("L1Confirmations for latest block %v is only %v (did not hit expected %v)", genesisBlock.Number(), l1Confs, numTransactions) } diff --git a/system_tests/outbox_test.go b/system_tests/outbox_test.go index c68df6ea22..25c52396f9 100644 --- a/system_tests/outbox_test.go +++ b/system_tests/outbox_test.go @@ -175,6 +175,7 @@ func TestOutboxProofs(t *testing.T) { sibling := place ^ which position := merkletree.LevelAndLeaf{ + // #nosec G115 Level: uint64(level), Leaf: sibling, } @@ -201,6 +202,7 @@ func TestOutboxProofs(t *testing.T) { leaf := total - 1 // preceding it. We subtract 1 since we count from 0 partial := merkletree.LevelAndLeaf{ + // #nosec G115 Level: uint64(level), Leaf: leaf, } @@ -289,6 +291,7 @@ func TestOutboxProofs(t *testing.T) { step.Leaf += 1 << step.Level // we start on the min partial's zero-hash sibling known[step] = zero + // #nosec G115 for step.Level < uint64(treeLevels) { curr, ok := known[step] diff --git a/system_tests/recreatestate_rpc_test.go b/system_tests/recreatestate_rpc_test.go index 7b09552e28..4833d35536 100644 --- a/system_tests/recreatestate_rpc_test.go +++ b/system_tests/recreatestate_rpc_test.go @@ -362,12 +362,14 @@ func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, cacheConfig Require(t, err) l2info.GenerateAccount("User2") + // #nosec G115 for i := genesis; i < uint64(txCount)+genesis; i++ { tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, common.Big1, nil) err := client.SendTransaction(ctx, tx) Require(t, err) receipt, err := EnsureTxSucceeded(ctx, client, tx) Require(t, err) + // #nosec G115 if have, want := receipt.BlockNumber.Uint64(), uint64(i)+1; have != want { Fatal(t, "internal test error - tx got included in unexpected block number, have:", have, "want:", want) } @@ -378,6 +380,7 @@ func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, cacheConfig Fatal(t, "missing current block") } lastBlock := currentHeader.Number.Uint64() + // #nosec G115 if want := genesis + uint64(txCount); lastBlock < want { Fatal(t, "internal test error - not enough blocks produced during preparation, want:", want, "have:", lastBlock) } @@ -391,6 +394,7 @@ func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, cacheConfig bc = builder.L2.ExecNode.Backend.ArbInterface().BlockChain() gas := skipGas blocks := skipBlocks + // #nosec G115 for i := genesis; i <= genesis+uint64(txCount); i++ { block := bc.GetBlockByNumber(i) if block == nil { @@ -423,6 +427,7 @@ func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, cacheConfig } } } + // #nosec G115 for i := genesis + 1; i <= genesis+uint64(txCount); i += i % 10 { _, err = client.BalanceAt(ctx, GetTestAddressForAccountName(t, "User2"), new(big.Int).SetUint64(i)) if err != nil { diff --git a/system_tests/seqfeed_test.go b/system_tests/seqfeed_test.go index 5e70fdf098..21f0755225 100644 --- a/system_tests/seqfeed_test.go +++ b/system_tests/seqfeed_test.go @@ -164,12 +164,12 @@ func compareAllMsgResultsFromConsensusAndExecution( } var lastResult *execution.MessageResult - for msgCount := 1; arbutil.MessageIndex(msgCount) <= consensusMsgCount; msgCount++ { + for msgCount := arbutil.MessageIndex(1); msgCount <= consensusMsgCount; msgCount++ { pos := msgCount - 1 resultExec, err := testClient.ExecNode.ResultAtPos(arbutil.MessageIndex(pos)) Require(t, err) - resultConsensus, err := testClient.ConsensusNode.TxStreamer.ResultAtCount(arbutil.MessageIndex(msgCount)) + resultConsensus, err := testClient.ConsensusNode.TxStreamer.ResultAtCount(msgCount) Require(t, err) if !reflect.DeepEqual(resultExec, resultConsensus) { diff --git a/system_tests/seqinbox_test.go b/system_tests/seqinbox_test.go index 6babe5833f..a9f66b0e2f 100644 --- a/system_tests/seqinbox_test.go +++ b/system_tests/seqinbox_test.go @@ -265,6 +265,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { for j := 0; j < numMessages; j++ { sourceNum := rand.Int() % len(state.accounts) source := state.accounts[sourceNum] + // #nosec G115 amount := new(big.Int).SetUint64(uint64(rand.Int()) % state.balances[source].Uint64()) reserveAmount := new(big.Int).SetUint64(l2pricing.InitialBaseFeeWei * 100000000) if state.balances[source].Cmp(new(big.Int).Add(amount, reserveAmount)) < 0 { @@ -314,6 +315,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { for j := 0; ; j++ { haveNonce, err := builder.L1.Client.PendingNonceAt(ctx, seqOpts.From) Require(t, err) + // #nosec G115 if haveNonce == uint64(seqNonce) { break } @@ -380,6 +382,7 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { t.Errorf("Transaction: %v was not refunded, balance diff: %v, cost: %v", tx.Hash(), diff, txCost) } + // #nosec G115 state.l2BlockNumber += uint64(numMessages) state.l1BlockNumber = txRes.BlockNumber.Uint64() blockStates = append(blockStates, state) diff --git a/system_tests/stylus_trace_test.go b/system_tests/stylus_trace_test.go index cb303874d6..5c4463d9f7 100644 --- a/system_tests/stylus_trace_test.go +++ b/system_tests/stylus_trace_test.go @@ -76,6 +76,7 @@ func sendAndTraceTransaction( } func intToBytes(v int) []byte { + // #nosec G115 return binary.BigEndian.AppendUint64(nil, uint64(v)) } diff --git a/util/arbmath/bips.go b/util/arbmath/bips.go index 646dad3a92..39b014f3ac 100644 --- a/util/arbmath/bips.go +++ b/util/arbmath/bips.go @@ -27,24 +27,35 @@ func BigMulByBips(value *big.Int, bips Bips) *big.Int { return BigMulByFrac(value, int64(bips), int64(OneInBips)) } +func BigMulByUBips(value *big.Int, bips UBips) *big.Int { + return BigMulByUFrac(value, uint64(bips), uint64(OneInUBips)) +} + func IntMulByBips(value int64, bips Bips) int64 { return value * int64(bips) / int64(OneInBips) } +// UintMulByBips multiplies a uint value by a bips value +// bips must be positive and not cause an overflow func UintMulByBips(value uint64, bips Bips) uint64 { + // #nosec G115 return value * uint64(bips) / uint64(OneInBips) } -func SaturatingCastToBips(value uint64) Bips { - return Bips(SaturatingCast[int64](value)) -} - -func (bips UBips) Uint64() uint64 { - return uint64(bips) +// UintSaturatingMulByBips multiplies a uint value by a bips value, +// saturating at the maximum bips value (not the maximum uint64 result), +// then rounding down and returning a uint64. +// Returns 0 if bips is less than or equal to zero +func UintSaturatingMulByBips(value uint64, bips Bips) uint64 { + if bips <= 0 { + return 0 + } + // #nosec G115 + return SaturatingUMul(value, uint64(bips)) / uint64(OneInBips) } -func (bips Bips) Uint64() uint64 { - return uint64(bips) +func SaturatingCastToBips(value uint64) Bips { + return Bips(SaturatingCast[int64](value)) } // BigDivToBips returns dividend/divisor as bips, saturating if out of bounds diff --git a/util/arbmath/math.go b/util/arbmath/math.go index e5bed67f6d..07a9941b65 100644 --- a/util/arbmath/math.go +++ b/util/arbmath/math.go @@ -29,6 +29,7 @@ func NextOrCurrentPowerOf2(value uint64) uint64 { // Log2ceil the log2 of the int, rounded up func Log2ceil(value uint64) uint64 { + // #nosec G115 return uint64(64 - bits.LeadingZeros64(value)) } @@ -228,8 +229,8 @@ func BigMulByFrac(value *big.Int, numerator, denominator int64) *big.Int { return value } -// BigMulByUfrac multiply a huge by a rational whose components are non-negative -func BigMulByUfrac(value *big.Int, numerator, denominator uint64) *big.Int { +// BigMulByUFrac multiply a huge by a rational whose components are non-negative +func BigMulByUFrac(value *big.Int, numerator, denominator uint64) *big.Int { value = new(big.Int).Set(value) value.Mul(value, new(big.Int).SetUint64(numerator)) value.Div(value, new(big.Int).SetUint64(denominator)) @@ -407,6 +408,8 @@ func ApproxExpBasisPoints(value Bips, accuracy uint64) Bips { if negative { input = -value } + // This cast is safe because input is always positive + // #nosec G115 x := uint64(input) bips := uint64(OneInBips) diff --git a/util/arbmath/math_test.go b/util/arbmath/math_test.go index 528666dc19..3660f3657e 100644 --- a/util/arbmath/math_test.go +++ b/util/arbmath/math_test.go @@ -44,6 +44,7 @@ func TestMath(t *testing.T) { // try the first million sqrts for i := 0; i < 1000000; i++ { + // #nosec G115 input := uint64(i) approx := ApproxSquareRoot(input) correct := math.Sqrt(float64(input)) diff --git a/util/headerreader/blob_client.go b/util/headerreader/blob_client.go index 2b47a940c3..160323cf60 100644 --- a/util/headerreader/blob_client.go +++ b/util/headerreader/blob_client.go @@ -191,6 +191,7 @@ func (b *BlobClient) blobSidecars(ctx context.Context, slot uint64, versionedHas rawData, err := beaconRequest[json.RawMessage](b, ctx, fmt.Sprintf("/eth/v1/beacon/blob_sidecars/%d", slot)) if err != nil || len(rawData) == 0 { // blobs are pruned after 4096 epochs (1 epoch = 32 slots), we determine if the requested slot were to be pruned by a non-archive endpoint + // #nosec G115 roughAgeOfSlot := uint64(time.Now().Unix()) - (b.genesisTime + slot*b.secondsPerSlot) if roughAgeOfSlot > b.secondsPerSlot*32*4096 { return nil, fmt.Errorf("beacon client in blobSidecars got error or empty response fetching older blobs in slot: %d, an archive endpoint is required, please refer to https://docs.arbitrum.io/run-arbitrum-node/l1-ethereum-beacon-chain-rpc-providers, err: %w", slot, err) diff --git a/util/merkletree/merkleEventProof_test.go b/util/merkletree/merkleEventProof_test.go index b64cc88c2a..6af8479190 100644 --- a/util/merkletree/merkleEventProof_test.go +++ b/util/merkletree/merkleEventProof_test.go @@ -22,6 +22,7 @@ func initializedMerkleAccumulatorForTesting() *merkleAccumulator.MerkleAccumulat func TestProofForNext(t *testing.T) { leaves := make([]common.Hash, 13) for i := range leaves { + // #nosec G115 leaves[i] = pseudorandomForTesting(uint64(i)) } diff --git a/validator/server_arb/machine.go b/validator/server_arb/machine.go index adca9695e2..e77e071d70 100644 --- a/validator/server_arb/machine.go +++ b/validator/server_arb/machine.go @@ -92,7 +92,7 @@ func LoadSimpleMachine(wasm string, libraries []string, debugChain bool) (*Arbit cWasm := C.CString(wasm) cLibraries := CreateCStringList(libraries) debug := usize(arbmath.BoolToUint32(debugChain)) - mach := C.arbitrator_load_machine(cWasm, cLibraries, C.long(len(libraries)), debug) + mach := C.arbitrator_load_machine(cWasm, cLibraries, C.long(len(libraries)), debug, false) C.free(unsafe.Pointer(cWasm)) FreeCStringList(cLibraries, len(libraries)) if mach == nil { diff --git a/validator/server_arb/machine_cache.go b/validator/server_arb/machine_cache.go index 55ef61cf11..35f3406236 100644 --- a/validator/server_arb/machine_cache.go +++ b/validator/server_arb/machine_cache.go @@ -31,7 +31,7 @@ type MachineCache struct { } type MachineCacheConfig struct { - CachedChallengeMachines int `koanf:"cached-challenge-machines"` + CachedChallengeMachines uint64 `koanf:"cached-challenge-machines"` InitialSteps uint64 `koanf:"initial-steps"` } @@ -42,7 +42,7 @@ var DefaultMachineCacheConfig = MachineCacheConfig{ func MachineCacheConfigConfigAddOptions(prefix string, f *flag.FlagSet) { f.Uint64(prefix+".initial-steps", DefaultMachineCacheConfig.InitialSteps, "initial steps between machines") - f.Int(prefix+".cached-challenge-machines", DefaultMachineCacheConfig.CachedChallengeMachines, "how many machines to store in cache while working on a challenge (should be even)") + f.Uint64(prefix+".cached-challenge-machines", DefaultMachineCacheConfig.CachedChallengeMachines, "how many machines to store in cache while working on a challenge (should be even)") } // `initialMachine` won't be mutated by this function. @@ -140,7 +140,7 @@ func (c *MachineCache) unlockBuild(err error) { } func (c *MachineCache) setRangeLocked(ctx context.Context, start uint64, end uint64) error { - newInterval := (end - start) / uint64(c.config.CachedChallengeMachines) + newInterval := (end - start) / c.config.CachedChallengeMachines if newInterval == 0 { newInterval = 2 } @@ -150,7 +150,7 @@ func (c *MachineCache) setRangeLocked(ctx context.Context, start uint64, end uin if end >= c.finalMachineStep { end = c.finalMachineStep - newInterval/2 } - newInterval = (end - start) / uint64(c.config.CachedChallengeMachines) + newInterval = (end - start) / c.config.CachedChallengeMachines if newInterval == 0 { newInterval = 1 } @@ -212,7 +212,7 @@ func (c *MachineCache) populateCache(ctx context.Context) error { if nextMachine.GetStepCount()+c.machineStepInterval >= c.finalMachineStep { break } - if len(c.machines) >= c.config.CachedChallengeMachines { + if uint64(len(c.machines)) >= c.config.CachedChallengeMachines { break } nextMachine = nextMachine.CloneMachineInterface() @@ -236,6 +236,7 @@ func (c *MachineCache) getClosestMachine(stepCount uint64) (int, MachineInterfac } stepsFromStart := stepCount - c.firstMachineStep var index int + // #nosec G115 if c.machineStepInterval == 0 || stepsFromStart > c.machineStepInterval*uint64(len(c.machines)-1) { index = len(c.machines) - 1 } else { diff --git a/validator/server_jit/jit_machine.go b/validator/server_jit/jit_machine.go index 41d28f0418..da36d75dae 100644 --- a/validator/server_jit/jit_machine.go +++ b/validator/server_jit/jit_machine.go @@ -306,6 +306,7 @@ func (machine *JitMachine) prove( if err != nil { return state, fmt.Errorf("failed to read memory usage from Jit machine: %w", err) } + // #nosec G115 if memoryUsed > uint64(machine.wasmMemoryUsageLimit) { log.Warn("memory used by jit wasm exceeds the wasm memory usage limit", "limit", machine.wasmMemoryUsageLimit, "memoryUsed", memoryUsed) } diff --git a/validator/validation_entry.go b/validator/validation_entry.go index d340993fa2..4ec6919d3b 100644 --- a/validator/validation_entry.go +++ b/validator/validation_entry.go @@ -7,9 +7,8 @@ import ( ) type BatchInfo struct { - Number uint64 - BlockHash common.Hash - Data []byte + Number uint64 + Data []byte } type ValidationInput struct { diff --git a/validator/valnode/redis/consumer.go b/validator/valnode/redis/consumer.go index 2b025600cc..e0d53ffb2e 100644 --- a/validator/valnode/redis/consumer.go +++ b/validator/valnode/redis/consumer.go @@ -103,11 +103,13 @@ func (s *ValidationServer) Start(ctx_in context.Context) { case <-ready: // Wait until the stream exists and start consuming iteratively. } s.StopWaiter.CallIteratively(func(ctx context.Context) time.Duration { + log.Debug("waiting for request token", "cid", c.Id()) select { case <-ctx.Done(): return 0 case <-requestTokenQueue: } + log.Debug("got request token", "cid", c.Id()) req, err := c.Consume(ctx) if err != nil { log.Error("Consuming request", "error", err) @@ -115,10 +117,12 @@ func (s *ValidationServer) Start(ctx_in context.Context) { return 0 } if req == nil { + log.Debug("consumed nil", "cid", c.Id()) // There's nothing in the queue requestTokenQueue <- struct{}{} return time.Second } + log.Debug("forwarding work", "cid", c.Id(), "workid", req.ID) select { case <-ctx.Done(): case workQueue <- workUnit{req, moduleRoot}: @@ -131,7 +135,7 @@ func (s *ValidationServer) Start(ctx_in context.Context) { for { select { case <-readyStreams: - log.Trace("At least one stream is ready") + log.Debug("At least one stream is ready") return // Don't block Start if at least one of the stream is ready. case <-time.After(s.config.StreamTimeout): log.Error("Waiting for redis streams timed out") @@ -142,22 +146,27 @@ func (s *ValidationServer) Start(ctx_in context.Context) { } }) for i := 0; i < workers; i++ { + i := i s.StopWaiter.LaunchThread(func(ctx context.Context) { for { + log.Debug("waiting for work", "thread", i) var work workUnit select { case <-ctx.Done(): return case work = <-workQueue: } + log.Debug("got work", "thread", i, "workid", work.req.ID) valRun := s.spawner.Launch(work.req.Value, work.moduleRoot) res, err := valRun.Await(ctx) if err != nil { log.Error("Error validating", "request value", work.req.Value, "error", err) } else { + log.Debug("done work", "thread", i, "workid", work.req.ID) if err := s.consumers[work.moduleRoot].SetResult(ctx, work.req.ID, res); err != nil { log.Error("Error setting result for request", "id", work.req.ID, "result", res, "error", err) } + log.Debug("set result", "thread", i, "workid", work.req.ID) } select { case <-ctx.Done(): diff --git a/wavmio/stub.go b/wavmio/stub.go index 1395fb4235..0c82506ff3 100644 --- a/wavmio/stub.go +++ b/wavmio/stub.go @@ -66,6 +66,7 @@ func parsePreimageBytes(path string) { if err != nil { panic(err) } + // #nosec G115 if uint64(read) != fieldSize { panic("missing bytes reading data") } @@ -77,18 +78,18 @@ func parsePreimageBytes(path string) { func StubInit() { preimages = make(map[common.Hash][]byte) var delayedMsgPath arrayFlags - seqMsgPosFlag := flag.Int("inbox-position", 0, "position for sequencer inbox message") - posWithinMsgFlag := flag.Int("position-within-message", 0, "position inside sequencer inbox message") - delayedPositionFlag := flag.Int("delayed-inbox-position", 0, "position for first delayed inbox message") + seqMsgPosFlag := flag.Uint64("inbox-position", 0, "position for sequencer inbox message") + posWithinMsgFlag := flag.Uint64("position-within-message", 0, "position inside sequencer inbox message") + delayedPositionFlag := flag.Uint64("delayed-inbox-position", 0, "position for first delayed inbox message") lastBlockFlag := flag.String("last-block-hash", "0000000000000000000000000000000000000000000000000000000000000000", "lastBlockHash") flag.Var(&delayedMsgPath, "delayed-inbox", "delayed inbox messages (multiple values)") inboxPath := flag.String("inbox", "", "file to load sequencer message") preimagesPath := flag.String("preimages", "", "file to load preimages from") flag.Parse() - seqMsgPos = uint64(*seqMsgPosFlag) - posWithinMsg = uint64(*posWithinMsgFlag) - delayedMsgFirstPos = uint64(*delayedPositionFlag) + seqMsgPos = *seqMsgPosFlag + posWithinMsg = *posWithinMsgFlag + delayedMsgFirstPos = *delayedPositionFlag lastBlockHash = common.HexToHash(*lastBlockFlag) for _, path := range delayedMsgPath { msg, err := os.ReadFile(path)