mirror of
https://github.com/privacy-scaling-explorations/mpc-framework.git
synced 2026-04-19 03:01:39 -04:00
Merge pull request #14 from privacy-scaling-explorations/update-circuit-type
Updates for summon io and new circuit type
This commit is contained in:
59
README.md
59
README.md
@@ -2,7 +2,7 @@
|
||||
|
||||
A framework that makes MPC easy in TypeScript.
|
||||
|
||||
Choose from multiple existing circuit generators and MPC backends, or create
|
||||
Choose from multiple existing circuit generators and MPC engines, or create
|
||||
your own.
|
||||
|
||||
## What is MPC?
|
||||
@@ -36,12 +36,12 @@ For a more technical introduction, see [Computerphile's video on Garbled Circuit
|
||||
In addition to `mpc-framework`, you will need:
|
||||
|
||||
- a circuit generator to turn your MPC program into a circuit (or byo precompiled or handwritten circuit)
|
||||
- an mpc-framework backend to do the underlying cryptography
|
||||
- an mpc-framework engine to do the underlying cryptography
|
||||
|
||||
```sh
|
||||
npm install mpc-framework
|
||||
npm install summon-ts # circuit generator
|
||||
npm install emp-wasm-backend # backend
|
||||
npm install emp-wasm-engine # engine
|
||||
```
|
||||
|
||||
### Step 1: Create a Circuit
|
||||
@@ -51,13 +51,19 @@ circuit. This is a special simplified program in the form of a fixed tree
|
||||
specifying how to combine values together. Regular programs allow the CPU to
|
||||
branch into different code paths, and circuits can't do that. It's possible to
|
||||
write these circuits by hand (or using third party tools), but you might find it
|
||||
easier to use [summon](https://github.com/voltrevo/summon/):
|
||||
easier to use [summon](https://github.com/privacy-scaling-explorations/summon/):
|
||||
|
||||
```ts
|
||||
// This isn't exactly TypeScript, but it uses the same syntax and has enough in
|
||||
// common that you can use the .ts extension and get useful intellisense
|
||||
|
||||
export default function main(a: number, b: number) {
|
||||
export default (io: Summon.IO) => {
|
||||
// Alice provides a number called 'a'
|
||||
const a = io.input('alice', 'a', summon.number());
|
||||
|
||||
// Bob provides a number called 'b'
|
||||
const b = io.input('bob', 'b', summon.number());
|
||||
|
||||
let result;
|
||||
|
||||
// This seems like a branch that I just said is not allowed, but this is just
|
||||
@@ -69,7 +75,8 @@ export default function main(a: number, b: number) {
|
||||
result = b;
|
||||
}
|
||||
|
||||
return result;
|
||||
// Everyone gets an output called 'result'
|
||||
io.outputPublic('result', result);
|
||||
}
|
||||
|
||||
// We could inline this, but we're just demonstrating that summon supports
|
||||
@@ -88,19 +95,19 @@ import * as summon from 'summon-ts';
|
||||
|
||||
await summon.init();
|
||||
|
||||
const { circuit } = summon.compileBoolean(
|
||||
const { circuit } = summon.compile({
|
||||
// Specify the entry point, similar to the `main` field of package.json
|
||||
'circuit/main.ts',
|
||||
path: 'circuit/main.ts',
|
||||
|
||||
// This is the bit width of numbers in your summon program. You can use any
|
||||
// width you like, but all numbers in the program will be the same. You can
|
||||
// achieve smaller bit widths within the program using masking (the unused
|
||||
// gates will be optimized away). It's also possible to define classes for
|
||||
// matrices/floats/etc.
|
||||
16,
|
||||
boolifyWidth: 8,
|
||||
|
||||
// File tree to compile
|
||||
{
|
||||
files: {
|
||||
'circuit/main.ts': `
|
||||
// Include code from step 1
|
||||
// This can be inlined or you can use build tools to just include a
|
||||
@@ -109,34 +116,18 @@ const { circuit } = summon.compileBoolean(
|
||||
`,
|
||||
// Other files can be specified here
|
||||
},
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
### Step 3: Set up your Protocol
|
||||
|
||||
```ts
|
||||
import { Protocol } from 'mpc-framework';
|
||||
import { EmpWasmBackend } from 'emp-wasm-backend';
|
||||
import { EmpWasmEngine } from 'emp-wasm-engine';
|
||||
|
||||
// ...
|
||||
|
||||
// Specify who provides each input, and who receives each output
|
||||
// (Our chosen backend currently requires that everyone gets all outputs)
|
||||
const mpcSettings = [
|
||||
{
|
||||
name: 'alice',
|
||||
inputs: ['a'],
|
||||
outputs: ['main'],
|
||||
},
|
||||
{
|
||||
name: 'bob',
|
||||
inputs: ['b'],
|
||||
outputs: ['main'],
|
||||
},
|
||||
// You can have more than 2 parties. We're just keeping it simple here.
|
||||
];
|
||||
|
||||
const protocol = new Protocol(circuit, mpcSettings, new EmpWasmBackend());
|
||||
const protocol = new Protocol(circuit, new EmpWasmEngine());
|
||||
```
|
||||
|
||||
### Step 4: Run the Protocol
|
||||
@@ -169,15 +160,15 @@ For clarity, a complete version of the example above is provided as
|
||||
|
||||
| Name | Similar to | Related Repos |
|
||||
| ----------------------------------------------------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [`summon-ts`](https://github.com/voltrevo/summon-ts/) | TypeScript | [`summon`](https://github.com/voltrevo/summon/), [`boolify`](https://github.com/voltrevo/boolify/), [`ValueScript`](https://github.com/voltrevo/ValueScript/) |
|
||||
| [`circom-2-arithc-ts`](https://github.com/voltrevo/circom-2-arithc-ts/) | Circom | [`circom-2-arithc`](https://github.com/namnc/circom-2-arithc/), [`circom`](https://github.com/iden3/circom/) |
|
||||
| [`summon-ts`](https://github.com/privacy-scaling-explorations/summon-ts/) | TypeScript | [`summon`](https://github.com/privacy-scaling-explorations/summon/), [`boolify`](https://github.com/privacy-scaling-explorations/boolify/), [`ValueScript`](https://github.com/voltrevo/ValueScript/) |
|
||||
| [`circom-2-arithc-ts`](https://github.com/privacy-scaling-explorations/circom-2-arithc-ts/) | Circom | [`circom-2-arithc`](https://github.com/namnc/circom-2-arithc/), [`circom`](https://github.com/iden3/circom/) |
|
||||
|
||||
## **Backends**
|
||||
## **Engines**
|
||||
|
||||
| Name | Description | Related Repos |
|
||||
| ------------------------------------------------------------------- | --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [`emp-wasm-backend`](https://github.com/voltrevo/emp-wasm-backend/) | Secure MPC using authenticated garbling | [`emp-wasm`](https://github.com/voltrevo/emp-wasm), [`emp-ag2pc`](https://github.com/emp-toolkit/emp-ag2pc/), [`emp-agmpc`](https://github.com/emp-toolkit/emp-agmpc/) |
|
||||
| [`mpz-ts`](https://github.com/voltrevo/mpz-ts) | Semi-honest 2PC | [`mpz`](https://github.com/privacy-scaling-explorations/mpz) |
|
||||
| [`emp-wasm-engine`](https://github.com/privacy-scaling-explorations/emp-wasm-engine/) | Secure MPC using authenticated garbling | [`emp-wasm`](https://github.com/privacy-scaling-explorations/emp-wasm), [`emp-ag2pc`](https://github.com/emp-toolkit/emp-ag2pc/), [`emp-agmpc`](https://github.com/emp-toolkit/emp-agmpc/) |
|
||||
| [`mpz-ts`](https://github.com/privacy-scaling-explorations/mpz-ts) | Semi-honest 2PC | [`mpz`](https://github.com/privacy-scaling-explorations/mpz) |
|
||||
|
||||
## Example Projects
|
||||
|
||||
|
||||
27
package-lock.json
generated
27
package-lock.json
generated
@@ -1,16 +1,16 @@
|
||||
{
|
||||
"name": "mpc-framework",
|
||||
"version": "0.2.1",
|
||||
"version": "0.3.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "mpc-framework",
|
||||
"version": "0.2.1",
|
||||
"version": "0.3.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ee-typed": "^0.1.1",
|
||||
"mpc-framework-common": "^0.1.1",
|
||||
"mpc-framework-common": "^0.3.0",
|
||||
"msgpackr": "^1.11.0",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
@@ -29,7 +29,7 @@
|
||||
"eslint-plugin-react-refresh": "^0.4.6",
|
||||
"mocha": "^10.7.0",
|
||||
"prettier": "^3.4.2",
|
||||
"summon-ts": "^0.2.5",
|
||||
"summon-ts": "^0.6.0",
|
||||
"tsx": "^4.16.5",
|
||||
"typescript": "^5.4.5"
|
||||
}
|
||||
@@ -1366,6 +1366,13 @@
|
||||
"sha3": "^2.1.4"
|
||||
}
|
||||
},
|
||||
"node_modules/emp-wasm-backend/node_modules/mpc-framework-common": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/mpc-framework-common/-/mpc-framework-common-0.1.1.tgz",
|
||||
"integrity": "sha512-D+o1vSdFPl9v55c0kgM2dGcUR0IZQn3teeQHA5pWiwjokbMt7uiNHHqQKyrzsY2Y4TfBbVKjnS9yjM6szIO5Ng==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
|
||||
@@ -2278,9 +2285,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/mpc-framework-common": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/mpc-framework-common/-/mpc-framework-common-0.1.1.tgz",
|
||||
"integrity": "sha512-D+o1vSdFPl9v55c0kgM2dGcUR0IZQn3teeQHA5pWiwjokbMt7uiNHHqQKyrzsY2Y4TfBbVKjnS9yjM6szIO5Ng==",
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/mpc-framework-common/-/mpc-framework-common-0.3.0.tgz",
|
||||
"integrity": "sha512-LHKnvcUyVx3Ct3rUJNmkOegApRXl7NtR2Ezi+PbJCqkTdwOca3K8F7JgMOhXyvIqtRW62biETIYWordzCeDVBw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ms": {
|
||||
@@ -2805,9 +2812,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/summon-ts": {
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/summon-ts/-/summon-ts-0.2.5.tgz",
|
||||
"integrity": "sha512-VtsdFLyvctiYzgfXFH18UlD5u9Do8aNU0sBxiiDT0Tqdru1vAT+LfBwLSRfisry5avEUheYWMFL/5Hix3rIo5Q==",
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/summon-ts/-/summon-ts-0.6.0.tgz",
|
||||
"integrity": "sha512-mY0Z5gHovzT9Htscj+gBswiLr9ADSMpQplqybuEPvsdCde85Uz2dpCDG8ucffl/6xpVzDEG/JoXbH+SXKzjCqg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mpc-framework",
|
||||
"version": "0.2.1",
|
||||
"version": "0.3.0",
|
||||
"description": "MPC framework supporting a variety of circuit generators and backends",
|
||||
"type": "module",
|
||||
"main": "dist/src/index.js",
|
||||
@@ -40,13 +40,13 @@
|
||||
"prettier": "^3.4.2",
|
||||
"emp-wasm-backend": "^0.2.1",
|
||||
"mocha": "^10.7.0",
|
||||
"summon-ts": "^0.2.5",
|
||||
"summon-ts": "^0.6.0",
|
||||
"tsx": "^4.16.5",
|
||||
"typescript": "^5.4.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"ee-typed": "^0.1.1",
|
||||
"mpc-framework-common": "^0.1.1",
|
||||
"mpc-framework-common": "^0.3.0",
|
||||
"msgpackr": "^1.11.0",
|
||||
"zod": "^3.23.8"
|
||||
}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
import PlaintextBackendHostSession from './PlaintextBackendHostSession.js';
|
||||
import PlaintextBackendClientSession from './PlaintextBackendClientSession.js';
|
||||
import {
|
||||
Backend,
|
||||
BackendSession,
|
||||
Circuit,
|
||||
MpcSettings,
|
||||
} from 'mpc-framework-common';
|
||||
|
||||
export default class PlaintextBackend implements Backend {
|
||||
run(
|
||||
circuit: Circuit,
|
||||
mpcSettings: MpcSettings,
|
||||
name: string,
|
||||
input: Record<string, unknown>,
|
||||
send: (to: string, msg: Uint8Array) => void,
|
||||
): BackendSession {
|
||||
const hostName = mpcSettings[0].name ?? '0';
|
||||
|
||||
if (name === hostName) {
|
||||
return new PlaintextBackendHostSession(
|
||||
circuit,
|
||||
mpcSettings,
|
||||
name,
|
||||
input,
|
||||
send,
|
||||
);
|
||||
}
|
||||
|
||||
return new PlaintextBackendClientSession(
|
||||
circuit,
|
||||
mpcSettings,
|
||||
name,
|
||||
input,
|
||||
send,
|
||||
hostName,
|
||||
);
|
||||
}
|
||||
}
|
||||
26
src/PlaintextEngine/PlaintextEngine.ts
Normal file
26
src/PlaintextEngine/PlaintextEngine.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import PlaintextEngineHostSession from './PlaintextEngineHostSession.js';
|
||||
import PlaintextEngineClientSession from './PlaintextEngineClientSession.js';
|
||||
import { Engine, EngineSession, Circuit } from 'mpc-framework-common';
|
||||
|
||||
export default class PlaintextEngine implements Engine {
|
||||
run(
|
||||
circuit: Circuit,
|
||||
name: string,
|
||||
input: Record<string, unknown>,
|
||||
send: (to: string, msg: Uint8Array) => void,
|
||||
): EngineSession {
|
||||
const hostName = circuit.mpcSettings[0].name ?? '0';
|
||||
|
||||
if (name === hostName) {
|
||||
return new PlaintextEngineHostSession(circuit, name, input, send);
|
||||
}
|
||||
|
||||
return new PlaintextEngineClientSession(
|
||||
circuit,
|
||||
name,
|
||||
input,
|
||||
send,
|
||||
hostName,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,14 @@
|
||||
import { pack, unpack } from 'msgpackr';
|
||||
import defer from '../helpers/defer.js';
|
||||
import { z } from 'zod';
|
||||
import { BackendSession, Circuit, MpcSettings } from 'mpc-framework-common';
|
||||
import { EngineSession, Circuit } from 'mpc-framework-common';
|
||||
|
||||
export default class PlaintextBackendClientSession implements BackendSession {
|
||||
export default class PlaintextEngineClientSession implements EngineSession {
|
||||
outputReceived = defer<Record<string, unknown>>();
|
||||
inputsSent = false;
|
||||
|
||||
constructor(
|
||||
public circuit: Circuit,
|
||||
public mpcSettings: MpcSettings,
|
||||
public name: string,
|
||||
public input: Record<string, unknown>,
|
||||
public send: (to: string, msg: Uint8Array) => void,
|
||||
@@ -5,9 +5,9 @@ import delay from '../helpers/delay.js';
|
||||
import defer from '../helpers/defer.js';
|
||||
import evaluate, { u32Arithmetic } from '../helpers/evaluate.js';
|
||||
import errorToString from '../helpers/errorToString.js';
|
||||
import { BackendSession, Circuit, MpcSettings } from 'mpc-framework-common';
|
||||
import { EngineSession, Circuit } from 'mpc-framework-common';
|
||||
|
||||
export default class PlaintextBackendHostSession implements BackendSession {
|
||||
export default class PlaintextEngineHostSession implements EngineSession {
|
||||
outputPromise: Promise<Record<string, unknown>>;
|
||||
combinedInputs = defer<Record<string, unknown>>();
|
||||
partialCombinedInputs: Record<string, unknown>;
|
||||
@@ -15,7 +15,6 @@ export default class PlaintextBackendHostSession implements BackendSession {
|
||||
|
||||
constructor(
|
||||
public circuit: Circuit,
|
||||
public mpcSettings: MpcSettings,
|
||||
public name: string,
|
||||
public input: Record<string, unknown>,
|
||||
public send: (to: string, msg: Uint8Array) => void,
|
||||
@@ -30,8 +29,8 @@ export default class PlaintextBackendHostSession implements BackendSession {
|
||||
(async () => {
|
||||
// eslint-disable-next-line no-unmodified-loop-condition
|
||||
while (shouldPing) {
|
||||
for (let i = 1; i < this.mpcSettings.length; i++) {
|
||||
const to = this.mpcSettings[i].name ?? i.toString();
|
||||
for (let i = 1; i < this.circuit.mpcSettings.length; i++) {
|
||||
const to = this.circuit.mpcSettings[i].name ?? i.toString();
|
||||
this.send(to, pack('ping'));
|
||||
}
|
||||
|
||||
@@ -50,8 +49,8 @@ export default class PlaintextBackendHostSession implements BackendSession {
|
||||
const fullResult = evaluate(this.circuit, combinedInputs, u32Arithmetic);
|
||||
let selfResult: Record<string, unknown> = {};
|
||||
|
||||
for (let i = 0; i < this.mpcSettings.length; i++) {
|
||||
const { name = i.toString(), outputs } = this.mpcSettings[i];
|
||||
for (let i = 0; i < this.circuit.mpcSettings.length; i++) {
|
||||
const { name = i.toString(), outputs } = this.circuit.mpcSettings[i];
|
||||
const result: Record<string, unknown> = {};
|
||||
|
||||
for (const outputName of outputs) {
|
||||
@@ -74,7 +73,7 @@ export default class PlaintextBackendHostSession implements BackendSession {
|
||||
throw new Error('Already received');
|
||||
}
|
||||
|
||||
const peerInfo = this.mpcSettings.find(
|
||||
const peerInfo = this.circuit.mpcSettings.find(
|
||||
(s, i) => from === (s.name ?? i.toString()),
|
||||
);
|
||||
|
||||
@@ -94,7 +93,10 @@ export default class PlaintextBackendHostSession implements BackendSession {
|
||||
|
||||
this.peerInputsReceived.add(from);
|
||||
|
||||
if (this.peerInputsReceived.size === this.mpcSettings.length - 1) {
|
||||
if (
|
||||
this.peerInputsReceived.size ===
|
||||
this.circuit.mpcSettings.length - 1
|
||||
) {
|
||||
this.combinedInputs.resolve(this.partialCombinedInputs);
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -1,11 +1,10 @@
|
||||
import { Backend, Circuit, MpcSettings } from 'mpc-framework-common';
|
||||
import { Engine, Circuit } from 'mpc-framework-common';
|
||||
import Session from './Session.js';
|
||||
|
||||
export default class Protocol {
|
||||
constructor(
|
||||
public circuit: Circuit,
|
||||
public mpcSettings: MpcSettings,
|
||||
public backend: Backend,
|
||||
public engine: Engine,
|
||||
) {}
|
||||
|
||||
join(
|
||||
@@ -13,13 +12,6 @@ export default class Protocol {
|
||||
input: Record<string, unknown>,
|
||||
send: (to: string, msg: Uint8Array) => void,
|
||||
): Session {
|
||||
return new Session(
|
||||
this.circuit,
|
||||
this.mpcSettings,
|
||||
this.backend,
|
||||
name,
|
||||
input,
|
||||
send,
|
||||
);
|
||||
return new Session(this.circuit, this.engine, name, input, send);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +1,23 @@
|
||||
import {
|
||||
Backend,
|
||||
BackendSession,
|
||||
Circuit,
|
||||
MpcSettings,
|
||||
} from 'mpc-framework-common';
|
||||
import { Engine, EngineSession, Circuit } from 'mpc-framework-common';
|
||||
|
||||
export default class Session {
|
||||
backendSession: BackendSession;
|
||||
engineSession: EngineSession;
|
||||
|
||||
constructor(
|
||||
public circuit: Circuit,
|
||||
public mpcSettings: MpcSettings,
|
||||
public backend: Backend,
|
||||
public engine: Engine,
|
||||
public name: string,
|
||||
public input: Record<string, unknown>,
|
||||
public send: (to: string, msg: Uint8Array) => void,
|
||||
) {
|
||||
this.backendSession = backend.run(circuit, mpcSettings, name, input, send);
|
||||
this.engineSession = engine.run(circuit, name, input, send);
|
||||
}
|
||||
|
||||
handleMessage(from: string, msg: Uint8Array) {
|
||||
this.backendSession.handleMessage(from, msg);
|
||||
this.engineSession.handleMessage(from, msg);
|
||||
}
|
||||
|
||||
async output(): Promise<Record<string, unknown>> {
|
||||
return await this.backendSession.output();
|
||||
return await this.engineSession.output();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable camelcase */
|
||||
import { Circuit } from 'mpc-framework-common';
|
||||
|
||||
export default function evaluate<T>(
|
||||
@@ -15,25 +14,23 @@ export default function evaluate<T>(
|
||||
|
||||
const wires = new Array<T>(wireCount).fill(arithmetic.init(0));
|
||||
|
||||
for (const { value, wire_index } of Object.values(circuit.info.constants)) {
|
||||
wires[wire_index] = arithmetic.init(value);
|
||||
for (const { value, address } of circuit.info.constants) {
|
||||
wires[address] = arithmetic.init(value);
|
||||
}
|
||||
|
||||
if (
|
||||
Object.keys(inputs).length !==
|
||||
Object.keys(circuit.info.input_name_to_wire_index).length
|
||||
) {
|
||||
if (Object.keys(inputs).length !== circuit.info.inputs.length) {
|
||||
throw new Error('Mismatch between input len and required input len');
|
||||
}
|
||||
|
||||
for (const [name, value] of Object.entries(inputs)) {
|
||||
const wireIndex = circuit.info.input_name_to_wire_index[name];
|
||||
const inputInfo = circuit.info.inputs.find(i => i.name === name);
|
||||
const address = inputInfo?.address;
|
||||
|
||||
if (wireIndex === undefined) {
|
||||
if (address === undefined) {
|
||||
throw new Error(`Couldn't map input ${name} to a wire`);
|
||||
}
|
||||
|
||||
wires[wireIndex] = arithmetic.init(value);
|
||||
wires[address] = arithmetic.init(value);
|
||||
}
|
||||
|
||||
let i = 1;
|
||||
@@ -79,10 +76,8 @@ export default function evaluate<T>(
|
||||
|
||||
const res: Record<string, T> = {};
|
||||
|
||||
for (const [name, wireIndex] of Object.entries(
|
||||
circuit.info.output_name_to_wire_index,
|
||||
)) {
|
||||
res[name] = wires[wireIndex];
|
||||
for (const { name, address } of circuit.info.outputs) {
|
||||
res[name] = wires[address];
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
@@ -2,8 +2,8 @@ export { default as Protocol } from './Protocol.js';
|
||||
export { default as Session } from './Session.js';
|
||||
export {
|
||||
type Circuit,
|
||||
type Backend,
|
||||
type BackendSession,
|
||||
type Engine,
|
||||
type EngineSession,
|
||||
type MpcParticipantSettings,
|
||||
type MpcSettings,
|
||||
} from 'mpc-framework-common';
|
||||
@@ -11,4 +11,4 @@ export {
|
||||
// This is NOT exported because it is almost never wanted and depends
|
||||
// unnecessarily on msgpackr. Importing msgpackr creates a lot of permissions
|
||||
// noise in Deno on startup.
|
||||
// export { default as PlaintextBackend } from './PlaintextBackend/PlaintextBackend.js';
|
||||
// export { default as PlaintextEngine } from './PlaintextEngine/PlaintextEngine.js';
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
import * as summon from 'summon-ts';
|
||||
import { EmpWasmBackend } from 'emp-wasm-backend';
|
||||
|
||||
import * as mpcf from '../src';
|
||||
import { LocalComms, makeLocalCommsPair } from './helpers/LocalComms';
|
||||
import assert from '../src/helpers/assert';
|
||||
import { expect } from 'chai';
|
||||
|
||||
describe('EmpWasmBackend', () => {
|
||||
it('3 + 5', async () => {
|
||||
const outputs = await demo();
|
||||
expect(outputs).to.deep.eq([{ main: 8 }, { main: 8 }]);
|
||||
});
|
||||
});
|
||||
|
||||
async function demo() {
|
||||
await summon.init();
|
||||
|
||||
const [aliceComms, bobComms] = makeLocalCommsPair();
|
||||
|
||||
const circuit = summon.compileBoolean('/src/main.ts', 4, {
|
||||
'/src/main.ts': `
|
||||
export default function main(a: number, b: number) {
|
||||
return a + b;
|
||||
}
|
||||
`,
|
||||
});
|
||||
|
||||
const mpcSettings = [
|
||||
{
|
||||
name: 'alice',
|
||||
inputs: ['a'],
|
||||
outputs: ['main'],
|
||||
},
|
||||
{
|
||||
name: 'bob',
|
||||
inputs: ['b'],
|
||||
outputs: ['main'],
|
||||
},
|
||||
];
|
||||
|
||||
const protocol = new mpcf.Protocol(
|
||||
circuit,
|
||||
mpcSettings,
|
||||
new EmpWasmBackend(),
|
||||
);
|
||||
|
||||
const outputs = await Promise.all([
|
||||
runParty('alice', protocol, aliceComms),
|
||||
runParty('bob', protocol, bobComms),
|
||||
]);
|
||||
|
||||
return outputs;
|
||||
}
|
||||
|
||||
async function runParty(
|
||||
party: 'alice' | 'bob',
|
||||
protocol: mpcf.Protocol,
|
||||
comms: LocalComms,
|
||||
) {
|
||||
const otherParty = party === 'alice' ? 'bob' : 'alice';
|
||||
|
||||
const session = protocol.join(
|
||||
party,
|
||||
party === 'alice' ? { a: 3 } : { b: 5 },
|
||||
(to, msg) => {
|
||||
assert(to === otherParty);
|
||||
comms.send(msg);
|
||||
},
|
||||
);
|
||||
|
||||
const buffered = comms.recv();
|
||||
|
||||
if (buffered.length > 0) {
|
||||
session.handleMessage(otherParty, buffered);
|
||||
}
|
||||
|
||||
comms.recvBuf.on('data', data => session.handleMessage(otherParty, data));
|
||||
|
||||
const output = await session.output();
|
||||
|
||||
return output;
|
||||
}
|
||||
@@ -5,13 +5,21 @@ import once from '../../src/helpers/once';
|
||||
const aPlusB = once(async () => {
|
||||
await summon.init();
|
||||
|
||||
return summon.compile('/src/main.ts', {
|
||||
'/src/main.ts': `
|
||||
export default function c(a: number, b: number) {
|
||||
return a + b;
|
||||
}
|
||||
`,
|
||||
const { circuit } = summon.compile({
|
||||
path: '/src/main.ts',
|
||||
files: {
|
||||
'/src/main.ts': `
|
||||
export default (io: Summon.IO) => {
|
||||
const a = io.input('alice', 'a', summon.number());
|
||||
const b = io.input('bob', 'b', summon.number());
|
||||
|
||||
io.outputPublic('c', a + b);
|
||||
}
|
||||
`,
|
||||
},
|
||||
});
|
||||
|
||||
return circuit;
|
||||
});
|
||||
|
||||
export default aPlusB;
|
||||
|
||||
@@ -1,28 +1,13 @@
|
||||
import { expect } from 'chai';
|
||||
import Protocol from '../src/Protocol';
|
||||
import aPlusB from './circuits/aPlusB';
|
||||
import PlaintextBackend from '../src/PlaintextBackend/PlaintextBackend';
|
||||
import PlaintextEngine from '../src/PlaintextEngine/PlaintextEngine';
|
||||
import { EventEmitter } from 'ee-typed';
|
||||
import assert from '../src/helpers/assert';
|
||||
|
||||
describe('plaintext', () => {
|
||||
it('3 + 5', async () => {
|
||||
const protocol = new Protocol(
|
||||
await aPlusB(),
|
||||
[
|
||||
{
|
||||
name: 'alice',
|
||||
inputs: ['a'],
|
||||
outputs: ['c'],
|
||||
},
|
||||
{
|
||||
name: 'bob',
|
||||
inputs: ['b'],
|
||||
outputs: ['c'],
|
||||
},
|
||||
],
|
||||
new PlaintextBackend(),
|
||||
);
|
||||
const protocol = new Protocol(await aPlusB(), new PlaintextEngine());
|
||||
|
||||
const messageEvents = new EventEmitter<{
|
||||
aliceToBob(msg: Uint8Array): void;
|
||||
|
||||
Reference in New Issue
Block a user