Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: sdk to return proofs if requested #2014

Merged
merged 4 commits into from
Jul 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading