Skip to content

Commit

Permalink
fix: serialize AvmVerificationKeyData (#8529)
Browse files Browse the repository at this point in the history
This PR adds a integration test for the RPC layer between the queue and
agent to validate that all the function calls correctly encode/decode
their inputs and outputs.
  • Loading branch information
alexghr authored Sep 13, 2024
1 parent 16fba46 commit 78c94a4
Show file tree
Hide file tree
Showing 8 changed files with 276 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/devnet-deploys.yml
Original file line number Diff line number Diff line change
Expand Up @@ -770,7 +770,7 @@ jobs:
run: |
./.github/scripts/wait_for_infra.sh pxe ${{ env.DEPLOY_TAG }} ${{ env.API_KEY }}
- name: Deploy verifier (allow failure)
- name: Deploy verifier
working-directory: ./yarn-project/aztec/terraform/pxe
run: |
set -eo pipefail
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/end-to-end/package.local.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
"test": "LOG_LEVEL=${LOG_LEVEL:-verbose} DEBUG_COLORS=1 NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --testTimeout=300000 --forceExit",
"test:unit": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest src/fixtures"
}
}
}
37 changes: 34 additions & 3 deletions yarn-project/foundation/src/json-rpc/server/json_rpc_server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import compress from 'koa-compress';
import Router from 'koa-router';

import { createDebugLogger } from '../../log/index.js';
import { promiseWithResolvers } from '../../promise/utils.js';
import { type JsonClassConverterInput, type StringClassConverterInput } from '../class_converter.js';
import { convertBigintsInObj } from '../convert.js';
import { type ClassMaps, JsonProxy } from './json_proxy.js';
Expand All @@ -19,6 +20,13 @@ export class JsonRpcServer {
* The proxy object.
*/
public proxy: JsonProxy;

/**
* The HTTP server accepting remote requests.
* This member field is initialized when the server is started.
*/
private httpServer?: http.Server;

constructor(
private handler: object,
private stringClassMap: StringClassConverterInput,
Expand Down Expand Up @@ -141,9 +149,32 @@ export class JsonRpcServer {
* @param port - Port number.
* @param prefix - Prefix string.
*/
public start(port: number, prefix = '') {
const httpServer = http.createServer(this.getApp(prefix).callback());
httpServer.listen(port);
public start(port: number, prefix = ''): void {
if (this.httpServer) {
throw new Error('Server is already listening');
}

this.httpServer = http.createServer(this.getApp(prefix).callback());
this.httpServer.listen(port);
}

/**
* Stops the HTTP server
*/
public stop(): Promise<void> {
if (!this.httpServer) {
return Promise.resolve();
}

const { promise, resolve, reject } = promiseWithResolvers<void>();
this.httpServer.close(err => {
if (err) {
reject(err);
} else {
resolve();
}
});
return promise;
}

/**
Expand Down
1 change: 1 addition & 0 deletions yarn-project/prover-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
"@types/memdown": "^3.0.0",
"@types/node": "^18.7.23",
"@types/source-map-support": "^0.5.10",
"get-port": "^7.1.0",
"jest": "^29.5.0",
"jest-mock-extended": "^3.0.3",
"ts-node": "^10.9.1",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { PublicKernelType, type ServerCircuitProver } from '@aztec/circuit-types';
import { ClientIvcProof, Fr, PrivateKernelEmptyInputData, TubeInputs } from '@aztec/circuits.js';
import {
makeAvmCircuitInputs,
makeBaseParityInputs,
makeBaseRollupInputs,
makeBlockMergeRollupInputs,
makeBlockRootRollupInputs,
makeHeader,
makeMergeRollupInputs,
makePublicKernelCircuitPrivateInputs,
makePublicKernelTailCircuitPrivateInputs,
makeRootParityInputs,
makeRootRollupInputs,
} from '@aztec/circuits.js/testing';
import { type JsonRpcServer } from '@aztec/foundation/json-rpc/server';
import { NoopTelemetryClient } from '@aztec/telemetry-client/noop';

import getPort from 'get-port';

import { MockProver } from '../test/mock_prover.js';
import { MemoryProvingQueue } from './memory-proving-queue.js';
import { ProverAgent } from './prover-agent.js';
import { createProvingJobSourceClient, createProvingJobSourceServer } from './rpc.js';

describe('Prover agent <-> queue integration', () => {
let queue: MemoryProvingQueue;
let queueRpcServer: JsonRpcServer;
let agent: ProverAgent;
let prover: ServerCircuitProver;

type MakeInputs = {
[K in keyof ServerCircuitProver]: () => Parameters<ServerCircuitProver[K]>[0];
};

const makeInputs: MakeInputs = {
getAvmProof: makeAvmCircuitInputs,
getBaseParityProof: makeBaseParityInputs,
getBaseRollupProof: makeBaseRollupInputs,
getRootParityProof: makeRootParityInputs,
getBlockMergeRollupProof: makeBlockMergeRollupInputs,
getBlockRootRollupProof: makeBlockRootRollupInputs,
getEmptyPrivateKernelProof: () =>
new PrivateKernelEmptyInputData(makeHeader(), Fr.random(), Fr.random(), Fr.random()),
getEmptyTubeProof: () => new PrivateKernelEmptyInputData(makeHeader(), Fr.random(), Fr.random(), Fr.random()),
getMergeRollupProof: makeMergeRollupInputs,
getPublicKernelProof: () => {
return {
type: PublicKernelType.APP_LOGIC,
inputs: makePublicKernelCircuitPrivateInputs(),
};
},
getPublicTailProof: () => {
return {
type: PublicKernelType.TAIL,
inputs: makePublicKernelTailCircuitPrivateInputs(),
};
},
getRootRollupProof: makeRootRollupInputs,
getTubeProof: () => new TubeInputs(ClientIvcProof.empty()),
};

beforeEach(async () => {
prover = new MockProver();

queue = new MemoryProvingQueue(new NoopTelemetryClient(), 100, 10);
queue.start();
const port = await getPort();
queueRpcServer = createProvingJobSourceServer(queue);
queueRpcServer.start(port);

agent = new ProverAgent(prover, 1, 10);
const queueRpcClient = createProvingJobSourceClient(`http://127.0.0.1:${port}`);
agent.start(queueRpcClient);
});

afterEach(async () => {
await agent.stop();
await queueRpcServer.stop();
await queue.stop();
});

it.each(Object.entries(makeInputs))('can call %s over JSON-RPC', async (fnName, makeInputs) => {
const resp = await queue[fnName as keyof ServerCircuitProver](makeInputs() as any);
expect(resp).toBeDefined();
});
});
3 changes: 3 additions & 0 deletions yarn-project/prover-client/src/prover-agent/rpc.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { type ProvingJobSource } from '@aztec/circuit-types';
import {
AvmCircuitInputs,
AvmVerificationKeyData,
AztecAddress,
BaseOrMergeRollupPublicInputs,
BaseParityInputs,
Expand Down Expand Up @@ -37,6 +38,7 @@ export function createProvingJobSourceServer(queue: ProvingJobSource): JsonRpcSe
return new JsonRpcServer(
queue,
{
AvmVerificationKeyData,
AvmCircuitInputs,
BaseOrMergeRollupPublicInputs,
BaseParityInputs,
Expand Down Expand Up @@ -75,6 +77,7 @@ export function createProvingJobSourceClient(
return createJsonRpcClient(
url,
{
AvmVerificationKeyData,
AvmCircuitInputs,
BaseOrMergeRollupPublicInputs,
BaseParityInputs,
Expand Down
148 changes: 148 additions & 0 deletions yarn-project/prover-client/src/test/mock_prover.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import {
type PublicInputsAndRecursiveProof,
type PublicInputsAndTubeProof,
type ServerCircuitProver,
makePublicInputsAndRecursiveProof,
} from '@aztec/circuit-types';
import {
AvmVerificationKeyData,
type BaseOrMergeRollupPublicInputs,
type BlockRootOrBlockMergePublicInputs,
type KernelCircuitPublicInputs,
type PublicKernelCircuitPublicInputs,
RECURSIVE_PROOF_LENGTH,
type RecursiveProof,
type RootRollupPublicInputs,
VerificationKeyData,
makeEmptyProof,
makeRecursiveProof,
} from '@aztec/circuits.js';
import {
makeBaseOrMergeRollupPublicInputs,
makeBlockRootOrBlockMergeRollupPublicInputs,
makeKernelCircuitPublicInputs,
makePublicKernelCircuitPublicInputs,
makeRootParityInput,
makeRootRollupPublicInputs,
} from '@aztec/circuits.js/testing';

export class MockProver implements ServerCircuitProver {
constructor() {}

getAvmProof() {
return Promise.resolve(
Promise.resolve({
proof: makeEmptyProof(),
verificationKey: AvmVerificationKeyData.makeFake(),
}),
);
}

getBaseParityProof() {
return Promise.resolve(makeRootParityInput(RECURSIVE_PROOF_LENGTH));
}

getRootParityProof() {
return Promise.resolve(makeRootParityInput(RECURSIVE_PROOF_LENGTH));
}

getBaseRollupProof() {
return Promise.resolve(
makePublicInputsAndRecursiveProof(
makeBaseOrMergeRollupPublicInputs(),
makeRecursiveProof(RECURSIVE_PROOF_LENGTH),
VerificationKeyData.makeFake(),
),
);
}

getMergeRollupProof(): Promise<PublicInputsAndRecursiveProof<BaseOrMergeRollupPublicInputs>> {
return Promise.resolve(
makePublicInputsAndRecursiveProof(
makeBaseOrMergeRollupPublicInputs(),
makeRecursiveProof(RECURSIVE_PROOF_LENGTH),
VerificationKeyData.makeFake(),
),
);
}

getBlockMergeRollupProof() {
return Promise.resolve(
makePublicInputsAndRecursiveProof(
makeBlockRootOrBlockMergeRollupPublicInputs(),
makeRecursiveProof(RECURSIVE_PROOF_LENGTH),
VerificationKeyData.makeFake(),
),
);
}

getBlockRootRollupProof(): Promise<PublicInputsAndRecursiveProof<BlockRootOrBlockMergePublicInputs>> {
return Promise.resolve(
makePublicInputsAndRecursiveProof(
makeBlockRootOrBlockMergeRollupPublicInputs(),
makeRecursiveProof(RECURSIVE_PROOF_LENGTH),
VerificationKeyData.makeFake(),
),
);
}

getEmptyPrivateKernelProof(): Promise<PublicInputsAndRecursiveProof<KernelCircuitPublicInputs>> {
return Promise.resolve(
makePublicInputsAndRecursiveProof(
makeKernelCircuitPublicInputs(),
makeRecursiveProof(RECURSIVE_PROOF_LENGTH),
VerificationKeyData.makeFake(),
),
);
}

getEmptyTubeProof(): Promise<PublicInputsAndTubeProof<KernelCircuitPublicInputs>> {
return Promise.resolve(
makePublicInputsAndRecursiveProof(
makeKernelCircuitPublicInputs(),
makeRecursiveProof(RECURSIVE_PROOF_LENGTH),
VerificationKeyData.makeFake(),
),
);
}

getPublicKernelProof(): Promise<PublicInputsAndRecursiveProof<PublicKernelCircuitPublicInputs>> {
return Promise.resolve(
makePublicInputsAndRecursiveProof(
makePublicKernelCircuitPublicInputs(),
makeRecursiveProof(RECURSIVE_PROOF_LENGTH),
VerificationKeyData.makeFake(),
),
);
}

getPublicTailProof(): Promise<PublicInputsAndRecursiveProof<KernelCircuitPublicInputs>> {
return Promise.resolve(
makePublicInputsAndRecursiveProof(
makeKernelCircuitPublicInputs(),
makeRecursiveProof(RECURSIVE_PROOF_LENGTH),
VerificationKeyData.makeFake(),
),
);
}

getRootRollupProof(): Promise<PublicInputsAndRecursiveProof<RootRollupPublicInputs>> {
return Promise.resolve(
makePublicInputsAndRecursiveProof(
makeRootRollupPublicInputs(),
makeRecursiveProof(RECURSIVE_PROOF_LENGTH),
VerificationKeyData.makeFake(),
),
);
}

getTubeProof(): Promise<{
tubeVK: VerificationKeyData;
tubeProof: RecursiveProof<typeof RECURSIVE_PROOF_LENGTH>;
}> {
return Promise.resolve({
tubeVK: VerificationKeyData.makeFake(),
tubeProof: makeRecursiveProof(RECURSIVE_PROOF_LENGTH),
});
}
}
1 change: 1 addition & 0 deletions yarn-project/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,7 @@ __metadata:
"@types/node": ^18.7.23
"@types/source-map-support": ^0.5.10
commander: ^12.1.0
get-port: ^7.1.0
jest: ^29.5.0
jest-mock-extended: ^3.0.3
lodash.chunk: ^4.2.0
Expand Down

0 comments on commit 78c94a4

Please sign in to comment.