Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
926 changes: 778 additions & 148 deletions Cargo.lock

Large diffs are not rendered by default.

7 changes: 3 additions & 4 deletions ethexe/processor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,24 @@ ethexe-runtime-common = { workspace = true, features = ["std"] }
ethexe-runtime = { workspace = true, features = ["std"] }
gear-core.workspace = true
gprimitives = { workspace = true, features = ["std"] }
gear-runtime-interface = { workspace = true, features = ["std"] }
gear-runtime-interface = { workspace = true, default-features = false, features = ["std"] }
gear-sandbox-host.workspace = true
gear-lazy-pages.workspace = true
gear-wasm-instrument = { workspace = true, features = ["std"] }
core-processor.workspace = true

futures.workspace = true
thiserror.workspace = true
wasmtime.workspace = true
wasmtime = "43.0.1"
log.workspace = true
parity-scale-codec = { workspace = true, features = ["std", "derive"] }
sp-allocator = { workspace = true, features = ["std"] }
sp-wasm-interface = { workspace = true, features = ["std", "wasmtime"] }
tokio = { workspace = true, features = ["full"] }
crossbeam = { workspace = true, features = ["crossbeam-channel"] }
itertools = { workspace = true, features = ["use_std"] }
gear-workspace-hack.workspace = true
anyhow.workspace = true
derive_more.workspace = true
scopeguard.workspace = true

[dev-dependencies]
anyhow.workspace = true
Expand Down
2 changes: 0 additions & 2 deletions ethexe/processor/src/handling/run/chunk_execution_spawn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,9 @@ pub async fn spawn_chunk_execution(
.map(|(program_id, state_hash)| {
let (instrumented_code, code_metadata) = ctx.program_code(program_id)?;
let mut executor = ctx.inner().instance_creator.instantiate()?;
let db = ctx.inner().db.cas().clone_boxed();
let promise_out_tx = ctx.inner().promise_out_tx.clone();
Ok(thread_pool::spawn(move || {
let (jn, new_state_hash, gas_spent) = executor.run(
db,
ProcessQueueContext {
program_id,
state_root: state_hash,
Expand Down
8 changes: 4 additions & 4 deletions ethexe/processor/src/handling/run/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -498,10 +498,10 @@ mod tests {
.collect();

let transitions = InBlockTransitions::new(0, states, Default::default());

let db = Database::memory();
let mut ctx = CommonRunContext::new(
Database::memory(),
InstanceCreator::new(host::runtime()).unwrap(),
db.clone(),
InstanceCreator::new(db.clone(), host::runtime()).unwrap(),
transitions,
1_000_000,
CHUNK_PROCESSING_THREADS,
Expand Down Expand Up @@ -662,7 +662,7 @@ mod tests {
in_block_transitions,
100,
16,
InstanceCreator::new(host::runtime()).unwrap(),
InstanceCreator::new(db.clone(), host::runtime()).unwrap(),
BlockHeader::dummy(3),
);
access_state(
Expand Down
22 changes: 5 additions & 17 deletions ethexe/processor/src/host/api/allocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use crate::host::context::HostContext;
use sp_wasm_interface::{FunctionContext, IntoValue, Pointer, StoreData};
use crate::host::{StoreData, context};
use wasmtime::{Caller, Linker};

pub fn link(linker: &mut Linker<StoreData>) -> Result<(), wasmtime::Error> {
Expand All @@ -27,21 +26,10 @@ pub fn link(linker: &mut Linker<StoreData>) -> Result<(), wasmtime::Error> {
Ok(())
}

fn free(caller: Caller<'_, StoreData>, ptr: i32) {
let mut host_context = HostContext { caller };

host_context
.deallocate_memory(Pointer::<u8>::new(ptr as _))
.unwrap();
fn free(caller: Caller<'_, StoreData>, ptr: u32) {
context::allocator(caller).deallocate(ptr).unwrap()
}

fn malloc(caller: Caller<'_, StoreData>, size: i32) -> i32 {
let mut host_context = HostContext { caller };

host_context
.allocate_memory(size as _)
.unwrap()
.into_value()
.as_i32()
.unwrap()
fn malloc(caller: Caller<'_, StoreData>, size: u32) -> u32 {
context::allocator(caller).allocate(size).unwrap()
}
33 changes: 13 additions & 20 deletions ethexe/processor/src/host/api/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use crate::host::{api::MemoryWrap, threads};
use crate::host::{StoreData, context, threads};
use gprimitives::H256;
use sp_wasm_interface::StoreData;
use wasmtime::{Caller, Linker};

pub fn link(linker: &mut Linker<StoreData>) -> Result<(), wasmtime::Error> {
Expand All @@ -32,43 +31,37 @@ pub fn link(linker: &mut Linker<StoreData>) -> Result<(), wasmtime::Error> {
fn update_state_hash(caller: Caller<'_, StoreData>, program_state_hash_ptr: i32) {
log::trace!(target: "host_call", "update_state_hash(program_state_hash={program_state_hash_ptr:?})");

let memory = MemoryWrap(caller.data().memory());

let hash_slice = memory.slice(&caller, program_state_hash_ptr as usize, size_of::<H256>());
let program_state_hash = H256::from_slice(hash_slice);
let program_state_hash =
context::memory(caller).decode(program_state_hash_ptr as usize, size_of::<H256>());

threads::update_state_hash(program_state_hash);
}

fn read_by_hash(caller: Caller<'_, StoreData>, hash_ptr: i32) -> i64 {
fn read_by_hash(mut caller: Caller<'_, StoreData>, hash_ptr: i32) -> i64 {
log::trace!(target: "host_call", "read_by_hash(hash_ptr={hash_ptr:?})");

let memory = MemoryWrap(caller.data().memory());

let hash_slice = memory.slice(&caller, hash_ptr as usize, size_of::<H256>());
let hash = H256::from_slice(hash_slice);
let hash = context::memory(&mut caller).decode(hash_ptr as usize, size_of::<H256>());

let maybe_data = threads::with_db(|db| db.read(hash));
let maybe_data = caller.data().db.read(hash);

let res = maybe_data
.map(|data| super::allocate_and_write_raw(caller, data).1)
.map(|data| super::allocate_and_write_raw(caller, data))
.unwrap_or(0);

log::trace!(target: "host_call", "read_by_hash(..) -> {res:?}");

res
}

fn write(caller: Caller<'_, StoreData>, ptr: i32, len: i32) -> i32 {
fn write(mut caller: Caller<'_, StoreData>, ptr: i32, len: i32) -> i32 {
log::trace!(target: "host_call", "write(ptr={ptr:?}, len={len:?})");

let memory = MemoryWrap(caller.data().memory());

let data = memory.slice(&caller, ptr as usize, len as usize);

let hash = threads::with_db(|db| db.write(data));
let db = caller.data().db.clone_boxed();
let memory = context::memory(&mut caller);
let data = memory.slice(ptr as usize, len as usize);
let hash = db.write(data);

let (_caller, res) = super::allocate_and_write(caller, hash);
let res = super::allocate_and_write(caller, hash);

// This extracts first bytes (ptr).
let res = res as i32;
Expand Down
40 changes: 13 additions & 27 deletions ethexe/processor/src/host/api/lazy_pages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@

// TODO (breathx): remove cloning of slices from wasm memory (unsafe casts).

use crate::host::{api::MemoryWrap, threads::EthexeHostLazyPages};
use crate::host::{StoreData, context, threads::EthexeHostLazyPages};
use gear_lazy_pages::LazyPagesVersion;
use gear_runtime_interface::{LazyPagesInitContext, lazy_pages_detail};
use sp_wasm_interface::StoreData;
use wasmtime::{Caller, Linker};

pub fn link(linker: &mut Linker<StoreData>) -> Result<(), wasmtime::Error> {
Expand Down Expand Up @@ -67,21 +66,17 @@ pub fn link(linker: &mut Linker<StoreData>) -> Result<(), wasmtime::Error> {
fn change_wasm_memory_addr_and_size(caller: Caller<'_, StoreData>, addr: i64, size: i64) {
log::trace!(target: "host_call", "change_wasm_memory_addr_and_size(addr={addr:?}, size={size:?})");

let memory = MemoryWrap(caller.data().memory());

let addr = memory.decode_by_val(&caller, addr);

let size = memory.decode_by_val(&caller, size);
let memory = context::memory(caller);
let addr = memory.decode_by_val(addr);
let size = memory.decode_by_val(size);

lazy_pages_detail::change_wasm_memory_addr_and_size(addr, size);
}

fn init_lazy_pages(caller: Caller<'_, StoreData>, ctx: i64) -> i32 {
log::trace!(target: "host_call", "init_lazy_pages(ctx={ctx:?})");

let memory = MemoryWrap(caller.data().memory());

let ctx: LazyPagesInitContext = memory.decode_by_val(&caller, ctx);
let ctx: LazyPagesInitContext = context::memory(caller).decode_by_val(ctx);

gear_lazy_pages::init(LazyPagesVersion::Version1, ctx.into(), EthexeHostLazyPages)
.map_err(|err| log::error!("Cannot initialize lazy-pages: {err}"))
Expand All @@ -91,9 +86,7 @@ fn init_lazy_pages(caller: Caller<'_, StoreData>, ctx: i64) -> i32 {
fn init_lazy_pages_for_program(caller: Caller<'_, StoreData>, ctx: i64) {
log::trace!(target: "host_call", "init_lazy_pages_for_program(ctx={ctx:?})");

let memory = MemoryWrap(caller.data().memory());

let ctx = memory.decode_by_val(&caller, ctx);
let ctx = context::memory(caller).decode_by_val(ctx);

lazy_pages_detail::init_lazy_pages_for_program(ctx);
}
Expand All @@ -103,7 +96,7 @@ fn lazy_pages_status(caller: Caller<'_, StoreData>) -> i64 {

let status = lazy_pages_detail::lazy_pages_status();

let (_caller, res) = super::allocate_and_write(caller, status);
let res = super::allocate_and_write(caller, status);

log::trace!(target: "host_call", "lazy_pages_status(..) -> {res:?}");

Expand All @@ -124,28 +117,21 @@ fn pre_process_memory_accesses(
) -> i32 {
log::trace!(target: "host_call", "pre_process_memory_accesses(reads={reads:?}, writes={writes:?}, gas_bytes={gas_bytes:?})");

let memory = MemoryWrap(caller.data().memory());

let reads = memory.slice_by_val(&caller, reads);

let writes = memory.slice_by_val(&caller, writes);
let mut memory = context::memory(&mut caller);
let reads = memory.slice_by_val(reads);
let writes = memory.slice_by_val(writes);

// 8 len bytes of u64 counter.
// read gas_bytes into `mut` variable because `pre_process_memory_accesses` updates
// it, then write updated slice to memory. Can't use `slice_mut` here without using `.to_vec()`
// on `writes` and `reads`.
let mut gas_counter: u64 = u64::from_le_bytes(
memory
.slice(&caller, gas_bytes as usize, 8)
.try_into()
.unwrap(),
);
let mut gas_counter: u64 = u64::from_le_bytes(memory.array::<8>(gas_bytes as usize));

let res =
lazy_pages_detail::pre_process_memory_accesses(reads, writes, &mut gas_counter) as i32;

memory
.slice_mut(&mut caller, gas_bytes as usize, 8)
.slice_mut(gas_bytes as usize, 8)
.copy_from_slice(&gas_counter.to_le_bytes());
log::trace!(target: "host_call", "pre_process_memory_accesses(..) -> {res:?}");

Expand All @@ -157,7 +143,7 @@ fn write_accessed_pages(caller: Caller<'_, StoreData>) -> i64 {

let pages = lazy_pages_detail::write_accessed_pages();

let (_caller, res) = super::allocate_and_write(caller, pages);
let res = super::allocate_and_write(caller, pages);

log::trace!(target: "host_call", "write_accessed_pages(..) -> {res:?}");

Expand Down
9 changes: 4 additions & 5 deletions ethexe/processor/src/host/api/logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use super::MemoryWrap;
use crate::host::{StoreData, context};
use log::Level;
use sp_wasm_interface::StoreData;
use wasmtime::{Caller, Linker};

pub fn link(linker: &mut Linker<StoreData>) -> Result<(), wasmtime::Error> {
Expand All @@ -39,12 +38,12 @@ fn log(caller: Caller<'_, StoreData>, level: i32, target: i64, message: i64) {
_ => Level::Trace,
};

let memory = MemoryWrap(caller.data().memory());
let memory = context::memory(caller);

let target = memory.slice_by_val(&caller, target);
let target = memory.slice_by_val(target);
let target = core::str::from_utf8(target).unwrap_or_default();

let message = memory.slice_by_val(&caller, message);
let message = memory.slice_by_val(message);
let message = core::str::from_utf8(message).unwrap_or_default();

log::log!(target: target, level, "{message}");
Expand Down
Loading
Loading