drive_proof_verifier/proof/
token_pre_programmed_distributions.rs

1use crate::error::MapGroveDbError;
2use crate::verify::verify_tenderdash_proof;
3use crate::{types::TokenPreProgrammedDistributions, ContextProvider, Error};
4use dapi_grpc::platform::v0::{
5    get_token_pre_programmed_distributions_request, GetTokenPreProgrammedDistributionsRequest,
6    GetTokenPreProgrammedDistributionsResponse, Proof, ResponseMetadata,
7};
8use dapi_grpc::platform::VersionedGrpcResponse;
9use dpp::dashcore::Network;
10use dpp::prelude::Identifier;
11use dpp::version::PlatformVersion;
12use drive::drive::tokens::distribution::queries::QueryPreProgrammedDistributionStartAt;
13use drive::drive::Drive;
14
15use super::FromProof;
16
17impl FromProof<GetTokenPreProgrammedDistributionsRequest> for TokenPreProgrammedDistributions {
18    type Request = GetTokenPreProgrammedDistributionsRequest;
19    type Response = GetTokenPreProgrammedDistributionsResponse;
20
21    fn maybe_from_proof_with_metadata<'a, I: Into<Self::Request>, O: Into<Self::Response>>(
22        request: I,
23        response: O,
24        _network: Network,
25        platform_version: &PlatformVersion,
26        provider: &'a dyn ContextProvider,
27    ) -> Result<(Option<Self>, ResponseMetadata, Proof), Error>
28    where
29        Self: Sized + 'a,
30    {
31        let request: Self::Request = request.into();
32        let response: Self::Response = response.into();
33
34        let get_token_pre_programmed_distributions_request::Version::V0(req_v0) =
35            request.version.ok_or(Error::EmptyVersion)?;
36
37        let token_id: [u8; 32] =
38            req_v0
39                .token_id
40                .as_slice()
41                .try_into()
42                .map_err(|_| Error::RequestError {
43                    error: "token_id must be 32 bytes".into(),
44                })?;
45
46        let start_at = match req_v0.start_at_info {
47            Some(start_at_info) => {
48                let start_at_recipient = match start_at_info.start_recipient {
49                    Some(recipient_bytes) => {
50                        let recipient_id =
51                            Identifier::from_bytes(&recipient_bytes).map_err(|_| {
52                                Error::RequestError {
53                                    error: "start_recipient must be 32 bytes".into(),
54                                }
55                            })?;
56                        // Default to inclusive: if omitted the start recipient is included.
57                        let included = start_at_info.start_recipient_included.unwrap_or(true);
58                        Some((recipient_id, included))
59                    }
60                    None => None,
61                };
62
63                Some(QueryPreProgrammedDistributionStartAt {
64                    start_at_time: start_at_info.start_time_ms,
65                    start_at_recipient,
66                })
67            }
68            None => None,
69        };
70
71        let limit = req_v0
72            .limit
73            .map(|l| {
74                u16::try_from(l).map_err(|_| Error::RequestError {
75                    error: "limit exceeds u16::MAX".into(),
76                })
77            })
78            .transpose()?;
79
80        let metadata = response
81            .metadata()
82            .or(Err(Error::EmptyResponseMetadata))?
83            .clone();
84
85        let proof = response.proof_owned().or(Err(Error::NoProofInResult))?;
86
87        let (root_hash, result): ([u8; 32], TokenPreProgrammedDistributions) =
88            Drive::verify_token_pre_programmed_distributions(
89                &proof.grovedb_proof,
90                token_id,
91                start_at,
92                limit,
93                false,
94                platform_version,
95            )
96            .map_drive_error(&proof, &metadata)?;
97
98        verify_tenderdash_proof(&proof, &metadata, &root_hash, provider)?;
99
100        if result.0.is_empty() {
101            Ok((None, metadata, proof))
102        } else {
103            Ok((Some(result), metadata, proof))
104        }
105    }
106}