@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.
- package/dist/_settings/cryptography-settings.d.ts +5 -1
- package/dist/_settings/cryptography-settings.d.ts.map +1 -1
- package/dist/_settings/cryptography-settings.js +5 -1
- package/dist/crypto/index.d.ts +5 -9
- package/dist/crypto/index.d.ts.map +1 -1
- package/dist/crypto/index.js +7 -9
- package/dist/crypto/private-public-keys/create-ed25519-keys-from-mnemonic.d.ts +22 -0
- package/dist/crypto/private-public-keys/create-ed25519-keys-from-mnemonic.d.ts.map +1 -0
- package/dist/crypto/private-public-keys/create-ed25519-keys-from-mnemonic.js +65 -0
- package/dist/crypto/private-public-keys/get-ed25519-public-key-from-private-key.d.ts +11 -0
- package/dist/crypto/private-public-keys/get-ed25519-public-key-from-private-key.d.ts.map +1 -0
- package/dist/crypto/private-public-keys/get-ed25519-public-key-from-private-key.js +15 -0
- package/dist/crypto/signature/create-ed25519-signature.d.ts +16 -0
- package/dist/crypto/signature/create-ed25519-signature.d.ts.map +1 -0
- package/dist/crypto/signature/create-ed25519-signature.js +26 -0
- package/dist/crypto/signature/ed25519-primitives.d.ts +25 -0
- package/dist/crypto/signature/ed25519-primitives.d.ts.map +1 -0
- package/dist/crypto/signature/ed25519-primitives.js +65 -0
- package/dist/crypto/signature/verify-ed25519-signature.d.ts +13 -0
- package/dist/crypto/signature/verify-ed25519-signature.d.ts.map +1 -0
- package/dist/crypto/signature/verify-ed25519-signature.js +31 -0
- package/dist/errors/index.d.ts +2 -0
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +2 -0
- package/dist/errors/library/library-errors.d.ts +101 -0
- package/dist/errors/library/library-errors.d.ts.map +1 -0
- package/dist/errors/library/library-errors.js +133 -0
- package/dist/errors/settlement/settlement-errors.d.ts +74 -0
- package/dist/errors/settlement/settlement-errors.d.ts.map +1 -0
- package/dist/errors/settlement/settlement-errors.js +93 -0
- package/dist/errors/share-data/share-data-errors.d.ts +21 -0
- package/dist/errors/share-data/share-data-errors.d.ts.map +1 -1
- package/dist/errors/share-data/share-data-errors.js +30 -1
- package/dist/helpers/apply-share-function.d.ts +23 -0
- package/dist/helpers/apply-share-function.d.ts.map +1 -0
- package/dist/helpers/apply-share-function.js +32 -0
- package/dist/helpers/index.d.ts +1 -0
- package/dist/helpers/index.d.ts.map +1 -1
- package/dist/helpers/index.js +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/library/authorize-library.d.ts +17 -0
- package/dist/library/authorize-library.d.ts.map +1 -0
- package/dist/library/authorize-library.js +39 -0
- package/dist/library/build-library.d.ts +49 -0
- package/dist/library/build-library.d.ts.map +1 -0
- package/dist/library/build-library.js +119 -0
- package/dist/library/caching-library-store.d.ts +19 -0
- package/dist/library/caching-library-store.d.ts.map +1 -0
- package/dist/library/caching-library-store.js +56 -0
- package/dist/library/canonical-json.d.ts +12 -0
- package/dist/library/canonical-json.d.ts.map +1 -0
- package/dist/library/canonical-json.js +30 -0
- package/dist/library/compile-rule-source.d.ts +21 -0
- package/dist/library/compile-rule-source.d.ts.map +1 -0
- package/dist/library/compile-rule-source.js +91 -0
- package/dist/library/evaluate-library-rules.d.ts +36 -0
- package/dist/library/evaluate-library-rules.d.ts.map +1 -0
- package/dist/library/evaluate-library-rules.js +47 -0
- package/dist/library/evaluate-library.d.ts +34 -0
- package/dist/library/evaluate-library.d.ts.map +1 -0
- package/dist/library/evaluate-library.js +66 -0
- package/dist/library/in-memory-library-store.d.ts +22 -0
- package/dist/library/in-memory-library-store.d.ts.map +1 -0
- package/dist/library/in-memory-library-store.js +92 -0
- package/dist/library/index.d.ts +18 -0
- package/dist/library/index.d.ts.map +1 -0
- package/dist/library/index.js +33 -0
- package/dist/library/library-hash.d.ts +9 -0
- package/dist/library/library-hash.d.ts.map +1 -0
- package/dist/library/library-hash.js +14 -0
- package/dist/library/library-models.d.ts +134 -0
- package/dist/library/library-models.d.ts.map +1 -0
- package/dist/library/library-models.js +84 -0
- package/dist/library/library-proof.d.ts +40 -0
- package/dist/library/library-proof.d.ts.map +1 -0
- package/dist/library/library-proof.js +44 -0
- package/dist/library/library-reference.d.ts +75 -0
- package/dist/library/library-reference.d.ts.map +1 -0
- package/dist/library/library-reference.js +98 -0
- package/dist/library/library-server.d.ts +17 -0
- package/dist/library/library-server.d.ts.map +1 -0
- package/dist/library/library-server.js +45 -0
- package/dist/library/library-store.d.ts +37 -0
- package/dist/library/library-store.d.ts.map +1 -0
- package/dist/library/library-store.js +2 -0
- package/dist/library/remote-library-models.d.ts +54 -0
- package/dist/library/remote-library-models.d.ts.map +1 -0
- package/dist/library/remote-library-models.js +2 -0
- package/dist/library/remote-library-store.d.ts +15 -0
- package/dist/library/remote-library-store.d.ts.map +1 -0
- package/dist/library/remote-library-store.js +59 -0
- package/dist/library/verify-library.d.ts +21 -0
- package/dist/library/verify-library.d.ts.map +1 -0
- package/dist/library/verify-library.js +86 -0
- package/dist/models/functions/share-data-function-models.d.ts +6 -74
- package/dist/models/functions/share-data-function-models.d.ts.map +1 -1
- package/dist/models/functions/share-data-function-models.js +7 -65
- package/dist/models/index.d.ts +1 -0
- package/dist/models/index.d.ts.map +1 -1
- package/dist/models/index.js +1 -0
- package/dist/models/safe/transactions/sharedata-transactions-models.d.ts +5 -0
- package/dist/models/safe/transactions/sharedata-transactions-models.d.ts.map +1 -1
- package/dist/models/settlement/settlement-models.d.ts +221 -0
- package/dist/models/settlement/settlement-models.d.ts.map +1 -0
- package/dist/models/settlement/settlement-models.js +152 -0
- package/dist/models/share-data/share-data-models.d.ts +12 -0
- package/dist/models/share-data/share-data-models.d.ts.map +1 -1
- package/dist/models/share-data/share-data-persistence-models.d.ts +3 -0
- package/dist/models/share-data/share-data-persistence-models.d.ts.map +1 -1
- package/dist/models/shareblock/shareblock-models.d.ts +179 -3
- package/dist/models/shareblock/shareblock-models.d.ts.map +1 -1
- package/dist/models/shareblock/shareblock-models.js +99 -7
- package/dist/sandbox/in-process-executor.d.ts +13 -0
- package/dist/sandbox/in-process-executor.d.ts.map +1 -0
- package/dist/sandbox/in-process-executor.js +31 -0
- package/dist/sandbox/index.d.ts +8 -0
- package/dist/sandbox/index.d.ts.map +1 -0
- package/dist/sandbox/index.js +23 -0
- package/dist/sandbox/remote-sandbox-executor.d.ts +12 -0
- package/dist/sandbox/remote-sandbox-executor.d.ts.map +1 -0
- package/dist/sandbox/remote-sandbox-executor.js +49 -0
- package/dist/sandbox/remote-sandbox-models.d.ts +37 -0
- package/dist/sandbox/remote-sandbox-models.d.ts.map +1 -0
- package/dist/sandbox/remote-sandbox-models.js +2 -0
- package/dist/sandbox/rule-evaluator.d.ts +32 -0
- package/dist/sandbox/rule-evaluator.d.ts.map +1 -0
- package/dist/sandbox/rule-evaluator.js +23 -0
- package/dist/sandbox/run-sandboxed.d.ts +24 -0
- package/dist/sandbox/run-sandboxed.d.ts.map +1 -0
- package/dist/sandbox/run-sandboxed.js +88 -0
- package/dist/sandbox/sandbox-models.d.ts +40 -0
- package/dist/sandbox/sandbox-models.d.ts.map +1 -0
- package/dist/sandbox/sandbox-models.js +2 -0
- package/dist/sandbox/sandbox-server.d.ts +22 -0
- package/dist/sandbox/sandbox-server.d.ts.map +1 -0
- package/dist/sandbox/sandbox-server.js +62 -0
- package/package.json +3 -4
- package/dist/crypto/private-public-keys/create-key-pair-from-mnemonic.d.ts +0 -12
- package/dist/crypto/private-public-keys/create-key-pair-from-mnemonic.d.ts.map +0 -1
- package/dist/crypto/private-public-keys/create-key-pair-from-mnemonic.js +0 -54
- package/dist/crypto/private-public-keys/create-key-pair-from-private-key.d.ts +0 -11
- package/dist/crypto/private-public-keys/create-key-pair-from-private-key.d.ts.map +0 -1
- package/dist/crypto/private-public-keys/create-key-pair-from-private-key.js +0 -50
- package/dist/crypto/private-public-keys/create-key-pair-from-public-key.d.ts +0 -11
- package/dist/crypto/private-public-keys/create-key-pair-from-public-key.d.ts.map +0 -1
- package/dist/crypto/private-public-keys/create-key-pair-from-public-key.js +0 -51
- package/dist/crypto/private-public-keys/generation/create-entropy-for-elliptical-curve.d.ts +0 -10
- package/dist/crypto/private-public-keys/generation/create-entropy-for-elliptical-curve.d.ts.map +0 -1
- package/dist/crypto/private-public-keys/generation/create-entropy-for-elliptical-curve.js +0 -51
- package/dist/crypto/private-public-keys/generation/generate-key-pair.d.ts +0 -11
- package/dist/crypto/private-public-keys/generation/generate-key-pair.d.ts.map +0 -1
- package/dist/crypto/private-public-keys/generation/generate-key-pair.js +0 -49
- package/dist/crypto/private-public-keys/generation/get-private-public-key-from-keypair.d.ts +0 -15
- package/dist/crypto/private-public-keys/generation/get-private-public-key-from-keypair.d.ts.map +0 -1
- package/dist/crypto/private-public-keys/generation/get-private-public-key-from-keypair.js +0 -21
- package/dist/crypto/signature/create-crypto-signature.d.ts +0 -20
- package/dist/crypto/signature/create-crypto-signature.d.ts.map +0 -1
- package/dist/crypto/signature/create-crypto-signature.js +0 -26
- package/dist/crypto/signature/verify-crypto-signature-by-data.d.ts +0 -17
- package/dist/crypto/signature/verify-crypto-signature-by-data.d.ts.map +0 -1
- package/dist/crypto/signature/verify-crypto-signature-by-data.js +0 -61
- package/dist/crypto/signature/verify-crypto-signature-by-hash.d.ts +0 -17
- package/dist/crypto/signature/verify-crypto-signature-by-hash.d.ts.map +0 -1
- 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"}
|