drive_proof_verifier/proof/
identity_keys_remaining_budgets.rs1use crate::error::MapGroveDbError;
2use crate::types::identity_keys_remaining_budgets::IdentityKeysRemainingBudgets;
3use crate::verify::{supported_grovedb_proof_bytes, verify_tenderdash_proof};
4use crate::{ContextProvider, Error, FromProof};
5use dapi_grpc::platform::v0::{
6 get_identity_keys_remaining_budgets_request, GetIdentityKeysRemainingBudgetsRequest,
7 GetIdentityKeysRemainingBudgetsResponse, Proof, ResponseMetadata,
8};
9use dapi_grpc::platform::VersionedGrpcResponse;
10use dpp::dashcore::Network;
11use dpp::identity::KeyID;
12use dpp::version::PlatformVersion;
13use drive::drive::Drive;
14use std::collections::BTreeSet;
15
16pub(crate) fn parse_request(
20 request: GetIdentityKeysRemainingBudgetsRequest,
21) -> Result<([u8; 32], Vec<KeyID>), Error> {
22 let get_identity_keys_remaining_budgets_request::Version::V0(v0) =
23 request.version.ok_or(Error::EmptyVersion)?;
24 let identity_id = <[u8; 32]>::try_from(v0.identity_id).map_err(|_| Error::RequestError {
25 error: "can't convert identity_id to [u8; 32]".to_string(),
26 })?;
27 if v0.key_ids.is_empty() {
28 return Err(Error::RequestError {
29 error: "key_ids must name at least one key".to_string(),
30 });
31 }
32 if v0.key_ids.iter().collect::<BTreeSet<_>>().len() != v0.key_ids.len() {
33 return Err(Error::RequestError {
34 error: "key_ids must not repeat a key id".to_string(),
35 });
36 }
37 Ok((identity_id, v0.key_ids))
38}
39
40impl FromProof<GetIdentityKeysRemainingBudgetsRequest> for IdentityKeysRemainingBudgets {
41 type Request = GetIdentityKeysRemainingBudgetsRequest;
42 type Response = GetIdentityKeysRemainingBudgetsResponse;
43
44 fn maybe_from_proof_with_metadata<'a, I: Into<Self::Request>, O: Into<Self::Response>>(
45 request: I,
46 response: O,
47 _network: Network,
48 platform_version: &PlatformVersion,
49 provider: &'a dyn ContextProvider,
50 ) -> Result<(Option<Self>, ResponseMetadata, Proof), Error>
51 where
52 Self: Sized + 'a,
53 {
54 let request: Self::Request = request.into();
55 let response: Self::Response = response.into();
56
57 let (identity_id, key_ids) = parse_request(request)?;
58
59 let metadata = response
60 .metadata()
61 .or(Err(Error::EmptyResponseMetadata))?
62 .clone();
63
64 let proof = response.proof_owned().or(Err(Error::NoProofInResult))?;
65
66 let (root_hash, result) = Drive::verify_identity_keys_remaining_budgets(
67 supported_grovedb_proof_bytes(&proof)?,
68 identity_id,
69 &key_ids,
70 false,
71 platform_version,
72 )
73 .map_drive_error(&proof, &metadata)?;
74
75 verify_tenderdash_proof(&proof, &metadata, &root_hash, provider)?;
76
77 Ok((Some(result), metadata, proof))
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84 use dapi_grpc::platform::v0::get_identity_keys_remaining_budgets_request::GetIdentityKeysRemainingBudgetsRequestV0;
85
86 fn request(
87 identity_id: Vec<u8>,
88 key_ids: Vec<KeyID>,
89 ) -> GetIdentityKeysRemainingBudgetsRequest {
90 GetIdentityKeysRemainingBudgetsRequest {
91 version: Some(get_identity_keys_remaining_budgets_request::Version::V0(
92 GetIdentityKeysRemainingBudgetsRequestV0 {
93 identity_id,
94 key_ids,
95 prove: true,
96 },
97 )),
98 }
99 }
100
101 #[test]
102 fn should_parse_a_well_formed_request() {
103 let (identity_id, key_ids) =
104 parse_request(request(vec![4; 32], vec![7, 1])).expect("expected to parse");
105 assert_eq!(identity_id, [4; 32]);
106 assert_eq!(key_ids, vec![7, 1]);
107 }
108
109 #[test]
110 fn should_refuse_a_request_the_node_would_refuse_before_verifying_anything() {
111 assert!(matches!(
112 parse_request(GetIdentityKeysRemainingBudgetsRequest { version: None }),
113 Err(Error::EmptyVersion)
114 ));
115 for (bad_request, expected) in [
116 (request(vec![4; 31], vec![1]), "identity_id"),
117 (request(vec![4; 32], vec![]), "at least one key"),
118 (request(vec![4; 32], vec![2, 3, 2]), "must not repeat"),
119 ] {
120 assert!(
121 matches!(
122 parse_request(bad_request),
123 Err(Error::RequestError { error }) if error.contains(expected)
124 ),
125 "expected a request error about `{expected}`"
126 );
127 }
128 }
129}