Skip to content

Commit b4bbec1

Browse files
committed
refactor
1 parent 7d7235b commit b4bbec1

File tree

9 files changed

+250
-134
lines changed

9 files changed

+250
-134
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { TaskEither } from 'fp-ts/TaskEither';
2+
3+
export type InterfaceKind = FpInterfaceType | TsInterfaceType;
4+
5+
export type FpInterfaceType = 'fp';
6+
export const fpInterfaceTag: FpInterfaceType = 'fp';
7+
8+
export type TsInterfaceType = 'ts';
9+
export const tsInterfaceTag: TsInterfaceType = 'ts';
10+
11+
export type ChooseType<
12+
InterfaceType extends InterfaceKind,
13+
FpType,
14+
TsType
15+
> = InterfaceType extends FpInterfaceType
16+
? FpType
17+
: InterfaceType extends TsInterfaceType
18+
? TsType
19+
: never;
20+
21+
export type RetType<InterfaceType extends InterfaceKind, T> = ChooseType<
22+
InterfaceType,
23+
TaskEither<string, T>,
24+
Promise<T>
25+
>;
26+
27+
export interface WithInterfaceTag<IType extends InterfaceKind> {
28+
readonly __interface_tag: IType;
29+
}

src/library/plugin/fp/pluginLoader.ts

Lines changed: 71 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
import * as path from 'path';
22
import {
3-
FpInterfaceType,
43
IMinAuthPlugin,
54
IMinAuthPluginFactory,
6-
TsInterfaceType,
7-
fpInterfaceTag,
8-
tsInterfaceTag
5+
tsToFpMinAuthPluginFactory
96
} from './pluginType';
107
import * as R from 'fp-ts/Record';
118
import { pipe } from 'fp-ts/function';
@@ -23,8 +20,14 @@ import { fromFailablePromise, liftZodParseResult } from '@utils/fp/TaskEither';
2320
import {
2421
IProofCache,
2522
IProofCacheProvider,
26-
toTsCheckCachedProof
23+
tsToFpProofCacheProvider
2724
} from './proofCache';
25+
import {
26+
FpInterfaceType,
27+
TsInterfaceType,
28+
fpInterfaceTag,
29+
tsInterfaceTag
30+
} from './interfaceKind';
2831

2932
export const configurationSchema = z.object({
3033
pluginDir: z.string().optional(),
@@ -76,15 +79,15 @@ export interface UntypedPluginInstance
7679

7780
export type UntypedPluginFactory =
7881
| IMinAuthPluginFactory<
79-
IMinAuthPlugin<FpInterfaceType, unknown, unknown>,
8082
FpInterfaceType,
83+
IMinAuthPlugin<FpInterfaceType, unknown, unknown>,
8184
unknown,
8285
unknown,
8386
unknown
8487
>
8588
| IMinAuthPluginFactory<
86-
IMinAuthPlugin<TsInterfaceType, unknown, unknown>,
8789
TsInterfaceType,
90+
IMinAuthPlugin<TsInterfaceType, unknown, unknown>,
8891
unknown,
8992
unknown,
9093
unknown
@@ -108,50 +111,49 @@ const validatePluginCfg = (
108111
const initializePlugin = (
109112
pluginModulePath: string,
110113
pluginCfg: unknown,
111-
proofCache: IProofCache
114+
proofCache: IProofCache<FpInterfaceType>
112115
): TaskEither<string, UntypedPluginInstance> =>
113116
pipe(
114117
TE.Do,
115118
TE.bind('pluginModule', () => importPluginModule(pluginModulePath)),
116-
TE.let('pluginFactory', ({ pluginModule }) => pluginModule.default),
117-
TE.bind('typedPluginCfg', ({ pluginFactory }) =>
118-
validatePluginCfg(pluginCfg, pluginFactory)
119+
TE.let('rawPluginFactory', ({ pluginModule }) => pluginModule.default),
120+
TE.bind('typedPluginCfg', ({ rawPluginFactory }) =>
121+
validatePluginCfg(pluginCfg, rawPluginFactory)
122+
),
123+
TE.bind('pluginFactory', ({ rawPluginFactory }) =>
124+
rawPluginFactory.__interface_tag === fpInterfaceTag
125+
? TE.right(rawPluginFactory)
126+
: rawPluginFactory.__interface_tag === tsInterfaceTag
127+
? TE.right(tsToFpMinAuthPluginFactory(rawPluginFactory))
128+
: // TODO This check should be moved to `importPluginModule`
129+
TE.left('invalid plugin module')
119130
),
120131
TE.chain(
121132
({
122133
pluginFactory,
123134
typedPluginCfg
124135
}): TaskEither<string, UntypedPluginInstance> =>
125-
pluginFactory.__interface_tag === fpInterfaceTag
126-
? pluginFactory.initialize(typedPluginCfg, proofCache.checkEachProof)
127-
: pluginFactory.__interface_tag === tsInterfaceTag
128-
? pipe(
129-
fromFailablePromise(() =>
130-
pluginFactory.initialize(
131-
typedPluginCfg,
132-
toTsCheckCachedProof(proofCache.checkEachProof)
133-
)
134-
),
135-
TE.map(
136-
(obj): UntypedPluginInstance => ({
137-
__interface_tag: fpInterfaceTag,
138-
verifyAndGetOutput: (pia, sp) =>
139-
fromFailablePromise(() => obj.verifyAndGetOutput(pia, sp)),
140-
publicInputArgsSchema: obj.publicInputArgsSchema,
141-
customRoutes: obj.customRoutes,
142-
verificationKey: obj.verificationKey
143-
})
144-
)
145-
)
146-
: // TODO This check should be moved to `importPluginModule`
147-
TE.throwError('invalid plugin module')
136+
pluginFactory.initialize(typedPluginCfg, proofCache.checkEachProof)
148137
)
149138
);
150139

140+
export type UntypedProofCacheProvider =
141+
| IProofCacheProvider<FpInterfaceType>
142+
| IProofCacheProvider<TsInterfaceType>;
143+
151144
export const initializePlugins = (
152145
cfg: Configuration,
153-
proofCacheProvider: IProofCacheProvider
146+
rawProofCacheProvider: UntypedProofCacheProvider
154147
): TaskEither<string, ActivePlugins> => {
148+
const proofCacheProvider: TaskEither<
149+
string,
150+
IProofCacheProvider<FpInterfaceType>
151+
> = rawProofCacheProvider.__interface_tag == fpInterfaceTag
152+
? TE.right(rawProofCacheProvider)
153+
: rawProofCacheProvider.__interface_tag == tsInterfaceTag
154+
? TE.right(tsToFpProofCacheProvider(rawProofCacheProvider))
155+
: TE.left('proof cache provider: unknown interface type');
156+
155157
const resolvePluginModulePath =
156158
(name: string, optionalPath?: string) => () => {
157159
const dir =
@@ -164,38 +166,45 @@ export const initializePlugins = (
164166
: path.resolve(optionalPath);
165167
};
166168

167-
const resolveModulePathAndInitializePlugin = (
168-
pluginName: string,
169-
pluginCfg: {
170-
path?: string | undefined;
171-
config?: unknown;
172-
}
173-
): TaskEither<string, UntypedPluginInstance> =>
174-
pipe(
175-
TE.Do,
176-
TE.bind('modulePath', () =>
177-
TE.fromIO(resolvePluginModulePath(pluginName, pluginCfg.path))
178-
),
179-
TE.tapIO(({ modulePath }) => () => {
180-
console.info(`loading plugin ${pluginName} from ${modulePath}`);
181-
console.log(pluginCfg.config);
182-
}),
183-
TE.tap(() => proofCacheProvider.initCacheFor(pluginName)),
184-
TE.bind('proofCache', () => proofCacheProvider.getCacheOf(pluginName)),
185-
TE.chain(({ modulePath, proofCache }) =>
186-
initializePlugin(modulePath, pluginCfg.config ?? {}, proofCache)
187-
),
188-
TE.mapLeft(
189-
(err) => `error while initializing plugin ${pluginName}: ${err}`
190-
)
191-
);
169+
const resolveModulePathAndInitializePlugin =
170+
(proofCacheProvider: IProofCacheProvider<FpInterfaceType>) =>
171+
(
172+
pluginName: string,
173+
pluginCfg: {
174+
path?: string | undefined;
175+
config?: unknown;
176+
}
177+
): TaskEither<string, UntypedPluginInstance> =>
178+
pipe(
179+
TE.Do,
180+
TE.bind('modulePath', () =>
181+
TE.fromIO(resolvePluginModulePath(pluginName, pluginCfg.path))
182+
),
183+
TE.tapIO(({ modulePath }) => () => {
184+
console.info(`loading plugin ${pluginName} from ${modulePath}`);
185+
console.log(pluginCfg.config);
186+
}),
187+
TE.tap(() => proofCacheProvider.initCacheFor(pluginName)),
188+
TE.bind('proofCache', () => proofCacheProvider.getCacheOf(pluginName)),
189+
TE.chain(({ modulePath, proofCache }) =>
190+
initializePlugin(modulePath, pluginCfg.config ?? {}, proofCache)
191+
),
192+
TE.mapLeft(
193+
(err) => `error while initializing plugin ${pluginName}: ${err}`
194+
)
195+
);
192196

193197
const Applicative = TE.getApplicativeTaskValidation(
194198
T.ApplyPar,
195199
pipe(Str.Semigroup, S.intercalate(', '))
196200
);
197201

198-
return R.traverseWithIndex(Applicative)(resolveModulePathAndInitializePlugin)(
199-
cfg.plugins
202+
return pipe(
203+
proofCacheProvider,
204+
TE.chain((pcp) =>
205+
R.traverseWithIndex(Applicative)(
206+
resolveModulePathAndInitializePlugin(pcp)
207+
)(cfg.plugins)
208+
)
200209
);
201210
};

src/library/plugin/fp/pluginType.ts

Lines changed: 54 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,18 @@
11
import { RequestHandler } from 'express';
2-
import { TaskEither } from 'fp-ts/lib/TaskEither';
32
import { JsonProof } from 'o1js';
43
import z from 'zod';
5-
import { CachedProof } from './proofCache';
4+
import { CachedProof, fpToTsCheckCachedProofs } from './proofCache';
5+
import {
6+
InterfaceKind,
7+
WithInterfaceTag,
8+
RetType,
9+
TsInterfaceType,
10+
FpInterfaceType
11+
} from './interfaceKind';
12+
import { fromFailablePromise } from '@utils/fp/TaskEither';
613

714
// Interfaces used on the server side.
815

9-
export type InterfaceKind = FpInterfaceType | TsInterfaceType;
10-
11-
export type FpInterfaceType = 'fp';
12-
export const fpInterfaceTag: FpInterfaceType = 'fp';
13-
14-
export type TsInterfaceType = 'ts';
15-
export const tsInterfaceTag: TsInterfaceType = 'ts';
16-
17-
export type ChooseType<
18-
InterfaceType extends InterfaceKind,
19-
FpType,
20-
TsType
21-
> = InterfaceType extends FpInterfaceType
22-
? FpType
23-
: InterfaceType extends TsInterfaceType
24-
? TsType
25-
: never;
26-
27-
export type RetType<InterfaceType extends InterfaceKind, T> = ChooseType<
28-
InterfaceType,
29-
TaskEither<string, T>,
30-
Promise<T>
31-
>;
32-
33-
export interface WithInterfaceTag<IType extends InterfaceKind> {
34-
readonly __interface_tag: IType;
35-
}
36-
3716
export interface IMinAuthPlugin<
3817
InterfaceType extends InterfaceKind,
3918
PublicInputArgs,
@@ -65,8 +44,8 @@ export interface IMinAuthPlugin<
6544

6645
// TODO: generic type inference?
6746
export interface IMinAuthPluginFactory<
68-
PluginType extends IMinAuthPlugin<InterfaceType, PublicInputArgs, Output>,
6947
InterfaceType extends InterfaceKind,
48+
PluginType extends IMinAuthPlugin<InterfaceType, PublicInputArgs, Output>,
7049
Configuration,
7150
PublicInputArgs,
7251
Output
@@ -114,3 +93,47 @@ export interface IMinAuthProverFactory<
11493
> extends WithInterfaceTag<InterfaceType> {
11594
initialize(cfg: Configuration): RetType<InterfaceType, ProverType>;
11695
}
96+
97+
// ts -> fp
98+
99+
export const tsToFpMinAuthPlugin = <PublicInputArgs, Output>(
100+
i: IMinAuthPlugin<TsInterfaceType, PublicInputArgs, Output>
101+
): IMinAuthPlugin<FpInterfaceType, PublicInputArgs, Output> => {
102+
return {
103+
__interface_tag: 'fp',
104+
verifyAndGetOutput: (pia, sp) =>
105+
fromFailablePromise(() => i.verifyAndGetOutput(pia, sp)),
106+
publicInputArgsSchema: i.publicInputArgsSchema,
107+
customRoutes: i.customRoutes,
108+
verificationKey: i.verificationKey
109+
};
110+
};
111+
112+
export const tsToFpMinAuthPluginFactory = <
113+
Configuration,
114+
PublicInputArgs,
115+
Output
116+
>(
117+
i: IMinAuthPluginFactory<
118+
TsInterfaceType,
119+
IMinAuthPlugin<TsInterfaceType, PublicInputArgs, Output>,
120+
Configuration,
121+
PublicInputArgs,
122+
Output
123+
>
124+
): IMinAuthPluginFactory<
125+
FpInterfaceType,
126+
IMinAuthPlugin<FpInterfaceType, PublicInputArgs, Output>,
127+
Configuration,
128+
PublicInputArgs,
129+
Output
130+
> => {
131+
return {
132+
__interface_tag: 'fp',
133+
configurationSchema: i.configurationSchema,
134+
initialize: (cfg, c) =>
135+
fromFailablePromise(() =>
136+
i.initialize(cfg, fpToTsCheckCachedProofs(c)).then(tsToFpMinAuthPlugin)
137+
)
138+
};
139+
};

0 commit comments

Comments
 (0)