From e4f9750d3a58aab763f4d59378d9e28f47e96f49 Mon Sep 17 00:00:00 2001 From: Konstantin Shuplenkov Date: Mon, 6 Sep 2021 16:48:06 +0300 Subject: [PATCH 01/15] feat: handle new drive error codes --- lib/errors/AbciResponseError.js | 44 ----- lib/externalApis/drive/DriveClient.js | 6 +- .../createGrpcErrorFromDriveResponse.js | 72 ++++++++ .../handlers/handleAbciResponseError.js | 50 ------ .../broadcastStateTransitionHandlerFactory.js | 12 +- .../platform/getDataContractHandlerFactory.js | 16 +- .../platform/getDocumentsHandlerFactory.js | 18 +- ...entitiesByPublicKeyHashesHandlerFactory.js | 17 +- .../platform/getIdentityHandlerFactory.js | 18 +- ...ntityIdsByPublicKeyHashesHandlerFactory.js | 24 +-- .../platform/platformHandlersFactory.js | 14 +- package-lock.json | 170 ++++++++++-------- package.json | 2 +- test/unit/externalApis/drive/DriveClient.js | 35 ++-- .../createGrpcErrorFromDriveResponse.js | 75 ++++++++ .../handlers/handleAbciResponseError.js | 84 --------- .../broadcastStateTransitionHandlerFactory.js | 36 ++++ .../platform/getDataContractHandlerFactory.js | 34 +--- .../platform/getDocumentsHandlerFactory.js | 35 +--- ...entitiesByPublicKeyHashesHandlerFactory.js | 33 +--- .../platform/getIdentityHandlerFactory.js | 31 ---- ...ntityIdsByPublicKeyHashesHandlerFactory.js | 34 +--- 22 files changed, 326 insertions(+), 534 deletions(-) delete mode 100644 lib/errors/AbciResponseError.js create mode 100644 lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js delete mode 100644 lib/grpcServer/handlers/handleAbciResponseError.js create mode 100644 test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.js delete mode 100644 test/unit/grpcServer/handlers/handleAbciResponseError.js diff --git a/lib/errors/AbciResponseError.js b/lib/errors/AbciResponseError.js deleted file mode 100644 index 9157d98c8..000000000 --- a/lib/errors/AbciResponseError.js +++ /dev/null @@ -1,44 +0,0 @@ -class AbciResponseError extends Error { - /** - * @param {number} errorCode - * @param {Object} abciError - * @param {string} abciError.message - * @param {Object} abciError.data - */ - constructor(errorCode, { message, data }) { - super(); - - this.errorCode = errorCode; - this.message = message; - this.data = data; - } - - /** - * Get error code - * - * @return {number} - */ - getErrorCode() { - return this.errorCode; - } - - /** - * Get error message - * - * @return {string} - */ - getMessage() { - return this.message; - } - - /** - * Get error data - * - * @return {Object} - */ - getData() { - return this.data; - } -} - -module.exports = AbciResponseError; diff --git a/lib/externalApis/drive/DriveClient.js b/lib/externalApis/drive/DriveClient.js index 7cec75fe2..66d37003f 100644 --- a/lib/externalApis/drive/DriveClient.js +++ b/lib/externalApis/drive/DriveClient.js @@ -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 { /** @@ -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); } /** diff --git a/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js b/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js new file mode 100644 index 000000000..1633e0fb5 --- /dev/null +++ b/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js @@ -0,0 +1,72 @@ +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 createConsensusError = require('@dashevo/dpp/lib/errors/consensus/createConsensusError'); +const AlreadyExistsGrpcError = require('@dashevo/grpc-common/lib/server/error/AlreadyExistsGrpcError'); +const VersionMismatchGrpcError = require('@dashevo/grpc-common/lib/server/error/VersionMismatchGrpcError'); + +/** + * @typedef createGrpcErrorFromDriveResponse + * @param {number} code + * @param {string} info + * @return {GrpcError} + */ +function createGrpcErrorFromDriveResponse(code, info) { + const decodedInfo = cbor.decode(Buffer.from(info, 'base64')); + + // 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: + return new InternalGrpcError(decodedInfo.message, decodedInfo.metadata); + case GrpcErrorCodes.UNAVAILABLE: + return new UnavailableGrpcError(decodedInfo.message, decodedInfo.metadata); + case GrpcErrorCodes.VERSION_MISMATCH: + return new VersionMismatchGrpcError(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 < 100) { + return new GrpcError(code, decodedInfo.message, decodedInfo.metadata); + } + + if (code >= 1000 && code < 5000) { + return createConsensusError(code, decodedInfo); + } + + return new GrpcError(code, `Unknown error code: ${code}`, decodedInfo); +} + +module.exports = createGrpcErrorFromDriveResponse; diff --git a/lib/grpcServer/handlers/handleAbciResponseError.js b/lib/grpcServer/handlers/handleAbciResponseError.js deleted file mode 100644 index 44d05db43..000000000 --- a/lib/grpcServer/handlers/handleAbciResponseError.js +++ /dev/null @@ -1,50 +0,0 @@ -const { - server: { - error: { - InternalGrpcError, - InvalidArgumentGrpcError, - DeadlineExceededGrpcError, - ResourceExhaustedGrpcError, - NotFoundGrpcError, - FailedPreconditionGrpcError, - UnavailableGrpcError, - }, - }, -} = require('@dashevo/grpc-common'); - -/** - * @typedef handleAbciResponseError - * @param {AbciResponseError} error - */ -function handleAbciResponseError(error) { - const code = error.getErrorCode(); - const message = error.getMessage(); - const data = error.getData(); - - switch (code) { - case 7: // UNAVAILABLE - throw new UnavailableGrpcError(message, data); - case 6: // MEMORY_LIMIT_EXCEEDED - throw new ResourceExhaustedGrpcError(message, data); - case 5: // EXECUTION_TIMED_OUT - throw new DeadlineExceededGrpcError(message, data); - case 4: // INSUFFICIENT_FUNDS - throw new FailedPreconditionGrpcError(message, data); - case 3: // NOT_FOUND - throw new NotFoundGrpcError(message, data); - case 2: // INVALID_ARGUMENT - throw new InvalidArgumentGrpcError(message, data); - case 1: // INTERNAL - default: { - if (data && data.toString() === 'Timed out waiting for tx to be included in a block') { - throw new DeadlineExceededGrpcError(data.toString(), {}); - } - - const e = new Error(message); - - throw new InternalGrpcError(e, data); - } - } -} - -module.exports = handleAbciResponseError; diff --git a/lib/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js b/lib/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js index d4ca03509..2ed9e20af 100644 --- a/lib/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js @@ -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 * @@ -53,11 +51,7 @@ function broadcastStateTransitionHandlerFactory(rpcClient, handleAbciResponseErr } if (result.code !== undefined && result.code !== 0) { - const { error: abciError } = JSON.parse(result.log); - - handleAbciResponseError( - new AbciResponseError(result.code, abciError), - ); + throw createGrpcErrorFromDriveResponse(result.code, result.info); } return new BroadcastStateTransitionResponse(); diff --git a/lib/grpcServer/handlers/platform/getDataContractHandlerFactory.js b/lib/grpcServer/handlers/platform/getDataContractHandlerFactory.js index be4d6b15b..27f433fe7 100644 --- a/lib/grpcServer/handlers/platform/getDataContractHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/getDataContractHandlerFactory.js @@ -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 * @@ -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); } diff --git a/lib/grpcServer/handlers/platform/getDocumentsHandlerFactory.js b/lib/grpcServer/handlers/platform/getDocumentsHandlerFactory.js index 3d2f37d15..cf9798431 100644 --- a/lib/grpcServer/handlers/platform/getDocumentsHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/getDocumentsHandlerFactory.js @@ -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 * @@ -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); } diff --git a/lib/grpcServer/handlers/platform/getIdentitiesByPublicKeyHashesHandlerFactory.js b/lib/grpcServer/handlers/platform/getIdentitiesByPublicKeyHashesHandlerFactory.js index 83d3a6bae..eca1f3c75 100644 --- a/lib/grpcServer/handlers/platform/getIdentitiesByPublicKeyHashesHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/getIdentitiesByPublicKeyHashesHandlerFactory.js @@ -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 @@ -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); } diff --git a/lib/grpcServer/handlers/platform/getIdentityHandlerFactory.js b/lib/grpcServer/handlers/platform/getIdentityHandlerFactory.js index f77e2963e..071a4c0ee 100644 --- a/lib/grpcServer/handlers/platform/getIdentityHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/getIdentityHandlerFactory.js @@ -12,15 +12,12 @@ const { }, } = require('@dashevo/dapi-grpc'); -const AbciResponseError = require('../../../errors/AbciResponseError'); - /** * @param {DriveClient} driveClient - * @param {handleAbciResponseError} handleAbciResponseError * * @returns {getIdentityHandler} */ -function getIdentityHandlerFactory(driveClient, handleAbciResponseError) { +function getIdentityHandlerFactory(driveClient) { /** * @typedef getIdentityHandler * @@ -39,17 +36,8 @@ function getIdentityHandlerFactory(driveClient, handleAbciResponseError) { const prove = request.getProve(); - let identityResponseBuffer; - - try { - identityResponseBuffer = await driveClient - .fetchIdentity(id, prove); - } catch (e) { - if (e instanceof AbciResponseError) { - handleAbciResponseError(e); - } - throw e; - } + const identityResponseBuffer = await driveClient + .fetchIdentity(id, prove); return GetIdentityResponse.deserializeBinary(identityResponseBuffer); } diff --git a/lib/grpcServer/handlers/platform/getIdentityIdsByPublicKeyHashesHandlerFactory.js b/lib/grpcServer/handlers/platform/getIdentityIdsByPublicKeyHashesHandlerFactory.js index 768858396..148537793 100644 --- a/lib/grpcServer/handlers/platform/getIdentityIdsByPublicKeyHashesHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/getIdentityIdsByPublicKeyHashesHandlerFactory.js @@ -12,16 +12,13 @@ const { }, } = require('@dashevo/dapi-grpc'); -const AbciResponseError = require('../../../errors/AbciResponseError'); - /** * * @param {DriveClient} driveClient - * @param {handleAbciResponseError} handleAbciResponseError * @return {getIdentityIdsByPublicKeyHashesHandler} */ function getIdentityIdsByPublicKeyHashesHandlerFactory( - driveClient, handleAbciResponseError, + driveClient, ) { /** * @typedef getIdentityIdsByPublicKeyHashesHandler @@ -39,20 +36,11 @@ function getIdentityIdsByPublicKeyHashesHandlerFactory( const prove = request.getProve(); - let identityIdsResponseBuffer; - - try { - identityIdsResponseBuffer = await driveClient - .fetchIdentityIdsByPublicKeyHashes( - publicKeyHashes, - prove, - ); - } catch (e) { - if (e instanceof AbciResponseError) { - handleAbciResponseError(e); - } - throw e; - } + const identityIdsResponseBuffer = await driveClient + .fetchIdentityIdsByPublicKeyHashes( + publicKeyHashes, + prove, + ); return GetIdentityIdsByPublicKeyHashesResponse.deserializeBinary(identityIdsResponseBuffer); } diff --git a/lib/grpcServer/handlers/platform/platformHandlersFactory.js b/lib/grpcServer/handlers/platform/platformHandlersFactory.js index 0f1e8d2d4..4945ed271 100644 --- a/lib/grpcServer/handlers/platform/platformHandlersFactory.js +++ b/lib/grpcServer/handlers/platform/platformHandlersFactory.js @@ -46,7 +46,7 @@ const { const log = require('../../../log'); -const handleAbciResponseError = require('../handleAbciResponseError'); +const createGrpcErrorFromDriveResponse = require('../createGrpcErrorFromDriveResponse'); const getIdentityHandlerFactory = require( './getIdentityHandlerFactory', @@ -100,7 +100,7 @@ function platformHandlersFactory( // broadcastStateTransition const broadcastStateTransitionHandler = broadcastStateTransitionHandlerFactory( rpcClient, - handleAbciResponseError, + createGrpcErrorFromDriveResponse, ); const wrappedBroadcastStateTransition = jsonToProtobufHandlerWrapper( @@ -116,7 +116,7 @@ function platformHandlersFactory( // getIdentity const getIdentityHandler = getIdentityHandlerFactory( - driveClient, handleAbciResponseError, + driveClient, ); const wrappedGetIdentity = jsonToProtobufHandlerWrapper( @@ -132,7 +132,7 @@ function platformHandlersFactory( // getDocuments const getDocumentsHandler = getDocumentsHandlerFactory( - driveClient, handleAbciResponseError, + driveClient, ); const wrappedGetDocuments = jsonToProtobufHandlerWrapper( @@ -148,7 +148,7 @@ function platformHandlersFactory( // getDataContract const getDataContractHandler = getDataContractHandlerFactory( - driveClient, handleAbciResponseError, + driveClient, ); const wrappedGetDataContract = jsonToProtobufHandlerWrapper( @@ -164,7 +164,7 @@ function platformHandlersFactory( // getIdentitiesByPublicKeyHashes const getIdentitiesByPublicKeyHashesHandler = getIdentitiesByPublicKeyHashesHandlerFactory( - driveClient, handleAbciResponseError, + driveClient, ); const wrappedGetIdentitiesByPublicKeyHashes = jsonToProtobufHandlerWrapper( @@ -180,7 +180,7 @@ function platformHandlersFactory( // getIdentityIdsByPublicKeyHashes const getIdentityIdsByPublicKeyHashesHandler = getIdentityIdsByPublicKeyHashesHandlerFactory( - driveClient, handleAbciResponseError, + driveClient, ); const wrappedGetIdentityIdsByPublicKeyHashes = jsonToProtobufHandlerWrapper( diff --git a/package-lock.json b/package-lock.json index 5d80c509f..ba28d17a0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,52 +24,52 @@ } }, "@babel/generator": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.0.tgz", - "integrity": "sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.4.tgz", + "integrity": "sha512-d3itta0tu+UayjEORPNz6e1T3FtvWlP5N4V5M+lhp/CxT4oAA7/NcScnpRyspUMLK6tu9MNHmQHxRykuN2R7hw==", "dev": true, "requires": { - "@babel/types": "^7.15.0", + "@babel/types": "^7.15.4", "jsesc": "^2.5.1", "source-map": "^0.5.0" } }, "@babel/helper-function-name": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz", - "integrity": "sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz", + "integrity": "sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.14.5", - "@babel/template": "^7.14.5", - "@babel/types": "^7.14.5" + "@babel/helper-get-function-arity": "^7.15.4", + "@babel/template": "^7.15.4", + "@babel/types": "^7.15.4" } }, "@babel/helper-get-function-arity": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz", - "integrity": "sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz", + "integrity": "sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA==", "dev": true, "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.15.4" } }, "@babel/helper-hoist-variables": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz", - "integrity": "sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz", + "integrity": "sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA==", "dev": true, "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.15.4" } }, "@babel/helper-split-export-declaration": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz", - "integrity": "sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.15.4.tgz", + "integrity": "sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw==", "dev": true, "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.15.4" } }, "@babel/helper-validator-identifier": { @@ -90,43 +90,43 @@ } }, "@babel/parser": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", - "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.4.tgz", + "integrity": "sha512-xmzz+7fRpjrvDUj+GV7zfz/R3gSK2cOxGlazaXooxspCr539cbTXJKvBJzSVI2pPhcRGquoOtaIkKCsHQUiO3w==", "dev": true }, "@babel/template": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", - "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.15.4.tgz", + "integrity": "sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg==", "dev": true, "requires": { "@babel/code-frame": "^7.14.5", - "@babel/parser": "^7.14.5", - "@babel/types": "^7.14.5" + "@babel/parser": "^7.15.4", + "@babel/types": "^7.15.4" } }, "@babel/traverse": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.0.tgz", - "integrity": "sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.4.tgz", + "integrity": "sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA==", "dev": true, "requires": { "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.0", - "@babel/helper-function-name": "^7.14.5", - "@babel/helper-hoist-variables": "^7.14.5", - "@babel/helper-split-export-declaration": "^7.14.5", - "@babel/parser": "^7.15.0", - "@babel/types": "^7.15.0", + "@babel/generator": "^7.15.4", + "@babel/helper-function-name": "^7.15.4", + "@babel/helper-hoist-variables": "^7.15.4", + "@babel/helper-split-export-declaration": "^7.15.4", + "@babel/parser": "^7.15.4", + "@babel/types": "^7.15.4", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.4.tgz", + "integrity": "sha512-0f1HJFuGmmbrKTCZtbm3cU+b/AqdEYk5toj5iQur58xkVMlS0JWaKxTBSmCXd47uiN7vbcozAupm6Mvs80GNhw==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.14.9", @@ -196,9 +196,9 @@ }, "dependencies": { "@types/node": { - "version": "12.20.20", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.20.tgz", - "integrity": "sha512-kqmxiJg4AT7rsSPIhO6eoBIx9mNwwpeH42yjtgQh6X2ANSpLpvToMXv+LMFdfxpwG1FZXZ41OGZMiUAtbBLEvg==" + "version": "12.20.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.23.tgz", + "integrity": "sha512-FW0q7NI8UnjbKrJK8NGr6QXY69ATw9IFe6ItIo5yozPwA9DU/xkhiPddctUVyrmFXvyFYerYgQak/qu200UBDw==" } } }, @@ -224,9 +224,8 @@ } }, "@dashevo/dpp": { - "version": "0.21.0-dev.3", - "resolved": "https://registry.npmjs.org/@dashevo/dpp/-/dpp-0.21.0-dev.3.tgz", - "integrity": "sha512-LhtwemScbTU6mwJKsVpYSZkXbGXJ73H2Zyo5bxfGnVNI1p4HAbTaMSiheG3g6OU+RV28fadq9plUPnM+lE10Ug==", + "version": "github:dashevo/js-dpp#107bd86fb4eead2c3f2b4fd5aefba98f0388b83b", + "from": "github:dashevo/js-dpp#error-necessary-data", "requires": { "@apidevtools/json-schema-ref-parser": "^8.0.0", "@dashevo/dashcore-lib": "~0.19.25", @@ -421,15 +420,21 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, "@types/long": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" }, "@types/node": { - "version": "16.7.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.1.tgz", - "integrity": "sha512-ncRdc45SoYJ2H4eWU9ReDfp3vtFqDYhjOsKlFFUDEn8V1Bgr2RjYal8YT5byfadWIRluhPFU6JiDOl0H6Sl87A==" + "version": "16.7.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.10.tgz", + "integrity": "sha512-S63Dlv4zIPb8x6MMTgDq5WWRJQe56iBEY0O3SOFA9JrRienkOVDXSXBjjJw6HTNQYSE2JI6GMCR6LVbIMHJVvA==" }, "@ungap/promise-all-settled": { "version": "1.1.2", @@ -534,9 +539,9 @@ "dev": true }, "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", "requires": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" @@ -888,6 +893,7 @@ "requires": { "anymatch": "~3.1.1", "braces": "~3.0.2", + "fsevents": "~2.3.1", "glob-parent": "~5.1.0", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", @@ -1539,9 +1545,9 @@ } }, "eslint-plugin-import": { - "version": "2.24.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.24.1.tgz", - "integrity": "sha512-KSFWhNxPH8OGJwpRJJs+Z7I0a13E2iFQZJIvSnCu6KUs4qmgAm3xN9GYBCSoiGWmwA7gERZPXqYQjcoCROnYhQ==", + "version": "2.24.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.24.2.tgz", + "integrity": "sha512-hNVtyhiEtZmpsabL4neEj+6M5DCLgpYyG9nzJY8lZQeQXEn5UPW1DpUdsMHMXsq98dbNm7nt1w9ZMSVpfJdi8Q==", "dev": true, "requires": { "array-includes": "^3.1.3", @@ -1558,7 +1564,7 @@ "pkg-up": "^2.0.0", "read-pkg-up": "^3.0.0", "resolve": "^1.20.0", - "tsconfig-paths": "^3.10.1" + "tsconfig-paths": "^3.11.0" }, "dependencies": { "debug": { @@ -1846,9 +1852,9 @@ "dev": true }, "follow-redirects": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.2.tgz", - "integrity": "sha512-yLR6WaE2lbF0x4K2qE2p9PEXKLDjUjnR/xmjS3wHAYxtlsI9MLLBJUZirAHKzUZDGLxje7w/cXR49WOUo4rbsA==", + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.3.tgz", + "integrity": "sha512-3MkHxknWMUtb23apkgz/83fDoe+y+qr0TdgacGIA7bew+QLBo3vdgEN2xEsuXNivpFy4CyDhBBZnNZOtalmenw==", "dev": true }, "foreground-child": { @@ -1915,6 +1921,13 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -2658,12 +2671,12 @@ } }, "json5": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", - "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dev": true, "requires": { - "minimist": "^1.2.5" + "minimist": "^1.2.0" } }, "jsonparse": { @@ -3130,9 +3143,9 @@ "dev": true }, "mongodb": { - "version": "3.6.11", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.11.tgz", - "integrity": "sha512-4Y4lTFHDHZZdgMaHmojtNAlqkvddX2QQBEN0K//GzxhGwlI9tZ9R0vhbjr1Decw+TF7qK0ZLjQT292XgHRRQgw==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.0.tgz", + "integrity": "sha512-JOAYjT9WYeRFkIP6XtDidAr3qvpfLRJhT2iokRWWH0tgqCQr9kmSfOJBZ3Ry0E5A3EqKxVPVhN3MV8Gn03o7pA==", "dev": true, "requires": { "bl": "^2.2.1", @@ -3226,9 +3239,9 @@ } }, "node-abi": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.0.tgz", - "integrity": "sha512-g6bZh3YCKQRdwuO/tSZZYJAw622SjsRfJ2X0Iy4sSOHZ34/sPPdVBn8fev2tj7njzLwuqPw9uMtGsGkO5kIQvg==", + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", + "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", "requires": { "semver": "^5.4.1" }, @@ -4672,12 +4685,13 @@ } }, "tsconfig-paths": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.10.1.tgz", - "integrity": "sha512-rETidPDgCpltxF7MjBZlAFPUHv5aHH2MymyPvh+vEyWAED4Eb/WeMbsnD/JDr4OKPOA1TssDHgIcpTN5Kh0p6Q==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz", + "integrity": "sha512-7ecdYDnIdmv639mmDwslG6KQg1Z9STTz1j7Gcz0xa+nshh/gKDAHcPxRbWOsA3SPp0tXP2leTcY9Kw+NAkfZzA==", "dev": true, "requires": { - "json5": "^2.2.0", + "@types/json5": "^0.0.29", + "json5": "^1.0.1", "minimist": "^1.2.0", "strip-bom": "^3.0.0" } @@ -4931,9 +4945,9 @@ } }, "ws": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz", - "integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==" + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.4.tgz", + "integrity": "sha512-zP9z6GXm6zC27YtspwH99T3qTG7bBFv2VIkeHstMLrLlDJuzA7tQ5ls3OJ1hOGGCzTQPniNJoHXIAOS0Jljohg==" }, "y18n": { "version": "5.0.8", diff --git a/package.json b/package.json index cf659e2fa..160d4a4f8 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "@dashevo/dapi-grpc": "~0.21.0-dev.8", "@dashevo/dashcore-lib": "~0.19.25", "@dashevo/dashd-rpc": "^2.0.2", - "@dashevo/dpp": "~0.21.0-dev.2", + "@dashevo/dpp": "github:dashevo/js-dpp#error-necessary-data", "@dashevo/grpc-common": "~0.4.0", "@grpc/grpc-js": "^1.3.6", "ajv": "^8.6.0", diff --git a/test/unit/externalApis/drive/DriveClient.js b/test/unit/externalApis/drive/DriveClient.js index 4fbb95682..0efd335cf 100644 --- a/test/unit/externalApis/drive/DriveClient.js +++ b/test/unit/externalApis/drive/DriveClient.js @@ -7,10 +7,11 @@ const dirtyChai = require('dirty-chai'); const generateRandomIdentifier = require('@dashevo/dpp/lib/test/utils/generateRandomIdentifier'); const getIdentityFixture = require('@dashevo/dpp/lib/test/fixtures/getIdentityFixture'); +const InvalidArgumentGrpcError = require('@dashevo/grpc-common/lib/server/error/InvalidArgumentGrpcError'); +const GrpcErrorCodes = require('@dashevo/grpc-common/lib/server/error/GrpcErrorCodes'); const DriveClient = require('../../../../lib/externalApis/drive/DriveClient'); const RPCError = require('../../../../lib/rpcServer/RPCError'); -const AbciResponseError = require('../../../../lib/errors/AbciResponseError'); chai.use(chaiAsPromised); @@ -45,26 +46,20 @@ describe('DriveClient', () => { } }); - it('should throw ABCI error response have one', async () => { + it('should throw ABCI error if response have one', async () => { const drive = new DriveClient({ host: '127.0.0.1', port: 3000 }); - const abciError = { - message: 'Some ABCI error', - data: { - name: 'someData', - }, - }; - - const responseLog = JSON.stringify({ - error: abciError, - }); - sinon.stub(drive.client, 'request') .resolves({ result: { response: { - code: 42, - log: responseLog, + code: GrpcErrorCodes.INVALID_ARGUMENT, + info: cbor.encode({ + metadata: { + name: 'someData', + }, + message: 'some message', + }).toString('base64'), }, }, }); @@ -72,10 +67,12 @@ describe('DriveClient', () => { try { await drive.fetchDataContract('someId'); } catch (e) { - expect(e).to.be.an.instanceOf(AbciResponseError); - expect(e.getErrorCode()).to.equal(42); - expect(e.getMessage()).to.equal(abciError.message); - expect(e.getData()).to.deep.equal(abciError.data); + expect(e).to.be.an.instanceOf(InvalidArgumentGrpcError); + expect(e.getCode()).to.equal(3); + expect(e.getMessage()).to.equal('some message'); + expect(e.getRawMetadata()).to.deep.equal({ + name: 'someData', + }); } }); diff --git a/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.js b/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.js new file mode 100644 index 000000000..1d214044f --- /dev/null +++ b/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.js @@ -0,0 +1,75 @@ +const GrpcErrorCodes = require('@dashevo/grpc-common/lib/server/error/GrpcErrorCodes'); +const GrpcError = require('@dashevo/grpc-common/lib/server/error/GrpcError'); +const cbor = require('cbor'); +const AbstractConsensusError = require('@dashevo/dpp/lib/errors/consensus/AbstractConsensusError'); +const createGrpcErrorFromDriveResponse = require( + '../../../../lib/grpcServer/handlers/createGrpcErrorFromDriveResponse', +); + +describe('handleAbciResponseError', () => { + let message; + let metadata; + + beforeEach(() => { + message = 'message'; + metadata = cbor.encode({ + message, + metadata: { + error: 'some data', + }, + }).toString('base64'); + }); + + Object.entries(GrpcErrorCodes) + .forEach(([codeClass, code]) => { + it(`should throw ${codeClass} if response code is ${code}`, () => { + try { + createGrpcErrorFromDriveResponse(code, metadata); + } catch (e) { + expect(e).to.be.an.instanceOf(GrpcError); + expect(e.getMessage()).to.equal(message); + expect(e.getCode()).to.equal(code); + } + }); + }); + + it('should throw GrpcError if error code = 17', () => { + try { + createGrpcErrorFromDriveResponse(17, metadata); + } catch (e) { + expect(e).to.be.an.instanceOf(GrpcError); + expect(e.getMessage()).to.equal(message); + expect(e.getCode()).to.equal(17); + } + }); + + it('should throw GrpcError if error code = 99', () => { + try { + createGrpcErrorFromDriveResponse(99, metadata); + } catch (e) { + expect(e).to.be.an.instanceOf(GrpcError); + expect(e.getMessage()).to.equal(message); + expect(e.getCode()).to.equal(99); + } + }); + + it('should throw ConsensusError if error code = 1000', () => { + try { + createGrpcErrorFromDriveResponse(1000, cbor.encode([42, 'a']).toString('base64')); + } catch (e) { + expect(e).to.be.an.instanceOf(AbstractConsensusError); + expect(e.getMessage()).to.equal(message); + expect(e.getCode()).to.equal(1000); + } + }); + + it('should throw Unknown error code >= 5000', () => { + try { + createGrpcErrorFromDriveResponse(5000, metadata); + } catch (e) { + expect(e).to.be.an.instanceOf(GrpcError); + expect(e.getMessage()).to.equal('Unknown error code: 5000'); + expect(e.getCode()).to.equal(5000); + } + }); +}); diff --git a/test/unit/grpcServer/handlers/handleAbciResponseError.js b/test/unit/grpcServer/handlers/handleAbciResponseError.js deleted file mode 100644 index aa0e6d86f..000000000 --- a/test/unit/grpcServer/handlers/handleAbciResponseError.js +++ /dev/null @@ -1,84 +0,0 @@ -const { - server: { - error: { - InternalGrpcError, - InvalidArgumentGrpcError, - DeadlineExceededGrpcError, - ResourceExhaustedGrpcError, - NotFoundGrpcError, - }, - }, -} = require('@dashevo/grpc-common'); - -const handleAbciResponseError = require( - '../../../../lib/grpcServer/handlers/handleAbciResponseError', -); - -const AbciResponseError = require('../../../../lib/errors/AbciResponseError'); - -describe('handleAbciResponseError', () => { - let message; - let data; - - beforeEach(() => { - message = 'message'; - data = { error: 'some data' }; - }); - - [ - { code: 6, errorClass: ResourceExhaustedGrpcError }, - { code: 5, errorClass: DeadlineExceededGrpcError }, - { code: 3, errorClass: NotFoundGrpcError }, - { code: 2, errorClass: InvalidArgumentGrpcError }, - { code: 1, errorClass: InternalGrpcError }, - ].forEach(({ code, errorClass }) => { - it(`should throw ${errorClass.name} if response code is ${code}`, () => { - try { - handleAbciResponseError( - new AbciResponseError(code, { message, data }), - ); - } catch (e) { - expect(e).to.be.an.instanceOf(errorClass); - - if (code === 1) { - expect(e.getMessage()).to.equal('Internal error'); - } else { - expect(e.getMessage()).to.equal(message); - } - } - }); - }); - - it('should throw DeadlineExceededGrpcError if internal timeout error have been received', () => { - try { - handleAbciResponseError( - new AbciResponseError( - 1, - { - message: 'Internal error', - data: 'Timed out waiting for tx to be included in a block', - }, - ), - ); - } catch (e) { - expect(e).to.be.an.instanceOf(DeadlineExceededGrpcError); - expect(e.getMessage()).to.equal('Timed out waiting for tx to be included in a block'); - } - }); - - it('should throw InternalGrpcError if error without data have been received', async () => { - try { - handleAbciResponseError( - new AbciResponseError( - 1, - { - message: 'Internal error', - }, - ), - ); - } catch (e) { - expect(e).to.be.an.instanceOf(InternalGrpcError); - expect(e.getMessage()).to.equal('Internal error'); - } - }); -}); diff --git a/test/unit/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js b/test/unit/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js index 7e2acb844..9a0c96357 100644 --- a/test/unit/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js +++ b/test/unit/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js @@ -16,6 +16,9 @@ const { const DashPlatformProtocol = require('@dashevo/dpp'); const getDataContractFixture = require('@dashevo/dpp/lib/test/fixtures/getDataContractFixture'); +const GrpcErrorCodes = require('@dashevo/grpc-common/lib/server/error/GrpcErrorCodes'); +const NotFoundGrpcError = require('@dashevo/grpc-common/lib/server/error/NotFoundGrpcError'); +const cbor = require('cbor'); const GrpcCallMock = require('../../../../../lib/test/mock/GrpcCallMock'); const broadcastStateTransitionHandlerFactory = require( @@ -30,6 +33,7 @@ describe('broadcastStateTransitionHandlerFactory', () => { let stateTransitionFixture; let log; let code; + let createGrpcErrorFromDriveResponseMock; beforeEach(async function beforeEach() { const dpp = new DashPlatformProtocol(); @@ -70,8 +74,11 @@ describe('broadcastStateTransitionHandlerFactory', () => { request: this.sinon.stub().resolves(response), }; + createGrpcErrorFromDriveResponseMock = this.sinon.stub(); + broadcastStateTransitionHandler = broadcastStateTransitionHandlerFactory( rpcClientMock, + createGrpcErrorFromDriveResponseMock, ); }); @@ -109,6 +116,8 @@ describe('broadcastStateTransitionHandlerFactory', () => { try { await broadcastStateTransitionHandler(call); + + expect.fail('should throw an error'); } catch (e) { expect(e.message).to.equal(error.message); expect(e.data).to.equal(error.data); @@ -125,9 +134,36 @@ describe('broadcastStateTransitionHandlerFactory', () => { try { await broadcastStateTransitionHandler(call); + + expect.fail('should throw AlreadyExistsGrpcError'); } catch (e) { expect(e).to.be.an.instanceOf(AlreadyExistsGrpcError); expect(e.getMessage()).to.equal('State transition already in chain'); } }); + + it('should throw GrpcError if error code is not 0', async () => { + const message = 'not found'; + const metadata = { + data: 'some data', + }; + + createGrpcErrorFromDriveResponseMock.returns( + new NotFoundGrpcError(message, metadata), + ); + + response.result.code = GrpcErrorCodes.NOT_FOUND; + response.result.info = cbor.encode({ message, metadata }).toString('base64'); + + try { + await broadcastStateTransitionHandler(call); + + expect.fail('should throw AlreadyExistsGrpcError'); + } catch (e) { + expect(e).to.be.an.instanceOf(NotFoundGrpcError); + expect(e.getMessage()).to.equal(message); + expect(e.getRawMetadata()).to.deep.equal(metadata); + expect(e.getCode()).to.equal(response.result.code); + } + }); }); diff --git a/test/unit/grpcServer/handlers/platform/getDataContractHandlerFactory.js b/test/unit/grpcServer/handlers/platform/getDataContractHandlerFactory.js index 0ea911e76..4513fbbbf 100644 --- a/test/unit/grpcServer/handlers/platform/getDataContractHandlerFactory.js +++ b/test/unit/grpcServer/handlers/platform/getDataContractHandlerFactory.js @@ -24,8 +24,6 @@ const getDataContractHandlerFactory = require( '../../../../../lib/grpcServer/handlers/platform/getDataContractHandlerFactory', ); -const AbciResponseError = require('../../../../../lib/errors/AbciResponseError'); - describe('getDataContractHandlerFactory', () => { let call; let getDataContractHandler; @@ -33,7 +31,6 @@ describe('getDataContractHandlerFactory', () => { let request; let id; let dataContractFixture; - let handleAbciResponseErrorMock; let proofFixture; let proofMock; let response; @@ -69,11 +66,8 @@ describe('getDataContractHandlerFactory', () => { fetchDataContract: this.sinon.stub().resolves(response.serializeBinary()), }; - handleAbciResponseErrorMock = this.sinon.stub(); - getDataContractHandler = getDataContractHandlerFactory( driveStateRepositoryMock, - handleAbciResponseErrorMock, ); }); @@ -85,8 +79,6 @@ describe('getDataContractHandlerFactory', () => { const contractBinary = result.getDataContract(); expect(contractBinary).to.be.an.instanceOf(Uint8Array); - expect(handleAbciResponseErrorMock).to.not.be.called(); - expect(contractBinary).to.deep.equal(dataContractFixture.toBuffer()); const proof = result.getProof(); @@ -128,33 +120,10 @@ describe('getDataContractHandlerFactory', () => { expect(e).to.be.instanceOf(InvalidArgumentGrpcError); expect(e.getMessage()).to.equal('id is not specified'); expect(driveStateRepositoryMock.fetchDataContract).to.be.not.called(); - expect(handleAbciResponseErrorMock).to.be.not.called(); - } - }); - - it('should throw InvalidArgumentGrpcError if driveStateRepository throws AbciResponseError', async () => { - const code = 2; - const message = 'Some error'; - const data = 42; - const abciResponseError = new AbciResponseError(code, { message, data }); - - const handleError = new InvalidArgumentGrpcError('Another error'); - - handleAbciResponseErrorMock.throws(handleError); - - driveStateRepositoryMock.fetchDataContract.throws(abciResponseError); - - try { - await getDataContractHandler(call); - - expect.fail('should throw InvalidArgumentGrpcError'); - } catch (e) { - expect(e).to.equal(handleError); - expect(handleAbciResponseErrorMock).to.be.calledOnceWith(abciResponseError); } }); - it('should throw error if driveStateRepository throws unknown error', async () => { + it('should throw error if driveStateRepository throws an error', async () => { const message = 'Some error'; const abciResponseError = new Error(message); @@ -166,7 +135,6 @@ describe('getDataContractHandlerFactory', () => { expect.fail('should throw error'); } catch (e) { expect(e).to.equal(abciResponseError); - expect(handleAbciResponseErrorMock).to.be.not.called(); } }); }); diff --git a/test/unit/grpcServer/handlers/platform/getDocumentsHandlerFactory.js b/test/unit/grpcServer/handlers/platform/getDocumentsHandlerFactory.js index 016ce083d..90bf6a685 100644 --- a/test/unit/grpcServer/handlers/platform/getDocumentsHandlerFactory.js +++ b/test/unit/grpcServer/handlers/platform/getDocumentsHandlerFactory.js @@ -26,8 +26,6 @@ const getDocumentsHandlerFactory = require( '../../../../../lib/grpcServer/handlers/platform/getDocumentsHandlerFactory', ); -const AbciResponseError = require('../../../../../lib/errors/AbciResponseError'); - describe('getDocumentsHandlerFactory', () => { let call; let getDocumentsHandler; @@ -41,7 +39,6 @@ describe('getDocumentsHandlerFactory', () => { let limit; let startAfter; let startAt; - let handleAbciResponseErrorMock; let documentsSerialized; let proofFixture; let response; @@ -95,11 +92,8 @@ describe('getDocumentsHandlerFactory', () => { fetchDocuments: this.sinon.stub().resolves(response.serializeBinary()), }; - handleAbciResponseErrorMock = this.sinon.stub(); - getDocumentsHandler = getDocumentsHandlerFactory( driveStateRepositoryMock, - handleAbciResponseErrorMock, ); }); @@ -130,7 +124,6 @@ describe('getDocumentsHandlerFactory', () => { ); expect(documentsBinary[0]).to.deep.equal(documentsSerialized[0]); - expect(handleAbciResponseErrorMock).to.be.not.called(); const proof = result.getProof(); @@ -157,8 +150,6 @@ describe('getDocumentsHandlerFactory', () => { true, ); - expect(handleAbciResponseErrorMock).to.be.not.called(); - const proof = result.getProof(); expect(proof).to.be.an.instanceOf(Proof); @@ -181,7 +172,6 @@ describe('getDocumentsHandlerFactory', () => { expect(e).to.be.instanceOf(InvalidArgumentGrpcError); expect(e.getMessage()).to.equal('dataContractId is not specified'); expect(driveStateRepositoryMock.fetchDocuments).to.be.not.called(); - expect(handleAbciResponseErrorMock).to.be.not.called(); } }); @@ -197,32 +187,10 @@ describe('getDocumentsHandlerFactory', () => { expect(e).to.be.instanceOf(InvalidArgumentGrpcError); expect(e.getMessage()).to.equal('documentType is not specified'); expect(driveStateRepositoryMock.fetchDocuments).to.be.not.called(); - expect(handleAbciResponseErrorMock).to.be.not.called(); - } - }); - - it('should throw InvalidArgumentGrpcError if fetchDocuments throws AbciResponseError', async () => { - const code = 2; - const message = 'Some error'; - const data = 42; - const abciResponseError = new AbciResponseError(code, { message, data }); - const handleError = new InvalidArgumentGrpcError('Another error'); - - handleAbciResponseErrorMock.throws(handleError); - - driveStateRepositoryMock.fetchDocuments.throws(abciResponseError); - - try { - await getDocumentsHandler(call); - - expect.fail('should throw InvalidArgumentGrpcError error'); - } catch (e) { - expect(e).to.equal(handleError); - expect(handleAbciResponseErrorMock).to.be.calledOnceWith(abciResponseError); } }); - it('should throw error if fetchDocuments throws unknown error', async () => { + it('should throw error if fetchDocuments throws an error', async () => { const error = new Error('Some error'); driveStateRepositoryMock.fetchDocuments.throws(error); @@ -233,7 +201,6 @@ describe('getDocumentsHandlerFactory', () => { expect.fail('should throw InvalidArgumentGrpcError error'); } catch (e) { expect(e).to.equal(error); - expect(handleAbciResponseErrorMock).to.not.be.called(); } }); }); diff --git a/test/unit/grpcServer/handlers/platform/getIdentitiesByPublicKeyHashesHandlerFactory.js b/test/unit/grpcServer/handlers/platform/getIdentitiesByPublicKeyHashesHandlerFactory.js index d5eb53bdc..e31f62534 100644 --- a/test/unit/grpcServer/handlers/platform/getIdentitiesByPublicKeyHashesHandlerFactory.js +++ b/test/unit/grpcServer/handlers/platform/getIdentitiesByPublicKeyHashesHandlerFactory.js @@ -22,12 +22,9 @@ const getIdentitiesByPublicKeyHashesHandlerFactory = require( const GrpcCallMock = require('../../../../../lib/test/mock/GrpcCallMock'); -const AbciResponseError = require('../../../../../lib/errors/AbciResponseError'); - describe('getIdentitiesByPublicKeyHashesHandlerFactory', () => { let call; let driveStateRepositoryMock; - let handleAbciResponseErrorMock; let getIdentitiesByPublicKeyHashesHandler; let identity; let publicKeyHash; @@ -48,7 +45,6 @@ describe('getIdentitiesByPublicKeyHashesHandlerFactory', () => { identity = getIdentityFixture(); - handleAbciResponseErrorMock = this.sinon.stub(); proofFixture = { rootTreeProof: Buffer.alloc(1, 1), storeTreeProof: Buffer.alloc(1, 2), @@ -71,7 +67,6 @@ describe('getIdentitiesByPublicKeyHashesHandlerFactory', () => { getIdentitiesByPublicKeyHashesHandler = getIdentitiesByPublicKeyHashesHandlerFactory( driveStateRepositoryMock, - handleAbciResponseErrorMock, ); }); @@ -90,8 +85,6 @@ describe('getIdentitiesByPublicKeyHashesHandlerFactory', () => { expect(driveStateRepositoryMock.fetchIdentitiesByPublicKeyHashes) .to.be.calledOnceWith([publicKeyHash], false); - expect(handleAbciResponseErrorMock).to.not.be.called(); - const proof = result.getProof(); expect(proof).to.be.undefined(); @@ -124,33 +117,10 @@ describe('getIdentitiesByPublicKeyHashesHandlerFactory', () => { expect(e).to.be.instanceOf(InvalidArgumentGrpcError); expect(e.getMessage()).to.equal('No public key hashes were provided'); expect(driveStateRepositoryMock.fetchIdentitiesByPublicKeyHashes).to.not.be.called(); - expect(handleAbciResponseErrorMock).to.not.be.called(); - } - }); - - it('should throw an error when fetchIdentity throws an AbciResponseError', async () => { - const code = 2; - const message = 'Some error'; - const data = 42; - const abciResponseError = new AbciResponseError(code, { message, data }); - const handleError = new InvalidArgumentGrpcError('Another error'); - - driveStateRepositoryMock.fetchIdentitiesByPublicKeyHashes.throws(abciResponseError); - handleAbciResponseErrorMock.throws(handleError); - - try { - await getIdentitiesByPublicKeyHashesHandler(call); - - expect.fail('should throw an error'); - } catch (e) { - expect(e).to.equal(handleError); - expect(driveStateRepositoryMock.fetchIdentitiesByPublicKeyHashes) - .to.be.calledOnceWith([publicKeyHash]); - expect(handleAbciResponseErrorMock).to.be.calledOnceWith(abciResponseError); } }); - it('should throw an error when fetchIdentity throws unknown error', async () => { + it('should throw an error when fetchIdentity throws an error', async () => { const error = new Error('Unknown error'); driveStateRepositoryMock.fetchIdentitiesByPublicKeyHashes.throws(error); @@ -163,7 +133,6 @@ describe('getIdentitiesByPublicKeyHashesHandlerFactory', () => { expect(e).to.equal(error); expect(driveStateRepositoryMock.fetchIdentitiesByPublicKeyHashes) .to.be.calledOnceWith([publicKeyHash]); - expect(handleAbciResponseErrorMock).to.not.be.called(); } }); }); diff --git a/test/unit/grpcServer/handlers/platform/getIdentityHandlerFactory.js b/test/unit/grpcServer/handlers/platform/getIdentityHandlerFactory.js index 7f96c16c2..abd187616 100644 --- a/test/unit/grpcServer/handlers/platform/getIdentityHandlerFactory.js +++ b/test/unit/grpcServer/handlers/platform/getIdentityHandlerFactory.js @@ -22,14 +22,10 @@ const getIdentityHandlerFactory = require('../../../../../lib/grpcServer/handler const GrpcCallMock = require('../../../../../lib/test/mock/GrpcCallMock'); -const AbciResponseError = require('../../../../../lib/errors/AbciResponseError'); - - describe('getIdentityHandlerFactory', () => { let call; let driveStateRepositoryMock; let id; - let handleAbciResponseErrorMock; let getIdentityHandler; let identity; let proofFixture; @@ -62,15 +58,12 @@ describe('getIdentityHandlerFactory', () => { response.setProof(proofMock); response.setIdentity(identity.toBuffer()); - handleAbciResponseErrorMock = this.sinon.stub(); - driveStateRepositoryMock = { fetchIdentity: this.sinon.stub().resolves(response.serializeBinary()), }; getIdentityHandler = getIdentityHandlerFactory( driveStateRepositoryMock, - handleAbciResponseErrorMock, ); }); @@ -83,7 +76,6 @@ describe('getIdentityHandlerFactory', () => { expect(result).to.be.an.instanceOf(GetIdentityResponse); expect(result.getIdentity()).to.deep.equal(identity.toBuffer()); expect(driveStateRepositoryMock.fetchIdentity).to.be.calledOnceWith(id, false); - expect(handleAbciResponseErrorMock).to.not.be.called(); const proof = result.getProof(); expect(proof).to.be.undefined(); @@ -119,28 +111,6 @@ describe('getIdentityHandlerFactory', () => { expect(e).to.be.instanceOf(InvalidArgumentGrpcError); expect(e.getMessage()).to.equal('id is not specified'); expect(driveStateRepositoryMock.fetchIdentity).to.not.be.called(); - expect(handleAbciResponseErrorMock).to.not.be.called(); - } - }); - - it('should throw an error when fetchIdentity throws an AbciResponseError', async () => { - const code = 2; - const message = 'Some error'; - const data = 42; - const abciResponseError = new AbciResponseError(code, { message, data }); - const handleError = new InvalidArgumentGrpcError('Another error'); - - driveStateRepositoryMock.fetchIdentity.throws(abciResponseError); - handleAbciResponseErrorMock.throws(handleError); - - try { - await getIdentityHandler(call); - - expect.fail('should throw an error'); - } catch (e) { - expect(e).to.equal(handleError); - expect(driveStateRepositoryMock.fetchIdentity).to.be.calledOnceWith(id); - expect(handleAbciResponseErrorMock).to.be.calledOnceWith(abciResponseError); } }); @@ -156,7 +126,6 @@ describe('getIdentityHandlerFactory', () => { } catch (e) { expect(e).to.equal(error); expect(driveStateRepositoryMock.fetchIdentity).to.be.calledOnceWith(id); - expect(handleAbciResponseErrorMock).to.not.be.called(); } }); }); diff --git a/test/unit/grpcServer/handlers/platform/getIdentityIdsByPublicKeyHashesHandlerFactory.js b/test/unit/grpcServer/handlers/platform/getIdentityIdsByPublicKeyHashesHandlerFactory.js index 4dc7b8fe6..c8e40fa5c 100644 --- a/test/unit/grpcServer/handlers/platform/getIdentityIdsByPublicKeyHashesHandlerFactory.js +++ b/test/unit/grpcServer/handlers/platform/getIdentityIdsByPublicKeyHashesHandlerFactory.js @@ -22,12 +22,9 @@ const getIdentityIdsByPublicKeyHashesHandlerFactory = require( const GrpcCallMock = require('../../../../../lib/test/mock/GrpcCallMock'); -const AbciResponseError = require('../../../../../lib/errors/AbciResponseError'); - describe('getIdentityIdsByPublicKeyHashesHandlerFactory', () => { let call; let driveStateRepositoryMock; - let handleAbciResponseErrorMock; let getIdentityIdsByPublicKeyHashesHandler; let identity; let publicKeyHash; @@ -48,8 +45,6 @@ describe('getIdentityIdsByPublicKeyHashesHandlerFactory', () => { identity = getIdentityFixture(); - handleAbciResponseErrorMock = this.sinon.stub(); - proofFixture = { rootTreeProof: Buffer.alloc(1, 1), storeTreeProof: Buffer.alloc(1, 2), @@ -72,7 +67,6 @@ describe('getIdentityIdsByPublicKeyHashesHandlerFactory', () => { getIdentityIdsByPublicKeyHashesHandler = getIdentityIdsByPublicKeyHashesHandlerFactory( driveStateRepositoryMock, - handleAbciResponseErrorMock, ); }); @@ -91,8 +85,6 @@ describe('getIdentityIdsByPublicKeyHashesHandlerFactory', () => { expect(driveStateRepositoryMock.fetchIdentityIdsByPublicKeyHashes) .to.be.calledOnceWith([publicKeyHash], false); - expect(handleAbciResponseErrorMock).to.not.be.called(); - const proof = result.getProof(); expect(proof).to.be.undefined(); }); @@ -127,33 +119,10 @@ describe('getIdentityIdsByPublicKeyHashesHandlerFactory', () => { expect(e).to.be.instanceOf(InvalidArgumentGrpcError); expect(e.getMessage()).to.equal('No public key hashes were provided'); expect(driveStateRepositoryMock.fetchIdentityIdsByPublicKeyHashes).to.not.be.called(); - expect(handleAbciResponseErrorMock).to.not.be.called(); - } - }); - - it('should throw an error when fetchIdentity throws an AbciResponseError', async () => { - const code = 2; - const message = 'Some error'; - const data = 42; - const abciResponseError = new AbciResponseError(code, { message, data }); - const handleError = new InvalidArgumentGrpcError('Another error'); - - driveStateRepositoryMock.fetchIdentityIdsByPublicKeyHashes.throws(abciResponseError); - handleAbciResponseErrorMock.throws(handleError); - - try { - await getIdentityIdsByPublicKeyHashesHandler(call); - - expect.fail('should throw an error'); - } catch (e) { - expect(e).to.equal(handleError); - expect(driveStateRepositoryMock.fetchIdentityIdsByPublicKeyHashes) - .to.be.calledOnceWith([publicKeyHash]); - expect(handleAbciResponseErrorMock).to.be.calledOnceWith(abciResponseError); } }); - it('should throw an error when fetchIdentity throws unknown error', async () => { + it('should throw an error when fetchIdentity throws an error', async () => { const error = new Error('Unknown error'); driveStateRepositoryMock.fetchIdentityIdsByPublicKeyHashes.throws(error); @@ -166,7 +135,6 @@ describe('getIdentityIdsByPublicKeyHashesHandlerFactory', () => { expect(e).to.equal(error); expect(driveStateRepositoryMock.fetchIdentityIdsByPublicKeyHashes) .to.be.calledOnceWith([publicKeyHash]); - expect(handleAbciResponseErrorMock).to.not.be.called(); } }); }); From 08ee6e24e8468018717bc09f689a7c57f3afe018 Mon Sep 17 00:00:00 2001 From: Konstantin Shuplenkov Date: Tue, 7 Sep 2021 18:46:03 +0300 Subject: [PATCH 02/15] fix: PR comments --- .../createGrpcErrorFromDriveResponse.js | 4 +-- .../broadcastStateTransitionHandlerFactory.js | 10 +++++- .../createGrpcErrorFromDriveResponse.js | 2 +- .../broadcastStateTransitionHandlerFactory.js | 31 +++++++++++++++++++ 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js b/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js index 1633e0fb5..0d783b0e2 100644 --- a/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js +++ b/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js @@ -58,7 +58,7 @@ function createGrpcErrorFromDriveResponse(code, info) { return new GrpcError(code, decodedInfo.message, decodedInfo.metadata); } - if (code >= 17 && code < 100) { + if (code >= 17 && code < 1000) { return new GrpcError(code, decodedInfo.message, decodedInfo.metadata); } @@ -66,7 +66,7 @@ function createGrpcErrorFromDriveResponse(code, info) { return createConsensusError(code, decodedInfo); } - return new GrpcError(code, `Unknown error code: ${code}`, decodedInfo); + return new GrpcError(GrpcErrorCodes.INTERNAL, `Unknown error code: ${code}`, decodedInfo); } module.exports = createGrpcErrorFromDriveResponse; diff --git a/lib/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js b/lib/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js index 2ed9e20af..c8a66659c 100644 --- a/lib/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js @@ -12,6 +12,7 @@ const { BroadcastStateTransitionResponse, }, } = require('@dashevo/dapi-grpc'); +const InternalGrpcError = require('@dashevo/grpc-common/lib/server/error/InternalGrpcError'); /** * @param {jaysonClient} rpcClient @@ -50,7 +51,14 @@ function broadcastStateTransitionHandlerFactory(rpcClient, createGrpcErrorFromDr throw error; } - if (result.code !== undefined && result.code !== 0) { + if (result.code === undefined) { + const error = new Error(); + Object.assign(error, result); + + throw new InternalGrpcError(error); + } + + if (result.code !== 0) { throw createGrpcErrorFromDriveResponse(result.code, result.info); } diff --git a/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.js b/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.js index 1d214044f..f18bc28e9 100644 --- a/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.js +++ b/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.js @@ -6,7 +6,7 @@ const createGrpcErrorFromDriveResponse = require( '../../../../lib/grpcServer/handlers/createGrpcErrorFromDriveResponse', ); -describe('handleAbciResponseError', () => { +describe('createGrpcErrorFromDriveResponse', () => { let message; let metadata; diff --git a/test/unit/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js b/test/unit/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js index 9a0c96357..d39aab562 100644 --- a/test/unit/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js +++ b/test/unit/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js @@ -19,6 +19,7 @@ const getDataContractFixture = require('@dashevo/dpp/lib/test/fixtures/getDataCo const GrpcErrorCodes = require('@dashevo/grpc-common/lib/server/error/GrpcErrorCodes'); const NotFoundGrpcError = require('@dashevo/grpc-common/lib/server/error/NotFoundGrpcError'); const cbor = require('cbor'); +const InternalGrpcError = require('@dashevo/grpc-common/lib/server/error/InternalGrpcError'); const GrpcCallMock = require('../../../../../lib/test/mock/GrpcCallMock'); const broadcastStateTransitionHandlerFactory = require( @@ -67,6 +68,7 @@ describe('broadcastStateTransitionHandlerFactory', () => { hash: 'B762539A7C17C33A65C46727BFCF2C701390E6AD7DE5190B6CC1CF843CA7E262', height: '24', + code, }, }; @@ -164,6 +166,35 @@ describe('broadcastStateTransitionHandlerFactory', () => { expect(e.getMessage()).to.equal(message); expect(e.getRawMetadata()).to.deep.equal(metadata); expect(e.getCode()).to.equal(response.result.code); + expect(createGrpcErrorFromDriveResponseMock).to.be.calledWithExactly( + response.result.code, + response.result.info, + ); + } + }); + + it('should throw InternalGrpcError result codes is undefined', async () => { + const message = 'not found'; + const metadata = { + data: 'some data', + }; + + createGrpcErrorFromDriveResponseMock.returns( + new NotFoundGrpcError(message, metadata), + ); + + response.result.code = undefined; + response.result.info = cbor.encode({ message, metadata }).toString('base64'); + + try { + await broadcastStateTransitionHandler(call); + + expect.fail('should throw InternalGrpcError'); + } catch (e) { + expect(e).to.be.an.instanceOf(InternalGrpcError); + expect(e.getMessage()).to.equal('Internal error'); + expect(e.getError().info).to.deep.equal(response.result.info); + expect(createGrpcErrorFromDriveResponseMock).to.not.be.called(); } }); }); From 9286d6f0226112748f0cd54227127dfb28b67d4a Mon Sep 17 00:00:00 2001 From: Konstantin Shuplenkov Date: Wed, 8 Sep 2021 13:32:16 +0300 Subject: [PATCH 03/15] fix: PR comments --- .../createGrpcErrorFromDriveResponse.js | 9 ++++--- .../broadcastStateTransitionHandlerFactory.js | 8 ------ .../createGrpcErrorFromDriveResponse.js | 11 ++++++++ .../broadcastStateTransitionHandlerFactory.js | 26 ------------------- 4 files changed, 16 insertions(+), 38 deletions(-) diff --git a/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js b/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js index 0d783b0e2..0d6db01e7 100644 --- a/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js +++ b/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js @@ -16,7 +16,6 @@ const { const GrpcErrorCodes = require('@dashevo/grpc-common/lib/server/error/GrpcErrorCodes'); const createConsensusError = require('@dashevo/dpp/lib/errors/consensus/createConsensusError'); const AlreadyExistsGrpcError = require('@dashevo/grpc-common/lib/server/error/AlreadyExistsGrpcError'); -const VersionMismatchGrpcError = require('@dashevo/grpc-common/lib/server/error/VersionMismatchGrpcError'); /** * @typedef createGrpcErrorFromDriveResponse @@ -25,6 +24,10 @@ const VersionMismatchGrpcError = require('@dashevo/grpc-common/lib/server/error/ * @return {GrpcError} */ function createGrpcErrorFromDriveResponse(code, info) { + if (code === undefined) { + return new InternalGrpcError('Drive’s error code is empty'); + } + const decodedInfo = cbor.decode(Buffer.from(info, 'base64')); // eslint-disable-next-line default-case @@ -45,8 +48,6 @@ function createGrpcErrorFromDriveResponse(code, info) { return new InternalGrpcError(decodedInfo.message, decodedInfo.metadata); case GrpcErrorCodes.UNAVAILABLE: return new UnavailableGrpcError(decodedInfo.message, decodedInfo.metadata); - case GrpcErrorCodes.VERSION_MISMATCH: - return new VersionMismatchGrpcError(decodedInfo.metadata); case GrpcErrorCodes.CANCELLED: case GrpcErrorCodes.UNKNOWN: case GrpcErrorCodes.UNAUTHENTICATED: @@ -66,7 +67,7 @@ function createGrpcErrorFromDriveResponse(code, info) { return createConsensusError(code, decodedInfo); } - return new GrpcError(GrpcErrorCodes.INTERNAL, `Unknown error code: ${code}`, decodedInfo); + return new GrpcError(GrpcErrorCodes.INTERNAL, `Unknown Drive’s error code: ${code}`, decodedInfo); } module.exports = createGrpcErrorFromDriveResponse; diff --git a/lib/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js b/lib/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js index c8a66659c..0c67810f7 100644 --- a/lib/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js @@ -12,7 +12,6 @@ const { BroadcastStateTransitionResponse, }, } = require('@dashevo/dapi-grpc'); -const InternalGrpcError = require('@dashevo/grpc-common/lib/server/error/InternalGrpcError'); /** * @param {jaysonClient} rpcClient @@ -51,13 +50,6 @@ function broadcastStateTransitionHandlerFactory(rpcClient, createGrpcErrorFromDr throw error; } - if (result.code === undefined) { - const error = new Error(); - Object.assign(error, result); - - throw new InternalGrpcError(error); - } - if (result.code !== 0) { throw createGrpcErrorFromDriveResponse(result.code, result.info); } diff --git a/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.js b/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.js index f18bc28e9..625a20d8c 100644 --- a/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.js +++ b/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.js @@ -2,6 +2,7 @@ const GrpcErrorCodes = require('@dashevo/grpc-common/lib/server/error/GrpcErrorC const GrpcError = require('@dashevo/grpc-common/lib/server/error/GrpcError'); const cbor = require('cbor'); const AbstractConsensusError = require('@dashevo/dpp/lib/errors/consensus/AbstractConsensusError'); +const InternalGrpcError = require('@dashevo/grpc-common/lib/server/error/InternalGrpcError'); const createGrpcErrorFromDriveResponse = require( '../../../../lib/grpcServer/handlers/createGrpcErrorFromDriveResponse', ); @@ -72,4 +73,14 @@ describe('createGrpcErrorFromDriveResponse', () => { expect(e.getCode()).to.equal(5000); } }); + + + it('should return InternalGrpcError if codes is undefined', async () => { + try { + createGrpcErrorFromDriveResponse(); + } catch (e) { + expect(e).to.be.an.instanceOf(InternalGrpcError); + expect(e.getMessage()).to.equal('Drive’s error code is empty'); + } + }); }); diff --git a/test/unit/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js b/test/unit/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js index d39aab562..ca8df9d57 100644 --- a/test/unit/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js +++ b/test/unit/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js @@ -19,7 +19,6 @@ const getDataContractFixture = require('@dashevo/dpp/lib/test/fixtures/getDataCo const GrpcErrorCodes = require('@dashevo/grpc-common/lib/server/error/GrpcErrorCodes'); const NotFoundGrpcError = require('@dashevo/grpc-common/lib/server/error/NotFoundGrpcError'); const cbor = require('cbor'); -const InternalGrpcError = require('@dashevo/grpc-common/lib/server/error/InternalGrpcError'); const GrpcCallMock = require('../../../../../lib/test/mock/GrpcCallMock'); const broadcastStateTransitionHandlerFactory = require( @@ -172,29 +171,4 @@ describe('broadcastStateTransitionHandlerFactory', () => { ); } }); - - it('should throw InternalGrpcError result codes is undefined', async () => { - const message = 'not found'; - const metadata = { - data: 'some data', - }; - - createGrpcErrorFromDriveResponseMock.returns( - new NotFoundGrpcError(message, metadata), - ); - - response.result.code = undefined; - response.result.info = cbor.encode({ message, metadata }).toString('base64'); - - try { - await broadcastStateTransitionHandler(call); - - expect.fail('should throw InternalGrpcError'); - } catch (e) { - expect(e).to.be.an.instanceOf(InternalGrpcError); - expect(e.getMessage()).to.equal('Internal error'); - expect(e.getError().info).to.deep.equal(response.result.info); - expect(createGrpcErrorFromDriveResponseMock).to.not.be.called(); - } - }); }); From ae5cc332839375dace84d79025e8676f4085626a Mon Sep 17 00:00:00 2001 From: Konstantin Shuplenkov Date: Wed, 8 Sep 2021 13:51:39 +0300 Subject: [PATCH 04/15] fix: PR comments --- lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js b/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js index 0d6db01e7..f93b0ddae 100644 --- a/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js +++ b/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js @@ -67,7 +67,7 @@ function createGrpcErrorFromDriveResponse(code, info) { return createConsensusError(code, decodedInfo); } - return new GrpcError(GrpcErrorCodes.INTERNAL, `Unknown Drive’s error code: ${code}`, decodedInfo); + return new InternalGrpcError(`Unknown Drive’s error code: ${code}`); } module.exports = createGrpcErrorFromDriveResponse; From 37eb5a15d166dcc6406071ce781cf87f465d79fa Mon Sep 17 00:00:00 2001 From: Konstantin Shuplenkov Date: Wed, 8 Sep 2021 14:05:27 +0300 Subject: [PATCH 05/15] fix: PR comments --- .../handlers/createGrpcErrorFromDriveResponse.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js b/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js index f93b0ddae..0be885f25 100644 --- a/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js +++ b/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js @@ -25,7 +25,7 @@ const AlreadyExistsGrpcError = require('@dashevo/grpc-common/lib/server/error/Al */ function createGrpcErrorFromDriveResponse(code, info) { if (code === undefined) { - return new InternalGrpcError('Drive’s error code is empty'); + return new InternalGrpcError(new Error('Drive’s error code is empty')); } const decodedInfo = cbor.decode(Buffer.from(info, 'base64')); @@ -44,8 +44,14 @@ function createGrpcErrorFromDriveResponse(code, info) { return new ResourceExhaustedGrpcError(decodedInfo.message, decodedInfo.metadata); case GrpcErrorCodes.FAILED_PRECONDITION: return new FailedPreconditionGrpcError(decodedInfo.message, decodedInfo.metadata); - case GrpcErrorCodes.INTERNAL: - return new InternalGrpcError(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: @@ -67,7 +73,7 @@ function createGrpcErrorFromDriveResponse(code, info) { return createConsensusError(code, decodedInfo); } - return new InternalGrpcError(`Unknown Drive’s error code: ${code}`); + return new InternalGrpcError(new Error(`Unknown Drive’s error code: ${code}`)); } module.exports = createGrpcErrorFromDriveResponse; From 3098fa8adde7b7c1dee0e8e2207c5390a5784270 Mon Sep 17 00:00:00 2001 From: Konstantin Shuplenkov Date: Wed, 8 Sep 2021 14:24:32 +0300 Subject: [PATCH 06/15] fix: PR comments --- .../createGrpcErrorFromDriveResponse.js | 119 +++++++++++------- 1 file changed, 74 insertions(+), 45 deletions(-) diff --git a/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.js b/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.js index 625a20d8c..bfd5bc21a 100644 --- a/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.js +++ b/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.js @@ -9,78 +9,107 @@ const createGrpcErrorFromDriveResponse = require( describe('createGrpcErrorFromDriveResponse', () => { let message; - let metadata; + let info; + let encodedInfo; beforeEach(() => { message = 'message'; - metadata = cbor.encode({ + info = { message, metadata: { error: 'some data', }, - }).toString('base64'); + }; + + encodedInfo = cbor.encode(info).toString('base64'); }); Object.entries(GrpcErrorCodes) .forEach(([codeClass, code]) => { - it(`should throw ${codeClass} if response code is ${code}`, () => { - try { - createGrpcErrorFromDriveResponse(code, metadata); - } catch (e) { - expect(e).to.be.an.instanceOf(GrpcError); - expect(e.getMessage()).to.equal(message); - expect(e.getCode()).to.equal(code); + it(`should throw ${codeClass} if response code is ${code}`, function it() { + if (code === GrpcErrorCodes.INTERNAL) { + // we have this test separate + this.skip(); + } + + const error = createGrpcErrorFromDriveResponse(code, encodedInfo); + + let messageToCheck = message; + + if (code === GrpcErrorCodes.FAILED_PRECONDITION) { + messageToCheck = `Failed precondition: ${messageToCheck}`; } + + expect(error).to.be.an.instanceOf(GrpcError); + expect(error.getMessage()).to.equal(messageToCheck); + expect(error.getCode()).to.equal(code); + expect(error.getRawMetadata()).to.deep.equal(info.metadata); }); }); it('should throw GrpcError if error code = 17', () => { - try { - createGrpcErrorFromDriveResponse(17, metadata); - } catch (e) { - expect(e).to.be.an.instanceOf(GrpcError); - expect(e.getMessage()).to.equal(message); - expect(e.getCode()).to.equal(17); - } + const error = createGrpcErrorFromDriveResponse(17, encodedInfo); + + expect(error).to.be.an.instanceOf(GrpcError); + expect(error.getMessage()).to.equal(message); + expect(error.getCode()).to.equal(17); + expect(error.getRawMetadata()).to.deep.equal(info.metadata); }); it('should throw GrpcError if error code = 99', () => { - try { - createGrpcErrorFromDriveResponse(99, metadata); - } catch (e) { - expect(e).to.be.an.instanceOf(GrpcError); - expect(e.getMessage()).to.equal(message); - expect(e.getCode()).to.equal(99); - } + const error = createGrpcErrorFromDriveResponse(99, encodedInfo); + + expect(error).to.be.an.instanceOf(GrpcError); + expect(error.getMessage()).to.equal(message); + expect(error.getCode()).to.equal(99); + expect(error.getRawMetadata()).to.deep.equal(info.metadata); }); it('should throw ConsensusError if error code = 1000', () => { - try { - createGrpcErrorFromDriveResponse(1000, cbor.encode([42, 'a']).toString('base64')); - } catch (e) { - expect(e).to.be.an.instanceOf(AbstractConsensusError); - expect(e.getMessage()).to.equal(message); - expect(e.getCode()).to.equal(1000); - } + const error = createGrpcErrorFromDriveResponse(1000, cbor.encode([42, 'a']).toString('base64')); + + expect(error).to.be.an.instanceOf(AbstractConsensusError); + expect(error.getConstructorArguments()).to.deep.equal([42, 'a']); + expect(error.getCode()).to.equal(1000); }); it('should throw Unknown error code >= 5000', () => { - try { - createGrpcErrorFromDriveResponse(5000, metadata); - } catch (e) { - expect(e).to.be.an.instanceOf(GrpcError); - expect(e.getMessage()).to.equal('Unknown error code: 5000'); - expect(e.getCode()).to.equal(5000); - } + const error = createGrpcErrorFromDriveResponse(5000, encodedInfo); + + expect(error).to.be.an.instanceOf(GrpcError); + expect(error.getMessage()).to.equal('Internal error'); + expect(error.getError().message).to.deep.equal('Unknown Drive’s error code: 5000'); + }); + + it('should return InternalGrpcError if codes is undefined', () => { + const error = createGrpcErrorFromDriveResponse(); + + expect(error).to.be.an.instanceOf(InternalGrpcError); + expect(error.getMessage()).to.equal('Internal error'); + expect(error.getError().message).to.deep.equal('Drive’s error code is empty'); }); + it('should return InternalGrpcError if code = 13', () => { + const errorInfo = { + message, + metadata: { + ...info.metadata, + stack: { + data: 'stack info', + }, + }, + }; + + const error = createGrpcErrorFromDriveResponse( + GrpcErrorCodes.INTERNAL, + cbor.encode(errorInfo).toString('base64'), + ); - it('should return InternalGrpcError if codes is undefined', async () => { - try { - createGrpcErrorFromDriveResponse(); - } catch (e) { - expect(e).to.be.an.instanceOf(InternalGrpcError); - expect(e.getMessage()).to.equal('Drive’s error code is empty'); - } + expect(error).to.be.an.instanceOf(InternalGrpcError); + expect(error.getMessage()).to.equal('Internal error'); + expect(error.getCode()).to.equal(GrpcErrorCodes.INTERNAL); + expect(error.getError().message).to.deep.equal(message); + expect(error.getError().stack).to.deep.equal(errorInfo.metadata.stack); + expect(error.getRawMetadata()).to.deep.equal(info.metadata); }); }); From b314b16012150c2269f65b7ae8899dc07fe9b1f8 Mon Sep 17 00:00:00 2001 From: Konstantin Shuplenkov Date: Wed, 8 Sep 2021 15:45:42 +0300 Subject: [PATCH 07/15] fix: PR comments --- .../handlers/platform/broadcastStateTransitionHandlerFactory.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js b/test/unit/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js index ca8df9d57..366f71896 100644 --- a/test/unit/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js +++ b/test/unit/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js @@ -143,7 +143,7 @@ describe('broadcastStateTransitionHandlerFactory', () => { } }); - it('should throw GrpcError if error code is not 0', async () => { + it('should throw call createGrpcErrorFromDriveResponse if error code is not 0', async () => { const message = 'not found'; const metadata = { data: 'some data', From 4a0a268f1ec36975e96f273381a6822ac958638f Mon Sep 17 00:00:00 2001 From: Konstantin Shuplenkov Date: Thu, 9 Sep 2021 17:50:12 +0300 Subject: [PATCH 08/15] fix: PR comments --- lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js b/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js index 0be885f25..3e9428b02 100644 --- a/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js +++ b/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js @@ -28,7 +28,7 @@ function createGrpcErrorFromDriveResponse(code, info) { return new InternalGrpcError(new Error('Drive’s error code is empty')); } - const decodedInfo = cbor.decode(Buffer.from(info, 'base64')); + const decodedInfo = info ? cbor.decode(Buffer.from(info, 'base64')) : undefined; // eslint-disable-next-line default-case switch (code) { @@ -70,7 +70,7 @@ function createGrpcErrorFromDriveResponse(code, info) { } if (code >= 1000 && code < 5000) { - return createConsensusError(code, decodedInfo); + return createConsensusError(code, decodedInfo || []); } return new InternalGrpcError(new Error(`Unknown Drive’s error code: ${code}`)); From 0bdcd364b461984673e1650bfd2b3e56be2605bf Mon Sep 17 00:00:00 2001 From: Konstantin Shuplenkov Date: Thu, 9 Sep 2021 19:47:43 +0300 Subject: [PATCH 09/15] fix: PR comments --- .../createGrpcErrorFromDriveResponse.js | 26 +++++++++++++++-- .../platform/platformHandlersFactory.js | 1 + ...tForStateTransitionResultHandlerFactory.js | 15 ++++------ ...tForStateTransitionResultHandlerFactory.js | 28 +++++++++++++++---- 4 files changed, 51 insertions(+), 19 deletions(-) diff --git a/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js b/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js index 3e9428b02..abd47253c 100644 --- a/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js +++ b/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js @@ -14,8 +14,8 @@ const { }, } = require('@dashevo/grpc-common'); const GrpcErrorCodes = require('@dashevo/grpc-common/lib/server/error/GrpcErrorCodes'); -const createConsensusError = require('@dashevo/dpp/lib/errors/consensus/createConsensusError'); const AlreadyExistsGrpcError = require('@dashevo/grpc-common/lib/server/error/AlreadyExistsGrpcError'); +const createConsensusError = require('@dashevo/dpp/lib/errors/consensus/createConsensusError'); /** * @typedef createGrpcErrorFromDriveResponse @@ -66,11 +66,31 @@ function createGrpcErrorFromDriveResponse(code, info) { } if (code >= 17 && code < 1000) { - return new GrpcError(code, decodedInfo.message, decodedInfo.metadata); + return new GrpcError(GrpcErrorCodes.UNKNOWN, decodedInfo.message, decodedInfo.metadata); } if (code >= 1000 && code < 5000) { - return createConsensusError(code, decodedInfo || []); + 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 ResourceExhaustedGrpcError(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}`)); diff --git a/lib/grpcServer/handlers/platform/platformHandlersFactory.js b/lib/grpcServer/handlers/platform/platformHandlersFactory.js index 4945ed271..f06be4deb 100644 --- a/lib/grpcServer/handlers/platform/platformHandlersFactory.js +++ b/lib/grpcServer/handlers/platform/platformHandlersFactory.js @@ -214,6 +214,7 @@ function platformHandlersFactory( waitForTransactionToBeProvable, blockchainListener, dpp, + createGrpcErrorFromDriveResponse, ); const wrappedWaitForStateTransitionResult = jsonToProtobufHandlerWrapper( diff --git a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js index 3e9faa603..7c59b0947 100644 --- a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -17,8 +17,6 @@ const { }, } = require('@dashevo/dapi-grpc'); -const cbor = require('cbor'); - const TransactionWaitPeriodExceededError = require('../../../errors/TransactionWaitPeriodExceededError'); const TransactionErrorResult = require('../../../externalApis/tenderdash/waitForTransactionToBeProvable/transactionResult/TransactionErrorResult'); @@ -28,6 +26,7 @@ const TransactionErrorResult = require('../../../externalApis/tenderdash/waitFor * @param {waitForTransactionToBeProvable} waitForTransactionToBeProvable * @param {BlockchainListener} blockchainListener * @param {DashPlatformProtocol} dpp + * @param {createGrpcErrorFromDriveResponse} createGrpcErrorFromDriveResponse * @param {number} stateTransitionWaitTimeout * @return {waitForStateTransitionResultHandler} */ @@ -36,6 +35,7 @@ function waitForStateTransitionResultHandlerFactory( waitForTransactionToBeProvable, blockchainListener, dpp, + createGrpcErrorFromDriveResponse, stateTransitionWaitTimeout = 80000, ) { /** @@ -43,18 +43,13 @@ function waitForStateTransitionResultHandlerFactory( * @return {StateTransitionBroadcastError} */ function createStateTransitionDeliverError(txDeliverResult) { - const { error: abciError } = JSON.parse(txDeliverResult.log); - - let errorData; - if (abciError.data) { - errorData = cbor.encode(abciError.data); - } + const grpcError = createGrpcErrorFromDriveResponse(txDeliverResult.code, txDeliverResult.info); const error = new StateTransitionBroadcastError(); error.setCode(txDeliverResult.code); - error.setMessage(abciError.message); - error.setData(errorData); + error.setMessage(grpcError.getMessage()); + error.setData(grpcError.getRawMetadata()); return error; } diff --git a/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js index cdf5d0942..dd951f172 100644 --- a/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js +++ b/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -31,6 +31,7 @@ const waitForTransactionResult = require('../../../../../lib/externalApis/tender const waitForStateTransitionResultHandlerFactory = require('../../../../../lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory'); const waitForHeightFactory = require('../../../../../lib/externalApis/tenderdash/waitForHeightFactory'); +const NotFoundGrpcError = require('@dashevo/grpc-common/lib/server/error/NotFoundGrpcError'); describe('waitForStateTransitionResultHandlerFactory', () => { let call; @@ -48,11 +49,20 @@ describe('waitForStateTransitionResultHandlerFactory', () => { let waitForTransactionToBeProvable; let transactionNotFoundError; let storeTreeProofs; + let createGrpcErrorFromDriveResponseMock; + let errorInfo; beforeEach(function beforeEach() { const hashString = '56458F2D8A8617EA322931B72C103CDD93820004E534295183A6EF215B93C76E'; hash = Buffer.from(hashString, 'hex'); + errorInfo = { + message: 'Identity not found', + metadata: { + error: 'some data', + }, + }; + wsMessagesFixture = { success: { query: "tm.event = 'Tx'", @@ -87,8 +97,8 @@ describe('waitForStateTransitionResultHandlerFactory', () => { height: '135', tx: 'pWR0eXBlAmlhc3NldExvY2ujZXByb29momR0eXBlAGtpbnN0YW50TG9ja1ilAR272lhhsS11I/IKpeDUL1LePc0tXC/pGbpntZ8FDSBuAAAAAMfKlZZZ3oAHaxO0bEIYXCSEpwTuR/baTwASqjgFgDAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa291dHB1dEluZGV4AGt0cmFuc2FjdGlvbljfAwAAAAFl5SQeBBDkK7Us9JcOU+Gp1oi4NIl/01A+5GAKeHi2JwEAAABrSDBFAiEAq9XMPgtU9J0imH6YJ/RtbxwJsavuhIpECU5Lw9h0xpoCIEgkU1njDQCe06YqRyeVYc6wK8G7Y/M5X+XicfJKo5P6ASEDK3jwtdIToEQAgTPMXxpjon4geQaNbbRNT/Xz50UgdHH/////AgEAAAAAAAAAFmoU8HHK+aRqNJOWXjNlOO3iWwvV45CDkAAAAAAAABl2qRTFVGzrfaB6ZhmvE8h2unBNgcJIMIisAAAAAGlzaWduYXR1cmVYQR/OHDEQUcSxczLBvMP9Z0HmRaDoCS6tTyFLbWhn7bAfJTlPF9hIbh13260WSCiDceJjWaYB0JuOGsqu2ZB5F0dDanB1YmxpY0tleXOBo2JpZABkZGF0YVghA85GJWE321+kW0HIwl3M6wO9BIHDxY80HlQgc1wRalT5ZHR5cGUAb3Byb3RvY29sVmVyc2lvbgA=', result: { - code: 2, - log: '{"error":{"message":"Invalid state transition","data":{"errors":[{"name":"IdentityPublicKeyAlreadyExistsError","message":"Identity public key already exists","publicKeyHash":{"type":"Buffer","data":[216,100,221,206,173,76,253,13,66,247,118,172,153,161,161,189,154,91,240,205]}}]}}}', + code: 1043, + info: cbor.encode(errorInfo).toString('base64'), }, }, }, @@ -160,11 +170,16 @@ describe('waitForStateTransitionResultHandlerFactory', () => { waitForHeight, ); + createGrpcErrorFromDriveResponseMock = this.sinon.stub().returns( + new NotFoundGrpcError(errorInfo.message, errorInfo.metadata), + ); + waitForStateTransitionResultHandler = waitForStateTransitionResultHandlerFactory( fetchProofForStateTransition, waitForTransactionToBeProvable, blockchainListener, dppMock, + createGrpcErrorFromDriveResponseMock, 1000, ); }); @@ -242,13 +257,14 @@ describe('waitForStateTransitionResultHandlerFactory', () => { const errorCode = error.getCode(); const errorMessage = error.getMessage(); - const { error: abciError } = JSON.parse( - wsMessagesFixture.error.data.value.TxResult.result.log, + expect(createGrpcErrorFromDriveResponseMock).to.be.calledOnceWithExactly( + wsMessagesFixture.error.data.value.TxResult.result.code, + wsMessagesFixture.error.data.value.TxResult.result.info, ); expect(errorCode).to.equal(wsMessagesFixture.error.data.value.TxResult.result.code); - expect(errorData).to.deep.equal(cbor.encode(abciError.data)); - expect(errorMessage).to.equal(abciError.message); + expect(errorData).to.deep.equal(errorInfo.metadata); + expect(errorMessage).to.equal(errorInfo.message); done(); }); From b692da4a52a76893f86968a66e221701606bd334 Mon Sep 17 00:00:00 2001 From: Konstantin Shuplenkov Date: Fri, 10 Sep 2021 16:37:25 +0300 Subject: [PATCH 10/15] fix: unit tests --- .../createGrpcErrorFromDriveResponse.js | 47 ++++++++++++++----- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.js b/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.js index bfd5bc21a..1a37b78af 100644 --- a/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.js +++ b/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.js @@ -1,8 +1,10 @@ const GrpcErrorCodes = require('@dashevo/grpc-common/lib/server/error/GrpcErrorCodes'); const GrpcError = require('@dashevo/grpc-common/lib/server/error/GrpcError'); const cbor = require('cbor'); -const AbstractConsensusError = require('@dashevo/dpp/lib/errors/consensus/AbstractConsensusError'); const InternalGrpcError = require('@dashevo/grpc-common/lib/server/error/InternalGrpcError'); +const InvalidArgumentGrpcError = require('@dashevo/grpc-common/lib/server/error/InvalidArgumentGrpcError'); +const ResourceExhaustedGrpcError = require('@dashevo/grpc-common/lib/server/error/ResourceExhaustedGrpcError'); +const generateRandomIdentifier = require('@dashevo/dpp/lib/test/utils/generateRandomIdentifier'); const createGrpcErrorFromDriveResponse = require( '../../../../lib/grpcServer/handlers/createGrpcErrorFromDriveResponse', ); @@ -27,7 +29,7 @@ describe('createGrpcErrorFromDriveResponse', () => { Object.entries(GrpcErrorCodes) .forEach(([codeClass, code]) => { it(`should throw ${codeClass} if response code is ${code}`, function it() { - if (code === GrpcErrorCodes.INTERNAL) { + if (code === GrpcErrorCodes.INTERNAL || code === GrpcErrorCodes.VERSION_MISMATCH) { // we have this test separate this.skip(); } @@ -52,25 +54,44 @@ describe('createGrpcErrorFromDriveResponse', () => { expect(error).to.be.an.instanceOf(GrpcError); expect(error.getMessage()).to.equal(message); - expect(error.getCode()).to.equal(17); + expect(error.getCode()).to.equal(GrpcErrorCodes.UNKNOWN); expect(error.getRawMetadata()).to.deep.equal(info.metadata); }); - it('should throw GrpcError if error code = 99', () => { - const error = createGrpcErrorFromDriveResponse(99, encodedInfo); + it('should throw ConsensusError if error code = 1000', () => { + const error = createGrpcErrorFromDriveResponse(1000); + + expect(error).to.be.an.instanceOf(InvalidArgumentGrpcError); + expect(error.getRawMetadata()).to.deep.equal({ code: 1000 }); + }); + + it('should throw ConsensusError if error code = 2000', () => { + const id = generateRandomIdentifier(); + + const error = createGrpcErrorFromDriveResponse( + 2000, + cbor.encode([id]).toString('base64'), + ); expect(error).to.be.an.instanceOf(GrpcError); - expect(error.getMessage()).to.equal(message); - expect(error.getCode()).to.equal(99); - expect(error.getRawMetadata()).to.deep.equal(info.metadata); + expect(error.getCode()).to.equal(GrpcErrorCodes.UNAUTHENTICATED); + expect(error.getRawMetadata()).to.deep.equal({ code: 2000 }); }); - it('should throw ConsensusError if error code = 1000', () => { - const error = createGrpcErrorFromDriveResponse(1000, cbor.encode([42, 'a']).toString('base64')); + it('should throw ConsensusError if error code = 3000', () => { + const error = createGrpcErrorFromDriveResponse(3000, cbor.encode([20, 10]).toString('base64')); + + expect(error).to.be.an.instanceOf(ResourceExhaustedGrpcError); + expect(error.getRawMetadata()).to.deep.equal({ code: 3000 }); + }); + + it('should throw ConsensusError if error code = 4000', () => { + const dataContractId = generateRandomIdentifier(); + + const error = createGrpcErrorFromDriveResponse(4000, cbor.encode([dataContractId]).toString('base64')); - expect(error).to.be.an.instanceOf(AbstractConsensusError); - expect(error.getConstructorArguments()).to.deep.equal([42, 'a']); - expect(error.getCode()).to.equal(1000); + expect(error).to.be.an.instanceOf(InvalidArgumentGrpcError); + expect(error.getRawMetadata()).to.deep.equal({ code: 4000 }); }); it('should throw Unknown error code >= 5000', () => { From 3368ba4285c47c41381f2cab9f43dab60dd5a602 Mon Sep 17 00:00:00 2001 From: Konstantin Shuplenkov Date: Mon, 13 Sep 2021 17:46:25 +0300 Subject: [PATCH 11/15] fix: waitForStateTransitionResultHandler data should be encoded by cbor --- .github/workflows/.env | 8 ++++---- .../waitForStateTransitionResultHandlerFactory.js | 3 ++- .../waitForStateTransitionResultHandlerFactory.js | 4 ++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/.env b/.github/workflows/.env index 5e4c4850a..1a6d475cd 100644 --- a/.github/workflows/.env +++ b/.github/workflows/.env @@ -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 diff --git a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js index 7c59b0947..363c99b3c 100644 --- a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -17,6 +17,7 @@ const { }, } = require('@dashevo/dapi-grpc'); +const cbor = require('cbor'); const TransactionWaitPeriodExceededError = require('../../../errors/TransactionWaitPeriodExceededError'); const TransactionErrorResult = require('../../../externalApis/tenderdash/waitForTransactionToBeProvable/transactionResult/TransactionErrorResult'); @@ -49,7 +50,7 @@ function waitForStateTransitionResultHandlerFactory( error.setCode(txDeliverResult.code); error.setMessage(grpcError.getMessage()); - error.setData(grpcError.getRawMetadata()); + error.setData(cbor.encode(grpcError.getRawMetadata())); return error; } diff --git a/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js index dd951f172..e019bc27f 100644 --- a/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js +++ b/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -22,6 +22,7 @@ const getIdentityCreateTransitionFixture = require('@dashevo/dpp/lib/test/fixtur const { EventEmitter } = require('events'); const cbor = require('cbor'); +const NotFoundGrpcError = require('@dashevo/grpc-common/lib/server/error/NotFoundGrpcError'); const BlockchainListener = require('../../../../../lib/externalApis/tenderdash/BlockchainListener'); const GrpcCallMock = require('../../../../../lib/test/mock/GrpcCallMock'); @@ -31,7 +32,6 @@ const waitForTransactionResult = require('../../../../../lib/externalApis/tender const waitForStateTransitionResultHandlerFactory = require('../../../../../lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory'); const waitForHeightFactory = require('../../../../../lib/externalApis/tenderdash/waitForHeightFactory'); -const NotFoundGrpcError = require('@dashevo/grpc-common/lib/server/error/NotFoundGrpcError'); describe('waitForStateTransitionResultHandlerFactory', () => { let call; @@ -263,7 +263,7 @@ describe('waitForStateTransitionResultHandlerFactory', () => { ); expect(errorCode).to.equal(wsMessagesFixture.error.data.value.TxResult.result.code); - expect(errorData).to.deep.equal(errorInfo.metadata); + expect(errorData).to.deep.equal(cbor.encode(errorInfo.metadata)); expect(errorMessage).to.equal(errorInfo.message); done(); From f60801de1696a842650d3bfc57d3a9f6b22cf57c Mon Sep 17 00:00:00 2001 From: Konstantin Shuplenkov Date: Tue, 14 Sep 2021 18:41:58 +0300 Subject: [PATCH 12/15] chore: update dpp to 0.21.0-dev.4 --- package-lock.json | 27 +++++++++++++++++---------- package.json | 2 +- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index ba28d17a0..f9fe9e4ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -136,7 +136,8 @@ "@cto.af/textdecoder": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/@cto.af/textdecoder/-/textdecoder-0.0.0.tgz", - "integrity": "sha512-sJpx3F5xcVV/9jNYJQtvimo4Vfld/nD3ph+ZWtQzZ03Zo8rJC7QKQTRcIGS13Rcz80DwFNthCWMrd58vpY4ZAQ==" + "integrity": "sha512-sJpx3F5xcVV/9jNYJQtvimo4Vfld/nD3ph+ZWtQzZ03Zo8rJC7QKQTRcIGS13Rcz80DwFNthCWMrd58vpY4ZAQ==", + "dev": true }, "@dashevo/dapi-client": { "version": "0.21.0-dev.6", @@ -224,18 +225,19 @@ } }, "@dashevo/dpp": { - "version": "github:dashevo/js-dpp#107bd86fb4eead2c3f2b4fd5aefba98f0388b83b", - "from": "github:dashevo/js-dpp#error-necessary-data", + "version": "0.21.0-dev.4", + "resolved": "https://registry.npmjs.org/@dashevo/dpp/-/dpp-0.21.0-dev.4.tgz", + "integrity": "sha512-H1QP1ZdZnptYe4rztIdkohts8Y11J2izt6LDkquZR9+kfrpv4gCiWqs+UeslCY06HiaeXVjLUHwk+x7JZOvVNQ==", "requires": { "@apidevtools/json-schema-ref-parser": "^8.0.0", "@dashevo/dashcore-lib": "~0.19.25", "@dashevo/feature-flags-contract": "0.1.0", "@dashevo/re2-wasm": "~1.0.4", "ajv": "^8.6.0", - "ajv-formats": "^2.1.0", + "ajv-formats": "^2.1.1", "bignumber.js": "^9.0.1", "bs58": "^4.0.1", - "cbor": "^7.0.5", + "cbor": "^8.0.0", "json-schema-traverse": "^1.0.0", "lodash.clonedeep": "^4.5.0", "lodash.clonedeepwith": "^4.5.0", @@ -245,13 +247,17 @@ }, "dependencies": { "cbor": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cbor/-/cbor-7.0.6.tgz", - "integrity": "sha512-rgt2RFogHGDLFU5r0kSfyeBc+de55DwYHP73KxKsQxsR5b0CYuQPH6AnJaXByiohpLdjQqj/K0SFcOV+dXdhSA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-8.0.0.tgz", + "integrity": "sha512-nMmaLWbj7+bC6MsApKRIig8h+yjgNLhPLXaCelq5+C7mpWsHgIcseZSdvgexSY5uE1Q3m2uPvIDZwSdxdo7qig==", "requires": { - "@cto.af/textdecoder": "^0.0.0", - "nofilter": "^2.0.3" + "nofilter": "^3.0.2" } + }, + "nofilter": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.0.3.tgz", + "integrity": "sha512-TN/MCrQmXQk5DyUJ8TGUq1Il8rv4fTsjddLmMopV006QP8DMkglmGgYfQKD5620vXLRXfr8iGI6ZZ4/ZWld2cQ==" } } }, @@ -3263,6 +3269,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-2.0.3.tgz", "integrity": "sha512-FbuXC+lK+GU2+63D1kC1ETiZo+Z7SIi7B+mxKTCH1byrh6WFvfBCN/wpherFz0a0bjGd7EKTst/cz0yLeNngug==", + "dev": true, "requires": { "@cto.af/textdecoder": "^0.0.0" } diff --git a/package.json b/package.json index 160d4a4f8..e49d1fc94 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "@dashevo/dapi-grpc": "~0.21.0-dev.8", "@dashevo/dashcore-lib": "~0.19.25", "@dashevo/dashd-rpc": "^2.0.2", - "@dashevo/dpp": "github:dashevo/js-dpp#error-necessary-data", + "@dashevo/dpp": "~0.21.0-dev.4", "@dashevo/grpc-common": "~0.4.0", "@grpc/grpc-js": "^1.3.6", "ajv": "^8.6.0", From 49a8a1271d5ddf9d290407c9035489cd62aed6f7 Mon Sep 17 00:00:00 2001 From: Konstantin Shuplenkov Date: Tue, 14 Sep 2021 18:42:32 +0300 Subject: [PATCH 13/15] chore: update dpp to 0.21.0-dev.4 --- package-lock.json | 20 ++++++++++---------- package.json | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index f9fe9e4ed..89c55396a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -140,9 +140,9 @@ "dev": true }, "@dashevo/dapi-client": { - "version": "0.21.0-dev.6", - "resolved": "https://registry.npmjs.org/@dashevo/dapi-client/-/dapi-client-0.21.0-dev.6.tgz", - "integrity": "sha512-9/n2DGpFpePrd6zarLMNOUyE9pH6SktCqZ2cUUQJFa/2ReU1PaEGIZXojtY7yFk1Yz1n8PeLIgplUM/v/jEjzQ==", + "version": "0.21.0-dev.7", + "resolved": "https://registry.npmjs.org/@dashevo/dapi-client/-/dapi-client-0.21.0-dev.7.tgz", + "integrity": "sha512-fNfby71MJasseVRLmNURZvBSFqAhCpkJaSoJhf2AK2zmJ1YDFhJkB0IdnMMyjgfnxrzmVYL8X0wf+fLpiVJ6dw==", "dev": true, "requires": { "@dashevo/dapi-grpc": "~0.21.0-dev.8", @@ -637,12 +637,12 @@ "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" }, "axios": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", - "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", "dev": true, "requires": { - "follow-redirects": "^1.10.0" + "follow-redirects": "^1.14.0" } }, "balanced-match": { @@ -1858,9 +1858,9 @@ "dev": true }, "follow-redirects": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.3.tgz", - "integrity": "sha512-3MkHxknWMUtb23apkgz/83fDoe+y+qr0TdgacGIA7bew+QLBo3vdgEN2xEsuXNivpFy4CyDhBBZnNZOtalmenw==", + "version": "1.14.4", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz", + "integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==", "dev": true }, "foreground-child": { diff --git a/package.json b/package.json index e49d1fc94..ad73d326a 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "zeromq": "5.2.0" }, "devDependencies": { - "@dashevo/dapi-client": "~0.21.0-dev.6", + "@dashevo/dapi-client": "~0.21.0-dev.7", "@dashevo/dp-services-ctl": "github:dashevo/js-dp-services-ctl#v0.19-dev", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", From b0fa1f8e164aae30818d530022bb327215fc9571 Mon Sep 17 00:00:00 2001 From: Konstantin Shuplenkov Date: Wed, 15 Sep 2021 11:19:11 +0300 Subject: [PATCH 14/15] chore: update dpp to 0.21.0-dev.4 --- .github/workflows/.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/.env b/.github/workflows/.env index 1a6d475cd..45240c404 100644 --- a/.github/workflows/.env +++ b/.github/workflows/.env @@ -1,4 +1,4 @@ DRIVE_BRANCH=feat/grpc-error-codes DASHMATE_BRANCH=error-codes TEST_SUITE_BRANCH=error-codes -SDK_BRANCH=error-codes +#SDK_BRANCH=error-codes From b9eede12b54bc093f8bbf4802d09b5bc0ad8cd36 Mon Sep 17 00:00:00 2001 From: Ivan Shumkov Date: Wed, 15 Sep 2021 13:39:30 +0300 Subject: [PATCH 15/15] fix: fee validation throws repeatable gRPC error --- .../handlers/createGrpcErrorFromDriveResponse.js | 2 +- .../handlers/createGrpcErrorFromDriveResponse.js | 15 +++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js b/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js index abd47253c..ad1d7a0f3 100644 --- a/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js +++ b/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js @@ -84,7 +84,7 @@ function createGrpcErrorFromDriveResponse(code, info) { // Fee if (code >= 3000 && code < 4000) { - return new ResourceExhaustedGrpcError(consensusError.message, { code }); + return new FailedPreconditionGrpcError(consensusError.message, { code }); } // State diff --git a/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.js b/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.js index 1a37b78af..fd6981319 100644 --- a/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.js +++ b/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.js @@ -3,7 +3,7 @@ const GrpcError = require('@dashevo/grpc-common/lib/server/error/GrpcError'); const cbor = require('cbor'); const InternalGrpcError = require('@dashevo/grpc-common/lib/server/error/InternalGrpcError'); const InvalidArgumentGrpcError = require('@dashevo/grpc-common/lib/server/error/InvalidArgumentGrpcError'); -const ResourceExhaustedGrpcError = require('@dashevo/grpc-common/lib/server/error/ResourceExhaustedGrpcError'); +const FailedPreconditionGrpcError = require('@dashevo/grpc-common/lib/server/error/FailedPreconditionGrpcError'); const generateRandomIdentifier = require('@dashevo/dpp/lib/test/utils/generateRandomIdentifier'); const createGrpcErrorFromDriveResponse = require( '../../../../lib/grpcServer/handlers/createGrpcErrorFromDriveResponse', @@ -27,13 +27,12 @@ describe('createGrpcErrorFromDriveResponse', () => { }); Object.entries(GrpcErrorCodes) + // We have special tests below for these error codes + .filter(([, code]) => ( + ![GrpcErrorCodes.VERSION_MISMATCH, GrpcErrorCodes.INTERNAL].includes(code) + )) .forEach(([codeClass, code]) => { - it(`should throw ${codeClass} if response code is ${code}`, function it() { - if (code === GrpcErrorCodes.INTERNAL || code === GrpcErrorCodes.VERSION_MISMATCH) { - // we have this test separate - this.skip(); - } - + it(`should throw ${codeClass} if response code is ${code}`, () => { const error = createGrpcErrorFromDriveResponse(code, encodedInfo); let messageToCheck = message; @@ -81,7 +80,7 @@ describe('createGrpcErrorFromDriveResponse', () => { it('should throw ConsensusError if error code = 3000', () => { const error = createGrpcErrorFromDriveResponse(3000, cbor.encode([20, 10]).toString('base64')); - expect(error).to.be.an.instanceOf(ResourceExhaustedGrpcError); + expect(error).to.be.an.instanceOf(FailedPreconditionGrpcError); expect(error.getRawMetadata()).to.deep.equal({ code: 3000 }); });