trac-msb 0.2.8 → 0.2.9

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 (123) hide show
  1. package/msb.mjs +3 -3
  2. package/package.json +8 -3
  3. package/proto/network.proto +74 -0
  4. package/rpc/create_server.js +2 -2
  5. package/rpc/handlers.js +2 -2
  6. package/rpc/rpc_server.js +2 -2
  7. package/rpc/rpc_services.js +44 -3
  8. package/rpc/utils/helpers.js +1 -1
  9. package/src/config/env.js +2 -0
  10. package/src/core/network/Network.js +29 -61
  11. package/src/core/network/identity/NetworkWalletFactory.js +2 -2
  12. package/src/core/network/protocols/LegacyProtocol.js +67 -0
  13. package/src/core/network/protocols/NetworkMessages.js +48 -0
  14. package/src/core/network/protocols/ProtocolInterface.js +31 -0
  15. package/src/core/network/protocols/ProtocolSession.js +59 -0
  16. package/src/core/network/protocols/V1Protocol.js +64 -0
  17. package/src/core/network/protocols/legacy/NetworkMessageRouter.js +84 -0
  18. package/src/core/network/protocols/legacy/handlers/GetRequestHandler.js +53 -0
  19. package/src/core/network/protocols/legacy/handlers/ResponseHandler.js +37 -0
  20. package/src/core/network/{messaging → protocols/legacy}/validators/base/BaseResponse.js +1 -2
  21. package/src/core/network/protocols/shared/handlers/RoleOperationHandler.js +88 -0
  22. package/src/core/network/protocols/shared/handlers/SubnetworkOperationHandler.js +93 -0
  23. package/src/core/network/{messaging → protocols/shared}/handlers/TransferOperationHandler.js +16 -15
  24. package/src/core/network/{messaging → protocols/shared}/handlers/base/BaseOperationHandler.js +7 -11
  25. package/src/core/network/{messaging → protocols/shared}/validators/PartialBootstrapDeployment.js +2 -2
  26. package/src/core/network/{messaging → protocols/shared}/validators/PartialRoleAccess.js +5 -5
  27. package/src/core/network/{messaging → protocols/shared}/validators/PartialTransaction.js +4 -4
  28. package/src/core/network/{messaging → protocols/shared}/validators/PartialTransfer.js +4 -4
  29. package/src/core/network/{messaging → protocols/shared}/validators/base/PartialOperation.js +14 -12
  30. package/src/core/network/protocols/v1/NetworkMessageRouter.js +15 -0
  31. package/src/core/network/services/ConnectionManager.js +4 -4
  32. package/src/core/network/services/MessageOrchestrator.js +1 -1
  33. package/src/core/network/services/TransactionPoolService.js +1 -2
  34. package/src/core/network/services/TransactionRateLimiterService.js +5 -3
  35. package/src/core/state/State.js +1 -2
  36. package/src/index.js +153 -180
  37. package/src/messages/network/v1/NetworkMessageBuilder.js +325 -0
  38. package/src/messages/network/v1/NetworkMessageDirector.js +137 -0
  39. package/src/messages/network/v1/networkMessageFactory.js +12 -0
  40. package/src/messages/state/ApplyStateMessageBuilder.js +661 -0
  41. package/src/messages/state/ApplyStateMessageDirector.js +516 -0
  42. package/src/messages/state/applyStateMessageFactory.js +12 -0
  43. package/src/utils/buffer.js +53 -1
  44. package/src/utils/cli.js +0 -8
  45. package/src/utils/constants.js +34 -14
  46. package/src/utils/normalizers.js +84 -2
  47. package/src/utils/protobuf/network.cjs +840 -0
  48. package/src/utils/protobuf/operationHelpers.js +10 -0
  49. package/tests/acceptance/v1/rpc.test.mjs +1 -1
  50. package/tests/fixtures/networkV1.fixtures.js +84 -0
  51. package/tests/fixtures/protobuf.fixtures.js +83 -0
  52. package/tests/helpers/config.js +1 -1
  53. package/tests/helpers/setupApplyTests.js +53 -46
  54. package/tests/unit/messages/messages.test.js +12 -0
  55. package/tests/unit/messages/network/NetworkMessageBuilder.test.js +276 -0
  56. package/tests/unit/messages/network/NetworkMessageDirector.test.js +203 -0
  57. package/tests/unit/messages/state/applyStateMessageBuilder.complete.test.js +521 -0
  58. package/tests/unit/messages/state/applyStateMessageBuilder.partial.test.js +233 -0
  59. package/tests/unit/network/ConnectionManager.test.js +6 -5
  60. package/tests/unit/network/networkModule.test.js +3 -2
  61. package/tests/unit/state/apply/addAdmin/addAdminHappyPathScenario.js +10 -6
  62. package/tests/unit/state/apply/addAdmin/addAdminScenarioHelpers.js +9 -6
  63. package/tests/unit/state/apply/addAdmin/state.apply.addAdmin.test.js +10 -7
  64. package/tests/unit/state/apply/addIndexer/addIndexerScenarioHelpers.js +18 -21
  65. package/tests/unit/state/apply/addWriter/addWriterScenarioHelpers.js +53 -38
  66. package/tests/unit/state/apply/adminRecovery/adminRecoveryScenarioHelpers.js +46 -35
  67. package/tests/unit/state/apply/appendWhitelist/appendWhitelistScenarioHelpers.js +13 -16
  68. package/tests/unit/state/apply/balanceInitialization/balanceInitializationScenarioHelpers.js +17 -11
  69. package/tests/unit/state/apply/banValidator/banValidatorScenarioHelpers.js +11 -12
  70. package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentScenarioHelpers.js +9 -7
  71. package/tests/unit/state/apply/common/commonScenarioHelper.js +15 -14
  72. package/tests/unit/state/apply/common/payload-structure/initializationDisabledScenario.js +9 -4
  73. package/tests/unit/state/apply/disableInitialization/disableInitializationScenarioHelpers.js +17 -11
  74. package/tests/unit/state/apply/removeWriter/removeWriterScenarioHelpers.js +19 -14
  75. package/tests/unit/state/apply/transfer/transferDoubleSpendAcrossValidatorsScenario.js +37 -29
  76. package/tests/unit/state/apply/transfer/transferScenarioHelpers.js +9 -7
  77. package/tests/unit/state/apply/txOperation/txOperationScenarioHelpers.js +11 -9
  78. package/tests/unit/unit.test.js +1 -1
  79. package/tests/unit/utils/buffer/buffer.test.js +62 -1
  80. package/tests/unit/utils/normalizers/normalizers.test.js +469 -0
  81. package/tests/unit/utils/protobuf/operationHelpers.test.js +120 -2
  82. package/docs/networking-dualstack-plan.md +0 -75
  83. package/docs/networking-layer-redesign.md +0 -155
  84. package/src/core/network/messaging/NetworkMessages.js +0 -64
  85. package/src/core/network/messaging/handlers/GetRequestHandler.js +0 -113
  86. package/src/core/network/messaging/handlers/ResponseHandler.js +0 -107
  87. package/src/core/network/messaging/handlers/RoleOperationHandler.js +0 -114
  88. package/src/core/network/messaging/handlers/SubnetworkOperationHandler.js +0 -149
  89. package/src/core/network/messaging/routes/NetworkMessageRouter.js +0 -98
  90. package/src/core/network/messaging/validators/AdminResponse.js +0 -58
  91. package/src/core/network/messaging/validators/CustomNodeResponse.js +0 -46
  92. package/src/messages/base/StateBuilder.js +0 -25
  93. package/src/messages/completeStateMessages/CompleteStateMessageBuilder.js +0 -425
  94. package/src/messages/completeStateMessages/CompleteStateMessageDirector.js +0 -252
  95. package/src/messages/completeStateMessages/CompleteStateMessageOperations.js +0 -296
  96. package/src/messages/partialStateMessages/PartialStateMessageBuilder.js +0 -272
  97. package/src/messages/partialStateMessages/PartialStateMessageDirector.js +0 -137
  98. package/src/messages/partialStateMessages/PartialStateMessageOperations.js +0 -138
  99. package/tests/integration/apply/addAdmin/addAdminBasic.test.js +0 -69
  100. package/tests/integration/apply/addAdmin/addAdminRecovery.test.js +0 -126
  101. package/tests/integration/apply/addIndexer.test.js +0 -239
  102. package/tests/integration/apply/addWhitelist.test.js +0 -53
  103. package/tests/integration/apply/addWriter.test.js +0 -245
  104. package/tests/integration/apply/apply.test.js +0 -19
  105. package/tests/integration/apply/banValidator.test.js +0 -116
  106. package/tests/integration/apply/postTx/invalidSubValues.test.js +0 -103
  107. package/tests/integration/apply/postTx/postTx.test.js +0 -196
  108. package/tests/integration/apply/removeIndexer.test.js +0 -132
  109. package/tests/integration/apply/removeWriter.test.js +0 -168
  110. package/tests/integration/apply/transfer.test.js +0 -83
  111. package/tests/integration/integration.test.js +0 -9
  112. package/tests/unit/messageOperations/assembleAddIndexerMessage.test.js +0 -21
  113. package/tests/unit/messageOperations/assembleAddWriterMessage.test.js +0 -17
  114. package/tests/unit/messageOperations/assembleAdminMessage.test.js +0 -68
  115. package/tests/unit/messageOperations/assembleBanWriterMessage.test.js +0 -17
  116. package/tests/unit/messageOperations/assemblePostTransaction.test.js +0 -424
  117. package/tests/unit/messageOperations/assembleRemoveIndexerMessage.test.js +0 -19
  118. package/tests/unit/messageOperations/assembleRemoveWriterMessage.test.js +0 -17
  119. package/tests/unit/messageOperations/assembleWhitelistMessages.test.js +0 -59
  120. package/tests/unit/messageOperations/commonsStateMessageOperationsTest.js +0 -278
  121. package/tests/unit/messageOperations/stateMessageOperations.test.js +0 -19
  122. /package/src/core/network/{messaging → protocols/legacy}/validators/ValidatorResponse.js +0 -0
  123. /package/src/utils/{operations.js → applyOperations.js} +0 -0
@@ -0,0 +1,64 @@
1
+ import Protomux from 'protomux';
2
+ import ProtocolInterface from './ProtocolInterface.js';
3
+ import b4a from 'b4a';
4
+ import c from 'compact-encoding';
5
+
6
+ class V1Protocol extends ProtocolInterface {
7
+ #channel;
8
+ #session;
9
+ #config;
10
+ #router;
11
+
12
+ constructor(router, connection, config) {
13
+ super(router, connection, config);
14
+ this.#config = config;
15
+ this.#router = router;
16
+ this.init(connection);
17
+ }
18
+
19
+ get channel() {
20
+ return this.#channel;
21
+ }
22
+
23
+ get session() {
24
+ return this.#session;
25
+ }
26
+
27
+ init(connection) {
28
+ const mux = Protomux.from(connection);
29
+ connection.userData = mux;
30
+
31
+ this.#channel = mux.createChannel({
32
+ protocol: 'network/v1',
33
+ onopen() { },
34
+ onclose() { }
35
+ });
36
+
37
+ this.#channel.open();
38
+
39
+ this.#session = this.#channel.addMessage({
40
+ encoding: c.raw,
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');
47
+ }
48
+ } catch (error) {
49
+ console.error(`NetworkMessages: Failed to handle incoming v1 message: ${error.message}`);
50
+ }
51
+ }
52
+ });
53
+ }
54
+
55
+ send(message) {
56
+ this.#session.send(message);
57
+ }
58
+
59
+ close() {
60
+ this.#channel.close();
61
+ }
62
+ }
63
+
64
+ export default V1Protocol;
@@ -0,0 +1,84 @@
1
+ import b4a from "b4a";
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";
7
+ import { NETWORK_MESSAGE_TYPES } from '../../../../utils/constants.js';
8
+ import * as operation from '../../../../utils/applyOperations.js';
9
+ import State from "../../../state/State.js";
10
+ import PeerWallet from "trac-wallet";
11
+
12
+ class NetworkMessageRouter {
13
+ #handlers;
14
+ #config;
15
+
16
+ /**
17
+ * @param {State} state
18
+ * @param {PeerWallet} wallet
19
+ * @param {TransactionRateLimiterService} rateLimiterService
20
+ * @param {TransactionPoolService} txPoolService
21
+ * @param {ConnectionManager} connectionManager
22
+ * @param {object} config
23
+ **/
24
+ constructor(state, wallet, rateLimiterService, txPoolService, connectionManager, config) {
25
+ this.#config = config;
26
+
27
+ this.#handlers = {
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),
33
+ }
34
+ }
35
+
36
+ // NOTE: messageProtomux can be deleted, ad this is a session, and we can extract this from connection
37
+ async route(incomingMessage, connection, messageProtomux) {
38
+ const channelString = b4a.toString(this.#config.channel, 'utf8');
39
+ if (this.#isGetRequest(incomingMessage)) {
40
+ await this.#handlers.get.handle(incomingMessage, messageProtomux, connection, channelString);
41
+ }
42
+ else if (this.#isResponse(incomingMessage)) {
43
+ await this.#handlers.response.handle(incomingMessage, connection, channelString);
44
+ }
45
+ else if (this.#isRoleAccessOperation(incomingMessage)) {
46
+ await this.#handlers.roleTransaction.handle(incomingMessage, connection);
47
+ }
48
+ else if (this.#isSubnetworkOperation(incomingMessage)) {
49
+ await this.#handlers.subNetworkTransaction.handle(incomingMessage, connection);
50
+ }
51
+ else if (this.#isTransferOperation(incomingMessage)) {
52
+ await this.#handlers.tracNetworkTransaction.handle(incomingMessage, connection);
53
+ }
54
+ else {
55
+ throw new Error(`Failed to route message. Pubkey of requester is ${connection.remotePublicKey ? b4a.toString(connection.remotePublicKey, 'hex') : 'unknown'}`);
56
+ }
57
+
58
+ }
59
+
60
+ #isGetRequest(message) {
61
+ return Object.values(NETWORK_MESSAGE_TYPES.GET).includes(message);
62
+ }
63
+
64
+
65
+ #isResponse(message) {
66
+ return Object.values(NETWORK_MESSAGE_TYPES.RESPONSE).includes(message.op);
67
+ }
68
+
69
+ #isRoleAccessOperation(message) {
70
+ return operation.isRoleAccess(message.type)
71
+ }
72
+
73
+ #isSubnetworkOperation(message) {
74
+ return operation.isTransaction(message.type) ||
75
+ operation.isBootstrapDeployment(message.type)
76
+ }
77
+
78
+ #isTransferOperation(message) {
79
+ return operation.isTransfer(message.type)
80
+ }
81
+ }
82
+
83
+
84
+ export default NetworkMessageRouter;
@@ -0,0 +1,53 @@
1
+ import { NETWORK_MESSAGE_TYPES } from '../../../../../utils/constants.js';
2
+ import PeerWallet from 'trac-wallet';
3
+ import b4a from 'b4a';
4
+
5
+ class GetRequestHandler {
6
+ #wallet;
7
+ #state;
8
+
9
+ constructor(wallet, state) {
10
+ this.#wallet = wallet;
11
+ this.#state = state;
12
+ }
13
+
14
+ get state() {
15
+ return this.#state;
16
+ }
17
+
18
+ async handle(message, messageProtomux, connection, channelString) {
19
+ switch (message) {
20
+ case NETWORK_MESSAGE_TYPES.GET.VALIDATOR:
21
+ await this.handleGetValidatorResponse(messageProtomux, connection, channelString);
22
+ break;
23
+ default:
24
+ throw new Error(`Unhandled GET type: ${message}`);
25
+ }
26
+ }
27
+
28
+ async handleGetValidatorResponse(messageProtomux, connection, channelString) {
29
+ const nonce = PeerWallet.generateNonce().toString('hex');
30
+ const payload = {
31
+ op: 'validatorResponse',
32
+ wk: this.state.writingKey.toString('hex'),
33
+ address: this.#wallet.address,
34
+ nonce: nonce,
35
+ channel: channelString,
36
+ issuer: connection.remotePublicKey.toString('hex'),
37
+ timestamp: Date.now(),
38
+ };
39
+
40
+
41
+ const hashInput = b4a.from(JSON.stringify(payload), 'utf8');
42
+ const hash = await PeerWallet.blake3(hashInput);
43
+ const sig = this.#wallet.sign(hash);
44
+
45
+ const responseMessage = {
46
+ ...payload,
47
+ sig: sig.toString('hex'),
48
+ };
49
+ messageProtomux.send(responseMessage);
50
+ }
51
+ }
52
+
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,7 +1,6 @@
1
1
  import b4a from 'b4a';
2
2
  import PeerWallet from 'trac-wallet';
3
- import { bufferToAddress } from '../../../../state/utils/address.js';
4
- import State from '../../../../state/State.js';
3
+ import State from '../../../../../state/State.js';
5
4
 
6
5
  /*
7
6
  BaseResponse class for handling common validation logic for network responses.
@@ -0,0 +1,88 @@
1
+ import {OperationType} from '../../../../../utils/constants.js';
2
+ import PartialRoleAccess from "../validators/PartialRoleAccess.js";
3
+ import BaseOperationHandler from './base/BaseOperationHandler.js';
4
+ import {applyStateMessageFactory} from "../../../../../messages/state/applyStateMessageFactory.js";
5
+ import {safeEncodeApplyOperation} from "../../../../../utils/protobuf/operationHelpers.js";
6
+ import {normalizeRoleAccessOperation} from "../../../../../utils/normalizers.js";
7
+
8
+ class RoleOperationHandler extends BaseOperationHandler {
9
+ #partialRoleAccessValidator;
10
+ #wallet;
11
+ #config;
12
+ #txPoolService;
13
+
14
+ /**
15
+ * @param {State} state
16
+ * @param {PeerWallet} wallet
17
+ * @param {TransactionRateLimiterService} rateLimiter
18
+ * @param {TransactionPoolService} txPoolService
19
+ * @param {object} config
20
+ **/
21
+ constructor(state, wallet, rateLimiter, txPoolService ,config) {
22
+ super(state, wallet, rateLimiter, txPoolService, config);
23
+ this.#wallet = wallet;
24
+ this.#config = config;
25
+ this.#partialRoleAccessValidator = new PartialRoleAccess(state, this.#wallet.address ,this.#config)
26
+ this.#txPoolService = txPoolService;
27
+ }
28
+
29
+ get partialRoleAccessValidator() {
30
+ return this.#partialRoleAccessValidator;
31
+ }
32
+
33
+ async handleOperation(message, connection) {
34
+ const normalizedPartialRoleAccessPayload = normalizeRoleAccessOperation(message, this.#config)
35
+ const isValid = await this.partialRoleAccessValidator.validate(normalizedPartialRoleAccessPayload)
36
+ let completePayload = null
37
+ if (!isValid) {
38
+ throw new Error("OperationHandler: partial role access payload validation failed.");
39
+ }
40
+
41
+ switch (normalizedPartialRoleAccessPayload.type) {
42
+ case OperationType.ADD_WRITER:
43
+ completePayload = await applyStateMessageFactory(this.#wallet, this.#config)
44
+ .buildCompleteAddWriterMessage(
45
+ normalizedPartialRoleAccessPayload.address,
46
+ normalizedPartialRoleAccessPayload.rao.tx,
47
+ normalizedPartialRoleAccessPayload.rao.txv,
48
+ normalizedPartialRoleAccessPayload.rao.iw,
49
+ normalizedPartialRoleAccessPayload.rao.in,
50
+ normalizedPartialRoleAccessPayload.rao.is,
51
+ )
52
+ break;
53
+ case OperationType.REMOVE_WRITER:
54
+ completePayload = await applyStateMessageFactory(this.#wallet, this.#config)
55
+ .buildCompleteRemoveWriterMessage(
56
+ normalizedPartialRoleAccessPayload.address,
57
+ normalizedPartialRoleAccessPayload.rao.tx,
58
+ normalizedPartialRoleAccessPayload.rao.txv,
59
+ normalizedPartialRoleAccessPayload.rao.iw,
60
+ normalizedPartialRoleAccessPayload.rao.in,
61
+ normalizedPartialRoleAccessPayload.rao.is,
62
+ )
63
+ break;
64
+ case OperationType.ADMIN_RECOVERY:
65
+
66
+ completePayload = await applyStateMessageFactory(this.#wallet, this.#config)
67
+ .buildCompleteAdminRecoveryMessage(
68
+ normalizedPartialRoleAccessPayload.address,
69
+ normalizedPartialRoleAccessPayload.rao.tx,
70
+ normalizedPartialRoleAccessPayload.rao.txv,
71
+ normalizedPartialRoleAccessPayload.rao.iw,
72
+ normalizedPartialRoleAccessPayload.rao.in,
73
+ normalizedPartialRoleAccessPayload.rao.is,
74
+ )
75
+ break;
76
+ default:
77
+ throw new Error("OperationHandler: Assembling complete role access operation failed due to unsupported operation type.");
78
+ }
79
+
80
+ if (!completePayload) {
81
+ throw new Error("OperationHandler: Assembling complete role access operation failed.");
82
+ }
83
+
84
+ this.#txPoolService.addTransaction(safeEncodeApplyOperation(completePayload))
85
+ }
86
+ }
87
+
88
+ export default RoleOperationHandler;
@@ -0,0 +1,93 @@
1
+ import BaseOperationHandler from './base/BaseOperationHandler.js';
2
+ import {
3
+ OperationType
4
+ } from '../../../../../utils/constants.js';
5
+ import PartialBootstrapDeployment from "../validators/PartialBootstrapDeployment.js";
6
+ import PartialTransaction from "../validators/PartialTransaction.js";
7
+ import {applyStateMessageFactory} from "../../../../../messages/state/applyStateMessageFactory.js";
8
+ import {safeEncodeApplyOperation} from "../../../../../utils/protobuf/operationHelpers.js";
9
+ import {
10
+ normalizeBootstrapDeploymentOperation,
11
+ normalizeTransactionOperation
12
+ } from "../../../../../utils/normalizers.js";
13
+
14
+
15
+ class SubnetworkOperationHandler extends BaseOperationHandler {
16
+ #partialBootstrapDeploymentValidator;
17
+ #partialTransactionValidator;
18
+ #config;
19
+ #wallet;
20
+ #txPoolService;
21
+
22
+ /**
23
+ * @param {State} state
24
+ * @param {PeerWallet} wallet
25
+ * @param {TransactionRateLimiterService} rateLimiter
26
+ * @param {TransactionPoolService} txPoolService
27
+ * @param {object} config
28
+ **/
29
+ constructor( state, wallet, rateLimiter, txPoolService, config) {
30
+ super(state, wallet, rateLimiter, txPoolService, config);
31
+ this.#config = config;
32
+ this.#wallet = wallet
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
+ }
37
+
38
+ async handleOperation(payload, connection) {
39
+ if (payload.type === OperationType.TX) {
40
+ await this.#partialTransactionSubHandler(payload, connection);
41
+ } else if (payload.type === OperationType.BOOTSTRAP_DEPLOYMENT) {
42
+ await this.#partialBootstrapDeploymentSubHandler(payload, connection);
43
+ } else {
44
+ throw new Error('Unsupported operation type for SubnetworkOperationHandler');
45
+ }
46
+ }
47
+
48
+ async #partialTransactionSubHandler(payload, connection) {
49
+ const normalizedPayload = normalizeTransactionOperation(payload, this.#config);
50
+ const isValid = await this.#partialTransactionValidator.validate(normalizedPayload);
51
+ if (!isValid) {
52
+ throw new Error("SubnetworkHandler: Transaction validation failed.");
53
+ }
54
+
55
+ const completeTransactionOperation = await applyStateMessageFactory(this.#wallet,this.#config)
56
+ .buildCompleteTransactionOperationMessage(
57
+ normalizedPayload.address,
58
+ normalizedPayload.txo.tx,
59
+ normalizedPayload.txo.txv,
60
+ normalizedPayload.txo.iw,
61
+ normalizedPayload.txo.in,
62
+ normalizedPayload.txo.ch,
63
+ normalizedPayload.txo.is,
64
+ normalizedPayload.txo.bs,
65
+ normalizedPayload.txo.mbs
66
+ )
67
+ this.#txPoolService.addTransaction(safeEncodeApplyOperation(completeTransactionOperation));
68
+ }
69
+
70
+ async #partialBootstrapDeploymentSubHandler(payload, connection) {
71
+ const normalizedPayload = normalizeBootstrapDeploymentOperation(payload, this.#config);
72
+ const isValid = await this.#partialBootstrapDeploymentValidator.validate(normalizedPayload);
73
+ if (!isValid) {
74
+ throw new Error("SubnetworkHandler: Bootstrap deployment validation failed.");
75
+ }
76
+
77
+
78
+ const completeBootstrapDeploymentOperation = await applyStateMessageFactory(this.#wallet, this.#config)
79
+ .buildCompleteBootstrapDeploymentMessage(
80
+ normalizedPayload.address,
81
+ normalizedPayload.bdo.tx,
82
+ normalizedPayload.bdo.txv,
83
+ normalizedPayload.bdo.bs,
84
+ normalizedPayload.bdo.ic,
85
+ normalizedPayload.bdo.in,
86
+ normalizedPayload.bdo.is
87
+ )
88
+ this.#txPoolService.addTransaction(safeEncodeApplyOperation(completeBootstrapDeploymentOperation));
89
+
90
+ }
91
+ }
92
+
93
+ export default SubnetworkOperationHandler;
@@ -1,45 +1,46 @@
1
1
  import BaseOperationHandler from './base/BaseOperationHandler.js';
2
- import CompleteStateMessageOperations
3
- from "../../../../messages/completeStateMessages/CompleteStateMessageOperations.js";
4
- import {OperationType} from '../../../../utils/constants.js';
2
+ import {OperationType} from '../../../../../utils/constants.js';
5
3
  import PartialTransfer from "../validators/PartialTransfer.js";
6
- import {normalizeTransferOperation} from "../../../../utils/normalizers.js"
4
+ import {normalizeTransferOperation} from "../../../../../utils/normalizers.js"
5
+ import {applyStateMessageFactory} from "../../../../../messages/state/applyStateMessageFactory.js";
6
+ import {safeEncodeApplyOperation} from "../../../../../utils/protobuf/operationHelpers.js";
7
7
 
8
8
  class TransferOperationHandler extends BaseOperationHandler {
9
9
  #partialTransferValidator;
10
10
  #config;
11
11
  #wallet;
12
+ #txPoolService;
12
13
 
13
14
  /**
14
- * @param {Network} network
15
15
  * @param {State} state
16
16
  * @param {PeerWallet} wallet
17
17
  * @param {TransactionRateLimiterService} rateLimiter
18
18
  * @param {object} config
19
19
  **/
20
- constructor(network, state, wallet, rateLimiter, config) {
21
- super(network, state, wallet, rateLimiter, config);
20
+ constructor(state, wallet, rateLimiter, txPoolService, config) {
21
+ super(state, wallet, rateLimiter, txPoolService, config);
22
22
  this.#config = config;
23
23
  this.#wallet = wallet;
24
- this.#partialTransferValidator = new PartialTransfer(state, wallet, this.#config);
24
+ this.#partialTransferValidator = new PartialTransfer(state, this.#wallet.address, this.#config);
25
+ this.#txPoolService = txPoolService;
25
26
  }
26
27
 
27
- async handleOperation(payload) {
28
+ async handleOperation(payload, connection) {
28
29
  if (payload.type !== OperationType.TRANSFER) {
29
30
  throw new Error('Unsupported operation type for TransferOperationHandler');
30
31
  }
31
- await this.#handleTransfer(payload);
32
+ await this.#handleTransfer(payload, connection);
32
33
  }
33
34
 
34
- async #handleTransfer(payload) {
35
+ async #handleTransfer(payload, connection) {
35
36
  const normalizedPayload = normalizeTransferOperation(payload, this.#config);
36
37
  const isValid = await this.#partialTransferValidator.validate(normalizedPayload);
37
38
  if (!isValid) {
38
39
  throw new Error("TransferHandler: Transfer validation failed.");
39
40
  }
40
41
 
41
- const completeTransferOperation = await new CompleteStateMessageOperations(this.#wallet, this.#config)
42
- .assembleCompleteTransferOperationMessage(
42
+ const completeTransferOperation = await applyStateMessageFactory(this.#wallet, this.#config)
43
+ .buildCompleteTransferOperationMessage(
43
44
  normalizedPayload.address,
44
45
  normalizedPayload.tro.tx,
45
46
  normalizedPayload.tro.txv,
@@ -47,9 +48,9 @@ class TransferOperationHandler extends BaseOperationHandler {
47
48
  normalizedPayload.tro.to,
48
49
  normalizedPayload.tro.am,
49
50
  normalizedPayload.tro.is
50
- );
51
+ )
51
52
 
52
- this.network.transactionPoolService.addTransaction(completeTransferOperation);
53
+ this.#txPoolService.addTransaction(safeEncodeApplyOperation(completeTransferOperation));
53
54
  }
54
55
  }
55
56
 
@@ -1,35 +1,31 @@
1
1
  import b4a from 'b4a';
2
- import {MAX_PARTIAL_TX_PAYLOAD_BYTE_SIZE, TRANSACTION_POOL_SIZE} from '../../../../../utils/constants.js';
2
+ import {MAX_PARTIAL_TX_PAYLOAD_BYTE_SIZE, TRANSACTION_POOL_SIZE} from '../../../../../../utils/constants.js';
3
3
 
4
4
  class BaseOperationHandler {
5
- #network;
6
5
  #state;
7
6
  #wallet;
8
7
  #rateLimiter;
8
+ #txPoolService;
9
9
  #config;
10
10
 
11
11
  /**
12
- * @param {Network} network
13
12
  * @param {State} state
14
13
  * @param {PeerWallet} wallet
15
14
  * @param {TransactionRateLimiterService} rateLimiter
15
+ * @param {TransactionPoolService} txPoolService
16
16
  * @param {object} config
17
17
  **/
18
- constructor(network, state, wallet, rateLimiter, config) {
18
+ constructor(state, wallet, rateLimiter, txPoolService, config) {
19
19
  if (new.target === BaseOperationHandler) {
20
20
  throw new Error('BaseOperationHandler is abstract and cannot be instantiated directly');
21
21
  }
22
- this.#network = network;
23
22
  this.#state = state;
24
23
  this.#wallet = wallet;
25
24
  this.#rateLimiter = rateLimiter;
25
+ this.#txPoolService = txPoolService;
26
26
  this.#config = config;
27
27
  }
28
28
 
29
- get network() {
30
- return this.#network;
31
- }
32
-
33
29
  async validateBasicRequirements(payload, connection) {
34
30
  // Validate if operation can be processed:
35
31
  // - Non-writable nodes cannot process operations
@@ -42,7 +38,7 @@ class BaseOperationHandler {
42
38
  throw new Error('OperationHandler: State is not writable or is an indexer without admin privileges.');
43
39
  }
44
40
 
45
- if (this.#network.transactionPoolService.tx_pool.length >= TRANSACTION_POOL_SIZE) {
41
+ if (this.#txPoolService.tx_pool.length >= TRANSACTION_POOL_SIZE) {
46
42
  throw new Error("OperationHandler: Transaction pool is full, ignoring incoming transaction.");
47
43
  }
48
44
 
@@ -51,7 +47,7 @@ class BaseOperationHandler {
51
47
  }
52
48
 
53
49
  if (!this.#config.disableRateLimit) {
54
- const shouldDisconnect = this.#rateLimiter.handleRateLimit(connection, this.#network);
50
+ const shouldDisconnect = this.#rateLimiter.handleRateLimit(connection);
55
51
  if (shouldDisconnect) {
56
52
  throw new Error(`OperationHandler: Rate limit exceeded for peer ${b4a.toString(connection.remotePublicKey, 'hex')}. Disconnecting...`);
57
53
  }
@@ -1,8 +1,8 @@
1
1
  import PartialOperation from './base/PartialOperation.js';
2
2
 
3
3
  class PartialBootstrapDeployment extends PartialOperation {
4
- constructor(state, wallet , config) {
5
- super(state, wallet , config);
4
+ constructor(state, selfAddress , config) {
5
+ super(state, selfAddress , config);
6
6
  }
7
7
 
8
8
  async validate(payload) {
@@ -1,14 +1,14 @@
1
1
  import b4a from 'b4a';
2
- import {OperationType} from "../../../../utils/constants.js";
3
- import {bufferToAddress} from "../../../state/utils/address.js";
2
+ import {OperationType} from "../../../../../utils/constants.js";
3
+ import {bufferToAddress} from "../../../../state/utils/address.js";
4
4
  import PartialOperation from './base/PartialOperation.js';
5
- import {bufferToBigInt} from "../../../../utils/amountSerialization.js";
5
+ import {bufferToBigInt} from "../../../../../utils/amountSerialization.js";
6
6
 
7
7
  class PartialRoleAccess extends PartialOperation {
8
8
  #config;
9
9
 
10
- constructor(state, wallet, config) {
11
- super(state, wallet, config);
10
+ constructor(state, selfAddress, config) {
11
+ super(state, selfAddress, config);
12
12
  this.#config = config
13
13
  }
14
14
 
@@ -1,13 +1,13 @@
1
1
  import b4a from 'b4a';
2
- import {safeDecodeApplyOperation} from "../../../../utils/protobuf/operationHelpers.js";
3
- import deploymentEntryUtils from "../../../state/utils/deploymentEntry.js";
2
+ import {safeDecodeApplyOperation} from "../../../../../utils/protobuf/operationHelpers.js";
3
+ import deploymentEntryUtils from "../../../../state/utils/deploymentEntry.js";
4
4
  import PartialOperation from './base/PartialOperation.js';
5
5
 
6
6
  class PartialTransaction extends PartialOperation {
7
7
  #config
8
8
 
9
- constructor(state, wallet, config) {
10
- super(state, wallet, config);
9
+ constructor(state, selfAddress, config) {
10
+ super(state, selfAddress, config);
11
11
  this.#config = config
12
12
  }
13
13
 
@@ -1,14 +1,14 @@
1
1
  import PeerWallet from 'trac-wallet';
2
2
 
3
- import {bufferToAddress} from "../../../state/utils/address.js";
4
- import {bufferToBigInt} from "../../../../utils/amountSerialization.js";
3
+ import {bufferToAddress} from "../../../../state/utils/address.js";
4
+ import {bufferToBigInt} from "../../../../../utils/amountSerialization.js";
5
5
  import PartialOperation from './base/PartialOperation.js';
6
6
 
7
7
  class PartialTransfer extends PartialOperation {
8
8
  #config
9
9
 
10
- constructor(state, wallet, config) {
11
- super(state, wallet, config);
10
+ constructor(state, selfAddress, config) {
11
+ super(state, selfAddress, config);
12
12
  this.#config = config
13
13
  }
14
14