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,6 +2,17 @@ import PartialStateMessageBuilder from './PartialStateMessageBuilder.js';
2
2
  import PartialStateMessageDirector from './PartialStateMessageDirector.js';
3
3
 
4
4
  class PartialStateMessageOperations {
5
+ #wallet;
6
+ #config
7
+
8
+ /**
9
+ * @param {PeerWallet} wallet - Wallet of the requester/invoker node that broadcasts the operation
10
+ * @param {object} config - A configuration object
11
+ */
12
+ constructor(wallet, config) {
13
+ this.#wallet = wallet;
14
+ this.#config = config;
15
+ }
5
16
 
6
17
  /**
7
18
  * Assembles a PARTIAL bootstrap deployment operation, which can be sent to a validator.
@@ -9,8 +20,6 @@ class PartialStateMessageOperations {
9
20
  * Bootstrap deployment is required to register a subnetwork. The network will reject
10
21
  * TransactionOperation messages for external bootstraps that are not registered.
11
22
  * Do NOT attempt to register the MSB bootstrap key.
12
- *
13
- * @param {Object} wallet - Wallet of the requester/invoker node that broadcasts the operation
14
23
  * @param {String} externalBootstrap - Bootstrap key from the subnetwork to be registered.
15
24
  * MUST be different from the MSB bootstrap key.
16
25
  * BEFORE deploying ensure if the subnetwork bootstrap is not already deployed.
@@ -20,13 +29,13 @@ class PartialStateMessageOperations {
20
29
  * @returns {Promise<Object>} The assembled bootstrap deployment operation message
21
30
  * @throws {Error} If assembly of the bootstrap deployment operation message fails
22
31
  */
23
- static async assembleBootstrapDeploymentMessage(wallet, externalBootstrap, channel, txValidity) {
32
+ async assembleBootstrapDeploymentMessage(externalBootstrap, channel, txValidity) {
24
33
  try {
25
- const builder = new PartialStateMessageBuilder(wallet);
34
+ const builder = new PartialStateMessageBuilder(this.#wallet, this.#config);
26
35
  const director = new PartialStateMessageDirector();
27
36
  director.builder = builder;
28
37
  return await director.buildPartialBootstrapDeploymentMessage(
29
- wallet.address,
38
+ this.#wallet.address,
30
39
  externalBootstrap,
31
40
  channel,
32
41
  txValidity
@@ -36,34 +45,34 @@ class PartialStateMessageOperations {
36
45
  }
37
46
  }
38
47
 
39
- static async assembleAddWriterMessage(wallet, writingKey, txValidity) {
48
+ async assembleAddWriterMessage(writingKey, txValidity) {
40
49
  try {
41
- const builder = new PartialStateMessageBuilder(wallet);
50
+ const builder = new PartialStateMessageBuilder(this.#wallet, this.#config);
42
51
  const director = new PartialStateMessageDirector();
43
52
  director.builder = builder;
44
- return await director.buildAddWriterMessage(wallet.address, writingKey, txValidity);
53
+ return await director.buildAddWriterMessage(this.#wallet.address, writingKey, txValidity);
45
54
  } catch (error) {
46
55
  throw new Error(`Failed to assemble add writer message: ${error.message}`);
47
56
  }
48
57
  }
49
58
 
50
- static async assembleRemoveWriterMessage(wallet, writerKey, txValidity) {
59
+ async assembleRemoveWriterMessage(writerKey, txValidity) {
51
60
  try {
52
- const builder = new PartialStateMessageBuilder(wallet);
61
+ const builder = new PartialStateMessageBuilder(this.#wallet, this.#config);
53
62
  const director = new PartialStateMessageDirector();
54
63
  director.builder = builder;
55
- return await director.buildRemoveWriterMessage(wallet.address, writerKey, txValidity);
64
+ return await director.buildRemoveWriterMessage(this.#wallet.address, writerKey, txValidity);
56
65
  } catch (error) {
57
66
  throw new Error(`Failed to assemble remove writer message: ${error.message}`);
58
67
  }
59
68
  }
60
69
 
61
- static async assembleAdminRecoveryMessage(wallet, writingKey, txValidity) {
70
+ async assembleAdminRecoveryMessage(writingKey, txValidity) {
62
71
  try {
63
- const builder = new PartialStateMessageBuilder(wallet);
72
+ const builder = new PartialStateMessageBuilder(this.#wallet, this.#config);
64
73
  const director = new PartialStateMessageDirector();
65
74
  director.builder = builder;
66
- return await director.buildAdminRecoveryMessage(wallet.address, writingKey, txValidity);
75
+ return await director.buildAdminRecoveryMessage(this.#wallet.address, writingKey, txValidity);
67
76
  } catch (error) {
68
77
  throw new Error(`Failed to assemble admin recovery message: ${error.message}`);
69
78
  }
@@ -73,8 +82,6 @@ class PartialStateMessageOperations {
73
82
  /**
74
83
  * Assembles a PARTIAL transaction operation, which can be sent to a validator, who can then
75
84
  * sign the transaction to make it COMPLETE.
76
- *
77
- * @param {Object} wallet - Wallet of the requester/invoker node that broadcasts the transaction
78
85
  * @param {String} incomingWritingKey - Writing key from the subnetwork, used for authentication of the requesting node
79
86
  * @param {String} txValidity - Transaction validity hash representing current indexer combination.
80
87
  * Transaction remains valid as long as indexer keys maintain their order.
@@ -91,13 +98,13 @@ class PartialStateMessageOperations {
91
98
  * @returns {Promise<Object>} The assembled transaction operation message
92
99
  * @throws {Error} If assembly of the transaction operation message fails
93
100
  */
94
- static async assembleTransactionOperationMessage(wallet, incomingWritingKey, txValidity, contentHash, externalBootstrap, msbBootstrap) {
101
+ async assembleTransactionOperationMessage(incomingWritingKey, txValidity, contentHash, externalBootstrap, msbBootstrap) {
95
102
  try {
96
- const builder = new PartialStateMessageBuilder(wallet);
103
+ const builder = new PartialStateMessageBuilder(this.#wallet, this.#config);
97
104
  const director = new PartialStateMessageDirector();
98
105
  director.builder = builder;
99
106
  return await director.buildTransactionOperationMessage(
100
- wallet.address,
107
+ this.#wallet.address,
101
108
  incomingWritingKey,
102
109
  txValidity,
103
110
  contentHash,
@@ -109,13 +116,13 @@ class PartialStateMessageOperations {
109
116
  }
110
117
  }
111
118
 
112
- static async assembleTransferOperationMessage(wallet, recipientAddress, amount, txValidity) {
119
+ async assembleTransferOperationMessage(recipientAddress, amount, txValidity) {
113
120
  try {
114
- const builder = new PartialStateMessageBuilder(wallet);
121
+ const builder = new PartialStateMessageBuilder(this.#wallet, this.#config);
115
122
  const director = new PartialStateMessageDirector();
116
123
  director.builder = builder;
117
124
  return await director.buildTransferOperationMessage(
118
- wallet.address,
125
+ this.#wallet.address,
119
126
  recipientAddress,
120
127
  amount,
121
128
  txValidity
@@ -10,9 +10,7 @@ import {
10
10
  BOOTSTRAP_BYTE_LENGTH,
11
11
  CHANNEL_BYTE_LENGTH,
12
12
  AMOUNT_BYTE_LENGTH,
13
- TRAC_ADDRESS_SIZE,
14
13
  } from './constants.js';
15
-
16
14
  //TODO: ATTENTION - CURRENT IMPLEMENTATION UTILIZES `custom` FOR MULTIPLE TIMES IN MANY SCHEMAS. IT SHOULD BE CLEANED UP
17
15
  // TO UTILIZE ONLY ONE FUNCTION COMMON FOR ALL THE SCHEMAS. CREATE A TICKED P2/P3.
18
16
 
@@ -25,8 +23,13 @@ class Check {
25
23
  #validateTransactionOperationSchema
26
24
  #validateTransferOperationSchema
27
25
  #validateBalanceInitializationSchema
26
+ #config
28
27
 
29
- constructor() {
28
+ /**
29
+ * @param {object} config
30
+ **/
31
+ constructor(config) {
32
+ this.#config = config
30
33
 
31
34
  this.#validator = new Validator({
32
35
  useNewCustomCheckerFunction: true,
@@ -101,6 +104,7 @@ class Check {
101
104
 
102
105
  // Complete by default - no writer needed
103
106
  #compileCoreAdminOperationSchema() {
107
+ const addressLength = this.#config.addressLength
104
108
  const schema = {
105
109
  $$strict: true,
106
110
  type: {
@@ -124,7 +128,7 @@ class Check {
124
128
  return value;
125
129
  }
126
130
  },
127
- address: { type: 'buffer', length: TRAC_ADDRESS_SIZE, required: true }, // invoker adddress (admin)
131
+ address: {type: 'buffer', length: addressLength, required: true}, // invoker adddress (admin)
128
132
  cao: {
129
133
  strict: true,
130
134
  type: 'object',
@@ -163,14 +167,14 @@ class Check {
163
167
  return value;
164
168
  }
165
169
  },
166
- address: { type: 'buffer', length: TRAC_ADDRESS_SIZE, required: true },
170
+ address: { type: 'buffer', length: this.#config.addressLength, required: true },
167
171
  bio: {
168
172
  strict: true,
169
173
  type: 'object',
170
174
  props: {
171
175
  tx: { type: 'buffer', length: HASH_BYTE_LENGTH, required: true }, // tx hash
172
176
  txv: { type: 'buffer', length: HASH_BYTE_LENGTH, required: true }, // tx validity
173
- ia: { type: 'buffer', length: TRAC_ADDRESS_SIZE, required: true }, // selected address to specific operation.
177
+ ia: { type: 'buffer', length: this.#config.addressLength, required: true }, // selected address to specific operation.
174
178
  am: { type: 'buffer', length: AMOUNT_BYTE_LENGTH, required: true }, // amount to transfer
175
179
  in: { type: 'buffer', length: NONCE_BYTE_LENGTH, required: true }, // nonce of the invoker
176
180
  is: { type: 'buffer', length: SIGNATURE_BYTE_LENGTH, required: true }, // signature of the invoker
@@ -211,14 +215,14 @@ class Check {
211
215
  return value;
212
216
  }
213
217
  },
214
- address: { type: 'buffer', length: TRAC_ADDRESS_SIZE, required: true }, // invoker adddress (admin)
218
+ address: {type: 'buffer', length: this.#config.addressLength, required: true}, // invoker adddress (admin)
215
219
  aco: {
216
220
  strict: true,
217
221
  type: 'object',
218
222
  props: {
219
223
  tx: { type: 'buffer', length: HASH_BYTE_LENGTH, required: true }, // tx hash
220
224
  txv: { type: 'buffer', length: HASH_BYTE_LENGTH, required: true }, // tx validity
221
- ia: { type: 'buffer', length: TRAC_ADDRESS_SIZE, required: true }, // incoming address - selected address for specific operation
225
+ ia: { type: 'buffer', length: this.#config.addressLength, required: true }, // incoming address - selected address for specific operation
222
226
  in: { type: 'buffer', length: NONCE_BYTE_LENGTH, required: true }, // nonce
223
227
  is: { type: 'buffer', length: SIGNATURE_BYTE_LENGTH, required: true }, // signature
224
228
  }
@@ -256,7 +260,7 @@ class Check {
256
260
  return value;
257
261
  }
258
262
  },
259
- address: { type: 'buffer', length: TRAC_ADDRESS_SIZE, required: true },
263
+ address: {type: 'buffer', length: this.#config.addressLength, required: true},
260
264
  rao: {
261
265
  strict: true,
262
266
  type: 'object',
@@ -266,7 +270,7 @@ class Check {
266
270
  iw: { type: 'buffer', length: WRITER_BYTE_LENGTH, required: true }, // writing key of the invoker
267
271
  in: { type: 'buffer', length: NONCE_BYTE_LENGTH, required: true }, // nonce of the invoker
268
272
  is: { type: 'buffer', length: SIGNATURE_BYTE_LENGTH, required: true }, // signature
269
- va: { type: 'buffer', length: TRAC_ADDRESS_SIZE, optional: true },
273
+ va: { type: 'buffer', length: this.#config.addressLength, optional: true },
270
274
  vn: { type: 'buffer', length: NONCE_BYTE_LENGTH, optional: true },
271
275
  vs: { type: 'buffer', length: SIGNATURE_BYTE_LENGTH, optional: true }
272
276
 
@@ -325,7 +329,7 @@ class Check {
325
329
  return value;
326
330
  }
327
331
  },
328
- address: { type: 'buffer', length: TRAC_ADDRESS_SIZE, required: true }, // invoker address
332
+ address: {type: 'buffer', length: this.#config.addressLength, required: true}, // invoker address
329
333
  txo: {
330
334
  strict: true,
331
335
  type: 'object',
@@ -338,7 +342,7 @@ class Check {
338
342
  mbs: { type: 'buffer', length: BOOTSTRAP_BYTE_LENGTH, required: true }, // MSB bootstrap key
339
343
  in: { type: 'buffer', length: NONCE_BYTE_LENGTH, required: true }, // Nonce of the requesting node
340
344
  is: { type: 'buffer', length: SIGNATURE_BYTE_LENGTH, required: true }, // Requester's signature
341
- va: { type: 'buffer', length: TRAC_ADDRESS_SIZE, optional: true }, //validator address
345
+ va: { type: 'buffer', length: this.#config.addressLength, optional: true }, //validator address
342
346
  vn: { type: 'buffer', length: NONCE_BYTE_LENGTH, optional: true }, //validator nonce
343
347
  vs: { type: 'buffer', length: SIGNATURE_BYTE_LENGTH, optional: true }, //validator signature
344
348
  },
@@ -396,7 +400,7 @@ class Check {
396
400
  return value;
397
401
  }
398
402
  },
399
- address: { type: 'buffer', length: TRAC_ADDRESS_SIZE, required: true },
403
+ address: {type: 'buffer', length: this.#config.addressLength, required: true},
400
404
  bdo: {
401
405
 
402
406
  strict: true,
@@ -408,7 +412,7 @@ class Check {
408
412
  ic: { type: 'buffer', length: CHANNEL_BYTE_LENGTH, required: true },
409
413
  in: { type: 'buffer', length: NONCE_BYTE_LENGTH, required: true },
410
414
  is: { type: 'buffer', length: SIGNATURE_BYTE_LENGTH, required: true },
411
- va: { type: 'buffer', length: TRAC_ADDRESS_SIZE, optional: true },
415
+ va: { type: 'buffer', length: this.#config.addressLength, optional: true },
412
416
  vn: { type: 'buffer', length: NONCE_BYTE_LENGTH, optional: true },
413
417
  vs: { type: 'buffer', length: SIGNATURE_BYTE_LENGTH, optional: true },
414
418
  },
@@ -466,18 +470,18 @@ class Check {
466
470
  return value;
467
471
  }
468
472
  },
469
- address: { type: 'buffer', length: TRAC_ADDRESS_SIZE, required: true },
473
+ address: {type: 'buffer', length: this.#config.addressLength, required: true},
470
474
  tro: {
471
475
  strict: true,
472
476
  type: 'object',
473
477
  props: {
474
478
  tx: { type: 'buffer', length: HASH_BYTE_LENGTH, required: true }, // tx hash
475
479
  txv: { type: 'buffer', length: HASH_BYTE_LENGTH, required: true }, // tx validity
476
- to: { type: 'buffer', length: TRAC_ADDRESS_SIZE, required: true }, // recipient address
480
+ to: { type: 'buffer', length: this.#config.addressLength, required: true }, // recipient address
477
481
  am: { type: 'buffer_amount', length: AMOUNT_BYTE_LENGTH, required: true }, // amount to transfer
478
482
  in: { type: 'buffer', length: NONCE_BYTE_LENGTH, required: true }, // nonce of the invoker
479
483
  is: { type: 'buffer', length: SIGNATURE_BYTE_LENGTH, required: true }, // signature of the invoker
480
- va: { type: 'buffer', length: TRAC_ADDRESS_SIZE, optional: true }, // validator address
484
+ va: { type: 'buffer', length: this.#config.addressLength, optional: true }, // validator address
481
485
  vn: { type: 'buffer', length: NONCE_BYTE_LENGTH, optional: true }, // validator nonce
482
486
  vs: { type: 'buffer', length: SIGNATURE_BYTE_LENGTH, optional: true } // validator signature
483
487
 
@@ -83,20 +83,20 @@ export async function coreInfoCommand(state) {
83
83
  }
84
84
  }
85
85
 
86
- export async function getValidatorAddressCommand(state, wkHexString) {
86
+ export async function getValidatorAddressCommand(state, wkHexString, prefix) {
87
87
  const payload = await state.getSigned(EntryType.WRITER_ADDRESS + wkHexString);
88
88
  if (payload === null) {
89
89
  console.log(`No address assigned to the writer key: ${wkHexString}`);
90
90
  } else {
91
- console.log(`Address assigned to the writer key: ${wkHexString} - ${bufferToAddress(payload)}`);
91
+ console.log(`Address assigned to the writer key: ${wkHexString} - ${bufferToAddress(payload, prefix)}`);
92
92
  }
93
93
  }
94
94
 
95
- export async function getDeploymentCommand(state, bootstrapHex) {
95
+ export async function getDeploymentCommand(state, bootstrapHex, addressLength) {
96
96
  const deploymentEntry = await state.getRegisteredBootstrapEntry(bootstrapHex);
97
97
  console.log(`Searching deployment for bootstrap: ${bootstrapHex}`);
98
98
  if (deploymentEntry) {
99
- const decodedDeploymentEntry = deploymentEntryUtils.decode(deploymentEntry);
99
+ const decodedDeploymentEntry = deploymentEntryUtils.decode(deploymentEntry, addressLength);
100
100
  const txhash = decodedDeploymentEntry.txHash.toString("hex");
101
101
  console.log(`Bootstrap deployed under transaction hash: ${txhash}`);
102
102
  const payload = await state.getSigned(txhash);
@@ -189,7 +189,7 @@ export function getUnconfirmedLengthCommand(state) {
189
189
  return unconfirmedLength;
190
190
  }
191
191
 
192
- export async function getTxPayloadsBulkCommand(state, hashes) {
192
+ export async function getTxPayloadsBulkCommand(state, hashes, config) {
193
193
  if (!Array.isArray(hashes) || hashes.length === 0) {
194
194
  throw new Error("Missing hash list.");
195
195
  }
@@ -208,7 +208,7 @@ export async function getTxPayloadsBulkCommand(state, hashes) {
208
208
  if (result === null || result === undefined) {
209
209
  res.missing.push(hash);
210
210
  } else {
211
- const decodedResult = normalizeDecodedPayloadForJson(result.decoded);
211
+ const decodedResult = normalizeDecodedPayloadForJson(result.decoded, config);
212
212
  res.results.push({ hash, payload: decodedResult });
213
213
  }
214
214
  });
@@ -225,20 +225,20 @@ export async function getTxHashesCommand(state, start, end) {
225
225
  }
226
226
  }
227
227
 
228
- export async function getTxDetailsCommand(state, hash) {
228
+ export async function getTxDetailsCommand(state, hash, config) {
229
229
  try {
230
230
  const rawPayload = await get_confirmed_tx_info(state, hash);
231
231
  if (!rawPayload) {
232
232
  console.log(`No payload found for tx hash: ${hash}`);
233
233
  return null;
234
234
  }
235
- return normalizeDecodedPayloadForJson(rawPayload.decoded);
235
+ return normalizeDecodedPayloadForJson(rawPayload.decoded, config);
236
236
  } catch (error) {
237
237
  throw new Error("Invalid params to perform the request.", error.message);
238
238
  }
239
239
  }
240
240
 
241
- export async function getExtendedTxDetailsCommand(state, hash, confirmed) {
241
+ export async function getExtendedTxDetailsCommand(state, hash, confirmed, config) {
242
242
  if (confirmed) {
243
243
  const rawPayload = await get_confirmed_tx_info(state, hash);
244
244
  if (!rawPayload) {
@@ -248,7 +248,7 @@ export async function getExtendedTxDetailsCommand(state, hash, confirmed) {
248
248
  if (confirmedLength === null) {
249
249
  throw new Error(`No confirmed length found for tx hash: ${hash} in confirmed mode`);
250
250
  }
251
- const normalizedPayload = normalizeDecodedPayloadForJson(rawPayload.decoded, true);
251
+ const normalizedPayload = normalizeDecodedPayloadForJson(rawPayload.decoded, config);
252
252
  const fee = state.getFee();
253
253
  return {
254
254
  txDetails: normalizedPayload,
@@ -261,7 +261,7 @@ export async function getExtendedTxDetailsCommand(state, hash, confirmed) {
261
261
  if (!rawPayload) {
262
262
  throw new Error(`No payload found for tx hash: ${hash}`);
263
263
  }
264
- const normalizedPayload = normalizeDecodedPayloadForJson(rawPayload.decoded, true);
264
+ const normalizedPayload = normalizeDecodedPayloadForJson(rawPayload.decoded, config);
265
265
  const length = await state.getTransactionConfirmedLength(hash);
266
266
  if (length === null) {
267
267
  return {
@@ -40,6 +40,8 @@ export const EventType = Object.freeze({
40
40
  WRITABLE: 'writable',
41
41
  UNWRITABLE: 'unwritable',
42
42
  WARNING: 'warning',
43
+ VALIDATOR_CONNECTION_READY: 'validator-connection-ready',
44
+ VALIDATOR_CONNECTION_TIMEOUT: 'validator-connection-timeout',
43
45
  });
44
46
 
45
47
  // Role managment constants
@@ -66,7 +68,6 @@ export const MAX_PEERS = 64;
66
68
  export const MAX_PARALLEL = 64;
67
69
  export const MAX_SERVER_CONNECTIONS = Infinity;
68
70
  export const MAX_CLIENT_CONNECTIONS = Infinity;
69
- export const DHT_BOOTSTRAPS = ['116.202.214.149:10001', '157.180.12.214:10001', 'node1.hyperdht.org:49737', 'node2.hyperdht.org:49737', 'node3.hyperdht.org:49737'];
70
71
  export const MAX_WRITERS_FOR_ADMIN_INDEXER_CONNECTION = 10;
71
72
  // State
72
73
  export const ACK_INTERVAL = 1_000;
@@ -119,11 +120,3 @@ export const NETWORK_MESSAGE_TYPES = Object.freeze({
119
120
  NODE: 'nodeResponse'
120
121
  },
121
122
  });
122
-
123
- export const TRAC_ADDRESS_SIZE = 63; // TODO: Change this to config().addressLength || 63
124
- export const NETWORK_ID = 918; // TODO: Change this to config().network_id || 918
125
-
126
- export const MAX_VALIDATORS = 50
127
- export const MAX_RETRIES = 3
128
-
129
- export const MAX_REQUEST_COUNT = 5;
@@ -1,11 +1,8 @@
1
1
  import fs from 'fs'; // TODO: If we are using bare environment, we should use bare-fs instead
2
2
  import path from 'path';
3
3
  import { WHITELIST_FILEPATH, BALANCE_MIGRATION_FILEPATH, BALANCE_MIGRATED_DIR, WHITELIST_MIGRATION_DIR } from '../utils/constants.js';
4
- import { isAddressValid } from '../core/state/utils/address.js';
5
4
  import { decimalStringToBigInt, bigIntTo16ByteBuffer, bufferToBigInt, bigIntToDecimalString } from './amountSerialization.js';
6
- import PeerWallet from 'trac-wallet';
7
- import b4a from 'b4a';
8
- import { ZERO_LICENSE } from '../core/state/utils/nodeEntry.js';
5
+
9
6
  const MIGRATED_FILE_REGEX = /^migrated(\d+)\.csv$/;
10
7
 
11
8
  /**
@@ -1,6 +1,6 @@
1
1
  import b4a from "b4a";
2
2
  import {bufferToAddress} from "../core/state/utils/address.js";
3
- import { EntryType, TRAC_ADDRESS_SIZE } from "./constants.js";
3
+ import { EntryType } from "./constants.js";
4
4
 
5
5
  //TODO: change file name or split functions below into multiple files (Remember to update imports and tests accordingly)
6
6
 
@@ -48,7 +48,7 @@ export const safeJsonParse = (str) => {
48
48
  return undefined;
49
49
  }
50
50
 
51
- export async function getFormattedIndexersWithAddresses(state) {
51
+ export async function getFormattedIndexersWithAddresses(state, config) {
52
52
  const indexers = await state.getIndexersEntry();
53
53
  const formatted = indexers.map((entry) => ({
54
54
  writingKey: b4a.toString(entry.key, "hex"),
@@ -56,7 +56,10 @@ export async function getFormattedIndexersWithAddresses(state) {
56
56
 
57
57
  const results = await Promise.all(
58
58
  formatted.map(async (entry) => {
59
- const address = bufferToAddress(await state.getSigned(EntryType.WRITER_ADDRESS + entry.writingKey));
59
+ const address = bufferToAddress(
60
+ await state.getSigned(EntryType.WRITER_ADDRESS + entry.writingKey),
61
+ config.addressPrefix
62
+ );
60
63
 
61
64
  return {
62
65
  ...entry,
@@ -68,14 +71,14 @@ export async function getFormattedIndexersWithAddresses(state) {
68
71
  return results;
69
72
  }
70
73
 
71
- export function formatIndexersEntry(indexersEntry) {
74
+ export function formatIndexersEntry(indexersEntry, addressLength) {
72
75
 
73
76
  const count = indexersEntry[0];
74
77
  const indexers = [];
75
78
 
76
79
  for (let i = 0; i < count; i++) {
77
- const start = 1 + (i * TRAC_ADDRESS_SIZE);
78
- const end = start + TRAC_ADDRESS_SIZE;
80
+ const start = 1 + (i * addressLength);
81
+ const end = start + addressLength;
79
82
  const indexerAddr = indexersEntry.subarray(start, end);
80
83
  indexers.push(indexerAddr.toString('ascii'));
81
84
  }
@@ -86,20 +89,6 @@ export function formatIndexersEntry(indexersEntry) {
86
89
  };
87
90
  }
88
91
 
89
- export function convertAdminCoreOperationPayloadToHex(payload) {
90
- return {
91
- ...payload,
92
- address: bufferToAddress(payload.address),
93
- aco: {
94
- tx: payload.aco.tx.toString('hex'),
95
- txv: payload.aco.txv.toString('hex'),
96
- in: payload.aco.in.toString('hex'),
97
- ia: payload.aco.ia.toString('hex'),
98
- is: payload.aco.is.toString('hex'),
99
- },
100
- };
101
- }
102
-
103
92
  export function isTransactionRecordPut(entry) {
104
93
  const isPut = entry.type === "put";
105
94
  const isHex = isHexString(entry.key);
@@ -4,8 +4,8 @@ import PeerWallet from 'trac-wallet';
4
4
  import b4a from 'b4a';
5
5
  import { ZERO_LICENSE } from '../core/state/utils/nodeEntry.js';
6
6
 
7
- export async function validateAddressFromIncomingFile(stateInstance, address, adminEntry) {
8
- if (!isAddressValid(address)) {
7
+ export async function validateAddressFromIncomingFile(stateInstance, config, address, adminEntry) {
8
+ if (!isAddressValid(address, config.addressPrefix)) {
9
9
  throw new Error(`Invalid address format: '${address}'. Please ensure all addresses are valid.`);
10
10
  }
11
11
 
@@ -10,10 +10,11 @@ import { bufferToBigInt } from './amountSerialization.js'
10
10
  * to the correct buffer or hexadecimal string format for processing.
11
11
  *
12
12
  * @param {Object} payload The raw payload for the transfer operation.
13
+ * @param {object} config The environment configuration object.
13
14
  * @returns {Object} A new object with addresses converted to buffers and hex values normalized.
14
15
  * @throws {Error} If the payload is invalid or missing required fields.
15
16
  */
16
- export function normalizeTransferOperation(payload) {
17
+ export function normalizeTransferOperation(payload, config) {
17
18
  if (!payload || typeof payload !== 'object' || !payload.tro) {
18
19
  throw new Error('Invalid payload for transfer operation normalization.');
19
20
  }
@@ -31,19 +32,19 @@ export function normalizeTransferOperation(payload) {
31
32
  tx: normalizeHex(tro.tx), // Transaction hash
32
33
  txv: normalizeHex(tro.txv), // Transaction validity
33
34
  in: normalizeHex(tro.in), // Nonce
34
- to: addressToBuffer(tro.to), // Recipient address
35
+ to: addressToBuffer(tro.to, config.addressPrefix), // Recipient address
35
36
  am: normalizeHex(tro.am), // Amount
36
37
  is: normalizeHex(tro.is) // Signature
37
38
  };
38
39
 
39
40
  return {
40
41
  type,
41
- address: addressToBuffer(address),
42
+ address: addressToBuffer(address, config.addressPrefix),
42
43
  tro: normalizedTro
43
44
  };
44
45
  }
45
46
 
46
- export function normalizeTransactionOperation(payload) {
47
+ export function normalizeTransactionOperation(payload, config) {
47
48
  if (!payload || typeof payload !== 'object' || !payload.txo) {
48
49
  throw new Error('Invalid payload for transaction operation normalization.');
49
50
  }
@@ -70,7 +71,7 @@ export function normalizeTransactionOperation(payload) {
70
71
 
71
72
  return {
72
73
  type,
73
- address: addressToBuffer(address),
74
+ address: addressToBuffer(address, config.addressPrefix),
74
75
  txo: normalizedTxo
75
76
  };
76
77
  }
@@ -82,7 +83,7 @@ export function normalizeTransactionOperation(payload) {
82
83
  * @param {Object} payload The decoded transaction payload.
83
84
  * @returns {Object} A new object with Buffer values converted to hex strings.
84
85
  */
85
- export function normalizeDecodedPayloadForJson(payload) {
86
+ export function normalizeDecodedPayloadForJson(payload, config) {
86
87
  if (!payload || typeof payload !== "object") {
87
88
  return payload;
88
89
  }
@@ -96,7 +97,7 @@ export function normalizeDecodedPayloadForJson(payload) {
96
97
  if (b4a.isBuffer(value)) {
97
98
  // 👇 intercept address buffers by key name (e.g. `address`)
98
99
  if (addressKeys.some(k => key.toLowerCase().includes(k))) {
99
- const addr = bufferToAddress(value);
100
+ const addr = bufferToAddress(value, config.addressPrefix);
100
101
  newPayload[key] = addr ?? b4a.toString(value, "hex");
101
102
  } else if (key.toLowerCase().includes("am")) {
102
103
  const amount = bufferToBigInt(value)
@@ -107,7 +108,7 @@ export function normalizeDecodedPayloadForJson(payload) {
107
108
 
108
109
  } else if (typeof value === "object" && value !== null) {
109
110
  // recursively handle nested objects
110
- newPayload[key] = normalizeDecodedPayloadForJson(value);
111
+ newPayload[key] = normalizeDecodedPayloadForJson(value, config);
111
112
 
112
113
  } else {
113
114
  newPayload[key] = value;
@@ -115,4 +116,4 @@ export function normalizeDecodedPayloadForJson(payload) {
115
116
  }
116
117
  }
117
118
  return newPayload;
118
- }
119
+ }
@@ -1,6 +1,6 @@
1
1
  import request from "supertest"
2
2
  import { bufferToBigInt, licenseBufferToBigInt } from "../../../../src/utils/amountSerialization.js"
3
- import { ZERO_WK } from "../../../../rpc/constants.mjs"
3
+ import { ZERO_WK } from "../../../../rpc/constants.js"
4
4
  import { ADMIN_INITIAL_STAKED_BALANCE } from "../../../../src/utils/constants.js"
5
5
  import { BALANCE_TO_STAKE } from "../../../../src/core/state/utils/balance.js"
6
6
  import { randomAddress } from "../../../unit/state/stateTestUtils.js"
@@ -72,7 +72,7 @@ export const registerAccountTests = (context) => {
72
72
  })
73
73
 
74
74
  it("returns default state for non-existent node", async () => {
75
- const address = randomAddress()
75
+ const address = randomAddress(context.rpcMsb.config.addressPrefix)
76
76
 
77
77
  const res = await request(context.server).get(`/v1/account/${address}`)
78
78
  expect(res.statusCode).toBe(200)
@@ -37,7 +37,7 @@ export const registerBalanceTests = (context) => {
37
37
  })
38
38
 
39
39
  it("returns zero balance for an unknown address", async () => {
40
- const address = randomAddress()
40
+ const address = randomAddress(context.rpcMsb.config.addressPrefix)
41
41
  const res = await request(context.server).get(`/v1/balance/${address}`)
42
42
  expect(res.statusCode).toBe(200)
43
43
  expect(res.body.address).toBe(address)
@@ -1,7 +1,7 @@
1
1
  import request from "supertest"
2
2
  import b4a from "b4a"
3
3
  import { $TNK } from "../../../../src/core/state/utils/balance.js"
4
- import { buildRpcSelfTransferPayload } from "../../../helpers/transactionPayloads.mjs"
4
+ import { buildRpcSelfTransferPayload, waitForConnection } from "../../../helpers/transactionPayloads.mjs"
5
5
 
6
6
  const toBase64 = (value) => b4a.toString(b4a.from(JSON.stringify(value)), "base64")
7
7
 
@@ -9,10 +9,11 @@ export const registerBroadcastTransactionTests = (context) => {
9
9
  describe("POST /v1/broadcast-transaction", () => {
10
10
  it("broadcasts transaction and returns lengths", async () => {
11
11
  const { payload } = await buildRpcSelfTransferPayload(
12
- context.wallet,
12
+ context,
13
13
  context.rpcMsb.state,
14
14
  1n
15
15
  );
16
+ await waitForConnection(context.rpcMsb)
16
17
  const res = await request(context.server)
17
18
  .post("/v1/broadcast-transaction")
18
19
  .set("Accept", "application/json")
@@ -30,6 +31,7 @@ export const registerBroadcastTransactionTests = (context) => {
30
31
  })
31
32
 
32
33
  it("returns 400 when payload is missing", async () => {
34
+ await waitForConnection(context.rpcMsb)
33
35
  const res = await request(context.server)
34
36
  .post("/v1/broadcast-transaction")
35
37
  .set("Accept", "application/json")
@@ -40,6 +42,7 @@ export const registerBroadcastTransactionTests = (context) => {
40
42
  })
41
43
 
42
44
  it("returns 400 when payload is not base64", async () => {
45
+ await waitForConnection(context.rpcMsb)
43
46
  const res = await request(context.server)
44
47
  .post("/v1/broadcast-transaction")
45
48
  .set("Accept", "application/json")
@@ -52,6 +55,8 @@ export const registerBroadcastTransactionTests = (context) => {
52
55
  // TODO: enable once handler returns 400 for client-side decode errors
53
56
  it.skip("returns 400 when decoded payload is not valid JSON", async () => {
54
57
  const invalidJsonBase64 = b4a.toString(b4a.from("{{invalid"), "base64")
58
+
59
+ await waitForConnection(context.rpcMsb)
55
60
  const res = await request(context.server)
56
61
  .post("/v1/broadcast-transaction")
57
62
  .set("Accept", "application/json")
@@ -67,6 +72,8 @@ export const registerBroadcastTransactionTests = (context) => {
67
72
  type: 1,
68
73
  address: context.wallet.address,
69
74
  }
75
+
76
+ await waitForConnection(context.rpcMsb)
70
77
  const res = await request(context.server)
71
78
  .post("/v1/broadcast-transaction")
72
79
  .set("Accept", "application/json")
@@ -81,6 +88,7 @@ export const registerBroadcastTransactionTests = (context) => {
81
88
  const largeString = "a".repeat(3_000_000)
82
89
  const payload = toBase64({ type: 1, address: context.wallet.address, txo: { large: largeString } })
83
90
 
91
+ await waitForConnection(context.rpcMsb)
84
92
  const res = await request(context.server)
85
93
  .post("/v1/broadcast-transaction")
86
94
  .set("Accept", "application/json")
@@ -99,6 +107,7 @@ export const registerBroadcastTransactionTests = (context) => {
99
107
  )
100
108
 
101
109
  const payload = tracCrypto.transaction.build(txData, b4a.from(context.wallet.secretKey, 'hex'))
110
+ await waitForConnection(context.rpcMsb)
102
111
  const res = await request(context.server)
103
112
  .post("/v1/broadcast-transaction")
104
113
  .set("Accept", "application/json")