drive_proof_verifier/proof/
token_direct_purchase.rs

1use std::collections::BTreeSet;
2
3use dapi_grpc::platform::{
4    v0::{
5        get_token_direct_purchase_prices_request::Version as RequestVersion,
6        GetTokenDirectPurchasePricesRequest, GetTokenDirectPurchasePricesResponse, Proof,
7        ResponseMetadata,
8    },
9    VersionedGrpcResponse,
10};
11use dpp::{
12    dashcore::{secp256k1::hashes::hex::DisplayHex, Network},
13    version::PlatformVersion,
14};
15use drive::drive::Drive;
16
17use crate::{
18    error::MapGroveDbError, types::TokenDirectPurchasePrices, verify::verify_tenderdash_proof,
19    ContextProvider, Error,
20};
21
22use super::FromProof;
23
24impl FromProof<GetTokenDirectPurchasePricesRequest> for TokenDirectPurchasePrices {
25    type Request = GetTokenDirectPurchasePricesRequest;
26    type Response = GetTokenDirectPurchasePricesResponse;
27
28    fn maybe_from_proof_with_metadata<'a, I: Into<Self::Request>, O: Into<Self::Response>>(
29        request: I,
30        response: O,
31        _network: Network,
32        platform_version: &PlatformVersion,
33        provider: &'a dyn ContextProvider,
34    ) -> Result<(Option<Self>, ResponseMetadata, Proof), Error>
35    where
36        Self: 'a,
37    {
38        let request: Self::Request = request.into();
39        let response: Self::Response = response.into();
40
41        // Parse response to read proof and metadata
42        let proof = response.proof().or(Err(Error::NoProofInResult))?;
43
44        let mtd = response.metadata().or(Err(Error::EmptyResponseMetadata))?;
45
46        let token_ids = match request.version.ok_or(Error::EmptyVersion)? {
47            RequestVersion::V0(v0) => v0.token_ids,
48        }
49        .into_iter()
50        .map(<[u8; 32]>::try_from)
51        .collect::<Result<BTreeSet<_>, _>>() // BTreeSet to make it unique
52        .map_err(|e| Error::RequestError {
53            error: format!("token id {} has invalid length", e.to_lower_hex_string()),
54        })?
55        .into_iter()
56        .collect::<Vec<_>>();
57
58        // Extract content from proof and verify Drive/GroveDB proofs
59        let (root_hash, tokens): (_, Self) = Drive::verify_token_direct_selling_prices(
60            &proof.grovedb_proof,
61            &token_ids,
62            false,
63            platform_version,
64        )
65        .map_drive_error(proof, mtd)?;
66
67        verify_tenderdash_proof(proof, mtd, &root_hash, provider)?;
68
69        if tokens.is_empty() {
70            return Ok((None, mtd.clone(), proof.clone()));
71        }
72
73        Ok((Some(tokens), mtd.clone(), proof.clone()))
74    }
75}