@@ -5,40 +5,51 @@ import fs from "node:fs";
55import path from "node:path" ;
66import { z } from "zod" ;
77import { promiseWithResolvers } from "../utils.js" ;
8- import { inWorkingDir , makeRunCommand } from "./utils.js" ;
9-
10- export type OrderId = string & { __brand : "OrderId" } ;
11- export type PartyIndex = 0 | 1 | 2 ;
12- /**
13- * Deterministically determined based on the tokens being swapped
14- */
15- export type Side = "seller" | "buyer" ;
16-
17- type Order = {
18- side : Side ;
19- id : OrderId ;
20- inputShared : string ;
21- result : ReturnType < typeof promiseWithResolvers < string > > ;
22- } ;
8+ import { inWorkingDir , makeRunCommand , splitInput } from "./utils.js" ;
239
2410export class MpcProverService {
25- // TODO: split this service into per party service to manage storage easier
26- #storage: Record < PartyIndex , Map < OrderId , Order > > = {
27- 0 : new Map ( ) ,
28- 1 : new Map ( ) ,
29- 2 : new Map ( ) ,
11+ readonly #parties = {
12+ 0 : new MpcProverPartyService ( 0 ) ,
13+ 1 : new MpcProverPartyService ( 1 ) ,
14+ 2 : new MpcProverPartyService ( 2 ) ,
3015 } ;
16+
17+ async prove (
18+ inputsShared : Awaited < ReturnType < typeof splitInput > > ,
19+ params : {
20+ orderId : OrderId ;
21+ side : Side ;
22+ circuit : CompiledCircuit ;
23+ // TODO: infer number of public inputs
24+ numPublicInputs : number ;
25+ } ,
26+ ) {
27+ return await Promise . all (
28+ inputsShared . map ( async ( { partyIndex, inputShared } ) => {
29+ return await this . #parties[ partyIndex ] . requestProveAsParty ( {
30+ ...params ,
31+ inputShared,
32+ } ) ;
33+ } ) ,
34+ ) ;
35+ }
36+ }
37+
38+ class MpcProverPartyService {
39+ #storage: Map < OrderId , Order > = new Map ( ) ;
40+
41+ constructor ( readonly partyIndex : PartyIndex ) { }
42+
3143 async requestProveAsParty ( params : {
3244 orderId : OrderId ;
3345 side : Side ;
34- partyIndex : PartyIndex ;
3546 inputShared : string ;
3647 circuit : CompiledCircuit ;
3748 // TODO: infer number of public inputs
3849 numPublicInputs : number ;
3950 } ) {
4051 // TODO(security): authorization
41- if ( this . #storage[ params . partyIndex ] . has ( params . orderId ) ) {
52+ if ( this . #storage. has ( params . orderId ) ) {
4253 throw new Error ( `order already exists ${ params . orderId } ` ) ;
4354 }
4455 const order : Order = {
@@ -47,10 +58,9 @@ export class MpcProverService {
4758 side : params . side ,
4859 result : promiseWithResolvers ( ) ,
4960 } ;
50- this . #storage[ params . partyIndex ] . set ( params . orderId , order ) ;
61+ this . #storage. set ( params . orderId , order ) ;
5162
5263 this . #tryExecuteOrder( params . orderId , {
53- partyIndex : params . partyIndex ,
5464 circuit : params . circuit ,
5565 numPublicInputs : params . numPublicInputs ,
5666 } ) ;
@@ -62,21 +72,20 @@ export class MpcProverService {
6272 orderId : OrderId ,
6373
6474 params : {
65- partyIndex : PartyIndex ;
6675 circuit : CompiledCircuit ;
6776 numPublicInputs : number ;
6877 } ,
6978 ) {
70- const order = this . #storage[ params . partyIndex ] . get ( orderId ) ;
79+ const order = this . #storage. get ( orderId ) ;
7180 if ( ! order ) {
7281 throw new Error (
73- `order not found in party storage ${ params . partyIndex } : ${ orderId } ` ,
82+ `order not found in party storage ${ this . partyIndex } : ${ orderId } ` ,
7483 ) ;
7584 }
7685
77- const otherOrders = Array . from (
78- this . #storage [ params . partyIndex ] . values ( ) ,
79- ) . filter ( ( o ) => o . id !== order . id && o . side !== order . side ) ;
86+ const otherOrders = Array . from ( this . #storage . values ( ) ) . filter (
87+ ( o ) => o . id !== order . id && o . side !== order . side ,
88+ ) ;
8089 if ( otherOrders . length === 0 ) {
8190 return ;
8291 }
@@ -87,13 +96,12 @@ export class MpcProverService {
8796 : ( [ otherOrder . inputShared , order . inputShared ] as const ) ;
8897 console . log (
8998 "executing orders" ,
90- params . partyIndex ,
99+ this . partyIndex ,
91100 omit ( order , [ "inputShared" , "result" ] ) ,
92101 omit ( otherOrder , [ "inputShared" , "result" ] ) ,
93102 ) ;
94103 try {
95- const { proof } = await this . proveAsParty ( {
96- partyIndex : params . partyIndex ,
104+ const { proof } = await this . #prove( {
97105 circuit : params . circuit ,
98106 input0Shared : inputsShared [ 0 ] ,
99107 input1Shared : inputsShared [ 1 ] ,
@@ -108,15 +116,14 @@ export class MpcProverService {
108116 }
109117 }
110118
111- async proveAsParty ( params : {
112- partyIndex : number ;
119+ async #prove( params : {
113120 circuit : CompiledCircuit ;
114121 input0Shared : string ;
115122 input1Shared : string ;
116123 // TODO: infer number of public inputs
117124 numPublicInputs : number ;
118125 } ) {
119- console . log ( "proving as party" , params . partyIndex ) ;
126+ console . log ( "proving as party" , this . partyIndex ) ;
120127 return await inWorkingDir ( async ( workingDir ) => {
121128 for ( const [ traderIndex , inputShared ] of [
122129 params . input0Shared ,
@@ -125,7 +132,7 @@ export class MpcProverService {
125132 fs . writeFileSync (
126133 path . join (
127134 workingDir ,
128- `Prover${ traderIndex } .toml.${ params . partyIndex } .shared` ,
135+ `Prover${ traderIndex } .toml.${ this . partyIndex } .shared` ,
129136 ) ,
130137 ethers . getBytes ( inputShared ) ,
131138 ) ;
@@ -136,7 +143,7 @@ export class MpcProverService {
136143
137144 const runCommand = makeRunCommand ( __dirname ) ;
138145 await runCommand (
139- `./run-party.sh ${ workingDir } ${ circuitPath } ${ params . partyIndex } ` ,
146+ `./run-party.sh ${ workingDir } ${ circuitPath } ${ this . partyIndex } ` ,
140147 ) ;
141148
142149 const publicInputs = z
@@ -152,7 +159,7 @@ export class MpcProverService {
152159 ) ;
153160 const proofData = Uint8Array . from (
154161 fs . readFileSync (
155- path . join ( workingDir , `proof.${ params . partyIndex } .proof` ) ,
162+ path . join ( workingDir , `proof.${ this . partyIndex } .proof` ) ,
156163 ) ,
157164 ) ;
158165 // arcane magic
@@ -168,3 +175,17 @@ export class MpcProverService {
168175 } ) ;
169176 }
170177}
178+
179+ export type OrderId = string & { __brand : "OrderId" } ;
180+ export type PartyIndex = 0 | 1 | 2 ;
181+ /**
182+ * Deterministically determined based on the tokens being swapped
183+ */
184+ export type Side = "seller" | "buyer" ;
185+
186+ type Order = {
187+ side : Side ;
188+ id : OrderId ;
189+ inputShared : string ;
190+ result : ReturnType < typeof promiseWithResolvers < string > > ;
191+ } ;
0 commit comments