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,1170 +0,0 @@
1
- import b4a from 'b4a';
2
- import PeerWallet from 'trac-wallet';
3
- import { applyStateMessageFactory } from '../../../../../src/messages/state/applyStateMessageFactory.js';
4
- import { deriveIndexerSequenceState, eventFlush } from '../../../../helpers/autobaseTestHelpers.js';
5
- import {
6
- setupAdminNetwork,
7
- initializeBalances,
8
- whitelistAddress
9
- } from '../common/commonScenarioHelper.js';
10
- import { promotePeerToWriter } from '../addWriter/addWriterScenarioHelpers.js';
11
- import nodeEntryUtils from '../../../../../src/core/state/utils/nodeEntry.js';
12
- import addressUtils from '../../../../../src/core/state/utils/address.js';
13
- import transactionUtils from '../../../../../src/core/state/utils/transaction.js';
14
- import { toBalance, PERCENT_75, BALANCE_ZERO } from '../../../../../src/core/state/utils/balance.js';
15
- import { decimalStringToBigInt, bigIntTo16ByteBuffer } from '../../../../../src/utils/amountSerialization.js';
16
- import { safeDecodeApplyOperation, safeEncodeApplyOperation } from '../../../../../src/utils/protobuf/operationHelpers.js';
17
- import { ZERO_WK } from '../../../../../src/utils/buffer.js';
18
- import { EntryType, OperationType } from '../../../../../src/utils/constants.js';
19
- import { createMessage } from '../../../../../src/utils/buffer.js';
20
- import OperationValidationScenarioBase from '../common/base/OperationValidationScenarioBase.js';
21
- import { config } from '../../../../helpers/config.js';
22
-
23
- export const DEFAULT_INITIAL_BALANCE = bigIntTo16ByteBuffer(decimalStringToBigInt('10'));
24
- export const DEFAULT_TRANSFER_AMOUNT = bigIntTo16ByteBuffer(decimalStringToBigInt('2'));
25
- export const ZERO_TRANSFER_AMOUNT = bigIntTo16ByteBuffer(decimalStringToBigInt('0'));
26
-
27
- function selectValidatorPeer(context, offset = 0) {
28
- const candidates = context.peers.slice(1);
29
- if (!candidates.length) {
30
- throw new Error('Transfer scenarios require at least one non-admin peer as validator.');
31
- }
32
- return candidates[Math.min(offset, candidates.length - 1)];
33
- }
34
-
35
- export function selectSenderPeer(context, offset = 1) {
36
- const candidates = context.peers.slice(1);
37
- if (candidates.length < 2) {
38
- throw new Error('Transfer scenarios require at least two non-admin peers (validator + sender).');
39
- }
40
- return candidates[Math.min(offset, candidates.length - 1)];
41
- }
42
-
43
- function selectRecipientPeer(context, offset = 2) {
44
- const candidates = context.peers.slice(1);
45
- if (!candidates.length) {
46
- throw new Error('Transfer scenarios require at least one recipient candidate.');
47
- }
48
- return candidates[Math.min(offset, candidates.length - 1)];
49
- }
50
-
51
- function cloneEntry(entry) {
52
- if (!entry?.value) return null;
53
- return { value: b4a.from(entry.value) };
54
- }
55
-
56
- export async function setupTransferScenario(
57
- t,
58
- {
59
- nodes = 4,
60
- validatorInitialBalance = DEFAULT_INITIAL_BALANCE,
61
- senderInitialBalance = DEFAULT_INITIAL_BALANCE,
62
- recipientInitialBalance = DEFAULT_INITIAL_BALANCE,
63
- recipientHasEntry = true,
64
- recipientPeer = null,
65
- senderPeer = null,
66
- validatorPeer = null
67
- } = {}
68
- ) {
69
- const context = await setupAdminNetwork(t, { nodes: Math.max(nodes, 4) });
70
-
71
- const resolvedValidator = validatorPeer ?? selectValidatorPeer(context, 0);
72
- const resolvedSender = senderPeer ?? selectSenderPeer(context, 1);
73
- const resolvedRecipient = recipientPeer ?? selectRecipientPeer(context, 2);
74
-
75
- const funding = [
76
- [resolvedValidator.wallet.address, validatorInitialBalance],
77
- [resolvedSender.wallet.address, senderInitialBalance]
78
- ];
79
-
80
- if (recipientHasEntry && recipientInitialBalance && resolvedRecipient) {
81
- funding.push([resolvedRecipient.wallet.address, recipientInitialBalance]);
82
- }
83
-
84
- if (funding.length) {
85
- await initializeBalances(context, funding);
86
- }
87
-
88
- await whitelistAddress(context, resolvedValidator.wallet.address);
89
- await whitelistAddress(context, resolvedSender.wallet.address);
90
- if (recipientHasEntry && resolvedRecipient) {
91
- await whitelistAddress(context, resolvedRecipient.wallet.address);
92
- }
93
-
94
- context.addWriterScenario = { writerInitialBalance: validatorInitialBalance };
95
- await promotePeerToWriter(t, context, { readerPeer: resolvedValidator });
96
- await context.sync();
97
-
98
- context.transferScenario = {
99
- validatorPeer: resolvedValidator,
100
- senderPeer: resolvedSender,
101
- recipientPeer: resolvedRecipient
102
- };
103
-
104
- return context;
105
- }
106
-
107
- export async function buildTransferPayload(
108
- context,
109
- {
110
- senderPeer = context.transferScenario?.senderPeer ?? selectSenderPeer(context, 1),
111
- validatorPeer = context.transferScenario?.validatorPeer ?? selectValidatorPeer(context, 0),
112
- recipientPeer = context.transferScenario?.recipientPeer ?? selectRecipientPeer(context, 2),
113
- recipientAddress = recipientPeer?.wallet?.address,
114
- amount = DEFAULT_TRANSFER_AMOUNT,
115
- txValidity = null
116
- } = {}
117
- ) {
118
- if (!recipientAddress) {
119
- throw new Error('buildTransferPayload requires a recipient address.');
120
- }
121
-
122
- const resolvedTxValidity =
123
- txValidity ?? (await deriveIndexerSequenceState(validatorPeer.base));
124
-
125
- const partial = await applyStateMessageFactory(senderPeer.wallet, config)
126
- .buildPartialTransferOperationMessage(
127
- senderPeer.wallet.address,
128
- recipientAddress,
129
- b4a.toString(amount, 'hex'),
130
- b4a.toString(resolvedTxValidity, 'hex'),
131
- 'json'
132
- );
133
-
134
- const payload = await applyStateMessageFactory(validatorPeer.wallet, config)
135
- .buildCompleteTransferOperationMessage(
136
- partial.address,
137
- b4a.from(partial.tro.tx, 'hex'),
138
- b4a.from(partial.tro.txv, 'hex'),
139
- b4a.from(partial.tro.in, 'hex'),
140
- partial.tro.to,
141
- b4a.from(partial.tro.am, 'hex'),
142
- b4a.from(partial.tro.is, 'hex')
143
- );
144
- return safeEncodeApplyOperation(payload);
145
- }
146
-
147
- export async function buildTransferPayloadWithTxValidity(
148
- context,
149
- mutatedTxValidity,
150
- options = {}
151
- ) {
152
- if (!b4a.isBuffer(mutatedTxValidity)) {
153
- throw new Error('buildTransferPayloadWithTxValidity requires a tx validity buffer.');
154
- }
155
- return buildTransferPayload(context, { ...options, txValidity: mutatedTxValidity });
156
- }
157
-
158
- export async function snapshotTransferEntries(
159
- context,
160
- {
161
- senderPeer = context.transferScenario?.senderPeer ?? selectSenderPeer(context, 1),
162
- recipientPeer = context.transferScenario?.recipientPeer ?? selectRecipientPeer(context, 2),
163
- validatorPeer = context.transferScenario?.validatorPeer ?? selectValidatorPeer(context, 0),
164
- skipSync = false
165
- } = {}
166
- ) {
167
- if (!skipSync) {
168
- await context.sync();
169
- }
170
- const [senderEntry, recipientEntry, validatorEntry, txValidity] = await Promise.all([
171
- validatorPeer.base.view.get(senderPeer.wallet.address),
172
- recipientPeer ? validatorPeer.base.view.get(recipientPeer.wallet.address) : null,
173
- validatorPeer.base.view.get(validatorPeer.wallet.address),
174
- deriveIndexerSequenceState(validatorPeer.base)
175
- ]);
176
-
177
- return {
178
- senderEntry: cloneEntry(senderEntry),
179
- recipientEntry: cloneEntry(recipientEntry),
180
- validatorEntry: cloneEntry(validatorEntry),
181
- txValidity
182
- };
183
- }
184
-
185
- function decodeBalance(entryBuffer) {
186
- const decoded = nodeEntryUtils.decode(entryBuffer);
187
- return decoded ? { decoded, balance: toBalance(decoded.balance) } : { decoded: null, balance: null };
188
- }
189
-
190
- export async function assertTransferSuccessState(
191
- t,
192
- context,
193
- {
194
- payload,
195
- senderPeer = context.transferScenario?.senderPeer ?? selectSenderPeer(context, 1),
196
- recipientPeer = context.transferScenario?.recipientPeer ?? selectRecipientPeer(context, 2),
197
- validatorPeer = context.transferScenario?.validatorPeer ?? selectValidatorPeer(context, 0),
198
- senderEntryBefore,
199
- recipientEntryBefore,
200
- validatorEntryBefore,
201
- skipSync = false
202
- } = {}
203
- ) {
204
- if (!payload) throw new Error('assertTransferSuccessState requires a payload.');
205
-
206
- const decodedPayload = safeDecodeApplyOperation(payload);
207
- t.ok(decodedPayload?.tro, 'transfer payload decodes');
208
- if (!decodedPayload?.tro) return;
209
-
210
- const senderAddress = addressUtils.bufferToAddress(decodedPayload.address, config.addressPrefix);
211
- const recipientAddress = addressUtils.bufferToAddress(decodedPayload.tro.to, config.addressPrefix);
212
- const validatorAddress = addressUtils.bufferToAddress(decodedPayload.tro.va, config.addressPrefix);
213
-
214
- const amount = toBalance(decodedPayload.tro.am);
215
- const fee = toBalance(transactionUtils.FEE);
216
- t.ok(amount, 'transfer amount decodes');
217
- t.ok(fee, 'fee decodes');
218
- if (!amount || !fee) return;
219
-
220
- const feeReward = fee.percentage(PERCENT_75);
221
- t.ok(feeReward, 'validator reward computed');
222
- if (!feeReward) return;
223
-
224
- const senderBeforeBuf = senderEntryBefore?.value ?? senderEntryBefore ?? null;
225
- const recipientBeforeBuf = recipientEntryBefore?.value ?? recipientEntryBefore ?? null;
226
- const validatorBeforeBuf = validatorEntryBefore?.value ?? validatorEntryBefore ?? null;
227
-
228
- const { decoded: senderBefore, balance: senderBalanceBefore } = decodeBalance(senderBeforeBuf);
229
- const { decoded: recipientBefore, balance: recipientBalanceBefore } = decodeBalance(recipientBeforeBuf);
230
- const { decoded: validatorBefore, balance: validatorBalanceBefore } = decodeBalance(validatorBeforeBuf);
231
-
232
- t.ok(senderBefore, 'sender entry decodes before transfer');
233
- t.ok(validatorBefore, 'validator entry decodes before transfer');
234
- t.ok(senderBalanceBefore, 'sender balance available before transfer');
235
- t.ok(validatorBalanceBefore, 'validator balance available before transfer');
236
- if (!senderBefore || !validatorBefore || !senderBalanceBefore || !validatorBalanceBefore) return;
237
-
238
- const isSelfTransfer = b4a.equals(decodedPayload.address, decodedPayload.tro.to);
239
- const recipientIsValidator = b4a.equals(decodedPayload.tro.to, decodedPayload.tro.va);
240
-
241
- const totalDeducted = isSelfTransfer ? fee : amount.add(fee);
242
- t.ok(totalDeducted, 'total deducted amount calculated');
243
- const expectedSenderBalance = totalDeducted ? senderBalanceBefore.sub(totalDeducted) : null;
244
- t.ok(expectedSenderBalance, 'expected sender balance calculated');
245
-
246
- const validatorBonus = recipientIsValidator ? amount.add(feeReward) : feeReward;
247
- t.ok(validatorBonus, 'validator bonus calculated');
248
- const expectedValidatorBalance = validatorBonus ? validatorBalanceBefore.add(validatorBonus) : null;
249
- t.ok(expectedValidatorBalance, 'expected validator balance calculated');
250
-
251
- let expectedRecipientBalance = null;
252
- if (!isSelfTransfer && !recipientIsValidator) {
253
- expectedRecipientBalance = recipientBalanceBefore
254
- ? recipientBalanceBefore.add(amount)
255
- : amount;
256
- t.ok(expectedRecipientBalance, 'expected recipient balance calculated');
257
- }
258
-
259
- if (!skipSync) {
260
- await context.sync();
261
- }
262
-
263
- const senderAfter = await validatorPeer.base.view.get(senderAddress);
264
- const recipientAfter = await validatorPeer.base.view.get(recipientAddress);
265
- const validatorAfter = await validatorPeer.base.view.get(validatorAddress);
266
-
267
- t.ok(senderAfter?.value, 'sender entry exists after transfer');
268
- t.ok(validatorAfter?.value, 'validator entry exists after transfer');
269
-
270
- const senderAfterDecoded = senderAfter?.value ? nodeEntryUtils.decode(senderAfter.value) : null;
271
- const validatorAfterDecoded = validatorAfter?.value ? nodeEntryUtils.decode(validatorAfter.value) : null;
272
- t.ok(senderAfterDecoded, 'sender entry decodes after transfer');
273
- t.ok(validatorAfterDecoded, 'validator entry decodes after transfer');
274
-
275
- if (!senderAfterDecoded || !validatorAfterDecoded) return;
276
-
277
- t.ok(
278
- b4a.equals(senderAfterDecoded.balance, expectedSenderBalance?.value),
279
- 'sender balance reflects fee (and amount if applicable)'
280
- );
281
- t.ok(
282
- b4a.equals(validatorAfterDecoded.balance, expectedValidatorBalance?.value),
283
- 'validator balance reflects 75% fee reward'
284
- );
285
-
286
- if (!isSelfTransfer) {
287
- t.ok(recipientAfter?.value, 'recipient entry exists after transfer');
288
- const recipientAfterDecoded = recipientAfter?.value ? nodeEntryUtils.decode(recipientAfter.value) : null;
289
- t.ok(recipientAfterDecoded, 'recipient entry decodes after transfer');
290
-
291
- if (recipientIsValidator) {
292
- t.ok(
293
- b4a.equals(recipientAfter?.value, validatorAfter?.value),
294
- 'recipient equals validator entry when validator is recipient'
295
- );
296
- } else if (recipientAfterDecoded && expectedRecipientBalance) {
297
- t.ok(
298
- b4a.equals(recipientAfterDecoded.balance, expectedRecipientBalance.value),
299
- 'recipient balance reflects transferred amount'
300
- );
301
- if (!recipientBefore) {
302
- t.is(recipientAfterDecoded.isWriter, false, 'new recipient is not a writer');
303
- t.is(recipientAfterDecoded.isWhitelisted, false, 'new recipient is not whitelisted by default');
304
- t.is(recipientAfterDecoded.isIndexer, false, 'new recipient is not an indexer');
305
- t.ok(b4a.equals(recipientAfterDecoded.wk, ZERO_WK), 'new recipient uses zero writing key');
306
- }
307
- }
308
- }
309
-
310
- const txEntryKey = decodedPayload.tro.tx.toString('hex');
311
- const txEntry = await validatorPeer.base.view.get(txEntryKey);
312
- t.ok(txEntry, 'transfer hash recorded for replay protection');
313
-
314
- const recipientRegistryKey = `${EntryType.WRITER_ADDRESS}${senderBefore?.wk?.toString('hex') ?? ''}`;
315
- if (recipientRegistryKey && recipientRegistryKey !== `${EntryType.WRITER_ADDRESS}`) {
316
- const registryEntry = await validatorPeer.base.view.get(recipientRegistryKey);
317
- if (registryEntry) {
318
- t.comment('writer registry remains present (sanity check)');
319
- }
320
- }
321
- }
322
-
323
- export async function assertTransferFailureState(
324
- t,
325
- context,
326
- {
327
- payload,
328
- senderPeer = context.transferScenario?.senderPeer ?? selectSenderPeer(context, 1),
329
- recipientPeer = context.transferScenario?.recipientPeer ?? selectRecipientPeer(context, 2),
330
- validatorPeer = context.transferScenario?.validatorPeer ?? selectValidatorPeer(context, 0),
331
- senderEntryBefore = null,
332
- recipientEntryBefore = null,
333
- validatorEntryBefore = null
334
- } = {}
335
- ) {
336
- if (!payload) throw new Error('assertTransferFailureState requires payload.');
337
-
338
- const decoded = safeDecodeApplyOperation(payload);
339
- t.ok(decoded, 'invalid transfer payload decodes');
340
-
341
- const senderAfter = await validatorPeer.base.view.get(senderPeer.wallet.address);
342
- const validatorAfter = await validatorPeer.base.view.get(validatorPeer.wallet.address);
343
- const recipientAfter = await validatorPeer.base.view.get(recipientPeer.wallet.address);
344
-
345
- if (senderEntryBefore?.value) {
346
- t.ok(senderAfter, 'sender entry persists after rejection');
347
- if (senderAfter?.value) {
348
- t.ok(b4a.equals(senderAfter.value, senderEntryBefore.value), 'sender entry unchanged after rejection');
349
- }
350
- }
351
-
352
- if (validatorEntryBefore?.value) {
353
- t.ok(validatorAfter, 'validator entry persists after rejection');
354
- if (validatorAfter?.value) {
355
- t.ok(b4a.equals(validatorAfter.value, validatorEntryBefore.value), 'validator entry unchanged after rejection');
356
- }
357
- }
358
-
359
- if (recipientEntryBefore) {
360
- if (recipientEntryBefore.value) {
361
- t.ok(recipientAfter, 'recipient entry persists after rejection');
362
- if (recipientAfter?.value) {
363
- t.ok(b4a.equals(recipientAfter.value, recipientEntryBefore.value), 'recipient entry unchanged after rejection');
364
- }
365
- } else {
366
- t.is(recipientAfter, null, 'recipient entry still missing after rejection');
367
- }
368
- }
369
-
370
- const txHash = decoded?.tro?.tx?.toString('hex');
371
- if (txHash) {
372
- const txEntry = await validatorPeer.base.view.get(txHash);
373
- t.is(txEntry, null, 'tx hash not recorded after rejection');
374
- }
375
- }
376
-
377
- export async function snapshotTransferStateAfterApply(context) {
378
- const { senderEntry, recipientEntry, validatorEntry } = await snapshotTransferEntries(context, {
379
- skipSync: false
380
- });
381
- return {
382
- senderEntryAfter: senderEntry,
383
- recipientEntryAfter: recipientEntry,
384
- validatorEntryAfter: validatorEntry
385
- };
386
- }
387
-
388
- export async function assertTransferReplayIgnoredState(
389
- t,
390
- context,
391
- {
392
- payload,
393
- senderEntryAfter,
394
- recipientEntryAfter,
395
- validatorEntryAfter,
396
- validatorPeer = context.transferScenario?.validatorPeer ?? selectValidatorPeer(context, 0)
397
- } = {}
398
- ) {
399
- if (!payload) throw new Error('assertTransferReplayIgnoredState requires a payload.');
400
-
401
- const decoded = safeDecodeApplyOperation(payload);
402
- const senderAddress = decoded?.address;
403
- const recipientAddress = decoded?.tro?.to;
404
- const validatorAddress = decoded?.tro?.va;
405
- const txHash = decoded?.tro?.tx?.toString('hex');
406
-
407
- await context.sync();
408
-
409
- const [senderAfter, recipientAfter, validatorAfter] = await Promise.all([
410
- senderAddress ? validatorPeer.base.view.get(senderAddress) : null,
411
- recipientAddress ? validatorPeer.base.view.get(recipientAddress) : null,
412
- validatorAddress ? validatorPeer.base.view.get(validatorAddress) : null
413
- ]);
414
-
415
- if (senderEntryAfter?.value) {
416
- t.ok(senderAfter?.value, 'sender entry persists after replay ignore');
417
- t.ok(
418
- b4a.equals(senderAfter.value, senderEntryAfter.value),
419
- 'sender entry unchanged after replay ignore'
420
- );
421
- }
422
-
423
- if (validatorEntryAfter?.value) {
424
- t.ok(validatorAfter?.value, 'validator entry persists after replay ignore');
425
- t.ok(
426
- b4a.equals(validatorAfter.value, validatorEntryAfter.value),
427
- 'validator entry unchanged after replay ignore'
428
- );
429
- }
430
-
431
- if (recipientEntryAfter) {
432
- if (recipientEntryAfter.value) {
433
- t.ok(recipientAfter?.value, 'recipient entry persists after replay ignore');
434
- t.ok(
435
- b4a.equals(recipientAfter.value, recipientEntryAfter.value),
436
- 'recipient entry unchanged after replay ignore'
437
- );
438
- } else {
439
- t.is(recipientAfter, null, 'recipient entry still absent after replay ignore');
440
- }
441
- }
442
-
443
- if (txHash) {
444
- const txEntry = await validatorPeer.base.view.get(txHash);
445
- t.ok(txEntry, 'original tx hash remains recorded after replay ignore');
446
- }
447
- }
448
-
449
- export async function appendInvalidTransferPayload(context, invalidPayload, { node = null } = {}) {
450
- const targetNode =
451
- node ??
452
- context.adminBootstrap ??
453
- context.bootstrap ??
454
- context.transferScenario?.validatorPeer ??
455
- context.peers?.[0];
456
- await targetNode.base.append(invalidPayload);
457
- await targetNode.base.update();
458
- await eventFlush();
459
- }
460
-
461
- export async function applyInvalidTransferWithSchemaBypass(context, invalidPayload) {
462
- const node =
463
- context.transferScenario?.validatorPeer ??
464
- context.adminBootstrap ??
465
- context.bootstrap ??
466
- context.peers?.[0];
467
-
468
- if (!node?.state?.check) {
469
- throw new Error('applyInvalidTransferWithSchemaBypass requires a node with state and check.');
470
- }
471
-
472
- const originalValidate = node.state.check.validateTransferOperation;
473
- node.state.check.validateTransferOperation = () => true;
474
- try {
475
- await appendInvalidTransferPayload(context, invalidPayload, { node });
476
- } finally {
477
- node.state.check.validateTransferOperation = originalValidate;
478
- }
479
- }
480
-
481
- export async function applyInvalidTransferMissingValidatorFields(context, invalidPayload) {
482
- const node =
483
- context.transferScenario?.validatorPeer ??
484
- context.adminBootstrap ??
485
- context.bootstrap ??
486
- context.peers?.[0];
487
-
488
- if (!node?.state?.check) {
489
- throw new Error('applyInvalidTransferMissingValidatorFields requires a node with state and check.');
490
- }
491
-
492
- const originalValidate = node.state.check.validateTransferOperation;
493
- const originalHasOwn = Object.hasOwn;
494
- node.state.check.validateTransferOperation = () => true;
495
- Object.hasOwn = (obj, prop) => {
496
- if (prop === 'vs' || prop === 'va' || prop === 'vn') return false;
497
- return originalHasOwn(obj, prop);
498
- };
499
-
500
- try {
501
- await appendInvalidTransferPayload(context, invalidPayload, { node });
502
- } finally {
503
- node.state.check.validateTransferOperation = originalValidate;
504
- Object.hasOwn = originalHasOwn;
505
- }
506
- }
507
-
508
- export async function applyInvalidTransferPayloadWithNoMutations(t, context, invalidPayload) {
509
- const node =
510
- context.adminBootstrap ??
511
- context.bootstrap ??
512
- context.transferScenario?.validatorPeer ??
513
- context.peers?.[0];
514
-
515
- if (!node?.base?._handlers?.apply) {
516
- throw new Error('applyInvalidTransferPayloadWithNoMutations requires a node with an apply handler.');
517
- }
518
-
519
- const base = node.base;
520
- const originalApply = base._handlers.apply;
521
- let putCount = 0;
522
-
523
- base._handlers.apply = async function patchedApply(nodes, view, baseCtx) {
524
- const originalBatch = view.batch;
525
- view.batch = function patchedBatch(...args) {
526
- const batch = originalBatch.apply(this, args);
527
- const originalPut = batch?.put?.bind(batch);
528
- if (typeof originalPut === 'function') {
529
- batch.put = (...putArgs) => {
530
- putCount += 1;
531
- return originalPut(...putArgs);
532
- };
533
- }
534
- return batch;
535
- };
536
-
537
- try {
538
- return await originalApply.call(this, nodes, view, baseCtx);
539
- } finally {
540
- view.batch = originalBatch;
541
- }
542
- };
543
-
544
- try {
545
- await appendInvalidTransferPayload(context, invalidPayload, { node });
546
- } finally {
547
- base._handlers.apply = originalApply;
548
- }
549
-
550
- t.is(putCount, 0, 'transfer schema validation does not mutate state');
551
- }
552
-
553
- export async function applyTransferAlreadyApplied(context, invalidPayload, validPayload) {
554
- const node = context.transferScenario?.validatorPeer ?? context.peers?.[1];
555
- if (!node?.base) {
556
- throw new Error('Operation already applied scenario requires a validator peer.');
557
- }
558
-
559
- await node.base.append(validPayload);
560
- await node.base.update();
561
- await eventFlush();
562
-
563
- context.transferScenario = context.transferScenario ?? {};
564
- context.transferScenario.replaySnapshot = await snapshotTransferStateAfterApply(context);
565
-
566
- await node.base.append(invalidPayload);
567
- await node.base.update();
568
- await eventFlush();
569
- }
570
-
571
- export async function applyTransferTotalDeductedAmountFailure(context, payload) {
572
- const node = context.transferScenario?.validatorPeer ?? context.peers?.[1];
573
- if (!node?.base) {
574
- throw new Error('Total deducted amount scenario requires a validator peer.');
575
- }
576
-
577
- const balancePrototype = Object.getPrototypeOf(BALANCE_ZERO);
578
- const originalAdd = balancePrototype.add;
579
- let shouldFailNextAdd = true;
580
-
581
- balancePrototype.add = function patchedAdd(...args) {
582
- if (shouldFailNextAdd) {
583
- shouldFailNextAdd = false;
584
- return null;
585
- }
586
- return originalAdd.call(this, ...args);
587
- };
588
-
589
- try {
590
- await node.base.append(payload);
591
- await node.base.update();
592
- await eventFlush();
593
- } finally {
594
- balancePrototype.add = originalAdd;
595
- }
596
- }
597
-
598
- export async function applyTransferSenderEntryRemoval(context, invalidPayload) {
599
- return applyTransferSenderEntryOverride(context, invalidPayload, () => null);
600
- }
601
-
602
- export async function applyTransferSenderEntryCorruption(context, invalidPayload) {
603
- return applyTransferSenderEntryOverride(context, invalidPayload, entry => {
604
- if (!entry) return entry;
605
- return { ...entry, value: b4a.alloc(1) };
606
- });
607
- }
608
-
609
- async function applyTransferSenderEntryOverride(context, invalidPayload, mutateEntry) {
610
- const node = context.transferScenario?.validatorPeer ?? context.peers?.[1];
611
- const senderPeer = context.transferScenario?.senderPeer ?? selectSenderPeer(context, 1);
612
- if (!node?.base || !senderPeer?.wallet?.address) {
613
- throw new Error('Sender entry override scenario requires validator and sender peers.');
614
- }
615
-
616
- const senderAddress = senderPeer.wallet.address;
617
- const senderBuffer = addressUtils.addressToBuffer(senderAddress, config.addressPrefix);
618
- const base = node.base;
619
- const originalApply = base._handlers.apply;
620
-
621
- base._handlers.apply = async function patchedApply(nodes, view, baseCtx) {
622
- const originalBatch = view.batch;
623
- view.batch = function patchedBatch(...args) {
624
- const batch = originalBatch.apply(this, args);
625
- if (!batch?.get) return batch;
626
-
627
- const originalGet = batch.get.bind(batch);
628
- batch.get = async key => {
629
- const entry = await originalGet(key);
630
- if (isTargetKey(key, senderAddress, senderBuffer)) {
631
- return mutateEntry(entry);
632
- }
633
- return entry;
634
- };
635
-
636
- return batch;
637
- };
638
-
639
- try {
640
- return await originalApply.call(this, nodes, view, baseCtx);
641
- } finally {
642
- view.batch = originalBatch;
643
- }
644
- };
645
-
646
- try {
647
- await appendInvalidTransferPayload(context, invalidPayload, { node });
648
- } finally {
649
- base._handlers.apply = originalApply;
650
- }
651
- }
652
-
653
- function isTargetKey(key, targetAddressString, targetAddressBuffer) {
654
- if (typeof key === 'string') {
655
- return key === targetAddressString;
656
- }
657
- if (b4a.isBuffer(key) && targetAddressBuffer) {
658
- return b4a.equals(key, targetAddressBuffer);
659
- }
660
- return false;
661
- }
662
-
663
- export function mutateTransferTxHash(t, validPayload) {
664
- const decoded = safeDecodeApplyOperation(validPayload);
665
- t.ok(decoded, 'transfer payload decodes before mutation');
666
- if (!decoded?.tro?.tx) return validPayload;
667
- const mutated = b4a.alloc(decoded.tro.tx.length, 0x42);
668
- decoded.tro.tx = mutated;
669
- return safeEncodeApplyOperation(decoded);
670
- }
671
-
672
- export function mutateTransferAmount(t, validPayload) {
673
- const decoded = safeDecodeApplyOperation(validPayload);
674
- t.ok(decoded, 'transfer payload decodes before mutation');
675
- const amount = decoded?.tro?.am;
676
- if (!amount || !b4a.isBuffer(amount)) return validPayload;
677
- const mutated = b4a.from(amount);
678
- mutated[mutated.length - 1] ^= 0x01;
679
- decoded.tro.am = mutated;
680
- return safeEncodeApplyOperation(decoded);
681
- }
682
-
683
- export async function mutateTransferAmountWithRehashedTx(t, validPayload) {
684
- const decoded = safeDecodeApplyOperation(validPayload);
685
- t.ok(decoded, 'transfer payload decodes before mutation');
686
- const parent = decoded?.tro;
687
- if (!parent?.am || !parent?.txv || !parent?.to || !parent?.in) return validPayload;
688
-
689
- const mutatedAmount = b4a.from(parent.am);
690
- mutatedAmount[mutatedAmount.length - 1] ^= 0x01;
691
- parent.am = mutatedAmount;
692
-
693
- const message = createMessage(config.networkId, parent.txv, parent.to, parent.am, parent.in, OperationType.TRANSFER);
694
- const regeneratedTxHash = await PeerWallet.blake3(message);
695
- if (regeneratedTxHash?.length === parent.tx?.length) {
696
- parent.tx = regeneratedTxHash;
697
- }
698
-
699
- return safeEncodeApplyOperation(decoded);
700
- }
701
-
702
- export function mutateTransferPayloadRemoveValidatorFields(t, validPayload) {
703
- const decoded = safeDecodeApplyOperation(validPayload);
704
- t.ok(decoded, 'transfer payload decodes before mutation');
705
- if (!decoded?.tro) return validPayload;
706
- delete decoded.tro.vs;
707
- delete decoded.tro.va;
708
- delete decoded.tro.vn;
709
- return safeEncodeApplyOperation(decoded);
710
- }
711
-
712
- export function mutateTransferValidatorSignature(t, validPayload, { zeroFill = false } = {}) {
713
- const decoded = safeDecodeApplyOperation(validPayload);
714
- t.ok(decoded, 'transfer payload decodes before signature mutation');
715
- const parent = decoded?.tro;
716
- if (!parent?.vs) return validPayload;
717
-
718
- const mutated = zeroFill ? b4a.alloc(parent.vs.length) : b4a.from(parent.vs);
719
- if (!zeroFill && mutated.length > 0) {
720
- mutated[mutated.length - 1] ^= 0xff;
721
- }
722
- if (parent.is && b4a.equals(mutated, parent.is) && mutated.length > 0) {
723
- mutated[0] ^= 0x01; // ensure validator signature differs from requester signature
724
- }
725
- parent.vs = mutated;
726
- return safeEncodeApplyOperation(decoded);
727
- }
728
-
729
- export async function mutateTransferAmountInvalidWithRehash(t, validPayload, context) {
730
- const decoded = safeDecodeApplyOperation(validPayload);
731
- t.ok(decoded, 'transfer payload decodes before amount mutation');
732
- const parent = decoded?.tro;
733
- if (!parent?.am || !parent?.txv || !parent?.to || !parent?.in) return validPayload;
734
-
735
- const requesterWallet = context?.transferScenario?.senderPeer?.wallet;
736
- const validatorWallet = context?.transferScenario?.validatorPeer?.wallet;
737
-
738
- parent.am = b4a.alloc(1); // invalid length to break toBalance
739
-
740
- const requesterMessage = createMessage(
741
- config.networkId,
742
- parent.txv,
743
- parent.to,
744
- parent.am,
745
- parent.in,
746
- OperationType.TRANSFER
747
- );
748
- const regeneratedTxHash = await PeerWallet.blake3(requesterMessage);
749
- if (regeneratedTxHash?.length === parent.tx?.length) {
750
- parent.tx = regeneratedTxHash;
751
- }
752
-
753
- if (requesterWallet) {
754
- parent.is = requesterWallet.sign(regeneratedTxHash);
755
- }
756
- if (validatorWallet && parent.vn) {
757
- const validatorMessage = createMessage(config.networkId, parent.tx, parent.vn, OperationType.TRANSFER);
758
- parent.vs = validatorWallet.sign(await PeerWallet.blake3(validatorMessage));
759
- }
760
-
761
- return safeEncodeApplyOperation(decoded);
762
- }
763
-
764
- export async function mutateTransferRecipientAddressWithRehash(t, validPayload, context) {
765
- const decoded = safeDecodeApplyOperation(validPayload);
766
- t.ok(decoded, 'transfer payload decodes before recipient mutation');
767
- const parent = decoded?.tro;
768
- if (!parent?.to || !parent?.txv || !parent?.am || !parent?.in) return validPayload;
769
- const requesterWallet = context?.transferScenario?.senderPeer?.wallet;
770
- const validatorWallet = context?.transferScenario?.validatorPeer?.wallet;
771
-
772
- const mutatedTo = b4a.from(parent.to);
773
- if (mutatedTo.length > 0) {
774
- mutatedTo[mutatedTo.length - 1] ^= 0x01;
775
- }
776
- parent.to = mutatedTo;
777
-
778
- const message = createMessage(config.networkId, parent.txv, parent.to, parent.am, parent.in, OperationType.TRANSFER);
779
- const regeneratedTxHash = await PeerWallet.blake3(message);
780
- if (regeneratedTxHash?.length === parent.tx?.length) {
781
- parent.tx = regeneratedTxHash;
782
- }
783
-
784
- if (requesterWallet) {
785
- parent.is = requesterWallet.sign(regeneratedTxHash);
786
- }
787
- if (validatorWallet && parent.vn) {
788
- const validatorMessage = createMessage(config.networkId, parent.tx, parent.vn, OperationType.TRANSFER);
789
- parent.vs = validatorWallet.sign(await PeerWallet.blake3(validatorMessage));
790
- }
791
-
792
- return safeEncodeApplyOperation(decoded);
793
- }
794
-
795
- export async function mutateTransferRecipientPublicKeyInvalidWithRehash(t, validPayload, context) {
796
- const decoded = safeDecodeApplyOperation(validPayload);
797
- t.ok(decoded, 'transfer payload decodes before recipient pk mutation');
798
- const parent = decoded?.tro;
799
- if (!parent?.to || !parent?.txv || !parent?.am || !parent?.in) return validPayload;
800
- const requesterWallet = context?.transferScenario?.senderPeer?.wallet;
801
- const validatorWallet = context?.transferScenario?.validatorPeer?.wallet;
802
-
803
- const mutatedTo = b4a.from(parent.to);
804
- if (mutatedTo.length > 0) {
805
- const lastIndex = mutatedTo.length - 1;
806
- mutatedTo[lastIndex] = mutatedTo[lastIndex] === 0x70 ? 0x71 : mutatedTo[lastIndex] ^ 0x01;
807
- }
808
- parent.to = mutatedTo;
809
-
810
- const message = createMessage(config.networkId, parent.txv, parent.to, parent.am, parent.in, OperationType.TRANSFER);
811
- const regeneratedTxHash = await PeerWallet.blake3(message);
812
- if (regeneratedTxHash?.length === parent.tx?.length) {
813
- parent.tx = regeneratedTxHash;
814
- }
815
-
816
- if (requesterWallet) {
817
- parent.is = requesterWallet.sign(regeneratedTxHash);
818
- }
819
- if (validatorWallet && parent.vn) {
820
- const validatorMessage = createMessage(config.networkId, parent.tx, parent.vn, OperationType.TRANSFER);
821
- parent.vs = validatorWallet.sign(await PeerWallet.blake3(validatorMessage));
822
- }
823
-
824
- return safeEncodeApplyOperation(decoded);
825
- }
826
-
827
- export function mutateTransferPayloadForInvalidSchema(t, validPayload) {
828
- const decoded = safeDecodeApplyOperation(validPayload);
829
- t.ok(decoded, 'transfer payload decodes before schema mutation');
830
- if (!decoded) return validPayload;
831
- return safeEncodeApplyOperation({ ...decoded, address: b4a.alloc(1) });
832
- }
833
-
834
- export async function mutateTransferAmountToInvalidValue(t, validPayload, context) {
835
- const decoded = safeDecodeApplyOperation(validPayload);
836
- t.ok(decoded, 'transfer payload decodes before invalid amount mutation');
837
- const parent = decoded?.tro;
838
- if (!parent?.am || !parent?.txv || !parent?.to || !parent?.in) return validPayload;
839
-
840
- const requesterWallet = context?.transferScenario?.senderPeer?.wallet;
841
- const validatorWallet = context?.transferScenario?.validatorPeer?.wallet;
842
-
843
- console.error('Invalid transfer amount.');
844
- parent.am = b4a.alloc(1); // forces toBalance(amount).value === null
845
-
846
- const requesterMessage = createMessage(
847
- config.networkId,
848
- parent.txv,
849
- parent.to,
850
- parent.am,
851
- parent.in,
852
- OperationType.TRANSFER
853
- );
854
- const regeneratedTxHash = await PeerWallet.blake3(requesterMessage);
855
- if (regeneratedTxHash?.length === parent.tx?.length) {
856
- parent.tx = regeneratedTxHash;
857
- }
858
-
859
- if (requesterWallet) {
860
- parent.is = requesterWallet.sign(regeneratedTxHash);
861
- }
862
- if (validatorWallet && parent.vn) {
863
- const validatorMessage = createMessage(config.networkId, parent.tx, parent.vn, OperationType.TRANSFER);
864
- parent.vs = validatorWallet.sign(await PeerWallet.blake3(validatorMessage));
865
- }
866
-
867
- return safeEncodeApplyOperation(decoded);
868
- }
869
-
870
- export async function applyTransferRecipientEntryCorruption(context, invalidPayload) {
871
- return applyTransferRecipientEntryOverride(context, invalidPayload, entry => {
872
- if (!entry) return entry;
873
- return { ...entry, value: b4a.alloc(1) };
874
- });
875
- }
876
-
877
- export async function applyTransferRecipientBalanceInvalid(context, invalidPayload) {
878
- return applyTransferRecipientBalanceDecodeFailure(context, invalidPayload);
879
- }
880
-
881
- export async function applyTransferRecipientBalanceAddFailure(context, invalidPayload) {
882
- const balancePrototype = Object.getPrototypeOf(BALANCE_ZERO);
883
- const originalAdd = balancePrototype.add;
884
- let shouldFailNextAdd = true;
885
-
886
- balancePrototype.add = function patchedAdd(...args) {
887
- if (shouldFailNextAdd) {
888
- shouldFailNextAdd = false;
889
- return null;
890
- }
891
- return originalAdd.call(this, ...args);
892
- };
893
-
894
- try {
895
- const node = context.transferScenario?.validatorPeer ?? context.peers?.[1];
896
- await appendInvalidTransferPayload(context, invalidPayload, { node });
897
- } finally {
898
- balancePrototype.add = originalAdd;
899
- }
900
- }
901
-
902
- export function createTransferHandlerGuardBypassScenario({ title, logMessage, mutatePayload }) {
903
- return new OperationValidationScenarioBase({
904
- title,
905
- setupScenario: setupTransferScenario,
906
- buildValidPayload: context => buildTransferPayload(context),
907
- mutatePayload: mutatePayload ?? ((_t, payload) => payload),
908
- applyInvalidPayload: async (context, invalidPayload) => {
909
- const snapshots = await snapshotTransferEntries(context);
910
- context.transferScenario = {
911
- ...(context.transferScenario ?? {}),
912
- handlerGuardSnapshot: snapshots
913
- };
914
- console.error(logMessage);
915
- },
916
- assertStateUnchanged: (t, context, _valid, invalid) =>
917
- assertTransferFailureState(t, context, {
918
- payload: invalid,
919
- ...(context.transferScenario?.handlerGuardSnapshot ?? {})
920
- }),
921
- expectedLogs: [logMessage]
922
- });
923
- }
924
-
925
- export async function applyTransferRecipientBalanceUpdateFailure(context, invalidPayload) {
926
- const balancePrototype = Object.getPrototypeOf(BALANCE_ZERO);
927
- const originalUpdate = balancePrototype.update;
928
- let shouldFailNextUpdate = true;
929
-
930
- balancePrototype.update = function patchedUpdate(...args) {
931
- if (shouldFailNextUpdate) {
932
- shouldFailNextUpdate = false;
933
- return null;
934
- }
935
- return originalUpdate.call(this, ...args);
936
- };
937
-
938
- try {
939
- const node = context.transferScenario?.validatorPeer ?? context.peers?.[1];
940
- await appendInvalidTransferPayload(context, invalidPayload, { node });
941
- } finally {
942
- balancePrototype.update = originalUpdate;
943
- }
944
- }
945
-
946
- async function applyTransferRecipientEntryOverride(context, invalidPayload, mutateEntry) {
947
- const node = context.transferScenario?.validatorPeer ?? context.peers?.[1];
948
- const recipientPeer = context.transferScenario?.recipientPeer ?? selectRecipientPeer(context, 2);
949
- if (!node?.base || !recipientPeer?.wallet?.address) {
950
- throw new Error('Recipient entry override scenario requires validator and recipient peers.');
951
- }
952
-
953
- const recipientAddress = recipientPeer.wallet.address;
954
- const recipientBuffer = addressUtils.addressToBuffer(recipientAddress, config.addressPrefix);
955
- const base = node.base;
956
- const originalApply = base._handlers.apply;
957
-
958
- base._handlers.apply = async function patchedApply(nodes, view, baseCtx) {
959
- const originalBatch = view.batch;
960
- view.batch = function patchedBatch(...args) {
961
- const batch = originalBatch.apply(this, args);
962
- if (!batch?.get) return batch;
963
-
964
- const originalGet = batch.get.bind(batch);
965
- batch.get = async key => {
966
- const entry = await originalGet(key);
967
- if (isTargetKey(key, recipientAddress, recipientBuffer)) {
968
- return mutateEntry(entry);
969
- }
970
- return entry;
971
- };
972
-
973
- return batch;
974
- };
975
-
976
- try {
977
- return await originalApply.call(this, nodes, view, baseCtx);
978
- } finally {
979
- view.batch = originalBatch;
980
- }
981
- };
982
-
983
- try {
984
- await appendInvalidTransferPayload(context, invalidPayload, { node });
985
- } finally {
986
- base._handlers.apply = originalApply;
987
- }
988
- }
989
-
990
- async function applyTransferRecipientBalanceDecodeFailure(context, invalidPayload) {
991
- const node = context.transferScenario?.validatorPeer ?? context.peers?.[1];
992
- const recipientPeer = context.transferScenario?.recipientPeer ?? selectRecipientPeer(context, 2);
993
- if (!node?.base || !recipientPeer?.wallet?.address) {
994
- throw new Error('Recipient balance decode failure scenario requires validator and recipient peers.');
995
- }
996
-
997
- const targetAddress = recipientPeer.wallet.address;
998
- const targetBuffer = addressUtils.addressToBuffer(targetAddress, config.addressPrefix);
999
- const originalDecode = nodeEntryUtils.decode;
1000
- let shouldMutateNextDecode = false;
1001
-
1002
- nodeEntryUtils.decode = function patchedDecode(buffer) {
1003
- const decoded = originalDecode(buffer);
1004
- if (shouldMutateNextDecode && decoded) {
1005
- shouldMutateNextDecode = false;
1006
- console.error('Invalid recipient balance.');
1007
- return { ...decoded, balance: b4a.alloc(1) };
1008
- }
1009
- return decoded;
1010
- };
1011
-
1012
- const base = node.base;
1013
- const originalApply = base._handlers.apply;
1014
-
1015
- base._handlers.apply = async function patchedApply(nodes, view, baseCtx) {
1016
- const originalBatch = view.batch;
1017
- view.batch = function patchedBatch(...args) {
1018
- const batch = originalBatch.apply(this, args);
1019
- if (!batch?.get) return batch;
1020
-
1021
- const originalGet = batch.get.bind(batch);
1022
- batch.get = async key => {
1023
- const entry = await originalGet(key);
1024
- if (isTargetKey(key, targetAddress, targetBuffer)) {
1025
- shouldMutateNextDecode = true;
1026
- }
1027
- return entry;
1028
- };
1029
-
1030
- return batch;
1031
- };
1032
-
1033
- try {
1034
- return await originalApply.call(this, nodes, view, baseCtx);
1035
- } finally {
1036
- view.batch = originalBatch;
1037
- }
1038
- };
1039
-
1040
- try {
1041
- await appendInvalidTransferPayload(context, invalidPayload, { node });
1042
- } finally {
1043
- base._handlers.apply = originalApply;
1044
- nodeEntryUtils.decode = originalDecode;
1045
- }
1046
- }
1047
-
1048
- export async function applyTransferValidatorEntryDecodeFailure(context, invalidPayload) {
1049
- const { node, validatorEntryBuffer } = await resolveValidatorContext(context);
1050
-
1051
- const originalDecode = nodeEntryUtils.decode;
1052
- let decodeCount = 0;
1053
-
1054
- nodeEntryUtils.decode = function patchedDecode(buffer) {
1055
- if (validatorEntryBuffer && b4a.isBuffer(buffer) && b4a.equals(buffer, validatorEntryBuffer)) {
1056
- decodeCount += 1;
1057
- if (decodeCount === 2) {
1058
- console.error('Invalid validator entry.');
1059
- return null;
1060
- }
1061
- }
1062
- return originalDecode(buffer);
1063
- };
1064
-
1065
- try {
1066
- await appendInvalidTransferPayload(context, invalidPayload, { node });
1067
- } finally {
1068
- nodeEntryUtils.decode = originalDecode;
1069
- }
1070
- }
1071
-
1072
- export async function applyTransferValidatorBalanceInvalid(context, invalidPayload) {
1073
- const { node, validatorEntryBuffer } = await resolveValidatorContext(context);
1074
-
1075
- const originalDecode = nodeEntryUtils.decode;
1076
-
1077
- nodeEntryUtils.decode = function patchedDecode(buffer) {
1078
- const decoded = originalDecode(buffer);
1079
- if (decoded && validatorEntryBuffer && b4a.isBuffer(buffer) && b4a.equals(buffer, validatorEntryBuffer)) {
1080
- console.error('Invalid validator balance.');
1081
- return { ...decoded, balance: b4a.alloc(1) };
1082
- }
1083
- return decoded;
1084
- };
1085
-
1086
- try {
1087
- await appendInvalidTransferPayload(context, invalidPayload, { node });
1088
- } finally {
1089
- nodeEntryUtils.decode = originalDecode;
1090
- }
1091
- }
1092
-
1093
- export async function applyTransferValidatorRewardFailure(context, invalidPayload) {
1094
- const { node } = await resolveValidatorContext(context);
1095
- const balancePrototype = Object.getPrototypeOf(BALANCE_ZERO);
1096
- const originalPercentage = balancePrototype.percentage;
1097
- let shouldFailNextPercentage = true;
1098
-
1099
- balancePrototype.percentage = function patchedPercentage(...args) {
1100
- if (shouldFailNextPercentage) {
1101
- shouldFailNextPercentage = false;
1102
- console.error('Invalid validator reward.');
1103
- return null;
1104
- }
1105
- return originalPercentage.call(this, ...args);
1106
- };
1107
-
1108
- try {
1109
- await appendInvalidTransferPayload(context, invalidPayload, { node });
1110
- } finally {
1111
- balancePrototype.percentage = originalPercentage;
1112
- }
1113
- }
1114
-
1115
- export async function applyTransferValidatorBalanceAddFailure(context, invalidPayload) {
1116
- const { node } = await resolveValidatorContext(context);
1117
- const balancePrototype = Object.getPrototypeOf(BALANCE_ZERO);
1118
- const originalAdd = balancePrototype.add;
1119
- let shouldFailNextAdd = true;
1120
-
1121
- balancePrototype.add = function patchedAdd(...args) {
1122
- if (shouldFailNextAdd) {
1123
- shouldFailNextAdd = false;
1124
- return null;
1125
- }
1126
- return originalAdd.call(this, ...args);
1127
- };
1128
-
1129
- try {
1130
- await appendInvalidTransferPayload(context, invalidPayload, { node });
1131
- } finally {
1132
- balancePrototype.add = originalAdd;
1133
- }
1134
- }
1135
-
1136
- export async function applyTransferValidatorBalanceUpdateFailure(context, invalidPayload) {
1137
- const { node } = await resolveValidatorContext(context);
1138
- const balancePrototype = Object.getPrototypeOf(BALANCE_ZERO);
1139
- const originalUpdate = balancePrototype.update;
1140
- let updateCallCount = 0;
1141
-
1142
- balancePrototype.update = function patchedUpdate(...args) {
1143
- updateCallCount += 1;
1144
- if (updateCallCount === 2) {
1145
- return null;
1146
- }
1147
- return originalUpdate.call(this, ...args);
1148
- };
1149
-
1150
- try {
1151
- await appendInvalidTransferPayload(context, invalidPayload, { node });
1152
- } finally {
1153
- balancePrototype.update = originalUpdate;
1154
- }
1155
- }
1156
-
1157
- async function resolveValidatorContext(context) {
1158
- const node = context.transferScenario?.validatorPeer ?? context.peers?.[1];
1159
- const validatorPeer = context.transferScenario?.validatorPeer ?? selectValidatorPeer(context, 0);
1160
- if (!node?.base || !validatorPeer?.wallet?.address) {
1161
- throw new Error('Validator scenario requires a validator peer.');
1162
- }
1163
-
1164
- const validatorEntry = await node.base.view.get(validatorPeer.wallet.address);
1165
- if (!validatorEntry?.value) {
1166
- throw new Error('Validator scenario requires an existing validator entry.');
1167
- }
1168
-
1169
- return { node, validatorPeer, validatorEntryBuffer: validatorEntry.value };
1170
- }