Skip to content

feat(sdk): asset lock quorum and core locked height verification #2030

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

Open
wants to merge 35 commits into
base: v2.0-dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
b3f5f17
feat(sdk): asset lock quorum verify against platform
lklimek Jul 25, 2024
9de013f
feat(sdk)!: params of dash networks - testnet, mainnet, etc
lklimek Aug 15, 2024
6362883
feat(sdk): network type, continued
lklimek Aug 15, 2024
f984ced
feat: asset lock verify
lklimek Aug 15, 2024
bff31d5
refactor(dapi-client): replace CanRetry.is_node_failure with !CanRetr…
lklimek Aug 15, 2024
e3a5538
feat(sdk): Error implements CanRetry
lklimek Aug 15, 2024
4df0c40
fix(dapi-grpc): GetEpochsInfoRequest not marked as versioned
lklimek Aug 15, 2024
f41f2bc
test(sdk): asset locks verify tests, WIP
lklimek Aug 15, 2024
3517779
fix(sdk): local devnet uses LlmqTest
lklimek Aug 15, 2024
d9cada9
test(sdk): asset_lock test vectors
lklimek Aug 15, 2024
0c04b42
Merge remote-tracking branch 'origin/v1.1-dev' into fix/sdk-invalid-q…
lklimek Aug 15, 2024
c9c4a21
fix(dapi-grpc): fix const
lklimek Aug 16, 2024
f57e455
fix(sdk): build error due to imports
lklimek Aug 16, 2024
b5dfc6a
chore(sdk): cargo fmt
lklimek Aug 19, 2024
1f1c957
Merge remote-tracking branch 'origin/v1.1-dev' into fix/sdk-invalid-q…
lklimek Aug 21, 2024
c4cc766
Merge branch 'master' into fix/sdk-invalid-quorum
lklimek Aug 30, 2024
5d33c31
Merge remote-tracking branch 'origin/v1.7-dev' into fix/sdk-invalid-q…
lklimek Dec 10, 2024
727cc20
chore: fix build
lklimek Dec 10, 2024
50a5267
Merge branch 'v1.8-dev' into fix/sdk-invalid-quorum
lklimek Dec 13, 2024
ee83d83
Merge remote-tracking branch 'origin/v2.0-dev' into fix/sdk-invalid-q…
lklimek Feb 24, 2025
bd6a4ff
feat: verify instant asset lock signature
lklimek Mar 3, 2025
9a67e22
Merge remote-tracking branch 'origin/v2.0-dev' into fix/sdk-invalid-q…
lklimek Mar 3, 2025
b2c6b13
refactor: use Network from dashcore
lklimek Mar 4, 2025
1264c18
refactor: further simplify Network type processing
lklimek Mar 4, 2025
521fdac
chore: remove verification of AssetLockProof::Instant
lklimek Mar 5, 2025
969fb0e
chore: minor cleanup
lklimek Mar 5, 2025
dd50797
chore: self-review
lklimek Mar 5, 2025
821bfd7
chore: fix warnings and failing build
lklimek Mar 5, 2025
a6910f2
test: remove unsupported test case
lklimek Mar 5, 2025
9ca5a7b
doc: fix some docs
lklimek Mar 5, 2025
de4de67
chore: use async_trait for StateTransitionBuilder
lklimek Mar 6, 2025
c22fa07
chore: remove duplicate async_trait
lklimek Mar 6, 2025
20a836b
chore(sdk): s/core_network()/network()/
lklimek Mar 6, 2025
ed981b6
Merge remote-tracking branch 'origin/v2.0-dev' into fix/sdk-invalid-q…
lklimek Mar 18, 2025
bb8dcff
build(dpp): remove unused ordered-float dependency
lklimek Mar 18, 2025
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
101 changes: 53 additions & 48 deletions packages/dapi-grpc/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,94 +63,99 @@ 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; 40] = [
//
// Sort alphabetically to simplify maintenance.
const VERSIONED_REQUESTS: [&str; 41] = [
"GetContestedResourceIdentityVotesRequest",
"GetContestedResourcesRequest",
"GetContestedResourceVoteStateRequest",
"GetContestedResourceVotersForIdentityRequest",
"GetDataContractHistoryRequest",
"GetDataContractRequest",
"GetDataContractsRequest",
"GetDocumentsRequest",
"GetEpochsInfoRequest",
"GetEvonodesProposedEpochBlocksByIdsRequest",
"GetEvonodesProposedEpochBlocksByRangeRequest",
"GetGroupActionsRequest",
"GetGroupActionSignersRequest",
"GetGroupInfoRequest",
"GetGroupInfosRequest",
"GetIdentitiesBalancesRequest",
"GetIdentitiesByPublicKeyHashesRequest",
"GetIdentitiesContractKeysRequest",
"GetIdentitiesRequest",
"GetIdentitiesBalancesRequest",
"GetIdentityNonceRequest",
"GetIdentityContractNonceRequest",
"GetIdentitiesTokenBalancesRequest",
"GetIdentitiesTokenInfosRequest",
"GetIdentityBalanceAndRevisionRequest",
"GetIdentityBalanceRequest",
"GetIdentityByPublicKeyHashRequest",
"GetIdentityContractNonceRequest",
"GetIdentityKeysRequest",
"GetIdentityNonceRequest",
"GetIdentityRequest",
"GetIdentityTokenBalancesRequest",
"GetIdentityTokenInfosRequest",
"GetPathElementsRequest",
"GetPrefundedSpecializedBalanceRequest",
"GetProofsRequest",
"WaitForStateTransitionResultRequest",
"GetProtocolVersionUpgradeStateRequest",
"GetProtocolVersionUpgradeVoteStatusRequest",
"GetPathElementsRequest",
"GetIdentitiesContractKeysRequest",
"GetPrefundedSpecializedBalanceRequest",
"GetContestedResourcesRequest",
"GetContestedResourceVoteStateRequest",
"GetContestedResourceVotersForIdentityRequest",
"GetContestedResourceIdentityVotesRequest",
"GetVotePollsByEndDateRequest",
"GetTotalCreditsInPlatformRequest",
"GetEvonodesProposedEpochBlocksByIdsRequest",
"GetEvonodesProposedEpochBlocksByRangeRequest",
"GetStatusRequest",
"GetIdentityTokenBalancesRequest",
"GetIdentitiesTokenBalancesRequest",
"GetIdentityTokenInfosRequest",
"GetIdentitiesTokenInfosRequest",
"GetTotalCreditsInPlatformRequest",
"GetVotePollsByEndDateRequest",
"GetTokenStatusesRequest",
"GetTokenTotalSupplyRequest",
"GetGroupInfoRequest",
"GetGroupInfosRequest",
"GetGroupActionsRequest",
"GetGroupActionSignersRequest",
"WaitForStateTransitionResultRequest",
];

// The following responses are excluded as they don't support proofs:
// - "GetConsensusParamsResponse"
// - "GetStatusResponse"
//
// "GetEvonodesProposedEpochBlocksResponse" is used for 2 Requests
//
// Sort alphabetically to simplify maintenance.
const VERSIONED_RESPONSES: [&str; 39] = [
"GetContestedResourceIdentityVotesResponse",
"GetContestedResourcesResponse",
"GetContestedResourceVoteStateResponse",
"GetContestedResourceVotersForIdentityResponse",
"GetDataContractHistoryResponse",
"GetDataContractResponse",
"GetDataContractsResponse",
"GetDocumentsResponse",
"GetIdentitiesByPublicKeyHashesResponse",
"GetIdentitiesResponse",
"GetIdentitiesBalancesResponse",
"GetEpochsInfoResponse",
"GetEvonodesProposedEpochBlocksResponse",
"GetGroupActionsResponse",
"GetGroupActionSignersResponse",
"GetGroupInfoResponse",
"GetGroupInfosResponse",
"GetIdentityBalanceAndRevisionResponse",
"GetIdentityBalanceResponse",
"GetIdentityNonceResponse",
"GetIdentityContractNonceResponse",
"GetIdentityByPublicKeyHashResponse",
"GetIdentityContractNonceResponse",
"GetIdentityKeysResponse",
"GetIdentityNonceResponse",
"GetIdentityResponse",
"GetIdentityTokenBalancesResponse",
"GetIdentityTokenInfosResponse",
"GetIdentitiesBalancesResponse",
"GetIdentitiesByPublicKeyHashesResponse",
"GetIdentitiesContractKeysResponse",
"GetIdentitiesResponse",
"GetIdentitiesTokenBalancesResponse",
"GetIdentitiesTokenInfosResponse",
"GetPathElementsResponse",
"GetPrefundedSpecializedBalanceResponse",
"GetProofsResponse",
"WaitForStateTransitionResultResponse",
"GetEpochsInfoResponse",
"GetProtocolVersionUpgradeStateResponse",
"GetProtocolVersionUpgradeVoteStatusResponse",
"GetPathElementsResponse",
"GetIdentitiesContractKeysResponse",
"GetPrefundedSpecializedBalanceResponse",
"GetContestedResourcesResponse",
"GetContestedResourceVoteStateResponse",
"GetContestedResourceVotersForIdentityResponse",
"GetContestedResourceIdentityVotesResponse",
"GetVotePollsByEndDateResponse",
"GetTotalCreditsInPlatformResponse",
"GetEvonodesProposedEpochBlocksResponse",
"GetIdentityTokenBalancesResponse",
"GetIdentitiesTokenBalancesResponse",
"GetIdentityTokenInfosResponse",
"GetIdentitiesTokenInfosResponse",
"GetTokenStatusesResponse",
"GetTokenTotalSupplyResponse",
"GetGroupInfoResponse",
"GetGroupInfosResponse",
"GetGroupActionsResponse",
"GetGroupActionSignersResponse",
"GetVotePollsByEndDateResponse",
"WaitForStateTransitionResultResponse",
];

check_unique(&VERSIONED_REQUESTS).expect("VERSIONED_REQUESTS");
Expand Down
17 changes: 17 additions & 0 deletions packages/rs-dapi-client/src/executor.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::transport::TransportRequest;
use crate::{Address, CanRetry, DapiClientError, RequestSettings};
use dapi_grpc::mock::Mockable;
use dapi_grpc::platform::VersionedGrpcResponse;
use dapi_grpc::tonic::async_trait;
use std::fmt::Debug;

Expand Down Expand Up @@ -127,6 +128,22 @@ where
}
}

impl<T: VersionedGrpcResponse> VersionedGrpcResponse for ExecutionResponse<T> {
type Error = T::Error;

fn metadata(&self) -> Result<&dapi_grpc::platform::v0::ResponseMetadata, Self::Error> {
self.inner.metadata()
}

fn proof(&self) -> Result<&dapi_grpc::platform::v0::Proof, Self::Error> {
self.inner.proof()
}

fn proof_owned(self) -> Result<dapi_grpc::platform::v0::Proof, Self::Error> {
self.inner.proof_owned()
}
}

/// Result of request execution
pub type ExecutionResult<R, E> = Result<ExecutionResponse<R>, ExecutionError<E>>;

Expand Down
2 changes: 1 addition & 1 deletion packages/rs-dpp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ dash-sdk-features = [
# "json-object",
# "platform-value",
# "system_contracts",
# "validation", # TODO: This one is big
"validation", # TODO: This one is big
"identity-hashing",
"data-contract-json-conversion",
# "identity-serialization",
Expand Down
2 changes: 1 addition & 1 deletion packages/rs-dpp/src/core_types/validator_set/v0/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ mod tests {
let node_ip = "192.168.1.1".to_string();
let node_id = PubkeyHash::from_slice(&[4; 20]).unwrap();
let validator = ValidatorV0 {
pro_tx_hash: pro_tx_hash.clone(),
pro_tx_hash,
public_key,
node_ip,
node_id,
Expand Down
2 changes: 1 addition & 1 deletion packages/rs-drive-proof-verifier/src/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ impl<C: AsRef<dyn ContextProvider> + Send + Sync> ContextProvider for C {
}
}

impl<'a, T: ContextProvider + 'a> ContextProvider for std::sync::Mutex<T>
impl<T: ContextProvider> ContextProvider for std::sync::Mutex<T>
where
Self: Sync + Send,
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ impl TryFrom<&GetStatusResponse> for Version {
let protocol = v0
.version
.as_ref()
.and_then(|v| v.protocol.clone())
.and_then(|v| v.protocol)
.map(|p| Protocol {
tenderdash: p.tenderdash.map(|t| TenderdashProtocol {
p2p: t.p2p,
Expand Down
2 changes: 1 addition & 1 deletion packages/rs-drive-proof-verifier/src/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ pub fn verify_signature_digest(
});
}
let signature = Signature::Basic(
<Bls12381G2Impl as Pairing>::Signature::from_compressed(&signature)
<Bls12381G2Impl as Pairing>::Signature::from_compressed(signature)
.into_option()
.ok_or(Error::SignatureVerificationError {
error: "Could not verify signature digest".to_string(),
Expand Down
41 changes: 39 additions & 2 deletions packages/rs-sdk/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,37 @@ pub enum Error {
/// Epoch not found; we must have at least one epoch
#[error("No epoch found on Platform; it should never happen")]
EpochNotFound,
/// Quorum not found; try again later
#[error(
"Quorum {quorum_hash_hex} of type {quorum_type} at height {core_chain_locked_height}: {e}"
)]
QuorumNotFound {
quorum_hash_hex: String,
quorum_type: u32,
core_chain_locked_height: u32,
e: ContextProviderError,
},

/// Asset lock not found; try again later.
///
/// ## Parameters
///
/// - core locked height in asset lock
/// - current core locked height on the platform
#[error("Asset lock for core locked height {core_locked_height_in_asset_lock} not available yet, max available locked core height is {core_locked_height_on_platform}; try again later")]
CoreLockedHeightNotYetAvailable {
core_locked_height_in_asset_lock: u32,
core_locked_height_on_platform: u32,
},

/// Provided asset lock is invalid
///
/// ## Parameters
///
/// - 0 - detailed error message
#[error("Invalid asset lock: {0}")]
InvalidAssetLock(String),

/// SDK operation timeout reached error
#[error("SDK operation timeout {} secs reached: {1}", .0.as_secs())]
TimeoutReached(Duration, String),
Expand Down Expand Up @@ -100,7 +131,7 @@ impl TryFrom<StateTransitionBroadcastErrorProto> for StateTransitionBroadcastErr
type Error = Error;

fn try_from(value: StateTransitionBroadcastErrorProto) -> Result<Self, Self::Error> {
let cause = if value.data.len() > 0 {
let cause = if !value.data.is_empty() {
let consensus_error =
ConsensusError::deserialize_from_bytes(&value.data).map_err(|e| {
tracing::debug!("Failed to deserialize consensus error: {}", e);
Expand Down Expand Up @@ -178,7 +209,13 @@ where

impl CanRetry for Error {
fn can_retry(&self) -> bool {
matches!(self, Error::StaleNode(..) | Error::TimeoutReached(_, _))
matches!(
self,
Error::StaleNode(..)
| Error::TimeoutReached(_, _)
| Error::CoreLockedHeightNotYetAvailable { .. }
| Error::QuorumNotFound { .. }
)
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/rs-sdk/src/platform/fetch_unproved.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ where
Self::maybe_from_unproved_with_metadata(
request.clone(),
response,
sdk.network,
sdk.network(),
sdk.version(),
)
.map_err(|e| ExecutionError {
Expand Down
2 changes: 1 addition & 1 deletion packages/rs-sdk/src/platform/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ impl Query<proto::GetIdentityKeysRequest> for Identifier {
}
}

impl<'a> Query<DocumentQuery> for DriveDocumentQuery<'a> {
impl Query<DocumentQuery> for DriveDocumentQuery<'_> {
fn query(self, prove: bool) -> Result<DocumentQuery, Error> {
if !prove {
unimplemented!("queries without proofs are not supported yet");
Expand Down
3 changes: 2 additions & 1 deletion packages/rs-sdk/src/platform/transition.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
//! State transitions used to put changed objects to the Dash Platform.
pub mod asset_lock;
pub mod broadcast;
pub(crate) mod broadcast_identity;
pub mod broadcast_request;
pub mod fungible_tokens;
pub mod purchase_document;
pub mod put_contract;
pub mod put_document;
Expand All @@ -17,4 +19,3 @@ pub mod waitable;
pub mod withdraw_from_identity;

pub use txid::TxId;
pub mod fungible_tokens;
Loading
Loading