1use super::*;
17
18use snarkvm_utilities::LoggableError;
19
20impl<N: Network, C: ConsensusStorage<N>> Ledger<N, C> {
21 pub fn find_block_height_from_state_root(&self, state_root: N::StateRoot) -> Result<Option<u32>> {
23 self.vm.block_store().find_block_height_from_state_root(state_root)
24 }
25
26 pub fn find_block_hash(&self, transaction_id: &N::TransactionID) -> Result<Option<N::BlockHash>> {
28 self.vm.block_store().find_block_hash(transaction_id)
29 }
30
31 pub fn find_block_height_from_solution_id(&self, solution_id: &SolutionID<N>) -> Result<Option<u32>> {
33 self.vm.block_store().find_block_height_from_solution_id(solution_id)
34 }
35
36 pub fn find_latest_transaction_id_from_program_id(
38 &self,
39 program_id: &ProgramID<N>,
40 ) -> Result<Option<N::TransactionID>> {
41 self.vm.transaction_store().find_latest_transaction_id_from_program_id(program_id)
42 }
43
44 pub fn find_transaction_id_from_program_id_and_edition(
46 &self,
47 program_id: &ProgramID<N>,
48 edition: u16,
49 ) -> Result<Option<N::TransactionID>> {
50 self.vm.transaction_store().find_transaction_id_from_program_id_and_edition(program_id, edition)
51 }
52
53 pub fn find_transaction_id_from_transition_id(
55 &self,
56 transition_id: &N::TransitionID,
57 ) -> Result<Option<N::TransactionID>> {
58 self.vm.transaction_store().find_transaction_id_from_transition_id(transition_id)
59 }
60
61 pub fn find_transition_id(&self, id: &Field<N>) -> Result<N::TransitionID> {
63 self.vm.transition_store().find_transition_id(id)
64 }
65
66 #[allow(clippy::type_complexity)]
68 pub fn find_record_ciphertexts<'a>(
69 &'a self,
70 view_key: &'a ViewKey<N>,
71 filter: RecordsFilter<N>,
72 ) -> Result<impl 'a + Iterator<Item = (Field<N>, Cow<'a, Record<N, Ciphertext<N>>>)>> {
73 let address_x_coordinate = view_key.to_address().to_x_coordinate();
75 let sk_tag = match GraphKey::try_from(view_key) {
77 Ok(graph_key) => graph_key.sk_tag(),
78 Err(e) => bail!("Failed to derive the graph key from the view key: {e}"),
79 };
80
81 Ok(self.records().flat_map(move |cow| {
82 let (commitment, record) = match cow {
84 (Cow::Borrowed(commitment), record) => (*commitment, record),
85 (Cow::Owned(commitment), record) => (commitment, record),
86 };
87
88 if !record.is_owner_with_address_x_coordinate(view_key, &address_x_coordinate) {
90 return None;
91 }
92
93 let commitment = match filter {
95 RecordsFilter::All => Ok(Some(commitment)),
96 RecordsFilter::Spent => Record::<N, Plaintext<N>>::tag(sk_tag, commitment).and_then(|tag| {
97 self.contains_tag(&tag).map(|is_spent| match is_spent {
99 true => Some(commitment),
100 false => None,
101 })
102 }),
103 RecordsFilter::Unspent => Record::<N, Plaintext<N>>::tag(sk_tag, commitment).and_then(|tag| {
104 self.contains_tag(&tag).map(|is_spent| match is_spent {
106 true => None,
107 false => Some(commitment),
108 })
109 }),
110 RecordsFilter::SlowSpent(private_key) => {
111 Record::<N, Plaintext<N>>::serial_number(private_key, commitment).and_then(|serial_number| {
112 self.contains_serial_number(&serial_number).map(|is_spent| match is_spent {
114 true => Some(commitment),
115 false => None,
116 })
117 })
118 }
119 RecordsFilter::SlowUnspent(private_key) => {
120 Record::<N, Plaintext<N>>::serial_number(private_key, commitment).and_then(|serial_number| {
121 self.contains_serial_number(&serial_number).map(|is_spent| match is_spent {
123 true => None,
124 false => Some(commitment),
125 })
126 })
127 }
128 };
129
130 match commitment {
131 Ok(Some(commitment)) => Some((commitment, record)),
132 Ok(None) => None,
133 Err(err) => {
134 err.log_warning(format!("Failed to process 'find_record_ciphertexts({filter:?})'"));
135 None
136 }
137 }
138 }))
139 }
140
141 #[allow(clippy::type_complexity)]
143 pub fn find_records<'a>(
144 &'a self,
145 view_key: &'a ViewKey<N>,
146 filter: RecordsFilter<N>,
147 ) -> Result<impl 'a + Iterator<Item = (Field<N>, Record<N, Plaintext<N>>)>> {
148 self.find_record_ciphertexts(view_key, filter).map(|iter| {
149 iter.flat_map(|(commitment, record)| match record.decrypt(view_key) {
150 Ok(record) => Some((commitment, record)),
151 Err(err) => {
152 err.log_warning("Failed to decrypt record");
153 None
154 }
155 })
156 })
157 }
158}