trac-msb 0.2.6 → 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 +9 -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 +131 -72
  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 +248 -62
  34. package/src/core/network/services/MessageOrchestrator.js +83 -0
  35. package/src/core/network/services/TransactionPoolService.js +9 -8
  36. package/src/core/network/services/ValidatorObserverService.js +95 -34
  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 -9
  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 +48 -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 +41 -70
  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,34 +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';
18
+ import MessageOrchestrator from './services/MessageOrchestrator.js';
20
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
+
21
31
  const wakeup = new w();
22
32
 
23
33
  class Network extends ReadyResource {
24
- #dht_bootstrap = DHT_BOOTSTRAPS;
25
34
  #swarm = null;
26
- #enable_wallet;
27
- #channel;
28
35
  #networkMessages;
29
36
  #transactionPoolService;
30
37
  #validatorObserverService;
31
38
  #validatorConnectionManager;
32
- #options;
39
+ #validatorMessageOrchestrator;
40
+ #config;
33
41
  #identityProvider = null;
34
-
35
- 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) {
36
52
  super();
37
- this.#options = options;
38
- this.#enable_wallet = options.enable_wallet !== false;
39
- this.#channel = channel;
40
- this.#transactionPoolService = new TransactionPoolService(state, address, options);
41
- this.#validatorObserverService = new ValidatorObserverService(this, state, address, options);
42
- this.#networkMessages = new NetworkMessages(this, options);
43
- this.#validatorConnectionManager = new ConnectionManager({ maxValidators: options.max_validators });
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);
44
63
  this.admin_stream = null;
45
64
  this.admin = null;
46
65
  this.validator = null;
@@ -52,10 +71,6 @@ class Network extends ReadyResource {
52
71
  return this.#swarm;
53
72
  }
54
73
 
55
- get channel() {
56
- return this.#channel;
57
- }
58
-
59
74
  get transactionPoolService() {
60
75
  return this.#transactionPoolService;
61
76
  }
@@ -68,8 +83,15 @@ class Network extends ReadyResource {
68
83
  return this.#validatorConnectionManager;
69
84
  }
70
85
 
86
+ get validatorMessageOrchestrator() {
87
+ return this.#validatorMessageOrchestrator;
88
+ }
89
+
71
90
  async _open() {
72
91
  console.log('Network initialization...');
92
+
93
+ this.setupNetworkListeners();
94
+
73
95
  this.transactionPoolService.start();
74
96
  this.validatorObserverService.start();
75
97
  }
@@ -81,11 +103,53 @@ class Network extends ReadyResource {
81
103
  this.#validatorObserverService.stopValidatorObserver();
82
104
  await sleep(5_000);
83
105
 
106
+ this.cleanupNetworkListeners();
107
+ this.cleanupPendingConnections();
108
+
84
109
  if (this.#swarm !== null) {
85
110
  this.#swarm.destroy();
86
111
  }
87
112
  }
88
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
+
89
153
  async replicate(
90
154
  state,
91
155
  store,
@@ -96,14 +160,14 @@ class Network extends ReadyResource {
96
160
  const wrappedWallet = this.#getNetworkWalletWrapper(wallet, keyPair);
97
161
  this.#swarm = new Hyperswarm({
98
162
  keyPair,
99
- bootstrap: this.#dht_bootstrap,
163
+ bootstrap: this.#config.dhtBootstrap,
100
164
  maxPeers: MAX_PEERS,
101
165
  maxParallel: MAX_PARALLEL,
102
166
  maxServerConnections: MAX_SERVER_CONNECTIONS,
103
167
  maxClientConnections: MAX_CLIENT_CONNECTIONS
104
168
  });
105
169
 
106
- console.log(`Channel: ${b4a.toString(this.#channel)}`);
170
+ console.log(`Channel: ${b4a.toString(this.#config.channel)}`);
107
171
  this.#networkMessages.initializeMessageRouter(state, wrappedWallet);
108
172
 
109
173
  this.#swarm.on('connection', async (connection) => {
@@ -114,6 +178,12 @@ class Network extends ReadyResource {
114
178
  const stream = store.replicate(connection);
115
179
  wakeup.addStream(stream);
116
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
+
117
187
  connection.on('close', () => {
118
188
  if (this.admin_stream === connection) {
119
189
  this.admin_stream = null;
@@ -144,13 +214,21 @@ class Network extends ReadyResource {
144
214
 
145
215
  });
146
216
 
147
- this.#swarm.join(this.#channel, { server: true, client: true });
217
+ this.#swarm.join(this.#config.channel, { server: true, client: true });
148
218
  this.#swarm.flush();
149
219
  }
150
220
  }
151
221
 
222
+ isConnectionPending(publicKey) {
223
+ return this.#pendingConnections.has(publicKey);
224
+ }
225
+
226
+ pendingConnectionsCount() {
227
+ return this.#pendingConnections.size;
228
+ }
229
+
152
230
  async initializeNetworkingKeyPair(store, wallet) {
153
- if (!this.#enable_wallet) {
231
+ if (!this.#config.enableWallet) {
154
232
  return await store.createKeyPair(TRAC_NAMESPACE);
155
233
  } else {
156
234
  return {
@@ -161,27 +239,28 @@ class Network extends ReadyResource {
161
239
  }
162
240
 
163
241
  async tryConnect(publicKey, type = null) {
164
- if (null === this.#swarm) throw new Error('Network swarm is not initialized');
165
-
166
- if (false === this.#swarm.peers.has(publicKey)) {
167
- this.#swarm.joinPeer(b4a.from(publicKey, 'hex'));
168
- let cnt = 0;
169
- while (false === this.#swarm.peers.has(publicKey)) {
170
- if (cnt >= 1500) break;
171
- await sleep(10);
172
- cnt += 1;
173
- }
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;
174
246
  }
175
247
 
176
- if (this.#swarm.peers.has(publicKey)) {
177
- let stream;
178
- const peerInfo = this.#swarm.peers.get(publicKey)
179
- stream = this.#swarm._allConnections.get(peerInfo.publicKey)
180
- if (stream !== undefined && stream.messenger !== undefined) {
181
- if (type === 'validator') {
182
- this.#validatorConnectionManager.addValidator(b4a.from(publicKey, 'hex'), stream)
183
- }
184
- await this.#sendRequestByType(stream, type);
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 });
253
+
254
+ const target = b4a.from(publicKey, 'hex');
255
+ if (!this.#swarm.peers.has(publicKey)) {
256
+ this.#swarm.joinPeer(target);
257
+ }
258
+
259
+ const peerInfo = this.#swarm.peers.get(publicKey);
260
+ if (peerInfo) {
261
+ const connection = this.#swarm._allConnections.get(peerInfo.publicKey);
262
+ if (connection && connection.messenger) {
263
+ await this.#finalizeConnection(publicKey, type, connection);
185
264
  }
186
265
  }
187
266
  }
@@ -191,6 +270,12 @@ class Network extends ReadyResource {
191
270
  this.#swarm.peers.get(publicKey).connectedTime != -1
192
271
  }
193
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
+
194
279
  async #sendRequestByType(stream, type) {
195
280
  const waitFor = {
196
281
  validator: () => this.validatorConnectionManager.connectionCount(),
@@ -207,7 +292,7 @@ class Network extends ReadyResource {
207
292
  } else {
208
293
  return;
209
294
  }
210
- await this.spinLock(() => !waitFor)
295
+ await this.spinLock(() => !waitFor())
211
296
  };
212
297
 
213
298
  async spinLock(conditionFn, maxIterations = 1500, intervalMs = 10) {
@@ -218,39 +303,13 @@ class Network extends ReadyResource {
218
303
  }
219
304
  }
220
305
 
221
- async sendMessageToNode(nodePublicKey, message) {
222
- try {
223
- if (!nodePublicKey || !message) {
224
- return;
225
- }
226
- await this.tryConnect(nodePublicKey, 'node');
227
-
228
- await this.spinLock(() =>
229
- this.custom_stream === null ||
230
- !b4a.equals(this.custom_node, b4a.from(nodePublicKey, 'hex'))
231
- );
232
- if (
233
- this.custom_stream !== null &&
234
- this.custom_node !== null &&
235
- b4a.equals(this.custom_node, b4a.from(nodePublicKey, 'hex'))
236
- ) {
237
- await this.custom_stream.messenger.send(message);
238
- } else {
239
- throw new Error(`Failed to send message to node: ${nodePublicKey}`);
240
- }
241
-
242
- } catch (e) {
243
- console.log(e)
244
- }
245
- }
246
-
247
306
  #getNetworkWalletWrapper(wallet, keyPair) {
248
307
  if (!this.#identityProvider) {
249
308
  this.#identityProvider = NetworkWalletFactory.provide({
250
- enableWallet: this.#enable_wallet,
309
+ enableWallet: this.#config.enableWallet,
251
310
  wallet,
252
311
  keyPair,
253
- networkPrefix: this.#options?.networkPrefix
312
+ networkPrefix: this.#config.addressPrefix
254
313
  });
255
314
  }
256
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
  }