@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.
Files changed (110) hide show
  1. package/.babelrc +5 -0
  2. package/.editorconfig +13 -0
  3. package/.eslintignore +1 -0
  4. package/.eslintrc +15 -0
  5. package/.mocharc.yml +4 -0
  6. package/CHANGELOG.md +397 -0
  7. package/LICENSE +20 -0
  8. package/README.md +37 -0
  9. package/karma.conf.js +53 -0
  10. package/package.json +107 -0
  11. package/test/.eslintrc +12 -0
  12. package/test/integration/DashPlatformProtocol.spec.js +53 -0
  13. package/test/integration/ajv/keywords/byteArray/addByteArrayKeyword.spec.js +148 -0
  14. package/test/integration/dataContract/DataContractFacade.spec.js +84 -0
  15. package/test/integration/dataContract/stateTransition/DataContractCreateTransition/validation/basic/validateDataContractCreateTransitionBasicFactory.spec.js +357 -0
  16. package/test/integration/dataContract/stateTransition/DataContractUpdateTransition/validation/basic/validateDataContractUpdateTransitionBasicFactory.spec.js +444 -0
  17. package/test/integration/dataContract/validation/validateDataContractFactory.spec.js +2191 -0
  18. package/test/integration/document/Document.spec.js +90 -0
  19. package/test/integration/document/DocumentFacade.spec.js +155 -0
  20. package/test/integration/document/stateTransition/DocumentsBatchTransition/DocumentBatchTransition.spec.js +83 -0
  21. package/test/integration/document/stateTransition/DocumentsBatchTransition/validation/basic/validateDocumentsBatchTransitionBasicFactory.spec.js +1146 -0
  22. package/test/integration/document/stateTransition/DocumentsBatchTransition/validation/state/executeDataTriggersFactory.spec.js +294 -0
  23. package/test/integration/document/validation/validateDocumentFactory.spec.js +447 -0
  24. package/test/integration/error/consensus/createConsensusError.spec.js +21 -0
  25. package/test/integration/identity/IdentityFacade.spec.js +187 -0
  26. package/test/integration/identity/stateTransition/IdentityCreateTransition/validation/basic/validateIdentityCreateTransitionBasicFactory.spec.js +422 -0
  27. package/test/integration/identity/stateTransition/IdentityTopUpTransition/validation/basic/validateIdentityTopUpTransitionBasicFactory.spec.js +361 -0
  28. package/test/integration/identity/stateTransition/IdentityUpdateTransition/validation/basic/validateIdentityUpdateTransitionBasicFactory.spec.js +595 -0
  29. package/test/integration/identity/stateTransition/IdentityUpdateTransition/validation/state/validateIdentityUpdateTransitionStateFactory.spec.js +299 -0
  30. package/test/integration/identity/stateTransition/IdentityUpdateTransition/validation/state/validatePublicKeysState.spec.js +66 -0
  31. package/test/integration/identity/stateTransition/assetLockProof/chain/validateChainAssetLockProofStructureFactory.spec.js +415 -0
  32. package/test/integration/identity/stateTransition/assetLockProof/fetchAssetLockTransactionOutputFactory.spec.js +134 -0
  33. package/test/integration/identity/stateTransition/assetLockProof/instant/validateInstantAssetLockProofStructureFactory.spec.js +401 -0
  34. package/test/integration/identity/stateTransition/assetLockProof/validateAssetLockTransactionFactory.spec.js +205 -0
  35. package/test/integration/identity/stateTransition/validatePublicKeySignaturesFactory.spec.js +127 -0
  36. package/test/integration/identity/validation/validateIdentityFactory.spec.js +370 -0
  37. package/test/integration/identity/validation/validatePublicKeysFactory.spec.js +497 -0
  38. package/test/integration/stateTransition/AbstractStateTransitionIdentitySigned.spec.js +507 -0
  39. package/test/integration/stateTransition/StateTransitionFacade.spec.js +418 -0
  40. package/test/integration/stateTransition/calculateStateTransitionFee.spec.js +35 -0
  41. package/test/integration/util/generateEntropy.spec.js +17 -0
  42. package/test/integration/util/serializer.spec.js +24 -0
  43. package/test/unit/DashPlatformProtocol.spec.js +79 -0
  44. package/test/unit/Identifier.spec.js +123 -0
  45. package/test/unit/Metadata.spec.js +37 -0
  46. package/test/unit/dataContract/DataContract.spec.js +407 -0
  47. package/test/unit/dataContract/DataContractFactory.spec.js +178 -0
  48. package/test/unit/dataContract/createDataContract.spec.js +57 -0
  49. package/test/unit/dataContract/errors/InvalidDataContractError.spec.js +46 -0
  50. package/test/unit/dataContract/generateDataContractId.spec.js +19 -0
  51. package/test/unit/dataContract/getBinaryPropertiesFromSchema.spec.js +103 -0
  52. package/test/unit/dataContract/getPropertyDefinitionByPath.spec.js +84 -0
  53. package/test/unit/dataContract/stateTransition/DataContractCreateTransition/DataContractCreateTransition.spec.js +160 -0
  54. package/test/unit/dataContract/stateTransition/DataContractCreateTransition/applyDataContractCreateTransitionFactory.spec.js +48 -0
  55. package/test/unit/dataContract/stateTransition/DataContractCreateTransition/validation/state/validateDataContractCreateTransitionStateFactory.spec.js +85 -0
  56. package/test/unit/dataContract/stateTransition/DataContractUpdateTransition/DataContractUpdateTransition.spec.js +158 -0
  57. package/test/unit/dataContract/stateTransition/DataContractUpdateTransition/applyDataContractUpdateTransitionFactory.spec.js +47 -0
  58. package/test/unit/dataContract/stateTransition/DataContractUpdateTransition/validation/basic/validateIndicesAreBackwardCompatible.spec.js +121 -0
  59. package/test/unit/dataContract/stateTransition/DataContractUpdateTransition/validation/state/validateDataContractUpdateTransitionStateFactory.spec.js +111 -0
  60. package/test/unit/dataContract/validation/validateDataContractMaxDepthFactory.spec.js +93 -0
  61. package/test/unit/dataContract/validation/validateDataContractPatternsFactory.spec.js +64 -0
  62. package/test/unit/dataTrigger/DataTrigger.spec.js +132 -0
  63. package/test/unit/dataTrigger/DataTriggerExecutionContext.spec.js +29 -0
  64. package/test/unit/dataTrigger/dashpayDataTriggers/createContactRequestDataTrigger.spec.js +109 -0
  65. package/test/unit/dataTrigger/dpnsTriggers/createDomainDataTrigger.spec.js +382 -0
  66. package/test/unit/dataTrigger/featureFlagDataTriggers/createFeatureFlagDataTrigger.spec.js +101 -0
  67. package/test/unit/dataTrigger/getDataTriggersFactory.spec.js +113 -0
  68. package/test/unit/dataTrigger/rejectDataTrigger.spec.js +51 -0
  69. package/test/unit/dataTrigger/rewardShareDataTriggers/createMasternodeRewardSharesDataTrigger.spec.js +200 -0
  70. package/test/unit/decodeProtocolEntityFactory.spec.js +75 -0
  71. package/test/unit/document/Document.spec.js +444 -0
  72. package/test/unit/document/DocumentFactory.spec.js +376 -0
  73. package/test/unit/document/errors/InvalidDocumentError.spec.js +46 -0
  74. package/test/unit/document/fetchAndValidateDataContractFactory.spec.js +66 -0
  75. package/test/unit/document/stateTransition/DocumetsBatchTransition/DocumentsBatchTransition.spec.js +168 -0
  76. package/test/unit/document/stateTransition/DocumetsBatchTransition/applyDocumentsBatchTransitionFactory.spec.js +171 -0
  77. package/test/unit/document/stateTransition/DocumetsBatchTransition/documentTransition/DocumentCreateTransition.spec.js +25 -0
  78. package/test/unit/document/stateTransition/DocumetsBatchTransition/validation/basic/findDuplicatesById.spec.js +31 -0
  79. package/test/unit/document/stateTransition/DocumetsBatchTransition/validation/basic/findDuplicatesByIndices.spec.js +122 -0
  80. package/test/unit/document/stateTransition/DocumetsBatchTransition/validation/basic/validatePartialCompoundIndices.spec.js +75 -0
  81. package/test/unit/document/stateTransition/DocumetsBatchTransition/validation/state/fetchDocumentsFactory.spec.js +128 -0
  82. package/test/unit/document/stateTransition/DocumetsBatchTransition/validation/state/validateDocumentsBatchTransitionStateFactory.spec.js +811 -0
  83. package/test/unit/document/stateTransition/DocumetsBatchTransition/validation/state/validateDocumentsUniquenessByIndicesFactory.spec.js +279 -0
  84. package/test/unit/errors/consensus/codes.spec.js +102 -0
  85. package/test/unit/identity/Identity.spec.js +243 -0
  86. package/test/unit/identity/IdentityFactory.spec.js +274 -0
  87. package/test/unit/identity/IdentityPublicKey.spec.js +273 -0
  88. package/test/unit/identity/creditsConverter.spec.js +34 -0
  89. package/test/unit/identity/errors/InvalidIdentityError.spec.js +46 -0
  90. package/test/unit/identity/stateTransition/IdentityCreateTransition/IdentityCreateTransition.spec.js +184 -0
  91. package/test/unit/identity/stateTransition/IdentityCreateTransition/applyIdentityCreateTransitionFactory.spec.js +90 -0
  92. package/test/unit/identity/stateTransition/IdentityCreateTransition/validation/state/validateIdentityCreateTransitionStateFactory.spec.js +71 -0
  93. package/test/unit/identity/stateTransition/IdentityTopUpTransition/IdentityTopUpTransition.spec.js +137 -0
  94. package/test/unit/identity/stateTransition/IdentityTopUpTransition/applyIdentityTopUpTransitionFactory.spec.js +108 -0
  95. package/test/unit/identity/stateTransition/IdentityTopUpTransition/validation/state/validateIdentityTopUpTransitionStateFactory.spec.js +22 -0
  96. package/test/unit/identity/stateTransition/IdentityUpdateTransition/IdentityUpdateTransition.spec.js +219 -0
  97. package/test/unit/identity/stateTransition/IdentityUpdateTransition/applyIdentityUpdateTransitionFactory.spec.js +149 -0
  98. package/test/unit/identity/stateTransition/assetLockProof/createAssetLockProofInstance.spec.js +21 -0
  99. package/test/unit/identity/stateTransition/assetLockProof/fetchAssetLockPublicKeyHashFactory.spec.js +36 -0
  100. package/test/unit/identity/validation/validateRequiredPurposeAndSecurityLevelFactory.spec.js +47 -0
  101. package/test/unit/stateTransition/StateTransitionFactory.spec.js +160 -0
  102. package/test/unit/stateTransition/createStateTransitionFactory.spec.js +72 -0
  103. package/test/unit/stateTransition/errors/InvalidStateTransitionError.spec.js +51 -0
  104. package/test/unit/stateTransition/validation/validateStateTransitionBasicFactory.spec.js +138 -0
  105. package/test/unit/stateTransition/validation/validateStateTransitionFeeFactory.spec.js +372 -0
  106. package/test/unit/stateTransition/validation/validateStateTransitionIdentitySignatureFactory.spec.js +339 -0
  107. package/test/unit/stateTransition/validation/validateStateTransitionKeySignatureFactory.spec.js +86 -0
  108. package/test/unit/stateTransition/validation/validateStateTransitionStateFactory.spec.js +89 -0
  109. package/test/unit/version/validateProtocolVersionFactory.spec.js +80 -0
  110. package/webpack.config.js +49 -0
@@ -0,0 +1,132 @@
1
+ const bs58 = require('bs58');
2
+ const AbstractDocumentTransition = require('../../../lib/document/stateTransition/DocumentsBatchTransition/documentTransition/AbstractDocumentTransition');
3
+ const DataTrigger = require('../../../lib/dataTrigger/DataTrigger');
4
+ const DataTriggerExecutionContext = require('../../../lib/dataTrigger/DataTriggerExecutionContext');
5
+ const getDpnsContractFixture = require('../../../lib/test/fixtures/getDpnsContractFixture');
6
+ const DataTriggerExecutionResult = require('../../../lib/dataTrigger/DataTriggerExecutionResult');
7
+ const getDocumentsFixture = require('../../../lib/test/fixtures/getDocumentsFixture');
8
+ const DataTriggerExecutionError = require('../../../lib/errors/consensus/state/dataContract/dataTrigger/DataTriggerExecutionError');
9
+ const DataTriggerInvalidResultError = require('../../../lib/errors/consensus/state/dataContract/dataTrigger/DataTriggerInvalidResultError');
10
+
11
+ describe('DataTrigger', () => {
12
+ let dataContractMock;
13
+ let context;
14
+ let triggerStub;
15
+ let document;
16
+ let topLevelIdentity;
17
+
18
+ beforeEach(function beforeEach() {
19
+ triggerStub = this.sinonSandbox.stub().resolves(new DataTriggerExecutionResult());
20
+ dataContractMock = getDpnsContractFixture();
21
+
22
+ ([document] = getDocumentsFixture());
23
+
24
+ context = new DataTriggerExecutionContext(
25
+ null,
26
+ bs58.decode('5zcXZpTLWFwZjKjq3ME5KVavtZa9YUaZESVzrndehBhq'),
27
+ dataContractMock,
28
+ );
29
+
30
+ topLevelIdentity = context.getOwnerId();
31
+ });
32
+
33
+ it('should check trigger fields', () => {
34
+ const trigger = new DataTrigger(
35
+ dataContractMock.getId(),
36
+ document.getType(),
37
+ AbstractDocumentTransition.ACTIONS.CREATE,
38
+ triggerStub,
39
+ topLevelIdentity,
40
+ );
41
+
42
+ expect(trigger.dataContractId).to.equal(dataContractMock.getId());
43
+ expect(trigger.documentType).to.equal(document.getType());
44
+ expect(trigger.transitionAction).to.equal(AbstractDocumentTransition.ACTIONS.CREATE);
45
+ expect(trigger.trigger).to.equal(triggerStub);
46
+ expect(trigger.topLevelIdentity).to.equal(topLevelIdentity);
47
+ });
48
+
49
+ describe('#execute', () => {
50
+ it('should check trigger execution', async () => {
51
+ const trigger = new DataTrigger(
52
+ dataContractMock.getId(),
53
+ document.getType(),
54
+ AbstractDocumentTransition.ACTIONS.CREATE,
55
+ triggerStub,
56
+ topLevelIdentity,
57
+ );
58
+
59
+ const result = await trigger.execute(context);
60
+
61
+ expect(result).to.be.instanceOf(DataTriggerExecutionResult);
62
+ });
63
+
64
+ it('should pass through the result of the trigger function', async () => {
65
+ const functionResult = new DataTriggerExecutionResult();
66
+
67
+ const triggerError = new Error('Trigger error');
68
+
69
+ functionResult.addError(triggerError);
70
+
71
+ triggerStub.resolves(functionResult);
72
+
73
+ const trigger = new DataTrigger(
74
+ dataContractMock.getId(),
75
+ document.getType(),
76
+ AbstractDocumentTransition.ACTIONS.CREATE,
77
+ triggerStub,
78
+ topLevelIdentity,
79
+ );
80
+
81
+ const result = await trigger.execute(document, context);
82
+
83
+ expect(result).to.deep.equal(functionResult);
84
+ expect(result.getErrors()[0]).to.deep.equal(triggerError);
85
+ });
86
+
87
+ it('should return a result with execution error if trigger function have thrown an error', async () => {
88
+ const triggerError = new Error('Trigger error');
89
+
90
+ triggerStub.throws(triggerError);
91
+
92
+ const trigger = new DataTrigger(
93
+ dataContractMock.getId(),
94
+ document.getType(),
95
+ AbstractDocumentTransition.ACTIONS.CREATE,
96
+ triggerStub,
97
+ topLevelIdentity,
98
+ );
99
+
100
+ const result = await trigger.execute(document, context);
101
+
102
+ expect(result).to.be.an.instanceOf(DataTriggerExecutionResult);
103
+
104
+ const [error] = result.getErrors();
105
+
106
+ expect(error).to.be.an.instanceOf(DataTriggerExecutionError);
107
+
108
+ expect(error.getExecutionError()).to.equal(triggerError);
109
+ });
110
+
111
+ it('should return a result with invalid result error if trigger function have not returned any result', async () => {
112
+ triggerStub.resolves(null);
113
+
114
+ const trigger = new DataTrigger(
115
+ dataContractMock.getId(),
116
+ document.getType(),
117
+ AbstractDocumentTransition.ACTIONS.CREATE,
118
+ triggerStub,
119
+ topLevelIdentity,
120
+ );
121
+
122
+ const result = await trigger.execute(document, context);
123
+
124
+ expect(result).to.be.an.instanceOf(DataTriggerExecutionResult);
125
+
126
+ const [error] = result.getErrors();
127
+
128
+ expect(error).to.be.an.instanceOf(DataTriggerInvalidResultError);
129
+ expect(error.message).to.equal('Data trigger have not returned any result');
130
+ });
131
+ });
132
+ });
@@ -0,0 +1,29 @@
1
+ const bs58 = require('bs58');
2
+ const DataTriggerExecutionContext = require('../../../lib/dataTrigger/DataTriggerExecutionContext');
3
+ const createStateRepositoryMock = require('../../../lib/test/mocks/createStateRepositoryMock');
4
+ const getDpnsContractFixture = require('../../../lib/test/fixtures/getDpnsContractFixture');
5
+ const StateTransitionExecutionContext = require('../../../lib/stateTransition/StateTransitionExecutionContext');
6
+
7
+ describe('DataTriggerExecutionContext', () => {
8
+ let dataContractMock;
9
+ let stateRepositoryMock;
10
+
11
+ beforeEach(function beforeEach() {
12
+ dataContractMock = getDpnsContractFixture();
13
+ stateRepositoryMock = createStateRepositoryMock(this.sinonSandbox);
14
+ });
15
+
16
+ it('should have all getters working', () => {
17
+ const ownerId = bs58.decode('5zcXZpTLWFwZjKjq3ME5KVavtZa9YUaZESVzrndehBhq');
18
+ const context = new DataTriggerExecutionContext(
19
+ stateRepositoryMock,
20
+ ownerId,
21
+ dataContractMock,
22
+ new StateTransitionExecutionContext(),
23
+ );
24
+
25
+ expect(context.getDataContract()).to.be.deep.equal(dataContractMock);
26
+ expect(context.getStateRepository()).to.be.deep.equal(stateRepositoryMock);
27
+ expect(context.getOwnerId()).to.be.deep.equal(ownerId);
28
+ });
29
+ });
@@ -0,0 +1,109 @@
1
+ const createContactRequestDataTrigger = require('../../../../lib/dataTrigger/dashpayDataTriggers/createContactRequestDataTrigger');
2
+
3
+ const DataTriggerExecutionContext = require('../../../../lib/dataTrigger/DataTriggerExecutionContext');
4
+ const DataTriggerExecutionResult = require('../../../../lib/dataTrigger/DataTriggerExecutionResult');
5
+ const DataTriggerConditionError = require('../../../../lib/errors/consensus/state/dataContract/dataTrigger/DataTriggerConditionError');
6
+
7
+ const createStateRepositoryMock = require('../../../../lib/test/mocks/createStateRepositoryMock');
8
+ const getDocumentTransitionFixture = require('../../../../lib/test/fixtures/getDocumentTransitionsFixture');
9
+
10
+ const getDashPayContractFixture = require('../../../../lib/test/fixtures/getDashPayContractFixture');
11
+ const { getContactRequestDocumentFixture } = require('../../../../lib/test/fixtures/getDashPayDocumentFixture');
12
+ const StateTransitionExecutionContext = require('../../../../lib/stateTransition/StateTransitionExecutionContext');
13
+
14
+ describe('createContactRequestDataTrigger', () => {
15
+ let context;
16
+ let dashPayIdentity;
17
+ let stateRepositoryMock;
18
+ let dataContract;
19
+ let contactRequestDocument;
20
+ let documentTransition;
21
+
22
+ beforeEach(function beforeEach() {
23
+ contactRequestDocument = getContactRequestDocumentFixture();
24
+ dataContract = getDashPayContractFixture();
25
+
26
+ [documentTransition] = getDocumentTransitionFixture({
27
+ create: [contactRequestDocument],
28
+ });
29
+
30
+ stateRepositoryMock = createStateRepositoryMock(this.sinonSandbox);
31
+ stateRepositoryMock.fetchLatestPlatformBlockHeader.resolves({
32
+ coreChainLockedHeight: 42,
33
+ });
34
+
35
+ context = new DataTriggerExecutionContext(
36
+ stateRepositoryMock,
37
+ contactRequestDocument.getOwnerId(),
38
+ dataContract,
39
+ new StateTransitionExecutionContext(),
40
+ );
41
+
42
+ dashPayIdentity = context.getOwnerId();
43
+ });
44
+
45
+ it('should successfully execute if document is valid', async () => {
46
+ contactRequestDocument.data.coreHeightCreatedAt = 40;
47
+
48
+ [documentTransition] = getDocumentTransitionFixture({
49
+ create: [contactRequestDocument],
50
+ });
51
+
52
+ const result = await createContactRequestDataTrigger(
53
+ documentTransition, context, dashPayIdentity,
54
+ );
55
+
56
+ expect(result).to.be.an.instanceOf(DataTriggerExecutionResult);
57
+ expect(stateRepositoryMock.fetchLatestPlatformBlockHeader).to.be.calledOnce();
58
+ expect(result.isOk()).to.be.true();
59
+ });
60
+
61
+ it('should successfully execute if document has no `coreHeightCreatedAt` field', async () => {
62
+ const result = await createContactRequestDataTrigger(
63
+ documentTransition, context, dashPayIdentity,
64
+ );
65
+
66
+ expect(result).to.be.an.instanceOf(DataTriggerExecutionResult);
67
+ expect(stateRepositoryMock.fetchLatestPlatformBlockHeader).to.be.not.called();
68
+ expect(result.isOk()).to.be.true();
69
+ });
70
+
71
+ it('should fail with out of window error', async () => {
72
+ contactRequestDocument.data.coreHeightCreatedAt = 10;
73
+
74
+ [documentTransition] = getDocumentTransitionFixture({
75
+ create: [contactRequestDocument],
76
+ });
77
+
78
+ const result = await createContactRequestDataTrigger(
79
+ documentTransition, context, dashPayIdentity,
80
+ );
81
+
82
+ expect(result).to.be.an.instanceOf(DataTriggerExecutionResult);
83
+ expect(result.isOk()).to.be.false();
84
+
85
+ const [error] = result.getErrors();
86
+
87
+ expect(error).to.be.an.instanceOf(DataTriggerConditionError);
88
+ expect(error.message).to.equal('Core height 10 is out of block height window from 34 to 50');
89
+ });
90
+
91
+ it('should successfully execute on dry run', async () => {
92
+ contactRequestDocument.data.coreHeightCreatedAt = 10;
93
+ [documentTransition] = getDocumentTransitionFixture({
94
+ create: [contactRequestDocument],
95
+ });
96
+
97
+ context.getStateTransitionExecutionContext().enableDryRun();
98
+
99
+ const result = await createContactRequestDataTrigger(
100
+ documentTransition, context, dashPayIdentity,
101
+ );
102
+
103
+ context.getStateTransitionExecutionContext().disableDryRun();
104
+
105
+ expect(result).to.be.an.instanceOf(DataTriggerExecutionResult);
106
+ expect(stateRepositoryMock.fetchLatestPlatformBlockHeader).to.be.not.called();
107
+ expect(result.isOk()).to.be.true();
108
+ });
109
+ });
@@ -0,0 +1,382 @@
1
+ const createDomainDataTrigger = require('../../../../lib/dataTrigger/dpnsTriggers/createDomainDataTrigger');
2
+
3
+ const DataTriggerExecutionContext = require('../../../../lib/dataTrigger/DataTriggerExecutionContext');
4
+ const DataTriggerExecutionResult = require('../../../../lib/dataTrigger/DataTriggerExecutionResult');
5
+
6
+ const { getParentDocumentFixture, getChildDocumentFixture, getTopDocumentFixture } = require('../../../../lib/test/fixtures/getDpnsDocumentFixture');
7
+ const getPreorderDocumentFixture = require('../../../../lib/test/fixtures/getPreorderDocumentFixture');
8
+ const getDpnsContractFixture = require('../../../../lib/test/fixtures/getDpnsContractFixture');
9
+ const getDocumentTransitionFixture = require('../../../../lib/test/fixtures/getDocumentTransitionsFixture');
10
+ const createStateRepositoryMock = require('../../../../lib/test/mocks/createStateRepositoryMock');
11
+
12
+ const { hash } = require('../../../../lib/util/hash');
13
+
14
+ const DataTriggerConditionError = require('../../../../lib/errors/consensus/state/dataContract/dataTrigger/DataTriggerConditionError');
15
+ const Identifier = require('../../../../lib/identifier/Identifier');
16
+ const StateTransitionExecutionContext = require('../../../../lib/stateTransition/StateTransitionExecutionContext');
17
+
18
+ describe('createDomainDataTrigger', () => {
19
+ let parentDocumentTransition;
20
+ let childDocumentTransition;
21
+ let childDocument;
22
+ let parentDocument;
23
+ let topDocument;
24
+ let context;
25
+ let stateRepositoryMock;
26
+ let dataContract;
27
+ let topLevelIdentity;
28
+ let executionContext;
29
+
30
+ beforeEach(function beforeEach() {
31
+ dataContract = getDpnsContractFixture();
32
+
33
+ topDocument = getTopDocumentFixture();
34
+ parentDocument = getParentDocumentFixture();
35
+ childDocument = getChildDocumentFixture();
36
+ const preorderDocument = getPreorderDocumentFixture();
37
+
38
+ [parentDocumentTransition] = getDocumentTransitionFixture({
39
+ create: [parentDocument],
40
+ });
41
+
42
+ [childDocumentTransition] = getDocumentTransitionFixture({
43
+ create: [childDocument],
44
+ });
45
+
46
+ const {
47
+ preorderSalt, records, normalizedParentDomainName, normalizedLabel,
48
+ } = childDocument.getData();
49
+
50
+ let fullDomainName = normalizedLabel;
51
+ if (normalizedParentDomainName.length > 0) {
52
+ fullDomainName = `${normalizedLabel}.${normalizedParentDomainName}`;
53
+ }
54
+
55
+ stateRepositoryMock = createStateRepositoryMock(this.sinonSandbox);
56
+ stateRepositoryMock.fetchDocuments.resolves([]);
57
+
58
+ const [normalizedParentLabel] = normalizedParentDomainName.split('.');
59
+ const normalizedGrandParentDomainName = normalizedParentDomainName.split('.')
60
+ .slice(1)
61
+ .join('.');
62
+
63
+ stateRepositoryMock.fetchDocuments
64
+ .withArgs(
65
+ dataContract.getId(),
66
+ childDocument.getType(),
67
+ {
68
+ where: [
69
+ ['normalizedParentDomainName', '==', normalizedGrandParentDomainName],
70
+ ['normalizedLabel', '==', normalizedParentLabel],
71
+ ],
72
+ },
73
+ )
74
+ .resolves([parentDocument]);
75
+
76
+ const saltedDomainHashBuffer = Buffer.concat([
77
+ preorderSalt,
78
+ Buffer.from(fullDomainName),
79
+ ]);
80
+
81
+ const saltedDomainHash = hash(saltedDomainHashBuffer);
82
+
83
+ stateRepositoryMock.fetchDocuments
84
+ .withArgs(
85
+ dataContract.getId(),
86
+ 'preorder',
87
+ { where: [['saltedDomainHash', '==', saltedDomainHash]] },
88
+ )
89
+ .resolves([preorderDocument.toObject()]);
90
+
91
+ stateRepositoryMock.fetchTransaction.resolves(null);
92
+
93
+ stateRepositoryMock.fetchTransaction
94
+ .withArgs(
95
+ records.dashUniqueIdentityId,
96
+ )
97
+ .resolves({ confirmations: 10 });
98
+
99
+ executionContext = new StateTransitionExecutionContext();
100
+
101
+ context = new DataTriggerExecutionContext(
102
+ stateRepositoryMock,
103
+ records.dashUniqueIdentityId,
104
+ dataContract,
105
+ executionContext,
106
+ );
107
+
108
+ topLevelIdentity = context.getOwnerId();
109
+ });
110
+
111
+ it('should successfully execute if document is valid', async () => {
112
+ const result = await createDomainDataTrigger(
113
+ childDocumentTransition, context, topLevelIdentity,
114
+ );
115
+
116
+ expect(result.isOk()).to.be.true();
117
+ });
118
+
119
+ it('should fail with invalid normalizedLabel', async () => {
120
+ childDocument = getChildDocumentFixture({ normalizedLabel: childDocument.getData().label });
121
+ stateRepositoryMock.fetchTransaction
122
+ .withArgs(
123
+ childDocument.getData().records.dashUniqueIdentityId,
124
+ )
125
+ .resolves({ confirmations: 10 });
126
+
127
+ [childDocumentTransition] = getDocumentTransitionFixture({
128
+ create: [childDocument],
129
+ });
130
+
131
+ const result = await createDomainDataTrigger(
132
+ childDocumentTransition, context, topLevelIdentity,
133
+ );
134
+
135
+ expect(result).to.be.an.instanceOf(DataTriggerExecutionResult);
136
+ expect(result.isOk()).to.be.false();
137
+
138
+ const [error] = result.getErrors();
139
+
140
+ expect(error).to.be.an.instanceOf(DataTriggerConditionError);
141
+ expect(error.message).to.equal('Normalized label doesn\'t match label');
142
+ });
143
+
144
+ it('should fail with invalid parent domain', async () => {
145
+ childDocument = getChildDocumentFixture({
146
+ label: 'label',
147
+ normalizedLabel: 'label',
148
+ normalizedParentDomainName: 'parent.invalidname',
149
+ });
150
+
151
+ stateRepositoryMock.fetchTransaction
152
+ .withArgs(
153
+ childDocument.getData().records.dashUniqueIdentityId,
154
+ )
155
+ .resolves({ confirmations: 10 });
156
+
157
+ [childDocumentTransition] = getDocumentTransitionFixture({
158
+ create: [childDocument],
159
+ });
160
+
161
+ const result = await createDomainDataTrigger(
162
+ childDocumentTransition, context, topLevelIdentity,
163
+ );
164
+
165
+ expect(result).to.be.an.instanceOf(DataTriggerExecutionResult);
166
+ expect(result.isOk()).to.be.false();
167
+
168
+ const [error] = result.getErrors();
169
+
170
+ expect(error).to.be.an.instanceOf(DataTriggerConditionError);
171
+ expect(error.message).to.equal('Parent domain is not present');
172
+
173
+ expect(stateRepositoryMock.fetchDocuments).to.have.been.calledOnceWithExactly(
174
+ context.getDataContract().getId(),
175
+ 'domain',
176
+ {
177
+ where: [
178
+ ['normalizedParentDomainName', '==', 'invalidname'],
179
+ ['normalizedLabel', '==', 'parent'],
180
+ ],
181
+ },
182
+ executionContext,
183
+ );
184
+ });
185
+
186
+ it('should fail with invalid dashUniqueIdentityId', async () => {
187
+ const dashUniqueIdentityId = Identifier.from(
188
+ Buffer.alloc(32, 5),
189
+ );
190
+
191
+ childDocument = getChildDocumentFixture({
192
+ records: {
193
+ dashUniqueIdentityId: dashUniqueIdentityId.toBuffer(),
194
+ },
195
+ });
196
+
197
+ [childDocumentTransition] = getDocumentTransitionFixture({
198
+ create: [childDocument],
199
+ });
200
+
201
+ const result = await createDomainDataTrigger(
202
+ childDocumentTransition, context, topLevelIdentity,
203
+ );
204
+
205
+ expect(result).to.be.an.instanceOf(DataTriggerExecutionResult);
206
+ expect(result.isOk()).to.be.false();
207
+
208
+ const [error] = result.getErrors();
209
+
210
+ expect(error).to.be.an.instanceOf(DataTriggerConditionError);
211
+ expect(error.message).to.equal(`ownerId ${childDocument.getOwnerId()} doesn't match dashUniqueIdentityId ${dashUniqueIdentityId}`);
212
+ });
213
+
214
+ it('should fail with invalid dashAliasIdentityId', async () => {
215
+ const dashUniqueIdentityId = Identifier.from(
216
+ Buffer.alloc(32, 2),
217
+ );
218
+
219
+ childDocument = getChildDocumentFixture({
220
+ records: {
221
+ dashAliasIdentityId: dashUniqueIdentityId.toBuffer(),
222
+ },
223
+ });
224
+
225
+ [childDocumentTransition] = getDocumentTransitionFixture({
226
+ create: [childDocument],
227
+ });
228
+
229
+ const result = await createDomainDataTrigger(
230
+ childDocumentTransition, context, topLevelIdentity,
231
+ );
232
+
233
+ expect(result).to.be.an.instanceOf(DataTriggerExecutionResult);
234
+ expect(result.isOk()).to.be.false();
235
+
236
+ const [error] = result.getErrors();
237
+
238
+ expect(error).to.be.an.instanceOf(DataTriggerConditionError);
239
+ expect(error.message).to.equal(`ownerId ${childDocument.getOwnerId()} doesn't match dashAliasIdentityId ${dashUniqueIdentityId}`);
240
+ });
241
+
242
+ it('should fail with preorder document was not found', async () => {
243
+ childDocument = getChildDocumentFixture({
244
+ preorderSalt: Buffer.alloc(256, '012fd'),
245
+ });
246
+
247
+ [childDocumentTransition] = getDocumentTransitionFixture({
248
+ create: [childDocument],
249
+ });
250
+
251
+ const result = await createDomainDataTrigger(
252
+ childDocumentTransition, context, topLevelIdentity,
253
+ );
254
+
255
+ expect(result).to.be.an.instanceOf(DataTriggerExecutionResult);
256
+ expect(result.isOk()).to.be.false();
257
+
258
+ const [error] = result.getErrors();
259
+
260
+ expect(error).to.be.an.instanceOf(DataTriggerConditionError);
261
+ expect(error.message).to.equal('preorderDocument was not found');
262
+ });
263
+
264
+ it('should fail with invalid full domain name length', async () => {
265
+ childDocument = getChildDocumentFixture({
266
+ normalizedParentDomainName: 'a'.repeat(512),
267
+ });
268
+
269
+ [childDocumentTransition] = getDocumentTransitionFixture({
270
+ create: [childDocument],
271
+ });
272
+
273
+ const result = await createDomainDataTrigger(
274
+ childDocumentTransition, context, topLevelIdentity,
275
+ );
276
+
277
+ expect(result).to.be.an.instanceOf(DataTriggerExecutionResult);
278
+ expect(result.isOk()).to.be.false();
279
+
280
+ const [error] = result.getErrors();
281
+
282
+ expect(error).to.be.an.instanceOf(DataTriggerConditionError);
283
+ expect(error.message).to.equal(
284
+ 'Full domain name length can not be more than 253 characters long but got 518',
285
+ );
286
+ });
287
+
288
+ it('should fail with identity can\'t create top level domain', async () => {
289
+ parentDocumentTransition.data.normalizedParentDomainName = '';
290
+
291
+ topLevelIdentity = Buffer.from('someIdentity');
292
+
293
+ const result = await createDomainDataTrigger(
294
+ parentDocumentTransition, context, topLevelIdentity,
295
+ );
296
+
297
+ expect(result).to.be.an.instanceOf(DataTriggerExecutionResult);
298
+ expect(result.isOk()).to.be.false();
299
+
300
+ const [error] = result.getErrors();
301
+
302
+ expect(error).to.be.an.instanceOf(DataTriggerConditionError);
303
+ expect(error.message).to.equal(
304
+ 'Can\'t create top level domain for this identity',
305
+ );
306
+ });
307
+
308
+ it('should fail with disallowed domain creation', async () => {
309
+ parentDocument.ownerId = Buffer.from('newId');
310
+
311
+ const result = await createDomainDataTrigger(
312
+ childDocumentTransition, context, topLevelIdentity,
313
+ );
314
+
315
+ expect(result).to.be.an.instanceOf(DataTriggerExecutionResult);
316
+ expect(result.isOk()).to.be.false();
317
+
318
+ const [error] = result.getErrors();
319
+ expect(error).to.be.an.instanceOf(DataTriggerConditionError);
320
+ expect(error.message).to.equal(
321
+ 'The subdomain can be created only by the parent domain owner',
322
+ );
323
+ });
324
+
325
+ it('should fail with allowing subdomains for non top level domain', async () => {
326
+ childDocument = getChildDocumentFixture({ subdomainRules: { allowSubdomains: true } });
327
+
328
+ [childDocumentTransition] = getDocumentTransitionFixture({
329
+ create: [childDocument],
330
+ });
331
+
332
+ const result = await createDomainDataTrigger(
333
+ childDocumentTransition, context, topLevelIdentity,
334
+ );
335
+
336
+ expect(result).to.be.an.instanceOf(DataTriggerExecutionResult);
337
+ expect(result.isOk()).to.be.false();
338
+
339
+ const [error] = result.getErrors();
340
+
341
+ expect(error).to.be.an.instanceOf(DataTriggerConditionError);
342
+ expect(error.message).to.equal(
343
+ 'Allowing subdomains registration is forbidden for non top level domains',
344
+ );
345
+ });
346
+
347
+ it('should allow creating a second level domain by any identity', async () => {
348
+ topDocument.ownerId = 'anotherId';
349
+
350
+ stateRepositoryMock.fetchDocuments.resolves([topDocument]);
351
+
352
+ const result = await createDomainDataTrigger(
353
+ parentDocumentTransition, context, topLevelIdentity,
354
+ );
355
+
356
+ expect(result.isOk()).to.be.true();
357
+ });
358
+
359
+ it('should return DataTriggerExecutionResult om dry run', async () => {
360
+ context.getStateTransitionExecutionContext().enableDryRun();
361
+
362
+ childDocument = getChildDocumentFixture({ normalizedLabel: childDocument.getData().label });
363
+ stateRepositoryMock.fetchTransaction
364
+ .withArgs(
365
+ childDocument.getData().records.dashUniqueIdentityId,
366
+ )
367
+ .resolves({ confirmations: 10 });
368
+
369
+ [childDocumentTransition] = getDocumentTransitionFixture({
370
+ create: [childDocument],
371
+ });
372
+
373
+ const result = await createDomainDataTrigger(
374
+ childDocumentTransition, context, topLevelIdentity,
375
+ );
376
+
377
+ context.getStateTransitionExecutionContext().disableDryRun();
378
+
379
+ expect(result).to.be.an.instanceOf(DataTriggerExecutionResult);
380
+ expect(result.isOk()).to.be.true();
381
+ });
382
+ });