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