1use std::fmt::{Debug, Display, Formatter};
2
3use miden_node_utils::limiter::{QueryParamLimiter, QueryParamStorageMapKeyTotalLimit};
4use miden_protocol::Word;
5use miden_protocol::account::{
6 Account,
7 AccountHeader,
8 AccountId,
9 AccountStorageHeader,
10 StorageMap,
11 StorageMapKey,
12 StorageSlotHeader,
13 StorageSlotName,
14 StorageSlotType,
15};
16use miden_protocol::asset::Asset;
17use miden_protocol::block::BlockNumber;
18use miden_protocol::block::account_tree::AccountWitness;
19use miden_protocol::crypto::merkle::SparseMerklePath;
20use miden_protocol::crypto::merkle::smt::SmtProof;
21use miden_protocol::utils::serde::{Deserializable, DeserializationError, Serializable};
22
23use super::try_convert;
24use crate::decode;
25use crate::decode::{ConversionResultExt, GrpcDecodeExt};
26use crate::errors::ConversionError;
27use crate::generated::{self as proto};
28
29#[cfg(test)]
30mod tests;
31
32impl Display for proto::account::AccountId {
36 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
37 write!(f, "0x")?;
38 for byte in &self.id {
39 write!(f, "{byte:02x}")?;
40 }
41 Ok(())
42 }
43}
44
45impl Debug for proto::account::AccountId {
46 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
47 Display::fmt(self, f)
48 }
49}
50
51impl TryFrom<proto::account::AccountId> for AccountId {
55 type Error = ConversionError;
56
57 fn try_from(account_id: proto::account::AccountId) -> Result<Self, Self::Error> {
58 AccountId::read_from_bytes(&account_id.id)
59 .map_err(|_| ConversionError::message("value is not in the range 0..MODULUS"))
60 }
61}
62
63impl From<&AccountId> for proto::account::AccountId {
67 fn from(account_id: &AccountId) -> Self {
68 (*account_id).into()
69 }
70}
71
72impl From<AccountId> for proto::account::AccountId {
73 fn from(account_id: AccountId) -> Self {
74 Self { id: account_id.to_bytes() }
75 }
76}
77
78#[derive(Debug, PartialEq)]
82pub struct AccountSummary {
83 pub account_id: AccountId,
84 pub account_commitment: Word,
85 pub block_num: BlockNumber,
86}
87
88impl From<&AccountSummary> for proto::account::AccountSummary {
89 fn from(update: &AccountSummary) -> Self {
90 Self {
91 account_id: Some(update.account_id.into()),
92 account_commitment: Some(update.account_commitment.into()),
93 block_num: update.block_num.as_u32(),
94 }
95 }
96}
97
98#[derive(Debug, PartialEq)]
99pub struct AccountInfo {
100 pub summary: AccountSummary,
101 pub details: Option<Account>,
102}
103
104impl From<&AccountInfo> for proto::account::AccountDetails {
105 fn from(AccountInfo { summary, details }: &AccountInfo) -> Self {
106 Self {
107 summary: Some(summary.into()),
108 details: details.as_ref().map(Serializable::to_bytes),
109 }
110 }
111}
112
113impl TryFrom<proto::account::AccountStorageHeader> for AccountStorageHeader {
117 type Error = ConversionError;
118
119 fn try_from(value: proto::account::AccountStorageHeader) -> Result<Self, Self::Error> {
120 let proto::account::AccountStorageHeader { slots } = value;
121
122 let slot_headers = slots
123 .into_iter()
124 .map(|slot| {
125 let decoder = slot.decoder();
126 let slot_name = StorageSlotName::new(slot.slot_name)?;
127 let slot_type = storage_slot_type_from_raw(slot.slot_type)?;
128 let commitment = decode!(decoder, slot.commitment)?;
129 Ok(StorageSlotHeader::new(slot_name, slot_type, commitment))
130 })
131 .collect::<Result<Vec<_>, ConversionError>>()
132 .context("slots")?;
133
134 Ok(AccountStorageHeader::new(slot_headers)?)
135 }
136}
137
138pub struct AccountRequest {
143 pub account_id: AccountId,
144 pub block_num: Option<BlockNumber>,
146 pub details: Option<AccountDetailRequest>,
147}
148
149impl TryFrom<proto::rpc::AccountRequest> for AccountRequest {
150 type Error = ConversionError;
151
152 fn try_from(value: proto::rpc::AccountRequest) -> Result<Self, Self::Error> {
153 let decoder = value.decoder();
154 let proto::rpc::AccountRequest { account_id, block_num, details } = value;
155
156 let account_id = decode!(decoder, account_id)?;
157 let block_num = block_num.map(Into::into);
158
159 let details = details.map(TryFrom::try_from).transpose().context("details")?;
160
161 Ok(AccountRequest { account_id, block_num, details })
162 }
163}
164
165#[derive(Debug)]
167pub struct AccountDetailRequest {
168 pub code_commitment: Option<Word>,
169 pub asset_vault_commitment: Option<Word>,
170 pub storage_request: AccountStorageRequest,
171}
172
173#[derive(Debug, Clone, PartialEq, Eq)]
174pub enum AccountStorageRequest {
175 None,
176 AllStorageMaps,
177 Explicit(Vec<StorageMapRequest>),
178}
179
180impl TryFrom<proto::rpc::account_request::AccountDetailRequest> for AccountDetailRequest {
181 type Error = ConversionError;
182
183 fn try_from(
184 value: proto::rpc::account_request::AccountDetailRequest,
185 ) -> Result<Self, Self::Error> {
186 use proto::rpc::account_request::account_detail_request::StorageRequest as ProtoStorageRequest;
187
188 let proto::rpc::account_request::AccountDetailRequest {
189 code_commitment,
190 asset_vault_commitment,
191 storage_request,
192 } = value;
193
194 let code_commitment =
195 code_commitment.map(TryFrom::try_from).transpose().context("code_commitment")?;
196 let asset_vault_commitment = asset_vault_commitment
197 .map(TryFrom::try_from)
198 .transpose()
199 .context("asset_vault_commitment")?;
200
201 let storage_request = match storage_request {
202 None => AccountStorageRequest::None,
203 Some(ProtoStorageRequest::AllStorageMaps(true)) => {
204 AccountStorageRequest::AllStorageMaps
205 },
206 Some(ProtoStorageRequest::AllStorageMaps(false)) => {
207 return Err(ConversionError::message("all_storage_maps must be true when set"));
208 },
209 Some(ProtoStorageRequest::StorageMaps(requests)) => {
210 let requests = try_convert(requests.storage_maps)
211 .collect::<Result<_, _>>()
212 .context("storage_maps")?;
213 AccountStorageRequest::Explicit(requests)
214 },
215 };
216
217 Ok(AccountDetailRequest {
218 code_commitment,
219 asset_vault_commitment,
220 storage_request,
221 })
222 }
223}
224
225#[derive(Debug, Clone, PartialEq, Eq)]
226pub struct StorageMapRequest {
227 pub slot_name: StorageSlotName,
228 pub slot_data: SlotData,
229}
230
231impl TryFrom<proto::rpc::account_request::account_detail_request::StorageMapDetailRequest>
232 for StorageMapRequest
233{
234 type Error = ConversionError;
235
236 fn try_from(
237 value: proto::rpc::account_request::account_detail_request::StorageMapDetailRequest,
238 ) -> Result<Self, Self::Error> {
239 let decoder = value.decoder();
240 let proto::rpc::account_request::account_detail_request::StorageMapDetailRequest {
241 slot_name,
242 slot_data,
243 } = value;
244
245 let slot_name = StorageSlotName::new(slot_name).context("slot_name")?;
246 let slot_data = decode!(decoder, slot_data)?;
247
248 Ok(StorageMapRequest { slot_name, slot_data })
249 }
250}
251
252#[derive(Debug, Clone, PartialEq, Eq)]
254pub enum SlotData {
255 All,
256 MapKeys(Vec<StorageMapKey>),
257}
258
259impl
260 TryFrom<
261 proto::rpc::account_request::account_detail_request::storage_map_detail_request::SlotData,
262 > for SlotData
263{
264 type Error = ConversionError;
265
266 fn try_from(
267 value: proto::rpc::account_request::account_detail_request::storage_map_detail_request::SlotData,
268 ) -> Result<Self, Self::Error> {
269 use proto::rpc::account_request::account_detail_request::storage_map_detail_request::SlotData as ProtoSlotData;
270
271 Ok(match value {
272 ProtoSlotData::AllEntries(true) => SlotData::All,
273 ProtoSlotData::AllEntries(false) => {
274 return Err(ConversionError::message("enum variant discriminant out of range"));
275 },
276 ProtoSlotData::MapKeys(keys) => {
277 let keys = try_convert(keys.map_keys).collect::<Result<Vec<_>, _>>()?;
278 SlotData::MapKeys(keys)
279 },
280 })
281 }
282}
283
284impl TryFrom<proto::account::AccountHeader> for AccountHeader {
288 type Error = ConversionError;
289
290 fn try_from(value: proto::account::AccountHeader) -> Result<Self, Self::Error> {
291 let decoder = value.decoder();
292 let proto::account::AccountHeader {
293 account_id,
294 vault_root,
295 storage_commitment,
296 code_commitment,
297 nonce,
298 } = value;
299
300 let account_id = decode!(decoder, account_id)?;
301 let vault_root = decode!(decoder, vault_root)?;
302 let storage_commitment = decode!(decoder, storage_commitment)?;
303 let code_commitment = decode!(decoder, code_commitment)?;
304 let nonce = nonce
305 .try_into()
306 .map_err(|e| ConversionError::message(format!("{e}")))
307 .context("nonce")?;
308
309 Ok(AccountHeader::new(
310 account_id,
311 nonce,
312 vault_root,
313 storage_commitment,
314 code_commitment,
315 ))
316 }
317}
318
319impl From<AccountHeader> for proto::account::AccountHeader {
320 fn from(header: AccountHeader) -> Self {
321 proto::account::AccountHeader {
322 account_id: Some(header.id().into()),
323 vault_root: Some(header.vault_root().into()),
324 storage_commitment: Some(header.storage_commitment().into()),
325 code_commitment: Some(header.code_commitment().into()),
326 nonce: header.nonce().as_canonical_u64(),
327 }
328 }
329}
330
331impl From<AccountStorageHeader> for proto::account::AccountStorageHeader {
332 fn from(value: AccountStorageHeader) -> Self {
333 let slots = value
334 .slots()
335 .map(|slot_header| proto::account::account_storage_header::StorageSlot {
336 slot_name: slot_header.name().to_string(),
337 slot_type: storage_slot_type_to_raw(slot_header.slot_type()),
338 commitment: Some(proto::primitives::Digest::from(slot_header.value())),
339 })
340 .collect();
341
342 Self { slots }
343 }
344}
345
346#[derive(Debug, Clone, PartialEq, Eq)]
356pub enum AccountVaultDetails {
357 LimitExceeded,
360
361 Assets(Vec<Asset>),
363}
364
365impl AccountVaultDetails {
366 pub const MAX_RETURN_ENTRIES: usize = 1000;
369
370 pub fn empty() -> Self {
371 Self::Assets(Vec::new())
372 }
373
374 pub fn from_assets(assets: Vec<Asset>) -> Self {
376 if assets.len() > Self::MAX_RETURN_ENTRIES {
377 Self::LimitExceeded
378 } else {
379 Self::Assets(assets)
380 }
381 }
382}
383
384impl TryFrom<proto::rpc::AccountVaultDetails> for AccountVaultDetails {
385 type Error = ConversionError;
386
387 fn try_from(value: proto::rpc::AccountVaultDetails) -> Result<Self, Self::Error> {
388 let proto::rpc::AccountVaultDetails { too_many_assets, assets } = value;
389
390 if too_many_assets {
391 Ok(Self::LimitExceeded)
392 } else {
393 let parsed_assets = Result::<Vec<_>, ConversionError>::from_iter(
394 assets.into_iter().map(Asset::try_from),
395 )?;
396 Ok(Self::Assets(parsed_assets))
397 }
398 }
399}
400
401impl From<AccountVaultDetails> for proto::rpc::AccountVaultDetails {
402 fn from(value: AccountVaultDetails) -> Self {
403 match value {
404 AccountVaultDetails::LimitExceeded => Self {
405 too_many_assets: true,
406 assets: Vec::new(),
407 },
408 AccountVaultDetails::Assets(assets) => Self {
409 too_many_assets: false,
410 assets: Vec::from_iter(assets.into_iter().map(proto::primitives::Asset::from)),
411 },
412 }
413 }
414}
415
416#[derive(Debug, Clone, PartialEq, Eq)]
421pub struct AccountStorageMapDetails {
422 pub slot_name: StorageSlotName,
423 pub entries: StorageMapEntries,
424}
425
426#[derive(Debug, Clone, PartialEq, Eq)]
433pub enum StorageMapEntries {
434 LimitExceeded,
437
438 AllEntries(Vec<(StorageMapKey, Word)>),
441
442 EntriesWithProofs(Vec<SmtProof>),
445}
446
447impl AccountStorageMapDetails {
448 pub const MAX_RETURN_ENTRIES: usize = 1000;
450
451 pub const MAX_SMT_PROOF_ENTRIES: usize = QueryParamStorageMapKeyTotalLimit::LIMIT;
459
460 pub fn from_all_entries(slot_name: StorageSlotName, storage_map: &StorageMap) -> Self {
465 if storage_map.num_entries() > Self::MAX_RETURN_ENTRIES {
466 Self {
467 slot_name,
468 entries: StorageMapEntries::LimitExceeded,
469 }
470 } else {
471 let entries = Vec::from_iter(storage_map.entries().map(|(k, v)| (*k, *v)));
472 Self {
473 slot_name,
474 entries: StorageMapEntries::AllEntries(entries),
475 }
476 }
477 }
478
479 pub fn from_forest_entries(
483 slot_name: StorageSlotName,
484 entries: Vec<(StorageMapKey, Word)>,
485 ) -> Self {
486 if entries.len() > Self::MAX_RETURN_ENTRIES {
487 Self {
488 slot_name,
489 entries: StorageMapEntries::LimitExceeded,
490 }
491 } else {
492 Self {
493 slot_name,
494 entries: StorageMapEntries::AllEntries(entries),
495 }
496 }
497 }
498
499 pub fn from_proofs(slot_name: StorageSlotName, proofs: Vec<SmtProof>) -> Self {
504 if proofs.len() > Self::MAX_SMT_PROOF_ENTRIES {
505 Self {
506 slot_name,
507 entries: StorageMapEntries::LimitExceeded,
508 }
509 } else {
510 Self {
511 slot_name,
512 entries: StorageMapEntries::EntriesWithProofs(proofs),
513 }
514 }
515 }
516
517 pub fn limit_exceeded(slot_name: StorageSlotName) -> Self {
519 Self {
520 slot_name,
521 entries: StorageMapEntries::LimitExceeded,
522 }
523 }
524}
525
526impl TryFrom<proto::rpc::account_storage_details::AccountStorageMapDetails>
527 for AccountStorageMapDetails
528{
529 type Error = ConversionError;
530
531 fn try_from(
532 value: proto::rpc::account_storage_details::AccountStorageMapDetails,
533 ) -> Result<Self, Self::Error> {
534 use proto::rpc::account_storage_details::account_storage_map_details::{
535 AllMapEntries,
536 Entries as ProtoEntries,
537 MapEntriesWithProofs,
538 };
539
540 let proto::rpc::account_storage_details::AccountStorageMapDetails {
541 slot_name,
542 too_many_entries,
543 entries,
544 } = value;
545
546 let slot_name = StorageSlotName::new(slot_name).context("slot_name")?;
547
548 let entries = if too_many_entries {
549 StorageMapEntries::LimitExceeded
550 } else {
551 match entries {
552 None => {
553 return Err(ConversionError::missing_field::<
554 proto::rpc::account_storage_details::AccountStorageMapDetails,
555 >("entries"));
556 },
557 Some(ProtoEntries::AllEntries(AllMapEntries { entries })) => {
558 let entries = entries
559 .into_iter()
560 .map(|entry| {
561 let decoder = entry.decoder();
562 let key = StorageMapKey::new(decode!(decoder, entry.key)?);
563 let value = decode!(decoder, entry.value)?;
564 Ok((key, value))
565 })
566 .collect::<Result<Vec<_>, ConversionError>>()
567 .context("entries")?;
568 StorageMapEntries::AllEntries(entries)
569 },
570 Some(ProtoEntries::EntriesWithProofs(MapEntriesWithProofs { entries })) => {
571 let proofs = entries
572 .into_iter()
573 .map(|entry| {
574 let decoder = entry.decoder();
575 decode!(decoder, entry.proof)
576 })
577 .collect::<Result<Vec<_>, ConversionError>>()
578 .context("entries")?;
579 StorageMapEntries::EntriesWithProofs(proofs)
580 },
581 }
582 };
583
584 Ok(Self { slot_name, entries })
585 }
586}
587
588impl From<AccountStorageMapDetails>
589 for proto::rpc::account_storage_details::AccountStorageMapDetails
590{
591 fn from(value: AccountStorageMapDetails) -> Self {
592 use proto::rpc::account_storage_details::account_storage_map_details::{
593 AllMapEntries,
594 Entries as ProtoEntries,
595 MapEntriesWithProofs,
596 };
597
598 let AccountStorageMapDetails { slot_name, entries } = value;
599
600 let (too_many_entries, proto_entries) = match entries {
601 StorageMapEntries::LimitExceeded => (true, None),
602 StorageMapEntries::AllEntries(entries) => {
603 let all = AllMapEntries {
604 entries: Vec::from_iter(entries.into_iter().map(|(key, value)| {
605 proto::rpc::account_storage_details::account_storage_map_details::all_map_entries::StorageMapEntry {
606 key: Some(key.into()),
607 value: Some(value.into()),
608 }
609 })),
610 };
611 (false, Some(ProtoEntries::AllEntries(all)))
612 },
613 StorageMapEntries::EntriesWithProofs(proofs) => {
614 use miden_protocol::crypto::merkle::smt::SmtLeaf;
615
616 let with_proofs = MapEntriesWithProofs {
617 entries: Vec::from_iter(proofs.into_iter().map(|proof| {
618 let (key, value) = match proof.leaf() {
620 SmtLeaf::Empty(_) => {
621 (miden_protocol::EMPTY_WORD, miden_protocol::EMPTY_WORD)
622 },
623 SmtLeaf::Single((k, v)) => (*k, *v),
624 SmtLeaf::Multiple(entries) => entries.iter().next().map_or(
625 (miden_protocol::EMPTY_WORD, miden_protocol::EMPTY_WORD),
626 |(k, v)| (*k, *v),
627 ),
628 };
629 let smt_opening = proto::primitives::SmtOpening::from(proof);
630 proto::rpc::account_storage_details::account_storage_map_details::map_entries_with_proofs::StorageMapEntryWithProof {
631 key: Some(key.into()),
632 value: Some(value.into()),
633 proof: Some(smt_opening),
634 }
635 })),
636 };
637 (false, Some(ProtoEntries::EntriesWithProofs(with_proofs)))
638 },
639 };
640
641 Self {
642 slot_name: slot_name.to_string(),
643 too_many_entries,
644 entries: proto_entries,
645 }
646 }
647}
648
649#[derive(Debug, Clone, PartialEq)]
650pub struct AccountStorageDetails {
651 pub header: AccountStorageHeader,
652 pub map_details: Vec<AccountStorageMapDetails>,
653}
654
655impl AccountStorageDetails {
656 pub fn all_limits_exceeded(
658 header: AccountStorageHeader,
659 slot_names: impl IntoIterator<Item = StorageSlotName>,
660 ) -> Self {
661 Self {
662 header,
663 map_details: Vec::from_iter(
664 slot_names.into_iter().map(AccountStorageMapDetails::limit_exceeded),
665 ),
666 }
667 }
668}
669
670impl TryFrom<proto::rpc::AccountStorageDetails> for AccountStorageDetails {
671 type Error = ConversionError;
672
673 fn try_from(value: proto::rpc::AccountStorageDetails) -> Result<Self, Self::Error> {
674 let decoder = value.decoder();
675 let proto::rpc::AccountStorageDetails { header, map_details } = value;
676
677 let header = decode!(decoder, header)?;
678
679 let map_details =
680 try_convert(map_details).collect::<Result<Vec<_>, _>>().context("map_details")?;
681
682 Ok(Self { header, map_details })
683 }
684}
685
686impl From<AccountStorageDetails> for proto::rpc::AccountStorageDetails {
687 fn from(value: AccountStorageDetails) -> Self {
688 let AccountStorageDetails { header, map_details } = value;
689
690 Self {
691 header: Some(header.into()),
692 map_details: map_details.into_iter().map(Into::into).collect(),
693 }
694 }
695}
696
697fn storage_slot_type_from_raw(slot_type: u32) -> Result<StorageSlotType, ConversionError> {
698 Ok(match slot_type {
699 0 => StorageSlotType::Value,
700 1 => StorageSlotType::Map,
701 _ => {
702 return Err(ConversionError::message("enum variant discriminant out of range"));
703 },
704 })
705}
706
707const fn storage_slot_type_to_raw(slot_type: StorageSlotType) -> u32 {
708 match slot_type {
709 StorageSlotType::Value => 0,
710 StorageSlotType::Map => 1,
711 }
712}
713
714pub struct AccountResponse {
719 pub block_num: BlockNumber,
720 pub witness: AccountWitness,
721 pub details: Option<AccountDetails>,
722}
723
724impl TryFrom<proto::rpc::AccountResponse> for AccountResponse {
725 type Error = ConversionError;
726
727 fn try_from(value: proto::rpc::AccountResponse) -> Result<Self, Self::Error> {
728 let decoder = value.decoder();
729 let proto::rpc::AccountResponse { block_num, witness, details } = value;
730
731 let block_num = block_num
732 .ok_or(ConversionError::missing_field::<proto::rpc::AccountResponse>("block_num"))?
733 .into();
734
735 let witness = decode!(decoder, witness)?;
736
737 let details = details.map(TryFrom::try_from).transpose().context("details")?;
738
739 Ok(AccountResponse { block_num, witness, details })
740 }
741}
742
743impl From<AccountResponse> for proto::rpc::AccountResponse {
744 fn from(value: AccountResponse) -> Self {
745 let AccountResponse { block_num, witness, details } = value;
746
747 Self {
748 witness: Some(witness.into()),
749 details: details.map(Into::into),
750 block_num: Some(block_num.into()),
751 }
752 }
753}
754
755pub struct AccountDetails {
760 pub account_header: AccountHeader,
761 pub account_code: Option<Vec<u8>>,
762 pub vault_details: AccountVaultDetails,
763 pub storage_details: AccountStorageDetails,
764}
765
766impl AccountDetails {
767 pub fn with_storage_limits_exceeded(
769 account_header: AccountHeader,
770 account_code: Option<Vec<u8>>,
771 vault_details: AccountVaultDetails,
772 storage_header: AccountStorageHeader,
773 slot_names: impl IntoIterator<Item = StorageSlotName>,
774 ) -> Self {
775 Self {
776 account_header,
777 account_code,
778 vault_details,
779 storage_details: AccountStorageDetails::all_limits_exceeded(storage_header, slot_names),
780 }
781 }
782}
783
784impl TryFrom<proto::rpc::account_response::AccountDetails> for AccountDetails {
785 type Error = ConversionError;
786
787 fn try_from(value: proto::rpc::account_response::AccountDetails) -> Result<Self, Self::Error> {
788 let decoder = value.decoder();
789 let proto::rpc::account_response::AccountDetails {
790 header,
791 code,
792 vault_details,
793 storage_details,
794 } = value;
795
796 let account_header = decode!(decoder, header)?;
797
798 let storage_details = decode!(decoder, storage_details)?;
799
800 let vault_details = decode!(decoder, vault_details)?;
801 let account_code = code;
802
803 Ok(AccountDetails {
804 account_header,
805 account_code,
806 vault_details,
807 storage_details,
808 })
809 }
810}
811
812impl From<AccountDetails> for proto::rpc::account_response::AccountDetails {
813 fn from(value: AccountDetails) -> Self {
814 let AccountDetails {
815 account_header,
816 storage_details,
817 account_code,
818 vault_details,
819 } = value;
820
821 let header = Some(proto::account::AccountHeader::from(account_header));
822 let storage_details = Some(storage_details.into());
823 let code = account_code;
824 let vault_details = Some(vault_details.into());
825
826 Self {
827 header,
828 storage_details,
829 code,
830 vault_details,
831 }
832 }
833}
834
835impl TryFrom<proto::account::AccountWitness> for AccountWitness {
839 type Error = ConversionError;
840
841 fn try_from(account_witness: proto::account::AccountWitness) -> Result<Self, Self::Error> {
842 let decoder = account_witness.decoder();
843 let witness_id = decode!(decoder, account_witness.witness_id)?;
844 let commitment = decode!(decoder, account_witness.commitment)?;
845 let path = decode!(decoder, account_witness.path)?;
846
847 AccountWitness::new(witness_id, commitment, path).map_err(|err| {
848 ConversionError::deserialization(
849 "AccountWitness",
850 DeserializationError::InvalidValue(err.to_string()),
851 )
852 })
853 }
854}
855
856impl From<AccountWitness> for proto::account::AccountWitness {
857 fn from(witness: AccountWitness) -> Self {
858 Self {
859 account_id: Some(witness.id().into()),
860 witness_id: Some(witness.id().into()),
861 commitment: Some(witness.state_commitment().into()),
862 path: Some(witness.into_proof().into_parts().0.into()),
863 }
864 }
865}
866
867#[derive(Clone, Debug, PartialEq, Eq)]
871pub struct AccountWitnessRecord {
872 pub account_id: AccountId,
873 pub witness: AccountWitness,
874}
875
876impl TryFrom<proto::account::AccountWitness> for AccountWitnessRecord {
877 type Error = ConversionError;
878
879 fn try_from(
880 account_witness_record: proto::account::AccountWitness,
881 ) -> Result<Self, Self::Error> {
882 let decoder = account_witness_record.decoder();
883 let witness_id = decode!(decoder, account_witness_record.witness_id)?;
884 let commitment = decode!(decoder, account_witness_record.commitment)?;
885 let account_id = decode!(decoder, account_witness_record.account_id)?;
886 let path: SparseMerklePath = decode!(decoder, account_witness_record.path)?;
887
888 let witness = AccountWitness::new(witness_id, commitment, path).map_err(|err| {
889 ConversionError::deserialization(
890 "AccountWitness",
891 DeserializationError::InvalidValue(err.to_string()),
892 )
893 })?;
894
895 Ok(Self { account_id, witness })
896 }
897}
898
899impl From<AccountWitnessRecord> for proto::account::AccountWitness {
900 fn from(from: AccountWitnessRecord) -> Self {
901 Self {
902 account_id: Some(from.account_id.into()),
903 witness_id: Some(from.witness.id().into()),
904 commitment: Some(from.witness.state_commitment().into()),
905 path: Some(from.witness.path().clone().into()),
906 }
907 }
908}
909
910impl TryFrom<proto::primitives::Asset> for Asset {
914 type Error = ConversionError;
915
916 fn try_from(asset: proto::primitives::Asset) -> Result<Self, Self::Error> {
917 let decoder = asset.decoder();
918 let key_word: Word = decode!(decoder, asset.key)?;
919 let value_word: Word = decode!(decoder, asset.value)?;
920
921 let asset = Asset::from_key_value_words(key_word, value_word)?;
922 Ok(asset)
923 }
924}
925
926impl From<Asset> for proto::primitives::Asset {
927 fn from(asset_from: Asset) -> Self {
928 proto::primitives::Asset {
929 key: Some(asset_from.to_key_word().into()),
930 value: Some(asset_from.to_value_word().into()),
931 }
932 }
933}