trac-msb 0.2.8 → 0.2.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 (151) hide show
  1. package/.github/workflows/acceptance-tests.yml +7 -11
  2. package/.github/workflows/lint-pr-title.yml +26 -0
  3. package/.github/workflows/unit-tests.yml +2 -8
  4. package/CODE_OF_CONDUCT.md +128 -0
  5. package/README.md +33 -18
  6. package/docker-compose.yml +1 -0
  7. package/docs/trac_network_http_api.openapi.yaml +889 -0
  8. package/msb.mjs +5 -22
  9. package/package.json +14 -10
  10. package/proto/network.proto +74 -0
  11. package/rpc/create_server.js +2 -2
  12. package/rpc/handlers.js +165 -92
  13. package/rpc/routes/v1.js +3 -1
  14. package/rpc/rpc_server.js +4 -4
  15. package/rpc/rpc_services.js +62 -25
  16. package/rpc/utils/helpers.js +83 -52
  17. package/src/config/args.js +46 -0
  18. package/src/config/config.js +78 -5
  19. package/src/config/env.js +70 -3
  20. package/src/core/network/Network.js +34 -70
  21. package/src/core/network/identity/NetworkWalletFactory.js +2 -2
  22. package/src/core/network/protocols/LegacyProtocol.js +67 -0
  23. package/src/core/network/protocols/NetworkMessages.js +48 -0
  24. package/src/core/network/protocols/ProtocolInterface.js +31 -0
  25. package/src/core/network/protocols/ProtocolSession.js +59 -0
  26. package/src/core/network/protocols/V1Protocol.js +64 -0
  27. package/src/core/network/protocols/legacy/NetworkMessageRouter.js +84 -0
  28. package/src/core/network/protocols/legacy/handlers/GetRequestHandler.js +53 -0
  29. package/src/core/network/protocols/legacy/handlers/ResponseHandler.js +37 -0
  30. package/src/core/network/{messaging → protocols/legacy}/validators/base/BaseResponse.js +2 -3
  31. package/src/core/network/protocols/shared/handlers/RoleOperationHandler.js +88 -0
  32. package/src/core/network/protocols/shared/handlers/SubnetworkOperationHandler.js +93 -0
  33. package/src/core/network/{messaging → protocols/shared}/handlers/TransferOperationHandler.js +17 -16
  34. package/src/core/network/{messaging → protocols/shared}/handlers/base/BaseOperationHandler.js +10 -15
  35. package/src/core/network/{messaging → protocols/shared}/validators/PartialBootstrapDeployment.js +2 -2
  36. package/src/core/network/{messaging → protocols/shared}/validators/PartialRoleAccess.js +5 -5
  37. package/src/core/network/{messaging → protocols/shared}/validators/PartialTransaction.js +4 -4
  38. package/src/core/network/{messaging → protocols/shared}/validators/PartialTransfer.js +4 -4
  39. package/src/core/network/{messaging → protocols/shared}/validators/base/PartialOperation.js +14 -12
  40. package/src/core/network/protocols/v1/NetworkMessageRouter.js +15 -0
  41. package/src/core/network/services/ConnectionManager.js +5 -5
  42. package/src/core/network/services/MessageOrchestrator.js +2 -2
  43. package/src/core/network/services/TransactionPoolService.js +5 -6
  44. package/src/core/network/services/TransactionRateLimiterService.js +12 -13
  45. package/src/core/network/services/ValidatorObserverService.js +5 -6
  46. package/src/core/state/State.js +3 -5
  47. package/src/index.js +156 -181
  48. package/src/messages/network/v1/NetworkMessageBuilder.js +325 -0
  49. package/src/messages/network/v1/NetworkMessageDirector.js +137 -0
  50. package/src/messages/network/v1/networkMessageFactory.js +12 -0
  51. package/src/messages/state/ApplyStateMessageBuilder.js +661 -0
  52. package/src/messages/state/ApplyStateMessageDirector.js +516 -0
  53. package/src/messages/state/applyStateMessageFactory.js +12 -0
  54. package/src/utils/buffer.js +53 -1
  55. package/src/utils/check.js +1 -1
  56. package/src/utils/cli.js +0 -8
  57. package/src/utils/constants.js +33 -30
  58. package/src/utils/fileUtils.js +13 -0
  59. package/src/utils/normalizers.js +84 -2
  60. package/src/utils/protobuf/network.cjs +840 -0
  61. package/src/utils/protobuf/operationHelpers.js +10 -0
  62. package/src/utils/type.js +26 -0
  63. package/tests/acceptance/v1/balance/balance.test.mjs +1 -2
  64. package/tests/acceptance/v1/broadcast-transaction/broadcast-transaction.test.mjs +26 -30
  65. package/tests/acceptance/v1/health/health.test.mjs +33 -0
  66. package/tests/acceptance/v1/rpc.test.mjs +4 -3
  67. package/tests/acceptance/v1/tx/tx.test.mjs +27 -16
  68. package/tests/acceptance/v1/tx-details/tx-details.test.mjs +26 -12
  69. package/tests/fixtures/check.fixtures.js +33 -32
  70. package/tests/fixtures/networkV1.fixtures.js +85 -0
  71. package/tests/fixtures/protobuf.fixtures.js +109 -25
  72. package/tests/helpers/StateNetworkFactory.js +2 -2
  73. package/tests/helpers/address.js +6 -0
  74. package/tests/helpers/autobaseTestHelpers.js +2 -1
  75. package/tests/helpers/config.js +2 -1
  76. package/tests/helpers/setupApplyTests.js +59 -56
  77. package/tests/unit/messages/messages.test.js +12 -0
  78. package/tests/unit/messages/network/NetworkMessageBuilder.test.js +276 -0
  79. package/tests/unit/messages/network/NetworkMessageDirector.test.js +201 -0
  80. package/tests/unit/messages/state/applyStateMessageBuilder.complete.test.js +521 -0
  81. package/tests/unit/messages/state/applyStateMessageBuilder.partial.test.js +233 -0
  82. package/tests/unit/network/ConnectionManager.test.js +6 -5
  83. package/tests/unit/network/networkModule.test.js +3 -2
  84. package/tests/unit/state/apply/addAdmin/addAdminHappyPathScenario.js +10 -6
  85. package/tests/unit/state/apply/addAdmin/addAdminScenarioHelpers.js +9 -6
  86. package/tests/unit/state/apply/addAdmin/state.apply.addAdmin.test.js +10 -7
  87. package/tests/unit/state/apply/addIndexer/addIndexerScenarioHelpers.js +18 -21
  88. package/tests/unit/state/apply/addWriter/addWriterScenarioHelpers.js +53 -38
  89. package/tests/unit/state/apply/adminRecovery/adminRecoveryScenarioHelpers.js +46 -35
  90. package/tests/unit/state/apply/appendWhitelist/appendWhitelistScenarioHelpers.js +13 -16
  91. package/tests/unit/state/apply/balanceInitialization/balanceInitializationScenarioHelpers.js +17 -11
  92. package/tests/unit/state/apply/banValidator/banValidatorScenarioHelpers.js +11 -12
  93. package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentScenarioHelpers.js +9 -7
  94. package/tests/unit/state/apply/common/commonScenarioHelper.js +15 -14
  95. package/tests/unit/state/apply/common/payload-structure/initializationDisabledScenario.js +9 -4
  96. package/tests/unit/state/apply/disableInitialization/disableInitializationScenarioHelpers.js +17 -11
  97. package/tests/unit/state/apply/removeWriter/removeWriterScenarioHelpers.js +19 -14
  98. package/tests/unit/state/apply/transfer/transferDoubleSpendAcrossValidatorsScenario.js +37 -29
  99. package/tests/unit/state/apply/transfer/transferScenarioHelpers.js +9 -7
  100. package/tests/unit/state/apply/txOperation/txOperationScenarioHelpers.js +11 -9
  101. package/tests/unit/unit.test.js +1 -1
  102. package/tests/unit/utils/buffer/buffer.test.js +62 -1
  103. package/tests/unit/utils/fileUtils/readAddressesFromWhitelistFile.test.js +4 -3
  104. package/tests/unit/utils/fileUtils/readBalanceMigrationFile.test.js +3 -2
  105. package/tests/unit/utils/migrationUtils/validateAddressFromIncomingFile.test.js +3 -2
  106. package/tests/unit/utils/normalizers/normalizers.test.js +469 -0
  107. package/tests/unit/utils/protobuf/operationHelpers.test.js +120 -2
  108. package/tests/unit/utils/type/type.test.js +25 -0
  109. package/tests/unit/utils/utils.test.js +1 -0
  110. package/docs/networking-dualstack-plan.md +0 -75
  111. package/docs/networking-layer-redesign.md +0 -155
  112. package/src/core/network/messaging/NetworkMessages.js +0 -64
  113. package/src/core/network/messaging/handlers/GetRequestHandler.js +0 -113
  114. package/src/core/network/messaging/handlers/ResponseHandler.js +0 -107
  115. package/src/core/network/messaging/handlers/RoleOperationHandler.js +0 -114
  116. package/src/core/network/messaging/handlers/SubnetworkOperationHandler.js +0 -149
  117. package/src/core/network/messaging/routes/NetworkMessageRouter.js +0 -98
  118. package/src/core/network/messaging/validators/AdminResponse.js +0 -58
  119. package/src/core/network/messaging/validators/CustomNodeResponse.js +0 -46
  120. package/src/messages/base/StateBuilder.js +0 -25
  121. package/src/messages/completeStateMessages/CompleteStateMessageBuilder.js +0 -425
  122. package/src/messages/completeStateMessages/CompleteStateMessageDirector.js +0 -252
  123. package/src/messages/completeStateMessages/CompleteStateMessageOperations.js +0 -296
  124. package/src/messages/partialStateMessages/PartialStateMessageBuilder.js +0 -272
  125. package/src/messages/partialStateMessages/PartialStateMessageDirector.js +0 -137
  126. package/src/messages/partialStateMessages/PartialStateMessageOperations.js +0 -138
  127. package/tests/integration/apply/addAdmin/addAdminBasic.test.js +0 -69
  128. package/tests/integration/apply/addAdmin/addAdminRecovery.test.js +0 -126
  129. package/tests/integration/apply/addIndexer.test.js +0 -239
  130. package/tests/integration/apply/addWhitelist.test.js +0 -53
  131. package/tests/integration/apply/addWriter.test.js +0 -245
  132. package/tests/integration/apply/apply.test.js +0 -19
  133. package/tests/integration/apply/banValidator.test.js +0 -116
  134. package/tests/integration/apply/postTx/invalidSubValues.test.js +0 -103
  135. package/tests/integration/apply/postTx/postTx.test.js +0 -196
  136. package/tests/integration/apply/removeIndexer.test.js +0 -132
  137. package/tests/integration/apply/removeWriter.test.js +0 -168
  138. package/tests/integration/apply/transfer.test.js +0 -83
  139. package/tests/integration/integration.test.js +0 -9
  140. package/tests/unit/messageOperations/assembleAddIndexerMessage.test.js +0 -21
  141. package/tests/unit/messageOperations/assembleAddWriterMessage.test.js +0 -17
  142. package/tests/unit/messageOperations/assembleAdminMessage.test.js +0 -68
  143. package/tests/unit/messageOperations/assembleBanWriterMessage.test.js +0 -17
  144. package/tests/unit/messageOperations/assemblePostTransaction.test.js +0 -424
  145. package/tests/unit/messageOperations/assembleRemoveIndexerMessage.test.js +0 -19
  146. package/tests/unit/messageOperations/assembleRemoveWriterMessage.test.js +0 -17
  147. package/tests/unit/messageOperations/assembleWhitelistMessages.test.js +0 -59
  148. package/tests/unit/messageOperations/commonsStateMessageOperationsTest.js +0 -278
  149. package/tests/unit/messageOperations/stateMessageOperations.test.js +0 -19
  150. /package/src/core/network/{messaging → protocols/legacy}/validators/ValidatorResponse.js +0 -0
  151. /package/src/utils/{operations.js → applyOperations.js} +0 -0
@@ -1,196 +0,0 @@
1
- import {hook, test} from '../../../helpers/wrapper.js';
2
- import b4a from "b4a";
3
- import {
4
- generatePostTx,
5
- initTemporaryDirectory,
6
- randomBytes,
7
- removeTemporaryDirectory,
8
- setupMsbAdmin,
9
- setupMsbPeer,
10
- setupMsbWriter,
11
- tick,
12
- fundPeer,
13
- deployExternalBootstrap,
14
- tryToSyncWriters,
15
- waitForHash,
16
- waitDemotion,
17
- promoteToWriter
18
- } from '../../../helpers/setupApplyTests.js';
19
- import {safeDecodeApplyOperation, safeEncodeApplyOperation} from '../../../../src/utils/protobuf/operationHelpers.js'
20
- import {testKeyPair1, testKeyPair2, testKeyPair3, testKeyPair4, testKeyPair5} from '../../../fixtures/apply.fixtures.js';
21
- import {OperationType} from "../../../../src/utils/constants.js";
22
- import {addressToBuffer} from "../../../../src/core/state/utils/address.js";
23
- import { $TNK } from '../../../../src/core/state/utils/balance.js';
24
- import { config } from '../../../helpers/config.js';
25
-
26
- let tmpDirectory, admin, writer, externalNode, externalBootstrap, maliciousPeer;
27
-
28
- const close = async node => {
29
- await node.msb.close()
30
- }
31
-
32
- hook('Initialize nodes', async t => {
33
- const randomChannel = randomBytes(32).toString('hex');
34
-
35
- const baseOptions = {
36
- enableTxApplyLogs: false,
37
- enableInteractiveMode: false,
38
- enableRoleRequester: false,
39
- enableValidatorObserver: false,
40
- channel: randomChannel,
41
- }
42
-
43
- tmpDirectory = await initTemporaryDirectory();
44
- admin = await setupMsbAdmin(testKeyPair1, tmpDirectory, baseOptions);
45
- writer = await setupMsbWriter(admin, 'writer1', testKeyPair2, tmpDirectory, admin.options);
46
- externalNode = await setupMsbPeer('reader1', testKeyPair4, tmpDirectory, admin.options);
47
- await fundPeer(admin, externalNode, $TNK(1n)) // we fund it since it will deploy stuff
48
- externalBootstrap = await deployExternalBootstrap(writer, externalNode)
49
- await tryToSyncWriters(writer, admin)
50
- maliciousPeer = await setupMsbPeer('maliciousWriter', testKeyPair5, tmpDirectory, admin.options);
51
- await fundPeer(admin, maliciousPeer, $TNK(10n))
52
- });
53
-
54
- test('handleApplyTxOperation (apply) - Append POST_TX into the base - Happy path', async t => {
55
- const {postTx, txHash} = await generatePostTx(writer, externalNode, externalBootstrap)
56
- await writer.msb.state.append(postTx)
57
- await waitForHash(writer, txHash)
58
- await tick();
59
-
60
- const result = await writer.msb.state.get(txHash);
61
- t.ok(result, 'post tx added to the base');
62
- })
63
-
64
- // Negative cases
65
-
66
- // TODO: This test has been disabled because we got rid of JSON schema validation in favor of protobuf validation. To enable this test again, we need to write a fake protobuf schema for postTx (maybe also for other operations) and forge an invalid payload.
67
-
68
- // test('nested object in postTx', async t => {
69
- // //is already tested in /test/check/postTx.test.js
70
- // let { postTx, preTxHash: txHash } = await generatePostTx(admin.msb, admin.wallet, legitWallet)
71
- // postTx = {
72
- // ...postTx,
73
- // foo: 'bar',
74
- // }
75
- // await admin.msb.state.append(postTx);
76
- // await tick();
77
-
78
- // t.absent(await admin.msb.state.get(txHash), 'post tx with nested object should not be added to the base');
79
- // postTx = {
80
- // ...postTx,
81
- // value: {
82
- // ...postTx.value,
83
- // foo: 'bar',
84
- // }
85
- // }
86
- // await admin.msb.state.append(postTx);
87
- // await tick();
88
- // t.absent(await admin.msb.state.get(txHash), 'post tx with nested object in value property should not be added to the base');
89
-
90
- // })
91
-
92
- test('handleApplyTxOperation (apply) - different operation type', async t => {
93
- const maliciousWriter = await promoteToWriter(admin, maliciousPeer)
94
- const {postTx, txHash} = await generatePostTx(writer, externalNode, externalBootstrap)
95
- const replaceByte = (input, index, replacement) => {
96
- const bufferHex = b4a.from(input, 'hex');
97
- bufferHex[index] = replacement;
98
- return b4a.from(bufferHex, 'hex');
99
- }
100
-
101
- const replacedPostTx = replaceByte(b4a.toString(postTx, 'hex'), 1, OperationType.ADD_ADMIN);
102
-
103
- await waitDemotion(maliciousWriter, async () => {
104
- await maliciousWriter.msb.state.append(replacedPostTx);
105
- })
106
- await tick();
107
-
108
- t.absent(await writer.msb.state.get(txHash), 'post tx with incorrect operation type should not be added to the base');
109
- })
110
-
111
- test('handleApplyTxOperation (apply) - invalid postTx signature (adversary signature - writer signature)', async t => {
112
- const maliciousWriter = await promoteToWriter(admin, maliciousPeer)
113
- const {postTx, txHash} = await generatePostTx(writer, externalNode, externalBootstrap)
114
- let decodedPostTx = safeDecodeApplyOperation(postTx);
115
-
116
- decodedPostTx.txo.vs = maliciousWriter.wallet.sign(
117
- b4a.concat([decodedPostTx.txo.tx, decodedPostTx.txo.vn])
118
- );
119
- const encodedMaliciousPostTx = safeEncodeApplyOperation(decodedPostTx);
120
- await waitDemotion(maliciousWriter, async () => {
121
- await maliciousWriter.msb.state.append(encodedMaliciousPostTx);
122
- })
123
-
124
- const result = await admin.msb.state.get(txHash);
125
- t.absent(result, 'adversary\'s fake signature should not be added to the base');
126
- });
127
-
128
-
129
- test('handleApplyTxOperation (apply) - invalid postTx signature (adversary signature - peer signature)', async t => {
130
- const maliciousWriter = await promoteToWriter(admin, maliciousPeer)
131
- const {postTx, txHash} = await generatePostTx(writer, externalNode, externalBootstrap)
132
-
133
- let decodedPostTx = safeDecodeApplyOperation(postTx);
134
-
135
- decodedPostTx.txo.is = maliciousWriter.wallet.sign(
136
- decodedPostTx.txo.tx
137
- );
138
- const encodedMaliciousPostTx = safeEncodeApplyOperation(decodedPostTx);
139
- await waitDemotion(maliciousWriter, async () => {
140
- await maliciousWriter.msb.state.append(encodedMaliciousPostTx);
141
- })
142
-
143
- const result = await writer.msb.state.get(txHash);
144
- t.absent(result, 'adversary prepared fake postTx signature (third key pair) should not be added to the base');
145
- });
146
-
147
- test('handleApplyTxOperation (apply) - oversized transaction', async t => {
148
- const maliciousWriter = await promoteToWriter(admin, maliciousPeer)
149
- const {postTx, txHash} = await generatePostTx(writer, externalNode, externalBootstrap)
150
- let decodedPostTx = safeDecodeApplyOperation(postTx);
151
-
152
- decodedPostTx.txo.vn = randomBytes(5000);
153
- const encodedMaliciousPostTx = safeEncodeApplyOperation(decodedPostTx);
154
-
155
- await waitDemotion(maliciousWriter, async () => {
156
- await maliciousWriter.msb.state.append(encodedMaliciousPostTx);
157
- })
158
- const result = await admin.msb.state.get(txHash);
159
- t.absent(result, 'oversized post tx should not be added to the base');
160
- });
161
-
162
- test('handleApplyTxOperation (apply) - invalid postTx address (malicious node replaces address)', async t => {
163
- const maliciousWriter = await promoteToWriter(admin, maliciousPeer)
164
- const {postTx, txHash} = await generatePostTx(writer, externalNode, externalBootstrap)
165
- let decodedPostTx = safeDecodeApplyOperation(postTx);
166
- decodedPostTx.address = addressToBuffer(maliciousWriter.wallet.address, config.addressPrefix);
167
- const encodedMaliciousPostTx = safeEncodeApplyOperation(decodedPostTx);
168
- await maliciousWriter.msb.state.append(encodedMaliciousPostTx);
169
- await waitDemotion(maliciousWriter, async () => {
170
- await maliciousWriter.msb.state.append(encodedMaliciousPostTx);
171
- })
172
- const result = await admin.msb.state.get(txHash);
173
- t.absent(result, 'post tx with malicious address should not be added to the base');
174
- });
175
-
176
- test('handleApplyTxOperation (apply) - invalid postTx txo.ia (malicious node replaces ia)', async t => {
177
- const maliciousWriter = await promoteToWriter(admin, maliciousPeer)
178
- const {postTx, txHash} = await generatePostTx(writer, externalNode, externalBootstrap)
179
- let decodedPostTx = safeDecodeApplyOperation(postTx);
180
- decodedPostTx.txo.ia = addressToBuffer(maliciousWriter.wallet.address, config.addressPrefix);
181
- const encodedMaliciousPostTx = safeEncodeApplyOperation(decodedPostTx);
182
- await waitDemotion(maliciousWriter, async () => {
183
- await maliciousWriter.msb.state.append(encodedMaliciousPostTx);
184
- })
185
- const result = await admin.msb.state.get(txHash);
186
- t.absent(result, 'post tx with malicious txo.ia should not be added to the base');
187
- });
188
-
189
- hook('Clean up postTx setup', async t => {
190
- // close msbBoostrap and remove temp directory
191
- if (writer?.msb) await close(writer)
192
- if (externalNode?.msb) await close(externalNode)
193
- if (admin?.msb) await close(admin)
194
- if (maliciousPeer?.msb) await close(maliciousPeer)
195
- if (tmpDirectory) await removeTemporaryDirectory(tmpDirectory);
196
- });
@@ -1,132 +0,0 @@
1
- import {test, hook} from '../../helpers/wrapper.js';
2
-
3
- import CompleteStateMessageOperations from '../../../src/messages/completeStateMessages/CompleteStateMessageOperations.js';
4
- import { config } from '../../helpers/config.js';
5
- import {
6
- initTemporaryDirectory,
7
- removeTemporaryDirectory,
8
- setupMsbAdmin,
9
- setupMsbWriter,
10
- randomBytes,
11
- setupMsbIndexer, waitForNodeState, tryToSyncWriters
12
- } from '../../helpers/setupApplyTests.js';
13
- import {testKeyPair1, testKeyPair2, testKeyPair3, testKeyPair4} from '../../fixtures/apply.fixtures.js';
14
- import b4a from 'b4a'
15
-
16
- let tmpDirectory, admin, indexer1, indexer2, writer;
17
-
18
- hook('Initialize nodes for addIndexer tests', async t => {
19
- const randomChannel = randomBytes(32).toString('hex');
20
- const baseOptions = {
21
- enableTxApplyLogs: false,
22
- enableInteractiveMode: false,
23
- enableRoleRequester: false,
24
- enableValidatorObserver: false,
25
- channel: randomChannel,
26
- }
27
- tmpDirectory = await initTemporaryDirectory();
28
-
29
- admin = await setupMsbAdmin(testKeyPair1, tmpDirectory, baseOptions);
30
- indexer1 = await setupMsbWriter(admin, 'indexer1', testKeyPair2, tmpDirectory, admin.options);
31
- indexer1 = await setupMsbIndexer(indexer1, admin);
32
-
33
- indexer2 = await setupMsbWriter(admin, 'indexer2', testKeyPair3, tmpDirectory, admin.options);
34
- indexer2 = await setupMsbIndexer(indexer2, admin);
35
-
36
- writer = await setupMsbWriter(admin, 'writer', testKeyPair4, tmpDirectory, admin.options);
37
- });
38
-
39
- test('handleApplyRemoveIndexerOperation (apply) - Append removeIndexer payload into the base - happy path', async t => {
40
- // indexer1 is already an indexer -> this indexer will lose its indexer status and will become a writer.
41
- // indexer2 is already an indexer
42
- // writer is already a writer
43
- const indexersEntryBefore = await writer.msb.state.getIndexersEntry();
44
- const validity = await admin.msb.state.getIndexerSequenceState()
45
- const assembledRemoveIndexerMessage = await new CompleteStateMessageOperations(admin.wallet, config)
46
- .assembleRemoveIndexerMessage(indexer1.wallet.address, validity);
47
- await admin.msb.state.append(assembledRemoveIndexerMessage);
48
- await tryToSyncWriters(admin, indexer1, indexer2);
49
- await waitForNodeState(indexer1, indexer1.wallet.address, {
50
- wk: indexer1.msb.state.writingKey,
51
- isWhitelisted: true,
52
- isWriter: true,
53
- isIndexer: false,
54
- })
55
-
56
- const indexersEntry = await indexer1.msb.state.getIndexersEntry();
57
- const nodeEntryIndexer1 = await indexer1.msb.state.getNodeEntry(indexer1.wallet.address);
58
-
59
- t.is(indexersEntry.length, indexersEntryBefore.length - 1, `Indexers entry count should be still ${indexersEntryBefore.length - 1}`);
60
- t.is(!!indexersEntry.find(({ key }) => b4a.equals(key, indexer1.msb.state.writingKey)), false, 'Indexer address should not be included in the indexers entry');
61
- t.is(nodeEntryIndexer1.isWriter, true, 'Node info should indicate that the node is a writer');
62
- t.is(nodeEntryIndexer1.isIndexer, false, 'Node info should indicate that the node is not an indexer');
63
- });
64
-
65
-
66
- test('handleApplyRemoveIndexerOperation (apply) - Append removeIndexer payload into the base - idempotence', async t => {
67
- // indexer1 is already a writer (after the previous test) -> let's test idempotence on this node.
68
- // indexer2 is already an indexer
69
- // writer is already a writer
70
- const adminSignedLengthBefore = admin.msb.state.getSignedLength();
71
- const indexer2SignedLengthBefore = indexer2.msb.state.getSignedLength();
72
- const writerSignedLengthBefore = writer.msb.state.getSignedLength();
73
-
74
- const indexersEntryBefore = await indexer1.msb.state.getIndexersEntry();
75
- const validity = await admin.msb.state.getIndexerSequenceState()
76
- const assembledRemoveIndexerMessage = await new CompleteStateMessageOperations(admin.wallet, config)
77
- .assembleRemoveIndexerMessage(indexer1.wallet.address, validity);
78
- await admin.msb.state.append(assembledRemoveIndexerMessage);
79
- await tryToSyncWriters(admin, indexer2, writer);
80
-
81
- const adminSignedLengthAfter = admin.msb.state.getSignedLength();
82
- const indexer2SignedLengthAfter = indexer2.msb.state.getSignedLength();
83
- const writerSignedLengthAfter = writer.msb.state.getSignedLength();
84
-
85
- const indexersEntry = await indexer1.msb.state.getIndexersEntry();
86
- const nodeInfo = await indexer1.msb.state.getNodeEntry(indexer1.wallet.address);
87
-
88
- t.is(indexersEntry.length, indexersEntryBefore.length, `Indexers entry count should remain ${indexersEntryBefore.length}`);
89
- t.is(!!indexersEntry.find(({ key }) => b4a.equals(key, indexer1.msb.state.writingKey)), false, 'Indexer address should not be included in the indexers entry');
90
- t.is(nodeInfo.isWriter, true, 'Node info should indicate that the node is a writer');
91
- t.is(nodeInfo.isIndexer, false, 'Node info should indicate that the node is not an indexer');
92
- t.is(adminSignedLengthBefore, adminSignedLengthAfter, 'Admin signed length should not change');
93
- t.is(indexer2SignedLengthBefore, indexer2SignedLengthAfter, 'Indexer2 signed length should not change');
94
- t.is(writerSignedLengthBefore, writerSignedLengthAfter, 'Writer signed length should not change');
95
- });
96
-
97
- test('handleApplyAddIndexerOperation (apply) - Append removeIndexer payload into the base by non-admin node', async t => {
98
- // indexer1 is already a writer.
99
- // indexer2 is already an indexer -> should still be an indexer after the operation.
100
- // writer is already a writer -> will try to remove indexer2 as a non-admin node, however it should not be allowed.
101
- const indexersEntryBefore = await indexer2.msb.state.getIndexersEntry();
102
- const writerSignedLengthBefore = admin.msb.state.getSignedLength();
103
- const indexer2SignedLengthBefore = indexer2.msb.state.getSignedLength();
104
-
105
- const validity = await admin.msb.state.getIndexerSequenceState()
106
- const assembledRemoveIndexerMessage = await new CompleteStateMessageOperations(admin.wallet, config)
107
- .assembleRemoveIndexerMessage(indexer2.wallet.address, validity);
108
- await writer.msb.state.append(assembledRemoveIndexerMessage);
109
- await tryToSyncWriters(admin, indexer2, writer);
110
-
111
- const writerSignedLengthAfter = writer.msb.state.getSignedLength();
112
- const indexer2SignedLengthAfter = indexer2.msb.state.getSignedLength();
113
-
114
- const indexersEntry = await indexer2.msb.state.getIndexersEntry();
115
- const nodeInfo = await indexer2.msb.state.getNodeEntry(indexer2.wallet.address);
116
-
117
- t.is(indexersEntry.length, indexersEntryBefore.length, `Indexers entry count should be still ${indexersEntryBefore.length}`);
118
- t.is(!!indexersEntry.find(({ key }) => b4a.equals(key, indexer2.msb.state.writingKey)), true, 'Indexer address should not be included in the indexers entry');
119
- t.is(nodeInfo.isIndexer, true, 'Node info should indicate that the node is an indexer');
120
- t.is(writerSignedLengthBefore, writerSignedLengthAfter, 'Writer signed length should not change');
121
- t.is(indexer2SignedLengthBefore, indexer2SignedLengthAfter, 'Indexer2 signed length should not change');
122
- });
123
-
124
- hook('Clean up removeIndexer setup', async t => {
125
- const toClose = []
126
- if (admin?.msb) toClose.push(admin.msb.close());
127
- if (indexer1?.msb) toClose.push(indexer1.msb.close());
128
- if (indexer2?.msb) toClose.push(indexer2.msb.close());
129
- if (writer?.msb) toClose.push(writer.msb.close());
130
- await Promise.all(toClose)
131
- if (tmpDirectory) await removeTemporaryDirectory(tmpDirectory);
132
- });
@@ -1,168 +0,0 @@
1
- import {test, hook} from '../../helpers/wrapper.js';
2
- import b4a from 'b4a';
3
- import {
4
- setupMsbAdmin,
5
- initTemporaryDirectory,
6
- removeTemporaryDirectory,
7
- setupMsbWriter,
8
- randomBytes,
9
- setupMsbIndexer,
10
- tryToSyncWriters,
11
- waitForNotIndexer,
12
- waitForNodeState,
13
- } from '../../helpers/setupApplyTests.js';
14
- import {
15
- testKeyPair1,
16
- testKeyPair2,
17
- testKeyPair3,
18
- testKeyPair4,
19
- testKeyPair5,
20
- testKeyPair6
21
- } from '../../fixtures/apply.fixtures.js';
22
- import CompleteStateMessageOperations from '../../../src/messages/completeStateMessages/CompleteStateMessageOperations.js';
23
- import PartialStateMessageOperations from '../../../src/messages/partialStateMessages/PartialStateMessageOperations.js';
24
- import { config } from '../../helpers/config.js';
25
-
26
- let admin, writer1, writer2, writer3, writer4, indexer, tmpDirectory;
27
-
28
- const sendRemoveWriter = async (invoker, broadcaster) => {
29
- const validity = await invoker.msb.state.getIndexerSequenceState()
30
- const writerRemoval = await new PartialStateMessageOperations(invoker.wallet, config)
31
- .assembleRemoveWriterMessage(
32
- b4a.toString(invoker.msb.state.writingKey, 'hex'),
33
- b4a.toString(validity, 'hex')
34
- );
35
-
36
- const raw = await new CompleteStateMessageOperations(broadcaster.wallet, config)
37
- .assembleRemoveWriterMessage(
38
- writerRemoval.address,
39
- b4a.from(writerRemoval.rao.tx, 'hex'),
40
- b4a.from(writerRemoval.rao.txv, 'hex'),
41
- b4a.from(writerRemoval.rao.iw, 'hex'),
42
- b4a.from(writerRemoval.rao.in, 'hex'),
43
- b4a.from(writerRemoval.rao.is, 'hex'),
44
- )
45
-
46
- return await broadcaster.msb.state.append(raw)
47
- }
48
-
49
- hook('Initialize nodes for removeWriter tests', async () => {
50
- tmpDirectory = await initTemporaryDirectory()
51
- const randomChannel = randomBytes(32).toString('hex');
52
-
53
- admin = await setupMsbAdmin(testKeyPair1, tmpDirectory, {
54
- enableTxApplyLogs: false,
55
- enableInteractiveMode: false,
56
- enableRoleRequester: false,
57
- enableValidatorObserver: false,
58
- channel: randomChannel,
59
- });
60
- writer1 = await setupMsbWriter(admin, 'writer', testKeyPair2, tmpDirectory, admin.options);
61
- writer2 = await setupMsbWriter(admin, 'writer2', testKeyPair3, tmpDirectory, admin.options);
62
- writer3 = await setupMsbWriter(admin, 'writer3', testKeyPair4, tmpDirectory, admin.options);
63
- writer4 = await setupMsbWriter(admin, 'writer4', testKeyPair5, tmpDirectory, admin.options);
64
-
65
- indexer = await setupMsbWriter(admin, 'indexer', testKeyPair6, tmpDirectory, admin.options);
66
- indexer = await setupMsbIndexer(indexer, admin);
67
- })
68
-
69
- test('handleApplyRemoveWriterOperation (apply) - Append removeWriter payload into the base - happy path', async (t) => {
70
- // writer1 is already a writer -> this writer will lose its writer status
71
- // writer2 is already a writer
72
- // writer3 is already a writer
73
- // writer4 is already a writer
74
- // indexer is already an indexer
75
- await sendRemoveWriter(writer1, writer2)
76
- await tryToSyncWriters(admin, writer2, writer3, writer4, indexer);
77
- await waitForNodeState(writer2, writer1.wallet.address, {
78
- wk: writer1.msb.state.writingKey,
79
- isWhitelisted: true,
80
- isWriter: false,
81
- isIndexer: false,
82
- })
83
-
84
- const resultRemoveWriter = await writer2.msb.state.getNodeEntry(writer1.wallet.address); // check if the writer entry was removed successfully in the base
85
-
86
- t.ok(resultRemoveWriter, 'Result should not be null');
87
- t.ok(b4a.equals(resultRemoveWriter.wk, writer1.msb.state.writingKey), 'Result writing key should match writer writing key');
88
- t.is(resultRemoveWriter.isWriter, false, 'Node should not be a writer anymore');
89
- t.is(resultRemoveWriter.isIndexer, false, 'Result should not indicate that the peer is an indexer');
90
- t.is(writer1.msb.state.isWritable(), false, 'peer should not be writable');
91
- });
92
-
93
- test('handleApplyRemoveWriterOperation (apply) - Append removeWriter payload into the base - idempotency', async (t) => {
94
- // writer1 is not a writer.
95
- // writer2 is already a writer -> this writer will lose its writer status
96
- // writer3 is already a writer
97
- // writer4 is already a writer
98
- // indexer is already an indexer.
99
- await sendRemoveWriter(writer2, writer3)
100
- await tryToSyncWriters(admin, writer3, writer4, indexer);
101
- await waitForNodeState(writer3, writer2.wallet.address, {
102
- wk: writer2.msb.state.writingKey,
103
- isWhitelisted: true,
104
- isWriter: false,
105
- isIndexer: false,
106
- });
107
-
108
- const signedLengthAdminBefore = admin.msb.state.getSignedLength();
109
- const signedLengthWriter3Before = writer3.msb.state.getSignedLength();
110
- await sendRemoveWriter(writer2, writer3)
111
- await tryToSyncWriters(admin, writer3, writer4, indexer);
112
- await waitForNodeState(writer3, writer2.wallet.address, {
113
- wk: writer2.msb.state.writingKey,
114
- isWhitelisted: true,
115
- isWriter: false,
116
- isIndexer: false,
117
- });
118
-
119
-
120
- const signedLengthAdminAfter = admin.msb.state.getSignedLength();
121
- const signedLengthWriter3After = writer3.msb.state.getSignedLength();
122
-
123
- t.is(signedLengthAdminBefore, signedLengthAdminAfter, 'Admin signed length should not change');
124
- t.is(signedLengthWriter3Before, signedLengthWriter3After, 'Writer3 signed length should not change');
125
- });
126
-
127
- test('handleApplyRemoveWriterOperation (apply) - Append removeWriter payload into the base - indexer will NOT be removed', async (t) => {
128
- // writer1 is not a writer.
129
- // writer2 is not a writer
130
- // writer3 is already a writer.
131
- // writer4 is already a writer.
132
- // indexer is already an indexer.
133
- await sendRemoveWriter(indexer, admin)
134
- await tryToSyncWriters(admin, writer3, writer4);
135
-
136
- await waitForNodeState(writer3, indexer.wallet.address, {
137
- wk: indexer.msb.state.writingKey,
138
- isWhitelisted: true,
139
- isWriter: false,
140
- isIndexer: false,
141
- })
142
-
143
- await waitForNotIndexer(indexer);
144
- await writer3.msb.state.getNodeEntry(indexer.wallet.address);
145
- const indexersEntry = await writer3.msb.state.getIndexersEntry();
146
-
147
- t.ok(indexersEntry, 'Indexers entry should not be null');
148
- t.ok(indexersEntry.find(({ key }) => b4a.equals(key, indexer.msb.state.writingKey)))
149
- t.is(indexer.msb.state.isWritable(), true, 'Peer should remain writable');
150
- })
151
-
152
- test('handleApplyRemoveWriterOperation (apply) - validator and invoker are the same', async (t) => {
153
- // TODO: Implement when apply tests are fixed
154
- t.pass('Skipping test: Placeholder. To be implemented later.');
155
- });
156
-
157
- hook('Clean up removeWriter setup', async t => {
158
- // close msb instances and remove temp directory
159
- const toClose = []
160
- if (admin?.msb) toClose.push(admin.msb.close());
161
- if (writer1?.msb) toClose.push(writer1.msb.close());
162
- if (writer2?.msb) toClose.push(writer2.msb.close());
163
- if (writer3?.msb) toClose.push(writer3.msb.close());
164
- if (writer4?.msb) toClose.push(writer4.msb.close());
165
- if (indexer?.msb) toClose.push(indexer.msb.close());
166
- await Promise.all(toClose)
167
- if (tmpDirectory) await removeTemporaryDirectory(tmpDirectory);
168
- })
@@ -1,83 +0,0 @@
1
- import b4a from 'b4a';
2
- import { test, hook } from '../../helpers/wrapper.js';
3
- import {
4
- setupMsbAdmin,
5
- initTemporaryDirectory,
6
- randomBytes,
7
- setupMsbWriter,
8
- waitForHash,
9
- removeTemporaryDirectory
10
- } from '../../helpers/setupApplyTests.js';
11
- import {
12
- testKeyPair1,
13
- testKeyPair2,
14
- testKeyPair3,
15
- testKeyPair4
16
- } from '../../fixtures/apply.fixtures.js';
17
- import PartialStateMessageOperations from "../../../src/messages/partialStateMessages/PartialStateMessageOperations.js";
18
- import CompleteStateMessageOperations from '../../../src/messages/completeStateMessages/CompleteStateMessageOperations.js';
19
- import { $TNK } from '../../../src/core/state/utils/balance.js';
20
- import { config } from '../../helpers/config.js';
21
-
22
- const buildTransfer = async (admin, from, to, amount) => {
23
- const txValidity = await from.msb.state.getIndexerSequenceState()
24
- const tx = await new PartialStateMessageOperations(from.wallet, config)
25
- .assembleTransferOperationMessage(to.wallet.address, b4a.toString(amount, 'hex'), b4a.toString(txValidity, 'hex'))
26
- return {
27
- raw: await new CompleteStateMessageOperations(admin.wallet, config)
28
- .assembleCompleteTransferOperationMessage(
29
- tx.address,
30
- b4a.from(tx.tro.tx, 'hex'),
31
- b4a.from(tx.tro.txv, 'hex'),
32
- b4a.from(tx.tro.in, 'hex'),
33
- tx.tro.to,
34
- b4a.from(tx.tro.am, 'hex'),
35
- b4a.from(tx.tro.is, 'hex'),
36
- ),
37
- hash: tx.tro.tx
38
- }
39
- }
40
-
41
- let admin, writer1, writer2, writer3, tmpDirectory;
42
-
43
- hook('Initialize nodes for addWriter tests', async t => {
44
- const randomChannel = randomBytes(32).toString('hex');
45
- const baseOptions = {
46
- enableTxApplyLogs: false,
47
- enableInteractiveMode: false,
48
- enableRoleRequester: false,
49
- channel: randomChannel,
50
- enableValidatorObserver: false
51
- }
52
- tmpDirectory = await initTemporaryDirectory();
53
- admin = await setupMsbAdmin(testKeyPair1, tmpDirectory, baseOptions);
54
- writer1 = await setupMsbWriter(admin, 'writer1', testKeyPair2, tmpDirectory, admin.options)
55
- writer2 = await setupMsbWriter(admin, 'writer2', testKeyPair3, tmpDirectory, admin.options)
56
- writer3 = await setupMsbWriter(admin, 'writer3', testKeyPair4, tmpDirectory, admin.options)
57
- });
58
-
59
- test('handleApplyTransferOperation (apply) - append two transfers', async t => {
60
- const first = await buildTransfer(admin, writer2, writer3, $TNK(1n))
61
- const second = await buildTransfer(admin, writer2, writer3, $TNK(1n))
62
- const raw = [first.raw, second.raw]
63
- await admin.msb.state.base.append(raw)
64
- await Promise.all(
65
- [await waitForHash(writer2, first.hash), await waitForHash(writer2, second.hash)]
66
- );
67
-
68
- const firstResult = await writer2.msb.state.get(first.hash)
69
- const secondResult = await writer2.msb.state.get(second.hash)
70
- t.ok(firstResult, 'First result should not be null');
71
- t.ok(secondResult, 'Second result should not be null');
72
- })
73
-
74
- hook('Clean up handleApplyTransferOperation setup', async t => {
75
- const toClose = []
76
- if (admin?.msb) toClose.push(admin.msb.close());
77
- if (writer1?.msb) toClose.push(writer1.msb.close());
78
- if (writer2?.msb) toClose.push(writer2.msb.close());
79
- if (writer3?.msb) toClose.push(writer3.msb.close());
80
-
81
- await Promise.all(toClose)
82
- if (tmpDirectory) await removeTemporaryDirectory(tmpDirectory);
83
- });
@@ -1,9 +0,0 @@
1
- import { default as test } from 'brittle';
2
-
3
- async function runTests() {
4
- test.pause();
5
- await import('./apply/apply.test.js');
6
- test.resume();
7
- }
8
-
9
- await runTests();
@@ -1,21 +0,0 @@
1
- import test from 'brittle';
2
- import CompleteStateMessageOperations from '../../src/messages/completeStateMessages/CompleteStateMessageOperations.js';
3
- import { OperationType } from '../../src/utils/protobuf/applyOperations.cjs';
4
- import { writingKeyNonAdmin, walletNonAdmin, initAll ,walletAdmin} from '../fixtures/assembleMessage.fixtures.js';
5
- import { messageOperationsBkoTest } from './commonsStateMessageOperationsTest.js';
6
- import { safeDecodeApplyOperation } from '../../src/utils/protobuf/operationHelpers.js';
7
- import { config } from '../../helpers/config.js';
8
-
9
- const testName = 'assembleAddIndexerMessage';
10
- test(testName, async (t) => {
11
- await initAll();
12
- const assembler = async (wallet, address) => {
13
- return safeDecodeApplyOperation(await new CompleteStateMessageOperations(wallet, config).assembleAddIndexerMessage(address));
14
- }
15
-
16
- await messageOperationsBkoTest(t, testName, assembler, walletAdmin, writingKeyNonAdmin, OperationType.ADD_INDEXER, 2, walletNonAdmin.address);
17
-
18
- });
19
-
20
-
21
-
@@ -1,17 +0,0 @@
1
- import test from 'brittle';
2
- import CompleteStateMessageOperations from '../../src/messages/completeStateMessages/CompleteStateMessageOperations.js';
3
- import {OperationType} from '../../src/utils/protobuf/applyOperations.cjs';
4
- import {initAll, walletNonAdmin, writingKeyNonAdmin} from '../fixtures/assembleMessage.fixtures.js';
5
- import {messageOperationsEkoTest} from './commonsStateMessageOperationsTest.js';
6
- import {safeDecodeApplyOperation} from '../../src/utils/protobuf/operationHelpers.js';
7
- import { config } from '../../helpers/config.js'
8
-
9
- const testName = 'assembleAddWriterMessage';
10
- test(testName, async (t) => {
11
- await initAll();
12
- const assembler = async (wallet, writingKey) => {
13
- return safeDecodeApplyOperation(await new CompleteStateMessageOperations(wallet, config).assembleAddWriterMessage(writingKey));
14
- }
15
-
16
- await messageOperationsEkoTest(t, testName, assembler, walletNonAdmin, writingKeyNonAdmin, OperationType.ADD_WRITER, 3, walletNonAdmin.address);
17
- });