Skip to content

Commit

Permalink
feat!: handle new drive error codes (dashevo#405)
Browse files Browse the repository at this point in the history
Co-authored-by: Ivan Shumkov <ivan@shumkov.ru>
  • Loading branch information
Konstantin Shuplenkov and shumkov committed Sep 15, 2021
1 parent 13a0997 commit 2a02887
Show file tree
Hide file tree
Showing 25 changed files with 474 additions and 570 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/.env
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
DRIVE_BRANCH=update-dpp
DASHMATE_BRANCH=feat/update-sdk
TEST_SUITE_BRANCH=update-dpp
SDK_BRANCH=feat/driveProtocolVersion
DRIVE_BRANCH=feat/grpc-error-codes
DASHMATE_BRANCH=error-codes
TEST_SUITE_BRANCH=error-codes
#SDK_BRANCH=error-codes
44 changes: 0 additions & 44 deletions lib/errors/AbciResponseError.js

This file was deleted.

6 changes: 2 additions & 4 deletions lib/externalApis/drive/DriveClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const jayson = require('jayson/promise');
const cbor = require('cbor');

const RPCError = require('../../rpcServer/RPCError');
const AbciResponseError = require('../../errors/AbciResponseError');
const createGrpcErrorFromDriveResponse = require('../../grpcServer/handlers/createGrpcErrorFromDriveResponse');

class DriveClient {
/**
Expand Down Expand Up @@ -54,9 +54,7 @@ class DriveClient {
return Buffer.from(response.value, 'base64');
}

const { error: abciError } = JSON.parse(response.log);

throw new AbciResponseError(response.code, abciError);
throw createGrpcErrorFromDriveResponse(response.code, response.info);
}

/**
Expand Down
99 changes: 99 additions & 0 deletions lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
const cbor = require('cbor');
const {
server: {
error: {
InternalGrpcError,
InvalidArgumentGrpcError,
DeadlineExceededGrpcError,
ResourceExhaustedGrpcError,
NotFoundGrpcError,
FailedPreconditionGrpcError,
UnavailableGrpcError,
GrpcError,
},
},
} = require('@dashevo/grpc-common');
const GrpcErrorCodes = require('@dashevo/grpc-common/lib/server/error/GrpcErrorCodes');
const AlreadyExistsGrpcError = require('@dashevo/grpc-common/lib/server/error/AlreadyExistsGrpcError');
const createConsensusError = require('@dashevo/dpp/lib/errors/consensus/createConsensusError');

/**
* @typedef createGrpcErrorFromDriveResponse
* @param {number} code
* @param {string} info
* @return {GrpcError}
*/
function createGrpcErrorFromDriveResponse(code, info) {
if (code === undefined) {
return new InternalGrpcError(new Error('Drive’s error code is empty'));
}

const decodedInfo = info ? cbor.decode(Buffer.from(info, 'base64')) : undefined;

// eslint-disable-next-line default-case
switch (code) {
case GrpcErrorCodes.INVALID_ARGUMENT:
return new InvalidArgumentGrpcError(decodedInfo.message, decodedInfo.metadata);
case GrpcErrorCodes.DEADLINE_EXCEEDED:
return new DeadlineExceededGrpcError(decodedInfo.message, decodedInfo.metadata);
case GrpcErrorCodes.NOT_FOUND:
return new NotFoundGrpcError(decodedInfo.message, decodedInfo.metadata);
case GrpcErrorCodes.ALREADY_EXISTS:
return new AlreadyExistsGrpcError(decodedInfo.message, decodedInfo.metadata);
case GrpcErrorCodes.RESOURCE_EXHAUSTED:
return new ResourceExhaustedGrpcError(decodedInfo.message, decodedInfo.metadata);
case GrpcErrorCodes.FAILED_PRECONDITION:
return new FailedPreconditionGrpcError(decodedInfo.message, decodedInfo.metadata);
case GrpcErrorCodes.INTERNAL: {
const error = new Error(decodedInfo.message);
error.stack = decodedInfo.metadata.stack;

delete decodedInfo.metadata.stack;

return new InternalGrpcError(error, decodedInfo.metadata);
}
case GrpcErrorCodes.UNAVAILABLE:
return new UnavailableGrpcError(decodedInfo.message, decodedInfo.metadata);
case GrpcErrorCodes.CANCELLED:
case GrpcErrorCodes.UNKNOWN:
case GrpcErrorCodes.UNAUTHENTICATED:
case GrpcErrorCodes.DATA_LOSS:
case GrpcErrorCodes.UNIMPLEMENTED:
case GrpcErrorCodes.OUT_OF_RANGE:
case GrpcErrorCodes.ABORTED:
case GrpcErrorCodes.PERMISSION_DENIED:
return new GrpcError(code, decodedInfo.message, decodedInfo.metadata);
}

if (code >= 17 && code < 1000) {
return new GrpcError(GrpcErrorCodes.UNKNOWN, decodedInfo.message, decodedInfo.metadata);
}

if (code >= 1000 && code < 5000) {
const consensusError = createConsensusError(code, decodedInfo || []);

// Basic
if (code >= 1000 && code < 2000) {
return new InvalidArgumentGrpcError(consensusError.message, { code });
}

// Signature
if (code >= 2000 && code < 3000) {
return new GrpcError(GrpcErrorCodes.UNAUTHENTICATED, consensusError.message, { code });
}

// Fee
if (code >= 3000 && code < 4000) {
return new FailedPreconditionGrpcError(consensusError.message, { code });
}

// State
if (code >= 4000 && code < 5000) {
return new InvalidArgumentGrpcError(consensusError.message, { code });
}
}

return new InternalGrpcError(new Error(`Unknown Drive’s error code: ${code}`));
}

module.exports = createGrpcErrorFromDriveResponse;
50 changes: 0 additions & 50 deletions lib/grpcServer/handlers/handleAbciResponseError.js

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,13 @@ const {
},
} = require('@dashevo/dapi-grpc');

const AbciResponseError = require('../../../errors/AbciResponseError');

/**
* @param {jaysonClient} rpcClient
* @param {handleAbciResponseError} handleAbciResponseError
* @param {createGrpcErrorFromDriveResponse} createGrpcErrorFromDriveResponse
*
* @returns {broadcastStateTransitionHandler}
*/
function broadcastStateTransitionHandlerFactory(rpcClient, handleAbciResponseError) {
function broadcastStateTransitionHandlerFactory(rpcClient, createGrpcErrorFromDriveResponse) {
/**
* @typedef broadcastStateTransitionHandler
*
Expand Down Expand Up @@ -52,12 +50,8 @@ function broadcastStateTransitionHandlerFactory(rpcClient, handleAbciResponseErr
throw error;
}

if (result.code !== undefined && result.code !== 0) {
const { error: abciError } = JSON.parse(result.log);

handleAbciResponseError(
new AbciResponseError(result.code, abciError),
);
if (result.code !== 0) {
throw createGrpcErrorFromDriveResponse(result.code, result.info);
}

return new BroadcastStateTransitionResponse();
Expand Down
16 changes: 2 additions & 14 deletions lib/grpcServer/handlers/platform/getDataContractHandlerFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,12 @@ const {
},
} = require('@dashevo/dapi-grpc');

const AbciResponseError = require('../../../errors/AbciResponseError');

/**
* @param {DriveClient} driveClient
* @param {handleAbciResponseError} handleAbciResponseError
*
* @returns {getDataContractHandler}
*/
function getDataContractHandlerFactory(driveClient, handleAbciResponseError) {
function getDataContractHandlerFactory(driveClient) {
/**
* @typedef getDataContractHandler
*
Expand All @@ -37,16 +34,7 @@ function getDataContractHandlerFactory(driveClient, handleAbciResponseError) {
throw new InvalidArgumentGrpcError('id is not specified');
}

let dataContractResponseBuffer;
try {
dataContractResponseBuffer = await driveClient
.fetchDataContract(id, prove);
} catch (e) {
if (e instanceof AbciResponseError) {
handleAbciResponseError(e);
}
throw e;
}
const dataContractResponseBuffer = await driveClient.fetchDataContract(id, prove);

return GetDataContractResponse.deserializeBinary(dataContractResponseBuffer);
}
Expand Down
18 changes: 4 additions & 14 deletions lib/grpcServer/handlers/platform/getDocumentsHandlerFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,14 @@ const {
},
} = require('@dashevo/dapi-grpc');

const AbciResponseError = require('../../../errors/AbciResponseError');

/**
*
* @param {DriveClient} driveClient
* @param {handleAbciResponseError} handleAbciResponseError
*
* @returns {getDocumentsHandler}
*/
function getDocumentsHandlerFactory(driveClient, handleAbciResponseError) {
function getDocumentsHandlerFactory(driveClient) {
/**
* @typedef getDocumentsHandler
*
Expand Down Expand Up @@ -110,17 +108,9 @@ function getDocumentsHandlerFactory(driveClient, handleAbciResponseError) {

const prove = request.getProve();

let documentResponseBuffer;
try {
documentResponseBuffer = await driveClient.fetchDocuments(
dataContractId, documentType, options, prove,
);
} catch (e) {
if (e instanceof AbciResponseError) {
handleAbciResponseError(e);
}
throw e;
}
const documentResponseBuffer = await driveClient.fetchDocuments(
dataContractId, documentType, options, prove,
);

return GetDocumentsResponse.deserializeBinary(documentResponseBuffer);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,13 @@ const {
},
} = require('@dashevo/dapi-grpc');

const AbciResponseError = require('../../../errors/AbciResponseError');

/**
*
* @param {DriveClient} driveClient
* @param {handleAbciResponseError} handleAbciResponseError
* @return {getIdentitiesByPublicKeyHashesHandler}
*/
function getIdentitiesByPublicKeyHashesHandlerFactory(
driveClient, handleAbciResponseError,
driveClient,
) {
/**
* @typedef getIdentitiesByPublicKeyHashesHandler
Expand All @@ -39,16 +36,8 @@ function getIdentitiesByPublicKeyHashesHandlerFactory(

const prove = request.getProve();

let identitiesResponseBuffer;
try {
identitiesResponseBuffer = await driveClient
.fetchIdentitiesByPublicKeyHashes(publicKeyHashes, prove);
} catch (e) {
if (e instanceof AbciResponseError) {
handleAbciResponseError(e);
}
throw e;
}
const identitiesResponseBuffer = await driveClient
.fetchIdentitiesByPublicKeyHashes(publicKeyHashes, prove);

return GetIdentitiesByPublicKeyHashesResponse.deserializeBinary(identitiesResponseBuffer);
}
Expand Down
Loading

0 comments on commit 2a02887

Please sign in to comment.