@degenerate/generic 0.4.0 → 0.7.0

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 (166) hide show
  1. package/dist/_settings/cryptography-settings.d.ts +5 -1
  2. package/dist/_settings/cryptography-settings.d.ts.map +1 -1
  3. package/dist/_settings/cryptography-settings.js +5 -1
  4. package/dist/crypto/index.d.ts +5 -9
  5. package/dist/crypto/index.d.ts.map +1 -1
  6. package/dist/crypto/index.js +7 -9
  7. package/dist/crypto/private-public-keys/create-ed25519-keys-from-mnemonic.d.ts +22 -0
  8. package/dist/crypto/private-public-keys/create-ed25519-keys-from-mnemonic.d.ts.map +1 -0
  9. package/dist/crypto/private-public-keys/create-ed25519-keys-from-mnemonic.js +65 -0
  10. package/dist/crypto/private-public-keys/get-ed25519-public-key-from-private-key.d.ts +11 -0
  11. package/dist/crypto/private-public-keys/get-ed25519-public-key-from-private-key.d.ts.map +1 -0
  12. package/dist/crypto/private-public-keys/get-ed25519-public-key-from-private-key.js +15 -0
  13. package/dist/crypto/signature/create-ed25519-signature.d.ts +16 -0
  14. package/dist/crypto/signature/create-ed25519-signature.d.ts.map +1 -0
  15. package/dist/crypto/signature/create-ed25519-signature.js +26 -0
  16. package/dist/crypto/signature/ed25519-primitives.d.ts +25 -0
  17. package/dist/crypto/signature/ed25519-primitives.d.ts.map +1 -0
  18. package/dist/crypto/signature/ed25519-primitives.js +65 -0
  19. package/dist/crypto/signature/verify-ed25519-signature.d.ts +13 -0
  20. package/dist/crypto/signature/verify-ed25519-signature.d.ts.map +1 -0
  21. package/dist/crypto/signature/verify-ed25519-signature.js +31 -0
  22. package/dist/errors/index.d.ts +2 -0
  23. package/dist/errors/index.d.ts.map +1 -1
  24. package/dist/errors/index.js +2 -0
  25. package/dist/errors/library/library-errors.d.ts +101 -0
  26. package/dist/errors/library/library-errors.d.ts.map +1 -0
  27. package/dist/errors/library/library-errors.js +133 -0
  28. package/dist/errors/settlement/settlement-errors.d.ts +74 -0
  29. package/dist/errors/settlement/settlement-errors.d.ts.map +1 -0
  30. package/dist/errors/settlement/settlement-errors.js +93 -0
  31. package/dist/errors/share-data/share-data-errors.d.ts +21 -0
  32. package/dist/errors/share-data/share-data-errors.d.ts.map +1 -1
  33. package/dist/errors/share-data/share-data-errors.js +30 -1
  34. package/dist/helpers/apply-share-function.d.ts +23 -0
  35. package/dist/helpers/apply-share-function.d.ts.map +1 -0
  36. package/dist/helpers/apply-share-function.js +32 -0
  37. package/dist/helpers/index.d.ts +1 -0
  38. package/dist/helpers/index.d.ts.map +1 -1
  39. package/dist/helpers/index.js +1 -0
  40. package/dist/index.d.ts +2 -0
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +2 -0
  43. package/dist/library/authorize-library.d.ts +17 -0
  44. package/dist/library/authorize-library.d.ts.map +1 -0
  45. package/dist/library/authorize-library.js +39 -0
  46. package/dist/library/build-library.d.ts +49 -0
  47. package/dist/library/build-library.d.ts.map +1 -0
  48. package/dist/library/build-library.js +119 -0
  49. package/dist/library/caching-library-store.d.ts +19 -0
  50. package/dist/library/caching-library-store.d.ts.map +1 -0
  51. package/dist/library/caching-library-store.js +56 -0
  52. package/dist/library/canonical-json.d.ts +12 -0
  53. package/dist/library/canonical-json.d.ts.map +1 -0
  54. package/dist/library/canonical-json.js +30 -0
  55. package/dist/library/compile-rule-source.d.ts +21 -0
  56. package/dist/library/compile-rule-source.d.ts.map +1 -0
  57. package/dist/library/compile-rule-source.js +91 -0
  58. package/dist/library/evaluate-library-rules.d.ts +36 -0
  59. package/dist/library/evaluate-library-rules.d.ts.map +1 -0
  60. package/dist/library/evaluate-library-rules.js +47 -0
  61. package/dist/library/evaluate-library.d.ts +34 -0
  62. package/dist/library/evaluate-library.d.ts.map +1 -0
  63. package/dist/library/evaluate-library.js +66 -0
  64. package/dist/library/in-memory-library-store.d.ts +22 -0
  65. package/dist/library/in-memory-library-store.d.ts.map +1 -0
  66. package/dist/library/in-memory-library-store.js +92 -0
  67. package/dist/library/index.d.ts +18 -0
  68. package/dist/library/index.d.ts.map +1 -0
  69. package/dist/library/index.js +33 -0
  70. package/dist/library/library-hash.d.ts +9 -0
  71. package/dist/library/library-hash.d.ts.map +1 -0
  72. package/dist/library/library-hash.js +14 -0
  73. package/dist/library/library-models.d.ts +134 -0
  74. package/dist/library/library-models.d.ts.map +1 -0
  75. package/dist/library/library-models.js +84 -0
  76. package/dist/library/library-proof.d.ts +40 -0
  77. package/dist/library/library-proof.d.ts.map +1 -0
  78. package/dist/library/library-proof.js +44 -0
  79. package/dist/library/library-reference.d.ts +75 -0
  80. package/dist/library/library-reference.d.ts.map +1 -0
  81. package/dist/library/library-reference.js +98 -0
  82. package/dist/library/library-server.d.ts +17 -0
  83. package/dist/library/library-server.d.ts.map +1 -0
  84. package/dist/library/library-server.js +45 -0
  85. package/dist/library/library-store.d.ts +37 -0
  86. package/dist/library/library-store.d.ts.map +1 -0
  87. package/dist/library/library-store.js +2 -0
  88. package/dist/library/remote-library-models.d.ts +54 -0
  89. package/dist/library/remote-library-models.d.ts.map +1 -0
  90. package/dist/library/remote-library-models.js +2 -0
  91. package/dist/library/remote-library-store.d.ts +15 -0
  92. package/dist/library/remote-library-store.d.ts.map +1 -0
  93. package/dist/library/remote-library-store.js +59 -0
  94. package/dist/library/verify-library.d.ts +21 -0
  95. package/dist/library/verify-library.d.ts.map +1 -0
  96. package/dist/library/verify-library.js +86 -0
  97. package/dist/models/functions/share-data-function-models.d.ts +6 -74
  98. package/dist/models/functions/share-data-function-models.d.ts.map +1 -1
  99. package/dist/models/functions/share-data-function-models.js +7 -65
  100. package/dist/models/index.d.ts +1 -0
  101. package/dist/models/index.d.ts.map +1 -1
  102. package/dist/models/index.js +1 -0
  103. package/dist/models/safe/transactions/sharedata-transactions-models.d.ts +5 -0
  104. package/dist/models/safe/transactions/sharedata-transactions-models.d.ts.map +1 -1
  105. package/dist/models/settlement/settlement-models.d.ts +221 -0
  106. package/dist/models/settlement/settlement-models.d.ts.map +1 -0
  107. package/dist/models/settlement/settlement-models.js +152 -0
  108. package/dist/models/share-data/share-data-models.d.ts +12 -0
  109. package/dist/models/share-data/share-data-models.d.ts.map +1 -1
  110. package/dist/models/share-data/share-data-persistence-models.d.ts +3 -0
  111. package/dist/models/share-data/share-data-persistence-models.d.ts.map +1 -1
  112. package/dist/models/shareblock/shareblock-models.d.ts +179 -3
  113. package/dist/models/shareblock/shareblock-models.d.ts.map +1 -1
  114. package/dist/models/shareblock/shareblock-models.js +99 -7
  115. package/dist/sandbox/in-process-executor.d.ts +13 -0
  116. package/dist/sandbox/in-process-executor.d.ts.map +1 -0
  117. package/dist/sandbox/in-process-executor.js +31 -0
  118. package/dist/sandbox/index.d.ts +8 -0
  119. package/dist/sandbox/index.d.ts.map +1 -0
  120. package/dist/sandbox/index.js +23 -0
  121. package/dist/sandbox/remote-sandbox-executor.d.ts +12 -0
  122. package/dist/sandbox/remote-sandbox-executor.d.ts.map +1 -0
  123. package/dist/sandbox/remote-sandbox-executor.js +49 -0
  124. package/dist/sandbox/remote-sandbox-models.d.ts +37 -0
  125. package/dist/sandbox/remote-sandbox-models.d.ts.map +1 -0
  126. package/dist/sandbox/remote-sandbox-models.js +2 -0
  127. package/dist/sandbox/rule-evaluator.d.ts +32 -0
  128. package/dist/sandbox/rule-evaluator.d.ts.map +1 -0
  129. package/dist/sandbox/rule-evaluator.js +23 -0
  130. package/dist/sandbox/run-sandboxed.d.ts +24 -0
  131. package/dist/sandbox/run-sandboxed.d.ts.map +1 -0
  132. package/dist/sandbox/run-sandboxed.js +88 -0
  133. package/dist/sandbox/sandbox-models.d.ts +40 -0
  134. package/dist/sandbox/sandbox-models.d.ts.map +1 -0
  135. package/dist/sandbox/sandbox-models.js +2 -0
  136. package/dist/sandbox/sandbox-server.d.ts +22 -0
  137. package/dist/sandbox/sandbox-server.d.ts.map +1 -0
  138. package/dist/sandbox/sandbox-server.js +62 -0
  139. package/package.json +3 -4
  140. package/dist/crypto/private-public-keys/create-key-pair-from-mnemonic.d.ts +0 -12
  141. package/dist/crypto/private-public-keys/create-key-pair-from-mnemonic.d.ts.map +0 -1
  142. package/dist/crypto/private-public-keys/create-key-pair-from-mnemonic.js +0 -54
  143. package/dist/crypto/private-public-keys/create-key-pair-from-private-key.d.ts +0 -11
  144. package/dist/crypto/private-public-keys/create-key-pair-from-private-key.d.ts.map +0 -1
  145. package/dist/crypto/private-public-keys/create-key-pair-from-private-key.js +0 -50
  146. package/dist/crypto/private-public-keys/create-key-pair-from-public-key.d.ts +0 -11
  147. package/dist/crypto/private-public-keys/create-key-pair-from-public-key.d.ts.map +0 -1
  148. package/dist/crypto/private-public-keys/create-key-pair-from-public-key.js +0 -51
  149. package/dist/crypto/private-public-keys/generation/create-entropy-for-elliptical-curve.d.ts +0 -10
  150. package/dist/crypto/private-public-keys/generation/create-entropy-for-elliptical-curve.d.ts.map +0 -1
  151. package/dist/crypto/private-public-keys/generation/create-entropy-for-elliptical-curve.js +0 -51
  152. package/dist/crypto/private-public-keys/generation/generate-key-pair.d.ts +0 -11
  153. package/dist/crypto/private-public-keys/generation/generate-key-pair.d.ts.map +0 -1
  154. package/dist/crypto/private-public-keys/generation/generate-key-pair.js +0 -49
  155. package/dist/crypto/private-public-keys/generation/get-private-public-key-from-keypair.d.ts +0 -15
  156. package/dist/crypto/private-public-keys/generation/get-private-public-key-from-keypair.d.ts.map +0 -1
  157. package/dist/crypto/private-public-keys/generation/get-private-public-key-from-keypair.js +0 -21
  158. package/dist/crypto/signature/create-crypto-signature.d.ts +0 -20
  159. package/dist/crypto/signature/create-crypto-signature.d.ts.map +0 -1
  160. package/dist/crypto/signature/create-crypto-signature.js +0 -26
  161. package/dist/crypto/signature/verify-crypto-signature-by-data.d.ts +0 -17
  162. package/dist/crypto/signature/verify-crypto-signature-by-data.d.ts.map +0 -1
  163. package/dist/crypto/signature/verify-crypto-signature-by-data.js +0 -61
  164. package/dist/crypto/signature/verify-crypto-signature-by-hash.d.ts +0 -17
  165. package/dist/crypto/signature/verify-crypto-signature-by-hash.d.ts.map +0 -1
  166. package/dist/crypto/signature/verify-crypto-signature-by-hash.js +0 -58
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.appendLibraryVersion = exports.addLibraryDelegate = exports.createLibraryEntity = void 0;
4
+ const create_ed25519_signature_1 = require("../crypto/signature/create-ed25519-signature");
5
+ const get_ed25519_public_key_from_private_key_1 = require("../crypto/private-public-keys/get-ed25519-public-key-from-private-key");
6
+ const library_errors_1 = require("../errors/library/library-errors");
7
+ const authorize_library_1 = require("./authorize-library");
8
+ const library_hash_1 = require("./library-hash");
9
+ const library_models_1 = require("./library-models");
10
+ const library_proof_1 = require("./library-proof");
11
+ const assertGasLimit = (gasLimit) => {
12
+ if (!Number.isInteger(gasLimit) || gasLimit < 1 || gasLimit > library_models_1.MAX_GAS_UNITS) {
13
+ throw new library_errors_1.LibraryEntityInvalidError(`gasLimit must be an integer in [1, ${library_models_1.MAX_GAS_UNITS}] (got ${gasLimit})`);
14
+ }
15
+ };
16
+ const signVersion = (kind, id, source, previousHash, createdAt, privateKey, publicKey) => {
17
+ const currentHash = (0, library_hash_1.computeVersionHash)(source, previousHash);
18
+ const payload = (0, library_proof_1.buildVersionProofPayload)({
19
+ id,
20
+ currentHash,
21
+ previousHash,
22
+ createdAt,
23
+ purpose: (0, library_proof_1.versionPurpose)(kind),
24
+ publicKey,
25
+ });
26
+ return {
27
+ createdAt,
28
+ previousHash,
29
+ source,
30
+ currentHash,
31
+ proof: { publicKey, signature: (0, create_ed25519_signature_1.createEd25519Signature)(privateKey, payload) },
32
+ proofType: library_models_1.LibraryProofType.CRYPTOGRAPHIC_SIGNATURE,
33
+ };
34
+ };
35
+ const signHead = (kind, id, head, privateKey, publicKey) => {
36
+ const payload = (0, library_proof_1.buildHeadProofPayload)({ id, head, purpose: (0, library_proof_1.headPurpose)(kind), publicKey });
37
+ return { currentHash: head, proof: { publicKey, signature: (0, create_ed25519_signature_1.createEd25519Signature)(privateKey, payload) } };
38
+ };
39
+ /**
40
+ * Creates a new library entity from its first version. The entity `id` is the
41
+ * first version's `currentHash` (content-addressed identity); the signing key
42
+ * becomes the entity owner.
43
+ */
44
+ const createLibraryEntity = (args) => {
45
+ assertGasLimit(args.gasLimit);
46
+ const publicKey = (0, get_ed25519_public_key_from_private_key_1.getEd25519PublicKeyFromPrivateKey)(args.privateKey);
47
+ const createdAt = args.createdAt ?? Date.now();
48
+ // Identity is content-addressed: the first version's hash (seeded with an
49
+ // empty previousHash) IS the entity id. The hash does not depend on id, so
50
+ // it can be computed before signing the proof (which does bind id).
51
+ const previousHash = '';
52
+ const id = (0, library_hash_1.computeVersionHash)(args.source, previousHash);
53
+ const firstVersion = signVersion(args.kind, id, args.source, previousHash, createdAt, args.privateKey, publicKey);
54
+ return {
55
+ kind: args.kind,
56
+ id,
57
+ name: args.name,
58
+ description: args.description,
59
+ gasLimit: args.gasLimit,
60
+ owner: { publicKey },
61
+ delegations: [],
62
+ versions: [firstVersion],
63
+ head: signHead(args.kind, id, id, args.privateKey, publicKey),
64
+ };
65
+ };
66
+ exports.createLibraryEntity = createLibraryEntity;
67
+ /**
68
+ * Grants `signerPublicKey` the right to append versions, signed by the owner.
69
+ * Returns a new entity (the input is not mutated). Rejects with
70
+ * {@link LibraryDelegationNotAuthorizedError} if the signing key is not the
71
+ * owner (which also blocks a delegate from re-delegating — a delegate's key is
72
+ * never the owner key) or if the grant targets the owner itself.
73
+ */
74
+ const addLibraryDelegate = (entity, args) => {
75
+ const ownerPublicKey = (0, get_ed25519_public_key_from_private_key_1.getEd25519PublicKeyFromPrivateKey)(args.ownerPrivateKey);
76
+ if (ownerPublicKey !== entity.owner.publicKey) {
77
+ throw new library_errors_1.LibraryDelegationNotAuthorizedError(entity.id, ownerPublicKey, 'only the owner may delegate');
78
+ }
79
+ if (args.signerPublicKey === entity.owner.publicKey) {
80
+ throw new library_errors_1.LibraryDelegationNotAuthorizedError(entity.id, ownerPublicKey, 'the owner is already authorized');
81
+ }
82
+ const createdAt = args.createdAt ?? Date.now();
83
+ const payload = (0, library_proof_1.buildDelegationProofPayload)({
84
+ id: entity.id,
85
+ signerPublicKey: args.signerPublicKey,
86
+ purpose: (0, library_proof_1.delegatePurpose)(entity.kind),
87
+ publicKey: ownerPublicKey,
88
+ });
89
+ const delegation = {
90
+ signerPublicKey: args.signerPublicKey,
91
+ createdAt,
92
+ proof: { publicKey: ownerPublicKey, signature: (0, create_ed25519_signature_1.createEd25519Signature)(args.ownerPrivateKey, payload) },
93
+ };
94
+ return { ...entity, delegations: [...entity.delegations, delegation] };
95
+ };
96
+ exports.addLibraryDelegate = addLibraryDelegate;
97
+ /**
98
+ * Appends a new signed version to an entity's ledger and returns a new entity
99
+ * (the input is not mutated). The new version chains to the prior tip via
100
+ * `previousHash`, and a fresh head proof is minted over the new tip.
101
+ *
102
+ * Gated: the signer must be the owner or a verified delegate
103
+ * ({@link isLibraryAuthorizedSigner}), else {@link LibraryVersionNotAuthorizedError}.
104
+ */
105
+ const appendLibraryVersion = (entity, args) => {
106
+ const publicKey = (0, get_ed25519_public_key_from_private_key_1.getEd25519PublicKeyFromPrivateKey)(args.privateKey);
107
+ if (!(0, authorize_library_1.isLibraryAuthorizedSigner)(entity, publicKey)) {
108
+ throw new library_errors_1.LibraryVersionNotAuthorizedError(entity.id, publicKey);
109
+ }
110
+ const createdAt = args.createdAt ?? Date.now();
111
+ const previousHash = entity.versions[entity.versions.length - 1].currentHash;
112
+ const version = signVersion(entity.kind, entity.id, args.source, previousHash, createdAt, args.privateKey, publicKey);
113
+ return {
114
+ ...entity,
115
+ versions: [...entity.versions, version],
116
+ head: signHead(entity.kind, entity.id, version.currentHash, args.privateKey, publicKey),
117
+ };
118
+ };
119
+ exports.appendLibraryVersion = appendLibraryVersion;
@@ -0,0 +1,19 @@
1
+ import { LibraryStore } from './library-store';
2
+ /**
3
+ * A read-through in-memory cache over a {@link LibraryStore} — the "resolve
4
+ * once, retain in memory" hydration cache. When a reference is resolved, the
5
+ * entity is fetched (and re-verified) from the underlying store once and kept;
6
+ * later resolutions of the same id are served from memory.
7
+ *
8
+ * Safe with no invalidation logic: library ids are content-addressed and a
9
+ * reference pins an immutable `currentHash`, and version ledgers are
10
+ * append-only — so a cached entity always still contains the pinned version. We
11
+ * cache the underlying store's already-verified entity and deep-clone on the way
12
+ * in and out, so a caller cannot corrupt the cache by mutating a returned
13
+ * object. Writes through this wrapper keep the cache coherent.
14
+ *
15
+ * It is itself a `LibraryStore`, so it is a drop-in anywhere a store is taken
16
+ * (`resolveLibraryReference`, `executeFunctionReference`, the apply path).
17
+ */
18
+ export declare const createCachingLibraryStore: (store: LibraryStore) => LibraryStore;
19
+ //# sourceMappingURL=caching-library-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"caching-library-store.d.ts","sourceRoot":"","sources":["../../src/library/caching-library-store.ts"],"names":[],"mappings":"AACA,OAAO,EAAyC,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAItF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,yBAAyB,GAAI,OAAO,YAAY,KAAG,YAoC/D,CAAC"}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createCachingLibraryStore = void 0;
4
+ const clone = (value) => JSON.parse(JSON.stringify(value));
5
+ /**
6
+ * A read-through in-memory cache over a {@link LibraryStore} — the "resolve
7
+ * once, retain in memory" hydration cache. When a reference is resolved, the
8
+ * entity is fetched (and re-verified) from the underlying store once and kept;
9
+ * later resolutions of the same id are served from memory.
10
+ *
11
+ * Safe with no invalidation logic: library ids are content-addressed and a
12
+ * reference pins an immutable `currentHash`, and version ledgers are
13
+ * append-only — so a cached entity always still contains the pinned version. We
14
+ * cache the underlying store's already-verified entity and deep-clone on the way
15
+ * in and out, so a caller cannot corrupt the cache by mutating a returned
16
+ * object. Writes through this wrapper keep the cache coherent.
17
+ *
18
+ * It is itself a `LibraryStore`, so it is a drop-in anywhere a store is taken
19
+ * (`resolveLibraryReference`, `executeFunctionReference`, the apply path).
20
+ */
21
+ const createCachingLibraryStore = (store) => {
22
+ const cache = new Map();
23
+ const get = async (id) => {
24
+ const cached = cache.get(id);
25
+ if (cached) {
26
+ return clone(cached);
27
+ }
28
+ const entity = await store.get(id); // underlying store re-verifies on read
29
+ if (entity) {
30
+ cache.set(id, clone(entity));
31
+ return clone(entity);
32
+ }
33
+ return undefined;
34
+ };
35
+ return {
36
+ get,
37
+ async getVersion(id, currentHash) {
38
+ const entity = await get(id);
39
+ return entity?.versions.find((version) => version.currentHash === currentHash);
40
+ },
41
+ async has(id) {
42
+ return cache.has(id) || store.has(id);
43
+ },
44
+ list: (filter) => store.list(filter),
45
+ search: (query) => store.search(query),
46
+ async save(entity) {
47
+ await store.save(entity);
48
+ cache.set(entity.id, clone(entity)); // keep the cache fresh after an append
49
+ },
50
+ async delete(id) {
51
+ await store.delete(id);
52
+ cache.delete(id);
53
+ },
54
+ };
55
+ };
56
+ exports.createCachingLibraryStore = createCachingLibraryStore;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Deterministic JSON serialization: object keys are sorted recursively so the
3
+ * same logical value always produces byte-identical output regardless of key
4
+ * insertion order. Array order is preserved (it is significant).
5
+ *
6
+ * This is the preimage builder for every library hash and signed payload. It is
7
+ * deliberately NOT raw string concatenation — concatenating `source +
8
+ * previousHash` is ambiguous (`"ab"+"c"` collides with `"a"+"bc"`), which a
9
+ * canonical JSON object avoids.
10
+ */
11
+ export declare const canonicalJsonStringify: (value: unknown) => string;
12
+ //# sourceMappingURL=canonical-json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical-json.d.ts","sourceRoot":"","sources":["../../src/library/canonical-json.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB,GAAI,OAAO,OAAO,KAAG,MACpB,CAAC"}
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.canonicalJsonStringify = void 0;
4
+ /**
5
+ * Deterministic JSON serialization: object keys are sorted recursively so the
6
+ * same logical value always produces byte-identical output regardless of key
7
+ * insertion order. Array order is preserved (it is significant).
8
+ *
9
+ * This is the preimage builder for every library hash and signed payload. It is
10
+ * deliberately NOT raw string concatenation — concatenating `source +
11
+ * previousHash` is ambiguous (`"ab"+"c"` collides with `"a"+"bc"`), which a
12
+ * canonical JSON object avoids.
13
+ */
14
+ const canonicalJsonStringify = (value) => JSON.stringify(sortValue(value));
15
+ exports.canonicalJsonStringify = canonicalJsonStringify;
16
+ const sortValue = (value) => {
17
+ if (Array.isArray(value)) {
18
+ return value.map(sortValue);
19
+ }
20
+ if (value !== null && typeof value === 'object') {
21
+ const source = value;
22
+ return Object.keys(source)
23
+ .sort()
24
+ .reduce((acc, key) => {
25
+ acc[key] = sortValue(source[key]);
26
+ return acc;
27
+ }, {});
28
+ }
29
+ return value;
30
+ };
@@ -0,0 +1,21 @@
1
+ import { IShareRule } from '../models/rules/share-rule-models';
2
+ /**
3
+ * Compiles a rule defined with the existing `@degenerate/rules` model into a
4
+ * SELF-CONTAINED predicate source — `({ current, proposed }) => boolean` — that
5
+ * runs in the bare sandbox (no `require`, no ambient `Date`/`Math.random`).
6
+ *
7
+ * The compiled source embeds the rule's conditions as data and inlines an
8
+ * interpreter that mirrors the engine's `evaluateRule` semantics exactly:
9
+ * - a rule passes iff EVERY `currentDataConditions` holds against `current`
10
+ * AND EVERY `proposedDataConditions` holds against `proposed`;
11
+ * - if either condition array is empty the rule fails (matches the engine's
12
+ * `currentResult/proposedResult` short-circuit);
13
+ * - each condition resolves its dot-path property, evaluates by type, then
14
+ * applies the IS/IS_NOT qualifier (booleans are special-cased: a non-boolean
15
+ * value fails outright, before the qualifier).
16
+ *
17
+ * Faithfulness to the engine is verified by a cross-check test in
18
+ * `@degenerate/rules` (compiled verdict === `evaluateRule(...)`).
19
+ */
20
+ export declare const compileRuleToSource: (rule: IShareRule) => string;
21
+ //# sourceMappingURL=compile-rule-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile-rule-source.d.ts","sourceRoot":"","sources":["../../src/library/compile-rule-source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAE/D;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,mBAAmB,GAAI,MAAM,UAAU,KAAG,MAMtD,CAAC"}
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.compileRuleToSource = void 0;
4
+ /**
5
+ * Compiles a rule defined with the existing `@degenerate/rules` model into a
6
+ * SELF-CONTAINED predicate source — `({ current, proposed }) => boolean` — that
7
+ * runs in the bare sandbox (no `require`, no ambient `Date`/`Math.random`).
8
+ *
9
+ * The compiled source embeds the rule's conditions as data and inlines an
10
+ * interpreter that mirrors the engine's `evaluateRule` semantics exactly:
11
+ * - a rule passes iff EVERY `currentDataConditions` holds against `current`
12
+ * AND EVERY `proposedDataConditions` holds against `proposed`;
13
+ * - if either condition array is empty the rule fails (matches the engine's
14
+ * `currentResult/proposedResult` short-circuit);
15
+ * - each condition resolves its dot-path property, evaluates by type, then
16
+ * applies the IS/IS_NOT qualifier (booleans are special-cased: a non-boolean
17
+ * value fails outright, before the qualifier).
18
+ *
19
+ * Faithfulness to the engine is verified by a cross-check test in
20
+ * `@degenerate/rules` (compiled verdict === `evaluateRule(...)`).
21
+ */
22
+ const compileRuleToSource = (rule) => {
23
+ const data = JSON.stringify({
24
+ currentDataConditions: rule.currentDataConditions ?? [],
25
+ proposedDataConditions: rule.proposedDataConditions ?? [],
26
+ });
27
+ return `({ current, proposed }) => { var R = ${data}; ${INTERPRETER} }`;
28
+ };
29
+ exports.compileRuleToSource = compileRuleToSource;
30
+ // The inlined interpreter. Kept as plain ES5-ish JS so it runs verbatim in the
31
+ // sandbox. Mirrors packages/rules/src/evaluation/* condition logic.
32
+ const INTERPRETER = `
33
+ var get = function (o, path) {
34
+ return String(path).split('.').reduce(function (acc, key) {
35
+ return (acc && acc[key] !== undefined) ? acc[key] : undefined;
36
+ }, o);
37
+ };
38
+ var checkType = function (v, t) {
39
+ switch (t) {
40
+ case 'STRING': return typeof v === 'string';
41
+ case 'NUMBER': return typeof v === 'number';
42
+ case 'INTEGER': return Number.isInteger(v);
43
+ case 'BOOLEAN': return typeof v === 'boolean';
44
+ case 'OBJECT': return typeof v === 'object' && v !== null;
45
+ case 'ARRAY': return Array.isArray(v);
46
+ case 'NULL': return v === null;
47
+ case 'UNDEFINED': return typeof v === 'undefined';
48
+ case 'FUNCTION': return typeof v === 'function';
49
+ case 'BIGINT': return typeof v === 'bigint';
50
+ default: return false;
51
+ }
52
+ };
53
+ var evalCond = function (obj, c) {
54
+ var v = get(obj, c.targettedProperty);
55
+ var base;
56
+ switch (c.conditionType) {
57
+ case 'TYPEOF': base = checkType(v, c.conditionValue); break;
58
+ case 'EQUAL': base = v === c.conditionValue; break;
59
+ case 'GREATER_THAN': base = v > c.conditionValue; break;
60
+ case 'LESS_THAN': base = v < c.conditionValue; break;
61
+ case 'GREATER_THAN_OR_EQUAL': base = v >= c.conditionValue; break;
62
+ case 'LESS_THAN_OR_EQUAL': base = v <= c.conditionValue; break;
63
+ case 'CONTAINS':
64
+ base = (typeof c.conditionValue === 'string')
65
+ ? c.conditionValue.includes(v.toString())
66
+ : c.conditionValue.includes(v);
67
+ break;
68
+ case 'STARTS_WITH': base = v.toString().startsWith(c.conditionValue.toString()); break;
69
+ case 'ENDS_WITH': base = v.toString().endsWith(c.conditionValue.toString()); break;
70
+ case 'NULL': base = v === null; break;
71
+ case 'EMPTY':
72
+ base = Array.isArray(v) ? (v.length === 0) : (v === null || v === undefined || v === '');
73
+ break;
74
+ case 'PATTERN': base = new RegExp(c.conditionValue).test(v); break;
75
+ case 'TRUE':
76
+ case 'FALSE': {
77
+ if (typeof v !== 'boolean') { return false; }
78
+ var want = (c.conditionType === 'TRUE');
79
+ return c.conditionTypeQualifier === 'IS_NOT' ? (v !== want) : (v === want);
80
+ }
81
+ default: return false;
82
+ }
83
+ return c.conditionTypeQualifier === 'IS_NOT' ? !base : base;
84
+ };
85
+ if (R.currentDataConditions.length === 0 || R.proposedDataConditions.length === 0) {
86
+ return R.currentDataConditions.length !== 0 && R.proposedDataConditions.length !== 0;
87
+ }
88
+ var currentOk = R.currentDataConditions.every(function (c) { return evalCond(current, c); });
89
+ var proposedOk = R.proposedDataConditions.every(function (c) { return evalCond(proposed, c); });
90
+ return currentOk && proposedOk;
91
+ `;
@@ -0,0 +1,36 @@
1
+ import { IShareData } from '../models/share-data/share-data-models';
2
+ import { RuleEvaluator } from '../sandbox/rule-evaluator';
3
+ import { LibraryReference } from './library-reference';
4
+ import { LibraryStore } from './library-store';
5
+ /** Why a rule reference did not pass. `unresolved` = the rule could not be loaded/verified. */
6
+ export type LibraryRuleFailureReason = 'rejected' | 'gas-exceeded' | 'threw' | 'invalid-output' | 'unresolved';
7
+ export interface LibraryRuleReferenceResult {
8
+ reference: LibraryReference;
9
+ passed: boolean;
10
+ reason?: LibraryRuleFailureReason;
11
+ error?: string;
12
+ }
13
+ export interface LibraryRulesVerdict {
14
+ /** True only if every rule reference passed. Empty input passes (vacuously). */
15
+ passed: boolean;
16
+ results: LibraryRuleReferenceResult[];
17
+ /** The subset that did not pass (the diagnostics). */
18
+ failures: LibraryRuleReferenceResult[];
19
+ }
20
+ export interface EvaluateLibraryRuleReferencesOptions {
21
+ current: IShareData;
22
+ proposed: IShareData;
23
+ store: LibraryStore;
24
+ evaluator?: RuleEvaluator;
25
+ }
26
+ /**
27
+ * Resolves a set of rule references from the library and sandbox-evaluates each
28
+ * against the proposed transition, combining the verdicts: the set passes only
29
+ * if every rule passes. Per-reference diagnostics say which rule failed and why.
30
+ *
31
+ * Fail-closed: a rule that cannot be resolved/verified (a dangling or tampered
32
+ * reference) counts as a failure (`reason: 'unresolved'`), so a transition is
33
+ * never let through because a governing rule could not be loaded.
34
+ */
35
+ export declare const evaluateLibraryRuleReferences: (references: LibraryReference[], options: EvaluateLibraryRuleReferencesOptions) => Promise<LibraryRulesVerdict>;
36
+ //# sourceMappingURL=evaluate-library-rules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluate-library-rules.d.ts","sourceRoot":"","sources":["../../src/library/evaluate-library-rules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,EAAgC,aAAa,EAAE,MAAM,2BAA2B,CAAC;AACxF,OAAO,EAAyB,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,+FAA+F;AAC/F,MAAM,MAAM,wBAAwB,GAAG,UAAU,GAAG,cAAc,GAAG,OAAO,GAAG,gBAAgB,GAAG,YAAY,CAAC;AAE/G,MAAM,WAAW,0BAA0B;IACvC,SAAS,EAAE,gBAAgB,CAAC;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,wBAAwB,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAChC,gFAAgF;IAChF,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,0BAA0B,EAAE,CAAC;IACtC,sDAAsD;IACtD,QAAQ,EAAE,0BAA0B,EAAE,CAAC;CAC1C;AAED,MAAM,WAAW,oCAAoC;IACjD,OAAO,EAAE,UAAU,CAAC;IACpB,QAAQ,EAAE,UAAU,CAAC;IACrB,KAAK,EAAE,YAAY,CAAC;IACpB,SAAS,CAAC,EAAE,aAAa,CAAC;CAC7B;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,6BAA6B,GACtC,YAAY,gBAAgB,EAAE,EAC9B,SAAS,oCAAoC,KAC9C,OAAO,CAAC,mBAAmB,CA8B7B,CAAC"}
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.evaluateLibraryRuleReferences = void 0;
4
+ const rule_evaluator_1 = require("../sandbox/rule-evaluator");
5
+ const library_reference_1 = require("./library-reference");
6
+ /**
7
+ * Resolves a set of rule references from the library and sandbox-evaluates each
8
+ * against the proposed transition, combining the verdicts: the set passes only
9
+ * if every rule passes. Per-reference diagnostics say which rule failed and why.
10
+ *
11
+ * Fail-closed: a rule that cannot be resolved/verified (a dangling or tampered
12
+ * reference) counts as a failure (`reason: 'unresolved'`), so a transition is
13
+ * never let through because a governing rule could not be loaded.
14
+ */
15
+ const evaluateLibraryRuleReferences = async (references, options) => {
16
+ const evaluator = options.evaluator ?? (0, rule_evaluator_1.createInProcessRuleEvaluator)();
17
+ const results = [];
18
+ for (const reference of references) {
19
+ try {
20
+ const evaluation = await (0, library_reference_1.evaluateRuleReference)(reference, options.store, {
21
+ current: options.current,
22
+ proposed: options.proposed,
23
+ evaluator,
24
+ });
25
+ if (!evaluation.ok) {
26
+ results.push({ reference, passed: false, reason: evaluation.failure, error: evaluation.error });
27
+ }
28
+ else if (evaluation.passed !== true) {
29
+ results.push({ reference, passed: false, reason: 'rejected' });
30
+ }
31
+ else {
32
+ results.push({ reference, passed: true });
33
+ }
34
+ }
35
+ catch (err) {
36
+ results.push({
37
+ reference,
38
+ passed: false,
39
+ reason: 'unresolved',
40
+ error: err instanceof Error ? err.message : String(err),
41
+ });
42
+ }
43
+ }
44
+ const failures = results.filter((result) => !result.passed);
45
+ return { passed: failures.length === 0, results, failures };
46
+ };
47
+ exports.evaluateLibraryRuleReferences = evaluateLibraryRuleReferences;
@@ -0,0 +1,34 @@
1
+ import { RuleEvaluationResult, RuleEvaluator } from '../sandbox/rule-evaluator';
2
+ import { FunctionExecutionResult, FunctionExecutor } from '../sandbox/sandbox-models';
3
+ import { IShareData } from '../models/share-data/share-data-models';
4
+ import { ILibraryEntity } from './library-models';
5
+ export interface EvaluateLibraryFunctionOptions {
6
+ current: IShareData;
7
+ input: unknown;
8
+ /** Defaults to the entity's declared `gasLimit`. */
9
+ gasLimit?: number;
10
+ /** Evaluate a specific version; defaults to the head. */
11
+ versionHash?: string;
12
+ /** Defaults to a fresh in-process executor. */
13
+ executor?: FunctionExecutor;
14
+ }
15
+ /**
16
+ * Runs a library FUNCTION in isolation against sample `current` state + `input`,
17
+ * so a function can be tested independently of any ShareData. Verifies the
18
+ * entity first and rejects a non-function with {@link LibraryKindMismatchError}.
19
+ */
20
+ export declare const evaluateLibraryFunction: (entity: ILibraryEntity, options: EvaluateLibraryFunctionOptions) => Promise<FunctionExecutionResult>;
21
+ export interface EvaluateLibraryRuleOptions {
22
+ current: IShareData;
23
+ proposed: IShareData;
24
+ gasLimit?: number;
25
+ versionHash?: string;
26
+ evaluator?: RuleEvaluator;
27
+ }
28
+ /**
29
+ * Runs a library RULE in isolation against a sample `current` → `proposed`
30
+ * transition, so a rule can be tested independently. Verifies the entity first
31
+ * and rejects a non-rule with {@link LibraryKindMismatchError}.
32
+ */
33
+ export declare const evaluateLibraryRule: (entity: ILibraryEntity, options: EvaluateLibraryRuleOptions) => Promise<RuleEvaluationResult>;
34
+ //# sourceMappingURL=evaluate-library.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluate-library.d.ts","sourceRoot":"","sources":["../../src/library/evaluate-library.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgC,oBAAoB,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC9G,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACtF,OAAO,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AAGpE,OAAO,EAAE,cAAc,EAAsC,MAAM,kBAAkB,CAAC;AAkBtF,MAAM,WAAW,8BAA8B;IAC3C,OAAO,EAAE,UAAU,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AAED;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,GAChC,QAAQ,cAAc,EACtB,SAAS,8BAA8B,KACxC,OAAO,CAAC,uBAAuB,CAajC,CAAC;AAEF,MAAM,WAAW,0BAA0B;IACvC,OAAO,EAAE,UAAU,CAAC;IACpB,QAAQ,EAAE,UAAU,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,aAAa,CAAC;CAC7B;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAC5B,QAAQ,cAAc,EACtB,SAAS,0BAA0B,KACpC,OAAO,CAAC,oBAAoB,CAgB9B,CAAC"}
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.evaluateLibraryRule = exports.evaluateLibraryFunction = void 0;
4
+ const library_errors_1 = require("../errors/library/library-errors");
5
+ const in_process_executor_1 = require("../sandbox/in-process-executor");
6
+ const rule_evaluator_1 = require("../sandbox/rule-evaluator");
7
+ const compile_rule_source_1 = require("./compile-rule-source");
8
+ const library_models_1 = require("./library-models");
9
+ const verify_library_1 = require("./verify-library");
10
+ /**
11
+ * Resolves which version to evaluate: a specific `versionHash`, or the head
12
+ * (latest) when omitted. Throws if a requested version is not present.
13
+ */
14
+ const resolveVersion = (entity, versionHash) => {
15
+ if (versionHash === undefined) {
16
+ return entity.versions[entity.versions.length - 1];
17
+ }
18
+ const version = entity.versions.find((candidate) => candidate.currentHash === versionHash);
19
+ if (!version) {
20
+ throw new library_errors_1.LibraryEntityInvalidError(`no version ${versionHash} on entity ${entity.id}`);
21
+ }
22
+ return version;
23
+ };
24
+ /**
25
+ * Runs a library FUNCTION in isolation against sample `current` state + `input`,
26
+ * so a function can be tested independently of any ShareData. Verifies the
27
+ * entity first and rejects a non-function with {@link LibraryKindMismatchError}.
28
+ */
29
+ const evaluateLibraryFunction = async (entity, options) => {
30
+ (0, verify_library_1.verifyLibraryEntity)(entity);
31
+ if (entity.kind !== library_models_1.LibraryEntityKind.FUNCTION) {
32
+ throw new library_errors_1.LibraryKindMismatchError(entity.id, library_models_1.LibraryEntityKind.FUNCTION, entity.kind);
33
+ }
34
+ const version = resolveVersion(entity, options.versionHash);
35
+ const executor = options.executor ?? (0, in_process_executor_1.createInProcessFunctionExecutor)();
36
+ return executor.execute({
37
+ source: version.source,
38
+ current: options.current,
39
+ input: options.input,
40
+ gasLimit: options.gasLimit ?? entity.gasLimit,
41
+ });
42
+ };
43
+ exports.evaluateLibraryFunction = evaluateLibraryFunction;
44
+ /**
45
+ * Runs a library RULE in isolation against a sample `current` → `proposed`
46
+ * transition, so a rule can be tested independently. Verifies the entity first
47
+ * and rejects a non-rule with {@link LibraryKindMismatchError}.
48
+ */
49
+ const evaluateLibraryRule = async (entity, options) => {
50
+ (0, verify_library_1.verifyLibraryEntity)(entity);
51
+ if (entity.kind !== library_models_1.LibraryEntityKind.RULE) {
52
+ throw new library_errors_1.LibraryKindMismatchError(entity.id, library_models_1.LibraryEntityKind.RULE, entity.kind);
53
+ }
54
+ const version = resolveVersion(entity, options.versionHash);
55
+ const evaluator = options.evaluator ?? (0, rule_evaluator_1.createInProcessRuleEvaluator)();
56
+ // B1: a rule entity's source is the canonical rule DEFINITION; derive the
57
+ // sandbox predicate from it via the (faithfulness-proven) compiler.
58
+ const definition = JSON.parse(version.source);
59
+ return evaluator.evaluate({
60
+ source: (0, compile_rule_source_1.compileRuleToSource)(definition),
61
+ current: options.current,
62
+ proposed: options.proposed,
63
+ gasLimit: options.gasLimit ?? entity.gasLimit,
64
+ });
65
+ };
66
+ exports.evaluateLibraryRule = evaluateLibraryRule;
@@ -0,0 +1,22 @@
1
+ import { ILibraryEntity, ILibraryVersion } from './library-models';
2
+ import { LibraryListFilter, LibrarySearchQuery, LibraryStore } from './library-store';
3
+ /**
4
+ * In-memory {@link LibraryStore}. Deep-copies on the way in and out so callers
5
+ * cannot mutate stored state by reference, and re-verifies on every read.
6
+ *
7
+ * The optional `seed` models data already present in a backend: it is stored
8
+ * WITHOUT verification, precisely so that the re-verify-on-read contract is what
9
+ * catches a tampered backing record.
10
+ */
11
+ export declare class InMemoryLibraryStore implements LibraryStore {
12
+ private readonly entities;
13
+ constructor(seed?: ILibraryEntity[]);
14
+ get(id: string): Promise<ILibraryEntity | undefined>;
15
+ getVersion(id: string, currentHash: string): Promise<ILibraryVersion | undefined>;
16
+ has(id: string): Promise<boolean>;
17
+ list(filter?: LibraryListFilter): Promise<ILibraryEntity[]>;
18
+ search(query: LibrarySearchQuery): Promise<ILibraryEntity[]>;
19
+ save(entity: ILibraryEntity): Promise<void>;
20
+ delete(id: string): Promise<void>;
21
+ }
22
+ //# sourceMappingURL=in-memory-library-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-library-store.d.ts","sourceRoot":"","sources":["../../src/library/in-memory-library-store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAqBtF;;;;;;;GAOG;AACH,qBAAa,oBAAqB,YAAW,YAAY;IACrD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqC;gBAElD,IAAI,GAAE,cAAc,EAAO;IAMjC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC;IASpD,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC;IAKjF,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIjC,IAAI,CAAC,MAAM,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAI3D,MAAM,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAmB5D,IAAI,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB3C,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG1C"}