monero_interface/
provides_outputs.rs

1use core::future::Future;
2use alloc::{format, vec::Vec};
3
4use monero_oxide::ed25519::{Point, CompressedPoint};
5
6use crate::InterfaceError;
7
8/// The response to an query for the information of a RingCT output.
9#[derive(Clone, Copy, PartialEq, Eq, Debug)]
10pub struct RingCtOutputInformation {
11  /// The block number of the block this output was added to the chain in.
12  pub block_number: usize,
13  /// If the output is unlocked, per the node's local view.
14  pub unlocked: bool,
15  /// The output's key.
16  ///
17  /// This is a `CompressedPoint`, not an `Point`, as it may be invalid. `CompressedPoint`
18  /// only asserts validity on decompression and allows representing invalid points.
19  pub key: CompressedPoint,
20  /// The output's commitment.
21  pub commitment: Point,
22  /// The transaction which created this output.
23  pub transaction: [u8; 32],
24}
25
26/// Provides unvalidated information about outputs.
27pub trait ProvidesUnvalidatedOutputs: Sync {
28  /// Get the indexes for this transaction's outputs on the blockchain.
29  ///
30  /// No validation is performed.
31  fn output_indexes(
32    &self,
33    hash: [u8; 32],
34  ) -> impl Send + Future<Output = Result<Vec<u64>, InterfaceError>>;
35
36  /// Get the specified outputs from the RingCT (zero-amount) pool.
37  ///
38  /// No validation of the outputs is performed other than confirming the correct amount is
39  /// returned.
40  fn ringct_outputs(
41    &self,
42    indexes: &[u64],
43  ) -> impl Send + Future<Output = Result<Vec<RingCtOutputInformation>, InterfaceError>>;
44}
45
46/// Provides information about outputs.
47pub trait ProvidesOutputs: Sync {
48  /// Get the indexes for this transaction's outputs on the blockchain.
49  ///
50  /// No validation is performed.
51  // We could check the outputs are contiguous if this was bound to only V2 transactions.
52  fn output_indexes(
53    &self,
54    hash: [u8; 32],
55  ) -> impl Send + Future<Output = Result<Vec<u64>, InterfaceError>>;
56
57  /// Get the specified outputs from the RingCT (zero-amount) pool.
58  ///
59  /// No validation of the outputs is performed other than confirming the correct amount is
60  /// returned.
61  fn ringct_outputs(
62    &self,
63    indexes: &[u64],
64  ) -> impl Send + Future<Output = Result<Vec<RingCtOutputInformation>, InterfaceError>>;
65}
66
67impl<P: ProvidesUnvalidatedOutputs> ProvidesOutputs for P {
68  fn output_indexes(
69    &self,
70    hash: [u8; 32],
71  ) -> impl Send + Future<Output = Result<Vec<u64>, InterfaceError>> {
72    <P as ProvidesUnvalidatedOutputs>::output_indexes(self, hash)
73  }
74
75  /// Get the specified outputs from the RingCT (zero-amount) pool.
76  ///
77  /// No validation of the outputs is performed other than confirming the correct amount is
78  /// returned.
79  fn ringct_outputs(
80    &self,
81    indexes: &[u64],
82  ) -> impl Send + Future<Output = Result<Vec<RingCtOutputInformation>, InterfaceError>> {
83    async move {
84      let outputs = <P as ProvidesUnvalidatedOutputs>::ringct_outputs(self, indexes).await?;
85      if outputs.len() != indexes.len() {
86        Err(InterfaceError::InternalError(format!(
87          "`{}` returned {} outputs, expected {}",
88          "ProvidesUnvalidatedOutputs::ringct_outputs",
89          outputs.len(),
90          indexes.len(),
91        )))?;
92      }
93      Ok(outputs)
94    }
95  }
96}