Skip to main content

miden_node_persistence/
protocol.rs

1use std::sync::Arc;
2
3use miden_objects::proto;
4use miden_protobuf::{DecodeMessage, DecodeMessageExt};
5use miden_protocol::MastForest;
6use miden_protocol::account::{AccountCode, AccountProcedureRoot};
7use miden_protocol::utils::serde::{Deserializable, Serializable};
8
9use crate::{PersistenceError, ProtobufValue, generated};
10
11macro_rules! codec {
12    ($domain:ty, $message:ty, $build:ident, $encode:expr) => {
13        impl ProtobufValue for $domain {
14            type Message = $message;
15            fn to_proto(&self) -> Self::Message {
16                ($encode)(self)
17            }
18            fn from_proto(message: Self::Message) -> Result<Self, PersistenceError> {
19                Ok(message.$build()?)
20            }
21        }
22    };
23}
24
25codec!(
26    miden_protocol::account::Account,
27    proto::account::Account,
28    decode_and_verify,
29    |value: &miden_protocol::account::Account| value.into()
30);
31codec!(
32    miden_protocol::account::AccountStorageHeader,
33    proto::account::AccountStorageHeader,
34    decode_and_verify,
35    |value: &miden_protocol::account::AccountStorageHeader| value.into()
36);
37codec!(
38    miden_protocol::asset::Asset,
39    proto::asset::Asset,
40    decode_and_verify,
41    |value: &miden_protocol::asset::Asset| value.into()
42);
43codec!(
44    miden_protocol::note::Note,
45    proto::note::Note,
46    decode_and_verify,
47    |value: &miden_protocol::note::Note| value.into()
48);
49codec!(
50    miden_protocol::note::NoteHeader,
51    proto::note::NoteHeader,
52    decode_and_verify,
53    |value: &miden_protocol::note::NoteHeader| (*value).into()
54);
55codec!(
56    miden_protocol::note::NoteDetails,
57    proto::note::NoteDetails,
58    decode_and_verify,
59    |value: &miden_protocol::note::NoteDetails| value.into()
60);
61codec!(
62    miden_protocol::note::NoteScript,
63    proto::note::NoteScript,
64    decode_and_verify,
65    |value: &miden_protocol::note::NoteScript| value.into()
66);
67codec!(
68    miden_protocol::note::NoteStorage,
69    proto::note::NoteStorage,
70    decode_and_verify,
71    |value: &miden_protocol::note::NoteStorage| value.into()
72);
73codec!(
74    miden_protocol::note::NoteAttachments,
75    proto::note::NoteAttachments,
76    decode_and_verify,
77    |value: &miden_protocol::note::NoteAttachments| value.into()
78);
79codec!(
80    miden_protocol::protocol_config::ProtocolConfig,
81    proto::protocol_config::ProtocolConfig,
82    decode_and_verify,
83    |value: &miden_protocol::protocol_config::ProtocolConfig| value.into()
84);
85codec!(
86    miden_protocol::crypto::merkle::SparseMerklePath,
87    proto::primitives::SparseMerklePath,
88    decode_and_verify,
89    |value: &miden_protocol::crypto::merkle::SparseMerklePath| value.clone().into()
90);
91codec!(
92    miden_protocol::crypto::merkle::mmr::PartialMmr,
93    proto::primitives::PartialMmr,
94    decode_and_verify,
95    |value: &miden_protocol::crypto::merkle::mmr::PartialMmr| value.into()
96);
97codec!(
98    miden_protocol::block::BlockHeader,
99    proto::blockchain::BlockHeader,
100    decode_and_build_unchecked,
101    |value: &miden_protocol::block::BlockHeader| value.into()
102);
103codec!(
104    miden_protocol::block::SignedBlock,
105    proto::blockchain::SignedBlock,
106    decode_and_build_unchecked,
107    |value: &miden_protocol::block::SignedBlock| value.into()
108);
109codec!(
110    miden_protocol::transaction::TransactionInputs,
111    proto::transaction::TransactionInputs,
112    decode_and_build_unchecked,
113    |value: &miden_protocol::transaction::TransactionInputs| value.into()
114);
115codec!(
116    miden_protocol::transaction::ProvenTransaction,
117    proto::transaction::ProvenTransaction,
118    decode_and_build_unchecked,
119    |value: &miden_protocol::transaction::ProvenTransaction| value.into()
120);
121
122// The miden-objects protobuf conversion can omit MAST node hashes for untrusted validation. Stored
123// code keeps these hashes so MastForest::read_from_bytes can restore it as trusted data.
124impl ProtobufValue for AccountCode {
125    type Message = generated::AccountCode;
126
127    fn to_proto(&self) -> Self::Message {
128        generated::AccountCode {
129            mast: Some(generated::MastForest { encoded: self.mast().to_bytes() }),
130            procedure_roots: self.procedure_roots().map(Into::into).collect(),
131        }
132    }
133
134    fn from_proto(message: Self::Message) -> Result<Self, PersistenceError> {
135        let mast = message.mast.ok_or_else(|| {
136            miden_protobuf::ConversionError::missing_field::<generated::AccountCode>("mast")
137        })?;
138        let mast = Arc::new(MastForest::read_from_bytes(&mast.encoded)?);
139        let roots = message
140            .procedure_roots
141            .into_iter()
142            .map(|root| root.decode_fields().map(AccountProcedureRoot::from_raw))
143            .collect::<Result<Vec<_>, _>>()?;
144        Ok(AccountCode::from_parts(mast, roots)?)
145    }
146}