Skip to content

Commit 98bebee

Browse files
committed
Merge remote-tracking branch 'origin/v1.4-dev' into refactor/sdk-mock-errors
2 parents bd7499d + 244f5f9 commit 98bebee

349 files changed

Lines changed: 442 additions & 181 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

packages/dapi/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ async function createGrpcErrorFromDriveResponse(code, info) {
6464
const message = decodedInfo.message;
6565
const data = decodedInfo.data || {};
6666

67+
const serializedConsensusError = data.serializedError;
68+
delete data.serializedError;
69+
6770
// gRPC error codes
6871
if (code <= 16) {
6972
const CommonErrorClass = COMMON_ERROR_CLASSES[code.toString()];
@@ -111,9 +114,15 @@ async function createGrpcErrorFromDriveResponse(code, info) {
111114

112115
// DPP errors
113116
if (code >= 10000 && code < 50000) {
117+
const consensusMetadata = {
118+
...createRawMetadata(data),
119+
code,
120+
'dash-serialized-consensus-error-bin': Buffer.from(serializedConsensusError),
121+
};
122+
114123
let consensusError;
115124
try {
116-
consensusError = deserializeConsensusError(data.serializedError || []);
125+
consensusError = deserializeConsensusError(serializedConsensusError);
117126
} catch (e) {
118127
logger.error({
119128
err: e,
@@ -128,7 +137,7 @@ async function createGrpcErrorFromDriveResponse(code, info) {
128137
if (code >= 10000 && code < 20000) {
129138
return new InvalidArgumentGrpcError(
130139
consensusError.message,
131-
{ code, ...createRawMetadata(data) },
140+
consensusMetadata,
132141
);
133142
}
134143

@@ -137,23 +146,23 @@ async function createGrpcErrorFromDriveResponse(code, info) {
137146
return new GrpcError(
138147
GrpcErrorCodes.UNAUTHENTICATED,
139148
consensusError.message,
140-
{ code, ...createRawMetadata(data) },
149+
consensusMetadata,
141150
);
142151
}
143152

144153
// Fee
145154
if (code >= 30000 && code < 40000) {
146155
return new FailedPreconditionGrpcError(
147156
consensusError.message,
148-
{ code, ...createRawMetadata(data) },
157+
consensusMetadata,
149158
);
150159
}
151160

152161
// State
153162
if (code >= 40000 && code < 50000) {
154163
return new InvalidArgumentGrpcError(
155164
consensusError.message,
156-
{ code, ...createRawMetadata(data) },
165+
consensusMetadata,
157166
);
158167
}
159168
}

packages/dapi/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.spec.js

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ describe('createGrpcErrorFromDriveResponse', () => {
6969
it('should throw basic consensus error if error code = 10000', async () => {
7070
const consensusError = new ProtocolVersionParsingError('test');
7171

72-
const data = { serializedError: consensusError.serialize() };
72+
const serializedError = consensusError.serialize();
73+
const data = { serializedError };
7374
info = { data };
7475

7576
const error = await createGrpcErrorFromDriveResponse(10000, cbor.encode(info).toString('base64'));
@@ -78,7 +79,7 @@ describe('createGrpcErrorFromDriveResponse', () => {
7879
expect(error.message).to.be.equals(consensusError.message);
7980
expect(error.getRawMetadata()).to.deep.equal({
8081
code: 10000,
81-
'drive-error-data-bin': cbor.encode(data),
82+
'dash-serialized-consensus-error-bin': serializedError,
8283
});
8384
});
8485

@@ -87,7 +88,8 @@ describe('createGrpcErrorFromDriveResponse', () => {
8788

8889
const consensusError = new IdentityNotFoundError(id);
8990

90-
const data = { serializedError: consensusError.serialize() };
91+
const serializedError = consensusError.serialize();
92+
const data = { serializedError };
9193
info = { data };
9294

9395
const error = await createGrpcErrorFromDriveResponse(
@@ -100,22 +102,23 @@ describe('createGrpcErrorFromDriveResponse', () => {
100102
expect(error.getCode()).to.equal(GrpcErrorCodes.UNAUTHENTICATED);
101103
expect(error.getRawMetadata()).to.deep.equal({
102104
code: 20000,
103-
'drive-error-data-bin': cbor.encode(data),
105+
'dash-serialized-consensus-error-bin': serializedError,
104106
});
105107
});
106108

107109
it('should throw fee consensus error if error code = 30000', async () => {
108110
const consensusError = new BalanceIsNotEnoughError(BigInt(20), BigInt(10));
109111

110-
const data = { serializedError: consensusError.serialize() };
112+
const serializedError = consensusError.serialize();
113+
const data = { serializedError };
111114
info = { data };
112115

113116
const error = await createGrpcErrorFromDriveResponse(30000, cbor.encode(info).toString('base64'));
114117

115118
expect(error).to.be.an.instanceOf(FailedPreconditionGrpcError);
116119
expect(error.getRawMetadata()).to.deep.equal({
117120
code: 30000,
118-
'drive-error-data-bin': cbor.encode(data),
121+
'dash-serialized-consensus-error-bin': serializedError,
119122
});
120123
});
121124

@@ -124,7 +127,8 @@ describe('createGrpcErrorFromDriveResponse', () => {
124127

125128
const consensusError = new DataContractAlreadyPresentError(dataContractId);
126129

127-
const data = { serializedError: consensusError.serialize() };
130+
const serializedError = consensusError.serialize();
131+
const data = { serializedError };
128132
info = { data };
129133

130134
const error = await createGrpcErrorFromDriveResponse(
@@ -135,7 +139,7 @@ describe('createGrpcErrorFromDriveResponse', () => {
135139
expect(error).to.be.an.instanceOf(InvalidArgumentGrpcError);
136140
expect(error.getRawMetadata()).to.deep.equal({
137141
code: 40000,
138-
'drive-error-data-bin': cbor.encode(data),
142+
'dash-serialized-consensus-error-bin': serializedError,
139143
});
140144
});
141145

packages/js-dapi-client/lib/transport/GrpcTransport/createGrpcTransportError.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,13 @@ async function createGrpcTransportError(grpcError, dapiAddress) {
119119

120120
// DPP consensus errors
121121
if (code >= 10000 && code < 50000) {
122-
const consensusError = deserializeConsensusError(data.serializedError || []);
122+
const consensusErrorString = metadata['dash-serialized-consensus-error-bin'];
123+
if (!consensusErrorString) {
124+
throw new Error(`Can't deserialize consensus error ${code}: serialized data is missing`);
125+
}
126+
127+
const consensusErrorBytes = Buffer.from(consensusErrorString, 'base64');
128+
const consensusError = deserializeConsensusError(consensusErrorBytes);
123129

124130
delete data.serializedError;
125131

packages/js-dapi-client/test/unit/transport/GrpcTransport/createGrpcTransportError.spec.js

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,17 +155,14 @@ describe('createGrpcTransportError', () => {
155155

156156
it('should return InvalidRequestDPPError', async () => {
157157
// grpc-js expects Buffer
158-
let driveErrorDataBin = cbor.encode({
159-
serializedError: new ProtocolVersionParsingError('test').serialize(),
160-
...errorData,
161-
});
158+
let serializedError = new ProtocolVersionParsingError('test').serialize();
162159

163160
// and grpc-web expects string
164161
// TODO: remove when we switch to single grpc implementation for both Node and Web
165162
if (typeof window !== 'undefined') {
166-
driveErrorDataBin = driveErrorDataBin.toString('base64');
163+
serializedError = serializedError.toString('base64');
167164
}
168-
metadata.set('drive-error-data-bin', driveErrorDataBin);
165+
metadata.set('dash-serialized-consensus-error-bin', serializedError);
169166

170167
const grpcError = new GrpcError(
171168
10001,

packages/rs-dapi-client/src/dapi_client.rs

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,21 @@ use crate::connection_pool::ConnectionPool;
1414
#[cfg(feature = "mocks")]
1515
use crate::Address;
1616
use crate::{
17-
transport::{TransportClient, TransportRequest},
17+
transport::{TransportClient, TransportError, TransportRequest},
1818
AddressList, CanRetry, DapiRequestExecutor, ExecutionError, ExecutionResponse, ExecutionResult,
1919
RequestSettings,
2020
};
2121

2222
/// General DAPI request error type.
2323
#[derive(Debug, thiserror::Error)]
2424
#[cfg_attr(feature = "mocks", derive(serde::Serialize, serde::Deserialize))]
25-
pub enum DapiClientError<TE: Mockable> {
25+
pub enum DapiClientError {
2626
/// The error happened on transport layer
2727
#[error("transport error: {0}")]
28-
Transport(#[cfg_attr(feature = "mocks", serde(with = "dapi_grpc::mock::serde_mockable"))] TE),
28+
Transport(
29+
#[cfg_attr(feature = "mocks", serde(with = "dapi_grpc::mock::serde_mockable"))]
30+
TransportError,
31+
),
2932
/// There are no valid DAPI addresses to use.
3033
#[error("no available addresses to use")]
3134
NoAvailableAddresses,
@@ -39,7 +42,7 @@ pub enum DapiClientError<TE: Mockable> {
3942
Mock(#[from] crate::mock::MockError),
4043
}
4144

42-
impl<TE: CanRetry + Mockable> CanRetry for DapiClientError<TE> {
45+
impl CanRetry for DapiClientError {
4346
fn can_retry(&self) -> bool {
4447
use DapiClientError::*;
4548
match self {
@@ -52,17 +55,10 @@ impl<TE: CanRetry + Mockable> CanRetry for DapiClientError<TE> {
5255
}
5356
}
5457

55-
#[cfg(feature = "mocks")]
56-
#[derive(serde::Serialize, serde::Deserialize)]
57-
struct TransportErrorData {
58-
transport_error: Vec<u8>,
59-
address: Address,
60-
}
61-
6258
/// Serialization of [DapiClientError].
6359
///
6460
/// We need to do manual serialization because of the generic type parameter which doesn't support serde derive.
65-
impl<TE: Mockable> Mockable for DapiClientError<TE> {
61+
impl Mockable for DapiClientError {
6662
#[cfg(feature = "mocks")]
6763
fn mock_serialize(&self) -> Option<Vec<u8>> {
6864
Some(serde_json::to_vec(self).expect("serialize DAPI client error"))
@@ -112,11 +108,11 @@ impl DapiRequestExecutor for DapiClient {
112108
&self,
113109
request: R,
114110
settings: RequestSettings,
115-
) -> ExecutionResult<R::Response, DapiClientError<<R::Client as TransportClient>::Error>>
111+
) -> ExecutionResult<R::Response, DapiClientError>
116112
where
117113
R: TransportRequest + Mockable,
118114
R::Response: Mockable,
119-
<R::Client as TransportClient>::Error: Mockable,
115+
TransportError: Mockable,
120116
{
121117
// Join settings of different sources to get final version of the settings for this execution:
122118
let applied_settings = self
@@ -150,9 +146,10 @@ impl DapiRequestExecutor for DapiClient {
150146
.read()
151147
.expect("can't get address list for read");
152148

153-
let address_result = address_list.get_live_address().cloned().ok_or(
154-
DapiClientError::<<R::Client as TransportClient>::Error>::NoAvailableAddresses,
155-
);
149+
let address_result = address_list
150+
.get_live_address()
151+
.cloned()
152+
.ok_or(DapiClientError::NoAvailableAddresses);
156153

157154
drop(address_list);
158155

packages/rs-dapi-client/src/executor.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::transport::{TransportClient, TransportRequest};
1+
use crate::transport::TransportRequest;
22
use crate::{Address, CanRetry, DapiClientError, RequestSettings};
33
use dapi_grpc::mock::Mockable;
44
use dapi_grpc::tonic::async_trait;
@@ -12,11 +12,10 @@ pub trait DapiRequestExecutor {
1212
&self,
1313
request: R,
1414
settings: RequestSettings,
15-
) -> ExecutionResult<R::Response, DapiClientError<<R::Client as TransportClient>::Error>>
15+
) -> ExecutionResult<R::Response, DapiClientError>
1616
where
1717
R: TransportRequest + Mockable,
18-
R::Response: Mockable,
19-
<R::Client as TransportClient>::Error: Mockable;
18+
R::Response: Mockable;
2019
}
2120

2221
/// Unwrap wrapped types

packages/rs-dapi-client/src/lib.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ pub use address_list::AddressList;
1818
pub use address_list::AddressListError;
1919
pub use connection_pool::ConnectionPool;
2020
pub use dapi_client::{DapiClient, DapiClientError};
21-
use dapi_grpc::mock::Mockable;
2221
#[cfg(feature = "dump")]
2322
pub use dump::DumpData;
2423
pub use executor::{
@@ -38,21 +37,19 @@ pub use request_settings::RequestSettings;
3837
/// let mut client = MockDapiClient::new();
3938
/// let request: proto::GetIdentityRequest = proto::get_identity_request::GetIdentityRequestV0 { id: b"0".to_vec(), prove: true }.into();
4039
/// let response = request.execute(&mut client, RequestSettings::default()).await?;
41-
/// # Ok::<(), ExecutionError<DapiClientError<_>>>(())
40+
/// # Ok::<(), ExecutionError<DapiClientError>>(())
4241
/// # };
4342
/// ```
4443
pub trait DapiRequest {
4544
/// Response from DAPI for this specific request.
4645
type Response;
47-
/// An error type for the transport this request uses.
48-
type TransportError: Mockable;
4946

5047
/// Executes the request.
5148
fn execute<'c, D: DapiRequestExecutor>(
5249
self,
5350
dapi_client: &'c D,
5451
settings: RequestSettings,
55-
) -> BoxFuture<'c, ExecutionResult<Self::Response, DapiClientError<Self::TransportError>>>
52+
) -> BoxFuture<'c, ExecutionResult<Self::Response, DapiClientError>>
5653
where
5754
Self: 'c;
5855
}
@@ -61,13 +58,11 @@ pub trait DapiRequest {
6158
impl<T: transport::TransportRequest + Send> DapiRequest for T {
6259
type Response = T::Response;
6360

64-
type TransportError = <T::Client as transport::TransportClient>::Error;
65-
6661
fn execute<'c, D: DapiRequestExecutor>(
6762
self,
6863
dapi_client: &'c D,
6964
settings: RequestSettings,
70-
) -> BoxFuture<'c, ExecutionResult<Self::Response, DapiClientError<Self::TransportError>>>
65+
) -> BoxFuture<'c, ExecutionResult<Self::Response, DapiClientError>>
7166
where
7267
Self: 'c,
7368
{

packages/rs-dapi-client/src/mock.rs

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@
1212
//! See `tests/mock_dapi_client.rs` for an example.
1313
1414
use crate::{
15-
transport::{TransportClient, TransportRequest},
16-
DapiClientError, DapiRequestExecutor, ExecutionError, ExecutionResponse, ExecutionResult,
17-
RequestSettings,
15+
transport::TransportRequest, DapiClientError, DapiRequestExecutor, ExecutionError,
16+
ExecutionResponse, ExecutionResult, RequestSettings,
1817
};
1918
use dapi_grpc::mock::Mockable;
2019
use dapi_grpc::tonic::async_trait;
@@ -36,10 +35,7 @@ pub struct MockDapiClient {
3635
expectations: Expectations,
3736
}
3837
/// Result of executing a mock request
39-
pub type MockResult<R> = ExecutionResult<
40-
<R as TransportRequest>::Response,
41-
DapiClientError<<<R as TransportRequest>::Client as TransportClient>::Error>,
42-
>;
38+
pub type MockResult<T> = ExecutionResult<<T as TransportRequest>::Response, DapiClientError>;
4339

4440
impl MockDapiClient {
4541
/// Create a new mock client
@@ -366,19 +362,3 @@ where
366362
}
367363
}
368364
}
369-
370-
/// Convert response into inner type
371-
pub trait InnerInto<T> {
372-
/// Convert response into inner type
373-
fn inner_into(self) -> T;
374-
}
375-
376-
/// Blanket implementation of InnerInto for types that implement FromInner
377-
impl<T, U> InnerInto<U> for T
378-
where
379-
U: FromInner<T>,
380-
{
381-
fn inner_into(self) -> U {
382-
U::from_inner(self)
383-
}
384-
}

0 commit comments

Comments
 (0)