@dashevo/wasm-dpp 0.23.0-dev.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc +5 -0
- package/.editorconfig +13 -0
- package/.eslintignore +1 -0
- package/.eslintrc +15 -0
- package/.mocharc.yml +4 -0
- package/CHANGELOG.md +397 -0
- package/LICENSE +20 -0
- package/README.md +37 -0
- package/karma.conf.js +53 -0
- package/package.json +107 -0
- package/test/.eslintrc +12 -0
- package/test/integration/DashPlatformProtocol.spec.js +53 -0
- package/test/integration/ajv/keywords/byteArray/addByteArrayKeyword.spec.js +148 -0
- package/test/integration/dataContract/DataContractFacade.spec.js +84 -0
- package/test/integration/dataContract/stateTransition/DataContractCreateTransition/validation/basic/validateDataContractCreateTransitionBasicFactory.spec.js +357 -0
- package/test/integration/dataContract/stateTransition/DataContractUpdateTransition/validation/basic/validateDataContractUpdateTransitionBasicFactory.spec.js +444 -0
- package/test/integration/dataContract/validation/validateDataContractFactory.spec.js +2191 -0
- package/test/integration/document/Document.spec.js +90 -0
- package/test/integration/document/DocumentFacade.spec.js +155 -0
- package/test/integration/document/stateTransition/DocumentsBatchTransition/DocumentBatchTransition.spec.js +83 -0
- package/test/integration/document/stateTransition/DocumentsBatchTransition/validation/basic/validateDocumentsBatchTransitionBasicFactory.spec.js +1146 -0
- package/test/integration/document/stateTransition/DocumentsBatchTransition/validation/state/executeDataTriggersFactory.spec.js +294 -0
- package/test/integration/document/validation/validateDocumentFactory.spec.js +447 -0
- package/test/integration/error/consensus/createConsensusError.spec.js +21 -0
- package/test/integration/identity/IdentityFacade.spec.js +187 -0
- package/test/integration/identity/stateTransition/IdentityCreateTransition/validation/basic/validateIdentityCreateTransitionBasicFactory.spec.js +422 -0
- package/test/integration/identity/stateTransition/IdentityTopUpTransition/validation/basic/validateIdentityTopUpTransitionBasicFactory.spec.js +361 -0
- package/test/integration/identity/stateTransition/IdentityUpdateTransition/validation/basic/validateIdentityUpdateTransitionBasicFactory.spec.js +595 -0
- package/test/integration/identity/stateTransition/IdentityUpdateTransition/validation/state/validateIdentityUpdateTransitionStateFactory.spec.js +299 -0
- package/test/integration/identity/stateTransition/IdentityUpdateTransition/validation/state/validatePublicKeysState.spec.js +66 -0
- package/test/integration/identity/stateTransition/assetLockProof/chain/validateChainAssetLockProofStructureFactory.spec.js +415 -0
- package/test/integration/identity/stateTransition/assetLockProof/fetchAssetLockTransactionOutputFactory.spec.js +134 -0
- package/test/integration/identity/stateTransition/assetLockProof/instant/validateInstantAssetLockProofStructureFactory.spec.js +401 -0
- package/test/integration/identity/stateTransition/assetLockProof/validateAssetLockTransactionFactory.spec.js +205 -0
- package/test/integration/identity/stateTransition/validatePublicKeySignaturesFactory.spec.js +127 -0
- package/test/integration/identity/validation/validateIdentityFactory.spec.js +370 -0
- package/test/integration/identity/validation/validatePublicKeysFactory.spec.js +497 -0
- package/test/integration/stateTransition/AbstractStateTransitionIdentitySigned.spec.js +507 -0
- package/test/integration/stateTransition/StateTransitionFacade.spec.js +418 -0
- package/test/integration/stateTransition/calculateStateTransitionFee.spec.js +35 -0
- package/test/integration/util/generateEntropy.spec.js +17 -0
- package/test/integration/util/serializer.spec.js +24 -0
- package/test/unit/DashPlatformProtocol.spec.js +79 -0
- package/test/unit/Identifier.spec.js +123 -0
- package/test/unit/Metadata.spec.js +37 -0
- package/test/unit/dataContract/DataContract.spec.js +407 -0
- package/test/unit/dataContract/DataContractFactory.spec.js +178 -0
- package/test/unit/dataContract/createDataContract.spec.js +57 -0
- package/test/unit/dataContract/errors/InvalidDataContractError.spec.js +46 -0
- package/test/unit/dataContract/generateDataContractId.spec.js +19 -0
- package/test/unit/dataContract/getBinaryPropertiesFromSchema.spec.js +103 -0
- package/test/unit/dataContract/getPropertyDefinitionByPath.spec.js +84 -0
- package/test/unit/dataContract/stateTransition/DataContractCreateTransition/DataContractCreateTransition.spec.js +160 -0
- package/test/unit/dataContract/stateTransition/DataContractCreateTransition/applyDataContractCreateTransitionFactory.spec.js +48 -0
- package/test/unit/dataContract/stateTransition/DataContractCreateTransition/validation/state/validateDataContractCreateTransitionStateFactory.spec.js +85 -0
- package/test/unit/dataContract/stateTransition/DataContractUpdateTransition/DataContractUpdateTransition.spec.js +158 -0
- package/test/unit/dataContract/stateTransition/DataContractUpdateTransition/applyDataContractUpdateTransitionFactory.spec.js +47 -0
- package/test/unit/dataContract/stateTransition/DataContractUpdateTransition/validation/basic/validateIndicesAreBackwardCompatible.spec.js +121 -0
- package/test/unit/dataContract/stateTransition/DataContractUpdateTransition/validation/state/validateDataContractUpdateTransitionStateFactory.spec.js +111 -0
- package/test/unit/dataContract/validation/validateDataContractMaxDepthFactory.spec.js +93 -0
- package/test/unit/dataContract/validation/validateDataContractPatternsFactory.spec.js +64 -0
- package/test/unit/dataTrigger/DataTrigger.spec.js +132 -0
- package/test/unit/dataTrigger/DataTriggerExecutionContext.spec.js +29 -0
- package/test/unit/dataTrigger/dashpayDataTriggers/createContactRequestDataTrigger.spec.js +109 -0
- package/test/unit/dataTrigger/dpnsTriggers/createDomainDataTrigger.spec.js +382 -0
- package/test/unit/dataTrigger/featureFlagDataTriggers/createFeatureFlagDataTrigger.spec.js +101 -0
- package/test/unit/dataTrigger/getDataTriggersFactory.spec.js +113 -0
- package/test/unit/dataTrigger/rejectDataTrigger.spec.js +51 -0
- package/test/unit/dataTrigger/rewardShareDataTriggers/createMasternodeRewardSharesDataTrigger.spec.js +200 -0
- package/test/unit/decodeProtocolEntityFactory.spec.js +75 -0
- package/test/unit/document/Document.spec.js +444 -0
- package/test/unit/document/DocumentFactory.spec.js +376 -0
- package/test/unit/document/errors/InvalidDocumentError.spec.js +46 -0
- package/test/unit/document/fetchAndValidateDataContractFactory.spec.js +66 -0
- package/test/unit/document/stateTransition/DocumetsBatchTransition/DocumentsBatchTransition.spec.js +168 -0
- package/test/unit/document/stateTransition/DocumetsBatchTransition/applyDocumentsBatchTransitionFactory.spec.js +171 -0
- package/test/unit/document/stateTransition/DocumetsBatchTransition/documentTransition/DocumentCreateTransition.spec.js +25 -0
- package/test/unit/document/stateTransition/DocumetsBatchTransition/validation/basic/findDuplicatesById.spec.js +31 -0
- package/test/unit/document/stateTransition/DocumetsBatchTransition/validation/basic/findDuplicatesByIndices.spec.js +122 -0
- package/test/unit/document/stateTransition/DocumetsBatchTransition/validation/basic/validatePartialCompoundIndices.spec.js +75 -0
- package/test/unit/document/stateTransition/DocumetsBatchTransition/validation/state/fetchDocumentsFactory.spec.js +128 -0
- package/test/unit/document/stateTransition/DocumetsBatchTransition/validation/state/validateDocumentsBatchTransitionStateFactory.spec.js +811 -0
- package/test/unit/document/stateTransition/DocumetsBatchTransition/validation/state/validateDocumentsUniquenessByIndicesFactory.spec.js +279 -0
- package/test/unit/errors/consensus/codes.spec.js +102 -0
- package/test/unit/identity/Identity.spec.js +243 -0
- package/test/unit/identity/IdentityFactory.spec.js +274 -0
- package/test/unit/identity/IdentityPublicKey.spec.js +273 -0
- package/test/unit/identity/creditsConverter.spec.js +34 -0
- package/test/unit/identity/errors/InvalidIdentityError.spec.js +46 -0
- package/test/unit/identity/stateTransition/IdentityCreateTransition/IdentityCreateTransition.spec.js +184 -0
- package/test/unit/identity/stateTransition/IdentityCreateTransition/applyIdentityCreateTransitionFactory.spec.js +90 -0
- package/test/unit/identity/stateTransition/IdentityCreateTransition/validation/state/validateIdentityCreateTransitionStateFactory.spec.js +71 -0
- package/test/unit/identity/stateTransition/IdentityTopUpTransition/IdentityTopUpTransition.spec.js +137 -0
- package/test/unit/identity/stateTransition/IdentityTopUpTransition/applyIdentityTopUpTransitionFactory.spec.js +108 -0
- package/test/unit/identity/stateTransition/IdentityTopUpTransition/validation/state/validateIdentityTopUpTransitionStateFactory.spec.js +22 -0
- package/test/unit/identity/stateTransition/IdentityUpdateTransition/IdentityUpdateTransition.spec.js +219 -0
- package/test/unit/identity/stateTransition/IdentityUpdateTransition/applyIdentityUpdateTransitionFactory.spec.js +149 -0
- package/test/unit/identity/stateTransition/assetLockProof/createAssetLockProofInstance.spec.js +21 -0
- package/test/unit/identity/stateTransition/assetLockProof/fetchAssetLockPublicKeyHashFactory.spec.js +36 -0
- package/test/unit/identity/validation/validateRequiredPurposeAndSecurityLevelFactory.spec.js +47 -0
- package/test/unit/stateTransition/StateTransitionFactory.spec.js +160 -0
- package/test/unit/stateTransition/createStateTransitionFactory.spec.js +72 -0
- package/test/unit/stateTransition/errors/InvalidStateTransitionError.spec.js +51 -0
- package/test/unit/stateTransition/validation/validateStateTransitionBasicFactory.spec.js +138 -0
- package/test/unit/stateTransition/validation/validateStateTransitionFeeFactory.spec.js +372 -0
- package/test/unit/stateTransition/validation/validateStateTransitionIdentitySignatureFactory.spec.js +339 -0
- package/test/unit/stateTransition/validation/validateStateTransitionKeySignatureFactory.spec.js +86 -0
- package/test/unit/stateTransition/validation/validateStateTransitionStateFactory.spec.js +89 -0
- package/test/unit/version/validateProtocolVersionFactory.spec.js +80 -0
- package/webpack.config.js +49 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
const verifyDocumentsUniquenessByIndicesFactory = require('../../../../../../../lib/document/stateTransition/DocumentsBatchTransition/validation/state/validateDocumentsUniquenessByIndicesFactory');
|
|
2
|
+
|
|
3
|
+
const getDocumentsFixture = require('../../../../../../../lib/test/fixtures/getDocumentsFixture');
|
|
4
|
+
const getContractFixture = require('../../../../../../../lib/test/fixtures/getDataContractFixture');
|
|
5
|
+
const getDocumentTransitionsFixture = require('../../../../../../../lib/test/fixtures/getDocumentTransitionsFixture');
|
|
6
|
+
|
|
7
|
+
const { expectValidationError } = require('../../../../../../../lib/test/expect/expectError');
|
|
8
|
+
const createStateRepositoryMock = require('../../../../../../../lib/test/mocks/createStateRepositoryMock');
|
|
9
|
+
|
|
10
|
+
const ValidationResult = require('../../../../../../../lib/validation/ValidationResult');
|
|
11
|
+
|
|
12
|
+
const DuplicateUniqueIndexError = require('../../../../../../../lib/errors/consensus/state/document/DuplicateUniqueIndexError');
|
|
13
|
+
const StateTransitionExecutionContext = require('../../../../../../../lib/stateTransition/StateTransitionExecutionContext');
|
|
14
|
+
|
|
15
|
+
describe('validateDocumentsUniquenessByIndices', () => {
|
|
16
|
+
let stateRepositoryMock;
|
|
17
|
+
let validateDocumentsUniquenessByIndices;
|
|
18
|
+
let documents;
|
|
19
|
+
let documentTransitions;
|
|
20
|
+
let dataContract;
|
|
21
|
+
let ownerId;
|
|
22
|
+
let executionContext;
|
|
23
|
+
|
|
24
|
+
beforeEach(function beforeEach() {
|
|
25
|
+
({ ownerId } = getDocumentsFixture);
|
|
26
|
+
|
|
27
|
+
documents = getDocumentsFixture(dataContract);
|
|
28
|
+
documentTransitions = getDocumentTransitionsFixture({
|
|
29
|
+
create: documents,
|
|
30
|
+
});
|
|
31
|
+
dataContract = getContractFixture();
|
|
32
|
+
|
|
33
|
+
stateRepositoryMock = createStateRepositoryMock(this.sinonSandbox);
|
|
34
|
+
stateRepositoryMock.fetchDocuments.resolves([]);
|
|
35
|
+
|
|
36
|
+
executionContext = new StateTransitionExecutionContext();
|
|
37
|
+
|
|
38
|
+
validateDocumentsUniquenessByIndices = verifyDocumentsUniquenessByIndicesFactory(
|
|
39
|
+
stateRepositoryMock,
|
|
40
|
+
);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should return valid result if Documents have no unique indices', async () => {
|
|
44
|
+
const [niceDocument] = documents;
|
|
45
|
+
const noIndexDocumentTransitions = getDocumentTransitionsFixture({
|
|
46
|
+
create: [niceDocument],
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const result = await validateDocumentsUniquenessByIndices(
|
|
50
|
+
ownerId,
|
|
51
|
+
noIndexDocumentTransitions,
|
|
52
|
+
dataContract,
|
|
53
|
+
executionContext,
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
expect(result).to.be.an.instanceOf(ValidationResult);
|
|
57
|
+
expect(result.isValid()).to.be.true();
|
|
58
|
+
expect(stateRepositoryMock.fetchDocuments).to.have.not.been.called();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('should return valid result if Document has unique indices and there are no duplicates', async () => {
|
|
62
|
+
const [, , , william] = documents;
|
|
63
|
+
|
|
64
|
+
stateRepositoryMock.fetchDocuments
|
|
65
|
+
.withArgs(
|
|
66
|
+
dataContract.getId().toBuffer(),
|
|
67
|
+
william.getType(),
|
|
68
|
+
{
|
|
69
|
+
where: [
|
|
70
|
+
['$ownerId', '==', ownerId],
|
|
71
|
+
['firstName', '==', william.get('firstName')],
|
|
72
|
+
],
|
|
73
|
+
},
|
|
74
|
+
)
|
|
75
|
+
.resolves([william]);
|
|
76
|
+
|
|
77
|
+
stateRepositoryMock.fetchDocuments
|
|
78
|
+
.withArgs(
|
|
79
|
+
dataContract.getId().toBuffer(),
|
|
80
|
+
william.getType(),
|
|
81
|
+
{
|
|
82
|
+
where: [
|
|
83
|
+
['$ownerId', '==', ownerId],
|
|
84
|
+
['lastName', '==', william.get('lastName')],
|
|
85
|
+
],
|
|
86
|
+
},
|
|
87
|
+
)
|
|
88
|
+
.resolves([william]);
|
|
89
|
+
|
|
90
|
+
const result = await validateDocumentsUniquenessByIndices(
|
|
91
|
+
ownerId,
|
|
92
|
+
documentTransitions,
|
|
93
|
+
dataContract,
|
|
94
|
+
executionContext,
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
expect(result).to.be.an.instanceOf(ValidationResult);
|
|
98
|
+
expect(result.isValid()).to.be.true();
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('should return invalid result if Document has unique indices and there are duplicates', async () => {
|
|
102
|
+
const [, , , william, leon] = documents;
|
|
103
|
+
|
|
104
|
+
const indicesDefinition = dataContract.getDocumentSchema(william.getType()).indices;
|
|
105
|
+
|
|
106
|
+
stateRepositoryMock.fetchDocuments
|
|
107
|
+
.withArgs(
|
|
108
|
+
dataContract.getId(),
|
|
109
|
+
william.getType(),
|
|
110
|
+
{
|
|
111
|
+
where: [
|
|
112
|
+
['$ownerId', '==', ownerId],
|
|
113
|
+
['firstName', '==', william.get('firstName')],
|
|
114
|
+
],
|
|
115
|
+
},
|
|
116
|
+
)
|
|
117
|
+
.resolves([leon]);
|
|
118
|
+
|
|
119
|
+
stateRepositoryMock.fetchDocuments
|
|
120
|
+
.withArgs(
|
|
121
|
+
dataContract.getId(),
|
|
122
|
+
william.getType(),
|
|
123
|
+
{
|
|
124
|
+
where: [
|
|
125
|
+
['$ownerId', '==', ownerId],
|
|
126
|
+
['lastName', '==', william.get('lastName')],
|
|
127
|
+
],
|
|
128
|
+
},
|
|
129
|
+
)
|
|
130
|
+
.resolves([leon]);
|
|
131
|
+
|
|
132
|
+
stateRepositoryMock.fetchDocuments
|
|
133
|
+
.withArgs(
|
|
134
|
+
dataContract.getId(),
|
|
135
|
+
leon.getType(),
|
|
136
|
+
{
|
|
137
|
+
where: [
|
|
138
|
+
['$ownerId', '==', ownerId],
|
|
139
|
+
['firstName', '==', leon.get('firstName')],
|
|
140
|
+
],
|
|
141
|
+
},
|
|
142
|
+
)
|
|
143
|
+
.resolves([william]);
|
|
144
|
+
|
|
145
|
+
stateRepositoryMock.fetchDocuments
|
|
146
|
+
.withArgs(
|
|
147
|
+
dataContract.getId(),
|
|
148
|
+
leon.getType(),
|
|
149
|
+
{
|
|
150
|
+
where: [
|
|
151
|
+
['$ownerId', '==', ownerId],
|
|
152
|
+
['lastName', '==', leon.get('lastName')],
|
|
153
|
+
],
|
|
154
|
+
},
|
|
155
|
+
)
|
|
156
|
+
.resolves([william]);
|
|
157
|
+
|
|
158
|
+
const result = await validateDocumentsUniquenessByIndices(
|
|
159
|
+
ownerId,
|
|
160
|
+
documentTransitions,
|
|
161
|
+
dataContract,
|
|
162
|
+
executionContext,
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
expectValidationError(result, DuplicateUniqueIndexError, 4);
|
|
166
|
+
|
|
167
|
+
const errors = result.getErrors();
|
|
168
|
+
|
|
169
|
+
const [error] = result.getErrors();
|
|
170
|
+
|
|
171
|
+
expect(error.getCode()).to.equal(4009);
|
|
172
|
+
|
|
173
|
+
expect(errors.map((e) => e.getDocumentId())).to.have.deep.members([
|
|
174
|
+
documentTransitions[3].getId().toBuffer(),
|
|
175
|
+
documentTransitions[3].getId().toBuffer(),
|
|
176
|
+
documentTransitions[4].getId().toBuffer(),
|
|
177
|
+
documentTransitions[4].getId().toBuffer(),
|
|
178
|
+
]);
|
|
179
|
+
|
|
180
|
+
expect(errors.map((e) => e.getDuplicatingProperties())).to.have.deep.members([
|
|
181
|
+
indicesDefinition[0].properties.map((i) => Object.keys(i)[0]),
|
|
182
|
+
indicesDefinition[1].properties.map((i) => Object.keys(i)[0]),
|
|
183
|
+
indicesDefinition[0].properties.map((i) => Object.keys(i)[0]),
|
|
184
|
+
indicesDefinition[1].properties.map((i) => Object.keys(i)[0]),
|
|
185
|
+
]);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it('should return valid result if Document has undefined field from index', async () => {
|
|
189
|
+
const indexedDocument = documents[7];
|
|
190
|
+
const indexedDocumentTransitions = getDocumentTransitionsFixture({
|
|
191
|
+
create: [indexedDocument],
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
stateRepositoryMock.fetchDocuments
|
|
195
|
+
.withArgs(
|
|
196
|
+
dataContract.getId().toBuffer(),
|
|
197
|
+
indexedDocument.getType(),
|
|
198
|
+
{
|
|
199
|
+
where: [
|
|
200
|
+
['$ownerId', '==', ownerId],
|
|
201
|
+
['firstName', '==', indexedDocument.get('firstName')],
|
|
202
|
+
],
|
|
203
|
+
},
|
|
204
|
+
)
|
|
205
|
+
.resolves([indexedDocument]);
|
|
206
|
+
|
|
207
|
+
stateRepositoryMock.fetchDocuments
|
|
208
|
+
.withArgs(
|
|
209
|
+
dataContract.getId(),
|
|
210
|
+
indexedDocument.getType(),
|
|
211
|
+
{
|
|
212
|
+
where: [
|
|
213
|
+
['$ownerId', '==', ownerId],
|
|
214
|
+
],
|
|
215
|
+
},
|
|
216
|
+
)
|
|
217
|
+
.resolves([indexedDocument]);
|
|
218
|
+
|
|
219
|
+
const result = await validateDocumentsUniquenessByIndices(
|
|
220
|
+
ownerId,
|
|
221
|
+
indexedDocumentTransitions,
|
|
222
|
+
dataContract,
|
|
223
|
+
executionContext,
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
expect(result).to.be.an.instanceOf(ValidationResult);
|
|
227
|
+
expect(result.isValid()).to.be.true();
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it('should return valid result if Document being created and has createdAt and updatedAt indices', async () => {
|
|
231
|
+
const [, , , , , , uniqueDatesDocument] = documents;
|
|
232
|
+
|
|
233
|
+
const uniqueDatesDocumentTransitions = getDocumentTransitionsFixture({
|
|
234
|
+
create: [uniqueDatesDocument],
|
|
235
|
+
});
|
|
236
|
+
stateRepositoryMock.fetchDocuments
|
|
237
|
+
.withArgs(
|
|
238
|
+
dataContract.getId().toBuffer(),
|
|
239
|
+
uniqueDatesDocument.getType(),
|
|
240
|
+
{
|
|
241
|
+
where: [
|
|
242
|
+
['$createdAt', '==', uniqueDatesDocument.getCreatedAt().getTime()],
|
|
243
|
+
['$updatedAt', '==', uniqueDatesDocument.getUpdatedAt().getTime()],
|
|
244
|
+
],
|
|
245
|
+
},
|
|
246
|
+
)
|
|
247
|
+
.resolves([uniqueDatesDocument]);
|
|
248
|
+
|
|
249
|
+
const result = await validateDocumentsUniquenessByIndices(
|
|
250
|
+
ownerId,
|
|
251
|
+
uniqueDatesDocumentTransitions,
|
|
252
|
+
dataContract,
|
|
253
|
+
executionContext,
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
expect(result.isValid()).to.be.true();
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it('should return invalid result on dry run', async () => {
|
|
260
|
+
const [niceDocument] = documents;
|
|
261
|
+
const noIndexDocumentTransitions = getDocumentTransitionsFixture({
|
|
262
|
+
create: [niceDocument],
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
executionContext.enableDryRun();
|
|
266
|
+
|
|
267
|
+
const result = await validateDocumentsUniquenessByIndices(
|
|
268
|
+
ownerId,
|
|
269
|
+
noIndexDocumentTransitions,
|
|
270
|
+
dataContract,
|
|
271
|
+
executionContext,
|
|
272
|
+
);
|
|
273
|
+
executionContext.disableDryRun();
|
|
274
|
+
|
|
275
|
+
expect(result).to.be.an.instanceOf(ValidationResult);
|
|
276
|
+
expect(result.isValid()).to.be.true();
|
|
277
|
+
expect(stateRepositoryMock.fetchDocuments).to.have.not.been.called();
|
|
278
|
+
});
|
|
279
|
+
});
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const codes = require('../../../../lib/errors/consensus/codes');
|
|
4
|
+
const AbstractConsensusError = require('../../../../lib/errors/consensus/AbstractConsensusError');
|
|
5
|
+
const AbstractBasicError = require('../../../../lib/errors/consensus/basic/AbstractBasicError');
|
|
6
|
+
const AbstractSignatureError = require('../../../../lib/errors/consensus/signature/AbstractSignatureError');
|
|
7
|
+
const AbstractFeeError = require('../../../../lib/errors/consensus/fee/AbstractFeeError');
|
|
8
|
+
const AbstractStateError = require('../../../../lib/errors/consensus/state/AbstractStateError');
|
|
9
|
+
|
|
10
|
+
const getAllFiles = (dirPath, arrayOfFiles) => {
|
|
11
|
+
const files = fs.readdirSync(dirPath);
|
|
12
|
+
|
|
13
|
+
// eslint-disable-next-line no-param-reassign
|
|
14
|
+
arrayOfFiles = arrayOfFiles || [];
|
|
15
|
+
|
|
16
|
+
files.forEach((file) => {
|
|
17
|
+
if (fs.statSync(`${dirPath}/${file}`).isDirectory()) {
|
|
18
|
+
// eslint-disable-next-line no-param-reassign
|
|
19
|
+
arrayOfFiles = getAllFiles(`${dirPath}/${file}`, arrayOfFiles);
|
|
20
|
+
} else if (file.slice(-3) === '.js') {
|
|
21
|
+
arrayOfFiles.push(path.join(dirPath, '/', file));
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
return arrayOfFiles;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
function isChildOf(classToCheck, parentClass) {
|
|
29
|
+
if (!classToCheck || !classToCheck.prototype) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (classToCheck.prototype instanceof parentClass) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return isChildOf(classToCheck.prototype, parentClass);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const errorClasses = Object.values(codes).map((ErrorClass) => ErrorClass);
|
|
41
|
+
const errorClassDuplicates = errorClasses.filter((item, index) => (
|
|
42
|
+
errorClasses.indexOf(item) !== index
|
|
43
|
+
));
|
|
44
|
+
|
|
45
|
+
describe('Consensus error codes', () => {
|
|
46
|
+
// Skip the tests for browsers
|
|
47
|
+
if (global.window !== undefined) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const normalizedPath = path.join(__dirname, '../../../../lib/errors/');
|
|
52
|
+
const allFiles = getAllFiles(normalizedPath);
|
|
53
|
+
|
|
54
|
+
allFiles.forEach((fileName) => {
|
|
55
|
+
// eslint-disable-next-line global-require,import/no-dynamic-require
|
|
56
|
+
const ErrorClass = require(fileName);
|
|
57
|
+
|
|
58
|
+
if (
|
|
59
|
+
(isChildOf(ErrorClass, AbstractConsensusError)) && !ErrorClass.name.startsWith('Abstract')
|
|
60
|
+
) {
|
|
61
|
+
context(ErrorClass.name, () => {
|
|
62
|
+
let code;
|
|
63
|
+
let AssignedErrorClass;
|
|
64
|
+
|
|
65
|
+
beforeEach(() => {
|
|
66
|
+
const result = Object.entries(codes)
|
|
67
|
+
.find(([, ErrorClassWithCode]) => ErrorClassWithCode === ErrorClass);
|
|
68
|
+
|
|
69
|
+
if (result) {
|
|
70
|
+
code = Number(result[0]);
|
|
71
|
+
// eslint-disable-next-line prefer-destructuring
|
|
72
|
+
AssignedErrorClass = result[1];
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should have error code defined', () => {
|
|
77
|
+
expect(AssignedErrorClass).to.exist();
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('should have been define in the correct code range', () => {
|
|
81
|
+
if (isChildOf(ErrorClass, AbstractBasicError)) {
|
|
82
|
+
expect(code).to.be.above(999);
|
|
83
|
+
expect(code).to.be.below(2000);
|
|
84
|
+
} else if (isChildOf(ErrorClass, AbstractSignatureError)) {
|
|
85
|
+
expect(code).to.be.above(1999);
|
|
86
|
+
expect(code).to.be.below(3000);
|
|
87
|
+
} else if (isChildOf(ErrorClass, AbstractFeeError)) {
|
|
88
|
+
expect(code).to.be.above(2999);
|
|
89
|
+
expect(code).to.be.below(4000);
|
|
90
|
+
} else if (isChildOf(ErrorClass, AbstractStateError)) {
|
|
91
|
+
expect(code).to.be.above(3999);
|
|
92
|
+
expect(code).to.be.below(5000);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('should not have duplicates', () => {
|
|
97
|
+
expect(errorClassDuplicates).to.not.include(ErrorClass);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
});
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
const generateRandomIdentifier = require('../../../lib/test/utils/generateRandomIdentifier');
|
|
2
|
+
|
|
3
|
+
const IdentityPublicKey = require('../../../lib/identity/IdentityPublicKey');
|
|
4
|
+
const Metadata = require('../../../lib/Metadata');
|
|
5
|
+
const protocolVersion = require('../../../lib/version/protocolVersion');
|
|
6
|
+
|
|
7
|
+
const Identity = require('../../../lib/identity/Identity');
|
|
8
|
+
const serializer = require('../../../lib/util/serializer');
|
|
9
|
+
const hash = require('../../../lib/util/hash');
|
|
10
|
+
|
|
11
|
+
describe('Identity', () => {
|
|
12
|
+
let rawIdentity;
|
|
13
|
+
let identity;
|
|
14
|
+
let hashMock;
|
|
15
|
+
let encodeMock;
|
|
16
|
+
let metadataFixture;
|
|
17
|
+
|
|
18
|
+
beforeEach(function beforeEach() {
|
|
19
|
+
rawIdentity = {
|
|
20
|
+
protocolVersion: protocolVersion.latestVersion,
|
|
21
|
+
id: generateRandomIdentifier(),
|
|
22
|
+
publicKeys: [
|
|
23
|
+
{
|
|
24
|
+
id: 0,
|
|
25
|
+
type: IdentityPublicKey.TYPES.ECDSA_SECP256K1,
|
|
26
|
+
data: Buffer.alloc(36).fill('a'),
|
|
27
|
+
purpose: IdentityPublicKey.PURPOSES.AUTHENTICATION,
|
|
28
|
+
securityLevel: IdentityPublicKey.SECURITY_LEVELS.MASTER,
|
|
29
|
+
readOnly: false,
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
balance: 0,
|
|
33
|
+
revision: 0,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
identity = new Identity(rawIdentity);
|
|
37
|
+
|
|
38
|
+
metadataFixture = new Metadata(42, 0);
|
|
39
|
+
|
|
40
|
+
identity.setMetadata(metadataFixture);
|
|
41
|
+
|
|
42
|
+
encodeMock = this.sinonSandbox.stub(serializer, 'encode');
|
|
43
|
+
hashMock = this.sinonSandbox.stub(hash, 'hash');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
afterEach(() => {
|
|
47
|
+
encodeMock.restore();
|
|
48
|
+
hashMock.restore();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe('#constructor', () => {
|
|
52
|
+
it('should set variables from raw model', () => {
|
|
53
|
+
const instance = new Identity(rawIdentity);
|
|
54
|
+
|
|
55
|
+
expect(instance.id).to.deep.equal(rawIdentity.id);
|
|
56
|
+
expect(instance.type).to.equal(rawIdentity.type);
|
|
57
|
+
expect(instance.publicKeys).to.deep.equal(
|
|
58
|
+
rawIdentity.publicKeys.map((rawPublicKey) => new IdentityPublicKey(rawPublicKey)),
|
|
59
|
+
);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
describe('#getId', () => {
|
|
64
|
+
it('should return set id', () => {
|
|
65
|
+
expect(identity.getId()).to.deep.equal(rawIdentity.id);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('#getPublicKeys', () => {
|
|
70
|
+
it('should return set public keys', () => {
|
|
71
|
+
expect(identity.getPublicKeys()).to.deep.equal(
|
|
72
|
+
rawIdentity.publicKeys.map((rawPublicKey) => new IdentityPublicKey(rawPublicKey)),
|
|
73
|
+
);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
describe('#setPublicKeys', () => {
|
|
78
|
+
it('should set public keys', () => {
|
|
79
|
+
identity.setPublicKeys(42);
|
|
80
|
+
expect(identity.publicKeys).to.equal(42);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
describe('#getPublicKeyById', () => {
|
|
85
|
+
it('should return a public key for a given id', () => {
|
|
86
|
+
const key = identity.getPublicKeyById(0);
|
|
87
|
+
|
|
88
|
+
expect(key).to.be.deep.equal(new IdentityPublicKey(rawIdentity.publicKeys[0]));
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("should return undefined if there's no key with such id", () => {
|
|
92
|
+
const key = identity.getPublicKeyById(3);
|
|
93
|
+
expect(key).to.be.undefined();
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
describe('#toBuffer', () => {
|
|
98
|
+
it('should return serialized Identity', () => {
|
|
99
|
+
const encodeMockData = Buffer.from('42');
|
|
100
|
+
encodeMock.returns(encodeMockData); // for example
|
|
101
|
+
|
|
102
|
+
const result = identity.toBuffer();
|
|
103
|
+
|
|
104
|
+
const identityDataToEncode = identity.toObject();
|
|
105
|
+
delete identityDataToEncode.protocolVersion;
|
|
106
|
+
|
|
107
|
+
const protocolVersionUInt32 = Buffer.alloc(4);
|
|
108
|
+
protocolVersionUInt32.writeUInt32LE(identity.getProtocolVersion(), 0);
|
|
109
|
+
|
|
110
|
+
expect(encodeMock).to.have.been.calledOnceWith(identityDataToEncode);
|
|
111
|
+
expect(result).to.deep.equal(Buffer.concat([protocolVersionUInt32, encodeMockData]));
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('#hash', () => {
|
|
116
|
+
it('should return hex string of a buffer return by serialize', () => {
|
|
117
|
+
const buffer = Buffer.from('someString');
|
|
118
|
+
|
|
119
|
+
encodeMock.returns(buffer);
|
|
120
|
+
hashMock.returns(buffer);
|
|
121
|
+
|
|
122
|
+
const result = identity.hash();
|
|
123
|
+
|
|
124
|
+
const identityDataToEncode = identity.toObject();
|
|
125
|
+
delete identityDataToEncode.protocolVersion;
|
|
126
|
+
|
|
127
|
+
const protocolVersionUInt32 = Buffer.alloc(4);
|
|
128
|
+
protocolVersionUInt32.writeUInt32LE(identity.getProtocolVersion(), 0);
|
|
129
|
+
|
|
130
|
+
expect(encodeMock).to.have.been.calledOnceWith(identityDataToEncode);
|
|
131
|
+
expect(hashMock).to.have.been.calledOnceWith(Buffer.concat([protocolVersionUInt32, buffer]));
|
|
132
|
+
expect(result).to.equal(buffer);
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
describe('#toObject', () => {
|
|
137
|
+
it('should return plain object representation', () => {
|
|
138
|
+
expect(identity.toObject()).to.deep.equal(rawIdentity);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
describe('#toJSON', () => {
|
|
143
|
+
it('should return json representation', () => {
|
|
144
|
+
const jsonIdentity = identity.toJSON();
|
|
145
|
+
|
|
146
|
+
expect(jsonIdentity).to.deep.equal({
|
|
147
|
+
protocolVersion: protocolVersion.latestVersion,
|
|
148
|
+
id: rawIdentity.id.toString(),
|
|
149
|
+
publicKeys: [
|
|
150
|
+
{
|
|
151
|
+
id: 0,
|
|
152
|
+
type: IdentityPublicKey.TYPES.ECDSA_SECP256K1,
|
|
153
|
+
data: rawIdentity.publicKeys[0].data.toString('base64'),
|
|
154
|
+
purpose: IdentityPublicKey.PURPOSES.AUTHENTICATION,
|
|
155
|
+
securityLevel: IdentityPublicKey.SECURITY_LEVELS.MASTER,
|
|
156
|
+
readOnly: false,
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
balance: 0,
|
|
160
|
+
revision: 0,
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
describe('#getBalance', () => {
|
|
166
|
+
it('should return set identity balance', () => {
|
|
167
|
+
identity.balance = 42;
|
|
168
|
+
expect(identity.getBalance()).to.equal(42);
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
describe('#setBalance', () => {
|
|
173
|
+
it('should set identity balance', () => {
|
|
174
|
+
identity.setBalance(42);
|
|
175
|
+
expect(identity.balance).to.equal(42);
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
describe('#increaseBalance', () => {
|
|
180
|
+
it('should increase identity balance', () => {
|
|
181
|
+
const result = identity.increaseBalance(42);
|
|
182
|
+
|
|
183
|
+
expect(result).to.equal(42);
|
|
184
|
+
expect(identity.balance).to.equal(42);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
describe('#reduceBalance', () => {
|
|
189
|
+
it('should reduce identity balance', () => {
|
|
190
|
+
identity.balance = 42;
|
|
191
|
+
|
|
192
|
+
const result = identity.reduceBalance(2);
|
|
193
|
+
|
|
194
|
+
expect(result).to.equal(40);
|
|
195
|
+
expect(identity.balance).to.equal(40);
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
describe('#setMetadata', () => {
|
|
200
|
+
it('should set metadata', () => {
|
|
201
|
+
const otherMetadata = new Metadata(43, 1);
|
|
202
|
+
|
|
203
|
+
identity.setMetadata(otherMetadata);
|
|
204
|
+
|
|
205
|
+
expect(identity.metadata).to.deep.equal(otherMetadata);
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
describe('#getMetadata', () => {
|
|
210
|
+
it('should get metadata', () => {
|
|
211
|
+
expect(identity.getMetadata()).to.deep.equal(metadataFixture);
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
describe('#getPublicKeyMaxId', () => {
|
|
216
|
+
it('should get the biggest public key ID', () => {
|
|
217
|
+
identity.publicKeys.push(
|
|
218
|
+
new IdentityPublicKey({
|
|
219
|
+
id: 99,
|
|
220
|
+
type: IdentityPublicKey.TYPES.ECDSA_SECP256K1,
|
|
221
|
+
data: Buffer.alloc(36).fill('a'),
|
|
222
|
+
purpose: IdentityPublicKey.PURPOSES.AUTHENTICATION,
|
|
223
|
+
securityLevel: IdentityPublicKey.SECURITY_LEVELS.MASTER,
|
|
224
|
+
readOnly: false,
|
|
225
|
+
}),
|
|
226
|
+
new IdentityPublicKey({
|
|
227
|
+
id: 50,
|
|
228
|
+
type: IdentityPublicKey.TYPES.ECDSA_SECP256K1,
|
|
229
|
+
data: Buffer.alloc(36).fill('a'),
|
|
230
|
+
purpose: IdentityPublicKey.PURPOSES.AUTHENTICATION,
|
|
231
|
+
securityLevel: IdentityPublicKey.SECURITY_LEVELS.MASTER,
|
|
232
|
+
readOnly: false,
|
|
233
|
+
}),
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
const maxId = identity.getPublicKeyMaxId();
|
|
237
|
+
|
|
238
|
+
const publicKeyIds = identity.getPublicKeys().map((publicKey) => publicKey.getId());
|
|
239
|
+
|
|
240
|
+
expect(Math.max(...publicKeyIds)).to.equal(maxId);
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
});
|