sp_virtualization/
manager.rs1use crate::{DestroyError, ExecError, Memory, MemoryError, MemoryT, Virt, VirtT};
21use sp_wasm_interface::{ExecAction, ExecOutcome, InstanceId, Virtualization};
22use std::collections::HashMap;
23
24struct VirtInstance {
26 virt: Virt,
27 memory: Memory,
28}
29
30pub struct VirtManager {
35 instances: HashMap<InstanceId, VirtInstance>,
36 counter: u32,
37}
38
39impl Default for VirtManager {
40 fn default() -> Self {
41 Self { instances: HashMap::new(), counter: 0 }
42 }
43}
44
45impl Virtualization for VirtManager {
46 fn instantiate(&mut self, program: &[u8]) -> sp_wasm_interface::Result<Result<InstanceId, u8>> {
47 let virt = match Virt::instantiate(program) {
48 Ok(virt) => virt,
49 Err(err) => return Ok(Err(err.into())),
50 };
51
52 let instance_id = InstanceId({
53 let old = self.counter;
54 self.counter = old + 1;
55 old
56 });
57
58 self.instances.insert(instance_id, VirtInstance { memory: virt.memory(), virt });
59
60 Ok(Ok(instance_id))
61 }
62
63 fn run(
64 &mut self,
65 instance_id: InstanceId,
66 gas_left: i64,
67 action: ExecAction<'_>,
68 ) -> sp_wasm_interface::Result<Result<ExecOutcome, u8>> {
69 let instance = match self.instances.get_mut(&instance_id) {
70 Some(instance) => instance,
71 None => return Ok(Err(ExecError::InvalidInstance.into())),
72 };
73
74 let result = instance.virt.run(gas_left, action);
75 Ok(result.map_err(|err| err.into()))
76 }
77
78 fn destroy(&mut self, instance_id: InstanceId) -> sp_wasm_interface::Result<Result<(), u8>> {
79 if self.instances.remove(&instance_id).is_some() {
80 Ok(Ok(()))
81 } else {
82 Ok(Err(DestroyError::InvalidInstance.into()))
83 }
84 }
85
86 fn read_memory(
87 &mut self,
88 instance_id: InstanceId,
89 offset: u32,
90 dest: &mut [u8],
91 ) -> sp_wasm_interface::Result<Result<(), u8>> {
92 let Some(instance) = self.instances.get_mut(&instance_id) else {
93 return Ok(Err(MemoryError::InvalidInstance.into()));
94 };
95 if let Err(err) = instance.memory.read(offset, dest) {
96 return Ok(Err(err.into()));
97 }
98 Ok(Ok(()))
99 }
100
101 fn write_memory(
102 &mut self,
103 instance_id: InstanceId,
104 offset: u32,
105 src: &[u8],
106 ) -> sp_wasm_interface::Result<Result<(), u8>> {
107 let Some(instance) = self.instances.get_mut(&instance_id) else {
108 return Ok(Err(MemoryError::InvalidInstance.into()));
109 };
110 if let Err(err) = instance.memory.write(offset, src) {
111 return Ok(Err(err.into()));
112 }
113 Ok(Ok(()))
114 }
115}