Skip to content

Commit

Permalink
fix(sdk): mock sdk cannot find quorum keys
Browse files Browse the repository at this point in the history
  • Loading branch information
lklimek committed Aug 16, 2024
1 parent c9c4a21 commit 100b8c2
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 46 deletions.
71 changes: 44 additions & 27 deletions packages/rs-sdk/src/mock/sdk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
//! See [MockDashPlatformSdk] for more details.
use crate::{
platform::{types::identity::IdentityRequest, DocumentQuery, Fetch, FetchMany, Query},
Error,
Error, Sdk,
};
use arc_swap::ArcSwapOption;
use dapi_grpc::platform::v0::{Proof, ResponseMetadata};
use dapi_grpc::{
mock::Mockable,
platform::v0::{self as proto},
};
use dpp::dashcore::Network;
use dpp::version::PlatformVersion;
use drive_proof_verifier::{error::ContextProviderError, FromProof, MockContextProvider};
use drive_proof_verifier::{error::ContextProviderError, ContextProvider, FromProof};
use rs_dapi_client::mock::MockError;
use rs_dapi_client::{
mock::{Key, MockDapiClient},
Expand All @@ -34,47 +35,55 @@ use super::MockResponse;
/// ## Panics
///
/// Can panic on errors.
#[derive(Debug, Clone)]
#[derive(Debug)]
pub struct MockDashPlatformSdk {
from_proof_expectations: BTreeMap<Key, Vec<u8>>,
platform_version: &'static PlatformVersion,
dapi: Arc<Mutex<MockDapiClient>>,
prove: bool,
quorum_provider: Option<Arc<MockContextProvider>>,
sdk: ArcSwapOption<Sdk>,
}

impl MockDashPlatformSdk {
pub(crate) fn new(
version: &'static PlatformVersion,
dapi: Arc<Mutex<MockDapiClient>>,
prove: bool,
) -> Self {
/// Returns true when requests should use proofs.
///
/// ## Panics
///
/// Panics when sdk is not set during initialization.
pub fn prove(&self) -> bool {
if let Some(sdk) = self.sdk.load().as_ref() {
sdk.prove()
} else {
panic!("sdk must be set when creating mock ")
}
}

/// Create new mock SDK.
///
/// ## Note
///
/// You have to call [MockDashPlatformSdk::with_sdk()] to set sdk, otherwise Mock SDK will panic.
pub(crate) fn new(version: &'static PlatformVersion, dapi: Arc<Mutex<MockDapiClient>>) -> Self {
Self {
from_proof_expectations: Default::default(),
platform_version: version,
dapi,
prove,
quorum_provider: None,
sdk: ArcSwapOption::new(None),
}
}

pub(crate) fn version<'v>(&self) -> &'v PlatformVersion {
self.platform_version
pub(crate) fn set_sdk(&mut self, sdk: Sdk) {
self.sdk.store(Some(Arc::new(sdk)));
}
/// Define a directory where files containing quorum information, like quorum public keys, are stored.
///
/// This directory will be used to load quorum information from files.
/// You can use [SdkBuilder::with_dump_dir()](crate::SdkBuilder::with_dump_dir()) to generate these files.
pub fn quorum_info_dir<P: AsRef<std::path::Path>>(&mut self, dir: P) -> &mut Self {
let mut provider = MockContextProvider::new();
provider.quorum_keys_dir(Some(dir.as_ref().to_path_buf()));
self.quorum_provider = Some(Arc::new(provider));

self
pub(crate) fn version<'v>(&self) -> &'v PlatformVersion {
self.platform_version
}

/// Load all expectations from files in a directory.
///
///
/// By default, mock expectations are loaded when Sdk is built with [SdkBuilder::build()](crate::SdkBuilder::build()).
/// This function can be used to load expectations after the Sdk is created, or use alternative location.
/// Expectation files must be prefixed with [DapiClient::DUMP_FILE_PREFIX] and
/// have `.json` extension.
pub async fn load_expectations<P: AsRef<std::path::Path>>(
Expand Down Expand Up @@ -278,7 +287,7 @@ impl MockDashPlatformSdk {
where
<<O as Fetch>::Request as TransportRequest>::Response: Default,
{
let grpc_request = query.query(self.prove).expect("query must be correct");
let grpc_request = query.query(self.prove()).expect("query must be correct");
self.expect(grpc_request, object).await?;

Ok(self)
Expand Down Expand Up @@ -332,7 +341,7 @@ impl MockDashPlatformSdk {
Response = <<O as FetchMany<K, R>>::Request as TransportRequest>::Response,
> + Sync,
{
let grpc_request = query.query(self.prove).expect("query must be correct");
let grpc_request = query.query(self.prove()).expect("query must be correct");
self.expect(grpc_request, objects).await?;

Ok(self)
Expand Down Expand Up @@ -393,7 +402,7 @@ impl MockDashPlatformSdk {
),
None => {
let version = self.version();
let provider = self.quorum_provider.as_ref()
let provider = self.context_provider()
.ok_or(ContextProviderError::InvalidQuorum(
"expectation not found and quorum info provider not initialized with sdk.mock().quorum_info_dir()".to_string()
))?;
Expand All @@ -402,11 +411,19 @@ impl MockDashPlatformSdk {
response,
Network::Regtest,
version,
provider,
&provider,
)?
}
};

Ok(data)
}
/// Return context provider implementation defined for upstreeam Sdk object.
fn context_provider(&self) -> Option<impl ContextProvider> {
if let Some(sdk) = self.sdk.load_full() {
sdk.clone().context_provider()
} else {
None
}
}
}
27 changes: 21 additions & 6 deletions packages/rs-sdk/src/sdk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -840,22 +840,37 @@ impl SdkBuilder {
None => {
let dapi =Arc::new(tokio::sync::Mutex::new( MockDapiClient::new()));
// We create mock context provider that will use the mock DAPI client to retrieve data contracts.
let context_provider = self.context_provider.unwrap_or(Box::new(MockContextProvider::new()));

Sdk {
let context_provider = self.context_provider.unwrap_or_else(||{
let mut cp=MockContextProvider::new();
if let Some(ref dump_dir) = self.dump_dir {
cp.quorum_keys_dir(Some(dump_dir.clone()));
}
Box::new(cp)
}
);
let mock_sdk = MockDashPlatformSdk::new(self.version, Arc::clone(&dapi));
let mock_sdk = Arc::new(Mutex::new(mock_sdk));
let sdk= Sdk {
network: self.network,
inner:SdkInstance::Mock {
mock:Arc::new(Mutex::new( MockDashPlatformSdk::new(self.version, Arc::clone(&dapi), self.proofs))),
mock:mock_sdk.clone(),
dapi,
version:self.version,
},
network_type: self.network_type,
dump_dir: self.dump_dir,
dump_dir: self.dump_dir.clone(),
proofs:self.proofs,
internal_cache: Default::default(),
context_provider:Some(Arc::new(context_provider)),
cancel_token: self.cancel_token,
}
};
let mut guard = mock_sdk.try_lock().expect("mock sdk is in use by another thread and connot be reconfigured");
guard.set_sdk(sdk.clone());
if let Some(ref dump_dir) = self.dump_dir {
pollster::block_on( guard.load_expectations(dump_dir))?;
};

sdk
},
#[cfg(not(feature = "mocks"))]
None => return Err(Error::Config("Mock mode is not available. Please enable `mocks` feature or provide address list.".to_string())),
Expand Down
16 changes: 3 additions & 13 deletions packages/rs-sdk/tests/fetch/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
//! This module contains [Config] struct that can be used to configure dash-platform-sdk.
//! It's mainly used for testing.
use dash_sdk::networks::NetworkType;
use dpp::platform_value::string_encoding::Encoding;
use dpp::{
dashcore::{hashes::Hash, ProTxHash},
Expand Down Expand Up @@ -211,18 +210,10 @@ impl Config {
// offline testing takes precedence over network testing
#[cfg(feature = "offline-testing")]
let sdk = {
let mut mock_sdk = dash_sdk::SdkBuilder::new_mock()
dash_sdk::SdkBuilder::new_mock()
.with_dump_dir(&dump_dir)
.build()
.expect("initialize api");

mock_sdk
.mock()
.quorum_info_dir(&dump_dir)
.load_expectations(&dump_dir)
.await
.expect("load expectations");

mock_sdk
.expect("initialize api")
};

sdk
Expand All @@ -238,7 +229,6 @@ impl Config {
Encoding::Base58,
)
.unwrap()
.into()
}

fn default_data_contract_id() -> Identifier {
Expand Down

0 comments on commit 100b8c2

Please sign in to comment.