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,20 +1,18 @@
1
1
  import Protomux from 'protomux';
2
2
  import ProtocolInterface from './ProtocolInterface.js';
3
+ import b4a from 'b4a';
3
4
  import c from 'compact-encoding';
4
- import {encodeV1networkOperation, decodeV1networkOperation} from '../../../utils/protobuf/operationHelpers.js';
5
5
 
6
6
  class V1Protocol extends ProtocolInterface {
7
7
  #channel;
8
8
  #session;
9
+ #config;
9
10
  #router;
10
- #publicKeyHex;
11
- #pendingRequestService;
12
11
 
13
- constructor(router, connection, pendingRequestService, config) {
14
- super(router, connection, pendingRequestService, config);
12
+ constructor(router, connection, config) {
13
+ super(router, connection, config);
14
+ this.#config = config;
15
15
  this.#router = router;
16
- this.#publicKeyHex = connection.remotePublicKey.toString('hex');
17
- this.#pendingRequestService = pendingRequestService;
18
16
  this.init(connection);
19
17
  }
20
18
 
@@ -32,47 +30,30 @@ class V1Protocol extends ProtocolInterface {
32
30
 
33
31
  this.#channel = mux.createChannel({
34
32
  protocol: 'network/v1',
35
- onopen() {
36
- },
37
- onclose() {
38
- }
33
+ onopen() { },
34
+ onclose() { }
39
35
  });
40
36
 
41
37
  this.#channel.open();
42
38
 
43
39
  this.#session = this.#channel.addMessage({
44
40
  encoding: c.raw,
45
- onmessage: (incomingMessage) => {
46
- this.#router.route(incomingMessage, connection).catch((err) => {
47
- console.error(`V1Protocol: unhandled router error: ${err.message}`);
48
- try {
49
- connection.end();
50
- } catch {
41
+ onmessage: async (incomingMessage) => {
42
+ try {
43
+ if (b4a.isBuffer(incomingMessage)) {
44
+ await this.#router.route(incomingMessage, connection, this.#session);
45
+ } else {
46
+ throw new Error('NetworkMessages: v1 message must be a buffer');
51
47
  }
52
- });
48
+ } catch (error) {
49
+ console.error(`NetworkMessages: Failed to handle incoming v1 message: ${error.message}`);
50
+ }
53
51
  }
54
52
  });
55
53
  }
56
54
 
57
- // TODO: Consider making this method private/internal-only, just like 'encode'
58
- // NOTE: This method might be moved to v1/NetworkMessageRouter.js as it is only used there
59
- decode(message) {
60
- return decodeV1networkOperation(message);
61
- }
62
-
63
- async send(message) {
64
- const encodedMessage = encodeV1networkOperation(message);
65
- const msgReplyPromise = this.#pendingRequestService.registerPendingRequest(this.#publicKeyHex, message);
66
- try {
67
- this.#session.send(encodedMessage);
68
- } catch (error) {
69
- this.#pendingRequestService.rejectPendingRequest(message.id, error);
70
- }
71
- return msgReplyPromise;
72
- }
73
-
74
- sendAndForget(message) {
75
- this.#session.send(encodeV1networkOperation(message));
55
+ send(message) {
56
+ this.#session.send(message);
76
57
  }
77
58
 
78
59
  close() {
@@ -1,12 +1,13 @@
1
1
  import b4a from "b4a";
2
- import _ from 'lodash';
3
- import LegacyGetRequestHandler from "./handlers/LegacyGetRequestHandler.js";
4
- import LegacyResponseHandler from "./handlers/LegacyResponseHandler.js";
5
- import LegacyRoleOperationHandler from "./handlers/LegacyRoleOperationHandler.js";
6
- import LegacySubnetworkOperationHandler from "./handlers/LegacySubnetworkOperationHandler.js";
7
- import LegacyTransferOperationHandler from "./handlers/LegacyTransferOperationHandler.js";
2
+ import GetRequestHandler from "./handlers/GetRequestHandler.js";
3
+ import ResponseHandler from "./handlers/ResponseHandler.js";
4
+ import RoleOperationHandler from "../shared/handlers/RoleOperationHandler.js";
5
+ import SubnetworkOperationHandler from "../shared/handlers/SubnetworkOperationHandler.js";
6
+ import TransferOperationHandler from "../shared/handlers/TransferOperationHandler.js";
8
7
  import { NETWORK_MESSAGE_TYPES } from '../../../../utils/constants.js';
9
8
  import * as operation from '../../../../utils/applyOperations.js';
9
+ import State from "../../../state/State.js";
10
+ import PeerWallet from "trac-wallet";
10
11
 
11
12
  class NetworkMessageRouter {
12
13
  #handlers;
@@ -17,32 +18,29 @@ class NetworkMessageRouter {
17
18
  * @param {PeerWallet} wallet
18
19
  * @param {TransactionRateLimiterService} rateLimiterService
19
20
  * @param {TransactionPoolService} txPoolService
21
+ * @param {ConnectionManager} connectionManager
20
22
  * @param {Config} config
21
23
  **/
22
- constructor(state, wallet, rateLimiterService, txPoolService, config) {
24
+ constructor(state, wallet, rateLimiterService, txPoolService, connectionManager, config) {
23
25
  this.#config = config;
24
26
 
25
27
  this.#handlers = {
26
- get: new LegacyGetRequestHandler(wallet, state),
27
- response: new LegacyResponseHandler(state, wallet, this.#config),
28
- roleTransaction: new LegacyRoleOperationHandler(state, wallet, rateLimiterService, txPoolService, this.#config),
29
- subNetworkTransaction: new LegacySubnetworkOperationHandler(state, wallet, rateLimiterService, txPoolService, this.#config),
30
- tracNetworkTransaction: new LegacyTransferOperationHandler(state, wallet, rateLimiterService, txPoolService, this.#config),
31
-
28
+ get: new GetRequestHandler(wallet, state),
29
+ response: new ResponseHandler(state, wallet, connectionManager, this.#config),
30
+ roleTransaction: new RoleOperationHandler(state, wallet, rateLimiterService, txPoolService, this.#config),
31
+ subNetworkTransaction: new SubnetworkOperationHandler(state, wallet, rateLimiterService, txPoolService, this.#config),
32
+ tracNetworkTransaction: new TransferOperationHandler(state, wallet, rateLimiterService, txPoolService, this.#config),
32
33
  }
33
34
  }
34
35
 
35
- async route(incomingMessage, connection) {
36
- this.#preValidate(incomingMessage);
36
+ // NOTE: messageProtomux can be deleted, ad this is a session, and we can extract this from connection
37
+ async route(incomingMessage, connection, messageProtomux) {
37
38
  const channelString = b4a.toString(this.#config.channel, 'utf8');
38
-
39
- // We received a legacy message, so we set the connection protocol accordingly
40
- connection.protocolSession.setLegacyAsPreferredProtocol();
41
39
  if (this.#isGetRequest(incomingMessage)) {
42
- await this.#handlers.get.handle(incomingMessage, connection, channelString);
40
+ await this.#handlers.get.handle(incomingMessage, messageProtomux, connection, channelString);
43
41
  }
44
42
  else if (this.#isResponse(incomingMessage)) {
45
- await this.#handlers.response.handle(incomingMessage, channelString);
43
+ await this.#handlers.response.handle(incomingMessage, connection, channelString);
46
44
  }
47
45
  else if (this.#isRoleAccessOperation(incomingMessage)) {
48
46
  await this.#handlers.roleTransaction.handle(incomingMessage, connection);
@@ -56,18 +54,14 @@ class NetworkMessageRouter {
56
54
  else {
57
55
  throw new Error(`Failed to route message. Pubkey of requester is ${connection.remotePublicKey ? b4a.toString(connection.remotePublicKey, 'hex') : 'unknown'}`);
58
56
  }
59
- }
60
57
 
61
- #preValidate(message) {
62
- if (!_.isPlainObject(message) && typeof message !== 'string') {
63
- throw new Error('Invalid message format: expected object or string.');
64
- }
65
58
  }
66
59
 
67
60
  #isGetRequest(message) {
68
61
  return Object.values(NETWORK_MESSAGE_TYPES.GET).includes(message);
69
62
  }
70
63
 
64
+
71
65
  #isResponse(message) {
72
66
  return Object.values(NETWORK_MESSAGE_TYPES.RESPONSE).includes(message.op);
73
67
  }
@@ -2,7 +2,7 @@ import { NETWORK_MESSAGE_TYPES } from '../../../../../utils/constants.js';
2
2
  import PeerWallet from 'trac-wallet';
3
3
  import b4a from 'b4a';
4
4
 
5
- class LegacyGetRequestHandler {
5
+ class GetRequestHandler {
6
6
  #wallet;
7
7
  #state;
8
8
 
@@ -15,17 +15,17 @@ class LegacyGetRequestHandler {
15
15
  return this.#state;
16
16
  }
17
17
 
18
- async handle(message, connection, channelString) {
18
+ async handle(message, messageProtomux, connection, channelString) {
19
19
  switch (message) {
20
20
  case NETWORK_MESSAGE_TYPES.GET.VALIDATOR:
21
- await this.handleGetValidatorResponse(connection, channelString);
21
+ await this.handleGetValidatorResponse(messageProtomux, connection, channelString);
22
22
  break;
23
23
  default:
24
24
  throw new Error(`Unhandled GET type: ${message}`);
25
25
  }
26
26
  }
27
27
 
28
- async handleGetValidatorResponse(connection, channelString) {
28
+ async handleGetValidatorResponse(messageProtomux, connection, channelString) {
29
29
  const nonce = PeerWallet.generateNonce().toString('hex');
30
30
  const payload = {
31
31
  op: 'validatorResponse',
@@ -46,8 +46,8 @@ class LegacyGetRequestHandler {
46
46
  ...payload,
47
47
  sig: sig.toString('hex'),
48
48
  };
49
- connection.protocolSession.sendAndForget(responseMessage)
49
+ messageProtomux.send(responseMessage);
50
50
  }
51
51
  }
52
52
 
53
- export default LegacyGetRequestHandler;
53
+ export default GetRequestHandler;
@@ -0,0 +1,37 @@
1
+ import ValidatorResponse from '../validators/ValidatorResponse.js';
2
+ import PeerWallet from 'trac-wallet';
3
+
4
+ class ResponseHandler {
5
+ #responseValidator;
6
+ #connectionManager;
7
+
8
+
9
+ constructor(state, wallet, connectionManager ,config) {
10
+ this.#responseValidator = new ValidatorResponse(state, wallet, config);
11
+ this.#connectionManager = connectionManager;
12
+
13
+ }
14
+
15
+ async handle(message, connection, channelString) {
16
+ await this.#handleValidatorResponse(message, connection, channelString);
17
+ }
18
+
19
+ async #handleValidatorResponse(message, connection, channelString) {
20
+ const isValid = await this.#responseValidator.validate(message, channelString);
21
+ if (isValid) {
22
+ const validatorAddressString = message.address;
23
+ const validatorPublicKey = PeerWallet.decodeBech32m(validatorAddressString);
24
+
25
+ if (this.#connectionManager.connected(validatorPublicKey)) {
26
+ return;
27
+ // TODO: What we should return? Or maybe we should throw?
28
+ }
29
+
30
+ this.#connectionManager.addValidator(validatorPublicKey, connection)
31
+ } else {
32
+ throw new Error("Validator response verification failed");
33
+ }
34
+ }
35
+ }
36
+
37
+ export default ResponseHandler;
@@ -1,16 +1,15 @@
1
1
  import {OperationType} from '../../../../../utils/constants.js';
2
- import PartialRoleAccessValidator from "../../shared/validators/PartialRoleAccessValidator.js";
3
- import BaseStateOperationHandler from './BaseStateOperationHandler.js';
2
+ import PartialRoleAccess from "../validators/PartialRoleAccess.js";
3
+ import BaseOperationHandler from './base/BaseOperationHandler.js';
4
4
  import {applyStateMessageFactory} from "../../../../../messages/state/applyStateMessageFactory.js";
5
5
  import {safeEncodeApplyOperation} from "../../../../../utils/protobuf/operationHelpers.js";
6
6
  import {normalizeRoleAccessOperation} from "../../../../../utils/normalizers.js";
7
- import { publicKeyToAddress } from "../../../../../utils/helpers.js"
8
- import b4a from "b4a";
9
7
 
10
- class LegacyRoleOperationHandler extends BaseStateOperationHandler {
8
+ class RoleOperationHandler extends BaseOperationHandler {
11
9
  #partialRoleAccessValidator;
12
10
  #wallet;
13
11
  #config;
12
+ #txPoolService;
14
13
 
15
14
  /**
16
15
  * @param {State} state
@@ -23,7 +22,8 @@ class LegacyRoleOperationHandler extends BaseStateOperationHandler {
23
22
  super(state, wallet, rateLimiter, txPoolService, config);
24
23
  this.#wallet = wallet;
25
24
  this.#config = config;
26
- this.#partialRoleAccessValidator = new PartialRoleAccessValidator(state, this.#wallet.address ,this.#config)
25
+ this.#partialRoleAccessValidator = new PartialRoleAccess(state, this.#wallet.address ,this.#config)
26
+ this.#txPoolService = txPoolService;
27
27
  }
28
28
 
29
29
  get partialRoleAccessValidator() {
@@ -35,8 +35,7 @@ class LegacyRoleOperationHandler extends BaseStateOperationHandler {
35
35
  const isValid = await this.partialRoleAccessValidator.validate(normalizedPartialRoleAccessPayload)
36
36
  let completePayload = null
37
37
  if (!isValid) {
38
- throw new Error(
39
- `OperationHandler: partial role access payload validation failed. Requested by ${publicKeyToAddress(connection.remotePublicKey, this.#config)}`);
38
+ throw new Error("OperationHandler: partial role access payload validation failed.");
40
39
  }
41
40
 
42
41
  switch (normalizedPartialRoleAccessPayload.type) {
@@ -75,21 +74,15 @@ class LegacyRoleOperationHandler extends BaseStateOperationHandler {
75
74
  )
76
75
  break;
77
76
  default:
78
- throw new Error(
79
- `OperationHandler: Assembling complete role access operation failed due to unsupported operation type. Requested by ${publicKeyToAddress(connection.remotePublicKey, this.#config)}`
80
- );
77
+ throw new Error("OperationHandler: Assembling complete role access operation failed due to unsupported operation type.");
81
78
  }
82
79
 
83
80
  if (!completePayload) {
84
- throw new Error(
85
- `OperationHandler: Assembling complete role access operation failed. Requested by ${publicKeyToAddress(connection.remotePublicKey, this.#config)}`
86
- );
81
+ throw new Error("OperationHandler: Assembling complete role access operation failed.");
87
82
  }
88
83
 
89
- const encodedOperation = safeEncodeApplyOperation(completePayload);
90
- const txHash = b4a.toString(completePayload.rao.tx, 'hex');
91
- this.enqueueTransaction(txHash, encodedOperation);
84
+ this.#txPoolService.addTransaction(safeEncodeApplyOperation(completePayload))
92
85
  }
93
86
  }
94
87
 
95
- export default LegacyRoleOperationHandler;
88
+ export default RoleOperationHandler;
@@ -1,24 +1,23 @@
1
- import BaseStateOperationHandler from './BaseStateOperationHandler.js';
1
+ import BaseOperationHandler from './base/BaseOperationHandler.js';
2
2
  import {
3
3
  OperationType
4
4
  } from '../../../../../utils/constants.js';
5
- import PartialBootstrapDeploymentValidator from "../../shared/validators/PartialBootstrapDeploymentValidator.js";
6
- import PartialTransactionValidator from "../../shared/validators/PartialTransactionValidator.js";
5
+ import PartialBootstrapDeployment from "../validators/PartialBootstrapDeployment.js";
6
+ import PartialTransaction from "../validators/PartialTransaction.js";
7
7
  import {applyStateMessageFactory} from "../../../../../messages/state/applyStateMessageFactory.js";
8
8
  import {safeEncodeApplyOperation} from "../../../../../utils/protobuf/operationHelpers.js";
9
9
  import {
10
10
  normalizeBootstrapDeploymentOperation,
11
11
  normalizeTransactionOperation
12
12
  } from "../../../../../utils/normalizers.js";
13
- import b4a from "b4a";
14
- import {publicKeyToAddress} from "../../../../../utils/helpers.js";
15
13
 
16
14
 
17
- class LegacySubnetworkOperationHandler extends BaseStateOperationHandler {
15
+ class SubnetworkOperationHandler extends BaseOperationHandler {
18
16
  #partialBootstrapDeploymentValidator;
19
17
  #partialTransactionValidator;
20
18
  #config;
21
19
  #wallet;
20
+ #txPoolService;
22
21
 
23
22
  /**
24
23
  * @param {State} state
@@ -27,23 +26,22 @@ class LegacySubnetworkOperationHandler extends BaseStateOperationHandler {
27
26
  * @param {TransactionPoolService} txPoolService
28
27
  * @param {Config} config
29
28
  **/
30
- constructor(state, wallet, rateLimiter, txPoolService, config) {
29
+ constructor( state, wallet, rateLimiter, txPoolService, config) {
31
30
  super(state, wallet, rateLimiter, txPoolService, config);
32
31
  this.#config = config;
33
32
  this.#wallet = wallet
34
- this.#partialBootstrapDeploymentValidator = new PartialBootstrapDeploymentValidator(state, this.#wallet.address, config);
35
- this.#partialTransactionValidator = new PartialTransactionValidator(state, this.#wallet.address, config);
33
+ this.#partialBootstrapDeploymentValidator = new PartialBootstrapDeployment(state, this.#wallet.address, config);
34
+ this.#partialTransactionValidator = new PartialTransaction(state, this.#wallet.address, config);
35
+ this.#txPoolService = txPoolService;
36
36
  }
37
37
 
38
- async handleOperation(payload, connection) {
38
+ async handleOperation(payload, connection) {
39
39
  if (payload.type === OperationType.TX) {
40
40
  await this.#partialTransactionSubHandler(payload, connection);
41
41
  } else if (payload.type === OperationType.BOOTSTRAP_DEPLOYMENT) {
42
42
  await this.#partialBootstrapDeploymentSubHandler(payload, connection);
43
43
  } else {
44
- throw new Error(
45
- `Unsupported operation type for LegacySubnetworkOperationHandler. Requested by ${publicKeyToAddress(connection.remotePublicKey, this.#config)} `
46
- );
44
+ throw new Error('Unsupported operation type for SubnetworkOperationHandler');
47
45
  }
48
46
  }
49
47
 
@@ -51,12 +49,10 @@ class LegacySubnetworkOperationHandler extends BaseStateOperationHandler {
51
49
  const normalizedPayload = normalizeTransactionOperation(payload, this.#config);
52
50
  const isValid = await this.#partialTransactionValidator.validate(normalizedPayload);
53
51
  if (!isValid) {
54
- throw new Error(`
55
- SubnetworkHandler: Transaction validation failed. Requested by ${publicKeyToAddress(connection.remotePublicKey, this.#config)}`
56
- );
52
+ throw new Error("SubnetworkHandler: Transaction validation failed.");
57
53
  }
58
54
 
59
- const completeTransactionOperation = await applyStateMessageFactory(this.#wallet, this.#config)
55
+ const completeTransactionOperation = await applyStateMessageFactory(this.#wallet,this.#config)
60
56
  .buildCompleteTransactionOperationMessage(
61
57
  normalizedPayload.address,
62
58
  normalizedPayload.txo.tx,
@@ -68,19 +64,14 @@ class LegacySubnetworkOperationHandler extends BaseStateOperationHandler {
68
64
  normalizedPayload.txo.bs,
69
65
  normalizedPayload.txo.mbs
70
66
  )
71
- const encodedOperation = safeEncodeApplyOperation(completeTransactionOperation);
72
- const txHash = b4a.toString(normalizedPayload.txo.tx, 'hex');
73
- this.enqueueTransaction(txHash, encodedOperation);
74
-
67
+ this.#txPoolService.addTransaction(safeEncodeApplyOperation(completeTransactionOperation));
75
68
  }
76
69
 
77
70
  async #partialBootstrapDeploymentSubHandler(payload, connection) {
78
71
  const normalizedPayload = normalizeBootstrapDeploymentOperation(payload, this.#config);
79
72
  const isValid = await this.#partialBootstrapDeploymentValidator.validate(normalizedPayload);
80
73
  if (!isValid) {
81
- throw new Error(
82
- `SubnetworkHandler: Bootstrap deployment validation failed. Requested by ${publicKeyToAddress(connection.remotePublicKey, this.#config)}`
83
- );
74
+ throw new Error("SubnetworkHandler: Bootstrap deployment validation failed.");
84
75
  }
85
76
 
86
77
 
@@ -94,11 +85,9 @@ class LegacySubnetworkOperationHandler extends BaseStateOperationHandler {
94
85
  normalizedPayload.bdo.in,
95
86
  normalizedPayload.bdo.is
96
87
  )
97
- const encodedOperation = safeEncodeApplyOperation(completeBootstrapDeploymentOperation);
98
- const txHash = b4a.toString(normalizedPayload.bdo.tx, 'hex');
99
- this.enqueueTransaction(txHash, encodedOperation);
88
+ this.#txPoolService.addTransaction(safeEncodeApplyOperation(completeBootstrapDeploymentOperation));
100
89
 
101
90
  }
102
91
  }
103
92
 
104
- export default LegacySubnetworkOperationHandler;
93
+ export default SubnetworkOperationHandler;
@@ -1,36 +1,33 @@
1
- import BaseStateOperationHandler from './BaseStateOperationHandler.js';
1
+ import BaseOperationHandler from './base/BaseOperationHandler.js';
2
2
  import {OperationType} from '../../../../../utils/constants.js';
3
- import PartialTransferValidator from "../../shared/validators/PartialTransferValidator.js";
3
+ import PartialTransfer from "../validators/PartialTransfer.js";
4
4
  import {normalizeTransferOperation} from "../../../../../utils/normalizers.js"
5
5
  import {applyStateMessageFactory} from "../../../../../messages/state/applyStateMessageFactory.js";
6
6
  import {safeEncodeApplyOperation} from "../../../../../utils/protobuf/operationHelpers.js";
7
- import b4a from "b4a";
8
- import {publicKeyToAddress} from "../../../../../utils/helpers.js";
9
7
 
10
- class LegacyTransferOperationHandler extends BaseStateOperationHandler {
8
+ class TransferOperationHandler extends BaseOperationHandler {
11
9
  #partialTransferValidator;
12
10
  #config;
13
11
  #wallet;
12
+ #txPoolService;
14
13
 
15
14
  /**
16
15
  * @param {State} state
17
16
  * @param {PeerWallet} wallet
18
17
  * @param {TransactionRateLimiterService} rateLimiter
19
- * @param {TransactionPoolService} txPoolService
20
18
  * @param {Config} config
21
19
  **/
22
20
  constructor(state, wallet, rateLimiter, txPoolService, config) {
23
21
  super(state, wallet, rateLimiter, txPoolService, config);
24
22
  this.#config = config;
25
23
  this.#wallet = wallet;
26
- this.#partialTransferValidator = new PartialTransferValidator(state, this.#wallet.address, this.#config);
24
+ this.#partialTransferValidator = new PartialTransfer(state, this.#wallet.address, this.#config);
25
+ this.#txPoolService = txPoolService;
27
26
  }
28
27
 
29
28
  async handleOperation(payload, connection) {
30
29
  if (payload.type !== OperationType.TRANSFER) {
31
- throw new Error(
32
- `Unsupported operation type for LegacyTransferOperationHandler. Requested by ${publicKeyToAddress(connection.remotePublicKey, this.#config)}`
33
- );
30
+ throw new Error('Unsupported operation type for TransferOperationHandler');
34
31
  }
35
32
  await this.#handleTransfer(payload, connection);
36
33
  }
@@ -39,9 +36,7 @@ class LegacyTransferOperationHandler extends BaseStateOperationHandler {
39
36
  const normalizedPayload = normalizeTransferOperation(payload, this.#config);
40
37
  const isValid = await this.#partialTransferValidator.validate(normalizedPayload);
41
38
  if (!isValid) {
42
- throw new Error(
43
- `TransferHandler: Transfer validation failed. Requested by ${publicKeyToAddress(connection.remotePublicKey, this.#config)}`
44
- );
39
+ throw new Error("TransferHandler: Transfer validation failed.");
45
40
  }
46
41
 
47
42
  const completeTransferOperation = await applyStateMessageFactory(this.#wallet, this.#config)
@@ -54,10 +49,9 @@ class LegacyTransferOperationHandler extends BaseStateOperationHandler {
54
49
  normalizedPayload.tro.am,
55
50
  normalizedPayload.tro.is
56
51
  )
57
- const encodedOperation = safeEncodeApplyOperation(completeTransferOperation);
58
- const txHash = b4a.toString(normalizedPayload.tro.tx, 'hex');
59
- this.enqueueTransaction(txHash, encodedOperation);
52
+
53
+ this.#txPoolService.addTransaction(safeEncodeApplyOperation(completeTransferOperation));
60
54
  }
61
55
  }
62
56
 
63
- export default LegacyTransferOperationHandler;
57
+ export default TransferOperationHandler;
@@ -1,7 +1,6 @@
1
1
  import b4a from 'b4a';
2
- import {publicKeyToAddress} from "../../../../../utils/helpers.js";
3
2
 
4
- class BaseStateOperationHandler {
3
+ class BaseOperationHandler {
5
4
  #state;
6
5
  #wallet;
7
6
  #rateLimiter;
@@ -16,8 +15,8 @@ class BaseStateOperationHandler {
16
15
  * @param {Config} config
17
16
  **/
18
17
  constructor(state, wallet, rateLimiter, txPoolService, config) {
19
- if (new.target === BaseStateOperationHandler) {
20
- throw new Error('BaseStateOperationHandler is abstract and cannot be instantiated directly');
18
+ if (new.target === BaseOperationHandler) {
19
+ throw new Error('BaseOperationHandler is abstract and cannot be instantiated directly');
21
20
  }
22
21
  this.#state = state;
23
22
  this.#wallet = wallet;
@@ -38,18 +37,18 @@ class BaseStateOperationHandler {
38
37
  throw new Error('OperationHandler: State is not writable or is an indexer without admin privileges.');
39
38
  }
40
39
 
41
- this.#txPoolService.validateEnqueue();
42
- if (b4a.byteLength(JSON.stringify(payload)) > this.#config.transactionPoolSize) {
43
- throw new Error(
44
- `OperationHandler: Payload size exceeds maximum limit of ${this.#config.transactionPoolSize} bytes by ${b4a.byteLength(JSON.stringify(payload)) - this.#config.transactionPoolSize} bytes.`);
40
+ if (this.#txPoolService.tx_pool.length >= this.#config.transactionPoolSize) {
41
+ throw new Error("OperationHandler: Transaction pool is full, ignoring incoming transaction.");
42
+ }
43
+
44
+ if (b4a.byteLength(JSON.stringify(payload)) > this.#config.maxPartialTxPayloadByteSize) {
45
+ throw new Error(`OperationHandler: Payload size exceeds maximum limit of ${this.#config.maxPartialTxPayloadByteSize} bytes by ${b4a.byteLength(JSON.stringify(payload)) - this.#config.maxPartialTxPayloadByteSize} bytes.`);
45
46
  }
46
47
 
47
48
  if (!this.#config.disableRateLimit) {
48
- const shouldDisconnect = this.#rateLimiter.legacyHandleRateLimit(connection);
49
+ const shouldDisconnect = this.#rateLimiter.handleRateLimit(connection);
49
50
  if (shouldDisconnect) {
50
- throw new Error(
51
- `OperationHandler: Rate limit exceeded for ${publicKeyToAddress(connection.remotePublicKey, this.#config)}. Disconnecting...`
52
- );
51
+ throw new Error(`OperationHandler: Rate limit exceeded for peer ${b4a.toString(connection.remotePublicKey, 'hex')}. Disconnecting...`);
53
52
  }
54
53
  }
55
54
  }
@@ -59,19 +58,9 @@ class BaseStateOperationHandler {
59
58
  await this.handleOperation(payload, connection);
60
59
  }
61
60
 
62
- enqueueTransaction(txHash, encodedOperation) {
63
- try {
64
- this.#txPoolService.addTransaction(txHash, encodedOperation);
65
- } catch (error) {
66
- throw new Error(
67
- `${this.constructor.name}: Failed to add transaction ${txHash} to transaction pool: ${error?.message ?? String(error)}`
68
- );
69
- }
70
- }
71
-
72
61
  async handleOperation(payload, connection) {
73
62
  throw new Error('handleOperation must be implemented by child class');
74
63
  }
75
64
 
76
65
  }
77
- export default BaseStateOperationHandler;
66
+ export default BaseOperationHandler;
@@ -1,8 +1,6 @@
1
- import PartialOperationValidator from './PartialOperationValidator.js';
2
- import {ResultCode} from "../../../../../utils/constants.js";
3
- import SharedValidatorRejectionError from '../errors/SharedValidatorRejectionError.js';
1
+ import PartialOperation from './base/PartialOperation.js';
4
2
 
5
- class PartialBootstrapDeploymentValidator extends PartialOperationValidator {
3
+ class PartialBootstrapDeployment extends PartialOperation {
6
4
  constructor(state, selfAddress , config) {
7
5
  super(state, selfAddress , config);
8
6
  }
@@ -28,12 +26,9 @@ class PartialBootstrapDeploymentValidator extends PartialOperationValidator {
28
26
  async validateBootstrapRegistration(payload) {
29
27
  const bootstrapString = payload.bdo.bs.toString('hex');
30
28
  if (null !== await this.state.getRegisteredBootstrapEntryUnsigned(bootstrapString)) {
31
- throw new SharedValidatorRejectionError(
32
- ResultCode.BOOTSTRAP_ALREADY_EXISTS,
33
- `Bootstrap with hash ${bootstrapString} already exists in the state. Bootstrap must be unique.`
34
- );
29
+ throw new Error(`Bootstrap with hash ${bootstrapString} already exists in the state. Bootstrap must be unique.`);
35
30
  }
36
31
  }
37
32
  }
38
33
 
39
- export default PartialBootstrapDeploymentValidator;
34
+ export default PartialBootstrapDeployment;