trac-msb 0.2.17 → 0.2.19

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 (365) hide show
  1. package/README.md +62 -2
  2. package/SECURITY.md +9 -6
  3. package/cli/commandHandler.js +272 -0
  4. package/cli/handlers.js +210 -0
  5. package/cli/interactive.js +182 -0
  6. package/msb.mjs +7 -8
  7. package/package.json +33 -11
  8. package/rpc/create_server.js +44 -44
  9. package/rpc/handlers.js +43 -56
  10. package/rpc/routes/index.js +8 -8
  11. package/rpc/rpc_server.js +6 -2
  12. package/rpc/utils/helpers.js +46 -66
  13. package/scripts/pear-runner.js +170 -0
  14. package/src/config/args.js +60 -13
  15. package/src/config/config.js +163 -14
  16. package/src/config/env.js +57 -25
  17. package/src/core/network/Network.js +121 -56
  18. package/src/core/network/protocols/LegacyProtocol.js +21 -11
  19. package/src/core/network/protocols/NetworkMessages.js +38 -17
  20. package/src/core/network/protocols/ProtocolInterface.js +15 -3
  21. package/src/core/network/protocols/ProtocolSession.js +144 -17
  22. package/src/core/network/protocols/V1Protocol.js +37 -18
  23. package/src/core/network/protocols/connectionPolicies.js +174 -0
  24. package/src/core/network/protocols/legacy/NetworkMessageRouter.js +26 -20
  25. package/src/core/network/protocols/{shared/handlers/base/BaseOperationHandler.js → legacy/handlers/BaseStateOperationHandler.js} +25 -14
  26. package/src/core/network/protocols/legacy/handlers/{GetRequestHandler.js → LegacyGetRequestHandler.js} +9 -9
  27. package/src/core/network/protocols/legacy/handlers/LegacyResponseHandler.js +23 -0
  28. package/src/core/network/protocols/{shared/handlers/RoleOperationHandler.js → legacy/handlers/LegacyRoleOperationHandler.js} +19 -12
  29. package/src/core/network/protocols/{shared/handlers/SubnetworkOperationHandler.js → legacy/handlers/LegacySubnetworkOperationHandler.js} +29 -18
  30. package/src/core/network/protocols/{shared/handlers/TransferOperationHandler.js → legacy/handlers/LegacyTransferOperationHandler.js} +18 -12
  31. package/src/core/network/protocols/legacy/validators/base/BaseResponse.js +7 -10
  32. package/src/core/network/protocols/shared/validators/{PartialBootstrapDeployment.js → PartialBootstrapDeploymentValidator.js} +9 -4
  33. package/src/core/network/protocols/shared/validators/{base/PartialOperation.js → PartialOperationValidator.js} +53 -31
  34. package/src/core/network/protocols/shared/validators/{PartialRoleAccess.js → PartialRoleAccessValidator.js} +51 -17
  35. package/src/core/network/protocols/shared/validators/{PartialTransaction.js → PartialTransactionValidator.js} +21 -7
  36. package/src/core/network/protocols/shared/validators/{PartialTransfer.js → PartialTransferValidator.js} +32 -14
  37. package/src/core/network/protocols/v1/NetworkMessageRouter.js +91 -7
  38. package/src/core/network/protocols/v1/V1ProtocolError.js +27 -0
  39. package/src/core/network/protocols/v1/handlers/V1BaseOperationHandler.js +66 -0
  40. package/src/core/network/protocols/v1/handlers/V1BroadcastTransactionOperationHandler.js +272 -0
  41. package/src/core/network/protocols/v1/handlers/V1LivenessOperationHandler.js +88 -0
  42. package/src/core/network/protocols/v1/handlers/broadcastTransaction/BroadcastTransactionErrorMapper.js +84 -0
  43. package/src/core/network/protocols/v1/handlers/broadcastTransaction/BroadcastTransactionOperationStrategies.js +128 -0
  44. package/src/core/network/protocols/v1/handlers/broadcastTransaction/BroadcastTransactionPayloadUtils.js +26 -0
  45. package/src/core/network/protocols/v1/validators/V1BaseOperation.js +212 -0
  46. package/src/core/network/protocols/v1/validators/V1BroadcastTransactionRequest.js +28 -0
  47. package/src/core/network/protocols/v1/validators/V1BroadcastTransactionResponse.js +260 -0
  48. package/src/core/network/protocols/v1/validators/V1LivenessRequest.js +15 -0
  49. package/src/core/network/protocols/v1/validators/V1LivenessResponse.js +17 -0
  50. package/src/core/network/protocols/v1/validators/V1ValidationSchema.js +210 -0
  51. package/src/core/network/services/ConnectionManager.js +149 -96
  52. package/src/core/network/services/MessageOrchestrator.js +197 -37
  53. package/src/core/network/services/PendingRequestService.js +175 -0
  54. package/src/core/network/services/TransactionCommitService.js +149 -0
  55. package/src/core/network/services/TransactionPoolService.js +129 -18
  56. package/src/core/network/services/TransactionRateLimiterService.js +57 -35
  57. package/src/core/network/services/ValidatorHealthCheckService.js +127 -0
  58. package/src/core/network/services/ValidatorObserverService.js +400 -121
  59. package/src/core/state/State.js +259 -156
  60. package/src/core/state/utils/address.js +4 -9
  61. package/src/core/state/utils/balance.js +7 -7
  62. package/src/core/state/utils/roles.js +1 -1
  63. package/src/index.js +320 -278
  64. package/src/messages/network/v1/NetworkMessageBuilder.js +71 -100
  65. package/src/messages/network/v1/NetworkMessageDirector.js +16 -50
  66. package/src/messages/network/v1/networkMessageFactory.js +1 -1
  67. package/src/messages/state/ApplyStateMessageBuilder.js +6 -6
  68. package/src/messages/state/applyStateMessageFactory.js +1 -1
  69. package/src/utils/Scheduler.js +0 -8
  70. package/src/utils/buffer.js +1 -1
  71. package/src/utils/check.js +12 -13
  72. package/src/utils/constants.js +78 -5
  73. package/src/utils/deepEqualApplyPayload.js +40 -0
  74. package/src/utils/errors.js +20 -0
  75. package/src/utils/fileUtils.js +12 -3
  76. package/src/utils/helpers.js +10 -1
  77. package/src/utils/logger.js +25 -0
  78. package/src/utils/migrationUtils.js +3 -3
  79. package/src/utils/normalizers.js +38 -0
  80. package/src/utils/protobuf/networkV1.generated.cjs +2460 -0
  81. package/src/utils/protobuf/operationHelpers.js +24 -3
  82. package/.dockerignore +0 -16
  83. package/.github/workflows/acceptance-tests.yml +0 -38
  84. package/.github/workflows/lint-pr-title.yml +0 -26
  85. package/.github/workflows/publish.yml +0 -33
  86. package/.github/workflows/unit-tests.yml +0 -34
  87. package/CODE_OF_CONDUCT.md +0 -128
  88. package/docker-compose.yml +0 -17
  89. package/dockerfile +0 -41
  90. package/docs/fee_distribution.md +0 -89
  91. package/docs/trac_network_http_api.openapi.yaml +0 -889
  92. package/migration/.gitkeep +0 -0
  93. package/proto/applyOperations.proto +0 -117
  94. package/proto/network.proto +0 -74
  95. package/rpc/rpc_services.js +0 -163
  96. package/scripts/generate-protobufs.js +0 -42
  97. package/src/core/network/identity/NetworkWalletFactory.js +0 -77
  98. package/src/core/network/protocols/legacy/handlers/ResponseHandler.js +0 -37
  99. package/src/utils/cli.js +0 -130
  100. package/src/utils/cliCommands.js +0 -280
  101. package/src/utils/protobuf/network.cjs +0 -840
  102. package/tests/acceptance/v1/account/account.test.mjs +0 -123
  103. package/tests/acceptance/v1/balance/balance.test.mjs +0 -54
  104. package/tests/acceptance/v1/broadcast-transaction/broadcast-transaction.test.mjs +0 -116
  105. package/tests/acceptance/v1/confirmed-length/confirmed-length.test.mjs +0 -19
  106. package/tests/acceptance/v1/fee/fee.test.mjs +0 -11
  107. package/tests/acceptance/v1/health/health.test.mjs +0 -33
  108. package/tests/acceptance/v1/rpc.test.mjs +0 -95
  109. package/tests/acceptance/v1/tx/tx.test.mjs +0 -111
  110. package/tests/acceptance/v1/tx-details/tx-details.test.mjs +0 -213
  111. package/tests/acceptance/v1/tx-hashes/tx-hashes.test.mjs +0 -72
  112. package/tests/acceptance/v1/tx-payloads-bulk/tx-payloads-bulk.test.mjs +0 -27
  113. package/tests/acceptance/v1/txv/txv.test.mjs +0 -11
  114. package/tests/acceptance/v1/unconfirmed-length/unconfirmed-length.test.mjs +0 -11
  115. package/tests/fixtures/apply.fixtures.js +0 -77
  116. package/tests/fixtures/assembleMessage.fixtures.js +0 -41
  117. package/tests/fixtures/check.fixtures.js +0 -428
  118. package/tests/fixtures/networkV1.fixtures.js +0 -85
  119. package/tests/fixtures/protobuf.fixtures.js +0 -388
  120. package/tests/helpers/StateNetworkFactory.js +0 -155
  121. package/tests/helpers/address.js +0 -6
  122. package/tests/helpers/autobaseTestHelpers.js +0 -419
  123. package/tests/helpers/config.js +0 -4
  124. package/tests/helpers/createTestSignature.js +0 -13
  125. package/tests/helpers/regexHelper.js +0 -3
  126. package/tests/helpers/setupApplyTests.js +0 -587
  127. package/tests/helpers/transactionPayloads.mjs +0 -92
  128. package/tests/helpers/wrapper.js +0 -28
  129. package/tests/unit/messages/messages.test.js +0 -12
  130. package/tests/unit/messages/network/NetworkMessageBuilder.test.js +0 -276
  131. package/tests/unit/messages/network/NetworkMessageDirector.test.js +0 -201
  132. package/tests/unit/messages/state/applyStateMessageBuilder.complete.test.js +0 -525
  133. package/tests/unit/messages/state/applyStateMessageBuilder.partial.test.js +0 -237
  134. package/tests/unit/network/ConnectionManager.test.js +0 -191
  135. package/tests/unit/network/NetworkWalletFactory.test.js +0 -156
  136. package/tests/unit/network/networkModule.test.js +0 -10
  137. package/tests/unit/state/State.test.js +0 -80
  138. package/tests/unit/state/apply/addAdmin/addAdminHappyPathScenario.js +0 -42
  139. package/tests/unit/state/apply/addAdmin/addAdminScenarioHelpers.js +0 -276
  140. package/tests/unit/state/apply/addAdmin/adminEntryEncodingFailureScenario.js +0 -30
  141. package/tests/unit/state/apply/addAdmin/adminEntryExistsScenario.js +0 -78
  142. package/tests/unit/state/apply/addAdmin/nodeEntryInitializationFailureScenario.js +0 -30
  143. package/tests/unit/state/apply/addAdmin/nonBootstrapNodeScenario.js +0 -68
  144. package/tests/unit/state/apply/addAdmin/state.apply.addAdmin.test.js +0 -159
  145. package/tests/unit/state/apply/addIndexer/addIndexerHappyPathScenario.js +0 -39
  146. package/tests/unit/state/apply/addIndexer/addIndexerMultipleIndexersInTheNetworkScenario.js +0 -167
  147. package/tests/unit/state/apply/addIndexer/addIndexerPretenderAlreadyIndexerScenario.js +0 -21
  148. package/tests/unit/state/apply/addIndexer/addIndexerPretenderNotWriterScenario.js +0 -21
  149. package/tests/unit/state/apply/addIndexer/addIndexerRemoveAndReAddScenario.js +0 -186
  150. package/tests/unit/state/apply/addIndexer/addIndexerScenarioHelpers.js +0 -443
  151. package/tests/unit/state/apply/addIndexer/addIndexerWriterKeyAlreadyRegisteredScenario.js +0 -32
  152. package/tests/unit/state/apply/addIndexer/state.apply.addIndexer.test.js +0 -297
  153. package/tests/unit/state/apply/addWriter/addWriterHappyPathScenario.js +0 -41
  154. package/tests/unit/state/apply/addWriter/addWriterInvalidValidatorSignatureScenario.js +0 -32
  155. package/tests/unit/state/apply/addWriter/addWriterNewWkScenario.js +0 -149
  156. package/tests/unit/state/apply/addWriter/addWriterRequesterAlreadyWriterScenario.js +0 -21
  157. package/tests/unit/state/apply/addWriter/addWriterRequesterBalanceInsufficientScenario.js +0 -21
  158. package/tests/unit/state/apply/addWriter/addWriterRequesterEntryDecodeFailureScenario.js +0 -19
  159. package/tests/unit/state/apply/addWriter/addWriterRequesterEntryMissingScenario.js +0 -19
  160. package/tests/unit/state/apply/addWriter/addWriterRequesterIndexerScenario.js +0 -21
  161. package/tests/unit/state/apply/addWriter/addWriterRequesterNotWhitelistedScenario.js +0 -21
  162. package/tests/unit/state/apply/addWriter/addWriterScenarioHelpers.js +0 -766
  163. package/tests/unit/state/apply/addWriter/addWriterStakeBalanceUpdateFailureScenario.js +0 -50
  164. package/tests/unit/state/apply/addWriter/addWriterStakeInsufficientBalanceScenario.js +0 -29
  165. package/tests/unit/state/apply/addWriter/addWriterStakeInvalidBalanceScenario.js +0 -29
  166. package/tests/unit/state/apply/addWriter/addWriterStakeInvalidEntryScenario.js +0 -21
  167. package/tests/unit/state/apply/addWriter/addWriterStakeStakedBalanceFailureScenario.js +0 -37
  168. package/tests/unit/state/apply/addWriter/addWriterStakeSubtractFailureScenario.js +0 -42
  169. package/tests/unit/state/apply/addWriter/addWriterValidatorRewardScenario.js +0 -106
  170. package/tests/unit/state/apply/addWriter/addWriterWriterKeyMismatchScenario.js +0 -54
  171. package/tests/unit/state/apply/addWriter/addWriterWriterKeyOwnershipScenario.js +0 -54
  172. package/tests/unit/state/apply/addWriter/addWriterZeroWriterKeyScenario.js +0 -29
  173. package/tests/unit/state/apply/addWriter/state.apply.addWriter.test.js +0 -309
  174. package/tests/unit/state/apply/adminRecovery/adminRecoveryHappyPathScenario.js +0 -30
  175. package/tests/unit/state/apply/adminRecovery/adminRecoveryScenarioHelpers.js +0 -881
  176. package/tests/unit/state/apply/adminRecovery/state.apply.adminRecovery.test.js +0 -435
  177. package/tests/unit/state/apply/appendWhitelist/appendWhitelistBanAndReapplyScenario.js +0 -78
  178. package/tests/unit/state/apply/appendWhitelist/appendWhitelistExistingReaderHappyPathScenario.js +0 -98
  179. package/tests/unit/state/apply/appendWhitelist/appendWhitelistFeeAfterDisableScenario.js +0 -66
  180. package/tests/unit/state/apply/appendWhitelist/appendWhitelistHappyPathScenario.js +0 -55
  181. package/tests/unit/state/apply/appendWhitelist/appendWhitelistInsufficientAdminBalanceScenario.js +0 -103
  182. package/tests/unit/state/apply/appendWhitelist/appendWhitelistNodeAlreadyWhitelistedScenario.js +0 -60
  183. package/tests/unit/state/apply/appendWhitelist/appendWhitelistScenarioHelpers.js +0 -189
  184. package/tests/unit/state/apply/appendWhitelist/state.apply.appendWhitelist.test.js +0 -220
  185. package/tests/unit/state/apply/balanceInitialization/balanceInitializationHappyPathScenario.js +0 -82
  186. package/tests/unit/state/apply/balanceInitialization/balanceInitializationScenarioHelpers.js +0 -111
  187. package/tests/unit/state/apply/balanceInitialization/invalidAmountScenario.js +0 -45
  188. package/tests/unit/state/apply/balanceInitialization/nodeEntryBalanceUpdateFailureScenario.js +0 -82
  189. package/tests/unit/state/apply/balanceInitialization/state.apply.balanceInitialization.test.js +0 -189
  190. package/tests/unit/state/apply/banValidator/banValidatorBanAndReWhitelistScenario.js +0 -156
  191. package/tests/unit/state/apply/banValidator/banValidatorHappyPathScenario.js +0 -36
  192. package/tests/unit/state/apply/banValidator/banValidatorScenarioHelpers.js +0 -531
  193. package/tests/unit/state/apply/banValidator/banValidatorSequentialBansScenario.js +0 -74
  194. package/tests/unit/state/apply/banValidator/banValidatorTargetDecodeFailureScenario.js +0 -19
  195. package/tests/unit/state/apply/banValidator/banValidatorTargetIndexerScenario.js +0 -32
  196. package/tests/unit/state/apply/banValidator/banValidatorTargetNodeEntryMissingScenario.js +0 -19
  197. package/tests/unit/state/apply/banValidator/banValidatorTargetRoleUpdateFailureScenario.js +0 -19
  198. package/tests/unit/state/apply/banValidator/banValidatorWhitelistedNonWriterScenario.js +0 -38
  199. package/tests/unit/state/apply/banValidator/banValidatorWhitelistedZeroBalanceScenario.js +0 -91
  200. package/tests/unit/state/apply/banValidator/banValidatorWithdrawFailureScenario.js +0 -19
  201. package/tests/unit/state/apply/banValidator/state.apply.banValidator.test.js +0 -266
  202. package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentDuplicateRegistrationScenario.js +0 -143
  203. package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentHappyPathScenario.js +0 -26
  204. package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentIncompleteOperationScenario.js +0 -94
  205. package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentInvalidDeploymentEntryScenario.js +0 -37
  206. package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentMultipleBootstrapScenario.js +0 -86
  207. package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentScenarioHelpers.js +0 -347
  208. package/tests/unit/state/apply/bootstrapDeployment/invalidValidatorNodeEntryScenario.js +0 -57
  209. package/tests/unit/state/apply/bootstrapDeployment/state.apply.bootstrapDeployment.test.js +0 -429
  210. package/tests/unit/state/apply/common/access-control/adminConsistencyMismatchScenario.js +0 -120
  211. package/tests/unit/state/apply/common/access-control/adminEntryDecodeFailureScenario.js +0 -130
  212. package/tests/unit/state/apply/common/access-control/adminEntryExistsScenario.js +0 -93
  213. package/tests/unit/state/apply/common/access-control/adminEntryMissingScenario.js +0 -108
  214. package/tests/unit/state/apply/common/access-control/adminOnlyGuardScenario.js +0 -126
  215. package/tests/unit/state/apply/common/access-control/adminPublicKeyDecodeFailureScenario.js +0 -121
  216. package/tests/unit/state/apply/common/access-control/roleAccessOperationValidationScenario.js +0 -50
  217. package/tests/unit/state/apply/common/adminControlOperationValidationScenario.js +0 -56
  218. package/tests/unit/state/apply/common/balances/adminEntryUpdateFailureScenario.js +0 -52
  219. package/tests/unit/state/apply/common/balances/base/requesterBalanceScenarioBase.js +0 -198
  220. package/tests/unit/state/apply/common/balances/feeDecodeFailureScenario.js +0 -52
  221. package/tests/unit/state/apply/common/balances/requesterBalanceDecodeFailureScenario.js +0 -15
  222. package/tests/unit/state/apply/common/balances/requesterBalanceFeeApplicationFailureScenario.js +0 -11
  223. package/tests/unit/state/apply/common/balances/requesterBalanceInsufficientScenario.js +0 -15
  224. package/tests/unit/state/apply/common/balances/requesterBalanceUpdateFailureScenario.js +0 -11
  225. package/tests/unit/state/apply/common/balances/validatorEntryRewardFailureScenario.js +0 -11
  226. package/tests/unit/state/apply/common/balances/validatorEntryUpdateFailureScenario.js +0 -11
  227. package/tests/unit/state/apply/common/balances/validatorNodeEntryDecodeFailureScenario.js +0 -40
  228. package/tests/unit/state/apply/common/base/OperationValidationScenarioBase.js +0 -114
  229. package/tests/unit/state/apply/common/commonScenarioHelper.js +0 -103
  230. package/tests/unit/state/apply/common/indexer/indexerNodeEntryDecodeFailureScenario.js +0 -36
  231. package/tests/unit/state/apply/common/indexer/indexerNodeEntryMissingScenario.js +0 -36
  232. package/tests/unit/state/apply/common/indexer/indexerRoleUpdateFailureScenario.js +0 -29
  233. package/tests/unit/state/apply/common/indexer/indexerSequenceStateInvalidScenario.js +0 -66
  234. package/tests/unit/state/apply/common/invalidMessageComponentValidationScenario.js +0 -84
  235. package/tests/unit/state/apply/common/nodeEntryInitializationFailureScenario.js +0 -47
  236. package/tests/unit/state/apply/common/operationAlreadyAppliedScenario.js +0 -85
  237. package/tests/unit/state/apply/common/payload-structure/addressWithInvalidPublicKeyScenario.js +0 -52
  238. package/tests/unit/state/apply/common/payload-structure/initializationDisabledScenario.js +0 -54
  239. package/tests/unit/state/apply/common/payload-structure/invalidAddressValidationScenario.js +0 -73
  240. package/tests/unit/state/apply/common/payload-structure/invalidHashValidationScenario.js +0 -71
  241. package/tests/unit/state/apply/common/payload-structure/invalidPayloadValidationScenario.js +0 -31
  242. package/tests/unit/state/apply/common/payload-structure/invalidSignatureValidationScenario.js +0 -142
  243. package/tests/unit/state/apply/common/payload-structure/partialOperationValidationScenario.js +0 -87
  244. package/tests/unit/state/apply/common/requester/requesterNodeEntryBufferMissingScenario.js +0 -71
  245. package/tests/unit/state/apply/common/requester/requesterNodeEntryDecodeFailureScenario.js +0 -73
  246. package/tests/unit/state/apply/common/requester/requesterNodeEntryMissingScenario.js +0 -36
  247. package/tests/unit/state/apply/common/requesterAddressValidationScenario.js +0 -44
  248. package/tests/unit/state/apply/common/requesterPublicKeyValidationScenario.js +0 -25
  249. package/tests/unit/state/apply/common/transactionValidityMismatchScenario.js +0 -98
  250. package/tests/unit/state/apply/common/validatorConsistency/base/validatorConsistencyScenarioBase.js +0 -202
  251. package/tests/unit/state/apply/common/validatorConsistency/validatorEntryDecodeFailureScenario.js +0 -17
  252. package/tests/unit/state/apply/common/validatorConsistency/validatorEntryMissingScenario.js +0 -44
  253. package/tests/unit/state/apply/common/validatorConsistency/validatorInactiveScenario.js +0 -19
  254. package/tests/unit/state/apply/common/validatorConsistency/validatorWriterKeyMismatchScenario.js +0 -18
  255. package/tests/unit/state/apply/common/validatorEntryValidation/base/validatorEntryValidationScenarioBase.js +0 -315
  256. package/tests/unit/state/apply/common/validatorEntryValidation/validatorEntryInvalidBalanceScenario.js +0 -18
  257. package/tests/unit/state/apply/common/writerKeyExistsValidationScenario.js +0 -43
  258. package/tests/unit/state/apply/disableInitialization/disableInitializationAlreadyDisabledScenario.js +0 -53
  259. package/tests/unit/state/apply/disableInitialization/disableInitializationHappyPathScenario.js +0 -24
  260. package/tests/unit/state/apply/disableInitialization/disableInitializationScenarioHelpers.js +0 -204
  261. package/tests/unit/state/apply/disableInitialization/state.apply.disableInitialization.test.js +0 -161
  262. package/tests/unit/state/apply/missing-tests.md +0 -18
  263. package/tests/unit/state/apply/removeIndexer/removeIndexerHappyPathScenario.js +0 -58
  264. package/tests/unit/state/apply/removeIndexer/removeIndexerReAddAndRemoveAgainScenario.js +0 -98
  265. package/tests/unit/state/apply/removeIndexer/removeIndexerRemoveMultipleIndexersScenario.js +0 -167
  266. package/tests/unit/state/apply/removeIndexer/removeIndexerScenarioHelpers.js +0 -429
  267. package/tests/unit/state/apply/removeIndexer/removeIndexerTargetNotIndexerScenario.js +0 -22
  268. package/tests/unit/state/apply/removeIndexer/removeIndexerWriterKeyMissingScenario.js +0 -20
  269. package/tests/unit/state/apply/removeIndexer/state.apply.removeIndexer.test.js +0 -291
  270. package/tests/unit/state/apply/removeWriter/removeWriterAndAddWriterAgainScenario.js +0 -87
  271. package/tests/unit/state/apply/removeWriter/removeWriterHappyPathScenario.js +0 -38
  272. package/tests/unit/state/apply/removeWriter/removeWriterInvalidValidatorSignatureScenario.js +0 -32
  273. package/tests/unit/state/apply/removeWriter/removeWriterRequesterBalanceInsufficientScenario.js +0 -21
  274. package/tests/unit/state/apply/removeWriter/removeWriterRequesterEntryDecodeFailureScenario.js +0 -19
  275. package/tests/unit/state/apply/removeWriter/removeWriterRequesterEntryMissingScenario.js +0 -19
  276. package/tests/unit/state/apply/removeWriter/removeWriterRequesterIndexerScenario.js +0 -21
  277. package/tests/unit/state/apply/removeWriter/removeWriterRequesterNotWriterScenario.js +0 -21
  278. package/tests/unit/state/apply/removeWriter/removeWriterRequesterRoleUpdateFailureScenario.js +0 -19
  279. package/tests/unit/state/apply/removeWriter/removeWriterScenarioHelpers.js +0 -348
  280. package/tests/unit/state/apply/removeWriter/removeWriterThroughWriterValidatorScenario.js +0 -113
  281. package/tests/unit/state/apply/removeWriter/removeWriterUnstakeFailureScenario.js +0 -33
  282. package/tests/unit/state/apply/removeWriter/removeWriterWriterKeyMismatchScenario.js +0 -21
  283. package/tests/unit/state/apply/removeWriter/removeWriterWriterKeyOwnershipScenario.js +0 -26
  284. package/tests/unit/state/apply/removeWriter/removeWriterWriterKeyRegistryMissingScenario.js +0 -22
  285. package/tests/unit/state/apply/removeWriter/state.apply.removeWriter.test.js +0 -307
  286. package/tests/unit/state/apply/state.apply.test.js +0 -24
  287. package/tests/unit/state/apply/transfer/state.apply.transfer.test.js +0 -819
  288. package/tests/unit/state/apply/transfer/transferContractSchemaValidationScenario.js +0 -22
  289. package/tests/unit/state/apply/transfer/transferDoubleSpendAcrossValidatorsScenario.js +0 -146
  290. package/tests/unit/state/apply/transfer/transferDoubleSpendSameBatchScenario.js +0 -63
  291. package/tests/unit/state/apply/transfer/transferDoubleSpendSingleValidatorScenario.js +0 -67
  292. package/tests/unit/state/apply/transfer/transferExistingRecipientAmountScenario.js +0 -31
  293. package/tests/unit/state/apply/transfer/transferExistingRecipientZeroAmountScenario.js +0 -31
  294. package/tests/unit/state/apply/transfer/transferHandlerGuardScenarios.js +0 -22
  295. package/tests/unit/state/apply/transfer/transferHappyPathScenario.js +0 -8
  296. package/tests/unit/state/apply/transfer/transferInvalidIncomingDataScenario.js +0 -66
  297. package/tests/unit/state/apply/transfer/transferNewRecipientAmountScenario.js +0 -31
  298. package/tests/unit/state/apply/transfer/transferNewRecipientZeroAmountScenario.js +0 -31
  299. package/tests/unit/state/apply/transfer/transferScenarioHelpers.js +0 -1170
  300. package/tests/unit/state/apply/transfer/transferSelfTransferAmountScenario.js +0 -38
  301. package/tests/unit/state/apply/transfer/transferSelfTransferZeroAmountScenario.js +0 -38
  302. package/tests/unit/state/apply/transfer/transferValidatorRecipientAmountScenario.js +0 -38
  303. package/tests/unit/state/apply/transfer/transferValidatorRecipientZeroAmountScenario.js +0 -38
  304. package/tests/unit/state/apply/txOperation/state.apply.txOperation.test.js +0 -318
  305. package/tests/unit/state/apply/txOperation/txOperationBootstrapNotRegisteredScenario.js +0 -70
  306. package/tests/unit/state/apply/txOperation/txOperationDifferentValidatorCreatorHappyPathScenario.js +0 -23
  307. package/tests/unit/state/apply/txOperation/txOperationInvalidDeploymentEntryScenario.js +0 -48
  308. package/tests/unit/state/apply/txOperation/txOperationInvalidFeeAmountScenario.js +0 -39
  309. package/tests/unit/state/apply/txOperation/txOperationInvalidSubnetCreatorAddressScenario.js +0 -46
  310. package/tests/unit/state/apply/txOperation/txOperationRequesterCreatorHappyPathScenario.js +0 -21
  311. package/tests/unit/state/apply/txOperation/txOperationScenarioHelpers.js +0 -432
  312. package/tests/unit/state/apply/txOperation/txOperationStandardHappyPathScenario.js +0 -21
  313. package/tests/unit/state/apply/txOperation/txOperationTransferFeeAddCreatorBalanceFailureScenario.js +0 -26
  314. package/tests/unit/state/apply/txOperation/txOperationTransferFeeAddValidatorBalanceFailureScenario.js +0 -25
  315. package/tests/unit/state/apply/txOperation/txOperationTransferFeeAddValidatorBonusFailureScenario.js +0 -27
  316. package/tests/unit/state/apply/txOperation/txOperationTransferFeeDecodeCreatorEntryScenario.js +0 -18
  317. package/tests/unit/state/apply/txOperation/txOperationTransferFeeDecodeRequesterEntryScenario.js +0 -17
  318. package/tests/unit/state/apply/txOperation/txOperationTransferFeeDecodeValidatorEntryScenario.js +0 -31
  319. package/tests/unit/state/apply/txOperation/txOperationTransferFeeGuardBypassScenario.js +0 -49
  320. package/tests/unit/state/apply/txOperation/txOperationTransferFeeGuardScenarioFactory.js +0 -93
  321. package/tests/unit/state/apply/txOperation/txOperationTransferFeeInsufficientRequesterBalanceScenario.js +0 -28
  322. package/tests/unit/state/apply/txOperation/txOperationTransferFeeInvalidCreatorBalanceScenario.js +0 -29
  323. package/tests/unit/state/apply/txOperation/txOperationTransferFeeInvalidRequesterBalanceScenario.js +0 -28
  324. package/tests/unit/state/apply/txOperation/txOperationTransferFeeInvalidRequesterEntryScenario.js +0 -17
  325. package/tests/unit/state/apply/txOperation/txOperationTransferFeeInvalidValidatorBalanceScenario.js +0 -33
  326. package/tests/unit/state/apply/txOperation/txOperationTransferFeeMissingCreatorEntryScenario.js +0 -18
  327. package/tests/unit/state/apply/txOperation/txOperationTransferFeeSubtractFailureScenario.js +0 -25
  328. package/tests/unit/state/apply/txOperation/txOperationTransferFeeUpdateCreatorBalanceFailureScenario.js +0 -26
  329. package/tests/unit/state/apply/txOperation/txOperationTransferFeeUpdateFailureScenario.js +0 -25
  330. package/tests/unit/state/apply/txOperation/txOperationTransferFeeUpdateValidatorBalanceFailureScenario.js +0 -26
  331. package/tests/unit/state/apply/txOperation/txOperationTransferFeeUpdateValidatorBonusFailureScenario.js +0 -27
  332. package/tests/unit/state/apply/txOperation/txOperationValidatorCreatorHappyPathScenario.js +0 -21
  333. package/tests/unit/state/stateModule.test.js +0 -23
  334. package/tests/unit/state/stateTestUtils.js +0 -32
  335. package/tests/unit/state/utils/address.test.js +0 -63
  336. package/tests/unit/state/utils/adminEntry.test.js +0 -52
  337. package/tests/unit/state/utils/balance.test.js +0 -320
  338. package/tests/unit/state/utils/lengthEntry.test.js +0 -54
  339. package/tests/unit/state/utils/nodeEntry.test.js +0 -298
  340. package/tests/unit/state/utils/roles.test.js +0 -44
  341. package/tests/unit/unit.test.js +0 -14
  342. package/tests/unit/utils/amountSerialization/amountSerialization.test.js +0 -237
  343. package/tests/unit/utils/buffer/buffer.test.js +0 -251
  344. package/tests/unit/utils/check/adminControlOperation.test.js +0 -156
  345. package/tests/unit/utils/check/balanceInitializationOperation.test.js +0 -54
  346. package/tests/unit/utils/check/bootstrapDeploymentOperation.test.js +0 -104
  347. package/tests/unit/utils/check/check.test.js +0 -17
  348. package/tests/unit/utils/check/common.test.js +0 -419
  349. package/tests/unit/utils/check/coreAdminOperation.test.js +0 -95
  350. package/tests/unit/utils/check/roleAccessOperation.test.js +0 -255
  351. package/tests/unit/utils/check/transactionOperation.test.js +0 -107
  352. package/tests/unit/utils/check/transferOperation.test.js +0 -102
  353. package/tests/unit/utils/fileUtils/readAddressesFromWhitelistFile.test.js +0 -95
  354. package/tests/unit/utils/fileUtils/readBalanceMigrationFile.test.js +0 -149
  355. package/tests/unit/utils/helpers/helpers.test.js +0 -11
  356. package/tests/unit/utils/helpers/isHexString.test.js +0 -12
  357. package/tests/unit/utils/helpers/normalizeHex.test.js +0 -82
  358. package/tests/unit/utils/migrationUtils/validateAddressFromIncomingFile.test.js +0 -100
  359. package/tests/unit/utils/normalizers/normalizers.test.js +0 -469
  360. package/tests/unit/utils/protobuf/applyOperations.test.js +0 -91
  361. package/tests/unit/utils/protobuf/operationHelpers.test.js +0 -305
  362. package/tests/unit/utils/protobuf/protobuf.test.js +0 -12
  363. package/tests/unit/utils/type/type.test.js +0 -25
  364. package/tests/unit/utils/utils.test.js +0 -20
  365. package/whitelist/.gitkeep +0 -0
@@ -6,22 +6,34 @@
6
6
  class ProtocolInterface {
7
7
 
8
8
  // TODO: Refactor this so we don't need to pass a reference for the whole network instance
9
- constructor(router, connection, config) {
9
+ constructor(_router, _connection, _pendingRequestService, _config) {
10
10
  if (new.target === ProtocolInterface) {
11
11
  throw new Error('ProtocolInterface cannot be instantiated directly');
12
12
  }
13
13
  }
14
14
 
15
- init(connection) {
15
+ init(_connection) {
16
16
  // Abstract method. Need to be implemented by subclasses.
17
17
  throw new Error('init() method must be implemented by subclass');
18
18
  }
19
19
 
20
- send(message) {
20
+ // TODO: This method is only kept here because of v1, but it should be probably removed from the interface
21
+ // Remove it after we finish refactoring v1 protocol
22
+ decode(_message) {
23
+ // Abstract method. Need to be implemented by subclasses.
24
+ throw new Error('decode() method must be implemented by subclass');
25
+ }
26
+
27
+ async send(_message) {
21
28
  // Abstract method. Need to be implemented by subclasses.
22
29
  throw new Error('send() method must be implemented by subclass');
23
30
  }
24
31
 
32
+ sendAndForget(_message) {
33
+ // Abstract method. Need to be implemented by subclasses.
34
+ throw new Error('sendAndForget() method must be implemented by subclass');
35
+ }
36
+
25
37
  close() {
26
38
  // Abstract method. Need to be implemented by subclasses.
27
39
  throw new Error('close() method must be implemented by subclass');
@@ -1,40 +1,158 @@
1
- // ProtocolSession is a per-peer (per Hyperswarm connection) wrapper that exposes the available
1
+ // ProtocolSession is a per-peer (per Hyperswarm connection) bridge that exposes the available
2
2
  // protocol messengers (legacy JSON, v1 binary) in one place.
3
3
  //
4
4
  // Why it exists:
5
5
  // - `setupProtomuxMessages(connection)` creates Protomux channels/messages for a specific peer.
6
+
7
+ import { networkMessageFactory } from '../../../messages/network/v1/networkMessageFactory.js';
8
+ import { generateUUID } from '../../../utils/helpers.js';
9
+ import { NETWORK_CAPABILITIES, ResultCode } from '../../../utils/constants.js';
10
+ import { Logger } from '../../../utils/logger.js';
11
+
6
12
  class ProtocolSession {
7
13
  #legacyProtocol;
8
14
  #v1Protocol;
15
+ #preferredProtocol = null;
16
+ #activeProtocol = null;
17
+ #supportedProtocols = {
18
+ LEGACY: 'legacy',
19
+ V1: 'v1'
20
+ }
21
+ #wallet;
22
+ #config;
23
+ #capabilities;
24
+ #logger;
9
25
 
10
- constructor(legacyProtocol, v1Protocol) {
26
+ constructor(legacyProtocol, v1Protocol, wallet, config) {
11
27
  // These are Protomux "message" objects (returned by channel.addMessage).
12
28
  // They are connection-scoped and expose .send(...), already wired to the channel's encoding.
13
29
  this.#legacyProtocol = legacyProtocol;
14
30
  this.#v1Protocol = v1Protocol;
31
+
32
+ this.#activeProtocol = this.#v1Protocol;
33
+ this.#wallet = wallet;
34
+ this.#config = config;
35
+ this.#capabilities = NETWORK_CAPABILITIES;
36
+ this.#logger = new Logger(config);
15
37
  }
16
38
 
17
- getLegacy() {
18
- return this.#legacyProtocol;
39
+ get preferredProtocol() {
40
+ return this.#preferredProtocol;
19
41
  }
20
42
 
21
- getV1() {
22
- return this.#v1Protocol;
43
+ get supportedProtocols() {
44
+ return this.#supportedProtocols;
23
45
  }
24
46
 
25
- get(protocol) {
26
- if (protocol === 'legacy') return this.#legacyProtocol;
27
- if (protocol === 'v1') return this.#v1Protocol;
28
- return null;
47
+ isProbed() {
48
+ return this.#preferredProtocol !== null;
29
49
  }
30
50
 
31
- has(protocol) {
32
- return Boolean(this.get(protocol));
51
+ setLegacyAsPreferredProtocol() {
52
+ if (this.isProbed()) {
53
+ // TODO: SOMETIMES WE ARE PROBING NODE FOR MULTIPLE AMOUNT OF TIME, THIS IS BAD. WE NEED TO INVESTIGATE THIS.
54
+ //this.#logger.warn(`ProtocolSession: preferred protocol is already set and cannot be changed to LEGACY. Current preferred protocol: ${this.#preferredProtocol}`);
55
+ return;
56
+ }
57
+ this.#preferredProtocol = this.#supportedProtocols.LEGACY;
58
+ this.#activeProtocol = this.#legacyProtocol;
59
+ this.#logger.debug('ProtocolSession: set preferred protocol to LEGACY');
33
60
  }
34
61
 
35
- send(message) {
36
- // TODO: Support v1 messages
37
- this.#legacyProtocol.send(message);
62
+ setV1AsPreferredProtocol() {
63
+ if (this.isProbed()) {
64
+ // TODO: SOMETIMES WE ARE PROBING NODE FOR MULTIPLE AMOUNT OF TIME, THIS IS BAD. WE NEED TO INVESTIGATE THIS.
65
+ //this.#logger.warn(`ProtocolSession: preferred protocol is already set and cannot be changed to V1. Current preferred protocol: ${this.#preferredProtocol}`);
66
+ return;
67
+ }
68
+
69
+ this.#preferredProtocol = this.#supportedProtocols.V1;
70
+ this.#activeProtocol = this.#v1Protocol;
71
+ this.#logger.debug('ProtocolSession: set preferred protocol to V1');
72
+ }
73
+
74
+ /**
75
+ * Probes the peer to determine which protocol version they support/prefer.
76
+ * This is needed to know if the connected peer supports the new v1 protocol
77
+ * or if we should fall back to legacy for this connection.
78
+ *
79
+ * TODO: After legacy protocol is retired, we can remove the concept of "probing" and just use v1 directly.
80
+ * For now, this is needed to determine which protocol to use for health checks.
81
+ * A good future improvement would be to implement a more robust negotiation mechanism that doesn't rely on timeouts
82
+ * (e.g. peer sends a "hello" message indicating supported protocol versions right after connection is established).
83
+ */
84
+ async probe() {
85
+ if (this.isProbed()) {
86
+ this.#logger.warn(`ProtocolSession: preferred protocol is already set. Skipping probe. Current preferred protocol: ${this.#preferredProtocol}`);
87
+ return; // TODO: Consider not returning silently
88
+ }
89
+
90
+ try {
91
+ const message = await this.#buildLivenessRequest();
92
+ if (!this.#v1Protocol) {
93
+ throw new Error('ProtocolSession: v1 protocol not available for probing');
94
+ }
95
+ const result = await this.#v1Protocol.send(message);
96
+ if (result !== ResultCode.OK) {
97
+ // TODO: Think about how to handle failure result codes after legacy protocol is retired
98
+ this.#logger.warn(`ProtocolSession: v1 protocol probe failed with non-OK result code: ${result}`);
99
+ this.setLegacyAsPreferredProtocol();
100
+ return;
101
+ }
102
+ this.setV1AsPreferredProtocol();
103
+ } catch (err) {
104
+ this.#logger.debug(`ProtocolSession: v1 protocol probe failed, falling back to legacy. Details: ${err?.message ?? err}`);
105
+ this.setLegacyAsPreferredProtocol();
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Sends a single health check message to a peer.
111
+ * This is used by the ValidatorHealthCheckService.
112
+ * @returns {Promise<ResultCode>} Result code indicating success or failure of the health check.
113
+ */
114
+ async sendHealthCheck() {
115
+ switch (this.#preferredProtocol) {
116
+ case this.#supportedProtocols.V1:
117
+ try {
118
+ const message = await this.#buildLivenessRequest();
119
+ return await this.#v1Protocol.send(message);
120
+ }
121
+ catch (err) {
122
+ this.#logger.error(`ProtocolSession: v1 health check failed: ${err?.message ?? err}`);
123
+ return ResultCode.UNEXPECTED_ERROR; // TODO: Consider just propagating the error instead
124
+ }
125
+ case this.#supportedProtocols.LEGACY:
126
+ this.#logger.warn('ProtocolSession: health check not supported on LEGACY protocol');
127
+ return ResultCode.OK; // TODO: Consider implementing a new result code (e.g. NOT_SUPPORTED) instead of returning OK
128
+ default:
129
+ this.#logger.warn('ProtocolSession: preferred protocol not set. Call probe() first.');
130
+ return ResultCode.UNSPECIFIED; // TODO: Define a more specific result code.
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Tells whether the connected peer supports health checks, which is a feature of the v1 protocol.
136
+ * @returns {Boolean} True if health checks are supported in the preferred protocol, false otherwise.
137
+ */
138
+ isHealthCheckSupported() {
139
+ if (this.#preferredProtocol === null) {
140
+ throw new Error('ProtocolSession: preferred protocol not set. Call probe() first.');
141
+ }
142
+ return this.#preferredProtocol === this.#supportedProtocols.V1;
143
+ }
144
+
145
+ // TODO: Consider moving this method to be used only in V1 internally, just like 'encode'
146
+ decode(message) {
147
+ return this.#activeProtocol.decode(message);
148
+ }
149
+
150
+ async send(message) {
151
+ return this.#activeProtocol.send(message);
152
+ }
153
+
154
+ sendAndForget(message) {
155
+ this.#activeProtocol.sendAndForget(message);
38
156
  }
39
157
 
40
158
  close() {
@@ -42,7 +160,7 @@ class ProtocolSession {
42
160
  try {
43
161
  this.#legacyProtocol.close();
44
162
  } catch (e) {
45
- console.error('Failed to close legacy channel:', e); // TODO: Think about throwing instead
163
+ this.#logger.error(`ProtocolSession: failed to close legacy channel: ${e?.message ?? e}`); // TODO: Think about throwing instead
46
164
  }
47
165
  }
48
166
 
@@ -50,10 +168,19 @@ class ProtocolSession {
50
168
  try {
51
169
  this.#v1Protocol.close();
52
170
  } catch (e) {
53
- console.error('Failed to close v1 channel:', e); // TODO: Think about throwing instead
171
+ this.#logger.error(`ProtocolSession: failed to close v1 channel: ${e?.message ?? e}`); // TODO: Think about throwing instead
54
172
  }
55
173
  }
56
174
  }
175
+
176
+ async #buildLivenessRequest() {
177
+ if (!this.#wallet || !this.#config) {
178
+ throw new Error('ProtocolSession: wallet/config not set for liveness request');
179
+ }
180
+ const requestId = generateUUID();
181
+ return await networkMessageFactory(this.#wallet, this.#config)
182
+ .buildLivenessRequest(requestId, this.#capabilities);
183
+ }
57
184
  }
58
185
 
59
186
  export default ProtocolSession;
@@ -1,18 +1,20 @@
1
1
  import Protomux from 'protomux';
2
2
  import ProtocolInterface from './ProtocolInterface.js';
3
- import b4a from 'b4a';
4
3
  import c from 'compact-encoding';
4
+ import {encodeV1networkOperation, decodeV1networkOperation} from '../../../utils/protobuf/operationHelpers.js';
5
5
 
6
6
  class V1Protocol extends ProtocolInterface {
7
7
  #channel;
8
8
  #session;
9
- #config;
10
9
  #router;
10
+ #publicKeyHex;
11
+ #pendingRequestService;
11
12
 
12
- constructor(router, connection, config) {
13
- super(router, connection, config);
14
- this.#config = config;
13
+ constructor(router, connection, pendingRequestService, config) {
14
+ super(router, connection, pendingRequestService, config);
15
15
  this.#router = router;
16
+ this.#publicKeyHex = connection.remotePublicKey.toString('hex');
17
+ this.#pendingRequestService = pendingRequestService;
16
18
  this.init(connection);
17
19
  }
18
20
 
@@ -30,30 +32,47 @@ class V1Protocol extends ProtocolInterface {
30
32
 
31
33
  this.#channel = mux.createChannel({
32
34
  protocol: 'network/v1',
33
- onopen() { },
34
- onclose() { }
35
+ onopen() {
36
+ },
37
+ onclose() {
38
+ }
35
39
  });
36
40
 
37
41
  this.#channel.open();
38
42
 
39
43
  this.#session = this.#channel.addMessage({
40
44
  encoding: c.raw,
41
- onmessage: async (incomingMessage) => {
42
- try {
43
- if (b4a.isBuffer(incomingMessage)) {
44
- await this.#router.route(incomingMessage, connection, this.#session);
45
- } else {
46
- throw new Error('NetworkMessages: v1 message must be a buffer');
45
+ onmessage: (incomingMessage) => {
46
+ this.#router.route(incomingMessage, connection).catch((err) => {
47
+ console.error(`V1Protocol: unhandled router error: ${err.message}`);
48
+ try {
49
+ connection.end();
50
+ } catch {
47
51
  }
48
- } catch (error) {
49
- console.error(`NetworkMessages: Failed to handle incoming v1 message: ${error.message}`);
50
- }
52
+ });
51
53
  }
52
54
  });
53
55
  }
54
56
 
55
- send(message) {
56
- this.#session.send(message);
57
+ // TODO: Consider making this method private/internal-only, just like 'encode'
58
+ // NOTE: This method might be moved to v1/NetworkMessageRouter.js as it is only used there
59
+ decode(message) {
60
+ return decodeV1networkOperation(message);
61
+ }
62
+
63
+ async send(message) {
64
+ const encodedMessage = encodeV1networkOperation(message);
65
+ const msgReplyPromise = this.#pendingRequestService.registerPendingRequest(this.#publicKeyHex, message);
66
+ try {
67
+ this.#session.send(encodedMessage);
68
+ } catch (error) {
69
+ this.#pendingRequestService.rejectPendingRequest(message.id, error);
70
+ }
71
+ return msgReplyPromise;
72
+ }
73
+
74
+ sendAndForget(message) {
75
+ this.#session.send(encodeV1networkOperation(message));
57
76
  }
58
77
 
59
78
  close() {
@@ -0,0 +1,174 @@
1
+ import { ResultCode } from '../../../utils/constants.js';
2
+
3
+ // TODO: Consider how to behave with ResultCode.UNSPECIFIED
4
+
5
+ /**
6
+ * Sender actions are consumed by the message orchestrator after a validator responds.
7
+ * They define whether the validator should be treated as successful, rotated out, or kept
8
+ * in the pool without rotation for the current result code.
9
+ */
10
+ export const SENDER_ACTION = Object.freeze({
11
+ UNDEFINED: 'UNDEFINED',
12
+ SUCCESS: 'SUCCESS',
13
+ ROTATE: 'ROTATE',
14
+ NO_ROTATE: 'NO_ROTATE',
15
+ });
16
+
17
+ // Result codes that mean the validator completed the request successfully.
18
+ const SUCCESS_CODES = new Set([
19
+ ResultCode.OK,
20
+ ]);
21
+
22
+ // Result codes that should rotate the validator out of the sender pool after the response.
23
+ // In practice these are transport, protocol, validation, or validator-side failures that make
24
+ // the current peer unsuitable to keep as the next sender candidate.
25
+ const ROTATE_CODES = new Set([
26
+ ResultCode.UNSPECIFIED,
27
+ ResultCode.INVALID_PAYLOAD,
28
+ ResultCode.RATE_LIMITED,
29
+ ResultCode.SIGNATURE_INVALID,
30
+ ResultCode.UNEXPECTED_ERROR,
31
+ ResultCode.TIMEOUT,
32
+ ResultCode.NODE_HAS_NO_WRITE_ACCESS,
33
+ ResultCode.TX_ACCEPTED_PROOF_UNAVAILABLE,
34
+ ResultCode.NODE_OVERLOADED,
35
+ ResultCode.OPERATION_TYPE_UNKNOWN,
36
+ ResultCode.SCHEMA_VALIDATION_FAILED,
37
+ ResultCode.REQUESTER_ADDRESS_INVALID,
38
+ ResultCode.REQUESTER_PUBLIC_KEY_INVALID,
39
+ ResultCode.TX_HASH_MISMATCH,
40
+ ResultCode.TX_SIGNATURE_INVALID,
41
+ ResultCode.TX_EXPIRED,
42
+ ResultCode.TX_ALREADY_EXISTS,
43
+ ResultCode.OPERATION_ALREADY_COMPLETED,
44
+ ResultCode.REQUESTER_NOT_FOUND,
45
+ ResultCode.INSUFFICIENT_FEE_BALANCE,
46
+ ResultCode.EXTERNAL_BOOTSTRAP_EQUALS_MSB_BOOTSTRAP,
47
+ ResultCode.SELF_VALIDATION_FORBIDDEN,
48
+ ResultCode.ROLE_NODE_ENTRY_NOT_FOUND,
49
+ ResultCode.ROLE_NODE_ALREADY_WRITER,
50
+ ResultCode.ROLE_NODE_NOT_WHITELISTED,
51
+ ResultCode.ROLE_NODE_NOT_WRITER,
52
+ ResultCode.ROLE_NODE_IS_INDEXER,
53
+ ResultCode.ROLE_ADMIN_ENTRY_MISSING,
54
+ ResultCode.ROLE_INVALID_RECOVERY_CASE,
55
+ ResultCode.ROLE_UNKNOWN_OPERATION,
56
+ ResultCode.ROLE_INVALID_WRITER_KEY,
57
+ ResultCode.ROLE_INSUFFICIENT_FEE_BALANCE,
58
+ ResultCode.MSB_BOOTSTRAP_MISMATCH,
59
+ ResultCode.EXTERNAL_BOOTSTRAP_NOT_DEPLOYED,
60
+ ResultCode.EXTERNAL_BOOTSTRAP_TX_MISSING,
61
+ ResultCode.EXTERNAL_BOOTSTRAP_MISMATCH,
62
+ ResultCode.BOOTSTRAP_ALREADY_EXISTS,
63
+ ResultCode.TRANSFER_RECIPIENT_ADDRESS_INVALID,
64
+ ResultCode.TRANSFER_RECIPIENT_PUBLIC_KEY_INVALID,
65
+ ResultCode.TRANSFER_AMOUNT_TOO_LARGE,
66
+ ResultCode.TRANSFER_SENDER_NOT_FOUND,
67
+ ResultCode.TRANSFER_INSUFFICIENT_BALANCE,
68
+ ResultCode.TRANSFER_RECIPIENT_BALANCE_OVERFLOW,
69
+ ResultCode.TX_HASH_INVALID_FORMAT,
70
+ ResultCode.INTERNAL_ENQUEUE_VALIDATION_FAILED,
71
+ ResultCode.TX_COMMITTED_RECEIPT_MISSING,
72
+ ResultCode.VALIDATOR_RESPONSE_TX_TYPE_INVALID,
73
+ ResultCode.VALIDATOR_RESPONSE_TX_TYPE_UNKNOWN,
74
+ ResultCode.VALIDATOR_RESPONSE_TX_TYPE_UNSUPPORTED,
75
+ ResultCode.VALIDATOR_RESPONSE_SCHEMA_INVALID,
76
+ ResultCode.PENDING_REQUEST_MISSING_TX_DATA,
77
+ ResultCode.PROOF_PAYLOAD_MISMATCH,
78
+ ResultCode.VALIDATOR_WRITER_KEY_NOT_REGISTERED,
79
+ ResultCode.VALIDATOR_ADDRESS_MISMATCH,
80
+ ResultCode.VALIDATOR_NODE_ENTRY_NOT_FOUND,
81
+ ResultCode.VALIDATOR_NODE_NOT_WRITER,
82
+ ResultCode.VALIDATOR_WRITER_KEY_MISMATCH,
83
+ ResultCode.VALIDATOR_TX_OBJECT_INVALID,
84
+ ResultCode.VALIDATOR_VA_MISSING,
85
+ ResultCode.TX_INVALID_PAYLOAD
86
+ ]);
87
+
88
+ const NO_ROTATE_CODES = new Set([
89
+ ResultCode.TX_ALREADY_PENDING,
90
+ ]);
91
+
92
+ export function resultToValidatorAction(resultCode) {
93
+ if (SUCCESS_CODES.has(resultCode)) return SENDER_ACTION.SUCCESS;
94
+ if (ROTATE_CODES.has(resultCode)) return SENDER_ACTION.ROTATE;
95
+ if (NO_ROTATE_CODES.has(resultCode)) return SENDER_ACTION.NO_ROTATE;
96
+ return SENDER_ACTION.UNDEFINED;
97
+ }
98
+
99
+ /**
100
+ * Keep connection result codes:
101
+ * - ResultCode.OK
102
+ * - ResultCode.TIMEOUT
103
+ * - ResultCode.TX_ACCEPTED_PROOF_UNAVAILABLE
104
+ * - ResultCode.TX_ALREADY_PENDING
105
+ * - ResultCode.TX_HASH_INVALID_FORMAT
106
+ * - ResultCode.INTERNAL_ENQUEUE_VALIDATION_FAILED
107
+ * - ResultCode.TX_COMMITTED_RECEIPT_MISSING
108
+ * - ResultCode.VALIDATOR_RESPONSE_TX_TYPE_INVALID
109
+ * - ResultCode.VALIDATOR_RESPONSE_TX_TYPE_UNKNOWN
110
+ * - ResultCode.VALIDATOR_RESPONSE_TX_TYPE_UNSUPPORTED
111
+ * - ResultCode.VALIDATOR_RESPONSE_SCHEMA_INVALID
112
+ * - ResultCode.PENDING_REQUEST_MISSING_TX_DATA
113
+ * - ResultCode.PROOF_PAYLOAD_MISMATCH
114
+ * - ResultCode.VALIDATOR_WRITER_KEY_NOT_REGISTERED
115
+ * - ResultCode.VALIDATOR_ADDRESS_MISMATCH
116
+ * - ResultCode.VALIDATOR_NODE_ENTRY_NOT_FOUND
117
+ * - ResultCode.VALIDATOR_NODE_NOT_WRITER
118
+ * - ResultCode.VALIDATOR_WRITER_KEY_MISMATCH
119
+ * - ResultCode.VALIDATOR_TX_OBJECT_INVALID
120
+ * - ResultCode.VALIDATOR_VA_MISSING
121
+ */
122
+ const VALIDATOR_SIDE_END_CONNECTION_CODES = new Set([
123
+ // BASE_TRANSPORT_AND_VALIDATOR_STATUS
124
+ ResultCode.UNSPECIFIED,
125
+ ResultCode.INVALID_PAYLOAD,
126
+ ResultCode.RATE_LIMITED,
127
+ ResultCode.SIGNATURE_INVALID,
128
+ ResultCode.UNEXPECTED_ERROR,
129
+ ResultCode.NODE_HAS_NO_WRITE_ACCESS,
130
+ ResultCode.NODE_OVERLOADED,
131
+
132
+ // SHARED_VALIDATORS_REQUEST_PAYLOAD
133
+ ResultCode.OPERATION_TYPE_UNKNOWN,
134
+ ResultCode.SCHEMA_VALIDATION_FAILED,
135
+ ResultCode.REQUESTER_ADDRESS_INVALID,
136
+ ResultCode.REQUESTER_PUBLIC_KEY_INVALID,
137
+ ResultCode.TX_HASH_MISMATCH,
138
+ ResultCode.TX_SIGNATURE_INVALID,
139
+ ResultCode.TX_EXPIRED,
140
+ ResultCode.TX_ALREADY_EXISTS,
141
+ ResultCode.OPERATION_ALREADY_COMPLETED,
142
+ ResultCode.REQUESTER_NOT_FOUND,
143
+ ResultCode.INSUFFICIENT_FEE_BALANCE,
144
+ ResultCode.EXTERNAL_BOOTSTRAP_EQUALS_MSB_BOOTSTRAP,
145
+ ResultCode.SELF_VALIDATION_FORBIDDEN,
146
+ ResultCode.ROLE_NODE_ENTRY_NOT_FOUND,
147
+ ResultCode.ROLE_NODE_ALREADY_WRITER,
148
+ ResultCode.ROLE_NODE_NOT_WHITELISTED,
149
+ ResultCode.ROLE_NODE_NOT_WRITER,
150
+ ResultCode.ROLE_NODE_IS_INDEXER,
151
+ ResultCode.ROLE_ADMIN_ENTRY_MISSING,
152
+ ResultCode.ROLE_INVALID_RECOVERY_CASE,
153
+ ResultCode.ROLE_UNKNOWN_OPERATION,
154
+ ResultCode.ROLE_INVALID_WRITER_KEY,
155
+ ResultCode.ROLE_INSUFFICIENT_FEE_BALANCE,
156
+ ResultCode.MSB_BOOTSTRAP_MISMATCH,
157
+ ResultCode.EXTERNAL_BOOTSTRAP_NOT_DEPLOYED,
158
+ ResultCode.EXTERNAL_BOOTSTRAP_TX_MISSING,
159
+ ResultCode.EXTERNAL_BOOTSTRAP_MISMATCH,
160
+ ResultCode.BOOTSTRAP_ALREADY_EXISTS,
161
+ ResultCode.TRANSFER_RECIPIENT_ADDRESS_INVALID,
162
+ ResultCode.TRANSFER_RECIPIENT_PUBLIC_KEY_INVALID,
163
+ ResultCode.TRANSFER_AMOUNT_TOO_LARGE,
164
+ ResultCode.TRANSFER_SENDER_NOT_FOUND,
165
+ ResultCode.TRANSFER_INSUFFICIENT_BALANCE,
166
+ ResultCode.TRANSFER_RECIPIENT_BALANCE_OVERFLOW,
167
+
168
+ // VALIDATOR_RESPONSE_PROOF_AND_IDENTITY_VALIDATION
169
+ ResultCode.TX_INVALID_PAYLOAD,
170
+ ]);
171
+
172
+ export function shouldEndConnection(resultCode) {
173
+ return VALIDATOR_SIDE_END_CONNECTION_CODES.has(resultCode);
174
+ }
@@ -1,13 +1,12 @@
1
1
  import b4a from "b4a";
2
- import GetRequestHandler from "./handlers/GetRequestHandler.js";
3
- import ResponseHandler from "./handlers/ResponseHandler.js";
4
- import RoleOperationHandler from "../shared/handlers/RoleOperationHandler.js";
5
- import SubnetworkOperationHandler from "../shared/handlers/SubnetworkOperationHandler.js";
6
- import TransferOperationHandler from "../shared/handlers/TransferOperationHandler.js";
2
+ import _ from 'lodash';
3
+ import LegacyGetRequestHandler from "./handlers/LegacyGetRequestHandler.js";
4
+ import LegacyResponseHandler from "./handlers/LegacyResponseHandler.js";
5
+ import LegacyRoleOperationHandler from "./handlers/LegacyRoleOperationHandler.js";
6
+ import LegacySubnetworkOperationHandler from "./handlers/LegacySubnetworkOperationHandler.js";
7
+ import LegacyTransferOperationHandler from "./handlers/LegacyTransferOperationHandler.js";
7
8
  import { NETWORK_MESSAGE_TYPES } from '../../../../utils/constants.js';
8
9
  import * as operation from '../../../../utils/applyOperations.js';
9
- import State from "../../../state/State.js";
10
- import PeerWallet from "trac-wallet";
11
10
 
12
11
  class NetworkMessageRouter {
13
12
  #handlers;
@@ -15,32 +14,35 @@ class NetworkMessageRouter {
15
14
 
16
15
  /**
17
16
  * @param {State} state
18
- * @param {PeerWallet} wallet
17
+ * @param {IWallet} wallet
19
18
  * @param {TransactionRateLimiterService} rateLimiterService
20
19
  * @param {TransactionPoolService} txPoolService
21
- * @param {ConnectionManager} connectionManager
22
20
  * @param {Config} config
23
21
  **/
24
- constructor(state, wallet, rateLimiterService, txPoolService, connectionManager, config) {
22
+ constructor(state, wallet, rateLimiterService, txPoolService, config) {
25
23
  this.#config = config;
26
24
 
27
25
  this.#handlers = {
28
- get: new GetRequestHandler(wallet, state),
29
- response: new ResponseHandler(state, wallet, connectionManager, this.#config),
30
- roleTransaction: new RoleOperationHandler(state, wallet, rateLimiterService, txPoolService, this.#config),
31
- subNetworkTransaction: new SubnetworkOperationHandler(state, wallet, rateLimiterService, txPoolService, this.#config),
32
- tracNetworkTransaction: new TransferOperationHandler(state, wallet, rateLimiterService, txPoolService, this.#config),
26
+ get: new LegacyGetRequestHandler(wallet, state),
27
+ response: new LegacyResponseHandler(state, wallet, this.#config),
28
+ roleTransaction: new LegacyRoleOperationHandler(state, wallet, rateLimiterService, txPoolService, this.#config),
29
+ subNetworkTransaction: new LegacySubnetworkOperationHandler(state, wallet, rateLimiterService, txPoolService, this.#config),
30
+ tracNetworkTransaction: new LegacyTransferOperationHandler(state, wallet, rateLimiterService, txPoolService, this.#config),
31
+
33
32
  }
34
33
  }
35
34
 
36
- // NOTE: messageProtomux can be deleted, ad this is a session, and we can extract this from connection
37
- async route(incomingMessage, connection, messageProtomux) {
35
+ async route(incomingMessage, connection) {
36
+ this.#preValidate(incomingMessage);
38
37
  const channelString = b4a.toString(this.#config.channel, 'utf8');
38
+
39
+ // We received a legacy message, so we set the connection protocol accordingly
40
+ connection.protocolSession.setLegacyAsPreferredProtocol();
39
41
  if (this.#isGetRequest(incomingMessage)) {
40
- await this.#handlers.get.handle(incomingMessage, messageProtomux, connection, channelString);
42
+ await this.#handlers.get.handle(incomingMessage, connection, channelString);
41
43
  }
42
44
  else if (this.#isResponse(incomingMessage)) {
43
- await this.#handlers.response.handle(incomingMessage, connection, channelString);
45
+ await this.#handlers.response.handle(incomingMessage, channelString);
44
46
  }
45
47
  else if (this.#isRoleAccessOperation(incomingMessage)) {
46
48
  await this.#handlers.roleTransaction.handle(incomingMessage, connection);
@@ -54,14 +56,18 @@ class NetworkMessageRouter {
54
56
  else {
55
57
  throw new Error(`Failed to route message. Pubkey of requester is ${connection.remotePublicKey ? b4a.toString(connection.remotePublicKey, 'hex') : 'unknown'}`);
56
58
  }
59
+ }
57
60
 
61
+ #preValidate(message) {
62
+ if (!_.isPlainObject(message) && typeof message !== 'string') {
63
+ throw new Error('Invalid message format: expected object or string.');
64
+ }
58
65
  }
59
66
 
60
67
  #isGetRequest(message) {
61
68
  return Object.values(NETWORK_MESSAGE_TYPES.GET).includes(message);
62
69
  }
63
70
 
64
-
65
71
  #isResponse(message) {
66
72
  return Object.values(NETWORK_MESSAGE_TYPES.RESPONSE).includes(message.op);
67
73
  }
@@ -1,6 +1,7 @@
1
1
  import b4a from 'b4a';
2
+ import {publicKeyToAddress} from "../../../../../utils/helpers.js";
2
3
 
3
- class BaseOperationHandler {
4
+ class BaseStateOperationHandler {
4
5
  #state;
5
6
  #wallet;
6
7
  #rateLimiter;
@@ -9,14 +10,14 @@ class BaseOperationHandler {
9
10
 
10
11
  /**
11
12
  * @param {State} state
12
- * @param {PeerWallet} wallet
13
+ * @param {IWallet} wallet
13
14
  * @param {TransactionRateLimiterService} rateLimiter
14
15
  * @param {TransactionPoolService} txPoolService
15
16
  * @param {Config} config
16
17
  **/
17
18
  constructor(state, wallet, rateLimiter, txPoolService, config) {
18
- if (new.target === BaseOperationHandler) {
19
- throw new Error('BaseOperationHandler is abstract and cannot be instantiated directly');
19
+ if (new.target === BaseStateOperationHandler) {
20
+ throw new Error('BaseStateOperationHandler is abstract and cannot be instantiated directly');
20
21
  }
21
22
  this.#state = state;
22
23
  this.#wallet = wallet;
@@ -37,18 +38,18 @@ class BaseOperationHandler {
37
38
  throw new Error('OperationHandler: State is not writable or is an indexer without admin privileges.');
38
39
  }
39
40
 
40
- if (this.#txPoolService.tx_pool.length >= this.#config.transactionPoolSize) {
41
- throw new Error("OperationHandler: Transaction pool is full, ignoring incoming transaction.");
42
- }
43
-
44
- if (b4a.byteLength(JSON.stringify(payload)) > this.#config.maxPartialTxPayloadByteSize) {
45
- throw new Error(`OperationHandler: Payload size exceeds maximum limit of ${this.#config.maxPartialTxPayloadByteSize} bytes by ${b4a.byteLength(JSON.stringify(payload)) - this.#config.maxPartialTxPayloadByteSize} bytes.`);
41
+ this.#txPoolService.validateEnqueue();
42
+ if (b4a.byteLength(JSON.stringify(payload)) > this.#config.transactionPoolSize) {
43
+ throw new Error(
44
+ `OperationHandler: Payload size exceeds maximum limit of ${this.#config.transactionPoolSize} bytes by ${b4a.byteLength(JSON.stringify(payload)) - this.#config.transactionPoolSize} bytes.`);
46
45
  }
47
46
 
48
47
  if (!this.#config.disableRateLimit) {
49
- const shouldDisconnect = this.#rateLimiter.handleRateLimit(connection);
48
+ const shouldDisconnect = this.#rateLimiter.legacyHandleRateLimit(connection);
50
49
  if (shouldDisconnect) {
51
- throw new Error(`OperationHandler: Rate limit exceeded for peer ${b4a.toString(connection.remotePublicKey, 'hex')}. Disconnecting...`);
50
+ throw new Error(
51
+ `OperationHandler: Rate limit exceeded for ${publicKeyToAddress(connection.remotePublicKey, this.#config)}. Disconnecting...`
52
+ );
52
53
  }
53
54
  }
54
55
  }
@@ -58,9 +59,19 @@ class BaseOperationHandler {
58
59
  await this.handleOperation(payload, connection);
59
60
  }
60
61
 
61
- async handleOperation(payload, connection) {
62
+ enqueueTransaction(txHash, encodedOperation) {
63
+ try {
64
+ this.#txPoolService.addTransaction(txHash, encodedOperation);
65
+ } catch (error) {
66
+ throw new Error(
67
+ `${this.constructor.name}: Failed to add transaction ${txHash} to transaction pool: ${error?.message ?? String(error)}`
68
+ );
69
+ }
70
+ }
71
+
72
+ async handleOperation(_payload, _connection) {
62
73
  throw new Error('handleOperation must be implemented by child class');
63
74
  }
64
75
 
65
76
  }
66
- export default BaseOperationHandler;
77
+ export default BaseStateOperationHandler;