gate-evm-tools 1.0.25 → 1.0.27

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 (352) hide show
  1. package/README.md +33 -11
  2. package/bin/workflow.cjs +19 -0
  3. package/dist/commands/check.d.ts.map +1 -1
  4. package/dist/commands/check.js +21 -57
  5. package/dist/commands/check.js.map +1 -1
  6. package/dist/commands/checkBatch.d.ts +4 -0
  7. package/dist/commands/checkBatch.d.ts.map +1 -0
  8. package/dist/commands/checkBatch.js +57 -0
  9. package/dist/commands/checkBatch.js.map +1 -0
  10. package/dist/commands/checkOptions.d.ts +3 -0
  11. package/dist/commands/checkOptions.d.ts.map +1 -1
  12. package/dist/commands/checkOptions.js +10 -1
  13. package/dist/commands/checkOptions.js.map +1 -1
  14. package/dist/commands/prepare.d.ts +1 -2
  15. package/dist/commands/prepare.d.ts.map +1 -1
  16. package/dist/commands/prepare.js +2 -17
  17. package/dist/commands/prepare.js.map +1 -1
  18. package/dist/commands/sync.d.ts.map +1 -1
  19. package/dist/commands/sync.js +2 -17
  20. package/dist/commands/sync.js.map +1 -1
  21. package/dist/commands/validate.d.ts.map +1 -1
  22. package/dist/commands/validate.js +2 -17
  23. package/dist/commands/validate.js.map +1 -1
  24. package/dist/core/BytecodeChecker.d.ts.map +1 -1
  25. package/dist/core/BytecodeChecker.js +16 -1
  26. package/dist/core/BytecodeChecker.js.map +1 -1
  27. package/dist/core/legacyProxyArtifact.d.ts +6 -0
  28. package/dist/core/legacyProxyArtifact.d.ts.map +1 -0
  29. package/dist/core/legacyProxyArtifact.js +36 -0
  30. package/dist/core/legacyProxyArtifact.js.map +1 -0
  31. package/dist/index.js +3 -3
  32. package/dist/index.js.map +1 -1
  33. package/dist/types.d.ts +2 -2
  34. package/dist/types.d.ts.map +1 -1
  35. package/dist/utils/hardhat.d.ts +4 -0
  36. package/dist/utils/hardhat.d.ts.map +1 -0
  37. package/dist/utils/hardhat.js +9 -0
  38. package/dist/utils/hardhat.js.map +1 -0
  39. package/dist-runtime/config/hardhatAdapters.d.ts +5 -0
  40. package/dist-runtime/config/hardhatAdapters.js +53 -0
  41. package/dist-runtime/config/hardhatAdapters.js.map +1 -0
  42. package/dist-runtime/config/networks.d.ts +8 -0
  43. package/dist-runtime/config/networks.js +269 -0
  44. package/dist-runtime/config/networks.js.map +1 -0
  45. package/dist-runtime/config/openzeppelin.d.ts +28 -0
  46. package/dist-runtime/config/openzeppelin.js +144 -0
  47. package/dist-runtime/config/openzeppelin.js.map +1 -0
  48. package/dist-runtime/config/rpc.d.ts +7 -0
  49. package/dist-runtime/config/rpc.js +19 -0
  50. package/dist-runtime/config/rpc.js.map +1 -0
  51. package/dist-runtime/config/zksyncSolcPath.d.ts +1 -0
  52. package/dist-runtime/config/zksyncSolcPath.js +61 -0
  53. package/dist-runtime/config/zksyncSolcPath.js.map +1 -0
  54. package/dist-runtime/migrate.d.ts +13 -0
  55. package/dist-runtime/migrate.js +208 -0
  56. package/dist-runtime/migrate.js.map +1 -0
  57. package/dist-runtime/package.json +1 -0
  58. package/dist-runtime/projectHardhat.d.ts +4 -0
  59. package/dist-runtime/projectHardhat.js +16 -0
  60. package/dist-runtime/projectHardhat.js.map +1 -0
  61. package/dist-runtime/runtime-identity.json +4 -0
  62. package/dist-runtime/template-migration.json +293 -0
  63. package/dist-runtime/workflow/checkCode.d.ts +1 -0
  64. package/dist-runtime/workflow/checkCode.js +16 -0
  65. package/dist-runtime/workflow/checkCode.js.map +1 -0
  66. package/dist-runtime/workflow/checkCodeFinalize.d.ts +1 -0
  67. package/dist-runtime/workflow/checkCodeFinalize.js +11 -0
  68. package/dist-runtime/workflow/checkCodeFinalize.js.map +1 -0
  69. package/dist-runtime/workflow/checkCodePlan.d.ts +1 -0
  70. package/dist-runtime/workflow/checkCodePlan.js +11 -0
  71. package/dist-runtime/workflow/checkCodePlan.js.map +1 -0
  72. package/dist-runtime/workflow/cli.d.ts +1 -0
  73. package/dist-runtime/workflow/cli.js +302 -0
  74. package/dist-runtime/workflow/cli.js.map +1 -0
  75. package/dist-runtime/workflow/commitContractInfo.d.ts +1 -0
  76. package/dist-runtime/workflow/commitContractInfo.js +64 -0
  77. package/dist-runtime/workflow/commitContractInfo.js.map +1 -0
  78. package/dist-runtime/workflow/create2Hashes.d.ts +1 -0
  79. package/dist-runtime/workflow/create2Hashes.js +76 -0
  80. package/dist-runtime/workflow/create2Hashes.js.map +1 -0
  81. package/dist-runtime/workflow/forkSourceProxy.d.ts +1 -0
  82. package/dist-runtime/workflow/forkSourceProxy.js +151 -0
  83. package/dist-runtime/workflow/forkSourceProxy.js.map +1 -0
  84. package/dist-runtime/workflow/importState.d.ts +1 -0
  85. package/dist-runtime/workflow/importState.js +193 -0
  86. package/dist-runtime/workflow/importState.js.map +1 -0
  87. package/dist-runtime/workflow/lib/authority.d.ts +28 -0
  88. package/dist-runtime/workflow/lib/authority.js +122 -0
  89. package/dist-runtime/workflow/lib/authority.js.map +1 -0
  90. package/dist-runtime/workflow/lib/calldata.d.ts +2 -0
  91. package/dist-runtime/workflow/lib/calldata.js +8 -0
  92. package/dist-runtime/workflow/lib/calldata.js.map +1 -0
  93. package/dist-runtime/workflow/lib/calls.d.ts +23 -0
  94. package/dist-runtime/workflow/lib/calls.js +316 -0
  95. package/dist-runtime/workflow/lib/calls.js.map +1 -0
  96. package/dist-runtime/workflow/lib/checkCode/args.d.ts +2 -0
  97. package/dist-runtime/workflow/lib/checkCode/args.js +68 -0
  98. package/dist-runtime/workflow/lib/checkCode/args.js.map +1 -0
  99. package/dist-runtime/workflow/lib/checkCode/command.d.ts +5 -0
  100. package/dist-runtime/workflow/lib/checkCode/command.js +35 -0
  101. package/dist-runtime/workflow/lib/checkCode/command.js.map +1 -0
  102. package/dist-runtime/workflow/lib/checkCode/dependencies.d.ts +6 -0
  103. package/dist-runtime/workflow/lib/checkCode/dependencies.js +125 -0
  104. package/dist-runtime/workflow/lib/checkCode/dependencies.js.map +1 -0
  105. package/dist-runtime/workflow/lib/checkCode/finalize.d.ts +17 -0
  106. package/dist-runtime/workflow/lib/checkCode/finalize.js +174 -0
  107. package/dist-runtime/workflow/lib/checkCode/finalize.js.map +1 -0
  108. package/dist-runtime/workflow/lib/checkCode/index.d.ts +3 -0
  109. package/dist-runtime/workflow/lib/checkCode/index.js +20 -0
  110. package/dist-runtime/workflow/lib/checkCode/index.js.map +1 -0
  111. package/dist-runtime/workflow/lib/checkCode/plan.d.ts +22 -0
  112. package/dist-runtime/workflow/lib/checkCode/plan.js +145 -0
  113. package/dist-runtime/workflow/lib/checkCode/plan.js.map +1 -0
  114. package/dist-runtime/workflow/lib/checkCodeReport.d.ts +25 -0
  115. package/dist-runtime/workflow/lib/checkCodeReport.js +102 -0
  116. package/dist-runtime/workflow/lib/checkCodeReport.js.map +1 -0
  117. package/dist-runtime/workflow/lib/checkCodeRunner.d.ts +87 -0
  118. package/dist-runtime/workflow/lib/checkCodeRunner.js +964 -0
  119. package/dist-runtime/workflow/lib/checkCodeRunner.js.map +1 -0
  120. package/dist-runtime/workflow/lib/cliTool.d.ts +10 -0
  121. package/dist-runtime/workflow/lib/cliTool.js +25 -0
  122. package/dist-runtime/workflow/lib/cliTool.js.map +1 -0
  123. package/dist-runtime/workflow/lib/config.d.ts +33 -0
  124. package/dist-runtime/workflow/lib/config.js +100 -0
  125. package/dist-runtime/workflow/lib/config.js.map +1 -0
  126. package/dist-runtime/workflow/lib/contractInfoCandidates.d.ts +82 -0
  127. package/dist-runtime/workflow/lib/contractInfoCandidates.js +441 -0
  128. package/dist-runtime/workflow/lib/contractInfoCandidates.js.map +1 -0
  129. package/dist-runtime/workflow/lib/create2.d.ts +49 -0
  130. package/dist-runtime/workflow/lib/create2.js +194 -0
  131. package/dist-runtime/workflow/lib/create2.js.map +1 -0
  132. package/dist-runtime/workflow/lib/create2Hashes.d.ts +22 -0
  133. package/dist-runtime/workflow/lib/create2Hashes.js +57 -0
  134. package/dist-runtime/workflow/lib/create2Hashes.js.map +1 -0
  135. package/dist-runtime/workflow/lib/deploymentInfo.d.ts +40 -0
  136. package/dist-runtime/workflow/lib/deploymentInfo.js +240 -0
  137. package/dist-runtime/workflow/lib/deploymentInfo.js.map +1 -0
  138. package/dist-runtime/workflow/lib/deploymentRecords.d.ts +137 -0
  139. package/dist-runtime/workflow/lib/deploymentRecords.js +374 -0
  140. package/dist-runtime/workflow/lib/deploymentRecords.js.map +1 -0
  141. package/dist-runtime/workflow/lib/deployments.d.ts +21 -0
  142. package/dist-runtime/workflow/lib/deployments.js +240 -0
  143. package/dist-runtime/workflow/lib/deployments.js.map +1 -0
  144. package/dist-runtime/workflow/lib/erc1967.d.ts +5 -0
  145. package/dist-runtime/workflow/lib/erc1967.js +29 -0
  146. package/dist-runtime/workflow/lib/erc1967.js.map +1 -0
  147. package/dist-runtime/workflow/lib/errors.d.ts +6 -0
  148. package/dist-runtime/workflow/lib/errors.js +77 -0
  149. package/dist-runtime/workflow/lib/errors.js.map +1 -0
  150. package/dist-runtime/workflow/lib/executionId.d.ts +7 -0
  151. package/dist-runtime/workflow/lib/executionId.js +26 -0
  152. package/dist-runtime/workflow/lib/executionId.js.map +1 -0
  153. package/dist-runtime/workflow/lib/executionPlan.d.ts +85 -0
  154. package/dist-runtime/workflow/lib/executionPlan.js +450 -0
  155. package/dist-runtime/workflow/lib/executionPlan.js.map +1 -0
  156. package/dist-runtime/workflow/lib/executionProgress.d.ts +5 -0
  157. package/dist-runtime/workflow/lib/executionProgress.js +100 -0
  158. package/dist-runtime/workflow/lib/executionProgress.js.map +1 -0
  159. package/dist-runtime/workflow/lib/external.d.ts +62 -0
  160. package/dist-runtime/workflow/lib/external.js +282 -0
  161. package/dist-runtime/workflow/lib/external.js.map +1 -0
  162. package/dist-runtime/workflow/lib/externalExecutionScanner.d.ts +64 -0
  163. package/dist-runtime/workflow/lib/externalExecutionScanner.js +638 -0
  164. package/dist-runtime/workflow/lib/externalExecutionScanner.js.map +1 -0
  165. package/dist-runtime/workflow/lib/forkSnapshot.d.ts +34 -0
  166. package/dist-runtime/workflow/lib/forkSnapshot.js +167 -0
  167. package/dist-runtime/workflow/lib/forkSnapshot.js.map +1 -0
  168. package/dist-runtime/workflow/lib/gateTool.d.ts +16 -0
  169. package/dist-runtime/workflow/lib/gateTool.js +177 -0
  170. package/dist-runtime/workflow/lib/gateTool.js.map +1 -0
  171. package/dist-runtime/workflow/lib/gateToolSync.d.ts +22 -0
  172. package/dist-runtime/workflow/lib/gateToolSync.js +253 -0
  173. package/dist-runtime/workflow/lib/gateToolSync.js.map +1 -0
  174. package/dist-runtime/workflow/lib/lock.d.ts +52 -0
  175. package/dist-runtime/workflow/lib/lock.js +269 -0
  176. package/dist-runtime/workflow/lib/lock.js.map +1 -0
  177. package/dist-runtime/workflow/lib/migrationState.d.ts +103 -0
  178. package/dist-runtime/workflow/lib/migrationState.js +920 -0
  179. package/dist-runtime/workflow/lib/migrationState.js.map +1 -0
  180. package/dist-runtime/workflow/lib/operatorExecution.d.ts +28 -0
  181. package/dist-runtime/workflow/lib/operatorExecution.js +134 -0
  182. package/dist-runtime/workflow/lib/operatorExecution.js.map +1 -0
  183. package/dist-runtime/workflow/lib/parameters.d.ts +58 -0
  184. package/dist-runtime/workflow/lib/parameters.js +322 -0
  185. package/dist-runtime/workflow/lib/parameters.js.map +1 -0
  186. package/dist-runtime/workflow/lib/pendingDeploymentReuse.d.ts +29 -0
  187. package/dist-runtime/workflow/lib/pendingDeploymentReuse.js +277 -0
  188. package/dist-runtime/workflow/lib/pendingDeploymentReuse.js.map +1 -0
  189. package/dist-runtime/workflow/lib/proxy.d.ts +18 -0
  190. package/dist-runtime/workflow/lib/proxy.js +19 -0
  191. package/dist-runtime/workflow/lib/proxy.js.map +1 -0
  192. package/dist-runtime/workflow/lib/registryCommit.d.ts +33 -0
  193. package/dist-runtime/workflow/lib/registryCommit.js +319 -0
  194. package/dist-runtime/workflow/lib/registryCommit.js.map +1 -0
  195. package/dist-runtime/workflow/lib/release.d.ts +57 -0
  196. package/dist-runtime/workflow/lib/release.js +256 -0
  197. package/dist-runtime/workflow/lib/release.js.map +1 -0
  198. package/dist-runtime/workflow/lib/releaseFinalize.d.ts +14 -0
  199. package/dist-runtime/workflow/lib/releaseFinalize.js +571 -0
  200. package/dist-runtime/workflow/lib/releaseFinalize.js.map +1 -0
  201. package/dist-runtime/workflow/lib/releaseParameters.d.ts +43 -0
  202. package/dist-runtime/workflow/lib/releaseParameters.js +184 -0
  203. package/dist-runtime/workflow/lib/releaseParameters.js.map +1 -0
  204. package/dist-runtime/workflow/lib/reporter.d.ts +39 -0
  205. package/dist-runtime/workflow/lib/reporter.js +452 -0
  206. package/dist-runtime/workflow/lib/reporter.js.map +1 -0
  207. package/dist-runtime/workflow/lib/resultPaths.d.ts +17 -0
  208. package/dist-runtime/workflow/lib/resultPaths.js +29 -0
  209. package/dist-runtime/workflow/lib/resultPaths.js.map +1 -0
  210. package/dist-runtime/workflow/lib/runtimeVersion.d.ts +10 -0
  211. package/dist-runtime/workflow/lib/runtimeVersion.js +46 -0
  212. package/dist-runtime/workflow/lib/runtimeVersion.js.map +1 -0
  213. package/dist-runtime/workflow/lib/signer.d.ts +10 -0
  214. package/dist-runtime/workflow/lib/signer.js +105 -0
  215. package/dist-runtime/workflow/lib/signer.js.map +1 -0
  216. package/dist-runtime/workflow/lib/signerIdentity.d.ts +1 -0
  217. package/dist-runtime/workflow/lib/signerIdentity.js +23 -0
  218. package/dist-runtime/workflow/lib/signerIdentity.js.map +1 -0
  219. package/dist-runtime/workflow/lib/simulation.d.ts +35 -0
  220. package/dist-runtime/workflow/lib/simulation.js +282 -0
  221. package/dist-runtime/workflow/lib/simulation.js.map +1 -0
  222. package/dist-runtime/workflow/lib/simulationCallers.d.ts +44 -0
  223. package/dist-runtime/workflow/lib/simulationCallers.js +260 -0
  224. package/dist-runtime/workflow/lib/simulationCallers.js.map +1 -0
  225. package/dist-runtime/workflow/lib/sourceRpcPolicy.d.ts +1 -0
  226. package/dist-runtime/workflow/lib/sourceRpcPolicy.js +43 -0
  227. package/dist-runtime/workflow/lib/sourceRpcPolicy.js.map +1 -0
  228. package/dist-runtime/workflow/lib/state.d.ts +6 -0
  229. package/dist-runtime/workflow/lib/state.js +25 -0
  230. package/dist-runtime/workflow/lib/state.js.map +1 -0
  231. package/dist-runtime/workflow/lib/staticValidation.d.ts +22 -0
  232. package/dist-runtime/workflow/lib/staticValidation.js +124 -0
  233. package/dist-runtime/workflow/lib/staticValidation.js.map +1 -0
  234. package/dist-runtime/workflow/lib/zksyncForkCapability.d.ts +27 -0
  235. package/dist-runtime/workflow/lib/zksyncForkCapability.js +52 -0
  236. package/dist-runtime/workflow/lib/zksyncForkCapability.js.map +1 -0
  237. package/dist-runtime/workflow/lib/zksyncForkRunner.d.ts +57 -0
  238. package/dist-runtime/workflow/lib/zksyncForkRunner.js +344 -0
  239. package/dist-runtime/workflow/lib/zksyncForkRunner.js.map +1 -0
  240. package/dist-runtime/workflow/reconcileExternal.d.ts +1 -0
  241. package/dist-runtime/workflow/reconcileExternal.js +87 -0
  242. package/dist-runtime/workflow/reconcileExternal.js.map +1 -0
  243. package/dist-runtime/workflow/reconcileExternalRun.d.ts +1 -0
  244. package/dist-runtime/workflow/reconcileExternalRun.js +77 -0
  245. package/dist-runtime/workflow/reconcileExternalRun.js.map +1 -0
  246. package/dist-runtime/workflow/releaseFinalize.d.ts +1 -0
  247. package/dist-runtime/workflow/releaseFinalize.js +11 -0
  248. package/dist-runtime/workflow/releaseFinalize.js.map +1 -0
  249. package/dist-runtime/workflow/run.d.ts +40 -0
  250. package/dist-runtime/workflow/run.js +858 -0
  251. package/dist-runtime/workflow/run.js.map +1 -0
  252. package/dist-runtime/workflow/staticValidate.d.ts +1 -0
  253. package/dist-runtime/workflow/staticValidate.js +26 -0
  254. package/dist-runtime/workflow/staticValidate.js.map +1 -0
  255. package/dist-runtime/workflow/steps/call.d.ts +3 -0
  256. package/dist-runtime/workflow/steps/call.js +9 -0
  257. package/dist-runtime/workflow/steps/call.js.map +1 -0
  258. package/dist-runtime/workflow/steps/check.d.ts +3 -0
  259. package/dist-runtime/workflow/steps/check.js +9 -0
  260. package/dist-runtime/workflow/steps/check.js.map +1 -0
  261. package/dist-runtime/workflow/steps/custom.d.ts +3 -0
  262. package/dist-runtime/workflow/steps/custom.js +33 -0
  263. package/dist-runtime/workflow/steps/custom.js.map +1 -0
  264. package/dist-runtime/workflow/steps/deploy.d.ts +3 -0
  265. package/dist-runtime/workflow/steps/deploy.js +595 -0
  266. package/dist-runtime/workflow/steps/deploy.js.map +1 -0
  267. package/dist-runtime/workflow/steps/upgrade.d.ts +3 -0
  268. package/dist-runtime/workflow/steps/upgrade.js +465 -0
  269. package/dist-runtime/workflow/steps/upgrade.js.map +1 -0
  270. package/dist-runtime/workflow/steps/view.d.ts +3 -0
  271. package/dist-runtime/workflow/steps/view.js +9 -0
  272. package/dist-runtime/workflow/steps/view.js.map +1 -0
  273. package/package.json +26 -5
  274. package/runtime/config/hardhatAdapters.ts +50 -0
  275. package/runtime/config/networks.ts +296 -0
  276. package/runtime/config/openzeppelin.ts +173 -0
  277. package/runtime/config/rpc.ts +27 -0
  278. package/runtime/config/zksyncSolcPath.ts +59 -0
  279. package/runtime/hardhat-types.d.ts +2 -0
  280. package/runtime/migrate.ts +154 -0
  281. package/runtime/projectHardhat.ts +10 -0
  282. package/runtime/template-migration.json +293 -0
  283. package/runtime/workflow/checkCode.ts +13 -0
  284. package/runtime/workflow/checkCodeFinalize.ts +8 -0
  285. package/runtime/workflow/checkCodePlan.ts +8 -0
  286. package/runtime/workflow/cli.ts +356 -0
  287. package/runtime/workflow/commitContractInfo.ts +63 -0
  288. package/runtime/workflow/create2Hashes.ts +79 -0
  289. package/runtime/workflow/forkSourceProxy.ts +193 -0
  290. package/runtime/workflow/importState.ts +190 -0
  291. package/runtime/workflow/lib/authority.ts +170 -0
  292. package/runtime/workflow/lib/calldata.ts +9 -0
  293. package/runtime/workflow/lib/calls.ts +407 -0
  294. package/runtime/workflow/lib/checkCode/args.ts +76 -0
  295. package/runtime/workflow/lib/checkCode/command.ts +36 -0
  296. package/runtime/workflow/lib/checkCode/dependencies.ts +112 -0
  297. package/runtime/workflow/lib/checkCode/finalize.ts +198 -0
  298. package/runtime/workflow/lib/checkCode/index.ts +18 -0
  299. package/runtime/workflow/lib/checkCode/plan.ts +163 -0
  300. package/runtime/workflow/lib/checkCodeReport.ts +133 -0
  301. package/runtime/workflow/lib/checkCodeRunner.ts +1225 -0
  302. package/runtime/workflow/lib/cliTool.ts +31 -0
  303. package/runtime/workflow/lib/config.ts +130 -0
  304. package/runtime/workflow/lib/contractInfoCandidates.ts +690 -0
  305. package/runtime/workflow/lib/create2.ts +278 -0
  306. package/runtime/workflow/lib/create2Hashes.ts +83 -0
  307. package/runtime/workflow/lib/deploymentInfo.ts +286 -0
  308. package/runtime/workflow/lib/deploymentRecords.ts +576 -0
  309. package/runtime/workflow/lib/deployments.ts +276 -0
  310. package/runtime/workflow/lib/erc1967.ts +57 -0
  311. package/runtime/workflow/lib/errors.ts +95 -0
  312. package/runtime/workflow/lib/executionId.ts +35 -0
  313. package/runtime/workflow/lib/executionPlan.ts +550 -0
  314. package/runtime/workflow/lib/executionProgress.ts +127 -0
  315. package/runtime/workflow/lib/external.ts +372 -0
  316. package/runtime/workflow/lib/externalExecutionScanner.ts +892 -0
  317. package/runtime/workflow/lib/forkSnapshot.ts +231 -0
  318. package/runtime/workflow/lib/gateTool.ts +261 -0
  319. package/runtime/workflow/lib/gateToolSync.ts +398 -0
  320. package/runtime/workflow/lib/lock.ts +388 -0
  321. package/runtime/workflow/lib/migrationState.ts +1246 -0
  322. package/runtime/workflow/lib/operatorExecution.ts +174 -0
  323. package/runtime/workflow/lib/parameters.ts +437 -0
  324. package/runtime/workflow/lib/pendingDeploymentReuse.ts +428 -0
  325. package/runtime/workflow/lib/proxy.ts +45 -0
  326. package/runtime/workflow/lib/registryCommit.ts +455 -0
  327. package/runtime/workflow/lib/release.ts +329 -0
  328. package/runtime/workflow/lib/releaseFinalize.ts +711 -0
  329. package/runtime/workflow/lib/releaseParameters.ts +248 -0
  330. package/runtime/workflow/lib/reporter.ts +502 -0
  331. package/runtime/workflow/lib/resultPaths.ts +49 -0
  332. package/runtime/workflow/lib/runtimeVersion.ts +28 -0
  333. package/runtime/workflow/lib/signer.ts +124 -0
  334. package/runtime/workflow/lib/signerIdentity.ts +22 -0
  335. package/runtime/workflow/lib/simulation.ts +415 -0
  336. package/runtime/workflow/lib/simulationCallers.ts +335 -0
  337. package/runtime/workflow/lib/sourceRpcPolicy.ts +41 -0
  338. package/runtime/workflow/lib/state.ts +25 -0
  339. package/runtime/workflow/lib/staticValidation.ts +142 -0
  340. package/runtime/workflow/lib/zksyncForkCapability.ts +80 -0
  341. package/runtime/workflow/lib/zksyncForkRunner.ts +505 -0
  342. package/runtime/workflow/reconcileExternal.ts +86 -0
  343. package/runtime/workflow/reconcileExternalRun.ts +88 -0
  344. package/runtime/workflow/releaseFinalize.ts +8 -0
  345. package/runtime/workflow/run.ts +1072 -0
  346. package/runtime/workflow/staticValidate.ts +23 -0
  347. package/runtime/workflow/steps/call.ts +10 -0
  348. package/runtime/workflow/steps/check.ts +10 -0
  349. package/runtime/workflow/steps/custom.ts +43 -0
  350. package/runtime/workflow/steps/deploy.ts +771 -0
  351. package/runtime/workflow/steps/upgrade.ts +598 -0
  352. package/runtime/workflow/steps/view.ts +10 -0
@@ -0,0 +1,550 @@
1
+ import crypto from "crypto";
2
+ import fs from "fs";
3
+ import path from "path";
4
+
5
+ export type ReleaseKind = "development" | "admin_release";
6
+ export type ExecutionRoute = "operator" | "external";
7
+
8
+ export interface ReleaseExecutionTransaction {
9
+ transactionId: string;
10
+ stepId: string;
11
+ transactionIndex: number;
12
+ route: ExecutionRoute;
13
+ executor: string;
14
+ to: string;
15
+ value: string;
16
+ data: string;
17
+ operation: 0 | 1;
18
+ scheme?: "zksync-eravm";
19
+ factoryDeps?: string[];
20
+ }
21
+
22
+ export interface ReleaseExecutionPlan {
23
+ version: 1;
24
+ taskId: string;
25
+ target: string;
26
+ executionId: string;
27
+ releaseKind: ReleaseKind;
28
+ operator: string;
29
+ transactions: ReleaseExecutionTransaction[];
30
+ planHash: string;
31
+ createdAt: string;
32
+ }
33
+
34
+ type PlanBody = Omit<ReleaseExecutionPlan, "planHash" | "createdAt">;
35
+
36
+ export interface ReleaseExecutionTransactionInput {
37
+ stepId: string;
38
+ executor: string;
39
+ to: string;
40
+ value: string;
41
+ data: string;
42
+ operation: 0 | 1;
43
+ scheme?: "zksync-eravm";
44
+ factoryDeps?: string[];
45
+ }
46
+
47
+ export interface CompletedExecutionTransaction {
48
+ transactionId: string;
49
+ transactionHash: string;
50
+ }
51
+
52
+ export interface PlannedExecutionTransaction extends ReleaseExecutionTransaction {
53
+ executionAction: "execute" | "package" | "replay";
54
+ transactionHash?: string;
55
+ }
56
+
57
+ export class ExecutionSegmentDeferred extends Error {
58
+ constructor(readonly transactionId: string) {
59
+ super(`Execution is waiting for the preceding external segment before ${transactionId}`);
60
+ this.name = "ExecutionSegmentDeferred";
61
+ }
62
+ }
63
+
64
+ const SAFE_ID = /^[A-Za-z0-9][A-Za-z0-9_-]{0,199}$/;
65
+ const ADDRESS = /^0x[0-9a-fA-F]{40}$/;
66
+ const DATA = /^0x(?:[0-9a-fA-F]{2})*$/;
67
+ const HASH = /^[0-9a-f]{64}$/;
68
+
69
+ const safeId = (value: unknown, label: string): string => {
70
+ if (typeof value !== "string" || !SAFE_ID.test(value)) {
71
+ throw new Error(`${label} must match ${SAFE_ID}`);
72
+ }
73
+ return value;
74
+ };
75
+
76
+ const address = (value: unknown, label: string): string => {
77
+ if (typeof value !== "string" || !ADDRESS.test(value)) {
78
+ throw new Error(`${label} must be an EVM address`);
79
+ }
80
+ if (value.toLowerCase() === "0x0000000000000000000000000000000000000000") {
81
+ throw new Error(`${label} must be non-zero`);
82
+ }
83
+ return value.toLowerCase();
84
+ };
85
+
86
+ const value = (raw: unknown, label: string): string => {
87
+ if (typeof raw !== "string" || !/^(?:0[xX][0-9a-fA-F]+|[0-9]+)$/.test(raw)) {
88
+ throw new Error(`${label} must be a nonnegative integer string`);
89
+ }
90
+ return BigInt(raw).toString(10);
91
+ };
92
+
93
+ const data = (raw: unknown, label: string): string => {
94
+ if (typeof raw !== "string" || !DATA.test(raw)) {
95
+ throw new Error(`${label} must be canonical byte calldata`);
96
+ }
97
+ return raw.toLowerCase();
98
+ };
99
+
100
+ const factoryDeps = (raw: unknown, label: string): string[] => {
101
+ if (!Array.isArray(raw)) throw new Error(`${label} must be an array`);
102
+ const seen = new Set<string>();
103
+ const normalized: string[] = [];
104
+ for (const [index, dependency] of raw.entries()) {
105
+ if (typeof dependency !== "string" || !/^0x(?:[0-9a-fA-F]{2})+$/.test(dependency)) {
106
+ throw new Error(`${label}[${index}] must be non-empty byte-aligned bytecode`);
107
+ }
108
+ const value = dependency.toLowerCase();
109
+ const hash = crypto
110
+ .createHash("sha256")
111
+ .update(Buffer.from(value.slice(2), "hex"))
112
+ .digest("hex");
113
+ if (seen.has(hash)) continue;
114
+ seen.add(hash);
115
+ normalized.push(value);
116
+ }
117
+ return normalized;
118
+ };
119
+
120
+ const exactKeys = (value: Record<string, unknown>, expected: string[], label: string): void => {
121
+ const actual = Object.keys(value).sort();
122
+ const wanted = [...expected].sort();
123
+ if (actual.length !== wanted.length || actual.some((key, index) => key !== wanted[index])) {
124
+ throw new Error(`${label} contains unsupported or missing fields`);
125
+ }
126
+ };
127
+
128
+ const record = (raw: unknown, label: string): Record<string, unknown> => {
129
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
130
+ throw new Error(`${label} must be an object`);
131
+ }
132
+ return raw as Record<string, unknown>;
133
+ };
134
+
135
+ const normalizeTransaction = (
136
+ raw: unknown,
137
+ index: number,
138
+ strict: boolean,
139
+ ): ReleaseExecutionTransaction => {
140
+ const input = record(raw, `transactions[${index}]`);
141
+ const isZkSync = input.scheme === "zksync-eravm";
142
+ if (input.scheme !== undefined && !isZkSync) {
143
+ throw new Error(`transactions[${index}].scheme must be zksync-eravm when present`);
144
+ }
145
+ if (isZkSync && input.factoryDeps === undefined) {
146
+ throw new Error(`transactions[${index}].factoryDeps is required for zkSync`);
147
+ }
148
+ if (!isZkSync && input.factoryDeps !== undefined) {
149
+ throw new Error(`transactions[${index}].factoryDeps is only supported for zkSync`);
150
+ }
151
+ if (strict) {
152
+ exactKeys(input, [
153
+ "transactionId",
154
+ "stepId",
155
+ "transactionIndex",
156
+ "route",
157
+ "executor",
158
+ "to",
159
+ "value",
160
+ "data",
161
+ "operation",
162
+ ...(isZkSync ? ["scheme", "factoryDeps"] : []),
163
+ ], `transactions[${index}]`);
164
+ }
165
+ if (input.transactionIndex !== index) {
166
+ throw new Error(`transactions[${index}].transactionIndex must equal ${index}`);
167
+ }
168
+ if (input.route !== "operator" && input.route !== "external") {
169
+ throw new Error(`transactions[${index}].route is invalid`);
170
+ }
171
+ if (input.operation !== 0 && input.operation !== 1) {
172
+ throw new Error(`transactions[${index}].operation must be 0 or 1`);
173
+ }
174
+ return {
175
+ transactionId: safeId(input.transactionId, `transactions[${index}].transactionId`),
176
+ stepId: safeId(input.stepId, `transactions[${index}].stepId`),
177
+ transactionIndex: index,
178
+ route: input.route,
179
+ executor: address(input.executor, `transactions[${index}].executor`),
180
+ to: address(input.to, `transactions[${index}].to`),
181
+ value: value(input.value, `transactions[${index}].value`),
182
+ data: data(input.data, `transactions[${index}].data`),
183
+ operation: input.operation,
184
+ ...(isZkSync ? {
185
+ scheme: "zksync-eravm" as const,
186
+ factoryDeps: factoryDeps(input.factoryDeps, `transactions[${index}].factoryDeps`),
187
+ } : {}),
188
+ };
189
+ };
190
+
191
+ const normalizeBody = (raw: unknown, strict: boolean): PlanBody => {
192
+ const input = record(raw, "execution plan");
193
+ if (strict) {
194
+ exactKeys(input, [
195
+ "version",
196
+ "taskId",
197
+ "target",
198
+ "executionId",
199
+ "releaseKind",
200
+ "operator",
201
+ "transactions",
202
+ ], "execution plan body");
203
+ }
204
+ if (input.version !== 1) throw new Error("execution plan version must be 1");
205
+ if (input.releaseKind !== "development" && input.releaseKind !== "admin_release") {
206
+ throw new Error("execution plan releaseKind is invalid");
207
+ }
208
+ if (!Array.isArray(input.transactions)) {
209
+ throw new Error("execution plan transactions must be an array");
210
+ }
211
+ const operator = address(input.operator, "execution plan operator");
212
+ const transactions = input.transactions.map((transaction, index) => (
213
+ normalizeTransaction(transaction, index, strict)
214
+ ));
215
+ const transactionIds = new Set<string>();
216
+ for (const transaction of transactions) {
217
+ if (transactionIds.has(transaction.transactionId)) {
218
+ throw new Error(`execution plan contains duplicate transactionId ${transaction.transactionId}`);
219
+ }
220
+ transactionIds.add(transaction.transactionId);
221
+ if (transaction.route === "operator" && transaction.executor !== operator) {
222
+ throw new Error(`operator transaction ${transaction.transactionId} must use the plan operator`);
223
+ }
224
+ if (transaction.route === "external" && transaction.executor === operator) {
225
+ throw new Error(`external transaction ${transaction.transactionId} cannot use the plan operator`);
226
+ }
227
+ }
228
+ if (
229
+ input.releaseKind === "development"
230
+ && transactions.some((transaction) => transaction.route === "external")
231
+ ) {
232
+ throw new Error("development execution plans cannot contain external transactions");
233
+ }
234
+ return {
235
+ version: 1,
236
+ taskId: safeId(input.taskId, "execution plan taskId"),
237
+ target: safeId(input.target, "execution plan target"),
238
+ executionId: safeId(input.executionId, "execution plan executionId"),
239
+ releaseKind: input.releaseKind,
240
+ operator,
241
+ transactions,
242
+ };
243
+ };
244
+
245
+ const hashBody = (body: PlanBody): string => {
246
+ return crypto.createHash("sha256").update(JSON.stringify(body)).digest("hex");
247
+ };
248
+
249
+ const confinedPath = (
250
+ root: string,
251
+ taskDir: string,
252
+ target: string,
253
+ executionId: string,
254
+ ): string => {
255
+ const resolvedRoot = path.resolve(root);
256
+ const resolvedTask = path.resolve(taskDir);
257
+ const relativeTask = path.relative(resolvedRoot, resolvedTask);
258
+ if (relativeTask === "" || relativeTask.startsWith("..") || path.isAbsolute(relativeTask)) {
259
+ throw new Error("execution plan task directory must be inside the project root");
260
+ }
261
+ const filePath = path.join(resolvedTask, "results", target, executionId, "execution-plan.json");
262
+ const relativeFile = path.relative(resolvedTask, filePath);
263
+ if (relativeFile.startsWith("..") || path.isAbsolute(relativeFile)) {
264
+ throw new Error("execution plan path escapes the task directory");
265
+ }
266
+ return filePath;
267
+ };
268
+
269
+ const assertNoSymlinks = (root: string, target: string): void => {
270
+ const resolvedRoot = path.resolve(root);
271
+ const resolvedTarget = path.resolve(target);
272
+ const relative = path.relative(resolvedRoot, resolvedTarget);
273
+ if (relative.startsWith("..") || path.isAbsolute(relative)) {
274
+ throw new Error("execution plan path escapes its trusted root");
275
+ }
276
+ let current = resolvedRoot;
277
+ if (fs.existsSync(current) && fs.lstatSync(current).isSymbolicLink()) {
278
+ throw new Error("execution plan path contains a symlink");
279
+ }
280
+ for (const segment of relative.split(path.sep).filter(Boolean)) {
281
+ current = path.join(current, segment);
282
+ if (fs.existsSync(current) && fs.lstatSync(current).isSymbolicLink()) {
283
+ throw new Error("execution plan path contains a symlink");
284
+ }
285
+ }
286
+ };
287
+
288
+ const writeExclusive = (filePath: string, value: unknown): void => {
289
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
290
+ let descriptor: number;
291
+ try {
292
+ descriptor = fs.openSync(filePath, "wx", 0o600);
293
+ } catch (error) {
294
+ throw error;
295
+ }
296
+ try {
297
+ fs.writeFileSync(descriptor, JSON.stringify(value, null, 2) + "\n");
298
+ fs.fsyncSync(descriptor);
299
+ } catch (error) {
300
+ fs.closeSync(descriptor);
301
+ fs.unlinkSync(filePath);
302
+ throw error;
303
+ }
304
+ fs.closeSync(descriptor);
305
+ };
306
+
307
+ export class ReleaseExecutionPlanner {
308
+ private readonly body: Omit<PlanBody, "transactions">;
309
+ private readonly expected?: PlanBody;
310
+ private readonly transactions: ReleaseExecutionTransaction[] = [];
311
+ private readonly segmentedExecution: boolean;
312
+ private readonly completedTransactions: CompletedExecutionTransaction[];
313
+ private readonly segmentEnd: number;
314
+
315
+ constructor(input: {
316
+ taskId: string;
317
+ target: string;
318
+ executionId: string;
319
+ releaseKind: ReleaseKind;
320
+ operator: string;
321
+ expectedPlan?: ReleaseExecutionPlan;
322
+ segmentedExecution?: boolean;
323
+ completedTransactions?: CompletedExecutionTransaction[];
324
+ }) {
325
+ const body = normalizeBody({
326
+ version: 1,
327
+ taskId: input.taskId,
328
+ target: input.target,
329
+ executionId: input.executionId,
330
+ releaseKind: input.releaseKind,
331
+ operator: input.operator,
332
+ transactions: [],
333
+ }, false);
334
+ this.body = {
335
+ version: 1,
336
+ taskId: body.taskId,
337
+ target: body.target,
338
+ executionId: body.executionId,
339
+ releaseKind: body.releaseKind,
340
+ operator: body.operator,
341
+ };
342
+ if (input.expectedPlan) {
343
+ const expected = normalizeBody(input.expectedPlan, false);
344
+ for (const key of ["taskId", "target", "executionId", "releaseKind", "operator"] as const) {
345
+ if (expected[key] !== this.body[key]) {
346
+ throw new Error(`locked execution plan ${key} does not match the runtime`);
347
+ }
348
+ }
349
+ this.expected = expected;
350
+ }
351
+ this.segmentedExecution = input.segmentedExecution === true;
352
+ this.completedTransactions = input.completedTransactions ?? [];
353
+ if (this.segmentedExecution && !this.expected) {
354
+ throw new Error("segmented execution requires a locked execution plan");
355
+ }
356
+ if (!this.segmentedExecution && this.completedTransactions.length > 0) {
357
+ throw new Error("completed transactions require segmented execution");
358
+ }
359
+ if (this.expected) {
360
+ if (this.completedTransactions.length > this.expected.transactions.length) {
361
+ throw new Error("completed transactions exceed the execution plan");
362
+ }
363
+ for (const [index, completed] of this.completedTransactions.entries()) {
364
+ if (
365
+ completed.transactionId !== this.expected.transactions[index]?.transactionId
366
+ || typeof completed.transactionHash !== "string"
367
+ || !/^0x[0-9a-fA-F]{64}$/.test(completed.transactionHash)
368
+ ) {
369
+ throw new Error("completed transactions must form a contiguous plan prefix");
370
+ }
371
+ }
372
+ }
373
+ const expectedTransactions = this.expected?.transactions ?? [];
374
+ let segmentEnd = this.completedTransactions.length;
375
+ if (this.segmentedExecution && segmentEnd < expectedTransactions.length) {
376
+ if (expectedTransactions[segmentEnd].route === "operator") {
377
+ while (
378
+ segmentEnd < expectedTransactions.length
379
+ && expectedTransactions[segmentEnd].route === "operator"
380
+ ) segmentEnd += 1;
381
+ }
382
+ while (
383
+ segmentEnd < expectedTransactions.length
384
+ && expectedTransactions[segmentEnd].route === "external"
385
+ ) segmentEnd += 1;
386
+ } else if (!this.segmentedExecution) {
387
+ segmentEnd = Number.MAX_SAFE_INTEGER;
388
+ }
389
+ this.segmentEnd = segmentEnd;
390
+ }
391
+
392
+ add(input: ReleaseExecutionTransactionInput): PlannedExecutionTransaction {
393
+ const index = this.transactions.length;
394
+ const stepId = safeId(input.stepId, "planned transaction stepId");
395
+ const executor = address(input.executor, "planned transaction executor");
396
+ const transaction = normalizeTransaction({
397
+ transactionId: `tx-${String(index + 1).padStart(4, "0")}-${stepId}`,
398
+ stepId,
399
+ transactionIndex: index,
400
+ route: executor === this.body.operator ? "operator" : "external",
401
+ executor,
402
+ to: input.to,
403
+ value: input.value,
404
+ data: input.data,
405
+ operation: input.operation,
406
+ ...(input.scheme === undefined ? {} : { scheme: input.scheme }),
407
+ ...(input.factoryDeps === undefined ? {} : { factoryDeps: input.factoryDeps }),
408
+ }, index, false);
409
+ if (this.body.releaseKind === "development" && transaction.route === "external") {
410
+ throw new Error("development execution plans cannot contain external transactions");
411
+ }
412
+ const expected = this.expected?.transactions[index];
413
+ if (this.expected && (!expected || JSON.stringify(expected) !== JSON.stringify(transaction))) {
414
+ throw new Error(
415
+ `transaction ${transaction.transactionId} does not match locked execution plan`,
416
+ );
417
+ }
418
+ if (this.segmentedExecution && index >= this.segmentEnd) {
419
+ throw new ExecutionSegmentDeferred(transaction.transactionId);
420
+ }
421
+ this.transactions.push(transaction);
422
+ const completed = this.completedTransactions[index];
423
+ if (completed) {
424
+ return {
425
+ ...transaction,
426
+ executionAction: "replay",
427
+ transactionHash: completed.transactionHash.toLowerCase(),
428
+ };
429
+ }
430
+ return {
431
+ ...transaction,
432
+ executionAction: transaction.route === "external" ? "package" : "execute",
433
+ };
434
+ }
435
+
436
+ complete(options: { allowPartial?: boolean } = {}): PlanBody {
437
+ if (
438
+ this.expected
439
+ && this.transactions.length !== this.expected.transactions.length
440
+ && options.allowPartial !== true
441
+ ) {
442
+ throw new Error("execution did not consume every locked transaction");
443
+ }
444
+ if (options.allowPartial === true && !this.segmentedExecution) {
445
+ throw new Error("partial execution plan completion requires segmented execution");
446
+ }
447
+ return normalizeBody({
448
+ ...this.body,
449
+ transactions: this.transactions,
450
+ }, false);
451
+ }
452
+ }
453
+
454
+ export const writeReleaseExecutionPlan = (input: {
455
+ root: string;
456
+ taskDir: string;
457
+ plan: PlanBody;
458
+ }): ReleaseExecutionPlan => {
459
+ const body = normalizeBody(input.plan, false);
460
+ const filePath = confinedPath(input.root, input.taskDir, body.target, body.executionId);
461
+ assertNoSymlinks(input.root, filePath);
462
+ const plan: ReleaseExecutionPlan = {
463
+ ...body,
464
+ planHash: hashBody(body),
465
+ createdAt: new Date().toISOString(),
466
+ };
467
+ if (fs.existsSync(filePath)) {
468
+ const existing = loadReleaseExecutionPlan({
469
+ root: input.root,
470
+ taskDir: input.taskDir,
471
+ target: body.target,
472
+ executionId: body.executionId,
473
+ });
474
+ if (existing.planHash === plan.planHash) return existing;
475
+ throw new Error("execution plan already exists with different content");
476
+ }
477
+ writeExclusive(filePath, plan);
478
+ return plan;
479
+ };
480
+
481
+ export const loadReleaseExecutionPlan = (input: {
482
+ root: string;
483
+ taskDir: string;
484
+ target: string;
485
+ executionId: string;
486
+ expectedHash?: string;
487
+ }): ReleaseExecutionPlan => {
488
+ const target = safeId(input.target, "execution plan target");
489
+ const executionId = safeId(input.executionId, "execution plan executionId");
490
+ const filePath = confinedPath(input.root, input.taskDir, target, executionId);
491
+ assertNoSymlinks(input.root, filePath);
492
+ let parsed: unknown;
493
+ try {
494
+ parsed = JSON.parse(fs.readFileSync(filePath, "utf8"));
495
+ } catch (error) {
496
+ throw new Error(
497
+ `Cannot load execution plan: ${error instanceof Error ? error.message : String(error)}`,
498
+ );
499
+ }
500
+ const inputPlan = record(parsed, "execution plan");
501
+ exactKeys(inputPlan, [
502
+ "version",
503
+ "taskId",
504
+ "target",
505
+ "executionId",
506
+ "releaseKind",
507
+ "operator",
508
+ "transactions",
509
+ "planHash",
510
+ "createdAt",
511
+ ], "execution plan");
512
+ const body = normalizeBody({
513
+ version: inputPlan.version,
514
+ taskId: inputPlan.taskId,
515
+ target: inputPlan.target,
516
+ executionId: inputPlan.executionId,
517
+ releaseKind: inputPlan.releaseKind,
518
+ operator: inputPlan.operator,
519
+ transactions: inputPlan.transactions,
520
+ }, true);
521
+ if (body.target !== target || body.executionId !== executionId) {
522
+ throw new Error("execution plan path identity does not match its contents");
523
+ }
524
+ if (typeof inputPlan.createdAt !== "string" || !Number.isFinite(Date.parse(inputPlan.createdAt))) {
525
+ throw new Error("execution plan createdAt must be an ISO timestamp");
526
+ }
527
+ const calculatedHash = hashBody(body);
528
+ if (typeof inputPlan.planHash !== "string" || !HASH.test(inputPlan.planHash)) {
529
+ throw new Error("execution plan planHash is invalid");
530
+ }
531
+ if (inputPlan.planHash !== calculatedHash) {
532
+ throw new Error("execution plan hash does not match its contents");
533
+ }
534
+ if (input.expectedHash !== undefined && input.expectedHash !== calculatedHash) {
535
+ throw new Error("execution plan hash does not match the parameter lock");
536
+ }
537
+ return {
538
+ ...body,
539
+ planHash: calculatedHash,
540
+ createdAt: inputPlan.createdAt,
541
+ };
542
+ };
543
+
544
+ export const releaseExecutionPlanRelativePath = (
545
+ taskDir: string,
546
+ plan: Pick<ReleaseExecutionPlan, "target" | "executionId">,
547
+ ): string => path.relative(
548
+ taskDir,
549
+ path.join(taskDir, "results", plan.target, plan.executionId, "execution-plan.json"),
550
+ ).split(path.sep).join("/");
@@ -0,0 +1,127 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import type {
4
+ CompletedExecutionTransaction,
5
+ ReleaseExecutionPlan,
6
+ } from "./executionPlan";
7
+ import { loadOperatorExecutionResult } from "./operatorExecution";
8
+
9
+ const TRANSACTION_HASH = /^0x[0-9a-fA-F]{64}$/;
10
+
11
+ const reconciliationPath = (
12
+ taskDir: string,
13
+ plan: ReleaseExecutionPlan,
14
+ ): string => path.join(
15
+ taskDir,
16
+ "results",
17
+ plan.target,
18
+ plan.executionId,
19
+ "external-reconciliation.json",
20
+ );
21
+
22
+ const readReconciliationMatches = (
23
+ taskDir: string,
24
+ plan: ReleaseExecutionPlan,
25
+ ): Array<Record<string, unknown>> => {
26
+ const filePath = reconciliationPath(taskDir, plan);
27
+ if (!fs.existsSync(filePath)) return [];
28
+ let parsed: unknown;
29
+ try {
30
+ parsed = JSON.parse(fs.readFileSync(filePath, "utf8"));
31
+ } catch (error) {
32
+ throw new Error(
33
+ `external reconciliation report is invalid: ${error instanceof Error ? error.message : String(error)}`,
34
+ );
35
+ }
36
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
37
+ throw new Error("external reconciliation report must be an object");
38
+ }
39
+ const report = parsed as Record<string, unknown>;
40
+ if (
41
+ report.version !== 1
42
+ || report.taskId !== plan.taskId
43
+ || report.target !== plan.target
44
+ || report.executionId !== plan.executionId
45
+ || report.executionPlanHash !== plan.planHash
46
+ || !Array.isArray(report.matches)
47
+ ) {
48
+ throw new Error("external reconciliation report does not match the execution plan");
49
+ }
50
+ if (report.status === "failed") {
51
+ throw new Error("failed external reconciliation cannot be resumed");
52
+ }
53
+ return report.matches as Array<Record<string, unknown>>;
54
+ };
55
+
56
+ export const loadCompletedExecutionPrefix = (input: {
57
+ taskDir: string;
58
+ plan: ReleaseExecutionPlan;
59
+ }): CompletedExecutionTransaction[] => {
60
+ const operatorPath = path.join(
61
+ input.taskDir,
62
+ "results",
63
+ input.plan.target,
64
+ input.plan.executionId,
65
+ "operator-execution.json",
66
+ );
67
+ const operatorResult = fs.existsSync(operatorPath)
68
+ ? loadOperatorExecutionResult({ taskDir: input.taskDir, plan: input.plan })
69
+ : undefined;
70
+ const evidence = new Map<string, CompletedExecutionTransaction>();
71
+ for (const receipt of operatorResult?.receipts ?? []) {
72
+ evidence.set(receipt.transactionId, receipt);
73
+ }
74
+
75
+ const seenMatches = new Set<string>();
76
+ for (const match of readReconciliationMatches(input.taskDir, input.plan)) {
77
+ const transactionIndex = match.transactionIndex;
78
+ const expected = Number.isSafeInteger(transactionIndex)
79
+ ? input.plan.transactions[transactionIndex as number]
80
+ : undefined;
81
+ if (
82
+ !expected
83
+ || match.transactionId !== expected.transactionId
84
+ || match.route !== expected.route
85
+ || String(match.executor).toLowerCase() !== expected.executor
86
+ || typeof match.transactionHash !== "string"
87
+ || !TRANSACTION_HASH.test(match.transactionHash)
88
+ || (match.receiptStatus !== 0 && match.receiptStatus !== 1)
89
+ || typeof match.finalized !== "boolean"
90
+ || seenMatches.has(expected.transactionId)
91
+ ) {
92
+ throw new Error("external reconciliation matches do not bind the execution plan");
93
+ }
94
+ seenMatches.add(expected.transactionId);
95
+ if (match.receiptStatus === 0) {
96
+ throw new Error(`reverted transaction ${expected.transactionId} cannot be resumed`);
97
+ }
98
+ if (expected.route === "operator") {
99
+ const receipt = evidence.get(expected.transactionId);
100
+ if (receipt && receipt.transactionHash !== match.transactionHash.toLowerCase()) {
101
+ throw new Error(`operator reconciliation hash differs for ${expected.transactionId}`);
102
+ }
103
+ continue;
104
+ }
105
+ if (match.finalized) {
106
+ evidence.set(expected.transactionId, {
107
+ transactionId: expected.transactionId,
108
+ transactionHash: match.transactionHash.toLowerCase(),
109
+ });
110
+ }
111
+ }
112
+
113
+ const completed: CompletedExecutionTransaction[] = [];
114
+ let prefixEnded = false;
115
+ for (const transaction of input.plan.transactions) {
116
+ const item = evidence.get(transaction.transactionId);
117
+ if (!item) {
118
+ prefixEnded = true;
119
+ continue;
120
+ }
121
+ if (prefixEnded) {
122
+ throw new Error("execution evidence must form a contiguous plan prefix");
123
+ }
124
+ completed.push(item);
125
+ }
126
+ return completed;
127
+ };