Skip to content

Commit

Permalink
fix(sdk): failed to deserialize consensus error (#2410)
Browse files Browse the repository at this point in the history
  • Loading branch information
shumkov authored Jan 13, 2025
1 parent e07271e commit be5cd6d
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 10 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/rs-sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ tokio-test = { version = "0.4.4" }
clap = { version = "4.5.4", features = ["derive"] }
sanitize-filename = { version = "0.5.0" }
test-case = { version = "3.3.1" }
assert_matches = "1.5.0"

[features]
default = ["mocks", "offline-testing"]
Expand Down
118 changes: 108 additions & 10 deletions packages/rs-sdk/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,16 +88,25 @@ impl From<DapiClientError> for Error {
.metadata()
.get_bin("dash-serialized-consensus-error-bin")
{
return ConsensusError::deserialize_from_bytes(
consensus_error_value.as_encoded_bytes(),
)
.map(|consensus_error| {
Self::Protocol(ProtocolError::ConsensusError(Box::new(consensus_error)))
})
.unwrap_or_else(|e| {
tracing::debug!("Failed to deserialize consensus error: {}", e);
Self::Protocol(e)
});
return consensus_error_value
.to_bytes()
.map(|bytes| {
ConsensusError::deserialize_from_bytes(&bytes)
.map(|consensus_error| {
Self::Protocol(ProtocolError::ConsensusError(Box::new(
consensus_error,
)))
})
.unwrap_or_else(|e| {
tracing::debug!("Failed to deserialize consensus error: {}", e);
Self::Protocol(e)
})
})
.unwrap_or_else(|e| {
tracing::debug!("Failed to deserialize consensus error: {}", e);
// TODO: Introduce a specific error for this case
Self::Generic(format!("Invalid consensus error encoding: {e}"))
});
}
// Otherwise we parse the error code and act accordingly
if status.code() == Code::AlreadyExists {
Expand Down Expand Up @@ -157,3 +166,92 @@ pub enum StaleNodeError {
tolerance_ms: u64,
},
}

#[cfg(test)]
mod tests {
use super::*;

mod from_dapi_client_error {
use super::*;
use assert_matches::assert_matches;
use base64::Engine;
use dapi_grpc::tonic::metadata::{MetadataMap, MetadataValue};
use dpp::consensus::basic::identity::IdentityAssetLockProofLockedTransactionMismatchError;
use dpp::consensus::basic::BasicError;
use dpp::dashcore::hashes::Hash;
use dpp::dashcore::Txid;
use dpp::serialization::PlatformSerializableWithPlatformVersion;
use dpp::version::PlatformVersion;

#[test]
fn test_already_exists() {
let error = DapiClientError::Transport(TransportError::Grpc(
dapi_grpc::tonic::Status::new(Code::AlreadyExists, "Object already exists"),
));

let sdk_error: Error = error.into();
assert!(matches!(sdk_error, Error::AlreadyExists(_)));
}

#[test]
fn test_consensus_error() {
let platform_version = PlatformVersion::latest();

let consensus_error = ConsensusError::BasicError(
BasicError::IdentityAssetLockProofLockedTransactionMismatchError(
IdentityAssetLockProofLockedTransactionMismatchError::new(
Txid::from_byte_array([0; 32]),
Txid::from_byte_array([1; 32]),
),
),
);

let consensus_error_bytes = consensus_error
.serialize_to_bytes_with_platform_version(platform_version)
.expect("serialize consensus error to bytes");

let mut metadata = MetadataMap::new();
metadata.insert_bin(
"dash-serialized-consensus-error-bin",
MetadataValue::from_bytes(&consensus_error_bytes),
);

let status =
dapi_grpc::tonic::Status::with_metadata(Code::InvalidArgument, "Test", metadata);

let error = DapiClientError::Transport(TransportError::Grpc(status));

let sdk_error = Error::from(error);

assert_matches!(
sdk_error,
Error::Protocol(ProtocolError::ConsensusError(e)) if matches!(*e, ConsensusError::BasicError(
BasicError::IdentityAssetLockProofLockedTransactionMismatchError(_)
))
);
}

#[test]
fn test_consensus_error_with_fixture() {
let consensus_error_bytes = base64::engine::general_purpose::STANDARD.decode("ATUgJOJEYbuHBqyTeApO/ptxQ8IAw8nm9NbGROu1nyE/kqcgDTlFeUG0R4wwVcbZJMFErL+VSn63SUpP49cequ3fsKw=").expect("decode base64");
let consensus_error = MetadataValue::from_bytes(&consensus_error_bytes);

let mut metadata = MetadataMap::new();
metadata.insert_bin("dash-serialized-consensus-error-bin", consensus_error);

let status =
dapi_grpc::tonic::Status::with_metadata(Code::InvalidArgument, "Test", metadata);

let error = DapiClientError::Transport(TransportError::Grpc(status));

let sdk_error = Error::from(error);

assert_matches!(
sdk_error,
Error::Protocol(ProtocolError::ConsensusError(e)) if matches!(*e, ConsensusError::BasicError(
BasicError::IdentityAssetLockProofLockedTransactionMismatchError(_)
))
);
}
}
}

0 comments on commit be5cd6d

Please sign in to comment.