trac-msb 0.2.4 → 0.2.6

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 (239) hide show
  1. package/.dockerignore +16 -0
  2. package/.github/workflows/acceptance-tests.yml +7 -0
  3. package/.github/workflows/publish.yml +40 -0
  4. package/.github/workflows/{CI.yml → unit-tests.yml} +1 -1
  5. package/README.md +175 -50
  6. package/docker-compose.yml +16 -0
  7. package/dockerfile +41 -0
  8. package/docs/fee_distribution.md +89 -0
  9. package/msb.mjs +12 -14
  10. package/package.json +8 -4
  11. package/rpc/constants.mjs +4 -1
  12. package/rpc/handlers.mjs +109 -66
  13. package/rpc/routes/v1.mjs +3 -1
  14. package/rpc/rpc_services.js +126 -0
  15. package/rpc/utils/confirmedParameter.mjs +17 -0
  16. package/rpc/utils/url.mjs +38 -0
  17. package/src/core/network/Network.js +27 -10
  18. package/src/core/network/identity/NetworkWalletFactory.js +78 -0
  19. package/src/core/network/services/ConnectionManager.js +2 -2
  20. package/src/core/network/services/ValidatorObserverService.js +7 -4
  21. package/src/core/state/State.js +28 -22
  22. package/src/index.js +197 -385
  23. package/src/utils/cliCommands.js +280 -0
  24. package/src/utils/constants.js +3 -1
  25. package/tests/acceptance/v1/account/account.test.mjs +123 -0
  26. package/tests/acceptance/v1/balance/balance.test.mjs +55 -0
  27. package/tests/acceptance/v1/broadcast-transaction/broadcast-transaction.test.mjs +111 -0
  28. package/tests/acceptance/v1/confirmed-length/confirmed-length.test.mjs +19 -0
  29. package/tests/acceptance/v1/fee/fee.test.mjs +11 -0
  30. package/tests/acceptance/v1/rpc.test.mjs +62 -291
  31. package/tests/acceptance/v1/tx/tx.test.mjs +98 -0
  32. package/tests/acceptance/v1/tx-details/tx-details.test.mjs +195 -0
  33. package/tests/acceptance/v1/tx-hashes/tx-hashes.test.mjs +72 -0
  34. package/tests/acceptance/v1/tx-payloads-bulk/tx-payloads-bulk.test.mjs +27 -0
  35. package/tests/acceptance/v1/txv/txv.test.mjs +11 -0
  36. package/tests/acceptance/v1/unconfirmed-length/unconfirmed-length.test.mjs +11 -0
  37. package/tests/helpers/StateNetworkFactory.js +157 -0
  38. package/tests/helpers/autobaseTestHelpers.js +369 -0
  39. package/tests/helpers/createTestSignature.js +12 -0
  40. package/tests/helpers/transactionPayloads.mjs +78 -0
  41. package/tests/unit/network/NetworkWalletFactory.test.js +156 -0
  42. package/tests/unit/state/apply/addAdmin/addAdminHappyPathScenario.js +38 -0
  43. package/tests/unit/state/apply/addAdmin/addAdminScenarioHelpers.js +273 -0
  44. package/tests/unit/state/apply/addAdmin/adminEntryEncodingFailureScenario.js +30 -0
  45. package/tests/unit/state/apply/addAdmin/adminEntryExistsScenario.js +78 -0
  46. package/tests/unit/state/apply/addAdmin/nodeEntryInitializationFailureScenario.js +30 -0
  47. package/tests/unit/state/apply/addAdmin/nonBootstrapNodeScenario.js +68 -0
  48. package/tests/unit/state/apply/addAdmin/state.apply.addAdmin.test.js +155 -0
  49. package/tests/unit/state/apply/addIndexer/addIndexerHappyPathScenario.js +39 -0
  50. package/tests/unit/state/apply/addIndexer/addIndexerMultipleIndexersInTheNetworkScenario.js +167 -0
  51. package/tests/unit/state/apply/addIndexer/addIndexerPretenderAlreadyIndexerScenario.js +21 -0
  52. package/tests/unit/state/apply/addIndexer/addIndexerPretenderNotWriterScenario.js +21 -0
  53. package/tests/unit/state/apply/addIndexer/addIndexerRemoveAndReAddScenario.js +186 -0
  54. package/tests/unit/state/apply/addIndexer/addIndexerScenarioHelpers.js +445 -0
  55. package/tests/unit/state/apply/addIndexer/addIndexerWriterKeyAlreadyRegisteredScenario.js +32 -0
  56. package/tests/unit/state/apply/addIndexer/state.apply.addIndexer.test.js +297 -0
  57. package/tests/unit/state/apply/addWriter/addWriterHappyPathScenario.js +41 -0
  58. package/tests/unit/state/apply/addWriter/addWriterInvalidValidatorSignatureScenario.js +32 -0
  59. package/tests/unit/state/apply/addWriter/addWriterNewWkScenario.js +149 -0
  60. package/tests/unit/state/apply/addWriter/addWriterRequesterAlreadyWriterScenario.js +21 -0
  61. package/tests/unit/state/apply/addWriter/addWriterRequesterBalanceInsufficientScenario.js +21 -0
  62. package/tests/unit/state/apply/addWriter/addWriterRequesterEntryDecodeFailureScenario.js +19 -0
  63. package/tests/unit/state/apply/addWriter/addWriterRequesterEntryMissingScenario.js +19 -0
  64. package/tests/unit/state/apply/addWriter/addWriterRequesterIndexerScenario.js +21 -0
  65. package/tests/unit/state/apply/addWriter/addWriterRequesterNotWhitelistedScenario.js +21 -0
  66. package/tests/unit/state/apply/addWriter/addWriterScenarioHelpers.js +757 -0
  67. package/tests/unit/state/apply/addWriter/addWriterStakeBalanceUpdateFailureScenario.js +50 -0
  68. package/tests/unit/state/apply/addWriter/addWriterStakeInsufficientBalanceScenario.js +29 -0
  69. package/tests/unit/state/apply/addWriter/addWriterStakeInvalidBalanceScenario.js +29 -0
  70. package/tests/unit/state/apply/addWriter/addWriterStakeInvalidEntryScenario.js +21 -0
  71. package/tests/unit/state/apply/addWriter/addWriterStakeStakedBalanceFailureScenario.js +37 -0
  72. package/tests/unit/state/apply/addWriter/addWriterStakeSubtractFailureScenario.js +42 -0
  73. package/tests/unit/state/apply/addWriter/addWriterValidatorRewardScenario.js +105 -0
  74. package/tests/unit/state/apply/addWriter/addWriterWriterKeyMismatchScenario.js +54 -0
  75. package/tests/unit/state/apply/addWriter/addWriterWriterKeyOwnershipScenario.js +54 -0
  76. package/tests/unit/state/apply/addWriter/addWriterZeroWriterKeyScenario.js +29 -0
  77. package/tests/unit/state/apply/addWriter/state.apply.addWriter.test.js +309 -0
  78. package/tests/unit/state/apply/adminRecovery/adminRecoveryHappyPathScenario.js +30 -0
  79. package/tests/unit/state/apply/adminRecovery/adminRecoveryScenarioHelpers.js +866 -0
  80. package/tests/unit/state/apply/adminRecovery/state.apply.adminRecovery.test.js +439 -0
  81. package/tests/unit/state/apply/appendWhitelist/appendWhitelistBanAndReapplyScenario.js +78 -0
  82. package/tests/unit/state/apply/appendWhitelist/appendWhitelistExistingReaderHappyPathScenario.js +98 -0
  83. package/tests/unit/state/apply/appendWhitelist/appendWhitelistFeeAfterDisableScenario.js +66 -0
  84. package/tests/unit/state/apply/appendWhitelist/appendWhitelistHappyPathScenario.js +55 -0
  85. package/tests/unit/state/apply/appendWhitelist/appendWhitelistInsufficientAdminBalanceScenario.js +103 -0
  86. package/tests/unit/state/apply/appendWhitelist/appendWhitelistNodeAlreadyWhitelistedScenario.js +60 -0
  87. package/tests/unit/state/apply/appendWhitelist/appendWhitelistScenarioHelpers.js +191 -0
  88. package/tests/unit/state/apply/appendWhitelist/state.apply.appendWhitelist.test.js +220 -0
  89. package/tests/unit/state/apply/balanceInitialization/balanceInitializationHappyPathScenario.js +82 -0
  90. package/tests/unit/state/apply/balanceInitialization/balanceInitializationScenarioHelpers.js +106 -0
  91. package/tests/unit/state/apply/balanceInitialization/invalidAmountScenario.js +45 -0
  92. package/tests/unit/state/apply/balanceInitialization/nodeEntryBalanceUpdateFailureScenario.js +81 -0
  93. package/tests/unit/state/apply/balanceInitialization/state.apply.balanceInitialization.test.js +189 -0
  94. package/tests/unit/state/apply/banValidator/banValidatorBanAndReWhitelistScenario.js +155 -0
  95. package/tests/unit/state/apply/banValidator/banValidatorHappyPathScenario.js +36 -0
  96. package/tests/unit/state/apply/banValidator/banValidatorScenarioHelpers.js +534 -0
  97. package/tests/unit/state/apply/banValidator/banValidatorSequentialBansScenario.js +74 -0
  98. package/tests/unit/state/apply/banValidator/banValidatorTargetDecodeFailureScenario.js +19 -0
  99. package/tests/unit/state/apply/banValidator/banValidatorTargetIndexerScenario.js +32 -0
  100. package/tests/unit/state/apply/banValidator/banValidatorTargetNodeEntryMissingScenario.js +19 -0
  101. package/tests/unit/state/apply/banValidator/banValidatorTargetRoleUpdateFailureScenario.js +19 -0
  102. package/tests/unit/state/apply/banValidator/banValidatorWhitelistedNonWriterScenario.js +38 -0
  103. package/tests/unit/state/apply/banValidator/banValidatorWhitelistedZeroBalanceScenario.js +91 -0
  104. package/tests/unit/state/apply/banValidator/banValidatorWithdrawFailureScenario.js +19 -0
  105. package/tests/unit/state/apply/banValidator/state.apply.banValidator.test.js +266 -0
  106. package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentDuplicateRegistrationScenario.js +142 -0
  107. package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentHappyPathScenario.js +26 -0
  108. package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentIncompleteOperationScenario.js +94 -0
  109. package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentInvalidDeploymentEntryScenario.js +37 -0
  110. package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentMultipleBootstrapScenario.js +86 -0
  111. package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentScenarioHelpers.js +344 -0
  112. package/tests/unit/state/apply/bootstrapDeployment/invalidValidatorNodeEntryScenario.js +57 -0
  113. package/tests/unit/state/apply/bootstrapDeployment/state.apply.bootstrapDeployment.test.js +429 -0
  114. package/tests/unit/state/apply/common/access-control/adminConsistencyMismatchScenario.js +119 -0
  115. package/tests/unit/state/apply/common/access-control/adminEntryDecodeFailureScenario.js +130 -0
  116. package/tests/unit/state/apply/common/access-control/adminEntryExistsScenario.js +93 -0
  117. package/tests/unit/state/apply/common/access-control/adminEntryMissingScenario.js +108 -0
  118. package/tests/unit/state/apply/common/access-control/adminOnlyGuardScenario.js +126 -0
  119. package/tests/unit/state/apply/common/access-control/adminPublicKeyDecodeFailureScenario.js +120 -0
  120. package/tests/unit/state/apply/common/access-control/roleAccessOperationValidationScenario.js +50 -0
  121. package/tests/unit/state/apply/common/adminControlOperationValidationScenario.js +56 -0
  122. package/tests/unit/state/apply/common/balances/adminEntryUpdateFailureScenario.js +52 -0
  123. package/tests/unit/state/apply/common/balances/base/requesterBalanceScenarioBase.js +197 -0
  124. package/tests/unit/state/apply/common/balances/feeDecodeFailureScenario.js +52 -0
  125. package/tests/unit/state/apply/common/balances/requesterBalanceDecodeFailureScenario.js +15 -0
  126. package/tests/unit/state/apply/common/balances/requesterBalanceFeeApplicationFailureScenario.js +11 -0
  127. package/tests/unit/state/apply/common/balances/requesterBalanceInsufficientScenario.js +15 -0
  128. package/tests/unit/state/apply/common/balances/requesterBalanceUpdateFailureScenario.js +11 -0
  129. package/tests/unit/state/apply/common/balances/validatorEntryRewardFailureScenario.js +11 -0
  130. package/tests/unit/state/apply/common/balances/validatorEntryUpdateFailureScenario.js +11 -0
  131. package/tests/unit/state/apply/common/balances/validatorNodeEntryDecodeFailureScenario.js +40 -0
  132. package/tests/unit/state/apply/common/base/OperationValidationScenarioBase.js +114 -0
  133. package/tests/unit/state/apply/common/commonScenarioHelper.js +103 -0
  134. package/tests/unit/state/apply/common/indexer/indexerNodeEntryDecodeFailureScenario.js +36 -0
  135. package/tests/unit/state/apply/common/indexer/indexerNodeEntryMissingScenario.js +36 -0
  136. package/tests/unit/state/apply/common/indexer/indexerRoleUpdateFailureScenario.js +29 -0
  137. package/tests/unit/state/apply/common/indexer/indexerSequenceStateInvalidScenario.js +66 -0
  138. package/tests/unit/state/apply/common/invalidMessageComponentValidationScenario.js +84 -0
  139. package/tests/unit/state/apply/common/nodeEntryInitializationFailureScenario.js +47 -0
  140. package/tests/unit/state/apply/common/operationAlreadyAppliedScenario.js +85 -0
  141. package/tests/unit/state/apply/common/payload-structure/addressWithInvalidPublicKeyScenario.js +52 -0
  142. package/tests/unit/state/apply/common/payload-structure/initializationDisabledScenario.js +49 -0
  143. package/tests/unit/state/apply/common/payload-structure/invalidAddressValidationScenario.js +73 -0
  144. package/tests/unit/state/apply/common/payload-structure/invalidHashValidationScenario.js +71 -0
  145. package/tests/unit/state/apply/common/payload-structure/invalidPayloadValidationScenario.js +31 -0
  146. package/tests/unit/state/apply/common/payload-structure/invalidSignatureValidationScenario.js +142 -0
  147. package/tests/unit/state/apply/common/payload-structure/partialOperationValidationScenario.js +87 -0
  148. package/tests/unit/state/apply/common/requester/requesterNodeEntryBufferMissingScenario.js +70 -0
  149. package/tests/unit/state/apply/common/requester/requesterNodeEntryDecodeFailureScenario.js +72 -0
  150. package/tests/unit/state/apply/common/requester/requesterNodeEntryMissingScenario.js +36 -0
  151. package/tests/unit/state/apply/common/requesterAddressValidationScenario.js +44 -0
  152. package/tests/unit/state/apply/common/requesterPublicKeyValidationScenario.js +25 -0
  153. package/tests/unit/state/apply/common/transactionValidityMismatchScenario.js +98 -0
  154. package/tests/unit/state/apply/common/validatorConsistency/base/validatorConsistencyScenarioBase.js +201 -0
  155. package/tests/unit/state/apply/common/validatorConsistency/validatorEntryDecodeFailureScenario.js +17 -0
  156. package/tests/unit/state/apply/common/validatorConsistency/validatorEntryMissingScenario.js +44 -0
  157. package/tests/unit/state/apply/common/validatorConsistency/validatorInactiveScenario.js +19 -0
  158. package/tests/unit/state/apply/common/validatorConsistency/validatorWriterKeyMismatchScenario.js +18 -0
  159. package/tests/unit/state/apply/common/validatorEntryValidation/base/validatorEntryValidationScenarioBase.js +314 -0
  160. package/tests/unit/state/apply/common/validatorEntryValidation/validatorEntryInvalidBalanceScenario.js +18 -0
  161. package/tests/unit/state/apply/common/writerKeyExistsValidationScenario.js +43 -0
  162. package/tests/unit/state/apply/disableInitialization/disableInitializationAlreadyDisabledScenario.js +53 -0
  163. package/tests/unit/state/apply/disableInitialization/disableInitializationHappyPathScenario.js +24 -0
  164. package/tests/unit/state/apply/disableInitialization/disableInitializationScenarioHelpers.js +197 -0
  165. package/tests/unit/state/apply/disableInitialization/state.apply.disableInitialization.test.js +161 -0
  166. package/tests/unit/state/apply/missing-tests.md +18 -0
  167. package/tests/unit/state/apply/removeIndexer/removeIndexerHappyPathScenario.js +58 -0
  168. package/tests/unit/state/apply/removeIndexer/removeIndexerReAddAndRemoveAgainScenario.js +98 -0
  169. package/tests/unit/state/apply/removeIndexer/removeIndexerRemoveMultipleIndexersScenario.js +167 -0
  170. package/tests/unit/state/apply/removeIndexer/removeIndexerScenarioHelpers.js +428 -0
  171. package/tests/unit/state/apply/removeIndexer/removeIndexerTargetNotIndexerScenario.js +22 -0
  172. package/tests/unit/state/apply/removeIndexer/removeIndexerWriterKeyMissingScenario.js +20 -0
  173. package/tests/unit/state/apply/removeIndexer/state.apply.removeIndexer.test.js +291 -0
  174. package/tests/unit/state/apply/removeWriter/removeWriterAndAddWriterAgainScenario.js +87 -0
  175. package/tests/unit/state/apply/removeWriter/removeWriterHappyPathScenario.js +38 -0
  176. package/tests/unit/state/apply/removeWriter/removeWriterInvalidValidatorSignatureScenario.js +32 -0
  177. package/tests/unit/state/apply/removeWriter/removeWriterRequesterBalanceInsufficientScenario.js +21 -0
  178. package/tests/unit/state/apply/removeWriter/removeWriterRequesterEntryDecodeFailureScenario.js +19 -0
  179. package/tests/unit/state/apply/removeWriter/removeWriterRequesterEntryMissingScenario.js +19 -0
  180. package/tests/unit/state/apply/removeWriter/removeWriterRequesterIndexerScenario.js +21 -0
  181. package/tests/unit/state/apply/removeWriter/removeWriterRequesterNotWriterScenario.js +21 -0
  182. package/tests/unit/state/apply/removeWriter/removeWriterRequesterRoleUpdateFailureScenario.js +19 -0
  183. package/tests/unit/state/apply/removeWriter/removeWriterScenarioHelpers.js +344 -0
  184. package/tests/unit/state/apply/removeWriter/removeWriterThroughWriterValidatorScenario.js +113 -0
  185. package/tests/unit/state/apply/removeWriter/removeWriterUnstakeFailureScenario.js +33 -0
  186. package/tests/unit/state/apply/removeWriter/removeWriterWriterKeyMismatchScenario.js +21 -0
  187. package/tests/unit/state/apply/removeWriter/removeWriterWriterKeyOwnershipScenario.js +26 -0
  188. package/tests/unit/state/apply/removeWriter/removeWriterWriterKeyRegistryMissingScenario.js +22 -0
  189. package/tests/unit/state/apply/removeWriter/state.apply.removeWriter.test.js +307 -0
  190. package/tests/unit/state/apply/state.apply.test.js +24 -0
  191. package/tests/unit/state/apply/transfer/state.apply.transfer.test.js +819 -0
  192. package/tests/unit/state/apply/transfer/transferContractSchemaValidationScenario.js +22 -0
  193. package/tests/unit/state/apply/transfer/transferDoubleSpendAcrossValidatorsScenario.js +137 -0
  194. package/tests/unit/state/apply/transfer/transferDoubleSpendSameBatchScenario.js +63 -0
  195. package/tests/unit/state/apply/transfer/transferDoubleSpendSingleValidatorScenario.js +67 -0
  196. package/tests/unit/state/apply/transfer/transferExistingRecipientAmountScenario.js +31 -0
  197. package/tests/unit/state/apply/transfer/transferExistingRecipientZeroAmountScenario.js +31 -0
  198. package/tests/unit/state/apply/transfer/transferHandlerGuardScenarios.js +22 -0
  199. package/tests/unit/state/apply/transfer/transferHappyPathScenario.js +8 -0
  200. package/tests/unit/state/apply/transfer/transferInvalidIncomingDataScenario.js +66 -0
  201. package/tests/unit/state/apply/transfer/transferNewRecipientAmountScenario.js +31 -0
  202. package/tests/unit/state/apply/transfer/transferNewRecipientZeroAmountScenario.js +31 -0
  203. package/tests/unit/state/apply/transfer/transferScenarioHelpers.js +1167 -0
  204. package/tests/unit/state/apply/transfer/transferSelfTransferAmountScenario.js +38 -0
  205. package/tests/unit/state/apply/transfer/transferSelfTransferZeroAmountScenario.js +38 -0
  206. package/tests/unit/state/apply/transfer/transferValidatorRecipientAmountScenario.js +38 -0
  207. package/tests/unit/state/apply/transfer/transferValidatorRecipientZeroAmountScenario.js +38 -0
  208. package/tests/unit/state/apply/txOperation/state.apply.txOperation.test.js +318 -0
  209. package/tests/unit/state/apply/txOperation/txOperationBootstrapNotRegisteredScenario.js +70 -0
  210. package/tests/unit/state/apply/txOperation/txOperationDifferentValidatorCreatorHappyPathScenario.js +23 -0
  211. package/tests/unit/state/apply/txOperation/txOperationInvalidDeploymentEntryScenario.js +48 -0
  212. package/tests/unit/state/apply/txOperation/txOperationInvalidFeeAmountScenario.js +39 -0
  213. package/tests/unit/state/apply/txOperation/txOperationInvalidSubnetCreatorAddressScenario.js +46 -0
  214. package/tests/unit/state/apply/txOperation/txOperationRequesterCreatorHappyPathScenario.js +21 -0
  215. package/tests/unit/state/apply/txOperation/txOperationScenarioHelpers.js +429 -0
  216. package/tests/unit/state/apply/txOperation/txOperationStandardHappyPathScenario.js +21 -0
  217. package/tests/unit/state/apply/txOperation/txOperationTransferFeeAddCreatorBalanceFailureScenario.js +26 -0
  218. package/tests/unit/state/apply/txOperation/txOperationTransferFeeAddValidatorBalanceFailureScenario.js +25 -0
  219. package/tests/unit/state/apply/txOperation/txOperationTransferFeeAddValidatorBonusFailureScenario.js +27 -0
  220. package/tests/unit/state/apply/txOperation/txOperationTransferFeeDecodeCreatorEntryScenario.js +18 -0
  221. package/tests/unit/state/apply/txOperation/txOperationTransferFeeDecodeRequesterEntryScenario.js +17 -0
  222. package/tests/unit/state/apply/txOperation/txOperationTransferFeeDecodeValidatorEntryScenario.js +31 -0
  223. package/tests/unit/state/apply/txOperation/txOperationTransferFeeGuardBypassScenario.js +49 -0
  224. package/tests/unit/state/apply/txOperation/txOperationTransferFeeGuardScenarioFactory.js +92 -0
  225. package/tests/unit/state/apply/txOperation/txOperationTransferFeeInsufficientRequesterBalanceScenario.js +28 -0
  226. package/tests/unit/state/apply/txOperation/txOperationTransferFeeInvalidCreatorBalanceScenario.js +29 -0
  227. package/tests/unit/state/apply/txOperation/txOperationTransferFeeInvalidRequesterBalanceScenario.js +28 -0
  228. package/tests/unit/state/apply/txOperation/txOperationTransferFeeInvalidRequesterEntryScenario.js +17 -0
  229. package/tests/unit/state/apply/txOperation/txOperationTransferFeeInvalidValidatorBalanceScenario.js +33 -0
  230. package/tests/unit/state/apply/txOperation/txOperationTransferFeeMissingCreatorEntryScenario.js +18 -0
  231. package/tests/unit/state/apply/txOperation/txOperationTransferFeeSubtractFailureScenario.js +25 -0
  232. package/tests/unit/state/apply/txOperation/txOperationTransferFeeUpdateCreatorBalanceFailureScenario.js +26 -0
  233. package/tests/unit/state/apply/txOperation/txOperationTransferFeeUpdateFailureScenario.js +25 -0
  234. package/tests/unit/state/apply/txOperation/txOperationTransferFeeUpdateValidatorBalanceFailureScenario.js +26 -0
  235. package/tests/unit/state/apply/txOperation/txOperationTransferFeeUpdateValidatorBonusFailureScenario.js +27 -0
  236. package/tests/unit/state/apply/txOperation/txOperationValidatorCreatorHappyPathScenario.js +21 -0
  237. package/tests/unit/state/stateModule.test.js +1 -0
  238. package/tests/unit/state/stateTestUtils.js +5 -1
  239. package/.env +0 -3
@@ -0,0 +1,66 @@
1
+ import OperationValidationScenarioBase from '../base/OperationValidationScenarioBase.js';
2
+ import { eventFlush } from '../../../../../helpers/autobaseTestHelpers.js';
3
+
4
+ const passThroughPayload = (_t, payload) => payload;
5
+
6
+ export default class IndexerSequenceStateInvalidScenario extends OperationValidationScenarioBase {
7
+ constructor({
8
+ title,
9
+ setupScenario,
10
+ buildValidPayload,
11
+ assertStateUnchanged,
12
+ mutatePayload = passThroughPayload,
13
+ applyInvalidPayload = applyWithIndexerSequenceFailure,
14
+ expectedLogs
15
+ }) {
16
+ super({
17
+ title,
18
+ setupScenario,
19
+ buildValidPayload,
20
+ mutatePayload,
21
+ applyInvalidPayload,
22
+ assertStateUnchanged,
23
+ expectedLogs
24
+ });
25
+ }
26
+ }
27
+
28
+ async function applyWithIndexerSequenceFailure(context, invalidPayload) {
29
+ const node = context.bootstrap ?? context.adminBootstrap ?? context.peers?.[0];
30
+ if (!node?.base?.system) {
31
+ return;
32
+ }
33
+
34
+ const system = node.base.system;
35
+ const originalDescriptor = Object.getOwnPropertyDescriptor(system, 'indexers');
36
+ const originalValue = system.indexers;
37
+ let injected = false;
38
+
39
+ Object.defineProperty(system, 'indexers', {
40
+ configurable: true,
41
+ enumerable: true,
42
+ get() {
43
+ if (!injected) {
44
+ injected = true;
45
+ throw new Error('forced indexer sequence state failure');
46
+ }
47
+ return originalValue;
48
+ },
49
+ set(value) {
50
+ // preserve setter semantics
51
+ return Reflect.set(system, 'indexers', value);
52
+ }
53
+ });
54
+
55
+ try {
56
+ await node.base.append(invalidPayload).catch(() => {});
57
+ await node.base.update().catch(() => {});
58
+ } finally {
59
+ if (originalDescriptor) {
60
+ Object.defineProperty(system, 'indexers', originalDescriptor);
61
+ } else {
62
+ system.indexers = originalValue;
63
+ }
64
+ await eventFlush();
65
+ }
66
+ }
@@ -0,0 +1,84 @@
1
+ import OperationValidationScenarioBase from './base/OperationValidationScenarioBase.js';
2
+ import { eventFlush } from '../../../../helpers/autobaseTestHelpers.js';
3
+ import b4a from 'b4a';
4
+ import { safeDecodeApplyOperation, safeEncodeApplyOperation } from '../../../../../src/utils/protobuf/operationHelpers.js';
5
+
6
+ export const MessageComponentStrategy = {
7
+ TX_VALIDITY: 'TX_VALIDITY',
8
+ NONCE: 'NONCE'
9
+ };
10
+
11
+ export default class InvalidMessageComponentValidationScenario extends OperationValidationScenarioBase {
12
+ constructor({
13
+ title,
14
+ setupScenario,
15
+ buildValidPayload,
16
+ assertStateUnchanged,
17
+ strategy = MessageComponentStrategy.TX_VALIDITY,
18
+ applyInvalidPayload = defaultApplyInvalidPayload,
19
+ expectedLogs
20
+ }) {
21
+ const mutatePayload = createMutationStrategy(strategy);
22
+ super({
23
+ title,
24
+ setupScenario,
25
+ buildValidPayload,
26
+ mutatePayload,
27
+ applyInvalidPayload,
28
+ assertStateUnchanged,
29
+ expectedLogs
30
+ });
31
+ }
32
+ }
33
+
34
+ function createMutationStrategy(strategy) {
35
+ switch (strategy) {
36
+ case MessageComponentStrategy.NONCE:
37
+ return mutateNonce;
38
+ case MessageComponentStrategy.TX_VALIDITY:
39
+ default:
40
+ return mutateTxValidity;
41
+ }
42
+ }
43
+
44
+ function mutateTxValidity(t, validPayload) {
45
+ return mutateComponent(t, validPayload, 'txv');
46
+ }
47
+
48
+ function mutateNonce(t, validPayload) {
49
+ return mutateComponent(t, validPayload, 'in');
50
+ }
51
+
52
+ function mutateComponent(t, validPayload, componentKey) {
53
+ const decodedPayload = safeDecodeApplyOperation(validPayload);
54
+ t.ok(decodedPayload, 'fixtures decode');
55
+
56
+ const parent = findParentWithKey(decodedPayload, componentKey);
57
+ if (!parent || !parent[componentKey]) return validPayload;
58
+
59
+ parent[componentKey] = flipBuffer(parent[componentKey]);
60
+ return safeEncodeApplyOperation(decodedPayload);
61
+ }
62
+
63
+ function findParentWithKey(payload, key) {
64
+ const parents = ['cao', 'bio', 'aco', 'tro', 'rao', 'bdo', 'txo'];
65
+ for (const parentKey of parents) {
66
+ const parent = payload[parentKey];
67
+ if (parent?.[key]) return parent;
68
+ }
69
+ return null;
70
+ }
71
+
72
+ function flipBuffer(buf) {
73
+ const clone = b4a.from(buf);
74
+ if (clone.length === 0) return clone;
75
+ clone[clone.length - 1] ^= 0xff;
76
+ return clone;
77
+ }
78
+
79
+ async function defaultApplyInvalidPayload(context, invalidPayload) {
80
+ const { bootstrap } = context;
81
+ await bootstrap.base.append(invalidPayload);
82
+ await bootstrap.base.update();
83
+ await eventFlush();
84
+ }
@@ -0,0 +1,47 @@
1
+ import OperationValidationScenarioBase from './base/OperationValidationScenarioBase.js';
2
+ import nodeEntryUtils from '../../../../../src/core/state/utils/nodeEntry.js';
3
+ import { eventFlush } from '../../../../helpers/autobaseTestHelpers.js';
4
+
5
+ /**
6
+ * Forces nodeEntryUtils.init to return an empty buffer once, triggering
7
+ * "Failed to initialize node entry." in handlers that create a fresh entry.
8
+ */
9
+ export default function createNodeEntryInitializationFailureScenario({
10
+ title,
11
+ setupScenario,
12
+ buildValidPayload,
13
+ assertStateUnchanged,
14
+ selectNode,
15
+ expectedLogs = ['Failed to initialize node entry.']
16
+ }) {
17
+ return new OperationValidationScenarioBase({
18
+ title,
19
+ setupScenario,
20
+ buildValidPayload,
21
+ mutatePayload: (_t, payload) => payload,
22
+ applyInvalidPayload: async (context, invalidPayload) => {
23
+ const node = selectNode ? selectNode(context) : context.adminBootstrap;
24
+ const originalInit = nodeEntryUtils.init;
25
+ let shouldFailNextInit = true;
26
+
27
+ nodeEntryUtils.init = function patchedInit(...args) {
28
+ if (shouldFailNextInit) {
29
+ shouldFailNextInit = false;
30
+ console.error(expectedLogs[0]);
31
+ return Buffer.alloc(0);
32
+ }
33
+ return originalInit.call(this, ...args);
34
+ };
35
+
36
+ try {
37
+ await node.base.append(invalidPayload);
38
+ await node.base.update();
39
+ await eventFlush();
40
+ } finally {
41
+ nodeEntryUtils.init = originalInit;
42
+ }
43
+ },
44
+ assertStateUnchanged,
45
+ expectedLogs
46
+ });
47
+ }
@@ -0,0 +1,85 @@
1
+ import { eventFlush } from '../../../../helpers/autobaseTestHelpers.js';
2
+ import OperationValidationScenarioBase from './base/OperationValidationScenarioBase.js';
3
+
4
+ export default class OperationAlreadyAppliedScenario extends OperationValidationScenarioBase {
5
+ constructor({
6
+ title,
7
+ setupScenario,
8
+ buildValidPayload,
9
+ assertStateUnchanged,
10
+ mutatePayload = passThroughPayload,
11
+ selectNode = defaultSelectNode,
12
+ applyInvalidPayload,
13
+ beforeInvalidApply,
14
+ expectedLogs
15
+ }) {
16
+ const applyPayload =
17
+ applyInvalidPayload ??
18
+ ((context, invalidPayload, t, validPayload) =>
19
+ defaultApplyInvalidPayload({
20
+ context,
21
+ invalidPayload,
22
+ validPayload,
23
+ selectNode,
24
+ beforeInvalidApply,
25
+ t
26
+ }));
27
+
28
+ super({
29
+ title,
30
+ setupScenario,
31
+ buildValidPayload,
32
+ mutatePayload,
33
+ applyInvalidPayload: applyPayload,
34
+ assertStateUnchanged,
35
+ expectedLogs
36
+ });
37
+ }
38
+ }
39
+
40
+ function passThroughPayload(_t, payload) {
41
+ return payload;
42
+ }
43
+
44
+ function defaultSelectNode(context) {
45
+ return context.adminBootstrap ?? context.bootstrap ?? context.peers?.[0] ?? null;
46
+ }
47
+
48
+ async function defaultApplyInvalidPayload({
49
+ context,
50
+ invalidPayload,
51
+ validPayload,
52
+ selectNode,
53
+ beforeInvalidApply,
54
+ t
55
+ }) {
56
+ const node = selectNode(context);
57
+ if (!node?.base) {
58
+ throw new Error('Operation already applied scenario requires a writable node.');
59
+ }
60
+
61
+ await node.base.append(validPayload);
62
+ await node.base.update();
63
+ await eventFlush();
64
+
65
+ let cleanup;
66
+ if (beforeInvalidApply) {
67
+ cleanup = await beforeInvalidApply({
68
+ context,
69
+ node,
70
+ invalidPayload,
71
+ validPayload,
72
+ t
73
+ });
74
+ }
75
+
76
+ try {
77
+ await node.base.append(invalidPayload);
78
+ await node.base.update();
79
+ await eventFlush();
80
+ } finally {
81
+ if (typeof cleanup === 'function') {
82
+ await cleanup();
83
+ }
84
+ }
85
+ }
@@ -0,0 +1,52 @@
1
+ import b4a from 'b4a';
2
+ import InvalidAddressValidationScenario from './invalidAddressValidationScenario.js';
3
+ import {
4
+ safeDecodeApplyOperation,
5
+ safeEncodeApplyOperation
6
+ } from '../../../../../../src/utils/protobuf/operationHelpers.js';
7
+
8
+ export default function createAddressWithInvalidPublicKeyScenario(config, pathOverride) {
9
+ const { addressPath, ...rest } = config ?? {};
10
+ const normalizedPath = normalizePath(pathOverride ?? addressPath);
11
+
12
+ return new InvalidAddressValidationScenario({
13
+ ...rest,
14
+ mutatePayload: (t, payload) => mutateAddressBuffer(t, payload, normalizedPath)
15
+ });
16
+ }
17
+
18
+ function normalizePath(path) {
19
+ if (!path) return ['address'];
20
+ return Array.isArray(path) ? path : [path];
21
+ }
22
+
23
+ function mutateAddressBuffer(t, validPayload, path) {
24
+ const decodedPayload = safeDecodeApplyOperation(validPayload);
25
+ t.ok(decodedPayload, 'fixtures decode');
26
+
27
+ const parent = locateParent(decodedPayload, path);
28
+ if (!parent) return validPayload;
29
+
30
+ const field = path[path.length - 1];
31
+ const buffer = parent[field];
32
+ if (!b4a.isBuffer(buffer)) return validPayload;
33
+
34
+ const mutatedBuffer = b4a.from(buffer);
35
+ const lastIndex = mutatedBuffer.length - 1;
36
+ const currentChar = mutatedBuffer[lastIndex];
37
+ const asciiP = 'p'.charCodeAt(0);
38
+ const asciiQ = 'q'.charCodeAt(0);
39
+ mutatedBuffer[lastIndex] = currentChar === asciiP ? asciiQ : asciiP;
40
+
41
+ parent[field] = mutatedBuffer;
42
+ return safeEncodeApplyOperation(decodedPayload);
43
+ }
44
+
45
+ function locateParent(payload, path) {
46
+ let current = payload;
47
+ for (let i = 0; i < path.length - 1; i++) {
48
+ if (!current) return null;
49
+ current = current[path[i]];
50
+ }
51
+ return current ?? null;
52
+ }
@@ -0,0 +1,49 @@
1
+ import { eventFlush, deriveIndexerSequenceState } from '../../../../../helpers/autobaseTestHelpers.js';
2
+ import OperationValidationScenarioBase from '../base/OperationValidationScenarioBase.js';
3
+ import CompleteStateMessageOperations from '../../../../../../src/messages/completeStateMessages/CompleteStateMessageOperations.js';
4
+
5
+ export default class InitializationDisabledScenario extends OperationValidationScenarioBase {
6
+ constructor({
7
+ title,
8
+ setupScenario,
9
+ buildValidPayload,
10
+ assertStateUnchanged,
11
+ expectedLogs
12
+ }) {
13
+ super({
14
+ title,
15
+ setupScenario,
16
+ buildValidPayload,
17
+ mutatePayload: passThroughPayload,
18
+ applyInvalidPayload: disableInitializationAndApply,
19
+ assertStateUnchanged,
20
+ expectedLogs
21
+ });
22
+ }
23
+ }
24
+
25
+ function passThroughPayload(_t, payload) {
26
+ return payload;
27
+ }
28
+
29
+ async function disableInitializationAndApply(context, invalidPayload) {
30
+ const adminNode = context.adminBootstrap ?? context.bootstrap;
31
+ if (!adminNode) {
32
+ throw new Error('Initialization disabled scenario requires admin bootstrap context.');
33
+ }
34
+
35
+ const txValidity = await deriveIndexerSequenceState(adminNode.base);
36
+ const disablePayload = await CompleteStateMessageOperations.assembleDisableInitializationMessage(
37
+ adminNode.wallet,
38
+ adminNode.base.local.key,
39
+ txValidity
40
+ );
41
+
42
+ await adminNode.base.append(disablePayload);
43
+ await adminNode.base.update();
44
+ await eventFlush();
45
+
46
+ await adminNode.base.append(invalidPayload);
47
+ await adminNode.base.update();
48
+ await eventFlush();
49
+ }
@@ -0,0 +1,73 @@
1
+ import b4a from 'b4a';
2
+ import { eventFlush } from '../../../../../helpers/autobaseTestHelpers.js';
3
+ import {
4
+ safeDecodeApplyOperation,
5
+ safeEncodeApplyOperation
6
+ } from '../../../../../../src/utils/protobuf/operationHelpers.js';
7
+ import OperationValidationScenarioBase from '../base/OperationValidationScenarioBase.js';
8
+
9
+ export default class InvalidAddressValidationScenario extends OperationValidationScenarioBase {
10
+ constructor({
11
+ title,
12
+ setupScenario,
13
+ buildValidPayload,
14
+ assertStateUnchanged,
15
+ addressPath,
16
+ mutatePayload,
17
+ applyInvalidPayload = defaultApplyInvalidPayload,
18
+ expectedLogs
19
+ }) {
20
+ const mutation = mutatePayload ?? createDefaultMutation(addressPath ?? ['address']);
21
+
22
+ super({
23
+ title,
24
+ setupScenario,
25
+ buildValidPayload,
26
+ mutatePayload: mutation,
27
+ applyInvalidPayload,
28
+ assertStateUnchanged,
29
+ expectedLogs
30
+ });
31
+ }
32
+ }
33
+
34
+ function createDefaultMutation(addressPath) {
35
+ const pathArray = Array.isArray(addressPath) ? addressPath : [addressPath];
36
+ if (!pathArray.length) {
37
+ throw new Error('Invalid address mutation requires a non-empty addressPath.');
38
+ }
39
+
40
+ return (t, validPayload) => {
41
+ const decodedPayload = safeDecodeApplyOperation(validPayload);
42
+ t.ok(decodedPayload, 'fixtures decode');
43
+
44
+ const parent = locateParent(decodedPayload, pathArray);
45
+ if (!parent) return validPayload;
46
+
47
+ const field = pathArray[pathArray.length - 1];
48
+ const buffer = parent[field];
49
+ if (!b4a.isBuffer(buffer)) return validPayload;
50
+
51
+ const mutated = b4a.from(buffer);
52
+ mutated[0] = mutated[0] === 120 ? 121 : 120;
53
+ parent[field] = mutated;
54
+
55
+ return safeEncodeApplyOperation(decodedPayload);
56
+ };
57
+ }
58
+
59
+ function locateParent(payload, pathArray) {
60
+ let current = payload;
61
+ for (let i = 0; i < pathArray.length - 1; i++) {
62
+ if (!current) return null;
63
+ current = current[pathArray[i]];
64
+ }
65
+ return current ?? null;
66
+ }
67
+
68
+ async function defaultApplyInvalidPayload(context, invalidPayload) {
69
+ const { bootstrap } = context;
70
+ await bootstrap.base.append(invalidPayload);
71
+ await bootstrap.base.update();
72
+ await eventFlush();
73
+ }
@@ -0,0 +1,71 @@
1
+ import { eventFlush } from '../../../../../helpers/autobaseTestHelpers.js';
2
+ import {
3
+ safeDecodeApplyOperation,
4
+ safeEncodeApplyOperation
5
+ } from '../../../../../../src/utils/protobuf/operationHelpers.js';
6
+ import { blake3Hash } from '../../../../../../src/utils/crypto.js';
7
+ import OperationValidationScenarioBase from '../base/OperationValidationScenarioBase.js';
8
+
9
+ export default class InvalidHashValidationScenario extends OperationValidationScenarioBase {
10
+ constructor({
11
+ title,
12
+ setupScenario,
13
+ buildValidPayload,
14
+ assertStateUnchanged,
15
+ mutatePayload = defaultMutateHash,
16
+ applyInvalidPayload = defaultApplyInvalidPayload,
17
+ expectedLogs
18
+ }) {
19
+ super({
20
+ title,
21
+ setupScenario,
22
+ buildValidPayload,
23
+ mutatePayload,
24
+ applyInvalidPayload,
25
+ assertStateUnchanged,
26
+ expectedLogs
27
+ });
28
+ }
29
+ }
30
+
31
+ async function defaultMutateHash(t, validPayload) {
32
+ const decodedPayload = safeDecodeApplyOperation(validPayload);
33
+ t.ok(decodedPayload, 'fixtures decode');
34
+
35
+ const invalidHash = await blake3Hash(validPayload);
36
+
37
+ switch (true) {
38
+ case Boolean(decodedPayload.cao?.tx):
39
+ decodedPayload.cao.tx = invalidHash;
40
+ break;
41
+ case Boolean(decodedPayload.bio?.tx):
42
+ decodedPayload.bio.tx = invalidHash;
43
+ break;
44
+ case Boolean(decodedPayload.aco?.tx):
45
+ decodedPayload.aco.tx = invalidHash;
46
+ break;
47
+ case Boolean(decodedPayload.tro?.tx):
48
+ decodedPayload.tro.tx = invalidHash;
49
+ break;
50
+ case Boolean(decodedPayload.rao?.tx):
51
+ decodedPayload.rao.tx = invalidHash;
52
+ break;
53
+ case Boolean(decodedPayload.bdo?.tx):
54
+ decodedPayload.bdo.tx = invalidHash;
55
+ break;
56
+ case Boolean(decodedPayload.txo?.tx):
57
+ decodedPayload.txo.tx = invalidHash;
58
+ break;
59
+ default:
60
+ return validPayload;
61
+ }
62
+
63
+ return safeEncodeApplyOperation(decodedPayload);
64
+ }
65
+
66
+ async function defaultApplyInvalidPayload(context, invalidPayload) {
67
+ const { bootstrap } = context;
68
+ await bootstrap.base.append(invalidPayload);
69
+ await bootstrap.base.update();
70
+ await eventFlush();
71
+ }
@@ -0,0 +1,31 @@
1
+ import { eventFlush } from '../../../../../helpers/autobaseTestHelpers.js';
2
+ import OperationValidationScenarioBase from '../base/OperationValidationScenarioBase.js';
3
+
4
+ export default class InvalidPayloadValidationScenario extends OperationValidationScenarioBase {
5
+ constructor({
6
+ title,
7
+ setupScenario,
8
+ buildValidPayload,
9
+ mutatePayload,
10
+ assertStateUnchanged,
11
+ applyInvalidPayload = defaultApplyInvalidPayload,
12
+ expectedLogs
13
+ }) {
14
+ super({
15
+ title,
16
+ setupScenario,
17
+ buildValidPayload,
18
+ mutatePayload,
19
+ applyInvalidPayload,
20
+ assertStateUnchanged,
21
+ expectedLogs
22
+ });
23
+ }
24
+ }
25
+
26
+ async function defaultApplyInvalidPayload(context, invalidPayload) {
27
+ const { bootstrap } = context;
28
+ await bootstrap.base.append(invalidPayload);
29
+ await bootstrap.base.update();
30
+ await eventFlush();
31
+ }
@@ -0,0 +1,142 @@
1
+ import b4a from 'b4a';
2
+ import { eventFlush } from '../../../../../helpers/autobaseTestHelpers.js';
3
+ import {
4
+ safeDecodeApplyOperation,
5
+ safeEncodeApplyOperation
6
+ } from '../../../../../../src/utils/protobuf/operationHelpers.js';
7
+ import OperationValidationScenarioBase from '../base/OperationValidationScenarioBase.js';
8
+ import { createSignature } from '../../../../../helpers/createTestSignature.js';
9
+
10
+ export const SignatureMutationStrategy = {
11
+ ZERO_FILL: 0,
12
+ FOREIGN_SIGNATURE: 1,
13
+ TYPE_MISMATCH: 2,
14
+ AMOUNT_SIGNATURE: 3
15
+ };
16
+
17
+ export default class InvalidSignatureValidationScenario extends OperationValidationScenarioBase {
18
+ constructor({
19
+ title,
20
+ setupScenario,
21
+ buildValidPayload,
22
+ assertStateUnchanged,
23
+ strategy = SignatureMutationStrategy.FOREIGN_SIGNATURE,
24
+ applyInvalidPayload = defaultApplyInvalidPayload,
25
+ expectedLogs
26
+ }) {
27
+ const mutatePayload = createMutationStrategy(strategy);
28
+ super({
29
+ title,
30
+ setupScenario,
31
+ buildValidPayload,
32
+ mutatePayload,
33
+ applyInvalidPayload,
34
+ assertStateUnchanged,
35
+ expectedLogs
36
+ });
37
+ }
38
+ }
39
+
40
+ function createMutationStrategy(strategy) {
41
+ switch (strategy) {
42
+ case SignatureMutationStrategy.ZERO_FILL:
43
+ return zeroFillSignature;
44
+ case SignatureMutationStrategy.TYPE_MISMATCH:
45
+ return typeMismatchSignature;
46
+ case SignatureMutationStrategy.AMOUNT_SIGNATURE:
47
+ return mutateAmountSignature;
48
+ case SignatureMutationStrategy.FOREIGN_SIGNATURE:
49
+ default:
50
+ return foreignSignature;
51
+ }
52
+ }
53
+
54
+ async function foreignSignature(t, validPayload) {
55
+ const decodedPayload = safeDecodeApplyOperation(validPayload);
56
+ t.ok(decodedPayload, 'fixtures decode');
57
+
58
+ const signatureParent = findSignatureParent(decodedPayload);
59
+ if (!signatureParent || !signatureParent.parent?.tx) return validPayload;
60
+
61
+ const { signature } = await createSignature(signatureParent.parent.tx);
62
+ if (signature?.length === signatureParent.parent.is.length) {
63
+ signatureParent.parent.is = signature;
64
+ } else {
65
+ signatureParent.parent.is = b4a.alloc(signatureParent.parent.is.length);
66
+ }
67
+
68
+ return safeEncodeApplyOperation(decodedPayload);
69
+ }
70
+
71
+ async function zeroFillSignature(t, validPayload) {
72
+ const decodedPayload = safeDecodeApplyOperation(validPayload);
73
+ t.ok(decodedPayload, 'fixtures decode');
74
+
75
+ const signatureParent = findSignatureParent(decodedPayload);
76
+ if (!signatureParent) return validPayload;
77
+
78
+ if (!signatureParent.parent?.tx) return validPayload;
79
+ const { signature } = await createSignature(signatureParent.parent.tx);
80
+ if (signature?.length === signatureParent.parent.is.length) {
81
+ signatureParent.parent.is = signature;
82
+ } else {
83
+ signatureParent.parent.is = b4a.alloc(signatureParent.parent.is.length);
84
+ }
85
+ return safeEncodeApplyOperation(decodedPayload);
86
+ }
87
+
88
+ async function typeMismatchSignature(t, validPayload) {
89
+ const decodedPayload = safeDecodeApplyOperation(validPayload);
90
+ t.ok(decodedPayload, 'fixtures decode');
91
+
92
+ const signatureParent = findSignatureParent(decodedPayload);
93
+ if (!signatureParent) return validPayload;
94
+
95
+ if (!signatureParent.parent?.tx) return validPayload;
96
+ const { signature } = await createSignature(signatureParent.parent.tx);
97
+ if (signature?.length === signatureParent.parent.is.length) {
98
+ const mutatedSignature = Buffer.from(signature);
99
+ mutatedSignature[mutatedSignature.length - 1] ^= 0xff;
100
+ signatureParent.parent.is = mutatedSignature;
101
+ } else {
102
+ signatureParent.parent.is = Buffer.from((signatureParent.parent.is.length).toString());
103
+ }
104
+ return safeEncodeApplyOperation(decodedPayload);
105
+ }
106
+
107
+ async function mutateAmountSignature(t, validPayload) {
108
+ const decodedPayload = safeDecodeApplyOperation(validPayload);
109
+ t.ok(decodedPayload, 'fixtures decode');
110
+
111
+ const parent = findSignatureParent(decodedPayload);
112
+ if (!parent?.parent?.am) return validPayload;
113
+
114
+ if (!parent.parent.tx) return validPayload;
115
+ const { signature } = await createSignature(parent.parent.tx);
116
+ if (signature?.length !== parent.parent.is.length) return validPayload;
117
+
118
+ const mutatedAmount = b4a.from(parent.parent.am);
119
+ mutatedAmount[mutatedAmount.length - 1] ^= 0xff;
120
+ parent.parent.am = mutatedAmount;
121
+ parent.parent.is = signature;
122
+
123
+ return safeEncodeApplyOperation(decodedPayload);
124
+ }
125
+
126
+ function findSignatureParent(payload) {
127
+ const signatureParents = ['cao', 'bio', 'aco', 'tro', 'rao', 'bdo', 'txo'];
128
+ for (const key of signatureParents) {
129
+ const parent = payload[key];
130
+ if (parent?.is) {
131
+ return { parent, key };
132
+ }
133
+ }
134
+ return null;
135
+ }
136
+
137
+ async function defaultApplyInvalidPayload(context, invalidPayload) {
138
+ const { bootstrap } = context;
139
+ await bootstrap.base.append(invalidPayload);
140
+ await bootstrap.base.update();
141
+ await eventFlush();
142
+ }