essential_vm/
state_read.rs1use crate::{
4    error::{MemoryError, OpAsyncError, OpAsyncResult, StackError},
5    Vm,
6};
7use core::{
8    future::Future,
9    pin::Pin,
10    task::{Context, Poll},
11};
12use essential_types::{convert::u8_32_from_word_4, ContentAddress, Key, Word};
13
14pub trait StateRead {
16    type Error: core::fmt::Debug + core::fmt::Display;
18    type Future: Future<Output = Result<Vec<Vec<Word>>, Self::Error>> + Unpin;
32
33    fn key_range(&self, contract_addr: ContentAddress, key: Key, num_values: usize)
36        -> Self::Future;
37}
38
39pub(crate) struct StateReadFuture<'vm, S>
43where
44    S: StateRead,
45{
46    future: S::Future,
48    mem_addr: usize,
50    pub(crate) vm: &'vm mut Vm,
52}
53
54impl<S> Future for StateReadFuture<'_, S>
55where
56    S: StateRead,
57{
58    type Output = OpAsyncResult<(), S::Error>;
61    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
62        match Pin::new(&mut self.future).poll(cx) {
63            Poll::Pending => Poll::Pending,
64            Poll::Ready(res) => {
65                let mem_addr = self.mem_addr;
66                let res = res
67                    .map_err(OpAsyncError::StateRead)
68                    .and_then(|words| write_values_to_memory(mem_addr, words, self.vm));
69                Poll::Ready(res)
70            }
71        }
72    }
73}
74
75pub fn key_range<'vm, S>(
77    state_read: &S,
78    contract_addr: &ContentAddress,
79    vm: &'vm mut Vm,
80) -> OpAsyncResult<StateReadFuture<'vm, S>, S::Error>
81where
82    S: StateRead,
83{
84    let mem_addr = vm.stack.pop()?;
85    let mem_addr = usize::try_from(mem_addr).map_err(|_| MemoryError::IndexOutOfBounds)?;
86    let future = read_key_range(state_read, contract_addr, vm)?;
87    Ok(StateReadFuture {
88        future,
89        mem_addr,
90        vm,
91    })
92}
93
94pub fn key_range_ext<'vm, S>(
96    state_read: &S,
97    vm: &'vm mut Vm,
98) -> OpAsyncResult<StateReadFuture<'vm, S>, S::Error>
99where
100    S: StateRead,
101{
102    let mem_addr = vm.stack.pop()?;
103    let mem_addr = usize::try_from(mem_addr).map_err(|_| MemoryError::IndexOutOfBounds)?;
104    let future = read_key_range_ext(state_read, vm)?;
105    Ok(StateReadFuture {
106        future,
107        mem_addr,
108        vm,
109    })
110}
111
112fn read_key_range<S>(
114    state_read: &S,
115    contract_addr: &ContentAddress,
116    vm: &mut Vm,
117) -> OpAsyncResult<S::Future, S::Error>
118where
119    S: StateRead,
120{
121    let num_keys = vm.stack.pop()?;
122    let num_keys = usize::try_from(num_keys).map_err(|_| StackError::IndexOutOfBounds)?;
123    let key = vm
124        .stack
125        .pop_len_words::<_, _, StackError>(|words| Ok(words.to_vec()))?;
126    Ok(state_read.key_range(contract_addr.clone(), key, num_keys))
127}
128
129fn read_key_range_ext<S>(state_read: &S, vm: &mut Vm) -> OpAsyncResult<S::Future, S::Error>
132where
133    S: StateRead,
134{
135    let num_keys = vm.stack.pop()?;
136    let num_keys = usize::try_from(num_keys).map_err(|_| StackError::IndexOutOfBounds)?;
137    let key = vm
138        .stack
139        .pop_len_words::<_, _, StackError>(|words| Ok(words.to_vec()))?;
140    let contract_addr = ContentAddress(u8_32_from_word_4(vm.stack.pop4()?));
141    Ok(state_read.key_range(contract_addr, key, num_keys))
142}
143
144fn write_values_to_memory<E>(
146    mem_addr: usize,
147    values: Vec<Vec<Word>>,
148    vm: &mut Vm,
149) -> OpAsyncResult<(), E> {
150    let values_len = Word::try_from(values.len()).map_err(|_| MemoryError::Overflow)?;
151    let index_len_pairs_len = values_len.checked_mul(2).ok_or(MemoryError::Overflow)?;
152    let mut mem_addr = Word::try_from(mem_addr).map_err(|_| MemoryError::IndexOutOfBounds)?;
153    let mut value_addr = mem_addr
154        .checked_add(index_len_pairs_len)
155        .ok_or(MemoryError::Overflow)?;
156    for value in values {
157        let value_len = Word::try_from(value.len()).map_err(|_| MemoryError::Overflow)?;
158        vm.memory.store_range(mem_addr, &[value_addr, value_len])?;
160        vm.memory.store_range(value_addr, &value)?;
162        value_addr += value_len;
164        mem_addr += 2;
165    }
166    Ok(())
167}