corevm_engine/
host_calls.rs1use alloc::vec::Vec;
2use bytes::Bytes;
3use core::ops::Range;
4use corevm_host::{
5 fs::{self, ReadBlock},
6 PageNum, PAGE_SIZE,
7};
8use jam_pvm_common::{ApiError, InvokeOutcome};
9use jam_types::{SignedGas, SEGMENT_LEN};
10
11pub trait InnerVm {
13 fn void(&mut self, page: PageNum, num_pages: u32) -> Result<(), ApiError>;
14 fn zero(&mut self, page: PageNum, num_pages: u32) -> Result<(), ApiError>;
15 fn poke(&mut self, outer_src: &[u8], inner_dst: u32) -> Result<(), ApiError>;
16 fn peek_into(&mut self, outer_dst: &mut [u8], inner_src: u32) -> Result<(), ApiError>;
17 fn invoke(
18 &mut self,
19 gas: SignedGas,
20 regs: [u64; 13],
21 ) -> Result<(InvokeOutcome, SignedGas, [u64; 13]), ApiError>;
22 fn expunge(self) -> Result<u64, ApiError>;
23
24 fn zero_poke(&mut self, outer_src: &[u8], inner_dst: u32) -> Result<(), ApiError> {
25 let page = PageNum::from_address(inner_dst);
27 let num_pages = (outer_src.len() as u32).div_ceil(PAGE_SIZE);
28 self.zero(page, num_pages)?;
29 self.poke(outer_src, inner_dst)?;
31 Ok(())
32 }
33
34 fn poke_ro_rw_data_page(
35 &mut self,
36 data: &[u8],
37 address_range: &Range<u32>,
38 address: u32,
39 ) -> Result<(), ApiError> {
40 debug_assert_eq!(0, address % PAGE_SIZE);
41 debug_assert!(address_range.contains(&address));
42 let data_start = address - address_range.start;
43 if data_start < data.len() as u32 {
44 let data_start = data_start as usize;
46 let data_end = (data_start + PAGE_SIZE as usize).min(data.len());
47 let data_range = data_start..data_end;
48 self.zero_poke(&data[data_range], address)?;
49 } else {
50 let page = PageNum::from_address(address);
52 self.zero(page, 1)?;
53 }
54 Ok(())
55 }
56}
57
58pub trait OuterVm {
61 type InnerVm: crate::InnerVm;
63
64 fn export(&mut self, segment: &[u8; SEGMENT_LEN]) -> Result<(), ApiError>;
69
70 fn read_file_block(&mut self, block_ref: &fs::BlockRef) -> Option<Bytes>;
72
73 fn machine(&mut self, code: &[u8], program_counter: u64) -> Result<Self::InnerVm, ApiError>;
75
76 fn read_file(&mut self, block_ref: &fs::BlockRef) -> Result<Vec<u8>, fs::Error> {
80 let mut block_reader = self.block_reader();
81 let buf = fs::read(block_ref, &mut block_reader)?;
82 Ok(buf)
83 }
84
85 fn block_reader(&mut self) -> Lookup<'_, Self> {
88 Lookup { outer_vm: self }
89 }
90}
91
92pub struct Lookup<'a, O: OuterVm + ?Sized> {
94 pub outer_vm: &'a mut O,
95}
96
97impl<O: OuterVm + ?Sized> ReadBlock for Lookup<'_, O> {
98 fn read_block(&mut self, block_ref: &fs::BlockRef) -> Result<Bytes, fs::IoError> {
99 self.outer_vm.read_file_block(block_ref).ok_or(fs::IoError)
100 }
101}