@aztec/prover-client 0.42.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/README.md +1 -0
- package/dest/config.d.ts +21 -0
- package/dest/config.d.ts.map +1 -0
- package/dest/config.js +31 -0
- package/dest/index.d.ts +4 -0
- package/dest/index.d.ts.map +1 -0
- package/dest/index.js +3 -0
- package/dest/mocks/fixtures.d.ts +22 -0
- package/dest/mocks/fixtures.d.ts.map +1 -0
- package/dest/mocks/fixtures.js +95 -0
- package/dest/mocks/test_context.d.ts +32 -0
- package/dest/mocks/test_context.d.ts.map +1 -0
- package/dest/mocks/test_context.js +116 -0
- package/dest/orchestrator/block-building-helpers.d.ts +36 -0
- package/dest/orchestrator/block-building-helpers.d.ts.map +1 -0
- package/dest/orchestrator/block-building-helpers.js +236 -0
- package/dest/orchestrator/orchestrator.d.ts +113 -0
- package/dest/orchestrator/orchestrator.d.ts.map +1 -0
- package/dest/orchestrator/orchestrator.js +574 -0
- package/dest/orchestrator/proving-state.d.ts +68 -0
- package/dest/orchestrator/proving-state.d.ts.map +1 -0
- package/dest/orchestrator/proving-state.js +142 -0
- package/dest/orchestrator/tx-proving-state.d.ts +35 -0
- package/dest/orchestrator/tx-proving-state.d.ts.map +1 -0
- package/dest/orchestrator/tx-proving-state.js +92 -0
- package/dest/prover-agent/index.d.ts +4 -0
- package/dest/prover-agent/index.d.ts.map +1 -0
- package/dest/prover-agent/index.js +4 -0
- package/dest/prover-agent/memory-proving-queue.d.ts +64 -0
- package/dest/prover-agent/memory-proving-queue.d.ts.map +1 -0
- package/dest/prover-agent/memory-proving-queue.js +187 -0
- package/dest/prover-agent/prover-agent.d.ts +30 -0
- package/dest/prover-agent/prover-agent.d.ts.map +1 -0
- package/dest/prover-agent/prover-agent.js +115 -0
- package/dest/prover-agent/proving-error.d.ts +5 -0
- package/dest/prover-agent/proving-error.d.ts.map +1 -0
- package/dest/prover-agent/proving-error.js +9 -0
- package/dest/prover-agent/rpc.d.ts +5 -0
- package/dest/prover-agent/rpc.d.ts.map +1 -0
- package/dest/prover-agent/rpc.js +53 -0
- package/dest/tx-prover/tx-prover.d.ts +65 -0
- package/dest/tx-prover/tx-prover.d.ts.map +1 -0
- package/dest/tx-prover/tx-prover.js +122 -0
- package/package.json +87 -0
- package/src/config.ts +59 -0
- package/src/index.ts +4 -0
- package/src/mocks/fixtures.ts +182 -0
- package/src/mocks/test_context.ts +217 -0
- package/src/orchestrator/block-building-helpers.ts +470 -0
- package/src/orchestrator/orchestrator.ts +883 -0
- package/src/orchestrator/proving-state.ts +210 -0
- package/src/orchestrator/tx-proving-state.ts +139 -0
- package/src/prover-agent/index.ts +3 -0
- package/src/prover-agent/memory-proving-queue.ts +303 -0
- package/src/prover-agent/prover-agent.ts +144 -0
- package/src/prover-agent/proving-error.ts +9 -0
- package/src/prover-agent/rpc.ts +91 -0
- package/src/tx-prover/tx-prover.ts +171 -0
package/package.json
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aztec/prover-client",
|
|
3
|
+
"version": "0.42.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": "./dest/index.js",
|
|
7
|
+
"./prover-agent": "./dest/prover-agent/index.js"
|
|
8
|
+
},
|
|
9
|
+
"typedocOptions": {
|
|
10
|
+
"entryPoints": [
|
|
11
|
+
"./src/index.ts"
|
|
12
|
+
],
|
|
13
|
+
"name": "Prover Client",
|
|
14
|
+
"tsconfig": "./tsconfig.json"
|
|
15
|
+
},
|
|
16
|
+
"inherits": [
|
|
17
|
+
"../package.common.json",
|
|
18
|
+
"./package.local.json"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "yarn clean && tsc -b",
|
|
22
|
+
"build:dev": "tsc -b --watch",
|
|
23
|
+
"clean": "rm -rf ./dest .tsbuildinfo",
|
|
24
|
+
"formatting": "run -T prettier --check ./src && run -T eslint ./src",
|
|
25
|
+
"formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src",
|
|
26
|
+
"bb": "node --no-warnings ./dest/bb/index.js",
|
|
27
|
+
"test": "LOG_LEVEL=${LOG_LEVEL:-silent} DEBUG_COLORS=1 NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --testTimeout=1500000 --forceExit"
|
|
28
|
+
},
|
|
29
|
+
"jest": {
|
|
30
|
+
"moduleNameMapper": {
|
|
31
|
+
"^(\\.{1,2}/.*)\\.[cm]?js$": "$1"
|
|
32
|
+
},
|
|
33
|
+
"testRegex": "./src/.*\\.test\\.(js|mjs|ts)$",
|
|
34
|
+
"rootDir": "./src",
|
|
35
|
+
"transform": {
|
|
36
|
+
"^.+\\.tsx?$": [
|
|
37
|
+
"@swc/jest"
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
"extensionsToTreatAsEsm": [
|
|
41
|
+
".ts"
|
|
42
|
+
],
|
|
43
|
+
"reporters": [
|
|
44
|
+
[
|
|
45
|
+
"default",
|
|
46
|
+
{
|
|
47
|
+
"summaryThreshold": 9999
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"@aztec/bb-prover": "0.42.0",
|
|
54
|
+
"@aztec/circuit-types": "0.42.0",
|
|
55
|
+
"@aztec/circuits.js": "0.42.0",
|
|
56
|
+
"@aztec/foundation": "0.42.0",
|
|
57
|
+
"@aztec/kv-store": "0.42.0",
|
|
58
|
+
"@aztec/noir-protocol-circuits-types": "0.42.0",
|
|
59
|
+
"@aztec/simulator": "0.42.0",
|
|
60
|
+
"@aztec/world-state": "0.42.0",
|
|
61
|
+
"@noir-lang/types": "portal:../../noir/packages/types",
|
|
62
|
+
"commander": "^9.0.0",
|
|
63
|
+
"lodash.chunk": "^4.2.0",
|
|
64
|
+
"source-map-support": "^0.5.21",
|
|
65
|
+
"tslib": "^2.4.0"
|
|
66
|
+
},
|
|
67
|
+
"devDependencies": {
|
|
68
|
+
"@jest/globals": "^29.5.0",
|
|
69
|
+
"@types/jest": "^29.5.0",
|
|
70
|
+
"@types/memdown": "^3.0.0",
|
|
71
|
+
"@types/node": "^18.7.23",
|
|
72
|
+
"@types/source-map-support": "^0.5.10",
|
|
73
|
+
"jest": "^29.5.0",
|
|
74
|
+
"jest-mock-extended": "^3.0.3",
|
|
75
|
+
"ts-node": "^10.9.1",
|
|
76
|
+
"typescript": "^5.0.4"
|
|
77
|
+
},
|
|
78
|
+
"files": [
|
|
79
|
+
"dest",
|
|
80
|
+
"src",
|
|
81
|
+
"!*.test.*"
|
|
82
|
+
],
|
|
83
|
+
"types": "./dest/index.d.ts",
|
|
84
|
+
"engines": {
|
|
85
|
+
"node": ">=18"
|
|
86
|
+
}
|
|
87
|
+
}
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { type ProverConfig } from '@aztec/circuit-types';
|
|
2
|
+
|
|
3
|
+
import { tmpdir } from 'os';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The prover configuration.
|
|
7
|
+
*/
|
|
8
|
+
export type ProverClientConfig = ProverConfig & {
|
|
9
|
+
/** The working directory to use for simulation/proving */
|
|
10
|
+
acvmWorkingDirectory: string;
|
|
11
|
+
/** The path to the ACVM binary */
|
|
12
|
+
acvmBinaryPath: string;
|
|
13
|
+
/** The working directory to for proving */
|
|
14
|
+
bbWorkingDirectory: string;
|
|
15
|
+
/** The path to the bb binary */
|
|
16
|
+
bbBinaryPath: string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Returns the prover configuration from the environment variables.
|
|
21
|
+
* Note: If an environment variable is not set, the default value is used.
|
|
22
|
+
* @returns The prover configuration.
|
|
23
|
+
*/
|
|
24
|
+
export function getProverEnvVars(): ProverClientConfig {
|
|
25
|
+
const {
|
|
26
|
+
AZTEC_NODE_URL,
|
|
27
|
+
ACVM_WORKING_DIRECTORY = tmpdir(),
|
|
28
|
+
ACVM_BINARY_PATH = '',
|
|
29
|
+
BB_WORKING_DIRECTORY = tmpdir(),
|
|
30
|
+
BB_BINARY_PATH = '',
|
|
31
|
+
/** @deprecated */
|
|
32
|
+
PROVER_AGENTS = '1',
|
|
33
|
+
PROVER_AGENT_ENABLED = '1',
|
|
34
|
+
PROVER_AGENT_CONCURRENCY = PROVER_AGENTS,
|
|
35
|
+
PROVER_AGENT_POLL_INTERVAL_MS = '100',
|
|
36
|
+
PROVER_REAL_PROOFS = '',
|
|
37
|
+
} = process.env;
|
|
38
|
+
|
|
39
|
+
const realProofs = ['1', 'true'].includes(PROVER_REAL_PROOFS);
|
|
40
|
+
const proverAgentEnabled = ['1', 'true'].includes(PROVER_AGENT_ENABLED);
|
|
41
|
+
const parsedProverConcurrency = parseInt(PROVER_AGENT_CONCURRENCY, 10);
|
|
42
|
+
const proverAgentConcurrency = Number.isSafeInteger(parsedProverConcurrency) ? parsedProverConcurrency : 1;
|
|
43
|
+
const parsedProverAgentPollInterval = parseInt(PROVER_AGENT_POLL_INTERVAL_MS, 10);
|
|
44
|
+
const proverAgentPollInterval = Number.isSafeInteger(parsedProverAgentPollInterval)
|
|
45
|
+
? parsedProverAgentPollInterval
|
|
46
|
+
: 100;
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
acvmWorkingDirectory: ACVM_WORKING_DIRECTORY,
|
|
50
|
+
acvmBinaryPath: ACVM_BINARY_PATH,
|
|
51
|
+
bbBinaryPath: BB_BINARY_PATH,
|
|
52
|
+
bbWorkingDirectory: BB_WORKING_DIRECTORY,
|
|
53
|
+
realProofs,
|
|
54
|
+
proverAgentEnabled,
|
|
55
|
+
proverAgentPollInterval,
|
|
56
|
+
proverAgentConcurrency,
|
|
57
|
+
nodeUrl: AZTEC_NODE_URL,
|
|
58
|
+
};
|
|
59
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MerkleTreeId,
|
|
3
|
+
type ProcessedTx,
|
|
4
|
+
makeEmptyProcessedTx as makeEmptyProcessedTxFromHistoricalTreeRoots,
|
|
5
|
+
makeProcessedTx,
|
|
6
|
+
mockTx,
|
|
7
|
+
} from '@aztec/circuit-types';
|
|
8
|
+
import {
|
|
9
|
+
AztecAddress,
|
|
10
|
+
EthAddress,
|
|
11
|
+
Fr,
|
|
12
|
+
GasFees,
|
|
13
|
+
GlobalVariables,
|
|
14
|
+
KernelCircuitPublicInputs,
|
|
15
|
+
MAX_NEW_L2_TO_L1_MSGS_PER_TX,
|
|
16
|
+
MAX_NEW_NOTE_HASHES_PER_TX,
|
|
17
|
+
MAX_NEW_NULLIFIERS_PER_TX,
|
|
18
|
+
MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
|
|
19
|
+
NULLIFIER_TREE_HEIGHT,
|
|
20
|
+
PUBLIC_DATA_SUBTREE_HEIGHT,
|
|
21
|
+
PublicDataTreeLeaf,
|
|
22
|
+
PublicDataUpdateRequest,
|
|
23
|
+
} from '@aztec/circuits.js';
|
|
24
|
+
import { fr, makeProof } from '@aztec/circuits.js/testing';
|
|
25
|
+
import { makeTuple } from '@aztec/foundation/array';
|
|
26
|
+
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
27
|
+
import { randomBytes } from '@aztec/foundation/crypto';
|
|
28
|
+
import { type DebugLogger } from '@aztec/foundation/log';
|
|
29
|
+
import { fileURLToPath } from '@aztec/foundation/url';
|
|
30
|
+
import { NativeACVMSimulator, type SimulationProvider, WASMSimulator } from '@aztec/simulator';
|
|
31
|
+
import { type MerkleTreeOperations } from '@aztec/world-state';
|
|
32
|
+
|
|
33
|
+
import * as fs from 'fs/promises';
|
|
34
|
+
import path from 'path';
|
|
35
|
+
|
|
36
|
+
const {
|
|
37
|
+
BB_RELEASE_DIR = 'cpp/build/bin',
|
|
38
|
+
TEMP_DIR = '/tmp',
|
|
39
|
+
BB_BINARY_PATH = '',
|
|
40
|
+
BB_WORKING_DIRECTORY = '',
|
|
41
|
+
NOIR_RELEASE_DIR = 'noir-repo/target/release',
|
|
42
|
+
ACVM_BINARY_PATH = '',
|
|
43
|
+
ACVM_WORKING_DIRECTORY = '',
|
|
44
|
+
} = process.env;
|
|
45
|
+
|
|
46
|
+
// Determines if we have access to the bb binary and a tmp folder for temp files
|
|
47
|
+
export const getEnvironmentConfig = async (logger: DebugLogger) => {
|
|
48
|
+
try {
|
|
49
|
+
const expectedBBPath = BB_BINARY_PATH
|
|
50
|
+
? BB_BINARY_PATH
|
|
51
|
+
: `${path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../../barretenberg/', BB_RELEASE_DIR)}/bb`;
|
|
52
|
+
await fs.access(expectedBBPath, fs.constants.R_OK);
|
|
53
|
+
const tempWorkingDirectory = `${TEMP_DIR}/${randomBytes(4).toString('hex')}`;
|
|
54
|
+
const bbWorkingDirectory = BB_WORKING_DIRECTORY ? BB_WORKING_DIRECTORY : `${tempWorkingDirectory}/bb`;
|
|
55
|
+
await fs.mkdir(bbWorkingDirectory, { recursive: true });
|
|
56
|
+
logger.verbose(`Using native BB binary at ${expectedBBPath} with working directory ${bbWorkingDirectory}`);
|
|
57
|
+
|
|
58
|
+
const expectedAcvmPath = ACVM_BINARY_PATH
|
|
59
|
+
? ACVM_BINARY_PATH
|
|
60
|
+
: `${path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../../noir/', NOIR_RELEASE_DIR)}/acvm`;
|
|
61
|
+
await fs.access(expectedAcvmPath, fs.constants.R_OK);
|
|
62
|
+
const acvmWorkingDirectory = ACVM_WORKING_DIRECTORY ? ACVM_WORKING_DIRECTORY : `${tempWorkingDirectory}/acvm`;
|
|
63
|
+
await fs.mkdir(acvmWorkingDirectory, { recursive: true });
|
|
64
|
+
logger.verbose(`Using native ACVM binary at ${expectedAcvmPath} with working directory ${acvmWorkingDirectory}`);
|
|
65
|
+
return {
|
|
66
|
+
acvmWorkingDirectory,
|
|
67
|
+
bbWorkingDirectory,
|
|
68
|
+
expectedAcvmPath,
|
|
69
|
+
expectedBBPath,
|
|
70
|
+
directoryToCleanup: ACVM_WORKING_DIRECTORY && BB_WORKING_DIRECTORY ? undefined : tempWorkingDirectory,
|
|
71
|
+
};
|
|
72
|
+
} catch (err) {
|
|
73
|
+
logger.verbose(`Native BB not available, error: ${err}`);
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export async function getSimulationProvider(
|
|
79
|
+
config: { acvmWorkingDirectory: string | undefined; acvmBinaryPath: string | undefined },
|
|
80
|
+
logger?: DebugLogger,
|
|
81
|
+
): Promise<SimulationProvider> {
|
|
82
|
+
if (config.acvmBinaryPath && config.acvmWorkingDirectory) {
|
|
83
|
+
try {
|
|
84
|
+
await fs.access(config.acvmBinaryPath, fs.constants.R_OK);
|
|
85
|
+
await fs.mkdir(config.acvmWorkingDirectory, { recursive: true });
|
|
86
|
+
logger?.info(
|
|
87
|
+
`Using native ACVM at ${config.acvmBinaryPath} and working directory ${config.acvmWorkingDirectory}`,
|
|
88
|
+
);
|
|
89
|
+
return new NativeACVMSimulator(config.acvmWorkingDirectory, config.acvmBinaryPath);
|
|
90
|
+
} catch {
|
|
91
|
+
logger?.warn(`Failed to access ACVM at ${config.acvmBinaryPath}, falling back to WASM`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
logger?.info('Using WASM ACVM simulation');
|
|
95
|
+
return new WASMSimulator();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export const makeBloatedProcessedTx = async (builderDb: MerkleTreeOperations, seed = 0x1) => {
|
|
99
|
+
seed *= MAX_NEW_NULLIFIERS_PER_TX; // Ensure no clashing given incremental seeds
|
|
100
|
+
const tx = mockTx(seed);
|
|
101
|
+
const kernelOutput = KernelCircuitPublicInputs.empty();
|
|
102
|
+
kernelOutput.constants.historicalHeader = await builderDb.buildInitialHeader();
|
|
103
|
+
kernelOutput.end.publicDataUpdateRequests = makeTuple(
|
|
104
|
+
MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
|
|
105
|
+
i => new PublicDataUpdateRequest(fr(i), fr(i + 10), i + 20),
|
|
106
|
+
seed + 0x500,
|
|
107
|
+
);
|
|
108
|
+
kernelOutput.end.publicDataUpdateRequests = makeTuple(
|
|
109
|
+
MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
|
|
110
|
+
i => new PublicDataUpdateRequest(fr(i), fr(i + 10), i + 20),
|
|
111
|
+
seed + 0x600,
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
const processedTx = makeProcessedTx(tx, kernelOutput, makeProof(), []);
|
|
115
|
+
|
|
116
|
+
processedTx.data.end.newNoteHashes = makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, fr, seed + 0x100);
|
|
117
|
+
processedTx.data.end.newNullifiers = makeTuple(MAX_NEW_NULLIFIERS_PER_TX, fr, seed + 0x100000);
|
|
118
|
+
|
|
119
|
+
processedTx.data.end.newNullifiers[tx.data.forPublic!.end.newNullifiers.length - 1] = Fr.zero();
|
|
120
|
+
|
|
121
|
+
processedTx.data.end.newL2ToL1Msgs = makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_TX, fr, seed + 0x300);
|
|
122
|
+
processedTx.data.end.noteEncryptedLogsHash = Fr.fromBuffer(processedTx.noteEncryptedLogs.hash());
|
|
123
|
+
processedTx.data.end.encryptedLogsHash = Fr.fromBuffer(processedTx.encryptedLogs.hash());
|
|
124
|
+
processedTx.data.end.unencryptedLogsHash = Fr.fromBuffer(processedTx.unencryptedLogs.hash());
|
|
125
|
+
|
|
126
|
+
return processedTx;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
export const makeEmptyProcessedTx = async (builderDb: MerkleTreeOperations, chainId: Fr, version: Fr) => {
|
|
130
|
+
const header = await builderDb.buildInitialHeader();
|
|
131
|
+
return makeEmptyProcessedTxFromHistoricalTreeRoots(header, chainId, version);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
// Updates the expectedDb trees based on the new note hashes, contracts, and nullifiers from these txs
|
|
135
|
+
export const updateExpectedTreesFromTxs = async (db: MerkleTreeOperations, txs: ProcessedTx[]) => {
|
|
136
|
+
await db.appendLeaves(
|
|
137
|
+
MerkleTreeId.NOTE_HASH_TREE,
|
|
138
|
+
txs.flatMap(tx =>
|
|
139
|
+
padArrayEnd(
|
|
140
|
+
tx.data.end.newNoteHashes.filter(x => !x.isZero()),
|
|
141
|
+
Fr.zero(),
|
|
142
|
+
MAX_NEW_NOTE_HASHES_PER_TX,
|
|
143
|
+
),
|
|
144
|
+
),
|
|
145
|
+
);
|
|
146
|
+
await db.batchInsert(
|
|
147
|
+
MerkleTreeId.NULLIFIER_TREE,
|
|
148
|
+
txs.flatMap(tx =>
|
|
149
|
+
padArrayEnd(
|
|
150
|
+
tx.data.end.newNullifiers.filter(x => !x.isZero()),
|
|
151
|
+
Fr.zero(),
|
|
152
|
+
MAX_NEW_NULLIFIERS_PER_TX,
|
|
153
|
+
).map(x => x.toBuffer()),
|
|
154
|
+
),
|
|
155
|
+
NULLIFIER_TREE_HEIGHT,
|
|
156
|
+
);
|
|
157
|
+
for (const tx of txs) {
|
|
158
|
+
await db.batchInsert(
|
|
159
|
+
MerkleTreeId.PUBLIC_DATA_TREE,
|
|
160
|
+
tx.data.end.publicDataUpdateRequests.map(write => {
|
|
161
|
+
return new PublicDataTreeLeaf(write.leafSlot, write.newValue).toBuffer();
|
|
162
|
+
}),
|
|
163
|
+
PUBLIC_DATA_SUBTREE_HEIGHT,
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
export const makeGlobals = (blockNumber: number) => {
|
|
169
|
+
return new GlobalVariables(
|
|
170
|
+
Fr.ZERO,
|
|
171
|
+
Fr.ZERO,
|
|
172
|
+
new Fr(blockNumber),
|
|
173
|
+
Fr.ZERO,
|
|
174
|
+
EthAddress.ZERO,
|
|
175
|
+
AztecAddress.ZERO,
|
|
176
|
+
GasFees.empty(),
|
|
177
|
+
);
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
export const makeEmptyProcessedTestTx = (builderDb: MerkleTreeOperations): Promise<ProcessedTx> => {
|
|
181
|
+
return makeEmptyProcessedTx(builderDb, Fr.ZERO, Fr.ZERO);
|
|
182
|
+
};
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { type BBProverConfig } from '@aztec/bb-prover';
|
|
2
|
+
import {
|
|
3
|
+
type BlockProver,
|
|
4
|
+
type BlockResult,
|
|
5
|
+
type ProcessedTx,
|
|
6
|
+
type ProvingTicket,
|
|
7
|
+
type ServerCircuitProver,
|
|
8
|
+
type Tx,
|
|
9
|
+
type TxValidator,
|
|
10
|
+
} from '@aztec/circuit-types';
|
|
11
|
+
import {
|
|
12
|
+
type Gas,
|
|
13
|
+
GlobalVariables,
|
|
14
|
+
Header,
|
|
15
|
+
type Nullifier,
|
|
16
|
+
type TxContext,
|
|
17
|
+
getMockVerificationKeys,
|
|
18
|
+
} from '@aztec/circuits.js';
|
|
19
|
+
import { type Fr } from '@aztec/foundation/fields';
|
|
20
|
+
import { type DebugLogger } from '@aztec/foundation/log';
|
|
21
|
+
import { openTmpStore } from '@aztec/kv-store/utils';
|
|
22
|
+
import {
|
|
23
|
+
type ContractsDataSourcePublicDB,
|
|
24
|
+
type PublicExecution,
|
|
25
|
+
type PublicExecutionResult,
|
|
26
|
+
PublicExecutionResultBuilder,
|
|
27
|
+
type PublicExecutor,
|
|
28
|
+
PublicProcessor,
|
|
29
|
+
RealPublicKernelCircuitSimulator,
|
|
30
|
+
type SimulationProvider,
|
|
31
|
+
WASMSimulator,
|
|
32
|
+
type WorldStatePublicDB,
|
|
33
|
+
} from '@aztec/simulator';
|
|
34
|
+
import { type MerkleTreeOperations, MerkleTrees } from '@aztec/world-state';
|
|
35
|
+
|
|
36
|
+
import * as fs from 'fs/promises';
|
|
37
|
+
import { type MockProxy, mock } from 'jest-mock-extended';
|
|
38
|
+
|
|
39
|
+
import { TestCircuitProver } from '../../../bb-prover/src/test/test_circuit_prover.js';
|
|
40
|
+
import { ProvingOrchestrator } from '../orchestrator/orchestrator.js';
|
|
41
|
+
import { MemoryProvingQueue } from '../prover-agent/memory-proving-queue.js';
|
|
42
|
+
import { ProverAgent } from '../prover-agent/prover-agent.js';
|
|
43
|
+
import { getEnvironmentConfig, getSimulationProvider, makeGlobals } from './fixtures.js';
|
|
44
|
+
|
|
45
|
+
class DummyProverClient implements BlockProver {
|
|
46
|
+
constructor(private orchestrator: ProvingOrchestrator, private verificationKeys = getMockVerificationKeys()) {}
|
|
47
|
+
startNewBlock(numTxs: number, globalVariables: GlobalVariables, l1ToL2Messages: Fr[]): Promise<ProvingTicket> {
|
|
48
|
+
return this.orchestrator.startNewBlock(numTxs, globalVariables, l1ToL2Messages, this.verificationKeys);
|
|
49
|
+
}
|
|
50
|
+
addNewTx(tx: ProcessedTx): Promise<void> {
|
|
51
|
+
return this.orchestrator.addNewTx(tx);
|
|
52
|
+
}
|
|
53
|
+
cancelBlock(): void {
|
|
54
|
+
return this.orchestrator.cancelBlock();
|
|
55
|
+
}
|
|
56
|
+
finaliseBlock(): Promise<BlockResult> {
|
|
57
|
+
return this.orchestrator.finaliseBlock();
|
|
58
|
+
}
|
|
59
|
+
setBlockCompleted(): Promise<void> {
|
|
60
|
+
return this.orchestrator.setBlockCompleted();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export class TestContext {
|
|
65
|
+
public blockProver: BlockProver;
|
|
66
|
+
constructor(
|
|
67
|
+
public publicExecutor: MockProxy<PublicExecutor>,
|
|
68
|
+
public publicContractsDB: MockProxy<ContractsDataSourcePublicDB>,
|
|
69
|
+
public publicWorldStateDB: MockProxy<WorldStatePublicDB>,
|
|
70
|
+
public publicProcessor: PublicProcessor,
|
|
71
|
+
public simulationProvider: SimulationProvider,
|
|
72
|
+
public globalVariables: GlobalVariables,
|
|
73
|
+
public actualDb: MerkleTreeOperations,
|
|
74
|
+
public prover: ServerCircuitProver,
|
|
75
|
+
public proverAgent: ProverAgent,
|
|
76
|
+
public orchestrator: ProvingOrchestrator,
|
|
77
|
+
public blockNumber: number,
|
|
78
|
+
public directoriesToCleanup: string[],
|
|
79
|
+
public logger: DebugLogger,
|
|
80
|
+
) {
|
|
81
|
+
this.blockProver = new DummyProverClient(this.orchestrator);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
static async new(
|
|
85
|
+
logger: DebugLogger,
|
|
86
|
+
proverCount = 4,
|
|
87
|
+
createProver: (bbConfig: BBProverConfig) => Promise<ServerCircuitProver> = _ =>
|
|
88
|
+
Promise.resolve(new TestCircuitProver(new WASMSimulator())),
|
|
89
|
+
blockNumber = 3,
|
|
90
|
+
) {
|
|
91
|
+
const globalVariables = makeGlobals(blockNumber);
|
|
92
|
+
|
|
93
|
+
const publicExecutor = mock<PublicExecutor>();
|
|
94
|
+
const publicContractsDB = mock<ContractsDataSourcePublicDB>();
|
|
95
|
+
const publicWorldStateDB = mock<WorldStatePublicDB>();
|
|
96
|
+
const publicKernel = new RealPublicKernelCircuitSimulator(new WASMSimulator());
|
|
97
|
+
const actualDb = await MerkleTrees.new(openTmpStore()).then(t => t.asLatest());
|
|
98
|
+
const processor = new PublicProcessor(
|
|
99
|
+
actualDb,
|
|
100
|
+
publicExecutor,
|
|
101
|
+
publicKernel,
|
|
102
|
+
GlobalVariables.empty(),
|
|
103
|
+
Header.empty(),
|
|
104
|
+
publicContractsDB,
|
|
105
|
+
publicWorldStateDB,
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
let localProver: ServerCircuitProver;
|
|
109
|
+
const config = await getEnvironmentConfig(logger);
|
|
110
|
+
const simulationProvider = await getSimulationProvider({
|
|
111
|
+
acvmWorkingDirectory: config?.acvmWorkingDirectory,
|
|
112
|
+
acvmBinaryPath: config?.expectedAcvmPath,
|
|
113
|
+
});
|
|
114
|
+
if (!config) {
|
|
115
|
+
localProver = new TestCircuitProver(simulationProvider);
|
|
116
|
+
} else {
|
|
117
|
+
const bbConfig: BBProverConfig = {
|
|
118
|
+
acvmBinaryPath: config.expectedAcvmPath,
|
|
119
|
+
acvmWorkingDirectory: config.acvmWorkingDirectory,
|
|
120
|
+
bbBinaryPath: config.expectedBBPath,
|
|
121
|
+
bbWorkingDirectory: config.bbWorkingDirectory,
|
|
122
|
+
};
|
|
123
|
+
localProver = await createProver(bbConfig);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const queue = new MemoryProvingQueue();
|
|
127
|
+
const orchestrator = new ProvingOrchestrator(actualDb, queue);
|
|
128
|
+
const agent = new ProverAgent(localProver, proverCount);
|
|
129
|
+
|
|
130
|
+
agent.start(queue);
|
|
131
|
+
|
|
132
|
+
return new this(
|
|
133
|
+
publicExecutor,
|
|
134
|
+
publicContractsDB,
|
|
135
|
+
publicWorldStateDB,
|
|
136
|
+
processor,
|
|
137
|
+
simulationProvider,
|
|
138
|
+
globalVariables,
|
|
139
|
+
actualDb,
|
|
140
|
+
localProver,
|
|
141
|
+
agent,
|
|
142
|
+
orchestrator,
|
|
143
|
+
blockNumber,
|
|
144
|
+
[config?.directoryToCleanup ?? ''],
|
|
145
|
+
logger,
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async cleanup() {
|
|
150
|
+
await this.proverAgent.stop();
|
|
151
|
+
for (const dir of this.directoriesToCleanup.filter(x => x !== '')) {
|
|
152
|
+
await fs.rm(dir, { recursive: true, force: true });
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
public async processPublicFunctions(
|
|
157
|
+
txs: Tx[],
|
|
158
|
+
maxTransactions: number,
|
|
159
|
+
blockProver?: BlockProver,
|
|
160
|
+
txValidator?: TxValidator<ProcessedTx>,
|
|
161
|
+
) {
|
|
162
|
+
const defaultExecutorImplementation = (
|
|
163
|
+
execution: PublicExecution,
|
|
164
|
+
_globalVariables: GlobalVariables,
|
|
165
|
+
availableGas: Gas,
|
|
166
|
+
_txContext: TxContext,
|
|
167
|
+
_pendingNullifiers: Nullifier[],
|
|
168
|
+
transactionFee?: Fr,
|
|
169
|
+
_sideEffectCounter?: number,
|
|
170
|
+
) => {
|
|
171
|
+
for (const tx of txs) {
|
|
172
|
+
const allCalls = tx.publicTeardownFunctionCall.isEmpty()
|
|
173
|
+
? tx.enqueuedPublicFunctionCalls
|
|
174
|
+
: [...tx.enqueuedPublicFunctionCalls, tx.publicTeardownFunctionCall];
|
|
175
|
+
for (const request of allCalls) {
|
|
176
|
+
if (execution.contractAddress.equals(request.contractAddress)) {
|
|
177
|
+
const result = PublicExecutionResultBuilder.fromPublicCallRequest({ request }).build({
|
|
178
|
+
startGasLeft: availableGas,
|
|
179
|
+
endGasLeft: availableGas,
|
|
180
|
+
transactionFee,
|
|
181
|
+
});
|
|
182
|
+
return Promise.resolve(result);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
throw new Error(`Unexpected execution request: ${execution}`);
|
|
187
|
+
};
|
|
188
|
+
return await this.processPublicFunctionsWithMockExecutorImplementation(
|
|
189
|
+
txs,
|
|
190
|
+
maxTransactions,
|
|
191
|
+
blockProver,
|
|
192
|
+
txValidator,
|
|
193
|
+
defaultExecutorImplementation,
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
public async processPublicFunctionsWithMockExecutorImplementation(
|
|
198
|
+
txs: Tx[],
|
|
199
|
+
maxTransactions: number,
|
|
200
|
+
blockProver?: BlockProver,
|
|
201
|
+
txValidator?: TxValidator<ProcessedTx>,
|
|
202
|
+
executorMock?: (
|
|
203
|
+
execution: PublicExecution,
|
|
204
|
+
globalVariables: GlobalVariables,
|
|
205
|
+
availableGas: Gas,
|
|
206
|
+
txContext: TxContext,
|
|
207
|
+
pendingNullifiers: Nullifier[],
|
|
208
|
+
transactionFee?: Fr,
|
|
209
|
+
sideEffectCounter?: number,
|
|
210
|
+
) => Promise<PublicExecutionResult>,
|
|
211
|
+
) {
|
|
212
|
+
if (executorMock) {
|
|
213
|
+
this.publicExecutor.simulate.mockImplementation(executorMock);
|
|
214
|
+
}
|
|
215
|
+
return await this.publicProcessor.process(txs, maxTransactions, blockProver, txValidator);
|
|
216
|
+
}
|
|
217
|
+
}
|