Skip to content

Commit 85be83a

Browse files
authored
Merge pull request #376 from proto-kit/feature/separate-settlement-bridging
Separate settlement and bridging functionally
2 parents e386b94 + 6e79227 commit 85be83a

38 files changed

+2286
-1052
lines changed

packages/common/src/compiling/CompileRegistry.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,22 +47,17 @@ export class CompileRegistry {
4747
return result;
4848
}
4949

50-
public async compile(target: CompileTarget, proverNeeded: boolean = true) {
51-
if (this.artifacts[target.name] === undefined || this.inForceProverBlock) {
50+
public async compile(target: CompileTarget, nameOverride?: string) {
51+
const name = nameOverride ?? target.name;
52+
if (this.artifacts[name] === undefined || this.inForceProverBlock) {
5253
const artifact = await this.compiler.compileContract(target);
53-
this.artifacts[target.name] = artifact;
54+
this.artifacts[name] = artifact;
5455
return artifact;
5556
}
56-
return this.artifacts[target.name];
57+
return this.artifacts[name];
5758
}
5859

5960
public getArtifact(name: string): CompileArtifact | undefined {
60-
if (this.artifacts[name] === undefined) {
61-
throw new Error(
62-
`Artifact for ${name} not available, did you compile it via the CompileRegistry?`
63-
);
64-
}
65-
6661
return this.artifacts[name];
6762
}
6863

packages/common/src/types.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
// allows to reference interfaces as 'classes' rather than instances
2-
import { Bool, DynamicProof, Field, Proof, ProofBase, PublicKey } from "o1js";
2+
import {
3+
Bool,
4+
DynamicProof,
5+
Field,
6+
Proof,
7+
ProofBase,
8+
PublicKey,
9+
Option,
10+
} from "o1js";
311

412
export type TypedClass<Class> = new (...args: any[]) => Class;
513

@@ -56,3 +64,5 @@ export type InferProofBase<
5664
: ProofType extends DynamicProof<infer PI, infer PO>
5765
? ProofBase<PI, PO>
5866
: undefined;
67+
68+
export class O1PublicKeyOption extends Option(PublicKey) {}

packages/protocol/src/hooks/NoopSettlementHook.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ import {
55
ProvableSettlementHook,
66
SettlementHookInputs,
77
} from "../settlement/modularity/ProvableSettlementHook";
8-
import { SettlementSmartContractBase } from "../settlement/contracts/SettlementSmartContract";
8+
import { SettlementContractType } from "../settlement/contracts/settlement/SettlementBase";
99

1010
@injectable()
1111
export class NoopSettlementHook extends ProvableSettlementHook<
1212
Record<string, never>
1313
> {
1414
public async beforeSettlement(
15-
contract: SettlementSmartContractBase,
15+
contract: SettlementContractType,
1616
state: SettlementHookInputs
1717
) {
1818
noop();

packages/protocol/src/index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,11 @@ export * from "./state/assert/assert";
4545
export * from "./settlement/contracts/authorizations/ContractAuthorization";
4646
export * from "./settlement/contracts/authorizations/UpdateMessagesHashAuth";
4747
export * from "./settlement/contracts/authorizations/TokenBridgeDeploymentAuth";
48-
export * from "./settlement/contracts/SettlementSmartContract";
49-
export * from "./settlement/contracts/SettlementContractProtocolModule";
48+
export * from "./settlement/contracts/settlement/SettlementBase";
49+
export * from "./settlement/contracts/settlement/SettlementContract";
50+
export * from "./settlement/contracts/settlement/BridgingSettlementContract";
51+
export * from "./settlement/contracts/BridgingSettlementContractModule";
52+
export * from "./settlement/contracts/SettlementSmartContractModule";
5053
export * from "./settlement/contracts/DispatchSmartContract";
5154
export * from "./settlement/contracts/DispatchContractProtocolModule";
5255
export * from "./settlement/contracts/BridgeContract";
@@ -60,6 +63,7 @@ export * from "./settlement/messages/OutgoingMessageArgument";
6063
export * from "./settlement/messages/OutgoingMessage";
6164
export * from "./settlement/modules/NetworkStateSettlementModule";
6265
export * from "./settlement/messages/Deposit";
66+
export * from "./settlement/ContractArgsRegistry";
6367
export { constants as ProtocolConstants } from "./Constants";
6468
export * from "./hashing/protokit-prefixes";
6569
export * from "./hashing/mina-prefixes";
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { injectable, singleton } from "tsyringe";
2+
import merge from "lodash/merge";
3+
4+
export interface StaticInitializationContract<Args> {
5+
getInitializationArgs(): Args;
6+
}
7+
8+
export type NaiveObjectSchema<Obj> = {
9+
[Key in keyof Obj]: undefined extends Obj[Key] ? "Optional" : "Required";
10+
};
11+
12+
/*
13+
interface Test {
14+
one: string;
15+
two?: string;
16+
}
17+
18+
const x: NaiveObjectSchema<Test> = {
19+
one: "Required",
20+
two: "Optional",
21+
};
22+
*/
23+
24+
@injectable()
25+
@singleton()
26+
export class ContractArgsRegistry {
27+
args: Record<string, any> = {};
28+
29+
public addArgs<Type>(name: string, addition: Partial<Type>) {
30+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
31+
const args: Partial<Type> = this.args[name] ?? {};
32+
this.args[name] = merge(args, addition);
33+
}
34+
35+
public resetArgs(name: string) {
36+
delete this.args[name];
37+
}
38+
39+
public getArgs<Type>(name: string, schema: NaiveObjectSchema<Type>): Type {
40+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
41+
const args = this.args[name] ?? {};
42+
43+
const missing = Object.entries<"Optional" | "Required">(schema).filter(
44+
([key, type]) => {
45+
// We filter only if the key is required and isn't present
46+
return type === "Required" && args[key] === undefined;
47+
}
48+
);
49+
50+
if (missing.length > 0) {
51+
const missingKeys = missing.map(([key]) => key);
52+
throw new Error(
53+
`Contract args for ${name} not all present, ${missingKeys} are missing`
54+
);
55+
} else {
56+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
57+
return args as Type;
58+
}
59+
}
60+
}

packages/protocol/src/settlement/SettlementContractModule.ts

Lines changed: 56 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,19 @@ import { ProtocolModule } from "../protocol/ProtocolModule";
1616
import { ContractModule } from "./ContractModule";
1717
import { DispatchContractProtocolModule } from "./contracts/DispatchContractProtocolModule";
1818
import { DispatchContractType } from "./contracts/DispatchSmartContract";
19-
import {
20-
SettlementContractConfig,
21-
SettlementContractProtocolModule,
22-
} from "./contracts/SettlementContractProtocolModule";
23-
import { SettlementContractType } from "./contracts/SettlementSmartContract";
19+
import { BridgingSettlementContractModule } from "./contracts/BridgingSettlementContractModule";
2420
import { BridgeContractType } from "./contracts/BridgeContract";
2521
import {
2622
BridgeContractConfig,
2723
BridgeContractProtocolModule,
2824
} from "./contracts/BridgeContractProtocolModule";
29-
import { GetContracts } from "./modularity/types";
25+
import { GetContracts, InferContractType } from "./modularity/types";
26+
import { BridgingSettlementContractType } from "./contracts/settlement/BridgingSettlementContract";
27+
import { SettlementContractType } from "./contracts/settlement/SettlementBase";
28+
import {
29+
SettlementContractConfig,
30+
SettlementSmartContractModule,
31+
} from "./contracts/SettlementSmartContractModule";
3032

3133
export type SettlementModulesRecord = ModulesRecord<
3234
TypedClass<ContractModule<unknown, unknown>>
@@ -36,6 +38,12 @@ export type MandatorySettlementModulesRecord = {
3638
SettlementContract: TypedClass<
3739
ContractModule<SettlementContractType, SettlementContractConfig>
3840
>;
41+
};
42+
43+
export type BridgingSettlementModulesRecord = {
44+
SettlementContract: TypedClass<
45+
ContractModule<BridgingSettlementContractType, SettlementContractConfig>
46+
>;
3947
DispatchContract: TypedClass<ContractModule<DispatchContractType, unknown>>;
4048
BridgeContract: TypedClass<
4149
ContractModule<BridgeContractType, BridgeContractConfig>
@@ -44,8 +52,7 @@ export type MandatorySettlementModulesRecord = {
4452

4553
@injectable()
4654
export class SettlementContractModule<
47-
SettlementModules extends SettlementModulesRecord &
48-
MandatorySettlementModulesRecord,
55+
SettlementModules extends SettlementModulesRecord,
4956
>
5057
extends ModuleContainer<SettlementModules>
5158
implements ProtocolModule<unknown>
@@ -54,10 +61,7 @@ export class SettlementContractModule<
5461
super(definition);
5562
}
5663

57-
public static from<
58-
SettlementModules extends SettlementModulesRecord &
59-
MandatorySettlementModulesRecord,
60-
>(
64+
public static from<SettlementModules extends SettlementModulesRecord>(
6165
modules: SettlementModules
6266
): TypedClass<SettlementContractModule<SettlementModules>> {
6367
return class ScopedSettlementContractModule extends SettlementContractModule<SettlementModules> {
@@ -67,27 +71,18 @@ export class SettlementContractModule<
6771
};
6872
}
6973

70-
public static mandatoryModules() {
74+
public static settlementOnly() {
7175
return {
72-
SettlementContract: SettlementContractProtocolModule,
73-
DispatchContract: DispatchContractProtocolModule,
74-
BridgeContract: BridgeContractProtocolModule,
76+
SettlementContract: SettlementSmartContractModule,
7577
} as const;
7678
}
7779

78-
public static fromDefaults() {
79-
return SettlementContractModule.from(
80-
SettlementContractModule.mandatoryModules()
81-
);
82-
}
83-
84-
public static with<AdditionalModules extends SettlementModulesRecord>(
85-
additionalModules: AdditionalModules
86-
) {
87-
return SettlementContractModule.from({
88-
...SettlementContractModule.mandatoryModules(),
89-
...additionalModules,
90-
} as const);
80+
public static settlementAndBridging() {
81+
return {
82+
SettlementContract: BridgingSettlementContractModule,
83+
DispatchContract: DispatchContractProtocolModule,
84+
BridgeContract: BridgeContractProtocolModule,
85+
} as const;
9186
}
9287

9388
// ** For protocol module
@@ -116,30 +111,40 @@ export class SettlementContractModule<
116111
return Object.fromEntries(contracts);
117112
}
118113

119-
public createContracts(addresses: {
120-
settlement: PublicKey;
121-
dispatch: PublicKey;
122-
}): {
123-
settlement: SettlementContractType & SmartContract;
124-
dispatch: DispatchContractType & SmartContract;
125-
} {
126-
const { DispatchContract, SettlementContract } = this.getContractClasses();
127-
128-
const dispatchInstance = new DispatchContract(addresses.dispatch);
129-
const settlementInstance = new SettlementContract(addresses.settlement);
130-
131-
return {
132-
dispatch: dispatchInstance,
133-
settlement: settlementInstance,
134-
};
135-
}
136-
137-
public createBridgeContract(
114+
public createContract<ContractName extends StringKeyOf<SettlementModules>>(
115+
contractName: ContractName,
138116
address: PublicKey,
139117
tokenId?: Field
140-
): BridgeContractType & SmartContract {
141-
const { BridgeContract } = this.getContractClasses();
118+
): InferContractType<SettlementModules[ContractName]> {
119+
const module = this.resolve(contractName);
120+
const ContractClass = module.contractFactory();
121+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
122+
return new ContractClass(address, tokenId) as InferContractType<
123+
SettlementModules[ContractName]
124+
>;
125+
}
142126

143-
return new BridgeContract(address, tokenId);
127+
public createContracts<
128+
ContractName extends keyof SettlementModules,
129+
>(addresses: {
130+
[Key in ContractName]: PublicKey;
131+
}): {
132+
[Key in ContractName]: SmartContract &
133+
InferContractType<SettlementModules[Key]>;
134+
} {
135+
const classes = this.getContractClasses();
136+
137+
const obj: Record<string, SmartContract> = {};
138+
// eslint-disable-next-line guard-for-in
139+
for (const key in addresses) {
140+
const ContractClass = classes[key];
141+
obj[key] = new ContractClass(addresses[key]);
142+
}
143+
144+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
145+
return obj as {
146+
[Key in keyof SettlementModules]: SmartContract &
147+
InferContractType<SettlementModules[Key]>;
148+
};
144149
}
145150
}

0 commit comments

Comments
 (0)