trac-msb 0.2.13 → 0.2.15

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 (121) hide show
  1. package/.github/workflows/acceptance-tests.yml +38 -0
  2. package/.github/workflows/lint-pr-title.yml +26 -0
  3. package/.github/workflows/publish.yml +33 -0
  4. package/.github/workflows/unit-tests.yml +34 -0
  5. package/package.json +7 -12
  6. package/proto/network.proto +74 -0
  7. package/rpc/rpc_services.js +4 -22
  8. package/scripts/generate-protobufs.js +12 -37
  9. package/src/config/config.js +9 -26
  10. package/src/config/env.js +17 -27
  11. package/src/core/network/Network.js +36 -73
  12. package/src/core/network/protocols/LegacyProtocol.js +11 -21
  13. package/src/core/network/protocols/NetworkMessages.js +17 -38
  14. package/src/core/network/protocols/ProtocolInterface.js +2 -14
  15. package/src/core/network/protocols/ProtocolSession.js +17 -144
  16. package/src/core/network/protocols/V1Protocol.js +18 -37
  17. package/src/core/network/protocols/legacy/NetworkMessageRouter.js +19 -25
  18. package/src/core/network/protocols/legacy/handlers/{LegacyGetRequestHandler.js → GetRequestHandler.js} +6 -6
  19. package/src/core/network/protocols/legacy/handlers/ResponseHandler.js +37 -0
  20. package/src/core/network/protocols/{legacy/handlers/LegacyRoleOperationHandler.js → shared/handlers/RoleOperationHandler.js} +11 -18
  21. package/src/core/network/protocols/{legacy/handlers/LegacySubnetworkOperationHandler.js → shared/handlers/SubnetworkOperationHandler.js} +17 -28
  22. package/src/core/network/protocols/{legacy/handlers/LegacyTransferOperationHandler.js → shared/handlers/TransferOperationHandler.js} +11 -17
  23. package/src/core/network/protocols/{legacy/handlers/BaseStateOperationHandler.js → shared/handlers/base/BaseOperationHandler.js} +12 -23
  24. package/src/core/network/protocols/shared/validators/{PartialBootstrapDeploymentValidator.js → PartialBootstrapDeployment.js} +4 -9
  25. package/src/core/network/protocols/shared/validators/{PartialRoleAccessValidator.js → PartialRoleAccess.js} +17 -51
  26. package/src/core/network/protocols/shared/validators/{PartialTransactionValidator.js → PartialTransaction.js} +7 -21
  27. package/src/core/network/protocols/shared/validators/{PartialTransferValidator.js → PartialTransfer.js} +9 -26
  28. package/src/core/network/protocols/shared/validators/{PartialOperationValidator.js → base/PartialOperation.js} +25 -47
  29. package/src/core/network/protocols/v1/NetworkMessageRouter.js +7 -91
  30. package/src/core/network/services/ConnectionManager.js +94 -146
  31. package/src/core/network/services/MessageOrchestrator.js +27 -151
  32. package/src/core/network/services/TransactionPoolService.js +18 -129
  33. package/src/core/network/services/TransactionRateLimiterService.js +34 -52
  34. package/src/core/network/services/ValidatorObserverService.js +26 -18
  35. package/src/core/state/State.js +19 -70
  36. package/src/index.js +8 -6
  37. package/src/messages/network/v1/NetworkMessageBuilder.js +79 -59
  38. package/src/messages/network/v1/NetworkMessageDirector.js +50 -16
  39. package/src/utils/Scheduler.js +8 -0
  40. package/src/utils/constants.js +5 -71
  41. package/src/utils/helpers.js +1 -10
  42. package/src/utils/normalizers.js +0 -38
  43. package/src/utils/protobuf/network.cjs +840 -0
  44. package/src/utils/protobuf/operationHelpers.js +3 -24
  45. package/tests/acceptance/v1/account/account.test.mjs +2 -8
  46. package/tests/acceptance/v1/tx/tx.test.mjs +1 -23
  47. package/tests/acceptance/v1/tx-details/tx-details.test.mjs +6 -34
  48. package/tests/fixtures/assembleMessage.fixtures.js +8 -7
  49. package/tests/fixtures/networkV1.fixtures.js +28 -2
  50. package/tests/helpers/autobaseTestHelpers.js +5 -2
  51. package/tests/helpers/createTestSignature.js +3 -2
  52. package/tests/helpers/transactionPayloads.mjs +2 -2
  53. package/tests/unit/messages/network/NetworkMessageBuilder.test.js +79 -239
  54. package/tests/unit/messages/network/NetworkMessageDirector.test.js +77 -223
  55. package/tests/unit/messages/state/applyStateMessageBuilder.complete.test.js +5 -1
  56. package/tests/unit/messages/state/applyStateMessageBuilder.partial.test.js +5 -1
  57. package/tests/unit/network/ConnectionManager.test.js +191 -0
  58. package/tests/unit/network/networkModule.test.js +1 -4
  59. package/tests/unit/unit.test.js +2 -2
  60. package/tests/unit/utils/fileUtils/readAddressesFromWhitelistFile.test.js +2 -2
  61. package/tests/unit/utils/fileUtils/readBalanceMigrationFile.test.js +2 -2
  62. package/tests/unit/utils/protobuf/operationHelpers.test.js +4 -2
  63. package/tests/unit/utils/utils.test.js +0 -1
  64. package/proto/network/v1/enums/message_type.proto +0 -16
  65. package/proto/network/v1/enums/result_code.proto +0 -84
  66. package/proto/network/v1/messages/broadcast_transaction_request.proto +0 -9
  67. package/proto/network/v1/messages/broadcast_transaction_response.proto +0 -13
  68. package/proto/network/v1/messages/liveness_request.proto +0 -8
  69. package/proto/network/v1/messages/liveness_response.proto +0 -11
  70. package/proto/network/v1/network_message.proto +0 -22
  71. package/src/core/network/protocols/connectionPolicies.js +0 -88
  72. package/src/core/network/protocols/legacy/handlers/LegacyResponseHandler.js +0 -23
  73. package/src/core/network/protocols/shared/errors/SharedValidatorRejectionError.js +0 -27
  74. package/src/core/network/protocols/v1/V1ProtocolError.js +0 -91
  75. package/src/core/network/protocols/v1/handlers/V1BaseOperationHandler.js +0 -65
  76. package/src/core/network/protocols/v1/handlers/V1BroadcastTransactionOperationHandler.js +0 -389
  77. package/src/core/network/protocols/v1/handlers/V1LivenessOperationHandler.js +0 -87
  78. package/src/core/network/protocols/v1/validators/V1BaseOperation.js +0 -211
  79. package/src/core/network/protocols/v1/validators/V1BroadcastTransactionRequest.js +0 -26
  80. package/src/core/network/protocols/v1/validators/V1BroadcastTransactionResponse.js +0 -276
  81. package/src/core/network/protocols/v1/validators/V1LivenessRequest.js +0 -15
  82. package/src/core/network/protocols/v1/validators/V1LivenessResponse.js +0 -17
  83. package/src/core/network/protocols/v1/validators/V1ValidationSchema.js +0 -210
  84. package/src/core/network/services/PendingRequestService.js +0 -172
  85. package/src/core/network/services/TransactionCommitService.js +0 -149
  86. package/src/core/network/services/ValidatorHealthCheckService.js +0 -127
  87. package/src/utils/deepEqualApplyPayload.js +0 -40
  88. package/src/utils/logger.js +0 -25
  89. package/src/utils/protobuf/networkV1.generated.cjs +0 -2460
  90. package/tests/unit/network/LegacyNetworkMessageRouter.test.js +0 -54
  91. package/tests/unit/network/ProtocolSession.test.js +0 -127
  92. package/tests/unit/network/services/ConnectionManager.test.js +0 -450
  93. package/tests/unit/network/services/MessageOrchestrator.test.js +0 -445
  94. package/tests/unit/network/services/PendingRequestService.test.js +0 -431
  95. package/tests/unit/network/services/TransactionCommitService.test.js +0 -246
  96. package/tests/unit/network/services/TransactionPoolService.test.js +0 -489
  97. package/tests/unit/network/services/TransactionRateLimiterService.test.js +0 -139
  98. package/tests/unit/network/services/ValidatorHealthCheckService.test.js +0 -115
  99. package/tests/unit/network/services/services.test.js +0 -17
  100. package/tests/unit/network/utils/v1TestUtils.js +0 -153
  101. package/tests/unit/network/v1/NetworkMessageRouterV1.test.js +0 -151
  102. package/tests/unit/network/v1/V1BaseOperation.test.js +0 -356
  103. package/tests/unit/network/v1/V1BroadcastTransactionOperationHandler.test.js +0 -129
  104. package/tests/unit/network/v1/V1BroadcastTransactionRequest.test.js +0 -53
  105. package/tests/unit/network/v1/V1BroadcastTransactionResponse.test.js +0 -512
  106. package/tests/unit/network/v1/V1LivenessRequest.test.js +0 -32
  107. package/tests/unit/network/v1/V1LivenessResponse.test.js +0 -45
  108. package/tests/unit/network/v1/V1ResultCode.test.js +0 -84
  109. package/tests/unit/network/v1/V1ValidationSchema.test.js +0 -13
  110. package/tests/unit/network/v1/connectionPolicies.test.js +0 -49
  111. package/tests/unit/network/v1/handlers/V1BaseOperationHandler.test.js +0 -284
  112. package/tests/unit/network/v1/handlers/V1BroadcastTransactionOperationHandler.test.js +0 -794
  113. package/tests/unit/network/v1/handlers/V1LivenessOperationHandler.test.js +0 -193
  114. package/tests/unit/network/v1/v1.handlers.test.js +0 -15
  115. package/tests/unit/network/v1/v1.test.js +0 -19
  116. package/tests/unit/network/v1/v1ValidationSchema/broadcastTransactionRequest.test.js +0 -119
  117. package/tests/unit/network/v1/v1ValidationSchema/broadcastTransactionResponse.test.js +0 -136
  118. package/tests/unit/network/v1/v1ValidationSchema/common.test.js +0 -308
  119. package/tests/unit/network/v1/v1ValidationSchema/livenessRequest.test.js +0 -90
  120. package/tests/unit/network/v1/v1ValidationSchema/livenessResponse.test.js +0 -133
  121. package/tests/unit/utils/deepEqualApplyPayload/deepEqualApplyPayload.test.js +0 -102
@@ -1,49 +0,0 @@
1
- import { test } from 'brittle';
2
-
3
- import { resultToValidatorAction, SENDER_ACTION } from '../../../../src/core/network/protocols/connectionPolicies.js';
4
- import { ResultCode } from '../../../../src/utils/constants.js';
5
-
6
- test('connectionPolicies maps OK to SUCCESS', t => {
7
- t.is(
8
- resultToValidatorAction(ResultCode.OK),
9
- SENDER_ACTION.SUCCESS
10
- );
11
- });
12
-
13
- test('connectionPolicies maps TX_ALREADY_PENDING to NO_ROTATE', t => {
14
- t.is(
15
- resultToValidatorAction(ResultCode.TX_ALREADY_PENDING),
16
- SENDER_ACTION.NO_ROTATE
17
- );
18
- });
19
-
20
- test('connectionPolicies maps TX_COMMITTED_RECEIPT_MISSING to ROTATE', t => {
21
- t.is(
22
- resultToValidatorAction(ResultCode.TX_COMMITTED_RECEIPT_MISSING),
23
- SENDER_ACTION.ROTATE
24
- );
25
- });
26
-
27
- test('connectionPolicies maps unknown result code to UNDEFINED', t => {
28
- t.is(
29
- resultToValidatorAction(999999),
30
- SENDER_ACTION.UNDEFINED
31
- );
32
- });
33
-
34
- test('connectionPolicies maps every ResultCode constant to a concrete sender action', t => {
35
- const unassigned = [];
36
-
37
- for (const [name, code] of Object.entries(ResultCode)) {
38
- const action = resultToValidatorAction(code);
39
- if (action === SENDER_ACTION.UNDEFINED) {
40
- unassigned.push(`${name}(${code})`);
41
- }
42
- }
43
-
44
- t.alike(
45
- unassigned,
46
- [],
47
- `Unassigned ResultCode entries in policy: ${unassigned.join(', ')}`
48
- );
49
- });
@@ -1,284 +0,0 @@
1
- import test from 'brittle';
2
- import V1BaseOperationHandler from '../../../../../src/core/network/protocols/v1/handlers/V1BaseOperationHandler.js';
3
- import {V1ProtocolError, V1UnexpectedError} from '../../../../../src/core/network/protocols/v1/V1ProtocolError.js';
4
-
5
- class MockRateLimiter {
6
- constructor() { this.called = false; }
7
- v1HandleRateLimit(conn) {
8
- this.called = true;
9
- this.conn = conn;
10
- }
11
- }
12
-
13
- class MockPendingReqService {
14
- constructor() {
15
- this.entries = {};
16
- this.stopped = [];
17
- this.resolved = [];
18
- this.rejected = [];
19
- this.shouldReject = true;
20
- }
21
- getPendingRequest(id) { return this.entries[id]; }
22
- stopPendingRequestTimeout(id) { this.stopped.push(id); }
23
- resolvePendingRequest(id, code) { this.resolved.push({ id, code }); }
24
- rejectPendingRequest(id, err) {
25
- if (this.shouldReject) this.rejected.push({ id, err });
26
- return this.shouldReject;
27
- }
28
- }
29
-
30
- const mockConfig = { disableRateLimit: false };
31
-
32
- test('constructor: stores provided config -> config getter returns same reference', async (t) => {
33
- const handler = new V1BaseOperationHandler(null, null, mockConfig);
34
- t.is(handler.config, mockConfig, 'Should return the config passed in the constructor');
35
- });
36
-
37
- test('applyRateLimit: rate limit enabled -> calls rate limiter with connection', async (t) => {
38
- const rateLimiter = new MockRateLimiter();
39
- const handler = new V1BaseOperationHandler(rateLimiter, null, mockConfig);
40
- const conn = { id: 1 };
41
-
42
- handler.applyRateLimit(conn);
43
-
44
- t.ok(rateLimiter.called, 'Should call the rate limiter when enabled');
45
- t.is(rateLimiter.conn, conn, 'Should pass the connection to the rate limiter');
46
- });
47
-
48
- test('applyRateLimit: disableRateLimit=true -> skips rate limiter call', async (t) => {
49
- const rateLimiter = new MockRateLimiter();
50
- const handler = new V1BaseOperationHandler(rateLimiter, null, { disableRateLimit: true });
51
-
52
- handler.applyRateLimit({});
53
-
54
- t.absent(rateLimiter.called, 'Should NOT call the rate limiter when disableRateLimit is true');
55
- });
56
-
57
- test('resolvePendingResponse: pending request missing -> returns false', async (t) => {
58
- const pendingReq = new MockPendingReqService();
59
- const handler = new V1BaseOperationHandler(null, pendingReq, mockConfig);
60
-
61
- const result = await handler.resolvePendingResponse({ id: 'msg-123' }, {}, {}, () => {}, {});
62
-
63
- t.is(result, false, 'Should return false if the pending request does not exist');
64
- });
65
-
66
- test('resolvePendingResponse: valid pending response -> stops timeout and resolves request', async (t) => {
67
- const pendingReq = new MockPendingReqService();
68
- pendingReq.entries['msg-123'] = { id: 'msg-123' };
69
-
70
- const handler = new V1BaseOperationHandler(null, pendingReq, mockConfig);
71
-
72
- let validated = false;
73
- const validatorMock = { async validate() { validated = true; } };
74
- const extractCodeMock = () => 'SUCCESS';
75
-
76
- const result = await handler.resolvePendingResponse(
77
- { id: 'msg-123' },
78
- {},
79
- validatorMock,
80
- extractCodeMock,
81
- {}
82
- );
83
-
84
- t.is(result, true, 'Should return true after resolving the request');
85
- t.is(pendingReq.stopped[0], 'msg-123', 'Should stop the timeout');
86
- t.ok(validated, 'Should call validation');
87
- t.is(pendingReq.resolved[0].code, 'SUCCESS', 'Should extract resultCode and resolve');
88
- });
89
-
90
- test('resolvePendingResponse: validator throws -> propagates validation error', async (t) => {
91
- const pendingReq = new MockPendingReqService();
92
- pendingReq.entries['msg-123'] = { id: 'msg-123' };
93
-
94
- const handler = new V1BaseOperationHandler(null, pendingReq, mockConfig);
95
-
96
- const validatorMock = {
97
- async validate() { throw new Error('Validation Failed'); }
98
- };
99
-
100
- await t.exception(async () => {
101
- await handler.resolvePendingResponse(
102
- { id: 'msg-123' },
103
- {},
104
- validatorMock,
105
- () => {},
106
- {}
107
- );
108
- }, /Validation Failed/, 'Should propagate the validation error');
109
- });
110
-
111
- test('handlePendingResponseError: request already rejected -> does not close connection', async (t) => {
112
- const pendingReq = new MockPendingReqService();
113
- pendingReq.shouldReject = false;
114
-
115
- const handler = new V1BaseOperationHandler(null, pendingReq, mockConfig);
116
-
117
- let ended = false;
118
- const connMock = { end: () => { ended = true; } };
119
-
120
- handler.handlePendingResponseError('msg-123', connMock, new Error('test'), 'step');
121
-
122
- t.absent(ended, 'Should NOT end the connection if the request was already rejected');
123
- });
124
-
125
- test('handlePendingResponseError: unknown native error -> maps to V1UnexpectedError', async (t) => {
126
- const pendingReq = new MockPendingReqService();
127
- const handler = new V1BaseOperationHandler(null, pendingReq, mockConfig);
128
-
129
- // Bypass display logic for isolation
130
- handler.displayError = () => {};
131
-
132
- let ended = false;
133
- const connMock = {
134
- end: () => { ended = true; },
135
- remotePublicKey: Buffer.alloc(32)
136
- };
137
-
138
- handler.handlePendingResponseError(
139
- 'msg-123',
140
- connMock,
141
- new Error('Random native error'),
142
- 'test-step'
143
- );
144
-
145
- t.is(pendingReq.rejected.length, 1, 'Should reject the pending request');
146
-
147
- const capturedError = pendingReq.rejected[0].err;
148
-
149
- t.ok(capturedError instanceof V1UnexpectedError, 'Should map to V1UnexpectedError');
150
- t.is(capturedError.message, 'Random native error', 'Should preserve original message');
151
- t.absent(ended, 'V1UnexpectedError should not close the connection by default');
152
- });
153
-
154
- test('handlePendingResponseError: protocol error with endConnection=true -> does not close connection directly', async (t) => {
155
- const pendingReq = new MockPendingReqService();
156
- const handler = new V1BaseOperationHandler(null, pendingReq, mockConfig);
157
-
158
- handler.displayError = () => {};
159
-
160
- let ended = false;
161
- const connMock = {
162
- end: () => { ended = true; },
163
- remotePublicKey: Buffer.alloc(32)
164
- };
165
-
166
- const protocolError = new V1ProtocolError(999, 'FATAL_ERROR', true);
167
-
168
- handler.handlePendingResponseError(
169
- 'msg-123',
170
- connMock,
171
- protocolError,
172
- 'test-step'
173
- );
174
-
175
- t.is(
176
- pendingReq.rejected[0].err,
177
- protocolError,
178
- 'Should pass protocol error without wrapping'
179
- );
180
-
181
- t.absent(ended, 'Connection closing is delegated to ConnectionManager');
182
- });
183
-
184
- test('handlePendingResponseError: delegates logging -> calls displayError', async (t) => {
185
- const pendingReq = new MockPendingReqService();
186
- const handler = new V1BaseOperationHandler(null, pendingReq, { hrp: 'trac' });
187
-
188
- let called = false;
189
- handler.displayError = () => { called = true; };
190
-
191
- handler.handlePendingResponseError(
192
- 'msg-1',
193
- { end() {}, remotePublicKey: Buffer.alloc(32) },
194
- new Error('boom'),
195
- 'step'
196
- );
197
-
198
- t.ok(called);
199
- });
200
-
201
- test('handlePendingResponseError: protocol-shaped error -> keeps original error instance', async (t) => {
202
- const pendingReq = new MockPendingReqService();
203
- const handler = new V1BaseOperationHandler(null, pendingReq, mockConfig);
204
-
205
- const protocolError = new V1ProtocolError(123, 'protocol-shaped', false);
206
-
207
- handler.displayError = () => {};
208
-
209
- handler.handlePendingResponseError(
210
- 'msg-1',
211
- { end() {}, remotePublicKey: Buffer.alloc(32) },
212
- protocolError,
213
- 'step'
214
- );
215
-
216
- t.is(
217
- pendingReq.rejected[0].err,
218
- protocolError,
219
- 'Should not wrap protocol error'
220
- );
221
- });
222
-
223
- test('handlePendingResponseError: undefined error -> uses Unexpected error fallback', async (t) => {
224
- const pendingReq = new MockPendingReqService();
225
- const handler = new V1BaseOperationHandler(null, pendingReq, mockConfig);
226
-
227
- handler.displayError = () => {};
228
-
229
- handler.handlePendingResponseError(
230
- 'msg-123',
231
- { end() {}, remotePublicKey: Buffer.alloc(32) },
232
- undefined,
233
- 'step'
234
- );
235
-
236
- const captured = pendingReq.rejected[0].err;
237
-
238
- t.ok(captured instanceof V1UnexpectedError);
239
- t.is(captured.message, 'Unexpected error');
240
- });
241
-
242
- test('displayError: real implementation with invalid config -> throws', async (t) => {
243
- const pendingReq = new MockPendingReqService();
244
-
245
- const handler = new V1BaseOperationHandler(
246
- null,
247
- pendingReq,
248
- {} // intentionally invalid config
249
- );
250
-
251
- const originalConsoleError = console.error;
252
- console.error = () => {};
253
-
254
- await t.exception(() => {
255
- handler.displayError(
256
- 'step',
257
- Buffer.alloc(33, 1),
258
- new Error('boom')
259
- );
260
- });
261
-
262
- console.error = originalConsoleError;
263
-
264
- t.pass();
265
- });
266
-
267
- test('handlePendingResponseError: primitive error value -> uses Unexpected error fallback', async (t) => {
268
- const pendingReq = new MockPendingReqService();
269
- const handler = new V1BaseOperationHandler(null, pendingReq, mockConfig);
270
-
271
- handler.displayError = () => {};
272
-
273
- handler.handlePendingResponseError(
274
- 'msg-123',
275
- { end() {}, remotePublicKey: Buffer.alloc(32) },
276
- 'string error',
277
- 'step'
278
- );
279
-
280
- const captured = pendingReq.rejected[0].err;
281
-
282
- t.ok(captured instanceof V1UnexpectedError);
283
- t.is(captured.message, 'Unexpected error');
284
- });