Skip to main content

drive_proof_verifier/proof/
token_direct_purchase.rs

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