@psavelis/enterprise-blockchain 0.1.0 → 1.1.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 (296) hide show
  1. package/README.md +15 -2
  2. package/dist/aid-settlement/application/reconciler.d.ts +13 -0
  3. package/dist/aid-settlement/application/reconciler.d.ts.map +1 -0
  4. package/dist/aid-settlement/application/reconciler.js +77 -0
  5. package/dist/aid-settlement/domain/entities.d.ts +24 -0
  6. package/dist/aid-settlement/domain/entities.d.ts.map +1 -0
  7. package/dist/aid-settlement/domain/entities.js +1 -0
  8. package/dist/aid-settlement/domain/ports.d.ts +10 -0
  9. package/dist/aid-settlement/domain/ports.d.ts.map +1 -0
  10. package/dist/aid-settlement/domain/ports.js +1 -0
  11. package/dist/aid-settlement/index.d.ts +19 -0
  12. package/dist/aid-settlement/index.d.ts.map +1 -0
  13. package/dist/aid-settlement/index.js +23 -0
  14. package/dist/aid-settlement/infrastructure/in-memory-store.d.ts +12 -0
  15. package/dist/aid-settlement/infrastructure/in-memory-store.d.ts.map +1 -0
  16. package/dist/aid-settlement/infrastructure/in-memory-store.js +17 -0
  17. package/dist/credentialing/application/clearance-evaluator.d.ts +10 -0
  18. package/dist/credentialing/application/clearance-evaluator.d.ts.map +1 -0
  19. package/dist/credentialing/application/clearance-evaluator.js +63 -0
  20. package/dist/credentialing/domain/entities.d.ts +28 -0
  21. package/dist/credentialing/domain/entities.d.ts.map +1 -0
  22. package/dist/credentialing/domain/entities.js +1 -0
  23. package/dist/credentialing/domain/ports.d.ts +9 -0
  24. package/dist/credentialing/domain/ports.d.ts.map +1 -0
  25. package/dist/credentialing/domain/ports.js +1 -0
  26. package/dist/credentialing/index.d.ts +19 -0
  27. package/dist/credentialing/index.d.ts.map +1 -0
  28. package/dist/credentialing/index.js +23 -0
  29. package/dist/credentialing/infrastructure/in-memory-store.d.ts +11 -0
  30. package/dist/credentialing/infrastructure/in-memory-store.d.ts.map +1 -0
  31. package/dist/credentialing/infrastructure/in-memory-store.js +14 -0
  32. package/dist/hsm/application/asymmetric-key-service.d.ts +23 -0
  33. package/dist/hsm/application/asymmetric-key-service.d.ts.map +1 -0
  34. package/dist/hsm/application/asymmetric-key-service.js +109 -0
  35. package/dist/hsm/application/envelope-encryption-service.d.ts +18 -0
  36. package/dist/hsm/application/envelope-encryption-service.d.ts.map +1 -0
  37. package/dist/hsm/application/envelope-encryption-service.js +59 -0
  38. package/dist/hsm/application/symmetric-key-service.d.ts +34 -0
  39. package/dist/hsm/application/symmetric-key-service.d.ts.map +1 -0
  40. package/dist/hsm/application/symmetric-key-service.js +107 -0
  41. package/dist/hsm/domain/entities.d.ts +104 -0
  42. package/dist/hsm/domain/entities.d.ts.map +1 -0
  43. package/dist/hsm/domain/entities.js +10 -0
  44. package/dist/hsm/domain/ports.d.ts +20 -0
  45. package/dist/hsm/domain/ports.d.ts.map +1 -0
  46. package/dist/hsm/domain/ports.js +1 -0
  47. package/dist/hsm/index.d.ts +48 -0
  48. package/dist/hsm/index.d.ts.map +1 -0
  49. package/dist/hsm/index.js +97 -0
  50. package/dist/hsm/infrastructure/audit-log-factory.d.ts +59 -0
  51. package/dist/hsm/infrastructure/audit-log-factory.d.ts.map +1 -0
  52. package/dist/hsm/infrastructure/audit-log-factory.js +95 -0
  53. package/dist/hsm/infrastructure/audit-log.d.ts +8 -0
  54. package/dist/hsm/infrastructure/audit-log.d.ts.map +1 -0
  55. package/dist/hsm/infrastructure/audit-log.js +18 -0
  56. package/dist/hsm/infrastructure/file-audit-log.d.ts +55 -0
  57. package/dist/hsm/infrastructure/file-audit-log.d.ts.map +1 -0
  58. package/dist/hsm/infrastructure/file-audit-log.js +128 -0
  59. package/dist/hsm/infrastructure/key-store.d.ts +9 -0
  60. package/dist/hsm/infrastructure/key-store.d.ts.map +1 -0
  61. package/dist/hsm/infrastructure/key-store.js +12 -0
  62. package/dist/hsm/infrastructure/syslog-audit-log.d.ts +64 -0
  63. package/dist/hsm/infrastructure/syslog-audit-log.d.ts.map +1 -0
  64. package/dist/hsm/infrastructure/syslog-audit-log.js +167 -0
  65. package/dist/index.d.ts +22 -0
  66. package/dist/index.d.ts.map +1 -0
  67. package/dist/index.js +37 -0
  68. package/dist/integrations/besu-client/error-mapper.d.ts +9 -0
  69. package/dist/integrations/besu-client/error-mapper.d.ts.map +1 -0
  70. package/dist/integrations/besu-client/error-mapper.js +22 -0
  71. package/dist/integrations/besu-client/index.d.ts +65 -0
  72. package/dist/integrations/besu-client/index.d.ts.map +1 -0
  73. package/dist/integrations/besu-client/index.js +276 -0
  74. package/dist/integrations/besu-client/ports.d.ts +44 -0
  75. package/dist/integrations/besu-client/ports.d.ts.map +1 -0
  76. package/dist/integrations/besu-client/ports.js +1 -0
  77. package/dist/integrations/corda-gateway/index.d.ts +37 -0
  78. package/dist/integrations/corda-gateway/index.d.ts.map +1 -0
  79. package/dist/integrations/corda-gateway/index.js +234 -0
  80. package/dist/integrations/corda-gateway/ports.d.ts +33 -0
  81. package/dist/integrations/corda-gateway/ports.d.ts.map +1 -0
  82. package/dist/integrations/corda-gateway/ports.js +1 -0
  83. package/dist/integrations/fabric-gateway/index.d.ts +78 -0
  84. package/dist/integrations/fabric-gateway/index.d.ts.map +1 -0
  85. package/dist/integrations/fabric-gateway/index.js +214 -0
  86. package/dist/integrations/fabric-gateway/ports.d.ts +50 -0
  87. package/dist/integrations/fabric-gateway/ports.d.ts.map +1 -0
  88. package/dist/integrations/fabric-gateway/ports.js +1 -0
  89. package/dist/integrations/index.d.ts +19 -0
  90. package/dist/integrations/index.d.ts.map +1 -0
  91. package/dist/integrations/index.js +19 -0
  92. package/dist/integrations/shared/env.d.ts +4 -0
  93. package/dist/integrations/shared/env.d.ts.map +1 -0
  94. package/dist/integrations/shared/env.js +24 -0
  95. package/dist/integrations/shared/retry.d.ts +79 -0
  96. package/dist/integrations/shared/retry.d.ts.map +1 -0
  97. package/dist/integrations/shared/retry.js +315 -0
  98. package/dist/mpc/adapters.d.ts +36 -0
  99. package/dist/mpc/adapters.d.ts.map +1 -0
  100. package/dist/mpc/adapters.js +46 -0
  101. package/dist/mpc/crypto.d.ts +2 -0
  102. package/dist/mpc/crypto.d.ts.map +1 -0
  103. package/dist/mpc/crypto.js +2 -0
  104. package/dist/mpc/dsa.d.ts +134 -0
  105. package/dist/mpc/dsa.d.ts.map +1 -0
  106. package/dist/mpc/dsa.js +127 -0
  107. package/dist/mpc/field.d.ts +127 -0
  108. package/dist/mpc/field.d.ts.map +1 -0
  109. package/dist/mpc/field.js +209 -0
  110. package/dist/mpc/hybrid-kem.d.ts +96 -0
  111. package/dist/mpc/hybrid-kem.d.ts.map +1 -0
  112. package/dist/mpc/hybrid-kem.js +136 -0
  113. package/dist/mpc/index.d.ts +135 -0
  114. package/dist/mpc/index.d.ts.map +1 -0
  115. package/dist/mpc/index.js +348 -0
  116. package/dist/mpc/kyber.d.ts +134 -0
  117. package/dist/mpc/kyber.d.ts.map +1 -0
  118. package/dist/mpc/kyber.js +143 -0
  119. package/dist/mpc/ports.d.ts +67 -0
  120. package/dist/mpc/ports.d.ts.map +1 -0
  121. package/dist/mpc/ports.js +9 -0
  122. package/dist/mpc/quantum.d.ts +80 -0
  123. package/dist/mpc/quantum.d.ts.map +1 -0
  124. package/dist/mpc/quantum.js +180 -0
  125. package/dist/p2mr/adapters.d.ts +31 -0
  126. package/dist/p2mr/adapters.d.ts.map +1 -0
  127. package/dist/p2mr/adapters.js +35 -0
  128. package/dist/p2mr/index.d.ts +63 -0
  129. package/dist/p2mr/index.d.ts.map +1 -0
  130. package/dist/p2mr/index.js +59 -0
  131. package/dist/p2mr/merkle-tree.d.ts +109 -0
  132. package/dist/p2mr/merkle-tree.d.ts.map +1 -0
  133. package/dist/p2mr/merkle-tree.js +239 -0
  134. package/dist/p2mr/p2mr-output.d.ts +142 -0
  135. package/dist/p2mr/p2mr-output.d.ts.map +1 -0
  136. package/dist/p2mr/p2mr-output.js +150 -0
  137. package/dist/p2mr/ports.d.ts +52 -0
  138. package/dist/p2mr/ports.d.ts.map +1 -0
  139. package/dist/p2mr/ports.js +9 -0
  140. package/dist/p2mr/script-interpreter.d.ts +92 -0
  141. package/dist/p2mr/script-interpreter.d.ts.map +1 -0
  142. package/dist/p2mr/script-interpreter.js +535 -0
  143. package/dist/p2mr/script-leaf.d.ts +70 -0
  144. package/dist/p2mr/script-leaf.d.ts.map +1 -0
  145. package/dist/p2mr/script-leaf.js +203 -0
  146. package/dist/p2mr/spend-proof.d.ts +95 -0
  147. package/dist/p2mr/spend-proof.d.ts.map +1 -0
  148. package/dist/p2mr/spend-proof.js +358 -0
  149. package/dist/p2mr/types.d.ts +209 -0
  150. package/dist/p2mr/types.d.ts.map +1 -0
  151. package/dist/p2mr/types.js +9 -0
  152. package/dist/privacy/application/view-projector.d.ts +13 -0
  153. package/dist/privacy/application/view-projector.d.ts.map +1 -0
  154. package/dist/privacy/application/view-projector.js +85 -0
  155. package/dist/privacy/domain/entities.d.ts +26 -0
  156. package/dist/privacy/domain/entities.d.ts.map +1 -0
  157. package/dist/privacy/domain/entities.js +1 -0
  158. package/dist/privacy/domain/ports.d.ts +7 -0
  159. package/dist/privacy/domain/ports.d.ts.map +1 -0
  160. package/dist/privacy/domain/ports.js +1 -0
  161. package/dist/privacy/index.d.ts +21 -0
  162. package/dist/privacy/index.d.ts.map +1 -0
  163. package/dist/privacy/index.js +25 -0
  164. package/dist/privacy/infrastructure/in-memory-store.d.ts +8 -0
  165. package/dist/privacy/infrastructure/in-memory-store.d.ts.map +1 -0
  166. package/dist/privacy/infrastructure/in-memory-store.js +7 -0
  167. package/dist/protocols/besu-port.d.ts +80 -0
  168. package/dist/protocols/besu-port.d.ts.map +1 -0
  169. package/dist/protocols/besu-port.js +1 -0
  170. package/dist/protocols/corda-port.d.ts +103 -0
  171. package/dist/protocols/corda-port.d.ts.map +1 -0
  172. package/dist/protocols/corda-port.js +9 -0
  173. package/dist/protocols/credentialing-port.d.ts +11 -0
  174. package/dist/protocols/credentialing-port.d.ts.map +1 -0
  175. package/dist/protocols/credentialing-port.js +1 -0
  176. package/dist/protocols/fabric-port.d.ts +89 -0
  177. package/dist/protocols/fabric-port.d.ts.map +1 -0
  178. package/dist/protocols/fabric-port.js +9 -0
  179. package/dist/protocols/index.d.ts +14 -0
  180. package/dist/protocols/index.d.ts.map +1 -0
  181. package/dist/protocols/index.js +7 -0
  182. package/dist/protocols/p2mr-port.d.ts +159 -0
  183. package/dist/protocols/p2mr-port.d.ts.map +1 -0
  184. package/dist/protocols/p2mr-port.js +12 -0
  185. package/dist/protocols/privacy-port.d.ts +9 -0
  186. package/dist/protocols/privacy-port.d.ts.map +1 -0
  187. package/dist/protocols/privacy-port.js +1 -0
  188. package/dist/protocols/traceability-port.d.ts +12 -0
  189. package/dist/protocols/traceability-port.d.ts.map +1 -0
  190. package/dist/protocols/traceability-port.js +1 -0
  191. package/dist/shared/collection-store.d.ts +12 -0
  192. package/dist/shared/collection-store.d.ts.map +1 -0
  193. package/dist/shared/collection-store.js +26 -0
  194. package/dist/shared/commit.d.ts +24 -0
  195. package/dist/shared/commit.d.ts.map +1 -0
  196. package/dist/shared/commit.js +50 -0
  197. package/dist/shared/crypto.d.ts +2 -0
  198. package/dist/shared/crypto.d.ts.map +1 -0
  199. package/dist/shared/crypto.js +4 -0
  200. package/dist/shared/date.d.ts +2 -0
  201. package/dist/shared/date.d.ts.map +1 -0
  202. package/dist/shared/date.js +3 -0
  203. package/dist/shared/index.d.ts +9 -0
  204. package/dist/shared/index.d.ts.map +1 -0
  205. package/dist/shared/index.js +11 -0
  206. package/dist/shared/logger.d.ts +37 -0
  207. package/dist/shared/logger.d.ts.map +1 -0
  208. package/dist/shared/logger.js +45 -0
  209. package/dist/shared/store.d.ts +25 -0
  210. package/dist/shared/store.d.ts.map +1 -0
  211. package/dist/shared/store.js +18 -0
  212. package/dist/shared/telemetry-sdk.d.ts +26 -0
  213. package/dist/shared/telemetry-sdk.d.ts.map +1 -0
  214. package/dist/shared/telemetry-sdk.js +97 -0
  215. package/dist/shared/telemetry.d.ts +86 -0
  216. package/dist/shared/telemetry.d.ts.map +1 -0
  217. package/dist/shared/telemetry.js +137 -0
  218. package/dist/stark-settlement/application/aggregator-service.d.ts +112 -0
  219. package/dist/stark-settlement/application/aggregator-service.d.ts.map +1 -0
  220. package/dist/stark-settlement/application/aggregator-service.js +256 -0
  221. package/dist/stark-settlement/application/ledger-service.d.ts +114 -0
  222. package/dist/stark-settlement/application/ledger-service.d.ts.map +1 -0
  223. package/dist/stark-settlement/application/ledger-service.js +318 -0
  224. package/dist/stark-settlement/application/settlement-service.d.ts +104 -0
  225. package/dist/stark-settlement/application/settlement-service.d.ts.map +1 -0
  226. package/dist/stark-settlement/application/settlement-service.js +251 -0
  227. package/dist/stark-settlement/domain/entities.d.ts +365 -0
  228. package/dist/stark-settlement/domain/entities.d.ts.map +1 -0
  229. package/dist/stark-settlement/domain/entities.js +29 -0
  230. package/dist/stark-settlement/domain/ports.d.ts +485 -0
  231. package/dist/stark-settlement/domain/ports.d.ts.map +1 -0
  232. package/dist/stark-settlement/domain/ports.js +14 -0
  233. package/dist/stark-settlement/domain/value-objects.d.ts +268 -0
  234. package/dist/stark-settlement/domain/value-objects.d.ts.map +1 -0
  235. package/dist/stark-settlement/domain/value-objects.js +500 -0
  236. package/dist/stark-settlement/index.d.ts +172 -0
  237. package/dist/stark-settlement/index.d.ts.map +1 -0
  238. package/dist/stark-settlement/index.js +193 -0
  239. package/dist/stark-settlement/infrastructure/adapters/audit-adapter.d.ts +52 -0
  240. package/dist/stark-settlement/infrastructure/adapters/audit-adapter.d.ts.map +1 -0
  241. package/dist/stark-settlement/infrastructure/adapters/audit-adapter.js +154 -0
  242. package/dist/stark-settlement/infrastructure/adapters/bitcoin-adapter.d.ts +88 -0
  243. package/dist/stark-settlement/infrastructure/adapters/bitcoin-adapter.d.ts.map +1 -0
  244. package/dist/stark-settlement/infrastructure/adapters/bitcoin-adapter.js +187 -0
  245. package/dist/stark-settlement/infrastructure/adapters/clock-adapter.d.ts +59 -0
  246. package/dist/stark-settlement/infrastructure/adapters/clock-adapter.d.ts.map +1 -0
  247. package/dist/stark-settlement/infrastructure/adapters/clock-adapter.js +85 -0
  248. package/dist/stark-settlement/infrastructure/adapters/dilithium-adapter.d.ts +60 -0
  249. package/dist/stark-settlement/infrastructure/adapters/dilithium-adapter.d.ts.map +1 -0
  250. package/dist/stark-settlement/infrastructure/adapters/dilithium-adapter.js +104 -0
  251. package/dist/stark-settlement/infrastructure/adapters/event-emitter-adapter.d.ts +115 -0
  252. package/dist/stark-settlement/infrastructure/adapters/event-emitter-adapter.d.ts.map +1 -0
  253. package/dist/stark-settlement/infrastructure/adapters/event-emitter-adapter.js +191 -0
  254. package/dist/stark-settlement/infrastructure/adapters/fiat-adapter.d.ts +65 -0
  255. package/dist/stark-settlement/infrastructure/adapters/fiat-adapter.d.ts.map +1 -0
  256. package/dist/stark-settlement/infrastructure/adapters/fiat-adapter.js +207 -0
  257. package/dist/stark-settlement/infrastructure/adapters/mock-stark-adapter.d.ts +73 -0
  258. package/dist/stark-settlement/infrastructure/adapters/mock-stark-adapter.d.ts.map +1 -0
  259. package/dist/stark-settlement/infrastructure/adapters/mock-stark-adapter.js +287 -0
  260. package/dist/stark-settlement/infrastructure/adapters/solana-adapter.d.ts +78 -0
  261. package/dist/stark-settlement/infrastructure/adapters/solana-adapter.d.ts.map +1 -0
  262. package/dist/stark-settlement/infrastructure/adapters/solana-adapter.js +172 -0
  263. package/dist/stark-settlement/infrastructure/adapters/starknet-proof-adapter.d.ts +56 -0
  264. package/dist/stark-settlement/infrastructure/adapters/starknet-proof-adapter.d.ts.map +1 -0
  265. package/dist/stark-settlement/infrastructure/adapters/starknet-proof-adapter.js +261 -0
  266. package/dist/stark-settlement/infrastructure/adapters/stone-proof-adapter.d.ts +125 -0
  267. package/dist/stark-settlement/infrastructure/adapters/stone-proof-adapter.d.ts.map +1 -0
  268. package/dist/stark-settlement/infrastructure/adapters/stone-proof-adapter.js +416 -0
  269. package/dist/stark-settlement/infrastructure/persistence/ledger-store.d.ts +68 -0
  270. package/dist/stark-settlement/infrastructure/persistence/ledger-store.d.ts.map +1 -0
  271. package/dist/stark-settlement/infrastructure/persistence/ledger-store.js +238 -0
  272. package/dist/stark-settlement/infrastructure/persistence/offset-store.d.ts +30 -0
  273. package/dist/stark-settlement/infrastructure/persistence/offset-store.d.ts.map +1 -0
  274. package/dist/stark-settlement/infrastructure/persistence/offset-store.js +57 -0
  275. package/dist/stark-settlement/infrastructure/persistence/outbox-store.d.ts +45 -0
  276. package/dist/stark-settlement/infrastructure/persistence/outbox-store.d.ts.map +1 -0
  277. package/dist/stark-settlement/infrastructure/persistence/outbox-store.js +171 -0
  278. package/dist/traceability/application/recall-assessor.d.ts +13 -0
  279. package/dist/traceability/application/recall-assessor.d.ts.map +1 -0
  280. package/dist/traceability/application/recall-assessor.js +74 -0
  281. package/dist/traceability/domain/entities.d.ts +23 -0
  282. package/dist/traceability/domain/entities.d.ts.map +1 -0
  283. package/dist/traceability/domain/entities.js +1 -0
  284. package/dist/traceability/domain/ports.d.ts +23 -0
  285. package/dist/traceability/domain/ports.d.ts.map +1 -0
  286. package/dist/traceability/domain/ports.js +1 -0
  287. package/dist/traceability/domain/recall.d.ts +12 -0
  288. package/dist/traceability/domain/recall.d.ts.map +1 -0
  289. package/dist/traceability/domain/recall.js +1 -0
  290. package/dist/traceability/index.d.ts +22 -0
  291. package/dist/traceability/index.d.ts.map +1 -0
  292. package/dist/traceability/index.js +26 -0
  293. package/dist/traceability/infrastructure/in-memory-store.d.ts +13 -0
  294. package/dist/traceability/infrastructure/in-memory-store.d.ts.map +1 -0
  295. package/dist/traceability/infrastructure/in-memory-store.js +24 -0
  296. package/package.json +12 -9
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Script Leaf Creation and Validation
3
+ *
4
+ * Provides factory functions and validation for P2MR script leaves.
5
+ * Each leaf type has specific requirements for its parameters.
6
+ */
7
+ // ---------------------------------------------------------------------------
8
+ // Validation
9
+ // ---------------------------------------------------------------------------
10
+ /**
11
+ * Validate a public key hash format.
12
+ *
13
+ * @param hash - Hash to validate.
14
+ * @returns true if the hash is 64 hex characters.
15
+ */
16
+ function isValidPublicKeyHash(hash) {
17
+ return /^[a-f0-9]{64}$/i.test(hash);
18
+ }
19
+ /**
20
+ * Validate a script leaf for correctness.
21
+ *
22
+ * Checks:
23
+ * - Type is a valid ScriptLeafType
24
+ * - publicKeyHashes is non-empty and contains valid hashes
25
+ * - Condition-specific parameters are valid
26
+ *
27
+ * @param leaf - Script leaf to validate.
28
+ * @returns Validation result with error message if invalid.
29
+ */
30
+ export function validateScriptLeaf(leaf) {
31
+ // Validate type
32
+ const validTypes = [
33
+ "ml-dsa-65-sig",
34
+ "timelock",
35
+ "multisig-ml-dsa",
36
+ "hsm-attested-sig",
37
+ ];
38
+ if (!validTypes.includes(leaf.type)) {
39
+ return { valid: false, error: `Invalid script leaf type: ${leaf.type}` };
40
+ }
41
+ // Validate publicKeyHashes
42
+ if (!Array.isArray(leaf.publicKeyHashes) ||
43
+ leaf.publicKeyHashes.length === 0) {
44
+ return { valid: false, error: "publicKeyHashes must be a non-empty array" };
45
+ }
46
+ for (let i = 0; i < leaf.publicKeyHashes.length; i++) {
47
+ if (!isValidPublicKeyHash(leaf.publicKeyHashes[i])) {
48
+ return {
49
+ valid: false,
50
+ error: `Invalid public key hash at index ${i}: must be 64 hex characters`,
51
+ };
52
+ }
53
+ }
54
+ // Type-specific validation
55
+ switch (leaf.type) {
56
+ case "ml-dsa-65-sig":
57
+ // Single signature requires exactly one public key hash
58
+ if (leaf.publicKeyHashes.length !== 1) {
59
+ return {
60
+ valid: false,
61
+ error: "ml-dsa-65-sig requires exactly one public key hash",
62
+ };
63
+ }
64
+ break;
65
+ case "timelock":
66
+ // Timelock requires exactly one public key hash and a locktime
67
+ if (leaf.publicKeyHashes.length !== 1) {
68
+ return {
69
+ valid: false,
70
+ error: "timelock requires exactly one public key hash",
71
+ };
72
+ }
73
+ if (typeof leaf.locktime !== "number" || leaf.locktime < 0) {
74
+ return {
75
+ valid: false,
76
+ error: "timelock requires a non-negative locktime",
77
+ };
78
+ }
79
+ break;
80
+ case "multisig-ml-dsa": {
81
+ // Multisig requires at least 2 public key hashes and valid threshold
82
+ if (leaf.publicKeyHashes.length < 2) {
83
+ return {
84
+ valid: false,
85
+ error: "multisig-ml-dsa requires at least 2 public key hashes",
86
+ };
87
+ }
88
+ const threshold = leaf.threshold ?? leaf.publicKeyHashes.length;
89
+ if (threshold < 1 || threshold > leaf.publicKeyHashes.length) {
90
+ return {
91
+ valid: false,
92
+ error: `threshold must be between 1 and ${leaf.publicKeyHashes.length}`,
93
+ };
94
+ }
95
+ break;
96
+ }
97
+ case "hsm-attested-sig":
98
+ // HSM-attested requires exactly one public key hash and an HSM slot ID
99
+ if (leaf.publicKeyHashes.length !== 1) {
100
+ return {
101
+ valid: false,
102
+ error: "hsm-attested-sig requires exactly one public key hash",
103
+ };
104
+ }
105
+ if (typeof leaf.hsmSlotId !== "string" || leaf.hsmSlotId.length === 0) {
106
+ return {
107
+ valid: false,
108
+ error: "hsm-attested-sig requires a non-empty hsmSlotId",
109
+ };
110
+ }
111
+ break;
112
+ }
113
+ return { valid: true };
114
+ }
115
+ // ---------------------------------------------------------------------------
116
+ // Factory Functions
117
+ // ---------------------------------------------------------------------------
118
+ /**
119
+ * Create a simple ML-DSA-65 signature leaf.
120
+ *
121
+ * Requires a single valid signature from the specified public key.
122
+ *
123
+ * @param publicKeyHash - SHA-256 hash of the authorized ML-DSA-65 public key.
124
+ * @returns A validated ScriptLeaf.
125
+ * @throws Error if the hash is invalid.
126
+ */
127
+ export function createSingleSigLeaf(publicKeyHash) {
128
+ const leaf = {
129
+ type: "ml-dsa-65-sig",
130
+ publicKeyHashes: [publicKeyHash],
131
+ };
132
+ const result = validateScriptLeaf(leaf);
133
+ if (!result.valid) {
134
+ throw new Error(result.error);
135
+ }
136
+ return leaf;
137
+ }
138
+ /**
139
+ * Create a time-locked signature leaf.
140
+ *
141
+ * Requires a valid signature from the specified public key, but only after
142
+ * the locktime has passed.
143
+ *
144
+ * @param publicKeyHash - SHA-256 hash of the authorized ML-DSA-65 public key.
145
+ * @param locktime - Unix timestamp (ms) after which spending is allowed.
146
+ * @returns A validated ScriptLeaf.
147
+ * @throws Error if parameters are invalid.
148
+ */
149
+ export function createTimelockLeaf(publicKeyHash, locktime) {
150
+ const leaf = {
151
+ type: "timelock",
152
+ publicKeyHashes: [publicKeyHash],
153
+ locktime,
154
+ };
155
+ const result = validateScriptLeaf(leaf);
156
+ if (!result.valid) {
157
+ throw new Error(result.error);
158
+ }
159
+ return leaf;
160
+ }
161
+ /**
162
+ * Create a multisig leaf requiring k-of-n signatures.
163
+ *
164
+ * @param publicKeyHashes - SHA-256 hashes of all authorized ML-DSA-65 public keys.
165
+ * @param threshold - Minimum number of valid signatures required.
166
+ * @returns A validated ScriptLeaf.
167
+ * @throws Error if parameters are invalid.
168
+ */
169
+ export function createMultisigLeaf(publicKeyHashes, threshold) {
170
+ const leaf = {
171
+ type: "multisig-ml-dsa",
172
+ publicKeyHashes: [...publicKeyHashes],
173
+ threshold,
174
+ };
175
+ const result = validateScriptLeaf(leaf);
176
+ if (!result.valid) {
177
+ throw new Error(result.error);
178
+ }
179
+ return leaf;
180
+ }
181
+ /**
182
+ * Create an HSM-attested signature leaf.
183
+ *
184
+ * Requires a valid signature from the specified public key, plus attestation
185
+ * proof that the signature was produced by the specified HSM slot.
186
+ *
187
+ * @param publicKeyHash - SHA-256 hash of the authorized ML-DSA-65 public key.
188
+ * @param hsmSlotId - Identifier of the required HSM slot.
189
+ * @returns A validated ScriptLeaf.
190
+ * @throws Error if parameters are invalid.
191
+ */
192
+ export function createHsmAttestedLeaf(publicKeyHash, hsmSlotId) {
193
+ const leaf = {
194
+ type: "hsm-attested-sig",
195
+ publicKeyHashes: [publicKeyHash],
196
+ hsmSlotId,
197
+ };
198
+ const result = validateScriptLeaf(leaf);
199
+ if (!result.valid) {
200
+ throw new Error(result.error);
201
+ }
202
+ return leaf;
203
+ }
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Spend Proof Construction and Validation
3
+ *
4
+ * Provides functions for building and validating spend proofs.
5
+ * A spend proof demonstrates that:
6
+ * 1. The revealed leaf hashes to the output's Merkle root
7
+ * 2. The witness satisfies the leaf's spending condition
8
+ */
9
+ import type { P2MROutput, SpendProof, SpendWitness, SpendVerificationResult } from "./types.js";
10
+ import { MerkleTree } from "./merkle-tree.js";
11
+ /**
12
+ * Options for building a spend proof.
13
+ */
14
+ export interface BuildSpendProofOptions {
15
+ /**
16
+ * ID of the output being spent.
17
+ */
18
+ outputId: string;
19
+ /**
20
+ * The Merkle tree containing the spending conditions.
21
+ * This must be the same tree used to create the output.
22
+ */
23
+ tree: MerkleTree;
24
+ /**
25
+ * Index of the leaf (spending condition) to use.
26
+ */
27
+ leafIndex: number;
28
+ /**
29
+ * Witness data satisfying the spending condition.
30
+ */
31
+ witness: SpendWitness;
32
+ }
33
+ /**
34
+ * Build a spend proof for a P2MR output.
35
+ *
36
+ * The proof consists of:
37
+ * 1. The output ID being spent
38
+ * 2. The revealed script leaf (spending condition)
39
+ * 3. A Merkle proof from the leaf to the root
40
+ * 4. Witness data (public keys, signatures, etc.)
41
+ *
42
+ * @param options - Spend proof options.
43
+ * @returns A complete spend proof.
44
+ * @throws Error if leaf index is out of bounds.
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * const proof = buildSpendProof({
49
+ * outputId: output.outputId,
50
+ * tree: merkleTree,
51
+ * leafIndex: 0,
52
+ * witness: {
53
+ * publicKeys: [myPublicKey],
54
+ * signatures: [mySignature],
55
+ * },
56
+ * });
57
+ * ```
58
+ */
59
+ export declare function buildSpendProof(options: BuildSpendProofOptions): SpendProof;
60
+ /**
61
+ * Validate the structural correctness of a spend proof.
62
+ *
63
+ * This performs preliminary checks that don't require cryptographic
64
+ * signature verification. Full validation requires the script interpreter.
65
+ *
66
+ * Checks:
67
+ * 1. Output ID is present
68
+ * 2. Revealed leaf passes structural validation
69
+ * 3. Merkle proof is structurally valid
70
+ * 4. Witness has required fields for the leaf type
71
+ *
72
+ * @param proof - The spend proof to validate.
73
+ * @returns Validation result with error if invalid.
74
+ */
75
+ export declare function validateSpendProofStructure(proof: SpendProof): SpendVerificationResult;
76
+ /**
77
+ * Verify that a spend proof's Merkle path leads to the expected root.
78
+ *
79
+ * @param proof - The spend proof.
80
+ * @param expectedRoot - The Merkle root from the P2MR output.
81
+ * @returns Verification result.
82
+ */
83
+ export declare function verifyMerkleProof(proof: SpendProof, expectedRoot: string): SpendVerificationResult;
84
+ /**
85
+ * Perform full structural and Merkle verification of a spend proof.
86
+ *
87
+ * This does NOT verify signatures - that requires the script interpreter
88
+ * which is implemented separately.
89
+ *
90
+ * @param proof - The spend proof.
91
+ * @param output - The P2MR output being spent.
92
+ * @returns Verification result.
93
+ */
94
+ export declare function verifySpendProofStructure(proof: SpendProof, output: P2MROutput): SpendVerificationResult;
95
+ //# sourceMappingURL=spend-proof.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spend-proof.d.ts","sourceRoot":"","sources":["../../src/p2mr/spend-proof.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,UAAU,EAEV,UAAU,EACV,YAAY,EAEZ,uBAAuB,EAExB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,UAAU,EAAkB,MAAM,kBAAkB,CAAC;AAO9D;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,IAAI,EAAE,UAAU,CAAC;IAEjB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,OAAO,EAAE,YAAY,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,UAAU,CAmB3E;AAMD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,UAAU,GAChB,uBAAuB,CA0GzB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,UAAU,EACjB,YAAY,EAAE,MAAM,GACnB,uBAAuB,CA0CzB;AAED;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,UAAU,GACjB,uBAAuB,CAiDzB"}
@@ -0,0 +1,358 @@
1
+ /**
2
+ * Spend Proof Construction and Validation
3
+ *
4
+ * Provides functions for building and validating spend proofs.
5
+ * A spend proof demonstrates that:
6
+ * 1. The revealed leaf hashes to the output's Merkle root
7
+ * 2. The witness satisfies the leaf's spending condition
8
+ */
9
+ import { MerkleTree, hashScriptLeaf } from "./merkle-tree.js";
10
+ import { validateScriptLeaf } from "./script-leaf.js";
11
+ /**
12
+ * Build a spend proof for a P2MR output.
13
+ *
14
+ * The proof consists of:
15
+ * 1. The output ID being spent
16
+ * 2. The revealed script leaf (spending condition)
17
+ * 3. A Merkle proof from the leaf to the root
18
+ * 4. Witness data (public keys, signatures, etc.)
19
+ *
20
+ * @param options - Spend proof options.
21
+ * @returns A complete spend proof.
22
+ * @throws Error if leaf index is out of bounds.
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * const proof = buildSpendProof({
27
+ * outputId: output.outputId,
28
+ * tree: merkleTree,
29
+ * leafIndex: 0,
30
+ * witness: {
31
+ * publicKeys: [myPublicKey],
32
+ * signatures: [mySignature],
33
+ * },
34
+ * });
35
+ * ```
36
+ */
37
+ export function buildSpendProof(options) {
38
+ const { outputId, tree, leafIndex, witness } = options;
39
+ const leaves = tree.leaves;
40
+ if (leafIndex < 0 || leafIndex >= leaves.length) {
41
+ throw new Error(`Leaf index ${leafIndex} out of bounds [0, ${leaves.length - 1}]`);
42
+ }
43
+ const revealedLeaf = leaves[leafIndex];
44
+ const merkleProof = tree.getProof(leafIndex);
45
+ return {
46
+ outputId,
47
+ revealedLeaf,
48
+ merkleProof,
49
+ witness,
50
+ };
51
+ }
52
+ // ---------------------------------------------------------------------------
53
+ // Spend Proof Validation (Structural)
54
+ // ---------------------------------------------------------------------------
55
+ /**
56
+ * Validate the structural correctness of a spend proof.
57
+ *
58
+ * This performs preliminary checks that don't require cryptographic
59
+ * signature verification. Full validation requires the script interpreter.
60
+ *
61
+ * Checks:
62
+ * 1. Output ID is present
63
+ * 2. Revealed leaf passes structural validation
64
+ * 3. Merkle proof is structurally valid
65
+ * 4. Witness has required fields for the leaf type
66
+ *
67
+ * @param proof - The spend proof to validate.
68
+ * @returns Validation result with error if invalid.
69
+ */
70
+ export function validateSpendProofStructure(proof) {
71
+ const auditTrail = [];
72
+ // Step 1: Validate output ID
73
+ if (!proof.outputId || proof.outputId.length === 0) {
74
+ auditTrail.push({
75
+ step: "Output ID check",
76
+ passed: false,
77
+ detail: "Output ID is required",
78
+ });
79
+ return {
80
+ valid: false,
81
+ reason: "Missing output ID",
82
+ auditTrail,
83
+ };
84
+ }
85
+ auditTrail.push({
86
+ step: "Output ID check",
87
+ passed: true,
88
+ detail: `Output ID: ${proof.outputId}`,
89
+ });
90
+ // Step 2: Validate revealed leaf structure
91
+ const leafResult = validateScriptLeaf(proof.revealedLeaf);
92
+ if (!leafResult.valid) {
93
+ const errorMsg = leafResult.error ?? "Unknown validation error";
94
+ auditTrail.push({
95
+ step: "Leaf structure check",
96
+ passed: false,
97
+ detail: errorMsg,
98
+ });
99
+ return {
100
+ valid: false,
101
+ reason: `Invalid leaf: ${errorMsg}`,
102
+ auditTrail,
103
+ };
104
+ }
105
+ auditTrail.push({
106
+ step: "Leaf structure check",
107
+ passed: true,
108
+ detail: `Type: ${proof.revealedLeaf.type}`,
109
+ });
110
+ // Step 3: Validate Merkle proof structure
111
+ if (!Array.isArray(proof.merkleProof)) {
112
+ auditTrail.push({
113
+ step: "Merkle proof structure",
114
+ passed: false,
115
+ detail: "Merkle proof must be an array",
116
+ });
117
+ return {
118
+ valid: false,
119
+ reason: "Invalid Merkle proof structure",
120
+ auditTrail,
121
+ };
122
+ }
123
+ for (let i = 0; i < proof.merkleProof.length; i++) {
124
+ const node = proof.merkleProof[i];
125
+ if (!isValidMerkleProofNode(node)) {
126
+ auditTrail.push({
127
+ step: `Merkle proof node ${i}`,
128
+ passed: false,
129
+ detail: "Invalid node structure",
130
+ });
131
+ return {
132
+ valid: false,
133
+ reason: `Invalid Merkle proof node at index ${i}`,
134
+ auditTrail,
135
+ };
136
+ }
137
+ }
138
+ auditTrail.push({
139
+ step: "Merkle proof structure",
140
+ passed: true,
141
+ detail: `Proof length: ${proof.merkleProof.length}`,
142
+ });
143
+ // Step 4: Validate witness structure for leaf type
144
+ const witnessResult = validateWitnessStructure(proof.revealedLeaf, proof.witness);
145
+ if (!witnessResult.valid) {
146
+ auditTrail.push({
147
+ step: "Witness structure check",
148
+ passed: false,
149
+ detail: witnessResult.reason,
150
+ });
151
+ return {
152
+ valid: false,
153
+ reason: witnessResult.reason,
154
+ auditTrail,
155
+ };
156
+ }
157
+ auditTrail.push({
158
+ step: "Witness structure check",
159
+ passed: true,
160
+ detail: `${proof.witness.publicKeys.length} keys, ${proof.witness.signatures.length} signatures`,
161
+ });
162
+ return {
163
+ valid: true,
164
+ reason: "Spend proof structure is valid",
165
+ auditTrail,
166
+ };
167
+ }
168
+ /**
169
+ * Verify that a spend proof's Merkle path leads to the expected root.
170
+ *
171
+ * @param proof - The spend proof.
172
+ * @param expectedRoot - The Merkle root from the P2MR output.
173
+ * @returns Verification result.
174
+ */
175
+ export function verifyMerkleProof(proof, expectedRoot) {
176
+ const auditTrail = [];
177
+ // Compute leaf hash
178
+ const leafHash = hashScriptLeaf(proof.revealedLeaf);
179
+ auditTrail.push({
180
+ step: "Compute leaf hash",
181
+ passed: true,
182
+ detail: `Hash: ${leafHash.substring(0, 16)}...`,
183
+ });
184
+ // Verify Merkle path
185
+ const verified = MerkleTree.verify(proof.revealedLeaf, proof.merkleProof, expectedRoot);
186
+ if (!verified) {
187
+ auditTrail.push({
188
+ step: "Merkle path verification",
189
+ passed: false,
190
+ detail: `Expected root: ${expectedRoot.substring(0, 16)}...`,
191
+ });
192
+ return {
193
+ valid: false,
194
+ reason: "Merkle proof does not verify to expected root",
195
+ auditTrail,
196
+ };
197
+ }
198
+ auditTrail.push({
199
+ step: "Merkle path verification",
200
+ passed: true,
201
+ detail: `Root: ${expectedRoot.substring(0, 16)}...`,
202
+ });
203
+ return {
204
+ valid: true,
205
+ reason: "Merkle proof verified successfully",
206
+ auditTrail,
207
+ };
208
+ }
209
+ /**
210
+ * Perform full structural and Merkle verification of a spend proof.
211
+ *
212
+ * This does NOT verify signatures - that requires the script interpreter
213
+ * which is implemented separately.
214
+ *
215
+ * @param proof - The spend proof.
216
+ * @param output - The P2MR output being spent.
217
+ * @returns Verification result.
218
+ */
219
+ export function verifySpendProofStructure(proof, output) {
220
+ const auditTrail = [];
221
+ // Step 1: Verify output ID matches
222
+ if (proof.outputId !== output.outputId) {
223
+ auditTrail.push({
224
+ step: "Output ID match",
225
+ passed: false,
226
+ detail: `Proof: ${proof.outputId}, Output: ${output.outputId}`,
227
+ });
228
+ return {
229
+ valid: false,
230
+ reason: "Spend proof output ID does not match output",
231
+ auditTrail,
232
+ };
233
+ }
234
+ auditTrail.push({
235
+ step: "Output ID match",
236
+ passed: true,
237
+ detail: output.outputId,
238
+ });
239
+ // Step 2: Validate proof structure
240
+ const structureResult = validateSpendProofStructure(proof);
241
+ auditTrail.push(...(structureResult.auditTrail ?? []));
242
+ if (!structureResult.valid) {
243
+ return {
244
+ valid: false,
245
+ reason: structureResult.reason,
246
+ auditTrail,
247
+ };
248
+ }
249
+ // Step 3: Verify Merkle proof
250
+ const merkleResult = verifyMerkleProof(proof, output.merkleRoot);
251
+ auditTrail.push(...(merkleResult.auditTrail ?? []));
252
+ if (!merkleResult.valid) {
253
+ return {
254
+ valid: false,
255
+ reason: merkleResult.reason,
256
+ auditTrail,
257
+ };
258
+ }
259
+ return {
260
+ valid: true,
261
+ reason: "Spend proof structure and Merkle path verified",
262
+ auditTrail,
263
+ };
264
+ }
265
+ // ---------------------------------------------------------------------------
266
+ // Helper Functions
267
+ // ---------------------------------------------------------------------------
268
+ /**
269
+ * Check if a value is a valid MerkleProofNode.
270
+ */
271
+ function isValidMerkleProofNode(node) {
272
+ if (typeof node !== "object" || node === null) {
273
+ return false;
274
+ }
275
+ const n = node;
276
+ if (typeof n.hash !== "string" || !/^[a-f0-9]{64}$/i.test(n.hash)) {
277
+ return false;
278
+ }
279
+ if (n.position !== "left" && n.position !== "right") {
280
+ return false;
281
+ }
282
+ return true;
283
+ }
284
+ /**
285
+ * Validate witness structure for a given leaf type.
286
+ */
287
+ function validateWitnessStructure(leaf, witness) {
288
+ // Check basic witness requirements
289
+ if (!Array.isArray(witness.publicKeys) || witness.publicKeys.length === 0) {
290
+ return {
291
+ valid: false,
292
+ reason: "Witness must include at least one public key",
293
+ };
294
+ }
295
+ if (!Array.isArray(witness.signatures) || witness.signatures.length === 0) {
296
+ return {
297
+ valid: false,
298
+ reason: "Witness must include at least one signature",
299
+ };
300
+ }
301
+ // Type-specific validation
302
+ switch (leaf.type) {
303
+ case "ml-dsa-65-sig":
304
+ if (witness.publicKeys.length !== 1 || witness.signatures.length !== 1) {
305
+ return {
306
+ valid: false,
307
+ reason: "ml-dsa-65-sig requires exactly 1 public key and 1 signature",
308
+ };
309
+ }
310
+ break;
311
+ case "timelock":
312
+ if (witness.publicKeys.length !== 1 || witness.signatures.length !== 1) {
313
+ return {
314
+ valid: false,
315
+ reason: "timelock requires exactly 1 public key and 1 signature",
316
+ };
317
+ }
318
+ if (typeof witness.timestamp !== "number") {
319
+ return {
320
+ valid: false,
321
+ reason: "timelock requires a timestamp in the witness",
322
+ };
323
+ }
324
+ break;
325
+ case "multisig-ml-dsa": {
326
+ const threshold = leaf.threshold ?? leaf.publicKeyHashes.length;
327
+ if (witness.signatures.length < threshold) {
328
+ return {
329
+ valid: false,
330
+ reason: `multisig-ml-dsa requires at least ${threshold} signatures`,
331
+ };
332
+ }
333
+ if (witness.publicKeys.length < threshold) {
334
+ return {
335
+ valid: false,
336
+ reason: `multisig-ml-dsa requires at least ${threshold} public keys`,
337
+ };
338
+ }
339
+ break;
340
+ }
341
+ case "hsm-attested-sig":
342
+ if (witness.publicKeys.length !== 1 || witness.signatures.length !== 1) {
343
+ return {
344
+ valid: false,
345
+ reason: "hsm-attested-sig requires exactly 1 public key and 1 signature",
346
+ };
347
+ }
348
+ if (typeof witness.hsmAttestation !== "string" ||
349
+ witness.hsmAttestation.length === 0) {
350
+ return {
351
+ valid: false,
352
+ reason: "hsm-attested-sig requires HSM attestation in the witness",
353
+ };
354
+ }
355
+ break;
356
+ }
357
+ return { valid: true, reason: "Witness structure valid" };
358
+ }