Skip to content

Commit

Permalink
feat: sdk to return proofs if requested (#2014)
Browse files Browse the repository at this point in the history
  • Loading branch information
QuantumExplorer authored Jul 28, 2024
1 parent 05c4d9d commit 9001aa9
Show file tree
Hide file tree
Showing 20 changed files with 324 additions and 141 deletions.
167 changes: 103 additions & 64 deletions packages/rs-drive-proof-verifier/src/proof.rs

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions packages/rs-sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ serde = { version = "1.0.197", default-features = false, features = [
], optional = true }
serde_json = { version = "1.0", features = ["preserve_order"], optional = true }
tracing = { version = "0.1.40" }
hex = { version = "0.4.3", optional = true }
hex = { version = "0.4.3"}
dotenvy = { version = "0.15.7", optional = true }
envy = { version = "0.4.2", optional = true }
futures = { version = "0.3.30" }
Expand Down Expand Up @@ -66,7 +66,6 @@ mocks = [
"dpp/random-identities",
"drive/serde",
"drive-proof-verifier/mocks",
"dep:hex",
"dep:dotenvy",
"dep:envy",
"dep:lru",
Expand Down
2 changes: 1 addition & 1 deletion packages/rs-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ In order to build application that uses Dash Platform SDK, you need to:

Dash Platform SDK supports mocking with `mocks` feature which provides a
convenient way to define mock expectations and use the SDK without actual
connection to the Platform.
connection to Platform.

You can see examples of mocking in [mock_fetch.rs](tests/fetch/mock_fetch.rs) and [mock_fetch_many.rs](tests/fetch/mock_fetch_many.rs).

Expand Down
2 changes: 1 addition & 1 deletion packages/rs-sdk/examples/read_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ async fn main() {
// Convert bytes to identifier object that can be used as a Query
let id = Identifier::from_bytes(&DATA_CONTRACT_ID_BYTES).expect("parse data contract id");

// Fetch identity from the Platform
// Fetch identity from Platform
let contract: Option<DataContract> =
DataContract::fetch(&sdk, id).await.expect("fetch identity");

Expand Down
2 changes: 1 addition & 1 deletion packages/rs-sdk/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub enum Error {
#[error("Required {0} not found: {1}")]
MissingDependency(String, String),
/// Epoch not found; we must have at least one epoch
#[error("No epoch found on the Platform; it should never happen")]
#[error("No epoch found on Platform; it should never happen")]
EpochNotFound,
/// SDK operation timeout reached error
#[error("SDK operation timeout {} secs reached: {1}", .0.as_secs())]
Expand Down
10 changes: 5 additions & 5 deletions packages/rs-sdk/src/mock/provider.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Example ContextProvider that uses the Core gRPC API to fetch data from the platform.
//! Example ContextProvider that uses the Core gRPC API to fetch data from Platform.

use crate::core_client::CoreClient;
use crate::platform::Fetch;
Expand All @@ -12,7 +12,7 @@ use std::hash::Hash;
use std::num::NonZeroUsize;
use std::sync::Arc;

/// Context provider that uses the Core gRPC API to fetch data from the platform.
/// Context provider that uses the Core gRPC API to fetch data from Platform.
///
/// Example [ContextProvider] used by the Sdk for testing purposes.
pub struct GrpcContextProvider {
Expand Down Expand Up @@ -40,7 +40,7 @@ pub struct GrpcContextProvider {

/// Directory where to store dumped data.
///
/// This is used to store data that is fetched from the platform and can be used for testing purposes.
/// This is used to store data that is fetched from Platform and can be used for testing purposes.
#[cfg(feature = "mocks")]
pub dump_dir: Option<std::path::PathBuf>,
}
Expand Down Expand Up @@ -83,7 +83,7 @@ impl GrpcContextProvider {
}
/// Set the directory where to store dumped data.
///
/// When set, the context provider will store data fetched from the platform into this directory.
/// When set, the context provider will store data fetched from Platform into this directory.
#[cfg(feature = "mocks")]
pub fn set_dump_dir(&mut self, dump_dir: Option<std::path::PathBuf>) {
self.dump_dir = dump_dir;
Expand Down Expand Up @@ -216,7 +216,7 @@ impl ContextProvider for GrpcContextProvider {

/// Thread-safe cache of various objects inside the SDK.
///
/// This is used to cache objects that are expensive to fetch from the platform, like data contracts.
/// This is used to cache objects that are expensive to fetch from Platform, like data contracts.
pub struct Cache<K: Hash + Eq, V> {
// We use a Mutex to allow access to the cache when we don't have mutable &self
// And we use Arc to allow multiple threads to access the cache without having to clone it
Expand Down
13 changes: 7 additions & 6 deletions packages/rs-sdk/src/mock/sdk.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Mocking mechanisms for Dash Platform SDK.
//!
//! See [MockDashPlatformSdk] for more details.
use dapi_grpc::platform::v0::ResponseMetadata;
use dapi_grpc::platform::v0::{Proof, ResponseMetadata};
use dapi_grpc::{
mock::Mockable,
platform::v0::{self as proto},
Expand Down Expand Up @@ -219,11 +219,11 @@ impl MockDashPlatformSdk {
/// ## Generic Parameters
///
/// - `O`: Type of the object that will be returned in response to the query. Must implement [Fetch] and [MockResponse].
/// - `Q`: Type of the query that will be sent to the platform. Must implement [Query] and [Mockable].
/// - `Q`: Type of the query that will be sent to Platform. Must implement [Query] and [Mockable].
///
/// ## Arguments
///
/// - `query`: Query that will be sent to the platform.
/// - `query`: Query that will be sent to Platform.
/// - `object`: Object that will be returned in response to `query`, or None if the object is expected to not exist.
///
/// ## Returns
Expand Down Expand Up @@ -284,11 +284,11 @@ impl MockDashPlatformSdk {
///
/// - `O`: Type of the object that will be returned in response to the query.
/// Must implement [FetchMany]. `Vec<O>` must implement [MockResponse].
/// - `Q`: Type of the query that will be sent to the platform. Must implement [Query] and [Mockable].
/// - `Q`: Type of the query that will be sent to Platform. Must implement [Query] and [Mockable].
///
/// ## Arguments
///
/// - `query`: Query that will be sent to the platform.
/// - `query`: Query that will be sent to Platform.
/// - `objects`: Vector of objects that will be returned in response to `query`, or None if no objects are expected.
///
/// ## Returns
Expand Down Expand Up @@ -369,7 +369,7 @@ impl MockDashPlatformSdk {
&self,
request: O::Request,
response: O::Response,
) -> Result<(Option<O>, ResponseMetadata), drive_proof_verifier::Error>
) -> Result<(Option<O>, ResponseMetadata, Proof), drive_proof_verifier::Error>
where
O::Request: Mockable,
Option<O>: MockResponse,
Expand All @@ -381,6 +381,7 @@ impl MockDashPlatformSdk {
Some(d) => (
Option::<O>::mock_deserialize(self, d),
ResponseMetadata::default(),
Proof::default(),
),
None => {
let version = self.version();
Expand Down
2 changes: 1 addition & 1 deletion packages/rs-sdk/src/platform/block_info_from_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use drive::error::proof::ProofError;
///
/// # Errors
/// Returns an error if:
/// - The `epoch` value in the response metadata exceeds the maximum value that can be represented by a 16-bit integer. This is considered a data validity error as it indicates the platform returned an unexpectedly high epoch number.
/// - The `epoch` value in the response metadata exceeds the maximum value that can be represented by a 16-bit integer. This is considered a data validity error as it indicates Platform returned an unexpectedly high epoch number.
///
/// The function encapsulates errors into the application's own `Error` type, providing a unified interface for error handling across the application.
pub fn block_info_from_metadata(response_metadata: &ResponseMetadata) -> Result<BlockInfo, Error> {
Expand Down
2 changes: 1 addition & 1 deletion packages/rs-sdk/src/platform/delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ macro_rules! delegate_from_proof_variant {
response: O,
version: &dpp::version::PlatformVersion,
provider: &'a dyn drive_proof_verifier::ContextProvider,
) -> Result<(Option<Self>, ResponseMetadata), drive_proof_verifier::Error>
) -> Result<(Option<Self>, ResponseMetadata, dapi_grpc::platform::v0::Proof), drive_proof_verifier::Error>
where
Self: Sized + 'a,
{
Expand Down
16 changes: 10 additions & 6 deletions packages/rs-sdk/src/platform/document_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use dapi_grpc::platform::v0::get_documents_request::Version::V0;
use dapi_grpc::platform::v0::{
self as platform_proto,
get_documents_request::{get_documents_request_v0::Start, GetDocumentsRequestV0},
GetDocumentsRequest, ResponseMetadata,
GetDocumentsRequest, Proof, ResponseMetadata,
};
use dpp::{
data_contract::{
Expand Down Expand Up @@ -162,21 +162,25 @@ impl FromProof<DocumentQuery> for Document {
response: O,
version: &dpp::version::PlatformVersion,
provider: &'a dyn drive_proof_verifier::ContextProvider,
) -> Result<(Option<Self>, ResponseMetadata), drive_proof_verifier::Error>
) -> Result<(Option<Self>, ResponseMetadata, Proof), drive_proof_verifier::Error>
where
Self: Sized + 'a,
{
let request: Self::Request = request.into();

let (documents, metadata): (Option<Documents>, ResponseMetadata) =
let (documents, metadata, proof): (Option<Documents>, ResponseMetadata, Proof) =
<Documents as FromProof<Self::Request>>::maybe_from_proof_with_metadata(
request, response, version, provider,
)?;

match documents {
None => Ok((None, metadata)),
None => Ok((None, metadata, proof)),
Some(docs) => match docs.len() {
0 | 1 => Ok((docs.into_iter().next().and_then(|(_, v)| v), metadata)),
0 | 1 => Ok((
docs.into_iter().next().and_then(|(_, v)| v),
metadata,
proof,
)),
n => Err(drive_proof_verifier::Error::ResponseDecodeError {
error: format!("expected 1 element, got {}", n),
}),
Expand All @@ -193,7 +197,7 @@ impl FromProof<DocumentQuery> for drive_proof_verifier::types::Documents {
response: O,
version: &dpp::version::PlatformVersion,
provider: &'a dyn drive_proof_verifier::ContextProvider,
) -> Result<(Option<Self>, ResponseMetadata), drive_proof_verifier::Error>
) -> Result<(Option<Self>, ResponseMetadata, Proof), drive_proof_verifier::Error>
where
Self: Sized + 'a,
{
Expand Down
74 changes: 62 additions & 12 deletions packages/rs-sdk/src/platform/fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
//! It allows fetching of various types of data such as `Identity`, `DataContract`, and `Document`.
//!
//! ## Traits
//! - [Fetch]: An asynchronous trait that defines how to fetch data from the platform.
//! - [Fetch]: An asynchronous trait that defines how to fetch data from Platform.
//! It requires the implementing type to also implement [Debug] and [FromProof]
//! traits. The associated [Fetch::Request]` type needs to implement [TransportRequest].

use crate::mock::MockResponse;
use crate::{error::Error, platform::query::Query, Sdk};
use dapi_grpc::platform::v0::{self as platform_proto, ResponseMetadata};
use dapi_grpc::platform::v0::{self as platform_proto, Proof, ResponseMetadata};
use dpp::voting::votes::Vote;
use dpp::{
block::extended_epoch_info::ExtendedEpochInfo, document::Document, platform_value::Identifier,
Expand All @@ -23,9 +23,9 @@ use std::fmt::Debug;
use super::types::identity::IdentityRequest;
use super::DocumentQuery;

/// Trait implemented by objects that can be fetched from the platform.
/// Trait implemented by objects that can be fetched from Platform.
///
/// To fetch an object from the platform, you need to define some query (criteria that fetched object must match) and
/// To fetch an object from Platform, you need to define some query (criteria that fetched object must match) and
/// use [Fetch::fetch()] for your object type.
///
/// Implementators of this trait should implement at least the [fetch_with_metadata()](Fetch::fetch_with_metadata)
Expand Down Expand Up @@ -59,16 +59,16 @@ where
Response = <<Self as Fetch>::Request as DapiRequest>::Response,
>,
{
/// Type of request used to fetch data from the platform.
/// Type of request used to fetch data from Platform.
///
/// Most likely, one of the types defined in [`dapi_grpc::platform::v0`].
///
/// This type must implement [`TransportRequest`] and [`MockRequest`].
type Request: TransportRequest + Into<<Self as FromProof<<Self as Fetch>::Request>>::Request>;

/// Fetch single object from the Platfom.
/// Fetch single object from Platform.
///
/// Fetch object from the platform that satisfies provided [Query].
/// Fetch object from Platform that satisfies provided [Query].
/// Most often, the Query is an [Identifier] of the object to be fetched.
///
/// ## Parameters
Expand All @@ -93,15 +93,16 @@ where
Self::fetch_with_settings(sdk, query, RequestSettings::default()).await
}

/// Fetch single object from the Platfom.
/// Fetch single object from Platform with metadata.
///
/// Fetch object from the platform that satisfies provided [Query].
/// Fetch object from Platform that satisfies provided [Query].
/// Most often, the Query is an [Identifier] of the object to be fetched.
///
/// ## Parameters
///
/// - `sdk`: An instance of [Sdk].
/// - `query`: A query parameter implementing [`crate::platform::query::Query`] to specify the data to be fetched.
/// - `settings`: An optional `RequestSettings` to give greater flexibility on the request.
///
/// ## Returns
///
Expand Down Expand Up @@ -137,9 +138,58 @@ where
}
}

/// Fetch single object from the Platfom.
/// Fetch single object from Platform with metadata and underlying proof.
///
/// Fetch object from the platform that satisfies provided [Query].
/// Fetch object from Platform that satisfies provided [Query].
/// Most often, the Query is an [Identifier] of the object to be fetched.
///
/// This method is meant to give the user library a way to see the underlying proof
/// for educational purposes. This method should most likely only be used for debugging.
///
/// ## Parameters
///
/// - `sdk`: An instance of [Sdk].
/// - `query`: A query parameter implementing [`crate::platform::query::Query`] to specify the data to be fetched.
/// - `settings`: An optional `RequestSettings` to give greater flexibility on the request.
///
/// ## Returns
///
/// Returns:
/// * `Ok(Some(Self))` when object is found
/// * `Ok(None)` when object is not found
/// * [`Err(Error)`](Error) when an error occurs
///
/// ## Error Handling
///
/// Any errors encountered during the execution are returned as [Error] instances.
async fn fetch_with_metadata_and_proof<Q: Query<<Self as Fetch>::Request>>(
sdk: &Sdk,
query: Q,
settings: Option<RequestSettings>,
) -> Result<(Option<Self>, ResponseMetadata, Proof), Error> {
let request = query.query(sdk.prove())?;

let response = request
.clone()
.execute(sdk, settings.unwrap_or_default())
.await?;

let object_type = std::any::type_name::<Self>().to_string();
tracing::trace!(request = ?request, response = ?response, object_type, "fetched object from platform");

let (object, response_metadata, proof): (Option<Self>, ResponseMetadata, Proof) = sdk
.parse_proof_with_metadata_and_proof(request, response)
.await?;

match object {
Some(item) => Ok((item.into(), response_metadata, proof)),
None => Ok((None, response_metadata, proof)),
}
}

/// Fetch single object from Platform.
///
/// Fetch object from Platform that satisfies provided [Query].
/// Most often, the Query is an [Identifier] of the object to be fetched.
///
/// ## Parameters
Expand Down Expand Up @@ -167,7 +217,7 @@ where
Ok(object)
}

/// Fetch single object from the Platform by identifier.
/// Fetch single object from Platform by identifier.
///
/// Convenience method that allows fetching objects by identifier for types that implement [Query] for [Identifier].
///
Expand Down
Loading

0 comments on commit 9001aa9

Please sign in to comment.