From c04400401ab5d7d554e635f8401a7b6bb9e45621 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Wed, 18 Sep 2024 15:46:59 +0700 Subject: [PATCH 01/23] feat: get node statuses in sdk --- packages/rs-dapi-client/src/address_list.rs | 7 ++- packages/rs-dapi-client/src/dapi_client.rs | 5 ++ packages/rs-dapi-client/src/transport/grpc.rs | 9 +++ packages/rs-dpp/src/lib.rs | 1 + packages/rs-dpp/src/node/mod.rs | 1 + packages/rs-dpp/src/node/status/mod.rs | 40 +++++++++++++ packages/rs-dpp/src/node/status/v0/mod.rs | 21 +++++++ packages/rs-drive-proof-verifier/src/proof.rs | 56 ++++++++++++++++++- packages/rs-sdk/README.md | 8 +-- packages/rs-sdk/src/mock/requests.rs | 2 + packages/rs-sdk/src/platform/fetch.rs | 8 ++- packages/rs-sdk/src/platform/query.rs | 18 +++++- packages/rs-sdk/src/sdk.rs | 16 ++++++ 13 files changed, 182 insertions(+), 10 deletions(-) create mode 100644 packages/rs-dpp/src/node/mod.rs create mode 100644 packages/rs-dpp/src/node/status/mod.rs create mode 100644 packages/rs-dpp/src/node/status/v0/mod.rs diff --git a/packages/rs-dapi-client/src/address_list.rs b/packages/rs-dapi-client/src/address_list.rs index ab4e2ba0eb..49a08594a9 100644 --- a/packages/rs-dapi-client/src/address_list.rs +++ b/packages/rs-dapi-client/src/address_list.rs @@ -85,7 +85,7 @@ pub enum AddressListError { /// A structure to manage DAPI addresses to select from /// for [DapiRequest](crate::DapiRequest) execution. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct AddressList { addresses: HashSet
, base_ban_period: Duration, @@ -198,6 +198,11 @@ impl AddressList { pub fn is_empty(&self) -> bool { self.addresses.is_empty() } + + /// Getter function that returns a clone of the Hashset of addresses + pub fn addresses(&self) -> HashSet
{ + self.addresses.clone() + } } impl From<&str> for AddressList { diff --git a/packages/rs-dapi-client/src/dapi_client.rs b/packages/rs-dapi-client/src/dapi_client.rs index 8e5a3d660b..65ccda55c0 100644 --- a/packages/rs-dapi-client/src/dapi_client.rs +++ b/packages/rs-dapi-client/src/dapi_client.rs @@ -112,6 +112,11 @@ impl DapiClient { dump_dir: None, } } + + /// Return the [DapiClient] address list. + pub fn address_list(&self) -> Arc> { + Arc::clone(&self.address_list) + } } #[async_trait] diff --git a/packages/rs-dapi-client/src/transport/grpc.rs b/packages/rs-dapi-client/src/transport/grpc.rs index 43680130e8..a6f7c62514 100644 --- a/packages/rs-dapi-client/src/transport/grpc.rs +++ b/packages/rs-dapi-client/src/transport/grpc.rs @@ -386,3 +386,12 @@ impl_transport_request_grpc!( }, subscribe_to_transactions_with_proofs ); + +// rpc getStatus(GetStatusRequest) returns (GetStatusResponse); +impl_transport_request_grpc!( + platform_proto::GetStatusRequest, + platform_proto::GetStatusResponse, + PlatformGrpcClient, + RequestSettings::default(), + get_status +); diff --git a/packages/rs-dpp/src/lib.rs b/packages/rs-dpp/src/lib.rs index d2dc8b7f6e..403ad9bf07 100644 --- a/packages/rs-dpp/src/lib.rs +++ b/packages/rs-dpp/src/lib.rs @@ -42,6 +42,7 @@ pub mod block; pub mod core_subsidy; pub mod fee; pub mod nft; +pub mod node; pub mod prefunded_specialized_balance; pub mod serialization; #[cfg(any( diff --git a/packages/rs-dpp/src/node/mod.rs b/packages/rs-dpp/src/node/mod.rs new file mode 100644 index 0000000000..822c7293f8 --- /dev/null +++ b/packages/rs-dpp/src/node/mod.rs @@ -0,0 +1 @@ +pub mod status; diff --git a/packages/rs-dpp/src/node/status/mod.rs b/packages/rs-dpp/src/node/status/mod.rs new file mode 100644 index 0000000000..6861f2cdda --- /dev/null +++ b/packages/rs-dpp/src/node/status/mod.rs @@ -0,0 +1,40 @@ +pub mod v0; + +use crate::identifier::Identifier; +use crate::ProtocolError; +use bincode::{Decode, Encode}; +use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; +use serde::{Deserialize, Serialize}; +use v0::{EvonodeStatusV0, EvonodeStatusV0Getters}; + +/// Information about the status of an Evonode +#[derive( + Clone, + Debug, + PartialEq, + Serialize, + Deserialize, + Encode, + Decode, + PlatformSerialize, + PlatformDeserialize, +)] +pub enum EvonodeStatus { + V0(EvonodeStatusV0), +} + +impl EvonodeStatusV0Getters for EvonodeStatus { + /// Returns the Evonode Identifier + fn pro_tx_hash(&self) -> String { + match self { + EvonodeStatus::V0(v0) => v0.pro_tx_hash.clone(), + } + } + + /// Returns the Evonode's latest stored block height + fn latest_block_height(&self) -> u64 { + match self { + EvonodeStatus::V0(v0) => v0.latest_block_height, + } + } +} diff --git a/packages/rs-dpp/src/node/status/v0/mod.rs b/packages/rs-dpp/src/node/status/v0/mod.rs new file mode 100644 index 0000000000..d52575ade4 --- /dev/null +++ b/packages/rs-dpp/src/node/status/v0/mod.rs @@ -0,0 +1,21 @@ +use crate::identifier::Identifier; +use bincode::{Decode, Encode}; +use serde::{Deserialize, Serialize}; + +/// Information about the status of an Evonode +#[derive(Clone, Debug, PartialEq, Encode, Decode, Serialize, Deserialize)] +pub struct EvonodeStatusV0 { + /// The Identifier of the Evonode + pub pro_tx_hash: String, + /// The latest block height stored on the Evonode + pub latest_block_height: u64, +} + +/// Trait defining getters for `EvonodeStatusV0`. +pub trait EvonodeStatusV0Getters { + /// Returns the Evonode proTxHash + fn pro_tx_hash(&self) -> String; + + /// Returns the Evonode's latest stored block height + fn latest_block_height(&self) -> u64; +} diff --git a/packages/rs-drive-proof-verifier/src/proof.rs b/packages/rs-drive-proof-verifier/src/proof.rs index de46f75a1e..defab9420a 100644 --- a/packages/rs-drive-proof-verifier/src/proof.rs +++ b/packages/rs-drive-proof-verifier/src/proof.rs @@ -33,13 +33,16 @@ use dpp::dashcore::{Network, ProTxHash}; use dpp::document::{Document, DocumentV0Getters}; use dpp::identity::identities_contract_keys::IdentitiesContractKeys; use dpp::identity::Purpose; +use dpp::node::status::v0::EvonodeStatusV0; +use dpp::node::status::EvonodeStatus; use dpp::platform_value::{self}; use dpp::prelude::{DataContract, Identifier, Identity}; use dpp::serialization::PlatformDeserializable; use dpp::state_transition::proof_result::StateTransitionProofResult; use dpp::state_transition::StateTransition; -use dpp::version::PlatformVersion; +use dpp::version::{self, PlatformVersion}; use dpp::voting::votes::Vote; +use dpp::ProtocolError; use drive::drive::identity::key::fetch::{ IdentityKeysRequest, KeyKindRequestType, KeyRequestType, PurposeU8, SecurityLevelU8, }; @@ -1692,6 +1695,57 @@ impl FromProof for TotalCreditsInPla } } +impl FromProof for EvonodeStatus { + type Request = platform::GetStatusRequest; + type Response = platform::GetStatusResponse; + + fn maybe_from_proof_with_metadata<'a, I: Into, O: Into>( + request: I, + response: O, + network: Network, + platform_version: &PlatformVersion, + provider: &'a dyn ContextProvider, + ) -> Result<(Option, ResponseMetadata, Proof), Error> + where + Self: Sized + 'a, + { + let response: Self::Response = response.into(); + let version = response.version.unwrap(); + let (pro_tx_hash, latest_block_height) = match version { + platform::get_status_response::Version::V0(v0) => { + let pro_tx_hash = match v0.node { + Some(node) => node.pro_tx_hash, + None => None, + }; + let chain = match v0.chain { + Some(chain) => chain.latest_block_height, + None => { + tracing::debug!("Missing chain message from response"); + 0 + } + }; + (pro_tx_hash, chain) + } + }; + tracing::info!("{:?}", pro_tx_hash); + if pro_tx_hash.is_some() { + let evonode_status = EvonodeStatus::V0(EvonodeStatusV0 { + pro_tx_hash: Identifier::from_bytes(&pro_tx_hash.unwrap()) + .unwrap() + .to_string(platform_value::string_encoding::Encoding::Base58), + latest_block_height, + }); + Ok(( + Some(evonode_status), + ResponseMetadata::default(), + Proof::default(), + )) + } else { + Ok((None, ResponseMetadata::default(), Proof::default())) + } + } +} + /// Convert u32, if 0 return None, otherwise return Some(u16). /// Errors when value is out of range. fn u32_to_u16_opt(i: u32) -> Result, Error> { diff --git a/packages/rs-sdk/README.md b/packages/rs-sdk/README.md index 4d543c5857..c14b9bbd59 100644 --- a/packages/rs-sdk/README.md +++ b/packages/rs-sdk/README.md @@ -97,9 +97,9 @@ Run the offline test using the following command: cargo test -p dash-platform-sdk ``` -## Implementing Fetch and FetchAny on new objects +## Implementing Fetch and FetchMany on new objects -How to implement `Fetch` and `FetchAny` trait on new object types (`Object`). +How to implement `Fetch` and `FetchMany` trait on new object types (`Object`). It's basically copy-paste and tweaking of existing implementation for another object type. @@ -114,7 +114,7 @@ Definitions: Checklist: 1. [ ] Ensure protobuf messages are defined in `packages/dapi-grpc/protos/platform/v0/platform.proto` and generated - correctly in `packages/dapi-grpc/src/platform/proto/org.dash.platform.dapi.v0.rs`. + correctly in `packages/dapi-grpc/src/platform/client/org.dash.platform.dapi.v0.rs`. 2. [ ] In `packages/dapi-grpc/build.rs`, add `Request` to `VERSIONED_REQUESTS` and response `Response` to `VERSIONED_RESPONSES`. This should add derive of `VersionedGrpcMessage` (and some more) in `org.dash.platform.dapi.v0.rs`. 3. [ ] Link request and response type to dapi-client by adding appropriate invocation of `impl_transport_request_grpc!` macro @@ -123,7 +123,7 @@ in `packages/rs-dapi-client/src/transport/grpc.rs`. used internally. If you intend to implement `FetchMany`, you should define type returned by `fetch_many()` using `RetrievedObjects` - that will store collection of returned objects, indexd by some key. + that will store collection of returned objects, indexed by some key. 5. [ ] Implement `FromProof` trait for the `Object` (or type defined in `types.rs`) in `packages/rs-drive-proof-verifier/src/proof.rs`. 6. [ ] Implement `Query` trait for the `Request` in `packages/rs-sdk/src/platform/query.rs`. 7. [ ] Implement `Fetch` trait for the `Object` (or type defined in `types.rs`), with inner type Request = `Request`, diff --git a/packages/rs-sdk/src/mock/requests.rs b/packages/rs-sdk/src/mock/requests.rs index 6cb4dde30d..31e10ff6c5 100644 --- a/packages/rs-sdk/src/mock/requests.rs +++ b/packages/rs-sdk/src/mock/requests.rs @@ -6,6 +6,7 @@ use dpp::{ document::{serialization_traits::DocumentCborMethodsV0, Document}, identifier::Identifier, identity::IdentityPublicKey, + node::status::EvonodeStatus, platform_serialization::{platform_encode_to_vec, platform_versioned_decode_from_slice}, prelude::{DataContract, Identity}, serialization::{ @@ -229,3 +230,4 @@ impl_mock_response!(VotePollsGroupedByTimestamp); impl_mock_response!(PrefundedSpecializedBalance); impl_mock_response!(TotalCreditsInPlatform); impl_mock_response!(ElementFetchRequestItem); +impl_mock_response!(EvonodeStatus); diff --git a/packages/rs-sdk/src/platform/fetch.rs b/packages/rs-sdk/src/platform/fetch.rs index 109140bdb7..039b0b3cfd 100644 --- a/packages/rs-sdk/src/platform/fetch.rs +++ b/packages/rs-sdk/src/platform/fetch.rs @@ -13,8 +13,8 @@ use crate::{error::Error, platform::query::Query, Sdk}; 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, - prelude::Identity, + block::extended_epoch_info::ExtendedEpochInfo, document::Document, node::status::EvonodeStatus, + platform_value::Identifier, prelude::Identity, }; use drive_proof_verifier::FromProof; use rs_dapi_client::{transport::TransportRequest, DapiRequest, RequestSettings}; @@ -282,3 +282,7 @@ impl Fetch for drive_proof_verifier::types::PrefundedSpecializedBalance { impl Fetch for Vote { type Request = platform_proto::GetContestedResourceIdentityVotesRequest; } + +impl Fetch for EvonodeStatus { + type Request = platform_proto::GetStatusRequest; +} diff --git a/packages/rs-sdk/src/platform/query.rs b/packages/rs-sdk/src/platform/query.rs index 6e7de72013..e6778aeba9 100644 --- a/packages/rs-sdk/src/platform/query.rs +++ b/packages/rs-sdk/src/platform/query.rs @@ -7,6 +7,7 @@ use dapi_grpc::platform::v0::get_contested_resource_identity_votes_request::GetC use dapi_grpc::platform::v0::get_contested_resource_voters_for_identity_request::GetContestedResourceVotersForIdentityRequestV0; use dapi_grpc::platform::v0::get_contested_resources_request::GetContestedResourcesRequestV0; use dapi_grpc::platform::v0::get_path_elements_request::GetPathElementsRequestV0; +use dapi_grpc::platform::v0::get_status_request::GetStatusRequestV0; use dapi_grpc::platform::v0::get_total_credits_in_platform_request::GetTotalCreditsInPlatformRequestV0; use dapi_grpc::platform::v0::{ self as proto, get_identity_keys_request, get_identity_keys_request::GetIdentityKeysRequestV0, @@ -17,10 +18,11 @@ use dapi_grpc::platform::v0::{ GetProtocolVersionUpgradeVoteStatusRequest, GetTotalCreditsInPlatformRequest, KeyRequestType, }; use dapi_grpc::platform::v0::{ - GetContestedResourceIdentityVotesRequest, GetPrefundedSpecializedBalanceRequest, - GetVotePollsByEndDateRequest, + get_status_request, GetContestedResourceIdentityVotesRequest, + GetPrefundedSpecializedBalanceRequest, GetStatusRequest, GetVotePollsByEndDateRequest, }; use dashcore_rpc::dashcore::{hashes::Hash, ProTxHash}; +use dpp::node::status::EvonodeStatus; use dpp::version::PlatformVersionError; use dpp::{block::epoch::EpochIndex, prelude::Identifier}; use drive::query::contested_resource_votes_given_by_identity_query::ContestedResourceVotesGivenByIdentityQuery; @@ -583,3 +585,15 @@ impl Query for NoParamQuery { Ok(request) } } + +impl Query for () { + fn query(self, prove: bool) -> Result { + // ignore proof + + let request: GetStatusRequest = GetStatusRequest { + version: Some(get_status_request::Version::V0(GetStatusRequestV0 {})), + }; + + Ok(request) + } +} diff --git a/packages/rs-sdk/src/sdk.rs b/packages/rs-sdk/src/sdk.rs index fb8bd7fed8..4f94ef6332 100644 --- a/packages/rs-sdk/src/sdk.rs +++ b/packages/rs-sdk/src/sdk.rs @@ -507,6 +507,22 @@ impl Sdk { pub fn shutdown(&self) { self.cancel_token.cancel(); } + + /// Return the [DapiClient] address list + pub fn address_list(&self) -> Result { + match &self.inner { + SdkInstance::Dapi { dapi, version: _ } => { + let address_list_arc = dapi.address_list(); + let address_list_lock = address_list_arc + .read() + .map_err(|e| format!("Failed to read address list: {e}"))?; + Ok(address_list_lock.clone()) + } + SdkInstance::Mock { .. } => { + todo!(); + } + } + } } #[async_trait::async_trait] From 94235ee563a3dde3accfedba64dc688515ea420f Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Wed, 18 Sep 2024 20:04:38 +0700 Subject: [PATCH 02/23] fixes --- packages/rs-dpp/src/node/status/mod.rs | 1 - packages/rs-dpp/src/node/status/v0/mod.rs | 1 - packages/rs-sdk/src/sdk.rs | 3 --- 3 files changed, 5 deletions(-) diff --git a/packages/rs-dpp/src/node/status/mod.rs b/packages/rs-dpp/src/node/status/mod.rs index 6861f2cdda..20d75a4b88 100644 --- a/packages/rs-dpp/src/node/status/mod.rs +++ b/packages/rs-dpp/src/node/status/mod.rs @@ -1,6 +1,5 @@ pub mod v0; -use crate::identifier::Identifier; use crate::ProtocolError; use bincode::{Decode, Encode}; use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; diff --git a/packages/rs-dpp/src/node/status/v0/mod.rs b/packages/rs-dpp/src/node/status/v0/mod.rs index d52575ade4..7183cd373b 100644 --- a/packages/rs-dpp/src/node/status/v0/mod.rs +++ b/packages/rs-dpp/src/node/status/v0/mod.rs @@ -1,4 +1,3 @@ -use crate::identifier::Identifier; use bincode::{Decode, Encode}; use serde::{Deserialize, Serialize}; diff --git a/packages/rs-sdk/src/sdk.rs b/packages/rs-sdk/src/sdk.rs index 4f94ef6332..ba35c1c022 100644 --- a/packages/rs-sdk/src/sdk.rs +++ b/packages/rs-sdk/src/sdk.rs @@ -781,9 +781,6 @@ impl SdkBuilder { if sdk.context_provider.is_none() { #[cfg(feature = "mocks")] if !self.core_ip.is_empty() { - tracing::warn!("ContextProvider not set; mocking with Dash Core. \ - Please provide your own ContextProvider with SdkBuilder::with_context_provider()."); - let mut context_provider = GrpcContextProvider::new(None, &self.core_ip, self.core_port, &self.core_user, &self.core_password, self.data_contract_cache_size, self.quorum_public_keys_cache_size)?; From 45ebe6c95073c2ba8786d1366dc4cb17ccb5452b Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Wed, 18 Sep 2024 20:28:42 +0700 Subject: [PATCH 03/23] error handling --- packages/rs-drive-proof-verifier/src/proof.rs | 44 ++++++++++++------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/packages/rs-drive-proof-verifier/src/proof.rs b/packages/rs-drive-proof-verifier/src/proof.rs index defab9420a..c42ff041d0 100644 --- a/packages/rs-drive-proof-verifier/src/proof.rs +++ b/packages/rs-drive-proof-verifier/src/proof.rs @@ -1710,7 +1710,12 @@ impl FromProof for EvonodeStatus { Self: Sized + 'a, { let response: Self::Response = response.into(); - let version = response.version.unwrap(); + let version = match response.version { + Some(version) => version, + None => { + return Err(ProtocolError::Generic("No version in the response".to_string()).into()) + } + }; let (pro_tx_hash, latest_block_height) = match version { platform::get_status_response::Version::V0(v0) => { let pro_tx_hash = match v0.node { @@ -1727,21 +1732,28 @@ impl FromProof for EvonodeStatus { (pro_tx_hash, chain) } }; - tracing::info!("{:?}", pro_tx_hash); - if pro_tx_hash.is_some() { - let evonode_status = EvonodeStatus::V0(EvonodeStatusV0 { - pro_tx_hash: Identifier::from_bytes(&pro_tx_hash.unwrap()) - .unwrap() - .to_string(platform_value::string_encoding::Encoding::Base58), - latest_block_height, - }); - Ok(( - Some(evonode_status), - ResponseMetadata::default(), - Proof::default(), - )) - } else { - Ok((None, ResponseMetadata::default(), Proof::default())) + match pro_tx_hash { + Some(hash) => match Identifier::from_bytes(&hash) { + Ok(identifier) => { + let evonode_status = EvonodeStatus::V0(EvonodeStatusV0 { + pro_tx_hash: identifier + .to_string(platform_value::string_encoding::Encoding::Base58), + latest_block_height, + }); + + Ok(( + Some(evonode_status), + ResponseMetadata::default(), + Proof::default(), + )) + } + Err(e) => Err(ProtocolError::Generic(format!( + "Failed to convert pro_tx_hash to Identifier: {}", + e + )) + .into()), + }, + None => Ok((None, ResponseMetadata::default(), Proof::default())), } } } From 6d1af4c9753dfe153f0233fae154de2141af785e Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Thu, 19 Sep 2024 17:18:09 +0700 Subject: [PATCH 04/23] return references instead of clones --- packages/rs-dapi-client/src/address_list.rs | 6 +++--- packages/rs-dapi-client/src/dapi_client.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/rs-dapi-client/src/address_list.rs b/packages/rs-dapi-client/src/address_list.rs index 49a08594a9..8282e6893f 100644 --- a/packages/rs-dapi-client/src/address_list.rs +++ b/packages/rs-dapi-client/src/address_list.rs @@ -199,9 +199,9 @@ impl AddressList { self.addresses.is_empty() } - /// Getter function that returns a clone of the Hashset of addresses - pub fn addresses(&self) -> HashSet
{ - self.addresses.clone() + /// Getter function that returns a reference to the Hashset of addresses + pub fn addresses(&self) -> &HashSet
{ + &self.addresses } } diff --git a/packages/rs-dapi-client/src/dapi_client.rs b/packages/rs-dapi-client/src/dapi_client.rs index 65ccda55c0..17748ab2b0 100644 --- a/packages/rs-dapi-client/src/dapi_client.rs +++ b/packages/rs-dapi-client/src/dapi_client.rs @@ -114,8 +114,8 @@ impl DapiClient { } /// Return the [DapiClient] address list. - pub fn address_list(&self) -> Arc> { - Arc::clone(&self.address_list) + pub fn address_list(&self) -> &Arc> { + &self.address_list } } From 7f098fc94a1a7825ba39365a1bfa0fcf464d1d27 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Thu, 19 Sep 2024 21:46:48 +0700 Subject: [PATCH 05/23] fix --- packages/rs-drive-proof-verifier/src/proof.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/rs-drive-proof-verifier/src/proof.rs b/packages/rs-drive-proof-verifier/src/proof.rs index c42ff041d0..6058861b16 100644 --- a/packages/rs-drive-proof-verifier/src/proof.rs +++ b/packages/rs-drive-proof-verifier/src/proof.rs @@ -1700,11 +1700,11 @@ impl FromProof for EvonodeStatus { type Response = platform::GetStatusResponse; fn maybe_from_proof_with_metadata<'a, I: Into, O: Into>( - request: I, + _request: I, response: O, - network: Network, - platform_version: &PlatformVersion, - provider: &'a dyn ContextProvider, + _network: Network, + _platform_version: &PlatformVersion, + _provider: &'a dyn ContextProvider, ) -> Result<(Option, ResponseMetadata, Proof), Error> where Self: Sized + 'a, From e4099569d02f13661f3e947fefd4e8fc38be621c Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Thu, 26 Sep 2024 15:15:21 +0200 Subject: [PATCH 06/23] refactor --- Cargo.lock | 1 + packages/rs-dapi-client/src/lib.rs | 1 + packages/rs-dpp/src/lib.rs | 1 - packages/rs-dpp/src/node/mod.rs | 1 - packages/rs-dpp/src/node/status/mod.rs | 39 -------- packages/rs-dpp/src/node/status/v0/mod.rs | 20 ----- packages/rs-drive-proof-verifier/src/proof.rs | 72 +-------------- packages/rs-drive-proof-verifier/src/types.rs | 48 +++++++++- .../rs-drive-proof-verifier/src/unproved.rs | 22 ++++- packages/rs-sdk/Cargo.toml | 4 +- packages/rs-sdk/src/lib.rs | 4 +- packages/rs-sdk/src/mock.rs | 3 +- packages/rs-sdk/src/mock/requests.rs | 11 +-- packages/rs-sdk/src/platform.rs | 1 + packages/rs-sdk/src/platform/fetch.rs | 8 +- .../rs-sdk/src/platform/fetch_unproved.rs | 76 +++++++++------- packages/rs-sdk/src/platform/query.rs | 3 +- packages/rs-sdk/src/platform/types.rs | 1 + packages/rs-sdk/src/platform/types/evonode.rs | 90 +++++++++++++++++++ 19 files changed, 226 insertions(+), 180 deletions(-) delete mode 100644 packages/rs-dpp/src/node/mod.rs delete mode 100644 packages/rs-dpp/src/node/status/mod.rs delete mode 100644 packages/rs-dpp/src/node/status/v0/mod.rs create mode 100644 packages/rs-sdk/src/platform/types/evonode.rs diff --git a/Cargo.lock b/Cargo.lock index ad59187b72..64a7a07128 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1213,6 +1213,7 @@ dependencies = [ "arc-swap", "async-trait", "base64 0.22.1", + "bincode", "bip37-bloom-filter", "chrono", "ciborium", diff --git a/packages/rs-dapi-client/src/lib.rs b/packages/rs-dapi-client/src/lib.rs index e4f5836e29..976537097e 100644 --- a/packages/rs-dapi-client/src/lib.rs +++ b/packages/rs-dapi-client/src/lib.rs @@ -14,6 +14,7 @@ pub mod transport; pub use address_list::Address; pub use address_list::AddressList; +pub use connection_pool::ConnectionPool; pub use dapi_client::DapiRequestExecutor; pub use dapi_client::{DapiClient, DapiClientError}; use dapi_grpc::mock::Mockable; diff --git a/packages/rs-dpp/src/lib.rs b/packages/rs-dpp/src/lib.rs index 082008042b..6dd0312fc2 100644 --- a/packages/rs-dpp/src/lib.rs +++ b/packages/rs-dpp/src/lib.rs @@ -42,7 +42,6 @@ pub mod block; pub mod core_subsidy; pub mod fee; pub mod nft; -pub mod node; pub mod prefunded_specialized_balance; pub mod serialization; #[cfg(any( diff --git a/packages/rs-dpp/src/node/mod.rs b/packages/rs-dpp/src/node/mod.rs deleted file mode 100644 index 822c7293f8..0000000000 --- a/packages/rs-dpp/src/node/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod status; diff --git a/packages/rs-dpp/src/node/status/mod.rs b/packages/rs-dpp/src/node/status/mod.rs deleted file mode 100644 index 20d75a4b88..0000000000 --- a/packages/rs-dpp/src/node/status/mod.rs +++ /dev/null @@ -1,39 +0,0 @@ -pub mod v0; - -use crate::ProtocolError; -use bincode::{Decode, Encode}; -use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; -use serde::{Deserialize, Serialize}; -use v0::{EvonodeStatusV0, EvonodeStatusV0Getters}; - -/// Information about the status of an Evonode -#[derive( - Clone, - Debug, - PartialEq, - Serialize, - Deserialize, - Encode, - Decode, - PlatformSerialize, - PlatformDeserialize, -)] -pub enum EvonodeStatus { - V0(EvonodeStatusV0), -} - -impl EvonodeStatusV0Getters for EvonodeStatus { - /// Returns the Evonode Identifier - fn pro_tx_hash(&self) -> String { - match self { - EvonodeStatus::V0(v0) => v0.pro_tx_hash.clone(), - } - } - - /// Returns the Evonode's latest stored block height - fn latest_block_height(&self) -> u64 { - match self { - EvonodeStatus::V0(v0) => v0.latest_block_height, - } - } -} diff --git a/packages/rs-dpp/src/node/status/v0/mod.rs b/packages/rs-dpp/src/node/status/v0/mod.rs deleted file mode 100644 index 7183cd373b..0000000000 --- a/packages/rs-dpp/src/node/status/v0/mod.rs +++ /dev/null @@ -1,20 +0,0 @@ -use bincode::{Decode, Encode}; -use serde::{Deserialize, Serialize}; - -/// Information about the status of an Evonode -#[derive(Clone, Debug, PartialEq, Encode, Decode, Serialize, Deserialize)] -pub struct EvonodeStatusV0 { - /// The Identifier of the Evonode - pub pro_tx_hash: String, - /// The latest block height stored on the Evonode - pub latest_block_height: u64, -} - -/// Trait defining getters for `EvonodeStatusV0`. -pub trait EvonodeStatusV0Getters { - /// Returns the Evonode proTxHash - fn pro_tx_hash(&self) -> String; - - /// Returns the Evonode's latest stored block height - fn latest_block_height(&self) -> u64; -} diff --git a/packages/rs-drive-proof-verifier/src/proof.rs b/packages/rs-drive-proof-verifier/src/proof.rs index 8183994645..89fef81360 100644 --- a/packages/rs-drive-proof-verifier/src/proof.rs +++ b/packages/rs-drive-proof-verifier/src/proof.rs @@ -25,8 +25,6 @@ use dpp::dashcore::{Network, ProTxHash}; use dpp::document::{Document, DocumentV0Getters}; use dpp::identity::identities_contract_keys::IdentitiesContractKeys; use dpp::identity::Purpose; -use dpp::node::status::v0::EvonodeStatusV0; -use dpp::node::status::EvonodeStatus; use dpp::platform_value::{self}; use dpp::prelude::{DataContract, Identifier, Identity}; use dpp::serialization::PlatformDeserializable; @@ -34,7 +32,6 @@ use dpp::state_transition::proof_result::StateTransitionProofResult; use dpp::state_transition::StateTransition; use dpp::version::PlatformVersion; use dpp::voting::votes::Vote; -use dpp::ProtocolError; use drive::drive::identity::key::fetch::{ IdentityKeysRequest, KeyKindRequestType, KeyRequestType, PurposeU8, SecurityLevelU8, }; @@ -83,7 +80,7 @@ pub trait FromProof { /// /// * `Ok(Some(object, metadata))` when the requested object was found in the proof. /// * `Ok(None)` when the requested object was not found in the proof; this can be interpreted as proof of non-existence. - /// For collections, returns Ok(None) if none of the requested objects were found. + /// For collections, returns Ok(None) if none of the requested objects were found. /// * `Err(Error)` when either the provided data is invalid or proof validation failed. fn maybe_from_proof<'a, I: Into, O: Into>( request: I, @@ -113,7 +110,7 @@ pub trait FromProof { /// /// * `Ok(Some((object, metadata)))` when the requested object was found in the proof. /// * `Ok(None)` when the requested object was not found in the proof; this can be interpreted as proof of non-existence. - /// For collections, returns Ok(None) if none of the requested objects were found. + /// For collections, returns Ok(None) if none of the requested objects were found. /// * `Err(Error)` when either the provided data is invalid or proof validation failed. fn maybe_from_proof_with_metadata<'a, I: Into, O: Into>( request: I, @@ -1719,71 +1716,6 @@ impl FromProof for TotalCreditsInPla )) } } - -impl FromProof for EvonodeStatus { - type Request = platform::GetStatusRequest; - type Response = platform::GetStatusResponse; - - fn maybe_from_proof_with_metadata<'a, I: Into, O: Into>( - _request: I, - response: O, - _network: Network, - _platform_version: &PlatformVersion, - _provider: &'a dyn ContextProvider, - ) -> Result<(Option, ResponseMetadata, Proof), Error> - where - Self: Sized + 'a, - { - let response: Self::Response = response.into(); - let version = match response.version { - Some(version) => version, - None => { - return Err(ProtocolError::Generic("No version in the response".to_string()).into()) - } - }; - let (pro_tx_hash, latest_block_height) = match version { - platform::get_status_response::Version::V0(v0) => { - let pro_tx_hash = match v0.node { - Some(node) => node.pro_tx_hash, - None => None, - }; - let chain = match v0.chain { - Some(chain) => chain.latest_block_height, - None => { - tracing::debug!("Missing chain message from response"); - 0 - } - }; - (pro_tx_hash, chain) - } - }; - - match pro_tx_hash { - Some(hash) => match Identifier::from_bytes(&hash) { - Ok(identifier) => { - let evonode_status = EvonodeStatus::V0(EvonodeStatusV0 { - pro_tx_hash: identifier - .to_string(platform_value::string_encoding::Encoding::Base58), - latest_block_height, - }); - - Ok(( - Some(evonode_status), - ResponseMetadata::default(), - Proof::default(), - )) - } - Err(e) => Err(ProtocolError::Generic(format!( - "Failed to convert pro_tx_hash to Identifier: {}", - e - )) - .into()), - }, - None => Ok((None, ResponseMetadata::default(), Proof::default())), - } - } -} - impl FromProof for ProposerBlockCounts { type Request = platform::GetEvonodesProposedEpochBlocksByIdsRequest; type Response = platform::GetEvonodesProposedEpochBlocksResponse; diff --git a/packages/rs-drive-proof-verifier/src/types.rs b/packages/rs-drive-proof-verifier/src/types.rs index d28ba69302..c1fa3cbddb 100644 --- a/packages/rs-drive-proof-verifier/src/types.rs +++ b/packages/rs-drive-proof-verifier/src/types.rs @@ -5,6 +5,7 @@ //! In this case, the [FromProof](crate::FromProof) trait is implemented for dedicated object type //! defined in this module. +use dapi_grpc::platform::v0::GetStatusResponse; use dpp::data_contract::document_type::DocumentType; use dpp::fee::Credits; use dpp::platform_value::Value; @@ -25,13 +26,15 @@ use dpp::{ util::deserializer::ProtocolVersion, }; use drive::grovedb::Element; +use hex::ToHex; use std::collections::{BTreeMap, BTreeSet}; +use crate::Error; use dpp::block::block_info::BlockInfo; use dpp::core_types::validator_set::ValidatorSet; -use dpp::dashcore::QuorumHash; use dpp::voting::vote_info_storage::contested_document_vote_poll_winner_info::ContestedDocumentVotePollWinnerInfo; use drive::grovedb::query_result_type::Path; + #[cfg(feature = "mocks")] use { bincode::{Decode, Encode}, @@ -614,3 +617,46 @@ pub struct ProposerBlockCountByRange(pub u64); #[derive(Debug)] #[cfg_attr(feature = "mocks", derive(serde::Serialize, serde::Deserialize))] pub struct ProposerBlockCountById(pub u64); + +#[derive(Debug, Clone)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] +/// Status of a network node +pub struct EvonodeStatus { + /// The Identifier of the Evonode + pub pro_tx_hash: String, + /// The latest block height stored on the Evonode + pub latest_block_height: u64, +} + +impl TryFrom for EvonodeStatus { + type Error = Error; + fn try_from(response: GetStatusResponse) -> Result { + use dapi_grpc::platform::v0::get_status_response::Version; + match response.version { + Some(Version::V0(v0)) => { + let node = v0.node.ok_or(Error::ProtocolError { + error: "missing node information".to_string(), + })?; + + let chain = v0.chain.ok_or(Error::ProtocolError { + error: "missing chain information".to_string(), + })?; + + Ok(Self { + pro_tx_hash: node + .pro_tx_hash + .ok_or(Error::ProtocolError { + error: "Missing pro_tx_hash".to_string(), + })? + .encode_hex(), + latest_block_height: chain.latest_block_height, + }) + } + None => Err(Error::EmptyVersion), + } + } +} diff --git a/packages/rs-drive-proof-verifier/src/unproved.rs b/packages/rs-drive-proof-verifier/src/unproved.rs index c2f30c6452..7207ace006 100644 --- a/packages/rs-drive-proof-verifier/src/unproved.rs +++ b/packages/rs-drive-proof-verifier/src/unproved.rs @@ -1,7 +1,8 @@ -use crate::types::CurrentQuorumsInfo; +use crate::types::{CurrentQuorumsInfo, EvonodeStatus}; use crate::Error; use dapi_grpc::platform::v0::ResponseMetadata; use dapi_grpc::platform::v0::{self as platform}; +use dapi_grpc::tonic::async_trait; use dpp::bls_signatures::PublicKey as BlsPublicKey; use dpp::core_types::validator::v0::ValidatorV0; use dpp::core_types::validator_set::v0::ValidatorSetV0; @@ -273,3 +274,22 @@ impl FromUnproved for CurrentQuorumsInfo Ok((Some(info), metadata)) } } + +#[async_trait] +impl FromUnproved for EvonodeStatus { + type Request = platform::GetStatusRequest; + type Response = platform::GetStatusResponse; + + fn maybe_from_unproved_with_metadata, O: Into>( + _request: I, + response: O, + _network: Network, + _platform_version: &PlatformVersion, + ) -> Result<(Option, ResponseMetadata), Error> + where + Self: Sized, + { + let status = Self::try_from(response.into())?; + Ok((Some(status), Default::default())) + } +} diff --git a/packages/rs-sdk/Cargo.toml b/packages/rs-sdk/Cargo.toml index 8934df17dc..18402c6297 100644 --- a/packages/rs-sdk/Cargo.toml +++ b/packages/rs-sdk/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] arc-swap = { version = "1.7.1" } +bincode = { version = "2.0.0-rc.3", features = ["serde"], optional = true } dpp = { path = "../rs-dpp", default-features = false, features = [ "dash-sdk-features", ] } @@ -26,7 +27,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"} +hex = { version = "0.4.3" } dotenvy = { version = "0.15.7", optional = true } envy = { version = "0.4.2", optional = true } futures = { version = "0.3.30" } @@ -58,6 +59,7 @@ test-case = { version = "3.3.1" } default = ["mocks", "offline-testing"] mocks = [ + "dep:bincode", "dep:serde", "dep:serde_json", "rs-dapi-client/mocks", diff --git a/packages/rs-sdk/src/lib.rs b/packages/rs-sdk/src/lib.rs index e09eb4d3bb..d165a211a5 100644 --- a/packages/rs-sdk/src/lib.rs +++ b/packages/rs-sdk/src/lib.rs @@ -32,8 +32,8 @@ //! //! 1. [`Identifier`](crate::platform::Identifier) - fetches an object by its identifier //! 2. [`DocumentQuery`](crate::platform::DocumentQuery) - fetches documents based on search conditions; see -//! [query syntax documentation](https://docs.dash.org/projects/platform/en/stable/docs/reference/query-syntax.html) -//! for more details. +//! [query syntax documentation](https://docs.dash.org/projects/platform/en/stable/docs/reference/query-syntax.html) +//! for more details. //! 3. [`DriveQuery`](crate::platform::DriveDocumentQuery) - can be used to build more complex queries //! //! ## Testability diff --git a/packages/rs-sdk/src/mock.rs b/packages/rs-sdk/src/mock.rs index b3f1b69c63..159aa73eba 100644 --- a/packages/rs-sdk/src/mock.rs +++ b/packages/rs-sdk/src/mock.rs @@ -32,11 +32,12 @@ pub mod sdk; // Otherwise dapi_grpc_macros::Mockable fails. // TODO: move Mockable to some crate that can be shared between dapi-grpc, rs-dapi-client, and dash-sdk pub use dapi_grpc::mock::Mockable; - // MockResponse is needed even if mocks feature is disabled - it just does nothing. #[cfg(not(feature = "mocks"))] pub use noop::MockResponse; #[cfg(feature = "mocks")] pub use requests::MockResponse; #[cfg(feature = "mocks")] +pub(crate) use requests::BINCODE_CONFIG; +#[cfg(feature = "mocks")] pub use sdk::MockDashPlatformSdk; diff --git a/packages/rs-sdk/src/mock/requests.rs b/packages/rs-sdk/src/mock/requests.rs index 20f23d8c85..1996ae9373 100644 --- a/packages/rs-sdk/src/mock/requests.rs +++ b/packages/rs-sdk/src/mock/requests.rs @@ -6,7 +6,6 @@ use dpp::{ document::{serialization_traits::DocumentCborMethodsV0, Document}, identifier::Identifier, identity::IdentityPublicKey, - node::status::EvonodeStatus, platform_serialization::{platform_encode_to_vec, platform_versioned_decode_from_slice}, prelude::{DataContract, Identity}, serialization::{ @@ -16,13 +15,14 @@ use dpp::{ voting::votes::{resource_vote::ResourceVote, Vote}, }; use drive_proof_verifier::types::{ - Contenders, ContestedResources, ElementFetchRequestItem, IdentityBalanceAndRevision, - MasternodeProtocolVote, PrefundedSpecializedBalance, ProposerBlockCounts, - RetrievedIntegerValue, TotalCreditsInPlatform, VotePollsGroupedByTimestamp, Voters, + Contenders, ContestedResources, CurrentQuorumsInfo, ElementFetchRequestItem, EvonodeStatus, + IdentityBalanceAndRevision, MasternodeProtocolVote, PrefundedSpecializedBalance, + ProposerBlockCounts, RetrievedIntegerValue, TotalCreditsInPlatform, + VotePollsGroupedByTimestamp, Voters, }; use std::collections::BTreeMap; -static BINCODE_CONFIG: bincode::config::Configuration = bincode::config::standard(); +pub(crate) static BINCODE_CONFIG: bincode::config::Configuration = bincode::config::standard(); /// Trait implemented by objects that can be used in mock expectation responses. /// @@ -245,3 +245,4 @@ impl_mock_response!(PrefundedSpecializedBalance); impl_mock_response!(TotalCreditsInPlatform); impl_mock_response!(ElementFetchRequestItem); impl_mock_response!(EvonodeStatus); +impl_mock_response!(CurrentQuorumsInfo); diff --git a/packages/rs-sdk/src/platform.rs b/packages/rs-sdk/src/platform.rs index aab3d2153a..a4c0fb83f4 100644 --- a/packages/rs-sdk/src/platform.rs +++ b/packages/rs-sdk/src/platform.rs @@ -32,5 +32,6 @@ pub use { document_query::DocumentQuery, fetch::Fetch, fetch_many::FetchMany, + fetch_unproved::FetchUnproved, query::{LimitQuery, Query, QueryStartInfo, DEFAULT_EPOCH_QUERY_LIMIT}, }; diff --git a/packages/rs-sdk/src/platform/fetch.rs b/packages/rs-sdk/src/platform/fetch.rs index 039b0b3cfd..109140bdb7 100644 --- a/packages/rs-sdk/src/platform/fetch.rs +++ b/packages/rs-sdk/src/platform/fetch.rs @@ -13,8 +13,8 @@ use crate::{error::Error, platform::query::Query, Sdk}; 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, node::status::EvonodeStatus, - platform_value::Identifier, prelude::Identity, + block::extended_epoch_info::ExtendedEpochInfo, document::Document, platform_value::Identifier, + prelude::Identity, }; use drive_proof_verifier::FromProof; use rs_dapi_client::{transport::TransportRequest, DapiRequest, RequestSettings}; @@ -282,7 +282,3 @@ impl Fetch for drive_proof_verifier::types::PrefundedSpecializedBalance { impl Fetch for Vote { type Request = platform_proto::GetContestedResourceIdentityVotesRequest; } - -impl Fetch for EvonodeStatus { - type Request = platform_proto::GetStatusRequest; -} diff --git a/packages/rs-sdk/src/platform/fetch_unproved.rs b/packages/rs-sdk/src/platform/fetch_unproved.rs index d25fc86b50..74ead3e875 100644 --- a/packages/rs-sdk/src/platform/fetch_unproved.rs +++ b/packages/rs-sdk/src/platform/fetch_unproved.rs @@ -1,16 +1,18 @@ use crate::error::Error; -use crate::platform::proto; +use crate::mock::MockResponse; use crate::Sdk; -use dapi_grpc::platform::v0::get_current_quorums_info_request::GetCurrentQuorumsInfoRequestV0; -use dapi_grpc::platform::v0::{self as platform_proto}; +use dapi_grpc::platform::v0::{self as platform_proto, ResponseMetadata}; +use drive_proof_verifier::types::EvonodeStatus; use drive_proof_verifier::unproved::FromUnproved; use rs_dapi_client::{transport::TransportRequest, DapiRequest, RequestSettings}; use std::fmt::Debug; +use super::Query; + #[async_trait::async_trait] pub trait FetchUnproved where - Self: Sized + Debug, + Self: Sized + Debug + MockResponse, { /// Type of request used to fetch data from Platform. type Request: TransportRequest; @@ -25,8 +27,20 @@ where /// * `Ok(Some(Self))` when object is found. /// * `Ok(None)` when object is not found. /// * [`Err(Error)`](Error) when an error occurs. - async fn fetch_unproved(sdk: &Sdk) -> Result, Error> { - Self::fetch_unproved_with_settings(sdk, RequestSettings::default()).await + async fn fetch_unproved::Request>>( + sdk: &Sdk, + query: Q, + ) -> Result, Error> + where + Self: FromUnproved< + ::Request, + Request = ::Request, + Response = <::Request as TransportRequest>::Response, + >, + { + let (obj, _mtd) = + Self::fetch_unproved_with_settings(sdk, query, RequestSettings::default()).await?; + Ok(obj) } /// Fetch unproved data from the Platform with custom settings. @@ -40,36 +54,36 @@ where /// * `Ok(Some(Self))` when object is found. /// * `Ok(None)` when object is not found. /// * [`Err(Error)`](Error) when an error occurs. - async fn fetch_unproved_with_settings( + async fn fetch_unproved_with_settings::Request>>( sdk: &Sdk, + query: Q, settings: RequestSettings, - ) -> Result, Error>; -} - -#[async_trait::async_trait] -impl FetchUnproved for drive_proof_verifier::types::CurrentQuorumsInfo { - type Request = platform_proto::GetCurrentQuorumsInfoRequest; - - async fn fetch_unproved_with_settings( - sdk: &Sdk, - settings: RequestSettings, - ) -> Result, Error> { - // Create the request from the query - let request = Self::Request { - version: Some(proto::get_current_quorums_info_request::Version::V0( - GetCurrentQuorumsInfoRequestV0 {}, - )), - }; + ) -> Result<(Option, ResponseMetadata), Error> + where + Self: FromUnproved< + ::Request, + Request = ::Request, + Response = <::Request as TransportRequest>::Response, + >, + { + // Default implementation + let request: ::Request = query.query(false)?; // Execute the request using the Sdk instance let response = request.clone().execute(sdk, settings).await?; - // Parse the response into a CurrentQuorumsInfo object along with metadata - match Self::maybe_from_unproved_with_metadata(request, response, sdk.network, sdk.version()) - { - Ok((Some(info), _metadata)) => Ok(Some(info)), - Ok((None, _metadata)) => Ok(None), - Err(err) => Err(err.into()), - } + // Parse the response into the appropriate type along with metadata + let (object, mtd): (Option, platform_proto::ResponseMetadata) = + Self::maybe_from_unproved_with_metadata(request, response, sdk.network, sdk.version())?; + + Ok((object, mtd)) } } + +impl FetchUnproved for drive_proof_verifier::types::CurrentQuorumsInfo { + type Request = platform_proto::GetCurrentQuorumsInfoRequest; +} + +impl FetchUnproved for EvonodeStatus { + type Request = platform_proto::GetStatusRequest; +} diff --git a/packages/rs-sdk/src/platform/query.rs b/packages/rs-sdk/src/platform/query.rs index 211b3d5fb8..adc48b23f1 100644 --- a/packages/rs-sdk/src/platform/query.rs +++ b/packages/rs-sdk/src/platform/query.rs @@ -2,6 +2,7 @@ //! //! [Query] trait is used to specify individual objects as well as search criteria for fetching multiple objects from Platform. use super::types::epoch::EpochQuery; +use super::types::evonode::EvoNode; use crate::{error::Error, platform::document_query::DocumentQuery}; use dapi_grpc::mock::Mockable; use dapi_grpc::platform::v0::get_contested_resource_identity_votes_request::GetContestedResourceIdentityVotesRequestV0; @@ -647,7 +648,7 @@ impl Query for LimitQuery for () { +impl Query for EvoNode { fn query(self, _prove: bool) -> Result { // ignore proof diff --git a/packages/rs-sdk/src/platform/types.rs b/packages/rs-sdk/src/platform/types.rs index 97a12c40b5..e4fbab2d47 100644 --- a/packages/rs-sdk/src/platform/types.rs +++ b/packages/rs-sdk/src/platform/types.rs @@ -1,5 +1,6 @@ //! Type-specific implementation for various dpp object types to make queries more convenient and intuitive. pub mod epoch; +pub mod evonode; pub mod identity; pub mod proposed_blocks; mod total_credits_in_platform; diff --git a/packages/rs-sdk/src/platform/types/evonode.rs b/packages/rs-sdk/src/platform/types/evonode.rs new file mode 100644 index 0000000000..8dd8715096 --- /dev/null +++ b/packages/rs-sdk/src/platform/types/evonode.rs @@ -0,0 +1,90 @@ +//! Evo Node represents a network node (server). + +use crate::mock::BINCODE_CONFIG; +use dapi_grpc::mock::Mockable; +use dapi_grpc::platform::v0::get_status_request::GetStatusRequestV0; +use dapi_grpc::platform::v0::{self as proto, get_status_request, GetStatusRequest}; +use dapi_grpc::tonic::IntoRequest; +use futures::future::BoxFuture; +use futures::{FutureExt, TryFutureExt}; +use rs_dapi_client::transport::{ + AppliedRequestSettings, PlatformGrpcClient, TransportClient, TransportRequest, +}; +use rs_dapi_client::{Address, ConnectionPool, RequestSettings}; +use serde::{Deserialize, Serialize}; +use std::fmt::Debug; + +/// EvoNode allows querying the status of a single node using DAPI. +/// +/// ## Example +/// +/// ```rust +/// use dash_sdk::{platform::query::EvoNode, Sdk}; +/// use futures::executor::block_on; +/// +/// let sdk = Sdk::new_mock(); +/// let node = EvoNode::new("https://44.232.196.6:443".parse().unwrap()); +/// let status = block_on(node.get_status(&sdk)).unwrap(); +/// ``` + +#[derive(Debug, Clone)] +#[cfg_attr(feature = "mocks", derive(Serialize, Deserialize))] +pub struct EvoNode(Address); + +#[cfg(feature = "mocks")] +impl Mockable for EvoNode { + fn mock_deserialize(data: &[u8]) -> Option { + if let Ok((obj, _)) = bincode::serde::decode_from_slice(data, BINCODE_CONFIG) { + Some(obj) + } else { + None + } + } +} +impl TransportRequest for EvoNode { + type Client = PlatformGrpcClient; + type Response = proto::GetStatusResponse; + + const SETTINGS_OVERRIDES: rs_dapi_client::RequestSettings = RequestSettings::default(); + + fn method_name(&self) -> &'static str { + "get_status" + } + + fn execute_transport<'c>( + self, + _client: &'c mut Self::Client, + settings: &AppliedRequestSettings, + ) -> BoxFuture<'c, Result::Error>> { + let uri = self.0.uri(); + // As this is single node connection case, we create a new connection pool with space for a single connection + // and we drop it after use. + // + // We also create a new client to use with this request, so that the user does not need to + // reconfigure SDK to use a single node. + let pool = ConnectionPool::new(1); + let mut client = Self::Client::with_uri_and_settings(uri.clone(), settings, &pool); + let mut grpc_request = GetStatusRequest { + version: Some(get_status_request::Version::V0(GetStatusRequestV0 {})), + } + .into_request(); + + // we need to establish connection only with provided node, so we override client + + if !settings.timeout.is_zero() { + grpc_request.set_timeout(settings.timeout); + } + + async move { + let response = client + .get_status(grpc_request) + .map_ok(|response| response.into_inner()) + .await; + + drop(client); + drop(pool); + response + } + .boxed() + } +} From fa4bb873ff2cbe77b48ed7ecf6dd63ea0b30b790 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Thu, 26 Sep 2024 16:02:07 +0200 Subject: [PATCH 07/23] chore(sdk): status tests --- packages/rs-sdk/src/platform/types/evonode.rs | 18 ++++++-- packages/rs-sdk/tests/fetch/evonode.rs | 46 +++++++++++++++++++ packages/rs-sdk/tests/fetch/mod.rs | 1 + 3 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 packages/rs-sdk/tests/fetch/evonode.rs diff --git a/packages/rs-sdk/src/platform/types/evonode.rs b/packages/rs-sdk/src/platform/types/evonode.rs index 8dd8715096..1dd4528709 100644 --- a/packages/rs-sdk/src/platform/types/evonode.rs +++ b/packages/rs-sdk/src/platform/types/evonode.rs @@ -5,6 +5,7 @@ use dapi_grpc::mock::Mockable; use dapi_grpc::platform::v0::get_status_request::GetStatusRequestV0; use dapi_grpc::platform::v0::{self as proto, get_status_request, GetStatusRequest}; use dapi_grpc::tonic::IntoRequest; +pub use drive_proof_verifier::types::EvonodeStatus; use futures::future::BoxFuture; use futures::{FutureExt, TryFutureExt}; use rs_dapi_client::transport::{ @@ -18,19 +19,28 @@ use std::fmt::Debug; /// /// ## Example /// -/// ```rust -/// use dash_sdk::{platform::query::EvoNode, Sdk}; +/// ```rust,no_run +/// use dash_sdk::{platform::types::evonode::EvoNode,platform::FetchUnproved, Sdk}; +/// use drive_proof_verifier::types::EvonodeStatus; /// use futures::executor::block_on; /// /// let sdk = Sdk::new_mock(); -/// let node = EvoNode::new("https://44.232.196.6:443".parse().unwrap()); -/// let status = block_on(node.get_status(&sdk)).unwrap(); +/// let uri: http::Uri = "http://127.0.0.1:1".parse().unwrap(); +/// let node = EvoNode::new(uri.into()); +/// let status = block_on(EvonodeStatus::fetch_unproved(&sdk, node)).unwrap(); /// ``` #[derive(Debug, Clone)] #[cfg_attr(feature = "mocks", derive(Serialize, Deserialize))] pub struct EvoNode(Address); +impl EvoNode { + /// Creates a new `EvoNode` with the given address. + pub fn new(address: Address) -> Self { + Self(address) + } +} + #[cfg(feature = "mocks")] impl Mockable for EvoNode { fn mock_deserialize(data: &[u8]) -> Option { diff --git a/packages/rs-sdk/tests/fetch/evonode.rs b/packages/rs-sdk/tests/fetch/evonode.rs new file mode 100644 index 0000000000..6302f5fd7d --- /dev/null +++ b/packages/rs-sdk/tests/fetch/evonode.rs @@ -0,0 +1,46 @@ +//! Test evo node status and other node-related functionality. + +use dash_sdk::platform::{types::evonode::EvoNode, FetchUnproved}; +use drive_proof_verifier::types::EvonodeStatus; +use http::Uri; + +use super::{common::setup_logs, config::Config}; + +/// Given some existing evonode URIs, WHEN we connect to them, THEN we get status. +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +async fn test_evonode_status() { + setup_logs(); + + let cfg = Config::new(); + let sdk = cfg.setup_api("test_evonode_status").await; + + let addresses = sdk.address_list().unwrap(); + + for address in addresses.addresses() { + let node = EvoNode::new(address.clone()); + let status = EvonodeStatus::fetch_unproved(&sdk, node) + .await + .expect("fetch evonode status") + .expect("found evonode status"); + + tracing::debug!(?status, ?address, "evonode status"); + } +} + +/// Given invalid evonode URI, when we request status, we get error. +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +async fn test_evonode_status_refused() { + setup_logs(); + + let cfg = Config::new(); + let sdk = cfg.setup_api("test_evonode_status_refused").await; + + let uri: Uri = "http://127.0.0.1:1".parse().unwrap(); + + let node = EvoNode::new(uri.clone().into()); + let result = EvonodeStatus::fetch_unproved(&sdk, node).await; + + assert!(result.is_err()); + + tracing::debug!(?result, ?uri, "evonode status"); +} diff --git a/packages/rs-sdk/tests/fetch/mod.rs b/packages/rs-sdk/tests/fetch/mod.rs index 76e6c84c69..363e35f069 100644 --- a/packages/rs-sdk/tests/fetch/mod.rs +++ b/packages/rs-sdk/tests/fetch/mod.rs @@ -17,6 +17,7 @@ mod contested_resource_voters; mod data_contract; mod document; mod epoch; +mod evonode; mod identity; mod identity_contract_nonce; mod mock_fetch; From bad801c48529e7a165d04c27cea0007a23faceef Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Thu, 26 Sep 2024 16:21:49 +0200 Subject: [PATCH 08/23] chore: minor improvements --- packages/rs-drive-proof-verifier/src/types.rs | 22 ++++++---- packages/rs-sdk/tests/fetch/evonode.rs | 40 ++++++++++++++++--- 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/packages/rs-drive-proof-verifier/src/types.rs b/packages/rs-drive-proof-verifier/src/types.rs index c1fa3cbddb..be0fa7102a 100644 --- a/packages/rs-drive-proof-verifier/src/types.rs +++ b/packages/rs-drive-proof-verifier/src/types.rs @@ -26,7 +26,6 @@ use dpp::{ util::deserializer::ProtocolVersion, }; use drive::grovedb::Element; -use hex::ToHex; use std::collections::{BTreeMap, BTreeSet}; use crate::Error; @@ -627,7 +626,7 @@ pub struct ProposerBlockCountById(pub u64); /// Status of a network node pub struct EvonodeStatus { /// The Identifier of the Evonode - pub pro_tx_hash: String, + pub pro_tx_hash: [u8; ProTxHash::LEN], /// The latest block height stored on the Evonode pub latest_block_height: u64, } @@ -646,13 +645,20 @@ impl TryFrom for EvonodeStatus { error: "missing chain information".to_string(), })?; + let protx = node.pro_tx_hash.ok_or(Error::ProtocolError { + error: "Missing pro_tx_hash".to_string(), + })?; + let protx_len = protx.len(); + Ok(Self { - pro_tx_hash: node - .pro_tx_hash - .ok_or(Error::ProtocolError { - error: "Missing pro_tx_hash".to_string(), - })? - .encode_hex(), + pro_tx_hash: protx.clone().try_into().map_err(|_| Error::ProtocolError { + error: format!( + "Invalid pro_tx_hash size: {} != {}", + protx_len, + ProTxHash::LEN + ), + })?, + latest_block_height: chain.latest_block_height, }) } diff --git a/packages/rs-sdk/tests/fetch/evonode.rs b/packages/rs-sdk/tests/fetch/evonode.rs index 6302f5fd7d..9a167a8891 100644 --- a/packages/rs-sdk/tests/fetch/evonode.rs +++ b/packages/rs-sdk/tests/fetch/evonode.rs @@ -1,12 +1,16 @@ //! Test evo node status and other node-related functionality. use dash_sdk::platform::{types::evonode::EvoNode, FetchUnproved}; +use dpp::dashcore::{hashes::Hash, ProTxHash}; use drive_proof_verifier::types::EvonodeStatus; use http::Uri; use super::{common::setup_logs, config::Config}; +use std::time::Duration; /// Given some existing evonode URIs, WHEN we connect to them, THEN we get status. +use tokio::time::timeout; + #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn test_evonode_status() { setup_logs(); @@ -18,12 +22,36 @@ async fn test_evonode_status() { for address in addresses.addresses() { let node = EvoNode::new(address.clone()); - let status = EvonodeStatus::fetch_unproved(&sdk, node) - .await - .expect("fetch evonode status") - .expect("found evonode status"); - - tracing::debug!(?status, ?address, "evonode status"); + match timeout( + Duration::from_secs(3), + EvonodeStatus::fetch_unproved(&sdk, node), + ) + .await + { + Ok(Ok(Some(status))) => { + tracing::debug!(?status, ?address, "evonode status"); + // Add assertions here to verify the status contents + assert!( + status.latest_block_height > 0, + "latest block height must be positive" + ); + assert!( + status.pro_tx_hash.len() == ProTxHash::LEN, + "latest block hash must be non-empty" + ); + // Add more specific assertions based on expected status properties + } + Ok(Ok(None)) => { + tracing::warn!(?address, "No status found for evonode"); + panic!("No status found for evonode"); + } + Ok(Err(e)) => { + tracing::error!(?address, error = ?e, "Error fetching evonode status"); + } + Err(_) => { + tracing::error!(?address, "Timeout while fetching evonode status"); + } + } } } From 18d3df8637326f6c4e1550ea674568ae76f3d5fc Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Fri, 27 Sep 2024 09:27:16 +0200 Subject: [PATCH 09/23] refactor(dapi-client): impl IntoIterator for address list --- packages/rs-dapi-client/src/address_list.rs | 14 +++++++++----- packages/rs-sdk/tests/fetch/evonode.rs | 3 ++- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/rs-dapi-client/src/address_list.rs b/packages/rs-dapi-client/src/address_list.rs index 8282e6893f..bf09b1af8c 100644 --- a/packages/rs-dapi-client/src/address_list.rs +++ b/packages/rs-dapi-client/src/address_list.rs @@ -198,11 +198,6 @@ impl AddressList { pub fn is_empty(&self) -> bool { self.addresses.is_empty() } - - /// Getter function that returns a reference to the Hashset of addresses - pub fn addresses(&self) -> &HashSet
{ - &self.addresses - } } impl From<&str> for AddressList { @@ -226,3 +221,12 @@ impl FromIterator for AddressList { address_list } } + +impl IntoIterator for AddressList { + type Item = Address; + type IntoIter = std::collections::hash_set::IntoIter
; + + fn into_iter(self) -> Self::IntoIter { + self.addresses.into_iter() + } +} diff --git a/packages/rs-sdk/tests/fetch/evonode.rs b/packages/rs-sdk/tests/fetch/evonode.rs index 9a167a8891..44bb4e4a9e 100644 --- a/packages/rs-sdk/tests/fetch/evonode.rs +++ b/packages/rs-sdk/tests/fetch/evonode.rs @@ -20,7 +20,7 @@ async fn test_evonode_status() { let addresses = sdk.address_list().unwrap(); - for address in addresses.addresses() { + for address in addresses { let node = EvoNode::new(address.clone()); match timeout( Duration::from_secs(3), @@ -57,6 +57,7 @@ async fn test_evonode_status() { /// Given invalid evonode URI, when we request status, we get error. #[tokio::test(flavor = "multi_thread", worker_threads = 1)] +#[cfg(feature = "network-testing")] // No mocking of error responses async fn test_evonode_status_refused() { setup_logs(); From 9a86b8f35ac6b05a3b1d26d770ec7391ba99f7bf Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Fri, 27 Sep 2024 09:59:04 +0200 Subject: [PATCH 10/23] fix: get status connecting to wrong node --- packages/dapi-grpc/build.rs | 9 +++-- .../rs-drive-proof-verifier/src/unproved.rs | 1 + .../rs-sdk/src/platform/fetch_unproved.rs | 35 ++++++++++++++++--- packages/rs-sdk/src/platform/query.rs | 2 +- packages/rs-sdk/tests/fetch/evonode.rs | 7 ++-- 5 files changed, 42 insertions(+), 12 deletions(-) diff --git a/packages/dapi-grpc/build.rs b/packages/dapi-grpc/build.rs index 4bd36542e8..f70b685fbd 100644 --- a/packages/dapi-grpc/build.rs +++ b/packages/dapi-grpc/build.rs @@ -47,7 +47,7 @@ fn configure_platform(mut platform: MappingConfig) -> MappingConfig { // Derive features for versioned messages // // "GetConsensusParamsRequest" is excluded as this message does not support proofs - const VERSIONED_REQUESTS: [&str; 29] = [ + const VERSIONED_REQUESTS: [&str; 30] = [ "GetDataContractHistoryRequest", "GetDataContractRequest", "GetDataContractsRequest", @@ -77,9 +77,13 @@ fn configure_platform(mut platform: MappingConfig) -> MappingConfig { "GetTotalCreditsInPlatformRequest", "GetEvonodesProposedEpochBlocksByIdsRequest", "GetEvonodesProposedEpochBlocksByRangeRequest", + "GetStatusRequest", ]; - // "GetConsensusParamsResponse" is excluded as this message does not support proofs + // The following responses are excluded as they don't support proofs: + // - "GetConsensusParamsResponse" + // - "GetStatusResponse" + // // "GetEvonodesProposedEpochBlocksResponse" is used for 2 Requests const VERSIONED_RESPONSES: [&str; 29] = [ "GetDataContractHistoryResponse", @@ -213,6 +217,7 @@ impl MappingConfig { /// /// * `protobuf_file` - Path to the protobuf file to use as input. /// * `out_dir` - Output directory where subdirectories for generated files will be created. + /// /// Depending on the features, either `client`, `server` or `client_server` subdirectory /// will be created inside `out_dir`. fn new(protobuf_file: PathBuf, out_dir: PathBuf) -> Self { diff --git a/packages/rs-drive-proof-verifier/src/unproved.rs b/packages/rs-drive-proof-verifier/src/unproved.rs index 7207ace006..e27716ffa0 100644 --- a/packages/rs-drive-proof-verifier/src/unproved.rs +++ b/packages/rs-drive-proof-verifier/src/unproved.rs @@ -290,6 +290,7 @@ impl FromUnproved for EvonodeStatus { Self: Sized, { let status = Self::try_from(response.into())?; + // we use default response metadata, as this request does not return any metadata Ok((Some(status), Default::default())) } } diff --git a/packages/rs-sdk/src/platform/fetch_unproved.rs b/packages/rs-sdk/src/platform/fetch_unproved.rs index 74ead3e875..ea48e110d9 100644 --- a/packages/rs-sdk/src/platform/fetch_unproved.rs +++ b/packages/rs-sdk/src/platform/fetch_unproved.rs @@ -1,14 +1,17 @@ +use super::{types::evonode::EvoNode, Query}; use crate::error::Error; use crate::mock::MockResponse; use crate::Sdk; -use dapi_grpc::platform::v0::{self as platform_proto, ResponseMetadata}; +use dapi_grpc::platform::v0::{ + self as platform_proto, get_status_request::GetStatusRequestV0, GetStatusRequest, + GetStatusResponse, ResponseMetadata, +}; +use dpp::{dashcore::Network, version::PlatformVersion}; use drive_proof_verifier::types::EvonodeStatus; use drive_proof_verifier::unproved::FromUnproved; use rs_dapi_client::{transport::TransportRequest, DapiRequest, RequestSettings}; use std::fmt::Debug; -use super::Query; - #[async_trait::async_trait] pub trait FetchUnproved where @@ -85,5 +88,29 @@ impl FetchUnproved for drive_proof_verifier::types::CurrentQuorumsInfo { } impl FetchUnproved for EvonodeStatus { - type Request = platform_proto::GetStatusRequest; + type Request = EvoNode; +} + +// We need to delegate FromUnproved for the impl FetchUnproved for EvonodeStatus. +#[async_trait::async_trait] +impl FromUnproved for EvonodeStatus { + type Request = EvoNode; + type Response = GetStatusResponse; + + fn maybe_from_unproved_with_metadata, O: Into>( + _request: I, + response: O, + network: Network, + platform_version: &PlatformVersion, + ) -> Result<(Option, ResponseMetadata), drive_proof_verifier::Error> + where + Self: Sized, + { + >::maybe_from_unproved_with_metadata( + GetStatusRequestV0 {}, + response, + network, + platform_version, + ) + } } diff --git a/packages/rs-sdk/src/platform/query.rs b/packages/rs-sdk/src/platform/query.rs index adc48b23f1..287f8b6951 100644 --- a/packages/rs-sdk/src/platform/query.rs +++ b/packages/rs-sdk/src/platform/query.rs @@ -100,7 +100,7 @@ where { fn query(self, prove: bool) -> Result { if !prove { - unimplemented!("queries without proofs are not supported yet"); + tracing::warn!(request= ?self, "sending query without proof, ensure data is trusted"); } Ok(self) } diff --git a/packages/rs-sdk/tests/fetch/evonode.rs b/packages/rs-sdk/tests/fetch/evonode.rs index 44bb4e4a9e..26e483e411 100644 --- a/packages/rs-sdk/tests/fetch/evonode.rs +++ b/packages/rs-sdk/tests/fetch/evonode.rs @@ -1,12 +1,10 @@ //! Test evo node status and other node-related functionality. +use super::{common::setup_logs, config::Config}; use dash_sdk::platform::{types::evonode::EvoNode, FetchUnproved}; use dpp::dashcore::{hashes::Hash, ProTxHash}; use drive_proof_verifier::types::EvonodeStatus; use http::Uri; - -use super::{common::setup_logs, config::Config}; - use std::time::Duration; /// Given some existing evonode URIs, WHEN we connect to them, THEN we get status. use tokio::time::timeout; @@ -68,8 +66,7 @@ async fn test_evonode_status_refused() { let node = EvoNode::new(uri.clone().into()); let result = EvonodeStatus::fetch_unproved(&sdk, node).await; + tracing::debug!(?result, ?uri, "evonode status"); assert!(result.is_err()); - - tracing::debug!(?result, ?uri, "evonode status"); } From beadf24a195969aad9fca805c8b11f4d1863fa2d Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Fri, 27 Sep 2024 10:09:19 +0200 Subject: [PATCH 11/23] chore: fix dump of evonode --- packages/rs-dapi-client/src/dump.rs | 1 - packages/rs-sdk/src/platform/types/evonode.rs | 10 +++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/rs-dapi-client/src/dump.rs b/packages/rs-dapi-client/src/dump.rs index c81399395b..a1e23d1ff2 100644 --- a/packages/rs-dapi-client/src/dump.rs +++ b/packages/rs-dapi-client/src/dump.rs @@ -189,7 +189,6 @@ impl DapiClient { response: &MockResult, dump_dir: Option, ) where - R: Mockable, ::Response: Mockable, { let path = match dump_dir { diff --git a/packages/rs-sdk/src/platform/types/evonode.rs b/packages/rs-sdk/src/platform/types/evonode.rs index 1dd4528709..a6ac4a8e6a 100644 --- a/packages/rs-sdk/src/platform/types/evonode.rs +++ b/packages/rs-sdk/src/platform/types/evonode.rs @@ -44,11 +44,11 @@ impl EvoNode { #[cfg(feature = "mocks")] impl Mockable for EvoNode { fn mock_deserialize(data: &[u8]) -> Option { - if let Ok((obj, _)) = bincode::serde::decode_from_slice(data, BINCODE_CONFIG) { - Some(obj) - } else { - None - } + serde_json::de::from_slice(data).ok() + } + + fn mock_serialize(&self) -> Option> { + serde_json::ser::to_vec(self).ok() } } impl TransportRequest for EvoNode { From 4263ed90813aec8fcdbf534c613c5c8948658abb Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Fri, 27 Sep 2024 10:15:39 +0200 Subject: [PATCH 12/23] chore: fix mocking --- packages/rs-sdk/src/mock/sdk.rs | 8 ++++++-- packages/rs-sdk/tests/fetch/evonode.rs | 3 +-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/rs-sdk/src/mock/sdk.rs b/packages/rs-sdk/src/mock/sdk.rs index 0f37c7dd36..02258c0cd1 100644 --- a/packages/rs-sdk/src/mock/sdk.rs +++ b/packages/rs-sdk/src/mock/sdk.rs @@ -2,7 +2,10 @@ //! //! See [MockDashPlatformSdk] for more details. use crate::{ - platform::{types::identity::IdentityRequest, DocumentQuery, Fetch, FetchMany, Query}, + platform::{ + types::{evonode::EvoNode, identity::IdentityRequest}, + DocumentQuery, Fetch, FetchMany, Query, + }, Error, Sdk, }; use arc_swap::ArcSwapOption; @@ -201,9 +204,10 @@ impl MockDashPlatformSdk { self.load_expectation::(filename) .await? } + "EvoNode" => self.load_expectation::(filename).await?, _ => { return Err(Error::Config(format!( - "unknown request type {} in {}", + "unknown request type {} in {}, missing match arm in load_expectations?", request_type, filename.display() ))) diff --git a/packages/rs-sdk/tests/fetch/evonode.rs b/packages/rs-sdk/tests/fetch/evonode.rs index 26e483e411..f27a738c31 100644 --- a/packages/rs-sdk/tests/fetch/evonode.rs +++ b/packages/rs-sdk/tests/fetch/evonode.rs @@ -16,7 +16,7 @@ async fn test_evonode_status() { let cfg = Config::new(); let sdk = cfg.setup_api("test_evonode_status").await; - let addresses = sdk.address_list().unwrap(); + let addresses = cfg.address_list(); for address in addresses { let node = EvoNode::new(address.clone()); @@ -55,7 +55,6 @@ async fn test_evonode_status() { /// Given invalid evonode URI, when we request status, we get error. #[tokio::test(flavor = "multi_thread", worker_threads = 1)] -#[cfg(feature = "network-testing")] // No mocking of error responses async fn test_evonode_status_refused() { setup_logs(); From 99335cdfd09063f715ff4b716ddd4863e306ddfb Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Fri, 27 Sep 2024 10:18:07 +0200 Subject: [PATCH 13/23] chore:remove unused bincode --- Cargo.lock | 1 - packages/rs-sdk/Cargo.toml | 2 -- packages/rs-sdk/src/mock.rs | 2 -- packages/rs-sdk/src/mock/requests.rs | 2 +- packages/rs-sdk/src/platform/types/evonode.rs | 1 - 5 files changed, 1 insertion(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 64a7a07128..ad59187b72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1213,7 +1213,6 @@ dependencies = [ "arc-swap", "async-trait", "base64 0.22.1", - "bincode", "bip37-bloom-filter", "chrono", "ciborium", diff --git a/packages/rs-sdk/Cargo.toml b/packages/rs-sdk/Cargo.toml index 18402c6297..b2efa71805 100644 --- a/packages/rs-sdk/Cargo.toml +++ b/packages/rs-sdk/Cargo.toml @@ -5,7 +5,6 @@ edition = "2021" [dependencies] arc-swap = { version = "1.7.1" } -bincode = { version = "2.0.0-rc.3", features = ["serde"], optional = true } dpp = { path = "../rs-dpp", default-features = false, features = [ "dash-sdk-features", ] } @@ -59,7 +58,6 @@ test-case = { version = "3.3.1" } default = ["mocks", "offline-testing"] mocks = [ - "dep:bincode", "dep:serde", "dep:serde_json", "rs-dapi-client/mocks", diff --git a/packages/rs-sdk/src/mock.rs b/packages/rs-sdk/src/mock.rs index 159aa73eba..7ad4dc7ccd 100644 --- a/packages/rs-sdk/src/mock.rs +++ b/packages/rs-sdk/src/mock.rs @@ -38,6 +38,4 @@ pub use noop::MockResponse; #[cfg(feature = "mocks")] pub use requests::MockResponse; #[cfg(feature = "mocks")] -pub(crate) use requests::BINCODE_CONFIG; -#[cfg(feature = "mocks")] pub use sdk::MockDashPlatformSdk; diff --git a/packages/rs-sdk/src/mock/requests.rs b/packages/rs-sdk/src/mock/requests.rs index 1996ae9373..1c8d098895 100644 --- a/packages/rs-sdk/src/mock/requests.rs +++ b/packages/rs-sdk/src/mock/requests.rs @@ -22,7 +22,7 @@ use drive_proof_verifier::types::{ }; use std::collections::BTreeMap; -pub(crate) static BINCODE_CONFIG: bincode::config::Configuration = bincode::config::standard(); +static BINCODE_CONFIG: bincode::config::Configuration = bincode::config::standard(); /// Trait implemented by objects that can be used in mock expectation responses. /// diff --git a/packages/rs-sdk/src/platform/types/evonode.rs b/packages/rs-sdk/src/platform/types/evonode.rs index a6ac4a8e6a..cc7efd82af 100644 --- a/packages/rs-sdk/src/platform/types/evonode.rs +++ b/packages/rs-sdk/src/platform/types/evonode.rs @@ -1,6 +1,5 @@ //! Evo Node represents a network node (server). -use crate::mock::BINCODE_CONFIG; use dapi_grpc::mock::Mockable; use dapi_grpc::platform::v0::get_status_request::GetStatusRequestV0; use dapi_grpc::platform::v0::{self as proto, get_status_request, GetStatusRequest}; From e58541db6329a376950c95ebb83167fd07f4b23c Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Fri, 27 Sep 2024 10:18:37 +0200 Subject: [PATCH 14/23] test(e2e): test vectors --- .../tests/vectors/test_evonode_status/.gitkeep | 0 ...bca1c40d35547373d23f3ba329df2b6d993b374.json | Bin 0 -> 12549 bytes .../test_evonode_status_refused/.gitkeep | 0 ...5864123671ed14d3f0c537aa8e878d24e529de5.json | Bin 0 -> 155 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 packages/rs-sdk/tests/vectors/test_evonode_status/.gitkeep create mode 100644 packages/rs-sdk/tests/vectors/test_evonode_status/msg_EvoNode_244e3005966550cd3cb2837d3bca1c40d35547373d23f3ba329df2b6d993b374.json create mode 100644 packages/rs-sdk/tests/vectors/test_evonode_status_refused/.gitkeep create mode 100644 packages/rs-sdk/tests/vectors/test_evonode_status_refused/msg_EvoNode_6db392ff1869b56ecc7de9ace5864123671ed14d3f0c537aa8e878d24e529de5.json diff --git a/packages/rs-sdk/tests/vectors/test_evonode_status/.gitkeep b/packages/rs-sdk/tests/vectors/test_evonode_status/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/rs-sdk/tests/vectors/test_evonode_status/msg_EvoNode_244e3005966550cd3cb2837d3bca1c40d35547373d23f3ba329df2b6d993b374.json b/packages/rs-sdk/tests/vectors/test_evonode_status/msg_EvoNode_244e3005966550cd3cb2837d3bca1c40d35547373d23f3ba329df2b6d993b374.json new file mode 100644 index 0000000000000000000000000000000000000000..c20459952525c3e46f5b54f7947af4b0a4d5d4ea GIT binary patch literal 12549 zcmcJV+iv4V5JdC5pP^^M7A4ZQ^b`4jAXwxEWD&y&68mYf|DHPCLy5XhjpYR-i?W72 z-PP5X;mp^?ufM!}{_XF#m)FI1+41e=kKaG*>zC)n_T}yQxm&#b`(?3R{Q3I&&wtzd z`}KI&Ka6+d@~&S!Z2MtY-!Hy>`r*^p#gBh2wmpWLBC%cH6Qz~X;Q#mOwn#BrTPcGH{Iq@A5vaM7^)n}TQ2i{iId^G z`*ksFy5XT4d;X@C1Cvb1&E?Fm8M7=3p=+Z1F@iBTT%`$^WOCbN1l}7eMqII=UyWVG zMmPfUe8Let(07|neqCB*I6|w@sB=`DOPpV)wj=J)zbBgF*r%GIhhjE(QSV~w^6^00 z2ze^JFtE)jEBt9RUrI-KOvHha4}0ZdHxpKr-zAH1bP2Z-a^#6)nN@+Hab?iOpRb~b zx6wtsEWxpJc?~r%K%-g8+aRWbi*atrK6azBiUGF>%1Do+43-*8OETJeE=R04 zlBuPtg32&$T)TFqQH*!QN{0l^8!WM|WFcnjAjC!$3rB}0M@U=KzoW}W;IawH?52N{ ziXL@wu@Ia0BlENy*PAN%LVH${Hksl2mFhYXJ!JmN%UwROg8R`nT1I%0?L&@#1dqoi z2CG%^bikAHkLe;&&rAdM?D*W2DFmc|nO_xB9$aL>Dy@QjK+wC(@FgJjn_Qzd%T`85cy5oy{n1mtFhTH!Nv7{Iuo413 z2-4Q`LX&B!vy=LP%k!-C{C*k#WaFSD{@A;TXU;tS;u+TbvAhC0R>!iSo&!){dobm( zJZqJZ%l1q@4Eru?53fuRk4iNjZR)1Z`x~3&=-^Y)K|IvJLtYyVY4y5Fv)p1K7L*hG zENaNae7#!y)!+ylTU_9SV2cH@mLk=V7KE73TRS)63$ysz)d9|!t%B(7F(IjFBEVqP zXg?g(D){j$xIE^VVU7#*vbFW$MNd=JqyfqL#>GZ8^?%r+123zjdImDsm>1^j-x@cPsH~HH=UTWK5T1#_|T{dV|kFqP=O`W_3do5fco2RqsV%RH6 zcrtUOsjbhP)WJ`c;NYb-5@5ug!_1E{5Wa5{n-+5*pfgIoULd zMVNrtpXW*yc83P8Y6KYh5)%}0(Vv{H)8ZJZ;pua$GL2(Irnw z@>zBhPvxbu$v?)&5+2^p4z<=350il>hG#JDK-z;9lixJOMSH+zYBx1uJl6m+ZkU~} zbqtxdXeZ|A%w;IPKYbb_ke<%buQ4}lDciX>8JU1xFb7qzE|BK>%u^i4%2fU$YS@&? zYZpPnft$)NmtxDATl>+nF60v|q-!iG^&u<^KA!Gdw>$INRG3mGo#o@S@l5ROVqG@A zFT5|%qMm4HXMo{_pxP@FofkDfT6ivU**et<)%JS-qSI<8NSvQS(zFbUhgB&#o635- v0cjy?X0rUm?RvL{Xx>afDnlks50uqY3B5r3%o3L*eDuS?zseVV{QT{I0Ki(4 literal 0 HcmV?d00001 diff --git a/packages/rs-sdk/tests/vectors/test_evonode_status_refused/.gitkeep b/packages/rs-sdk/tests/vectors/test_evonode_status_refused/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/rs-sdk/tests/vectors/test_evonode_status_refused/msg_EvoNode_6db392ff1869b56ecc7de9ace5864123671ed14d3f0c537aa8e878d24e529de5.json b/packages/rs-sdk/tests/vectors/test_evonode_status_refused/msg_EvoNode_6db392ff1869b56ecc7de9ace5864123671ed14d3f0c537aa8e878d24e529de5.json new file mode 100644 index 0000000000000000000000000000000000000000..c80da24adbea4698e7b9af024c6761ca9cb3c143 GIT binary patch literal 155 zcmXAgOA5m<3`D!mF|-!7rg7^;`<|kd&>u7q++yri$lWWu2r+Loqm}NrI6XckW>Vqm z;_Eq?ofpzrmW8RLnUvl+f7Ll0!d`5kaI|&1Zl!Zdq?g`v7#IMbjwS<-fgy&{aJ0+_ U^3O#KZQ Date: Fri, 27 Sep 2024 10:36:34 +0200 Subject: [PATCH 15/23] chore: impl From for GetStatusRequest --- packages/rs-sdk/src/platform/fetch_unproved.rs | 10 ++++++---- packages/rs-sdk/src/platform/types/evonode.rs | 7 +++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/rs-sdk/src/platform/fetch_unproved.rs b/packages/rs-sdk/src/platform/fetch_unproved.rs index ea48e110d9..2ce3afc4f9 100644 --- a/packages/rs-sdk/src/platform/fetch_unproved.rs +++ b/packages/rs-sdk/src/platform/fetch_unproved.rs @@ -3,8 +3,7 @@ use crate::error::Error; use crate::mock::MockResponse; use crate::Sdk; use dapi_grpc::platform::v0::{ - self as platform_proto, get_status_request::GetStatusRequestV0, GetStatusRequest, - GetStatusResponse, ResponseMetadata, + self as platform_proto, GetStatusRequest, GetStatusResponse, ResponseMetadata, }; use dpp::{dashcore::Network, version::PlatformVersion}; use drive_proof_verifier::types::EvonodeStatus; @@ -24,6 +23,7 @@ where /// /// ## Parameters /// - `sdk`: An instance of [Sdk]. + /// - `query`: Query used to fetch data from the Platform. /// /// ## Returns /// Returns: @@ -50,6 +50,7 @@ where /// /// ## Parameters /// - `sdk`: An instance of [Sdk]. + /// - `query`: Query used to fetch data from the Platform. /// - `settings`: Request settings for the connection to Platform. /// /// ## Returns @@ -98,7 +99,7 @@ impl FromUnproved for EvonodeStatus { type Response = GetStatusResponse; fn maybe_from_unproved_with_metadata, O: Into>( - _request: I, + request: I, response: O, network: Network, platform_version: &PlatformVersion, @@ -106,8 +107,9 @@ impl FromUnproved for EvonodeStatus { where Self: Sized, { + // delegate to the FromUnproved >::maybe_from_unproved_with_metadata( - GetStatusRequestV0 {}, + request.into(), response, network, platform_version, diff --git a/packages/rs-sdk/src/platform/types/evonode.rs b/packages/rs-sdk/src/platform/types/evonode.rs index cc7efd82af..8425de1f7a 100644 --- a/packages/rs-sdk/src/platform/types/evonode.rs +++ b/packages/rs-sdk/src/platform/types/evonode.rs @@ -97,3 +97,10 @@ impl TransportRequest for EvoNode { .boxed() } } + +impl From for GetStatusRequest { + fn from(_node: EvoNode) -> Self { + // we don't need to send any data to the node, and address is handled in impl TrasportRequest + GetStatusRequestV0 {}.into() + } +} From 1ff4fce8d054e3dd3482277bd49a5918e9159409 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Fri, 27 Sep 2024 12:03:28 +0200 Subject: [PATCH 16/23] feat(sdk): EvonodeStatus additional fields --- packages/rs-drive-proof-verifier/src/types.rs | 158 +++++++++++++++--- packages/rs-sdk/tests/fetch/evonode.rs | 4 +- 2 files changed, 136 insertions(+), 26 deletions(-) diff --git a/packages/rs-drive-proof-verifier/src/types.rs b/packages/rs-drive-proof-verifier/src/types.rs index be0fa7102a..6046366cf3 100644 --- a/packages/rs-drive-proof-verifier/src/types.rs +++ b/packages/rs-drive-proof-verifier/src/types.rs @@ -26,6 +26,7 @@ use dpp::{ util::deserializer::ProtocolVersion, }; use drive::grovedb::Element; +use hex::ToHex; use std::collections::{BTreeMap, BTreeSet}; use crate::Error; @@ -623,12 +624,76 @@ pub struct ProposerBlockCountById(pub u64); derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), platform_serialize(unversioned) )] -/// Status of a network node +/// Status of a network node. +/// +/// Some fields may be `None` if the information is not available, eg. when the node is not fully functional. pub struct EvonodeStatus { /// The Identifier of the Evonode - pub pro_tx_hash: [u8; ProTxHash::LEN], + pub pro_tx_hash: Option<[u8; ProTxHash::LEN]>, // We don't use ProTxHash as it doesn't implement Encode/Decode /// The latest block height stored on the Evonode - pub latest_block_height: u64, + pub latest_block_height: Option, + /// Version of DAPI service + pub dapi_version: Option, + /// Version of Drive-ABCI service + pub drive_version: Option, + /// Version of Tenderdash service + pub tenderdash_version: Option, + /// Tenderdash P2P protocol version information + pub tenderdash_p2p_protocol: Option, + /// Tenderdash block protocol version information + pub tenderdash_block_protocol: Option, + /// Latest supported Drive protocol version + pub drive_latest_protocol: Option, + /// Current active Drive protocol version + pub drive_current_protocol: Option, + /// Local time of the node, in seconds since the Unix epoch + pub local_time: Option, + /// Last block time, in seconds since the Unix epoch + pub block_time: Option, + /// Genesis time, in seconds since the Unix epoch + pub genesis_time: Option, + /// Time of the current epoch + pub epoch_time: Option, + /// Tenderdash node ID (public key derived from the private key) + pub tenderdash_node_id: Option>, + /// Information if the node is catching up the Platform chain (Tenderdash) + pub catching_up: Option, + /// Latest platfom block hash + pub latest_block_hash: Option>, + /// Latest platform app hash + pub latest_app_hash: Option>, + /// Earliest block hash stored by the node + pub earliest_block_hash: Option>, + /// Earliest app hash stored by the node + pub earliest_app_hash: Option>, + /// Earliest block height stored by the node + pub earliest_block_height: Option, + /// Maximum block height of the peers + pub max_peer_block_height: Option, + /// Core chain locked height used by the node + pub core_chain_locked_height: Option, + /// Network chain ID + pub chain_id: Option, + /// Number of peers in the addressbook + pub peers_count: Option, + /// Information if the node is listening for incoming connections + pub listening: Option, + /// State sync total time + pub sync_total_time: Option, + /// State sync remaining time + pub sync_remaining_time: Option, + /// State sync total snapshots + pub sync_total_snapshots: Option, + /// State sync chunk process average time + pub sync_chunk_process_avg_time: Option, + /// State sync snapshot height + pub sync_snapshot_height: Option, + /// State sync snapshot chunks count + pub sync_snapshot_chunks_count: Option, + /// State sync backfilled blocks + pub sync_backfilled_blocks: Option, + /// State sync backfill blocks total + pub sync_backfill_blocks_total: Option, } impl TryFrom for EvonodeStatus { @@ -637,29 +702,74 @@ impl TryFrom for EvonodeStatus { use dapi_grpc::platform::v0::get_status_response::Version; match response.version { Some(Version::V0(v0)) => { - let node = v0.node.ok_or(Error::ProtocolError { - error: "missing node information".to_string(), - })?; - - let chain = v0.chain.ok_or(Error::ProtocolError { - error: "missing chain information".to_string(), - })?; - - let protx = node.pro_tx_hash.ok_or(Error::ProtocolError { - error: "Missing pro_tx_hash".to_string(), - })?; - let protx_len = protx.len(); + let node = v0.node; + let chain = v0.chain; + let protx: Option<[u8; ProTxHash::LEN]> = node + .as_ref() + .and_then(|n| { + n.pro_tx_hash.as_ref().map(|h| { + h.clone().try_into().map_err(|_| Error::ProtocolError { + error: format!( + "unvalid protxhash length: {:?}", + h.encode_hex::() + ), + }) + }) + }) + .transpose()?; + + let software = v0.version.as_ref().and_then(|v| v.software.clone()); + let protocol = v0.version.as_ref().and_then(|v| v.protocol.clone()); + + let tenderdash_protocol = protocol.as_ref().and_then(|p| p.tenderdash.clone()); + let drive_protocol = protocol.as_ref().and_then(|p| p.drive.clone()); + + let time = v0.time; + let network = v0.network; + let state_sync = v0.state_sync; Ok(Self { - pro_tx_hash: protx.clone().try_into().map_err(|_| Error::ProtocolError { - error: format!( - "Invalid pro_tx_hash size: {} != {}", - protx_len, - ProTxHash::LEN - ), - })?, - - latest_block_height: chain.latest_block_height, + pro_tx_hash: protx, + latest_block_height: chain.as_ref().map(|c| c.latest_block_height), + dapi_version: software.as_ref().map(|s| s.dapi.clone()), + drive_version: software.as_ref().and_then(|s| s.drive.clone()), + tenderdash_version: software.as_ref().and_then(|s| s.tenderdash.clone()), + tenderdash_p2p_protocol: tenderdash_protocol.as_ref().map(|p| p.p2p), + tenderdash_block_protocol: tenderdash_protocol.as_ref().map(|p| p.block), + drive_latest_protocol: drive_protocol.as_ref().map(|d| d.latest), + drive_current_protocol: drive_protocol.as_ref().map(|d| d.current), + local_time: time.as_ref().map(|t| t.local), + block_time: time.as_ref().and_then(|t| t.block), + genesis_time: time.as_ref().and_then(|t| t.genesis), + epoch_time: time.as_ref().and_then(|t| t.epoch), + tenderdash_node_id: node.as_ref().map(|n| n.id.clone()), + catching_up: chain.as_ref().map(|c| c.catching_up), + latest_block_hash: chain.as_ref().map(|c| c.latest_block_hash.clone()), + latest_app_hash: chain.as_ref().map(|c| c.latest_app_hash.clone()), + earliest_block_hash: chain.as_ref().map(|c| c.earliest_block_hash.clone()), + earliest_app_hash: chain.as_ref().map(|c| c.earliest_app_hash.clone()), + earliest_block_height: chain.as_ref().map(|c| c.earliest_block_height), + max_peer_block_height: chain.as_ref().map(|c| c.max_peer_block_height), + core_chain_locked_height: chain + .as_ref() + .and_then(|c| c.core_chain_locked_height), + chain_id: network.as_ref().map(|n| n.chain_id.clone()), + peers_count: network.as_ref().map(|n| n.peers_count), + listening: network.as_ref().map(|n| n.listening), + sync_total_time: state_sync.as_ref().map(|s| s.total_synced_time), + sync_remaining_time: state_sync.as_ref().map(|s| s.remaining_time), + sync_total_snapshots: state_sync.as_ref().map(|s| s.total_snapshots), + sync_chunk_process_avg_time: state_sync + .as_ref() + .map(|s| s.chunk_process_avg_time), + sync_snapshot_height: state_sync.as_ref().map(|s| s.snapshot_height), + sync_snapshot_chunks_count: state_sync + .as_ref() + .map(|s| s.snapshot_chunks_count), + sync_backfilled_blocks: state_sync.as_ref().map(|s| s.backfilled_blocks), + sync_backfill_blocks_total: state_sync + .as_ref() + .map(|s| s.backfill_blocks_total), }) } None => Err(Error::EmptyVersion), diff --git a/packages/rs-sdk/tests/fetch/evonode.rs b/packages/rs-sdk/tests/fetch/evonode.rs index f27a738c31..e38420e228 100644 --- a/packages/rs-sdk/tests/fetch/evonode.rs +++ b/packages/rs-sdk/tests/fetch/evonode.rs @@ -30,11 +30,11 @@ async fn test_evonode_status() { tracing::debug!(?status, ?address, "evonode status"); // Add assertions here to verify the status contents assert!( - status.latest_block_height > 0, + status.latest_block_height.unwrap_or_default() > 0, "latest block height must be positive" ); assert!( - status.pro_tx_hash.len() == ProTxHash::LEN, + status.pro_tx_hash.unwrap_or_default().len() == ProTxHash::LEN, "latest block hash must be non-empty" ); // Add more specific assertions based on expected status properties From 9a22712976f0f066ca9722f3fc99db639022af36 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Fri, 27 Sep 2024 12:03:53 +0200 Subject: [PATCH 17/23] test(sdk): regen test vectors --- ...a1c40d35547373d23f3ba329df2b6d993b374.json | Bin 12549 -> 12549 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/packages/rs-sdk/tests/vectors/test_evonode_status/msg_EvoNode_244e3005966550cd3cb2837d3bca1c40d35547373d23f3ba329df2b6d993b374.json b/packages/rs-sdk/tests/vectors/test_evonode_status/msg_EvoNode_244e3005966550cd3cb2837d3bca1c40d35547373d23f3ba329df2b6d993b374.json index c20459952525c3e46f5b54f7947af4b0a4d5d4ea..6eafe3314ea97f2673a8c9d30b73ea1b912ded8f 100644 GIT binary patch delta 33 kcmZooYE9a(Ltns9$HY>{)KJIN9D*iakXPIMPG6i60JF*pDgXcg delta 36 jcmZooYE9a(LtofH$JAKI#1er_4JRv#D{p?MFU|-6$eaoZ From 191240701eef04c6d4063c8e44156520a060eb73 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Fri, 27 Sep 2024 12:05:34 +0200 Subject: [PATCH 18/23] chore: more meaningful msg --- packages/rs-sdk/src/sdk.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rs-sdk/src/sdk.rs b/packages/rs-sdk/src/sdk.rs index ba35c1c022..cc4a2d94d1 100644 --- a/packages/rs-sdk/src/sdk.rs +++ b/packages/rs-sdk/src/sdk.rs @@ -519,7 +519,7 @@ impl Sdk { Ok(address_list_lock.clone()) } SdkInstance::Mock { .. } => { - todo!(); + unimplemented!("mock Sdk does not have address list") } } } From 5491d3fcc0caa1751ea08018f45d3f1b3eb8e127 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Fri, 27 Sep 2024 12:13:54 +0200 Subject: [PATCH 19/23] chore: fix features --- packages/rs-sdk/src/platform/types/evonode.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/rs-sdk/src/platform/types/evonode.rs b/packages/rs-sdk/src/platform/types/evonode.rs index 8425de1f7a..cc84470efe 100644 --- a/packages/rs-sdk/src/platform/types/evonode.rs +++ b/packages/rs-sdk/src/platform/types/evonode.rs @@ -11,6 +11,7 @@ use rs_dapi_client::transport::{ AppliedRequestSettings, PlatformGrpcClient, TransportClient, TransportRequest, }; use rs_dapi_client::{Address, ConnectionPool, RequestSettings}; +#[cfg(feature = "mocks")] use serde::{Deserialize, Serialize}; use std::fmt::Debug; From baa706fa72534ff898c6b8b8c13f1e46a7a86b4b Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Fri, 27 Sep 2024 12:46:58 +0200 Subject: [PATCH 20/23] chore: fix build --- packages/rs-sdk/src/platform/types/evonode.rs | 3 ++- packages/rs-sdk/src/sdk.rs | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/rs-sdk/src/platform/types/evonode.rs b/packages/rs-sdk/src/platform/types/evonode.rs index cc84470efe..bdf285357e 100644 --- a/packages/rs-sdk/src/platform/types/evonode.rs +++ b/packages/rs-sdk/src/platform/types/evonode.rs @@ -41,12 +41,13 @@ impl EvoNode { } } -#[cfg(feature = "mocks")] impl Mockable for EvoNode { + #[cfg(feature = "mocks")] fn mock_deserialize(data: &[u8]) -> Option { serde_json::de::from_slice(data).ok() } + #[cfg(feature = "mocks")] fn mock_serialize(&self) -> Option> { serde_json::ser::to_vec(self).ok() } diff --git a/packages/rs-sdk/src/sdk.rs b/packages/rs-sdk/src/sdk.rs index cc4a2d94d1..abd02e184c 100644 --- a/packages/rs-sdk/src/sdk.rs +++ b/packages/rs-sdk/src/sdk.rs @@ -518,6 +518,7 @@ impl Sdk { .map_err(|e| format!("Failed to read address list: {e}"))?; Ok(address_list_lock.clone()) } + #[cfg(feature = "mocks")] SdkInstance::Mock { .. } => { unimplemented!("mock Sdk does not have address list") } From b2caae831c734d2f9b959f7e515e04957bfcdeab Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Fri, 27 Sep 2024 15:23:58 +0200 Subject: [PATCH 21/23] chore: apply review feedback --- packages/rs-drive-proof-verifier/src/types.rs | 416 ++++++++++++------ .../rs-drive-proof-verifier/src/unproved.rs | 4 +- packages/rs-sdk/src/mock/requests.rs | 4 +- .../rs-sdk/src/platform/fetch_unproved.rs | 6 +- packages/rs-sdk/src/platform/types/evonode.rs | 2 +- packages/rs-sdk/tests/fetch/evonode.rs | 10 +- 6 files changed, 288 insertions(+), 154 deletions(-) diff --git a/packages/rs-drive-proof-verifier/src/types.rs b/packages/rs-drive-proof-verifier/src/types.rs index 6046366cf3..e7f0c3f04d 100644 --- a/packages/rs-drive-proof-verifier/src/types.rs +++ b/packages/rs-drive-proof-verifier/src/types.rs @@ -5,7 +5,7 @@ //! In this case, the [FromProof](crate::FromProof) trait is implemented for dedicated object type //! defined in this module. -use dapi_grpc::platform::v0::GetStatusResponse; +use dapi_grpc::platform::v0::{get_status_response, GetStatusResponse}; use dpp::data_contract::document_type::DocumentType; use dpp::fee::Credits; use dpp::platform_value::Value; @@ -26,7 +26,6 @@ use dpp::{ util::deserializer::ProtocolVersion, }; use drive::grovedb::Element; -use hex::ToHex; use std::collections::{BTreeMap, BTreeSet}; use crate::Error; @@ -618,158 +617,293 @@ pub struct ProposerBlockCountByRange(pub u64); #[cfg_attr(feature = "mocks", derive(serde::Serialize, serde::Deserialize))] pub struct ProposerBlockCountById(pub u64); -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] + +/// The status of an EvoNode. +pub struct EvoNodeStatus { + /// Information about protocol and software components versions. + pub version: Version, + /// Information about the node. + pub node: Node, + /// Layer 2 blockchain information + pub chain: Chain, + /// Node networking information. + pub network: Network, + /// Information about state synchronization progress. + pub state_sync: StateSync, + /// Information about current time used by the node. + pub time: Time, +} +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] + +/// Information about protocol and software components versions. +pub struct Version { + /// Information about software components versions. + pub software: Option, + /// Information about protocol version. + pub protocol: Option, +} +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] +/// Information about software components versions. +pub struct Software { + /// DAPI version, semver-compatible string. + pub dapi: String, + /// Drive version, semver-compatible string. + pub drive: Option, + /// Tenderdash version, semver-compatible string. + pub tenderdash: Option, +} +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] +/// Information about protocol-level versions used by the node +pub struct Protocol { + /// Tenderdash protocols version. + pub tenderdash: Option, + /// Drive protocols version. + pub drive: Option, +} +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] +/// Tenderdash protocol versions. +pub struct TenderdashProtocol { + /// Tenderdash P2P protocol version. + pub p2p: u32, + /// Tenderdash block protocol version. + pub block: u32, +} + +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] + +/// Drive protocol versions. +pub struct DriveProtocol { + /// Latest version supported by the node. + pub latest: u32, + /// Current version used by the node. + pub current: u32, +} +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] + +/// Information about current time used by the node. +pub struct Time { + /// Local time of the node. Unix timestamp since epoch. + pub local: u64, + /// Time of the last block. Unix timestamp since epoch. + pub block: Option, + /// Genesis time. Unix timestamp since epoch. + pub genesis: Option, + /// Epoch number + pub epoch: Option, +} + +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] + +/// Evo node identification information. +pub struct Node { + /// Node ID + pub id: Vec, + /// ProTxHash of masternode; None for full nodes + pub pro_tx_hash: Option>, +} +#[derive(Debug, Clone, Default)] #[cfg_attr( feature = "mocks", derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), platform_serialize(unversioned) )] -/// Status of a network node. -/// -/// Some fields may be `None` if the information is not available, eg. when the node is not fully functional. -pub struct EvonodeStatus { - /// The Identifier of the Evonode - pub pro_tx_hash: Option<[u8; ProTxHash::LEN]>, // We don't use ProTxHash as it doesn't implement Encode/Decode - /// The latest block height stored on the Evonode - pub latest_block_height: Option, - /// Version of DAPI service - pub dapi_version: Option, - /// Version of Drive-ABCI service - pub drive_version: Option, - /// Version of Tenderdash service - pub tenderdash_version: Option, - /// Tenderdash P2P protocol version information - pub tenderdash_p2p_protocol: Option, - /// Tenderdash block protocol version information - pub tenderdash_block_protocol: Option, - /// Latest supported Drive protocol version - pub drive_latest_protocol: Option, - /// Current active Drive protocol version - pub drive_current_protocol: Option, - /// Local time of the node, in seconds since the Unix epoch - pub local_time: Option, - /// Last block time, in seconds since the Unix epoch - pub block_time: Option, - /// Genesis time, in seconds since the Unix epoch - pub genesis_time: Option, - /// Time of the current epoch - pub epoch_time: Option, - /// Tenderdash node ID (public key derived from the private key) - pub tenderdash_node_id: Option>, - /// Information if the node is catching up the Platform chain (Tenderdash) - pub catching_up: Option, - /// Latest platfom block hash - pub latest_block_hash: Option>, - /// Latest platform app hash - pub latest_app_hash: Option>, - /// Earliest block hash stored by the node - pub earliest_block_hash: Option>, - /// Earliest app hash stored by the node - pub earliest_app_hash: Option>, - /// Earliest block height stored by the node - pub earliest_block_height: Option, - /// Maximum block height of the peers - pub max_peer_block_height: Option, - /// Core chain locked height used by the node + +/// Layer 2 blockchain information +pub struct Chain { + /// Whether the node is catching up with the network. + pub catching_up: bool, + /// Block hash of the latest block on the node. + pub latest_block_hash: Vec, + /// Latest app hash of the node, as visible in the latest block. + pub latest_app_hash: Vec, + /// Block hash of the earliest block available on the node. + pub earliest_block_hash: Vec, + /// Earliest app hash of the node, as visible in the earliest block. + pub earliest_app_hash: Vec, + /// Height of the latest block available on the node. + pub latest_block_height: u64, + /// Height of the earliest block available on the node. + pub earliest_block_height: u64, + /// Maximum block height of the peers connected to the node. + pub max_peer_block_height: u64, + /// Current core chain locked height. pub core_chain_locked_height: Option, - /// Network chain ID - pub chain_id: Option, - /// Number of peers in the addressbook - pub peers_count: Option, - /// Information if the node is listening for incoming connections - pub listening: Option, - /// State sync total time - pub sync_total_time: Option, - /// State sync remaining time - pub sync_remaining_time: Option, - /// State sync total snapshots - pub sync_total_snapshots: Option, - /// State sync chunk process average time - pub sync_chunk_process_avg_time: Option, - /// State sync snapshot height - pub sync_snapshot_height: Option, - /// State sync snapshot chunks count - pub sync_snapshot_chunks_count: Option, - /// State sync backfilled blocks - pub sync_backfilled_blocks: Option, - /// State sync backfill blocks total - pub sync_backfill_blocks_total: Option, -} - -impl TryFrom for EvonodeStatus { +} +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] +/// Node networking information. +pub struct Network { + /// Identifier of chain the node is member of. + pub chain_id: String, + /// Number of peers in the address book. + pub peers_count: u32, + /// Whether the node is listening for incoming connections. + pub listening: bool, +} + +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] +/// Information about state synchronization progress. +pub struct StateSync { + /// Total time spent on state synchronization. + pub total_synced_time: u64, + /// Estimated remaining time to finish state synchronization. + pub remaining_time: u64, + /// Total number of snapshots available. + pub total_snapshots: u32, + /// Average time spent on processing a chunk of snapshot data. + pub chunk_process_avg_time: u64, + /// Height of the latest snapshot. + pub snapshot_height: u64, + /// Number of chunks in the latest snapshot. + pub snapshot_chunks_count: u64, + /// Number of backfilled blocks. + pub backfilled_blocks: u64, + /// Total number of blocks to backfill. + pub backfill_blocks_total: u64, +} + +impl TryFrom for EvoNodeStatus { type Error = Error; + fn try_from(response: GetStatusResponse) -> Result { - use dapi_grpc::platform::v0::get_status_response::Version; match response.version { - Some(Version::V0(v0)) => { - let node = v0.node; - let chain = v0.chain; - let protx: Option<[u8; ProTxHash::LEN]> = node + Some(get_status_response::Version::V0(v0)) => { + let software = v0 + .version .as_ref() - .and_then(|n| { - n.pro_tx_hash.as_ref().map(|h| { - h.clone().try_into().map_err(|_| Error::ProtocolError { - error: format!( - "unvalid protxhash length: {:?}", - h.encode_hex::() - ), - }) - }) + .and_then(|v| v.software.clone()) + .map(|s| Software { + dapi: s.dapi, + drive: s.drive, + tenderdash: s.tenderdash, + }); + + let protocol = v0.version.and_then(|v| v.protocol).map(|p| Protocol { + tenderdash: p.tenderdash.map(|t| TenderdashProtocol { + p2p: t.p2p, + block: t.block, + }), + drive: p.drive.map(|d| DriveProtocol { + latest: d.latest, + current: d.current, + }), + }); + + let version = Version { software, protocol }; + + let node = v0 + .node + .map(|n| Node { + id: n.id, + pro_tx_hash: n.pro_tx_hash, }) - .transpose()?; - - let software = v0.version.as_ref().and_then(|v| v.software.clone()); - let protocol = v0.version.as_ref().and_then(|v| v.protocol.clone()); - - let tenderdash_protocol = protocol.as_ref().and_then(|p| p.tenderdash.clone()); - let drive_protocol = protocol.as_ref().and_then(|p| p.drive.clone()); - - let time = v0.time; - let network = v0.network; - let state_sync = v0.state_sync; + .unwrap_or_default(); + + let chain = v0 + .chain + .map(|c| Chain { + catching_up: c.catching_up, + latest_block_hash: c.latest_block_hash, + latest_app_hash: c.latest_app_hash, + earliest_block_hash: c.earliest_block_hash, + earliest_app_hash: c.earliest_app_hash, + latest_block_height: c.latest_block_height, + earliest_block_height: c.earliest_block_height, + max_peer_block_height: c.max_peer_block_height, + core_chain_locked_height: c.core_chain_locked_height, + }) + .unwrap_or_default(); + + let network = v0 + .network + .map(|n| Network { + chain_id: n.chain_id, + peers_count: n.peers_count, + listening: n.listening, + }) + .unwrap_or_default(); + + let state_sync = v0 + .state_sync + .map(|s| StateSync { + total_synced_time: s.total_synced_time, + remaining_time: s.remaining_time, + total_snapshots: s.total_snapshots, + chunk_process_avg_time: s.chunk_process_avg_time, + snapshot_height: s.snapshot_height, + snapshot_chunks_count: s.snapshot_chunks_count, + backfilled_blocks: s.backfilled_blocks, + backfill_blocks_total: s.backfill_blocks_total, + }) + .unwrap_or_default(); + + let time = v0 + .time + .map(|t| Time { + local: t.local, + block: t.block, + genesis: t.genesis, + epoch: t.epoch, + }) + .unwrap_or_default(); Ok(Self { - pro_tx_hash: protx, - latest_block_height: chain.as_ref().map(|c| c.latest_block_height), - dapi_version: software.as_ref().map(|s| s.dapi.clone()), - drive_version: software.as_ref().and_then(|s| s.drive.clone()), - tenderdash_version: software.as_ref().and_then(|s| s.tenderdash.clone()), - tenderdash_p2p_protocol: tenderdash_protocol.as_ref().map(|p| p.p2p), - tenderdash_block_protocol: tenderdash_protocol.as_ref().map(|p| p.block), - drive_latest_protocol: drive_protocol.as_ref().map(|d| d.latest), - drive_current_protocol: drive_protocol.as_ref().map(|d| d.current), - local_time: time.as_ref().map(|t| t.local), - block_time: time.as_ref().and_then(|t| t.block), - genesis_time: time.as_ref().and_then(|t| t.genesis), - epoch_time: time.as_ref().and_then(|t| t.epoch), - tenderdash_node_id: node.as_ref().map(|n| n.id.clone()), - catching_up: chain.as_ref().map(|c| c.catching_up), - latest_block_hash: chain.as_ref().map(|c| c.latest_block_hash.clone()), - latest_app_hash: chain.as_ref().map(|c| c.latest_app_hash.clone()), - earliest_block_hash: chain.as_ref().map(|c| c.earliest_block_hash.clone()), - earliest_app_hash: chain.as_ref().map(|c| c.earliest_app_hash.clone()), - earliest_block_height: chain.as_ref().map(|c| c.earliest_block_height), - max_peer_block_height: chain.as_ref().map(|c| c.max_peer_block_height), - core_chain_locked_height: chain - .as_ref() - .and_then(|c| c.core_chain_locked_height), - chain_id: network.as_ref().map(|n| n.chain_id.clone()), - peers_count: network.as_ref().map(|n| n.peers_count), - listening: network.as_ref().map(|n| n.listening), - sync_total_time: state_sync.as_ref().map(|s| s.total_synced_time), - sync_remaining_time: state_sync.as_ref().map(|s| s.remaining_time), - sync_total_snapshots: state_sync.as_ref().map(|s| s.total_snapshots), - sync_chunk_process_avg_time: state_sync - .as_ref() - .map(|s| s.chunk_process_avg_time), - sync_snapshot_height: state_sync.as_ref().map(|s| s.snapshot_height), - sync_snapshot_chunks_count: state_sync - .as_ref() - .map(|s| s.snapshot_chunks_count), - sync_backfilled_blocks: state_sync.as_ref().map(|s| s.backfilled_blocks), - sync_backfill_blocks_total: state_sync - .as_ref() - .map(|s| s.backfill_blocks_total), + version, + node, + chain, + network, + state_sync, + time, }) } None => Err(Error::EmptyVersion), diff --git a/packages/rs-drive-proof-verifier/src/unproved.rs b/packages/rs-drive-proof-verifier/src/unproved.rs index e27716ffa0..d9fd37009c 100644 --- a/packages/rs-drive-proof-verifier/src/unproved.rs +++ b/packages/rs-drive-proof-verifier/src/unproved.rs @@ -1,4 +1,4 @@ -use crate::types::{CurrentQuorumsInfo, EvonodeStatus}; +use crate::types::{CurrentQuorumsInfo, EvoNodeStatus}; use crate::Error; use dapi_grpc::platform::v0::ResponseMetadata; use dapi_grpc::platform::v0::{self as platform}; @@ -276,7 +276,7 @@ impl FromUnproved for CurrentQuorumsInfo } #[async_trait] -impl FromUnproved for EvonodeStatus { +impl FromUnproved for EvoNodeStatus { type Request = platform::GetStatusRequest; type Response = platform::GetStatusResponse; diff --git a/packages/rs-sdk/src/mock/requests.rs b/packages/rs-sdk/src/mock/requests.rs index 1c8d098895..d29e48d410 100644 --- a/packages/rs-sdk/src/mock/requests.rs +++ b/packages/rs-sdk/src/mock/requests.rs @@ -15,7 +15,7 @@ use dpp::{ voting::votes::{resource_vote::ResourceVote, Vote}, }; use drive_proof_verifier::types::{ - Contenders, ContestedResources, CurrentQuorumsInfo, ElementFetchRequestItem, EvonodeStatus, + Contenders, ContestedResources, CurrentQuorumsInfo, ElementFetchRequestItem, EvoNodeStatus, IdentityBalanceAndRevision, MasternodeProtocolVote, PrefundedSpecializedBalance, ProposerBlockCounts, RetrievedIntegerValue, TotalCreditsInPlatform, VotePollsGroupedByTimestamp, Voters, @@ -244,5 +244,5 @@ impl_mock_response!(VotePollsGroupedByTimestamp); impl_mock_response!(PrefundedSpecializedBalance); impl_mock_response!(TotalCreditsInPlatform); impl_mock_response!(ElementFetchRequestItem); -impl_mock_response!(EvonodeStatus); +impl_mock_response!(EvoNodeStatus); impl_mock_response!(CurrentQuorumsInfo); diff --git a/packages/rs-sdk/src/platform/fetch_unproved.rs b/packages/rs-sdk/src/platform/fetch_unproved.rs index 2ce3afc4f9..9e89ad163a 100644 --- a/packages/rs-sdk/src/platform/fetch_unproved.rs +++ b/packages/rs-sdk/src/platform/fetch_unproved.rs @@ -6,7 +6,7 @@ use dapi_grpc::platform::v0::{ self as platform_proto, GetStatusRequest, GetStatusResponse, ResponseMetadata, }; use dpp::{dashcore::Network, version::PlatformVersion}; -use drive_proof_verifier::types::EvonodeStatus; +use drive_proof_verifier::types::EvoNodeStatus; use drive_proof_verifier::unproved::FromUnproved; use rs_dapi_client::{transport::TransportRequest, DapiRequest, RequestSettings}; use std::fmt::Debug; @@ -88,13 +88,13 @@ impl FetchUnproved for drive_proof_verifier::types::CurrentQuorumsInfo { type Request = platform_proto::GetCurrentQuorumsInfoRequest; } -impl FetchUnproved for EvonodeStatus { +impl FetchUnproved for EvoNodeStatus { type Request = EvoNode; } // We need to delegate FromUnproved for the impl FetchUnproved for EvonodeStatus. #[async_trait::async_trait] -impl FromUnproved for EvonodeStatus { +impl FromUnproved for EvoNodeStatus { type Request = EvoNode; type Response = GetStatusResponse; diff --git a/packages/rs-sdk/src/platform/types/evonode.rs b/packages/rs-sdk/src/platform/types/evonode.rs index bdf285357e..f343eb1268 100644 --- a/packages/rs-sdk/src/platform/types/evonode.rs +++ b/packages/rs-sdk/src/platform/types/evonode.rs @@ -4,7 +4,7 @@ use dapi_grpc::mock::Mockable; use dapi_grpc::platform::v0::get_status_request::GetStatusRequestV0; use dapi_grpc::platform::v0::{self as proto, get_status_request, GetStatusRequest}; use dapi_grpc::tonic::IntoRequest; -pub use drive_proof_verifier::types::EvonodeStatus; +pub use drive_proof_verifier::types::EvoNodeStatus; use futures::future::BoxFuture; use futures::{FutureExt, TryFutureExt}; use rs_dapi_client::transport::{ diff --git a/packages/rs-sdk/tests/fetch/evonode.rs b/packages/rs-sdk/tests/fetch/evonode.rs index e38420e228..0d35d5be9f 100644 --- a/packages/rs-sdk/tests/fetch/evonode.rs +++ b/packages/rs-sdk/tests/fetch/evonode.rs @@ -3,7 +3,7 @@ use super::{common::setup_logs, config::Config}; use dash_sdk::platform::{types::evonode::EvoNode, FetchUnproved}; use dpp::dashcore::{hashes::Hash, ProTxHash}; -use drive_proof_verifier::types::EvonodeStatus; +use drive_proof_verifier::types::EvoNodeStatus; use http::Uri; use std::time::Duration; /// Given some existing evonode URIs, WHEN we connect to them, THEN we get status. @@ -22,7 +22,7 @@ async fn test_evonode_status() { let node = EvoNode::new(address.clone()); match timeout( Duration::from_secs(3), - EvonodeStatus::fetch_unproved(&sdk, node), + EvoNodeStatus::fetch_unproved(&sdk, node), ) .await { @@ -30,11 +30,11 @@ async fn test_evonode_status() { tracing::debug!(?status, ?address, "evonode status"); // Add assertions here to verify the status contents assert!( - status.latest_block_height.unwrap_or_default() > 0, + status.chain.latest_block_height > 0, "latest block height must be positive" ); assert!( - status.pro_tx_hash.unwrap_or_default().len() == ProTxHash::LEN, + status.node.pro_tx_hash.unwrap_or_default().len() == ProTxHash::LEN, "latest block hash must be non-empty" ); // Add more specific assertions based on expected status properties @@ -64,7 +64,7 @@ async fn test_evonode_status_refused() { let uri: Uri = "http://127.0.0.1:1".parse().unwrap(); let node = EvoNode::new(uri.clone().into()); - let result = EvonodeStatus::fetch_unproved(&sdk, node).await; + let result = EvoNodeStatus::fetch_unproved(&sdk, node).await; tracing::debug!(?result, ?uri, "evonode status"); assert!(result.is_err()); From 821af1fe1da83f19322bf1c288657d1e8008e4b4 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Fri, 27 Sep 2024 15:27:37 +0200 Subject: [PATCH 22/23] refactor: move EvoNodeStatus to separate file --- packages/rs-drive-proof-verifier/src/types.rs | 309 +----------------- .../src/types/evonode_status.rs | 304 +++++++++++++++++ 2 files changed, 312 insertions(+), 301 deletions(-) create mode 100644 packages/rs-drive-proof-verifier/src/types/evonode_status.rs diff --git a/packages/rs-drive-proof-verifier/src/types.rs b/packages/rs-drive-proof-verifier/src/types.rs index e7f0c3f04d..d49301720b 100644 --- a/packages/rs-drive-proof-verifier/src/types.rs +++ b/packages/rs-drive-proof-verifier/src/types.rs @@ -5,7 +5,10 @@ //! In this case, the [FromProof](crate::FromProof) trait is implemented for dedicated object type //! defined in this module. -use dapi_grpc::platform::v0::{get_status_response, GetStatusResponse}; +mod evonode_status; + +use dpp::block::block_info::BlockInfo; +use dpp::core_types::validator_set::ValidatorSet; use dpp::data_contract::document_type::DocumentType; use dpp::fee::Credits; use dpp::platform_value::Value; @@ -14,6 +17,7 @@ use dpp::version::PlatformVersion; pub use dpp::version::ProtocolVersionVoteCount; use dpp::voting::contender_structs::{Contender, ContenderWithSerializedDocument}; use dpp::voting::vote_choices::resource_vote_choice::ResourceVoteChoice; +use dpp::voting::vote_info_storage::contested_document_vote_poll_winner_info::ContestedDocumentVotePollWinnerInfo; use dpp::voting::vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePoll; use dpp::voting::vote_polls::VotePoll; use dpp::voting::votes::resource_vote::ResourceVote; @@ -25,15 +29,10 @@ use dpp::{ prelude::{DataContract, Identifier, IdentityPublicKey, Revision}, util::deserializer::ProtocolVersion, }; +use drive::grovedb::query_result_type::Path; use drive::grovedb::Element; use std::collections::{BTreeMap, BTreeSet}; -use crate::Error; -use dpp::block::block_info::BlockInfo; -use dpp::core_types::validator_set::ValidatorSet; -use dpp::voting::vote_info_storage::contested_document_vote_poll_winner_info::ContestedDocumentVotePollWinnerInfo; -use drive::grovedb::query_result_type::Path; - #[cfg(feature = "mocks")] use { bincode::{Decode, Encode}, @@ -42,6 +41,8 @@ use { platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}, }; +pub use evonode_status::*; + /// A data structure that holds a set of objects of a generic type `O`, indexed by a key of type `K`. /// /// This type is typically returned by functions that operate on multiple objects, such as fetching multiple objects @@ -616,297 +617,3 @@ pub struct ProposerBlockCountByRange(pub u64); #[derive(Debug)] #[cfg_attr(feature = "mocks", derive(serde::Serialize, serde::Deserialize))] pub struct ProposerBlockCountById(pub u64); - -#[derive(Debug, Clone, Default)] -#[cfg_attr( - feature = "mocks", - derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), - platform_serialize(unversioned) -)] - -/// The status of an EvoNode. -pub struct EvoNodeStatus { - /// Information about protocol and software components versions. - pub version: Version, - /// Information about the node. - pub node: Node, - /// Layer 2 blockchain information - pub chain: Chain, - /// Node networking information. - pub network: Network, - /// Information about state synchronization progress. - pub state_sync: StateSync, - /// Information about current time used by the node. - pub time: Time, -} -#[derive(Debug, Clone, Default)] -#[cfg_attr( - feature = "mocks", - derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), - platform_serialize(unversioned) -)] - -/// Information about protocol and software components versions. -pub struct Version { - /// Information about software components versions. - pub software: Option, - /// Information about protocol version. - pub protocol: Option, -} -#[derive(Debug, Clone, Default)] -#[cfg_attr( - feature = "mocks", - derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), - platform_serialize(unversioned) -)] -/// Information about software components versions. -pub struct Software { - /// DAPI version, semver-compatible string. - pub dapi: String, - /// Drive version, semver-compatible string. - pub drive: Option, - /// Tenderdash version, semver-compatible string. - pub tenderdash: Option, -} -#[derive(Debug, Clone, Default)] -#[cfg_attr( - feature = "mocks", - derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), - platform_serialize(unversioned) -)] -/// Information about protocol-level versions used by the node -pub struct Protocol { - /// Tenderdash protocols version. - pub tenderdash: Option, - /// Drive protocols version. - pub drive: Option, -} -#[derive(Debug, Clone, Default)] -#[cfg_attr( - feature = "mocks", - derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), - platform_serialize(unversioned) -)] -/// Tenderdash protocol versions. -pub struct TenderdashProtocol { - /// Tenderdash P2P protocol version. - pub p2p: u32, - /// Tenderdash block protocol version. - pub block: u32, -} - -#[derive(Debug, Clone, Default)] -#[cfg_attr( - feature = "mocks", - derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), - platform_serialize(unversioned) -)] - -/// Drive protocol versions. -pub struct DriveProtocol { - /// Latest version supported by the node. - pub latest: u32, - /// Current version used by the node. - pub current: u32, -} -#[derive(Debug, Clone, Default)] -#[cfg_attr( - feature = "mocks", - derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), - platform_serialize(unversioned) -)] - -/// Information about current time used by the node. -pub struct Time { - /// Local time of the node. Unix timestamp since epoch. - pub local: u64, - /// Time of the last block. Unix timestamp since epoch. - pub block: Option, - /// Genesis time. Unix timestamp since epoch. - pub genesis: Option, - /// Epoch number - pub epoch: Option, -} - -#[derive(Debug, Clone, Default)] -#[cfg_attr( - feature = "mocks", - derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), - platform_serialize(unversioned) -)] - -/// Evo node identification information. -pub struct Node { - /// Node ID - pub id: Vec, - /// ProTxHash of masternode; None for full nodes - pub pro_tx_hash: Option>, -} -#[derive(Debug, Clone, Default)] -#[cfg_attr( - feature = "mocks", - derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), - platform_serialize(unversioned) -)] - -/// Layer 2 blockchain information -pub struct Chain { - /// Whether the node is catching up with the network. - pub catching_up: bool, - /// Block hash of the latest block on the node. - pub latest_block_hash: Vec, - /// Latest app hash of the node, as visible in the latest block. - pub latest_app_hash: Vec, - /// Block hash of the earliest block available on the node. - pub earliest_block_hash: Vec, - /// Earliest app hash of the node, as visible in the earliest block. - pub earliest_app_hash: Vec, - /// Height of the latest block available on the node. - pub latest_block_height: u64, - /// Height of the earliest block available on the node. - pub earliest_block_height: u64, - /// Maximum block height of the peers connected to the node. - pub max_peer_block_height: u64, - /// Current core chain locked height. - pub core_chain_locked_height: Option, -} -#[derive(Debug, Clone, Default)] -#[cfg_attr( - feature = "mocks", - derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), - platform_serialize(unversioned) -)] -/// Node networking information. -pub struct Network { - /// Identifier of chain the node is member of. - pub chain_id: String, - /// Number of peers in the address book. - pub peers_count: u32, - /// Whether the node is listening for incoming connections. - pub listening: bool, -} - -#[derive(Debug, Clone, Default)] -#[cfg_attr( - feature = "mocks", - derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), - platform_serialize(unversioned) -)] -/// Information about state synchronization progress. -pub struct StateSync { - /// Total time spent on state synchronization. - pub total_synced_time: u64, - /// Estimated remaining time to finish state synchronization. - pub remaining_time: u64, - /// Total number of snapshots available. - pub total_snapshots: u32, - /// Average time spent on processing a chunk of snapshot data. - pub chunk_process_avg_time: u64, - /// Height of the latest snapshot. - pub snapshot_height: u64, - /// Number of chunks in the latest snapshot. - pub snapshot_chunks_count: u64, - /// Number of backfilled blocks. - pub backfilled_blocks: u64, - /// Total number of blocks to backfill. - pub backfill_blocks_total: u64, -} - -impl TryFrom for EvoNodeStatus { - type Error = Error; - - fn try_from(response: GetStatusResponse) -> Result { - match response.version { - Some(get_status_response::Version::V0(v0)) => { - let software = v0 - .version - .as_ref() - .and_then(|v| v.software.clone()) - .map(|s| Software { - dapi: s.dapi, - drive: s.drive, - tenderdash: s.tenderdash, - }); - - let protocol = v0.version.and_then(|v| v.protocol).map(|p| Protocol { - tenderdash: p.tenderdash.map(|t| TenderdashProtocol { - p2p: t.p2p, - block: t.block, - }), - drive: p.drive.map(|d| DriveProtocol { - latest: d.latest, - current: d.current, - }), - }); - - let version = Version { software, protocol }; - - let node = v0 - .node - .map(|n| Node { - id: n.id, - pro_tx_hash: n.pro_tx_hash, - }) - .unwrap_or_default(); - - let chain = v0 - .chain - .map(|c| Chain { - catching_up: c.catching_up, - latest_block_hash: c.latest_block_hash, - latest_app_hash: c.latest_app_hash, - earliest_block_hash: c.earliest_block_hash, - earliest_app_hash: c.earliest_app_hash, - latest_block_height: c.latest_block_height, - earliest_block_height: c.earliest_block_height, - max_peer_block_height: c.max_peer_block_height, - core_chain_locked_height: c.core_chain_locked_height, - }) - .unwrap_or_default(); - - let network = v0 - .network - .map(|n| Network { - chain_id: n.chain_id, - peers_count: n.peers_count, - listening: n.listening, - }) - .unwrap_or_default(); - - let state_sync = v0 - .state_sync - .map(|s| StateSync { - total_synced_time: s.total_synced_time, - remaining_time: s.remaining_time, - total_snapshots: s.total_snapshots, - chunk_process_avg_time: s.chunk_process_avg_time, - snapshot_height: s.snapshot_height, - snapshot_chunks_count: s.snapshot_chunks_count, - backfilled_blocks: s.backfilled_blocks, - backfill_blocks_total: s.backfill_blocks_total, - }) - .unwrap_or_default(); - - let time = v0 - .time - .map(|t| Time { - local: t.local, - block: t.block, - genesis: t.genesis, - epoch: t.epoch, - }) - .unwrap_or_default(); - - Ok(Self { - version, - node, - chain, - network, - state_sync, - time, - }) - } - None => Err(Error::EmptyVersion), - } - } -} diff --git a/packages/rs-drive-proof-verifier/src/types/evonode_status.rs b/packages/rs-drive-proof-verifier/src/types/evonode_status.rs new file mode 100644 index 0000000000..39f8ac902c --- /dev/null +++ b/packages/rs-drive-proof-verifier/src/types/evonode_status.rs @@ -0,0 +1,304 @@ +//! Status details of EvoNode, like version, current height, etc. + +use crate::Error; +use dapi_grpc::platform::v0::{get_status_response, GetStatusResponse}; + +#[cfg(feature = "mocks")] +use { + bincode::{Decode, Encode}, + dpp::{version as platform_version, ProtocolError}, + platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}, +}; + +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] +/// The status of an EvoNode. +pub struct EvoNodeStatus { + /// Information about protocol and software components versions. + pub version: Version, + /// Information about the node. + pub node: Node, + /// Layer 2 blockchain information + pub chain: Chain, + /// Node networking information. + pub network: Network, + /// Information about state synchronization progress. + pub state_sync: StateSync, + /// Information about current time used by the node. + pub time: Time, +} +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] + +/// Information about protocol and software components versions. +pub struct Version { + /// Information about software components versions. + pub software: Option, + /// Information about protocol version. + pub protocol: Option, +} +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] +/// Information about software components versions. +pub struct Software { + /// DAPI version, semver-compatible string. + pub dapi: String, + /// Drive version, semver-compatible string. + pub drive: Option, + /// Tenderdash version, semver-compatible string. + pub tenderdash: Option, +} +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] +/// Information about protocol-level versions used by the node +pub struct Protocol { + /// Tenderdash protocols version. + pub tenderdash: Option, + /// Drive protocols version. + pub drive: Option, +} +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] +/// Tenderdash protocol versions. +pub struct TenderdashProtocol { + /// Tenderdash P2P protocol version. + pub p2p: u32, + /// Tenderdash block protocol version. + pub block: u32, +} + +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] + +/// Drive protocol versions. +pub struct DriveProtocol { + /// Latest version supported by the node. + pub latest: u32, + /// Current version used by the node. + pub current: u32, +} +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] + +/// Information about current time used by the node. +pub struct Time { + /// Local time of the node. Unix timestamp since epoch. + pub local: u64, + /// Time of the last block. Unix timestamp since epoch. + pub block: Option, + /// Genesis time. Unix timestamp since epoch. + pub genesis: Option, + /// Epoch number + pub epoch: Option, +} + +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] + +/// Evo node identification information. +pub struct Node { + /// Node ID + pub id: Vec, + /// ProTxHash of masternode; None for full nodes + pub pro_tx_hash: Option>, +} +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] + +/// Layer 2 blockchain information +pub struct Chain { + /// Whether the node is catching up with the network. + pub catching_up: bool, + /// Block hash of the latest block on the node. + pub latest_block_hash: Vec, + /// Latest app hash of the node, as visible in the latest block. + pub latest_app_hash: Vec, + /// Block hash of the earliest block available on the node. + pub earliest_block_hash: Vec, + /// Earliest app hash of the node, as visible in the earliest block. + pub earliest_app_hash: Vec, + /// Height of the latest block available on the node. + pub latest_block_height: u64, + /// Height of the earliest block available on the node. + pub earliest_block_height: u64, + /// Maximum block height of the peers connected to the node. + pub max_peer_block_height: u64, + /// Current core chain locked height. + pub core_chain_locked_height: Option, +} +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] +/// Node networking information. +pub struct Network { + /// Identifier of chain the node is member of. + pub chain_id: String, + /// Number of peers in the address book. + pub peers_count: u32, + /// Whether the node is listening for incoming connections. + pub listening: bool, +} + +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] +/// Information about state synchronization progress. +pub struct StateSync { + /// Total time spent on state synchronization. + pub total_synced_time: u64, + /// Estimated remaining time to finish state synchronization. + pub remaining_time: u64, + /// Total number of snapshots available. + pub total_snapshots: u32, + /// Average time spent on processing a chunk of snapshot data. + pub chunk_process_avg_time: u64, + /// Height of the latest snapshot. + pub snapshot_height: u64, + /// Number of chunks in the latest snapshot. + pub snapshot_chunks_count: u64, + /// Number of backfilled blocks. + pub backfilled_blocks: u64, + /// Total number of blocks to backfill. + pub backfill_blocks_total: u64, +} + +impl TryFrom for EvoNodeStatus { + type Error = Error; + + fn try_from(response: GetStatusResponse) -> Result { + match response.version { + Some(get_status_response::Version::V0(v0)) => { + let software = v0 + .version + .as_ref() + .and_then(|v| v.software.clone()) + .map(|s| Software { + dapi: s.dapi, + drive: s.drive, + tenderdash: s.tenderdash, + }); + + let protocol = v0.version.and_then(|v| v.protocol).map(|p| Protocol { + tenderdash: p.tenderdash.map(|t| TenderdashProtocol { + p2p: t.p2p, + block: t.block, + }), + drive: p.drive.map(|d| DriveProtocol { + latest: d.latest, + current: d.current, + }), + }); + + let version = Version { software, protocol }; + + let node = v0 + .node + .map(|n| Node { + id: n.id, + pro_tx_hash: n.pro_tx_hash, + }) + .unwrap_or_default(); + + let chain = v0 + .chain + .map(|c| Chain { + catching_up: c.catching_up, + latest_block_hash: c.latest_block_hash, + latest_app_hash: c.latest_app_hash, + earliest_block_hash: c.earliest_block_hash, + earliest_app_hash: c.earliest_app_hash, + latest_block_height: c.latest_block_height, + earliest_block_height: c.earliest_block_height, + max_peer_block_height: c.max_peer_block_height, + core_chain_locked_height: c.core_chain_locked_height, + }) + .unwrap_or_default(); + + let network = v0 + .network + .map(|n| Network { + chain_id: n.chain_id, + peers_count: n.peers_count, + listening: n.listening, + }) + .unwrap_or_default(); + + let state_sync = v0 + .state_sync + .map(|s| StateSync { + total_synced_time: s.total_synced_time, + remaining_time: s.remaining_time, + total_snapshots: s.total_snapshots, + chunk_process_avg_time: s.chunk_process_avg_time, + snapshot_height: s.snapshot_height, + snapshot_chunks_count: s.snapshot_chunks_count, + backfilled_blocks: s.backfilled_blocks, + backfill_blocks_total: s.backfill_blocks_total, + }) + .unwrap_or_default(); + + let time = v0 + .time + .map(|t| Time { + local: t.local, + block: t.block, + genesis: t.genesis, + epoch: t.epoch, + }) + .unwrap_or_default(); + + Ok(Self { + version, + node, + chain, + network, + state_sync, + time, + }) + } + None => Err(Error::EmptyVersion), + } + } +} From 7f9c668ec858c534ceb5027a2f1c5885ddf0f84e Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Fri, 27 Sep 2024 16:01:25 +0200 Subject: [PATCH 23/23] refactor: apply rabbit's feedback --- .../src/types/evonode_status.rs | 148 +++++++++++++----- packages/rs-sdk/src/platform/types/evonode.rs | 4 +- 2 files changed, 115 insertions(+), 37 deletions(-) diff --git a/packages/rs-drive-proof-verifier/src/types/evonode_status.rs b/packages/rs-drive-proof-verifier/src/types/evonode_status.rs index 39f8ac902c..87831de0f6 100644 --- a/packages/rs-drive-proof-verifier/src/types/evonode_status.rs +++ b/packages/rs-drive-proof-verifier/src/types/evonode_status.rs @@ -1,7 +1,10 @@ //! Status details of EvoNode, like version, current height, etc. use crate::Error; -use dapi_grpc::platform::v0::{get_status_response, GetStatusResponse}; +use dapi_grpc::platform::v0::{ + get_status_response::{self}, + GetStatusResponse, +}; #[cfg(feature = "mocks")] use { @@ -208,7 +211,22 @@ impl TryFrom for EvoNodeStatus { type Error = Error; fn try_from(response: GetStatusResponse) -> Result { - match response.version { + Ok(Self { + version: Version::try_from(&response)?, + node: Node::try_from(&response)?, + chain: Chain::try_from(&response)?, + network: Network::try_from(&response)?, + state_sync: StateSync::try_from(&response)?, + time: Time::try_from(&response)?, + }) + } +} + +impl TryFrom<&GetStatusResponse> for Version { + type Error = Error; + + fn try_from(response: &GetStatusResponse) -> Result { + match &response.version { Some(get_status_response::Version::V0(v0)) => { let software = v0 .version @@ -220,54 +238,109 @@ impl TryFrom for EvoNodeStatus { tenderdash: s.tenderdash, }); - let protocol = v0.version.and_then(|v| v.protocol).map(|p| Protocol { - tenderdash: p.tenderdash.map(|t| TenderdashProtocol { - p2p: t.p2p, - block: t.block, - }), - drive: p.drive.map(|d| DriveProtocol { - latest: d.latest, - current: d.current, - }), - }); + let protocol = v0 + .version + .as_ref() + .and_then(|v| v.protocol.clone()) + .map(|p| Protocol { + tenderdash: p.tenderdash.map(|t| TenderdashProtocol { + p2p: t.p2p, + block: t.block, + }), + drive: p.drive.map(|d| DriveProtocol { + latest: d.latest, + current: d.current, + }), + }); + + Ok(Self { software, protocol }) + } + _ => Err(Error::EmptyVersion), + } + } +} - let version = Version { software, protocol }; +impl TryFrom<&GetStatusResponse> for Node { + type Error = Error; + fn try_from(response: &GetStatusResponse) -> Result { + match &response.version { + Some(get_status_response::Version::V0(v0)) => { let node = v0 .node - .map(|n| Node { - id: n.id, - pro_tx_hash: n.pro_tx_hash, + .as_ref() + .map(|n| Self { + id: n.id.clone(), + pro_tx_hash: n.pro_tx_hash.clone(), }) .unwrap_or_default(); + Ok(node) + } + _ => Err(Error::EmptyVersion), + } + } +} + +impl TryFrom<&GetStatusResponse> for Chain { + type Error = Error; + fn try_from(response: &GetStatusResponse) -> Result { + match &response.version { + Some(get_status_response::Version::V0(v0)) => { let chain = v0 .chain - .map(|c| Chain { + .as_ref() + .map(|c| Self { catching_up: c.catching_up, - latest_block_hash: c.latest_block_hash, - latest_app_hash: c.latest_app_hash, - earliest_block_hash: c.earliest_block_hash, - earliest_app_hash: c.earliest_app_hash, + latest_block_hash: c.latest_block_hash.clone(), + latest_app_hash: c.latest_app_hash.clone(), + earliest_block_hash: c.earliest_block_hash.clone(), + earliest_app_hash: c.earliest_app_hash.clone(), latest_block_height: c.latest_block_height, earliest_block_height: c.earliest_block_height, max_peer_block_height: c.max_peer_block_height, core_chain_locked_height: c.core_chain_locked_height, }) .unwrap_or_default(); + Ok(chain) + } + _ => Err(Error::EmptyVersion), + } + } +} +impl TryFrom<&GetStatusResponse> for Network { + type Error = Error; + + fn try_from(response: &GetStatusResponse) -> Result { + match &response.version { + Some(get_status_response::Version::V0(v0)) => { let network = v0 .network - .map(|n| Network { - chain_id: n.chain_id, + .as_ref() + .map(|n| Self { + chain_id: n.chain_id.clone(), peers_count: n.peers_count, listening: n.listening, }) .unwrap_or_default(); + Ok(network) + } + _ => Err(Error::EmptyVersion), + } + } +} +impl TryFrom<&GetStatusResponse> for StateSync { + type Error = Error; + + fn try_from(response: &GetStatusResponse) -> Result { + match &response.version { + Some(get_status_response::Version::V0(v0)) => { let state_sync = v0 .state_sync - .map(|s| StateSync { + .as_ref() + .map(|s| Self { total_synced_time: s.total_synced_time, remaining_time: s.remaining_time, total_snapshots: s.total_snapshots, @@ -278,27 +351,32 @@ impl TryFrom for EvoNodeStatus { backfill_blocks_total: s.backfill_blocks_total, }) .unwrap_or_default(); + Ok(state_sync) + } + _ => Err(Error::EmptyVersion), + } + } +} + +impl TryFrom<&GetStatusResponse> for Time { + type Error = Error; + fn try_from(response: &GetStatusResponse) -> Result { + match &response.version { + Some(get_status_response::Version::V0(v0)) => { let time = v0 .time - .map(|t| Time { + .as_ref() + .map(|t| Self { local: t.local, block: t.block, genesis: t.genesis, epoch: t.epoch, }) .unwrap_or_default(); - - Ok(Self { - version, - node, - chain, - network, - state_sync, - time, - }) + Ok(time) } - None => Err(Error::EmptyVersion), + _ => Err(Error::EmptyVersion), } } } diff --git a/packages/rs-sdk/src/platform/types/evonode.rs b/packages/rs-sdk/src/platform/types/evonode.rs index f343eb1268..01c0630b49 100644 --- a/packages/rs-sdk/src/platform/types/evonode.rs +++ b/packages/rs-sdk/src/platform/types/evonode.rs @@ -21,13 +21,13 @@ use std::fmt::Debug; /// /// ```rust,no_run /// use dash_sdk::{platform::types::evonode::EvoNode,platform::FetchUnproved, Sdk}; -/// use drive_proof_verifier::types::EvonodeStatus; +/// use drive_proof_verifier::types::EvoNodeStatus; /// use futures::executor::block_on; /// /// let sdk = Sdk::new_mock(); /// let uri: http::Uri = "http://127.0.0.1:1".parse().unwrap(); /// let node = EvoNode::new(uri.into()); -/// let status = block_on(EvonodeStatus::fetch_unproved(&sdk, node)).unwrap(); +/// let status = block_on(EvoNodeStatus::fetch_unproved(&sdk, node)).unwrap(); /// ``` #[derive(Debug, Clone)]