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
@@ -1,167 +0,0 @@
1
- import b4a from 'b4a';
2
- import { test } from 'brittle';
3
- import nodeEntryUtils from '../../../../../src/core/state/utils/nodeEntry.js';
4
- import { EntryType } from '../../../../../src/utils/constants.js';
5
- import lengthEntryUtils from '../../../../../src/core/state/utils/lengthEntry.js';
6
- import { eventFlush } from '../../../../helpers/autobaseTestHelpers.js';
7
- import { initializeBalances, whitelistAddress } from '../common/commonScenarioHelper.js';
8
- import { promotePeerToWriter } from '../addWriter/addWriterScenarioHelpers.js';
9
- import {
10
- setupAddIndexerScenario,
11
- selectIndexerCandidatePeer,
12
- buildAddIndexerPayload,
13
- assertAddIndexerSuccessState,
14
- ensureIndexerRegistration
15
- } from '../addIndexer/addIndexerScenarioHelpers.js';
16
- import { buildRemoveIndexerPayload, assertRemoveIndexerSuccessState } from './removeIndexerScenarioHelpers.js';
17
-
18
- export default function removeIndexerRemoveMultipleIndexersScenario() {
19
- test('State.apply removeIndexer removes multiple indexers sequentially, leaving only admin', async t => {
20
- const context = await setupAddIndexerScenario(t, { nodes: 4 });
21
- const adminPeer = context.adminBootstrap;
22
- const initialIndexerCount = getIndexerCount(adminPeer.base);
23
-
24
- const candidates = [
25
- selectIndexerCandidatePeer(context, 0),
26
- selectIndexerCandidatePeer(context, 1),
27
- selectIndexerCandidatePeer(context, 2)
28
- ];
29
-
30
- for (const peer of candidates.slice(1)) {
31
- await prepareWriterCandidate(t, context, peer);
32
- }
33
-
34
- for (const peer of candidates) {
35
- await promoteWriterToIndexer(t, context, peer);
36
- }
37
-
38
- for (const peer of candidates) {
39
- const writersLengthBefore = await readWritersLength(adminPeer.base);
40
- const indexerEntryBefore = await adminPeer.base.view.get(peer.wallet.address);
41
- const adminEntryBefore = await adminPeer.base.view.get(adminPeer.wallet.address);
42
-
43
- ensureIndexerRegistration(adminPeer.base, peer.base.local.key);
44
-
45
- const payload = await buildRemoveIndexerPayload(context, {
46
- indexerPeer: peer,
47
- adminPeer
48
- });
49
-
50
- await adminPeer.base.append(payload);
51
- await adminPeer.base.update();
52
- await eventFlush();
53
-
54
- await assertRemoveIndexerSuccessState(t, context, {
55
- indexerPeer: peer,
56
- adminPeer,
57
- indexerEntryBefore: { value: b4a.from(indexerEntryBefore.value) },
58
- adminEntryBefore: { value: b4a.from(adminEntryBefore.value) },
59
- payload,
60
- writersLengthBefore,
61
- skipSync: true
62
- });
63
-
64
- }
65
-
66
- assertIndexerCount(t, context, 1);
67
- await assertOnlyAdminIsIndexer(t, context);
68
- });
69
- }
70
-
71
- async function prepareWriterCandidate(t, context, peer) {
72
- const funding = context.addWriterScenario?.writerInitialBalance;
73
- if (!funding) {
74
- throw new Error('addIndexer scenarios require writerInitialBalance buffer.');
75
- }
76
- const expectedWriterIndex = await deriveNextWriterIndex(context.adminBootstrap.base);
77
- await initializeBalances(context, [[peer.wallet.address, funding]]);
78
- await whitelistAddress(context, peer.wallet.address);
79
- await promotePeerToWriter(t, context, { readerPeer: peer, expectedWriterIndex });
80
- }
81
-
82
- async function promoteWriterToIndexer(t, context, writerPeer) {
83
- const adminPeer = context.adminBootstrap;
84
- const writerAddress = writerPeer.wallet.address;
85
-
86
- const writerEntryBefore = await adminPeer.base.view.get(writerAddress);
87
- t.ok(writerEntryBefore, 'writer entry exists before addIndexer');
88
- const adminEntryBefore = await adminPeer.base.view.get(adminPeer.wallet.address);
89
- t.ok(adminEntryBefore, 'admin entry exists before addIndexer');
90
-
91
- const payload = await buildAddIndexerPayload(context, {
92
- writerPeer,
93
- adminPeer
94
- });
95
-
96
- await adminPeer.base.append(payload);
97
- await adminPeer.base.update();
98
- await eventFlush();
99
-
100
- await assertAddIndexerSuccessState(t, context, {
101
- writerPeer,
102
- adminPeer,
103
- writerEntryBefore: { value: b4a.from(writerEntryBefore.value) },
104
- adminEntryBefore: { value: b4a.from(adminEntryBefore.value) },
105
- payload,
106
- skipSync: true
107
- });
108
- }
109
-
110
- function getIndexerCount(base) {
111
- return Object.values(base.system.indexers ?? {}).length;
112
- }
113
-
114
- function assertIndexerCount(t, context, expectedCount) {
115
- const base = context.adminBootstrap.base;
116
- const count = getIndexerCount(base);
117
- t.is(count, expectedCount, 'admin observes expected indexer count');
118
- }
119
-
120
- async function assertOnlyAdminIsIndexer(t, context) {
121
- const adminKey = context.adminBootstrap.base.local.key;
122
- const membership = Object.values(context.adminBootstrap.base.system.indexers ?? {});
123
- t.is(membership.length, 1, 'admin retains a single indexer');
124
- const onlyEntry = membership[0]?.key;
125
- t.ok(onlyEntry && b4a.equals(onlyEntry, adminKey), 'admin stays sole indexer');
126
-
127
- // Removed indexers should now be writers without validator membership (admin view).
128
- for (const candidate of context.peers.slice(1, 4)) {
129
- await assertNodeIsWriterNonIndexer(t, candidate, [context.adminBootstrap]);
130
- }
131
- }
132
-
133
- async function assertNodeIsWriterNonIndexer(t, targetPeer, allPeers) {
134
- const writingKey = targetPeer.base.local.key;
135
- for (const peer of allPeers) {
136
- const entry = await peer.base.view.get(targetPeer.wallet.address);
137
- t.ok(entry, `${peer.name} sees downgraded entry for ${targetPeer.wallet.address}`);
138
- const decoded = nodeEntryUtils.decode(entry?.value);
139
- t.ok(decoded, `${peer.name} decodes downgraded entry for ${targetPeer.wallet.address}`);
140
- if (!decoded) continue;
141
- t.is(decoded.isIndexer, false, `${peer.name} marks ${targetPeer.wallet.address} as non-indexer`);
142
- t.is(decoded.isWriter, true, `${peer.name} keeps ${targetPeer.wallet.address} as writer`);
143
- t.is(decoded.isWhitelisted, true, `${peer.name} keeps ${targetPeer.wallet.address} whitelisted`);
144
- const hasMembership = indexerMembershipIncludes(peer.base, writingKey);
145
- t.is(hasMembership, false, `${peer.name} does not keep ${targetPeer.wallet.address} in validator set`);
146
- }
147
- }
148
-
149
- async function readWritersLength(base) {
150
- const entry = await base.view.get(EntryType.WRITERS_LENGTH);
151
- if (!entry?.value) return 0;
152
- return entry.value.readUInt32BE();
153
- }
154
-
155
- async function deriveNextWriterIndex(base) {
156
- const entry = await base.view.get(EntryType.WRITERS_LENGTH);
157
- if (!entry?.value) {
158
- return 0;
159
- }
160
- return lengthEntryUtils.decodeBE(entry.value);
161
- }
162
-
163
- function indexerMembershipIncludes(base, writingKey) {
164
- const entries = base?.system?.indexers;
165
- if (!entries) return false;
166
- return Object.values(entries).some(entry => entry?.key && b4a.equals(entry.key, writingKey));
167
- }
@@ -1,429 +0,0 @@
1
- import b4a from 'b4a';
2
- import nodeEntryUtils from '../../../../../src/core/state/utils/nodeEntry.js';
3
- import { BALANCE_FEE, toBalance } from '../../../../../src/core/state/utils/balance.js';
4
- import addressUtils from '../../../../../src/core/state/utils/address.js';
5
- import nodeRoleUtils from '../../../../../src/core/state/utils/roles.js';
6
- import { EntryType } from '../../../../../src/utils/constants.js';
7
- import { safeDecodeApplyOperation } from '../../../../../src/utils/protobuf/operationHelpers.js';
8
- import { eventFlush } from '../../../../helpers/autobaseTestHelpers.js';
9
- import {
10
- setupAddIndexerScenario,
11
- selectIndexerCandidatePeer,
12
- buildAddIndexerPayload,
13
- buildRemoveIndexerPayload as buildRemoveIndexerPayloadFromAddHelper,
14
- buildRemoveIndexerPayloadWithTxValidity as buildRemoveIndexerPayloadWithTxValidityFromAddHelper,
15
- assertAddIndexerSuccessState
16
- } from '../addIndexer/addIndexerScenarioHelpers.js';
17
- import { config } from '../../../../helpers/config.js';
18
-
19
- export async function setupRemoveIndexerScenario(t, options = {}) {
20
- const context = await setupAddIndexerScenario(t, options);
21
- const adminPeer = context.adminBootstrap;
22
- const indexerPeer = selectIndexerCandidatePeer(context);
23
-
24
- const writerEntryBefore = await adminPeer.base.view.get(indexerPeer.wallet.address);
25
- if (!writerEntryBefore?.value) {
26
- throw new Error('setupRemoveIndexerScenario requires a writer entry before promotion.');
27
- }
28
- const adminEntryBefore = await adminPeer.base.view.get(adminPeer.wallet.address);
29
- if (!adminEntryBefore?.value) {
30
- throw new Error('setupRemoveIndexerScenario requires an admin entry before promotion.');
31
- }
32
-
33
- const addPayload = await buildAddIndexerPayload(context, { writerPeer: indexerPeer, adminPeer });
34
- await adminPeer.base.append(addPayload);
35
- await adminPeer.base.update();
36
- await eventFlush();
37
-
38
- await assertAddIndexerSuccessState(t, context, {
39
- writerPeer: indexerPeer,
40
- adminPeer,
41
- writerEntryBefore: { value: b4a.from(writerEntryBefore.value) },
42
- adminEntryBefore: { value: b4a.from(adminEntryBefore.value) },
43
- payload: addPayload
44
- });
45
-
46
- const indexerEntryBeforeRemoval = await adminPeer.base.view.get(indexerPeer.wallet.address);
47
- const adminEntryBeforeRemoval = await adminPeer.base.view.get(adminPeer.wallet.address);
48
- const writersLengthBeforeRemoval = await readWritersLength(adminPeer.base);
49
-
50
- context.removeIndexerScenario = {
51
- ...(context.removeIndexerScenario ?? {}),
52
- indexerPeer,
53
- indexerEntryBeforeRemoval: indexerEntryBeforeRemoval
54
- ? { value: b4a.from(indexerEntryBeforeRemoval.value) }
55
- : null,
56
- adminEntryBeforeRemoval: adminEntryBeforeRemoval
57
- ? { value: b4a.from(adminEntryBeforeRemoval.value) }
58
- : null,
59
- writersLengthBeforeRemoval
60
- };
61
-
62
- return context;
63
- }
64
-
65
- export async function buildRemoveIndexerPayload(context, options = {}) {
66
- return buildRemoveIndexerPayloadFromAddHelper(context, options);
67
- }
68
-
69
- export async function buildRemoveIndexerPayloadWithTxValidity(context, mutatedTxValidity, options = {}) {
70
- return buildRemoveIndexerPayloadWithTxValidityFromAddHelper(context, mutatedTxValidity, options);
71
- }
72
-
73
- export async function applyWithRemoveIndexerRoleUpdateFailure(context, invalidPayload) {
74
- const adminPeer = context.adminBootstrap ?? context.bootstrap ?? context.peers?.[0] ?? null;
75
- if (!adminPeer?.base) {
76
- throw new Error('RemoveIndexer role mutation failure scenario requires a writable node.');
77
- }
78
-
79
- const originalSetter = nodeEntryUtils.setRoleAndWriterKey;
80
- let shouldFail = true;
81
- nodeEntryUtils.setRoleAndWriterKey = function patchedSetRoleAndWriterKey(...args) {
82
- if (shouldFail) {
83
- shouldFail = false;
84
- return null;
85
- }
86
- return originalSetter.apply(this, args);
87
- };
88
-
89
- try {
90
- await adminPeer.base.append(invalidPayload);
91
- await adminPeer.base.update();
92
- await eventFlush();
93
- } finally {
94
- nodeEntryUtils.setRoleAndWriterKey = originalSetter;
95
- }
96
- }
97
-
98
- export async function applyWithoutIndexerMembership(context, invalidPayload) {
99
- const adminPeer = context.adminBootstrap ?? context.bootstrap ?? context.peers?.[0] ?? null;
100
- const indexerPeer = context.removeIndexerScenario?.indexerPeer ?? selectIndexerCandidatePeer(context);
101
- if (!adminPeer?.base || !indexerPeer?.wallet?.address) {
102
- throw new Error('RemoveIndexer missing indexer membership scenario requires a writable admin and indexer peer.');
103
- }
104
-
105
- const targetAddress = indexerPeer.wallet.address;
106
- const targetAddressBuffer = addressUtils.addressToBuffer(targetAddress, config.addressPrefix);
107
- if (!targetAddressBuffer) {
108
- throw new Error('RemoveIndexer missing indexer membership scenario requires a decodable indexer address.');
109
- }
110
-
111
- const replacementWriterKey = b4a.alloc(32, 0xaa);
112
- const originalApply = adminPeer.base._handlers.apply;
113
-
114
- adminPeer.base._handlers.apply = async function patchedApply(nodes, view, baseCtx) {
115
- let mutatedOnce = false;
116
- const originalBatch = view.batch;
117
- view.batch = function patchedBatch(...args) {
118
- const batch = originalBatch.apply(this, args);
119
- if (!batch?.get) return batch;
120
-
121
- const originalGet = batch.get.bind(batch);
122
- batch.get = async key => {
123
- if (mutatedOnce) return originalGet(key);
124
-
125
- const isTarget =
126
- (typeof key === 'string' && key === targetAddress) ||
127
- (b4a.isBuffer(key) && b4a.equals(key, targetAddressBuffer));
128
- if (!isTarget) return originalGet(key);
129
-
130
- const entry = await originalGet(key);
131
- if (!entry?.value) {
132
- throw new Error('RemoveIndexer missing indexer membership scenario requires an existing indexer entry.');
133
- }
134
-
135
- const mutated = nodeEntryUtils.setRoleAndWriterKey(
136
- b4a.from(entry.value),
137
- nodeRoleUtils.NodeRole.INDEXER,
138
- replacementWriterKey
139
- );
140
- if (!mutated) {
141
- throw new Error('Failed to mutate indexer writing key.');
142
- }
143
-
144
- mutatedOnce = true;
145
- return { ...entry, value: mutated };
146
- };
147
-
148
- return batch;
149
- };
150
-
151
- try {
152
- return await originalApply.call(this, nodes, view, baseCtx);
153
- } finally {
154
- view.batch = originalBatch;
155
- }
156
- };
157
-
158
- try {
159
- await adminPeer.base.append(invalidPayload);
160
- await adminPeer.base.update();
161
- await eventFlush();
162
- } finally {
163
- adminPeer.base._handlers.apply = originalApply;
164
- }
165
- }
166
-
167
- export async function assertRemoveIndexerSuccessState(
168
- t,
169
- context,
170
- {
171
- indexerPeer = context.removeIndexerScenario?.indexerPeer ?? selectIndexerCandidatePeer(context),
172
- adminPeer = context.adminBootstrap,
173
- indexerEntryBefore = context.removeIndexerScenario?.indexerEntryBeforeRemoval,
174
- adminEntryBefore = context.removeIndexerScenario?.adminEntryBeforeRemoval,
175
- payload,
176
- writersLengthBefore = context.removeIndexerScenario?.writersLengthBeforeRemoval,
177
- skipSync = false
178
- } = {}
179
- ) {
180
- if (!indexerEntryBefore?.value) {
181
- throw new Error('assertRemoveIndexerSuccessState requires the indexer entry before removal.');
182
- }
183
- if (!adminEntryBefore?.value) {
184
- throw new Error('assertRemoveIndexerSuccessState requires the admin entry before removal.');
185
- }
186
- if (!payload) {
187
- throw new Error('assertRemoveIndexerSuccessState requires the removeIndexer payload.');
188
- }
189
- if (typeof writersLengthBefore !== 'number') {
190
- throw new Error('assertRemoveIndexerSuccessState requires writersLengthBefore.');
191
- }
192
-
193
- const decodedBefore = nodeEntryUtils.decode(indexerEntryBefore.value);
194
- t.ok(decodedBefore, 'indexer entry before removeIndexer decodes');
195
- if (!decodedBefore) return;
196
- t.is(decodedBefore.isWhitelisted, true, 'indexer is whitelisted before removal');
197
- t.is(decodedBefore.isWriter, true, 'indexer retains writer role before removal');
198
- t.is(decodedBefore.isIndexer, true, 'indexer role set before removal');
199
-
200
- const indexerEntryAfter = await adminPeer.base.view.get(indexerPeer.wallet.address);
201
- t.ok(indexerEntryAfter, 'indexer entry exists after removeIndexer');
202
- const decodedAfter = nodeEntryUtils.decode(indexerEntryAfter?.value);
203
- t.ok(decodedAfter, 'indexer entry decodes after removeIndexer');
204
- if (!decodedAfter) return;
205
- t.is(decodedAfter.isWhitelisted, true, 'indexer remains whitelisted after removal');
206
- t.is(decodedAfter.isWriter, true, 'node downgraded to writer after removeIndexer');
207
- t.is(decodedAfter.isIndexer, false, 'indexer flag cleared after removeIndexer');
208
- t.ok(b4a.equals(decodedAfter.wk, decodedBefore.wk), 'writer key preserved after removeIndexer');
209
- t.ok(
210
- b4a.equals(decodedAfter.balance, decodedBefore.balance),
211
- 'node balance preserved after removeIndexer'
212
- );
213
- t.ok(
214
- b4a.equals(decodedAfter.stakedBalance, decodedBefore.stakedBalance),
215
- 'node staked balance preserved after removeIndexer'
216
- );
217
- t.ok(b4a.equals(decodedAfter.license, decodedBefore.license), 'license preserved after removeIndexer');
218
-
219
- await assertWriterRegistry(t, adminPeer.base, decodedBefore.wk, indexerPeer.wallet.address);
220
- await assertWriterIndexUpdates(t, adminPeer.base, writersLengthBefore, indexerPeer.wallet.address);
221
- await assertAdminFeeDeducted(t, adminPeer.base, adminEntryBefore.value, adminPeer.wallet.address);
222
- await assertRemoveIndexerPayloadMetadata(
223
- t,
224
- adminPeer.base,
225
- payload,
226
- adminPeer.wallet.address,
227
- indexerPeer.wallet.address
228
- );
229
- assertIndexerMembershipRemoved(t, adminPeer.base, decodedBefore.wk);
230
-
231
- if (!skipSync) {
232
- await context.sync();
233
- await assertDemotedNodeState(t, indexerPeer.base, indexerPeer.wallet.address, decodedBefore.wk);
234
- }
235
- }
236
-
237
- export async function assertRemoveIndexerFailureState(
238
- t,
239
- context,
240
- {
241
- indexerPeer = context.removeIndexerScenario?.indexerPeer ?? selectIndexerCandidatePeer(context),
242
- adminPeer = context.adminBootstrap,
243
- writersLengthBefore = context.removeIndexerScenario?.writersLengthBeforeRemoval,
244
- skipSync = false
245
- } = {}
246
- ) {
247
- const base = adminPeer.base;
248
- const writersLength = typeof writersLengthBefore === 'number'
249
- ? writersLengthBefore
250
- : await readWritersLength(base);
251
-
252
- await assertIndexerStillRegistered(t, base, indexerPeer, writersLength);
253
-
254
- if (!skipSync) {
255
- await context.sync();
256
- await assertIndexerStillRegistered(t, indexerPeer.base, indexerPeer, writersLength);
257
- }
258
- }
259
-
260
- export async function assertRemoveIndexerGuardFailureState(
261
- t,
262
- context,
263
- {
264
- indexerPeer = context.removeIndexerScenario?.indexerPeer ?? selectIndexerCandidatePeer(context),
265
- adminPeer = context.adminBootstrap,
266
- skipSync = false
267
- } = {}
268
- ) {
269
- await assertMinimalIndexerState(t, adminPeer.base, indexerPeer);
270
-
271
- if (!skipSync) {
272
- await context.sync();
273
- await assertMinimalIndexerState(t, indexerPeer.base, indexerPeer);
274
- }
275
- }
276
-
277
- async function assertWriterRegistry(t, base, writingKey, expectedAddress) {
278
- const registryKey = EntryType.WRITER_ADDRESS + writingKey.toString('hex');
279
- const entry = await base.view.get(registryKey);
280
- t.ok(entry, 'writer registry entry exists after removeIndexer');
281
- const addressBuffer = addressUtils.addressToBuffer(expectedAddress, config.addressPrefix);
282
- t.ok(addressBuffer, 'indexer address encodes to buffer');
283
- if (!entry?.value || !addressBuffer) return;
284
- t.ok(
285
- b4a.equals(entry.value, addressBuffer),
286
- 'writer registry maps writing key to downgraded writer address'
287
- );
288
- }
289
-
290
- async function assertWriterIndexUpdates(t, base, lengthBefore, expectedAddress) {
291
- const lengthAfter = await readWritersLength(base);
292
- t.is(lengthAfter, lengthBefore + 1, 'writers length increments after removeIndexer');
293
-
294
- const indexEntry = await base.view.get(EntryType.WRITERS_INDEX + lengthBefore);
295
- t.ok(indexEntry, 'writers index entry stored after removeIndexer');
296
- const addressBuffer = addressUtils.addressToBuffer(expectedAddress, config.addressPrefix);
297
- if (!indexEntry?.value || !addressBuffer) return;
298
- t.ok(
299
- b4a.equals(indexEntry.value, addressBuffer),
300
- 'writers index entry stores downgraded writer address'
301
- );
302
- }
303
-
304
- async function assertAdminFeeDeducted(t, base, adminEntryBeforeValue, adminAddress) {
305
- const decodedAdminBefore = nodeEntryUtils.decode(adminEntryBeforeValue);
306
- t.ok(decodedAdminBefore, 'admin entry before removeIndexer decodes');
307
- if (!decodedAdminBefore) return;
308
-
309
- const adminBalanceBefore = toBalance(decodedAdminBefore.balance);
310
- t.ok(adminBalanceBefore, 'admin balance before removeIndexer decodes');
311
- if (!adminBalanceBefore) return;
312
-
313
- const adminEntryAfter = await base.view.get(adminAddress);
314
- t.ok(adminEntryAfter, 'admin entry exists after removeIndexer');
315
- const decodedAdminAfter = nodeEntryUtils.decode(adminEntryAfter?.value);
316
- t.ok(decodedAdminAfter, 'admin entry decodes after removeIndexer');
317
- if (!decodedAdminAfter) return;
318
-
319
- const adminBalanceAfter = toBalance(decodedAdminAfter.balance);
320
- t.ok(adminBalanceAfter, 'admin balance after removeIndexer decodes');
321
- if (!adminBalanceAfter) return;
322
-
323
- const expectedBalance = adminBalanceBefore.sub(BALANCE_FEE);
324
- t.ok(expectedBalance, 'admin balance after fee computation succeeds');
325
- if (!expectedBalance) return;
326
-
327
- t.ok(
328
- b4a.equals(decodedAdminAfter.balance, expectedBalance.value),
329
- 'admin balance reduced by removeIndexer fee'
330
- );
331
- t.ok(
332
- b4a.equals(decodedAdminAfter.stakedBalance, decodedAdminBefore.stakedBalance),
333
- 'admin staked balance remains unchanged after removeIndexer'
334
- );
335
- }
336
-
337
- async function assertRemoveIndexerPayloadMetadata(t, base, payload, expectedAdmin, expectedTarget) {
338
- const decodedOperation = safeDecodeApplyOperation(payload);
339
- t.ok(decodedOperation, 'removeIndexer payload decodes');
340
- if (!decodedOperation) return;
341
-
342
- const requesterAddressBuffer = decodedOperation.address;
343
- t.ok(requesterAddressBuffer, 'removeIndexer payload contains requester address');
344
- const requesterAddress = addressUtils.bufferToAddress(requesterAddressBuffer, config.addressPrefix);
345
- t.ok(requesterAddress, 'removeIndexer requester address decodes');
346
- if (requesterAddress) {
347
- t.is(requesterAddress, expectedAdmin, 'removeIndexer payload signed by admin');
348
- }
349
-
350
- const targetAddressBuffer = decodedOperation?.aco?.ia;
351
- t.ok(targetAddressBuffer, 'removeIndexer payload contains target indexer address');
352
- const targetAddress = addressUtils.bufferToAddress(targetAddressBuffer, config.addressPrefix);
353
- t.ok(targetAddress, 'removeIndexer target address decodes');
354
- if (targetAddress) {
355
- t.is(targetAddress, expectedTarget, 'removeIndexer payload nominates expected indexer');
356
- }
357
-
358
- const txHashBuffer = decodedOperation?.aco?.tx;
359
- t.ok(txHashBuffer, 'removeIndexer tx hash extracted');
360
- if (txHashBuffer) {
361
- const txEntry = await base.view.get(txHashBuffer.toString('hex'));
362
- t.ok(txEntry, 'removeIndexer transaction recorded for replay protection');
363
- }
364
- }
365
-
366
- function assertIndexerMembershipRemoved(t, base, writingKey) {
367
- const hasMembership = indexerMembershipIncludes(base, writingKey);
368
- t.is(hasMembership, false, 'indexer writer key removed from validator set');
369
- }
370
-
371
- async function assertDemotedNodeState(t, base, address, writingKey) {
372
- const entry = await base.view.get(address);
373
- t.ok(entry, 'downgraded entry exists after removeIndexer');
374
- const decoded = nodeEntryUtils.decode(entry?.value);
375
- t.ok(decoded, 'downgraded entry decodes after removeIndexer');
376
- if (!decoded) return;
377
- t.is(decoded.isIndexer, false, 'node remains non-indexer after removeIndexer sync');
378
- t.is(decoded.isWriter, true, 'node remains writer after removeIndexer sync');
379
- t.is(decoded.isWhitelisted, true, 'node remains whitelisted after removeIndexer sync');
380
- t.ok(b4a.equals(decoded.wk, writingKey), 'writer key preserved after removeIndexer sync');
381
- assertIndexerMembershipRemoved(t, base, writingKey);
382
- }
383
-
384
- async function assertIndexerStillRegistered(t, base, indexerPeer, writersLengthBefore) {
385
- const entry = await base.view.get(indexerPeer.wallet.address);
386
- t.ok(entry, 'indexer entry persists after failed removeIndexer');
387
- const decoded = nodeEntryUtils.decode(entry?.value);
388
- t.ok(decoded, 'indexer entry decodes after failed removeIndexer');
389
- if (!decoded) return;
390
-
391
- t.is(decoded.isIndexer, true, 'indexer role preserved after failed removeIndexer');
392
- t.is(decoded.isWriter, true, 'writer role preserved after failed removeIndexer');
393
- t.is(decoded.isWhitelisted, true, 'whitelist flag preserved after failed removeIndexer');
394
- assertIndexerMembershipPresent(t, base, decoded.wk);
395
-
396
- if (typeof writersLengthBefore === 'number') {
397
- const writersLengthAfter = await readWritersLength(base);
398
- t.is(
399
- writersLengthAfter,
400
- writersLengthBefore,
401
- 'writers length unchanged after failed removeIndexer'
402
- );
403
- }
404
- }
405
-
406
- function assertIndexerMembershipPresent(t, base, writingKey) {
407
- const hasMembership = indexerMembershipIncludes(base, writingKey);
408
- t.ok(hasMembership, 'indexer writer key remains in validator set');
409
- }
410
-
411
- async function assertMinimalIndexerState(t, base, indexerPeer) {
412
- const entry = await base.view.get(indexerPeer.wallet.address);
413
- t.ok(entry, 'indexer entry persists after failed removeIndexer');
414
- const decoded = nodeEntryUtils.decode(entry?.value);
415
- t.ok(decoded, 'indexer entry decodes after failed removeIndexer');
416
- if (!decoded) return;
417
- }
418
-
419
- async function readWritersLength(base) {
420
- const entry = await base.view.get(EntryType.WRITERS_LENGTH);
421
- if (!entry?.value) return 0;
422
- return entry.value.readUInt32BE();
423
- }
424
-
425
- function indexerMembershipIncludes(base, writingKey) {
426
- const entries = base?.system?.indexers;
427
- if (!entries) return false;
428
- return Object.values(entries).some(entry => entry?.key && b4a.equals(entry.key, writingKey));
429
- }
@@ -1,22 +0,0 @@
1
- import { test } from 'brittle';
2
- import nodeRoleUtils from '../../../../../src/core/state/utils/roles.js';
3
- import OperationValidationScenarioBase from '../common/base/OperationValidationScenarioBase.js';
4
- import { applyWithPretenderRoleMutation } from '../addIndexer/addIndexerScenarioHelpers.js';
5
- import {
6
- setupRemoveIndexerScenario,
7
- buildRemoveIndexerPayload,
8
- assertRemoveIndexerFailureState
9
- } from './removeIndexerScenarioHelpers.js';
10
-
11
- export default function removeIndexerTargetNotIndexerScenario() {
12
- new OperationValidationScenarioBase({
13
- title: 'State.apply removeIndexer rejects payloads when target is not an indexer',
14
- setupScenario: setupRemoveIndexerScenario,
15
- buildValidPayload: context => buildRemoveIndexerPayload(context),
16
- mutatePayload: (_t, payload) => payload,
17
- applyInvalidPayload: (context, invalidPayload) =>
18
- applyWithPretenderRoleMutation(context, invalidPayload, nodeRoleUtils.NodeRole.WRITER),
19
- assertStateUnchanged: (t, context) => assertRemoveIndexerFailureState(t, context, { skipSync: true }),
20
- expectedLogs: ['Node must be an indexer.']
21
- }).performScenario(test);
22
- }
@@ -1,20 +0,0 @@
1
- import OperationValidationScenarioBase from '../common/base/OperationValidationScenarioBase.js';
2
- import {
3
- setupRemoveIndexerScenario,
4
- buildRemoveIndexerPayload,
5
- assertRemoveIndexerGuardFailureState,
6
- applyWithoutIndexerMembership
7
- } from './removeIndexerScenarioHelpers.js';
8
-
9
- export default function removeIndexerWriterKeyMissingScenario() {
10
- new OperationValidationScenarioBase({
11
- title: 'State.apply removeIndexer rejects payloads when writer key is missing from indexer list',
12
- setupScenario: setupRemoveIndexerScenario,
13
- buildValidPayload: context => buildRemoveIndexerPayload(context),
14
- mutatePayload: (_t, payload) => payload,
15
- applyInvalidPayload: (context, invalidPayload) =>
16
- applyWithoutIndexerMembership(context, invalidPayload),
17
- assertStateUnchanged: (t, context) => assertRemoveIndexerGuardFailureState(t, context, { skipSync: true }),
18
- expectedLogs: ['Writer key does not exist in indexer list.']
19
- }).performScenario();
20
- }