From 114eec6b128a9152d0c959ae6bdc6d78efab9c2b Mon Sep 17 00:00:00 2001 From: PhilWindle Date: Tue, 16 Apr 2024 11:43:23 +0000 Subject: [PATCH] fix: Take a deep copy of circuit inputs for proving --- .../structs/kernel/public_call_data.test.ts | 10 +++++++ .../src/structs/kernel/public_call_data.ts | 26 ++++++++++++++----- ...blic_kernel_circuit_private_inputs.test.ts | 17 ++++++++++++ .../public_kernel_circuit_private_inputs.ts | 17 +++++++++--- ...kernel_tail_circuit_private_inputs.test.ts | 17 ++++++++++++ ...blic_kernel_tail_circuit_private_inputs.ts | 24 ++++++++++++++--- .../non_existent_read_request_hints.ts | 7 ++++- .../src/public/abstract_phase_manager.ts | 7 ++--- .../src/public/tail_phase_manager.ts | 4 ++- 9 files changed, 111 insertions(+), 18 deletions(-) create mode 100644 yarn-project/circuits.js/src/structs/kernel/public_call_data.test.ts create mode 100644 yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_private_inputs.test.ts create mode 100644 yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.test.ts diff --git a/yarn-project/circuits.js/src/structs/kernel/public_call_data.test.ts b/yarn-project/circuits.js/src/structs/kernel/public_call_data.test.ts new file mode 100644 index 000000000000..cafa167f31ee --- /dev/null +++ b/yarn-project/circuits.js/src/structs/kernel/public_call_data.test.ts @@ -0,0 +1,10 @@ +import { makePublicCallData } from '../../tests/factories.js'; +import { PublicCallData } from './public_call_data.js'; + +describe('PublicCallData', () => { + it('PublicCallData after serialization and deserialization is equal to the original', () => { + const original = makePublicCallData(123, true); + const serialized = PublicCallData.fromBuffer(original.toBuffer()); + expect(original).toEqual(serialized); + }); +}); diff --git a/yarn-project/circuits.js/src/structs/kernel/public_call_data.ts b/yarn-project/circuits.js/src/structs/kernel/public_call_data.ts index 5d53b9a49a79..249bd3fa1a88 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_call_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_call_data.ts @@ -1,10 +1,10 @@ -import { type Fr } from '@aztec/foundation/fields'; -import { type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; +import { Fr } from '@aztec/foundation/fields'; +import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; -import { type MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL } from '../../constants.gen.js'; -import { type CallRequest } from '../call_request.js'; -import { type Proof } from '../proof.js'; -import { type PublicCallStackItem } from '../public_call_stack_item.js'; +import { MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL } from '../../constants.gen.js'; +import { CallRequest } from '../call_request.js'; +import { Proof } from '../proof.js'; +import { PublicCallStackItem } from '../public_call_stack_item.js'; /** * Public calldata assembled from the kernel execution result and proof. @@ -42,4 +42,18 @@ export class PublicCallData { this.bytecodeHash, ); } + + static fromBuffer(buffer: BufferReader | Buffer) { + const reader = BufferReader.asReader(buffer); + return new PublicCallData( + reader.readObject(PublicCallStackItem), + reader.readArray( + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, + CallRequest, + ), + reader.readObject(Proof), + reader.readObject(Fr), + reader.readObject(Fr), + ); + } } diff --git a/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_private_inputs.test.ts b/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_private_inputs.test.ts new file mode 100644 index 000000000000..0240c1b081cb --- /dev/null +++ b/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_private_inputs.test.ts @@ -0,0 +1,17 @@ +import { makePublicKernelCircuitPrivateInputs } from '../../tests/factories.js'; +import { PublicKernelCircuitPrivateInputs } from './public_kernel_circuit_private_inputs.js'; + +describe('PublicKernelCircuitPrivateInputs', () => { + it('PublicKernelCircuitPrivateInputs after serialization and deserialization is equal to the original', () => { + const original = makePublicKernelCircuitPrivateInputs(123); + const serialized = PublicKernelCircuitPrivateInputs.fromBuffer(original.toBuffer()); + expect(original).toEqual(serialized); + }); + + it('PublicKernelCircuitPrivateInputs after clone is equal to the original', () => { + const original = makePublicKernelCircuitPrivateInputs(123); + const serialized = original.clone(); + expect(original).toEqual(serialized); + expect(original).not.toBe(serialized); + }); +}); diff --git a/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_private_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_private_inputs.ts index 86530dc0f4d9..63f377cd63c0 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_private_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_private_inputs.ts @@ -1,7 +1,7 @@ -import { serializeToBuffer } from '@aztec/foundation/serialize'; +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; -import { type PublicCallData } from './public_call_data.js'; -import { type PublicKernelData } from './public_kernel_data.js'; +import { PublicCallData } from './public_call_data.js'; +import { PublicKernelData } from './public_kernel_data.js'; /** * Inputs to the public kernel circuit. @@ -21,4 +21,15 @@ export class PublicKernelCircuitPrivateInputs { toBuffer() { return serializeToBuffer(this.previousKernel, this.publicCall); } + + static fromBuffer(buffer: BufferReader | Buffer) { + const reader = BufferReader.asReader(buffer); + const previousKernel = reader.readObject(PublicKernelData); + const publicCall = reader.readObject(PublicCallData); + return new PublicKernelCircuitPrivateInputs(previousKernel, publicCall); + } + + clone() { + return PublicKernelCircuitPrivateInputs.fromBuffer(this.toBuffer()); + } } diff --git a/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.test.ts b/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.test.ts new file mode 100644 index 000000000000..e53f3f2df214 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.test.ts @@ -0,0 +1,17 @@ +import { makePublicKernelTailCircuitPrivateInputs } from '../../tests/factories.js'; +import { PublicKernelTailCircuitPrivateInputs } from './public_kernel_tail_circuit_private_inputs.js'; + +describe('PublicKernelTailCircuitPrivateInputs', () => { + it('PublicKernelTailCircuitPrivateInputs after serialization and deserialization is equal to the original', () => { + const original = makePublicKernelTailCircuitPrivateInputs(123); + const serialized = PublicKernelTailCircuitPrivateInputs.fromBuffer(original.toBuffer()); + expect(original).toEqual(serialized); + }); + + it('PublicKernelTailCircuitPrivateInputs after clone is equal to the original', () => { + const original = makePublicKernelTailCircuitPrivateInputs(123); + const serialized = original.clone(); + expect(original).toEqual(serialized); + expect(original).not.toBe(serialized); + }); +}); diff --git a/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts index 073c0598861d..be3037d45653 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts @@ -1,8 +1,11 @@ -import { serializeToBuffer } from '@aztec/foundation/serialize'; +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; -import { type NullifierNonExistentReadRequestHints } from '../non_existent_read_request_hints.js'; -import { type NullifierReadRequestHints } from '../read_request_hints.js'; -import { type PublicKernelData } from './public_kernel_data.js'; +import { + type NullifierNonExistentReadRequestHints, + nullifierNonExistentReadRequestHintsFromBuffer, +} from '../non_existent_read_request_hints.js'; +import { type NullifierReadRequestHints, nullifierReadRequestHintsFromBuffer } from '../read_request_hints.js'; +import { PublicKernelData } from './public_kernel_data.js'; /** * Inputs to the public kernel circuit. @@ -30,4 +33,17 @@ export class PublicKernelTailCircuitPrivateInputs { this.nullifierNonExistentReadRequestHints, ); } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new PublicKernelTailCircuitPrivateInputs( + reader.readObject(PublicKernelData), + nullifierReadRequestHintsFromBuffer(reader), + nullifierNonExistentReadRequestHintsFromBuffer(reader), + ); + } + + clone() { + return PublicKernelTailCircuitPrivateInputs.fromBuffer(this.toBuffer()); + } } diff --git a/yarn-project/circuits.js/src/structs/non_existent_read_request_hints.ts b/yarn-project/circuits.js/src/structs/non_existent_read_request_hints.ts index a459be8be340..9659c63d0c30 100644 --- a/yarn-project/circuits.js/src/structs/non_existent_read_request_hints.ts +++ b/yarn-project/circuits.js/src/structs/non_existent_read_request_hints.ts @@ -84,7 +84,12 @@ export class NonExistentReadRequestHints< } toBuffer() { - return serializeToBuffer(this.nonMembershipHints, this.nextPendingValueIndices); + return serializeToBuffer( + this.nonMembershipHints, + this.nextPendingValueIndices, + this.sortedPendingValues, + this.sortedPendingValueHints, + ); } } diff --git a/yarn-project/simulator/src/public/abstract_phase_manager.ts b/yarn-project/simulator/src/public/abstract_phase_manager.ts index 092adbbc6202..75cc8d22c7eb 100644 --- a/yarn-project/simulator/src/public/abstract_phase_manager.ts +++ b/yarn-project/simulator/src/public/abstract_phase_manager.ts @@ -338,14 +338,15 @@ export abstract class AbstractPhaseManager { ): Promise<[PublicKernelCircuitPrivateInputs, PublicKernelCircuitPublicInputs]> { const previousKernel = this.getPreviousKernelData(previousOutput, previousProof); + // We take a deep copy (clone) of these inputs to be passed to the prover const inputs = new PublicKernelCircuitPrivateInputs(previousKernel, callData); switch (this.phase) { case PublicKernelPhase.SETUP: - return [inputs, await this.publicKernel.publicKernelCircuitSetup(inputs)]; + return [inputs.clone(), await this.publicKernel.publicKernelCircuitSetup(inputs)]; case PublicKernelPhase.APP_LOGIC: - return [inputs, await this.publicKernel.publicKernelCircuitAppLogic(inputs)]; + return [inputs.clone(), await this.publicKernel.publicKernelCircuitAppLogic(inputs)]; case PublicKernelPhase.TEARDOWN: - return [inputs, await this.publicKernel.publicKernelCircuitTeardown(inputs)]; + return [inputs.clone(), await this.publicKernel.publicKernelCircuitTeardown(inputs)]; default: throw new Error(`No public kernel circuit for inputs`); } diff --git a/yarn-project/simulator/src/public/tail_phase_manager.ts b/yarn-project/simulator/src/public/tail_phase_manager.ts index 0cc78be521f9..44ebe1dd2d38 100644 --- a/yarn-project/simulator/src/public/tail_phase_manager.ts +++ b/yarn-project/simulator/src/public/tail_phase_manager.ts @@ -101,12 +101,14 @@ export class TailPhaseManager extends AbstractPhaseManager { endNonRevertibleData.newNullifiers, end.newNullifiers, ); + + // We take a deep copy (clone) of these to pass to the prover const inputs = new PublicKernelTailCircuitPrivateInputs( previousKernel, nullifierReadRequestHints, nullifierNonExistentReadRequestHints, ); - return [inputs, await this.publicKernel.publicKernelCircuitTail(inputs)]; + return [inputs.clone(), await this.publicKernel.publicKernelCircuitTail(inputs)]; } private sortNoteHashes(noteHashes: Tuple): Tuple {