use alloc::{collections::btree_map::Entry, vec::Vec};
use miden_core::{
AdviceMap, Felt, Word,
crypto::merkle::{InnerNodeInfo, MerkleError, MerklePath, MerkleStore, NodeIndex},
precompile::PrecompileRequest,
};
mod inputs;
pub use inputs::AdviceInputs;
mod errors;
pub use errors::AdviceError;
use crate::{host::AdviceMutation, processor::AdviceProviderInterface};
#[derive(Debug, Clone, Default)]
pub struct AdviceProvider {
stack: Vec<Felt>,
map: AdviceMap,
store: MerkleStore,
pc_requests: Vec<PrecompileRequest>,
}
impl AdviceProvider {
pub fn apply_mutations(
&mut self,
mutations: impl IntoIterator<Item = AdviceMutation>,
) -> Result<(), AdviceError> {
mutations.into_iter().try_for_each(|mutation| self.apply_mutation(mutation))
}
fn apply_mutation(&mut self, mutation: AdviceMutation) -> Result<(), AdviceError> {
match mutation {
AdviceMutation::ExtendStack { values } => {
self.extend_stack(values);
},
AdviceMutation::ExtendMap { other } => {
self.extend_map(&other)?;
},
AdviceMutation::ExtendMerkleStore { infos } => {
self.extend_merkle_store(infos);
},
AdviceMutation::ExtendPrecompileRequests { data } => {
self.extend_precompile_requests(data);
},
}
Ok(())
}
pub fn pop_stack(&mut self) -> Result<Felt, AdviceError> {
self.stack.pop().ok_or(AdviceError::StackReadFailed)
}
pub fn pop_stack_word(&mut self) -> Result<Word, AdviceError> {
if self.stack.len() < 4 {
return Err(AdviceError::StackReadFailed);
}
let idx = self.stack.len() - 4;
let result =
[self.stack[idx + 3], self.stack[idx + 2], self.stack[idx + 1], self.stack[idx]];
self.stack.truncate(idx);
Ok(result.into())
}
pub fn pop_stack_dword(&mut self) -> Result<[Word; 2], AdviceError> {
let word0 = self.pop_stack_word()?;
let word1 = self.pop_stack_word()?;
Ok([word0, word1])
}
pub fn push_stack(&mut self, value: Felt) {
self.stack.push(value)
}
pub fn push_stack_word(&mut self, word: &Word) {
self.stack.extend(word.iter().rev())
}
pub fn push_from_map(&mut self, key: Word, include_len: bool) -> Result<(), AdviceError> {
let values = self.map.get(&key).ok_or(AdviceError::MapKeyNotFound { key })?;
self.stack.extend(values.iter().rev());
if include_len {
self.stack
.push(Felt::try_from(values.len() as u64).expect("value length too big"));
}
Ok(())
}
pub fn stack(&self) -> &[Felt] {
&self.stack
}
pub fn extend_stack<I>(&mut self, iter: I)
where
I: IntoIterator<Item = Felt>,
{
self.stack.extend(iter);
}
pub fn contains_map_key(&self, key: &Word) -> bool {
self.map.contains_key(key)
}
pub fn get_mapped_values(&self, key: &Word) -> Option<&[Felt]> {
self.map.get(key).map(|value| value.as_ref())
}
pub fn insert_into_map(&mut self, key: Word, values: Vec<Felt>) -> Result<(), AdviceError> {
match self.map.entry(key) {
Entry::Vacant(entry) => {
entry.insert(values.into());
},
Entry::Occupied(entry) => {
let existing_values = entry.get().as_ref();
if existing_values != values {
return Err(AdviceError::MapKeyAlreadyPresent {
key,
prev_values: existing_values.to_vec(),
new_values: values,
});
}
},
}
Ok(())
}
pub fn extend_map(&mut self, other: &AdviceMap) -> Result<(), AdviceError> {
self.map.merge(other).map_err(|((key, prev_values), new_values)| {
AdviceError::MapKeyAlreadyPresent {
key,
prev_values: prev_values.to_vec(),
new_values: new_values.to_vec(),
}
})
}
pub fn get_tree_node(&self, root: Word, depth: Felt, index: Felt) -> Result<Word, AdviceError> {
let index = NodeIndex::from_elements(&depth, &index)
.map_err(|_| AdviceError::InvalidMerkleTreeNodeIndex { depth, index })?;
self.store.get_node(root, index).map_err(AdviceError::MerkleStoreLookupFailed)
}
pub fn has_merkle_path(
&self,
root: Word,
depth: Felt,
index: Felt,
) -> Result<bool, AdviceError> {
let index = NodeIndex::from_elements(&depth, &index)
.map_err(|_| AdviceError::InvalidMerkleTreeNodeIndex { depth, index })?;
match self.store.get_path(root, index) {
Ok(_) => Ok(true),
Err(MerkleError::RootNotInStore(..)) => Ok(false),
Err(MerkleError::NodeIndexNotFoundInStore(..)) => Ok(false),
Err(err) => Err(AdviceError::MerkleStoreLookupFailed(err)),
}
}
pub fn get_merkle_path(
&self,
root: Word,
depth: Felt,
index: Felt,
) -> Result<MerklePath, AdviceError> {
let index = NodeIndex::from_elements(&depth, &index)
.map_err(|_| AdviceError::InvalidMerkleTreeNodeIndex { depth, index })?;
self.store
.get_path(root, index)
.map(|value| value.path)
.map_err(AdviceError::MerkleStoreLookupFailed)
}
pub fn update_merkle_node(
&mut self,
root: Word,
depth: Felt,
index: Felt,
value: Word,
) -> Result<(MerklePath, Word), AdviceError> {
let node_index = NodeIndex::from_elements(&depth, &index)
.map_err(|_| AdviceError::InvalidMerkleTreeNodeIndex { depth, index })?;
self.store
.set_node(root, node_index, value)
.map(|root| (root.path, root.root))
.map_err(AdviceError::MerkleStoreUpdateFailed)
}
pub fn merge_roots(&mut self, lhs: Word, rhs: Word) -> Result<Word, AdviceError> {
self.store.merge_roots(lhs, rhs).map_err(AdviceError::MerkleStoreMergeFailed)
}
pub fn has_merkle_root(&self, root: Word) -> bool {
self.store.get_node(root, NodeIndex::root()).is_ok()
}
pub fn extend_merkle_store<I>(&mut self, iter: I)
where
I: IntoIterator<Item = InnerNodeInfo>,
{
self.store.extend(iter);
}
pub fn precompile_requests(&self) -> &[PrecompileRequest] {
&self.pc_requests
}
pub fn extend_precompile_requests<I>(&mut self, iter: I)
where
I: IntoIterator<Item = PrecompileRequest>,
{
self.pc_requests.extend(iter);
}
pub fn take_precompile_requests(&mut self) -> Vec<PrecompileRequest> {
core::mem::take(&mut self.pc_requests)
}
pub fn extend_from_inputs(&mut self, inputs: &AdviceInputs) -> Result<(), AdviceError> {
self.extend_stack(inputs.stack.iter().cloned().rev());
self.extend_merkle_store(inputs.store.inner_nodes());
self.extend_map(&inputs.map)
}
pub fn into_parts(self) -> (Vec<Felt>, AdviceMap, MerkleStore, Vec<PrecompileRequest>) {
(self.stack, self.map, self.store, self.pc_requests)
}
}
impl From<AdviceInputs> for AdviceProvider {
fn from(inputs: AdviceInputs) -> Self {
let AdviceInputs { mut stack, map, store } = inputs;
stack.reverse();
Self {
stack,
map,
store,
pc_requests: Vec::new(),
}
}
}
impl AdviceProviderInterface for AdviceProvider {
#[inline(always)]
fn pop_stack(&mut self) -> Result<Felt, AdviceError> {
self.pop_stack()
}
#[inline(always)]
fn pop_stack_word(&mut self) -> Result<Word, AdviceError> {
self.pop_stack_word()
}
#[inline(always)]
fn pop_stack_dword(&mut self) -> Result<[Word; 2], AdviceError> {
self.pop_stack_dword()
}
#[inline(always)]
fn get_merkle_path(
&self,
root: Word,
depth: Felt,
index: Felt,
) -> Result<Option<MerklePath>, AdviceError> {
self.get_merkle_path(root, depth, index).map(Some)
}
#[inline(always)]
fn update_merkle_node(
&mut self,
root: Word,
depth: Felt,
index: Felt,
value: Word,
) -> Result<Option<MerklePath>, AdviceError> {
self.update_merkle_node(root, depth, index, value).map(|(path, _)| Some(path))
}
}