diff --git a/lib/dataContract/DataContractFactory.js b/lib/dataContract/DataContractFactory.js index 67fb0203..df6f2be6 100644 --- a/lib/dataContract/DataContractFactory.js +++ b/lib/dataContract/DataContractFactory.js @@ -6,7 +6,7 @@ const generateDataContractId = require('./generateDataContractId'); const DataContractCreateTransition = require('./stateTransition/DataContractCreateTransition/DataContractCreateTransition'); const generateEntropy = require('../util/generateEntropy'); -const ConsensusError = require('../errors/consensus/ConsensusError'); +const AbstractConsensusError = require('../errors/consensus/AbstractConsensusError'); class DataContractFactory { /** @@ -88,7 +88,7 @@ class DataContractFactory { rawDataContract.protocolVersion = protocolVersion; } catch (error) { - if (error instanceof ConsensusError) { + if (error instanceof AbstractConsensusError) { throw new InvalidDataContractError([error]); } diff --git a/lib/dataContract/errors/InvalidDataContractError.js b/lib/dataContract/errors/InvalidDataContractError.js index 559d604d..28f78e44 100644 --- a/lib/dataContract/errors/InvalidDataContractError.js +++ b/lib/dataContract/errors/InvalidDataContractError.js @@ -2,7 +2,7 @@ const DPPError = require('../../errors/DPPError'); class InvalidDataContractError extends DPPError { /** - * @param {ConsensusError[]} errors + * @param {AbstractConsensusError[]} errors * @param {RawDataContract} rawDataContract */ constructor(errors, rawDataContract) { @@ -20,7 +20,7 @@ class InvalidDataContractError extends DPPError { /** * Get validation errors * - * @return {ConsensusError[]} + * @return {AbstractConsensusError[]} */ getErrors() { return this.errors; diff --git a/lib/dataContract/stateTransition/DataContractCreateTransition/validation/state/validateDataContractCreateTransitionStateFactory.js b/lib/dataContract/stateTransition/DataContractCreateTransition/validation/state/validateDataContractCreateTransitionStateFactory.js index 6f39bd8f..6c59cf2a 100644 --- a/lib/dataContract/stateTransition/DataContractCreateTransition/validation/state/validateDataContractCreateTransitionStateFactory.js +++ b/lib/dataContract/stateTransition/DataContractCreateTransition/validation/state/validateDataContractCreateTransitionStateFactory.js @@ -24,7 +24,7 @@ function validateDataContractCreateTransitionStateFactory(stateRepository) { if (existingDataContract) { result.addError( - new DataContractAlreadyPresentError(dataContract), + new DataContractAlreadyPresentError(dataContractId.toBuffer()), ); } diff --git a/lib/dataContract/validation/validateDataContractFactory.js b/lib/dataContract/validation/validateDataContractFactory.js index 602774dd..42c5c33f 100644 --- a/lib/dataContract/validation/validateDataContractFactory.js +++ b/lib/dataContract/validation/validateDataContractFactory.js @@ -119,7 +119,6 @@ module.exports = function validateDataContractFactory( isUniqueIndexLimitReached = true; result.addError(new UniqueIndicesLimitReachedError( - rawDataContract, documentType, )); } @@ -133,7 +132,6 @@ module.exports = function validateDataContractFactory( if (isSingleIndex) { result.addError(new SystemPropertyIndexAlreadyPresentError( - rawDataContract, documentType, indexDefinition, propertyName, @@ -159,7 +157,6 @@ module.exports = function validateDataContractFactory( .map(([propertyName]) => { result.addError( new UndefinedIndexPropertyError( - rawDataContract, documentType, indexDefinition, propertyName, @@ -205,7 +202,6 @@ module.exports = function validateDataContractFactory( if (invalidPropertyType) { result.addError(new InvalidIndexPropertyTypeError( - rawDataContract, documentType, indexDefinition, propertyName, @@ -219,7 +215,6 @@ module.exports = function validateDataContractFactory( if (maxLength === undefined) { result.addError( new InvalidIndexedPropertyConstraintError( - rawDataContract, documentType, indexDefinition, propertyName, @@ -232,7 +227,6 @@ module.exports = function validateDataContractFactory( if (maxLength !== undefined && maxLength > MAX_INDEXED_STRING_PROPERTY_LENGTH) { result.addError( new InvalidIndexedPropertyConstraintError( - rawDataContract, documentType, indexDefinition, propertyName, @@ -254,7 +248,7 @@ module.exports = function validateDataContractFactory( if (!allAreRequired && !allAreNotRequired) { result.addError( - new InvalidCompoundIndexError(rawDataContract, documentType, indexDefinition), + new InvalidCompoundIndexError(documentType, indexDefinition), ); } } @@ -265,7 +259,6 @@ module.exports = function validateDataContractFactory( if (indicesFingerprints.includes(indicesFingerprint)) { result.addError( new DuplicateIndexError( - rawDataContract, documentType, indexDefinition, ), diff --git a/lib/dataContract/validation/validateDataContractMaxDepthFactory.js b/lib/dataContract/validation/validateDataContractMaxDepthFactory.js index 7e0e0d6a..ceea4baf 100644 --- a/lib/dataContract/validation/validateDataContractMaxDepthFactory.js +++ b/lib/dataContract/validation/validateDataContractMaxDepthFactory.js @@ -1,7 +1,7 @@ const lodashCloneDeep = require('lodash.clonedeep'); const ValidationResult = require('../../validation/ValidationResult'); -const JsonSchemaError = require('../../errors/consensus/basic/JsonSchemaError'); const DataContractMaxDepthExceedError = require('../../errors/consensus/basic/dataContract/DataContractMaxDepthExceedError'); +const InvalidJsonSchemaRefError = require('../../errors/consensus/basic/dataContract/InvalidJsonSchemaRefError'); /** * Check that JSON Schema max depth is less than max value @@ -64,7 +64,11 @@ function validateDataContractMaxDepthFactory(refParser) { }, }); } catch (error) { - result.addError(new JsonSchemaError(error)); + const consensusError = new InvalidJsonSchemaRefError(error.message); + + consensusError.setRefError(error); + + result.addError(consensusError); return result; } @@ -74,7 +78,11 @@ function validateDataContractMaxDepthFactory(refParser) { } catch (error) { if (error instanceof DataContractMaxDepthExceedError) { result.addError(error); + + return result; } + + throw error; } return result; diff --git a/lib/dataContract/validation/validateDataContractPatternsFactory.js b/lib/dataContract/validation/validateDataContractPatternsFactory.js index 078eaa4e..f6717348 100644 --- a/lib/dataContract/validation/validateDataContractPatternsFactory.js +++ b/lib/dataContract/validation/validateDataContractPatternsFactory.js @@ -1,6 +1,6 @@ const traverse = require('json-schema-traverse'); const ValidationResult = require('../../validation/ValidationResult'); -const IncompatibleRe2PatternError = require('../../document/errors/IncompatibleRe2PatternError'); +const IncompatibleRe2PatternError = require('../../errors/consensus/basic/dataContract/IncompatibleRe2PatternError'); /** * @@ -27,7 +27,11 @@ function validateDataContractPatternsFactory( // eslint-disable-next-line no-new new RE2(value, 'u'); } catch (e) { - result.addError(new IncompatibleRe2PatternError(value, path, e.message)); + const consensusError = new IncompatibleRe2PatternError(value, path, e.message); + + consensusError.setPatternError(e); + + result.addError(consensusError); } } }); diff --git a/lib/dataTrigger/DataTrigger.js b/lib/dataTrigger/DataTrigger.js index 6d377a1e..c0932e06 100644 --- a/lib/dataTrigger/DataTrigger.js +++ b/lib/dataTrigger/DataTrigger.js @@ -48,28 +48,32 @@ class DataTrigger { * @returns {Promise} */ async execute(documentTransition, context) { - let result = new DataTriggerExecutionResult(); + let result; try { result = await this.trigger(documentTransition, context, this.topLevelIdentity); } catch (e) { - result.addError( - new DataTriggerExecutionError( - this, - context.getDataContract(), - context.getOwnerId(), - e, - ), + result = new DataTriggerExecutionResult(); + + const consensusError = new DataTriggerExecutionError( + context.getDataContract().getId().toBuffer(), + documentTransition.getId().toBuffer(), + e.message, ); + + consensusError.setExecutionError(e); + + result.addError(consensusError); + + return result; } if (!(result instanceof DataTriggerExecutionResult)) { result = new DataTriggerExecutionResult(); result.addError( new DataTriggerInvalidResultError( - this, - context.getDataContract(), - context.getOwnerId(), + context.getDataContract().getId().toBuffer(), + documentTransition.getId().toBuffer(), ), ); } diff --git a/lib/dataTrigger/dashpayDataTriggers/createContactRequestDataTrigger.js b/lib/dataTrigger/dashpayDataTriggers/createContactRequestDataTrigger.js index 73c9943a..0298e89e 100644 --- a/lib/dataTrigger/dashpayDataTriggers/createContactRequestDataTrigger.js +++ b/lib/dataTrigger/dashpayDataTriggers/createContactRequestDataTrigger.js @@ -32,14 +32,16 @@ async function createContactRequestDataTrigger(documentTransition, context) { const heightWindowEnd = coreChainLockedHeight + BLOCKS_WINDOW_SIZE; if (coreHeightCreatedAt < heightWindowStart || coreHeightCreatedAt > heightWindowEnd) { - result.addError( - new DataTriggerConditionError( - documentTransition, - context.getDataContract(), - context.getOwnerId(), - 'Core height is out of block height window', - ), + const error = new DataTriggerConditionError( + context.getDataContract().getId().toBuffer(), + documentTransition.getId().toBuffer(), + `Core height ${coreHeightCreatedAt} is out of block height window from ${heightWindowStart} to ${heightWindowEnd}`, ); + + error.setOwnerId(context.getOwnerId()); + error.setDocumentTransition(documentTransition); + + result.addError(error); } return result; diff --git a/lib/dataTrigger/dpnsTriggers/createDomainDataTrigger.js b/lib/dataTrigger/dpnsTriggers/createDomainDataTrigger.js index ea200a27..3c64931b 100644 --- a/lib/dataTrigger/dpnsTriggers/createDomainDataTrigger.js +++ b/lib/dataTrigger/dpnsTriggers/createDomainDataTrigger.js @@ -32,62 +32,72 @@ async function createDomainDataTrigger(documentTransition, context, topLevelIden } if (fullDomainName.length > MAX_PRINTABLE_DOMAIN_NAME_LENGTH) { - result.addError( - new DataTriggerConditionError( - documentTransition, - context.getDataContract(), - context.getOwnerId(), - 'Full domain name length can not be more than 253 characters long', - ), + const error = new DataTriggerConditionError( + context.getDataContract().getId().toBuffer(), + documentTransition.getId().toBuffer(), + `Full domain name length can not be more than ${MAX_PRINTABLE_DOMAIN_NAME_LENGTH} characters long but got ${fullDomainName.length}`, ); + + error.setOwnerId(context.getOwnerId()); + error.setDocumentTransition(documentTransition); + + result.addError(error); } if (normalizedLabel !== label.toLowerCase()) { - result.addError( - new DataTriggerConditionError( - documentTransition, - context.getDataContract(), - context.getOwnerId(), - 'Normalized label doesn\'t match label', - ), + const error = new DataTriggerConditionError( + context.getDataContract().getId().toBuffer(), + documentTransition.getId().toBuffer(), + 'Normalized label doesn\'t match label', ); + + error.setOwnerId(context.getOwnerId()); + error.setDocumentTransition(documentTransition); + + result.addError(error); } if (records.dashUniqueIdentityId && !context.getOwnerId().equals(records.dashUniqueIdentityId) ) { - result.addError( - new DataTriggerConditionError( - documentTransition, - context.getDataContract(), - context.getOwnerId(), - 'ownerId doesn\'t match dashUniqueIdentityId', - ), + const error = new DataTriggerConditionError( + context.getDataContract().getId().toBuffer(), + documentTransition.getId().toBuffer(), + `ownerId ${context.getOwnerId()} doesn't match dashUniqueIdentityId ${records.dashUniqueIdentityId}`, ); + + error.setOwnerId(context.getOwnerId()); + error.setDocumentTransition(documentTransition); + + result.addError(error); } if (records.dashAliasIdentityId && !context.getOwnerId().equals(records.dashAliasIdentityId)) { - result.addError( - new DataTriggerConditionError( - documentTransition, - context.getDataContract(), - context.getOwnerId(), - 'ownerId doesn\'t match dashAliasIdentityId', - ), + const error = new DataTriggerConditionError( + context.getDataContract().getId().toBuffer(), + documentTransition.getId().toBuffer(), + `ownerId ${context.getOwnerId()} doesn't match dashAliasIdentityId ${records.dashAliasIdentityId}`, ); + + error.setOwnerId(context.getOwnerId()); + error.setDocumentTransition(documentTransition); + + result.addError(error); } if (normalizedParentDomainName.length === 0 && !context.getOwnerId().equals(topLevelIdentity)) { - result.addError( - new DataTriggerConditionError( - documentTransition, - context.getDataContract(), - context.getOwnerId(), - 'Can\'t create top level domain for this identity', - ), + const error = new DataTriggerConditionError( + context.getDataContract().getId().toBuffer(), + documentTransition.getId().toBuffer(), + 'Can\'t create top level domain for this identity', ); + + error.setOwnerId(context.getOwnerId()); + error.setDocumentTransition(documentTransition); + + result.addError(error); } if (normalizedParentDomainName.length > 0) { @@ -108,39 +118,45 @@ async function createDomainDataTrigger(documentTransition, context, topLevelIden ); if (!parentDomain) { - result.addError( - new DataTriggerConditionError( - documentTransition, - context.getDataContract(), - context.getOwnerId(), - 'Parent domain is not present', - ), + const error = new DataTriggerConditionError( + context.getDataContract().getId().toBuffer(), + documentTransition.getId().toBuffer(), + 'Parent domain is not present', ); + error.setOwnerId(context.getOwnerId()); + error.setDocumentTransition(documentTransition); + + result.addError(error); + return result; } if (subdomainRules.allowSubdomains === true) { - result.addError( - new DataTriggerConditionError( - documentTransition, - context.getDataContract(), - context.getOwnerId(), - 'Allowing subdomains registration is forbidden for non top level domains', - ), + const error = new DataTriggerConditionError( + context.getDataContract().getId().toBuffer(), + documentTransition.getId().toBuffer(), + 'Allowing subdomains registration is forbidden for non top level domains', ); + + error.setOwnerId(context.getOwnerId()); + error.setDocumentTransition(documentTransition); + + result.addError(error); } if (parentDomain.getData().subdomainRules.allowSubdomains === false && !context.getOwnerId().equals(parentDomain.getOwnerId())) { - result.addError( - new DataTriggerConditionError( - documentTransition, - context.getDataContract(), - context.getOwnerId(), - 'The subdomain can be created only by the parent domain owner', - ), + const error = new DataTriggerConditionError( + context.getDataContract().getId().toBuffer(), + documentTransition.getId().toBuffer(), + 'The subdomain can be created only by the parent domain owner', ); + + error.setOwnerId(context.getOwnerId()); + error.setDocumentTransition(documentTransition); + + result.addError(error); } } @@ -159,14 +175,16 @@ async function createDomainDataTrigger(documentTransition, context, topLevelIden ); if (!preorderDocument) { - result.addError( - new DataTriggerConditionError( - documentTransition, - context.getDataContract(), - context.getOwnerId(), - 'preorderDocument was not found', - ), + const error = new DataTriggerConditionError( + context.getDataContract().getId().toBuffer(), + documentTransition.getId().toBuffer(), + 'preorderDocument was not found', ); + + error.setOwnerId(context.getOwnerId()); + error.setDocumentTransition(documentTransition); + + result.addError(error); } return result; diff --git a/lib/dataTrigger/featureFlagsDataTriggers/createFeatureFlagDataTrigger.js b/lib/dataTrigger/featureFlagsDataTriggers/createFeatureFlagDataTrigger.js index 5ef2bfd5..7ae858e0 100644 --- a/lib/dataTrigger/featureFlagsDataTriggers/createFeatureFlagDataTrigger.js +++ b/lib/dataTrigger/featureFlagsDataTriggers/createFeatureFlagDataTrigger.js @@ -17,27 +17,31 @@ async function createFeatureFlagDataTrigger(documentTransition, context, topLeve const { height: blockHeight } = await stateRepository.fetchLatestPlatformBlockHeader(); if (Long.fromNumber(documentTransition.get('enableAtHeight')).lt(blockHeight)) { - result.addError( - new DataTriggerConditionError( - documentTransition, - context.getDataContract(), - context.getOwnerId(), - 'Feature flag cannot be enabled in the past', - ), + const error = new DataTriggerConditionError( + context.getDataContract().getId().toBuffer(), + documentTransition.getId().toBuffer(), + `Feature flag cannot be enabled in the past on block ${documentTransition.get('enableAtHeight')}. Current block height is ${blockHeight}`, ); + error.setOwnerId(context.getOwnerId()); + error.setDocumentTransition(documentTransition); + + result.addError(error); + return result; } if (!context.getOwnerId().equals(topLevelIdentityId)) { - result.addError( - new DataTriggerConditionError( - documentTransition, - context.getDataContract(), - context.getOwnerId(), - 'This identity can\'t activate selected feature flag', - ), + const error = new DataTriggerConditionError( + context.getDataContract().getId().toBuffer(), + documentTransition.getId().toBuffer(), + 'This identity can\'t activate selected feature flag', ); + + error.setOwnerId(context.getOwnerId()); + error.setDocumentTransition(documentTransition); + + result.addError(error); } return result; diff --git a/lib/dataTrigger/rejectDataTrigger.js b/lib/dataTrigger/rejectDataTrigger.js index fee0e848..fd5ae711 100644 --- a/lib/dataTrigger/rejectDataTrigger.js +++ b/lib/dataTrigger/rejectDataTrigger.js @@ -14,9 +14,8 @@ async function rejectDataTrigger(documentTransition, context) { result.addError( new DataTriggerConditionError( - documentTransition, - context.getDataContract(), - context.getOwnerId(), + documentTransition.getId().toBuffer(), + context.getDataContract().getId().toBuffer(), 'Action is not allowed', ), ); diff --git a/lib/decodeProtocolEntityFactory.js b/lib/decodeProtocolEntityFactory.js index 9744b2b8..3073d5bc 100644 --- a/lib/decodeProtocolEntityFactory.js +++ b/lib/decodeProtocolEntityFactory.js @@ -19,16 +19,16 @@ function decodeProtocolEntityFactory(versionCompatibilityMap) { try { protocolVersion = buffer.slice(0, 4).readUInt32LE(0); } catch (error) { - throw new ProtocolVersionParsingError( - buffer, - error, - ); + const consensusError = new ProtocolVersionParsingError(error.message); + + consensusError.setParsingError(error); + + throw consensusError; } // Parsed protocol version must be equal or lower than current version if (protocolVersion > currentProtocolVersion) { throw new UnsupportedProtocolVersionError( - buffer, protocolVersion, currentProtocolVersion, ); @@ -43,7 +43,6 @@ function decodeProtocolEntityFactory(versionCompatibilityMap) { // Parsed protocol version must higher or equal to the minimum compatible version if (protocolVersion < minimalProtocolVersion) { throw new IncompatibleProtocolVersionError( - buffer, protocolVersion, minimalProtocolVersion, ); @@ -55,10 +54,11 @@ function decodeProtocolEntityFactory(versionCompatibilityMap) { buffer.slice(4, buffer.length), ); } catch (error) { - throw new SerializedObjectParsingError( - buffer, - error, - ); + const consensusError = new SerializedObjectParsingError(error.message); + + consensusError.setParsingError(error); + + throw consensusError; } return [protocolVersion, rawEntity]; diff --git a/lib/document/DocumentFacade.js b/lib/document/DocumentFacade.js index f63f7d2a..9ac2d1d8 100644 --- a/lib/document/DocumentFacade.js +++ b/lib/document/DocumentFacade.js @@ -40,7 +40,7 @@ class DocumentFacade { * Create Document * * @param {DataContract} dataContract - * @param {Buffer} ownerId + * @param {Identifier|Buffer} ownerId * @param {string} type * @param {Object} [data] * @return {Document} diff --git a/lib/document/DocumentFactory.js b/lib/document/DocumentFactory.js index b1718acb..95e87b2e 100644 --- a/lib/document/DocumentFactory.js +++ b/lib/document/DocumentFactory.js @@ -8,7 +8,7 @@ const DocumentsBatchTransition = require('./stateTransition/DocumentsBatchTransi const AbstractDocumentTransition = require('./stateTransition/DocumentsBatchTransition/documentTransition/AbstractDocumentTransition'); const DocumentCreateTransition = require('./stateTransition/DocumentsBatchTransition/documentTransition/DocumentCreateTransition'); -const ConsensusError = require('../errors/consensus/ConsensusError'); +const AbstractConsensusError = require('../errors/consensus/AbstractConsensusError'); const InvalidActionNameError = require('./errors/InvalidActionNameError'); const NoDocumentsSuppliedError = require('./errors/NoDocumentsSuppliedError'); const MismatchOwnerIdsError = require('./errors/MismatchOwnerIdsError'); @@ -39,7 +39,7 @@ class DocumentFactory { * Create Document * * @param {DataContract} dataContract - * @param {Buffer} ownerId + * @param {Identifier|Buffer} ownerId * @param {string} type * @param {Object} [data] * @return {Document} @@ -174,7 +174,7 @@ class DocumentFactory { rawDocument.$protocolVersion = protocolVersion; } catch (error) { - if (error instanceof ConsensusError) { + if (error instanceof AbstractConsensusError) { throw new InvalidDocumentError([error]); } diff --git a/lib/document/errors/InvalidDocumentError.js b/lib/document/errors/InvalidDocumentError.js index 29690052..5fd30eb6 100644 --- a/lib/document/errors/InvalidDocumentError.js +++ b/lib/document/errors/InvalidDocumentError.js @@ -2,7 +2,7 @@ const DPPError = require('../../errors/DPPError'); class InvalidDocumentError extends DPPError { /** - * @param {ConsensusError[]} errors + * @param {AbstractConsensusError[]} errors * @param {RawDocument} rawDocument */ constructor(errors, rawDocument) { @@ -20,7 +20,7 @@ class InvalidDocumentError extends DPPError { /** * Get validation errors * - * @return {ConsensusError[]} + * @return {AbstractConsensusError[]} */ getErrors() { return this.errors; diff --git a/lib/document/fetchAndValidateDataContractFactory.js b/lib/document/fetchAndValidateDataContractFactory.js index ca2bf3ec..e00a4e1c 100644 --- a/lib/document/fetchAndValidateDataContractFactory.js +++ b/lib/document/fetchAndValidateDataContractFactory.js @@ -20,7 +20,7 @@ function fetchAndValidateDataContractFactory(stateRepository) { if (!Object.prototype.hasOwnProperty.call(rawDocument, '$dataContractId')) { result.addError( - new MissingDataContractIdError(rawDocument), + new MissingDataContractIdError(), ); } @@ -42,7 +42,7 @@ function fetchAndValidateDataContractFactory(stateRepository) { if (!dataContract) { result.addError( - new DataContractNotPresentError(dataContractId), + new DataContractNotPresentError(dataContractId.toBuffer()), ); } diff --git a/lib/document/stateTransition/DocumentsBatchTransition/validation/basic/validateDocumentsBatchTransitionBasicFactory.js b/lib/document/stateTransition/DocumentsBatchTransition/validation/basic/validateDocumentsBatchTransitionBasicFactory.js index 592b7591..74a00a2f 100644 --- a/lib/document/stateTransition/DocumentsBatchTransition/validation/basic/validateDocumentsBatchTransitionBasicFactory.js +++ b/lib/document/stateTransition/DocumentsBatchTransition/validation/basic/validateDocumentsBatchTransitionBasicFactory.js @@ -4,7 +4,7 @@ const AbstractDocumentTransition = require('../../documentTransition/AbstractDoc const DataContractNotPresentError = require('../../../../../errors/consensus/basic/document/DataContractNotPresentError'); const InvalidDocumentTransitionIdError = require('../../../../../errors/consensus/basic/document/InvalidDocumentTransitionIdError'); -const DuplicateDocumentTransitionsError = require('../../../../../errors/consensus/basic/document/DuplicateDocumentTransitionsError'); +const DuplicateDocumentTransitionsWithIdsError = require('../../../../../errors/consensus/basic/document/DuplicateDocumentTransitionsWithIdsError'); const MissingDocumentTransitionTypeError = require('../../../../../errors/consensus/basic/document/MissingDocumentTransitionTypeError'); const InvalidDocumentTypeError = require('../../../../../errors/consensus/basic/document/InvalidDocumentTypeError'); const InvalidDocumentTransitionActionError = require('../../../../../errors/consensus/basic/document/InvalidDocumentTransitionActionError'); @@ -21,6 +21,7 @@ const convertBuffersToArrays = require('../../../../../util/convertBuffersToArra const documentsBatchTransitionSchema = require('../../../../../../schema/document/stateTransition/documentsBatch.json'); const createAndValidateIdentifier = require('../../../../../identifier/createAndValidateIdentifier'); +const DuplicateDocumentTransitionsWithIndicesError = require('../../../../../errors/consensus/basic/document/DuplicateDocumentTransitionsWithIndicesError'); /** * @param {findDuplicatesById} findDuplicatesById @@ -84,7 +85,7 @@ function validateDocumentsBatchTransitionBasicFactory( // Validate $type if (!Object.prototype.hasOwnProperty.call(rawDocumentTransition, '$type')) { result.addError( - new MissingDocumentTransitionTypeError(rawDocumentTransition), + new MissingDocumentTransitionTypeError(), ); return; @@ -92,7 +93,10 @@ function validateDocumentsBatchTransitionBasicFactory( if (!dataContract.isDocumentDefined(rawDocumentTransition.$type)) { result.addError( - new InvalidDocumentTypeError(rawDocumentTransition.$type, dataContract), + new InvalidDocumentTypeError( + rawDocumentTransition.$type, + dataContract.getId().toBuffer(), + ), ); return; @@ -101,7 +105,7 @@ function validateDocumentsBatchTransitionBasicFactory( // Validate $action if (!Object.prototype.hasOwnProperty.call(rawDocumentTransition, '$action')) { result.addError( - new MissingDocumentTransitionActionError(rawDocumentTransition), + new MissingDocumentTransitionActionError(), ); return; @@ -147,7 +151,10 @@ function validateDocumentsBatchTransitionBasicFactory( if (!rawDocumentTransition.$id.equals(documentId)) { result.addError( - new InvalidDocumentTransitionIdError(rawDocumentTransition), + new InvalidDocumentTransitionIdError( + documentId, + rawDocumentTransition.$id, + ), ); } } @@ -164,9 +171,10 @@ function validateDocumentsBatchTransitionBasicFactory( break; default: - throw new InvalidDocumentTransitionActionError( - rawDocumentTransition.$action, - rawDocumentTransition, + result.addError( + new InvalidDocumentTransitionActionError( + rawDocumentTransition.$action, + ), ); } }); @@ -179,7 +187,11 @@ function validateDocumentsBatchTransitionBasicFactory( const duplicateTransitions = findDuplicatesById(rawDocumentTransitions); if (duplicateTransitions.length > 0) { result.addError( - new DuplicateDocumentTransitionsError(duplicateTransitions), + new DuplicateDocumentTransitionsWithIdsError( + duplicateTransitions.map( + (documentTransition) => [documentTransition.$type, documentTransition.$id], + ), + ), ); } @@ -191,7 +203,11 @@ function validateDocumentsBatchTransitionBasicFactory( if (duplicateTransitionsByIndices.length > 0) { result.addError( - new DuplicateDocumentTransitionsError(duplicateTransitionsByIndices), + new DuplicateDocumentTransitionsWithIndicesError( + duplicateTransitionsByIndices.map( + (documentTransition) => [documentTransition.$type, documentTransition.$id], + ), + ), ); } @@ -232,7 +248,7 @@ function validateDocumentsBatchTransitionBasicFactory( .reduce((obj, rawDocumentTransition) => { if (!Object.prototype.hasOwnProperty.call(rawDocumentTransition, '$dataContractId')) { result.addError( - new MissingDataContractIdError(rawDocumentTransition), + new MissingDataContractIdError(), ); return obj; diff --git a/lib/document/stateTransition/DocumentsBatchTransition/validation/basic/validatePartialCompoundIndices.js b/lib/document/stateTransition/DocumentsBatchTransition/validation/basic/validatePartialCompoundIndices.js index ee75319f..4b50cd03 100644 --- a/lib/document/stateTransition/DocumentsBatchTransition/validation/basic/validatePartialCompoundIndices.js +++ b/lib/document/stateTransition/DocumentsBatchTransition/validation/basic/validatePartialCompoundIndices.js @@ -51,10 +51,12 @@ function validatePartialCompoundIndices( const isOk = allAreDefined || allAreUndefined; if (!isOk) { - result.addError(new InconsistentCompoundIndexDataError( - rawDocumentTransition.$type, - indexDefinition, - )); + result.addError( + new InconsistentCompoundIndexDataError( + rawDocumentTransition.$type, + indexDefinition.properties.map((i) => Object.keys(i)[0]), + ), + ); } }); }); diff --git a/lib/document/stateTransition/DocumentsBatchTransition/validation/state/executeDataTriggersFactory.js b/lib/document/stateTransition/DocumentsBatchTransition/validation/state/executeDataTriggersFactory.js index 7c1b4bda..70b1cfaa 100644 --- a/lib/document/stateTransition/DocumentsBatchTransition/validation/state/executeDataTriggersFactory.js +++ b/lib/document/stateTransition/DocumentsBatchTransition/validation/state/executeDataTriggersFactory.js @@ -31,7 +31,7 @@ function executeDataTriggersFactory(getDataTriggers) { /** * Execute data trigger for a document with a context * - * @typedef executeDataTriggers + * @typedef {executeDataTriggers} * * @param {DocumentCreateTransition[] * |DocumentReplaceTransition[] diff --git a/lib/document/stateTransition/DocumentsBatchTransition/validation/state/validateDocumentsBatchTransitionStateFactory.js b/lib/document/stateTransition/DocumentsBatchTransition/validation/state/validateDocumentsBatchTransitionStateFactory.js index 69a00157..a6d687dd 100644 --- a/lib/document/stateTransition/DocumentsBatchTransition/validation/state/validateDocumentsBatchTransitionStateFactory.js +++ b/lib/document/stateTransition/DocumentsBatchTransition/validation/state/validateDocumentsBatchTransitionStateFactory.js @@ -94,7 +94,11 @@ function validateDocumentsBatchTransitionStateFactory( const updatedAtTime = documentTransition.getUpdatedAt().getTime(); if (createdAtTime !== updatedAtTime) { - result.addError(new DocumentTimestampsMismatchError(documentTransition)); + result.addError( + new DocumentTimestampsMismatchError( + documentTransition.getId().toBuffer(), + ), + ); } } @@ -102,10 +106,15 @@ function validateDocumentsBatchTransitionStateFactory( if (documentTransition.getCreatedAt() !== undefined) { const createdAtTime = documentTransition.getCreatedAt().getTime(); + // TODO: Why we comparing dates and numbers? if (createdAtTime < timeWindowStart || createdAtTime > timeWindowEnd) { result.addError( new DocumentTimestampWindowViolationError( - 'createdAt', documentTransition, fetchedDocument, + 'createdAt', + documentTransition.getId().toBuffer(), + documentTransition.getCreatedAt(), + timeWindowStart, + timeWindowEnd, ), ); } @@ -115,10 +124,15 @@ function validateDocumentsBatchTransitionStateFactory( if (documentTransition.getUpdatedAt() !== undefined) { const updatedAtTime = documentTransition.getUpdatedAt().getTime(); + // TODO: Why we comparing dates and numbers? if (updatedAtTime < timeWindowStart || updatedAtTime > timeWindowEnd) { result.addError( new DocumentTimestampWindowViolationError( - 'updatedAt', documentTransition, fetchedDocument, + 'updatedAt', + documentTransition.getId().toBuffer(), + documentTransition.getUpdatedAt(), + timeWindowStart, + timeWindowEnd, ), ); } @@ -126,7 +140,7 @@ function validateDocumentsBatchTransitionStateFactory( if (fetchedDocument) { result.addError( - new DocumentAlreadyPresentError(documentTransition, fetchedDocument), + new DocumentAlreadyPresentError(documentTransition.getId().toBuffer()), ); } break; @@ -138,7 +152,11 @@ function validateDocumentsBatchTransitionStateFactory( if (updatedAtTime < timeWindowStart || updatedAtTime > timeWindowEnd) { result.addError( new DocumentTimestampWindowViolationError( - 'updatedAt', documentTransition, fetchedDocument, + 'updatedAt', + documentTransition.getId().toBuffer(), + documentTransition.getUpdatedAt(), + timeWindowStart, + timeWindowEnd, ), ); } @@ -149,7 +167,10 @@ function validateDocumentsBatchTransitionStateFactory( && documentTransition.getRevision() !== fetchedDocument.getRevision() + 1 ) { result.addError( - new InvalidDocumentRevisionError(documentTransition, fetchedDocument), + new InvalidDocumentRevisionError( + documentTransition.getId().toBuffer(), + fetchedDocument.getRevision(), + ), ); } } @@ -157,7 +178,7 @@ function validateDocumentsBatchTransitionStateFactory( case AbstractDocumentTransition.ACTIONS.DELETE: { if (!fetchedDocument) { result.addError( - new DocumentNotFoundError(documentTransition), + new DocumentNotFoundError(documentTransition.getId().toBuffer()), ); break; @@ -165,7 +186,11 @@ function validateDocumentsBatchTransitionStateFactory( if (!fetchedDocument.getOwnerId().equals(ownerId)) { result.addError( - new DocumentOwnerIdMismatchError(documentTransition, fetchedDocument), + new DocumentOwnerIdMismatchError( + documentTransition.getId().toBuffer(), + ownerId.toBuffer(), + fetchedDocument.getOwnerId().toBuffer(), + ), ); } diff --git a/lib/document/stateTransition/DocumentsBatchTransition/validation/state/validateDocumentsUniquenessByIndicesFactory.js b/lib/document/stateTransition/DocumentsBatchTransition/validation/state/validateDocumentsUniquenessByIndicesFactory.js index 7cc1572d..05ae13d2 100644 --- a/lib/document/stateTransition/DocumentsBatchTransition/validation/state/validateDocumentsUniquenessByIndicesFactory.js +++ b/lib/document/stateTransition/DocumentsBatchTransition/validation/state/validateDocumentsUniquenessByIndicesFactory.js @@ -1,5 +1,5 @@ const ValidationResult = require('../../../../../validation/ValidationResult'); -const DuplicateDocumentError = require('../../../../../errors/consensus/state/document/DuplicateDocumentError'); +const DuplicateUniqueIndexError = require('../../../../../errors/consensus/state/document/DuplicateUniqueIndexError'); const AbstractDocumentTransition = require('../../documentTransition/AbstractDocumentTransition'); /** @@ -101,14 +101,7 @@ function validateDocumentsUniquenessByIndicesFactory(stateRepository) { }); }); - let fetchedDocumentsByIndices; - - try { - fetchedDocumentsByIndices = await Promise.all(fetchRawDocumentPromises); - } catch (e) { - result.addError(e); - return result; - } + const fetchedDocumentsByIndices = await Promise.all(fetchRawDocumentPromises); // 3. Create errors if duplicates found fetchedDocumentsByIndices @@ -120,9 +113,9 @@ function validateDocumentsUniquenessByIndicesFactory(stateRepository) { return !isEmpty && !onlyOriginDocument; }).forEach((rawDocuments) => { result.addError( - new DuplicateDocumentError( - rawDocuments.documentTransition, - rawDocuments.indexDefinition, + new DuplicateUniqueIndexError( + rawDocuments.documentTransition.getId().toBuffer(), + rawDocuments.indexDefinition.properties.map((i) => Object.keys(i)[0]), ), ); }); diff --git a/lib/document/validation/validateDocumentFactory.js b/lib/document/validation/validateDocumentFactory.js index 4e0e9578..fe649041 100644 --- a/lib/document/validation/validateDocumentFactory.js +++ b/lib/document/validation/validateDocumentFactory.js @@ -27,7 +27,7 @@ module.exports = function validateDocumentFactory( if (!Object.prototype.hasOwnProperty.call(rawDocument, '$type')) { result.addError( - new MissingDocumentTypeError(rawDocument), + new MissingDocumentTypeError(), ); return result; @@ -35,7 +35,10 @@ module.exports = function validateDocumentFactory( if (!dataContract.isDocumentDefined(rawDocument.$type)) { result.addError( - new InvalidDocumentTypeError(rawDocument.$type, dataContract), + new InvalidDocumentTypeError( + rawDocument.$type, + dataContract.getId().toBuffer(), + ), ); return result; @@ -63,6 +66,10 @@ module.exports = function validateDocumentFactory( ), ); + if (!result.isValid()) { + return result; + } + return result; } diff --git a/lib/errors/consensus/AbstractConsensusError.js b/lib/errors/consensus/AbstractConsensusError.js new file mode 100644 index 00000000..c4da5d16 --- /dev/null +++ b/lib/errors/consensus/AbstractConsensusError.js @@ -0,0 +1,58 @@ +const DPPError = require('../DPPError'); + +const CONSTRUCTOR_ARGUMENTS_SYMBOL = Symbol.for('constructorArguments'); + +/** + * @abstract + */ +class AbstractConsensusError extends DPPError { + /** + * @param {string} message + */ + constructor(message) { + super(message); + + this[CONSTRUCTOR_ARGUMENTS_SYMBOL] = []; + } + + /** + * @return {number} + */ + getCode() { + // Mitigate recursive dependency + + // eslint-disable-next-line global-require + const codes = require('./codes'); + + const code = Object.keys(codes) + .find((c) => this.constructor === codes[c]); + + if (!code) { + throw new Error('Error code is not defined'); + } + + return parseInt(code, 10); + } + + /** + * Get array of the error's arguments + * + * @returns {*[]} + */ + getConstructorArguments() { + return this[CONSTRUCTOR_ARGUMENTS_SYMBOL]; + } + + /** + * Set the error's arguments. + * Must be called from the constructor + * + * @protected + * @param {Object|Array} args + */ + setConstructorArguments(args) { + this[CONSTRUCTOR_ARGUMENTS_SYMBOL] = Array.from(args); + } +} + +module.exports = AbstractConsensusError; diff --git a/lib/errors/consensus/ConsensusError.js b/lib/errors/consensus/ConsensusError.js deleted file mode 100644 index 6827d036..00000000 --- a/lib/errors/consensus/ConsensusError.js +++ /dev/null @@ -1,24 +0,0 @@ -const DPPError = require('../DPPError'); - -class ConsensusError extends DPPError { - /** - * @return {number} - */ - getCode() { - // Mitigate recursive dependency - - // eslint-disable-next-line global-require - const codes = require('./codes'); - - const code = Object.keys(codes) - .find((c) => this.constructor === codes[c]); - - if (!code) { - throw new Error('Error code is not defined'); - } - - return parseInt(code, 10); - } -} - -module.exports = ConsensusError; diff --git a/lib/errors/consensus/basic/AbstractBasicError.js b/lib/errors/consensus/basic/AbstractBasicError.js index 10284f13..876c150d 100644 --- a/lib/errors/consensus/basic/AbstractBasicError.js +++ b/lib/errors/consensus/basic/AbstractBasicError.js @@ -1,9 +1,9 @@ -const ConsensusError = require('../ConsensusError'); +const AbstractConsensusError = require('../AbstractConsensusError'); /** * @abstract */ -class AbstractBasicError extends ConsensusError { +class AbstractBasicError extends AbstractConsensusError { } diff --git a/lib/errors/consensus/basic/InvalidIdentifierError.js b/lib/errors/consensus/basic/InvalidIdentifierError.js index b1100287..7e004f55 100644 --- a/lib/errors/consensus/basic/InvalidIdentifierError.js +++ b/lib/errors/consensus/basic/InvalidIdentifierError.js @@ -3,13 +3,15 @@ const AbstractBasicError = require('./AbstractBasicError'); class InvalidIdentifierError extends AbstractBasicError { /** * @param {string} identifierName - * @param {IdentifierError} error + * @param {string} message */ - constructor(identifierName, error) { - super(`Invalid ${identifierName}: ${error.message}`); + constructor(identifierName, message) { + super(`Invalid ${identifierName}: ${message}`); this.identifierName = identifierName; - this.error = error; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** @@ -21,13 +23,22 @@ class InvalidIdentifierError extends AbstractBasicError { return this.identifierName; } + /** + * Set identifier error + * + * @param {Error} error + */ + setIdentifierError(error) { + this.identifierError = error; + } + /** * Get identifier error * - * @return {IdentifierError} + * @return {Error} */ getIdentifierError() { - return this.error; + return this.identifierError; } } diff --git a/lib/errors/consensus/basic/JsonSchemaCompilationError.js b/lib/errors/consensus/basic/JsonSchemaCompilationError.js new file mode 100644 index 00000000..ebf9699a --- /dev/null +++ b/lib/errors/consensus/basic/JsonSchemaCompilationError.js @@ -0,0 +1,12 @@ +const AbstractBasicError = require('./AbstractBasicError'); + +class JsonSchemaCompilationError extends AbstractBasicError { + constructor(message) { + super(message); + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); + } +} + +module.exports = JsonSchemaCompilationError; diff --git a/lib/errors/consensus/basic/JsonSchemaError.js b/lib/errors/consensus/basic/JsonSchemaError.js index b526f039..ee5b4f9c 100644 --- a/lib/errors/consensus/basic/JsonSchemaError.js +++ b/lib/errors/consensus/basic/JsonSchemaError.js @@ -1,10 +1,64 @@ const AbstractBasicError = require('./AbstractBasicError'); class JsonSchemaError extends AbstractBasicError { - constructor(error) { - super(error.message); + /** + * @param {string} message + * @param {string} keyword + * @param {string} instancePath + * @param {string} schemaPath + * @param {Object} params + * @param {string} [propertyName] + */ + constructor(message, keyword, instancePath, schemaPath, params, propertyName) { + super(message); - Object.assign(this, error); + this.keyword = keyword; + + this.instancePath = instancePath; + + this.schemaPath = schemaPath; + + this.params = params; + + this.propertyName = propertyName; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); + } + + /** + * @return {string} + */ + getKeyword() { + return this.keyword; + } + + /** + * @return {string} + */ + getInstancePath() { + return this.instancePath; + } + + /** + * @return {string} + */ + getSchemaPath() { + return this.schemaPath; + } + + /** + * @return {Object} + */ + getParams() { + return this.params; + } + + /** + * @return {string} + */ + getPropertyName() { + return this.propertyName; } } diff --git a/lib/errors/consensus/basic/dataContract/AbstractIndexError.js b/lib/errors/consensus/basic/dataContract/AbstractIndexError.js index 3e3fe86e..60799a6b 100644 --- a/lib/errors/consensus/basic/dataContract/AbstractIndexError.js +++ b/lib/errors/consensus/basic/dataContract/AbstractIndexError.js @@ -7,27 +7,16 @@ const AbstractBasicError = require('../AbstractBasicError'); class AbstractIndexError extends AbstractBasicError { /** * @param {string} message - * @param {RawDataContract} rawDataContract * @param {string} documentType * @param {Object} indexDefinition */ - constructor(message, rawDataContract, documentType, indexDefinition) { + constructor(message, documentType, indexDefinition) { super(message); - this.rawDataContract = rawDataContract; this.documentType = documentType; this.indexDefintion = indexDefinition; } - /** - * Get raw Data Contract - * - * @return {RawDataContract} - */ - getRawDataContract() { - return this.rawDataContract; - } - /** * Get Document type * diff --git a/lib/errors/consensus/basic/dataContract/DuplicateIndexError.js b/lib/errors/consensus/basic/dataContract/DuplicateIndexError.js index 745956d4..83910d06 100644 --- a/lib/errors/consensus/basic/dataContract/DuplicateIndexError.js +++ b/lib/errors/consensus/basic/dataContract/DuplicateIndexError.js @@ -2,19 +2,20 @@ const AbstractIndexError = require('./AbstractIndexError'); class DuplicateIndexError extends AbstractIndexError { /** - * @param {RawDataContract} rawDataContract * @param {string} documentType * @param {Object} indexDefinition */ - constructor(rawDataContract, documentType, indexDefinition) { + constructor(documentType, indexDefinition) { const message = `Duplicate index definition for "${documentType}" document`; super( message, - rawDataContract, documentType, indexDefinition, ); + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } } diff --git a/lib/document/errors/IncompatibleRe2PatternError.js b/lib/errors/consensus/basic/dataContract/IncompatibleRe2PatternError.js similarity index 51% rename from lib/document/errors/IncompatibleRe2PatternError.js rename to lib/errors/consensus/basic/dataContract/IncompatibleRe2PatternError.js index 66538260..2e107258 100644 --- a/lib/document/errors/IncompatibleRe2PatternError.js +++ b/lib/errors/consensus/basic/dataContract/IncompatibleRe2PatternError.js @@ -1,18 +1,17 @@ -const ConsensusError = require('../../errors/consensus/ConsensusError'); +const AbstractConsensusError = require('../../AbstractConsensusError'); -class IncompatibleRe2PatternError extends ConsensusError { +class IncompatibleRe2PatternError extends AbstractConsensusError { /** * * @param {string} pattern * @param {string} path - * @param {string} originalErrorMessage + * @param {string} message */ - constructor(pattern, path, originalErrorMessage) { - super(`Pattern ${pattern} at ${path} is not compatible with Re2: ${originalErrorMessage}`); + constructor(pattern, path, message) { + super(`Pattern ${pattern} at ${path} is not compatible with Re2: ${message}`); this.pattern = pattern; this.path = path; - this.originalErrorMessage = originalErrorMessage; } /** @@ -32,11 +31,17 @@ class IncompatibleRe2PatternError extends ConsensusError { } /** - * - * @returns {string} + * @param {Error} error + */ + setPatternError(error) { + this.patternError = error; + } + + /** + * @returns {Error} */ - getOriginalErrorMessage() { - return this.originalErrorMessage; + getPatternError() { + return this.patternError; } } diff --git a/lib/errors/consensus/basic/dataContract/InvalidCompoundIndexError.js b/lib/errors/consensus/basic/dataContract/InvalidCompoundIndexError.js index 20f6d317..1bebb96a 100644 --- a/lib/errors/consensus/basic/dataContract/InvalidCompoundIndexError.js +++ b/lib/errors/consensus/basic/dataContract/InvalidCompoundIndexError.js @@ -3,17 +3,18 @@ const AbstractIndexError = require('./AbstractIndexError'); class InvalidCompoundIndexError extends AbstractIndexError { /** * - * @param {RawDataContract} rawDataContract * @param {string} documentType * @param {Object} indexDefinition */ - constructor(rawDataContract, documentType, indexDefinition) { + constructor(documentType, indexDefinition) { super( - 'All or none of unique compound index properties must be set', - rawDataContract, + `All or none of unique compound index properties must be set for "${documentType}" document`, documentType, indexDefinition, ); + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } } diff --git a/lib/errors/consensus/basic/dataContract/InvalidDataContractIdError.js b/lib/errors/consensus/basic/dataContract/InvalidDataContractIdError.js index 8e459e36..46891dc7 100644 --- a/lib/errors/consensus/basic/dataContract/InvalidDataContractIdError.js +++ b/lib/errors/consensus/basic/dataContract/InvalidDataContractIdError.js @@ -1,15 +1,25 @@ +const bs58 = require('bs58'); + const AbstractBasicError = require('../AbstractBasicError'); +const Identifier = require('../../../../identifier/Identifier'); + class InvalidDataContractIdError extends AbstractBasicError { /** * @param {Buffer} expectedId * @param {Buffer} invalidId */ constructor(expectedId, invalidId) { - super(`DataContract ID must be ${expectedId.toString('hex')}, got ${invalidId.toString('hex')}`); + const expectedIdentifier = Identifier.from(expectedId); + const invalidIdentifier = bs58.encode(invalidId); + + super(`Data Contract ID must be ${expectedIdentifier}, got ${invalidIdentifier}`); this.expectedId = expectedId; this.invalidId = invalidId; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** diff --git a/lib/errors/consensus/basic/dataContract/InvalidIndexPropertyTypeError.js b/lib/errors/consensus/basic/dataContract/InvalidIndexPropertyTypeError.js index e1f722f9..f6f2c6aa 100644 --- a/lib/errors/consensus/basic/dataContract/InvalidIndexPropertyTypeError.js +++ b/lib/errors/consensus/basic/dataContract/InvalidIndexPropertyTypeError.js @@ -2,24 +2,25 @@ const AbstractIndexError = require('./AbstractIndexError'); class InvalidIndexPropertyTypeError extends AbstractIndexError { /** - * @param {RawDataContract} rawDataContract * @param {string} documentType * @param {Object} indexDefinition * @param {string} propertyName * @param {string} propertyType */ - constructor(rawDataContract, documentType, indexDefinition, propertyName, propertyType) { - const message = `'${propertyName}' property has an invalid type ${propertyType} and can not be used as index`; + constructor(documentType, indexDefinition, propertyName, propertyType) { + const message = `'${propertyName}' property for ${documentType} document has an invalid type ${propertyType} and can not be used as index`; super( message, - rawDataContract, documentType, indexDefinition, ); this.propertyName = propertyName; this.propertyType = propertyType; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** diff --git a/lib/errors/consensus/basic/dataContract/InvalidIndexedPropertyConstraintError.js b/lib/errors/consensus/basic/dataContract/InvalidIndexedPropertyConstraintError.js index b27fd6a0..58acbb13 100644 --- a/lib/errors/consensus/basic/dataContract/InvalidIndexedPropertyConstraintError.js +++ b/lib/errors/consensus/basic/dataContract/InvalidIndexedPropertyConstraintError.js @@ -2,7 +2,6 @@ const AbstractIndexError = require('./AbstractIndexError'); class InvalidIndexedPropertyConstraintError extends AbstractIndexError { /** - * @param {RawDataContract} rawDataContract * @param {string} documentType * @param {Object} indexDefinition * @param {string} propertyName @@ -10,19 +9,17 @@ class InvalidIndexedPropertyConstraintError extends AbstractIndexError { * @param {string} reason */ constructor( - rawDataContract, documentType, indexDefinition, propertyName, constraintName, reason, ) { - const message = `Indexed property '${propertyName}' have invalid constraint '${constraintName}',` + const message = `Indexed property '${propertyName}' for ${documentType} document have invalid constraint '${constraintName}',` + ` reason '${reason}'`; super( message, - rawDataContract, documentType, indexDefinition, ); @@ -30,6 +27,9 @@ class InvalidIndexedPropertyConstraintError extends AbstractIndexError { this.propertyName = propertyName; this.constraintName = constraintName; this.reason = reason; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** diff --git a/lib/errors/consensus/basic/dataContract/InvalidJsonSchemaRefError.js b/lib/errors/consensus/basic/dataContract/InvalidJsonSchemaRefError.js new file mode 100644 index 00000000..272479c9 --- /dev/null +++ b/lib/errors/consensus/basic/dataContract/InvalidJsonSchemaRefError.js @@ -0,0 +1,26 @@ +const AbstractBasicError = require('../AbstractBasicError'); + +class InvalidJsonSchemaRefError extends AbstractBasicError { + constructor(message) { + super(`Invalid JSON Schema $ref: ${message}`); + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); + } + + /** + * @param {Error} error + */ + setRefError(error) { + this.refError = error; + } + + /** + * @returns {Error} + */ + getRefError() { + return this.refError; + } +} + +module.exports = InvalidJsonSchemaRefError; diff --git a/lib/errors/consensus/basic/dataContract/SystemPropertyIndexAlreadyPresentError.js b/lib/errors/consensus/basic/dataContract/SystemPropertyIndexAlreadyPresentError.js index 07dc5cae..8f36f297 100644 --- a/lib/errors/consensus/basic/dataContract/SystemPropertyIndexAlreadyPresentError.js +++ b/lib/errors/consensus/basic/dataContract/SystemPropertyIndexAlreadyPresentError.js @@ -2,22 +2,23 @@ const AbstractIndexError = require('./AbstractIndexError'); class SystemPropertyIndexAlreadyPresentError extends AbstractIndexError { /** - * @param {RawDataContract} rawDataContract * @param {string} documentType * @param {Object} indexDefinition * @param {string} propertyName */ - constructor(rawDataContract, documentType, indexDefinition, propertyName) { - const message = `Single-property index on ${propertyName} system property is already present for quering.`; + constructor(documentType, indexDefinition, propertyName) { + const message = `Single-property index on ${propertyName} system property is already indexed for ${documentType} document.`; super( message, - rawDataContract, documentType, indexDefinition, ); this.propertyName = propertyName; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** diff --git a/lib/errors/consensus/basic/dataContract/UndefinedIndexPropertyError.js b/lib/errors/consensus/basic/dataContract/UndefinedIndexPropertyError.js index 30cc4f08..c25ecb89 100644 --- a/lib/errors/consensus/basic/dataContract/UndefinedIndexPropertyError.js +++ b/lib/errors/consensus/basic/dataContract/UndefinedIndexPropertyError.js @@ -2,22 +2,23 @@ const AbstractIndexError = require('./AbstractIndexError'); class UndefinedIndexPropertyError extends AbstractIndexError { /** - * @param {RawDataContract} rawDataContract * @param {string} documentType * @param {Object} indexDefinition * @param {string} propertyName */ - constructor(rawDataContract, documentType, indexDefinition, propertyName) { - const message = `'${propertyName}' property is not defined in the document`; + constructor(documentType, indexDefinition, propertyName) { + const message = `'${propertyName}' property is not defined in the ${documentType} document`; super( message, - rawDataContract, documentType, indexDefinition, ); this.propertyName = propertyName; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** diff --git a/lib/errors/consensus/basic/dataContract/UniqueIndicesLimitReachedError.js b/lib/errors/consensus/basic/dataContract/UniqueIndicesLimitReachedError.js index f338e4dc..6ddf5c07 100644 --- a/lib/errors/consensus/basic/dataContract/UniqueIndicesLimitReachedError.js +++ b/lib/errors/consensus/basic/dataContract/UniqueIndicesLimitReachedError.js @@ -2,19 +2,20 @@ const AbstractIndexError = require('./AbstractIndexError'); class UniqueIndicesLimitReachedError extends AbstractIndexError { /** - * @param {RawDataContract} rawDataContract * @param {string} documentType */ - constructor(rawDataContract, documentType) { + constructor(documentType) { const message = `'${documentType}' document has more ` - + `than ${UniqueIndicesLimitReachedError.UNIQUE_INDEX_LIMIT} unique index $defs`; + + `than ${UniqueIndicesLimitReachedError.UNIQUE_INDEX_LIMIT} unique indexes`; super( message, - rawDataContract, documentType, {}, ); + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } } diff --git a/lib/errors/consensus/basic/decode/IncompatibleProtocolVersionError.js b/lib/errors/consensus/basic/decode/IncompatibleProtocolVersionError.js index e6b52ff1..05329506 100644 --- a/lib/errors/consensus/basic/decode/IncompatibleProtocolVersionError.js +++ b/lib/errors/consensus/basic/decode/IncompatibleProtocolVersionError.js @@ -1,28 +1,20 @@ -const ConsensusError = require('../../ConsensusError'); +const AbstractConsensusError = require('../../AbstractConsensusError'); -class IncompatibleProtocolVersionError extends ConsensusError { +class IncompatibleProtocolVersionError extends AbstractConsensusError { /** - * @param {Buffer} payload * @param {number} parsedProtocolVersion * @param {number} minimalProtocolVersion */ - constructor(payload, parsedProtocolVersion, minimalProtocolVersion) { + constructor(parsedProtocolVersion, minimalProtocolVersion) { super( `Protocol version ${parsedProtocolVersion} is not supported. Minimal supported protocol version is ${minimalProtocolVersion}`, ); - this.payload = payload; this.parsedProtocolVersion = parsedProtocolVersion; this.minimalProtocolVersion = minimalProtocolVersion; - } - /** - * Get object payload - * - * @return {Buffer} - */ - getPayload() { - return this.payload; + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** diff --git a/lib/errors/consensus/basic/decode/ProtocolVersionParsingError.js b/lib/errors/consensus/basic/decode/ProtocolVersionParsingError.js index aabc7cb6..3f1eac88 100644 --- a/lib/errors/consensus/basic/decode/ProtocolVersionParsingError.js +++ b/lib/errors/consensus/basic/decode/ProtocolVersionParsingError.js @@ -1,26 +1,21 @@ -const ConsensusError = require('../../ConsensusError'); +const AbstractConsensusError = require('../../AbstractConsensusError'); -class ProtocolVersionParsingError extends ConsensusError { +class ProtocolVersionParsingError extends AbstractConsensusError { /** - * @param {Buffer} payload - * @param {Error} parsingError + * @param {string} message */ - constructor(payload, parsingError) { - super( - `Can't read protocol version from serialized object: ${parsingError.message}`, - ); + constructor(message) { + super(`Can't read protocol version from serialized object: ${message}`); - this.payload = payload; - this.parsingError = parsingError; + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** - * Get object payload - * - * @return {Buffer} + * @param {Error} error */ - getPayload() { - return this.payload; + setParsingError(error) { + this.parsingError = error; } /** diff --git a/lib/errors/consensus/basic/decode/SerializedObjectParsingError.js b/lib/errors/consensus/basic/decode/SerializedObjectParsingError.js index 751a12da..be0a7152 100644 --- a/lib/errors/consensus/basic/decode/SerializedObjectParsingError.js +++ b/lib/errors/consensus/basic/decode/SerializedObjectParsingError.js @@ -1,26 +1,21 @@ -const ConsensusError = require('../../ConsensusError'); +const AbstractConsensusError = require('../../AbstractConsensusError'); -class SerializedObjectParsingError extends ConsensusError { +class SerializedObjectParsingError extends AbstractConsensusError { /** - * @param {Buffer} payload - * @param {Error} parsingError + * @param {string} message */ - constructor(payload, parsingError) { - super( - `Parsing of a serialized object failed due to: ${parsingError.message}`, - ); + constructor(message) { + super(`Parsing of a serialized object failed due to: ${message}`); - this.payload = payload; - this.parsingError = parsingError; + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** - * Get payload - * - * @return {Buffer} + * @param {Error} error */ - getPayload() { - return this.payload; + setParsingError(error) { + this.parsingError = error; } /** diff --git a/lib/errors/consensus/basic/decode/UnsupportedProtocolVersionError.js b/lib/errors/consensus/basic/decode/UnsupportedProtocolVersionError.js index 2438abdd..0bce8b3b 100644 --- a/lib/errors/consensus/basic/decode/UnsupportedProtocolVersionError.js +++ b/lib/errors/consensus/basic/decode/UnsupportedProtocolVersionError.js @@ -1,28 +1,20 @@ -const ConsensusError = require('../../ConsensusError'); +const AbstractConsensusError = require('../../AbstractConsensusError'); -class UnsupportedProtocolVersionError extends ConsensusError { +class UnsupportedProtocolVersionError extends AbstractConsensusError { /** - * @param {Buffer} payload * @param {number} parsedProtocolVersion * @param {number} currentProtocolVersion */ - constructor(payload, parsedProtocolVersion, currentProtocolVersion) { + constructor(parsedProtocolVersion, currentProtocolVersion) { super( `Protocol version ${parsedProtocolVersion} is not supported. Current version is ${currentProtocolVersion}`, ); - this.payload = payload; this.parsedProtocolVersion = parsedProtocolVersion; this.currentProtocolVersion = currentProtocolVersion; - } - /** - * Get object payload - * - * @return {Buffer} - */ - getPayload() { - return this.payload; + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** diff --git a/lib/errors/consensus/basic/document/DataContractNotPresentError.js b/lib/errors/consensus/basic/document/DataContractNotPresentError.js index a54158f6..60bd9326 100644 --- a/lib/errors/consensus/basic/document/DataContractNotPresentError.js +++ b/lib/errors/consensus/basic/document/DataContractNotPresentError.js @@ -1,19 +1,25 @@ const AbstractBasicError = require('../AbstractBasicError'); +const Identifier = require('../../../../identifier/Identifier'); class DataContractNotPresentError extends AbstractBasicError { /** - * @param {Identifier|Buffer} dataContractId + * @param {Buffer} dataContractId */ constructor(dataContractId) { - super('Data Contract with specified ID is not present'); + const dataContractIdentifier = Identifier.from(dataContractId); - this.dataContractId = dataContractId; + super(`Data Contract ${dataContractIdentifier} is not present`); + + this.dataContractId = dataContractIdentifier; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** * Get Data Contract ID * - * @return {Identifier|Buffer} + * @return {Identifier} */ getDataContractId() { return this.dataContractId; diff --git a/lib/errors/consensus/basic/document/DuplicateDocumentTransitionsError.js b/lib/errors/consensus/basic/document/DuplicateDocumentTransitionsError.js deleted file mode 100644 index b92ebca6..00000000 --- a/lib/errors/consensus/basic/document/DuplicateDocumentTransitionsError.js +++ /dev/null @@ -1,27 +0,0 @@ -const AbstractBasicError = require('../AbstractBasicError'); - -class DuplicateDocumentTransitionsError extends AbstractBasicError { - /** - * @param { - * Array. - * } rawDocumentTransitions - */ - constructor(rawDocumentTransitions) { - super('Duplicated document transitions found in state transition'); - - this.rawDocumentTransitions = rawDocumentTransitions; - } - - /** - * Get duplicate raw transitions - * - * @return { - * Array. - * } - */ - getRawDocumentTransitions() { - return this.rawDocumentTransitions; - } -} - -module.exports = DuplicateDocumentTransitionsError; diff --git a/lib/errors/consensus/basic/document/DuplicateDocumentTransitionsWithIdsError.js b/lib/errors/consensus/basic/document/DuplicateDocumentTransitionsWithIdsError.js new file mode 100644 index 00000000..4186ca89 --- /dev/null +++ b/lib/errors/consensus/basic/document/DuplicateDocumentTransitionsWithIdsError.js @@ -0,0 +1,34 @@ +const AbstractBasicError = require('../AbstractBasicError'); +const Identifier = require('../../../../identifier/Identifier'); + +class DuplicateDocumentTransitionsWithIdsError extends AbstractBasicError { + /** + * @param { + * [string, Buffer][] + * } documentTransitionReferences + */ + constructor(documentTransitionReferences) { + const references = documentTransitionReferences + .map(([type, id]) => `${type} ${Identifier.from(id)}`).join(', '); + + super(`Document transitions with duplicate IDs: ${references}`); + + this.documentTransitionReferences = documentTransitionReferences; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); + } + + /** + * Get duplicate transition references + * + * @return { + * [string, Buffer][] + * } + */ + getDocumentTransitionReferences() { + return this.documentTransitionReferences; + } +} + +module.exports = DuplicateDocumentTransitionsWithIdsError; diff --git a/lib/errors/consensus/basic/document/DuplicateDocumentTransitionsWithIndicesError.js b/lib/errors/consensus/basic/document/DuplicateDocumentTransitionsWithIndicesError.js new file mode 100644 index 00000000..50420ff5 --- /dev/null +++ b/lib/errors/consensus/basic/document/DuplicateDocumentTransitionsWithIndicesError.js @@ -0,0 +1,34 @@ +const AbstractBasicError = require('../AbstractBasicError'); +const Identifier = require('../../../../identifier/Identifier'); + +class DuplicateDocumentTransitionsWithIndicesError extends AbstractBasicError { + /** + * @param { + * [string, Buffer][] + * } documentTransitionReferences + */ + constructor(documentTransitionReferences) { + const references = documentTransitionReferences + .map(([type, id]) => `${type} ${Identifier.from(id)}`).join(', '); + + super(`Document transitions with duplicate unique properties: ${references}`); + + this.documentTransitionReferences = documentTransitionReferences; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); + } + + /** + * Get duplicate raw transition references + * + * @return { + * [string, Buffer][] + * } + */ + getDocumentTransitionReferences() { + return this.documentTransitionReferences; + } +} + +module.exports = DuplicateDocumentTransitionsWithIndicesError; diff --git a/lib/errors/consensus/basic/document/InconsistentCompoundIndexDataError.js b/lib/errors/consensus/basic/document/InconsistentCompoundIndexDataError.js index f223436b..ac66dc52 100644 --- a/lib/errors/consensus/basic/document/InconsistentCompoundIndexDataError.js +++ b/lib/errors/consensus/basic/document/InconsistentCompoundIndexDataError.js @@ -4,21 +4,23 @@ class InconsistentCompoundIndexDataError extends AbstractBasicError { /** * * @param {string} documentType - * @param {Object} indexDefinition + * @param {string[]} indexedProperties */ - constructor(documentType, indexDefinition) { - super('Unique compound index properties are partially set'); + constructor(documentType, indexedProperties) { + super(`Unique compound index properties ${indexedProperties.join(', ')} are partially set for ${documentType} document`); this.documentType = documentType; - this.indexDefinition = indexDefinition; + this.indexedProperties = indexedProperties; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** - * - * @return {Object} + * @return {string[]} */ - getIndexDefinition() { - return this.indexDefinition; + getIndexedProperties() { + return this.indexedProperties; } /** diff --git a/lib/errors/consensus/basic/document/InvalidDocumentTransitionActionError.js b/lib/errors/consensus/basic/document/InvalidDocumentTransitionActionError.js index 9c6c6428..5187a693 100644 --- a/lib/errors/consensus/basic/document/InvalidDocumentTransitionActionError.js +++ b/lib/errors/consensus/basic/document/InvalidDocumentTransitionActionError.js @@ -2,14 +2,15 @@ const AbstractBasicError = require('../AbstractBasicError'); class InvalidDocumentTransitionActionError extends AbstractBasicError { /** - * @param {*} action - * @param {Object} rawDocumentTransition + * @param {number} action */ - constructor(action, rawDocumentTransition) { + constructor(action) { super(`Document transition action ${action} is not supported`); this.action = action; - this.rawDocumentTransition = rawDocumentTransition; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** @@ -20,15 +21,6 @@ class InvalidDocumentTransitionActionError extends AbstractBasicError { getAction() { return this.action; } - - /** - * Get document transition - * - * @return {Object} - */ - getRawDocumentTransition() { - return this.rawDocumentTransition; - } } module.exports = InvalidDocumentTransitionActionError; diff --git a/lib/errors/consensus/basic/document/InvalidDocumentTransitionIdError.js b/lib/errors/consensus/basic/document/InvalidDocumentTransitionIdError.js index 010ec359..5862f321 100644 --- a/lib/errors/consensus/basic/document/InvalidDocumentTransitionIdError.js +++ b/lib/errors/consensus/basic/document/InvalidDocumentTransitionIdError.js @@ -1,26 +1,33 @@ const AbstractBasicError = require('../AbstractBasicError'); +const Identifier = require('../../../../identifier/Identifier'); class InvalidDocumentTransitionIdError extends AbstractBasicError { /** - * @param { - * RawDocumentCreateTransition|RawDocumentReplaceTransition|RawDocumentDeleteTransition - * } rawDocumentTransition + * @param {Buffer} expectedId + * @param {Buffer} invalidId */ - constructor(rawDocumentTransition) { - super('Invalid document transition id'); + constructor(expectedId, invalidId) { + super(`Invalid document transition id ${Identifier.from(invalidId)}, expected ${Identifier.from(expectedId)}`); - this.rawDocumentTransition = rawDocumentTransition; + this.expectedId = expectedId; + this.invalidId = invalidId; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); + } + + /** + * @return {Buffer} + */ + getExpectedId() { + return this.expectedId; } /** - * Get raw document transition - * - * @return { - * RawDocumentCreateTransition|RawDocumentReplaceTransition|RawDocumentDeleteTransition - * } + * @return {Buffer} */ - getRawDocumentTransition() { - return this.rawDocumentTransition; + getInvalidId() { + return this.invalidId; } } diff --git a/lib/errors/consensus/basic/document/InvalidDocumentTypeError.js b/lib/errors/consensus/basic/document/InvalidDocumentTypeError.js index 8e40c5d7..44810a21 100644 --- a/lib/errors/consensus/basic/document/InvalidDocumentTypeError.js +++ b/lib/errors/consensus/basic/document/InvalidDocumentTypeError.js @@ -1,15 +1,19 @@ const AbstractBasicError = require('../AbstractBasicError'); +const Identifier = require('../../../../identifier/Identifier'); class InvalidDocumentTypeError extends AbstractBasicError { /** * @param {string} type - * @param {DataContract} dataContract + * @param {Buffer} dataContractId */ - constructor(type, dataContract) { - super(`Data Contract doesn't define document with type ${type}`); + constructor(type, dataContractId) { + super(`Data Contract ${Identifier.from(dataContractId)} doesn't define document with type ${type}`); this.type = type; - this.dataContract = dataContract; + this.dataContractId = dataContractId; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** @@ -22,12 +26,12 @@ class InvalidDocumentTypeError extends AbstractBasicError { } /** - * Get Data Contract + * Get Data Contract ID * - * @return {DataContract} + * @return {Identifier} */ - getDataContract() { - return this.dataContract; + getDataContractId() { + return this.dataContractId; } } diff --git a/lib/errors/consensus/basic/document/MissingDataContractIdError.js b/lib/errors/consensus/basic/document/MissingDataContractIdError.js index cfad5a08..20f58045 100644 --- a/lib/errors/consensus/basic/document/MissingDataContractIdError.js +++ b/lib/errors/consensus/basic/document/MissingDataContractIdError.js @@ -1,22 +1,8 @@ const AbstractBasicError = require('../AbstractBasicError'); class MissingDataContractIdError extends AbstractBasicError { - /** - * @param {RawDocument} rawDocument - */ - constructor(rawDocument) { + constructor() { super('$dataContractId is not present'); - - this.rawDocument = rawDocument; - } - - /** - * Get raw Document - * - * @return {RawDocument} - */ - getRawDocument() { - return this.rawDocument; } } diff --git a/lib/errors/consensus/basic/document/MissingDocumentTransitionActionError.js b/lib/errors/consensus/basic/document/MissingDocumentTransitionActionError.js index 5126e883..ad272105 100644 --- a/lib/errors/consensus/basic/document/MissingDocumentTransitionActionError.js +++ b/lib/errors/consensus/basic/document/MissingDocumentTransitionActionError.js @@ -1,22 +1,8 @@ const AbstractBasicError = require('../AbstractBasicError'); class MissingDocumentTransitionActionError extends AbstractBasicError { - /** - * @param {AbstractDocumentTransition} rawDocumentTransition - */ - constructor(rawDocumentTransition) { + constructor() { super('$action is not present'); - - this.rawDocumentTransition = rawDocumentTransition; - } - - /** - * Get raw Document - * - * @return {Object} - */ - getRawDocumentTransition() { - return this.rawDocumentTransition; } } diff --git a/lib/errors/consensus/basic/document/MissingDocumentTransitionTypeError.js b/lib/errors/consensus/basic/document/MissingDocumentTransitionTypeError.js index 19f3c108..359259fe 100644 --- a/lib/errors/consensus/basic/document/MissingDocumentTransitionTypeError.js +++ b/lib/errors/consensus/basic/document/MissingDocumentTransitionTypeError.js @@ -1,30 +1,8 @@ const AbstractBasicError = require('../AbstractBasicError'); class MissingDocumentTransitionTypeError extends AbstractBasicError { - /** - * @param { - * RawDocumentCreateTransition| - * RawDocumentReplaceTransition| - * RawDocumentDeleteTransition - * } rawDocumentTransition - */ - constructor(rawDocumentTransition) { + constructor() { super('$type is not present'); - - this.rawDocumentTransition = rawDocumentTransition; - } - - /** - * Get Raw Document Transition - * - * @return { - * RawDocumentCreateTransition| - * RawDocumentReplaceTransition| - * RawDocumentDeleteTransition - * } - */ - getRawDocument() { - return this.rawDocumentTransition; } } diff --git a/lib/errors/consensus/basic/document/MissingDocumentTypeError.js b/lib/errors/consensus/basic/document/MissingDocumentTypeError.js index 713c89a5..390a3350 100644 --- a/lib/errors/consensus/basic/document/MissingDocumentTypeError.js +++ b/lib/errors/consensus/basic/document/MissingDocumentTypeError.js @@ -1,22 +1,8 @@ const AbstractBasicError = require('../AbstractBasicError'); class MissingDocumentTypeError extends AbstractBasicError { - /** - * @param {RawDocument} rawDocument - */ - constructor(rawDocument) { + constructor() { super('$type is not present'); - - this.rawDocument = rawDocument; - } - - /** - * Get raw Document - * - * @return {RawDocument} - */ - getRawDocument() { - return this.rawDocument; } } diff --git a/lib/errors/consensus/basic/identity/DuplicatedIdentityPublicKeyError.js b/lib/errors/consensus/basic/identity/DuplicatedIdentityPublicKeyError.js index 8a9b27b2..125946f0 100644 --- a/lib/errors/consensus/basic/identity/DuplicatedIdentityPublicKeyError.js +++ b/lib/errors/consensus/basic/identity/DuplicatedIdentityPublicKeyError.js @@ -2,21 +2,24 @@ const AbstractBasicError = require('../AbstractBasicError'); class DuplicatedIdentityPublicKeyError extends AbstractBasicError { /** - * @param {RawIdentityPublicKey[]} rawPublicKeys + * @param {number[]} duplicatedPublicKeyIds */ - constructor(rawPublicKeys) { - super('Duplicated public keys found'); + constructor(duplicatedPublicKeyIds) { + super(`Duplicated public keys ${duplicatedPublicKeyIds.join(', ')} found`); - this.rawPublicKeys = rawPublicKeys; + this.duplicatedPublicKeyIds = duplicatedPublicKeyIds; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** - * Get public keys + * Get duplicated public key ids * - * @return {RawIdentityPublicKey[]} + * @return {number[]} */ - getRawPublicKeys() { - return this.rawPublicKeys; + getDuplicatedPublicKeysIds() { + return this.duplicatedPublicKeyIds; } } diff --git a/lib/errors/consensus/basic/identity/DuplicatedIdentityPublicKeyIdError.js b/lib/errors/consensus/basic/identity/DuplicatedIdentityPublicKeyIdError.js index a1a92809..f78be27e 100644 --- a/lib/errors/consensus/basic/identity/DuplicatedIdentityPublicKeyIdError.js +++ b/lib/errors/consensus/basic/identity/DuplicatedIdentityPublicKeyIdError.js @@ -2,21 +2,24 @@ const AbstractBasicError = require('../AbstractBasicError'); class DuplicatedIdentityPublicKeyIdError extends AbstractBasicError { /** - * @param {RawIdentityPublicKey[]} rawPublicKeys + * @param {number[]} duplicatedIds */ - constructor(rawPublicKeys) { - super('Duplicated public key ids found'); + constructor(duplicatedIds) { + super(`Duplicated public key ids ${duplicatedIds.join(', ')} found`); - this.rawPublicKeys = rawPublicKeys; + this.duplicatedIds = duplicatedIds; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** - * Get public keys + * Get duplicated public key ids * - * @return {RawIdentityPublicKey[]} + * @return {number[]} */ - getRawPublicKeys() { - return this.rawPublicKeys; + getDuplicatedIds() { + return this.duplicatedIds; } } diff --git a/lib/errors/consensus/basic/identity/IdentityAssetLockProofLockedTransactionMismatchError.js b/lib/errors/consensus/basic/identity/IdentityAssetLockProofLockedTransactionMismatchError.js new file mode 100644 index 00000000..a1eca0cb --- /dev/null +++ b/lib/errors/consensus/basic/identity/IdentityAssetLockProofLockedTransactionMismatchError.js @@ -0,0 +1,33 @@ +const AbstractBasicError = require('../AbstractBasicError'); + +class IdentityAssetLockProofLockedTransactionMismatchError extends AbstractBasicError { + /** + * @param {Buffer} instantLockTransactionId + * @param {Buffer} assetLockTransactionId + */ + constructor(instantLockTransactionId, assetLockTransactionId) { + super(`Instant Lock transaction ${instantLockTransactionId.toString('hex')} and Asset lock transaction ${assetLockTransactionId.toString('hex')} mismatch`); + + this.instantLockTransactionId = instantLockTransactionId; + this.assetLockTransactionId = assetLockTransactionId; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); + } + + /** + * @return {Buffer} + */ + getInstantLockTransactionId() { + return this.instantLockTransactionId; + } + + /** + * @return {Buffer} + */ + getAssetLockTransactionId() { + return this.assetLockTransactionId; + } +} + +module.exports = IdentityAssetLockProofLockedTransactionMismatchError; diff --git a/lib/errors/consensus/basic/identity/IdentityAssetLockProofMismatchError.js b/lib/errors/consensus/basic/identity/IdentityAssetLockProofMismatchError.js deleted file mode 100644 index 4cfaa8c0..00000000 --- a/lib/errors/consensus/basic/identity/IdentityAssetLockProofMismatchError.js +++ /dev/null @@ -1,9 +0,0 @@ -const AbstractBasicError = require('../AbstractBasicError'); - -class IdentityAssetLockProofMismatchError extends AbstractBasicError { - constructor() { - super('Asset lock proof mismatch'); - } -} - -module.exports = IdentityAssetLockProofMismatchError; diff --git a/lib/errors/consensus/basic/identity/IdentityAssetLockTransactionIsNotFoundError.js b/lib/errors/consensus/basic/identity/IdentityAssetLockTransactionIsNotFoundError.js index 2d30c0d0..3b9cdfa1 100644 --- a/lib/errors/consensus/basic/identity/IdentityAssetLockTransactionIsNotFoundError.js +++ b/lib/errors/consensus/basic/identity/IdentityAssetLockTransactionIsNotFoundError.js @@ -2,21 +2,23 @@ const AbstractBasicError = require('../AbstractBasicError'); class IdentityAssetLockTransactionIsNotFoundError extends AbstractBasicError { /** - * - * @param {Buffer} outPoint + * @param {Buffer} transactionId */ - constructor(outPoint) { - super('Asset Lock transaction with specified outPoint was not found'); + constructor(transactionId) { + super(`Asset Lock transaction ${transactionId.toString('hex')} is not found`); + + this.transactionId = transactionId; - this.outPoint = outPoint; + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** * * @returns {Buffer} */ - getOutPoint() { - return this.outPoint; + getTransactionId() { + return this.transactionId; } } diff --git a/lib/errors/consensus/basic/identity/IdentityAssetLockTransactionOutPointAlreadyExistsError.js b/lib/errors/consensus/basic/identity/IdentityAssetLockTransactionOutPointAlreadyExistsError.js index b0154a65..ee5afc92 100644 --- a/lib/errors/consensus/basic/identity/IdentityAssetLockTransactionOutPointAlreadyExistsError.js +++ b/lib/errors/consensus/basic/identity/IdentityAssetLockTransactionOutPointAlreadyExistsError.js @@ -2,19 +2,31 @@ const AbstractBasicError = require('../AbstractBasicError'); class IdentityAssetLockTransactionOutPointAlreadyExistsError extends AbstractBasicError { /** - * @param {Buffer} outPoint + * @param {Buffer} transactionId + * @param {number} outputIndex */ - constructor(outPoint) { - super('Asset lock transaction outPoint already exists'); + constructor(transactionId, outputIndex) { + super(`Asset lock transaction ${transactionId.toString('hex')} output ${outputIndex} already used`); - this.outPoint = outPoint; + this.transactionId = transactionId; + this.outputIndex = outputIndex; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** * @return {Buffer} */ - getOutPoint() { - return this.outPoint; + getTransactionId() { + return this.transactionId; + } + + /** + * @return {number} + */ + getOutputIndex() { + return this.outputIndex; } } diff --git a/lib/errors/consensus/basic/identity/IdentityAssetLockTransactionOutputNotFoundError.js b/lib/errors/consensus/basic/identity/IdentityAssetLockTransactionOutputNotFoundError.js index d54086bb..0611a78d 100644 --- a/lib/errors/consensus/basic/identity/IdentityAssetLockTransactionOutputNotFoundError.js +++ b/lib/errors/consensus/basic/identity/IdentityAssetLockTransactionOutputNotFoundError.js @@ -8,6 +8,9 @@ class IdentityAssetLockTransactionOutputNotFoundError extends AbstractBasicError super(`Asset Lock Transaction Output with index ${outputIndex} not found`); this.outputIndex = outputIndex; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** diff --git a/lib/errors/consensus/basic/identity/InvalidAssetLockProofCoreChainHeightError.js b/lib/errors/consensus/basic/identity/InvalidAssetLockProofCoreChainHeightError.js index ab31da19..4a5368d6 100644 --- a/lib/errors/consensus/basic/identity/InvalidAssetLockProofCoreChainHeightError.js +++ b/lib/errors/consensus/basic/identity/InvalidAssetLockProofCoreChainHeightError.js @@ -2,7 +2,6 @@ const AbstractBasicError = require('../AbstractBasicError'); class InvalidAssetLockProofCoreChainHeightError extends AbstractBasicError { /** - * * @param {number} proofCoreChainLockedHeight * @param {number} currentCoreChainLockedHeight */ @@ -11,6 +10,9 @@ class InvalidAssetLockProofCoreChainHeightError extends AbstractBasicError { this.proofCoreChainLockedHeight = proofCoreChainLockedHeight; this.currentCoreChainLockedHeight = currentCoreChainLockedHeight; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** diff --git a/lib/errors/consensus/basic/identity/InvalidAssetLockProofTransactionHeightError.js b/lib/errors/consensus/basic/identity/InvalidAssetLockProofTransactionHeightError.js index 510fe98b..297b6d68 100644 --- a/lib/errors/consensus/basic/identity/InvalidAssetLockProofTransactionHeightError.js +++ b/lib/errors/consensus/basic/identity/InvalidAssetLockProofTransactionHeightError.js @@ -2,7 +2,6 @@ const AbstractBasicError = require('../AbstractBasicError'); class InvalidAssetLockProofTransactionHeightError extends AbstractBasicError { /** - * * @param {number} proofCoreChainLockedHeight * @param {number} transactionHeight */ @@ -11,6 +10,9 @@ class InvalidAssetLockProofTransactionHeightError extends AbstractBasicError { this.proofCoreChainLockedHeight = proofCoreChainLockedHeight; this.transactionHeight = transactionHeight; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** diff --git a/lib/errors/consensus/basic/identity/InvalidAssetLockTransactionOutputReturnSize.js b/lib/errors/consensus/basic/identity/InvalidAssetLockTransactionOutputReturnSize.js new file mode 100644 index 00000000..d08e5e9b --- /dev/null +++ b/lib/errors/consensus/basic/identity/InvalidAssetLockTransactionOutputReturnSize.js @@ -0,0 +1,26 @@ +const AbstractBasicError = require('../AbstractBasicError'); + +class InvalidAssetLockTransactionOutputReturnSize extends AbstractBasicError { + /** + * @param {number} outputIndex + */ + constructor(outputIndex) { + super(`Asset Lock output ${outputIndex} has invalid public key hash. Must be 20 length bytes hash.`); + + this.outputIndex = outputIndex; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); + } + + /** + * Get asset lock transaction output index + * + * @return {number} + */ + getOutputIndex() { + return this.outputIndex; + } +} + +module.exports = InvalidAssetLockTransactionOutputReturnSize; diff --git a/lib/errors/consensus/basic/identity/InvalidIdentityAssetLockProofError.js b/lib/errors/consensus/basic/identity/InvalidIdentityAssetLockProofError.js deleted file mode 100644 index a43e6ec2..00000000 --- a/lib/errors/consensus/basic/identity/InvalidIdentityAssetLockProofError.js +++ /dev/null @@ -1,12 +0,0 @@ -const AbstractBasicError = require('../AbstractBasicError'); - -class InvalidIdentityAssetLockProofError extends AbstractBasicError { - /** - * @param {string} message - */ - constructor(message) { - super(`Invalid asset lock proof: ${message}`); - } -} - -module.exports = InvalidIdentityAssetLockProofError; diff --git a/lib/errors/consensus/basic/identity/InvalidIdentityAssetLockProofSignatureError.js b/lib/errors/consensus/basic/identity/InvalidIdentityAssetLockProofSignatureError.js deleted file mode 100644 index c97e9629..00000000 --- a/lib/errors/consensus/basic/identity/InvalidIdentityAssetLockProofSignatureError.js +++ /dev/null @@ -1,9 +0,0 @@ -const AbstractBasicError = require('../AbstractBasicError'); - -class InvalidIdentityAssetLockProofSignatureError extends AbstractBasicError { - constructor() { - super('Invalid Asset lock proof signature'); - } -} - -module.exports = InvalidIdentityAssetLockProofSignatureError; diff --git a/lib/errors/consensus/basic/identity/InvalidIdentityAssetLockTransactionError.js b/lib/errors/consensus/basic/identity/InvalidIdentityAssetLockTransactionError.js index 7962b4a4..236dcbc6 100644 --- a/lib/errors/consensus/basic/identity/InvalidIdentityAssetLockTransactionError.js +++ b/lib/errors/consensus/basic/identity/InvalidIdentityAssetLockTransactionError.js @@ -6,6 +6,23 @@ class InvalidIdentityAssetLockTransactionError extends AbstractBasicError { */ constructor(message) { super(`Invalid asset lock transaction: ${message}`); + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); + } + + /** + * @param {Error} error + */ + setValidationError(error) { + this.validationError = error; + } + + /** + * @returns {Error} + */ + getValidationError() { + return this.validationError; } } diff --git a/lib/errors/consensus/basic/identity/InvalidIdentityAssetLockTransactionOutputError.js b/lib/errors/consensus/basic/identity/InvalidIdentityAssetLockTransactionOutputError.js index af5abc0b..88166b8d 100644 --- a/lib/errors/consensus/basic/identity/InvalidIdentityAssetLockTransactionOutputError.js +++ b/lib/errors/consensus/basic/identity/InvalidIdentityAssetLockTransactionOutputError.js @@ -2,22 +2,24 @@ const AbstractBasicError = require('../AbstractBasicError'); class InvalidIdentityAssetLockTransactionOutputError extends AbstractBasicError { /** - * @param {string} message - * @param {Object} output + * @param {number} outputIndex */ - constructor(message, output) { - super(`Invalid asset lock transaction output: ${message}`); + constructor(outputIndex) { + super(`Asset lock output ${outputIndex} is not a valid standard OP_RETURN output`); - this.output = output; + this.outputIndex = outputIndex; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** * Get lock transaction output * - * @return {Object} + * @return {number} */ - getOutput() { - return this.output; + getOutputIndex() { + return this.outputIndex; } } diff --git a/lib/errors/consensus/basic/identity/InvalidIdentityPublicKeyDataError.js b/lib/errors/consensus/basic/identity/InvalidIdentityPublicKeyDataError.js index 15edc6ac..bd558443 100644 --- a/lib/errors/consensus/basic/identity/InvalidIdentityPublicKeyDataError.js +++ b/lib/errors/consensus/basic/identity/InvalidIdentityPublicKeyDataError.js @@ -2,28 +2,35 @@ const AbstractBasicError = require('../AbstractBasicError'); class InvalidIdentityPublicKeyDataError extends AbstractBasicError { /** - * @param {RawIdentityPublicKey} publicKey - * @param {Error} validationError + * @param {number} publicKeyId + * @param {string} message */ - constructor(publicKey, validationError) { - super(`Invalid identity public key data ${publicKey.data}`); + constructor(publicKeyId, message) { + super(`Invalid identity public key ${publicKeyId} data: ${message}`); - this.publicKey = publicKey; - this.validationError = validationError; + this.publicKeyId = publicKeyId; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** - * Get identity public key + * Get identity public key ID * - * @return {RawIdentityPublicKey} + * @return {number} */ - getPublicKey() { - return this.publicKey; + getPublicKeyId() { + return this.publicKeyId; + } + + /** + * @param {Error} error + */ + setValidationError(error) { + this.validationError = error; } /** - * Get public key data validation error - * * @return {Error} */ getValidationError() { diff --git a/lib/errors/consensus/basic/identity/InvalidInstantAssetLockProofError.js b/lib/errors/consensus/basic/identity/InvalidInstantAssetLockProofError.js new file mode 100644 index 00000000..9c5bced0 --- /dev/null +++ b/lib/errors/consensus/basic/identity/InvalidInstantAssetLockProofError.js @@ -0,0 +1,29 @@ +const AbstractBasicError = require('../AbstractBasicError'); + +class InvalidInstantAssetLockProofError extends AbstractBasicError { + /** + * @param {string} message + */ + constructor(message) { + super(`Invalid instant lock proof: ${message}`); + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); + } + + /** + * @param {Error} error + */ + setValidationError(error) { + this.validationError = error; + } + + /** + * @return {Error} + */ + getValidationError() { + return this.validationError; + } +} + +module.exports = InvalidInstantAssetLockProofError; diff --git a/lib/errors/consensus/basic/identity/InvalidInstantAssetLockProofSignatureError.js b/lib/errors/consensus/basic/identity/InvalidInstantAssetLockProofSignatureError.js new file mode 100644 index 00000000..cb11509d --- /dev/null +++ b/lib/errors/consensus/basic/identity/InvalidInstantAssetLockProofSignatureError.js @@ -0,0 +1,9 @@ +const AbstractBasicError = require('../AbstractBasicError'); + +class InvalidInstantAssetLockProofSignatureError extends AbstractBasicError { + constructor() { + super('Invalid instant lock proof signature'); + } +} + +module.exports = InvalidInstantAssetLockProofSignatureError; diff --git a/lib/errors/consensus/basic/stateTransition/InvalidStateTransitionTypeError.js b/lib/errors/consensus/basic/stateTransition/InvalidStateTransitionTypeError.js index b7bbddb0..020e32ac 100644 --- a/lib/errors/consensus/basic/stateTransition/InvalidStateTransitionTypeError.js +++ b/lib/errors/consensus/basic/stateTransition/InvalidStateTransitionTypeError.js @@ -2,21 +2,24 @@ const AbstractBasicError = require('../AbstractBasicError'); class InvalidStateTransitionTypeError extends AbstractBasicError { /** - * @param {RawStateTransition} rawStateTransition + * @param {number} type */ - constructor(rawStateTransition) { - super(`Invalid State Transition type ${rawStateTransition.type}`); + constructor(type) { + super(`Invalid State Transition type ${type}`); - this.rawStateTransition = rawStateTransition; + this.type = type; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** - * Get raw State Transition + * Get state transition type * - * @return {RawStateTransition} + * @return {number} */ - getRawStateTransition() { - return this.rawStateTransition; + getType() { + return this.type; } } diff --git a/lib/errors/consensus/basic/stateTransition/MissingStateTransitionTypeError.js b/lib/errors/consensus/basic/stateTransition/MissingStateTransitionTypeError.js index 27675f80..e6d25247 100644 --- a/lib/errors/consensus/basic/stateTransition/MissingStateTransitionTypeError.js +++ b/lib/errors/consensus/basic/stateTransition/MissingStateTransitionTypeError.js @@ -1,22 +1,8 @@ const AbstractBasicError = require('../AbstractBasicError'); class MissingStateTransitionTypeError extends AbstractBasicError { - /** - * @param {RawStateTransition} rawStateTransition - */ - constructor(rawStateTransition) { - super('type is not present'); - - this.rawStateTransition = rawStateTransition; - } - - /** - * Get raw State Transition - * - * @return {RawStateTransition} - */ - getRawStateTransition() { - return this.rawStateTransition; + constructor() { + super('State Transition type is not present'); } } diff --git a/lib/errors/consensus/basic/stateTransition/StateTransitionMaxSizeExceededError.js b/lib/errors/consensus/basic/stateTransition/StateTransitionMaxSizeExceededError.js index 779a797e..3ba0c9f4 100644 --- a/lib/errors/consensus/basic/stateTransition/StateTransitionMaxSizeExceededError.js +++ b/lib/errors/consensus/basic/stateTransition/StateTransitionMaxSizeExceededError.js @@ -2,22 +2,35 @@ const AbstractBasicError = require('../AbstractBasicError'); class StateTransitionMaxSizeExceededError extends AbstractBasicError { /** - * @param {RawDataContractCreateTransition|RawDocumentsBatchTransition} rawStateTransition + * @param {number} actualSizeKBytes * @param {number} maxSizeKBytes */ - constructor(rawStateTransition, maxSizeKBytes) { - super(`State transition size is more than ${maxSizeKBytes}kb`); + constructor(actualSizeKBytes, maxSizeKBytes) { + super(`State transition size ${actualSizeKBytes} Kb is more than maximum ${maxSizeKBytes} Kb`); - this.rawStateTransition = rawStateTransition; + this.actualSizeKBytes = actualSizeKBytes; + this.maxSizeKBytes = maxSizeKBytes; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); + } + + /** + * Get actual state transition size in Kb + * + * @return {number} + */ + getActualSizeKBytes() { + return this.actualSizeKBytes; } /** - * Get raw State Transition + * Get max state transition size in Kb * - * @return {RawDataContractCreateTransition|RawDocumentsBatchTransition} + * @return {number} */ - getRawStateTransition() { - return this.rawStateTransition; + getMaxSizeKBytes() { + return this.maxSizeKBytes; } } diff --git a/lib/errors/consensus/codes.js b/lib/errors/consensus/codes.js index 7083d5e7..8dc8f5cd 100644 --- a/lib/errors/consensus/codes.js +++ b/lib/errors/consensus/codes.js @@ -13,7 +13,6 @@ const InvalidIndexPropertyTypeError = require('./basic/dataContract/InvalidIndex const SystemPropertyIndexAlreadyPresentError = require('./basic/dataContract/SystemPropertyIndexAlreadyPresentError'); const UndefinedIndexPropertyError = require('./basic/dataContract/UndefinedIndexPropertyError'); const UniqueIndicesLimitReachedError = require('./basic/dataContract/UniqueIndicesLimitReachedError'); -const DuplicateDocumentTransitionsError = require('./basic/document/DuplicateDocumentTransitionsError'); const InconsistentCompoundIndexDataError = require('./basic/document/InconsistentCompoundIndexDataError'); const InvalidDocumentTransitionActionError = require('./basic/document/InvalidDocumentTransitionActionError'); const InvalidDocumentTransitionIdError = require('./basic/document/InvalidDocumentTransitionIdError'); @@ -25,14 +24,12 @@ const MissingDocumentTransitionTypeError = require('./basic/document/MissingDocu const MissingDocumentTypeError = require('./basic/document/MissingDocumentTypeError'); const DuplicatedIdentityPublicKeyError = require('./basic/identity/DuplicatedIdentityPublicKeyError'); const DuplicatedIdentityPublicKeyIdError = require('./basic/identity/DuplicatedIdentityPublicKeyIdError'); -const IdentityAssetLockProofMismatchError = require('./basic/identity/IdentityAssetLockProofMismatchError'); +const IdentityAssetLockProofLockedTransactionMismatchError = require('./basic/identity/IdentityAssetLockProofLockedTransactionMismatchError'); const IdentityAssetLockTransactionIsNotFoundError = require('./basic/identity/IdentityAssetLockTransactionIsNotFoundError'); const IdentityAssetLockTransactionOutPointAlreadyExistsError = require('./basic/identity/IdentityAssetLockTransactionOutPointAlreadyExistsError'); const IdentityAssetLockTransactionOutputNotFoundError = require('./basic/identity/IdentityAssetLockTransactionOutputNotFoundError'); const InvalidAssetLockProofCoreChainHeightError = require('./basic/identity/InvalidAssetLockProofCoreChainHeightError'); const InvalidAssetLockProofTransactionHeightError = require('./basic/identity/InvalidAssetLockProofTransactionHeightError'); -const InvalidIdentityAssetLockProofError = require('./basic/identity/InvalidIdentityAssetLockProofError'); -const InvalidIdentityAssetLockProofSignatureError = require('./basic/identity/InvalidIdentityAssetLockProofSignatureError'); const InvalidIdentityAssetLockTransactionError = require('./basic/identity/InvalidIdentityAssetLockTransactionError'); const InvalidIdentityAssetLockTransactionOutputError = require('./basic/identity/InvalidIdentityAssetLockTransactionOutputError'); const InvalidIdentityPublicKeyDataError = require('./basic/identity/InvalidIdentityPublicKeyDataError'); @@ -56,10 +53,18 @@ const DocumentNotFoundError = require('./state/document/DocumentNotFoundError'); const DocumentOwnerIdMismatchError = require('./state/document/DocumentOwnerIdMismatchError'); const DocumentTimestampsMismatchError = require('./state/document/DocumentTimestampsMismatchError'); const DocumentTimestampWindowViolationError = require('./state/document/DocumentTimestampWindowViolationError'); -const DuplicateDocumentError = require('./state/document/DuplicateDocumentError'); +const DuplicateUniqueIndexError = require('./state/document/DuplicateUniqueIndexError'); const InvalidDocumentRevisionError = require('./state/document/InvalidDocumentRevisionError'); const IdentityAlreadyExistsError = require('./state/identity/IdentityAlreadyExistsError'); const IdentityPublicKeyAlreadyExistsError = require('./state/identity/IdentityPublicKeyAlreadyExistsError'); +const InvalidJsonSchemaRefError = require('./basic/dataContract/InvalidJsonSchemaRefError'); +const JsonSchemaCompilationError = require('./basic/JsonSchemaCompilationError'); +const DuplicateDocumentTransitionsWithIdsError = require('./basic/document/DuplicateDocumentTransitionsWithIdsError'); +const DuplicateDocumentTransitionsWithIndicesError = require('./basic/document/DuplicateDocumentTransitionsWithIndicesError'); +const InvalidAssetLockTransactionOutputReturnSize = require('./basic/identity/InvalidAssetLockTransactionOutputReturnSize'); +const InvalidInstantAssetLockProofError = require('./basic/identity/InvalidInstantAssetLockProofError'); +const InvalidInstantAssetLockProofSignatureError = require('./basic/identity/InvalidInstantAssetLockProofSignatureError'); +const IncompatibleRe2PatternError = require('./basic/dataContract/IncompatibleRe2PatternError'); const codes = { /** @@ -73,51 +78,56 @@ const codes = { 1003: SerializedObjectParsingError, // General - 1004: JsonSchemaError, - 1005: InvalidIdentifierError, + 1004: JsonSchemaCompilationError, + 1005: JsonSchemaError, + 1006: InvalidIdentifierError, // Data Contract - 1006: DataContractMaxDepthExceedError, - 1007: DuplicateIndexError, - 1008: InvalidCompoundIndexError, - 1009: InvalidDataContractIdError, - 1010: InvalidIndexedPropertyConstraintError, - 1011: InvalidIndexPropertyTypeError, - 1012: SystemPropertyIndexAlreadyPresentError, - 1013: UndefinedIndexPropertyError, - 1014: UniqueIndicesLimitReachedError, + 1007: DataContractMaxDepthExceedError, + 1008: DuplicateIndexError, + 1009: IncompatibleRe2PatternError, + 1010: InvalidCompoundIndexError, + 1011: InvalidDataContractIdError, + 1012: InvalidIndexedPropertyConstraintError, + 1013: InvalidIndexPropertyTypeError, + 1014: InvalidJsonSchemaRefError, + 1015: SystemPropertyIndexAlreadyPresentError, + 1016: UndefinedIndexPropertyError, + 1017: UniqueIndicesLimitReachedError, // Document - 1015: DataContractNotPresentError, - 1016: DuplicateDocumentTransitionsError, - 1017: InconsistentCompoundIndexDataError, - 1018: InvalidDocumentTransitionActionError, - 1019: InvalidDocumentTransitionIdError, - 1020: InvalidDocumentTypeError, - 1021: MissingDataContractIdError, - 1022: MissingDocumentTransitionActionError, - 1023: MissingDocumentTransitionTypeError, - 1024: MissingDocumentTypeError, + 1018: DataContractNotPresentError, + 1019: DuplicateDocumentTransitionsWithIdsError, + 1020: DuplicateDocumentTransitionsWithIndicesError, + 1021: InconsistentCompoundIndexDataError, + 1022: InvalidDocumentTransitionActionError, + 1023: InvalidDocumentTransitionIdError, + 1024: InvalidDocumentTypeError, + 1025: MissingDataContractIdError, + 1026: MissingDocumentTransitionActionError, + 1027: MissingDocumentTransitionTypeError, + 1028: MissingDocumentTypeError, // Identity - 1025: DuplicatedIdentityPublicKeyError, - 1026: DuplicatedIdentityPublicKeyIdError, - 1027: IdentityAssetLockProofMismatchError, - 1028: IdentityAssetLockTransactionIsNotFoundError, - 1029: IdentityAssetLockTransactionOutPointAlreadyExistsError, - 1030: IdentityAssetLockTransactionOutputNotFoundError, - 1031: InvalidAssetLockProofCoreChainHeightError, - 1032: InvalidAssetLockProofTransactionHeightError, - 1033: InvalidIdentityAssetLockProofError, - 1034: InvalidIdentityAssetLockProofSignatureError, - 1035: InvalidIdentityAssetLockTransactionError, - 1036: InvalidIdentityAssetLockTransactionOutputError, - 1037: InvalidIdentityPublicKeyDataError, + 1029: DuplicatedIdentityPublicKeyError, + 1030: DuplicatedIdentityPublicKeyIdError, + 1031: IdentityAssetLockProofLockedTransactionMismatchError, + 1032: IdentityAssetLockTransactionIsNotFoundError, + 1033: IdentityAssetLockTransactionOutPointAlreadyExistsError, + 1034: IdentityAssetLockTransactionOutputNotFoundError, + 1035: InvalidAssetLockProofCoreChainHeightError, + 1036: InvalidAssetLockProofTransactionHeightError, + 1037: InvalidAssetLockTransactionOutputReturnSize, + 1038: InvalidIdentityAssetLockTransactionError, + 1039: InvalidIdentityAssetLockTransactionOutputError, + 1040: InvalidIdentityPublicKeyDataError, + 1041: InvalidInstantAssetLockProofError, + 1042: InvalidInstantAssetLockProofSignatureError, // State Transition - 1038: InvalidStateTransitionTypeError, - 1039: MissingStateTransitionTypeError, - 1040: StateTransitionMaxSizeExceededError, + 1043: InvalidStateTransitionTypeError, + 1044: MissingStateTransitionTypeError, + 1045: StateTransitionMaxSizeExceededError, /** * Signature @@ -150,7 +160,7 @@ const codes = { 4006: DocumentOwnerIdMismatchError, 4007: DocumentTimestampsMismatchError, 4008: DocumentTimestampWindowViolationError, - 4009: DuplicateDocumentError, + 4009: DuplicateUniqueIndexError, 4010: InvalidDocumentRevisionError, // Identity diff --git a/lib/errors/consensus/createConsensusError.js b/lib/errors/consensus/createConsensusError.js new file mode 100644 index 00000000..17e5f169 --- /dev/null +++ b/lib/errors/consensus/createConsensusError.js @@ -0,0 +1,17 @@ +const codes = require('./codes'); + +/** + * + * @param {number} code + * @param {*[]} args + * @returns {*} + */ +function createConsensusError(code, args) { + if (!codes[code]) { + throw new Error(`Consensus error with code ${code} is not defined. Probably you need to update DPP`); + } + + return new codes[code](...args); +} + +module.exports = createConsensusError; diff --git a/lib/errors/consensus/fee/AbstractFeeError.js b/lib/errors/consensus/fee/AbstractFeeError.js index e9873582..bf74fd1e 100644 --- a/lib/errors/consensus/fee/AbstractFeeError.js +++ b/lib/errors/consensus/fee/AbstractFeeError.js @@ -1,9 +1,9 @@ -const ConsensusError = require('../ConsensusError'); +const AbstractConsensusError = require('../AbstractConsensusError'); /** * @abstract */ -class AbstractFeeError extends ConsensusError { +class AbstractFeeError extends AbstractConsensusError { } diff --git a/lib/errors/consensus/fee/BalanceIsNotEnoughError.js b/lib/errors/consensus/fee/BalanceIsNotEnoughError.js index 992b801f..817aab07 100644 --- a/lib/errors/consensus/fee/BalanceIsNotEnoughError.js +++ b/lib/errors/consensus/fee/BalanceIsNotEnoughError.js @@ -2,17 +2,29 @@ const AbstractFeeError = require('./AbstractFeeError'); class BalanceIsNotEnoughError extends AbstractFeeError { /** - * * @param {number} balance + * @param {number} fee */ - constructor(balance) { - super('Balance is not enough'); + constructor(balance, fee) { + super(`Current credits balance ${balance} is not enough to pay ${fee} fee`); this.balance = balance; + this.fee = fee; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); + } + + /** + * @return {number} + */ + getFee() { + return this.fee; } /** - * Get Identity balance + * Get current balance + * * @return {number} */ getBalance() { diff --git a/lib/errors/consensus/signature/AbstractSignatureError.js b/lib/errors/consensus/signature/AbstractSignatureError.js index 182dbc73..0e179a27 100644 --- a/lib/errors/consensus/signature/AbstractSignatureError.js +++ b/lib/errors/consensus/signature/AbstractSignatureError.js @@ -1,9 +1,9 @@ -const ConsensusError = require('../ConsensusError'); +const AbstractConsensusError = require('../AbstractConsensusError'); /** * @abstract */ -class AbstractSignatureError extends ConsensusError { +class AbstractSignatureError extends AbstractConsensusError { } diff --git a/lib/errors/consensus/signature/IdentityNotFoundError.js b/lib/errors/consensus/signature/IdentityNotFoundError.js index c3528a6c..e7b5d7da 100644 --- a/lib/errors/consensus/signature/IdentityNotFoundError.js +++ b/lib/errors/consensus/signature/IdentityNotFoundError.js @@ -1,13 +1,17 @@ const AbstractSignatureError = require('./AbstractSignatureError'); +const Identifier = require('../../../identifier/Identifier'); class IdentityNotFoundError extends AbstractSignatureError { /** * @param {Buffer} identityId */ constructor(identityId) { - super('Identity not found'); + super(`Identity ${Identifier.from(identityId)} not found`); this.identityId = identityId; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** diff --git a/lib/errors/consensus/signature/InvalidIdentityPublicKeyTypeError.js b/lib/errors/consensus/signature/InvalidIdentityPublicKeyTypeError.js index e1e1da82..ab70e5f6 100644 --- a/lib/errors/consensus/signature/InvalidIdentityPublicKeyTypeError.js +++ b/lib/errors/consensus/signature/InvalidIdentityPublicKeyTypeError.js @@ -8,6 +8,9 @@ class InvalidIdentityPublicKeyTypeError extends AbstractSignatureError { super(`Invalid identity public key type ${type}`); this.type = type; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** diff --git a/lib/errors/consensus/signature/InvalidStateTransitionSignatureError.js b/lib/errors/consensus/signature/InvalidStateTransitionSignatureError.js index fcfaea47..daf1c8d9 100644 --- a/lib/errors/consensus/signature/InvalidStateTransitionSignatureError.js +++ b/lib/errors/consensus/signature/InvalidStateTransitionSignatureError.js @@ -1,22 +1,8 @@ const AbstractSignatureError = require('./AbstractSignatureError'); class InvalidStateTransitionSignatureError extends AbstractSignatureError { - /** - * @param {AbstractStateTransition} stateTransition - */ - constructor(stateTransition) { - super(`Invalid State Transition signature ${stateTransition.getSignature()}`); - - this.stateTransition = stateTransition; - } - - /** - * Get State Transition - * - * @return {AbstractStateTransition} - */ - getRawStateTransition() { - return this.stateTransition; + constructor() { + super('Invalid State Transition signature'); } } diff --git a/lib/errors/consensus/signature/MissingPublicKeyError.js b/lib/errors/consensus/signature/MissingPublicKeyError.js index fa1a4e1c..d2adf105 100644 --- a/lib/errors/consensus/signature/MissingPublicKeyError.js +++ b/lib/errors/consensus/signature/MissingPublicKeyError.js @@ -5,9 +5,12 @@ class MissingPublicKeyError extends AbstractSignatureError { * @param {number} publicKeyId */ constructor(publicKeyId) { - super("Public key with such id doesn't exist"); + super(`Public key ${publicKeyId} doesn't exist`); this.publicKeyId = publicKeyId; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** diff --git a/lib/errors/consensus/state/AbstractStateError.js b/lib/errors/consensus/state/AbstractStateError.js index b78d5093..31685bc8 100644 --- a/lib/errors/consensus/state/AbstractStateError.js +++ b/lib/errors/consensus/state/AbstractStateError.js @@ -1,6 +1,6 @@ -const ConsensusError = require('../ConsensusError'); +const AbstractConsensusError = require('../AbstractConsensusError'); -class AbstractStateError extends ConsensusError { +class AbstractStateError extends AbstractConsensusError { } diff --git a/lib/errors/consensus/state/dataContract/DataContractAlreadyPresentError.js b/lib/errors/consensus/state/dataContract/DataContractAlreadyPresentError.js index 737e9cc4..625f529d 100644 --- a/lib/errors/consensus/state/dataContract/DataContractAlreadyPresentError.js +++ b/lib/errors/consensus/state/dataContract/DataContractAlreadyPresentError.js @@ -1,22 +1,26 @@ const AbstractStateError = require('../AbstractStateError'); +const Identifier = require('../../../../identifier/Identifier'); class DataContractAlreadyPresentError extends AbstractStateError { /** - * @param {DataContract} dataContract + * @param {Buffer} dataContractId */ - constructor(dataContract) { - super('Data Contract is already present'); + constructor(dataContractId) { + super(`Data Contract ${Identifier.from(dataContractId)} is already present`); - this.dataContract = dataContract; + this.dataContractId = dataContractId; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** - * Get Data Contract + * Get Data Contract ID * - * @return {DataContract} + * @return {Buffer} */ - getDataContract() { - return this.dataContract; + getDataContractId() { + return this.dataContractId; } } diff --git a/lib/errors/consensus/state/dataContract/dataTrigger/AbstractDataTriggerError.js b/lib/errors/consensus/state/dataContract/dataTrigger/AbstractDataTriggerError.js index 8d7a95ac..b5e77aca 100644 --- a/lib/errors/consensus/state/dataContract/dataTrigger/AbstractDataTriggerError.js +++ b/lib/errors/consensus/state/dataContract/dataTrigger/AbstractDataTriggerError.js @@ -5,24 +5,36 @@ const AbstractStateError = require('../../AbstractStateError'); */ class AbstractDataTriggerError extends AbstractStateError { /** + * @param {Buffer} dataContractId + * @param {Buffer} documentTransitionId * @param {string} message - * @param {DataContract} dataContract - * @param {Identifier|Buffer} ownerId */ - constructor(message, dataContract, ownerId) { + constructor(dataContractId, documentTransitionId, message) { super(message); - this.dataContract = dataContract; - this.ownerId = ownerId; + this.dataContractId = dataContractId; + this.documentTransitionId = documentTransitionId; } /** - * Get data trigger data contract - * - * @return {DataContract} + * @returns {Buffer} + */ + getDocumentTransitionId() { + return this.documentTransitionId; + } + + /** + * @returns {Buffer} + */ + getDataContractId() { + return this.dataContractId; + } + + /** + * @param {Identifier} ownerId */ - getDataContract() { - return this.dataContract; + setOwnerId(ownerId) { + this.ownerId = ownerId; } /** @@ -33,6 +45,26 @@ class AbstractDataTriggerError extends AbstractStateError { getOwnerId() { return this.ownerId; } + + /** + * @param { + * DocumentCreateTransition|DocumentReplaceTransition|DocumentDeleteTransition + * } documentTransition + */ + setDocumentTransition(documentTransition) { + this.documentTransition = documentTransition; + } + + /** + * Get document transition + * + * @returns { + * DocumentCreateTransition|DocumentReplaceTransition|DocumentDeleteTransition + * } + */ + getDocumentTransition() { + return this.documentTransition; + } } module.exports = AbstractDataTriggerError; diff --git a/lib/errors/consensus/state/dataContract/dataTrigger/DataTriggerConditionError.js b/lib/errors/consensus/state/dataContract/dataTrigger/DataTriggerConditionError.js index 180f2ad8..d1473ef9 100644 --- a/lib/errors/consensus/state/dataContract/dataTrigger/DataTriggerConditionError.js +++ b/lib/errors/consensus/state/dataContract/dataTrigger/DataTriggerConditionError.js @@ -2,28 +2,15 @@ const AbstractDataTriggerError = require('./AbstractDataTriggerError'); class DataTriggerConditionError extends AbstractDataTriggerError { /** - * @param { - * DocumentCreateTransition|DocumentReplaceTransition|DocumentDeleteTransition - * } documentTransition - * @param {DataContract} dataContract - * @param {Identifier|Buffer} ownerId + * @param {Buffer} dataContractId + * @param {Buffer} documentTransitionId * @param {string} message */ - constructor(documentTransition, dataContract, ownerId, message) { - super(message, dataContract, ownerId); + constructor(dataContractId, documentTransitionId, message) { + super(dataContractId, documentTransitionId, message); - this.documentTransition = documentTransition; - } - - /** - * Get document transition - * - * @returns { - * DocumentCreateTransition|DocumentReplaceTransition|DocumentDeleteTransition - * } - */ - getDocumentTransition() { - return this.documentTransition; + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } } diff --git a/lib/errors/consensus/state/dataContract/dataTrigger/DataTriggerExecutionError.js b/lib/errors/consensus/state/dataContract/dataTrigger/DataTriggerExecutionError.js index 586f33c3..1704bf96 100644 --- a/lib/errors/consensus/state/dataContract/dataTrigger/DataTriggerExecutionError.js +++ b/lib/errors/consensus/state/dataContract/dataTrigger/DataTriggerExecutionError.js @@ -2,34 +2,33 @@ const AbstractDataTriggerError = require('./AbstractDataTriggerError'); class DataTriggerExecutionError extends AbstractDataTriggerError { /** - * @param {DataTrigger} dataTrigger - * @param {DataContract} dataContract - * @param {Identifier|Buffer} ownerId - * @param {Error} error + * @param {Buffer} dataContractId + * @param {Buffer} documentTransitionId + * @param {string} message */ - constructor(dataTrigger, dataContract, ownerId, error) { - super(error.message, dataContract, ownerId); + constructor(dataContractId, documentTransitionId, message) { + super(dataContractId, documentTransitionId, message); - this.error = error; - this.dataTrigger = dataTrigger; + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** - * Return internal error instance + * Set internal error * - * @return {Error} + * @param {Error} error */ - getError() { - return this.error; + setExecutionError(error) { + this.executionError = error; } /** - * Get data trigger + * Return internal error * - * @return {DataTrigger} + * @return {Error} */ - getDataTrigger() { - return this.dataTrigger; + getExecutionError() { + return this.executionError; } } diff --git a/lib/errors/consensus/state/dataContract/dataTrigger/DataTriggerInvalidResultError.js b/lib/errors/consensus/state/dataContract/dataTrigger/DataTriggerInvalidResultError.js index aae2e00d..35bb9a37 100644 --- a/lib/errors/consensus/state/dataContract/dataTrigger/DataTriggerInvalidResultError.js +++ b/lib/errors/consensus/state/dataContract/dataTrigger/DataTriggerInvalidResultError.js @@ -2,23 +2,14 @@ const AbstractDataTriggerError = require('./AbstractDataTriggerError'); class DataTriggerInvalidResultError extends AbstractDataTriggerError { /** - * @param {DataTrigger} dataTrigger - * @param {DataContract} dataContract - * @param {Identifier|Buffer} ownerId + * @param {Buffer} dataContractId + * @param {Buffer} documentTransitionId */ - constructor(dataTrigger, dataContract, ownerId) { - super('Data trigger have not returned any result', dataContract, ownerId); + constructor(dataContractId, documentTransitionId) { + super(dataContractId, documentTransitionId, 'Data trigger have not returned any result'); - this.dataTrigger = dataTrigger; - } - - /** - * Get data trigger - * - * @returns {DataTrigger} - */ - getDataTrigger() { - return this.dataTrigger; + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } } diff --git a/lib/errors/consensus/state/document/DocumentAlreadyPresentError.js b/lib/errors/consensus/state/document/DocumentAlreadyPresentError.js index 4e2164bd..33f9045a 100644 --- a/lib/errors/consensus/state/document/DocumentAlreadyPresentError.js +++ b/lib/errors/consensus/state/document/DocumentAlreadyPresentError.js @@ -1,33 +1,26 @@ const AbstractStateError = require('../AbstractStateError'); +const Identifier = require('../../../../identifier/Identifier'); class DocumentAlreadyPresentError extends AbstractStateError { /** - * @param {DocumentCreateTransition} documentTransition - * @param {Document} fetchedDocument + * @param {Buffer} documentId */ - constructor(documentTransition, fetchedDocument) { - super('Document with the same ID is already present'); + constructor(documentId) { + super(`Document ${Identifier.from(documentId)} is already present`); - this.documentTransition = documentTransition; - this.fetchedDocument = fetchedDocument; - } + this.documentId = documentId; - /** - * Get document create transition - * - * @return {DocumentCreateTransition} - */ - getDocumentTransition() { - return this.documentTransition; + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** - * Get fetched Document + * Get document ID * - * @return {Document} + * @return {Buffer} */ - getFetchedDocument() { - return this.fetchedDocument; + getDocumentId() { + return this.documentId; } } diff --git a/lib/errors/consensus/state/document/DocumentNotFoundError.js b/lib/errors/consensus/state/document/DocumentNotFoundError.js index f71f9741..c0981560 100644 --- a/lib/errors/consensus/state/document/DocumentNotFoundError.js +++ b/lib/errors/consensus/state/document/DocumentNotFoundError.js @@ -4,27 +4,29 @@ const AbstractDocumentTransition = require('../../../../document/stateTransition class DocumentNotFoundError extends AbstractStateError { /** - * @param {DocumentReplaceTransition - * |DocumentDeleteTransition} documentTransition + * @param {Buffer} documentId */ - constructor(documentTransition) { + constructor(documentId) { const noun = { [AbstractDocumentTransition.ACTIONS.REPLACE]: 'Updated', [AbstractDocumentTransition.ACTIONS.DELETE]: 'Deleted', }; - super(`${noun[documentTransition.getAction()]} Document not found`); + super(`${noun[documentId]} document not found`); - this.documentTransition = documentTransition; + this.documentId = documentId; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** - * Get Document Transition + * Get Document ID * - * @return {DocumentReplaceTransition|DocumentDeleteTransition} + * @return {Buffer} */ - getDocumentTransition() { - return this.documentTransition; + getDocumentId() { + return this.documentId; } } diff --git a/lib/errors/consensus/state/document/DocumentOwnerIdMismatchError.js b/lib/errors/consensus/state/document/DocumentOwnerIdMismatchError.js index 14dfe5c2..fcd1ebeb 100644 --- a/lib/errors/consensus/state/document/DocumentOwnerIdMismatchError.js +++ b/lib/errors/consensus/state/document/DocumentOwnerIdMismatchError.js @@ -1,34 +1,48 @@ const AbstractStateError = require('../AbstractStateError'); +const Identifier = require('../../../../identifier/Identifier'); class DocumentOwnerIdMismatchError extends AbstractStateError { /** - * @param {DocumentReplaceTransition - * |DocumentDeleteTransition} documentTransition - * @param {Document} fetchedDocument + * @param {Buffer} documentId + * @param {Buffer} documentOwnerId + * @param {Buffer} existingDocumentOwnerId */ - constructor(documentTransition, fetchedDocument) { - super('Document owner id mismatch with previous versions'); + constructor(documentId, documentOwnerId, existingDocumentOwnerId) { + super(`Provided document ${Identifier.from(documentId)} owner ID ${Identifier.from(documentOwnerId)} mismatch with existing ${Identifier.from(existingDocumentOwnerId)}`); - this.documentTransition = documentTransition; - this.fetchedDocument = fetchedDocument; + this.documentId = documentId; + this.documentOwnerId = documentOwnerId; + this.existingDocumentOwnerId = existingDocumentOwnerId; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); + } + + /** + * Get document ID + * + * @returns {Buffer} + */ + getDocumentId() { + return this.documentId; } /** - * Get Document Action Transition + * Get document owner ID * - * @return {DocumentReplaceTransition|DocumentDeleteTransition} + * @return {Buffer} */ - getDocumentTransition() { - return this.documentTransition; + getDocumentOwnerId() { + return this.documentOwnerId; } /** - * Get fetched Document + * Get existing Document owner ID * - * @return {Document} + * @return {Buffer} */ - getFetchedDocument() { - return this.fetchedDocument; + getExistingDocumentOwnerId() { + return this.existingDocumentOwnerId; } } diff --git a/lib/errors/consensus/state/document/DocumentTimestampWindowViolationError.js b/lib/errors/consensus/state/document/DocumentTimestampWindowViolationError.js index abeb8cf2..0973acc7 100644 --- a/lib/errors/consensus/state/document/DocumentTimestampWindowViolationError.js +++ b/lib/errors/consensus/state/document/DocumentTimestampWindowViolationError.js @@ -1,18 +1,25 @@ const AbstractStateError = require('../AbstractStateError'); +const Identifier = require('../../../../identifier/Identifier'); class DocumentTimestampWindowViolationError extends AbstractStateError { /** * @param {string} timestampName - * @param {DocumentCreateTransition - * |DocumentReplaceTransition} documentTransition - * @param {Document} fetchedDocument + * @param {Buffer} documentId + * @param {Date} timestamp + * @param {Date} timeWindowStart + * @param {Date} timeWindowEnd */ - constructor(timestampName, documentTransition, fetchedDocument) { - super(`Document ${timestampName} timestamp are out of block time window`); + constructor(timestampName, documentId, timestamp, timeWindowStart, timeWindowEnd) { + super(`Document ${Identifier.from(documentId)} ${timestampName} timestamp (${timestamp}) are out of block time window from ${timeWindowStart} and ${timeWindowEnd}`); - this.documentTransition = documentTransition; - this.fetchedDocument = fetchedDocument; this.timestampName = timestampName; + this.documentId = documentId; + this.timestamp = timestamp; + this.timeWindowStart = timeWindowStart; + this.timeWindowEnd = timeWindowEnd; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** @@ -25,21 +32,35 @@ class DocumentTimestampWindowViolationError extends AbstractStateError { } /** - * Get Document Action Transition + * Get Document ID * - * @return {DocumentReplaceTransition|DocumentDeleteTransition} + * @return {Buffer} */ - getDocumentTransition() { - return this.documentTransition; + getDocumentId() { + return this.documentId; } /** - * Get fetched Document + * Get timestamp * - * @return {Document} + * @return {Date} + */ + getTimestamp() { + return this.timestamp; + } + + /** + * @returns {Date} + */ + getTimeWindowStart() { + return this.timeWindowStart; + } + + /** + * @returns {Date} */ - getFetchedDocument() { - return this.fetchedDocument; + getTimeWindowEnd() { + return this.timeWindowEnd; } } diff --git a/lib/errors/consensus/state/document/DocumentTimestampsMismatchError.js b/lib/errors/consensus/state/document/DocumentTimestampsMismatchError.js index bf14f39e..9e80abf4 100644 --- a/lib/errors/consensus/state/document/DocumentTimestampsMismatchError.js +++ b/lib/errors/consensus/state/document/DocumentTimestampsMismatchError.js @@ -1,22 +1,26 @@ const AbstractStateError = require('../AbstractStateError'); +const Identifier = require('../../../../identifier/Identifier'); class DocumentTimestampsMismatchError extends AbstractStateError { /** - * @param {DocumentCreateTransition} documentTransition + * @param {Buffer} documentId */ - constructor(documentTransition) { - super('Document createdAt and updatedAt timestamps are not equal'); + constructor(documentId) { + super(`Document ${Identifier.from(documentId)} createdAt and updatedAt timestamps are not equal`); - this.documentTransition = documentTransition; + this.documentId = documentId; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** * Get document create transition * - * @return {DocumentCreateTransition} + * @return {Buffer} */ - getDocumentTransition() { - return this.documentTransition; + getDocumentId() { + return this.documentId; } } diff --git a/lib/errors/consensus/state/document/DuplicateDocumentError.js b/lib/errors/consensus/state/document/DuplicateDocumentError.js deleted file mode 100644 index 1788639f..00000000 --- a/lib/errors/consensus/state/document/DuplicateDocumentError.js +++ /dev/null @@ -1,34 +0,0 @@ -const AbstractStateError = require('../AbstractStateError'); - -class DuplicateDocumentError extends AbstractStateError { - /** - * @param {DocumentCreateTransition|DocumentReplaceTransition} documentTransition - * @param {Object} indexDefinition - */ - constructor(documentTransition, indexDefinition) { - super('Duplicate Document found'); - - this.documentTransition = documentTransition; - this.indexDefinition = indexDefinition; - } - - /** - * Get document action transition - * - * @return {DocumentCreateTransition|DocumentReplaceTransition} - */ - getDocumentTransition() { - return this.documentTransition; - } - - /** - * Get index definition - * - * @return {Object} - */ - getIndexDefinition() { - return this.indexDefinition; - } -} - -module.exports = DuplicateDocumentError; diff --git a/lib/errors/consensus/state/document/DuplicateUniqueIndexError.js b/lib/errors/consensus/state/document/DuplicateUniqueIndexError.js new file mode 100644 index 00000000..3900887c --- /dev/null +++ b/lib/errors/consensus/state/document/DuplicateUniqueIndexError.js @@ -0,0 +1,38 @@ +const AbstractStateError = require('../AbstractStateError'); +const Identifier = require('../../../../identifier/Identifier'); + +class DuplicateUniqueIndexError extends AbstractStateError { + /** + * @param {Buffer} documentId + * @param {string[]} duplicatingProperties + */ + constructor(documentId, duplicatingProperties) { + super(`Document ${Identifier.from(documentId)} has duplicate unique properties ${duplicatingProperties.join(', ')} with other documents`); + + this.documentId = documentId; + this.duplicatingProperties = duplicatingProperties; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); + } + + /** + * Get document id + * + * @return {Buffer} + */ + getDocumentId() { + return this.documentId; + } + + /** + * Get duplicating properties + * + * @return {string[]} + */ + getDuplicatingProperties() { + return this.duplicatingProperties; + } +} + +module.exports = DuplicateUniqueIndexError; diff --git a/lib/errors/consensus/state/document/InvalidDocumentRevisionError.js b/lib/errors/consensus/state/document/InvalidDocumentRevisionError.js index 33401d98..b59999b2 100644 --- a/lib/errors/consensus/state/document/InvalidDocumentRevisionError.js +++ b/lib/errors/consensus/state/document/InvalidDocumentRevisionError.js @@ -1,33 +1,37 @@ const AbstractStateError = require('../AbstractStateError'); +const Identifier = require('../../../../identifier/Identifier'); class InvalidDocumentRevisionError extends AbstractStateError { /** - * @param {DocumentReplaceTransition} documentTransition - * @param {Document} fetchedDocument + * @param {Buffer} documentId + * @param {number} currentRevision */ - constructor(documentTransition, fetchedDocument) { - super('Invalid Document revision'); + constructor(documentId, currentRevision) { + super(`Document ${Identifier.from(documentId)} has invalid revision. The current revision is ${currentRevision}`); - this.documentTransition = documentTransition; - this.fetchedDocument = fetchedDocument; + this.documentId = documentId; + this.currentRevision = currentRevision; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** - * Get Document replace transition + * Get Document ID * - * @return {DocumentReplaceTransition} + * @return {Buffer} */ - getDocumentTransition() { - return this.documentTransition; + getDocumentId() { + return this.documentId; } /** - * Get fetched Document + * Get current revision * - * @return {Document} + * @return {number} */ - getFetchedDocument() { - return this.fetchedDocument; + getCurrentRevision() { + return this.currentRevision; } } diff --git a/lib/errors/consensus/state/identity/IdentityAlreadyExistsError.js b/lib/errors/consensus/state/identity/IdentityAlreadyExistsError.js index 01d5f1c7..de45c767 100644 --- a/lib/errors/consensus/state/identity/IdentityAlreadyExistsError.js +++ b/lib/errors/consensus/state/identity/IdentityAlreadyExistsError.js @@ -1,22 +1,26 @@ const AbstractStateError = require('../AbstractStateError'); +const Identifier = require('../../../../identifier/Identifier'); class IdentityAlreadyExistsError extends AbstractStateError { /** - * @param {IdentityCreateTransition} stateTransition + * @param {Buffer} identityId */ - constructor(stateTransition) { - super(`Identity with id ${stateTransition.getIdentityId()} already exists`); + constructor(identityId) { + super(`Identity ${Identifier.from(identityId)} already exists`); - this.stateTransition = stateTransition; + this.identityId = identityId; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** - * Get state transition + * Get identity id * - * @return {IdentityCreateTransition} + * @return {Buffer} */ - getStateTransition() { - return this.stateTransition; + getIdentityId() { + return this.identityId; } } diff --git a/lib/errors/consensus/state/identity/IdentityPublicKeyAlreadyExistsError.js b/lib/errors/consensus/state/identity/IdentityPublicKeyAlreadyExistsError.js index 699ecc80..6c758f1b 100644 --- a/lib/errors/consensus/state/identity/IdentityPublicKeyAlreadyExistsError.js +++ b/lib/errors/consensus/state/identity/IdentityPublicKeyAlreadyExistsError.js @@ -2,18 +2,21 @@ const AbstractStateError = require('../AbstractStateError'); class IdentityPublicKeyAlreadyExistsError extends AbstractStateError { /** - * @param {string} publicKeyHash + * @param {Buffer} publicKeyHash */ constructor(publicKeyHash) { - super('Identity public key already exists'); + super(`Identity public key ${publicKeyHash.toString('hex')} already exists`); this.publicKeyHash = publicKeyHash; + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); } /** * Get public key hash * - * @return {string} + * @return {Buffer} */ getPublicKeyHash() { return this.publicKeyHash; diff --git a/lib/identifier/createAndValidateIdentifier.js b/lib/identifier/createAndValidateIdentifier.js index 7e37ca74..bff9f56d 100644 --- a/lib/identifier/createAndValidateIdentifier.js +++ b/lib/identifier/createAndValidateIdentifier.js @@ -13,9 +13,11 @@ function createAndValidateIdentifier(name, buffer, result) { return new Identifier(buffer); } catch (e) { if (e instanceof IdentifierError) { - result.addError( - new InvalidIdentifierError(name, e), - ); + const consensusError = new InvalidIdentifierError(name, e.message); + + consensusError.setIdentifierError(e); + + result.addError(consensusError); return undefined; } diff --git a/lib/identity/IdentityFactory.js b/lib/identity/IdentityFactory.js index e4bada26..99381881 100644 --- a/lib/identity/IdentityFactory.js +++ b/lib/identity/IdentityFactory.js @@ -7,7 +7,7 @@ const IdentityTopUpTransition = require('./stateTransition/IdentityTopUpTransiti const InvalidIdentityError = require('./errors/InvalidIdentityError'); const InstantAssetLockProof = require('./stateTransition/assetLockProof/instant/InstantAssetLockProof'); const ChainAssetLockProof = require('./stateTransition/assetLockProof/chain/ChainAssetLockProof'); -const ConsensusError = require('../errors/consensus/ConsensusError'); +const AbstractConsensusError = require('../errors/consensus/AbstractConsensusError'); class IdentityFactory { /** @@ -92,7 +92,7 @@ class IdentityFactory { rawIdentity.protocolVersion = protocolVersion; } catch (error) { - if (error instanceof ConsensusError) { + if (error instanceof AbstractConsensusError) { throw new InvalidIdentityError([error]); } diff --git a/lib/identity/errors/AssetLockTransactionIsNotFoundError.js b/lib/identity/errors/AssetLockTransactionIsNotFoundError.js new file mode 100644 index 00000000..8eefd16d --- /dev/null +++ b/lib/identity/errors/AssetLockTransactionIsNotFoundError.js @@ -0,0 +1,22 @@ +const DPPError = require('../../errors/DPPError'); + +class AssetLockTransactionIsNotFoundError extends DPPError { + /** + * @param {string} transactionId + */ + constructor(transactionId) { + super(`Asset Lock transaction ${transactionId} is not found`); + + this.transactionId = transactionId; + } + + /** + * + * @returns {string} + */ + getTransactionId() { + return this.transactionId; + } +} + +module.exports = AssetLockTransactionIsNotFoundError; diff --git a/lib/identity/errors/InvalidIdentityError.js b/lib/identity/errors/InvalidIdentityError.js index a2683a68..ec8bfb83 100644 --- a/lib/identity/errors/InvalidIdentityError.js +++ b/lib/identity/errors/InvalidIdentityError.js @@ -2,7 +2,7 @@ const DPPError = require('../../errors/DPPError'); class InvalidIdentityError extends DPPError { /** - * @param {ConsensusError[]} errors + * @param {AbstractConsensusError[]} errors * @param {RawIdentity} rawIdentity */ constructor(errors, rawIdentity) { @@ -20,7 +20,7 @@ class InvalidIdentityError extends DPPError { /** * Get validation errors * - * @return {ConsensusError[]} + * @return {AbstractConsensusError[]} */ getErrors() { return this.errors; diff --git a/lib/identity/stateTransition/IdentityCreateTransition/validation/state/validateIdentityCreateTransitionStateFactory.js b/lib/identity/stateTransition/IdentityCreateTransition/validation/state/validateIdentityCreateTransitionStateFactory.js index f7eb13de..52baf127 100644 --- a/lib/identity/stateTransition/IdentityCreateTransition/validation/state/validateIdentityCreateTransitionStateFactory.js +++ b/lib/identity/stateTransition/IdentityCreateTransition/validation/state/validateIdentityCreateTransitionStateFactory.js @@ -33,7 +33,9 @@ function validateIdentityCreateTransitionStateFactory( const identity = await stateRepository.fetchIdentity(identityId); if (identity) { - result.addError(new IdentityAlreadyExistsError(stateTransition)); + result.addError( + new IdentityAlreadyExistsError(identityId.toBuffer()), + ); } if (!result.isValid()) { diff --git a/lib/identity/stateTransition/IdentityCreateTransition/validation/state/validateIdentityPublicKeysUniquenessFactory.js b/lib/identity/stateTransition/IdentityCreateTransition/validation/state/validateIdentityPublicKeysUniquenessFactory.js index 2cf979c3..7d8acdc4 100644 --- a/lib/identity/stateTransition/IdentityCreateTransition/validation/state/validateIdentityPublicKeysUniquenessFactory.js +++ b/lib/identity/stateTransition/IdentityCreateTransition/validation/state/validateIdentityPublicKeysUniquenessFactory.js @@ -34,7 +34,9 @@ function validateIdentityPublicKeysUniquenessFactory(stateRepository) { .forEach((publicKeyHash, index) => { if (identityIds[index]) { validationResult.addError( - new IdentityPublicKeyAlreadyExistsError(publicKeyHash), + new IdentityPublicKeyAlreadyExistsError( + publicKeyHash, + ), ); } }); diff --git a/lib/identity/stateTransition/assetLockProof/chain/validateChainAssetLockProofStructureFactory.js b/lib/identity/stateTransition/assetLockProof/chain/validateChainAssetLockProofStructureFactory.js index 57df5b1c..a37799da 100644 --- a/lib/identity/stateTransition/assetLockProof/chain/validateChainAssetLockProofStructureFactory.js +++ b/lib/identity/stateTransition/assetLockProof/chain/validateChainAssetLockProofStructureFactory.js @@ -60,7 +60,11 @@ function validateChainAssetLockProofStructureFactory( const rawTransaction = await stateRepository.fetchTransaction(transactionHash); if (rawTransaction === null) { - result.addError(new IdentityAssetLockTransactionIsNotFoundError(outPointBuffer)); + result.addError( + new IdentityAssetLockTransactionIsNotFoundError( + Buffer.from(transactionHash, 'hex'), + ), + ); return result; } diff --git a/lib/identity/stateTransition/assetLockProof/fetchAssetLockTransactionOutputFactory.js b/lib/identity/stateTransition/assetLockProof/fetchAssetLockTransactionOutputFactory.js index bc41513b..a8263556 100644 --- a/lib/identity/stateTransition/assetLockProof/fetchAssetLockTransactionOutputFactory.js +++ b/lib/identity/stateTransition/assetLockProof/fetchAssetLockTransactionOutputFactory.js @@ -1,8 +1,8 @@ const { Transaction } = require('@dashevo/dashcore-lib'); const InstantAssetLockProof = require('./instant/InstantAssetLockProof'); const ChainAssetLockProof = require('./chain/ChainAssetLockProof'); -const IdentityAssetLockTransactionIsNotFoundError = require('../../../errors/consensus/basic/identity/IdentityAssetLockTransactionIsNotFoundError'); -const UnknownAssetLockProofError = require('../../errors/UnknownAssetLockProofTypeError'); +const AssetLockTransactionIsNotFoundError = require('../../errors/AssetLockTransactionIsNotFoundError'); +const UnknownAssetLockProofTypeError = require('../../errors/UnknownAssetLockProofTypeError'); /** * @param {StateRepository} stateRepository @@ -29,14 +29,14 @@ function fetchAssetLockTransactionOutputFactory( const { outputIndex, transactionHash } = outPoint; const rawTransaction = await stateRepository.fetchTransaction(transactionHash); if (rawTransaction === null) { - throw new IdentityAssetLockTransactionIsNotFoundError(assetLockProof.getOutPoint()); + throw new AssetLockTransactionIsNotFoundError(transactionHash); } const transaction = new Transaction(rawTransaction.data); return transaction.outputs[outputIndex]; } - throw new UnknownAssetLockProofError(assetLockProof.getType()); + throw new UnknownAssetLockProofTypeError(assetLockProof.getType()); } return fetchAssetLockTransactionOutput; diff --git a/lib/identity/stateTransition/assetLockProof/instant/validateInstantAssetLockProofStructureFactory.js b/lib/identity/stateTransition/assetLockProof/instant/validateInstantAssetLockProofStructureFactory.js index 81f7a238..6ad61e97 100644 --- a/lib/identity/stateTransition/assetLockProof/instant/validateInstantAssetLockProofStructureFactory.js +++ b/lib/identity/stateTransition/assetLockProof/instant/validateInstantAssetLockProofStructureFactory.js @@ -3,9 +3,9 @@ const { InstantLock } = require('@dashevo/dashcore-lib'); const instantAssetLockProofSchema = require('../../../../../schema/identity/stateTransition/assetLockProof/instantAssetLockProof.json'); const convertBuffersToArrays = require('../../../../util/convertBuffersToArrays'); -const InvalidIdentityAssetLockProofError = require('../../../../errors/consensus/basic/identity/InvalidIdentityAssetLockProofError'); -const IdentityAssetLockProofMismatchError = require('../../../../errors/consensus/basic/identity/IdentityAssetLockProofMismatchError'); -const InvalidIdentityAssetLockProofSignatureError = require('../../../../errors/consensus/basic/identity/InvalidIdentityAssetLockProofSignatureError'); +const InvalidInstantAssetLockProofError = require('../../../../errors/consensus/basic/identity/InvalidInstantAssetLockProofError'); +const IdentityAssetLockProofLockedTransactionMismatchError = require('../../../../errors/consensus/basic/identity/IdentityAssetLockProofLockedTransactionMismatchError'); +const InvalidIdentityAssetLockProofSignatureError = require('../../../../errors/consensus/basic/identity/InvalidInstantAssetLockProofSignatureError'); /** * @param {JsonSchemaValidator} jsonSchemaValidator @@ -38,7 +38,9 @@ function validateInstantAssetLockProofStructureFactory( try { instantLock = InstantLock.fromBuffer(rawAssetLockProof.instantLock); } catch (e) { - const error = new InvalidIdentityAssetLockProofError(e.message); + const error = new InvalidInstantAssetLockProofError(e.message); + + error.setValidationError(e); result.addError(error); @@ -69,7 +71,12 @@ function validateInstantAssetLockProofStructureFactory( const { publicKeyHash, transaction } = validateAssetLockTransactionResult.getData(); if (instantLock.txid !== transaction.id) { - result.addError(new IdentityAssetLockProofMismatchError()); + result.addError( + new IdentityAssetLockProofLockedTransactionMismatchError( + Buffer.from(instantLock.txid, 'hex'), + Buffer.from(transaction.id, 'hex'), + ), + ); return result; } diff --git a/lib/identity/stateTransition/assetLockProof/validateAssetLockTransactionFactory.js b/lib/identity/stateTransition/assetLockProof/validateAssetLockTransactionFactory.js index 07199ab3..daeed59a 100644 --- a/lib/identity/stateTransition/assetLockProof/validateAssetLockTransactionFactory.js +++ b/lib/identity/stateTransition/assetLockProof/validateAssetLockTransactionFactory.js @@ -5,6 +5,7 @@ const IdentityAssetLockTransactionOutputNotFoundError = require('../../../errors const InvalidIdentityAssetLockTransactionOutputError = require('../../../errors/consensus/basic/identity/InvalidIdentityAssetLockTransactionOutputError'); const ValidationResult = require('../../../validation/ValidationResult'); const IdentityAssetLockTransactionOutPointAlreadyExistsError = require('../../../errors/consensus/basic/identity/IdentityAssetLockTransactionOutPointAlreadyExistsError'); +const InvalidAssetLockTransactionOutputReturnSize = require('../../../errors/consensus/basic/identity/InvalidAssetLockTransactionOutputReturnSize'); /** * @@ -27,10 +28,12 @@ function validateAssetLockTransactionFactory(stateRepository) { let transaction; try { transaction = new Transaction(rawTransaction); - } catch (e) { - const error = new InvalidIdentityAssetLockTransactionError(e.message); + } catch (error) { + const consensusError = new InvalidIdentityAssetLockTransactionError(error.message); - result.addError(error); + consensusError.setValidationError(error); + + result.addError(consensusError); return result; } @@ -47,7 +50,7 @@ function validateAssetLockTransactionFactory(stateRepository) { if (!output.script.isDataOut()) { result.addError( - new InvalidIdentityAssetLockTransactionOutputError('Output is not a valid standard OP_RETURN output', output), + new InvalidIdentityAssetLockTransactionOutputError(outputIndex), ); return result; @@ -57,7 +60,7 @@ function validateAssetLockTransactionFactory(stateRepository) { if (publicKeyHash.length !== 20) { result.addError( - new InvalidIdentityAssetLockTransactionOutputError('Output has invalid public key hash', output), + new InvalidAssetLockTransactionOutputReturnSize(outputIndex), ); return result; @@ -70,7 +73,10 @@ function validateAssetLockTransactionFactory(stateRepository) { if (outPointIsUsed) { result.addError( - new IdentityAssetLockTransactionOutPointAlreadyExistsError(outPointBuffer), + new IdentityAssetLockTransactionOutPointAlreadyExistsError( + Buffer.from(transaction.id, 'hex'), + outputIndex, + ), ); return result; diff --git a/lib/identity/validation/validateIdentityExistenceFactory.js b/lib/identity/validation/validateIdentityExistenceFactory.js index ea09d24e..1b060bd7 100644 --- a/lib/identity/validation/validateIdentityExistenceFactory.js +++ b/lib/identity/validation/validateIdentityExistenceFactory.js @@ -17,7 +17,7 @@ function validateIdentityExistenceFactory(stateRepository) { const identity = await stateRepository.fetchIdentity(identityId); if (!identity) { - result.addError(new IdentityNotFoundError(identityId)); + result.addError(new IdentityNotFoundError(identityId.toBuffer())); } result.setData(identity); diff --git a/lib/identity/validation/validatePublicKeysFactory.js b/lib/identity/validation/validatePublicKeysFactory.js index 15778f13..30fe4696 100644 --- a/lib/identity/validation/validatePublicKeysFactory.js +++ b/lib/identity/validation/validatePublicKeysFactory.js @@ -63,12 +63,14 @@ function validatePublicKeysFactory(validator) { }); if (duplicatedIds.length > 0) { - result.addError(new DuplicatedIdentityPublicKeyIdError(rawPublicKeys)); + result.addError( + new DuplicatedIdentityPublicKeyIdError(duplicatedIds), + ); } // Check that there's no duplicated keys const keysCount = {}; - const duplicatedKeys = []; + const duplicatedKeyIds = []; rawPublicKeys.forEach((rawPublicKey) => { const dataHex = rawPublicKey.data.toString('hex'); @@ -76,12 +78,14 @@ function validatePublicKeysFactory(validator) { ? 1 : keysCount[dataHex] + 1; if (keysCount[dataHex] > 1) { - duplicatedKeys.push(dataHex); + duplicatedKeyIds.push(rawPublicKey.id); } }); - if (duplicatedKeys.length > 0) { - result.addError(new DuplicatedIdentityPublicKeyError(rawPublicKeys)); + if (duplicatedKeyIds.length > 0) { + result.addError( + new DuplicatedIdentityPublicKeyError(duplicatedKeyIds), + ); } // validate key data @@ -90,12 +94,16 @@ function validatePublicKeysFactory(validator) { const dataHex = rawPublicKey.data.toString('hex'); if (!PublicKey.isValid(dataHex)) { - result.addError( - new InvalidIdentityPublicKeyDataError( - rawPublicKey, - PublicKey.getValidationError(dataHex), - ), + const validationError = PublicKey.getValidationError(dataHex); + + const consensusError = new InvalidIdentityPublicKeyDataError( + rawPublicKey.id, + validationError.message, ); + + consensusError.setValidationError(validationError); + + result.addError(consensusError); } }); diff --git a/lib/stateTransition/StateTransitionFactory.js b/lib/stateTransition/StateTransitionFactory.js index 29cea415..f23ef92d 100644 --- a/lib/stateTransition/StateTransitionFactory.js +++ b/lib/stateTransition/StateTransitionFactory.js @@ -1,5 +1,5 @@ const InvalidStateTransitionError = require('./errors/InvalidStateTransitionError'); -const ConsensusError = require('../errors/consensus/ConsensusError'); +const AbstractConsensusError = require('../errors/consensus/AbstractConsensusError'); class StateTransitionFactory { /** @@ -65,7 +65,7 @@ class StateTransitionFactory { rawStateTransition.protocolVersion = protocolVersion; } catch (error) { - if (error instanceof ConsensusError) { + if (error instanceof AbstractConsensusError) { throw new InvalidStateTransitionError([error]); } diff --git a/lib/stateTransition/errors/InvalidStateTransitionError.js b/lib/stateTransition/errors/InvalidStateTransitionError.js index c44852b2..589e32fa 100644 --- a/lib/stateTransition/errors/InvalidStateTransitionError.js +++ b/lib/stateTransition/errors/InvalidStateTransitionError.js @@ -2,7 +2,7 @@ const DPPError = require('../../errors/DPPError'); class InvalidStateTransitionError extends DPPError { /** - * @param {ConsensusError[]} errors + * @param {AbstractConsensusError[]} errors * @param {RawStateTransition} [rawStateTransition] */ constructor(errors, rawStateTransition = undefined) { @@ -20,7 +20,7 @@ class InvalidStateTransitionError extends DPPError { /** * Get validation errors * - * @return {ConsensusError[]} + * @return {AbstractConsensusError[]} */ getErrors() { return this.errors; diff --git a/lib/stateTransition/validation/validateStateTransitionBasicFactory.js b/lib/stateTransition/validation/validateStateTransitionBasicFactory.js index c66df743..4613556d 100644 --- a/lib/stateTransition/validation/validateStateTransitionBasicFactory.js +++ b/lib/stateTransition/validation/validateStateTransitionBasicFactory.js @@ -23,7 +23,7 @@ function validateStateTransitionBasicFactory( if (!Object.prototype.hasOwnProperty.call(rawStateTransition, 'type')) { result.addError( - new MissingStateTransitionTypeError(rawStateTransition), + new MissingStateTransitionTypeError(), ); return result; @@ -31,7 +31,7 @@ function validateStateTransitionBasicFactory( if (!validationFunctionsByType[rawStateTransition.type]) { result.addError( - new InvalidStateTransitionTypeError(rawStateTransition), + new InvalidStateTransitionTypeError(rawStateTransition.type), ); return result; @@ -54,7 +54,10 @@ function validateStateTransitionBasicFactory( } catch (e) { if (e instanceof MaxEncodedBytesReachedError) { result.addError( - new StateTransitionMaxSizeExceededError(rawStateTransition, e.getMaxSizeKBytes()), + new StateTransitionMaxSizeExceededError( + Math.floor(e.getPayload().length / 1024), + e.getMaxSizeKBytes(), + ), ); } else { throw e; diff --git a/lib/stateTransition/validation/validateStateTransitionFeeFactory.js b/lib/stateTransition/validation/validateStateTransitionFeeFactory.js index 83e8e523..c75079a2 100644 --- a/lib/stateTransition/validation/validateStateTransitionFeeFactory.js +++ b/lib/stateTransition/validation/validateStateTransitionFeeFactory.js @@ -60,7 +60,7 @@ function validateStateTransitionFeeFactory( if (balance < feeSize) { result.addError( - new BalanceIsNotEnoughError(balance), + new BalanceIsNotEnoughError(balance, feeSize), ); } diff --git a/lib/stateTransition/validation/validateStateTransitionKeySignatureFactory.js b/lib/stateTransition/validation/validateStateTransitionKeySignatureFactory.js index 5255fa83..5b97264d 100644 --- a/lib/stateTransition/validation/validateStateTransitionKeySignatureFactory.js +++ b/lib/stateTransition/validation/validateStateTransitionKeySignatureFactory.js @@ -35,7 +35,7 @@ function validateStateTransitionKeySignatureFactory( } if (!signatureIsVerified) { - result.addError(new InvalidStateTransitionSignatureError(stateTransition)); + result.addError(new InvalidStateTransitionSignatureError()); } return result; diff --git a/lib/test/bootstrap.js b/lib/test/bootstrap.js index 422768c5..7664fa28 100644 --- a/lib/test/bootstrap.js +++ b/lib/test/bootstrap.js @@ -3,10 +3,12 @@ const sinon = require('sinon'); const sinonChai = require('sinon-chai'); const dirtyChai = require('dirty-chai'); const chaiAsPromised = require('chai-as-promised'); +const chaiString = require('chai-string'); use(sinonChai); use(chaiAsPromised); use(dirtyChai); +use(chaiString); beforeEach(function beforeEach() { if (!this.sinonSandbox) { diff --git a/lib/test/expect/expectError.js b/lib/test/expect/expectError.js index 6fc8dce0..b8ad446b 100644 --- a/lib/test/expect/expectError.js +++ b/lib/test/expect/expectError.js @@ -1,16 +1,16 @@ const { expect } = require('chai'); const ValidationResult = require('../../validation/ValidationResult'); -const ConsensusError = require('../../errors/consensus/ConsensusError'); +const AbstractConsensusError = require('../../errors/consensus/AbstractConsensusError'); const JsonSchemaError = require('../../errors/consensus/basic/JsonSchemaError'); const expectError = { /** * @param {ValidationResult} result - * @param {ConsensusError} [errorClass] + * @param {AbstractConsensusError} [errorClass] * @param {number} [count] */ - expectValidationError(result, errorClass = ConsensusError, count = 1) { + expectValidationError(result, errorClass = AbstractConsensusError, count = 1) { expect(result).to.be.an.instanceOf(ValidationResult); expect(result.getErrors()).to.have.lengthOf(count); diff --git a/lib/test/mocks/SomeConsensusError.js b/lib/test/mocks/SomeConsensusError.js new file mode 100644 index 00000000..0cae2395 --- /dev/null +++ b/lib/test/mocks/SomeConsensusError.js @@ -0,0 +1,19 @@ +const AbstractConsensusError = require('../../errors/consensus/AbstractConsensusError'); + +class SomeConsensusError extends AbstractConsensusError { + constructor(message) { + super(message); + + // eslint-disable-next-line prefer-rest-params + this.setConstructorArguments(arguments); + } + + /** + * @returns {number} + */ + getCode() { + return Number.MAX_SAFE_INTEGER; + } +} + +module.exports = SomeConsensusError; diff --git a/lib/util/getFunctionParams.js b/lib/util/getFunctionParams.js new file mode 100644 index 00000000..18ef78be --- /dev/null +++ b/lib/util/getFunctionParams.js @@ -0,0 +1,59 @@ +const STRIP_COMMENTS = /(\/\/.*$)|(\/\*[\s\S]*?\*\/)|(\s*=[^,)]*(('(?:\\'|[^'\r\n])*')|("(?:\\"|[^"\r\n])*"))|(\s*=[^,)]*))/mg; +const ARGUMENT_NAMES = /([^\s,]+)/g; + +/** + * Get function params + * + * @param {Function} fn + * @param {number} skip Skip params + * @return {array} + */ +function getFunctionParams(fn, skip = 0) { + const functionString = fn.toString().replace(STRIP_COMMENTS, ''); + + let params = functionString.slice( + functionString.indexOf('(') + 1, + functionString.indexOf(')'), + ).match(ARGUMENT_NAMES); + + if (params === null) { + params = []; + } + + const filteredParams = []; + let openDestructors = 0; + let skippedCount = 0; + + for (let i = 0; i < params.length; i++) { + switch (params[i]) { + case '{': + openDestructors++; + + break; + case '}': + openDestructors--; + + if (openDestructors === 0 && skippedCount < skip) { + skippedCount++; + } + + break; + default: + if (openDestructors > 0) { + break; + } + + if (skippedCount < skip) { + skippedCount++; + + break; + } + + filteredParams.push(params[i]); + } + } + + return filteredParams; +} + +module.exports = getFunctionParams; diff --git a/lib/validation/JsonSchemaValidator.js b/lib/validation/JsonSchemaValidator.js index 24879b8d..0e49db83 100644 --- a/lib/validation/JsonSchemaValidator.js +++ b/lib/validation/JsonSchemaValidator.js @@ -1,7 +1,9 @@ const dataContractMetaSchema = require('../../schema/dataContract/dataContractMeta'); const ValidationResult = require('./ValidationResult'); + const JsonSchemaError = require('../errors/consensus/basic/JsonSchemaError'); +const JsonSchemaCompilationError = require('../errors/consensus/basic/JsonSchemaCompilationError'); class JsonSchemaValidator { constructor(ajv) { @@ -37,7 +39,14 @@ class JsonSchemaValidator { }); return new ValidationResult( - (this.ajv.errors || []).map((error) => new JsonSchemaError(error)), + (this.ajv.errors || []).map((error) => new JsonSchemaError( + error.message, + error.keyword, + error.instancePath, + error.schemaPath, + error.params, + error.propertyName, + )), ); } @@ -61,7 +70,7 @@ class JsonSchemaValidator { this.ajv.compile(schema); } catch (e) { result.addError( - new JsonSchemaError(e), + new JsonSchemaCompilationError(e.message), ); } finally { Object.keys(additionalSchemas).forEach((schemaId) => { @@ -69,6 +78,19 @@ class JsonSchemaValidator { }); } + if (this.ajv.errors) { + result.addError( + this.ajv.errors.map((error) => new JsonSchemaError( + error.message, + error.keyword, + error.instancePath, + error.schemaPath, + error.params, + error.propertyName, + )), + ); + } + return result; } } diff --git a/lib/validation/ValidationResult.js b/lib/validation/ValidationResult.js index 0808a33e..9ba88c59 100644 --- a/lib/validation/ValidationResult.js +++ b/lib/validation/ValidationResult.js @@ -1,6 +1,6 @@ class ValidationResult { /** - * @param {ConsensusError[]} [errors] + * @param {AbstractConsensusError[]} [errors] */ constructor(errors = []) { this.errors = errors; @@ -10,7 +10,7 @@ class ValidationResult { /** * Add consensus error * - * @param {...ConsensusError} error + * @param {...AbstractConsensusError} error */ addError(...error) { this.errors.push(...error); @@ -19,12 +19,21 @@ class ValidationResult { /** * Get consensus errors * - * @return {ConsensusError[]} + * @return {AbstractConsensusError[]} */ getErrors() { return this.errors; } + /** + * Get the first consensus error + * + * @returns {AbstractConsensusError} + */ + getFirstError() { + return this.errors[0]; + } + /** * Is data valid * diff --git a/package-lock.json b/package-lock.json index 38c9698d..a1836f19 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1846,6 +1846,16 @@ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, "blob": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", @@ -2228,6 +2238,12 @@ "check-error": "^1.0.2" } }, + "chai-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/chai-string/-/chai-string-1.5.0.tgz", + "integrity": "sha512-sydDC3S3pNAQMYwJrs6dQX0oBQ6KfIPuOZ78n7rocW0eJJlsHPh2t3kwW7xfwYA/1Bf6/arGtSUo16rxR2JFlw==", + "dev": true + }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -2259,6 +2275,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", @@ -3733,6 +3750,13 @@ "flat-cache": "^2.0.1" } }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -3978,6 +4002,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", @@ -5999,6 +6030,13 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "nan": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", + "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", + "dev": true, + "optional": true + }, "nanoid": { "version": "3.1.20", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", @@ -8702,6 +8740,7 @@ "anymatch": "^2.0.0", "async-each": "^1.0.1", "braces": "^2.3.2", + "fsevents": "^1.2.7", "glob-parent": "^3.1.0", "inherits": "^2.0.3", "is-binary-path": "^1.0.0", @@ -8735,6 +8774,17 @@ "to-regex-range": "^2.1.0" } }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, "glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", diff --git a/package.json b/package.json index f76d35db..1dffc87b 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "babel-loader": "^8.1.0", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", + "chai-string": "^1.5.0", "core-js": "^3.6.4", "dirty-chai": "^2.0.1", "eslint": "^6.8.0", diff --git a/test/integration/dataContract/DataContractFacade.spec.js b/test/integration/dataContract/DataContractFacade.spec.js index 5f840966..6ece1a27 100644 --- a/test/integration/dataContract/DataContractFacade.spec.js +++ b/test/integration/dataContract/DataContractFacade.spec.js @@ -21,7 +21,11 @@ describe('DataContractFacade', () => { dataContract = getDataContractFixture(); - dataContractFactory = new DataContractFactory(dpp, undefined); + dataContractFactory = new DataContractFactory( + dpp, + undefined, + undefined, + ); }); describe('create', () => { diff --git a/test/integration/dataContract/stateTransition/DataContractCreateTransition/validation/basic/validateDataContractCreateTransitionBasicFactory.spec.js b/test/integration/dataContract/stateTransition/DataContractCreateTransition/validation/basic/validateDataContractCreateTransitionBasicFactory.spec.js index 152c9123..ce6fac7d 100644 --- a/test/integration/dataContract/stateTransition/DataContractCreateTransition/validation/basic/validateDataContractCreateTransitionBasicFactory.spec.js +++ b/test/integration/dataContract/stateTransition/DataContractCreateTransition/validation/basic/validateDataContractCreateTransitionBasicFactory.spec.js @@ -21,9 +21,8 @@ const { const ValidationResult = require('../../../../../../../lib/validation/ValidationResult'); -const ConsensusError = require('../../../../../../../lib/errors/consensus/ConsensusError'); - const InvalidDataContractIdError = require('../../../../../../../lib/errors/consensus/basic/dataContract/InvalidDataContractIdError'); +const SomeConsensusError = require('../../../../../../../lib/test/mocks/SomeConsensusError'); describe('validateDataContractCreateTransitionBasicFactory', () => { let validateDataContractMock; @@ -71,9 +70,9 @@ describe('validateDataContractCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('protocolVersion'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('protocolVersion'); }); it('should be an integer', async () => { @@ -85,8 +84,8 @@ describe('validateDataContractCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/protocolVersion'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/protocolVersion'); + expect(error.getKeyword()).to.equal('type'); }); it('should not be less than 0', async () => { @@ -98,8 +97,8 @@ describe('validateDataContractCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.keyword).to.equal('minimum'); - expect(error.instancePath).to.equal('/protocolVersion'); + expect(error.getKeyword()).to.equal('minimum'); + expect(error.getInstancePath()).to.equal('/protocolVersion'); }); it('should not be greater than current version (0)', async () => { @@ -111,8 +110,8 @@ describe('validateDataContractCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.keyword).to.equal('maximum'); - expect(error.instancePath).to.equal('/protocolVersion'); + expect(error.getKeyword()).to.equal('maximum'); + expect(error.getInstancePath()).to.equal('/protocolVersion'); }); }); @@ -126,9 +125,9 @@ describe('validateDataContractCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('type'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('type'); }); it('should be equal to 0', async () => { @@ -140,9 +139,9 @@ describe('validateDataContractCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/type'); - expect(error.keyword).to.equal('const'); - expect(error.params.allowedValue).to.equal(0); + expect(error.getInstancePath()).to.equal('/type'); + expect(error.getKeyword()).to.equal('const'); + expect(error.getParams().allowedValue).to.equal(0); }); }); @@ -156,13 +155,13 @@ describe('validateDataContractCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('dataContract'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('dataContract'); }); it('should be valid', async () => { - const dataContractError = new ConsensusError('test'); + const dataContractError = new SomeConsensusError('test'); const dataContractResult = new ValidationResult([ dataContractError, ]); @@ -197,6 +196,7 @@ describe('validateDataContractCreateTransitionBasicFactory', () => { expect(error).to.be.an.instanceOf(InvalidDataContractIdError); expect(error.getExpectedId()).to.deep.equal(expectedId); expect(error.getInvalidId()).to.deep.equal(rawStateTransition.dataContract.$id); + expect(error.getCode()).to.equal(1011); }); }); @@ -210,9 +210,9 @@ describe('validateDataContractCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('entropy'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('entropy'); }); it('should be a byte array', async () => { @@ -224,10 +224,10 @@ describe('validateDataContractCreateTransitionBasicFactory', () => { const [error, byteArrayError] = result.getErrors(); - expect(error.instancePath).to.equal('/entropy/0'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/entropy/0'); + expect(error.getKeyword()).to.equal('type'); - expect(byteArrayError.keyword).to.equal('byteArray'); + expect(byteArrayError.getKeyword()).to.equal('byteArray'); }); it('should be no less than 32 bytes', async () => { @@ -239,9 +239,9 @@ describe('validateDataContractCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/entropy'); - expect(error.keyword).to.equal('minItems'); - expect(error.params.limit).to.equal(32); + expect(error.getInstancePath()).to.equal('/entropy'); + expect(error.getKeyword()).to.equal('minItems'); + expect(error.getParams().limit).to.equal(32); }); it('should be no longer than 32 bytes', async () => { @@ -253,9 +253,9 @@ describe('validateDataContractCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/entropy'); - expect(error.keyword).to.equal('maxItems'); - expect(error.params.limit).to.equal(32); + expect(error.getInstancePath()).to.equal('/entropy'); + expect(error.getKeyword()).to.equal('maxItems'); + expect(error.getParams().limit).to.equal(32); }); }); @@ -269,9 +269,9 @@ describe('validateDataContractCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('signature'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('signature'); }); it('should be a byte array', async () => { @@ -283,10 +283,10 @@ describe('validateDataContractCreateTransitionBasicFactory', () => { const [error, byteArrayError] = result.getErrors(); - expect(error.instancePath).to.equal('/signature/0'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/signature/0'); + expect(error.getKeyword()).to.equal('type'); - expect(byteArrayError.keyword).to.equal('byteArray'); + expect(byteArrayError.getKeyword()).to.equal('byteArray'); }); it('should be not less than 65 bytes', async () => { @@ -298,9 +298,9 @@ describe('validateDataContractCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/signature'); - expect(error.keyword).to.equal('minItems'); - expect(error.params.limit).to.equal(65); + expect(error.getInstancePath()).to.equal('/signature'); + expect(error.getKeyword()).to.equal('minItems'); + expect(error.getParams().limit).to.equal(65); }); it('should be not longer than 65 bytes', async () => { @@ -312,9 +312,9 @@ describe('validateDataContractCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/signature'); - expect(error.keyword).to.equal('maxItems'); - expect(error.params.limit).to.equal(65); + expect(error.getInstancePath()).to.equal('/signature'); + expect(error.getKeyword()).to.equal('maxItems'); + expect(error.getParams().limit).to.equal(65); }); }); @@ -329,7 +329,7 @@ describe('validateDataContractCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/signaturePublicKeyId'); - expect(error.keyword).to.equal('type'); + expect(error.getKeyword()).to.equal('type'); }); it('should not be < 0', async () => { @@ -342,7 +342,7 @@ describe('validateDataContractCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/signaturePublicKeyId'); - expect(error.keyword).to.equal('minimum'); + expect(error.getKeyword()).to.equal('minimum'); }); }); diff --git a/test/integration/dataContract/validation/validateDataContractFactory.spec.js b/test/integration/dataContract/validation/validateDataContractFactory.spec.js index 8a73ad76..a4735ac2 100644 --- a/test/integration/dataContract/validation/validateDataContractFactory.spec.js +++ b/test/integration/dataContract/validation/validateDataContractFactory.spec.js @@ -24,7 +24,9 @@ const SystemPropertyIndexAlreadyPresentError = require('../../../../lib/errors/c const UniqueIndicesLimitReachedError = require('../../../../lib/errors/consensus/basic/dataContract/UniqueIndicesLimitReachedError'); const InvalidIndexedPropertyConstraintError = require('../../../../lib/errors/consensus/basic/dataContract/InvalidIndexedPropertyConstraintError'); const InvalidCompoundIndexError = require('../../../../lib/errors/consensus/basic/dataContract/InvalidCompoundIndexError'); -const IncompatibleRe2PatternError = require('../../../../lib/document/errors/IncompatibleRe2PatternError'); +const IncompatibleRe2PatternError = require('../../../../lib/errors/consensus/basic/dataContract/IncompatibleRe2PatternError'); +const InvalidJsonSchemaRefError = require('../../../../lib/errors/consensus/basic/dataContract/InvalidJsonSchemaRefError'); +const JsonSchemaCompilationError = require('../../../../lib/errors/consensus/basic/JsonSchemaCompilationError'); describe('validateDataContractFactory', function main() { this.timeout(15000); @@ -75,9 +77,9 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('protocolVersion'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('protocolVersion'); }); it('should be an integer', async () => { @@ -89,8 +91,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/protocolVersion'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/protocolVersion'); + expect(error.getKeyword()).to.equal('type'); }); it('should not be less than 0', async () => { @@ -102,8 +104,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.keyword).to.equal('minimum'); - expect(error.instancePath).to.equal('/protocolVersion'); + expect(error.getKeyword()).to.equal('minimum'); + expect(error.getInstancePath()).to.equal('/protocolVersion'); }); it('should not be greater than current version (0)', async () => { @@ -115,8 +117,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.keyword).to.equal('maximum'); - expect(error.instancePath).to.equal('/protocolVersion'); + expect(error.getKeyword()).to.equal('maximum'); + expect(error.getInstancePath()).to.equal('/protocolVersion'); }); }); @@ -130,9 +132,9 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('$schema'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('$schema'); }); it('should be a string', async () => { @@ -144,8 +146,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/$schema'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/$schema'); + expect(error.getKeyword()).to.equal('type'); }); it('should be a particular url', async () => { @@ -157,8 +159,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.keyword).to.equal('const'); - expect(error.instancePath).to.equal('/$schema'); + expect(error.getKeyword()).to.equal('const'); + expect(error.getInstancePath()).to.equal('/$schema'); }); }); @@ -172,9 +174,9 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('ownerId'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('ownerId'); }); it('should be a byte array', async () => { @@ -186,10 +188,10 @@ describe('validateDataContractFactory', function main() { const [error, byteArrayError] = result.getErrors(); - expect(error.instancePath).to.equal('/ownerId/0'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/ownerId/0'); + expect(error.getKeyword()).to.equal('type'); - expect(byteArrayError.keyword).to.equal('byteArray'); + expect(byteArrayError.getKeyword()).to.equal('byteArray'); }); it('should be no less than 32 bytes', async () => { @@ -201,8 +203,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/ownerId'); - expect(error.keyword).to.equal('minItems'); + expect(error.getInstancePath()).to.equal('/ownerId'); + expect(error.getKeyword()).to.equal('minItems'); }); it('should be no longer than 32 bytes', async () => { @@ -214,8 +216,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/ownerId'); - expect(error.keyword).to.equal('maxItems'); + expect(error.getInstancePath()).to.equal('/ownerId'); + expect(error.getKeyword()).to.equal('maxItems'); }); }); @@ -229,9 +231,9 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('$id'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('$id'); }); it('should be a byte array', async () => { @@ -243,10 +245,10 @@ describe('validateDataContractFactory', function main() { const [error, byteArrayError] = result.getErrors(); - expect(error.instancePath).to.equal('/$id/0'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/$id/0'); + expect(error.getKeyword()).to.equal('type'); - expect(byteArrayError.keyword).to.equal('byteArray'); + expect(byteArrayError.getKeyword()).to.equal('byteArray'); }); it('should be no less than 32 bytes', async () => { @@ -258,8 +260,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/$id'); - expect(error.keyword).to.equal('minItems'); + expect(error.getInstancePath()).to.equal('/$id'); + expect(error.getKeyword()).to.equal('minItems'); }); it('should be no longer than 32 bytes', async () => { @@ -271,8 +273,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/$id'); - expect(error.keyword).to.equal('maxItems'); + expect(error.getInstancePath()).to.equal('/$id'); + expect(error.getKeyword()).to.equal('maxItems'); }); }); @@ -296,8 +298,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/$defs'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/$defs'); + expect(error.getKeyword()).to.equal('type'); }); it('should not be empty', async () => { @@ -309,8 +311,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/$defs'); - expect(error.keyword).to.equal('minProperties'); + expect(error.getInstancePath()).to.equal('/$defs'); + expect(error.getKeyword()).to.equal('minProperties'); }); it('should have no non-alphanumeric properties', async () => { @@ -324,11 +326,11 @@ describe('validateDataContractFactory', function main() { const [patternError, propertyNamesError] = result.getErrors(); - expect(patternError.instancePath).to.equal('/$defs'); - expect(patternError.keyword).to.equal('pattern'); + expect(patternError.getInstancePath()).to.equal('/$defs'); + expect(patternError.getKeyword()).to.equal('pattern'); - expect(propertyNamesError.instancePath).to.equal('/$defs'); - expect(propertyNamesError.keyword).to.equal('propertyNames'); + expect(propertyNamesError.getInstancePath()).to.equal('/$defs'); + expect(propertyNamesError.getKeyword()).to.equal('propertyNames'); }); it('should have no more than 100 properties', async () => { @@ -344,8 +346,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/$defs'); - expect(error.keyword).to.equal('maxProperties'); + expect(error.getInstancePath()).to.equal('/$defs'); + expect(error.getKeyword()).to.equal('maxProperties'); }); it('should have valid property names', async () => { @@ -380,8 +382,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/$defs'); - expect(error.keyword).to.equal('pattern'); + expect(error.getInstancePath()).to.equal('/$defs'); + expect(error.getKeyword()).to.equal('pattern'); }), ); }); @@ -397,9 +399,9 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('documents'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('documents'); }); it('should be an object', async () => { @@ -411,8 +413,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/documents'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/documents'); + expect(error.getKeyword()).to.equal('type'); }); it('should not be empty', async () => { @@ -424,8 +426,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/documents'); - expect(error.keyword).to.equal('minProperties'); + expect(error.getInstancePath()).to.equal('/documents'); + expect(error.getKeyword()).to.equal('minProperties'); }); it('should have valid property names (document types)', async () => { @@ -456,8 +458,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/documents'); - expect(error.keyword).to.equal('pattern'); + expect(error.getInstancePath()).to.equal('/documents'); + expect(error.getKeyword()).to.equal('pattern'); }), ); }); @@ -477,8 +479,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/documents'); - expect(error.keyword).to.equal('maxProperties'); + expect(error.getInstancePath()).to.equal('/documents'); + expect(error.getKeyword()).to.equal('maxProperties'); }); describe('Document schema', () => { @@ -492,7 +494,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/niceDocument/properties'); - expect(error.keyword).to.equal('minProperties'); + expect(error.getKeyword()).to.equal('minProperties'); }); it('should have type "object"', async () => { @@ -505,7 +507,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/niceDocument/type'); - expect(error.keyword).to.equal('const'); + expect(error.getKeyword()).to.equal('const'); }); it('should have "properties"', async () => { @@ -518,8 +520,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/niceDocument'); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('properties'); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('properties'); }); it('should have nested "properties"', async () => { @@ -546,8 +548,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/niceDocument/properties/object/prefixItems/0/properties/something'); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('properties'); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('properties'); }); it('should have valid property names', async () => { @@ -651,8 +653,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/niceDocument'); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('additionalProperties'); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('additionalProperties'); }); it('should have "additionalProperties" defined to false', async () => { @@ -665,7 +667,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/niceDocument/additionalProperties'); - expect(error.keyword).to.equal('const'); + expect(error.getKeyword()).to.equal('const'); }); it('should have nested "additionalProperties" defined', async () => { @@ -691,8 +693,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/niceDocument/properties/object/prefixItems/0'); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('additionalProperties'); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('additionalProperties'); }); it('should return invalid result if there are additional properties', async () => { @@ -705,7 +707,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('additionalProperties'); + expect(error.getKeyword()).to.equal('additionalProperties'); }); it('should have no more than 100 properties', async () => { @@ -724,7 +726,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/niceDocument/properties'); - expect(error.keyword).to.equal('maxProperties'); + expect(error.getKeyword()).to.equal('maxProperties'); }); it('should have defined items for arrays', async () => { @@ -744,8 +746,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/new/properties/something'); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('items'); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('items'); }); it('should have sub schema in items for arrays', async () => { @@ -773,8 +775,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/new/properties/something/items'); - expect(error.keyword).to.equal('type'); - expect(error.params.type).to.equal('object'); + expect(error.getKeyword()).to.equal('type'); + expect(error.getParams().type).to.equal('object'); }); it('should have items if prefixItems is used for arrays', async () => { @@ -804,8 +806,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/new/properties/something'); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('items'); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('items'); }); it('should not have items disabled if prefixItems is used for arrays', async () => { @@ -834,8 +836,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/new/properties/something/items'); - expect(error.keyword).to.equal('const'); - expect(error.params.allowedValue).to.equal(false); + expect(error.getKeyword()).to.equal('const'); + expect(error.getParams().allowedValue).to.equal(false); }); it('should return invalid result if "default" keyword is used', async () => { @@ -848,7 +850,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/indexedDocument/properties/firstName'); - expect(error.keyword).to.equal('unevaluatedProperties'); + expect(error.getKeyword()).to.equal('unevaluatedProperties'); }); it('should return invalid result if remote `$ref` is used', async () => { @@ -863,7 +865,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/indexedDocument/$ref'); - expect(error.keyword).to.equal('pattern'); + expect(error.getKeyword()).to.equal('pattern'); }); it('should not have `propertyNames`', async () => { @@ -887,8 +889,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/indexedDocument'); - expect(error.keyword).to.equal('unevaluatedProperties'); - expect(error.params.unevaluatedProperty).to.equal('propertyNames'); + expect(error.getKeyword()).to.equal('unevaluatedProperties'); + expect(error.getParams().unevaluatedProperty).to.equal('propertyNames'); }); it('should have `maxItems` if `uniqueItems` is used', async () => { @@ -910,8 +912,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/indexedDocument/properties/something'); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('items'); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('items'); }); it('should have `maxItems` no bigger than 100000 if `uniqueItems` is used', async () => { @@ -943,7 +945,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/indexedDocument/properties/something/maxItems'); - expect(error.keyword).to.equal('maximum'); + expect(error.getKeyword()).to.equal('maximum'); }); it('should return invalid result if document JSON Schema is not valid', async () => { @@ -961,10 +963,12 @@ describe('validateDataContractFactory', function main() { const result = await validateDataContract(rawDataContract); - expectJsonSchemaError(result); + expectValidationError(result, JsonSchemaCompilationError); const [error] = result.getErrors(); + expect(error.getCode()).to.equal(1004); + expect(error.message).to.be.a('string').and.satisfy((msg) => ( msg.startsWith('unknown format "lalala" ignored in schema') )); @@ -989,8 +993,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/indexedDocument/properties/something'); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('maxLength'); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('maxLength'); }); it('should have `maxLength` no bigger than 50000 if `pattern` is used', async () => { @@ -1013,7 +1017,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/indexedDocument/properties/something/maxLength'); - expect(error.keyword).to.equal('maximum'); + expect(error.getKeyword()).to.equal('maximum'); }); it('should have `maxLength` if `format` is used', async () => { @@ -1035,8 +1039,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/indexedDocument/properties/something'); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('maxLength'); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('maxLength'); }); it('should have `maxLength` no bigger than 50000 if `format` is used', async () => { @@ -1059,7 +1063,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/indexedDocument/properties/something/maxLength'); - expect(error.keyword).to.equal('maximum'); + expect(error.getKeyword()).to.equal('maximum'); }); it('should not have incompatible patterns', async () => { @@ -1081,11 +1085,10 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(1009); expect(error.getPattern()).to.equal('^((?!-|_)[a-zA-Z0-9-_]{0,62}[a-zA-Z0-9])$'); expect(error.getPath()).to.equal('/documents/indexedDocument/properties/something'); - expect(error.getOriginalErrorMessage()).to.be.a('string').and.satisfy((msg) => ( - msg.startsWith('Invalid regular expression') - )); + expect(error.getPatternError()).to.be.instanceOf(Error); }); describe('byteArray', () => { @@ -1099,8 +1102,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/withByteArrays/properties/byteArrayField/byteArray'); - expect(error.keyword).to.equal('type'); - expect(error.params.type).to.equal('boolean'); + expect(error.getKeyword()).to.equal('type'); + expect(error.getParams().type).to.equal('boolean'); }); it('should equal to true', async () => { @@ -1113,8 +1116,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/withByteArrays/properties/byteArrayField/byteArray'); - expect(error.keyword).to.equal('const'); - expect(error.params.allowedValue).to.equal(true); + expect(error.getKeyword()).to.equal('const'); + expect(error.getParams().allowedValue).to.equal(true); }); it('should be used with type `array`', async () => { @@ -1127,7 +1130,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/withByteArrays/properties/byteArrayField/type'); - expect(error.keyword).to.equal('const'); + expect(error.getKeyword()).to.equal('const'); }); it('should not be used with `items`', async () => { @@ -1137,10 +1140,11 @@ describe('validateDataContractFactory', function main() { const result = await validateDataContract(rawDataContract); - expectJsonSchemaError(result, 1); + expectValidationError(result, JsonSchemaCompilationError); const [error] = result.getErrors(); + expect(error.getCode()).to.equal(1004); expect(error.message).to.equal("'byteArray' should not be used with 'items'"); }); }); @@ -1157,7 +1161,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/withByteArrays/properties/identifierField'); - expect(error.keyword).to.equal('required'); + expect(error.getKeyword()).to.equal('required'); }); it('should be used with byte array not shorter than 32 bytes', async () => { @@ -1170,7 +1174,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/withByteArrays/properties/identifierField/minItems'); - expect(error.keyword).to.equal('const'); + expect(error.getKeyword()).to.equal('const'); }); it('should be used with byte array not longer than 32 bytes', async () => { @@ -1183,7 +1187,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/withByteArrays/properties/identifierField/maxItems'); - expect(error.keyword).to.equal('const'); + expect(error.getKeyword()).to.equal('const'); }); }); }); @@ -1201,7 +1205,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/indexedDocument/indices'); - expect(error.keyword).to.equal('type'); + expect(error.getKeyword()).to.equal('type'); }); it('should have at least one item', async () => { @@ -1214,7 +1218,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/indexedDocument/indices'); - expect(error.keyword).to.equal('minItems'); + expect(error.getKeyword()).to.equal('minItems'); }); it('should return invalid result if there are duplicated indices', async () => { @@ -1228,8 +1232,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(1008); expect(error.getIndexDefinition()).to.deep.equal(indexDefinition); - expect(error.getRawDataContract()).to.deep.equal(rawDataContract); expect(error.getDocumentType()).to.deep.equal('indexedDocument'); }); @@ -1244,7 +1248,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/indexedDocument/indices/0'); - expect(error.keyword).to.equal('type'); + expect(error.getKeyword()).to.equal('type'); }); it('should have properties definition', async () => { @@ -1257,8 +1261,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/indexedDocument/indices/0'); - expect(error.params.missingProperty).to.equal('properties'); - expect(error.keyword).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('properties'); + expect(error.getKeyword()).to.equal('required'); }); describe('properties definition', () => { @@ -1275,7 +1279,7 @@ describe('validateDataContractFactory', function main() { expect(error.instancePath).to.equal( '/documents/indexedDocument/indices/0/properties', ); - expect(error.keyword).to.equal('type'); + expect(error.getKeyword()).to.equal('type'); }); it('should have at least one property defined', async () => { @@ -1291,7 +1295,7 @@ describe('validateDataContractFactory', function main() { expect(error.instancePath).to.equal( '/documents/indexedDocument/indices/0/properties', ); - expect(error.keyword).to.equal('minItems'); + expect(error.getKeyword()).to.equal('minItems'); }); it('should have no more than 10 property $defs', async () => { @@ -1309,7 +1313,7 @@ describe('validateDataContractFactory', function main() { expect(error.instancePath).to.equal( '/documents/indexedDocument/indices/0/properties', ); - expect(error.keyword).to.equal('maxItems'); + expect(error.getKeyword()).to.equal('maxItems'); }); describe('property definition', () => { @@ -1326,7 +1330,7 @@ describe('validateDataContractFactory', function main() { expect(error.instancePath).to.equal( '/documents/indexedDocument/indices/0/properties/0', ); - expect(error.keyword).to.equal('type'); + expect(error.getKeyword()).to.equal('type'); }); it('should have at least one property', async () => { @@ -1342,7 +1346,7 @@ describe('validateDataContractFactory', function main() { expect(error.instancePath).to.equal( '/documents/indexedDocument/indices/0/properties', ); - expect(error.keyword).to.equal('minItems'); + expect(error.getKeyword()).to.equal('minItems'); }); it('should have no more than one property', async () => { @@ -1360,7 +1364,7 @@ describe('validateDataContractFactory', function main() { expect(error.instancePath).to.equal( '/documents/indexedDocument/indices/0/properties/0', ); - expect(error.keyword).to.equal('maxProperties'); + expect(error.getKeyword()).to.equal('maxProperties'); }); it('should have property values only "asc" or "desc"', async () => { @@ -1376,7 +1380,7 @@ describe('validateDataContractFactory', function main() { expect(error.instancePath).to.equal( '/documents/indexedDocument/indices/0/properties/0/$ownerId', ); - expect(error.keyword).to.equal('enum'); + expect(error.getKeyword()).to.equal('enum'); }); }); }); @@ -1391,7 +1395,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/documents/indexedDocument/indices/0/unique'); - expect(error.keyword).to.equal('type'); + expect(error.getKeyword()).to.equal('type'); }); it('should have no more than 10 indices', async () => { @@ -1414,7 +1418,7 @@ describe('validateDataContractFactory', function main() { expect(error.instancePath).to.equal( '/documents/indexedDocument/indices', ); - expect(error.keyword).to.equal('maxItems'); + expect(error.getKeyword()).to.equal('maxItems'); }); it('should have no more than 3 unique indices', async () => { @@ -1438,7 +1442,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.getRawDataContract()).to.equal(rawDataContract); + expect(error.getCode()).to.equal(1017); expect(error.getDocumentType()).to.equal('indexedDocument'); }); @@ -1459,8 +1463,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(1015); expect(error.getPropertyName()).to.equal('$id'); - expect(error.getRawDataContract()).to.deep.equal(rawDataContract); expect(error.getDocumentType()).to.deep.equal('indexedDocument'); expect(error.getIndexDefinition()).to.deep.equal(indexDefinition); }); @@ -1478,8 +1482,8 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(1016); expect(error.getPropertyName()).to.equal('missingProperty'); - expect(error.getRawDataContract()).to.deep.equal(rawDataContract); expect(error.getDocumentType()).to.deep.equal('indexedDocument'); expect(error.getIndexDefinition()).to.deep.equal(indexDefinition); }); @@ -1511,9 +1515,9 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(1013); expect(error.getPropertyName()).to.equal('objectProperty'); expect(error.getPropertyType()).to.equal('object'); - expect(error.getRawDataContract()).to.deep.equal(rawDataContract); expect(error.getDocumentType()).to.deep.equal('indexedDocument'); expect(error.getIndexDefinition()).to.deep.equal(indexDefinition); }); @@ -1548,9 +1552,9 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(1013); expect(error.getPropertyName()).to.equal('arrayProperty'); expect(error.getPropertyType()).to.equal('array'); - expect(error.getRawDataContract()).to.deep.equal(rawDataContract); expect(error.getDocumentType()).to.deep.equal('indexedDocument'); expect(error.getIndexDefinition()).to.deep.equal(indexDefinition); }); @@ -1574,10 +1578,11 @@ describe('validateDataContractFactory', function main() { const result = await validateDataContract(rawDataContract); expectValidationError(result, InvalidIndexPropertyTypeError); - const [error] = result.getErrors(); + const error = result.getFirstError(); + + expect(error.getCode()).to.equal(1013); expect(error.getPropertyName()).to.equal('mentions'); expect(error.getPropertyType()).to.equal('array'); - expect(error.getRawDataContract()).to.deep.equal(rawDataContract); expect(error.getDocumentType()).to.deep.equal('indexedArray'); expect(error.getIndexDefinition()).to.deep.equal(indexDefinition); }); @@ -1599,10 +1604,11 @@ describe('validateDataContractFactory', function main() { const result = await validateDataContract(rawDataContract); expectValidationError(result, InvalidIndexPropertyTypeError); - const [error] = result.getErrors(); + const error = result.getFirstError(); + + expect(error.getCode()).to.equal(1013); expect(error.getPropertyName()).to.equal('mentions'); expect(error.getPropertyType()).to.equal('array'); - expect(error.getRawDataContract()).to.deep.equal(rawDataContract); expect(error.getDocumentType()).to.deep.equal('indexedArray'); expect(error.getIndexDefinition()).to.deep.equal(indexDefinition); }); @@ -1627,10 +1633,11 @@ describe('validateDataContractFactory', function main() { const result = await validateDataContract(rawDataContract); expectValidationError(result, InvalidIndexPropertyTypeError); - const [error] = result.getErrors(); + const error = result.getFirstError(); + + expect(error.getCode()).to.equal(1013); expect(error.getPropertyName()).to.equal('mentions'); expect(error.getPropertyType()).to.equal('array'); - expect(error.getRawDataContract()).to.deep.equal(rawDataContract); expect(error.getDocumentType()).to.deep.equal('indexedArray'); expect(error.getIndexDefinition()).to.deep.equal(indexDefinition); }); @@ -1662,9 +1669,9 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(1013); expect(error.getPropertyName()).to.equal('arrayProperty'); expect(error.getPropertyType()).to.equal('array'); - expect(error.getRawDataContract()).to.deep.equal(rawDataContract); expect(error.getDocumentType()).to.deep.equal('indexedDocument'); expect(error.getIndexDefinition()).to.deep.equal(indexDefinition); }); @@ -1700,9 +1707,9 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(1013); expect(error.getPropertyName()).to.equal('arrayProperty'); expect(error.getPropertyType()).to.equal('array'); - expect(error.getRawDataContract()).to.deep.equal(rawDataContract); expect(error.getDocumentType()).to.deep.equal('indexedDocument'); expect(error.getIndexDefinition()).to.deep.equal(indexDefinition); }); @@ -1716,6 +1723,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(1010); expect(error.getIndexDefinition()).to.deep.equal( rawDataContract.documents.optionalUniqueIndexedDocument.indices[1], ); @@ -1743,7 +1751,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.keyword).to.equal('type'); + expect(error.getKeyword()).to.equal('type'); expect(error.instancePath).to.equal('/documents/niceDocument/dependentSchemas'); expect(error.message).to.equal('must be object'); }); @@ -1768,7 +1776,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.keyword).to.equal('type'); + expect(error.getKeyword()).to.equal('type'); expect(error.instancePath).to.equal('/documents/niceDocument/dependentRequired'); expect(error.message).to.equal('must be object'); }); @@ -1795,7 +1803,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.keyword).to.equal('type'); + expect(error.getKeyword()).to.equal('type'); expect(error.instancePath).to.equal('/documents/niceDocument/dependentRequired/zxy'); expect(error.message).to.equal('must be array'); }); @@ -1820,7 +1828,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.keyword).to.equal('type'); + expect(error.getKeyword()).to.equal('type'); expect(error.instancePath).to.equal('/documents/niceDocument/dependentRequired/zxy/0'); expect(error.message).to.equal('must be string'); }); @@ -1845,7 +1853,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); - expect(error.keyword).to.equal('uniqueItems'); + expect(error.getKeyword()).to.equal('uniqueItems'); expect(error.instancePath).to.equal('/documents/niceDocument/dependentRequired/zxy'); expect(error.message).to.equal('must NOT have duplicate items (items ## 2 and 1 are identical)'); }); @@ -1856,13 +1864,13 @@ describe('validateDataContractFactory', function main() { const result = await validateDataContract(rawDataContract); - expectJsonSchemaError(result); + expectValidationError(result, InvalidJsonSchemaRefError); const [error] = result.getErrors(); - expect(error.message).to.be.a('string').and.satisfy((msg) => ( - msg.startsWith('Circular $ref pointer') - )); + expect(error.getCode()).to.equal(1014); + + expect(error.message).to.startsWith('Invalid JSON Schema $ref: Circular $ref pointer found'); }); it('should return invalid result if indexed property missing maxLength constraint', async () => { @@ -1874,6 +1882,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(1012); expect(error.getPropertyName()).to.equal('firstName'); expect(error.getConstraintName()).to.equal('maxLength'); expect(error.getReason()).to.equal('should be set'); @@ -1888,6 +1897,7 @@ describe('validateDataContractFactory', function main() { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(1012); expect(error.getPropertyName()).to.equal('firstName'); expect(error.getConstraintName()).to.equal('maxLength'); expect(error.getReason()).to.equal('should be less or equal 1024'); diff --git a/test/integration/document/stateTransition/DocumentsBatchTransition/validation/basic/validateDocumentsBatchTransitionBasicFactory.spec.js b/test/integration/document/stateTransition/DocumentsBatchTransition/validation/basic/validateDocumentsBatchTransitionBasicFactory.spec.js index e934624c..a3d9bd7a 100644 --- a/test/integration/document/stateTransition/DocumentsBatchTransition/validation/basic/validateDocumentsBatchTransitionBasicFactory.spec.js +++ b/test/integration/document/stateTransition/DocumentsBatchTransition/validation/basic/validateDocumentsBatchTransitionBasicFactory.spec.js @@ -24,8 +24,6 @@ const { expectValidationError, expectJsonSchemaError } = require('../../../../.. const createStateRepositoryMock = require('../../../../../../../lib/test/mocks/createStateRepositoryMock'); -const ConsensusError = require('../../../../../../../lib/errors/consensus/ConsensusError'); -const DuplicateDocumentTransitionsError = require('../../../../../../../lib/errors/consensus/basic/document/DuplicateDocumentTransitionsError'); const InvalidDocumentTransitionIdError = require('../../../../../../../lib/errors/consensus/basic/document/InvalidDocumentTransitionIdError'); const DataContractNotPresentError = require('../../../../../../../lib/errors/consensus/basic/document/DataContractNotPresentError'); const MissingDataContractIdError = require('../../../../../../../lib/errors/consensus/basic/document/MissingDataContractIdError'); @@ -34,7 +32,9 @@ const InvalidDocumentTypeError = require('../../../../../../../lib/errors/consen const MissingDocumentTransitionActionError = require('../../../../../../../lib/errors/consensus/basic/document/MissingDocumentTransitionActionError'); const InvalidDocumentTransitionActionError = require('../../../../../../../lib/errors/consensus/basic/document/InvalidDocumentTransitionActionError'); const InvalidIdentifierError = require('../../../../../../../lib/errors/consensus/basic/InvalidIdentifierError'); -const IdentifierError = require('../../../../../../../lib/identifier/errors/IdentifierError'); +const DuplicateDocumentTransitionsWithIndicesError = require('../../../../../../../lib/errors/consensus/basic/document/DuplicateDocumentTransitionsWithIndicesError'); +const DuplicateDocumentTransitionsWithIdsError = require('../../../../../../../lib/errors/consensus/basic/document/DuplicateDocumentTransitionsWithIdsError'); +const SomeConsensusError = require('../../../../../../../lib/test/mocks/SomeConsensusError'); describe('validateDocumentsBatchTransitionBasicFactory', () => { let dataContract; @@ -112,9 +112,9 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('protocolVersion'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('protocolVersion'); }); it('should be an integer', async () => { @@ -126,8 +126,8 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/protocolVersion'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/protocolVersion'); + expect(error.getKeyword()).to.equal('type'); }); it('should not be less than 0', async () => { @@ -139,8 +139,8 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.keyword).to.equal('minimum'); - expect(error.instancePath).to.equal('/protocolVersion'); + expect(error.getKeyword()).to.equal('minimum'); + expect(error.getInstancePath()).to.equal('/protocolVersion'); }); it('should not be greater than current version (0)', async () => { @@ -152,8 +152,8 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.keyword).to.equal('maximum'); - expect(error.instancePath).to.equal('/protocolVersion'); + expect(error.getKeyword()).to.equal('maximum'); + expect(error.getInstancePath()).to.equal('/protocolVersion'); }); }); @@ -167,9 +167,9 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('type'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('type'); }); it('should be equal 1', async () => { @@ -181,9 +181,9 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/type'); - expect(error.keyword).to.equal('const'); - expect(error.params.allowedValue).to.equal(1); + expect(error.getInstancePath()).to.equal('/type'); + expect(error.getKeyword()).to.equal('const'); + expect(error.getParams().allowedValue).to.equal(1); }); }); @@ -199,9 +199,9 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('ownerId'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('ownerId'); }); it('should be a byte array', async () => { @@ -215,10 +215,10 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error, byteArrayError] = result.getErrors(); - expect(error.instancePath).to.equal('/ownerId/0'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/ownerId/0'); + expect(error.getKeyword()).to.equal('type'); - expect(byteArrayError.keyword).to.equal('byteArray'); + expect(byteArrayError.getKeyword()).to.equal('byteArray'); }); it('should be no less than 32 bytes', async () => { @@ -233,7 +233,7 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/ownerId'); - expect(error.keyword).to.equal('minItems'); + expect(error.getKeyword()).to.equal('minItems'); }); it('should be no longer than 32 bytes', async () => { @@ -248,7 +248,7 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/ownerId'); - expect(error.keyword).to.equal('maxItems'); + expect(error.getKeyword()).to.equal('maxItems'); }); }); @@ -265,8 +265,8 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('transitions'); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('transitions'); }); it('should be an array', async () => { @@ -281,7 +281,7 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/transitions'); - expect(error.keyword).to.equal('type'); + expect(error.getKeyword()).to.equal('type'); }); it('should have at least one element', async () => { @@ -296,8 +296,8 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/transitions'); - expect(error.keyword).to.equal('minItems'); - expect(error.params.limit).to.equal(1); + expect(error.getKeyword()).to.equal('minItems'); + expect(error.getParams().limit).to.equal(1); }); it('should have no more than 10 elements', async () => { @@ -310,8 +310,8 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/transitions'); - expect(error.keyword).to.equal('maxItems'); - expect(error.params.limit).to.equal(10); + expect(error.getKeyword()).to.equal('maxItems'); + expect(error.getParams().limit).to.equal(10); }); it('should have objects as elements', async () => { @@ -324,7 +324,7 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/transitions/0'); - expect(error.keyword).to.equal('type'); + expect(error.getKeyword()).to.equal('type'); }); describe('document transition', () => { @@ -341,8 +341,8 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('$id'); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('$id'); }); it('should be a byte array', async () => { @@ -357,9 +357,9 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error, byteArrayError] = result.getErrors(); expect(error.instancePath).to.equal('/$id/0'); - expect(error.keyword).to.equal('type'); + expect(error.getKeyword()).to.equal('type'); - expect(byteArrayError.keyword).to.equal('byteArray'); + expect(byteArrayError.getKeyword()).to.equal('byteArray'); }); it('should be no less than 32 bytes', async () => { @@ -374,8 +374,8 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/$id'); - expect(error.keyword).to.equal('minItems'); - expect(error.params.limit).to.equal(32); + expect(error.getKeyword()).to.equal('minItems'); + expect(error.getParams().limit).to.equal(32); }); it('should be no longer than 32 bytes', async () => { @@ -390,8 +390,8 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/$id'); - expect(error.keyword).to.equal('maxItems'); - expect(error.params.limit).to.equal(32); + expect(error.getKeyword()).to.equal('maxItems'); + expect(error.getParams().limit).to.equal(32); }); it('should no have duplicate IDs in the state transition', async () => { @@ -401,11 +401,14 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const result = await validateDocumentsBatchTransitionBasic(rawStateTransition); - expectValidationError(result, DuplicateDocumentTransitionsError); + expectValidationError(result, DuplicateDocumentTransitionsWithIdsError); const [error] = result.getErrors(); - expect(error.getRawDocumentTransitions()).to.deep.equal(duplicates); + expect(error.getCode()).to.equal(1019); + expect(error.getDocumentTransitionReferences()).to.deep.equal( + duplicates.map((d) => [d.$type, d.$id]), + ); expect(stateRepositoryMock.fetchDataContract).to.have.been.calledOnceWithExactly( dataContract.getId(), @@ -432,7 +435,7 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.getRawDocument()).to.equal(firstDocumentTransition); + expect(error.getCode()).to.equal(1025); expect(stateRepositoryMock.fetchDataContract).to.have.been.calledOnceWithExactly( dataContract.getId(), @@ -459,8 +462,11 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(1006); + expect(error.getIdentifierName()).to.equal('$dataContractId'); - expect(error.getIdentifierError()).to.be.instanceOf(IdentifierError); + + expect(error.getIdentifierError()).to.be.instanceOf(Error); expect(error.getIdentifierError().message).to.equal('Identifier expects Buffer'); expect(stateRepositoryMock.fetchDataContract).to.have.been.calledOnceWithExactly( @@ -486,6 +492,7 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(1018); expect(error.getDataContractId()).to.deep.equal(dataContract.getId()); expect(stateRepositoryMock.fetchDataContract).to.have.been.calledOnceWithExactly( @@ -510,7 +517,7 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.getRawDocument()).to.equal(firstDocumentTransition); + expect(error.getCode()).to.equal(1027); expect(stateRepositoryMock.fetchDataContract).to.have.been.calledOnceWithExactly( dataContract.getId(), @@ -532,8 +539,11 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(1024); expect(error.getType()).to.equal(firstDocumentTransition.$type); - expect(error.getDataContract()).to.equal(dataContract); + + expect(Buffer.isBuffer(error.getDataContractId())).to.be.true(); + expect(error.getDataContractId()).to.deep.equal(dataContract.getId().toBuffer()); expect(stateRepositoryMock.fetchDataContract).to.have.been.calledOnceWithExactly( dataContract.getId(), @@ -557,7 +567,7 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.getRawDocumentTransition()).to.equal(firstDocumentTransition); + expect(error.getCode()).to.equal(1026); expect(stateRepositoryMock.fetchDataContract).to.have.been.calledOnceWithExactly( dataContract.getId(), @@ -596,6 +606,7 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { it('should be valid generated ID', async () => { const [firstTransition] = rawStateTransition.transitions; + const expectedId = firstTransition.$id; firstTransition.$id = generateRandomIdentifier(); const result = await validateDocumentsBatchTransitionBasic(rawStateTransition); @@ -604,7 +615,13 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.getRawDocumentTransition()).to.deep.equal(firstTransition); + expect(error.getCode()).to.equal(1023); + + expect(Buffer.isBuffer(error.getExpectedId())).to.be.true(); + expect(error.getExpectedId()).to.deep.equal(expectedId); + + expect(Buffer.isBuffer(error.getInvalidId())).to.be.true(); + expect(error.getInvalidId()).to.deep.equal(firstTransition.$id); expect(stateRepositoryMock.fetchDataContract).to.have.been.calledOnceWithExactly( dataContract.getId(), @@ -630,8 +647,8 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('$entropy'); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('$entropy'); }); it('should be a byte array', async () => { @@ -646,9 +663,9 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error, byteArrayError] = result.getErrors(); expect(error.instancePath).to.equal('/$entropy/0'); - expect(error.keyword).to.equal('type'); + expect(error.getKeyword()).to.equal('type'); - expect(byteArrayError.keyword).to.equal('byteArray'); + expect(byteArrayError.getKeyword()).to.equal('byteArray'); }); it('should be no less than 32 bytes', async () => { @@ -663,8 +680,8 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/$entropy'); - expect(error.keyword).to.equal('minItems'); - expect(error.params.limit).to.equal(32); + expect(error.getKeyword()).to.equal('minItems'); + expect(error.getParams().limit).to.equal(32); }); it('should be no longer than 32 bytes', async () => { @@ -679,8 +696,8 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/$entropy'); - expect(error.keyword).to.equal('maxItems'); - expect(error.params.limit).to.equal(32); + expect(error.getKeyword()).to.equal('maxItems'); + expect(error.getParams().limit).to.equal(32); }); }); }); @@ -716,8 +733,8 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.params.missingProperty).to.equal('$revision'); - expect(error.keyword).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('$revision'); + expect(error.getKeyword()).to.equal('required'); }); it('should be a number', async () => { @@ -732,7 +749,7 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/$revision'); - expect(error.keyword).to.equal('type'); + expect(error.getKeyword()).to.equal('type'); }); it('should be multiple of 1.0', async () => { @@ -747,7 +764,7 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/$revision'); - expect(error.keyword).to.equal('type'); + expect(error.getKeyword()).to.equal('type'); }); it('should have a minimum value of 1', async () => { @@ -762,11 +779,47 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/$revision'); - expect(error.keyword).to.equal('minimum'); + expect(error.getKeyword()).to.equal('minimum'); }); }); }); + describe('delete', () => { + beforeEach(() => { + documentTransitions = getDocumentTransitionsFixture({ + create: [], + replace: [], + delete: documents, + }); + + stateTransition = new DocumentsBatchTransition({ + protocolVersion: protocolVersion.latestVersion, + ownerId, + contractId: dataContract.getId(), + transitions: documentTransitions.map((t) => t.toObject()), + signature: Buffer.alloc(65), + signaturePublicKeyId: 0, + }, [dataContract]); + + rawStateTransition = stateTransition.toObject(); + }); + + it('should return invalid result if delete transaction is not valid', async () => { + const [documentTransition] = rawStateTransition.transitions; + + delete documentTransition.$id; + + const result = await validateDocumentsBatchTransitionBasic(rawStateTransition); + + expectJsonSchemaError(result); + + const [error] = result.getErrors(); + + expect(error.getParams().missingProperty).to.equal('$id'); + expect(error.getKeyword()).to.equal('required'); + }); + }); + it('should return invalid result if there are duplicate unique index values', async () => { const duplicates = [documentTransitions[1].toObject()]; @@ -774,11 +827,15 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const result = await validateDocumentsBatchTransitionBasic(rawStateTransition); - expectValidationError(result, DuplicateDocumentTransitionsError); + expectValidationError(result, DuplicateDocumentTransitionsWithIndicesError); const [error] = result.getErrors(); - expect(error.getRawDocumentTransitions()).to.deep.equal(duplicates); + expect(error.getCode()).to.equal(1020); + + expect(error.getDocumentTransitionReferences()).to.deep.equal( + duplicates.map((d) => [d.$type, d.$id]), + ); expect(stateRepositoryMock.fetchDataContract).to.have.been.calledOnceWithExactly( dataContract.getId(), @@ -793,7 +850,7 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { }); it('should return invalid result if compound index doesn\'t contain all fields', async () => { - const consensusError = new ConsensusError('error'); + const consensusError = new SomeConsensusError('error'); validatePartialCompoundIndicesMock.returns( new ValidationResult([consensusError]), @@ -832,8 +889,8 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('signature'); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('signature'); }); it('should be a byte array', async () => { @@ -846,9 +903,9 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error, byteArrayError] = result.getErrors(); expect(error.instancePath).to.equal('/signature/0'); - expect(error.keyword).to.equal('type'); + expect(error.getKeyword()).to.equal('type'); - expect(byteArrayError.keyword).to.equal('byteArray'); + expect(byteArrayError.getKeyword()).to.equal('byteArray'); }); it('should be not less than 65 bytes', async () => { @@ -861,8 +918,8 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/signature'); - expect(error.keyword).to.equal('minItems'); - expect(error.params.limit).to.equal(65); + expect(error.getKeyword()).to.equal('minItems'); + expect(error.getParams().limit).to.equal(65); }); it('should be not longer than 65 bytes', async () => { @@ -875,8 +932,8 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/signature'); - expect(error.keyword).to.equal('maxItems'); - expect(error.params.limit).to.equal(65); + expect(error.getKeyword()).to.equal('maxItems'); + expect(error.getParams().limit).to.equal(65); }); }); @@ -891,7 +948,7 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/signaturePublicKeyId'); - expect(error.keyword).to.equal('type'); + expect(error.getKeyword()).to.equal('type'); }); it('should not be < 0', async () => { @@ -904,7 +961,7 @@ describe('validateDocumentsBatchTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/signaturePublicKeyId'); - expect(error.keyword).to.equal('minimum'); + expect(error.getKeyword()).to.equal('minimum'); }); }); diff --git a/test/integration/document/validation/validateDocumentFactory.spec.js b/test/integration/document/validation/validateDocumentFactory.spec.js index 02c9f565..c60e5e78 100644 --- a/test/integration/document/validation/validateDocumentFactory.spec.js +++ b/test/integration/document/validation/validateDocumentFactory.spec.js @@ -60,9 +60,9 @@ describe('validateDocumentFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('$protocolVersion'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('$protocolVersion'); }); it('should be an integer', () => { @@ -74,8 +74,8 @@ describe('validateDocumentFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/$protocolVersion'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/$protocolVersion'); + expect(error.getKeyword()).to.equal('type'); }); it('should not be less than 0', () => { @@ -87,8 +87,8 @@ describe('validateDocumentFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/$protocolVersion'); - expect(error.keyword).to.equal('minimum'); + expect(error.getInstancePath()).to.equal('/$protocolVersion'); + expect(error.getKeyword()).to.equal('minimum'); }); it('should not be greater than current Document protocol version (0)', () => { @@ -100,8 +100,8 @@ describe('validateDocumentFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/$protocolVersion'); - expect(error.keyword).to.equal('maximum'); + expect(error.getInstancePath()).to.equal('/$protocolVersion'); + expect(error.getKeyword()).to.equal('maximum'); }); }); @@ -115,9 +115,9 @@ describe('validateDocumentFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('$id'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('$id'); }); it('should be a byte array', () => { @@ -129,10 +129,10 @@ describe('validateDocumentFactory', () => { const [error, byteArrayError] = result.getErrors(); - expect(error.instancePath).to.equal('/$id/0'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/$id/0'); + expect(error.getKeyword()).to.equal('type'); - expect(byteArrayError.keyword).to.equal('byteArray'); + expect(byteArrayError.getKeyword()).to.equal('byteArray'); }); it('should be no less than 32 bytes', () => { @@ -144,8 +144,8 @@ describe('validateDocumentFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/$id'); - expect(error.keyword).to.equal('minItems'); + expect(error.getInstancePath()).to.equal('/$id'); + expect(error.getKeyword()).to.equal('minItems'); }); it('should be no longer than 32 bytes', () => { @@ -157,8 +157,8 @@ describe('validateDocumentFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/$id'); - expect(error.keyword).to.equal('maxItems'); + expect(error.getInstancePath()).to.equal('/$id'); + expect(error.getKeyword()).to.equal('maxItems'); }); }); @@ -175,7 +175,7 @@ describe('validateDocumentFactory', () => { const [error] = result.getErrors(); - expect(error.getRawDocument()).to.equal(rawDocument); + expect(error.getCode()).to.equal(1028); }); it('should be defined in Data Contract', () => { @@ -190,6 +190,7 @@ describe('validateDocumentFactory', () => { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(1024); expect(error.getType()).to.equal('undefinedDocument'); }); @@ -221,9 +222,9 @@ describe('validateDocumentFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('$revision'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('$revision'); }); it('should be a number', () => { @@ -235,8 +236,8 @@ describe('validateDocumentFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/$revision'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/$revision'); + expect(error.getKeyword()).to.equal('type'); }); it('should be an integer', () => { @@ -248,8 +249,8 @@ describe('validateDocumentFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/$revision'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/$revision'); + expect(error.getKeyword()).to.equal('type'); }); it('should be greater or equal to one', () => { @@ -261,8 +262,8 @@ describe('validateDocumentFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/$revision'); - expect(error.keyword).to.equal('minimum'); + expect(error.getInstancePath()).to.equal('/$revision'); + expect(error.getKeyword()).to.equal('minimum'); }); }); @@ -276,9 +277,9 @@ describe('validateDocumentFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('$dataContractId'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('$dataContractId'); }); it('should be a byte array', () => { @@ -290,10 +291,10 @@ describe('validateDocumentFactory', () => { const [error, byteArrayError] = result.getErrors(); - expect(error.instancePath).to.equal('/$dataContractId/0'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/$dataContractId/0'); + expect(error.getKeyword()).to.equal('type'); - expect(byteArrayError.keyword).to.equal('byteArray'); + expect(byteArrayError.getKeyword()).to.equal('byteArray'); }); it('should be no less than 32 bytes', () => { @@ -305,8 +306,8 @@ describe('validateDocumentFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/$dataContractId'); - expect(error.keyword).to.equal('minItems'); + expect(error.getInstancePath()).to.equal('/$dataContractId'); + expect(error.getKeyword()).to.equal('minItems'); }); it('should be no longer than 32 bytes', () => { @@ -318,8 +319,8 @@ describe('validateDocumentFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/$dataContractId'); - expect(error.keyword).to.equal('maxItems'); + expect(error.getInstancePath()).to.equal('/$dataContractId'); + expect(error.getKeyword()).to.equal('maxItems'); }); }); @@ -333,9 +334,9 @@ describe('validateDocumentFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('$ownerId'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('$ownerId'); }); it('should be a byte array', () => { @@ -348,9 +349,9 @@ describe('validateDocumentFactory', () => { const [error, byteArrayError] = result.getErrors(); expect(error.instancePath).to.equal('/$ownerId/0'); - expect(error.keyword).to.equal('type'); + expect(error.getKeyword()).to.equal('type'); - expect(byteArrayError.keyword).to.equal('byteArray'); + expect(byteArrayError.getKeyword()).to.equal('byteArray'); }); it('should be no less than 32 bytes', () => { @@ -363,7 +364,7 @@ describe('validateDocumentFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/$ownerId'); - expect(error.keyword).to.equal('minItems'); + expect(error.getKeyword()).to.equal('minItems'); }); it('should be no longer than 32 bytes', () => { @@ -376,7 +377,7 @@ describe('validateDocumentFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/$ownerId'); - expect(error.keyword).to.equal('maxItems'); + expect(error.getKeyword()).to.equal('maxItems'); }); }); }); @@ -392,7 +393,7 @@ describe('validateDocumentFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/name'); - expect(error.keyword).to.equal('type'); + expect(error.getKeyword()).to.equal('type'); }); it('should return an error if the second document is not valid against Data Contract', () => { @@ -407,7 +408,7 @@ describe('validateDocumentFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('additionalProperties'); + expect(error.getKeyword()).to.equal('additionalProperties'); }); }); @@ -424,7 +425,7 @@ describe('validateDocumentFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/byteArrayField'); - expect(error.keyword).to.equal('maxItems'); + expect(error.getKeyword()).to.equal('maxItems'); }); it('should return valid result is a document is valid', () => { diff --git a/test/integration/error/consensus/createConsensusError.spec.js b/test/integration/error/consensus/createConsensusError.spec.js new file mode 100644 index 00000000..a24895a7 --- /dev/null +++ b/test/integration/error/consensus/createConsensusError.spec.js @@ -0,0 +1,21 @@ +const InvalidDataContractIdError = require('../../../../lib/errors/consensus/basic/dataContract/InvalidDataContractIdError'); +const generateRandomIdentifier = require('../../../../lib/test/utils/generateRandomIdentifier'); +const createConsensusError = require('../../../../lib/errors/consensus/createConsensusError'); + +describe('createConsensusError', () => { + it('should create an error instance from code and arguments', () => { + const expectedId = generateRandomIdentifier(); + const invalidId = Buffer.alloc(16).fill(1); + + const error = new InvalidDataContractIdError(expectedId.toBuffer(), invalidId); + + const restoredError = createConsensusError(error.getCode(), error.getConstructorArguments()); + + // Stack will be always different so we need to skip it for comparison + expect(restoredError.message).to.equal(error.message); + expect(restoredError.getExpectedId()).to.deep.equal(error.getExpectedId()); + expect(restoredError.getInvalidId()).to.deep.equal(error.getInvalidId()); + expect(restoredError.getConstructorArguments()).to.deep.equal(error.getConstructorArguments()); + expect(restoredError.getCode()).to.deep.equal(error.getCode()); + }); +}); diff --git a/test/integration/identity/stateTransition/IdentityCreateTransition/validation/basic/validateIdentityCreateTransitionBasicFactory.spec.js b/test/integration/identity/stateTransition/IdentityCreateTransition/validation/basic/validateIdentityCreateTransitionBasicFactory.spec.js index 8ca83077..18867347 100644 --- a/test/integration/identity/stateTransition/IdentityCreateTransition/validation/basic/validateIdentityCreateTransitionBasicFactory.spec.js +++ b/test/integration/identity/stateTransition/IdentityCreateTransition/validation/basic/validateIdentityCreateTransitionBasicFactory.spec.js @@ -16,9 +16,9 @@ const { } = require('../../../../../../../lib/test/expect/expectError'); const ValidationResult = require('../../../../../../../lib/validation/ValidationResult'); -const ConsensusError = require('../../../../../../../lib/errors/consensus/ConsensusError'); const InstantAssetLockProof = require('../../../../../../../lib/identity/stateTransition/assetLockProof/instant/InstantAssetLockProof'); const ChainAssetLockProof = require('../../../../../../../lib/identity/stateTransition/assetLockProof/chain/ChainAssetLockProof'); +const SomeConsensusError = require('../../../../../../../lib/test/mocks/SomeConsensusError'); describe('validateIdentityCreateTransitionBasicFactory', () => { let validateIdentityCreateTransitionBasic; @@ -76,9 +76,9 @@ describe('validateIdentityCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('protocolVersion'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('protocolVersion'); }); it('should be an integer', async () => { @@ -90,8 +90,8 @@ describe('validateIdentityCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/protocolVersion'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/protocolVersion'); + expect(error.getKeyword()).to.equal('type'); }); it('should not be less than 0', async () => { @@ -103,8 +103,8 @@ describe('validateIdentityCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.keyword).to.equal('minimum'); - expect(error.instancePath).to.equal('/protocolVersion'); + expect(error.getKeyword()).to.equal('minimum'); + expect(error.getInstancePath()).to.equal('/protocolVersion'); }); it('should not be greater than current version (0)', async () => { @@ -116,8 +116,8 @@ describe('validateIdentityCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.keyword).to.equal('maximum'); - expect(error.instancePath).to.equal('/protocolVersion'); + expect(error.getKeyword()).to.equal('maximum'); + expect(error.getInstancePath()).to.equal('/protocolVersion'); }); }); @@ -131,9 +131,9 @@ describe('validateIdentityCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('type'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('type'); }); it('should be equal to 2', async () => { @@ -145,9 +145,9 @@ describe('validateIdentityCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/type'); - expect(error.keyword).to.equal('const'); - expect(error.params.allowedValue).to.equal(2); + expect(error.getInstancePath()).to.equal('/type'); + expect(error.getKeyword()).to.equal('const'); + expect(error.getParams().allowedValue).to.equal(2); }); }); @@ -163,9 +163,9 @@ describe('validateIdentityCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.params.missingProperty).to.equal('assetLockProof'); - expect(error.keyword).to.equal('required'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getParams().missingProperty).to.equal('assetLockProof'); + expect(error.getKeyword()).to.equal('required'); }); it('should be an object', async () => { @@ -177,12 +177,12 @@ describe('validateIdentityCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/assetLockProof'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/assetLockProof'); + expect(error.getKeyword()).to.equal('type'); }); it('should be valid', async () => { - const assetLockError = new ConsensusError('test'); + const assetLockError = new SomeConsensusError('test'); const assetLockResult = new ValidationResult([ assetLockError, ]); @@ -218,9 +218,9 @@ describe('validateIdentityCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.params.missingProperty).to.equal('publicKeys'); - expect(error.keyword).to.equal('required'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getParams().missingProperty).to.equal('publicKeys'); + expect(error.getKeyword()).to.equal('required'); }); it('should not be empty', async () => { @@ -234,8 +234,8 @@ describe('validateIdentityCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.keyword).to.equal('minItems'); - expect(error.instancePath).to.equal('/publicKeys'); + expect(error.getKeyword()).to.equal('minItems'); + expect(error.getInstancePath()).to.equal('/publicKeys'); }); it('should not have more than 10 items', async () => { @@ -253,8 +253,8 @@ describe('validateIdentityCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.keyword).to.equal('maxItems'); - expect(error.instancePath).to.equal('/publicKeys'); + expect(error.getKeyword()).to.equal('maxItems'); + expect(error.getInstancePath()).to.equal('/publicKeys'); }); it('should be unique', async () => { @@ -268,12 +268,12 @@ describe('validateIdentityCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.keyword).to.equal('uniqueItems'); - expect(error.instancePath).to.equal('/publicKeys'); + expect(error.getKeyword()).to.equal('uniqueItems'); + expect(error.getInstancePath()).to.equal('/publicKeys'); }); it('should be valid', async () => { - const publicKeysError = new ConsensusError('test'); + const publicKeysError = new SomeConsensusError('test'); const publicKeysResult = new ValidationResult([ publicKeysError, ]); @@ -305,8 +305,8 @@ describe('validateIdentityCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('signature'); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('signature'); }); it('should be a byte array', async () => { @@ -319,9 +319,9 @@ describe('validateIdentityCreateTransitionBasicFactory', () => { const [error, byteArrayError] = result.getErrors(); expect(error.instancePath).to.equal('/signature/0'); - expect(error.keyword).to.equal('type'); + expect(error.getKeyword()).to.equal('type'); - expect(byteArrayError.keyword).to.equal('byteArray'); + expect(byteArrayError.getKeyword()).to.equal('byteArray'); }); it('should be not shorter than 65 bytes', async () => { @@ -334,7 +334,7 @@ describe('validateIdentityCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/signature'); - expect(error.keyword).to.equal('minItems'); + expect(error.getKeyword()).to.equal('minItems'); }); it('should be not longer than 65 bytes', async () => { @@ -347,7 +347,7 @@ describe('validateIdentityCreateTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/signature'); - expect(error.keyword).to.equal('maxItems'); + expect(error.getKeyword()).to.equal('maxItems'); }); }); diff --git a/test/integration/identity/stateTransition/IdentityTopUpTransition/validation/basic/validateIdentityTopUpTransitionBasicFactory.spec.js b/test/integration/identity/stateTransition/IdentityTopUpTransition/validation/basic/validateIdentityTopUpTransitionBasicFactory.spec.js index e503bef2..74fdc6d3 100644 --- a/test/integration/identity/stateTransition/IdentityTopUpTransition/validation/basic/validateIdentityTopUpTransitionBasicFactory.spec.js +++ b/test/integration/identity/stateTransition/IdentityTopUpTransition/validation/basic/validateIdentityTopUpTransitionBasicFactory.spec.js @@ -17,9 +17,9 @@ const { const ValidationResult = require('../../../../../../../lib/validation/ValidationResult'); -const ConsensusError = require('../../../../../../../lib/errors/consensus/ConsensusError'); const ChainAssetLockProof = require('../../../../../../../lib/identity/stateTransition/assetLockProof/chain/ChainAssetLockProof'); const InstantAssetLockProof = require('../../../../../../../lib/identity/stateTransition/assetLockProof/instant/InstantAssetLockProof'); +const SomeConsensusError = require('../../../../../../../lib/test/mocks/SomeConsensusError'); describe('validateIdentityTopUpTransitionBasicFactory', () => { let rawStateTransition; @@ -68,9 +68,9 @@ describe('validateIdentityTopUpTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('protocolVersion'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('protocolVersion'); }); it('should be an integer', async () => { @@ -82,8 +82,8 @@ describe('validateIdentityTopUpTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/protocolVersion'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/protocolVersion'); + expect(error.getKeyword()).to.equal('type'); }); it('should not be less than 0', async () => { @@ -95,8 +95,8 @@ describe('validateIdentityTopUpTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.keyword).to.equal('minimum'); - expect(error.instancePath).to.equal('/protocolVersion'); + expect(error.getKeyword()).to.equal('minimum'); + expect(error.getInstancePath()).to.equal('/protocolVersion'); }); it('should not be greater than current version (0)', async () => { @@ -108,8 +108,8 @@ describe('validateIdentityTopUpTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.keyword).to.equal('maximum'); - expect(error.instancePath).to.equal('/protocolVersion'); + expect(error.getKeyword()).to.equal('maximum'); + expect(error.getInstancePath()).to.equal('/protocolVersion'); }); }); @@ -123,9 +123,9 @@ describe('validateIdentityTopUpTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('type'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('type'); }); it('should be equal to 3', async () => { @@ -137,9 +137,9 @@ describe('validateIdentityTopUpTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/type'); - expect(error.keyword).to.equal('const'); - expect(error.params.allowedValue).to.equal(3); + expect(error.getInstancePath()).to.equal('/type'); + expect(error.getKeyword()).to.equal('const'); + expect(error.getParams().allowedValue).to.equal(3); }); }); @@ -155,9 +155,9 @@ describe('validateIdentityTopUpTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.params.missingProperty).to.equal('assetLockProof'); - expect(error.keyword).to.equal('required'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getParams().missingProperty).to.equal('assetLockProof'); + expect(error.getKeyword()).to.equal('required'); }); it('should be an object', async () => { @@ -169,12 +169,12 @@ describe('validateIdentityTopUpTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/assetLockProof'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/assetLockProof'); + expect(error.getKeyword()).to.equal('type'); }); it('should be valid', async () => { - const assetLockError = new ConsensusError('test'); + const assetLockError = new SomeConsensusError('test'); const assetLockResult = new ValidationResult([ assetLockError, ]); @@ -210,9 +210,9 @@ describe('validateIdentityTopUpTransitionBasicFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('identityId'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('identityId'); }); it('should be a byte array', async () => { @@ -226,10 +226,10 @@ describe('validateIdentityTopUpTransitionBasicFactory', () => { const [error, byteArrayError] = result.getErrors(); - expect(error.instancePath).to.equal('/identityId/0'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/identityId/0'); + expect(error.getKeyword()).to.equal('type'); - expect(byteArrayError.keyword).to.equal('byteArray'); + expect(byteArrayError.getKeyword()).to.equal('byteArray'); }); it('should be no less than 32 bytes', async () => { @@ -244,7 +244,7 @@ describe('validateIdentityTopUpTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/identityId'); - expect(error.keyword).to.equal('minItems'); + expect(error.getKeyword()).to.equal('minItems'); }); it('should be no longer than 32 bytes', async () => { @@ -259,7 +259,7 @@ describe('validateIdentityTopUpTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/identityId'); - expect(error.keyword).to.equal('maxItems'); + expect(error.getKeyword()).to.equal('maxItems'); }); }); @@ -274,8 +274,8 @@ describe('validateIdentityTopUpTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('signature'); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('signature'); }); it('should be a byte array', async () => { @@ -288,9 +288,9 @@ describe('validateIdentityTopUpTransitionBasicFactory', () => { const [error, byteArrayError] = result.getErrors(); expect(error.instancePath).to.equal('/signature/0'); - expect(error.keyword).to.equal('type'); + expect(error.getKeyword()).to.equal('type'); - expect(byteArrayError.keyword).to.equal('byteArray'); + expect(byteArrayError.getKeyword()).to.equal('byteArray'); }); it('should be not shorter than 65 bytes', async () => { @@ -303,7 +303,7 @@ describe('validateIdentityTopUpTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/signature'); - expect(error.keyword).to.equal('minItems'); + expect(error.getKeyword()).to.equal('minItems'); }); it('should be not longer than 65 bytes', async () => { @@ -316,7 +316,7 @@ describe('validateIdentityTopUpTransitionBasicFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/signature'); - expect(error.keyword).to.equal('maxItems'); + expect(error.getKeyword()).to.equal('maxItems'); }); }); diff --git a/test/integration/identity/stateTransition/assetLockProof/chain/validateChainAssetLockProofStructureFactory.spec.js b/test/integration/identity/stateTransition/assetLockProof/chain/validateChainAssetLockProofStructureFactory.spec.js index 03419f59..64a1ff9a 100644 --- a/test/integration/identity/stateTransition/assetLockProof/chain/validateChainAssetLockProofStructureFactory.spec.js +++ b/test/integration/identity/stateTransition/assetLockProof/chain/validateChainAssetLockProofStructureFactory.spec.js @@ -13,9 +13,9 @@ const { expectValidationError, expectJsonSchemaError } = require( const validateChainAssetLockProofStructureFactory = require('../../../../../../lib/identity/stateTransition/assetLockProof/chain/validateChainAssetLockProofStructureFactory'); const ValidationResult = require('../../../../../../lib/validation/ValidationResult'); const IdentityAssetLockTransactionIsNotFoundError = require('../../../../../../lib/errors/consensus/basic/identity/IdentityAssetLockTransactionIsNotFoundError'); -const ConsensusError = require('../../../../../../lib/errors/consensus/ConsensusError'); const InvalidAssetLockProofCoreChainHeightError = require('../../../../../../lib/errors/consensus/basic/identity/InvalidAssetLockProofCoreChainHeightError'); const InvalidAssetLockProofTransactionHeightError = require('../../../../../../lib/errors/consensus/basic/identity/InvalidAssetLockProofTransactionHeightError'); +const SomeConsensusError = require('../../../../../../lib/test/mocks/SomeConsensusError'); describe('validateChainAssetLockProofStructureFactory', () => { let rawProof; @@ -26,9 +26,11 @@ describe('validateChainAssetLockProofStructureFactory', () => { let validateAssetLockTransactionResult; let publicKeyHash; let rawTransaction; + let transactionHash; beforeEach(async function beforeEach() { rawTransaction = '030000000137feb5676d0851337ea3c9a992496aab7a0b3eee60aeeb9774000b7f4bababa5000000006b483045022100d91557de37645c641b948c6cd03b4ae3791a63a650db3e2fee1dcf5185d1b10402200e8bd410bf516ca61715867666d31e44495428ce5c1090bf2294a829ebcfa4ef0121025c3cc7fbfc52f710c941497fd01876c189171ea227458f501afcb38a297d65b4ffffffff021027000000000000166a14152073ca2300a86b510fa2f123d3ea7da3af68dcf77cb0090a0000001976a914152073ca2300a86b510fa2f123d3ea7da3af68dc88ac00000000'; + transactionHash = '6e200d059fb567ba19e92f5c2dcd3dde522fd4e0a50af223752db16158dabb1d'; const assetLock = getChainAssetLockFixture(); @@ -77,9 +79,9 @@ describe('validateChainAssetLockProofStructureFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('type'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('type'); expect(stateRepositoryMock.fetchTransaction).to.not.be.called(); expect(validateAssetLockTransactionMock).to.not.be.called(); @@ -95,8 +97,8 @@ describe('validateChainAssetLockProofStructureFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/type'); - expect(error.keyword).to.equal('const'); + expect(error.getInstancePath()).to.equal('/type'); + expect(error.getKeyword()).to.equal('const'); expect(stateRepositoryMock.fetchTransaction).to.not.be.called(); expect(stateRepositoryMock.fetchLatestPlatformBlockHeader).to.not.be.called(); @@ -113,9 +115,9 @@ describe('validateChainAssetLockProofStructureFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('coreChainLockedHeight'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('coreChainLockedHeight'); expect(stateRepositoryMock.fetchTransaction).to.not.be.called(); expect(validateAssetLockTransactionMock).to.not.be.called(); @@ -131,8 +133,8 @@ describe('validateChainAssetLockProofStructureFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/coreChainLockedHeight'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/coreChainLockedHeight'); + expect(error.getKeyword()).to.equal('type'); expect(stateRepositoryMock.fetchTransaction).to.not.be.called(); expect(validateAssetLockTransactionMock).to.not.be.called(); @@ -148,8 +150,8 @@ describe('validateChainAssetLockProofStructureFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/coreChainLockedHeight'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/coreChainLockedHeight'); + expect(error.getKeyword()).to.equal('type'); expect(stateRepositoryMock.fetchTransaction).to.not.be.called(); expect(validateAssetLockTransactionMock).to.not.be.called(); @@ -165,8 +167,8 @@ describe('validateChainAssetLockProofStructureFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/coreChainLockedHeight'); - expect(error.keyword).to.equal('minimum'); + expect(error.getInstancePath()).to.equal('/coreChainLockedHeight'); + expect(error.getKeyword()).to.equal('minimum'); expect(stateRepositoryMock.fetchTransaction).to.not.be.called(); expect(validateAssetLockTransactionMock).to.not.be.called(); @@ -183,7 +185,7 @@ describe('validateChainAssetLockProofStructureFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/coreChainLockedHeight'); - expect(error.keyword).to.equal('maximum'); + expect(error.getKeyword()).to.equal('maximum'); expect(stateRepositoryMock.fetchTransaction).to.not.be.called(); expect(validateAssetLockTransactionMock).to.not.be.called(); @@ -198,8 +200,10 @@ describe('validateChainAssetLockProofStructureFactory', () => { const result = await validateChainAssetLockProofStructure(rawProof); expectValidationError(result, InvalidAssetLockProofCoreChainHeightError); + const [error] = result.getErrors(); + expect(error.getCode()).to.equal(1035); expect(error.getProofCoreChainLockedHeight()).to.equal(42); expect(error.getCurrentCoreChainLockedHeight()).to.equal(41); }); @@ -216,8 +220,8 @@ describe('validateChainAssetLockProofStructureFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('outPoint'); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('outPoint'); expect(stateRepositoryMock.fetchTransaction).to.not.be.called(); expect(validateAssetLockTransactionMock).to.not.be.called(); @@ -234,9 +238,9 @@ describe('validateChainAssetLockProofStructureFactory', () => { const [error, byteArrayError] = result.getErrors(); expect(error.instancePath).to.equal('/outPoint/0'); - expect(error.keyword).to.equal('type'); + expect(error.getKeyword()).to.equal('type'); - expect(byteArrayError.keyword).to.equal('byteArray'); + expect(byteArrayError.getKeyword()).to.equal('byteArray'); expect(stateRepositoryMock.fetchTransaction).to.not.be.called(); expect(validateAssetLockTransactionMock).to.not.be.called(); @@ -253,7 +257,7 @@ describe('validateChainAssetLockProofStructureFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/outPoint'); - expect(error.keyword).to.equal('minItems'); + expect(error.getKeyword()).to.equal('minItems'); expect(stateRepositoryMock.fetchTransaction).to.not.be.called(); expect(validateAssetLockTransactionMock).to.not.be.called(); @@ -270,7 +274,7 @@ describe('validateChainAssetLockProofStructureFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/outPoint'); - expect(error.keyword).to.equal('maxItems'); + expect(error.getKeyword()).to.equal('maxItems'); expect(stateRepositoryMock.fetchTransaction).to.not.be.called(); expect(validateAssetLockTransactionMock).to.not.be.called(); @@ -283,24 +287,30 @@ describe('validateChainAssetLockProofStructureFactory', () => { const result = await validateChainAssetLockProofStructure(rawProof); expectValidationError(result, IdentityAssetLockTransactionIsNotFoundError); + const [error] = result.getErrors(); - expect(error.getOutPoint()).to.deep.equal(rawProof.outPoint); + expect(error.getCode()).to.equal(1032); + expect(error.getTransactionId()).to.deep.equal( + Buffer.from(transactionHash, 'hex'), + ); expect(stateRepositoryMock.fetchTransaction).to.be.calledOnceWithExactly( - '6e200d059fb567ba19e92f5c2dcd3dde522fd4e0a50af223752db16158dabb1d', + transactionHash, ); expect(validateAssetLockTransactionMock).to.not.be.called(); expect(stateRepositoryMock.fetchLatestPlatformBlockHeader).to.be.calledOnce(); }); it('should point to valid transaction', async () => { - const consensusError = new ConsensusError('test'); + const consensusError = new SomeConsensusError('test'); + validateAssetLockTransactionResult.addError(consensusError); const result = await validateChainAssetLockProofStructure(rawProof); - expectValidationError(result, ConsensusError); + expectValidationError(result, SomeConsensusError); + const [error] = result.getErrors(); expect(error).to.deep.equal(consensusError); @@ -315,13 +325,15 @@ describe('validateChainAssetLockProofStructureFactory', () => { const result = await validateChainAssetLockProofStructure(rawProof); expectValidationError(result, InvalidAssetLockProofTransactionHeightError); + const [error] = result.getErrors(); + expect(error.getCode()).to.equal(1036); expect(error.getProofCoreChainLockedHeight()).to.equal(41); expect(error.getTransactionHeight()).to.equal(42); expect(stateRepositoryMock.fetchTransaction).to.be.calledOnceWithExactly( - '6e200d059fb567ba19e92f5c2dcd3dde522fd4e0a50af223752db16158dabb1d', + transactionHash, ); expect(validateAssetLockTransactionMock).to.not.be.called(); expect(stateRepositoryMock.fetchLatestPlatformBlockHeader).to.be.calledOnce(); @@ -336,7 +348,7 @@ describe('validateChainAssetLockProofStructureFactory', () => { expect(result.getData()).to.deep.equal(publicKeyHash); expect(stateRepositoryMock.fetchTransaction).to.be.calledOnceWithExactly( - '6e200d059fb567ba19e92f5c2dcd3dde522fd4e0a50af223752db16158dabb1d', + transactionHash, ); expect(validateAssetLockTransactionMock).to.be.calledOnceWithExactly( Buffer.from(rawTransaction, 'hex'), diff --git a/test/integration/identity/stateTransition/assetLockProof/fetchAssetLockTransactionOutputFactory.spec.js b/test/integration/identity/stateTransition/assetLockProof/fetchAssetLockTransactionOutputFactory.spec.js index feada184..60503537 100644 --- a/test/integration/identity/stateTransition/assetLockProof/fetchAssetLockTransactionOutputFactory.spec.js +++ b/test/integration/identity/stateTransition/assetLockProof/fetchAssetLockTransactionOutputFactory.spec.js @@ -4,8 +4,9 @@ const fetchAssetLockTransactionOutputFactory = require('../../../../../lib/ident const getChainAssetLockFixture = require('../../../../../lib/test/fixtures/getChainAssetLockProofFixture'); const getInstantAssetLockProofFixture = require('../../../../../lib/test/fixtures/getInstantAssetLockProofFixture'); const createStateRepositoryMock = require('../../../../../lib/test/mocks/createStateRepositoryMock'); -const IdentityAssetLockTransactionIsNotFoundError = require('../../../../../lib/errors/consensus/basic/identity/IdentityAssetLockTransactionIsNotFoundError'); + const UnknownAssetLockProofError = require('../../../../../lib/identity/errors/UnknownAssetLockProofTypeError'); +const AssetLockTransactionIsNotFoundError = require('../../../../../lib/identity/errors/AssetLockTransactionIsNotFoundError'); describe('fetchAssetLockTransactionOutputFactory', () => { let fetchAssetLockTransactionOutput; @@ -36,6 +37,7 @@ describe('fetchAssetLockTransactionOutputFactory', () => { describe('ChainAssetLockProof', () => { let assetLockProofFixture; let output; + let transactionHash; beforeEach(() => { const rawTransaction = '030000000137feb5676d0851337ea3c9a992496aab7a0b3eee60aeeb9774000b7f4bababa5000000006b483045022100d91557de37645c641b948c6cd03b4ae3791a63a650db3e2fee1dcf5185d1b10402200e8bd410bf516ca61715867666d31e44495428ce5c1090bf2294a829ebcfa4ef0121025c3cc7fbfc52f710c941497fd01876c189171ea227458f501afcb38a297d65b4ffffffff021027000000000000166a14152073ca2300a86b510fa2f123d3ea7da3af68dcf77cb0090a0000001976a914152073ca2300a86b510fa2f123d3ea7da3af68dc88ac00000000'; @@ -47,6 +49,9 @@ describe('fetchAssetLockTransactionOutputFactory', () => { const transaction = new Transaction(rawTransaction); ([output] = transaction.outputs); + + const outPoint = Transaction.parseOutPointBuffer(assetLockProofFixture.getOutPoint()); + ({ transactionHash } = outPoint); }); it('should fetch output from state repository', async () => { @@ -56,9 +61,6 @@ describe('fetchAssetLockTransactionOutputFactory', () => { expect(assetLockTransactionOutput).to.deep.equal(output); - const outPoint = Transaction.parseOutPointBuffer(assetLockProofFixture.getOutPoint()); - const { transactionHash } = outPoint; - expect(stateRepositoryMock.fetchTransaction).to.be.calledOnceWithExactly(transactionHash); }); @@ -72,8 +74,8 @@ describe('fetchAssetLockTransactionOutputFactory', () => { expect.fail('should throw IdentityAssetLockTransactionIsNotFoundError'); } catch (e) { - expect(e).to.be.an.instanceOf(IdentityAssetLockTransactionIsNotFoundError); - expect(e.getOutPoint()).to.deep.equal(assetLockProofFixture.getOutPoint()); + expect(e).to.be.an.instanceOf(AssetLockTransactionIsNotFoundError); + expect(e.getTransactionId()).to.deep.equal(transactionHash); } }); }); diff --git a/test/integration/identity/stateTransition/assetLockProof/instant/validateInstantAssetLockProofStructureFactory.spec.js b/test/integration/identity/stateTransition/assetLockProof/instant/validateInstantAssetLockProofStructureFactory.spec.js index 30304129..377e807b 100644 --- a/test/integration/identity/stateTransition/assetLockProof/instant/validateInstantAssetLockProofStructureFactory.spec.js +++ b/test/integration/identity/stateTransition/assetLockProof/instant/validateInstantAssetLockProofStructureFactory.spec.js @@ -9,9 +9,9 @@ const createAjv = require('../../../../../../lib/ajv/createAjv'); const getInstantAssetLockFixture = require('../../../../../../lib/test/fixtures/getInstantAssetLockProofFixture'); const JsonSchemaValidator = require('../../../../../../lib/validation/JsonSchemaValidator'); const createStateRepositoryMock = require('../../../../../../lib/test/mocks/createStateRepositoryMock'); -const InvalidIdentityAssetLockProofError = require('../../../../../../lib/errors/consensus/basic/identity/InvalidIdentityAssetLockProofError'); -const IdentityAssetLockProofMismatchError = require('../../../../../../lib/errors/consensus/basic/identity/IdentityAssetLockProofMismatchError'); -const InvalidIdentityAssetLockProofSignatureError = require('../../../../../../lib/errors/consensus/basic/identity/InvalidIdentityAssetLockProofSignatureError'); +const InvalidIdentityAssetLockProofError = require('../../../../../../lib/errors/consensus/basic/identity/InvalidInstantAssetLockProofError'); +const IdentityAssetLockProofLockedTransactionMismatchError = require('../../../../../../lib/errors/consensus/basic/identity/IdentityAssetLockProofLockedTransactionMismatchError'); +const InvalidIdentityAssetLockProofSignatureError = require('../../../../../../lib/errors/consensus/basic/identity/InvalidInstantAssetLockProofSignatureError'); const { expectValidationError, expectJsonSchemaError } = require( '../../../../../../lib/test/expect/expectError', @@ -94,9 +94,9 @@ describe('validateInstantAssetLockProofStructureFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('type'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('type'); expect(stateRepositoryMock.verifyInstantLock).to.not.be.called(); expect(instantLockMock.verify).to.not.be.called(); @@ -112,8 +112,8 @@ describe('validateInstantAssetLockProofStructureFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/type'); - expect(error.keyword).to.equal('const'); + expect(error.getInstancePath()).to.equal('/type'); + expect(error.getKeyword()).to.equal('const'); expect(stateRepositoryMock.verifyInstantLock).to.not.be.called(); expect(instantLockMock.verify).to.not.be.called(); @@ -131,9 +131,9 @@ describe('validateInstantAssetLockProofStructureFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('instantLock'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('instantLock'); expect(stateRepositoryMock.verifyInstantLock).to.not.be.called(); expect(instantLockMock.verify).to.not.be.called(); @@ -149,10 +149,10 @@ describe('validateInstantAssetLockProofStructureFactory', () => { const [error, byteArrayError] = result.getErrors(); - expect(error.instancePath).to.equal('/instantLock/0'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/instantLock/0'); + expect(error.getKeyword()).to.equal('type'); - expect(byteArrayError.keyword).to.equal('byteArray'); + expect(byteArrayError.getKeyword()).to.equal('byteArray'); expect(stateRepositoryMock.verifyInstantLock).to.not.be.called(); expect(instantLockMock.verify).to.not.be.called(); @@ -168,8 +168,8 @@ describe('validateInstantAssetLockProofStructureFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/instantLock'); - expect(error.keyword).to.equal('minItems'); + expect(error.getInstancePath()).to.equal('/instantLock'); + expect(error.getKeyword()).to.equal('minItems'); expect(stateRepositoryMock.verifyInstantLock).to.not.be.called(); expect(instantLockMock.verify).to.not.be.called(); @@ -185,8 +185,8 @@ describe('validateInstantAssetLockProofStructureFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/instantLock'); - expect(error.keyword).to.equal('maxItems'); + expect(error.getInstancePath()).to.equal('/instantLock'); + expect(error.getKeyword()).to.equal('maxItems'); expect(stateRepositoryMock.verifyInstantLock).to.not.be.called(); expect(instantLockMock.verify).to.not.be.called(); @@ -205,7 +205,8 @@ describe('validateInstantAssetLockProofStructureFactory', () => { const [error] = result.getErrors(); - expect(error.message).to.equal(`Invalid asset lock proof: ${instantLockError.message}`); + expect(error.getCode()).to.equal(1041); + expect(error.getValidationError()).to.equal(instantLockError); expect(stateRepositoryMock.verifyInstantLock).to.not.be.called(); expect(instantLockMock.verify).to.not.be.called(); @@ -213,11 +214,18 @@ describe('validateInstantAssetLockProofStructureFactory', () => { }); it('should lock the same transaction', async () => { - instantLockMock.txid = '123'; + const txId = Buffer.alloc(32); + instantLockMock.txid = txId.toString('hex'); const result = await validateInstantAssetLockProofStructure(rawProof); - expectValidationError(result, IdentityAssetLockProofMismatchError); + expectValidationError(result, IdentityAssetLockProofLockedTransactionMismatchError); + + const [error] = result.getErrors(); + + expect(error.getCode()).to.equal(1031); + expect(error.getInstantLockTransactionId()).to.deep.equal(txId); + expect(error.getAssetLockTransactionId()).to.deep.equal(Buffer.from(transaction.id, 'hex')); expect(stateRepositoryMock.verifyInstantLock).to.be.calledOnce(); expect(instantLockMock.verify).to.not.be.called(); @@ -231,6 +239,10 @@ describe('validateInstantAssetLockProofStructureFactory', () => { expectValidationError(result, InvalidIdentityAssetLockProofSignatureError); + const [error] = result.getErrors(); + + expect(error.getCode()).to.equal(1042); + expect(stateRepositoryMock.verifyInstantLock).to.be.calledOnce(); expect(validateAssetLockTransactionMock).to.not.be.called(); }); @@ -246,9 +258,9 @@ describe('validateInstantAssetLockProofStructureFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('transaction'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('transaction'); expect(stateRepositoryMock.verifyInstantLock).to.not.be.called(); expect(instantLockMock.verify).to.not.be.called(); @@ -264,10 +276,10 @@ describe('validateInstantAssetLockProofStructureFactory', () => { const [error, byteArrayError] = result.getErrors(); - expect(error.instancePath).to.equal('/transaction/0'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/transaction/0'); + expect(error.getKeyword()).to.equal('type'); - expect(byteArrayError.keyword).to.equal('byteArray'); + expect(byteArrayError.getKeyword()).to.equal('byteArray'); expect(stateRepositoryMock.verifyInstantLock).to.not.be.called(); expect(instantLockMock.verify).to.not.be.called(); @@ -284,7 +296,7 @@ describe('validateInstantAssetLockProofStructureFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/transaction'); - expect(error.keyword).to.equal('minItems'); + expect(error.getKeyword()).to.equal('minItems'); expect(stateRepositoryMock.verifyInstantLock).to.not.be.called(); expect(instantLockMock.verify).to.not.be.called(); @@ -301,7 +313,7 @@ describe('validateInstantAssetLockProofStructureFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/transaction'); - expect(error.keyword).to.equal('maxItems'); + expect(error.getKeyword()).to.equal('maxItems'); expect(stateRepositoryMock.verifyInstantLock).to.not.be.called(); expect(instantLockMock.verify).to.not.be.called(); @@ -309,7 +321,13 @@ describe('validateInstantAssetLockProofStructureFactory', () => { }); it('should should be valid', async () => { - validateAssetLockTransactionResult.addError(new InvalidIdentityAssetLockTransactionError('Unknown special transaction type')); + const validationError = new Error('parsing failed'); + + const consensusError = new InvalidIdentityAssetLockTransactionError(validationError.message); + + consensusError.setValidationError(validationError); + + validateAssetLockTransactionResult.addError(consensusError); validateAssetLockTransactionMock.resolves(validateAssetLockTransactionResult); const result = await validateInstantAssetLockProofStructure(rawProof); @@ -318,7 +336,11 @@ describe('validateInstantAssetLockProofStructureFactory', () => { const [error] = result.getErrors(); - expect(error.message).to.equal('Invalid asset lock transaction: Unknown special transaction type'); + expect(error.getCode()).to.equal(1038); + + expect(error).to.equal(consensusError); + + expect(error.getValidationError()).to.equal(validationError); expect(stateRepositoryMock.verifyInstantLock).to.be.calledOnce(); expect(instantLockMock.verify).to.not.be.called(); @@ -337,8 +359,8 @@ describe('validateInstantAssetLockProofStructureFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('outputIndex'); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('outputIndex'); expect(stateRepositoryMock.verifyInstantLock).to.not.be.called(); expect(instantLockMock.verify).to.not.be.called(); @@ -354,7 +376,7 @@ describe('validateInstantAssetLockProofStructureFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/outputIndex'); - expect(error.keyword).to.equal('type'); + expect(error.getKeyword()).to.equal('type'); expect(stateRepositoryMock.verifyInstantLock).to.not.be.called(); expect(instantLockMock.verify).to.not.be.called(); @@ -370,7 +392,7 @@ describe('validateInstantAssetLockProofStructureFactory', () => { const [error] = result.getErrors(); expect(error.instancePath).to.equal('/outputIndex'); - expect(error.keyword).to.equal('minimum'); + expect(error.getKeyword()).to.equal('minimum'); expect(stateRepositoryMock.verifyInstantLock).to.not.be.called(); expect(instantLockMock.verify).to.not.be.called(); diff --git a/test/integration/identity/stateTransition/assetLockProof/validateAssetLockTransactionFactory.spec.js b/test/integration/identity/stateTransition/assetLockProof/validateAssetLockTransactionFactory.spec.js index fd17af42..1c3dfdf5 100644 --- a/test/integration/identity/stateTransition/assetLockProof/validateAssetLockTransactionFactory.spec.js +++ b/test/integration/identity/stateTransition/assetLockProof/validateAssetLockTransactionFactory.spec.js @@ -1,13 +1,19 @@ const rewiremock = require('rewiremock/node'); const { Transaction } = require('@dashevo/dashcore-lib'); + const validateAssetLockTransactionFactory = require('../../../../../lib/identity/stateTransition/assetLockProof/validateAssetLockTransactionFactory'); const createStateRepositoryMock = require('../../../../../lib/test/mocks/createStateRepositoryMock'); + const ValidationResult = require('../../../../../lib/validation/ValidationResult'); + +const { expectValidationError } = require('../../../../../lib/test/expect/expectError'); + const InvalidIdentityAssetLockTransactionError = require('../../../../../lib/errors/consensus/basic/identity/InvalidIdentityAssetLockTransactionError'); const IdentityAssetLockTransactionOutputNotFoundError = require('../../../../../lib/errors/consensus/basic/identity/IdentityAssetLockTransactionOutputNotFoundError'); const IdentityAssetLockTransactionOutPointAlreadyExistsError = require('../../../../../lib/errors/consensus/basic/identity/IdentityAssetLockTransactionOutPointAlreadyExistsError'); const InvalidIdentityAssetLockTransactionOutputError = require('../../../../../lib/errors/consensus/basic/identity/InvalidIdentityAssetLockTransactionOutputError'); +const InvalidAssetLockTransactionOutputReturnSize = require('../../../../../lib/errors/consensus/basic/identity/InvalidAssetLockTransactionOutputReturnSize'); function getValidateAssetLockTransactionFactoryMock(TransactionClassMock) { return rewiremock.proxy( @@ -55,14 +61,12 @@ describe('validateAssetLockTransactionFactory', () => { const result = await validateAssetLockTransaction(rawTransaction, outputIndex); - expect(result).to.be.an.instanceOf(ValidationResult); - expect(result.isValid()).to.be.false(); - expect(result.getErrors()).to.be.an('array'); - expect(result.getErrors()).to.have.lengthOf(1); + expectValidationError(result, InvalidIdentityAssetLockTransactionError); const [error] = result.getErrors(); - expect(error).to.be.an.instanceOf(InvalidIdentityAssetLockTransactionError); + expect(error.getCode()).to.equal(1038); + expect(error.getValidationError()).to.be.instanceOf(Error); expect(result.getData()).to.be.undefined(); expect(stateRepositoryMock.isAssetLockTransactionOutPointAlreadyUsed).to.not.be.called(); @@ -72,14 +76,11 @@ describe('validateAssetLockTransactionFactory', () => { outputIndex = 42; const result = await validateAssetLockTransaction(rawTransaction, outputIndex); - expect(result).to.be.an.instanceOf(ValidationResult); - expect(result.isValid()).to.be.false(); - expect(result.getErrors()).to.be.an('array'); - expect(result.getErrors()).to.have.lengthOf(1); + expectValidationError(result, IdentityAssetLockTransactionOutputNotFoundError); const [error] = result.getErrors(); - expect(error).to.be.an.instanceOf(IdentityAssetLockTransactionOutputNotFoundError); + expect(error.getCode()).to.equal(1034); expect(error.getOutputIndex()).to.equal(outputIndex); expect(result.getData()).to.be.undefined(); @@ -103,18 +104,18 @@ describe('validateAssetLockTransactionFactory', () => { validateAssetLockTransaction = validateAssetLockTransactionFactoryMocked(stateRepositoryMock); const result = await validateAssetLockTransaction(rawTransaction, outputIndex); - expect(result).to.be.an.instanceOf(ValidationResult); - expect(result.isValid()).to.be.false(); - expect(result.getErrors()).to.be.an('array'); - expect(result.getErrors()).to.have.lengthOf(1); + + expectValidationError(result, InvalidIdentityAssetLockTransactionOutputError); const [error] = result.getErrors(); - expect(error).to.be.an.instanceOf(InvalidIdentityAssetLockTransactionOutputError); + + expect(error.getCode()).to.equal(1039); + expect(error.getOutputIndex()).to.equal(outputIndex); }); it('should contain valid public key hash', async function it() { const isDataOut = this.sinonSandbox.stub().returns(true); - const getData = this.sinonSandbox.stub().returns(''); + const getData = this.sinonSandbox.stub().returns(Buffer.alloc(0)); TransactionClassMock = function transactionClassMock() { this.outputs = [{ @@ -131,13 +132,13 @@ describe('validateAssetLockTransactionFactory', () => { validateAssetLockTransaction = validateAssetLockTransactionFactoryMocked(stateRepositoryMock); const result = await validateAssetLockTransaction(rawTransaction, outputIndex); - expect(result).to.be.an.instanceOf(ValidationResult); - expect(result.isValid()).to.be.false(); - expect(result.getErrors()).to.be.an('array'); - expect(result.getErrors()).to.have.lengthOf(1); + + expectValidationError(result, InvalidAssetLockTransactionOutputReturnSize); const [error] = result.getErrors(); - expect(error).to.be.an.instanceOf(InvalidIdentityAssetLockTransactionOutputError); + + expect(error.getCode()).to.equal(1037); + expect(error.getOutputIndex()).to.equal(outputIndex); }); it('should return IdentityAssetLockTransactionOutPointAlreadyExistsError if outPoint was already used', async () => { @@ -145,18 +146,17 @@ describe('validateAssetLockTransactionFactory', () => { const result = await validateAssetLockTransaction(rawTransaction, outputIndex); - expect(result).to.be.an.instanceOf(ValidationResult); - expect(result.isValid()).to.be.false(); - expect(result.getErrors()).to.be.an('array'); - expect(result.getErrors()).to.have.lengthOf(1); + expectValidationError(result, IdentityAssetLockTransactionOutPointAlreadyExistsError); const [error] = result.getErrors(); - expect(error).to.be.an.instanceOf(IdentityAssetLockTransactionOutPointAlreadyExistsError); + expect(error.getCode()).to.equal(1033); const transaction = new Transaction(rawTransaction); - expect(error.getOutPoint()).to.deep.equal(transaction.getOutPointBuffer(outputIndex)); + expect(Buffer.isBuffer(error.getTransactionId())).to.be.true(); + expect(error.getTransactionId()).to.deep.equal(Buffer.from(transaction.id, 'hex')); + expect(error.getOutputIndex()).to.deep.equal(outputIndex); expect(result.getData()).to.be.undefined(); expect(stateRepositoryMock.isAssetLockTransactionOutPointAlreadyUsed) diff --git a/test/integration/identity/validation/validateIdentityFactory.spec.js b/test/integration/identity/validation/validateIdentityFactory.spec.js index 19d292c0..f77027c4 100644 --- a/test/integration/identity/validation/validateIdentityFactory.spec.js +++ b/test/integration/identity/validation/validateIdentityFactory.spec.js @@ -56,9 +56,9 @@ describe('validateIdentityFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.params.missingProperty).to.equal('id'); - expect(error.keyword).to.equal('required'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getParams().missingProperty).to.equal('id'); + expect(error.getKeyword()).to.equal('required'); expect(validatePublicKeysMock).to.not.be.called(); }); @@ -72,10 +72,10 @@ describe('validateIdentityFactory', () => { const [error, byteArrayError] = result.getErrors(); - expect(error.instancePath).to.equal('/id/0'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/id/0'); + expect(error.getKeyword()).to.equal('type'); - expect(byteArrayError.keyword).to.equal('byteArray'); + expect(byteArrayError.getKeyword()).to.equal('byteArray'); expect(validatePublicKeysMock).to.not.be.called(); }); @@ -89,8 +89,8 @@ describe('validateIdentityFactory', () => { const [error] = result.getErrors(); - expect(error.keyword).to.equal('minItems'); - expect(error.instancePath).to.equal('/id'); + expect(error.getKeyword()).to.equal('minItems'); + expect(error.getInstancePath()).to.equal('/id'); expect(validatePublicKeysMock).to.not.be.called(); }); @@ -104,8 +104,8 @@ describe('validateIdentityFactory', () => { const [error] = result.getErrors(); - expect(error.keyword).to.equal('maxItems'); - expect(error.instancePath).to.equal('/id'); + expect(error.getKeyword()).to.equal('maxItems'); + expect(error.getInstancePath()).to.equal('/id'); expect(validatePublicKeysMock).to.not.be.called(); }); @@ -121,9 +121,9 @@ describe('validateIdentityFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.params.missingProperty).to.equal('balance'); - expect(error.keyword).to.equal('required'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getParams().missingProperty).to.equal('balance'); + expect(error.getKeyword()).to.equal('required'); expect(validatePublicKeysMock).to.not.be.called(); }); @@ -137,8 +137,8 @@ describe('validateIdentityFactory', () => { const [error] = result.getErrors(); - expect(error.keyword).to.equal('type'); - expect(error.instancePath).to.equal('/balance'); + expect(error.getKeyword()).to.equal('type'); + expect(error.getInstancePath()).to.equal('/balance'); expect(validatePublicKeysMock).to.not.be.called(); }); @@ -152,8 +152,8 @@ describe('validateIdentityFactory', () => { const [error] = result.getErrors(); - expect(error.keyword).to.equal('minimum'); - expect(error.instancePath).to.equal('/balance'); + expect(error.getKeyword()).to.equal('minimum'); + expect(error.getInstancePath()).to.equal('/balance'); expect(validatePublicKeysMock).to.not.be.called(); @@ -175,9 +175,9 @@ describe('validateIdentityFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.params.missingProperty).to.equal('publicKeys'); - expect(error.keyword).to.equal('required'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getParams().missingProperty).to.equal('publicKeys'); + expect(error.getKeyword()).to.equal('required'); expect(validatePublicKeysMock).to.not.be.called(); }); @@ -191,8 +191,9 @@ describe('validateIdentityFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/publicKeys'); - expect(error.keyword).to.equal('type'); + expect(error.getCode()).to.equal(1005); + expect(error.getInstancePath()).to.equal('/publicKeys'); + expect(error.getKeyword()).to.equal('type'); expect(validatePublicKeysMock).to.not.be.called(); }); @@ -206,8 +207,8 @@ describe('validateIdentityFactory', () => { const [error] = result.getErrors(); - expect(error.keyword).to.equal('minItems'); - expect(error.instancePath).to.equal('/publicKeys'); + expect(error.getKeyword()).to.equal('minItems'); + expect(error.getInstancePath()).to.equal('/publicKeys'); expect(validatePublicKeysMock).to.not.be.called(); }); @@ -221,8 +222,8 @@ describe('validateIdentityFactory', () => { const [error] = result.getErrors(); - expect(error.keyword).to.equal('uniqueItems'); - expect(error.instancePath).to.equal('/publicKeys'); + expect(error.getKeyword()).to.equal('uniqueItems'); + expect(error.getInstancePath()).to.equal('/publicKeys'); expect(validatePublicKeysMock).to.not.be.called(); }); @@ -241,8 +242,8 @@ describe('validateIdentityFactory', () => { const [error] = result.getErrors(); - expect(error.keyword).to.equal('maxItems'); - expect(error.instancePath).to.equal('/publicKeys'); + expect(error.getKeyword()).to.equal('maxItems'); + expect(error.getInstancePath()).to.equal('/publicKeys'); expect(validatePublicKeysMock).to.not.be.called(); }); @@ -258,9 +259,9 @@ describe('validateIdentityFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.params.missingProperty).to.equal('revision'); - expect(error.keyword).to.equal('required'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getParams().missingProperty).to.equal('revision'); + expect(error.getKeyword()).to.equal('required'); expect(validatePublicKeysMock).to.not.be.called(); }); @@ -274,8 +275,8 @@ describe('validateIdentityFactory', () => { const [error] = result.getErrors(); - expect(error.keyword).to.equal('type'); - expect(error.instancePath).to.equal('/revision'); + expect(error.getKeyword()).to.equal('type'); + expect(error.getInstancePath()).to.equal('/revision'); expect(validatePublicKeysMock).to.not.be.called(); }); @@ -289,8 +290,8 @@ describe('validateIdentityFactory', () => { const [error] = result.getErrors(); - expect(error.keyword).to.equal('minimum'); - expect(error.instancePath).to.equal('/revision'); + expect(error.getKeyword()).to.equal('minimum'); + expect(error.getInstancePath()).to.equal('/revision'); expect(validatePublicKeysMock).to.not.be.called(); diff --git a/test/integration/identity/validation/validatePublicKeysFactory.spec.js b/test/integration/identity/validation/validatePublicKeysFactory.spec.js index 47884572..45c6d12a 100644 --- a/test/integration/identity/validation/validatePublicKeysFactory.spec.js +++ b/test/integration/identity/validation/validatePublicKeysFactory.spec.js @@ -55,9 +55,9 @@ describe('validatePublicKeysFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('id'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('id'); }); it('should be a number', () => { @@ -69,8 +69,8 @@ describe('validatePublicKeysFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/id'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/id'); + expect(error.getKeyword()).to.equal('type'); }); it('should be an integer', () => { @@ -82,8 +82,8 @@ describe('validatePublicKeysFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/id'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/id'); + expect(error.getKeyword()).to.equal('type'); }); it('should be greater or equal to one', () => { @@ -95,8 +95,8 @@ describe('validatePublicKeysFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/id'); - expect(error.keyword).to.equal('minimum'); + expect(error.getInstancePath()).to.equal('/id'); + expect(error.getKeyword()).to.equal('minimum'); }); }); @@ -110,8 +110,8 @@ describe('validatePublicKeysFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/data'); - expect(error.keyword).to.equal('minItems'); + expect(error.getInstancePath()).to.equal('/data'); + expect(error.getKeyword()).to.equal('minItems'); }); it('should be a number', () => { @@ -123,8 +123,8 @@ describe('validatePublicKeysFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/type'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/type'); + expect(error.getKeyword()).to.equal('type'); }); }); @@ -138,9 +138,9 @@ describe('validatePublicKeysFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal(''); - expect(error.keyword).to.equal('required'); - expect(error.params.missingProperty).to.equal('data'); + expect(error.getInstancePath()).to.equal(''); + expect(error.getKeyword()).to.equal('required'); + expect(error.getParams().missingProperty).to.equal('data'); }); it('should be a byte array', () => { @@ -152,10 +152,10 @@ describe('validatePublicKeysFactory', () => { const [error, byteArrayError] = result.getErrors(); - expect(error.instancePath).to.equal('/data/0'); - expect(error.keyword).to.equal('type'); + expect(error.getInstancePath()).to.equal('/data/0'); + expect(error.getKeyword()).to.equal('type'); - expect(byteArrayError.keyword).to.equal('byteArray'); + expect(byteArrayError.getKeyword()).to.equal('byteArray'); }); describe('ECDSA_SECP256K1', () => { @@ -168,8 +168,8 @@ describe('validatePublicKeysFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/data'); - expect(error.keyword).to.equal('minItems'); + expect(error.getInstancePath()).to.equal('/data'); + expect(error.getKeyword()).to.equal('minItems'); }); it('should be no longer than 33 bytes', () => { @@ -181,8 +181,8 @@ describe('validatePublicKeysFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/data'); - expect(error.keyword).to.equal('maxItems'); + expect(error.getInstancePath()).to.equal('/data'); + expect(error.getKeyword()).to.equal('maxItems'); }); }); @@ -197,8 +197,8 @@ describe('validatePublicKeysFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/data'); - expect(error.keyword).to.equal('minItems'); + expect(error.getInstancePath()).to.equal('/data'); + expect(error.getKeyword()).to.equal('minItems'); }); it('should be no longer than 48 bytes', () => { @@ -211,8 +211,8 @@ describe('validatePublicKeysFactory', () => { const [error] = result.getErrors(); - expect(error.instancePath).to.equal('/data'); - expect(error.keyword).to.equal('maxItems'); + expect(error.getInstancePath()).to.equal('/data'); + expect(error.getKeyword()).to.equal('maxItems'); }); }); }); @@ -226,7 +226,8 @@ describe('validatePublicKeysFactory', () => { const [error] = result.getErrors(); - expect(error.getRawPublicKeys()).to.equal(rawPublicKeys); + expect(error.getCode()).to.equal(1030); + expect(error.getDuplicatedIds()).to.deep.equal([rawPublicKeys[1].id]); }); it('should return invalid result if there are duplicate keys', () => { @@ -238,7 +239,8 @@ describe('validatePublicKeysFactory', () => { const [error] = result.getErrors(); - expect(error.getRawPublicKeys()).to.equal(rawPublicKeys); + expect(error.getCode()).to.equal(1029); + expect(error.getDuplicatedPublicKeysIds()).to.deep.equal([rawPublicKeys[1].id]); }); it('should return invalid result if key data is not a valid DER', () => { @@ -250,8 +252,10 @@ describe('validatePublicKeysFactory', () => { const [error] = result.getErrors(); - expect(error.getPublicKey()).to.deep.equal(rawPublicKeys[1]); - expect(error.getValidationError()).to.be.an.instanceOf(TypeError); + expect(error.getCode()).to.equal(1040); + expect(error.getPublicKeyId()).to.deep.equal(rawPublicKeys[1].id); + expect(error.getValidationError()).to.be.instanceOf(TypeError); + expect(error.getValidationError().message).to.equal('Invalid DER format public key'); }); it('should pass valid public keys', () => { diff --git a/test/integration/stateTransition/StateTransitionFacade.spec.js b/test/integration/stateTransition/StateTransitionFacade.spec.js index 64e34f99..b652b4ab 100644 --- a/test/integration/stateTransition/StateTransitionFacade.spec.js +++ b/test/integration/stateTransition/StateTransitionFacade.spec.js @@ -19,7 +19,7 @@ const IdentityPublicKey = require('../../../lib/identity/IdentityPublicKey'); const MissingOptionError = require('../../../lib/errors/MissingOptionError'); const createDPPMock = require('../../../lib/test/mocks/createDPPMock'); -const ConsensusError = require('../../../lib/errors/consensus/ConsensusError'); +const SomeConsensusError = require('../../../lib/test/mocks/SomeConsensusError'); describe('StateTransitionFacade', () => { let dpp; @@ -214,7 +214,7 @@ describe('StateTransitionFacade', () => { }); it('should return invalid result if not enough balance to pay fee for State Transition', async () => { - const consensusError = new ConsensusError('error'); + const consensusError = new SomeConsensusError('error'); dpp.stateTransition.validateStateTransitionFee = () => new ValidationResult([consensusError]); @@ -230,7 +230,7 @@ describe('StateTransitionFacade', () => { }); it('should return invalid result if State Transition is invalid against state', async () => { - const consensusError = new ConsensusError('error'); + const consensusError = new SomeConsensusError('error'); dpp.stateTransition.validateStateTransitionState = () => ( new ValidationResult([consensusError]) diff --git a/test/unit/dataContract/DataContractFactory.spec.js b/test/unit/dataContract/DataContractFactory.spec.js index 67efb2b0..deeabb84 100644 --- a/test/unit/dataContract/DataContractFactory.spec.js +++ b/test/unit/dataContract/DataContractFactory.spec.js @@ -10,9 +10,9 @@ const DataContractCreateTransition = require('../../../lib/dataContract/stateTra const ValidationResult = require('../../../lib/validation/ValidationResult'); const InvalidDataContractError = require('../../../lib/dataContract/errors/InvalidDataContractError'); -const ConsensusError = require('../../../lib/errors/consensus/ConsensusError'); const SerializedObjectParsingError = require('../../../lib/errors/consensus/basic/decode/SerializedObjectParsingError'); const createDPPMock = require('../../../lib/test/mocks/createDPPMock'); +const SomeConsensusError = require('../../../lib/test/mocks/SomeConsensusError'); describe('DataContractFactory', () => { let DataContractFactory; @@ -101,7 +101,7 @@ describe('DataContractFactory', () => { }); it('should throw an error if passed object is not valid', async () => { - const validationError = new ConsensusError('test'); + const validationError = new SomeConsensusError('test'); validateDataContractMock.returns(new ValidationResult([validationError])); diff --git a/test/unit/dataContract/stateTransition/DataContractCreateTransition/validation/state/validateDataContractCreateTransitionStateFactory.spec.js b/test/unit/dataContract/stateTransition/DataContractCreateTransition/validation/state/validateDataContractCreateTransitionStateFactory.spec.js index 90ce5ad0..2b56aff0 100644 --- a/test/unit/dataContract/stateTransition/DataContractCreateTransition/validation/state/validateDataContractCreateTransitionStateFactory.spec.js +++ b/test/unit/dataContract/stateTransition/DataContractCreateTransition/validation/state/validateDataContractCreateTransitionStateFactory.spec.js @@ -39,7 +39,9 @@ describe('validateDataContractCreateTransitionStateFactory', () => { const [error] = result.getErrors(); - expect(error.getDataContract().toObject()).to.deep.equal(dataContract.toObject()); + expect(error.getCode()).to.equal(4000); + expect(Buffer.isBuffer(error.getDataContractId())).to.be.true(); + expect(error.getDataContractId()).to.deep.equal(dataContract.getId().toBuffer()); expect(stateRepositoryMock.fetchDataContract).to.be.calledOnceWithExactly(dataContract.getId()); }); diff --git a/test/unit/dataContract/validation/validateDataContractMaxDepthFactory.spec.js b/test/unit/dataContract/validation/validateDataContractMaxDepthFactory.spec.js index cc8f9a42..da999dc6 100644 --- a/test/unit/dataContract/validation/validateDataContractMaxDepthFactory.spec.js +++ b/test/unit/dataContract/validation/validateDataContractMaxDepthFactory.spec.js @@ -2,8 +2,8 @@ const validateDataContractMaxDepthFactory = require('../../../../lib/dataContrac const ValidationResult = require('../../../../lib/validation/ValidationResult'); const { expectValidationError } = require('../../../../lib/test/expect/expectError'); const DataContractMaxDepthExceedError = require('../../../../lib/errors/consensus/basic/dataContract/DataContractMaxDepthExceedError'); -const JsonSchemaError = require('../../../../lib/errors/consensus/basic/JsonSchemaError'); const generateDeepJson = require('../../../../lib/test/utils/generateDeepJson'); +const InvalidJsonSchemaRefError = require('../../../../lib/errors/consensus/basic/dataContract/InvalidJsonSchemaRefError'); describe('validateDataContractMaxDepthFactory', () => { let refParserMock; @@ -30,7 +30,9 @@ describe('validateDataContractMaxDepthFactory', () => { expectValidationError(result); const [error] = result.getErrors(); + expect(error).to.be.an.instanceOf(DataContractMaxDepthExceedError); + expect(error.getCode()).to.equal(1007); }); it('should return valid result if depth = MAX_DEPTH', async () => { @@ -60,7 +62,9 @@ describe('validateDataContractMaxDepthFactory', () => { expectValidationError(result); const [error] = result.getErrors(); + expect(error).to.be.an.instanceOf(DataContractMaxDepthExceedError); + expect(error.getCode()).to.equal(1007); }); it('should return error if refParser throws an error', async () => { @@ -71,10 +75,11 @@ describe('validateDataContractMaxDepthFactory', () => { const result = await validateDataContractMaxDepth(dataContractFixture); expectValidationError(result); + const [error] = result.getErrors(); - expect(error).to.be.an.instanceOf(JsonSchemaError); - expect(error.message).to.equal(refParserError.message); + expect(error).to.be.an.instanceOf(InvalidJsonSchemaRefError); + expect(error.message).to.equal(`Invalid JSON Schema $ref: ${refParserError.message}`); }); it('should return valid result', async () => { diff --git a/test/unit/dataContract/validation/validateDataContractPatternsFactory.spec.js b/test/unit/dataContract/validation/validateDataContractPatternsFactory.spec.js index 05310184..bb2b2233 100644 --- a/test/unit/dataContract/validation/validateDataContractPatternsFactory.spec.js +++ b/test/unit/dataContract/validation/validateDataContractPatternsFactory.spec.js @@ -4,7 +4,7 @@ const validateDataContractPatternsFactory = require('../../../../lib/dataContrac const { expectValidationError } = require( '../../../../lib/test/expect/expectError', ); -const IncompatibleRe2PatternError = require('../../../../lib/document/errors/IncompatibleRe2PatternError'); +const IncompatibleRe2PatternError = require('../../../../lib/errors/consensus/basic/dataContract/IncompatibleRe2PatternError'); describe('validateDataContractPatternsFactory', () => { let validateDataContractPatterns; @@ -56,10 +56,9 @@ describe('validateDataContractPatternsFactory', () => { expectValidationError(result, IncompatibleRe2PatternError); const [error] = result.getErrors(); + expect(error.getCode()).to.equal(1009); expect(error.getPattern()).to.equal('^((?!-|_)[a-zA-Z0-9-_]{0,62}[a-zA-Z0-9])$'); expect(error.getPath()).to.equal('/properties/bar'); - expect(error.getOriginalErrorMessage()).to.be.a('string').and.satisfy((msg) => ( - msg.startsWith('Invalid regular expression') - )); + expect(error.getPatternError()).to.be.instanceOf(Error); }); }); diff --git a/test/unit/dataTrigger/DataTrigger.spec.js b/test/unit/dataTrigger/DataTrigger.spec.js index 152ad9da..8cbcf225 100644 --- a/test/unit/dataTrigger/DataTrigger.spec.js +++ b/test/unit/dataTrigger/DataTrigger.spec.js @@ -100,8 +100,12 @@ describe('DataTrigger', () => { const result = await trigger.execute(document, context); expect(result).to.be.an.instanceOf(DataTriggerExecutionResult); - expect(result.getErrors()[0]).to.be.an.instanceOf(DataTriggerExecutionError); - expect(result.getErrors()[0].getError()).to.equal(triggerError); + + const [error] = result.getErrors(); + + expect(error).to.be.an.instanceOf(DataTriggerExecutionError); + + expect(error.getExecutionError()).to.equal(triggerError); }); it('should return a result with invalid result error if trigger function have not returned any result', async () => { @@ -118,8 +122,11 @@ describe('DataTrigger', () => { const result = await trigger.execute(document, context); expect(result).to.be.an.instanceOf(DataTriggerExecutionResult); - expect(result.getErrors()[0]).to.be.an.instanceOf(DataTriggerInvalidResultError); - expect(result.getErrors()[0].message).to.equal('Data trigger have not returned any result'); + + const [error] = result.getErrors(); + + expect(error).to.be.an.instanceOf(DataTriggerInvalidResultError); + expect(error.message).to.equal('Data trigger have not returned any result'); }); }); }); diff --git a/test/unit/dataTrigger/dashpayDataTriggers/createContactRequestDataTrigger.spec.js b/test/unit/dataTrigger/dashpayDataTriggers/createContactRequestDataTrigger.spec.js index 5a40cedd..9fb64fd6 100644 --- a/test/unit/dataTrigger/dashpayDataTriggers/createContactRequestDataTrigger.spec.js +++ b/test/unit/dataTrigger/dashpayDataTriggers/createContactRequestDataTrigger.spec.js @@ -83,6 +83,6 @@ describe('createContactRequestDataTrigger', () => { const [error] = result.getErrors(); expect(error).to.be.an.instanceOf(DataTriggerConditionError); - expect(error.message).to.equal('Core height is out of block height window'); + expect(error.message).to.equal('Core height 10 is out of block height window from 34 to 50'); }); }); diff --git a/test/unit/dataTrigger/dpnsTriggers/createDomainDataTrigger.spec.js b/test/unit/dataTrigger/dpnsTriggers/createDomainDataTrigger.spec.js index 2fdbe888..04d3cbe9 100644 --- a/test/unit/dataTrigger/dpnsTriggers/createDomainDataTrigger.spec.js +++ b/test/unit/dataTrigger/dpnsTriggers/createDomainDataTrigger.spec.js @@ -12,6 +12,7 @@ const createStateRepositoryMock = require('../../../../lib/test/mocks/createStat const hash = require('../../../../lib/util/hash'); const DataTriggerConditionError = require('../../../../lib/errors/consensus/state/dataContract/dataTrigger/DataTriggerConditionError'); +const Identifier = require('../../../../lib/identifier/Identifier'); describe('createDomainDataTrigger', () => { let parentDocumentTransition; @@ -177,9 +178,13 @@ describe('createDomainDataTrigger', () => { }); it('should fail with invalid dashUniqueIdentityId', async () => { + const dashUniqueIdentityId = Identifier.from( + Buffer.alloc(32, 5), + ); + childDocument = getChildDocumentFixture({ records: { - dashUniqueIdentityId: Buffer.alloc(32, 5), + dashUniqueIdentityId: dashUniqueIdentityId.toBuffer(), }, }); @@ -197,13 +202,17 @@ describe('createDomainDataTrigger', () => { const [error] = result.getErrors(); expect(error).to.be.an.instanceOf(DataTriggerConditionError); - expect(error.message).to.equal('ownerId doesn\'t match dashUniqueIdentityId'); + expect(error.message).to.equal(`ownerId ${childDocument.getOwnerId()} doesn't match dashUniqueIdentityId ${dashUniqueIdentityId}`); }); it('should fail with invalid dashAliasIdentityId', async () => { + const dashUniqueIdentityId = Identifier.from( + Buffer.alloc(32, 2), + ); + childDocument = getChildDocumentFixture({ records: { - dashAliasIdentityId: Buffer.alloc(32, 2), + dashAliasIdentityId: dashUniqueIdentityId.toBuffer(), }, }); @@ -221,7 +230,7 @@ describe('createDomainDataTrigger', () => { const [error] = result.getErrors(); expect(error).to.be.an.instanceOf(DataTriggerConditionError); - expect(error.message).to.equal('ownerId doesn\'t match dashAliasIdentityId'); + expect(error.message).to.equal(`ownerId ${childDocument.getOwnerId()} doesn't match dashAliasIdentityId ${dashUniqueIdentityId}`); }); it('should fail with preorder document was not found', async () => { @@ -266,7 +275,7 @@ describe('createDomainDataTrigger', () => { expect(error).to.be.an.instanceOf(DataTriggerConditionError); expect(error.message).to.equal( - 'Full domain name length can not be more than 253 characters long', + 'Full domain name length can not be more than 253 characters long but got 518', ); }); diff --git a/test/unit/dataTrigger/featureFlagDataTriggers/createFeatureFlagDataTrigger.spec.js b/test/unit/dataTrigger/featureFlagDataTriggers/createFeatureFlagDataTrigger.spec.js index 3bc57fa6..84550863 100644 --- a/test/unit/dataTrigger/featureFlagDataTriggers/createFeatureFlagDataTrigger.spec.js +++ b/test/unit/dataTrigger/featureFlagDataTriggers/createFeatureFlagDataTrigger.spec.js @@ -51,7 +51,7 @@ describe('createFeatureFlagDataTrigger', () => { const [error] = result.getErrors(); expect(error).to.be.an.instanceOf(DataTriggerConditionError); - expect(error.message).to.equal('Feature flag cannot be enabled in the past'); + expect(error.message).to.equal('Feature flag cannot be enabled in the past on block 1. Current block height is 42'); }); it('should return an error if owner id is not equal to top level identity id', async () => { diff --git a/test/unit/dataTrigger/rejectDataTrigger.spec.js b/test/unit/dataTrigger/rejectDataTrigger.spec.js index 428ea389..8c26061e 100644 --- a/test/unit/dataTrigger/rejectDataTrigger.spec.js +++ b/test/unit/dataTrigger/rejectDataTrigger.spec.js @@ -39,7 +39,11 @@ describe('rejectDataTrigger', () => { const result = await rejectDataTrigger(documentTransition, context); expect(result).to.be.an.instanceOf(DataTriggerExecutionResult); - expect(result.getErrors()[0].message).to.equal('Action is not allowed'); + expect(result.isOk()).to.be.false(); + + const [error] = result.getErrors(); + + expect(error.message).to.equal('Action is not allowed'); }); }); diff --git a/test/unit/decodeProtocolEntityFactory.spec.js b/test/unit/decodeProtocolEntityFactory.spec.js index eeca3e11..4f9c4717 100644 --- a/test/unit/decodeProtocolEntityFactory.spec.js +++ b/test/unit/decodeProtocolEntityFactory.spec.js @@ -47,7 +47,6 @@ describe('decodeProtocolEntityFactory', () => { } catch (e) { expect(e).to.be.an.instanceOf(ProtocolVersionParsingError); - expect(e.getPayload()).to.equal(buffer); expect(e.getParsingError()).to.be.instanceOf(Error); expect(e.getCode()).to.equal(1000); } @@ -66,7 +65,6 @@ describe('decodeProtocolEntityFactory', () => { } catch (e) { expect(e).to.be.an.instanceOf(UnsupportedProtocolVersionError); - expect(e.getPayload()).to.equal(buffer); expect(e.getParsedProtocolVersion()).to.equal(parsedProtocolVersion); expect(e.getCurrentProtocolVersion()).to.equal(currentProtocolVersion); expect(e.getCode()).to.equal(1001); @@ -102,7 +100,6 @@ describe('decodeProtocolEntityFactory', () => { } catch (e) { expect(e).to.be.an.instanceOf(IncompatibleProtocolVersionError); - expect(e.getPayload()).to.equal(buffer); expect(e.getParsedProtocolVersion()).to.equal(parsedProtocolVersion); expect(e.getMinimalProtocolVersion()).to.equal(minimalProtocolVersion); expect(e.getCode()).to.equal(1002); @@ -119,7 +116,6 @@ describe('decodeProtocolEntityFactory', () => { } catch (e) { expect(e).to.be.an.instanceOf(SerializedObjectParsingError); - expect(e.getPayload()).to.equal(buffer); expect(e.getParsingError()).to.be.an.instanceOf(Error); expect(e.getCode()).to.equal(1003); } diff --git a/test/unit/document/DocumentFactory.spec.js b/test/unit/document/DocumentFactory.spec.js index 2e9f5d4a..7fb6b97f 100644 --- a/test/unit/document/DocumentFactory.spec.js +++ b/test/unit/document/DocumentFactory.spec.js @@ -20,11 +20,11 @@ const InvalidActionNameError = require('../../../lib/document/errors/InvalidActi const NoDocumentsSuppliedError = require('../../../lib/document/errors/NoDocumentsSuppliedError'); const MismatchOwnerIdsError = require('../../../lib/document/errors/MismatchOwnerIdsError'); const InvalidInitialRevisionError = require('../../../lib/document/errors/InvalidInitialRevisionError'); -const ConsensusError = require('../../../lib/errors/consensus/ConsensusError'); const SerializedObjectParsingError = require('../../../lib/errors/consensus/basic/decode/SerializedObjectParsingError'); const generateRandomIdentifier = require('../../../lib/test/utils/generateRandomIdentifier'); const createDPPMock = require('../../../lib/test/mocks/createDPPMock'); +const SomeConsensusError = require('../../../lib/test/mocks/SomeConsensusError'); describe('DocumentFactory', () => { let decodeProtocolEntityMock; @@ -191,7 +191,7 @@ describe('DocumentFactory', () => { }); it('should throw InvalidDocumentError if passed object is not valid', async () => { - const validationError = new ConsensusError('test'); + const validationError = new SomeConsensusError('test'); validateDocumentMock.returns( new ValidationResult([validationError]), @@ -216,7 +216,7 @@ describe('DocumentFactory', () => { }); it('should throw InvalidDocumentError if Data Contract is not valid', async () => { - const fetchContractError = new ConsensusError('error'); + const fetchContractError = new SomeConsensusError('error'); fetchAndValidateDataContractMock.returns( new ValidationResult([fetchContractError]), diff --git a/test/unit/document/fetchAndValidateDataContractFactory.spec.js b/test/unit/document/fetchAndValidateDataContractFactory.spec.js index 57652b33..7cb112f3 100644 --- a/test/unit/document/fetchAndValidateDataContractFactory.spec.js +++ b/test/unit/document/fetchAndValidateDataContractFactory.spec.js @@ -41,7 +41,7 @@ describe('fetchAndValidateDataContractFactory', () => { const [error] = result.getErrors(); - expect(error.getRawDocument()).to.equal(rawDocument); + expect(error.getCode()).to.equal(1025); }); it('should return with invalid result if Data Contract is not present', async () => { @@ -53,6 +53,7 @@ describe('fetchAndValidateDataContractFactory', () => { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(1018); expect(error.getDataContractId()).to.deep.equal(rawDocument.$dataContractId); }); diff --git a/test/unit/document/stateTransition/DocumetsBatchTransition/validation/basic/validatePartialCompoundIndices.spec.js b/test/unit/document/stateTransition/DocumetsBatchTransition/validation/basic/validatePartialCompoundIndices.spec.js index 2d37b9ea..de02c49c 100644 --- a/test/unit/document/stateTransition/DocumetsBatchTransition/validation/basic/validatePartialCompoundIndices.spec.js +++ b/test/unit/document/stateTransition/DocumetsBatchTransition/validation/basic/validatePartialCompoundIndices.spec.js @@ -32,12 +32,16 @@ describe('validatePartialCompoundIndices', () => { expectValidationError(result, InconsistentCompoundIndexDataError); - const { optionalUniqueIndexedDocument } = dataContract.getDocuments(); const [error] = result.getErrors(); - expect(error.getIndexDefinition()).to.deep.equal( - optionalUniqueIndexedDocument.indices[1], + expect(error.getCode()).to.equal(1021); + + const { optionalUniqueIndexedDocument } = dataContract.getDocuments(); + + expect(error.getIndexedProperties()).to.deep.equal( + optionalUniqueIndexedDocument.indices[1].properties.map((i) => Object.keys(i)[0]), ); + expect(error.getDocumentType()).to.equal('optionalUniqueIndexedDocument'); }); diff --git a/test/unit/document/stateTransition/DocumetsBatchTransition/validation/state/validateDocumentsBatchTransitionStateFactory.spec.js b/test/unit/document/stateTransition/DocumetsBatchTransition/validation/state/validateDocumentsBatchTransitionStateFactory.spec.js index 8c17a4a2..3115f283 100644 --- a/test/unit/document/stateTransition/DocumetsBatchTransition/validation/state/validateDocumentsBatchTransitionStateFactory.spec.js +++ b/test/unit/document/stateTransition/DocumetsBatchTransition/validation/state/validateDocumentsBatchTransitionStateFactory.spec.js @@ -21,13 +21,13 @@ const DataContractNotPresentError = require('../../../../../../../lib/errors/Dat const DocumentAlreadyPresentError = require('../../../../../../../lib/errors/consensus/state/document/DocumentAlreadyPresentError'); const DocumentNotFoundError = require('../../../../../../../lib/errors/consensus/state/document/DocumentNotFoundError'); const InvalidDocumentRevisionError = require('../../../../../../../lib/errors/consensus/state/document/InvalidDocumentRevisionError'); -const ConsensusError = require('../../../../../../../lib/errors/consensus/ConsensusError'); const InvalidDocumentActionError = require('../../../../../../../lib/document/errors/InvalidDocumentActionError'); const DocumentOwnerIdMismatchError = require('../../../../../../../lib/errors/consensus/state/document/DocumentOwnerIdMismatchError'); const DocumentTimestampsMismatchError = require('../../../../../../../lib/errors/consensus/state/document/DocumentTimestampsMismatchError'); const DocumentTimestampWindowViolationError = require('../../../../../../../lib/errors/consensus/state/document/DocumentTimestampWindowViolationError'); const generateRandomIdentifier = require('../../../../../../../lib/test/utils/generateRandomIdentifier'); +const SomeConsensusError = require('../../../../../../../lib/test/mocks/SomeConsensusError'); describe('validateDocumentsBatchTransitionStateFactory', () => { let validateDocumentsBatchTransitionState; @@ -42,6 +42,7 @@ describe('validateDocumentsBatchTransitionStateFactory', () => { let documentTransitions; let abciHeader; let fakeTime; + let blockTime; beforeEach(function beforeEach() { dataContract = getDataContractFixture(); @@ -67,9 +68,11 @@ describe('validateDocumentsBatchTransitionStateFactory', () => { }, }); + blockTime = new Date().getTime() / 1000; + abciHeader = { time: { - seconds: new Date().getTime() / 1000, + seconds: blockTime, }, }; @@ -127,8 +130,9 @@ describe('validateDocumentsBatchTransitionStateFactory', () => { const [error] = result.getErrors(); - expect(error.getDocumentTransition()).to.deep.equal(documentTransitions[0]); - expect(error.getFetchedDocument()).to.deep.equal(documents[0]); + expect(error.getCode()).to.equal(4004); + expect(Buffer.isBuffer(error.getDocumentId())).to.be.true(); + expect(error.getDocumentId()).to.deep.equal(documentTransitions[0].getId().toBuffer()); expect(stateRepositoryMock.fetchDataContract).to.have.been.calledOnceWithExactly( dataContract.getId(), @@ -160,7 +164,9 @@ describe('validateDocumentsBatchTransitionStateFactory', () => { const [error] = result.getErrors(); - expect(error.getDocumentTransition()).to.deep.equal(documentTransitions[0]); + expect(error.getCode()).to.equal(4005); + expect(Buffer.isBuffer(error.getDocumentId())).to.be.true(); + expect(error.getDocumentId()).to.deep.equal(documentTransitions[0].getId().toBuffer()); expect(stateRepositoryMock.fetchDataContract).to.have.been.calledOnceWithExactly( dataContract.getId(), @@ -192,7 +198,9 @@ describe('validateDocumentsBatchTransitionStateFactory', () => { const [error] = result.getErrors(); - expect(error.getDocumentTransition()).to.deep.equal(documentTransitions[0]); + expect(error.getCode()).to.equal(4005); + expect(Buffer.isBuffer(error.getDocumentId())).to.be.true(); + expect(error.getDocumentId()).to.deep.equal(documentTransitions[0].getId().toBuffer()); expect(stateRepositoryMock.fetchDataContract).to.have.been.calledOnceWithExactly( dataContract.getId(), @@ -230,8 +238,10 @@ describe('validateDocumentsBatchTransitionStateFactory', () => { const [error] = result.getErrors(); - expect(error.getDocumentTransition()).to.deep.equal(documentTransitions[0]); - expect(error.getFetchedDocument()).to.deep.equal(documents[0]); + expect(error.getCode()).to.equal(4010); + expect(Buffer.isBuffer(error.getDocumentId())).to.be.true(); + expect(error.getDocumentId()).to.deep.equal(documentTransitions[0].getId().toBuffer()); + expect(error.getCurrentRevision()).to.deep.equal(documents[0].getRevision()); expect(stateRepositoryMock.fetchDataContract).to.have.been.calledOnceWithExactly( dataContract.getId(), @@ -250,7 +260,7 @@ describe('validateDocumentsBatchTransitionStateFactory', () => { replaceDocument.setRevision(1); const fetchedDocument = new Document(documents[0].toObject(), dataContract); - fetchedDocument.ownerId = generateRandomIdentifier().toBuffer(); + fetchedDocument.ownerId = generateRandomIdentifier(); documentTransitions = getDocumentTransitionsFixture({ create: [], @@ -271,8 +281,19 @@ describe('validateDocumentsBatchTransitionStateFactory', () => { const [error] = result.getErrors(); - expect(error.getDocumentTransition()).to.deep.equal(documentTransitions[0]); - expect(error.getFetchedDocument()).to.deep.equal(fetchedDocument); + expect(error.getCode()).to.equal(4006); + expect(Buffer.isBuffer(error.getDocumentId())).to.be.true(); + expect(error.getDocumentId()).to.deep.equal(documentTransitions[0].getId().toBuffer()); + + expect(Buffer.isBuffer(error.getDocumentOwnerId())).to.be.true(); + expect(error.getDocumentOwnerId()).to.deep.equal( + replaceDocument.getOwnerId().toBuffer(), + ); + + expect(Buffer.isBuffer(error.getExistingDocumentOwnerId())).to.be.true(); + expect(error.getExistingDocumentOwnerId()).to.deep.equal( + fetchedDocument.getOwnerId().toBuffer(), + ); expect(stateRepositoryMock.fetchDataContract).to.have.been.calledOnceWithExactly( dataContract.getId(), @@ -321,7 +342,7 @@ describe('validateDocumentsBatchTransitionStateFactory', () => { }); it('should return invalid result if there are duplicate document transitions according to unique indices', async () => { - const duplicateDocumentsError = new ConsensusError('error'); + const duplicateDocumentsError = new SomeConsensusError('error'); validateDocumentsUniquenessByIndicesMock.resolves( new ValidationResult([duplicateDocumentsError]), @@ -385,6 +406,7 @@ describe('validateDocumentsBatchTransitionStateFactory', () => { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(4002); expect(error).to.equal(dataTriggerExecutionError); expect(stateRepositoryMock.fetchDataContract).to.have.been.calledOnceWithExactly( @@ -427,6 +449,21 @@ describe('validateDocumentsBatchTransitionStateFactory', () => { }); describe('Timestamps', () => { + let timeWindowStart; + let timeWindowEnd; + + beforeEach(() => { + timeWindowStart = new Date(blockTime * 1000); + timeWindowStart.setMinutes( + timeWindowStart.getMinutes() - 5, + ); + + timeWindowEnd = new Date(blockTime * 1000); + timeWindowEnd.setMinutes( + timeWindowEnd.getMinutes() + 5, + ); + }); + describe('CREATE transition', () => { it('should return invalid result if timestamps mismatch', async () => { documentTransitions = getDocumentTransitionsFixture({ @@ -450,9 +487,12 @@ describe('validateDocumentsBatchTransitionStateFactory', () => { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(4007); + documentTransitions[0].updatedAt = new Date(); - expect(error.getDocumentTransition()).to.deep.equal(documentTransitions[0]); + expect(Buffer.isBuffer(error.getDocumentId())).to.be.true(); + expect(error.getDocumentId()).to.deep.equal(documentTransitions[0].getId().toBuffer()); }); it('should return invalid result if "$createdAt" have violated time window', async () => { @@ -479,13 +519,19 @@ describe('validateDocumentsBatchTransitionStateFactory', () => { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(4008); + documentTransitions[0].createdAt.setMinutes( documentTransitions[0].createdAt.getMinutes() - 6, ); documentTransitions[0].updatedAt = undefined; - expect(error.getDocumentTransition()).to.deep.equal(documentTransitions[0]); + expect(Buffer.isBuffer(error.getDocumentId())).to.be.true(); + expect(error.getDocumentId()).to.deep.equal(documentTransitions[0].getId().toBuffer()); expect(error.getTimestampName()).to.equal('createdAt'); + expect(error.getTimestamp()).to.deep.equal(documentTransitions[0].createdAt); + expect(error.getTimeWindowStart()).to.deep.equal(timeWindowStart); + expect(error.getTimeWindowEnd()).to.deep.equal(timeWindowEnd); }); it('should return invalid result if "$updatedAt" have violated time window', async () => { @@ -512,13 +558,19 @@ describe('validateDocumentsBatchTransitionStateFactory', () => { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(4008); + documentTransitions[0].updatedAt.setMinutes( documentTransitions[0].updatedAt.getMinutes() - 6, ); documentTransitions[0].createdAt = undefined; - expect(error.getDocumentTransition()).to.deep.equal(documentTransitions[0]); + expect(Buffer.isBuffer(error.getDocumentId())).to.be.true(); + expect(error.getDocumentId()).to.deep.equal(documentTransitions[0].getId().toBuffer()); expect(error.getTimestampName()).to.equal('updatedAt'); + expect(error.getTimestamp()).to.deep.equal(documentTransitions[0].updatedAt); + expect(error.getTimeWindowStart()).to.deep.equal(timeWindowStart); + expect(error.getTimeWindowEnd()).to.deep.equal(timeWindowEnd); }); }); @@ -552,13 +604,18 @@ describe('validateDocumentsBatchTransitionStateFactory', () => { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(4008); + documentTransitions[0].updatedAt.setMinutes( documentTransitions[0].updatedAt.getMinutes() - 6, ); - expect(error.getDocumentTransition()).to.deep.equal(documentTransitions[0]); - expect(error.getFetchedDocument()).to.deep.equal(documents[1]); + expect(Buffer.isBuffer(error.getDocumentId())).to.be.true(); + expect(error.getDocumentId()).to.deep.equal(documentTransitions[0].getId().toBuffer()); expect(error.getTimestampName()).to.equal('updatedAt'); + expect(error.getTimestamp()).to.deep.equal(documentTransitions[0].updatedAt); + expect(error.getTimeWindowStart()).to.deep.equal(timeWindowStart); + expect(error.getTimeWindowEnd()).to.deep.equal(timeWindowEnd); }); }); }); diff --git a/test/unit/document/stateTransition/DocumetsBatchTransition/validation/state/validateDocumentsUniquenessByIndicesFactory.spec.js b/test/unit/document/stateTransition/DocumetsBatchTransition/validation/state/validateDocumentsUniquenessByIndicesFactory.spec.js index 32778c10..22c2d672 100644 --- a/test/unit/document/stateTransition/DocumetsBatchTransition/validation/state/validateDocumentsUniquenessByIndicesFactory.spec.js +++ b/test/unit/document/stateTransition/DocumetsBatchTransition/validation/state/validateDocumentsUniquenessByIndicesFactory.spec.js @@ -9,7 +9,7 @@ const createStateRepositoryMock = require('../../../../../../../lib/test/mocks/c const ValidationResult = require('../../../../../../../lib/validation/ValidationResult'); -const DuplicateDocumentError = require('../../../../../../../lib/errors/consensus/state/document/DuplicateDocumentError'); +const DuplicateUniqueIndexError = require('../../../../../../../lib/errors/consensus/state/document/DuplicateUniqueIndexError'); describe('validateDocumentsUniquenessByIndices', () => { let stateRepositoryMock; @@ -149,22 +149,26 @@ describe('validateDocumentsUniquenessByIndices', () => { ownerId, documentTransitions, dataContract, ); - expectValidationError(result, DuplicateDocumentError, 4); + expectValidationError(result, DuplicateUniqueIndexError, 4); const errors = result.getErrors(); - expect(errors.map((e) => e.getDocumentTransition())).to.have.deep.members([ - documentTransitions[3], - documentTransitions[3], - documentTransitions[4], - documentTransitions[4], + const [error] = result.getErrors(); + + expect(error.getCode()).to.equal(4009); + + expect(errors.map((e) => e.getDocumentId())).to.have.deep.members([ + documentTransitions[3].getId().toBuffer(), + documentTransitions[3].getId().toBuffer(), + documentTransitions[4].getId().toBuffer(), + documentTransitions[4].getId().toBuffer(), ]); - expect(errors.map((e) => e.getIndexDefinition())).to.have.deep.members([ - indicesDefinition[0], - indicesDefinition[1], - indicesDefinition[0], - indicesDefinition[1], + expect(errors.map((e) => e.getDuplicatingProperties())).to.have.deep.members([ + indicesDefinition[0].properties.map((i) => Object.keys(i)[0]), + indicesDefinition[1].properties.map((i) => Object.keys(i)[0]), + indicesDefinition[0].properties.map((i) => Object.keys(i)[0]), + indicesDefinition[1].properties.map((i) => Object.keys(i)[0]), ]); }); diff --git a/test/unit/identity/IdentityFactory.spec.js b/test/unit/identity/IdentityFactory.spec.js index 60fda16c..6efdf92c 100644 --- a/test/unit/identity/IdentityFactory.spec.js +++ b/test/unit/identity/IdentityFactory.spec.js @@ -9,7 +9,6 @@ const IdentityTopUpTransition = require('../../../lib/identity/stateTransition/I const getIdentityFixture = require('../../../lib/test/fixtures/getIdentityFixture'); const ValidationResult = require('../../../lib/validation/ValidationResult'); -const ConsensusError = require('../../../lib/errors/consensus/ConsensusError'); const SerializedObjectParsingError = require('../../../lib/errors/consensus/basic/decode/SerializedObjectParsingError'); const InvalidIdentityError = require( @@ -19,6 +18,7 @@ const getInstantAssetLockProofFixture = require('../../../lib/test/fixtures/getI const InstantAssetLockProof = require('../../../lib/identity/stateTransition/assetLockProof/instant/InstantAssetLockProof'); const getChainAssetLockProofFixture = require('../../../lib/test/fixtures/getChainAssetLockProofFixture'); const createDPPMock = require('../../../lib/test/mocks/createDPPMock'); +const SomeConsensusError = require('../../../lib/test/mocks/SomeConsensusError'); describe('IdentityFactory', () => { let factory; @@ -92,7 +92,7 @@ describe('IdentityFactory', () => { }); it('should throw an error if validation have failed', () => { - const errors = [new ConsensusError('error')]; + const errors = [new SomeConsensusError('error')]; validateIdentityMock.returns(new ValidationResult(errors)); diff --git a/test/unit/identity/stateTransition/IdentityCreateTransition/validation/state/validateIdentityCreateTransitionStateFactory.spec.js b/test/unit/identity/stateTransition/IdentityCreateTransition/validation/state/validateIdentityCreateTransitionStateFactory.spec.js index c613675a..51da315d 100644 --- a/test/unit/identity/stateTransition/IdentityCreateTransition/validation/state/validateIdentityCreateTransitionStateFactory.spec.js +++ b/test/unit/identity/stateTransition/IdentityCreateTransition/validation/state/validateIdentityCreateTransitionStateFactory.spec.js @@ -51,8 +51,9 @@ describe('validateIdentityCreateTransitionStateFactory', () => { const [error] = result.getErrors(); - expect(error.message).to.equal(`Identity with id ${stateTransition.getIdentityId()} already exists`); - expect(error.getStateTransition()).to.deep.equal(stateTransition); + expect(error.getCode()).to.equal(4011); + expect(Buffer.isBuffer(error.getIdentityId())).to.be.true(); + expect(error.getIdentityId()).to.deep.equal(stateTransition.getIdentityId()); }); it('should return invalid result if identity public key already exists', async () => { diff --git a/test/unit/identity/stateTransition/IdentityCreateTransition/validation/state/validateIdentityPublicKeysUniquenessFactory.spec.js b/test/unit/identity/stateTransition/IdentityCreateTransition/validation/state/validateIdentityPublicKeysUniquenessFactory.spec.js index a00cce4e..01e1baa1 100644 --- a/test/unit/identity/stateTransition/IdentityCreateTransition/validation/state/validateIdentityPublicKeysUniquenessFactory.spec.js +++ b/test/unit/identity/stateTransition/IdentityCreateTransition/validation/state/validateIdentityPublicKeysUniquenessFactory.spec.js @@ -45,6 +45,7 @@ describe('validateIdentityPublicKeysUniquenessFactory', () => { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(4012); expect(error.getPublicKeyHash()).to.deep.equal(identity.getPublicKeyById(0).hash()); }); diff --git a/test/unit/identity/validation/validateIdentityExistenceFactory.spec.js b/test/unit/identity/validation/validateIdentityExistenceFactory.spec.js index 9180112e..3c0174a9 100644 --- a/test/unit/identity/validation/validateIdentityExistenceFactory.spec.js +++ b/test/unit/identity/validation/validateIdentityExistenceFactory.spec.js @@ -32,7 +32,9 @@ describe('validateIdentityExistence', () => { const [error] = result.getErrors(); - expect(error.getIdentityId()).to.equal(identity.getId()); + expect(error.getCode()).to.equal(2000); + expect(Buffer.isBuffer(error.getIdentityId())).to.be.true(); + expect(error.getIdentityId()).to.deep.equal(identity.getId().toBuffer()); }); it('should return valid result', async () => { diff --git a/test/unit/stateTransition/StateTransitionFactory.spec.js b/test/unit/stateTransition/StateTransitionFactory.spec.js index 59c747ec..d9e9f7e8 100644 --- a/test/unit/stateTransition/StateTransitionFactory.spec.js +++ b/test/unit/stateTransition/StateTransitionFactory.spec.js @@ -6,11 +6,11 @@ const ValidationResult = require('../../../lib/validation/ValidationResult'); const InvalidStateTransitionError = require('../../../lib/stateTransition/errors/InvalidStateTransitionError'); -const ConsensusError = require('../../../lib/errors/consensus/ConsensusError'); const SerializedObjectParsingError = require('../../../lib/errors/consensus/basic/decode/SerializedObjectParsingError'); const createDPPMock = require('../../../lib/test/mocks/createDPPMock'); const StateTransitionFactory = require('../../../lib/stateTransition/StateTransitionFactory'); +const SomeConsensusError = require('../../../lib/test/mocks/SomeConsensusError'); describe('StateTransitionFactory', () => { let validateStateTransitionBasicMock; @@ -69,7 +69,7 @@ describe('StateTransitionFactory', () => { }); it('should throw InvalidStateTransitionError if passed object is not valid', async () => { - const validationError = new ConsensusError('test'); + const validationError = new SomeConsensusError('test'); validateStateTransitionBasicMock.returns(new ValidationResult([validationError])); diff --git a/test/unit/stateTransition/validation/validateStateTransitionBasicFactory.spec.js b/test/unit/stateTransition/validation/validateStateTransitionBasicFactory.spec.js index 5f8d0422..4997f117 100644 --- a/test/unit/stateTransition/validation/validateStateTransitionBasicFactory.spec.js +++ b/test/unit/stateTransition/validation/validateStateTransitionBasicFactory.spec.js @@ -14,10 +14,10 @@ const { const ValidationResult = require('../../../../lib/validation/ValidationResult'); -const ConsensusError = require('../../../../lib/errors/consensus/ConsensusError'); const MissingStateTransitionTypeError = require('../../../../lib/errors/consensus/basic/stateTransition/MissingStateTransitionTypeError'); const InvalidStateTransitionTypeError = require('../../../../lib/errors/consensus/basic/stateTransition/InvalidStateTransitionTypeError'); const createDPPMock = require('../../../../lib/test/mocks/createDPPMock'); +const SomeConsensusError = require('../../../../lib/test/mocks/SomeConsensusError'); describe('validateStateTransitionBasicFactory', () => { let validateStateTransitionBasic; @@ -83,7 +83,7 @@ describe('validateStateTransitionBasicFactory', () => { }); it('should return invalid result if ST is invalid against validation function', async () => { - const extensionError = new ConsensusError('test'); + const extensionError = new SomeConsensusError('test'); const extensionResult = new ValidationResult([ extensionError, ]); @@ -116,6 +116,10 @@ describe('validateStateTransitionBasicFactory', () => { ); expectValidationError(result, StateTransitionMaxSizeExceededError); + + const [error] = result.getErrors(); + + expect(error.getCode()).to.equal(1045); }); it('should return valid result', async () => { diff --git a/test/unit/stateTransition/validation/validateStateTransitionFeeFactory.spec.js b/test/unit/stateTransition/validation/validateStateTransitionFeeFactory.spec.js index 04130828..5e631877 100644 --- a/test/unit/stateTransition/validation/validateStateTransitionFeeFactory.spec.js +++ b/test/unit/stateTransition/validation/validateStateTransitionFeeFactory.spec.js @@ -66,6 +66,7 @@ describe('validateStateTransitionFeeFactory', () => { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(3000); expect(error.getBalance()).to.equal(identity.balance); expect(stateRepositoryMock.fetchIdentity).to.be.calledOnceWithExactly( @@ -124,6 +125,7 @@ describe('validateStateTransitionFeeFactory', () => { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(3000); expect(error.getBalance()).to.equal(identity.balance); expect(stateRepositoryMock.fetchIdentity).to.be.calledOnceWithExactly( @@ -179,6 +181,7 @@ describe('validateStateTransitionFeeFactory', () => { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(3000); expect(error.getBalance()).to.equal(outputAmount); expect(stateRepositoryMock.fetchIdentity).to.be.not.called(); @@ -236,6 +239,7 @@ describe('validateStateTransitionFeeFactory', () => { const [error] = result.getErrors(); + expect(error.getCode()).to.equal(3000); expect(error.getBalance()).to.equal(outputAmount + identity.balance); expect(stateRepositoryMock.fetchIdentity).to.be.calledOnceWithExactly( diff --git a/test/unit/stateTransition/validation/validateStateTransitionIdentitySignatureFactory.spec.js b/test/unit/stateTransition/validation/validateStateTransitionIdentitySignatureFactory.spec.js index 042021e3..3ed9df44 100644 --- a/test/unit/stateTransition/validation/validateStateTransitionIdentitySignatureFactory.spec.js +++ b/test/unit/stateTransition/validation/validateStateTransitionIdentitySignatureFactory.spec.js @@ -5,9 +5,9 @@ const InvalidIdentityPublicKeyTypeError = require('../../../../lib/errors/consen const InvalidStateTransitionSignatureError = require('../../../../lib/errors/consensus/signature/InvalidStateTransitionSignatureError'); const MissingPublicKeyError = require('../../../../lib/errors/consensus/signature/MissingPublicKeyError'); const generateRandomIdentifier = require('../../../../lib/test/utils/generateRandomIdentifier'); -const ConsensusError = require('../../../../lib/errors/consensus/ConsensusError'); const { expectValidationError } = require('../../../../lib/test/expect/expectError'); +const SomeConsensusError = require('../../../../lib/test/mocks/SomeConsensusError'); describe('validateStateTransitionIdentitySignatureFactory', () => { let validateStateTransitionIdentitySignature; @@ -71,7 +71,7 @@ describe('validateStateTransitionIdentitySignatureFactory', () => { }); it('should return invalid result if owner id doesn\'t exist', async () => { - const consensusError = new ConsensusError('error'); + const consensusError = new SomeConsensusError('error'); validateIdentityExistenceResult.addError(consensusError); @@ -159,7 +159,6 @@ describe('validateStateTransitionIdentitySignatureFactory', () => { const [error] = result.getErrors(); expect(error).to.be.instanceOf(InvalidStateTransitionSignatureError); - expect(error.getRawStateTransition()).to.equal(stateTransition); expect(validateIdentityExistenceMock).to.be.calledOnceWithExactly(ownerId); expect(identity.getPublicKeyById).to.be.calledOnceWithExactly(publicKeyId); diff --git a/test/unit/stateTransition/validation/validateStateTransitionKeySignatureFactory.spec.js b/test/unit/stateTransition/validation/validateStateTransitionKeySignatureFactory.spec.js index cf81e9d3..f0f84f01 100644 --- a/test/unit/stateTransition/validation/validateStateTransitionKeySignatureFactory.spec.js +++ b/test/unit/stateTransition/validation/validateStateTransitionKeySignatureFactory.spec.js @@ -40,6 +40,10 @@ describe('validateStateTransitionKeySignatureFactory', () => { expectValidationError(result, InvalidStateTransitionSignatureError); + const [error] = result.getErrors(); + + expect(error.getCode()).to.equal(2002); + expect(fetchAssetLockPublicKeyHashMock).to.be.calledOnceWithExactly( stateTransition.getAssetLockProof(), ); diff --git a/test/unit/stateTransition/validation/validateStateTransitionStateFactory.spec.js b/test/unit/stateTransition/validation/validateStateTransitionStateFactory.spec.js index 2b80ff5d..7a98631f 100644 --- a/test/unit/stateTransition/validation/validateStateTransitionStateFactory.spec.js +++ b/test/unit/stateTransition/validation/validateStateTransitionStateFactory.spec.js @@ -11,8 +11,8 @@ const ValidationResult = require('../../../../lib/validation/ValidationResult'); const DataContractFactory = require('../../../../lib/dataContract/DataContractFactory'); const InvalidStateTransitionTypeError = require('../../../../lib/stateTransition/errors/InvalidStateTransitionTypeError'); -const ConsensusError = require('../../../../lib/errors/consensus/ConsensusError'); const createDPPMock = require('../../../../lib/test/mocks/createDPPMock'); +const SomeConsensusError = require('../../../../lib/test/mocks/SomeConsensusError'); describe('validateStateTransitionStateFactory', () => { let validateDataContractSTDataMock; @@ -56,7 +56,7 @@ describe('validateStateTransitionStateFactory', () => { }); it('should return invalid result if Data Contract State Transition is not valid', async () => { - const dataContractError = new ConsensusError('test'); + const dataContractError = new SomeConsensusError('test'); const dataContractResult = new ValidationResult([ dataContractError, ]);