@proto-kit/module 0.1.1-develop.165 → 0.1.1-develop.1661

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 (118) hide show
  1. package/dist/factories/MethodIdFactory.d.ts +9 -0
  2. package/dist/factories/MethodIdFactory.d.ts.map +1 -0
  3. package/dist/factories/MethodIdFactory.js +11 -0
  4. package/dist/factories/MethodIdFactory.js.map +1 -0
  5. package/dist/index.d.ts +5 -7
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +6 -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 +215 -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 +22 -5
  22. package/dist/method/runtimeMethod.d.ts.map +1 -1
  23. package/dist/method/runtimeMethod.js +79 -24
  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 +20 -0
  28. package/dist/runtime/MethodIdResolver.d.ts.map +1 -0
  29. package/dist/runtime/MethodIdResolver.js +91 -0
  30. package/dist/runtime/MethodIdResolver.js.map +1 -0
  31. package/dist/runtime/Runtime.d.ts +22 -28
  32. package/dist/runtime/Runtime.d.ts.map +1 -1
  33. package/dist/runtime/Runtime.js +116 -70
  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 +23 -14
  40. package/dist/runtime/RuntimeModule.d.ts.map +1 -1
  41. package/dist/runtime/RuntimeModule.js +47 -10
  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 +13 -0
  57. package/src/index.ts +5 -7
  58. package/src/messages/OutgoingMessages.ts +122 -0
  59. package/src/method/MethodParameterEncoder.ts +260 -0
  60. package/src/method/runtimeMethod.ts +146 -31
  61. package/src/runtime/MethodIdResolver.ts +108 -0
  62. package/src/runtime/Runtime.ts +191 -112
  63. package/src/runtime/RuntimeEnvironment.ts +16 -0
  64. package/src/runtime/RuntimeModule.ts +77 -27
  65. package/src/state/InMemoryStateService.ts +14 -18
  66. package/test/Runtime.test.ts +69 -36
  67. package/test/TestingRuntime.ts +43 -0
  68. package/test/messages/message.test.ts +42 -0
  69. package/test/method/MethodParameterEncoder.test.ts +121 -0
  70. package/test/method/runtimeMethod-fail.test.ts +50 -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 +19 -16
  75. package/test/modules/MethodIdResolver.test.ts +73 -0
  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/dist/chain/Chain.d.ts +0 -109
  81. package/dist/chain/Chain.d.ts.map +0 -1
  82. package/dist/chain/Chain.js +0 -229
  83. package/dist/method/MethodExecutionContext.d.ts +0 -73
  84. package/dist/method/MethodExecutionContext.d.ts.map +0 -1
  85. package/dist/method/MethodExecutionContext.js +0 -112
  86. package/dist/method/MethodParameterDecoder.d.ts +0 -22
  87. package/dist/method/MethodParameterDecoder.d.ts.map +0 -1
  88. package/dist/method/MethodParameterDecoder.js +0 -33
  89. package/dist/method/RuntimeMethodExecutionContext.d.ts +0 -57
  90. package/dist/method/RuntimeMethodExecutionContext.d.ts.map +0 -1
  91. package/dist/method/RuntimeMethodExecutionContext.js +0 -92
  92. package/dist/method/assert.d.ts +0 -12
  93. package/dist/method/assert.d.ts.map +0 -1
  94. package/dist/method/assert.js +0 -23
  95. package/dist/method/decorator.d.ts +0 -45
  96. package/dist/method/decorator.d.ts.map +0 -1
  97. package/dist/method/decorator.js +0 -140
  98. package/dist/state/State.d.ts +0 -65
  99. package/dist/state/State.d.ts.map +0 -1
  100. package/dist/state/State.js +0 -114
  101. package/dist/state/StateMap.d.ts +0 -37
  102. package/dist/state/StateMap.d.ts.map +0 -1
  103. package/dist/state/StateMap.js +0 -56
  104. package/dist/state/StateServiceProvider.d.ts +0 -10
  105. package/dist/state/StateServiceProvider.d.ts.map +0 -1
  106. package/dist/state/StateServiceProvider.js +0 -34
  107. package/src/method/MethodParameterDecoder.ts +0 -68
  108. package/src/method/RuntimeMethodExecutionContext.ts +0 -111
  109. package/src/method/assert.test.ts +0 -49
  110. package/src/method/assert.ts +0 -27
  111. package/src/state/State.ts +0 -154
  112. package/src/state/StateMap.ts +0 -69
  113. package/src/state/StateServiceProvider.ts +0 -24
  114. package/src/state/decorator.ts +0 -65
  115. package/test/state/MerkleTree.test.ts +0 -95
  116. package/test/state/MockAsyncMerkleStore.ts +0 -28
  117. package/test/transaction.test.ts +0 -82
  118. package/tsconfig.test.json +0 -9
@@ -1,34 +1,54 @@
1
- // eslint-disable-next-line max-len
2
- /* eslint-disable @typescript-eslint/no-explicit-any,@typescript-eslint/no-unsafe-assignment */
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
16
  import {
17
- fieldToString,
18
- stringToField,
19
17
  MethodPublicOutput,
18
+ StateServiceProvider,
19
+ SimpleAsyncStateService,
20
+ RuntimeMethodExecutionContext,
21
+ RuntimeTransaction,
22
+ NetworkState,
20
23
  } from "@proto-kit/protocol";
21
24
 
22
25
  import {
23
26
  combineMethodName,
24
27
  isRuntimeMethod,
28
+ runtimeMethodTypeMetadataKey,
25
29
  toWrappedMethod,
26
- WrappedMethod,
27
- } from "../method/runtimeMethod.js";
28
- import { StateService } from "../state/InMemoryStateService.js";
29
- import { StateServiceProvider } from "../state/StateServiceProvider";
30
-
31
- import { RuntimeModule } from "./RuntimeModule.js";
30
+ AsyncWrappedMethod,
31
+ } from "../method/runtimeMethod";
32
+ import { MethodIdFactory } from "../factories/MethodIdFactory";
33
+
34
+ import { RuntimeModule } from "./RuntimeModule";
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
+ }
32
52
 
33
53
  /**
34
54
  * Record of modules accepted by the Runtime module container.
@@ -45,66 +65,56 @@ const errors = {
45
65
  new Error(`Unable to find method with id ${methodKey}`),
46
66
  };
47
67
 
48
- /**
49
- * Definition / required arguments for the Runtime class
50
- */
51
- export interface RuntimeDefinition<Modules extends RuntimeModulesRecord> {
52
- state: StateService;
53
- modules: Modules;
54
- config?: ModulesConfig<Modules>;
55
- }
56
-
57
68
  export class RuntimeZkProgrammable<
58
- Modules extends RuntimeModulesRecord
69
+ Modules extends RuntimeModulesRecord,
59
70
  > extends ZkProgrammable<undefined, MethodPublicOutput> {
60
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
61
71
  public constructor(public runtime: Runtime<Modules>) {
62
72
  super();
63
73
  }
64
74
 
65
- public get appChain() {
66
- return this.runtime.appChain;
75
+ public get areProofsEnabled() {
76
+ return this.runtime.areProofsEnabled;
67
77
  }
68
78
 
69
- public zkProgramFactory(): PlainZkProgram<undefined, MethodPublicOutput> {
79
+ public zkProgramFactory(): PlainZkProgram<undefined, MethodPublicOutput>[] {
70
80
  type Methods = Record<
71
81
  string,
72
82
  {
73
83
  privateInputs: any;
74
- method: WrappedMethod;
84
+ method: AsyncWrappedMethod;
75
85
  }
76
86
  >;
77
87
  // We need to use explicit type annotations here,
78
88
  // therefore we can't use destructuring
79
- // eslint-disable-next-line max-len
80
- // eslint-disable-next-line @typescript-eslint/no-use-before-define,prefer-destructuring,putout/putout
89
+
90
+ // eslint-disable-next-line prefer-destructuring
81
91
  const runtime: Runtime<Modules> = this.runtime;
82
92
 
93
+ const MAXIMUM_METHODS_PER_ZK_PROGRAM = 8;
94
+
83
95
  const runtimeMethods = runtime.runtimeModuleNames.reduce<Methods>(
84
96
  (allMethods, runtimeModuleName) => {
85
- runtime.isValidModuleName(
86
- runtime.definition.modules,
87
- runtimeModuleName
88
- );
97
+ runtime.isValidModuleName(runtime.definition, runtimeModuleName);
89
98
 
90
99
  /**
91
100
  * Couldnt find a better way to circumvent the type assertion
92
101
  * regarding resolving only known modules. We assert in the line above
93
102
  * but we cast it to any anyways to satisfy the proof system.
94
103
  */
95
- // eslint-disable-next-line max-len
104
+
96
105
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
97
106
  const runtimeModule = runtime.resolve(runtimeModuleName as any);
98
107
 
99
- // eslint-disable-next-line max-len
100
108
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
101
109
  const modulePrototype = Object.getPrototypeOf(runtimeModule) as Record<
102
110
  string,
103
- (...args: unknown[]) => unknown
111
+ // Technically not all methods have to be async, but for this context it's ok
112
+ (...args: unknown[]) => Promise<unknown>
104
113
  >;
105
114
 
106
- const modulePrototypeMethods =
107
- Object.getOwnPropertyNames(modulePrototype);
115
+ const modulePrototypeMethods = getAllPropertyNames(runtimeModule).map(
116
+ (method) => method.toString()
117
+ );
108
118
 
109
119
  const moduleMethods = modulePrototypeMethods.reduce<Methods>(
110
120
  (allModuleMethods, methodName) => {
@@ -114,14 +124,17 @@ export class RuntimeZkProgrammable<
114
124
  methodName
115
125
  );
116
126
  const method = modulePrototype[methodName];
117
- const wrappedMethod = Reflect.apply(
118
- toWrappedMethod,
127
+ const invocationType = Reflect.getMetadata(
128
+ runtimeMethodTypeMetadataKey,
119
129
  runtimeModule,
120
- [methodName, method]
130
+ methodName
121
131
  );
122
132
 
123
- // eslint-disable-next-line no-warning-comments
124
- // TODO: find out how to import the Tuple type
133
+ const wrappedMethod: AsyncWrappedMethod = Reflect.apply(
134
+ toWrappedMethod,
135
+ runtimeModule,
136
+ [methodName, method, { invocationType }]
137
+ );
125
138
 
126
139
  const privateInputs = Reflect.getMetadata(
127
140
  "design:paramtypes",
@@ -153,30 +166,87 @@ export class RuntimeZkProgrammable<
153
166
  );
154
167
 
155
168
  const sortedRuntimeMethods = Object.fromEntries(
156
- // eslint-disable-next-line @typescript-eslint/require-array-sort-compare
157
169
  Object.entries(runtimeMethods).sort()
158
170
  );
159
171
 
160
- const program = Experimental.ZkProgram({
161
- publicOutput: MethodPublicOutput,
162
- methods: sortedRuntimeMethods,
163
- });
164
-
165
- const SelfProof = Experimental.ZkProgram.Proof(program);
166
-
167
- const methods = Object.keys(sortedRuntimeMethods).reduce<
168
- Record<string, any>
169
- >((boundMethods, methodName) => {
170
- boundMethods[methodName] = program[methodName].bind(program);
171
- return boundMethods;
172
- }, {});
173
-
174
- return {
175
- compile: program.compile.bind(program),
176
- verify: program.verify.bind(program),
177
- Proof: SelfProof,
178
- 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;
179
221
  };
222
+
223
+ return splitRuntimeMethods().map((bucket, index) => {
224
+ const name = `RuntimeProgram-${index}`;
225
+ const program = ZkProgram({
226
+ name,
227
+ publicOutput: MethodPublicOutput,
228
+ methods: bucket,
229
+ });
230
+
231
+ const SelfProof = ZkProgram.Proof(program);
232
+
233
+ const methods = Object.keys(bucket).reduce<Record<string, any>>(
234
+ (boundMethods, methodName) => {
235
+ boundMethods[methodName] = program[methodName].bind(program);
236
+ return boundMethods;
237
+ },
238
+ {}
239
+ );
240
+
241
+ return {
242
+ name,
243
+ compile: program.compile.bind(program),
244
+ verify: program.verify.bind(program),
245
+ analyzeMethods: program.analyzeMethods.bind(program),
246
+ Proof: SelfProof,
247
+ methods,
248
+ };
249
+ });
180
250
  }
181
251
  }
182
252
 
@@ -187,51 +257,59 @@ export class RuntimeZkProgrammable<
187
257
  @injectable()
188
258
  export class Runtime<Modules extends RuntimeModulesRecord>
189
259
  extends ModuleContainer<Modules>
190
- implements WithZkProgrammable<undefined, MethodPublicOutput>
260
+ implements RuntimeEnvironment, CompilableModule
191
261
  {
192
262
  public static from<Modules extends RuntimeModulesRecord>(
193
- definition: RuntimeDefinition<Modules>
194
- ) {
195
- return new Runtime(definition);
263
+ definition: Modules
264
+ ): TypedClass<Runtime<Modules>> {
265
+ return class RuntimeScoped extends Runtime<Modules> {
266
+ public constructor() {
267
+ super(definition);
268
+ }
269
+ };
196
270
  }
197
271
 
198
272
  // runtime modules composed into a ZkProgram
199
- public program?: ReturnType<typeof Experimental.ZkProgram>;
273
+ public program?: ReturnType<typeof ZkProgram>;
200
274
 
201
- public definition: RuntimeDefinition<Modules>;
275
+ // No idea why we have to do this, but if we don't re-define it here,
276
+ // js can't access it from the superclass somehow
277
+ public definition: Modules;
202
278
 
203
279
  public zkProgrammable: ZkProgrammable<undefined, MethodPublicOutput>;
204
280
 
205
- // eslint-disable-next-line no-warning-comments
206
- // TODO DI
207
- private readonly stateServiceProviderInstance = new StateServiceProvider(
208
- this.definition.state
209
- );
210
-
211
281
  /**
212
282
  * Creates a new Runtime from the provided config
213
283
  *
214
284
  * @param modules - Configuration object for the constructed Runtime
215
285
  */
216
- public constructor(definition: RuntimeDefinition<Modules>) {
286
+ public constructor(definition: Modules) {
217
287
  super(definition);
218
288
  this.definition = definition;
219
289
  this.zkProgrammable = new RuntimeZkProgrammable<Modules>(this);
220
- // this.registerValue({
221
- // Runtime: this,
222
- // });
223
290
  }
224
291
 
225
- public get appChain(): AreProofsEnabled | undefined {
226
- return this.container.resolve<AreProofsEnabled>("AppChain");
292
+ // TODO Remove after changing DFs to type-based approach
293
+ public create(childContainerProvider: ChildContainerProvider) {
294
+ super.create(childContainerProvider);
295
+
296
+ this.useDependencyFactory(MethodIdFactory);
227
297
  }
228
298
 
229
- public get stateService(): StateService {
230
- return this.stateServiceProviderInstance.stateService;
299
+ public get areProofsEnabled(): AreProofsEnabled | undefined {
300
+ return this.container.resolve<AreProofsEnabled>("AreProofsEnabled");
231
301
  }
232
302
 
233
303
  public get stateServiceProvider(): StateServiceProvider {
234
- return this.stateServiceProviderInstance;
304
+ return this.container.resolve<StateServiceProvider>("StateServiceProvider");
305
+ }
306
+
307
+ public get stateService(): SimpleAsyncStateService {
308
+ return this.stateServiceProvider.stateService;
309
+ }
310
+
311
+ public get methodIdResolver(): MethodIdResolver {
312
+ return this.container.resolve<MethodIdResolver>("MethodIdResolver");
235
313
  }
236
314
 
237
315
  /**
@@ -245,52 +323,43 @@ export class Runtime<Modules extends RuntimeModulesRecord>
245
323
  * @param methodId The encoded name of the method to call.
246
324
  * Encoding: "stringToField(module.name) << 128 + stringToField(method-name)"
247
325
  */
248
- public getMethodById(methodId: bigint): (...args: unknown[]) => unknown {
249
- const [moduleName, methodName] = this.getMethodNameFromId(methodId);
326
+ public getMethodById(
327
+ methodId: bigint
328
+ ): ((...args: unknown[]) => Promise<unknown>) | undefined {
329
+ const methodDescriptor =
330
+ this.methodIdResolver.getMethodNameFromId(methodId);
331
+
332
+ if (methodDescriptor === undefined) {
333
+ return undefined;
334
+ }
335
+ const [moduleName, methodName] = methodDescriptor;
250
336
 
251
- this.isValidModuleName(this.definition.modules, moduleName);
337
+ this.assertIsValidModuleName(moduleName);
252
338
  const module = this.resolve(moduleName);
253
339
 
254
- // eslint-disable-next-line max-len
255
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions,@typescript-eslint/no-unsafe-member-access
340
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
256
341
  const method = (module as any)[methodName];
257
342
  if (method === undefined) {
258
343
  throw errors.methodNotFound(`${moduleName}.${methodName}`);
259
344
  }
260
345
 
261
346
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
262
- return (method as (...args: unknown[]) => unknown).bind(module);
263
- }
264
-
265
- public getMethodNameFromId(methodId: bigint): [string, string] {
266
- // eslint-disable-next-line @typescript-eslint/no-magic-numbers
267
- const moduleName = fieldToString(methodId >> 128n);
268
- // eslint-disable-next-line @typescript-eslint/no-magic-numbers
269
- const methodName = fieldToString(methodId % 2n ** 128n);
270
-
271
- return [moduleName, methodName];
272
- }
273
-
274
- public getMethodId(moduleName: string, methodName: string): bigint {
275
- return (
276
- // eslint-disable-next-line @typescript-eslint/no-magic-numbers
277
- (stringToField(moduleName).toBigInt() << 128n) +
278
- stringToField(methodName).toBigInt()
279
- );
347
+ return (method as (...args: unknown[]) => Promise<unknown>).bind(module);
280
348
  }
281
349
 
282
350
  /**
283
351
  * Add a name and other respective properties required by RuntimeModules,
284
352
  * that come from the current Runtime
285
353
  *
286
- * @param name - Name of the runtime module to decorate
354
+ * @param moduleName - Name of the runtime module to decorate
355
+ * @param containedModule
287
356
  */
288
357
  public decorateModule(
289
358
  moduleName: StringKeyOf<Modules>,
290
359
  containedModule: InstanceType<Modules[StringKeyOf<Modules>]>
291
360
  ) {
292
361
  containedModule.name = moduleName;
293
- containedModule.runtime = this;
362
+ containedModule.parent = this;
294
363
 
295
364
  super.decorateModule(moduleName, containedModule);
296
365
  }
@@ -299,6 +368,16 @@ export class Runtime<Modules extends RuntimeModulesRecord>
299
368
  * @returns A list of names of all the registered module names
300
369
  */
301
370
  public get runtimeModuleNames() {
302
- return Object.keys(this.definition.modules);
371
+ return this.moduleNames;
372
+ }
373
+
374
+ public async compile(registry: CompileRegistry) {
375
+ const context = container.resolve(RuntimeMethodExecutionContext);
376
+ context.setup({
377
+ transaction: RuntimeTransaction.dummyTransaction(),
378
+ networkState: NetworkState.empty(),
379
+ });
380
+ return await this.zkProgrammable.compile(registry);
303
381
  }
304
382
  }
383
+ /* 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,41 +1,75 @@
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
+
12
+ import { runtimeMethodNamesMetadataKey } from "../method/runtimeMethod";
13
+ import {
14
+ OutgoingMessages,
15
+ OutgoingMessagesRecord,
16
+ } from "../messages/OutgoingMessages";
10
17
 
11
- import type {
12
- Runtime,
13
- RuntimeDefinition,
14
- RuntimeModulesRecord,
15
- } from "./Runtime";
18
+ import { RuntimeEnvironment } from "./RuntimeEnvironment";
16
19
 
17
20
  const errors = {
18
21
  inputDataNotSet: () => new Error("Input data for runtime execution not set"),
19
22
  };
20
23
 
21
- /**
22
- * This type exists to carry over certain runtime properties
23
- * to runtime modules, until we can inject them through DI.
24
- */
25
- export interface PartialRuntime
26
- extends Pick<Runtime<RuntimeModulesRecord>, "zkProgrammable"> {
27
- 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
+ }
28
50
 
29
- 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
+ }
30
57
  }
31
58
 
32
59
  /**
33
60
  * Base class for runtime modules providing the necessary utilities.
34
61
  */
35
62
  @injectable()
36
- export class RuntimeModule<Config> extends ConfigurableModule<Config> {
63
+ export class RuntimeModule<
64
+ Config = NoConfig,
65
+ > extends ConfigurableModule<Config> {
37
66
  public static presets: Presets<unknown> = {};
38
67
 
68
+ /**
69
+ * Holds all method names that are callable throw transactions
70
+ */
71
+ public readonly runtimeMethodNames: string[] = [];
72
+
39
73
  /**
40
74
  * This property exists only to typecheck that the RuntimeModule
41
75
  * was extended correctly in e.g. a decorator. We need at least
@@ -45,17 +79,33 @@ export class RuntimeModule<Config> extends ConfigurableModule<Config> {
45
79
 
46
80
  public name?: string;
47
81
 
48
- public runtime?: Runtime<RuntimeModulesRecord>;
82
+ public parent?: RuntimeEnvironment;
49
83
 
50
- private getInputs(): RuntimeMethodExecutionData {
51
- const { input } = container.resolve<RuntimeMethodExecutionContext>(
52
- RuntimeMethodExecutionContext
84
+ public events?: RuntimeEvents<any> = undefined;
85
+
86
+ public messages?: OutgoingMessages<OutgoingMessagesRecord> = undefined;
87
+
88
+ public constructor() {
89
+ super();
90
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
91
+ const methodNames: string[] | undefined = Reflect.getMetadata(
92
+ runtimeMethodNamesMetadataKey,
93
+ this
53
94
  );
95
+ this.runtimeMethodNames = methodNames ?? [];
96
+ }
54
97
 
55
- if (input === undefined) {
56
- throw errors.inputDataNotSet();
57
- }
58
- 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
+ });
59
109
  }
60
110
 
61
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
  }