1use crate::errors::InvokeError;
2use crate::internal_prelude::*;
3#[cfg(feature = "coverage")]
4use crate::utils::save_coverage_data;
5use crate::vm::wasm::constants::*;
6use crate::vm::wasm::errors::*;
7use crate::vm::wasm::traits::*;
8use crate::vm::wasm::WasmEngine;
9use radix_engine_interface::api::actor_api::EventFlags;
10use radix_engine_interface::blueprints::package::CodeHash;
11use sbor::rust::mem::MaybeUninit;
12#[cfg(not(feature = "fuzzing"))]
13use sbor::rust::sync::Arc;
14use wasmi::core::HostError;
15use wasmi::errors::InstantiationError;
16use wasmi::*;
17
18type HostState = WasmiInstanceEnv;
19
20pub struct WasmiModule {
22 module: Module,
23 #[allow(dead_code)]
24 code_size_bytes: usize,
25}
26
27pub struct WasmiInstance {
32 store: Store<HostState>,
33 instance: Instance,
34 memory: Memory,
35}
36
37pub struct WasmiInstanceEnv {
39 runtime_ptr: MaybeUninit<*mut Box<dyn WasmRuntime>>,
40}
41
42impl WasmiInstanceEnv {
43 pub fn new() -> Self {
44 Self {
45 runtime_ptr: MaybeUninit::uninit(),
46 }
47 }
48}
49
50macro_rules! grab_runtime {
51 ($caller: expr) => {{
52 let runtime: &mut Box<dyn WasmRuntime> =
53 unsafe { &mut *$caller.data().runtime_ptr.assume_init() };
54 runtime
55 }};
56}
57macro_rules! grab_memory {
58 ($caller: expr) => {{
59 match $caller.get_export(EXPORT_MEMORY) {
60 Some(Extern::Memory(memory)) => memory,
61 _ => panic!("Failed to find memory export"),
62 }
63 }};
64}
65
66fn consume_buffer(
68 caller: Caller<'_, HostState>,
69 buffer_id: BufferId,
70 destination_ptr: u32,
71) -> Result<(), InvokeError<WasmRuntimeError>> {
72 let runtime = grab_runtime!(caller);
73 let memory = grab_memory!(caller);
74
75 let result = runtime.buffer_consume(buffer_id);
76 match result {
77 Ok(slice) => {
78 write_memory(caller, memory, destination_ptr, &slice)?;
79 Ok(())
80 }
81 Err(e) => Err(e),
82 }
83}
84
85fn call_method(
86 mut caller: Caller<'_, HostState>,
87 receiver_ptr: u32,
88 receiver_len: u32,
89 ident_ptr: u32,
90 ident_len: u32,
91 args_ptr: u32,
92 args_len: u32,
93) -> Result<u64, InvokeError<WasmRuntimeError>> {
94 let runtime = grab_runtime!(caller);
95 let memory = grab_memory!(caller);
96
97 let receiver = read_memory(caller.as_context_mut(), memory, receiver_ptr, receiver_len)?;
98 let ident = read_memory(caller.as_context_mut(), memory, ident_ptr, ident_len)?;
99 let args = read_memory(caller.as_context_mut(), memory, args_ptr, args_len)?;
100
101 runtime
102 .object_call(receiver, ident, args)
103 .map(|buffer| buffer.0)
104}
105
106fn call_direct_method(
107 mut caller: Caller<'_, HostState>,
108 receiver_ptr: u32,
109 receiver_len: u32,
110 ident_ptr: u32,
111 ident_len: u32,
112 args_ptr: u32,
113 args_len: u32,
114) -> Result<u64, InvokeError<WasmRuntimeError>> {
115 let runtime = grab_runtime!(caller);
116 let memory = grab_memory!(caller);
117
118 let receiver = read_memory(caller.as_context_mut(), memory, receiver_ptr, receiver_len)?;
119 let ident = read_memory(caller.as_context_mut(), memory, ident_ptr, ident_len)?;
120 let args = read_memory(caller.as_context_mut(), memory, args_ptr, args_len)?;
121
122 runtime
123 .object_call_direct(receiver, ident, args)
124 .map(|buffer| buffer.0)
125}
126
127fn call_module_method(
128 mut caller: Caller<'_, HostState>,
129 receiver_ptr: u32,
130 receiver_len: u32,
131 module_id: u32,
132 ident_ptr: u32,
133 ident_len: u32,
134 args_ptr: u32,
135 args_len: u32,
136) -> Result<u64, InvokeError<WasmRuntimeError>> {
137 let runtime = grab_runtime!(caller);
138 let memory = grab_memory!(caller);
139
140 let receiver = read_memory(caller.as_context_mut(), memory, receiver_ptr, receiver_len)?;
141 let ident = read_memory(caller.as_context_mut(), memory, ident_ptr, ident_len)?;
142 let args = read_memory(caller.as_context_mut(), memory, args_ptr, args_len)?;
143
144 runtime
145 .object_call_module(receiver, module_id, ident, args)
146 .map(|buffer| buffer.0)
147}
148
149fn call_function(
150 mut caller: Caller<'_, HostState>,
151 package_address_ptr: u32,
152 package_address_len: u32,
153 blueprint_name_ptr: u32,
154 blueprint_name_len: u32,
155 ident_ptr: u32,
156 ident_len: u32,
157 args_ptr: u32,
158 args_len: u32,
159) -> Result<u64, InvokeError<WasmRuntimeError>> {
160 let runtime = grab_runtime!(caller);
161 let memory = grab_memory!(caller);
162
163 let package_address = read_memory(
164 caller.as_context_mut(),
165 memory,
166 package_address_ptr,
167 package_address_len,
168 )?;
169 let blueprint_name = read_memory(
170 caller.as_context_mut(),
171 memory,
172 blueprint_name_ptr,
173 blueprint_name_len,
174 )?;
175 let ident = read_memory(caller.as_context_mut(), memory, ident_ptr, ident_len)?;
176 let args = read_memory(caller.as_context_mut(), memory, args_ptr, args_len)?;
177
178 runtime
179 .blueprint_call(package_address, blueprint_name, ident, args)
180 .map(|buffer| buffer.0)
181}
182
183fn new_object(
184 mut caller: Caller<'_, HostState>,
185 blueprint_name_ptr: u32,
186 blueprint_name_len: u32,
187 object_states_ptr: u32,
188 object_states_len: u32,
189) -> Result<u64, InvokeError<WasmRuntimeError>> {
190 let runtime = grab_runtime!(caller);
191 let memory = grab_memory!(caller);
192
193 runtime
194 .object_new(
195 read_memory(
196 caller.as_context_mut(),
197 memory,
198 blueprint_name_ptr,
199 blueprint_name_len,
200 )?,
201 read_memory(
202 caller.as_context_mut(),
203 memory,
204 object_states_ptr,
205 object_states_len,
206 )?,
207 )
208 .map(|buffer| buffer.0)
209}
210
211fn new_key_value_store(
212 mut caller: Caller<'_, HostState>,
213 schema_id_ptr: u32,
214 schema_id_len: u32,
215) -> Result<u64, InvokeError<WasmRuntimeError>> {
216 let runtime = grab_runtime!(caller);
217 let memory = grab_memory!(caller);
218
219 runtime
220 .key_value_store_new(read_memory(
221 caller.as_context_mut(),
222 memory,
223 schema_id_ptr,
224 schema_id_len,
225 )?)
226 .map(|buffer| buffer.0)
227}
228
229fn allocate_global_address(
230 mut caller: Caller<'_, HostState>,
231 package_address_ptr: u32,
232 package_address_len: u32,
233 blueprint_name_ptr: u32,
234 blueprint_name_len: u32,
235) -> Result<u64, InvokeError<WasmRuntimeError>> {
236 let runtime = grab_runtime!(caller);
237 let memory = grab_memory!(caller);
238
239 runtime
240 .address_allocate(
241 read_memory(
242 caller.as_context_mut(),
243 memory,
244 package_address_ptr,
245 package_address_len,
246 )?,
247 read_memory(
248 caller.as_context_mut(),
249 memory,
250 blueprint_name_ptr,
251 blueprint_name_len,
252 )?,
253 )
254 .map(|buffer| buffer.0)
255}
256
257fn get_reservation_address(
258 mut caller: Caller<'_, HostState>,
259 node_id_ptr: u32,
260 node_id_len: u32,
261) -> Result<u64, InvokeError<WasmRuntimeError>> {
262 let runtime = grab_runtime!(caller);
263 let memory = grab_memory!(caller);
264
265 runtime
266 .address_get_reservation_address(read_memory(
267 caller.as_context_mut(),
268 memory,
269 node_id_ptr,
270 node_id_len,
271 )?)
272 .map(|buffer| buffer.0)
273}
274
275fn execution_cost_unit_limit(
276 caller: Caller<'_, HostState>,
277) -> Result<u32, InvokeError<WasmRuntimeError>> {
278 let runtime = grab_runtime!(caller);
279
280 runtime.costing_get_execution_cost_unit_limit()
281}
282
283fn execution_cost_unit_price(
284 caller: Caller<'_, HostState>,
285) -> Result<u64, InvokeError<WasmRuntimeError>> {
286 let runtime = grab_runtime!(caller);
287
288 runtime
289 .costing_get_execution_cost_unit_price()
290 .map(|buffer| buffer.0)
291}
292
293fn finalization_cost_unit_limit(
294 caller: Caller<'_, HostState>,
295) -> Result<u32, InvokeError<WasmRuntimeError>> {
296 let runtime = grab_runtime!(caller);
297
298 runtime.costing_get_finalization_cost_unit_limit()
299}
300
301fn finalization_cost_unit_price(
302 caller: Caller<'_, HostState>,
303) -> Result<u64, InvokeError<WasmRuntimeError>> {
304 let runtime = grab_runtime!(caller);
305
306 runtime
307 .costing_get_finalization_cost_unit_price()
308 .map(|buffer| buffer.0)
309}
310
311fn usd_price(caller: Caller<'_, HostState>) -> Result<u64, InvokeError<WasmRuntimeError>> {
312 let runtime = grab_runtime!(caller);
313
314 runtime.costing_get_usd_price().map(|buffer| buffer.0)
315}
316
317fn tip_percentage(caller: Caller<'_, HostState>) -> Result<u32, InvokeError<WasmRuntimeError>> {
318 let runtime = grab_runtime!(caller);
319
320 runtime.costing_get_tip_percentage()
321}
322
323fn fee_balance(caller: Caller<'_, HostState>) -> Result<u64, InvokeError<WasmRuntimeError>> {
324 let runtime = grab_runtime!(caller);
325
326 runtime.costing_get_fee_balance().map(|buffer| buffer.0)
327}
328
329fn globalize_object(
330 mut caller: Caller<'_, HostState>,
331 obj_id_ptr: u32,
332 obj_id_len: u32,
333 modules_ptr: u32,
334 modules_len: u32,
335 address_ptr: u32,
336 address_len: u32,
337) -> Result<u64, InvokeError<WasmRuntimeError>> {
338 let runtime = grab_runtime!(caller);
339 let memory = grab_memory!(caller);
340
341 runtime
342 .globalize_object(
343 read_memory(caller.as_context_mut(), memory, obj_id_ptr, obj_id_len)?,
344 read_memory(caller.as_context_mut(), memory, modules_ptr, modules_len)?,
345 read_memory(caller.as_context_mut(), memory, address_ptr, address_len)?,
346 )
347 .map(|buffer| buffer.0)
348}
349
350fn instance_of(
351 mut caller: Caller<'_, HostState>,
352 component_id_ptr: u32,
353 component_id_len: u32,
354 package_address_ptr: u32,
355 package_address_len: u32,
356 blueprint_name_ptr: u32,
357 blueprint_name_len: u32,
358) -> Result<u32, InvokeError<WasmRuntimeError>> {
359 let runtime = grab_runtime!(caller);
360 let memory = grab_memory!(caller);
361
362 runtime.instance_of(
363 read_memory(
364 caller.as_context_mut(),
365 memory,
366 component_id_ptr,
367 component_id_len,
368 )?,
369 read_memory(
370 caller.as_context_mut(),
371 memory,
372 package_address_ptr,
373 package_address_len,
374 )?,
375 read_memory(
376 caller.as_context_mut(),
377 memory,
378 blueprint_name_ptr,
379 blueprint_name_len,
380 )?,
381 )
382}
383
384fn blueprint_id(
385 mut caller: Caller<'_, HostState>,
386 component_id_ptr: u32,
387 component_id_len: u32,
388) -> Result<u64, InvokeError<WasmRuntimeError>> {
389 let runtime = grab_runtime!(caller);
390 let memory = grab_memory!(caller);
391
392 runtime
393 .blueprint_id(read_memory(
394 caller.as_context_mut(),
395 memory,
396 component_id_ptr,
397 component_id_len,
398 )?)
399 .map(|buffer| buffer.0)
400}
401
402fn get_outer_object(
403 mut caller: Caller<'_, HostState>,
404 component_id_ptr: u32,
405 component_id_len: u32,
406) -> Result<u64, InvokeError<WasmRuntimeError>> {
407 let runtime = grab_runtime!(caller);
408 let memory = grab_memory!(caller);
409
410 runtime
411 .get_outer_object(read_memory(
412 caller.as_context_mut(),
413 memory,
414 component_id_ptr,
415 component_id_len,
416 )?)
417 .map(|buffer| buffer.0)
418}
419
420fn lock_key_value_store_entry(
421 mut caller: Caller<'_, HostState>,
422 node_id_ptr: u32,
423 node_id_len: u32,
424 offset_ptr: u32,
425 offset_len: u32,
426 flags: u32,
427) -> Result<u32, InvokeError<WasmRuntimeError>> {
428 let runtime = grab_runtime!(caller);
429 let memory = grab_memory!(caller);
430
431 let node_id = read_memory(caller.as_context_mut(), memory, node_id_ptr, node_id_len)?;
432 let substate_key = read_memory(caller.as_context_mut(), memory, offset_ptr, offset_len)?;
433
434 runtime.key_value_store_open_entry(node_id, substate_key, flags)
435}
436
437fn key_value_entry_get(
438 caller: Caller<'_, HostState>,
439 handle: u32,
440) -> Result<u64, InvokeError<WasmRuntimeError>> {
441 let runtime = grab_runtime!(caller);
442
443 runtime.key_value_entry_get(handle).map(|buffer| buffer.0)
444}
445
446fn key_value_entry_set(
447 mut caller: Caller<'_, HostState>,
448 handle: u32,
449 buffer_ptr: u32,
450 buffer_len: u32,
451) -> Result<(), InvokeError<WasmRuntimeError>> {
452 let runtime = grab_runtime!(caller);
453 let memory = grab_memory!(caller);
454 let data = read_memory(caller.as_context_mut(), memory, buffer_ptr, buffer_len)?;
455 runtime.key_value_entry_set(handle, data)
456}
457
458fn key_value_entry_remove(
459 caller: Caller<'_, HostState>,
460 handle: u32,
461) -> Result<u64, InvokeError<WasmRuntimeError>> {
462 let runtime = grab_runtime!(caller);
463
464 runtime
465 .key_value_entry_remove(handle)
466 .map(|buffer| buffer.0)
467}
468
469fn unlock_key_value_entry(
470 caller: Caller<'_, HostState>,
471 handle: u32,
472) -> Result<(), InvokeError<WasmRuntimeError>> {
473 let runtime = grab_runtime!(caller);
474
475 runtime.key_value_entry_close(handle)
476}
477
478fn key_value_store_remove(
479 mut caller: Caller<'_, HostState>,
480 node_id_ptr: u32,
481 node_id_len: u32,
482 key_ptr: u32,
483 key_len: u32,
484) -> Result<u64, InvokeError<WasmRuntimeError>> {
485 let runtime = grab_runtime!(caller);
486 let memory = grab_memory!(caller);
487 let node_id = read_memory(caller.as_context_mut(), memory, node_id_ptr, node_id_len)?;
488 let key = read_memory(caller.as_context_mut(), memory, key_ptr, key_len)?;
489
490 runtime
491 .key_value_store_remove_entry(node_id, key)
492 .map(|buffer| buffer.0)
493}
494
495fn lock_field(
496 caller: Caller<'_, HostState>,
497 object_handle: u32,
498 field: u32,
499 flags: u32,
500) -> Result<u32, InvokeError<WasmRuntimeError>> {
501 let runtime = grab_runtime!(caller);
502
503 runtime.actor_open_field(object_handle, field as u8, flags)
504}
505
506fn field_lock_read(
507 caller: Caller<'_, HostState>,
508 handle: u32,
509) -> Result<u64, InvokeError<WasmRuntimeError>> {
510 let runtime = grab_runtime!(caller);
511
512 runtime.field_entry_read(handle).map(|buffer| buffer.0)
513}
514
515fn field_lock_write(
516 mut caller: Caller<'_, HostState>,
517 handle: u32,
518 data_ptr: u32,
519 data_len: u32,
520) -> Result<(), InvokeError<WasmRuntimeError>> {
521 let runtime = grab_runtime!(caller);
522 let memory = grab_memory!(caller);
523
524 let data = read_memory(caller.as_context_mut(), memory, data_ptr, data_len)?;
525
526 runtime.field_entry_write(handle, data)
527}
528
529fn field_lock_release(
530 caller: Caller<'_, HostState>,
531 handle: u32,
532) -> Result<(), InvokeError<WasmRuntimeError>> {
533 let runtime = grab_runtime!(caller);
534
535 runtime.field_entry_close(handle)
536}
537
538fn actor_get_node_id(
539 caller: Caller<'_, HostState>,
540 handle: u32,
541) -> Result<u64, InvokeError<WasmRuntimeError>> {
542 let runtime = grab_runtime!(caller);
543
544 runtime.actor_get_node_id(handle).map(|buffer| buffer.0)
545}
546
547fn get_package_address(
548 caller: Caller<'_, HostState>,
549) -> Result<u64, InvokeError<WasmRuntimeError>> {
550 let runtime = grab_runtime!(caller);
551
552 runtime.actor_get_package_address().map(|buffer| buffer.0)
553}
554
555fn get_blueprint_name(caller: Caller<'_, HostState>) -> Result<u64, InvokeError<WasmRuntimeError>> {
556 let runtime = grab_runtime!(caller);
557
558 runtime.actor_get_blueprint_name().map(|buffer| buffer.0)
559}
560
561#[inline]
562fn consume_wasm_execution_units(
563 caller: Caller<'_, HostState>,
564 n: u64,
565) -> Result<(), InvokeError<WasmRuntimeError>> {
566 let runtime: &mut Box<dyn WasmRuntime> =
567 unsafe { &mut *caller.data().runtime_ptr.assume_init() };
568
569 runtime.consume_wasm_execution_units(n as u32)
572}
573
574fn emit_event(
575 mut caller: Caller<'_, HostState>,
576 event_name_ptr: u32,
577 event_name_len: u32,
578 event_data_ptr: u32,
579 event_data_len: u32,
580 flags: u32,
581) -> Result<(), InvokeError<WasmRuntimeError>> {
582 let runtime = grab_runtime!(caller);
583 let memory = grab_memory!(caller);
584
585 let event_name = read_memory(
586 caller.as_context_mut(),
587 memory,
588 event_name_ptr,
589 event_name_len,
590 )?;
591 let event_data = read_memory(
592 caller.as_context_mut(),
593 memory,
594 event_data_ptr,
595 event_data_len,
596 )?;
597 let event_flags = EventFlags::from_bits(flags).ok_or(InvokeError::SelfError(
598 WasmRuntimeError::InvalidEventFlags(flags),
599 ))?;
600
601 runtime.actor_emit_event(event_name, event_data, event_flags)
602}
603
604fn get_transaction_hash(
605 caller: Caller<'_, HostState>,
606) -> Result<u64, InvokeError<WasmRuntimeError>> {
607 let runtime = grab_runtime!(caller);
608
609 runtime.sys_get_transaction_hash().map(|buffer| buffer.0)
610}
611
612fn generate_ruid(caller: Caller<'_, HostState>) -> Result<u64, InvokeError<WasmRuntimeError>> {
613 let runtime = grab_runtime!(caller);
614
615 runtime.sys_generate_ruid().map(|buffer| buffer.0)
616}
617
618fn emit_log(
619 mut caller: Caller<'_, HostState>,
620 level_ptr: u32,
621 level_len: u32,
622 message_ptr: u32,
623 message_len: u32,
624) -> Result<(), InvokeError<WasmRuntimeError>> {
625 let runtime = grab_runtime!(caller);
626 let memory = grab_memory!(caller);
627
628 let level = read_memory(caller.as_context_mut(), memory, level_ptr, level_len)?;
629 let message = read_memory(caller.as_context_mut(), memory, message_ptr, message_len)?;
630
631 runtime.sys_log(level, message)
632}
633
634fn bech32_encode_address(
635 mut caller: Caller<'_, HostState>,
636 address_ptr: u32,
637 address_len: u32,
638) -> Result<u64, InvokeError<WasmRuntimeError>> {
639 let runtime = grab_runtime!(caller);
640 let memory = grab_memory!(caller);
641
642 let address = read_memory(caller.as_context_mut(), memory, address_ptr, address_len)?;
643
644 runtime
645 .sys_bech32_encode_address(address)
646 .map(|buffer| buffer.0)
647}
648
649fn panic(
650 mut caller: Caller<'_, HostState>,
651 message_ptr: u32,
652 message_len: u32,
653) -> Result<(), InvokeError<WasmRuntimeError>> {
654 let runtime = grab_runtime!(caller);
655 let memory = grab_memory!(caller);
656
657 let message = read_memory(caller.as_context_mut(), memory, message_ptr, message_len)?;
658
659 runtime.sys_panic(message)
660}
661
662fn bls12381_v1_verify(
663 mut caller: Caller<'_, HostState>,
664 message_ptr: u32,
665 message_len: u32,
666 public_key_ptr: u32,
667 public_key_len: u32,
668 signature_ptr: u32,
669 signature_len: u32,
670) -> Result<u32, InvokeError<WasmRuntimeError>> {
671 let runtime = grab_runtime!(caller);
672 let memory = grab_memory!(caller);
673
674 let message = read_memory(caller.as_context_mut(), memory, message_ptr, message_len)?;
675 let public_key = read_memory(
676 caller.as_context_mut(),
677 memory,
678 public_key_ptr,
679 public_key_len,
680 )?;
681 let signature = read_memory(
682 caller.as_context_mut(),
683 memory,
684 signature_ptr,
685 signature_len,
686 )?;
687
688 runtime.crypto_utils_bls12381_v1_verify(message, public_key, signature)
689}
690
691fn bls12381_v1_aggregate_verify(
692 mut caller: Caller<'_, HostState>,
693 pub_keys_and_msgs_ptr: u32,
694 pub_keys_and_msgs_len: u32,
695 signature_ptr: u32,
696 signature_len: u32,
697) -> Result<u32, InvokeError<WasmRuntimeError>> {
698 let runtime = grab_runtime!(caller);
699 let memory = grab_memory!(caller);
700
701 let pub_keys_and_msgs = read_memory(
702 caller.as_context_mut(),
703 memory,
704 pub_keys_and_msgs_ptr,
705 pub_keys_and_msgs_len,
706 )?;
707 let signature = read_memory(
708 caller.as_context_mut(),
709 memory,
710 signature_ptr,
711 signature_len,
712 )?;
713
714 runtime.crypto_utils_bls12381_v1_aggregate_verify(pub_keys_and_msgs, signature)
715}
716
717fn bls12381_v1_fast_aggregate_verify(
718 mut caller: Caller<'_, HostState>,
719 message_ptr: u32,
720 message_len: u32,
721 public_keys_ptr: u32,
722 public_keys_len: u32,
723 signature_ptr: u32,
724 signature_len: u32,
725) -> Result<u32, InvokeError<WasmRuntimeError>> {
726 let runtime = grab_runtime!(caller);
727 let memory = grab_memory!(caller);
728
729 let message = read_memory(caller.as_context_mut(), memory, message_ptr, message_len)?;
730 let public_keys = read_memory(
731 caller.as_context_mut(),
732 memory,
733 public_keys_ptr,
734 public_keys_len,
735 )?;
736 let signature = read_memory(
737 caller.as_context_mut(),
738 memory,
739 signature_ptr,
740 signature_len,
741 )?;
742
743 runtime.crypto_utils_bls12381_v1_fast_aggregate_verify(message, public_keys, signature)
744}
745
746fn bls12381_g2_signature_aggregate(
747 mut caller: Caller<'_, HostState>,
748 signatures_ptr: u32,
749 signatures_len: u32,
750) -> Result<u64, InvokeError<WasmRuntimeError>> {
751 let runtime = grab_runtime!(caller);
752 let memory = grab_memory!(caller);
753
754 let signatures = read_memory(
755 caller.as_context_mut(),
756 memory,
757 signatures_ptr,
758 signatures_len,
759 )?;
760
761 runtime
762 .crypto_utils_bls12381_g2_signature_aggregate(signatures)
763 .map(|buffer| buffer.0)
764}
765
766fn keccak256_hash(
767 mut caller: Caller<'_, HostState>,
768 data_ptr: u32,
769 data_len: u32,
770) -> Result<u64, InvokeError<WasmRuntimeError>> {
771 let runtime = grab_runtime!(caller);
772 let memory = grab_memory!(caller);
773
774 let data = read_memory(caller.as_context_mut(), memory, data_ptr, data_len)?;
775
776 runtime
777 .crypto_utils_keccak256_hash(data)
778 .map(|buffer| buffer.0)
779}
780
781fn blake2b_256_hash(
782 mut caller: Caller<'_, HostState>,
783 data_ptr: u32,
784 data_len: u32,
785) -> Result<u64, InvokeError<WasmRuntimeError>> {
786 let runtime = grab_runtime!(caller);
787 let memory = grab_memory!(caller);
788
789 let data = read_memory(caller.as_context_mut(), memory, data_ptr, data_len)?;
790
791 runtime
792 .crypto_utils_blake2b_256_hash(data)
793 .map(|buffer| buffer.0)
794}
795
796fn ed25519_verify(
797 mut caller: Caller<'_, HostState>,
798 message_ptr: u32,
799 message_len: u32,
800 public_key_ptr: u32,
801 public_key_len: u32,
802 signature_ptr: u32,
803 signature_len: u32,
804) -> Result<u32, InvokeError<WasmRuntimeError>> {
805 let runtime = grab_runtime!(caller);
806 let memory = grab_memory!(caller);
807
808 let message = read_memory(caller.as_context_mut(), memory, message_ptr, message_len)?;
809 let public_key = read_memory(
810 caller.as_context_mut(),
811 memory,
812 public_key_ptr,
813 public_key_len,
814 )?;
815 let signature = read_memory(
816 caller.as_context_mut(),
817 memory,
818 signature_ptr,
819 signature_len,
820 )?;
821
822 runtime.crypto_utils_ed25519_verify(message, public_key, signature)
823}
824
825fn secp256k1_ecdsa_verify(
826 mut caller: Caller<'_, HostState>,
827 message_ptr: u32,
828 message_len: u32,
829 public_key_ptr: u32,
830 public_key_len: u32,
831 signature_ptr: u32,
832 signature_len: u32,
833) -> Result<u32, InvokeError<WasmRuntimeError>> {
834 let runtime = grab_runtime!(caller);
835 let memory = grab_memory!(caller);
836
837 let message = read_memory(caller.as_context_mut(), memory, message_ptr, message_len)?;
838 let public_key = read_memory(
839 caller.as_context_mut(),
840 memory,
841 public_key_ptr,
842 public_key_len,
843 )?;
844 let signature = read_memory(
845 caller.as_context_mut(),
846 memory,
847 signature_ptr,
848 signature_len,
849 )?;
850
851 runtime.crypto_utils_secp256k1_ecdsa_verify(message, public_key, signature)
852}
853
854fn secp256k1_ecdsa_verify_and_key_recover(
855 mut caller: Caller<'_, HostState>,
856 message_ptr: u32,
857 message_len: u32,
858 signature_ptr: u32,
859 signature_len: u32,
860) -> Result<u64, InvokeError<WasmRuntimeError>> {
861 let runtime = grab_runtime!(caller);
862 let memory = grab_memory!(caller);
863
864 let message = read_memory(caller.as_context_mut(), memory, message_ptr, message_len)?;
865 let signature = read_memory(
866 caller.as_context_mut(),
867 memory,
868 signature_ptr,
869 signature_len,
870 )?;
871
872 runtime
873 .crypto_utils_secp256k1_ecdsa_verify_and_key_recover(message, signature)
874 .map(|buffer| buffer.0)
875}
876
877fn secp256k1_ecdsa_verify_and_key_recover_uncompressed(
878 mut caller: Caller<'_, HostState>,
879 message_ptr: u32,
880 message_len: u32,
881 signature_ptr: u32,
882 signature_len: u32,
883) -> Result<u64, InvokeError<WasmRuntimeError>> {
884 let runtime = grab_runtime!(caller);
885 let memory = grab_memory!(caller);
886
887 let message = read_memory(caller.as_context_mut(), memory, message_ptr, message_len)?;
888 let signature = read_memory(
889 caller.as_context_mut(),
890 memory,
891 signature_ptr,
892 signature_len,
893 )?;
894
895 runtime
896 .crypto_utils_secp256k1_ecdsa_verify_and_key_recover_uncompressed(message, signature)
897 .map(|buffer| buffer.0)
898}
899
900#[cfg(feature = "radix_engine_tests")]
901fn test_host_read_memory(
902 mut caller: Caller<'_, HostState>,
903 memory_offs: u32,
904 data_len: u32,
905) -> Result<(), InvokeError<WasmRuntimeError>> {
906 let memory = grab_memory!(caller);
908
909 read_memory(caller.as_context_mut(), memory, memory_offs, data_len)?;
910
911 Ok(())
912}
913
914#[cfg(feature = "radix_engine_tests")]
915fn test_host_write_memory(
916 mut caller: Caller<'_, HostState>,
917 memory_ptr: u32,
918 data_len: u32,
919) -> Result<(), InvokeError<WasmRuntimeError>> {
920 let memory = grab_memory!(caller);
923
924 let data = vec![0u8; data_len as usize];
925 write_memory(caller.as_context_mut(), memory, memory_ptr, &data)?;
926
927 Ok(())
928}
929
930#[cfg(feature = "radix_engine_tests")]
931fn test_host_check_memory_is_clean(
932 caller: Caller<'_, HostState>,
933) -> Result<u64, InvokeError<WasmRuntimeError>> {
934 let memory = grab_memory!(caller);
936 let store_ctx = caller.as_context();
937
938 let data = memory.data(&store_ctx);
939 let clean = !data.iter().any(|&x| x != 0x0);
940
941 Ok(clean as u64)
942}
943macro_rules! linker_define {
946 ($linker: expr, $name: expr, $var: expr) => {
947 $linker
948 .define(MODULE_ENV_NAME, $name, $var)
949 .expect(stringify!("Failed to define new linker item {}", $name));
950 };
951}
952
953#[derive(Debug)]
954pub enum WasmiInstantiationError {
955 CompilationError(Error),
956 PreInstantiationError(Error),
957 InstantiationError(InstantiationError),
958}
959
960impl WasmiModule {
961 pub fn new(code: &[u8]) -> Result<Self, WasmiInstantiationError> {
962 let mut config = wasmi::Config::default();
963
964 config.compilation_mode(wasmi::CompilationMode::LazyTranslation);
972 let engine = Engine::new(&config);
973
974 let module = unsafe {
975 Module::new_unchecked(&engine, code)
976 .map_err(WasmiInstantiationError::CompilationError)?
977 };
978
979 Ok(Self {
980 module,
981 code_size_bytes: code.len(),
982 })
983 }
984
985 fn host_funcs_set(module: &Module, store: &mut Store<HostState>) -> Result<InstancePre, Error> {
986 let host_consume_buffer = Func::wrap(
987 store.as_context_mut(),
988 |caller: Caller<'_, HostState>,
989 buffer_id: BufferId,
990 destination_ptr: u32|
991 -> Result<(), Error> {
992 consume_buffer(caller, buffer_id, destination_ptr).map_err(|e| Error::host(e))
993 },
994 );
995
996 let host_call_method = Func::wrap(
997 store.as_context_mut(),
998 |caller: Caller<'_, HostState>,
999 receiver_ptr: u32,
1000 receiver_len: u32,
1001 ident_ptr: u32,
1002 ident_len: u32,
1003 args_ptr: u32,
1004 args_len: u32|
1005 -> Result<u64, Error> {
1006 call_method(
1007 caller,
1008 receiver_ptr,
1009 receiver_len,
1010 ident_ptr,
1011 ident_len,
1012 args_ptr,
1013 args_len,
1014 )
1015 .map_err(|e| Error::host(e))
1016 },
1017 );
1018
1019 let host_call_module_method = Func::wrap(
1020 store.as_context_mut(),
1021 |caller: Caller<'_, HostState>,
1022 receiver_ptr: u32,
1023 receiver_len: u32,
1024 module_id: u32,
1025 ident_ptr: u32,
1026 ident_len: u32,
1027 args_ptr: u32,
1028 args_len: u32|
1029 -> Result<u64, Error> {
1030 call_module_method(
1031 caller,
1032 receiver_ptr,
1033 receiver_len,
1034 module_id,
1035 ident_ptr,
1036 ident_len,
1037 args_ptr,
1038 args_len,
1039 )
1040 .map_err(|e| Error::host(e))
1041 },
1042 );
1043
1044 let host_call_direct_method = Func::wrap(
1045 store.as_context_mut(),
1046 |caller: Caller<'_, HostState>,
1047 receiver_ptr: u32,
1048 receiver_len: u32,
1049 ident_ptr: u32,
1050 ident_len: u32,
1051 args_ptr: u32,
1052 args_len: u32|
1053 -> Result<u64, Error> {
1054 call_direct_method(
1055 caller,
1056 receiver_ptr,
1057 receiver_len,
1058 ident_ptr,
1059 ident_len,
1060 args_ptr,
1061 args_len,
1062 )
1063 .map_err(|e| Error::host(e))
1064 },
1065 );
1066
1067 let host_blueprint_call = Func::wrap(
1068 store.as_context_mut(),
1069 |caller: Caller<'_, HostState>,
1070 package_address_ptr: u32,
1071 package_address_len: u32,
1072 blueprint_name_ptr: u32,
1073 blueprint_name_len: u32,
1074 ident_ptr: u32,
1075 ident_len: u32,
1076 args_ptr: u32,
1077 args_len: u32|
1078 -> Result<u64, Error> {
1079 call_function(
1080 caller,
1081 package_address_ptr,
1082 package_address_len,
1083 blueprint_name_ptr,
1084 blueprint_name_len,
1085 ident_ptr,
1086 ident_len,
1087 args_ptr,
1088 args_len,
1089 )
1090 .map_err(|e| Error::host(e))
1091 },
1092 );
1093
1094 let host_new_component = Func::wrap(
1095 store.as_context_mut(),
1096 |caller: Caller<'_, HostState>,
1097 blueprint_name_ptr: u32,
1098 blueprint_name_len: u32,
1099 object_states_ptr: u32,
1100 object_states_len: u32|
1101 -> Result<u64, Error> {
1102 new_object(
1103 caller,
1104 blueprint_name_ptr,
1105 blueprint_name_len,
1106 object_states_ptr,
1107 object_states_len,
1108 )
1109 .map_err(|e| Error::host(e))
1110 },
1111 );
1112
1113 let host_new_key_value_store = Func::wrap(
1114 store.as_context_mut(),
1115 |caller: Caller<'_, HostState>,
1116 schema_ptr: u32,
1117 schema_len: u32|
1118 -> Result<u64, Error> {
1119 new_key_value_store(caller, schema_ptr, schema_len).map_err(|e| Error::host(e))
1120 },
1121 );
1122
1123 let host_allocate_global_address = Func::wrap(
1124 store.as_context_mut(),
1125 |caller: Caller<'_, HostState>,
1126 package_address_ptr: u32,
1127 package_address_len: u32,
1128 blueprint_name_ptr: u32,
1129 blueprint_name_len: u32|
1130 -> Result<u64, Error> {
1131 allocate_global_address(
1132 caller,
1133 package_address_ptr,
1134 package_address_len,
1135 blueprint_name_ptr,
1136 blueprint_name_len,
1137 )
1138 .map_err(|e| Error::host(e))
1139 },
1140 );
1141
1142 let host_get_reservation_address = Func::wrap(
1143 store.as_context_mut(),
1144 |caller: Caller<'_, HostState>,
1145 node_id_ptr: u32,
1146 node_id_len: u32|
1147 -> Result<u64, Error> {
1148 get_reservation_address(caller, node_id_ptr, node_id_len)
1149 .map_err(|e| Error::host(e))
1150 },
1151 );
1152
1153 let host_execution_cost_unit_limit = Func::wrap(
1154 store.as_context_mut(),
1155 |caller: Caller<'_, HostState>| -> Result<u32, Error> {
1156 execution_cost_unit_limit(caller).map_err(|e| Error::host(e))
1157 },
1158 );
1159
1160 let host_execution_cost_unit_price = Func::wrap(
1161 store.as_context_mut(),
1162 |caller: Caller<'_, HostState>| -> Result<u64, Error> {
1163 execution_cost_unit_price(caller).map_err(|e| Error::host(e))
1164 },
1165 );
1166
1167 let host_finalization_cost_unit_limit = Func::wrap(
1168 store.as_context_mut(),
1169 |caller: Caller<'_, HostState>| -> Result<u32, Error> {
1170 finalization_cost_unit_limit(caller).map_err(|e| Error::host(e))
1171 },
1172 );
1173
1174 let host_finalization_cost_unit_price = Func::wrap(
1175 store.as_context_mut(),
1176 |caller: Caller<'_, HostState>| -> Result<u64, Error> {
1177 finalization_cost_unit_price(caller).map_err(|e| Error::host(e))
1178 },
1179 );
1180
1181 let host_usd_price = Func::wrap(
1182 store.as_context_mut(),
1183 |caller: Caller<'_, HostState>| -> Result<u64, Error> {
1184 usd_price(caller).map_err(|e| Error::host(e))
1185 },
1186 );
1187
1188 let host_tip_percentage = Func::wrap(
1189 store.as_context_mut(),
1190 |caller: Caller<'_, HostState>| -> Result<u32, Error> {
1191 tip_percentage(caller).map_err(|e| Error::host(e))
1192 },
1193 );
1194
1195 let host_fee_balance = Func::wrap(
1196 store.as_context_mut(),
1197 |caller: Caller<'_, HostState>| -> Result<u64, Error> {
1198 fee_balance(caller).map_err(|e| Error::host(e))
1199 },
1200 );
1201
1202 let host_globalize_object = Func::wrap(
1203 store.as_context_mut(),
1204 |caller: Caller<'_, HostState>,
1205 obj_ptr: u32,
1206 obj_len: u32,
1207 modules_ptr: u32,
1208 modules_len: u32,
1209 address_ptr: u32,
1210 address_len: u32|
1211 -> Result<u64, Error> {
1212 globalize_object(
1213 caller,
1214 obj_ptr,
1215 obj_len,
1216 modules_ptr,
1217 modules_len,
1218 address_ptr,
1219 address_len,
1220 )
1221 .map_err(|e| Error::host(e))
1222 },
1223 );
1224
1225 let host_instance_of = Func::wrap(
1226 store.as_context_mut(),
1227 |caller: Caller<'_, HostState>,
1228 object_id_ptr: u32,
1229 object_id_len: u32,
1230 package_address_ptr: u32,
1231 package_address_len: u32,
1232 blueprint_name_ptr: u32,
1233 blueprint_name_len: u32|
1234 -> Result<u32, Error> {
1235 instance_of(
1236 caller,
1237 object_id_ptr,
1238 object_id_len,
1239 package_address_ptr,
1240 package_address_len,
1241 blueprint_name_ptr,
1242 blueprint_name_len,
1243 )
1244 .map_err(|e| Error::host(e))
1245 },
1246 );
1247
1248 let host_get_blueprint_id = Func::wrap(
1249 store.as_context_mut(),
1250 |caller: Caller<'_, HostState>,
1251 object_id_ptr: u32,
1252 object_id_len: u32|
1253 -> Result<u64, Error> {
1254 blueprint_id(caller, object_id_ptr, object_id_len).map_err(|e| Error::host(e))
1255 },
1256 );
1257
1258 let host_get_outer_object = Func::wrap(
1259 store.as_context_mut(),
1260 |caller: Caller<'_, HostState>,
1261 object_id_ptr: u32,
1262 object_id_len: u32|
1263 -> Result<u64, Error> {
1264 get_outer_object(caller, object_id_ptr, object_id_len).map_err(|e| Error::host(e))
1265 },
1266 );
1267
1268 let host_lock_key_value_store_entry = Func::wrap(
1269 store.as_context_mut(),
1270 |caller: Caller<'_, HostState>,
1271 node_id_ptr: u32,
1272 node_id_len: u32,
1273 offset_ptr: u32,
1274 offset_len: u32,
1275 mutable: u32|
1276 -> Result<u32, Error> {
1277 lock_key_value_store_entry(
1278 caller,
1279 node_id_ptr,
1280 node_id_len,
1281 offset_ptr,
1282 offset_len,
1283 mutable,
1284 )
1285 .map_err(|e| Error::host(e))
1286 },
1287 );
1288
1289 let host_key_value_entry_get = Func::wrap(
1290 store.as_context_mut(),
1291 |caller: Caller<'_, HostState>, handle: u32| -> Result<u64, Error> {
1292 key_value_entry_get(caller, handle).map_err(|e| Error::host(e))
1293 },
1294 );
1295
1296 let host_key_value_entry_set = Func::wrap(
1297 store.as_context_mut(),
1298 |caller: Caller<'_, HostState>,
1299 handle: u32,
1300 buffer_ptr: u32,
1301 buffer_len: u32|
1302 -> Result<(), Error> {
1303 key_value_entry_set(caller, handle, buffer_ptr, buffer_len)
1304 .map_err(|e| Error::host(e))
1305 },
1306 );
1307
1308 let host_key_value_entry_remove = Func::wrap(
1309 store.as_context_mut(),
1310 |caller: Caller<'_, HostState>, handle: u32| -> Result<u64, Error> {
1311 key_value_entry_remove(caller, handle).map_err(|e| Error::host(e))
1312 },
1313 );
1314
1315 let host_unlock_key_value_entry = Func::wrap(
1316 store.as_context_mut(),
1317 |caller: Caller<'_, HostState>, handle: u32| -> Result<(), Error> {
1318 unlock_key_value_entry(caller, handle).map_err(|e| Error::host(e))
1319 },
1320 );
1321
1322 let host_key_value_store_remove = Func::wrap(
1323 store.as_context_mut(),
1324 |caller: Caller<'_, HostState>,
1325 node_id_ptr: u32,
1326 node_id_len: u32,
1327 key_ptr: u32,
1328 key_len: u32|
1329 -> Result<u64, Error> {
1330 key_value_store_remove(caller, node_id_ptr, node_id_len, key_ptr, key_len)
1331 .map_err(|e| Error::host(e))
1332 },
1333 );
1334
1335 let host_lock_field = Func::wrap(
1336 store.as_context_mut(),
1337 |caller: Caller<'_, HostState>,
1338 object_handle: u32,
1339 field: u32,
1340 lock_flags: u32|
1341 -> Result<u32, Error> {
1342 lock_field(caller, object_handle, field, lock_flags).map_err(|e| Error::host(e))
1343 },
1344 );
1345
1346 let host_field_lock_read = Func::wrap(
1347 store.as_context_mut(),
1348 |caller: Caller<'_, HostState>, handle: u32| -> Result<u64, Error> {
1349 field_lock_read(caller, handle).map_err(|e| Error::host(e))
1350 },
1351 );
1352
1353 let host_field_lock_write = Func::wrap(
1354 store.as_context_mut(),
1355 |caller: Caller<'_, HostState>,
1356 handle: u32,
1357 data_ptr: u32,
1358 data_len: u32|
1359 -> Result<(), Error> {
1360 field_lock_write(caller, handle, data_ptr, data_len).map_err(|e| Error::host(e))
1361 },
1362 );
1363
1364 let host_field_lock_release = Func::wrap(
1365 store.as_context_mut(),
1366 |caller: Caller<'_, HostState>, handle: u32| -> Result<(), Error> {
1367 field_lock_release(caller, handle).map_err(|e| Error::host(e))
1368 },
1369 );
1370
1371 let host_actor_get_node_id = Func::wrap(
1372 store.as_context_mut(),
1373 |caller: Caller<'_, HostState>, handle: u32| -> Result<u64, Error> {
1374 actor_get_node_id(caller, handle).map_err(|e| Error::host(e))
1375 },
1376 );
1377
1378 let host_get_package_address = Func::wrap(
1379 store.as_context_mut(),
1380 |caller: Caller<'_, HostState>| -> Result<u64, Error> {
1381 get_package_address(caller).map_err(|e| Error::host(e))
1382 },
1383 );
1384
1385 let host_get_blueprint_name = Func::wrap(
1386 store.as_context_mut(),
1387 |caller: Caller<'_, HostState>| -> Result<u64, Error> {
1388 get_blueprint_name(caller).map_err(|e| Error::host(e))
1389 },
1390 );
1391
1392 let host_consume_wasm_execution_units = Func::wrap(
1393 store.as_context_mut(),
1394 |caller: Caller<'_, HostState>, n: u64| -> Result<(), Error> {
1395 consume_wasm_execution_units(caller, n).map_err(|e| Error::host(e))
1396 },
1397 );
1398
1399 let host_emit_event = Func::wrap(
1400 store.as_context_mut(),
1401 |caller: Caller<'_, HostState>,
1402 event_name_ptr: u32,
1403 event_name_len: u32,
1404 event_data_ptr: u32,
1405 event_data_len: u32,
1406 flags: u32|
1407 -> Result<(), Error> {
1408 emit_event(
1409 caller,
1410 event_name_ptr,
1411 event_name_len,
1412 event_data_ptr,
1413 event_data_len,
1414 flags,
1415 )
1416 .map_err(|e| Error::host(e))
1417 },
1418 );
1419
1420 let host_emit_log = Func::wrap(
1421 store.as_context_mut(),
1422 |caller: Caller<'_, HostState>,
1423 level_ptr: u32,
1424 level_len: u32,
1425 message_ptr: u32,
1426 message_len: u32|
1427 -> Result<(), Error> {
1428 emit_log(caller, level_ptr, level_len, message_ptr, message_len)
1429 .map_err(|e| Error::host(e))
1430 },
1431 );
1432
1433 let host_panic = Func::wrap(
1434 store.as_context_mut(),
1435 |caller: Caller<'_, HostState>,
1436 message_ptr: u32,
1437 message_len: u32|
1438 -> Result<(), Error> {
1439 panic(caller, message_ptr, message_len).map_err(|e| Error::host(e))
1440 },
1441 );
1442
1443 let host_bech32_encode_address = Func::wrap(
1444 store.as_context_mut(),
1445 |caller: Caller<'_, HostState>,
1446 address_ptr: u32,
1447 address_len: u32|
1448 -> Result<u64, Error> {
1449 bech32_encode_address(caller, address_ptr, address_len).map_err(|e| Error::host(e))
1450 },
1451 );
1452
1453 let host_get_transaction_hash = Func::wrap(
1454 store.as_context_mut(),
1455 |caller: Caller<'_, HostState>| -> Result<u64, Error> {
1456 get_transaction_hash(caller).map_err(|e| Error::host(e))
1457 },
1458 );
1459
1460 let host_generate_ruid = Func::wrap(
1461 store.as_context_mut(),
1462 |caller: Caller<'_, HostState>| -> Result<u64, Error> {
1463 generate_ruid(caller).map_err(|e| Error::host(e))
1464 },
1465 );
1466
1467 let host_bls12381_v1_verify = Func::wrap(
1468 store.as_context_mut(),
1469 |caller: Caller<'_, HostState>,
1470 message_ptr: u32,
1471 message_len: u32,
1472 public_key_ptr: u32,
1473 public_key_len: u32,
1474 signature_ptr: u32,
1475 signature_len: u32|
1476 -> Result<u32, Error> {
1477 bls12381_v1_verify(
1478 caller,
1479 message_ptr,
1480 message_len,
1481 public_key_ptr,
1482 public_key_len,
1483 signature_ptr,
1484 signature_len,
1485 )
1486 .map_err(|e| Error::host(e))
1487 },
1488 );
1489
1490 let host_bls12381_v1_aggregate_verify = Func::wrap(
1491 store.as_context_mut(),
1492 |caller: Caller<'_, HostState>,
1493 pub_keys_and_msgs_ptr: u32,
1494 pub_keys_and_msgs_len: u32,
1495 signature_ptr: u32,
1496 signature_len: u32|
1497 -> Result<u32, Error> {
1498 bls12381_v1_aggregate_verify(
1499 caller,
1500 pub_keys_and_msgs_ptr,
1501 pub_keys_and_msgs_len,
1502 signature_ptr,
1503 signature_len,
1504 )
1505 .map_err(|e| Error::host(e))
1506 },
1507 );
1508
1509 let host_bls12381_v1_fast_aggregate_verify = Func::wrap(
1510 store.as_context_mut(),
1511 |caller: Caller<'_, HostState>,
1512 message_ptr: u32,
1513 message_len: u32,
1514 public_keys_ptr: u32,
1515 public_keys_len: u32,
1516 signature_ptr: u32,
1517 signature_len: u32|
1518 -> Result<u32, Error> {
1519 bls12381_v1_fast_aggregate_verify(
1520 caller,
1521 message_ptr,
1522 message_len,
1523 public_keys_ptr,
1524 public_keys_len,
1525 signature_ptr,
1526 signature_len,
1527 )
1528 .map_err(|e| Error::host(e))
1529 },
1530 );
1531
1532 let host_bls12381_g2_signature_aggregate = Func::wrap(
1533 store.as_context_mut(),
1534 |caller: Caller<'_, HostState>,
1535 signatures_ptr: u32,
1536 signatures_len: u32|
1537 -> Result<u64, Error> {
1538 bls12381_g2_signature_aggregate(caller, signatures_ptr, signatures_len)
1539 .map_err(|e| Error::host(e))
1540 },
1541 );
1542
1543 let host_keccak256_hash = Func::wrap(
1544 store.as_context_mut(),
1545 |caller: Caller<'_, HostState>, data_ptr: u32, data_len: u32| -> Result<u64, Error> {
1546 keccak256_hash(caller, data_ptr, data_len).map_err(|e| Error::host(e))
1547 },
1548 );
1549
1550 let host_blake2b_256_hash = Func::wrap(
1551 store.as_context_mut(),
1552 |caller: Caller<'_, HostState>, data_ptr: u32, data_len: u32| -> Result<u64, Error> {
1553 blake2b_256_hash(caller, data_ptr, data_len).map_err(|e| Error::host(e))
1554 },
1555 );
1556
1557 let host_ed25519_verify = Func::wrap(
1558 store.as_context_mut(),
1559 |caller: Caller<'_, HostState>,
1560 message_ptr: u32,
1561 message_len: u32,
1562 public_key_ptr: u32,
1563 public_key_len: u32,
1564 signature_ptr: u32,
1565 signature_len: u32|
1566 -> Result<u32, Error> {
1567 ed25519_verify(
1568 caller,
1569 message_ptr,
1570 message_len,
1571 public_key_ptr,
1572 public_key_len,
1573 signature_ptr,
1574 signature_len,
1575 )
1576 .map_err(|e| Error::host(e))
1577 },
1578 );
1579 let host_secp2561k1_ecdsa_verify = Func::wrap(
1580 store.as_context_mut(),
1581 |caller: Caller<'_, HostState>,
1582 message_ptr: u32,
1583 message_len: u32,
1584 public_key_ptr: u32,
1585 public_key_len: u32,
1586 signature_ptr: u32,
1587 signature_len: u32|
1588 -> Result<u32, Error> {
1589 secp256k1_ecdsa_verify(
1590 caller,
1591 message_ptr,
1592 message_len,
1593 public_key_ptr,
1594 public_key_len,
1595 signature_ptr,
1596 signature_len,
1597 )
1598 .map_err(|e| Error::host(e))
1599 },
1600 );
1601 let host_secp2561k1_ecdsa_verify_and_key_recover = Func::wrap(
1602 store.as_context_mut(),
1603 |caller: Caller<'_, HostState>,
1604 message_ptr: u32,
1605 message_len: u32,
1606 signature_ptr: u32,
1607 signature_len: u32|
1608 -> Result<u64, Error> {
1609 secp256k1_ecdsa_verify_and_key_recover(
1610 caller,
1611 message_ptr,
1612 message_len,
1613 signature_ptr,
1614 signature_len,
1615 )
1616 .map_err(|e| Error::host(e))
1617 },
1618 );
1619 let host_secp2561k1_ecdsa_verify_and_key_recover_uncompressed = Func::wrap(
1620 store.as_context_mut(),
1621 |caller: Caller<'_, HostState>,
1622 message_ptr: u32,
1623 message_len: u32,
1624 signature_ptr: u32,
1625 signature_len: u32|
1626 -> Result<u64, Error> {
1627 secp256k1_ecdsa_verify_and_key_recover_uncompressed(
1628 caller,
1629 message_ptr,
1630 message_len,
1631 signature_ptr,
1632 signature_len,
1633 )
1634 .map_err(|e| Error::host(e))
1635 },
1636 );
1637
1638 let mut linker = <Linker<HostState>>::new(module.engine());
1639
1640 linker_define!(linker, BUFFER_CONSUME_FUNCTION_NAME, host_consume_buffer);
1641 linker_define!(linker, OBJECT_CALL_FUNCTION_NAME, host_call_method);
1642 linker_define!(
1643 linker,
1644 OBJECT_CALL_MODULE_FUNCTION_NAME,
1645 host_call_module_method
1646 );
1647 linker_define!(
1648 linker,
1649 OBJECT_CALL_DIRECT_FUNCTION_NAME,
1650 host_call_direct_method
1651 );
1652 linker_define!(linker, BLUEPRINT_CALL_FUNCTION_NAME, host_blueprint_call);
1653 linker_define!(linker, OBJECT_NEW_FUNCTION_NAME, host_new_component);
1654
1655 linker_define!(
1656 linker,
1657 ADDRESS_ALLOCATE_FUNCTION_NAME,
1658 host_allocate_global_address
1659 );
1660 linker_define!(
1661 linker,
1662 ADDRESS_GET_RESERVATION_ADDRESS_FUNCTION_NAME,
1663 host_get_reservation_address
1664 );
1665 linker_define!(
1666 linker,
1667 COSTING_GET_EXECUTION_COST_UNIT_LIMIT_FUNCTION_NAME,
1668 host_execution_cost_unit_limit
1669 );
1670 linker_define!(
1671 linker,
1672 COSTING_GET_EXECUTION_COST_UNIT_PRICE_FUNCTION_NAME,
1673 host_execution_cost_unit_price
1674 );
1675 linker_define!(
1676 linker,
1677 COSTING_GET_FINALIZATION_COST_UNIT_LIMIT_FUNCTION_NAME,
1678 host_finalization_cost_unit_limit
1679 );
1680 linker_define!(
1681 linker,
1682 COSTING_GET_FINALIZATION_COST_UNIT_PRICE_FUNCTION_NAME,
1683 host_finalization_cost_unit_price
1684 );
1685 linker_define!(linker, COSTING_GET_USD_PRICE_FUNCTION_NAME, host_usd_price);
1686 linker_define!(
1687 linker,
1688 COSTING_GET_TIP_PERCENTAGE_FUNCTION_NAME,
1689 host_tip_percentage
1690 );
1691 linker_define!(
1692 linker,
1693 COSTING_GET_FEE_BALANCE_FUNCTION_NAME,
1694 host_fee_balance
1695 );
1696 linker_define!(
1697 linker,
1698 OBJECT_GLOBALIZE_FUNCTION_NAME,
1699 host_globalize_object
1700 );
1701 linker_define!(linker, OBJECT_INSTANCE_OF_FUNCTION_NAME, host_instance_of);
1702 linker_define!(
1703 linker,
1704 OBJECT_GET_BLUEPRINT_ID_FUNCTION_NAME,
1705 host_get_blueprint_id
1706 );
1707 linker_define!(
1708 linker,
1709 OBJECT_GET_OUTER_OBJECT_FUNCTION_NAME,
1710 host_get_outer_object
1711 );
1712 linker_define!(linker, ACTOR_OPEN_FIELD_FUNCTION_NAME, host_lock_field);
1713
1714 linker_define!(
1715 linker,
1716 KEY_VALUE_STORE_NEW_FUNCTION_NAME,
1717 host_new_key_value_store
1718 );
1719 linker_define!(
1720 linker,
1721 KEY_VALUE_STORE_OPEN_ENTRY_FUNCTION_NAME,
1722 host_lock_key_value_store_entry
1723 );
1724 linker_define!(
1725 linker,
1726 KEY_VALUE_ENTRY_READ_FUNCTION_NAME,
1727 host_key_value_entry_get
1728 );
1729 linker_define!(
1730 linker,
1731 KEY_VALUE_ENTRY_WRITE_FUNCTION_NAME,
1732 host_key_value_entry_set
1733 );
1734 linker_define!(
1735 linker,
1736 KEY_VALUE_ENTRY_REMOVE_FUNCTION_NAME,
1737 host_key_value_entry_remove
1738 );
1739 linker_define!(
1740 linker,
1741 KEY_VALUE_ENTRY_CLOSE_FUNCTION_NAME,
1742 host_unlock_key_value_entry
1743 );
1744 linker_define!(
1745 linker,
1746 KEY_VALUE_STORE_REMOVE_ENTRY_FUNCTION_NAME,
1747 host_key_value_store_remove
1748 );
1749
1750 linker_define!(linker, FIELD_ENTRY_READ_FUNCTION_NAME, host_field_lock_read);
1751 linker_define!(
1752 linker,
1753 FIELD_ENTRY_WRITE_FUNCTION_NAME,
1754 host_field_lock_write
1755 );
1756 linker_define!(
1757 linker,
1758 FIELD_ENTRY_CLOSE_FUNCTION_NAME,
1759 host_field_lock_release
1760 );
1761 linker_define!(
1762 linker,
1763 ACTOR_GET_OBJECT_ID_FUNCTION_NAME,
1764 host_actor_get_node_id
1765 );
1766 linker_define!(
1767 linker,
1768 ACTOR_GET_PACKAGE_ADDRESS_FUNCTION_NAME,
1769 host_get_package_address
1770 );
1771 linker_define!(
1772 linker,
1773 ACTOR_GET_BLUEPRINT_NAME_FUNCTION_NAME,
1774 host_get_blueprint_name
1775 );
1776 linker_define!(
1777 linker,
1778 COSTING_CONSUME_WASM_EXECUTION_UNITS_FUNCTION_NAME,
1779 host_consume_wasm_execution_units
1780 );
1781 linker_define!(linker, ACTOR_EMIT_EVENT_FUNCTION_NAME, host_emit_event);
1782 linker_define!(linker, SYS_LOG_FUNCTION_NAME, host_emit_log);
1783 linker_define!(linker, SYS_PANIC_FUNCTION_NAME, host_panic);
1784 linker_define!(
1785 linker,
1786 SYS_GET_TRANSACTION_HASH_FUNCTION_NAME,
1787 host_get_transaction_hash
1788 );
1789 linker_define!(
1790 linker,
1791 SYS_BECH32_ENCODE_ADDRESS_FUNCTION_NAME,
1792 host_bech32_encode_address
1793 );
1794 linker_define!(linker, SYS_GENERATE_RUID_FUNCTION_NAME, host_generate_ruid);
1795 linker_define!(
1796 linker,
1797 CRYPTO_UTILS_BLS12381_V1_VERIFY_FUNCTION_NAME,
1798 host_bls12381_v1_verify
1799 );
1800 linker_define!(
1801 linker,
1802 CRYPTO_UTILS_BLS12381_V1_AGGREGATE_VERIFY_FUNCTION_NAME,
1803 host_bls12381_v1_aggregate_verify
1804 );
1805 linker_define!(
1806 linker,
1807 CRYPTO_UTILS_BLS12381_V1_FAST_AGGREGATE_VERIFY_FUNCTION_NAME,
1808 host_bls12381_v1_fast_aggregate_verify
1809 );
1810 linker_define!(
1811 linker,
1812 CRYPTO_UTILS_BLS12381_G2_SIGNATURE_AGGREGATE_FUNCTION_NAME,
1813 host_bls12381_g2_signature_aggregate
1814 );
1815 linker_define!(
1816 linker,
1817 CRYPTO_UTILS_KECCAK256_HASH_FUNCTION_NAME,
1818 host_keccak256_hash
1819 );
1820 linker_define!(
1821 linker,
1822 CRYPTO_UTILS_BLAKE2B_256_HASH_FUNCTION_NAME,
1823 host_blake2b_256_hash
1824 );
1825 linker_define!(
1826 linker,
1827 CRYPTO_UTILS_ED25519_VERIFY_FUNCTION_NAME,
1828 host_ed25519_verify
1829 );
1830 linker_define!(
1831 linker,
1832 CRYPTO_UTILS_SECP256K1_ECDSA_VERIFY_FUNCTION_NAME,
1833 host_secp2561k1_ecdsa_verify
1834 );
1835 linker_define!(
1836 linker,
1837 CRYPTO_UTILS_SECP256K1_ECDSA_VERIFY_AND_KEY_RECOVER_FUNCTION_NAME,
1838 host_secp2561k1_ecdsa_verify_and_key_recover
1839 );
1840 linker_define!(
1841 linker,
1842 CRYPTO_UTILS_SECP256K1_ECDSA_VERIFY_AND_KEY_RECOVER_UNCOMPRESSED_FUNCTION_NAME,
1843 host_secp2561k1_ecdsa_verify_and_key_recover_uncompressed
1844 );
1845
1846 #[cfg(feature = "radix_engine_tests")]
1847 {
1848 let host_read_memory = Func::wrap(
1849 store.as_context_mut(),
1850 |caller: Caller<'_, HostState>,
1851 memory_offs: u32,
1852 data_len: u32|
1853 -> Result<(), Error> {
1854 test_host_read_memory(caller, memory_offs, data_len).map_err(|e| Error::host(e))
1855 },
1856 );
1857 let host_write_memory = Func::wrap(
1858 store.as_context_mut(),
1859 |caller: Caller<'_, HostState>,
1860 memory_offs: u32,
1861 data_len: u32|
1862 -> Result<(), Error> {
1863 test_host_write_memory(caller, memory_offs, data_len)
1864 .map_err(|e| Error::host(e))
1865 },
1866 );
1867 let host_check_memory_is_clean = Func::wrap(
1868 store.as_context_mut(),
1869 |caller: Caller<'_, HostState>| -> Result<u64, Error> {
1870 test_host_check_memory_is_clean(caller).map_err(|e| Error::host(e))
1871 },
1872 );
1873 linker_define!(linker, "test_host_read_memory", host_read_memory);
1874 linker_define!(linker, "test_host_write_memory", host_write_memory);
1875 linker_define!(
1876 linker,
1877 "test_host_check_memory_is_clean",
1878 host_check_memory_is_clean
1879 );
1880 }
1881
1882 linker.instantiate(store.as_context_mut(), &module)
1883 }
1884
1885 pub fn instantiate(&self) -> Result<WasmiInstance, WasmiInstantiationError> {
1886 let mut store = Store::new(self.module.engine(), WasmiInstanceEnv::new());
1887
1888 let instance = Self::host_funcs_set(&self.module, &mut store)
1889 .map_err(WasmiInstantiationError::PreInstantiationError)?
1890 .ensure_no_start(store.as_context_mut())
1891 .map_err(WasmiInstantiationError::InstantiationError)?;
1892
1893 let memory = match instance.get_export(store.as_context_mut(), EXPORT_MEMORY) {
1894 Some(Extern::Memory(memory)) => memory,
1895 _ => panic!("Failed to find memory export"),
1896 };
1897
1898 Ok(WasmiInstance {
1899 instance,
1900 store,
1901 memory,
1902 })
1903 }
1904
1905 fn instantiate_unchecked(&self) -> WasmiInstance {
1906 self.instantiate().expect("Failed to instantiate")
1907 }
1908}
1909
1910fn read_memory(
1911 store: impl AsContextMut,
1912 memory: Memory,
1913 ptr: u32,
1914 len: u32,
1915) -> Result<Vec<u8>, InvokeError<WasmRuntimeError>> {
1916 let store_ctx = store.as_context();
1917 let data = memory.data(&store_ctx);
1918 let ptr = ptr as usize;
1919 let len = len as usize;
1920
1921 if ptr > data.len() || ptr + len > data.len() {
1922 return Err(InvokeError::SelfError(WasmRuntimeError::MemoryAccessError));
1923 }
1924 Ok(data[ptr..ptr + len].to_vec())
1925}
1926
1927fn write_memory(
1928 mut store: impl AsContextMut,
1929 memory: Memory,
1930 ptr: u32,
1931 data: &[u8],
1932) -> Result<(), InvokeError<WasmRuntimeError>> {
1933 let mut store_ctx = store.as_context_mut();
1934 let mem_data = memory.data(&mut store_ctx);
1935
1936 if ptr as usize > mem_data.len() || ptr as usize + data.len() > mem_data.len() {
1937 return Err(InvokeError::SelfError(WasmRuntimeError::MemoryAccessError));
1938 }
1939
1940 memory
1941 .write(&mut store.as_context_mut(), ptr as usize, data)
1942 .or_else(|_| Err(InvokeError::SelfError(WasmRuntimeError::MemoryAccessError)))
1943}
1944
1945fn read_slice(
1946 store: impl AsContextMut,
1947 memory: Memory,
1948 v: Slice,
1949) -> Result<Vec<u8>, InvokeError<WasmRuntimeError>> {
1950 let ptr = v.ptr();
1951 let len = v.len();
1952
1953 read_memory(store, memory, ptr, len)
1954}
1955
1956impl WasmiInstance {
1957 fn get_export_func(&mut self, name: &str) -> Result<Func, InvokeError<WasmRuntimeError>> {
1958 self.instance
1959 .get_export(self.store.as_context_mut(), name)
1960 .and_then(Extern::into_func)
1961 .ok_or_else(|| {
1962 InvokeError::SelfError(WasmRuntimeError::UnknownExport(name.to_string()))
1963 })
1964 }
1965}
1966
1967impl HostError for InvokeError<WasmRuntimeError> {}
1968
1969impl From<Error> for InvokeError<WasmRuntimeError> {
1970 fn from(err: Error) -> Self {
1971 let e_str = format!("{:?}", err);
1972 if let Some(invoke_err) = err.downcast::<InvokeError<WasmRuntimeError>>() {
1973 invoke_err.clone()
1974 } else {
1975 InvokeError::SelfError(WasmRuntimeError::ExecutionError(e_str))
1976 }
1977 }
1978}
1979
1980impl WasmInstance for WasmiInstance {
1981 fn invoke_export<'r>(
1982 &mut self,
1983 func_name: &str,
1984 args: Vec<Buffer>,
1985 runtime: &mut Box<dyn WasmRuntime + 'r>,
1986 ) -> Result<Vec<u8>, InvokeError<WasmRuntimeError>> {
1987 {
1988 self.store
1993 .data_mut()
1994 .runtime_ptr
1995 .write(runtime as *mut _ as usize as *mut _);
1996 }
1997
1998 let func = self.get_export_func(func_name).unwrap();
1999 let input: Vec<Val> = args
2000 .into_iter()
2001 .map(|buffer| Val::I64(buffer.as_i64()))
2002 .collect();
2003 let mut ret = [Val::I64(0)];
2004
2005 let call_result = func
2006 .call(self.store.as_context_mut(), &input, &mut ret)
2007 .map_err(|e| {
2008 let err: InvokeError<WasmRuntimeError> = e.into();
2009 err
2010 });
2011
2012 let result = match call_result {
2013 Ok(_) => match ret[0] {
2014 Val::I64(ret) => read_slice(
2015 self.store.as_context_mut(),
2016 self.memory,
2017 Slice::transmute_i64(ret),
2018 ),
2019 _ => Err(InvokeError::SelfError(WasmRuntimeError::InvalidWasmPointer)),
2020 },
2021 Err(err) => Err(err),
2022 };
2023
2024 #[cfg(feature = "coverage")]
2025 if let Ok(dump_coverage) = self.get_export_func("dump_coverage") {
2026 if let Ok(blueprint_buffer) = runtime.actor_get_blueprint_name() {
2027 let blueprint_name =
2028 String::from_utf8(runtime.buffer_consume(blueprint_buffer.id()).unwrap())
2029 .unwrap();
2030
2031 let mut ret = [Val::I64(0)];
2032 dump_coverage
2033 .call(self.store.as_context_mut(), &[], &mut ret)
2034 .unwrap();
2035 let coverage_data = match ret[0] {
2036 Val::I64(ret) => read_slice(
2037 self.store.as_context_mut(),
2038 self.memory,
2039 Slice::transmute_i64(ret),
2040 ),
2041 _ => Err(InvokeError::SelfError(WasmRuntimeError::InvalidWasmPointer)),
2042 }
2043 .unwrap();
2044 save_coverage_data(&blueprint_name, &coverage_data);
2045 }
2046 }
2047
2048 result
2049 }
2050}
2051
2052#[derive(Debug, Clone)]
2053pub struct WasmiEngineOptions {
2054 max_cache_size: usize,
2055}
2056
2057pub struct WasmiEngine {
2058 #[cfg(all(not(feature = "fuzzing"), not(feature = "moka")))]
2060 modules_cache: RefCell<lru::LruCache<CodeHash, Arc<WasmiModule>>>,
2061 #[cfg(all(not(feature = "fuzzing"), feature = "moka"))]
2062 modules_cache: moka::sync::Cache<CodeHash, Arc<WasmiModule>>,
2063 #[cfg(feature = "fuzzing")]
2064 #[allow(dead_code)]
2065 modules_cache: usize,
2066}
2067
2068impl Default for WasmiEngine {
2069 fn default() -> Self {
2070 Self::new(WasmiEngineOptions {
2071 max_cache_size: WASM_ENGINE_CACHE_SIZE,
2072 })
2073 }
2074}
2075
2076impl WasmiEngine {
2077 pub fn new(options: WasmiEngineOptions) -> Self {
2078 #[cfg(all(not(feature = "fuzzing"), not(feature = "moka")))]
2079 let modules_cache = RefCell::new(lru::LruCache::new(
2080 sbor::rust::num::NonZeroUsize::new(options.max_cache_size).unwrap(),
2081 ));
2082 #[cfg(all(not(feature = "fuzzing"), feature = "moka"))]
2083 let modules_cache = moka::sync::Cache::builder()
2084 .weigher(|_key: &CodeHash, _value: &Arc<WasmiModule>| -> u32 {
2085 1u32
2087 })
2088 .max_capacity(options.max_cache_size as u64)
2089 .build();
2090 #[cfg(feature = "fuzzing")]
2091 let modules_cache = options.max_cache_size;
2092
2093 Self { modules_cache }
2094 }
2095}
2096
2097impl WasmEngine for WasmiEngine {
2098 type WasmInstance = WasmiInstance;
2099
2100 #[allow(unused_variables)]
2101 fn instantiate(&self, code_hash: CodeHash, instrumented_code: &[u8]) -> WasmiInstance {
2102 #[cfg(not(feature = "fuzzing"))]
2103 {
2104 #[cfg(not(feature = "moka"))]
2105 {
2106 if let Some(cached_module) = self.modules_cache.borrow_mut().get(&code_hash) {
2107 return cached_module.instantiate_unchecked();
2108 }
2109 }
2110 #[cfg(feature = "moka")]
2111 if let Some(cached_module) = self.modules_cache.get(&code_hash) {
2112 return cached_module.as_ref().instantiate_unchecked();
2113 }
2114 }
2115
2116 let module = WasmiModule::new(instrumented_code).expect("Failed to compile module");
2117 let instance = module.instantiate_unchecked();
2118
2119 #[cfg(not(feature = "fuzzing"))]
2120 {
2121 #[cfg(not(feature = "moka"))]
2122 self.modules_cache
2123 .borrow_mut()
2124 .put(code_hash, Arc::new(module));
2125 #[cfg(feature = "moka")]
2126 self.modules_cache.insert(code_hash, Arc::new(module));
2127 }
2128
2129 instance
2130 }
2131}
2132
2133#[cfg(test)]
2144mod tests {
2145 use super::*;
2146 use wabt::{wat2wasm, wat2wasm_with_features, ErrorKind, Features};
2147 use wasmi::Global;
2148
2149 static MODULE_MUTABLE_GLOBALS: &str = r#"
2150 (module
2151 ;; below line is invalid if feature 'Import/Export mutable globals' is disabled
2152 ;; see: https://github.com/WebAssembly/mutable-global/blob/master/proposals/mutable-global/Overview.md
2153 (global $g (import "env" "global_mutable_value") (mut i32))
2154
2155 ;; Simple function that always returns `0`
2156 (func $increase_global_value (param $step i32) (result i32)
2157
2158 (global.set $g
2159 (i32.add
2160 (global.get $g)
2161 (local.get $step)))
2162
2163 (i32.const 0)
2164 )
2165 (memory $0 1)
2166 (export "memory" (memory $0))
2167 (export "increase_global_value" (func $increase_global_value))
2168 )
2169 "#;
2170
2171 #[test]
2173 fn test_wasm_non_mvp_mutable_globals_build_with_feature_disabled() {
2174 let mut features = Features::new();
2175 features.disable_mutable_globals();
2176
2177 assert!(
2178 match wat2wasm_with_features(MODULE_MUTABLE_GLOBALS, features) {
2179 Err(err) => {
2180 match err.kind() {
2181 ErrorKind::Validate(msg) => {
2182 msg.contains("mutable globals cannot be imported")
2183 }
2184 _ => false,
2185 }
2186 }
2187 Ok(_) => false,
2188 }
2189 )
2190 }
2191 pub fn run_module_with_mutable_global(
2192 module: &Module,
2193 mut store: StoreContextMut<WasmiInstanceEnv>,
2194 func_name: &str,
2195 global_name: &str,
2196 global_value: &Global,
2197 step: i32,
2198 ) {
2199 let mut linker = <Linker<HostState>>::new(module.engine());
2200 linker_define!(linker, global_name, *global_value);
2201
2202 let instance = linker
2203 .instantiate(store.as_context_mut(), &module)
2204 .unwrap()
2205 .ensure_no_start(store.as_context_mut())
2206 .unwrap();
2207
2208 let func = instance
2209 .get_export(store.as_context_mut(), func_name)
2210 .and_then(Extern::into_func)
2211 .unwrap();
2212
2213 let input = [Val::I32(step)];
2214 let mut ret = [Val::I32(0)];
2215
2216 let _ = func.call(store.as_context_mut(), &input, &mut ret);
2217 }
2218
2219 #[test]
2220 fn test_wasm_non_mvp_mutable_globals_execute_code() {
2221 let code = wat2wasm(MODULE_MUTABLE_GLOBALS).unwrap();
2223
2224 let wasmi_module = WasmiModule::new(&code).unwrap();
2225 let module = wasmi_module.module;
2226
2227 let mut store = Store::new(&module.engine(), WasmiInstanceEnv::new());
2228
2229 let global_value = Global::new(store.as_context_mut(), Val::I32(100), Mutability::Var);
2231
2232 run_module_with_mutable_global(
2233 &module,
2234 store.as_context_mut(),
2235 "increase_global_value",
2236 "global_mutable_value",
2237 &global_value,
2238 1000,
2239 );
2240 let updated_value = global_value.get(store.as_context());
2241 let val = match updated_value {
2242 Val::I32(val) => val,
2243 _ => panic!("Unexpected return value type"),
2244 };
2245 assert_eq!(val, 1100);
2246
2247 run_module_with_mutable_global(
2248 &module,
2249 store.as_context_mut(),
2250 "increase_global_value",
2251 "global_mutable_value",
2252 &global_value,
2253 10000,
2254 );
2255 let updated_value = global_value.get(store.as_context());
2256 let val = match updated_value {
2257 Val::I32(val) => val,
2258 _ => panic!("Unexpected return value type"),
2259 };
2260 assert_eq!(val, 11100);
2261 }
2262}