@proto-kit/module 0.1.1-develop.164 → 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.
- package/dist/factories/MethodIdFactory.d.ts +9 -0
- package/dist/factories/MethodIdFactory.d.ts.map +1 -0
- package/dist/factories/MethodIdFactory.js +11 -0
- package/dist/factories/MethodIdFactory.js.map +1 -0
- package/dist/index.d.ts +5 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -7
- package/dist/index.js.map +1 -0
- package/dist/messages/OutgoingMessage.d.ts +96 -0
- package/dist/messages/OutgoingMessage.d.ts.map +1 -0
- package/dist/messages/OutgoingMessage.js +68 -0
- package/dist/messages/OutgoingMessage.js.map +1 -0
- package/dist/messages/OutgoingMessages.d.ts +215 -0
- package/dist/messages/OutgoingMessages.d.ts.map +1 -0
- package/dist/messages/OutgoingMessages.js +66 -0
- package/dist/messages/OutgoingMessages.js.map +1 -0
- package/dist/method/MethodParameterEncoder.d.ts +26 -0
- package/dist/method/MethodParameterEncoder.d.ts.map +1 -0
- package/dist/method/MethodParameterEncoder.js +169 -0
- package/dist/method/MethodParameterEncoder.js.map +1 -0
- package/dist/method/runtimeMethod.d.ts +22 -5
- package/dist/method/runtimeMethod.d.ts.map +1 -1
- package/dist/method/runtimeMethod.js +79 -24
- package/dist/method/runtimeMethod.js.map +1 -0
- package/dist/module/decorator.js +1 -0
- package/dist/module/decorator.js.map +1 -0
- package/dist/runtime/MethodIdResolver.d.ts +20 -0
- package/dist/runtime/MethodIdResolver.d.ts.map +1 -0
- package/dist/runtime/MethodIdResolver.js +91 -0
- package/dist/runtime/MethodIdResolver.js.map +1 -0
- package/dist/runtime/Runtime.d.ts +22 -28
- package/dist/runtime/Runtime.d.ts.map +1 -1
- package/dist/runtime/Runtime.js +116 -70
- package/dist/runtime/Runtime.js.map +1 -0
- package/dist/runtime/RuntimeEnvironment.d.ts +10 -0
- package/dist/runtime/RuntimeEnvironment.d.ts.map +1 -0
- package/dist/runtime/RuntimeEnvironment.js +2 -0
- package/dist/runtime/RuntimeEnvironment.js.map +1 -0
- package/dist/runtime/RuntimeModule.d.ts +23 -14
- package/dist/runtime/RuntimeModule.d.ts.map +1 -1
- package/dist/runtime/RuntimeModule.js +47 -10
- package/dist/runtime/RuntimeModule.js.map +1 -0
- package/dist/state/InMemoryStateService.d.ts +11 -10
- package/dist/state/InMemoryStateService.d.ts.map +1 -1
- package/dist/state/InMemoryStateService.js +11 -8
- package/dist/state/InMemoryStateService.js.map +1 -0
- package/dist/state/decorator.d.ts.map +1 -1
- package/dist/state/decorator.js +2 -4
- package/dist/state/decorator.js.map +1 -0
- package/dist/testing/TestingRuntime.d.ts +8 -0
- package/dist/testing/TestingRuntime.d.ts.map +1 -0
- package/dist/testing/TestingRuntime.js +31 -0
- package/dist/testing/TestingRuntime.js.map +1 -0
- package/jest.config.cjs +12 -1
- package/package.json +10 -11
- package/src/factories/MethodIdFactory.ts +13 -0
- package/src/index.ts +5 -7
- package/src/messages/OutgoingMessages.ts +122 -0
- package/src/method/MethodParameterEncoder.ts +260 -0
- package/src/method/runtimeMethod.ts +146 -31
- package/src/runtime/MethodIdResolver.ts +108 -0
- package/src/runtime/Runtime.ts +191 -112
- package/src/runtime/RuntimeEnvironment.ts +16 -0
- package/src/runtime/RuntimeModule.ts +77 -27
- package/src/state/InMemoryStateService.ts +14 -18
- package/test/Runtime.test.ts +69 -36
- package/test/TestingRuntime.ts +43 -0
- package/test/messages/message.test.ts +42 -0
- package/test/method/MethodParameterEncoder.test.ts +121 -0
- package/test/method/runtimeMethod-fail.test.ts +50 -0
- package/{src/method/decorator.test.ts → test/method/runtimeMethod.test.ts} +3 -3
- package/test/modules/Admin.ts +4 -4
- package/test/modules/Balances.test.ts +92 -78
- package/test/modules/Balances.ts +19 -16
- package/test/modules/MethodIdResolver.test.ts +73 -0
- package/test/modules/State.test.ts +81 -0
- package/test/runtimeMethod.test.ts +192 -20
- package/test/tsconfig.json +7 -0
- package/tsconfig.json +2 -2
- package/dist/chain/Chain.d.ts +0 -109
- package/dist/chain/Chain.d.ts.map +0 -1
- package/dist/chain/Chain.js +0 -229
- package/dist/method/MethodExecutionContext.d.ts +0 -73
- package/dist/method/MethodExecutionContext.d.ts.map +0 -1
- package/dist/method/MethodExecutionContext.js +0 -112
- package/dist/method/MethodParameterDecoder.d.ts +0 -22
- package/dist/method/MethodParameterDecoder.d.ts.map +0 -1
- package/dist/method/MethodParameterDecoder.js +0 -33
- package/dist/method/RuntimeMethodExecutionContext.d.ts +0 -57
- package/dist/method/RuntimeMethodExecutionContext.d.ts.map +0 -1
- package/dist/method/RuntimeMethodExecutionContext.js +0 -92
- package/dist/method/assert.d.ts +0 -12
- package/dist/method/assert.d.ts.map +0 -1
- package/dist/method/assert.js +0 -23
- package/dist/method/decorator.d.ts +0 -45
- package/dist/method/decorator.d.ts.map +0 -1
- package/dist/method/decorator.js +0 -140
- package/dist/state/State.d.ts +0 -65
- package/dist/state/State.d.ts.map +0 -1
- package/dist/state/State.js +0 -114
- package/dist/state/StateMap.d.ts +0 -37
- package/dist/state/StateMap.d.ts.map +0 -1
- package/dist/state/StateMap.js +0 -56
- package/dist/state/StateServiceProvider.d.ts +0 -10
- package/dist/state/StateServiceProvider.d.ts.map +0 -1
- package/dist/state/StateServiceProvider.js +0 -34
- package/src/method/MethodParameterDecoder.ts +0 -68
- package/src/method/RuntimeMethodExecutionContext.ts +0 -111
- package/src/method/assert.test.ts +0 -49
- package/src/method/assert.ts +0 -27
- package/src/state/State.ts +0 -154
- package/src/state/StateMap.ts +0 -69
- package/src/state/StateServiceProvider.ts +0 -24
- package/src/state/decorator.ts +0 -65
- package/test/state/MerkleTree.test.ts +0 -95
- package/test/state/MockAsyncMerkleStore.ts +0 -28
- package/test/transaction.test.ts +0 -82
- package/tsconfig.test.json +0 -9
package/src/runtime/Runtime.ts
CHANGED
|
@@ -1,34 +1,54 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import {
|
|
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
|
-
|
|
27
|
-
} from "../method/runtimeMethod
|
|
28
|
-
import {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
import {
|
|
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
|
|
66
|
-
return this.runtime.
|
|
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:
|
|
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
|
-
|
|
80
|
-
// eslint-disable-next-line
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
118
|
-
|
|
127
|
+
const invocationType = Reflect.getMetadata(
|
|
128
|
+
runtimeMethodTypeMetadataKey,
|
|
119
129
|
runtimeModule,
|
|
120
|
-
|
|
130
|
+
methodName
|
|
121
131
|
);
|
|
122
132
|
|
|
123
|
-
|
|
124
|
-
|
|
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
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
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
|
|
260
|
+
implements RuntimeEnvironment, CompilableModule
|
|
191
261
|
{
|
|
192
262
|
public static from<Modules extends RuntimeModulesRecord>(
|
|
193
|
-
definition:
|
|
194
|
-
) {
|
|
195
|
-
return
|
|
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
|
|
273
|
+
public program?: ReturnType<typeof ZkProgram>;
|
|
200
274
|
|
|
201
|
-
|
|
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:
|
|
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
|
-
|
|
226
|
-
|
|
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
|
|
230
|
-
return this.
|
|
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.
|
|
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(
|
|
249
|
-
|
|
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.
|
|
337
|
+
this.assertIsValidModuleName(moduleName);
|
|
252
338
|
const module = this.resolve(moduleName);
|
|
253
339
|
|
|
254
|
-
// eslint-disable-next-line
|
|
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
|
|
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.
|
|
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
|
|
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
|
-
|
|
9
|
-
|
|
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
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
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<
|
|
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
|
|
82
|
+
public parent?: RuntimeEnvironment;
|
|
49
83
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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 "
|
|
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
|
|
5
|
+
* Naive implementation of an in-memory variant of the StateService interface
|
|
10
6
|
*/
|
|
11
|
-
export class InMemoryStateService implements
|
|
12
|
-
|
|
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
|
-
|
|
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
|
}
|