@proto-kit/module 0.1.1-develop.600 → 0.1.1-develop.833
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/LICENSE.md +201 -201
- package/dist/method/MethodParameterDecoder.d.ts +10 -10
- package/dist/method/MethodParameterDecoder.js +40 -40
- package/dist/method/MethodParameterEncoder.d.ts +15 -8
- package/dist/method/MethodParameterEncoder.d.ts.map +1 -1
- package/dist/method/MethodParameterEncoder.js +122 -48
- package/dist/method/runtimeMethod.d.ts +6 -5
- package/dist/method/runtimeMethod.d.ts.map +1 -1
- package/dist/method/runtimeMethod.js +13 -26
- package/dist/runtime/MethodIdResolver.d.ts +7 -0
- package/dist/runtime/MethodIdResolver.d.ts.map +1 -1
- package/dist/runtime/MethodIdResolver.js +35 -2
- package/dist/runtime/Runtime.d.ts +6 -5
- package/dist/runtime/Runtime.d.ts.map +1 -1
- package/dist/runtime/Runtime.js +29 -22
- package/dist/runtime/RuntimeEnvironment.d.ts +2 -2
- package/dist/runtime/RuntimeEnvironment.d.ts.map +1 -1
- package/dist/runtime/RuntimeModule.d.ts +2 -2
- package/dist/runtime/RuntimeModule.d.ts.map +1 -1
- package/dist/runtime/RuntimeModule.js +10 -8
- package/dist/src/factories/MethodIdFactory.d.ts +10 -0
- package/dist/src/factories/MethodIdFactory.d.ts.map +1 -0
- package/dist/src/factories/MethodIdFactory.js +10 -0
- package/dist/src/index.d.ts +11 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +10 -0
- package/dist/src/method/MethodParameterEncoder.d.ts +22 -0
- package/dist/src/method/MethodParameterEncoder.d.ts.map +1 -0
- package/dist/src/method/MethodParameterEncoder.js +103 -0
- package/dist/src/method/runtimeMethod.d.ts +26 -0
- package/dist/src/method/runtimeMethod.d.ts.map +1 -0
- package/dist/src/method/runtimeMethod.js +164 -0
- package/dist/src/module/decorator.d.ts +8 -0
- package/dist/src/module/decorator.d.ts.map +1 -0
- package/dist/src/module/decorator.js +15 -0
- package/dist/src/runtime/MethodIdResolver.d.ts +20 -0
- package/dist/src/runtime/MethodIdResolver.d.ts.map +1 -0
- package/dist/src/runtime/MethodIdResolver.js +100 -0
- package/dist/src/runtime/Runtime.d.ts +71 -0
- package/dist/src/runtime/Runtime.d.ts.map +1 -0
- package/dist/src/runtime/Runtime.js +215 -0
- package/dist/src/runtime/RuntimeEnvironment.d.ts +10 -0
- package/dist/src/runtime/RuntimeEnvironment.d.ts.map +1 -0
- package/dist/src/runtime/RuntimeEnvironment.js +1 -0
- package/dist/src/runtime/RuntimeModule.d.ts +26 -0
- package/dist/src/runtime/RuntimeModule.d.ts.map +1 -0
- package/dist/src/runtime/RuntimeModule.js +85 -0
- package/dist/src/state/InMemoryStateService.d.ts +15 -0
- package/dist/src/state/InMemoryStateService.d.ts.map +1 -0
- package/dist/src/state/InMemoryStateService.js +28 -0
- package/dist/src/state/decorator.d.ts +7 -0
- package/dist/src/state/decorator.d.ts.map +1 -0
- package/dist/src/state/decorator.js +39 -0
- package/dist/state/InMemoryStateService.d.ts +10 -6
- package/dist/state/InMemoryStateService.d.ts.map +1 -1
- package/dist/state/InMemoryStateService.js +10 -8
- package/dist/state/decorator.d.ts.map +1 -1
- package/dist/state/decorator.js +0 -3
- package/dist/test/Runtime.test.d.ts +2 -0
- package/dist/test/Runtime.test.d.ts.map +1 -0
- package/dist/test/Runtime.test.js +24 -0
- package/dist/test/TestingRuntime.d.ts +7 -0
- package/dist/test/TestingRuntime.d.ts.map +1 -0
- package/dist/test/TestingRuntime.js +29 -0
- package/dist/test/method/runtimeMethod.test.d.ts +2 -0
- package/dist/test/method/runtimeMethod.test.d.ts.map +1 -0
- package/dist/test/method/runtimeMethod.test.js +30 -0
- package/dist/test/modules/Admin.d.ts +10 -0
- package/dist/test/modules/Admin.d.ts.map +1 -0
- package/dist/test/modules/Admin.js +29 -0
- package/dist/test/modules/Balances.d.ts +23 -0
- package/dist/test/modules/Balances.d.ts.map +1 -0
- package/dist/test/modules/Balances.js +98 -0
- package/dist/test/modules/Balances.test.d.ts +2 -0
- package/dist/test/modules/Balances.test.d.ts.map +1 -0
- package/dist/test/modules/Balances.test.js +201 -0
- package/dist/test/modules/MethodIdResolver.test.d.ts +2 -0
- package/dist/test/modules/MethodIdResolver.test.d.ts.map +1 -0
- package/dist/test/modules/MethodIdResolver.test.js +67 -0
- package/dist/test/modules/State.test.d.ts +2 -0
- package/dist/test/modules/State.test.d.ts.map +1 -0
- package/dist/test/modules/State.test.js +42 -0
- package/dist/test/runtimeMethod.test.d.ts +2 -0
- package/dist/test/runtimeMethod.test.d.ts.map +1 -0
- package/dist/test/runtimeMethod.test.js +50 -0
- package/package.json +5 -5
- package/src/method/MethodParameterEncoder.ts +192 -81
- package/src/method/runtimeMethod.ts +29 -44
- package/src/runtime/MethodIdResolver.ts +51 -1
- package/src/runtime/Runtime.ts +48 -29
- package/src/runtime/RuntimeEnvironment.ts +4 -7
- package/src/runtime/RuntimeModule.ts +13 -15
- package/src/state/InMemoryStateService.ts +13 -13
- package/src/state/decorator.ts +1 -3
- package/test/Runtime.test.ts +68 -41
- package/test/TestingRuntime.ts +45 -0
- package/test/method/MethodParameterEncoder.test.ts +152 -0
- package/{src/method/decorator.test.ts → test/method/runtimeMethod.test.ts} +2 -2
- package/test/modules/Admin.ts +3 -3
- package/test/modules/Balances.test.ts +57 -61
- package/test/modules/Balances.ts +15 -18
- package/test/modules/{methodId.test.ts → MethodIdResolver.test.ts} +14 -23
- package/test/modules/State.test.ts +41 -50
- package/test/runtimeMethod.test.ts +19 -32
- package/test/tsconfig.json +7 -0
- package/tsconfig.json +2 -2
- package/test/transaction.test.ts +0 -82
- package/tsconfig.test.json +0 -9
package/package.json
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
"name": "@proto-kit/module",
|
|
3
3
|
"license": "MIT",
|
|
4
4
|
"private": false,
|
|
5
|
-
"version": "0.1.1-develop.
|
|
5
|
+
"version": "0.1.1-develop.833+397881ed",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"build": "tsc -p tsconfig.json",
|
|
9
9
|
"dev": "tsc -p tsconfig.json --watch",
|
|
10
10
|
"lint": "eslint ./src ./test",
|
|
11
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 -- ./
|
|
13
|
-
"test:watch": "npm run test:file -- ./
|
|
12
|
+
"test": "npm run test:file -- ./test/**",
|
|
13
|
+
"test:watch": "npm run test:file -- ./test/** --watch"
|
|
14
14
|
},
|
|
15
15
|
"main": "dist/index.js",
|
|
16
16
|
"publishConfig": {
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"peerDependencies": {
|
|
29
29
|
"@proto-kit/common": "*",
|
|
30
30
|
"@proto-kit/protocol": "*",
|
|
31
|
-
"o1js": "
|
|
31
|
+
"o1js": "^1.1.0",
|
|
32
32
|
"tsyringe": "^4.7.0"
|
|
33
33
|
},
|
|
34
|
-
"gitHead": "
|
|
34
|
+
"gitHead": "397881ed5d8f98f5005bcd7be7f5a12b3bc6f956"
|
|
35
35
|
}
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
/* eslint-disable
|
|
2
|
-
import {
|
|
1
|
+
/* eslint-disable @typescript-eslint/consistent-type-assertions */
|
|
2
|
+
import {
|
|
3
|
+
Field,
|
|
4
|
+
Proof,
|
|
5
|
+
Provable,
|
|
6
|
+
DynamicProof,
|
|
7
|
+
FlexibleProvablePure,
|
|
8
|
+
} from "o1js";
|
|
3
9
|
import {
|
|
4
10
|
ArgumentTypes,
|
|
5
11
|
ProofTypes,
|
|
6
|
-
ToFieldable,
|
|
7
12
|
ToFieldableStatic,
|
|
8
|
-
|
|
13
|
+
TypedClass,
|
|
14
|
+
filterNonUndefined,
|
|
9
15
|
} from "@proto-kit/common";
|
|
10
16
|
|
|
11
17
|
import type { RuntimeModule } from "../runtime/RuntimeModule";
|
|
@@ -22,12 +28,55 @@ const errors = {
|
|
|
22
28
|
),
|
|
23
29
|
};
|
|
24
30
|
|
|
25
|
-
type
|
|
31
|
+
type ArgumentType =
|
|
32
|
+
| FlexibleProvablePure<any>
|
|
33
|
+
| typeof Proof<unknown, unknown>
|
|
34
|
+
| typeof DynamicProof<unknown, unknown>;
|
|
35
|
+
|
|
36
|
+
type ArgTypeArray = ArgumentType[];
|
|
37
|
+
|
|
38
|
+
type ArgArray = ArgumentTypes[];
|
|
39
|
+
|
|
40
|
+
function isProofType(type: unknown): type is typeof Proof {
|
|
41
|
+
return (type as unknown as TypedClass<unknown>).prototype instanceof Proof;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function isDynamicProofType(type: unknown): type is typeof DynamicProof {
|
|
45
|
+
return (
|
|
46
|
+
(type as unknown as TypedClass<unknown>).prototype instanceof DynamicProof
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function isProofBaseType(
|
|
51
|
+
type: unknown
|
|
52
|
+
): type is typeof Proof | typeof DynamicProof {
|
|
53
|
+
return isProofType(type) || isDynamicProofType(type);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function getAllPropertyNamesOfPrototypeChain(type: unknown): string[] {
|
|
57
|
+
if (type === undefined || type === null) {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
return Object.getOwnPropertyNames(type).concat(
|
|
61
|
+
...getAllPropertyNamesOfPrototypeChain(Object.getPrototypeOf(type))
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function isFlexibleProvablePure(
|
|
66
|
+
type: unknown
|
|
67
|
+
): type is FlexibleProvablePure<unknown> {
|
|
68
|
+
// The required properties are defined on the prototype for Structs and CircuitValues
|
|
69
|
+
// but on the constructor function itself for Field and Bool
|
|
70
|
+
// For aliases like Balance in library, it can even be 2 steps upwards the prototype chain
|
|
71
|
+
const props = getAllPropertyNamesOfPrototypeChain(type);
|
|
72
|
+
const mandatory = ["toFields", "fromFields", "sizeInFields"];
|
|
73
|
+
return mandatory.every((prop) => props.includes(prop));
|
|
74
|
+
}
|
|
26
75
|
|
|
27
76
|
export class MethodParameterEncoder {
|
|
28
77
|
public static fromMethod(target: RuntimeModule<unknown>, methodName: string) {
|
|
29
78
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
30
|
-
const paramtypes:
|
|
79
|
+
const paramtypes: ArgTypeArray = Reflect.getMetadata(
|
|
31
80
|
"design:paramtypes",
|
|
32
81
|
target,
|
|
33
82
|
methodName
|
|
@@ -39,103 +88,165 @@ export class MethodParameterEncoder {
|
|
|
39
88
|
);
|
|
40
89
|
}
|
|
41
90
|
|
|
91
|
+
const indizes = paramtypes
|
|
92
|
+
.map((type, index) => {
|
|
93
|
+
if (isProofBaseType(type) || isFlexibleProvablePure(type)) {
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
return `${index}`;
|
|
97
|
+
})
|
|
98
|
+
.filter(filterNonUndefined);
|
|
99
|
+
if (indizes.length > 0) {
|
|
100
|
+
const indexString = indizes.reduce((a, b) => `${a}, ${b}`);
|
|
101
|
+
throw new Error(
|
|
102
|
+
`Not all arguments of method '${target.name}.${methodName}' are provable types or proofs (indizes: [${indexString}])`
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
42
106
|
return new MethodParameterEncoder(paramtypes);
|
|
43
107
|
}
|
|
44
108
|
|
|
45
|
-
public static fieldSize(type:
|
|
109
|
+
public static fieldSize(type: ArgumentType): number | undefined {
|
|
110
|
+
if (isProofBaseType(type)) {
|
|
111
|
+
return (
|
|
112
|
+
(MethodParameterEncoder.fieldSize(type.publicInputType) ?? 0) +
|
|
113
|
+
(MethodParameterEncoder.fieldSize(type.publicOutputType) ?? 0)
|
|
114
|
+
);
|
|
115
|
+
}
|
|
46
116
|
// as any, since we shouldn't be using this workaround in the first place
|
|
47
|
-
return (type as
|
|
117
|
+
return (type as FlexibleProvablePure<unknown>).sizeInFields();
|
|
48
118
|
}
|
|
49
119
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
public decode(argsJSON: string[]): FlexibleProvable<unknown>[] {
|
|
53
|
-
return this.types.map((type, index) => {
|
|
54
|
-
// eslint-disable-next-line @typescript-eslint/init-declarations
|
|
55
|
-
let value: FlexibleProvable<unknown>;
|
|
56
|
-
|
|
57
|
-
try {
|
|
58
|
-
// eslint-disable-next-line max-len
|
|
59
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
60
|
-
value = type.fromJSON(
|
|
61
|
-
JSON.parse(argsJSON[index])
|
|
62
|
-
) as FlexibleProvable<unknown>;
|
|
63
|
-
} catch (e: unknown) {
|
|
64
|
-
if (e instanceof Error) {
|
|
65
|
-
throw errors.typeNotCompatible(type.constructor.name, e.message);
|
|
66
|
-
}
|
|
67
|
-
throw errors.typeNotCompatible(type.constructor.name);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return value;
|
|
71
|
-
});
|
|
72
|
-
}
|
|
120
|
+
public constructor(private readonly types: ArgTypeArray) {}
|
|
73
121
|
|
|
74
|
-
public
|
|
75
|
-
if (fields.length < this.fieldSize) {
|
|
76
|
-
throw errors.fieldLengthNotMatching(this.fieldSize, fields.length);
|
|
122
|
+
public decode(fields: Field[], auxiliary: string[]): Promise<ArgArray> {
|
|
123
|
+
if (fields.length < this.fieldSize()) {
|
|
124
|
+
throw errors.fieldLengthNotMatching(this.fieldSize(), fields.length);
|
|
77
125
|
}
|
|
78
126
|
|
|
79
127
|
let stack = fields.slice();
|
|
128
|
+
const auxiliaryStack = auxiliary.slice();
|
|
80
129
|
|
|
81
|
-
return
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
130
|
+
return Promise.all(
|
|
131
|
+
this.types.map((type) => {
|
|
132
|
+
const numberFieldsNeeded = MethodParameterEncoder.fieldSize(type) ?? -1;
|
|
133
|
+
if (numberFieldsNeeded === -1) {
|
|
134
|
+
throw errors.typeNotCompatible(type.constructor.name);
|
|
135
|
+
}
|
|
136
|
+
const structFields = stack.slice(0, numberFieldsNeeded);
|
|
137
|
+
stack = stack.slice(numberFieldsNeeded);
|
|
138
|
+
|
|
139
|
+
// Decode proof
|
|
140
|
+
if (isProofBaseType(type)) {
|
|
141
|
+
const auxiliaryData = auxiliaryStack.shift();
|
|
142
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
143
|
+
const proofData: { proof: string; maxProofsVerified: 0 | 1 | 2 } =
|
|
144
|
+
JSON.parse(auxiliaryData!);
|
|
145
|
+
|
|
146
|
+
const inputFieldSize = MethodParameterEncoder.fieldSize(
|
|
147
|
+
type.publicInputType
|
|
148
|
+
)!;
|
|
149
|
+
const input = structFields
|
|
150
|
+
.slice(0, inputFieldSize)
|
|
151
|
+
.map((x) => x.toString());
|
|
152
|
+
const output = structFields
|
|
153
|
+
.slice(inputFieldSize)
|
|
154
|
+
.map((x) => x.toString());
|
|
155
|
+
|
|
156
|
+
// fromJSON has incompatible signature for Proof and DynamicProof
|
|
157
|
+
if (isProofType(type)) {
|
|
158
|
+
return type.fromJSON({
|
|
159
|
+
...proofData,
|
|
160
|
+
publicInput: input,
|
|
161
|
+
publicOutput: output,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
if (isDynamicProofType(type)) {
|
|
165
|
+
return type.fromJSON({
|
|
166
|
+
...proofData,
|
|
167
|
+
publicInput: input,
|
|
168
|
+
publicOutput: output,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return (type as FlexibleProvablePure<unknown>).fromFields(
|
|
174
|
+
structFields
|
|
175
|
+
) as any;
|
|
176
|
+
})
|
|
177
|
+
);
|
|
90
178
|
}
|
|
91
179
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
180
|
+
/**
|
|
181
|
+
* Variant of encode() for provable code that skips the unprovable
|
|
182
|
+
* json encoding
|
|
183
|
+
*/
|
|
184
|
+
public encode(args: ArgumentTypes) {
|
|
96
185
|
/**
|
|
97
186
|
* Use the type info obtained previously to convert
|
|
98
187
|
* the args passed to fields
|
|
99
188
|
*/
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
189
|
+
return args
|
|
190
|
+
.map((argument, index) => {
|
|
191
|
+
if (argument instanceof Proof || argument instanceof DynamicProof) {
|
|
192
|
+
const argumentType = this.types[index] as ProofTypes;
|
|
193
|
+
|
|
194
|
+
const { publicOutputType, publicInputType } = argumentType;
|
|
195
|
+
|
|
196
|
+
const inputFields =
|
|
197
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
198
|
+
publicInputType?.toFields(argument.publicInput as any) ?? [];
|
|
199
|
+
|
|
200
|
+
const outputFields =
|
|
201
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
202
|
+
publicOutputType?.toFields(argument.publicOutput as any) ?? [];
|
|
203
|
+
|
|
204
|
+
let auxiliary = "";
|
|
205
|
+
|
|
206
|
+
// Has to be asProver, because this function will be called by runtimeMethod
|
|
207
|
+
// to transform the args into a Field[] to compute the argsHash
|
|
208
|
+
// In this case, the auxiliary might be empty, but it isn't used by that method anyways
|
|
209
|
+
Provable.asProver(() => {
|
|
210
|
+
const jsonProof = argument.toJSON();
|
|
211
|
+
auxiliary = JSON.stringify({
|
|
212
|
+
proof: jsonProof.proof,
|
|
213
|
+
maxProofsVerified: jsonProof.maxProofsVerified,
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
return {
|
|
218
|
+
fields: [...inputFields, ...outputFields],
|
|
219
|
+
auxiliary,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
129
222
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
223
|
+
const argumentType = this.types[index] as ToFieldableStatic;
|
|
224
|
+
return {
|
|
225
|
+
fields: argumentType.toFields(argument),
|
|
226
|
+
auxiliary: undefined,
|
|
227
|
+
};
|
|
228
|
+
})
|
|
229
|
+
.reduce<{
|
|
230
|
+
fields: Field[];
|
|
231
|
+
auxiliary: string[];
|
|
232
|
+
}>(
|
|
233
|
+
(a, b) => {
|
|
234
|
+
return {
|
|
235
|
+
fields: [...a.fields, ...b.fields],
|
|
236
|
+
auxiliary:
|
|
237
|
+
b.auxiliary !== undefined
|
|
238
|
+
? [...a.auxiliary, b.auxiliary]
|
|
239
|
+
: a.auxiliary,
|
|
240
|
+
};
|
|
241
|
+
},
|
|
242
|
+
{ fields: [], auxiliary: [] }
|
|
243
|
+
);
|
|
134
244
|
}
|
|
135
245
|
|
|
136
|
-
public
|
|
246
|
+
public fieldSize(): number {
|
|
137
247
|
return this.types
|
|
138
248
|
.map((type) => MethodParameterEncoder.fieldSize(type) ?? 0)
|
|
139
249
|
.reduce((a, b) => a + b, 0);
|
|
140
250
|
}
|
|
141
251
|
}
|
|
252
|
+
/* eslint-enable @typescript-eslint/consistent-type-assertions */
|
|
@@ -1,34 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
Bool,
|
|
4
|
-
Field,
|
|
5
|
-
FlexibleProvable,
|
|
6
|
-
Poseidon,
|
|
7
|
-
Proof,
|
|
8
|
-
ProvableExtended,
|
|
9
|
-
} from "o1js";
|
|
1
|
+
import { Bool, Field, Poseidon } from "o1js";
|
|
10
2
|
import { container } from "tsyringe";
|
|
11
3
|
import {
|
|
12
4
|
StateTransition,
|
|
13
|
-
DefaultProvableHashList,
|
|
14
5
|
ProvableStateTransition,
|
|
15
6
|
MethodPublicOutput,
|
|
16
7
|
RuntimeMethodExecutionContext,
|
|
17
|
-
|
|
8
|
+
StateTransitionReductionList,
|
|
18
9
|
} from "@proto-kit/protocol";
|
|
19
10
|
import {
|
|
20
11
|
DecoratedMethod,
|
|
21
12
|
toProver,
|
|
22
13
|
ZkProgrammable,
|
|
23
|
-
ToFieldable,
|
|
24
|
-
ToFieldableStatic,
|
|
25
|
-
ProofTypes,
|
|
26
14
|
ArgumentTypes,
|
|
27
|
-
TypedClass,
|
|
28
|
-
O1JSPrimitive,
|
|
29
15
|
} from "@proto-kit/common";
|
|
30
16
|
|
|
31
17
|
import type { RuntimeModule } from "../runtime/RuntimeModule.js";
|
|
18
|
+
|
|
32
19
|
import { MethodParameterEncoder } from "./MethodParameterEncoder";
|
|
33
20
|
|
|
34
21
|
const errors = {
|
|
@@ -49,10 +36,9 @@ const errors = {
|
|
|
49
36
|
};
|
|
50
37
|
|
|
51
38
|
export function toStateTransitionsHash(
|
|
52
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
53
39
|
stateTransitions: StateTransition<any>[]
|
|
54
40
|
) {
|
|
55
|
-
const stateTransitionsHashList = new
|
|
41
|
+
const stateTransitionsHashList = new StateTransitionReductionList(
|
|
56
42
|
ProvableStateTransition
|
|
57
43
|
);
|
|
58
44
|
|
|
@@ -66,35 +52,33 @@ export function toStateTransitionsHash(
|
|
|
66
52
|
.toField();
|
|
67
53
|
}
|
|
68
54
|
|
|
69
|
-
// eslint-disable-next-line etc/prefer-interface
|
|
70
55
|
export type WrappedMethod = (...args: ArgumentTypes) => MethodPublicOutput;
|
|
56
|
+
export type AsyncWrappedMethod = (
|
|
57
|
+
...args: ArgumentTypes
|
|
58
|
+
) => Promise<MethodPublicOutput>;
|
|
71
59
|
|
|
72
60
|
export function toWrappedMethod(
|
|
73
61
|
this: RuntimeModule<unknown>,
|
|
74
62
|
methodName: string,
|
|
75
|
-
moduleMethod: (...args: ArgumentTypes) =>
|
|
76
|
-
methodArguments: ArgumentTypes,
|
|
63
|
+
moduleMethod: (...args: ArgumentTypes) => Promise<any>,
|
|
77
64
|
options: {
|
|
78
65
|
invocationType: RuntimeMethodInvocationType;
|
|
79
66
|
}
|
|
80
|
-
) {
|
|
67
|
+
): AsyncWrappedMethod {
|
|
81
68
|
const executionContext = container.resolve<RuntimeMethodExecutionContext>(
|
|
82
69
|
RuntimeMethodExecutionContext
|
|
83
70
|
);
|
|
84
71
|
|
|
85
|
-
const wrappedMethod:
|
|
86
|
-
|
|
72
|
+
const wrappedMethod: AsyncWrappedMethod = async (
|
|
73
|
+
...args
|
|
74
|
+
): Promise<MethodPublicOutput> => {
|
|
75
|
+
await Reflect.apply(moduleMethod, this, args);
|
|
87
76
|
const {
|
|
88
77
|
result: { stateTransitions, status },
|
|
89
|
-
input,
|
|
90
78
|
} = executionContext.current();
|
|
91
79
|
|
|
92
80
|
const stateTransitionsHash = toStateTransitionsHash(stateTransitions);
|
|
93
81
|
|
|
94
|
-
if (input === undefined) {
|
|
95
|
-
throw errors.methodInputsNotProvided();
|
|
96
|
-
}
|
|
97
|
-
|
|
98
82
|
const { name, runtime } = this;
|
|
99
83
|
|
|
100
84
|
if (name === undefined) {
|
|
@@ -122,14 +106,13 @@ export function toWrappedMethod(
|
|
|
122
106
|
* Use the type info obtained previously to convert
|
|
123
107
|
* the args passed to fields
|
|
124
108
|
*/
|
|
125
|
-
const {
|
|
109
|
+
const { fields } = MethodParameterEncoder.fromMethod(
|
|
110
|
+
this,
|
|
111
|
+
methodName
|
|
112
|
+
).encode(args);
|
|
126
113
|
|
|
127
114
|
// Assert that the argsHash that has been signed matches the given arguments
|
|
128
|
-
|
|
129
|
-
// i.e. the result of the if-statement will be the same for all executions
|
|
130
|
-
// of this method
|
|
131
|
-
const argsHash =
|
|
132
|
-
methodArguments.length > 0 ? Poseidon.hash(argsFields) : Field(0);
|
|
115
|
+
const argsHash = Poseidon.hash(fields);
|
|
133
116
|
|
|
134
117
|
transaction.argsHash.assertEquals(
|
|
135
118
|
argsHash,
|
|
@@ -189,11 +172,16 @@ export function isRuntimeMethod(
|
|
|
189
172
|
|
|
190
173
|
export type RuntimeMethodInvocationType = "SIGNATURE" | "INCOMING_MESSAGE";
|
|
191
174
|
|
|
192
|
-
function runtimeMethodInternal(options: {
|
|
175
|
+
function runtimeMethodInternal(options: {
|
|
176
|
+
invocationType: RuntimeMethodInvocationType;
|
|
177
|
+
}) {
|
|
193
178
|
return (
|
|
194
179
|
target: RuntimeModule<unknown>,
|
|
195
180
|
methodName: string,
|
|
196
|
-
descriptor:
|
|
181
|
+
descriptor: TypedPropertyDescriptor<
|
|
182
|
+
// TODO Limit possible parameter types
|
|
183
|
+
(...args: any[]) => Promise<any>
|
|
184
|
+
>
|
|
197
185
|
) => {
|
|
198
186
|
const executionContext = container.resolve<RuntimeMethodExecutionContext>(
|
|
199
187
|
RuntimeMethodExecutionContext
|
|
@@ -223,11 +211,11 @@ function runtimeMethodInternal(options: { invocationType: RuntimeMethodInvocatio
|
|
|
223
211
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
224
212
|
const simulatedMethod = descriptor.value as DecoratedMethod;
|
|
225
213
|
|
|
226
|
-
descriptor.value = function value(
|
|
214
|
+
descriptor.value = async function value(
|
|
227
215
|
this: RuntimeModule<unknown>,
|
|
228
216
|
...args: ArgumentTypes
|
|
229
217
|
) {
|
|
230
|
-
const constructorName = this.
|
|
218
|
+
const constructorName = this.name!;
|
|
231
219
|
|
|
232
220
|
/**
|
|
233
221
|
* If its a top level method call, wrap it into a wrapped method,
|
|
@@ -239,7 +227,6 @@ function runtimeMethodInternal(options: { invocationType: RuntimeMethodInvocatio
|
|
|
239
227
|
const simulatedWrappedMethod = Reflect.apply(toWrappedMethod, this, [
|
|
240
228
|
methodName,
|
|
241
229
|
simulatedMethod,
|
|
242
|
-
args,
|
|
243
230
|
options,
|
|
244
231
|
]);
|
|
245
232
|
|
|
@@ -248,7 +235,7 @@ function runtimeMethodInternal(options: { invocationType: RuntimeMethodInvocatio
|
|
|
248
235
|
* RuntimeMethodExecutionContext state, meaning it enters and exits
|
|
249
236
|
* the context properly.
|
|
250
237
|
*/
|
|
251
|
-
|
|
238
|
+
|
|
252
239
|
async function prover(this: ZkProgrammable<any, any>) {
|
|
253
240
|
executionContext.beforeMethod(constructorName, methodName, args);
|
|
254
241
|
const innerProver = toProver(
|
|
@@ -257,7 +244,6 @@ function runtimeMethodInternal(options: { invocationType: RuntimeMethodInvocatio
|
|
|
257
244
|
false,
|
|
258
245
|
...args
|
|
259
246
|
).bind(this);
|
|
260
|
-
// eslint-disable-next-line @typescript-eslint/init-declarations
|
|
261
247
|
let result: Awaited<ReturnType<typeof innerProver>>;
|
|
262
248
|
try {
|
|
263
249
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
@@ -278,10 +264,9 @@ function runtimeMethodInternal(options: { invocationType: RuntimeMethodInvocatio
|
|
|
278
264
|
executionContext.setProver(prover.bind(this.runtime.zkProgrammable));
|
|
279
265
|
}
|
|
280
266
|
|
|
281
|
-
// eslint-disable-next-line @typescript-eslint/init-declarations
|
|
282
267
|
let result: unknown;
|
|
283
268
|
try {
|
|
284
|
-
result = Reflect.apply(simulatedMethod, this, args);
|
|
269
|
+
result = await Reflect.apply(simulatedMethod, this, args);
|
|
285
270
|
} finally {
|
|
286
271
|
executionContext.afterMethod();
|
|
287
272
|
}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { filterNonUndefined } from "@proto-kit/common";
|
|
2
|
+
import { stringToField, RuntimeMethodIdMapping } from "@proto-kit/protocol";
|
|
2
3
|
import { Poseidon } from "o1js";
|
|
3
4
|
import { inject, injectable } from "tsyringe";
|
|
4
5
|
|
|
6
|
+
import {
|
|
7
|
+
RuntimeMethodInvocationType,
|
|
8
|
+
runtimeMethodTypeMetadataKey,
|
|
9
|
+
} from "../method/runtimeMethod";
|
|
10
|
+
|
|
5
11
|
import type { Runtime, RuntimeModulesRecord } from "./Runtime";
|
|
6
12
|
|
|
7
13
|
/**
|
|
@@ -33,6 +39,50 @@ export class MethodIdResolver {
|
|
|
33
39
|
}, {});
|
|
34
40
|
}
|
|
35
41
|
|
|
42
|
+
/**
|
|
43
|
+
* The purpose of this method is to provide a dictionary where
|
|
44
|
+
* we can look up properties like methodId and invocationType
|
|
45
|
+
* for each runtimeMethod using their module name and method name
|
|
46
|
+
*/
|
|
47
|
+
public methodIdMap(): RuntimeMethodIdMapping {
|
|
48
|
+
const methodIdResolver =
|
|
49
|
+
this.runtime.dependencyContainer.resolve<MethodIdResolver>(
|
|
50
|
+
"MethodIdResolver"
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const rawMappings = this.runtime.moduleNames.flatMap((moduleName) => {
|
|
54
|
+
const module = this.runtime.resolve(moduleName);
|
|
55
|
+
return module.runtimeMethodNames.map((method) => {
|
|
56
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
57
|
+
const type = Reflect.getMetadata(
|
|
58
|
+
runtimeMethodTypeMetadataKey,
|
|
59
|
+
module,
|
|
60
|
+
method
|
|
61
|
+
) as RuntimeMethodInvocationType | undefined;
|
|
62
|
+
|
|
63
|
+
if (type !== undefined) {
|
|
64
|
+
return {
|
|
65
|
+
name: `${moduleName}.${method}`,
|
|
66
|
+
methodId: methodIdResolver.getMethodId(moduleName, method),
|
|
67
|
+
type,
|
|
68
|
+
} as const;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return undefined;
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
return rawMappings
|
|
76
|
+
.filter(filterNonUndefined)
|
|
77
|
+
.reduce<RuntimeMethodIdMapping>((acc, entry) => {
|
|
78
|
+
acc[entry.name] = {
|
|
79
|
+
methodId: entry.methodId,
|
|
80
|
+
type: entry.type,
|
|
81
|
+
};
|
|
82
|
+
return acc;
|
|
83
|
+
}, {});
|
|
84
|
+
}
|
|
85
|
+
|
|
36
86
|
public getMethodNameFromId(methodId: bigint): [string, string] | undefined {
|
|
37
87
|
const methodPath = this.dictionary[methodId.toString()];
|
|
38
88
|
|