@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,418 @@
|
|
|
1
|
+
const { PrivateKey } = require('@dashevo/dashcore-lib');
|
|
2
|
+
|
|
3
|
+
const DashPlatformProtocol = require('../../../lib/DashPlatformProtocol');
|
|
4
|
+
|
|
5
|
+
const DataContractCreateTransition = require('../../../lib/dataContract/stateTransition/DataContractCreateTransition/DataContractCreateTransition');
|
|
6
|
+
|
|
7
|
+
const ValidationResult = require('../../../lib/validation/ValidationResult');
|
|
8
|
+
|
|
9
|
+
const getDataContractFixture = require('../../../lib/test/fixtures/getDataContractFixture');
|
|
10
|
+
const getDocumentsFixture = require('../../../lib/test/fixtures/getDocumentsFixture');
|
|
11
|
+
const getIdentityCreateTransitionFixture = require('../../../lib/test/fixtures/getIdentityCreateTransitionFixture');
|
|
12
|
+
|
|
13
|
+
const createStateRepositoryMock = require('../../../lib/test/mocks/createStateRepositoryMock');
|
|
14
|
+
|
|
15
|
+
const DataContractFactory = require('../../../lib/dataContract/DataContractFactory');
|
|
16
|
+
const DocumentFactory = require('../../../lib/document/DocumentFactory');
|
|
17
|
+
|
|
18
|
+
const IdentityPublicKey = require('../../../lib/identity/IdentityPublicKey');
|
|
19
|
+
|
|
20
|
+
const MissingOptionError = require('../../../lib/errors/MissingOptionError');
|
|
21
|
+
const createDPPMock = require('../../../lib/test/mocks/createDPPMock');
|
|
22
|
+
const SomeConsensusError = require('../../../lib/test/mocks/SomeConsensusError');
|
|
23
|
+
|
|
24
|
+
describe('StateTransitionFacade', () => {
|
|
25
|
+
let dpp;
|
|
26
|
+
let dataContractCreateTransition;
|
|
27
|
+
let documentsBatchTransition;
|
|
28
|
+
let stateRepositoryMock;
|
|
29
|
+
let dataContract;
|
|
30
|
+
let identityPublicKey;
|
|
31
|
+
|
|
32
|
+
beforeEach(async function beforeEach() {
|
|
33
|
+
const privateKeyModel = new PrivateKey();
|
|
34
|
+
const privateKey = privateKeyModel.toWIF();
|
|
35
|
+
const publicKey = privateKeyModel.toPublicKey().toBuffer();
|
|
36
|
+
const publicKeyId = 1;
|
|
37
|
+
|
|
38
|
+
identityPublicKey = new IdentityPublicKey()
|
|
39
|
+
.setId(publicKeyId)
|
|
40
|
+
.setType(IdentityPublicKey.TYPES.ECDSA_SECP256K1)
|
|
41
|
+
.setData(publicKey)
|
|
42
|
+
.setPurpose(IdentityPublicKey.PURPOSES.AUTHENTICATION)
|
|
43
|
+
.setSecurityLevel(IdentityPublicKey.PURPOSES.MASTER);
|
|
44
|
+
|
|
45
|
+
dataContract = getDataContractFixture();
|
|
46
|
+
|
|
47
|
+
const dataContractFactory = new DataContractFactory(createDPPMock(), undefined);
|
|
48
|
+
|
|
49
|
+
dataContractCreateTransition = dataContractFactory.createDataContractCreateTransition(
|
|
50
|
+
dataContract,
|
|
51
|
+
);
|
|
52
|
+
await dataContractCreateTransition.sign(identityPublicKey, privateKey);
|
|
53
|
+
|
|
54
|
+
const documentFactory = new DocumentFactory(createDPPMock(), undefined, undefined);
|
|
55
|
+
|
|
56
|
+
documentsBatchTransition = documentFactory.createStateTransition({
|
|
57
|
+
create: getDocumentsFixture(dataContract),
|
|
58
|
+
});
|
|
59
|
+
await documentsBatchTransition.sign(identityPublicKey, privateKey);
|
|
60
|
+
|
|
61
|
+
const getPublicKeyById = this.sinonSandbox.stub().returns(identityPublicKey);
|
|
62
|
+
const getBalance = this.sinonSandbox.stub().returns(10000);
|
|
63
|
+
|
|
64
|
+
const identity = {
|
|
65
|
+
getPublicKeyById,
|
|
66
|
+
type: 2,
|
|
67
|
+
getBalance,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const timeInSeconds = Math.ceil(new Date().getTime() / 1000);
|
|
71
|
+
|
|
72
|
+
stateRepositoryMock = createStateRepositoryMock(this.sinonSandbox);
|
|
73
|
+
stateRepositoryMock.fetchIdentity.resolves(identity);
|
|
74
|
+
stateRepositoryMock.fetchLatestPlatformBlockHeader.resolves({
|
|
75
|
+
time: {
|
|
76
|
+
seconds: timeInSeconds,
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
dpp = new DashPlatformProtocol({
|
|
81
|
+
stateRepository: stateRepositoryMock,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
await dpp.initialize();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
describe('createFromObject', () => {
|
|
88
|
+
it('should throw MissingOption if stateRepository is not set', async () => {
|
|
89
|
+
dpp = new DashPlatformProtocol();
|
|
90
|
+
await dpp.initialize();
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
await dpp.stateTransition.createFromObject(
|
|
94
|
+
dataContractCreateTransition.toObject(),
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
expect.fail('MissingOption should be thrown');
|
|
98
|
+
} catch (e) {
|
|
99
|
+
expect(e).to.be.an.instanceOf(MissingOptionError);
|
|
100
|
+
expect(e.getOptionName()).to.equal('stateRepository');
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('should skip checking for state repository if skipValidation is set', async () => {
|
|
105
|
+
dpp = new DashPlatformProtocol();
|
|
106
|
+
await dpp.initialize();
|
|
107
|
+
|
|
108
|
+
await dpp.stateTransition.createFromObject(
|
|
109
|
+
dataContractCreateTransition.toObject(),
|
|
110
|
+
{ skipValidation: true },
|
|
111
|
+
);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('should create State Transition from plain object', async () => {
|
|
115
|
+
const result = await dpp.stateTransition.createFromObject(
|
|
116
|
+
dataContractCreateTransition.toObject(),
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
expect(result).to.be.an.instanceOf(DataContractCreateTransition);
|
|
120
|
+
|
|
121
|
+
expect(result.toObject()).to.deep.equal(dataContractCreateTransition.toObject());
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
describe('createFromBuffer', () => {
|
|
126
|
+
it('should throw MissingOption if stateRepository is not set', async () => {
|
|
127
|
+
dpp = new DashPlatformProtocol();
|
|
128
|
+
await dpp.initialize();
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
await dpp.stateTransition.createFromBuffer(
|
|
132
|
+
dataContractCreateTransition.toBuffer(),
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
expect.fail('MissingOption should be thrown');
|
|
136
|
+
} catch (e) {
|
|
137
|
+
expect(e).to.be.an.instanceOf(MissingOptionError);
|
|
138
|
+
expect(e.getOptionName()).to.equal('stateRepository');
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('should skip checking for state repository if skipValidation is set', async () => {
|
|
143
|
+
dpp = new DashPlatformProtocol();
|
|
144
|
+
await dpp.initialize();
|
|
145
|
+
|
|
146
|
+
await dpp.stateTransition.createFromBuffer(
|
|
147
|
+
dataContractCreateTransition.toBuffer(),
|
|
148
|
+
{ skipValidation: true },
|
|
149
|
+
);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('should create State Transition from string', async () => {
|
|
153
|
+
const result = await dpp.stateTransition.createFromBuffer(
|
|
154
|
+
dataContractCreateTransition.toBuffer(),
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
expect(result).to.be.an.instanceOf(DataContractCreateTransition);
|
|
158
|
+
|
|
159
|
+
expect(result.toObject()).to.deep.equal(dataContractCreateTransition.toObject());
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
describe('validate', () => {
|
|
164
|
+
let validateBasicSpy;
|
|
165
|
+
let validateSignatureSpy;
|
|
166
|
+
let validateFeeSpy;
|
|
167
|
+
let validateStateSpy;
|
|
168
|
+
|
|
169
|
+
beforeEach(function beforeEach() {
|
|
170
|
+
validateBasicSpy = this.sinonSandbox.spy(
|
|
171
|
+
dpp.stateTransition,
|
|
172
|
+
'validateBasic',
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
validateSignatureSpy = this.sinonSandbox.spy(
|
|
176
|
+
dpp.stateTransition,
|
|
177
|
+
'validateSignature',
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
validateFeeSpy = this.sinonSandbox.spy(
|
|
181
|
+
dpp.stateTransition,
|
|
182
|
+
'validateFee',
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
validateStateSpy = this.sinonSandbox.spy(
|
|
186
|
+
dpp.stateTransition,
|
|
187
|
+
'validateState',
|
|
188
|
+
);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it('should return invalid result if State Transition structure is invalid', async () => {
|
|
192
|
+
const rawStateTransition = dataContractCreateTransition.toObject();
|
|
193
|
+
delete rawStateTransition.protocolVersion;
|
|
194
|
+
|
|
195
|
+
const result = await dpp.stateTransition.validate(rawStateTransition);
|
|
196
|
+
|
|
197
|
+
expect(result).to.be.an.instanceOf(ValidationResult);
|
|
198
|
+
expect(result.isValid()).to.be.false();
|
|
199
|
+
|
|
200
|
+
expect(validateBasicSpy).to.be.calledOnceWithExactly(rawStateTransition);
|
|
201
|
+
expect(validateSignatureSpy).to.not.be.called();
|
|
202
|
+
expect(validateFeeSpy).to.not.be.called();
|
|
203
|
+
expect(validateStateSpy).to.not.be.called();
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('should return invalid result if State Transition signature is invalid', async () => {
|
|
207
|
+
dataContractCreateTransition.signature = Buffer.alloc(65).fill(1);
|
|
208
|
+
|
|
209
|
+
const result = await dpp.stateTransition.validate(dataContractCreateTransition);
|
|
210
|
+
|
|
211
|
+
expect(result).to.be.an.instanceOf(ValidationResult);
|
|
212
|
+
expect(result.isValid()).to.be.false();
|
|
213
|
+
|
|
214
|
+
expect(validateBasicSpy).to.be.calledOnceWithExactly(dataContractCreateTransition);
|
|
215
|
+
expect(validateSignatureSpy).to.be.calledOnceWithExactly(dataContractCreateTransition);
|
|
216
|
+
expect(validateFeeSpy).to.not.be.called();
|
|
217
|
+
expect(validateStateSpy).to.not.be.called();
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('should return invalid result if not enough balance to pay fee for State Transition', async () => {
|
|
221
|
+
const consensusError = new SomeConsensusError('error');
|
|
222
|
+
|
|
223
|
+
dpp.stateTransition.validateStateTransitionFee = () => new ValidationResult([consensusError]);
|
|
224
|
+
|
|
225
|
+
const result = await dpp.stateTransition.validate(dataContractCreateTransition);
|
|
226
|
+
|
|
227
|
+
expect(result).to.be.an.instanceOf(ValidationResult);
|
|
228
|
+
expect(result.isValid()).to.be.false();
|
|
229
|
+
|
|
230
|
+
expect(validateBasicSpy).to.be.calledOnceWithExactly(dataContractCreateTransition);
|
|
231
|
+
expect(validateSignatureSpy).to.be.calledOnceWithExactly(dataContractCreateTransition);
|
|
232
|
+
expect(validateFeeSpy).to.be.calledOnceWithExactly(dataContractCreateTransition);
|
|
233
|
+
expect(validateStateSpy).to.not.be.called();
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
it('should return invalid result if State Transition is invalid against state', async () => {
|
|
237
|
+
const consensusError = new SomeConsensusError('error');
|
|
238
|
+
|
|
239
|
+
dpp.stateTransition.validateStateTransitionState = () => (
|
|
240
|
+
new ValidationResult([consensusError])
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
const result = await dpp.stateTransition.validate(dataContractCreateTransition);
|
|
244
|
+
|
|
245
|
+
expect(result).to.be.an.instanceOf(ValidationResult);
|
|
246
|
+
expect(result.isValid()).to.be.false();
|
|
247
|
+
|
|
248
|
+
expect(validateBasicSpy).to.be.calledOnceWithExactly(dataContractCreateTransition);
|
|
249
|
+
expect(validateSignatureSpy).to.be.calledOnceWithExactly(dataContractCreateTransition);
|
|
250
|
+
expect(validateFeeSpy).to.be.calledOnceWithExactly(dataContractCreateTransition);
|
|
251
|
+
expect(validateStateSpy).to.be.calledOnceWithExactly(dataContractCreateTransition);
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it('should validate DataContractCreateTransition', async () => {
|
|
255
|
+
const result = await dpp.stateTransition.validate(
|
|
256
|
+
dataContractCreateTransition,
|
|
257
|
+
);
|
|
258
|
+
|
|
259
|
+
expect(result).to.be.an.instanceOf(ValidationResult);
|
|
260
|
+
expect(result.isValid()).to.be.true();
|
|
261
|
+
|
|
262
|
+
expect(validateBasicSpy).to.be.calledOnceWithExactly(dataContractCreateTransition);
|
|
263
|
+
expect(validateSignatureSpy).to.be.calledOnceWithExactly(dataContractCreateTransition);
|
|
264
|
+
expect(validateFeeSpy).to.be.calledOnceWithExactly(dataContractCreateTransition);
|
|
265
|
+
expect(validateStateSpy).to.be.calledOnceWithExactly(dataContractCreateTransition);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
it('should validate DocumentsBatchTransition', async function it() {
|
|
269
|
+
stateRepositoryMock.fetchDocuments.resolves([]);
|
|
270
|
+
|
|
271
|
+
stateRepositoryMock.fetchDataContract.resolves(dataContract);
|
|
272
|
+
stateRepositoryMock.fetchIdentity.resolves({
|
|
273
|
+
getPublicKeyById: this.sinonSandbox.stub().returns(identityPublicKey),
|
|
274
|
+
getBalance: this.sinonSandbox.stub().returns(10000),
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
const result = await dpp.stateTransition.validate(
|
|
278
|
+
documentsBatchTransition,
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
expect(result).to.be.an.instanceOf(ValidationResult);
|
|
282
|
+
expect(result.isValid()).to.be.true();
|
|
283
|
+
|
|
284
|
+
expect(validateBasicSpy).to.be.calledOnceWithExactly(documentsBatchTransition);
|
|
285
|
+
expect(validateSignatureSpy).to.be.calledOnceWithExactly(documentsBatchTransition);
|
|
286
|
+
expect(validateFeeSpy).to.be.calledOnceWithExactly(documentsBatchTransition);
|
|
287
|
+
expect(validateStateSpy).to.be.calledOnceWithExactly(documentsBatchTransition);
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
describe('validateBasic', () => {
|
|
292
|
+
it('should throw MissingOption if stateRepository is not set', async () => {
|
|
293
|
+
dpp = new DashPlatformProtocol();
|
|
294
|
+
await dpp.initialize();
|
|
295
|
+
|
|
296
|
+
try {
|
|
297
|
+
await dpp.stateTransition.validateBasic(
|
|
298
|
+
dataContractCreateTransition.toObject(),
|
|
299
|
+
);
|
|
300
|
+
|
|
301
|
+
expect.fail('MissingOption should be thrown');
|
|
302
|
+
} catch (e) {
|
|
303
|
+
expect(e).to.be.an.instanceOf(MissingOptionError);
|
|
304
|
+
expect(e.getOptionName()).to.equal('stateRepository');
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
it('should validate State Transition', async () => {
|
|
309
|
+
const result = await dpp.stateTransition.validateBasic(
|
|
310
|
+
dataContractCreateTransition.toObject(),
|
|
311
|
+
);
|
|
312
|
+
|
|
313
|
+
expect(result).to.be.an.instanceOf(ValidationResult);
|
|
314
|
+
expect(result.isValid()).to.be.true();
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
describe('validateSignature', () => {
|
|
319
|
+
it('should throw MissingOption if stateRepository is not set', async () => {
|
|
320
|
+
dpp = new DashPlatformProtocol();
|
|
321
|
+
await dpp.initialize();
|
|
322
|
+
|
|
323
|
+
try {
|
|
324
|
+
await dpp.stateTransition.validateSignature(
|
|
325
|
+
dataContractCreateTransition,
|
|
326
|
+
);
|
|
327
|
+
|
|
328
|
+
expect.fail('MissingOption should be thrown');
|
|
329
|
+
} catch (e) {
|
|
330
|
+
expect(e).to.be.an.instanceOf(MissingOptionError);
|
|
331
|
+
expect(e.getOptionName()).to.equal('stateRepository');
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
it('should validate identity signed State Transition', async () => {
|
|
336
|
+
const result = await dpp.stateTransition.validateSignature(
|
|
337
|
+
dataContractCreateTransition,
|
|
338
|
+
);
|
|
339
|
+
|
|
340
|
+
expect(result).to.be.an.instanceOf(ValidationResult);
|
|
341
|
+
expect(result.isValid()).to.be.true();
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
it('should validate key signed State Transition', async () => {
|
|
345
|
+
const oneTimePrivateKey = new PrivateKey(
|
|
346
|
+
'af432c476f65211f45f48f1d42c9c0b497e56696aa1736b40544ef1a496af837',
|
|
347
|
+
);
|
|
348
|
+
|
|
349
|
+
const identityCreateTransition = getIdentityCreateTransitionFixture(oneTimePrivateKey);
|
|
350
|
+
|
|
351
|
+
await identityCreateTransition.signByPrivateKey(
|
|
352
|
+
oneTimePrivateKey,
|
|
353
|
+
IdentityPublicKey.TYPES.ECDSA_SECP256K1,
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
const result = await dpp.stateTransition.validateSignature(
|
|
357
|
+
identityCreateTransition,
|
|
358
|
+
);
|
|
359
|
+
|
|
360
|
+
expect(result).to.be.an.instanceOf(ValidationResult);
|
|
361
|
+
expect(result.isValid()).to.be.true();
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
describe('validateFee', () => {
|
|
366
|
+
it('should throw MissingOption if stateRepository is not set', async () => {
|
|
367
|
+
dpp = new DashPlatformProtocol();
|
|
368
|
+
await dpp.initialize();
|
|
369
|
+
|
|
370
|
+
try {
|
|
371
|
+
await dpp.stateTransition.validateFee(
|
|
372
|
+
dataContractCreateTransition,
|
|
373
|
+
);
|
|
374
|
+
|
|
375
|
+
expect.fail('MissingOption should be thrown');
|
|
376
|
+
} catch (e) {
|
|
377
|
+
expect(e).to.be.an.instanceOf(MissingOptionError);
|
|
378
|
+
expect(e.getOptionName()).to.equal('stateRepository');
|
|
379
|
+
}
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
it('should validate State Transition', async () => {
|
|
383
|
+
const result = await dpp.stateTransition.validateFee(
|
|
384
|
+
dataContractCreateTransition,
|
|
385
|
+
);
|
|
386
|
+
|
|
387
|
+
expect(result).to.be.an.instanceOf(ValidationResult);
|
|
388
|
+
expect(result.isValid()).to.be.true();
|
|
389
|
+
});
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
describe('validateState', () => {
|
|
393
|
+
it('should throw MissingOption if stateRepository is not set', async () => {
|
|
394
|
+
dpp = new DashPlatformProtocol();
|
|
395
|
+
await dpp.initialize();
|
|
396
|
+
|
|
397
|
+
try {
|
|
398
|
+
await dpp.stateTransition.validateState(
|
|
399
|
+
dataContractCreateTransition,
|
|
400
|
+
);
|
|
401
|
+
|
|
402
|
+
expect.fail('MissingOption should be thrown');
|
|
403
|
+
} catch (e) {
|
|
404
|
+
expect(e).to.be.an.instanceOf(MissingOptionError);
|
|
405
|
+
expect(e.getOptionName()).to.equal('stateRepository');
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
it('should validate State Transition', async () => {
|
|
410
|
+
const result = await dpp.stateTransition.validateState(
|
|
411
|
+
dataContractCreateTransition,
|
|
412
|
+
);
|
|
413
|
+
|
|
414
|
+
expect(result).to.be.an.instanceOf(ValidationResult);
|
|
415
|
+
expect(result.isValid()).to.be.true();
|
|
416
|
+
});
|
|
417
|
+
});
|
|
418
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const calculateStateTransitionFee = require('../../../lib/stateTransition/fee/calculateStateTransitionFee');
|
|
2
|
+
|
|
3
|
+
const getIdentityCreateTransitionFixture = require('../../../lib/test/fixtures/getIdentityCreateTransitionFixture');
|
|
4
|
+
const IdentityPublicKey = require('../../../lib/identity/IdentityPublicKey');
|
|
5
|
+
const ReadOperation = require('../../../lib/stateTransition/fee/operations/ReadOperation');
|
|
6
|
+
const WriteOperation = require('../../../lib/stateTransition/fee/operations/WriteOperation');
|
|
7
|
+
const DeleteOperation = require('../../../lib/stateTransition/fee/operations/DeleteOperation');
|
|
8
|
+
const PreCalculatedOperation = require('../../../lib/stateTransition/fee/operations/PreCalculatedOperation');
|
|
9
|
+
|
|
10
|
+
describe('calculateStateTransitionFee', () => {
|
|
11
|
+
let stateTransition;
|
|
12
|
+
|
|
13
|
+
beforeEach(async () => {
|
|
14
|
+
const privateKey = 'af432c476f65211f45f48f1d42c9c0b497e56696aa1736b40544ef1a496af837';
|
|
15
|
+
|
|
16
|
+
stateTransition = getIdentityCreateTransitionFixture();
|
|
17
|
+
await stateTransition.signByPrivateKey(privateKey, IdentityPublicKey.TYPES.ECDSA_SECP256K1);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// TODO: Must be more comprehensive. After we settle all factors and formula.
|
|
21
|
+
it('should calculate fee based on executed operations', () => {
|
|
22
|
+
const executionContext = stateTransition.getExecutionContext();
|
|
23
|
+
|
|
24
|
+
executionContext.addOperation(
|
|
25
|
+
new ReadOperation(10),
|
|
26
|
+
new WriteOperation(5, 5),
|
|
27
|
+
new DeleteOperation(6, 6),
|
|
28
|
+
new PreCalculatedOperation(12, 12),
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
const result = calculateStateTransitionFee(stateTransition);
|
|
32
|
+
|
|
33
|
+
expect(result).to.equal(13616);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const { generate: generateEntropy } = require('../../../lib/util/entropyGenerator');
|
|
2
|
+
|
|
3
|
+
describe('generateEntropy', () => {
|
|
4
|
+
it('should generate a byte array of length 32', () => {
|
|
5
|
+
const entropy = generateEntropy();
|
|
6
|
+
|
|
7
|
+
expect(Buffer.isBuffer(entropy)).to.be.true();
|
|
8
|
+
expect(entropy.byteLength).to.be.equal(32);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('should generate random byte array', () => {
|
|
12
|
+
const randomBuffer = generateEntropy();
|
|
13
|
+
const secondRandomBuffer = generateEntropy();
|
|
14
|
+
|
|
15
|
+
expect(randomBuffer).to.not.deep.equal(secondRandomBuffer);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const { encode } = require('../../../lib/util/serializer');
|
|
2
|
+
|
|
3
|
+
const DataSerializationError = require('../../../lib/util/errors/MaxEncodedBytesReachedError');
|
|
4
|
+
|
|
5
|
+
describe('serializer', function main() {
|
|
6
|
+
this.timeout(10000);
|
|
7
|
+
|
|
8
|
+
describe('#encode', () => {
|
|
9
|
+
it('should throw an error if payload is larger that 16 Kb', () => {
|
|
10
|
+
const payload = {};
|
|
11
|
+
for (let i = 0; i < 10000; i++) {
|
|
12
|
+
payload[i] = i;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
encode(payload);
|
|
17
|
+
expect.fail('Error was not thrown');
|
|
18
|
+
} catch (e) {
|
|
19
|
+
expect(e).to.be.an.instanceOf(DataSerializationError);
|
|
20
|
+
expect(e.getPayload()).to.deep.equal(payload);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
const { default: Ajv } = require('ajv/dist/2020');
|
|
2
|
+
|
|
3
|
+
const protocolVersion = require('../../lib/version/protocolVersion');
|
|
4
|
+
|
|
5
|
+
const DashPlatformProtocol = require('../../lib/DashPlatformProtocol');
|
|
6
|
+
const JsonSchemaValidator = require('../../lib/validation/JsonSchemaValidator');
|
|
7
|
+
|
|
8
|
+
const createStateRepositoryMock = require('../../lib/test/mocks/createStateRepositoryMock');
|
|
9
|
+
|
|
10
|
+
describe('DashPlatformProtocol', () => {
|
|
11
|
+
let dpp;
|
|
12
|
+
let stateRepositoryMock;
|
|
13
|
+
let jsonSchemaValidatorMock;
|
|
14
|
+
|
|
15
|
+
beforeEach(async function beforeEach() {
|
|
16
|
+
stateRepositoryMock = createStateRepositoryMock(this.sinonSandbox);
|
|
17
|
+
jsonSchemaValidatorMock = {};
|
|
18
|
+
|
|
19
|
+
dpp = new DashPlatformProtocol({
|
|
20
|
+
stateRepository: stateRepositoryMock,
|
|
21
|
+
jsonSchemaValidator: jsonSchemaValidatorMock,
|
|
22
|
+
});
|
|
23
|
+
await dpp.initialize();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
describe('constructor', () => {
|
|
27
|
+
it('should create JsonSchemaValidator if not passed in options', async () => {
|
|
28
|
+
dpp = new DashPlatformProtocol();
|
|
29
|
+
await dpp.initialize();
|
|
30
|
+
|
|
31
|
+
const jsonSchemaValidator = dpp.getJsonSchemaValidator();
|
|
32
|
+
|
|
33
|
+
expect(jsonSchemaValidator).to.be.instanceOf(JsonSchemaValidator);
|
|
34
|
+
expect(jsonSchemaValidator.ajv).to.be.instanceOf(Ajv);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should set default protocol version', () => {
|
|
38
|
+
dpp = new DashPlatformProtocol();
|
|
39
|
+
|
|
40
|
+
expect(dpp.protocolVersion).to.equal(protocolVersion.latestVersion);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe('getStateRepository', () => {
|
|
45
|
+
it('should return StateRepository', () => {
|
|
46
|
+
const result = dpp.getStateRepository();
|
|
47
|
+
|
|
48
|
+
expect(result).to.equal(stateRepositoryMock);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe('getJsonSchemaValidator', () => {
|
|
53
|
+
it('should return JsonSchemaValidator', () => {
|
|
54
|
+
const result = dpp.getJsonSchemaValidator();
|
|
55
|
+
|
|
56
|
+
expect(result).to.equal(jsonSchemaValidatorMock);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
describe('setProtocolVersion', () => {
|
|
61
|
+
it('should set protocol version', () => {
|
|
62
|
+
expect(dpp.protocolVersion).to.equal(protocolVersion.latestVersion);
|
|
63
|
+
|
|
64
|
+
dpp.setProtocolVersion(42);
|
|
65
|
+
|
|
66
|
+
expect(dpp.protocolVersion).to.equal(42);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe('getProtocolVersion', () => {
|
|
71
|
+
it('should get protocol version', () => {
|
|
72
|
+
expect(dpp.getProtocolVersion()).to.equal(protocolVersion.latestVersion);
|
|
73
|
+
|
|
74
|
+
dpp.setProtocolVersion(42);
|
|
75
|
+
|
|
76
|
+
expect(dpp.getProtocolVersion()).to.equal(42);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
});
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
const crypto = require('crypto');
|
|
2
|
+
const bs58 = require('bs58');
|
|
3
|
+
const Identifier = require('../../lib/identifier/Identifier');
|
|
4
|
+
const IdentifierError = require('../../lib/identifier/errors/IdentifierError');
|
|
5
|
+
|
|
6
|
+
describe('Identifier', () => {
|
|
7
|
+
let buffer;
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
buffer = crypto.randomBytes(32);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
describe('#constructor', () => {
|
|
14
|
+
it('should accept Buffer', () => {
|
|
15
|
+
const identifier = new Identifier(buffer);
|
|
16
|
+
|
|
17
|
+
expect(identifier).to.be.deep.equal(buffer);
|
|
18
|
+
expect(identifier).to.be.an.instanceOf(Identifier);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should throw error if first argument is not Buffer', () => {
|
|
22
|
+
expect(
|
|
23
|
+
() => new Identifier(1),
|
|
24
|
+
).to.throw(IdentifierError, 'Identifier expects Buffer');
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('should throw error if buffer is not 32 bytes long', () => {
|
|
28
|
+
expect(
|
|
29
|
+
() => new Identifier(Buffer.alloc(30)),
|
|
30
|
+
).to.throw(IdentifierError, 'Identifier must be 32 long');
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
describe('#toBuffer', () => {
|
|
35
|
+
it('should return a new normal Buffer', () => {
|
|
36
|
+
const identifier = new Identifier(buffer);
|
|
37
|
+
|
|
38
|
+
expect(identifier.toBuffer()).to.deep.equal(buffer);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe('#encodeCBOR', () => {
|
|
43
|
+
let encoderMock;
|
|
44
|
+
|
|
45
|
+
beforeEach(function before() {
|
|
46
|
+
encoderMock = {
|
|
47
|
+
pushAny: this.sinonSandbox.stub(),
|
|
48
|
+
};
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should encode using cbor encoder', () => {
|
|
52
|
+
const identifier = new Identifier(buffer);
|
|
53
|
+
|
|
54
|
+
const result = identifier.encodeCBOR(encoderMock);
|
|
55
|
+
|
|
56
|
+
expect(result).to.be.true();
|
|
57
|
+
expect(encoderMock.pushAny).to.be.calledOnceWithExactly(buffer);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe('#toJSON', () => {
|
|
62
|
+
it('should return a base58 encoded string', () => {
|
|
63
|
+
const identifier = new Identifier(buffer);
|
|
64
|
+
|
|
65
|
+
const string = identifier.toJSON();
|
|
66
|
+
|
|
67
|
+
expect(string).to.equal(bs58.encode(buffer));
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe('#toString', () => {
|
|
72
|
+
it('should return a base58 encoded string by default', () => {
|
|
73
|
+
const base58string = bs58.encode(buffer);
|
|
74
|
+
|
|
75
|
+
const identifier = new Identifier(buffer);
|
|
76
|
+
|
|
77
|
+
const string = identifier.toString();
|
|
78
|
+
|
|
79
|
+
expect(string).to.equal(base58string);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('should return a string encoded with specified encoding', () => {
|
|
83
|
+
const identifier = new Identifier(buffer);
|
|
84
|
+
|
|
85
|
+
const string = identifier.toString('base64');
|
|
86
|
+
|
|
87
|
+
expect(string).to.equal(buffer.toString('base64'));
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe('#from', () => {
|
|
92
|
+
it('should create an instance from Buffer', async () => {
|
|
93
|
+
const identifier = Identifier.from(buffer);
|
|
94
|
+
|
|
95
|
+
expect(identifier).to.be.an.instanceOf(Identifier);
|
|
96
|
+
expect(identifier).to.deep.equal(buffer);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('should throw error if buffer is passed among with encoding', async () => {
|
|
100
|
+
expect(
|
|
101
|
+
() => Identifier.from(buffer, 'base64'),
|
|
102
|
+
).to.throw(IdentifierError, 'encoding accepted only with type string');
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('should create an instance with a base58 string', () => {
|
|
106
|
+
const string = bs58.encode(buffer);
|
|
107
|
+
|
|
108
|
+
const identifier = Identifier.from(string);
|
|
109
|
+
|
|
110
|
+
expect(identifier).to.be.an.instanceOf(Identifier);
|
|
111
|
+
expect(identifier).to.deep.equal(buffer);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('should create an instance with a base64 string', () => {
|
|
115
|
+
const string = buffer.toString('base64');
|
|
116
|
+
|
|
117
|
+
const identifier = Identifier.from(string, 'base64');
|
|
118
|
+
|
|
119
|
+
expect(identifier).to.be.an.instanceOf(Identifier);
|
|
120
|
+
expect(identifier).to.deep.equal(buffer);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
});
|