@proto-kit/common 0.1.1-develop.153

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 (112) hide show
  1. package/LICENSE.md +201 -0
  2. package/dist/Constants.d.ts +4 -0
  3. package/dist/Constants.d.ts.map +1 -0
  4. package/dist/Constants.js +3 -0
  5. package/dist/config/ConfigurableModule.d.ts +21 -0
  6. package/dist/config/ConfigurableModule.d.ts.map +1 -0
  7. package/dist/config/ConfigurableModule.js +19 -0
  8. package/dist/config/ConfigurationAggregator.d.ts +10 -0
  9. package/dist/config/ConfigurationAggregator.d.ts.map +1 -0
  10. package/dist/config/ConfigurationAggregator.js +35 -0
  11. package/dist/config/ConfigurationReceiver.d.ts +25 -0
  12. package/dist/config/ConfigurationReceiver.d.ts.map +1 -0
  13. package/dist/config/ConfigurationReceiver.js +36 -0
  14. package/dist/config/ModuleContainer.d.ts +103 -0
  15. package/dist/config/ModuleContainer.d.ts.map +1 -0
  16. package/dist/config/ModuleContainer.js +163 -0
  17. package/dist/config/types.d.ts +2 -0
  18. package/dist/config/types.d.ts.map +1 -0
  19. package/dist/config/types.js +1 -0
  20. package/dist/index.d.ts +9 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +9 -0
  23. package/dist/model/MethodPublicInput.d.ts +51 -0
  24. package/dist/model/MethodPublicInput.d.ts.map +1 -0
  25. package/dist/model/MethodPublicInput.js +11 -0
  26. package/dist/model/Option.d.ts +89 -0
  27. package/dist/model/Option.d.ts.map +1 -0
  28. package/dist/model/Option.js +86 -0
  29. package/dist/model/Path.d.ts +31 -0
  30. package/dist/model/Path.d.ts.map +1 -0
  31. package/dist/model/Path.js +44 -0
  32. package/dist/model/StateTransition.d.ts +85 -0
  33. package/dist/model/StateTransition.d.ts.map +1 -0
  34. package/dist/model/StateTransition.js +58 -0
  35. package/dist/model/StateTransitionProvableBatch.d.ts +56 -0
  36. package/dist/model/StateTransitionProvableBatch.d.ts.map +1 -0
  37. package/dist/model/StateTransitionProvableBatch.js +20 -0
  38. package/dist/prover/block/BlockProver.d.ts +199 -0
  39. package/dist/prover/block/BlockProver.d.ts.map +1 -0
  40. package/dist/prover/block/BlockProver.js +119 -0
  41. package/dist/prover/block/BlockScopedModule.d.ts +3 -0
  42. package/dist/prover/block/BlockScopedModule.d.ts.map +1 -0
  43. package/dist/prover/block/BlockScopedModule.js +6 -0
  44. package/dist/prover/statetransition/StateTransitionProver.d.ts +92 -0
  45. package/dist/prover/statetransition/StateTransitionProver.d.ts.map +1 -0
  46. package/dist/prover/statetransition/StateTransitionProver.js +127 -0
  47. package/dist/prover/statetransition/StateTransitionWitnessProvider.d.ts +16 -0
  48. package/dist/prover/statetransition/StateTransitionWitnessProvider.d.ts.map +1 -0
  49. package/dist/prover/statetransition/StateTransitionWitnessProvider.js +17 -0
  50. package/dist/src/model/Option.d.ts +158 -0
  51. package/dist/src/model/Option.d.ts.map +1 -0
  52. package/dist/src/model/Option.js +53 -0
  53. package/dist/src/model/Path.d.ts +35 -0
  54. package/dist/src/model/Path.d.ts.map +1 -0
  55. package/dist/src/model/Path.js +51 -0
  56. package/dist/src/model/StateTransition.d.ts +201 -0
  57. package/dist/src/model/StateTransition.d.ts.map +1 -0
  58. package/dist/src/model/StateTransition.js +43 -0
  59. package/dist/src/utils/PrefixedHashList.d.ts +15 -0
  60. package/dist/src/utils/PrefixedHashList.d.ts.map +1 -0
  61. package/dist/src/utils/PrefixedHashList.js +28 -0
  62. package/dist/src/utils/ProvableHashList.d.ts +30 -0
  63. package/dist/src/utils/ProvableHashList.d.ts.map +1 -0
  64. package/dist/src/utils/ProvableHashList.js +43 -0
  65. package/dist/types.d.ts +11 -0
  66. package/dist/types.d.ts.map +1 -0
  67. package/dist/types.js +1 -0
  68. package/dist/utils/PrefixedHashList.d.ts +14 -0
  69. package/dist/utils/PrefixedHashList.d.ts.map +1 -0
  70. package/dist/utils/PrefixedHashList.js +12 -0
  71. package/dist/utils/PrefixedProvableHashList.d.ts +8 -0
  72. package/dist/utils/PrefixedProvableHashList.d.ts.map +1 -0
  73. package/dist/utils/PrefixedProvableHashList.js +12 -0
  74. package/dist/utils/ProvableHashList.d.ts +26 -0
  75. package/dist/utils/ProvableHashList.d.ts.map +1 -0
  76. package/dist/utils/ProvableHashList.js +35 -0
  77. package/dist/utils/Utils.d.ts +22 -0
  78. package/dist/utils/Utils.d.ts.map +1 -0
  79. package/dist/utils/Utils.js +41 -0
  80. package/dist/utils/merkletree/MemoryMerkleTreeStorage.d.ts +26 -0
  81. package/dist/utils/merkletree/MemoryMerkleTreeStorage.d.ts.map +1 -0
  82. package/dist/utils/merkletree/MemoryMerkleTreeStorage.js +79 -0
  83. package/dist/utils/merkletree/RollupMerkleTree.d.ts +143 -0
  84. package/dist/utils/merkletree/RollupMerkleTree.d.ts.map +1 -0
  85. package/dist/utils/merkletree/RollupMerkleTree.js +246 -0
  86. package/dist/utils.d.ts +2 -0
  87. package/dist/utils.d.ts.map +1 -0
  88. package/dist/utils.js +7 -0
  89. package/dist/zkProgrammable/ProvableMethodExecutionContext.d.ts +53 -0
  90. package/dist/zkProgrammable/ProvableMethodExecutionContext.d.ts.map +1 -0
  91. package/dist/zkProgrammable/ProvableMethodExecutionContext.js +98 -0
  92. package/dist/zkProgrammable/ZkProgrammable.d.ts +32 -0
  93. package/dist/zkProgrammable/ZkProgrammable.d.ts.map +1 -0
  94. package/dist/zkProgrammable/ZkProgrammable.js +60 -0
  95. package/dist/zkProgrammable/provableMethod.d.ts +16 -0
  96. package/dist/zkProgrammable/provableMethod.d.ts.map +1 -0
  97. package/dist/zkProgrammable/provableMethod.js +69 -0
  98. package/jest.config.cjs +1 -0
  99. package/package.json +35 -0
  100. package/src/config/ConfigurableModule.ts +44 -0
  101. package/src/config/ModuleContainer.ts +265 -0
  102. package/src/index.ts +9 -0
  103. package/src/types.ts +17 -0
  104. package/src/utils.ts +10 -0
  105. package/src/zkProgrammable/ProvableMethodExecutionContext.ts +122 -0
  106. package/src/zkProgrammable/ZkProgrammable.ts +119 -0
  107. package/src/zkProgrammable/provableMethod.ts +109 -0
  108. package/test/config/ModuleContainer.test.ts +82 -0
  109. package/test/tsconfig.json +4 -0
  110. package/test/zkProgrammable/ZkProgrammable.test.ts +283 -0
  111. package/tsconfig.json +8 -0
  112. package/tsconfig.test.json +9 -0
@@ -0,0 +1,246 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ /* eslint-disable id-length */
11
+ /* eslint-disable line-comment-position */
12
+ /* eslint-disable no-inline-comments */
13
+ /* eslint-disable @typescript-eslint/no-magic-numbers */
14
+ import { Bool, Circuit, Field, Poseidon, Struct } from "snarkyjs";
15
+ import { notInCircuit } from "../utils";
16
+ // external API
17
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
18
+ export { RollupMerkleTree, RollupMerkleWitness };
19
+ // internal API
20
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
21
+ export { maybeSwap };
22
+ /**
23
+ * The {@link BaseMerkleWitness} class defines a circuit-compatible base class
24
+ * for [Merkle Witness'](https://computersciencewiki.org/index.php/Merkle_proof).
25
+ */
26
+ class RollupMerkleWitness extends Struct({
27
+ path: Circuit.array(Field, 256 - 1),
28
+ isLeft: Circuit.array(Bool, 256 - 1),
29
+ }) {
30
+ height() {
31
+ return RollupMerkleWitness.height;
32
+ }
33
+ /**
34
+ * Calculates a root depending on the leaf value.
35
+ * @param leaf Value of the leaf node that belongs to this Witness.
36
+ * @returns The calculated root.
37
+ */
38
+ calculateRoot(hash) {
39
+ const n = this.height();
40
+ for (let index = 1; index < n; ++index) {
41
+ const isLeft = this.isLeft[index - 1];
42
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
43
+ const [left, right] = maybeSwap(isLeft, hash, this.path[index - 1]);
44
+ hash = Poseidon.hash([left, right]);
45
+ }
46
+ return hash;
47
+ }
48
+ /**
49
+ * Calculates the index of the leaf node that belongs to this Witness.
50
+ * @returns Index of the leaf.
51
+ */
52
+ calculateIndex() {
53
+ let powerOfTwo = Field(1);
54
+ let index = Field(0);
55
+ const n = this.height();
56
+ // eslint-disable-next-line no-underscore-dangle
57
+ for (let index_ = 1; index_ < n; ++index_) {
58
+ index = Circuit.if(this.isLeft[index_ - 1], index, index.add(powerOfTwo));
59
+ powerOfTwo = powerOfTwo.mul(2);
60
+ }
61
+ return index;
62
+ }
63
+ }
64
+ RollupMerkleWitness.height = 256;
65
+ /**
66
+ * A [Merkle Tree](https://en.wikipedia.org/wiki/Merkle_tree) is a binary tree in
67
+ * which every leaf is the cryptography hash of a piece of data,
68
+ * and every node is the hash of the concatenation of its two child nodes.
69
+ *
70
+ * A Merkle Tree allows developers to easily and securely verify
71
+ * the integrity of large amounts of data.
72
+ *
73
+ * Take a look at our [documentation](https://docs.minaprotocol.com/en/zkapps)
74
+ * on how to use Merkle Trees in combination with zkApps and
75
+ * zero knowledge programming!
76
+ *
77
+ * Levels are indexed from leaves (level 0) to root (level N - 1).
78
+ */
79
+ class RollupMerkleTree {
80
+ static get leafCount() {
81
+ return 2n ** BigInt(RollupMerkleTree.height - 1);
82
+ }
83
+ constructor(store) {
84
+ this.store = store;
85
+ // eslint-disable-next-line @shopify/prefer-class-properties
86
+ this.zeroes = [0n];
87
+ for (let index = 1; index < RollupMerkleTree.height; index += 1) {
88
+ const previousLevel = Field(this.zeroes[index - 1]);
89
+ this.zeroes.push(Poseidon.hash([previousLevel, previousLevel]).toBigInt());
90
+ }
91
+ }
92
+ /**
93
+ * Returns a node which lives at a given index and level.
94
+ * @param level Level of the node.
95
+ * @param index Index of the node.
96
+ * @returns The data of the node.
97
+ */
98
+ getNode(level, index) {
99
+ return Field(this.store.getNode(index, level) ?? this.zeroes[level]);
100
+ }
101
+ /**
102
+ * Returns the root of the [Merkle Tree](https://en.wikipedia.org/wiki/Merkle_tree).
103
+ * @returns The root of the Merkle Tree.
104
+ */
105
+ getRoot() {
106
+ return this.getNode(RollupMerkleTree.height - 1, 0n);
107
+ }
108
+ // eslint-disable-next-line no-warning-comments
109
+ // TODO: this allows to set a node at an index larger than the size. OK?
110
+ setNode(level, index, value) {
111
+ this.store.setNode(index, level, value.toBigInt());
112
+ }
113
+ /**
114
+ * TODO: if this is passed an index bigger than the max, it will set a couple
115
+ * of out-of-bounds nodes but not affect the real Merkle root. OK?
116
+ */
117
+ /**
118
+ * Sets the value of a leaf node at a given index to a given value.
119
+ * @param index Position of the leaf node.
120
+ * @param leaf New value.
121
+ */
122
+ setLeaf(index, leaf) {
123
+ if (index >= this.leafCount) {
124
+ index %= this.leafCount;
125
+ }
126
+ this.store.openTransaction();
127
+ this.setNode(0, index, leaf);
128
+ let currentIndex = index;
129
+ for (let level = 1; level < RollupMerkleTree.height; level += 1) {
130
+ currentIndex /= 2n;
131
+ const left = this.getNode(level - 1, currentIndex * 2n);
132
+ const right = this.getNode(level - 1, currentIndex * 2n + 1n);
133
+ this.setNode(level, currentIndex, Poseidon.hash([left, right]));
134
+ }
135
+ this.store.commit();
136
+ }
137
+ /**
138
+ * Returns the witness (also known as
139
+ * [Merkle Proof or Merkle Witness](https://computersciencewiki.org/index.php/Merkle_proof))
140
+ * for the leaf at the given index.
141
+ * @param index Position of the leaf node.
142
+ * @returns The witness that belongs to the leaf.
143
+ */
144
+ getWitness(index) {
145
+ if (index >= this.leafCount) {
146
+ index %= this.leafCount;
147
+ }
148
+ const path = [];
149
+ const isLefts = [];
150
+ for (let level = 0; level < RollupMerkleTree.height - 1; level += 1) {
151
+ const isLeft = index % 2n === 0n;
152
+ const sibling = this.getNode(level, isLeft ? index + 1n : index - 1n);
153
+ isLefts.push(Bool(isLeft));
154
+ path.push(sibling);
155
+ index /= 2n;
156
+ }
157
+ return new RollupMerkleWitness({
158
+ isLeft: isLefts,
159
+ path,
160
+ });
161
+ }
162
+ // eslint-disable-next-line no-warning-comments, max-len
163
+ // TODO: should this take an optional offset? should it fail if the array is too long?
164
+ /**
165
+ * Fills all leaves of the tree.
166
+ * @param leaves Values to fill the leaves with.
167
+ */
168
+ fill(leaves) {
169
+ leaves.forEach((value, index) => {
170
+ this.setLeaf(BigInt(index), value);
171
+ });
172
+ }
173
+ /**
174
+ * Returns the amount of leaf nodes.
175
+ * @returns Amount of leaf nodes.
176
+ */
177
+ get leafCount() {
178
+ return RollupMerkleTree.leafCount;
179
+ }
180
+ }
181
+ RollupMerkleTree.height = 256;
182
+ __decorate([
183
+ notInCircuit(),
184
+ __metadata("design:type", Function),
185
+ __metadata("design:paramtypes", [Number, BigInt]),
186
+ __metadata("design:returntype", Field)
187
+ ], RollupMerkleTree.prototype, "getNode", null);
188
+ __decorate([
189
+ notInCircuit(),
190
+ __metadata("design:type", Function),
191
+ __metadata("design:paramtypes", []),
192
+ __metadata("design:returntype", Field)
193
+ ], RollupMerkleTree.prototype, "getRoot", null);
194
+ __decorate([
195
+ notInCircuit(),
196
+ __metadata("design:type", Function),
197
+ __metadata("design:paramtypes", [BigInt, Field]),
198
+ __metadata("design:returntype", void 0)
199
+ ], RollupMerkleTree.prototype, "setLeaf", null);
200
+ __decorate([
201
+ notInCircuit(),
202
+ __metadata("design:type", Function),
203
+ __metadata("design:paramtypes", [BigInt]),
204
+ __metadata("design:returntype", RollupMerkleWitness)
205
+ ], RollupMerkleTree.prototype, "getWitness", null);
206
+ __decorate([
207
+ notInCircuit(),
208
+ __metadata("design:type", Function),
209
+ __metadata("design:paramtypes", [Array]),
210
+ __metadata("design:returntype", void 0)
211
+ ], RollupMerkleTree.prototype, "fill", null);
212
+ // eslint-disable-next-line @typescript-eslint/no-namespace
213
+ export var MerkleTreeUtils;
214
+ (function (MerkleTreeUtils) {
215
+ function normalizeKey(key) {
216
+ // if(NJORD_MERKLE_TREE_HEIGHT < 256){
217
+ // return fieldMod(key, Field(RollupMerkleTree.leafCount).toConstant())
218
+ // eslint-disable-next-line max-len
219
+ // // return modPower2(key, RollupMerkleTree.height - 1) //TODO Fix modPower2
220
+ // }else{
221
+ return key;
222
+ // }
223
+ }
224
+ MerkleTreeUtils.normalizeKey = normalizeKey;
225
+ function checkMembership(witness, root, key, value) {
226
+ const root2 = witness.calculateRoot(value);
227
+ const key2 = witness.calculateIndex();
228
+ key.assertEquals(key2, "Keys of MerkleWitness does not match");
229
+ return root.equals(root2);
230
+ }
231
+ MerkleTreeUtils.checkMembership = checkMembership;
232
+ function computeRoot(witness, value) {
233
+ return witness.calculateRoot(value);
234
+ }
235
+ MerkleTreeUtils.computeRoot = computeRoot;
236
+ })(MerkleTreeUtils || (MerkleTreeUtils = {}));
237
+ /**
238
+ * More efficient version of `maybeSwapBad` which
239
+ * reuses an intermediate variable
240
+ */
241
+ function maybeSwap(b, x, y) {
242
+ const m = b.toField().mul(x.sub(y)); // b*(x - y)
243
+ const x1 = y.add(m); // y + b*(x - y)
244
+ const y2 = x.sub(m); // x - b*(x - y) = x + b*(y - x)
245
+ return [x1, y2];
246
+ }
@@ -0,0 +1,2 @@
1
+ export declare function requireTrue(condition: boolean, errorOrFunction: Error | (() => Error)): void;
2
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CACzB,SAAS,EAAE,OAAO,EAClB,eAAe,EAAE,KAAK,GAAG,CAAC,MAAM,KAAK,CAAC,GACrC,IAAI,CAMN"}
package/dist/utils.js ADDED
@@ -0,0 +1,7 @@
1
+ export function requireTrue(condition, errorOrFunction) {
2
+ if (!condition) {
3
+ throw typeof errorOrFunction === "function"
4
+ ? errorOrFunction()
5
+ : errorOrFunction;
6
+ }
7
+ }
@@ -0,0 +1,53 @@
1
+ import type { FlexibleProvable, Proof } from "snarkyjs";
2
+ export declare class ProvableMethodExecutionResult {
3
+ moduleName?: string;
4
+ methodName?: string;
5
+ args?: FlexibleProvable<unknown>[];
6
+ prover?: () => Promise<Proof<unknown, unknown>>;
7
+ prove<ProofType extends Proof<unknown, unknown>>(): Promise<ProofType>;
8
+ }
9
+ /**
10
+ * Execution context used to wrap runtime module methods,
11
+ * allowing them to post relevant information (such as execution status)
12
+ * into the context without any unnecessary 'prop drilling'.
13
+ */
14
+ export declare class ProvableMethodExecutionContext {
15
+ id: string;
16
+ methods: string[];
17
+ result: ProvableMethodExecutionResult;
18
+ /**
19
+ * Adds a method prover to the current execution context,
20
+ * which can be collected and ran asynchronously at a later point in time.
21
+ *
22
+ * @param prove - Prover function to be ran later,
23
+ * when the method execution needs to be proven
24
+ */
25
+ setProver(prover: () => Promise<Proof<unknown, unknown>>): void;
26
+ /**
27
+ * Adds a method to the method execution stack, reseting the execution context
28
+ * in a case a new top-level (non nested) method call is made.
29
+ *
30
+ * @param methodName - Name of the method being captured in the context
31
+ */
32
+ beforeMethod(moduleName: string, methodName: string, args: FlexibleProvable<unknown>[]): void;
33
+ /**
34
+ * Removes the latest method from the execution context stack,
35
+ * keeping track of the amount of 'unfinished' methods. Allowing
36
+ * for the context to distinguish between top-level and nested method calls.
37
+ */
38
+ afterMethod(): void;
39
+ get isTopLevel(): boolean;
40
+ get isFinished(): boolean;
41
+ /**
42
+ * @returns - Current execution context state
43
+ */
44
+ current(): {
45
+ isFinished: boolean;
46
+ result: ProvableMethodExecutionResult;
47
+ };
48
+ /**
49
+ * Manually clears/resets the execution context
50
+ */
51
+ clear(): void;
52
+ }
53
+ //# sourceMappingURL=ProvableMethodExecutionContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProvableMethodExecutionContext.d.ts","sourceRoot":"","sources":["../../src/zkProgrammable/ProvableMethodExecutionContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAaxD,qBAAa,6BAA6B;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,IAAI,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC;IAEnC,MAAM,CAAC,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAE1C,KAAK,CAEhB,SAAS,SAAS,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,KACtC,OAAO,CAAC,SAAS,CAAC;CAaxB;AAED;;;;GAIG;AACH,qBACa,8BAA8B;IAClC,EAAE,SAAc;IAEhB,OAAO,EAAE,MAAM,EAAE,CAAM;IAEvB,MAAM,EAAE,6BAA6B,CACN;IAItC;;;;;;OAMG;IACI,SAAS,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAI/D;;;;;OAKG;IACI,YAAY,CACjB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,gBAAgB,CAAC,OAAO,CAAC,EAAE;IAYnC;;;;OAIG;IACI,WAAW;IAIlB,IAAW,UAAU,YAEpB;IAED,IAAW,UAAU,YAEpB;IAED;;OAEG;IACI,OAAO;;;;IAOd;;OAEG;IACI,KAAK;CAGb"}
@@ -0,0 +1,98 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { singleton } from "tsyringe";
8
+ import uniqueId from "lodash/uniqueId";
9
+ const errors = {
10
+ moduleOrMethodNameNotSet: () => new Error("Module or method name not set"),
11
+ proverNotSet: (moduleName, methodName) => new Error(`Prover not set for '${moduleName}.${methodName}', did you forget to decorate your method?`),
12
+ };
13
+ export class ProvableMethodExecutionResult {
14
+ async prove() {
15
+ if (!this.prover) {
16
+ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
17
+ if (!this.moduleName || !this.methodName) {
18
+ throw errors.moduleOrMethodNameNotSet();
19
+ }
20
+ throw errors.proverNotSet(this.moduleName, this.methodName);
21
+ }
22
+ // turn the prover result into the desired proof type
23
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
24
+ return (await this.prover());
25
+ }
26
+ }
27
+ /**
28
+ * Execution context used to wrap runtime module methods,
29
+ * allowing them to post relevant information (such as execution status)
30
+ * into the context without any unnecessary 'prop drilling'.
31
+ */
32
+ let ProvableMethodExecutionContext = class ProvableMethodExecutionContext {
33
+ constructor() {
34
+ this.id = uniqueId();
35
+ this.methods = [];
36
+ this.result = new ProvableMethodExecutionResult();
37
+ }
38
+ // eslint-disable-next-line no-warning-comments,max-len
39
+ // TODO See if we should make this class generic, bc I think we can persist the type
40
+ /**
41
+ * Adds a method prover to the current execution context,
42
+ * which can be collected and ran asynchronously at a later point in time.
43
+ *
44
+ * @param prove - Prover function to be ran later,
45
+ * when the method execution needs to be proven
46
+ */
47
+ setProver(prover) {
48
+ this.result.prover = prover;
49
+ }
50
+ /**
51
+ * Adds a method to the method execution stack, reseting the execution context
52
+ * in a case a new top-level (non nested) method call is made.
53
+ *
54
+ * @param methodName - Name of the method being captured in the context
55
+ */
56
+ beforeMethod(moduleName, methodName, args) {
57
+ if (this.isFinished) {
58
+ this.clear();
59
+ this.result.moduleName = moduleName;
60
+ this.result.methodName = methodName;
61
+ this.result.args = args;
62
+ }
63
+ this.methods.push(methodName);
64
+ }
65
+ /**
66
+ * Removes the latest method from the execution context stack,
67
+ * keeping track of the amount of 'unfinished' methods. Allowing
68
+ * for the context to distinguish between top-level and nested method calls.
69
+ */
70
+ afterMethod() {
71
+ this.methods.pop();
72
+ }
73
+ get isTopLevel() {
74
+ return this.methods.length === 1;
75
+ }
76
+ get isFinished() {
77
+ return this.methods.length === 0;
78
+ }
79
+ /**
80
+ * @returns - Current execution context state
81
+ */
82
+ current() {
83
+ return {
84
+ isFinished: this.isFinished,
85
+ result: this.result,
86
+ };
87
+ }
88
+ /**
89
+ * Manually clears/resets the execution context
90
+ */
91
+ clear() {
92
+ this.result = new ProvableMethodExecutionResult();
93
+ }
94
+ };
95
+ ProvableMethodExecutionContext = __decorate([
96
+ singleton()
97
+ ], ProvableMethodExecutionContext);
98
+ export { ProvableMethodExecutionContext };
@@ -0,0 +1,32 @@
1
+ import { Experimental, FlexibleProvablePure, Proof } from "snarkyjs";
2
+ export interface CompileArtifact {
3
+ verificationKey: string;
4
+ }
5
+ export interface AreProofsEnabled {
6
+ areProofsEnabled: boolean;
7
+ setProofsEnabled: (areProofsEnabled: boolean) => void;
8
+ }
9
+ export interface Verify<PublicInput, PublicOutput> {
10
+ (proof: Proof<PublicInput, PublicOutput>): Promise<boolean>;
11
+ }
12
+ export interface Compile {
13
+ (): Promise<CompileArtifact>;
14
+ }
15
+ export interface PlainZkProgram<PublicInput = undefined, PublicOutput = void> {
16
+ compile: Compile;
17
+ verify: Verify<PublicInput, PublicOutput>;
18
+ Proof: ReturnType<typeof Experimental.ZkProgram.Proof<FlexibleProvablePure<PublicInput>, FlexibleProvablePure<PublicOutput>>>;
19
+ methods: Record<string, ((...args: any) => Promise<Proof<PublicInput, PublicOutput>>) | ((publicInput: PublicInput, ...args: any) => Promise<Proof<PublicInput, PublicOutput>>)>;
20
+ }
21
+ export declare function verifyToMockable<PublicInput, PublicOutput>(verify: Verify<PublicInput, PublicOutput>, { areProofsEnabled }: AreProofsEnabled): (proof: Proof<PublicInput, PublicOutput>) => Promise<boolean>;
22
+ export declare const mockVerificationKey = "mock-verification-key";
23
+ export declare function compileToMockable(compile: Compile, { areProofsEnabled }: AreProofsEnabled): () => Promise<CompileArtifact>;
24
+ export declare abstract class ZkProgrammable<PublicInput = undefined, PublicOutput = void> {
25
+ abstract get appChain(): AreProofsEnabled | undefined;
26
+ abstract zkProgramFactory(): PlainZkProgram<PublicInput, PublicOutput>;
27
+ get zkProgram(): PlainZkProgram<PublicInput, PublicOutput>;
28
+ }
29
+ export interface WithZkProgrammable<PublicInput = undefined, PublicOutput = void> {
30
+ zkProgrammable: ZkProgrammable<PublicInput, PublicOutput>;
31
+ }
32
+ //# sourceMappingURL=ZkProgrammable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ZkProgrammable.d.ts","sourceRoot":"","sources":["../../src/zkProgrammable/ZkProgrammable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAUrE,MAAM,WAAW,eAAe;IAC9B,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,gBAAgB,EAAE,CAAC,gBAAgB,EAAE,OAAO,KAAK,IAAI,CAAC;CACvD;AAED,MAAM,WAAW,MAAM,CAAC,WAAW,EAAE,YAAY;IAC/C,CAAC,KAAK,EAAE,KAAK,CAAC,WAAW,EAAE,YAAY,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC7D;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,OAAO,CAAC,eAAe,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,cAAc,CAAC,WAAW,GAAG,SAAS,EAAE,YAAY,GAAG,IAAI;IAC1E,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IAC1C,KAAK,EAAE,UAAU,CACf,OAAO,YAAY,CAAC,SAAS,CAAC,KAAK,CACjC,oBAAoB,CAAC,WAAW,CAAC,EACjC,oBAAoB,CAAC,YAAY,CAAC,CACnC,CACF,CAAC;IACF,OAAO,EAAE,MAAM,CACb,MAAM,EACJ,CAAC,CAEC,GAAG,IAAI,EAAE,GAAG,KACT,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC,GAC/C,CAAC,CACC,WAAW,EAAE,WAAW,EAExB,GAAG,IAAI,EAAE,GAAG,KACT,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC,CAClD,CAAC;CACH;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,YAAY,EACxD,MAAM,EAAE,MAAM,CAAC,WAAW,EAAE,YAAY,CAAC,EACzC,EAAE,gBAAgB,EAAE,EAAE,gBAAgB,WAEjB,MAAM,WAAW,EAAE,YAAY,CAAC,sBAiBtD;AAED,eAAO,MAAM,mBAAmB,0BAA0B,CAAC;AAC3D,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,OAAO,EAChB,EAAE,gBAAgB,EAAE,EAAE,gBAAgB,GACrC,MAAM,OAAO,CAAC,eAAe,CAAC,CAUhC;AAED,8BAAsB,cAAc,CAClC,WAAW,GAAG,SAAS,EACvB,YAAY,GAAG,IAAI;IAEnB,aAAoB,QAAQ,IAAI,gBAAgB,GAAG,SAAS,CAAC;aAE7C,gBAAgB,IAAI,cAAc,CAAC,WAAW,EAAE,YAAY,CAAC;IAE7E,IACW,SAAS,IAAI,cAAc,CAAC,WAAW,EAAE,YAAY,CAAC,CAYhE;CACF;AAED,MAAM,WAAW,kBAAkB,CACjC,WAAW,GAAG,SAAS,EACvB,YAAY,GAAG,IAAI;IAEnB,cAAc,EAAE,cAAc,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;CAC3D"}
@@ -0,0 +1,60 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { Memoize } from "typescript-memoize";
11
+ import { mockProof } from "./provableMethod";
12
+ const errors = {
13
+ appChainNotSet: (name) => new Error(`Appchain was not injected for: ${name}`),
14
+ };
15
+ export function verifyToMockable(verify, { areProofsEnabled }) {
16
+ return async (proof) => {
17
+ if (areProofsEnabled) {
18
+ let verified = false;
19
+ try {
20
+ verified = await verify(proof);
21
+ }
22
+ catch (error) {
23
+ // silently fail verification
24
+ console.error(error);
25
+ verified = false;
26
+ }
27
+ return verified;
28
+ }
29
+ return proof.proof === mockProof;
30
+ };
31
+ }
32
+ export const mockVerificationKey = "mock-verification-key";
33
+ export function compileToMockable(compile, { areProofsEnabled }) {
34
+ return async () => {
35
+ if (areProofsEnabled) {
36
+ return await compile();
37
+ }
38
+ return {
39
+ verificationKey: mockVerificationKey,
40
+ };
41
+ };
42
+ }
43
+ export class ZkProgrammable {
44
+ get zkProgram() {
45
+ const zkProgram = this.zkProgramFactory();
46
+ if (!this.appChain) {
47
+ throw errors.appChainNotSet(this.constructor.name);
48
+ }
49
+ return {
50
+ ...zkProgram,
51
+ verify: verifyToMockable(zkProgram.verify, this.appChain),
52
+ compile: compileToMockable(zkProgram.compile, this.appChain),
53
+ };
54
+ }
55
+ }
56
+ __decorate([
57
+ Memoize(),
58
+ __metadata("design:type", Object),
59
+ __metadata("design:paramtypes", [])
60
+ ], ZkProgrammable.prototype, "zkProgram", null);
@@ -0,0 +1,16 @@
1
+ import { ProvableMethodExecutionContext } from "./ProvableMethodExecutionContext";
2
+ import type { ZkProgrammable } from "./ZkProgrammable";
3
+ export type DecoratedMethod = (...args: unknown[]) => unknown;
4
+ export declare const mockProof = "mock-proof";
5
+ export declare function toProver(methodName: string, simulatedMethod: DecoratedMethod, isFirstParameterPublicInput: boolean, ...args: unknown[]): (this: ZkProgrammable<any, any>) => Promise<import("snarkyjs/dist/node/lib/proof_system").Proof<any, any>>;
6
+ /**
7
+ * Decorates a provable method on a 'prover class', depending on
8
+ * if proofs are enabled or not, either runs the respective zkProgram prover,
9
+ * or simulates the method execution and issues a mock proof.
10
+ *
11
+ * @param isFirstParameterPublicInput
12
+ * @param executionContext
13
+ * @returns
14
+ */
15
+ export declare function provableMethod(isFirstParameterPublicInput?: boolean, executionContext?: ProvableMethodExecutionContext): <Target extends ZkProgrammable<any, any>>(target: Target, methodName: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
16
+ //# sourceMappingURL=provableMethod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provableMethod.d.ts","sourceRoot":"","sources":["../../src/zkProgrammable/provableMethod.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,8BAA8B,EAAE,MAAM,kCAAkC,CAAC;AAClF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGvD,MAAM,MAAM,eAAe,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;AAE9D,eAAO,MAAM,SAAS,eAAe,CAAC;AAEtC,wBAAgB,QAAQ,CACtB,UAAU,EAAE,MAAM,EAClB,eAAe,EAAE,eAAe,EAChC,2BAA2B,EAAE,OAAO,EACpC,GAAG,IAAI,EAAE,OAAO,EAAE,UAGiB,eAAe,GAAG,EAAE,GAAG,CAAC,4EAyB5D;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,2BAA2B,UAAO,EAClC,gBAAgB,GAAE,8BAEjB,yEAKa,MAAM,cACN,kBAAkB,wBA4CjC"}
@@ -0,0 +1,69 @@
1
+ import { container } from "tsyringe";
2
+ import { ProvableMethodExecutionContext } from "./ProvableMethodExecutionContext";
3
+ export const mockProof = "mock-proof";
4
+ export function toProver(methodName, simulatedMethod, isFirstParameterPublicInput, ...args) {
5
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
+ return async function prover() {
7
+ const areProofsEnabled = this.appChain?.areProofsEnabled;
8
+ if (areProofsEnabled ?? false) {
9
+ const programProvableMethod = this.zkProgram.methods[methodName];
10
+ return await Reflect.apply(programProvableMethod, this, args);
11
+ }
12
+ // create a mock proof by simulating method execution in JS
13
+ const publicOutput = Reflect.apply(simulatedMethod, this, args);
14
+ return new this.zkProgram.Proof({
15
+ proof: mockProof,
16
+ // eslint-disable-next-line no-warning-comments
17
+ // TODO: provide undefined if public input is not used
18
+ publicInput: isFirstParameterPublicInput ? args[0] : undefined,
19
+ publicOutput,
20
+ /**
21
+ * We set this to the max possible number, to avoid having
22
+ * to manually count in-circuit proof verifications
23
+ */
24
+ maxProofsVerified: 2,
25
+ });
26
+ };
27
+ }
28
+ /**
29
+ * Decorates a provable method on a 'prover class', depending on
30
+ * if proofs are enabled or not, either runs the respective zkProgram prover,
31
+ * or simulates the method execution and issues a mock proof.
32
+ *
33
+ * @param isFirstParameterPublicInput
34
+ * @param executionContext
35
+ * @returns
36
+ */
37
+ export function provableMethod(isFirstParameterPublicInput = true, executionContext = container.resolve(ProvableMethodExecutionContext)) {
38
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
39
+ return (target, methodName, descriptor) => {
40
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
41
+ const simulatedMethod = descriptor.value;
42
+ descriptor.value = function value(...args) {
43
+ const prover = toProver(methodName, simulatedMethod, isFirstParameterPublicInput, ...args);
44
+ executionContext.beforeMethod(this.constructor.name, methodName, args);
45
+ /**
46
+ * Check if the method is called at the top level,
47
+ * if yes then create a prover.
48
+ */
49
+ if (executionContext.isTopLevel) {
50
+ executionContext.setProver(prover.bind(this));
51
+ }
52
+ /**
53
+ * Regardless of if the method is called from the top level
54
+ * or not, execute its simulated (Javascript) version and
55
+ * return the result.
56
+ */
57
+ // eslint-disable-next-line @typescript-eslint/init-declarations
58
+ let result;
59
+ try {
60
+ result = Reflect.apply(simulatedMethod, this, args);
61
+ }
62
+ finally {
63
+ executionContext.afterMethod();
64
+ }
65
+ return result;
66
+ };
67
+ return descriptor;
68
+ };
69
+ }
@@ -0,0 +1 @@
1
+ module.exports = require("../../jest.config.cjs");
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@proto-kit/common",
3
+ "license": "MIT",
4
+ "private": false,
5
+ "type": "module",
6
+ "version": "0.1.1-develop.153+10a7974",
7
+ "scripts": {
8
+ "build": "tsc -p tsconfig.json",
9
+ "dev": "tsc -p tsconfig.json --watch",
10
+ "lint": "eslint ./src ./test",
11
+ "test:file": "node --experimental-vm-modules --experimental-wasm-modules --experimental-wasm-threads ../../node_modules/jest/bin/jest.js",
12
+ "test": "npm run test:file -- ./src/** ./test/**",
13
+ "test:watch": "npm run test:file -- ./src/** ./test/** --watch"
14
+ },
15
+ "main": "dist/index.js",
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "dependencies": {
20
+ "lodash": "^4.17.21",
21
+ "loglevel": "^1.8.1",
22
+ "reflect-metadata": "^0.1.13",
23
+ "tsyringe": "^4.7.0",
24
+ "typescript-memoize": "^1.1.1"
25
+ },
26
+ "peerDependencies": {
27
+ "snarkyjs": "0.11.0",
28
+ "tsyringe": "^4.7.0"
29
+ },
30
+ "devDependencies": {
31
+ "@jest/globals": "^29.5.0",
32
+ "@types/lodash": "^4.14.194"
33
+ },
34
+ "gitHead": "10a7974582f79be6f4f099eec83c4b0359cce2a6"
35
+ }