Skip to content

Commit e47c37f

Browse files
author
Eduardo Leegwater Simões
authored
Merge pull request #332 from dusk-network/revert-326-single-instance-per-call
Revert "One instance per contract function call"
2 parents ff6184d + 4d9b175 commit e47c37f

File tree

4 files changed

+172
-150
lines changed

4 files changed

+172
-150
lines changed

piecrust/CHANGELOG.md

-2
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717

1818
### Changed
1919

20-
- Change to have one instance per contract function call [#325]
2120
- Upgrade `dusk-wasmtime` to version `17`
2221

2322
### Fixed
2423

25-
- Fix bad dereferences in caused by instance reclamation [#325]
2624
- Fix overflow in gas limit calculation in inter-contract call
2725

2826
## [0.15.0] - 2024-01-24

piecrust/src/imports.rs

+23-19
Original file line numberDiff line numberDiff line change
@@ -138,12 +138,12 @@ pub(crate) fn hq(
138138
) -> WasmtimeResult<u32> {
139139
let env = fenv.data_mut();
140140

141-
let mut instance = env.self_instance();
141+
let instance = env.self_instance();
142142

143143
let name_len = name_len as usize;
144144

145-
check_ptr(&instance, name_ofs, name_len)?;
146-
check_arg(&instance, arg_len)?;
145+
check_ptr(instance, name_ofs, name_len)?;
146+
check_arg(instance, arg_len)?;
147147

148148
let name = instance.with_memory(|buf| {
149149
// performance: use a dedicated buffer here?
@@ -163,11 +163,11 @@ pub(crate) fn hd(
163163
) -> WasmtimeResult<u32> {
164164
let env = fenv.data_mut();
165165

166-
let mut instance = env.self_instance();
166+
let instance = env.self_instance();
167167

168168
let name_len = name_len as usize;
169169

170-
check_ptr(&instance, name_ofs, name_len)?;
170+
check_ptr(instance, name_ofs, name_len)?;
171171

172172
let name = instance.with_memory(|buf| {
173173
// performance: use a dedicated buffer here?
@@ -194,13 +194,13 @@ pub(crate) fn c(
194194
) -> WasmtimeResult<i32> {
195195
let env = fenv.data_mut();
196196

197-
let mut instance = env.self_instance();
197+
let instance = env.self_instance();
198198

199199
let name_len = name_len as usize;
200200

201-
check_ptr(&instance, mod_id_ofs, CONTRACT_ID_BYTES)?;
202-
check_ptr(&instance, name_ofs, name_len)?;
203-
check_arg(&instance, arg_len)?;
201+
check_ptr(instance, mod_id_ofs, CONTRACT_ID_BYTES)?;
202+
check_ptr(instance, name_ofs, name_len)?;
203+
check_arg(instance, arg_len)?;
204204

205205
let argbuf_ofs = instance.arg_buffer_offset();
206206

@@ -222,8 +222,12 @@ pub(crate) fn c(
222222
&memory[mod_id_ofs..][..std::mem::size_of::<ContractId>()],
223223
);
224224

225-
let mut callee = env.instance(mod_id)?;
226-
env.push_callstack(mod_id, callee_limit, callee.mem_len());
225+
let callee_stack_element = env
226+
.push_callstack(mod_id, callee_limit)
227+
.expect("pushing to the callstack should succeed");
228+
let callee = env
229+
.instance(&callee_stack_element.contract_id)
230+
.expect("callee instance should exist");
227231

228232
callee.snap().map_err(|err| Error::MemorySnapshotFailure {
229233
reason: None,
@@ -238,7 +242,7 @@ pub(crate) fn c(
238242
let ret_len = callee
239243
.call(name, arg.len() as u32, callee_limit)
240244
.map_err(Error::normalize)?;
241-
check_arg(&callee, ret_len as u32)?;
245+
check_arg(callee, ret_len as u32)?;
242246

243247
// copy back result
244248
callee.read_argument(&mut memory[argbuf_ofs..][..ret_len as usize]);
@@ -287,8 +291,8 @@ pub(crate) fn emit(
287291

288292
let topic_len = topic_len as usize;
289293

290-
check_ptr(&instance, topic_ofs, topic_len)?;
291-
check_arg(&instance, arg_len)?;
294+
check_ptr(instance, topic_ofs, topic_len)?;
295+
check_arg(instance, arg_len)?;
292296

293297
let data = instance.with_arg_buf(|buf| {
294298
let arg_len = arg_len as usize;
@@ -323,7 +327,7 @@ fn feed(mut fenv: Caller<Env>, arg_len: u32) -> WasmtimeResult<()> {
323327
let env = fenv.data_mut();
324328
let instance = env.self_instance();
325329

326-
check_arg(&instance, arg_len)?;
330+
check_arg(instance, arg_len)?;
327331

328332
let data = instance.with_arg_buf(|buf| {
329333
let arg_len = arg_len as usize;
@@ -338,7 +342,7 @@ fn hdebug(mut fenv: Caller<Env>, msg_len: u32) -> WasmtimeResult<()> {
338342
let env = fenv.data_mut();
339343
let instance = env.self_instance();
340344

341-
check_arg(&instance, msg_len)?;
345+
check_arg(instance, msg_len)?;
342346

343347
Ok(instance.with_arg_buf(|buf| {
344348
let slice = &buf[..msg_len as usize];
@@ -361,7 +365,7 @@ fn limit(fenv: Caller<Env>) -> u64 {
361365

362366
fn spent(fenv: Caller<Env>) -> u64 {
363367
let env = fenv.data();
364-
let mut instance = env.self_instance();
368+
let instance = env.self_instance();
365369

366370
let limit = env.limit();
367371
let remaining = instance.get_remaining_gas();
@@ -373,7 +377,7 @@ fn panic(fenv: Caller<Env>, arg_len: u32) -> WasmtimeResult<()> {
373377
let env = fenv.data();
374378
let instance = env.self_instance();
375379

376-
check_arg(&instance, arg_len)?;
380+
check_arg(instance, arg_len)?;
377381

378382
Ok(instance.with_arg_buf(|buf| {
379383
let slice = &buf[..arg_len as usize];
@@ -388,7 +392,7 @@ fn panic(fenv: Caller<Env>, arg_len: u32) -> WasmtimeResult<()> {
388392
}
389393

390394
fn owner(fenv: Caller<Env>, mod_id_ofs: usize) -> WasmtimeResult<i32> {
391-
check_ptr(&fenv.data().self_instance(), mod_id_ofs, CONTRACT_ID_BYTES)?;
395+
check_ptr(fenv.data().self_instance(), mod_id_ofs, CONTRACT_ID_BYTES)?;
392396

393397
let env = fenv.data();
394398

piecrust/src/instance.rs

+36-60
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
// Copyright (c) DUSK NETWORK. All rights reserved.
66

77
use std::io;
8-
use std::mem::MaybeUninit;
98
use std::ops::{Deref, DerefMut};
109

1110
use dusk_wasmtime::{Instance, Module, Mutability, Store, ValType};
@@ -18,47 +17,15 @@ use crate::store::Memory;
1817
use crate::Error;
1918

2019
pub struct WrappedInstance {
21-
inner: *mut WrappedInstanceInner,
22-
original: bool,
23-
}
24-
25-
impl Clone for WrappedInstance {
26-
fn clone(&self) -> Self {
27-
Self {
28-
inner: self.inner,
29-
original: false,
30-
}
31-
}
32-
}
33-
34-
impl Drop for WrappedInstance {
35-
fn drop(&mut self) {
36-
if self.original {
37-
unsafe {
38-
let _ = Box::from_raw(self.inner);
39-
}
40-
}
41-
}
42-
}
43-
44-
impl Deref for WrappedInstance {
45-
type Target = WrappedInstanceInner;
46-
47-
fn deref(&self) -> &Self::Target {
48-
unsafe { &*self.inner }
49-
}
50-
}
51-
52-
impl DerefMut for WrappedInstance {
53-
fn deref_mut(&mut self) -> &mut Self::Target {
54-
unsafe { &mut *self.inner }
55-
}
20+
instance: Instance,
21+
arg_buf_ofs: usize,
22+
store: Store<Env>,
23+
memory: Memory,
5624
}
5725

5826
pub(crate) struct Env {
5927
self_id: ContractId,
6028
session: Session,
61-
instance: MaybeUninit<WrappedInstance>,
6229
}
6330

6431
impl Deref for Env {
@@ -76,8 +43,20 @@ impl DerefMut for Env {
7643
}
7744

7845
impl Env {
79-
pub fn self_instance(&self) -> WrappedInstance {
80-
unsafe { self.instance.assume_init_ref().clone() }
46+
pub fn self_instance<'b>(&self) -> &'b mut WrappedInstance {
47+
let stack_element = self
48+
.session
49+
.nth_from_top(0)
50+
.expect("there should be at least one element in the call stack");
51+
self.instance(&stack_element.contract_id)
52+
.expect("instance should exist")
53+
}
54+
55+
pub fn instance<'b>(
56+
&self,
57+
contract_id: &ContractId,
58+
) -> Option<&'b mut WrappedInstance> {
59+
self.session.instance(contract_id)
8160
}
8261

8362
pub fn limit(&self) -> u64 {
@@ -115,7 +94,6 @@ impl WrappedInstance {
11594
let env = Env {
11695
self_id: contract_id,
11796
session,
118-
instance: MaybeUninit::uninit(),
11997
};
12098

12199
let module =
@@ -199,38 +177,31 @@ impl WrappedInstance {
199177
// A memory is no longer new after one instantiation
200178
memory.is_new = false;
201179

202-
let inner = WrappedInstanceInner {
180+
let wrapped = WrappedInstance {
203181
store,
204182
instance,
205183
arg_buf_ofs,
206184
memory,
207185
};
208186

209-
let mut instance = WrappedInstance {
210-
inner: Box::into_raw(Box::new(inner)),
211-
original: true,
212-
};
213-
let instance_clone = instance.clone();
214-
215-
instance.store.data_mut().instance = MaybeUninit::new(instance_clone);
216-
217-
Ok(instance)
187+
Ok(wrapped)
218188
}
219-
}
220189

221-
pub struct WrappedInstanceInner {
222-
instance: Instance,
223-
arg_buf_ofs: usize,
224-
store: Store<Env>,
225-
memory: Memory,
226-
}
227-
228-
impl WrappedInstanceInner {
229190
pub(crate) fn snap(&mut self) -> io::Result<()> {
230191
self.memory.snap()?;
231192
Ok(())
232193
}
233194

195+
pub(crate) fn revert(&mut self) -> io::Result<()> {
196+
self.memory.revert()?;
197+
Ok(())
198+
}
199+
200+
pub(crate) fn apply(&mut self) -> io::Result<()> {
201+
self.memory.apply()?;
202+
Ok(())
203+
}
204+
234205
// Write argument into instance
235206
pub(crate) fn write_argument(&mut self, arg: &[u8]) {
236207
self.with_arg_buf_mut(|buf| buf[..arg.len()].copy_from_slice(arg))
@@ -267,6 +238,11 @@ impl WrappedInstanceInner {
267238
self.memory.current_len
268239
}
269240

241+
/// Sets the length of the memory.
242+
pub(crate) fn set_len(&mut self, len: usize) {
243+
self.memory.current_len = len;
244+
}
245+
270246
pub(crate) fn with_arg_buf<F, R>(&self, f: F) -> R
271247
where
272248
F: FnOnce(&[u8]) -> R,
@@ -366,7 +342,7 @@ impl WrappedInstanceInner {
366342
}
367343

368344
fn map_call_err(
369-
instance: &mut WrappedInstanceInner,
345+
instance: &mut WrappedInstance,
370346
err: dusk_wasmtime::Error,
371347
) -> Error {
372348
if instance.get_remaining_gas() == 0 {

0 commit comments

Comments
 (0)