@proto-kit/module 0.1.1-develop.191 → 0.1.1-develop.2024

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 (110) hide show
  1. package/dist/factories/MethodIdFactory.d.ts +6 -6
  2. package/dist/factories/MethodIdFactory.d.ts.map +1 -1
  3. package/dist/factories/MethodIdFactory.js +10 -34
  4. package/dist/factories/MethodIdFactory.js.map +1 -0
  5. package/dist/index.d.ts +4 -7
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +5 -7
  8. package/dist/index.js.map +1 -0
  9. package/dist/messages/OutgoingMessage.d.ts +96 -0
  10. package/dist/messages/OutgoingMessage.d.ts.map +1 -0
  11. package/dist/messages/OutgoingMessage.js +68 -0
  12. package/dist/messages/OutgoingMessage.js.map +1 -0
  13. package/dist/messages/OutgoingMessages.d.ts +231 -0
  14. package/dist/messages/OutgoingMessages.d.ts.map +1 -0
  15. package/dist/messages/OutgoingMessages.js +66 -0
  16. package/dist/messages/OutgoingMessages.js.map +1 -0
  17. package/dist/method/MethodParameterEncoder.d.ts +26 -0
  18. package/dist/method/MethodParameterEncoder.d.ts.map +1 -0
  19. package/dist/method/MethodParameterEncoder.js +169 -0
  20. package/dist/method/MethodParameterEncoder.js.map +1 -0
  21. package/dist/method/runtimeMethod.d.ts +21 -5
  22. package/dist/method/runtimeMethod.d.ts.map +1 -1
  23. package/dist/method/runtimeMethod.js +69 -25
  24. package/dist/method/runtimeMethod.js.map +1 -0
  25. package/dist/module/decorator.js +1 -0
  26. package/dist/module/decorator.js.map +1 -0
  27. package/dist/runtime/MethodIdResolver.d.ts +10 -8
  28. package/dist/runtime/MethodIdResolver.d.ts.map +1 -1
  29. package/dist/runtime/MethodIdResolver.js +74 -33
  30. package/dist/runtime/MethodIdResolver.js.map +1 -0
  31. package/dist/runtime/Runtime.d.ts +20 -26
  32. package/dist/runtime/Runtime.d.ts.map +1 -1
  33. package/dist/runtime/Runtime.js +117 -62
  34. package/dist/runtime/Runtime.js.map +1 -0
  35. package/dist/runtime/RuntimeEnvironment.d.ts +10 -0
  36. package/dist/runtime/RuntimeEnvironment.d.ts.map +1 -0
  37. package/dist/runtime/RuntimeEnvironment.js +2 -0
  38. package/dist/runtime/RuntimeEnvironment.js.map +1 -0
  39. package/dist/runtime/RuntimeModule.d.ts +18 -15
  40. package/dist/runtime/RuntimeModule.d.ts.map +1 -1
  41. package/dist/runtime/RuntimeModule.js +33 -8
  42. package/dist/runtime/RuntimeModule.js.map +1 -0
  43. package/dist/state/InMemoryStateService.d.ts +11 -10
  44. package/dist/state/InMemoryStateService.d.ts.map +1 -1
  45. package/dist/state/InMemoryStateService.js +11 -8
  46. package/dist/state/InMemoryStateService.js.map +1 -0
  47. package/dist/state/decorator.d.ts.map +1 -1
  48. package/dist/state/decorator.js +2 -4
  49. package/dist/state/decorator.js.map +1 -0
  50. package/dist/testing/TestingRuntime.d.ts +8 -0
  51. package/dist/testing/TestingRuntime.d.ts.map +1 -0
  52. package/dist/testing/TestingRuntime.js +31 -0
  53. package/dist/testing/TestingRuntime.js.map +1 -0
  54. package/jest.config.cjs +12 -1
  55. package/package.json +10 -11
  56. package/src/factories/MethodIdFactory.ts +10 -17
  57. package/src/index.ts +4 -7
  58. package/src/messages/OutgoingMessages.ts +122 -0
  59. package/src/method/MethodParameterEncoder.ts +262 -0
  60. package/src/method/runtimeMethod.ts +130 -33
  61. package/src/runtime/MethodIdResolver.ts +83 -46
  62. package/src/runtime/Runtime.ts +193 -100
  63. package/src/runtime/RuntimeEnvironment.ts +16 -0
  64. package/src/runtime/RuntimeModule.ts +62 -30
  65. package/src/state/InMemoryStateService.ts +14 -18
  66. package/test/Runtime.test.ts +68 -42
  67. package/test/TestingRuntime.ts +43 -0
  68. package/test/messages/message.test.ts +42 -0
  69. package/test/method/MethodParameterEncoder.test.ts +124 -0
  70. package/test/method/runtimeMethod-fail.test.ts +53 -0
  71. package/{src/method/decorator.test.ts → test/method/runtimeMethod.test.ts} +3 -3
  72. package/test/modules/Admin.ts +4 -4
  73. package/test/modules/Balances.test.ts +92 -78
  74. package/test/modules/Balances.ts +15 -17
  75. package/test/modules/{methodId.test.ts → MethodIdResolver.test.ts} +24 -36
  76. package/test/modules/State.test.ts +81 -0
  77. package/test/runtimeMethod.test.ts +192 -20
  78. package/test/tsconfig.json +7 -0
  79. package/tsconfig.json +2 -2
  80. package/LICENSE.md +0 -201
  81. package/dist/method/MethodParameterDecoder.d.ts +0 -22
  82. package/dist/method/MethodParameterDecoder.d.ts.map +0 -1
  83. package/dist/method/MethodParameterDecoder.js +0 -33
  84. package/dist/method/RuntimeMethodExecutionContext.d.ts +0 -57
  85. package/dist/method/RuntimeMethodExecutionContext.d.ts.map +0 -1
  86. package/dist/method/RuntimeMethodExecutionContext.js +0 -92
  87. package/dist/method/assert.d.ts +0 -12
  88. package/dist/method/assert.d.ts.map +0 -1
  89. package/dist/method/assert.js +0 -23
  90. package/dist/state/State.d.ts +0 -65
  91. package/dist/state/State.d.ts.map +0 -1
  92. package/dist/state/State.js +0 -114
  93. package/dist/state/StateMap.d.ts +0 -37
  94. package/dist/state/StateMap.d.ts.map +0 -1
  95. package/dist/state/StateMap.js +0 -56
  96. package/dist/state/StateServiceProvider.d.ts +0 -10
  97. package/dist/state/StateServiceProvider.d.ts.map +0 -1
  98. package/dist/state/StateServiceProvider.js +0 -34
  99. package/src/method/MethodParameterDecoder.ts +0 -68
  100. package/src/method/RuntimeMethodExecutionContext.ts +0 -111
  101. package/src/method/assert.test.ts +0 -49
  102. package/src/method/assert.ts +0 -27
  103. package/src/state/State.ts +0 -154
  104. package/src/state/StateMap.ts +0 -69
  105. package/src/state/StateServiceProvider.ts +0 -24
  106. package/src/state/decorator.ts +0 -65
  107. package/test/state/MerkleTree.test.ts +0 -95
  108. package/test/state/MockAsyncMerkleStore.ts +0 -28
  109. package/test/transaction.test.ts +0 -82
  110. package/tsconfig.test.json +0 -9
@@ -1,32 +1,54 @@
1
- // eslint-disable-next-line max-len
2
- /* eslint-disable @typescript-eslint/no-explicit-any,@typescript-eslint/no-unsafe-assignment,max-lines */
3
- import { Experimental } from "snarkyjs";
4
- import { DependencyContainer, injectable } from "tsyringe";
1
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-argument */
2
+ import { ZkProgram } from "o1js";
3
+ import { container, DependencyContainer, injectable } from "tsyringe";
5
4
  import {
6
5
  StringKeyOf,
7
6
  ModuleContainer,
8
- ModulesConfig,
9
7
  ModulesRecord,
10
8
  TypedClass,
11
9
  ZkProgrammable,
12
10
  PlainZkProgram,
13
- WithZkProgrammable,
14
11
  AreProofsEnabled,
12
+ ChildContainerProvider,
13
+ CompilableModule,
14
+ CompileRegistry,
15
15
  } from "@proto-kit/common";
16
- import { MethodPublicOutput } from "@proto-kit/protocol";
16
+ import {
17
+ MethodPublicOutput,
18
+ StateServiceProvider,
19
+ SimpleAsyncStateService,
20
+ RuntimeMethodExecutionContext,
21
+ RuntimeTransaction,
22
+ NetworkState,
23
+ } from "@proto-kit/protocol";
17
24
 
18
25
  import {
19
26
  combineMethodName,
20
27
  isRuntimeMethod,
28
+ runtimeMethodTypeMetadataKey,
21
29
  toWrappedMethod,
22
- WrappedMethod,
23
- } from "../method/runtimeMethod.js";
24
- import { StateService } from "../state/InMemoryStateService.js";
25
- import { StateServiceProvider } from "../state/StateServiceProvider";
30
+ AsyncWrappedMethod,
31
+ } from "../method/runtimeMethod";
26
32
  import { MethodIdFactory } from "../factories/MethodIdFactory";
27
33
 
28
- import { RuntimeModule } from "./RuntimeModule.js";
34
+ import { RuntimeModule } from "./RuntimeModule";
29
35
  import { MethodIdResolver } from "./MethodIdResolver";
36
+ import { RuntimeEnvironment } from "./RuntimeEnvironment";
37
+
38
+ export function getAllPropertyNames(obj: any) {
39
+ let currentPrototype: any | undefined = obj;
40
+ let keys: (string | symbol)[] = [];
41
+ // if primitive (primitives still have keys) skip the first iteration
42
+ if (!(obj instanceof Object)) {
43
+ currentPrototype = Object.getPrototypeOf(obj);
44
+ }
45
+ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
46
+ while (currentPrototype) {
47
+ keys = keys.concat(Reflect.ownKeys(currentPrototype));
48
+ currentPrototype = Object.getPrototypeOf(currentPrototype);
49
+ }
50
+ return keys;
51
+ }
30
52
 
31
53
  /**
32
54
  * Record of modules accepted by the Runtime module container.
@@ -43,66 +65,56 @@ const errors = {
43
65
  new Error(`Unable to find method with id ${methodKey}`),
44
66
  };
45
67
 
46
- /**
47
- * Definition / required arguments for the Runtime class
48
- */
49
- export interface RuntimeDefinition<Modules extends RuntimeModulesRecord> {
50
- state: StateService;
51
- modules: Modules;
52
- config?: ModulesConfig<Modules>;
53
- }
54
-
55
68
  export class RuntimeZkProgrammable<
56
- Modules extends RuntimeModulesRecord
69
+ Modules extends RuntimeModulesRecord,
57
70
  > extends ZkProgrammable<undefined, MethodPublicOutput> {
58
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
59
71
  public constructor(public runtime: Runtime<Modules>) {
60
72
  super();
61
73
  }
62
74
 
63
- public get appChain() {
64
- return this.runtime.appChain;
75
+ public get areProofsEnabled() {
76
+ return this.runtime.areProofsEnabled;
65
77
  }
66
78
 
67
- public zkProgramFactory(): PlainZkProgram<undefined, MethodPublicOutput> {
79
+ public zkProgramFactory(): PlainZkProgram<undefined, MethodPublicOutput>[] {
68
80
  type Methods = Record<
69
81
  string,
70
82
  {
71
83
  privateInputs: any;
72
- method: WrappedMethod;
84
+ method: AsyncWrappedMethod;
73
85
  }
74
86
  >;
75
87
  // We need to use explicit type annotations here,
76
88
  // therefore we can't use destructuring
77
- // eslint-disable-next-line max-len
78
- // eslint-disable-next-line @typescript-eslint/no-use-before-define,prefer-destructuring,putout/putout
89
+
90
+ // eslint-disable-next-line prefer-destructuring
79
91
  const runtime: Runtime<Modules> = this.runtime;
80
92
 
93
+ const MAXIMUM_METHODS_PER_ZK_PROGRAM = 8;
94
+
81
95
  const runtimeMethods = runtime.runtimeModuleNames.reduce<Methods>(
82
96
  (allMethods, runtimeModuleName) => {
83
- runtime.isValidModuleName(
84
- runtime.definition.modules,
85
- runtimeModuleName
86
- );
97
+ runtime.isValidModuleName(runtime.definition, runtimeModuleName);
87
98
 
88
99
  /**
89
100
  * Couldnt find a better way to circumvent the type assertion
90
101
  * regarding resolving only known modules. We assert in the line above
91
102
  * but we cast it to any anyways to satisfy the proof system.
92
103
  */
93
- // eslint-disable-next-line max-len
104
+
94
105
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
95
106
  const runtimeModule = runtime.resolve(runtimeModuleName as any);
96
107
 
97
- // eslint-disable-next-line max-len
98
108
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
99
109
  const modulePrototype = Object.getPrototypeOf(runtimeModule) as Record<
100
110
  string,
101
- (...args: unknown[]) => unknown
111
+ // Technically not all methods have to be async, but for this context it's ok
112
+ (...args: unknown[]) => Promise<unknown>
102
113
  >;
103
114
 
104
- const modulePrototypeMethods =
105
- Object.getOwnPropertyNames(modulePrototype);
115
+ const modulePrototypeMethods = getAllPropertyNames(runtimeModule).map(
116
+ (method) => method.toString()
117
+ );
106
118
 
107
119
  const moduleMethods = modulePrototypeMethods.reduce<Methods>(
108
120
  (allModuleMethods, methodName) => {
@@ -112,14 +124,17 @@ export class RuntimeZkProgrammable<
112
124
  methodName
113
125
  );
114
126
  const method = modulePrototype[methodName];
115
- const wrappedMethod = Reflect.apply(
116
- toWrappedMethod,
127
+ const invocationType = Reflect.getMetadata(
128
+ runtimeMethodTypeMetadataKey,
117
129
  runtimeModule,
118
- [methodName, method]
130
+ methodName
119
131
  );
120
132
 
121
- // eslint-disable-next-line no-warning-comments
122
- // TODO: find out how to import the Tuple type
133
+ const wrappedMethod: AsyncWrappedMethod = Reflect.apply(
134
+ toWrappedMethod,
135
+ runtimeModule,
136
+ [methodName, method, { invocationType }]
137
+ );
123
138
 
124
139
  const privateInputs = Reflect.getMetadata(
125
140
  "design:paramtypes",
@@ -151,30 +166,100 @@ export class RuntimeZkProgrammable<
151
166
  );
152
167
 
153
168
  const sortedRuntimeMethods = Object.fromEntries(
154
- // eslint-disable-next-line @typescript-eslint/require-array-sort-compare
155
169
  Object.entries(runtimeMethods).sort()
156
170
  );
157
171
 
158
- const program = Experimental.ZkProgram({
159
- publicOutput: MethodPublicOutput,
160
- methods: sortedRuntimeMethods,
161
- });
162
-
163
- const SelfProof = Experimental.ZkProgram.Proof(program);
164
-
165
- const methods = Object.keys(sortedRuntimeMethods).reduce<
166
- Record<string, any>
167
- >((boundMethods, methodName) => {
168
- boundMethods[methodName] = program[methodName].bind(program);
169
- return boundMethods;
170
- }, {});
171
-
172
- return {
173
- compile: program.compile.bind(program),
174
- verify: program.verify.bind(program),
175
- Proof: SelfProof,
176
- methods,
172
+ const splitRuntimeMethods = () => {
173
+ const buckets: Array<
174
+ Record<
175
+ string,
176
+ {
177
+ privateInputs: any;
178
+ method: AsyncWrappedMethod;
179
+ }
180
+ >
181
+ > = [];
182
+ Object.entries(sortedRuntimeMethods).forEach(
183
+ async ([methodName, method]) => {
184
+ let methodAdded = false;
185
+ for (const bucket of buckets) {
186
+ if (buckets.length === 0) {
187
+ const record: Record<
188
+ string,
189
+ {
190
+ privateInputs: any;
191
+ method: AsyncWrappedMethod;
192
+ }
193
+ > = {};
194
+ record[methodName] = method;
195
+ buckets.push(record);
196
+ methodAdded = true;
197
+ break;
198
+ } else if (
199
+ Object.keys(bucket).length <=
200
+ MAXIMUM_METHODS_PER_ZK_PROGRAM - 1
201
+ ) {
202
+ bucket[methodName] = method;
203
+ methodAdded = true;
204
+ break;
205
+ }
206
+ }
207
+ if (!methodAdded) {
208
+ const record: Record<
209
+ string,
210
+ {
211
+ privateInputs: any;
212
+ method: AsyncWrappedMethod;
213
+ }
214
+ > = {};
215
+ record[methodName] = method;
216
+ buckets.push(record);
217
+ }
218
+ }
219
+ );
220
+ return buckets;
177
221
  };
222
+
223
+ return splitRuntimeMethods().map((bucket, index) => {
224
+ const name = `RuntimeProgram-${index}`;
225
+ const wrappedBucket = Object.fromEntries(
226
+ Object.entries(bucket).map(([methodName, methodDef]) => [
227
+ methodName,
228
+ {
229
+ privateInputs: methodDef.privateInputs,
230
+ method: async (...args: any[]) => {
231
+ const publicOutput = await methodDef.method(...args);
232
+ return { publicOutput };
233
+ },
234
+ },
235
+ ])
236
+ );
237
+
238
+ const program = ZkProgram({
239
+ name,
240
+ publicOutput: MethodPublicOutput,
241
+ methods: wrappedBucket,
242
+ });
243
+
244
+ const SelfProof = ZkProgram.Proof(program);
245
+
246
+ const methods = Object.keys(bucket).reduce<Record<string, any>>(
247
+ (boundMethods, methodName) => {
248
+ boundMethods[methodName] = program[methodName].bind(program);
249
+ return boundMethods;
250
+ },
251
+ {}
252
+ );
253
+
254
+ return {
255
+ name,
256
+ compile: program.compile.bind(program),
257
+ verify: program.verify.bind(program),
258
+ analyzeMethods: program.analyzeMethods.bind(program),
259
+ Proof: SelfProof,
260
+ methods,
261
+ };
262
+ });
178
263
  }
179
264
  }
180
265
 
@@ -185,59 +270,59 @@ export class RuntimeZkProgrammable<
185
270
  @injectable()
186
271
  export class Runtime<Modules extends RuntimeModulesRecord>
187
272
  extends ModuleContainer<Modules>
188
- implements WithZkProgrammable<undefined, MethodPublicOutput>
273
+ implements RuntimeEnvironment, CompilableModule
189
274
  {
190
275
  public static from<Modules extends RuntimeModulesRecord>(
191
- definition: RuntimeDefinition<Modules>
192
- ) {
193
- return new Runtime(definition);
276
+ definition: Modules
277
+ ): TypedClass<Runtime<Modules>> {
278
+ return class RuntimeScoped extends Runtime<Modules> {
279
+ public constructor() {
280
+ super(definition);
281
+ }
282
+ };
194
283
  }
195
284
 
196
285
  // runtime modules composed into a ZkProgram
197
- public program?: ReturnType<typeof Experimental.ZkProgram>;
286
+ public program?: ReturnType<typeof ZkProgram>;
198
287
 
199
- public definition: RuntimeDefinition<Modules>;
288
+ // No idea why we have to do this, but if we don't re-define it here,
289
+ // js can't access it from the superclass somehow
290
+ public definition: Modules;
200
291
 
201
292
  public zkProgrammable: ZkProgrammable<undefined, MethodPublicOutput>;
202
293
 
203
- // eslint-disable-next-line no-warning-comments
204
- // TODO DI
205
- private readonly stateServiceProviderInstance = new StateServiceProvider(
206
- this.definition.state
207
- );
208
-
209
294
  /**
210
295
  * Creates a new Runtime from the provided config
211
296
  *
212
297
  * @param modules - Configuration object for the constructed Runtime
213
298
  */
214
- public constructor(definition: RuntimeDefinition<Modules>) {
299
+ public constructor(definition: Modules) {
215
300
  super(definition);
216
301
  this.definition = definition;
217
302
  this.zkProgrammable = new RuntimeZkProgrammable<Modules>(this);
218
-
219
- // this.registerDependencyFactories([MethodIdFactory]);
220
303
  }
221
304
 
222
- // eslint-disable-next-line no-warning-comments
223
305
  // TODO Remove after changing DFs to type-based approach
224
- public start() {
225
- this.registerValue({
226
- Runtime: this,
227
- });
228
- this.registerDependencyFactories([MethodIdFactory]);
229
- }
306
+ public create(childContainerProvider: ChildContainerProvider) {
307
+ super.create(childContainerProvider);
230
308
 
231
- public get appChain(): AreProofsEnabled | undefined {
232
- return this.container.resolve<AreProofsEnabled>("AppChain");
309
+ this.useDependencyFactory(MethodIdFactory);
233
310
  }
234
311
 
235
- public get stateService(): StateService {
236
- return this.stateServiceProviderInstance.stateService;
312
+ public get areProofsEnabled(): AreProofsEnabled | undefined {
313
+ return this.container.resolve<AreProofsEnabled>("AreProofsEnabled");
237
314
  }
238
315
 
239
316
  public get stateServiceProvider(): StateServiceProvider {
240
- return this.stateServiceProviderInstance;
317
+ return this.container.resolve<StateServiceProvider>("StateServiceProvider");
318
+ }
319
+
320
+ public get stateService(): SimpleAsyncStateService {
321
+ return this.stateServiceProvider.stateService;
322
+ }
323
+
324
+ public get methodIdResolver(): MethodIdResolver {
325
+ return this.container.resolve<MethodIdResolver>("MethodIdResolver");
241
326
  }
242
327
 
243
328
  /**
@@ -253,28 +338,26 @@ export class Runtime<Modules extends RuntimeModulesRecord>
253
338
  */
254
339
  public getMethodById(
255
340
  methodId: bigint
256
- ): ((...args: unknown[]) => unknown) | undefined {
257
- const methodDescriptor = this.container
258
- .resolve<MethodIdResolver>("MethodIdResolver")
259
- .getMethodNameFromId(methodId);
341
+ ): ((...args: unknown[]) => Promise<unknown>) | undefined {
342
+ const methodDescriptor =
343
+ this.methodIdResolver.getMethodNameFromId(methodId);
260
344
 
261
345
  if (methodDescriptor === undefined) {
262
346
  return undefined;
263
347
  }
264
348
  const [moduleName, methodName] = methodDescriptor;
265
349
 
266
- this.isValidModuleName(this.definition.modules, moduleName);
350
+ this.assertIsValidModuleName(moduleName);
267
351
  const module = this.resolve(moduleName);
268
352
 
269
- // eslint-disable-next-line max-len
270
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions,@typescript-eslint/no-unsafe-member-access
353
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
271
354
  const method = (module as any)[methodName];
272
355
  if (method === undefined) {
273
356
  throw errors.methodNotFound(`${moduleName}.${methodName}`);
274
357
  }
275
358
 
276
359
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
277
- return (method as (...args: unknown[]) => unknown).bind(module);
360
+ return (method as (...args: unknown[]) => Promise<unknown>).bind(module);
278
361
  }
279
362
 
280
363
  /**
@@ -289,7 +372,7 @@ export class Runtime<Modules extends RuntimeModulesRecord>
289
372
  containedModule: InstanceType<Modules[StringKeyOf<Modules>]>
290
373
  ) {
291
374
  containedModule.name = moduleName;
292
- containedModule.runtime = this;
375
+ containedModule.parent = this;
293
376
 
294
377
  super.decorateModule(moduleName, containedModule);
295
378
  }
@@ -298,6 +381,16 @@ export class Runtime<Modules extends RuntimeModulesRecord>
298
381
  * @returns A list of names of all the registered module names
299
382
  */
300
383
  public get runtimeModuleNames() {
301
- return Object.keys(this.definition.modules);
384
+ return this.moduleNames;
385
+ }
386
+
387
+ public async compile(registry: CompileRegistry) {
388
+ const context = container.resolve(RuntimeMethodExecutionContext);
389
+ context.setup({
390
+ transaction: RuntimeTransaction.dummyTransaction(),
391
+ networkState: NetworkState.empty(),
392
+ });
393
+ return await this.zkProgrammable.compile(registry);
302
394
  }
303
395
  }
396
+ /* eslint-enable @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-argument */
@@ -0,0 +1,16 @@
1
+ import { AreProofsEnabled, WithZkProgrammable } from "@proto-kit/common";
2
+ import {
3
+ MethodPublicOutput,
4
+ SimpleAsyncStateService,
5
+ StateServiceProvider,
6
+ } from "@proto-kit/protocol";
7
+
8
+ import { MethodIdResolver } from "./MethodIdResolver";
9
+
10
+ export interface RuntimeEnvironment
11
+ extends WithZkProgrammable<undefined, MethodPublicOutput> {
12
+ get areProofsEnabled(): AreProofsEnabled | undefined;
13
+ get stateService(): SimpleAsyncStateService;
14
+ get stateServiceProvider(): StateServiceProvider;
15
+ get methodIdResolver(): MethodIdResolver;
16
+ }
@@ -1,40 +1,68 @@
1
- import { ConfigurableModule, Presets } from "@proto-kit/common";
1
+ import { ConfigurableModule, NoConfig, Presets } from "@proto-kit/common";
2
2
  import { container, injectable } from "tsyringe";
3
- import { NetworkState, RuntimeTransaction } from "@proto-kit/protocol";
4
-
5
3
  import {
4
+ NetworkState,
5
+ RuntimeTransaction,
6
6
  RuntimeMethodExecutionContext,
7
7
  RuntimeMethodExecutionData,
8
- } from "../method/RuntimeMethodExecutionContext";
9
- import { StateService } from "../state/InMemoryStateService";
8
+ RuntimeMethodExecutionDataStruct,
9
+ } from "@proto-kit/protocol";
10
+ import { FlexibleProvablePure, Provable, Bool } from "o1js";
11
+
10
12
  import { runtimeMethodNamesMetadataKey } from "../method/runtimeMethod";
13
+ import {
14
+ OutgoingMessages,
15
+ OutgoingMessagesRecord,
16
+ } from "../messages/OutgoingMessages";
11
17
 
12
- import type {
13
- Runtime,
14
- RuntimeDefinition,
15
- RuntimeModulesRecord,
16
- } from "./Runtime";
18
+ import { RuntimeEnvironment } from "./RuntimeEnvironment";
17
19
 
18
20
  const errors = {
19
21
  inputDataNotSet: () => new Error("Input data for runtime execution not set"),
20
22
  };
21
23
 
22
- /**
23
- * This type exists to carry over certain runtime properties
24
- * to runtime modules, until we can inject them through DI.
25
- */
26
- export interface PartialRuntime
27
- extends Pick<Runtime<RuntimeModulesRecord>, "zkProgrammable"> {
28
- definition: Pick<RuntimeDefinition<RuntimeModulesRecord>, "state">;
24
+ type EventRecord = Record<string, FlexibleProvablePure<any>>;
25
+
26
+ type InferProvable<T extends FlexibleProvablePure<any>> =
27
+ T extends Provable<infer U> ? U : never;
28
+
29
+ export class RuntimeEvents<Events extends EventRecord> {
30
+ public constructor(private readonly events: Events) {}
31
+
32
+ public emitIf<Key extends keyof Events>(
33
+ condition: Bool,
34
+ eventName: Key,
35
+ event: InferProvable<Events[Key]>
36
+ ) {
37
+ if (this.events === undefined) {
38
+ throw new Error(
39
+ "'events' property not defined, make sure to define the event types on your runtimemodule"
40
+ );
41
+ }
42
+ const eventType: FlexibleProvablePure<any> = this.events[eventName];
43
+ if (typeof eventName !== "string") {
44
+ throw new Error("Only string");
45
+ }
46
+ return container
47
+ .resolve(RuntimeMethodExecutionContext)
48
+ .addEvent(eventType, event, eventName, condition);
49
+ }
29
50
 
30
- get stateService(): StateService;
51
+ public emit<Key extends keyof Events>(
52
+ eventName: Key,
53
+ event: InferProvable<Events[Key]>
54
+ ) {
55
+ this.emitIf(Bool(true), eventName, event);
56
+ }
31
57
  }
32
58
 
33
59
  /**
34
60
  * Base class for runtime modules providing the necessary utilities.
35
61
  */
36
62
  @injectable()
37
- export class RuntimeModule<Config> extends ConfigurableModule<Config> {
63
+ export class RuntimeModule<
64
+ Config = NoConfig,
65
+ > extends ConfigurableModule<Config> {
38
66
  public static presets: Presets<unknown> = {};
39
67
 
40
68
  /**
@@ -51,9 +79,11 @@ export class RuntimeModule<Config> extends ConfigurableModule<Config> {
51
79
 
52
80
  public name?: string;
53
81
 
54
- public test?: number;
82
+ public parent?: RuntimeEnvironment;
55
83
 
56
- public runtime?: Runtime<RuntimeModulesRecord>;
84
+ public events?: RuntimeEvents<any> = undefined;
85
+
86
+ public messages?: OutgoingMessages<OutgoingMessagesRecord> = undefined;
57
87
 
58
88
  public constructor() {
59
89
  super();
@@ -65,15 +95,17 @@ export class RuntimeModule<Config> extends ConfigurableModule<Config> {
65
95
  this.runtimeMethodNames = methodNames ?? [];
66
96
  }
67
97
 
68
- private getInputs(): RuntimeMethodExecutionData {
69
- const { input } = container.resolve<RuntimeMethodExecutionContext>(
70
- RuntimeMethodExecutionContext
71
- );
72
-
73
- if (input === undefined) {
74
- throw errors.inputDataNotSet();
75
- }
76
- return input;
98
+ public getInputs(): RuntimeMethodExecutionData {
99
+ return Provable.witness(RuntimeMethodExecutionDataStruct, () => {
100
+ const { input } = container.resolve<RuntimeMethodExecutionContext>(
101
+ RuntimeMethodExecutionContext
102
+ );
103
+ if (input === undefined) {
104
+ throw errors.inputDataNotSet();
105
+ }
106
+
107
+ return input;
108
+ });
77
109
  }
78
110
 
79
111
  public get transaction(): RuntimeTransaction {
@@ -1,27 +1,23 @@
1
- import { Field } from "snarkyjs";
2
-
3
- export interface StateService {
4
- get: (key: Field) => Field[] | undefined;
5
- set: (key: Field, value: Field[] | undefined) => void;
6
- }
1
+ import { Field } from "o1js";
2
+ import { SimpleAsyncStateService } from "@proto-kit/protocol";
7
3
 
8
4
  /**
9
- * Naive implementation of a StateService for testing purposes
5
+ * Naive implementation of an in-memory variant of the StateService interface
10
6
  */
11
- export class InMemoryStateService implements StateService {
12
- public values: Record<string, Field[] | undefined> = {};
7
+ export class InMemoryStateService implements SimpleAsyncStateService {
8
+ /**
9
+ * This mapping container null values if the specific entry has been deleted.
10
+ * This is used by the CachedState service to keep track of deletions
11
+ */
12
+ public values: Record<string, Field[] | null> = {};
13
13
 
14
- public get(key: Field): Field[] | undefined {
15
- return this.values[key.toString()];
14
+ public async get(key: Field): Promise<Field[] | undefined> {
15
+ return this.values[key.toString()] ?? undefined;
16
16
  }
17
17
 
18
- public set(key: Field, value: Field[] | undefined) {
19
- if (
20
- value === undefined &&
21
- Object.prototype.hasOwnProperty.call(this.values, key.toString())
22
- ) {
23
- // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
24
- delete this.values[key.toString()];
18
+ public async set(key: Field, value: Field[] | undefined) {
19
+ if (value === undefined) {
20
+ this.values[key.toString()] = null;
25
21
  } else {
26
22
  this.values[key.toString()] = value;
27
23
  }