Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat(sdk): get node status #2139

Merged
merged 28 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
c044004
feat: get node statuses in sdk
pauldelucia Sep 18, 2024
94235ee
fixes
pauldelucia Sep 18, 2024
45ebe6c
error handling
pauldelucia Sep 18, 2024
6d1af4c
return references instead of clones
pauldelucia Sep 19, 2024
7f098fc
fix
pauldelucia Sep 19, 2024
ea65946
Merge branch 'v1.3-dev' into feat/get-node-status-in-sdk
pauldelucia Sep 19, 2024
af067ed
Merge branch 'v1.3-dev' into feat/get-node-status-in-sdk
pauldelucia Sep 19, 2024
e4e26c4
Merge branch 'v1.4-dev' into feat/get-node-status-in-sdk
lklimek Sep 25, 2024
5537a05
Merge branch 'v1.4-dev' into feat/get-node-status-in-sdk
lklimek Sep 26, 2024
e409956
refactor
lklimek Sep 26, 2024
fa4bb87
chore(sdk): status tests
lklimek Sep 26, 2024
bad801c
chore: minor improvements
lklimek Sep 26, 2024
18d3df8
refactor(dapi-client): impl IntoIterator for address list
lklimek Sep 27, 2024
9a86b8f
fix: get status connecting to wrong node
lklimek Sep 27, 2024
beadf24
chore: fix dump of evonode
lklimek Sep 27, 2024
4263ed9
chore: fix mocking
lklimek Sep 27, 2024
99335cd
chore:remove unused bincode
lklimek Sep 27, 2024
e58541d
test(e2e): test vectors
lklimek Sep 27, 2024
ddbda44
chore: impl From<EvoNode> for GetStatusRequest
lklimek Sep 27, 2024
1ff4fce
feat(sdk): EvonodeStatus additional fields
lklimek Sep 27, 2024
9a22712
test(sdk): regen test vectors
lklimek Sep 27, 2024
1912407
chore: more meaningful msg
lklimek Sep 27, 2024
5491d3f
chore: fix features
lklimek Sep 27, 2024
c66c815
Merge remote-tracking branch 'origin/v1.4-dev' into feat/get-node-sta…
lklimek Sep 27, 2024
baa706f
chore: fix build
lklimek Sep 27, 2024
b2caae8
chore: apply review feedback
lklimek Sep 27, 2024
821af1f
refactor: move EvoNodeStatus to separate file
lklimek Sep 27, 2024
7f9c668
refactor: apply rabbit's feedback
lklimek Sep 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions packages/dapi-grpc/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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 {
Expand Down
11 changes: 10 additions & 1 deletion packages/rs-dapi-client/src/address_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Address>,
base_ban_period: Duration,
Expand Down Expand Up @@ -221,3 +221,12 @@ impl FromIterator<Uri> for AddressList {
address_list
}
}

impl IntoIterator for AddressList {
type Item = Address;
type IntoIter = std::collections::hash_set::IntoIter<Address>;

fn into_iter(self) -> Self::IntoIter {
self.addresses.into_iter()
}
}
5 changes: 5 additions & 0 deletions packages/rs-dapi-client/src/dapi_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ impl DapiClient {
dump_dir: None,
}
}

/// Return the [DapiClient] address list.
pub fn address_list(&self) -> &Arc<RwLock<AddressList>> {
&self.address_list
}
}

#[async_trait]
Expand Down
1 change: 0 additions & 1 deletion packages/rs-dapi-client/src/dump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@ impl DapiClient {
response: &MockResult<R>,
dump_dir: Option<PathBuf>,
) where
R: Mockable,
<R as TransportRequest>::Response: Mockable,
{
let path = match dump_dir {
Expand Down
1 change: 1 addition & 0 deletions packages/rs-dapi-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
9 changes: 9 additions & 0 deletions packages/rs-dapi-client/src/transport/grpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,3 +421,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
);
13 changes: 7 additions & 6 deletions packages/rs-drive-proof-verifier/src/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ use crate::from_request::TryFromRequest;
use crate::provider::DataContractProvider;
use crate::verify::verify_tenderdash_proof;
use crate::{types, types::*, ContextProvider, Error};
use dapi_grpc::platform::v0::get_evonodes_proposed_epoch_blocks_by_range_request::get_evonodes_proposed_epoch_blocks_by_range_request_v0::Start;
use dapi_grpc::platform::v0::get_identities_contract_keys_request::GetIdentitiesContractKeysRequestV0;
use dapi_grpc::platform::v0::get_path_elements_request::GetPathElementsRequestV0;
use dapi_grpc::platform::v0::get_protocol_version_upgrade_vote_status_request::{
self, GetProtocolVersionUpgradeVoteStatusRequestV0,
};
use dapi_grpc::platform::v0::security_level_map::KeyKindRequestType as GrpcKeyKind;
use dapi_grpc::platform::v0::{get_contested_resource_identity_votes_request, get_data_contract_history_request, get_data_contract_request, get_data_contracts_request, get_epochs_info_request, get_evonodes_proposed_epoch_blocks_by_ids_request, get_evonodes_proposed_epoch_blocks_by_range_request, get_identities_balances_request, get_identities_contract_keys_request, get_identity_balance_and_revision_request, get_identity_balance_request, get_identity_by_public_key_hash_request, get_identity_contract_nonce_request, get_identity_keys_request, get_identity_nonce_request, get_identity_request, get_path_elements_request, get_prefunded_specialized_balance_request, GetContestedResourceVotersForIdentityRequest, GetContestedResourceVotersForIdentityResponse, GetPathElementsRequest, GetPathElementsResponse, GetProtocolVersionUpgradeStateRequest, GetProtocolVersionUpgradeStateResponse, GetProtocolVersionUpgradeVoteStatusRequest, GetProtocolVersionUpgradeVoteStatusResponse, Proof, ResponseMetadata};
use dapi_grpc::platform::v0::{
get_contested_resource_identity_votes_request, get_data_contract_history_request, get_data_contract_request, get_data_contracts_request, get_epochs_info_request, get_evonodes_proposed_epoch_blocks_by_ids_request, get_evonodes_proposed_epoch_blocks_by_range_request, get_identities_balances_request, get_identities_contract_keys_request, get_identity_balance_and_revision_request, get_identity_balance_request, get_identity_by_public_key_hash_request, get_identity_contract_nonce_request, get_identity_keys_request, get_identity_nonce_request, get_identity_request, get_path_elements_request, get_prefunded_specialized_balance_request, GetContestedResourceVotersForIdentityRequest, GetContestedResourceVotersForIdentityResponse, GetPathElementsRequest, GetPathElementsResponse, GetProtocolVersionUpgradeStateRequest, GetProtocolVersionUpgradeStateResponse, GetProtocolVersionUpgradeVoteStatusRequest, GetProtocolVersionUpgradeVoteStatusResponse, Proof, ResponseMetadata
};
use dapi_grpc::platform::{
v0::{self as platform, key_request_type, KeyRequestType as GrpcKeyType},
VersionedGrpcResponse,
Expand All @@ -35,15 +38,14 @@ use drive::drive::identity::key::fetch::{
use drive::drive::Drive;
use drive::error::proof::ProofError;
use drive::query::contested_resource_votes_given_by_identity_query::ContestedResourceVotesGivenByIdentityQuery;
use drive::query::proposer_block_count_query::ProposerQueryType;
use drive::query::vote_poll_contestant_votes_query::ContestedDocumentVotePollVotesDriveQuery;
use drive::query::vote_poll_vote_state_query::ContestedDocumentVotePollDriveQuery;
use drive::query::vote_polls_by_document_type_query::VotePollsByDocumentTypeQuery;
use drive::query::{DriveDocumentQuery, VotePollsByEndDateDriveQuery};
use std::array::TryFromSliceError;
use std::collections::BTreeMap;
use std::num::TryFromIntError;
use dapi_grpc::platform::v0::get_evonodes_proposed_epoch_blocks_by_range_request::get_evonodes_proposed_epoch_blocks_by_range_request_v0::Start;
use drive::query::proposer_block_count_query::ProposerQueryType;

/// Parse and verify the received proof and retrieve the requested object, if any.
///
Expand Down Expand Up @@ -78,7 +80,7 @@ pub trait FromProof<Req> {
///
/// * `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<Self::Request>, O: Into<Self::Response>>(
request: I,
Expand Down Expand Up @@ -108,7 +110,7 @@ pub trait FromProof<Req> {
///
/// * `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<Self::Request>, O: Into<Self::Response>>(
request: I,
Expand Down Expand Up @@ -1714,7 +1716,6 @@ impl FromProof<platform::GetTotalCreditsInPlatformRequest> for TotalCreditsInPla
))
}
}

impl FromProof<platform::GetEvonodesProposedEpochBlocksByIdsRequest> for ProposerBlockCounts {
type Request = platform::GetEvonodesProposedEpochBlocksByIdsRequest;
type Response = platform::GetEvonodesProposedEpochBlocksResponse;
Expand Down
54 changes: 53 additions & 1 deletion packages/rs-drive-proof-verifier/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -27,11 +28,12 @@ use dpp::{
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::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},
Expand Down Expand Up @@ -614,3 +616,53 @@ 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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's have it nested as proto otherwise it's too messy

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

/// The Identifier of the Evonode
pub pro_tx_hash: [u8; ProTxHash::LEN],
/// The latest block height stored on the Evonode
pub latest_block_height: u64,
}

impl TryFrom<GetStatusResponse> for EvonodeStatus {
type Error = Error;
fn try_from(response: GetStatusResponse) -> Result<Self, Self::Error> {
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();

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,
})
}
None => Err(Error::EmptyVersion),
}
lklimek marked this conversation as resolved.
Show resolved Hide resolved
}
}
23 changes: 22 additions & 1 deletion packages/rs-drive-proof-verifier/src/unproved.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -273,3 +274,23 @@ impl FromUnproved<platform::GetCurrentQuorumsInfoRequest> for CurrentQuorumsInfo
Ok((Some(info), metadata))
}
}

#[async_trait]
impl FromUnproved<platform::GetStatusRequest> for EvonodeStatus {
type Request = platform::GetStatusRequest;
type Response = platform::GetStatusResponse;

fn maybe_from_unproved_with_metadata<I: Into<Self::Request>, O: Into<Self::Response>>(
_request: I,
response: O,
_network: Network,
_platform_version: &PlatformVersion,
) -> Result<(Option<Self>, ResponseMetadata), Error>
where
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()))
}
}
2 changes: 1 addition & 1 deletion packages/rs-sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ serde = { version = "1.0.197", default-features = false, features = [
], optional = true }
serde_json = { version = "1.0", features = ["preserve_order"], optional = true }
tracing = { version = "0.1.40" }
hex = { version = "0.4.3"}
hex = { version = "0.4.3" }
dotenvy = { version = "0.15.7", optional = true }
envy = { version = "0.4.2", optional = true }
futures = { version = "0.3.30" }
Expand Down
8 changes: 4 additions & 4 deletions packages/rs-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand All @@ -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
Expand All @@ -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`,
Expand Down
4 changes: 2 additions & 2 deletions packages/rs-sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion packages/rs-sdk/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ 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;
Expand Down
9 changes: 6 additions & 3 deletions packages/rs-sdk/src/mock/requests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ 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;

Expand Down Expand Up @@ -243,3 +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!(CurrentQuorumsInfo);
8 changes: 6 additions & 2 deletions packages/rs-sdk/src/mock/sdk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -201,9 +204,10 @@ impl MockDashPlatformSdk {
self.load_expectation::<proto::GetTotalCreditsInPlatformRequest>(filename)
.await?
}
"EvoNode" => self.load_expectation::<EvoNode>(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()
)))
Expand Down
1 change: 1 addition & 0 deletions packages/rs-sdk/src/platform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
};
Loading
Loading