@aztec/pxe 0.36.0 → 0.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/config/index.d.ts +17 -2
- package/dest/config/index.d.ts.map +1 -1
- package/dest/config/index.js +1 -1
- package/dest/index.d.ts +1 -0
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +3 -1
- package/dest/kernel_oracle/index.d.ts +1 -1
- package/dest/kernel_oracle/index.d.ts.map +1 -1
- package/dest/kernel_oracle/index.js +2 -2
- package/dest/kernel_prover/bb_prover/bb_native_proof_creator.d.ts +95 -0
- package/dest/kernel_prover/bb_prover/bb_native_proof_creator.d.ts.map +1 -0
- package/dest/kernel_prover/bb_prover/bb_native_proof_creator.js +437 -0
- package/dest/kernel_prover/{proof_creator.d.ts → interface/proof_creator.d.ts} +16 -35
- package/dest/kernel_prover/interface/proof_creator.d.ts.map +1 -0
- package/dest/kernel_prover/interface/proof_creator.js +2 -0
- package/dest/kernel_prover/kernel_prover.d.ts +4 -4
- package/dest/kernel_prover/kernel_prover.d.ts.map +1 -1
- package/dest/kernel_prover/kernel_prover.js +10 -37
- package/dest/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.d.ts +1 -1
- package/dest/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.d.ts.map +1 -1
- package/dest/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.js +4 -33
- package/dest/kernel_prover/proving_data_oracle.d.ts +1 -1
- package/dest/kernel_prover/proving_data_oracle.d.ts.map +1 -1
- package/dest/kernel_prover/test/test_circuit_prover.d.ts +16 -0
- package/dest/kernel_prover/test/test_circuit_prover.d.ts.map +1 -0
- package/dest/kernel_prover/test/test_circuit_prover.js +67 -0
- package/dest/pxe_service/create_pxe_service.d.ts +3 -1
- package/dest/pxe_service/create_pxe_service.d.ts.map +1 -1
- package/dest/pxe_service/create_pxe_service.js +16 -3
- package/dest/pxe_service/pxe_service.d.ts +5 -4
- package/dest/pxe_service/pxe_service.d.ts.map +1 -1
- package/dest/pxe_service/pxe_service.js +16 -57
- package/dest/simulator_oracle/index.d.ts +5 -4
- package/dest/simulator_oracle/index.d.ts.map +1 -1
- package/dest/simulator_oracle/index.js +12 -3
- package/package.json +14 -12
- package/src/config/index.ts +19 -2
- package/src/index.ts +3 -0
- package/src/kernel_oracle/index.ts +1 -1
- package/src/kernel_prover/bb_prover/bb_native_proof_creator.ts +713 -0
- package/src/kernel_prover/interface/proof_creator.ts +79 -0
- package/src/kernel_prover/kernel_prover.ts +19 -48
- package/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts +5 -40
- package/src/kernel_prover/proving_data_oracle.ts +1 -1
- package/src/kernel_prover/test/test_circuit_prover.ts +96 -0
- package/src/pxe_service/create_pxe_service.ts +17 -1
- package/src/pxe_service/pxe_service.ts +31 -68
- package/src/simulator_oracle/index.ts +16 -7
- package/dest/kernel_prover/proof_creator.d.ts.map +0 -1
- package/dest/kernel_prover/proof_creator.js +0 -68
- package/src/kernel_prover/proof_creator.ts +0 -157
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type PrivateCircuitPublicInputs,
|
|
3
|
+
type PrivateKernelCircuitPublicInputs,
|
|
4
|
+
type PrivateKernelInitCircuitPrivateInputs,
|
|
5
|
+
type PrivateKernelInnerCircuitPrivateInputs,
|
|
6
|
+
type PrivateKernelTailCircuitPrivateInputs,
|
|
7
|
+
type PrivateKernelTailCircuitPublicInputs,
|
|
8
|
+
type Proof,
|
|
9
|
+
} from '@aztec/circuits.js';
|
|
10
|
+
import { type Fr } from '@aztec/foundation/fields';
|
|
11
|
+
import { type ACVMField } from '@aztec/simulator';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Represents the output of the proof creation process for init and inner private kernel circuit.
|
|
15
|
+
* Contains the public inputs required for the init and inner private kernel circuit and the generated proof.
|
|
16
|
+
*/
|
|
17
|
+
export type ProofOutput<PublicInputsType> = {
|
|
18
|
+
/**
|
|
19
|
+
* The public inputs required for the proof generation process.
|
|
20
|
+
*/
|
|
21
|
+
publicInputs: PublicInputsType;
|
|
22
|
+
/**
|
|
23
|
+
* The zk-SNARK proof for the kernel execution.
|
|
24
|
+
*/
|
|
25
|
+
proof: Proof;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* ProofCreator provides functionality to create and validate proofs, and retrieve
|
|
30
|
+
* siloed commitments necessary for maintaining transaction privacy and security on the network.
|
|
31
|
+
*/
|
|
32
|
+
export interface ProofCreator {
|
|
33
|
+
/**
|
|
34
|
+
* Computes the siloed commitments for a given set of public inputs.
|
|
35
|
+
*
|
|
36
|
+
* @param publicInputs - The public inputs containing the contract address and new note hashes to be used in generating siloed note hashes.
|
|
37
|
+
* @returns An array of Fr (finite field) elements representing the siloed commitments.
|
|
38
|
+
*/
|
|
39
|
+
getSiloedCommitments(publicInputs: PrivateCircuitPublicInputs): Promise<Fr[]>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Creates a proof output for a given signed transaction request and private call data for the first iteration.
|
|
43
|
+
*
|
|
44
|
+
* @param privateKernelInputsInit - The private data structure for the initial iteration.
|
|
45
|
+
* @returns A Promise resolving to a ProofOutput object containing public inputs and the kernel proof.
|
|
46
|
+
*/
|
|
47
|
+
createProofInit(
|
|
48
|
+
privateKernelInputsInit: PrivateKernelInitCircuitPrivateInputs,
|
|
49
|
+
): Promise<ProofOutput<PrivateKernelCircuitPublicInputs>>;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Creates a proof output for a given previous kernel data and private call data for an inner iteration.
|
|
53
|
+
*
|
|
54
|
+
* @param privateKernelInputsInner - The private input data structure for the inner iteration.
|
|
55
|
+
* @returns A Promise resolving to a ProofOutput object containing public inputs and the kernel proof.
|
|
56
|
+
*/
|
|
57
|
+
createProofInner(
|
|
58
|
+
privateKernelInputsInner: PrivateKernelInnerCircuitPrivateInputs,
|
|
59
|
+
): Promise<ProofOutput<PrivateKernelCircuitPublicInputs>>;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Creates a proof output based on the last inner kernel iteration kernel data for the final ordering iteration.
|
|
63
|
+
*
|
|
64
|
+
* @param privateKernelInputsTail - The private input data structure for the final ordering iteration.
|
|
65
|
+
* @returns A Promise resolving to a ProofOutput object containing public inputs and the kernel proof.
|
|
66
|
+
*/
|
|
67
|
+
createProofTail(
|
|
68
|
+
privateKernelInputsTail: PrivateKernelTailCircuitPrivateInputs,
|
|
69
|
+
): Promise<ProofOutput<PrivateKernelTailCircuitPublicInputs>>;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Creates a proof for an app circuit.
|
|
73
|
+
*
|
|
74
|
+
* @param partialWitness - The witness produced via circuit simulation
|
|
75
|
+
* @param bytecode - The circuit bytecode in gzipped bincode format
|
|
76
|
+
* @returns A Promise resolving to a Proof object
|
|
77
|
+
*/
|
|
78
|
+
createAppCircuitProof(partialWitness: Map<number, ACVMField>, bytecode: Buffer): Promise<Proof>;
|
|
79
|
+
}
|
|
@@ -1,34 +1,33 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CallRequest,
|
|
3
3
|
Fr,
|
|
4
|
-
MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,
|
|
5
4
|
MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL,
|
|
6
5
|
MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,
|
|
7
|
-
NoteHashReadRequestMembershipWitness,
|
|
8
6
|
PrivateCallData,
|
|
9
7
|
PrivateKernelCircuitPublicInputs,
|
|
10
8
|
PrivateKernelData,
|
|
11
9
|
PrivateKernelInitCircuitPrivateInputs,
|
|
12
10
|
PrivateKernelInnerCircuitPrivateInputs,
|
|
13
11
|
PrivateKernelTailCircuitPrivateInputs,
|
|
12
|
+
type PrivateKernelTailCircuitPublicInputs,
|
|
13
|
+
type Proof,
|
|
14
14
|
type TxRequest,
|
|
15
15
|
VK_TREE_HEIGHT,
|
|
16
16
|
VerificationKey,
|
|
17
17
|
makeEmptyProof,
|
|
18
18
|
} from '@aztec/circuits.js';
|
|
19
|
-
import { makeTuple } from '@aztec/foundation/array';
|
|
20
19
|
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
21
20
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
22
21
|
import { assertLength } from '@aztec/foundation/serialize';
|
|
23
22
|
import { pushTestData } from '@aztec/foundation/testing';
|
|
24
|
-
import { type ExecutionResult, collectNullifiedNoteHashCounters } from '@aztec/simulator';
|
|
23
|
+
import { type ExecutionResult, collectNoteHashLeafIndexMap, collectNullifiedNoteHashCounters } from '@aztec/simulator';
|
|
25
24
|
|
|
25
|
+
import { type ProofCreator, type ProofOutput } from './interface/proof_creator.js';
|
|
26
26
|
import {
|
|
27
27
|
buildPrivateKernelInnerHints,
|
|
28
28
|
buildPrivateKernelTailHints,
|
|
29
29
|
buildPrivateKernelTailOutputs,
|
|
30
30
|
} from './private_inputs_builders/index.js';
|
|
31
|
-
import { KernelProofCreator, type ProofCreator, type ProofOutput, type ProofOutputFinal } from './proof_creator.js';
|
|
32
31
|
import { type ProvingDataOracle } from './proving_data_oracle.js';
|
|
33
32
|
|
|
34
33
|
/**
|
|
@@ -39,7 +38,8 @@ import { type ProvingDataOracle } from './proving_data_oracle.js';
|
|
|
39
38
|
*/
|
|
40
39
|
export class KernelProver {
|
|
41
40
|
private log = createDebugLogger('aztec:kernel-prover');
|
|
42
|
-
|
|
41
|
+
|
|
42
|
+
constructor(private oracle: ProvingDataOracle, private proofCreator: ProofCreator) {}
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* Generate a proof for a given transaction request and execution result.
|
|
@@ -51,20 +51,21 @@ export class KernelProver {
|
|
|
51
51
|
* @param executionResult - The execution result object containing nested executions and preimages.
|
|
52
52
|
* @returns A Promise that resolves to a KernelProverOutput object containing proof, public inputs, and output notes.
|
|
53
53
|
*/
|
|
54
|
-
async prove(
|
|
54
|
+
async prove(
|
|
55
|
+
txRequest: TxRequest,
|
|
56
|
+
executionResult: ExecutionResult,
|
|
57
|
+
): Promise<ProofOutput<PrivateKernelTailCircuitPublicInputs>> {
|
|
55
58
|
const executionStack = [executionResult];
|
|
56
59
|
let firstIteration = true;
|
|
57
60
|
let previousVerificationKey = VerificationKey.makeFake();
|
|
58
61
|
|
|
59
|
-
let output: ProofOutput = {
|
|
62
|
+
let output: ProofOutput<PrivateKernelCircuitPublicInputs> = {
|
|
60
63
|
publicInputs: PrivateKernelCircuitPublicInputs.empty(),
|
|
61
64
|
proof: makeEmptyProof(),
|
|
62
65
|
};
|
|
63
66
|
|
|
64
|
-
const
|
|
65
|
-
collectNullifiedNoteHashCounters(executionResult)
|
|
66
|
-
noteHashNullifierCounterMap.set(noteHashCounter, nullifierCounter),
|
|
67
|
-
);
|
|
67
|
+
const noteHashLeafIndexMap = collectNoteHashLeafIndexMap(executionResult);
|
|
68
|
+
const noteHashNullifierCounterMap = collectNullifiedNoteHashCounters(executionResult);
|
|
68
69
|
|
|
69
70
|
while (executionStack.length) {
|
|
70
71
|
const currentExecution = executionStack.pop()!;
|
|
@@ -75,38 +76,16 @@ export class KernelProver {
|
|
|
75
76
|
);
|
|
76
77
|
const publicCallRequests = currentExecution.enqueuedPublicFunctionCalls.map(result => result.toCallRequest());
|
|
77
78
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
for (let rr = 0; rr < noteHashReadRequestMembershipWitnesses.length; rr++) {
|
|
82
|
-
// Pretty sure this check was forever broken. I made some changes to Fr and this started triggering.
|
|
83
|
-
// The conditional makes no sense to me anyway.
|
|
84
|
-
// if (currentExecution.callStackItem.publicInputs.readRequests[rr] == Fr.ZERO) {
|
|
85
|
-
// throw new Error(
|
|
86
|
-
// 'Number of read requests output from Noir circuit does not match number of read request commitment indices output from simulator.',
|
|
87
|
-
// );
|
|
88
|
-
// }
|
|
89
|
-
const rrWitness = noteHashReadRequestMembershipWitnesses[rr];
|
|
90
|
-
if (!rrWitness.isTransient) {
|
|
91
|
-
// Non-transient reads must contain full membership witness with sibling path from commitment to root.
|
|
92
|
-
// Get regular membership witness to fill in sibling path in the read request witness.
|
|
93
|
-
const membershipWitness = await this.oracle.getNoteMembershipWitness(rrWitness.leafIndex.toBigInt());
|
|
94
|
-
rrWitness.siblingPath = membershipWitness.siblingPath;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// fill in witnesses for remaining/empty read requests
|
|
99
|
-
noteHashReadRequestMembershipWitnesses.push(
|
|
100
|
-
...Array(MAX_NOTE_HASH_READ_REQUESTS_PER_CALL - noteHashReadRequestMembershipWitnesses.length)
|
|
101
|
-
.fill(0)
|
|
102
|
-
.map(() => NoteHashReadRequestMembershipWitness.empty(BigInt(0))),
|
|
79
|
+
const proof = await this.proofCreator.createAppCircuitProof(
|
|
80
|
+
currentExecution.partialWitness,
|
|
81
|
+
currentExecution.acir,
|
|
103
82
|
);
|
|
104
83
|
|
|
105
84
|
const privateCallData = await this.createPrivateCallData(
|
|
106
85
|
currentExecution,
|
|
107
86
|
privateCallRequests,
|
|
108
87
|
publicCallRequests,
|
|
109
|
-
|
|
88
|
+
proof,
|
|
110
89
|
);
|
|
111
90
|
|
|
112
91
|
const hints = buildPrivateKernelInnerHints(
|
|
@@ -148,7 +127,7 @@ export class KernelProver {
|
|
|
148
127
|
`Calling private kernel tail with hwm ${previousKernelData.publicInputs.minRevertibleSideEffectCounter}`,
|
|
149
128
|
);
|
|
150
129
|
|
|
151
|
-
const hints = await buildPrivateKernelTailHints(output.publicInputs, this.oracle);
|
|
130
|
+
const hints = await buildPrivateKernelTailHints(output.publicInputs, noteHashLeafIndexMap, this.oracle);
|
|
152
131
|
|
|
153
132
|
const expectedOutputs = buildPrivateKernelTailOutputs(hints.sortedNewNoteHashes, hints.sortedNewNullifiers);
|
|
154
133
|
|
|
@@ -162,7 +141,7 @@ export class KernelProver {
|
|
|
162
141
|
{ callStackItem, vk }: ExecutionResult,
|
|
163
142
|
privateCallRequests: CallRequest[],
|
|
164
143
|
publicCallRequests: CallRequest[],
|
|
165
|
-
|
|
144
|
+
proof: Proof,
|
|
166
145
|
) {
|
|
167
146
|
const { contractAddress, functionData } = callStackItem;
|
|
168
147
|
|
|
@@ -188,9 +167,6 @@ export class KernelProver {
|
|
|
188
167
|
// const acirHash = keccak256(Buffer.from(bytecode, 'hex'));
|
|
189
168
|
const acirHash = Fr.fromBuffer(Buffer.alloc(32, 0));
|
|
190
169
|
|
|
191
|
-
// TODO
|
|
192
|
-
const proof = makeEmptyProof();
|
|
193
|
-
|
|
194
170
|
return PrivateCallData.from({
|
|
195
171
|
callStackItem,
|
|
196
172
|
privateCallStack,
|
|
@@ -202,11 +178,6 @@ export class KernelProver {
|
|
|
202
178
|
contractClassPublicBytecodeCommitment,
|
|
203
179
|
saltedInitializationHash,
|
|
204
180
|
functionLeafMembershipWitness,
|
|
205
|
-
noteHashReadRequestMembershipWitnesses: makeTuple(
|
|
206
|
-
MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,
|
|
207
|
-
i => noteHashReadRequestMembershipWitnesses[i],
|
|
208
|
-
0,
|
|
209
|
-
),
|
|
210
181
|
acirHash,
|
|
211
182
|
});
|
|
212
183
|
}
|
|
@@ -4,13 +4,11 @@ import {
|
|
|
4
4
|
type MAX_ENCRYPTED_LOGS_PER_TX,
|
|
5
5
|
MAX_NEW_NOTE_HASHES_PER_TX,
|
|
6
6
|
MAX_NEW_NULLIFIERS_PER_TX,
|
|
7
|
-
MAX_NOTE_HASH_READ_REQUESTS_PER_TX,
|
|
8
7
|
MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX,
|
|
9
8
|
type MAX_NULLIFIER_READ_REQUESTS_PER_TX,
|
|
10
9
|
type MAX_UNENCRYPTED_LOGS_PER_TX,
|
|
11
10
|
MembershipWitness,
|
|
12
11
|
NULLIFIER_TREE_HEIGHT,
|
|
13
|
-
type NoteHashContext,
|
|
14
12
|
type Nullifier,
|
|
15
13
|
type NullifierKeyValidationRequestContext,
|
|
16
14
|
type PrivateKernelCircuitPublicInputs,
|
|
@@ -18,9 +16,9 @@ import {
|
|
|
18
16
|
type ReadRequestContext,
|
|
19
17
|
type SideEffect,
|
|
20
18
|
type SideEffectType,
|
|
19
|
+
buildNoteHashReadRequestHints,
|
|
21
20
|
buildNullifierReadRequestHints,
|
|
22
21
|
buildTransientDataHints,
|
|
23
|
-
countAccumulatedItems,
|
|
24
22
|
sortByCounterGetSortedHints,
|
|
25
23
|
} from '@aztec/circuits.js';
|
|
26
24
|
import { makeTuple } from '@aztec/foundation/array';
|
|
@@ -50,42 +48,6 @@ function sortSideEffects<T extends SideEffectType, K extends number>(
|
|
|
50
48
|
return [sorted.map(({ sideEffect }) => sideEffect) as Tuple<T, K>, originalToSorted as Tuple<number, K>];
|
|
51
49
|
}
|
|
52
50
|
|
|
53
|
-
function isValidNoteHashReadRequest(readRequest: SideEffect, noteHash: NoteHashContext) {
|
|
54
|
-
return (
|
|
55
|
-
noteHash.value.equals(readRequest.value) &&
|
|
56
|
-
noteHash.counter < readRequest.counter.toNumber() &&
|
|
57
|
-
(noteHash.nullifierCounter === 0 || noteHash.nullifierCounter > readRequest.counter.toNumber())
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Performs the matching between an array of read request and an array of note hashes. This produces
|
|
63
|
-
* hints for the private kernel tail circuit to efficiently match a read request with the corresponding
|
|
64
|
-
* note hash. Several read requests might be pointing to the same note hash. It is therefore valid
|
|
65
|
-
* to return more than one hint with the same index.
|
|
66
|
-
*
|
|
67
|
-
* @param noteHashReadRequests - The array of read requests.
|
|
68
|
-
* @param noteHashes - The array of note hashes.
|
|
69
|
-
* @returns An array of hints where each element is the index of the note hash in note hashes array
|
|
70
|
-
* corresponding to the read request. In other words we have readRequests[i] == noteHashes[hints[i]].
|
|
71
|
-
*/
|
|
72
|
-
function getNoteHashReadRequestHints(
|
|
73
|
-
noteHashReadRequests: Tuple<SideEffect, typeof MAX_NOTE_HASH_READ_REQUESTS_PER_TX>,
|
|
74
|
-
noteHashes: Tuple<NoteHashContext, typeof MAX_NEW_NOTE_HASHES_PER_TX>,
|
|
75
|
-
): Tuple<number, typeof MAX_NOTE_HASH_READ_REQUESTS_PER_TX> {
|
|
76
|
-
const hints = makeTuple(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, () => 0);
|
|
77
|
-
const numReadRequests = countAccumulatedItems(noteHashReadRequests);
|
|
78
|
-
for (let i = 0; i < numReadRequests; i++) {
|
|
79
|
-
const readRequest = noteHashReadRequests[i];
|
|
80
|
-
const noteHashIndex = noteHashes.findIndex((n: NoteHashContext) => isValidNoteHashReadRequest(readRequest, n));
|
|
81
|
-
if (noteHashIndex === -1) {
|
|
82
|
-
throw new Error(`The read request at index ${i} ${readRequest} does not match to any note hash.`);
|
|
83
|
-
}
|
|
84
|
-
hints[i] = noteHashIndex;
|
|
85
|
-
}
|
|
86
|
-
return hints;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
51
|
function getNullifierReadRequestHints(
|
|
90
52
|
nullifierReadRequests: Tuple<ReadRequestContext, typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX>,
|
|
91
53
|
nullifiers: Tuple<Nullifier, typeof MAX_NEW_NULLIFIERS_PER_TX>,
|
|
@@ -131,11 +93,14 @@ async function getMasterNullifierSecretKeys(
|
|
|
131
93
|
|
|
132
94
|
export async function buildPrivateKernelTailHints(
|
|
133
95
|
publicInputs: PrivateKernelCircuitPublicInputs,
|
|
96
|
+
noteHashLeafIndexMap: Map<bigint, bigint>,
|
|
134
97
|
oracle: ProvingDataOracle,
|
|
135
98
|
) {
|
|
136
|
-
const noteHashReadRequestHints =
|
|
99
|
+
const noteHashReadRequestHints = await buildNoteHashReadRequestHints(
|
|
100
|
+
oracle,
|
|
137
101
|
publicInputs.validationRequests.noteHashReadRequests,
|
|
138
102
|
publicInputs.end.newNoteHashes,
|
|
103
|
+
noteHashLeafIndexMap,
|
|
139
104
|
);
|
|
140
105
|
|
|
141
106
|
const nullifierReadRequestHints = await getNullifierReadRequestHints(
|
|
@@ -58,7 +58,7 @@ export interface ProvingDataOracle {
|
|
|
58
58
|
* @param leafIndex - The leaf index of the note in the note hash tree.
|
|
59
59
|
* @returns the MembershipWitness for the note.
|
|
60
60
|
*/
|
|
61
|
-
|
|
61
|
+
getNoteHashMembershipWitness(leafIndex: bigint): Promise<MembershipWitness<typeof NOTE_HASH_TREE_HEIGHT>>;
|
|
62
62
|
|
|
63
63
|
getNullifierMembershipWitness(nullifier: Fr): Promise<NullifierMembershipWitness | undefined>;
|
|
64
64
|
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { type CircuitSimulationStats } from '@aztec/circuit-types/stats';
|
|
2
|
+
import {
|
|
3
|
+
type PrivateCircuitPublicInputs,
|
|
4
|
+
type PrivateKernelCircuitPublicInputs,
|
|
5
|
+
type PrivateKernelInitCircuitPrivateInputs,
|
|
6
|
+
type PrivateKernelInnerCircuitPrivateInputs,
|
|
7
|
+
type PrivateKernelTailCircuitPrivateInputs,
|
|
8
|
+
type PrivateKernelTailCircuitPublicInputs,
|
|
9
|
+
Proof,
|
|
10
|
+
makeEmptyProof,
|
|
11
|
+
} from '@aztec/circuits.js';
|
|
12
|
+
import { siloNoteHash } from '@aztec/circuits.js/hash';
|
|
13
|
+
import { createDebugLogger } from '@aztec/foundation/log';
|
|
14
|
+
import { elapsed } from '@aztec/foundation/timer';
|
|
15
|
+
import { executeInit, executeInner, executeTail, executeTailForPublic } from '@aztec/noir-protocol-circuits-types';
|
|
16
|
+
|
|
17
|
+
import { type ProofCreator, type ProofOutput } from '../interface/proof_creator.js';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Test Proof Creator executes circuit simulations and provides fake proofs.
|
|
21
|
+
*/
|
|
22
|
+
export class TestProofCreator implements ProofCreator {
|
|
23
|
+
constructor(private log = createDebugLogger('aztec:test_proof_creator')) {}
|
|
24
|
+
|
|
25
|
+
public getSiloedCommitments(publicInputs: PrivateCircuitPublicInputs) {
|
|
26
|
+
const contractAddress = publicInputs.callContext.storageContractAddress;
|
|
27
|
+
|
|
28
|
+
return Promise.resolve(
|
|
29
|
+
publicInputs.newNoteHashes.map(commitment => siloNoteHash(contractAddress, commitment.value)),
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public async createProofInit(
|
|
34
|
+
privateInputs: PrivateKernelInitCircuitPrivateInputs,
|
|
35
|
+
): Promise<ProofOutput<PrivateKernelCircuitPublicInputs>> {
|
|
36
|
+
const [duration, result] = await elapsed(() => executeInit(privateInputs));
|
|
37
|
+
this.log.debug(`Simulated private kernel init`, {
|
|
38
|
+
eventName: 'circuit-simulation',
|
|
39
|
+
circuitName: 'private-kernel-init',
|
|
40
|
+
duration,
|
|
41
|
+
inputSize: privateInputs.toBuffer().length,
|
|
42
|
+
outputSize: result.toBuffer().length,
|
|
43
|
+
} satisfies CircuitSimulationStats);
|
|
44
|
+
const proof = makeEmptyProof();
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
publicInputs: result,
|
|
48
|
+
proof: proof,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public async createProofInner(
|
|
53
|
+
privateInputs: PrivateKernelInnerCircuitPrivateInputs,
|
|
54
|
+
): Promise<ProofOutput<PrivateKernelCircuitPublicInputs>> {
|
|
55
|
+
const [duration, result] = await elapsed(() => executeInner(privateInputs));
|
|
56
|
+
this.log.debug(`Simulated private kernel inner`, {
|
|
57
|
+
eventName: 'circuit-simulation',
|
|
58
|
+
circuitName: 'private-kernel-inner',
|
|
59
|
+
duration,
|
|
60
|
+
inputSize: privateInputs.toBuffer().length,
|
|
61
|
+
outputSize: result.toBuffer().length,
|
|
62
|
+
} satisfies CircuitSimulationStats);
|
|
63
|
+
const proof = makeEmptyProof();
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
publicInputs: result,
|
|
67
|
+
proof: proof,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
public async createProofTail(
|
|
72
|
+
privateInputs: PrivateKernelTailCircuitPrivateInputs,
|
|
73
|
+
): Promise<ProofOutput<PrivateKernelTailCircuitPublicInputs>> {
|
|
74
|
+
const isForPublic = privateInputs.isForPublic();
|
|
75
|
+
const [duration, result] = await elapsed(() =>
|
|
76
|
+
isForPublic ? executeTailForPublic(privateInputs) : executeTail(privateInputs),
|
|
77
|
+
);
|
|
78
|
+
this.log.debug(`Simulated private kernel ordering`, {
|
|
79
|
+
eventName: 'circuit-simulation',
|
|
80
|
+
circuitName: 'private-kernel-ordering',
|
|
81
|
+
duration,
|
|
82
|
+
inputSize: privateInputs.toBuffer().length,
|
|
83
|
+
outputSize: result.toBuffer().length,
|
|
84
|
+
} satisfies CircuitSimulationStats);
|
|
85
|
+
const proof = makeEmptyProof();
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
publicInputs: result,
|
|
89
|
+
proof: proof,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
createAppCircuitProof(_1: Map<number, string>, _2: Buffer): Promise<Proof> {
|
|
94
|
+
return Promise.resolve(new Proof(Buffer.alloc(0)));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -13,6 +13,9 @@ import { join } from 'path';
|
|
|
13
13
|
|
|
14
14
|
import { type PXEServiceConfig } from '../config/index.js';
|
|
15
15
|
import { KVPxeDatabase } from '../database/kv_pxe_database.js';
|
|
16
|
+
import { BBNativeProofCreator } from '../kernel_prover/bb_prover/bb_native_proof_creator.js';
|
|
17
|
+
import { type ProofCreator } from '../kernel_prover/interface/proof_creator.js';
|
|
18
|
+
import { TestProofCreator } from '../kernel_prover/test/test_circuit_prover.js';
|
|
16
19
|
import { PXEService } from './pxe_service.js';
|
|
17
20
|
|
|
18
21
|
/**
|
|
@@ -23,12 +26,14 @@ import { PXEService } from './pxe_service.js';
|
|
|
23
26
|
* @param aztecNode - The AztecNode instance to be used by the server.
|
|
24
27
|
* @param config - The PXE Service Config to use
|
|
25
28
|
* @param options - (Optional) Optional information for creating an PXEService.
|
|
29
|
+
* @param proofCreator - An optional proof creator to use in place of any other configuration
|
|
26
30
|
* @returns A Promise that resolves to the started PXEService instance.
|
|
27
31
|
*/
|
|
28
32
|
export async function createPXEService(
|
|
29
33
|
aztecNode: AztecNode,
|
|
30
34
|
config: PXEServiceConfig,
|
|
31
35
|
useLogSuffix: string | boolean | undefined = undefined,
|
|
36
|
+
proofCreator?: ProofCreator,
|
|
32
37
|
) {
|
|
33
38
|
const logSuffix =
|
|
34
39
|
typeof useLogSuffix === 'boolean' ? (useLogSuffix ? randomBytes(3).toString('hex') : undefined) : useLogSuffix;
|
|
@@ -42,7 +47,18 @@ export async function createPXEService(
|
|
|
42
47
|
);
|
|
43
48
|
const db = new KVPxeDatabase(await initStoreForRollup(AztecLmdbStore.open(pxeDbPath), l1Contracts.rollupAddress));
|
|
44
49
|
|
|
45
|
-
|
|
50
|
+
// (@PhilWindle) Temporary validation until WASM is implemented
|
|
51
|
+
let prover: ProofCreator | undefined = proofCreator;
|
|
52
|
+
if (!prover) {
|
|
53
|
+
if (config.proverEnabled && (!config.bbBinaryPath || !config.bbWorkingDirectory)) {
|
|
54
|
+
throw new Error(`Prover must be configured with binary path and working directory`);
|
|
55
|
+
}
|
|
56
|
+
prover = !config.proverEnabled
|
|
57
|
+
? new TestProofCreator()
|
|
58
|
+
: new BBNativeProofCreator(config.bbBinaryPath!, config.bbWorkingDirectory!);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const server = new PXEService(keyStore, aztecNode, db, prover, config, logSuffix);
|
|
46
62
|
for (const contract of [
|
|
47
63
|
getCanonicalClassRegisterer(),
|
|
48
64
|
getCanonicalInstanceDeployer(),
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type AuthWitness,
|
|
3
3
|
type AztecNode,
|
|
4
|
-
EncryptedFunctionL2Logs,
|
|
5
|
-
type EncryptedL2Log,
|
|
6
4
|
EncryptedTxL2Logs,
|
|
7
5
|
ExtendedNote,
|
|
8
6
|
type FunctionCall,
|
|
@@ -20,8 +18,6 @@ import {
|
|
|
20
18
|
type TxExecutionRequest,
|
|
21
19
|
type TxHash,
|
|
22
20
|
type TxReceipt,
|
|
23
|
-
UnencryptedFunctionL2Logs,
|
|
24
|
-
type UnencryptedL2Log,
|
|
25
21
|
UnencryptedTxL2Logs,
|
|
26
22
|
isNoirCallStackUnresolved,
|
|
27
23
|
} from '@aztec/circuit-types';
|
|
@@ -34,24 +30,23 @@ import {
|
|
|
34
30
|
MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX,
|
|
35
31
|
type PartialAddress,
|
|
36
32
|
type PrivateKernelTailCircuitPublicInputs,
|
|
37
|
-
|
|
38
|
-
type SideEffect,
|
|
33
|
+
PublicCallRequest,
|
|
39
34
|
computeContractClassId,
|
|
40
35
|
getContractClassFromArtifact,
|
|
41
36
|
} from '@aztec/circuits.js';
|
|
42
37
|
import { computeCommitmentNonce, siloNullifier } from '@aztec/circuits.js/hash';
|
|
43
38
|
import { type ContractArtifact, type DecodedReturn, FunctionSelector, encodeArguments } from '@aztec/foundation/abi';
|
|
44
39
|
import { arrayNonEmptyLength, padArrayEnd } from '@aztec/foundation/collection';
|
|
45
|
-
import { Fr } from '@aztec/foundation/fields';
|
|
40
|
+
import { Fr, type Point } from '@aztec/foundation/fields';
|
|
46
41
|
import { SerialQueue } from '@aztec/foundation/fifo';
|
|
47
42
|
import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log';
|
|
48
43
|
import { Timer } from '@aztec/foundation/timer';
|
|
49
44
|
import {
|
|
50
45
|
type AcirSimulator,
|
|
51
46
|
type ExecutionResult,
|
|
52
|
-
collectEncryptedLogs,
|
|
53
47
|
collectEnqueuedPublicFunctionCalls,
|
|
54
|
-
|
|
48
|
+
collectSortedEncryptedLogs,
|
|
49
|
+
collectSortedUnencryptedLogs,
|
|
55
50
|
resolveOpcodeLocations,
|
|
56
51
|
} from '@aztec/simulator';
|
|
57
52
|
import { type ContractClassWithId, type ContractInstanceWithAddress } from '@aztec/types/contracts';
|
|
@@ -62,6 +57,7 @@ import { ContractDataOracle } from '../contract_data_oracle/index.js';
|
|
|
62
57
|
import { type PxeDatabase } from '../database/index.js';
|
|
63
58
|
import { NoteDao } from '../database/note_dao.js';
|
|
64
59
|
import { KernelOracle } from '../kernel_oracle/index.js';
|
|
60
|
+
import { type ProofCreator } from '../kernel_prover/interface/proof_creator.js';
|
|
65
61
|
import { KernelProver } from '../kernel_prover/kernel_prover.js';
|
|
66
62
|
import { getAcirSimulator } from '../simulator/index.js';
|
|
67
63
|
import { Synchronizer } from '../synchronizer/index.js';
|
|
@@ -83,6 +79,7 @@ export class PXEService implements PXE {
|
|
|
83
79
|
private keyStore: KeyStore,
|
|
84
80
|
private node: AztecNode,
|
|
85
81
|
private db: PxeDatabase,
|
|
82
|
+
private proofCreator: ProofCreator,
|
|
86
83
|
private config: PXEServiceConfig,
|
|
87
84
|
logSuffix?: string,
|
|
88
85
|
) {
|
|
@@ -216,8 +213,20 @@ export class PXEService implements PXE {
|
|
|
216
213
|
return this.keyStore.getPublicKeysHash(address);
|
|
217
214
|
}
|
|
218
215
|
|
|
219
|
-
public async registerRecipient(recipient: CompleteAddress): Promise<void> {
|
|
216
|
+
public async registerRecipient(recipient: CompleteAddress, publicKeys: Point[] = []): Promise<void> {
|
|
220
217
|
const wasAdded = await this.db.addCompleteAddress(recipient);
|
|
218
|
+
|
|
219
|
+
// TODO #5834: This should be refactored to be okay with only adding complete address
|
|
220
|
+
if (publicKeys.length !== 0) {
|
|
221
|
+
await this.keyStore.addPublicKeysForAccount(
|
|
222
|
+
recipient.address,
|
|
223
|
+
publicKeys[0],
|
|
224
|
+
publicKeys[1],
|
|
225
|
+
publicKeys[2],
|
|
226
|
+
publicKeys[3],
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
|
|
221
230
|
if (wasAdded) {
|
|
222
231
|
this.log.info(`Added recipient:\n ${recipient.toReadableString()}`);
|
|
223
232
|
} else {
|
|
@@ -654,18 +663,27 @@ export class PXEService implements PXE {
|
|
|
654
663
|
const executionResult = await this.#simulate(txExecutionRequest, msgSender);
|
|
655
664
|
|
|
656
665
|
const kernelOracle = new KernelOracle(this.contractDataOracle, this.keyStore, this.node);
|
|
657
|
-
const kernelProver = new KernelProver(kernelOracle);
|
|
666
|
+
const kernelProver = new KernelProver(kernelOracle, this.proofCreator);
|
|
658
667
|
this.log.debug(`Executing kernel prover...`);
|
|
659
668
|
const { proof, publicInputs } = await kernelProver.prove(txExecutionRequest.toTxRequest(), executionResult);
|
|
660
669
|
|
|
661
|
-
const
|
|
670
|
+
const unencryptedLogs = new UnencryptedTxL2Logs([collectSortedUnencryptedLogs(executionResult)]);
|
|
671
|
+
const encryptedLogs = new EncryptedTxL2Logs([collectSortedEncryptedLogs(executionResult)]);
|
|
662
672
|
const enqueuedPublicFunctions = collectEnqueuedPublicFunctionCalls(executionResult);
|
|
673
|
+
const teardownPublicFunction = PublicCallRequest.empty();
|
|
663
674
|
|
|
664
675
|
// HACK(#1639): Manually patches the ordering of the public call stack
|
|
665
676
|
// TODO(#757): Enforce proper ordering of enqueued public calls
|
|
666
677
|
await this.patchPublicCallStackOrdering(publicInputs, enqueuedPublicFunctions);
|
|
667
678
|
|
|
668
|
-
const tx = new Tx(
|
|
679
|
+
const tx = new Tx(
|
|
680
|
+
publicInputs,
|
|
681
|
+
proof,
|
|
682
|
+
encryptedLogs,
|
|
683
|
+
unencryptedLogs,
|
|
684
|
+
enqueuedPublicFunctions,
|
|
685
|
+
teardownPublicFunction,
|
|
686
|
+
);
|
|
669
687
|
return new SimulatedTx(tx, executionResult.returnValues);
|
|
670
688
|
}
|
|
671
689
|
|
|
@@ -776,61 +794,6 @@ export class PXEService implements PXE {
|
|
|
776
794
|
);
|
|
777
795
|
}
|
|
778
796
|
|
|
779
|
-
// As above, this is a hack for encrypted/unencrypted logs ordering, now they are sorted. Since the private kernel
|
|
780
|
-
// cannot keep track of side effects that happen after or before a nested call, we override the gathered logs.
|
|
781
|
-
// As a sanity check, we at least verify that the elements are the same, so we are only tweaking their ordering.
|
|
782
|
-
// See yarn-project/end-to-end/src/e2e_ordering.test.ts
|
|
783
|
-
// See https://github.com/AztecProtocol/aztec-packages/issues/1641
|
|
784
|
-
// Added as part of resolving #5017
|
|
785
|
-
private patchLogsOrdering(execResult: ExecutionResult) {
|
|
786
|
-
const encLogs = collectEncryptedLogs(execResult).flatMap(l => l.logs);
|
|
787
|
-
const unencLogs = collectUnencryptedLogs(execResult).flatMap(l => l.logs);
|
|
788
|
-
const getLogs = (res: ExecutionResult, enc: boolean) => {
|
|
789
|
-
const logs: SideEffect[] = enc
|
|
790
|
-
? res.callStackItem.publicInputs.encryptedLogsHashes.concat(res.nestedExecutions.flatMap(e => getLogs(e, true)))
|
|
791
|
-
: res.callStackItem.publicInputs.unencryptedLogsHashes.concat(
|
|
792
|
-
res.nestedExecutions.flatMap(e => getLogs(e, false)),
|
|
793
|
-
);
|
|
794
|
-
|
|
795
|
-
return logs;
|
|
796
|
-
};
|
|
797
|
-
|
|
798
|
-
const sortSEs = (a: SideEffect, b: SideEffect) => {
|
|
799
|
-
if (a.isEmpty()) {
|
|
800
|
-
return 1;
|
|
801
|
-
} else if (b.isEmpty()) {
|
|
802
|
-
return -1;
|
|
803
|
-
} else {
|
|
804
|
-
return Number(a.counter.toBigInt() - b.counter.toBigInt());
|
|
805
|
-
}
|
|
806
|
-
};
|
|
807
|
-
|
|
808
|
-
const sortedEncLogs = getLogs(execResult, true).sort(sortSEs);
|
|
809
|
-
const sortedUnencLogs = getLogs(execResult, false).sort(sortSEs);
|
|
810
|
-
|
|
811
|
-
const finalEncLogs: EncryptedL2Log[] = [];
|
|
812
|
-
sortedEncLogs.forEach((sideEffect: SideEffect) => {
|
|
813
|
-
if (!sideEffect.isEmpty()) {
|
|
814
|
-
const isLog = (log: EncryptedL2Log) => Fr.fromBuffer(log.hash()).equals(sideEffect.value);
|
|
815
|
-
const thisLogIndex = encLogs.findIndex(isLog);
|
|
816
|
-
finalEncLogs.push(encLogs[thisLogIndex]);
|
|
817
|
-
}
|
|
818
|
-
});
|
|
819
|
-
|
|
820
|
-
const finalUnencLogs: UnencryptedL2Log[] = [];
|
|
821
|
-
sortedUnencLogs.forEach((sideEffect: SideEffect) => {
|
|
822
|
-
if (!sideEffect.isEmpty()) {
|
|
823
|
-
const isLog = (log: UnencryptedL2Log) => Fr.fromBuffer(log.hash()).equals(sideEffect.value);
|
|
824
|
-
const thisLogIndex = unencLogs.findIndex(isLog);
|
|
825
|
-
finalUnencLogs.push(unencLogs[thisLogIndex]);
|
|
826
|
-
}
|
|
827
|
-
});
|
|
828
|
-
|
|
829
|
-
const encryptedLogs = new EncryptedTxL2Logs([new EncryptedFunctionL2Logs(finalEncLogs)]);
|
|
830
|
-
const unencryptedLogs = new UnencryptedTxL2Logs([new UnencryptedFunctionL2Logs(finalUnencLogs)]);
|
|
831
|
-
return { encryptedLogs, unencryptedLogs };
|
|
832
|
-
}
|
|
833
|
-
|
|
834
797
|
public async isGlobalStateSynchronized() {
|
|
835
798
|
return await this.synchronizer.isGlobalStateSynchronized();
|
|
836
799
|
}
|