Skip to content

Commit

Permalink
fix(sdk): broadcasting state transition missing impl of contract prov…
Browse files Browse the repository at this point in the history
…ider
  • Loading branch information
lklimek committed Jun 28, 2024
1 parent 467bfa7 commit c68b617
Show file tree
Hide file tree
Showing 11 changed files with 85 additions and 31 deletions.
2 changes: 1 addition & 1 deletion packages/rs-drive-proof-verifier/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ pub mod types;
mod verify;
pub use error::Error;
pub use proof::{FromProof, Length};
pub use provider::ContextProvider;
#[cfg(feature = "mocks")]
pub use provider::MockContextProvider;
pub use provider::{ContextProvider, DataContractProvider};
pub mod from_request;

// Needed for #[derive(PlatformSerialize, PlatformDeserialize)]
Expand Down
29 changes: 8 additions & 21 deletions packages/rs-drive-proof-verifier/src/proof.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::from_request::TryFromRequest;
use crate::provider::DataContractProvider;
use crate::{types, types::*, ContextProvider, Error};
use dapi_grpc::platform::v0::get_identities_contract_keys_request::GetIdentitiesContractKeysRequestV0;
use dapi_grpc::platform::v0::get_path_elements_request::GetPathElementsRequestV0;
Expand Down Expand Up @@ -46,11 +47,10 @@ use drive::query::contested_resource_votes_given_by_identity_query::ContestedRes
use drive::query::vote_poll_contestant_votes_query::ContestedDocumentVotePollVotesDriveQuery;
use drive::query::vote_poll_vote_state_query::ContestedDocumentVotePollDriveQuery;
use drive::query::vote_polls_by_document_type_query::VotePollsByDocumentTypeQuery;
use drive::query::{ContractLookupFn, DriveQuery, VotePollsByEndDateDriveQuery};
use drive::query::{DriveQuery, VotePollsByEndDateDriveQuery};
use std::array::TryFromSliceError;
use std::collections::BTreeMap;
use std::num::TryFromIntError;
use std::sync::Arc;

use crate::verify::verify_tenderdash_proof;

Expand Down Expand Up @@ -861,7 +861,7 @@ impl FromProof<platform::BroadcastStateTransitionRequest> for StateTransitionPro
epoch: (metadata.epoch as u16).try_into()?,
};

let contracts_provider_fn = known_contracts_provider_fn(provider);
let contracts_provider_fn = provider.as_contract_lookup_fn();

let (root_hash, result) = Drive::verify_state_transition_was_executed_with_proof(
&state_transition,
Expand Down Expand Up @@ -1271,8 +1271,8 @@ impl FromProof<platform::GetContestedResourcesRequest> for ContestedResources {

// Decode request to get drive query
let drive_query = VotePollsByDocumentTypeQuery::try_from_request(request)?;
let resolved_request = drive_query
.resolve_with_known_contracts_provider(&known_contracts_provider_fn(provider))?;
let resolved_request =
drive_query.resolve_with_known_contracts_provider(&provider.as_contract_lookup_fn())?;

// Parse response to read proof and metadata
let proof = response.proof().or(Err(Error::NoProofInResult))?;
Expand Down Expand Up @@ -1314,7 +1314,7 @@ impl FromProof<platform::GetContestedResourceVoteStateRequest> for Contenders {
let drive_query = ContestedDocumentVotePollDriveQuery::try_from_request(request)?;

// Resolve request to get verify_*_proof
let contracts_provider = known_contracts_provider_fn(provider);
let contracts_provider = provider.as_contract_lookup_fn();
let resolved_request =
drive_query.resolve_with_known_contracts_provider(&contracts_provider)?;

Expand Down Expand Up @@ -1365,7 +1365,7 @@ impl FromProof<GetContestedResourceVotersForIdentityRequest> for Voters {
let drive_query = ContestedDocumentVotePollVotesDriveQuery::try_from_request(request)?;

// Parse request to get resolved contract that implements verify_*_proof
let contracts_provider = known_contracts_provider_fn(provider);
let contracts_provider = provider.as_contract_lookup_fn();

let resolved_request =
drive_query.resolve_with_known_contracts_provider(&contracts_provider)?;
Expand Down Expand Up @@ -1414,7 +1414,7 @@ impl FromProof<platform::GetContestedResourceIdentityVotesRequest> for ResourceV
let proof = response.proof().or(Err(Error::NoProofInResult))?;
let mtd = response.metadata().or(Err(Error::EmptyResponseMetadata))?;

let contract_provider_fn = known_contracts_provider_fn(provider);
let contract_provider_fn = provider.as_contract_lookup_fn();
let (root_hash, voters) = drive_query
.verify_identity_votes_given_proof(
&proof.grovedb_proof,
Expand Down Expand Up @@ -1584,19 +1584,6 @@ fn u32_to_u16_opt(i: u32) -> Result<Option<u16>, Error> {
Ok(i)
}

/// Returns function that uses [ContextProvider] to provide a [DataContract] to Drive proof verification functions
fn known_contracts_provider_fn<'a, P: ContextProvider + ?Sized + 'a>(
provider: &'a P,
) -> Box<ContractLookupFn> {
let f = |id: &Identifier| -> Result<Option<Arc<DataContract>>, drive::error::Error> {
provider.get_data_contract(id).map_err(|e| {
drive::error::Error::Proof(ProofError::ErrorRetrievingContract(e.to_string()))
})
};

Box::new(f)
}

/// Determine number of non-None elements
pub trait Length {
/// Return number of non-None elements in the data structure
Expand Down
22 changes: 22 additions & 0 deletions packages/rs-drive-proof-verifier/src/provider.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::error::ContextProviderError;
use dpp::prelude::{DataContract, Identifier};
use drive::{error::proof::ProofError, query::ContractLookupFn};
#[cfg(feature = "mocks")]
use hex::ToHex;
use std::{io::ErrorKind, ops::Deref, sync::Arc};
Expand Down Expand Up @@ -95,6 +96,27 @@ where
}
}

/// A trait that provides a function that can be used to look up a [DataContract] by its [Identifier].
///
/// This trait is automatically implemented for any type that implements [ContextProvider].
/// It is used internally by the Drive proof verification functions to look up data contracts.
pub trait DataContractProvider: Send + Sync {
/// Returns [ContractLookupFn] function that can be used to look up a [DataContract] by its [Identifier].
fn as_contract_lookup_fn(&self) -> Box<ContractLookupFn>;
}
impl<C: ContextProvider + ?Sized> DataContractProvider for C {
/// Returns function that uses [ContextProvider] to provide a [DataContract] to Drive proof verification functions
fn as_contract_lookup_fn(&self) -> Box<ContractLookupFn> {
let f = |id: &Identifier| -> Result<Option<Arc<DataContract>>, drive::error::Error> {
self.get_data_contract(id).map_err(|e| {
drive::error::Error::Proof(ProofError::ErrorRetrievingContract(e.to_string()))
})
};

Box::new(f)
}
}

/// Mock ContextProvider that can read quorum keys from files.
///
/// Use [dash_sdk::SdkBuilder::with_dump_dir()] to generate quorum keys files.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,12 @@ impl Drive {

let document_type = contract
.document_type_for_name(transition.document_type_name())
.map_err(|_| {
.map_err(|e| {
Error::Proof(ProofError::UnknownContract(format!(
"unknown contract document {} with id {}",
"cannot fetch contract for document {} with id {}: {}",
transition.document_type_name(),
transition.data_contract_id()
transition.data_contract_id(),
e
)))
})?;

Expand Down
9 changes: 8 additions & 1 deletion packages/rs-sdk/src/platform/transition/broadcast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use dapi_grpc::platform::VersionedGrpcResponse;
use dpp::state_transition::proof_result::StateTransitionProofResult;
use dpp::state_transition::StateTransition;
use drive::drive::Drive;
use drive_proof_verifier::error::ContextProviderError;
use drive_proof_verifier::DataContractProvider;
use rs_dapi_client::{DapiRequest, RequestSettings};

#[async_trait::async_trait]
Expand Down Expand Up @@ -47,12 +49,17 @@ impl BroadcastStateTransition for StateTransition {

let block_info = block_info_from_metadata(response.metadata()?)?;
let proof = response.proof_owned()?;
let context_provider =
sdk.context_provider()
.ok_or(Error::from(ContextProviderError::Config(
"Context provider not initialized".to_string(),
)))?;

let (_, result) = Drive::verify_state_transition_was_executed_with_proof(
self,
&block_info,
proof.grovedb_proof.as_slice(),
&|_| Ok(None),
&context_provider.as_contract_lookup_fn(),
sdk.version(),
)?;

Expand Down
9 changes: 8 additions & 1 deletion packages/rs-sdk/src/platform/transition/put_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ use dpp::state_transition::data_contract_create_transition::DataContractCreateTr
use dpp::state_transition::proof_result::StateTransitionProofResult;
use dpp::state_transition::StateTransition;
use drive::drive::Drive;
use drive_proof_verifier::error::ContextProviderError;
use drive_proof_verifier::DataContractProvider;
use rs_dapi_client::{DapiRequest, RequestSettings};

#[async_trait::async_trait]
Expand Down Expand Up @@ -103,12 +105,17 @@ impl<S: Signer> PutContract<S> for DataContract {
let block_info = block_info_from_metadata(response.metadata()?)?;

let proof = response.proof_owned()?;
let context_provider =
sdk.context_provider()
.ok_or(Error::from(ContextProviderError::Config(
"Context provider not initialized".to_string(),
)))?;

let (_, result) = Drive::verify_state_transition_was_executed_with_proof(
&state_transition,
&block_info,
proof.grovedb_proof.as_slice(),
&|_| Ok(None),
&context_provider.as_contract_lookup_fn(),
sdk.version(),
)?;

Expand Down
9 changes: 8 additions & 1 deletion packages/rs-sdk/src/platform/transition/put_identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use dapi_grpc::tonic::Code;
use dpp::dashcore::PrivateKey;
use dpp::identity::signer::Signer;
use dpp::prelude::{AssetLockProof, Identity};
use drive_proof_verifier::error::ContextProviderError;
use drive_proof_verifier::DataContractProvider;

use crate::platform::block_info_from_metadata::block_info_from_metadata;
use dpp::state_transition::proof_result::StateTransitionProofResult;
Expand Down Expand Up @@ -103,12 +105,17 @@ impl<S: Signer> PutIdentity<S> for Identity {

let block_info = block_info_from_metadata(response.metadata()?)?;
let proof = response.proof_owned()?;
let context_provider =
sdk.context_provider()
.ok_or(Error::from(ContextProviderError::Config(
"Context provider not initialized".to_string(),
)))?;

let (_, result) = Drive::verify_state_transition_was_executed_with_proof(
&state_transition,
&block_info,
proof.grovedb_proof.as_slice(),
&|_| Ok(None),
&context_provider.as_contract_lookup_fn(),
sdk.version(),
)?;

Expand Down
9 changes: 8 additions & 1 deletion packages/rs-sdk/src/platform/transition/top_up_identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ use dpp::state_transition::identity_topup_transition::methods::IdentityTopUpTran
use dpp::state_transition::identity_topup_transition::IdentityTopUpTransition;
use dpp::state_transition::proof_result::StateTransitionProofResult;
use drive::drive::Drive;
use drive_proof_verifier::error::ContextProviderError;
use drive_proof_verifier::DataContractProvider;
use rs_dapi_client::{DapiRequest, RequestSettings};

#[async_trait::async_trait]
Expand Down Expand Up @@ -54,12 +56,17 @@ impl TopUpIdentity for Identity {
let block_info = block_info_from_metadata(response.metadata()?)?;

let proof = response.proof_owned()?;
let context_provider =
sdk.context_provider()
.ok_or(Error::from(ContextProviderError::Config(
"Context provider not initialized".to_string(),
)))?;

let (_, result) = Drive::verify_state_transition_was_executed_with_proof(
&state_transition,
&block_info,
proof.grovedb_proof.as_slice(),
&|_| Ok(None),
&context_provider.as_contract_lookup_fn(),
sdk.version(),
)?;

Expand Down
8 changes: 7 additions & 1 deletion packages/rs-sdk/src/platform/transition/vote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use dpp::state_transition::proof_result::StateTransitionProofResult;
use dpp::voting::votes::resource_vote::accessors::v0::ResourceVoteGettersV0;
use dpp::voting::votes::Vote;
use drive::drive::Drive;
use drive_proof_verifier::{error::ContextProviderError, DataContractProvider};
use rs_dapi_client::DapiRequest;

#[async_trait::async_trait]
Expand Down Expand Up @@ -122,12 +123,17 @@ impl<S: Signer> PutVote<S> for Vote {

let block_info = block_info_from_metadata(response.metadata()?)?;
let proof = response.proof_owned()?;
let context_provider =
sdk.context_provider()
.ok_or(Error::from(ContextProviderError::Config(
"Context provider not initialized".to_string(),
)))?;

let (_, result) = Drive::verify_state_transition_was_executed_with_proof(
&masternode_vote_transition,
&block_info,
proof.grovedb_proof.as_slice(),
&|_| Ok(None),
&context_provider.as_contract_lookup_fn(),
sdk.version(),
)?;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use dpp::identity::Identity;
use dpp::prelude::UserFeeIncrease;

use dpp::state_transition::identity_credit_withdrawal_transition::IdentityCreditWithdrawalTransition;
use drive_proof_verifier::error::ContextProviderError;
use drive_proof_verifier::DataContractProvider;

use crate::platform::block_info_from_metadata::block_info_from_metadata;
use crate::platform::transition::broadcast_request::BroadcastRequestForStateTransition;
Expand Down Expand Up @@ -74,12 +76,17 @@ impl WithdrawFromIdentity for Identity {
let block_info = block_info_from_metadata(response.metadata()?)?;

let proof = response.proof_owned()?;
let context_provider =
sdk.context_provider()
.ok_or(Error::from(ContextProviderError::Config(
"Context provider not initialized".to_string(),
)))?;

let (_, result) = Drive::verify_state_transition_was_executed_with_proof(
&state_transition,
&block_info,
proof.grovedb_proof.as_slice(),
&|_| Ok(None),
&context_provider.as_contract_lookup_fn(),
sdk.version(),
)?;

Expand Down
3 changes: 3 additions & 0 deletions packages/rs-sdk/src/sdk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,9 @@ impl Sdk {
}
}
}
pub fn context_provider(&self) -> Option<impl ContextProvider> {
self.context_provider.as_ref().map(Arc::clone)
}

/// Returns a mutable reference to the `MockDashPlatformSdk` instance.
///
Expand Down

0 comments on commit c68b617

Please sign in to comment.