use alloc::string::ToString;
use miden_protocol::Word;
use miden_protocol::crypto::merkle::smt::{LeafIndex, SMT_DEPTH, SmtLeaf, SmtProof};
use crate::rpc::domain::MissingFieldHelper;
use crate::rpc::errors::RpcConversionError;
use crate::rpc::generated as proto;
impl From<&(Word, Word)> for proto::primitives::SmtLeafEntry {
fn from(value: &(Word, Word)) -> Self {
proto::primitives::SmtLeafEntry {
key: Some(value.0.into()),
value: Some(value.1.into()),
}
}
}
impl TryFrom<&proto::primitives::SmtLeafEntry> for (Word, Word) {
type Error = RpcConversionError;
fn try_from(value: &proto::primitives::SmtLeafEntry) -> Result<Self, Self::Error> {
let key = match value.key {
Some(key) => key.try_into()?,
None => return Err(proto::primitives::SmtLeafEntry::missing_field(stringify!(key))),
};
let value: Word = match value.value {
Some(value) => value.try_into()?,
None => return Err(proto::primitives::SmtLeafEntry::missing_field(stringify!(value))),
};
Ok((key, value))
}
}
impl From<SmtLeaf> for proto::primitives::SmtLeaf {
fn from(value: SmtLeaf) -> Self {
(&value).into()
}
}
impl From<&SmtLeaf> for proto::primitives::SmtLeaf {
fn from(value: &SmtLeaf) -> Self {
match value {
SmtLeaf::Empty(index) => proto::primitives::SmtLeaf {
leaf: Some(proto::primitives::smt_leaf::Leaf::EmptyLeafIndex(index.position())),
},
SmtLeaf::Single(entry) => proto::primitives::SmtLeaf {
leaf: Some(proto::primitives::smt_leaf::Leaf::Single(entry.into())),
},
SmtLeaf::Multiple(entries) => proto::primitives::SmtLeaf {
leaf: Some(proto::primitives::smt_leaf::Leaf::Multiple(
proto::primitives::SmtLeafEntryList {
entries: entries.iter().map(Into::into).collect(),
},
)),
},
}
}
}
impl TryFrom<&proto::primitives::SmtLeaf> for SmtLeaf {
type Error = RpcConversionError;
fn try_from(value: &proto::primitives::SmtLeaf) -> Result<Self, Self::Error> {
match &value.leaf {
Some(proto::primitives::smt_leaf::Leaf::EmptyLeafIndex(index)) => Ok(SmtLeaf::Empty(
LeafIndex::<SMT_DEPTH>::new(*index)
.map_err(|err| RpcConversionError::InvalidField(err.to_string()))?,
)),
Some(proto::primitives::smt_leaf::Leaf::Single(entry)) => {
Ok(SmtLeaf::Single(entry.try_into()?))
},
Some(proto::primitives::smt_leaf::Leaf::Multiple(entries)) => {
let entries =
entries.entries.iter().map(TryInto::try_into).collect::<Result<_, _>>()?;
Ok(SmtLeaf::Multiple(entries))
},
None => Err(proto::primitives::SmtLeaf::missing_field(stringify!(leaf))),
}
}
}
impl From<SmtProof> for proto::primitives::SmtOpening {
fn from(value: SmtProof) -> Self {
let (path, leaf) = value.into_parts();
proto::primitives::SmtOpening {
leaf: Some(leaf.into()),
path: Some(path.into()),
}
}
}
impl TryFrom<proto::primitives::SmtOpening> for SmtProof {
type Error = RpcConversionError;
fn try_from(value: proto::primitives::SmtOpening) -> Result<Self, Self::Error> {
let leaf = match &value.leaf {
Some(leaf) => leaf.try_into()?,
None => return Err(proto::primitives::SmtOpening::missing_field(stringify!(leaf))),
};
let path = match value.path {
Some(path) => path.try_into()?,
None => return Err(proto::primitives::SmtOpening::missing_field(stringify!(path))),
};
SmtProof::new(path, leaf).map_err(|err| RpcConversionError::InvalidField(err.to_string()))
}
}