Skip to content
This repository has been archived by the owner on Dec 16, 2021. It is now read-only.

feat!: use new error codes and data for ABCI responses #562

Merged
merged 14 commits into from
Sep 15, 2021
68 changes: 0 additions & 68 deletions lib/abci/errors/AbciError.js

This file was deleted.

13 changes: 0 additions & 13 deletions lib/abci/errors/InsufficientFundsError.js

This file was deleted.

29 changes: 0 additions & 29 deletions lib/abci/errors/InternalAbciError.js

This file was deleted.

18 changes: 0 additions & 18 deletions lib/abci/errors/InvalidArgumentAbciError.js

This file was deleted.

18 changes: 0 additions & 18 deletions lib/abci/errors/NotFoundAbciError.js

This file was deleted.

12 changes: 0 additions & 12 deletions lib/abci/errors/UnavailableAbciError.js

This file was deleted.

30 changes: 0 additions & 30 deletions lib/abci/errors/VerboseInternalAbciError.js

This file was deleted.

55 changes: 21 additions & 34 deletions lib/abci/errors/wrapInErrorHandlerFactory.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
const {
tendermint: {
abci: {
Event,
EventAttribute,
},
},
} = require('@dashevo/abci/types');

const AbciError = require('./AbciError');
const InternalAbciError = require('./InternalAbciError');
const VerboseInternalAbciError = require('./VerboseInternalAbciError');
const cbor = require('cbor');
const GrpcError = require('@dashevo/grpc-common/lib/server/error/GrpcError');
const InternalGrpcError = require('@dashevo/grpc-common/lib/server/error/InternalGrpcError');
const VerboseInternalGrpcError = require('@dashevo/grpc-common/lib/server/error/VerboseInternalGrpcError');
const DPPValidationError = require('../handlers/errors/DPPValidationError');

/**
* @param {BaseLogger} logger
Expand Down Expand Up @@ -45,13 +38,20 @@ function wrapInErrorHandlerFactory(logger, isProductionEnvironment) {
} catch (e) {
let error = e;

if (e instanceof DPPValidationError) {
return {
code: error.getCode(),
info: cbor.encode(error.getInfo()).toString('base64'),
};
}

// Wrap all non ABCI errors to an internal ABCI error
if (!(e instanceof AbciError)) {
error = new InternalAbciError(e);
if (!(e instanceof GrpcError)) {
error = new InternalGrpcError(e);
}

// Log only internal ABCI errors
if (error instanceof InternalAbciError) {
if (error instanceof InternalGrpcError) {
// in consensus ABCI handlers (blockBegin, deliverTx, blockEnd, commit)
// we should propagate the error upwards
// to halt the Drive
Expand All @@ -69,31 +69,18 @@ function wrapInErrorHandlerFactory(logger, isProductionEnvironment) {
);

if (!isProductionEnvironment) {
error = new VerboseInternalAbciError(error);
error = new VerboseInternalGrpcError(error);
}
}

const events = [];

const attributes = Object.entries(error.getTags())
.map(([key, value]) => new EventAttribute({ key, value, index: true }));

if (attributes.length > 0) {
events.push(new Event({
type: 'error',
attributes,
}));
}
const serializedError = cbor.encode({
message: error.getMessage(),
metadata: error.getRawMetadata(),
});

return {
code: error.getCode(),
log: JSON.stringify({
error: {
message: error.getMessage(),
data: error.getData(),
},
}),
events,
info: serializedError.toString('base64'),
};
}
}
Expand Down
6 changes: 3 additions & 3 deletions lib/abci/handlers/deliverTxHandlerFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const AbstractDocumentTransition = require(
'@dashevo/dpp/lib/document/stateTransition/DocumentsBatchTransition/documentTransition/AbstractDocumentTransition',
);

const InvalidArgumentAbciError = require('../errors/InvalidArgumentAbciError');
const DPPValidationError = require('./errors/DPPValidationError');

const DOCUMENT_ACTION_DESCRIPTONS = {
[AbstractDocumentTransition.ACTIONS.CREATE]: 'created',
Expand Down Expand Up @@ -80,14 +80,14 @@ function deliverTxHandlerFactory(
const result = await transactionalDpp.stateTransition.validateState(stateTransition);

if (!result.isValid()) {
consensusLogger.info('State transition data is invalid');
consensusLogger.info('State transition is invalid against the state');
consensusLogger.debug({
consensusErrors: result.getErrors(),
});

blockExecutionContext.incrementInvalidTxCount();

throw new InvalidArgumentAbciError('Invalid state transition', { errors: result.getErrors() });
throw new DPPValidationError('State transition is invalid against the state', result.getErrors());
}

// Apply state transition to the state
Expand Down
32 changes: 32 additions & 0 deletions lib/abci/handlers/errors/DPPValidationError.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
class DPPValidationError extends Error {
/**
*
* @param {string} message
* @param {AbstractConsenusError[]} errors
*/
constructor(message, errors) {
super(message);

this.errors = errors;
}

/**
* Get error code
*
* @returns {number}
*/
getCode() {
return this.errors[0].getCode();
}

/**
* Get error info
*
* @returns {Array}
*/
getInfo() {
return this.errors[0].getConstructorArguments();
}
}

module.exports = DPPValidationError;
6 changes: 3 additions & 3 deletions lib/abci/handlers/query/dataContractQueryHandlerFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const {
},
} = require('@dashevo/dapi-grpc');

const NotFoundAbciError = require('../../errors/NotFoundAbciError');
const NotFoundGrpcError = require('@dashevo/grpc-common/lib/server/error/NotFoundGrpcError');

/**
*
Expand Down Expand Up @@ -44,7 +44,7 @@ function dataContractQueryHandlerFactory(
async function dataContractQueryHandler(params, { id }, request) {
// There is no signed state (current committed block height less then 2)
if (blockExecutionContext.isEmpty() || previousBlockExecutionContext.isEmpty()) {
throw new NotFoundAbciError('Data Contract not found');
throw new NotFoundGrpcError('Data Contract not found');
}

const response = createQueryResponse(GetDataContractResponse, request.prove);
Expand All @@ -53,7 +53,7 @@ function dataContractQueryHandlerFactory(

let dataContractBuffer;
if (!dataContract && !request.prove) {
throw new NotFoundAbciError('Data Contract not found');
throw new NotFoundGrpcError('Data Contract not found');
} else if (dataContract) {
dataContractBuffer = dataContract.toBuffer();
}
Expand Down
Loading