trac-msb 0.2.7 → 0.2.8

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 (146) hide show
  1. package/.github/workflows/publish.yml +8 -16
  2. package/docs/networking-dualstack-plan.md +75 -0
  3. package/docs/networking-layer-redesign.md +155 -0
  4. package/msb.mjs +11 -23
  5. package/package.json +2 -3
  6. package/rpc/{create_server.mjs → create_server.js} +2 -2
  7. package/rpc/{handlers.mjs → handlers.js} +5 -5
  8. package/rpc/routes/{index.mjs → index.js} +1 -1
  9. package/rpc/routes/{v1.mjs → v1.js} +1 -1
  10. package/rpc/{rpc_server.mjs → rpc_server.js} +1 -1
  11. package/rpc/rpc_services.js +4 -4
  12. package/src/config/config.js +137 -0
  13. package/src/config/env.js +61 -0
  14. package/src/core/network/Network.js +119 -73
  15. package/src/core/network/identity/NetworkWalletFactory.js +3 -4
  16. package/src/core/network/messaging/NetworkMessages.js +12 -11
  17. package/src/core/network/messaging/handlers/GetRequestHandler.js +5 -4
  18. package/src/core/network/messaging/handlers/ResponseHandler.js +4 -5
  19. package/src/core/network/messaging/handlers/RoleOperationHandler.js +17 -19
  20. package/src/core/network/messaging/handlers/SubnetworkOperationHandler.js +44 -38
  21. package/src/core/network/messaging/handlers/TransferOperationHandler.js +29 -25
  22. package/src/core/network/messaging/handlers/base/BaseOperationHandler.js +20 -21
  23. package/src/core/network/messaging/routes/NetworkMessageRouter.js +24 -20
  24. package/src/core/network/messaging/validators/AdminResponse.js +2 -2
  25. package/src/core/network/messaging/validators/CustomNodeResponse.js +2 -2
  26. package/src/core/network/messaging/validators/PartialBootstrapDeployment.js +3 -3
  27. package/src/core/network/messaging/validators/PartialRoleAccess.js +15 -12
  28. package/src/core/network/messaging/validators/PartialTransaction.js +9 -10
  29. package/src/core/network/messaging/validators/PartialTransfer.js +10 -7
  30. package/src/core/network/messaging/validators/ValidatorResponse.js +2 -2
  31. package/src/core/network/messaging/validators/base/BaseResponse.js +13 -5
  32. package/src/core/network/messaging/validators/base/PartialOperation.js +37 -21
  33. package/src/core/network/services/ConnectionManager.js +9 -15
  34. package/src/core/network/services/MessageOrchestrator.js +10 -22
  35. package/src/core/network/services/TransactionPoolService.js +9 -8
  36. package/src/core/network/services/ValidatorObserverService.js +46 -21
  37. package/src/core/state/State.js +136 -139
  38. package/src/core/state/utils/address.js +18 -16
  39. package/src/core/state/utils/adminEntry.js +17 -16
  40. package/src/core/state/utils/deploymentEntry.js +15 -15
  41. package/src/core/state/utils/transaction.js +3 -95
  42. package/src/index.js +153 -201
  43. package/src/messages/completeStateMessages/CompleteStateMessageBuilder.js +36 -32
  44. package/src/messages/completeStateMessages/CompleteStateMessageOperations.js +39 -42
  45. package/src/messages/partialStateMessages/PartialStateMessageBuilder.js +20 -20
  46. package/src/messages/partialStateMessages/PartialStateMessageOperations.js +29 -22
  47. package/src/utils/check.js +21 -17
  48. package/src/utils/cliCommands.js +11 -11
  49. package/src/utils/constants.js +2 -10
  50. package/src/utils/fileUtils.js +1 -4
  51. package/src/utils/helpers.js +9 -20
  52. package/src/utils/migrationUtils.js +2 -2
  53. package/src/utils/normalizers.js +10 -9
  54. package/tests/acceptance/v1/account/account.test.mjs +2 -2
  55. package/tests/acceptance/v1/balance/balance.test.mjs +1 -1
  56. package/tests/acceptance/v1/broadcast-transaction/broadcast-transaction.test.mjs +11 -2
  57. package/tests/acceptance/v1/rpc.test.mjs +9 -9
  58. package/tests/acceptance/v1/tx/tx.test.mjs +4 -2
  59. package/tests/acceptance/v1/tx-details/tx-details.test.mjs +7 -3
  60. package/tests/fixtures/check.fixtures.js +42 -42
  61. package/tests/fixtures/protobuf.fixtures.js +27 -26
  62. package/tests/helpers/StateNetworkFactory.js +3 -5
  63. package/tests/helpers/autobaseTestHelpers.js +1 -2
  64. package/tests/helpers/config.js +3 -0
  65. package/tests/helpers/setupApplyTests.js +89 -82
  66. package/tests/helpers/transactionPayloads.mjs +26 -12
  67. package/tests/integration/apply/addAdmin/addAdminBasic.test.js +10 -9
  68. package/tests/integration/apply/addAdmin/addAdminRecovery.test.js +20 -19
  69. package/tests/integration/apply/addIndexer.test.js +23 -21
  70. package/tests/integration/apply/addWhitelist.test.js +9 -9
  71. package/tests/integration/apply/addWriter.test.js +33 -32
  72. package/tests/integration/apply/banValidator.test.js +16 -9
  73. package/tests/integration/apply/postTx/invalidSubValues.test.js +4 -4
  74. package/tests/integration/apply/postTx/postTx.test.js +7 -33
  75. package/tests/integration/apply/removeIndexer.test.js +11 -7
  76. package/tests/integration/apply/removeWriter.test.js +20 -19
  77. package/tests/integration/apply/transfer.test.js +18 -16
  78. package/tests/unit/messageOperations/assembleAddIndexerMessage.test.js +2 -2
  79. package/tests/unit/messageOperations/assembleAddWriterMessage.test.js +2 -1
  80. package/tests/unit/messageOperations/assembleAdminMessage.test.js +9 -10
  81. package/tests/unit/messageOperations/assembleBanWriterMessage.test.js +3 -2
  82. package/tests/unit/messageOperations/assemblePostTransaction.test.js +25 -43
  83. package/tests/unit/messageOperations/assembleRemoveIndexerMessage.test.js +2 -2
  84. package/tests/unit/messageOperations/assembleRemoveWriterMessage.test.js +2 -2
  85. package/tests/unit/messageOperations/assembleWhitelistMessages.test.js +5 -4
  86. package/tests/unit/messageOperations/commonsStateMessageOperationsTest.js +4 -3
  87. package/tests/unit/network/ConnectionManager.test.js +4 -2
  88. package/tests/unit/network/NetworkWalletFactory.test.js +14 -14
  89. package/tests/unit/state/apply/addAdmin/addAdminHappyPathScenario.js +6 -6
  90. package/tests/unit/state/apply/addAdmin/addAdminScenarioHelpers.js +8 -8
  91. package/tests/unit/state/apply/addAdmin/state.apply.addAdmin.test.js +6 -5
  92. package/tests/unit/state/apply/addIndexer/addIndexerScenarioHelpers.js +24 -23
  93. package/tests/unit/state/apply/addWriter/addWriterScenarioHelpers.js +10 -16
  94. package/tests/unit/state/apply/addWriter/addWriterValidatorRewardScenario.js +2 -1
  95. package/tests/unit/state/apply/adminRecovery/adminRecoveryScenarioHelpers.js +45 -41
  96. package/tests/unit/state/apply/adminRecovery/state.apply.adminRecovery.test.js +3 -7
  97. package/tests/unit/state/apply/appendWhitelist/appendWhitelistScenarioHelpers.js +17 -16
  98. package/tests/unit/state/apply/balanceInitialization/balanceInitializationScenarioHelpers.js +3 -4
  99. package/tests/unit/state/apply/balanceInitialization/nodeEntryBalanceUpdateFailureScenario.js +2 -1
  100. package/tests/unit/state/apply/banValidator/banValidatorBanAndReWhitelistScenario.js +2 -1
  101. package/tests/unit/state/apply/banValidator/banValidatorScenarioHelpers.js +23 -25
  102. package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentDuplicateRegistrationScenario.js +2 -1
  103. package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentScenarioHelpers.js +19 -18
  104. package/tests/unit/state/apply/common/access-control/adminConsistencyMismatchScenario.js +5 -4
  105. package/tests/unit/state/apply/common/access-control/adminPublicKeyDecodeFailureScenario.js +4 -3
  106. package/tests/unit/state/apply/common/balances/base/requesterBalanceScenarioBase.js +2 -1
  107. package/tests/unit/state/apply/common/commonScenarioHelper.js +3 -4
  108. package/tests/unit/state/apply/common/payload-structure/initializationDisabledScenario.js +2 -2
  109. package/tests/unit/state/apply/common/payload-structure/invalidHashValidationScenario.js +2 -2
  110. package/tests/unit/state/apply/common/requester/requesterNodeEntryBufferMissingScenario.js +2 -1
  111. package/tests/unit/state/apply/common/requester/requesterNodeEntryDecodeFailureScenario.js +2 -1
  112. package/tests/unit/state/apply/common/validatorConsistency/base/validatorConsistencyScenarioBase.js +2 -1
  113. package/tests/unit/state/apply/common/validatorEntryValidation/base/validatorEntryValidationScenarioBase.js +2 -1
  114. package/tests/unit/state/apply/disableInitialization/disableInitializationScenarioHelpers.js +11 -10
  115. package/tests/unit/state/apply/removeIndexer/removeIndexerScenarioHelpers.js +6 -5
  116. package/tests/unit/state/apply/removeWriter/removeWriterScenarioHelpers.js +6 -7
  117. package/tests/unit/state/apply/transfer/transferDoubleSpendAcrossValidatorsScenario.js +35 -34
  118. package/tests/unit/state/apply/transfer/transferScenarioHelpers.js +44 -43
  119. package/tests/unit/state/apply/txOperation/txOperationScenarioHelpers.js +26 -25
  120. package/tests/unit/state/apply/txOperation/txOperationTransferFeeGuardScenarioFactory.js +2 -1
  121. package/tests/unit/state/stateModule.test.js +0 -1
  122. package/tests/unit/state/stateTestUtils.js +7 -3
  123. package/tests/unit/state/utils/address.test.js +3 -3
  124. package/tests/unit/state/utils/adminEntry.test.js +10 -9
  125. package/tests/unit/utils/check/adminControlOperation.test.js +3 -3
  126. package/tests/unit/utils/check/balanceInitializationOperation.test.js +2 -2
  127. package/tests/unit/utils/check/bootstrapDeploymentOperation.test.js +2 -3
  128. package/tests/unit/utils/check/common.test.js +7 -6
  129. package/tests/unit/utils/check/coreAdminOperation.test.js +3 -3
  130. package/tests/unit/utils/check/roleAccessOperation.test.js +3 -2
  131. package/tests/unit/utils/check/transactionOperation.test.js +3 -3
  132. package/tests/unit/utils/check/transferOperation.test.js +3 -3
  133. package/tests/unit/utils/fileUtils/readAddressesFromWhitelistFile.test.js +2 -1
  134. package/tests/unit/utils/fileUtils/readBalanceMigrationFile.test.js +2 -1
  135. package/tests/unit/utils/migrationUtils/validateAddressFromIncomingFile.test.js +7 -0
  136. package/tests/unit/utils/utils.test.js +0 -1
  137. package/src/core/state/utils/indexerEntry.js +0 -105
  138. package/src/utils/crypto.js +0 -11
  139. package/tests/unit/state/utils/indexerEntry.test.js +0 -83
  140. package/tests/unit/state/utils/transaction.test.js +0 -97
  141. package/tests/unit/utils/crypto/createHash.test.js +0 -15
  142. /package/rpc/{constants.mjs → constants.js} +0 -0
  143. /package/rpc/{cors.mjs → cors.js} +0 -0
  144. /package/rpc/utils/{confirmedParameter.mjs → confirmedParameter.js} +0 -0
  145. /package/rpc/utils/{helpers.mjs → helpers.js} +0 -0
  146. /package/rpc/utils/{url.mjs → url.js} +0 -0
@@ -2,7 +2,6 @@ import ReadyResource from 'ready-resource';
2
2
  import Hyperswarm from 'hyperswarm';
3
3
  import w from 'protomux-wakeup';
4
4
  import b4a from 'b4a';
5
-
6
5
  import TransactionPoolService from './services/TransactionPoolService.js';
7
6
  import ValidatorObserverService from './services/ValidatorObserverService.js';
8
7
  import NetworkMessages from './messaging/NetworkMessages.js';
@@ -13,37 +12,54 @@ import {
13
12
  MAX_PARALLEL,
14
13
  MAX_SERVER_CONNECTIONS,
15
14
  MAX_CLIENT_CONNECTIONS,
16
- NETWORK_MESSAGE_TYPES,
17
- DHT_BOOTSTRAPS
15
+ NETWORK_MESSAGE_TYPES
18
16
  } from '../../utils/constants.js';
19
17
  import ConnectionManager from './services/ConnectionManager.js';
20
18
  import MessageOrchestrator from './services/MessageOrchestrator.js';
21
19
  import NetworkWalletFactory from './identity/NetworkWalletFactory.js';
20
+ import { EventType } from '../../utils/constants.js';
21
+
22
+ // -- Debug Mode --
23
+ // TODO: Implement a better debug system in the future. This is just temporary.
24
+ const DEBUG = false;
25
+ const debugLog = (...args) => {
26
+ if (DEBUG) {
27
+ console.log('DEBUG [Network] ==> ', ...args);
28
+ }
29
+ };
30
+
22
31
  const wakeup = new w();
23
32
 
24
33
  class Network extends ReadyResource {
25
- #dht_bootstrap = DHT_BOOTSTRAPS;
26
34
  #swarm = null;
27
- #enable_wallet;
28
- #channel;
29
35
  #networkMessages;
30
36
  #transactionPoolService;
31
37
  #validatorObserverService;
32
38
  #validatorConnectionManager;
33
39
  #validatorMessageOrchestrator;
34
- #options;
40
+ #config;
35
41
  #identityProvider = null;
36
-
37
- constructor(state, channel, address = null, options = {}) {
42
+ #pendingConnections;
43
+ #connectTimeoutMs;
44
+ #maxPendingConnections;
45
+
46
+ /**
47
+ * @param {State} state
48
+ * @param {object} config
49
+ * @param {string} address
50
+ **/
51
+ constructor(state, config, address = null) {
38
52
  super();
39
- this.#options = options;
40
- this.#enable_wallet = options.enable_wallet !== false;
41
- this.#channel = channel;
42
- this.#transactionPoolService = new TransactionPoolService(state, address, options);
43
- this.#validatorObserverService = new ValidatorObserverService(this, state, address, options);
44
- this.#networkMessages = new NetworkMessages(this, options);
45
- this.#validatorConnectionManager = new ConnectionManager({ maxValidators: options.max_validators });
46
- this.#validatorMessageOrchestrator = new MessageOrchestrator(this.#validatorConnectionManager, state);
53
+ this.#config = config
54
+ this.#connectTimeoutMs = config.connectTimeoutMs || 5000;
55
+ this.#maxPendingConnections = config.maxPendingConnections || 50;
56
+
57
+ this.#pendingConnections = new Map();
58
+ this.#transactionPoolService = new TransactionPoolService(state, address, this.#config);
59
+ this.#validatorObserverService = new ValidatorObserverService(this, state, address, this.#config);
60
+ this.#networkMessages = new NetworkMessages(this, this.#config);
61
+ this.#validatorConnectionManager = new ConnectionManager(this.#config);
62
+ this.#validatorMessageOrchestrator = new MessageOrchestrator(this.#validatorConnectionManager, state, this.#config);
47
63
  this.admin_stream = null;
48
64
  this.admin = null;
49
65
  this.validator = null;
@@ -55,10 +71,6 @@ class Network extends ReadyResource {
55
71
  return this.#swarm;
56
72
  }
57
73
 
58
- get channel() {
59
- return this.#channel;
60
- }
61
-
62
74
  get transactionPoolService() {
63
75
  return this.#transactionPoolService;
64
76
  }
@@ -77,6 +89,9 @@ class Network extends ReadyResource {
77
89
 
78
90
  async _open() {
79
91
  console.log('Network initialization...');
92
+
93
+ this.setupNetworkListeners();
94
+
80
95
  this.transactionPoolService.start();
81
96
  this.validatorObserverService.start();
82
97
  }
@@ -88,11 +103,53 @@ class Network extends ReadyResource {
88
103
  this.#validatorObserverService.stopValidatorObserver();
89
104
  await sleep(5_000);
90
105
 
106
+ this.cleanupNetworkListeners();
107
+ this.cleanupPendingConnections();
108
+
91
109
  if (this.#swarm !== null) {
92
110
  this.#swarm.destroy();
93
111
  }
94
112
  }
95
113
 
114
+ setupNetworkListeners() {
115
+ // VALIDATOR_CONNECTION_TIMEOUT
116
+ this.on(EventType.VALIDATOR_CONNECTION_TIMEOUT, ({ publicKey, type, timeoutMs }) => {
117
+ debugLog(`Network Event: VALIDATOR_CONNECTION_TIMEOUT | PublicKey: ${publicKey} | Type: ${type} | TimeoutMs: ${timeoutMs}`);
118
+ this.#pendingConnections.delete(publicKey);
119
+ });
120
+
121
+ // VALIDATOR_CONNECTION_READY
122
+ this.on(EventType.VALIDATOR_CONNECTION_READY, ({ publicKey, type, connection }) => {
123
+ debugLog(`Network Event: VALIDATOR_CONNECTION_READY | PublicKey: ${publicKey} | Type: ${type}`);
124
+ const { timeoutId } = this.#pendingConnections.get(publicKey);
125
+ if (!timeoutId) return;
126
+
127
+ clearTimeout(timeoutId);
128
+ this.#pendingConnections.delete(publicKey);
129
+
130
+ if (type === 'validator') {
131
+ const target = b4a.from(publicKey, 'hex');
132
+ this.#validatorConnectionManager.addValidator(target, connection);
133
+ this.#sendRequestByType(connection, type);
134
+ }
135
+ });
136
+ }
137
+
138
+ cleanupNetworkListeners() {
139
+ // connect:timeout
140
+ this.removeAllListeners('connect:timeout');
141
+
142
+ // connect:ready
143
+ this.removeAllListeners('connect:ready');
144
+ }
145
+
146
+ cleanupPendingConnections() {
147
+ for (const { timeoutId } of this.#pendingConnections.values()) {
148
+ clearTimeout(timeoutId);
149
+ }
150
+ this.#pendingConnections.clear();
151
+ }
152
+
96
153
  async replicate(
97
154
  state,
98
155
  store,
@@ -103,14 +160,14 @@ class Network extends ReadyResource {
103
160
  const wrappedWallet = this.#getNetworkWalletWrapper(wallet, keyPair);
104
161
  this.#swarm = new Hyperswarm({
105
162
  keyPair,
106
- bootstrap: this.#dht_bootstrap,
163
+ bootstrap: this.#config.dhtBootstrap,
107
164
  maxPeers: MAX_PEERS,
108
165
  maxParallel: MAX_PARALLEL,
109
166
  maxServerConnections: MAX_SERVER_CONNECTIONS,
110
167
  maxClientConnections: MAX_CLIENT_CONNECTIONS
111
168
  });
112
169
 
113
- console.log(`Channel: ${b4a.toString(this.#channel)}`);
170
+ console.log(`Channel: ${b4a.toString(this.#config.channel)}`);
114
171
  this.#networkMessages.initializeMessageRouter(state, wrappedWallet);
115
172
 
116
173
  this.#swarm.on('connection', async (connection) => {
@@ -121,6 +178,12 @@ class Network extends ReadyResource {
121
178
  const stream = store.replicate(connection);
122
179
  wakeup.addStream(stream);
123
180
 
181
+ const publicKey = b4a.toString(connection.remotePublicKey, 'hex');
182
+ if (this.#pendingConnections.has(publicKey)) {
183
+ const { type } = this.#pendingConnections.get(publicKey);
184
+ await this.#finalizeConnection(publicKey, type, connection);
185
+ }
186
+
124
187
  connection.on('close', () => {
125
188
  if (this.admin_stream === connection) {
126
189
  this.admin_stream = null;
@@ -151,13 +214,21 @@ class Network extends ReadyResource {
151
214
 
152
215
  });
153
216
 
154
- this.#swarm.join(this.#channel, { server: true, client: true });
217
+ this.#swarm.join(this.#config.channel, { server: true, client: true });
155
218
  this.#swarm.flush();
156
219
  }
157
220
  }
158
221
 
222
+ isConnectionPending(publicKey) {
223
+ return this.#pendingConnections.has(publicKey);
224
+ }
225
+
226
+ pendingConnectionsCount() {
227
+ return this.#pendingConnections.size;
228
+ }
229
+
159
230
  async initializeNetworkingKeyPair(store, wallet) {
160
- if (!this.#enable_wallet) {
231
+ if (!this.#config.enableWallet) {
161
232
  return await store.createKeyPair(TRAC_NAMESPACE);
162
233
  } else {
163
234
  return {
@@ -169,34 +240,29 @@ class Network extends ReadyResource {
169
240
 
170
241
  async tryConnect(publicKey, type = null) {
171
242
  if (this.#swarm === null) throw new Error('Network swarm is not initialized');
243
+ if (this.#pendingConnections.has(publicKey) || this.#pendingConnections.size >= this.#maxPendingConnections) {
244
+ debugLog(`Network.tryConnect: Connection to peer: ${publicKey} as type: ${type} is already pending or max pending connections reached.`);
245
+ return;
246
+ }
247
+
248
+ const timeoutId = setTimeout(() => {
249
+ if (!this.#pendingConnections.has(publicKey)) return;
250
+ this.emit(EventType.VALIDATOR_CONNECTION_TIMEOUT, { publicKey, type, timeoutMs: this.#connectTimeoutMs });
251
+ }, this.#connectTimeoutMs);
252
+ this.#pendingConnections.set(publicKey, { type, timeoutId });
172
253
 
173
254
  const target = b4a.from(publicKey, 'hex');
174
255
  if (!this.#swarm.peers.has(publicKey)) {
175
256
  this.#swarm.joinPeer(target);
176
- let cnt = 0;
177
- while (!this.#swarm.peers.has(publicKey) && cnt < 1500) { // TODO: Get rid of the magic number and add a config option for this
178
- await sleep(10);
179
- cnt += 1;
180
- }
181
257
  }
182
258
 
183
259
  const peerInfo = this.#swarm.peers.get(publicKey);
184
- if (!peerInfo) return;
185
-
186
- // Wait for the swarm to establish the connection and for protomux to attach
187
- let stream = this.#swarm._allConnections.get(peerInfo.publicKey);
188
- let attempts = 0;
189
- while ((!stream || !stream.messenger) && attempts < 1500) { // TODO: Get rid of the magic number and add a config option
190
- await sleep(10);
191
- attempts += 1;
192
- stream = this.#swarm._allConnections.get(peerInfo.publicKey);
193
- }
194
- if (!stream || !stream.messenger) return;
195
-
196
- if (type === 'validator') {
197
- this.#validatorConnectionManager.addValidator(target, stream);
260
+ if (peerInfo) {
261
+ const connection = this.#swarm._allConnections.get(peerInfo.publicKey);
262
+ if (connection && connection.messenger) {
263
+ await this.#finalizeConnection(publicKey, type, connection);
264
+ }
198
265
  }
199
- await this.#sendRequestByType(stream, type);
200
266
  }
201
267
 
202
268
  async isConnected(publicKey) {
@@ -204,6 +270,12 @@ class Network extends ReadyResource {
204
270
  this.#swarm.peers.get(publicKey).connectedTime != -1
205
271
  }
206
272
 
273
+ async #finalizeConnection(publicKey, type, connection) {
274
+ if (!this.#pendingConnections.has(publicKey)) return;
275
+ this.emit(EventType.VALIDATOR_CONNECTION_READY, { publicKey, type, connection });
276
+ debugLog(`Network.finalizeConnection: Connected to peer: ${publicKey} as type: ${type}`);
277
+ }
278
+
207
279
  async #sendRequestByType(stream, type) {
208
280
  const waitFor = {
209
281
  validator: () => this.validatorConnectionManager.connectionCount(),
@@ -231,39 +303,13 @@ class Network extends ReadyResource {
231
303
  }
232
304
  }
233
305
 
234
- async sendMessageToNode(nodePublicKey, message) {
235
- try {
236
- if (!nodePublicKey || !message) {
237
- return;
238
- }
239
- await this.tryConnect(nodePublicKey, 'node');
240
-
241
- await this.spinLock(() =>
242
- this.custom_stream === null ||
243
- !b4a.equals(this.custom_node, b4a.from(nodePublicKey, 'hex'))
244
- );
245
- if (
246
- this.custom_stream !== null &&
247
- this.custom_node !== null &&
248
- b4a.equals(this.custom_node, b4a.from(nodePublicKey, 'hex'))
249
- ) {
250
- await this.custom_stream.messenger.send(message);
251
- } else {
252
- throw new Error(`Failed to send message to node: ${nodePublicKey}`);
253
- }
254
-
255
- } catch (e) {
256
- console.log(e)
257
- }
258
- }
259
-
260
306
  #getNetworkWalletWrapper(wallet, keyPair) {
261
307
  if (!this.#identityProvider) {
262
308
  this.#identityProvider = NetworkWalletFactory.provide({
263
- enableWallet: this.#enable_wallet,
309
+ enableWallet: this.#config.enableWallet,
264
310
  wallet,
265
311
  keyPair,
266
- networkPrefix: this.#options?.networkPrefix
312
+ networkPrefix: this.#config.addressPrefix
267
313
  });
268
314
  }
269
315
  return this.#identityProvider;
@@ -1,14 +1,13 @@
1
1
  import PeerWallet from 'trac-wallet';
2
- import { TRAC_NETWORK_MSB_MAINNET_PREFIX } from 'trac-wallet/constants.js';
3
2
  import b4a from 'b4a';
4
3
 
5
4
  export class NetworkWalletFactory {
6
5
  static provide(options = {}) {
7
6
  const {
8
- enableWallet = true,
7
+ enableWallet,
9
8
  wallet,
10
9
  keyPair,
11
- networkPrefix = TRAC_NETWORK_MSB_MAINNET_PREFIX
10
+ networkPrefix
12
11
  } = options;
13
12
 
14
13
  if (enableWallet) {
@@ -34,7 +33,7 @@ class EphemeralWallet {
34
33
  #secretKey;
35
34
  #address;
36
35
 
37
- constructor(keyPair, networkPrefix = TRAC_NETWORK_MSB_MAINNET_PREFIX) {
36
+ constructor(keyPair, networkPrefix) {
38
37
 
39
38
  if (!keyPair?.publicKey || !keyPair?.secretKey) {
40
39
  throw new Error('NetworkIdentityProvider: keyPair with publicKey and secretKey is required');
@@ -3,27 +3,28 @@ import Protomux from 'protomux';
3
3
  import b4a from 'b4a';
4
4
  import c from 'compact-encoding';
5
5
  import NetworkMessageRouter from './routes/NetworkMessageRouter.js';
6
+ import Network from '../Network.js';
6
7
 
7
8
  class NetworkMessages {
8
9
  #messageRouter;
9
10
  #network;
10
- #options;
11
+ #config;
11
12
 
12
- constructor(network, options = {}) {
13
+ /**
14
+ * @param {Network} network
15
+ * @param {object} config
16
+ **/
17
+ constructor(network, config) {
13
18
  this.#network = network;
14
- this.#options = options;
15
- }
16
-
17
- get network() {
18
- return this.#network;
19
+ this.#config = config;
19
20
  }
20
21
 
21
22
  initializeMessageRouter(state, wallet) {
22
23
  this.#messageRouter = new NetworkMessageRouter(
23
- this.network,
24
+ this.#network,
24
25
  state,
25
26
  wallet,
26
- this.#options
27
+ this.#config
27
28
  );
28
29
  }
29
30
 
@@ -31,7 +32,7 @@ class NetworkMessages {
31
32
  const mux = Protomux.from(connection);
32
33
  connection.userData = mux;
33
34
  const message_channel = mux.createChannel({
34
- protocol: b4a.toString(this.network.channel, 'utf8'),
35
+ protocol: b4a.toString(this.#config.channel, 'utf8'),
35
36
  onopen() { },
36
37
  onclose() { }
37
38
  });
@@ -50,7 +51,7 @@ class NetworkMessages {
50
51
  } catch (error) {
51
52
  console.error(`NetworkMessages: Failed to handle incoming message: ${error.message}`);
52
53
  } finally {
53
- this.network.swarm.leavePeer(connection.remotePublicKey);
54
+ this.#network.swarm.leavePeer(connection.remotePublicKey);
54
55
  }
55
56
  }
56
57
  });
@@ -1,7 +1,6 @@
1
1
  import { NETWORK_MESSAGE_TYPES } from '../../../../utils/constants.js';
2
2
  import PeerWallet from 'trac-wallet';
3
3
  import b4a from 'b4a';
4
- import { blake3Hash } from '../../../../utils/crypto.js';
5
4
 
6
5
  class GetRequestHandler {
7
6
  #wallet;
@@ -44,7 +43,9 @@ class GetRequestHandler {
44
43
  timestamp: Date.now(),
45
44
  };
46
45
 
47
- const hash = await blake3Hash(JSON.stringify(payload));
46
+
47
+ const hashInput = b4a.from(JSON.stringify(payload), 'utf8');
48
+ const hash = await PeerWallet.blake3(hashInput);
48
49
  const sig = this.#wallet.sign(hash);
49
50
 
50
51
  const responseMessage = {
@@ -76,7 +77,7 @@ class GetRequestHandler {
76
77
  issuer: connection.remotePublicKey.toString('hex'),
77
78
  timestamp: Date.now(),
78
79
  };
79
- const hash = await blake3Hash(JSON.stringify(payload));
80
+ const hash = await PeerWallet.blake3(JSON.stringify(payload));
80
81
  const sig = this.#wallet.sign(hash);
81
82
 
82
83
  const responseMessage = {
@@ -97,7 +98,7 @@ class GetRequestHandler {
97
98
  timestamp: Date.now(),
98
99
  };
99
100
 
100
- const hash = await blake3Hash(JSON.stringify(payload));
101
+ const hash = await PeerWallet.blake3(JSON.stringify(payload));
101
102
  const sig = this.#wallet.sign(hash);
102
103
 
103
104
  const responseMessage = {
@@ -3,7 +3,6 @@ import ValidatorResponse from '../validators/ValidatorResponse.js';
3
3
  import AdminResponse from '../validators/AdminResponse.js';
4
4
  import CustomNodeResponse from '../validators/CustomNodeResponse.js';
5
5
  import PeerWallet from 'trac-wallet';
6
- import b4a from "b4a";
7
6
 
8
7
  class ResponseHandler {
9
8
  #network;
@@ -12,12 +11,12 @@ class ResponseHandler {
12
11
  #adminValidator;
13
12
  #customNodeValidator;
14
13
 
15
- constructor(network, state, wallet) {
14
+ constructor(network, state, wallet, config) {
16
15
  this.#network = network;
17
16
  this.#state = state;
18
- this.#responseValidator = new ValidatorResponse(this.state, wallet);
19
- this.#adminValidator = new AdminResponse(this.state, wallet);
20
- this.#customNodeValidator = new CustomNodeResponse(this.state, wallet);
17
+ this.#responseValidator = new ValidatorResponse(this.state, wallet, config);
18
+ this.#adminValidator = new AdminResponse(this.state, wallet, config);
19
+ this.#customNodeValidator = new CustomNodeResponse(this.state, wallet, config);
21
20
 
22
21
  }
23
22
 
@@ -10,20 +10,21 @@ class RoleOperationHandler extends BaseOperationHandler {
10
10
  #partialRoleAccessValidator;
11
11
  #wallet;
12
12
  #network;
13
+ #config;
13
14
 
14
- constructor(network, state, wallet, rateLimiter, options = {}) {
15
- super(network, state, wallet, rateLimiter, options);
15
+ /**
16
+ * @param {Network} network
17
+ * @param {State} state
18
+ * @param {PeerWallet} wallet
19
+ * @param {TransactionRateLimiterService} rateLimiter
20
+ * @param {object} config
21
+ **/
22
+ constructor(network, state, wallet, rateLimiter, config) {
23
+ super(network, state, wallet, rateLimiter, config);
16
24
  this.#wallet = wallet;
25
+ this.#config = config;
17
26
  this.#network = network;
18
- this.#partialRoleAccessValidator = new PartialRoleAccess(state)
19
- }
20
-
21
- get wallet() {
22
- return this.#wallet;
23
- }
24
-
25
- get network() {
26
- return this.#network;
27
+ this.#partialRoleAccessValidator = new PartialRoleAccess(state, wallet ,this.#config)
27
28
  }
28
29
 
29
30
  get partialRoleAccessValidator() {
@@ -40,8 +41,7 @@ class RoleOperationHandler extends BaseOperationHandler {
40
41
 
41
42
  switch (normalizedPartialRoleAccessPayload.type) {
42
43
  case OperationType.ADD_WRITER:
43
- completePayload = await CompleteStateMessageOperations.assembleAddWriterMessage(
44
- this.wallet,
44
+ completePayload = await new CompleteStateMessageOperations(this.#wallet, this.#config).assembleAddWriterMessage(
45
45
  normalizedPartialRoleAccessPayload.address,
46
46
  normalizedPartialRoleAccessPayload.rao.tx,
47
47
  normalizedPartialRoleAccessPayload.rao.txv,
@@ -51,8 +51,7 @@ class RoleOperationHandler extends BaseOperationHandler {
51
51
  );
52
52
  break;
53
53
  case OperationType.REMOVE_WRITER:
54
- completePayload = await CompleteStateMessageOperations.assembleRemoveWriterMessage(
55
- this.wallet,
54
+ completePayload = await new CompleteStateMessageOperations(this.#wallet, this.#config).assembleRemoveWriterMessage(
56
55
  normalizedPartialRoleAccessPayload.address,
57
56
  normalizedPartialRoleAccessPayload.rao.tx,
58
57
  normalizedPartialRoleAccessPayload.rao.txv,
@@ -62,8 +61,7 @@ class RoleOperationHandler extends BaseOperationHandler {
62
61
  );
63
62
  break;
64
63
  case OperationType.ADMIN_RECOVERY:
65
- completePayload = await CompleteStateMessageOperations.assembleAdminRecoveryMessage(
66
- this.wallet,
64
+ completePayload = await new CompleteStateMessageOperations(this.#wallet, this.#config).assembleAdminRecoveryMessage(
67
65
  normalizedPartialRoleAccessPayload.address,
68
66
  normalizedPartialRoleAccessPayload.rao.tx,
69
67
  normalizedPartialRoleAccessPayload.rao.txv,
@@ -81,7 +79,7 @@ class RoleOperationHandler extends BaseOperationHandler {
81
79
  throw new Error("OperationHandler: Assembling complete role access operation failed.");
82
80
  }
83
81
 
84
- this.network.transactionPoolService.addTransaction(completePayload)
82
+ this.#network.transactionPoolService.addTransaction(completePayload)
85
83
  }
86
84
 
87
85
  #normalizePartialRoleAccess(payload) {
@@ -107,7 +105,7 @@ class RoleOperationHandler extends BaseOperationHandler {
107
105
 
108
106
  return {
109
107
  type,
110
- address: addressToBuffer(address),
108
+ address: addressToBuffer(address, this.#config.addressPrefix),
111
109
  rao: normalizedRao
112
110
  };
113
111
  }
@@ -1,28 +1,34 @@
1
1
  import BaseOperationHandler from './base/BaseOperationHandler.js';
2
- import CompleteStateMessageOperations from "../../../../messages/completeStateMessages/CompleteStateMessageOperations.js";
2
+ import CompleteStateMessageOperations
3
+ from "../../../../messages/completeStateMessages/CompleteStateMessageOperations.js";
3
4
  import {
4
5
  OperationType
5
6
  } from '../../../../utils/constants.js';
6
7
  import PartialBootstrapDeployment from "../validators/PartialBootstrapDeployment.js";
7
- import {addressToBuffer, bufferToAddress} from "../../../state/utils/address.js";
8
+ import {addressToBuffer} from "../../../state/utils/address.js";
8
9
  import PartialTransaction from "../validators/PartialTransaction.js";
9
10
  import {normalizeHex} from "../../../../utils/helpers.js";
10
11
 
11
- /**
12
- * THIS CLASS IS ULTRA IMPORTANT BECAUSE IF SOMEONE WILL SEND A TRASH TO VALIDATOR AND IT WON'T BE HANDLED PROPERTLY -
13
- * FOR EXAMPLE VALIDATOR WILL BROADCAST IT TO THE INDEXER LAYER THEN IT WILL BE BANNED. SO EVERYTHING WHAT IS TRASH
14
- * MUST BE REFUSED.
15
- * TODO: WE SHOULD AUDIT VALIDATORS AND MAKE SURE THEY ARE NOT BROADCASTING TRASH TO THE INDEXER LAYER.
16
- */
17
12
 
18
13
  class SubnetworkOperationHandler extends BaseOperationHandler {
19
14
  #partialBootstrapDeploymentValidator;
20
15
  #partialTransactionValidator;
21
-
22
- constructor(network, state, wallet, rateLimiter, options = {}) {
23
- super(network, state, wallet, rateLimiter, options);
24
- this.#partialBootstrapDeploymentValidator = new PartialBootstrapDeployment(this.state);
25
- this.#partialTransactionValidator = new PartialTransaction(this.state);
16
+ #config;
17
+ #wallet;
18
+
19
+ /**
20
+ * @param {Network} network
21
+ * @param {State} state
22
+ * @param {PeerWallet} wallet
23
+ * @param {TransactionRateLimiterService} rateLimiter
24
+ * @param {object} config
25
+ **/
26
+ constructor(network, state, wallet, rateLimiter, config) {
27
+ super(network, state, wallet, rateLimiter, config);
28
+ this.#config = config
29
+ this.#wallet = wallet
30
+ this.#partialBootstrapDeploymentValidator = new PartialBootstrapDeployment(state, wallet, config);
31
+ this.#partialTransactionValidator = new PartialTransaction(state, wallet, config);
26
32
  }
27
33
 
28
34
  async handleOperation(payload) {
@@ -36,24 +42,24 @@ class SubnetworkOperationHandler extends BaseOperationHandler {
36
42
  }
37
43
 
38
44
  async #partialTransactionSubHandler(payload) {
39
- const normalizedPayload = this.#normalizeTransactionOperation(payload);
45
+ const normalizedPayload = this.#normalizeTransactionOperation(payload, this.#config);
40
46
  const isValid = await this.#partialTransactionValidator.validate(normalizedPayload);
41
47
  if (!isValid) {
42
48
  throw new Error("SubnetworkHandler: Transaction validation failed.");
43
49
  }
44
50
 
45
- const completeTransactionOperation = await CompleteStateMessageOperations.assembleCompleteTransactionOperationMessage(
46
- this.wallet,
47
- normalizedPayload.address,
48
- normalizedPayload.txo.tx,
49
- normalizedPayload.txo.txv,
50
- normalizedPayload.txo.iw,
51
- normalizedPayload.txo.in,
52
- normalizedPayload.txo.ch,
53
- normalizedPayload.txo.is,
54
- normalizedPayload.txo.bs,
55
- normalizedPayload.txo.mbs
56
- );
51
+ const completeTransactionOperation = await new CompleteStateMessageOperations(this.#wallet, this.#config)
52
+ .assembleCompleteTransactionOperationMessage(
53
+ normalizedPayload.address,
54
+ normalizedPayload.txo.tx,
55
+ normalizedPayload.txo.txv,
56
+ normalizedPayload.txo.iw,
57
+ normalizedPayload.txo.in,
58
+ normalizedPayload.txo.ch,
59
+ normalizedPayload.txo.is,
60
+ normalizedPayload.txo.bs,
61
+ normalizedPayload.txo.mbs
62
+ );
57
63
  this.network.transactionPoolService.addTransaction(completeTransactionOperation);
58
64
  }
59
65
 
@@ -64,16 +70,16 @@ class SubnetworkOperationHandler extends BaseOperationHandler {
64
70
  throw new Error("SubnetworkHandler: Bootstrap deployment validation failed.");
65
71
  }
66
72
 
67
- const completeBootstrapDeploymentOperation = await CompleteStateMessageOperations.assembleCompleteBootstrapDeployment(
68
- this.wallet,
69
- normalizedPayload.address,
70
- normalizedPayload.bdo.tx,
71
- normalizedPayload.bdo.txv,
72
- normalizedPayload.bdo.bs,
73
- normalizedPayload.bdo.ic,
74
- normalizedPayload.bdo.in,
75
- normalizedPayload.bdo.is,
76
- )
73
+ const completeBootstrapDeploymentOperation = await new CompleteStateMessageOperations(this.#wallet, this.#config)
74
+ .assembleCompleteBootstrapDeployment(
75
+ normalizedPayload.address,
76
+ normalizedPayload.bdo.tx,
77
+ normalizedPayload.bdo.txv,
78
+ normalizedPayload.bdo.bs,
79
+ normalizedPayload.bdo.ic,
80
+ normalizedPayload.bdo.in,
81
+ normalizedPayload.bdo.is,
82
+ )
77
83
  this.network.transactionPoolService.addTransaction(completeBootstrapDeploymentOperation);
78
84
 
79
85
  }
@@ -102,7 +108,7 @@ class SubnetworkOperationHandler extends BaseOperationHandler {
102
108
 
103
109
  return {
104
110
  type,
105
- address: addressToBuffer(address),
111
+ address: addressToBuffer(address, this.#config.addressPrefix),
106
112
  bdo: normalizedBdo
107
113
  };
108
114
  }
@@ -134,7 +140,7 @@ class SubnetworkOperationHandler extends BaseOperationHandler {
134
140
 
135
141
  return {
136
142
  type,
137
- address: addressToBuffer(address),
143
+ address: addressToBuffer(address, this.#config.addressPrefix),
138
144
  txo: normalizedTxo
139
145
  };
140
146
  }