gate-evm-tools 1.0.31 → 1.2.1

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 (349) hide show
  1. package/README.md +34 -20
  2. package/bin/cli.js +3 -0
  3. package/bin/delivery.cjs +8 -7
  4. package/dist/commands/check.d.ts.map +1 -1
  5. package/dist/commands/check.js +26 -2
  6. package/dist/commands/check.js.map +1 -1
  7. package/dist/commands/plan/index.d.ts.map +1 -1
  8. package/dist/commands/plan/index.js +1 -1
  9. package/dist/commands/plan/index.js.map +1 -1
  10. package/dist/core/preparation/batch.d.ts +26 -0
  11. package/dist/core/preparation/batch.d.ts.map +1 -0
  12. package/dist/core/preparation/batch.js +72 -0
  13. package/dist/core/preparation/batch.js.map +1 -0
  14. package/dist/core/preparation/evm.d.ts +23 -4
  15. package/dist/core/preparation/evm.d.ts.map +1 -1
  16. package/dist/core/preparation/evm.js +19 -3
  17. package/dist/core/preparation/evm.js.map +1 -1
  18. package/dist/core/preparation/evmManifestSync.d.ts +5 -0
  19. package/dist/core/preparation/evmManifestSync.d.ts.map +1 -1
  20. package/dist/core/preparation/evmManifestSync.js +15 -7
  21. package/dist/core/preparation/evmManifestSync.js.map +1 -1
  22. package/dist/core/preparation/index.d.ts +2 -2
  23. package/dist/core/preparation/index.d.ts.map +1 -1
  24. package/dist/core/preparation/manifest.d.ts +2 -0
  25. package/dist/core/preparation/manifest.d.ts.map +1 -1
  26. package/dist/core/preparation/manifest.js +2 -2
  27. package/dist/core/preparation/manifest.js.map +1 -1
  28. package/dist/core/preparation/normalize.d.ts.map +1 -1
  29. package/dist/core/preparation/normalize.js +53 -11
  30. package/dist/core/preparation/normalize.js.map +1 -1
  31. package/dist/core/preparation/transparent.d.ts +23 -0
  32. package/dist/core/preparation/transparent.d.ts.map +1 -0
  33. package/dist/core/preparation/transparent.js +103 -0
  34. package/dist/core/preparation/transparent.js.map +1 -0
  35. package/dist/core/preparation/types.d.ts +47 -5
  36. package/dist/core/preparation/types.d.ts.map +1 -1
  37. package/dist/core/preparation/zksync.d.ts.map +1 -1
  38. package/dist/core/preparation/zksync.js +2 -0
  39. package/dist/core/preparation/zksync.js.map +1 -1
  40. package/dist/custody/credential.d.ts.map +1 -1
  41. package/dist/custody/credential.js +1 -6
  42. package/dist/custody/credential.js.map +1 -1
  43. package/dist/deployment-evm/index.d.ts +4 -0
  44. package/dist/deployment-evm/index.d.ts.map +1 -0
  45. package/dist/deployment-evm/index.js +3 -0
  46. package/dist/deployment-evm/index.js.map +1 -0
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +4 -0
  49. package/dist/index.js.map +1 -1
  50. package/dist/sync/index.d.ts.map +1 -1
  51. package/dist/sync/index.js +5 -0
  52. package/dist/sync/index.js.map +1 -1
  53. package/dist/types.d.ts +3 -0
  54. package/dist/types.d.ts.map +1 -1
  55. package/dist/workflow/index.d.ts +4 -1
  56. package/dist/workflow/index.d.ts.map +1 -1
  57. package/dist/workflow/index.js +2 -0
  58. package/dist/workflow/index.js.map +1 -1
  59. package/dist-cjs/core/preparation/batch.js +76 -0
  60. package/dist-cjs/core/preparation/batch.js.map +1 -0
  61. package/dist-cjs/core/preparation/evm.js +25 -7
  62. package/dist-cjs/core/preparation/evm.js.map +1 -1
  63. package/dist-cjs/core/preparation/evmManifestSync.js +15 -7
  64. package/dist-cjs/core/preparation/evmManifestSync.js.map +1 -1
  65. package/dist-cjs/core/preparation/manifest.js +2 -2
  66. package/dist-cjs/core/preparation/manifest.js.map +1 -1
  67. package/dist-cjs/core/preparation/normalize.js +53 -11
  68. package/dist-cjs/core/preparation/normalize.js.map +1 -1
  69. package/dist-cjs/core/preparation/transparent.js +110 -0
  70. package/dist-cjs/core/preparation/transparent.js.map +1 -0
  71. package/dist-cjs/core/preparation/zksync.js +2 -0
  72. package/dist-cjs/core/preparation/zksync.js.map +1 -1
  73. package/dist-cjs/custody/credential.js +1 -6
  74. package/dist-cjs/custody/credential.js.map +1 -1
  75. package/dist-cjs/deployment-evm/index.js +10 -0
  76. package/dist-cjs/deployment-evm/index.js.map +1 -0
  77. package/dist-cjs/sync/index.js +5 -0
  78. package/dist-cjs/sync/index.js.map +1 -1
  79. package/dist-cjs/workflow/index.js +11 -1
  80. package/dist-cjs/workflow/index.js.map +1 -1
  81. package/dist-runtime/config/hardhatAdapters.js +2 -1
  82. package/dist-runtime/config/hardhatAdapters.js.map +1 -1
  83. package/dist-runtime/delivery/aggregate-bootstrap.js +3 -1
  84. package/dist-runtime/delivery/aggregate-bootstrap.js.map +1 -1
  85. package/dist-runtime/delivery/aggregate-channel.js +7 -3
  86. package/dist-runtime/delivery/aggregate-channel.js.map +1 -1
  87. package/dist-runtime/delivery/aggregate-diagnostics.d.ts +14 -0
  88. package/dist-runtime/delivery/aggregate-diagnostics.js +73 -0
  89. package/dist-runtime/delivery/aggregate-diagnostics.js.map +1 -0
  90. package/dist-runtime/delivery/aggregate-inputs.d.ts +13 -9
  91. package/dist-runtime/delivery/aggregate-source.js +11 -3
  92. package/dist-runtime/delivery/aggregate-source.js.map +1 -1
  93. package/dist-runtime/delivery/aggregate-worker.js +12 -4
  94. package/dist-runtime/delivery/aggregate-worker.js.map +1 -1
  95. package/dist-runtime/delivery/aggregate.js +2 -2
  96. package/dist-runtime/delivery/aggregate.js.map +1 -1
  97. package/dist-runtime/delivery/business-extension.d.ts +10 -0
  98. package/dist-runtime/delivery/business-extension.js +38 -0
  99. package/dist-runtime/delivery/business-extension.js.map +1 -0
  100. package/dist-runtime/delivery/calldata-archive.d.ts +18 -0
  101. package/dist-runtime/delivery/calldata-archive.js +31 -0
  102. package/dist-runtime/delivery/calldata-archive.js.map +1 -0
  103. package/dist-runtime/delivery/calldata-details.d.ts +47 -0
  104. package/dist-runtime/delivery/calldata-details.js +94 -0
  105. package/dist-runtime/delivery/calldata-details.js.map +1 -0
  106. package/dist-runtime/delivery/calldata-format.d.ts +4 -0
  107. package/dist-runtime/delivery/calldata-format.js +17 -0
  108. package/dist-runtime/delivery/calldata-format.js.map +1 -0
  109. package/dist-runtime/delivery/calldata-preparations.d.ts +13 -0
  110. package/dist-runtime/delivery/calldata-preparations.js +85 -0
  111. package/dist-runtime/delivery/calldata-preparations.js.map +1 -0
  112. package/dist-runtime/delivery/calldata-review.d.ts +44 -0
  113. package/dist-runtime/delivery/calldata-review.js +131 -0
  114. package/dist-runtime/delivery/calldata-review.js.map +1 -0
  115. package/dist-runtime/delivery/codec-pin.d.ts +2 -2
  116. package/dist-runtime/delivery/codec-pin.js +4 -4
  117. package/dist-runtime/delivery/codec-pin.js.map +1 -1
  118. package/dist-runtime/delivery/compiler-files.js +3 -1
  119. package/dist-runtime/delivery/compiler-files.js.map +1 -1
  120. package/dist-runtime/delivery/compiler-pins.js +1 -1
  121. package/dist-runtime/delivery/compiler.js +17 -16
  122. package/dist-runtime/delivery/compiler.js.map +1 -1
  123. package/dist-runtime/delivery/config.d.ts +1 -1
  124. package/dist-runtime/delivery/config.js +27 -2
  125. package/dist-runtime/delivery/config.js.map +1 -1
  126. package/dist-runtime/delivery/configuration-definition.d.ts +9 -0
  127. package/dist-runtime/delivery/configuration-definition.js +33 -6
  128. package/dist-runtime/delivery/configuration-definition.js.map +1 -1
  129. package/dist-runtime/delivery/configuration.js +7 -4
  130. package/dist-runtime/delivery/configuration.js.map +1 -1
  131. package/dist-runtime/delivery/contract-source.d.ts +14 -0
  132. package/dist-runtime/delivery/contract-source.js +138 -0
  133. package/dist-runtime/delivery/contract-source.js.map +1 -0
  134. package/dist-runtime/delivery/custom-format.js +51 -24
  135. package/dist-runtime/delivery/custom-format.js.map +1 -1
  136. package/dist-runtime/delivery/development-inputs.d.ts +14 -0
  137. package/dist-runtime/delivery/development-inputs.js +76 -0
  138. package/dist-runtime/delivery/development-inputs.js.map +1 -0
  139. package/dist-runtime/delivery/development.d.ts +3 -1
  140. package/dist-runtime/delivery/development.js +24 -10
  141. package/dist-runtime/delivery/development.js.map +1 -1
  142. package/dist-runtime/delivery/eoa.d.ts +1 -0
  143. package/dist-runtime/delivery/execution-identity.d.ts +15 -0
  144. package/dist-runtime/delivery/execution-identity.js +33 -0
  145. package/dist-runtime/delivery/execution-identity.js.map +1 -0
  146. package/dist-runtime/delivery/existing-code.js +14 -6
  147. package/dist-runtime/delivery/existing-code.js.map +1 -1
  148. package/dist-runtime/delivery/history-package.d.ts +2 -0
  149. package/dist-runtime/delivery/history-package.js +70 -0
  150. package/dist-runtime/delivery/history-package.js.map +1 -0
  151. package/dist-runtime/delivery/history-registration.d.ts +1 -1
  152. package/dist-runtime/delivery/inputs.js +22 -15
  153. package/dist-runtime/delivery/inputs.js.map +1 -1
  154. package/dist-runtime/delivery/journal.js +18 -10
  155. package/dist-runtime/delivery/journal.js.map +1 -1
  156. package/dist-runtime/delivery/parameter-defaults.d.ts +10 -0
  157. package/dist-runtime/delivery/parameter-defaults.js +86 -0
  158. package/dist-runtime/delivery/parameter-defaults.js.map +1 -0
  159. package/dist-runtime/delivery/parameters.d.ts +2 -0
  160. package/dist-runtime/delivery/parameters.js +22 -0
  161. package/dist-runtime/delivery/parameters.js.map +1 -1
  162. package/dist-runtime/delivery/planning.d.ts +4 -1
  163. package/dist-runtime/delivery/planning.js +19 -3
  164. package/dist-runtime/delivery/planning.js.map +1 -1
  165. package/dist-runtime/delivery/preparation.js +43 -23
  166. package/dist-runtime/delivery/preparation.js.map +1 -1
  167. package/dist-runtime/delivery/production-environment.js +2 -1
  168. package/dist-runtime/delivery/production-environment.js.map +1 -1
  169. package/dist-runtime/delivery/production-finalization.js +23 -9
  170. package/dist-runtime/delivery/production-finalization.js.map +1 -1
  171. package/dist-runtime/delivery/production-intent.d.ts +2 -0
  172. package/dist-runtime/delivery/production-intent.js +16 -0
  173. package/dist-runtime/delivery/production-intent.js.map +1 -0
  174. package/dist-runtime/delivery/production.d.ts +129 -8
  175. package/dist-runtime/delivery/production.js +60 -11
  176. package/dist-runtime/delivery/production.js.map +1 -1
  177. package/dist-runtime/delivery/project-files.d.ts +3 -3
  178. package/dist-runtime/delivery/project-files.js +19 -14
  179. package/dist-runtime/delivery/project-files.js.map +1 -1
  180. package/dist-runtime/delivery/project-rpc.d.ts +19 -0
  181. package/dist-runtime/delivery/project-rpc.js +138 -0
  182. package/dist-runtime/delivery/project-rpc.js.map +1 -0
  183. package/dist-runtime/delivery/project.d.ts +3 -1
  184. package/dist-runtime/delivery/project.js +21 -8
  185. package/dist-runtime/delivery/project.js.map +1 -1
  186. package/dist-runtime/delivery/public-calldata.d.ts +25 -0
  187. package/dist-runtime/delivery/public-calldata.js +97 -0
  188. package/dist-runtime/delivery/public-calldata.js.map +1 -0
  189. package/dist-runtime/delivery/release-graph.d.ts +7 -3
  190. package/dist-runtime/delivery/release-graph.js +58 -25
  191. package/dist-runtime/delivery/release-graph.js.map +1 -1
  192. package/dist-runtime/delivery/release-history-capture.js +22 -26
  193. package/dist-runtime/delivery/release-history-capture.js.map +1 -1
  194. package/dist-runtime/delivery/release-history.d.ts +3 -2
  195. package/dist-runtime/delivery/release-history.js +97 -50
  196. package/dist-runtime/delivery/release-history.js.map +1 -1
  197. package/dist-runtime/delivery/release-inputs.d.ts +33 -0
  198. package/dist-runtime/delivery/release-inputs.js +129 -0
  199. package/dist-runtime/delivery/release-inputs.js.map +1 -0
  200. package/dist-runtime/delivery/release.d.ts +38 -14
  201. package/dist-runtime/delivery/release.js +81 -29
  202. package/dist-runtime/delivery/release.js.map +1 -1
  203. package/dist-runtime/delivery/safe.d.ts +1 -0
  204. package/dist-runtime/delivery/safe.js +13 -2
  205. package/dist-runtime/delivery/safe.js.map +1 -1
  206. package/dist-runtime/delivery/same-fork-baseline.d.ts +1 -1
  207. package/dist-runtime/delivery/same-fork-baseline.js +5 -4
  208. package/dist-runtime/delivery/same-fork-baseline.js.map +1 -1
  209. package/dist-runtime/delivery/setup.d.ts +1 -1
  210. package/dist-runtime/delivery/setup.js +21 -6
  211. package/dist-runtime/delivery/setup.js.map +1 -1
  212. package/dist-runtime/delivery/source.d.ts +1 -0
  213. package/dist-runtime/delivery/source.js +12 -10
  214. package/dist-runtime/delivery/source.js.map +1 -1
  215. package/dist-runtime/delivery/task-identity.d.ts +23 -0
  216. package/dist-runtime/delivery/task-identity.js +109 -0
  217. package/dist-runtime/delivery/task-identity.js.map +1 -0
  218. package/dist-runtime/delivery/toolchain.d.ts +3 -0
  219. package/dist-runtime/delivery/toolchain.js +52 -0
  220. package/dist-runtime/delivery/toolchain.js.map +1 -0
  221. package/dist-runtime/delivery/validation.js +7 -2
  222. package/dist-runtime/delivery/validation.js.map +1 -1
  223. package/dist-runtime/runtime-identity.json +2 -2
  224. package/dist-runtime/vendor/plan-codec/index.cjs +97 -20
  225. package/dist-runtime/vendor/plan-codec/index.d.cts +6 -0
  226. package/dist-runtime/vendor/plan-codec/provenance.json +9 -8
  227. package/dist-runtime/workflow/lib/calls.js +1 -0
  228. package/dist-runtime/workflow/lib/calls.js.map +1 -1
  229. package/dist-runtime/workflow/lib/checkCodeRunner.js +7 -4
  230. package/dist-runtime/workflow/lib/checkCodeRunner.js.map +1 -1
  231. package/dist-runtime/workflow/lib/context.d.ts +1 -0
  232. package/dist-runtime/workflow/lib/create2.d.ts +4 -26
  233. package/dist-runtime/workflow/lib/create2.js +2 -67
  234. package/dist-runtime/workflow/lib/create2.js.map +1 -1
  235. package/dist-runtime/workflow/lib/deploymentInfo.d.ts +2 -0
  236. package/dist-runtime/workflow/lib/deploymentInfo.js +6 -0
  237. package/dist-runtime/workflow/lib/deploymentInfo.js.map +1 -1
  238. package/dist-runtime/workflow/lib/deploymentRecords.d.ts +2 -0
  239. package/dist-runtime/workflow/lib/deploymentRecords.js +1 -1
  240. package/dist-runtime/workflow/lib/deploymentRecords.js.map +1 -1
  241. package/dist-runtime/workflow/lib/externalExecutionScanner.js +2 -1
  242. package/dist-runtime/workflow/lib/externalExecutionScanner.js.map +1 -1
  243. package/dist-runtime/workflow/lib/gateTool.js +2 -2
  244. package/dist-runtime/workflow/lib/gateTool.js.map +1 -1
  245. package/dist-runtime/workflow/lib/gateToolSync.d.ts +3 -0
  246. package/dist-runtime/workflow/lib/gateToolSync.js +5 -0
  247. package/dist-runtime/workflow/lib/gateToolSync.js.map +1 -1
  248. package/dist-runtime/workflow/lib/parameters.js +5 -0
  249. package/dist-runtime/workflow/lib/parameters.js.map +1 -1
  250. package/dist-runtime/workflow/lib/proxy.d.ts +1 -0
  251. package/dist-runtime/workflow/lib/proxy.js.map +1 -1
  252. package/dist-runtime/workflow/run.js +1 -3
  253. package/dist-runtime/workflow/run.js.map +1 -1
  254. package/dist-runtime/workflow/steps/deploy.js +53 -0
  255. package/dist-runtime/workflow/steps/deploy.js.map +1 -1
  256. package/dist-runtime/workflow/steps/upgrade.js +24 -10
  257. package/dist-runtime/workflow/steps/upgrade.js.map +1 -1
  258. package/docs/compiler-qualification.md +8 -2
  259. package/docs/delivery-aggregate.md +2 -0
  260. package/docs/delivery-calldata.md +27 -0
  261. package/docs/delivery-development.md +6 -0
  262. package/docs/delivery-execution-store.md +1 -1
  263. package/docs/delivery-inputs.md +55 -6
  264. package/docs/delivery-parameters.md +1 -1
  265. package/docs/delivery-release.md +77 -7
  266. package/docs/delivery-safe.md +7 -4
  267. package/docs/delivery-setup.md +72 -20
  268. package/docs/delivery-source.md +8 -8
  269. package/docs/direct-package-acceptance.md +2 -0
  270. package/docs/openzeppelin-acceptance.md +86 -0
  271. package/docs/openzeppelin-baseline.json +27 -0
  272. package/docs/openzeppelin-integration.md +115 -0
  273. package/docs/plans/2026-10-28-openzeppelin-toolkit-consolidation.md +396 -0
  274. package/docs/plans/2026-11-02-transparent-proxy-delivery.md +78 -0
  275. package/docs/superpowers/plans/2026-08-17-custody-hardhat-signers.md +1 -1
  276. package/docs/workflow-reference.md +12 -4
  277. package/docs/workflow-runtime.md +6 -0
  278. package/package.json +19 -5
  279. package/runtime/config/hardhatAdapters.ts +2 -1
  280. package/runtime/delivery/aggregate-bootstrap.ts +3 -1
  281. package/runtime/delivery/aggregate-channel.ts +6 -3
  282. package/runtime/delivery/aggregate-diagnostics.ts +63 -0
  283. package/runtime/delivery/aggregate-source.ts +6 -2
  284. package/runtime/delivery/aggregate-worker.ts +15 -5
  285. package/runtime/delivery/aggregate.ts +2 -2
  286. package/runtime/delivery/business-extension.ts +33 -0
  287. package/runtime/delivery/calldata-archive.ts +25 -0
  288. package/runtime/delivery/calldata-details.ts +90 -0
  289. package/runtime/delivery/calldata-format.ts +14 -0
  290. package/runtime/delivery/calldata-preparations.ts +76 -0
  291. package/runtime/delivery/calldata-review.ts +126 -0
  292. package/runtime/delivery/codec-pin.ts +3 -3
  293. package/runtime/delivery/compiler-files.ts +3 -1
  294. package/runtime/delivery/compiler-pins.ts +1 -1
  295. package/runtime/delivery/compiler.ts +18 -17
  296. package/runtime/delivery/config.ts +25 -2
  297. package/runtime/delivery/configuration-definition.ts +34 -7
  298. package/runtime/delivery/configuration.ts +8 -5
  299. package/runtime/delivery/contract-source.ts +112 -0
  300. package/runtime/delivery/custom-format.ts +20 -5
  301. package/runtime/delivery/development-inputs.ts +42 -0
  302. package/runtime/delivery/development.ts +14 -11
  303. package/runtime/delivery/execution-identity.ts +32 -0
  304. package/runtime/delivery/existing-code.ts +7 -6
  305. package/runtime/delivery/history-package.ts +50 -0
  306. package/runtime/delivery/inputs.ts +18 -11
  307. package/runtime/delivery/journal.ts +14 -10
  308. package/runtime/delivery/parameter-defaults.ts +75 -0
  309. package/runtime/delivery/parameters.ts +18 -0
  310. package/runtime/delivery/planning.ts +19 -5
  311. package/runtime/delivery/preparation.ts +17 -1
  312. package/runtime/delivery/production-environment.ts +2 -1
  313. package/runtime/delivery/production-finalization.ts +19 -10
  314. package/runtime/delivery/production-intent.ts +14 -0
  315. package/runtime/delivery/production.ts +51 -11
  316. package/runtime/delivery/project-files.ts +16 -11
  317. package/runtime/delivery/project-rpc.ts +116 -0
  318. package/runtime/delivery/project.ts +19 -7
  319. package/runtime/delivery/public-calldata.ts +74 -0
  320. package/runtime/delivery/release-graph.ts +44 -14
  321. package/runtime/delivery/release-history-capture.ts +19 -9
  322. package/runtime/delivery/release-history.ts +76 -22
  323. package/runtime/delivery/release-inputs.ts +107 -0
  324. package/runtime/delivery/release.ts +56 -18
  325. package/runtime/delivery/safe.ts +14 -3
  326. package/runtime/delivery/same-fork-baseline.ts +5 -4
  327. package/runtime/delivery/setup.ts +20 -8
  328. package/runtime/delivery/source.ts +10 -10
  329. package/runtime/delivery/task-identity.ts +85 -0
  330. package/runtime/delivery/toolchain.ts +48 -0
  331. package/runtime/delivery/validation.ts +7 -2
  332. package/runtime/vendor/plan-codec/index.cjs +97 -20
  333. package/runtime/vendor/plan-codec/index.d.cts +6 -0
  334. package/runtime/vendor/plan-codec/provenance.json +9 -8
  335. package/runtime/workflow/lib/calls.ts +1 -0
  336. package/runtime/workflow/lib/checkCodeRunner.ts +7 -3
  337. package/runtime/workflow/lib/context.ts +1 -0
  338. package/runtime/workflow/lib/create2.ts +7 -108
  339. package/runtime/workflow/lib/deploymentInfo.ts +8 -0
  340. package/runtime/workflow/lib/deploymentRecords.ts +3 -1
  341. package/runtime/workflow/lib/externalExecutionScanner.ts +2 -1
  342. package/runtime/workflow/lib/gateTool.ts +2 -2
  343. package/runtime/workflow/lib/gateToolSync.ts +8 -0
  344. package/runtime/workflow/lib/parameters.ts +4 -0
  345. package/runtime/workflow/lib/proxy.ts +1 -0
  346. package/runtime/workflow/run.ts +1 -2
  347. package/runtime/workflow/steps/deploy.ts +42 -0
  348. package/runtime/workflow/steps/upgrade.ts +19 -11
  349. package/bin/workflow.cjs +0 -19
@@ -5,6 +5,7 @@ import {randomUUID} from 'node:crypto';
5
5
  import path from 'node:path';
6
6
  import {strictData} from './data';
7
7
  import {exactObject} from '../workflow/lib/canonicalData';
8
+ import {workerFailures} from './aggregate-diagnostics';
8
9
  export class OwnedWorkerFailure extends Error {}
9
10
  export type Command='stage'|'check'|'bind'|'close'|'abort';
10
11
  export interface WorkerMessage {version:1;session:string;epoch:string;target:string;id:number;command:Command;data:unknown}
@@ -32,10 +33,12 @@ export class OwnedWorker {
32
33
  if(!pending||reply.session!==session||reply.target!==target||reply.epoch!==this.epoch||reply.id!==pending.message.id||reply.command!==pending.message.command)throw new OwnedWorkerFailure('Unexpected worker protocol reply');
33
34
  const value=exactObject(reply.data,['ok','value'],'worker reply');
34
35
  if(value.ok!==true){
35
- const details=exactObject(value.value,['phase'],'worker failure');
36
- const phases=['protocol','project-loader','source-open','source-configuration','fork-setup','target-configuration','compile','planning','staged-reread','barrier','configuration-seal','binding'];
36
+ const hasReason=Object.hasOwn(value.value as object,'reason');
37
+ const details=exactObject(value.value,['phase',...(hasReason?['reason']:[])],'worker failure');
38
+ const phases=['protocol','project-loader','source-open','source-configuration','fork-setup','fork-verify','fork-signer','target-configuration','compile','planning','existing-code-artifacts','staged-reread','barrier','source-recheck','source-seal','plan-recheck','compiler-recheck','configuration-seal','binding'];
37
39
  if(!phases.includes(String(details.phase)))throw new Error('Invalid worker failure');
38
- this.fail(new OwnedWorkerFailure('Owned worker failed during '+details.phase));return;
40
+ if(hasReason&&(typeof details.reason!=='string'||!Object.hasOwn(workerFailures,details.reason)))throw new Error('Invalid worker failure reason');
41
+ this.fail(new OwnedWorkerFailure('Owned worker failed during '+details.phase+' ('+role+')'+(hasReason?': '+workerFailures[details.reason as string]:'')));return;
39
42
  }
40
43
  clearTimeout(pending.timer);this.#pending=undefined;pending.resolve(value.value);
41
44
  }catch{this.fail(new OwnedWorkerFailure('Owned worker failed or sent an invalid reply'));}
@@ -0,0 +1,63 @@
1
+ /** Finite diagnostics only: provider errors can contain RPC credentials and payloads. */
2
+ export const sourceRpcFailures = {
3
+ 'source-history-unavailable': 'Source RPC cannot read historical state at the pinned block; configure an RPC with historical-state access without changing the pinned block.',
4
+ 'source-access-denied': 'Source RPC denied access; check the configured RPC access without exposing credentials.',
5
+ 'source-rate-limited': 'Source RPC rate limit exceeded; use an RPC with sufficient read capacity for the pinned fork.',
6
+ 'source-transport-failed': 'Source RPC transport failed; check connectivity and the RPC response timeout for the pinned fork.',
7
+ 'source-request-failed': 'Source RPC request failed.',
8
+ } as const;
9
+ export type SourceRpcFailure = keyof typeof sourceRpcFailures;
10
+
11
+ const invariantMessages = [
12
+ 'Source read failed',
13
+ 'Planning source/input/runtime identity drift',
14
+ 'Planning pinned fork/source identity mismatch',
15
+ 'Captured fork interval drift',
16
+ 'Captured fork interval closed or bound',
17
+ 'Fork audit provider mutation/identity violation',
18
+ 'Fork audit baseline/provider identity changed',
19
+ 'Pending or unobservable fork transactions',
20
+ 'Fork audit changed while enumerating',
21
+ 'Audit transaction lookup mismatch',
22
+ 'Custom input closure drift at collection completion',
23
+ 'Compiler contribution drift',
24
+ 'Compiler effective config drift',
25
+ 'Compiler package payload drift',
26
+ 'Compiler package resolution drift',
27
+ 'Compiler npm lock drift',
28
+ 'Delivery configuration/runtime drift or mismatch',
29
+ 'Source provider changed',
30
+ 'Source pinned block drift',
31
+ ] as const;
32
+ export const workerFailures: Readonly<Record<string, string>> = Object.freeze({
33
+ ...sourceRpcFailures,
34
+ ...Object.fromEntries(invariantMessages.map((message, index) => ['invariant-'+index,message])),
35
+ 'compiler-input-drift': 'Compiler input bytes changed during qualification.',
36
+ });
37
+
38
+ /** Only exact reviewed messages or a fixed category may cross the worker channel. */
39
+ export function workerFailureReason(error: unknown): string | undefined {
40
+ const source = workerSourceFailure(error);
41
+ if (source) return source;
42
+ const message = error instanceof Error ? error.message : '';
43
+ const index = invariantMessages.findIndex(known => known === message);
44
+ if (index >= 0) return 'invariant-'+index;
45
+ if (message.startsWith('Compiler input drift: ')) return 'compiler-input-drift';
46
+ return undefined;
47
+ }
48
+
49
+ export function sourceRpcFailure(error: unknown): SourceRpcFailure {
50
+ const known = workerSourceFailure(error);
51
+ if (known) return known;
52
+ const message = error instanceof Error ? error.message : '';
53
+ if (/archive|historical\s+state|missing trie node|state.*(?:unavailable|not available)/i.test(message)) return 'source-history-unavailable';
54
+ if (/too many requests|rate.?limit/i.test(message) || (error as {code?:unknown} | null)?.code === -32005) return 'source-rate-limited';
55
+ if (/\b(?:401|403)\b|unauthorized|forbidden|authentication|invalid api key/i.test(message)) return 'source-access-denied';
56
+ if (/socket|ECONNRESET|ECONNREFUSED|UND_ERR_|timed? ?out|timeout|fetch failed/i.test(message)) return 'source-transport-failed';
57
+ return 'source-request-failed';
58
+ }
59
+
60
+ export function workerSourceFailure(error: unknown): SourceRpcFailure | undefined {
61
+ const message = error instanceof Error ? error.message : '';
62
+ return (Object.keys(sourceRpcFailures) as SourceRpcFailure[]).find(reason => message.includes(sourceRpcFailures[reason]));
63
+ }
@@ -4,6 +4,7 @@ import {randomUUID} from 'node:crypto';
4
4
  import {isAllowedSourceRpcMethod} from '../workflow/lib/sourceRpcPolicy';
5
5
  import type {DeliveryRequest} from './protocol';
6
6
  import type {HardhatRuntimeEnvironment} from 'hardhat/types';
7
+ import {sourceRpcFailure,sourceRpcFailures} from './aggregate-diagnostics';
7
8
  export interface SourceHandshake {
8
9
  version:1;session:string;epoch:string;target:string;proxyUrl:string;
9
10
  snapshot:{version:1;sourceNetwork:string;chainId:number;blockNumber:number;blockHash:string;runner:{kind:'hardhat';version:'2.26.3'}};
@@ -13,7 +14,10 @@ export async function openOwnedSource(hre:HardhatRuntimeEnvironment,request:Deli
13
14
  }> {
14
15
  if(hre.network.name!==request.network)throw new Error('Source HRE network mismatch');
15
16
  const provider=hre.network.provider;
16
- const rpc=(method:string,params:unknown[]=[])=>provider.request({method,params});
17
+ const rpc=async(method:string,params:unknown[]=[])=>{
18
+ try{return await provider.request({method,params});}
19
+ catch(cause){throw new Error(sourceRpcFailures[sourceRpcFailure(cause)]);}
20
+ };
17
21
  const chainId=Number(BigInt(await rpc('eth_chainId') as string));
18
22
  if(!Number.isSafeInteger(chainId)||chainId!==hre.network.config.chainId)throw new Error('Source chain identity mismatch');
19
23
  const tag=request.fork?'0x'+request.fork.blockNumber.toString(16):'latest';
@@ -27,7 +31,7 @@ export async function openOwnedSource(hre:HardhatRuntimeEnvironment,request:Deli
27
31
  const error=(code:number,message:string)=>({jsonrpc:'2.0',id:raw?.id??null,error:{code,message}});
28
32
  if(!raw||typeof raw!=='object'||Array.isArray(raw)||raw.jsonrpc!=='2.0'||typeof raw.method!=='string'||(raw.params!==undefined&&!Array.isArray(raw.params)))return error(-32600,'Invalid JSON-RPC request');
29
33
  if(!isAllowedSourceRpcMethod(raw.method))return error(-32601,'Source RPC method is not allowed');
30
- try{return {jsonrpc:'2.0',id:raw.id??null,result:await rpc(raw.method,raw.params??[])};}catch{return error(-32000,'Source RPC request failed');}
34
+ try{return {jsonrpc:'2.0',id:raw.id??null,result:await rpc(raw.method,raw.params??[])};}catch(cause){return error(-32000,sourceRpcFailures[sourceRpcFailure(cause)]);}
31
35
  };
32
36
  const server=http.createServer(async(req,res)=>{
33
37
  if(req.method!=='POST'||req.url!==endpoint){reply(res,404,{error:'Unknown JSON-RPC endpoint'});return;}
@@ -9,6 +9,7 @@ import type {StagedDeliveryCollection,DeliveryCollection} from './planning';
9
9
  import type {DeliveryConfigurationHandle,DeliveryConfigurationEvidence} from './configuration';
10
10
  import type {DeliveryCompilerCollector,CompilerEvidence} from './compiler';
11
11
  import type {openOwnedSource} from './aggregate-source';
12
+ import {workerFailureReason,sourceRpcFailures} from './aggregate-diagnostics';
12
13
 
13
14
  if(!process.send||!process.connected||require.main!==module){console.error('Aggregate worker requires an owned channel');process.exit(1);}
14
15
  let state:'new'|'staging'|'staged'|'checked'|'bound'|'closed'|'failed'='new',last=0;
@@ -24,7 +25,7 @@ async function dispatch(message:WorkerMessage):Promise<unknown>{
24
25
  if(message.command==='stage'){
25
26
  if(state!=='new')throw new Error('Duplicate worker stage');
26
27
  state='staging';initial=deepFreeze(strictData(message.data)) as any;
27
- exactObject(initial,initial.role==='source'?['root','workspaceRoot','projectRoot','request','role','handshakePath']:['root','workspaceRoot','projectRoot','request','role','handshake','target','params','steps','deploymentId','businessRoot','executionId','sourceDefinitionHash'],'worker stage input');
28
+ exactObject(initial,initial.role==='source'?['root','workspaceRoot','projectRoot','request','role','handshakePath']:['root','workspaceRoot','projectRoot','request','role','handshake','target','params','steps','deploymentId','businessRoot','executionId','sourceDefinitionHash',...(Object.hasOwn(initial,'derivationSeed')?['derivationSeed']:[])],'worker stage input');
28
29
  const {parseDeliveryRequest}=require('./protocol') as typeof import('./protocol');
29
30
  const request=parseDeliveryRequest(initial.request);role=initial.role;
30
31
  if(!['source','target'].includes(role)||request.network!==message.target||request.mode!=='simulate')throw new Error('Worker target mismatch');
@@ -54,8 +55,10 @@ async function dispatch(message:WorkerMessage):Promise<unknown>{
54
55
  const {WorkflowState}=require('../workflow/lib/state') as typeof import('../workflow/lib/state');
55
56
  const {qualifyDeliveryCompiler}=require('./compiler') as typeof import('./compiler');
56
57
  phase='fork-setup';const simulation=await setupSimulationFork(hre,request.network,{snapshotJson:JSON.stringify(initial.handshake.snapshot),sourceRpcUrl:initial.handshake.proxyUrl});
58
+ phase='fork-verify';
57
59
  await verifySimulationForkSnapshot(hre,simulation);
58
60
  const operator=(request.devSigner??request.operator)!.toLowerCase();
61
+ phase='fork-signer';
59
62
  const signer=await impersonateWorkflowSimulationSigner(hre,operator);
60
63
  phase='target-configuration';config=require('./configuration').openDeliveryConfiguration({workspaceRoot:initial.workspaceRoot,projectRoot:initial.projectRoot,network:request.network});
61
64
  phase='compile';compiler=await qualifyDeliveryCompiler(hre);
@@ -68,12 +71,12 @@ async function dispatch(message:WorkerMessage):Promise<unknown>{
68
71
  const identities={read:async()=>header,readSourceBlock:async(blockNumber:number)=>{
69
72
  const rpc=async(method:string,params:unknown[])=>{
70
73
  const response=await fetch(initial.handshake.proxyUrl,{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({jsonrpc:'2.0',id:1,method,params}),signal:AbortSignal.timeout(30000)});
71
- const data=await response.json() as any;if(data.error)throw new Error('Source read failed');return data.result;
74
+ const data=await response.json() as any;if(data.error)throw new Error(Object.values(sourceRpcFailures).includes(data.error.message)?data.error.message:'Source read failed');return data.result;
72
75
  };
73
76
  const [chain,block]=await Promise.all([rpc('eth_chainId',[]),rpc('eth_getBlockByNumber',['0x'+blockNumber.toString(16),false])]);
74
77
  return {chainId:BigInt(chain).toString(),blockNumber:Number(BigInt(block.number)),blockHash:block.hash};
75
78
  }};
76
- phase='planning';stage=await stageDeliveryPlan({context,header,identities,steps:initial.steps,derivationSeed:initial.executionId});
79
+ phase='planning';stage=await stageDeliveryPlan({context,header,identities,steps:initial.steps,derivationSeed:initial.derivationSeed??initial.executionId});
77
80
  if(!stage.snapshot.preparations.length){
78
81
  phase='existing-code-artifacts';
79
82
  const {collectExistingCodeArtifacts,requiredExistingAddresses}=require('./existing-code') as typeof import('./existing-code');
@@ -87,8 +90,14 @@ async function dispatch(message:WorkerMessage):Promise<unknown>{
87
90
  if(message.command==='check'){
88
91
  phase='barrier';await (require('./compiler-io') as typeof import('./compiler-io')).yieldCompilerIo();
89
92
  if(state!=='staged')throw new Error('Worker check order violation');
90
- if(role==='source'){await source!.check();finalConfiguration=config!.seal() as DeliveryConfigurationEvidence;state='checked';return {configuration:finalConfiguration};}
93
+ if(role==='source'){
94
+ phase='source-recheck';await source!.check();
95
+ phase='source-seal';finalConfiguration=config!.seal() as DeliveryConfigurationEvidence;
96
+ state='checked';return {configuration:finalConfiguration};
97
+ }
98
+ phase='plan-recheck';
91
99
  await stage!.assertUnchanged();
100
+ phase='compiler-recheck';
92
101
  if(canonicalJson(compiler!.evidence())!==canonicalJson(stagedCompiler))throw new Error('Compiler contribution drift');
93
102
  phase='configuration-seal';finalConfiguration=config!.seal() as DeliveryConfigurationEvidence;
94
103
  state='checked';return {configuration:finalConfiguration,...contribution};
@@ -125,7 +134,8 @@ process.on('message',async raw=>{
125
134
  state='failed';
126
135
  const active=association;
127
136
 
128
- if(active&&process.connected)await new Promise<void>(resolve=>process.send!({version:1,...active,id:last,command:(raw as any)?.command,data:{ok:false,value:{phase}}},()=>resolve()));
137
+ const reason=workerFailureReason(error);
138
+ if(active&&process.connected)await new Promise<void>(resolve=>process.send!({version:1,...active,id:last,command:(raw as any)?.command,data:{ok:false,value:{phase,...(reason?{reason}:{})}}},()=>resolve()));
129
139
  await cleanup().catch(()=>{});process.exit(1);
130
140
  }
131
141
  });
@@ -1,5 +1,6 @@
1
1
  /** Owned multi-target input qualification. This grants no release-ready or broadcast authority. */
2
2
  import fs from 'node:fs';
3
+ import {aggregateInputHash} from './execution-identity';
3
4
  import os from 'node:os';
4
5
  import path from 'node:path';
5
6
  import {randomUUID} from 'node:crypto';
@@ -115,8 +116,7 @@ async function collectOwnedAggregate(raw:DeliveryAggregateOptions):Promise<Reado
115
116
  }
116
117
  const union=[...files].sort(([a],[b])=>a.localeCompare(b,'en')).map(([path,digest])=>({path,digest}));
117
118
  // No runtime state, observation, plan hash or randomized compiler exact evidence enters this preimage.
118
- const inputsHash=semanticHash({version:1,business:sealed,sourceDefinitions,runtime:parentRuntime,files:union,
119
- targets:contributions.map(row=>({target:row.target,configuration:row.configuration.configurationRuntimeHash,sourceConfiguration:row.sourceConfiguration.configurationRuntimeHash,compiler:row.compiler.stableDigest,custom:row.custom}))});
119
+ const inputsHash=aggregateInputHash({inputs:{business:sealed,sourceDefinitions,runtime:parentRuntime,files:union,targets:contributions}});
120
120
  live();
121
121
  const collections:DeliveryCollection[]=[];
122
122
  for(const row of rows){
@@ -0,0 +1,33 @@
1
+ /** Shared declarative steps may gain network parameters without changing accepted dev behavior. */
2
+ import {resolveValue, type WorkflowStep} from '../workflow/lib/parameters';
3
+ import {canonicalJson} from '../workflow/lib/canonicalData';
4
+ import {pointerPart} from './data';
5
+ import type {ResolvedDeliveryParameters} from './parameters';
6
+
7
+ export function validateHistoricalBusinessExtension(input: {
8
+ before: readonly WorkflowStep[]; after: readonly WorkflowStep[];
9
+ previous: ResolvedDeliveryParameters; current: ResolvedDeliveryParameters; target: Record<string, unknown>;
10
+ }): void {
11
+ if ([...input.before, ...input.after].some(step => step.kind === 'custom')) throw Error('Historical custom steps require unchanged manifest/schema and parameters');
12
+ const symbolicState = {get: (key: string) => ({$ref: `state.${key}`})};
13
+ const project = (steps: readonly WorkflowStep[], params: unknown) => steps.map(step => {
14
+ const {name: _name, description: _description, ...operation} = step;
15
+ return resolveValue(operation, {targetId: input.previous.target, target: input.target,
16
+ params: params as Record<string, unknown>, state: symbolicState as never});
17
+ });
18
+ if (canonicalJson(project(input.before, input.previous.values)) !== canonicalJson(project(input.after, input.current.values))) throw Error('Historical resolved development operations changed');
19
+ const references = new Set<string>();
20
+ const visit = (value: unknown): void => {
21
+ if (typeof value === 'string' && value.startsWith('$param.')) references.add('/' + value.slice(7).split('.').map(pointerPart).join('/'));
22
+ else if (value && typeof value === 'object') {
23
+ const ref = (value as any).$ref;
24
+ if (typeof ref === 'string' && ref.startsWith('param.')) references.add('/' + ref.slice(6).split('.').map(pointerPart).join('/'));
25
+ else Object.values(value).forEach(visit);
26
+ }
27
+ };
28
+ input.after.forEach(visit);
29
+ for (const leaf of input.current.provenance) {
30
+ if (!input.previous.provenance.some(old => old.path === leaf.path)
31
+ && ![...references].some(ref => leaf.path === ref || leaf.path.startsWith(ref + '/'))) throw Error('Historical added parameter is not used by the shared steps');
32
+ }
33
+ }
@@ -0,0 +1,25 @@
1
+ /** Immutable project-local file publication. This is not execution authority. */
2
+ import { projectRoot } from './project-files';
3
+ import { atomicDevelopmentWrite, withDevelopmentFileLock, fileBytes, byteHash } from './materialization';
4
+ import { canonicalJson, semanticHash } from '../workflow/lib/canonicalData';
5
+ import { safeId } from './protocol';
6
+ import { serializeDeliveryCalls, deliveryCalldataPath } from './calldata-format';
7
+ import type { DeliveryCall } from './public-calldata';
8
+ export async function archiveDeliveryCalls(input:{workspaceRoot:string;projectRoot:string;deploymentId:string;calls:readonly DeliveryCall[];provenance:unknown;assertCurrent():void}){
9
+ const root=projectRoot(input.workspaceRoot,input.projectRoot),deployment=safeId(input.deploymentId,'deploymentId');
10
+ const bytes=serializeDeliveryCalls(input.calls)+'\n',sha256=byteHash(bytes);
11
+ const path=deliveryCalldataPath(deployment,sha256);
12
+ const body={version:1,path,sha256,provenance:input.provenance};
13
+ const record=canonicalJson(body)+'\n',provenancePath=`.gate-delivery/deliveries/${deployment}/${sha256}-${semanticHash(body)}.json`;
14
+ return withDevelopmentFileLock(root,async()=>{
15
+ input.assertCurrent();
16
+ for(const [file,content] of [[path,bytes],[provenancePath,record]]){
17
+ const existing=fileBytes(root,file);
18
+ if(existing!==null&&existing!==content)throw Error('Immutable calldata archive conflict');
19
+ if(existing===null)atomicDevelopmentWrite(root,file,content);
20
+ }
21
+ input.assertCurrent();
22
+ if(fileBytes(root,path)!==bytes)throw Error('Published calldata changed');
23
+ return {status:'READY' as const,path,sha256,size:Buffer.byteLength(bytes),provenance:{path:provenancePath,sha256:byteHash(record)}};
24
+ });
25
+ }
@@ -0,0 +1,90 @@
1
+ /** Explanations of verified wrapper ABI payloads; never additional transactions. */
2
+ import { Interface, getCreate2Address, keccak256, type ParamType } from 'ethers';
3
+ import { parseCalldataInvocation, type CalldataInvocation } from './calldata-review';
4
+ import type { PreparationEntry } from './journal';
5
+ import { canonicalJson } from '../workflow/lib/canonicalData';
6
+ export interface ExpandedCall {
7
+ to: string; name: string; description: string; abi: string[]; calldata: string;
8
+ value?: string; allowFailure?: boolean; details?: ExpandedDetails;
9
+ }
10
+ export type ExpandedDetails =
11
+ | { type: 'multicall'; calls: ExpandedCall[] }
12
+ | { type: 'create2'; contract: string; role: string; factory: string; salt: string; saltDescription: string;
13
+ constructor: { abi: string[]; args: unknown[]; initialization?: ExpandedCall };
14
+ initCodeHash: string; predictedAddress: string; create2ForwardValue?: string; callForwardValue?: string;
15
+ placeholderImplementation?: string; afterDeployment?: ExpandedCall }
16
+ | { type: 'upgrade'; proxy: string; newImplementation: string; initialization: ExpandedCall | null };
17
+ const childAt = (i: CalldataInvocation, path: number[]) => i.payloads.find(p => JSON.stringify(p.argumentPath) === JSON.stringify(path))?.invocation;
18
+ export function readableInvocationAbi(i: CalldataInvocation): string[] {
19
+ const iface=new Interface(i.abi as any);
20
+ const fragment=i.kind==='constructor'?iface.deploy:iface.getFunction(i.method);
21
+ if (!fragment) throw Error('Readable invocation ABI missing');
22
+ return [fragment.format('full')];
23
+ }
24
+ /** Keep authored business intent, append exact verified arguments without copying wrapper bytecode. */
25
+ export function describeDeliveryInvocation(description: string, raw: CalldataInvocation): string {
26
+ const invocation = parseCalldataInvocation(raw);
27
+ function argumentsText(i: CalldataInvocation, depth: number): string {
28
+ if (depth > 24) throw Error('Nested calldata description exceeds supported depth');
29
+ const iface = new Interface(i.abi as any);
30
+ const fragment = i.kind === 'constructor' ? iface.deploy : iface.getFunction(i.method);
31
+ if (!fragment) throw Error('Description invocation ABI missing');
32
+ const named = (type: ParamType, value: unknown, path: number[]): string =>
33
+ `${type.name || `arg${path[path.length - 1]}`}(${type.format('sighash')})=${render(type, value, path)}`;
34
+ const render = (type: ParamType, value: unknown, path: number[]): string => {
35
+ const payload = i.payloads.find(p => canonicalJson(p.argumentPath) === canonicalJson(path));
36
+ if (payload) {
37
+ const nested = payload.invocation;
38
+ const call = `${nested.method}(${argumentsText(nested, depth + 1)})`;
39
+ return nested.kind === 'constructor' ? `{initCodeHash=${keccak256(nested.data)}, ${call}}` : call;
40
+ }
41
+ if (type.baseType === 'array') return '[' + (value as unknown[])
42
+ .map((item, index) => render(type.arrayChildren!, item, [...path, index])).join(', ') + ']';
43
+ if (type.baseType === 'tuple') return '(' + type.components!
44
+ .map((component, index) => named(component, (value as unknown[])[index], [...path, index])).join(', ') + ')';
45
+ return canonicalJson(value);
46
+ };
47
+ return fragment.inputs.map((type, index) => named(type, i.expectedArguments[index], [index])).join(', ');
48
+ }
49
+ const args = argumentsText(invocation, 0);
50
+ return args ? `${description}\n执行参数:${args}` : description;
51
+ }
52
+ /** Caller validates its preparation journal against the frozen plan first. */
53
+ export function expandDeliveryInvocation(raw: CalldataInvocation, to: string, intent: {name:string;description:string}, entry?: PreparationEntry, depth=0): ExpandedDetails | undefined {
54
+ if(depth>24)throw Error('Nested calldata exceeds supported depth');
55
+ const i=parseCalldataInvocation(raw),args=i.expectedArguments;
56
+ const child=(invocation:CalldataInvocation,target:string,name:string,value='0'):ExpandedCall=>({to:target,name,description:describeDeliveryInvocation(`${intent.description};内部动作:${name}`,invocation),abi:readableInvocationAbi(invocation),calldata:invocation.data,
57
+ ...(BigInt(value)===0n?{}:{value}),...((details=>details?{details}:{})(expandDeliveryInvocation(invocation,target,{name,description:intent.description},entry,depth+1)))});
58
+ if(['aggregate3((address,bool,bytes)[])','aggregate3Value((address,bool,uint256,bytes)[])'].includes(i.method)) {
59
+ const withValue=i.method.startsWith('aggregate3Value');
60
+ return {type:'multicall',calls:(args[0] as any[]).map((row,index)=>{
61
+ const invocation=childAt(i,[0,index,withValue?3:2]);
62
+ if(!invocation)throw Error('Multicall child ABI missing');
63
+ const known=entry?.prepared.plan.transactions.find(tx=>tx.to.toLowerCase()===row[0].toLowerCase()&&tx.data.toLowerCase()===invocation.data);
64
+ const names:Record<string,string>={'deploy-implementation':'部署业务实现','deploy-proxy':'部署代理','deploy-contract':'CREATE2 部署合约','upgrade-proxy':'升级代理并按既定参数初始化'};
65
+ return {...child(invocation,row[0],known?names[known.purpose]??known.purpose:`${intent.name} / ${index+1}`,withValue?row[2]:'0'),allowFailure:row[1]};
66
+ })};
67
+ }
68
+ if(i.method==='deploy(bytes32,bytes,bytes,uint256,uint256)') {
69
+ const ctor=childAt(i,[1]);
70
+ if(!entry||!ctor||ctor.kind!=='constructor')throw Error('CREATE2 explanation requires frozen preparation and constructor ABI');
71
+ const initCodeHash=keccak256(ctor.data),predictedAddress=getCreate2Address(to,String(args[0]),initCodeHash).toLowerCase();
72
+ const deployed=entry.prepared.plan.deployments.find(d=>d.salt.toLowerCase()===String(args[0]).toLowerCase()&&d.address.toLowerCase()===predictedAddress);
73
+ if(!deployed||deployed.initCodeHash&&deployed.initCodeHash.toLowerCase()!==initCodeHash)throw Error('CREATE2 salt, initCode or predicted address differs from frozen preparation');
74
+ const request=entry.prepared.request,placeholder=request.kind==='uups-placeholder-deploy'&&deployed.role==='proxy';
75
+ const initialization=deployed.role==='proxy'?childAt(ctor,[request.kind==='transparent-deploy'?2:1]):undefined;
76
+ if(ctor.payloads.length&&!initialization)throw Error('Constructor executable payload has no registered adapter');
77
+ const forward=childAt(i,[2]);
78
+ return {type:'create2',contract:deployed.role==='proxy'?(request.kind==='transparent-deploy'?'TransparentUpgradeableProxy':'ERC1967Proxy'):request.contract,
79
+ role:deployed.role,factory:to,salt:String(args[0]),saltDescription:deployed.role==='proxy'?'proxySalt:确定代理地址的 CREATE2 盐值,与实现盐值分离':deployed.role==='implementation'?'implementationSalt:本轮业务实现的 CREATE2 盐值,与代理盐值分离':'本轮合约的 CREATE2 盐值',
80
+ constructor:{abi:readableInvocationAbi(ctor),args:ctor.expectedArguments,...(initialization?{initialization:child(initialization,predictedAddress,'构造期间初始化')}: {})},
81
+ initCodeHash,predictedAddress,...(BigInt(String(args[3]))===0n?{}:{create2ForwardValue:String(args[3])}),...(BigInt(String(args[4]))===0n?{}:{callForwardValue:String(args[4])}),
82
+ ...(placeholder?{placeholderImplementation:request.placeholderImplementation}:{}),...(forward?{afterDeployment:child(forward,predictedAddress,'部署后调用',String(args[4]))}:{})};
83
+ }
84
+ if(['upgradeToAndCall(address,bytes)','upgradeAndCall(address,address,bytes)'].includes(i.method)) {
85
+ const transparent=i.method.startsWith('upgradeAndCall'),proxy=transparent?String(args[0]):to,newImplementation=String(args[transparent?1:0]),initializer=childAt(i,[transparent?2:1]);
86
+ return {type:'upgrade',proxy,newImplementation,initialization:initializer?child(initializer,proxy,'升级附带初始化'):null};
87
+ }
88
+ if(i.payloads.length)throw Error('Executable nested payload has no registered explanation adapter');
89
+ return undefined;
90
+ }
@@ -0,0 +1,14 @@
1
+ /** One readable, deterministic file format and path for every public delivery. */
2
+ import { canonicalJson } from '../workflow/lib/canonicalData';
3
+ import { safeId } from './protocol';
4
+ import type { DeliveryCall } from './public-calldata';
5
+
6
+ /** No trailing newline: file publishers append exactly one before hashing. */
7
+ export function serializeDeliveryCalls(calls: readonly DeliveryCall[]): string {
8
+ return JSON.stringify(JSON.parse(canonicalJson(calls)), null, 2);
9
+ }
10
+
11
+ export function deliveryCalldataPath(deploymentId: string, sha256: string): string {
12
+ if (!/^[a-f0-9]{64}$/.test(sha256)) throw Error('Invalid calldata content digest');
13
+ return `scripts/tasks/${safeId(deploymentId, 'deploymentId')}/deliveries/${sha256}/calldata.json`;
14
+ }
@@ -0,0 +1,76 @@
1
+ /** Planning-only adapter: reconstruct deployment intent from frozen requests and compiled artifacts. */
2
+ import { Interface, concat, type InterfaceAbi } from 'ethers';
3
+ import type { PreparationEntry } from './journal';
4
+ import type { ReleaseExecutionTransaction } from '../workflow/lib/transactionPlanner';
5
+ import { createCalldataInvocation, reviewTransaction, type CalldataInvocation, type CalldataTransactionReview } from './calldata-review';
6
+
7
+ const factoryAbi = ['function deploy(bytes32 salt,bytes initCode,bytes data,uint256 create2ForwardValue,uint256 callForwardValue) payable returns(address)'];
8
+ const upgradeAbi = ['function upgradeToAndCall(address newImplementation,bytes data) payable'];
9
+ const adminAbi = ['function upgradeAndCall(address proxy,address implementation,bytes data) payable'];
10
+ const multicallAbi = [
11
+ 'function aggregate3(tuple(address target,bool allowFailure,bytes callData)[] calls) payable returns(tuple(bool success,bytes returnData)[])',
12
+ 'function aggregate3Value(tuple(address target,bool allowFailure,uint256 value,bytes callData)[] calls) payable returns(tuple(bool success,bytes returnData)[])',
13
+ ];
14
+ type ArtifactReader = { readArtifact(name: string): Promise<{ abi: InterfaceAbi; bytecode: string }> };
15
+ export async function preparationCalldataReviews(entries: readonly PreparationEntry[], transactions: readonly ReleaseExecutionTransaction[], artifacts: ArtifactReader): Promise<CalldataTransactionReview[]> {
16
+ const result: CalldataTransactionReview[] = [];
17
+ for (const entry of entries) {
18
+ const { request, plan } = entry.prepared;
19
+ const artifact = await artifacts.readArtifact(request.contract);
20
+ const implementation = plan.deployments.find(d => d.role === 'implementation');
21
+ const initializer = request.kind !== 'create2-deploy' && request.call
22
+ ? createCalldataInvocation({ abi: artifact.abi, method: request.call.method, args: request.call.args,
23
+ data: new Interface(artifact.abi).encodeFunctionData(request.call.method, request.call.args) }) : undefined;
24
+ const inner = new Map<string, CalldataInvocation>();
25
+ for (const tx of plan.transactions) {
26
+ let invocation: CalldataInvocation;
27
+ if (tx.purpose === 'upgrade-proxy') {
28
+ if (request.kind === 'create2-deploy' || !implementation) throw Error('Upgrade ABI intent missing');
29
+ const transparent = request.kind === 'transparent-upgrade';
30
+ const args = transparent ? [request.proxy, implementation.address, initializer?.data ?? '0x'] : [implementation.address, initializer?.data ?? '0x'];
31
+ invocation = createCalldataInvocation({ abi: transparent ? adminAbi : upgradeAbi, method: transparent ? 'upgradeAndCall' : 'upgradeToAndCall', args, data: tx.data,
32
+ payloads: initializer ? [{ argumentPath: [transparent ? 2 : 1], invocation: initializer }] : [] });
33
+ } else {
34
+ const role = tx.purpose === 'deploy-proxy' ? 'proxy' : tx.purpose === 'deploy-implementation' ? 'implementation' : 'contract';
35
+ const deployed = plan.deployments.find(d => d.role === role);
36
+ if (!deployed) throw Error('Deployment ABI intent missing');
37
+ const proxy = role === 'proxy';
38
+ const transparent = request.kind === 'transparent-deploy';
39
+ const code = proxy ? await artifacts.readArtifact(transparent
40
+ ? '@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol:TransparentUpgradeableProxy'
41
+ : '@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol:ERC1967Proxy') : artifact;
42
+ const args = !proxy ? request.constructorArgs : request.kind === 'uups-placeholder-deploy'
43
+ ? [request.placeholderImplementation, '0x'] : transparent
44
+ ? [implementation!.address, request.proxyAdminOwner, initializer?.data ?? '0x'] : undefined;
45
+ if (!args) throw Error('Proxy constructor ABI intent missing');
46
+ const constructor = createCalldataInvocation({ abi: code.abi, method: null, args, bytecode: code.bytecode,
47
+ data: concat([code.bytecode, new Interface(code.abi).encodeDeploy(args)]),
48
+ payloads: proxy && transparent && initializer ? [{ argumentPath: [2], invocation: initializer }] : [] });
49
+ if (new Interface(code.abi).encodeDeploy(args).toLowerCase() !== deployed.constructorInput.toLowerCase()) throw Error('Constructor calldata differs from preparation');
50
+ const forward = request.kind === 'create2-deploy' ? [request.create2ForwardValue ?? '0', request.callForwardValue ?? '0'] : ['0', '0'];
51
+ invocation = createCalldataInvocation({ abi: factoryAbi, method: 'deploy', args: [deployed.salt, constructor.data, '0x', ...forward], data: tx.data,
52
+ payloads: [{ argumentPath: [1], invocation: constructor }] });
53
+ }
54
+ inner.set(tx.id, invocation);
55
+ }
56
+ for (const mapping of entry.mappings) {
57
+ const tx = transactions.find(t => t.transactionId === mapping.transactionId);
58
+ if (!tx) throw Error('Calldata preparation mapping missing');
59
+ const calls = mapping.gateToolTransactionIds.map(id => {
60
+ const intent = inner.get(id), prepared = plan.transactions.find(t => t.id === id);
61
+ if (!intent || !prepared) throw Error('Inner calldata ABI intent missing');
62
+ return { intent, prepared };
63
+ });
64
+ if (mapping.kind === 'direct') {
65
+ if (calls.length !== 1) throw Error('Direct calldata mapping must contain one invocation');
66
+ result.push(reviewTransaction(tx, calls[0].intent));
67
+ } else {
68
+ const withValue = calls.some(c => BigInt(c.prepared.value) !== 0n), method = withValue ? 'aggregate3Value' : 'aggregate3';
69
+ const args = [calls.map(({ prepared: p }) => withValue ? [p.to, false, p.value, p.data] : [p.to, false, p.data])];
70
+ result.push(reviewTransaction(tx, createCalldataInvocation({ abi: multicallAbi, method, args, data: tx.data,
71
+ payloads: calls.map((c, index) => ({ argumentPath: [0, index, withValue ? 3 : 2], invocation: c.intent })) })));
72
+ }
73
+ }
74
+ }
75
+ return result;
76
+ }
@@ -0,0 +1,126 @@
1
+ /** Pure ABI review. Expected arguments come from planning, never from decoding submitted bytes. */
2
+ import { AbiCoder, Interface, ParamType, type InterfaceAbi } from 'ethers';
3
+ import { canonicalJson, deepFreeze } from '../workflow/lib/canonicalData';
4
+ import type { ReleaseExecutionTransaction } from '../workflow/lib/transactionPlanner';
5
+ import { strictData } from './data';
6
+
7
+ export interface CalldataPayload {
8
+ argumentPath: number[];
9
+ invocation: CalldataInvocation;
10
+ }
11
+ export interface CalldataInvocation {
12
+ kind: 'function' | 'constructor';
13
+ abi: unknown[];
14
+ method: string;
15
+ selector: string | null;
16
+ bytecode: string | null;
17
+ expectedArguments: unknown[];
18
+ decodedArguments: unknown[];
19
+ data: string;
20
+ payloads: CalldataPayload[];
21
+ check: 'matches-frozen-intent';
22
+ }
23
+ export interface CalldataTransactionReview {
24
+ transactionId: string;
25
+ to: string;
26
+ value: string;
27
+ operation: 0 | 1;
28
+ invocation: CalldataInvocation;
29
+ }
30
+ export interface CalldataReviewSink {
31
+ record(transaction: ReleaseExecutionTransaction, input: { abi: InterfaceAbi; method: string; args: readonly unknown[] }): void;
32
+ }
33
+ function bytes(value: unknown): string {
34
+ if (typeof value !== 'string' || !/^0x(?:[a-fA-F0-9]{2})*$/.test(value)) throw Error('Invalid ABI review bytes');
35
+ return value.toLowerCase();
36
+ }
37
+ /** Decimal strings retain uint256 precision; positional tuples are unambiguous even with duplicate names. */
38
+ function argument(type: ParamType, value: any): unknown {
39
+ if (type.baseType === 'array') {
40
+ if (!Array.isArray(value) || (type.arrayLength !== -1 && value.length !== type.arrayLength)) throw Error('Invalid ABI review array');
41
+ return Array.from(value, v => argument(type.arrayChildren!, v));
42
+ }
43
+ if (type.baseType === 'tuple') {
44
+ if (!value || typeof value !== 'object') throw Error('Invalid ABI review tuple');
45
+ return type.components!.map((p, i) => argument(p, Array.isArray(value) ? value[i] : value[p.name]));
46
+ }
47
+ if (/^u?int\d*$/.test(type.type)) {
48
+ if (typeof value === 'number' && !Number.isSafeInteger(value)) throw Error('Unsafe ABI review integer');
49
+ if (!['bigint', 'number', 'string'].includes(typeof value) || (typeof value === 'string' && !value.trim())) throw Error('Invalid ABI review integer');
50
+ return BigInt(value).toString();
51
+ }
52
+ if (type.type === 'address') return String(value).toLowerCase();
53
+ if (/^bytes\d*$/.test(type.type)) return bytes(value);
54
+ if ((type.type === 'bool' && typeof value !== 'boolean') || (type.type === 'string' && typeof value !== 'string')) throw Error('Invalid ABI review scalar');
55
+ return value;
56
+ }
57
+ function argumentsOf(types: readonly ParamType[], args: readonly unknown[]): unknown[] {
58
+ if (!Array.isArray(args) || types.length !== args.length) throw Error('ABI review argument count mismatch');
59
+ return types.map((p, i) => argument(p, args[i]));
60
+ }
61
+ export function createCalldataInvocation(input: {
62
+ abi: InterfaceAbi; method: string | null; args: readonly unknown[]; data: string;
63
+ bytecode?: string; payloads?: CalldataPayload[];
64
+ }): CalldataInvocation {
65
+ const iface = new Interface(input.abi), fragment = input.method === null ? iface.deploy : iface.getFunction(input.method);
66
+ if (!fragment) throw Error('ABI review method missing');
67
+ const expectedArguments = argumentsOf(fragment.inputs, input.args), data = bytes(input.data);
68
+ const bytecode = input.method === null ? bytes(input.bytecode) : null;
69
+ if (input.method !== null && input.bytecode !== undefined) throw Error('Function review cannot contain constructor bytecode');
70
+ const encoded = input.method === null ? bytecode + iface.encodeDeploy(expectedArguments).slice(2) : iface.encodeFunctionData(input.method, expectedArguments).toLowerCase();
71
+ if (encoded !== data) throw Error('Calldata differs from expected ABI encoding');
72
+ const decoded = input.method === null
73
+ ? AbiCoder.defaultAbiCoder().decode(fragment.inputs, '0x' + data.slice(bytecode!.length))
74
+ : iface.decodeFunctionData(input.method, data);
75
+ const decodedArguments = argumentsOf(fragment.inputs, Array.from(decoded));
76
+ if (canonicalJson(expectedArguments) !== canonicalJson(decodedArguments)) throw Error('Decoded calldata differs from frozen intent');
77
+ const payloads = (input.payloads ?? []).map(p => {
78
+ if (!Array.isArray(p.argumentPath) || !p.argumentPath.length || p.argumentPath.some(i => !Number.isSafeInteger(i) || i < 0)) throw Error('Invalid nested calldata argument path');
79
+ let value: any = expectedArguments;
80
+ for (const index of p.argumentPath) {
81
+ if (!Array.isArray(value) || index >= value.length) throw Error('Nested calldata argument path missing');
82
+ value = value[index];
83
+ }
84
+ const invocation = parseCalldataInvocation(p.invocation);
85
+ if (value !== invocation.data) throw Error('Nested calldata differs from enclosing payload');
86
+ return { argumentPath: p.argumentPath, invocation };
87
+ });
88
+ if (new Set(payloads.map(p => canonicalJson(p.argumentPath))).size !== payloads.length) throw Error('Duplicate nested calldata payload');
89
+ const method = input.method === null ? 'constructor' : fragment.format('sighash');
90
+ const required: number[][] = [];
91
+ if (method === 'deploy(bytes32,bytes,bytes,uint256,uint256)') {
92
+ required.push([1]);
93
+ if (expectedArguments[2] !== '0x') required.push([2]);
94
+ if (payloads.find(p => canonicalJson(p.argumentPath) === '[1]')?.invocation.kind !== 'constructor') throw Error('CREATE2 constructor ABI review required');
95
+ } else if (method === 'upgradeToAndCall(address,bytes)' && expectedArguments[1] !== '0x') required.push([1]);
96
+ else if (method === 'upgradeAndCall(address,address,bytes)' && expectedArguments[2] !== '0x') required.push([2]);
97
+ else if (['aggregate3((address,bool,bytes)[])', 'aggregate3Value((address,bool,uint256,bytes)[])'].includes(method)) {
98
+ const index = method.startsWith('aggregate3Value') ? 3 : 2;
99
+ (expectedArguments[0] as unknown[]).forEach((_, i) => required.push([0, i, index]));
100
+ }
101
+ for (const path of required) if (!payloads.some(p => canonicalJson(p.argumentPath) === canonicalJson(path))) throw Error('Nested calldata ABI review required');
102
+ return deepFreeze({ kind: input.method === null ? 'constructor' : 'function', abi: [JSON.parse(fragment.format('json'))],
103
+ method, selector: input.method === null ? null : iface.getFunction(input.method)!.selector,
104
+ bytecode, expectedArguments, decodedArguments, data, payloads, check: 'matches-frozen-intent' });
105
+ }
106
+ export function parseCalldataInvocation(raw: unknown): CalldataInvocation {
107
+ const v = strictData(raw) as CalldataInvocation;
108
+ if (!v || !['function', 'constructor'].includes(v.kind) || !Array.isArray(v.payloads)) throw Error('Invalid calldata invocation');
109
+ const parsed = createCalldataInvocation({ abi: v.abi as InterfaceAbi, method: v.kind === 'constructor' ? null : v.method,
110
+ args: v.expectedArguments, data: v.data, ...(v.kind === 'constructor' ? { bytecode: v.bytecode! } : {}), payloads: v.payloads });
111
+ if (canonicalJson(parsed) !== canonicalJson(v)) throw Error('Noncanonical or modified ABI review');
112
+ return parsed;
113
+ }
114
+ export function reviewTransaction(tx: ReleaseExecutionTransaction, invocation: CalldataInvocation): CalldataTransactionReview {
115
+ const parsed = parseCalldataInvocation(invocation);
116
+ if (parsed.kind !== 'function' || parsed.data !== tx.data) throw Error('ABI review transaction calldata mismatch');
117
+ return deepFreeze({ transactionId: tx.transactionId, to: tx.to, value: tx.value, operation: tx.operation, invocation: parsed });
118
+ }
119
+ export function parseCalldataReviews(raw: unknown, transactions: readonly ReleaseExecutionTransaction[]): CalldataTransactionReview[] {
120
+ if (!Array.isArray(raw) || raw.length !== transactions.length) throw Error('Complete calldata ABI review required');
121
+ return deepFreeze(raw.map((value, index) => {
122
+ const v = strictData(value) as CalldataTransactionReview, expected = reviewTransaction(transactions[index], v.invocation);
123
+ if (canonicalJson(v) !== canonicalJson(expected)) throw Error('ABI review transaction binding mismatch');
124
+ return expected;
125
+ }));
126
+ }
@@ -1,3 +1,3 @@
1
- // Reviewed vendor identity. Refresh explicitly after rebuilding from committed canonical sources.
2
- export const PLAN_CODEC_PROVENANCE_SHA256 = '63bc721e90943e08478a67a72d1bef8ce69a034552f225b90ee2c6e5396785ce';
3
- export const PLAN_CODEC_SOURCE_COMMIT = '9b175e7906ca6735aeca92b50ce7cf716d980f17';
1
+ // Reviewed canonical codec; rebuilt from the recorded SmartFlow sources.
2
+ export const PLAN_CODEC_SOURCE_COMMIT = "ee0f90991ca1a94c3f58c8893df16d0c8c41b230";
3
+ export const PLAN_CODEC_PROVENANCE_SHA256 = "212e560b26b7560a73df1f20bd789fce1e5c3f409afba2d5a5c5c39cb2518ce7";
@@ -83,7 +83,9 @@ export class CompilerFiles {
83
83
  const dependency = compilerDependencyPins[`${metadata.name}@${metadata.version}`];
84
84
  if ((enforceReviewed && !pin && !dependency) || (pin && (pin.version !== metadata.version || pin.integrity !== entry.integrity || pin.payloadDigest !== payloadDigest)) || (dependency && (dependency.integrity !== entry.integrity || dependency.payloadDigest !== payloadDigest))) throw new Error(`Unapproved compiler adapter package payload: ${metadata.name}`);
85
85
  const tarball = typeof entry.resolved === 'string' && entry.resolved.startsWith('file:') && entry.resolved.endsWith('.tgz');
86
- if (!tarball && (typeof entry.resolved !== 'string' || !entry.resolved.startsWith('https://registry.npmjs.org/'))) throw new Error('Unsupported compiler package source');
86
+ const registry = typeof entry.resolved === 'string'
87
+ && ['https://registry.npmjs.org/', 'https://registry.npmmirror.com/'].some(prefix => entry.resolved.startsWith(prefix));
88
+ if (!tarball && !registry) throw new Error('Unsupported compiler package source');
87
89
  const value: CompilerPackage = { lockLocation, name: metadata.name, version: metadata.version, integrity: entry.integrity, source: { kind: tarball ? 'tarball' : 'registry', identity: entry.integrity }, payload, payloadDigest };
88
90
  if (this.packages.has(lockLocation) && semanticHash(this.packages.get(lockLocation)) !== semanticHash(value)) throw new Error('Compiler package payload drift');
89
91
  this.packages.set(lockLocation, value);
@@ -39,7 +39,7 @@ export const compilerTaskPins: Record<string, string[]> = {
39
39
  "086f478dc6172a8ad8053f21b47637cde5ed55e76fd68f4d19b957ca2ba89356"
40
40
  ],
41
41
  "compile:solidity:get-source-names": [
42
- "a1b8fb51de8eafdf94e28fac8ba9402e0e6e01268a07118bb1b9c30f029abce9",
42
+ "cde87b363a60ee09606119b95a59091d185514660b13b860a9d1fd72586034c4",
43
43
  "9583d07a487241a306f8f3664134538b3090a176a3f21deffac38351f3b67221"
44
44
  ],
45
45
  "compile:solidity:read-file": [